1use crate::gps::{
2 frame1::{
3 Word10 as Ephemeris1Word10, Word3 as Ephemeris1Word3, Word4 as Ephemeris1Word4,
4 Word5 as Ephemeris1Word5, Word6 as Ephemeris1Word6, Word7 as Ephemeris1Word7,
5 Word8 as Ephemeris1Word8, Word9 as Ephemeris1Word9,
6 },
7 frame2::{
8 Word10 as Ephemeris2Word10, Word3 as Ephemeris2Word3, Word4 as Ephemeris2Word4,
9 Word5 as Ephemeris2Word5, Word6 as Ephemeris2Word6, Word7 as Ephemeris2Word7,
10 Word8 as Ephemeris2Word8, Word9 as Ephemeris2Word9,
11 },
12 frame3::{
13 Word10 as Ephemeris3Word10, Word3 as Ephemeris3Word3, Word4 as Ephemeris3Word4,
14 Word5 as Ephemeris3Word5, Word6 as Ephemeris3Word6, Word7 as Ephemeris3Word7,
15 Word8 as Ephemeris3Word8, Word9 as Ephemeris3Word9,
16 },
17 GpsDataByte, GpsQzssFrame, GpsQzssFrameId, GpsQzssHow, GpsQzssSubframe, GpsQzssTelemetry,
18};
19
20#[cfg(feature = "log")]
21use log::{error, trace};
22
23#[derive(Default, Debug, Copy, Clone, PartialEq)]
24enum State {
25 #[default]
27 Telemetry,
28
29 How,
31
32 DataWord,
34}
35
36pub struct GpsQzssDecoder {
37 ptr: usize,
39
40 pub(crate) dword: u32,
42
43 pub(crate) collected: usize,
45
46 state: State,
48
49 tlm: GpsQzssTelemetry,
51
52 how: GpsQzssHow,
54
55 subframe: GpsQzssSubframe,
57
58 storage: u32,
60
61 parity_check: bool,
63}
64
65impl Default for GpsQzssDecoder {
66 fn default() -> Self {
68 let state = State::default();
69
70 Self {
71 state,
72 ptr: 0,
73 dword: 0,
74 collected: 0,
75 storage: 0,
76 parity_check: true,
77 tlm: Default::default(),
78 how: Default::default(),
79 subframe: Default::default(),
80 }
81 }
82}
83
84impl GpsQzssDecoder {
85 pub fn parse(&mut self, byte: GpsDataByte) -> Option<GpsQzssFrame> {
88 match byte {
90 GpsDataByte::LsbPadded(byte) => {
91 self.collected += 6;
92 self.dword <<= 6;
93 self.dword |= (byte as u32) >> 2;
94 },
95 GpsDataByte::MsbPadded(byte) => {
96 self.collected += 6;
97 self.dword <<= 6;
98 self.dword |= (byte & 0x3f) as u32;
99 },
100 GpsDataByte::Byte(byte) => {
101 self.collected += 8;
102 self.dword <<= 8;
103 self.dword |= byte as u32;
104 },
105 }
106
107 #[cfg(feature = "log")]
108 trace!(
109 "GPS - data collection - ptr={} dword=0x{:08x}",
110 self.ptr,
111 self.dword
112 );
113
114 if self.collected < 30 {
115 return None;
117 }
118
119 let dword = self.dword;
121
122 let mut ret = Option::<GpsQzssFrame>::None;
123
124 #[cfg(feature = "log")]
126 trace!(
127 "GPS - state={:?} - decoding dword=0x{:08x}",
128 self.state,
129 dword
130 );
131
132 match self.state {
133 State::Telemetry => match GpsQzssTelemetry::decode(dword) {
134 Ok(tlm) => {
135 self.tlm = tlm;
136 self.state = State::How;
137 #[cfg(feature = "log")]
138 trace!("GPS - TLM {:?}", tlm);
139 },
140 #[cfg(feature = "log")]
141 Err(e) => {
142 error!("GPS - TLM decoding error: {:?}", e);
143 },
144 #[cfg(not(feature = "log"))]
145 Err(_) => {},
146 },
147
148 State::How => match GpsQzssHow::decode(dword) {
149 Ok(how) => {
150 self.how = how;
151 self.state = State::DataWord;
152 self.ptr = 3;
153
154 match how.frame_id {
155 GpsQzssFrameId::Ephemeris1 => {
156 self.subframe = GpsQzssSubframe::Ephemeris1(Default::default());
157 },
158 GpsQzssFrameId::Ephemeris2 => {
159 self.subframe = GpsQzssSubframe::Ephemeris2(Default::default());
160 },
161 GpsQzssFrameId::Ephemeris3 => {
162 self.subframe = GpsQzssSubframe::Ephemeris3(Default::default());
163 },
164 }
165 #[cfg(feature = "log")]
166 trace!("GPS - HOW {:?}", how);
167 },
168 #[cfg(feature = "log")]
169 Err(e) => {
170 error!("GPS - HOW decoding error: {:?}", e);
171 self.ptr = 0;
172 self.dword = 0;
173 self.state = State::default();
174 },
175 #[cfg(not(feature = "log"))]
176 Err(_) => {},
177 },
178
179 State::DataWord => {
180 match self.how.frame_id {
181 GpsQzssFrameId::Ephemeris1 => match self.ptr {
182 3 => {
183 let word = Ephemeris1Word3::decode(self.dword);
184
185 let frame = self.subframe.as_mut_eph1().expect("internal error");
186
187 frame.week = word.week;
188 frame.ura = word.ura;
189 frame.ca_or_p_l2 = word.ca_or_p_l2;
190 frame.health = word.health;
191 frame.iodc |= (word.iodc_msb as u16) << 8;
192 #[cfg(feature = "log")]
193 trace!("GPS - EPH #1 Word#3 {:?}", word);
194 },
195 4 => {
196 let word = Ephemeris1Word4::decode(self.dword);
197 let frame = self.subframe.as_mut_eph1().expect("internal error");
198 frame.l2_p_data_flag = word.l2_p_data_flag;
199 frame.reserved_word4 = word.reserved;
200 #[cfg(feature = "log")]
201 trace!("GPS - EPH #1 Word#4 {:?}", word);
202 },
203 5 => {
204 let word = Ephemeris1Word5::decode(self.dword);
205 let frame = self.subframe.as_mut_eph1().expect("internal error");
206 frame.reserved_word5 = word.reserved;
207 #[cfg(feature = "log")]
208 trace!("GPS - EPH #1 Word#5 {:?}", word);
209 },
210 6 => {
211 let word = Ephemeris1Word6::decode(self.dword);
212 let frame = self.subframe.as_mut_eph1().expect("internal error");
213 frame.reserved_word6 = word.reserved;
214 #[cfg(feature = "log")]
215 trace!("GPS - EPH #1 Word#6 {:?}", word);
216 },
217 7 => {
218 let word = Ephemeris1Word7::decode(self.dword);
219 let frame = self.subframe.as_mut_eph1().expect("internal error");
220 frame.tgd = (word.tgd as f64) / 2_f64.powi(31);
221 frame.reserved_word7 = word.reserved;
222 #[cfg(feature = "log")]
223 trace!("GPS - EPH #1 Word#7 {:?}", word);
224 },
225 8 => {
226 let word = Ephemeris1Word8::decode(self.dword);
227 let frame = self.subframe.as_mut_eph1().expect("internal error");
228 frame.toc = (word.toc as u32) * 16;
229 frame.iodc |= word.iodc_lsb as u16;
230 #[cfg(feature = "log")]
231 trace!("GPS - EPH #1 Word#8 {:?}", word);
232 },
233 9 => {
234 let word = Ephemeris1Word9::decode(self.dword);
235 let frame = self.subframe.as_mut_eph1().expect("internal error");
236 frame.af2 = (word.af2 as f64) / 2.0_f64.powi(55);
237 frame.af1 = (word.af1 as f64) / 2.0_f64.powi(43);
238 #[cfg(feature = "log")]
239 trace!("GPS - EPH #1 Word#9 {:?}", word);
240 },
241 10 => {
242 let word = Ephemeris1Word10::decode(self.dword);
243 let frame = self.subframe.as_mut_eph1().expect("internal error");
244 frame.af0 = (word.af0 as f64) / 2.0_f64.powi(31);
245 #[cfg(feature = "log")]
246 trace!("GPS - EPH #1 Word#10 {:?}", word);
247 },
248 _ => {
249 unreachable!("invalid state");
250 },
251 },
252 GpsQzssFrameId::Ephemeris2 => match self.ptr {
253 3 => {
254 let word = Ephemeris2Word3::decode(self.dword);
255 let frame = self.subframe.as_mut_eph2().expect("internal error");
256 frame.crs = (word.crs as f64) / 2.0_f64.powi(5);
257 frame.iode = word.iode;
258 #[cfg(feature = "log")]
259 trace!("GPS - EPH #2 Word#3 {:?}", word);
260 },
261 4 => {
262 let word = Ephemeris2Word4::decode(self.dword);
263 let frame = self.subframe.as_mut_eph2().expect("internal error");
264 frame.dn = (word.dn as f64) / 2.0_f64.powi(43);
265 self.storage = word.m0_msb as u32;
266 #[cfg(feature = "log")]
267 trace!("GPS - EPH #2 Word#4 {:?}", word);
268 },
269 5 => {
270 let word = Ephemeris2Word5::decode(self.dword);
271 let frame = self.subframe.as_mut_eph2().expect("internal error");
272
273 let mut m0 = self.storage;
274 m0 <<= 24;
275 m0 |= word.m0_lsb as u32;
276
277 frame.m0 = ((m0 as i32) as f64) / 2.0_f64.powi(31);
278
279 #[cfg(feature = "log")]
280 trace!("GPS - EPH #2 Word#5 {:?}", word);
281 },
282 6 => {
283 let word = Ephemeris2Word6::decode(self.dword);
284 let frame = self.subframe.as_mut_eph2().expect("internal error");
285 frame.cuc = (word.cuc as f64) / 2.0_f64.powi(29);
286 self.storage = word.e_msb as u32;
287 #[cfg(feature = "log")]
288 trace!("GPS - EPH #2 Word#6 {:?}", word);
289 },
290 7 => {
291 let word = Ephemeris2Word7::decode(self.dword);
292 let frame = self.subframe.as_mut_eph2().expect("internal error");
293
294 let mut e = self.storage;
295 e <<= 24;
296 e |= word.e_lsb;
297
298 frame.e = (e as f64) / 2.0_f64.powi(33);
299 #[cfg(feature = "log")]
300 trace!("GPS - EPH #2 Word#7 {:?}", word);
301 },
302 8 => {
303 let word = Ephemeris2Word8::decode(self.dword);
304 let frame = self.subframe.as_mut_eph2().expect("internal error");
305
306 frame.cus = (word.cus as f64) / 2.0_f64.powi(29);
307 self.storage = word.sqrt_a_msb as u32;
308 #[cfg(feature = "log")]
309 trace!("GPS - EPH #2 Word#8 {:?}", word);
310 },
311 9 => {
312 let word = Ephemeris2Word9::decode(self.dword);
313 let frame = self.subframe.as_mut_eph2().expect("internal error");
314
315 let mut sqrt_a = self.storage;
316 sqrt_a <<= 24;
317 sqrt_a |= word.sqrt_a_lsb;
318
319 frame.sqrt_a = (sqrt_a as f64) / 2.0_f64.powi(19);
320
321 #[cfg(feature = "log")]
322 trace!("GPS - EPH #2 Word#9 {:?}", word);
323 },
324 10 => {
325 let word = Ephemeris2Word10::decode(self.dword);
326 let frame = self.subframe.as_mut_eph2().expect("internal error");
327
328 frame.aodo = word.aodo;
329 frame.fit_int_flag = word.fitint;
330 frame.toe = (word.toe as u32) * 16;
331
332 #[cfg(feature = "log")]
333 trace!("GPS - EPH #2 Word#10 {:?}", word);
334 },
335 _ => {
336 unreachable!("invalid state");
337 },
338 },
339 GpsQzssFrameId::Ephemeris3 => match self.ptr {
340 3 => {
341 let word = Ephemeris3Word3::decode(self.dword);
342 let frame = self.subframe.as_mut_eph3().expect("internal error");
343 frame.cic = (word.cic as f64) / 2.0_f64.powi(29);
344 self.storage = word.omega0_msb as u32;
345
346 #[cfg(feature = "log")]
347 trace!("GPS - EPH #3 Word#3 {:?}", word);
348 },
349 4 => {
350 let word = Ephemeris3Word4::decode(self.dword);
351 let frame = self.subframe.as_mut_eph3().expect("internal error");
352
353 let mut omega0 = self.storage;
354 omega0 <<= 24;
355 omega0 |= word.omega0_lsb;
356
357 frame.omega0 = ((omega0 as i32) as f64) / 2.0_f64.powi(31);
358
359 #[cfg(feature = "log")]
360 trace!("GPS - EPH #3 Word#4 {:?}", word);
361 },
362 5 => {
363 let word = Ephemeris3Word5::decode(self.dword);
364 let frame = self.subframe.as_mut_eph3().expect("internal error");
365
366 frame.cis = (word.cis as f64) / 2.0_f64.powi(29);
367
368 self.storage = word.i0_msb as u32;
369
370 #[cfg(feature = "log")]
371 trace!("GPS - EPH #2 Word#5 {:?}", word);
372 },
373 6 => {
374 let word = Ephemeris3Word6::decode(self.dword);
375 let frame = self.subframe.as_mut_eph3().expect("internal error");
376
377 let mut i0 = self.storage;
378 i0 <<= 24;
379 i0 |= word.i0_lsb;
380
381 frame.i0 = (i0 as f64) / 2.0_f64.powi(31);
382
383 #[cfg(feature = "log")]
384 trace!("GPS - EPH #3 Word#6 {:?}", word);
385 },
386 7 => {
387 let word = Ephemeris3Word7::decode(self.dword);
388 let frame = self.subframe.as_mut_eph3().expect("internal error");
389
390 frame.crc = (word.crc as f64) / 2.0_f64.powi(5);
391 self.storage = word.omega_msb as u32;
392
393 #[cfg(feature = "log")]
394 trace!("GPS - EPH #3 Word#7 {:?}", word);
395 },
396 8 => {
397 let word = Ephemeris3Word8::decode(self.dword);
398 let frame = self.subframe.as_mut_eph3().expect("internal error");
399
400 let mut omega = self.storage;
401 omega <<= 24;
402 omega |= word.omega_lsb;
403
404 frame.omega = ((omega as i32) as f64) / 2.0_f64.powi(31);
405
406 #[cfg(feature = "log")]
407 trace!("GPS - EPH #3 Word#8 {:?}", word);
408 },
409 9 => {
410 let word = Ephemeris3Word9::decode(self.dword);
411 let frame = self.subframe.as_mut_eph3().expect("internal error");
412
413 frame.omega_dot = (word.omega_dot as f64) / 2.0_f64.powi(43);
414
415 #[cfg(feature = "log")]
416 trace!("GPS - EPH #3 Word#9 {:?}", word);
417 },
418 10 => {
419 let word = Ephemeris3Word10::decode(self.dword);
420 let frame = self.subframe.as_mut_eph3().expect("internal error");
421
422 frame.idot = (word.idot as f64) / 2.0_f64.powi(43);
423 frame.iode = word.iode;
424
425 #[cfg(feature = "log")]
426 trace!("GPS - EPH #3 Word#10 {:?}", word);
427 },
428 _ => {
429 unreachable!("invalid state");
430 },
431 },
432 }
433
434 self.ptr += 1;
435 },
436 }
437
438 self.collected = 0;
440 self.dword = 0;
441
442 if self.ptr == 11 {
443 ret = Some(GpsQzssFrame {
444 how: self.how,
445 telemetry: self.tlm,
446 subframe: self.subframe,
447 });
448
449 self.ptr = 0;
450 self.state = State::Telemetry;
451 }
452
453 ret
454 }
455
456 pub fn without_parity_verification(&self) -> Self {
458 Self {
459 ptr: self.ptr,
460 collected: 0,
461 dword: 0,
462 storage: 0,
463 state: self.state,
464 parity_check: false,
465 tlm: self.tlm.clone(),
466 how: self.how.clone(),
467 subframe: self.subframe.clone(),
468 }
469 }
470}
471
472#[cfg(test)]
473mod test {
474 use crate::{
475 gps::{GpsDataByte, GpsQzssDecoder, GpsQzssSubframe},
476 GpsQzssFrameId,
477 };
478
479 use crate::tests::from_ublox_be_bytes;
480
481 #[cfg(all(feature = "std", feature = "log"))]
482 use crate::tests::init_logger;
483
484 #[test]
485 fn test_tlm_decoding() {
486 #[cfg(all(feature = "std", feature = "log"))]
487 init_logger();
488
489 let bytes = [
490 GpsDataByte::Byte(0x8B),
491 GpsDataByte::Byte(0x00),
492 GpsDataByte::Byte(0x0D),
493 GpsDataByte::lsb_padded(0x00), ];
495
496 let mut decoder = GpsQzssDecoder::default();
497
498 for byte in bytes {
499 let _ = decoder.parse(byte);
500 }
501
502 assert_eq!(decoder.tlm.message, 3);
503 assert_eq!(decoder.tlm.integrity, false);
504 assert_eq!(decoder.tlm.reserved_bits, true);
505 }
506
507 #[test]
508 fn test_ublox_tlm_decoding() {
509 #[cfg(all(feature = "std", feature = "log"))]
510 init_logger();
511
512 let bytes = [
513 GpsDataByte::msb_padded(0x22),
514 GpsDataByte::Byte(0xC1),
515 GpsDataByte::Byte(0x3E),
516 GpsDataByte::Byte(0x1B), ];
518
519 let mut decoder = GpsQzssDecoder::default();
520
521 for byte in bytes {
522 let _ = decoder.parse(byte);
523 }
524
525 assert_eq!(decoder.tlm.message, 0x13E);
526 assert_eq!(decoder.tlm.integrity, false);
527 assert_eq!(decoder.tlm.reserved_bits, false);
528
529 let bytes = [0x22, 0xC1, 0x3E, 0x1B];
530 let bytes = from_ublox_be_bytes(&bytes);
531
532 let mut decoder = GpsQzssDecoder::default();
533
534 for byte in bytes {
535 let _ = decoder.parse(byte);
536 }
537
538 assert_eq!(decoder.tlm.message, 0x13E);
539 assert_eq!(decoder.tlm.integrity, false);
540 assert_eq!(decoder.tlm.reserved_bits, false);
541 }
542
543 #[test]
544 fn test_tlmhow_decoding() {
545 #[cfg(all(feature = "std", feature = "log"))]
546 init_logger();
547
548 let bytes = [
549 GpsDataByte::msb_padded(0x22),
550 GpsDataByte::Byte(0xC1),
551 GpsDataByte::Byte(0x3E),
552 GpsDataByte::Byte(0x1B), GpsDataByte::MsbPadded(0x15),
554 GpsDataByte::Byte(0x27),
555 GpsDataByte::Byte(0xC9),
556 GpsDataByte::Byte(0x73), ];
558
559 let mut decoder = GpsQzssDecoder::default();
560
561 for byte in bytes {
562 let _ = decoder.parse(byte);
563 }
564
565 assert_eq!(decoder.tlm.message, 0x13E);
566 assert_eq!(decoder.tlm.integrity, false);
567 assert_eq!(decoder.tlm.reserved_bits, false);
568
569 assert_eq!(decoder.how.alert, false);
570 assert_eq!(decoder.how.anti_spoofing, true);
571 assert_eq!(decoder.how.frame_id, GpsQzssFrameId::Ephemeris1);
572 }
573
574 #[test]
575 fn test_ublox_tlmhow_decoding() {
576 #[cfg(all(feature = "std", feature = "log"))]
577 init_logger();
578
579 let bytes = [
580 GpsDataByte::MsbPadded(0x22),
581 GpsDataByte::Byte(0xC1),
582 GpsDataByte::Byte(0x3E),
583 GpsDataByte::Byte(0x1B), GpsDataByte::MsbPadded(0x15),
585 GpsDataByte::Byte(0x27),
586 GpsDataByte::Byte(0xC9),
587 GpsDataByte::Byte(0x73), ];
589
590 let mut decoder = GpsQzssDecoder::default();
591
592 for byte in bytes {
593 let _ = decoder.parse(byte);
594 }
595
596 assert_eq!(decoder.tlm.message, 0x13E);
597 assert_eq!(decoder.tlm.integrity, false);
598 assert_eq!(decoder.tlm.reserved_bits, false);
599
600 assert_eq!(decoder.how.alert, false);
601 assert_eq!(decoder.how.anti_spoofing, true);
602 assert_eq!(decoder.how.frame_id, GpsQzssFrameId::Ephemeris1);
603
604 let bytes = from_ublox_be_bytes(&[0x22, 0xC1, 0x3E, 0x1B, 0x15, 0x27, 0xC9, 0x73]);
605
606 let mut decoder = GpsQzssDecoder::default();
607
608 for byte in bytes {
609 let _ = decoder.parse(byte);
610 }
611
612 assert_eq!(decoder.tlm.message, 0x13E);
613 assert_eq!(decoder.tlm.integrity, false);
614 assert_eq!(decoder.tlm.reserved_bits, false);
615
616 assert_eq!(decoder.how.alert, false);
617 assert_eq!(decoder.how.anti_spoofing, true);
618 assert_eq!(decoder.how.frame_id, GpsQzssFrameId::Ephemeris1);
619 }
620
621 #[test]
622 fn test_incomplete_frame() {
623 #[cfg(all(feature = "std", feature = "log"))]
624 init_logger();
625
626 let mut found = false;
627
628 let bytes = [
629 GpsDataByte::Byte(0x8B),
630 GpsDataByte::Byte(0x00),
631 GpsDataByte::Byte(0x0D),
632 GpsDataByte::lsb_padded(0x00), ];
634
635 let mut decoder = GpsQzssDecoder::default();
636
637 for byte in bytes {
638 if let Some(_) = decoder.parse(byte) {
639 found = true;
640 }
641 }
642
643 assert!(!found, "Invalid GPS frame decoded!");
644
645 let bytes = [
646 GpsDataByte::Byte(0x8B),
647 GpsDataByte::Byte(0x00),
648 GpsDataByte::Byte(0x0D),
649 GpsDataByte::lsb_padded(0x00), GpsDataByte::Byte(0x8B),
651 GpsDataByte::Byte(0x00),
652 GpsDataByte::Byte(0x0D),
653 GpsDataByte::lsb_padded(0x00), GpsDataByte::Byte(0x8B),
655 GpsDataByte::Byte(0x00),
656 GpsDataByte::Byte(0x0D),
657 GpsDataByte::lsb_padded(0x00), GpsDataByte::Byte(0x8B),
659 GpsDataByte::Byte(0x00),
660 GpsDataByte::Byte(0x0D),
661 GpsDataByte::lsb_padded(0x00), GpsDataByte::Byte(0x8B),
663 GpsDataByte::Byte(0x00),
664 GpsDataByte::Byte(0x0D),
665 GpsDataByte::lsb_padded(0x00), GpsDataByte::Byte(0x8B),
667 GpsDataByte::Byte(0x00),
668 GpsDataByte::Byte(0x0D),
669 GpsDataByte::lsb_padded(0x00), GpsDataByte::Byte(0x8B),
671 GpsDataByte::Byte(0x00),
672 GpsDataByte::Byte(0x0D),
673 GpsDataByte::lsb_padded(0x00), GpsDataByte::Byte(0x8B),
675 GpsDataByte::Byte(0x00),
676 GpsDataByte::Byte(0x0D),
677 GpsDataByte::lsb_padded(0x00), GpsDataByte::Byte(0x8B),
679 GpsDataByte::Byte(0x00),
680 GpsDataByte::Byte(0x0D),
681 ];
682
683 let mut decoder = GpsQzssDecoder::default();
684
685 for byte in bytes {
686 if let Some(_) = decoder.parse(byte) {
687 found = true;
688 }
689 }
690
691 assert!(!found, "Invalid GPS frame decoded");
692 }
693
694 #[test]
695 fn test_eph1_frame() {
696 #[cfg(all(feature = "std", feature = "log"))]
697 init_logger();
698
699 let mut found = false;
700
701 let bytes = from_ublox_be_bytes(&[
702 0x22, 0xC1, 0x3E, 0x1B, 0x15, 0x27, 0xC9, 0x73, 0x13, 0xE4, 0x00, 0x04, 0x10, 0x4F, 0x5D, 0x31, 0x97, 0x44, 0xE6, 0xD7, 0x07, 0x75, 0x57, 0x83, 0x33, 0x0C, 0x80, 0xB5, 0x92, 0x50, 0x42, 0xA1, 0x80, 0x00, 0x16, 0x84, 0x31, 0x2C, 0x30, 0x33,
713 ]);
714
715 let mut decoder = GpsQzssDecoder::default().without_parity_verification();
716
717 for byte in bytes {
718 if let Some(frame) = decoder.parse(byte) {
719 assert_eq!(decoder.tlm.message, 0x13E);
720 assert_eq!(decoder.tlm.integrity, false);
721 assert_eq!(decoder.tlm.reserved_bits, false);
722
723 assert_eq!(decoder.how.alert, false);
724 assert_eq!(decoder.how.anti_spoofing, true);
725 assert_eq!(decoder.how.frame_id, GpsQzssFrameId::Ephemeris1);
726
727 match frame.subframe {
728 GpsQzssSubframe::Ephemeris1(frame1) => {
729 assert_eq!(frame1.af2, 0.0);
730 assert!((frame1.af1 - 1.023181539495e-011).abs() < 1e-14);
731 assert!((frame1.af0 - -4.524961113930e-004).abs() < 1.0e-11);
732 assert_eq!(frame1.week, 318);
733 assert_eq!(frame1.toc, 266_400);
734 assert_eq!(frame1.health, 0);
735 found = true;
736 },
737 _ => panic!("incorrect subframe decoded!"),
738 }
739 }
740 }
741
742 assert!(found, "GPS decoding failed!");
743 }
744
745 #[test]
746 fn test_eph2_frame() {
747 #[cfg(all(feature = "std", feature = "log"))]
748 init_logger();
749
750 let mut found = false;
751
752 let bytes = from_ublox_be_bytes(&[
753 0x22, 0xC1, 0x3E, 0x1B, 0x15, 0x27, 0xEA, 0x1B, 0x12, 0x7F, 0xF1, 0x65, 0x8C, 0x68, 0x1F, 0x7C, 0x02, 0x49, 0x34, 0x15, 0xBF, 0xF8, 0x81, 0x1E, 0x99, 0x1B, 0x81, 0x14, 0x04, 0x3E, 0x68, 0x6E, 0x83, 0x34, 0x72, 0x21, 0x90, 0x42, 0x9F, 0x7B,
764 ]);
765
766 let mut decoder = GpsQzssDecoder::default().without_parity_verification();
767
768 for byte in bytes {
769 if let Some(frame) = decoder.parse(byte) {
770 assert_eq!(decoder.tlm.message, 0x13E);
771 assert_eq!(decoder.tlm.integrity, false);
772 assert_eq!(decoder.tlm.reserved_bits, false);
773
774 assert_eq!(decoder.how.alert, false);
775 assert_eq!(decoder.how.anti_spoofing, true);
776 assert_eq!(decoder.how.frame_id, GpsQzssFrameId::Ephemeris2);
777
778 match frame.subframe {
779 GpsQzssSubframe::Ephemeris2(frame2) => {
780 assert_eq!(frame2.toe, 266_400);
781 assert_eq!(frame2.crs, -1.843750000000e+000);
782 assert!((frame2.sqrt_a - 5.153602432251e+003).abs() < 1e-9);
783 assert!((frame2.m0 - 9.768415465951e-001).abs() < 1e-9);
784 assert!((frame2.cuc - -5.587935447693e-008).abs() < 1e-9);
785 assert!((frame2.e - 8.578718174249e-003).abs() < 1e-9);
786 assert!((frame2.cus - 8.093193173409e-006).abs() < 1e-9);
787 assert!((frame2.cuc - -5.587935447693e-008).abs() < 1e-6);
788 assert!((frame2.dn - 1.444277586415e-009).abs() < 1e-9);
789 assert_eq!(frame2.fit_int_flag, false);
790 found = true;
791 },
792 _ => panic!("incorrect subframe decoded!"),
793 }
794 }
795 }
796
797 assert!(found, "GPS decoding failed!");
798 }
799
800 #[test]
801 fn test_eph3_frame() {
802 #[cfg(all(feature = "std", feature = "log"))]
803 init_logger();
804
805 let mut found = false;
806
807 let bytes = from_ublox_be_bytes(&[
808 0x22, 0xC1, 0x3E, 0x1B, 0x15, 0x28, 0x0B, 0xDB, 0x00, 0x0A, 0xEA, 0x34, 0x03, 0x3C,
809 0xFF, 0xEE, 0xBF, 0xE5, 0xC9, 0xEB, 0x13, 0x6F, 0xB6, 0x4E, 0x86, 0xF4, 0xAB, 0x2C,
810 0x06, 0x71, 0xEB, 0x44, 0x3F, 0xEA, 0xF6, 0x02, 0x92, 0x45, 0x52, 0x13,
811 ]);
812
813 let mut decoder = GpsQzssDecoder::default().without_parity_verification();
814
815 for byte in bytes {
816 if let Some(frame) = decoder.parse(byte) {
817 assert_eq!(decoder.tlm.message, 0x13E);
818 assert_eq!(decoder.tlm.integrity, false);
819 assert_eq!(decoder.tlm.reserved_bits, false);
820
821 assert_eq!(decoder.how.alert, false);
822 assert_eq!(decoder.how.anti_spoofing, true);
823 assert_eq!(decoder.how.frame_id, GpsQzssFrameId::Ephemeris3);
824
825 match frame.subframe {
826 GpsQzssSubframe::Ephemeris3(frame3) => {
827 assert!((frame3.cic - 8.009374141693e-008).abs() < 1e-9);
828 assert!((frame3.cis - -1.955777406693e-007).abs() < 1E-9);
829 assert!((frame3.crc - 2.225625000000e+002).abs() < 1E-9);
830 assert!((frame3.i0 - 3.070601043291e-001).abs() < 1e-9);
831 assert!((frame3.idot - 1.548414729768e-010).abs() < 1E-9);
832 assert!((frame3.omega0 - -6.871047024615e-001).abs() < 1e-9);
833 assert!((frame3.omega_dot - -2.449269231874e-009).abs() < 1e-9);
834 assert!((frame3.omega - -6.554632573389e-001).abs() < 1e-9);
835 found = true;
836 },
837 _ => panic!("incorrect subframe decoded!"),
838 }
839 }
840 }
841
842 assert!(found, "GPS decoding failed!");
843 }
844}