Skip to main content

esp_radio/ieee802154/
frame.rs

1use alloc::vec::Vec;
2
3use ieee802154::mac::{FrameContent, Header};
4
5pub(crate) const FRAME_SIZE: usize = 129;
6pub(crate) const FRAME_VERSION_1: u8 = 0x10; // IEEE 802.15.4 - 2006 & 2011
7pub(crate) const FRAME_VERSION_2: u8 = 0x20; // IEEE 802.15.4 - 2015
8
9// These offsets index the length-stripped PSDU that every caller passes in:
10// frames are built from a pointer one byte past the PHY length byte (`.add(1)`)
11// and the RX path reads `RX_BUFFER[1..]`, so byte 0 is the first FCF octet. The
12// IEEE 802.15.4 FCF carries the AR (ack-request) bit in FCF octet 0 and the
13// frame-version field in FCF octet 1.
14const FRAME_AR_OFFSET: usize = 0;
15const FRAME_AR_BIT: u8 = 0x20;
16const FRAME_VERSION_OFFSET: usize = 1;
17const FRAME_VERSION_MASK: u8 = 0x30;
18
19/// IEEE 802.15.4 MAC frame
20#[derive(Debug, Clone, PartialEq, Eq)]
21#[instability::unstable]
22#[cfg_attr(feature = "defmt", derive(defmt::Format))]
23pub struct Frame {
24    /// Header
25    pub header: Header,
26    /// Content
27    pub content: FrameContent,
28    /// Payload
29    pub payload: Vec<u8>,
30    /// This is a 2-byte CRC checksum
31    pub footer: [u8; 2],
32}
33
34/// IEEE 802.15.4 MAC frame which has been received
35#[derive(Debug, Clone, PartialEq, Eq)]
36#[cfg_attr(feature = "defmt", derive(defmt::Format))]
37#[instability::unstable]
38pub struct ReceivedFrame {
39    /// Frame
40    pub frame: Frame,
41    /// Receiver channel
42    pub channel: u8,
43    /// Received Signal Strength Indicator (RSSI)
44    pub rssi: i8,
45    /// Link Quality Indication (LQI)
46    pub lqi: u8,
47}
48
49pub(crate) fn frame_is_ack_required(frame: &[u8]) -> bool {
50    frame
51        .get(FRAME_AR_OFFSET)
52        .is_some_and(|fcf| fcf & FRAME_AR_BIT != 0)
53}
54
55pub(crate) fn frame_get_version(frame: &[u8]) -> u8 {
56    frame
57        .get(FRAME_VERSION_OFFSET)
58        .map_or(0, |fcf| fcf & FRAME_VERSION_MASK)
59}