{"id":16237575,"url":"https://github.com/lexus2k/tinyproto","last_synced_at":"2026-04-28T19:01:26.894Z","repository":{"id":37334048,"uuid":"53769163","full_name":"lexus2k/tinyproto","owner":"lexus2k","description":"Tiny Software Protocol for communication over UART, SPI, etc","archived":false,"fork":false,"pushed_at":"2026-04-03T18:40:43.000Z","size":5861,"stargazers_count":267,"open_issues_count":10,"forks_count":57,"subscribers_count":12,"default_branch":"master","last_synced_at":"2026-04-03T20:55:26.311Z","etag":null,"topics":["arduino","atmega","avr","communication","esp32","hdlc","hdlc-like","microcontroller","protocol","protocol-library","rfc1662","serial","serialport","spi","spi-protocol","win32","windows-desktop"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lexus2k.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.md","dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":"lexus2k","tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":["https://www.bitcoinqrcodemaker.com/?style=ethereum\u0026address=0x20608A71470Bc84a3232621819f578Fb9C02A460","https://www.bitcoinqrcodemaker.com/?style=bitcoin\u0026address=3CtUY6Ag2zsvm1JyqeeKeK8kjdG7Tnjr5W"]}},"created_at":"2016-03-13T05:28:16.000Z","updated_at":"2026-04-03T18:40:47.000Z","dependencies_parsed_at":"2024-10-25T17:24:02.834Z","dependency_job_id":"1201ea71-5a57-4c0d-a250-36bf02796315","html_url":"https://github.com/lexus2k/tinyproto","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/lexus2k/tinyproto","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lexus2k%2Ftinyproto","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lexus2k%2Ftinyproto/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lexus2k%2Ftinyproto/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lexus2k%2Ftinyproto/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lexus2k","download_url":"https://codeload.github.com/lexus2k/tinyproto/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lexus2k%2Ftinyproto/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32394478,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T14:34:11.604Z","status":"ssl_error","status_checked_at":"2026-04-28T14:32:37.009Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arduino","atmega","avr","communication","esp32","hdlc","hdlc-like","microcontroller","protocol","protocol-library","rfc1662","serial","serialport","spi","spi-protocol","win32","windows-desktop"],"created_at":"2024-10-10T13:36:11.215Z","updated_at":"2026-04-28T19:01:26.888Z","avatar_url":"https://github.com/lexus2k.png","language":"C++","funding_links":["https://ko-fi.com/lexus2k","https://www.bitcoinqrcodemaker.com/?style=ethereum\u0026address=0x20608A71470Bc84a3232621819f578Fb9C02A460","https://www.bitcoinqrcodemaker.com/?style=bitcoin\u0026address=3CtUY6Ag2zsvm1JyqeeKeK8kjdG7Tnjr5W"],"categories":["C++"],"sub_categories":[],"readme":"\n![Tiny Protocol](.travis/tinylogo.svg)\u003cbr\u003e\n![Github actions](https://github.com/lexus2k/tinyproto/actions/workflows/main.yml/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/lexus2k/tinyproto/badge.svg?branch=master)](https://coveralls.io/github/lexus2k/tinyproto?branch=master)\n[![Documentation](https://codedocs.xyz/lexus2k/tinyproto.svg)](https://codedocs.xyz/lexus2k/tinyproto/)\n![License](https://img.shields.io/badge/license-GPLv3-blue)\n![License](https://img.shields.io/badge/license-Commercial-blue)\n\n---\n\n**TinyProto** is a lightweight, portable HDLC-based data link layer protocol for embedded systems and microcontrollers. Communicate reliably over UART, SPI, I2C or any byte stream — with automatic retransmission, CRC error detection, and zero dynamic memory allocation.\n\n---\n\n## Table of Contents\n\n- [Introduction](#introduction)\n- [Protocol Modes](#protocol-modes)\n- [Architecture](#architecture)\n- [Key Features](#key-features)\n- [Supported Platforms](#supported-platforms)\n- [Quick Start](#quick-start)\n  - [C API](#c-api)\n  - [C++ API](#c-api-1)\n  - [Python](#python)\n- [Building](#building)\n- [Testing](#testing)\n- [Installation](#installation)\n- [Tools](#tools)\n- [API Reference](#api-reference)\n- [License](#license)\n\n## Introduction\n\nTinyProto is a **Layer 2 (Data Link)** protocol implementation based on [RFC 1662](https://tools.ietf.org/html/rfc1662) and the [HDLC](https://en.wikipedia.org/wiki/High-Level_Data_Link_Control) specification. It provides reliable, framed communication between two or more devices over any byte-oriented transport (UART, SPI, I2C, USB CDC, TCP sockets, etc.).\n\nThe library is designed for resource-constrained environments — from 8-bit AVR microcontrollers with just 60 bytes of SRAM to full Linux/Windows desktop systems. All memory is statically allocated; no `malloc` is ever called.\n\nTinyProto is **not** an application-layer protocol. It can be used as a transport for higher-level protocols such as Protocol Buffers, MessagePack, JSON, or any custom framing you need.\n\n## Protocol Modes\n\nTinyProto supports three protocol layers, from simplest to most capable:\n\n| Layer | API Prefix | Description | Use Case |\n|-------|-----------|-------------|----------|\n| **Light** | `tiny_light_*` | SLIP-like framing with optional CRC. No acknowledgments. | Simple, low-overhead streaming |\n| **HDLC** | `hdlc_*` | Low-level HDLC framing (flag bytes, byte stuffing, CRC). | Custom protocol building blocks |\n| **Full-Duplex (FD)** | `tiny_fd_*` | Complete HDLC implementation with sliding window, ACK/NAK, retransmission | Reliable bidirectional communication |\n\n### Full-Duplex Modes (FD)\n\nThe FD protocol supports two HDLC operating modes:\n\n#### ABM — Asynchronous Balanced Mode (Peer-to-Peer)\n\n```\n┌────────────┐                        ┌────────────┐\n│  Device A  │ ◄──── UART/SPI ──────► │  Device B  │\n│   (peer)   │      bidirectional     │   (peer)   │\n└────────────┘                        └────────────┘\n```\n\n- Both devices are **equal peers** — either side can initiate communication\n- Connection established via **SABM/UA** exchange\n- Supports hot plug/unplug with automatic reconnection\n- Ideal for: point-to-point links between two MCUs, MCU ↔ PC communication\n\n#### NRM — Normal Response Mode (Multi-drop / RS-485)\n\n```\n┌────────────┐      ┌────────────┐      ┌────────────┐\n│  Primary   │─────►│ Secondary1 │      │ Secondary2 │\n│  (master)  │◄─────│  addr = 1  │      │  addr = 2  │\n│            │─────────────────────────►│            │\n│            │◄─────────────────────────│            │\n└────────────┘      └────────────┘      └────────────┘\n```\n\n- **One primary** station controls communication with **multiple secondaries**\n- Primary polls each secondary in round-robin order using P/F (Poll/Final) bit\n- Secondaries only transmit when polled\n- Connection established via **SNRM/UA** exchange\n- Supports full sliding window for each secondary (up to 7 outstanding frames)\n- Ideal for: RS-485 buses, multi-drop serial networks, sensor networks\n\n### Frame Types\n\nTinyProto implements all standard HDLC frame types:\n\n| Frame | Type | Description |\n|-------|------|-------------|\n| **I** | Information | Carries user data with sequence numbers |\n| **RR** | Supervisory | Receiver Ready — acknowledges received frames |\n| **RNR** | Supervisory | Receiver Not Ready — flow control |\n| **REJ** | Supervisory | Reject — requests retransmission from sequence N |\n| **SREJ** | Supervisory | Selective Reject — requests retransmission of specific frame |\n| **SABM** | Unnumbered | Set ABM — initiates peer-to-peer connection |\n| **SNRM** | Unnumbered | Set NRM — initiates primary/secondary connection |\n| **DISC** | Unnumbered | Disconnect — terminates connection |\n| **UA** | Unnumbered | Unnumbered Acknowledge — confirms mode setting |\n| **DM** | Unnumbered | Disconnected Mode — rejects commands when disconnected |\n| **FRMR** | Unnumbered | Frame Reject — reports protocol errors |\n| **UI** | Unnumbered | Unnumbered Information — connectionless data |\n| **RSET** | Unnumbered | Reset — resets sequence counters |\n\n## Architecture\n\n```\n┌─────────────────────────────────────────────────┐\n│                   Application                   │\n├──────────────┬──────────────┬───────────────────┤\n│  C++ API     │   C API      │   Python API      │\n│  IFd / Hdlc  │  tiny_fd_*   │   tinyproto.*     │\n│  Light       │  hdlc_*      │                   │\n├──────────────┴──────────────┴───────────────────┤\n│            Full-Duplex Protocol (FD)            │\n│    ┌─────────────┬────────────┬───────────┐     │\n│    │ I-frame     │  S-frame   │  U-frame  │     │\n│    │ queue       │  handler   │  handler  │     │\n│    └─────────────┴────────────┴───────────┘     │\n├─────────────────────────────────────────────────┤\n│             HDLC Low-Level Framing              │\n│          (byte stuffing, CRC, flags)            │\n├─────────────────────────────────────────────────┤\n│           Hardware Abstraction Layer            │\n│         (timers, mutexes, serial I/O)           │\n├─────────────────────────────────────────────────┤\n│     UART  │  SPI  │  I2C  │  USB  │  TCP  │ ...│\n└─────────────────────────────────────────────────┘\n```\n\n## Key Features\n\n- **Reliable Delivery** — Sliding window (1–7 frames), automatic retransmission, REJ and SREJ recovery\n- **Error Detection** — 8-bit checksum, FCS-16 (CCITT), or FCS-32 (CCITT)\n- **Two HDLC Modes** — ABM (peer-to-peer) and NRM (primary/secondary multi-drop)\n- **Hot Plug/Unplug** — Automatic connection recovery in ABM mode\n- **Zero Dynamic Allocation** — All buffers are statically sized; fully deterministic memory usage\n- **Tiny Footprint** — From 60 bytes SRAM, 1.3 KiB flash (features are compile-time configurable)\n- **Large Frames** — Payload up to 32 KiB (configurable)\n- **Full Logging** — Built-in protocol debug logging with CSV export\n- **Multi-Language** — C, C++, and Python APIs\n- **Portable** — Works on any platform with a C99 compiler\n\n## Supported Platforms\n\nTinyProto runs anywhere a C99/C++11 compiler is available:\n\n| Platform | MCU Examples | Transport |\n|----------|-------------|-----------|\n| **Arduino** | Uno, Mega, Zero, Due, Nano | UART, SPI |\n| **ESP32** | ESP32, ESP32-S2, ESP32-C3 | UART, SPI |\n| **ARM Cortex** | STM32, nRF52, Teensy, SAMD | UART, SPI, I2C |\n| **AVR** | ATmega328, ATmega2560 | UART |\n| **Linux** | Any | UART, TCP, pipes |\n| **Windows** | Any | COM ports, TCP |\n| **RISC-V** | ESP32-C3, GD32V | UART, SPI |\n\n### Custom Platform Support\n\nIf your platform isn't listed, implement the HAL abstraction (timing + mutex functions):\n\n1. Add `TINY_CUSTOM_PLATFORM` to your compiler defines\n2. Implement HAL functions and call `tiny_hal_init()`\n3. Optionally add `CONFIG_TINYHAL_THREAD_SUPPORT` for multi-threaded environments\n\nSee [hal/linux/linux_hal.inl](src/hal/linux/linux_hal.inl) and [hal/esp32/esp32_hal.inl](src/hal/esp32/esp32_hal.inl) for reference implementations, or use the template at [tools/hal_template_functions/platform_hal.c](tools/hal_template_functions/platform_hal.c).\n\n## Quick Start\n\n### C API\n\n**ABM mode (peer-to-peer):**\n\n```c\n#include \"proto/fd/tiny_fd.h\"\n\n// Callback when a complete message is received\nvoid on_frame_received(void *udata, uint8_t addr, uint8_t *buf, int len)\n{\n    printf(\"Received %d bytes\\n\", len);\n}\n\n// Allocate protocol buffer (use tiny_fd_buffer_size_by_mtu() to calculate)\nuint8_t buffer[tiny_fd_buffer_size_by_mtu(64, 4)];\n\ntiny_fd_handle_t handle;\ntiny_fd_init_t init = {\n    .pdata        = NULL,\n    .on_read_cb   = on_frame_received,\n    .buffer       = buffer,\n    .buffer_size  = sizeof(buffer),\n    .window_frames = 4,\n    .send_timeout  = 1000,\n    .retry_timeout = 200,\n    .retries       = 3,\n    .crc_type      = HDLC_CRC_16,\n    .mode          = TINY_FD_MODE_ABM,\n};\n\ntiny_fd_init(\u0026handle, \u0026init);\n\n// In your main loop:\n// 1. Feed received bytes to the protocol\ntiny_fd_on_rx_data(handle, rx_bytes, rx_len);\n\n// 2. Get bytes to transmit\nuint8_t tx_buf[64];\nint tx_len = tiny_fd_get_tx_data(handle, tx_buf, sizeof(tx_buf), 0);\nif (tx_len \u003e 0) {\n    serial_write(tx_buf, tx_len);\n}\n\n// 3. Send application data\ntiny_fd_send_packet(handle, \"Hello\", 6, 1000);\n```\n\n**NRM mode (multi-drop primary):**\n\n```c\ntiny_fd_init_t init = {\n    // ... same as above, plus:\n    .mode         = TINY_FD_MODE_NRM,\n    .peers_count  = 3,           // support up to 3 secondaries\n    .addr         = TINY_FD_PRIMARY_ADDR,  // this is the primary station\n};\n```\n\n**NRM mode (secondary station):**\n\n```c\ntiny_fd_init_t init = {\n    // ... same as above, plus:\n    .mode         = TINY_FD_MODE_NRM,\n    .addr         = 1,           // unique secondary address (1-63)\n};\n```\n\n### C++ API\n\n**Full-duplex with static buffer (Arduino-friendly):**\n\n```cpp\n#include \"TinyProtocolFd.h\"\n\n// Static buffer — no heap allocation\ntinyproto::Fd\u003c1024\u003e proto;\n\nvoid onReceive(void *udata, uint8_t addr, tinyproto::IPacket \u0026pkt) {\n    // Process received message\n    Serial.write(pkt.data(), pkt.size());\n}\n\nvoid setup() {\n    Serial.begin(115200);\n    proto.setReceiveCallback(onReceive);\n    proto.setWindowSize(4);\n    proto.enableCrc16();\n    proto.begin();\n}\n\nvoid loop() {\n    // Feed serial data to protocol\n    if (Serial.available()) {\n        uint8_t byte = Serial.read();\n        proto.run_rx(\u0026byte, 1);\n    }\n    // Transmit protocol data\n    uint8_t tx;\n    if (proto.run_tx(\u0026tx, 1) == 1) {\n        Serial.write(tx);\n    }\n}\n```\n\n**Dynamic buffer (desktop / powerful MCUs):**\n\n```cpp\n#include \"TinyProtocolFd.h\"\n\n// Dynamic allocation — buffer size determined at runtime\ntinyproto::FdD proto(4096);\nproto.setWindowSize(7);\nproto.enableCrc32();\nproto.begin();\n\n// Send data\nproto.write(\"Hello World\", 12);\n```\n\n### Python\n\n```python\nimport tinyproto\n\nproto = tinyproto.Hdlc()\n\ndef on_read(data):\n    print(\"Received:\", data.hex())\n\nproto.on_read = on_read\nproto.begin()\n\n# Feed raw bytes from your transport\nproto.rx(bytearray([0x7E, 0xFF, 0x3F, 0xF3, 0x39, 0x7E]))\n\n# Queue data and get encoded bytes to transmit\nproto.put(bytearray(b\"Hello\"))\ntx_data = proto.tx()\n```\n\n## Building\n\n### Linux\n\n```bash\n# Using Make\nmake\n\n# Using CMake\nmkdir build \u0026\u0026 cd build\ncmake -DEXAMPLES=ON ..\nmake\n\n# Run unit tests\nmake ARCH=linux unittest\n./bld/unit_test\n```\n\n### Windows\n\n```bash\nmkdir build \u0026\u0026 cd build\ncmake -G \"Visual Studio 16 2019\" -DEXAMPLES=ON ..\n# Open the generated .sln file in Visual Studio\n```\n\n### ESP32 (IDF)\n\nPlace the library in your project's `components/` directory, then build normally with `idf.py build` or `make`.\n\n### AVR\n\n```bash\nmake ARCH=avr\n```\n\n## Testing\n\nTinyProto has a comprehensive test suite with **101 tests** covering all protocol layers:\n\n```bash\n# Build and run all tests\nmake ARCH=linux DEBUG_MODE=y unittest \u0026\u0026 ./bld/unit_test\n\n# Run specific test groups\n./bld/unit_test -g TINY_FD_ABM    # ABM mode tests (28 tests)\n./bld/unit_test -g TINY_FD_NRM    # NRM mode tests (15 tests)\n./bld/unit_test -g CPP_FD         # C++ FD wrapper tests (10 tests)\n./bld/unit_test -g CPP_HDLC       # C++ HDLC wrapper tests (3 tests)\n./bld/unit_test -g CPP_LIGHT      # C++ Light wrapper tests (3 tests)\n./bld/unit_test -g HDLC           # Low-level HDLC tests\n./bld/unit_test -g LIGHT          # Light protocol tests\n```\n\n## Installation\n\n### Arduino\n\n**Option 1** — From source:\n1. Download from https://github.com/lexus2k/tinyproto\n2. Copy to `Arduino/libraries/tinyproto`\n3. Restart Arduino IDE → Examples → tinyproto\n\n**Option 2** — Library Manager:\n1. Arduino IDE → Sketch → Include Library → Manage Libraries\n2. Search for \"tinyproto\" and install\n\n### ESP32 IDF\n\n```bash\ncd your_project/components\ngit clone https://github.com/lexus2k/tinyproto\n```\n\n### PlatformIO\n\nAdd to `platformio.ini`:\n```ini\nlib_deps = lexus2k/tinyproto\n```\n\n### Python\n\n```bash\ncd tinyproto\npython setup.py install\n```\n\n## Tools\n\n### tiny_loopback\n\nA serial loopback testing tool for benchmarking and debugging:\n\n```bash\n# Build\nmake ARCH=linux\n\n# Test Light protocol\n./bld/tiny_loopback -p /dev/ttyUSB0 -t light -g -c 8 -a -r\n\n# Test Full-Duplex protocol\n./bld/tiny_loopback -p /dev/ttyUSB0 -t fd -c 8 -w 3 -g -a -r\n```\n\n## API Reference\n\nFull API documentation is available at [codedocs.xyz/lexus2k/tinyproto](https://codedocs.xyz/lexus2k/tinyproto/).\n\n### Key C Functions\n\n| Function | Description |\n|----------|-------------|\n| `tiny_fd_init()` | Initialize FD protocol instance |\n| `tiny_fd_close()` | Close and free FD instance |\n| `tiny_fd_on_rx_data()` | Feed received bytes to protocol |\n| `tiny_fd_get_tx_data()` | Get bytes to transmit |\n| `tiny_fd_send_packet()` | Queue data for transmission |\n| `tiny_fd_send_to()` | Send to specific peer address (NRM) |\n| `tiny_fd_get_status()` | Check connection status |\n| `tiny_fd_disconnect()` | Initiate disconnect |\n\n### Key C++ Classes\n\n| Class | Description |\n|-------|-------------|\n| `tinyproto::Fd\u003cN\u003e` | FD protocol with static N-byte buffer |\n| `tinyproto::FdD` | FD protocol with dynamic buffer allocation |\n| `tinyproto::Hdlc` | HDLC low-level framing |\n| `tinyproto::Light` | Lightweight SLIP-like protocol |\n| `tinyproto::IPacket` | Packet buffer for data exchange |\n\n## License\n\nDual licensed under **GPLv3** and **Commercial** licenses.\n\nCopyright 2016-2025 (C) Alexey Dynda\n\n**GNU General Public License:** Protocol Library is free software under the GNU Lesser General Public License v3.0 or later. See [COPYING](COPYING) for details.\n\n**Commercial License:** Available for proprietary use. Contact via email on the [GitHub account](https://github.com/lexus2k) for details.\n\n---\n\n\u003cp align=\"center\"\u003e\n  \u003csub\u003eIf you find this library useful, consider supporting its development.\u003c/sub\u003e\n\u003c/p\u003e\n\n| Bitcoin | Ethereum |\n|:-------:|:--------:|\n| ![BTC](.travis/btc_segwit.png) | ![ETH](.travis/eth.png) |\n| `3CtUY6Ag2zsvm1JyqeeKeK8kjdG7Tnjr5W` | `0x20608A71470Bc84a3232621819f578Fb9C02A460` |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flexus2k%2Ftinyproto","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flexus2k%2Ftinyproto","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flexus2k%2Ftinyproto/lists"}