Ash

Description

See ash-protocol.h for source code.

Use the Asynchronous Serial Host (ASH) Framework interfaces on a host microcontroller when it communicates with an Ember chip via EZSP-UART.

See ash-common.h for source code.

Functions

uint8_t ashEncodeByte (uint8_t len, uint8_t byte, uint8_t *offset)
Builds an ASH frame.
EzspStatus ashDecodeByte (uint8_t byte, uint8_t *out, uint8_t *outLen)
Decodes and validates an ASH frame.
uint8_t ashRandomizeArray (uint8_t seed, uint8_t *buf, uint8_t len)
Randomizes array contents by XORing with an 8-bit pseudo random sequence.
void ashStartAckTimer (void)
Sets ashAckTimer to the specified period and starts it running.
bool ashAckTimerHasExpired (void)
Indicates whether or not ashAckTimer has expired.
void ashAdjustAckPeriod (bool expired)
Adapts the acknowledgement timer period to the observed ACK delay.
void ashStartNrTimer (void)
Starts the Not Ready timer.
bool ashNrTimerHasExpired (void)
Tests whether the Not Ready timer has expired or has stopped.

Macros

#define ashStopAckTimer (void)   do { ashAckTimer = 0; } while (false)
Stops and clears ashAckTimer.
#define ASH_VERSION 2
#define ASH_FLAG 0x7E
frame delimiter
#define ASH_ESC 0x7D
byte stuffing escape byte
#define ASH_XON 0x11
flow control byte - means resume transmission
#define ASH_XOFF 0x13
flow control byte - means suspend transmission
#define ASH_SUB 0x18
replaces bytes w framing, overrun or overflow errors
#define ASH_CAN 0x1A
frame cancel byte
#define ASH_WAKE 0xFF
wake signal byte (also means NCP data pending)
#define ASH_FLIP 0x20
XOR mask used in byte stuffing.
#define ASH_MIN_DATA_FIELD_LEN EZSP_MIN_FRAME_LENGTH
#define ASH_MAX_DATA_FIELD_LEN EZSP_MAX_FRAME_LENGTH
#define ASH_MIN_DATA_FRAME_LEN (ASH_MIN_DATA_FIELD_LEN + 1)
#define ASH_MIN_FRAME_LEN 1
#define ASH_MAX_FRAME_LEN (ASH_MAX_DATA_FIELD_LEN + 1)
#define ASH_CRC_LEN 2
#define ASH_MIN_FRAME_WITH_CRC_LEN (ASH_MIN_FRAME_LEN + ASH_CRC_LEN)
#define ASH_MAX_FRAME_WITH_CRC_LEN (ASH_MAX_FRAME_LEN + ASH_CRC_LEN)
#define ASH_NCP_SHFRAME_RX_LEN 2
longest non-data frame received
#define ASH_NCP_SHFRAME_TX_LEN 3
longest non-data frame sent
#define ASH_HOST_SHFRAME_RX_LEN 3
longest non-data frame received
#define ASH_HOST_SHFRAME_TX_LEN 2
longest non-data frame sent
#define ASH_DFRAME_MASK 0x80
#define ASH_CONTROL_DATA 0x00
#define ASH_SHFRAME_MASK 0xE0
#define ASH_CONTROL_ACK 0x80
#define ASH_CONTROL_NAK 0xA0
#define ASH_CONTROL_RST 0xC0
#define ASH_CONTROL_RSTACK 0xC1
#define ASH_CONTROL_ERROR 0xC2
#define ASH_ACKNUM_MASK 0x07
acknowledge frame number
#define ASH_ACKNUM_BIT 0
#define ASH_RFLAG_MASK 0x08
retransmitted frame flag
#define ASH_RFLAG_BIT 3
#define ASH_NFLAG_MASK 0x08
receiver not ready flag
#define ASH_NFLAG_BIT 3
#define ASH_PFLAG_MASK 0x10
flag reserved for future use
#define ASH_PFLAG_BIT 4
#define ASH_FRMNUM_MASK 0x70
DATA frame number.
#define ASH_FRMNUM_BIT 4
#define ASH_GET_RFLAG (ctl)   ((ctl & ASH_RFLAG_MASK ) >> ASH_RFLAG_BIT)
#define ASH_GET_NFLAG (ctl)   ((ctl & ASH_NFLAG_MASK ) >> ASH_NFLAG_BIT)
#define ASH_GET_FRMNUM (ctl)   ((ctl & ASH_FRMNUM_MASK ) >> ASH_FRMNUM_BIT)
#define ASH_GET_ACKNUM (ctl)   ((ctl & ASH_ACKNUM_MASK ) >> ASH_ACKNUM_BIT)
#define ASH_FRAME_LEN_DATA_MIN (ASH_MIN_DATA_FIELD_LEN + 1)
#define ASH_FRAME_LEN_ACK 1
#define ASH_FRAME_LEN_NAK 1
#define ASH_FRAME_LEN_RST 1
#define ASH_FRAME_LEN_RSTACK 3
#define ASH_FRAME_LEN_ERROR 3
#define MOD8 (n)   ((n) & 7)
mask to frame number modulus

