Skip to main content

gnss_protos/gps/
frame1.rs

1use crate::twos_complement;
2
3const WORD3_WEEK_MASK: u32 = 0x3ff00000;
4const WORD3_WEEK_SHIFT: u32 = 20;
5const WORD3_CA_P_L2_MASK: u32 = 0x000C0000;
6const WORD3_CA_P_L2_SHIFT: u32 = 18;
7const WORD3_URA_MASK: u32 = 0x0003C000;
8const WORD3_URA_SHIFT: u32 = 14;
9const WORD3_HEALTH_MASK: u32 = 0x00003f00;
10const WORD3_HEALTH_SHIFT: u32 = 8;
11const WORD3_IODC_MASK: u32 = 0x000000c0;
12const WORD3_IODC_SHIFT: u32 = 6;
13
14const WORD4_L2P_DATA_MASK: u32 = 0x20000000;
15const WORD4_RESERVED_MASK: u32 = 0x1fffffc0;
16const WORD4_RESERVED_SHIFT: u32 = 6;
17
18const WORD5_RESERVED_MASK: u32 = 0x3fffffc0;
19const WORD5_RESERVED_SHIFT: u32 = 6;
20
21const WORD6_RESERVED_MASK: u32 = 0x3fffffc0;
22const WORD6_RESERVED_SHIFT: u32 = 6;
23
24const WORD7_RESERVED_MASK: u32 = 0x3fffc000;
25const WORD7_RESERVED_SHIFT: u32 = 14;
26const WORD7_TGD_MASK: u32 = 0x00003fc0;
27const WORD7_TGD_SHIFT: u32 = 6;
28
29const WORD8_IODC_MASK: u32 = 0x3fc00000;
30const WORD8_IODC_SHIFT: u32 = 22;
31const WORD8_TOC_MASK: u32 = 0x003fffc0;
32const WORD8_TOC_SHIFT: u32 = 6;
33
34const WORD9_AF2_MASK: u32 = 0x3fc00000;
35const WORD9_AF2_SHIFT: u32 = 22;
36const WORD9_AF1_MASK: u32 = 0x003fffc0;
37const WORD9_AF1_SHIFT: u32 = 6;
38
39const WORD10_AF0_MASK: u32 = 0x3fffff00;
40const WORD10_AF0_SHIFT: u32 = 8;
41
42/// GPS / QZSS Frame #1 interpretation
43#[derive(Debug, Default, Copy, Clone, PartialEq)]
44pub struct GpsQzssFrame1 {
45    /// 10-bit week counter (no rollover compensation).
46    pub week: u16,
47
48    /// 2-bit C/A or P ON L2.  
49    /// When asserted, indicates the NAV data stream was commanded OFF on the L2 channel P-code.
50    pub ca_or_p_l2: u8,
51
52    /// 4-bit URA index. The lower the better, interpret as follow (error in meters)
53    /// - 0:  0 < ura <= 2.4m
54    /// - 1:  2.4 < ura <= 3.4m
55    /// - 2:  3.4 < ura <= 4.85
56    /// - 3:  4.85 < ura <= 6.85
57    /// - 4:  6.85 < ura <= 9.65
58    /// - 5:  9.65 < ura <= 13.65
59    /// - 6:  13.65 < ura <= 24.00
60    /// - 7:  24.00 < ura <= 48.00
61    /// - 8:  48.00 < ura <= 96.00
62    /// - 9:  96.00 < ura <= 192.00
63    /// - 10: 192.00 < ura <=  384.00
64    /// - 11: 384.00 < ura <=  768.00
65    /// - 12: 768.00 < ura <= 1536.00
66    /// - 13: 1536.00 < ura <= 3072.00
67    /// - 14: 3072.00 < ura <= 6144.00
68    /// - 15: 6144.00 < ura
69    ///
70    /// For each URA index, users may compute a nominal URA value (x)
71    ///  - ura < 6: 2**(1+N/2)
72    ///  - ura > 6: 2**(N-2)
73    pub ura: u8,
74
75    /// 6-bit SV Health. 0 means all good.
76    pub health: u8,
77
78    /// 10-bit IODC.  
79    pub iodc: u16,
80
81    /// Time of clock (in seconds)
82    pub toc: u32,
83
84    /// 8-bit TGD (in seconds)
85    pub tgd: f64,
86
87    /// af2 (in seconds per s^-^&)
88    pub af2: f64,
89
90    /// af1 (in seconds per seconds)
91    pub af1: f64,
92
93    /// af0 (in seconds)
94    pub af0: f64,
95
96    /// 32-bit reserved word #4
97    pub reserved_word4: u32,
98
99    pub l2_p_data_flag: bool,
100
101    /// 24-bit reserved word #5
102    pub reserved_word5: u32,
103
104    /// 24-bit reserved word #6
105    pub reserved_word6: u32,
106
107    ///16-bit reserved word #7
108    pub reserved_word7: u16,
109}
110
111impl GpsQzssFrame1 {
112    pub fn with_week(mut self, week: u16) -> Self {
113        self.week = week;
114        self
115    }
116
117    pub fn with_health(mut self, health: u8) -> Self {
118        self.health = health;
119        self
120    }
121
122    pub fn with_toc(mut self, toc: u32) -> Self {
123        self.toc = toc;
124        self
125    }
126
127    pub fn with_tgd(mut self, tgd: f64) -> Self {
128        self.tgd = tgd;
129        self
130    }
131
132    pub fn with_ura(mut self, ura: u8) -> Self {
133        self.ura = ura;
134        self
135    }
136
137    pub fn with_af0(mut self, af0: f64) -> Self {
138        self.af0 = af0;
139        self
140    }
141
142    pub fn with_af1(mut self, af1: f64) -> Self {
143        self.af1 = af1;
144        self
145    }
146
147    pub fn with_af2(mut self, af2: f64) -> Self {
148        self.af2 = af2;
149        self
150    }
151}
152
153#[derive(Debug, Default, Clone)]
154pub struct Word3 {
155    /// 10-bit week counter
156    pub week: u16,
157
158    /// 2 bits C/A or P ON L2
159    pub ca_or_p_l2: u8,
160
161    /// 4-bit URA index
162    pub ura: u8,
163
164    /// 6-bit SV Health
165    pub health: u8,
166
167    /// 2-bit (MSB) IODC, you will have to associate this to Word # 8
168    pub iodc_msb: u8,
169}
170
171impl Word3 {
172    pub(crate) fn decode(dword: u32) -> Self {
173        let week = ((dword & WORD3_WEEK_MASK) >> WORD3_WEEK_SHIFT) as u16;
174        let ca_or_p_l2 = ((dword & WORD3_CA_P_L2_MASK) >> WORD3_CA_P_L2_SHIFT) as u8;
175        let ura = ((dword & WORD3_URA_MASK) >> WORD3_URA_SHIFT) as u8;
176        let health = ((dword & WORD3_HEALTH_MASK) >> WORD3_HEALTH_SHIFT) as u8;
177        let iodc_msb = ((dword & WORD3_IODC_MASK) >> WORD3_IODC_SHIFT) as u8;
178
179        Self {
180            week,
181            ca_or_p_l2,
182            ura,
183            health,
184            iodc_msb,
185        }
186    }
187}
188
189#[derive(Debug, Default, Clone)]
190pub struct Word4 {
191    pub l2_p_data_flag: bool,
192    pub reserved: u32,
193}
194
195impl Word4 {
196    pub(crate) fn decode(dword: u32) -> Self {
197        let l2_p_data_flag = (dword & WORD4_L2P_DATA_MASK) > 0;
198        let reserved = ((dword & WORD4_RESERVED_MASK) >> WORD4_RESERVED_SHIFT) as u32;
199        Self {
200            l2_p_data_flag,
201            reserved,
202        }
203    }
204}
205
206#[derive(Debug, Default, Clone)]
207pub struct Word5 {
208    /// 24-bit reserved
209    pub reserved: u32,
210}
211
212impl Word5 {
213    pub(crate) fn decode(dword: u32) -> Self {
214        let reserved = (dword & WORD5_RESERVED_MASK) >> WORD5_RESERVED_SHIFT;
215        Self { reserved }
216    }
217}
218
219#[derive(Debug, Default, Clone)]
220pub struct Word6 {
221    /// 24-bit reserved
222    pub reserved: u32,
223}
224
225impl Word6 {
226    pub(crate) fn decode(dword: u32) -> Self {
227        let reserved = (dword & WORD6_RESERVED_MASK) >> WORD6_RESERVED_SHIFT;
228        Self { reserved }
229    }
230}
231
232#[derive(Debug, Default, Clone)]
233pub struct Word7 {
234    /// 16-bit reserved
235    pub reserved: u16,
236
237    /// TGD
238    pub tgd: i8,
239}
240
241impl Word7 {
242    pub(crate) fn decode(dword: u32) -> Self {
243        let reserved = ((dword & WORD7_RESERVED_MASK) >> WORD7_RESERVED_SHIFT) as u16;
244        let tgd = ((dword & WORD7_TGD_MASK) >> WORD7_TGD_SHIFT) as i8;
245        Self { reserved, tgd }
246    }
247}
248
249#[derive(Debug, Default, Clone)]
250pub struct Word8 {
251    /// 8-bit IODC LSB to associate with Word # 3
252    pub iodc_lsb: u8,
253
254    /// 16 bit ToC
255    pub toc: u16,
256}
257
258impl Word8 {
259    pub(crate) fn decode(dword: u32) -> Self {
260        let iodc_lsb = ((dword & WORD8_IODC_MASK) >> WORD8_IODC_SHIFT) as u8;
261        let toc = ((dword & WORD8_TOC_MASK) >> WORD8_TOC_SHIFT) as u16;
262        Self { iodc_lsb, toc }
263    }
264}
265
266#[derive(Debug, Default, Clone)]
267pub struct Word9 {
268    /// 8 bit af2
269    pub af2: i8,
270
271    /// 16 bit af1
272    pub af1: i16,
273}
274
275impl Word9 {
276    pub(crate) fn decode(dword: u32) -> Self {
277        let af2 = ((dword & WORD9_AF2_MASK) >> WORD9_AF2_SHIFT) as i8;
278        let af1 = ((dword & WORD9_AF1_MASK) >> WORD9_AF1_SHIFT) as i16;
279        Self { af2, af1 }
280    }
281}
282
283#[derive(Debug, Default, Clone)]
284pub struct Word10 {
285    /// 22-bit af0
286    pub af0: i32,
287}
288
289impl Word10 {
290    pub(crate) fn decode(dword: u32) -> Self {
291        let af0 = ((dword & WORD10_AF0_MASK) >> WORD10_AF0_SHIFT) as u32;
292        let af0 = twos_complement(af0, 0x3fffff, 0x200000);
293        Self { af0 }
294    }
295}