lps22df_rs/
lib.rs

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