Skip to content

Commit

Permalink
another refactor
Browse files Browse the repository at this point in the history
considering we might be distributing multiple rust crates from 1 repo.

also review rust docs
- added API layout to landing page
- filled in some missing info in functions' docs

review `print_details()` output
- show pipe information in `print_details()`
- show TX address in `print_details()`
- fix IRQ settings' output
  • Loading branch information
2bndy5 committed Oct 29, 2024
1 parent 9fc47fc commit fc29509
Show file tree
Hide file tree
Showing 29 changed files with 265 additions and 74 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[workspace]
members = ["library", "examples/rust", "bindings/python", "bindings/node"]
default-members = ["library"]
members = ["crates/rf24-rs", "examples/rust", "bindings/python", "bindings/node"]
default-members = ["crates/rf24-rs"]
resolver = "2"

[workspace.package]
Expand Down
9 changes: 6 additions & 3 deletions bindings/node/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
[package]
edition = "2021"
name = "rf24_node"
version = "0.0.0"
version.workspace = true
repository.workspace = true
edition.workspace = true
rust-version.workspace = true
license-file.workspace = true

[lib]
crate-type = ["cdylib"]
Expand All @@ -16,4 +19,4 @@ napi-build = "2.0.1"

[target.'cfg(target_os = "linux")'.dependencies]
linux-embedded-hal = "0.4.0"
rf24-rs = { path = "../../library", features = ["std"] }
rf24-rs = { path = "../../crates/rf24-rs", features = ["std"] }
2 changes: 1 addition & 1 deletion bindings/python/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ pyo3 = {version = "0.22.5", features = ["extension-module"]}

[target.'cfg(target_os = "linux")'.dependencies]
linux-embedded-hal = "0.4.0"
rf24-rs = { path = "../../library", features = ["std"]}
rf24-rs = { path = "../../crates/rf24-rs", features = ["std"]}
4 changes: 4 additions & 0 deletions crates/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# crates folder

This folder contains the rust sources that will be published to crates-io
and used as local dependencies in the [../bindings/\*](../bindings/).
File renamed without changes.
File renamed without changes.
67 changes: 67 additions & 0 deletions crates/rf24-rs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# rf24-rs

This is a rust driver library for the nRF24L01 wireless transceivers.

See the examples in the repository's [examples/rust](https://github.com/nRF24/rf24-rs/blob/main/examples/rust) folder.

[rf24-struct]: struct@crate::radio::RF24

## Basic API

- [`RF24::new()`](fn@crate::radio::RF24::new)
- [`RF24`][rf24-struct]`::`[`init()`](fn@crate::radio::prelude::EsbRadio::init)
- [`RF24`][rf24-struct]`::`[`is_rx()`](fn@crate::radio::prelude::EsbRadio::is_rx)
- [`RF24`][rf24-struct]`::`[`as_rx()`](fn@crate::radio::prelude::EsbRadio::as_rx)
- [`RF24`][rf24-struct]`::`[`as_tx()`](fn@crate::radio::prelude::EsbRadio::as_tx)
- [`RF24`][rf24-struct]`::`[`open_tx_pipe()`](fn@crate::radio::prelude::EsbPipe::open_tx_pipe)
- [`RF24`][rf24-struct]`::`[`open_rx_pipe()`](fn@crate::radio::prelude::EsbPipe::open_rx_pipe)
- [`RF24`][rf24-struct]`::`[`close_rx_pipe()`](fn@crate::radio::prelude::EsbPipe::close_rx_pipe)
- [`RF24`][rf24-struct]`::`[`available()`](fn@crate::radio::prelude::EsbFifo::available)
- [`RF24`][rf24-struct]`::`[`available_pipe()`](fn@crate::radio::prelude::EsbFifo::available_pipe)
- [`RF24`][rf24-struct]`::`[`read()`](fn@crate::radio::prelude::EsbRadio::read)
- [`RF24`][rf24-struct]`::`[`send()`](fn@crate::radio::prelude::EsbRadio::send)
- [`RF24`][rf24-struct]`::`[`resend()`](fn@crate::radio::prelude::EsbRadio::resend)
- [`RF24`][rf24-struct]`::`[`set_channel()`](fn@crate::radio::prelude::EsbChannel::set_channel)
- [`RF24`][rf24-struct]`::`[`get_channel()`](fn@crate::radio::prelude::EsbChannel::get_channel)

