nrf24radio/
lib.rs

1//! NRF24L01(+) no-std multi-level device driver for executor agnostic embedded `Rust`.
2//! 
3//! What do each of these mean:
4//!   - NRF24L01(+) : Works with both the NRF24L01 and NRF24L01+ devices.
5//!   - No std : The driver works in all embedded environments.
6//!   - Multi-level : The driver exposes both a low level and a high level API.
7//!   - Executor agnostic : The driver does not depend on a specific executor.
8
9
10
11#![no_std]
12
13#![feature(let_chains)]
14#![feature(const_mut_refs)]
15#![feature(inherent_associated_types)]
16
17
18
19pub mod common;
20pub mod pipe;
21
22
23
24mod config;
25mod error;
26mod state;
27
28
29
30pub use config::*;
31
32pub use error::*;
33
34pub use state::*;
35
36
37
38use common::*;
39
40use embedded_hal::digital::OutputPin;
41
42use embedded_hal_async::{
43    digital::Wait,
44    spi::SpiDevice,
45};
46
47
48
49/// Global garbage buffer.
50/// This buffer is used by all drivers to dump garbage data or flush caches.
51/// Data races don't matter because this is garbage data.
52#[link_section = ".uninit.NRF24RADIO.scratch"]
53static mut SCRATCH: [u8; 33] = [0u8; 33];
54
55
56
57/// TODO : Make pipes optional to allow for lower memory footprint.
58/// TODO : Improve (optional) logging in all methods.
59/// TODO : Enforce correct pipe configurations (TX == RX0) (TX == DYN & AA).
60pub struct Driver<SPI, CE, IRQ> {
61    /// The SPI interface to the NRF24 device.
62    spi: SPI,
63
64    /// The CE pin output to the NRF24 device.
65    ce: CE,
66
67    /// Optional IRQ pin to wait for device events.
68    /// This is set optional to facilitate using the driver in low pin count
69    /// devices, altoug the performance and power consumption of the driver
70    /// will worsen if this pin is not provided.
71    irq: Option<IRQ>,
72
73    /// Current state of the device.
74    state: State,
75
76    /// Current configuration of the device.
77    #[allow(dead_code)]
78    config: Config,
79
80    /// References to the RX pipes' buffers.
81    /// The buffers must be static to be able to use them from different tasks.
82    /// Synchronization is handled internally by the driver.
83    rxpipes: [&'static mut pipe::DataPipe; 6],
84
85    /// Reference to the TX pipe buffer.
86    /// The buffers must be static to be able to use them from different tasks.
87    /// Synchronization is handled internally by the driver.
88    txpipe: &'static mut pipe::DataPipe,
89}
90
91
92/// Common high level method for general use of NRF24L01(+) devices.
93/// Creating / Configuring the driver.
94impl<SPI: SpiDevice, CE: OutputPin, IRQ: Wait> Driver<SPI, CE, IRQ> {
95    /// Common error type emitted by this driver.
96    pub type Error = (Error, Option<HardwareError<SPI::Error, CE::Error, IRQ::Error>>);
97
98    /// Creates a new NRF24L01(+) driver.
99    pub async fn create(mut spi: SPI, mut ce: CE, irq: Option<IRQ>, rxpipes: [&'static mut pipe::DataPipe; 6], txpipe: &'static mut pipe::DataPipe) -> Result<Self, Self::Error> {
100        // Disable CE.
101        if let Err( hwe ) = ce.set_low() {
102            return Err( (Error::FailedDriverCreation, Some( HardwareError::ChipEnable(hwe) )) );
103        }
104
105        // Clear PWR UP bit.
106        if let Err( hwe ) = spi.write( &[(1 << 5) | Register::Config as u8, 0b00001000] ).await {
107            return Err( (Error::FailedDriverCreation, Some( HardwareError::Serial(hwe) )) );
108        }
109
110        // Flush RX FIFO.
111        if let Err( hwe ) = spi.write( &[Command::FlushRX as u8] ).await {
112            return Err( (Error::FailedDriverCreation, Some( HardwareError::Serial(hwe) )) );
113        }
114
115        // Flush TX FIFO.
116        if let Err( hwe ) = spi.write( &[Command::FlushTX as u8] ).await {
117            return Err( (Error::FailedDriverCreation, Some( HardwareError::Serial(hwe) )) );
118        }
119
120        Ok( Self {
121            spi,
122            ce,
123            irq,
124            state: State::PowerDown,
125            config: Config::new(),
126            rxpipes,
127            txpipe,
128        })
129    }
130
131    /// Configures the nRF24L01(+) device driver.
132    pub async fn configure(&mut self, config: Config) -> Result<(), Self::Error> {
133        // Set to at least standby.
134        if (self.state == State::Transmitting) || (self.state == State::Receiving) {
135            self.standby().await?;
136        }
137
138        // Enable all features (can go unused).
139        if let Err( hwe ) = self.writereg(Register::Features, 0b111).await {
140            return Err( (Error::FailedDriverConfiguration, Some(hwe)) )
141        }
142
143        // Create a buffer for address transmission.
144        let mut buf;
145
146        // Write the main address (Pipe 0).
147        buf = [(1 << 5) | Register::RX0Address as u8, config.main[4], config.main[3], config.main[2], config.main[1], config.main[0]];
148
149        if let Err( hwe ) = self.writebuf( &buf ).await {
150            return Err( (Error::FailedDriverConfiguration, Some(hwe)) )
151        }
152
153        // Write the main address (TX Pipe).
154        buf[0] = (1 << 5) | Register::TXAddress as u8;
155
156        if let Err( hwe ) = self.writebuf( &buf ).await {
157            return Err( (Error::FailedDriverConfiguration, Some(hwe)) )
158        }
159
160        // Write the base address with Pipe 1.
161        buf = [(1 << 5) | Register::RX1Address as u8, config.sub[0], config.base[3], config.base[2], config.base[1], config.base[0]];
162
163        if let Err( hwe ) = self.writebuf( &buf ).await {
164            return Err( (Error::FailedDriverConfiguration, Some(hwe)) )
165        }
166
167        // Write all the sub-addresses.
168        let regs = [Register::RX2Address, Register::RX3Address, Register::RX4Address, Register::RX5Address];
169        for (r, v) in regs.iter().zip( &config.sub[1..5] ) {
170            if let Err( hwe ) = self.writereg(r, *v).await {
171                return Err( (Error::FailedDriverConfiguration, Some(hwe)) )
172            }
173        }
174
175        // Configure the RF channel.
176        if let Err( hwe ) = self.writereg( Register::RFChannel, config.ch).await {
177            return Err( (Error::FailedDriverConfiguration, Some(hwe)) )
178        }
179
180        // Configure the RF power and data rate.
181        let mut rfsetup = 0;
182
183        match config.dr {
184            DataRate::High => rfsetup |= 1 << 3,
185            DataRate::Low  => rfsetup |= 1 << 5,
186            _ => (),
187        }
188
189        match config.gain {
190            Gain::Max  => rfsetup |= 0b110,
191            Gain::High => rfsetup |= 0b100,
192            Gain::Mid  => rfsetup |= 0b010,
193            _ => (),
194        }
195        
196        if let Err( hwe ) = self.writereg( Register::RFSetup, rfsetup).await {
197            return Err( (Error::FailedDriverConfiguration, Some(hwe)) )
198        }
199
200        // Configure the address width.
201        let aw = match config.aw {
202            0..=3 => 0b01,
203            4     => 0b10,
204            _     => 0b11,
205        };
206
207        if let Err( hwe ) = self.writereg( Register::AddressWidth, aw).await {
208            return Err( (Error::FailedDriverConfiguration, Some(hwe)) )
209        }
210
211        // Configure the CRC bytes.
212        let cfg = match config.crc {
213            CRCBytes::Two => 0b1100,
214            CRCBytes::One => 0b1000,
215            _             => 0b0000,
216        };
217
218        if let Err( hwe ) = self.writereg( Register::Config, cfg).await {
219            return Err( (Error::FailedDriverConfiguration, Some(hwe)) )
220        }
221
222        #[cfg(feature = "log")]
223        defmt::debug!("Finished driver configuration");
224
225        Ok( () )
226    }
227}
228
229
230/// High level methods to use the RX interface of NRF24L01(+) devices.
231/// Opening / Handling the RX pipes.
232impl<SPI: SpiDevice, CE: OutputPin, IRQ: Wait> Driver<SPI, CE, IRQ> {
233    /// Open the RX pipe with the given configuration.
234    /// WARNING : RX pipe 0 cannot be set as fixed size pipe.
235    pub async fn openrx(&mut self, n: u8, mut config: pipe::RXConfig) -> Result<pipe::RXDataPipe, Self::Error> {
236        use pipe::*;
237
238        // Validate the pipe number.
239        if n > 5 { return Err( ( Error::IllegalPipeNumber(n), None ) ) }
240
241        #[cfg(feature = "log")]
242        defmt::trace!("RX Driver : Pipe number validated");
243
244        // Check if the pipe is already open.
245        if self.rxpipes[n as usize].open() { return Err( ( Error::PipeCurrentlyUsed, None ) ) }
246
247        #[cfg(feature = "log")]
248        defmt::trace!("RX Driver : Pipe {} is open", n);
249
250        // If configuring pipe 0, reset to default.
251        if n == 0 { config = Default::default() }
252
253        // Read the DYNPD register.
254        let mut dynpd = match self.readreg( Register::DynamicPayload ).await {
255            Err(hwe) => return Err( ( Error::RXPipeCreationFailed(n), Some(hwe) ) ),
256            Ok(d) => d,
257        };
258
259        #[cfg(feature = "log")]
260        defmt::trace!("RX Driver : Read DYNPD register");
261
262        match config.size {
263            // Set fixed size payload.
264            PayloadSize::Fixed( size ) => {
265                // Set the payload size.
266                if let Err(hwe) = self.writereg(0x11 + (n as u8), size).await {
267                    return Err( ( Error::RXPipeCreationFailed(n), Some(hwe) ) )
268                }
269
270                // Clear dynamic payload.
271                dynpd &= !(1 << n);
272            },
273
274            // Set dynamic payload.
275            PayloadSize::Dynamic => dynpd |= 1 << n,
276        }
277
278        // Write the dynamic payload register.
279        if let Err(hwe) = self.writereg(Register::DynamicPayload, dynpd).await {
280            return Err( ( Error::RXPipeCreationFailed(n), Some(hwe) ) )
281        }
282
283        #[cfg(feature = "log")]
284        defmt::trace!("RX Driver : Configured DYNPD register");
285
286        // Read the AUTO ACK register.
287        let mut autoack = match self.readreg(Register::EnableAutoACK).await {
288            Err(hwe) => return Err( ( Error::RXPipeCreationFailed(n), Some(hwe) ) ),
289            Ok(a) => a,
290        };
291
292        #[cfg(feature = "log")]
293        defmt::trace!("RX Driver : Read auto-ACK register");
294
295        // Check if auto-ACK is enabled.
296        match config.ack {
297            false => autoack &= !(1 << n),
298            true  => autoack |=   1 << n ,
299        }
300
301        // Write the auto-ack register.
302        if let Err(hwe) = self.writereg(Register::EnableAutoACK, autoack).await {
303            return Err( ( Error::RXPipeCreationFailed(n), Some(hwe) ) )
304        }
305
306        #[cfg(feature = "log")]
307        defmt::trace!("RX Driver : Configured auto-ACK register");
308
309        // Read the EN RX register.
310        let enable = match self.readreg(Register::EnabledRXAddress).await {
311            Err(hwe) => return Err( ( Error::RXPipeCreationFailed(n), Some(hwe) ) ),
312            Ok(a) => a,
313        };
314
315        #[cfg(feature = "log")]
316        defmt::trace!("RX Driver : Read EN RX register");
317
318        // Write the EN RX register.
319        if let Err(hwe) = self.writereg(Register::EnableAutoACK, enable | (1 << n)).await {
320            return Err( ( Error::RXPipeCreationFailed(n), Some(hwe) ) )
321        }
322
323        // Set the driver flag on the pipe and open the pipe.
324        self.rxpipes[n as usize].driver = DriverState::Registered;
325        self.rxpipes[n as usize].pipestate = PipeState::Open;
326        self.rxpipes[n as usize].bufstate = BufferState::Empty;
327        self.rxpipes[n as usize].error = None;
328
329        #[cfg(feature = "log")]
330        defmt::debug!("RX Driver : RX Data pipe configured");
331
332        Ok( RXDataPipe::new( unsafe { &mut *(self.rxpipes[n as usize] as *mut _) } ) )
333    }
334
335    /// Attempts to send a payload. Returns the number of bytes sent in total.
336    /// This method may wait indefinitely if the TX pipe is dropped / crashes
337    /// or the SPI hardware fails.
338    pub async fn rxdata(&mut self, wait: bool) -> Result<Option<(u8, usize, bool)>, Self::Error> {
339        #[cfg(feature = "log")]
340        defmt::trace!("RX Driver : Setting RX Mode");
341
342        // Assert the RX mode. Would be NOOP if already in TX mode.
343        self.rxmode().await?;
344
345        #[cfg(feature = "log")]
346        defmt::trace!("RX Driver : Reached RX Mode");
347
348        // Read the status register to check if the RX DR IRQ is set.
349        let mut status = self.status(wait).await?;
350
351        #[cfg(feature = "log")]
352        defmt::trace!("RX Driver : Status {:b}", status);
353
354        // If the IRQ is not set return early.
355        if (status & (1 << 6)) == 0 { return Ok( None ) }
356
357        // Read the payload width.
358        let width = match self.pldwidth().await {
359            Err(hwe) => return Err( ( Error::UnknownPayloadWidth, Some(hwe) ) ),
360            Ok(w) => w,
361        };
362
363        #[cfg(feature = "log")]
364        defmt::trace!("RX Driver : Payload width {}", width);
365
366        // Get the pipe number.
367        let mut npipe = (status >> 1) & 0b111;
368
369        // If pipe number is bigger than 5 recheck the number.
370        if npipe > 5 {
371            #[cfg(feature = "log")]
372            defmt::warn!("RX Driver : Illegal pipe number. Reading again...");
373
374            // Reread status and validate.
375            status = self.status(false).await?;
376
377            // Get pipe number again.
378            npipe = (status >> 1) & 0b111;
379
380            // If the pipe number is wrong again abort.
381            if npipe > 5 {
382                #[cfg(feature = "log")]
383                defmt::error!("RX Driver : Illegal pipe number");
384
385                // Clear the IRQ.
386                let _ = self.clearirqs().await;
387
388                return Ok( None )
389            }
390        }
391
392        // Validate payload width.
393        if width > 32 { return Err( ( Error::RXOverflow, None ) ) }
394
395        #[cfg(feature = "log")]
396        defmt::debug!("RX Driver : Pipe {} has {} bytes", npipe, width);
397
398        // Create the write buffer.
399        let mut write = [0; 33];
400        write[0] = Command::ReadPayload as u8;
401
402        // Check the state of the pipe.
403        let read = match self.rxpipes[npipe as usize].pipestate {
404            PipeState::Open => match self.rxpipes[npipe as usize].bufstate {
405                BufferState::Empty => &mut self.rxpipes[npipe as usize].buf[0..=width as usize],
406                BufferState::Ready => unsafe { &mut SCRATCH[0..=width as usize] },
407            },
408
409            PipeState::Closed => unsafe { &mut SCRATCH[0..=width as usize] },
410        };
411
412        #[cfg(feature = "log")]
413        defmt::trace!("RX Driver : Submitting Read Payload command...");
414
415        // Read the data into the correct buffer.
416        if let Err( hwe ) = self.spi.transfer(read, &write[0..=width as usize]).await {
417            return Err( ( Error::FailedPacketDownload, Some( HardwareError::Serial(hwe) ) ) )
418        }
419
420        #[cfg(feature = "log")]
421        defmt::debug!("RX Driver : Read Payload command completed");
422
423        // Clear the IRQs.
424        let _ = self.clearirqs().await;
425
426        // Set the buffer as ready.
427        self.rxpipes[npipe as usize].valid = width as u8;
428        self.rxpipes[npipe as usize].bufstate = BufferState::Ready;
429
430        // If the pipe was closed, disable the pipe.
431        if self.rxpipes[npipe as usize].closed() {
432            #[cfg(feature = "log")]
433            defmt::warn!("RX Driver : Target pipe ({}) is closed. Disabling pipe on device", npipe);
434
435            // Read the enable register.
436            let enable = match self.readreg(Register::EnabledRXAddress).await {
437                Err(_) => return Ok( None ),
438                Ok(e) => e,
439            };
440
441            #[cfg(feature = "log")]
442            defmt::trace!("RX Driver : Read RX enable register");
443
444            // Write the modified register.
445            let _ = self.writereg(Register::EnabledRXAddress, enable & !(1 << npipe)).await;
446
447            #[cfg(feature = "log")]
448            defmt::trace!("RX Driver : Updated RX enable register");
449
450            // Return `None` because no open pipe was modified.
451            return Ok( None )
452        }
453
454        #[cfg(feature = "log")]
455        defmt::trace!("RX Driver : Checking for more data in FIFO");
456
457        // Check if there is more data in the FIFO.
458        let more = match self.statuses(false).await {
459            Ok([_, fifo]) => (fifo & 1) == 0,
460            Err(_) => false,
461        };
462
463        #[cfg(feature = "log")]
464        defmt::trace!("RX Driver : TX FIFO -> {}", more);
465
466        Ok( Some( (npipe, width as usize, more) ) )
467    }
468}
469
470
471/// High level methods to use the TX interface of NRF24L01(+) devices.
472/// Opening / Handling the TX pipe.
473impl<SPI: SpiDevice, CE: OutputPin, IRQ: Wait> Driver<SPI, CE, IRQ> {
474    /// Opens the TX pipe with the given configuration.
475    pub async fn opentx(&mut self, config: pipe::TXConfig) -> Result<pipe::TXDataPipe, Self::Error> {
476        use pipe::*;
477
478        // Check if the pipe is already open or registered.
479        if self.txpipe.open() { return Err( ( Error::PipeCurrentlyUsed, None ) ) }
480
481        // Create the SETUP RETR register.
482        let setup = (config.delay << 4) | (config.retries & 0xF);
483
484        #[cfg(feature = "log")]
485        defmt::trace!("TX Driver : Writing setup register ({:b})", setup);
486
487        // Write the SETUP RETR register.
488        if let Err( hwe ) = self.writereg(Register::SetupRetries, setup).await {
489            return Err( ( Error::TXPipeCreationFailed, Some(hwe) ) );
490        }
491
492        #[cfg(feature = "log")]
493        defmt::debug!("TX Driver : Wrote setup register ({:b})", setup);
494
495        #[cfg(feature = "log")]
496        defmt::trace!("TX Driver : Reading DYNPD register");
497
498        // Read the DYNPD register.
499        let dynpd = match self.readreg(Register::DynamicPayload).await {
500            Err(hwe) => return Err( ( Error::TXPipeCreationFailed, Some(hwe) ) ),
501            Ok(d) => d,
502        };
503
504        #[cfg(feature = "log")]
505        defmt::trace!("TX Driver : Read DYNPD register ({:b})", dynpd);
506
507        // Write the DYNPD register.
508        if let Err( hwe ) = self.writereg(Register::DynamicPayload, dynpd | 1).await {
509            return Err( ( Error::TXPipeCreationFailed, Some(hwe) ) );
510        }
511
512        #[cfg(feature = "log")]
513        defmt::debug!("TX Driver : Wrote DYNPD register ({:b})", dynpd | 1);
514
515        // Set the flags to open the pipe.
516        self.txpipe.driver = DriverState::Registered;
517        self.txpipe.pipestate = PipeState::Open;
518        self.txpipe.bufstate = BufferState::Empty;
519        self.txpipe.error = None;
520
521        #[cfg(feature = "log")]
522        defmt::debug!("TX Driver : TX Pipe is open");
523
524        // Create the TX pipe.
525        Ok( TXDataPipe::new( unsafe { &mut *(self.txpipe as *mut _) } ) )
526    }
527
528    /// Attempts to send a payload. Returns the number of bytes sent in total.
529    /// This method may wait indefinitely if the TX pipe is dropped / crashes
530    /// or the SPI hardware fails.
531    pub async fn txdata(&mut self, wait: bool) -> Result<Option<usize>, Self::Error> {
532        use pipe::*;
533
534        // Check that the TX pipe is open.
535        if self.txpipe.closed() { return Err( ( Error::PipeClosed, None ) ) }
536
537        // Check for data in the TX pipe.
538        match self.txpipe.bufstate {
539            // Wait for data to send.
540            BufferState::Empty if wait => if let Err( e ) = Watcher::new( &self.txpipe, BufferState::Ready ).await {
541                return Err( ( e, None ) )
542            },
543
544            // There is no data to send.
545            BufferState::Empty => return Ok( None ),
546
547            // There is data to send.
548            BufferState::Ready => (),
549        }
550
551        // Set the TX command.
552        self.txpipe.buf[0] = if self.txpipe.ack { Command::WritePayload as u8 } else { Command::WritePayloadNoAck as u8 };
553
554        // Assert the TX mode. Would be NOOP if already in TX mode.
555        if let Err( ( error, hwe ) ) = self.txmode().await {
556            // Write the error to the pipe.
557            self.txpipe.error = Some( error );
558
559            // Set the pipe as empty to release it.
560            self.txpipe.bufstate = BufferState::Empty;
561
562            // Report the error.
563            return Err( ( error, hwe ) );
564        }
565
566        // Flag to mark the first transaction.
567        let mut first = true;
568
569        // Byte counter.
570        let mut bytes = 0;
571
572        // Send all packets in the transaction, capture any errors.
573        let (error, hwe) = loop {
574            // Check if the pipe was dropped.
575            if self.txpipe.closed() { break (Error::PipeClosed, None) }
576
577            // Read the status registers.
578            if let Ok( [status, fifo] ) = self.statuses(!first).await {
579                // Check for a retry error.
580                if (status & (1 << 4)) != 0 { break (Error::MaxRetries, None) }
581
582                // Check if there are no more packets and the FIFO is empty.
583                if (self.txpipe.ntx == 0) && ((fifo & (1 << 4)) != 0) {
584                    // Set the empty flag to allow for the next packet.
585                    self.txpipe.bufstate = BufferState::Empty;
586
587                    // End the transaction.
588                    return Ok( Some(bytes) );
589                }
590
591                // Check if there is space in the FIFO and there are packets left.
592                if ((status & 1) == 0) && (self.txpipe.ntx > 0) && (self.txpipe.ready()) {
593                    // Only clear the TX DS IRQ when sending new data to avoid deadlocks.
594                    while let Err(_) = self.clearirq(false, true, false).await {}
595
596                    // Push the packet to the device.
597                    if let Err(e) = self.spi.write( &self.txpipe.buf[0..=self.txpipe.valid as usize] ).await {
598                        break ( Error::FailedPacketUpload, Some( HardwareError::Serial( e ) ) )
599                    }
600
601                    // Increment the byte counter.
602                    bytes += self.txpipe.valid as usize;
603
604                    // Decrement the counter of transactions.
605                    self.txpipe.ntx -= 1;
606
607                    // Sync to avoid the compiler reordering this read.
608                    core::sync::atomic::compiler_fence( core::sync::atomic::Ordering::SeqCst );
609
610                    // Set the empty flag to allow for the next packet.
611                    if self.txpipe.ntx > 0 { self.txpipe.bufstate = BufferState::Empty }
612
613                    // Clear the first packet flag.
614                    first = false;
615                }
616            }
617        };
618
619        // Cancel the transaction.
620        self.txcancel( Some(error) ).await;
621
622        Err( ( error, hwe ) )
623    }
624
625    /// Cancels an ongoing transaction and clears the TX pipe.
626    /// This method may wait indefinitely if the SPI hardware fails.
627    pub async fn txcancel(&mut self, error: Option<Error>) {
628        // Flush the TX FIFO.
629        while let Err(_) = self.command( Command::FlushTX ).await {}
630
631        // Clear all IRQs.
632        while let Err(_) = self.clearirqs().await {}
633
634        // Set the error in the pipe.
635        self.txpipe.error = error;
636
637        // Set the empty flag to allow for the next packet.
638        self.txpipe.bufstate = BufferState::Empty;
639    }
640}
641
642
643
644/// Intermediate methods for interacting with NRF24L01(+) devices.
645/// Reading specific registers, complex commands and routine interactions.
646impl<SPI: SpiDevice, CE: OutputPin, IRQ: Wait> Driver<SPI, CE, IRQ> {
647    /// Clears the given IRQs from the status register.
648    pub async fn clearirq(&mut self, rxdr: bool, txds: bool, retries: bool) -> Result<(), HardwareError<SPI::Error, CE::Error, IRQ::Error>> {
649        // Build the IRQ clear byte.
650        let mut irq = 0;
651
652        if retries { irq |= 1 << 4 }
653        if txds    { irq |= 1 << 5 }
654        if rxdr    { irq |= 1 << 6 }
655
656        // Write the register.
657        self.writereg(Register::Status, irq).await
658    }
659
660    /// Clears all IRQs from the status register.
661    pub async fn clearirqs(&mut self) -> Result<(), HardwareError<SPI::Error, CE::Error, IRQ::Error>> {
662        self.writereg(Register::Status, 0b111 << 4).await
663    }
664
665    /// Reads the payload width of the top level FIFO packet.
666    pub async fn pldwidth(&mut self) -> Result<u8, HardwareError<SPI::Error, CE::Error, IRQ::Error>> {
667        // Create the read buffer.
668        let mut read = [0; 2];
669
670        // Perform the SPI transfer.
671        self.spi.transfer(&mut read, &[Command::PayloadWidth as u8, 0]).await.map_err( HardwareError::Serial )?;
672
673        Ok( read[1] )
674    }
675
676    /// Reads the device's STATUS register.
677    /// If the wait flag is set the driver will wait for the IRQ pin to go low.
678    /// If the pin is not available, it will perform an immediate read.
679    pub async fn status(&mut self, wait: bool) -> Result<u8, Self::Error> {
680        // Wait if the flag is set and IRQ pin is available.
681        if wait && let Some(ref mut irq) = self.irq {
682            if let Err( hwe ) = irq.wait_for_low().await.map_err( HardwareError::Interrupt ) {
683                return Err( ( Error::CouldNotReadStatus, Some(hwe) ) );
684            }
685        }
686
687        // RX buffer.
688        let mut read = [0u8];
689
690        // Perform the SPI transfer.
691        if let Err( hwe ) = self.spi.transfer(&mut read, &[0xFF]).await {
692            return Err( ( Error::CouldNotReadStatus, Some( HardwareError::Serial(hwe) ) ) );
693        }
694
695        Ok( read[0] )
696    }
697
698    /// Reads the device's STATUS and FIFO STATUS registers.
699    /// If the wait flag is set the driver will wait for the IRQ pin to go low.
700    /// If the pin is not available, it will perform an immediate read.
701    pub async fn statuses(&mut self, wait: bool) -> Result<[u8; 2], Self::Error> {
702        // Wait if flag is set and IRQ pin is available.
703        if wait && let Some(ref mut irq) = self.irq {
704            if let Err( hwe ) = irq.wait_for_low().await.map_err( HardwareError::Interrupt ) {
705                return Err( ( Error::CouldNotReadStatus, Some(hwe) ) );
706            }
707        }
708
709        // Create the read buffer.
710        let mut read = [0; 2];
711
712        // Perform the SPI transfer.
713        if let Err( hwe ) = self.spi.transfer(&mut read, &[Register::FIFOStatus as u8, 0]).await {
714            return Err( ( Error::CouldNotReadStatus, Some( HardwareError::Serial(hwe) ) ) );
715        }
716
717        Ok( read )
718    }
719
720    /// Sets the device in a power down state.
721    /// In this state the device consumes the least energy but will take longer
722    /// to start transmitting or receiving.
723    pub async fn powerdown(&mut self) -> Result<(), Self::Error> {
724        // Return early if already in power down mode.
725        if self.state == State::PowerDown {
726            return Ok(())
727        }
728
729        // Check if in transmitting or receiving mode and disable CE.
730        if (self.state == State::Transmitting) || (self.state == State::Receiving) {
731            if let Err( hwe ) = self.ce.set_low().map_err( HardwareError::ChipEnable ) {
732                return Err( ( Error::FailedModeSet(State::Standby), Some(hwe) ) );
733            }
734
735            // Set state to standby.
736            self.state = State::Standby;
737        }
738
739        // Read the CONFIG register.
740        let config = match self.readreg(Register::Config).await {
741            Err( hwe ) => return Err( ( Error::FailedModeSet(State::PowerDown), Some(hwe) ) ),
742            Ok(c) => c,
743        };
744
745        // Write the CONFIG register, disable PWR UP bit.
746        if let Err( hwe ) = self.writereg(Register::Config, config & !(1 << 1)).await {
747            return Err( ( Error::FailedModeSet(State::PowerDown), Some(hwe) ) );
748        }
749
750        // Set the state.
751        self.state = State::PowerDown;
752
753        Ok( () )
754    }
755
756    /// Sets the device in a RX ready state.
757    /// In this state the device consumes the most energy but can begin
758    /// transmitting in less time than when in standby.
759    /// WARNING : The driver user must guarantee a delay depending on the mode
760    /// transition that happenned:
761    ///   - Standby     to RXMode : 130 microseconds
762    ///   - TXMode      to RXMode : 130 microseconds
763    ///   - Power down  to RXMode : 5 milliseconds
764    pub async fn rxmode(&mut self) -> Result<(), Self::Error> {
765        // Return early if already in TX mode.
766        if self.state == State::Receiving {
767            return Ok( () );
768        }
769
770        // Read the config register.
771        let mut config = match self.readreg( Register::Config ).await {
772            Err( hwe ) => return Err( (Error::FailedModeSet( State::Standby ), Some(hwe) ) ),
773            Ok( c ) => c
774        };
775
776        // Clear all bits but CRC configuration.
777        config &= 0b11 << 2;
778
779        // Set PWR UP bit. Set PRX bit. Mask TX and RT IRQs.
780        config |= (0b11 << 4) | (1 << 1) | 1;
781
782        // Write the CONFIG register.
783        if let Err( hwe ) = self.writereg( Register::Config, config ).await {
784            return Err( (Error::FailedModeSet( State::Standby ), Some(hwe) ) );
785        }
786
787        // Set the standby mode.
788        self.state = State::Standby;
789
790        // Enable CE output.
791        if let Err( hwe ) = self.ce.set_high().map_err( HardwareError::ChipEnable ) {
792            return Err( (Error::FailedModeSet( State::Receiving ), Some( hwe )) );
793        }
794
795        // Set the TX mode.
796        self.state = State::Receiving;
797
798        Ok( () )
799    }
800
801    /// Sets the device in a TX ready state.
802    /// In this state the device consumes the most energy but can begin
803    /// transmitting in less time than when in standby.
804    /// WARNING : The driver user must guarantee a delay depending on the mode
805    /// transition that happenned:
806    ///   - Standby     to TXMode : 130 microseconds
807    ///   - RXMode      to TXMode : 130 microseconds
808    ///   - Power down  to TXMode : 5 milliseconds
809    pub async fn txmode(&mut self) -> Result<(), Self::Error> {
810        // Return early if already in TX mode.
811        if self.state == State::Transmitting {
812            return Ok( () );
813        }
814
815        // Read the config register.
816        let mut config = match self.readreg( Register::Config ).await {
817            Err( hwe ) => return Err( (Error::FailedModeSet( State::Standby ), Some(hwe) ) ),
818            Ok( c ) => c
819        };
820
821        // Clear all bits but CRC configuration.
822        config &= 0b11 << 2;
823
824        // Set PWR UP bit. Mask RX IRQ.
825        config |= (1 << 6) | (1 << 1);
826
827        // Write the CONFIG register.
828        if let Err( hwe ) = self.writereg( Register::Config, config ).await {
829            return Err( (Error::FailedModeSet( State::Standby ), Some(hwe) ) );
830        }
831
832        // Set the standby mode.
833        self.state = State::Standby;
834
835        // Enable CE output.
836        if let Err( hwe ) = self.ce.set_high().map_err( HardwareError::ChipEnable ) {
837            return Err( (Error::FailedModeSet( State::Transmitting ), Some( hwe )) );
838        }
839
840        // Set the TX mode.
841        self.state = State::Transmitting;
842
843        Ok( () )
844    }
845
846    /// Sets the device in a standby state.
847    /// In this state the device consumes more energy than powered down but can
848    /// begin transmitting or receiving faster.
849    /// WARNING : The driver user must guarantee a delay depending on the mode
850    /// transition that happenned:
851    ///   - Power down  to Standby : 4.5 milliseconds
852    pub async fn standby(&mut self) -> Result<(), Self::Error> {
853        // Return early if already in standby mode.
854        if self.state == State::Standby{
855            return Ok( () );
856        }
857
858        // Check the state of the device.
859        match self.state {
860            // RX or TX mode.
861            State::Receiving | State::Transmitting => {
862                // Disable CE pin.
863                if let Err( hwe ) = self.ce.set_low().map_err( HardwareError::ChipEnable ) {
864                    return Err( (Error::FailedModeSet(State::Standby), Some(hwe) ) );
865                }
866
867                // Set the state.
868                self.state = State::Standby;
869
870                Ok(())
871            },
872
873            _ => {
874                // Read the config register.
875                let config = match self.readreg(Register::Config).await {
876                    Err( hwe ) => return Err( (Error::FailedModeSet(State::Standby), Some(hwe)) ),
877                    Ok(c) => c,
878                };
879
880                // Write the CONFIG register with enabled PWR UP bit.
881                if let Err( hwe ) = self.writereg(Register::Config, config | (1 << 1)).await {
882                    return Err( ( Error::FailedModeSet(State::Standby), Some(hwe) ) );
883                }
884
885                // Set the state.
886                self.state = State::Standby;
887
888                Ok( () )
889            },
890        }
891    }
892}
893
894
895
896/// Basic methods for interacting with the NRF24 device.
897/// Writing and reading buffers / commands / registers through SPI.
898impl<SPI: SpiDevice, CE: OutputPin, IRQ: Wait> Driver<SPI, CE, IRQ> {
899    /// Low level function to write a buffer to the device.
900    /// This function correlates to the `write` SPI function.
901    pub async fn writebuf(&mut self, buf: &[u8]) -> Result<(), HardwareError<SPI::Error, CE::Error, IRQ::Error>> {
902        self.spi.write(buf).await.map_err( HardwareError::Serial )
903    }
904
905    /// Low level function to write to a register.
906    pub async fn writereg<R: Into<u8>>(&mut self, r: R, v: u8) -> Result<(), HardwareError<SPI::Error, CE::Error, IRQ::Error>> {
907        // Create the command buffer.
908        let buf = [(1 << 5) | r.into(), v];
909
910        // Write to the register.
911        self.spi.write(&buf).await.map_err( HardwareError::Serial )
912    }
913
914    /// Low level function to read a register.
915    pub async fn readreg<R: Into<u8>>(&mut self, r: R) -> Result<u8, HardwareError<SPI::Error, CE::Error, IRQ::Error>> {
916        // Create the command buffer.
917        let write = [r.into(), 0x00];
918
919        // Create the receive buffer.
920        let mut read = [0u8; 2];
921
922        // Perform the transfer.
923        self.spi.transfer(&mut read, &write).await.map_err( HardwareError::Serial )?;
924
925        Ok( read[1] )
926    }
927
928    /// Low level function to send a 1 byte command.
929    pub async fn command(&mut self, c: Command) -> Result<(), HardwareError<SPI::Error, CE::Error, IRQ::Error>> {
930        self.spi.write(&[c.into()]).await.map_err( HardwareError::Serial )
931    }
932}
933
934
935
936impl<SPI, CE, IRQ> Drop for Driver<SPI, CE, IRQ> {
937    fn drop(&mut self) {
938        // Orphan all the data pipes.
939        self.txpipe.driver = DriverState::Orphaned;
940
941        for pipe in &mut self.rxpipes {
942            pipe.driver = DriverState::Orphaned;
943        }
944    }
945}