DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
devicenet.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 devicenet.h
6 * @brief DeviceNet link-adaptation codec (DETWS_ENABLE_DEVICENET) - the CAN-specific layer of
7 * "CIP over CAN".
8 *
9 * DeviceNet (ODVA) carries CIP over classic CAN. The CIP application layer (services, EPATH,
10 * data) is the same one the EtherNet/IP codec uses, so build the message body with the
11 * existing `cip_*` functions (`DETWS_ENABLE_CIP`); this module supplies the DeviceNet-specific
12 * link adaptation that is NOT part of CIP:
13 *
14 * - The 11-bit CAN **identifier** as a Message Group (1..4) + Message ID + MAC ID, per the
15 * DeviceNet identifier allocation:
16 * @code
17 * Group 1: 0 MsgID(4) SourceMAC(6) ids 0x000-0x3FF
18 * Group 2: 10 MAC(6) MsgID(3) ids 0x400-0x5FF
19 * Group 3: 11 MsgID(3) SourceMAC(6) ids 0x600-0x7BF
20 * Group 4: 11111 MsgID(6) ids 0x7C0-0x7EF
21 * @endcode
22 * - The explicit-message **header octet** (FRAG | XID | MAC ID).
23 * - The **fragmentation protocol** (type + modulo-64 count) and a reassembler for explicit
24 * messages longer than one 8-octet frame.
25 *
26 * Pure and host-tested. Drive it from the ESP32 TWAI peripheral or an MCP2515 over SPI to
27 * bridge a DeviceNet segment onto Wi-Fi.
28 *
29 * @author Douglas Quigg (dstroy0)
30 * @date 2026
31 */
32
33#ifndef DETERMINISTICESPASYNCWEBSERVER_DEVICENET_H
34#define DETERMINISTICESPASYNCWEBSERVER_DEVICENET_H
35
36#include "ServerConfig.h"
37
38#if DETWS_ENABLE_DEVICENET
39
41#include <stddef.h>
42#include <stdint.h>
43
44// Message-group identifier bases / field widths.
45#define DEVICENET_G1_BASE 0x000u ///< Message Group 1 (0x000-0x3FF)
46#define DEVICENET_G2_BASE 0x400u ///< Message Group 2 (0x400-0x5FF)
47#define DEVICENET_G3_BASE 0x600u ///< Message Group 3 (0x600-0x7BF)
48#define DEVICENET_G4_BASE 0x7C0u ///< Message Group 4 (0x7C0-0x7EF)
49#define DEVICENET_MAC_MASK 0x3Fu ///< MAC IDs are 0..63
50
51// Common Group 2 message IDs (predefined master/slave connection set).
52#define DEVICENET_G2_UNCONNECTED_EXPLICIT_REQ 4u ///< unconnected explicit request to a slave
53#define DEVICENET_G2_EXPLICIT_RESPONSE 3u ///< explicit / unconnected response from a slave
54#define DEVICENET_G2_POLL_COMMAND 5u ///< Poll command / change-of-state to a slave
55#define DEVICENET_G2_DUP_MAC_CHECK 7u ///< Duplicate MAC ID check
56
57// Explicit-message header octet fields.
58#define DEVICENET_HDR_FRAG 0x80u ///< this body is fragmented (a fragmentation octet follows)
59#define DEVICENET_HDR_XID 0x40u ///< transaction-id bit
60
61// Fragmentation octet: type in the top 2 bits, modulo-64 count in the low 6.
62#define DEVICENET_FRAG_FIRST 0x00u ///< first fragment
63#define DEVICENET_FRAG_MIDDLE 0x40u ///< middle fragment
64#define DEVICENET_FRAG_LAST 0x80u ///< last fragment
65#define DEVICENET_FRAG_ACK 0xC0u ///< fragment acknowledge
66#define DEVICENET_FRAG_TYPE_MASK 0xC0u
67#define DEVICENET_FRAG_COUNT_MASK 0x3Fu
68
69/** @brief DeviceNet message groups. */
70enum class DeviceNetGroup : uint8_t
71{
72 DEVICENET_GROUP_1 = 1,
73 DEVICENET_GROUP_2 = 2,
74 DEVICENET_GROUP_3 = 3,
75 DEVICENET_GROUP_4 = 4,
76};
77
78/** @brief A decoded DeviceNet identifier. */
79struct DeviceNetId
80{
81 DeviceNetGroup group;
82 uint8_t msg_id; ///< message id within the group
83 uint8_t mac_id; ///< source / node MAC id (0..63; not present for Group 4)
84};
85
86/** @brief Result of feeding a frame to the fragmentation reassembler. */
87enum class DeviceNetFragResult : uint8_t
88{
89 DEVICENET_FRAG_IGNORED = 0,
90 DEVICENET_FRAG_STARTED,
91 DEVICENET_FRAG_PROGRESS,
92 DEVICENET_FRAG_COMPLETE,
93 DEVICENET_FRAG_ERR,
94};
95
96/** @brief Fragmented-message reassembly context. */
97struct DeviceNetFragRx
98{
99 bool active;
100 uint8_t next_count; ///< next expected modulo-64 fragment count
101 uint16_t len; ///< octets stored so far
102 uint8_t buf[DETWS_DEVICENET_MSG_MAX]; ///< reassembled body (excludes the fragmentation octets)
103};
104
105// --- identifier ---
106
107/** @brief Encode a DeviceNet 11-bit CAN id. @p mac_id is ignored for Group 4. */
108bool devicenet_encode_id(uint32_t *id, DeviceNetGroup group, uint8_t msg_id, uint8_t mac_id);
109
110/** @brief Decode an 11-bit CAN id into its DeviceNet group / message id / MAC id. */
111bool devicenet_decode_id(uint32_t can_id, DeviceNetId *out);
112
113// --- explicit-message header + fragmentation octets ---
114
115/** @brief Compose the explicit-message header octet (FRAG / XID / MAC id). */
116uint8_t devicenet_msg_header(bool frag, bool xid, uint8_t mac_id);
117
118/** @brief Compose a fragmentation octet from a type (DEVICENET_FRAG_*) and a count. */
119uint8_t devicenet_frag_octet(uint8_t type, uint8_t count);
120
121// --- non-fragmented explicit message in one frame ---
122
123/**
124 * @brief Build a single-frame explicit message: [header octet][body...] at the group/msg id.
125 * @p body is typically a CIP request built with `cip_*`. Fails if it does not fit in 8 octets.
126 */
127bool devicenet_build_explicit(CanFrame *out, DeviceNetGroup group, uint8_t msg_id, uint8_t mac_id, const uint8_t *body,
128 uint8_t body_len);
129
130// --- fragmentation reassembly (messages longer than one frame) ---
131
132/** @brief Reset a reassembly context to idle. */
133void devicenet_frag_reset(DeviceNetFragRx *rx);
134
135/**
136 * @brief Feed a received frame's body (the octets after the CAN id) to the reassembler.
137 * @p body points at the explicit-message body starting with the header octet; the
138 * fragmentation octet (when DEVICENET_HDR_FRAG is set) is the second octet.
139 */
140DeviceNetFragResult devicenet_frag_feed(DeviceNetFragRx *rx, const uint8_t *body, uint8_t body_len);
141
142#endif // DETWS_ENABLE_DEVICENET
143#endif // DETERMINISTICESPASYNCWEBSERVER_DEVICENET_H
User-facing configuration for DeterministicESPAsyncWebServer.
Shared CAN 2.0 frame type for the CAN-based industrial codecs (one source of truth).
Definition can.h:44