1#![no_std]
2
3pub mod config;
4pub mod register;
5pub mod bus;
6mod calibration;
7
8pub mod testing;
9
10use core::fmt::{Debug};
11use embedded_hal_async::delay::DelayNs;
12use embedded_hal_async::i2c::SevenBitAddress;
13use crate::bus::{Bus, I2c, Spi};
14use crate::calibration::CalibrationData;
15use crate::config::Configuration;
16use crate::register::{chip_id, data, err_reg, odr, osr, pwr_ctrl, status, InvalidRegisterField, Readable, Writable};
17
18const BMP390_CHIP_ID:u8 = 0x60;
19
20#[derive(Debug)]
21pub enum Bmp390Error<BusError> {
22 Bus(BusError),
23 NotConnected,
24 UnexpectedRegisterData(InvalidRegisterField),
25}
26
27type Bmp390Result<T, BusError> = Result<T, Bmp390Error<BusError>>;
28
29type Bmp390I2c<T> = Bmp390<I2c<T>>;
30type Bmp390Spi<T> = Bmp390<Spi<T>>;
31
32pub struct Bmp390<B> {
33 bus: B,
34 calibration_data: CalibrationData,
35}
36
37impl<T> Bmp390I2c<T>
38where
39 T: embedded_hal_async::i2c::I2c,
40 I2c<T>: Bus,
41{
42 pub async fn new_i2c<D: DelayNs>(
43 i2c: T,
44 address: SevenBitAddress,
45 config: Configuration,
46 delay: &mut D) -> Bmp390Result<Self, <I2c<T> as Bus>::Error> {
47 Self::new(I2c::new(i2c, address), config, delay).await
48 }
49}
50
51impl<T> Bmp390Spi<T>
52where
53 T: embedded_hal_async::spi::SpiDevice,
54 Spi<T>: Bus,
55{
56 pub async fn new_spi<D: DelayNs>(
57 spi: T,
58 config: Configuration,
59 delay: &mut D) -> Bmp390Result<Self, <Spi<T> as Bus>::Error> {
60 Self::new(Spi::new(spi), config, delay).await
61 }
62}
63
64impl<B> Bmp390<B>
65where
66 B: Bus,
67{
68 async fn probe_ready<D: DelayNs>(bus: &mut B, delay: &mut D, attempts: u32) -> Bmp390Result<(), B::Error> {
69 for _ in 0..attempts {
70 if let Ok(id) = bus.read::<register::chip_id::ChipId>().await {
71 if id == BMP390_CHIP_ID {
72 return Ok(())
73 }
74 }
75
76 delay.delay_ms(1).await;
77 }
78
79 Err(Bmp390Error::NotConnected)
80 }
81 async fn new<D: DelayNs>(mut bus: B, config: Configuration, delay: &mut D) -> Bmp390Result<Self, B::Error> {
82 Self::probe_ready(&mut bus, delay, 5).await?;
84
85 let calibration_data = CalibrationData::new(&mut bus).await?;
86
87 bus.write::<pwr_ctrl::PwrCtrl>(&pwr_ctrl::PwrCtrlCfg {
88 press_en: config.enable_pressure,
89 temp_en: config.enable_temperature,
90 mode: config.mode,
91 }).await?;
92
93 bus.write::<osr::Osr>(&osr::OsrCfg {
94 osr_p: config.pressure_oversampling,
95 osr_t: config.temperature_oversampling,
96 }).await?;
97
98 bus.write::<odr::Odr>(&odr::OdrCfg {
99 odr_sel: config.output_data_rate
100 }).await?;
101
102 bus.write::<register::config::Config>(®ister::config::ConfigFields {
103 iir_filter: config.iir_filter_coefficient
104 }).await?;
105
106 Ok(Bmp390 { bus, calibration_data })
107 }
108
109 pub async fn read<R: Readable>(&mut self) -> Result<R::Out, Bmp390Error<B::Error>> {
110 Ok(self.bus.read::<R>().await?)
111 }
112
113 pub async fn write<W: Writable>(&mut self, v: &W::In) -> Result<(), Bmp390Error<B::Error>> {
114 Ok(self.bus.write::<W>(v).await?)
115 }
116
117 pub async fn is_connected(&mut self) -> Bmp390Result<bool, B::Error> {
118 let id = self.bus.read::<chip_id::ChipId>().await?;
119
120 Ok(id == BMP390_CHIP_ID)
121 }
122
123 pub async fn error_flags(&mut self) -> Bmp390Result<err_reg::ErrorFlags, B::Error> {
127 Ok(self.bus.read::<err_reg::ErrReg>().await?)
128 }
129
130 pub async fn status(&mut self) -> Bmp390Result<status::StatusFlags, B::Error> {
132 Ok(self.bus.read::<status::Status>().await?)
133 }
134
135 pub async fn set_mode(&mut self, mode: pwr_ctrl::PowerMode) -> Bmp390Result<(), B::Error> {
156 let mut pwr_ctrl = self.bus.read::<pwr_ctrl::PwrCtrl>().await?;
157 pwr_ctrl.mode = mode;
158 self.bus.write::<pwr_ctrl::PwrCtrl>(&pwr_ctrl).await?;
159 Ok(())
160 }
161 pub async fn mode(&mut self) -> Bmp390Result<pwr_ctrl::PowerMode, B::Error> {
171 Ok(self.bus.read::<pwr_ctrl::PwrCtrl>().await?.mode)
172 }
173
174 pub async fn read_sensor_data(&mut self) -> Bmp390Result<Measurement, B::Error> {
187 let measurement = self.bus.read::<data::Data>().await?;
188
189 let compensated_temperature =
190 self.calibration_data.compensate_temperature(measurement.temperature);
191 let compensated_pressure =
192 self.calibration_data.compensate_pressure(measurement.pressure);
193
194 Ok(Measurement {
195 pressure: compensated_pressure,
196 temperature: compensated_temperature,
197 })
198 }
199
200
201}
202
203pub struct Measurement {
205 pub pressure: f32,
206 pub temperature: f32,
207}