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

📄 dsa.c

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