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.

DSPF_sp_cfftr2_dit Function



I am trying to implement this function but am not getting expected results.

I have no experience with FFTs beyond the basics.

I am not using complex sampling techniques.  I am sampling real values for a 1024 point FFT.  I have set a 2048 block of memory to load in 1024 complex pairs, I am taking the data sampled data and storing it in the following way in an ISR:

    ls=readadc();
    FFT_BUF[SIP]=(float) ls;
    FFT_BUF[SIP+1]=0.0;
    SIP +=2;

Which is essentially setting the real part to the sample and the imaginary part to 0.

When I have sampled the 1024 points in the main loop:

        if(SIP==2048){
            DSPF_sp_cfftr2_dit(FFT_BUF,TWIDDLE,1024);   //Perform FFT
            bit_rev(FFT_BUF,1024);                                             //Bit reverse output

I execute the FFT.

The bit reversed twiddle factors were generated to an output file using the tw_r2fft.exe provided in support library dsplib\bin.  The bit_rev function is also out of the book "The function bit_rev in dsplib\support\fft can be used to bit reverse the output
array to convert it into normal order".

Here is some data out of the functions:

 

1st sampling 1st sampling 1st sampling 2nd Sampling 3rd Sampling
FFT_Buf FFT Output Bit Output Bit Output Bit
complex pairs Executed Reversal Reversal Reversal
-3038 338105 338105 -290228 218085
0 0 0 0 0
-5543 -3153 359273.7 -214004.3 254320.6
0 0 -7663.942 -19492.41 13102.34
-3736 -3034 388040.6 -256213.7 275259
0 5167 -17795.71 -24464.87 -20146.1
535 -3034 406778.7 -245672.9 272153
0 -5167 -18274.34 -39364.68 -41923.55
4777 -11423.71 406827 -249245 274799.4
0 16266.23 -20960.66 -57278.16 -56373.41
8904 -2586.288 415304.1 -255690.8 283111.3
0 -1588.226 -27263.58 -66833.44 -69459.13
12836 -2586.288 441582.8 -272289.9 269781.5
0 1588.226 -55222.3 -70711.03 -87490.95
16491 -11423.71 454954.7 -259401.6 306316.5
0 -16266.23 -81433.65 -131985.5 -68774.82
19800 -55086.15 482866.8 -246195.6 392471.3
0 37454.99 -121696.9 -29612.78 -110126.3
22698 -2473.693 454207.4 -311767.7 295269
0 -2390.008 -43609.31 -182044.6 -184659.8
25255 -2104.652 467742.1 -290084.3 305447.1
0 3152.816 -28269.77 -170482.2 -169210.4
27081 -4823.503 489846.6 -286439.6 349202.8
0 -8757.799 -18095.82 -188233.4 -206999.3
28285 -4823.503 527711.3 -336273.2 336798.9
0 8757.799 -56497.27 -226202.8 -230321.8
28948 -2104.652 572148.1 -357980.1 368848.4
0 -3152.816 -60404.96 -258956.6 -262332.1
29094 -2473.693 623642.3 -352535.8 413721.3
0 2390.008 -55796.34 -298238.6 -321133.1

Can you see anything wrong with the methodology I am using?

 

  • So what are the expected results?  It's not clear what issue you're seeing from the big glob of data.  I'd like to help, but I don't understand what issue you're having!

  • From my understanding of the FFT, the  transform will divide the sample into bins like a spectometer representing amplitudes.  I am sampling a 90Hz waveform which does have a small amount of 60Hz mixed into it. 

    As i look at the data givien, I am sorry the labeling of the data shown is not so descriptive.  There were 1024 samples, I showed the first 15 (in the 1st column this would be the acquired samples, in the rest of the columns, it would represent the first 15 bins.  The first column represents the acquired input sampling modified with the added complex number (0 for real) making up a complex pair for the input array into the FFT.  Column 2 shows the output values after the execution of the FFT on the 1st sampling run in a bit reversed order (as I read in the implementation, that the output array is in this form).  The 3rd, 4th, and 5th column are three different sampling runs of the FFT followed by the bit reversal routine.  In this data, I would expect to see the complex output pairs relating to the spectrum.  I would have expected that the real portions of these pairs (1st number of the pair) to be a relatively low values except in the two bins containing the 60hz and 90hz information.  The second number of the pair would be the imaginary part which I would expect to be basically zero.  I think that I would not expect to see any large negative numbers after performing the functions.

     

     

  • If you're just grabbing a chunk of data then you have effectively windowed your data with a rectangle.  Your resulting frequency will be convolved with a sync.  If you sample at an exact multiple of the frequency you're interested in then you will end up with data points that land at the zeros of the sync function and so it will look "clean".  That's not a typical scenario though.  I think you need to put the data through Matlab or something else to tell you if you have the correct output data.  Or run a generic C FFT that you "trust".

  • It is not necessary to interleave 0's values into FFT buffer array. Just put it as adc gets the samples, in your case

    ls=readadc();
    FFT_BUF[SIP]=ls;
    //FFT_BUF[SIP+1]=0.0;
    SIP +=1;

    if your sample data is a short type (16bits) then FFT_BUF must be the same type and then consider the q15 to float conversion

    if(SIP==2048){

        DSPF_q15tofl(FFT_BUF, FFT_BUF_float, 2048);    // <----------------------------q15 to float conversion
        DSPF_sp_cfftr2_dit(FFT_BUF_float,TWIDDLE,1024);   //Perform FFT
        bit_rev(FFT_BUF_float,1024);                                             //Bit reverse output

     

    if TWIDDLE factors and INDEX values of bit_rev are correct It should be work fine

    Finally, note that TWIDDLE factor coefficients must be bit reversed with the correct INDEX table.

        coef_FFT(TWIDDLE, 2048);             // c-code FFT coef generation
         bit_rev(TWIDDLE, 1024);                // bit-reversed

    I hope I've been of help.

  • Thank you, Gatson, for your input.  I really appreciate your time and effort.

    A couple of questions though:

    Is this an approach you have tried and confirmed?

    Gaston said:
    It is not necessary to interleave 0's values into FFT buffer array. Just put it as adc gets the samples, in your case

    How does this work?  The documentation for the function states this:

    void DSPF_sp_cfftr2_dit (float * x, float * w, short n)

    This routine performs the decimation-in-time (DIT) radix-2 FFT of the input
    array x. x has N complex floating-point numbers arranged as successive real
    and imaginary number pairs. Input array x contains N complex points (N*2 elements).
    The coefficients for the FFT are passed to the function in array w which
    contains N/2 complex numbers (N elements) as successive real and imaginary
    number pairs.

    I did not lay out the board to use complex sampling techniques.  Based on the docs I need to make complex pairs, hence I did the buffering of zeros (zero magnitude to imaginary component)  to format it to the documentation's convention.

    Regardless, I will attempt what you suggested.  Thank you again.

  • FYI, there is an app note that covers how to use an N/2 point complex FFT to implement an N point real FFT.  As I recall there is some post processing involved.

    Also, I attached some FFT code that I wrote early in 2005.  It's been a LONG time now, but I am pretty sure I put the corresponding test vector through Matlab to verify my output.  Note, I'm not using the technique in the app note here, just a straight-up complex FFT.

    Brad

    1-7-2005 FFT Experiments.zip
  • As you say, Input array must contain a (N*2) elements for a (N) FFT computation. Somehow FFT gets complex pairs of input data arranged in Real and Imaginary numbers and perform calculations in place. Note that Real has not the meaning of 'Real' word like sampled data from ADC. In this scope 'Real' is just a mathematical concept...I tell you because I got confused when I began to work on it...

    well, it is not easy to explain to me... Happily, Brad have already sent an application note that shows FFT implementation of real value sequences but this is a document with a huge mathematical content. Also I had to read it some years ago. I've checked the attached code and is similar than mine so it has to work.

    Regards,

    Gaston

  • I have been able to get the function to work using the implementation that Gaston mentioned

    "It is not necessary to interleave 0's values into FFT buffer array. Just put it as adc gets the samples"

    I had been looking into the Excel FFT function in the data analysis pack and found that I needed to do some post processing to convert the complex data into a magnitude vector.  I took 16 sets of raw ADC data and plugged it into the Excel function.  With Excel i was able to get magnitudes in the bin of interest to be within about a 10 count fluctuation between data sets (This is ideally the accuracy I need).  So I implemented the post-processing functions into the DSP application and found that I get about a 100 count fluctuation after adjusting the frequency to maximize the amplitude within the bin (touching on the coherent sampling you mentioned to eliminate spectral leakage).  I am guessing this result may be caused by Single Precision Processing??

    So, I am started to use the Double Precision function "DSPF_dp_cfftr2".  After implementation I am getting program crashes.  I have simply doubled the memory space for the variables used for the Single Precision to get them into double precision format:

    **Data Reserve FFT_BUFFERS,x=FFT Points/2 [*2 (Real, Complex)] *4(Bytes/loc) *2 (double)
                .bss    _TWIDDLE,8192,0x2000
                .global _TWIDDLE           

    **Data Reserve FFT_BUFFERS,x=FFT Points (1024)*2 (Real, Complex) *4(Bytes/loc)  *2 (double)
                 .bss     _FFT_BUF,16384,0x2000       
                .global _FFT_BUF

    **Data Reserve FFT_BINS,x=FFT Points (512)/2 (double)
                .bss _FFT_BIN,4096
                .global _FFT_BIN

    In the main application I redefined for double:

    extern double FFT_BUF[2*1024];
    extern double TWIDDLE[2*512];
    extern double FFT_BIN[512];

    I have used the function given within the DSPF_dp_cfftr2 function for generating the Twiddle factors (before I generated a table using the executable function with DSP LIB tools):

    gen_w_r2_dp(TWIDDLE,1024);

    I implement the function as so:

                DSPF_dp_cfftr2(FFT_BUF,TWIDDLE,1024);   //Perform FFT

    When emulating I can get to the function, but when I single step over it, it never comes out and somehow it writes some nonsense to the external peripheal location for the display.

    Any idea of what I may be doing wrong?

     

  • As a quick test, try disabling interrupts around the function call.  It might not actually be something that you did wrong, but something in the function itself.  If that doesn't fix it then we can take a closer look to see if you did something wrong.

  • The application currently reads the required samples, when I have filled the buffter, I am disabling the interrupts before processing anything.  The application will not be real time, so I have the luxury of not having to interrupt any functions.

    //Main loop
        while(1){                                            //Polling loop
            if(SIP==2048){                                    //Check for buffer filled
                CSR &= 0xFFFFFFFE;                            //Interrupts OFF
               
                DSPF_dp_cfftr2(FFT_BUF,TWIDDLE,1024);       //Perform FFT
                bit_rev_dp(FFT_BUF,2048);                    //Bit reverse output
                FFT_PP_dp(FFT_BUF,FFT_BIN,1024);            //Calculate complex magitudes

     

  • So did that fix it?

  • No what I displayed was the initial code, interrupts were already disabled.

  • Try out the C version of the function.

  • I have it working with the standard function.  My error.

    function call is dp_cfftr2(N, x, w, 1), I was calling dp_cfftr2(x, w, 1024).  Also, did not have include file present.  I do not know why I did not get a linking error.  Also, analyzing the TWIDDLE data, found some very high numbers, was using sin(), cos(), atan() instead of sindp(), cosdp(), atandp() as defined in fastmath. 

    Thank you for your time.  Sorry for the trouble.

  • Dan,

    I'm glad you got it worked out.  Thanks for reporting your errors.

    FYI, if you add the compiler option -pdsw225 you will get a warning for implicitly defined functions (it's in the "diagnostics" area).  Alternatively you can enable "remarks" for the compiler in that same area.  I recommend that everyone use -pdsw225 for all projects as that is the cause of many subtle errors.  When creating a new project this should be one of the default options.  I know for sure that has been implemented in CCS4 and I thought that was the case for CCS 3.3 as well (as of some service release).

    Brad

  • Thank you, the option works very well, it caught another implicit function use in an unused function.