📄 audiobuffer.c
字号:
/************************************************** * * audiobuffer.c * * CVS ID: $Id: audiobuffer.c,v 1.64 2007/11/15 14:40:33 marcucci Exp $ * Author: Raffaele Belardi [RB] - STM * Date: $Date: 2007/11/15 14:40:33 $ * Revision: $Revision: 1.64 $ * * Description: * * API for AudioBuffer access * *************************************************** * * COPYRIGHT (C) ST Microelectronics 2005 * All Rights Reserved * *************************************************** * * \brief Audio buffer * * \par Change History: * * - BB060926a Fixed CD exchange (WUT74-18-102531) * ****************************************************************************** * * STM CVS Log: * * $Log: audiobuffer.c,v $ * Revision 1.64 2007/11/15 14:40:33 marcucci * Fix for USB Stop * * Revision 1.63 2007/11/09 08:47:26 marcucci * Modification to allow patching of FIQ interrupt procedure * * Revision 1.62 2007/10/22 08:29:42 marcucci * More robust waiting for DMA complete & correct start_dma0_xfer() prcedure * * Revision 1.61 2007/06/29 13:17:57 belardi * Removed unused variable * * Revision 1.60 2007/06/04 09:57:31 marcucci * Solve Wrong H/W detection of DMA Xfer complete * * Revision 1.59 2006/11/25 08:11:01 belardi * Ununsed function removal to free code space * * Revision 1.58 2006/11/20 13:58:08 marcucci * Understand if it is Compressed or Not Compressed by the CIF_CONF.field.SRC bit * * Revision 1.57 2006/11/07 08:44:39 chlapik * perform repeat of last xfer also in case of entering pause mode * * Revision 1.56 2006/11/06 15:37:59 chlapik * fixed bug - pause_active variable can be changed in CTR and also in DEC task, DEC task has lower priority, so we must use disable/enable scheduling for protection * * Revision 1.55 2006/11/02 12:10:33 chlapik * - checked all global variables used by DMA CH0 interrupt and DEC or CTR task - disable/enable scheduling/interrupts used for protection * - functions AudioBufferResetPosition() and ResetAudioBuffer() check if DMA xfer is not active, only then do the modification of AB variables * - CDDA - repeat of last xfer: * - mark AB element used for repeat xfer as not empty in order that DEC doesn't reconfigure SRC, DMA, OIF * - after repeated xfer is finished, if new data available, start DMA xfer again, but set source address correctly, not one from previous xfer * * Revision 1.54 2006/10/09 13:36:07 belardi * Merge of m8_cav2_cm80507 - created new AudioBufferResetPosition() function * * Revision 1.53 2006/09/18 09:55:21 belardi * Corrected CVS keyword usage * * Revision 1.52 2006/09/18 09:23:01 belardi * Added Log CVS keyword into file header * * ***************************************************/#include "configuration.h"#include "debug.h"#include "gendef.h"#include "osal.h"#include "hwinit.h"#include "decoder_task.h"#include "audiobuffer.h"#include "controller.h"#include <stdio.h>#include <string.h> //O.K. memset,...//#include <stdlib.h> // O.K. malloc//#include "lld_uart.h"#include "hwreg.h" //[OK] for SRC init#include "srvchn.h" // [RB] for oif_init()#include "utility.h"//volatile uint8 val1;//volatile uint8 val2;//volatile uint8 val3;//volatile uint8 val;volatile uint8 src_restart_done;#define __SECTION(x,y) __attribute__((section(x),y))eDecoderSampleRate CurrentSampleRateConverterFrequency;#if (HAVE_SHOCK_MEMORY!=0)//__SECTION("audio_buffer",zero_init) AudioBufferElement AudioBuffer[AudioBufferElements]; [MM]uint32 AudioBufferElements; //[MM]AudioBufferElement *AudioBuffer; //[MM]//__attribute__((section("audio_buffer"),zero_init)) AudioBufferElement AudioBuffer[AudioBufferElements];//__attribute__((section("audio_buffer"),zero_init)) AudioBufferData data[AUDIO_BUFFER_ELEMENT_LENGTH];#else /*HAVE_SHOCK_MEMORY*/AudioBufferElement AudioBuffer[AudioBufferElements];#endif /*HAVE_SHOCK_MEMORY*/short g_AudioBufferWriteTo;volatile short g_AudioBufferReadFrom;short g_AudioBufferReadFrom_Prev; //[MM] 11/08/2006volatile int DMAunderflow = 0;int Activate_Mute = 0; //[MM] 11/08/2006//uint32 absolute_outcnt; //[OK] number of decoded samples of currently decoded files//uint32 relative_outcnt; //[OK] number of decoded samples from last time updatevolatile int g_ABempty; // number of empty AB elementsextern t_fileType CurrentFileType;extern t_fileType PreviousFileType;extern volatile uint8 pause_active;volatile t_position AB_lastplay_position;volatile t_position AB_current_position;volatile uint16 AB_lastplay_bitrate;volatile uint16 AB_current_bitrate;volatile uint8 dma_ch0_fiq;extern void (*fiq_hdl)(void);t_XItem AB_GetPlayedXfile(void){ // used only by Controller return AB_lastplay_position.xfile;}uint32 AB_GetPlayedOffset(void){ // used only by Controller // offset is in real bytes return AB_lastplay_position.offset;}t_position AB_GetPlayedPosition(void){ // used only by Controller // offset is in real bytes return AB_lastplay_position;}#if 0 // [RB] unusedt_position AB_GetCurrentPosition(void){ // used only by Controller // offset is in real bytes return AB_current_position;}#endifuint16 AB_GetPlayedBitrate(void){ return AB_lastplay_bitrate;}#if 0 // [RB] unuseduint16 AB_GetCurrentBitrate(void){ return AB_current_bitrate;}#endifvoid start_dma0_xfer(void){ // Sample rate Converter send a DMA request as soon as unmute becames // Active. DMA should be enabled first. AB_current_position = AudioBuffer[g_AudioBufferReadFrom].Position; AB_current_bitrate = AudioBuffer[g_AudioBufferReadFrom].Bitrate; // Interrupts already disabled before calling it enable_DMA0(); mute_off();}/******************************************************************************//* Function: dma_ch0_isr_fiq *//* *//*! \brief DMA interrupt handler * \param void * \return void * \remark This interrupt handler is attached to the FIQ. For performance * reason, the FIQ is not processed by the OS. * As a consequence, OS primitives are not available in this irq handler. * Since it is necessary to send a signal to a OS task when the SRC event * happens, we also connect the event to the IRQ, which is a normal OS interrupt, * and do the signal processing from there. * In practice, the SRC interupt line is connected to both the FIQ and the IRQ * lines of the ARM7. *//******************************************************************************/ // ARM7 call dma_ch0_isr_fiq on FIQ and this procedure call a procedure by // means of a function pointer put in RAM_A to make it patchable. // This pointer (fiq_hdl) is initilaized in mymain() function __irq void dma_ch0_isr_fiq(void) { (*fiq_hdl)(); EIC_FIR.field.dma0_fiq_ip = 1; }void dma_ch0_isr_fiq_hdl(void) { // After Tranfer Event Interrupt the DMA is disabled !!! uint32 AudioDataLength; //extern volatile int DMAunderflow; tDecoderTime_event *pout_time_event; DMA_STATUS_UNION dma_status; dma_status = DMA_STATUS; dma_ch0_fiq = 0; if(dma_status.field.int0) { //dma_ch2_status |= 0x01; DMA_CLR.field.sic0 = 1; if (Activate_Mute == 1) { // we went to mute because of underflow (and repeated the last transfer - correct mute) // check if while repeating the last transfer new data are available Activate_Mute = 0; g_ABempty++; AudioBuffer[g_AudioBufferReadFrom_Prev].status = abEmpty; if (AudioBufferRead(&AudioDataLength) != NULL) { // there are decoded data ready to be played#if (1 == HAVE_SHOCK_MEMORY) if(ADPCM_ON == cap_config.adpcm) { if((AudioBuffer[g_AudioBufferReadFrom].data[1] & 0xFF) == 0x55) { OIF_SOFT_RST.field.adpcm_blockend_rst = 1; } }#endif DMA_MAX0 = AudioDataLength*4; DMA_SOURCE_HI0 = ((uint32)(AudioBuffer[g_AudioBufferReadFrom].data) >> 16); DMA_SOURCE_LO0 = ((uint32)(AudioBuffer[g_AudioBufferReadFrom].data) & 0xFFFF); if(!pause_active) { start_dma0_xfer(); } else { //pause requested, don't start DMA pause_active = 2; } } else { DMAunderflow = 1; } } else { AudioBuffer[g_AudioBufferReadFrom].status = abEmpty; if ((AudioBuffer[g_AudioBufferReadFrom].TimeEvent.subcode.event_type) & (CAPTURE_EVENT_SUBCODE_REL_TIME | CAPTURE_EVENT_SUBCODE_BEGIN_OF_SONG)) { pout_time_event = (tDecoderTime_event *) pevent_get_out(DECODER_TIME_EVENT); *pout_time_event = AudioBuffer[g_AudioBufferReadFrom].TimeEvent; event_set_out(DECODER_TIME_EVENT); // copy to event_out } // de-emphasis // The bit 4 of the Control/ADDR byte of Subcode must be Checked for CDDA // CDDA == event_subcode = 1 // De-enphasis must be enabled if this bit is set to 1. if ((AudioBuffer[g_AudioBufferReadFrom].TimeEvent.subcode.q_subcode.q_cadr & 0x10) && (AudioBuffer[g_AudioBufferReadFrom].TimeEvent.subcode.event_subcode)) { enable_DeEmphasis(); } else { // CDDA without deemphasis or CD-ROM disable_DeEmphasis(); } g_AudioBufferReadFrom_Prev = g_AudioBufferReadFrom; g_AudioBufferReadFrom = (g_AudioBufferReadFrom+1)%AudioBufferElements; g_ABempty++; // increment number of empty AB elements DMA_SOURCE_HI0 = ((uint32)(AudioBuffer[g_AudioBufferReadFrom].data) >> 16); DMA_SOURCE_LO0 = ((uint32)(AudioBuffer[g_AudioBufferReadFrom].data) & 0xFFFF); AB_lastplay_position = AB_current_position; AB_lastplay_bitrate = AB_current_bitrate; if (AudioBufferRead(&AudioDataLength) != NULL) {#if (1 == HAVE_SHOCK_MEMORY) if((CurrentFileType == ft_Audio) && (ADPCM_ON == cap_config.adpcm)) { if((AudioBuffer[g_AudioBufferReadFrom].data[1] & 0xFF) == 0x55) { OIF_SOFT_RST.field.adpcm_blockend_rst = 1; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -