This is a simple program that displays a spectrum analyzer on the Nokia LCD from an input through a 3.5mm audio jack. It uses FFT\'s to compute the fourier transform of the incoming audio signal and display the amplitudes across the screen at the different frequencies.

Dependencies:   mbed NokiaLCD

Committer:
gth646f
Date:
Mon Feb 28 03:26:53 2011 +0000
Revision:
0:b6451e68016a

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gth646f 0:b6451e68016a 1
gth646f 0:b6451e68016a 2
gth646f 0:b6451e68016a 3
gth646f 0:b6451e68016a 4
gth646f 0:b6451e68016a 5 #include "mbed.h"
gth646f 0:b6451e68016a 6 #include "adc.h"
gth646f 0:b6451e68016a 7 #include "NokiaLCD.h"
gth646f 0:b6451e68016a 8
gth646f 0:b6451e68016a 9 #define MN 256 /*Number of points*/
gth646f 0:b6451e68016a 10 #define SAMPLE_RATE 48000
gth646f 0:b6451e68016a 11 NokiaLCD lcd(p5, p7, p8, p9, NokiaLCD::LCD6610); // mosi, sclk, cs, rst, type
gth646f 0:b6451e68016a 12
gth646f 0:b6451e68016a 13
gth646f 0:b6451e68016a 14 //Going to use the Mellen FFT rather than STM, as the STM (port by Igor) won't compile
gth646f 0:b6451e68016a 15 //extern "C" void cr4_fft_256_stm32(void *pssOUT, void *pssIN, uint16_t Nbin);
gth646f 0:b6451e68016a 16 extern "C" void fftR4(short *y, short *x, int N);
gth646f 0:b6451e68016a 17
gth646f 0:b6451e68016a 18 //use the LED as a bargraph
gth646f 0:b6451e68016a 19 DigitalOut l1(LED1);
gth646f 0:b6451e68016a 20 DigitalOut l2(LED2);
gth646f 0:b6451e68016a 21 DigitalOut l3(LED3);
gth646f 0:b6451e68016a 22 DigitalOut l4(LED4);
gth646f 0:b6451e68016a 23
gth646f 0:b6451e68016a 24 //set up a timer for timing FFT's
gth646f 0:b6451e68016a 25 Timer timer;
gth646f 0:b6451e68016a 26 Ticker ticker;
gth646f 0:b6451e68016a 27
gth646f 0:b6451e68016a 28 //Set up filesystem so we can write some useful files
gth646f 0:b6451e68016a 29 LocalFileSystem local("local");
gth646f 0:b6451e68016a 30 FILE *fp;
gth646f 0:b6451e68016a 31
gth646f 0:b6451e68016a 32
gth646f 0:b6451e68016a 33 //Set up a global buffer for audio data so interrupt can access it
gth646f 0:b6451e68016a 34 int Counter = 0;
gth646f 0:b6451e68016a 35 int16_t Buffer[5000];
gth646f 0:b6451e68016a 36
gth646f 0:b6451e68016a 37
gth646f 0:b6451e68016a 38 //Initialise ADC to maximum SAMPLE_RATE and cclk divide set to 1
gth646f 0:b6451e68016a 39 ADC adc(SAMPLE_RATE, 1);
gth646f 0:b6451e68016a 40
gth646f 0:b6451e68016a 41 //Functions to write 16 bit audio data and 32 bit headers to files in au format (cf sndRecorder Cookbook)
gth646f 0:b6451e68016a 42 void fwrite16(uint16_t v) {
gth646f 0:b6451e68016a 43 uint8_t *b = (uint8_t *)&v;
gth646f 0:b6451e68016a 44
gth646f 0:b6451e68016a 45 fprintf(fp,"%c%c", b[1], b[0]);
gth646f 0:b6451e68016a 46 }
gth646f 0:b6451e68016a 47 void fwrite32(uint32_t v) {
gth646f 0:b6451e68016a 48 uint8_t *b = (uint8_t *)&v;
gth646f 0:b6451e68016a 49
gth646f 0:b6451e68016a 50 fprintf(fp,"%c%c%c%c", b[3], b[2], b[1], b[0]);
gth646f 0:b6451e68016a 51 }
gth646f 0:b6451e68016a 52
gth646f 0:b6451e68016a 53
gth646f 0:b6451e68016a 54
gth646f 0:b6451e68016a 55 //Our interrupt handler for audio sampling
gth646f 0:b6451e68016a 56 void sample_ADC(int chan, uint32_t value) {
gth646f 0:b6451e68016a 57
gth646f 0:b6451e68016a 58 float s;
gth646f 0:b6451e68016a 59 s = adc.read(p20);
gth646f 0:b6451e68016a 60 int16_t b = (s -2048)*16;
gth646f 0:b6451e68016a 61 Buffer[Counter] = b;
gth646f 0:b6451e68016a 62 Counter += 1;
gth646f 0:b6451e68016a 63 /* bar graph */
gth646f 0:b6451e68016a 64 int g = abs(s-2048);
gth646f 0:b6451e68016a 65 l1 = g > 0.1f*2048;
gth646f 0:b6451e68016a 66 l2 = g > 0.3f*2048;
gth646f 0:b6451e68016a 67 l3 = g > 0.6f*2048;
gth646f 0:b6451e68016a 68 l4 = g > 0.8f*2048;
gth646f 0:b6451e68016a 69 }
gth646f 0:b6451e68016a 70
gth646f 0:b6451e68016a 71 int main() {
gth646f 0:b6451e68016a 72
gth646f 0:b6451e68016a 73 while (1) {
gth646f 0:b6451e68016a 74 //Prepare for burst mode on all ADC pins and set up interrupt handler (using ADC library from Simon Blandford
gth646f 0:b6451e68016a 75 adc.append(sample_ADC);
gth646f 0:b6451e68016a 76 adc.startmode(0,0);
gth646f 0:b6451e68016a 77 adc.burst(1);
gth646f 0:b6451e68016a 78 adc.setup(p20,1);
gth646f 0:b6451e68016a 79 //introduce a delay as initial waveform has bias whilst decoupling cap charges
gth646f 0:b6451e68016a 80 wait(.4);
gth646f 0:b6451e68016a 81 //start the interrupt and wait for about 4096 samples
gth646f 0:b6451e68016a 82 adc.interrupt_state(p20,1);
gth646f 0:b6451e68016a 83 wait(0.1);
gth646f 0:b6451e68016a 84 //Finsh up - Unset pin 20
gth646f 0:b6451e68016a 85 adc.interrupt_state(p20,0);
gth646f 0:b6451e68016a 86 adc.setup(p20,0);
gth646f 0:b6451e68016a 87 int actual_rate = adc.actual_sample_rate();
gth646f 0:b6451e68016a 88
gth646f 0:b6451e68016a 89 //now lets try mellen fft
gth646f 0:b6451e68016a 90 lcd.background(0x0000FF);
gth646f 0:b6451e68016a 91
gth646f 0:b6451e68016a 92 short mx[MN*2]; // input data 16 bit, 4 byte aligned x0r,x0i,x1r,x1i,....
gth646f 0:b6451e68016a 93 short my[MN*2]; // output data 16 bit,4 byte aligned y0r,y0i,y1r,y1i,....
gth646f 0:b6451e68016a 94 float data2[512];
gth646f 0:b6451e68016a 95 for (int i=0;i<MN*2;i++) mx[i]=0;
gth646f 0:b6451e68016a 96
gth646f 0:b6451e68016a 97 for (int i=0;i<MN;i=i+1) {
gth646f 0:b6451e68016a 98 mx[i*2]=Buffer[i];
gth646f 0:b6451e68016a 99 }
gth646f 0:b6451e68016a 100 //FILE* mlog = fopen("/local/mellen.csv","w");
gth646f 0:b6451e68016a 101 //call functions;
gth646f 0:b6451e68016a 102 fftR4(my, mx, MN);
gth646f 0:b6451e68016a 103 for (int i=0; i<MN; i=i+2) {
gth646f 0:b6451e68016a 104 data2[i]= sqrt(float( (my[i]*my[i]) +(my[i+1]*my[i+1])));
gth646f 0:b6451e68016a 105 //fprintf(mlog, "%d,%f\n", int(actual_rate/MN/2*i),sqrt(float( (my[i]*my[i]) +(my[i+1]*my[i+1])) ) );
gth646f 0:b6451e68016a 106 }
gth646f 0:b6451e68016a 107 //fclose(mlog);
gth646f 0:b6451e68016a 108
gth646f 0:b6451e68016a 109
gth646f 0:b6451e68016a 110 //Display amplitude on Nokia LCD
gth646f 0:b6451e68016a 111 lcd.cls();
gth646f 0:b6451e68016a 112 for (int i=0; i<128; i++) {
gth646f 0:b6451e68016a 113 data2[i+1] = 20*log10(data2[i+1]);
gth646f 0:b6451e68016a 114 lcd.fill(i, 0, 2, data2[i+1], 0x00FF00);
gth646f 0:b6451e68016a 115 }
gth646f 0:b6451e68016a 116 Counter = 0;
gth646f 0:b6451e68016a 117 }
gth646f 0:b6451e68016a 118 }
gth646f 0:b6451e68016a 119
gth646f 0:b6451e68016a 120
gth646f 0:b6451e68016a 121
gth646f 0:b6451e68016a 122
gth646f 0:b6451e68016a 123