Audio FFT using STM32L432KC Nucleo and .96" SPI OLED
Dependencies: Adafruit_GFX mbed
Diff: main.cpp
- Revision:
- 0:ac337301f28b
diff -r 000000000000 -r ac337301f28b main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Mar 23 00:36:24 2017 +0000 @@ -0,0 +1,86 @@ +#include "mbed.h" +#include "Adafruit_SSD1306.h" +#include "arm_math.h" + +DigitalOut led(LED1); +AnalogIn audio_in(PA_0); +Ticker sampler; + +SPI oled_spi(PA_7, PA_6, PA_5); +Adafruit_SSD1306_Spi oled(oled_spi, PA_11, PB_5, PB_4, 64); + +volatile int flag = 0; + +#define AMPLITUDE (1.0) // x * 3.3V +#define RANGE (32) +#define OFFSET (32) + +#define BUFFER_SIZE (128) +int16_t buffer[BUFFER_SIZE]; + +void calculate_sinewave(void); + +arm_rfft_fast_instance_f32 S; +float audio_buffer[BUFFER_SIZE * 2]; +float fft_output[BUFFER_SIZE * 2]; + +void sample() +{ + static int16_t count = 0; + if (flag) return; + audio_buffer[count++] = audio_in * 2.0f - 1.0f; + if (count == (BUFFER_SIZE * 2)) { + count = 0; + flag = 1; + } +} + +void do_fft() +{ + int32_t sum = 0; + arm_rfft_fast_f32 (&S, audio_buffer, fft_output, 0); + for (int i = 0; i != BUFFER_SIZE * 2; i += 2) { + float n = fft_output[i] * fft_output[i] + fft_output[i + 1] * fft_output[i + 1]; + buffer[i/2] = 20 * log10(n); // convert to dB + if (i != 0) sum += buffer[i/2]; // ignore DC component + } + int avg = sum / BUFFER_SIZE; + oled.printf("%+02ddB\r", avg); + buffer[0] = avg; // overwrite DC offset + for (int i = 0; i != BUFFER_SIZE; ++i) { + int offset = 48 - (buffer[i] - int(avg)); // Normalize the values + offset = std::max(0, offset); // Limit to display size + offset = std::min(63, offset); + oled.drawFastVLine(i, offset, 63, 1); + } + oled.drawFastHLine(0, 48 - avg / 2, 127, 0); + oled.drawFastHLine(0, 47 - avg / 2, 127, 0); + oled.drawFastHLine(0, 49 - avg / 2, 127, 0); + +} + + +int main() { + arm_rfft_fast_init_f32(&S , 256); + + oled_spi.frequency(8000000); + oled.begin(); + wait_ms(200); + + oled.splash(); + oled.display(); + wait(2); + oled.clearDisplay(); + + sampler.attach(sample, 1.0 / 6600.0); + + while(1) { + if (flag) { + do_fft(); + oled.display(); + oled.clearDisplay(); + led = !led; + flag = 0; + } + } +}