another attempt using a more complete support of the protocol and async serial stuff draft

Tue, 13 Sep 2016 21:32:48 +0200

author
David Douard <david.douard@logilab.fr>
date
Tue, 13 Sep 2016 21:32:48 +0200
changeset 4
219766126afb
parent 3
a3233abe730e
child 5
f1c85c2500f2

another attempt using a more complete support of the protocol and async serial stuff

src/main.cpp file | annotate | diff | comparison | revisions
--- a/src/main.cpp	Fri Sep 09 23:42:39 2016 +0200
+++ b/src/main.cpp	Tue Sep 13 21:32:48 2016 +0200
@@ -1,21 +1,27 @@
 #include "stdio.h"
+
 #include "mbed.h"
 #include "string"
+#include "CircularBuffer.h"
+
 #include "Terminal6x8.h"
 #include "Mono19x27.h"
 #include "Mono15x22.h"
 #include "Arial12x12.h"
 
-#include "BufferedSerial.h"
-
 #include "SSD1322.h"
 
 Serial pc(USBTX, USBRX);
-BufferedSerial hp(NC, PA_1, 64, 0); // serial4
+
+//BufferedSerial hp(NC, PA_1, 64, 0); // serial4
+#define HP_SERIAL_TX PC_7 // serial6 RX
+#define HP_SERIAL_RX PA_1 // serial4 RX
 
 SSD1322 dsp(SPI_8, 10000000, PB_15, PB_14, PB_13, PB_12, D11, D12, "SSD1322", 256, 64); 
 
-#define MAX_BUFF 14
+#define BUF_SIZE 32
+#define MAX_BUFF 15
+#define MAX_ERRS 10
 uint8_t curchar;
 uint8_t cmd;
 uint8_t nchars;
@@ -137,6 +143,202 @@
 {}
 #endif
 
