hdc302x_async/
types.rs

1use crate::hw_def::*;
2
3use core::fmt;
4
5/// HDC302x(-Q1) device driver
6#[derive(Debug)]
7pub struct Hdc302x<I2C, Delay> {
8    pub(crate) i2c: I2C,
9    pub(crate) delay: Delay,
10    pub(crate) i2c_addr: crate::hw_def::I2cAddr,
11}
12
13/// All possible errors in this crate
14#[derive(Debug)]
15pub enum Error<E> {
16    /// I²C communication error
17    I2c(E),
18    /// Invalid input data provided
19    InvalidInputData,
20    /// Failure of a checksum from the device was detected
21    CrcMismatch,
22}
23
24/// Raw (still in u16 format) temperature and/or humidity from the device
25#[derive(Debug)]
26pub enum RawDatum {
27    /// temerature and relative humidity from one-shot or auto mode
28    TempAndRelHumid(RawTempAndRelHumid),
29    /// minimum temperature since auto mode was enabled
30    MinTemp(u16),
31    /// maximum temperature since auto mode was enabled
32    MaxTemp(u16),
33    /// minimum relative humidity since auto mode was enabled
34    MinRelHumid(u16),
35    /// maximum relative humidity since auto mode was enabled
36    MaxRelHumid(u16),
37}
38impl RawDatum {
39    /// Get temperature in Fahrenheit
40    pub fn fahrenheit(&self) -> Option<f32> {
41        match self {
42            Self::TempAndRelHumid(RawTempAndRelHumid{temperature, ..}) => Some(raw_temp_to_fahrenheit(*temperature)),
43            Self::MinTemp(u16) => Some(raw_temp_to_fahrenheit(*u16)),
44            Self::MaxTemp(u16) => Some(raw_temp_to_fahrenheit(*u16)),
45            Self::MinRelHumid(_) => None,
46            Self::MaxRelHumid(_) => None,
47        }
48    }
49    /// Get temperature in Centigrade
50    pub fn centigrade(&self) -> Option<f32> {
51        match self {
52            Self::TempAndRelHumid(RawTempAndRelHumid{temperature, ..}) => Some(raw_temp_to_centigrade(*temperature)),
53            Self::MinTemp(u16) => Some(raw_temp_to_centigrade(*u16)),
54            Self::MaxTemp(u16) => Some(raw_temp_to_centigrade(*u16)),
55            Self::MinRelHumid(_) => None,
56            Self::MaxRelHumid(_) => None,
57        }
58    }
59    /// Get relative humidity in percent
60    pub fn humidity_percent(&self) -> Option<f32> {
61        match self {
62            Self::TempAndRelHumid(_) => None,
63            Self::MinTemp(_) => None,
64            Self::MaxTemp(_) => None,
65            Self::MinRelHumid(u16) => Some(raw_rel_humid_to_percent(*u16)),
66            Self::MaxRelHumid(u16) => Some(raw_rel_humid_to_percent(*u16)),
67        }
68    }
69}
70
71/// Raw (still in u16 format) temperature and relative humidity from the device
72#[derive(Debug)]
73pub struct RawTempAndRelHumid{
74    /// unprocessed temperature
75    pub temperature: u16,
76    /// unprocessed relative humiodity
77    pub humidity: u16,
78}
79impl RawTempAndRelHumid {
80    /// Get temperature in Fahrenheit
81    pub fn fahrenheit(&self) -> f32 {
82        raw_temp_to_fahrenheit(self.temperature)
83    }
84    /// Get temperature in Centigrade
85    pub fn centigrade(&self) -> f32 {
86        raw_temp_to_centigrade(self.temperature)
87    }
88    /// Get relative humidity in percent
89    pub fn humidity_percent(&self) -> f32 {
90        raw_rel_humid_to_percent(self.humidity)
91    }
92}
93
94/// Temp and/or humidity from the device after conversion
95#[derive(Debug)]
96pub enum Datum {
97    /// temerature and relative humidity from one-shot or auto mode
98    TempAndRelHumid(TempAndRelHumid),
99    /// minimum temperature since auto mode was enabled
100    MinTemp(Temp),
101    /// maximum temperature since auto mode was enabled
102    MaxTemp(Temp),
103    /// minimum relative humidity since auto mode was enabled
104    MinRelHumid(f32),
105    /// maximum relative humidity since auto mode was enabled
106    MaxRelHumid(f32),
107}
108impl From<&RawDatum> for Datum {
109    fn from(raw: &RawDatum) -> Self {
110        match raw {
111            RawDatum::TempAndRelHumid(raw) => Datum::TempAndRelHumid(raw.into()),
112            RawDatum::MinTemp(raw) => Datum::MinTemp((*raw).into()),
113            RawDatum::MaxTemp(raw) => Datum::MaxTemp((*raw).into()),
114            RawDatum::MinRelHumid(raw) => Datum::MinRelHumid(raw_rel_humid_to_percent(*raw)),
115            RawDatum::MaxRelHumid(raw) => Datum::MaxRelHumid(raw_rel_humid_to_percent(*raw)),
116        }
117    }
118}
119
120/// Temp and relative humidity from the device after conversion
121#[derive(Debug)]
122pub struct TempAndRelHumid {
123    /// degrees centigrade
124    pub centigrade: f32,
125    /// degrees fahrenheit
126    pub fahrenheit: f32,
127    /// relative humidity in percent
128    pub humidity_percent: f32,
129}
130impl From<&RawTempAndRelHumid> for TempAndRelHumid {
131    fn from(raw: &RawTempAndRelHumid) -> Self {
132        Self {
133            centigrade: raw_temp_to_centigrade(raw.temperature),
134            fahrenheit: raw_temp_to_fahrenheit(raw.temperature),
135            humidity_percent: raw_rel_humid_to_percent(raw.humidity),
136        }
137    }
138}
139/// Temp after conversion
140#[derive(Debug)]
141pub struct Temp{
142    /// degrees centigrade
143    pub centigrade: f32,
144    /// degrees fahrenheit
145    pub fahrenheit: f32,
146}
147impl From<u16> for Temp {
148    fn from(raw: u16) -> Self {
149        Self {
150            centigrade: raw_temp_to_centigrade(raw),
151            fahrenheit: raw_temp_to_fahrenheit(raw),
152        }
153    }
154}
155
156/// Status bits from the device
157#[derive(Clone, Copy, Debug, Eq, PartialEq)]
158pub struct StatusBits {
159    raw: u16,
160    /// at least one alert is active
161    pub at_least_one_alert: bool,
162    /// heater is enabled
163    pub heater_enabled: bool,
164    /// relative humidity tracking alert
165    pub rh_tracking_alert: bool,
166    /// temperature tracking alert
167    pub t_tracking_alert: bool,
168    /// relative humidity high tracking alert
169    pub rh_high_tracking_alert: bool,
170    /// relative humidity low tracking alert
171    pub rh_low_tracking_alert: bool,
172    /// temperature high tracking alert
173    pub t_high_tracking_alert: bool,
174    /// temperature low tracking alert
175    pub t_low_tracking_alert: bool,
176    /// reset (power-on or software) detected since last clear of status register
177    pub reset_since_clear: bool,
178    /// failure of a checksum from the driver was detected
179    pub checksum_failure: bool,
180}
181impl From<u16> for StatusBits {
182    fn from(raw: u16) -> Self {
183        Self {
184            raw,
185            at_least_one_alert: (raw >> STATUS_FIELD_LSBIT_AT_LEAST_ONE_ALERT) & ((1 << STATUS_FIELD_WIDTH_AT_LEAST_ONE_ALERT) - 1) != 0,
186            heater_enabled: (raw >> STATUS_FIELD_LSBIT_HEATER_ENABLED) & ((1 << STATUS_FIELD_WIDTH_HEATER_ENABLED) - 1) != 0,
187            rh_tracking_alert: (raw >> STATUS_FIELD_LSBIT_RH_TRACKING_ALERT) & ((1 << STATUS_FIELD_WIDTH_RH_TRACKING_ALERT) - 1) != 0,
188            t_tracking_alert: (raw >> STATUS_FIELD_LSBIT_T_TRACKING_ALERT) & ((1 << STATUS_FIELD_WIDTH_T_TRACKING_ALERT) - 1) != 0,
189            rh_high_tracking_alert: (raw >> STATUS_FIELD_LSBIT_RH_HIGH_TRACKING_ALERT) & ((1 << STATUS_FIELD_WIDTH_RH_HIGH_TRACKING_ALERT) - 1) != 0,
190            rh_low_tracking_alert: (raw >> STATUS_FIELD_LSBIT_RH_LOW_TRACKING_ALERT) & ((1 << STATUS_FIELD_WIDTH_RH_LOW_TRACKING_ALERT) - 1) != 0,
191            t_high_tracking_alert: (raw >> STATUS_FIELD_LSBIT_T_HIGH_TRACKING_ALERT) & ((1 << STATUS_FIELD_WIDTH_T_HIGH_TRACKING_ALERT) - 1) != 0,
192            t_low_tracking_alert: (raw >> STATUS_FIELD_LSBIT_T_LOW_TRACKING_ALERT) & ((1 << STATUS_FIELD_WIDTH_T_LOW_TRACKING_ALERT) - 1) != 0,
193            reset_since_clear: (raw >> STATUS_FIELD_LSBIT_RESET_SINCE_CLEAR) & ((1 << STATUS_FIELD_WIDTH_RESET_SINCE_CLEAR) - 1) != 0,
194            checksum_failure: (raw >> STATUS_FIELD_LSBIT_CHECKSUM_FAILURE) & ((1 << STATUS_FIELD_WIDTH_CHECKSUM_FAILURE) - 1) != 0,
195        }
196    }
197}
198impl StatusBits {
199    /// Get the raw status bits
200    pub fn raw(&self) -> u16 {
201        self.raw
202    }
203}
204impl fmt::Display for StatusBits {
205    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206        write!(f, "StatusBits {{ 0x{:02x}; ", self.raw)?;
207        if self.at_least_one_alert {
208            write!(f, "at_least_one_alert ")?;
209        }
210        if self.heater_enabled {
211            write!(f, "heater_enabled ")?;
212        }
213        if self.rh_tracking_alert {
214            write!(f, "rh_tracking_alert ")?;
215        }
216        if self.t_tracking_alert {
217            write!(f, "t_tracking_alert ")?;
218        }
219        if self.rh_high_tracking_alert {
220            write!(f, "rh_high_tracking_alert ")?;
221        }
222        if self.rh_low_tracking_alert {
223            write!(f, "rh_low_tracking_alert ")?;
224        }
225        if self.t_high_tracking_alert {
226            write!(f, "t_high_tracking_alert ")?;
227        }
228        if self.t_low_tracking_alert {
229            write!(f, "t_low_tracking_alert ")?;
230        }
231        if self.reset_since_clear {
232            write!(f, "reset_since_clear ")?;
233        }
234        if self.checksum_failure {
235            write!(f, "checksum_failure ")?;
236        }
237        write!(f, "}}")
238    }
239}
240
241
242/// Serial number of the device
243pub struct SerialNumber(pub [u8; 6]);
244impl fmt::Display for SerialNumber {
245    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
246        for byte in self.0.iter().rev() {
247            write!(f, "{:02X}", byte)?;
248        }
249        Ok(())
250    }
251}
252
253/// Manufacturer ID of the device
254#[derive(Clone, Copy)]
255pub enum ManufacturerId {
256    /// Texas Instruments
257    TexasInstruments,
258    /// Other
259    Other(u16),
260}
261impl From<u16> for ManufacturerId {
262    fn from(raw: u16) -> Self {
263        match raw {
264            MANUFACTURER_ID_TEXAS_INSTRUMENTS => ManufacturerId::TexasInstruments,
265            _ => ManufacturerId::Other(raw),
266        }
267    }
268}
269impl Into<u16> for ManufacturerId {
270    fn into(self) -> u16 {
271        match self {
272            ManufacturerId::TexasInstruments => MANUFACTURER_ID_TEXAS_INSTRUMENTS,
273            ManufacturerId::Other(id) => id,
274        }
275    }
276}
277impl fmt::Display for ManufacturerId {
278    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
279        match self {
280            ManufacturerId::TexasInstruments => {
281                let mid_u16: u16 = (*self).into();
282                write!(f, "Texas Instruments (0x{mid_u16:04X})")
283            }
284            ManufacturerId::Other(mid_u16) => write!(f, "Unknown (0x{mid_u16:04X})"),
285        }
286    }
287}