■■■■■■■■■■ FFT_samle_01 ■■■■■■■■■■

#include "mbed.h"
#include "N5110.h"

extern "C" void fftR4(short *y, short *x, int N);

float magnitude(short y1, short y2);
void updateSamples();
void doFFT();
void printSpectrum();
void printSamples();
void ledBarGraph();
void rgbDance();
void lcdEqualiser();
int calcPeakFrequency();

AnalogIn audio(p17);  // ADC pin must be biased at Vcc/2 using coupling capacitor and potential divider
BusOut leds(LED1,LED2,LED3,LED4);
LocalFileSystem local("local");               // Create the local filesystem under the name "local"
Serial serial(USBTX,USBRX);
//    VCC,SCE,RST,D/C,MOSI,SCLK,LED
N5110 lcd(p7,p8,p9,p10,p11,p13,p21);

PwmOut red(p23);  // RGB LEDs (same connections as app board)
PwmOut green(p24);
PwmOut blue(p25);

#define BUF_LEN 1024
#define SAMP_FREQ 10000

short samples[BUF_LEN];  // store the values read from ADC
short mx[BUF_LEN*2]; // input data 16 bit, 4 byte aligned  x0r,x0i,x1r,x1i,....
short my[BUF_LEN*2]; // output data 16 bit,4 byte aligned  y0r,y0i,y1r,y1i,....
float spectrum[BUF_LEN/2];  // frequency spectrum

char buffer[14];  // screen buffer

int tone;

int main()
{
    // initialise LCD and display welcomes message
    lcd.init();
    lcd.printString("Audio FFT",14,0);
    lcd.printString("Analyser",20,1);
    lcd.printString("Craig A. Evans",0,4);

    serial.baud(115200);

    red.period(1e-4); // 10 kHz period for starters
    // setting one PWM channel sets them all as they share the same frequency

    leds = 15;
    wait(2.0);   // short pause to allow coupling capacitor to charge
    leds = 0;
    lcd.clear();

    while(1) {

        //red = 1.0,green=1.0,blue=1.0;

        updateSamples();  // read in new analog values
        doFFT();          // calc FFT
        ledBarGraph();    // display amplitude bar graph on LEDs from sample values
        lcdEqualiser();   // plot spectrum on LCD
        rgbDance();
        //printSpectrum();
        //printSamples();
        tone = calcPeakFrequency();  // calculate peak frequcny and send over serial for debug
        wait_ms(10);  // update display 100 ms

    }
}

void ledBarGraph()
{
    float rms = 0.0;  // initialse array
    for (int i = 0; i < BUF_LEN; i++) {
        rms+= samples[i]*samples[i];
    }
    // calc the sum of the squares

    rms/=BUF_LEN;     // get the mean
    rms = sqrt(rms);  // and root to get the RMS
    rms/= 16384.0;  // scale according to 16-bit signed maximum value

    // check value and update LEDs to show amplitude
    if (rms > 0.8) {
        leds = 15;
    } else if (rms > 0.6) {
        leds = 7;
    } else if (rms > 0.4) {
        leds = 3;
    } else if (rms > 0.2) {
        leds = 1;
    } else {
        leds = 0;
    }

    //serial.printf("RMS = %f\n",rms);
}

float magnitude(short y1, short y2)
{
    return sqrt(float(y1*y1+y2*y2));  // pythagoras
}

void updateSamples()
{
    for (int i = 0; i < BUF_LEN; i++) {
        samples[i] = (short) (audio.read_u16() - 0x8000);  // read unsigned 16-bit and convert to signed 16-bit (subtract 32768)
        wait_us(1e6/SAMP_FREQ);  // wait for sampling frequency, should really implement with tickers
    }
}

void doFFT()
{
    // clear buffers
    for (int i=0; i<2*BUF_LEN; i++) {
        my[i] = 0;
        mx[i] = 0;
    }

    for (int i=0; i<BUF_LEN; i++) { // load samples in array (skip imaginary input values)
        mx[i*2]=samples[i];
    }

    fftR4(my, mx, BUF_LEN);  // call FFT routine

    int j = 0;
    for (int i = 0; i < BUF_LEN; i+=2) {
        spectrum[j] = magnitude(my[i],my[i+1]);  // get magnitude of FFT output to get spectrum data
        j++;
    }
}

void printSpectrum()
{
    FILE *fp = fopen("/local/fft.csv","w");
    //now write a CSV file to filesytem of frequency vs amplitude
    int j = 0;
    for (int i = 0; i < BUF_LEN; i+=2) {
        int frequency = int(SAMP_FREQ/BUF_LEN/2*i);  // calculate value of frequency bin
        fprintf(fp, "%d,%f\n", frequency, spectrum[j]);
        j++;
    }
    fclose(fp);
}

void printSamples()
{
    FILE *fp = fopen("/local/samples.csv","w");
    //now write a CSV file to filesytem of frequency vs amplitude
    for (int i = 0; i < BUF_LEN; i++) {
        fprintf(fp, "%d\n", samples[i]);
    }
    fclose(fp);
}

int calcPeakFrequency()
{
    float max = 0.0;
    int frequency = 0;
    int j = 0;
    for (int i=0; i<BUF_LEN; i+=2) {  // loop through spectrum and look for maximum value
        if (spectrum[j] > max) {
            max = spectrum[j];
            frequency = int(SAMP_FREQ/BUF_LEN/2*i);
        }
        j++;
    }
    //serial.printf("Max = %f\n",max);
    return frequency;
}

void lcdEqualiser()
{
    // spectrum has BUF_LEN/2 values = 512
    // screen has 84 pixel, giving 6 spectrum points per pixel

    float max = 0.0;  // used for normalisation later

    float pixelValue[84];

    for (int i=0; i<84; i++) {  // loop through array
        pixelValue[i] = 0.0;

        for (int y=0; y<6; y++) {
            pixelValue[i] += spectrum[i*6+y];  // sum the 6 values in the spectrum
        }
        pixelValue[i]/=6;  // calc. average for that pixel

        if (pixelValue[i] > max)  // check for biggest value
            max = pixelValue[i];
    }

    for (int i=0; i<84; i++) {  // loop through array
        pixelValue[i]/=max;  // normalise to 1.0
    }

    lcd.clear();
    for (int i=0; i<84; i++) {  // loop through array
        for (int j=0; j<= 47 - int(pixelValue[i]*47.0); j++) {  // loop through array
            lcd.setPixel(i,j);  // draw bar graphs for spectrum bins
        }
    }
    
    sprintf(buffer,"%4u Hz",tone);
    lcd.printString(buffer,40,0); 
    lcd.refresh();

}

void rgbDance()
{

    // spectrum has BUF_LEN/2 values = 512
    // split into 3 bins for R, G and B gives 170 bins per colour

    float ledColour[3];
    float total = 0.0;

    for (int i=0; i<60; i++) {
        ledColour[0] += spectrum[i];  // sum the 6 values in the spectrum
    }
    total += ledColour[0];
    for (int i=60; i<200; i++) {
        ledColour[1] += spectrum[i];  // sum the 6 values in the spectrum
    }
    total += ledColour[1];
    for (int i=200; i<512; i++) {
        ledColour[2] += spectrum[i];  // sum the 6 values in the spectrum
    }
    total += ledColour[2];

    float r = ledColour[0]/total;
    float g = ledColour[1]/total;
    float b = ledColour[2]/total;

    serial.printf("RGB = %f , %f , %f (%f)\n",r,g,b,r+g+b);

    r = 1.0 - r;   // common anode, smaller value is brighter
    g = 1.0 - g;   // bigger value is duller
    b = 1.0 - b;

    if (r > 1.0)
        r = 1.0;
    else if (r < 0.0)
        r = 0.0;

    if (g > 1.0)
        g = 1.0;
    else if (g < 0.0)
        g = 0.0;

    if (b > 1.0)
        b = 1.0;
    else if (b < 0.0)
        b = 0.0;

    red.write(r);  // set duty cycles
    green.write(g);
    blue.write(b);

}

