CMSIS libraries example to DAC output of NUCLEO boards (that have them e.g F429ZI) to an Oscilloscope to display frequency domain bins
main.cpp@0:05e2c9ca68e2, 2018-04-13 (annotated)
- Committer:
- martinsimpson
- Date:
- Fri Apr 13 08:59:47 2018 +0000
- Revision:
- 0:05e2c9ca68e2
1st Commit; FFT using CMSIS libraries to generate a DAC output to a front end of a basic Oscilloscope to obseverve a FFT scan with bins (see code for resolution)
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
martinsimpson | 0:05e2c9ca68e2 | 1 | #include "mbed.h" |
martinsimpson | 0:05e2c9ca68e2 | 2 | /* Include arm_math.h mathematic functions */ |
martinsimpson | 0:05e2c9ca68e2 | 3 | #include "arm_math.h" |
martinsimpson | 0:05e2c9ca68e2 | 4 | /* Include mbed-dsp libraries */ |
martinsimpson | 0:05e2c9ca68e2 | 5 | #include "arm_common_tables.h" |
martinsimpson | 0:05e2c9ca68e2 | 6 | #include "arm_const_structs.h" |
martinsimpson | 0:05e2c9ca68e2 | 7 | #include "math_helper.h" |
martinsimpson | 0:05e2c9ca68e2 | 8 | |
martinsimpson | 0:05e2c9ca68e2 | 9 | /* FFT settings */ |
martinsimpson | 0:05e2c9ca68e2 | 10 | #define SAMPLES 512 /* 256 real party and 256 imaginary parts */ |
martinsimpson | 0:05e2c9ca68e2 | 11 | #define FFT_SIZE SAMPLES / 2 /* FFT size is always the same size as we have samples, so 256 in our case */ |
martinsimpson | 0:05e2c9ca68e2 | 12 | |
martinsimpson | 0:05e2c9ca68e2 | 13 | /* Global variables */ |
martinsimpson | 0:05e2c9ca68e2 | 14 | float32_t Input[SAMPLES]; |
martinsimpson | 0:05e2c9ca68e2 | 15 | float32_t Output[FFT_SIZE]; |
martinsimpson | 0:05e2c9ca68e2 | 16 | bool trig=0; |
martinsimpson | 0:05e2c9ca68e2 | 17 | /* MBED class APIs */ |
martinsimpson | 0:05e2c9ca68e2 | 18 | DigitalOut myled(LED1); |
martinsimpson | 0:05e2c9ca68e2 | 19 | AnalogIn myADC(A1); |
martinsimpson | 0:05e2c9ca68e2 | 20 | AnalogOut myDAC(D13); |
martinsimpson | 0:05e2c9ca68e2 | 21 | Serial pc(USBTX, USBRX); |
martinsimpson | 0:05e2c9ca68e2 | 22 | Ticker timer; |
martinsimpson | 0:05e2c9ca68e2 | 23 | |
martinsimpson | 0:05e2c9ca68e2 | 24 | void sample(){ |
martinsimpson | 0:05e2c9ca68e2 | 25 | trig=1; |
martinsimpson | 0:05e2c9ca68e2 | 26 | } |
martinsimpson | 0:05e2c9ca68e2 | 27 | |
martinsimpson | 0:05e2c9ca68e2 | 28 | int main() { |
martinsimpson | 0:05e2c9ca68e2 | 29 | |
martinsimpson | 0:05e2c9ca68e2 | 30 | //arm_cfft_instance_f32 S; // ARM CFFT module |
martinsimpson | 0:05e2c9ca68e2 | 31 | float maxValue; // Max FFT value is stored here |
martinsimpson | 0:05e2c9ca68e2 | 32 | uint32_t maxIndex; // Index in Output array where max value is |
martinsimpson | 0:05e2c9ca68e2 | 33 | bool once=0; |
martinsimpson | 0:05e2c9ca68e2 | 34 | pc.baud(115200); |
martinsimpson | 0:05e2c9ca68e2 | 35 | pc.printf("Starting FFT\r\n"); |
martinsimpson | 0:05e2c9ca68e2 | 36 | while(1) { |
martinsimpson | 0:05e2c9ca68e2 | 37 | timer.attach_us(&sample,20); //20us 50KHz sampling rate |
martinsimpson | 0:05e2c9ca68e2 | 38 | for (int i = 0; i < SAMPLES; i += 2) { |
martinsimpson | 0:05e2c9ca68e2 | 39 | while (trig==0){} |
martinsimpson | 0:05e2c9ca68e2 | 40 | trig=0; |
martinsimpson | 0:05e2c9ca68e2 | 41 | Input[i] = myADC.read() - 0.5f; //Real part NB removing DC offset |
martinsimpson | 0:05e2c9ca68e2 | 42 | Input[i + 1] = 0; //Imaginary Part set to zero |
martinsimpson | 0:05e2c9ca68e2 | 43 | } |
martinsimpson | 0:05e2c9ca68e2 | 44 | timer.detach(); |
martinsimpson | 0:05e2c9ca68e2 | 45 | // Init the Complex FFT module, intFlag = 0, doBitReverse = 1 |
martinsimpson | 0:05e2c9ca68e2 | 46 | //NB using predefined arm_cfft_sR_f32_lenXXX, in this case XXX is 256 |
martinsimpson | 0:05e2c9ca68e2 | 47 | arm_cfft_f32(&arm_cfft_sR_f32_len256, Input, 0, 1); |
martinsimpson | 0:05e2c9ca68e2 | 48 | |
martinsimpson | 0:05e2c9ca68e2 | 49 | // Complex Magniture Module put results into Output(Half size of the Input) |
martinsimpson | 0:05e2c9ca68e2 | 50 | arm_cmplx_mag_f32(Input, Output, FFT_SIZE); |
martinsimpson | 0:05e2c9ca68e2 | 51 | |
martinsimpson | 0:05e2c9ca68e2 | 52 | //Calculates maxValue and returns corresponding value |
martinsimpson | 0:05e2c9ca68e2 | 53 | arm_max_f32(Output, FFT_SIZE, &maxValue, &maxIndex); |
martinsimpson | 0:05e2c9ca68e2 | 54 | |
martinsimpson | 0:05e2c9ca68e2 | 55 | if (once==0){ |
martinsimpson | 0:05e2c9ca68e2 | 56 | pc.printf("Maximum is %f\r\n",maxValue); |
martinsimpson | 0:05e2c9ca68e2 | 57 | once = 1; |
martinsimpson | 0:05e2c9ca68e2 | 58 | } |
martinsimpson | 0:05e2c9ca68e2 | 59 | |
martinsimpson | 0:05e2c9ca68e2 | 60 | //maxValue /= 100.0f; |
martinsimpson | 0:05e2c9ca68e2 | 61 | |
martinsimpson | 0:05e2c9ca68e2 | 62 | myDAC=1.0f; //SYNC Pulse to DAC Output |
martinsimpson | 0:05e2c9ca68e2 | 63 | wait_us(20); //Used on Oscilliscope set trigger level to the highest |
martinsimpson | 0:05e2c9ca68e2 | 64 | myDAC=0.0f; //point on this pulse (all FFT data will be scaled |
martinsimpson | 0:05e2c9ca68e2 | 65 | //90% of Max Value |
martinsimpson | 0:05e2c9ca68e2 | 66 | |
martinsimpson | 0:05e2c9ca68e2 | 67 | for (int i=0; i<FFT_SIZE/2 ; i++){ |
martinsimpson | 0:05e2c9ca68e2 | 68 | myDAC=(Output[i]/maxValue)*0.9f; // Scale to Max Value and scale to 90% |
martinsimpson | 0:05e2c9ca68e2 | 69 | wait_us(10); //Each pulse of 10us is 50KHz/256 = 195Hz resolution |
martinsimpson | 0:05e2c9ca68e2 | 70 | } |
martinsimpson | 0:05e2c9ca68e2 | 71 | myDAC=0.0f; |
martinsimpson | 0:05e2c9ca68e2 | 72 | } |
martinsimpson | 0:05e2c9ca68e2 | 73 | } |