blob: 0db59a5b2c30c8491d1383fe4ff4a2a7f22c21ae [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;
Brian Silvermana1e4d332019-02-17 22:53:13 -080016 remaining_space[0] = message.targets.size();
17 remaining_space = remaining_space.subspan(1);
18 for (size_t i = 0; i < 3; ++i) {
19 if (i < message.targets.size()) {
20 memcpy(remaining_space.data(), &message.targets[i].distance,
21 sizeof(float));
22 remaining_space = remaining_space.subspan(sizeof(float));
23 memcpy(remaining_space.data(), &message.targets[i].height, sizeof(float));
24 remaining_space = remaining_space.subspan(sizeof(float));
25 memcpy(remaining_space.data(), &message.targets[i].heading,
26 sizeof(float));
27 remaining_space = remaining_space.subspan(sizeof(float));
28 memcpy(remaining_space.data(), &message.targets[i].skew, sizeof(float));
29 remaining_space = remaining_space.subspan(sizeof(float));
30 } else {
31 remaining_space = remaining_space.subspan(sizeof(float) * 4);
32 }
Brian Silverman2eb89762019-02-17 15:16:37 -080033 }
34 remaining_space[0] = message.age.count();
35 remaining_space = remaining_space.subspan(1);
36 {
37 uint16_t crc = jevois_crc_init();
38 crc = jevois_crc_update(crc, buffer.data(),
39 buffer.size() - remaining_space.size());
40 crc = jevois_crc_finalize(crc);
41 CHECK_GE(static_cast<size_t>(remaining_space.size()), sizeof(crc));
42 memcpy(&remaining_space[0], &crc, sizeof(crc));
43 remaining_space = remaining_space.subspan(sizeof(crc));
44 }
45 CHECK(remaining_space.empty());
46 UartToTeensyBuffer result;
47 result.set_size(
48 CobsEncode<uart_to_teensy_size()>(buffer, result.mutable_backing_array())
49 .size());
50 return result;
51}
52
53tl::optional<Frame> UartUnpackToTeensy(
Parker Schuhd68e1b02019-02-22 20:59:16 -080054 gsl::span<const char> encoded_buffer) {
Brian Silverman2eb89762019-02-17 15:16:37 -080055 std::array<char, uart_to_teensy_size()> buffer;
56 if (static_cast<size_t>(
57 CobsDecode<uart_to_teensy_size()>(encoded_buffer, &buffer).size()) !=
58 buffer.size()) {
59 return tl::nullopt;
60 }
61
62 Frame message;
63 gsl::span<const char> remaining_input = buffer;
Brian Silvermana1e4d332019-02-17 22:53:13 -080064 const int number_targets = remaining_input[0];
65 remaining_input = remaining_input.subspan(1);
Brian Silverman2eb89762019-02-17 15:16:37 -080066 for (int i = 0; i < 3; ++i) {
Brian Silvermana1e4d332019-02-17 22:53:13 -080067 if (i < number_targets) {
68 message.targets.push_back({});
69 Target *const target = &message.targets.back();
70 memcpy(&target->distance, remaining_input.data(), sizeof(float));
71 remaining_input = remaining_input.subspan(sizeof(float));
72 memcpy(&target->height, remaining_input.data(), sizeof(float));
73 remaining_input = remaining_input.subspan(sizeof(float));
74 memcpy(&target->heading, remaining_input.data(), sizeof(float));
75 remaining_input = remaining_input.subspan(sizeof(float));
76 memcpy(&target->skew, remaining_input.data(), sizeof(float));
77 remaining_input = remaining_input.subspan(sizeof(float));
78 } else {
79 remaining_input = remaining_input.subspan(sizeof(float) * 4);
80 }
Brian Silverman2eb89762019-02-17 15:16:37 -080081 }
82 message.age = camera_duration(remaining_input[0]);
83 remaining_input = remaining_input.subspan(1);
84 {
85 uint16_t calculated_crc = jevois_crc_init();
86 calculated_crc = jevois_crc_update(calculated_crc, buffer.data(),
87 buffer.size() - remaining_input.size());
88 calculated_crc = jevois_crc_finalize(calculated_crc);
89 uint16_t received_crc;
90 CHECK_GE(static_cast<size_t>(remaining_input.size()), sizeof(received_crc));
91 memcpy(&received_crc, &remaining_input[0], sizeof(received_crc));
92 remaining_input = remaining_input.subspan(sizeof(received_crc));
93 CHECK(remaining_input.empty());
94 if (calculated_crc != received_crc) {
95 return tl::nullopt;
96 }
97 }
98 return message;
99}
100
101UartToCameraBuffer UartPackToCamera(const CameraCalibration &message) {
102 std::array<char, uart_to_camera_size()> buffer;
103 gsl::span<char> remaining_space = buffer;
104 for (int i = 0; i < 3; ++i) {
105 for (int j = 0; j < 4; ++j) {
106 memcpy(remaining_space.data(), &message.calibration(i, j), sizeof(float));
107 remaining_space = remaining_space.subspan(sizeof(float));
108 }
109 }
110 {
111 const int64_t teensy_now = message.teensy_now.time_since_epoch().count();
112 memcpy(remaining_space.data(), &teensy_now, sizeof(teensy_now));
113 remaining_space = remaining_space.subspan(sizeof(teensy_now));
114 }
115 {
116 const int64_t realtime_now =
117 message.realtime_now.time_since_epoch().count();
118 memcpy(remaining_space.data(), &realtime_now, sizeof(realtime_now));
119 remaining_space = remaining_space.subspan(sizeof(realtime_now));
120 }
121 memcpy(remaining_space.data(), &message.camera_command, 1);
122 remaining_space = remaining_space.subspan(1);
123 {
124 uint16_t crc = jevois_crc_init();
125 crc = jevois_crc_update(crc, buffer.data(),
126 buffer.size() - remaining_space.size());
127 crc = jevois_crc_finalize(crc);
128 CHECK_GE(static_cast<size_t>(remaining_space.size()), sizeof(crc));
129 memcpy(&remaining_space[0], &crc, sizeof(crc));
130 remaining_space = remaining_space.subspan(sizeof(crc));
131 }
132 CHECK(remaining_space.empty());
133 UartToCameraBuffer result;
134 result.set_size(
135 CobsEncode<uart_to_camera_size()>(buffer, result.mutable_backing_array())
136 .size());
137 return result;
138}
Brian Silvermanbfbbe872019-02-10 18:00:57 -0800139
140tl::optional<CameraCalibration> UartUnpackToCamera(
Parker Schuhd68e1b02019-02-22 20:59:16 -0800141 gsl::span<const char> encoded_buffer) {
Brian Silverman2eb89762019-02-17 15:16:37 -0800142 std::array<char, uart_to_camera_size()> buffer;
143 if (static_cast<size_t>(
144 CobsDecode<uart_to_camera_size()>(encoded_buffer, &buffer).size()) !=
145 buffer.size()) {
146 return tl::nullopt;
147 }
148
149 CameraCalibration message;
150 gsl::span<const char> remaining_input = buffer;
151 for (int i = 0; i < 3; ++i) {
152 for (int j = 0; j < 4; ++j) {
153 memcpy(&message.calibration(i, j), remaining_input.data(), sizeof(float));
154 remaining_input = remaining_input.subspan(sizeof(float));
155 }
156 }
157 {
158 int64_t teensy_now;
159 memcpy(&teensy_now, remaining_input.data(), sizeof(teensy_now));
160 message.teensy_now = aos::monotonic_clock::time_point(
161 aos::monotonic_clock::duration(teensy_now));
162 remaining_input = remaining_input.subspan(sizeof(teensy_now));
163 }
164 {
165 int64_t realtime_now;
166 memcpy(&realtime_now, remaining_input.data(), sizeof(realtime_now));
167 message.realtime_now = aos::realtime_clock::time_point(
168 aos::realtime_clock::duration(realtime_now));
169 remaining_input = remaining_input.subspan(sizeof(realtime_now));
170 }
171 memcpy(&message.camera_command, remaining_input.data(), 1);
172 remaining_input = remaining_input.subspan(1);
173 {
174 uint16_t calculated_crc = jevois_crc_init();
175 calculated_crc = jevois_crc_update(calculated_crc, buffer.data(),
176 buffer.size() - remaining_input.size());
177 calculated_crc = jevois_crc_finalize(calculated_crc);
178 uint16_t received_crc;
179 CHECK_GE(static_cast<size_t>(remaining_input.size()), sizeof(received_crc));
180 memcpy(&received_crc, &remaining_input[0], sizeof(received_crc));
181 remaining_input = remaining_input.subspan(sizeof(received_crc));
182 CHECK(remaining_input.empty());
183 if (calculated_crc != received_crc) {
184 return tl::nullopt;
185 }
186 }
187 return message;
Brian Silvermanbfbbe872019-02-10 18:00:57 -0800188}
189
190} // namespace jevois
191} // namespace frc971