用的创龙C6748的开发板,在mic_in的例程基础上,新增了一个中间变量 trsBufPtr,用来存储经过FFT变化的值,程序可以编译通过,但运行后,却没有声音输出,FFT和main程序如下,还请各位老师多多指教!!
main函数中绿色部分是我自己定义的变量以及FFT函数的调用!
/****************************************************************************/
FFT程序
/****************************************************************************/
#include <stdio.h> // C 语言标准输入输出函数库
#include <math.h> // C 数学函数库
#include "mathlib.h" // DSP 数学函数库
#include "dsplib.h" // DSP 函数库
#include "FFT.h"
/****************************************************************************/
/* */
/* 宏定义 */
/* */
/****************************************************************************/
// 软件断点
#define SW_BREAKPOINT asm(" SWBP 0 ");
// 快速傅里叶变换
// π 及 浮点数极小值
#define PI 3.14159
#define F_TOL (1e-06)
/****************************************************************************/
/* */
/* 全局变量 */
/* */
/****************************************************************************/
// 快速傅里叶变换测试
// 测试快速傅里叶变换点数
// 注意:TI DSP库 最大支持一次性计算 128K 个点的 FFT
#define Tn 1024
// 采样频率
#define Fs 1000.0
// 信号
float Input[2*Tn+4];
// FFT 输入信号
#pragma DATA_ALIGN(CFFT_In, 8);
float CFFT_In[2*Tn+4];
// FFT 输入信号 副本
float CFFT_InOrig[2*Tn+4];
// FFT 输出
#pragma DATA_ALIGN(CFFT_Out, 8);
float CFFT_Out[2*Tn+4];
// IFFT 输出
#pragma DATA_ALIGN(CFFT_InvOut, 8);
float CFFT_InvOut[2*Tn+4];
// 中间运算临时变量
float CTemp[2*Tn+4];
// 存储旋转因子
float Cw[2*Tn];
// 模
float Cmo[Tn+2];
// 二进制位翻转
#pragma DATA_ALIGN (brev, 8);
unsigned char brev[64]=
{
0x0, 0x20, 0x10, 0x30, 0x8, 0x28, 0x18, 0x38,
0x4, 0x24, 0x14, 0x34, 0xc, 0x2c, 0x1c, 0x3c,
0x2, 0x22, 0x12, 0x32, 0xa, 0x2a, 0x1a, 0x3a,
0x6, 0x26, 0x16, 0x36, 0xe, 0x2e, 0x1e, 0x3e,
0x1, 0x21, 0x11, 0x31, 0x9, 0x29, 0x19, 0x39,
0x5, 0x25, 0x15, 0x35, 0xd, 0x2d, 0x1d, 0x3d,
0x3, 0x23, 0x13, 0x33, 0xb, 0x2b, 0x1b, 0x3b,
0x7, 0x27, 0x17, 0x37, 0xf, 0x2f, 0x1f, 0x3f
};
/****************************************************************************/
/* */
/* 函数声明 */
/* */
/****************************************************************************/
/****************************************************************************/
/* */
/* 主函数 */
/* */
/****************************************************************************/
//int main(void)
//{
// FFT 测试
//FFTTest();
// 断点
//SW_BREAKPOINT;
//}
/****************************************************************************/
/* */
/* 快速傅里叶变换测试 */
/* */
/****************************************************************************/
// 产生旋转因子
void tw_gen(float *w, int n)
{
int i,j,k;
double x_t,y_t,theta1,theta2,theta3;
for(j=1,k=0;j<=n>>2;j=j<<2)
{
for(i=0;i<n>>2;i += j)
{
theta1=2*PI*i/n;
x_t=cos(theta1);
y_t=sin(theta1);
w[k]=(float)x_t;
w[k+1]=(float)y_t;
theta2=4*PI*i/n;
x_t=cos(theta2);
y_t=sin(theta2);
w[k+2]=(float)x_t;
w[k+3]=(float)y_t;
theta3=6*PI*i/n;
x_t=cos(theta3);
y_t=sin(theta3);
w[k+4]=(float)x_t;
w[k+5]=(float)y_t;
k+=6;
}
}
}
// 快速傅里叶变换
void FFT( unsigned int const *audioIn, unsigned int *audioOut)
{
// 产生待测试信号
unsigned int i;
// 确定快速傅里叶变换基
unsigned char rad;
if(Tn==16 || Tn==64 || Tn==256 || Tn==1024 || Tn==4096 || Tn==16384 || Tn==65536)
rad=4;
else if(Tn==8 || Tn==32 || Tn==128 || Tn==512 || Tn==2048 || Tn==8192 || Tn==32768)
rad=2;
else
{
printf ("不支持 计算 %d 点快速傅里叶变换!\n",Tn);
return;
}
// 复数 FFT
for (i=0;i<2*Tn;i++)
CFFT_In[i]=0.0;
for (i=0;i<Tn;i++)
{
CFFT_In[2*i]=(float)audioIn[i]; // 实部
CFFT_In[2*i+1]=0; // 虚部为 0
}
// 保留一份输入信号副本
memcpy(CFFT_InOrig,CFFT_In,2*Tn*sizeof(float));
// 产生旋转因子
tw_gen(Cw,Tn);
// FFT 计算
DSPF_sp_fftSPxSP(Tn,CFFT_In,Cw,CFFT_Out,brev,rad,0,Tn);
for (i=0;i<Tn;i++)
{
audioOut[i]=(int)CFFT_Out[2*i];
}
// 计算振幅
for(i=0;i<Tn;i++)
Cmo[i]=0.0;
for(i=0;i<Tn+2;i++)
{
Cmo[i]=sqrtsp(CFFT_Out[2*i]*CFFT_Out[2*i]+CFFT_Out[2*i+1]*CFFT_Out[2*i+1]);
Cmo[i]=Cmo[i]*2/Tn;
}
// 保留一份 FFT 结果副本
memcpy(CTemp,CFFT_Out,2*Tn*sizeof(float));
// IFFT 计算
DSPF_sp_ifftSPxSP(Tn,CFFT_Out,Cw,CFFT_InvOut,brev,rad,0,Tn);
}
————————————————————————————————————————————————————————————————
——————————————————————————————————————————————————————————————————
——————————————————————————————————————————————————————————————————
/****************************************************************************/
/* */
/* main函数
音频测试: MIC_IN读取音频数据,从LINE_OUT播出(DMA方式) */
/* */
/* 2015年07月20日 */
/* */
/****************************************************************************/
#include "TL6748.h"
#include "edma_event.h"
#include "interrupt.h"
#include "soc_OMAPL138.h"
#include "hw_syscfg0_OMAPL138.h"
#include "codecif.h"
#include "mcasp.h"
#include "edma.h"
#include "psc.h"
#include "uartStdio.h"
#include "aic3106_init.h"
#include "mcasp_init.h"
#include <string.h>
#include "FFT.h"
/****************************************************************************/
/* */
/* 宏定义 */
/* */
/****************************************************************************/
// I2S 使用2个 slot
#define I2S_SLOTS (2u)
// 发送/接收 每个 slot 大小
#define SLOT_SIZE (16u)
// 发送/接收数据 word 大小. Word size <= Slot size
#define WORD_SIZE (16u)
// 每个音频 buffer 采样点数
#define NUM_SAMPLES_PER_AUDIO_BUF (2000u)
// 发送/接收 buffer 个数
#define NUM_BUF (3u)
// 发送/接收使用链接 DMA 参数的个数
#define NUM_PAR (2u)
// 指定链接参数器的起始 ID
#define PAR_ID_START (40u)
// loop brffer的采样点的个数
#define NUM_SAMPLES_LOOP_BUF (10u)
// AIC3106 音频芯片的 I2C 从地址
#define I2C_SLAVE_CODEC_AIC31 (0x18u)
//每个采样点的字节数
#define BYTES_PER_SAMPLE (SLOT_SIZE >> 3)
#define AUDIO_BUF_SIZE (NUM_SAMPLES_PER_AUDIO_BUF \
* BYTES_PER_SAMPLE * I2S_SLOTS)
#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)
// 一个 paRAM 的大小
#define SIZE_PARAMSET (32u)
#define OPT_FIFO_WIDTH (0x02 << 8u)
/****************************************************************************/
/* 全局变量 */
/****************************************************************************/
// 当接收通道还没有接收到数据时,发送通道会发送这个 buf 的数据
static unsigned char loopBuf[NUM_SAMPLES_LOOP_BUF * BYTES_PER_SAMPLE] = {0};
// 发送 buffer,如果要添加新的 buffer 需要更新 NUM_BUF 宏的值
static unsigned char txBuf0[AUDIO_BUF_SIZE];
static unsigned char txBuf1[AUDIO_BUF_SIZE];
static unsigned char txBuf2[AUDIO_BUF_SIZE];
// 接收 buffer,如果要添加新的 buffer 需要更新 NUM_BUF 宏的值
static unsigned char rxBuf0[AUDIO_BUF_SIZE];
static unsigned char rxBuf1[AUDIO_BUF_SIZE];
static unsigned char rxBuf2[AUDIO_BUF_SIZE];
//// 接收 buffer,如果要添加新的 buffer 需要更新 NUM_BUF 宏的值
static unsigned char trsBuf0[AUDIO_BUF_SIZE];
static unsigned char trsBuf1[AUDIO_BUF_SIZE];
static unsigned char trsBuf2[AUDIO_BUF_SIZE];
// 下一个将要接收数据的 buffer
static volatile unsigned int nxtBufToRcv = 0;
// 最近收满数据的 buffer
static volatile unsigned int lastFullRxBuf = 0;
// paRAM ID 相对起始 paRAM 的偏移个数
static volatile unsigned short parOffRcvd = 0;
// paRAM ID 相对起始 paRAM 的偏移个数
static volatile unsigned short parOffSent = 0;
// 下一个将要发送的 paRAM ID 相对起始 paRAM 的偏移个数
static volatile unsigned short parOffTxToSend = 0;
// 上一次发送的 buffer
static volatile unsigned int lastSentTxBuf = NUM_BUF - 1;
// 接收 buffer 指针数组
static unsigned int const rxBufPtr[NUM_BUF] =
{
(unsigned int) rxBuf0,
(unsigned int) rxBuf1,
(unsigned int) rxBuf2
};
// 发送 buffer 指针数组
static unsigned int const txBufPtr[NUM_BUF] =
{
(unsigned int) txBuf0,
(unsigned int) txBuf1,
(unsigned int) txBuf2
};
// 对DSP接收到的buffer指针数组进行FFT变换,存储到中间指针数组
static unsigned int trsBufPtr[NUM_BUF] =
{
(unsigned int) trsBuf0,
(unsigned int) trsBuf1,
(unsigned int) trsBuf2
};
// 发送部分默认 paRAM 参数,这个参数将发送 loop buffer 的数据0
static struct EDMA3CCPaRAMEntry const txDefaultPar =
{
(unsigned int)(EDMA3CC_OPT_DAM | OPT_FIFO_WIDTH), // Opt
(unsigned int)loopBuf, // 源地址
(unsigned short)(BYTES_PER_SAMPLE), // aCnt
(unsigned short)(NUM_SAMPLES_LOOP_BUF), // bCnt
(unsigned int) SOC_MCASP_0_DATA_REGS, // 目标地址
(short) (BYTES_PER_SAMPLE), // 源 bIdx
(short)(0), // 目标 bIdx
(unsigned short)(PAR_TX_START * SIZE_PARAMSET), // 链接地址
(unsigned short)(0), // bCnt 重装值
(short)(0), // 源 cIdx
(short)(0), // 目标 cIdx
(unsigned short)1 // cCnt
};
// 发送部分默认 paRAM 参数
static struct EDMA3CCPaRAMEntry const rxDefaultPar =
{
(unsigned int)(EDMA3CC_OPT_SAM | OPT_FIFO_WIDTH), // Opt 设置源地址为FIFO模式,FIFO的大小为32-bit
(unsigned int)SOC_MCASP_0_DATA_REGS, // 源地址 MCASP 通过DMA访问的数据寄存器地址
(unsigned short)(BYTES_PER_SAMPLE), // aCnt 每个sample占用2个字节
(unsigned short)(1), // bCnt 一行有1个元素
(unsigned int)rxBuf0, // 目标地址
(short) (0), // 源 bIdx
(short)(BYTES_PER_SAMPLE), // 目标 bIdx 目标索引2个字节
(unsigned short)(PAR_RX_START * SIZE_PARAMSET), // 链接地址 到第40个 paRAM
(unsigned short)(0), // bCnt 重装值
(short)(0), // 源 cIdx
(short)(0), // 目标 cIdx
(unsigned short)1 // cCnt
};
/****************************************************************************/
/* */
/* 函数声明 */
/* */
/****************************************************************************/
static void ParamTxLoopJobSet(unsigned short parId);
static void I2SDMAParamInit(void);
static void InitAIC31I2S(void);
static void EDMA3IntSetup(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);
// DSP 中断初始化
static void InterruptInit(void);
static void InitMcaspEdma(void);
/****************************************************************************/
/* 主函数 */
/****************************************************************************/
int main(void)
{
unsigned short parToSend;
unsigned short parToLink;
//unsigned int i;
// 串口终端初始化 使用串口2
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);
// I2C 模块引脚配置
I2CPinMuxSetup(0);
// McASP 引脚配置
McASPPinMuxSetup();
// 使能 EDMA3 PSC
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);
// DSP 中断初始化
InterruptInit();
// 初始化 I2C 接口地址为 AIC31 的地址
I2CSetup(SOC_I2C_0_REGS, I2C_SLAVE_CODEC_AIC31);
I2CIntRegister(C674X_MASK_INT7, SYS_INT_I2C0_INT);
// 初始化 AIC31 音频芯片
InitAIC31I2S();
// 初始化 McASP 为 EDMA 方式
InitMcaspEdma();
// 主循环,当一个新的 buffer 接收完成后,lastFullRxBuf 将会在接收完成中断
// 里更新。如果 lastFullRxBuf 与 lastSentTxBuf 不相等就会发送新的数据。
while(1)
{
if(lastFullRxBuf != lastSentTxBuf)
{
// 标志将要设置的下一个要传输数据的链接 DAM 参数
parToSend = PAR_TX_START + (parOffTxToSend % NUM_PAR);
parOffTxToSend = (parOffTxToSend + 1) % NUM_PAR;
parToLink = PAR_TX_START + parOffTxToSend;
lastSentTxBuf = (lastSentTxBuf + 1) % NUM_BUF;
FFT(rxBufPtr,trsBufPtr);
// 复制 buffer
//memcpy((void *)trsBufPtr[lastFullRxBuf],
// (void *)rxBufPtr[lastFullRxBuf],
// AUDIO_BUF_SIZE);
// 复制 buffer
memcpy((void *)txBufPtr[lastSentTxBuf],
(void *)trsBufPtr[lastFullRxBuf],
AUDIO_BUF_SIZE);
// 设置相应的 DMA 参数用于发送数据
BufferTxDMAActivate(lastSentTxBuf, NUM_SAMPLES_PER_AUDIO_BUF,
(unsigned short)parToSend,
(unsigned short)parToLink);
}
}
}
/****************************************************************************/
/* */
/* 初始化 McASP 为 EDMA 方式 */
/* */
/****************************************************************************/
static void InitMcaspEdma(void)
{
EDMA3Init(SOC_EDMA30CC_0_REGS, 0);
EDMA3IntSetup();
// 申请 EDMA 通道,通道 0 用于接收,通道 1 用于发送
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);
// 初始化 DMA 参数
I2SDMAParamInit();
// 初始化 McASP 为 I2S 模式
McASPI2SConfigure(MCASP_BOTH_MODE, WORD_SIZE, SLOT_SIZE, I2S_SLOTS, MCASP_MODE_DMA);
// 使能 EDMA 传输
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);
// 启动 McASP 发送和接收
I2SDataTxRxActivate(MCASP_BOTH_MODE);
}
/****************************************************************************/
/* */
/* DSP 中断初始化 */
/* */
/****************************************************************************/
static void InterruptInit(void)
{
// 初始化 DSP 中断控制器
IntDSPINTCInit();
// 使能 DSP 全局中断
IntGlobalEnable();
}
/****************************************************************************/
/* */
/* 设置 EDMA 循环工作参数 */
/* */
/****************************************************************************/
static void ParamTxLoopJobSet(unsigned short parId)
{
EDMA3CCPaRAMEntry paramSet;
memcpy(¶mSet, &txDefaultPar, SIZE_PARAMSET - 2);
// 要链接的下一个 EDMA paRAM 参数通道
paramSet.linkAddr = parId * SIZE_PARAMSET;
EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, parId, ¶mSet);
}
/****************************************************************************/
/* */
/* 初始化 DMA 参数 */
/* */
/****************************************************************************/
// 接收的基本 paRAM 为通道0,发送的基本 paRAM 为通道1
//
// 接收 paRAM 0 将会初始化为接收数据到 rxBuf0,第一次初始化时只接收1个采样点。
// paRAM 0 没有使能传输完成中断,paRAM 0 传输完成后直接链接 paRAM 40 (PAR_RX_START)
// 链接 paRAM 参数后会继续下一个传输。
// 例如:PAR_RX_START = 40, 使用两个 paRAM = 2,则接收部分的 paRAM 链接将会
// 被初始为 0-->40-->41-->40
//
// 发送 paRAM 将会初始化为发送 loop buffer 的数据,这个数据的值为0(由于刚开始
// 还没收到数据,因此发送0数据)
// paRAM 1 将会链接 paRAM 42(PAR_TX_START),所以其他的 paRAM 参数将会链接到
// 自己,使发送数据的 EDMA 传输不会被中断传输。
// 例如:PAR_TX_START = 42, 使用两个 paRAM = 2,则接收部分的 paRAM 链接将会
// 被初始为 1-->42-->42, 43->43.
//
// 当接收buffer (rxBuf0)接收到数据时,将会在主循环里设置发送部分为pingpong
// 模式,其工作模式为 42-->43-->42-->43.......
static void I2SDMAParamInit(void)
{
EDMA3CCPaRAMEntry paramSet;
int idx;
// 初始化第0通道的 paRAM 用于接收,这个通道只设置接收一个采样点,
// 接收完成后不产生中断,直接链接到 PAR_RX_START 通道
memcpy(¶mSet, &rxDefaultPar, SIZE_PARAMSET - 2);
EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_RX, ¶mSet);
// 初始化两个通道的 paRAM 参数,pingpong传输,这两个通道使能了中断
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;
// 第一次传输时,由于通道0已经接收了一个采样点的数据存储在buffer0
// 里,因此这次接收从第二个采样点开始接收,数据存储于 buffer0
if( 0 == idx)
{
paramSet.destAddr += BYTES_PER_SAMPLE;
paramSet.bCnt -= 1;
}
EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, (PAR_RX_START + idx), ¶mSet);
}
// 初始化接收部分需要的参数
nxtBufToRcv = idx % NUM_BUF;
lastFullRxBuf = NUM_BUF - 1;
parOffRcvd = 0;
// 初始化第一通道的 paRAM 用于发送
memcpy(¶mSet, &txDefaultPar, SIZE_PARAMSET);
EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_TX, ¶mSet);
// 使能 EDMA 循环工作
for(idx = 0 ; idx < NUM_PAR; idx++)
{
ParamTxLoopJobSet(PAR_TX_START + idx);
}
// 初始化发送需要的参数
parOffSent = 0;
lastSentTxBuf = NUM_BUF - 1;
}
/****************************************************************************/
/* */
/* 初始化 AIC31 音频芯片 */
/* */
/****************************************************************************/
static void InitAIC31I2S(void)
{
volatile unsigned int delay = 0xFFF;
// 复位
AIC31Reset(SOC_I2C_0_REGS);
while(delay--);
// 初始化 AIC31 为 I2S 模式
AIC31DataConfig(SOC_I2C_0_REGS, AIC31_DATATYPE_I2S, SLOT_SIZE, 0);
// 初始化采样率为 48000Hz
AIC31SampleRateConfig(SOC_I2C_0_REGS, AIC31_MODE_BOTH, FS_48000_HZ);
// 初始化 ADC 0分贝增益,连接 MIC IN
AIC31ADCInit(SOC_I2C_0_REGS, ADC_GAIN_0DB, AIC31_MIC_IN);
// 初始化 DAC 0分贝衰减
AIC31DACInit(SOC_I2C_0_REGS, DAC_ATTEN_0DB);
}
/****************************************************************************/
/* */
/* 初始化 EDMA 中断 */
/* */
/****************************************************************************/
static void EDMA3IntSetup(void)
{
IntRegister(C674X_MASK_INT5, EDMA3CCComplIsr);
IntEventMap(C674X_MASK_INT5, SYS_INT_EDMA3_0_CC0_INT1);
IntEnable(C674X_MASK_INT5);
}
/****************************************************************************/
/* */
/* 激活 DMA 传输器的一个参数,用于发送给定的buffer */
/* */
/****************************************************************************/
void BufferTxDMAActivate(unsigned int txBuf, unsigned short numSamples,
unsigned short parId, unsigned short linkPar)
{
EDMA3CCPaRAMEntry paramSet;
// 复制默认参数
memcpy(¶mSet, &txDefaultPar, SIZE_PARAMSET - 2);
// 使能传输完成中断
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);
}
/****************************************************************************/
/* */
/* 激活 DMA 传输器的一个参数,用于接收数据到给定的buffer */
/* */
/****************************************************************************/
static void BufferRxDMAActivate(unsigned int rxBuf, unsigned short parId,
unsigned short parLink)
{
EDMA3CCPaRAMEntry paramSet;
// 复制默认参数
memcpy(¶mSet, &rxDefaultPar, SIZE_PARAMSET - 2);
// 使能传输完成中断
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);
}
/****************************************************************************/
/* */
/* 此函数会在接收完成中断里调用 */
/* */
/****************************************************************************/
static void McASPRxDMAComplHandler(void)
{
unsigned short nxtParToUpdate;
// 更新 lastFullRxBuf 标志一个新的接收 buffer 接收完成
lastFullRxBuf = (lastFullRxBuf + 1) % NUM_BUF;
nxtParToUpdate = PAR_RX_START + parOffRcvd;
parOffRcvd = (parOffRcvd + 1) % NUM_PAR;
// 激活 DMA 传输器的一个参数集,用于接收数据到给定的buffer
BufferRxDMAActivate(nxtBufToRcv, nxtParToUpdate,
PAR_RX_START + parOffRcvd);
// 更新下一个要接收数据的buffer
nxtBufToRcv = (nxtBufToRcv + 1) % NUM_BUF;
}
/****************************************************************************/
/* */
/* 此函数会在发送完成中断里调用 */
/* */
/****************************************************************************/
static void McASPTxDMAComplHandler(void)
{
ParamTxLoopJobSet((unsigned short)(PAR_TX_START + parOffSent));
parOffSent = (parOffSent + 1) % NUM_PAR;
}
/****************************************************************************/
/* */
/* EDMA 传输完成中断服务函数 */
/* */
/****************************************************************************/
static void EDMA3CCComplIsr(void)
{
IntEventClear(SYS_INT_EDMA3_0_CC0_INT1);
// 判断接收 DMA 完成
if(EDMA3GetIntrStatus(SOC_EDMA30CC_0_REGS) & (1 << EDMA3_CHA_MCASP0_RX))
{
// 清除 0 通道中断标志
EDMA3ClrIntr(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_RX);
McASPRxDMAComplHandler();
}
}