5 Commits
16 changed files with 667 additions and 208 deletions
+8 -6
View File
@@ -4,11 +4,13 @@ project(tf)
set(CMAKE_CXX_STANDARD GNU89)
set(SOURCE_FILES
demo/test/test.c
demo/test/TF_Config.h
demo/hello/master.c
demo/hello/slave.c
demo/hello/TF_Config.h
demo/simple/test.c
demo/simple/TF_Config.h
demo/socket_demo/master.c
demo/socket_demo/slave.c
demo/socket_demo/TF_Config.h
demo/multipart_tx/test.c
demo/multipart_tx/TF_Config.h
demo/demo.c
demo/demo.h
TinyFrame.c
@@ -18,6 +20,6 @@ set(SOURCE_FILES
demo/utils.h
)
include_directories(demo/test)
include_directories(demo/simple)
add_executable(tf ${SOURCE_FILES})
+2 -2
View File
@@ -52,7 +52,7 @@ DATA_CKSUM .. checksum, implemented as XOR of all preceding bytes in the message
- Start by calling `TF_Init()` with `TF_MASTER` or `TF_SLAVE` as the argument
- Implement `TF_WriteImpl()` - declared at the bottom of the header file as `extern`.
This function is used by `TF_Send()` and others to write bytes to your UART (or other physical layer).
Presently, always a full frame is sent to this function.
A frame can be sent in it's entirety, or in multiple parts, depending on its size.
- If you wish to use timeouts, periodically call `TF_Tick()`. The calling period determines
the length of 1 tick. This is used to time-out the parser in case it gets stuck
in a bad state (such as receiving a partial frame) and can also time-out ID listeners.
@@ -83,6 +83,6 @@ keep it, renew it's timeout, or let some other listener handle the message.
You'll find various examples in the `demo/` folder. Each example has it's own Makefile,
read it to see what options are available.
The demos are written for Linux, using sockets and `clone()` for background processing.
The demos are written for Linux, some using sockets and `clone()` for background processing.
They try to simulate real TinyFrame behavior in an embedded system with asynchronous
Rx and Tx. If you can't run the demos, the source files are still good as examples.
+7 -3
View File
@@ -1,4 +1,6 @@
//
// TinyFrame configuration file.
//
// Rename to TF_Config.h
//
@@ -19,7 +21,7 @@
// | 1 | ? | ? | ? | ? | ... | ? | <- size (bytes)
// '-----+----+-----+------+------------+- - - -+------------'
// !!! BOTH SIDES MUST USE THE SAME SETTINGS !!!
// !!! BOTH PEERS MUST USE THE SAME SETTINGS !!!
// Adjust sizes as desired (1,2,4)
#define TF_ID_BYTES 1
@@ -47,10 +49,12 @@ typedef uint8_t TF_COUNT;
//----------------------------- PARAMETERS ----------------------------------
// Maximum send / receive payload size (static buffers size)
// Maximum received payload size (static buffer)
// Larger payloads will be rejected.
#define TF_MAX_PAYLOAD_RX 1024
#define TF_MAX_PAYLOAD_TX 1024
// Size of the sending buffer. Larger payloads will be split to pieces and sent
// in multiple calls to the write function. This can be lowered to reduce RAM usage.
#define TF_SENDBUF_LEN 128
// --- Listener counts - determine sizes of the static slot tables ---
+28
View File
@@ -0,0 +1,28 @@
#include "TinyFrame.h"
/**
* This is an example of integrating TinyFrame into the application.
*
* TF_WriteImpl() is required, the mutex functions are weak and can
* be removed if not used. They are called from all TF_Send/Respond functions.
*
* Also remember to periodically call TF_Tick() if you wish to use the
* listener timeout feature.
*/
void TF_WriteImpl(const uint8_t *buff, size_t len)
{
// send to UART
}
/** Claim the TX interface before composing and sending a frame */
void TF_ClaimTx(void)
{
// take mutex
}
/** Free the TX interface after composing and sending a frame */
void TF_ReleaseTx(void)
{
// release mutex
}
+169 -96
View File
@@ -1,16 +1,19 @@
//---------------------------------------------------------------------------
#include "TinyFrame.h"
#include <string.h>
//#include "demo/utils.h"
//---------------------------------------------------------------------------
// Compatibility with ESP8266 SDK
#ifdef ICACHE_FLASH_ATTR
#define _TF_FN ICACHE_FLASH_ATTR
#define _TF_FN ICACHE_FLASH_ATTR
#else
#define _TF_FN
#define _TF_FN
#endif
// Helper macros
#define TF_MAX(a, b) ((a)>(b)?(a):(b))
#define TF_MIN(a, b) ((a)<(b)?(a):(b))
enum TFState {
TFState_SOF = 0, //!< Wait for SOF
TFState_LEN, //!< Wait for Number Of Bytes
@@ -27,6 +30,7 @@ typedef struct _IdListener_struct_ {
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;
} IdListener;
typedef struct _TypeListener_struct_ {
@@ -73,29 +77,29 @@ static struct TinyFrameStruct {
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
uint8_t sendbuf[TF_SENDBUF_LEN];
} tf;
//region Checksums
#if TF_CKSUM_TYPE == TF_CKSUM_NONE
// NONE
#define CKSUM_RESET(cksum)
#define CKSUM_ADD(cksum, byte)
#define CKSUM_FINALIZE(cksum)
// NONE
#define CKSUM_RESET(cksum)
#define CKSUM_ADD(cksum, byte)
#define CKSUM_FINALIZE(cksum)
#elif TF_CKSUM_TYPE == TF_CKSUM_XOR
// ~XOR
#define CKSUM_RESET(cksum) do { (cksum) = 0; } while (0)
#define CKSUM_ADD(cksum, byte) do { (cksum) ^= (byte); } while(0)
#define CKSUM_FINALIZE(cksum) do { (cksum) = (TF_CKSUM)~cksum; } while(0)
// ~XOR
#define CKSUM_RESET(cksum) do { (cksum) = 0; } while (0)
#define CKSUM_ADD(cksum, byte) do { (cksum) ^= (byte); } while(0)
#define CKSUM_FINALIZE(cksum) do { (cksum) = (TF_CKSUM)~cksum; } while(0)
#elif TF_CKSUM_TYPE == TF_CKSUM_CRC16
/** CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */
static const uint16_t crc16_table[256] = {
/** CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */
static const uint16_t crc16_table[256] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
@@ -128,20 +132,20 @@ static struct TinyFrameStruct {
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
};
static inline uint16_t crc16_byte(uint16_t cksum, const uint8_t byte)
{
static inline uint16_t crc16_byte(uint16_t cksum, const uint8_t byte)
{
return (cksum >> 8) ^ crc16_table[(cksum ^ byte) & 0xff];
}
}
#define CKSUM_RESET(cksum) do { (cksum) = 0; } while (0)
#define CKSUM_ADD(cksum, byte) do { (cksum) = crc16_byte((cksum), (byte)); } while(0)
#define CKSUM_FINALIZE(cksum)
#define CKSUM_RESET(cksum) do { (cksum) = 0; } while (0)
#define CKSUM_ADD(cksum, byte) do { (cksum) = crc16_byte((cksum), (byte)); } while(0)
#define CKSUM_FINALIZE(cksum)
#elif TF_CKSUM_TYPE == TF_CKSUM_CRC32
static const uint32_t crc32_table[] = { /* CRC polynomial 0xedb88320 */
static const uint32_t crc32_table[] = { /* CRC polynomial 0xedb88320 */
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
@@ -185,16 +189,16 @@ static struct TinyFrameStruct {
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
};
static inline uint32_t crc32_byte(uint32_t cksum, const uint8_t byte)
{
static inline uint32_t crc32_byte(uint32_t cksum, const uint8_t byte)
{
return (crc32_table[((cksum) ^ ((uint8_t)byte)) & 0xff] ^ ((cksum) >> 8));
}
}
#define CKSUM_RESET(cksum) do { (cksum) = (TF_CKSUM)0xFFFFFFFF; } while (0)
#define CKSUM_ADD(cksum, byte) do { (cksum) = crc32_byte(cksum, byte); } while(0)
#define CKSUM_FINALIZE(cksum) do { (cksum) = (TF_CKSUM)~(cksum); } while(0)
#define CKSUM_RESET(cksum) do { (cksum) = (TF_CKSUM)0xFFFFFFFF; } while (0)
#define CKSUM_ADD(cksum, byte) do { (cksum) = crc32_byte(cksum, byte); } while(0)
#define CKSUM_FINALIZE(cksum) do { (cksum) = (TF_CKSUM)~(cksum); } while(0)
#endif
@@ -229,6 +233,7 @@ static void _TF_FN cleanup_id_listener(TF_COUNT i, IdListener *lst)
// Make user clean up their data - only if not NULL
if (lst->userdata != NULL) {
msg.userdata = lst->userdata;
msg.userdata2 = lst->userdata2;
msg.data = NULL; // this is a signal that the listener should clean up
lst->fn(&msg); // return value is ignored here - use TF_STAY or TF_CLOSE
}
@@ -277,6 +282,7 @@ bool _TF_FN TF_AddIdListener(TF_Msg *msg, TF_Listener cb, TF_TICKS timeout)
lst->fn = cb;
lst->id = msg->frame_id;
lst->userdata = msg->userdata;
lst->userdata2 = msg->userdata2;
lst->timeout_max = lst->timeout = timeout;
if (i >= tf.count_id_lst) {
tf.count_id_lst = (TF_COUNT) (i + 1);
@@ -399,8 +405,10 @@ static void _TF_FN TF_HandleReceivedMessage(void)
ilst = &tf.id_listeners[i];
if (ilst->fn && ilst->id == msg.frame_id) {
msg.userdata = ilst->userdata; // pass userdata pointer to the callback
msg.userdata2 = ilst->userdata2;
res = ilst->fn(&msg);
ilst->userdata = msg.userdata; // put it back (may have changed the pointer or set to NULL)
ilst->userdata2 = msg.userdata2; // put it back (may have changed the pointer or set to NULL)
if (res != TF_NEXT) {
if (res == TF_CLOSE) {
@@ -414,6 +422,7 @@ static void _TF_FN TF_HandleReceivedMessage(void)
}
}
msg.userdata = NULL;
msg.userdata2 = NULL;
// clean up for the following listeners that don't use userdata
// Type listeners
@@ -466,9 +475,9 @@ void _TF_FN TF_ResetParser(void)
static void _TF_FN TF_ParsBeginFrame(void) {
// Reset state vars
CKSUM_RESET(tf.cksum);
#if TF_USE_SOF_BYTE
#if TF_USE_SOF_BYTE
CKSUM_ADD(tf.cksum, TF_SOF_BYTE);
#endif
#endif
tf.discard_data = false;
@@ -489,11 +498,11 @@ void _TF_FN TF_AcceptChar(unsigned char c)
#define COLLECT_NUMBER(dest, type) dest = (type)(((dest) << 8) | c); \
if (++tf.rxi == sizeof(type))
#if !TF_USE_SOF_BYTE
#if !TF_USE_SOF_BYTE
if (tf.state == TFState_SOF) {
TF_ParsBeginFrame();
}
#endif
#endif
switch (tf.state) {
case TFState_SOF:
@@ -523,15 +532,15 @@ void _TF_FN TF_AcceptChar(unsigned char c)
case TFState_TYPE:
CKSUM_ADD(tf.cksum, c);
COLLECT_NUMBER(tf.type, TF_TYPE) {
#if TF_CKSUM_TYPE == TF_CKSUM_NONE
#if TF_CKSUM_TYPE == TF_CKSUM_NONE
tf.state = TFState_DATA;
tf.rxi = 0;
#else
#else
// enter HEAD_CKSUM state
tf.state = TFState_HEAD_CKSUM;
tf.rxi = 0;
tf.ref_cksum = 0;
#endif
#endif
}
break;
@@ -573,16 +582,16 @@ void _TF_FN TF_AcceptChar(unsigned char c)
}
if (tf.rxi == tf.len) {
#if TF_CKSUM_TYPE == TF_CKSUM_NONE
#if TF_CKSUM_TYPE == TF_CKSUM_NONE
// All done
TF_HandleReceivedMessage();
TF_ResetParser();
#else
#else
// Enter DATA_CKSUM state
tf.state = TFState_DATA_CKSUM;
tf.rxi = 0;
tf.ref_cksum = 0;
#endif
#endif
}
break;
@@ -606,6 +615,18 @@ void _TF_FN TF_AcceptChar(unsigned char c)
}
}
// Helper macros for the Compose functions
// use variables: si - signed int, b - byte, outbuf - target buffer, pos - count of bytes in buffer
#define WRITENUM_BASE(type, num, xtra) \
for (si = sizeof(type)-1; si>=0; si--) { \
b = (uint8_t)((num) >> (si*8) & 0xFF); \
outbuff[pos++] = b; \
xtra; \
}
#define _NOOP()
#define WRITENUM(type, num) WRITENUM_BASE(type, num, _NOOP())
#define WRITENUM_CKSUM(type, num) WRITENUM_BASE(type, num, CKSUM_ADD(cksum, b))
/**
* Compose a frame (used internally by TF_Send and TF_Respond).
* The frame can be sent using TF_WriteImpl(), or received by TF_Accept()
@@ -613,19 +634,16 @@ void _TF_FN TF_AcceptChar(unsigned char c)
* @param outbuff - buffer to store the result in
* @param msgid - message ID is stored here, if not NULL
* @param type - message type
* @param data - data buffer
* @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, 0 on failure
*/
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,
static inline size_t _TF_FN TF_ComposeHead(uint8_t *outbuff, TF_ID *id_ptr,
TF_TYPE type, TF_LEN data_len,
TF_ID explicit_id, bool use_expl_id)
{
char si = 0; // signed small int
TF_LEN i = 0;
int8_t si = 0; // signed small int
uint8_t b = 0;
TF_ID id = 0;
TF_CKSUM cksum = 0;
@@ -635,11 +653,6 @@ static inline size_t _TF_FN TF_Compose(uint8_t *outbuff, TF_ID *id_ptr,
CKSUM_RESET(cksum);
// sanitize len
if (data_len > TF_MAX_PAYLOAD_TX) {
return 0;
}
// Gen ID
if (use_expl_id) {
id = explicit_id;
@@ -651,62 +664,127 @@ static inline size_t _TF_FN TF_Compose(uint8_t *outbuff, TF_ID *id_ptr,
}
}
if (id_ptr != NULL)
*id_ptr = id;
// DRY helper for writing a multi-byte variable to the buffer
#define WRITENUM_BASE(type, num, xtra) \
for (si = sizeof(type)-1; si>=0; si--) { \
b = (uint8_t)(num >> (si*8) & 0xFF); \
outbuff[pos++] = b; \
xtra; \
}
#define _NOOP()
#define WRITENUM(type, num) WRITENUM_BASE(type, num, _NOOP())
#define WRITENUM_CKSUM(type, num) WRITENUM_BASE(type, num, CKSUM_ADD(cksum, b))
if (id_ptr != NULL) *id_ptr = id;
// --- Start ---
CKSUM_RESET(cksum);
#if TF_USE_SOF_BYTE
#if TF_USE_SOF_BYTE
outbuff[pos++] = TF_SOF_BYTE;
CKSUM_ADD(cksum, TF_SOF_BYTE);
#endif
#endif
WRITENUM_CKSUM(TF_ID, id);
WRITENUM_CKSUM(TF_LEN, data_len);
WRITENUM_CKSUM(TF_TYPE, type);
#if TF_CKSUM_TYPE != TF_CKSUM_NONE
#if TF_CKSUM_TYPE != TF_CKSUM_NONE
CKSUM_FINALIZE(cksum);
WRITENUM(TF_CKSUM, cksum);
#endif
#endif
// --- payload begin ---
if (data_len > 0) {
CKSUM_RESET(cksum);
return pos;
}
/**
* Compose a frame (used internally by TF_Send and TF_Respond).
* The frame can be sent using TF_WriteImpl(), or received by TF_Accept()
*
* @param outbuff - buffer to store the result in
* @param data - data buffer
* @param data_len - data buffer len
* @param cksum - checksum variable, used for all calls to TF_ComposeBody. Must be reset before first use! (CKSUM_RESET(cksum);)
* @return nr of bytes in outbuff used
*/
static size_t _TF_FN TF_ComposeBody(uint8_t *outbuff, const uint8_t *data, TF_LEN data_len, TF_CKSUM *cksum)
{
TF_LEN i = 0;
uint8_t b = 0;
size_t pos = 0;
// DATA
for (i = 0; i < data_len; i++) {
b = data[i];
outbuff[pos++] = b;
CKSUM_ADD(cksum, b);
}
#if TF_CKSUM_TYPE != TF_CKSUM_NONE
CKSUM_FINALIZE(cksum);
WRITENUM(TF_CKSUM, cksum);
#endif
CKSUM_ADD(*cksum, b);
}
return pos;
}
/**
* Finalize a frame
*
* @param outbuff - buffer to store the result in
* @param cksum - checksum variable used for the body
* @return nr of bytes in outbuff used
*/
static size_t _TF_FN TF_ComposeTail(uint8_t *outbuff, TF_CKSUM *cksum)
{
int8_t si = 0; // signed small int
uint8_t b = 0;
size_t pos = 0;
#if TF_CKSUM_TYPE != TF_CKSUM_NONE
CKSUM_FINALIZE(*cksum);
WRITENUM(TF_CKSUM, *cksum);
#endif
return pos;
}
// send with listener
static bool _TF_FN TF_SendFrame(TF_Msg *msg, TF_Listener listener, TF_TICKS timeout)
{
size_t len = 0;
size_t remain = 0;
size_t sent = 0;
TF_CKSUM cksum = 0;
TF_ClaimTx();
len = TF_ComposeHead(tf.sendbuf,
&msg->frame_id,
msg->type,
msg->len,
msg->frame_id,
msg->is_response);
if (listener) TF_AddIdListener(msg, listener, timeout);
CKSUM_RESET(cksum);
remain = msg->len;
while (remain > 0) {
size_t chunk = TF_MIN(TF_SENDBUF_LEN - len, remain);
len += TF_ComposeBody(tf.sendbuf+len, msg->data+sent, (TF_LEN) chunk, &cksum);
remain -= chunk;
sent += chunk;
// Flush if the buffer is full and we have more to send
if (remain > 0 && len == TF_SENDBUF_LEN) {
TF_WriteImpl((const uint8_t *) tf.sendbuf, len);
len = 0;
}
}
// Flush if checksum wouldn't fit in the buffer
if (TF_SENDBUF_LEN - len < sizeof(TF_CKSUM)) {
TF_WriteImpl((const uint8_t *) tf.sendbuf, len);
len = 0;
}
// Add checksum, flush what remains to be sent
len += TF_ComposeTail(tf.sendbuf+len, &cksum);
TF_WriteImpl((const uint8_t *) tf.sendbuf, len);
TF_ReleaseTx();
return true;
}
// send without listener
bool _TF_FN TF_Send(TF_Msg *msg)
{
return TF_Query(msg, NULL, 0);
return TF_SendFrame(msg, NULL, 0);
}
// send without listener and struct
@@ -729,27 +807,13 @@ bool _TF_FN TF_QuerySimple(TF_TYPE type, const uint8_t *data, TF_LEN len, TF_Lis
msg.data = data;
msg.len = len;
msg.userdata = userdata;
return TF_Query(&msg, listener, timeout);
return TF_SendFrame(&msg, listener, timeout);
}
// send with listener
bool _TF_FN TF_Query(TF_Msg *msg, TF_Listener listener, TF_TICKS timeout)
{
size_t len;
len = TF_Compose(tf.sendbuf,
&msg->frame_id,
msg->type,
msg->data,
msg->len,
msg->frame_id,
msg->is_response);
if (len == 0) return false;
if (listener) TF_AddIdListener(msg, listener, timeout);
TF_WriteImpl((const uint8_t *) tf.sendbuf, len);
return true;
return TF_SendFrame(msg, listener, timeout);
}
// Like TF_Send, but with explicit frame ID
@@ -797,3 +861,12 @@ void _TF_FN TF_Tick(void)
}
}
void __attribute__((weak)) TF_ClaimTx(void)
{
// do nothing
}
void __attribute__((weak)) TF_ReleaseTx(void)
{
// do nothing
}
+19
View File
@@ -1,6 +1,17 @@
#ifndef TinyFrameH
#define TinyFrameH
/**
* TinyFrame protocol library
*
* (c) Ondřej Hruška 2017, MIT License
* no liability/warranty, free for any use, must retain this notice & license
*
* Upstream URL: https://github.com/MightyPork/TinyFrame
*/
#define TF_VERSION "1.2.0"
//---------------------------------------------------------------------------
#include <stdint.h> // for uint8_t etc
#include <stdbool.h> // for bool
@@ -105,6 +116,7 @@ typedef struct _TF_MSG_STRUCT_ {
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;
/**
@@ -118,6 +130,7 @@ static inline void TF_ClearMsg(TF_Msg *msg)
msg->data = NULL;
msg->len = 0;
msg->userdata = NULL;
msg->userdata2 = NULL;
}
/**
@@ -269,4 +282,10 @@ extern void TF_WriteImpl(const uint8_t *buff, size_t len);
*/
void TF_Tick(void);
/** Claim the TX interface before composing and sending a frame */
extern void TF_ClaimTx(void);
/** Free the TX interface after composing and sending a frame */
extern void TF_ReleaseTx(void);
#endif
+25
View File
@@ -0,0 +1,25 @@
//
// Created by MightyPork on 2017/10/15.
//
#ifndef TF_CONFIG_H
#define TF_CONFIG_H
#include <stdint.h>
#define TF_ID_BYTES 1
#define TF_LEN_BYTES 2
#define TF_TYPE_BYTES 1
#define TF_CKSUM_TYPE TF_CKSUM_CRC16
#define TF_USE_SOF_BYTE 1
#define TF_SOF_BYTE 0x01
typedef uint16_t TF_TICKS;
typedef uint8_t TF_COUNT;
#define TF_MAX_PAYLOAD_RX 10240
#define TF_SENDBUF_LEN 64
#define TF_MAX_ID_LST 10
#define TF_MAX_TYPE_LST 10
#define TF_MAX_GEN_LST 5
#define TF_PARSER_TIMEOUT_TICKS 10
#endif //TF_CONFIG_H
+297
View File
@@ -0,0 +1,297 @@
#include <stdio.h>
#include <string.h>
#include "../../TinyFrame.h"
#include "../utils.h"
extern const char *romeo;
/**
* 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, size_t len)
{
printf("--------------------\n");
printf("\033[32mTF_WriteImpl - sending frame:\033[0m\n");
dumpFrame(buff, len);
// Send it back as if we received it
TF_Accept(buff, len);
}
/** An example listener function */
TF_Result myListener(TF_Msg *msg)
{
dumpFrameInfo(msg);
if (strcmp(msg->data, romeo) == 0) {
printf("FILE TRANSFERRED OK!\r\n");
} else {
printf("FAIL!!!!\r\n");
}
return TF_STAY;
}
void main(void)
{
TF_Msg msg;
// Set up the TinyFrame library
TF_Init(TF_MASTER); // 1 = master, 0 = slave
TF_AddGenericListener(myListener);
printf("------ Simulate sending a LOOONG message --------\n");
TF_ClearMsg(&msg);
msg.type = 0x22;
msg.data = (pu8)romeo;
msg.len = strlen(romeo);
TF_Send(&msg);
}
const char *romeo ="THE TRAGEDY OF ROMEO AND JULIET\n"
"\n"
"by William Shakespeare\n"
"\n"
"\n"
"\n"
"Dramatis Personae\n"
"\n"
" Chorus.\n"
"\n"
"\n"
" Escalus, Prince of Verona.\n"
"\n"
" Paris, a young Count, kinsman to the Prince.\n"
"\n"
" Montague, heads of two houses at variance with each other.\n"
"\n"
" Capulet, heads of two houses at variance with each other.\n"
"\n"
" An old Man, of the Capulet family.\n"
"\n"
" Romeo, son to Montague.\n"
"\n"
" Tybalt, nephew to Lady Capulet.\n"
"\n"
" Mercutio, kinsman to the Prince and friend to Romeo.\n"
"\n"
" Benvolio, nephew to Montague, and friend to Romeo\n"
"\n"
" Tybalt, nephew to Lady Capulet.\n"
"\n"
" Friar Laurence, Franciscan.\n"
"\n"
" Friar John, Franciscan.\n"
"\n"
" Balthasar, servant to Romeo.\n"
"\n"
" Abram, servant to Montague.\n"
"\n"
" Sampson, servant to Capulet.\n"
"\n"
" Gregory, servant to Capulet.\n"
"\n"
" Peter, servant to Juliet's nurse.\n"
"\n"
" An Apothecary.\n"
"\n"
" Three Musicians.\n"
"\n"
" An Officer.\n"
"\n"
"\n"
" Lady Montague, wife to Montague.\n"
"\n"
" Lady Capulet, wife to Capulet.\n"
"\n"
" Juliet, daughter to Capulet.\n"
"\n"
" Nurse to Juliet.\n"
"\n"
"\n"
" Citizens of Verona; Gentlemen and Gentlewomen of both houses;\n"
" Maskers, Torchbearers, Pages, Guards, Watchmen, Servants, and\n"
" Attendants.\n"
"\n"
" SCENE.--Verona; Mantua.\n"
"\n"
"\n"
"\n"
" THE PROLOGUE\n"
"\n"
" Enter Chorus.\n"
"\n"
"\n"
" Chor. Two households, both alike in dignity,\n"
" In fair Verona, where we lay our scene,\n"
" From ancient grudge break to new mutiny,\n"
" Where civil blood makes civil hands unclean.\n"
" From forth the fatal loins of these two foes\n"
" A pair of star-cross'd lovers take their life;\n"
" Whose misadventur'd piteous overthrows\n"
" Doth with their death bury their parents' strife.\n"
" The fearful passage of their death-mark'd love,\n"
" And the continuance of their parents' rage,\n"
" Which, but their children's end, naught could remove,\n"
" Is now the two hours' traffic of our stage;\n"
" The which if you with patient ears attend,\n"
" What here shall miss, our toil shall strive to mend.\n"
" [Exit.]\n"
"\n"
"\n"
"\n"
"\n"
"ACT I. Scene I.\n"
"Verona. A public place.\n"
"\n"
"Enter Sampson and Gregory (with swords and bucklers) of the house\n"
"of Capulet.\n"
"\n"
"\n"
" Samp. Gregory, on my word, we'll not carry coals.\n"
"\n"
" Greg. No, for then we should be colliers.\n"
"\n"
" Samp. I mean, an we be in choler, we'll draw.\n"
"\n"
" Greg. Ay, while you live, draw your neck out of collar.\n"
"\n"
" Samp. I strike quickly, being moved.\n"
"\n"
" Greg. But thou art not quickly moved to strike.\n"
"\n"
" Samp. A dog of the house of Montague moves me.\n"
"\n"
" Greg. To move is to stir, and to be valiant is to stand.\n"
" Therefore, if thou art moved, thou runn'st away.\n"
"\n"
" Samp. A dog of that house shall move me to stand. I will take\n"
" the wall of any man or maid of Montague's.\n"
"\n"
" Greg. That shows thee a weak slave; for the weakest goes to the\n"
" wall.\n"
"\n"
" Samp. 'Tis true; and therefore women, being the weaker vessels,\n"
" are ever thrust to the wall. Therefore I will push Montague's men\n"
" from the wall and thrust his maids to the wall.\n"
"\n"
" Greg. The quarrel is between our masters and us their men.\n"
"\n"
" Samp. 'Tis all one. I will show myself a tyrant. When I have\n"
" fought with the men, I will be cruel with the maids- I will cut off\n"
" their heads.\n"
"\n"
" Greg. The heads of the maids?\n"
"\n"
" Samp. Ay, the heads of the maids, or their maidenheads.\n"
" Take it in what sense thou wilt.\n"
"\n"
" Greg. They must take it in sense that feel it.\n"
"\n"
" Samp. Me they shall feel while I am able to stand; and 'tis known I\n"
" am a pretty piece of flesh.\n"
"\n"
" Greg. 'Tis well thou art not fish; if thou hadst, thou hadst\n"
" been poor-John. Draw thy tool! Here comes two of the house of\n"
" Montagues.\n"
"\n"
" Enter two other Servingmen [Abram and Balthasar].\n"
"\n"
"\n"
" Samp. My naked weapon is out. Quarrel! I will back thee.\n"
"\n"
" Greg. How? turn thy back and run?\n"
"\n"
" Samp. Fear me not.\n"
"\n"
" Greg. No, marry. I fear thee!\n"
"\n"
" Samp. Let us take the law of our sides; let them begin.\n"
"\n"
" Greg. I will frown as I pass by, and let them take it as they list.\n"
"\n"
" Samp. Nay, as they dare. I will bite my thumb at them; which is\n"
" disgrace to them, if they bear it.\n"
"\n"
" Abr. Do you bite your thumb at us, sir?\n"
"\n"
" Samp. I do bite my thumb, sir.\n"
"\n"
" Abr. Do you bite your thumb at us, sir?\n"
"\n"
" Samp. [aside to Gregory] Is the law of our side if I say ay?\n"
"\n"
" Greg. [aside to Sampson] No.\n"
"\n"
" Samp. No, sir, I do not bite my thumb at you, sir; but I bite my\n"
" thumb, sir.\n"
"\n"
" Greg. Do you quarrel, sir?\n"
"\n"
" Abr. Quarrel, sir? No, sir.\n"
"\n"
" Samp. But if you do, sir, am for you. I serve as good a man as\n"
" you.\n"
"\n"
" Abr. No better.\n"
"\n"
" Samp. Well, sir.\n"
"\n"
" Enter Benvolio.\n"
"\n"
"\n"
" Greg. [aside to Sampson] Say 'better.' Here comes one of my\n"
" master's kinsmen.\n"
"\n"
" Samp. Yes, better, sir.\n"
"\n"
" Abr. You lie.\n"
"\n"
" Samp. Draw, if you be men. Gregory, remember thy swashing blow.\n"
" They fight.\n"
"\n"
" Ben. Part, fools! [Beats down their swords.]\n"
" Put up your swords. You know not what you do.\n"
"\n"
" Enter Tybalt.\n"
"\n"
"\n"
" Tyb. What, art thou drawn among these heartless hinds?\n"
" Turn thee Benvolio! look upon thy death.\n"
"\n"
" Ben. I do but keep the peace. Put up thy sword,\n"
" Or manage it to part these men with me.\n"
"\n"
" Tyb. What, drawn, and talk of peace? I hate the word\n"
" As I hate hell, all Montagues, and thee.\n"
" Have at thee, coward! They fight.\n"
"\n"
" Enter an officer, and three or four Citizens with clubs or\n"
" partisans.\n"
"\n"
"\n"
" Officer. Clubs, bills, and partisans! Strike! beat them down!\n"
"\n"
" Citizens. Down with the Capulets! Down with the Montagues!\n"
"\n"
" Enter Old Capulet in his gown, and his Wife.\n"
"\n"
"\n"
" Cap. What noise is this? Give me my long sword, ho!\n"
"\n"
" Wife. A crutch, a crutch! Why call you for a sword?\n"
"\n"
" Cap. My sword, I say! Old Montague is come\n"
" And flourishes his blade in spite of me.\n"
"\n"
" Enter Old Montague and his Wife.\n"
"\n"
"\n"
" Mon. Thou villain Capulet!- Hold me not, let me go.\n"
"\n"
" M. Wife. Thou shalt not stir one foot to seek a foe.\n"
"\n"
" Enter Prince Escalus, with his Train.\n"
"\n"
"\n"
"END OF FILE\n";
+11
View File
@@ -0,0 +1,11 @@
CFILES=../utils.c ../../TinyFrame.c
INCLDIRS=-I. -I.. -I../..
CFLAGS=-O0 -ggdb --std=gnu99 -Wno-main -Wall -Wextra $(CFILES) $(INCLDIRS)
run: test.bin
./test.bin
build: test.bin
test.bin: test.c $(CFILES)
gcc test.c $(CFLAGS) -o test.bin
@@ -16,7 +16,7 @@
typedef uint16_t TF_TICKS;
typedef uint8_t TF_COUNT;
#define TF_MAX_PAYLOAD_RX 1024
#define TF_MAX_PAYLOAD_TX 1024
#define TF_SENDBUF_LEN 1024
#define TF_MAX_ID_LST 10
#define TF_MAX_TYPE_LST 10
#define TF_MAX_GEN_LST 5
@@ -16,7 +16,7 @@
typedef uint16_t TF_TICKS;
typedef uint8_t TF_COUNT;
#define TF_MAX_PAYLOAD_RX 1024
#define TF_MAX_PAYLOAD_TX 1024
#define TF_SENDBUF_LEN 1024
#define TF_MAX_ID_LST 10
#define TF_MAX_TYPE_LST 10
#define TF_MAX_GEN_LST 5