|
|
|
@ -30,49 +30,49 @@ |
|
|
|
|
//region Resolve data types
|
|
|
|
|
|
|
|
|
|
#if TF_LEN_BYTES == 1 |
|
|
|
|
typedef uint8_t TF_LEN; |
|
|
|
|
typedef uint8_t TF_LEN; |
|
|
|
|
#elif TF_LEN_BYTES == 2 |
|
|
|
|
typedef uint16_t TF_LEN; |
|
|
|
|
typedef uint16_t TF_LEN; |
|
|
|
|
#elif TF_LEN_BYTES == 4 |
|
|
|
|
typedef uint32_t TF_LEN; |
|
|
|
|
typedef uint32_t TF_LEN; |
|
|
|
|
#else |
|
|
|
|
#error Bad value of TF_LEN_BYTES, must be 1, 2 or 4 |
|
|
|
|
#error Bad value of TF_LEN_BYTES, must be 1, 2 or 4 |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if TF_TYPE_BYTES == 1 |
|
|
|
|
typedef uint8_t TF_TYPE; |
|
|
|
|
typedef uint8_t TF_TYPE; |
|
|
|
|
#elif TF_TYPE_BYTES == 2 |
|
|
|
|
typedef uint16_t TF_TYPE; |
|
|
|
|
typedef uint16_t TF_TYPE; |
|
|
|
|
#elif TF_TYPE_BYTES == 4 |
|
|
|
|
typedef uint32_t TF_TYPE; |
|
|
|
|
typedef uint32_t TF_TYPE; |
|
|
|
|
#else |
|
|
|
|
#error Bad value of TF_TYPE_BYTES, must be 1, 2 or 4 |
|
|
|
|
#error Bad value of TF_TYPE_BYTES, must be 1, 2 or 4 |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if TF_ID_BYTES == 1 |
|
|
|
|
typedef uint8_t TF_ID; |
|
|
|
|
typedef uint8_t TF_ID; |
|
|
|
|
#elif TF_ID_BYTES == 2 |
|
|
|
|
typedef uint16_t TF_ID; |
|
|
|
|
typedef uint16_t TF_ID; |
|
|
|
|
#elif TF_ID_BYTES == 4 |
|
|
|
|
typedef uint32_t TF_ID; |
|
|
|
|
typedef uint32_t TF_ID; |
|
|
|
|
#else |
|
|
|
|
#error Bad value of TF_ID_BYTES, must be 1, 2 or 4 |
|
|
|
|
#error Bad value of TF_ID_BYTES, must be 1, 2 or 4 |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if TF_CKSUM_TYPE == TF_CKSUM_XOR || TF_CKSUM_TYPE == TF_CKSUM_NONE |
|
|
|
|
// ~XOR (if 0, still use 1 byte - it won't be used)
|
|
|
|
|
typedef uint8_t TF_CKSUM; |
|
|
|
|
// ~XOR (if 0, still use 1 byte - it won't be used)
|
|
|
|
|
typedef uint8_t TF_CKSUM; |
|
|
|
|
#elif TF_CKSUM_TYPE == TF_CKSUM_CRC16 |
|
|
|
|
// CRC16
|
|
|
|
|
typedef uint16_t TF_CKSUM; |
|
|
|
|
// CRC16
|
|
|
|
|
typedef uint16_t TF_CKSUM; |
|
|
|
|
#elif TF_CKSUM_TYPE == TF_CKSUM_CRC32 |
|
|
|
|
// CRC32
|
|
|
|
|
typedef uint32_t TF_CKSUM; |
|
|
|
|
// CRC32
|
|
|
|
|
typedef uint32_t TF_CKSUM; |
|
|
|
|
#else |
|
|
|
|
#error Bad value for TF_CKSUM_TYPE, must be 8, 16 or 32 |
|
|
|
|
#error Bad value for TF_CKSUM_TYPE, must be 8, 16 or 32 |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
//endregion
|
|
|
|
@ -87,26 +87,26 @@ |
|
|
|
|
|
|
|
|
|
/** Peer bit enum (used for init) */ |
|
|
|
|
typedef enum { |
|
|
|
|
TF_SLAVE = 0, |
|
|
|
|
TF_MASTER = 1, |
|
|
|
|
TF_SLAVE = 0, |
|
|
|
|
TF_MASTER = 1, |
|
|
|
|
} TF_Peer; |
|
|
|
|
|
|
|
|
|
typedef enum { |
|
|
|
|
TF_NEXT = 0, //!< Not handled, let other listeners handle it
|
|
|
|
|
TF_STAY = 1, //!< Handled, stay
|
|
|
|
|
TF_RENEW = 2, //!< Handled, stay, renew - useful only with listener timeout
|
|
|
|
|
TF_CLOSE = 3, //!< Handled, remove self
|
|
|
|
|
TF_NEXT = 0, //!< Not handled, let other listeners handle it
|
|
|
|
|
TF_STAY = 1, //!< Handled, stay
|
|
|
|
|
TF_RENEW = 2, //!< Handled, stay, renew - useful only with listener timeout
|
|
|
|
|
TF_CLOSE = 3, //!< Handled, remove self
|
|
|
|
|
} TF_Result; |
|
|
|
|
|
|
|
|
|
/** Data structure for sending / receiving messages */ |
|
|
|
|
typedef struct _TF_MSG_STRUCT_ { |
|
|
|
|
TF_ID frame_id; //!< message ID
|
|
|
|
|
bool is_response; //!< internal flag, set when using the Respond function. frame_id is then kept unchanged.
|
|
|
|
|
TF_TYPE type; //!< received or sent message type
|
|
|
|
|
const uint8_t *data; //!< buffer of received data or data to send. NULL = listener timed out, free userdata!
|
|
|
|
|
TF_LEN len; //!< length of the buffer
|
|
|
|
|
void *userdata; //!< here's a place for custom data; this data will be stored with the listener
|
|
|
|
|
void *userdata2; |
|
|
|
|
TF_ID frame_id; //!< message ID
|
|
|
|
|
bool is_response; //!< internal flag, set when using the Respond function. frame_id is then kept unchanged.
|
|
|
|
|
TF_TYPE type; //!< received or sent message type
|
|
|
|
|
const uint8_t *data; //!< buffer of received data or data to send. NULL = listener timed out, free userdata!
|
|
|
|
|
TF_LEN len; //!< length of the buffer
|
|
|
|
|
void *userdata; //!< here's a place for custom data; this data will be stored with the listener
|
|
|
|
|
void *userdata2; |
|
|
|
|
} TF_Msg; |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -114,7 +114,7 @@ typedef struct _TF_MSG_STRUCT_ { |
|
|
|
|
*/ |
|
|
|
|
static inline void TF_ClearMsg(TF_Msg *msg) |
|
|
|
|
{ |
|
|
|
|
memset(msg, 0, sizeof(TF_Msg)); |
|
|
|
|
memset(msg, 0, sizeof(TF_Msg)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
typedef struct TinyFrame_ TinyFrame; |
|
|
|
@ -132,78 +132,79 @@ typedef TF_Result (*TF_Listener)(TinyFrame *tf, TF_Msg *msg); |
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
enum TFState { |
|
|
|
|
TFState_SOF = 0, //!< Wait for SOF
|
|
|
|
|
TFState_LEN, //!< Wait for Number Of Bytes
|
|
|
|
|
TFState_HEAD_CKSUM, //!< Wait for header Checksum
|
|
|
|
|
TFState_ID, //!< Wait for ID
|
|
|
|
|
TFState_TYPE, //!< Wait for message type
|
|
|
|
|
TFState_DATA, //!< Receive payload
|
|
|
|
|
TFState_DATA_CKSUM //!< Wait for Checksum
|
|
|
|
|
enum TFState_ { |
|
|
|
|
TFState_SOF = 0, //!< Wait for SOF
|
|
|
|
|
TFState_LEN, //!< Wait for Number Of Bytes
|
|
|
|
|
TFState_HEAD_CKSUM, //!< Wait for header Checksum
|
|
|
|
|
TFState_ID, //!< Wait for ID
|
|
|
|
|
TFState_TYPE, //!< Wait for message type
|
|
|
|
|
TFState_DATA, //!< Receive payload
|
|
|
|
|
TFState_DATA_CKSUM //!< Wait for Checksum
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct TF_IdListener_ { |
|
|
|
|
TF_ID id; |
|
|
|
|
TF_Listener fn; |
|
|
|
|
TF_TICKS timeout; // nr of ticks remaining to disable this listener
|
|
|
|
|
TF_TICKS timeout_max; // the original timeout is stored here
|
|
|
|
|
void *userdata; |
|
|
|
|
void *userdata2; |
|
|
|
|
TF_ID id; |
|
|
|
|
TF_Listener fn; |
|
|
|
|
TF_TICKS timeout; // nr of ticks remaining to disable this listener
|
|
|
|
|
TF_TICKS timeout_max; // the original timeout is stored here
|
|
|
|
|
void *userdata; |
|
|
|
|
void *userdata2; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct TF_TypeListener_ { |
|
|
|
|
TF_TYPE type; |
|
|
|
|
TF_Listener fn; |
|
|
|
|
TF_TYPE type; |
|
|
|
|
TF_Listener fn; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct TF_GenericListener_ { |
|
|
|
|
TF_Listener fn; |
|
|
|
|
TF_Listener fn; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Frame parser internal state. |
|
|
|
|
*/ |
|
|
|
|
struct TinyFrame_ { |
|
|
|
|
/* Public user data */ |
|
|
|
|
union { |
|
|
|
|
void *userdata; |
|
|
|
|
uint32_t usertag; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// --- the rest of the struct is internal, do not access directly ---
|
|
|
|
|
|
|
|
|
|
/* Own state */ |
|
|
|
|
TF_Peer peer_bit; //!< Own peer bit (unqiue to avoid msg ID clash)
|
|
|
|
|
TF_ID next_id; //!< Next frame / frame chain ID
|
|
|
|
|
|
|
|
|
|
/* Parser state */ |
|
|
|
|
enum TFState state; |
|
|
|
|
TF_TICKS parser_timeout_ticks; |
|
|
|
|
TF_ID id; //!< Incoming packet ID
|
|
|
|
|
TF_LEN len; //!< Payload length
|
|
|
|
|
uint8_t data[TF_MAX_PAYLOAD_RX]; //!< Data byte buffer
|
|
|
|
|
TF_LEN rxi; //!< Field size byte counter
|
|
|
|
|
TF_CKSUM cksum; //!< Checksum calculated of the data stream
|
|
|
|
|
TF_CKSUM ref_cksum; //!< Reference checksum read from the message
|
|
|
|
|
TF_TYPE type; //!< Collected message type number
|
|
|
|
|
bool discard_data; //!< Set if (len > TF_MAX_PAYLOAD) to read the frame, but ignore the data.
|
|
|
|
|
|
|
|
|
|
/* --- Callbacks --- */ |
|
|
|
|
|
|
|
|
|
/* Transaction callbacks */ |
|
|
|
|
struct TF_IdListener_ id_listeners[TF_MAX_ID_LST]; |
|
|
|
|
struct TF_TypeListener_ type_listeners[TF_MAX_TYPE_LST]; |
|
|
|
|
struct TF_GenericListener_ generic_listeners[TF_MAX_GEN_LST]; |
|
|
|
|
|
|
|
|
|
// Those counters are used to optimize look-up times.
|
|
|
|
|
// They point to the highest used slot number,
|
|
|
|
|
// or close to it, depending on the removal order.
|
|
|
|
|
TF_COUNT count_id_lst; |
|
|
|
|
TF_COUNT count_type_lst; |
|
|
|
|
TF_COUNT count_generic_lst; |
|
|
|
|
|
|
|
|
|
// Buffer for building frames
|
|
|
|
|
uint8_t sendbuf[TF_SENDBUF_LEN]; |
|
|
|
|
/* Public user data */ |
|
|
|
|
union { |
|
|
|
|
// choice between two representations
|
|
|
|
|
void *userdata; |
|
|
|
|
uint32_t usertag; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// --- the rest of the struct is internal, do not access directly ---
|
|
|
|
|
|
|
|
|
|
/* Own state */ |
|
|
|
|
TF_Peer peer_bit; //!< Own peer bit (unqiue to avoid msg ID clash)
|
|
|
|
|
TF_ID next_id; //!< Next frame / frame chain ID
|
|
|
|
|
|
|
|
|
|
/* Parser state */ |
|
|
|
|
enum TFState_ state; |
|
|
|
|
TF_TICKS parser_timeout_ticks; |
|
|
|
|
TF_ID id; //!< Incoming packet ID
|
|
|
|
|
TF_LEN len; //!< Payload length
|
|
|
|
|
uint8_t data[TF_MAX_PAYLOAD_RX]; //!< Data byte buffer
|
|
|
|
|
TF_LEN rxi; //!< Field size byte counter
|
|
|
|
|
TF_CKSUM cksum; //!< Checksum calculated of the data stream
|
|
|
|
|
TF_CKSUM ref_cksum; //!< Reference checksum read from the message
|
|
|
|
|
TF_TYPE type; //!< Collected message type number
|
|
|
|
|
bool discard_data; //!< Set if (len > TF_MAX_PAYLOAD) to read the frame, but ignore the data.
|
|
|
|
|
|
|
|
|
|
/* --- Callbacks --- */ |
|
|
|
|
|
|
|
|
|
/* Transaction callbacks */ |
|
|
|
|
struct TF_IdListener_ id_listeners[TF_MAX_ID_LST]; |
|
|
|
|
struct TF_TypeListener_ type_listeners[TF_MAX_TYPE_LST]; |
|
|
|
|
struct TF_GenericListener_ generic_listeners[TF_MAX_GEN_LST]; |
|
|
|
|
|
|
|
|
|
// Those counters are used to optimize look-up times.
|
|
|
|
|
// They point to the highest used slot number,
|
|
|
|
|
// or close to it, depending on the removal order.
|
|
|
|
|
TF_COUNT count_id_lst; |
|
|
|
|
TF_COUNT count_type_lst; |
|
|
|
|
TF_COUNT count_generic_lst; |
|
|
|
|
|
|
|
|
|
// Buffer for building frames
|
|
|
|
|
uint8_t sendbuf[TF_SENDBUF_LEN]; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
@ -304,7 +305,8 @@ bool TF_Query(TinyFrame *tf, TF_Msg *msg, TF_Listener listener, TF_TICKS timeout |
|
|
|
|
/**
|
|
|
|
|
* Like TF_Query, but without the struct |
|
|
|
|
*/ |
|
|
|
|
bool TF_QuerySimple(TinyFrame *tf, TF_TYPE type, const uint8_t *data, TF_LEN len, TF_Listener listener, TF_TICKS timeout); |
|
|
|
|
bool TF_QuerySimple(TinyFrame *tf, TF_TYPE type, const uint8_t *data, TF_LEN len, |
|
|
|
|
TF_Listener listener, TF_TICKS timeout); |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Send a response to a received message. |
|
|
|
|