blob: 93e007287af476a3822674f0e3ef2a8682601259 [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
Stephan Pleinesf63bde82024-01-13 15:59:33 -080016namespace frc971::jevois {
Brian Silvermanbfbbe872019-02-10 18:00:57 -080017
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;
Austin Schuhb72be802022-01-02 12:26:28 -080020 absl::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;
Tyler Chatowd0a49742022-02-25 22:06:19 -080052 result.resize(result.capacity());
53 result.resize(
54 CobsEncode<uart_to_teensy_size()>(buffer, absl::Span<char>(result))
Brian Silverman2eb89762019-02-17 15:16:37 -080055 .size());
56 return result;
57}
58
James Kuszmaul3ae42262019-11-08 12:33:41 -080059std::optional<CameraFrame> UartUnpackToTeensy(
Austin Schuhb72be802022-01-02 12:26:28 -080060 absl::Span<const char> encoded_buffer) {
Brian Silverman2eb89762019-02-17 15:16:37 -080061 std::array<char, uart_to_teensy_size()> buffer;
62 if (static_cast<size_t>(
63 CobsDecode<uart_to_teensy_size()>(encoded_buffer, &buffer).size()) !=
64 buffer.size()) {
James Kuszmaul3ae42262019-11-08 12:33:41 -080065 return std::nullopt;
Brian Silverman2eb89762019-02-17 15:16:37 -080066 }
67
Brian Silvermanc41fb862019-03-02 21:14:46 -080068 CameraFrame message;
Austin Schuhb72be802022-01-02 12:26:28 -080069 absl::Span<const char> remaining_input(buffer);
Brian Silvermana1e4d332019-02-17 22:53:13 -080070 const int number_targets = remaining_input[0];
71 remaining_input = remaining_input.subspan(1);
Brian Silverman2eb89762019-02-17 15:16:37 -080072 for (int i = 0; i < 3; ++i) {
Brian Silvermana1e4d332019-02-17 22:53:13 -080073 if (i < number_targets) {
74 message.targets.push_back({});
75 Target *const target = &message.targets.back();
76 memcpy(&target->distance, remaining_input.data(), sizeof(float));
77 remaining_input = remaining_input.subspan(sizeof(float));
78 memcpy(&target->height, remaining_input.data(), sizeof(float));
79 remaining_input = remaining_input.subspan(sizeof(float));
80 memcpy(&target->heading, remaining_input.data(), sizeof(float));
81 remaining_input = remaining_input.subspan(sizeof(float));
82 memcpy(&target->skew, remaining_input.data(), sizeof(float));
83 remaining_input = remaining_input.subspan(sizeof(float));
84 } else {
85 remaining_input = remaining_input.subspan(sizeof(float) * 4);
86 }
Brian Silverman2eb89762019-02-17 15:16:37 -080087 }
88 message.age = camera_duration(remaining_input[0]);
89 remaining_input = remaining_input.subspan(1);
90 {
91 uint16_t calculated_crc = jevois_crc_init();
92 calculated_crc = jevois_crc_update(calculated_crc, buffer.data(),
93 buffer.size() - remaining_input.size());
94 calculated_crc = jevois_crc_finalize(calculated_crc);
95 uint16_t received_crc;
Austin Schuhf257f3c2019-10-27 21:00:43 -070096 AOS_CHECK_GE(static_cast<size_t>(remaining_input.size()),
97 sizeof(received_crc));
Brian Silverman2eb89762019-02-17 15:16:37 -080098 memcpy(&received_crc, &remaining_input[0], sizeof(received_crc));
99 remaining_input = remaining_input.subspan(sizeof(received_crc));
Austin Schuhf257f3c2019-10-27 21:00:43 -0700100 AOS_CHECK(remaining_input.empty());
Brian Silverman2eb89762019-02-17 15:16:37 -0800101 if (calculated_crc != received_crc) {
James Kuszmaul3ae42262019-11-08 12:33:41 -0800102 return std::nullopt;
Brian Silverman2eb89762019-02-17 15:16:37 -0800103 }
104 }
105 return message;
106}
107
108UartToCameraBuffer UartPackToCamera(const CameraCalibration &message) {
109 std::array<char, uart_to_camera_size()> buffer;
Austin Schuhb72be802022-01-02 12:26:28 -0800110 absl::Span<char> remaining_space(buffer);
Brian Silverman2eb89762019-02-17 15:16:37 -0800111 for (int i = 0; i < 3; ++i) {
112 for (int j = 0; j < 4; ++j) {
113 memcpy(remaining_space.data(), &message.calibration(i, j), sizeof(float));
114 remaining_space = remaining_space.subspan(sizeof(float));
115 }
116 }
117 {
118 const int64_t teensy_now = message.teensy_now.time_since_epoch().count();
119 memcpy(remaining_space.data(), &teensy_now, sizeof(teensy_now));
120 remaining_space = remaining_space.subspan(sizeof(teensy_now));
121 }
122 {
123 const int64_t realtime_now =
124 message.realtime_now.time_since_epoch().count();
125 memcpy(remaining_space.data(), &realtime_now, sizeof(realtime_now));
126 remaining_space = remaining_space.subspan(sizeof(realtime_now));
127 }
128 memcpy(remaining_space.data(), &message.camera_command, 1);
129 remaining_space = remaining_space.subspan(1);
130 {
131 uint16_t crc = jevois_crc_init();
132 crc = jevois_crc_update(crc, buffer.data(),
133 buffer.size() - remaining_space.size());
134 crc = jevois_crc_finalize(crc);
Austin Schuhf257f3c2019-10-27 21:00:43 -0700135 AOS_CHECK_GE(static_cast<size_t>(remaining_space.size()), sizeof(crc));
Brian Silverman2eb89762019-02-17 15:16:37 -0800136 memcpy(&remaining_space[0], &crc, sizeof(crc));
137 remaining_space = remaining_space.subspan(sizeof(crc));
138 }
Austin Schuhf257f3c2019-10-27 21:00:43 -0700139 AOS_CHECK(remaining_space.empty());
Brian Silverman2eb89762019-02-17 15:16:37 -0800140 UartToCameraBuffer result;
Tyler Chatowd0a49742022-02-25 22:06:19 -0800141 result.resize(result.capacity());
142 result.resize(
143 CobsEncode<uart_to_camera_size()>(buffer, absl::Span<char>(result))
Brian Silverman2eb89762019-02-17 15:16:37 -0800144 .size());
145 return result;
146}
Brian Silvermanbfbbe872019-02-10 18:00:57 -0800147
James Kuszmaul3ae42262019-11-08 12:33:41 -0800148std::optional<CameraCalibration> UartUnpackToCamera(
Austin Schuhb72be802022-01-02 12:26:28 -0800149 absl::Span<const char> encoded_buffer) {
Brian Silverman2eb89762019-02-17 15:16:37 -0800150 std::array<char, uart_to_camera_size()> buffer;
151 if (static_cast<size_t>(
152 CobsDecode<uart_to_camera_size()>(encoded_buffer, &buffer).size()) !=
153 buffer.size()) {
James Kuszmaul3ae42262019-11-08 12:33:41 -0800154 return std::nullopt;
Brian Silverman2eb89762019-02-17 15:16:37 -0800155 }
156
157 CameraCalibration message;
Austin Schuhb72be802022-01-02 12:26:28 -0800158 absl::Span<const char> remaining_input(buffer);
Brian Silverman2eb89762019-02-17 15:16:37 -0800159 for (int i = 0; i < 3; ++i) {
160 for (int j = 0; j < 4; ++j) {
161 memcpy(&message.calibration(i, j), remaining_input.data(), sizeof(float));
162 remaining_input = remaining_input.subspan(sizeof(float));
163 }
164 }
165 {
166 int64_t teensy_now;
167 memcpy(&teensy_now, remaining_input.data(), sizeof(teensy_now));
168 message.teensy_now = aos::monotonic_clock::time_point(
169 aos::monotonic_clock::duration(teensy_now));
170 remaining_input = remaining_input.subspan(sizeof(teensy_now));
171 }
172 {
173 int64_t realtime_now;
174 memcpy(&realtime_now, remaining_input.data(), sizeof(realtime_now));
175 message.realtime_now = aos::realtime_clock::time_point(
176 aos::realtime_clock::duration(realtime_now));
177 remaining_input = remaining_input.subspan(sizeof(realtime_now));
178 }
179 memcpy(&message.camera_command, remaining_input.data(), 1);
180 remaining_input = remaining_input.subspan(1);
181 {
182 uint16_t calculated_crc = jevois_crc_init();
183 calculated_crc = jevois_crc_update(calculated_crc, buffer.data(),
184 buffer.size() - remaining_input.size());
185 calculated_crc = jevois_crc_finalize(calculated_crc);
186 uint16_t received_crc;
Austin Schuhf257f3c2019-10-27 21:00:43 -0700187 AOS_CHECK_GE(static_cast<size_t>(remaining_input.size()),
188 sizeof(received_crc));
Brian Silverman2eb89762019-02-17 15:16:37 -0800189 memcpy(&received_crc, &remaining_input[0], sizeof(received_crc));
190 remaining_input = remaining_input.subspan(sizeof(received_crc));
Austin Schuhf257f3c2019-10-27 21:00:43 -0700191 AOS_CHECK(remaining_input.empty());
Brian Silverman2eb89762019-02-17 15:16:37 -0800192 if (calculated_crc != received_crc) {
James Kuszmaul3ae42262019-11-08 12:33:41 -0800193 return std::nullopt;
Brian Silverman2eb89762019-02-17 15:16:37 -0800194 }
195 }
196 return message;
Brian Silvermanbfbbe872019-02-10 18:00:57 -0800197}
198
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800199} // namespace frc971::jevois