embedded_nrf24l01_async/
lib.rs

1// Copyright 2018, Astro <astro@spaceboyz.net>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE>. This file
4// may not be copied, modified, or distributed except according to
5// those terms.
6
7//! nRF24L01+ driver for use with [embedded-hal](https://crates.io/crates/embedded-hal)
8
9#![warn(missing_docs, unused)]
10#![allow(async_fn_in_trait)]
11
12#![no_std]
13#[macro_use]
14extern crate bitfield;
15
16use core::fmt;
17use core::fmt::Debug;
18use embedded_hal_async::spi::SpiDevice;
19use embedded_hal::digital::OutputPin;
20
21mod config;
22pub use crate::config::{Configuration, CrcMode, DataRate};
23pub mod setup;
24
25mod registers;
26use crate::registers::{Config, Register, SetupAw, Status, Feature};
27mod command;
28use crate::command::{Command, ReadRegister, WriteRegister};
29mod payload;
30pub use crate::payload::Payload;
31mod error;
32pub use crate::error::Error;
33
34mod device;
35pub use crate::device::Device;
36mod standby;
37pub use crate::standby::StandbyMode;
38mod rx;
39pub use crate::rx::RxMode;
40mod tx;
41pub use crate::tx::TxMode;
42
43/// Number of RX pipes with configurable addresses
44pub const PIPES_COUNT: usize = 6;
45/// Minimum address length
46pub const MIN_ADDR_BYTES: usize = 2;
47/// Maximum address length
48pub const MAX_ADDR_BYTES: usize = 5;
49
50/// Driver for the nRF24L01+
51///
52/// Never deal with this directly. Instead, you store one of the following types:
53///
54/// * [`StandbyMode<D>`](struct.StandbyMode.html)
55/// * [`RxMode<D>`](struct.RxMode.html)
56/// * [`TxMode<D>`](struct.TxMode.html)
57///
58/// where `D: `[`Device`](trait.Device.html)
59pub struct NRF24L01<E: Debug, CE: OutputPin<Error = E>, SPI: SpiDevice<u8>> {
60    ce: CE,
61    /// 核心对象spi
62    pub spi: SPI,
63    config: Config,
64}
65
66impl<E: Debug, CE: OutputPin<Error = E>, SPI: SpiDevice<u8, Error = SPIE>, SPIE: Debug> fmt::Debug
67    for NRF24L01<E, CE, SPI>
68{
69    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
70        write!(f, "NRF24L01")
71    }
72}
73
74impl<E: Debug, CE: OutputPin<Error = E>, SPI: SpiDevice<u8, Error = SPIE>, SPIE: Debug>
75    NRF24L01<E, CE, SPI>
76{
77    /// Construct a new driver instance.
78    pub async fn new(mut ce: CE, spi: SPI) -> Result<StandbyMode<Self>, Error<SPIE>> {
79        ce.set_low().unwrap();
80
81        // Reset value
82        let mut config = Config(0b0000_1000);
83        config.set_mask_rx_dr(false);
84        config.set_mask_tx_ds(false);
85        config.set_mask_max_rt(false);
86        let mut device = NRF24L01 {
87            ce,
88            spi,
89            config,
90        };
91
92        match device.is_connected().await {
93            Err(e) => return Err(e),
94            Ok(false) => return Err(Error::NotConnected),
95            _ => {}
96        }
97
98        // Enable features
99        let mut features = Feature(0);
100        features.set_en_dyn_ack(true);
101        features.set_en_dpl(true);
102        device.write_register(features).await?;
103
104        StandbyMode::power_up(device).await.map_err(|(_, e)| e)
105    }
106
107    /// Reads and validates content of the `SETUP_AW` register.
108    pub async fn is_connected(&mut self) -> Result<bool, Error<SPIE>> {
109        let (_, setup_aw) = self.read_register::<SetupAw>().await?;
110        let valid = setup_aw.aw() <= 3;
111        Ok(valid)
112    }
113}
114
115impl<E: Debug, CE: OutputPin<Error = E>, SPI: SpiDevice<u8, Error = SPIE>, SPIE: Debug> Device
116    for NRF24L01<E, CE, SPI>
117{
118    type Error = Error<SPIE>;
119
120    fn ce_enable(&mut self) {
121        self.ce.set_high().unwrap();
122    }
123
124    fn ce_disable(&mut self) {
125        self.ce.set_low().unwrap();
126    }
127
128    async fn send_command<C: Command>(
129        &mut self,
130        command: &C,
131    ) -> Result<(Status, C::Response), Self::Error> {
132        // Allocate storage
133        let mut buf_storage = [0; 256];
134        let len = command.len();
135        let buf = &mut buf_storage[0..len];
136        // Serialize the command
137        command.encode(buf);
138
139        // SPI transaction
140        self.spi.transfer_in_place(buf).await.expect("TODO: panic message");
141
142        // Parse response
143        let status = Status(buf[0]);
144        let response = C::decode_response(buf);
145        // defmt::info!("send_command status: {:02X} _ {:08b}", status.0, status.0);
146        Ok((status, response))
147    }
148
149    async fn write_register<R: Register>(&mut self, register: R) -> Result<Status, Self::Error> {
150        let (status, ()) = self.send_command(&WriteRegister::new(register)).await?;
151        Ok(status)
152    }
153
154    async fn read_register<R: Register>(&mut self) -> Result<(Status, R), Self::Error> {
155        self.send_command(&ReadRegister::new()).await
156    }
157
158    async fn update_config<F, R>(&mut self, f: F) -> Result<R, Self::Error>
159    where
160        F: FnOnce(&mut Config) -> R,
161    {
162        // Mutate
163        let old_config = self.config.clone();
164        let result = f(&mut self.config);
165
166        if self.config != old_config {
167            let config = self.config.clone();
168            self.write_register(config).await?;
169        }
170        Ok(result)
171    }
172}