#[cfg(feature = "serde")]
use super::SerializeUbxPacketFields;
#[cfg(feature = "serde")]
use crate::serde::ser::SerializeMap;
#[allow(unused_imports, reason = "It is only unused in some feature sets")]
use crate::FieldIter;
use crate::{error::ParserError, UbxPacketMeta};
use ublox_derive::ubx_packet_recv;
const RF_BLOCK_SIZE: usize = 272;
const SPECTRUM_SIZE: usize = 256;
#[ubx_packet_recv]
#[ubx(class = 0x0a, id = 0x31, max_payload_len = 548)] struct MonSpan {
version: u8,
num_rf_blocks: u8,
reserved0: [u8; 2],
#[ubx(map_type = MonSpanRfBlockIter, may_fail,
from = MonSpanRfBlockIter::new,
is_valid = MonSpanRfBlockIter::is_valid)]
rf_blocks: [u8; 0],
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MonSpanRfBlock<'a> {
spectrum: &'a [u8; SPECTRUM_SIZE],
pub span: u32,
pub res: u32,
pub center: u32,
pub pga: u8,
}
impl<'a> MonSpanRfBlock<'a> {
pub fn spectrum_raw(&self) -> &[u8; SPECTRUM_SIZE] {
self.spectrum
}
pub fn spectrum_db(&self, index: usize) -> Option<f32> {
self.spectrum.get(index).map(|&v| v as f32 * 0.25)
}
pub fn spectrum_db_iter(&self) -> impl Iterator<Item = f32> + 'a {
self.spectrum.iter().map(|&v| v as f32 * 0.25)
}
pub fn num_points(&self) -> Option<u32> {
if self.res > 0 {
Some(self.span / self.res)
} else {
None
}
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for MonSpanRfBlock<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeStruct;
let mut state = serializer.serialize_struct("MonSpanRfBlock", 5)?;
state.serialize_field("spectrum", self.spectrum.as_slice())?;
state.serialize_field("span", &self.span)?;
state.serialize_field("res", &self.res)?;
state.serialize_field("center", &self.center)?;
state.serialize_field("pga", &self.pga)?;
state.end()
}
}
#[derive(Debug, Clone)]
pub struct MonSpanRfBlockIter<'a> {
data: &'a [u8],
offset: usize,
}
impl<'a> MonSpanRfBlockIter<'a> {
fn new(data: &'a [u8]) -> Self {
Self { data, offset: 0 }
}
#[allow(dead_code, reason = "Used by ubx_packet_recv macro for validation")]
fn is_valid(payload: &[u8]) -> bool {
payload.len().is_multiple_of(RF_BLOCK_SIZE)
}
}
impl<'a> core::iter::Iterator for MonSpanRfBlockIter<'a> {
type Item = MonSpanRfBlock<'a>;
fn next(&mut self) -> Option<Self::Item> {
let chunk = self.data.get(self.offset..self.offset + RF_BLOCK_SIZE)?;
let spectrum: &[u8; SPECTRUM_SIZE] = chunk[0..SPECTRUM_SIZE].try_into().ok()?;
let block = MonSpanRfBlock {
spectrum,
span: u32::from_le_bytes(chunk[256..260].try_into().ok()?),
res: u32::from_le_bytes(chunk[260..264].try_into().ok()?),
center: u32::from_le_bytes(chunk[264..268].try_into().ok()?),
pga: chunk[268],
};
self.offset += RF_BLOCK_SIZE;
Some(block)
}
}