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]
22pub struct Frame {
23    /// Header
24    pub header: Header,
25    /// Content
26    pub content: FrameContent,
27    /// Payload
28    pub payload: Vec<u8>,
29    /// This is a 2-byte CRC checksum
30    pub footer: [u8; 2],
31}
32
33// FIXME: Remove and use derive when defmt 1.0.2 is released (we need https://github.com/knurling-rs/defmt/pull/955)
34#[cfg(feature = "defmt")]
35impl defmt::Format for Frame {
36    fn format(&self, f: defmt::Formatter<'_>) {
37        defmt::write!(
38            f,
39            "Frame {{ header: {}, content: {}, payload: {:?}, footer: {:?} }}",
40            self.header,
41            self.content,
42            self.payload.as_slice(),
43            self.footer
44        );
45    }
46}
47
48/// IEEE 802.15.4 MAC frame which has been received
49#[derive(Debug, Clone, PartialEq, Eq)]
50#[cfg_attr(feature = "defmt", derive(defmt::Format))]
51#[instability::unstable]
52pub struct ReceivedFrame {
53    /// Frame
54    pub frame: Frame,
55    /// Receiver channel
56    pub channel: u8,
57    /// Received Signal Strength Indicator (RSSI)
58    pub rssi: i8,
59    /// Link Quality Indication (LQI)
60    pub lqi: u8,
61}
62
63pub(crate) fn frame_is_ack_required(frame: &[u8]) -> bool {
64    if frame.len() <= FRAME_AR_OFFSET {
65        return false;
66    }
67    (frame[FRAME_AR_OFFSET] & FRAME_AR_BIT) != 0
68}
69
70pub(crate) fn frame_get_version(frame: &[u8]) -> u8 {
71    if frame.len() <= FRAME_VERSION_OFFSET {
72        return 0;
73    }
74    frame[FRAME_VERSION_OFFSET] & FRAME_VERSION_MASK
75}