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}