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.

FFT- real-time requirement doesn't meet !

Expert 2370 points
Other Parts Discussed in Thread: ADS7881

Hi,

I am using ADS7881 to sample analog singal with frequency up tp 150 kHz and taking FFT over sampled data. I set the clock to see how much time it takes to perform FFT over 1024 points. It's taking almost 22 ms for 1024 data points that is really much from real-time point of view. I mean to say I am lossing sampled data points during the time FFT has been calculating. I am using DSPF_sp_cfftr2_dit function to compute FFT.

What other options do I have to make it faster or close to real time ?

I appreciate your quick help.

Thanks

 

 

  • My DSK board is C6713.

  • Hello, I recommend you use this function: DSPF_sp_fftSPxSP.asm
    Is the code/data in external memory? If so, is the cache and MAR bits enabled?

    What is the device MHz you are running at? 22msec seems way high
    If is real only FFT, you may want to consider: http://processors.wiki.ti.com/index.php/Efficient_FFT_Computation_of_Real_Input


    Regards,
    Gagan

  • Hi Gagan.

    Thanks for your reply.

    Code is in IRAM and FFT result is saving in External Memory. I don't know how to check cache and MAR bits enabled, I really have no idea how to do it?

    I am using IRAM and SDRAM to save FFT result .

    I think device is running at 225 MHz. However, I am using Timer1 at 56.25 MHz as the CONVST input to the ADS7881 but that shouldn't affect device clock. right ?

    I set the clock and put break point just after calculating FFT magnitude and calculated the time using the equation given below.

    (1/225 MHz)*clock cycle = Time taken for 1024 point FFT.

    I will check DSPF_sp_fftSPxSP.asm and let you know.

    Thanks.

  • Hi Gagan,

    I have enabled L2 Mode 4-way cache by checking 671x- Configure L2 Memory Settings box and initialized MAR bits by 0xFFF. Is that ok ?

    In the General tab of Global Setting, DSP Speed in MHz (CLKOUT) = 50.0000. Does it mean my device is running at 50 MHz ? How can I check device MHz running at ? I haven't worked much with C6713 so I really don't know about it.

    I looked over DSPF_sp_fftSPxSP function but coudn't figure out how to make it work. Can you provide me working example code for this OR tell me how to implement this ?

    I appreciate your help.

    Thanks.

  • One more thing is that I am using C6713 DSK not C674x.

     


  • Will any body please reply me ? I am still waiting...

  • ➢ I have enabled L2 Mode 4-way cache by checking 671x- Configure L2 Memory Settings box and initialized MAR bits by 0xFFF. Is that ok ?

    There are various MAR bits and you need to set the once that correspond to the right memory range

    ➢ In the General tab of Global Setting, DSP Speed in MHz (CLKOUT) = 50.0000. Does it mean my device is running at 50 MHz ?

    No. Device MHz is not decided by the above setting.

    The device MHz are generally set by the GEL file that is part of your CCS. The file generally sets device PLL registers that set the device speed

    ➢  How can I check device MHz running at ? I haven't worked much with C6713 so I really don't know about it.

    There are multiple ways to do that. Look at the CLKOUT signal, look at the PLL settings, or simply run a large while loop and measure the CPU clocks taken, then compare with wall clock time to see if it matches.

    ➢ I looked over DSPF_sp_fftSPxSP function but coudn't figure out how to make it work. Can you provide me working example code for this OR tell me how to implement this 

    What part is not clear? The DSPLIB comes with example showing how the fft is called:

    \c674x-dsplib_1_03_00_01\src\DSPF_sp_fftSPxSP

     

    Gagan

     

     

     

  • Hi,

    I followed the example but getting so much errors some thing like given below.

    DSPF_sp_fftSPxSP.asm", ERROR!   at line 217: [E0800] Instruction invalid for C6700

    Build Complete,
      292 Errors, 0 Warnings, 19 Remarks.

    Is it not valid for C6713 ?

    This is how I am calling this function.

    #include <stdio.h>
    #include <math.h>
    #include "dsplib674x.h"
    void DSPF_sp_fftSPxSP (int, float *, float *, float *, unsigned char *, int, int, int);
    void FFT_Split (int n, float *pIn, float *A, float *B, float *pOut);
    void Real_FFT ();

    //we can generate twidle factors using tw_gen();
    float w[2 * N];
    float A[N];
    float B[N];

    #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 fltcmp (const float *y1, const float *y2, int n, float tol)
    {
        int i;
        int flag = 0;

        for (i = 0; i < n; i++)
        {
            if (abs (y1[i] - y2[i]) > tol)
                flag = 1;
        }
        return flag;

    }

    void main ()
    {
        int i;

        // Generate real input sequence of length N
        for (i = 0; i < N; i++)
        {
            pInput[i] = sin (2 * 3.1415 * 500 * (i) / (double) N);
        }

        // Compute FFT and IFFT using Complex FFT of length N/2..
        Real_FFT ();

    }

    void Real_FFT ()
    {
        int i, rad, nTemp = N / 2;
        float *twiddle;
        int start, stop, overhead;

        if (nTemp == 16 || nTemp == 64 || nTemp == 256 || nTemp == 1024 || nTemp == 4096 || nTemp == 16384)
            rad = 4;
        else if (nTemp == 8 || nTemp == 32 || nTemp == 128 || nTemp == 512 || nTemp == 2048 || nTemp == 8192)
            rad = 2;
        else
        {
            printf ("%d Value of N is not supported \n", N);
            exit (0);
        }

        start = clock();
        stop = clock();

        overhead = stop - start;       

        // Real FFT of length N/2
        for (i = 0; i < N / 2; i++)
        {
            pRFFT_In[2 * i] = pInput[2 * i];            //arrange real input sequence to
            pRFFT_In[2 * i + 1] = pInput[2 * i + 1];   //N/2 complex sequence..
        }

        memcpy (pRFFT_InOrig, pRFFT_In, N * sizeof (float));

        tw_gen (w, N / 2);
        split_gen (A, B, N / 2);
        // Once w(twiddles), A, B Tables are generated they can be saved as .const
        // and need not be generated every time..
        twiddle = (float *) w;

        start = clock();
       
        // Forward FFT Calculation using N/2 complex FFT..
        DSPF_sp_fftSPxSP (N / 2, pRFFT_In, twiddle, pTemp, brev, rad, 0, N / 2);
        // FFT Split call to get complex FFT out of length N..
        FFT_Split (N / 2, pTemp, A, B, pRFFT_Out);
       
        stop = clock();

        printf("Clocks for %d Real FFT using N/2 Complex FFT= %d\n", N, (stop-start)-overhead);

        printf ("Real FFT using complex N/2 FFT:");

        if (fltcmp (pCFFT_Out, pRFFT_Out, 2 * N, F_TOL))
            printf ("**FAIL**\n");
        else
            printf ("##PASS##\n");

        // Inverse FFT calculation

        // IFFT Split call to get complex Inv FFT out of length N..
        IFFT_Split (N / 2, pRFFT_Out, A, B, pTemp);
        // Inverse FFT Calculation using N/2 complex IFFT..
        DSPF_sp_ifftSPxSP (N / 2, pTemp, twiddle, pRFFT_InvOut, brev, rad, 0, N / 2);

        printf ("Real FFT Reconstruction using complex N/2 FFT:");

        if (fltcmp (pRFFT_InOrig, pRFFT_InvOut, N, F_TOL))
            printf ("**FAIL**\n");
        else
            printf ("##PASS##\n");

    }

    /* Function for generating Specialized sequence of twiddle factors */
    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;
            }
        }
    }

    Please suggest what should I do now ?

  • No. The C67x core is supported by lib here: http://focus.ti.com/docs/toolsw/folders/print/sprc121.html

    You can use the same example though

     

    Regards,
    Gagan

     

  • Hi Gagan,

    I tried to use DSPF_sp_fftSPxSP function, program has no error and it builds fine but when I run the project I am getting following error and the DSP disconnected. Please find below my code.

    Trouble Halting Target CPU: Error 0x80000020/-1070 Fatal Error during: Execution

    #include "csl.h"
    #include "csl_irq.h"
    #include "math.h"
    #include "DSPF_sp_fftSPxSP.h"

    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
    };

    void main(void)

    {

    for(k=0; k < N; k++) // Generating input data
       
            {
                x[2*k] = sin(2*PI*500*i/N);
                x[2*k+1] = 0.0;
            }

            tw_genSPxSPfft(w, BLOCK_SZ); // generating twiddles

            DSPF_sp_fftSPxSP(N, x, w, y, brev, 4, 0, N); // calling FFT function

    }

    void tw_genSPxSPfft(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;                                                   
             }                                                           
         }                                                               
    }

    What's wrong am I doing here ?

  • Difficult to say. If you provide a test case, I can probably look at it
    Gagan 

  • Hi Gagan,

    Find below attached my code, I am using ADC to sample analog signal and then taking FFT.


    #include "csl.h"
    #include "csl_irq.h"
    #include "math.h"
    #include "DSPF_sp_fftSPxSP.h"

    /*Declarations*/
    #define BLOCK_SZ   1024/* size of data buffer */

    /*Global variables*/
    short r_buffer[BLOCK_SZ];

    #pragma DATA_ALIGN(x, 8)
    float x[2*BLOCK_SZ]; // input to FFT


    #pragma DATA_ALIGN(y, 8)
    float y[2*BLOCK_SZ]; // FFT output


    #pragma DATA_ALIGN(w, 8)
    float w[BLOCK_SZ]; // twiddles


    #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 i=0;      
    int k=0;


    void main()
    {
        HWI_enable();
        IRQ_enable(IRQ_EVT_EXTINT5);
        TIMER_start(hTimer1);
    }

    void  ExtINT5_ISR(void)
    {
        r_buffer[i++] = (*(unsigned volatile int *)ADS7881)>>2&0x0FFF;
               
        if (i >= BLOCK_SZ )          
        {
       
        i=0;

        for(k=0; k < BLOCK_SZ; k++)
       
            {
                x[2*k] = (float)r_buffer[k]; // real part
                x[2*k+1] = 0.0; // immaginary part
            }

            tw_genSPxSPfft(w, BLOCK_SZ);

            DSPF_sp_fftSPxSP(BLOCK_SZ, x, w, y, brev, 4, 0, BLOCK_SZ); // calling FFT function

        }         
    }

    Added tw_genSPxSPfft as .c file in the project.

    tw_genSPxSPfft(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;                                                   
             }                                                           
         }                                                               
    }

    Thanks.

  • Hi Gagan,

    I made this FFT function work but I want to compute real FFT as implemented in fft_demo project which I downloaded before. I have seen the code but there are few things I want to ask.

    #define N 512

    float pCFFT_In[2 * N + 4];
    float pCFFT_InvOut[2 * N + 4];
    float pCFFT_InOrig[2 * N + 4];

    Why the size of all the variables like mentioned above have additional 4 ?

    What these two functions are doing ?

    fltcmp (const float *y1, const float *y2, int n, float tol)

    memcpy (pRFFT_InOrig, pRFFT_In, N * sizeof (float));

    N is defined as 512 but half the size of N has passed to the function DSPF_sp_fftSPxSP as length of FFT.

    DSPF_sp_fftSPxSP (N / 2, pRFFT_In, twiddle, pTemp, brev, rad, 0, N / 2);

    I am wondering what is the actual length of FFT either 512 or 256 ? because the FFT output has 512 points..

     

  • Hey..

    Will some one please reply me here ?