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