rf24/radio/
prelude.rs

1//! This module defines the generic traits that may
2//! need to imported to use radio implementations.
3//!
4//! Since rustc only compiles objects that are used,
5//! it is convenient to import these traits with the `*` syntax.
6//!
7//! ```
8//! use rf24::radio::prelude::*;
9//! ```
10
11use crate::types::{CrcLength, DataRate, FifoState, PaLevel, StatusFlags};
12
13use super::RadioConfig;
14
15/// A trait to alias hardware related errors about the radio.
16pub trait RadioErrorType {
17    type Error;
18}
19
20/// A trait to represent manipulation of data pipes
21/// for an ESB capable transceiver.
22pub trait EsbPipe: RadioErrorType {
23    /// Open a specified `pipe` for receiving data when radio is in RX mode.
24    ///
25    /// If the specified `pipe` is not in range [0, 5], then this function does nothing.
26    ///
27    /// Up to 6 pipes can be open for reading at once. Open all the required
28    /// reading pipes, and then call [`EsbRadio::as_rx()`].
29    ///
30    /// ### About pipe addresses
31    /// Pipes 0 and 1 will store a full 5-byte address. Pipes 2-5 will technically
32    /// only store a single byte, borrowing up to 4 additional bytes from pipe 1 per
33    /// [`EsbPipe::set_address_length()`].
34    ///
35    /// Pipes 1-5 should share the same address, except the first byte.
36    /// Only the first byte in the array should be unique, e.g.
37    /// ```ignore
38    /// let a = ["Prime", "2Node", "3xxxx", "4xxxx"];
39    /// radio.open_rx_pipe(0, a[0].as_bytes()).unwrap(); // address used is "Prime"
40    /// radio.open_rx_pipe(1, a[1].as_bytes()).unwrap(); // address used is "2Node"
41    /// radio.open_rx_pipe(2, a[2].as_bytes()).unwrap(); // address used is "3Node"
42    /// radio.open_rx_pipe(3, a[3].as_bytes()).unwrap(); // address used is "4Node"
43    /// ```
44    ///
45    /// <div class="warning">
46    ///
47    /// Only pipe 0 can be used for transmitting. It is highly recommended to
48    /// avoid using pipe 0 to receive because of this.
49    ///
50    /// If the pipe 0 is opened for receiving by this function, the `address`
51    /// passed to this function (for pipe 0) will be restored at every call to
52    /// [`EsbRadio::as_rx()`].
53    /// This address restoration is implemented because of the underlying necessary
54    /// functionality of [`EsbRadio::as_tx()`].
55    ///
56    /// It is important that the `address` length for pipe 0
57    /// is equal to the length configured by [`EsbPipe::set_address_length()`].
58    ///
59    /// </div>
60    ///
61    /// Read [maniacBug's blog post](http://maniacalbits.blogspot.com/2013/04/rf24-addressing-nrf24l01-radios-require.html)
62    /// to understand how to avoid using malformed addresses.
63    fn open_rx_pipe(&mut self, pipe: u8, address: &[u8]) -> Result<(), Self::Error>;
64
65    /// Close a specified pipe from receiving data when radio is in RX mode.
66    fn close_rx_pipe(&mut self, pipe: u8) -> Result<(), Self::Error>;
67
68    /// Set the address length (applies to all pipes).
69    ///
70    /// If the specified length is clamped to the range [2, 5].
71    /// Any value outside that range defaults to 5.
72    fn set_address_length(&mut self, length: u8) -> Result<(), Self::Error>;
73
74    /// Get the currently configured address length (applied to all pipes).
75    fn get_address_length(&mut self) -> Result<u8, Self::Error>;
76}
77
78/// A trait to represent manipulation of a channel (aka frequency)
79/// for an ESB capable transceiver.
80pub trait EsbChannel: RadioErrorType {
81    /// Set the radio's currently selected channel.
82    ///
83    /// These channels translate to the RF frequency as an offset of Hz from 2400 MHz.
84    /// The default channel is 76 (2400 + 76 = 2.476 GHz).
85    fn set_channel(&mut self, channel: u8) -> Result<(), Self::Error>;
86
87    /// Get the radio's currently selected channel.
88    fn get_channel(&mut self) -> Result<u8, Self::Error>;
89}
90
91/// A trait to represent manipulation of [`StatusFlags`]
92/// for an ESB capable transceiver.
93pub trait EsbStatus: RadioErrorType {
94    /// Get the [`StatusFlags`] state that was cached from the latest SPI transaction.
95    fn get_status_flags(&self, flags: &mut StatusFlags);
96
97    /// Configure which status flags trigger the radio's IRQ pin.
98    ///
99    /// Set any member of [`StatusFlags`] to `false` to have the
100    /// IRQ pin ignore the corresponding event.
101    /// By default, all events are enabled and will trigger the IRQ pin,
102    /// a behavior equivalent to `set_status_flags(None)`.
103    fn set_status_flags(&mut self, flags: StatusFlags) -> Result<(), Self::Error>;
104
105    /// Clear the radio's IRQ status flags
106    ///
107    /// This needs to be done after the event has been handled.
108    ///
109    /// Set any member of [`StatusFlags`] to `true` to clear the corresponding
110    /// interrupt event. Setting any member of [`StatusFlags`] to `false` will leave
111    /// the corresponding status flag untouched. This means that the IRQ pin can remain
112    /// active (LOW) when multiple events occurred but only flag was cleared.
113    fn clear_status_flags(&mut self, flags: StatusFlags) -> Result<(), Self::Error>;
114
115    /// Refresh the internal cache of status byte
116    /// (which is also saved from every SPI transaction).
117    ///
118    /// Use [`EsbStatus::get_status_flags()`] to get the updated status flags.
119    fn update(&mut self) -> Result<(), Self::Error>;
120}
121
122/// A trait to represent manipulation of RX and TX FIFOs
123/// for an ESB capable transceiver.
124pub trait EsbFifo: RadioErrorType {
125    /// Flush the radio's RX FIFO.
126    fn flush_rx(&mut self) -> Result<(), Self::Error>;
127
128    /// Flush the radio's TX FIFO.
129    ///
130    /// This function is automatically called by [`EsbRadio::as_tx()`]
131    /// if ACK payloads are enabled.
132    fn flush_tx(&mut self) -> Result<(), Self::Error>;
133
134    /// Get the state of the specified FIFO.
135    ///
136    /// - Pass `true` to `about_tx` parameter to get the state of the TX FIFO.
137    /// - Pass `false` to `about_tx` parameter to get the state of the RX FIFO.
138    fn get_fifo_state(&mut self, about_tx: bool) -> Result<FifoState, Self::Error>;
139
140    /// Is there a payload available in the radio's RX FIFO?
141    ///
142    /// This function simply returns true if there is data to [`EsbRadio::read()`] from the RX FIFO.
143    /// Use [`EsbFifo::available_pipe()`] to get information about the pipe that received the data.
144    fn available(&mut self) -> Result<bool, Self::Error>;
145
146    /// This is similar to [`EsbFifo::available()`] except the `pipe` parameter is given
147    /// a mutable [`u8`] value, and the pipe number that received the data is stored to it.
148    ///
149    /// If there is no data ready to [`EsbRadio::read()`] in the RX FIFO, then the `pipe` parameter's
150    /// value is untouched.
151    ///
152    /// ```ignore
153    /// let mut pipe = 9; // using an invalid pipe number
154    /// if radio.available_pipe(&mut pipe).is_ok_and(|rv| rv) {
155    ///     // `pipe` should now be set to a valid pipe number
156    ///     print!("A Payload was received on pipe {pipe}");
157    /// }
158    /// ```
159    ///
160    /// <div class="warning">
161    ///
162    /// According to the nRF24L01 datasheet, the data saved to `pipe` is
163    /// "unreliable" during a FALLING transition on the IRQ pin.
164    ///
165    /// During an ISR (Interrupt Service Routine), call
166    /// [`EsbStatus::get_status_flags()`] and/or [`EsbStatus::clear_status_flags()`]
167    /// before calling this function.
168    ///
169    /// </div>
170    fn available_pipe(&mut self, pipe: &mut u8) -> Result<bool, Self::Error>;
171}
172
173/// A trait to represent manipulation of payload lengths (static or dynamic)
174/// for an ESB capable transceiver.
175pub trait EsbPayloadLength: RadioErrorType {
176    /// Set the radio's static payload length.
177    ///
178    /// Note, this has no effect when dynamic payloads are enabled.
179    fn set_payload_length(&mut self, length: u8) -> Result<(), Self::Error>;
180
181    /// Get the currently configured static payload length used on pipe 0
182    ///
183    /// Use [`EsbPayloadLength::get_dynamic_payload_length()`] instead when dynamic payloads are enabled.
184    fn get_payload_length(&mut self) -> Result<u8, Self::Error>;
185
186    /// Set the dynamic payloads feature for all pipes.
187    ///
188    /// Dynamic payloads are required to use ACK packets with payloads appended.
189    ///
190    /// Enabling dynamic payloads nullifies the effect of
191    /// [`EsbPayloadLength::set_payload_length()`] and
192    /// [`EsbPayloadLength::get_payload_length()`].
193    /// Use [`EsbPayloadLength::get_dynamic_payload_length()`] to
194    /// fetch the length of the next [`EsbFifo::available()`] payload in the RX FIFO.
195    ///
196    /// ```ignore
197    /// radio.set_dynamic_payloads(true).unwrap();
198    /// // ... then after or during RX mode:
199    /// if radio.available().unwrap() {
200    ///     let length = radio.get_dynamic_payload_length().unwrap();
201    ///     let mut payload = [0; 32];
202    ///     radio.read(&mut payload, length).unwrap();
203    ///     // do something with the new payload data:
204    ///     for byte in payload[..length as usize] {
205    ///         print!("{:#02x} ", byte);
206    ///     }
207    /// }
208    /// ```
209    fn set_dynamic_payloads(&mut self, enable: bool) -> Result<(), Self::Error>;
210
211    /// Get the current setting of the dynamic payloads feature.
212    ///
213    /// Controlled by [`EsbPayloadLength::set_dynamic_payloads()`].
214    fn get_dynamic_payloads(&self) -> bool;
215
216    /// Get the dynamic length of the next available payload in the RX FIFO.
217    ///
218    /// When dynamic payloads are disabled (via [`EsbPayloadLength::set_dynamic_payloads()`])
219    /// or there is no [`EsbFifo::available()`] payload in the RX FIFO, this function's
220    /// returned value shall be considered invalid.
221    fn get_dynamic_payload_length(&mut self) -> Result<u8, Self::Error>;
222}
223
224/// A trait to represent manipulation of the automatic acknowledgement feature
225/// for an ESB capable transceiver.
226pub trait EsbAutoAck: EsbPayloadLength + RadioErrorType {
227    /// Enable or disable the custom ACK (acknowledgement) payloads attached to auto-ack packets.
228    ///
229    /// By default this feature is disabled.
230    /// Using payloads in the auto-ack packets requires enabling dynamic payloads feature
231    /// This function will only ensure dynamic payloads are enabled on pipes 0 and 1.
232    /// Use [`EsbPayloadLength::set_dynamic_payloads()`] to enable dynamic payloads on all pipes.
233    ///
234    /// Use [`EsbFifo::available()`] to see if there any ACK payloads in the RX FIFO.
235    /// Use [`EsbRadio::read()`] to fetch the payloads from the RX FIFO.
236    ///
237    /// To append a payload to an auto ack packet, use [`EsbAutoAck::write_ack_payload()`].
238    fn set_ack_payloads(&mut self, enable: bool) -> Result<(), Self::Error>;
239
240    /// Get the current setting of the ACK payloads feature.
241    ///
242    /// Controlled with [`EsbAutoAck::set_ack_payloads()`].
243    fn get_ack_payloads(&self) -> bool;
244
245    /// Write a `buf` to the radio's TX FIFO for use with automatic ACK packets.
246    ///
247    /// The given `buf` will be the outgoing payload added to an automatic ACK packet
248    /// when acknowledging an incoming payload that was received with the specified
249    /// `pipe`. This function returns `true` if the payload was written to the TX FIFO.
250    /// It returns `false` under the following conditions:
251    ///
252    /// - the radio's TX FIFO is full.
253    /// - the specified `pipe` number is invalid (not in range [0, 5]).
254    /// - the ACK payload feature is not enabled (see [`EsbAutoAck::set_ack_payloads()`])
255    ///
256    /// It is important to discard any non-ACK payloads in the TX FIFO (using
257    /// [`EsbFifo::flush_tx()`]) before writing the first ACK payload into the TX FIFO.
258    /// This function can be used before and/or after calling [`EsbRadio::as_rx()`].
259    ///
260    /// <div class="warning">
261    ///
262    /// The payload must be loaded into the radio's TX FIFO _before_ the incoming
263    /// payload is received.
264    ///
265    /// Remember, the TX FIFO can only store a maximum of 3 payloads,
266    /// and there are typically more pipes than TX FIFO occupancy.
267    /// Expected behavior is better assured when the ACK payloads are only used
268    /// for 1 pipe.
269    ///
270    /// </div>
271    ///
272    /// Since ACK payloads require the dynamic payloads feature enabled, the given
273    /// `buf`'s length will determine the length of the payload in the ACK packet.
274    ///
275    /// See also [`EsbAutoAck::set_ack_payloads()`],
276    /// [`EsbPayloadLength::set_dynamic_payloads`], and [`EsbAutoAck::set_auto_ack()`].
277    fn write_ack_payload(&mut self, pipe: u8, buf: &[u8]) -> Result<bool, Self::Error>;
278
279    /// Enable or disable the auto-ack (automatic acknowledgement) feature for all
280    /// pipes.
281    ///
282    /// This feature is enabled by default. The auto-ack feature responds to every
283    /// received payload with an ACK packet. These ACK packets get sent
284    /// from the receiving radio back to the transmitting radio. To attach an
285    /// ACK payload to a ACK packet, use [`EsbAutoAck::write_ack_payload()`]`.
286    ///
287    /// If this feature is disabled on a transmitting radio, then the
288    /// transmitting radio will always report that the payload was received
289    /// (even if it was not). Please remember that this feature's configuration
290    /// needs to match for transmitting and receiving radios.
291    ///
292    /// When using the `ask_no_ack` parameter to [`EsbRadio::send()`] and [`EsbRadio::write()`],
293    /// this feature can be disabled for an individual payload. However, if this feature
294    /// is disabled, then the `ask_no_ack` parameter will have no effect.
295    ///
296    /// If disabling auto-acknowledgment packets, the ACK payloads
297    /// feature is also disabled as this feature is required to send ACK
298    /// payloads.
299    fn set_auto_ack(&mut self, enable: bool) -> Result<(), Self::Error>;
300
301    /// Set the auto-ack feature for an individual `pipe`.
302    ///
303    /// Pipe 0 is used for TX operations, which include sending ACK packets. If
304    /// using this feature on both TX & RX nodes, then pipe 0 must have this
305    /// feature enabled for the RX & TX operations. If this feature is disabled
306    /// on a transmitting radio's pipe 0, then the transmitting radio will
307    /// always report that the payload was received (even if it was not).
308    /// Remember to also enable this feature for any pipe that is openly
309    /// listening to a transmitting radio with this feature enabled.
310    ///
311    /// If this feature is enabled for pipe 0, then the `ask_no_ack` parameter to
312    /// [`EsbRadio::send()`] and [`EsbRadio::write()`] can be used to disable this feature for
313    /// an individual payload. However, if this feature is disabled for pipe 0,
314    /// then the `ask_no_ack` parameter will have no effect.
315    ///
316    /// If disabling auto-acknowledgment packets on pipe 0, the ACK
317    /// payloads feature is also disabled as this feature is required on pipe 0
318    /// to send ACK payloads.
319    fn set_auto_ack_pipe(&mut self, enable: bool, pipe: u8) -> Result<(), Self::Error>;
320
321    /// Set the number of retry attempts and delay between retry attempts when
322    /// transmitting a payload.
323    ///
324    /// When the auto-ack feature is enabled (via [`EsbAutoAck::set_auto_ack()`]),
325    /// the radio waits for an acknowledgement (ACK) packet during the `delay` between retry
326    /// attempts (`count`).
327    ///
328    /// Both parameters are clamped to range [0, 15].
329    /// - `delay`: How long to wait between each retry, in multiples of
330    ///   250 us (microseconds). The minimum value of 0 means 250 us, and
331    ///   the maximum value of 15 means 4000 us.
332    ///   The default value of 5 means 1500us (`5 * 250 + 250`).
333    /// - `count`: How many retries before giving up. The default/maximum is 15. Use
334    ///   0 to disable the auto-retry feature.
335    ///
336    /// Disabling the auto-retry feature on a transmitter still uses the
337    /// auto-ack feature (if enabled), except it will not retry to transmit if
338    /// the payload was not acknowledged on the first attempt.
339    fn set_auto_retries(&mut self, delay: u8, count: u8) -> Result<(), Self::Error>;
340
341    /// Allow the functionality of the `ask_no_ack` parameter in [`EsbRadio::send()`] and
342    /// [`EsbRadio::write()`].
343    ///
344    /// This only needs to called once before using the `ask_no_ack` parameter in
345    /// [`EsbRadio::send()`] and [`EsbRadio::write()`]. Enabling this feature will basically
346    /// allow disabling the auto-ack feature on a per-payload basis. Such behavior would be
347    /// desirable when transmitting to multiple radios that are setup to receive data from the
348    /// same address.
349    fn allow_ask_no_ack(&mut self, enable: bool) -> Result<(), Self::Error>;
350}
351
352/// A trait to represent manipulation of the power amplitude level
353/// for an ESB capable transceiver.
354pub trait EsbPaLevel: RadioErrorType {
355    /// Get the currently configured Power Amplitude Level (PA Level)
356    fn get_pa_level(&mut self) -> Result<PaLevel, Self::Error>;
357
358    /// Set the radio's Power Amplitude Level (PA Level)
359    fn set_pa_level(&mut self, pa_level: PaLevel) -> Result<(), Self::Error>;
360}
361
362/// A trait to represent manipulation of the state of power
363/// for an ESB capable transceiver.
364pub trait EsbPower: RadioErrorType {
365    /// Power down the radio.
366    ///
367    /// <div class="warning">
368    ///
369    /// The nRF24L01 cannot receive nor transmit data when powered down.
370    ///
371    /// </div>
372    fn power_down(&mut self) -> Result<(), Self::Error>;
373
374    /// Power up the radio.
375    ///
376    /// This wakes the radio from a sleep state, resulting in a
377    /// power standby mode that allows the radio to receive or transmit data.
378    ///
379    /// To ensure proper operation, this function will `delay` after the radio is powered up.
380    /// If the `delay` parameter is given a [`Some`] value, then the this function
381    /// will wait for the specified number of microseconds. If `delay` is a [`None`]
382    /// value, this function will wait for 5 milliseconds.
383    ///
384    /// To perform other tasks while the radio is powering up:
385    /// ```ignore
386    /// radio.power_up(Some(0)).unwrap();
387    /// // ... do something else for 5 milliseconds
388    /// radio.as_rx().unwrap();
389    /// ```
390    fn power_up(&mut self, delay: Option<u32>) -> Result<(), Self::Error>;
391
392    /// Get the current (cached) state of the radio's power.
393    ///
394    /// Returns `true` if powered up or `false` if powered down.
395    fn is_powered(&self) -> bool;
396}
397
398/// A trait to represent manipulation of Cyclical Redundancy Checksums
399/// for an ESB capable transceiver.
400pub trait EsbCrcLength: RadioErrorType {
401    /// Get the currently configured CRC (Cyclical Redundancy Checksum) length
402    fn get_crc_length(&mut self) -> Result<CrcLength, Self::Error>;
403
404    /// Set the radio's CRC (Cyclical Redundancy Checksum) length
405    fn set_crc_length(&mut self, crc_length: CrcLength) -> Result<(), Self::Error>;
406}
407
408/// A trait to represent manipulation of the Data Rate
409/// for an ESB capable transceiver.
410pub trait EsbDataRate: RadioErrorType {
411    /// Get the currently configured Data Rate
412    fn get_data_rate(&mut self) -> Result<DataRate, Self::Error>;
413
414    /// Set the radio's Data Rate
415    fn set_data_rate(&mut self, data_rate: DataRate) -> Result<(), Self::Error>;
416}
417
418/// A trait to represent debug output
419/// for an ESB capable transceiver.
420pub trait EsbDetails: RadioErrorType {
421    /// Print details about radio's current configuration.
422    ///
423    /// This should only be used for debugging development.
424    /// Using this in production should be limited due to a significant increase in
425    /// compile size.
426    fn print_details(&mut self) -> Result<(), Self::Error>;
427}
428
429pub trait EsbInit: RadioErrorType {
430    /// Initialize the radio's hardware.
431    ///
432    /// This is similar to [`EsbInit::with_config()`] (with [`RadioConfig::default()`]),
433    /// but this function also
434    ///
435    /// - waits 5 milliseconds for radio to finish powering up
436    /// - tests if radio module is compatible with generic nRF24L01+ variant
437    /// - checks if radio has responding correctly after configuration
438    ///
439    /// This function should only be called once after instantiating the radio object.
440    /// Afterward, it is quicker to use [`EsbInit::with_config()`] to reconfigure the
441    /// radio for different network requirements.
442    fn init(&mut self) -> Result<(), Self::Error>;
443
444    /// Reconfigure the radio using the given `config` object.
445    ///
446    /// See [`RadioConfig`] for more detail.
447    /// This function is a convenience where calling multiple configuration functions may
448    /// be cumbersome.
449    fn with_config(&mut self, config: &RadioConfig) -> Result<(), Self::Error>;
450}
451
452/// A trait to represent manipulation of an ESB capable transceiver.
453///
454/// Although the name is rather generic, this trait describes the
455/// behavior of a radio's rudimentary modes (RX and TX).
456pub trait EsbRadio: RadioErrorType {
457    /// Put the radio into active RX mode.
458    ///
459    /// Conventionally, this should be called after setting the RX addresses via
460    /// [`EsbPipe::open_rx_pipe()`]
461    ///
462    /// This function will restore the cached RX address set to pipe 0.
463    /// This is done because the [`EsbRadio::as_tx()`] will appropriate the
464    /// RX address on pipe 0 for auto-ack purposes.
465    fn as_rx(&mut self) -> Result<(), Self::Error>;
466
467    /// Put the radio into inactive TX mode.
468    ///
469    /// This must be called at least once before calling [`EsbRadio::send()`] or
470    /// [`EsbRadio::write()`].
471    ///
472    /// If the `tx_address` parameter is given [`Some`] value, then that will be
473    /// cached and set as the new TX address.
474    ///
475    /// For auto-ack purposes, this function will also restore
476    /// the cached `tx_address` to the RX pipe 0.
477    ///
478    /// This function will also flush the TX FIFO when ACK payloads are enabled
479    /// (via [`EsbAutoAck::set_ack_payloads()`]).
480    fn as_tx(&mut self, tx_address: Option<&[u8]>) -> Result<(), Self::Error>;
481
482    /// Is the radio in RX mode?
483    fn is_rx(&self) -> bool;
484
485    /// Blocking function to transmit a given payload.
486    ///
487    /// This transmits a payload (given by `buf`) and returns a bool describing if
488    /// the transmission was successful or not.
489    ///
490    /// See [`EsbRadio::write()`] for description of `ask_no_ack` parameter and more
491    /// detail about how the radio processes data in the TX FIFO.
492    fn send(&mut self, buf: &[u8], ask_no_ack: bool) -> Result<bool, Self::Error>;
493
494    /// Non-blocking function to prepare radio for transmitting payload(s).
495    ///
496    /// This is a helper function to [`EsbRadio::send()`].
497    ///
498    /// Unlike [`EsbRadio::send()`], this function does not wait for the radio to complete
499    /// the transmission. Instead it simply writes the given `buf` into the radio's TX FIFO.
500    /// If the TX FIFO is already full, this function just calls
501    /// [`EsbStatus::clear_status_flags()`] (only for `tx_df` and `tx_ds` flags) and returns
502    /// `false`.
503    ///
504    /// If `ask_no_ack` is true, then the transmitted payload will not use the auto-ack
505    /// feature. This parameter is different from [`EsbAutoAck::set_auto_ack()`] because it
506    /// controls the auto-ack feature for only the given payload (`buf`), whereas
507    /// [`EsbAutoAck::set_auto_ack()`] controls ACK packets for _all_ payloads.
508    /// If [`EsbAutoAck::allow_ask_no_ack()`] is not passed `true` at least once before passing
509    /// `true` to this parameter, then this parameter has no effect.
510    ///
511    /// This function's `start_tx` parameter determines if the radio should enter active
512    /// TX mode. This function does not exit active TX mode.
513    ///
514    /// The radio remains in active TX mode while there are payloads available in the TX FIFO.
515    /// Set the `start_tx` parameter `false` to prevent entering active TX mode. If the radio
516    /// is already in active TX mode (because it is processing payloads in the TX FIFO), then
517    /// this parameter has no effect.
518    fn write(&mut self, buf: &[u8], ask_no_ack: bool, start_tx: bool) -> Result<bool, Self::Error>;
519
520    /// Similar to [`EsbRadio::send()`] but specifically for failed transmissions.
521    ///
522    /// Remember, any failed transmission's payload will remain in the TX FIFO.
523    ///
524    /// This will reuse the payload in the top level of the radio's TX FIFO.
525    /// If successfully transmitted, this returns `true`, otherwise it returns `false`.
526    ///
527    /// Unlike [`EsbRadio::rewrite()`], this function will only make one attempt to
528    /// resend the failed payload.
529    fn resend(&mut self) -> Result<bool, Self::Error>;
530
531    /// Similar to [`EsbRadio::write()`] but specifically for failed transmissions.
532    ///
533    /// Remember, any failed transmission's payload will remain in the TX FIFO.
534    ///
535    /// This is a non-blocking helper to [`EsbRadio::resend()`].
536    /// This will put the radio in an active TX mode and reuse the payload in the top level
537    /// of the radio's TX FIFO.
538    ///
539    /// The reused payload will be continuously retransmitted until one of the following
540    /// conditions occurs:
541    ///
542    /// - The retransmission fails.
543    /// - A new payload is written to the radio's TX FIFO (via [`EsbRadio::write()`] or
544    ///   [`EsbRadio::send()`])
545    /// - The radio's TX FIFO is flushed (via [`EsbFifo::flush_tx()`]).
546    /// - The radio's CE pin is set to inactive LOW. This can be done directly on the pin or by calling
547    ///   [`EsbRadio::as_tx()`].
548    fn rewrite(&mut self) -> Result<(), Self::Error>;
549
550    /// Get the Auto-Retry Count (ARC) about the previous transmission.
551    ///
552    /// This data is reset for every payload attempted to transmit.
553    /// It cannot exceed 15 per the `count` parameter in [`EsbAutoAck::set_auto_retries()`].
554    /// If auto-ack feature is disabled, then this function provides no useful data.
555    fn get_last_arc(&mut self) -> Result<u8, Self::Error>;
556
557    /// Read data from the radio's RX FIFO into the specified `buf`.
558    ///
559    /// All payloads received by the radio are stored in the RX FIFO (a 3 layer stack).
560    /// Use [`EsbFifo::available()`] to determine if there is data ready to read.
561    ///
562    /// The `len` parameter determines how much data is stored to `buf`. Ultimately,
563    /// the value of `len` is restricted by the radio's maximum 32 byte limit and the
564    /// length of the given `buf`. Pass [`None`] to automatically use static payload length
565    /// (set by [`EsbPayloadLength::set_payload_length()`]) or the dynamic payload length
566    /// (fetched internally using [`EsbPayloadLength::get_dynamic_payload_length()`]) if
567    /// dynamic payload lengths are enable (see [`EsbPayloadLength::set_dynamic_payloads()`]).
568    fn read(&mut self, buf: &mut [u8], len: Option<u8>) -> Result<u8, Self::Error>;
569}