From fc29509803687841a41d6d5130697c8a4af7ab6e Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Tue, 29 Oct 2024 00:39:59 -0700 Subject: [PATCH] another refactor 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 --- Cargo.toml | 4 +- bindings/node/Cargo.toml | 9 +- bindings/python/Cargo.toml | 2 +- crates/README.md | 4 + .../rf24-rs}/.cargo/config.toml | 0 {library => crates/rf24-rs}/Cargo.toml | 0 crates/rf24-rs/README.md | 67 ++++++++++ {library => crates/rf24-rs}/src/lib.rs | 0 {library => crates/rf24-rs}/src/radio/mod.rs | 117 +++++++++++++----- .../rf24-rs}/src/radio/rf24/auto_ack.rs | 0 .../rf24-rs}/src/radio/rf24/channel.rs | 0 .../rf24-rs}/src/radio/rf24/constants.rs | 0 .../rf24-rs}/src/radio/rf24/crc_length.rs | 0 .../rf24-rs}/src/radio/rf24/data_rate.rs | 0 .../rf24-rs}/src/radio/rf24/details.rs | 105 ++++++++++++---- .../rf24-rs}/src/radio/rf24/fifo.rs | 0 .../rf24-rs}/src/radio/rf24/mod.rs | 5 + .../rf24-rs}/src/radio/rf24/pa_level.rs | 0 .../rf24-rs}/src/radio/rf24/payload_length.rs | 0 .../rf24-rs}/src/radio/rf24/pipe.rs | 0 .../rf24-rs}/src/radio/rf24/power.rs | 0 .../rf24-rs}/src/radio/rf24/radio.rs | 9 +- .../rf24-rs}/src/radio/rf24/status.rs | 0 {library => crates/rf24-rs}/src/types.rs | 0 cspell.config.yml | 1 + docs/src/index.md | 2 +- examples/rust/Cargo.toml | 3 +- justfile | 8 +- library/README.md | 3 - 29 files changed, 265 insertions(+), 74 deletions(-) create mode 100644 crates/README.md rename {library => crates/rf24-rs}/.cargo/config.toml (100%) rename {library => crates/rf24-rs}/Cargo.toml (100%) create mode 100644 crates/rf24-rs/README.md rename {library => crates/rf24-rs}/src/lib.rs (100%) rename {library => crates/rf24-rs}/src/radio/mod.rs (82%) rename {library => crates/rf24-rs}/src/radio/rf24/auto_ack.rs (100%) rename {library => crates/rf24-rs}/src/radio/rf24/channel.rs (100%) rename {library => crates/rf24-rs}/src/radio/rf24/constants.rs (100%) rename {library => crates/rf24-rs}/src/radio/rf24/crc_length.rs (100%) rename {library => crates/rf24-rs}/src/radio/rf24/data_rate.rs (100%) rename {library => crates/rf24-rs}/src/radio/rf24/details.rs (69%) rename {library => crates/rf24-rs}/src/radio/rf24/fifo.rs (100%) rename {library => crates/rf24-rs}/src/radio/rf24/mod.rs (98%) rename {library => crates/rf24-rs}/src/radio/rf24/pa_level.rs (100%) rename {library => crates/rf24-rs}/src/radio/rf24/payload_length.rs (100%) rename {library => crates/rf24-rs}/src/radio/rf24/pipe.rs (100%) rename {library => crates/rf24-rs}/src/radio/rf24/power.rs (100%) rename {library => crates/rf24-rs}/src/radio/rf24/radio.rs (99%) rename {library => crates/rf24-rs}/src/radio/rf24/status.rs (100%) rename {library => crates/rf24-rs}/src/types.rs (100%) delete mode 100644 library/README.md diff --git a/Cargo.toml b/Cargo.toml index c3e3486..95b7091 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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] diff --git a/bindings/node/Cargo.toml b/bindings/node/Cargo.toml index 7aa6b47..9dc73ba 100644 --- a/bindings/node/Cargo.toml +++ b/bindings/node/Cargo.toml @@ -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"] @@ -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"] } diff --git a/bindings/python/Cargo.toml b/bindings/python/Cargo.toml index 7f10d90..63d814e 100644 --- a/bindings/python/Cargo.toml +++ b/bindings/python/Cargo.toml @@ -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"]} diff --git a/crates/README.md b/crates/README.md new file mode 100644 index 0000000..2763825 --- /dev/null +++ b/crates/README.md @@ -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/). diff --git a/library/.cargo/config.toml b/crates/rf24-rs/.cargo/config.toml similarity index 100% rename from library/.cargo/config.toml rename to crates/rf24-rs/.cargo/config.toml diff --git a/library/Cargo.toml b/crates/rf24-rs/Cargo.toml similarity index 100% rename from library/Cargo.toml rename to crates/rf24-rs/Cargo.toml diff --git a/crates/rf24-rs/README.md b/crates/rf24-rs/README.md new file mode 100644 index 0000000..12c42a3 --- /dev/null +++ b/crates/rf24-rs/README.md @@ -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) diff --git a/library/src/lib.rs b/crates/rf24-rs/src/lib.rs similarity index 100% rename from library/src/lib.rs rename to crates/rf24-rs/src/lib.rs diff --git a/library/src/radio/mod.rs b/crates/rf24-rs/src/radio/mod.rs similarity index 82% rename from library/src/radio/mod.rs rename to crates/rf24-rs/src/radio/mod.rs index 6827530..214a907 100644 --- a/library/src/radio/mod.rs +++ b/crates/rf24-rs/src/radio/mod.rs @@ -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. /// @@ -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). @@ -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]; @@ -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; } @@ -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()`]. /// ///
/// /// 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. /// ///
/// @@ -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 @@ -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>; } @@ -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 @@ -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. @@ -473,25 +491,30 @@ 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; - /// 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], @@ -499,8 +522,34 @@ pub mod prelude { start_tx: bool, ) -> Result; + /// 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; + /// 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. diff --git a/library/src/radio/rf24/auto_ack.rs b/crates/rf24-rs/src/radio/rf24/auto_ack.rs similarity index 100% rename from library/src/radio/rf24/auto_ack.rs rename to crates/rf24-rs/src/radio/rf24/auto_ack.rs diff --git a/library/src/radio/rf24/channel.rs b/crates/rf24-rs/src/radio/rf24/channel.rs similarity index 100% rename from library/src/radio/rf24/channel.rs rename to crates/rf24-rs/src/radio/rf24/channel.rs diff --git a/library/src/radio/rf24/constants.rs b/crates/rf24-rs/src/radio/rf24/constants.rs similarity index 100% rename from library/src/radio/rf24/constants.rs rename to crates/rf24-rs/src/radio/rf24/constants.rs diff --git a/library/src/radio/rf24/crc_length.rs b/crates/rf24-rs/src/radio/rf24/crc_length.rs similarity index 100% rename from library/src/radio/rf24/crc_length.rs rename to crates/rf24-rs/src/radio/rf24/crc_length.rs diff --git a/library/src/radio/rf24/data_rate.rs b/crates/rf24-rs/src/radio/rf24/data_rate.rs similarity index 100% rename from library/src/radio/rf24/data_rate.rs rename to crates/rf24-rs/src/radio/rf24/data_rate.rs diff --git a/library/src/radio/rf24/details.rs b/crates/rf24-rs/src/radio/rf24/details.rs similarity index 69% rename from library/src/radio/rf24/details.rs rename to crates/rf24-rs/src/radio/rf24/details.rs index 36ae080..4e3dfe1 100644 --- a/library/src/radio/rf24/details.rs +++ b/crates/rf24-rs/src/radio/rf24/details.rs @@ -22,11 +22,11 @@ where DO: OutputPin, DELAY: DelayNs, { - type LoggingErrorType = Nrf24Error; + type DetailsErrorType = Nrf24Error; #[cfg(feature = "defmt")] #[cfg(target_os = "none")] - fn print_details(&mut self) -> Result<(), Self::LoggingErrorType> { + fn print_details(&mut self) -> Result<(), Self::DetailsErrorType> { defmt::println!("Is a plus variant_________{=bool}", self.is_plus_variant()); let channel = self.get_channel()?; @@ -89,19 +89,19 @@ where self.get_status_flags(&mut flags); defmt::println!( "IRQ on Data Ready_________{=bool}", - self._config_reg & mnemonics::MASK_RX_DR > 0 + (self._config_reg & mnemonics::MASK_RX_DR) == 0 ); defmt::println!(" Data Ready triggered__{=bool}", flags.rx_dr); - defmt::println!( - "IRQ on Data Fail__________{=bool}", - self._config_reg & mnemonics::MASK_MAX_RT > 0 - ); - defmt::println!(" Data Failed triggered_{=bool}", flags.tx_df); defmt::println!( "IRQ on Data Sent__________{=bool}", - self._config_reg & mnemonics::MASK_TX_DS > 0 + (self._config_reg & mnemonics::MASK_TX_DS) == 0 ); defmt::println!(" Data Sent triggered___{=bool}", flags.tx_ds); + defmt::println!( + "IRQ on Data Fail__________{=bool}", + (self._config_reg & mnemonics::MASK_MAX_RT) == 0 + ); + defmt::println!(" Data Fail triggered___{=bool}", flags.tx_df); let fifo = self.get_fifo_state(true)?; defmt::println!("TX FIFO___________________{}", fifo); @@ -118,26 +118,60 @@ where self.spi_read(1, registers::EN_AA)?; defmt::println!("Auto Acknowledgment_______0b{=0..8}", self._buf[1]); - + let rx = defmt::intern!("R"); + let tx = defmt::intern!("T"); defmt::println!( - "Primary Mode______________{}X", - if self._config_reg & 1 > 0 { "R" } else { "T" } + "Primary Mode______________{=istr}X", + if self._config_reg & 1 > 0 { rx } else { tx } ); defmt::println!( "Powered Up________________{=bool}", self._config_reg & 2 > 0 ); + + // print pipe addresses + self.spi_read(5, registers::TX_ADDR)?; + let mut address = [0u8; 4]; + address.copy_from_slice(&self._buf[2..6]); + address.reverse(); + defmt::println!( + "TX address_____________{=[u8; 4]:#08X}{=u8:02X}", + address, + self._buf[1] + ); + self.spi_read(1, registers::EN_RXADDR)?; + let open_pipes = self._buf[1]; + let opened = defmt::intern!(" open "); + let closed = defmt::intern!("closed"); + for pipe in 0..=5 { + self.spi_read(if pipe < 2 { 5 } else { 1 }, registers::RX_ADDR_P0 + pipe)?; + if pipe < 2 { + address.copy_from_slice(&self._buf[2..6]); + address.reverse(); + } + defmt::println!( + "Pipe ({=istr}) bound to {=[u8; 4]:#08X}{=u8:02X}", + if (open_pipes & (1u8 << pipe)) > 0 { + opened + } else { + closed + }, + // reverse the bytes read to represent how memory is stored + address, + self._buf[1], + ); + } Ok(()) } #[cfg(not(any(feature = "defmt", feature = "std")))] - fn print_details(&mut self) -> Result<(), Self::LoggingErrorType> { + fn print_details(&mut self) -> Result<(), Self::DetailsErrorType> { Ok(()) } #[cfg(not(target_os = "none"))] #[cfg(feature = "std")] - fn print_details(&mut self) -> Result<(), Self::LoggingErrorType> { + fn print_details(&mut self) -> Result<(), Self::DetailsErrorType> { std::println!("Is a plus variant_________{}", self.is_plus_variant()); let channel = self.get_channel()?; @@ -190,19 +224,19 @@ where self.get_status_flags(&mut flags); std::println!( "IRQ on Data Ready_________{}", - self._config_reg & mnemonics::MASK_RX_DR > 0 + (self._config_reg & mnemonics::MASK_RX_DR) == 0 ); std::println!(" Data Ready triggered__{}", flags.rx_dr); - std::println!( - "IRQ on Data Fail__________{}", - self._config_reg & mnemonics::MASK_MAX_RT > 0 - ); - std::println!(" Data Failed triggered_{}", flags.tx_df); std::println!( "IRQ on Data Sent__________{}", - self._config_reg & mnemonics::MASK_TX_DS > 0 + (self._config_reg & mnemonics::MASK_TX_DS) == 0 ); std::println!(" Data Sent triggered___{}", flags.tx_ds); + std::println!( + "IRQ on Data Fail__________{}", + (self._config_reg & mnemonics::MASK_MAX_RT) == 0 + ); + std::println!(" Data Fail triggered___{}", flags.tx_df); let fifo = self.get_fifo_state(true)?; std::println!("TX FIFO___________________{}", fifo); @@ -225,6 +259,35 @@ where if self._config_reg & 1 > 0 { "R" } else { "T" } ); std::println!("Powered Up________________{}", self._config_reg & 2 > 0); + + // print pipe addresses + self.spi_read(5, registers::TX_ADDR)?; + let mut address = [0u8; 4]; + address.copy_from_slice(&self._buf[2..6]); + std::println!( + "TX address_____________{:#08X}{:02X}", + u32::from_le_bytes(address), + self._buf[1] + ); + self.spi_read(1, registers::EN_RXADDR)?; + let open_pipes = self._buf[1]; + for pipe in 0..=5 { + self.spi_read(if pipe < 2 { 5 } else { 1 }, registers::RX_ADDR_P0 + pipe)?; + if pipe < 2 { + address.copy_from_slice(&self._buf[2..6]); + } + std::println!( + "Pipe ({}) bound to {:#08X}{:02X}", + if (open_pipes & (1u8 << pipe)) > 0 { + " open " + } else { + "closed" + }, + // reverse the bytes read to represent how memory is stored + u32::from_le_bytes(address), + self._buf[1], + ); + } Ok(()) } } diff --git a/library/src/radio/rf24/fifo.rs b/crates/rf24-rs/src/radio/rf24/fifo.rs similarity index 100% rename from library/src/radio/rf24/fifo.rs rename to crates/rf24-rs/src/radio/rf24/fifo.rs diff --git a/library/src/radio/rf24/mod.rs b/crates/rf24-rs/src/radio/rf24/mod.rs similarity index 98% rename from library/src/radio/rf24/mod.rs rename to crates/rf24-rs/src/radio/rf24/mod.rs index a1c4838..315e772 100644 --- a/library/src/radio/rf24/mod.rs +++ b/crates/rf24-rs/src/radio/rf24/mod.rs @@ -27,6 +27,11 @@ pub enum Nrf24Error { Gpo(DO), /// Represents a corruption of binary data (as it was transferred over the SPI bus' MISO) BinaryCorruption, + /// An Error used to prevent an infinite loop in [`RF24::send()`]. + /// + /// This only occurs when user code neglected to call [`RF24::as_tx()`] at least once + /// before calling [`RF24::send()`]. + NotAsTxError, } /// This struct implements the [`Esb*` traits](mod@crate::radio::prelude) diff --git a/library/src/radio/rf24/pa_level.rs b/crates/rf24-rs/src/radio/rf24/pa_level.rs similarity index 100% rename from library/src/radio/rf24/pa_level.rs rename to crates/rf24-rs/src/radio/rf24/pa_level.rs diff --git a/library/src/radio/rf24/payload_length.rs b/crates/rf24-rs/src/radio/rf24/payload_length.rs similarity index 100% rename from library/src/radio/rf24/payload_length.rs rename to crates/rf24-rs/src/radio/rf24/payload_length.rs diff --git a/library/src/radio/rf24/pipe.rs b/crates/rf24-rs/src/radio/rf24/pipe.rs similarity index 100% rename from library/src/radio/rf24/pipe.rs rename to crates/rf24-rs/src/radio/rf24/pipe.rs diff --git a/library/src/radio/rf24/power.rs b/crates/rf24-rs/src/radio/rf24/power.rs similarity index 100% rename from library/src/radio/rf24/power.rs rename to crates/rf24-rs/src/radio/rf24/power.rs diff --git a/library/src/radio/rf24/radio.rs b/crates/rf24-rs/src/radio/rf24/radio.rs similarity index 99% rename from library/src/radio/rf24/radio.rs rename to crates/rf24-rs/src/radio/rf24/radio.rs index 1f79942..4c16f11 100644 --- a/library/src/radio/rf24/radio.rs +++ b/crates/rf24-rs/src/radio/rf24/radio.rs @@ -136,14 +136,11 @@ where /// This function calls [`RF24::flush_tx()`] upon entry, but it does not /// deactivate the radio's CE pin upon exit. fn send(&mut self, buf: &[u8], ask_no_ack: bool) -> Result { - if self.is_rx() { - // check if in RX mode to prevent an infinite below - return Ok(false); - } self._ce_pin.set_low().map_err(Nrf24Error::Gpo)?; // this function only handles 1 payload at a time self.flush_tx()?; // flush the TX FIFO to ensure we are sending the given buf if !self.write(buf, ask_no_ack, true)? { + // write() also clears the status flags and asserts the CE pin return Ok(false); } self._delay_impl.delay_ns(10000); @@ -170,6 +167,10 @@ where ask_no_ack: bool, start_tx: bool, ) -> Result { + if self.is_rx() { + // check if in RX mode to prevent improper radio usage + return Err(Self::RadioErrorType::NotAsTxError); + } self.clear_status_flags(None)?; if self._status & 1 == 1 { // TX FIFO is full already diff --git a/library/src/radio/rf24/status.rs b/crates/rf24-rs/src/radio/rf24/status.rs similarity index 100% rename from library/src/radio/rf24/status.rs rename to crates/rf24-rs/src/radio/rf24/status.rs diff --git a/library/src/types.rs b/crates/rf24-rs/src/types.rs similarity index 100% rename from library/src/types.rs rename to crates/rf24-rs/src/types.rs diff --git a/cspell.config.yml b/cspell.config.yml index 877eb0b..060b621 100644 --- a/cspell.config.yml +++ b/cspell.config.yml @@ -30,6 +30,7 @@ words: - gpiod - HLINE - inlinehilite + - istr - Kbps - linenums - maturin diff --git a/docs/src/index.md b/docs/src/index.md index fc59c31..36ecbf2 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -5,7 +5,7 @@ ## API Docs -The Rust API documentation is hosted at [docs.rs](https://docs.rs/rf24). +The Rust API documentation is hosted at [docs.rs/rf24](https://docs.rs/rf24). Here, you will find the API for FFI (Foreign Function Interface) bindings: diff --git a/examples/rust/Cargo.toml b/examples/rust/Cargo.toml index 7d88e4f..1113d22 100644 --- a/examples/rust/Cargo.toml +++ b/examples/rust/Cargo.toml @@ -2,9 +2,10 @@ name = "rf24-rs-examples" version.workspace = true edition.workspace = true +rust-version.workspace = true [dependencies] -rf24-rs = {path = "../../library"} +rf24-rs = {path = "../../crates/rf24-rs"} embedded-hal = "1.0.0" anyhow = {version = "1.0.89", default-features = false } linux-embedded-hal = {version = "0.4.0", optional = true} diff --git a/justfile b/justfile index 43b2a3a..4841a23 100644 --- a/justfile +++ b/justfile @@ -4,7 +4,7 @@ set windows-shell := ["powershell.exe", "-NoLogo", "-Command"] [group("code coverage")] test profile='default': cargo llvm-cov --no-report \ - nextest --manifest-path library/Cargo.toml \ + nextest \ --lib --tests --color always --profile {{ profile }} # Clear previous test build artifacts @@ -16,19 +16,19 @@ test-clean: # generate pretty coverage report [group("code coverage")] pretty-cov *args='': - cargo llvm-cov report --json --output-path coverage.json --ignore-filename-regex details + cargo llvm-cov report --json --output-path coverage.json llvm-cov-pretty coverage.json {{ args }} # pass "--open" to this recipe's args to load HTML in your browser # generate detailed coverage report [group("code coverage")] llvm-cov *args='': - cargo llvm-cov report --html --ignore-filename-regex details {{ args }} + cargo llvm-cov report --html {{ args }} # generate lcov.info [group("code coverage")] lcov: - cargo llvm-cov report --lcov --output-path lcov.info --ignore-filename-regex details + cargo llvm-cov report --lcov --output-path lcov.info # pass "--open" to this recipe's "open" arg to load HTML in your browser # serve mkdocs diff --git a/library/README.md b/library/README.md deleted file mode 100644 index cff2bdd..0000000 --- a/library/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# rf24-rs - -This is a pure-rust driver for the nRF24L01 wireless transceivers.