This page provides step-by-step examples for using TinyProto in C, C++, and Python.
Overview
A typical TinyProto application follows this pattern:
- Allocate a protocol buffer (statically or dynamically)
- Initialize the protocol with your configuration and callbacks
- Main loop:
- Feed received bytes into the protocol (RX path)
- Get bytes from the protocol and send them (TX path)
- Send application data when needed
- Close the protocol when done
C API
ABM Mode — Peer-to-Peer
#include <stdio.h>
static void on_frame_received(void *udata, uint8_t addr, uint8_t *buf, int len)
{
printf("Received %d bytes from addr %d\n", len, addr);
}
static void on_connect(void *udata, uint8_t addr, bool connected)
{
printf("Peer %d %s\n", addr, connected ? "connected" : "disconnected");
}
int main(void)
{
printf("Init failed\n");
return -1;
}
while (1) {
uint8_t rx_buf[128];
int rx_len = serial_read(rx_buf, sizeof(rx_buf));
if (rx_len > 0) {
}
uint8_t tx_buf[128];
if (tx_len > 0) {
serial_write(tx_buf, tx_len);
}
}
return 0;
}
NRM Mode — Primary Station
NRM Mode — Secondary Station
UI Frames — Connectionless Data
UI (Unnumbered Information) frames can be sent without an established connection. They are not acknowledged and do not use sequence numbers.
C++ API
Static Buffer (No Heap)
Use tinyproto::Fd<N> for systems without dynamic allocation:
Dynamic Buffer
Use tinyproto::FdD on systems with heap allocation:
proto.
write(
"Hello World", 12);
Python API
import tinyproto
fd.crc = tinyproto.CRC_16
fd.mtu = 64
fd.window_size = 4
fd.on_read = lambda addr, data: print(f"Received from {addr}: {data.hex()}")
fd.on_connect_event = lambda addr, connected: print(f"Peer {addr}: {'up' if connected else 'down'}")
fd.begin()
fd.end()
For NRM mode in Python:
fd.mode = tinyproto.MODE_NRM
fd.addr = tinyproto.PRIMARY_ADDR
fd.peers_count = 3
fd.begin()
fd.register_peer(1)
fd.register_peer(2)
fd.send_to(1, b"Hello secondary 1")
fd.mode = tinyproto.MODE_NRM
fd.addr = 1
fd.begin()
fd.send(b"Hello primary")