PIC24 Support Libraries
Data Structures | Typedefs
dataXferImpl.h File Reference

Routines which implement the uC comm protocol. More...

#include <stdint.h>
#include <stdlib.h>
#include <assert.h>

Go to the source code of this file.

Data Structures

struct  XFER_VAR
 

Macros

Constants

These values are #defined as necessary so that the work under:

  • Pre-C99 (no bool, true, or false); this is MSVC++ in C mode and GCC for the PIC24.
  • C++ (bool, true, and false built in)
  • C++/CLI (NULL not defined)
#define FALSE   0
 
#define TRUE   1
 
#define ASSERT(x)   assert(x)
 
#define ASSERTM(msg, expr)   ASSERT(expr)
 An assert with message macro; the msg isn't used in C.
 
#define BOOL   unsigned char
 

Typedefs

typedef unsigned int uint
 An abbreviation for an unsigned integer.
 
typedef unsigned char uint8_t
 An abbreviation for an 8-bit unsigned integer.
 

Command-finding state machine

#define CMD_TOKEN   ((char) 0xAA)
 
#define ESCAPED_CMD   ((char) 0xFC)
 
#define CMD_LONG_VAR   ((char) 0xFD)
 
#define CMD_SEND_ONLY   ((char) 0xFE)
 
#define CMD_SEND_RECEIVE_VAR   ((char) 0xFF)
 
#define VAR_SIZE_BITS   2
 
#define VAR_SIZE_MASK   ((1 << VAR_SIZE_BITS) - 1)
 A mask which removes all but the variable size bits in the varBits field.
 
#define SHORT_VAR_MAX_LEN   (1 << VAR_SIZE_BITS)
 
enum  CMD_STATE { STATE_CMD_START, STATE_CMD_WAIT1, STATE_CMD_WAIT2 }
 
enum  CMD_OUTPUT {
  OUTPUT_CMD_NONE, OUTPUT_CMD_CHAR, OUTPUT_CMD_CMD, OUTPUT_CMD_REPEATED_CMD,
  OUTPUT_CMD_REPEATED_WAIT
}
 
void resetCommandFindMachine ()
 
CMD_OUTPUT stepCommandFindMachine (char c_inChar, char *c_outChar)
 

Data structures to store received variables

#define MAX_NUM_XFER_VARS   ((1 << (8 - VAR_SIZE_BITS)) - 1)
 Maximum number of transfer variables supported.
 
#define NUM_XFER_VARS   62
 
XFER_VAR xferVar [NUM_XFER_VARS]
 A table to hold the state of transfer variables.
 
uint8_t au8_xferVarWriteable [NUM_XFER_VARS/8+((NUM_XFER_VARS % 8) > 0)]
 

Receive state machine

#define CHAR_RECEIVED_INDEX   0xFF
 
#define NUM_ERROR_CODES   (ERR_MICROCONTROLLER_VAR_SPEC + 1)
 Number of error codes in the RECEIVE_ERROR enum.
 
enum  RECEIVE_STATE {
  STATE_RECV_START, STATE_RECV_CMD_WAIT, STATE_RECV_READ_BYTES, STATE_RECV_LONG_INDEX,
  STATE_RECV_LONG_LENGTH, STATE_RECV_SPEC_INDEX
}
 
enum  RECEIVE_ERROR {
  ERR_NONE = 0, ERR_REPEATED_CMD, ERR_TIMEOUT, ERR_INTERRUPTED_CMD,
  ERR_UNSPECIFIED_INDEX, ERR_INDEX_TOO_HIGH, ERR_VAR_SIZE_MISMATCH, ERR_READ_ONLY_VAR,
  ERR_MICROCONTROLLER_VAR_SPEC
}
 
RECEIVE_STATE getReceiveMachineState ()
 
char getReceiveMachineOutChar ()
 
uint getReceiveMachineIndex ()
 
RECEIVE_ERROR getReceiveMachineError ()
 
BOOL getReceiveMachineIsSpec ()
 
void resetReceiveMachine ()
 
void clearReceiveMachineError ()
 
void clearReceiveStruct ()
 
BOOL isReceiveMachineChar ()
 
BOOL isReceiveMachineData ()
 
BOOL isReceiveMachineSpec ()
 
uint getVarIndex (char c_cmd)
 
uint getVarLength (char c_cmd)
 
void assignBit (uint u_index, BOOL b_bitVal)
 
BOOL isVarWriteable (uint u_index)
 
RECEIVE_ERROR notifyOfTimeout ()
 
RECEIVE_ERROR stepReceiveMachine (char c_inChar)
 
const char * getReceiveErrorString ()
 Returns an error string matching the last error code.
 

Detailed Description

Routines which implement the uC comm protocol.

This implements code which receives data from a uC sent either as individual characters or as data packets. For a complete specification, see the uC comm protocol.

Two state machines implement this spec. The receive state machine uses the command-finding state machine in its operation, so that a user of this code will not normally need access to the command-finding machine.

Both machines can be reset (resetCommandFindMachine(), resetReceiveMachine()) and advanced by one state (stepCommandFindMachine(), stepReceiveMachine()).

Two mechanisms provide read access to the receive state machine. Low-level calls (getReceiveMachineOutChar(), getReceiveMachineIndex(), getReceiveMachineError(), getReceiveMachineIsSpec()) report machine state, while high-level calls (isReceiveMachineChar(), isReceiveMachineData(), isReceiveMachineSpec()) aggreate that state into more meaningful information.

Note: this is implemented in C (not C++), so that similar code can be re-used on a uC.

Implementation

The uC keeps state in xferVar; a NULL address indicates nothing is present.

On receive: implement as a state machine (see sketch below).

Receive state machine sketch

For simplicity, "getch" really means one invocation of the receive state machine, which is runs until the next getch. Timeouts are not shown: if too much time passes, the state machine is reset to the top. Likewise, receiving a command at any unexpected point causes a state machine reset.

varBits = getch
if !command:
  c = varBits  // This was just a normal char; return it
  return index = 0
  restart
// varBits is a command, not a char
if isLongVar(varBits):
  varNum, len = getch
else
  assign varNum, len from varBits
if isVarSpec and !MICROCONTROLLER
  getch len times to buf
  parse to var spec
  report any errors, restart
else if isValid(varNum, len)
  getch len times to var
  return varIndex
else
  getch len times and discard
  report error, restart
\author Bryan A. Jones, bjones AT ece DOT msstate DOT edu.

Definition in file dataXferImpl.h.

Macro Definition Documentation

◆ CHAR_RECEIVED_INDEX

#define CHAR_RECEIVED_INDEX   0xFF

This value retured for the index from the receive state machine (see, e.g., isReceiveMachineData) indicates that a character, not a command, was received.

Definition at line 358 of file dataXferImpl.h.

Referenced by isReceiveMachineChar(), isReceiveMachineData(), isReceiveMachineSpec(), and stepReceiveMachine().

◆ CMD_LONG_VAR

#define CMD_LONG_VAR   ((char) 0xFD)

After a command token, this value specifies that the command is a long variable.

Definition at line 213 of file dataXferImpl.h.

Referenced by stepReceiveMachine().

◆ CMD_SEND_ONLY

#define CMD_SEND_ONLY   ((char) 0xFE)

After a command token, this value specifies that the command is a send-only var.

Definition at line 217 of file dataXferImpl.h.

Referenced by stepReceiveMachine().

◆ CMD_SEND_RECEIVE_VAR

#define CMD_SEND_RECEIVE_VAR   ((char) 0xFF)

After a command token, this value specifies that the command is a send/receive var.

Definition at line 221 of file dataXferImpl.h.

Referenced by stepReceiveMachine().

◆ CMD_TOKEN

#define CMD_TOKEN   ((char) 0xAA)

The character used to begin a command. If this is not a command, then use the two-character sequence CMD_TOKEN ESCAPED_CMD; a CMD_TOKEN followed by any other value is a command.

