Audio FFT using STM32L432KC Nucleo and .96" SPI OLED

Dependencies:   Adafruit_GFX mbed

main.cpp

Committer:
ColoradoRob
Date:
2017-03-23
Revision:
1:947ee109759e
Parent:
0:ac337301f28b

File content as of revision 1:947ee109759e:

#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;
        }       
   }
}