Read an audio signal from the ADC, write it out to a file on the filestytem and perform a 1024 point FFT, writing frequency data to a csv file
Diff: main.cpp
- Revision:
- 0:5b7b619f59cd
diff -r 000000000000 -r 5b7b619f59cd main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun Mar 21 18:06:46 2010 +0000 @@ -0,0 +1,169 @@ + +#define SAMPLE_RATE 48000 + +#include "mbed.h" +#include "adc.h" + +//Going to use the Mellen FFT rather than STM, as the STM (port by Igor) won't compile +//extern "C" void cr4_fft_256_stm32(void *pssOUT, void *pssIN, uint16_t Nbin); +extern "C" void fftR4(short *y, short *x, int N); + +//use the LED as a bargraph +DigitalOut l1(LED1); +DigitalOut l2(LED2); +DigitalOut l3(LED3); +DigitalOut l4(LED4); + +//set up a timer for timing FFT's +Timer timer; + +//Set up filesystem so we can write some useful files + +LocalFileSystem local("local"); +FILE *fp; + +//Set up a global buffer for audio data so interrupt can access it +int Counter = 0; +int16_t Buffer[5000]; + +//Initialise ADC to maximum SAMPLE_RATE and cclk divide set to 1 +ADC adc(SAMPLE_RATE, 1); + +//Functions to write 16 bit audio data and 32 bit headers to files in au format (cf sndRecorder Cookbook) +void fwrite16(uint16_t v) +{ + uint8_t *b = (uint8_t *)&v; + + fprintf(fp,"%c%c", b[1], b[0]); +} +void fwrite32(uint32_t v) +{ + uint8_t *b = (uint8_t *)&v; + + fprintf(fp,"%c%c%c%c", b[3], b[2], b[1], b[0]); +} + +//Our interrupt handler for audio sampling +void sample_ADC(int chan, uint32_t value) { + + float s; + s = adc.read(p20); + int16_t b = (s -2048)*16; + Buffer[Counter] = b; + Counter += 1; + /* bar graph */ + int g = abs(s-2048); + l1 = g > 0.1f*2048; + l2 = g > 0.3f*2048; + l3 = g > 0.6f*2048; + l4 = g > 0.8f*2048; +} + +int main() { + + //Prepare for burst mode on all ADC pins and set up interrupt handler (using ADC library from Simon Blandford + adc.append(sample_ADC); + adc.startmode(0,0); + adc.burst(1); + adc.setup(p20,1); + + //introduce a delay as initial waveform has bias whilst decoupling cap charges + wait(1); + + //start the interrupt and wait for about 4096 samples + adc.interrupt_state(p20,1); + wait(0.1); + + //Finsh up - Unset pin 20 + adc.interrupt_state(p20,0); + adc.setup(p20,0); + int actual_rate = adc.actual_sample_rate(); + + //for debugging tell the terminal sample rate and how many samples we took + printf("Requested max sample rate is %u, actual max sample rate is %u.\n", + SAMPLE_RATE, actual_rate); + printf("We did %i samples\n",Counter); + + //write original audio file to filesytem so we can load on PC and see what's there (cf sndRecorder Cookbook) + fp = fopen("/local/out.au", "w"); + fprintf(fp,".snd"); + fwrite32(24); + fwrite32(-1); + fwrite32(3); + fwrite32(48000); + fwrite32(1); + int writeCount = 0; + while(writeCount <=Counter) { + fwrite16(Buffer[writeCount]); + writeCount+=1; + } + + //Not using the STM FFT, but leave code here for the moment + + /* + //now do a fft of the initial 1024 samples + #define N 256 //Number of points + uint32_t x[N], y[N]; // input and output arrays + int16_t real[N], imag[N]; // real and imaginary arrays + memset(real, 0, sizeof(real)); + memset(imag, 0, sizeof(imag)); + // real[1]=SHRT_MAX; + // Fill the input array + for (int i=0; i<N; i++) + { + x[i] = (((uint16_t)(Buffer[i])) | ((uint32_t)(0<<16))); + } + timer.reset(); + timer.start(); + cr4_fft_256_stm32(y, x, N); //computes the FFT of the x[N] samples + printf("ST32 fft up took %i\n",timer.read_us()); + FILE* log = fopen("/local/stm32.txt","w"); + for (int i=0; i<N; i++) + { + fprintf(log, "%d: %d, %d -> %d, %d\n", i, Buffer[i], 0 , int16_t(y[i] & 0xFFFF), int16_t(y[i] >> 16)); + } + fclose(log); + + //compute frequencies and magnitudes of result + FILE* spectrum = fopen("/local/stm32Spec.txt","w"); + for (int i=0; i<N/2; i++) + { + float real = int16_t(y[i] & 0xFFFF)* int16_t(y[i] & 0xFFFF); + float imag = int16_t(y[i] >> 16)* int16_t(y[i] >> 16); + fprintf(spectrum, "%d -> %f\n", int(SAMPLE_RATE/N*i),sqrt(imag+real)); + } + fclose(spectrum); + */ + + //now lets try mellen fft + timer.reset(); + timer.start(); + #define MN 1024 /*Number of points*/ + short mx[MN*2]; // input data 16 bit, 4 byte aligned x0r,x0i,x1r,x1i,.... + short my[MN*2]; // output data 16 bit,4 byte aligned y0r,y0i,y1r,y1i,.... + for (int i=0;i<MN*2;i++) mx[i]=0; + for (int i=0;i<MN;i=i+1) + { mx[i*2]=Buffer[i];} + printf("Mellen set up took %i\n",timer.read_us()); + //call functions + timer.reset(); + timer.start(); + fftR4(my, mx, MN); + printf("Mellen fft took %i\n",timer.read_us()); + FILE* mlog = fopen("/local/mellen.csv","w"); + + //now write a CSV file to filesytem of frequency vs amplitude + for (int i=0; i<MN; i=i+2) + { + // fprintf(mlog, "%d: %d -> %d\n", i, mx[i], my[i]); + fprintf(mlog, "%d,%f\n", int(actual_rate/MN/2*i),sqrt(float( (my[i]*my[i]) +(my[i+1]*my[i+1]) ) ) ); + } + fclose(mlog); + + +} + + + + +