Definition at line 205 of file dataXferImpl.h.

Referenced by stepCommandFindMachine(), and stepReceiveMachine().

◆ ESCAPED_CMD

#define ESCAPED_CMD   ((char) 0xFC)

After a command token, this value specifies that the character CMD_TOKEN was sent.

Definition at line 209 of file dataXferImpl.h.

Referenced by stepCommandFindMachine(), and stepReceiveMachine().

◆ NUM_XFER_VARS

#define NUM_XFER_VARS   62

Number of transfer variables supported. Must be less than the MAX_NUM_XFER_VARS.

Definition at line 335 of file dataXferImpl.h.

Referenced by clearReceiveStruct(), formatVar(), sendVar(), specifyVar(), and validateIndex().

◆ SHORT_VAR_MAX_LEN

#define SHORT_VAR_MAX_LEN   (1 << VAR_SIZE_BITS)

The maximum size of a short variable (which must fit in VAR_SIZE_BITS number of bits).

Definition at line 232 of file dataXferImpl.h.

◆ VAR_SIZE_BITS

#define VAR_SIZE_BITS   2

The number of bits in the variable size field of the varBits field, following a command token.

Definition at line 225 of file dataXferImpl.h.

Referenced by getVarIndex().

Enumeration Type Documentation

◆ CMD_OUTPUT

enum CMD_OUTPUT

The output of the command-finding state machine. See stepCommandFindMachine for more information.

Enumerator
OUTPUT_CMD_NONE 

The state machine produced no output, but is waiting for additional input.

OUTPUT_CMD_CHAR 

A character was received; c_outChar contains the character.

OUTPUT_CMD_CMD 

A command was received; c_outChar contains the command.

OUTPUT_CMD_REPEATED_CMD 

A repeated command was received; c_outChar contains the command.

OUTPUT_CMD_REPEATED_WAIT 

The machine received a CMD_TOKEN CMD_TOKEN CMD_TOKEN, so report a repeated command and wait for the next character to finish decoding.

Definition at line 247 of file dataXferImpl.h.

◆ CMD_STATE

enum CMD_STATE

State of the command-finding state machine. See stepCommandFindMachine for more information.

Enumerator
STATE_CMD_START 

The machine is in its starting state.

STATE_CMD_WAIT1 

The machine is waiting for another character; c_outChar is not valid.

STATE_CMD_WAIT2 

The machine is waiting for an additional character; c_outChar is not valid.

Definition at line 236 of file dataXferImpl.h.

◆ RECEIVE_ERROR

Protocol errors produced by the receive state machine. Internal errors (invalid state transitions, etc.) are detected via ASSERTs.

Enumerator
ERR_NONE 

No error; all state machine outputs are valid when the state is STATE_RECV_START after execution of stepReceiveMachine.

ERR_REPEATED_CMD 

A repeated command (the sequence CMD_TOKEN CMD_TOKEN c, where c != ESCAPED_CMD), was received.

ERR_TIMEOUT 

A timeout occurred in the middle of receiving a command.

ERR_INTERRUPTED_CMD 

A command occurred in the middle of receiving data belonging to an earlier command.

ERR_UNSPECIFIED_INDEX 

Data was sent to a variable that has not been specified: the pointer to its data is NULL.

ERR_INDEX_TOO_HIGH 

Data was sent to a variable which exceeds the NUM_XFER_VARS.

ERR_VAR_SIZE_MISMATCH 

The size of data sent to a variable does not match the size specified earlier.

ERR_READ_ONLY_VAR 

The destination variable is read-only.

ERR_MICROCONTROLLER_VAR_SPEC 

The microcontroller is sent a variable specification.

Definition at line 381 of file dataXferImpl.h.

◆ RECEIVE_STATE

States of the receive state machine. See stepReceiveMachine for more information.

Enumerator
STATE_RECV_START 

At the start of the machine.

STATE_RECV_CMD_WAIT 

Waiting for a command or escaped CMD_TOKEN.

