src/hp34comm.cpp

changeset 18
4fd621551d55
parent 16
c5e5bdc5ef49
child 19
a52d60613cf7
--- a/src/hp34comm.cpp	Wed Oct 26 22:41:16 2016 +0200
+++ b/src/hp34comm.cpp	Sat Oct 29 23:44:31 2016 +0200
@@ -15,19 +15,15 @@
 #endif
 
 DigitalOut lled(LED1);
-  
-HPSerial::HPSerial(PinName rx):
-  serial_rx(NC, rx),
-  ncmd(0) {
-  
-  //pc.printf("HPSerial init\n");
+
+
 
-  for(uint8_t i=0; i<MAX_ERRS; i++)
-    errs[i] = 0;
-  reset();
-  
-  serial_rx.baud(187500);
-  serial_rx.attach(this, &HPSerial::rxIrq, Serial::RxIrq);
+HPSerial::HPSerial(PinName tx, PinName rx):
+  serial(tx, rx)
+{
+  cur_state = do_state_initial(&rx_data, 0x00);
+  serial.baud(187500);
+  serial.attach(this, &HPSerial::rxIrq, Serial::RxIrq);
 }
 
 bool HPSerial::cmd_available(void) {
@@ -45,63 +41,11 @@
 unsigned int HPSerial::nerrors(uint8_t errorno) {
   return errs[errorno];
 }
-    
-		     
-  
-void HPSerial::reset(uint8_t errorno) {
-  timeouter.detach();
-  head = 0;
-  tx_state = Idle;
-  setstatedbg();
-  tx_cmd = 0xFF;
-  tx_ack = false;
-  tx_len = 0xFF;
-  memset(buf, 0, BUF_SIZE);
-  if (errorno != 0xFF){
-    errs[errorno]++;
-  }
-  
-}
 
-void HPSerial::handleAck(uint8_t val) {
-  if ((tx_state == Rx) & (tx_cmd == 0xFF) & (tx_ack == false) & (val == 0x66)) {
-    // special case: keypad does not acknwledge and takes precedence
-    // on the "bus"
-    tx_state = Tx;
-    setstatedbg();
-  } else
-    if (tx_cmd == 0xFF) // beginning of a packet, expect 0x99 as ack
-      if (val == 0x99)
-	{
-	  tx_ack = true;
-#ifdef DEBUG2
-	  ack = 1;
-	  wait_us(2);
-	  ack = 0;
-#endif
-	}
-      else 
-	reset(1);
-
-    else // expect 0x00 as ack
-      if (val == 0x00)
-	{
-	  tx_ack = true;
-#ifdef DEBUG2
-	  ack = 1;
-	  wait_us(2);
-	  ack = 0;
-#endif
-	}
-      else
-	reset(2);
-}
-
-void HPSerial::pushCmd(TrState direction, uint8_t cmd, uint8_t size, char *payload) {
+void HPSerial::pushCmd(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++)
@@ -110,114 +54,92 @@
   cmdbuf.push(val);
 }
 
-void HPSerial::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) {
-      if (val == 0x55) {
-	// packet was in fact a keystroke, tx_cmd is in fact the key
-	// stroke and no payload is expected 
-#ifdef DEBUG2
-      statetx = 1;
-#endif
-      pushCmd((TrState)Tx, tx_cmd, 0, (char*)buf);
-#ifdef DEBUG2
-      wait_us(2);
-      statetx = 0;
-#endif
-      reset();
-      } else {
-	// got a cmd, expect a payload size
-	tx_len = val;
-	tx_ack = false;
-      }
-    }
-    else if (tx_len == 0x55) {
-      // packet was in fact a keystroke, tx_cmd is in fact the key
-      // stroke and no payload is expected 
-#ifdef DEBUG2
-      statetx = 1;
-#endif
-      pushCmd((TrState)Tx, tx_cmd, 0, (char*)buf);
-#ifdef DEBUG2
-      wait_us(2);
-      statetx = 0;
-#endif
-      reset();
-    }
-    else if (tx_len > 0) {
-      // a payload char
-      buf[head++] = val;
-      tx_len--;
-      tx_ack = false;
-    }
-    else { // end of payload, manage sent content
-      uint8_t cur_state = tx_state;
-      pushCmd((TrState)tx_state, tx_cmd, head, (char*)buf); 
-      
-      switch(val) {
-      case 0x66: // a new transmisson
-	reset();
-	tx_state = cur_state;
-	setstatedbg();
-	break;
-      case 0x55:
-	reset();
-	break;
-      default:
-	reset(6);
-	break;
-      }
-    }
+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);
+}
+
+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)
+{
+  // we are idle, incoming char is a handcheck
+  // knwon handcheck values are 0x66 and 0x33
+  switch (c) {
+  case 0x33:
+    send_ack(0xCC);
+    return HPSerial::STATE_PAYLOAD_SIZE;
+    break;
+  case 0x66:
+    send_ack(0x99);
+    return HPSerial::STATE_COMMAND;
+    break;
+  default:
+    return do_state_initial(data, 0x00);
+  }
 }
 
