Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
TractionModemDefs.hxx
1
34#ifndef _TRACTIONMODEM_TRACTIONMODEMDEFS_HXX_
35#define _TRACTIONMODEM_TRACTIONMODEMDEFS_HXX_
36
37#include <string>
38
39#include "openlcb/Velocity.hxx"
40#include "utils/Crc.hxx"
41
42namespace traction_modem
43{
44
46struct Defs
47{
48 using Payload = std::string;
49
51 static constexpr uint32_t PREAMBLE = 0x41d2c37a;
53 static constexpr char PREAMBLE_FIRST = 0x41;
54
57 static constexpr uint16_t RESPONSE = 0x8000;
58
103
105 static constexpr unsigned LEN_HEADER = 4+2+2;
106
109 static constexpr unsigned LEN_BASE = 14;
111 static constexpr unsigned LEN_FN_SET = 6;
113 static constexpr unsigned LEN_SPEED_SET = 1;
115 static constexpr unsigned LEN_ESTOP_SET = 0;
117 static constexpr unsigned LEN_WIRELESS_PRESENT = 1;
119 static constexpr unsigned LEN_MEM_R = 6;
121 static constexpr unsigned LEN_MEM_W = 5;
122
124 static constexpr unsigned MAX_LEN = 512;
125
127 static constexpr unsigned OFS_CMD = 4;
129 static constexpr unsigned OFS_LEN = 6;
131 static constexpr unsigned OFS_DATA = 8;
132
134 struct Header
135 {
136 uint32_t preamble_;
137 uint16_t command_;
138 uint16_t length_;
139 };
140
142 struct Message
143 {
145 uint8_t data[0];
146 };
147
148 // CRC definition of a message.
149 struct CRC
150 {
151 union
152 {
153 uint16_t crc[3];
154 struct
155 {
156 uint16_t all_;
157 uint16_t even_;
158 uint16_t odd_;
159 };
160 };
161
165 bool operator==(const CRC &c)
166 {
167 return (all_ == c.all_ && even_ == c.even_ && odd_ == c.odd_);
168 }
169
173 bool operator!=(const CRC &c)
174 {
175 return !(all_ == c.all_ && even_ == c.even_ && odd_ == c.odd_);
176 }
177 };
178
182 static Payload get_wireless_present_payload(bool is_present)
183 {
184 Payload p;
186 append_uint8(&p, is_present ? 1 : 0);
187
188 append_crc(&p);
189 return p;
190 }
191
196 static Payload get_fn_set_payload(unsigned fn, uint16_t value)
197 {
198 Payload p;
200 append_uint32(&p, fn);
201 append_uint16(&p, value);
202
203 append_crc(&p);
204 return p;
205 }
206
211 {
212 Payload p;
214 append_uint8(&p, v.get_dcc_128());
215
216 append_crc(&p);
217 return p;
218 }
219
222 static Payload get_estop_payload()
223 {
224 Payload p;
226 // no data in the payload
227 append_crc(&p);
228 return p;
229 }
230
236 static Payload get_memr_payload(
237 uint8_t space, uint32_t address, uint8_t count)
238 {
239 Payload p;
241 append_uint32(&p, address);
242 append_uint8(&p, space);
243 append_uint8(&p, count);
244
245 append_crc(&p);
246 return p;
247 }
248
254 static Payload get_memw_payload(
255 uint8_t space, uint32_t address, const std::string& data)
256 {
257 return get_memw_payload(space, address, (const uint8_t*)data.data(), data.size());
258 }
259
266 static Payload get_memw_payload(
267 uint8_t space, uint32_t address, const uint8_t* buf, size_t count)
268 {
269 Payload p;
270 prepare(&p, CMD_MEM_W, LEN_MEM_W + count);
271 append_uint32(&p, address);
272 append_uint8(&p, space);
273 p.append((char*)buf, count);
274
275 append_crc(&p);
276 return p;
277 }
278
282 static void append_uint32(Payload *p, uint32_t v)
283 {
284 p->push_back(v >> 24);
285 p->push_back((v >> 16) & 0xff);
286 p->push_back((v >> 8) & 0xff);
287 p->push_back((v)&0xff);
288 }
289
293 static void append_uint16(Payload *p, uint16_t v)
294 {
295 p->push_back((v >> 8) & 0xff);
296 p->push_back((v)&0xff);
297 }
298
302 static void append_uint8(Payload *p, uint8_t v)
303 {
304 p->push_back((v)&0xff);
305 }
306
311 static void prepare(Payload *p, Command cmd, uint16_t len)
312 {
313 p->reserve(LEN_BASE + len);
315 append_uint16(p, cmd);
316 append_uint16(p, len);
317 }
318
322 static void append_crc(Payload *p)
323 {
324 CRC crc;
325 crc3_crc16_ccitt(p->data() + sizeof(uint32_t),
326 p->size() - sizeof(uint32_t), crc.crc);
327 append_uint16(p, crc.all_);
328 append_uint16(p, crc.even_);
329 append_uint16(p, crc.odd_);
330 }
331
336 static uint32_t get_uint32(const Payload &p, unsigned ofs)
337 {
338 uint32_t ret;
339 if ((ofs + 4) <= p.size())
340 {
341 memcpy(&ret, p.data() + ofs, 4);
342 return be32toh(ret);
343 }
344 return 0;
345 }
346
351 static uint16_t get_uint16(const Payload &p, unsigned ofs)
352 {
353 uint16_t ret;
354 if ((ofs + 2) <= p.size())
355 {
356 memcpy(&ret, p.data() + ofs, 2);
357 return be16toh(ret);
358 }
359 return 0;
360 }
361
368 static const CRC get_crc(const Payload &p, uint16_t length)
369 {
370 CRC result;
371 result.all_ = get_uint16(p, length + sizeof(Header));
372 result.even_ = get_uint16(p, length + sizeof(Header) + 2);
373 result.odd_ = get_uint16(p, length + sizeof(Header) + 4);
374 return result;
375 }
376
382 static bool is_valid(const Payload &p)
383 {
384 if (get_uint32(p, 0) != PREAMBLE)
385 {
386 return false;
387 }
388 uint16_t len = get_uint16(p, OFS_LEN);
389 if ((p.size() != LEN_BASE + len) || len > MAX_LEN)
390 {
391 return false;
392 }
393 return true;
394 }
395}; // struct Defs
396
397} // namespace traction_modem
398
399#endif // _TRACTIONMODEM_TRACTIONMODEMDEFS_HXX_
static void crc3_crc16_ccitt(const void *data, size_t length_bytes, uint16_t checksum[3])
Computes the triple-CRC value over a chunk of data.
Definition Crc.hxx:325
This class provides a mechanism for working with velocity in different forms.
Definition Velocity.hxx:73
uint8_t get_dcc_128()
Get the speed in DCC 128 speed step format.
Definition Velocity.cxx:48
bool operator!=(const CRC &c)
Overload != operator.
bool operator==(const CRC &c)
Overload == operator.
uint16_t even_
CRC of even bytes.
uint16_t odd_
CRC of odd bytes.
uint16_t all_
CRC of all bytes.
uint16_t command_
message command
uint32_t preamble_
packet preamble
The definition of a message.
uint8_t data[0]
start of the message data
Useful definitions for the traction modem.
static const CRC get_crc(const Payload &p, uint16_t length)
Extract the CRC value(s) from a given payload.
static void append_uint32(Payload *p, uint32_t v)
Appends an uint32_t in network byte order to the payload.
static bool is_valid(const Payload &p)
Verifies that a given payload is a valid packet.
static uint16_t get_uint16(const Payload &p, unsigned ofs)
Extract uint16_t value from a given offset in a wire formatted payload.
static constexpr unsigned MAX_LEN
Maximum allowed len value.
static constexpr unsigned LEN_HEADER
Length of a the header. 4 bytes preamble, 2 bytes cmd, 2 bytes length.
static constexpr unsigned LEN_MEM_R
Length of the data payload of a set estop packet.
@ RESP_ESTOP_SET
emergency stop response
@ CMD_ESTOP_SET
emergency stop request
@ CMD_SPEED_QUERY
query current speed
@ CMD_NOP
no-operation (do nothing)
@ CMD_FN_QUERY
query function status
@ CMD_WIRELESS_PRESENT
wireless present
@ RESP_MEM_R
memory read response
@ RESP_SPEED_QUERY
query current speed response
@ RESP_SPEED_SET
set velocity response
@ RESP_WIRELESS_PRESENT
wireless present response
@ CMD_BAUD_RATE_QUERY
query the supported baud rates
@ RESP_FN_SET
set function response
@ RESP_BAUD_RATE_QUERY
baud rate query response
@ RESP_DC_DCC_PRESENT
DC/DCC present response.
@ RESP_MEM_W
memory write response
@ CMD_BAUD_RATE_REQUEST
request a specific baud rate
@ RESP_FN_QUERY
query function status response
@ CMD_DC_DCC_PRESENT
DC/DCC present.
static constexpr unsigned OFS_LEN
Offset of the length in the packet.
static Payload get_speed_set_payload(openlcb::Velocity v)
Computes payload to set speed and direction.
static Payload get_memw_payload(uint8_t space, uint32_t address, const uint8_t *buf, size_t count)
Computes payload to write some data.
static Payload get_memr_payload(uint8_t space, uint32_t address, uint8_t count)
Computes payload to read some data.
static constexpr uint32_t PREAMBLE
Every command starts with these bytes.
static constexpr unsigned OFS_CMD
Offset of the command in the packet.
static Payload get_wireless_present_payload(bool is_present)
Computes payload for the wireless present message.
static constexpr unsigned LEN_ESTOP_SET
Length of the data payload of a set estop packet.
static constexpr unsigned LEN_BASE
Length of a zero-payload packet.
static constexpr unsigned LEN_WIRELESS_PRESENT
Length of the data payload of a wireless present packet.
static void append_crc(Payload *p)
Computes and appends the CRC to the payload.
static Payload get_fn_set_payload(unsigned fn, uint16_t value)
Computes payload to set a function.
static constexpr unsigned LEN_SPEED_SET
Length of the data payload of a set speed packet.
static void prepare(Payload *p, Command cmd, uint16_t len)
Prepares the header of a packet.
static constexpr unsigned OFS_DATA
Offset of the first data byte in the packet.
static constexpr unsigned LEN_FN_SET
Length of the data payload of a set function packet.
static uint32_t get_uint32(const Payload &p, unsigned ofs)
Extract uint32_t value from a given offset in a wire formatted payload.
static Payload get_estop_payload()
Computes payload to set estop.
static constexpr uint16_t RESPONSE
The most significant bit of each command means "response" to a previous message.
static constexpr unsigned LEN_MEM_W
Base length of the data, add the number of payload bytes.
static constexpr char PREAMBLE_FIRST
First byte of the preamble.
static void append_uint8(Payload *p, uint8_t v)
Appends an uint8_t to the payload.
static Payload get_memw_payload(uint8_t space, uint32_t address, const std::string &data)
Computes payload to write some data.
static void append_uint16(Payload *p, uint16_t v)
Appends an uint16_t in network byte order to the payload.