Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed MbedJSONValue
main.cpp
- Committer:
- Arkadi
- Date:
- 2018-08-26
- Revision:
- 10:e4e3f5af6b0a
- Parent:
- 9:e893fa820315
- Child:
- 11:db4e51a318c2
File content as of revision 10:e4e3f5af6b0a:
////////////////////////////////////////
// Tau_ReSpeaker_Sitch_V01 //
// Arkadiraf@gmail.com - 26/08/2018 //
////////////////////////////////////////
/*
json format: json:{"name":"auto"} - automatic mode
Json Format: json:{"name":"switch","mic":0, "spk": [0,1,0,0,0]} - manual mode
*/
/*
Bugs:
PA_14 and PA_13 are share with stlink - not available as interrupt pins
Used in polling mode instead
didnt switch to spk 5 - changed spk limits in auto switch perhaps this was the issue.
*/
/*
Board : Nucleo STM32F446RE
Power Source : USB || Jumper 5V source from STM32 DSP board
*/
/*
Nucleo board modification:
to use PH_0(MUX_S2) as IO modify boards as followed:
SB54 and SB55 ON
SB16 and SB50 (MCO) OFF
For use GPIO PC15 , PC14
SB48 and SB49 ON
R34 and R36 removed
http://www.st.com/content/ccc/resource/technical/document/user_manual/98/2e/fa/4b/e0/82/43/b7/DM00105823.pdf/files/DM00105823.pdf/jcr:content/translations/en.DM00105823.pdf
*/
/*
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)
MUX: CD74HC4067
PC_12 --> MUX_S0
PD_2 --> MUX_S1
PH_0 --> MUX_S2
PH_1 --> MUX_S3
Speaker Switch : SN74LVC1G3157
PB_2 --> EN_SPK_1
PB_1 --> EN_SPK_2
PB_15 --> EN_SPK_3
PB_14 --> EN_SPK_4
PB_13 --> EN_SPK_5
DSP Interrupt
PA_10 --> DSP_Trigger
MIC Interrupts:
PC_15 --> INTER_1
PC_14 --> INTER_2
PA_15 --> INTER_3
PA_14 --> INTER_4
PA_13 --> INTER_5
Digital Input
PC_13 --> BTN (Blue)
Analog Input
PA_0 --> A_DATA_1
PA_1 --> A_DATA_2
PA_4 --> A_DATA_3
PB_0 --> A_DATA_4
PC_1 --> A_DATA_5
Analog Output
*/
///////////////
// Libraries //
///////////////
#include "mbed.h"
#include "MbedJSONValue.h"
//#include <string>
///////////////
// #defines //
///////////////
//#define DEBUG_MOD1 // json packet recognise
//#define DEBUG_MOD2 // json parse
//#define DEBUG_MOD3 // switch handler
//#define DEBUG_MOD4 // serial with dsp module
//#define DEBUG_MOD10 // responsivity msges to gui
bool debuggingEn = 0;
#define MSG_BUFFER_SIZE 512
#define HEADER_SIZE 5
#define FOOTER_SIZE 2
#define TICKS2TOGGLE 1000000
/////////////
// Objects //
/////////////
// Time stamp timer
Timer timeStamp;
// Frequency Counter timer
Timer freqTimer;
// json
MbedJSONValue guiCmd;
// uart
Serial pc(USBTX, USBRX);
// uart switch_dsp
Serial dsp(PC_10, PC_11);
// digital input
DigitalIn user_button(PC_13);
// digital output
DigitalOut led(PA_5);
// interrup from dsp mcu (frequency counter)
InterruptIn dsp_trigger(PA_10);
// MUX: CD74HC4067
DigitalOut mux_s0(PC_12);
DigitalOut mux_s1(PD_2);
DigitalOut mux_s2(PH_0);
DigitalOut mux_s3(PH_1);
// speaker switch
DigitalOut en_spk_1(PB_2);
DigitalOut en_spk_2(PB_1);
DigitalOut en_spk_3(PB_15);
DigitalOut en_spk_4(PB_14);
DigitalOut en_spk_5(PB_13);
// MIC interrupts
DigitalIn inter_1(PC_15 , PullDown);
DigitalIn inter_2(PC_14 , PullDown);
DigitalIn inter_3(PA_15 , PullDown);
DigitalIn inter_4(PA_14 , PullDown);
DigitalIn inter_5(PA_13 , PullDown);
// analog input
AnalogIn a_data_1(PA_0);
AnalogIn a_data_2(PA_1);
AnalogIn a_data_3(PA_4);
AnalogIn a_data_4(PB_0);
AnalogIn a_data_5(PC_1);
///////////////
// variables //
///////////////
// analog input from microphone
uint16_t micAData[5]= {0};
// mic interrupt flag
int micInterrupt = 0;
bool autoFlag = 0; // automatic mode flag
// 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;
// Frequency calculator
volatile int freqTimeInterval = 0;
volatile bool dspIntFlag = 0;
///////////////
// Functions //
///////////////
// mic interrupt functions - not used, Polling mode
//void micInt_1()
//{
// micInterrupt = 1;
//}
//void micInt_2()
//{
// micInterrupt = 2;
//}
//void micInt_3()
//{
// micInterrupt = 3;
//}
//void micInt_4()
//{
// micInterrupt = 4;
//}
//void micInt_5()
//{
// micInterrupt = 5;
//}
// Serial Event function
void rxCallback(void);
// serial event from DSP
void rxDspCallback(void);
// initialize packet struct
void initPacket(void);
// Packet Parser
void parsePacket(void);
// switch Packet Handler
void switchPacket(void);
// initialize switch
void initSwitch(void);
// poll mic interrupt gpio
bool micPolling(void);
// Atuomatic Switch Handler
void autoSwitch(int micEvent);
// interrup event from the dsp (frequency counter)
void dspInterrupt();
////////////////////////
// Main Code Setup : //
////////////////////////
int main()
{
// init packet:
initPacket();
// init uart
pc.baud(57600);
dsp.baud(57600);
// attach serial event interrupt
pc.attach(&rxCallback, Serial::RxIrq);
// attach serial event interrupt
dsp.attach(&rxDspCallback, Serial::RxIrq);
// initialize switch
initSwitch();
#ifdef DEBUG_MOD1
pc.printf("ReSpeaker Test \r\n");
#endif
///////////////////////
// Main Code Loop : //
///////////////////////
while(1) { // GPIO polling for mic events
// frquency counter
if (dspIntFlag){
double calculatedFrequencyDouble = (double) (TICKS2TOGGLE * 2.0 ) / freqTimeInterval; // Calculated in MHz
int calculatedFrequency = (int) (calculatedFrequencyDouble * 1000000); // convert to hz
pc.printf("{\"event\":\"dspFreq\",\"Freq\":%d}\r\n",calculatedFrequency); // Printf
dspIntFlag=0;
}
if(0) { // no analog data to read (not implemented yet
micAData[0] = a_data_1.read_u16();
micAData[1] = a_data_2.read_u16();
micAData[2] = a_data_3.read_u16();
micAData[3] = a_data_4.read_u16();
micAData[4] = a_data_5.read_u16();
pc.printf("Data:%d,%d,%d,%d,%d\r\n",micAData[0],micAData[1],micAData[2],micAData[3],micAData[4]);
wait(1);
}
// change to interrupt - Problematic as PA_14 and PA_13 are share with stlink
if (micPolling()) { // simple polling of interrupt signals
if (autoFlag) { // update switch based on automatic selection
autoSwitch(micInterrupt);
}
if (1) { // send to pc event time
float callTime = timeStamp.read();
//pc.printf("IntMic: %d time: %.3f \r\n",micInterrupt,callTime); // Printf generates delay of about 5 millis
// send json formatted
pc.printf("{\"event\":\"micInt\",\"mic\":%d,\"time\":%.3f}\r\n",micInterrupt,callTime); // Printf generates delay of about 5 millis
// led blink
led = !led;
//wait(0.1);
// reset micInterrupt flag
micInterrupt=0;
}
}
}// end main loop
}// end main
///////////////
// Functions //
///////////////
// Interrup event from the dsp (frequency counter)
void dspInterrupt(){
freqTimeInterval = freqTimer.read_us() + 1; // compensate the time takes to read / reset
freqTimer.reset();
dspIntFlag = 1;
}//end dspInterrupt
// Atuomatic Switch Handler
void autoSwitch(int micEvent)
{
int micChannle = 0;
bool spkChannle[5]= {0};
// speaker selection:
// simple selection mode
micChannle = micEvent;
if ((micChannle >= 1) && (micChannle <= 5)) {// verify mic is in the limit
spkChannle[micChannle-1] = 1;
}
// update hardware
// update mic select mux
uint8_t micByte = (uint8_t) micChannle;
mux_s0.write((bool)(micByte & 0b00000001));
mux_s1.write((bool)(micByte & 0b00000010));
mux_s2.write((bool)(micByte & 0b00000100));
mux_s3.write((bool)(micByte & 0b00001000));
// update speakers:
en_spk_1.write(spkChannle[0]);
en_spk_2.write(spkChannle[1]);
en_spk_3.write(spkChannle[2]);
en_spk_4.write(spkChannle[3]);
en_spk_5.write(spkChannle[4]);
// send updated values json formatted
pc.printf("{\"event\":\"switch\",\"mic\":%d,\"spk\":[%d,%d,%d,%d,%d]}\r\n",micChannle,spkChannle[0],spkChannle[1],spkChannle[2],spkChannle[3],spkChannle[4]); // Printf generates delay of about 5 millis
}// end autoSwitch
// initialize switch
void initSwitch(void)
{
// attach serial event interrupt
pc.attach(&rxCallback, Serial::RxIrq);
// attach interrupt event for frequency counting
dsp_trigger.rise(&dspInterrupt);
// start timer
freqTimer.start();
// initialize timer
timeStamp.start();
// attach mic interrupts - Not used, polling mode
//inter_1.rise(&micInt_1);
//inter_2.rise(&micInt_2);
//inter_3.rise(&micInt_3);
//inter_4.rise(&micInt_4);
//inter_5.rise(&micInt_5);
// reset output / input
mux_s0.write(0);
mux_s1.write(0);
mux_s2.write(0);
mux_s3.write(0);
en_spk_1.write(0);
en_spk_2.write(0);
en_spk_3.write(0);
en_spk_4.write(0);
en_spk_5.write(0);
}// end init switch
// poll mic interrupt gpio
bool micPolling(void)
{
bool eventFlag=0;
// implementation of rising interrupt in polling mode:
if (inter_1.read() && (micInterrupt != 1)) {
eventFlag=1;
micInterrupt=1;
}
if (inter_2.read() && (micInterrupt != 2)) {
eventFlag=1;
micInterrupt=2;
}
if (inter_3.read() && (micInterrupt != 3)) {
eventFlag=1;
micInterrupt=3;
}
if (inter_4.read() && (micInterrupt != 4)) {
eventFlag=1;
micInterrupt=4;
}
if (inter_5.read() && (micInterrupt != 5)) {
eventFlag=1;
micInterrupt=5;
}
return eventFlag;
}
// serial event from DSP
void rxDspCallback(void)
{
while (dsp.readable()) {
uint8_t in_byte = dsp.getc();
#ifdef DEBUG_MOD4
pc.putc(in_byte);
#endif
}
} // end rxDspCallback
// Serial Event function
void rxCallback(void)
{
while (pc.readable()) {
// read icoming
//led = !led;
uint8_t in_byte = pc.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
}
// 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);
if (debuggingEn){
pc.printf("%s", 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 == "switch") {
// disable automatic mode
autoFlag=0;
// update controls
switchPacket();
} else if ((targetName == "dsp") || (targetName == "dspParam")) {
// send msg to dsp
dsp.printf("json:%s", json);
#ifdef DEBUG_MOD2
pc.printf("json:%s", json);
#endif
}
if (targetName == "auto") {
// automatic mode
autoFlag=1;
} else {
#ifdef DEBUG_MOD2
// unrecognised target
pc.printf("unrecognised target: %s \r\n", targetName.c_str());
#endif
}
// led blink
led = !led;
}// end parse
// switch Packet Handler
void switchPacket(void)
{
int micChannle = 0;
bool spkChannle[5]= {0};
// get debbug status
debuggingEn = guiCmd["debug"].get<int>();
// get mic channle
micChannle = guiCmd["mic"].get<int>();
// get speakers output
for (int ii=0 ; ii < 5 ; ii++) {
spkChannle[ii] = guiCmd["spk"][ii].get<bool>();
}
#ifdef DEBUG_MOD10
// send parsed values
pc.printf("mic: %d , spk: [%d,%d,%d,%d,%d]\r\n", micChannle,spkChannle[0],spkChannle[1],spkChannle[2],spkChannle[3],spkChannle[4]);
#endif
// update hardware
// update mic select mux
uint8_t micByte = (uint8_t) micChannle;
mux_s0.write((bool)(micByte & 0b00000001));
mux_s1.write((bool)(micByte & 0b00000010));
mux_s2.write((bool)(micByte & 0b00000100));
mux_s3.write((bool)(micByte & 0b00001000));
// update speakers:
en_spk_1.write(spkChannle[0]);
en_spk_2.write(spkChannle[1]);
en_spk_3.write(spkChannle[2]);
en_spk_4.write(spkChannle[3]);
en_spk_5.write(spkChannle[4]);
// end switch target parse
}// end switch packet