Generates vibe wave from DAC; Record signal from ADC;Computes envelope; compute FFT; Plot results (graph or frequency of maximal value) Original code from Martin Simpson.

Dependencies:   mbed-dsp

main.cpp

Committer:
guicat
Date:
2019-01-29
Revision:
2:7945f79d7c8e
Parent:
1:4a666bd3fef6

File content as of revision 2:7945f79d7c8e:

/*
Original code from MARTIN SIMPSON : CMSIS_FFT_mbed_os_DAC
https://os.mbed.com/users/martinsimpson/code/CMSIS_FFT_mbed_os_DAC/file/05e2c9ca68e2/main.cpp/

Modified by Guillaume Cathelain to generate simulation from DAC
*/

#include "mbed.h"
/* Include arm_math.h mathematic functions */
#include "arm_math.h"
/* Include mbed-dsp libraries */
#include "arm_common_tables.h"
#include "arm_const_structs.h"
#include "math_helper.h"

/* MBED class APIs */
//DigitalOut myled(LED1);
AnalogIn   myADC(A1);
AnalogOut  myDAC(D13);
Serial     pc(USBTX, USBRX);
Ticker     timer;

/* Global variables */
#define SAMPLE_FREQUENCY_UNDEC       1024                       // a ajuster selon la frequence de la porteuse
const float SAMPLE_TIME_UNDEC = 1.0/SAMPLE_FREQUENCY_UNDEC;
const int SAMPLES_UNDEC = 8*SAMPLE_FREQUENCY_UNDEC;             /* 8 secondes au total */

/*Decimation settings*/
const uint16_t numTaps = 31; // order(30) + 1
const float32_t firCoeffs[numTaps] = {0.0035214853,0.004185653,0.005849378,0.008574021,0.012351584,0.017101394,0.022671906,0.028847635,0.035360847,0.041907296,0.048164908,0.053814158,0.058558714,0.06214481,0.064378045,0.065136336,0.064378045,0.06214481,0.058558714,0.053814158,0.048164908,0.041907296,0.035360847,0.028847635,0.022671906,0.017101394,0.012351584,0.008574021,0.005849378,0.004185653,0.0035214853};
const uint8_t M = 32; // divise SAMPLE_FREQ_UNDEC. Limite max : M < VIBE_SAMPLES
const uint32_t blockSize = 64;
const uint32_t numBlocks = SAMPLES_UNDEC/blockSize;
static float32_t firState[numTaps + blockSize -1];
static float32_t undecimatedSignal[SAMPLES_UNDEC];
static float decimatedSignal[SAMPLES_UNDEC/M];
static float32_t  *pDecimatorInput, *pDecimatorOutput;


/* FFT settings */
#define FFT_SIZE                SAMPLES_UNDEC/M     /* FFT size is always the same size as we have samples, so 1024/256 in our case */
static float fftInput[FFT_SIZE*2]; // initialized with zeros
static float fftOutput[FFT_SIZE]; // initialized with zeros
static float maxValue;            // Max FFT value is stored here
static uint32_t maxIndex;         // Index in Output array where max value is


/* Define simulation settings*/    
#define CARRIER_FREQUENCY      (256) // ATTENTION multiple de 2 pour que SAMPLE_FREQUENCY multiple de CARRIER_FREQUENCY afin que VIBE_SAMPLES soit entier
const int CARRIER_SIZE = SAMPLE_FREQUENCY_UNDEC/CARRIER_FREQUENCY;
float carrier[CARRIER_SIZE];
#define MODUL_FREQUENCY     1
const int VIBE_SAMPLES =(SAMPLE_FREQUENCY_UNDEC/CARRIER_FREQUENCY)*int(0.1*CARRIER_FREQUENCY); // multiple de 1/CARRIER_FREQUENCY, durée 0.01s. Durée minimale = 1/CARRIER_FREQUENCY; durée max = 1/MODUL_FREQUENCY
const int MODUL_SIZE = SAMPLE_FREQUENCY_UNDEC/MODUL_FREQUENCY;
float modul[MODUL_SIZE];
const int SIM_SIZE = MODUL_SIZE;
float sim[SIM_SIZE];

