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.

TMS320C6678: FFTLIB: FFT errors

Part Number: TMS320C6678
Other Parts Discussed in Thread: FFTLIB

Hi,

I'm evaluating the FFTLIB FFT 1D complrex-to-complex basic routine (no OMP, single core), but re result of the computation are wrong.

I execute the test side-by-side with DSPLIB FFT (DSPF_sp_fftSPxSP): with same input (including twiddle) the DSPLIB results are correct while the FFLIB are not correct (I also check the results against Python numpy).

For instance, for N=16, I invoke FFLIB as:

      _fft_rad_2p2_next_sm1_notwid_br(in, in, 1, svg, 16, wd, out)

Where svg in a static int[64], wd is float[32] (twiddle), in and out are float[16][2] (cast to double).

The 1st and 9th points are correct (out[0] and out[7]) while all the other are wrong.

As test vector I use a simple ramp over real part:

    for(int i=0; i<16; ++i) { in[i][0]=i; in[i][1]=1;}

I test from 16 to 4096 points, with the same problems (first point is always good).

Any advice?

Thanks

  • Hi,

    I've notified the RTOS team. They will post their feedback directly here.

    Please state which RTOS SDK version are you using?

    Best Regards,
    Yordan
  • CCS 5.5
    CGT c6000 v7.4.23
    fftlib_3_1_0_0

    From fftlib I use:
    void _fft_rad_2p2_next_sm1_notwid_br(double *inp , double *out_l1, unsigned int n_per_pas, int *svg, int pas, double *coeff, double *outp);
    void _fft_rad_2p2_next_sm2_notwid_br(double *inp , double *out_l1, unsigned int n_per_pas, int *svg, int pas, double *coeff, double *outp);
    void _fft_rad_2p2_next_notwid_br(double *inp , double *out_l1, unsigned int n_per_pas, int *svg, int pas, double *coeff, double *outp);

    Invoked as in fft_sp_cmplx_notwid_br() (max points = 4096). Twiddle calculate as in tw_gen_cn() from fft_sp_1d_c2c_batch_d.c (little endian).

    By the way, the result are correct when input = {1,1} for all samples, but this is a special case: result are all zero but the first point.
  • Hi,

    There is some special initialization of endianess (I compile little endian) or twiddle factor requirement?

    My test is very simple:

    #include <math.h>
    
    #define NFFT    16
    
    static float w16d[2 * NFFT];
    
    static float fft_in[NFFT][2];
    static float fft_tmp[NFFT][2];
    static float fft_out[NFFT][2];
    
    static void tw_gen_cn (float *w, int n)
    {
        int i, j, k;
        const double PI = 3.141592654;
    
        for (j = 1, k = 0; j <= n >> 2; j = j << 2)
        {
            for (i = 0; i < n >> 2; i += j)
            {
    #ifdef _LITTLE_ENDIAN
                w[k]     = (float) sin (2 * PI * i / n);
                w[k + 1] = (float) cos (2 * PI * i / n);
                w[k + 2] = (float) sin (4 * PI * i / n);
                w[k + 3] = (float) cos (4 * PI * i / n);
                w[k + 4] = (float) sin (6 * PI * i / n);
                w[k + 5] = (float) cos (6 * PI * i / n);
    #else
                w[k]     = (float)  cos (2 * PI * i / n);
                w[k + 1] = (float) -sin (2 * PI * i / n);
                w[k + 2] = (float)  cos (4 * PI * i / n);
                w[k + 3] = (float) -sin (4 * PI * i / n);
                w[k + 4] = (float)  cos (6 * PI * i / n);
                w[k + 5] = (float) -sin (6 * PI * i / n);
    #endif
                k += 6;
            }
        }
    }
    
    extern void _fft_rad_2p2_next_sm1_notwid_br(double *inp , double *out_l1, unsigned int n_per_pas, int *svg, int pas, double *coeff, double *outp);
    
    extern void DSPF_sp_fftSPxSP (int N, float *ptr_x, float *ptr_w, float *ptr_y, unsigned char *brev, int n_min, int offset, int n_max);
    
    #include <stdio.h>
    
    int main()
    {
      static int svg[32];
    
      int i;
    
      tw_gen_cn(w16d, 16);
    
      for(i=0; i<NFFT; ++i)
      {
        fft_in[i][0]=i;
        fft_in[i][1]=1;
      }
    
      printf("\nInput:\n");
      for(i=0; i<NFFT; ++i)
      {
        printf(" %2d: %10.3f + %10.3fj    - tw= %10.3f + %10.3fj\n", i, fft_in[i][0], fft_out[i][1], w16d[i*2], w16d[i*2+1]);
      }
    
      //DSPF_sp_fftSPxSP(NFFT, fft_in[0], w16d, fft_out[0], 0, 4, 0, NFFT);   //brev not required on C6678
    
      _fft_rad_2p2_next_sm1_notwid_br((double*)fft_in[0], (double*)fft_tmp[0], 1, svg, NFFT, (double*)w16d, (double*)fft_out[0]);
    
      printf("\nResults:\n");
      for(i=0; i<NFFT; ++i)
      {
        printf(" %2d: %10.3f + %10.3fj\n", i, fft_out[i][0], fft_out[i][1]);
      }
    
      return 0;
    }
    

    The output is:

    Results:
      0:    120.000 +     16.000j       - OK
      1:    -32.000 +     32.000j       - Fail (expected: -8 +40j)
      2:    -32.000 +      0.000j       - Fail
      ... fail ...
      8:     -8.000 +      0.000j       - OK

      ...  fail ...

      12:     -8.000 +     -8.000j      - OK

      ... fail ...

  • Hi,

    I found the problem: it was related to the twiddle coefficient.

    From the LIBFFT header file fft_sp_cmplx_notwid_br: no twiddle required, but only a single coeff as "a pointer on a single twiddle factor Wn=exp(-j2PI/n) ; provided in the (IM:RE) form"

    I'm trying to check the precision as at fist glance is seem less precise then the DSPLIB one. For instance, last sample of a 512 point FFT (test pattern as in mi previous test example):

    DSPLIB: -256.000000, -41720.984375j
    FFLIB ; -255.959885, -41721.335938j
    Py numpi: -256.0, -41720.9898018j