■■■■■■■■■■ FFT_samle_02 ■■■■■■■■■■

// Audio Spectrum Display
// Copyright 2013 Tony DiCola (tony@tonydicola.com)
// Code ported from the guide at http://learn.adafruit.com/fft-fun-with-fourier-transforms?view=all

#include "mbed.h"
#include "NVIC_set_all_priorities.h"
#include <ctype.h>
#include "arm_math.h"
#include "arm_const_structs.h"
#include "hsi2rgbw_pwm.h"
#include "FastAnalogIn.h"

Serial pc(USBTX, USBRX);

FastAnalogIn   Audio(PTC2);

//#define RGBW_ext // Disable this line when you want to use the KL25Z on-board RGB LED.

#ifndef RGBW_ext
// HSI to RGB conversion with direct output to PWM channels - on-board RGB LED
hsi2rgbw_pwm led(LED_RED, LED_GREEN, LED_BLUE);
#else
// HSI to RGBW conversion with direct output to external PWM channels - RGBW LED
hsi2rgbw_pwm led(PTD4, PTA12, PTA4, PTA5); //Red, Green, Blue, White
#endif

// Dummy ISR for disabling NMI on PTA4 - !! DO NOT REMOVE THIS !!
// More info at https://mbed.org/questions/1387/How-can-I-access-the-FTFA_FOPT-register-/
extern "C" void NMI_Handler() {
    DigitalIn test(PTA4);
}

////////////////////////////////////////////////////////////////////////////////
// CONFIGURATION
// These values can be changed to alter the behavior of the spectrum display.
// KL25Z limitations
// -----------------
// - When used with the Spectrogram python script :
//   There is a substantial time lag between the music and the screen output.
//   Max allowed SAMPLE_RATE_HZ is 40000
//   Max allowed FFT_SIZE is 64
////////////////////////////////////////////////////////////////////////////////

int SLOWDOWN = 4;                       // Create an optical delay in spectrumLoop - useful when only one RGB led is used.
                                        // Only active when nonzero.
                                        // A value >= 1000 and <= 1000 + PIXEL_COUNT fixes the output to a single frequency
                                        // window = a single color.
int SAMPLE_RATE_HZ = 40000;             // Sample rate of the audio in hertz.
float SPECTRUM_MIN_DB = 30.0;           // Audio intensity (in decibels) that maps to low LED brightness.
float SPECTRUM_MAX_DB = 80.0;           // Audio intensity (in decibels) that maps to high LED brightness.
int LEDS_ENABLED = 1;                   // Control if the LED's should display the spectrum or not.  1 is true, 0 is false.
                                        // Useful for turning the LED display on and off with commands from the serial port.
const int FFT_SIZE = 64;                // Size of the FFT.
const int PIXEL_COUNT = 32;             // Number of pixels.  You should be able to increase this without
                                        // any other changes to the program.
const int MAX_CHARS = 65;               // Max size of the input command buffer

////////////////////////////////////////////////////////////////////////////////
// INTERNAL STATE
// These shouldn't be modified unless you know what you're doing.
////////////////////////////////////////////////////////////////////////////////
const static arm_cfft_instance_f32 *S;
Ticker samplingTimer;
float samples[FFT_SIZE*2];
float magnitudes[FFT_SIZE];
int sampleCounter = 0;
char commandBuffer[MAX_CHARS];
float frequencyWindow[PIXEL_COUNT+1];
float hues[PIXEL_COUNT];
bool commandRecv = 0;
////////////////////////////////////////////////////////////////////////////////
// UTILITY FUNCTIONS
////////////////////////////////////////////////////////////////////////////////

void rxisr() {
    char c = pc.getc();
    // Add any characters that aren't the end of a command (semicolon) to the input buffer.
    if (c != ';') {
        c = toupper(c);
        strncat(commandBuffer, &c, 1);
    } else {
        // Parse the command because an end of command token was encountered.
        commandRecv = 1;
    }
}

// Compute the average magnitude of a target frequency window vs. all other frequencies.
void windowMean(float* magnitudes, int lowBin, int highBin, float* windowMean, float* otherMean)
{
    *windowMean = 0;
    *otherMean = 0;
    // Notice the first magnitude bin is skipped because it represents the
    // average power of the signal.
    for (int i = 1; i < FFT_SIZE/2; ++i) {
        if (i >= lowBin && i <= highBin) {
            *windowMean += magnitudes[i];
        } else {
            *otherMean += magnitudes[i];
        }
    }
    *windowMean /= (highBin - lowBin) + 1;
    *otherMean /= (FFT_SIZE / 2 - (highBin - lowBin));
}

// Convert a frequency to the appropriate FFT bin it will fall within.
int frequencyToBin(float frequency)
{
    float binFrequency = float(SAMPLE_RATE_HZ) / float(FFT_SIZE);
    return int(frequency / binFrequency);
}

////////////////////////////////////////////////////////////////////////////////
// SPECTRUM DISPLAY FUNCTIONS
///////////////////////////////////////////////////////////////////////////////

void spectrumSetup()
{
    // Set the frequency window values by evenly dividing the possible frequency
    // spectrum across the number of neo pixels.
    float windowSize = (SAMPLE_RATE_HZ / 2.0) / float(PIXEL_COUNT);
    for (int i = 0; i < PIXEL_COUNT+1; ++i) {
        frequencyWindow[i] = i*windowSize;
    }
    // Evenly spread hues across all pixels.
    for (int i = 0; i < PIXEL_COUNT; ++i) {
        hues[i] = 360.0*(float(i)/float(PIXEL_COUNT-1));
    }
}

void spectrumLoop()
{
    // Update each LED based on the intensity of the audio
    // in the associated frequency window.
    static int SLrpt = 0, SLpixcnt = 0;
    int SLpixend = 0;
    float intensity, otherMean;
    if(SLOWDOWN != 0)
    {
        if(SLOWDOWN >= 1000)
        {
            if(SLOWDOWN <= (1000 + PIXEL_COUNT-1))
            {
                SLpixcnt = SLOWDOWN - 1000;
                SLrpt = 0;
                SLpixend = SLpixcnt + 1;
            }
            else
                SLOWDOWN = 0;
        }
        else
        {
            SLrpt++;
            if (SLrpt >= SLOWDOWN)
            {
                SLrpt = 0;
                SLpixcnt = SLpixcnt < PIXEL_COUNT-1 ? ++SLpixcnt : 0;
            }
            SLpixend = SLpixcnt + 1;
        }
    }
    else
    {
        SLpixcnt = 0;
        SLrpt = 0;
        SLpixend = PIXEL_COUNT;
    }
    for (int i = SLpixcnt; i < SLpixend; ++i) {
        windowMean(magnitudes,
                   frequencyToBin(frequencyWindow[i]),
                   frequencyToBin(frequencyWindow[i+1]),
                   &intensity,
                   &otherMean);
        // Convert intensity to decibels.
        intensity = 20.0*log10(intensity);
        // Scale the intensity and clamp between 0 and 1.0.
        intensity -= SPECTRUM_MIN_DB;
        intensity = intensity < 0.0 ? 0.0 : intensity;
        intensity /= (SPECTRUM_MAX_DB-SPECTRUM_MIN_DB);
        intensity = intensity > 1.0 ? 1.0 : intensity;
        led.hsi2rgbw(hues[i], 1.0, intensity);
    }
}

////////////////////////////////////////////////////////////////////////////////
// SAMPLING FUNCTIONS
////////////////////////////////////////////////////////////////////////////////

