Audio FFT using STM32L432KC Nucleo and .96" SPI OLED

Dependencies:   Adafruit_GFX mbed

Committer:
ColoradoRob
Date:
Thu Mar 23 00:42:09 2017 +0000
Revision:
1:947ee109759e
Parent:
0:ac337301f28b
Initial commit.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ColoradoRob 0:ac337301f28b 1 #include "mbed.h"
ColoradoRob 0:ac337301f28b 2 #include "Adafruit_SSD1306.h"
ColoradoRob 0:ac337301f28b 3 #include "arm_math.h"
ColoradoRob 0:ac337301f28b 4
ColoradoRob 0:ac337301f28b 5 DigitalOut led(LED1);
ColoradoRob 0:ac337301f28b 6 AnalogIn audio_in(PA_0);
ColoradoRob 0:ac337301f28b 7 Ticker sampler;
ColoradoRob 0:ac337301f28b 8
ColoradoRob 0:ac337301f28b 9 SPI oled_spi(PA_7, PA_6, PA_5);
ColoradoRob 0:ac337301f28b 10 Adafruit_SSD1306_Spi oled(oled_spi, PA_11, PB_5, PB_4, 64);
ColoradoRob 0:ac337301f28b 11
ColoradoRob 0:ac337301f28b 12 volatile int flag = 0;
ColoradoRob 0:ac337301f28b 13
ColoradoRob 0:ac337301f28b 14 #define AMPLITUDE (1.0) // x * 3.3V
ColoradoRob 0:ac337301f28b 15 #define RANGE (32)
ColoradoRob 0:ac337301f28b 16 #define OFFSET (32)
ColoradoRob 0:ac337301f28b 17
ColoradoRob 0:ac337301f28b 18 #define BUFFER_SIZE (128)
ColoradoRob 0:ac337301f28b 19 int16_t buffer[BUFFER_SIZE];
ColoradoRob 0:ac337301f28b 20
ColoradoRob 0:ac337301f28b 21 void calculate_sinewave(void);
ColoradoRob 0:ac337301f28b 22
ColoradoRob 0:ac337301f28b 23 arm_rfft_fast_instance_f32 S;
ColoradoRob 0:ac337301f28b 24 float audio_buffer[BUFFER_SIZE * 2];
ColoradoRob 0:ac337301f28b 25 float fft_output[BUFFER_SIZE * 2];
ColoradoRob 0:ac337301f28b 26
ColoradoRob 0:ac337301f28b 27 void sample()
ColoradoRob 0:ac337301f28b 28 {
ColoradoRob 0:ac337301f28b 29 static int16_t count = 0;
ColoradoRob 0:ac337301f28b 30 if (flag) return;
ColoradoRob 0:ac337301f28b 31 audio_buffer[count++] = audio_in * 2.0f - 1.0f;
ColoradoRob 0:ac337301f28b 32 if (count == (BUFFER_SIZE * 2)) {
ColoradoRob 0:ac337301f28b 33 count = 0;
ColoradoRob 0:ac337301f28b 34 flag = 1;
ColoradoRob 0:ac337301f28b 35 }
ColoradoRob 0:ac337301f28b 36 }
ColoradoRob 0:ac337301f28b 37
ColoradoRob 0:ac337301f28b 38 void do_fft()
ColoradoRob 0:ac337301f28b 39 {
ColoradoRob 0:ac337301f28b 40 int32_t sum = 0;
ColoradoRob 0:ac337301f28b 41 arm_rfft_fast_f32 (&S, audio_buffer, fft_output, 0);
ColoradoRob 0:ac337301f28b 42 for (int i = 0; i != BUFFER_SIZE * 2; i += 2) {
ColoradoRob 0:ac337301f28b 43 float n = fft_output[i] * fft_output[i] + fft_output[i + 1] * fft_output[i + 1];
ColoradoRob 0:ac337301f28b 44 buffer[i/2] = 20 * log10(n); // convert to dB
ColoradoRob 0:ac337301f28b 45 if (i != 0) sum += buffer[i/2]; // ignore DC component
ColoradoRob 0:ac337301f28b 46 }
ColoradoRob 0:ac337301f28b 47 int avg = sum / BUFFER_SIZE;
ColoradoRob 0:ac337301f28b 48 oled.printf("%+02ddB\r", avg);
ColoradoRob 0:ac337301f28b 49 buffer[0] = avg; // overwrite DC offset
ColoradoRob 0:ac337301f28b 50 for (int i = 0; i != BUFFER_SIZE; ++i) {
ColoradoRob 0:ac337301f28b 51 int offset = 48 - (buffer[i] - int(avg)); // Normalize the values
ColoradoRob 0:ac337301f28b 52 offset = std::max(0, offset); // Limit to display size
ColoradoRob 0:ac337301f28b 53 offset = std::min(63, offset);
ColoradoRob 0:ac337301f28b 54 oled.drawFastVLine(i, offset, 63, 1);
ColoradoRob 0:ac337301f28b 55 }
ColoradoRob 0:ac337301f28b 56 oled.drawFastHLine(0, 48 - avg / 2, 127, 0);
ColoradoRob 0:ac337301f28b 57 oled.drawFastHLine(0, 47 - avg / 2, 127, 0);
ColoradoRob 0:ac337301f28b 58 oled.drawFastHLine(0, 49 - avg / 2, 127, 0);
ColoradoRob 0:ac337301f28b 59
ColoradoRob 0:ac337301f28b 60 }
ColoradoRob 0:ac337301f28b 61
ColoradoRob 0:ac337301f28b 62
ColoradoRob 0:ac337301f28b 63 int main() {
ColoradoRob 0:ac337301f28b 64 arm_rfft_fast_init_f32(&S , 256);
ColoradoRob 0:ac337301f28b 65
ColoradoRob 0:ac337301f28b 66 oled_spi.frequency(8000000);
ColoradoRob 0:ac337301f28b 67 oled.begin();
ColoradoRob 0:ac337301f28b 68 wait_ms(200);
ColoradoRob 0:ac337301f28b 69
ColoradoRob 0:ac337301f28b 70 oled.splash();
ColoradoRob 0:ac337301f28b 71 oled.display();
ColoradoRob 0:ac337301f28b 72 wait(2);
ColoradoRob 0:ac337301f28b 73 oled.clearDisplay();
ColoradoRob 0:ac337301f28b 74
ColoradoRob 0:ac337301f28b 75 sampler.attach(sample, 1.0 / 6600.0);
ColoradoRob 0:ac337301f28b 76
ColoradoRob 0:ac337301f28b 77 while(1) {
ColoradoRob 0:ac337301f28b 78 if (flag) {
ColoradoRob 0:ac337301f28b 79 do_fft();
ColoradoRob 0:ac337301f28b 80 oled.display();
ColoradoRob 0:ac337301f28b 81 oled.clearDisplay();
ColoradoRob 0:ac337301f28b 82 led = !led;
ColoradoRob 0:ac337301f28b 83 flag = 0;
ColoradoRob 0:ac337301f28b 84 }
ColoradoRob 0:ac337301f28b 85 }
ColoradoRob 0:ac337301f28b 86 }