+
+
+/***** HP 34970A communication class ***/
+
+class HPSerial {
+
+public:
+  enum TrState {
+        Idle = 0,
+        Tx,
+        Rx,
+    };
+  typedef struct _CMD
+  {
+    TrState direction;
+    uint8_t cmd;
+    uint8_t size;
+    char value[MAX_BUFF+1];
+    unsigned long id;
+  } CMD;
+
+
+  
+  HPSerial(): ncmd(0), serial_tx(NC, HP_SERIAL_TX), serial_rx(NC, HP_SERIAL_RX) {
+    pc.printf("HPSerial init\n");
+    for(uint8_t i=0; i<MAX_ERRS; i++)
+      errs[i] = 0;
+    reset();
+
+    serial_tx.baud(187500);
+    serial_tx.attach(this, &HPSerial::txIrq, Serial::RxIrq); //sic!
+
+    serial_rx.baud(187500);
+    serial_rx.attach(this, &HPSerial::rxIrq, Serial::RxIrq);
+  }
+
+  bool cmd_available(void) {
+    return !cmdbuf.empty();
+  }
+
+  bool pop(CMD& cmd) {
+    return cmdbuf.pop(cmd);
+  }
+
+  bool cmd_buf_full(void) {
+    return cmdbuf.full();
+  }
+
+  unsigned int nerrors(uint8_t errorno) {
+    return errs[errorno];
+  }
+    
+		     
+  
+private:
+  void reset(uint8_t errorno=0xFF) {
+    head = 0;
+    tx_state = Idle;
+    tx_cmd = 0xFF;
+    tx_ack = false;
+    tx_len = 0xFF;
+    memset(buf, 0, BUF_SIZE);
+    if (errorno != 0xFF)
+      errs[errorno]++;
+  }
+
+  void handleAck(uint8_t val) {
+    if (tx_ack == true)
+      reset(0);
+
+    else 
+      if (tx_cmd == 0xFF) // still at the beginning of a packet, expect 0x99 as ack
+	if (val == 0x99)
+	  tx_ack = true;
+	else 
+	  reset(1);
+
+      else // expect 0x00 as ack
+	if (val == 0x00)
+	  tx_ack = true;
+	else
+	  reset(2);
+  }
+
+  void pushCmd(TrState direction, uint8_t cmd, uint8_t size, char *payload) {
+    CMD val;
+    uint8_t i;
+    val.id = ncmd++;
+    val.direction = direction;
+    val.cmd = cmd;
+    val.size = size;
+    for(i=0; i<size; i++)
+      val.value[i] = payload[i];
+    val.value[i] = 0x00;
+    cmdbuf.push(val);
+  }
+  
+  void handleChar(uint8_t val) {
+    if (tx_ack == false)
+      reset(3);
+    else // remaining of the state machine
+      if (tx_cmd == 0xFF) {
+	// begin of transmission, expect a cmd
+	tx_cmd = val;
+	tx_ack = false;
+	tx_len = 0xFF;
+      }
+      else if (tx_len == 0xFF) {
+	// got a cmd, expect a payload size
+	tx_len = val;
+	tx_ack = false;
+      }
+      else if (tx_len > 0) {
+	// a payload char
+	buf[head++] = val;
+	tx_len--;
+	tx_ack = false;
+      }
+      else {
+	uint8_t cur_state = tx_state;
+	pushCmd(tx_state, tx_cmd, head, buf); 
+	reset();
+	
+	if (val != 0x55) { // not an end of transmission
+	  // should be another cmd I think
+	  tx_cmd = val;
+	  tx_state = cur_state;
+	}
+      }
+  }
+
+  
+  void rxIrq(void) {
+    uint8_t val;
+    if(serial_rx.readable()) { // no reason why we would end here without this condition, but hey
+      val = serial_rx.getc();
+      
+      if (tx_state == Idle)
+	if (val == 0x66) {
+	  // no transmission in progress, expect a start of transmission
+	  tx_state = Rx;
+	  tx_ack = false;
+	}
+	else
+	  reset(4);
+    
+      else if (tx_state == Tx)  // manage the acks
+	handleAck(val);
+      
+      else 
+	handleChar(val);
+    }
+  }
+  
+  void txIrq(void) {
+    uint8_t val;
+    if(serial_tx.readable()) { // no reason why we would end here without this condition, but hey
+      val = serial_tx.getc();
+      
+      if (tx_state == Idle)
+	if (val == 0x66) {
+	  // no transmission in progress, expect a start of transmission
+	  tx_state = Tx;
+	  tx_ack = false;
+	}
+	else
+	  reset(5);
+    
+      else if (tx_state == Rx)  // manage the acks
+	handleAck(val);
+      
+      else 
+	handleChar(val);
+    }
+  }
+  
+private:
+  RawSerial serial_tx;
+  RawSerial serial_rx;
+  uint8_t buf[BUF_SIZE];
+  uint8_t head;
+  uint8_t tx_state;
+  uint8_t tx_cmd;
+  uint8_t tx_len;
+  bool tx_ack;
+  CircularBuffer<CMD, 32> cmdbuf;
+  unsigned long ncmd;
+  unsigned int errs[MAX_ERRS];
+};
+
+
+HPSerial hp;
+Ticker dsp_refresher;
+volatile bool must_refresh;
+
+void copy_to_lcd(void);
 void test_dsp();
 
 void setup() {
@@ -147,8 +349,6 @@
     pc.printf("\n\nSystem Core Clock = %.3f MHZ\r\n",
           (float)SystemCoreClock/1000000);
 
-    hp.baud(187500);
-
     // myLCD.set_font((unsigned char*) Terminal6x8);
     // myLCD.claim(stdout);      // send stdout to the LCD display
     // myLCD.claim(stderr);      // send stderr to the LCD display
@@ -161,6 +361,7 @@
     cmd = 0xFF;
     curchar = 0;
     nchars = 0;
+
     
     dsp.printf("HP34970A");
     dsp.set_font(Terminal6x8);
@@ -173,14 +374,17 @@
     dsp.copy_to_lcd();
     wait(2);
     dsp.cls();
+    
+    dsp_refresher.attach(&copy_to_lcd, 0.1);
     test_dsp();
     wait(2);
     dsp.cls();
+    
 }
 
-void go_msg() {
-  dsp.set_font((unsigned char*) Arial12x12);
-  dsp.locate(0, 38);
+void copy_to_lcd(void) {
+  if (must_refresh)
+    dsp.copy_to_lcd();
 }
 
 void show(uint8_t cmd, char *txt, uint8_t nchar=0) {
@@ -188,6 +392,8 @@
   uint16_t bgcolor, fgcolor;
   char *oldv;
 
+  must_refresh = false;
+  
   len = MAX_BUFF;
 
   for (i=0; i<sizeof(table)/sizeof(table[0]); ++i) {
@@ -266,8 +472,8 @@
       }
     }
   }