#define INC8 (n)   (n = ( MOD8 (n + 1)))
increment in frame number modulus

#define WITHIN_RANGE (lo, n, hi)   ( MOD8 (n - lo) <= MOD8 (hi - lo))
#define ashAckTimerIsRunning ()   (ashAckTimer != 0)
Indicates whether or not ashAckTimer is currently running.
#define ashAckTimerIsNotRunning ()   (ashAckTimer == 0)
Indicates whether or not ashAckTimer is currently running.
#define ashSetAckPeriod (msec)   do { ashAckPeriod = msec; ashAckTimer = 0; } while (false)
Sets the acknowledgement timer period (in msec) and stops the timer.
#define ashGetAckPeriod ()   (ashAckPeriod)
Returns the acknowledgement timer period (in msec).
#define ashSetAndStartAckTimer (msec)   do { ashSetAckPeriod (msec); ashStartAckTimer (); } while (false)
Sets the acknowledgement timer period (in msec), and starts the timer running.
#define ASH_NR_TIMER_BIT 4
#define ashStopNrTimer ()   do { ashNrTimer = 0; } while (false)
Stops the Not Ready timer.
#define ashNrTimerIsNotRunning ()   (ashAckTimer == 0)
Indicates whether or not ashNrTimer is currently running.

Variables

bool ashDecodeInProgress
uint16_t ashAckTimer
uint16_t ashAckPeriod
uint8_t ashNrTimer

Function Documentation

ashEncodeByte()

uint8_t ashEncodeByte ( uint8_t len,
uint8_t byte,
uint8_t * offset
)

Builds an ASH frame.

Byte stuffs the control and data fields as required, computes and appends the CRC and adds the ending flag byte. Called with the next byte to encode, this function may return several output bytes before it's ready for the next byte.

Parameters
len new frame flag / length of the frame to be encoded. A non-zero value begins a new frame, so all subsequent calls must use zero. The length includes control byte and data field, but not the flag or crc. This function does not validate the length.
byte the next byte of data to add to the frame. Note that in general the same byte of data may have to be passed more than once as escape bytes, the CRC and the end flag byte are output.
offset pointer to the offset of the next input byte. (If the frame data is the array data[], the next byte would be data[offset].) Is set to 0 when starting a new frame (ie, len is non-zero). Is set to 0xFF when the last byte of the frame is returned.
Returns
next encoded output byte in frame.

ashDecodeByte()

EzspStatus ashDecodeByte ( uint8_t byte,
uint8_t * out,
uint8_t * outLen
)

Decodes and validates an ASH frame.

Data is passed to it one byte at a time. Decodes byte stuffing, checks crc, finds the end flag and (if enabled) terminates the frame early on CAN or SUB bytes. The number of bytes output will not exceed the max valid frame length, which does not include the flag or the crc.

Parameters
byte the next byte of data to add to the frame
out pointer to where to write an output byte
outLen number of bytes output so far
Returns
status of frame decoding
  • ::EZSP_SUCCESS
  • ::EZSP_ASH_IN_PROGRESS
  • ::EZSP_ASH_CANCELLED
  • ::EZSP_ASH_BAD_CRC
  • ::EZSP_ASH_COMM_ERROR
  • ::EZSP_ASH_TOO_SHORT
  • ::EZSP_ASH_TOO_LONG

ashRandomizeArray()

uint8_t ashRandomizeArray ( uint8_t seed,
uint8_t * buf,
uint8_t len
)

Randomizes array contents by XORing with an 8-bit pseudo random sequence.

This reduces the likelihood that byte-stuffing will greatly increase the size of the payload. (This could happen if a DATA frame contained repeated instances of the same reserved byte value.)

Parameters
seed zero initializes the random sequence a non-zero value continues from a previous invocation
buf pointer to the array whose contents will be randomized
len number of bytes in the array to modify
Returns
last value of the sequence. If a buffer is processed in two or more chunks, as with linked buffers, this value should be passed back as the value of the seed argument

ashStartAckTimer()

void ashStartAckTimer ( void )

Sets ashAckTimer to the specified period and starts it running.

ashAckTimerHasExpired()

bool ashAckTimerHasExpired ( void )

Indicates whether or not ashAckTimer has expired.

If the timer is stopped then it is not expired.

