tmp1x2/
configuration.rs

1use crate::conversion::{convert_temp_to_register_extended, convert_temp_to_register_normal};
2use crate::RegisterU16;
3use crate::{
4    marker::mode, AlertPolarity, BitFlagsHigh as BFH, BitFlagsLow as BFL, Config,
5    ConversionRate as CR, Error, FaultQueue, ModeChangeError, Register, ThermostatMode, Tmp1x2,
6};
7use core::marker::PhantomData;
8#[cfg(not(feature = "async"))]
9use embedded_hal::i2c::I2c;
10#[cfg(feature = "async")]
11use embedded_hal_async::i2c::I2c as AsyncI2c;
12
13#[maybe_async_cfg::maybe(
14    sync(
15        cfg(not(feature = "async")),
16        self = "Tmp1x2",
17        idents(AsyncI2c(sync = "I2c"))
18    ),
19    async(feature = "async", keep_self)
20)]
21impl<I2C, E> Tmp1x2<I2C, mode::Continuous>
22where
23    I2C: AsyncI2c<Error = E>,
24{
25    /// Change into one-shot conversion mode (shutdown).
26    ///
27    /// If the mode change failed you will get a `ModeChangeError`.
28    /// You can get the unchanged device back from it.
29    pub async fn into_one_shot(
30        mut self,
31    ) -> Result<Tmp1x2<I2C, mode::OneShot>, ModeChangeError<E, Self>> {
32        if let Err(Error::I2C(e)) = self.config_one_shot().await {
33            return Err(ModeChangeError::I2C(e, self));
34        }
35        Ok(Tmp1x2 {
36            i2c: self.i2c,
37            address: self.address,
38            config: self.config,
39            a_temperature_conversion_was_started: false,
40            _mode: PhantomData,
41        })
42    }
43}
44
45#[maybe_async_cfg::maybe(
46    sync(
47        cfg(not(feature = "async")),
48        self = "Tmp1x2",
49        idents(AsyncI2c(sync = "I2c"))
50    ),
51    async(feature = "async", keep_self)
52)]
53impl<I2C, E> Tmp1x2<I2C, mode::OneShot>
54where
55    I2C: AsyncI2c<Error = E>,
56{
57    /// Change into continuous conversion mode.
58    ///
59    /// If the mode change failed you will get a `ModeChangeError`.
60    /// You can get the unchanged device back from it.
61    pub async fn into_continuous(
62        mut self,
63    ) -> Result<Tmp1x2<I2C, mode::Continuous>, ModeChangeError<E, Self>> {
64        if let Err(Error::I2C(e)) = self.config_continuous().await {
65            return Err(ModeChangeError::I2C(e, self));
66        }
67        Ok(Tmp1x2 {
68            i2c: self.i2c,
69            address: self.address,
70            config: self.config,
71            a_temperature_conversion_was_started: false,
72            _mode: PhantomData,
73        })
74    }
75
76    pub(crate) async fn trigger_one_shot_measurement(&mut self) -> Result<(), Error<E>> {
77        // This bit is not stored
78        self.write_register(Register::CONFIG, self.config.with_high_msb(BFH::ONE_SHOT))
79            .await
80    }
81}
82
83#[maybe_async_cfg::maybe(
84    sync(
85        cfg(not(feature = "async")),
86        self = "Tmp1x2",
87        idents(AsyncI2c(sync = "I2c"))
88    ),
89    async(feature = "async", keep_self)
90)]
91impl<I2C, E, MODE> Tmp1x2<I2C, MODE>
92where
93    I2C: AsyncI2c<Error = E>,
94{
95    async fn config_continuous(&mut self) -> Result<(), Error<E>> {
96        self.write_config(self.config.with_low_msb(BFH::SHUTDOWN))
97            .await
98    }
99
100    async fn config_one_shot(&mut self) -> Result<(), Error<E>> {
101        self.write_config(self.config.with_high_msb(BFH::SHUTDOWN))
102            .await
103    }
104
105    /// Enable the extended measurement mode.
106    ///
107    /// This allows measurement of temperatures above 128°C.
108    pub async fn enable_extended_mode(&mut self) -> Result<(), Error<E>> {
109        self.write_config(self.config.with_high_lsb(BFL::EXTENDED_MODE))
110            .await
111    }
112
113    /// Disable the extended measurement mode.
114    ///
115    /// This puts the device in normal measurement mode. It will not measure
116    /// temperatures above 128°C.
117    pub async fn disable_extended_mode(&mut self) -> Result<(), Error<E>> {
118        self.write_config(self.config.with_low_lsb(BFL::EXTENDED_MODE))
119            .await
120    }
121
122    /// Set the conversion rate when in continuous conversion mode.
123    pub async fn set_conversion_rate(&mut self, rate: CR) -> Result<(), Error<E>> {
124        let Config { lsb, msb } = self.config;
125        match rate {
126            CR::_0_25Hz => {
127                self.write_config(Config {
128                    lsb: lsb & !BFL::CONV_RATE1 & !BFL::CONV_RATE0,
129                    msb,
130                })
131                .await
132            }
133            CR::_1Hz => {
134                self.write_config(Config {
135                    lsb: lsb & !BFL::CONV_RATE1 | BFL::CONV_RATE0,
136                    msb,
137                })
138                .await
139            }
140            CR::_4Hz => {
141                self.write_config(Config {
142                    lsb: lsb | BFL::CONV_RATE1 & !BFL::CONV_RATE0,
143                    msb,
144                })
145                .await
146            }
147            CR::_8Hz => {
148                self.write_config(Config {
149                    lsb: lsb | BFL::CONV_RATE1 | BFL::CONV_RATE0,
150                    msb,
151                })
152                .await
153            }
154        }
155    }
156
157    /// Set the high temperature threshold.
158    ///
159    /// The value provided will be capped to be in the interval
160    /// `[-128.0, 127.9375]` in normal mode and `[-256.0, 255.875]` in
161    /// extended mode.
162    pub async fn set_high_temperature_threshold(
163        &mut self,
164        temperature: f32,
165    ) -> Result<(), Error<E>> {
166        self.set_temperature_threshold(temperature, Register::T_HIGH)
167            .await
168    }
169
170    /// Set the low temperature threshold.
171    ///
172    /// The value provided will be capped to be in the interval
173    /// `[-128.0, 127.9375]` in normal mode and `[-256.0, 255.875]` in
174    /// extended mode.
175    pub async fn set_low_temperature_threshold(
176        &mut self,
177        temperature: f32,
178    ) -> Result<(), Error<E>> {
179        self.set_temperature_threshold(temperature, Register::T_LOW)
180            .await
181    }
182
183    async fn set_temperature_threshold(
184        &mut self,
185        temperature: f32,
186        register: u8,
187    ) -> Result<(), Error<E>> {
188        if (self.config.lsb & BFL::EXTENDED_MODE) != 0 {
189            let (msb, lsb) = convert_temp_to_register_extended(temperature);
190            self.write_register(register, RegisterU16 { lsb, msb })
191                .await
192        } else {
193            let (msb, lsb) = convert_temp_to_register_normal(temperature);
194            self.write_register(register, RegisterU16 { lsb, msb })
195                .await
196        }
197    }
198
199    /// Set the fault queue.
200    ///
201    /// Set the number of consecutive faults that will trigger an alert.
202    pub async fn set_fault_queue(&mut self, fq: FaultQueue) -> Result<(), Error<E>> {
203        let Config { lsb, msb } = self.config;
204        match fq {
205            FaultQueue::_1 => {
206                self.write_config(Config {
207                    lsb,
208                    msb: msb & !BFH::FAULT_QUEUE1 & !BFH::FAULT_QUEUE0,
209                })
210                .await
211            }
212            FaultQueue::_2 => {
213                self.write_config(Config {
214                    lsb,
215                    msb: msb & !BFH::FAULT_QUEUE1 | BFH::FAULT_QUEUE0,
216                })
217                .await
218            }
219            FaultQueue::_4 => {
220                self.write_config(Config {
221                    lsb,
222                    msb: msb | BFH::FAULT_QUEUE1 & !BFH::FAULT_QUEUE0,
223                })
224                .await
225            }
226            FaultQueue::_6 => {
227                self.write_config(Config {
228                    lsb,
229                    msb: msb | BFH::FAULT_QUEUE1 | BFH::FAULT_QUEUE0,
230                })
231                .await
232            }
233        }
234    }
235
236    /// Set the alert polarity.
237    pub async fn set_alert_polarity(&mut self, polarity: AlertPolarity) -> Result<(), Error<E>> {
238        match polarity {
239            AlertPolarity::ActiveLow => {
240                self.write_config(self.config.with_low_msb(BFH::ALERT_POLARITY))
241                    .await
242            }
243            AlertPolarity::ActiveHigh => {
244                self.write_config(self.config.with_high_msb(BFH::ALERT_POLARITY))
245                    .await
246            }
247        }
248    }
249
250    /// Set the thermostat mode.
251    pub async fn set_thermostat_mode(&mut self, mode: ThermostatMode) -> Result<(), Error<E>> {
252        match mode {
253            ThermostatMode::Comparator => {
254                self.write_config(self.config.with_low_msb(BFH::THERMOSTAT))
255                    .await
256            }
257            ThermostatMode::Interrupt => {
258                self.write_config(self.config.with_high_msb(BFH::THERMOSTAT))
259                    .await
260            }
261        }
262    }
263
264    /// Reset the internal state of this driver to the default values.
265    ///
266    /// *Note:* This does not alter the state or configuration of the device.
267    ///
268    /// This resets the cached configuration register value in this driver to
269    /// the power-up (reset) configuration of the device.
270    ///
271    /// This needs to be called after performing a reset on the device, for
272    /// example through an I2C general-call Reset command, which was not done
273    /// through this driver to ensure that the configurations in the device
274    /// and in the driver match.
275    pub fn reset_internal_driver_state(&mut self) {
276        self.config = Config::default();
277    }
278}