use crate::binrw_util;
use alloc::vec::Vec;
use binrw::binrw;
use bitflags::bitflags;
#[binrw]
#[derive(Clone, Debug)]
pub struct GALNav {
#[br(map = binrw_util::map_u4)]
#[bw(map = binrw_util::unmap_u4)]
pub tow: Option<u32>,
#[br(map = binrw_util::map_u2)]
#[bw(map = binrw_util::unmap_u2)]
pub wnc: Option<u16>,
pub svid: u8,
pub source: u8,
pub sqrt_a: f64,
pub m_0: f64,
pub e: f64,
pub i_0: f64,
pub omega: f64,
pub omega_0: f64,
pub omegadot: f32,
pub idot: f32,
pub del_n: f32,
pub c_uc: f32,
pub c_us: f32,
pub c_rc: f32,
pub c_rs: f32,
pub c_ic: f32,
pub c_is: f32,
pub t_oe: u32,
pub t_oc: u32,
pub a_f2: f32,
pub a_f1: f32,
pub a_f0: f64,
pub wn_t_oe: u16,
pub wn_t_oc: u16,
pub iod_nav: u16,
#[br(map = GALNavHealthOssol::from_bits_retain)]
#[bw(map = |x: &GALNavHealthOssol| x.bits())]
pub health_ossol: GALNavHealthOssol,
pub health_prs: u8,
#[br(map = binrw_util::map_u1)]
#[bw(map = binrw_util::unmap_u1)]
pub sisa_l1e5a: Option<u8>,
#[br(map = binrw_util::map_u1)]
#[bw(map = binrw_util::unmap_u1)]
pub sisa_l1e5b: Option<u8>,
#[br(map = binrw_util::map_u1)]
#[bw(map = binrw_util::unmap_u1)]
pub sisa_l1ae6a: Option<u8>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub bgd_l1e5a: Option<f32>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub bgd_l1e5b: Option<f32>,
#[br(map = binrw_util::map_f4)]
#[bw(map = binrw_util::unmap_f4)]
pub bgd_l1ae6a: Option<f32>,
#[br(map = binrw_util::map_u1)]
#[bw(map = binrw_util::unmap_u1)]
pub cnav_enc: Option<u8>,
#[br(parse_with = binrw::helpers::until_eof)]
pub padding: Vec<u8>,
}
#[derive(Clone, Copy, Debug)]
pub struct GalSignalHealth {
pub working_without_guarantee: bool,
pub health_status: u8,
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct GALNavHealthOssol: u16 {
const L1B_VALID = 1 << 0;
const L1B_DVS = 1 << 1;
const L1B_HS_MASK = 0b11 << Self::L1B_HS_SHIFT;
const E5B_VALID = 1 << 4;
const E5B_DVS = 1 << 5;
const E5B_HS_MASK = 0b11 << Self::E5B_HS_SHIFT;
const E5A_VALID = 1 << 8;
const E5A_DVS = 1 << 9;
const E5A_HS_MASK = 0b11 << Self::E5A_HS_SHIFT;
}
}
impl GALNavHealthOssol {
const L1B_HS_SHIFT: u32 = 2;
const E5B_HS_SHIFT: u32 = 6;
const E5A_HS_SHIFT: u32 = 10;
fn health(
&self,
valid: Self,
dvs: Self,
hs_mask: Self,
hs_shift: u32,
) -> Option<GalSignalHealth> {
if !self.contains(valid) {
return None;
}
Some(GalSignalHealth {
working_without_guarantee: self.contains(dvs),
health_status: (self.intersection(hs_mask).bits() >> hs_shift) as u8,
})
}
pub fn l1b_health(&self) -> Option<GalSignalHealth> {
self.health(
Self::L1B_VALID,
Self::L1B_DVS,
Self::L1B_HS_MASK,
Self::L1B_HS_SHIFT,
)
}
pub fn e5b_health(&self) -> Option<GalSignalHealth> {
self.health(
Self::E5B_VALID,
Self::E5B_DVS,
Self::E5B_HS_MASK,
Self::E5B_HS_SHIFT,
)
}
pub fn e5a_health(&self) -> Option<GalSignalHealth> {
self.health(
Self::E5A_VALID,
Self::E5A_DVS,
Self::E5A_HS_MASK,
Self::E5A_HS_SHIFT,
)
}
}
impl GALNav {
pub const SOURCE_INAV: u8 = 2; pub const SOURCE_FNAV: u8 = 16;
pub const CNAV_E6B_UNENCRYPTED: u8 = 0x01;
pub const CNAV_E6C_UNENCRYPTED: u8 = 0x02;
}