void samplingCallback()
{
    // Read from the ADC and store the sample data
    samples[sampleCounter] = (1023 * Audio) - 511.0f;
    // Complex FFT functions require a coefficient for the imaginary part of the input.
    // Since we only have real data, set this coefficient to zero.
    samples[sampleCounter+1] = 0.0;
    // Update sample buffer position and stop after the buffer is filled
    sampleCounter += 2;
    if (sampleCounter >= FFT_SIZE*2) {
        samplingTimer.detach();
    }
}

void samplingBegin()
{
    // Reset sample buffer position and start callback at necessary rate.
    sampleCounter = 0;
    samplingTimer.attach_us(&samplingCallback, 1000000/SAMPLE_RATE_HZ);
}

bool samplingIsDone()
{
    return sampleCounter >= FFT_SIZE*2;
}

////////////////////////////////////////////////////////////////////////////////
// COMMAND PARSING FUNCTIONS
// These functions allow parsing simple commands input on the serial port.
// Commands allow reading and writing variables that control the device.
//
// All commands must end with a semicolon character.
//
// Example commands are:
// GET SAMPLE_RATE_HZ;
// - Get the sample rate of the device.
// SET SAMPLE_RATE_HZ 400;
// - Set the sample rate of the device to 400 hertz.
//
////////////////////////////////////////////////////////////////////////////////

void parseCommand(char* command)
{
    if (strcmp(command, "GET MAGNITUDES") == 0) {
        for (int i = 0; i < FFT_SIZE; ++i) {
            printf("%f\r\n", magnitudes[i]);
        }
    } else if (strcmp(command, "GET SAMPLES") == 0) {
        for (int i = 0; i < FFT_SIZE*2; i+=2) {
            printf("%f\r\n", samples[i]);
        }
    } else if (strcmp(command, "GET FFT_SIZE") == 0) {
        printf("%d\r\n", FFT_SIZE);
    } else if (strcmp(command, "GET SAMPLE_RATE_HZ") == 0) {
        printf("%d\r\n", SAMPLE_RATE_HZ);
    } else if (strstr(command, "SET SAMPLE_RATE_HZ") != NULL) {
        SAMPLE_RATE_HZ = (typeof(SAMPLE_RATE_HZ)) atof(command+(sizeof("SET SAMPLE_RATE_HZ")-1));
    } else if (strcmp(command, "GET LEDS_ENABLED") == 0) {
        printf("%d\r\n", LEDS_ENABLED);
    } else if (strstr(command, "SET LEDS_ENABLED") != NULL) {
        LEDS_ENABLED = (typeof(LEDS_ENABLED)) atof(command+(sizeof("SET LEDS_ENABLED")-1));
    } else if (strcmp(command, "GET SPECTRUM_MIN_DB") == 0) {
        printf("%f\r\n", SPECTRUM_MIN_DB);
    } else if (strstr(command, "SET SPECTRUM_MIN_DB") != NULL) {
        SPECTRUM_MIN_DB = (typeof(SPECTRUM_MIN_DB)) atof(command+(sizeof("SET SPECTRUM_MIN_DB")-1));
    } else if (strcmp(command, "GET SPECTRUM_MAX_DB") == 0) {
        printf("%f\r\n", SPECTRUM_MAX_DB);
    } else if (strstr(command, "SET SPECTRUM_MAX_DB") != NULL) {
        SPECTRUM_MAX_DB = (typeof(SPECTRUM_MAX_DB)) atof(command+(sizeof("SET SPECTRUM_MAX_DB")-1));
    } else if (strcmp(command, "GET SLOWDOWN") == 0) {
        printf("%d\r\n", SLOWDOWN);
    } else if (strstr(command, "SET SLOWDOWN") != NULL) {
        SLOWDOWN = (typeof(SLOWDOWN)) atoi(command+(sizeof("SET SLOWDOWN")-1));
    }

    // Update spectrum display values if sample rate was changed.
    if (strstr(command, "SET SAMPLE_RATE_HZ ") != NULL) {
        spectrumSetup();
    }

    // Turn off the LEDs if the state changed.
    if (LEDS_ENABLED == 0) {
    }
}

