use crate::{ephemeris::SatelliteState, signal::GnssSignal};
use std::time::Duration;
const NAV_MEAS_FLAG_CODE_VALID: u16 = 1 << 0;
const NAV_MEAS_FLAG_MEAS_DOPPLER_VALID: u16 = 1 << 2;
const NAV_MEAS_FLAG_CN0_VALID: u16 = 1 << 5;
pub const NAV_MEAS_FLAG_RAIM_EXCLUSION: u16 = 1 << 6;
#[derive(Debug, Clone, PartialOrd, PartialEq)]
#[repr(transparent)]
pub struct NavigationMeasurement(swiftnav_sys::navigation_measurement_t);
impl NavigationMeasurement {
pub fn new() -> Self {
unsafe { std::mem::zeroed::<NavigationMeasurement>() }
}
pub fn set_pseudorange(&mut self, value: f64) {
self.0.pseudorange = value;
self.0.flags |= NAV_MEAS_FLAG_CODE_VALID;
}
pub fn pseudorange(&self) -> Option<f64> {
if self.0.flags & NAV_MEAS_FLAG_CODE_VALID != 0 {
Some(self.0.pseudorange)
} else {
None
}
}
pub fn invalidate_pseudorange(&mut self) {
self.0.flags &= !NAV_MEAS_FLAG_CODE_VALID;
}
pub fn set_measured_doppler(&mut self, value: f64) {
self.0.measured_doppler = value;
self.0.flags |= NAV_MEAS_FLAG_MEAS_DOPPLER_VALID;
}
pub fn measured_doppler(&self) -> Option<f64> {
if self.0.flags & NAV_MEAS_FLAG_MEAS_DOPPLER_VALID != 0 {
Some(self.0.measured_doppler)
} else {
None
}
}
pub fn invalidate_measured_doppler(&mut self) {
self.0.flags &= !NAV_MEAS_FLAG_MEAS_DOPPLER_VALID;
}
pub fn set_satellite_state(&mut self, sat_state: &SatelliteState) {
self.0.sat_pos = *sat_state.pos.as_array_ref();
self.0.sat_vel = *sat_state.vel.as_array_ref();
self.0.sat_acc = *sat_state.acc.as_array_ref();
self.0.sat_clock_err = sat_state.clock_err;
self.0.sat_clock_err_rate = sat_state.clock_rate_err;
}
pub fn set_cn0(&mut self, value: f64) {
self.0.cn0 = value;
self.0.flags |= NAV_MEAS_FLAG_CN0_VALID;
}
pub fn cn0(&self) -> Option<f64> {
if self.0.flags & NAV_MEAS_FLAG_CN0_VALID != 0 {
Some(self.0.cn0)
} else {
None
}
}
pub fn invalidate_cn0(&mut self) {
self.0.flags &= !NAV_MEAS_FLAG_CN0_VALID;
}
pub fn set_lock_time(&mut self, value: Duration) {
self.0.lock_time = value.as_secs_f64();
}
pub fn lock_time(&self) -> Duration {
Duration::from_secs_f64(self.0.lock_time)
}
pub fn set_sid(&mut self, value: GnssSignal) {
self.0.sid = value.to_gnss_signal_t();
}
pub fn sid(&self) -> GnssSignal {
GnssSignal::from_gnss_signal_t(self.0.sid).unwrap()
}
pub fn set_flags(&mut self, flags: u16) {
self.0.flags = flags;
}
pub fn flags(&self) -> u16 {
self.0.flags
}
pub fn flags_are_all_valid(&self) -> bool {
unsafe { swiftnav_sys::nav_meas_flags_valid(self.0.flags) }
}
pub fn pseudorange_is_valid(&self) -> bool {
unsafe { swiftnav_sys::pseudorange_valid(&self.0) }
}
}
impl Default for NavigationMeasurement {
fn default() -> Self {
Self::new()
}
}
pub fn encode_lock_time(nav_meas_lock_time: Duration) -> u8 {
unsafe { swiftnav_sys::encode_lock_time(nav_meas_lock_time.as_secs_f64()) }
}
pub fn decode_lock_time(sbp_lock_time: u8) -> Duration {
let value = unsafe { swiftnav_sys::decode_lock_time(sbp_lock_time) };
Duration::from_secs_f64(value)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn encode() {
let mut ret;
ret = encode_lock_time(Duration::from_secs_f64(0.0));
assert_eq!(ret, 0, "Incorrect return ({} vs {})", ret, 0);
ret = encode_lock_time(Duration::from_secs_f64(0.05));
assert_eq!(ret, 1, "Incorrect return ({} vs {})", ret, 1);
ret = encode_lock_time(Duration::from_secs_f64(0.1));
assert_eq!(ret, 2, "Incorrect return ({} vs {})", ret, 2);
ret = encode_lock_time(Duration::from_secs_f64(0.2));
assert_eq!(ret, 3, "Incorrect return ({} vs {})", ret, 3);
ret = encode_lock_time(Duration::from_secs_f64(0.5));
assert_eq!(ret, 4, "Incorrect return ({} vs {})", ret, 4);
ret = encode_lock_time(Duration::from_secs_f64(1.0));
assert_eq!(ret, 5, "Incorrect return ({} vs {})", ret, 5);
ret = encode_lock_time(Duration::from_secs_f64(2.0));
assert_eq!(ret, 6, "Incorrect return ({} vs {})", ret, 6);
ret = encode_lock_time(Duration::from_secs_f64(4.0));
assert_eq!(ret, 7, "Incorrect return ({} vs {})", ret, 7);
ret = encode_lock_time(Duration::from_secs_f64(5.0));
assert_eq!(ret, 8, "Incorrect return ({} vs {})", ret, 8);
ret = encode_lock_time(Duration::from_secs_f64(10.0));
assert_eq!(ret, 9, "Incorrect return ({} vs {})", ret, 9);
ret = encode_lock_time(Duration::from_secs_f64(20.0));
assert_eq!(ret, 10, "Incorrect return ({} vs {})", ret, 10);
ret = encode_lock_time(Duration::from_secs_f64(50.0));
assert_eq!(ret, 11, "Incorrect return ({} vs {})", ret, 11);
ret = encode_lock_time(Duration::from_secs_f64(100.0));
assert_eq!(ret, 12, "Incorrect return ({} vs {})", ret, 12);
ret = encode_lock_time(Duration::from_secs_f64(200.0));
assert_eq!(ret, 13, "Incorrect return ({} vs {})", ret, 13);
ret = encode_lock_time(Duration::from_secs_f64(500.0));
assert_eq!(ret, 14, "Incorrect return ({} vs {})", ret, 14);
ret = encode_lock_time(Duration::from_secs_f64(1000.0));
assert_eq!(ret, 15, "Incorrect return ({} vs {})", ret, 15);
ret = encode_lock_time(Duration::new(u64::MAX, 1_000_000_000 - 1));
assert_eq!(ret, 15, "Incorrect return ({} vs {})", ret, 15);
}
#[test]
fn decode() {
let mut ret;
let mut exp;
ret = decode_lock_time(0);
exp = Duration::from_secs_f64(0.0);
assert_eq!(ret, exp, "Incorrect return ({:?} vs {:?})", ret, exp);
ret = decode_lock_time(0xF0);
exp = Duration::from_secs_f64(0.0);
assert_eq!(ret, exp, "Incorrect return ({:?} vs {:?})", ret, exp);
ret = decode_lock_time(1);
exp = Duration::from_secs_f64(0.032);
assert_eq!(ret, exp, "Incorrect return ({:?} vs {:?})", ret, exp);
ret = decode_lock_time(2);
exp = Duration::from_secs_f64(0.064);
assert_eq!(ret, exp, "Incorrect return ({:?} vs {:?})", ret, exp);
ret = decode_lock_time(3);
exp = Duration::from_secs_f64(0.128);
assert_eq!(ret, exp, "Incorrect return ({:?} vs {:?})", ret, exp);
ret = decode_lock_time(4);
exp = Duration::from_secs_f64(0.256);
assert_eq!(ret, exp, "Incorrect return ({:?} vs {:?})", ret, exp);
ret = decode_lock_time(5);
exp = Duration::from_secs_f64(0.512);
assert_eq!(ret, exp, "Incorrect return ({:?} vs {:?})", ret, exp);
ret = decode_lock_time(6);
exp = Duration::from_secs_f64(1.024);
assert_eq!(ret, exp, "Incorrect return ({:?} vs {:?})", ret, exp);
ret = decode_lock_time(7);
exp = Duration::from_secs_f64(2.048);
assert_eq!(ret, exp, "Incorrect return ({:?} vs {:?})", ret, exp);
ret = decode_lock_time(8);
exp = Duration::from_secs_f64(4.096);
assert_eq!(ret, exp, "Incorrect return ({:?} vs {:?})", ret, exp);
ret = decode_lock_time(9);
exp = Duration::from_secs_f64(8.192);
assert_eq!(ret, exp, "Incorrect return ({:?} vs {:?})", ret, exp);
ret = decode_lock_time(10);
exp = Duration::from_secs_f64(16.384);
assert_eq!(ret, exp, "Incorrect return ({:?} vs {:?})", ret, exp);
ret = decode_lock_time(11);
exp = Duration::from_secs_f64(32.768);
assert_eq!(ret, exp, "Incorrect return ({:?} vs {:?})", ret, exp);
ret = decode_lock_time(12);
exp = Duration::from_secs_f64(65.536);
assert_eq!(ret, exp, "Incorrect return ({:?} vs {:?})", ret, exp);
ret = decode_lock_time(13);
exp = Duration::from_secs_f64(131.072);
assert_eq!(ret, exp, "Incorrect return ({:?} vs {:?})", ret, exp);
ret = decode_lock_time(14);
exp = Duration::from_secs_f64(262.144);
assert_eq!(ret, exp, "Incorrect return ({:?} vs {:?})", ret, exp);
ret = decode_lock_time(15);
exp = Duration::from_secs_f64(524.288);
assert_eq!(ret, exp, "Incorrect return ({:?} vs {:?})", ret, exp);
}
#[test]
fn round_trip() {
let value_to_encode = Duration::from_secs_f64(260.0);
let encoded_value = encode_lock_time(value_to_encode);
let decoded_value = decode_lock_time(encoded_value);
assert_eq!(
encoded_value, 13,
"Incorrect return ({} vs {})",
encoded_value, 13
);
assert_eq!(
decoded_value,
Duration::from_secs_f64(131.072),
"Incorrect return ({:?} vs {:?})",
decoded_value,
Duration::from_secs_f64(131.072)
);
assert!(
decoded_value < value_to_encode,
"Minimum lock time not less than original lock time ({:?} < {:?})",
decoded_value,
value_to_encode
);
}
}