1use bitflags::bitflags;
2use heapless::Deque;
3use messages::*;
4
5pub const PARAM_SET_BURST_QUEUE_CAPACITY: usize = 512;
10pub const PARAM_SET_INGRESS_QUEUE_CAPACITY: usize = PARAM_SET_BURST_QUEUE_CAPACITY;
11pub const PARAM_SET_EVENT_QUEUE_CAPACITY: usize = PARAM_SET_BURST_QUEUE_CAPACITY;
12pub const PARAM_READ_INGRESS_QUEUE_CAPACITY: usize = PARAM_SET_BURST_QUEUE_CAPACITY;
13
14#[derive(Default)]
15pub struct Messages {
16 pub heartbeat: Option<HeartbeatMsg>,
17 pub param_request_read: Deque<ParamRequestReadMsg, PARAM_READ_INGRESS_QUEUE_CAPACITY>,
18 pub param_request_list: Option<ParamRequestListMsg>,
19 pub param_set: Deque<ParamSetMsg, PARAM_SET_INGRESS_QUEUE_CAPACITY>,
20 pub timesync: Option<TimesyncMsg>,
21 pub offboard_control: Option<OffboardControlMsg>,
22 pub cmd: Option<RosflightCmdMsg>,
23 pub aux_cmd: Option<RosflightAuxCmdMsg>,
24 pub external_attitude: Option<ExternalAttitudeMsg>,
25 pub rc_raw: Option<RcChannelsMsg>,
26}
27
28impl Messages {
29 pub fn has_pending(&self) -> bool {
30 self.heartbeat.is_some()
31 || !self.param_request_read.is_empty()
32 || self.param_request_list.is_some()
33 || !self.param_set.is_empty()
34 || self.timesync.is_some()
35 || self.offboard_control.is_some()
36 || self.cmd.is_some()
37 || self.aux_cmd.is_some()
38 || self.external_attitude.is_some()
39 || self.rc_raw.is_some()
40 }
41}
42
43pub trait Store<T> {
44 fn store(&mut self, msg: T);
45 fn take(&mut self) -> Option<T>;
46}
47
48macro_rules! impl_store {
50 ($ty:ty, $field:ident, $name:literal) => {
51 impl Store<$ty> for Messages {
52 fn store(&mut self, msg: $ty) {
53 let _ = self.$field.insert(msg);
54 }
55 fn take(&mut self) -> Option<$ty> {
56 self.$field.take()
57 }
58 }
59 };
60}
61
62impl_store!(HeartbeatMsg, heartbeat, "heartbeat");
64impl Store<ParamRequestReadMsg> for Messages {
65 fn store(&mut self, msg: ParamRequestReadMsg) {
66 if self.param_request_read.push_back(msg).is_err() {
67 crate::log_warn!("message queue full: param_request_read");
68 }
69 }
70
71 fn take(&mut self) -> Option<ParamRequestReadMsg> {
72 self.param_request_read.pop_front()
73 }
74}
75impl_store!(
76 ParamRequestListMsg,
77 param_request_list,
78 "param_request_list"
79);
80impl Store<ParamSetMsg> for Messages {
81 fn store(&mut self, msg: ParamSetMsg) {
82 if self.param_set.push_back(msg).is_err() {
83 crate::log_warn!("message queue full: param_set");
84 }
85 }
86
87 fn take(&mut self) -> Option<ParamSetMsg> {
88 self.param_set.pop_front()
89 }
90}
91impl_store!(TimesyncMsg, timesync, "timesync");
92impl_store!(OffboardControlMsg, offboard_control, "offboard_control");
93impl_store!(RosflightCmdMsg, cmd, "cmd");
94impl_store!(RosflightAuxCmdMsg, aux_cmd, "aux_cmd");
95impl_store!(ExternalAttitudeMsg, external_attitude, "external_attitude");
96
97pub mod messages {
98 use super::enums::*;
99 use crate::{packets::GNSSFixType, params::ParamValue, state_machine::ErrorFlag};
100 #[derive(Debug, Clone, Copy)]
103 pub struct HeartbeatMsg {
104 pub type_: u8, pub autopilot: u8, pub base_mode: u8, pub custom_mode: u32,
108 pub system_status: u8, pub mavlink_version: u8, }
111
112 #[derive(Debug, Clone, Copy)]
115 pub struct ParamRequestReadMsg {
116 pub target_system: u8,
117 pub target_component: u8,
118 pub param_identifier: ParamIdentifier,
119 }
120
121 #[derive(Debug, Clone, Copy)]
122 pub struct ParamRequestListMsg {
123 pub target_system: u8,
124 pub target_component: u8,
125 }
126
127 #[derive(Debug, Clone, Copy)]
128 pub struct ParamValueMsg {
129 pub param_id: [u8; 16],
130 pub param_value: ParamValue,
131 pub param_count: u16,
132 pub param_index: u16,
133 }
134
135 #[derive(Debug, Clone, Copy)]
136 pub struct ParamSetMsg {
137 pub target_system: u8,
138 pub target_component: u8,
139 pub param_id: [u8; 16],
140 pub param_value: ParamValue,
141 }
142
143 #[derive(Debug, Clone, Copy)]
144 pub struct AttitudeQuaternionMsg {
145 pub time_boot_ms: u32,
146 pub q1: f32, pub q2: f32, pub q3: f32, pub q4: f32, pub rollspeed: f32, pub pitchspeed: f32, pub yawspeed: f32, }
154
155 pub const RC_PACKET_CHANNELS: usize = 24;
157 #[derive(Debug, Clone, Copy)]
158 pub struct RcChannelsMsg {
159 pub time_boot_ms: u32,
160 pub chancount: u8,
161 pub channels: [u16; RC_PACKET_CHANNELS],
162 pub rssi: u8,
163 }
164
165 #[derive(Debug, Clone, Copy)]
166 pub struct TimesyncMsg {
167 pub tc1: i64,
168 pub ts1: i64,
169 }
170
171 #[derive(Debug, Clone, Copy)]
172 pub struct StatustextMsg {
173 pub severity: Severity,
174 pub text: [u8; 50],
175 }
176
177 #[derive(Debug, Clone, Copy)]
180 pub struct OffboardControlMsg {
181 pub mode: OffboardControlMode,
182 pub ignore: OffboardControlIgnore,
183 pub qx: f32,
184 pub qy: f32,
185 pub qz: f32,
186 pub fx: f32,
187 pub fy: f32,
188 pub fz: f32,
189 pub passthrough: [f32; 4],
190 }
191
192 #[derive(Debug, Clone, Copy)]
193 pub struct SmallImuMsg {
194 pub time_boot_us: u64,
195 pub xacc: f32,
196 pub yacc: f32,
197 pub zacc: f32,
198 pub xgyro: f32,
199 pub ygyro: f32,
200 pub zgyro: f32,
201 pub temperature: f32,
202 }
203
204 #[derive(Debug, Clone, Copy)]
205 pub struct SmallMagMsg {
206 pub xmag: f32,
207 pub ymag: f32,
208 pub zmag: f32,
209 }
210
211 #[derive(Debug, Clone, Copy)]
212 pub struct SmallBaroMsg {
213 pub altitude: f32, pub pressure: f32, pub temperature: f32, }
217
218 #[derive(Debug, Clone, Copy)]
219 pub struct DiffPressureMsg {
220 pub velocity: f32, pub diff_pressure: f32, pub temperature: f32, }
224
225 #[derive(Debug, Clone, Copy)]
226 pub struct SmallRangeMsg {
227 pub type_: RosflightRangeType,
228 pub range: f32, pub max_range: f32, pub min_range: f32, }
232
233 #[derive(Debug, Clone, Copy)]
234 pub struct RosflightCmdMsg {
235 pub command: RosflightCmd,
236 }
237
238 #[derive(Debug, Clone, Copy)]
239 pub struct RosflightCmdAckMsg {
240 pub command: RosflightCmd,
241 pub success: RosflightCmdResponse,
242 }
243
244 #[derive(Debug, Clone, Copy)]
245 pub struct RosflightOutputRawMsg {
246 pub stamp: u64,
247 pub values: [f32; 14],
248 }
249
250 #[derive(Debug, Clone, Copy)]
251 pub struct RosflightStatusMsg {
252 pub armed: u8,
253 pub failsafe: u8,
254 pub rc_override: u16,
255 pub offboard: u8,
256 pub error_code: ErrorFlag,
257 pub control_mode: OffboardControlMode,
258 pub num_errors: i16,
259 pub loop_time_us: i16,
260 }
261
262 #[derive(Debug, Clone, Copy)]
263 pub struct RosflightVersionMsg {
264 pub version: [u8; 50],
265 }
266
267 #[derive(Debug, Clone, Copy)]
268 pub struct RosflightAuxCmdMsg {
269 pub type_array: [RosflightAuxCmdType; 14usize],
270 pub aux_cmd_array: [f32; 14],
271 }
272
273 #[derive(Debug, Clone, Copy)]
274 pub struct ExternalAttitudeMsg {
275 pub qw: f32,
276 pub qx: f32,
277 pub qy: f32,
278 pub qz: f32,
279 }
280
281 #[derive(Debug, Clone, Copy)]
282 pub struct RosflightHardErrorMsg {
283 pub error_code: u32,
284 pub pc: u32,
285 pub reset_count: u32,
286 pub do_rearm: u32,
287 }
288
289 #[derive(Debug, Clone, Copy)]
290 pub struct RosflightGnssMsg {
291 pub seconds: i64,
292 pub nanos: i32,
293 pub fix_type: GNSSFixType,
294 pub num_sat: u8,
295 pub lat: f64, pub lon: f64, pub height: f32, pub vel_n: f32, pub vel_e: f32, pub vel_d: f32, pub h_acc: f32, pub v_acc: f32, pub s_acc: f32, pub rosflight_timestamp: u64, }
306
307 #[derive(Debug, Clone, Copy)]
308 pub struct BatteryStatusMsg {
309 pub battery_voltage: f32,
310 pub battery_current: f32,
311 }
312
313 #[derive(Debug, Clone, Copy)]
314 pub enum DownlinkMessage {
315 Heartbeat(HeartbeatMsg),
316 ParamValue(ParamValueMsg),
317 Status(RosflightStatusMsg),
318 Timesync(TimesyncMsg),
319 Version(RosflightVersionMsg),
320 OutputRaw(RosflightOutputRawMsg),
321 Attitude(AttitudeQuaternionMsg),
322 Baro(SmallBaroMsg),
323 DiffPressure(DiffPressureMsg),
324 Imu(SmallImuMsg),
325 Mag(SmallMagMsg),
326 RcRaw(RcChannelsMsg),
327 Range(SmallRangeMsg),
328 Gnss(RosflightGnssMsg),
329 CmdAck(RosflightCmdAckMsg),
330 RcChannels(RcChannelsMsg),
331 BatteryStatus(BatteryStatusMsg),
332 Statustext(StatustextMsg),
333 HardError(RosflightHardErrorMsg),
334 }
335}
336
337pub mod enums {
340 use super::bitflags;
341
342 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
343 pub enum RosflightCmd {
344 RcCalibration,
345 AccelCalibration,
346 GyroCalibration,
347 BaroCalibration,
348 AirspeedCalibration,
349 ReadParams,
350 WriteParams,
351 SetParamDefaults,
352 Reboot,
353 RebootToBootloader,
354 SendVersion,
355 ResetOrigin,
356 SendAllConfigInfos,
357 }
358
359 #[derive(Debug, Clone, Copy)]
360 pub enum RosflightCmdResponse {
361 RosflightCmdFailed,
362 RosflightCmdSuccess,
363 }
364
365 #[repr(u8)]
366 #[derive(Clone, Copy, Debug, PartialEq, Default)]
367 pub enum OffboardControlMode {
368 ModePassThrough = 0,
369 ModeRollratePitchrateYawrateThrottle = 1,
370 #[default]
371 ModeRollPitchYawrateThrottle = 2,
372 }
373
374 #[derive(Debug, Clone, Copy)]
375 pub enum RosflightAuxCmdType {
376 Disabled,
377 Servo,
378 Motor,
379 }
380
381 #[derive(Debug, Clone, Copy)]
382 pub enum Severity {
383 Emergency,
384 Alert,
385 Critical,
386 Error,
387 Warning,
388 Notice,
389 Info,
390 Debug,
391 }
392
393 bitflags! {
394 #[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
395 pub struct OffboardControlIgnore: u16 {
396 const IGNORE_FX = 1 << 0;
397 const IGNORE_FY = 1 << 1;
398 const IGNORE_FZ = 1 << 2;
399 const IGNORE_QX = 1 << 3;
400 const IGNORE_QY = 1 << 4;
401 const IGNORE_QZ = 1 << 5;
402 const IGNORE_PASS_0 = 1 << 6;
403 const IGNORE_PASS_1 = 1 << 7;
404 const IGNORE_PASS_2 = 1 << 8;
405 const IGNORE_PASS_3 = 1 << 9;
406 }
407 }
408
409 impl OffboardControlIgnore {
410 pub fn is_ignoring_qx(&self) -> bool {
411 self.intersects(Self::IGNORE_QX)
412 }
413
414 pub fn is_ignoring_qy(&self) -> bool {
415 self.intersects(Self::IGNORE_QY)
416 }
417
418 pub fn is_ignoring_qz(&self) -> bool {
419 self.intersects(Self::IGNORE_QZ)
420 }
421
422 pub fn is_ignoring_fx(&self) -> bool {
423 self.intersects(Self::IGNORE_FX)
424 }
425
426 pub fn is_ignoring_fy(&self) -> bool {
427 self.intersects(Self::IGNORE_FY)
428 }
429
430 pub fn is_ignoring_fz(&self) -> bool {
431 self.intersects(Self::IGNORE_FZ)
432 }
433 }
434
435 #[derive(Debug, Clone, Copy)]
436 pub enum GnssFixType {
437 GnssFixNoFix,
438 GnssFixDeadReckoningOnly,
439 GnssFix2dFix,
440 GnssFix3dFix,
441 GnssFixGnssPlusDeadReckoning,
442 GnssFixTimeFixOnly,
443 }
444
445 #[derive(Debug, Clone, Copy, Default)]
446 pub enum RosflightRangeType {
447 #[default]
448 RosflightRangeSonar,
449 RosflightRangeLidar,
450 }
451
452 #[derive(Debug, Clone, Copy)]
453 pub enum MavType {
454 Generic,
455 FixedWing,
456 Quadrotor,
457 }
458
459 #[derive(Debug, Clone, Copy, Default)]
460 pub enum LogLevel {
461 #[default]
462 Info,
463 Warn,
464 Error,
465 }
466
467 #[derive(Debug, Clone, Copy, PartialEq)]
468 pub enum ParamIdentifier {
469 ID([u8; 16]),
470 INDEX(i16),
471 }
472}