nrf24_rs/
config.rs

1//! Different structs and values for configuration of the chip.
2//!
3//! To construct a representation of your config, see [`NrfConfig`].
4//!
5//! # Default values
6//! All these options have a default value:
7//!
8//! * `addr_width`:             address width of 5 bytes.
9//! * `ack_payloads_enabled`:   false: acknowledgement payloads are disabled by default.
10//! * `auto_retry`:             enabled, will wait 1586µs on ack, and will retry 15 times.
11//! * `channel`:                channel 76.
12//! * `crc_encoding_scheme`:    encoding scheme with 2 bytes.
13//! * `data_rate`:              1Mbps.
14//! * `payload_size`:           static payload size of [`MAX_PAYLOAD_SIZE`] bytes.
15//! * `pa_level`:               min amplification level.
16//!
17use crate::register_acces::Register;
18use crate::MAX_PAYLOAD_SIZE;
19
20const MAX_CHANNEL: u8 = 125;
21
22/// Configuration builder struct for NRF chip.
23///
24/// Always created with the `default()` method and modified through
25/// the builder pattern. See [module level documentation][crate::config] for all the default values.
26///
27/// # Example: default
28/// ```rust
29/// use nrf24::Nrf24l01;
30/// use nrf24::config::NrfConfig;
31///
32/// let config = NrfConfig::default();
33///
34/// let mut chip = Nrf24l01::new(spi, ce, delay, config)?;
35/// ```
36///
37/// # Example: custom configuration
38/// ```rust
39/// use nrf24::Nrf24l01;
40/// use nrf24::config::{PALevel, DataRate, NrfConfig, PayloadSize};
41///
42/// let config = NrfConfig::default()
43///     .payload_size(PayloadSize::Dynamic) // set dynamic payload size
44///     .channel(7)
45///     .addr_width(3),
46///     .data_rate(DataRate::R2Mbps)
47///     .pa_level(PALevel::Max)
48///     .crc_encoding_scheme(EncodingScheme::NoRedundancyCheck) // disable crc
49///     .ack_payloads_enabled(true)
50///     .auto_retry((15, 15));
51///
52/// let mut chip = Nrf24l01::new(spi, ce, delay, config)?;
53/// ```
54#[derive(Copy, Clone)]
55#[cfg_attr(feature = "defmt", derive(defmt::Format))]
56pub struct NrfConfig {
57    pub(crate) payload_size: PayloadSize,
58    pub(crate) channel: u8,
59    pub(crate) addr_width: AddressWidth,
60    pub(crate) data_rate: DataRate,
61    pub(crate) pa_level: PALevel,
62    pub(crate) crc_encoding_scheme: EncodingScheme,
63    pub(crate) ack_payloads_enabled: bool,
64    pub(crate) auto_retry: AutoRetransmission,
65}
66
67impl NrfConfig {
68    /// Set Payload Size
69    /// A value of 0 means dynamic payloads will be enabled.
70    /// Values greater than [`MAX_PAYLOAD_SIZE`] will be floored.
71    pub fn payload_size<T: Into<PayloadSize>>(mut self, payload_size: T) -> Self {
72        self.payload_size = payload_size.into();
73        self
74    }
75    /// Set RF channel
76    /// Must be a number in [0..125], values outside will be clipped
77    pub fn channel(mut self, channel: u8) -> Self {
78        self.channel = core::cmp::min(channel, MAX_CHANNEL);
79        self
80    }
81    /// Set the Address Width
82    /// If using a number, it must be in [3..5], values outside will be clipped
83    pub fn addr_width<T: Into<AddressWidth>>(mut self, addr_width: T) -> Self {
84        self.addr_width = addr_width.into();
85        self
86    }
87    /// Set the Data Rate
88    pub fn data_rate(mut self, data_rate: DataRate) -> Self {
89        self.data_rate = data_rate;
90        self
91    }
92    /// Set the Power Amplification Level
93    pub fn pa_level(mut self, pa_level: PALevel) -> Self {
94        self.pa_level = pa_level;
95        self
96    }
97    /// Set the Cyclic Redundancy Check Encoding Scheme
98    pub fn crc_encoding_scheme(mut self, crc_encoding_scheme: EncodingScheme) -> Self {
99        self.crc_encoding_scheme = crc_encoding_scheme;
100        self
101    }
102    /// Configure if auto acknowledgements are enabled
103    pub fn ack_payloads_enabled(mut self, ack_payloads_enabled: bool) -> Self {
104        self.ack_payloads_enabled = ack_payloads_enabled;
105        self
106    }
107    /// Set the automatic retransmission config
108    pub fn auto_retry<T: Into<AutoRetransmission>>(mut self, auto_retry: T) -> Self {
109        self.auto_retry = auto_retry.into();
110        self
111    }
112}
113
114impl Default for NrfConfig {
115    fn default() -> Self {
116        Self {
117            channel: 76,
118            payload_size: PayloadSize::default(),
119            addr_width: AddressWidth::default(),
120            crc_encoding_scheme: EncodingScheme::default(),
121            pa_level: PALevel::default(),
122            data_rate: DataRate::default(),
123            ack_payloads_enabled: false,
124            auto_retry: AutoRetransmission::default(),
125        }
126    }
127}
128
129/// Different RF power levels. The higher the level the bigger range, but the more the current
130/// consumption.
131///
132/// Defaults to Min.
133#[derive(Copy, Clone)]
134pub enum PALevel {
135    /// -18 dBm, 7 mA current consumption.
136    Min = 0b0000_0000,
137    /// -12 dBm, 7.5 mA current consumption.
138    Low = 0b0000_0010,
139    /// -6 dBm, 9.0 mA current consumption.
140    High = 0b0000_0100,
141    /// -0 dBm, 11.3 mA current consumption.
142    Max = 0b0000_0110,
143}
144
145impl PALevel {
146    pub(crate) fn bitmask() -> u8 {
147        0b0000_0110
148    }
149    pub(crate) fn level(&self) -> u8 {
150        *self as u8
151    }
152}
153
154impl Default for PALevel {
155    fn default() -> Self {
156        PALevel::Min
157    }
158}
159
160impl From<u8> for PALevel {
161    fn from(t: u8) -> Self {
162        match t & Self::bitmask() {
163            0b0000_0000 => Self::Min,
164            0b0000_0010 => Self::Low,
165            0b0000_0100 => Self::High,
166            0b0000_0110 => Self::Max,
167            _ => unreachable!(),
168        }
169    }
170}
171
172#[cfg(feature = "defmt")]
173impl defmt::Format for PALevel {
174    fn format(&self, fmt: defmt::Formatter) {
175        match *self {
176            PALevel::Min => defmt::write!(fmt, "min (-18 dBm)"),
177            PALevel::Low => defmt::write!(fmt, "low (-12 dBm)"),
178            PALevel::High => defmt::write!(fmt, "high (-6 dBm)"),
179            PALevel::Max => defmt::write!(fmt, "max (0 dBm)"),
180        }
181    }
182}
183
184/// Enum representing the payload size.
185#[derive(PartialEq, Eq, Copy, Clone)]
186#[cfg_attr(feature = "defmt", derive(defmt::Format))]
187pub enum PayloadSize {
188    /// The chip will dynamically set the payload size, depending on the message size.
189    Dynamic,
190    /// Static payload size. Maximum value of 127.
191    Static(u8),
192}
193
194impl PayloadSize {
195    /// Truncates the payload size to be max [`MAX_PAYLOAD_SIZE`].
196    pub(crate) fn truncate(self) -> Self {
197        match self {
198            Self::Dynamic => Self::Dynamic,
199            Self::Static(n) => Self::Static(core::cmp::min(n, MAX_PAYLOAD_SIZE)),
200        }
201    }
202}
203
204impl Default for PayloadSize {
205    fn default() -> Self {
206        Self::Static(MAX_PAYLOAD_SIZE)
207    }
208}
209
210impl From<u8> for PayloadSize {
211    fn from(size: u8) -> Self {
212        match size {
213            0 => Self::Dynamic,
214            n => Self::Static(core::cmp::min(n, MAX_PAYLOAD_SIZE)),
215        }
216    }
217}
218
219/// Configured speed at which data will be sent.
220///
221/// Defaults to 2Mpbs.
222#[derive(Copy, Clone)]
223#[cfg_attr(feature = "defmt", derive(defmt::Format))]
224pub enum DataRate {
225    /// 1 Mbps
226    R1Mbps = 0b0000_0000,
227    /// 2 Mbps
228    R2Mbps = 0b0000_0001,
229}
230
231impl DataRate {
232    pub(crate) fn bitmask() -> u8 {
233        0b0000_1000
234    }
235    pub(crate) fn rate(&self) -> u8 {
236        *self as u8
237    }
238}
239
240impl Default for DataRate {
241    fn default() -> Self {
242        DataRate::R1Mbps
243    }
244}
245
246impl From<u8> for DataRate {
247    fn from(t: u8) -> Self {
248        match t & Self::bitmask() {
249            0b0000_0000 => Self::R1Mbps,
250            0b0000_1000 => Self::R2Mbps,
251            _ => unreachable!(),
252        }
253    }
254}
255
256/// Cyclic Redundancy Check encoding scheme.
257#[derive(Copy, Clone)]
258#[cfg_attr(feature = "defmt", derive(defmt::Format))]
259pub enum EncodingScheme {
260    /// No CRC check
261    NoRedundancyCheck = 0b0000_0000,
262    /// 1 byte
263    R1Byte = 0b0000_1000,
264    /// 2 bytes
265    R2Bytes = 0b0000_1100,
266}
267
268impl Default for EncodingScheme {
269    fn default() -> Self {
270        Self::R2Bytes
271    }
272}
273
274impl EncodingScheme {
275    pub(crate) fn bitmask() -> u8 {
276        0b0000_1100
277    }
278
279    pub(crate) fn scheme(&self) -> u8 {
280        *self as u8
281    }
282}
283
284impl From<u8> for EncodingScheme {
285    fn from(t: u8) -> Self {
286        match t & Self::bitmask() {
287            0b0000_0000 => Self::NoRedundancyCheck,
288            0b0000_1000 => Self::R1Byte,
289            0b0000_1100 => Self::R2Bytes,
290            _ => unreachable!(),
291        }
292    }
293}
294///
295/// Address width for the reading and writing pipes.
296#[derive(Copy, Clone)]
297pub enum AddressWidth {
298    /// 3 bytes
299    R3Bytes = 1,
300    /// 4 bytes
301    R4Bytes = 2,
302    /// 5 bytes
303    R5Bytes = 3,
304}
305
306impl AddressWidth {
307    pub(crate) fn value(&self) -> u8 {
308        *self as u8
309    }
310    pub(crate) fn from_register(t: u8) -> Self {
311        match t & 0b11 {
312            0b01 => Self::R3Bytes,
313            0b10 => Self::R4Bytes,
314            0b11 => Self::R5Bytes,
315            _ => unreachable!(),
316        }
317    }
318}
319impl Default for AddressWidth {
320    fn default() -> Self {
321        Self::R5Bytes
322    }
323}
324
325impl From<u8> for AddressWidth {
326    // from literal value
327    fn from(t: u8) -> Self {
328        match t {
329            0..=3 => Self::R3Bytes,
330            4 => Self::R4Bytes,
331            5..=u8::MAX => Self::R5Bytes,
332        }
333    }
334}
335
336#[cfg(feature = "defmt")]
337impl defmt::Format for AddressWidth {
338    fn format(&self, fmt: defmt::Formatter) {
339        match *self {
340            Self::R3Bytes => defmt::write!(fmt, "3 bytes"),
341            Self::R4Bytes => defmt::write!(fmt, "4 bytes"),
342            Self::R5Bytes => defmt::write!(fmt, "5 bytes"),
343        }
344    }
345}
346
347/// Configuration of automatic retransmission consisting of a retransmit delay
348/// and a retransmission count.
349///
350/// The delay before a retransmit is initiated, is calculated according to the following formula:
351/// > ((**delay** + 1) * 250) + 86 µs
352///
353/// # Default
354///
355/// * Auto retransmission delay has a default value of 5, which means `1586 µs`.
356/// * The chip will try to resend a failed message 15 times by default.
357#[derive(Copy, Clone)]
358pub struct AutoRetransmission {
359    delay: u8,
360    count: u8,
361}
362
363impl Default for AutoRetransmission {
364    fn default() -> Self {
365        Self {
366            delay: 5,
367            count: 15,
368        }
369    }
370}
371
372impl AutoRetransmission {
373    pub(crate) fn from_register(reg: u8) -> Self {
374        Self {
375            delay: reg >> 4,
376            count: reg & 0b0000_1111,
377        }
378    }
379    /// The auto retransmit delay value.
380    /// Values can be between 0 and 15.
381    /// The delay before a retransmit is initiated, is calculated according to the following formula:
382    /// > ((**delay** + 1) * 250) + 86 µs
383    pub fn raw_delay(&self) -> u8 {
384        self.delay
385    }
386
387    /// Returns the delay between auto retransmissions in ms.
388    pub fn delay(&self) -> u32 {
389        ((self.delay as u32 + 1) * 250) + 86
390    }
391    /// The number of times there will be an auto retransmission.
392    /// Guarantueed to be a value between 0 and 15.
393    pub fn count(&self) -> u8 {
394        self.count
395    }
396}
397
398impl From<(u8, u8)> for AutoRetransmission {
399    fn from((d, c): (u8, u8)) -> Self {
400        Self {
401            delay: core::cmp::min(d, 15),
402            count: core::cmp::min(c, 15),
403        }
404    }
405}
406
407#[cfg(feature = "defmt")]
408impl defmt::Format for AutoRetransmission {
409    fn format(&self, fmt: defmt::Formatter) {
410        defmt::write!(
411            fmt,
412            "AutoRetransmission {{ raw_delay: {=u8}, delay_µs: {=u32}, count: {=u8} }}",
413            &self.raw_delay(),
414            &self.delay(),
415            &self.count(),
416        )
417    }
418}
419
420/// Representation of the different data pipes through which data can be received.
421///
422/// An nRF24L01 configured as primary RX (PRX) will be able to receive data trough 6 different data
423/// pipes.
424/// One data pipe will have a unique address but share the same frequency channel.
425/// This means that up to 6 different nRF24L01 configured as primary TX (PTX) can communicate with
426/// one nRF24L01 configured as PRX, and the nRF24L01 configured as PRX will be able to distinguish
427/// between them.
428///
429/// The default assumed data pipe is 0.
430///
431/// Data pipe 0 has a unique 40 bit configurable address. Each of data pipe 1-5 has an 8 bit unique
432/// address and shares the 32 most significant address bits.
433///
434/// # Notes
435/// In the PTX device data pipe 0 is used to received the acknowledgement, and therefore the
436/// receive address for data pipe 0 has to be equal to the transmit address to be able to receive
437/// the acknowledgement.
438#[derive(Copy, Clone)]
439#[repr(u8)]
440#[cfg_attr(feature = "defmt", derive(defmt::Format))]
441pub enum DataPipe {
442    /// Data pipe 0.
443    /// Default pipe with a 40 bit configurable address.
444    /// This pipe is used in TX mode when auto acknowledgement is enabled. On this channel the ACK
445    /// messages are received.
446    DP0 = 0,
447    /// Data pipe 1.
448    DP1 = 1,
449    /// Data pipe 2.
450    DP2 = 2,
451    /// Data pipe 3.
452    DP3 = 3,
453    /// Data pipe 4.
454    DP4 = 4,
455    /// Data pipe 5.
456    DP5 = 5,
457}
458
459impl DataPipe {
460    pub(crate) fn pipe(&self) -> u8 {
461        *self as u8
462    }
463}
464
465impl Default for DataPipe {
466    fn default() -> Self {
467        DataPipe::DP0
468    }
469}
470
471impl From<u8> for DataPipe {
472    fn from(t: u8) -> Self {
473        match t {
474            0 => DataPipe::DP0,
475            1 => DataPipe::DP1,
476            2 => DataPipe::DP2,
477            3 => DataPipe::DP3,
478            4 => DataPipe::DP4,
479            5 => DataPipe::DP5,
480            _ => DataPipe::DP0,
481        }
482    }
483}
484
485impl Into<Register> for DataPipe {
486    fn into(self) -> Register {
487        match self {
488            DataPipe::DP0 => Register::RX_ADDR_P0,
489            DataPipe::DP1 => Register::RX_ADDR_P1,
490            DataPipe::DP2 => Register::RX_ADDR_P2,
491            DataPipe::DP3 => Register::RX_ADDR_P3,
492            DataPipe::DP4 => Register::RX_ADDR_P4,
493            DataPipe::DP5 => Register::RX_ADDR_P5,
494        }
495    }
496}