## Advanced API

- [`RF24`][rf24-struct]`::`[`write_ack_payload()`](fn@crate::radio::prelude::EsbAutoAck::write_ack_payload)
- [`RF24`][rf24-struct]`::`[`write()`](fn@crate::radio::prelude::EsbRadio::write)
- [`RF24`][rf24-struct]`::`[`rewrite()`](fn@crate::radio::prelude::EsbRadio::rewrite)
- [`RF24`][rf24-struct]`::`[`get_fifo_state()`](fn@crate::radio::prelude::EsbFifo::get_fifo_state)
- [`RF24`][rf24-struct]`::`[`clear_status_flags()`](fn@crate::radio::prelude::EsbStatus::clear_status_flags)
- [`RF24`][rf24-struct]`::`[`update()`](fn@crate::radio::prelude::EsbStatus::update)
- [`RF24`][rf24-struct]`::`[`get_status_flags()`](fn@crate::radio::prelude::EsbStatus::get_status_flags)
- [`RF24`][rf24-struct]`::`[`flush_rx()`](fn@crate::radio::prelude::EsbFifo::flush_rx)
- [`RF24`][rf24-struct]`::`[`flush_tx()`](fn@crate::radio::prelude::EsbFifo::flush_tx)
- [`RF24::start_carrier_wave()`](fn@crate::radio::RF24::start_carrier_wave)
- [`RF24::stop_carrier_wave()`](fn@crate::radio::RF24::stop_carrier_wave)
- [`RF24::test_rpd()`](fn@crate::radio::RF24::test_rpd)
- [`RF24`][rf24-struct]`::`[`get_last_arc()`](fn@crate::radio::prelude::EsbRadio::get_last_arc)
- [`RF24`][rf24-struct]`::`[`get_dynamic_payload_length()`](fn@crate::radio::prelude::EsbPayloadLength::get_dynamic_payload_length)

## Configuration API