ashAdjustAckPeriod()

void ashAdjustAckPeriod ( bool expired )

Adapts the acknowledgement timer period to the observed ACK delay.

If the timer is not running, it does nothing. If the timer has expired, the timeourt period is doubled. If the timer has not expired, the elapsed time is fed into simple IIR filter: T[n+1] = (7*T[n] + elapsedTime) / 8 The timeout period, ashAckPeriod, is limited such that: ASH_xxx_TIME_DATA_MIN <= ashAckPeriod <= ASH_xxx_TIME_DATA_MAX, where xxx is either HOST or NCP.

The acknowledgement timer is always stopped by this function.

Parameters
expired true if timer has expired

ashStartNrTimer()

void ashStartNrTimer ( void )

Starts the Not Ready timer.

On the host, this times nFlag refreshing when the host doesn't have room for callbacks for a prolonged period.

On the NCP, if this times out the NCP resumes sending callbacks.

ashNrTimerHasExpired()

bool ashNrTimerHasExpired ( void )

Tests whether the Not Ready timer has expired or has stopped.

If expired, it is stopped.

Returns
true if the Not Ready timer has expired or stopped

Macro Definition Documentation

ashStopAckTimer

void ashStopAckTimer ( ) do { ashAckTimer = 0; } while (false)

Stops and clears ashAckTimer.

ASH_FLAG

#define ASH_FLAG   0x7E

frame delimiter

ASH_ESC

#define ASH_ESC   0x7D

byte stuffing escape byte

ASH_XON

#define ASH_XON   0x11

flow control byte - means resume transmission

ASH_XOFF

#define ASH_XOFF   0x13

flow control byte - means suspend transmission

ASH_SUB

#define ASH_SUB   0x18

replaces bytes w framing, overrun or overflow errors

ASH_CAN

#define ASH_CAN   0x1A

frame cancel byte

ASH_WAKE

#define ASH_WAKE   0xFF

wake signal byte (also means NCP data pending)

ASH_FLIP

#define ASH_FLIP   0x20

XOR mask used in byte stuffing.

ASH_NCP_SHFRAME_RX_LEN

#define ASH_NCP_SHFRAME_RX_LEN   2

longest non-data frame received

ASH_NCP_SHFRAME_TX_LEN

#define ASH_NCP_SHFRAME_TX_LEN   3

longest non-data frame sent

ASH_HOST_SHFRAME_RX_LEN

#define ASH_HOST_SHFRAME_RX_LEN   3

longest non-data frame received

ASH_HOST_SHFRAME_TX_LEN

#define ASH_HOST_SHFRAME_TX_LEN   2

longest non-data frame sent

ASH_ACKNUM_MASK

#define ASH_ACKNUM_MASK   0x07

acknowledge frame number

ASH_RFLAG_MASK

#define ASH_RFLAG_MASK   0x08

retransmitted frame flag

ASH_NFLAG_MASK

#define ASH_NFLAG_MASK   0x08

receiver not ready flag

ASH_PFLAG_MASK

#define ASH_PFLAG_MASK   0x10

flag reserved for future use

ASH_FRMNUM_MASK

#define ASH_FRMNUM_MASK   0x70

DATA frame number.

MOD8

#define MOD8 ( n ) ((n) & 7)

mask to frame number modulus

INC8

#define INC8 ( n ) (n = ( MOD8 (n + 1)))

increment in frame number modulus

ashAckTimerIsRunning

#define ashAckTimerIsRunning ( ) (ashAckTimer != 0)

Indicates whether or not ashAckTimer is currently running.

The timer may be running even if expired.

ashAckTimerIsNotRunning

#define ashAckTimerIsNotRunning ( ) (ashAckTimer == 0)

Indicates whether or not ashAckTimer is currently running.

The timer may be running even if expired.

ashSetAckPeriod

#define ashSetAckPeriod ( msec ) do { ashAckPeriod = msec; ashAckTimer = 0; } while (false)

Sets the acknowledgement timer period (in msec) and stops the timer.

ashGetAckPeriod

#define ashGetAckPeriod ( ) (ashAckPeriod)

Returns the acknowledgement timer period (in msec).

ashSetAndStartAckTimer

#define ashSetAndStartAckTimer ( msec ) do { ashSetAckPeriod (msec); ashStartAckTimer (); } while (false)

Sets the acknowledgement timer period (in msec), and starts the timer running.

ashStopNrTimer

#define ashStopNrTimer ( ) do { ashNrTimer = 0; } while (false)

Stops the Not Ready timer.

ashNrTimerIsNotRunning

#define ashNrTimerIsNotRunning ( ) (ashAckTimer == 0)

Indicates whether or not ashNrTimer is currently running.