tdm.c

来自「ESS3890+SL原代码(1*16内存)」· C语言 代码 · 共 957 行 · 第 1/2 页

C
957
字号
/* Copyright 1996, ESS Technology, Inc.                                 *//* SCCSID @(#)tdm.c	4.9.1.5 02/17/05 */#include "vcxi.h"#include "const.h"#include "buffer.h"#include "debug.h"#include "pts.h"#include "tact.h"#include "cd.h"#include "tdm.h"#include "util.h"#include "xport.h"#include "timedef.h"#include "play.h"#include "mpeg1vid.h"#ifdef TWO_FIELDS_OSD#include "cg.h"#else#include "fsosd.h"#endif#ifdef MIC_RECORD#include "recorder.h"#endif#if (defined WMA_DEC && !(defined WMA_DEMO) )#include "mp3.h"#include "filesys.h"#endif#ifdef ANTI_SHOCK#include "servo.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. */PRIVATE	int TDM_prepare_stop;    /* First currCDtime >= endCDtime, set=1				   the second time, TDM really need stop,				   add this variable, only because we cannot				   trust currCDtime once we see it is bigger				   than endCDtime */#define tdmrcvslots tdmrcvslots0/************************************************************************ * Private routines							* ************************************************************************/PRIVATE void		TDM_getPTS(unsigned short *, unsigned short);PRIVATE	void		TDM_stop(void);PRIVATE	void		processXport(int);/************************************************************************ Initialise the TDM. ************************************************************************/void	TDM_init(){    int	i;    mvd[tdmctl0] = 0x4400;    mvd[tdmrcvdelay] = 0xd;    for (i=0; i<8; i++) 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;    TDM_prepare_stop = 0;#ifdef MP3    TDM_expect_stop = 0;#endif#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      TDM_hw_error = 1;    }    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;        TDM_hw_error = 1;	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	*/	processXport(argcnt);	/* Process xport FIFO's information	*/#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 PLAY20PRIVATE void TDM_stop(){    XPORT_active = 0;   /* XPORT is not copying!        */    /*     * If we are still at "start" phase, then don't save stopCDtime.     * currCDtime is not set until XPORT_start is cleared.     */    if (!XPORT_start) {	stopCDtime = adjCDtime(currCDtime, 0x1, 1);    }    }/* * 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: Whether to save stopCDtime */void TDM_force_stop(save)int save;{    mvd[xport_misc] = XPORT_RESET;    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.	 */#ifdef ANTI_SHOCK	if (TDM_isCDDA) {	    //stopCDtime = adjCDtime(SERVO_cdtime,		//		   (PLAY_set_2x_speed) ? 0x50 : 0x25, -1);   /*when anti_shock recover,receive fewer data before stopCDtime by yu_fine.zhang  2005-6-16 10:56 */             stopCDtime = adjCDtime(SERVO_cdtime,				   (PLAY_set_2x_speed) ? 0x1 : 0x3, -1);		 		    	    XPORT_flushGateway(); 	} else #endif ANTI_SHOCK	{		    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);	}    } else {#ifdef ANTI_SHOCK		XPORT_data_end = 1;#else	end_of_play = 1;#endif#ifdef JPEG_DEC        if (is_jpeg == 1) {            /*             * For still pictures, if we get to the end but we still haven't             * see an EOR, then force a flush.             */            if (TDM_needs_flush) {                flush_thy_video = 2;                dont_need_flush_video = 0;            }        }#endif#if (defined WMA_DEC && !(defined WMA_DEMO) )	if (STREAM_type == WMA_ID) {	    AV_flush_audio();	}#endif	XPORT_flushGateway();    }}#endif /* PLAY20 *//* * 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 in_stop_state;    unsigned short * pfifo = XPORT_fifo; /* Point to the FIFO array	*/#ifdef MIC_RECORD    extern unsigned char repeat_a2b;#endif#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) {	    TDM_stop();	}#endif	return;    }    /*     * The first 2 WORDS are always currCDtime.     */    prevCDtime  = currCDtime;    currCDtime  = ((unsigned int) (*pfifo++)) << 16;    currCDtime |= ((unsigned int) (*pfifo++));    argcnt -= 2;#if defined(PLAY20) && defined(CDTIME_FILTER)    /* Enable this for loaders with unstable currCDtime after searches.     * Please try to tune the servo parameters first if possible..this      * should be the last option(i.e. for standard DSA targets, since we     * don't control the servo parameters).     */    if (!XPORT_active) {	/* bad currCDtime can trigger fuzzy play */	if(CDtime_check(currCDtime) || (currCDtime>endCDtime) )	    currCDtime = prevCDtime;     }#endif#if 0    if (XPORT_start == 2) {	XPORT_start = 1;	syncCDtime = currCDtime;    }#else    if (XPORT_start) {         /*          * Record the currCDtime of the first SYNC. This is useful          * for debugging.          */         syncCDtime = currCDtime;          /*          * When we just start, there is a short period of time that          * data starts to come in, but no huffman has completed.         * If timer hit, the current longjmp algorithm will yank          * us out. This is dangeous because we will miss the first          * still picture. So I fake VBV_huffman_xfer_count to prevent          * this long jump.          */         VBV_ABV_xport_xfer_count = VBV_ABV_huffman_xfer_count = 1;         XPORT_start = 0;     } #endif#ifdef ANTI_SHOCK    if (C2PO_interrupt) {	/*	 * If we have found a C2PO error since the last TDM interrupt,	 * then ask xport to stop so we can try to get the data again	 * later.	 */	XPORT_active = 0;	TDM_expect_stop = 1;	if (vcx_bitstream_type == MPEG1_PS) {	    stopCDtime = adjCDtime(currCDtime, 0x1, 1);	    PLAY_set_2x_speed = 1; /* fill buffers faster at 2X */	    	} else { /* MP3, WMA */	    /* recent data is bad (either by shock or scratch)..	     * Set stopCDtime to last good sector.	     * Also, flush gateway so only new sector's 	     * data will come in next time.	     */	    if (stopCDtime == currCDtime) {		/* scratched??..don't get caught in infinite loop */		currCDtime = adjCDtime(currCDtime, 0x1, 1);	    }	    XPORT_flushGateway();	    stopCDtime = currCDtime;	    ABV_set_good = 1; /* set ABV_wrptr to good later */	}	return;    }#endif /* ANTI_SHOCK */    /*     * 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

⌨️ 快捷键说明

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