DeterministicESPAsyncWebServer v6.28.0
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
profibus.cpp
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 profibus.cpp
6 * @brief PROFIBUS-DP FDL telegram codec (see profibus.h).
7 */
8
10
11#if DETWS_ENABLE_PROFIBUS
12
13#include <string.h>
14
15uint8_t detws_pb_fcs(const uint8_t *bytes, size_t len)
16{
17 uint8_t sum = 0;
18 for (size_t i = 0; i < len; i++)
19 sum = (uint8_t)(sum + bytes[i]);
20 return sum;
21}
22
23size_t detws_pb_build_sd1(uint8_t da, uint8_t sa, uint8_t fc, uint8_t *out, size_t cap)
24{
25 if (!out || cap < 6)
26 return 0;
27 out[0] = Profibus::PB_SD1;
28 out[1] = da;
29 out[2] = sa;
30 out[3] = fc;
31 uint8_t body[3] = {da, sa, fc};
32 out[4] = detws_pb_fcs(body, 3);
33 out[5] = Profibus::PB_ED;
34 return 6;
35}
36
37size_t detws_pb_build_sd2(uint8_t da, uint8_t sa, uint8_t fc, const uint8_t *data, size_t data_len, uint8_t *out,
38 size_t cap)
39{
40 if (!out || (data_len && !data) || data_len > 246)
41 return 0;
42 // SD2 LE LEr SD2 DA SA FC [data] FCS ED
43 size_t n = 4 + 3 + data_len + 2; // (SD2,LE,LEr,SD2) + (DA,SA,FC) + data + (FCS,ED)
44 if (n > cap)
45 return 0;
46 uint8_t le = (uint8_t)(3 + data_len); // length of DA+SA+FC+data
47 size_t i = 0;
48 out[i++] = Profibus::PB_SD2;
49 out[i++] = le;
50 out[i++] = le; // LEr (redundant length)
51 out[i++] = Profibus::PB_SD2;
52 out[i++] = da;
53 out[i++] = sa;
54 out[i++] = fc;
55 if (data_len)
56 {
57 memcpy(out + i, data, data_len);
58 i += data_len;
59 }
60 // FCS over DA+SA+FC+data (out[4 .. 4+le-1]).
61 out[i++] = detws_pb_fcs(out + 4, le);
62 out[i++] = Profibus::PB_ED;
63 return i;
64}
65
66bool detws_pb_parse(const uint8_t *frame, size_t len, PbTelegram *out)
67{
68 if (!frame || !out || len < 6)
69 return false;
70
71 if (frame[0] == Profibus::PB_SD1)
72 {
73 // SD1 DA SA FC FCS ED (len >= 6 already guaranteed above)
74 uint8_t body[3] = {frame[1], frame[2], frame[3]};
75 if (detws_pb_fcs(body, 3) != frame[4] || frame[5] != Profibus::PB_ED)
76 return false;
77 out->sd = Profibus::PB_SD1;
78 out->da = frame[1];
79 out->sa = frame[2];
80 out->fc = frame[3];
81 out->data = nullptr;
82 out->data_len = 0;
83 return true;
84 }
85 if (frame[0] == Profibus::PB_SD2)
86 {
87 // SD2 LE LEr SD2 DA SA FC [data] FCS ED
88 if (len < 9)
89 return false;
90 uint8_t le = frame[1];
91 if (frame[2] != le || frame[3] != Profibus::PB_SD2)
92 return false;
93 if (le < 3)
94 return false;
95 size_t total = 4 + le + 2; // header(4) + le body + FCS + ED
96 if (len < total)
97 return false;
98 if (detws_pb_fcs(frame + 4, le) != frame[4 + le] || frame[4 + le + 1] != Profibus::PB_ED)
99 return false;
100 out->sd = Profibus::PB_SD2;
101 out->da = frame[4];
102 out->sa = frame[5];
103 out->fc = frame[6];
104 size_t dl = le - 3;
105 out->data = dl ? (frame + 7) : nullptr;
106 out->data_len = dl;
107 return true;
108 }
109 return false;
110}
111
112#endif // DETWS_ENABLE_PROFIBUS
PROFIBUS-DP FDL telegram codec (DETWS_ENABLE_PROFIBUS).