bme280/
spi.rs

1//! BME280 driver for sensors attached via SPI.
2
3#[cfg(feature = "async")]
4use core::future::Future;
5#[cfg(feature = "sync")]
6use embedded_hal::delay::DelayNs;
7#[cfg(feature = "sync")]
8use embedded_hal::spi::SpiDevice;
9#[cfg(feature = "async")]
10use embedded_hal_async::delay::DelayNs as AsyncDelayNs;
11#[cfg(feature = "async")]
12use embedded_hal_async::spi::SpiDevice as AsyncSpiDevice;
13
14#[cfg(feature = "async")]
15use super::{AsyncBME280Common, AsyncInterface};
16#[cfg(feature = "sync")]
17use super::{BME280Common, Interface};
18use super::{
19    Configuration, Error, IIRFilter, Measurements, Oversampling, BME280_H_CALIB_DATA_LEN,
20    BME280_P_T_CALIB_DATA_LEN, BME280_P_T_H_DATA_LEN,
21};
22
23/// Representation of a BME280
24#[maybe_async_cfg::maybe(
25    sync(
26        feature = "sync",
27        self = "BME280",
28        idents(
29            AsyncBME280Common(sync = "BME280Common"),
30            AsyncSPIInterface(sync = "SPIInterface"),
31        )
32    ),
33    async(feature = "async", keep_self)
34)]
35#[derive(Debug, Default)]
36pub struct AsyncBME280<SPI> {
37    common: AsyncBME280Common<AsyncSPIInterface<SPI>>,
38}
39
40#[maybe_async_cfg::maybe(
41    sync(
42        feature = "sync",
43        self = "BME280",
44        idents(
45            AsyncSpiDevice(sync = "SpiDevice"),
46            AsyncSpiBus(sync = "SpiBus"),
47            AsyncSPIInterface(sync = "SPIInterface"),
48            AsyncDelayNs(sync = "DelayNs"),
49            AsyncBME280Common(sync = "BME280Common"),
50        )
51    ),
52    async(feature = "async", keep_self)
53)]
54impl<SPI, SPIE> AsyncBME280<SPI>
55where
56    SPI: AsyncSpiDevice<Error = SPIE>,
57    // SPI::Buf: AsyncSpiBus<u8>,
58{
59    /// Create a new BME280 struct
60    pub fn new(spi: SPI) -> Result<Self, Error<SPIError<SPIE>>> {
61        Ok(Self {
62            common: AsyncBME280Common {
63                interface: AsyncSPIInterface { spi },
64                calibration: None,
65            },
66        })
67    }
68
69    /// Initializes the BME280.
70    /// This configures 2x temperature oversampling, 16x pressure oversampling, and the IIR filter
71    /// coefficient 16.
72    pub async fn init<D: AsyncDelayNs>(
73        &mut self,
74        delay: &mut D,
75    ) -> Result<(), Error<SPIError<SPIE>>> {
76        self.common
77            .init(
78                delay,
79                Configuration::default()
80                    .with_humidity_oversampling(Oversampling::Oversampling1X)
81                    .with_pressure_oversampling(Oversampling::Oversampling16X)
82                    .with_temperature_oversampling(Oversampling::Oversampling2X)
83                    .with_iir_filter(IIRFilter::Coefficient16),
84            )
85            .await
86    }
87
88    /// Initializes the BME280, applying the given configuration.
89    pub async fn init_with_config<D: AsyncDelayNs>(
90        &mut self,
91        delay: &mut D,
92        config: Configuration,
93    ) -> Result<(), Error<SPIError<SPIE>>> {
94        self.common.init(delay, config).await
95    }
96
97    /// Captures and processes sensor data for temperature, pressure, and humidity
98    pub async fn measure<D: AsyncDelayNs>(
99        &mut self,
100        delay: &mut D,
101    ) -> Result<Measurements<SPIError<SPIE>>, Error<SPIError<SPIE>>> {
102        self.common.measure(delay).await
103    }
104}
105
106/// Register access functions for SPI
107#[maybe_async_cfg::maybe(
108    sync(feature = "sync", self = "SPIInterface",),
109    async(feature = "async", keep_self)
110)]
111#[derive(Debug, Default)]
112struct AsyncSPIInterface<SPI> {
113    /// concrete SPI device implementation
114    spi: SPI,
115}
116
117#[cfg(feature = "sync")]
118impl<SPI> Interface for SPIInterface<SPI>
119where
120    SPI: SpiDevice,
121    // SPI::Buf: SpiBus<u8>,
122{
123    type Error = SPIError<SPI::Error>;
124
125    fn read_register(&mut self, register: u8) -> Result<u8, Error<Self::Error>> {
126        let mut result = [0u8];
127        self.read_any_register(register, &mut result)?;
128        Ok(result[0])
129    }
130
131    fn read_data(
132        &mut self,
133        register: u8,
134    ) -> Result<[u8; BME280_P_T_H_DATA_LEN], Error<Self::Error>> {
135        let mut data = [0; BME280_P_T_H_DATA_LEN];
136        self.read_any_register(register, &mut data)?;
137        Ok(data)
138    }
139
140    fn read_pt_calib_data(
141        &mut self,
142        register: u8,
143    ) -> Result<[u8; BME280_P_T_CALIB_DATA_LEN], Error<Self::Error>> {
144        let mut data = [0; BME280_P_T_CALIB_DATA_LEN];
145        self.read_any_register(register, &mut data)?;
146        Ok(data)
147    }
148
149    fn read_h_calib_data(
150        &mut self,
151        register: u8,
152    ) -> Result<[u8; BME280_H_CALIB_DATA_LEN], Error<Self::Error>> {
153        let mut data = [0; BME280_H_CALIB_DATA_LEN];
154        self.read_any_register(register, &mut data)?;
155        Ok(data)
156    }
157
158    fn write_register(&mut self, register: u8, payload: u8) -> Result<(), Error<Self::Error>> {
159        // If the first bit is 0, the register is written.
160        let transfer = [register & 0x7f, payload];
161        self.spi
162            .transfer(&mut [], &transfer)
163            .map_err(|e| Error::Bus(SPIError::SPI(e)))?;
164        Ok(())
165    }
166}
167
168#[cfg(feature = "async")]
169impl<SPI> AsyncInterface for AsyncSPIInterface<SPI>
170where
171    SPI: AsyncSpiDevice,
172    // SPI::Buf: AsyncSpiBus<u8>,
173{
174    type Error = SPIError<SPI::Error>;
175
176    type ReadRegisterFuture<'a> = impl Future<Output = Result<u8, Error<Self::Error>>>
177    where
178        SPI: 'a;
179    fn read_register(&mut self, register: u8) -> Self::ReadRegisterFuture<'_> {
180        async move {
181            let mut result = [0u8];
182            self.read_any_register(register, &mut result).await?;
183            Ok(result[0])
184        }
185    }
186
187    type ReadDataFuture<'a> = impl Future<Output = Result<[u8; BME280_P_T_H_DATA_LEN], Error<Self::Error>>>
188    where
189        SPI: 'a;
190    fn read_data(&mut self, register: u8) -> Self::ReadDataFuture<'_> {
191        async move {
192            let mut data = [0; BME280_P_T_H_DATA_LEN];
193            self.read_any_register(register, &mut data).await?;
194            Ok(data)
195        }
196    }
197
198    type ReadPtCalibDataFuture<'a> = impl Future<Output = Result<[u8; BME280_P_T_CALIB_DATA_LEN], Error<Self::Error>>>
199    where
200        SPI: 'a;
201    fn read_pt_calib_data(&mut self, register: u8) -> Self::ReadPtCalibDataFuture<'_> {
202        async move {
203            let mut data = [0; BME280_P_T_CALIB_DATA_LEN];
204            self.read_any_register(register, &mut data).await?;
205            Ok(data)
206        }
207    }
208
209    type ReadHCalibDataFuture<'a> = impl Future<Output = Result<[u8; BME280_H_CALIB_DATA_LEN], Error<Self::Error>>>
210    where
211        SPI: 'a;
212    fn read_h_calib_data(&mut self, register: u8) -> Self::ReadHCalibDataFuture<'_> {
213        async move {
214            let mut data = [0; BME280_H_CALIB_DATA_LEN];
215            self.read_any_register(register, &mut data).await?;
216            Ok(data)
217        }
218    }
219
220    type WriteRegisterFuture<'a> = impl Future<Output = Result<(), Error<Self::Error>>>
221    where
222        SPI: 'a;
223    fn write_register(&mut self, register: u8, payload: u8) -> Self::WriteRegisterFuture<'_> {
224        async move {
225            // If the first bit is 0, the register is written.
226            let transfer = [register & 0x7f, payload];
227            self.spi
228                .transfer(&mut [], &transfer)
229                .await
230                .map_err(|e| Error::Bus(SPIError::SPI(e)))?;
231            Ok(())
232        }
233    }
234}
235
236#[maybe_async_cfg::maybe(
237    sync(
238        feature = "sync",
239        self = "SPIInterface",
240        idents(AsyncSpiDevice(sync = "SpiDevice"), AsyncSpiBus(sync = "SpiBus"),)
241    ),
242    async(feature = "async", keep_self)
243)]
244impl<SPI> AsyncSPIInterface<SPI>
245where
246    SPI: AsyncSpiDevice,
247    // SPI::Buf: AsyncSpiBus<u8>,
248{
249    async fn read_any_register(
250        &mut self,
251        register: u8,
252        data: &mut [u8],
253    ) -> Result<(), Error<SPIError<SPI::Error>>> {
254        self.spi
255            .transfer(data, &[register])
256            .await
257            .map_err(|e| Error::Bus(SPIError::SPI(e)))?;
258        Ok(())
259    }
260}
261
262/// Error which occurred during an SPI transaction
263#[derive(Clone, Copy, Debug)]
264pub enum SPIError<SPIE> {
265    /// The SPI implementation returned an error
266    SPI(SPIE),
267}