rf24ble/
lib.rs

1#![no_std]
2#![doc(
3    html_logo_url = "https://raw.githubusercontent.com/nRF24/rf24-rs/main/docs/src/images/logo-square.png"
4)]
5#![doc(html_favicon_url = "https://github.com/nRF24/rf24-rs/raw/main/docs/src/images/favicon.ico")]
6#![doc = include_str!("../README.md")]
7//! ## Limitations
8//!
9//! Because the nRF24L01 wasn't designed for BLE advertising, it has some limitations that users should beware.
10//!
11//! 1. The maximum payload length is shortened to **18** bytes (when not broadcasting a device
12//!    name nor the radio's PA level). This is calculated as:
13//!
14//!    ```text
15//!    32 (nRF24L01 maximum) - 6 (MAC address) - 5 (required flags) - 3 (CRC checksum) = 18
16//!    ```
17//!
18//!    Use the helper function [`FakeBle::len_available()`](fn@crate::radio::FakeBle::len_available())
19//!    to determine if your payload will transmit.
20//! 2. The channels that BLE use are limited to the following three:
21//!
22//!    - 2.402 GHz
23//!    - 2.426 GHz
24//!    - 2.480 GHz
25//!
26//!    For convenience, use [`FakeBle::hop_channel()`](fn@crate::radio::FakeBle::hop_channel())
27//!    (when radio is in TX mode only) to switch between these frequencies.
28//! 3. CRC length is disabled in the nRF24L01 firmware because BLE specifications require 3 bytes,
29//!    and the nRF24L01 firmware can only handle a maximum of 2.
30//!    Thus, we append the required 3 bytes of the calculated CRC24 into the payload.
31//! 4. Address length of a BLE packet only uses 4 bytes.
32//! 5. The auto-ack (automatic acknowledgment) feature of the nRF24L01 is useless
33//!    when transmitting to BLE devices, thus the automatic re-transmit and custom ACK payloads
34//!    features are useless because they both depend on the automatic acknowledgments feature.
35//! 6. Dynamic payloads feature of the nRF24L01 isn't compatible with BLE specifications.
36//! 7. BLE specifications only allow using 1 Mbps RF data rate.
37//! 8. Only the "on data sent" (`tx_ds`) & "on data ready" (`rx_dr`) events will have
38//!    an effect on the interrupt (IRQ) pin. The "on data fail" (`tx_df`) event is never
39//!    triggered when the auto-ack feature is disabled.
40
41mod radio;
42pub use radio::{ble_config, BleChannels, FakeBle, BLE_CHANNEL};
43
44pub mod data_manipulation;
45
46pub mod services;
47
48#[cfg(test)]
49mod test {
50    use embedded_hal_mock::eh1::{
51        delay::NoopDelay,
52        digital::{Mock as PinMock, Transaction as PinTransaction},
53        spi::{Mock as SpiMock, Transaction as SpiTransaction},
54    };
55    use rf24::radio::RF24;
56
57    /// Takes an indefinite repetition of a tuple of 2 vectors: `(expected_data, response_data)`
58    /// and generates an array of `SpiTransaction`s.
59    ///
60    /// NOTE: This macro is only used to generate code in unit tests (for this crate only).
61    #[macro_export]
62    macro_rules! spi_test_expects {
63        ($( ($expected:expr , $response:expr $(,)? ) , ) + ) => {
64            [
65                $(
66                    SpiTransaction::transaction_start(),
67                    SpiTransaction::transfer_in_place($expected, $response),
68                    SpiTransaction::transaction_end(),
69                )*
70            ]
71        }
72    }
73
74    /// A tuple struct to encapsulate objects used to mock [`RF24`],
75    pub struct MockRadio(
76        pub RF24<SpiMock<u8>, PinMock, NoopDelay>,
77        pub SpiMock<u8>,
78        pub PinMock,
79    );
80
81    /// Create a mock objects using the given expectations.
82    ///
83    /// The `spi_expectations` parameter
84    pub fn mk_radio(
85        ce_expectations: &[PinTransaction],
86        spi_expectations: &[SpiTransaction<u8>],
87    ) -> MockRadio {
88        let spi = SpiMock::new(spi_expectations);
89        let ce_pin = PinMock::new(ce_expectations);
90        let delay_impl = NoopDelay;
91        let radio = RF24::new(ce_pin.clone(), spi.clone(), delay_impl);
92        MockRadio(radio, spi, ce_pin)
93    }
94}