FFT using CMSIS for non mbed-os for smaller capacity chips with DAC output e.g. F303K8 to display FFT to an Oscilloscope with example to send to MAX7219 LED Array

Dependencies:   MAX7219 mbed-dsp mbed

main.cpp

Committer:
martinsimpson
Date:
2018-04-13
Revision:
0:6daa40cd81ec

File content as of revision 0:6daa40cd81ec:

#include "mbed.h"
/*ADAFruit 8x8 LED Array driver chip SPI */
#include "max7219.h"
/* Include arm_math.h mathematic functions */
#include "arm_math.h"
/* Include mbed-dsp libraries */
#include "arm_common_tables.h"
#include "arm_const_structs.h"
#include "math_helper.h"

/* FFT settings */
#define SAMPLES                 512             /* 256 real party and 256 imaginary parts */
#define FFT_SIZE                SAMPLES / 2     /* FFT size is always the same size as we have samples, so 256 in our case */

/* Global variables */
float32_t Input[SAMPLES];
float32_t sampler[SAMPLES]={0};
float32_t Output[FFT_SIZE];
bool      trig=0;

/*Function Prototypes */
uint16_t convert_bar(uint16_t);
void sample();

/* MBED class APIs */
DigitalOut myled(LED1);
AnalogIn   myADC(A1);
AnalogOut  myDAC(A3);
Ticker     timer;

/* Other class APIs */
Max7219 max7219(D11, D12, D13, D10);//SPI0_MOSI, SPI0_MISO, SPI0_SCK, SPI0_SS);

void sample(){
    trig=1;
    }
    
int main() {

    uint8_t  array[]={0x1F,0x14,0x10,0x00,0x1F,0x14,0x10,0x00,0x10,0x1F,0x10}; //text 'FFT'
    uint16_t array_size=sizeof(array);
    int16_t  i,j;
    float maxValue;            // Max FFT value is stored here
    uint32_t maxIndex;         // Index in Output array where max value is
    
    printf("FFT Example using 32F303K8 DAC output\r\n");
    
    max7219_configuration_t cfg = {
         .device_number = 1,
         .decode_mode = 0,
         .intensity = Max7219::MAX7219_INTENSITY_4,
         .scan_limit = Max7219::MAX7219_SCAN_8
     };

     max7219.init_device(cfg);
     max7219.enable_device(1);
     max7219.set_display_test();
     max7219.clear_display_test();
     max7219.display_all_off();
   
     for(j=-8;j<=array_size;j++){
        for(i=1;i<=array_size;i++){
            max7219.write_digit(1,9-i+j,array[i-1]);
        }
        wait_ms(100);
        max7219.display_all_off();
     }

    //arm_cfft_instance_f32 S;   // ARM CFFT module
    //float maxValue;            // Max FFT value is stored here
    //uint32_t maxIndex;         // Index in Output array where max value is
    
    while(1) {
            timer.attach_us(&sample,30); //30us 30,30 250KHz sampling rate ********

            for (i = 0; i < SAMPLES; i += 2) {
                while (trig==0){}
                trig=0;  
                Input[i] = myADC.read() - 0.5f; //Real part NB removing DC offset
                Input[i + 1] = 0;               //Imaginary Part set to zero
            }
            timer.detach();
            // Init the Complex FFT module, intFlag = 0, doBitReverse = 1
            // NB using predefined arm_cfft_sR_f32_lenXXX, in this case XXX is 256
            arm_cfft_f32(&arm_cfft_sR_f32_len256, Input, 0, 1);

            // Complex Magniture Module put results into Output(Half size of the Input)
            arm_cmplx_mag_f32(Input, Output, FFT_SIZE);
        
        Output[0]=0;
        
        
            //Calculates maxValue and returns corresponding value
            arm_max_f32(Output, FFT_SIZE, &maxValue, &maxIndex);
            
        
            myDAC=1.0f; //SYNC here!! for Oscillscope at max DAC output for triggering purposes
            wait_us(20);//All FFT values will be lower since max scaling is 0.9 as below
            myDAC=0.0f;//set trigger level on oscilloscope between 0.9 to 1.0 (*3.3Volts) i.e. 3.0 to 3.3Volts
        
            for (i=2; i<FFT_SIZE/2 ; i++){
                myDAC=(Output[i]/maxValue)*0.9f; // All Values scaled to 0.0 to 0.9 for output to DAC
            //    if (Output[i]>0.2){printf("%d %f\r\n",i,(Output[i]/maxValue)*0.9f);}
                wait_us(10);
            }
            myDAC=0.0f;

            for (i=0; i<9;i++){
                max7219.write_digit(1,9-i,convert_bar((uint16_t)(Output[i*16]*2.9f)));//  5.8f
            }
        }
}

// Will take a number (numVal) 0 to 255 and return (converted) the next (lower) 2^n-1 value
// to light up all LEDS as a bar graph representation
uint16_t convert_bar(uint16_t numVal){
    if (numVal>255){return 0;} 
    uint16_t converted = 0;
        for (uint16_t i=1; i<=256 ; i*=2){
            if ((numVal/(i)) >= 1){converted = (i-1);}
            }
    return converted;   
}