Skip to content

Commit c6ed43d

Browse files
Specify Cyphal/UDP [experimental] (#127)
- Add Cyphal/UDP specification (marked as experimental); fixes #98. - Move CRC implementations to the appendix. The specification is quite concise because the key concepts are already covered in section "4.1 Abstract concepts". In the new section, I only had to cover the layouts.
1 parent 0093b35 commit c6ed43d

File tree

11 files changed

+688
-54
lines changed

11 files changed

+688
-54
lines changed

.vscode/settings.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,10 @@
6363
"attrib",
6464
"Autoconfigured",
6565
"autodetect",
66+
"AUTOSAR",
6667
"AWG",
6768
"Backus-Naur",
69+
"baremetal",
6870
"baz",
6971
"BAZ",
7072
"BCI",
@@ -79,11 +81,14 @@
7981
"bootloaders",
8082
"bootup",
8183
"broadcasted",
84+
"bytearray",
85+
"bytewise",
8286
"canadensis",
8387
"CANaerospace",
8488
"CANopen",
8589
"Cardinality",
8690
"cassert",
91+
"Castagnoli",
8792
"CCITT",
8893
"cfg",
8994
"CLI",
@@ -106,11 +111,14 @@
106111
"cstdint",
107112
"cyber",
108113
"Cyphal",
114+
"datagram",
115+
"datagrams",
109116
"Datasheet",
110117
"DCD",
111118
"dd",
112119
"de",
113120
"dec",
121+
"Deconflicts",
114122
"deconstructed",
115123
"deduplicated",
116124
"deduplication",
@@ -126,6 +134,7 @@
126134
"dq",
127135
"driverless",
128136
"Dronecode",
137+
"DSCP",
129138
"DSDL",
130139
"DTH",
131140
"DTID",
@@ -145,6 +154,8 @@
145154
"evolvable",
146155
"extensibility",
147156
"extensionpack",
157+
"FFFFU",
158+
"FFFFUL",
148159
"fn",
149160
"foo",
150161
"FOO",
@@ -180,13 +191,15 @@
180191
"IEC",
181192
"IETF",
182193
"iface",
194+
"IGMP",
183195
"ijk",
184196
"imp-lem-en-ta-ti-on-de-fin-ed",
185197
"Implementers",
186198
"incrementing",
187199
"Inkscape",
188200
"intdd",
189201
"integrators",
202+
"internetwork",
190203
"interoperate",
191204
"Intra",
192205
"intravehicular",
@@ -195,6 +208,7 @@
195208
"invariants",
196209
"iostream",
197210
"IP",
211+
"ISCSI",
198212
"JST",
199213
"JTAG",
200214
"kbit",
@@ -220,6 +234,7 @@
220234
"Mbit",
221235
"Mbps",
222236
"MDL",
237+
"memoryview",
223238
"merchantability",
224239
"metadata",
225240
"metaserializable",
@@ -235,6 +250,7 @@
235250
"MTTF",
236251
"MTU",
237252
"mul",
253+
"multicasting",
238254
"mycorrhizal",
239255
"NACK",
240256
"NAK",
@@ -248,6 +264,7 @@
248264
"NMEA",
249265
"NMI",
250266
"nodiscard",
267+
"noexcept",
251268
"nq",
252269
"ns",
253270
"nul",

specification/Cyphal_Specification.tex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,5 +118,6 @@ \section*{Limitation of liability}
118118
\input{transport/transport.tex}
119119
\input{application/application.tex}
120120
\input{sdt/sdt.tex}
121+
\input{appendices/appendices.tex}
121122

122123
\end{document}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
\appendix
2+
\input{appendices/crc.tex}

specification/appendices/crc.tex

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
\chapter{CRC algorithm implementations}
2+
3+
\section{CRC-16/CCITT-FALSE}\label{sec:appendix_crc16ccitt_false}
4+
5+
This algorithm is also known as CRC-16/AUTOSAR or CRC-16/IBM-3740.
6+
Not to be confused with CRC-16/KERMIT.
7+
8+
This algorithm has the following parameters:
9+
\begin{itemize}
10+
\item width: 16 bits;
11+
\item polynomial: $\mathrm{1021}_{16}$;
12+
\item initial value: $\mathrm{FFFF}_{16}$;
13+
\item input not reflected;
14+
\item output not reflected;
15+
\item no output XOR;
16+
\item the native byte order is big endian.
17+
\end{itemize}
18+
19+
The value for the input sequence $\left(49, 50, \ldots, 56, 57\right)$ is $\mathrm{29B1}_{16}$.
20+
21+
\subsection{C++, bitwise}
22+
23+
\begin{samepage}
24+
\begin{minted}{cpp}
25+
#include <array>
26+
#include <cstdint>
27+
#include <cstddef>
28+
29+
class CRC16_CCITT_False final
30+
{
31+
public:
32+
void add(const std::uint8_t byte)
33+
{
34+
value_ ^= static_cast<std::uint16_t>(byte) << 8U;
35+
for (std::uint8_t bit = 8; bit > 0; --bit)
36+
{
37+
if ((value_ & 0x8000U) != 0)
38+
{
39+
value_ = (value_ << 1U) ^ 0x1021U;
40+
}
41+
else
42+
{
43+
value_ = value_ << 1U;
44+
}
45+
}
46+
}
47+
48+
void add(const std::uint8_t* bytes, std::size_t length)
49+
{
50+
while (length --> 0)
51+
{
52+
add(*bytes++);
53+
}
54+
}
55+
56+
[[nodiscard]] std::uint16_t get() const { return value_; }
57+
58+
[[nodiscard]] std::array<std::uint8_t, 2> getBytes() const noexcept
59+
{
60+
const auto x = get();
61+
return {static_cast<std::uint8_t>(x >> 8U), static_cast<std::uint8_t>(x & 0xFFU)};
62+
}
63+
64+
private:
65+
std::uint16_t value_ = 0xFFFFU;
66+
};
67+
\end{minted}
68+
\end{samepage}
69+
70+
\subsection{Python, bytewise}
71+
72+
\begin{samepage}
73+
\begin{minted}{python}
74+
class CRC16CCITT:
75+
def __init__(self) -> None:
76+
self._value = 0xFFFF
77+
78+
def add(self, data: bytes | bytearray | memoryview) -> None:
79+
val = self._value
80+
for x in data:
81+
val = ((val << 8) & 0xFFFF) ^ self._TABLE[(val >> 8) ^ x]
82+
self._value = val
83+
84+
def check_residue(self) -> bool:
85+
return self._value == 0
86+
87+
@property
88+
def value(self) -> int:
89+
return self._value
90+
91+
@property
92+
def value_as_bytes(self) -> bytes:
93+
return self.value.to_bytes(2, "big")
94+
95+
_TABLE = [
96+
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
97+
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
98+
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
99+
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
100+
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
101+
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
102+
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
103+
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
104+
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
105+
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
106+
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
107+
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
108+
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
109+
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
110+
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
111+
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
112+
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
113+
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
114+
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
115+
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
116+
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
117+
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
118+
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
119+
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
120+
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
121+
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
122+
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
123+
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
124+
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
125+
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
126+
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
127+
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0,
128+
]
129+
\end{minted}
130+
\end{samepage}
131+
132+
\newpage
133+
\section{CRC-32C}\label{sec:appendix_crc32c}
134+
135+
This algorithm is also known as CRC-32/ISCSI, CRC-32/CASTAGNOLI, CRC-32/BASE91-C, or CRC-32/INTERLAKEN.
136+
137+
This algorithm has the following parameters:
138+
\begin{itemize}
139+
\item width: 32 bits;
140+
\item polynomial: $\mathrm{1EDC6F41}_{16}$;
141+
\item initial value: $\mathrm{FFFFFFFF}_{16}$;
142+
\item input reflected;
143+
\item output reflected;
144+
\item output XOR: $\mathrm{FFFFFFFF}_{16}$;
145+
\item residue: $\mathrm{B798B438}_{16}$ before output XOR, $\mathrm{48674BC7}_{16}$ after output XOR;
146+
\item the native byte order is little endian.
147+
\end{itemize}
148+
149+
The value for the input sequence $\left(49, 50, \ldots, 56, 57\right)$ is $\mathrm{E3069283}_{16}$.
150+
151+
\subsection{C++, bitwise}
152+
153+
\begin{samepage}
154+
\begin{minted}{cpp}
155+
#include <array>
156+
#include <cstdint>
157+
#include <cstddef>
158+
159+
class CRC32C final
160+
{
161+
public:
162+
static constexpr std::size_t Size = 4;
163+
164+
void update(const std::uint8_t b) noexcept
165+
{
166+
value_ ^= static_cast<std::uint32_t>(b);
167+
for (auto i = 0U; i < 8U; i++)
168+
{
169+
value_ = ((value_ & 1U) != 0) ? ((value_ >> 1U) ^ ReflectedPoly) : (value_ >> 1U);
170+
}
171+
}
172+
173+
[[nodiscard]] std::uint32_t get() const noexcept { return value_ ^ Xor; }
174+
175+
[[nodiscard]] std::array<std::uint8_t, Size> getBytes() const noexcept
176+
{
177+
const auto x = get();
178+
return {
179+
static_cast<std::uint8_t>(x >> (8U * 0U)),
180+
static_cast<std::uint8_t>(x >> (8U * 1U)),
181+
static_cast<std::uint8_t>(x >> (8U * 2U)),
182+
static_cast<std::uint8_t>(x >> (8U * 3U)),
183+
};
184+
}
185+
186+
[[nodiscard]] auto isResidueCorrect() const noexcept { return value_ == Residue; }
187+
188+
private:
189+
static constexpr std::uint32_t Xor = 0xFFFF'FFFFUL;
190+
static constexpr std::uint32_t ReflectedPoly = 0x82F6'3B78UL;
191+
static constexpr std::uint32_t Residue = 0xB798'B438UL;
192+
193+
std::uint32_t value_ = Xor;
194+
};
195+
\end{minted}
196+
\end{samepage}
197+
198+
\subsection{Python, bytewise}
199+
200+
\begin{samepage}
201+
\begin{minted}{python}
202+
class CRC32C:
203+
def __init__(self) -> None:
204+
self._value = 0xFFFFFFFF
205+
206+
def add(self, data: bytes | bytearray | memoryview) -> None:
207+
val = self._value
208+
for x in data:
209+
val = (val >> 8) ^ self._TABLE[x ^ (val & 0xFF)]
210+
self._value = val
211+
212+
def check_residue(self) -> bool:
213+
return self._value == 0xB798B438 # Checked before the output XOR is applied.
214+
215+
@property
216+
def value(self) -> int:
217+
return self._value ^ 0xFFFFFFFF
218+
219+
@property
220+
def value_as_bytes(self) -> bytes:
221+
return self.value.to_bytes(4, "little")
222+
223+
_TABLE = [
224+
0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
225+
0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
226+
0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
227+
0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
228+
0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
229+
0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
230+
0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
231+
0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
232+
0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
233+
0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
234+
0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
235+
0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
236+
0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
237+
0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
238+
0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
239+
0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
240+
0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
241+
0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
242+
0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
243+
0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
244+
0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
245+
0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
246+
0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
247+
0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
248+
0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
249+
0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
250+
0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
251+
0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
252+
0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
253+
0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
254+
0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
255+
0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351,
256+
]
257+
\end{minted}
258+
\end{samepage}

specification/application/functions.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ \subsection{Internet/LAN forwarding interface}
302302

303303
\DSDL{uavcan.internet.* --index-only}
304304

305-
\subsection{Meta-transport}
305+
\subsection{Meta-transport}\label{sec:application_functions_metatransport}
306306

307307
Data types defined in the namespace \DSDLReference{uavcan.metatransport}
308308
(see table~\ref{table:dsdl:uavcan.metatransport})

0 commit comments

Comments
 (0)