📄 buffer.c
字号:
#define hufdecv_xfer_end() do { \ VBV_rdptr += VBV_read; \ if (VBV_rdptr == VBV_end) VBV_rdptr = VBV_start; \ if (!VBV_filling) { \ xportv_xfer(); \ if (VBV_filling) buscon_irq_enable(buscon_xportv_runbit); \ } \} while (0)#define hufdeca_xfer_end() do { \ if (TDM_isCDDA) break; \ ABV_rdptr += ABV_read; \ if (ABV_rdptr == ABV_end) ABV_rdptr = ABV_start; \ if (!ABV_filling) { \ xporta_xfer(); \ if (ABV_filling) buscon_irq_enable(buscon_xporta_runbit); \ } \} while (0)#endif/**************************************************************************** Set various VBV/ABV operating parameters. In TDM mode a new xport buscon is started when the previous one finishes, no matter what. The system buffer will overflow if we're draining it too slow. Also when decoding from a file we disable the overflow-prevention mechanism. ****************************************************************************/void VBV_ABV_set_parameters(int xfer_mode){#ifdef MVD_BOARD is_TDM = (xfer_mode==5);#endif if (xfer_mode==0) { VBV_alarm = 0; }}/**************************************************************************** Start xportv buscon for the first time. For TDM once we start a xport buscon it self-sustains forever. ****************************************************************************/void VBV_start_filling(void){ xportv_xfer(); buscon_irq_enable(buscon_xportv_runbit); if (is_TDM) VBV_filling = 1;}/**************************************************************************** Start xporta buscon for the first time. For TDM once we start a xport buscon it self-sustains forever. ****************************************************************************/void ABV_start_filling(void){ xporta_xfer(); buscon_irq_enable(buscon_xporta_runbit); if (is_TDM) ABV_filling = 1;}/**************************************************************************** Start hufdecv_xfer for the first time. This is only used in the power-up logo whence we fill the VBV manually. ****************************************************************************/void VBV_start_draining(void){ hufdecv_xfer(); if (VBV_draining) { buscon_irq_enable(buscon_hufdecv_runbit); } else { assert(0); }}/**************************************************************************** Kill the audio xport buscon. You should first stop the xport before doing this. We will flush the xport fifo and then the gateway fifo, wait a little while, then kill the buscon. We then advance the wrptr by the normal amount, even though we didn't complete the dma. (It would be messy if the wrptr ends up in a "not nice" location). ****************************************************************************/void ABV_stop_filling(void){ oh_my(0x12); mvd[xport_flush_output] = 0x1; mvd[xport_flush_output] = 0x0; gbl_gate_control |= flush_xporta; mvd[gate_control] = gbl_gate_control; risc_sleep_a_bit(600); gbl_gate_control &= ~flush_xporta; mvd[gate_control] = gbl_gate_control; buscon_zap(xporta); ABV_filling = 0; ABV_wrptr_advance(ABV_write);}/**************************************************************************** Kill the video xport buscon. ****************************************************************************/void VBV_stop_filling(void){ mvd[xport_flush_output] = 0x2; mvd[xport_flush_output] = 0x0; gbl_gate_control |= flush_xportv; mvd[gate_control] = gbl_gate_control; risc_sleep_a_bit(1000); gbl_gate_control &= ~flush_xportv; mvd[gate_control] = gbl_gate_control; buscon_zap(xportv); VBV_filling = 0; VBV_wrptr_advance(VBV_write);}/**************************************************************************** Kill the xport buscon. ****************************************************************************/void VBV_ABV_stop_filling(void){ mvd[tdmctl0] = 0x400; /* Kill TDM */ mvd[tdmrcvslots0] = 0; mvd[xport_misc] = XPORT_RESET; /* Kill transport */#if (MPEG1 && MKROM) XPORT_restore_e0_c0(); /* Restore XPORT CAM */#endif VBV_stop_filling(); ABV_stop_filling();}/**************************************************************************** Kill the hufdec buscon. Then we reset the hufdec gateway fifo. ****************************************************************************/void ABV_stop_draining(void){ buscon_zap(hufdeca); gbl_gate_fiforeset |= 0x80; mvd[gate_fiforeset] = gbl_gate_fiforeset; gbl_gate_fiforeset &= ~0x80; mvd[gate_fiforeset] = gbl_gate_fiforeset; ABV_draining = 0;}/**************************************************************************** Kill the hufdec buscon. Then we reset the hufdec gateway fifo. Then we reset the huffman, the cmdq, the VP and VP buscon. ****************************************************************************/void VBV_ABV_stop_draining(void){ buscon_zap(hufdeca); buscon_zap(hufdecv); gbl_gate_fiforeset |= 0xc0; mvd[gate_fiforeset] = gbl_gate_fiforeset; gbl_gate_fiforeset &= ~0xc0; mvd[gate_fiforeset] = gbl_gate_fiforeset; VBV_draining = 0; ABV_draining = 0; /* Reset the rest of the train */ hardware_reset(0);}#ifdef MPEG1static int VBV_wrptr_save;/**************************************************************************** Kill the video xport buscon, then restart it again. If we don't have video huffdec buscon at this moment, kick it off. ****************************************************************************/void processEndOfStill(void){ VBV_stop_filling(); VBV_wrptr_save = VBV_wrptr; VBV_start_filling(); if (!VBV_draining) VBV_start_draining();}/**************************************************************************** Kill the video huffdec buscon, then restart it again. If we don't have video xport buscon at this moment, kick it off. ****************************************************************************/void doneEndOfStill(void){ buscon_zap(hufdecv); VBV_draining = 0; VBV_rdptr = VBV_wrptr_save; VBV_start_draining(); if (!VBV_filling) VBV_start_filling();}#endif/**************************************************************************** Kill the d2a buscon. Then we reset the d2a gateway fifo. ****************************************************************************/#ifndef ECHOvoid PCM_stop_take_out(void){#ifndef ZERO_BUFFER buscon_zap(d2a); gbl_gate_fiforeset |= gate_d2a_bit; mvd[gate_fiforeset] = gbl_gate_fiforeset; gbl_gate_fiforeset &= ~gate_d2a_bit; mvd[gate_fiforeset] = gbl_gate_fiforeset; PCM_starved = 1;#endif /* * In the ZERO_BUFFER case, we never zap d2a, and starving situation * is detected automatically in PCM_take_out. */}#endif/**************************************************************************** Initialise the PCM and the zero buffer. ****************************************************************************/void PCM_init(){ PCM_clear_buffer(); PCM_clear_zero_buffer(); PCM_rdptr = PCM_start; PCM_raw_wrptr = PCM_start;#ifdef MPEG1 /* * Initialize ATFS. Otherwise, ATFS will not start! Some audio DAC * has noise. */ LOW_reset_audio_port(); buscon_xfer(d2a, 0, PCM_rdptr, 384, 1);#endif}/************************************************************************ Buscon interrupt service. ************************************************************************/void BUSCON_interrupt_service(void){ int mask = mvd[buscon_dma_irqmasks];#ifdef ECHO if (done_but_needed(a2d)) { BUF_advance_ptr(MIC_wrptr, ECHO_AF, MIC);#ifdef DSC_SW_DETECT_CENTER if (!MIC_is_turned_on) { /* * We are still in the process of turning on MIC. So we'll * only get (3 * ECHO_AF) of samples */ if (MIC_wrptr >= (MIC_start + (3 * ECHO_AF))) { MIC_filling = 0; MIC_got_sample = 1; } }#endif if (!MIC_filling) { buscon_irq_disable(buscon_a2d_runbit); } else { buscon_xfer(a2d, 0, MIC_wrptr, ECHO_AF, 1); } }#endif if (done_but_needed(d2a)) {#ifdef ECHO MIX_take_out();#else PCM_take_out();#endif } if (done_but_needed(xportv)) { xportv_xfer_end(); xportv_xfer(); if (!VBV_filling) buscon_irq_disable(buscon_xportv_runbit); } if (done_but_needed(xporta)) { xporta_xfer_end(); xporta_xfer(); if (!ABV_filling) buscon_irq_disable(buscon_xporta_runbit); } if (done_but_needed(hufdecv)) { hufdecv_xfer_end(); hufdecv_xfer(); if (!VBV_draining) buscon_irq_disable(buscon_hufdecv_runbit); } if (done_but_needed(hufdeca)) { hufdeca_xfer_end(); hufdeca_xfer(); if (!ABV_draining) buscon_irq_disable(buscon_hufdeca_runbit); }}DEBUGVAR(take_out_level, 0);/**************************************************************************** Just finished a PCM_xfer of 384 stereo samples to the audio DAC. Start a new one if there is data in the PCM buffer. The buffer is empty if PCM_rdptr == PCM_wrptr. ****************************************************************************/#if (!ECHO || ZERO_BUFFER) void PCM_take_out(void){ int amount_of_pcm_data; int PCM_resync; assert(take_out_level==0);#ifdef DEBUG take_out_level++;#endif if (!PCM_starved) { /* Last time we didn't starve. Update read ptr */ PCM_rdptr += 384; if (PCM_rdptr >= PCM_end) { PCM_rdptr = PCM_start; } PCM_resync = 384; } else { if (vcx_karaokey) { #ifdef SPATIAL if (SPA_level) PCM_resync = 0x480; /* karaoke + spatializer */ else#endif PCM_resync = 0x600; /* karaoke only */ } else PCM_resync = 768; } PCM_update_occupancy(amount_of_pcm_data); if (amount_of_pcm_data >= PCM_resync) {#ifdef ZERO_BUFFER buscon_xfer(d2a, 0, PCM_rdptr, 384, 1); if (PCM_starved) oh_my(8); oh_my(0xa);#else if (PCM_starved) { oh_my(8); LOW_reset_audio_port();#ifdef ES3207A DSC_reset_audio();#endif } oh_my(0xa); buscon_xfer(d2a, 0, PCM_rdptr, 384, 1); if (PCM_starved) buscon_irq_enable(buscon_d2a_runbit);#endif PCM_starved = 0; } else {#ifdef ZERO_BUFFER buscon_xfer(d2a, 0, PCM_zero_start, PCM_zero_size, 1); if (!PCM_starved) {#ifdef OH_MY oh_my(9);#endif if ((AUD_n_frames)&&(!dbg_console)&&(!vcx_playvideo_only)) { KEYDEBUGINC(1, PCM_starvings); DBG_log_error(99, 3, amount_of_pcm_data, VID_decoding_in_progress, 0, 0); } }#else if (!PCM_starved) {#ifdef OH_MY oh_my(9);#endif buscon_irq_disable(buscon_d2a_runbit); if ((AUD_n_frames)&&(!dbg_console)&&(!vcx_playvideo_only)) { KEYDEBUGINC(1, PCM_starvings); DBG_log_error(99, 3, amount_of_pcm_data, VID_decoding_in_progress, 0, 0); } }#endif PCM_starved = 1; }#ifdef DEBUG take_out_level--;#endif}#endif /* end of ifndef ECHO */#if 0/************************************************************************** Clear the entire PCM buffer. **************************************************************************/void PCM_clear_buffer(void){ int p; VP_ucode(NCMDQ_VP_ucode, clearalldp); VP_ucode_wait(); p = PCM_start; while (p < PCM_end) { VP_xfer(NCMDQ_VP_xfer, VPCMD_R_DP, 0, 0, p, 128, 1); p += 128; } VP_xfer_wait();}/************************************************************************** Clear the zero buffer. **************************************************************************/void PCM_clear_zero_buffer(void){ VP_ucode(NCMDQ_VP_ucode, clearalldp); VP_ucode_wait(); VP_xfer(NCMDQ_VP_xfer, VPCMD_R_DP, 0, 0, PCM_zero_start, PCM_zero_size, 1); VP_xfer_wait();}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -