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

Dependencies:   mbed

Revision:
0:5b7b619f59cd
--- /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);    
+  
+        
+}
+        
+      
+      
+            
+