STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
frame.cpp
Go to the documentation of this file.
1#include "frame.h"
2
3#include <string.h>
4
5namespace radio_link {
6
7void put_u16(uint8_t* p, uint16_t v) {
8 p[0] = static_cast<uint8_t>(v & 0xFFu);
9 p[1] = static_cast<uint8_t>(v >> 8);
10}
11
12void put_u32(uint8_t* p, uint32_t v) {
13 p[0] = static_cast<uint8_t>(v & 0xFFu);
14 p[1] = static_cast<uint8_t>((v >> 8) & 0xFFu);
15 p[2] = static_cast<uint8_t>((v >> 16) & 0xFFu);
16 p[3] = static_cast<uint8_t>(v >> 24);
17}
18
19uint16_t get_u16(const uint8_t* p) {
20 return static_cast<uint16_t>(static_cast<uint16_t>(p[0]) |
21 (static_cast<uint16_t>(p[1]) << 8));
22}
23
24uint32_t get_u32(const uint8_t* p) {
25 return static_cast<uint32_t>(p[0]) | (static_cast<uint32_t>(p[1]) << 8) |
26 (static_cast<uint32_t>(p[2]) << 16) |
27 (static_cast<uint32_t>(p[3]) << 24);
28}
29
30uint16_t crc16(const uint8_t* data, size_t len) {
31 uint16_t crc = 0xFFFFu;
32 for (size_t i = 0; i < len; i++) {
33 crc ^= static_cast<uint16_t>(static_cast<uint16_t>(data[i]) << 8);
34 for (int b = 0; b < 8; b++) {
35 const uint16_t shifted = static_cast<uint16_t>(crc << 1);
36 crc = (crc & 0x8000u) ? static_cast<uint16_t>(shifted ^ 0x1021u)
37 : shifted;
38 }
39 }
40 return crc;
41}
42
43namespace {
44
45// Expected payload length for a type byte, or -1 if the type is unknown.
46int payload_len_for(uint8_t type) {
47 switch (static_cast<FrameType>(type)) {
49 return kHeartbeatLen;
51 return kSelfTestLen;
52 case FrameType::Arm:
53 return kArmLen;
55 return kUnArmLen;
56 default:
57 return -1;
58 }
59}
60
61} // namespace
62
63FrameStatus decode_frame(const uint8_t* buf, size_t len, Frame& out) {
64 if (buf == nullptr) {
66 }
67 if (len < kFrameOverhead) {
69 }
70 if (buf[0] != kFrameVersion) {
72 }
73 const uint8_t plen = buf[4];
74 // The length field must account for every byte we received, exactly.
75 if (plen > kFrameMaxPayload || len != kFrameOverhead + plen) {
77 }
78 const size_t body = kFrameHeaderLen + plen;
79 if (crc16(buf, body) != get_u16(buf + body)) {
81 }
82 const int want = payload_len_for(buf[1]);
83 if (want < 0) {
85 }
86 if (static_cast<int>(plen) != want) {
88 }
89 out.type = static_cast<FrameType>(buf[1]);
90 out.seq = get_u16(buf + 2);
91 out.payload_len = plen;
92 memcpy(out.payload, buf + kFrameHeaderLen, plen);
93 return FrameStatus::Ok;
94}
95
96FrameStatus encode_frame(FrameType type, uint16_t seq, const uint8_t* payload,
97 uint8_t payload_len, uint8_t* out, size_t out_cap,
98 size_t& out_len) {
99 if (out == nullptr || (payload == nullptr && payload_len > 0)) {
101 }
102 const int want = payload_len_for(static_cast<uint8_t>(type));
103 if (want < 0) {
105 }
106 if (static_cast<int>(payload_len) != want) {
108 }
109 const size_t total = kFrameOverhead + payload_len;
110 if (out_cap < total) {
112 }
113 out[0] = kFrameVersion;
114 out[1] = static_cast<uint8_t>(type);
115 put_u16(out + 2, seq);
116 out[4] = payload_len;
117 if (payload_len > 0) {
118 memcpy(out + kFrameHeaderLen, payload, payload_len);
119 }
120 const size_t body = kFrameHeaderLen + payload_len;
121 put_u16(out + body, crc16(out, body));
122 out_len = total;
123 return FrameStatus::Ok;
124}
125
126} // namespace radio_link
int32_t p
Definition flight_e2e.c:78
Over-the-air frame format for the LoRa command link.
*brief create JSON pointer *sa reference_tokens const string_t const string_t & b
Definition json.hpp:13878