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

main.cpp

Committer:
gth646f
Date:
2011-02-28
Revision:
0:b6451e68016a

File content as of revision 0:b6451e68016a:





#include "mbed.h"
#include "adc.h"
#include "NokiaLCD.h"

#define MN 256 /*Number of points*/
#define SAMPLE_RATE   48000
NokiaLCD lcd(p5, p7, p8, p9, NokiaLCD::LCD6610); // mosi, sclk, cs, rst, type


//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;
Ticker ticker;

//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() {

    while (1) {
        //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(.4);
        //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();

        //now lets try mellen fft
        lcd.background(0x0000FF);

        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,....
        float data2[512];
        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];
        }
        //FILE* mlog = fopen("/local/mellen.csv","w");
        //call functions;
        fftR4(my, mx, MN);
        for (int i=0; i<MN; i=i+2) {
            data2[i]= sqrt(float(   (my[i]*my[i])  +(my[i+1]*my[i+1])));
            //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);


        //Display amplitude on Nokia LCD
        lcd.cls();
        for (int i=0; i<128; i++) {
            data2[i+1] = 20*log10(data2[i+1]);
            lcd.fill(i, 0, 2, data2[i+1], 0x00FF00);
        }
        Counter = 0;
    }
}