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@0:6daa40cd81ec, 2018-04-13 (annotated)
- Committer:
- martinsimpson
- Date:
- Fri Apr 13 09:22:26 2018 +0000
- Revision:
- 0:6daa40cd81ec
1st commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
martinsimpson | 0:6daa40cd81ec | 1 | #include "mbed.h" |
martinsimpson | 0:6daa40cd81ec | 2 | /*ADAFruit 8x8 LED Array driver chip SPI */ |
martinsimpson | 0:6daa40cd81ec | 3 | #include "max7219.h" |
martinsimpson | 0:6daa40cd81ec | 4 | /* Include arm_math.h mathematic functions */ |
martinsimpson | 0:6daa40cd81ec | 5 | #include "arm_math.h" |
martinsimpson | 0:6daa40cd81ec | 6 | /* Include mbed-dsp libraries */ |
martinsimpson | 0:6daa40cd81ec | 7 | #include "arm_common_tables.h" |
martinsimpson | 0:6daa40cd81ec | 8 | #include "arm_const_structs.h" |
martinsimpson | 0:6daa40cd81ec | 9 | #include "math_helper.h" |
martinsimpson | 0:6daa40cd81ec | 10 | |
martinsimpson | 0:6daa40cd81ec | 11 | /* FFT settings */ |
martinsimpson | 0:6daa40cd81ec | 12 | #define SAMPLES 512 /* 256 real party and 256 imaginary parts */ |
martinsimpson | 0:6daa40cd81ec | 13 | #define FFT_SIZE SAMPLES / 2 /* FFT size is always the same size as we have samples, so 256 in our case */ |
martinsimpson | 0:6daa40cd81ec | 14 | |
martinsimpson | 0:6daa40cd81ec | 15 | /* Global variables */ |
martinsimpson | 0:6daa40cd81ec | 16 | float32_t Input[SAMPLES]; |
martinsimpson | 0:6daa40cd81ec | 17 | float32_t sampler[SAMPLES]={0}; |
martinsimpson | 0:6daa40cd81ec | 18 | float32_t Output[FFT_SIZE]; |
martinsimpson | 0:6daa40cd81ec | 19 | bool trig=0; |
martinsimpson | 0:6daa40cd81ec | 20 | |
martinsimpson | 0:6daa40cd81ec | 21 | /*Function Prototypes */ |
martinsimpson | 0:6daa40cd81ec | 22 | uint16_t convert_bar(uint16_t); |
martinsimpson | 0:6daa40cd81ec | 23 | void sample(); |
martinsimpson | 0:6daa40cd81ec | 24 | |
martinsimpson | 0:6daa40cd81ec | 25 | /* MBED class APIs */ |
martinsimpson | 0:6daa40cd81ec | 26 | DigitalOut myled(LED1); |
martinsimpson | 0:6daa40cd81ec | 27 | AnalogIn myADC(A1); |
martinsimpson | 0:6daa40cd81ec | 28 | AnalogOut myDAC(A3); |
martinsimpson | 0:6daa40cd81ec | 29 | Ticker timer; |
martinsimpson | 0:6daa40cd81ec | 30 | |
martinsimpson | 0:6daa40cd81ec | 31 | /* Other class APIs */ |
martinsimpson | 0:6daa40cd81ec | 32 | Max7219 max7219(D11, D12, D13, D10);//SPI0_MOSI, SPI0_MISO, SPI0_SCK, SPI0_SS); |
martinsimpson | 0:6daa40cd81ec | 33 | |
martinsimpson | 0:6daa40cd81ec | 34 | void sample(){ |
martinsimpson | 0:6daa40cd81ec | 35 | trig=1; |
martinsimpson | 0:6daa40cd81ec | 36 | } |
martinsimpson | 0:6daa40cd81ec | 37 | |
martinsimpson | 0:6daa40cd81ec | 38 | int main() { |
martinsimpson | 0:6daa40cd81ec | 39 | |
martinsimpson | 0:6daa40cd81ec | 40 | uint8_t array[]={0x1F,0x14,0x10,0x00,0x1F,0x14,0x10,0x00,0x10,0x1F,0x10}; //text 'FFT' |
martinsimpson | 0:6daa40cd81ec | 41 | uint16_t array_size=sizeof(array); |
martinsimpson | 0:6daa40cd81ec | 42 | int16_t i,j; |
martinsimpson | 0:6daa40cd81ec | 43 | float maxValue; // Max FFT value is stored here |
martinsimpson | 0:6daa40cd81ec | 44 | uint32_t maxIndex; // Index in Output array where max value is |
martinsimpson | 0:6daa40cd81ec | 45 | |
martinsimpson | 0:6daa40cd81ec | 46 | printf("FFT Example using 32F303K8 DAC output\r\n"); |
martinsimpson | 0:6daa40cd81ec | 47 | |
martinsimpson | 0:6daa40cd81ec | 48 | max7219_configuration_t cfg = { |
martinsimpson | 0:6daa40cd81ec | 49 | .device_number = 1, |
martinsimpson | 0:6daa40cd81ec | 50 | .decode_mode = 0, |
martinsimpson | 0:6daa40cd81ec | 51 | .intensity = Max7219::MAX7219_INTENSITY_4, |
martinsimpson | 0:6daa40cd81ec | 52 | .scan_limit = Max7219::MAX7219_SCAN_8 |
martinsimpson | 0:6daa40cd81ec | 53 | }; |
martinsimpson | 0:6daa40cd81ec | 54 | |
martinsimpson | 0:6daa40cd81ec | 55 | max7219.init_device(cfg); |
martinsimpson | 0:6daa40cd81ec | 56 | max7219.enable_device(1); |
martinsimpson | 0:6daa40cd81ec | 57 | max7219.set_display_test(); |
martinsimpson | 0:6daa40cd81ec | 58 | max7219.clear_display_test(); |
martinsimpson | 0:6daa40cd81ec | 59 | max7219.display_all_off(); |
martinsimpson | 0:6daa40cd81ec | 60 | |
martinsimpson | 0:6daa40cd81ec | 61 | for(j=-8;j<=array_size;j++){ |
martinsimpson | 0:6daa40cd81ec | 62 | for(i=1;i<=array_size;i++){ |
martinsimpson | 0:6daa40cd81ec | 63 | max7219.write_digit(1,9-i+j,array[i-1]); |
martinsimpson | 0:6daa40cd81ec | 64 | } |
martinsimpson | 0:6daa40cd81ec | 65 | wait_ms(100); |
martinsimpson | 0:6daa40cd81ec | 66 | max7219.display_all_off(); |
martinsimpson | 0:6daa40cd81ec | 67 | } |
martinsimpson | 0:6daa40cd81ec | 68 | |
martinsimpson | 0:6daa40cd81ec | 69 | //arm_cfft_instance_f32 S; // ARM CFFT module |
martinsimpson | 0:6daa40cd81ec | 70 | //float maxValue; // Max FFT value is stored here |
martinsimpson | 0:6daa40cd81ec | 71 | //uint32_t maxIndex; // Index in Output array where max value is |
martinsimpson | 0:6daa40cd81ec | 72 | |
martinsimpson | 0:6daa40cd81ec | 73 | while(1) { |
martinsimpson | 0:6daa40cd81ec | 74 | timer.attach_us(&sample,30); //30us 30,30 250KHz sampling rate ******** |
martinsimpson | 0:6daa40cd81ec | 75 | |
martinsimpson | 0:6daa40cd81ec | 76 | for (i = 0; i < SAMPLES; i += 2) { |
martinsimpson | 0:6daa40cd81ec | 77 | while (trig==0){} |
martinsimpson | 0:6daa40cd81ec | 78 | trig=0; |
martinsimpson | 0:6daa40cd81ec | 79 | Input[i] = myADC.read() - 0.5f; //Real part NB removing DC offset |
martinsimpson | 0:6daa40cd81ec | 80 | Input[i + 1] = 0; //Imaginary Part set to zero |
martinsimpson | 0:6daa40cd81ec | 81 | } |
martinsimpson | 0:6daa40cd81ec | 82 | timer.detach(); |
martinsimpson | 0:6daa40cd81ec | 83 | // Init the Complex FFT module, intFlag = 0, doBitReverse = 1 |
martinsimpson | 0:6daa40cd81ec | 84 | // NB using predefined arm_cfft_sR_f32_lenXXX, in this case XXX is 256 |
martinsimpson | 0:6daa40cd81ec | 85 | arm_cfft_f32(&arm_cfft_sR_f32_len256, Input, 0, 1); |
martinsimpson | 0:6daa40cd81ec | 86 | |
martinsimpson | 0:6daa40cd81ec | 87 | // Complex Magniture Module put results into Output(Half size of the Input) |
martinsimpson | 0:6daa40cd81ec | 88 | arm_cmplx_mag_f32(Input, Output, FFT_SIZE); |
martinsimpson | 0:6daa40cd81ec | 89 | |
martinsimpson | 0:6daa40cd81ec | 90 | Output[0]=0; |
martinsimpson | 0:6daa40cd81ec | 91 | |
martinsimpson | 0:6daa40cd81ec | 92 | |
martinsimpson | 0:6daa40cd81ec | 93 | //Calculates maxValue and returns corresponding value |
martinsimpson | 0:6daa40cd81ec | 94 | arm_max_f32(Output, FFT_SIZE, &maxValue, &maxIndex); |
martinsimpson | 0:6daa40cd81ec | 95 | |
martinsimpson | 0:6daa40cd81ec | 96 | |
martinsimpson | 0:6daa40cd81ec | 97 | myDAC=1.0f; //SYNC here!! for Oscillscope at max DAC output for triggering purposes |
martinsimpson | 0:6daa40cd81ec | 98 | wait_us(20);//All FFT values will be lower since max scaling is 0.9 as below |
martinsimpson | 0:6daa40cd81ec | 99 | myDAC=0.0f;//set trigger level on oscilloscope between 0.9 to 1.0 (*3.3Volts) i.e. 3.0 to 3.3Volts |
martinsimpson | 0:6daa40cd81ec | 100 | |
martinsimpson | 0:6daa40cd81ec | 101 | for (i=2; i<FFT_SIZE/2 ; i++){ |
martinsimpson | 0:6daa40cd81ec | 102 | myDAC=(Output[i]/maxValue)*0.9f; // All Values scaled to 0.0 to 0.9 for output to DAC |
martinsimpson | 0:6daa40cd81ec | 103 | // if (Output[i]>0.2){printf("%d %f\r\n",i,(Output[i]/maxValue)*0.9f);} |
martinsimpson | 0:6daa40cd81ec | 104 | wait_us(10); |
martinsimpson | 0:6daa40cd81ec | 105 | } |
martinsimpson | 0:6daa40cd81ec | 106 | myDAC=0.0f; |
martinsimpson | 0:6daa40cd81ec | 107 | |
martinsimpson | 0:6daa40cd81ec | 108 | for (i=0; i<9;i++){ |
martinsimpson | 0:6daa40cd81ec | 109 | max7219.write_digit(1,9-i,convert_bar((uint16_t)(Output[i*16]*2.9f)));// 5.8f |
martinsimpson | 0:6daa40cd81ec | 110 | } |
martinsimpson | 0:6daa40cd81ec | 111 | } |
martinsimpson | 0:6daa40cd81ec | 112 | } |
martinsimpson | 0:6daa40cd81ec | 113 | |
martinsimpson | 0:6daa40cd81ec | 114 | // Will take a number (numVal) 0 to 255 and return (converted) the next (lower) 2^n-1 value |
martinsimpson | 0:6daa40cd81ec | 115 | // to light up all LEDS as a bar graph representation |
martinsimpson | 0:6daa40cd81ec | 116 | uint16_t convert_bar(uint16_t numVal){ |
martinsimpson | 0:6daa40cd81ec | 117 | if (numVal>255){return 0;} |
martinsimpson | 0:6daa40cd81ec | 118 | uint16_t converted = 0; |
martinsimpson | 0:6daa40cd81ec | 119 | for (uint16_t i=1; i<=256 ; i*=2){ |
martinsimpson | 0:6daa40cd81ec | 120 | if ((numVal/(i)) >= 1){converted = (i-1);} |
martinsimpson | 0:6daa40cd81ec | 121 | } |
martinsimpson | 0:6daa40cd81ec | 122 | return converted; |
martinsimpson | 0:6daa40cd81ec | 123 | } |