nrf24_rs/
status.rs

1//! Status datastructures.
2use crate::config::DataPipe;
3
4/// Wrapper for the status value returned from the device.
5/// Provides convenience methods and debug implemantions.
6#[derive(Copy, Clone, Eq, PartialEq)]
7pub struct Status(u8);
8
9impl Status {
10    /// Returns the raw value represented by this struct.
11    pub fn raw(&self) -> u8 {
12        self.0
13    }
14    /// Indicates if there is data ready to be read.
15    pub fn data_ready(&self) -> bool {
16        (self.0 >> 6) & 1 != 0
17    }
18    /// Indicates whether data has been sent.
19    pub fn data_sent(&self) -> bool {
20        (self.0 >> 5) & 1 != 0
21    }
22    /// Indicates whether the max retries has been reached.
23    /// Can only be true if auto acknowledgement is enabled.
24    pub fn reached_max_retries(&self) -> bool {
25        (self.0 >> 4) & 1 != 0
26    }
27    /// Returns data pipe number for the payload availbe for reading
28    /// or None if RX FIFO is empty.
29    pub fn data_pipe_available(&self) -> Option<DataPipe> {
30        match (self.0 >> 1) & 0b111 {
31            x @ 0..=5 => Some(x.into()),
32            6 => panic!(),
33            7 => None,
34            _ => unreachable!(), // because we AND the value
35        }
36    }
37    /// Indicates whether the transmission queue is full or not.
38    pub fn tx_full(&self) -> bool {
39        (self.0 & 0b1) != 0
40    }
41}
42
43/// Represents the different interrupt types available on the nRF24L01.
44///
45/// Each variant corresponds to a specific interrupt condition, with values matching
46/// the bit positions in the STATUS register.
47///
48/// The nRF24L01 IRQ pin is active LOW and will be asserted when any enabled interrupt occurs.
49#[derive(Clone, Copy, PartialEq, Eq)]
50#[repr(u8)]
51pub enum InterruptKind {
52    /// Maximum number of TX retransmits interrupt.
53    MaxRetries = 0b0001_0000,
54    /// Data Sent TX FIFO interrupt. Asserted when packet transmitted on TX.
55    TxDataSent = 0b0010_0000,
56    /// Data Ready RX FIFO interrupt. Asserted when new data arrives RX FIFO.
57    RxDataReady = 0b0100_0000,
58}
59
60/// A bitfield representing multiple nRF24L01 interrupts.
61///
62/// This structure allows for the manipulation and checking of interrupt flags
63/// as they appear in the STATUS register. Multiple interrupts can be
64/// combined using the builder pattern methods.
65///
66/// # Examples
67///
68/// ```
69/// // Create an interrupt set with RX data ready and max retries
70/// let interrupts = Interrupts::new().rx_data_ready().max_retries();
71///
72/// // Check if a specific interrupt is set
73/// if interrupts.contains(InterruptKind::RxDataReady) {
74///     // Handle RX data ready interrupt
75/// }
76/// ```
77#[derive(Copy, Clone)]
78pub struct Interrupts(u8);
79
80impl Interrupts {
81    /// Creates a new empty interrupt set with no interrupts enabled.
82    pub fn new() -> Self {
83        Self(0)
84    }
85    /// Creates an interrupt set with all possible interrupts enabled.
86    pub fn all() -> Self {
87        Self::new().max_retries().tx_data_sent().rx_data_ready()
88    }
89    /// Adds the Maximum Retries interrupt to this set.
90    ///
91    /// This interrupt is triggered when the maximum number of retransmits
92    /// has been reached on a packet.
93    pub fn max_retries(mut self) -> Self {
94        self.0 |= InterruptKind::MaxRetries as u8;
95        self
96    }
97    /// Adds the TX Data Sent interrupt to this set.
98    ///
99    /// This interrupt is triggered when a packet has been successfully transmitted.
100    pub fn tx_data_sent(mut self) -> Self {
101        self.0 |= InterruptKind::TxDataSent as u8;
102        self
103    }
104    /// Adds the RX Data Ready interrupt to this set.
105    ///
106    /// This interrupt is triggered when new data has arrived in the RX FIFO.
107    pub fn rx_data_ready(mut self) -> Self {
108        self.0 |= InterruptKind::RxDataReady as u8;
109        self
110    }
111    /// Checks if the given interrupt kind is set in this interrupt set.
112    ///
113    /// Returns `true` if the interrupt is set, `false` otherwise.
114    pub fn contains(&self, irq: InterruptKind) -> bool {
115        self.0 & irq as u8 != 0
116    }
117    /// Returns the raw byte value of this interrupt set.
118    ///
119    /// This is useful when writing to the STATUS or CONFIG registers.
120    pub(crate) fn raw(&self) -> u8 {
121        self.0
122    }
123}
124
125impl From<u8> for Interrupts {
126    /// Converts a raw byte value to an Interrupts struct.
127    ///
128    /// Only bits that correspond to valid interrupts are preserved.
129    fn from(t: u8) -> Self {
130        Self(t & Self::all().raw())
131    }
132}
133
134impl From<u8> for Status {
135    fn from(t: u8) -> Self {
136        Status(t)
137    }
138}
139
140#[cfg(feature = "defmt")]
141impl defmt::Format for Status {
142    fn format(&self, fmt: defmt::Formatter) {
143        if self.raw() & 0x80 != 0 {
144            defmt::write!(
145                fmt,
146                "Invalid status. Something went wrong during communication with nrf24l01"
147            )
148        } else {
149            defmt::write!(
150            fmt,
151            "Status {{ data_ready: {}, data_sent: {}, reached_max_retries: {}, data_pipe_available: {:?}, tx_full: {} }}",
152            self.data_ready(),
153            self.data_sent(),
154            self.reached_max_retries(),
155            self.data_pipe_available(),
156            self.tx_full()
157        )
158        }
159    }
160}
161
162/// Wrapper around the FIFO status.
163#[derive(Copy, Clone, Eq, PartialEq)]
164pub struct FIFOStatus(u8);
165
166impl FIFOStatus {
167    /// Returns `true` if there are availbe locations in transmission queue
168    pub fn tx_full(&self) -> bool {
169        (self.0 >> 5) & 1 != 0
170    }
171
172    /// Returns `true` if the transmission queue is empty
173    pub fn tx_empty(&self) -> bool {
174        (self.0 >> 4) & 1 != 0
175    }
176
177    /// Returns `true` if there are availbe locations in receive queue
178    pub fn rx_full(&self) -> bool {
179        (self.0 >> 1) & 1 != 0
180    }
181
182    /// Returns `true` if the receive queue is empty
183    pub fn rx_empty(&self) -> bool {
184        self.0 & 1 != 0
185    }
186}
187
188impl From<u8> for FIFOStatus {
189    fn from(t: u8) -> Self {
190        FIFOStatus(t)
191    }
192}