did some cleaning

pull/9/head
Ondřej Hruška 7 years ago
parent b89f458c19
commit d1aec88f23
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 2
      Makefile
  2. 145
      TinyFrame.c
  3. 15
      TinyFrame.h
  4. 9
      test.c

@ -7,4 +7,4 @@ debug: tf.bin
gdb -q -ex run ./tf.bin gdb -q -ex run ./tf.bin
tf.bin: test.c TinyFrame.c TinyFrame.h tf.bin: test.c TinyFrame.c TinyFrame.h
gcc -Os --std=gnu89 -Wall -Wno-main -Wno-unused -Wextra test.c TinyFrame.c -I. -o tf.bin gcc -O0 -ggdb --std=gnu89 -Wall -Wno-main -Wextra test.c TinyFrame.c -I. -o tf.bin

@ -23,8 +23,8 @@ enum TFState {
typedef struct _IdListener_struct_ { typedef struct _IdListener_struct_ {
TF_ID id; TF_ID id;
TF_LISTENER fn; TF_LISTENER fn;
unsigned int timeout; // nr of ticks remaining to disable this listener TF_COUNT timeout; // nr of ticks remaining to disable this listener
unsigned int timeout_max; // the original timeout is stored here TF_COUNT timeout_max; // the original timeout is stored here
void *userdata; void *userdata;
} IdListener; } IdListener;
@ -51,7 +51,7 @@ static struct TinyFrameStruct {
TF_ID id; //!< Incoming packet ID TF_ID id; //!< Incoming packet ID
TF_LEN len; //!< Payload length TF_LEN len; //!< Payload length
uint8_t data[TF_MAX_PAYLOAD_RX]; //!< Data byte buffer uint8_t data[TF_MAX_PAYLOAD_RX]; //!< Data byte buffer
size_t rxi; //!< Byte counter TF_LEN rxi; //!< Field size byte counter
TF_CKSUM cksum; //!< Checksum calculated of the data stream TF_CKSUM cksum; //!< Checksum calculated of the data stream
TF_CKSUM ref_cksum; //!< Reference checksum read from the message TF_CKSUM ref_cksum; //!< Reference checksum read from the message
TF_TYPE type; //!< Collected message type number TF_TYPE type; //!< Collected message type number
@ -67,9 +67,9 @@ static struct TinyFrameStruct {
// Those counters are used to optimize look-up times. // Those counters are used to optimize look-up times.
// They point to the highest used slot number, // They point to the highest used slot number,
// or close to it, depending on the removal order. // or close to it, depending on the removal order.
size_t count_id_lst; TF_COUNT count_id_lst;
size_t count_type_lst; TF_COUNT count_type_lst;
size_t count_generic_lst; TF_COUNT count_generic_lst;
// Buffer for building frames // Buffer for building frames
uint8_t sendbuf[TF_MAX_PAYLOAD_TX + TF_OVERHEAD_BYTES]; // TODO generate and send frames without a buffer uint8_t sendbuf[TF_MAX_PAYLOAD_TX + TF_OVERHEAD_BYTES]; // TODO generate and send frames without a buffer
@ -210,19 +210,66 @@ void _TF_FN TF_Init(TF_PEER peer_bit)
//region Listeners //region Listeners
/**
* Notify callback about ID listener demise & clean it
*
* @param lst - listener to clean
*/
static void _TF_FN cleanup_id_listener(TF_COUNT i, IdListener *lst)
{
TF_MSG msg;
if (lst->fn == NULL) return;
msg.userdata = lst->userdata;
msg.data = NULL; // this is a signal that the listener should clean up
lst->fn(&msg);
lst->fn = NULL; // Discard listener
if (i == tf.count_id_lst - 1) {
tf.count_id_lst--;
}
}
/**
* Clean up Type listener
*
* @param lst - listener to clean
*/
static inline void _TF_FN cleanup_type_listener(TF_COUNT i, TypeListener *lst)
{
lst->fn = NULL; // Discard listener
if (i == tf.count_type_lst - 1) {
tf.count_type_lst--;
}
}
/**
* Clean up Generic listener
*
* @param lst - listener to clean
*/
static inline void _TF_FN cleanup_generic_listener(TF_COUNT i, GenericListener *lst)
{
lst->fn = NULL; // Discard listener
if (i == tf.count_generic_lst - 1) {
tf.count_generic_lst--;
}
}
bool _TF_FN TF_AddIdListener(TF_MSG *msg, TF_LISTENER cb, TF_TICKS timeout) bool _TF_FN TF_AddIdListener(TF_MSG *msg, TF_LISTENER cb, TF_TICKS timeout)
{ {
size_t i; TF_COUNT i;
IdListener *lst; IdListener *lst;
for (i = 0; i < TF_MAX_ID_LST; i++) { for (i = 0; i < TF_MAX_ID_LST; i++) {
lst = &tf.id_listeners[i]; lst = &tf.id_listeners[i];
// test for empty slot
if (lst->fn == NULL) { if (lst->fn == NULL) {
lst->fn = cb; lst->fn = cb;
lst->id = msg->frame_id; lst->id = msg->frame_id;
lst->userdata = msg->userdata; lst->userdata = msg->userdata;
lst->timeout_max = lst->timeout = timeout; lst->timeout_max = lst->timeout = timeout;
if (i >= tf.count_id_lst) { if (i >= tf.count_id_lst) {
tf.count_id_lst = i + 1; tf.count_id_lst = (TF_COUNT) (i + 1);
} }
return true; return true;
} }
@ -232,15 +279,16 @@ bool _TF_FN TF_AddIdListener(TF_MSG *msg, TF_LISTENER cb, TF_TICKS timeout)
bool _TF_FN TF_AddTypeListener(TF_TYPE frame_type, TF_LISTENER cb) bool _TF_FN TF_AddTypeListener(TF_TYPE frame_type, TF_LISTENER cb)
{ {
size_t i; TF_COUNT i;
TypeListener *lst; TypeListener *lst;
for (i = 0; i < TF_MAX_TYPE_LST; i++) { for (i = 0; i < TF_MAX_TYPE_LST; i++) {
lst = &tf.type_listeners[i]; lst = &tf.type_listeners[i];
// test for empty slot
if (lst->fn == NULL) { if (lst->fn == NULL) {
lst->fn = cb; lst->fn = cb;
lst->type = frame_type; lst->type = frame_type;
if (i >= tf.count_type_lst) { if (i >= tf.count_type_lst) {
tf.count_type_lst = i + 1; tf.count_type_lst = (TF_COUNT) (i + 1);
} }
return true; return true;
} }
@ -250,14 +298,15 @@ bool _TF_FN TF_AddTypeListener(TF_TYPE frame_type, TF_LISTENER cb)
bool _TF_FN TF_AddGenericListener(TF_LISTENER cb) bool _TF_FN TF_AddGenericListener(TF_LISTENER cb)
{ {
size_t i; TF_COUNT i;
GenericListener *lst; GenericListener *lst;
for (i = 0; i < TF_MAX_GEN_LST; i++) { for (i = 0; i < TF_MAX_GEN_LST; i++) {
lst = &tf.generic_listeners[i]; lst = &tf.generic_listeners[i];
// test for empty slot
if (lst->fn == NULL) { if (lst->fn == NULL) {
lst->fn = cb; lst->fn = cb;
if (i >= tf.count_generic_lst) { if (i >= tf.count_generic_lst) {
tf.count_generic_lst = i + 1; tf.count_generic_lst = (TF_COUNT) (i + 1);
} }
return true; return true;
} }
@ -267,15 +316,13 @@ bool _TF_FN TF_AddGenericListener(TF_LISTENER cb)
bool _TF_FN TF_RemoveIdListener(TF_ID frame_id) bool _TF_FN TF_RemoveIdListener(TF_ID frame_id)
{ {
size_t i; TF_COUNT i;
IdListener *lst; IdListener *lst;
for (i = 0; i < tf.count_id_lst; i++) { for (i = 0; i < tf.count_id_lst; i++) {
lst = &tf.id_listeners[i]; lst = &tf.id_listeners[i];
// test if live & matching
if (lst->fn != NULL && lst->id == frame_id) { if (lst->fn != NULL && lst->id == frame_id) {
lst->fn = NULL; cleanup_id_listener(i, lst);
if (i == tf.count_id_lst - 1) {
tf.count_id_lst--;
}
return true; return true;
} }
} }
@ -284,15 +331,13 @@ bool _TF_FN TF_RemoveIdListener(TF_ID frame_id)
bool _TF_FN TF_RemoveTypeListener(TF_TYPE type) bool _TF_FN TF_RemoveTypeListener(TF_TYPE type)
{ {
size_t i; TF_COUNT i;
TypeListener *lst; TypeListener *lst;
for (i = 0; i < tf.count_type_lst; i++) { for (i = 0; i < tf.count_type_lst; i++) {
lst = &tf.type_listeners[i]; lst = &tf.type_listeners[i];
// test if live & matching
if (lst->fn != NULL && lst->type == type) { if (lst->fn != NULL && lst->type == type) {
lst->fn = NULL; cleanup_type_listener(i, lst);
if (i == tf.count_type_lst - 1) {
tf.count_type_lst--;
}
return true; return true;
} }
} }
@ -301,15 +346,13 @@ bool _TF_FN TF_RemoveTypeListener(TF_TYPE type)
bool _TF_FN TF_RemoveGenericListener(TF_LISTENER cb) bool _TF_FN TF_RemoveGenericListener(TF_LISTENER cb)
{ {
size_t i; TF_COUNT i;
GenericListener *lst; GenericListener *lst;
for (i = 0; i < tf.count_generic_lst; i++) { for (i = 0; i < tf.count_generic_lst; i++) {
lst = &tf.generic_listeners[i]; lst = &tf.generic_listeners[i];
// test if live & matching
if (lst->fn == cb) { if (lst->fn == cb) {
lst->fn = NULL; cleanup_generic_listener(i, lst);
if (i == tf.count_generic_lst - 1) {
tf.count_generic_lst--;
}
return true; return true;
} }
} }
@ -319,7 +362,7 @@ bool _TF_FN TF_RemoveGenericListener(TF_LISTENER cb)
/** Handle a message that was just collected & verified by the parser */ /** Handle a message that was just collected & verified by the parser */
static void _TF_FN TF_HandleReceivedMessage(void) static void _TF_FN TF_HandleReceivedMessage(void)
{ {
size_t i; TF_COUNT i;
IdListener *ilst; IdListener *ilst;
TypeListener *tlst; TypeListener *tlst;
GenericListener *glst; GenericListener *glst;
@ -342,8 +385,9 @@ static void _TF_FN TF_HandleReceivedMessage(void)
for (i = 0; i < tf.count_id_lst; i++) { for (i = 0; i < tf.count_id_lst; i++) {
ilst = &tf.id_listeners[i]; ilst = &tf.id_listeners[i];
if (ilst->fn && ilst->id == msg.frame_id) { if (ilst->fn && ilst->id == msg.frame_id) {
msg.userdata = ilst->userdata; msg.userdata = ilst->userdata; // pass userdata pointer to the callback
if (ilst->fn(&msg)) return; if (ilst->fn(&msg)) return;
ilst->userdata = msg.userdata; // put it back (may have changed the pointer or set to NULL)
} }
} }
msg.userdata = NULL; msg.userdata = NULL;
@ -530,24 +574,25 @@ void _TF_FN TF_AcceptChar(unsigned char c)
* @param len - payload size in bytes * @param len - payload size in bytes
* @param explicit_id - ID to use in the frame (8-bit) * @param explicit_id - ID to use in the frame (8-bit)
* @param use_expl_id - whether to use the previous param * @param use_expl_id - whether to use the previous param
* @return nr of bytes in outbuff used by the frame, TF_ERROR (-1) on failure * @return nr of bytes in outbuff used by the frame, 0 on failure
*/ */
static inline int _TF_FN TF_Compose(uint8_t *outbuff, TF_ID *id_ptr, static inline size_t _TF_FN TF_Compose(uint8_t *outbuff, TF_ID *id_ptr,
TF_TYPE type, TF_TYPE type,
const uint8_t *data, TF_LEN data_len, const uint8_t *data, TF_LEN data_len,
TF_ID explicit_id, bool use_expl_id) TF_ID explicit_id, bool use_expl_id)
{ {
int i; char si; // signed small int
TF_LEN i;
uint8_t b; uint8_t b;
TF_ID id; TF_ID id;
TF_CKSUM cksum; TF_CKSUM cksum;
int pos = 0; size_t pos = 0; // can be needed to grow larger than TF_LEN
CKSUM_RESET(cksum); CKSUM_RESET(cksum);
// sanitize len // sanitize len
if (data_len > TF_MAX_PAYLOAD_TX) { if (data_len > TF_MAX_PAYLOAD_TX) {
return TF_ERROR; return 0;
} }
// Gen ID // Gen ID
@ -566,8 +611,8 @@ static inline int _TF_FN TF_Compose(uint8_t *outbuff, TF_ID *id_ptr,
// DRY helper for writing a multi-byte variable to the buffer // DRY helper for writing a multi-byte variable to the buffer
#define WRITENUM_BASE(type, num, xtra) \ #define WRITENUM_BASE(type, num, xtra) \
for (i = sizeof(type)-1; i>=0; i--) { \ for (si = sizeof(type)-1; si>=0; si--) { \
b = (uint8_t)(num >> (i*8) & 0xFF); \ b = (uint8_t)(num >> (si*8) & 0xFF); \
outbuff[pos++] = b; \ outbuff[pos++] = b; \
xtra; \ xtra; \
} }
@ -615,7 +660,7 @@ static inline int _TF_FN TF_Compose(uint8_t *outbuff, TF_ID *id_ptr,
bool _TF_FN TF_Send(TF_MSG *msg, TF_LISTENER listener, TF_TICKS timeout) bool _TF_FN TF_Send(TF_MSG *msg, TF_LISTENER listener, TF_TICKS timeout)
{ {
int len; size_t len;
len = TF_Compose(tf.sendbuf, len = TF_Compose(tf.sendbuf,
&msg->frame_id, &msg->frame_id,
msg->type, msg->type,
@ -624,11 +669,11 @@ bool _TF_FN TF_Send(TF_MSG *msg, TF_LISTENER listener, TF_TICKS timeout)
msg->frame_id, msg->frame_id,
msg->is_response); msg->is_response);
if (len == TF_ERROR) return false; if (len == 0) return false;
if (listener) TF_AddIdListener(msg, listener, timeout); if (listener) TF_AddIdListener(msg, listener, timeout);
TF_WriteImpl((const uint8_t *) tf.sendbuf, (TF_LEN)len); TF_WriteImpl((const uint8_t *) tf.sendbuf, len);
return true; return true;
} }
@ -644,11 +689,12 @@ bool _TF_FN TF_Respond(TF_MSG *msg, bool renew)
bool _TF_FN TF_RenewIdListener(TF_ID id) bool _TF_FN TF_RenewIdListener(TF_ID id)
{ {
size_t i; TF_COUNT i;
IdListener *lst; IdListener *lst;
for (i = 0; i < tf.count_id_lst; i++) { for (i = 0; i < tf.count_id_lst; i++) {
lst = &tf.id_listeners[i]; lst = &tf.id_listeners[i];
if (lst->fn && lst->id == id) { // test if live & matching
if (lst->fn != NULL && lst->id == id) {
lst->timeout = lst->timeout_max; lst->timeout = lst->timeout_max;
return true; return true;
} }
@ -659,8 +705,7 @@ bool _TF_FN TF_RenewIdListener(TF_ID id)
/** Timebase hook - for timeouts */ /** Timebase hook - for timeouts */
void _TF_FN TF_Tick(void) void _TF_FN TF_Tick(void)
{ {
size_t i; TF_COUNT i;
TF_MSG msg;
IdListener *lst; IdListener *lst;
// increment parser timeout (timeout is handled when receiving next byte) // increment parser timeout (timeout is handled when receiving next byte)
@ -671,15 +716,11 @@ void _TF_FN TF_Tick(void)
// decrement and expire ID listeners // decrement and expire ID listeners
for (i = 0; i < tf.count_id_lst; i++) { for (i = 0; i < tf.count_id_lst; i++) {
lst = &tf.id_listeners[i]; lst = &tf.id_listeners[i];
if (lst->fn && lst->timeout > 0) { if (!lst->fn || lst->timeout == 0) continue;
if (--lst->timeout != 0) continue; // count down...
if (--lst->timeout == 0) {
// Notify listener about timeout // Listener has expired
msg.userdata = lst->userdata; cleanup_id_listener(i, lst);
msg.data = NULL; // this is a signal that listener should clean up
lst->fn(&msg);
lst->fn = NULL; // Discard listener
} }
} }
} }

@ -56,9 +56,14 @@
// Value of the SOF byte (if TF_USE_SOF_BYTE == 1) // Value of the SOF byte (if TF_USE_SOF_BYTE == 1)
#define TF_SOF_BYTE 0x01 #define TF_SOF_BYTE 0x01
// used for timeout tick counters - should be large enough for all used timeouts
typedef uint16_t TF_TICKS;
// used in loops iterating over listeners
typedef uint8_t TF_COUNT;
//------------------------- End of user config ------------------------------ //------------------------- End of user config ------------------------------
typedef unsigned int TF_TICKS;
//region Resolve data types //region Resolve data types
@ -123,9 +128,6 @@ typedef unsigned int TF_TICKS;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Return value indicating error state
#define TF_ERROR -1
// Type-dependent masks for bit manipulation in the ID field // Type-dependent masks for bit manipulation in the ID field
#define TF_ID_MASK (TF_ID)(((TF_ID)1 << (sizeof(TF_ID)*8 - 1)) - 1) #define TF_ID_MASK (TF_ID)(((TF_ID)1 << (sizeof(TF_ID)*8 - 1)) - 1)
#define TF_ID_PEERBIT (TF_ID)((TF_ID)1 << ((sizeof(TF_ID)*8) - 1)) #define TF_ID_PEERBIT (TF_ID)((TF_ID)1 << ((sizeof(TF_ID)*8) - 1))
@ -145,8 +147,7 @@ typedef struct _TF_MSG_STRUCT_ {
TF_TYPE type; // received or sent message type 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! 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 TF_LEN len; // length of the buffer
void *userdata; // here's a place for custom data; this data will be void *userdata; // here's a place for custom data; this data will be stored with the listener
// stored with the listener
} TF_MSG; } TF_MSG;
/** /**
@ -282,7 +283,7 @@ void TF_AcceptChar(uint8_t c);
* *
* ! Implement this in your application code ! * ! Implement this in your application code !
*/ */
extern void TF_WriteImpl(const uint8_t *buff, TF_LEN len); extern void TF_WriteImpl(const uint8_t *buff, size_t len);
/** /**
* This function should be called periodically. * This function should be called periodically.

@ -11,7 +11,7 @@ static void dumpFrame(const uint8_t *buff, TF_LEN len);
* This function should be defined in the application code. * This function should be defined in the application code.
* It implements the lowest layer - sending bytes to UART (or other) * It implements the lowest layer - sending bytes to UART (or other)
*/ */
void TF_WriteImpl(const uint8_t *buff, TF_LEN len) void TF_WriteImpl(const uint8_t *buff, size_t len)
{ {
printf("--------------------\n"); printf("--------------------\n");
printf("\033[32mTF_WriteImpl - sending frame:\033[0m\n"); printf("\033[32mTF_WriteImpl - sending frame:\033[0m\n");
@ -42,23 +42,24 @@ bool testIdListener(TF_MSG *msg)
void main(void) void main(void)
{ {
TF_MSG msg;
const char *longstr = "Lorem ipsum dolor sit amet.";
// Set up the TinyFrame library // Set up the TinyFrame library
TF_Init(TF_MASTER); // 1 = master, 0 = slave TF_Init(TF_MASTER); // 1 = master, 0 = slave
TF_AddGenericListener(myListener); TF_AddGenericListener(myListener);
printf("------ Simulate sending a message --------\n"); printf("------ Simulate sending a message --------\n");
TF_MSG msg;
TF_ClearMsg(&msg); TF_ClearMsg(&msg);
msg.type = 0x22; msg.type = 0x22;
msg.data = (pu8)"Hello TinyFrame"; msg.data = (pu8)"Hello TinyFrame";
msg.len = 16; msg.len = 16;
TF_Send(&msg, NULL, 0); TF_Send(&msg, NULL, 0);
const char *longstr = "Lorem ipsum dolor sit amet.";
msg.type = 0x33; msg.type = 0x33;
msg.data = (pu8)longstr; msg.data = (pu8)longstr;
msg.len = strlen(longstr)+1; // add the null byte msg.len = (TF_LEN) (strlen(longstr)+1); // add the null byte
TF_Send(&msg, NULL, 0); TF_Send(&msg, NULL, 0);
msg.type = 0x44; msg.type = 0x44;

Loading…
Cancel
Save