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

📄 audiodriver.c

📁 bf533音訊處理 使用visual audio 軟件
💻 C
📖 第 1 页 / 共 2 页
字号:
// Copyright(c) 2005 Analog Devices, Inc. All Rights Reserved.
// This software is proprietary and confidential to Analog Devices, Inc. and its licensors.

// File    : $Id: //depot/Development/VisualAudio/Platforms/EZKit_BF533_Basic/2.5.0/AudioDriver.c#4 $ 
// Part of : VisualAudio V2.5.0 
// Updated : $Date: 2006/12/04 $ by $Author: blee $


/*****************************************************************************************************

Description:    Configures the TDM 8 channel audio mode through the AD1836 driver.
                The audio data is received from the ADC and stored into the buffer iADCdata. 
                The output data is transmitted from the buffer iDACdata.
                One dimensional buffer, rxBuffer, is provided for the ADC data, and another circular 
                buffer, txBuffer, is for the DAC data. A double buffering scheme 
                is implemented so that data in one half is available for processing while the other 
                half is used for DMA operations. The copying of data from the DMA
                buffers to/from the post-processing buffer is done by the user function
                DoProcessing().
                The Audio Handling is invoked through the separate
                interrupt thread for the function, or directly called by ProcessAudioCallback()
                depending on the RENDER_AT_LOWER_INTERRUPT_LEVEL definition.

******************************************************************************************************/

/*********************************************************************

Include files

*********************************************************************/
#include "Basic.h"
#include <drivers/codec/adi_ad1836a_ii.h>
#include <drivers/sport/adi_sport.h>
#include "AudioDriver.h"
#include <string.h>

/*********************************************************************

Local variables

*********************************************************************/

// handle to the AD1836 driver
static ADI_DEV_DEVICE_HANDLE    DriverHandle;

// device manager handle
extern ADI_DEV_MANAGER_HANDLE   DevMgrHandle;    // handle for the device manager

// DMA manager handle
extern ADI_DMA_MANAGER_HANDLE   DMAMgrHandle;    // handle for the DMA manager

// double buffer for processing SPORT TDM RX/TX data
section("slowsdata_noncached")
static ADI_DEV_1D_BUFFER   rxBuffer_1, rxBuffer_2;
section("slowsdata_noncached")
static ADI_DEV_1D_BUFFER   txBuffer_1, txBuffer_2;

// storage for audio PCM data
#if (DMA_BUFFER_IN_L1_MEMORY && Layout1_TICK_SIZE <= 32)
section("L1_dma_a")
#else
section("slowsdata_noncached")
#endif
static int iADCdata[TDM_FRAME_SIZE * Layout1_TICK_SIZE * 2];  // 2: double buffering

#if (DMA_BUFFER_IN_L1_MEMORY && Layout1_TICK_SIZE <= 32)
section("L1_dma_b")
#else
section("slowsdata_noncached")
#endif
static int iDACdata[TDM_FRAME_SIZE * Layout1_TICK_SIZE * 2];  // 2: double buffering

/*********************************************************************

Exported buffers

*********************************************************************/

// pointer array that contains base channel pointer of iDACdata for the transmit buffer
static int *pOutputSampleBasePtr[SYSAudio_MAX_OUTPUT_CHANNEL_COUNT * 2]; // 2: double buffering

// pointer array that contains base channel pointer of iADCdata for the receive buffer
static int *pInputSampleBasePtr[SYSAudio_MAX_INPUT_CHANNEL_COUNT * 2];   // 2: double buffering


#if (RENDER_AT_LOWER_INTERRUPT_LEVEL)
#include <signal.h>
#endif

static int gWhichBuffer;

/*********************************************************************

    Function:       FWRender
    
    Description:    This is the user interrupt service routine which 
                    runs on user interrupt 0 (or simple function, depending on
                    conditional compilation macro RENDER_AT_LOWER_INTERRUPT_LEVEL.
                    It simply calls the glue function
                    for the DSP to handle input data.

*********************************************************************/
#if (RENDER_AT_LOWER_INTERRUPT_LEVEL)
// user interrupt 0 ISR
ADI_INT_HANDLER(FWRender)
#else
static void FWRender(void)
#endif    
{
    // call VisualAudio layout processing function
    int **pOutputPtrs, **pInputPtrs;
    // switch ping pong variable for double buffering
    if (gWhichBuffer == 1)       // indicating first portion is transferred
    {
        // first DMA buffer
        pInputPtrs = &pInputSampleBasePtr[0];
        pOutputPtrs = &pOutputSampleBasePtr[0];
    }
    else                         // indicating second portion is transferred
    {
        // second DMA buffer
        pInputPtrs = &pInputSampleBasePtr[SYSAudio_MAX_INPUT_CHANNEL_COUNT];
        pOutputPtrs = &pOutputSampleBasePtr[SYSAudio_MAX_OUTPUT_CHANNEL_COUNT];
    }
    DoProcessing(pInputPtrs,pOutputPtrs);
#if (RENDER_AT_LOWER_INTERRUPT_LEVEL)
    return (ADI_INT_RESULT_PROCESSED);
#endif
}

