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.

Help in Complex FFT with F28335.

Other Parts Discussed in Thread: CONTROLSUITE

Hi all,

I'm doing a project that use FFT and IFFT. 

First I try with the example from FPU library ("2833x_RFFT_ADC_RT") and the result is very good. But after that I tranfer the Rfft_f32u function to Cfft_f32u,the FFT can't work properly.

Please help me solve this problem!

I attached the result from Watch wimdow:

This is the code of my program:

 


#include "Lab.h"                                    // Main include file


#define F_PER_SAMPLE 48000.0L/(float)FFT_REAL_SIZE  //Internal sampling rate is 48kHz

//RFFT_ADC_F32_STRUCT rfft_adc;
CFFT_F32_STRUCT cfft;

float32 FFTReal_out[2*FFT_REAL_SIZE];                //Calculated FFT result
float32 FFTReal_CosSinTable[FFT_REAL_SIZE];        //Coefficient table buffer
float32 FFTReal_Magnitude[FFT_REAL_SIZE/2+1];      //Magnitude of frequency spectrum
float32 FFTReal_Mag_Monitor[FFT_REAL_SIZE/2+1];
float32 THD[30];
//--- Global Variables
float32 AdcBuf[2*ADC_BUF_LEN];                    // ADC buffer allocation

volatile Uint16 FFTStartFlag = 0;            // One frame data ready flag

Uint16 DEBUG_TOGGLE = 1;                    // Used in realtime mode investigation
Uint16 k=0;
Uint32 PwmDuty;                                // measured PWM duty cycle
Uint32 PwmPeriod;                            // measured PWM period

// Prototype statements for functions found within this file.
interrupt void adc_isr(void);

/**********************************************************************
* Function: main()
*
* Description: Main function for C2833x Real-time RFFT
**********************************************************************/
void main(void)
{
    Uint16 i;
       float32 freq;                       // Frequency of single-frequency-component signal
   
//--- CPU Initialization
    InitSysCtrl();                        // Initialize the CPU (FILE: SysCtrl.c)
    InitGpio();                            // Initialize the shared GPIO pins (FILE: Gpio.c)
    InitPieCtrl();                        // Initialize and enable the PIE (FILE: PieCtrl.c)
    InitWatchdog();                        // Initialize the Watchdog Timer (FILE: WatchDog.c)

//--- Peripheral Initialization
    InitAdc();                            // Initialize the ADC (FILE: Adc.c)
    InitEPwm();                            // Initialize the EPwm (FILE: EPwm.c)

// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
       EALLOW;  // This is needed to write to EALLOW protected register
       PieVectTable.ADCINT = &adc_isr;
       EDIS;    // This is needed to disable write to EALLOW protected registers

    cfft.InPtr = &AdcBuf[0];                    //Input buffer
    cfft.OutPtr = &FFTReal_out[0];               //Output buffer
    cfft.CoefPtr = &FFTReal_CosSinTable[0];    //Twiddle factor
    cfft.FFTSize  = FFT_REAL_SIZE;
    cfft.Stages = FFT_REAL_STAGES;            //Real FFT stages
        //Magnitude output buffer

    CFFT_f32_sincostable(&cfft);                  //Calculate twiddle factor
 
     //Clean up output buffer
    for (i=0; i < FFT_REAL_SIZE; i++)
    {
         FFTReal_out[i] = 0;
    }
  
       //Clean up magnitude buffer
    for (i=0; i < FFT_REAL_SIZE/2; i++)
    {
            FFTReal_Magnitude[i] = 0;
    } 

//--- Enable global interrupts
    asm(" CLRC INTM, DBGM");            // Enable global interrupts and realtime debug

//--- Main Loop
    while(1)                            // endless loop - wait for an interrupt
    {
        if(FFTStartFlag)                // If one frame data ready, then do FFT
        {
            CFFT_f32u(&cfft);   // This version of FFT doesn't need buffer alignment
            cfft.CurrentOutPtr = &FFTReal_Magnitude[0];   
            CFFT_f32_mag(&cfft);        // Calculate spectrum amplitude
           
              
               freq = FFTReal_Magnitude[1];
               FFTReal_Mag_Monitor[0]=FFTReal_Magnitude[0]*24.0/4095.0;
              
               for(i=1;i<FFT_REAL_SIZE/2+1;i++)
               {   FFTReal_Mag_Monitor[i]=FFTReal_Magnitude[i]*48.0/4095.0;
                   if (i<31)
                   {
                   THD[i]=FFTReal_Mag_Monitor[i]/FFTReal_Mag_Monitor[1]*100.0;
                   }
                   //Looking for the maximum valude of spectrum magnitude
                  if(FFTReal_Magnitude[i] > freq)
                  {
                     
                      freq = FFTReal_Magnitude[i];
                  }
               }
            THD[0]=FFTReal_Mag_Monitor[0]/FFTReal_Mag_Monitor[1]*100.0;
           
                  
            FFTStartFlag = 0;                   //Start collecting the next frame of data
        }
        asm(" NOP");
    }
} //end of main()