+HPSerial::state_t HPSerial::do_state_command(HPSerial::instance_data_t *data,
+					     uint8_t c)
+{
+  if (c == 0x55) { // EoT
+    return do_state_initial(data, 0x00);
+  }
 
+  data->cmd = c;
+  data->size = 0;
+  send_ack(0x00);
+  return HPSerial::STATE_PAYLOAD_SIZE;
+}
 
-void HPSerial::setstatedbg(void) {
-#ifdef DEBUG2
-    if (tx_state == Rx)
-      staterx = 1;
-    else
-      staterx = 0;
-    if (tx_state == Tx)
-      statetx = 1;
-    else
-      statetx = 0;
-#endif
+HPSerial::state_t HPSerial::do_state_payload_size(HPSerial::instance_data_t *data,
+						  uint8_t c)
+{
+  data->size = c;
+  data->received = 0;
+  send_ack(0x00);
+  return HPSerial::STATE_PAYLOAD;
 }
 
+HPSerial::state_t HPSerial::do_state_payload(HPSerial::instance_data_t *data,
+					uint8_t c)
+{
+  data->payload[data->received++] = c;
+  send_ack(0x00);
+  if (data->received >= data->size) {
+    pushCmd(data->cmd, data->size, data->payload);
+    return HPSerial::STATE_COMMAND;
+  }
+  return HPSerial::STATE_PAYLOAD;
+}
+
+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);
+};
+
 void HPSerial::rxIrq(void) {
   uint8_t val;
-  if(serial_rx.readable()) { // no reason why we would end here without this condition, but hey
+  if(serial.readable()) { // no reason why we would end here without
+			  // this condition, but hey
 #ifdef DEBUG2
     inrx=1;
 #endif
     lled = 1;
-    val = serial_rx.getc();
-    
-    timeouter.attach(this, &HPSerial::timeout, 0.001); // if nothing else happen in the next ms, reset
-    
-    if (tx_state == Idle)
-      if (val == 0x66) {
-	// no transmission in progress, expect a start of transmission
-	tx_state = Rx;
-	tx_ack = false;
-	setstatedbg();
-      }
-      else {
-	reset(4);
-      }
-    else if (tx_ack == false)  // manage the acks
-      handleAck(val);
-    else 
-      handleChar(val);
+    val = serial.getc();
+    cur_state = run_state(cur_state, &rx_data, val);
     lled = 0;
 #ifdef DEBUG2
     inrx=0;
@@ -227,7 +149,5 @@
 
 
 void HPSerial::timeout(void) {
-  if (tx_state != Idle) {
-    reset(7);
-  }
+  cur_state = do_state_initial(&rx_data, 0x00);
 }

mercurial