Simplified version of FFT code - drives on-board LED as a "Colour Organ".

Dependencies:   FastAnalogIn NVIC_set_all_priorities mbed-dsp mbed

Fork of KL25Z_FFT_Demo_tony by Tony Abbey

main.cpp

Committer:
luisda130595
Date:
2016-11-15
Revision:
1:7421267b0777
Parent:
0:b8c9dffbbe7e
Child:
2:177596541c8d

File content as of revision 1:7421267b0777:

// 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"
#include <string>

FastAnalogIn   Audio(PTC2);
Serial pc(USBTX, USBRX);


//#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
////////////////////////////////////////////////////////////////////////////////
                                        // A value >= 1000 and <= 1000 + PIXEL_COUNT fixes the output to a single frequency
                                        // window = a single color.
int SAMPLE_RATE_HZ = 1000;             // Sample rate of the audio in hertz.

                                        // Useful for turning the LED display on and off with commands from the serial port.
const int FFT_SIZE = 256;                // Size of the FFT.

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

int arrayPosition;
int maxFrequencyValue;

int FFTFrequency;

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



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

////////////////////////////////////////////////////////////////////////////////
// FREQUENCY 
////////////////////////////////////////////////////////////////////////////////


void set_ArrayPosition()
{
    float maxValue = 0.0;
    
    for(int counter=0; counter < FFT_SIZE; counter++)
    {
        if(magnitudes[counter] > maxValue){
            maxValue = magnitudes[counter];
            arrayPosition = counter+1;
        }
    }
}

int get_FFTFrequency()
{
    maxFrequencyValue = SAMPLE_RATE_HZ/2;
    
    set_ArrayPosition();
    
    return (maxFrequencyValue*arrayPosition)/FFT_SIZE;
    
}
////////////////////////////////////////////////////////////////////////////////
// MAIN FUNCTION
////////////////////////////////////////////////////////////////////////////////

int main()
{
    NVIC_set_all_irq_priorities(1);
    NVIC_SetPriority(UART0_IRQn, 0);

    // 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(true) {
        // 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);
            //Obtaining the value of the frequency 
            FFTFrequency = get_FFTFrequency();
            
            for(int i=0; 
            pc.printf("Frequency is: ", FFTFrequency);
            pc.printf("\r\n [");
            
            // Restart audio sampling.
            samplingBegin();
        } 
    }
    
}