interrupt void  adc_isr(void)
{
    static float32 *AdcBufPtr = AdcBuf;                    // Pointer to ADC data buffer
    static volatile Uint16 GPIO34_count = 0;            // Counter for pin toggle

    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;                // Must acknowledge the PIE group

//--- Manage the ADC registers
    AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;                    // Reset SEQ1 to CONV00 state
    AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;                    // Clear ADC SEQ1 interrupt flag

//--- Read the ADC result
    *AdcBufPtr++ = AdcMirror.ADCRESULT0;                // Read the result
    *AdcBufPtr++=0;
    k++;
//--- Brute-force the circular buffer
    if( k==512 )
    {
        AdcBufPtr = AdcBuf;                                // Rewind the pointer to the beginning
        FFTStartFlag = 1;   
        k=0;                            // One frame data ready
    }

//--- Example: Toggle GPIO18 so we can read it with the ADC
    if(DEBUG_TOGGLE == 1)
    {
        GpioDataRegs.GPATOGGLE.bit.GPIO18 = 1;            // Toggle the pin
    }

//--- Example: Toggle GPIO34 at a 0.5 sec rate (connected to the LED on the ControlCARD).
//             (1/48000 sec/sample)*(1 samples/int)*(x interrupts/toggle) = (0.5 sec/toggle)
//             ==> x = 24000
    if(GPIO34_count++ > 24000)                            // Toggle slowly to see the LED blink
    {
        GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1;            // Toggle the pin
        GPIO34_count = 0;                                // Reset the counter
    }
   
    return;
}

BTW, I have another question about  "Graph" in CCS4.0. That is I can't make the data from ADC running online but just show the result at one time.

 

Regards,

