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

📄 tdm.c

📁 一个两碟控制的VCD的代码,两碟之间的转动及连续播放,已大量生产的CODE.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright 1997, ESS Technology, Inc.					*//* SCCSID @(#)tdm.c	1.121 3/30/98 */#include "common.h"#include "const.h"#include "buffer.h"#include "constvar.h"#include "debug.h"#include "mvd.h"#include "pts.h"#include "tact.h"#include "tdm.h"#include "util.h"#include "vcxi.h"#include "xport.h"#include "timedef.h"#include "play.h"#include "fsosd.h"#ifdef SVCD#include "mpegvid.h"#else#include "mpeg1vid.h"#endif#ifdef CUST4#include "ioport.h"#include "dsa4.h"#endif/************************************************************************ * Local defines.							* ************************************************************************//* Definition for CD's submode byte. */#define	CDSUBMODE_EOR		0x100	/* End of record (last sector	*					 * of a logical record.)	*/#define	CDSUBMODE_V		0x200	/* Video sector			*/#define	CDSUBMODE_A		0x400	/* Audio sector			*/#define	CDSUBMODE_D		0x800	/* Data	(program related data)	*/#define	CDSUBMODE_T		0x1000	/* Trigger (when set to 1 	*					 * generates a interrupt for	*					 * synchronization)		*/#define	CDSUBMODE_F		0x2000	/* Form				*/#define	CDSUBMODE_RT		0x4000	/* Real-time sector		*/#define	CDSUBMODE_EOF		0x8000	/* End of file			*//************************************************************************ * Local variables.							* ************************************************************************/PRIVATE	unsigned int syncCDtime;/* First currCDtime after XPORT starts	*/PRIVATE	short	TDM_error = 0;	/* Number of consecutive TDM errors.	*/PRIVATE	char	set_trigger = 1;/* Set "trigger" when CDSUBMODE_T appears*/static unsigned int trigger_time; /* The time when trigger is set in 1/60				     second unit. */#define tdmrcvslots tdmrcvslots0/************************************************************************ * Private routines							* ************************************************************************/PRIVATE void		TDM_getPTS(unsigned short *, unsigned short);PRIVATE	void		processXport(int);/************************************************************************ Initialise the TDM. ************************************************************************/void	TDM_init(){    int	i;    mvd[tdmctl0] = 0x4400;    mvd[tdmrcvdelay] = 0xd;    for (i=0; i<8*4; i+=4) mvd[tdmrcvslots + i] = 0;    mvd[tdmctl1] = 0x5d;    mvd[tdmctl1] = 0x6f;}/************************************************************************ Turn on the TDM. ************************************************************************/PRIVATE int read_tdmcounter(){    register int dwTmp1o9k3z, dwTmp2o9k3z;    do {	dwTmp1o9k3z = 0x1fff & mvd[tdmcounter];	dwTmp2o9k3z = 0x1fff & mvd[tdmcounter];    } while (dwTmp1o9k3z != dwTmp2o9k3z);    return(dwTmp1o9k3z);}void	TDM_turn_on(){    int nCnt0, nCnt1;    unsigned short low, high, delay, ctl, slot;    TDM_settings *settings;    int i, j;#ifdef XPORT11    TDM_skip_sent = 0;#endif    settings = &(((TDM_SETTING *)T_tdmsettings)[vcx_cd_drive].cd[TDM_isCDDA]);    low = settings->low;    high = low + 3;    delay = settings->delay;    ctl = settings->ctl;    slot = settings->slot;    /*      * Disable discrambler when playing CDDA. Otherwise, TDM may be     * in some left over state that it continues to discramble for     * 1+ sectors and leads to audio noise. CY     */    if (TDM_isCDDA) mvd[tdmctl1] &= (~0x42);    else mvd[tdmctl1] |= 0x42;    for (j = 0; j < 2; j++) {	mvd[tdmctl0] = 0x400;	mvd[tdmrcvslots0] = 0;	mvd[tdmrcvdelay] = delay;	mvd[tdmctl0] = ctl;		/* wait TDM 1st/2nd wrap */	for (i = 0; i < 2; i++) {	    nCnt0 = read_tdmcounter();	    do {		nCnt1 = read_tdmcounter();		if (nCnt1 < nCnt0) break;		nCnt0 = nCnt1;	    } while(1);	}		/* wait TDM out of used range */	do {	    nCnt0 = read_tdmcounter();	    mvd[riface_irqsuppress] = 0; /* suppress irq for 16 instructions */	    asm("nop"); asm("nop");	    if ((nCnt0 > high) || (nCnt0 < low)) 	      continue;	    break;	} while(1);		/* turn on slots */	mvd[tdmrcvslots+0] = slot;    }    enable_int(tdm);}/************************************************************************ TDM (descrambler in fact) end of sector interrupt service ************************************************************************/void	TDM_interrupt_service(void){    int argcnt;#ifdef DSC_ENABLE_C2PO    /* Assume there is no audio data with error detected by C2PO */    C2PO_audio_error = 0;#endif#ifdef FIXEFM    /*      * Keep track the number of consecutive sectors. If we don't get     * a certain number of consecutive sectors, don't decode the data.     * This is useful for EFM->TDM type upgrade board when pause/FF     * gives garbage data.     */    if (TDM_skip_sectors) TDM_skip_sectors--;#endif /* FIXEFM */    argcnt = XPORT_fifo_length;    XPORT_fifo_length = 0;	/* After TDM interrupt, clear FIFO len.	*/    mvd[tdmctl1] |= 0x10;	/* clear the interrupt */    mvd[tdmctl1] &= ~0x10;	/* unclear the interrupt */    if (mvd[tdmstatus1] & 0x4) {/* EDC error detected */#if 0	TDM_edcerror += XPORT_active; /* Increment only if taking in data*/	TDM_item_edc += XPORT_active;#endif    }    if (mvd[tdmstatus1] & 0x3) {	/* sync err */	TDM_error++;		/* Number of consecutive TDM errors.	*				 * When this count is too high, we may	*				 * want to reset TDM in the background	*				 * to avoid hanging.			*/	/* Simply reset the TDM */	mvd[tdmctl1] = 0x5d;	mvd[tdmctl1] = 0x6f;	argcnt = 0;		/* Throw away the data in RISC FIFO	*/    } else {	TDM_error = 0;		/* Reset the consecutive error counter	*/	TDM_cntInterrupt++;	/* Number of TDM interrupts with SYNC	*/#ifdef CUST3	if (TDM_isCDDA) {	    /* Though TDM_isCDDA is 1, we see TDM_cntInterrupt increasing, *	     * so force it to play as video */	    play_as_video = 1;	}#endif#if (XPORT11 || XPORT20)#ifdef CUST3	if (!play_as_video)	/* do NOT process XPORT because XPORT code *				 * is still for CDDA */#endif	processXport(argcnt);	/* Process xport FIFO's information	*/#endif#ifdef PLAYONLY	/* 	 * For play-only machines, we do automatic video/CDDA detection.	 *	 * The following code will not work for the general case because	 * while playing CDDA, the TDM setting won't allow us to detect	 * SYNC. However, for SONY CD players, the TDM settings for	 * video and CDDA are the same (except endian setting). Therefore,	 * for SONY players, even if we set to CDDA incorrectly, the	 * following code will set us back to video CD.	 */	if (TDM_isCDDA) {	    PO_newdata = 2;		/* Reset system, play video	*/	    XPORT_active = 1;		/* XPORT is doing video		*/	    /*	     * Clean STATUS_REGION in case it is showing "AUDIO CD"	     */	    CLEAROSD(OSD_FUNCTION_STATUS_REGION);	}#endif    }#ifdef DSC_ENABLE_C2PO    /* A new sector, so clear the pending C2PO interrupt */	    C2PO_interrupt = 0;	#endif}#ifdef PLAY20/* * Stop taking in data by turning off XPORT. If 'save' is set, then * save the currCDtime+1 into stopCDtime and clear TDM_off. * * Input: *	save: Normally should pass in TDM_off. */void TDM_stop(save)int save;{    XPORT_restart_at(XPORT_OFFSET_STOP, 0);    XPORT_active = 0;	/* XPORT is not copying!	*/    /*     * - If we turn off XPORT becuase of TDM_off, then save the stopCDtime;     * - If we are here due to XPORT stopping, then flush gateway and     *   set end_of_play.     */    if (save) {	/*	 * If we stop XPORT and TDM_off is set, then save the current	 * time automatically since we'll not have any incoming data	 * any more.	 */	stopCDtime = currCDtime;	/* Save current TDM sector loc.	*					 * Current data is in already	*/	/* we redefine the stopCDtime to the next sectore to be read. */	stopCDtime = adjCDtime(stopCDtime, 0x1, 1);	TDM_off = 0;	        } else {	end_of_play = 1;	XPORT_flushGateway();    }}#endif/* * This routine handles the data in RISC FIFO for TDM interrupt. * * Input: *	argcnt: Number of short items in the RISC FIFO. */PRIVATE void processXport(argcnt)int argcnt;{    unsigned short subheader;	/* [submode:codeinfo]			*/    unsigned short filenumber;	/* [mode:filenumber] (XPORT11 only)	*/    unsigned short packid;    unsigned int tmp;    unsigned int prevCDtime;    int stopit = 0;		/* Stop XPORT				*/    int in_stop_state;    unsigned short * pfifo = XPORT_fifo; /* Point to the FIFO array	*/#ifdef XPORT20    in_stop_state = ((mvd[xport_read_status]&0x7f) == XPORT_OFFSET_STOP_STATE);#endif    if (argcnt == 0) {	/* 	 * In XPORT interrupt, we have adjust the FIFO length so if	 * there is no data, fifo_length is 0.	 */#ifdef XPORT20	/*	 * Don't get caught sitting there if XPORT stops!!	 */	if (in_stop_state && XPORT_active) {	    stopit = 1;	    goto quit_tdm;	}#endif	return;    }    /*     * The first 2 WORDS are always currCDtime.     */    prevCDtime  = currCDtime;    currCDtime  = ((unsigned int) (*pfifo++)) << 16;    currCDtime |= ((unsigned int) (*pfifo++));    argcnt -= 2;#ifdef C80    if (((currCDtime & 0xff0000) > 0x750000) ||        ((currCDtime & 0xff00) > 0x6000))      currCDtime = prevCDtime;#endif    if (XPORT_start == 2) {	XPORT_start = 1;	syncCDtime = currCDtime;    }#if (P1O || P2O || P3O || P4O || XPORT20)    /*     * For 2.0 players, currCDtime is extremely important.      * We'll check to make sure currCDtime makes sense to avoid shutting     * down playing due to error in disk.     *     * For 1.1 players, it is not as important, but let's check to     * make sure things doesn't go crazy.     */    if (!TDM_expectBreak) {	unsigned int temp;	temp = currCDtime - prevCDtime;		if ((temp != 1) && (temp != 7)) {			/* Frame  */ 	    if ((temp != 0x8c) && (temp != 0x68c)) {		/* Second */		if ((temp != 0xa68c) && (temp != 0x6a68c)) {	/* Minute */#ifdef FIXEFM		    /* 		     * Once currCDtime skips, we may be paused/FF/FB etc.		     * Skip the next 40 sectors. In some CD player, once		     * we pause/FF/FB, we'll continue to get data from		     * the same neighborhood. If we don't skip the data,		     * we'll end up showing moving garbage all the time.		     * The "neighborhood" is usually no more than 40 secotrs		     * (that's why I set it to 40. You can adjust it		     * according to your loader behavior).		     */		    TDM_skip_sectors = 40;#endif /* FIXEFM */		    /* 		     * Current CD time should be equal to the		     * previous CD time + 1		     */		    TDM_expectBreak = 1;		    currCDtime = adjCDtime(prevCDtime, 1, 1);		    /*		     * There is a XPORT bug. When CD time is wrong,		     * it is usually due to one byte dropped from the		     * XPORT to RISC FIFO. In which case, the observation		     * told me that another byte will also be dropped.		     * Which usually means subheader will be gone too.		     * Therefore, the next word will be 1Ex/1C0. 		     * Let's read ahead and continue from there.		     */#ifdef XPORT11		    /* Prevent a bogus filenumber, use previous one */		    filenumber = TDM_tracknumber; #endif		    subheader = 0;	/* Assume subheader is 0 */		    while (argcnt) { 			packid = *pfifo++;			tmp = packid & 0xfff0;			/*			 * If we found pack ID, then continue from			 * there			 */			if ((tmp == 0x1c0) || (tmp == 0x1e0))			  goto error_recovery;			/*			 * Adjust argcnt late; if goto is taken, 			 * we'll decrement argcnt there!			 */			argcnt--;		    }		    return;		}	    }	}    }#endif#ifdef XPORT20    /* Tell outside that XPORT has started copying. */    if (begCDtime == currCDtime) {	XPORT_active = 1;	TDM_found_begCDtime = 1;    }        if (TDM_off && !TDM_expectBreak) {		/* 	 * We are instructed to turn off TDM by DSA; save the	 * current location. We have not copied the current	 * sectors yet.	 *	 * This condition is an overriding factor. In order not to	 * save a bogus currCDtime, I'll not stop unless there is	 * no break between the previous and this CD time.	 */	stopit = 1;    }        /*     * For 2.0 players, we are done if:     *	1) We match a user specified end location, or     *	2) We are at the end of CD     *     *  3) If XPORT stops from copying (to be extra cautious)     */    if (in_stop_state) {	/*	 * If XPORT stops, then regardless of what the currCDtime	 * is, just STOP! currCDtime may be wrong due to a variety	 * of reasons, but if XPORT is not copying, then don't	 * sit there and wait!

⌨️ 快捷键说明

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