9#include <power_frame_msg_platformio.h>
11#include "proto/message_translation/power_frame_msg.hpp"
14#include "proto/power_frame_msg.nanopb.h"
18const uint8_t START_END_FLAG_BYTE = 0x00;
29 uint16_t crc16(
const std::vector<uint8_t>& data, uint16_t length)
32 uint16_t crc = 0xFFFF;
37 x =
static_cast<uint8_t
>(crc >> 8u) ^ data[i++];
38 x ^=
static_cast<uint8_t
>(x >> 4u);
39 crc =
static_cast<uint16_t
>((crc << 8u) ^ (x << 12u) ^ (x << 5u) ^ x);
52 bool verifyLengthAndCrc(
const TbotsProto_PowerFrame& frame)
54 uint16_t expected_length;
55 std::vector<uint8_t> bytes;
56 switch (frame.which_power_msg)
58 case TbotsProto_PowerFrame_power_control_tag:
59 expected_length = TbotsProto_PowerPulseControl_size;
60 bytes = serializeToVector(frame.power_msg.power_control);
62 case TbotsProto_PowerFrame_power_status_tag:
63 expected_length = TbotsProto_PowerStatus_size;
64 bytes = serializeToVector(frame.power_msg.power_status);
69 uint16_t expected_crc = crc16(bytes,
static_cast<uint16_t
>(frame.length));
70 return frame.crc == expected_crc && frame.length == expected_length;
82 std::vector<uint8_t> cobsEncoding(
const std::vector<uint8_t>& to_encode)
84 auto encoded = std::vector<uint8_t>();
85 encoded.emplace_back(START_END_FLAG_BYTE);
87 size_t overhead_location = 1;
88 uint8_t overhead = 0x01;
90 for (
auto byte : to_encode)
92 if (
byte == START_END_FLAG_BYTE)
94 encoded.insert(encoded.begin() + overhead_location, overhead);
95 overhead_location = encoded.size();
100 encoded.emplace_back(
byte);
101 if (++overhead == 0xFF)
103 encoded.insert(encoded.begin() + overhead_location, overhead);
104 overhead_location = encoded.size();
109 encoded.insert(encoded.begin() + overhead_location, overhead);
110 encoded.emplace_back(START_END_FLAG_BYTE);
126 bool cobsDecoding(
const std::vector<uint8_t>& to_decode,
127 std::vector<uint8_t>& decoded)
129 if (to_decode.front() != START_END_FLAG_BYTE ||
130 to_decode.back() != START_END_FLAG_BYTE)
136 while (i < to_decode.size())
138 uint8_t overhead = to_decode[i++];
140 if (overhead + i > to_decode.size())
146 if (overhead == START_END_FLAG_BYTE && i != to_decode.size())
150 for (uint16_t j = 1; i < to_decode.size() && j < overhead; j++)
152 decoded.emplace_back(to_decode[i++]);
154 if (overhead < 0xFF && i != to_decode.size() - 1 &&
155 overhead != START_END_FLAG_BYTE)
157 decoded.emplace_back(START_END_FLAG_BYTE);
174TbotsProto_PowerFrame createUartFrame(
const T& power_msg)
176 TbotsProto_PowerFrame frame = TbotsProto_PowerFrame_init_default;
177 auto buffer = serializeToVector(power_msg);
178 frame.length =
static_cast<uint32_t
>(buffer.size());
179 frame.crc = crc16(buffer,
static_cast<uint16_t
>(frame.length));
180 setPowerMsg(frame, power_msg);
191std::vector<uint8_t>
inline marshallUartPacket(
const TbotsProto_PowerFrame& frame)
193 auto bytes = serializeToVector(frame);
194 return cobsEncoding(bytes);
205bool inline unmarshalUartPacket(
const std::vector<uint8_t>& data,
206 TbotsProto_PowerFrame& frame)
208 std::vector<uint8_t> decoded;
209 if (!cobsDecoding(data, decoded))
213 if (decoded.size() != TbotsProto_PowerFrame_size)
217 frame = TbotsProto_PowerFrame_init_default;
218 pb_istream_t stream =
219 pb_istream_from_buffer(
static_cast<uint8_t*
>(decoded.data()), decoded.size());
220 if (!pb_decode(&stream, TbotsProto_PowerFrame_fields, &frame))
224 return verifyLengthAndCrc(frame);
235size_t getMarshalledSize(
const T& power_msg)
237 auto frame = createUartFrame(power_msg);
238 auto buffer = serializeToVector(frame);
239 return cobsEncoding(buffer).size();