use crate::error::{Error, Result};
use crate::id::{GnssSatelliteId, GnssSystem};
use super::bits::{BitReader, BitWriter};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct GpsEphemeris {
pub satellite_id: u8,
pub week_number: u16,
pub sv_accuracy: u8,
pub code_on_l2: u8,
pub idot: i32,
pub iode: u8,
pub t_oc: u16,
pub a_f2: i16,
pub a_f1: i32,
pub a_f0: i32,
pub iodc: u16,
pub c_rs: i32,
pub delta_n: i32,
pub m0: i64,
pub c_uc: i32,
pub eccentricity: u64,
pub c_us: i32,
pub sqrt_a: u64,
pub t_oe: u16,
pub c_ic: i32,
pub omega0: i64,
pub c_is: i32,
pub i0: i64,
pub c_rc: i32,
pub omega: i64,
pub omega_dot: i32,
pub t_gd: i16,
pub sv_health: u8,
pub l2_p_data_flag: bool,
pub fit_interval: bool,
}
impl GpsEphemeris {
pub fn satellite(&self) -> Result<GnssSatelliteId> {
GnssSatelliteId::new(GnssSystem::Gps, self.satellite_id)
.map_err(|e| Error::Parse(format!("invalid GPS PRN in 1019: {e}")))
}
pub fn decode(body: &[u8]) -> Result<Self> {
let mut r = BitReader::new(body);
let message_number = r.u(12)? as u16;
if message_number != 1019 {
return Err(Error::Parse(format!(
"message {message_number} is not GPS ephemeris 1019"
)));
}
Ok(Self {
satellite_id: r.u(6)? as u8,
week_number: r.u(10)? as u16,
sv_accuracy: r.u(4)? as u8,
code_on_l2: r.u(2)? as u8,
idot: r.i(14)? as i32,
iode: r.u(8)? as u8,
t_oc: r.u(16)? as u16,
a_f2: r.i(8)? as i16,
a_f1: r.i(16)? as i32,
a_f0: r.i(22)? as i32,
iodc: r.u(10)? as u16,
c_rs: r.i(16)? as i32,
delta_n: r.i(16)? as i32,
m0: r.i(32)?,
c_uc: r.i(16)? as i32,
eccentricity: r.u(32)?,
c_us: r.i(16)? as i32,
sqrt_a: r.u(32)?,
t_oe: r.u(16)? as u16,
c_ic: r.i(16)? as i32,
omega0: r.i(32)?,
c_is: r.i(16)? as i32,
i0: r.i(32)?,
c_rc: r.i(16)? as i32,
omega: r.i(32)?,
omega_dot: r.i(24)? as i32,
t_gd: r.i(8)? as i16,
sv_health: r.u(6)? as u8,
l2_p_data_flag: r.flag()?,
fit_interval: r.flag()?,
})
}
pub fn encode(&self) -> Vec<u8> {
let mut w = BitWriter::new();
w.push_u(1019, 12);
w.push_u(u64::from(self.satellite_id), 6);
w.push_u(u64::from(self.week_number), 10);
w.push_u(u64::from(self.sv_accuracy), 4);
w.push_u(u64::from(self.code_on_l2), 2);
w.push_i(i64::from(self.idot), 14);
w.push_u(u64::from(self.iode), 8);
w.push_u(u64::from(self.t_oc), 16);
w.push_i(i64::from(self.a_f2), 8);
w.push_i(i64::from(self.a_f1), 16);
w.push_i(i64::from(self.a_f0), 22);
w.push_u(u64::from(self.iodc), 10);
w.push_i(i64::from(self.c_rs), 16);
w.push_i(i64::from(self.delta_n), 16);
w.push_i(self.m0, 32);
w.push_i(i64::from(self.c_uc), 16);
w.push_u(self.eccentricity, 32);
w.push_i(i64::from(self.c_us), 16);
w.push_u(self.sqrt_a, 32);
w.push_u(u64::from(self.t_oe), 16);
w.push_i(i64::from(self.c_ic), 16);
w.push_i(self.omega0, 32);
w.push_i(i64::from(self.c_is), 16);
w.push_i(self.i0, 32);
w.push_i(i64::from(self.c_rc), 16);
w.push_i(self.omega, 32);
w.push_i(i64::from(self.omega_dot), 24);
w.push_i(i64::from(self.t_gd), 8);
w.push_u(u64::from(self.sv_health), 6);
w.push_flag(self.l2_p_data_flag);
w.push_flag(self.fit_interval);
w.into_bytes()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct GlonassEphemeris {
pub satellite_id: u8,
pub frequency_channel: u8,
pub almanac_health: bool,
pub almanac_health_availability: bool,
pub p1: u8,
pub t_k: u16,
pub b_n_msb: bool,
pub p2: bool,
pub t_b: u8,
pub xn_dot: i32,
pub xn: i32,
pub xn_dot_dot: i8,
pub yn_dot: i32,
pub yn: i32,
pub yn_dot_dot: i8,
pub zn_dot: i32,
pub zn: i32,
pub zn_dot_dot: i8,
pub p3: bool,
pub gamma_n: i16,
pub m_p: u8,
pub m_l_n_third: bool,
pub tau_n: i32,
pub delta_tau_n: i8,
pub e_n: u8,
pub m_p4: bool,
pub m_f_t: u8,
pub m_n_t: u16,
pub m_m: u8,
pub additional_data_available: bool,
pub n_a: u16,
pub tau_c: i64,
pub m_n4: u8,
pub m_tau_gps: i32,
pub m_l_n_fifth: bool,
pub reserved: u8,
}
impl GlonassEphemeris {
pub fn satellite(&self) -> Result<GnssSatelliteId> {
GnssSatelliteId::new(GnssSystem::Glonass, self.satellite_id)
.map_err(|e| Error::Parse(format!("invalid GLONASS slot in 1020: {e}")))
}
pub fn decode(body: &[u8]) -> Result<Self> {
let mut r = BitReader::new(body);
let message_number = r.u(12)? as u16;
if message_number != 1020 {
return Err(Error::Parse(format!(
"message {message_number} is not GLONASS ephemeris 1020"
)));
}
Ok(Self {
satellite_id: r.u(6)? as u8,
frequency_channel: r.u(5)? as u8,
almanac_health: r.flag()?,
almanac_health_availability: r.flag()?,
p1: r.u(2)? as u8,
t_k: r.u(12)? as u16,
b_n_msb: r.flag()?,
p2: r.flag()?,
t_b: r.u(7)? as u8,
xn_dot: r.ism(24)? as i32,
xn: r.ism(27)? as i32,
xn_dot_dot: r.ism(5)? as i8,
yn_dot: r.ism(24)? as i32,
yn: r.ism(27)? as i32,
yn_dot_dot: r.ism(5)? as i8,
zn_dot: r.ism(24)? as i32,
zn: r.ism(27)? as i32,
zn_dot_dot: r.ism(5)? as i8,
p3: r.flag()?,
gamma_n: r.ism(11)? as i16,
m_p: r.u(2)? as u8,
m_l_n_third: r.flag()?,
tau_n: r.ism(22)? as i32,
delta_tau_n: r.ism(5)? as i8,
e_n: r.u(5)? as u8,
m_p4: r.flag()?,
m_f_t: r.u(4)? as u8,
m_n_t: r.u(11)? as u16,
m_m: r.u(2)? as u8,
additional_data_available: r.flag()?,
n_a: r.u(11)? as u16,
tau_c: r.ism(32)?,
m_n4: r.u(5)? as u8,
m_tau_gps: r.ism(22)? as i32,
m_l_n_fifth: r.flag()?,
reserved: r.u(7)? as u8,
})
}
pub fn encode(&self) -> Vec<u8> {
let mut w = BitWriter::new();
w.push_u(1020, 12);
w.push_u(u64::from(self.satellite_id), 6);
w.push_u(u64::from(self.frequency_channel), 5);
w.push_flag(self.almanac_health);
w.push_flag(self.almanac_health_availability);
w.push_u(u64::from(self.p1), 2);
w.push_u(u64::from(self.t_k), 12);
w.push_flag(self.b_n_msb);
w.push_flag(self.p2);
w.push_u(u64::from(self.t_b), 7);
w.push_ism(i64::from(self.xn_dot), 24);
w.push_ism(i64::from(self.xn), 27);
w.push_ism(i64::from(self.xn_dot_dot), 5);
w.push_ism(i64::from(self.yn_dot), 24);
w.push_ism(i64::from(self.yn), 27);
w.push_ism(i64::from(self.yn_dot_dot), 5);
w.push_ism(i64::from(self.zn_dot), 24);
w.push_ism(i64::from(self.zn), 27);
w.push_ism(i64::from(self.zn_dot_dot), 5);
w.push_flag(self.p3);
w.push_ism(i64::from(self.gamma_n), 11);
w.push_u(u64::from(self.m_p), 2);
w.push_flag(self.m_l_n_third);
w.push_ism(i64::from(self.tau_n), 22);
w.push_ism(i64::from(self.delta_tau_n), 5);
w.push_u(u64::from(self.e_n), 5);
w.push_flag(self.m_p4);
w.push_u(u64::from(self.m_f_t), 4);
w.push_u(u64::from(self.m_n_t), 11);
w.push_u(u64::from(self.m_m), 2);
w.push_flag(self.additional_data_available);
w.push_u(u64::from(self.n_a), 11);
w.push_ism(self.tau_c, 32);
w.push_u(u64::from(self.m_n4), 5);
w.push_ism(i64::from(self.m_tau_gps), 22);
w.push_flag(self.m_l_n_fifth);
w.push_u(u64::from(self.reserved), 7);
w.into_bytes()
}
}