STATE_RECV_READ_BYTES 

Reading data bytes in from a command.

STATE_RECV_LONG_INDEX 

Reading the variable index for a long var command.

STATE_RECV_LONG_LENGTH 

Reading the variable length for a long/specification command.

STATE_RECV_SPEC_INDEX 

Reading the variable index for a specification command.

Definition at line 362 of file dataXferImpl.h.

Function Documentation

◆ assignBit()

void assignBit ( uint  u_index,
BOOL  b_bitVal 
)

Assign a bit in the au8_xferVarWriteable bit field.

Parameters
u_indexThe index of the variable to set.
b_bitValBit value to set at this index.

Definition at line 267 of file dataXferImpl.c.

Referenced by specifyVar(), and stepReceiveMachine().

◆ clearReceiveMachineError()

void clearReceiveMachineError ( )

Clear the current receive machine error status; the caller should therefore handle or report this error to a higher level of the program.

Definition at line 169 of file dataXferImpl.c.

◆ clearReceiveStruct()

void clearReceiveStruct ( )

Clear the received data structure, so that no variables are specified.

Definition at line 188 of file dataXferImpl.c.

Referenced by initDataXfer().

◆ getReceiveMachineError()

RECEIVE_ERROR getReceiveMachineError ( )

Return the error last encountered by the receive state machine. See stepReceiveMachine for more information. This also clears the error status.

Definition at line 146 of file dataXferImpl.c.

◆ getReceiveMachineIndex()

uint getReceiveMachineIndex ( )

Return the index output by the receive state machine. See stepReceiveMachine for more information.

Definition at line 141 of file dataXferImpl.c.

◆ getReceiveMachineIsSpec()

BOOL getReceiveMachineIsSpec ( )

Determine if the last data found by the receive state machine was a specification; if not, it was data. See stepReceiveMachine for more information. PC only.

Definition at line 154 of file dataXferImpl.c.

◆ getReceiveMachineOutChar()

char getReceiveMachineOutChar ( )

Return the character output by the receive state machine. See stepReceiveMachine for more information.

Definition at line 137 of file dataXferImpl.c.

◆ getReceiveMachineState()

RECEIVE_STATE getReceiveMachineState ( )

Return the current receive machine state. See stepReceiveMachine for more information.

Definition at line 133 of file dataXferImpl.c.

◆ getVarIndex()

uint getVarIndex ( char  c_cmd)

Return the index of a variable in a command byte.

Parameters
c_cmdCommand byte.
Returns
Index of the variable.

Definition at line 220 of file dataXferImpl.c.

Referenced by stepReceiveMachine().

◆ getVarLength()

uint getVarLength ( char  c_cmd)

Return the number of bytes of a variable in a command byte.

Parameters
c_cmdCommand byte.
Returns
Number of bytes.

Definition at line 224 of file dataXferImpl.c.

Referenced by stepReceiveMachine().

◆ isReceiveMachineChar()

BOOL isReceiveMachineChar ( )

Determines if the receive state machine just received a character.

Returns
True when the machine just received a character.

Definition at line 200 of file dataXferImpl.c.

◆ isReceiveMachineData()

BOOL isReceiveMachineData ( )

Determines if the receive state machine just received some data.

Returns
True when the machine just received some data.

Definition at line 206 of file dataXferImpl.c.

◆ isReceiveMachineSpec()

BOOL isReceiveMachineSpec ( )

Determines if the receive state machine just received an updated specification. PC only.

Returns
True when the machine just received an updated spec.

Definition at line 213 of file dataXferImpl.c.

◆ isVarWriteable()

BOOL isVarWriteable ( uint  u_index)

Read a bit in the au8_xferVarWriteable bit field.

Parameters
u_indexThe index of the variable to set.
Returns
The bit value at this index. TRUE indicated the variable is writeable; FALSE indicates a read-only variable: only the microcontroller, but not the PC, may change its value.

Definition at line 279 of file dataXferImpl.c.

Referenced by sendVar(), and validateIndex().

◆ notifyOfTimeout()