void parserLoop()
{
    // Process any incoming characters from the serial port
    while (pc.readable()) {
        char c = pc.getc();
        // Add any characters that aren't the end of a command (semicolon) to the input buffer.
        if (c != ';') {
            c = toupper(c);
            strncat(commandBuffer, &c, 1);
        } else {
            // Parse the command because an end of command token was encountered.
            parseCommand(commandBuffer);
            // Clear the input buffer
            memset(commandBuffer, 0, sizeof(commandBuffer));
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
// MAIN FUNCTION
////////////////////////////////////////////////////////////////////////////////

int main()
{
    NVIC_set_all_irq_priorities(1);
    NVIC_SetPriority(UART0_IRQn, 0);
    // Set up serial port.
    pc.baud (38400);
    pc.attach(&rxisr);
#ifndef RGBW_ext
    led.invertpwm(1); //On-board KL25Z RGB LED uses common anode.
#endif 
    // Clear the input command buffer
    memset(commandBuffer, 0, sizeof(commandBuffer));

    // Initialize spectrum display
    spectrumSetup();

    // Begin sampling audio
    samplingBegin();

    // Init arm_ccft_32
    switch (FFT_SIZE)
    {
    case 16:
        S = & arm_cfft_sR_f32_len16;
        break;
    case 32:
        S = & arm_cfft_sR_f32_len32;
        break;
    case 64:
        S = & arm_cfft_sR_f32_len64;
        break;
    case 128:
        S = & arm_cfft_sR_f32_len128;
        break;
    case 256:
        S = & arm_cfft_sR_f32_len256;
        break;
    case 512:
        S = & arm_cfft_sR_f32_len512;
        break;
    case 1024:
        S = & arm_cfft_sR_f32_len1024;
        break;
    case 2048:
        S = & arm_cfft_sR_f32_len2048;
        break;
    case 4096:
        S = & arm_cfft_sR_f32_len4096;
        break;
    }

    while(1) {
        // Calculate FFT if a full sample is available.
        if (samplingIsDone()) {
            // Run FFT on sample data.
            // Run FFT on sample data.
            arm_cfft_f32(S, samples, 0, 1);
            // Calculate magnitude of complex numbers output by the FFT.
            arm_cmplx_mag_f32(samples, magnitudes, FFT_SIZE);

            if (LEDS_ENABLED == 1) {
                spectrumLoop();
            }

            // Restart audio sampling.
            samplingBegin();
        }

        // Parse any pending commands.
        if(commandRecv) {
//            pc.attach(NULL);
            parseCommand(commandBuffer);
            commandRecv = 0;
            // Clear the input buffer
            memset(commandBuffer, 0, sizeof(commandBuffer));
//            pc.attach(&rxisr);
        }
    }
}

■■■■■■■■■■ FFT_samle_03 ■■■■■■■■■■

#include "mbed.h"
#include <limits.h>

DigitalOut myled(LED1);
LocalFileSystem local("local");

// code from FFTCM3.s by Ivan Mellen
// http://www.luminarymicro.com/component/option,com_joomlaboard/Itemid,92/func,view/id,1636/catid,6/
extern "C" void fftR4(short *y, short *x, int N);
extern "C" void ifftR4(short *y, short *x, int N);

// code from STM32 DSP Library
/* 64 points*/
extern "C" void cr4_fft_64_stm32(void *pssOUT, void *pssIN, uint16_t Nbin);
/* 256 points */
extern "C" void cr4_fft_256_stm32(void *pssOUT, void *pssIN, uint16_t Nbin);
/* 1024 points */
extern "C" void cr4_fft_1024_stm32(void *pssOUT, void *pssIN, uint16_t Nbin);

void test_stm32()
{
#define N 64 /*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)(real[i])) | ((uint32_t)(imag[i]<<16)));
    }
    cr4_fft_64_stm32(y, x, N); /*computes the FFT of the x[N] samples*/
    FILE* log = fopen("/local/stm32.txt","w");
    for (int i=0; i<N; i++)
    {
        fprintf(log, "%d: %d, %d -> %d, %d\n", i, real[i], imag[i], int16_t(y[i] & 0xFFFF), int16_t(y[i] >> 16));
    }
    fclose(log);    
}

void test_mellen()
{
    short x[512]; // input data 16 bit, 4 byte aligned  x0r,x0i,x1r,x1i,....
    short y[512]; // output data 16 bit,4 byte aligned  y0r,y0i,y1r,y1i,....
    short z[512]; // same format...
    
    for (int i=0;i<512;i++) x[i]=0;
    for (int i=0;i<512;i=i+8)
      { x[i+0]=16384; x[i+2]=16384;    x[i+4]=-16384;  x[i+6]=-16384;}
    // x = [ 16384,16384,-16384,-16384,16384,...]  1/4 Fsampling
    
    //call functions
    fftR4(y, x, 256);   // y is in frequency domain y[128]=
    printf("fftR4 ok\n");
    ifftR4(z, y, 256);  // z should be x/N + noise introduced by 16 bit truncating 
    printf("ifftR4 ok\n");
    FILE* log = fopen("/local/mellen.txt","w");
    for (int i=0; i<256; i++)
    {
        fprintf(log, "%d: %d -> %d -> %d\n", i, x[i], y[i], z[i]);
    }
    fclose(log);    
}

int main()
{
    printf("Testing Mellen\n");
    test_mellen();
    printf("Testing STM32\n");
    test_stm32();
    printf("Done\n");
}

■■■■■■■■■■ FFT_samle_04 ■■■■■■■■■■

// Audio Spectrum Display
// Copyright 2013 Tony DiCola (tony@tonydicola.com)
// Code ported from the guide at http://learn.adafruit.com/fft-fun-with-fourier-transforms?view=all
// mods by Tony Abbey to simplify code to drive tri-colour LED as a "colour organ"

#include "mbed.h"
#include "NVIC_set_all_priorities.h"
#include <ctype.h>
#include "arm_math.h"
#include "arm_const_structs.h"
#include "FastAnalogIn.h"

Serial pc(USBTX, USBRX);

FastAnalogIn   Audio(PTC2);

//#define RGBW_ext // Disable this line when you want to use the KL25Z on-board RGB LED.

#ifndef RGBW_ext
// RGB  direct output to PWM channels - on-board RGB LED
    PwmOut gled(LED_GREEN);
    PwmOut rled(LED_RED);
    PwmOut bled(LED_BLUE);
#else
// HSI to RGBW conversion with direct output to external PWM channels - RGBW LED
// hsi2rgbw_pwm led(PTD4, PTA12, PTA4, PTA5); //Red, Green, Blue, White
#endif

// Dummy ISR for disabling NMI on PTA4 - !! DO NOT REMOVE THIS !!
// More info at https://mbed.org/questions/1387/How-can-I-access-the-FTFA_FOPT-register-/
extern "C" void NMI_Handler() {
    DigitalIn test(PTA4);
}

////////////////////////////////////////////////////////////////////////////////
// CONFIGURATION
// These values can be changed to alter the behavior of the spectrum display.
// KL25Z limitations
// -----------------
// - When used with the Spectrogram python script :
//   There is a substantial time lag between the music and the screen output.
//   Max allowed SAMPLE_RATE_HZ is 40000
//   Max allowed FFT_SIZE is 64
////////////////////////////////////////////////////////////////////////////////

int SLOWDOWN = 4;                       // Create an optical delay in spectrumLoop - useful when only one RGB led is used.
                                        // Only active when nonzero.
                                        // A value >= 1000 and <= 1000 + PIXEL_COUNT fixes the output to a single frequency
                                        // window = a single color.
int SAMPLE_RATE_HZ = 20000;             // Sample rate of the audio in hertz.
float SPECTRUM_MIN_DB = 20.0;           // Audio intensity (in decibels) that maps to low LED brightness.
float SPECTRUM_MAX_DB = 80.0;           // Audio intensity (in decibels) that maps to high LED brightness.
int LEDS_ENABLED = 1;                   // Control if the LED's should display the spectrum or not.  1 is true, 0 is false.
                                        // Useful for turning the LED display on and off with commands from the serial port.
const int FFT_SIZE = 64;                // Size of the FFT.
const int PIXEL_COUNT = 3;             // Number of pixels (RGB LED).  You should be able to increase this without
                                        // any other changes to the program.
const int MAX_CHARS = 65;               // Max size of the input command buffer

////////////////////////////////////////////////////////////////////////////////
// INTERNAL STATE
// These shouldn't be modified unless you know what you're doing.
////////////////////////////////////////////////////////////////////////////////
const static arm_cfft_instance_f32 *S;
Ticker samplingTimer;
float samples[FFT_SIZE*2];
float magnitudes[FFT_SIZE];
int sampleCounter = 0;
char commandBuffer[MAX_CHARS];
float frequencyWindow[PIXEL_COUNT+1];
float hues[PIXEL_COUNT];
bool commandRecv = 0;
////////////////////////////////////////////////////////////////////////////////
// UTILITY FUNCTIONS
////////////////////////////////////////////////////////////////////////////////

void rxisr() {
    char c = pc.getc();
    // Add any characters that aren't the end of a command (semicolon) to the input buffer.
    if (c != ';') {
        c = toupper(c);
        strncat(commandBuffer, &c, 1);
    } else {
        // Parse the command because an end of command token was encountered.
        commandRecv = 1;
    }
}

// Compute the average magnitude of a target frequency window vs. all other frequencies.
void windowMean(float* magnitudes, int lowBin, int highBin, float* windowMean, float* otherMean)
{
    *windowMean = 0;
    *otherMean = 0;
    // Notice the first magnitude bin is skipped because it represents the
    // average power of the signal.
    for (int i = 1; i < FFT_SIZE/2; ++i) {
        if (i >= lowBin && i <= highBin) {
            *windowMean += magnitudes[i];
        } else {
            *otherMean += magnitudes[i];
        }
    }
    *windowMean /= (highBin - lowBin) + 1;
    *otherMean /= (FFT_SIZE / 2 - (highBin - lowBin));
}

// Convert a frequency to the appropriate FFT bin it will fall within.
int frequencyToBin(float frequency)
{
    float binFrequency = float(SAMPLE_RATE_HZ) / float(FFT_SIZE);
    return int(frequency / binFrequency);
}

////////////////////////////////////////////////////////////////////////////////
// SPECTRUM DISPLAY FUNCTIONS
///////////////////////////////////////////////////////////////////////////////

void spectrumSetup()
{
    // Set the frequency window values by evenly dividing the possible frequency
    // spectrum across the number of neo pixels.
    float windowSize = (SAMPLE_RATE_HZ / 2.0) / float(PIXEL_COUNT);
    for (int i = 0; i < PIXEL_COUNT+1; ++i) {
        frequencyWindow[i] = i*windowSize;
    }
 
}

void spectrumLoop()
{
    // Update each LED based on the intensity of the audio
    // in the associated frequency window.
    static int SLrpt = 0, SLpixcnt = 0;
    int SLpixend = 0;
    float intensity, otherMean;
    if(SLOWDOWN != 0)
    {
        if(SLOWDOWN >= 1000)
        {
            if(SLOWDOWN <= (1000 + PIXEL_COUNT-1))
            {
                SLpixcnt = SLOWDOWN - 1000;
                SLrpt = 0;
                SLpixend = SLpixcnt + 1;
            }
            else
                SLOWDOWN = 0;
        }
        else
        {
            SLrpt++;
            if (SLrpt >= SLOWDOWN)
            {
                SLrpt = 0;
                SLpixcnt = SLpixcnt < PIXEL_COUNT-1 ? ++SLpixcnt : 0;
            }
            SLpixend = SLpixcnt + 1;
        }
    }
    else
    {
        SLpixcnt = 0;
        SLrpt = 0;
        SLpixend = PIXEL_COUNT;
    }
    for (int i = SLpixcnt; i < SLpixend; ++i) {
        windowMean(magnitudes,
                   frequencyToBin(frequencyWindow[i]),
                   frequencyToBin(frequencyWindow[i+1]),
                   &intensity,
                   &otherMean);
        // Convert intensity to decibels.
        intensity = 20.0*log10(intensity);
        // Scale the intensity and clamp between 0 and 1.0.
        intensity -= SPECTRUM_MIN_DB;
        intensity = intensity < 0.0 ? 0.0 : intensity;
        intensity /= (SPECTRUM_MAX_DB-SPECTRUM_MIN_DB);
        intensity = intensity > 1.0 ? 1.0 : intensity;
        hues[i]=intensity;
    }
    rled=1.0-hues[0] ;  // onboard LED is common anode so inversion needed
    gled=1.0-hues[1];
    bled=1.0-hues[2];
}

////////////////////////////////////////////////////////////////////////////////
// SAMPLING FUNCTIONS
////////////////////////////////////////////////////////////////////////////////

void samplingCallback()
{
    // Read from the ADC and store the sample data
    samples[sampleCounter] = (1023 * Audio) - 511.0f;
    // Complex FFT functions require a coefficient for the imaginary part of the input.
    // Since we only have real data, set this coefficient to zero.
    samples[sampleCounter+1] = 0.0;
    // Update sample buffer position and stop after the buffer is filled
    sampleCounter += 2;
    if (sampleCounter >= FFT_SIZE*2) {
        samplingTimer.detach();
    }
}

void samplingBegin()
{
    // Reset sample buffer position and start callback at necessary rate.
    sampleCounter = 0;
    samplingTimer.attach_us(&samplingCallback, 1000000/SAMPLE_RATE_HZ);
}

bool samplingIsDone()
{
    return sampleCounter >= FFT_SIZE*2;
}

////////////////////////////////////////////////////////////////////////////////
// COMMAND PARSING FUNCTIONS
// These functions allow parsing simple commands input on the serial port.
// Commands allow reading and writing variables that control the device.
//
// All commands must end with a semicolon character.
//
// Example commands are:
// GET SAMPLE_RATE_HZ;
// - Get the sample rate of the device.
// SET SAMPLE_RATE_HZ 400;
// - Set the sample rate of the device to 400 hertz.
//
////////////////////////////////////////////////////////////////////////////////

void parseCommand(char* command)
{
    if (strcmp(command, "GET MAGNITUDES") == 0) {
        for (int i = 0; i < FFT_SIZE; ++i) {
            printf("%f\r\n", magnitudes[i]);
        }
    } else if (strcmp(command, "GET SAMPLES") == 0) {
        for (int i = 0; i < FFT_SIZE*2; i+=2) {
            printf("%f\r\n", samples[i]);
        }
    } else if (strcmp(command, "GET FFT_SIZE") == 0) {
        printf("%d\r\n", FFT_SIZE);
    } else if (strcmp(command, "GET SAMPLE_RATE_HZ") == 0) {
        printf("%d\r\n", SAMPLE_RATE_HZ);
    } else if (strstr(command, "SET SAMPLE_RATE_HZ") != NULL) {
        SAMPLE_RATE_HZ = (typeof(SAMPLE_RATE_HZ)) atof(command+(sizeof("SET SAMPLE_RATE_HZ")-1));
    } else if (strcmp(command, "GET LEDS_ENABLED") == 0) {
        printf("%d\r\n", LEDS_ENABLED);
    } else if (strstr(command, "SET LEDS_ENABLED") != NULL) {
        LEDS_ENABLED = (typeof(LEDS_ENABLED)) atof(command+(sizeof("SET LEDS_ENABLED")-1));
    } else if (strcmp(command, "GET SPECTRUM_MIN_DB") == 0) {
        printf("%f\r\n", SPECTRUM_MIN_DB);
    } else if (strstr(command, "SET SPECTRUM_MIN_DB") != NULL) {
        SPECTRUM_MIN_DB = (typeof(SPECTRUM_MIN_DB)) atof(command+(sizeof("SET SPECTRUM_MIN_DB")-1));
    } else if (strcmp(command, "GET SPECTRUM_MAX_DB") == 0) {
        printf("%f\r\n", SPECTRUM_MAX_DB);
    } else if (strstr(command, "SET SPECTRUM_MAX_DB") != NULL) {
        SPECTRUM_MAX_DB = (typeof(SPECTRUM_MAX_DB)) atof(command+(sizeof("SET SPECTRUM_MAX_DB")-1));
    } else if (strcmp(command, "GET SLOWDOWN") == 0) {
        printf("%d\r\n", SLOWDOWN);
    } else if (strstr(command, "SET SLOWDOWN") != NULL) {
        SLOWDOWN = (typeof(SLOWDOWN)) atoi(command+(sizeof("SET SLOWDOWN")-1));
    }

    // Update spectrum display values if sample rate was changed.
    if (strstr(command, "SET SAMPLE_RATE_HZ ") != NULL) {
        spectrumSetup();
    } else if (strcmp(command, "GET HUES") == 0) {
        for (int i = 0; i < PIXEL_COUNT; ++i) {
            printf("%f\r\n", hues[i]);
        }
    }
    

    // Turn off the LEDs if the state changed.
    if (LEDS_ENABLED == 0) {
    }
}

void parserLoop()
{
    // Process any incoming characters from the serial port
    while (pc.readable()) {
        char c = pc.getc();
        // (doesnt work!) printf("%c",c); // echo characters typed
        // Add any characters that aren't the end of a command (semicolon) to the input buffer.
        if (c != ';') {
            c = toupper(c);
            strncat(commandBuffer, &c, 1);
        } else {
            // Parse the command because an end of command token was encountered.
            parseCommand(commandBuffer);
            // Clear the input buffer
            memset(commandBuffer, 0, sizeof(commandBuffer));
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
// MAIN FUNCTION
////////////////////////////////////////////////////////////////////////////////

int main()
{
    NVIC_set_all_irq_priorities(1);
    NVIC_SetPriority(UART0_IRQn, 0);
    // Set up serial port.
    pc.baud (38400);
    pc.attach(&rxisr);

    // Clear the input command buffer
    memset(commandBuffer, 0, sizeof(commandBuffer));

    // Initialize spectrum display
    spectrumSetup();

    // Begin sampling audio
    samplingBegin();

    // Init arm_ccft_32
    switch (FFT_SIZE)
    {
    case 16:
        S = & arm_cfft_sR_f32_len16;
        break;
    case 32:
        S = & arm_cfft_sR_f32_len32;
        break;
    case 64:
        S = & arm_cfft_sR_f32_len64;
        break;
    case 128:
        S = & arm_cfft_sR_f32_len128;
        break;
    case 256:
        S = & arm_cfft_sR_f32_len256;
        break;
    case 512:
        S = & arm_cfft_sR_f32_len512;
        break;
    case 1024:
        S = & arm_cfft_sR_f32_len1024;
        break;
    case 2048:
        S = & arm_cfft_sR_f32_len2048;
        break;
    case 4096:
        S = & arm_cfft_sR_f32_len4096;
        break;
    }

    while(1) {
        // Calculate FFT if a full sample is available.
        if (samplingIsDone()) {
            // Run FFT on sample data.
            arm_cfft_f32(S, samples, 0, 1);
            // Calculate magnitude of complex numbers output by the FFT.
            arm_cmplx_mag_f32(samples, magnitudes, FFT_SIZE);

            if (LEDS_ENABLED == 1) {
                spectrumLoop();
            }

            // Restart audio sampling.
            samplingBegin();
        printf("this will make it work  ");
        }

        // Parse any pending commands.
        if(commandRecv) {
//            pc.attach(NULL);
            parseCommand(commandBuffer);
            commandRecv = 0;
            // Clear the input buffer
            memset(commandBuffer, 0, sizeof(commandBuffer));
//            pc.attach(&rxisr);
        }
    }
}

■■■■■■■■■■ FFT_samle_05 ■■■■■■■■■■

#include "mbed.h"

DigitalOut myled(LED1);
DigitalOut led(LED2);
DigitalOut led2(LED3);
DigitalOut led3(LED4);
const int N=1024;  // Sample number
struct TWIDDLE {  // Structure factor for calculate fft

    float cosval [N/2];
    float sinval [N/2];

};
void FFT(float datos[N], int n, TWIDDLE &w); //Declaration of functions
void enviodatos(float datos[N], int n);
Serial pc(USBTX, USBRX);  //Declaration Serial port

int main() {        //Main program
    myled.write(0);
    led.write(0);
    led2.write(0);
    led3.write(0);
    int i;        //Parameters to calculate the values of a sine function. DATOS[N]=Amp*sin(w0*t)
    float arg;
    arg=2*3.1416/N; //argument of the structure TWIDDLE
    float tm,t,w0,T, Amp;
    tm=0.1; // increments of time (0,1seg)
    t=0; //initial time
    T=2*3.1416; //Period of signal
    w0=(2*3.1416/T); // angular frequency
    Amp=3;  //Amplitude
    struct TWIDDLE W; //Declarate of a type structure

    for (i=0; i<N/2; i++) { //Calculate all the TWIDDLE factors
        W.cosval[i]= cos(i*arg);
        W.sinval[i]= -sin(i*arg);
    }

    float DATOS[N]; //array to save the sinus values
    for (i=0; i<N; i++) { //calculate the sinus values
        DATOS[i]=Amp*sin(w0*t);
        t+=tm;
    }
    led.write(1); //Execution of the program to here OK
    FFT(DATOS,N,W); //Function to calculate FFT
    enviodatos(DATOS,N); //Function to send values to serial port
    led3.write(1); //Execution of the program to here OK
    while (1); //

}

void FFT(float datos[N], int n,TWIDDLE &w) {
    float temp1, temp2, temp3,temp4;   //variables needed to calculate FFT
    int i,j,k,p;
    int upper_leg, lower_leg;
    int leg_diff;
    int num_stages=0;
    int index, step;
    float datos_real[n], datos_imag[n]; //real and imaginary values
    for (p=0; p<n; p++) {
        datos_real[p]=datos[p];
        datos_imag[p]=0;
    }
    led2.write(1); // Execution of the program to here break it if N=>2048, else OK.
    i=1;
    do {
        num_stages+=1;
        i=i*2;
    } while (i!=n);

    leg_diff=n/2;
    step=1;

    for (i=0; i<num_stages; i++) {
        index=0;
        for (j=0; j<leg_diff; j++) {
            for (upper_leg=j; upper_leg<n; upper_leg+=(2*leg_diff)) {
                lower_leg=upper_leg+leg_diff;

                temp1= (datos_real[upper_leg]+ datos_real[lower_leg]);
                temp2= (datos_real[upper_leg]- datos_real[lower_leg]);
                temp3= (datos_imag[upper_leg]+ datos_imag[lower_leg]);
                temp4= (datos_imag[upper_leg]- datos_imag[lower_leg]);
                datos_real[lower_leg]= (temp2*w.cosval[index])-(temp4*w.sinval[index]);
                datos_imag[lower_leg]= (temp2*w.sinval[index]+temp4*w.cosval[index]);
                datos_real[upper_leg]= temp1;
                datos_imag[upper_leg]= temp3;
            }
            index+=step;
        }
        leg_diff=leg_diff/2;
        step*=2;
    }
//bit reversal

    j=0;
    for (i=1; i<(N-2); i++) {
        k=n/2;
        while (k<=j) {
            j=j-k;
            k=k/2;
        }
        j=j+k;

        if (i<j) {
            temp1= datos_real[j];
            temp2= datos_imag[j];
            datos_real[j]=datos_real[i];
            datos_imag[j]=datos_imag[i];
            datos_real[i]=temp1;
            datos_imag[i]=temp2;
        }
    }

    for (i=0; i<n; i++) {

        datos[i]= pow(sqrt(pow(datos_real[i],2)+pow(datos_imag[i],2)),2); //Calculate the power fft
    };

}

void enviodatos(float datos[N],int n) {
    int i=0,j=0,k=0,aux=0; //send to serial port the values correctly.
    unsigned char bytes[4];
    float dato;

    for (i=0; i<n; i++) {
        dato=datos[i];
        aux=dato;
        for (j=0; j<4; j++) {
            switch (j) {
                case 0:
                    bytes[j]=aux;
                    aux=aux>>8;
                    break;
                case 1:
                    bytes[j]=aux;
                    aux=aux>>8;
                    break;
                case 2:
                    bytes[j]=aux;
                    aux=aux>>8;
                    break;
                case 3:
                    bytes[j]=aux;
                    aux=aux>>8;
                    break;
            }
        }
        for (k=3; k>=0; k--) {

            while (pc.writeable()==0);
            pc.putc(bytes[k]);

        }
    }
}

■■■■■■■■■■ FFT_samle_06 ■■■■■■■■■■

// Nothing special, an example for using the library of FFT, Audio Spectrum Analyzer with LCD
#include "mbed.h"
#include "FFT.h"
#include "LCD_Serial.h"
// **********************************************************************************************
#define N 32
float Data[N*2];  
unsigned char PowerInt[N/2];
volatile int kbhit;
float Average;

AnalogIn    ChannelR(p16);
AnalogIn    ChannelL(p17);
AnalogIn    ChannelC(p18);
LCDSerial myLcd(p21,p22,p23,p24); // Data, Clock, Enable, Back
// **********************************************************************************************
void vUpdateDataAnalogs(float Analogs[]);
void vGraphicDisplay(unsigned char *Data);
// **********************************************************************************************
int main() {
    myLcd.vSetBacklight(1);
    myLcd.printf("\f FFT with mbed!!!");
    wait(2.0);
    myLcd.printf("\f");
    
    Average=0;
    for(int k=0;k<64;k++){
        Average+=ChannelC.read_u16();
        wait_us(100);
    }
    Average/=64;
   
    while(1){
        vUpdateDataAnalogs(Data);
        vFFT(Data-1,N);
        vCalPowerInt(Data,PowerInt,N/2);
        vGraphicDisplay(PowerInt);
        wait_ms(30);
    }
}
// **********************************************************************************************
void vUpdate(void){
    kbhit=1;
}
void vUpdateDataAnalogs(float Analogs[]){
    unsigned short TempReadR[32],TempReadL[32];
    Ticker Period;
    
    kbhit=0;
    Period.attach_us(&vUpdate,25); // 25 us, 40.000 Hz
    for(int k=0;k<32;k++){
        while(kbhit==0);
        kbhit=0;
        TempReadR[k]=ChannelR.read_u16();
    }
    for(int k=0;k<32;k++){
        while(kbhit==0);
        kbhit=0;
        TempReadL[k]=ChannelL.read_u16();
    }
    Period.detach();
    for(int k=0,j=0;k<32;k++,j++){
        Analogs[j]=(TempReadR[k]+TempReadL[k])/2;   // Promedio (x1[n]+x2[n]=X1[k]+X2[k])
        Analogs[j]=((float)(Analogs[j]-Average)/10);   // Desplazo y aplico escala.-
        Analogs[++j]=0;
    }
    return;
}
// **********************************************************************************************
void vGraphicDisplay(unsigned char *Data){
     unsigned char k;
 
     myLcd.vGotoxy(3,1);
     for(k=0;k<16;k++,Data++){
         if(*Data>192){myLcd.vPutc((*Data-193)/8);}else{myLcd.vPutc(' ');}
     }
     myLcd.vGotoxy(3,2);
     Data-=16;
    for(k=0;k<16;k++,Data++){
         if((*Data>128)&&(*Data<193)){myLcd.vPutc((*Data-129)/8);}else if(*Data>192){myLcd.vPutc(0x07);}else{myLcd.vPutc(' ');}
     }
     myLcd.vGotoxy(3,3);
     Data-=16;
     for(k=0;k<16;k++,Data++){
         if((*Data>64)&&(*Data<129)){myLcd.vPutc((*Data-65)/8);}else if(*Data>128){myLcd.vPutc(0x07);}else{myLcd.vPutc(' ');}
     }
     myLcd.vGotoxy(3,4);
     Data-=16;
     for(k=0;k<16;k++,Data++){
         if((*Data>0)&&(*Data<65)){myLcd.vPutc((*Data-1)/8);}else if(*Data>64){myLcd.vPutc(0x07);}else{myLcd.vPutc(' ');}
     }
 
 }

■■■■■■■■■■ FFT_samle_07 ■■■■■■■■■■

#define SAMPLE_RATE   48000

#include "mbed.h"
#include "adc.h"
#include "PololuLedStrip.h"

PololuLedStrip ledStrip(p8);

#define LED_COUNT 60
rgb_color colors[LED_COUNT];

Serial pc(USBTX,USBRX);

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

//Used to change colour of LED strips
//int testX = 0;

//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];
int16_t VoltageBuffer[5000];

//Initialise ADC to maximum SAMPLE_RATE and cclk divide set to 1
ADC adc(SAMPLE_RATE, 1);

int colourVoltage=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(0.05);
    //start the interrupt and wait for about 4096 samples
    adc.interrupt_state(p20,1);
    wait(0.05);
    
        //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-------------------------
        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,....
        float mz[MN*2]; // to store the final result
        for (int i=0;i<MN*2;i++) mx[i]=0;
        for (int i=0;i<MN*2;i++) mz[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])     ) )   );          
        
        mz[i]=sqrt(float(   (my[i]*my[i])  +(my[i+1]*my[i+1])     ) ) ;
         //fprintf(mlog, "%f\n", mz[i]  );
        }
        
        // detect the change of input frequency ******************************
    float maxFreq=0;
    float max=0;
    for (int i=2;i<512;i=i+1){
           
        if(mz[i]>max){
            max = mz[i];
            maxFreq=i;
            }//end if
        
        }//end for
    //fprintf(mlog, "%d\n",maxFreq  );
    
    int maxVoltage=0;
    for (int i=0;i<512;i=i+1){
           
        if(mx[i]>maxVoltage){
            maxVoltage = mx[i];
           
            }//end if
        }//end for
    
