Reads in audio signal on ADC, performs FFT and displays spectrum on Nokia 5110 LCD display.

Dependencies:   N5110 mbed

Revision:
0:a497562bb2f9
Child:
1:7c6c1f98b8f5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jul 22 15:03:32 2014 +0000
@@ -0,0 +1,144 @@
+#include "mbed.h"
+
+extern "C" void fftR4(short *y, short *x, int N);
+
+float magnitude(short y1, short y2);
+void updateSamples();
+void doFFT();
+void printSpectrum();
+void printSamples();
+void barGraph();
+int calcPeakFrequency();
+
+AnalogIn audio(p17);
+BusOut leds(LED1,LED2,LED3,LED4);
+LocalFileSystem local("local");               // Create the local filesystem under the name "local"
+Timer timer;
+Serial serial(USBTX,USBRX);
+
+#define BUF_LEN 1024
+#define SAMP_FREQ 10000
+
+short samples[BUF_LEN];
+short mx[BUF_LEN*2]; // input data 16 bit, 4 byte aligned  x0r,x0i,x1r,x1i,....
+short my[BUF_LEN*2]; // output data 16 bit,4 byte aligned  y0r,y0i,y1r,y1i,....
+float spectrum[BUF_LEN/2];
+
+int main()
+{
+    serial.baud(115200);
+    leds = 15;
+    wait(2.0);
+    leds = 0;
+
+    int tone;
+
+    while(1) {
+
+        updateSamples();
+        barGraph();
+        doFFT();
+        //printSpectrum();
+        //printSamples();
+        tone = calcPeakFrequency();
+        serial.printf("f = %u\n",tone);
+        wait_ms(10);
+
+    }
+}
+
+void barGraph()
+{
+    float rms = 0.0;
+    for (int i = 0; i < BUF_LEN; i++) {
+        rms+= samples[i]*samples[i];
+    }
+    rms/=BUF_LEN;
+    rms = sqrt(rms);
+    rms/= 16384.0;  // scale according to 16-bit signed maximum value
+
+    if (rms > 0.8) {
+        leds = 15;
+    } else if (rms > 0.6) {
+        leds = 7;
+    } else if (rms > 0.4) {
+        leds = 3;
+    } else if (rms > 0.2) {
+        leds = 1;
+    } else {
+        leds = 0;
+    }
+
+    serial.printf("RMS = %f\n",rms);
+}
+
+float magnitude(short y1, short y2)
+{
+    return sqrt(float(y1*y1+y2*y2));
+}
+
+void updateSamples()
+{
+    for (int i = 0; i < BUF_LEN; i++) {
+        samples[i] = (short) (audio.read_u16() - 0x8000);  // read unsigned 16-bit and convert to signed 16-bit (subtract 32768)
+        wait_us(1e6/SAMP_FREQ);
+    }
+}
+
+void doFFT()
+{
+    for (int i=0; i<2*BUF_LEN; i++) {
+        my[i] = 0;
+        mx[i] = 0;
+    }
+
+    for (int i=0; i<BUF_LEN; i++) { // load samples in array (skip imaginiary input values)
+        mx[i*2]=samples[i];
+    }
+
+    fftR4(my, mx, BUF_LEN);  // call FFT routine
+
+    int j = 0;
+    for (int i = 0; i < BUF_LEN; i+=2) {
+        spectrum[j] = magnitude(my[i],my[i+1]);
+        j++;
+    }
+}
+
+void printSpectrum()
+{
+    FILE *fp = fopen("/local/fft.csv","w");
+    //now write a CSV file to filesytem of frequency vs amplitude
+    int j = 0;
+    for (int i = 0; i < BUF_LEN; i+=2) {
+        int frequency = int(SAMP_FREQ/BUF_LEN/2*i);
+        fprintf(fp, "%d,%f\n", frequency, spectrum[j]);
+        j++;
+    }
+    fclose(fp);
+}
+
+void printSamples()
+{
+    FILE *fp = fopen("/local/samples.csv","w");
+    //now write a CSV file to filesytem of frequency vs amplitude
+    for (int i = 0; i < BUF_LEN; i++) {
+        fprintf(fp, "%d\n", samples[i]);
+    }
+    fclose(fp);
+}
+
+int calcPeakFrequency()
+{
+    float max = 0.0;
+    int frequency = 0;
+    int j = 0;
+    for (int i=0; i<BUF_LEN; i+=2) {
+        if (spectrum[j] > max) {
+            max = spectrum[j];
+            frequency = int(SAMP_FREQ/BUF_LEN/2*i);
+        }
+        j++;
+    }
+    return frequency;
+}
\ No newline at end of file