CMSIS 5.3.0 and CMSIS_DSP 1.7.0 on teensy 4

Status
Not open for further replies.

tomatokotom

New member
Hi everyone,
First, thanks to Paul for his work on teensy!

So, i just get a teensy 4 and try to do experiment with fft.
I saw than it was possible to do 4096 point fft with the CMSIS_DSP 1.7.0

Did someone manage to use it with the teensy 4?

Thanks
Thomas
 
Hey, Thanks DD4WH!!
I didn't notice it was this version on teensy 4.
So i have an other question, (because it was my main goal to do this):
I try to run the rfft to have just real number, but can't figure out how to do this. When i try this code( i found on the forum, and who is supposed to work), it don't do the Rfft( don't print "q15 real done"), but if i comment the rfft line, the cfft work (print Serial.println "q15 complex done").
may i have any clues to make it work?

here is the code
Code:
#include "arm_math.h"

#define forward    0
#define bitReverse 1
#define fftLength  1024
//
arm_rfft_instance_q15 rfft_inst;
arm_cfft_radix4_instance_q15 cfft_inst;
int16_t rdata[fftLength], rfft_buffer[fftLength];
int16_t cdata[2*fftLength];

//---------------------------------------------------
void setup() {
  Serial.println("start");
   Serial.begin(9600);
   while(!Serial){}
  arm_rfft_init_q15(&rfft_inst,fftLength, forward, bitReverse);
  arm_cfft_radix4_init_q15(&cfft_inst, fftLength, forward, bitReverse);
Serial.println("init done");

}

//-----------------------------
void loop() {
  for (int i=0; i<fftLength; i++) {
   rdata[i]     = (int16_t)(20000 + 4096*cos(2*3.1415926*i/16) + 6788*sin(2*3.1415926*i/4));  // real
   cdata[2*i]   = (int16_t)(20000 + 4096*cos(2*3.1415926*i/16) + 6788*sin(2*3.1415926*i/4));  // complex
   cdata[2*i+1] = 0;
  }
  Serial.println("wave generated");
  delay(100);
 
  uint32_t t0 = micros();
  arm_rfft_q15(&rfft_inst, rdata, rfft_buffer);
  Serial.println("q15 real done");
  Serial.print(micros() - t0);
  t0 = micros();
  arm_cfft_radix4_q15(&cfft_inst, cdata);
  Serial.println("q15 complex done");
  Serial.print("\t"); Serial.println(micros() - t0);
delay(2000);
}
 
First of all, it would be good to know what you want to do with the FFT!? Then it would be easier to decide whether you need a real FFT or a complex FFT.

Regarding the code you posted:

* you should NOT use the deprecated function "arm_cfft_radix4_q15" any more, use "arm_cfft_q15" instead!

* if you use a real FFT, the ARM function computes a complex FFT internally, BUT with half the number of FFT points and uses the conjugate symmetric property in order to process your real input data (it outputs complex data however). It seems that the ARM function arm_rfft_q15 nonetheless requires a double sized buffer (of size fftLength*2), although it internally uses a complex FFT of size fftLength/2

* I got the code running with the recently used and recommended functions by changing the following in your code:

Code:
#include "arm_math.h"
#include <arm_const_structs.h>

#define forward    0
#define bitReverse 1
#define fftLength  4096
//
const static arm_rfft_instance_q15 rfft_inst;
// deprecated, do not use!
//arm_cfft_radix4_instance_q15 cfft_inst;
const static arm_cfft_instance_q15 *cfft_inst;
// strange as it seems, the rfft_buffer has to be twice the size of the FFT !?
int16_t rdata[fftLength], rfft_buffer[fftLength * 2];
int16_t cdata[2*fftLength];

//---------------------------------------------------
void setup() {
  Serial.println("start");
   Serial.begin(9600);
   while(!Serial){}
  if(arm_rfft_init_q15(&rfft_inst,fftLength, forward, bitReverse) == ARM_MATH_SUCCESS) Serial.println("Successful: init rfft");
// deprecated, do not use !
//  if(arm_cfft_radix4_init_q15(&cfft_inst, fftLength, forward, bitReverse) == ARM_MATH_SUCCESS) Serial.println("Successful: init cfft");

  switch (fftLength) {
    case 16:
      cfft_inst = &arm_cfft_sR_q15_len16;
      break;
    case 32:
      cfft_inst = &arm_cfft_sR_q15_len32;
      break;
    case 64:
      cfft_inst = &arm_cfft_sR_q15_len64;
      break;
    case 128:
      cfft_inst = &arm_cfft_sR_q15_len128;
      break;
    case 256:
      cfft_inst = &arm_cfft_sR_q15_len256;
      break;
    case 512:
      cfft_inst = &arm_cfft_sR_q15_len512;
      break;
    case 1024:
      cfft_inst = &arm_cfft_sR_q15_len1024;
      break;
    case 2048:
      cfft_inst = &arm_cfft_sR_q15_len2048;
      break;
    case 4096:
      cfft_inst = &arm_cfft_sR_q15_len4096;
      break;
  }

Serial.print("CFFT init done with size "); Serial.println (fftLength);

}

//-----------------------------
void loop() {
  for (int i=0; i<fftLength; i++) {
   rdata[i]     = (int16_t)(20000 + 4096*cos(2*3.1415926*i/16) + 6788*sin(2*3.1415926*i/4));  // real
   cdata[2*i]   = (int16_t)(20000 + 4096*cos(2*3.1415926*i/16) + 6788*sin(2*3.1415926*i/4));  // complex
   cdata[2*i+1] = 0;
  }
  Serial.println("wave generated");
  delay(100);
 
  uint32_t t0 = micros();
  arm_rfft_q15(&rfft_inst, rdata, rfft_buffer);
  Serial.println("q15 real done");
  Serial.print("\t"); Serial.println(micros() - t0);
  t0 = micros();
// deprecated, do not use !
//  arm_cfft_radix4_q15(&cfft_inst, cdata);
  arm_cfft_q15(cfft_inst, cdata, forward, bitReverse);
  Serial.println("q15 complex done");
  Serial.print("\t"); Serial.println(micros() - t0);
delay(2000);

However I did not check whether the FFT delivered nice results, that would be your task :)

P.S.: for the real FFT, the maximum FFT length is 8192 (because it computes a 4096 point complex FFT internally), for the complex FFT the maximum size is 4096

P.P.S.: BTW, here is the documentation for the FFT functions: https://www.keil.com/pack/doc/CMSIS/DSP/html/group__groupTransforms.html
 
Hi DD4WH ,
Thanks for the anwser,
So i tried to use FFT to do experiment on finding spectral centroid on recorded sounds (it mean i just need real values), and i wanted to try the fastest way to do it (since in keil ressources, they say the real fft is a little bit faster than the complex.
But for the moment i'm stuck in an other part of my code, so i will do more experiments later on this point.
 
Status
Not open for further replies.
Back
Top