1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
//! This module contains definition of Frame Control field that is defined int 5.2.1.1 section.
use super::header::Address;
use super::DecodeError;

/// Defines the type of a MAC frame
///
/// Part of [`Header`].
///
/// [`Header`]: super::header::Header
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum FrameType {
    /// Beacon
    Beacon = 0b000,

    /// Data
    Data = 0b001,

    /// Acknowledgement
    Acknowledgement = 0b010,

    /// MAC command
    MacCommand = 0b011,

    /// Multipurpose
    Multipurpose = 0b101,

    /// Fragment of Fragment Ack
    FragOrFragAck = 0b110,

    /// Extended
    Extended = 0b111,
}

impl FrameType {
    /// Creates an instance of [`FrameType`] from the provided bits
    ///
    /// Returns `None`, if the provided bits don't encode a valid frame type.
    ///
    /// # Example
    ///
    /// ``` rust
    /// use ieee802154::mac::FrameType;
    ///
    /// let frame_type = FrameType::from_bits(0b001);
    /// assert_eq!(frame_type, Some(FrameType::Data));
    /// ```
    pub fn from_bits(bits: u8) -> Option<Self> {
        match bits {
            0b000 => Some(FrameType::Beacon),
            0b001 => Some(FrameType::Data),
            0b010 => Some(FrameType::Acknowledgement),
            0b011 => Some(FrameType::MacCommand),
            0b101 => Some(FrameType::Multipurpose),
            0b110 => Some(FrameType::FragOrFragAck),
            0b111 => Some(FrameType::Extended),
            _ => None,
        }
    }
}

/// Defines version information for a frame
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum FrameVersion {
    /// A frame conforming to the 802.15.4-2003 standard
    Ieee802154_2003 = 0b00,
    /// A frame conforming to the 802.15.4-2006 standard
    Ieee802154_2006 = 0b01,
    /// A frame conforming to the current 802.15.4 standard
    Ieee802154 = 0b10,
}

impl FrameVersion {
    /// Creates an instance of [`FrameVersion`] from the provided bits
    ///
    /// Returns `None`, if the provided bits don't encode a valid value of
    /// `FrameVersion`.
    ///
    /// # Example
    ///
    /// ``` rust
    /// use ieee802154::mac::FrameVersion;
    ///
    /// let version = FrameVersion::from_bits(0b0);
    /// assert_eq!(version, Some(FrameVersion::Ieee802154_2003));
    /// ```
    pub fn from_bits(bits: u8) -> Option<Self> {
        match bits {
            0b00 => Some(FrameVersion::Ieee802154_2003),
            0b01 => Some(FrameVersion::Ieee802154_2006),
            0b10 => Some(FrameVersion::Ieee802154),
            _ => None,
        }
    }
}

/// Defines the type of Address
///
/// # Example
/// ```rust
/// use ieee802154::mac::{Address, AddressMode, PanId, ShortAddress};
///
/// let example_addr = Some(Address::Short(PanId(0x3412), ShortAddress(0x7856)));
/// let address_mode = AddressMode::from(example_addr);
/// assert_eq!(address_mode, AddressMode::Short);
/// ```
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]

pub enum AddressMode {
    /// PAN identifier and address field are not present
    None = 0b00,
    /// Address field contains a 16 bit short address
    Short = 0b10,
    /// Address field contains a 64 bit extended address
    Extended = 0b11,
}

impl From<Option<Address>> for AddressMode {
    fn from(opt_addr: Option<Address>) -> Self {
        match opt_addr {
            Some(Address::Short(..)) => Self::Short,
            Some(Address::Extended(..)) => Self::Extended,
            None => Self::None,
        }
    }
}

impl From<Address> for AddressMode {
    fn from(addr: Address) -> Self {
        match addr {
            Address::Short(_, _) => Self::Short,
            Address::Extended(_, _) => Self::Extended,
        }
    }
}

impl AddressMode {
    /// Creates an instance of [`AddressMode`] from the provided bits
    ///
    /// Returns `None`, if the provided bits don't encode a valid value of
    /// `AddressMode`.
    ///
    /// # Example
    ///
    /// ``` rust
    /// use ieee802154::mac::AddressMode;
    /// // decode
    /// let address_mode = AddressMode::from_bits(0b10).unwrap();
    /// assert_eq!(address_mode, AddressMode::Short);
    /// ```
    pub fn from_bits(bits: u8) -> Result<Self, DecodeError> {
        match bits {
            0b00 => Ok(AddressMode::None),
            0b10 => Ok(AddressMode::Short),
            0b11 => Ok(AddressMode::Extended),
            _ => Err(DecodeError::InvalidAddressMode(bits)),
        }
    }
}

pub mod offset {
    pub const FRAME_TYPE: u16 = 0;
    pub const SECURITY: u16 = 3;
    pub const PENDING: u16 = 4;
    pub const ACK: u16 = 5;
    pub const PAN_ID_COMPRESS: u16 = 6;
    pub const SEQ_NO_SUPPRESS: u16 = 8;
    pub const IE_PRESENT: u16 = 9;
    pub const DEST_ADDR_MODE: u16 = 10;
    pub const VERSION: u16 = 12;
    pub const SRC_ADDR_MODE: u16 = 14u16;
}

pub mod mask {
    pub const FRAME_TYPE: u16 = 0x0007;
    pub const SECURITY: u16 = 0x0008;
    pub const PENDING: u16 = 0x0010;
    pub const ACK: u16 = 0x0020;
    pub const PAN_ID_COMPRESS: u16 = 0x0040;
    pub const SEQ_NO_SUPPRESS: u16 = 0x0100;
    pub const IE_PRESENT: u16 = 0x0200;
    pub const DEST_ADDR_MODE: u16 = 0x0C00;
    pub const VERSION: u16 = 0x3000;
    pub const SRC_ADDR_MODE: u16 = 0xC000;
}