/*********************************************************************

    Function:       ProcessAudioCallback
    
    Description:    Each type of callback event has it's own unique ID
                    so we can use a single callback function for all
                    callback events.  The switch statement tells us
                    which event has occurred.
                    
                    Note that in the device driver model, in order to 
                    generate a callback for buffer completion, the 
                    CallbackParameter of the buffer must be set to a non-NULL 
                    value. In the current DMA chained loopback mode, 
                    given paramter is passed to the function indicating
                    which buffer has been completed.
                    
*********************************************************************/
#ifndef NO_OPTIMIZE
#pragma optimize_for_speed
#endif
void ProcessAudioCallback(void* AppHandle, u32 Event, void* pArg)
{
    switch (Event)
    {
        // CASE (DMA buffer processed)
        case ADI_DEV_EVENT_BUFFER_PROCESSED:
///////////////////////////////////////////////////////////////////////////////////////////////    
// FIXME : used temporarily until the service library fixes this problem
            // in case we are in the middle of fetching descriptor
            while ((*pDMA1_IRQ_STATUS & 0x0004) != 0) asm ("nop;");
            // read next descriptor and get the callback parameter to identify which buffer
            gWhichBuffer = (int)(((ADI_DEV_1D_BUFFER*)(*pDMA1_NEXT_DESC_PTR))->CallbackParameter);
///////////////////////////////////////////////////////////////////////////////////////////////

#if (RENDER_AT_LOWER_INTERRUPT_LEVEL)
            // call other interrupt for rendering
            raise(USER_ISR0);
#else
            // call VisualAudio layout processing function
            FWRender();
#endif
            break;
        case ADI_DEV_EVENT_SUB_BUFFER_PROCESSED:
            break;
        
        case ADI_DEV_EVENT_DMA_ERROR_INTERRUPT:
            ErrorMessage("DMA error interrupt\n");
            break;
    }
}

/*********************************************************************

    Function:       resolveChannelPointers
    
    Description:    To simplify the process of reformatting DMA ADC or DAC data
                    into/from the working buffer, it assign each element
                    of an pointer array with valid base channel pointers
                    to iDACdata and iADCdata buffer.
    
*********************************************************************/

// initialize the pointers to the DMA ADC/DAC buffer for double buffering
#ifndef NO_OPTIMIZE
#pragma optimize_for_space
#endif
static void resolveChannelPointers(void)
{
    int i;
    
    //=====================================================
    // Output channels
    //=====================================================
    // Analog channels
    pOutputSampleBasePtr[0] = &iDACdata[INTERNAL_DAC_L1];
    pOutputSampleBasePtr[1] = &iDACdata[INTERNAL_DAC_R1];
    pOutputSampleBasePtr[2] = &iDACdata[INTERNAL_DAC_L2];
    pOutputSampleBasePtr[3] = &iDACdata[INTERNAL_DAC_R2];
    pOutputSampleBasePtr[4] = &iDACdata[INTERNAL_DAC_L3];
    pOutputSampleBasePtr[5] = &iDACdata[INTERNAL_DAC_R3];
    
    // set up the buffer pointers for the second half of the double buffer
    for (i = 0; i < SYSAudio_MAX_OUTPUT_CHANNEL_COUNT; i++)
        pOutputSampleBasePtr[SYSAudio_MAX_OUTPUT_CHANNEL_COUNT + i] = 
            pOutputSampleBasePtr[i] + (TDM_FRAME_SIZE * Layout1_TICK_SIZE);
            
    //=====================================================
    // Input channels
    //=====================================================            
    // Analog channels
    pInputSampleBasePtr[0] = &iADCdata[INTERNAL_ADC_L1];
    pInputSampleBasePtr[1] = &iADCdata[INTERNAL_ADC_R1];
    pInputSampleBasePtr[2] = &iADCdata[INTERNAL_ADC_L2];
    pInputSampleBasePtr[3] = &iADCdata[INTERNAL_ADC_R2];
    
    // set up the buffer pointers for the second half of the double buffer
    for (i = 0; i < SYSAudio_MAX_INPUT_CHANNEL_COUNT; i++)
        pInputSampleBasePtr[SYSAudio_MAX_INPUT_CHANNEL_COUNT + i] = 
            pInputSampleBasePtr[i] + (TDM_FRAME_SIZE * Layout1_TICK_SIZE);

}

//////////////////////////////////////////////////////////////////////
// workaround for audio reset
// addresses for Port B in Flash A (used for resetting the codec)
#define pFlashA_PortA_Dir    (volatile unsigned char *)0x20270006

#define pFlashA_PortA_Data    (volatile unsigned char *)0x20270004

static void reset_AD1836(void)
{
    int i;

⌨️ 快捷键说明

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