-  dsp.copy_to_lcd();
-
+  must_refresh = true;
+  //dsp.copy_to_lcd();
 }
 
 void test_dsp()
@@ -275,92 +481,32 @@
   show(0x00, "8g8g8g8g8g8g8", 13); // main dsp
   show(0x0C, "888", 3); // channel dsp
   show(0x0A, "\xFF\xFF\xFF\xFF", 4); // flags
-  dsp.copy_to_lcd();
 }
 
 
 void loop() { // run over and over
-  if (hp.readable()) {
-      uint8_t val = hp.getc();
-      DebugPulse(3);
-      // 0xFF: idle
-      // 0xFE: frame finished
-      // 0x66: Start of transmission received
-      pc.printf("  VAL=0x%X\tCMD=0x%X\n", val, cmd);
-      if (cmd == 0xFF) {
-          if ((val == 0x66) || (val == 0x99)) {
-              cmd = val;
-          } else if ((val == 0x00) || (val == 0x55)){
-              // probably an ACK for a keypad related event
-          } else {
-              // display "junk" byte
-              //DebugPulse();
-              show(0xFF, "", 0);
-	      dsp.printf("%02X:> %02x", cmd, val);
-          }
-
-      } else if (cmd == 0xFE ) {
-          if ((val == 0x66) || (val == 0x99)) {
-              cmd = val;
-          } else if (val == 0x55) {
-              cmd = 0xFF;
-          } else if (val == 0x00){
-              // probably an ACK for a keypad related event
-          } else {
-              // display "junk" byte
-              DebugPulse();
-              show(0xFF, "", 5);
-              dsp.printf("%02X=> %02x", cmd, val);
-          }
+  if (hp.cmd_available())
+    {
+      HPSerial::CMD cmd;
+      if (hp.pop(cmd))
+	{
+	  pc.printf("CMD[%s:%d %d/%d/%d/%d/%d/%d] %X\n", (cmd.direction==HPSerial::Rx)?"Rx":"Tx", cmd.id,
+		    hp.nerrors(0), 
+		    hp.nerrors(1), 
+		    hp.nerrors(2), 
+		    hp.nerrors(3), 
+		    hp.nerrors(4), 
+		    hp.nerrors(5), 
+		    cmd.cmd);
 
-      } else if (cmd == 0x66) { // waiting for the display command
-	if ((val == 0x0C) || (val == 0x00) || (val == 0x01) || (val == 0x02) || (val == 0x0A)) {
-              cmd = val;
-              nchars = 0;
-          } else {
-              cmd = 0xFE;
-              // display unknown cmd byte
-              DebugPulse();
-              show(0xFF, "", 10);
-              dsp.printf("%02X-> %02x", cmd, val);
-          }
-
-      } else if (cmd == 0x99) { // waiting for a 0x00, it's the DP that sent a keypress event
-        if (val != 0x00) {
-              show(0xFF, "", 0);
-	      dsp.printf("%02X kp %02X", cmd, val);
-        }
-        cmd = 0xFF;
-
-      } else if (nchars == 0) { // waiting for the number of chars to display
-          if (val>MAX_BUFF) {
-              // display warning
-              //dsp();
-              //dsp << cmd << " got len " << val;
-              //DebugPulse();
-              show(0xFF, "", 0);
-	      dsp.printf("%02X len %d", cmd, val);
-              cmd = 0xFE; // weird
-          } else {
-              nchars = val;
-              curchar = 0;
-          }
-
-      } else { // a character to display
-          buffer[curchar] = val;
-          curchar++;
-          if (curchar == nchars) {
-              buffer[curchar] = 0x00;
-              show(cmd, buffer, nchars);
-              nchars = 0;
-              curchar = 0;
-              cmd = 0xFE;
-          }
-      }
-
-      DebugPulse(4);
-      
-  }
+	  if (cmd.direction == HPSerial::Rx) {
+	    if ((cmd.cmd == 0x00) || (cmd.cmd == 0x0C))
+	      pc.printf("  data=%s\n", cmd.value);
+	    show(cmd.cmd, cmd.value, cmd.size);
+	    
+	  }
+	}
+    }
 }
 
 int main()

mercurial