1use embedded_hal::{delay::DelayNs, digital::OutputPin, spi::SpiDevice};
2mod auto_ack;
3pub(crate) mod bit_fields;
4mod channel;
5mod init;
6use bit_fields::{Config, Feature};
7mod constants;
8mod crc_length;
9mod data_rate;
10mod fifo;
11mod pa_level;
12mod payload_length;
13mod pipe;
14mod power;
15mod radio;
16pub use constants::{commands, mnemonics, registers};
17mod details;
18mod status;
19use super::prelude::{
20 EsbAutoAck, EsbChannel, EsbCrcLength, EsbFifo, EsbPaLevel, EsbPower, EsbRadio,
21};
22use crate::{
23 types::{CrcLength, PaLevel},
24 StatusFlags,
25};
26
27#[derive(Clone, Copy, Debug, PartialEq)]
29pub enum Nrf24Error<SPI, DO> {
30 Spi(SPI),
32 Gpo(DO),
34 BinaryCorruption,
36 NotAsTxError,
41}
42
43pub struct RF24<SPI, DO, DELAY> {
48 pub tx_delay: u32,
70 _spi: SPI,
71 pub ce_pin: DO,
77 _delay_impl: DELAY,
78 _buf: [u8; 33],
79 _status: StatusFlags,
80 _config_reg: Config,
81 _feature: Feature,
82 _pipe0_rx_addr: Option<[u8; 5]>,
83 _payload_length: u8,
84}
85
86impl<SPI, DO, DELAY> RF24<SPI, DO, DELAY>
87where
88 SPI: SpiDevice,
89 DO: OutputPin,
90 DELAY: DelayNs,
91{
92 pub fn new(ce_pin: DO, spi: SPI, delay_impl: DELAY) -> RF24<SPI, DO, DELAY> {
99 RF24 {
100 tx_delay: 250,
101 ce_pin,
102 _spi: spi,
103 _delay_impl: delay_impl,
104 _status: StatusFlags::from_bits(0),
105 _buf: [0u8; 33],
106 _pipe0_rx_addr: None,
107 _feature: Feature::from_bits(0)
108 .with_address_length(5)
109 .with_is_plus_variant(true),
110 _config_reg: Config::from_bits(0xC),
112 _payload_length: 32,
113 }
114 }
115
116 fn spi_transfer(&mut self, len: u8) -> Result<(), Nrf24Error<SPI::Error, DO::Error>> {
117 self._spi
118 .transfer_in_place(&mut self._buf[..len as usize])
119 .map_err(Nrf24Error::Spi)?;
120 self._status = StatusFlags::from_bits(self._buf[0]);
121 Ok(())
122 }
123
124 fn spi_read(&mut self, len: u8, command: u8) -> Result<(), Nrf24Error<SPI::Error, DO::Error>> {
130 self._buf[0] = command;
131 self.spi_transfer(len + 1)
132 }
133
134 fn spi_write_byte(
135 &mut self,
136 command: u8,
137 byte: u8,
138 ) -> Result<(), Nrf24Error<SPI::Error, DO::Error>> {
139 self._buf[0] = command | commands::W_REGISTER;
140 self._buf[1] = byte;
141 self.spi_transfer(2)
142 }
143
144 fn spi_write_buf(
145 &mut self,
146 command: u8,
147 buf: &[u8],
148 ) -> Result<(), Nrf24Error<SPI::Error, DO::Error>> {
149 self._buf[0] = command | commands::W_REGISTER;
150 let buf_len = buf.len();
151 self._buf[1..(buf_len + 1)].copy_from_slice(&buf[..buf_len]);
152 self.spi_transfer(buf_len as u8 + 1)
153 }
154
155 fn toggle_features(&mut self) -> Result<(), Nrf24Error<SPI::Error, DO::Error>> {
158 self._buf[0] = commands::ACTIVATE;
159 self._buf[1] = 0x73;
160 self.spi_transfer(2)
161 }
162
163 pub fn is_plus_variant(&self) -> bool {
168 self._feature.is_plus_variant()
169 }
170
171 pub fn rpd(&mut self) -> Result<bool, Nrf24Error<SPI::Error, DO::Error>> {
172 self.spi_read(1, registers::RPD)?;
173 Ok(self._buf[1] & 1 == 1)
174 }
175
176 pub fn start_carrier_wave(
177 &mut self,
178 level: PaLevel,
179 channel: u8,
180 ) -> Result<(), Nrf24Error<SPI::Error, DO::Error>> {
181 self.as_tx()?;
182 self.spi_read(1, registers::RF_SETUP)?;
183 self.spi_write_byte(registers::RF_SETUP, self._buf[1] | 0x90)?;
184 if self._feature.is_plus_variant() {
185 self.set_auto_ack(false)?;
186 self.set_auto_retries(0, 0)?;
187 let buf = [0xFF; 32];
188
189 self.spi_write_buf(registers::TX_ADDR, &buf[..5])?;
192 self.flush_tx()?; self.spi_write_buf(commands::W_TX_PAYLOAD, &buf)?;
195
196 self.set_crc_length(CrcLength::Disabled)?;
197 }
198 self.set_pa_level(level)?;
199 self.set_channel(channel)?;
200 self.ce_pin.set_high().map_err(Nrf24Error::Gpo)?;
201 if self._feature.is_plus_variant() {
202 self._delay_impl.delay_ns(1000000); self.rewrite()?;
204 }
205 Ok(())
206 }
207
208 pub fn stop_carrier_wave(&mut self) -> Result<(), Nrf24Error<SPI::Error, DO::Error>> {
209 self.power_down()?; self.spi_read(1, registers::RF_SETUP)?;
217 self.spi_write_byte(registers::RF_SETUP, self._buf[1] & !0x90)?;
218 self.ce_pin.set_low().map_err(Nrf24Error::Gpo)
219 }
220
221 pub fn set_lna(&mut self, enable: bool) -> Result<(), Nrf24Error<SPI::Error, DO::Error>> {
230 self.spi_read(1, registers::RF_SETUP)?;
231 let out = self._buf[1] & !1 | enable as u8;
232 self.spi_write_byte(registers::RF_SETUP, out)
233 }
234}
235
236#[cfg(test)]
239mod test {
240 extern crate std;
241 use super::{commands, registers, RF24};
242 use crate::radio::rf24::mnemonics;
243 use crate::spi_test_expects;
244 use embedded_hal_mock::eh1::delay::NoopDelay;
245 use embedded_hal_mock::eh1::digital::{
246 Mock as PinMock, State as PinState, Transaction as PinTransaction,
247 };
248 use embedded_hal_mock::eh1::spi::{Mock as SpiMock, Transaction as SpiTransaction};
249 use std::vec;
250
251 #[test]
252 pub fn test_rpd() {
253 let pin_expectations = [];
255 let mut pin_mock = PinMock::new(&pin_expectations);
256
257 let delay_mock = NoopDelay::new();
259
260 let spi_expectations = spi_test_expects![
261 (vec![registers::RPD, 0u8], vec![0xEu8, 0xFFu8]),
263 ];
264 let mut spi_mock = SpiMock::new(&spi_expectations);
265 let mut radio = RF24::new(pin_mock.clone(), spi_mock.clone(), delay_mock);
266 assert!(radio.rpd().unwrap());
267 spi_mock.done();
268 pin_mock.done();
269 }
270
271 pub fn start_carrier_wave_parametrized(is_plus_variant: bool) {
272 let mut pin_expectations = [
274 PinTransaction::set(PinState::Low),
275 PinTransaction::set(PinState::High),
276 ]
277 .to_vec();
278 if is_plus_variant {
279 pin_expectations.extend([
280 PinTransaction::set(PinState::Low),
281 PinTransaction::set(PinState::High),
282 ]);
283 }
284
285 let mut pin_mock = PinMock::new(&pin_expectations);
286
287 let delay_mock = NoopDelay::new();
289
290 let mut buf = [0xFFu8; 33];
291 buf[0] = commands::W_TX_PAYLOAD;
292 let mut address = [0xFFu8; 6];
293 address[0] = registers::TX_ADDR | commands::W_REGISTER;
294
295 let mut spi_expectations = spi_test_expects![
296 (
299 vec![registers::CONFIG | commands::W_REGISTER, 0xCu8],
300 vec![0xEu8, 0u8],
301 ),
302 (vec![registers::EN_RXADDR, 0u8], vec![0xEu8, 0u8]),
304 (
305 vec![registers::EN_RXADDR | commands::W_REGISTER, 1u8],
306 vec![0xEu8, 0u8],
307 ),
308 (vec![registers::RF_SETUP, 0u8], vec![0xEu8, 0u8]),
310 (
311 vec![registers::RF_SETUP | commands::W_REGISTER, 0x90u8],
312 vec![0xEu8, 0u8],
313 ),
314 ]
315 .to_vec();
316 if is_plus_variant {
317 spi_expectations.extend(spi_test_expects![
318 (
320 vec![registers::EN_AA | commands::W_REGISTER, 0u8],
321 vec![0xEu8, 0u8],
322 ),
323 (
325 vec![registers::SETUP_RETR | commands::W_REGISTER, 0u8],
326 vec![0xEu8, 0u8],
327 ),
328 (address.to_vec(), vec![0u8; 6]),
330 (vec![commands::FLUSH_TX], vec![0xEu8]),
332 (buf.to_vec(), vec![0u8; 33]),
334 (vec![registers::CONFIG, 0u8], vec![0xEu8, 0xCu8]),
336 (
337 vec![registers::CONFIG | commands::W_REGISTER, 0u8],
338 vec![0xEu8, 0u8],
339 ),
340 ]);
341 }
342 spi_expectations.extend(spi_test_expects![
343 (vec![registers::RF_SETUP, 0u8], vec![0xEu8, 0x91u8]),
346 (
347 vec![registers::RF_SETUP | commands::W_REGISTER, 0x97u8],
348 vec![0xEu8, 0u8],
349 ),
350 (
352 vec![registers::RF_CH | commands::W_REGISTER, 125u8],
353 vec![0xEu8, 0u8],
354 ),
355 ]);
356 if is_plus_variant {
357 spi_expectations.extend(spi_test_expects![
358 (
360 vec![
361 registers::STATUS | commands::W_REGISTER,
362 mnemonics::MASK_MAX_RT | mnemonics::MASK_TX_DS,
363 ],
364 vec![0xEu8, 0u8],
365 ),
366 (vec![commands::REUSE_TX_PL], vec![0xEu8]),
368 ]);
369 }
370
371 let mut spi_mock = SpiMock::new(&spi_expectations);
372 let mut radio = RF24::new(pin_mock.clone(), spi_mock.clone(), delay_mock);
373 radio._feature = radio._feature.with_is_plus_variant(is_plus_variant);
374 radio.start_carrier_wave(crate::PaLevel::Max, 0xFF).unwrap();
375 spi_mock.done();
376 pin_mock.done();
377 }
378
379 #[test]
380 fn start_carrier_wave_plus_variant() {
381 start_carrier_wave_parametrized(true);
382 }
383
384 #[test]
385 fn start_carrier_wave_non_plus_variant() {
386 start_carrier_wave_parametrized(false);
387 }
388
389 #[test]
390 pub fn stop_carrier_wave() {
391 let pin_expectations = [
393 PinTransaction::set(PinState::Low),
394 PinTransaction::set(PinState::Low),
397 ];
398 let mut pin_mock = PinMock::new(&pin_expectations);
399
400 let delay_mock = NoopDelay::new();
402
403 let spi_expectations = spi_test_expects![
404 (
406 vec![registers::CONFIG | commands::W_REGISTER, 0xCu8],
407 vec![0xEu8, 0u8],
408 ),
409 (vec![registers::RF_SETUP, 0u8], vec![0xEu8, 0x90u8]),
411 (
412 vec![registers::RF_SETUP | commands::W_REGISTER, 0u8],
413 vec![0xEu8, 0u8],
414 ),
415 ];
416 let mut spi_mock = SpiMock::new(&spi_expectations);
417 let mut radio = RF24::new(pin_mock.clone(), spi_mock.clone(), delay_mock);
418 radio.stop_carrier_wave().unwrap();
419 spi_mock.done();
420 pin_mock.done();
421 }
422
423 #[test]
424 pub fn set_lna() {
425 let pin_expectations = [];
427 let mut pin_mock = PinMock::new(&pin_expectations);
428
429 let delay_mock = NoopDelay::new();
431
432 let spi_expectations = spi_test_expects![
433 (vec![registers::RF_SETUP, 0u8], vec![0xEu8, 1u8]),
435 (
436 vec![registers::RF_SETUP | commands::W_REGISTER, 0u8],
437 vec![0xEu8, 0u8],
438 ),
439 ];
440 let mut spi_mock = SpiMock::new(&spi_expectations);
441 let mut radio = RF24::new(pin_mock.clone(), spi_mock.clone(), delay_mock);
442 radio.set_lna(false).unwrap();
443 spi_mock.done();
444 pin_mock.done();
445 }
446}