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

Committer:
jcobb
Date:
Sun Mar 21 18:06:46 2010 +0000
Revision:
0:5b7b619f59cd

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jcobb 0:5b7b619f59cd 1
jcobb 0:5b7b619f59cd 2 #define SAMPLE_RATE 48000
jcobb 0:5b7b619f59cd 3
jcobb 0:5b7b619f59cd 4 #include "mbed.h"
jcobb 0:5b7b619f59cd 5 #include "adc.h"
jcobb 0:5b7b619f59cd 6
jcobb 0:5b7b619f59cd 7 //Going to use the Mellen FFT rather than STM, as the STM (port by Igor) won't compile
jcobb 0:5b7b619f59cd 8 //extern "C" void cr4_fft_256_stm32(void *pssOUT, void *pssIN, uint16_t Nbin);
jcobb 0:5b7b619f59cd 9 extern "C" void fftR4(short *y, short *x, int N);
jcobb 0:5b7b619f59cd 10
jcobb 0:5b7b619f59cd 11 //use the LED as a bargraph
jcobb 0:5b7b619f59cd 12 DigitalOut l1(LED1);
jcobb 0:5b7b619f59cd 13 DigitalOut l2(LED2);
jcobb 0:5b7b619f59cd 14 DigitalOut l3(LED3);
jcobb 0:5b7b619f59cd 15 DigitalOut l4(LED4);
jcobb 0:5b7b619f59cd 16
jcobb 0:5b7b619f59cd 17 //set up a timer for timing FFT's
jcobb 0:5b7b619f59cd 18 Timer timer;
jcobb 0:5b7b619f59cd 19
jcobb 0:5b7b619f59cd 20 //Set up filesystem so we can write some useful files
jcobb 0:5b7b619f59cd 21
jcobb 0:5b7b619f59cd 22 LocalFileSystem local("local");
jcobb 0:5b7b619f59cd 23 FILE *fp;
jcobb 0:5b7b619f59cd 24
jcobb 0:5b7b619f59cd 25 //Set up a global buffer for audio data so interrupt can access it
jcobb 0:5b7b619f59cd 26 int Counter = 0;
jcobb 0:5b7b619f59cd 27 int16_t Buffer[5000];
jcobb 0:5b7b619f59cd 28
jcobb 0:5b7b619f59cd 29 //Initialise ADC to maximum SAMPLE_RATE and cclk divide set to 1
jcobb 0:5b7b619f59cd 30 ADC adc(SAMPLE_RATE, 1);
jcobb 0:5b7b619f59cd 31
jcobb 0:5b7b619f59cd 32 //Functions to write 16 bit audio data and 32 bit headers to files in au format (cf sndRecorder Cookbook)
jcobb 0:5b7b619f59cd 33 void fwrite16(uint16_t v)
jcobb 0:5b7b619f59cd 34 {
jcobb 0:5b7b619f59cd 35 uint8_t *b = (uint8_t *)&v;
jcobb 0:5b7b619f59cd 36
jcobb 0:5b7b619f59cd 37 fprintf(fp,"%c%c", b[1], b[0]);
jcobb 0:5b7b619f59cd 38 }
jcobb 0:5b7b619f59cd 39 void fwrite32(uint32_t v)
jcobb 0:5b7b619f59cd 40 {
jcobb 0:5b7b619f59cd 41 uint8_t *b = (uint8_t *)&v;
jcobb 0:5b7b619f59cd 42
jcobb 0:5b7b619f59cd 43 fprintf(fp,"%c%c%c%c", b[3], b[2], b[1], b[0]);
jcobb 0:5b7b619f59cd 44 }
jcobb 0:5b7b619f59cd 45
jcobb 0:5b7b619f59cd 46 //Our interrupt handler for audio sampling
jcobb 0:5b7b619f59cd 47 void sample_ADC(int chan, uint32_t value) {
jcobb 0:5b7b619f59cd 48
jcobb 0:5b7b619f59cd 49 float s;
jcobb 0:5b7b619f59cd 50 s = adc.read(p20);
jcobb 0:5b7b619f59cd 51 int16_t b = (s -2048)*16;
jcobb 0:5b7b619f59cd 52 Buffer[Counter] = b;
jcobb 0:5b7b619f59cd 53 Counter += 1;
jcobb 0:5b7b619f59cd 54 /* bar graph */
jcobb 0:5b7b619f59cd 55 int g = abs(s-2048);
jcobb 0:5b7b619f59cd 56 l1 = g > 0.1f*2048;
jcobb 0:5b7b619f59cd 57 l2 = g > 0.3f*2048;
jcobb 0:5b7b619f59cd 58 l3 = g > 0.6f*2048;
jcobb 0:5b7b619f59cd 59 l4 = g > 0.8f*2048;
jcobb 0:5b7b619f59cd 60 }
jcobb 0:5b7b619f59cd 61
jcobb 0:5b7b619f59cd 62 int main() {
jcobb 0:5b7b619f59cd 63
jcobb 0:5b7b619f59cd 64 //Prepare for burst mode on all ADC pins and set up interrupt handler (using ADC library from Simon Blandford
jcobb 0:5b7b619f59cd 65 adc.append(sample_ADC);
jcobb 0:5b7b619f59cd 66 adc.startmode(0,0);
jcobb 0:5b7b619f59cd 67 adc.burst(1);
jcobb 0:5b7b619f59cd 68 adc.setup(p20,1);
jcobb 0:5b7b619f59cd 69
jcobb 0:5b7b619f59cd 70 //introduce a delay as initial waveform has bias whilst decoupling cap charges
jcobb 0:5b7b619f59cd 71 wait(1);
jcobb 0:5b7b619f59cd 72
jcobb 0:5b7b619f59cd 73 //start the interrupt and wait for about 4096 samples
jcobb 0:5b7b619f59cd 74 adc.interrupt_state(p20,1);
jcobb 0:5b7b619f59cd 75 wait(0.1);
jcobb 0:5b7b619f59cd 76
jcobb 0:5b7b619f59cd 77 //Finsh up - Unset pin 20
jcobb 0:5b7b619f59cd 78 adc.interrupt_state(p20,0);
jcobb 0:5b7b619f59cd 79 adc.setup(p20,0);
jcobb 0:5b7b619f59cd 80 int actual_rate = adc.actual_sample_rate();
jcobb 0:5b7b619f59cd 81
jcobb 0:5b7b619f59cd 82 //for debugging tell the terminal sample rate and how many samples we took
jcobb 0:5b7b619f59cd 83 printf("Requested max sample rate is %u, actual max sample rate is %u.\n",
jcobb 0:5b7b619f59cd 84 SAMPLE_RATE, actual_rate);
jcobb 0:5b7b619f59cd 85 printf("We did %i samples\n",Counter);
jcobb 0:5b7b619f59cd 86
jcobb 0:5b7b619f59cd 87 //write original audio file to filesytem so we can load on PC and see what's there (cf sndRecorder Cookbook)
jcobb 0:5b7b619f59cd 88 fp = fopen("/local/out.au", "w");
jcobb 0:5b7b619f59cd 89 fprintf(fp,".snd");
jcobb 0:5b7b619f59cd 90 fwrite32(24);
jcobb 0:5b7b619f59cd 91 fwrite32(-1);
jcobb 0:5b7b619f59cd 92 fwrite32(3);
jcobb 0:5b7b619f59cd 93 fwrite32(48000);
jcobb 0:5b7b619f59cd 94 fwrite32(1);
jcobb 0:5b7b619f59cd 95 int writeCount = 0;
jcobb 0:5b7b619f59cd 96 while(writeCount <=Counter) {
jcobb 0:5b7b619f59cd 97 fwrite16(Buffer[writeCount]);
jcobb 0:5b7b619f59cd 98 writeCount+=1;
jcobb 0:5b7b619f59cd 99 }
jcobb 0:5b7b619f59cd 100
jcobb 0:5b7b619f59cd 101 //Not using the STM FFT, but leave code here for the moment
jcobb 0:5b7b619f59cd 102
jcobb 0:5b7b619f59cd 103 /*
jcobb 0:5b7b619f59cd 104 //now do a fft of the initial 1024 samples
jcobb 0:5b7b619f59cd 105 #define N 256 //Number of points
jcobb 0:5b7b619f59cd 106 uint32_t x[N], y[N]; // input and output arrays
jcobb 0:5b7b619f59cd 107 int16_t real[N], imag[N]; // real and imaginary arrays
jcobb 0:5b7b619f59cd 108 memset(real, 0, sizeof(real));
jcobb 0:5b7b619f59cd 109 memset(imag, 0, sizeof(imag));
jcobb 0:5b7b619f59cd 110 // real[1]=SHRT_MAX;
jcobb 0:5b7b619f59cd 111 // Fill the input array
jcobb 0:5b7b619f59cd 112 for (int i=0; i<N; i++)
jcobb 0:5b7b619f59cd 113 {
jcobb 0:5b7b619f59cd 114 x[i] = (((uint16_t)(Buffer[i])) | ((uint32_t)(0<<16)));
jcobb 0:5b7b619f59cd 115 }
jcobb 0:5b7b619f59cd 116 timer.reset();
jcobb 0:5b7b619f59cd 117 timer.start();
jcobb 0:5b7b619f59cd 118 cr4_fft_256_stm32(y, x, N); //computes the FFT of the x[N] samples
jcobb 0:5b7b619f59cd 119 printf("ST32 fft up took %i\n",timer.read_us());
jcobb 0:5b7b619f59cd 120 FILE* log = fopen("/local/stm32.txt","w");
jcobb 0:5b7b619f59cd 121 for (int i=0; i<N; i++)
jcobb 0:5b7b619f59cd 122 {
jcobb 0:5b7b619f59cd 123 fprintf(log, "%d: %d, %d -> %d, %d\n", i, Buffer[i], 0 , int16_t(y[i] & 0xFFFF), int16_t(y[i] >> 16));
jcobb 0:5b7b619f59cd 124 }
jcobb 0:5b7b619f59cd 125 fclose(log);
jcobb 0:5b7b619f59cd 126
jcobb 0:5b7b619f59cd 127 //compute frequencies and magnitudes of result
jcobb 0:5b7b619f59cd 128 FILE* spectrum = fopen("/local/stm32Spec.txt","w");
jcobb 0:5b7b619f59cd 129 for (int i=0; i<N/2; i++)
jcobb 0:5b7b619f59cd 130 {
jcobb 0:5b7b619f59cd 131 float real = int16_t(y[i] & 0xFFFF)* int16_t(y[i] & 0xFFFF);
jcobb 0:5b7b619f59cd 132 float imag = int16_t(y[i] >> 16)* int16_t(y[i] >> 16);
jcobb 0:5b7b619f59cd 133 fprintf(spectrum, "%d -> %f\n", int(SAMPLE_RATE/N*i),sqrt(imag+real));
jcobb 0:5b7b619f59cd 134 }
jcobb 0:5b7b619f59cd 135 fclose(spectrum);
jcobb 0:5b7b619f59cd 136 */
jcobb 0:5b7b619f59cd 137
jcobb 0:5b7b619f59cd 138 //now lets try mellen fft
jcobb 0:5b7b619f59cd 139 timer.reset();
jcobb 0:5b7b619f59cd 140 timer.start();
jcobb 0:5b7b619f59cd 141 #define MN 1024 /*Number of points*/
jcobb 0:5b7b619f59cd 142 short mx[MN*2]; // input data 16 bit, 4 byte aligned x0r,x0i,x1r,x1i,....
jcobb 0:5b7b619f59cd 143 short my[MN*2]; // output data 16 bit,4 byte aligned y0r,y0i,y1r,y1i,....
jcobb 0:5b7b619f59cd 144 for (int i=0;i<MN*2;i++) mx[i]=0;
jcobb 0:5b7b619f59cd 145 for (int i=0;i<MN;i=i+1)
jcobb 0:5b7b619f59cd 146 { mx[i*2]=Buffer[i];}
jcobb 0:5b7b619f59cd 147 printf("Mellen set up took %i\n",timer.read_us());
jcobb 0:5b7b619f59cd 148 //call functions
jcobb 0:5b7b619f59cd 149 timer.reset();
jcobb 0:5b7b619f59cd 150 timer.start();
jcobb 0:5b7b619f59cd 151 fftR4(my, mx, MN);
jcobb 0:5b7b619f59cd 152 printf("Mellen fft took %i\n",timer.read_us());
jcobb 0:5b7b619f59cd 153 FILE* mlog = fopen("/local/mellen.csv","w");
jcobb 0:5b7b619f59cd 154
jcobb 0:5b7b619f59cd 155 //now write a CSV file to filesytem of frequency vs amplitude
jcobb 0:5b7b619f59cd 156 for (int i=0; i<MN; i=i+2)
jcobb 0:5b7b619f59cd 157 {
jcobb 0:5b7b619f59cd 158 // fprintf(mlog, "%d: %d -> %d\n", i, mx[i], my[i]);
jcobb 0:5b7b619f59cd 159 fprintf(mlog, "%d,%f\n", int(actual_rate/MN/2*i),sqrt(float( (my[i]*my[i]) +(my[i+1]*my[i+1]) ) ) );
jcobb 0:5b7b619f59cd 160 }
jcobb 0:5b7b619f59cd 161 fclose(mlog);
jcobb 0:5b7b619f59cd 162
jcobb 0:5b7b619f59cd 163
jcobb 0:5b7b619f59cd 164 }
jcobb 0:5b7b619f59cd 165
jcobb 0:5b7b619f59cd 166
jcobb 0:5b7b619f59cd 167
jcobb 0:5b7b619f59cd 168
jcobb 0:5b7b619f59cd 169