DeterministicESPAsyncWebServer v6.28.0
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
mbplus.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 mbplus.h
6 * @brief Modbus Plus HDLC token-bus frame codec (DETWS_ENABLE_MBPLUS).
7 *
8 * Modbus Plus is Schneider's 1 Mbit/s token-passing peer bus. Its data link is HDLC-framed: a frame is
9 * delimited by the HDLC flag 0x7E, carries an address / control / the LLC+Modbus routing path + data,
10 * and ends with a CRC-16 (CRC-16/X-25). This codec builds/validates the HDLC frame (with 0x7E-flag
11 * delimiting and the standard bit/byte transparency handled at the byte level) around a Modbus routing
12 * path + PDU, plus the token-rotation helper that computes the next station in the logical ring:
13 *
14 * [7E][address][control][routing path...][data...][CRC-16 lo][CRC-16 hi][7E]
15 *
16 * The physical 1 Mbit/s bus is hardware-gated; this is the frame + token-MAC layer, reusing the shipped
17 * Modbus PDU model for the data. Pure, zero heap, no stdlib, host-testable.
18 */
19
20#ifndef DETERMINISTICESPASYNCWEBSERVER_MBPLUS_H
21#define DETERMINISTICESPASYNCWEBSERVER_MBPLUS_H
22
23#include "ServerConfig.h"
24#include <stddef.h>
25#include <stdint.h>
26
27#if DETWS_ENABLE_MBPLUS
28
29// Modbus Plus HDLC wire constants: integer values compared/emitted, in a namespacing struct.
30struct Mbplus
31{
32 static constexpr uint8_t MBPLUS_FLAG = 0x7E; ///< HDLC frame delimiter.
33 static constexpr uint8_t MBPLUS_MAX_STATION = 64; ///< stations 1..64 on a Modbus Plus segment.
34 static constexpr uint8_t MBPLUS_CTRL_DATA = 0x00; ///< data frame control.
35 static constexpr uint8_t MBPLUS_CTRL_TOKEN = 0x01; ///< token pass control.
36};
37
38/** @brief CRC-16/X-25 (the Modbus Plus HDLC FCS) over @p len bytes. */
39uint16_t detws_mbplus_crc(const uint8_t *bytes, size_t len);
40
41/**
42 * @brief Build a Modbus Plus HDLC frame: 7E addr ctrl [payload] CRClo CRChi 7E.
43 * @param address the destination station (1..64).
44 * @param control MBPLUS_CTRL_DATA / MBPLUS_CTRL_TOKEN.
45 * @param payload the routing path + Modbus PDU (may be null if payload_len == 0).
46 * @param payload_len its length.
47 * @return the frame length (1 + 1 + 1 + payload_len + 2 + 1), or 0 on overflow / bad args.
48 *
49 * The CRC covers address + control + payload (not the flags).
50 */
51size_t detws_mbplus_build(uint8_t address, uint8_t control, const uint8_t *payload, size_t payload_len, uint8_t *out,
52 size_t cap);
53
54/** @brief A parsed Modbus Plus frame (payload points into the input). */
55struct MbPlusFrame
56{
57 uint8_t address;
58 uint8_t control;
59 const uint8_t *payload;
60 size_t payload_len;
61};
62
63/** @brief Validate the flags + CRC and parse a Modbus Plus frame. @return true if well-formed. */
64bool detws_mbplus_parse(const uint8_t *frame, size_t len, MbPlusFrame *out);
65
66/**
67 * @brief Compute the next token holder in the logical ring.
68 * @param current this station's address (1..max_station).
69 * @param max_station the highest active station on the segment.
70 * @return the next station address, wrapping from max_station back to 1.
71 */
72uint8_t detws_mbplus_next_token(uint8_t current, uint8_t max_station);
73
74#endif // DETWS_ENABLE_MBPLUS
75#endif // DETERMINISTICESPASYNCWEBSERVER_MBPLUS_H
User-facing configuration for DeterministicESPAsyncWebServer.