# HG changeset patch # User David Douard # Date 1604959524 -3600 # Node ID c146d19101a3de2b570a726a84db1fd1aaf01e07 # Parent fc55f6eaa8bce3f4af4c45c005bb7e886730592e Refactor HPSerial to get rid of packet collision misbehavior completely split the key sending code from the irq-based receiveing logic. When sending keycodes, disable the RxIrq callback and handle send and recv of bytes synchronously. The keycode sending routine rus in a dedicated thread. diff -r fc55f6eaa8bc -r c146d19101a3 src/hp34comm.cpp --- a/src/hp34comm.cpp Sat Nov 07 19:24:11 2020 +0100 +++ b/src/hp34comm.cpp Mon Nov 09 23:05:24 2020 +0100 @@ -32,6 +32,7 @@ serial.baud(187500); serial.format(8, BufferedSerial::Even, 1); cur_state = STATE_IDLE; + send_thread.start(callback(this, &HPSerial::send_pending_key)); serial.attach(callback(this, &HPSerial::rx_irq), SerialBase::RxIrq); } @@ -69,6 +70,118 @@ sendbuf.push(keycode); } + +bool HPSerial::wait_for(uint8_t value) +{ + char c; + + for(uint8_t i=0; i<2; i++) + { + while(!serial.readable()) + wait_us(10); + //ThisThread::sleep_for(0.1ms); + serial.read(&c, 1); + if (value == c) + return true; + } + return false; +} + +void HPSerial::send_pending_key() { + uint8_t c; + + while(true) + { + if (!sendbuf.empty()) + { + if (cur_gstate == GSTATE_IDLE) + { + serial.attach(0, SerialBase::RxIrq); + cur_gstate = GSTATE_TX; + + c = 0x66; + serial.write(&c, 1); + if (!wait_for(0x99)) {} + // break; // XXX what to do? + + sendbuf.pop(c); + serial.write(&c, 1); + if (!wait_for(0x00)) {} + + c = 0x55; + serial.write(&c, 1); + cur_gstate = GSTATE_IDLE; + serial.attach(callback(this, &HPSerial::rx_irq), SerialBase::RxIrq); + } + } + //else // prevent from flooding the main unit + ThisThread::sleep_for(5ms); + } +} + +void HPSerial::send_startup_seq(uint8_t keycode) { + uint8_t c; + + while (cur_gstate != GSTATE_IDLE) { + ThisThread::sleep_for(1ms); + } + + serial.attach(0, SerialBase::RxIrq); + cur_gstate = GSTATE_TX; + + // Send the init seq 0x33 0x02 0xFF 0x55 + c = 0x33; + serial.write(&c, 1); + if (!wait_for(0xCC)) {} + + c = 0x02; + serial.write(&c, 1); + if (!wait_for(0x00)) {} + + c = 0xFF; + serial.write(&c, 1); + if (!wait_for(0x00)) {} + + c = keycode; + serial.write(&c, 1); + if (!wait_for(0x00)) {} + + c = 0x55; + serial.write(&c, 1); + cur_gstate = GSTATE_IDLE; + serial.attach(callback(this, &HPSerial::rx_irq), SerialBase::RxIrq); + +} + +void HPSerial::send_startup_seq() { + uint8_t c; + + while (cur_gstate != GSTATE_IDLE) { + ThisThread::sleep_for(1ms); + } + + serial.attach(0, SerialBase::RxIrq); + cur_gstate = GSTATE_TX; + + // Send the init seq 0x33 0x02 0x00 0x55 + c = 0x33; + serial.write(&c, 1); + if (!wait_for(0xCC)) {} + + c = 0x02; + serial.write(&c, 1); + if (!wait_for(0x00)) {} + + c = 0x00; + serial.write(&c, 1); + if (!wait_for(0x00)) {} + + c = 0x55; + serial.write(&c, 1); + cur_gstate = GSTATE_IDLE; + serial.attach(callback(this, &HPSerial::rx_irq), SerialBase::RxIrq); +} + void HPSerial::send_key_when_idle() { if (!sendbuf.empty() && cur_gstate == GSTATE_IDLE) { diff -r fc55f6eaa8bc -r c146d19101a3 src/hp34comm.h --- a/src/hp34comm.h Sat Nov 07 19:24:11 2020 +0100 +++ b/src/hp34comm.h Mon Nov 09 23:05:24 2020 +0100 @@ -33,6 +33,8 @@ void startup(uint8_t keycode=0xFF); void sendkey(uint8_t keycode); void send_key_when_idle(); + void send_startup_seq(); + void send_startup_seq(uint8_t keycode); private: void pushCmd(uint8_t cmd, uint8_t size, char *payload); @@ -54,6 +56,11 @@ unsigned int errs[MAX_ERRS]; Ticker timeouter; + Thread send_thread; + void send_pending_key(); + bool wait_for(uint8_t); + + public: // global state machine typedef enum { diff -r fc55f6eaa8bc -r c146d19101a3 src/main.cpp --- a/src/main.cpp Sat Nov 07 19:24:11 2020 +0100 +++ b/src/main.cpp Mon Nov 09 23:05:24 2020 +0100 @@ -270,9 +270,9 @@ dsp->cls(); printf("Initiate startup sequence\n"); if (last_key.keyevent == KEY_PRESSED) - hp->startup(kp_mapping[last_key.row][last_key.col]); + hp->send_startup_seq(kp_mapping[last_key.row][last_key.col]); else - hp->startup(); + hp->send_startup_seq(); } else { @@ -366,8 +366,8 @@ } // at each loop iteration, send buffered keycodes, if any - if (hp != NULL) - hp->send_key_when_idle(); + //if (hp != NULL) + // hp->send_key_when_idle(); if ((hp != NULL) && (hp->cmd_available())) {