pc.printf(" the max = %f\n",max );
pc.printf(" the maxFreq = %f\n",maxFreq );
pc.printf(" the colourValtage = %d\n", maxVoltage );

        /*for (int i = 0; i < LED_COUNT; i++){
        colors[i] = (rgb_color){ 0, 0, 0 };  
        } 
        
        if (maxFreq>60) maxFreq=60; // Limiting Length
        
         for (int i = 0; i < maxFreq; i++){
            colors[i] = (rgb_color){ abs(maxVoltage/11),abs(255-(maxVoltage/11)) ,abs(255-(maxVoltage/11)+50)  };
            }   
             ledStrip.write(colors, LED_COUNT);*/
            int actualFreq= (actual_rate/MN/2*maxFreq);
            pc.printf(" actualFreq = %d\n", actualFreq );
            
            
            //wait_ms(10);
            
            /*if (maxFreq>30){
            //testX=200;
            for (int i = 0; i < LED_COUNT; i++){
            colors[i] = (rgb_color){ 0, 20, 200 };
            }
            }

        if ((maxFreq>22)&&(maxFreq<30)){// if frequency bigger than 966Hz
            //testX= 10;
            for (int i = 0; i < LED_COUNT; i++){
            colors[i] = (rgb_color){ 250, 0, 0 };
            
            }
            }
        if (maxFreq<22){
            //testX=200;
            for (int i = 0; i < LED_COUNT; i++){
            colors[i] = (rgb_color){ 0, 250, 0 };
            }
            }*/
       
            //-----------
        
        //fclose(mlog);    
  Counter = 0;
        }// end while (1)
 
}

