Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 5 of 5

Thread: CMSIS 5.3.0 and CMSIS_DSP 1.7.0 on teensy 4

  1. #1
    Junior Member
    Join Date
    Oct 2019
    Posts
    4

    CMSIS 5.3.0 and CMSIS_DSP 1.7.0 on teensy 4

    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

  2. #2
    Senior Member DD4WH's Avatar
    Join Date
    Oct 2015
    Location
    Central Europe
    Posts
    508
    Yes, you can find an example here: https://forum.pjrc.com/threads/57267...ht=convolution

    It uses a forward 4096-point-FFT, a complex-multiply with a filter mask and an inverse 4096-point-FFT to filter realtime audio (Fast Convolution Filtering).

    The processor load is about 2.7% on the T4.

    P.S.: I just realized that the DSP version used in the latest Teensyduino is V.1.5.1, NOT 1.7.0

  3. #3
    Junior Member
    Join Date
    Oct 2019
    Posts
    4
    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);
    }

  4. #4
    Senior Member DD4WH's Avatar
    Join Date
    Oct 2015
    Location
    Central Europe
    Posts
    508
    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/...ransforms.html

  5. #5
    Junior Member
    Join Date
    Oct 2019
    Posts
    4
    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.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •