Refactor HPSerial to get rid of packet collision misbehavior draft

Mon, 09 Nov 2020 23:05:24 +0100

author
David Douard <david.douard@sdf3.org>
date
Mon, 09 Nov 2020 23:05:24 +0100
changeset 49
c146d19101a3
parent 48
fc55f6eaa8bc
child 50
279868684eb3

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()))
     {

mercurial