■■■■■■■■■■ FFT_samle_08 ■■■■■■■■■■

#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);    

}

■■■■■■■■■■ FFT_samle_09 ■■■■■■■■■■

/*
 * This is my code. It takes 16 samples of the analog in pins and writes the values back to the serial port.
 * Nathan Lasseter 2010
 */

#include "mbed.h"
#include "TextLCD.h"

extern void fft(float inarr[16], float outarr[16]);             //look for fft at link not compile time

//Serial pc(USBTX,USBRX);                                       ///dev/ttyACM0 is locked on university pc's
Serial pc(p9,p10);                                            //So I use /dev/ttyS0 instead
BusOut bargraph(p21,p22,p23,p24,p25,p26,p27,p28,p29,p30);       //Dot matrix bargraphs horizontal bus
BusOut graphs(p11,p12,p13,p14,p15,p16,p17,p18);                 //Dot matrix bargraphs vertical bus
AnalogIn   left(p19);                                           //Left channel input
AnalogIn   right(p20);                                          //Right channel input

void outputmatrix(float avg, int which) {                       //This is the simple dot matrix driver.
        switch (which) {                                        //Select a bargraph
            case 8: graphs = 0xFF;                              //8: off
            case 0: graphs = 0xFE;                              //0-7 are right to left. They turn on a bargraph by going low.
            case 1: graphs = 0xFC;
            case 2: graphs = 0xF8;
            case 3: graphs = 0xF0;
            case 4: graphs = 0xE0;
            case 5: graphs = 0xC0;
            case 6: graphs = 0x80;
            case 7: graphs = 0x00;
        }
        if (avg > 0.9) { bargraph=0x3FF; return; }              //Same principle, but set a value on the graph.
        if (avg > 0.8) { bargraph=0x1FF; return; }
        if (avg > 0.7) { bargraph=0x0FF; return; }
        if (avg > 0.6) { bargraph=0x07F; return; }
        if (avg > 0.5) { bargraph=0x03F; return; }
        if (avg > 0.4) { bargraph=0x01F; return; }
        if (avg > 0.3) { bargraph=0x00F; return; }
        if (avg > 0.2) { bargraph=0x007; return; }
        if (avg > 0.1) { bargraph=0x003; return; }
        if (avg > 0.0) { bargraph=0x001; return; }
        bargraph=0x000;                                         //Default to all off
}

