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.

Interpreting RFFT32 results

Other Parts Discussed in Thread: CONTROLSUITE

I implemented FFT using RFFT32 library. However, I have trouble interpreting the result. My current program is as follows (fftSize was defined as 128)

 

If I read the documentation correctly, ipcbsrc should be populated with input data, and ipcb is the result of the FFT magnitude. The ipcb in my program was populated by ADC which samples input signal from function generator (square wave @ 5kHz, 50% duty cycle) at 40kHz sampling rate.

The interesting element from ipcb are elements 29, 30, 31, 32, which have values of -130, 246, 52, and -179. The value of 246 is like the peak here, corresponds to frequency (30 + 1) / 256 * 40000 = 4843.75 Hz (very close to 5kHz, why?). But why do I get negative value?

Extra credit: why does element 0 have the highest value of 1546? (EDIT: I got the answer already. It's the DC component magnitude. Yes, no?)

Thanks

  • The 128 pt RFFT should treat the input as 64 pt complex data and run a 64-CFFT on it resulting in complex output, which, if plotted will show some negative values.

    I believe there is a bug in the structure intialization macros which initialize the fft size to N instead of N/2. You also have to perform some additional post-processing steps to get back the correct output which has NOT been implemented in this library as yet.....it will be in the next revision which will be soon

    please see section 2 of this wiki: http://processors.wiki.ti.com/index.php/Efficient_FFT_Computation_of_Real_Input#Computing_a_Length_N.2F2_Complex_FFT_from_a_Length_N_Real_Input_Sequence

    I would recommend using the CFFT and computing the magnitude for your code. As far as 0th value goes it is the DC value and it basically is a sum of your 128 samples/128. if your square wave has an offset this will be a non-zero values.

     

  • So, if I am to use CFFT32, what's the ipcbsrc input supposed to be?

    I'm currently sampling data from ADC at 40kHz and stored the data as follows:

     

    ipcbsrc[conversionCount & 0xFF] = (long) AdcResult.ADCRESULT0;

    That being said, I want to do 128-points FFT, could you verify that my code initialization are correct?

    #define N 128

    long ipcbsrc[2*N];

    long ipcb[2*N];

    CFFT32 fft = CFFT32_128P_DEFAULTS;

    CFFT32_brev(ipcbsrc, ipcb, N);

    CFFT32_brev(&ipcbsrc[1], &ipcb[1], N);

    fft.ipcbptr = ipcb;

    fft.magptr = ipcbsrc;

    fft.winptr = (long*) win;

    fft.init(&fft);

    fft.calc(&fft);

    fft.mag(&fft);

    So I'd expect the magnitude to be stored in ipcb at index 0, 2, 4, and so on?

  • you're initialization is correct: if your input data is real be sure to pad in alternate zeros for the imaginary parts though and then point ipcbsrc at this padded input matrix. The magnitude is real valued and contiguous in ipcb @ index 0,1,2,3..N

  • So let me check if my understanding is correct...

    ipcbsrc[0, 2, 4, 6, ... 254] <- data from ADC

    ipcbsrc[1, 3, 5, 7, ... 255] <- fill with zeros

    ipcb[0 ... 127] -> magnitude

    ipcb[128 ... 255] -> unusable data

    Thanks

  • Correct, although, i made a mistake, you configured ipcbsrc as your magptr so your magnitude plot will be in ipcbsrc[0...127]

  • That means, during the FFT computation, the ADC should not be allowed to change the contents of ipcbsrc, correct?

    Interestingly, after fft.mag(&fft), the ipcbsrc[0..127] are all zeros... fft.peakmag = 0, fft.peakfrq = 0

    This is how ipcbsrc gets populated:


    interrupt void adc_isr() {

    if (enableAdcCapture) {

    ipcbsrc[conversionCount & 0xFF] = (long) AdcResult.ADCRESULT0;

    ipcbsrc[conversionCount + 1 & 0xFF] = (long) 0;

    }

    if (enableAdcCapture) {

    if (conversionCount == 254) {

    conversionCount = 0;

    adcConversionComplete = 1;

    }

    else {

    conversionCount += 2;

    }

    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;

    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;

    return;

    }

     

     

    Here's my code that's related to FFT computation:

    #define fftSize 128


    long ipcbsrc[2 * fftSize];

    long ipcb[2 * fftSize];

    CFFT32 fft = CFFT32_128P_DEFAULTS;

    const long win[fftSize / 2] = HAMMING32;

     

    CFFT32_brev(ipcbsrc, ipcb, fftSize);

    CFFT32_brev(&ipcbsrc[1], &ipcb[1], fftSize);

    fft.ipcbptr = ipcb;

    fft.magptr = ipcbsrc;

    fft.winptr = (long*) win;

    fft.init(&fft);

    fft.calc(&fft);

    fft.mag(&fft);

     

     

  • Gloria,

    The input needs to be in Q31 format. You need to mulitply the adc samples by 2^15- left shift by 15

  • That now makes much more sense!

    Thanks very much, Vishal!

  • Quick question. There is this following code in F28035.cmd:

       ramfuncs            : LOAD = FLASHD,
                             RUN
    = RAML0,
                             LOAD_START
    (_RamfuncsLoadStart),
                             LOAD_END
    (_RamfuncsLoadEnd),
                             RUN_START
    (_RamfuncsRunStart),
                             PAGE
    = 0

    Does the CFFT32 copied from FLASH to RAML0 during runtime?

    Thanks

    EDIT: I do not find any #pragma that does so, but I just want to double check.

  • Hi Gloria,

    Usually the buffers are in RAM but the code fro the FFT can run out of flash. A good example for FLASH implementation is : controlSUITE\development_kits\F28069 controlSTICK\FPU - SineFIRFFT32---The same code can be adapted to the 2833x with a few changes to the .cmd file

    The function InitFlash() is in the section ramfuncs and needs to be copied over to RAM first and then executed to setup the FLASH but other than that the implementation is no different from the RAM version