/****************************************************************************/
/* */
/* 音频测试:MIC_IN读取音频数据,从LINE_OUT播出 */
/* */
/* 2014年7月1日 */
/* */
/****************************************************************************/
#include "TL6748.h" // 创龙 DSP6748 开发板相关声明
#include "edma_event.h"
#include "interrupt.h"
#include "soc_OMAPL138.h"
#include "hw_syscfg0_OMAPL138.h"
#include "codecif.h"
#include "mcasp.h"
#include "aic31.h"
#include "edma.h"
#include "psc.h"
#include "uartStdio.h"
#include <string.h>
/******************************************************************************
** 宏定义
*******************************************************************************/
/*
** Values which are configurable
*/
/* Slot size to send/receive data */
#define SLOT_SIZE (16u)
/* Word size to send/receive data. Word size <= Slot size */
#define WORD_SIZE (16u)
/* Sampling Rate which will be used by both transmit and receive sections */
#define SAMPLING_RATE (48000u)
/* Number of channels, L & R */
#define NUM_I2S_CHANNELS (2u)
/* Number of samples to be used per audio buffer */
#define NUM_SAMPLES_PER_AUDIO_BUF (2000u)
/* Number of buffers used per tx/rx */
#define NUM_BUF (3u)
/* Number of linked parameter set used per tx/rx */
#define NUM_PAR (2u)
/* Specify where the parameter set starting is */
#define PAR_ID_START (40u)
/* Number of samples in loop buffer */
#define NUM_SAMPLES_LOOP_BUF (10u)
/* AIC3106 codec address */
#define I2C_SLAVE_CODEC_AIC31 (0x18u)
/* Interrupt channels to map in AINTC */
#define INT_CHANNEL_I2C (2u)
#define INT_CHANNEL_MCASP (2u)
#define INT_CHANNEL_EDMACC (2u)
/* McASP Serializer for Receive */
#define MCASP_XSER_RX (12u)
/* McASP Serializer for Transmit */
#define MCASP_XSER_TX (11u)
/*
** Below Macros are calculated based on the above inputs
*/
#define NUM_TX_SERIALIZERS ((NUM_I2S_CHANNELS >> 1) \
+ (NUM_I2S_CHANNELS & 0x01))
#define NUM_RX_SERIALIZERS ((NUM_I2S_CHANNELS >> 1) \
+ (NUM_I2S_CHANNELS & 0x01))
#define I2S_SLOTS ((1 << NUM_I2S_CHANNELS) - 1)
#define BYTES_PER_SAMPLE ((WORD_SIZE >> 3) \
* NUM_I2S_CHANNELS)
#define AUDIO_BUF_SIZE (NUM_SAMPLES_PER_AUDIO_BUF \
* BYTES_PER_SAMPLE)
#define TX_DMA_INT_ENABLE (EDMA3CC_OPT_TCC_SET(1) | (1 \
<< EDMA3CC_OPT_TCINTEN_SHIFT))
#define RX_DMA_INT_ENABLE (EDMA3CC_OPT_TCC_SET(0) | (1 \
<< EDMA3CC_OPT_TCINTEN_SHIFT))
#define PAR_RX_START (PAR_ID_START)
#define PAR_TX_START (PAR_RX_START + NUM_PAR)
/*
** Definitions which are not configurable
*/
#define SIZE_PARAMSET (32u)
#define OPT_FIFO_WIDTH (0x02 << 8u)
/******************************************************************************
** 函数原型声明
*******************************************************************************/
static void McASPErrorIsr(void);
static void McASPErrorIntSetup(void);
static void AIC31I2SConfigure(void);
static void McASPI2SConfigure(void);
static void McASPTxDMAComplHandler(void);
static void McASPRxDMAComplHandler(void);
static void EDMA3CCComplIsr(void);
static void I2SDataTxRxActivate(void);
static void I2SDMAParamInit(void);
static void ParamTxLoopJobSet(unsigned short parId);
static void BufferTxDMAActivate(unsigned int txBuf, unsigned short numSamples,
unsigned short parToUpdate,
unsigned short linkAddr);
static void BufferRxDMAActivate(unsigned int rxBuf, unsigned short parId,
unsigned short parLink);
/****************************************************************************/
/* 全局变量 */
/****************************************************************************/
static unsigned char loopBuf[NUM_SAMPLES_LOOP_BUF * BYTES_PER_SAMPLE] = {0};
/*
** Transmit buffers. If any new buffer is to be added, define it here and
** update the NUM_BUF.
*/
static unsigned char txBuf0[AUDIO_BUF_SIZE];
static unsigned char txBuf1[AUDIO_BUF_SIZE];
static unsigned char txBuf2[AUDIO_BUF_SIZE];
/*
** Receive buffers. If any new buffer is to be added, define it here and
** update the NUM_BUF.
*/
static unsigned char rxBuf0[AUDIO_BUF_SIZE];
static unsigned char rxBuf1[AUDIO_BUF_SIZE];
static unsigned char rxBuf2[AUDIO_BUF_SIZE];
/*
** Next buffer to receive data. The data will be received in this buffer.
*/
static volatile unsigned int nxtBufToRcv = 0;
/*
** The RX buffer which filled latest.
*/
static volatile unsigned int lastFullRxBuf = 0;
/*
** The offset of the paRAM ID, from the starting of the paRAM set.
*/
static volatile unsigned short parOffRcvd = 0;
/*
** The offset of the paRAM ID sent, from starting of the paRAM set.
*/
static volatile unsigned short parOffSent = 0;
/*
** The offset of the paRAM ID to be sent next, from starting of the paRAM set.
*/
static volatile unsigned short parOffTxToSend = 0;
/*
** The transmit buffer which was sent last.
*/
static volatile unsigned int lastSentTxBuf = NUM_BUF - 1;
/* Array of receive buffer pointers */
static unsigned int const rxBufPtr[NUM_BUF] =
{
(unsigned int) rxBuf0,
(unsigned int) rxBuf1,
(unsigned int) rxBuf2
};
/* Array of transmit buffer pointers */
static unsigned int const txBufPtr[NUM_BUF] =
{
(unsigned int) txBuf0,
(unsigned int) txBuf1,
(unsigned int) txBuf2
};
/*
** Default paRAM for Transmit section. This will be transmitting from
** a loop buffer.
*/
static struct EDMA3CCPaRAMEntry const txDefaultPar =
{
(unsigned int)(EDMA3CC_OPT_DAM | (0x02 << 8u)), /* Opt field */
(unsigned int)loopBuf, /* source address */
(unsigned short)(BYTES_PER_SAMPLE), /* aCnt */
(unsigned short)(NUM_SAMPLES_LOOP_BUF), /* bCnt */
(unsigned int) SOC_MCASP_0_DATA_REGS, /* dest address */
(short) (BYTES_PER_SAMPLE), /* source bIdx */
(short)(0), /* dest bIdx */
(unsigned short)(PAR_TX_START * SIZE_PARAMSET), /* link address */
(unsigned short)(0), /* bCnt reload value */
(short)(0), /* source cIdx */
(short)(0), /* dest cIdx */
(unsigned short)1 /* cCnt */
};
/*
** Default paRAM for Receive section.
*/
static struct EDMA3CCPaRAMEntry const rxDefaultPar =
{
(unsigned int)(EDMA3CC_OPT_SAM | (0x02 << 8u)), /* Opt field */
(unsigned int)SOC_MCASP_0_DATA_REGS, /* source address */
(unsigned short)(BYTES_PER_SAMPLE), /* aCnt */
(unsigned short)(1), /* bCnt */
(unsigned int)rxBuf0, /* dest address */
(short) (0), /* source bIdx */
(short)(BYTES_PER_SAMPLE), /* dest bIdx */
(unsigned short)(PAR_RX_START * SIZE_PARAMSET), /* link address */
(unsigned short)(0), /* bCnt reload value */
(short)(0), /* source cIdx */
(short)(0), /* dest cIdx */
(unsigned short)1 /* cCnt */
};
/****************************************************************************/
/* 函数声明 */
/****************************************************************************/
static void ParamTxLoopJobSet(unsigned short parId);
static void I2SDMAParamInit(void);
static void AIC31I2SConfigure(void);
static void McASPI2SConfigure(void);
static void EDMA3IntSetup(void);
static void McASPErrorIntSetup(void);
static void I2SDataTxRxActivate(void);
void BufferTxDMAActivate(unsigned int txBuf, unsigned short numSamples,
unsigned short parId, unsigned short linkPar);
static void BufferRxDMAActivate(unsigned int rxBuf, unsigned short parId,
unsigned short parLink);
static void McASPRxDMAComplHandler(void);
static void McASPTxDMAComplHandler(void);
static void EDMA3CCComplIsr(void);
static void McASPErrorIsr(void);
/****************************************************************************/
/* 主函数 */
/****************************************************************************/
int main(void)
{
unsigned short parToSend;
unsigned short parToLink;
UARTStdioInit();
UARTPuts("\r\n ============Test Start===========.\r\n", -1);
UARTPuts("Welcome to StarterWare Audio_MIC_In Demo application.\r\n\r\n", -1);
UARTPuts("This application loops back the input at MIC_IN of the EVM to the LINE_OUT of the EVM\r\n\r\n", -1);
/* Set up pin mux for I2C module 0 */
I2CPinMuxSetup(0);
McASPPinMuxSetup();
/* Power up the McASP module */
PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_MCASP0, PSC_POWERDOMAIN_ALWAYS_ON,
PSC_MDCTL_NEXT_ENABLE);
/* Power up EDMA3CC_0 and EDMA3TC_0 */
PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_CC0, PSC_POWERDOMAIN_ALWAYS_ON,
PSC_MDCTL_NEXT_ENABLE);
PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_TC0, PSC_POWERDOMAIN_ALWAYS_ON,
PSC_MDCTL_NEXT_ENABLE);
#ifdef _TMS320C6X
// Initialize the DSP interrupt controller
IntDSPINTCInit();
#else
/* Initialize the ARM Interrupt Controller.*/
IntAINTCInit();
#endif
/* Initialize the I2C 0 interface for the codec AIC31 */
I2CCodecIfInit(SOC_I2C_0_REGS, INT_CHANNEL_I2C, I2C_SLAVE_CODEC_AIC31);
EDMA3Init(SOC_EDMA30CC_0_REGS, 0);
EDMA3IntSetup();
McASPErrorIntSetup();
#ifdef _TMS320C6X
IntGlobalEnable();
#else
/* Enable the interrupts generation at global level */
IntMasterIRQEnable();
IntGlobalEnable();
IntIRQEnable();
#endif
/*
** Request EDMA channels. Channel 0 is used for reception and
** Channel 1 is used for transmission
*/
EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, EDMA3_CHANNEL_TYPE_DMA,
EDMA3_CHA_MCASP0_TX, EDMA3_CHA_MCASP0_TX, 0);
EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, EDMA3_CHANNEL_TYPE_DMA,
EDMA3_CHA_MCASP0_RX, EDMA3_CHA_MCASP0_RX, 0);
/* Initialize the DMA parameters */
I2SDMAParamInit();
/* Configure the Codec for I2S mode */
AIC31I2SConfigure();
/* Configure the McASP for I2S */
McASPI2SConfigure();
/* Activate the audio transmission and reception */
I2SDataTxRxActivate();
/*
** Looop forever. if a new buffer is received, the lastFullRxBuf will be
** updated in the rx completion ISR. if it is not the lastSentTxBuf,
** buffer is to be sent. This has to be mapped to proper paRAM set.
*/
while(1)
{
if(lastFullRxBuf != lastSentTxBuf)
{
/*
** Start the transmission from the link paramset. The param set
** 1 will be linked to param set at PAR_TX_START. So do not
** update paRAM set1.
*/
parToSend = PAR_TX_START + (parOffTxToSend % NUM_PAR);
parOffTxToSend = (parOffTxToSend + 1) % NUM_PAR;
parToLink = PAR_TX_START + parOffTxToSend;
lastSentTxBuf = (lastSentTxBuf + 1) % NUM_BUF;
/* Copy the buffer */
memcpy((void *)txBufPtr[lastSentTxBuf],
(void *)rxBufPtr[lastFullRxBuf],
AUDIO_BUF_SIZE);
/*
** Send the buffer by setting the DMA params accordingly.
** Here the buffer to send and number of samples are passed as
** parameters. This is important, if only transmit section
** is to be used.
*/
BufferTxDMAActivate(lastSentTxBuf, NUM_SAMPLES_PER_AUDIO_BUF,
(unsigned short)parToSend,
(unsigned short)parToLink);
}
}
}
/*
** Assigns loop job for a parameter set
*/
static void ParamTxLoopJobSet(unsigned short parId)
{
EDMA3CCPaRAMEntry paramSet;
memcpy(¶mSet, &txDefaultPar, SIZE_PARAMSET - 2);
/* link the paRAM to itself */
paramSet.linkAddr = parId * SIZE_PARAMSET;
EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, parId, ¶mSet);
}
/*
** Initializes the DMA parameters.
** The RX basic paRAM set(channel) is 0 and TX basic paRAM set (channel) is 1.
**
** The RX paRAM set 0 will be initialized to receive data in the rx buffer 0.
** The transfer completion interrupt will not be enabled for paRAM set 0;
** paRAM set 0 will be linked to linked paRAM set starting (PAR_RX_START) of RX.
** and further reception only happens via linked paRAM set.
** For example, if the PAR_RX_START value is 40, and the number of paRAMS is 2,
** reception paRAM set linking will be initialized as 0-->40-->41-->40
**
** The TX paRAM sets will be initialized to transmit from the loop buffer.
** The size of the loop buffer can be configured.
** The transfer completion interrupt will not be enabled for paRAM set 1;
** paRAM set 1 will be linked to linked paRAM set starting (PAR_TX_START) of TX.
** All other paRAM sets will be linked to itself.
** and further transmission only happens via linked paRAM set.
** For example, if the PAR_RX_START value is 42, and the number of paRAMS is 2,
** So transmission paRAM set linking will be initialized as 1-->42-->42, 43->43.
*/
static void I2SDMAParamInit(void)
{
EDMA3CCPaRAMEntry paramSet;
int idx;
/* Initialize the 0th paRAM set for receive */
memcpy(¶mSet, &rxDefaultPar, SIZE_PARAMSET - 2);
EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_RX, ¶mSet);
/* further paramsets, enable interrupt */
paramSet.opt |= RX_DMA_INT_ENABLE;
for(idx = 0 ; idx < NUM_PAR; idx++)
{
paramSet.destAddr = rxBufPtr[idx];
paramSet.linkAddr = (PAR_RX_START + ((idx + 1) % NUM_PAR))
* (SIZE_PARAMSET);
paramSet.bCnt = NUM_SAMPLES_PER_AUDIO_BUF;
/*
** for the first linked paRAM set, start receiving the second
** sample only since the first sample is already received in
** rx buffer 0 itself.
*/
if( 0 == idx)
{
paramSet.destAddr += BYTES_PER_SAMPLE;
paramSet.bCnt -= BYTES_PER_SAMPLE;
}
EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, (PAR_RX_START + idx), ¶mSet);
}
/* Initialize the required variables for reception */
nxtBufToRcv = idx % NUM_BUF;
lastFullRxBuf = NUM_BUF - 1;
parOffRcvd = 0;
/* Initialize the 1st paRAM set for transmit */
memcpy(¶mSet, &txDefaultPar, SIZE_PARAMSET);
EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_TX, ¶mSet);
/* rest of the params, enable loop job */
for(idx = 0 ; idx < NUM_PAR; idx++)
{
ParamTxLoopJobSet(PAR_TX_START + idx);
}
/* Initialize the variables for transmit */
parOffSent = 0;
lastSentTxBuf = NUM_BUF - 1;
}
/*
** Function to configure the codec for I2S mode
*/
static void AIC31I2SConfigure(void)
{
volatile unsigned int delay = 0xFFF;
AIC31Reset(SOC_I2C_0_REGS);
while(delay--);
/* Configure the data format and sampling rate */
AIC31DataConfig(SOC_I2C_0_REGS, AIC31_DATATYPE_I2S, SLOT_SIZE, 0);
AIC31SampleRateConfig(SOC_I2C_0_REGS, AIC31_MODE_BOTH, SAMPLING_RATE);
/* Initialize both ADC and DAC */
AIC31ADCInit(SOC_I2C_0_REGS);
AIC31DACInit(SOC_I2C_0_REGS);
}
/*
** Configures the McASP Transmit Section in I2S mode.
*/
static void McASPI2SConfigure(void)
{
McASPRxReset(SOC_MCASP_0_CTRL_REGS);
McASPTxReset(SOC_MCASP_0_CTRL_REGS);
/* Enable the FIFOs for DMA transfer */
McASPReadFifoEnable(SOC_MCASP_0_FIFO_REGS, 1, 1);
McASPWriteFifoEnable(SOC_MCASP_0_FIFO_REGS, 1, 1);
/* Set I2S format in the transmitter/receiver format units */
McASPRxFmtI2SSet(SOC_MCASP_0_CTRL_REGS, WORD_SIZE, SLOT_SIZE,
MCASP_RX_MODE_DMA);
McASPTxFmtI2SSet(SOC_MCASP_0_CTRL_REGS, WORD_SIZE, SLOT_SIZE,
MCASP_TX_MODE_DMA);
/* Configure the frame sync. I2S shall work in TDM format with 2 slots */
McASPRxFrameSyncCfg(SOC_MCASP_0_CTRL_REGS, 2, MCASP_RX_FS_WIDTH_WORD,
MCASP_RX_FS_EXT_BEGIN_ON_FALL_EDGE);
McASPTxFrameSyncCfg(SOC_MCASP_0_CTRL_REGS, 2, MCASP_TX_FS_WIDTH_WORD,
MCASP_TX_FS_EXT_BEGIN_ON_RIS_EDGE);
/* configure the clock for receiver */
McASPRxClkCfg(SOC_MCASP_0_CTRL_REGS, MCASP_RX_CLK_EXTERNAL, 0, 0);
McASPRxClkPolaritySet(SOC_MCASP_0_CTRL_REGS, MCASP_RX_CLK_POL_RIS_EDGE);
McASPRxClkCheckConfig(SOC_MCASP_0_CTRL_REGS, MCASP_RX_CLKCHCK_DIV32,
0x00, 0xFF);
/* configure the clock for transmitter */
McASPTxClkCfg(SOC_MCASP_0_CTRL_REGS, MCASP_TX_CLK_EXTERNAL, 0, 0);
McASPTxClkPolaritySet(SOC_MCASP_0_CTRL_REGS, MCASP_TX_CLK_POL_FALL_EDGE);
McASPTxClkCheckConfig(SOC_MCASP_0_CTRL_REGS, MCASP_TX_CLKCHCK_DIV32,
0x00, 0xFF);
/* Enable synchronization of RX and TX sections */
McASPTxRxClkSyncEnable(SOC_MCASP_0_CTRL_REGS);
/* Enable the transmitter/receiver slots. I2S uses 2 slots */
McASPRxTimeSlotSet(SOC_MCASP_0_CTRL_REGS, I2S_SLOTS);
McASPTxTimeSlotSet(SOC_MCASP_0_CTRL_REGS, I2S_SLOTS);
/*
** Set the serializers, Currently only one serializer is set as
** transmitter and one serializer as receiver.
*/
McASPSerializerRxSet(SOC_MCASP_0_CTRL_REGS, MCASP_XSER_RX);
McASPSerializerTxSet(SOC_MCASP_0_CTRL_REGS, MCASP_XSER_TX);
/*
** Configure the McASP pins
** Input - Frame Sync, Clock and Serializer Rx
** Output - Serializer Tx is connected to the input of the codec
*/
McASPPinMcASPSet(SOC_MCASP_0_CTRL_REGS, 0xFFFFFFFF);
McASPPinDirOutputSet(SOC_MCASP_0_CTRL_REGS,MCASP_PIN_AXR(MCASP_XSER_TX));
McASPPinDirInputSet(SOC_MCASP_0_CTRL_REGS, MCASP_PIN_AFSX
| MCASP_PIN_ACLKX
| MCASP_PIN_AHCLKX
| MCASP_PIN_AXR(MCASP_XSER_RX));
/* Enable error interrupts for McASP */
McASPTxIntEnable(SOC_MCASP_0_CTRL_REGS, MCASP_TX_DMAERROR
| MCASP_TX_CLKFAIL
| MCASP_TX_SYNCERROR
| MCASP_TX_UNDERRUN);
McASPRxIntEnable(SOC_MCASP_0_CTRL_REGS, MCASP_RX_DMAERROR
| MCASP_RX_CLKFAIL
| MCASP_RX_SYNCERROR
| MCASP_RX_OVERRUN);
}
/*
** Sets up the interrupts for EDMA in AINTC
*/
static void EDMA3IntSetup(void)
{
#ifdef _TMS320C6X
IntRegister(C674X_MASK_INT5, EDMA3CCComplIsr);
IntEventMap(C674X_MASK_INT5, SYS_INT_EDMA3_0_CC0_INT1);
IntEnable(C674X_MASK_INT5);
#else
IntRegister(SYS_INT_CCINT0, EDMA3CCComplIsr);
IntChannelSet(SYS_INT_CCINT0, INT_CHANNEL_EDMACC);
IntSystemEnable(SYS_INT_CCINT0);
#endif
}
/*
** Sets up the error interrupts for McASP in AINTC
*/
static void McASPErrorIntSetup(void)
{
#ifdef _TMS320C6X
IntRegister(C674X_MASK_INT6, McASPErrorIsr);
IntEventMap(C674X_MASK_INT6, SYS_INT_MCASP0_INT);
IntEnable(C674X_MASK_INT6);
#else
/* Register the error ISR for McASP */
IntRegister(SYS_INT_MCASPINT, McASPErrorIsr);
IntChannelSet(SYS_INT_MCASPINT, INT_CHANNEL_MCASP);
IntSystemEnable(SYS_INT_MCASPINT);
#endif
}
/*
** Activates the data transmission/reception
** The DMA parameters shall be ready before calling this function.
*/
static void I2SDataTxRxActivate(void)
{
/* Start the clocks */
McASPRxClkStart(SOC_MCASP_0_CTRL_REGS, MCASP_RX_CLK_EXTERNAL);
McASPTxClkStart(SOC_MCASP_0_CTRL_REGS, MCASP_TX_CLK_EXTERNAL);
/* Enable EDMA for the transfer */
EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_RX,
EDMA3_TRIG_MODE_EVENT);
EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS,
EDMA3_CHA_MCASP0_TX, EDMA3_TRIG_MODE_EVENT);
/* Activate the serializers */
McASPRxSerActivate(SOC_MCASP_0_CTRL_REGS);
McASPTxSerActivate(SOC_MCASP_0_CTRL_REGS);
/* make sure that the XDATA bit is cleared to zero */
while(McASPTxStatusGet(SOC_MCASP_0_CTRL_REGS) & MCASP_TX_STAT_DATAREADY);
/* Activate the state machines */
McASPRxEnable(SOC_MCASP_0_CTRL_REGS);
McASPTxEnable(SOC_MCASP_0_CTRL_REGS);
}
/*
** Activates the DMA transfer for a parameterset from the given buffer.
*/
void BufferTxDMAActivate(unsigned int txBuf, unsigned short numSamples,
unsigned short parId, unsigned short linkPar)
{
EDMA3CCPaRAMEntry paramSet;
/* Copy the default paramset */
memcpy(¶mSet, &txDefaultPar, SIZE_PARAMSET - 2);
/* Enable completion interrupt */
paramSet.opt |= TX_DMA_INT_ENABLE;
paramSet.srcAddr = txBufPtr[txBuf];
paramSet.linkAddr = linkPar * SIZE_PARAMSET;
paramSet.bCnt = numSamples;
EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, parId, ¶mSet);
}
/*
** Activates the DMA transfer for a parameter set from the given buffer.
*/
static void BufferRxDMAActivate(unsigned int rxBuf, unsigned short parId,
unsigned short parLink)
{
EDMA3CCPaRAMEntry paramSet;
/* Copy the default paramset */
memcpy(¶mSet, &rxDefaultPar, SIZE_PARAMSET - 2);
/* Enable completion interrupt */
paramSet.opt |= RX_DMA_INT_ENABLE;
paramSet.destAddr = rxBufPtr[rxBuf];
paramSet.bCnt = NUM_SAMPLES_PER_AUDIO_BUF;
paramSet.linkAddr = parLink * SIZE_PARAMSET ;
EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, parId, ¶mSet);
}
/*
** This function will be called once receive DMA is completed
*/
static void McASPRxDMAComplHandler(void)
{
unsigned short nxtParToUpdate;
/*
** Update lastFullRxBuf to indicate a new buffer reception
** is completed.
*/
lastFullRxBuf = (lastFullRxBuf + 1) % NUM_BUF;
nxtParToUpdate = PAR_RX_START + parOffRcvd;
parOffRcvd = (parOffRcvd + 1) % NUM_PAR;
/*
** Update the DMA parameters for the received buffer to receive
** further data in proper buffer
*/
BufferRxDMAActivate(nxtBufToRcv, nxtParToUpdate,
PAR_RX_START + parOffRcvd);
/* update the next buffer to receive data */
nxtBufToRcv = (nxtBufToRcv + 1) % NUM_BUF;
}
/*
** This function will be called once transmit DMA is completed
*/
static void McASPTxDMAComplHandler(void)
{
ParamTxLoopJobSet((unsigned short)(PAR_TX_START + parOffSent));
parOffSent = (parOffSent + 1) % NUM_PAR;
}
/*
** EDMA transfer completion ISR
*/
static void EDMA3CCComplIsr(void)
{
#ifdef _TMS320C6X
IntEventClear(SYS_INT_EDMA3_0_CC0_INT1);
#else
IntSystemStatusClear(SYS_INT_CCINT0);
#endif
/* Check if receive DMA completed */
if(EDMA3GetIntrStatus(SOC_EDMA30CC_0_REGS) & (1 << EDMA3_CHA_MCASP0_RX))
{
/* Clear the interrupt status for the 0th channel */
EDMA3ClrIntr(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_RX);
McASPRxDMAComplHandler();
}
/* Check if transmit DMA completed */
if(EDMA3GetIntrStatus(SOC_EDMA30CC_0_REGS) & (1 << EDMA3_CHA_MCASP0_TX))
{
/* Clear the interrupt status for the first channel */
EDMA3ClrIntr(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_TX);
McASPTxDMAComplHandler();
}
}
/*
** Error ISR for McASP
*/
static void McASPErrorIsr(void)
{
#ifdef _TMS320C6X
IntEventClear(SYS_INT_MCASP0_INT);
#else
IntSystemStatusClear(SYS_INT_MCASPINT);
#endif
; /* Perform any error handling here.*/
}
/***************************** End Of File ***********************************/
将以上代码和以下代码合在一起:#include "math.h"
#include "mathlib.h"
#include "dsplib.h"
#define PI 3.1415926535
#define F_TOL (1e-06)
#define Tn 1024
#define Fs 48000.0
#define N 132 // 滤波器阶数(偶数)
#define FilterCount 5
const float F1s[FilterCount] = {20.0, 400.0, 1200.0, 4000.0, 13000.0};
const float F2s[FilterCount] = {400.0, 1200.0, 4000.0, 13000.0, 20000.0};
#pragma DATA_ALIGN(FIR_In, 8);
float FIR_In[Tn];
#pragma DATA_ALIGN(FIR_Outs, 8);
float FIR_Outs[FilterCount][Tn];
#pragma DATA_ALIGN(FIR_CombinedOut, 8);
float FIR_CombinedOut[Tn];
#pragma DATA_ALIGN(Bs, 8);
float Bs[FilterCount][N];
void FIRTest(void);
void design_blackman_bandpass_fir(float *h, int n, float f1, float f2, float fs);
void blackman_window(float *w, int n);
void normalize_filter_response(float *h, int n, float f1, float f2, float fs);
int main(void) {
int i; // 声明循环变量
for (i = 0; i < FilterCount; i++) {
design_blackman_bandpass_fir(Bs[i], N, F1s[i], F2s[i], Fs);
}
FIRTest();
return 0;
}
void blackman_window(float *w, int n) {
int i; // 声明循环变量
for (i = 0; i < n; i++) {
w[i] = 0.42f - 0.5f * cosf(2.0f * PI * i / (n - 1))
+ 0.08f * cosf(4.0f * PI * i / (n - 1));
}
}
void normalize_filter_response(float *h, int n, float f1, float f2, float fs) {
float center_freq = (f1 + f2) / 2.0f;
float omega = 2.0f * PI * center_freq / fs;
float real_gain = 0.0f;
int i; // 声明循环变量
for (i = 0; i < n; i++) {
real_gain += h[i] * cosf(omega * (i - (n-1)/2.0f));
}
if (fabsf(real_gain) > F_TOL) {
for (i = 0; i < n; i++) {
h[i] /= real_gain;
}
}
}
void design_blackman_bandpass_fir(float *h, int n, float f1, float f2, float fs) {
float w[N];
float fc1 = f1 / fs;
float fc2 = f2 / fs;
int i; // 声明循环变量
blackman_window(w, n);
for (i = 0; i < n; i++) {
float m = i - (n - 1)/2.0f;
h[i] = (fabsf(m) < F_TOL) ?
2.0f * (fc2 - fc1) :
(sinf(2.0f * PI * fc2 * m) - sinf(2.0f * PI * fc1 * m)) / (PI * m);
h[i] *= w[i];
}
normalize_filter_response(h, n, f1, f2, fs);
}
void FIRTest(void) {
int i, j; // 声明循环变量
// 生成测试信号 - 每个频段一个测试频率
for (i = 0; i < Tn; i++) {
float t = (float)i / Fs;
FIR_In[i] = 5.0f * sinf(2.0f * PI * 10.0f * t) + 5.0f * sinf(2.0f * PI * 15000.0f * t)+ 5.0f * sinf(2.0f * PI * 25000.0f * t);
}
// 初始化并处理滤波器输出
for (i = 0; i < Tn; i++) {
FIR_CombinedOut[i] = 0.0f;
}
for (j = 0; j < FilterCount; j++) {
DSPF_sp_fir_r2(FIR_In, Bs[j], FIR_Outs[j], N, Tn);
// 累加各滤波器输出
for (i = 0; i < Tn; i++) {
FIR_CombinedOut[i] += FIR_Outs[j][i];
}
}
}
将测试信号去掉,合成后的代码输入就是音频输入,输出就是音频输出,滤波器来处理数据基于TMS320C6748在CCS环境中实现
最新发布