RECEIVE_ERROR notifyOfTimeout ( )

Notify the state machine that a timeout occurred between receiving the previous and next character. A timeout may not lead to an error; for example, between two received data packets or two received characters, timeout are allowed.

Returns
An error code; ERROR_NONE (which is false) means no error occurred.

Definition at line 361 of file dataXferImpl.c.

◆ resetCommandFindMachine()

void resetCommandFindMachine ( )

Resets the command-finding state machine; see stepCommandFindMachine for more information.

Definition at line 17 of file dataXferImpl.c.

Referenced by resetReceiveMachine().

◆ resetReceiveMachine()

void resetReceiveMachine ( )

Reset the receive state machine to its initial state and clear the error status. The outputs are not reset, because they will not be valid until after an invocation of the state machine.

Definition at line 160 of file dataXferImpl.c.

Referenced by initDataXfer(), and notifyOfTimeout().

◆ stepCommandFindMachine()

CMD_OUTPUT stepCommandFindMachine ( char  c_inChar,
char *  c_outChar 
)

The command-finding state machine looks for commands in the data passed to it. Sequences it recognizes:

  • c, where c != CMD_TOKEN, outputs the character c.
  • CMD_TOKEN ESCAPED_CMD outputs the character CMD_TOKEN (known as an escaped command).
  • CMD_TOKEN c, where c != CMD_TOKEN and c != ESCAPED_CMD, outputs the command c.
  • CMD_TOKEN CMD_TOKEN ESCAPED_CMD outputs the command CMD_TOKEN (note that the second CMD_TOKEN is "escaped", so it is treated as a character specifying the command, not as the beginning of a command).
  • CMD_TOKEN CMD_TOKEN CMD_TOKEN outputs a repeated command then waits for the next character. See the state machine sketch below for more information.
  • CMD_TOKEN CMD_TOKEN c, where c != CMD_TOKEN and c != ESCAPED_CMD, outputs a repeated command c. This is a protocol violation, but must be reported at a higher level; this routine merely reports a repeated command. A sketch of the state machine:
    case START :
      if (c == CMD_TOKEN) state = WAIT1
      else output c as a character
    case WAIT1 :
      if (c == CMD_TOKEN) state = WAIT2
      if (c == ESCAPED_CMD) state = START, output CMD_TOKEN as a character
      else output c as a command
    case WAIT2 :
      if (c == ESCAPED_CMD) state = START, output command CMD_TOKEN
      if (c == CMD_TOKEN) output repeated command, remain in this state
      else output repeated command c
    
    Parameters
    c_inCharA character input to the machine.
    c_outCharThe character/command output by the machine when the returned state is not CMD_WAIT.
    Returns
    The output of the machine, which indicates if a command or character is available.

Definition at line 22 of file dataXferImpl.c.

Referenced by stepReceiveMachine().

◆ stepReceiveMachine()

RECEIVE_ERROR stepReceiveMachine ( char  c_inChar)

This state machine receives data from the microcontroller. It takes a character received plus an indication if a timeout occurred since the last invocation of this function and advances the machine. The machine produces outputs when the returned state is STATE_RECV_START. Outputs:

  • c_outChar, set if a character (versus a data packet) was received
  • u_index, set to the index of the data received
  • receiveError, an error code
  • b_isSpec, true if a specification packet was received.
    Parameters
    c_inCharA character for the state machine to process.
    Returns
    An error code; ERROR_NONE (which is false) means no error occurred.

Definition at line 374 of file dataXferImpl.c.

Variable Documentation

◆ au8_xferVarWriteable

uint8_t au8_xferVarWriteable[NUM_XFER_VARS/8+((NUM_XFER_VARS % 8) > 0)]

An array of isWriteable bits for each var. Each bit is true if the PC is allowed to change this variable; false otherwise. This does NOT restrict the microcontroller to read-only access to this variable.

Definition at line 101 of file dataXferImpl.c.

Referenced by assignBit(), clearReceiveStruct(), and isVarWriteable().