int main() {                                                    //Main code
    while(1) {
        int i;
/*        float leftin[16], leftout[16];                        //While technically it can support 16 bands over each of 2 channels...
        float rightin[16], rightout[16];
        for(i=0;i<16;i++) leftin[i] = left;
        for(i=0;i<16;i++) rightin[i] = right;
        fft(leftin, leftout);
        fft(rightin, rightout); */
        float in[16], out[16], avg[8];                          //I only use 8 on one channel
        for(i=0;i<16;i++) in[i] = (left + right) / 2;           //So I average the two
        fft(in, out);
        for(i=0;i<8;i++) avg[i] = (out[2*i] + out[(2*i)+1]) / 2;    //And then average pairs of bands
/*        pc.printf("%f %f %f %f  %f %f %f %f\t%f %f %f %f  %f %f %f %f\n",
            leftout[0], leftout[1], leftout[2], leftout[3],
            leftout[4], leftout[5], leftout[6], leftout[7],
            leftout[8], leftout[9], leftout[10], leftout[11],
            leftout[12], leftout[13], leftout[14], leftout[15]);
        pc.printf("%f %f %f %f  %f %f %f %f\t%f %f %f %f  %f %f %f %f\n\n",
            rightout[0], rightout[1], rightout[2], rightout[3],
            rightout[4], rightout[5], rightout[6], rightout[7],
            rightout[8], rightout[9], rightout[10], rightout[11],
            rightout[12], rightout[13], rightout[14], rightout[15]); */
        pc.printf("%f %f %f %f\t%f %f %f %f\r\n",             //Then print the values to the uart
            avg[0], avg[1], avg[2], avg[3],
            avg[4], avg[5], avg[6], avg[7]);
        for(i=0;i<8;i++) outputmatrix(avg[i], i);               //And display on the bargrpahs
    }
}

