DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
c37118.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file c37118.h
6 * @brief IEEE C37.118.2 synchrophasor frame codec (DETWS_ENABLE_C37118) - zero-heap frame
7 * builder + parser for the PMU / PDC wide-area-measurement wire protocol.
8 *
9 * A C37.118.2 frame (all fields big-endian / network order):
10 * @code
11 * SYNC(2) FRAMESIZE(2) IDCODE(2) SOC(4) FRACSEC(4) DATA(n) CHK(2)
12 * @endcode
13 * - SYNC: byte 0 = 0xAA; byte 1 = (frame_type << 4) | version (bits 6-4 type, 3-0 version).
14 * - FRAMESIZE: total octets in the frame, the CHK included.
15 * - SOC: seconds-of-century (Unix epoch seconds); FRACSEC: top 8 bits time quality, low
16 * 24 bits the fraction of a second.
17 * - CHK: CRC-CCITT (poly 0x1021, init 0xFFFF, no reflection, no final mask) over every
18 * octet up to but excluding the CHK itself.
19 *
20 * Frame types: data / header / config-1 / config-2 / command / config-3. The DATA contents
21 * are message-type specific (data frames depend on the configuration); this codec frames
22 * any payload and fully builds + parses the fixed Command frame. CRC verified against the
23 * canonical CRC-CCITT-FALSE check value.
24 *
25 * @author Douglas Quigg (dstroy0)
26 * @date 2026
27 */
28
29#ifndef DETERMINISTICESPASYNCWEBSERVER_C37118_H
30#define DETERMINISTICESPASYNCWEBSERVER_C37118_H
31
32#include "ServerConfig.h"
33
34#if DETWS_ENABLE_C37118
35
36#include <stddef.h>
37#include <stdint.h>
38
39#define C37118_SYNC_LEADER 0xAA ///< SYNC byte 0 (frame leader)
40#define C37118_TYPE_SHIFT 4 ///< SYNC byte 1: frame type occupies bits 6-4
41#define C37118_TYPE_MASK 0x07 ///< frame-type field width (after the shift)
42#define C37118_VERSION_MASK 0x0F ///< SYNC byte 1: version occupies bits 3-0
43
44// Frame types (SYNC byte 1, bits 6-4).
45#define C37118_TYPE_DATA 0
46#define C37118_TYPE_HEADER 1
47#define C37118_TYPE_CFG1 2
48#define C37118_TYPE_CFG2 3
49#define C37118_TYPE_CMD 4
50#define C37118_TYPE_CFG3 5
51
52#define C37118_VERSION_2005 1
53#define C37118_VERSION_2011 2
54
55// Command codes (Command-frame DATA word).
56#define C37118_CMD_DATA_OFF 1
57#define C37118_CMD_DATA_ON 2
58#define C37118_CMD_SEND_HDR 3
59#define C37118_CMD_SEND_CFG1 4
60#define C37118_CMD_SEND_CFG2 5
61#define C37118_CMD_SEND_CFG3 6
62
63#define C37118_MIN_FRAME 16 ///< header (14) + CHK (2), no payload
64
65/** @brief CRC-CCITT (0x1021, init 0xFFFF, no reflection, no final mask). */
66uint16_t c37118_crc(const uint8_t *data, size_t len);
67
68/**
69 * @brief Build a frame: SYNC + FRAMESIZE + IDCODE + SOC + FRACSEC + payload + CHK.
70 * @param type frame type (C37118_TYPE_*), placed in SYNC bits 6-4.
71 * @param version version nibble (e.g. C37118_VERSION_2011).
72 * @return total octets written, or 0 on overflow / bad input.
73 */
74size_t c37118_build_frame(uint8_t *buf, size_t cap, uint8_t type, uint8_t version, uint16_t idcode, uint32_t soc,
75 uint32_t fracsec, const uint8_t *payload, size_t payload_len);
76
77/** @brief Build a Command frame (DATA = the 16-bit command word), version 2011. */
78size_t c37118_build_command(uint8_t *buf, size_t cap, uint16_t idcode, uint32_t soc, uint32_t fracsec, uint16_t cmd);
79
80/** @brief A parsed frame; @ref data points INTO the source buffer (between FRACSEC and CHK). */
81struct C37118Frame
82{
83 uint8_t type; ///< frame type (bits 6-4 of SYNC byte 1)
84 uint8_t version; ///< version nibble (bits 3-0)
85 uint16_t framesize;
86 uint16_t idcode;
87 uint32_t soc;
88 uint32_t fracsec;
89 const uint8_t *data;
90 size_t data_len;
91};
92
93/**
94 * @brief Parse and CRC-validate a frame at the head of [buf, buf+len).
95 * @return true on a complete, CRC-valid frame; false on a bad SYNC, truncation, an
96 * out-of-range FRAMESIZE, or a CHK mismatch.
97 */
98bool c37118_parse_frame(const uint8_t *buf, size_t len, C37118Frame *out);
99
100/** @brief Read the command word from a parsed Command frame. */
101bool c37118_parse_command(const C37118Frame *f, uint16_t *cmd);
102
103#endif // DETWS_ENABLE_C37118
104
105#endif // DETERMINISTICESPASYNCWEBSERVER_C37118_H
User-facing configuration for DeterministicESPAsyncWebServer.