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}