DUE's more advanced FFT capabilities

I'm looking for the most efficient way to get the Arduino DUE to preform a FFT. Since I'm only interested in preforming FFTs of real signals, a symmetric transformer like the Hartley Transform would be best.

I know there are a few libraries floating around, but all the ones I can find have been made for the UNO (don't compile in the 1.5 IDE). Are there and FFT libraries for the DUE?
In the directories of IDE 1.5, I saw a few c files in ...\arduino\sam\system\CMSIS\CMSIS\DSP_Lib\Source\TransformFunctions
like arm_cfft_radix4_f32.c for example

These are excellent implementations intended for the Ardunio DUE's ARM4 core, but I cant seem to get them to compile (compiler error: cant find ARMCM4.h ... and when I add ARMCM4.h as a library, the compiler complains that it is an invalid library)

Any ideas? What other powerful libraries are there for the DUE that haven't been publicized?

Thanks!

Hi,
The Due, ARM3 not ARM4 so it does not have the DSP extension, my guess is that thats is why its complaining about the invalid library.

Duane B

rcarduino.blogspot.com

Oops, your absolutely right. The DUE has an ARM M3 and not M4 core. Still, its very strange to me why the Arduino 1.5 IDE comes with ARM M4 c and s files.

Anyways, any thoughts about a FFT library which will take advantage of the ARM M3's float operation capabilities (for example...) would be much appreciated.

I did find one which does compile:

It uses "double" for all of its data types. Does the ARM M3 process doubles as efficiently as floats? Or is it emulated and therefore take a much longer time to process?

Thanks again!

Sorry to disappoint, but as far as I am aware there is no floating point co processor either so no hardware support for float or double.

Duane B

yikes! well back to the drawing board...

I am sure there are good 32 bit fixed point libraries, have a look and let us know.

Duane B

There's always the Teensy 3.0, which has the DSP extensions in it's core.

lots of explaining can be found in hardware/arduino/sam/system/CMSIS/CMSIS/Documentation/DSP_Lib/html/index.html

as far as I can see now it is suposed to work , only not with hardware support (like in the M4).
it is even supposed to work on the M0 !

exciting !

... but on second thought, be aware that this stuff is covered by a licence.

I got the sketch to pass the errors mentioned above, but it seems to need to link with an .a file.
does anybody know how I should build these CMSIS files into a library and add that to the Arduino IDE ?

my sketch until now (based on one of the examples, but duly botched while trying to get it to compile) :

#define ARM_MATH_CM3 // this selects right environment for arm_math.h on DUE
#include <arm_math.h>

#define TEST_LENGTH_SAMPLES 2048 
 
static q31_t testOutput[TEST_LENGTH_SAMPLES/2]; // all types changed from f32 to q31 just to see if it mattered
 
uint32_t M = 0;
 
/* ------------------------------------------------------------------ 
* Global variables for FFT Bin Example 
* ------------------------------------------------------------------- */ 
uint32_t fftSize = 1024; 
uint32_t ifftFlag = 0; 
uint32_t doBitReverse = 1; 
 
/* Reference index at which max energy of bin ocuurs */ 
uint32_t refIndex = 213, testIndex = 0; 
 
/* ----------------------------------------------------------------------
Test Input signal contains 10KHz signal + Uniformly distributed white noise
** ------------------------------------------------------------------- */

q31_t testInput_f32_10khz[TEST_LENGTH_SAMPLES] = 
{   
-0.865129623056441, 	0.000000000000000, 	-2.655020678073846, 	0.000000000000000, 	0.600664612949661, 	0.000000000000000, 	0.080378093886515, 	0.000000000000000, 	
-2.899160484012034, 	0.000000000000000, 	2.563004262857762, 	0.000000000000000, 	3.078328403304206, 	0.000000000000000, 	0.105906778385130, 	0.000000000000000, 	
-1.620990298572947, 	0.000000000000000, 	-1.085103073196045, 	0.000000000000000, 	0.738606361195386, 	0.000000000000000, 	
-2.097831202853255, 	0.000000000000000, 	2.711952282071310, 	0.000000000000000, 	1.498539238246888, 	0.000000000000000, 	1.317457282535915, 	0.000000000000000, 	
-0.302765938349717, 	0.000000000000000, 	-0.044623707947201, 	0.000000000000000, 	2.337405215062395, 	0.000000000000000, 	-3.980689173859100, 	0.000000000000000, 	

};

void setup() {
  Serial.begin(19200);
}

void loop() {
       
     
       /** \example arm_fft_bin_example_f32.c 
  */  

	arm_status status; 
	arm_cfft_radix4_instance_q31 S; 
	q31_t maxValue; 
	 
	status = ARM_MATH_SUCCESS; 
	 
	/* Initialize the CFFT/CIFFT module */  
	status = arm_cfft_radix4_init_q31(&S, fftSize, ifftFlag, doBitReverse); 
	 
	/* Process the data through the CFFT/CIFFT module */ 
	arm_cfft_radix4_q31(&S, testInput_f32_10khz); 
	 
	 
	/* Process the data through the Complex Magnitude Module for  
	calculating the magnitude at each bin */ 
	arm_cmplx_mag_q31(testInput_f32_10khz, testOutput, fftSize);  
	 
	/* Calculates maxValue and returns corresponding BIN value */ 
	arm_max_q31(testOutput, fftSize, &maxValue, &testIndex); 
	 
	if(testIndex !=  refIndex) 
	{ 
		status = ARM_MATH_TEST_FAILURE; 
	} 
	 
	/* ---------------------------------------------------------------------- 
	** Loop here if the signals fail the PASS check. 
	** This denotes a test failure 
	** ------------------------------------------------------------------- */ 
	 
	if( status != ARM_MATH_SUCCESS) 
	{ 
		while(1); 
	} 

    while(1);                             /* main function does not return */
    
}

I got this library to work on the DUE.
see http://arduino.cc/forum/index.php/topic,140107.0.html

raalst:
lots of explaining can be found in hardware/arduino/sam/system/CMSIS/CMSIS/Documentation/DSP_Lib/html/index.html

as far as I can see now it is suposed to work , only not with hardware support (like in the M4).
it is even supposed to work on the M0 !

exciting !

... but on second thought, be aware that this stuff is covered by a licence.

I got the sketch to pass the errors mentioned above, but it seems to need to link with an .a file.
does anybody know how I should build these CMSIS files into a library and add that to the Arduino IDE ?

my sketch until now (based on one of the examples, but duly botched while trying to get it to compile) :

#define ARM_MATH_CM3 // this selects right environment for arm_math.h on DUE

#include <arm_math.h>

#define TEST_LENGTH_SAMPLES 2048

static q31_t testOutput[TEST_LENGTH_SAMPLES/2]; // all types changed from f32 to q31 just to see if it mattered

uint32_t M = 0;

/* ------------------------------------------------------------------

  • Global variables for FFT Bin Example
  • ------------------------------------------------------------------- */
    uint32_t fftSize = 1024;
    uint32_t ifftFlag = 0;
    uint32_t doBitReverse = 1;

/* Reference index at which max energy of bin ocuurs */
uint32_t refIndex = 213, testIndex = 0;

/* ----------------------------------------------------------------------
Test Input signal contains 10KHz signal + Uniformly distributed white noise
** ------------------------------------------------------------------- */

q31_t testInput_f32_10khz[TEST_LENGTH_SAMPLES] =
{  
-0.865129623056441, 0.000000000000000, -2.655020678073846, 0.000000000000000, 0.600664612949661, 0.000000000000000, 0.080378093886515, 0.000000000000000,
-2.899160484012034, 0.000000000000000, 2.563004262857762, 0.000000000000000, 3.078328403304206, 0.000000000000000, 0.105906778385130, 0.000000000000000,
-1.620990298572947, 0.000000000000000, -1.085103073196045, 0.000000000000000, 0.738606361195386, 0.000000000000000,
-2.097831202853255, 0.000000000000000, 2.711952282071310, 0.000000000000000, 1.498539238246888, 0.000000000000000, 1.317457282535915, 0.000000000000000,
-0.302765938349717, 0.000000000000000, -0.044623707947201, 0.000000000000000, 2.337405215062395, 0.000000000000000, -3.980689173859100, 0.000000000000000,

};

void setup() {
 Serial.begin(19200);
}

void loop() {
     
   
      /** \example arm_fft_bin_example_f32.c
 */

arm_status status; 
arm_cfft_radix4_instance_q31 S; 
q31_t maxValue; 
 
status = ARM_MATH_SUCCESS; 
 
/* Initialize the CFFT/CIFFT module */  
status = arm_cfft_radix4_init_q31(&S, fftSize, ifftFlag, doBitReverse); 
 
/* Process the data through the CFFT/CIFFT module */ 
arm_cfft_radix4_q31(&S, testInput_f32_10khz); 
 
 
/* Process the data through the Complex Magnitude Module for  
calculating the magnitude at each bin */ 
arm_cmplx_mag_q31(testInput_f32_10khz, testOutput, fftSize);  
 
/* Calculates maxValue and returns corresponding BIN value */ 
arm_max_q31(testOutput, fftSize, &maxValue, &testIndex); 
 
if(testIndex !=  refIndex) 
{ 
	status = ARM_MATH_TEST_FAILURE; 
} 
 
/* ---------------------------------------------------------------------- 
** Loop here if the signals fail the PASS check. 
** This denotes a test failure 
** ------------------------------------------------------------------- */ 
 
if( status != ARM_MATH_SUCCESS) 
{ 
	while(1); 
} 

while(1);                             /* main function does not return */
   
}

Could you finally get this library working under Q31? I can in Q15 and f32, but not under Q31!!!
Thank you

Nope, I was happy with whatever I could get to work, since I'm still at the
"thinking about it" phase of my project.
I have not really made an effort specifically for the Q31.
It might be hard, it could be simple ....

raalst:
Nope, I was happy with whatever I could get to work, since I'm still at the
"thinking about it" phase of my project.
I have not really made an effort specifically for the Q31.
It might be hard, it could be simple ....

It is not hard, I have it for Q15, the problem is, if I use any Q31 array, arduino just freezes!!

How can I implement this code to do an FFT from an AnalogRead

I attempted to ad the following code in place of the specified test signal "float32_t testInput_f32_10khz[2048]"

for (int x=0;x<2048;x++){
   float32_t voltage = analogRead(A0) * (5 / 1023.0);
   testInput_f32_10khz[x]=voltage;
   x++;
   testInput_f32_10khz[x]=0.000000000000000;
  }

But it always replies with a 0 value for the testIndex

try: voltage = (float) analogRead(0) * 5.0 / 1023.0; to ensure you do not get the 5/1023 being an int which would be zero. Also, maybe instead of 5.0 use 3.3 as Due is a 3.3 volt system?

If you have those spare parts, I would add an Raspberry Pi to handle the FFT. Just send the samples out using either SPI or UART and let that to crunch the numbers.