Guillaume Cathelain / Mbed OS Env_simDAC

Dependencies:   mbed-dsp

Committer:
guicat
Date:
Tue Jan 29 07:20:48 2019 +0000
Revision:
2:7945f79d7c8e
Parent:
1:4a666bd3fef6
First commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
guicat 1:4a666bd3fef6 1 /*
guicat 1:4a666bd3fef6 2 Original code from MARTIN SIMPSON : CMSIS_FFT_mbed_os_DAC
guicat 1:4a666bd3fef6 3 https://os.mbed.com/users/martinsimpson/code/CMSIS_FFT_mbed_os_DAC/file/05e2c9ca68e2/main.cpp/
guicat 1:4a666bd3fef6 4
guicat 1:4a666bd3fef6 5 Modified by Guillaume Cathelain to generate simulation from DAC
guicat 1:4a666bd3fef6 6 */
guicat 1:4a666bd3fef6 7
martinsimpson 0:05e2c9ca68e2 8 #include "mbed.h"
martinsimpson 0:05e2c9ca68e2 9 /* Include arm_math.h mathematic functions */
martinsimpson 0:05e2c9ca68e2 10 #include "arm_math.h"
martinsimpson 0:05e2c9ca68e2 11 /* Include mbed-dsp libraries */
martinsimpson 0:05e2c9ca68e2 12 #include "arm_common_tables.h"
martinsimpson 0:05e2c9ca68e2 13 #include "arm_const_structs.h"
martinsimpson 0:05e2c9ca68e2 14 #include "math_helper.h"
martinsimpson 0:05e2c9ca68e2 15
martinsimpson 0:05e2c9ca68e2 16 /* MBED class APIs */
guicat 1:4a666bd3fef6 17 //DigitalOut myled(LED1);
martinsimpson 0:05e2c9ca68e2 18 AnalogIn myADC(A1);
martinsimpson 0:05e2c9ca68e2 19 AnalogOut myDAC(D13);
martinsimpson 0:05e2c9ca68e2 20 Serial pc(USBTX, USBRX);
martinsimpson 0:05e2c9ca68e2 21 Ticker timer;
guicat 2:7945f79d7c8e 22
guicat 2:7945f79d7c8e 23 /* Global variables */
guicat 2:7945f79d7c8e 24 #define SAMPLE_FREQUENCY_UNDEC 1024 // a ajuster selon la frequence de la porteuse
guicat 2:7945f79d7c8e 25 const float SAMPLE_TIME_UNDEC = 1.0/SAMPLE_FREQUENCY_UNDEC;
guicat 2:7945f79d7c8e 26 const int SAMPLES_UNDEC = 8*SAMPLE_FREQUENCY_UNDEC; /* 8 secondes au total */
guicat 2:7945f79d7c8e 27
guicat 2:7945f79d7c8e 28 /*Decimation settings*/
guicat 2:7945f79d7c8e 29 const uint16_t numTaps = 31; // order(30) + 1
guicat 2:7945f79d7c8e 30 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};
guicat 2:7945f79d7c8e 31 const uint8_t M = 32; // divise SAMPLE_FREQ_UNDEC. Limite max : M < VIBE_SAMPLES
guicat 2:7945f79d7c8e 32 const uint32_t blockSize = 64;
guicat 2:7945f79d7c8e 33 const uint32_t numBlocks = SAMPLES_UNDEC/blockSize;
guicat 2:7945f79d7c8e 34 static float32_t firState[numTaps + blockSize -1];
guicat 2:7945f79d7c8e 35 static float32_t undecimatedSignal[SAMPLES_UNDEC];
guicat 2:7945f79d7c8e 36 static float decimatedSignal[SAMPLES_UNDEC/M];
guicat 2:7945f79d7c8e 37 static float32_t *pDecimatorInput, *pDecimatorOutput;
guicat 2:7945f79d7c8e 38
guicat 2:7945f79d7c8e 39
guicat 2:7945f79d7c8e 40 /* FFT settings */
guicat 2:7945f79d7c8e 41 #define FFT_SIZE SAMPLES_UNDEC/M /* FFT size is always the same size as we have samples, so 1024/256 in our case */
guicat 2:7945f79d7c8e 42 static float fftInput[FFT_SIZE*2]; // initialized with zeros
guicat 2:7945f79d7c8e 43 static float fftOutput[FFT_SIZE]; // initialized with zeros
guicat 2:7945f79d7c8e 44 static float maxValue; // Max FFT value is stored here
guicat 2:7945f79d7c8e 45 static uint32_t maxIndex; // Index in Output array where max value is
guicat 2:7945f79d7c8e 46
guicat 2:7945f79d7c8e 47
guicat 2:7945f79d7c8e 48 /* Define simulation settings*/
guicat 2:7945f79d7c8e 49 #define CARRIER_FREQUENCY (256) // ATTENTION multiple de 2 pour que SAMPLE_FREQUENCY multiple de CARRIER_FREQUENCY afin que VIBE_SAMPLES soit entier
guicat 2:7945f79d7c8e 50 const int CARRIER_SIZE = SAMPLE_FREQUENCY_UNDEC/CARRIER_FREQUENCY;
guicat 2:7945f79d7c8e 51 float carrier[CARRIER_SIZE];
guicat 2:7945f79d7c8e 52 #define MODUL_FREQUENCY 1
guicat 2:7945f79d7c8e 53 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
guicat 2:7945f79d7c8e 54 const int MODUL_SIZE = SAMPLE_FREQUENCY_UNDEC/MODUL_FREQUENCY;
guicat 2:7945f79d7c8e 55 float modul[MODUL_SIZE];
guicat 2:7945f79d7c8e 56 const int SIM_SIZE = MODUL_SIZE;
guicat 2:7945f79d7c8e 57 float sim[SIM_SIZE];
guicat 2:7945f79d7c8e 58
guicat 2:7945f79d7c8e 59 // Create the carrier buffer
guicat 2:7945f79d7c8e 60 void calculate_carrier(){
guicat 2:7945f79d7c8e 61 for (int i = 0; i < CARRIER_SIZE; i+=1) {
guicat 2:7945f79d7c8e 62 float t = i * SAMPLE_TIME_UNDEC;
guicat 2:7945f79d7c8e 63 float phase = 2* PI * CARRIER_FREQUENCY * t;
guicat 2:7945f79d7c8e 64 carrier[i] = sin(phase);
guicat 1:4a666bd3fef6 65 }
guicat 1:4a666bd3fef6 66 }
guicat 2:7945f79d7c8e 67 // Create the modulator buffer
guicat 2:7945f79d7c8e 68 void calculate_modulator(){
guicat 2:7945f79d7c8e 69 for (int i = 0; i < VIBE_SAMPLES; i+=1) {
guicat 2:7945f79d7c8e 70 modul[i] = 1.0;
guicat 2:7945f79d7c8e 71 }
guicat 2:7945f79d7c8e 72 for (int i = VIBE_SAMPLES; i < MODUL_SIZE; i+=1) {
guicat 2:7945f79d7c8e 73 modul[i] = 0.0;
guicat 2:7945f79d7c8e 74 }
guicat 2:7945f79d7c8e 75 }
guicat 2:7945f79d7c8e 76 // Calculate the sim signal
guicat 2:7945f79d7c8e 77 void calculate_sim(){
guicat 2:7945f79d7c8e 78 calculate_carrier();
guicat 2:7945f79d7c8e 79 calculate_modulator();
guicat 2:7945f79d7c8e 80 for (int i = 0;i<SIM_SIZE;i+=1){
guicat 2:7945f79d7c8e 81 int i_carrier = i - CARRIER_SIZE*int(float(i)/CARRIER_SIZE);
guicat 2:7945f79d7c8e 82 sim[i] = 0.5*modul[i]*carrier[i_carrier]+0.5;
guicat 2:7945f79d7c8e 83 }
guicat 2:7945f79d7c8e 84 }
guicat 2:7945f79d7c8e 85 // Create the modulated signal
guicat 1:4a666bd3fef6 86 int n=0;
guicat 1:4a666bd3fef6 87 void dac_generate(){
guicat 2:7945f79d7c8e 88 myDAC.write(sim[n]);
guicat 1:4a666bd3fef6 89 n++;
guicat 2:7945f79d7c8e 90 if (n>=SIM_SIZE){
guicat 1:4a666bd3fef6 91 n=0;
martinsimpson 0:05e2c9ca68e2 92 }
guicat 1:4a666bd3fef6 93 }
guicat 1:4a666bd3fef6 94
martinsimpson 0:05e2c9ca68e2 95
martinsimpson 0:05e2c9ca68e2 96 int main() {
guicat 2:7945f79d7c8e 97 /* Init serial communication*/
guicat 2:7945f79d7c8e 98 // pc.baud(115200); //should be higher
guicat 2:7945f79d7c8e 99 pc.baud(2000000);
guicat 2:7945f79d7c8e 100 /* DAC simulation*/
guicat 2:7945f79d7c8e 101 calculate_sim();
guicat 2:7945f79d7c8e 102 timer.attach(&dac_generate,SAMPLE_TIME_UNDEC);
guicat 1:4a666bd3fef6 103
guicat 2:7945f79d7c8e 104 /* DAC record */
guicat 2:7945f79d7c8e 105 for (int i = 0; i < SAMPLES_UNDEC; i += 1) {
guicat 2:7945f79d7c8e 106 wait(SAMPLE_TIME_UNDEC);
guicat 2:7945f79d7c8e 107 undecimatedSignal[i] = abs(myADC.read() - 0.5f); //Real part NB removing DC offset
guicat 2:7945f79d7c8e 108 }
guicat 2:7945f79d7c8e 109
guicat 2:7945f79d7c8e 110 /* Decimation*/
guicat 2:7945f79d7c8e 111 arm_fir_decimate_instance_f32 S;
guicat 2:7945f79d7c8e 112 arm_fir_decimate_init_f32(&S, numTaps, M,(float32_t *)&firCoeffs[0], (float32_t *)&firState[0], blockSize);
guicat 2:7945f79d7c8e 113 pDecimatorInput = &undecimatedSignal[0];
guicat 2:7945f79d7c8e 114 pDecimatorOutput = &decimatedSignal[0];
guicat 2:7945f79d7c8e 115 for(int i=0; i < numBlocks; i++)
guicat 2:7945f79d7c8e 116 {
guicat 2:7945f79d7c8e 117 arm_fir_decimate_f32(&S, pDecimatorInput + (i * blockSize), pDecimatorOutput + (i * blockSize/M), blockSize);
guicat 1:4a666bd3fef6 118 }
guicat 2:7945f79d7c8e 119
guicat 2:7945f79d7c8e 120 /* Init FFT*/
guicat 2:7945f79d7c8e 121 float meanDecimatedSignal;
guicat 2:7945f79d7c8e 122 arm_mean_f32(decimatedSignal,SAMPLES_UNDEC/M,&meanDecimatedSignal);
guicat 2:7945f79d7c8e 123 for (int i = 0; i < 2*FFT_SIZE; i += 2) {
guicat 2:7945f79d7c8e 124 fftInput[i] = decimatedSignal[i/2] - meanDecimatedSignal;
guicat 2:7945f79d7c8e 125 fftInput[i+1] = 0;
guicat 1:4a666bd3fef6 126 }
martinsimpson 0:05e2c9ca68e2 127
guicat 2:7945f79d7c8e 128 if (FFT_SIZE==1024){
guicat 2:7945f79d7c8e 129 arm_cfft_f32(&arm_cfft_sR_f32_len1024, fftInput, 0, 1);
guicat 2:7945f79d7c8e 130 } else if (FFT_SIZE==512){
guicat 2:7945f79d7c8e 131 arm_cfft_f32(&arm_cfft_sR_f32_len512, fftInput, 0, 1);
guicat 2:7945f79d7c8e 132 } else if (FFT_SIZE==256){
guicat 2:7945f79d7c8e 133 arm_cfft_f32(&arm_cfft_sR_f32_len256, fftInput, 0, 1);
guicat 2:7945f79d7c8e 134 } else if (FFT_SIZE==128){
guicat 2:7945f79d7c8e 135 arm_cfft_f32(&arm_cfft_sR_f32_len128, fftInput, 0, 1);
guicat 2:7945f79d7c8e 136 }
guicat 2:7945f79d7c8e 137
guicat 2:7945f79d7c8e 138 /* Compute FFT and max value */
guicat 2:7945f79d7c8e 139 arm_cmplx_mag_f32(fftInput, fftOutput, FFT_SIZE);
guicat 2:7945f79d7c8e 140 arm_max_f32(fftOutput, FFT_SIZE/2, &maxValue, &maxIndex);
guicat 2:7945f79d7c8e 141
guicat 2:7945f79d7c8e 142 /* GRAPHS*/
guicat 2:7945f79d7c8e 143 // /* PLOT DECIMATOR INPUT BUFFER */
guicat 2:7945f79d7c8e 144 // for (int i = 0; i < SAMPLES_UNDEC; i += 1) {
guicat 2:7945f79d7c8e 145 // pc.printf("%f\r\n",undecimatedSignal[i]);
guicat 2:7945f79d7c8e 146 // }
guicat 2:7945f79d7c8e 147 // /* PLOT DECIMATOR OUTPUT BUFFER */
guicat 2:7945f79d7c8e 148 // for (int i = 0; i < SAMPLES_UNDEC/M; i += 1) {
guicat 2:7945f79d7c8e 149 // pc.printf("%f\r\n",decimatedSignal[i]);
guicat 2:7945f79d7c8e 150 // }
guicat 2:7945f79d7c8e 151 // /* FFT graph, only positive frequency */
guicat 1:4a666bd3fef6 152 // for (int i=0; i<FFT_SIZE/2;i++){
guicat 2:7945f79d7c8e 153 // pc.printf("%f\r\n",fftOutput[i]);
guicat 1:4a666bd3fef6 154 // }
guicat 1:4a666bd3fef6 155
guicat 2:7945f79d7c8e 156 /* FFT RESULT */
guicat 1:4a666bd3fef6 157 // pc.printf("Maximum value is %f\r\n",maxValue);
guicat 1:4a666bd3fef6 158 // pc.printf("Index of maximum value is %d\r\n",maxIndex);
guicat 2:7945f79d7c8e 159 float freqStep = (SAMPLE_FREQUENCY_UNDEC/float(M)) / float(FFT_SIZE);
guicat 1:4a666bd3fef6 160 float maxFreq = maxIndex * freqStep;
guicat 2:7945f79d7c8e 161 pc.printf("Frequency of maximum value is %.3f +/- %.3f \r\n",maxFreq,freqStep);
martinsimpson 0:05e2c9ca68e2 162 }