This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28335: Convolution performance error in real time audio processing application

Part Number: TMS320F28335


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

  • Sorry Ignacio, I am unable to debug your code given the type of support we are able to offer through the forum. If you have specific questions related to the device, or software example we provide we will be happy to help .
  • Actually the code is based on the document example of yours called "Interfacing the TMS320F2833x to the AIC23B Stereo Audio Codec ". My code is compiling correctly but there is something going on that is overwriting the buffers and thus, corrupting the audio signal. When using the ping pong buffering technique, it seems that some noise appears which I am unable to filter.