use crate::hw_def::*;
use core::fmt;
#[cfg(feature="defmt")]
use defmt::Format;
#[cfg_attr(feature = "bincode", derive(Encode, Decode))]
#[cfg_attr(feature = "defmt", derive(Format))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone)]
#[derive(Debug)]
#[derive(PartialEq)]
pub struct Hdc302x<I2C, Delay> {
pub(crate) i2c: I2C,
pub(crate) delay: Delay,
pub(crate) i2c_addr: crate::hw_def::I2cAddr,
}
#[cfg_attr(feature = "bincode", derive(Encode, Decode))]
#[cfg_attr(feature = "defmt", derive(Format))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone)]
#[derive(Debug)]
pub enum Error<E> {
I2c(E),
InvalidInputData,
#[cfg(feature = "crc")]
CrcMismatch,
}
#[cfg_attr(feature = "bincode", derive(Encode, Decode))]
#[cfg_attr(feature = "defmt", derive(Format))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone)]
#[derive(Debug)]
#[derive(PartialEq)]
pub enum RawDatum {
TempAndRelHumid(RawTempAndRelHumid),
MinTemp(u16),
MaxTemp(u16),
MinRelHumid(u16),
MaxRelHumid(u16),
}
impl RawDatum {
pub fn fahrenheit(&self) -> Option<f32> {
match self {
Self::TempAndRelHumid(RawTempAndRelHumid{temperature, ..}) => Some(raw_temp_to_fahrenheit(*temperature)),
Self::MinTemp(u16) => Some(raw_temp_to_fahrenheit(*u16)),
Self::MaxTemp(u16) => Some(raw_temp_to_fahrenheit(*u16)),
Self::MinRelHumid(_) => None,
Self::MaxRelHumid(_) => None,
}
}
pub fn centigrade(&self) -> Option<f32> {
match self {
Self::TempAndRelHumid(RawTempAndRelHumid{temperature, ..}) => Some(raw_temp_to_centigrade(*temperature)),
Self::MinTemp(u16) => Some(raw_temp_to_centigrade(*u16)),
Self::MaxTemp(u16) => Some(raw_temp_to_centigrade(*u16)),
Self::MinRelHumid(_) => None,
Self::MaxRelHumid(_) => None,
}
}
pub fn humidity_percent(&self) -> Option<f32> {
match self {
Self::TempAndRelHumid(RawTempAndRelHumid{humidity, ..}) => Some(raw_rel_humid_to_percent(*humidity)),
Self::MinTemp(_) => None,
Self::MaxTemp(_) => None,
Self::MinRelHumid(u16) => Some(raw_rel_humid_to_percent(*u16)),
Self::MaxRelHumid(u16) => Some(raw_rel_humid_to_percent(*u16)),
}
}
}
#[cfg_attr(feature = "bincode", derive(Encode, Decode))]
#[cfg_attr(feature = "defmt", derive(Format))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone)]
#[derive(Debug)]
#[derive(Default)]
#[derive(PartialEq)]
pub struct RawTempAndRelHumid{
pub temperature: u16,
pub humidity: u16,
}
impl RawTempAndRelHumid {
pub fn fahrenheit(&self) -> f32 {
raw_temp_to_fahrenheit(self.temperature)
}
pub fn centigrade(&self) -> f32 {
raw_temp_to_centigrade(self.temperature)
}
pub fn humidity_percent(&self) -> f32 {
raw_rel_humid_to_percent(self.humidity)
}
}
#[cfg_attr(feature = "bincode", derive(Encode, Decode))]
#[cfg_attr(feature = "defmt", derive(Format))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone)]
#[derive(Debug)]
#[derive(PartialEq)]
pub enum Datum {
TempAndRelHumid(TempAndRelHumid),
MinTemp(Temp),
MaxTemp(Temp),
MinRelHumid(f32),
MaxRelHumid(f32),
}
impl From<&RawDatum> for Datum {
fn from(raw: &RawDatum) -> Self {
match raw {
RawDatum::TempAndRelHumid(raw) => Datum::TempAndRelHumid(raw.into()),
RawDatum::MinTemp(raw) => Datum::MinTemp((*raw).into()),
RawDatum::MaxTemp(raw) => Datum::MaxTemp((*raw).into()),
RawDatum::MinRelHumid(raw) => Datum::MinRelHumid(raw_rel_humid_to_percent(*raw)),
RawDatum::MaxRelHumid(raw) => Datum::MaxRelHumid(raw_rel_humid_to_percent(*raw)),
}
}
}
#[cfg_attr(feature = "bincode", derive(Encode, Decode))]
#[cfg_attr(feature = "defmt", derive(Format))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone)]
#[derive(Debug)]
#[derive(Default)]
#[derive(PartialEq)]
pub struct TempAndRelHumid {
pub centigrade: f32,
pub fahrenheit: f32,
pub humidity_percent: f32,
}
impl From<&RawTempAndRelHumid> for TempAndRelHumid {
fn from(raw: &RawTempAndRelHumid) -> Self {
Self {
centigrade: raw_temp_to_centigrade(raw.temperature),
fahrenheit: raw_temp_to_fahrenheit(raw.temperature),
humidity_percent: raw_rel_humid_to_percent(raw.humidity),
}
}
}
#[cfg_attr(feature = "bincode", derive(Encode, Decode))]
#[cfg_attr(feature = "defmt", derive(Format))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone)]
#[derive(Debug)]
#[derive(Default)]
#[derive(PartialEq)]
pub struct Temp{
pub centigrade: f32,
pub fahrenheit: f32,
}
impl From<u16> for Temp {
fn from(raw: u16) -> Self {
Self {
centigrade: raw_temp_to_centigrade(raw),
fahrenheit: raw_temp_to_fahrenheit(raw),
}
}
}
#[cfg_attr(feature = "bincode", derive(Encode, Decode))]
#[cfg_attr(feature = "defmt", derive(Format))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone)]
#[derive(Debug)]
#[derive(Default)]
#[derive(PartialEq)]
pub struct StatusBits {
raw: u16,
pub at_least_one_alert: bool,
pub heater_enabled: bool,
pub rh_tracking_alert: bool,
pub t_tracking_alert: bool,
pub rh_high_tracking_alert: bool,
pub rh_low_tracking_alert: bool,
pub t_high_tracking_alert: bool,
pub t_low_tracking_alert: bool,
pub reset_since_clear: bool,
pub checksum_failure: bool,
}
impl From<u16> for StatusBits {
fn from(raw: u16) -> Self {
Self {
raw,
at_least_one_alert: (raw >> STATUS_FIELD_LSBIT_AT_LEAST_ONE_ALERT) & ((1 << STATUS_FIELD_WIDTH_AT_LEAST_ONE_ALERT) - 1) != 0,
heater_enabled: (raw >> STATUS_FIELD_LSBIT_HEATER_ENABLED) & ((1 << STATUS_FIELD_WIDTH_HEATER_ENABLED) - 1) != 0,
rh_tracking_alert: (raw >> STATUS_FIELD_LSBIT_RH_TRACKING_ALERT) & ((1 << STATUS_FIELD_WIDTH_RH_TRACKING_ALERT) - 1) != 0,
t_tracking_alert: (raw >> STATUS_FIELD_LSBIT_T_TRACKING_ALERT) & ((1 << STATUS_FIELD_WIDTH_T_TRACKING_ALERT) - 1) != 0,
rh_high_tracking_alert: (raw >> STATUS_FIELD_LSBIT_RH_HIGH_TRACKING_ALERT) & ((1 << STATUS_FIELD_WIDTH_RH_HIGH_TRACKING_ALERT) - 1) != 0,
rh_low_tracking_alert: (raw >> STATUS_FIELD_LSBIT_RH_LOW_TRACKING_ALERT) & ((1 << STATUS_FIELD_WIDTH_RH_LOW_TRACKING_ALERT) - 1) != 0,
t_high_tracking_alert: (raw >> STATUS_FIELD_LSBIT_T_HIGH_TRACKING_ALERT) & ((1 << STATUS_FIELD_WIDTH_T_HIGH_TRACKING_ALERT) - 1) != 0,
t_low_tracking_alert: (raw >> STATUS_FIELD_LSBIT_T_LOW_TRACKING_ALERT) & ((1 << STATUS_FIELD_WIDTH_T_LOW_TRACKING_ALERT) - 1) != 0,
reset_since_clear: (raw >> STATUS_FIELD_LSBIT_RESET_SINCE_CLEAR) & ((1 << STATUS_FIELD_WIDTH_RESET_SINCE_CLEAR) - 1) != 0,
checksum_failure: (raw >> STATUS_FIELD_LSBIT_CHECKSUM_FAILURE) & ((1 << STATUS_FIELD_WIDTH_CHECKSUM_FAILURE) - 1) != 0,
}
}
}
impl StatusBits {
pub fn raw(&self) -> u16 {
self.raw
}
}
impl fmt::Display for StatusBits {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "StatusBits {{ 0x{:02x}; ", self.raw)?;
if self.at_least_one_alert {
write!(f, "at_least_one_alert ")?;
}
if self.heater_enabled {
write!(f, "heater_enabled ")?;
}
if self.rh_tracking_alert {
write!(f, "rh_tracking_alert ")?;
}
if self.t_tracking_alert {
write!(f, "t_tracking_alert ")?;
}
if self.rh_high_tracking_alert {
write!(f, "rh_high_tracking_alert ")?;
}
if self.rh_low_tracking_alert {
write!(f, "rh_low_tracking_alert ")?;
}
if self.t_high_tracking_alert {
write!(f, "t_high_tracking_alert ")?;
}
if self.t_low_tracking_alert {
write!(f, "t_low_tracking_alert ")?;
}
if self.reset_since_clear {
write!(f, "reset_since_clear ")?;
}
if self.checksum_failure {
write!(f, "checksum_failure ")?;
}
write!(f, "}}")
}
}
#[cfg_attr(feature = "bincode", derive(Encode, Decode))]
#[cfg_attr(feature = "defmt", derive(Format))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone)]
#[derive(Debug)]
#[derive(Default)]
#[derive(PartialEq)]
pub struct SerialNumber(pub [u8; 6]);
impl fmt::Display for SerialNumber {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for byte in self.0.iter().rev() {
write!(f, "{:02X}", byte)?;
}
Ok(())
}
}
impl core::ops::Deref for SerialNumber {
type Target = [u8; 6];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl AsRef<[u8; 6]> for SerialNumber {
fn as_ref(&self) -> &[u8; 6] {
&self.0
}
}
#[cfg_attr(feature = "bincode", derive(Encode, Decode))]
#[cfg_attr(feature = "defmt", derive(Format))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone)]
#[derive(Debug)]
#[derive(Default)]
#[derive(PartialEq)]
pub enum ManufacturerId {
#[default]
TexasInstruments,
Other(u16),
}
impl From<u16> for ManufacturerId {
fn from(raw: u16) -> Self {
match raw {
MANUFACTURER_ID_TEXAS_INSTRUMENTS => ManufacturerId::TexasInstruments,
_ => ManufacturerId::Other(raw),
}
}
}
impl From<ManufacturerId> for u16 {
fn from(manuf_id: ManufacturerId) -> u16 {
match manuf_id {
ManufacturerId::TexasInstruments => MANUFACTURER_ID_TEXAS_INSTRUMENTS,
ManufacturerId::Other(id) => id,
}
}
}
impl fmt::Display for ManufacturerId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ManufacturerId::TexasInstruments => {
let mid_u16: u16 = self.clone().into();
write!(f, "Texas Instruments (0x{mid_u16:04X})")
}
ManufacturerId::Other(mid_u16) => write!(f, "Unknown (0x{mid_u16:04X})"),
}
}
}