Skip to main content

gnss_protos/gps/
frame2.rs

1use crate::twos_complement;
2
3const WORD3_IODE_MASK: u32 = 0x3fc00000;
4const WORD3_IODE_SHIFT: u32 = 22;
5const WORD3_CRS_MASK: u32 = 0x003fffc0;
6const WORD3_CRS_SHIFT: u32 = 6;
7
8const WORD4_DELTA_N_MASK: u32 = 0x3fffc000;
9const WORD4_DELTA_N_SHIFT: u32 = 14;
10const WORD4_M0_MSB_MASK: u32 = 0x00003fc0;
11const WORD4_M0_MSB_SHIFT: u32 = 6;
12
13const WORD5_M0_LSB_MASK: u32 = 0x3fffffc0;
14const WORD5_M0_LSB_SHIFT: u32 = 6;
15
16const WORD6_CUC_MASK: u32 = 0x3fffc000;
17const WORD6_CUC_SHIFT: u32 = 14;
18const WORD6_E_MSB_MASK: u32 = 0x00003fc0;
19const WORD6_E_MSB_SHIFT: u32 = 6;
20
21const WORD7_E_LSB_MASK: u32 = 0x3fffffc0;
22const WORD7_E_LSB_SHIFT: u32 = 6;
23
24const WORD8_CUS_MASK: u32 = 0x3fffc000;
25const WORD8_CUS_SHIFT: u32 = 14;
26const WORD8_SQRTA_MSB_MASK: u32 = 0x00003fc0;
27const WORD8_SQRTA_MSB_SHIFT: u32 = 6;
28
29const WORD9_SQRTA_LSB_MASK: u32 = 0x3fffffc0;
30const WORD9_SQRTA_LSB_SHIFT: u32 = 6;
31
32const WORD10_TOE_MASK: u32 = 0x3fffc000;
33const WORD10_TOE_SHIFT: u32 = 14;
34const WORD10_FITINT_MASK: u32 = 0x00002000;
35const WORD10_AODO_MASK: u32 = 0x00001f00;
36const WORD10_AODO_SHIFT: u32 = 8;
37
38/// GPS / QZSS Frame #2 interpretation
39#[derive(Debug, Default, Copy, Clone, PartialEq)]
40pub struct GpsQzssFrame2 {
41    /// Time of issue of ephemeris (in seconds of week)
42    pub toe: u32,
43
44    /// IODE: Issue of Data (Ephemeris)
45    pub iode: u8,
46
47    /// Mean anomaly at reference time (in semi circles)
48    pub m0: f64,
49
50    /// Mean motion difference from computed value (in semi circles)
51    pub dn: f64,
52
53    /// Latitude cosine harmonic correction term
54    pub cuc: f64,
55
56    /// Latitude sine harmonic correction term
57    pub cus: f64,
58
59    /// Orbit radius sine harmonic correction term
60    pub crs: f64,
61
62    /// Eccentricity
63    pub e: f64,
64
65    /// Sqrt(a)
66    pub sqrt_a: f64,
67
68    /// Fit interval flag
69    pub fit_int_flag: bool,
70
71    /// 5-bit AODO
72    pub aodo: u8,
73}
74
75#[derive(Debug, Default, Clone)]
76pub struct Word3 {
77    pub iode: u8,
78    pub crs: i32,
79}
80
81impl Word3 {
82    pub(crate) fn decode(dword: u32) -> Self {
83        let iode = ((dword & WORD3_IODE_MASK) >> WORD3_IODE_SHIFT) as u8;
84        let crs = ((dword & WORD3_CRS_MASK) >> WORD3_CRS_SHIFT) as u32;
85        let crs = twos_complement(crs, 0xffff, 0x8000);
86        Self { iode, crs }
87    }
88}
89
90#[derive(Debug, Default, Clone)]
91pub struct Word4 {
92    /// Delta n
93    pub dn: i16,
94
95    /// M0 (8) msb, you need to associate this to Subframe #2 Word #5
96    pub m0_msb: u8,
97}
98
99impl Word4 {
100    pub(crate) fn decode(dword: u32) -> Self {
101        let dn = ((dword & WORD4_DELTA_N_MASK) >> WORD4_DELTA_N_SHIFT) as i16;
102        let m0_msb = ((dword & WORD4_M0_MSB_MASK) >> WORD4_M0_MSB_SHIFT) as u8;
103        Self { dn, m0_msb }
104    }
105}
106
107#[derive(Debug, Default, Clone)]
108pub struct Word5 {
109    /// M0 (24) lsb, you need to associate this to Subframe #2 Word #4
110    pub m0_lsb: u32,
111}
112
113impl Word5 {
114    pub(crate) fn decode(dword: u32) -> Self {
115        let m0_lsb = ((dword & WORD5_M0_LSB_MASK) >> WORD5_M0_LSB_SHIFT) as u32;
116        Self { m0_lsb }
117    }
118}
119
120#[derive(Debug, Default, Clone)]
121pub struct Word6 {
122    pub cuc: i16,
123
124    /// MSB(8) eccentricity, you need to associate this to Subframe #2 Word #7
125    pub e_msb: u8,
126}
127
128impl Word6 {
129    pub(crate) fn decode(dword: u32) -> Self {
130        let cuc = ((dword & WORD6_CUC_MASK) >> WORD6_CUC_SHIFT) as i16;
131        let e_msb = ((dword & WORD6_E_MSB_MASK) >> WORD6_E_MSB_SHIFT) as u8;
132        Self { cuc, e_msb }
133    }
134}
135
136#[derive(Debug, Default, Clone)]
137pub struct Word7 {
138    /// LSB(24) eccentricity, you need to associate this to Subframe #2 Word #6
139    pub e_lsb: u32,
140}
141
142impl Word7 {
143    pub(crate) fn decode(dword: u32) -> Self {
144        let e_lsb = ((dword & WORD7_E_LSB_MASK) >> WORD7_E_LSB_SHIFT) as u32;
145        Self { e_lsb }
146    }
147}
148
149#[derive(Debug, Default, Clone)]
150pub struct Word8 {
151    pub cus: i32,
152
153    /// MSB(8) A⁻¹: you need to associate this to Subframe #2 Word #9
154    pub sqrt_a_msb: u8,
155}
156
157impl Word8 {
158    pub(crate) fn decode(dword: u32) -> Self {
159        let cus = ((dword & WORD8_CUS_MASK) >> WORD8_CUS_SHIFT) as u32;
160
161        let cus = twos_complement(cus, 0xffff, 0x8000);
162        let sqrt_a_msb = ((dword & WORD8_SQRTA_MSB_MASK) >> WORD8_SQRTA_MSB_SHIFT) as u8;
163        Self { cus, sqrt_a_msb }
164    }
165}
166
167#[derive(Debug, Default, Clone)]
168pub struct Word9 {
169    /// LSB(24) A⁻¹: you need to associate this to Subframe #2 Word #8
170    pub sqrt_a_lsb: u32,
171}
172
173impl Word9 {
174    pub(crate) fn decode(dword: u32) -> Self {
175        let sqrt_a_lsb = ((dword & WORD9_SQRTA_LSB_MASK) >> WORD9_SQRTA_LSB_SHIFT) as u32;
176        Self { sqrt_a_lsb }
177    }
178}
179
180#[derive(Debug, Default, Clone)]
181pub struct Word10 {
182    /// Time of issue of Ephemeris (u16)
183    pub toe: u16,
184
185    /// Fit interval, differs between GPS and QZSS
186    pub fitint: bool,
187
188    /// 5-bit AODO
189    pub aodo: u8,
190}
191
192impl Word10 {
193    pub(crate) fn decode(dword: u32) -> Self {
194        let toe = ((dword & WORD10_TOE_MASK) >> WORD10_TOE_SHIFT) as u16;
195        let fitint = (dword & WORD10_FITINT_MASK) > 0;
196        let aodo = ((dword & WORD10_AODO_MASK) >> WORD10_AODO_SHIFT) as u8;
197        Self { toe, fitint, aodo }
198    }
199}
200
201// impl UnscaledFrame {
202//     pub fn scale(&self) -> GpsQzssFrame2 {
203//         GpsQzssFrame2 {
204//             iode: self.word3.iode,
205//             toe: (self.word10.toe as u32) * 16,
206//             crs: (self.word3.crs as f64) / 2.0_f64.powi(5),
207//             cus: (self.word8.cus as f64) / 2.0_f64.powi(29),
208//             cuc: (self.word6.cuc as f64) / 2.0_f64.powi(29),
209
210//             dn: {
211//                 let dn = self.word4.dn as f64;
212//                 dn / 2.0_f64.powi(43)
213//             },
214
215//             m0: {
216//                 let mut m0 = self.word4.m0_msb as u32;
217//                 m0 <<= 24;
218//                 m0 |= self.word5.m0_lsb as u32;
219
220//                 let m0 = (m0 as i32) as f64;
221//                 m0 / 2.0_f64.powi(31)
222//             },
223
224//             e: {
225//                 let mut e = self.word6.e_msb as u32;
226//                 e <<= 24;
227//                 e |= self.word7.e_lsb;
228
229//                 (e as f64) / 2.0_f64.powi(33)
230//             },
231
232//             sqrt_a: {
233//                 let mut sqrt_a = self.word8.sqrt_a_msb as u32;
234//                 sqrt_a <<= 24;
235//                 sqrt_a |= self.word9.sqrt_a_lsb;
236
237//                 (sqrt_a as f64) / 2.0_f64.powi(19)
238//             },
239
240//             aodo: self.word10.aodo,
241//             fit_int_flag: self.word10.fitint,
242//         }
243//     }
244// }