Hello,
I am developing an application for signal processing based on convolution in time domain. I am using the peripheral explorer kit with the TMS320F28335. My application receives and transmits the audio signal correctly but it DOES NOT PERFORM CONVOLUTION CORRECTLY. THE OUTPUT AUDIO SIGNAL IS NOISY AND DISTORTED EVEN IF THE CONVOLUTION KERNEL IS VERY SMALL. I am using a ping pong buffering technique, just like in one of the document examples TI offer.
At first, I thought my convolution functions were wrong but I tested them with another compiler and compared to a result simulated with Matlab. They were alright.
Then, I thought processing time could be the problem, but I checked the number of clock cycles convolution took, and it was less than the buffering time is, so that was not the problem.
I have also tried changing buffer´s size and even using more than 2 buffers.
I am also using static inline format in the functions that require fast computations.
On the other hand, simple processing like multiplying the input signal by 0.5 is working fine.
Anyway, here is a piece of the code I am using, hoping anyone can help me.
void main(void){
inv31=1.0/e231; // inv31 and e231 are variables for float to uint32 and viceversa conversion
ts=1/fs;
Zeros(signal_reverb,120); //fill the array "signal_reverb" with 120 zeros
EALLOW;
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
InitSysCtrl();
// Step 2. Initalize GPIO:
// Enable the GPIO PINS for McBSP operation.
InitMcbspGpio();
for(k2=0; k2<1024; k2++) { ping_buffer[k2] = 0xDEADDEAD; }
for(k2=0; k2<1024; k2++) { pong_buffer[k2] = 0xDEADDEAD; }
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
DINT;
// Initialize PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the DSP2833x_PieCtrl.c file.
InitPieCtrl();
EALLOW;
DINT; // Disable interrupts again (for now)
// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
// Step 4. Initialize the Peripherals
ping_buff_offset++; // Start at location 1 (32-bit r/w from loc. 1, then 0)
pong_buff_offset++; // Start at location 1 (32-bit r/w from loc. 1, then 0)
spia_init(); // Initialize
aic23_init(); // Set up AIC23
init_dma(); // Initialize the DMA before McBSP, so that DMA is ready to transfer the McBSP data
init_mcbspa(); // Initalize McBSP-A
delay_loop();
InitPieVectTable(); // default ISR's in PIE
InitAdc(); // Basic ADC setup, incl. calibration
AdcRegs.ADCTRL1.all = 0;
AdcRegs.ADCTRL1.bit.ACQ_PS = 7; // 7 = 8 x ADCCLK
AdcRegs.ADCTRL1.bit.SEQ_CASC =1; // 1=cascaded sequencer
AdcRegs.ADCTRL1.bit.CPS = 0; // divide by 1
AdcRegs.ADCTRL1.bit.CONT_RUN = 0; // single run mode
AdcRegs.ADCTRL2.all = 0;
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // 1=enable SEQ1 interrupt
AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 =1; // 1=SEQ1 start from ePWM_SOCA trigger
AdcRegs.ADCTRL2.bit.INT_MOD_SEQ1 = 0; // 0= interrupt after every end of sequence
AdcRegs.ADCTRL3.bit.ADCCLKPS = 3; // ADC clock: FCLK = HSPCLK / 2 * ADCCLKPS
// HSPCLK = 75MHz (see DSP2833x_SysCtrl.c)
// FCLK = 12.5 MHz
AdcRegs.ADCMAXCONV.all = 0x0001; // 2 conversions from Sequencer 1
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0; // Setup ADCINA0 as 1st SEQ1 conv.
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 1; // Setup ADCINA1 as 2nd SEQ1 conv.
EPwm2Regs.TBCTL.all = 0xC030; // Configure timer control register
EPwm2Regs.TBPRD = 2999; // TPPRD +1 = TPWM / (HSPCLKDIV * CLKDIV * TSYSCLK)
// = 20 µs / 6.667 ns
EPwm2Regs.ETPS.all = 0x0100; // Configure ADC start by ePWM2
EPwm2Regs.ETSEL.all = 0x0A00; // Enable SOCA to ADC
EALLOW;
DmaRegs.CH1.CONTROL.bit.RUN = 1; // Start rx on Channel 1
PieVectTable.DINTCH1 = &local_D_INTCH1_ISR;
PieVectTable.DINTCH2 = &local_D_INTCH2_ISR;
PieVectTable.ADCINT = &adc_isr;
PieVectTable.XINT2= &PB_1_isr;
GpioIntRegs.GPIOXINT2SEL.bit.GPIOSEL=0x11; //interrupcion pin 17 PB1
XIntruptRegs.XINT2CR.bit.POLARITY=1; //rising edge
XIntruptRegs.XINT2CR.bit.ENABLE = 1; //habilitar interrupcion
PieVectTable.XINT3= &PB_2_isr;
GpioIntRegs.GPIOXINT3SEL.bit.GPIOSEL=0x30; //interrupcion pin 48 PB2
XIntruptRegs.XINT3CR.bit.POLARITY=0; //falling edge
XIntruptRegs.XINT3CR.bit.ENABLE = 1; //habilitar interrupcion
PieCtrlRegs.PIECTRL.bit.ENPIE = 1; // Enable vector fetching from PIE block
PieCtrlRegs.PIEACK.all = 0xFFFF; // Enables PIE to drive a pulse into the CPU
// The interrupt can be asserted in the following interrupt lines
PieCtrlRegs.PIEIER7.bit.INTx1 = 1; // Enable INTx.1 of INT7 (DMA CH1)
PieCtrlRegs.PIEIER7.bit.INTx2 = 1; // Enable INTx.2 of INT7 (DMA CH2)
PieCtrlRegs.PIEIER1.bit.INTx6 = 1; // ADC
PieCtrlRegs.PIEIER1.bit.INTx5 = 1; // Enable INTx.5 for PB1
PieCtrlRegs.PIEIER12.bit.INTx1 = 1; // Enable INTx.1 for PB1
IER |= 0x0841; // Enable INT7 e INT 1
EINT; // Global enable of interrupts
ERTM;
EDIS;
while(1) {
} // Code loops here all the time
}
interrupt void local_D_INTCH1_ISR(void) // DMA Ch1 - McBSP-A Rx
{
int i=0;
volatile int32* buffer_ptr;
EALLOW;
if(first_interrupt==1) // No processing needs to be done (B/c interrupt occurs
{ // at beginning of DMA transfers to ping buffer - no data received yet)
first_interrupt=0; // Turn flag off and exit interrupt
}
else {
//Processing
if(DmaRegs.CH1.DST_ADDR_SHADOW == pong_buff_offset){
buffer_ptr = &ping_buffer[i];
}
else{
buffer_ptr = &pong_buffer[i];}
for(i=0;i<1024;i++){
IntroduceValue(signal_reverb, 120, *buffer_ptr * inv31); //inv31 is a variable that makes the change from int32 to float
proc=ScalarProduct(signal_reverb,reverb,120); /* "reverb" is an array which containt filter kernel coefficients: float reverb[120]=-0.001871,0.014558,-0.036099,0.076234,-0.144645,0.306967,-0.203836,0.031176,0.205971,-0.216072,-0.094820,0.005810,0.438313,-0.365561,-0.443729,1.000000,-0.447924,-0.289036,-0.076040,0.320146,0.008458,-0.272392,0.263552,0.053619,-0.418692,0.345900,-0.089618,0.074219,-0.097349,-0.129314,0.558494,-0.478845,0.099323,-0.143931,-0.025478,0.510928,-0.488743,0.138318,0.110688,-0.198126,0.017592,-0.020937,0.303042,-0.219316,0.000961,0.077650,-0.052390,-0.186102,0.164033,0.070026,0.011078,-0.089576,0.048322,-0.019847,-0.050418,-0.029683,-0.024453,0.256697,-0.101537,-0.009129,-0.101681,0.039336,0.020671,-0.111593,0.227559,-0.081903,-0.023346,-0.021141,0.032082,0.014515,-0.191666,0.158948,0.088647,-0.032522,-0.016933,-0.073106,-0.007888,0.055713,-0.075813,0.138317,0.013357,-0.092006,0.065468,-0.159921,0.185390,-0.124400,0.029958,0.114272,-0.077725,0.020679,-0.067709,0.022601,0.052976,-0.129635,0.156934,-0.017780,-0.016399,-0.053135,-0.016298,0.068743,-0.039309,-0.017181,0.102247,-0.102933,0.083282,-0.116368,0.104647,-0.037143,-0.052511,0.083584,-0.022814,0.058958,-0.115808,0.034019,0.030415,-0.031939,0.055004,-0.067622,0.098257,-0.094814};
*/
*buffer_ptr++=proc*e231; //e231 is a variable that makes the change from float to int32
}
// PieCtrlRegs.PIEACK.bit.ACK1 = 1;
// PieCtrlRegs.PIEACK.bit.ACK12 = 1;
// Once that is done, switch to the other buffer
DmaRegs.CH2.CONTROL.bit.RUN = 1; // Start tx on CH2 after CH1 has finished ping buffer
}
// When DMA first starts working on ping buffer, set the shadow registers
// to start at pong buffer next time and vice versa
if(DmaRegs.CH1.DST_ADDR_SHADOW == ping_buff_offset)
{
DmaRegs.CH1.DST_ADDR_SHADOW = pong_buff_offset;
DmaRegs.CH1.DST_BEG_ADDR_SHADOW = pong_buff_offset;
}
else
{
DmaRegs.CH1.DST_ADDR_SHADOW = ping_buff_offset;
DmaRegs.CH1.DST_BEG_ADDR_SHADOW = ping_buff_offset;
}
// To receive more interrupts from this PIE group, acknowledge this interrupt
PieCtrlRegs.PIEACK.all = PIEACK_GROUP7;
EDIS;
}
// INT7.2
interrupt void local_D_INTCH2_ISR(void) // DMA Ch2 - McBSP-A Tx
{
EALLOW;
// When DMA first starts working on ping buffer, set the shadow registers
// to start at pong buffer next time and vice versa
if(DmaRegs.CH2.SRC_ADDR_SHADOW == ping_buff_offset)
{
DmaRegs.CH2.SRC_ADDR_SHADOW = pong_buff_offset;
DmaRegs.CH2.SRC_BEG_ADDR_SHADOW = pong_buff_offset;
}
else
{
DmaRegs.CH2.SRC_ADDR_SHADOW = ping_buff_offset;
DmaRegs.CH2.SRC_BEG_ADDR_SHADOW = ping_buff_offset;
}
PieCtrlRegs.PIEACK.all = PIEACK_GROUP7; // To receive more interrupts from this PIE group, acknowledge this interrupt
EDIS;
}
That is the part of the code where the error I think might be.
The functions involved in the convolution operation are the following:
static inline void Shift(float table[], int size){
int i;
for(i=(size-1);i>=0;i--){
tabla[i]=tabla[i-1];
}
}
static inline float ScalarProduct(float signal[], float coeficientes[],int n){
float yk=0;
int i;
for (i=0;i<n;i++){
yk=yk+signal[i]*coeficientes[i];
}
return yk;
}
static inline void IntroduceValue(float signal[], int n, float valor){
Shift(signal,n);
signal[0]=valor;
}
I hope you can help me.
Kind regards,
Ignacio