- [`RF24`][rf24-struct]`::`[`set_status_flags()`](fn@crate::radio::prelude::EsbStatus::set_status_flags)
- [`RF24`][rf24-struct]`::`[`set_auto_ack()`](fn@crate::radio::prelude::EsbAutoAck::set_auto_ack)
- [`RF24`][rf24-struct]`::`[`set_auto_ack_pipe()`](fn@crate::radio::prelude::EsbAutoAck::set_auto_ack_pipe)
- [`RF24`][rf24-struct]`::`[`set_auto_retries()`](fn@crate::radio::prelude::EsbAutoAck::set_auto_retries)
- [`RF24`][rf24-struct]`::`[`set_dynamic_payloads()`](fn@crate::radio::prelude::EsbPayloadLength::set_dynamic_payloads)
- [`RF24`][rf24-struct]`::`[`allow_ask_no_ack()`](fn@crate::radio::prelude::EsbAutoAck::allow_ask_no_ack)
- [`RF24`][rf24-struct]`::`[`allow_ack_payloads()`](fn@crate::radio::prelude::EsbAutoAck::allow_ack_payloads)
- [`RF24`][rf24-struct]`::`[`set_address_length()`](fn@crate::radio::prelude::EsbPipe::set_address_length)
- [`RF24`][rf24-struct]`::`[`get_address_length()`](fn@crate::radio::prelude::EsbPipe::get_address_length)
- [`RF24`][rf24-struct]`::`[`set_payload_length()`](fn@crate::radio::prelude::EsbPayloadLength::set_payload_length)
- [`RF24`][rf24-struct]`::`[`get_payload_length()`](fn@crate::radio::prelude::EsbPayloadLength::get_payload_length)
- [`RF24`][rf24-struct]`::`[`set_data_rate()`](fn@crate::radio::prelude::EsbDataRate::set_data_rate)
- [`RF24`][rf24-struct]`::`[`get_data_rate()`](fn@crate::radio::prelude::EsbDataRate::get_data_rate)
- [`RF24`][rf24-struct]`::`[`set_pa_level()`](fn@crate::radio::prelude::EsbPaLevel::set_pa_level)
- [`RF24`][rf24-struct]`::`[`get_pa_level()`](fn@crate::radio::prelude::EsbPaLevel::get_pa_level)
- [`RF24::set_lna()`](fn@crate::radio::RF24::set_lna)
- [`RF24`][rf24-struct]`::`[`set_crc_length()`](fn@crate::radio::prelude::EsbCrcLength::set_crc_length)
- [`RF24`][rf24-struct]`::`[`get_crc_length()`](fn@crate::radio::prelude::EsbCrcLength::get_crc_length)
- [`RF24`][rf24-struct]`::`[`is_powered()`](fn@crate::radio::prelude::EsbPower::is_powered)
- [`RF24`][rf24-struct]`::`[`power_up()`](fn@crate::radio::prelude::EsbPower::power_up)
- [`RF24`][rf24-struct]`::`[`power_down()`](fn@crate::radio::prelude::EsbPower::power_down)
- [`RF24::is_plus_variant()`](fn@crate::radio::RF24::is_plus_variant)
File renamed without changes.
117 changes: 83 additions & 34 deletions library/src/radio/mod.rs → crates/rf24-rs/src/radio/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub mod prelude {
pub trait EsbPipe {
type PipeErrorType;

/// Open a specified `pipe` for receiving data when radio is in RX role.
/// Open a specified `pipe` for receiving data when radio is in RX mode.
///
/// If the specified `pipe` is not in range [0, 5], then this function does nothing.
///
Expand Down Expand Up @@ -58,14 +58,17 @@ pub mod prelude {
/// to understand how to avoid using malformed addresses.
fn open_rx_pipe(&mut self, pipe: u8, address: &[u8]) -> Result<(), Self::PipeErrorType>;

/// Set an address to pipe 0 for transmitting when radio is in TX role.
/// Set an address to pipe 0 for transmitting when radio is in TX mode.
///
fn open_tx_pipe(&mut self, address: &[u8]) -> Result<(), Self::PipeErrorType>;

/// Close a specified pipe from receiving data when radio is in RX role.
/// Close a specified pipe from receiving data when radio is in RX mode.
fn close_rx_pipe(&mut self, pipe: u8) -> Result<(), Self::PipeErrorType>;

/// Set the address length (applies to all pipes).
///
/// If the specified length is clamped to the range [2, 5].
/// Any value outside that range defaults to 5.
fn set_address_length(&mut self, length: u8) -> Result<(), Self::PipeErrorType>;

/// Get the currently configured address length (applied to all pipes).
Expand Down Expand Up @@ -208,7 +211,7 @@ pub mod prelude {
///
/// ```ignore
/// radio.set_dynamic_payloads(true).unwrap();
/// // ... then after or during RX role:
/// // ... then after or during RX mode:
/// if radio.available().unwrap() {
/// let length = radio.get_dynamic_payload_length().unwrap();
/// let mut payload = [0; 32];
Expand All @@ -226,7 +229,8 @@ pub mod prelude {

/// Get the dynamic length of the next available payload in the RX FIFO.
///
/// This returns `0` when dynamic payloads are disabled.
/// This returns `0` when dynamic payloads are disabled (via
/// [`EsbPayloadLength::set_dynamic_payloads()`]).
fn get_dynamic_payload_length(&mut self) -> Result<u8, Self::PayloadLengthErrorType>;
}

Expand Down Expand Up @@ -261,17 +265,17 @@ pub mod prelude {
///
/// It is important to discard any non-ACK payloads in the TX FIFO (using
/// [`EsbFifo::flush_tx()`]) before writing the first ACK payload into the TX FIFO.
/// This function can be used before and after calling [`EsbRadio::as_rx()`].
/// This function can be used before and/or after calling [`EsbRadio::as_rx()`].
///
/// <div class="warning">
///
/// The payload must be loaded into the radio's TX FIFO _before_ the incoming
/// payload is received.
///
/// Remember, the TX FIFO stack can store only 3 payloads,
/// Remember, the TX FIFO can only store a maximum of 3 payloads,
/// and there are typically more pipes than TX FIFO occupancy.
/// Expected behavior is better assured when the ACK payloads are only used
/// for 1 pipe
/// for 1 pipe.
///
/// </div>
///
Expand Down Expand Up @@ -335,14 +339,17 @@ pub mod prelude {
/// Set the number of retry attempts and delay between retry attempts when
/// transmitting a payload.
///
/// The radio is waiting for an acknowledgement (ACK) packet during the delay between retry attempts.
/// When the auto-ack feature is enabled (via [`EsbAutoAck::set_auto_ack()`]),
/// the radio waits for an acknowledgement (ACK) packet during the `delay` between retry
/// attempts (`count`).
///
/// Both parameters are clamped to range [0, 15].
/// - `delay`: How long to wait between each retry, in multiples of
/// 250 us. The minimum of 0 means 250 us, and the maximum of 15 means
/// 4000 us. The default value of 5 means 1500us (5 * 250 + 250).
/// 250 us (microseconds). The minimum value of 0 means 250 us, and
/// the maximum valueof 15 means 4000 us.
/// The default value of 5 means 1500us (`5 * 250 + 250`).
/// - `count`: How many retries before giving up. The default/maximum is 15. Use
/// 0 to disable the auto-retry feature all together.
/// 0 to disable the auto-retry feature.
///
/// Disabling the auto-retry feature on a transmitter still uses the
/// auto-ack feature (if enabled), except it will not retry to transmit if
Expand All @@ -354,7 +361,9 @@ pub mod prelude {
///
/// This only needs to called once before using the `ask_no_ack` parameter in
/// [`EsbRadio::send()`] and [`EsbRadio::write()`]. Enabling this feature will basically
/// allow disabling the auto-ack feature on a per-payload basis.
/// allow disabling the auto-ack feature on a per-payload basis. Such behavior would be
/// desirable when transmitting to multiple radios that are setup to receive data from the
/// same address.
fn allow_ask_no_ack(&mut self, enable: bool) -> Result<(), Self::AutoAckErrorType>;
}

Expand Down Expand Up @@ -394,7 +403,7 @@ pub mod prelude {
/// will wait for the specified number of microseconds. If `delay` is a [`None`]
/// value, this function will wait for 5 milliseconds.
///
/// To perform other tasks will the radio is powering up:
/// To perform other tasks while the radio is powering up:
/// ```ignore
/// radio.power_up(Some(0)).unwrap();
/// // ... do something else for 5 milliseconds
Expand Down Expand Up @@ -436,35 +445,44 @@ pub mod prelude {
/// A trait to represent debug output
/// for an ESB capable transceiver.
pub trait EsbDetails {
type LoggingErrorType;
type DetailsErrorType;

/// print details about radio's current configuration.
/// Print details about radio's current configuration.
///
/// This should only be used for debugging development.
/// Using in production should be limited due to increase in compile size.
fn print_details(&mut self) -> Result<(), Self::LoggingErrorType>;
/// Using this in production should be limited due to a significant increase in
/// compile size.
fn print_details(&mut self) -> Result<(), Self::DetailsErrorType>;
}

/// A trait to represent manipulation of an ESB capable transceiver.
///
/// Although the name is rather generic, this trait describes the
/// behavior of a radio's rudimentary roles (RX and TX).
/// behavior of a radio's rudimentary modes (RX and TX).
pub trait EsbRadio {
type RadioErrorType;

/// Initialize the radio's hardware
fn init(&mut self) -> Result<(), Self::RadioErrorType>;

/// Put the radio into RX role
/// Put the radio into active RX mode.
///
/// Conventionally, this should be called after setting the RX addresses via
/// [`EsbPipe::open_rx_pipe()`]
fn as_rx(&mut self) -> Result<(), Self::RadioErrorType>;

/// Put the radio into TX role
/// Put the radio into inactive TX mode.
///
/// This must be called at least once before calling [`EsbRadio::send()`] or
/// [`EsbRadio::write()`].
/// Conventionally, this should be called after setting the TX address via
/// [`EsbPipe::open_tx_pipe()`].
fn as_tx(&mut self) -> Result<(), Self::RadioErrorType>;

/// Is the radio in RX mode?
fn is_rx(&self) -> bool;

/// Blocking write.
/// Blocking function to transmit a given payload.
///
/// This transmits a payload (given by `buf`) and returns a bool describing if
/// the transmission was successful or not.
Expand All @@ -473,34 +491,65 @@ pub mod prelude {
/// detail about how the radio processes data in the TX FIFO.
fn send(&mut self, buf: &[u8], ask_no_ack: bool) -> Result<bool, Self::RadioErrorType>;

/// Non-blocking write.
/// Non-blocking function to prepare radio for transmitting payload(s).
///
/// This is a helper function to [`EsbRadio::send()`].
///
/// This function does not wait for the radio to complete the transmission.
/// Instead it simply writes the given `buf` into the radio's TX FIFO.
/// Unlike [`EsbRadio::send()`], this function does not wait for the radio to complete
/// the transmission. Instead it simply writes the given `buf` into the radio's TX FIFO.
/// If the TX FIFO is already full, this function just calls
/// [`EsbStatus::clear_status_flags()`] and returns `false`.
/// [`EsbStatus::clear_status_flags()`] (only for `tx_df` and `tx_ds` flags) and returns
/// `false`.
///
/// If `ask_no_ack` is true, then the transmitted payload will not use the auto-ack
/// feature. This parameter is different from auto-ack because it controls the
/// auto-ack feature for only this payload, whereas the auto-ack feature controls
/// ACK packets for all payloads. If [`EsbAutoAck::allow_ask_no_ack()`] is not called
/// at least once prior to asserting this parameter, then it has no effect.
/// feature. This parameter is different from [`EsbAutoAck::set_auto_ack()`] because it
/// controls the auto-ack feature for only the given payload (`buf`), whereas
/// [`EsbAutoAck::set_auto_ack()`] controls ACK packets for _all_ payloads.
/// If [`EsbAutoAck::allow_ask_no_ack()`] is not passed `true` at least once before passing
/// `true` to this parameter, then this parameter has no effect.
///
/// This function's `start_tx` parameter determines if the radio should enter active
/// TX mode. This function does not deactivate TX mode.
/// TX mode. This function does not exit active TX mode.
///
/// If the radio's remains in TX mode after successfully transmitting a payload,
/// then any subsequent payloads in the TX FIFO will automatically be processed.
/// Set the `start_tx` parameter `false` to prevent entering TX mode.
/// The radio remains in active TX mode while there are payloads available in the TX FIFO.
/// Set the `start_tx` parameter `false` to prevent entering active TX mode. If the radio
/// is already in active TX mode (because it is processing payloads in the TX FIFO), then
/// this parameter has no effect.
fn write(
&mut self,
buf: &[u8],
ask_no_ack: bool,
start_tx: bool,
) -> Result<bool, Self::RadioErrorType>;

/// Similar to [`EsbRadio::send()`] but specifically for failed transmissions.
///
/// Remember, any failed transmission's payload will remain in the TX FIFO.
///
/// This will reuse the payload in the top level of the radio's TX FIFO.
/// If successfully transmitted, this returns `true`, otherwise it returns `false`.
///
/// Unlike [`EsbRadio::rewrite()`], this function will only make one attempt to
/// resend the failed payload.
fn resend(&mut self) -> Result<bool, Self::RadioErrorType>;

/// Similar to [`EsbRadio::write()`] but specifically for failed transmissions.
///
/// Remember, any failed transmission's payload will remain in the TX FIFO.
///
/// This is a non-blocking helper to [`EsbRadio::resend()`].
/// This will put the radio in an active TX mode and reuse the payload in the top level
/// of the radio's TX FIFO.
///
/// The reused payload will be continuously retransmitted until one of the following
/// conditions occurs:
///
/// - The retransmission fails.
/// - A new payload is written to the radio's TX FIFO (via [`EsbRadio::write()`] or
/// [`EsbRadio::send()`])
/// - The radio's TX FIFO is flushed (via [`EsbFifo::flush_tx()`]).
/// - The radio's CE pin is set to inactive LOW. This can be done directly on the pin or by calling
/// [`EsbRadio::as_tx()`].
fn rewrite(&mut self) -> Result<(), Self::RadioErrorType>;

/// Get the Auto-Retry Count (ARC) about the previous transmission.
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit fc29509

Please sign in to comment.