Hoang Cuong.

 

  • Dear all,

    I also try with a constant array for the input of CFFT and it still can't work. Look like that the CFFT can't work when we have an interrupt in the program?

    How can I fix this problem?

    Regards,

    Hoang Cuong.

     

  • don't know why u use CFFT to calculate the real input data. this would cost more cycles. If u really want to use CFFT, make sure ur input buffer would have the correct data structure like input[0]=real[0], input[1]=imag[0], input[2]=real[1], input[3]=imag[1], where imag[x]=0;

    anyway, it's not a good way to do this unless u need to do I/Q detection or SSB  demodulation with 2 channel I/Q input. 

  • Dear Yu Cai,

    Thanks for your quick reply.

    I have to use CFFT with real input data  because I want to use the complex output data for the input of  IFFT.

    I have checked many times the input data buffer but it is right as you said.

    To define them problem, I have make a simple program. 

    It just has a constant  array for input of CFFT and some buffer. It work very well but when I add an interrupt to the program, the problem occur. 

    I really don't know why the CFFT can't work when we have an interrup in the program.

    Regards,

    Hoang Cuong.

     

  • I guess your problem is you didn't convert the ADC result to floating point then call the FPU CFFT library directly.

    Please notice that the example 2833x_RFFT_ADC_RT is for fixed point input (ADC_RESULT<<4) and floating point output.

    when you call CFFT function, u need to convert the ADC_RESULT to floating point since CFFT function assume your input is floating point input.

    I don't believe the problem is due to interrupt as long as the background program and ISR synchronize well. If you haven't got the correct result as suggested above, then try to play with cmd file. you don't need to write your own CFFT example code since there is one in controlSUITE (2833x_CFFT).  

    Good luck.

  • Dear Yu Cai,

    After working again with the CFFT example code (2833x_CFFT) I realize that the problem is not due to interrupt.

    In this example, the problem occur when I move the CFFT_f32 to For loop in main program. It likes that:

    Original example:

     

     

    void

     

    {.........

    main(void)

     

     

     

     

     

    cfft.CoefPtr = CFFTF32Coef;

     

    cfft.InPtr = CFFTin1Buff;

    cfft.OutPtr = CFFToutBuff;

    cfft.Stages = CFFT_STAGES;

    cfft.FFTSize = CFFT_SIZE; // FFT size

    CFFT_f32_sincostable(&cfft); // Calculate twiddle factor

    CFFT_f32(&cfft);

    CFFT_f32_mag(&cfft);

    for(;;){};}

    And after I modified:

    void main(void)

    {.........

    cfft.CoefPtr = CFFTF32Coef;

     

    cfft.InPtr = CFFTin1Buff;

    cfft.OutPtr = CFFToutBuff;

    cfft.Stages = CFFT_STAGES;

     

    cfft.FFTSize = CFFT_SIZE; // FFT size

     

    CFFT_f32_sincostable(&cfft); // Calculate twiddle factor

     

     

    for(;;){CFFT_f32(&cfft); };}

     

    The CFFT_f32 can't work when it lied in for() loop.

    Please help me explain why and how to solve it.

    Thanks very much,

    Hoang Cuong.

     

     

     

  • fft is done frame by frame and it's buffer will be updated each time when u call it. it doesn't make sense putting it into a while loop.

  • Dear Yu Cai,

    Thanks for your help.

    I also know that fft is done frame by frame and its buffer will be updated each time when I call it. So when I put the FFT into while loop I expected that the FFT will work nomally and the result will not change (because the input buffer don't be update). But the result is in the picture and the input buffer be affected by the CFFT. It's not the case with RFFT.

    I really don't know why.

    Regards,

    Hoang Cuong.

  • Dear Yu Cai,

    To clear about the result, I post in here some more picture about the CFFT before and after I put the CFFT to while loop.

    The result from the example code provided by TI:

    And after I put the CFFT into While loop, the result become:

    In the Picture 4, we can see the value of Input buffer has changed by the effect of CFFT.

    Could anyone tell me why?

    Regards,

    Hoang Cuong.

     

  • To save memory, the FFT is done by ping-pong buffer. so ur expectation that input buffer doesn't change wouldn't happen.

  • Dear Yu Cai,

    I have hear about the Ping-pong buffer and it makes the input buffer change. So with the CFFT in while loop, after I update the input it works well.

           for(;;)
           {
        Rad = 0.0f;
        for(i=0; i < (CFFT_SIZE*2); i=i+2)
            {
            CFFTin1Buff[i]   = sin(Rad) + cos(Rad*2.3567);       // Real Part
            CFFTin1Buff[i+1] = cos(Rad*8.345) + sin(Rad*5.789);  // Image Part
            CFFTin2Buff[i]   = CFFTin1Buff[i];                     // Not used in calculation
            CFFTin2Buff[i+1] = CFFTin1Buff[i+1];                 // Not used in calculation
            Rad = Rad + RadStep;
            }
         CFFT_f32(&cfft);
        };

    But my applicaion using ADC, so I saved the ADC value to one buffer (AdcBuf), and I copy it to the input buffer everywhen the ADC data frame ready. But it still can't work.

    This my code:

    void main(void)

    {....

    while(1)                            // endless loop - wait for an interrupt
        {
            if(FFTStartFlag)                // If one frame data ready, then do FFT
            {
                for (i=0; i < 2*FFT_REAL_SIZE; i++)
                {
                InputBuf[2*i]=AdcBuf[2*i];
                InputBuf[2*i+1]=AdcBuf[2*i+1];
                };
               
                CFFT_f32u(&cfft);   // This version of FFT doesn't need buffer alignment
                                  
                FFTStartFlag = 0;                   //Start collecting the next frame of data
            }
            asm(" NOP");
        }
    } //end of main()

    interrupt void  adc_isr(void)
    {
        static float32 *AdcBufPtr = AdcBuf;                    // Pointer to ADC data buffer
        static volatile Uint16 GPIO34_count = 0;            // Counter for pin toggle

        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;                // Must acknowledge the PIE group

    //--- Manage the ADC registers
        AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;                    // Reset SEQ1 to CONV00 state
        AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;                    // Clear ADC SEQ1 interrupt flag

    //--- Read the ADC result
        *AdcBufPtr++ = AdcMirror.ADCRESULT0;                // Read the result
        *AdcBufPtr++=0;
        k++;
    //--- Brute-force the circular buffer
        if( k==512 )
        {
            AdcBufPtr = AdcBuf;                                // Rewind the pointer to the beginning
            FFTStartFlag = 1;   
            k=0;                            // One frame data ready
        }

    }

    Please have a look and help me define the problem.

    It would be great if any one can give me an example code for CFFT using input from ADC.

    Thanks and regards,

    Hoang Cuong

  • Dear Yu Cai,

    Today I got the good result with CFFT. The problem is the different between input buffer of RFFT and CFFT. It makes me confuse.

    Thanks very much for your help.

    Regards,

    Hoang Cuong.

  • Hello Cuong,

    I am working on a project which involves FFT analysis.

    As per your question regarding the FFT, I am also facing similiar issues on the FFT algorithm.

    You have mentioned that RFFT_ADC algorithm is working OK, however I have some questions related to it. I hope you can help me through them.

    1. I am not able to understand what this line of code is doing - rfft_adc.Tail = & rfft.outBuf;

    2. Secondly, the function of variable  freq.  

    Sincerely,

    Jaspreet