embedded_nrf24l01_async/
config.rs

1use crate::command::{FlushRx, FlushTx, Nop};
2use crate::device::Device;
3use crate::registers::{
4    Config, Dynpd, EnAa, EnRxaddr, Feature, RfCh, RfSetup, SetupAw, SetupRetr, Status, TxAddr,
5};
6use crate::PIPES_COUNT;
7
8/// Supported air data rates.
9#[derive(Debug, PartialEq, Copy, Clone)]
10pub enum DataRate {
11    /// 250 Kbps
12    R250Kbps,
13    /// 1 Mbps
14    R1Mbps,
15    /// 2 Mbps
16    R2Mbps,
17}
18
19impl Default for DataRate {
20    fn default() -> DataRate {
21        DataRate::R1Mbps
22    }
23}
24
25/// Supported CRC modes
26#[derive(Debug, PartialEq, Copy, Clone)]
27pub enum CrcMode {
28    /// Disable all CRC generation/checking
29    Disabled,
30    /// One byte checksum
31    OneByte,
32    /// Two bytes checksum
33    TwoBytes,
34}
35
36impl CrcMode {
37    fn set_config(&self, config: &mut Config) {
38        let (en_crc, crco) = match *self {
39            CrcMode::Disabled => (false, false),
40            CrcMode::OneByte => (true, false),
41            CrcMode::TwoBytes => (true, true),
42        };
43        config.set_en_crc(en_crc);
44        config.set_crco(crco);
45    }
46}
47
48/// Configuration methods
49///
50/// These seem to work in all modes
51pub trait Configuration {
52    /// Underlying [`trait Device`](trait.Device.html)
53    type Inner: Device;
54    /// Get a mutable reference to the underlying device
55    fn device(&mut self) -> &mut Self::Inner;
56
57    /// Flush RX queue
58    ///
59    /// Discards all received packets that have not yet been [read](struct.RxMode.html#method.read) from the RX FIFO
60    async fn flush_rx(&mut self) -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
61        self.device().send_command(&FlushRx).await?;
62        Ok(())
63    }
64
65    /// Flush TX queue, discarding any unsent packets
66    async fn flush_tx(&mut self) -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
67        self.device().send_command(&FlushTx).await?;
68        Ok(())
69    }
70
71    /// Get frequency offset (channel)
72    async fn get_frequency(&mut self) -> Result<u8, <<Self as Configuration>::Inner as Device>::Error> {
73        let (_, register) = self.device().read_register::<RfCh>().await?;
74        let freq_offset = register.rf_ch();
75        Ok(freq_offset)
76    }
77
78    /// Set frequency offset (channel)
79    async fn set_frequency(
80        &mut self,
81        freq_offset: u8,
82    ) -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
83        assert!(freq_offset < 126);
84
85        let mut register = RfCh(0);
86        register.set_rf_ch(freq_offset);
87        self.device().write_register(register).await?;
88
89        Ok(())
90    }
91
92    /// power: `0`: -18 dBm, `3`: 0 dBm
93    async fn set_rf(
94        &mut self,
95        rate: &DataRate,
96        power: u8,
97    ) -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
98        assert!(power < 0b100);
99        let mut register = RfSetup(0);
100        register.set_rf_pwr(power);
101
102        let (dr_low, dr_high) = match *rate {
103            DataRate::R250Kbps => (true, false),
104            DataRate::R1Mbps => (false, false),
105            DataRate::R2Mbps => (false, true),
106        };
107        register.set_rf_dr_low(dr_low);
108        register.set_rf_dr_high(dr_high);
109
110        self.device().write_register(register).await?;
111        Ok(())
112    }
113
114    /// Set CRC mode
115    async fn set_crc(
116        &mut self,
117        mode: CrcMode,
118    ) -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
119        self.device().update_config(|config| mode.set_config(config)).await
120    }
121
122    /// Sets the interrupt mask
123    /// 
124    /// When an interrupt mask is set to true, the interrupt is masked and will not fire on the IRQ pin.
125    /// When set to false, it will trigger the IRQ pin.
126    async fn set_interrupt_mask(
127        &mut self,
128        data_ready_rx: bool,
129        data_sent_tx: bool,
130        max_retransmits_tx: bool
131    ) -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
132        self.device().update_config(|config| {
133            config.set_mask_rx_dr(data_ready_rx);
134            config.set_mask_tx_ds(data_sent_tx);
135            config.set_mask_max_rt(max_retransmits_tx);
136        }).await
137    }
138
139    /// Configure which RX pipes to enable
140    async fn set_pipes_rx_enable(
141        &mut self,
142        bools: &[bool; PIPES_COUNT],
143    ) -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
144        self.device().write_register(EnRxaddr::from_bools(bools)).await?;
145        Ok(())
146    }
147
148    /// Set address `addr` of pipe number `pipe_no`
149    async fn set_rx_addr(
150        &mut self,
151        pipe_no: usize,
152        addr: &[u8],
153    ) -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
154        macro_rules! w {
155            ( $($no: expr, $name: ident);+ ) => (
156                match pipe_no {
157                    $(
158                        $no => {
159                            use crate::registers::$name;
160                            let register = $name::new(addr);
161                            self.device().write_register(register).await?;
162                        }
163                    )+
164                        _ => panic!("No such pipe {}", pipe_no)
165                }
166            )
167        }
168        w!(0, RxAddrP0;
169           1, RxAddrP1;
170           2, RxAddrP2;
171           3, RxAddrP3;
172           4, RxAddrP4;
173           5, RxAddrP5);
174        Ok(())
175    }
176
177    /// Set address of the TX pipe
178    async fn set_tx_addr(
179        &mut self,
180        addr: &[u8],
181    ) -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
182        let register = TxAddr::new(addr);
183        self.device().write_register(register).await?;
184        Ok(())
185    }
186
187    /// Configure auto-retransmit
188    ///
189    /// To disable, call as `set_auto_retransmit(0, 0)`.
190    async fn set_auto_retransmit(
191        &mut self,
192        delay: u8,
193        count: u8,
194    ) -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
195        let mut register = SetupRetr(0);
196        register.set_ard(delay);
197        register.set_arc(count);
198        self.device().write_register(register).await?;
199        Ok(())
200    }
201
202    /// Obtain auto-acknowledgment configuration for all pipes
203    async fn get_auto_ack(
204        &mut self,
205    ) -> Result<[bool; PIPES_COUNT], <<Self as Configuration>::Inner as Device>::Error> {
206        // Read
207        let (_, register) = self.device().read_register::<EnAa>().await?;
208        Ok(register.to_bools())
209    }
210
211    /// Configure auto-acknowledgment for all RX pipes
212    ///
213    /// Auto ack is handled by the nrf24 if:
214    /// 1. Auto ack feature is enabled on Feature Register
215    /// 2. Auto ack is enabled for the pipe the packet was received on
216    async fn set_auto_ack(
217        &mut self,
218        bools: &[bool; PIPES_COUNT],
219    ) -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
220        // Convert back
221        let register = EnAa::from_bools(bools);
222        // Write back
223        self.device().write_register(register).await?;
224        Ok(())
225    }
226
227    /// Get address width configuration
228    async fn get_address_width(
229        &mut self,
230    ) -> Result<u8, <<Self as Configuration>::Inner as Device>::Error> {
231        let (_, register) = self.device().read_register::<SetupAw>().await?;
232        Ok(2 + register.aw())
233    }
234
235    /// Set address width configuration
236    async fn set_address_width(&mut self, width: u8)
237        -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
238
239        let register = SetupAw(width - 2);
240        self.device().write_register(register).await?;
241        Ok(())
242    }
243
244    /// Obtain interrupt pending status as `(RX_DR, TX_DR, MAX_RT)`
245    /// where `RX_DR` indicates new data in the RX FIFO, `TX_DR`
246    /// indicates that a packet has been sent, and `MAX_RT` indicates
247    /// maximum retransmissions without auto-ack.
248    async fn get_interrupts(
249        &mut self,
250    ) -> Result<(bool, bool, bool), <<Self as Configuration>::Inner as Device>::Error> {
251        let (status, ()) = self.device().send_command(&Nop).await?;
252        Ok((status.rx_dr(), status.tx_ds(), status.max_rt()))
253    }
254
255    /// Clear all interrupts
256    async fn clear_interrupts(
257        &mut self,
258    ) -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
259        let mut clear = Status(0);
260        clear.set_rx_dr(true);
261        clear.set_tx_ds(true);
262        clear.set_max_rt(true);
263        self.device().write_register(clear).await?;
264        Ok(())
265    }
266
267    /// ## `bools`
268    /// * `None`: Dynamic payload length
269    /// * `Some(len)`: Static payload length `len`
270    async fn set_pipes_rx_lengths(
271        &mut self,
272        lengths: &[Option<u8>; PIPES_COUNT],
273    ) -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
274        // Enable dynamic payload lengths
275        let mut bools = [true; PIPES_COUNT];
276        for (i, length) in lengths.iter().enumerate() {
277            bools[i] = length.is_none();
278        }
279        let dynpd = Dynpd::from_bools(&bools);
280        if dynpd.0 != 0 {
281            self.device().update_register::<Feature, _, _>(|feature| {
282                feature.set_en_dpl(true);
283            }).await?;
284        }
285        self.device().write_register(dynpd).await?;
286
287        // Set static payload lengths
288        macro_rules! set_rx_pw {
289            ($name: ident, $index: expr) => {{
290                use crate::registers::$name;
291                let length = lengths[$index].unwrap_or(0);
292                let mut register = $name(0);
293                register.set(length);
294                self.device().write_register(register).await?;
295            }};
296        }
297        set_rx_pw!(RxPwP0, 0);
298        set_rx_pw!(RxPwP1, 1);
299        set_rx_pw!(RxPwP2, 2);
300        set_rx_pw!(RxPwP3, 3);
301        set_rx_pw!(RxPwP4, 4);
302        set_rx_pw!(RxPwP5, 5);
303
304        Ok(())
305    }
306}