Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp@0:a497562bb2f9, 2014-07-22 (annotated)
- Committer:
- eencae
- Date:
- Tue Jul 22 15:03:32 2014 +0000
- Revision:
- 0:a497562bb2f9
- Child:
- 1:7c6c1f98b8f5
Initial version.; ; Reads in audio signal through ADC (signal needs externally biasing at Vcc/2).; ; Performs FFT on signal and extracts highest frequency component.; ; Also gets the RMS power in each set of samples and display a bar graph on the LEDs.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
eencae | 0:a497562bb2f9 | 1 | #include "mbed.h" |
eencae | 0:a497562bb2f9 | 2 | |
eencae | 0:a497562bb2f9 | 3 | extern "C" void fftR4(short *y, short *x, int N); |
eencae | 0:a497562bb2f9 | 4 | |
eencae | 0:a497562bb2f9 | 5 | float magnitude(short y1, short y2); |
eencae | 0:a497562bb2f9 | 6 | void updateSamples(); |
eencae | 0:a497562bb2f9 | 7 | void doFFT(); |
eencae | 0:a497562bb2f9 | 8 | void printSpectrum(); |
eencae | 0:a497562bb2f9 | 9 | void printSamples(); |
eencae | 0:a497562bb2f9 | 10 | void barGraph(); |
eencae | 0:a497562bb2f9 | 11 | int calcPeakFrequency(); |
eencae | 0:a497562bb2f9 | 12 | |
eencae | 0:a497562bb2f9 | 13 | AnalogIn audio(p17); |
eencae | 0:a497562bb2f9 | 14 | BusOut leds(LED1,LED2,LED3,LED4); |
eencae | 0:a497562bb2f9 | 15 | LocalFileSystem local("local"); // Create the local filesystem under the name "local" |
eencae | 0:a497562bb2f9 | 16 | Timer timer; |
eencae | 0:a497562bb2f9 | 17 | Serial serial(USBTX,USBRX); |
eencae | 0:a497562bb2f9 | 18 | |
eencae | 0:a497562bb2f9 | 19 | #define BUF_LEN 1024 |
eencae | 0:a497562bb2f9 | 20 | #define SAMP_FREQ 10000 |
eencae | 0:a497562bb2f9 | 21 | |
eencae | 0:a497562bb2f9 | 22 | short samples[BUF_LEN]; |
eencae | 0:a497562bb2f9 | 23 | short mx[BUF_LEN*2]; // input data 16 bit, 4 byte aligned x0r,x0i,x1r,x1i,.... |
eencae | 0:a497562bb2f9 | 24 | short my[BUF_LEN*2]; // output data 16 bit,4 byte aligned y0r,y0i,y1r,y1i,.... |
eencae | 0:a497562bb2f9 | 25 | float spectrum[BUF_LEN/2]; |
eencae | 0:a497562bb2f9 | 26 | |
eencae | 0:a497562bb2f9 | 27 | int main() |
eencae | 0:a497562bb2f9 | 28 | { |
eencae | 0:a497562bb2f9 | 29 | serial.baud(115200); |
eencae | 0:a497562bb2f9 | 30 | leds = 15; |
eencae | 0:a497562bb2f9 | 31 | wait(2.0); |
eencae | 0:a497562bb2f9 | 32 | leds = 0; |
eencae | 0:a497562bb2f9 | 33 | |
eencae | 0:a497562bb2f9 | 34 | int tone; |
eencae | 0:a497562bb2f9 | 35 | |
eencae | 0:a497562bb2f9 | 36 | while(1) { |
eencae | 0:a497562bb2f9 | 37 | |
eencae | 0:a497562bb2f9 | 38 | updateSamples(); |
eencae | 0:a497562bb2f9 | 39 | barGraph(); |
eencae | 0:a497562bb2f9 | 40 | doFFT(); |
eencae | 0:a497562bb2f9 | 41 | //printSpectrum(); |
eencae | 0:a497562bb2f9 | 42 | //printSamples(); |
eencae | 0:a497562bb2f9 | 43 | tone = calcPeakFrequency(); |
eencae | 0:a497562bb2f9 | 44 | serial.printf("f = %u\n",tone); |
eencae | 0:a497562bb2f9 | 45 | wait_ms(10); |
eencae | 0:a497562bb2f9 | 46 | |
eencae | 0:a497562bb2f9 | 47 | } |
eencae | 0:a497562bb2f9 | 48 | } |
eencae | 0:a497562bb2f9 | 49 | |
eencae | 0:a497562bb2f9 | 50 | void barGraph() |
eencae | 0:a497562bb2f9 | 51 | { |
eencae | 0:a497562bb2f9 | 52 | float rms = 0.0; |
eencae | 0:a497562bb2f9 | 53 | for (int i = 0; i < BUF_LEN; i++) { |
eencae | 0:a497562bb2f9 | 54 | rms+= samples[i]*samples[i]; |
eencae | 0:a497562bb2f9 | 55 | } |
eencae | 0:a497562bb2f9 | 56 | rms/=BUF_LEN; |
eencae | 0:a497562bb2f9 | 57 | rms = sqrt(rms); |
eencae | 0:a497562bb2f9 | 58 | rms/= 16384.0; // scale according to 16-bit signed maximum value |
eencae | 0:a497562bb2f9 | 59 | |
eencae | 0:a497562bb2f9 | 60 | if (rms > 0.8) { |
eencae | 0:a497562bb2f9 | 61 | leds = 15; |
eencae | 0:a497562bb2f9 | 62 | } else if (rms > 0.6) { |
eencae | 0:a497562bb2f9 | 63 | leds = 7; |
eencae | 0:a497562bb2f9 | 64 | } else if (rms > 0.4) { |
eencae | 0:a497562bb2f9 | 65 | leds = 3; |
eencae | 0:a497562bb2f9 | 66 | } else if (rms > 0.2) { |
eencae | 0:a497562bb2f9 | 67 | leds = 1; |
eencae | 0:a497562bb2f9 | 68 | } else { |
eencae | 0:a497562bb2f9 | 69 | leds = 0; |
eencae | 0:a497562bb2f9 | 70 | } |
eencae | 0:a497562bb2f9 | 71 | |
eencae | 0:a497562bb2f9 | 72 | serial.printf("RMS = %f\n",rms); |
eencae | 0:a497562bb2f9 | 73 | } |
eencae | 0:a497562bb2f9 | 74 | |
eencae | 0:a497562bb2f9 | 75 | float magnitude(short y1, short y2) |
eencae | 0:a497562bb2f9 | 76 | { |
eencae | 0:a497562bb2f9 | 77 | return sqrt(float(y1*y1+y2*y2)); |
eencae | 0:a497562bb2f9 | 78 | } |
eencae | 0:a497562bb2f9 | 79 | |
eencae | 0:a497562bb2f9 | 80 | void updateSamples() |
eencae | 0:a497562bb2f9 | 81 | { |
eencae | 0:a497562bb2f9 | 82 | for (int i = 0; i < BUF_LEN; i++) { |
eencae | 0:a497562bb2f9 | 83 | samples[i] = (short) (audio.read_u16() - 0x8000); // read unsigned 16-bit and convert to signed 16-bit (subtract 32768) |
eencae | 0:a497562bb2f9 | 84 | wait_us(1e6/SAMP_FREQ); |
eencae | 0:a497562bb2f9 | 85 | } |
eencae | 0:a497562bb2f9 | 86 | } |
eencae | 0:a497562bb2f9 | 87 | |
eencae | 0:a497562bb2f9 | 88 | void doFFT() |
eencae | 0:a497562bb2f9 | 89 | { |
eencae | 0:a497562bb2f9 | 90 | for (int i=0; i<2*BUF_LEN; i++) { |
eencae | 0:a497562bb2f9 | 91 | my[i] = 0; |
eencae | 0:a497562bb2f9 | 92 | mx[i] = 0; |
eencae | 0:a497562bb2f9 | 93 | } |
eencae | 0:a497562bb2f9 | 94 | |
eencae | 0:a497562bb2f9 | 95 | for (int i=0; i<BUF_LEN; i++) { // load samples in array (skip imaginiary input values) |
eencae | 0:a497562bb2f9 | 96 | mx[i*2]=samples[i]; |
eencae | 0:a497562bb2f9 | 97 | } |
eencae | 0:a497562bb2f9 | 98 | |
eencae | 0:a497562bb2f9 | 99 | fftR4(my, mx, BUF_LEN); // call FFT routine |
eencae | 0:a497562bb2f9 | 100 | |
eencae | 0:a497562bb2f9 | 101 | int j = 0; |
eencae | 0:a497562bb2f9 | 102 | for (int i = 0; i < BUF_LEN; i+=2) { |
eencae | 0:a497562bb2f9 | 103 | spectrum[j] = magnitude(my[i],my[i+1]); |
eencae | 0:a497562bb2f9 | 104 | j++; |
eencae | 0:a497562bb2f9 | 105 | } |
eencae | 0:a497562bb2f9 | 106 | } |
eencae | 0:a497562bb2f9 | 107 | |
eencae | 0:a497562bb2f9 | 108 | void printSpectrum() |
eencae | 0:a497562bb2f9 | 109 | { |
eencae | 0:a497562bb2f9 | 110 | FILE *fp = fopen("/local/fft.csv","w"); |
eencae | 0:a497562bb2f9 | 111 | //now write a CSV file to filesytem of frequency vs amplitude |
eencae | 0:a497562bb2f9 | 112 | int j = 0; |
eencae | 0:a497562bb2f9 | 113 | for (int i = 0; i < BUF_LEN; i+=2) { |
eencae | 0:a497562bb2f9 | 114 | int frequency = int(SAMP_FREQ/BUF_LEN/2*i); |
eencae | 0:a497562bb2f9 | 115 | fprintf(fp, "%d,%f\n", frequency, spectrum[j]); |
eencae | 0:a497562bb2f9 | 116 | j++; |
eencae | 0:a497562bb2f9 | 117 | } |
eencae | 0:a497562bb2f9 | 118 | fclose(fp); |
eencae | 0:a497562bb2f9 | 119 | } |
eencae | 0:a497562bb2f9 | 120 | |
eencae | 0:a497562bb2f9 | 121 | void printSamples() |
eencae | 0:a497562bb2f9 | 122 | { |
eencae | 0:a497562bb2f9 | 123 | FILE *fp = fopen("/local/samples.csv","w"); |
eencae | 0:a497562bb2f9 | 124 | //now write a CSV file to filesytem of frequency vs amplitude |
eencae | 0:a497562bb2f9 | 125 | for (int i = 0; i < BUF_LEN; i++) { |
eencae | 0:a497562bb2f9 | 126 | fprintf(fp, "%d\n", samples[i]); |
eencae | 0:a497562bb2f9 | 127 | } |
eencae | 0:a497562bb2f9 | 128 | fclose(fp); |
eencae | 0:a497562bb2f9 | 129 | } |
eencae | 0:a497562bb2f9 | 130 | |
eencae | 0:a497562bb2f9 | 131 | int calcPeakFrequency() |
eencae | 0:a497562bb2f9 | 132 | { |
eencae | 0:a497562bb2f9 | 133 | float max = 0.0; |
eencae | 0:a497562bb2f9 | 134 | int frequency = 0; |
eencae | 0:a497562bb2f9 | 135 | int j = 0; |
eencae | 0:a497562bb2f9 | 136 | for (int i=0; i<BUF_LEN; i+=2) { |
eencae | 0:a497562bb2f9 | 137 | if (spectrum[j] > max) { |
eencae | 0:a497562bb2f9 | 138 | max = spectrum[j]; |
eencae | 0:a497562bb2f9 | 139 | frequency = int(SAMP_FREQ/BUF_LEN/2*i); |
eencae | 0:a497562bb2f9 | 140 | } |
eencae | 0:a497562bb2f9 | 141 | j++; |
eencae | 0:a497562bb2f9 | 142 | } |
eencae | 0:a497562bb2f9 | 143 | return frequency; |
eencae | 0:a497562bb2f9 | 144 | } |