Proyecto que utiliza FFT para identificat tonos DTMF en la Freedom KL25Z

Dependencies:   FastAnalogIn NVIC_set_all_priorities mbed-dsp mbed

main.cpp

Committer:
henryclon
Date:
2015-12-02
Revision:
1:7655383ca5fd
Parent:
0:2ccf3099b859

File content as of revision 1:7655383ca5fd:

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

//Enrique García Sandoval A01224184
//Emmanuel Gonzalez Palacios A01228185

// Basado en el código de Frank Vannieuwkerke en KL25Z_FFT_Demo
// https://developer.mbed.org/users/frankvnk/code/KL25Z_FFT_Demo/

PwmOut myled(LED_GREEN);
Serial pc(USBTX, USBRX);
FastAnalogIn   Audio(PTC0);

////Parametros////
int SAMPLE_RATE_HZ = 4000;  
const int FFT_SIZE = 256;     

////Otras Variables para sampling y FFT////
const static arm_cfft_instance_f32 *S;
Ticker samplingTimer;
float samples[FFT_SIZE*2];
float magnitudes[FFT_SIZE];
int sampleCounter = 0;
//*********//

////Utilidades////
void printArr(int bigsize, float arr[]){ //Imprime un arreglo de valores
    int size = (bigsize/sizeof(arr[0]));
    pc.printf("\r\n [");
    int limit = size - 1;
    for (int i = 0; i < size; i++){
        i == limit ? pc.printf("%.3f", arr[i]): pc.printf("%.3f ,", arr[i]);
    }
    pc.printf("] \n");
}

int frequencyToBin(float frequency)
{
    float binFrequency = float(SAMPLE_RATE_HZ) / float(FFT_SIZE);
    return int(frequency / binFrequency);
}
//*********//

////Sampling////

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

//**********//

//Funciones para detección de DTMF//
int col1 = frequencyToBin(1209);
int col2 = frequencyToBin(1336);
int col3 = frequencyToBin(1477);
int row1 = frequencyToBin(697);
int row2 = frequencyToBin(770);
int row3 = frequencyToBin(852);
int row4 = frequencyToBin(941);
string valC1[] = {"1", "4", "7", "*"};
string valC2[] = {"2", "5", "8", "0"};
string valC3[] = {"3", "6", "9", "#"};


int maxCol(){ //Magnitud máxima en una columna
    int col = 0;
    float max = 0.0;
    if (magnitudes[col1] > max){
        max = magnitudes[col1];
        col = 1;    
    }
    if(magnitudes[col2] > max){
        max = magnitudes[col2];
        col = 2;   
    }  
    if(magnitudes[col3] > max){
        col = 3;   
    }   
    return col;
}

int maxRow(){ //Magnitud máxima en una fila
    int row = 0;
    float max = 0.0;
    if (magnitudes[row1] > max){
        max = magnitudes[row1];
        row = 1;    
    }
    if(magnitudes[row2] > max){
        max = magnitudes[row2];
        row = 2;   
    }  
    if(magnitudes[row3] > max){
        max = magnitudes[row3];
        row = 3;   
    }   
    if(magnitudes[row4] > max){
        row = 4;   
    }   
    return row;
}

string valor(){ //Determina qué tecla se presiona
    int R = maxRow() - 1;
    int C = maxCol();
    //pc.printf("Las coordenadas son: %i, %i \n", R, C); //debug
    string salida = "---";
    switch (C){
        case 1:
            salida = valC1[R];
            break;
        case 2:
            salida = valC2[R];
            break;
        case 3:
            salida = valC3[R];
            break;
    }
    return salida;
}
//**********//

int main(){
    myled = 0.995;
    
    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);
            // Restart audio sampling.
            samplingBegin();
            
            //Correr identificacion de tonos
            printf(valor().c_str());
            printf("\r\n");
        }

        
    }
}