Framing Details
This page covers the technical details of the framing system.
Frame Components
Frames consist of two parts:
- Header: Determines sync bytes and addressing
- Payload: Determines length encoding and checksum
Header Types
Basic Header (2 bytes)
[0x90] [0x70 + PayloadType]Two-byte sync for reliable synchronization. Recommended for most applications.
Tiny Header (1 byte)
[0x70 + PayloadType]Single-byte sync for bandwidth-limited scenarios.
None Header (0 bytes)
(no header)For trusted links where synchronization isn’t needed.
Payload Types
Minimal
[MSG_ID] [PAYLOAD...]1 byte overhead. Requires message length lookup. No checksum or length field.
Default
[LENGTH] [MSG_ID] [PAYLOAD...] [CRC_HI] [CRC_LO]4 bytes overhead. Includes length (1 byte, max 255) and Fletcher-16 checksum.
Extended
[LENGTH_HI] [LENGTH_LO] [MSG_ID] [PAYLOAD...] [CRC_HI] [CRC_LO]5 bytes overhead. 16-bit length field (max 65535 bytes).
ExtendedMultiSystemStream
[LENGTH_HI] [LENGTH_LO] [SRC] [DST] [SEQ] [MSG_ID] [PAYLOAD...] [CRC_HI] [CRC_LO]8 bytes overhead. Adds source/destination addresses and sequence numbers for multi-node networks.
Frame Profiles
Profiles combine header + payload types:
| Profile | Header | Payload | Total Overhead |
|---|---|---|---|
| Standard | Basic | Default | 6 bytes |
| Sensor | Tiny | Minimal | 2 bytes |
| IPC | None | Minimal | 1 byte |
| Bulk | Basic | Extended | 8 bytes |
| Network | Basic | ExtendedMultiSystemStream | 11 bytes |
Checksum (Fletcher-16)
The Default and Extended payload types use Fletcher-16 checksum.
Magic Numbers:
- Basic frame start:
0x90followed by0x70 + PayloadType - Tiny frame start:
0x70 + PayloadType - Payload type base value:
0x70
The checksum algorithm:
For each byte in [LENGTH, MSG_ID, PAYLOAD]: sum1 = (sum1 + byte) mod 255 sum2 = (sum2 + sum1) mod 255checksum = (sum2 << 8) | sum1Parser State Machine
The parser implements a state machine:
IDLE → wait for start byte(s)HEADER → read header bytesPAYLOAD → read length, msg_id, dataCHECKSUM → verify CRCCOMPLETE → return messageFor Minimal payloads, the parser requires a message length callback to determine payload size.
Usage in C++
#include "FrameProfiles.hpp"
using namespace FrameParsers;
// Using profilesuint8_t buffer[1024];ProfileStandardWriter writer(buffer, sizeof(buffer));ProfileStandardAccumulatingReader reader;
// Encodewriter.write(msg);send_data(writer.buffer(), writer.size());
// Decode (streaming)while (receiving) { if (auto result = reader.push_byte(read_byte())) { handle_message(result.msg_id, result.msg_data, result.msg_len); }}
// Decode (buffer)reader.add_data(buffer, buffer_size);while (auto result = reader.next()) { handle_message(result.msg_id, result.msg_data, result.msg_len);}Usage in Python
from struct_frame_parser import Parser, HeaderType, PayloadType
# Create parser with specific frame typesparser = Parser( enabled_headers=[HeaderType.BASIC, HeaderType.TINY], enabled_payloads=[PayloadType.DEFAULT, PayloadType.EXTENDED])
# Encodeframe = parser.encode( msg_id=42, msg=b"payload data", header_type=HeaderType.BASIC, payload_type=PayloadType.DEFAULT)
# Decode (byte-by-byte)for byte in incoming_data: result = parser.parse_byte(byte) if result.valid: handle_message(result)Custom Profiles
Create custom frame formats by combining header and payload types:
// Custom: Tiny header with Extended payloadusing CustomConfig = FrameConfig< HeaderTiny, PayloadExtended>;
FrameEncoderWithCrc<CustomConfig> encoder;BufferParserWithCrc<CustomConfig> parser;from struct_frame_parser import create_custom_profile, HeaderType, PayloadType
custom = create_custom_profile( "TinyExtended", HeaderType.TINY, PayloadType.EXTENDED)