// Create the carrier buffer
void calculate_carrier(){
    for (int i = 0; i < CARRIER_SIZE; i+=1) {
        float t = i * SAMPLE_TIME_UNDEC;
        float phase = 2* PI * CARRIER_FREQUENCY * t;
        carrier[i] = sin(phase);
    }
}
// Create the modulator buffer
void calculate_modulator(){
    for (int i = 0; i < VIBE_SAMPLES; i+=1) {
        modul[i] = 1.0;
    }
    for (int i = VIBE_SAMPLES; i < MODUL_SIZE; i+=1) {
        modul[i] = 0.0;
    }
}
// Calculate the sim signal
void calculate_sim(){
    calculate_carrier();
    calculate_modulator();    
    for (int i = 0;i<SIM_SIZE;i+=1){
        int i_carrier = i - CARRIER_SIZE*int(float(i)/CARRIER_SIZE);
        sim[i] = 0.5*modul[i]*carrier[i_carrier]+0.5;
    }
}
// Create the modulated signal
int n=0;
void dac_generate(){
    myDAC.write(sim[n]);
    n++;
    if (n>=SIM_SIZE){
        n=0;
    }
}
        

int main() {
    /* Init serial communication*/
//    pc.baud(115200); //should be higher
    pc.baud(2000000);
    /* DAC simulation*/
    calculate_sim();
    timer.attach(&dac_generate,SAMPLE_TIME_UNDEC);
    
    /* DAC record */
    for (int i = 0; i < SAMPLES_UNDEC; i += 1) {
        wait(SAMPLE_TIME_UNDEC);
        undecimatedSignal[i] = abs(myADC.read() - 0.5f); //Real part NB removing DC offset
    } 

    /* Decimation*/
    arm_fir_decimate_instance_f32 S;
    arm_fir_decimate_init_f32(&S, numTaps, M,(float32_t *)&firCoeffs[0], (float32_t *)&firState[0], blockSize);
    pDecimatorInput = &undecimatedSignal[0];
    pDecimatorOutput = &decimatedSignal[0];
    for(int i=0; i < numBlocks; i++)
    {
        arm_fir_decimate_f32(&S, pDecimatorInput + (i * blockSize), pDecimatorOutput + (i * blockSize/M), blockSize);
    }

    /* Init FFT*/
    float meanDecimatedSignal;
    arm_mean_f32(decimatedSignal,SAMPLES_UNDEC/M,&meanDecimatedSignal);
    for (int i = 0; i < 2*FFT_SIZE; i += 2) {
        fftInput[i] = decimatedSignal[i/2] - meanDecimatedSignal;
        fftInput[i+1] = 0;
    }    

    if (FFT_SIZE==1024){
        arm_cfft_f32(&arm_cfft_sR_f32_len1024, fftInput, 0, 1);  
    } else if (FFT_SIZE==512){
        arm_cfft_f32(&arm_cfft_sR_f32_len512, fftInput, 0, 1);
    } else if (FFT_SIZE==256){
        arm_cfft_f32(&arm_cfft_sR_f32_len256, fftInput, 0, 1);
    } else if (FFT_SIZE==128){
        arm_cfft_f32(&arm_cfft_sR_f32_len128, fftInput, 0, 1);
    }    

    /* Compute FFT and max value */
    arm_cmplx_mag_f32(fftInput, fftOutput, FFT_SIZE);
    arm_max_f32(fftOutput, FFT_SIZE/2, &maxValue, &maxIndex);

    /* GRAPHS*/
//    /* PLOT DECIMATOR INPUT BUFFER */
//    for (int i = 0; i < SAMPLES_UNDEC; i += 1) {
//        pc.printf("%f\r\n",undecimatedSignal[i]);
//    }  
//    /* PLOT DECIMATOR OUTPUT BUFFER */
//    for (int i = 0; i < SAMPLES_UNDEC/M; i += 1) {
//        pc.printf("%f\r\n",decimatedSignal[i]);
//    }   
//    /* FFT graph, only positive frequency */
//    for (int i=0; i<FFT_SIZE/2;i++){
//        pc.printf("%f\r\n",fftOutput[i]);
//    }

    /* FFT RESULT */
//    pc.printf("Maximum value is %f\r\n",maxValue);
//    pc.printf("Index of maximum value is %d\r\n",maxIndex);
    float freqStep = (SAMPLE_FREQUENCY_UNDEC/float(M)) / float(FFT_SIZE);
    float maxFreq = maxIndex * freqStep;
    pc.printf("Frequency of maximum value is %.3f +/- %.3f \r\n",maxFreq,freqStep);         
}