Hello! I faced the strange behavior of function C6accel_DSP_fft32x32().
It works fine in demo samples which are coming with c6accel lib (c6accel_1_01_00_07) from DVSDK 4 (dvsdk_omapl138-evm_04_03_00_06).
But with my input signal file this function returns wrong result.
Tell me please, what may be the cause. Thanks for any advice
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> /* Codec Engine includes */ #include <xdc/std.h> #include <ti/sdo/ce/Engine.h> #include <ti/sdo/ce/CERuntime.h> #include <ti/sdo/ce/osal/Memory.h> #include <xdc/runtime/System.h> /* Include C6ACCEL headers */ #include "../c6accelw/c6accelw.h" #define ENGINENAME "omapl138" #define ALGNAME "c6accel" #define APPNAME "test_DSP_FFT" #pragma DATA_ALIGN(pInputArray, 8); // The alignment is very important #pragma DATA_ALIGN(pOutputArray, 8); // for input/ouput and twiddle pointers #pragma DATA_ALIGN(pTwiddleTable, 8); signed int *pTwiddleTable; //Input twiddle factors signed int *pInputArray, *pOutputArray; /* Codec Engine engine and codec labels, defined in cfg file: */ static String algName = ALGNAME; static String engineName = ENGINENAME; static String progName = APPNAME; static String ref_src_fft = "complex_input_signal.dat"; static String sOut_file = "real_output_spectrum.dat"; // Create default heap memory configuration for wrapper static Memory_AllocParams wrapperMemParams = { Memory_CONTIGHEAP, Memory_CACHED, Memory_DEFAULTALIGNMENT, 0 }; int main () { int N = 32768;//count of points for FFT C6accel_Handle hC6accel = NULL; CERuntime_init(); hC6accel = C6accel_create(engineName, NULL, algName, NULL); while (1) { /*Check for failure*/ if ( hC6accel == NULL) { printf("%s: C6accel_create() failed \n",progName); break; } C6Accel_setSync(hC6accel); //Set C6Accel instance for synchronous call test_DSP_FFT(hC6accel,N); C6accel_delete(hC6accel); break; } return 0; } int test_DSP_FFT(C6accel_Handle hC6accel,unsigned int nx) { int i,j,status; unsigned int freaden; signed int iNum; double scale = 2147483647.5; FILE *fSamples, *fOut; UInt32 framesize = 2*nx*sizeof(int); //---------------memory allocation--------------------------------// pTwiddleTable = Memory_alloc(framesize, &wrapperMemParams); if (pTwiddleTable == NULL) { printf("Memory_alloc error\n"); return -1; } Memory_cacheWbInv(pTwiddleTable, framesize); memset (pTwiddleTable,0x00,framesize); pInputArray = Memory_alloc(framesize, &wrapperMemParams); if (pInputArray == NULL) { printf("Memory_alloc error\n"); return -1; } Memory_cacheWbInv(pInputArray, framesize); memset (pInputArray,0x00,framesize); pOutputArray = Memory_alloc(2*nx*sizeof(int), &wrapperMemParams); if (pOutputArray == NULL) { printf("\nFailed memory_alloc. \n"); return -1; } Memory_cacheWbInv(pOutputArray, framesize); memset (pOutputArray,0x00,framesize); //----------------------------------------------------------------// // Generate the twiddle table with real and imaginary parts gen_twiddle(pTwiddleTable, nx, scale); // read input complex data if ((fSamples = fopen(ref_src_fft,"rb")) == NULL) { printf("Failed to open file %s\n",ref_src_fft); return -1; } fread(pInputArray,sizeof(int),2*nx,fSamples); fclose(fSamples); // Call the fft32x32 in the C6Accel status = C6accel_DSP_fft32x32 (hC6accel,pTwiddleTable, nx, pInputArray, pOutputArray); printf("Status of C6accel_DSP_fft32x32 = %d\n",status); if (status!=NULL) return -1; signed int *pOut = malloc(nx*sizeof(int)); memset(pOut,0x00,nx*sizeof(int)); fOut = fopen("complex_output_spectrum.dat","wb"); fwrite(pOutputArray,sizeof(int),nx*2,fOut); fclose(fOut); //put in file module of complex while (1) { for (i=0,j=0; j<nx; i=i+2,j++) { pOut[j] = (int)(sqrt(pOutputArray[i]*pOutputArray[i]+pOutputArray[i+1]*pOutputArray[i+1])); } break; } fOut = fopen(sOut_file,"wb"); fwrite(pOut,sizeof(int),nx,fOut); fclose(fOut); Memory_free(pInputArray,framesize,&wrapperMemParams); Memory_free(pOutputArray,framesize,&wrapperMemParams); Memory_free(pTwiddleTable,framesize,&wrapperMemParams); free(pOut); printf("Done. See spectrum at file %s\n",sOut_file); return 0; } static int d2i(double d) //Truncate a 'double' to a 'int', with clamping. { if (d >= 2147483647.0) return (int)0x7FFFFFFF; if (d <= -2147483648.0) return (int)0x80000000; return (int)d; } int gen_twiddle(int *w, int n, double scale) { int i, j, k, s=0, t; for (j = 1, k = 0; j < n >> 2; j = j << 2, s++) { for (i = t=0; i < n >> 2; i += j, t++) { w[k + 5] = d2i(scale * cos(6.0 * PI * i / n)); w[k + 4] = d2i(scale * sin(6.0 * PI * i / n)); w[k + 3] = d2i(scale * cos(4.0 * PI * i / n)); w[k + 2] = d2i(scale * sin(4.0 * PI * i / n)); w[k + 1] = d2i(scale * cos(2.0 * PI * i / n)); w[k + 0] = d2i(scale * sin(2.0 * PI * i / n)); k += 6; } } return k; }
In data.zip you can find:
Hi,
I think this might be a case where the input data is not scaled properly due to which the output may be overflowing. I would strongly recommend you to download the C64x+ version of the DSPLIB, or view the details of the implementation of the fft_32x32 kernel mentioned in the document sprueb8b.pdf. There is also an example implementation of the 32 bit FFT function in the C64x+ DSP library.
The data that we passed in the test bench of the C6Accel is a pre-scaled data due to which you may not see this step implemented in the sample application.
Regards,
Rahul
---------------------------------------------------------------------------------Please click the Verify Answer button on this post if it answers your question.---------------------------------------------------------------------------------