Mon, 09 Nov 2020 23:05:24 +0100
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.
src/hp34comm.cpp | file | annotate | diff | comparison | revisions | |
src/hp34comm.h | file | annotate | diff | comparison | revisions | |
src/main.cpp | file | annotate | diff | comparison | revisions |
--- 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 <keycode> 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) {
--- 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 {
--- 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())) {