blob: b1fdcfb6ca4483c1d351e10949d9eb573dd894c6 [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
James Kuszmaul3ae42262019-11-08 12:33:41 -080058std::optional<CameraFrame> UartUnpackToTeensy(
59 gsl::span<const char> encoded_buffer) {
Brian Silverman2eb89762019-02-17 15:16:37 -080060 std::array<char, uart_to_teensy_size()> buffer;
61 if (static_cast<size_t>(
62 CobsDecode<uart_to_teensy_size()>(encoded_buffer, &buffer).size()) !=
63 buffer.size()) {
James Kuszmaul3ae42262019-11-08 12:33:41 -080064 return std::nullopt;
Brian Silverman2eb89762019-02-17 15:16:37 -080065 }
66
Brian Silvermanc41fb862019-03-02 21:14:46 -080067 CameraFrame message;
Brian Silverman2eb89762019-02-17 15:16:37 -080068 gsl::span<const char> remaining_input = buffer;
Brian Silvermana1e4d332019-02-17 22:53:13 -080069 const int number_targets = remaining_input[0];
70 remaining_input = remaining_input.subspan(1);
Brian Silverman2eb89762019-02-17 15:16:37 -080071 for (int i = 0; i < 3; ++i) {
Brian Silvermana1e4d332019-02-17 22:53:13 -080072 if (i < number_targets) {
73 message.targets.push_back({});
74 Target *const target = &message.targets.back();
75 memcpy(&target->distance, remaining_input.data(), sizeof(float));
76 remaining_input = remaining_input.subspan(sizeof(float));
77 memcpy(&target->height, remaining_input.data(), sizeof(float));
78 remaining_input = remaining_input.subspan(sizeof(float));
79 memcpy(&target->heading, remaining_input.data(), sizeof(float));
80 remaining_input = remaining_input.subspan(sizeof(float));
81 memcpy(&target->skew, remaining_input.data(), sizeof(float));
82 remaining_input = remaining_input.subspan(sizeof(float));
83 } else {
84 remaining_input = remaining_input.subspan(sizeof(float) * 4);
85 }
Brian Silverman2eb89762019-02-17 15:16:37 -080086 }
87 message.age = camera_duration(remaining_input[0]);
88 remaining_input = remaining_input.subspan(1);
89 {
90 uint16_t calculated_crc = jevois_crc_init();
91 calculated_crc = jevois_crc_update(calculated_crc, buffer.data(),
92 buffer.size() - remaining_input.size());
93 calculated_crc = jevois_crc_finalize(calculated_crc);
94 uint16_t received_crc;
Austin Schuhf257f3c2019-10-27 21:00:43 -070095 AOS_CHECK_GE(static_cast<size_t>(remaining_input.size()),
96 sizeof(received_crc));
Brian Silverman2eb89762019-02-17 15:16:37 -080097 memcpy(&received_crc, &remaining_input[0], sizeof(received_crc));
98 remaining_input = remaining_input.subspan(sizeof(received_crc));
Austin Schuhf257f3c2019-10-27 21:00:43 -070099 AOS_CHECK(remaining_input.empty());
Brian Silverman2eb89762019-02-17 15:16:37 -0800100 if (calculated_crc != received_crc) {
James Kuszmaul3ae42262019-11-08 12:33:41 -0800101 return std::nullopt;
Brian Silverman2eb89762019-02-17 15:16:37 -0800102 }
103 }
104 return message;
105}
106
107UartToCameraBuffer UartPackToCamera(const CameraCalibration &message) {
108 std::array<char, uart_to_camera_size()> buffer;
109 gsl::span<char> remaining_space = buffer;
110 for (int i = 0; i < 3; ++i) {
111 for (int j = 0; j < 4; ++j) {
112 memcpy(remaining_space.data(), &message.calibration(i, j), sizeof(float));
113 remaining_space = remaining_space.subspan(sizeof(float));
114 }
115 }
116 {
117 const int64_t teensy_now = message.teensy_now.time_since_epoch().count();
118 memcpy(remaining_space.data(), &teensy_now, sizeof(teensy_now));
119 remaining_space = remaining_space.subspan(sizeof(teensy_now));
120 }
121 {
122 const int64_t realtime_now =
123 message.realtime_now.time_since_epoch().count();
124 memcpy(remaining_space.data(), &realtime_now, sizeof(realtime_now));
125 remaining_space = remaining_space.subspan(sizeof(realtime_now));
126 }
127 memcpy(remaining_space.data(), &message.camera_command, 1);
128 remaining_space = remaining_space.subspan(1);
129 {
130 uint16_t crc = jevois_crc_init();
131 crc = jevois_crc_update(crc, buffer.data(),
132 buffer.size() - remaining_space.size());
133 crc = jevois_crc_finalize(crc);
Austin Schuhf257f3c2019-10-27 21:00:43 -0700134 AOS_CHECK_GE(static_cast<size_t>(remaining_space.size()), sizeof(crc));
Brian Silverman2eb89762019-02-17 15:16:37 -0800135 memcpy(&remaining_space[0], &crc, sizeof(crc));
136 remaining_space = remaining_space.subspan(sizeof(crc));
137 }
Austin Schuhf257f3c2019-10-27 21:00:43 -0700138 AOS_CHECK(remaining_space.empty());
Brian Silverman2eb89762019-02-17 15:16:37 -0800139 UartToCameraBuffer result;
140 result.set_size(
141 CobsEncode<uart_to_camera_size()>(buffer, result.mutable_backing_array())
142 .size());
143 return result;
144}
Brian Silvermanbfbbe872019-02-10 18:00:57 -0800145
James Kuszmaul3ae42262019-11-08 12:33:41 -0800146std::optional<CameraCalibration> UartUnpackToCamera(
Parker Schuhd68e1b02019-02-22 20:59:16 -0800147 gsl::span<const char> encoded_buffer) {
Brian Silverman2eb89762019-02-17 15:16:37 -0800148 std::array<char, uart_to_camera_size()> buffer;
149 if (static_cast<size_t>(
150 CobsDecode<uart_to_camera_size()>(encoded_buffer, &buffer).size()) !=
151 buffer.size()) {
James Kuszmaul3ae42262019-11-08 12:33:41 -0800152 return std::nullopt;
Brian Silverman2eb89762019-02-17 15:16:37 -0800153 }
154
155 CameraCalibration message;
156 gsl::span<const char> remaining_input = buffer;
157 for (int i = 0; i < 3; ++i) {
158 for (int j = 0; j < 4; ++j) {
159 memcpy(&message.calibration(i, j), remaining_input.data(), sizeof(float));
160 remaining_input = remaining_input.subspan(sizeof(float));
161 }
162 }
163 {
164 int64_t teensy_now;
165 memcpy(&teensy_now, remaining_input.data(), sizeof(teensy_now));
166 message.teensy_now = aos::monotonic_clock::time_point(
167 aos::monotonic_clock::duration(teensy_now));
168 remaining_input = remaining_input.subspan(sizeof(teensy_now));
169 }
170 {
171 int64_t realtime_now;
172 memcpy(&realtime_now, remaining_input.data(), sizeof(realtime_now));
173 message.realtime_now = aos::realtime_clock::time_point(
174 aos::realtime_clock::duration(realtime_now));
175 remaining_input = remaining_input.subspan(sizeof(realtime_now));
176 }
177 memcpy(&message.camera_command, remaining_input.data(), 1);
178 remaining_input = remaining_input.subspan(1);
179 {
180 uint16_t calculated_crc = jevois_crc_init();
181 calculated_crc = jevois_crc_update(calculated_crc, buffer.data(),
182 buffer.size() - remaining_input.size());
183 calculated_crc = jevois_crc_finalize(calculated_crc);
184 uint16_t received_crc;
Austin Schuhf257f3c2019-10-27 21:00:43 -0700185 AOS_CHECK_GE(static_cast<size_t>(remaining_input.size()),
186 sizeof(received_crc));
Brian Silverman2eb89762019-02-17 15:16:37 -0800187 memcpy(&received_crc, &remaining_input[0], sizeof(received_crc));
188 remaining_input = remaining_input.subspan(sizeof(received_crc));
Austin Schuhf257f3c2019-10-27 21:00:43 -0700189 AOS_CHECK(remaining_input.empty());
Brian Silverman2eb89762019-02-17 15:16:37 -0800190 if (calculated_crc != received_crc) {
James Kuszmaul3ae42262019-11-08 12:33:41 -0800191 return std::nullopt;
Brian Silverman2eb89762019-02-17 15:16:37 -0800192 }
193 }
194 return message;
Brian Silvermanbfbbe872019-02-10 18:00:57 -0800195}
196
197} // namespace jevois
198} // namespace frc971