# HG changeset patch # User David Douard # Date 1477777471 -7200 # Node ID 4fd621551d5536c7239bc3632c7b0ddd578772d5 # Parent 162fe523c37d7fc9d21d2f1688f7a84cf7bad0c9 [full replacement] implement a state machine for Rx diff -r 162fe523c37d -r 4fd621551d55 src/hp34comm.cpp --- a/src/hp34comm.cpp Wed Oct 26 22:41:16 2016 +0200 +++ b/src/hp34comm.cpp Sat Oct 29 23:44:31 2016 +0200 @@ -15,19 +15,15 @@ #endif DigitalOut lled(LED1); - -HPSerial::HPSerial(PinName rx): - serial_rx(NC, rx), - ncmd(0) { - - //pc.printf("HPSerial init\n"); + + - for(uint8_t i=0; i 0) { - // a payload char - buf[head++] = val; - tx_len--; - tx_ack = false; - } - else { // end of payload, manage sent content - uint8_t cur_state = tx_state; - pushCmd((TrState)tx_state, tx_cmd, head, (char*)buf); - - switch(val) { - case 0x66: // a new transmisson - reset(); - tx_state = cur_state; - setstatedbg(); - break; - case 0x55: - reset(); - break; - default: - reset(6); - break; - } - } +void HPSerial::send_ack(uint8_t c) { + timeouter.attach(this, &HPSerial::timeout, 0.001); // if nothing else happen in the next ms, reset + serial.putc(c); +} + +HPSerial::state_t HPSerial::do_state_initial(HPSerial::instance_data_t *data, + uint8_t c) +{ + // go back to initial state + data->cmd = 0xFF; + data->size = 0; + data->received = 0; + timeouter.detach(); + return HPSerial::STATE_IDLE; +} + +HPSerial::state_t HPSerial::do_state_handcheck(HPSerial::instance_data_t *data, + uint8_t c) +{ + // we are idle, incoming char is a handcheck + // knwon handcheck values are 0x66 and 0x33 + switch (c) { + case 0x33: + send_ack(0xCC); + return HPSerial::STATE_PAYLOAD_SIZE; + break; + case 0x66: + send_ack(0x99); + return HPSerial::STATE_COMMAND; + break; + default: + return do_state_initial(data, 0x00); + } } +HPSerial::state_t HPSerial::do_state_command(HPSerial::instance_data_t *data, + uint8_t c) +{ + if (c == 0x55) { // EoT + return do_state_initial(data, 0x00); + } + data->cmd = c; + data->size = 0; + send_ack(0x00); + return HPSerial::STATE_PAYLOAD_SIZE; +} -void HPSerial::setstatedbg(void) { -#ifdef DEBUG2 - if (tx_state == Rx) - staterx = 1; - else - staterx = 0; - if (tx_state == Tx) - statetx = 1; - else - statetx = 0; -#endif +HPSerial::state_t HPSerial::do_state_payload_size(HPSerial::instance_data_t *data, + uint8_t c) +{ + data->size = c; + data->received = 0; + send_ack(0x00); + return HPSerial::STATE_PAYLOAD; } +HPSerial::state_t HPSerial::do_state_payload(HPSerial::instance_data_t *data, + uint8_t c) +{ + data->payload[data->received++] = c; + send_ack(0x00); + if (data->received >= data->size) { + pushCmd(data->cmd, data->size, data->payload); + return HPSerial::STATE_COMMAND; + } + return HPSerial::STATE_PAYLOAD; +} + +HPSerial::state_t HPSerial::run_state(HPSerial::state_t cur_state, + HPSerial::instance_data_t *data, + uint8_t c) +{ + return (this->*(HPSerial::state_table[cur_state]))(data, c); +}; + void HPSerial::rxIrq(void) { uint8_t val; - if(serial_rx.readable()) { // no reason why we would end here without this condition, but hey + if(serial.readable()) { // no reason why we would end here without + // this condition, but hey #ifdef DEBUG2 inrx=1; #endif lled = 1; - val = serial_rx.getc(); - - timeouter.attach(this, &HPSerial::timeout, 0.001); // if nothing else happen in the next ms, reset - - if (tx_state == Idle) - if (val == 0x66) { - // no transmission in progress, expect a start of transmission - tx_state = Rx; - tx_ack = false; - setstatedbg(); - } - else { - reset(4); - } - else if (tx_ack == false) // manage the acks - handleAck(val); - else - handleChar(val); + val = serial.getc(); + cur_state = run_state(cur_state, &rx_data, val); lled = 0; #ifdef DEBUG2 inrx=0; @@ -227,7 +149,5 @@ void HPSerial::timeout(void) { - if (tx_state != Idle) { - reset(7); - } + cur_state = do_state_initial(&rx_data, 0x00); } diff -r 162fe523c37d -r 4fd621551d55 src/hp34comm.h --- a/src/hp34comm.h Wed Oct 26 22:41:16 2016 +0200 +++ b/src/hp34comm.h Sat Oct 29 23:44:31 2016 +0200 @@ -10,17 +10,13 @@ #define MAX_BUFF 16 #define BUF_SIZE 16 + + class HPSerial { public: - enum TrState { - Idle = 0, - Tx, - Rx, - }; typedef struct _CMD { - TrState direction; uint8_t cmd; uint8_t size; char value[MAX_BUFF+1]; @@ -29,7 +25,7 @@ - HPSerial(PinName rx); + HPSerial(PinName tx, PinName rx); bool cmd_available(void); bool pop(CMD& cmd); @@ -38,26 +34,57 @@ private: - void reset(uint8_t errorno=0xFF); - void handleAck(uint8_t val); - void pushCmd(TrState direction, uint8_t cmd, uint8_t size, char *payload); - void handleChar(uint8_t val); - void setstatedbg(void); + void pushCmd(uint8_t cmd, uint8_t size, char *payload); void rxIrq(void); void timeout(void); private: - RawSerial serial_rx; + RawSerial serial; uint8_t buf[BUF_SIZE]; uint8_t head; - uint8_t tx_state; - uint8_t tx_cmd; - uint8_t tx_len; - bool tx_ack; CircularBuffer cmdbuf; unsigned long ncmd; unsigned int errs[MAX_ERRS]; Ticker timeouter; + + // state machine stuff + typedef enum {STATE_IDLE, + STATE_HANDCHEKED, + STATE_COMMAND, + STATE_PAYLOAD_SIZE, + STATE_PAYLOAD, + NUM_STATES} state_t; + + + typedef struct instance_data { + uint8_t cmd; + uint8_t size; + uint8_t received; + char payload[MAX_BUFF]; + } instance_data_t; + + state_t do_state_initial(instance_data_t *data, uint8_t c); + state_t do_state_handcheck(instance_data_t *data, uint8_t c); + state_t do_state_command(instance_data_t *data, uint8_t c); + state_t do_state_payload_size(instance_data_t *data, uint8_t c); + state_t do_state_payload(instance_data_t *data, uint8_t c); + + void send_ack(uint8_t c); + + // pointer to "state method" (ie. one of the just above) + typedef state_t(HPSerial::*statemethod)(instance_data_t *data, uint8_t c); + statemethod const state_table[NUM_STATES] = { + &HPSerial::do_state_initial, + &HPSerial::do_state_handcheck, + &HPSerial::do_state_command, + &HPSerial::do_state_payload_size, + &HPSerial::do_state_payload, + }; + + state_t run_state(state_t cur_state, instance_data_t *data, uint8_t c); + + state_t cur_state; + instance_data rx_data; }; #endif diff -r 162fe523c37d -r 4fd621551d55 src/main.cpp --- a/src/main.cpp Wed Oct 26 22:41:16 2016 +0200 +++ b/src/main.cpp Sat Oct 29 23:44:31 2016 +0200 @@ -12,6 +12,8 @@ #include "SSD1322.h" #include "hp34comm.h" +#include "Keypad.h" + #if (defined STM32L432xx) // display #define DSP_MOSI PA_7 //A6 @@ -21,6 +23,7 @@ #define DSP_RST PB_5 //D11 #define DSP_DC PB_4 //D12 // UART for RX (CPU->DP) and TX (DP->CPU) combined +#define HP_TX PA_9 // serial1 TX #define HP_RX PA_10 // serial1 RX // misc #define DBGPIN PA_12 @@ -67,6 +70,9 @@ Timeout blinker; DigitalOut led(LED1); +Keypad kpad(std::vector({(int)PA_0, (int)PA_1}), + std::vector({(int)PA_8, (int)PA_11})); + uint8_t curchar; uint8_t cmd; uint8_t nchars; @@ -284,7 +290,7 @@ wait(2); dsp->cls(); - hp = new HPSerial(HP_RX); + hp = new HPSerial(HP_TX, HP_RX); //hp = NULL; } @@ -530,26 +536,23 @@ } for (uint8_t i=0; i<7; i++) err[i] = hp->nerrors(i); - printf("CMD[%s:%d] %02X", (cmd.direction==HPSerial::Rx)?"Rx":"Tx", cmd.id, - cmd.cmd); + printf("CMD[%d] %02X", cmd.id, cmd.cmd); - if (cmd.direction == HPSerial::Rx) { - if ((cmd.cmd == 0x00) || (cmd.cmd == 0x0C)) - printf(": '%s'\n", cmd.value); - else { - printf(":"); - for (uint8_t i=0; i