📄 dsa.c
字号:
dsa_flag = 0; /* Breaks to avoid infinite loop*/
DPRINTF(("rec retry\n"));
return;
}
if (rec_state != R_IDLE) {
RDSATimeCount++;
DEBUGASSIGN(dbgMaxRDSA, (RDSATimeCount > dbgMaxRDSA) ? RDSATimeCount
: dbgMaxRDSA);
}
switch (rec_state) {
case R_IDLE: /* Tx lowers DATA to indicate intend for SYNC */
SET_DSA_ACK;
SET_DSA_DATA;
SET_DSA_STROBE;
if (DSA_DATA_LOW) { /* Tx starts SYNC; Rv lowers ACK */
CLEAR_DSA_ACK;
dsa_rcv_mask = 0x8000; /* Most significant bit first */
dsa_word = 0;
rec_state = R_W_SYNC1;
}
break;
case R_W_SYNC1: /* Tx pulls up DATA; Rv pulls up ACK; SYNC done */
RDSATimeCount = 0;
if (DSA_DATA_HIGH) {
SET_DSA_ACK;
rec_state = R_REC0;
}
break;
/* data tranmission */
/* wait ST to 0 */
/* if it is 0, set ACK to 0 */
case R_REC0: /* Tx lowers STROBE; Rv gets DATA then lower ACK*/
if (DSA_STROBE_LOW) {
if (DSA_DATA_HIGH) dsa_word |= dsa_rcv_mask;
dsa_rcv_mask >>= 1;
CLEAR_DSA_ACK;
rec_state = R_REC1;
}
break;
/* wait ST to 1 */
/* if it is 1, set ACK to 1 */
case R_REC1: /* Tx raises STROBE; Rv raises ACK (1b done) */
if (DSA_STROBE_HIGH) {
SET_DSA_ACK;
rec_state = (dsa_rcv_mask == 0) ? R_W_ACK0 : R_REC0;
}
break;
case R_W_ACK0: /* Tx lowers ACK when done; Rv lowers STROBE */
if (DSA_ACK_LOW) {
SET_DSA_DATA; /* Receive count is correct. */
CLEAR_DSA_STROBE;
rec_state = R_W_ACK1;
}
break;
case R_W_ACK1: /* Tx raises ACK; Rv raises STROBE (done) */
if (DSA_ACK_HIGH) {
int tmp;
int update_time;
SET_DSA_STROBE;
DEBUGASSIGN(dbgReceiveDsa, dsa_word); /* Got the data */
tmp = 0;
update_time = 0;
r_tmp = (dsa_word >> 8) & 0xff;
if (r_tmp == SERVO_SEC) {
r_tmp = dsa_word & 0xff;
servo_sec = (unsigned int) hex2bcd[r_tmp];
dsa_word = 0; /* Filter out timing info. */
tmp = 1; /* Servo info changed */
update_time = 1;
stop_timer = glbTimer;
} else if (r_tmp == SERVO_MIN) {
r_tmp = dsa_word & 0xff;
servo_min = (unsigned int) hex2bcd[r_tmp];
dsa_word = 0; /* Filter out timing info. */
tmp = 1; /* Servo info changed */
} else if (r_tmp == SERVO_INDEX) {
r_tmp = dsa_word & 0xff;
servo_index = (unsigned int) hex2bcd[r_tmp];
dsa_word = 0; /* Filter out timing info. */
} else if (r_tmp == SERVO_TRACK) {
/* CDDA's track number is different from video */
r_tmp = (dsa_word & 0xff) - ((CDinfo.type == CD_CDDA) ? 0 : 1);
/* Used to inform that new track has come. *
* If current_key is a valid key, this track change may be *
* due to a previous command, so ignore it */
#ifdef P315
if (r_tmp != cur_track_number && current_key == (-1))
{
servo_track_changed = 1;
track_changed = 1;
}
#else
if (r_tmp > cur_track_number && current_key == (-1))
servo_track_changed = 1;
#endif
/*
* When servo_track changes, also clear servo_min/sec.
* Otherwise, for short audio tracks, we may stop
* early because of the left over servo_min/sec.
*/
servo_min = servo_sec = 0;
servo_track = (unsigned int) hex2bcd[r_tmp];
dsa_word = 0; /* Filter out timing info. */
tmp = 1; /* Servo info changed */
} else if (r_tmp == SERVO_CLOSED) {
cd_tray_closed();
}
if (tmp) {
if (CDinfo.type != CD_CDI) {
servo_info = (servo_min << 8) | servo_sec;
} else
servo_info = currCDtime >> 8; /* CDI time if funny! */
servo_info |= ((servo_track << 24) | (servo_index << 16));
updateLCDtime();
#ifdef P315
if(!cd_stop) {
if(play_state == PLAY_CD_DIGEST_STATE && track_changed == 1)
{
cur_track_number = bcd2hex[servo_track];
track_changed = 0;
}
panel_play_track(cur_track_number);
}
#endif
/* use servo time to check end of play */
if (TDM_isCDDA && update_time) { /* only do it when we received
second */
int tmp_time;
tmp_time = ((servo_info & 0xffff) << 8);
if (second_endCDtime != x00999999) /* intro mode */ {
CDDA_intro_time = adjCDtime(second_endCDtime,
CDDA_track_start_time, -1);
} else {
CDDA_intro_time = x00999999;
}
if ((CDDA_play_time <= tmp_time) ||
(CDDA_intro_time <= tmp_time)||
/* victor: because of the ATTI_REL mode and some wrongly encoded CD might have
incorrect track info, there is a possibility that CDDA_play_time hasn't been
reached before a new track occurs(ABEX), we add a check on the new track
here. */
(servo_track_changed)){
end_of_play = 1;
if (!servo_track_changed) {
if ((glbTimer - cdda_glbTimer) <= TWO_SECOND) {
/* we do not tust the time we receive in the
first two seconds since we started playcdda. */
end_of_play = 0;
}
} else {
servo_track_changed = 0; /* reset it, very important */
}
}
}
#ifdef P315
if ((DiscMode & DISC_OSD_ON) && ((!program_on) || (!cd_stop))) {
OSD_time_track(OSD_TIME_REGION_MASK | OSD_TRACK_REGION_MASK,
0);
OUTOSD(1,(char *)((cd_stop) ? MSG_e_total : MSG_e_track),
(char *)((cd_stop) ? MSG_c_total : MSG_c_track), 0);
if((play_state != PLAY_CD_DIGEST_STATE) &&
(play_state != PLAY_TRACK_DIGEST_STATE))
OSD_update_info(); /* OSD info needs to update */
}
#else
OSD_update_info(); /* OSD info needs to update */
#endif
}
dsa_flag = 0;
rec_state = R_IDLE;
}
break;
default:
break;
} /* End of Switch(rec_state) */
#else /*NO SERVO*/
if (SERVO_update_second) {
SERVO_update_second=0;
update_time = 1;
/* if (CDinfo.type != CD_CDI) {
servo_info = (servo_min << 8) | servo_sec;
} else
servo_info = currCDtime >> 8;
servo_info |= ((servo_track << 24) | (servo_index << 16));
*/
updateLCDtime();
#ifdef P315
if(!cd_stop)
if (play_state = PLAY_CD_DIGEST_STATE && SERVO_update_track= 1)
{
cur_track_number = bcd2hex[((servo_info>>24)&0xff];
track_changed = 0;
}
panel_play_track(cur_track_number);
}
#endif
/* use servo time to check end of play */
if (TDM_isCDDA && update_time) { /* only do it when we received
second */
int tmp_time;
tmp_time = ((servo_info & 0xffff) << 8);
if (second_endCDtime != x00999999) /* intro mode */ {
CDDA_intro_time = adjCDtime(second_endCDtime,
CDDA_track_start_time, -1);
} else {
CDDA_intro_time = x00999999;
}
if ((CDDA_play_time <= tmp_time) ||
(CDDA_intro_time <= tmp_time)||
/* victor: because of the ATTI_REL mode and some wrongly encoded CD might have
incorrect track info, there is a possibility that CDDA_play_time hasn't been
reached before a new track occurs(ABEX), we add a check on the new track
here. */
(SERVO_update_track)){
end_of_play = 1;
if (!SERVO_update_track) {
if ((glbTimer - cdda_glbTimer) <= TWO_SECOND) {
/* we do not tust the time we receive in the
first two seconds since we started playcdda. */
end_of_play = 0;
}
} else {
SERVO_update_track= 0; /* reset it, very important */
}
}
}
#ifdef P315
if ((DiscMode & DISC_OSD_ON) && ((!program_on) || (!cd_stop))) {
OSD_time_track(OSD_TIME_REGION_MASK | OSD_TRACK_REGION_MASK,
0);
OUTOSD(1,(char *)((cd_stop) ? MSG_e_total : MSG_e_track),
(char *)((cd_stop) ? MSG_c_total : MSG_c_track), 0);
if((play_state != PLAY_CD_DIGEST_STATE) &&
(play_state != PLAY_TRACK_DIGEST_STATE))
OSD_update_info(); /* OSD info needs to update */
}
#else
OSD_update_info(); /* OSD info needs to update */
#endif
}
dsa_flag = 0;
rec_state = R_IDLE;
#endif /* NO SERVO */
}
/*
* Receive data from servo. Since receive_dsa filters out disk's timing
* information (and set dsa_word to 0), we'll retry up to 3 times to
* get non-timing information.
*
* Input
* quit_on_any:
* Return with anything (including tk/index/mm/ss). Setting of this
* flag will also force something to be returned (i.e. even if
* forceDSAabort is set, we'll not abort and return).
*
* Return:
* 1: If successful or exhaust 3 retries.
* 0: If force to quit due to forceDSAabort
*
* Side effect:
* Global variable dsa_word has the non-timing info received from
* servo.
*
*/
int receive_dsa_all(quit_on_any)
int quit_on_any;
{
int retry = 3;
int count;
unsigned int prevClock, elapsed;
#ifndef SERVO
do {
DEBUGASSIGN(count, 0);
dsa_flag = 1;
prevClock = glbTimer;
do {
DEBUGINC(1, count);
DEBUGASSIGN(dbgMaxRcvAll, (count > dbgMaxRcvAll) ? count
: dbgMaxRcvAll);
/* glbTimer is updated in the interrupt handler */
elapsed = glbTimer - prevClock;
if (elapsed > TEN_SECOND) {
DEBUGINC(1, dbgServoRcv);
/*
* We have been here for 10 seconds, that's way too long for
* receive_dsa_all. It is unlikely we are ever going to
* receive anything. Let's break out of here and return error.
*
* I have seen elapsed time of 6.5 seconds.
*/
dsa_word = SERVO_ERROR << 8;
rec_state = R_IDLE; /* Terminate receive. */
/* !!! Need to be more robust!! */
break;
}
receive_dsa();
#ifdef LEDON /* MEIXINDA */
if (((led_timer + HALF_SECOND) <= glbTimer) && (led_flag == 1)) {
led_timer = glbTimer;
led_state ^= 1;
if (led_state == 1) {
#ifdef MEIXINDA_2CDS
if (cd_disc_slot == 1) {
vfdled = 0xfd;
} else {
vfdled = 0xfe;
}
#else
if (cd_disc_slot == 1) {
vfdled = 0xfb;
} else {
vfdled = 0xf7;
}
#endif
} else {
vfdled =0xff;
}
}
#endif
/*
* If we have received a higher priority command, then
* quit and go handle the higher priroity command. Don't
* wait to finish reciving, whatever we are getting is
* garbage anyway.
*/
if (forceDSAabort) return(0);
} while (dsa_flag);
DEBUGASSIGN(dbgMaxRcvElapse, (elapsed > dbgMaxRcvElapse) ? elapsed
: dbgMaxRcvElapse);
if (dsa_word || quit_on_any) break;
} while (--retry);
#endif /* NO SERVO */
return(1);
}
/**************************************************
DSA operation function
***************************************************/
/*
* Set CD-module's modes.
*
* NOTE: SERVO has a bug, if it receives 2 trans_dsa(DSA_mode, mode) in
* a "short" period of time, the mode is actually not changed
* even though it will report the mode has been changed.
*
* Therefore, we can't use the standard way to retry dsa_mode.
* At track boundary, we'll get SERVO_TRACK, SERVO_INDEX, SERVO_MIN,
* and receive_dsa_all only retries 3 time, so we many not get
* a chance to see SERVO_MODE_STATUS if we just retry like other
* cases.
*
* When going into DOUBLE speed, the servo usually takes around
* 1 second to respond! When going into NORMAL speed, the response
* time is a lot shorter.
*
* Input:
* mode: set CD's mode
*
* Return:
* 0: fail
* 1: successful
*/
PRIVATE int dsa_mode(mode)
int mode;
{
int retry = 2;
int force_quit; /* 1: force abort; 0: receive OK */
unsigned int nextTimer;
DISP_naicigam();
#ifdef SERVO
return(1);
#else /* NO SERVO */
if (currDSAmode == mode)
return;
currDSAmode = mode;
do {
trans_dsa(DSA_MODE, mode);
/* Give up to 1 second for SERVO_MODE_STATUS reply */
nextTimer = glbTimer + TWO_SECOND;
do {
force_quit = !receive_dsa_all(0);
if (force_quit || dsa_word)
break;
} while (glbTimer <= nextTimer);
if ((dsa_word == ((SERVO_MODE_STATUS << 8) | mode)) || force_quit)
return(1);
} while (--retry);
DEBUGASSIGN(dbgDSAmode, dsa_word);
err_code = ERR_DSAMODE;
return(0);
#endif /* NO SERVO */
}
/*
* Set CD-module's DAC modes.
* Input:
* mode: CD's DAC mode
*
* Return:
* 0: fail
* 1: successful
*/
PRIVATE int dsa_dac(dac)
int dac;
{
int retry = 2;
int force_quit; /* 1: force quit; 1: receive OK */
#ifdef SERVO
return(1);
#else /* NO SERVO */
do {
trans_dsa(DSA_DAC, dac);
force_quit = !receive_dsa_all(0);
if ((dsa_word == ((SERVO_DAC_STATUS << 8) | dac)) || !force_quit)
return(1);
} while (--retry);
DEBUGASSIGN(dbgDSAdac, dsa_word);
err_code = ERR_DSADAC;
return(0);
#endif /* NO SERVO */
}
/*
* This function simulates real dsa_release function by set the CDDA_play_time
* to a big number, so the end_of_play will not be set until a track change.
*
* Return:
* 1: successful
*/
int dsa_release(unsigned int track_start, unsigned int track_end)
{
CDDA_play_time = adjCDtime(track_end, track_start, -1);
return (1);
}
/*
* Close the tray. Servo answers with TRAY MOVING (which we ignore)
* and TRAY CLOSED command.
*/
int dsa_close(int power_down)
{
int tmp;
#ifdef TWO_CDS
int closetimer = 0;
#endif
#ifdef SERVO
return(SERVO_close());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -