![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
ReSpeaker DSP V02
Dependencies: mbed MbedJSONValue
main.cpp
- Committer:
- Arkadi
- Date:
- 2018-08-27
- Revision:
- 10:273127efdc6e
- Parent:
- 9:7e20c1e5a354
- Child:
- 11:07981b0d28d3
File content as of revision 10:273127efdc6e:
//////////////////////////////////////// // Tau_ReSpeaker_DSP V01 // // Arkadiraf@gmail.com - 26/08/2018 // //////////////////////////////////////// /* Json Format: json:{"name":"dsp","mode":"off"}\r\n */ /* Board : Nucleo STM32F446RE Power Source : USB */ /* Pinout: PC - Serial 2 PA_2 (Tx) --> STLINK PA_3 (Rx) --> STLINK Switch - Serial 3 PC_10 (Tx) --> SW_Rx PC_11 (Rx) --> SW_Tx I2C_Bus PB_8 --> SCL PB_9 --> SDA Digital output PA_5 --> led (DigitalOut) PA_10 --> DSP_Trigger Digital Input PC_13 --> BTN (Blue) PA_6 --> Toggle Pin (Loop Freq D12) Analog Input PA_0 --> SIG_IN_DSP (A0) Analog Output PA_4 --> SIG_OUT_DSP (A2) */ /////////////// // Libraries // /////////////// #include "mbed.h" #include "MbedJSONValue.h" /////////////// // #defines // /////////////// // UART debug modes: //#define DEBUG_MOD1 // json packet recognise #define DEBUG_MOD2 // json parse #define DEBUG_MOD3 // dsp handler #define DEBUG_MOD10 // responsivity msges to gui #define DEBUG_MOD11 // loop frequency indicator // Sine generator #define PI_DOUBLE (3.141592653589793238462) #define PI_FLOAT (3.14159f) // json commad #define MSG_BUFFER_SIZE 1024 #define HEADER_SIZE 5 #define FOOTER_SIZE 2 // Frequency counter #define TICKS2TOGGLE 1000000 ///////////// // Objects // ///////////// // json MbedJSONValue guiCmd; // uart Serial pc(USBTX, USBRX); // uart switch_dsp Serial switch_dsp(PC_10, PC_11); // digital DigitalIn user_button(PC_13); DigitalOut dsp_trigger(PA_10);// D2 DigitalOut led(PA_5); // D13 DigitalOut mytoggle(PA_6); // D12 // analog / define to init at mbed initialization. work directly with registers AnalogOut dsp_output(PA_4); AnalogIn dsp_input(PA_0); // ADC/DAC declarations ADC_HandleTypeDef hadc1; DAC_HandleTypeDef hdac1; /////////////// // variables // /////////////// // Frequency counter uint32_t toggleCounter = 0; // toogle pin state bool toggleCounterState = 0; // json buffer char json[MSG_BUFFER_SIZE]; // packet variables struct packetMSG_struct { // recieve message variables uint8_t header[HEADER_SIZE]; uint8_t footer[FOOTER_SIZE]; uint8_t syncIndex; // sync index for header / footer uint8_t syncFlag; // 0 - waiting for header, 1 - waiting for footer, 2 - verify footer, 3 - finish footer send to parser, flash buffer // buffer uint16_t bufferIndex; // buffer index uint8_t buffer[MSG_BUFFER_SIZE]; } ; packetMSG_struct packetMSG; // Dac Register for direct method of setting DAC value`s __IO uint32_t Dac_Reg = 0; // analog input //uint16_t adc_in=0; // toogle pin state bool toggelState=0; // create function pointer typedef void(*functionPtr)(void); functionPtr FilterFunction; // alternative functuin selection (faster mcu process) volatile uint8_t operationMode = 1; // 0 - off // 1 - passthrough - no filter // 2 - highpass - High Pass filter // 3 - hpf_trig - High Pass filter + Trigger mode // 4 - gains_trig - highpass filter + trigger mode + Gains vector // Trigger mode variables float signalGain = 1.0; // Signal Gain float trigTresh = 0.5; // threshold for trigger mode uint32_t trigDelaySet = 5000; // counter for pulse pass uint32_t trigDelay = trigDelaySet; // counter for pulse pass uint32_t trigPause = 10; // pause after trigger in microseconds // Filter variables //SOS Matrix limited to order 10 int FilterSections=1; float SOSMat[5][6]={ // Predefined SOS Matrix (second order 5Khz filter 1, -2, 1, 1, -1.961, 0.9624, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; float Gscale = 0.9810f; float filterCurrInput[6] = {0}; float filterLastInput[6] = {0}; float filterLLastInput[6] = {0}; // Buffer mode variables uint32_t bufferSizeSet = 5000; uint32_t bufferSize = bufferSizeSet; uint32_t preBufferSizeSet = 1000; uint32_t bufferCountDown = bufferSizeSet - preBufferSizeSet; float bufferADC[5000] = {0}; /////////////// // Functions // /////////////// // init functions header //hadc1 needs to be defined preiod #incude #include "adc_init.h" // initialize adc/dac directly for continious sample #include "filters.h" // nop operation inline void NOP() { __ASM volatile ("nop"); // one tick operation, Use to adjust frequency by slowing down the proccess } // Serial Event function void rxCallback(void); // initialize packet struct void initPacket(void); // Packet Parser void parsePacket(void); // DSP Packet Handler void dspPacket(void); // DSP Param Packet Handler void dspParamPacket(void); // DSP Filter Packet Handler void dspFilterPacket(void); // initialize DSP void initDSP(void); //////////////////////// // Main Code Setup : // //////////////////////// int main() { // init packet: initPacket(); // initialize DSP initDSP(); pc.baud(57600); switch_dsp.baud(57600); // pc is used for debbuging, in application mode the commands are from the switch_dsp. // attach serial event interrupt pc.attach(&rxCallback, Serial::RxIrq); // attach serial event interrupt switch_dsp.attach(&rxCallback, Serial::RxIrq); #ifdef DEBUG_MOD1 pc.printf("ReSpeaker Test \r\n"); #endif /////////////////////// // Main Code Loop : // /////////////////////// while(1) { // run selected filter if (operationMode == 0) { offMode(); } else if (operationMode == 1) { passthrough(); } else if (operationMode == 2) { highpass(); } else if (operationMode == 3) { highpassTrig(); } else if (operationMode == 4) { GainsTrig(); } //highpass_filter(); // more elegant but much slower option: //FilterFunction(); #ifdef DEBUG_MOD11 // toggle pin, Loop frequency indicator toggelState=!toggelState; mytoggle.write(toggelState); #endif // Frequency counter toggleCounter++; if (toggleCounter == TICKS2TOGGLE){ toggleCounter=0; toggleCounterState = !toggleCounterState; dsp_trigger.write(toggleCounterState); } } // end loop } // end main /////////////// // Functions // /////////////// // initialize DSP void initDSP(void) { // init dac ADC1_Init(); DAC1_Init(); HAL_ADC_Start(&hadc1); HAL_DAC_Start(&hdac1, DAC_CHANNEL_1); // define Dac Register for direct method of setting DAC value`s Dac_Reg = (uint32_t) (hdac1.Instance); Dac_Reg += __HAL_DHR12R1_ALIGNEMENT(DAC_ALIGN_12B_R); // intialize filter function pointer FilterFunction = passthrough;//highpass_filter; operationMode = 0 ; } // Serial Event function void rxCallback(void) { while ((pc.readable()) || (switch_dsp.readable())) { // read icoming uint8_t in_byte=0; //led = !led; if (pc.readable()) { in_byte = pc.getc(); } else if (switch_dsp.readable()) { in_byte = switch_dsp.getc(); } #ifdef DEBUG_MOD1 pc.putc(in_byte); #endif // detect start message , end message switch (packetMSG.syncFlag) { // waiting for header case 0: { if (packetMSG.header[packetMSG.syncIndex] == in_byte) { packetMSG.syncIndex++; if (packetMSG.syncIndex == HEADER_SIZE) { // finish header SYNC packetMSG.syncFlag = 1; // start collecting data, wait for footer packetMSG.bufferIndex = 0; packetMSG.syncIndex=0; } } else { // reinit sync packetMSG.syncIndex=0; } //pc.printf("case 0 , %d \r\n",packetMSG.syncIndex); break; } // waiting for footer case 1: { // add byte to buffer packetMSG.buffer[packetMSG.bufferIndex] = in_byte; packetMSG.bufferIndex++; if (packetMSG.bufferIndex >= MSG_BUFFER_SIZE) { // buffer overflow // reset buffer packetMSG.bufferIndex = 0; packetMSG.syncIndex = 0; packetMSG.syncFlag = 0; } else if (packetMSG.footer[packetMSG.syncIndex] == in_byte) { // footer char recieved packetMSG.syncIndex++; packetMSG.syncFlag=2; // move to verify footer } //pc.printf("case 2 , %d \r\n",packetMSG.syncIndex); break; } // verify footer case 2: { // add byte to buffer packetMSG.buffer[packetMSG.bufferIndex] = in_byte; packetMSG.bufferIndex++; if (packetMSG.bufferIndex >= MSG_BUFFER_SIZE) { // buffer overflow // reset buffer packetMSG.bufferIndex = 0; packetMSG.syncIndex = 0; packetMSG.syncFlag = 0; } else if (packetMSG.footer[packetMSG.syncIndex] == in_byte) { // footer char recieved packetMSG.syncIndex++; if (packetMSG.syncIndex == FOOTER_SIZE) { // finish footer SYNC packetMSG.syncFlag = 3; // copy packet to json buffer memcpy (&json, &packetMSG.buffer, packetMSG.bufferIndex); json[packetMSG.bufferIndex]=NULL; // end with NULL to indicate end of string // copy packet to json buffer with sprintf //sprintf(json, "%.*s", packetMSG.bufferIndex, packetMSG.buffer ); // send msg to parse. parsePacket(); // reset buffer packetMSG.bufferIndex = 0; packetMSG.syncIndex = 0; packetMSG.syncFlag = 0; } } else { // footer broke restart wait for footer packetMSG.syncFlag=1; // verify that it didnt broke on first footer char if (packetMSG.footer[0] == in_byte) { packetMSG.syncIndex=1; } else { packetMSG.syncIndex=0; } } break; } default: { pc.printf("Sonmething went wrong \r\n"); break; } } // end switch }// end uart readable } // end rxCallback // initialize packet struct void initPacket(void) { // init variables to default: packetMSG.header[0] = 'j'; packetMSG.header[1] = 's'; packetMSG.header[2] = 'o'; packetMSG.header[3] = 'n'; packetMSG.header[4] = ':'; packetMSG.footer[0]= 13; // /r packetMSG.footer[1]= 10; // /n packetMSG.syncIndex=0; // sync index for header / footer packetMSG.syncFlag=0; // 0 - waiting for header, 1 - waiting for footer, 2 - verify footer, 3 - finish footer send to parser, flash buffer packetMSG.bufferIndex=0; // buffer index }// end init Packet struct // Packet Parser void parsePacket(void) { string targetName; #ifdef DEBUG_MOD2 // write buffer to screen //pc.printf("%d, %.*s", packetMSG.bufferIndex ,packetMSG.bufferIndex, packetMSG.buffer ); pc.printf("%s", json); #endif // GUI message format Switch: {"name":"switch","mic":0, "spk": [0,1,0,0,0]} parse(guiCmd, json); // get target: targetName = guiCmd["name"].get<string>(); // switch / dsp #ifdef DEBUG_MOD2 // send parsed values pc.printf("targetName: %s \r\n", targetName.c_str()); #endif // select handler based on target mcu if (targetName == "dsp") { dspPacket(); } else if (targetName == "dspParam") { dspParamPacket(); } else if (targetName == "dspFilter") { dspFilterPacket(); } else { #ifdef DEBUG_MOD2 // unrecognised target pc.printf("unrecognised target: %s \r\n", targetName.c_str()); #endif } // led blink led = !led; }// end parse // DSP Packet Handler void dspPacket(void) { string modeType; // get operation mode modeType = guiCmd["mode"].get<string>(); #ifdef DEBUG_MOD10 // send parsed values pc.printf("mode: %s\r\n", modeType.c_str()); //switch_dsp.printf("mode: %s\r\n", modeType.c_str()); #endif // selected operation mode if ( modeType == "off" ) { FilterFunction = offMode; operationMode = 0 ; } else if( modeType == "passthrough" ) { FilterFunction = passthrough; operationMode = 1 ; } else if( modeType == "highpass" ) { FilterFunction = highpass; operationMode = 2 ; } else if( modeType == "hpf_trig" ) { FilterFunction = highpassTrig; operationMode = 3 ; } else if( modeType == "gain_trig" ) { FilterFunction = GainsTrig; operationMode = 4 ; } else { switch_dsp.printf("undefined mode %s \r\n", modeType.c_str()); FilterFunction = offMode; operationMode = 0 ; } // succesfull parse switch_dsp.printf("{\"Ack\":\"dsp\",\"mode\":\"%s\"}\r\n",modeType.c_str()); }// end dspPacket // DSP Param Packet Handler void dspParamPacket(void) { // get values. signalGain = ((float)guiCmd["gain"].get<int>())/1000; // issue in parsing doubles when the number is round trigTresh = ((float)guiCmd["trigTresh"].get<int>()) / 100.0f; trigDelaySet = (uint32_t)guiCmd["trigPass"].get<int>(); trigPause = (uint32_t)guiCmd["trigPause"].get<int>(); trigDelay = trigDelaySet; #ifdef DEBUG_MOD10 // send parsed values pc.printf("SignalGain: %.3f , trigTresh: %.3f , trigDelaySet %d , trigPause: %d\r\n", signalGain , trigTresh , trigDelaySet , trigPause); #endif // succesfull parse switch_dsp.printf("{\"Ack\":\"dspParam\",\"SignalGain\":%.3f,\"trigTresh\":%.3f,\"trigDelaySet\":%d,\"trigPause\":%d}\r\n", signalGain , trigTresh , trigDelaySet , trigPause); } // end dspParamPacket // DSP Filter Packet Handler void dspFilterPacket(void) { // get values. FilterSections = (guiCmd["Sections"].get<int>()); Gscale = ((float)(guiCmd["Gscale"].get<int>()))/10000.0f; // issue in parsing doubles // get SOSMat for (int jj=0 ; jj < FilterSections ; jj++){ for (int ii=0 ; ii < 5 ; ii++) { SOSMat[jj][ii] = ((float)guiCmd["SOSMat"][jj][ii].get<int>())/10000.0f; } } #ifdef DEBUG_MOD10 // send parsed values pc.printf("FilterSections: %d , Gscale: %.3f\r\n", FilterSections , Gscale); pc.printf("SOSMat \r\n"); for (int jj=0 ; jj < FilterSections ; jj++){ 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]); } #endif // succesfull parse switch_dsp.printf("{\"Ack\":\"dspFilter\",\"FilterSections\":%d,\"Gscale\":%.3f}\r\n", FilterSections , Gscale); } // end dspFilterPacket