📄 dsa.c
字号:
/* showingLogo = SHOWING_NOLOGO;*/
switch (play_sector_state) {
case PLAY_SECTOR_INIT:
XPORT_active = 0;
TDM_isCDDA = 0;
end_of_still = 0;
#ifdef SVCD
if (speed2) dsa_mode(MODE_ATTI_REL | MODE_CDROM | MODE_SPEED_DOUBLE);
else
#endif
dsa_mode(MODE_ATTI_REL | MODE_CDROM | MODE_SPEED_NORMAL);
vcx_user_video_stream = vstream;
reset_dsa_go();
begCDtime = begin;
go_failed = 0;
find_trials = 0;
dsatime = adjCDtime(begCDtime, 0x00000004, -1);
play_sector_state = PLAY_SECTOR_DSA_GO;
return(1);
case PLAY_SECTOR_DSA_GO:
#ifdef SERVO
status = dsa_go(dsatime);
if (!status) {
if (go_failed >= 2) {
DEBUGINC(1, dbgPlaySector);
play_sector_state = PLAY_SECTOR_INIT;
return(0); /* Really dead */
}
go_failed++;
}
else play_sector_state = PLAY_SECTOR_DSA_FIND_INIT;
return(1);
#else /* NOT SERVO */
status = dsa_go_step_by_step(dsatime);
if (!status) {
if (go_failed >= 2) {
DEBUGINC(1, dbgPlaySector);
play_sector_state = PLAY_SECTOR_INIT;
return(0); /* Really dead */
}
go_failed++;
} else if (status==2) {
play_sector_state = PLAY_SECTOR_DSA_FIND_INIT;
}
return(1);
#endif SERVO
case PLAY_SECTOR_DSA_FIND_INIT:
XPORT_play20video(XPORT_OFFSET_PLAY_SECTOR, vstream);
TDM_turn_on();
if (fuzzy_allowed) {
if (find_trials >= 2) {
DEBUGINC(1, dbgPlaySector);
XPORT_play20video(XPORT_OFFSET_FUZZY_PLAY, vstream);
TDM_turn_on();
XPORT_active = 1;
vcx_pause = 0;
return(3);
}
}
find_trials++;
previous_time = glbTimer;
play_sector_state = PLAY_SECTOR_DSA_FIND;
case PLAY_SECTOR_DSA_FIND:
#ifdef ECHO
MIC_service();
#endif
if (XPORT_active == 0) {
if (((glbTimer - previous_time) >= HALF_SECOND) ||
(currCDtime > begCDtime)) {
go_failed = 0;
play_sector_state = PLAY_SECTOR_DSA_GO;
}
return(1);
}
/* Bingo! */
play_sector_state = PLAY_SECTOR_INIT;
vcx_pause = 0;
return(2);
default: return(0);
}
}
/*
* This routine is used to do fuzzy search.
* Input:
* time: In CD sector format (i.e. MMSSFF where each of MM/SS/FF
* is a BCD value)
* size: Size of a CD sector
*
* Return:
* 1: successful
* 0: failure
*/
int fuzzyPlaySector(time, size)
int time, size;
{
int retry = 2;
/* showingLogo = SHOWING_NOLOGO;*/
/* Only change DSA mode if the current mode is not CDROM */
TDM_isCDDA = 0; /* Data is scrambled (as opposed to CDDA) */
#ifdef SVCD
if (speed2) dsa_mode(MODE_ATTI_REL | MODE_CDROM | MODE_SPEED_DOUBLE);
else
#endif
dsa_mode(MODE_ATTI_REL | MODE_CDROM | MODE_SPEED_NORMAL);
do {
if (dsa_go(time))
break;
} while (--retry);
/* Regardless of dsa_go is OK or not. */
XPORT_play20video(XPORT_OFFSET_FUZZY_PLAY, 0xe0);
TDM_turn_on();
if (retry) {
/* start decoding */
vcx_pause = 0;
return(1);
} else {
return(0);
}
}
/*
* Play CDDA data from "begin" time to "end" time where both "begin" and
* "end" are in absolute CD time format.
*
* Return:
* 1: successful
* 0: failure
*/
int playCDDA(int track_start_time, int begin, int end)
{
int retry = 3;
int diff_time;
extern RAMCODE RamCode;
/* Kill TDM so when we restart, left/right will not swap */
mvd[tdmctl0] = 0x400;
mvd[tdmrcvslots0] = 0;
system_audio_partial_reset(0);
#ifdef FRACTINT
if (!FRACT_process_on) {
FRACT_store = FRACTINT_START1;
FRACT_process_on = 1;
}
#endif
/* Only change DSA mode if the current mode is not AUDIO */
TDM_isCDDA = 1; /* This is CDDA data (unscrambled PCM data) */
/* vcx_playvideo_only = 0; */
#ifdef SVCD
if (speed2) dsa_mode(MODE_ATTI_REL | MODE_CDROM | MODE_SPEED_DOUBLE);
else
#endif
dsa_mode(MODE_ATTI_REL | MODE_AUDIO | MODE_SPEED_NORMAL);
CDDA_play_time = adjCDtime(end, track_start_time, -1);
CDDA_track_start_time = track_start_time;
do {
if (dsa_go(begin)) break;
} while (--retry);
/*
* Regardless of dsa_go result, just turn on XPORT and TDM. Otherwise,
* if high-level doesn't retry, we'll be stuck.
*/
#if 0
save_ramcode = RamCode;
VP_load_ucode(rcddamono);
#endif
XPORT_restart_at(XPORT_OFFSET_PLAY_CDDA, 1);
TDM_turn_on();
cdda_glbTimer = glbTimer;
/* if the begin time is not close to the begin track, we want to stop
it when we reach the end of track and ignore the 2 seconds
ignore time. This is to fix the problem that FF does not stop
at the end of track. */
diff_time = adjCDtime(begin, track_start_time, -1);
if (diff_time > 0x0500)
cdda_glbTimer = glbTimer - TWO_SECOND;
#ifdef LATER
#ifndef CDDA_PANEL
/*
* If we are not using the CDDA panel, then we'll need to
* show the logo if it is not being displayed.
*/
if (showingLogo != SHOWING_CDDALOGO) {
showLogo(TBLOFF_CDDASCN, TBLSZ_CDDASCN);
/* We allow multiple logo in digest */
if (!vcx_digest) showingLogo = SHOWING_CDDALOGO;
else showingLogo = SHOWING_NOLOGO;
}
#endif
#endif
return(retry);
}
void fill_screen(int color)
{
DISP_Info *dip;
int width;
int height;
dip = DISP_info + DISP_frame;
if ((vcx_user_video_stream == 0xe2) || (vcx_user_video_stream == 0x1e2)) {
DISP_frame = E2;
width = 704;
height = DISP_scn_height * 2;
} else {
DISP_frame = B;
width = 352;
height = 240; /* Set as NTSC source */
}
vcx_VertSz = height;
DISP_change_resolution(width, height);
DISP_paint_screen(color, 0, DISP_frame);
DISP_count = 0;
}
PRIVATE void init_dsa(void)
{
#ifdef SERVO_7
/* according to SERVO_7 SPEC. the three_disc changer will have to wait for
a Carousel stop #1 command from the loader before sending any command,
just in case of otherwise, we have a timeout here. */
#ifdef THREE_CDS
char retry;
retry = 2;
do {
if (!receive_dsa_all(0)) break; /* if error then quit */
if ((dsa_word & 0xff00) == (SERVO_CAROUSEL_STOPPED << 8))
break;
} while (--retry);
#endif /*THREE_CDS */
#endif /*SERVO_7 */
/* reset all state machine */
tran_state = D_IDLE;
rec_state = R_IDLE;
/* clear all flags */
CDinited = 0;
servo_track = 0;
servo_min = 0;
servo_sec = 0;
}
/************************************************************************
* Routines specific to Philips' DSA interface protocol (Games 6001) *
************************************************************************/
/*
* Transmit "cmd" and "data" from our chip to servo.
*
* Inputs:
* cmd: servo command
* data: associated data
*/
void trans_dsa(cmd, data)
int cmd, data;
{
char dsa_byte;
int dsa_second; /* 1st byte of data sent */
unsigned int TDSATimeCount; /* To prevent transmission error so *
* we can retrasmitt */
unsigned char mask; /* Mask for bit being trasmitted. */
int count = 0; /* Debug loop count */
int retry;
unsigned int prevClock, elapsed;
#ifndef SERVO
DEBUGASSIGN(dbgTransDsa, (cmd << 8) | data);
if (rec_state != R_IDLE) {
/*
* If we are in the middle of receiving, make sure we finish.
* Otherwise, if we are in R_W_ACK0, we may dead lock!
*/
if (!receive_dsa_all(1)) /* Any data, including tk/index/mm/ss */
return; /* Abort transmit, we have higher *
* priority command waiting. */
}
prevClock = glbTimer;
while (1) {
#ifdef ECHO
MIC_service();
#endif
DEBUGINC(1, count);
DEBUGASSIGN(dbgMaxTran, (count > dbgMaxTran) ? count
: dbgMaxTran);
/* glbTimer is updated in the interrupt handler */
elapsed = glbTimer - prevClock;
if (elapsed > ONE_SECOND) {
/* The usual elapsed time is ~.25 second */
DEBUGINC(1, dbgServoTran);
tran_state = D_IDLE; /* Reset the transmit state */
return;
}
switch (tran_state) {
case D_IDLE: /* Before actual synchronization */
TDSATimeCount = 0;
SET_DSA_DATA;
SET_DSA_ACK;
SET_DSA_STROBE;
tran_state = D_SYNC01;
break;
case D_SYNC01: /* Tx lower DATA; wait for Rv lower ACK */
CLEAR_DSA_DATA;
tran_state = D_SYNC02;
retry = 0;
break;
case D_SYNC02: /* When Rv lowers ACK; Tx pulls up DATA */
if (DSA_ACK_LOW) {
SET_DSA_DATA;
tran_state = D_SYNC03;
retry = 0;
} else {
/*
* Following code seems to avoid simultaneous transmission
* start problem!
*/
SET_DSA_DATA;
CLEAR_DSA_DATA;
if (retry++ > 30)
microEngine(); /* DSA not ready, talk with uP */
}
break;
case D_SYNC03: /* When Rv pulls up ACK, we are in sync */
if (DSA_ACK_HIGH) {
mask = 0x80;
dsa_byte = cmd; /* Command byte */
dsa_second = 0;
tran_state = D_TRAN01;
} else if (retry++ > 30)
microEngine(); /* DSA not ready, talk with uP */
break;
case D_TRAN01: /* Tx sets data then lowers STROBE */
if ((dsa_byte & mask) == 0) {
CLEAR_DSA_DATA;
} else {
SET_DSA_DATA;
}
mask >>= 1;
CLEAR_DSA_STROBE;
tran_state = D_TRAN02;
retry = 0;
break;
case D_TRAN02: /* Rv lowers ACK; Tx pulls up STROBE */
if (DSA_ACK_LOW) {
SET_DSA_STROBE;
tran_state = D_TRAN03;
retry = 0;
} else if (retry++ > 30)
microEngine(); /* DSA not ready, talk with uP */
break;
case D_TRAN03: /* Rv pulls ACK; one bit done */
if (DSA_ACK_HIGH) {
if (mask == 0) { /* 8b sent */
mask = 0x80;
if (dsa_second) { /* Both bytes are sent */
/* Prepare for communication acknowledge phase */
SET_DSA_STROBE;
SET_DSA_DATA;
CLEAR_DSA_ACK; /* Tx lowers ACK */
tran_state = D_ACK02;
retry = 0;
} else { /* Only 1 byte sent */
dsa_second = 1;
dsa_byte = data;
tran_state = D_TRAN01;
}
} else
tran_state = D_TRAN01;
} else if (retry++ > 30)
microEngine(); /* DSA not ready, talk with uP */
break;
case D_ACK02: /* Rv lowers STROBE */
TDSATimeCount++;
if (TDSATimeCount > 0xfff) { /* Time out */
DPRINTF(("tre retry\n"));
SET_DSA_STROBE; /* Resync */
SET_DSA_DATA;
SET_DSA_ACK;
tran_state = D_IDLE; /* Transmission failed */
} else {
if (DSA_STROBE_LOW) { /* Rv lowers STROBE; Tx pulls ACK*/
SET_DSA_ACK;
SET_DSA_STROBE;
SET_DSA_DATA;
tran_state = D_IDLE;
DEBUGASSIGN(dbgMaxTranElapse, (elapsed > dbgMaxTranElapse)
? elapsed
: dbgMaxTranElapse);
return;
} else if (retry++ > 30)
microEngine(); /* DSA not ready, talk with uP */
}
break;
default:
break;
} /* End of Switch(tran_state) */
}
#endif /* NO SERVO */
}
/* receive information from CD */
/* return dsa_word */
void receive_dsa(void)
{
char r_tmp;
int CDDA_intro_time;
int tmp;
int update_time;
#ifdef P315
int track_changed = 0;
#endif
/*
* Talk with uP while receiving from DSA. Otherwise, uP may be
* left out for long period of time, and it may think E3204 is
* dead.
*/
#ifdef TWO_CDS
if (closing) {
if ((DISC_1_CLOSE_IS_LOW) || (DISC_2_CLOSE_IS_LOW))
TRAY_STOP;
}
#endif
microEngine();
#ifdef ECHO
MIC_service();
#endif
#ifndef SERVO
/*
* If we are lost in the communication for too long, then try to
* recover it!
*/
if (RDSATimeCount > 0x1800) { /* Max I see is ~0x500 */
rec_state = R_IDLE;
RDSATimeCount = 0;
DEBUGINC(1, dbgDSArcv);
dsa_word = SERVO_ERROR << 8; /* Return error (whatever kind) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -