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

📄 dsa.c

📁 ESS3890+SL原代码(1*16内存)
💻 C
📖 第 1 页 / 共 4 页
字号:
	    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		*/		CPRINTF("TRE RETRY", TDSATimeCount);		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) */    }}/* receive information from CD *//* return dsa_word */void receive_dsa(void){    char r_tmp;    int CDDA_intro_time;        /*     * 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.     */    microEngine();#ifdef ECHO    MIC_service();#endif    /*     * 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)	*/	dsa_flag = 0;			/* Breaks to avoid infinite loop*/	CPRINTF("REC RETRY", dsa_word);	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) {	    SET_DSA_STROBE;	    DEBUGASSIGN(dbgReceiveDsa, dsa_word);	/* Got the data	*/	    r_tmp = (dsa_word >> 8) & 0xff;	    if (r_tmp == SERVO_SEC) {		r_tmp = dsa_word & 0xff;		/* update seconds */		servo_info &= ~((uint)0xff);		servo_info |= (uint)hex2bcd[r_tmp];#ifdef ANTI_SHOCK		/* for CDDA */		SERVO_cdtime = adjCDtime(CDDA_track_start_time, (servo_info & 0xffff) << 8, 1);#endif				       		dsa_word = 0;	/* Filter out timing info.	*/		OSD_update_time = 1;	    } else if (r_tmp == SERVO_MIN) {		r_tmp = dsa_word & 0xff;		/* update minutes */		servo_info &= ~((uint)0xff00);		servo_info |= (uint)hex2bcd[r_tmp] << 8;		dsa_word = 0;	/* Filter out timing info.	*/		OSD_update_time = 1;	    } else if (r_tmp == SERVO_INDEX) {		r_tmp = dsa_word & 0xff;		/* update index */		servo_info &= ~((uint)0xff00 << 8);		servo_info |= (uint)hex2bcd[r_tmp] << 16;		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);				/* Used to inform that new track has come.		 * ignore it until ~10 secs before track end.		 */		if ((cur_track_number == bcd2hex[servo_info>>24]) && 		    (AV_near_track_end_time < (servo_info & 0xffff))) {#ifdef FAST_MODE_CONTROL		    if (!fast_mode_ctrl)#endif		    {			AV_near_track_end_time = xINFINITY;			servo_track_changed = 1;		    }		}		/*		 * 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_info = (uint)hex2bcd[r_tmp] << 24;		dsa_word = 0;	/* Filter out timing info.	*/		OSD_update_time = 1;	    } else if (r_tmp == SERVO_CLOSED) {		cd_tray_closed();	    }	    	    dsa_flag = 0;	    rec_state = R_IDLE;	}	break;    default:	break;    }				/* End of Switch(rec_state) */    if (OSD_update_time) {	OSD_update_time = 0;	/* use servo time to check end of play */	if (TDM_isCDDA) { /* only do it when we received			     second */	    int tmp_time;	    tmp_time = ((servo_info & 0xffff) << 8);	    	    if (second_endCDtime != xMAX_CDTIME) /* intro mode */ {		CDDA_intro_time = adjCDtime(second_endCDtime, 					    CDDA_track_start_time, -1);	    } else {		CDDA_intro_time = xMAX_CDTIME;	    }	    	    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;		servo_track_changed = 0; /* reset it, very important */	    }	}	OSD_update_info();      /* OSD info needs to update */    }}/* * 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;    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();	    /*	     * 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);    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 */int dsa_mode(mode)int mode;{    int retry = 2;    int force_quit;	/* 1: force abort; 0: receive OK		*/    unsigned int nextTimer;    DISP_naicigam();       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);}/* * 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;#ifndef THREE_CDS    int retry = 2;    int force_quit;	/* 1: force abort; 0: receive OK		*/#ifdef  SERVO_7    /* for the new PHLIPS LOADER 7001, we have to send     * a Clear Toc command before close */    dsa_cleartoc();#endif  /* SERVO_7 */    do {	trans_dsa(DSA_CLOSE, 0);	do {	    force_quit = !receive_dsa_all(0);	    tmp = (dsa_word >> 8) & 0xff;	    if ((tmp == SERVO_CLOSED) || force_quit) 		return(1);	/* Closed*/	    else if (tmp == SERVO_ERROR)  		return(0);	/* Loader open	*/	    else if (tmp == SERVO_MOVING) 		continue;	/* Intermediate */	    else break;	/* Unexpected result */	} while (1);    } while (--retry);	/* Retry if we get unexpected result */#else    /* If not powering down, for 3-CD loaders we just send the command      * and return..for smoother playing.      */#ifdef SERVO_6003    TRAY_CLOSE;#else    trans_dsa(DSA_CLOSE, 0);#endif    if (power_down) {#ifdef SERVO_6003	cd_opened = 1;	eject_6003_retry = 2;	TRAY_CLOSE;#else	do {	    receive_dsa_all(0);	    tmp = (dsa_word >> 8) & 0xff;	    if (tmp == SERVO_CLOSED) return(1);	/* Closed*/	    else if (tmp == SERVO_MOVING) continue;	/* Intermediate */	    else break;	/* Unexpected result */	} while (1);#endif    }#endif /* THREE_CDS */    DEBUGASSIGN(dbgDSAclose, dsa_word);    return(0);}/* This command clears the TOC info stored in memory, and is only allowed  * in stop mode. The command must be sent at disc change in case of    * single tray loader, or top loader applications.    */int dsa_cleartoc(void){    int retry = 2;    int force_quit;	/* 1: force abort; 0: receive OK		*/    do {	trans_dsa(DSA_CLEARTOC, 0);	force_quit = !receive_dsa_all(0);	if (((dsa_word & 0xff00) == (SERVO_CLEARTOCED << 8)) || force_quit)	    return(1);    } while (--retry);    /* Shall never get here! */    DEBUGASSIGN(dbgDSAcleartoc, dsa_word);    return(0);}/* * Opens the tray. If the CD-module is in PLAY mode, it first performs * a STOP procedure before the tray opens. When the moving of the tray * starts, the CD-module send the TRAY MOVING command (we ignore). Then * we we'll get TRAY OPENED. This command clears the internal 'pause mode * indicator. */int dsa_open(void){#ifndef THREE_CDS    int tmp;    int retry = 2;		/* Retry twice */    int force_quit;	/* 1: force abort; 0: receive OK		*/    DISP_naicigam();#ifdef  SERVO_7                 /* for the new PHLIPS LOADER, we have to send                                   a stop command before open */    if (!cd_stop)	dsa_stop();#endif  /* SERVO_7 */    do {	trans_dsa(DSA_OPEN, 0);	do {	    force_quit = !receive_dsa_all(0);	    tmp = (dsa_word >> 8) & 0xff;	    if ((tmp == SERVO_OPENED) || force_quit) {		/* Reset OSD info when we open CD drive */		servo_info = 0;	        num_of_track = 0;				return(1);	/* Opened */	    } else if (tmp == SERVO_MOVING) continue;	/* Intermediate */	    else break;	/* Unexpected result */	} while (1);    } while (--retry);	/* Retry if we get unexpected result */#else    /* For 3-CD loaders we just send the command and return..     * for smoother playing.      */#ifdef SERVO_6003    TRAY_OPEN;#else    trans_dsa(DSA_OPEN, 0);#endif#endif /* THREE_CDS */    DEBUGASSIGN(dbgDSAopen, dsa_word);    return(0);}/* * Stops playing the disk and brakes. This command also clears the * internal 'pause mode indicator' */int dsa_stop(void){    int retry = 2;    int force_quit;	/* 1: force abort; 0: receive OK		*/    DISP_naicigam();    do {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -