Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
MemoryConfigDefs.hxx
Go to the documentation of this file.
1
35#ifndef _OPENLCB_MEMORYCONFIGDEFS_HXX_
36#define _OPENLCB_MEMORYCONFIGDEFS_HXX_
37
39#include "openlcb/Defs.hxx"
40#include "utils/macros.h"
41
42namespace openlcb
43{
44
48{
49 using DatagramPayload = string;
50
95
111
115 {
116 AVAIL_WUM = 0x8000,
117 AVAIL_UR = 0x4000,
118 AVAIL_UW = 0x2000,
121 AVAIL_SR = 0x1000,
122 AVAIL_R0xFC = 0x0800,
123 AVAIL_R0xFB = 0x0400,
124 AVAIL_W0xFB = 0x0200,
125 };
126
130 {
131 LENGTH_1 = 0x80,
132 LENGTH_2 = 0x40,
133 LENGTH_4 = 0x20,
134 LENGTH_63 = 0x10,
137 };
138
141 enum flags
142 {
143 FLAG_RO = 0x01,
144 FLAG_NZLA = 0x02,
145 };
146
147 enum errors
148 {
149 ERROR_SPACE_NOT_KNOWN = Defs::ERROR_INVALID_ARGS | 0x0001,
150 ERROR_OUT_OF_BOUNDS = Defs::ERROR_INVALID_ARGS | 0x0002,
151 ERROR_WRITE_TO_RO = Defs::ERROR_INVALID_ARGS | 0x0003,
152 };
153
154 static constexpr unsigned MAX_DATAGRAM_RW_BYTES = 64;
155
156 static bool is_special_space(uint8_t space)
157 {
158 return space > SPACE_SPECIAL;
159 }
160
161 static DatagramPayload write_datagram(
162 uint8_t space, uint32_t offset, const string &data = "")
163 {
164 DatagramPayload p;
165 p.reserve(7 + data.size());
166 p.push_back(DatagramDefs::CONFIGURATION);
167 p.push_back(COMMAND_WRITE);
168 p.push_back(0xff & (offset >> 24));
169 p.push_back(0xff & (offset >> 16));
170 p.push_back(0xff & (offset >> 8));
171 p.push_back(0xff & (offset));
172 if (is_special_space(space))
173 {
174 p[1] |= space & ~SPACE_SPECIAL;
175 }
176 else
177 {
178 p.push_back(space);
179 }
180 p += data;
181 return p;
182 }
183
184 static DatagramPayload read_datagram(
185 uint8_t space, uint32_t offset, uint8_t length)
186 {
187 DatagramPayload p;
188 p.reserve(7);
189 p.push_back(DatagramDefs::CONFIGURATION);
190 p.push_back(COMMAND_READ);
191 p.push_back(0xff & (offset >> 24));
192 p.push_back(0xff & (offset >> 16));
193 p.push_back(0xff & (offset >> 8));
194 p.push_back(0xff & (offset));
195 if (is_special_space(space))
196 {
197 p[1] |= space & ~SPACE_SPECIAL;
198 }
199 else
200 {
201 p.push_back(space);
202 }
203 p.push_back(length);
204 return p;
205 }
206
207 static DatagramPayload read_stream_datagram(uint8_t space, uint32_t offset,
208 uint8_t dst_stream_id, uint32_t length = 0xFFFFFFFF)
209 {
210 DatagramPayload p;
211 p.reserve(13);
212 p.push_back(DatagramDefs::CONFIGURATION);
213 p.push_back(COMMAND_READ_STREAM);
214 p.push_back(0xff & (offset >> 24));
215 p.push_back(0xff & (offset >> 16));
216 p.push_back(0xff & (offset >> 8));
217 p.push_back(0xff & (offset));
218 if (is_special_space(space))
219 {
220 p[1] |= space & ~SPACE_SPECIAL;
221 }
222 else
223 {
224 p.push_back(space);
225 }
226 p.push_back(0xff); // src ID
227 p.push_back(dst_stream_id); // dst ID
228 p.push_back(0xff & (length >> 24));
229 p.push_back(0xff & (length >> 16));
230 p.push_back(0xff & (length >> 8));
231 p.push_back(0xff & (length));
232 return p;
233 }
234
242 const DatagramPayload &payload, unsigned extra)
243 {
244 auto *bytes = payload_bytes(payload);
245 size_t sz = payload.size();
246 if (sz < 6 + extra)
247 {
248 return false;
249 }
250 if (((bytes[1] & COMMAND_FLAG_MASK) == 0) && (sz < 7 + extra))
251 {
252 return false;
253 }
254 return true;
255 }
256
259 static uint8_t get_space(const DatagramPayload &payload)
260 {
261 auto *bytes = payload_bytes(payload);
262 if (bytes[1] & COMMAND_FLAG_MASK)
263 {
264 return COMMAND_MASK + (bytes[1] & COMMAND_FLAG_MASK);
265 }
266 return bytes[6];
267 }
268
269 static unsigned get_payload_offset(const DatagramPayload &payload)
270 {
271 auto *bytes = payload_bytes(payload);
272 if (bytes[1] & COMMAND_FLAG_MASK)
273 {
274 return 6;
275 }
276 else
277 {
278 return 7;
279 }
280 }
281
284 static uint32_t get_address(const DatagramPayload &payload)
285 {
286 auto *bytes = payload_bytes(payload);
287 uint32_t a = bytes[2];
288 a <<= 8;
289 a |= bytes[3];
290 a <<= 8;
291 a |= bytes[4];
292 a <<= 8;
293 a |= bytes[5];
294 return a;
295 }
296
300 static const uint8_t *payload_bytes(const DatagramPayload &payload)
301 {
302 return (uint8_t *)payload.data();
303 }
304
305private:
308};
309
310} // namespace openlcb
311
312#endif // _OPENLCB_MEMORYCONFIGDEFS_HXX_
Payload DatagramPayload
Contents of a Datagram message.
Definition Datagram.hxx:51
@ CONFIGURATION
configuration message
Static constants and helper functions related to the Memory Configuration Protocol.
flags
Possible address space information flags.
@ FLAG_NZLA
space has a nonzero low address
available
Possible available options.
@ AVAIL_UW
unaligned writes supported
@ AVAIL_R0xFB
read from adddress space 0xFB available
@ AVAIL_SR
stream reads supported
@ AVAIL_W0xFB
write from adddress space 0xFB available
@ AVAIL_WUM
write under mask supported
@ AVAIL_R0xFC
read from adddress space 0xFC available
@ AVAIL_UR
unaligned reads supported
commands
Possible Commands for a configuration datagram.
@ COMMAND_WRITE_STREAM_FAILED
failed to write data using a stream
@ COMMAND_LOCK_REPLY
unlock the configuration space
@ COMMAND_READ_STREAM
command to read data using a stream
@ COMMAND_READ_REPLY
reply to read data from address space
@ COMMAND_RESET
reset node to its power on state
@ COMMAND_READ_STREAM_FAILED
failed to read data using a stream
@ COMMAND_READ
command to read data from address space
@ COMMAND_WRITE_UNDER_MASK
command to write data under mask
@ COMMAND_UNFREEZE
unfreeze operation of node
@ COMMAND_FREEZE
freeze operation of node
@ COMMAND_LOCK
lock the configuration space
@ COMMAND_UPDATE_COMPLETE
indicate that a sequence of commands is complete
@ COMMAND_WRITE
command to write data to address space
@ COMMAND_WRITE_STREAM
command to write data using a stream
@ COMMAND_UNIQUE_ID_REPLY
node unique id
@ COMMAND_FACTORY_RESET
reset node to factory defaults
@ COMMAND_REPLY_BIT_FOR_RW
This bit is present in REPLY commands for read-write commands.
@ COMMAND_WRITE_STREAM_REPLY
reply to write data using a stream
@ COMMAND_WRITE_REPLY
reply to write data to address space
@ COMMAND_READ_FAILED
failed to read data from address space
@ COMMAND_READ_STREAM_REPLY
reply to read data using a stream
@ COMMAND_UNIQUE_ID
ask for a node unique id
@ COMMAND_ENTER_BOOTLOADER
reset node in bootloader mode
@ COMMAND_PRESENT_MASK
mask for address space present bit
@ COMMAND_CDI
flags for a CDI space
@ COMMAND_PRESENT
address space is present
@ COMMAND_ALL_MEMORY
flags for an all memory space
@ COMMAND_WRITE_FAILED
failed to write data to address space
@ COMMAND_MAX_FOR_RW
command <= this value have fixed bit arrangement.
@ COMMAND_FLAG_MASK
mask for special memory space flags
@ COMMAND_CONFIG
flags for a config memory space
lengths
Possible supported write lengths.
@ LENGTH_2
write length of 2 supported
@ LENGTH_4
write length of 4 supported
@ LENGTH_1
write length of 1 supported
@ LENGTH_STREAM
stream writes supported
@ LENGTH_ARBITRARY
arbitrary write of any length supported
@ LENGTH_63
write length of 64 supported
static bool payload_min_length_check(const DatagramPayload &payload, unsigned extra)
spaces
Possible memory spaces.
@ SPACE_DCC_CV
proxy space for DCC functions
@ SPACE_SPECIAL
offset for the special memory spaces
@ SPACE_FDI
read-only for function definition XML
@ SPACE_FIRMWARE
firmware upgrade space
@ SPACE_ALL_MEMORY
all memory space
@ SPACE_ACDI_USR
read-write ACDI space
@ SPACE_CONFIG
config memory space
@ SPACE_FUNCTION
read-write for function data
@ SPACE_ACDI_SYS
read-only ACDI space
static const uint8_t * payload_bytes(const DatagramPayload &payload)
Type casts a DatagramPayload to an array of bytes.
static uint32_t get_address(const DatagramPayload &payload)
static uint8_t get_space(const DatagramPayload &payload)
MemoryConfigDefs()
Do not instantiate this class.