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}