Skyward boardcore
Loading...
Searching...
No Matches
APIFrames.h
Go to the documentation of this file.
1/* Copyright (c) 2021 Skyward Experimental Rocketry
2 * Author: Luca Erbetta
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#pragma once
24
25#include <interfaces/endianness.h>
26
27#include <algorithm>
28#include <cassert>
29#include <cstdint>
30#include <cstring>
31#include <ostream>
32#include <string>
33#include <type_traits>
34#include <utility>
35
36using std::min;
37using std::string;
38
39namespace Boardcore
40{
41
42namespace Xbee
43{
46static constexpr size_t MIN_RX_PACKET_FRAME_SIZE = 11;
47static constexpr size_t MIN_TX_REQUEST_FRAME_SIZE = 13;
48static constexpr size_t MIN_AT_COMMAND_FRAME_SIZE = 3;
49static constexpr size_t MIN_AT_RESPONSE_FRAME_SIZE = 4;
50
51static constexpr size_t TX_STATUS_FRAME_SIZE = 6;
52static constexpr size_t MODEM_STATUS_FRAME_SIZE = 1;
53
54static constexpr uint16_t MAX_PACKET_PAYLOAD_LENGTH = 256;
55static constexpr uint16_t MAX_AT_COMMAND_PARAMS_LENGTH = 20;
56static constexpr uint16_t MAX_AT_COMMAND_RESPONSE_LENGTH = 30;
57
58static constexpr size_t FRAME_DATA_SIZE =
59 MAX_PACKET_PAYLOAD_LENGTH + MIN_TX_REQUEST_FRAME_SIZE;
60
61static constexpr size_t MAX_API_FRAME_SIZE = FRAME_DATA_SIZE + 5;
62static constexpr size_t MIN_API_FRAME_SIZE = 5;
63
64static constexpr uint64_t ADDRESS_BROADCAST = 0xFFFF;
65static constexpr uint8_t START_DELIMITER = 0x7E;
66
77
89
99
107
121
127
136
137#pragma pack(1)
139{
140 uint8_t startDel = 0x7E;
141 uint16_t length = 0;
142 uint8_t frameType = 0;
143 uint8_t frameData[FRAME_DATA_SIZE];
144
145 uint8_t checksum = 0;
146 // Used for logging, not part of the standard Xbee API Frame
147 long long timestamp = 0;
148
149 APIFrame() { memset(frameData, 0, FRAME_DATA_SIZE); }
150
151 uint16_t getFrameDataLength() const
152 {
153 size_t len = swapBytes16(length) - 1;
154
155 return min(len, FRAME_DATA_SIZE);
156 }
157
158 void setFrameDataLength(uint16_t len)
159 {
160 length = swapBytes16(min((size_t)(len + 1), FRAME_DATA_SIZE + 1));
161 }
162
163 bool verifyChecksum() const
164 {
165 // Sum all the bytes including checksum and frame type.
166 // The sum can be stored in a uint8_t since we only care about the least
167 // significant byte.
168 uint8_t sum = checksum + frameType;
169 for (uint16_t i = 0; i < getFrameDataLength(); ++i)
170 sum += frameData[i];
171 return sum == 0xFF;
172 }
173
175 {
177 for (uint16_t i = 0; i < getFrameDataLength(); ++i)
178 checksum += frameData[i];
179
180 checksum = 0xFF - checksum;
181 }
182
183 template <typename FrameType>
185 {
186 static_assert(
187 std::is_base_of<APIFrame, FrameType>::value ||
188 std::is_same<APIFrame, FrameType>::value,
189 "FrameType must be derived from APIFrame or be an APIFrame");
190
191 return reinterpret_cast<FrameType*>(this);
192 }
193
194 size_t toBytes(uint8_t* bytes)
195 {
196 memcpy(bytes, this, 4 + getFrameDataLength());
197
198 bytes[4 + getFrameDataLength()] = checksum;
199 return 5 + getFrameDataLength();
200 }
201
202 static bool fromBytes(uint8_t* bytes, size_t size, APIFrame* f)
203 {
204 if (size >= MIN_API_FRAME_SIZE && size <= MAX_API_FRAME_SIZE)
205 {
206 memcpy(f, bytes, size - 1);
207 f->checksum = bytes[size - 1];
208
209 return true;
210 }
211 return false;
212 }
213};
214#pragma pack()
216{
218 {
220 setFrameDataLength(MIN_AT_COMMAND_FRAME_SIZE);
221 }
222
223 uint8_t getFrameID() const { return frameData[0]; }
224
225 void setFrameID(uint8_t frameId) { frameData[0] = frameId; }
226
227 const char* getATCommand() const
228 {
229 return reinterpret_cast<const char*>(&frameData[1]);
230 }
231
232 void setATCommand(const char* at)
233 {
234 frameData[1] = at[0];
235 frameData[2] = at[1];
236 }
237
238 uint8_t* getCommandDataPointer() { return &frameData[3]; }
239
240 uint16_t getCommandDataLength() const
241 {
242 return getFrameDataLength() - MIN_AT_COMMAND_FRAME_SIZE;
243 }
244
245 void setParameterSize(uint16_t size)
246 {
247 size = min((size_t)size, FRAME_DATA_SIZE - MIN_AT_COMMAND_FRAME_SIZE);
248
249 setFrameDataLength(MIN_AT_COMMAND_FRAME_SIZE + size);
250 }
251};
252static_assert(sizeof(ATCommandFrame) == sizeof(APIFrame),
253 "Size of derived classes must be the same as APIFrame class (no "
254 "additional members & no virtual functions)");
255
257{
259 {
261 setFrameDataLength(MIN_AT_RESPONSE_FRAME_SIZE);
262 }
263
264 uint8_t getFrameID() const { return frameData[0]; }
265
266 void setFrameID(uint8_t frameId) { frameData[0] = frameId; }
267
268 const char* getATCommand() const
269 {
270 return reinterpret_cast<const char*>(&frameData[1]);
271 }
272
273 void setATCommand(const char* at)
274 {
275 frameData[1] = at[0];
276 frameData[2] = at[1];
277 }
278
279 uint8_t getCommandStatus() const { return frameData[3]; }
280
281 void setCommandStatus(uint8_t cs) { frameData[3] = cs; }
282
283 uint8_t* getCommandDataPointer() { return &frameData[4]; }
284
285 uint16_t getCommandDataLength() const
286 {
287 return getFrameDataLength() - MIN_AT_RESPONSE_FRAME_SIZE;
288 }
289
290 void setCommandDataSize(uint16_t size)
291 {
292 size = min((size_t)size, FRAME_DATA_SIZE - MIN_AT_RESPONSE_FRAME_SIZE);
293
294 setFrameDataLength(MIN_AT_RESPONSE_FRAME_SIZE + size);
295 }
296};
297static_assert(sizeof(ATCommandFrame) == sizeof(APIFrame),
298 "Size of derived classes must be the same as APIFrame class (no "
299 "additional members & no virtual functions)");
300
302{
304 {
306 setFrameDataLength(MIN_TX_REQUEST_FRAME_SIZE);
307
308 // Reserved bytes
309 frameData[9] = 0xFF;
310 frameData[10] = 0xFE;
311 }
312
313 uint8_t getFrameID() const { return frameData[0]; }
314
315 void setFrameID(uint8_t frameId) { frameData[0] = frameId; }
316
317 uint64_t getDestAddress() const
318 {
319 uint64_t addr;
320 memcpy(&addr, &frameData[1], sizeof(uint64_t));
321 return swapBytes64(addr);
322 }
323
324 void setDestAddress(uint64_t address)
325 {
326 address = swapBytes64(address);
327 memcpy(&frameData[1], &address, 8);
328 }
329
330 uint8_t getBroadcastRadius() const { return frameData[11]; }
331
332 void setBroadcastRadius(uint8_t br) { frameData[11] = br; }
333
334 uint8_t getTrasmitOptions() const { return frameData[12]; }
335
336 void setTransmitOptions(uint8_t br) { frameData[12] = br; }
337
338 uint8_t* getRFDataPointer() { return &frameData[13]; }
339
340 uint16_t getRFDataLength() const
341 {
342 return min((size_t)(getFrameDataLength() - MIN_TX_REQUEST_FRAME_SIZE),
343 (size_t)MAX_PACKET_PAYLOAD_LENGTH);
344 }
345
346 void setRFDataLength(uint16_t size)
347 {
348 size = min(size, MAX_PACKET_PAYLOAD_LENGTH);
349
350 setFrameDataLength(MIN_TX_REQUEST_FRAME_SIZE + size);
351 }
352};
353static_assert(sizeof(TXRequestFrame) == sizeof(APIFrame),
354 "Size of derived classes must be the same as APIFrame class (no "
355 "additional members & no virtual functions)");
356
358{
360 {
362 setFrameDataLength(MODEM_STATUS_FRAME_SIZE);
363 }
364
365 uint8_t getStatus() const { return frameData[0]; }
366
367 void setStatus(uint8_t status) { frameData[0] = status; }
368};
369static_assert(sizeof(ModemStatusFrame) == sizeof(APIFrame),
370 "Size of derived classes must be the same as APIFrame class (no "
371 "additional members & no virtual functions)");
372
373struct TXStatusFrame : public APIFrame
374{
376 {
378 setFrameDataLength(TX_STATUS_FRAME_SIZE);
379
380 // Reserved bytes
381 frameData[1] = 0xFF;
382 frameData[2] = 0xFE;
383 }
384
385 uint8_t getFrameID() const { return frameData[0]; }
386
387 void setFrameID(uint8_t frameId) { frameData[0] = frameId; }
388
389 uint8_t getTransmitRetryCount() const { return frameData[3]; }
390
391 void setTransmitRetryCount(uint8_t trc) { frameData[3] = trc; }
392
393 uint8_t getDeliveryStatus() const { return frameData[4]; }
394
395 void setDeliveryStatus(uint8_t ds) { frameData[4] = ds; }
396
397 uint8_t getDiscoveryStatus() const { return frameData[5]; }
398
399 void setDiscoveryStatus(uint8_t ds) { frameData[5] = ds; }
400};
401
402static_assert(sizeof(TXStatusFrame) == sizeof(APIFrame),
403 "Size of derived classes must be the same as APIFrame class (no "
404 "additional members & no virtual functions)");
405
406struct RXPacketFrame : public APIFrame
407{
409 {
411 setFrameDataLength(MIN_RX_PACKET_FRAME_SIZE);
412
413 frameData[8] = 0xFF;
414 frameData[9] = 0xFE;
415 }
416
417 uint64_t getSourceAddress() const
418 {
419 uint64_t addr;
420 memcpy(&addr, &frameData[0], sizeof(uint64_t));
421 return swapBytes64(addr);
422 }
423
424 void setSourceAddress(uint64_t address)
425 {
426 address = swapBytes64(address);
427 uint8_t* addr = reinterpret_cast<uint8_t*>(&address);
428
429 memcpy(&frameData[0], addr, 8);
430 }
431
432 uint8_t getReceiveOptions() const { return frameData[10]; }
433
434 void setReceiveOptions(uint8_t ro) { frameData[10] = ro; }
435
436 uint8_t* getRXDataPointer() { return &frameData[11]; }
437
438 uint16_t getRXDataLength() const
439 {
440 return min((size_t)(getFrameDataLength() - MIN_RX_PACKET_FRAME_SIZE),
441 (size_t)MAX_PACKET_PAYLOAD_LENGTH);
442 }
443
444 void setRXDataLength(uint16_t size)
445 {
446 size = min(size, MAX_PACKET_PAYLOAD_LENGTH);
447
448 setFrameDataLength(MIN_RX_PACKET_FRAME_SIZE + size);
449 }
450};
451
452static_assert(sizeof(RXPacketFrame) == sizeof(APIFrame),
453 "Size of derived classes must be the same as APIFrame class (no "
454 "additional members & no virtual functions)");
455} // namespace Xbee
456
457} // namespace Boardcore
@ FTYPE_AT_COMMAND_RESPONSE
Definition APIFrames.h:72
@ DELS_NO_SPECTRUM_AVAILABLE
Definition APIFrames.h:113
This file includes all the types the logdecoder script will decode.
void setFrameDataLength(uint16_t len)
Definition APIFrames.h:158
uint8_t frameData[FRAME_DATA_SIZE]
Definition APIFrames.h:143
size_t toBytes(uint8_t *bytes)
Definition APIFrames.h:194
bool verifyChecksum() const
Definition APIFrames.h:163
FrameType * toFrameType()
Definition APIFrames.h:184
uint16_t getFrameDataLength() const
Definition APIFrames.h:151
static bool fromBytes(uint8_t *bytes, size_t size, APIFrame *f)
Definition APIFrames.h:202
uint16_t getCommandDataLength() const
Definition APIFrames.h:240
void setParameterSize(uint16_t size)
Definition APIFrames.h:245
void setATCommand(const char *at)
Definition APIFrames.h:232
void setFrameID(uint8_t frameId)
Definition APIFrames.h:225
const char * getATCommand() const
Definition APIFrames.h:227
void setStatus(uint8_t status)
Definition APIFrames.h:367
uint64_t getSourceAddress() const
Definition APIFrames.h:417
void setRXDataLength(uint16_t size)
Definition APIFrames.h:444
uint8_t getReceiveOptions() const
Definition APIFrames.h:432
uint16_t getRXDataLength() const
Definition APIFrames.h:438
void setSourceAddress(uint64_t address)
Definition APIFrames.h:424
void setReceiveOptions(uint8_t ro)
Definition APIFrames.h:434
uint16_t getRFDataLength() const
Definition APIFrames.h:340
void setFrameID(uint8_t frameId)
Definition APIFrames.h:315
uint8_t getBroadcastRadius() const
Definition APIFrames.h:330
void setTransmitOptions(uint8_t br)
Definition APIFrames.h:336
void setDestAddress(uint64_t address)
Definition APIFrames.h:324
void setBroadcastRadius(uint8_t br)
Definition APIFrames.h:332
void setRFDataLength(uint16_t size)
Definition APIFrames.h:346
uint8_t getTrasmitOptions() const
Definition APIFrames.h:334
uint64_t getDestAddress() const
Definition APIFrames.h:317
void setDeliveryStatus(uint8_t ds)
Definition APIFrames.h:395
uint8_t getDeliveryStatus() const
Definition APIFrames.h:393
uint8_t getTransmitRetryCount() const
Definition APIFrames.h:389
void setTransmitRetryCount(uint8_t trc)
Definition APIFrames.h:391
uint8_t getDiscoveryStatus() const
Definition APIFrames.h:397
void setFrameID(uint8_t frameId)
Definition APIFrames.h:387
void setDiscoveryStatus(uint8_t ds)
Definition APIFrames.h:399