use crate::{
ic,
register_access::mlx90614::{self, Register, DEV_ADDR},
Error, Mlx9061x, SlaveAddr,
};
use core::marker::PhantomData;
use embedded_hal::{
blocking::{delay::DelayMs, i2c},
digital::v2::OutputPin,
};
impl<E, I2C> Mlx9061x<I2C, ic::Mlx90614>
where
I2C: i2c::WriteRead<Error = E> + i2c::Write<Error = E>,
{
pub fn new_mlx90614(
i2c: I2C,
address: SlaveAddr,
eeprom_write_delay_ms: u8,
) -> Result<Self, Error<E>> {
let address = Self::get_address(address, DEV_ADDR)?;
Ok(Mlx9061x {
i2c,
eeprom_write_delay_ms,
address,
_ic: PhantomData,
})
}
pub fn ambient_temperature(&mut self) -> Result<f32, Error<E>> {
let t = self.read_u16(Register::TA)?;
let t = f32::from(t) * 0.02 - 273.15;
Ok(t)
}
pub fn object1_temperature(&mut self) -> Result<f32, Error<E>> {
let t = self.read_u16(Register::TOBJ1)?;
let t = f32::from(t) * 0.02 - 273.15;
Ok(t)
}
pub fn object2_temperature(&mut self) -> Result<f32, Error<E>> {
let t = self.read_u16(Register::TOBJ2)?;
let t = f32::from(t) * 0.02 - 273.15;
Ok(t)
}
pub fn raw_ir_channel1(&mut self) -> Result<u16, Error<E>> {
self.read_u16(Register::RAW_IR1)
}
pub fn raw_ir_channel2(&mut self) -> Result<u16, Error<E>> {
self.read_u16(Register::RAW_IR2)
}
pub fn emissivity(&mut self) -> Result<f32, Error<E>> {
let raw = self.read_u16(Register::EMISSIVITY)?;
Ok(f32::from(raw) / 65535.0)
}
pub fn set_emissivity<D: DelayMs<u8>>(
&mut self,
epsilon: f32,
delay: &mut D,
) -> Result<(), Error<E>> {
if epsilon < 0.1 || epsilon > 1.0 {
return Err(Error::InvalidInputData);
}
let eps = (epsilon * 65535.0 + 0.5) as u16;
if eps < 6553 {
return Err(Error::InvalidInputData);
}
self.write_u16_eeprom(Register::EMISSIVITY, eps as u16, delay)
}
pub fn device_id(&mut self) -> Result<u64, Error<E>> {
let mut id = 0;
for i in 0..4 {
let part = self.read_u16(Register::ID0 + i)?;
let part = u64::from(part) << (16 * (3 - i));
id |= part;
}
Ok(id)
}
}
pub fn wake_mlx90614<
E,
SclPin: OutputPin<Error = E>,
SdaPin: OutputPin<Error = E>,
D: DelayMs<u8>,
>(
scl: &mut SclPin,
sda: &mut SdaPin,
delay: &mut D,
) -> Result<(), E> {
scl.set_high()?;
sda.set_low()?;
delay.delay_ms(mlx90614::WAKE_DELAY_MS);
sda.set_high()
}