pub const DOT15D4_CHANNEL_MIN: u8 = 11;
pub const DOT15D4_CHANNEL_MAX: u8 = 26;
pub const DOT15D4_CHANNEL_BASE_FREQUENCY_MHZ: u32 = 2405;
pub const DOT15D4_CHANNEL_SPACING_MHZ: u32 = 5;
pub const DOT15D4_FCS_LEN: usize = 2;
pub const DOT15D4_FCF_LEN: usize = 2;
pub const DOT15D4_SEQ_LEN: usize = 1;
pub const DOT15D4_PAN_ID_LEN: usize = 2;
pub const DOT15D4_SHORT_ADDR_LEN: usize = 2;
pub const DOT15D4_EXTENDED_ADDR_LEN: usize = 8;
pub const DLT_IEEE802_15_4_WITHFCS: u32 = 195;
pub const DLT_IEEE802_15_4_NOFCS: u32 = 230;
pub const DLT_IEEE802_15_4_TAP: u32 = 283;
pub const fn channel_frequency_mhz(channel: u8) -> Option<u32> {
if channel >= DOT15D4_CHANNEL_MIN && channel <= DOT15D4_CHANNEL_MAX {
Some(
DOT15D4_CHANNEL_BASE_FREQUENCY_MHZ
+ DOT15D4_CHANNEL_SPACING_MHZ * (channel as u32 - DOT15D4_CHANNEL_MIN as u32),
)
} else {
None
}
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Dot15d4FrameType {
Beacon = 0,
Data = 1,
Ack = 2,
MacCommand = 3,
}
impl Dot15d4FrameType {
pub const fn from_u3(value: u8) -> Option<Self> {
match value {
0 => Some(Self::Beacon),
1 => Some(Self::Data),
2 => Some(Self::Ack),
3 => Some(Self::MacCommand),
_ => None,
}
}
pub const fn as_u3(self) -> u8 {
self as u8
}
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Dot15d4AddrMode {
None = 0,
Short = 2,
Extended = 3,
}
impl Dot15d4AddrMode {
pub const fn from_u2(value: u8) -> Option<Self> {
match value {
0 => Some(Self::None),
2 => Some(Self::Short),
3 => Some(Self::Extended),
_ => None,
}
}
pub const fn as_u2(self) -> u8 {
self as u8
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dot15d4_consts_channel_bounds_match_manifest() {
assert_eq!(DOT15D4_CHANNEL_MIN, 11);
assert_eq!(DOT15D4_CHANNEL_MAX, 26);
assert_eq!(DOT15D4_FCS_LEN, 2);
assert_eq!(DLT_IEEE802_15_4_WITHFCS, 195);
assert_eq!(DLT_IEEE802_15_4_NOFCS, 230);
assert_eq!(DLT_IEEE802_15_4_TAP, 283);
}
#[test]
fn dot15d4_consts_channel_frequency_round_trips() {
assert_eq!(channel_frequency_mhz(11), Some(2405));
assert_eq!(channel_frequency_mhz(12), Some(2410));
assert_eq!(channel_frequency_mhz(26), Some(2480));
assert_eq!(channel_frequency_mhz(27), None);
assert_eq!(channel_frequency_mhz(10), None);
assert_eq!(channel_frequency_mhz(0), None);
}
#[test]
fn dot15d4_consts_frame_type_round_trips() {
let frame_types = [
(0, Dot15d4FrameType::Beacon),
(1, Dot15d4FrameType::Data),
(2, Dot15d4FrameType::Ack),
(3, Dot15d4FrameType::MacCommand),
];
for (raw, frame_type) in frame_types {
assert_eq!(Dot15d4FrameType::from_u3(raw), Some(frame_type));
assert_eq!(frame_type.as_u3(), raw);
}
assert_eq!(Dot15d4FrameType::from_u3(4), None);
assert_eq!(Dot15d4FrameType::from_u3(5), None);
assert_eq!(Dot15d4FrameType::from_u3(6), None);
assert_eq!(Dot15d4FrameType::from_u3(7), None);
}
#[test]
fn dot15d4_consts_addr_mode_round_trips() {
let addr_modes = [
(0, Dot15d4AddrMode::None),
(2, Dot15d4AddrMode::Short),
(3, Dot15d4AddrMode::Extended),
];
for (raw, addr_mode) in addr_modes {
assert_eq!(Dot15d4AddrMode::from_u2(raw), Some(addr_mode));
assert_eq!(addr_mode.as_u2(), raw);
}
assert_eq!(Dot15d4AddrMode::from_u2(1), None);
}
}