Skip to main content

lps22df_rs/
driver.rs

1use super::{
2    BusOperation, DelayNs, I2c, RegisterOperation, SensorOperation, SevenBitAddress, SpiDevice,
3    bisync, i2c, prelude::*, spi,
4};
5
6use core::fmt::Debug;
7use core::marker::PhantomData;
8
9/// Driver for LPS22DF sensor.
10///
11/// The struct takes a bus to write to the registers.
12/// The bus is generalized over the BusOperation trait, allowing the use
13/// of I2C or SPI protocols; this also allows the user to implement sharing
14/// techniques to share the underlying bus.
15#[bisync]
16pub struct Lps22df<B, T, S>
17where
18    B: BusOperation,
19    T: DelayNs,
20    S: SensorState,
21{
22    pub bus: B,
23    pub tim: T,
24    _state: PhantomData<S>,
25}
26
27/// Driver errors.
28#[bisync]
29#[derive(Debug)]
30pub enum Error<B> {
31    Bus(B),          // Error at the bus level
32    UnexpectedValue, // Unexpected value read from a register
33}
34
35#[bisync]
36impl<B, T, S> Lps22df<B, T, S>
37where
38    B: BusOperation,
39    T: DelayNs,
40    S: SensorState,
41{
42    /// Constructor method based on general BusOperation implementation.
43    pub fn new_bus(bus: B, tim: T) -> Self {
44        Self {
45            bus,
46            tim,
47            _state: PhantomData,
48        }
49    }
50}
51
52#[bisync]
53impl<P, T> Lps22df<i2c::I2cBus<P>, T, OnState>
54where
55    P: I2c,
56    T: DelayNs,
57{
58    /// Constructor method for using the I2C bus.
59    pub fn new_i2c(i2c: P, address: I2CAddress, tim: T) -> Self {
60        // Initialize the I2C bus with the COMPONENT address
61        let bus = i2c::I2cBus::new(i2c, address as SevenBitAddress);
62        Self {
63            bus,
64            tim,
65            _state: PhantomData,
66        }
67    }
68}
69
70#[bisync]
71impl<P, T> Lps22df<spi::SpiBus<P>, T, OnState>
72where
73    P: SpiDevice,
74    T: DelayNs,
75{
76    /// Constructor method for using the SPI bus.
77    pub fn new_spi(spi: P, tim: T) -> Self {
78        // Initialize the SPI bus
79        let bus = spi::SpiBus::new(spi);
80        Self {
81            bus,
82            tim,
83            _state: PhantomData,
84        }
85    }
86}
87
88#[bisync]
89impl<B, T, S> SensorOperation for Lps22df<B, T, S>
90where
91    B: BusOperation,
92    T: DelayNs,
93    S: SensorState,
94{
95    type Error = Error<B::Error>;
96
97    #[inline]
98    async fn read_from_register(&mut self, reg: u8, buf: &mut [u8]) -> Result<(), Error<B::Error>> {
99        self.bus
100            .read_from_register(reg, buf)
101            .await
102            .map_err(Error::Bus)
103    }
104
105    #[inline]
106    async fn write_to_register(&mut self, reg: u8, buf: &[u8]) -> Result<(), Error<B::Error>> {
107        self.bus
108            .write_to_register(reg, buf)
109            .await
110            .map_err(Error::Bus)
111    }
112}
113
114#[bisync]
115impl<B: BusOperation, T: DelayNs> Lps22df<B, T, OnState> {
116    /// Get Device id: WHO_AM_I (0x0F)
117    ///
118    /// Device identification register (read only).
119    /// Returns the fixed device ID value to verify communication.
120    pub async fn id_get(&mut self) -> Result<u8, Error<B::Error>> {
121        WhoAmI::read(self).await.map(|reg| reg.id())
122    }
123    /// Configures the bus operating mode.
124    ///
125    /// Configures the serial interface mode and enables/disables I2C, I3C, SPI modes and related filters.
126    pub async fn bus_mode_set(&mut self, val: &BusMode) -> Result<(), Error<B::Error>> {
127        let mut if_ctrl = IfCtrl::read(self).await?;
128        if_ctrl.set_i2c_i3c_dis(((val.interface as u8) & 0x02) >> 1);
129        if_ctrl.set_int_en_i3c(((val.interface as u8) & 0x04) >> 2);
130        if_ctrl.set_sim((val.interface as u8) & 0x01);
131        if_ctrl.write(self).await?;
132
133        let mut i3c_if_ctrl = I3cIfCtrl::read(self).await?;
134        i3c_if_ctrl.set_asf_on((val.filter as u8) & 0x01);
135        i3c_if_ctrl.set_i3c_bus_avb_sel((val.i3c_ibi_time as u8) & 0x03);
136        i3c_if_ctrl.write(self).await?;
137
138        Ok(())
139    }
140    /// Retrive the bus operating mode.
141    ///
142    /// Reads interface control and I3C interface control registers to retrieve current bus operating mode,
143    /// filter configuration, and I3C IBI timing.
144    pub async fn bus_mode_get(&mut self) -> Result<BusMode, Error<B::Error>> {
145        let if_ctrl = IfCtrl::read(self).await?;
146        let i3c_if_ctrl = I3cIfCtrl::read(self).await?;
147
148        let interface = (if_ctrl.int_en_i3c() << 2) | (if_ctrl.i2c_i3c_dis() << 1) | if_ctrl.sim();
149        let interface = Interface::try_from(interface).unwrap_or(Interface::SelByHw);
150
151        let filter = Filter::try_from(i3c_if_ctrl.asf_on()).unwrap_or_default();
152
153        let i3c_ibi_time = i3c_if_ctrl.i3c_bus_avb_sel();
154        let i3c_ibi_time = I3cIbiTime::try_from(i3c_ibi_time).unwrap_or_default();
155
156        Ok(BusMode {
157            interface,
158            filter,
159            i3c_ibi_time,
160        })
161    }
162
163    /// Device initialization and reset control.
164    ///
165    /// This function manages the device initialization states including boot, reset, and driver ready modes.
166    /// - `Init::Boot`: Triggers a reboot of internal memory and waits for boot completion indicated by INT_SOURCE register.
167    /// - `Init::Reset`: Performs a software reset and waits for reset completion indicated by status register.
168    /// - `Init::DrvRdy`: Enables block data update and automatic register address increment for multi-byte access.
169    pub async fn init_set(&mut self, val: Init) -> Result<(), Error<B::Error>> {
170        // subsequent reads are required for a correct reset
171        let mut reg: [u8; 2] = [0, 0];
172        self.read_from_register(Reg::CtrlReg2 as u8, &mut reg)
173            .await?;
174        let mut ctrl_reg2 = CtrlReg2::from_bits(reg[0]);
175        let mut ctrl_reg3 = CtrlReg3::from_bits(reg[1]);
176        let mut cnt: u8 = 0;
177
178        match val {
179            Init::Boot => {
180                ctrl_reg2.set_boot(1);
181                ctrl_reg2.write(self).await?;
182
183                loop {
184                    let int_src = IntSource::read(self).await?;
185
186                    if int_src.boot_on() == 0 {
187                        break;
188                    }
189
190                    self.tim.delay_ms(10).await;
191
192                    if cnt >= 5 {
193                        return Err(Error::UnexpectedValue);
194                    }
195
196                    cnt += 1;
197                }
198            }
199            Init::Reset => {
200                ctrl_reg2.set_swreset(1);
201                self.write_to_register(Reg::CtrlReg2 as u8, &[ctrl_reg2.into()])
202                    .await?;
203
204                loop {
205                    let status = self.status_get().await?;
206                    if status.sw_reset == 0 {
207                        break;
208                    }
209
210                    self.tim.delay_ms(10).await;
211
212                    if cnt >= 5 {
213                        return Err(Error::UnexpectedValue);
214                    }
215
216                    cnt += 1;
217                }
218            }
219            Init::DrvRdy => {
220                ctrl_reg2.set_bdu(1);
221                ctrl_reg3.set_if_add_inc(1);
222                // subsequent writes are required for a correct reset
223                reg[0] = ctrl_reg2.into();
224                reg[1] = ctrl_reg3.into();
225                self.write_to_register(Reg::CtrlReg2 as u8, &reg).await?;
226            }
227        }
228
229        Ok(())
230    }
231    /// Device status retrieval.
232    ///
233    /// Reads multiple status-related registers to provide comprehensive device status information:
234    /// - Software reset completion status.
235    /// - Boot phase status.
236    /// - Pressure and temperature data ready flags.
237    /// - Pressure and temperature data overrun flags.
238    /// - One-shot measurement completion status.
239    /// - AUTOZERO reference completion status.
240    pub async fn status_get(&mut self) -> Result<Stat, Error<B::Error>> {
241        let ctrl_reg2 = CtrlReg2::read(self).await?;
242        let int_source = IntSource::read(self).await?;
243        let status = Status::read(self).await?;
244        let interrupt_cfg = InterruptCfg::read(self).await?;
245
246        Ok(Stat {
247            sw_reset: ctrl_reg2.swreset(),
248            boot: int_source.boot_on(),
249            drdy_pres: status.p_da(),
250            drdy_temp: status.t_da(),
251            ovr_pres: status.p_or(),
252            ovr_temp: status.t_or(),
253            end_meas: !ctrl_reg2.oneshot(),
254            ref_done: !interrupt_cfg.autozero(),
255        })
256    }
257    /// Electrical pin configuration setter.
258    ///
259    /// Configures the electrical characteristics of device pins including pull-up/down resistors and push-pull/open-drain modes.
260    /// - Configures IF_CTRL register for pull-up/down on INT, SDA, SDO, and CS pins.
261    /// - Configures CTRL_REG3 register for interrupt pin output type.
262    pub async fn pin_conf_set(&mut self, val: &PinConf) -> Result<(), Error<B::Error>> {
263        // Read IF_CTRL register
264        let mut if_ctrl = IfCtrl::read(self).await?;
265
266        // Configure IF_CTRL register fields
267        if_ctrl.set_int_pd_dis(!val.int_pull_down);
268        if_ctrl.set_sdo_pu_en(val.sdo_pull_up);
269        if_ctrl.set_sda_pu_en(val.sda_pull_up);
270        if_ctrl.set_cs_pu_dis(!val.cs_pull_up);
271
272        // Write back to IF_CTRL register
273        if_ctrl.write(self).await?;
274
275        // Read CTRL_REG3 register
276        let mut ctrl_reg3 = CtrlReg3::read(self).await?;
277
278        // Configure CTRL_REG3 register fields
279        ctrl_reg3.set_pp_od(!val.int_push_pull);
280
281        // Write back to CTRL_REG3 register
282        ctrl_reg3.write(self).await?;
283
284        Ok(())
285    }
286    /// Get Electrical pin configuration.
287    ///
288    /// Reads IF_CTRL and CTRL_REG3 registers to retrieve current electrical pin configuration.
289    pub async fn pin_conf_get(&mut self) -> Result<PinConf, Error<B::Error>> {
290        let if_ctrl = IfCtrl::read(self).await?;
291        let ctrl_reg3 = CtrlReg3::read(self).await?;
292
293        let val = PinConf {
294            sda_pull_up: if_ctrl.sda_pu_en(),
295            cs_pull_up: !if_ctrl.cs_pu_dis(),
296            int_pull_down: !if_ctrl.int_pd_dis(),
297            sdo_pull_up: if_ctrl.sdo_pu_en(),
298            int_push_pull: !ctrl_reg3.pp_od(),
299        };
300
301        Ok(val)
302    }
303    /// Retrieve status of all interrupt sources.
304    ///
305    /// Reads STATUS, INT_SOURCE, and FIFO_STATUS2 registers to provide a comprehensive snapshot of all interrupt flags,
306    /// including data-ready, threshold, FIFO full, FIFO overrun, and watermark interrupts.
307    pub async fn all_sources_get(&mut self) -> Result<AllSources, Error<B::Error>> {
308        let status = Status::read(self).await?;
309        let int_source = IntSource::read(self).await?;
310        let fifo_status2 = FifoStatus2::read(self).await?;
311
312        let val = AllSources {
313            drdy_pres: status.p_da(),
314            drdy_temp: status.t_da(),
315            over_pres: int_source.ph(),
316            under_pres: int_source.pl(),
317            thrsld_pres: int_source.ia(),
318            fifo_full: fifo_status2.fifo_full_ia(),
319            fifo_ovr: fifo_status2.fifo_ovr_ia(),
320            fifo_th: fifo_status2.fifo_wtm_ia(),
321        };
322
323        Ok(val)
324    }
325    /// Select conversion parameters.
326    ///
327    /// Sets output data rate, averaging, and low-pass filter configuration registers.
328    pub async fn mode_set(&mut self, val: &Md) -> Result<(), Error<B::Error>> {
329        let mut ctrl_reg1 = CtrlReg1::read(self).await?;
330        let mut ctrl_reg2 = CtrlReg2::read(self).await?;
331
332        ctrl_reg1.set_odr(val.odr as u8);
333        ctrl_reg1.set_avg(val.avg as u8);
334        ctrl_reg2.set_en_lpfp(val.lpf as u8 & 0x01);
335        ctrl_reg2.set_lfpf_cfg((val.lpf as u8 & 0x02) >> 1);
336
337        ctrl_reg1.write(self).await?;
338        ctrl_reg2.write(self).await?;
339
340        Ok(())
341    }
342    /// Get sensor conversion parameters.
343    ///
344    /// Reads output data rate, averaging, and low-pass filter configuration registers.
345    pub async fn mode_get(&mut self) -> Result<Md, Error<B::Error>> {
346        let ctrl_reg1 = CtrlReg1::read(self).await?;
347        let ctrl_reg2 = CtrlReg2::read(self).await?;
348
349        let odr = Odr::try_from(ctrl_reg1.odr()).unwrap_or_default();
350        let avg = Avg::try_from(ctrl_reg1.avg()).unwrap_or_default();
351        let lpf = (ctrl_reg2.lfpf_cfg() << 2) | ctrl_reg2.en_lpfp();
352        let lpf = LowPassFilter::try_from(lpf).unwrap_or_default();
353
354        Ok(Md { odr, avg, lpf })
355    }
356    /// Software trigger for One-Shot mode.
357    ///
358    /// Triggers a single pressure and temperature measurement if the device is in one-shot mode.
359    pub async fn trigger_sw(&mut self, md: &Md) -> Result<(), Error<B::Error>> {
360        if md.odr == Odr::OneShot {
361            let mut ctrl_reg2 = CtrlReg2::read(self).await?;
362            ctrl_reg2.set_oneshot(1);
363            ctrl_reg2.write(self).await?;
364        }
365        Ok(())
366    }
367    /// Sensor data retrieval.
368    ///
369    /// Reads pressure and temperature output registers and converts raw data to physical units.
370    pub async fn data_get(&mut self) -> Result<Data, Error<B::Error>> {
371        // Pressure conversion
372        let raw_pressure = PressOut::read(self).await?.pressure();
373        let pressure_hpa = from_lsb_to_hpa(raw_pressure);
374
375        // Temperature conversion
376        let raw_heat: i16 = TempOut::read(self).await?.temp_c();
377        let heat_deg_c = from_lsb_to_celsius(raw_heat);
378
379        // Construct Data
380        let data = Data {
381            pressure: Pressure {
382                hpa: pressure_hpa,
383                raw: raw_pressure,
384            },
385            heat: Heat {
386                deg_c: heat_deg_c,
387                raw: raw_heat,
388            },
389        };
390
391        Ok(data)
392    }
393
394    /// Pressure output raw value getter.
395    ///
396    /// Reads the 24-bit raw pressure output registers and returns the value left-aligned in a 32-bit integer.
397    pub async fn pressure_raw_get(&mut self) -> Result<u32, Error<B::Error>> {
398        Ok(PressOut::read(self).await?.into_bits())
399    }
400    /// Temperature output raw value getter.
401    ///
402    /// Reads the 16-bit raw temperature output registers.
403    pub async fn temperature_raw_get(&mut self) -> Result<i16, Error<B::Error>> {
404        TempOut::read(self).await.map(|reg| reg.temp_c())
405    }
406    /// Set FIFO operation mode and watermark level.
407    ///
408    /// Configures the FIFO_CTRL (0x14) register to select the FIFO operating mode, and
409    /// enable triggered FIFO modes.
410    pub async fn fifo_mode_set(&mut self, op: Operation) -> Result<(), Error<B::Error>> {
411        let mut fifo_ctrl = FifoCtrl::read(self).await?;
412
413        fifo_ctrl.set_f_mode((op as u8) & 0x03);
414        fifo_ctrl.set_trig_modes(((op as u8) & 0x04) >> 2);
415
416        fifo_ctrl.write(self).await
417    }
418    /// Get FIFO operation mode and watermark level.
419    ///
420    /// Reads FIFO_CTRL (0x14) and FIFO_WTM (0x15) registers to retrieve the current FIFO operating mode,
421    /// triggered mode status, and watermark level.
422    pub async fn fifo_mode_get(&mut self) -> Result<Operation, Error<B::Error>> {
423        let fifo_ctrl = FifoCtrl::read(self).await?;
424
425        let operation = (fifo_ctrl.trig_modes() << 2) | fifo_ctrl.f_mode();
426        Ok(Operation::try_from(operation).unwrap_or_default())
427    }
428
429    /// Sets the FIFO watermark level.
430    ///
431    /// The FIFO watermark is a programmable threshold that determines when a FIFO threshold interrupt is generated.
432    /// When the number of unread samples in the FIFO buffer reaches or exceeds this level, the device can trigger an interrupt
433    /// (if enabled via the INT_F_WTM bit in CTRL_REG4).
434    ///
435    /// Registers used:
436    /// - Writes to the `FIFO_WTM` (0x15) register, WTM[6:0] field.
437    ///
438    /// # Parameters
439    /// - `val`: Watermark threshold value (0..=127). Each unit corresponds to one FIFO sample (1 sample = 7 bytes: 1 TAG + 6 DATA).
440    ///
441    /// # Returns
442    /// - `Ok(())` on success.
443    /// - `Err`: If the value is out of range or a bus error occurs.
444    ///
445    /// # Panics
446    /// - Panics if `val >= 128` (assertion).
447    ///
448    /// # Example
449    /// ```rust
450    /// sensor.fifo_watermark_set(32)?;
451    /// ```
452    pub async fn fifo_watermark_set(&mut self, watermark: u8) -> Result<(), Error<B::Error>> {
453        assert!(watermark < 128);
454
455        let mut fifo_wtm = FifoWtm::read(self).await?;
456        fifo_wtm.set_wtm(watermark);
457        fifo_wtm.write(self).await
458    }
459
460    /// Retrieves the current FIFO watermark threshold value.
461    ///
462    /// This function reads the FIFO_WTM register and returns the current watermark threshold (WTM[6:0]).
463    /// The watermark determines when the FIFO threshold interrupt is triggered (if enabled).
464    ///
465    /// Registers used:
466    /// - Reads from the `FIFO_WTM` (0x15) register, FTH[6:0] field.
467    ///
468    /// # Returns
469    /// - `Ok(u8)`: The current FIFO watermark threshold (0..=127).
470    /// - `Err`: If a bus or register access error occurs.
471    ///
472    /// # Example
473    /// ```rust
474    /// let wtm = sensor.fifo_watermark_get()?;
475    /// ```
476    pub async fn fifo_watermark_get(&mut self) -> Result<u8, Error<B::Error>> {
477        let fifo_wtm = FifoWtm::read(self).await?;
478        Ok(fifo_wtm.wtm())
479    }
480
481    /// Enables or disables the FIFO stop-on-watermark feature.
482    ///
483    /// When enabled, the FIFO buffer stops collecting new data once the number of unread samples reaches the watermark threshold.
484    /// This is useful for applications that require precise control over the number of samples collected in the FIFO.
485    /// When disabled, the FIFO continues to collect data, potentially overwriting the oldest samples (depending on FIFO mode).
486    ///
487    /// # Parameters
488    /// - `fth`: `FifoEvent` enum value indicating whether to enable or disable the stop-on-watermark feature.
489    ///
490    /// # Returns
491    /// - `Ok(())` on success.
492    /// - `Err`: If a bus or register access error occurs.
493    ///
494    /// # Example
495    /// ```rust
496    /// sensor.fifo_stop_on_wtm_set(FifoEvent::Enable)?;
497    /// ```
498    pub async fn fifo_stop_on_wtm_set(&mut self, fth: FifoEvent) -> Result<(), Error<B::Error>> {
499        let mut fifo_ctrl = FifoCtrl::read(self).await?;
500        fifo_ctrl.set_stop_on_wtm(fth as u8);
501        fifo_ctrl.write(self).await
502    }
503
504    /// Reads the current status of the FIFO stop-on-watermark feature.
505    ///
506    /// This function checks whether the FIFO is configured to stop collecting data when the watermark threshold is reached.
507    /// Returns the current setting as a `FifoEvent` enum.
508    ///
509    /// Registers used:
510    /// - Reads from the `FIFO_CTRL` (0x14) register, STOP_ON_FTH bit (bit 3)
511    /// # Returns
512    /// - `Ok(FifoEvent)`: Current stop-on-watermark configuration.
513    /// - `Err`: If a bus or register access error occurs.
514    ///
515    /// # Example
516    /// ```rust
517    /// let stop_on_wtm = sensor.fifo_stop_on_wtm_get()?;
518    /// ```
519    pub async fn fifo_stop_on_wtm_get(&mut self) -> Result<FifoEvent, Error<B::Error>> {
520        let ctrl = FifoCtrl::read(self).await?;
521        let evt = FifoEvent::try_from(ctrl.stop_on_wtm()).unwrap_or_default();
522        Ok(evt)
523    }
524
525    /// Get the current number of unread samples stored in FIFO.
526    ///
527    /// Reads FIFO_STATUS1 (0x25) register which contains the FIFO stored data level (FSS[7:0]).
528    pub async fn fifo_level_get(&mut self) -> Result<u8, Error<B::Error>> {
529        let val: u8 = FifoStatus1::read(self).await?.fss();
530
531        Ok(val)
532    }
533    /// Retrieve multiple pressure samples from FIFO buffer.
534    ///
535    /// Reads `samp` number of pressure samples from FIFO_DATA_OUT_PRESS_XL/H/L registers (0x78-0x7A).
536    /// Each sample is 24-bit pressure data, converted to raw and hPa values.
537    pub async fn fifo_data_get(&mut self, samp: u8) -> Result<[FifoData; 32], Error<B::Error>> {
538        let mut data: [FifoData; 32] = [FifoData { raw: 0, hpa: 0.0 }; 32];
539        for item in data.iter_mut().take(samp as usize) {
540            let raw: i32 = FifoDataOutPress::read(self).await?.pressure();
541            let hpa = from_lsb_to_hpa(raw);
542
543            *item = FifoData { raw, hpa };
544        }
545
546        Ok(data)
547    }
548    /// Configure interrupt pins hardware signal behavior.
549    ///
550    /// Sets interrupt polarity, data-ready pulse mode, and interrupt latch mode by configuring CTRL_REG3 (0x12),
551    /// CTRL_REG4 (0x13), and INTERRUPT_CFG (0x0B) registers.
552    pub async fn interrupt_mode_set(&mut self, val: &IntMode) -> Result<(), Error<B::Error>> {
553        let mut ctrl_reg3 = CtrlReg3::read(self).await?;
554        let mut ctrl_reg4 = CtrlReg4::read(self).await?;
555        ctrl_reg3.set_int_h_l(val.active_low);
556        ctrl_reg4.set_drdy_pls(!val.drdy_latched);
557        ctrl_reg3.write(self).await?;
558        ctrl_reg4.write(self).await?;
559
560        let mut interrupt_cfg = InterruptCfg::read(self).await?;
561        interrupt_cfg.set_lir(val.int_latched);
562        interrupt_cfg.write(self).await?;
563
564        Ok(())
565    }
566    /// Retrieve interrupt pins hardware signal configuration.
567    ///
568    /// Reads CTRL_REG3 (0x12), CTRL_REG4 (0x13), and INTERRUPT_CFG (0x0B) registers to obtain
569    /// interrupt polarity, data-ready pulse mode, and interrupt latch mode.
570    pub async fn interrupt_mode_get(&mut self) -> Result<IntMode, Error<B::Error>> {
571        let interrupt_cfg = InterruptCfg::read(self).await?;
572        let ctrl_reg3 = CtrlReg3::read(self).await?;
573        let ctrl_reg4 = CtrlReg4::read(self).await?;
574
575        let active_low = ctrl_reg3.int_h_l();
576        let drdy_latched = !ctrl_reg4.drdy_pls();
577        let int_latched = interrupt_cfg.lir();
578
579        Ok(IntMode {
580            active_low,
581            drdy_latched,
582            int_latched,
583        })
584    }
585    /// Configure routing of interrupt signals on INT1 pin.
586    ///
587    /// Sets which interrupt signals are routed to the INT1 pin by configuring CTRL_REG4 (0x13) register.
588    pub async fn pin_int_route_set(&mut self, val: &PinIntRoute) -> Result<(), Error<B::Error>> {
589        let mut ctrl_reg4 = CtrlReg4::read(self).await?;
590        ctrl_reg4.set_drdy(val.drdy_pres);
591        ctrl_reg4.set_int_f_wtm(val.fifo_th);
592        ctrl_reg4.set_int_f_ovr(val.fifo_ovr);
593        ctrl_reg4.set_int_f_full(val.fifo_full);
594        ctrl_reg4.write(self).await?;
595
596        Ok(())
597    }
598    /// Retrieve routing configuration of interrupt signals on INT1 pin.
599    ///
600    /// Reads CTRL_REG4 (0x13) register to determine which interrupt signals are routed to INT1 pin.
601    pub async fn pin_int_route_get(&mut self) -> Result<PinIntRoute, Error<B::Error>> {
602        let reg = CtrlReg4::read(self).await?;
603
604        let val = PinIntRoute {
605            drdy_pres: reg.drdy(),
606            fifo_th: reg.int_f_wtm(),
607            fifo_ovr: reg.int_f_ovr(),
608            fifo_full: reg.int_f_full(),
609        };
610
611        Ok(val)
612    }
613    /// Configuration of Wake-up and Wake-up to Sleep.
614    ///
615    /// This function configures the interrupt generation based on pressure threshold crossing events.
616    /// It sets the interrupt enable bits for pressure high and low threshold events, programs the threshold
617    /// value, and enables the interrupt signal on the INT pin.
618    pub async fn int_on_threshold_mode_set(
619        &mut self,
620        val: &IntThMd,
621    ) -> Result<(), Error<B::Error>> {
622        let mut interrupt_cfg = InterruptCfg::read(self).await?;
623        let mut ths_p = ThsP::read(self).await?;
624
625        interrupt_cfg.set_phe(val.over_th);
626        interrupt_cfg.set_ple(val.under_th);
627        ths_p.set_ths(val.threshold);
628
629        interrupt_cfg.write(self).await?;
630        ths_p.write(self).await?;
631
632        let mut ctrl_reg4 = CtrlReg4::read(self).await?;
633        ctrl_reg4.set_int_en(1);
634        ctrl_reg4.write(self).await?;
635
636        Ok(())
637    }
638    /// Retrieve configuration of Wake-up and Wake-up to Sleep.
639    ///
640    /// Reads the interrupt configuration and threshold registers to obtain the current settings for
641    /// pressure threshold interrupt generation.
642    pub async fn int_on_threshold_mode_get(&mut self) -> Result<IntThMd, Error<B::Error>> {
643        let interrupt_cfg = InterruptCfg::read(self).await?;
644        let ths_p = ThsP::read(self).await?;
645
646        let over_th = interrupt_cfg.phe();
647        let under_th = interrupt_cfg.ple();
648        let threshold: u16 = ths_p.ths();
649        Ok(IntThMd {
650            over_th,
651            under_th,
652            threshold,
653        })
654    }
655    /// Configure reference mode for pressure offset and interrupt generation.
656    ///
657    /// This function sets the AUTOZERO and AUTOREFP modes, and controls resetting of reference registers.
658    /// AUTOZERO mode sets the current pressure as reference and outputs differential pressure.
659    /// AUTOREFP mode uses the reference only for interrupt generation without changing output pressure.
660    pub async fn reference_mode_set(&mut self, val: &RefMd) -> Result<(), Error<B::Error>> {
661        let mut interrupt_cfg = InterruptCfg::read(self).await?;
662
663        interrupt_cfg.set_autozero(val.get_ref);
664        interrupt_cfg.set_autorefp((val.apply_ref as u8) & 0x01);
665        interrupt_cfg.set_reset_az(((val.apply_ref as u8) & 0x02) >> 1);
666        interrupt_cfg.set_reset_arp(((val.apply_ref as u8) & 0x02) >> 1);
667
668        interrupt_cfg.write(self).await?;
669
670        Ok(())
671    }
672    /// Retrieve reference mode configuration.
673    ///
674    /// Reads the INTERRUPT_CFG register to obtain the current AUTOZERO and AUTOREFP settings,
675    /// as well as the reset state of reference registers.
676    pub async fn reference_mode_get(&mut self) -> Result<RefMd, Error<B::Error>> {
677        let interrupt_cfg = InterruptCfg::read(self).await?;
678        let apply_ref = (interrupt_cfg.reset_az() << 1) | interrupt_cfg.autorefp();
679        let apply_ref = ApplyRef::try_from(apply_ref).unwrap_or(ApplyRef::RstRefs);
680        let get_ref = interrupt_cfg.autozero();
681
682        Ok(RefMd { apply_ref, get_ref })
683    }
684    /// Set one-point calibration (OPC) offset value.
685    ///
686    /// Writes a 16-bit signed offset value to the pressure offset registers (RPDS_L and RPDS_H).
687    /// This offset is added to compensated pressure data to calibrate the sensor after soldering.
688    pub async fn opc_set(&mut self, val: i16) -> Result<(), Error<B::Error>> {
689        Rpds::new().with_offset(val).write(self).await
690    }
691    /// Retrieve one-point calibration (OPC) offset value.
692    ///
693    /// Reads the 16-bit signed offset value from the pressure offset registers (RPDS_L and RPDS_H).
694    pub async fn opc_get(&mut self) -> Result<i16, Error<B::Error>> {
695        Rpds::read(self).await.map(|reg| reg.offset())
696    }
697}
698
699#[bisync]
700pub fn from_lsb_to_hpa(lsb: i32) -> f32 {
701    (lsb as f32) / 1048576.0
702}
703
704#[bisync]
705pub fn from_lsb_to_celsius(lsb: i16) -> f32 {
706    (lsb as f32) / 100.0
707}
708
709/// I2C device addresses based on SDO/SA0 pin state.
710#[repr(u8)]
711#[derive(Clone, Copy, PartialEq)]
712#[bisync]
713pub enum I2CAddress {
714    /// I2C address when SA0 pin is low (0)
715    I2cAddL = 0x5C,
716    /// I2C address when SA0 pin is high (1)
717    I2cAddH = 0x5D,
718}
719
720#[bisync]
721pub const ID: u8 = 0xB4;