embedded_nrf24l01/
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    fn flush_rx(&mut self) -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
61        self.device().send_command(&FlushRx)?;
62        Ok(())
63    }
64
65    /// Flush TX queue, discarding any unsent packets
66    fn flush_tx(&mut self) -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
67        self.device().send_command(&FlushTx)?;
68        Ok(())
69    }
70
71    /// Get frequency offset (channel)
72    fn get_frequency(&mut self) -> Result<u8, <<Self as Configuration>::Inner as Device>::Error> {
73        let (_, register) = self.device().read_register::<RfCh>()?;
74        let freq_offset = register.rf_ch();
75        Ok(freq_offset)
76    }
77
78    /// Set frequency offset (channel)
79    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)?;
88
89        Ok(())
90    }
91
92    /// power: `0`: -18 dBm, `3`: 0 dBm
93    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)?;
111        Ok(())
112    }
113
114    /// Set CRC mode
115    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))
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    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        })
137    }
138
139    /// Configure which RX pipes to enable
140    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))?;
145        Ok(())
146    }
147
148    /// Set address `addr` of pipe number `pipe_no`
149    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)?;
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    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)?;
184        Ok(())
185    }
186
187    /// Configure auto-retransmit
188    ///
189    /// To disable, call as `set_auto_retransmit(0, 0)`.
190    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)?;
199        Ok(())
200    }
201
202    /// Obtain auto-acknowledgment configuration for all pipes
203    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>()?;
208        Ok(register.to_bools())
209    }
210
211    /// Configure auto-acknowledgment for all RX pipes
212    ///
213    /// TODO: handle switching tx/rx modes when auto-retransmit is enabled
214    fn set_auto_ack(
215        &mut self,
216        bools: &[bool; PIPES_COUNT],
217    ) -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
218        // Convert back
219        let register = EnAa::from_bools(bools);
220        // Write back
221        self.device().write_register(register)?;
222        Ok(())
223    }
224
225    /// Get address width configuration
226    fn get_address_width(
227        &mut self,
228    ) -> Result<u8, <<Self as Configuration>::Inner as Device>::Error> {
229        let (_, register) = self.device().read_register::<SetupAw>()?;
230        Ok(2 + register.aw())
231    }
232
233    /// Obtain interrupt pending status as `(RX_DR, TX_DR, MAX_RT)`
234    /// where `RX_DR` indicates new data in the RX FIFO, `TX_DR`
235    /// indicates that a packet has been sent, and `MAX_RT` indicates
236    /// maximum retransmissions without auto-ack.
237    fn get_interrupts(
238        &mut self,
239    ) -> Result<(bool, bool, bool), <<Self as Configuration>::Inner as Device>::Error> {
240        let (status, ()) = self.device().send_command(&Nop)?;
241        Ok((status.rx_dr(), status.tx_ds(), status.max_rt()))
242    }
243
244    /// Clear all interrupts
245    fn clear_interrupts(
246        &mut self,
247    ) -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
248        let mut clear = Status(0);
249        clear.set_rx_dr(true);
250        clear.set_tx_ds(true);
251        clear.set_max_rt(true);
252        self.device().write_register(clear)?;
253        Ok(())
254    }
255
256    /// ## `bools`
257    /// * `None`: Dynamic payload length
258    /// * `Some(len)`: Static payload length `len`
259    fn set_pipes_rx_lengths(
260        &mut self,
261        lengths: &[Option<u8>; PIPES_COUNT],
262    ) -> Result<(), <<Self as Configuration>::Inner as Device>::Error> {
263        // Enable dynamic payload lengths
264        let mut bools = [true; PIPES_COUNT];
265        for (i, length) in lengths.iter().enumerate() {
266            bools[i] = length.is_none();
267        }
268        let dynpd = Dynpd::from_bools(&bools);
269        if dynpd.0 != 0 {
270            self.device().update_register::<Feature, _, _>(|feature| {
271                feature.set_en_dpl(true);
272            })?;
273        }
274        self.device().write_register(dynpd)?;
275
276        // Set static payload lengths
277        macro_rules! set_rx_pw {
278            ($name: ident, $index: expr) => {{
279                use crate::registers::$name;
280                let length = lengths[$index].unwrap_or(0);
281                let mut register = $name(0);
282                register.set(length);
283                self.device().write_register(register)?;
284            }};
285        }
286        set_rx_pw!(RxPwP0, 0);
287        set_rx_pw!(RxPwP1, 1);
288        set_rx_pw!(RxPwP2, 2);
289        set_rx_pw!(RxPwP3, 3);
290        set_rx_pw!(RxPwP4, 4);
291        set_rx_pw!(RxPwP5, 5);
292
293        Ok(())
294    }
295}