blackbox_log/frame/gps/
mod.rs1mod def;
2
3use alloc::vec::Vec;
4
5pub use self::def::*;
6use super::Unit;
7use crate::filter::AppliedFilter;
8use crate::units::prelude::*;
9use crate::utils::as_i32;
10use crate::{units, Headers};
11
12#[derive(Debug, Clone)]
14pub struct GpsFrame<'data, 'headers, 'parser> {
15 headers: &'headers Headers<'data>,
16 raw: RawGpsFrame,
17 filter: &'parser AppliedFilter,
18}
19
20impl super::seal::Sealed for GpsFrame<'_, '_, '_> {}
21
22impl super::Frame for GpsFrame<'_, '_, '_> {
23 type Value = GpsValue;
24
25 #[inline]
26 fn len(&self) -> usize {
27 self.filter.len()
28 }
29
30 fn get_raw(&self, index: usize) -> Option<u32> {
31 let index = self.filter.get(index)?;
32 Some(self.raw.values[index])
33 }
34
35 fn get(&self, index: usize) -> Option<Self::Value> {
36 let frame_def = self.headers.gps_frame_def().unwrap();
37 let index = self.filter.get(index)?;
38
39 let def = &frame_def.fields[index];
40 let raw = self.raw.values[index];
41
42 let value = match def.unit {
43 GpsUnit::Coordinate => {
44 assert!(def.signed);
45 let value = as_i32(raw);
46
47 GpsValue::Coordinate(f64::from(value) / 10000000.)
48 }
49 GpsUnit::Altitude => {
50 let altitude = if def.signed {
51 as_i32(raw).into()
52 } else {
53 raw.into()
54 };
55
56 GpsValue::Altitude(Length::new::<meter>(altitude))
57 }
58 GpsUnit::Velocity => {
59 assert!(!def.signed);
60 GpsValue::Velocity(units::new::velocity(raw))
61 }
62 GpsUnit::Heading => {
63 assert!(!def.signed);
64 GpsValue::Heading(f64::from(raw) / 10.)
65 }
66 GpsUnit::Unitless => GpsValue::new_unitless(raw, def.signed),
67 };
68
69 Some(value)
70 }
71}
72
73impl<'data, 'headers, 'parser> GpsFrame<'data, 'headers, 'parser> {
74 pub(crate) fn new(
75 headers: &'headers Headers<'data>,
76 raw: RawGpsFrame,
77 filter: &'parser AppliedFilter,
78 ) -> Self {
79 Self {
80 headers,
81 raw,
82 filter,
83 }
84 }
85
86 pub fn time(&self) -> Time {
88 units::new::time(self.raw.time)
89 }
90
91 pub fn time_raw(&self) -> u64 {
96 self.raw.time
97 }
98}
99
100#[derive(Debug, Clone)]
101pub(crate) struct RawGpsFrame {
102 pub(crate) time: u64,
103 pub(crate) values: Vec<u32>,
104}
105
106#[derive(Debug, Clone, Copy, PartialEq)]
107pub enum GpsValue {
108 Coordinate(f64),
109 Altitude(Length),
110 Velocity(Velocity),
111 Heading(f64),
112 Unsigned(u32),
113 Signed(i32),
114}
115
116impl GpsValue {
117 const fn new_unitless(value: u32, signed: bool) -> Self {
118 if signed {
119 Self::Signed(as_i32(value))
120 } else {
121 Self::Unsigned(value)
122 }
123 }
124}
125
126impl From<GpsValue> for super::Value {
127 fn from(value: GpsValue) -> Self {
128 match value {
129 GpsValue::Coordinate(c) => Self::GpsCoordinate(c),
130 GpsValue::Altitude(a) => Self::Altitude(a),
131 GpsValue::Velocity(v) => Self::Velocity(v),
132 GpsValue::Heading(h) => Self::GpsHeading(h),
133 GpsValue::Unsigned(x) => Self::Unsigned(x),
134 GpsValue::Signed(x) => Self::Signed(x),
135 }
136 }
137}
138
139#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
140pub enum GpsUnit {
141 Coordinate,
142 Altitude,
143 Velocity,
144 Heading,
145 Unitless,
146}
147
148impl From<GpsUnit> for Unit {
149 fn from(unit: GpsUnit) -> Self {
150 match unit {
151 GpsUnit::Coordinate => Self::GpsCoordinate,
152 GpsUnit::Altitude => Self::Altitude,
153 GpsUnit::Velocity => Self::Velocity,
154 GpsUnit::Heading => Self::GpsHeading,
155 GpsUnit::Unitless => Self::Unitless,
156 }
157 }
158}