use crate::binrw_util;
use crate::{NestedBlock, NestedHeader, SubBlock};
use alloc::vec::Vec;
use binrw::binrw;
use super::sat_visibility::RiseSet;
#[binrw]
#[derive(Clone, Debug)]
pub struct ChannelStatus {
#[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 n: u8,
pub sb1_length: u8,
pub sb2_length: u8,
pub reserved: [u8; 3],
#[br(args { count: usize::from(n), inner: (usize::from(sb1_length), usize::from(sb2_length)) },
map = |v: Vec<NestedBlock<ChannelSatInfoHeader, ChannelStateInfo>>| v.into_iter().map(ChannelSatInfo::from).collect())]
#[bw(args_raw = (usize::from(*sb1_length), usize::from(*sb2_length)),
map = |v: &Vec<ChannelSatInfo>| v.iter().cloned().map(NestedBlock::from).collect::<Vec<NestedBlock<ChannelSatInfoHeader, ChannelStateInfo>>>())]
pub sat_info: Vec<ChannelSatInfo>,
}
#[binrw]
#[derive(Clone, Debug)]
struct ChannelSatInfoHeader {
pub svid: u8,
#[br(map = binrw_util::map_u1_zero)]
#[bw(map = binrw_util::unmap_u1_zero)]
pub freq_nr: Option<u8>,
pub reserved1: [u8; 2],
pub azimuth_rise_set: u16,
pub health_status: u16,
#[br(map = binrw_util::map_i1)]
#[bw(map = binrw_util::unmap_i1)]
pub elevation: Option<i8>,
pub n2: u8,
pub rx_channel: u8,
pub reserved2: u8,
}
impl NestedHeader for ChannelSatInfoHeader {
fn nested_count(&self) -> usize {
usize::from(self.n2)
}
}
#[derive(Clone, Debug)]
pub struct ChannelSatInfo {
pub svid: u8,
pub freq_nr: Option<u8>,
pub reserved1: [u8; 2],
pub azimuth_rise_set: u16,
pub health_status: u16,
pub elevation: Option<i8>,
pub n2: u8,
pub rx_channel: u8,
pub reserved2: u8,
pub state_info: Vec<ChannelStateInfo>,
}
impl From<NestedBlock<ChannelSatInfoHeader, ChannelStateInfo>> for ChannelSatInfo {
fn from(nb: NestedBlock<ChannelSatInfoHeader, ChannelStateInfo>) -> Self {
ChannelSatInfo {
svid: nb.header.svid,
freq_nr: nb.header.freq_nr,
reserved1: nb.header.reserved1,
azimuth_rise_set: nb.header.azimuth_rise_set,
health_status: nb.header.health_status,
elevation: nb.header.elevation,
n2: nb.header.n2,
rx_channel: nb.header.rx_channel,
reserved2: nb.header.reserved2,
state_info: nb.items.into_iter().map(SubBlock::into_inner).collect(),
}
}
}
impl From<ChannelSatInfo> for NestedBlock<ChannelSatInfoHeader, ChannelStateInfo> {
fn from(si: ChannelSatInfo) -> Self {
NestedBlock {
header: ChannelSatInfoHeader {
svid: si.svid,
freq_nr: si.freq_nr,
reserved1: si.reserved1,
azimuth_rise_set: si.azimuth_rise_set,
health_status: si.health_status,
elevation: si.elevation,
n2: si.n2,
rx_channel: si.rx_channel,
reserved2: si.reserved2,
},
items: si.state_info.into_iter().map(SubBlock::from).collect(),
}
}
}
impl ChannelSatInfo {
pub fn azimuth(&self) -> Option<u16> {
let value = self.azimuth_rise_set & 0x1FF;
if value == 511 {
None
} else {
Some(value)
}
}
pub fn rise_set(&self) -> RiseSet {
RiseSet::from((self.azimuth_rise_set >> 14) as u8)
}
}
#[binrw]
#[derive(Clone, Debug)]
pub struct ChannelStateInfo {
pub antenna: u8,
pub reserved: u8,
pub tracking_status: u16,
pub pvt_status: u16,
pub pvt_info: u16,
}