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
lennew 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.
bytethe 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.
offsetpointer 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
bytethe next byte of data to add to the frame
outpointer to where to write an output byte
outLennumber 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
seedzero initializes the random sequence a non-zero value continues from a previous invocation
bufpointer to the array whose contents will be randomized
lennumber 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
expiredtrue 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.