diff -r 4fd621551d55 -r a52d60613cf7 src/hp34comm.cpp --- a/src/hp34comm.cpp Sat Oct 29 23:44:31 2016 +0200 +++ b/src/hp34comm.cpp Wed Jan 18 23:19:13 2017 +0100 @@ -7,38 +7,111 @@ #ifdef DEBUG2 DigitalOut inrx(D9); -DigitalOut intx(D5); -DigitalOut ack(D6); -DigitalOut staterx(A0); -DigitalOut statetx(D10); #endif DigitalOut lled(LED1); +#define RXTIMEOUT 0.05 +#define STARTUPRETRY 0.5 +const uint8_t startup_seq[] = { + 0x33, + 0x01, + 0x01, + 0x40, + // 0x02, +}; +const uint8_t startup_seq2[] = { + 0x33, + 0x02, + 0x00, + 0x00, + // 0x02, +}; + +HPSerial::statemethod HPSerial::state_table[NUM_STATES] = { + &HPSerial::do_state_initial, + &HPSerial::do_state_command, + &HPSerial::do_state_payload_size, + &HPSerial::do_state_payload, + &HPSerial::do_state_sending, + &HPSerial::do_state_eot, +}; HPSerial::HPSerial(PinName tx, PinName rx): - serial(tx, rx) + serial(tx, rx), + cur_gstate(GSTATE_IDLE), + ncmd(0) { - cur_state = do_state_initial(&rx_data, 0x00); - serial.baud(187500); - serial.attach(this, &HPSerial::rxIrq, Serial::RxIrq); + serial.baud(187500); + cur_state = STATE_IDLE; + serial.attach(callback(this, &HPSerial::rxIrq), Serial::RxIrq); +} + +void HPSerial::startup(void) { + if (cur_gstate != GSTATE_STARTING) { + //_startup(); + cur_gstate = GSTATE_STARTING; + } + set_timer(0.002); // launch the startup in 10ms +} + +void HPSerial::_startup(void) +{ + cur_gstate = GSTATE_STARTING; + tr_data.size = sizeof(startup_seq); + tr_data.cmd = 0xFF; + tr_data.pos = 0; + for(uint8_t i=0; i + //send(startup, sizeof(startup)/sizeof(startup[0])); +} + +void HPSerial::sendkey(uint8_t keycode) +{ + tr_data.size = 2; + tr_data.cmd = 0xFF; + tr_data.pos = 0; + tr_data.payload[0] = 0x66; + tr_data.payload[1] = keycode; + cur_state = do_state_sending(); +} + +bool HPSerial::cmd_available(void) +{ return !cmdbuf.empty(); } -bool HPSerial::pop(CMD& cmd) { +bool HPSerial::pop(CMD& cmd) +{ return cmdbuf.pop(cmd); } -bool HPSerial::cmd_buf_full(void) { +bool HPSerial::cmd_buf_full(void) +{ return cmdbuf.full(); } -unsigned int HPSerial::nerrors(uint8_t errorno) { +unsigned int HPSerial::nerrors(uint8_t errorno) +{ return errs[errorno]; } @@ -55,79 +128,108 @@ } 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); + set_timer(RXTIMEOUT); // if nothing else happen in the next ms, reset } -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) +HPSerial::state_t HPSerial::do_state_initial(uint8_t c) { // we are idle, incoming char is a handcheck // knwon handcheck values are 0x66 and 0x33 + set_timer(RXTIMEOUT); // reset the watchdog switch (c) { case 0x33: send_ack(0xCC); return HPSerial::STATE_PAYLOAD_SIZE; break; + case 0x55: // EoT + return HPSerial::STATE_IDLE; + break; case 0x66: send_ack(0x99); return HPSerial::STATE_COMMAND; break; - default: - return do_state_initial(data, 0x00); + case 0xFF: + return HPSerial::STATE_IDLE; + default: // unknown value + send_ack(0xFF); + return HPSerial::STATE_IDLE; } } -HPSerial::state_t HPSerial::do_state_command(HPSerial::instance_data_t *data, - uint8_t c) +HPSerial::state_t HPSerial::do_state_command(uint8_t c) { if (c == 0x55) { // EoT - return do_state_initial(data, 0x00); + return STATE_IDLE; } - data->cmd = c; - data->size = 0; + tr_data.cmd = c; + tr_data.size = 0; + tr_data.pos = 0; send_ack(0x00); - return HPSerial::STATE_PAYLOAD_SIZE; + + if (c == 0x86) { // shutdown + pushCmd(tr_data.cmd, tr_data.size, tr_data.payload); + return HPSerial::STATE_IDLE; + } + return STATE_PAYLOAD_SIZE; } -HPSerial::state_t HPSerial::do_state_payload_size(HPSerial::instance_data_t *data, - uint8_t c) +HPSerial::state_t HPSerial::do_state_payload_size(uint8_t c) { - data->size = c; - data->received = 0; + tr_data.size = c; + tr_data.pos = 0; send_ack(0x00); - return HPSerial::STATE_PAYLOAD; + return STATE_PAYLOAD; } -HPSerial::state_t HPSerial::do_state_payload(HPSerial::instance_data_t *data, - uint8_t c) +HPSerial::state_t HPSerial::do_state_payload(uint8_t c) { - data->payload[data->received++] = c; + tr_data.payload[tr_data.pos++] = c; send_ack(0x00); - if (data->received >= data->size) { - pushCmd(data->cmd, data->size, data->payload); - return HPSerial::STATE_COMMAND; + if (tr_data.pos >= tr_data.size) { + pushCmd(tr_data.cmd, tr_data.size, tr_data.payload); + return HPSerial::STATE_IDLE; } return HPSerial::STATE_PAYLOAD; } +HPSerial::state_t HPSerial::do_state_sending(uint8_t c) +{ + // ghee + if (c == 0xFF) + { + tr_data.pos--; + tr_data.payload[tr_data.pos] += 1; + } + // TODO: check ACK values (c is the received ack) + if (tr_data.pos >= tr_data.size) + { + return do_state_eot(); + } + serial.putc(tr_data.payload[tr_data.pos++]); + set_timer(RXTIMEOUT); + return HPSerial::STATE_SENDING; +} + +HPSerial::state_t HPSerial::do_state_eot(uint8_t c) +{ + serial.putc(0x55); // EoT + if (cur_gstate == GSTATE_STARTING) { + cur_gstate = GSTATE_STARTING2; + set_timer(0.002); // launch startup2 in 10ms + } + else { + cur_gstate = GSTATE_IDLE; + set_timer(); // We are IDLE, detach the timeouter + } + return STATE_IDLE; +} + 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); + return (this->*(HPSerial::state_table[cur_state]))(c); }; void HPSerial::rxIrq(void) { @@ -139,7 +241,7 @@ #endif lled = 1; val = serial.getc(); - cur_state = run_state(cur_state, &rx_data, val); + cur_state = run_state(cur_state, val); lled = 0; #ifdef DEBUG2 inrx=0; @@ -149,5 +251,16 @@ void HPSerial::timeout(void) { - cur_state = do_state_initial(&rx_data, 0x00); + set_timer(); // detach the timeouter + if (cur_gstate == GSTATE_STARTING) + _startup(); + else if (cur_gstate == GSTATE_STARTING2) + _startup2(); + else // reset + { + cur_gstate = GSTATE_IDLE; + cur_state = STATE_IDLE; + } } + +