Sat, 29 Oct 2016 23:44:31 +0200
[full replacement] implement a state machine for Rx
#ifndef HP34COMM_H #define HP34COMM_H #include "mbed.h" #include "CircularBuffer.h" /***** HP 34970A communication class ***/ #define MAX_ERRS 10 #define MAX_BUFF 16 #define BUF_SIZE 16 class HPSerial { public: typedef struct _CMD { uint8_t cmd; uint8_t size; char value[MAX_BUFF+1]; unsigned long id; } CMD; HPSerial(PinName tx, PinName rx); bool cmd_available(void); bool pop(CMD& cmd); bool cmd_buf_full(void); unsigned int nerrors(uint8_t errorno); private: void pushCmd(uint8_t cmd, uint8_t size, char *payload); void rxIrq(void); void timeout(void); private: RawSerial serial; uint8_t buf[BUF_SIZE]; uint8_t head; CircularBuffer<CMD, 32> 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