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 + -
显示快捷键?