blob: 6ebfe30e75ddde4e7e36e46d47dc0bac7585e3df [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
Brian Silverman2eb89762019-02-17 15:16:37 -08005#include "aos/util/bitpacking.h"
6#include "third_party/GSL/include/gsl/gsl"
7#include "y2019/jevois/jevois_crc.h"
Brian Silvermanfdfb3132019-02-24 15:27:27 -08008#ifdef __linux__
9#include "aos/logging/logging.h"
10#else
Austin Schuhf257f3c2019-10-27 21:00:43 -070011#define AOS_CHECK(...)
12#define AOS_CHECK_GE(...)
Brian Silvermanfdfb3132019-02-24 15:27:27 -080013#endif
Brian Silverman2eb89762019-02-17 15:16:37 -080014
Brian Silvermanbfbbe872019-02-10 18:00:57 -080015namespace frc971 {
16namespace jevois {
17
Brian Silvermanc41fb862019-03-02 21:14:46 -080018UartToTeensyBuffer UartPackToTeensy(const CameraFrame &message) {
Brian Silverman2eb89762019-02-17 15:16:37 -080019 std::array<char, uart_to_teensy_size()> buffer;
20 gsl::span<char> remaining_space = buffer;
Brian Silvermana1e4d332019-02-17 22:53:13 -080021 remaining_space[0] = message.targets.size();
22 remaining_space = remaining_space.subspan(1);
23 for (size_t i = 0; i < 3; ++i) {
24 if (i < message.targets.size()) {
25 memcpy(remaining_space.data(), &message.targets[i].distance,
26 sizeof(float));
27 remaining_space = remaining_space.subspan(sizeof(float));
28 memcpy(remaining_space.data(), &message.targets[i].height, sizeof(float));
29 remaining_space = remaining_space.subspan(sizeof(float));
30 memcpy(remaining_space.data(), &message.targets[i].heading,
31 sizeof(float));
32 remaining_space = remaining_space.subspan(sizeof(float));
33 memcpy(remaining_space.data(), &message.targets[i].skew, sizeof(float));
34 remaining_space = remaining_space.subspan(sizeof(float));
35 } else {
36 remaining_space = remaining_space.subspan(sizeof(float) * 4);
37 }
Brian Silverman2eb89762019-02-17 15:16:37 -080038 }
39 remaining_space[0] = message.age.count();
40 remaining_space = remaining_space.subspan(1);
41 {
42 uint16_t crc = jevois_crc_init();
43 crc = jevois_crc_update(crc, buffer.data(),
44 buffer.size() - remaining_space.size());
45 crc = jevois_crc_finalize(crc);
Austin Schuhf257f3c2019-10-27 21:00:43 -070046 AOS_CHECK_GE(static_cast<size_t>(remaining_space.size()), sizeof(crc));
Brian Silverman2eb89762019-02-17 15:16:37 -080047 memcpy(&remaining_space[0], &crc, sizeof(crc));
48 remaining_space = remaining_space.subspan(sizeof(crc));
49 }
Austin Schuhf257f3c2019-10-27 21:00:43 -070050 AOS_CHECK(remaining_space.empty());
Brian Silverman2eb89762019-02-17 15:16:37 -080051 UartToTeensyBuffer result;
52 result.set_size(
53 CobsEncode<uart_to_teensy_size()>(buffer, result.mutable_backing_array())
54 .size());
55 return result;
56}
57
Brian Silvermanc41fb862019-03-02 21:14:46 -080058tl::optional<CameraFrame> UartUnpackToTeensy(gsl::span<const char> encoded_buffer) {
Brian Silverman2eb89762019-02-17 15:16:37 -080059 std::array<char, uart_to_teensy_size()> buffer;
60 if (static_cast<size_t>(
61 CobsDecode<uart_to_teensy_size()>(encoded_buffer, &buffer).size()) !=
62 buffer.size()) {
63 return tl::nullopt;
64 }
65
Brian Silvermanc41fb862019-03-02 21:14:46 -080066 CameraFrame message;
Brian Silverman2eb89762019-02-17 15:16:37 -080067 gsl::span<const char> remaining_input = buffer;
Brian Silvermana1e4d332019-02-17 22:53:13 -080068 const int number_targets = remaining_input[0];
69 remaining_input = remaining_input.subspan(1);
Brian Silverman2eb89762019-02-17 15:16:37 -080070 for (int i = 0; i < 3; ++i) {
Brian Silvermana1e4d332019-02-17 22:53:13 -080071 if (i < number_targets) {
72 message.targets.push_back({});
73 Target *const target = &message.targets.back();
74 memcpy(&target->distance, remaining_input.data(), sizeof(float));
75 remaining_input = remaining_input.subspan(sizeof(float));
76 memcpy(&target->height, remaining_input.data(), sizeof(float));
77 remaining_input = remaining_input.subspan(sizeof(float));
78 memcpy(&target->heading, remaining_input.data(), sizeof(float));
79 remaining_input = remaining_input.subspan(sizeof(float));
80 memcpy(&target->skew, remaining_input.data(), sizeof(float));
81 remaining_input = remaining_input.subspan(sizeof(float));
82 } else {
83 remaining_input = remaining_input.subspan(sizeof(float) * 4);
84 }
Brian Silverman2eb89762019-02-17 15:16:37 -080085 }
86 message.age = camera_duration(remaining_input[0]);
87 remaining_input = remaining_input.subspan(1);
88 {
89 uint16_t calculated_crc = jevois_crc_init();
90 calculated_crc = jevois_crc_update(calculated_crc, buffer.data(),
91 buffer.size() - remaining_input.size());
92 calculated_crc = jevois_crc_finalize(calculated_crc);
93 uint16_t received_crc;
Austin Schuhf257f3c2019-10-27 21:00:43 -070094 AOS_CHECK_GE(static_cast<size_t>(remaining_input.size()),
95 sizeof(received_crc));
Brian Silverman2eb89762019-02-17 15:16:37 -080096 memcpy(&received_crc, &remaining_input[0], sizeof(received_crc));
97 remaining_input = remaining_input.subspan(sizeof(received_crc));
Austin Schuhf257f3c2019-10-27 21:00:43 -070098 AOS_CHECK(remaining_input.empty());
Brian Silverman2eb89762019-02-17 15:16:37 -080099 if (calculated_crc != received_crc) {
100 return tl::nullopt;
101 }
102 }
103 return message;
104}
105
106UartToCameraBuffer UartPackToCamera(const CameraCalibration &message) {
107 std::array<char, uart_to_camera_size()> buffer;
108 gsl::span<char> remaining_space = buffer;
109 for (int i = 0; i < 3; ++i) {
110 for (int j = 0; j < 4; ++j) {
111 memcpy(remaining_space.data(), &message.calibration(i, j), sizeof(float));
112 remaining_space = remaining_space.subspan(sizeof(float));
113 }
114 }
115 {
116 const int64_t teensy_now = message.teensy_now.time_since_epoch().count();
117 memcpy(remaining_space.data(), &teensy_now, sizeof(teensy_now));
118 remaining_space = remaining_space.subspan(sizeof(teensy_now));
119 }
120 {
121 const int64_t realtime_now =
122 message.realtime_now.time_since_epoch().count();
123 memcpy(remaining_space.data(), &realtime_now, sizeof(realtime_now));
124 remaining_space = remaining_space.subspan(sizeof(realtime_now));
125 }
126 memcpy(remaining_space.data(), &message.camera_command, 1);
127 remaining_space = remaining_space.subspan(1);
128 {
129 uint16_t crc = jevois_crc_init();
130 crc = jevois_crc_update(crc, buffer.data(),
131 buffer.size() - remaining_space.size());
132 crc = jevois_crc_finalize(crc);
Austin Schuhf257f3c2019-10-27 21:00:43 -0700133 AOS_CHECK_GE(static_cast<size_t>(remaining_space.size()), sizeof(crc));
Brian Silverman2eb89762019-02-17 15:16:37 -0800134 memcpy(&remaining_space[0], &crc, sizeof(crc));
135 remaining_space = remaining_space.subspan(sizeof(crc));
136 }
Austin Schuhf257f3c2019-10-27 21:00:43 -0700137 AOS_CHECK(remaining_space.empty());
Brian Silverman2eb89762019-02-17 15:16:37 -0800138 UartToCameraBuffer result;
139 result.set_size(
140 CobsEncode<uart_to_camera_size()>(buffer, result.mutable_backing_array())
141 .size());
142 return result;
143}
Brian Silvermanbfbbe872019-02-10 18:00:57 -0800144
145tl::optional<CameraCalibration> UartUnpackToCamera(
Parker Schuhd68e1b02019-02-22 20:59:16 -0800146 gsl::span<const char> encoded_buffer) {
Brian Silverman2eb89762019-02-17 15:16:37 -0800147 std::array<char, uart_to_camera_size()> buffer;
148 if (static_cast<size_t>(
149 CobsDecode<uart_to_camera_size()>(encoded_buffer, &buffer).size()) !=
150 buffer.size()) {
151 return tl::nullopt;
152 }
153
154 CameraCalibration message;
155 gsl::span<const char> remaining_input = buffer;
156 for (int i = 0; i < 3; ++i) {
157 for (int j = 0; j < 4; ++j) {
158 memcpy(&message.calibration(i, j), remaining_input.data(), sizeof(float));
159 remaining_input = remaining_input.subspan(sizeof(float));
160 }
161 }
162 {
163 int64_t teensy_now;
164 memcpy(&teensy_now, remaining_input.data(), sizeof(teensy_now));
165 message.teensy_now = aos::monotonic_clock::time_point(
166 aos::monotonic_clock::duration(teensy_now));
167 remaining_input = remaining_input.subspan(sizeof(teensy_now));
168 }
169 {
170 int64_t realtime_now;
171 memcpy(&realtime_now, remaining_input.data(), sizeof(realtime_now));
172 message.realtime_now = aos::realtime_clock::time_point(
173 aos::realtime_clock::duration(realtime_now));
174 remaining_input = remaining_input.subspan(sizeof(realtime_now));
175 }
176 memcpy(&message.camera_command, remaining_input.data(), 1);
177 remaining_input = remaining_input.subspan(1);
178 {
179 uint16_t calculated_crc = jevois_crc_init();
180 calculated_crc = jevois_crc_update(calculated_crc, buffer.data(),
181 buffer.size() - remaining_input.size());
182 calculated_crc = jevois_crc_finalize(calculated_crc);
183 uint16_t received_crc;
Austin Schuhf257f3c2019-10-27 21:00:43 -0700184 AOS_CHECK_GE(static_cast<size_t>(remaining_input.size()),
185 sizeof(received_crc));
Brian Silverman2eb89762019-02-17 15:16:37 -0800186 memcpy(&received_crc, &remaining_input[0], sizeof(received_crc));
187 remaining_input = remaining_input.subspan(sizeof(received_crc));
Austin Schuhf257f3c2019-10-27 21:00:43 -0700188 AOS_CHECK(remaining_input.empty());
Brian Silverman2eb89762019-02-17 15:16:37 -0800189 if (calculated_crc != received_crc) {
190 return tl::nullopt;
191 }
192 }
193 return message;
Brian Silvermanbfbbe872019-02-10 18:00:57 -0800194}
195
196} // namespace jevois
197} // namespace frc971