Craig Evans
/
AudioIn
Reads in audio signal on ADC, performs FFT and displays spectrum on Nokia 5110 LCD display.
Diff: main.cpp
- 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