Arkadi Rafalovich / Mbed 2 deprecated TAU_ReSpeaker_DSP_V02

Dependencies:   mbed MbedJSONValue

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 ////////////////////////////////////////
00002 //      Tau_ReSpeaker_DSP V02         //
00003 //  Arkadiraf@gmail.com - 08/06/2019  //
00004 ////////////////////////////////////////
00005 /*
00006  Json Format: json:{"name":"dsp","mode":"off"}\r\n
00007 */
00008 
00009 
00010 
00011 /*
00012    Board : Nucleo STM32F446RE
00013    Power Source : DC-DC 5V Regulator E5V Jumper
00014 */
00015 
00016 /*
00017     Pinout:
00018     PC - Serial 2
00019     PA_2 (Tx) --> STLINK
00020     PA_3 (Rx) --> STLINK
00021 
00022     Switch - Serial 3
00023     PC_10 (Tx) --> SW_Rx
00024     PC_11 (Rx) --> SW_Tx
00025 
00026     Digital output
00027     PA_5 --> led (DigitalOut)
00028     PA_10 --> DSP_Trigger
00029 
00030     Digital Input
00031     PC_13 --> BTN (Blue)
00032 
00033     PA_6  --> Toggle Pin (Loop Freq D12)
00034 
00035     Analog Input
00036     PA_0 --> SIG_IN_DSP  (A0)
00037 
00038     Analog Output
00039     PA_4 --> SIG_OUT_DSP (A2)
00040 
00041 */
00042 
00043 ///////////////
00044 // Libraries //
00045 ///////////////
00046 #include "mbed.h"
00047 #include "MbedJSONValue.h"
00048 #include "chirp.h"
00049 ///////////////
00050 // #defines  //
00051 ///////////////
00052 
00053 //#define TOGGLE_IO_MODE  // loop frequency indicator
00054 
00055 // UART debug modes:
00056 //#define DEBUG_MOD1  // json packet recognise
00057 //#define DEBUG_MOD2   // json parse
00058 //#define DEBUG_MOD3   // dsp handler
00059 //#define DEBUG_MOD10  // responsivity msges to gui
00060 
00061 // PI variable
00062 #define PI_DOUBLE (3.141592653589793238462)
00063 #define PI_FLOAT  (3.14159f)
00064 
00065 // json commad
00066 #define MSG_BUFFER_SIZE 1024
00067 #define HEADER_SIZE 5
00068 #define FOOTER_SIZE 2
00069 
00070 // Frequency counter
00071 #define TICKS2TOGGLE 1000000
00072 
00073 /////////////
00074 // Objects //
00075 /////////////
00076 // json
00077 MbedJSONValue guiCmd;
00078 
00079 // uart
00080 Serial pc(USBTX, USBRX);
00081 
00082 // uart switch_dsp
00083 Serial switch_dsp(PC_10, PC_11);
00084 
00085 // digital
00086 DigitalIn user_button(PC_13);
00087 DigitalOut dsp_trigger(PA_10);// D2
00088 DigitalOut led(PA_5);       // D13
00089 DigitalOut mytoggle(PA_6);  // D12
00090 
00091 // analog / define to init at mbed initialization. work directly with registers
00092 AnalogOut dsp_output(PA_4);
00093 AnalogIn dsp_input(PA_0);
00094 
00095 
00096 // ADC/DAC declarations
00097 ADC_HandleTypeDef hadc1;
00098 DAC_HandleTypeDef hdac1;
00099 
00100 ///////////////
00101 // variables //
00102 ///////////////
00103 
00104 // Frequency counter
00105 uint32_t toggleCounter = 0;
00106 // toogle pin state
00107 bool toggleCounterState = 0;
00108 // toogle pin state
00109 bool toggelState=0;
00110 
00111 // json buffer
00112 char json[MSG_BUFFER_SIZE];
00113 
00114 // packet variables
00115 struct packetMSG_struct {
00116     // recieve message variables
00117     uint8_t header[HEADER_SIZE];
00118     uint8_t footer[FOOTER_SIZE];
00119     uint8_t syncIndex; // sync index for header / footer
00120     uint8_t syncFlag; // 0 - waiting for header, 1 -  waiting for footer, 2 - verify footer, 3 - finish footer send to parser, flash buffer
00121     // buffer
00122     uint16_t bufferIndex; // buffer index
00123     uint8_t buffer[MSG_BUFFER_SIZE];
00124 } ;
00125 packetMSG_struct packetMSG;
00126 
00127 
00128 // Dac Register for direct method of setting DAC value`s
00129 __IO uint32_t Dac_Reg = 0;
00130 
00131 // create function pointer
00132 typedef void(*functionPtr)(void);
00133 functionPtr FilterFunction;
00134 
00135 // alternative functuin selection (faster mcu process)
00136 volatile uint8_t operationMode = 1;
00137 // 0 -  off
00138 // 1 -  passthrough - no filter
00139 // 2 -  highpass    - High Pass filter
00140 // 3 -  hpf_trig    - High Pass filter + Trigger mode
00141 // 4 -  gains_trig  - highpass filter + trigger mode + Gains vector
00142 
00143 ///////////////
00144 // Functions //
00145 ///////////////
00146 
00147 // init functions header //hadc1 needs to be defined preiod #incude
00148 #include "adc_init.h" // initialize adc/dac directly for continious sample
00149 #include "filters.h"
00150 
00151 // nop operation
00152 inline void NOP()
00153 {
00154     __ASM volatile ("nop");    // one tick operation, Use to adjust frequency by slowing down the proccess
00155 }
00156 
00157 // Serial Event function
00158 void rxCallback(void);
00159 
00160 // initialize packet struct
00161 void initPacket(void);
00162 
00163 // Packet Parser
00164 void parsePacket(void);
00165 
00166 // DSP Packet Handler
00167 void dspPacket(void);
00168 
00169 // DSP Param Packet Handler
00170 void dspParamPacket(void);
00171 
00172 // DSP Filter Packet Handler
00173 void dspFilterPacket(void);
00174 
00175 // DSP Play Packet Handler
00176 void dspPlayPacket(void);
00177 
00178 // initialize DSP
00179 void initDSP(void);
00180 
00181 ////////////////////////
00182 //  Main Code Setup : //
00183 ////////////////////////
00184 int main()
00185 {
00186     // init packet:
00187     initPacket();
00188 
00189     // initialize DSP
00190     initDSP();
00191 
00192     pc.baud(57600);
00193     switch_dsp.baud(57600);
00194 
00195 
00196     // pc is used for debbuging, in  application mode the commands are from the switch_dsp.
00197     // attach serial event interrupt
00198     pc.attach(&rxCallback, Serial::RxIrq);
00199 
00200     // attach serial event interrupt
00201     switch_dsp.attach(&rxCallback, Serial::RxIrq);
00202 
00203 #ifdef DEBUG_MOD1
00204     pc.printf("ReSpeaker Test \r\n");
00205 #endif
00206 
00207     ///////////////////////
00208     //  Main Code Loop : //
00209     ///////////////////////
00210     while(1) {
00211         // run selected filter
00212         if (operationMode == 0) {
00213             offMode();
00214         } else if (operationMode == 1) {
00215             passthrough();
00216         } else if (operationMode == 2) {
00217             highpass();
00218         } else if (operationMode == 3) {
00219             highpassTrig();
00220         } else if (operationMode == 4) {
00221             GainsTrig();    
00222         }
00223         // more elegant but much slower option:
00224         //FilterFunction();
00225 #ifdef TOGGLE_IO_MODE
00226         // toggle pin, Loop frequency indicator
00227         toggelState=!toggelState;
00228         mytoggle.write(toggelState);
00229 #endif
00230         // Frequency counter
00231         toggleCounter++;
00232         if (toggleCounter == TICKS2TOGGLE) {
00233             toggleCounter=0;
00234             toggleCounterState = !toggleCounterState;
00235             dsp_trigger.write(toggleCounterState);
00236         }
00237     } // end loop
00238 } // end main
00239 
00240 ///////////////
00241 // Functions //
00242 ///////////////
00243 
00244 // initialize DSP
00245 void initDSP(void)
00246 {
00247     // init dac
00248     ADC1_Init();
00249     DAC1_Init();
00250 
00251     HAL_ADC_Start(&hadc1);
00252     HAL_DAC_Start(&hdac1, DAC_CHANNEL_1);
00253 
00254     // define Dac Register for direct method of setting DAC value`s
00255     Dac_Reg = (uint32_t) (hdac1.Instance);
00256     Dac_Reg += __HAL_DHR12R1_ALIGNEMENT(DAC_ALIGN_12B_R);
00257 
00258     // intialize filter function pointer
00259     FilterFunction = offMode;//highpass_filter;
00260     operationMode = 0 ;
00261 }
00262 
00263 // Serial Event function
00264 void rxCallback(void)
00265 {
00266     while ((pc.readable()) || (switch_dsp.readable())) {
00267         // read icoming
00268         uint8_t in_byte=0;
00269         //led = !led;
00270         if (pc.readable()) {
00271             in_byte = pc.getc();
00272         } else if (switch_dsp.readable()) {
00273             in_byte = switch_dsp.getc();
00274         }
00275 #ifdef DEBUG_MOD1
00276         pc.putc(in_byte);
00277 #endif
00278         // detect start message , end message
00279         switch (packetMSG.syncFlag) {
00280                 // waiting for header
00281             case 0: {
00282                 if (packetMSG.header[packetMSG.syncIndex] == in_byte) {
00283                     packetMSG.syncIndex++;
00284                     if (packetMSG.syncIndex == HEADER_SIZE) { // finish header SYNC
00285                         packetMSG.syncFlag = 1; // start collecting data, wait for footer
00286                         packetMSG.bufferIndex = 0;
00287                         packetMSG.syncIndex=0;
00288                     }
00289                 } else { // reinit sync
00290                     packetMSG.syncIndex=0;
00291                 }
00292                 //pc.printf("case 0 , %d  \r\n",packetMSG.syncIndex);
00293                 break;
00294             }
00295             // waiting for footer
00296             case 1: {
00297                 // add byte to buffer
00298                 packetMSG.buffer[packetMSG.bufferIndex] = in_byte;
00299                 packetMSG.bufferIndex++;
00300                 if (packetMSG.bufferIndex >= MSG_BUFFER_SIZE) { // buffer overflow
00301                     // reset buffer
00302                     packetMSG.bufferIndex = 0;
00303                     packetMSG.syncIndex = 0;
00304                     packetMSG.syncFlag = 0;
00305                 } else if (packetMSG.footer[packetMSG.syncIndex] == in_byte) { // footer char recieved
00306                     packetMSG.syncIndex++;
00307                     packetMSG.syncFlag=2; // move to verify footer
00308                 }
00309                 //pc.printf("case 2 , %d  \r\n",packetMSG.syncIndex);
00310                 break;
00311             }
00312             // verify footer
00313             case 2: {
00314                 // add byte to buffer
00315                 packetMSG.buffer[packetMSG.bufferIndex] = in_byte;
00316                 packetMSG.bufferIndex++;
00317                 if (packetMSG.bufferIndex >= MSG_BUFFER_SIZE) { // buffer overflow
00318                     // reset buffer
00319                     packetMSG.bufferIndex = 0;
00320                     packetMSG.syncIndex = 0;
00321                     packetMSG.syncFlag = 0;
00322                 } else if (packetMSG.footer[packetMSG.syncIndex] == in_byte) { // footer char recieved
00323                     packetMSG.syncIndex++;
00324                     if (packetMSG.syncIndex == FOOTER_SIZE) { // finish footer SYNC
00325                         packetMSG.syncFlag = 3;
00326                         // copy packet to json buffer
00327                         memcpy (&json, &packetMSG.buffer, packetMSG.bufferIndex);
00328                         json[packetMSG.bufferIndex]=NULL; // end with NULL to indicate end of string
00329                         // copy packet to json buffer with sprintf
00330                         //sprintf(json, "%.*s", packetMSG.bufferIndex, packetMSG.buffer );
00331                         // send msg to parse.
00332                         parsePacket();
00333                         // reset buffer
00334                         packetMSG.bufferIndex = 0;
00335                         packetMSG.syncIndex = 0;
00336                         packetMSG.syncFlag = 0;
00337                     }
00338                 } else { // footer broke restart wait for footer
00339                     packetMSG.syncFlag=1;
00340                     // verify that it didnt broke on first footer char
00341                     if (packetMSG.footer[0] == in_byte) {
00342                         packetMSG.syncIndex=1;
00343                     } else {
00344                         packetMSG.syncIndex=0;
00345                     }
00346                 }
00347                 break;
00348             }
00349             default: {
00350                 pc.printf("Sonmething went wrong \r\n");
00351                 break;
00352             }
00353         } // end switch
00354     }// end uart readable
00355 } // end rxCallback
00356 
00357 // initialize packet struct
00358 void initPacket(void)
00359 {
00360     // init variables to default:
00361     packetMSG.header[0] = 'j';
00362     packetMSG.header[1] = 's';
00363     packetMSG.header[2] = 'o';
00364     packetMSG.header[3] = 'n';
00365     packetMSG.header[4] = ':';
00366 
00367     packetMSG.footer[0]= 13; // /r
00368     packetMSG.footer[1]= 10; // /n
00369 
00370     packetMSG.syncIndex=0; // sync index for header / footer
00371     packetMSG.syncFlag=0; // 0 - waiting for header, 1 -  waiting for footer, 2 - verify footer, 3 - finish footer send to parser, flash buffer
00372     packetMSG.bufferIndex=0; // buffer index
00373 }// end init Packet struct
00374 
00375 
00376 
00377 // Packet Parser
00378 void parsePacket(void)
00379 {
00380     string targetName;
00381 #ifdef DEBUG_MOD2
00382     // write buffer to screen
00383     //pc.printf("%d, %.*s", packetMSG.bufferIndex ,packetMSG.bufferIndex, packetMSG.buffer );
00384     pc.printf("%s", json);
00385 #endif
00386 
00387     // GUI message format Switch: {"name":"switch","mic":0, "spk": [0,1,0,0,0]}
00388     parse(guiCmd, json);
00389 
00390     // get target:
00391     targetName = guiCmd["name"].get<string>(); // switch / dsp
00392 
00393 #ifdef DEBUG_MOD2
00394     // send parsed values
00395     pc.printf("targetName: %s \r\n", targetName.c_str());
00396 #endif
00397 
00398     // select handler based on target mcu
00399     if (targetName == "dsp") {
00400         dspPacket();
00401     } else if (targetName == "dspParam") {
00402         dspParamPacket();
00403     } else if (targetName == "dspFilter") {
00404         dspFilterPacket();
00405     } else if (targetName == "dspPlay") {
00406         dspPlayPacket();
00407     } else {
00408 #ifdef DEBUG_MOD2
00409         // unrecognised target
00410         pc.printf("unrecognised target: %s \r\n", targetName.c_str());
00411 #endif
00412     }
00413     // led blink
00414     led = !led;
00415 }// end parse
00416 
00417             
00418 // DSP Packet Handler
00419 void dspPacket(void)
00420 {
00421     string modeType;
00422     // get operation mode
00423     modeType = guiCmd["mode"].get<string>();
00424 
00425 #ifdef DEBUG_MOD10
00426     // send parsed values
00427     pc.printf("mode: %s\r\n", modeType.c_str());
00428     //switch_dsp.printf("mode: %s\r\n", modeType.c_str());
00429 #endif
00430     // selected operation mode
00431     if ( modeType == "off" ) {
00432         FilterFunction = offMode;
00433         operationMode = 0 ;
00434     } else if( modeType == "passthrough" ) {
00435         FilterFunction = passthrough;
00436         operationMode = 1 ;
00437     } else if( modeType == "highpass" ) {
00438         FilterFunction = highpass;
00439         operationMode = 2 ;
00440     } else if( modeType == "hpf_trig" ) {
00441         FilterFunction = highpassTrig;
00442         operationMode = 3 ;
00443     } else if( modeType == "gain_trig" ) {
00444         FilterFunction = GainsTrig;
00445         operationMode = 4 ;
00446     } else {
00447         switch_dsp.printf("undefined mode %s \r\n", modeType.c_str());
00448         FilterFunction = offMode;
00449         operationMode = 0 ;
00450     }
00451     // succesfull parse
00452     switch_dsp.printf("{\"Ack\":\"dsp\",\"mode\":\"%s\"}\r\n",modeType.c_str());
00453 }// end dspPacket
00454 // DSP Param Packet Handler
00455 void dspParamPacket(void)
00456 {
00457     // get values.
00458     signalGain      = ((float)guiCmd["gain"].get<int>())/1000; // issue in parsing doubles when the number is round
00459     trigTresh       = ((float)guiCmd["trigTresh"].get<int>()) / 100.0f;
00460     trigDelaySet    = (uint32_t)guiCmd["trigPass"].get<int>();
00461     trigPause       = (uint32_t)guiCmd["trigPause"].get<int>();
00462 
00463     trigDelay = trigDelaySet;
00464 #ifdef DEBUG_MOD10
00465     // send parsed values
00466     pc.printf("SignalGain: %.3f , trigTresh: %.3f , trigDelaySet %d , trigPause: %d\r\n", signalGain , trigTresh , trigDelaySet , trigPause);
00467 #endif
00468     // succesfull parse
00469     switch_dsp.printf("{\"Ack\":\"dspParam\",\"SignalGain\":%.3f,\"trigTresh\":%.3f,\"trigDelaySet\":%d,\"trigPause\":%d}\r\n", signalGain , trigTresh , trigDelaySet , trigPause);
00470 } // end dspParamPacket
00471 
00472 // DSP Filter Packet Handler
00473 void dspFilterPacket(void)
00474 {
00475     // get values.
00476     FilterSections  = (guiCmd["Sections"].get<int>());
00477     Gscale          = ((float)(guiCmd["Gscale"].get<int>()))/10000.0f; // issue in parsing doubles
00478 
00479     // get SOSMat
00480     for (int jj=0 ; jj < FilterSections ; jj++) {
00481         for (int ii=0 ; ii < 6 ; ii++) {
00482             SOSMat[jj][ii] = ((float)guiCmd["SOSMat"][ii+jj*6].get<int>())/10000.0f;
00483         }
00484     }
00485 #ifdef DEBUG_MOD10
00486     // send parsed values
00487     pc.printf("FilterSections: %d , Gscale: %.3f\r\n", FilterSections , Gscale);
00488     pc.printf("SOSMat \r\n");
00489     for (int jj=0 ; jj < FilterSections ; jj++) {
00490         pc.printf("%.3f , %.3f , %.3f , %.3f , %.3f , %.3f \r\n",SOSMat[jj][0] ,SOSMat[jj][1],SOSMat[jj][2],SOSMat[jj][3] ,SOSMat[jj][4] ,SOSMat[jj][5]);
00491     }
00492 #endif
00493     // succesfull parse
00494     switch_dsp.printf("{\"Ack\":\"dspFilter\",\"FilterSections\":%d,\"Gscale\":%.3f}\r\n", FilterSections , Gscale);
00495 } // end dspFilterPacket
00496 
00497 // DSP Play Packet Handler
00498 void dspPlayPacket(void)
00499 {
00500     // get values.
00501     float playGain      = ((float)guiCmd["gain"].get<int>())/1000; // issue in parsing doubles when the number is round
00502     uint32_t playFile       = (uint32_t)guiCmd["file"].get<int>(); // file to play
00503 
00504     // succesfull parse
00505     switch_dsp.printf("{\"Ack\":\"dspPlay\",\"file\":%d,\"gain\":%.3f}\r\n", playFile, playGain);
00506             //////////////////////////////////////////////////////////////////
00507             // Temp mode - need to update file selection ,  gain settings   //
00508             //////////////////////////////////////////////////////////////////
00509             __disable_irq();    // Disable Interrupts
00510             // generate chirp out
00511             for (int ii=0; ii<NUM_SAMPLES; ii++) {
00512                 // toogle io for loop frequency
00513                 toggelState=!toggelState;
00514                 mytoggle.write(toggelState);
00515                 // generate delay for 1MHz Sample rate
00516                 for (int jj=0; jj<31; jj++) {
00517                     NOP();
00518                 }
00519                 // micro nops :)
00520                 NOP();
00521                 NOP();
00522                 NOP();
00523                 NOP();
00524                 NOP();
00525                 NOP();
00526                 NOP();
00527                 // Output value using DAC
00528                 // HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, ADCValueOut);
00529                 *(__IO uint32_t *) Dac_Reg = chirpData[ii];
00530             }
00531             // Output value using DAC
00532             // HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, ADCValueOut);
00533             *(__IO uint32_t *) Dac_Reg = (uint16_t)(4095/2);
00534             __enable_irq();     // Enable Interrupts
00535             
00536             // Option to reset play mode after file has been played
00537             //operationMode = 0;
00538 } // end dspPlayPacket