⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dsa.c

📁 一个两碟控制的VCD的代码,两碟之间的转动及连续播放,已大量生产的CODE.
💻 C
📖 第 1 页 / 共 5 页
字号:
/*	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 + -