hts221-async 0.2.0

Async driver for the HTS221 temperature sensor.
Documentation
use super::super::I2cAddress;
use embedded_hal_async::i2c::*;

const CTRL_REG1: u8 = 0x20;

#[derive(Debug, Copy, Clone)]
enum Power {
    PowerDown,
    Active,
}

#[derive(Debug, Copy, Clone)]
pub enum BlockDataUpdate {
    Continuous,
    MsbLsbReading,
}

#[derive(Debug, Copy, Clone)]
pub enum OutputDataRate {
    OneShot,
    Hz1,
    Hz7,
    Hz12p5,
}

#[derive(Debug, Copy, Clone)]
pub(crate) struct Ctrl1 {
    power_down: Power,
    block_data_update: BlockDataUpdate,
    output_data_rate: OutputDataRate,
}

impl Ctrl1 {
    pub async fn read<I: I2c>(address: I2cAddress, i2c: &mut I) -> Result<Ctrl1, I::Error> {
        let mut buf = [0; 1];
        let _ = i2c
            .write_read(address.into(), &[CTRL_REG1], &mut buf)
            .await?;
        Ok(buf[0].into())
    }

    pub async fn write<I: I2c>(
        address: I2cAddress,
        i2c: &mut I,
        reg: Ctrl1,
    ) -> Result<(), I::Error> {
        let bytes = [CTRL_REG1, reg.into()];
        Ok(i2c.write(address.into(), &bytes).await?)
    }

    pub async fn modify<I: I2c, F: FnOnce(&mut Ctrl1)>(
        address: I2cAddress,
        i2c: &mut I,
        modify: F,
    ) -> Result<(), I::Error> {
        let mut reg = Self::read(address.into(), i2c).await?;
        modify(&mut reg);
        Self::write(address.into(), i2c, reg).await
    }

    #[allow(dead_code)]
    pub fn power_down(&mut self) -> &Self {
        self.power_down = Power::PowerDown;
        self
    }

    pub fn power_active(&mut self) -> &mut Self {
        self.power_down = Power::Active;
        self
    }

    pub fn output_data_rate(&mut self, odr: OutputDataRate) -> &mut Self {
        self.output_data_rate = odr;
        self
    }

    pub fn block_data_update(&mut self, bdu: BlockDataUpdate) -> &mut Self {
        self.block_data_update = bdu;
        self
    }
}

impl Into<Power> for u8 {
    fn into(self) -> Power {
        if (self & 0x80) != 0 {
            Power::Active
        } else {
            Power::PowerDown
        }
    }
}

impl From<Power> for u8 {
    fn from(p: Power) -> Self {
        match p {
            Power::PowerDown => 0b00000000,
            Power::Active => 0b10000000,
        }
    }
}

impl Into<BlockDataUpdate> for u8 {
    fn into(self) -> BlockDataUpdate {
        if (self & 0x40) != 0 {
            BlockDataUpdate::MsbLsbReading
        } else {
            BlockDataUpdate::Continuous
        }
    }
}

impl From<BlockDataUpdate> for u8 {
    fn from(bdu: BlockDataUpdate) -> u8 {
        match bdu {
            BlockDataUpdate::Continuous => 0b000,
            BlockDataUpdate::MsbLsbReading => 0b100,
        }
    }
}

impl Into<OutputDataRate> for u8 {
    fn into(self) -> OutputDataRate {
        let v = self & 0b11;

        match v {
            0b01 => OutputDataRate::Hz1,
            0b10 => OutputDataRate::Hz7,
            0b11 => OutputDataRate::Hz12p5,
            _ => OutputDataRate::OneShot,
        }
    }
}

impl From<OutputDataRate> for u8 {
    fn from(odr: OutputDataRate) -> Self {
        match odr {
            OutputDataRate::OneShot => 0b00,
            OutputDataRate::Hz1 => 0b01,
            OutputDataRate::Hz7 => 0b10,
            OutputDataRate::Hz12p5 => 0b11,
        }
    }
}

impl Into<Ctrl1> for u8 {
    fn into(self) -> Ctrl1 {
        Ctrl1 {
            power_down: self.into(),
            output_data_rate: self.into(),
            block_data_update: self.into(),
        }
    }
}

impl Into<u8> for Ctrl1 {
    fn into(self) -> u8 {
        u8::from(self.power_down)
            | u8::from(self.output_data_rate)
            | u8::from(self.block_data_update)
    }
}