■■■■■■■■■■ FFT_samle_10 ■■■■■■■■■■

/* 
    Novo projeto MBED_Tempo
    Criado para: 
    - calcular ValorMedio
    - Calcular Casos de OverFlow (Valores maiores que 4095 do AD)
    - Calcular Casos de UnderFlow (Valores menores que 0 do AD)
    - Calcular o tempo em ms de uma fuga.    
*/
#include <stdio.h>

#include "mbed.h"
#include "rtos.h"
#include "cmsis_os.h"
//#include "EthernetIf.h"
#include "EthernetInterface.h"
#include "Settings.h"
#include "Capture.h"
#include "Http_post.h"
//#include "CommTCP.h"
#include "SignalProcessor.h"
#include "EventDetector.h"
#include "limites.h"

//#include "TelnetServer.h"

//__attribute((section("AHBSRAM0"),aligned)) char LargeBuffer[1024]; 
EthernetInterface eth;

void thread1(void const *args)
{
    DigitalOut led1(LED1);
    int n = 0;
    //int tatual, tnovo;
    float rms[NUMBER_OF_CHANNELS], mv2[NUMBER_OF_CHANNELS];
    int under[NUMBER_OF_CHANNELS], over[NUMBER_OF_CHANNELS];
    
    Capture::Initialize();
    
    //Timer t;
    //t.start();
    //tatual = 0;
    
    while(1)
    {
        Capture::Wait();
        
        // Calcula o RMS dos 6 canais
        SignalProcessor::CalculateRMSBulk(rms, mv2, under, over);
        //printf("Tempo ms %d\n", t.read_ms());
        //t.reset();
        
        //rms[0] = 2050;
        //rms[1]=rms[2]=rms[3]=rms[4]=rms[5]=2000;
        
        for(int i=0;i<6;i++){
            //printf("Main %d\n", i);
            EventDetector::get_Detector(i).ProcessEvent(rms[i], mv2[i], under[i], over[i]);
            //wait_ms(2);
        }
        //Thread::yield();
        
        /*
        for(int i =0; i < 6; i++)
            printf("%5.2f\t", rms[i]);
        printf("\n");
        
        wait(5);
        */
        n++;
        if(n==60)
        {
            printf("%.2f %.0f %.2f %.0f\t%.2f %.0f %.2f %.0f\t%.2f %.0f %.2f %.0f\n",rms[0], mv2[0],rms[1],mv2[1],rms[2],mv2[2],rms[3],mv2[3],rms[4],mv2[4],rms[5],mv2[5]);
            led1 = !led1;            
            n=0;    
            //t.stop();
            
            /*
            tnovo = t.read_us();            
            printf("MAIN: The time XXX taken loop %d\n", tnovo - tatual);
            tatual = tnovo;
            t.reset();
            */
            //Thread::wait(1000); //1000
            wait(1);
        }
    }
}

/*
void InitializeEthernetLink()
{
    if(Settings::get_Dhcp())
        eth.init(); //Use DHCP
    else
        eth.init(Settings::get_IpAddress(),Settings::get_Netmask(),Settings::get_Gateway());
        
    eth.connect();
    printf("IP Address is %s\n", eth.getIPAddress());
}
*/
void InitializeEthernetLink()
{
    if(Settings::get_Dhcp())
        //EthernetIf::Initialize(); //Use DHCP
        eth.init(); //Use DHCP
    else
        //EthernetIf::Initialize(Settings::get_IpAddress(),Settings::get_Netmask(),Settings::get_Gateway());
        eth.init(Settings::get_IpAddress(),Settings::get_Netmask(),Settings::get_Gateway());
        
    //EthernetIf::Connect();
    eth.connect();
    //printf("IP Address is %s\n", EthernetIf::get_IpAddress());
    printf("IP Address is NEW %s\n", eth.getIPAddress());

}

int main() {
    FILE *f;
    //Set Highest Priority
    //osThreadSetPriority(osThreadGetId(),osPriorityHigh);
    
    Settings::ReadFile();    
    //printf("Passou Settings, carregou arquivo\n");
    //Settings::ShowValues();
    
    InitializeEthernetLink();
    //printf("Inicializou link Ethernet\n");
    
    //Start HTTP POST service
    Thread http_post(HttpPost::HttpPost_Thread);
    
    DisplayRAMBanks();
    
    //Start TCP daemon service
    //Thread TcpService(CommTCP::CommTCP_Thread);
    
    
    //Start Telnet Service
    //Thread telnetserver(TelnetServer::TelnetServer_Thread);
    //Start TFTP Service
    
    /*
    unsigned short vet[256] = {2105,2105,2113,2127,2127,2125,2112,2113,2130,2130,2123,2112,2112,2128,2128,2123,2112,2113,2136,2136,2374,2551,2671,2869,2887,3036,2964,2964,2964,3145,3145,3206,3209,3298,3298,3264,3261,3208,3239,3239,3197,3197,3113,3032,3065,3065,3000,2901,2943,2943,2900,2852,2844,2863,2863,2838,2764,2791,2724,2724,2668,2710,2636,2658,2658,2606,2527,2443,2434,2434,2258,2066,2061,2080,2080,2063,2055,2055,2070,2070,2064,2051,2054,2069,2069,2062,2054,2058,2066,2309,2062,2052,2054,2067,2067,2063,2051,2049,2068,2068,2060,2053,2050,2067,2066,2069,2051,2053,2070,2070,2064,2050,2053,2070,2070,2062,2052,2055,2068,2068,2065,2052,2057,2072,2072,2064,2054,2054,2072,2072,2064,2053,2052,2069,2069,2064,2052,2053,2064,2064,2062,2049,2051,2067,2067,2059,2051,2050,2068,2068,2058,2046,2050,2068,2068,2061,2052,2058,2068,2068,2059,2052,2053,2067,2067,1744,1526,1471,1289,1289,1137,1142,1055,1120,1120,997,967,894,941,941,928,887,1001,949,949,1028,1105,1079,1191,1191,1223,1211,1223,1267,1267,1325,1267,1356,1327,1327,1369,1439,1381,1498,1498,1503,1503,1527,1545,1545,1635,1650,1778,1792,1792,1971,2108,2109,2126,2126,2124,2117,2118,2131,2131,2126,2118,2118,2138,2138,2134,2124,2114,2135,2135,2129,2121,2120,2136,2136,2128,2122,2122,2143,2120,2130,2120,2121,2139,2139,2130,2119,2121,2136,2136,2129};
    float sen[12],cos[12],vm;
    SignalProcessor::CalculateFFT(vet,sen,cos,&vm,1);
    
    printf("VM = %f\n",vm);
    for(int i=0;i<12;i++)
    {
        printf("SEN%d = %f, COS%d = %f\n",i,sen[i],i,cos[i]);
    }
    */
    printf("Nova versao [8]\n\n");
    
    //printf("0x%lx\n",  LargeBuffer);
    
    //Jump to the capture routine(will run on this thread)  
    thread1(NULL);
   
    while(1){//never reaches here  
        printf("Reset\n");
        f = fopen(FILENAMERESET, "a");
        if (f == NULL)            
            f = fopen(FILENAMERESET, "w");
        fprintf(f, "Laco Errado\n");
        fclose(f);
        Thread::yield();
    }
}

■■■■■■■■■■ FFT_samle_11 ■■■■■■■■■■

#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;
    }
}