src/hp34comm.h

Sun, 01 Nov 2020 22:16:33 +0100

author
David Douard <david.douard@sdf3.org>
date
Sun, 01 Nov 2020 22:16:33 +0100
changeset 43
c850674a3101
parent 39
63c6a720cb97
child 44
b3c3d54d2c7c
permissions
-rw-r--r--

Add a series of reference serial data sessions from a working 34970A unit.

These sessions do have a few glitches, however (random off by one bit,
probably due to a sampling freq a bit too low).

Comes with an adapted version of the uart_filter.py script to interpret the
communication protocol.

#ifndef HP34COMM_H
#define HP34COMM_H

#include <mbed.h>
#include <CircularBuffer.h>

/***** HP 34970A communication class ***/

#define MAX_ERRS 10
#define MAX_BUFF 16
#define BUF_SIZE 16



class HPSerial {

public:
  typedef struct _CMD
  {
    uint8_t cmd;
    uint8_t size;
    char value[MAX_BUFF+1];
    unsigned long id;
  } CMD;

  HPSerial(PinName tx, PinName rx);

  bool cmd_available(void);
  bool pop(CMD& cmd);
  bool cmd_buf_full(void);
  unsigned int nerrors(uint8_t errorno);

  void startup(uint8_t keycode=0xFF);
  void sendkey(uint8_t keycode);

private:
  void pushCmd(uint8_t cmd, uint8_t size, char *payload);
  void rxIrq(void);
  void timeout(void);
  void set_timer(Kernel::Clock::duration_u32 v=0ms) {
    timeouter.detach();
    if (v > 0ms)
      timeouter.attach(callback(this, &HPSerial::timeout), v);
  }

 private:
  UnbufferedSerial serial;
  uint8_t buf[BUF_SIZE];
  uint8_t head;
  CircularBuffer<CMD, 32> cmdbuf;
  unsigned long ncmd;
  unsigned int errs[MAX_ERRS];
  Ticker timeouter;

 public:
  // global state machine
  typedef enum {
    GSTATE_STARTING,
    GSTATE_IDLE,
    GSTATE_TX,
    GSTATE_RX,
    NUM_GSTATES} gstate_t;
  gstate_t gstate() {return cur_gstate;};
  /* gstate_t do_start(); */
  /* gstate_t do_send(); */
  /* gstate_t do_receive(); */

  /* typedef gstate_t(HPSerial::*gstatemethod)(); */
  /* statemethod const gstate_table[NUM_GSTATES] = { */
  /*     &HPSerial::do_start, */
  /*     &HPSerial::do_send, */
  /*     &HPSerial::do_receive, */
  /* }; */

  /* gstate_t run_gstate(gstate_t cur_state); */
 private:
  gstate_t cur_gstate;

 public:
  // transmission state machine
  typedef enum {
    STATE_IDLE,
    STATE_COMMAND,
    STATE_PAYLOAD_SIZE,
    STATE_PAYLOAD,
    STATE_SENDING,
    STATE_EOT,
    NUM_STATES} state_t;
  state_t state() {return cur_state;};

 private:
  typedef struct state_data {
    uint8_t cmd;
    uint8_t size;
    uint8_t pos;
    char payload[MAX_BUFF];
  } state_data_t;

  void _startup(void);
  state_t do_state_initial(uint8_t c=0x00);
  state_t do_state_command(uint8_t c);
  state_t do_state_payload_size(uint8_t c);
  state_t do_state_payload(uint8_t c);
  state_t do_state_sending(uint8_t c=0x00);
  state_t do_state_eot(uint8_t c=0x55);

  void send_ack(uint8_t c);

  typedef state_t(HPSerial::*statemethod)(uint8_t c);
  static  statemethod state_table[NUM_STATES];
  state_t run_state(state_t cur_state, uint8_t c);

  state_t cur_state;
  state_data_t tr_data;
};


#endif

mercurial