ReSpeaker DSP V02

Dependencies:   mbed MbedJSONValue

main.cpp

Committer:
Arkadi
Date:
2018-08-06
Revision:
7:25c81cb23e42
Parent:
6:e8b4ca41c691
Child:
8:8a3e6241c104

File content as of revision 7:25c81cb23e42:

////////////////////////////////////////
//      Tau_ReSpeaker_DSP V01         //
//  Arkadiraf@gmail.com - 09/04/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)

    Digital Input
    PA_10 --> SW_Trigger
    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 512
#define HEADER_SIZE 5
#define FOOTER_SIZE 2

/////////////
// 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);
DigitalIn sw_trigger(PA_10);
DigitalOut led(PA_5);
DigitalOut mytoggle(PA_6);

// 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 //
///////////////

// 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 trigTresh = 0.75; // threshold for trigger mode
uint32_t trigDelaySet = 3000; // counter for pulse pass
uint32_t trigDelay = trigDelaySet; // counter for pulse pass
uint32_t trigPause = 5000; // pause after trigger in microseconds

///////////////
// 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);

// 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
    } // 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 {
#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 ;
    }

}// end dspPacket