blob: 0fc25c9291823b5ec5a8d225c306d615c17b99a1 [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
Austin Schuhb72be802022-01-02 12:26:28 -08005#include "absl/types/span.h"
Philipp Schrader790cb542023-07-05 21:06:52 -07006
Austin Schuh7fe04492022-01-02 13:37:21 -08007#include "aos/util/bitpacking.h"
Brian Silverman2eb89762019-02-17 15:16:37 -08008#include "y2019/jevois/jevois_crc.h"
Brian Silvermanfdfb3132019-02-24 15:27:27 -08009#ifdef __linux__
10#include "aos/logging/logging.h"
11#else
Austin Schuhf257f3c2019-10-27 21:00:43 -070012#define AOS_CHECK(...)
13#define AOS_CHECK_GE(...)
Brian Silvermanfdfb3132019-02-24 15:27:27 -080014#endif
Brian Silverman2eb89762019-02-17 15:16:37 -080015
Brian Silvermanbfbbe872019-02-10 18:00:57 -080016namespace frc971 {
17namespace jevois {
18
Brian Silvermanc41fb862019-03-02 21:14:46 -080019UartToTeensyBuffer UartPackToTeensy(const CameraFrame &message) {
Brian Silverman2eb89762019-02-17 15:16:37 -080020 std::array<char, uart_to_teensy_size()> buffer;
Austin Schuhb72be802022-01-02 12:26:28 -080021 absl::Span<char> remaining_space(buffer);
Brian Silvermana1e4d332019-02-17 22:53:13 -080022 remaining_space[0] = message.targets.size();
23 remaining_space = remaining_space.subspan(1);
24 for (size_t i = 0; i < 3; ++i) {
25 if (i < message.targets.size()) {
26 memcpy(remaining_space.data(), &message.targets[i].distance,
27 sizeof(float));
28 remaining_space = remaining_space.subspan(sizeof(float));
29 memcpy(remaining_space.data(), &message.targets[i].height, sizeof(float));
30 remaining_space = remaining_space.subspan(sizeof(float));
31 memcpy(remaining_space.data(), &message.targets[i].heading,
32 sizeof(float));
33 remaining_space = remaining_space.subspan(sizeof(float));
34 memcpy(remaining_space.data(), &message.targets[i].skew, sizeof(float));
35 remaining_space = remaining_space.subspan(sizeof(float));
36 } else {
37 remaining_space = remaining_space.subspan(sizeof(float) * 4);
38 }
Brian Silverman2eb89762019-02-17 15:16:37 -080039 }
40 remaining_space[0] = message.age.count();
41 remaining_space = remaining_space.subspan(1);
42 {
43 uint16_t crc = jevois_crc_init();
44 crc = jevois_crc_update(crc, buffer.data(),
45 buffer.size() - remaining_space.size());
46 crc = jevois_crc_finalize(crc);
Austin Schuhf257f3c2019-10-27 21:00:43 -070047 AOS_CHECK_GE(static_cast<size_t>(remaining_space.size()), sizeof(crc));
Brian Silverman2eb89762019-02-17 15:16:37 -080048 memcpy(&remaining_space[0], &crc, sizeof(crc));
49 remaining_space = remaining_space.subspan(sizeof(crc));
50 }
Austin Schuhf257f3c2019-10-27 21:00:43 -070051 AOS_CHECK(remaining_space.empty());
Brian Silverman2eb89762019-02-17 15:16:37 -080052 UartToTeensyBuffer result;
Tyler Chatowd0a49742022-02-25 22:06:19 -080053 result.resize(result.capacity());
54 result.resize(
55 CobsEncode<uart_to_teensy_size()>(buffer, absl::Span<char>(result))
Brian Silverman2eb89762019-02-17 15:16:37 -080056 .size());
57 return result;
58}
59
James Kuszmaul3ae42262019-11-08 12:33:41 -080060std::optional<CameraFrame> UartUnpackToTeensy(
Austin Schuhb72be802022-01-02 12:26:28 -080061 absl::Span<const char> encoded_buffer) {
Brian Silverman2eb89762019-02-17 15:16:37 -080062 std::array<char, uart_to_teensy_size()> buffer;
63 if (static_cast<size_t>(
64 CobsDecode<uart_to_teensy_size()>(encoded_buffer, &buffer).size()) !=
65 buffer.size()) {
James Kuszmaul3ae42262019-11-08 12:33:41 -080066 return std::nullopt;
Brian Silverman2eb89762019-02-17 15:16:37 -080067 }
68
Brian Silvermanc41fb862019-03-02 21:14:46 -080069 CameraFrame message;
Austin Schuhb72be802022-01-02 12:26:28 -080070 absl::Span<const char> remaining_input(buffer);
Brian Silvermana1e4d332019-02-17 22:53:13 -080071 const int number_targets = remaining_input[0];
72 remaining_input = remaining_input.subspan(1);
Brian Silverman2eb89762019-02-17 15:16:37 -080073 for (int i = 0; i < 3; ++i) {
Brian Silvermana1e4d332019-02-17 22:53:13 -080074 if (i < number_targets) {
75 message.targets.push_back({});
76 Target *const target = &message.targets.back();
77 memcpy(&target->distance, remaining_input.data(), sizeof(float));
78 remaining_input = remaining_input.subspan(sizeof(float));
79 memcpy(&target->height, remaining_input.data(), sizeof(float));
80 remaining_input = remaining_input.subspan(sizeof(float));
81 memcpy(&target->heading, remaining_input.data(), sizeof(float));
82 remaining_input = remaining_input.subspan(sizeof(float));
83 memcpy(&target->skew, remaining_input.data(), sizeof(float));
84 remaining_input = remaining_input.subspan(sizeof(float));
85 } else {
86 remaining_input = remaining_input.subspan(sizeof(float) * 4);
87 }
Brian Silverman2eb89762019-02-17 15:16:37 -080088 }
89 message.age = camera_duration(remaining_input[0]);
90 remaining_input = remaining_input.subspan(1);
91 {
92 uint16_t calculated_crc = jevois_crc_init();
93 calculated_crc = jevois_crc_update(calculated_crc, buffer.data(),
94 buffer.size() - remaining_input.size());
95 calculated_crc = jevois_crc_finalize(calculated_crc);
96 uint16_t received_crc;
Austin Schuhf257f3c2019-10-27 21:00:43 -070097 AOS_CHECK_GE(static_cast<size_t>(remaining_input.size()),
98 sizeof(received_crc));
Brian Silverman2eb89762019-02-17 15:16:37 -080099 memcpy(&received_crc, &remaining_input[0], sizeof(received_crc));
100 remaining_input = remaining_input.subspan(sizeof(received_crc));
Austin Schuhf257f3c2019-10-27 21:00:43 -0700101 AOS_CHECK(remaining_input.empty());
Brian Silverman2eb89762019-02-17 15:16:37 -0800102 if (calculated_crc != received_crc) {
James Kuszmaul3ae42262019-11-08 12:33:41 -0800103 return std::nullopt;
Brian Silverman2eb89762019-02-17 15:16:37 -0800104 }
105 }
106 return message;
107}
108
109UartToCameraBuffer UartPackToCamera(const CameraCalibration &message) {
110 std::array<char, uart_to_camera_size()> buffer;
Austin Schuhb72be802022-01-02 12:26:28 -0800111 absl::Span<char> remaining_space(buffer);
Brian Silverman2eb89762019-02-17 15:16:37 -0800112 for (int i = 0; i < 3; ++i) {
113 for (int j = 0; j < 4; ++j) {
114 memcpy(remaining_space.data(), &message.calibration(i, j), sizeof(float));
115 remaining_space = remaining_space.subspan(sizeof(float));
116 }
117 }
118 {
119 const int64_t teensy_now = message.teensy_now.time_since_epoch().count();
120 memcpy(remaining_space.data(), &teensy_now, sizeof(teensy_now));
121 remaining_space = remaining_space.subspan(sizeof(teensy_now));
122 }
123 {
124 const int64_t realtime_now =
125 message.realtime_now.time_since_epoch().count();
126 memcpy(remaining_space.data(), &realtime_now, sizeof(realtime_now));
127 remaining_space = remaining_space.subspan(sizeof(realtime_now));
128 }
129 memcpy(remaining_space.data(), &message.camera_command, 1);
130 remaining_space = remaining_space.subspan(1);
131 {
132 uint16_t crc = jevois_crc_init();
133 crc = jevois_crc_update(crc, buffer.data(),
134 buffer.size() - remaining_space.size());
135 crc = jevois_crc_finalize(crc);
Austin Schuhf257f3c2019-10-27 21:00:43 -0700136 AOS_CHECK_GE(static_cast<size_t>(remaining_space.size()), sizeof(crc));
Brian Silverman2eb89762019-02-17 15:16:37 -0800137 memcpy(&remaining_space[0], &crc, sizeof(crc));
138 remaining_space = remaining_space.subspan(sizeof(crc));
139 }
Austin Schuhf257f3c2019-10-27 21:00:43 -0700140 AOS_CHECK(remaining_space.empty());
Brian Silverman2eb89762019-02-17 15:16:37 -0800141 UartToCameraBuffer result;
Tyler Chatowd0a49742022-02-25 22:06:19 -0800142 result.resize(result.capacity());
143 result.resize(
144 CobsEncode<uart_to_camera_size()>(buffer, absl::Span<char>(result))
Brian Silverman2eb89762019-02-17 15:16:37 -0800145 .size());
146 return result;
147}
Brian Silvermanbfbbe872019-02-10 18:00:57 -0800148
James Kuszmaul3ae42262019-11-08 12:33:41 -0800149std::optional<CameraCalibration> UartUnpackToCamera(
Austin Schuhb72be802022-01-02 12:26:28 -0800150 absl::Span<const char> encoded_buffer) {
Brian Silverman2eb89762019-02-17 15:16:37 -0800151 std::array<char, uart_to_camera_size()> buffer;
152 if (static_cast<size_t>(
153 CobsDecode<uart_to_camera_size()>(encoded_buffer, &buffer).size()) !=
154 buffer.size()) {
James Kuszmaul3ae42262019-11-08 12:33:41 -0800155 return std::nullopt;
Brian Silverman2eb89762019-02-17 15:16:37 -0800156 }
157
158 CameraCalibration message;
Austin Schuhb72be802022-01-02 12:26:28 -0800159 absl::Span<const char> remaining_input(buffer);
Brian Silverman2eb89762019-02-17 15:16:37 -0800160 for (int i = 0; i < 3; ++i) {
161 for (int j = 0; j < 4; ++j) {
162 memcpy(&message.calibration(i, j), remaining_input.data(), sizeof(float));
163 remaining_input = remaining_input.subspan(sizeof(float));
164 }
165 }
166 {
167 int64_t teensy_now;
168 memcpy(&teensy_now, remaining_input.data(), sizeof(teensy_now));
169 message.teensy_now = aos::monotonic_clock::time_point(
170 aos::monotonic_clock::duration(teensy_now));
171 remaining_input = remaining_input.subspan(sizeof(teensy_now));
172 }
173 {
174 int64_t realtime_now;
175 memcpy(&realtime_now, remaining_input.data(), sizeof(realtime_now));
176 message.realtime_now = aos::realtime_clock::time_point(
177 aos::realtime_clock::duration(realtime_now));
178 remaining_input = remaining_input.subspan(sizeof(realtime_now));
179 }
180 memcpy(&message.camera_command, remaining_input.data(), 1);
181 remaining_input = remaining_input.subspan(1);
182 {
183 uint16_t calculated_crc = jevois_crc_init();
184 calculated_crc = jevois_crc_update(calculated_crc, buffer.data(),
185 buffer.size() - remaining_input.size());
186 calculated_crc = jevois_crc_finalize(calculated_crc);
187 uint16_t received_crc;
Austin Schuhf257f3c2019-10-27 21:00:43 -0700188 AOS_CHECK_GE(static_cast<size_t>(remaining_input.size()),
189 sizeof(received_crc));
Brian Silverman2eb89762019-02-17 15:16:37 -0800190 memcpy(&received_crc, &remaining_input[0], sizeof(received_crc));
191 remaining_input = remaining_input.subspan(sizeof(received_crc));
Austin Schuhf257f3c2019-10-27 21:00:43 -0700192 AOS_CHECK(remaining_input.empty());
Brian Silverman2eb89762019-02-17 15:16:37 -0800193 if (calculated_crc != received_crc) {
James Kuszmaul3ae42262019-11-08 12:33:41 -0800194 return std::nullopt;
Brian Silverman2eb89762019-02-17 15:16:37 -0800195 }
196 }
197 return message;
Brian Silvermanbfbbe872019-02-10 18:00:57 -0800198}
199
200} // namespace jevois
201} // namespace frc971