ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
zigbee.h
Go to the documentation of this file.
1// ProtoCore v1.0.16 - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4#ifndef PROTOCORE_ZIGBEE_H
5#define PROTOCORE_ZIGBEE_H
6
7#include "protocore_config.h" // the entry point: protocore_types.h for the widths
8
10
11/**
12 * @file zigbee.h
13 * @brief Zigbee EZSP / ASH framing codec (PROTOCORE_ENABLE_ZIGBEE) - Silicon Labs NCP.
14 *
15 * The ASH (Asynchronous Serial Host, UG101) data-link layer that carries EZSP frames to a
16 * Silicon Labs EmberZNet network co-processor over UART - a Zigbee network bridged to the
17 * web. Each ASH frame is a control byte + payload + a CRC-16/CCITT, byte-stuffed so the
18 * reserved control bytes never appear in the body, and terminated by a Flag byte (0x7E):
19 *
20 * [control | payload | CRC16(hi,lo)] --byte-stuffed--> ... | 0x7E
21 *
22 * The reserved bytes that get stuffed (as 0x7D followed by byte XOR 0x20) are the Flag
23 * 0x7E, the Escape 0x7D, XON 0x11, XOFF 0x13, Substitute 0x18, and Cancel 0x1A.
24 *
25 * protocore_ash_frame_encode() wraps a control byte + payload into a stuffed, CRC'd, flag-terminated
26 * frame; protocore_ash_frame_decode() finds the flag, removes the stuffing, and verifies the CRC.
27 * protocore_ash_crc16() is the shared CRC. The EZSP command the payload carries (version query, an
28 * incoming APS message, a network-init) is the application's. Pure - you carry the bytes
29 * over your UART - so it is fully host-testable.
30 *
31 * @c work is bytes the CALLER holds. This module reads none of them: it carries nothing
32 * between calls, so there is no state to keep and nothing to wipe. The parameter is there so
33 * a caller drives every namespace the same way.
34 *
35 * @author Douglas Quigg (dstroy0)
36 * @date 2026
37 */
38
39// PROTOCORE_ZIGBEE_BORROW - the bytes this module runs out of - is stated in protocore_config.h, which sums
40// it into its arena. Its size and its offset are each a static_assert, so a feature
41// combination that does not fit fails to compile rather than overrunning at run time.
42
43/** @brief ASH markers / reset control bytes. */
44#define ASH_FLAG 0x7E ///< frame delimiter
45#define ASH_ESCAPE 0x7D ///< byte-stuffing escape
46#define ASH_RST 0xC0 ///< reset control byte
47#define ASH_RSTACK 0xC1 ///< reset acknowledge
48#define ASH_ERROR 0xC2 ///< error
49
50/** @brief Dispatch table. Addressed by offset, so the layout is asserted below. */
51typedef struct
52{
53 uint16_t (*ash_crc16)(uint8_t *, const uint8_t *, uint16_t);
54 uint16_t (*ash_frame_encode)(uint8_t *, uint8_t, const uint8_t *, uint16_t, uint8_t *, uint16_t);
55 int (*ash_frame_decode)(uint8_t *, const uint8_t *, uint16_t, uint8_t *, uint8_t *, uint16_t, uint16_t *);
56} ZigbeeNs;
57PROTOCORE_NS_LAYOUT(ZigbeeNs, ash_crc16, ash_frame_encode, ash_frame_decode);
58
59/**
60 * @brief CRC-16/CCITT (polynomial 0x1021, MSB-first, init 0xFFFF) over buf.
61 * @param work PROTOCORE_ZIGBEE_BORROW bytes the caller took. Not held past the call.
62 * @param buf Buf
63 * @param len Len
64 * @return The uint16_t.
65 */
66uint16_t protocore_zigbee_ash_crc16(uint8_t *work, const uint8_t *buf, uint16_t len);
67/**
68 * @brief Encode an ASH frame: [control | payload] + CRC-16, byte-stuffed, .
69 * @param work PROTOCORE_ZIGBEE_BORROW bytes the caller took. Not held past the call.
70 * @param control Control
71 * @param payload Payload
72 * @param len Len
73 * @param out Out
74 * @param cap Cap
75 * @return The uint16_t.
76 */
77uint16_t protocore_zigbee_ash_frame_encode(uint8_t *work, uint8_t control, const uint8_t *payload, uint16_t len,
78 uint8_t *out, uint16_t cap);
79/**
80 * @brief Decode one ASH frame from the front of raw: find the flag, remove .
81 * @param work PROTOCORE_ZIGBEE_BORROW bytes the caller took. Not held past the call.
82 * @param raw Raw
83 * @param len Len
84 * @param control Control
85 * @param payload Payload
86 * @param pay_cap Pay cap
87 * @param pay_len Pay len
88 * @return The int.
89 */
90int protocore_zigbee_ash_frame_decode(uint8_t *work, const uint8_t *raw, uint16_t len, uint8_t *control,
91 uint8_t *payload, uint16_t pay_cap, uint16_t *pay_len);
92
93/** @brief Module namespace. */
97
99
100#endif // PROTOCORE_ZIGBEE_H
#define PROTOCORE_NS_LAYOUT(T,...)
Pin every dispatch slot of a table that is nothing but function pointers.
#define PROTOCORE_NS
Storage for a dispatch table. The const is load bearing.
Dispatch table. Addressed by offset, so the layout is asserted below.
Definition zigbee.h:52
uint16_t(* ash_crc16)(uint8_t *, const uint8_t *, uint16_t)
Definition zigbee.h:53
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
#define PROTOCORE_END_DECLS
Definition types.h:97
uint16_t protocore_zigbee_ash_crc16(uint8_t *work, const uint8_t *buf, uint16_t len)
CRC-16/CCITT (polynomial 0x1021, MSB-first, init 0xFFFF) over buf.
PROTOCORE_NS ZigbeeNs Zigbee PROTOCORE_UNUSED
Module namespace.
Definition zigbee.h:94
uint16_t protocore_zigbee_ash_frame_encode(uint8_t *work, uint8_t control, const uint8_t *payload, uint16_t len, uint8_t *out, uint16_t cap)
Encode an ASH frame: [control | payload] + CRC-16, byte-stuffed, .
int protocore_zigbee_ash_frame_decode(uint8_t *work, const uint8_t *raw, uint16_t len, uint8_t *control, uint8_t *payload, uint16_t pay_cap, uint16_t *pay_len)
Decode one ASH frame from the front of raw: find the flag, remove .