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
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_ {
TF_ID id;
TF_LISTENER fn;
unsigned int timeout; // nr of ticks remaining to disable this listener
unsigned int timeout_max; // the original timeout is stored here
TF_COUNT timeout; // nr of ticks remaining to disable this listener
TF_COUNT timeout_max; // the original timeout is stored here
void *userdata;
} IdListener;
@ -51,7 +51,7 @@ static struct TinyFrameStruct {
TF_ID id; //!< Incoming packet ID
TF_LEN len; //!< Payload length
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 ref_cksum; //!< Reference checksum read from the message
TF_TYPE type; //!< Collected message type number
@ -67,9 +67,9 @@ static struct TinyFrameStruct {
// 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.
size_t count_id_lst;
size_t count_type_lst;
size_t count_generic_lst;
TF_COUNT count_id_lst;
TF_COUNT count_type_lst;
TF_COUNT count_generic_lst;
// Buffer for building frames
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
/**
* 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)
{
size_t i;
TF_COUNT i;
IdListener *lst;
for (i = 0; i < TF_MAX_ID_LST; i++) {
lst = &tf.id_listeners[i];
// test for empty slot
if (lst->fn == NULL) {
lst->fn = cb;
lst->id = msg->frame_id;
lst->userdata = msg->userdata;
lst->timeout_max = lst->timeout = timeout;
if (i >= tf.count_id_lst) {
tf.count_id_lst = i + 1;
tf.count_id_lst = (TF_COUNT) (i + 1);
}
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)
{
size_t i;
TF_COUNT i;
TypeListener *lst;
for (i = 0; i < TF_MAX_TYPE_LST; i++) {
lst = &tf.type_listeners[i];
// test for empty slot
if (lst->fn == NULL) {
lst->fn = cb;
lst->type = frame_type;
if (i >= tf.count_type_lst) {
tf.count_type_lst = i + 1;
tf.count_type_lst = (TF_COUNT) (i + 1);
}
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)
{
size_t i;
TF_COUNT i;
GenericListener *lst;
for (i = 0; i < TF_MAX_GEN_LST; i++) {
lst = &tf.generic_listeners[i];
// test for empty slot
if (lst->fn == NULL) {
lst->fn = cb;
if (i >= tf.count_generic_lst) {
tf.count_generic_lst = i + 1;
tf.count_generic_lst = (TF_COUNT) (i + 1);
}
return true;
}
@ -267,15 +316,13 @@ bool _TF_FN TF_AddGenericListener(TF_LISTENER cb)
bool _TF_FN TF_RemoveIdListener(TF_ID frame_id)
{
size_t i;
TF_COUNT i;
IdListener *lst;
for (i = 0; i < tf.count_id_lst; i++) {
lst = &tf.id_listeners[i];
// test if live & matching
if (lst->fn != NULL && lst->id == frame_id) {
lst->fn = NULL;
if (i == tf.count_id_lst - 1) {
tf.count_id_lst--;
}
cleanup_id_listener(i, lst);
return true;
}
}
@ -284,15 +331,13 @@ bool _TF_FN TF_RemoveIdListener(TF_ID frame_id)
bool _TF_FN TF_RemoveTypeListener(TF_TYPE type)
{
size_t i;
TF_COUNT i;
TypeListener *lst;
for (i = 0; i < tf.count_type_lst; i++) {
lst = &tf.type_listeners[i];
// test if live & matching
if (lst->fn != NULL && lst->type == type) {
lst->fn = NULL;
if (i == tf.count_type_lst - 1) {
tf.count_type_lst--;
}
cleanup_type_listener(i, lst);
return true;
}
}
@ -301,15 +346,13 @@ bool _TF_FN TF_RemoveTypeListener(TF_TYPE type)
bool _TF_FN TF_RemoveGenericListener(TF_LISTENER cb)
{
size_t i;
TF_COUNT i;
GenericListener *lst;
for (i = 0; i < tf.count_generic_lst; i++) {
lst = &tf.generic_listeners[i];
// test if live & matching
if (lst->fn == cb) {
lst->fn = NULL;
if (i == tf.count_generic_lst - 1) {
tf.count_generic_lst--;
}
cleanup_generic_listener(i, lst);
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 */
static void _TF_FN TF_HandleReceivedMessage(void)
{
size_t i;
TF_COUNT i;
IdListener *ilst;
TypeListener *tlst;
GenericListener *glst;
@ -342,8 +385,9 @@ static void _TF_FN TF_HandleReceivedMessage(void)
for (i = 0; i < tf.count_id_lst; i++) {
ilst = &tf.id_listeners[i];
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;
ilst->userdata = msg.userdata; // put it back (may have changed the pointer or set to NULL)
}
}
msg.userdata = NULL;
@ -530,24 +574,25 @@ void _TF_FN TF_AcceptChar(unsigned char c)
* @param len - payload size in bytes
* @param explicit_id - ID to use in the frame (8-bit)
* @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,
const uint8_t *data, TF_LEN data_len,
TF_ID explicit_id, bool use_expl_id)
{
int i;
char si; // signed small int
TF_LEN i;
uint8_t b;
TF_ID id;
TF_CKSUM cksum;
int pos = 0;
size_t pos = 0; // can be needed to grow larger than TF_LEN
CKSUM_RESET(cksum);
// sanitize len
if (data_len > TF_MAX_PAYLOAD_TX) {
return TF_ERROR;
return 0;
}
// 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
#define WRITENUM_BASE(type, num, xtra) \
for (i = sizeof(type)-1; i>=0; i--) { \
b = (uint8_t)(num >> (i*8) & 0xFF); \
for (si = sizeof(type)-1; si>=0; si--) { \
b = (uint8_t)(num >> (si*8) & 0xFF); \
outbuff[pos++] = b; \
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)
{
int len;
size_t len;
len = TF_Compose(tf.sendbuf,
&msg->frame_id,
msg->type,
@ -624,11 +669,11 @@ bool _TF_FN TF_Send(TF_MSG *msg, TF_LISTENER listener, TF_TICKS timeout)
msg->frame_id,
msg->is_response);
if (len == TF_ERROR) return false;
if (len == 0) return false;
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;
}
@ -644,11 +689,12 @@ bool _TF_FN TF_Respond(TF_MSG *msg, bool renew)
bool _TF_FN TF_RenewIdListener(TF_ID id)
{
size_t i;
TF_COUNT i;
IdListener *lst;
for (i = 0; i < tf.count_id_lst; 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;
return true;
}
@ -659,8 +705,7 @@ bool _TF_FN TF_RenewIdListener(TF_ID id)
/** Timebase hook - for timeouts */
void _TF_FN TF_Tick(void)
{
size_t i;
TF_MSG msg;
TF_COUNT i;
IdListener *lst;
// 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
for (i = 0; i < tf.count_id_lst; i++) {
lst = &tf.id_listeners[i];
if (lst->fn && lst->timeout > 0) {
if (--lst->timeout != 0) continue;
// Notify listener about timeout
msg.userdata = lst->userdata;
msg.data = NULL; // this is a signal that listener should clean up
lst->fn(&msg);
lst->fn = NULL; // Discard listener
if (!lst->fn || lst->timeout == 0) continue;
// count down...
if (--lst->timeout == 0) {
// Listener has expired
cleanup_id_listener(i, lst);
}
}
}

@ -56,9 +56,14 @@
// Value of the SOF byte (if TF_USE_SOF_BYTE == 1)
#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 ------------------------------
typedef unsigned int TF_TICKS;
//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
#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))
@ -145,8 +147,7 @@ typedef struct _TF_MSG_STRUCT_ {
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 *userdata; // here's a place for custom data; this data will be stored with the listener
} TF_MSG;
/**
@ -282,7 +283,7 @@ void TF_AcceptChar(uint8_t c);
*
* ! 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.

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

Loading…
Cancel
Save