use heapless::Vec;
use postcard::experimental::max_size::MaxSize;
use serde::{Deserialize, Serialize};
use super::{Bandwidth, PpduFormat};
pub const MAX_RESPONDERS: usize = 8;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, MaxSize)]
#[non_exhaustive]
pub struct MeasurementSetup {
pub id: u8,
pub acquisition: AcquisitionFilter,
pub stimulus: Option<StimulusParams>,
}
impl MeasurementSetup {
pub fn new(id: u8) -> Self {
Self {
id,
acquisition: AcquisitionFilter::default(),
stimulus: None,
}
}
pub fn with_acquisition(mut self, acquisition: AcquisitionFilter) -> Self {
self.acquisition = acquisition;
self
}
pub fn with_stimulus(mut self, stimulus: StimulusParams) -> Self {
self.stimulus = Some(stimulus);
self
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, MaxSize)]
#[non_exhaustive]
pub struct AcquisitionFilter {
pub channel: Option<u8>,
pub bandwidth: Option<Bandwidth>,
pub ppdu_formats: PpduSet,
pub transmitter: Option<[u8; 6]>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, MaxSize)]
pub struct PpduSet(u16);
impl PpduSet {
pub const ANY: Self = Self(0);
const fn bit(f: PpduFormat) -> u16 {
1 << match f {
PpduFormat::Unknown => 0,
PpduFormat::Dsss => 1,
PpduFormat::NonHt => 2,
PpduFormat::Ht => 3,
PpduFormat::Vht => 4,
PpduFormat::VhtMu => 5,
PpduFormat::HeSu => 6,
PpduFormat::HeMu => 7,
PpduFormat::HeErSu => 8,
PpduFormat::HeTb => 9,
PpduFormat::Eht => 10,
}
}
pub const fn with(self, f: PpduFormat) -> Self {
Self(self.0 | Self::bit(f))
}
pub const fn contains(self, f: PpduFormat) -> bool {
self.0 == 0 || self.0 & Self::bit(f) != 0
}
pub const fn is_any(self) -> bool {
self.0 == 0
}
pub const fn only_he(self) -> bool {
let he = Self::bit(PpduFormat::HeSu)
| Self::bit(PpduFormat::HeMu)
| Self::bit(PpduFormat::HeErSu)
| Self::bit(PpduFormat::HeTb);
self.0 != 0 && self.0 & !he == 0
}
pub const fn excludes_legacy(self) -> bool {
self.0 != 0 && self.0 & (Self::bit(PpduFormat::Dsss) | Self::bit(PpduFormat::NonHt)) == 0
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, MaxSize)]
#[non_exhaustive]
pub struct StimulusParams {
pub periodicity_us: u32,
pub bandwidth: Bandwidth,
pub report: ReportType,
pub ng: u8,
pub nb: u8,
pub trigger_based: bool,
pub responders: Vec<[u8; 6], MAX_RESPONDERS>,
}
impl StimulusParams {
pub fn new(periodicity_us: u32, bandwidth: Bandwidth) -> Self {
Self {
periodicity_us,
bandwidth,
report: ReportType::Raw,
ng: 1,
nb: 8,
trigger_based: false,
responders: Vec::new(),
}
}
pub const fn rate_hz(&self) -> u16 {
if self.periodicity_us == 0 {
return u16::MAX;
}
let hz = 1_000_000 / self.periodicity_us;
if hz > u16::MAX as u32 { u16::MAX } else if hz == 0 { 1 } else { hz as u16 }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, MaxSize)]
#[non_exhaustive]
pub enum ReportType {
Raw,
Grouped,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum SetupError {
NoStimulus,
UnsupportedStimulus(&'static str),
UnsupportedAcquisition(&'static str),
}