blob: a776cdd464ee63bb86547782ba6313fc5ee1f8d0 [file] [log] [blame]
Brian Silvermanbfbbe872019-02-10 18:00:57 -08001#include "y2019/jevois/uart.h"
2
Brian Silverman2eb89762019-02-17 15:16:37 -08003#include <array>
4
5#include "aos/logging/logging.h"
6#include "aos/util/bitpacking.h"
7#include "third_party/GSL/include/gsl/gsl"
8#include "y2019/jevois/jevois_crc.h"
9
Brian Silvermanbfbbe872019-02-10 18:00:57 -080010namespace frc971 {
11namespace jevois {
12
Brian Silverman2eb89762019-02-17 15:16:37 -080013UartToTeensyBuffer UartPackToTeensy(const Frame &message) {
14 std::array<char, uart_to_teensy_size()> buffer;
15 gsl::span<char> remaining_space = buffer;
16 for (int i = 0; i < 3; ++i) {
17 memcpy(remaining_space.data(), &message.targets[i].distance, sizeof(float));
18 remaining_space = remaining_space.subspan(sizeof(float));
19 memcpy(remaining_space.data(), &message.targets[i].height, sizeof(float));
20 remaining_space = remaining_space.subspan(sizeof(float));
21 memcpy(remaining_space.data(), &message.targets[i].heading, sizeof(float));
22 remaining_space = remaining_space.subspan(sizeof(float));
23 memcpy(remaining_space.data(), &message.targets[i].skew, sizeof(float));
24 remaining_space = remaining_space.subspan(sizeof(float));
25 }
26 remaining_space[0] = message.age.count();
27 remaining_space = remaining_space.subspan(1);
28 {
29 uint16_t crc = jevois_crc_init();
30 crc = jevois_crc_update(crc, buffer.data(),
31 buffer.size() - remaining_space.size());
32 crc = jevois_crc_finalize(crc);
33 CHECK_GE(static_cast<size_t>(remaining_space.size()), sizeof(crc));
34 memcpy(&remaining_space[0], &crc, sizeof(crc));
35 remaining_space = remaining_space.subspan(sizeof(crc));
36 }
37 CHECK(remaining_space.empty());
38 UartToTeensyBuffer result;
39 result.set_size(
40 CobsEncode<uart_to_teensy_size()>(buffer, result.mutable_backing_array())
41 .size());
42 return result;
43}
44
45tl::optional<Frame> UartUnpackToTeensy(
46 const UartToTeensyBuffer &encoded_buffer) {
47 std::array<char, uart_to_teensy_size()> buffer;
48 if (static_cast<size_t>(
49 CobsDecode<uart_to_teensy_size()>(encoded_buffer, &buffer).size()) !=
50 buffer.size()) {
51 return tl::nullopt;
52 }
53
54 Frame message;
55 gsl::span<const char> remaining_input = buffer;
56 for (int i = 0; i < 3; ++i) {
57 memcpy(&message.targets[i].distance, remaining_input.data(), sizeof(float));
58 remaining_input = remaining_input.subspan(sizeof(float));
59 memcpy(&message.targets[i].height, remaining_input.data(), sizeof(float));
60 remaining_input = remaining_input.subspan(sizeof(float));
61 memcpy(&message.targets[i].heading, remaining_input.data(), sizeof(float));
62 remaining_input = remaining_input.subspan(sizeof(float));
63 memcpy(&message.targets[i].skew, remaining_input.data(), sizeof(float));
64 remaining_input = remaining_input.subspan(sizeof(float));
65 }
66 message.age = camera_duration(remaining_input[0]);
67 remaining_input = remaining_input.subspan(1);
68 {
69 uint16_t calculated_crc = jevois_crc_init();
70 calculated_crc = jevois_crc_update(calculated_crc, buffer.data(),
71 buffer.size() - remaining_input.size());
72 calculated_crc = jevois_crc_finalize(calculated_crc);
73 uint16_t received_crc;
74 CHECK_GE(static_cast<size_t>(remaining_input.size()), sizeof(received_crc));
75 memcpy(&received_crc, &remaining_input[0], sizeof(received_crc));
76 remaining_input = remaining_input.subspan(sizeof(received_crc));
77 CHECK(remaining_input.empty());
78 if (calculated_crc != received_crc) {
79 return tl::nullopt;
80 }
81 }
82 return message;
83}
84
85UartToCameraBuffer UartPackToCamera(const CameraCalibration &message) {
86 std::array<char, uart_to_camera_size()> buffer;
87 gsl::span<char> remaining_space = buffer;
88 for (int i = 0; i < 3; ++i) {
89 for (int j = 0; j < 4; ++j) {
90 memcpy(remaining_space.data(), &message.calibration(i, j), sizeof(float));
91 remaining_space = remaining_space.subspan(sizeof(float));
92 }
93 }
94 {
95 const int64_t teensy_now = message.teensy_now.time_since_epoch().count();
96 memcpy(remaining_space.data(), &teensy_now, sizeof(teensy_now));
97 remaining_space = remaining_space.subspan(sizeof(teensy_now));
98 }
99 {
100 const int64_t realtime_now =
101 message.realtime_now.time_since_epoch().count();
102 memcpy(remaining_space.data(), &realtime_now, sizeof(realtime_now));
103 remaining_space = remaining_space.subspan(sizeof(realtime_now));
104 }
105 memcpy(remaining_space.data(), &message.camera_command, 1);
106 remaining_space = remaining_space.subspan(1);
107 {
108 uint16_t crc = jevois_crc_init();
109 crc = jevois_crc_update(crc, buffer.data(),
110 buffer.size() - remaining_space.size());
111 crc = jevois_crc_finalize(crc);
112 CHECK_GE(static_cast<size_t>(remaining_space.size()), sizeof(crc));
113 memcpy(&remaining_space[0], &crc, sizeof(crc));
114 remaining_space = remaining_space.subspan(sizeof(crc));
115 }
116 CHECK(remaining_space.empty());
117 UartToCameraBuffer result;
118 result.set_size(
119 CobsEncode<uart_to_camera_size()>(buffer, result.mutable_backing_array())
120 .size());
121 return result;
122}
Brian Silvermanbfbbe872019-02-10 18:00:57 -0800123
124tl::optional<CameraCalibration> UartUnpackToCamera(
Brian Silverman2eb89762019-02-17 15:16:37 -0800125 const UartToCameraBuffer &encoded_buffer) {
126 std::array<char, uart_to_camera_size()> buffer;
127 if (static_cast<size_t>(
128 CobsDecode<uart_to_camera_size()>(encoded_buffer, &buffer).size()) !=
129 buffer.size()) {
130 return tl::nullopt;
131 }
132
133 CameraCalibration message;
134 gsl::span<const char> remaining_input = buffer;
135 for (int i = 0; i < 3; ++i) {
136 for (int j = 0; j < 4; ++j) {
137 memcpy(&message.calibration(i, j), remaining_input.data(), sizeof(float));
138 remaining_input = remaining_input.subspan(sizeof(float));
139 }
140 }
141 {
142 int64_t teensy_now;
143 memcpy(&teensy_now, remaining_input.data(), sizeof(teensy_now));
144 message.teensy_now = aos::monotonic_clock::time_point(
145 aos::monotonic_clock::duration(teensy_now));
146 remaining_input = remaining_input.subspan(sizeof(teensy_now));
147 }
148 {
149 int64_t realtime_now;
150 memcpy(&realtime_now, remaining_input.data(), sizeof(realtime_now));
151 message.realtime_now = aos::realtime_clock::time_point(
152 aos::realtime_clock::duration(realtime_now));
153 remaining_input = remaining_input.subspan(sizeof(realtime_now));
154 }
155 memcpy(&message.camera_command, remaining_input.data(), 1);
156 remaining_input = remaining_input.subspan(1);
157 {
158 uint16_t calculated_crc = jevois_crc_init();
159 calculated_crc = jevois_crc_update(calculated_crc, buffer.data(),
160 buffer.size() - remaining_input.size());
161 calculated_crc = jevois_crc_finalize(calculated_crc);
162 uint16_t received_crc;
163 CHECK_GE(static_cast<size_t>(remaining_input.size()), sizeof(received_crc));
164 memcpy(&received_crc, &remaining_input[0], sizeof(received_crc));
165 remaining_input = remaining_input.subspan(sizeof(received_crc));
166 CHECK(remaining_input.empty());
167 if (calculated_crc != received_crc) {
168 return tl::nullopt;
169 }
170 }
171 return message;
Brian Silvermanbfbbe872019-02-10 18:00:57 -0800172}
173
174} // namespace jevois
175} // namespace frc971