#![doc = include_str!("../README.md")]
#![no_std]
#![deny(missing_docs)]
use device_register::{EditRegister, ReadRegister, WriteRegister};
use embedded_hal::{
delay::DelayNs,
i2c::{I2c, SevenBitAddress},
};
pub use error::Error;
use register::*;
use tmp117_ll::Tmp117LL;
pub mod asynchronous;
pub mod error;
pub mod register;
pub mod tmp117_ll;
pub const CELCIUS_CONVERSION: f32 = 0.0078125;
pub enum Alert {
None,
High,
Low,
HighLow,
}
#[derive(Default)]
pub struct ContinuousConfig {
pub average: Average,
pub conversion: Conversion,
pub high: Option<f32>,
pub low: Option<f32>,
pub offset: Option<f32>,
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Id {
pub device: u16,
pub revision: u8,
}
pub struct Tmp117<T, E> {
tmp_ll: Tmp117LL<T, E>,
}
impl<T, E> Tmp117<T, E>
where
T: I2c<SevenBitAddress, Error = E>,
E: embedded_hal::i2c::Error,
{
pub fn new(i2c: T, addr: u8) -> Self {
Tmp117::<T, E> {
tmp_ll: Tmp117LL::new(i2c, addr),
}
}
pub fn new_from_ll(tmp_ll: Tmp117LL<T, E>) -> Self {
Tmp117::<T, E> { tmp_ll }
}
pub fn id(&mut self) -> Result<Id, Error<E>> {
let id: DeviceID = self.tmp_ll.read()?;
Ok(Id {
device: id.device_id().into(),
revision: id.revision().into(),
})
}
fn wait_eeprom(&mut self) -> Result<(), Error<E>> {
let mut configuration: Configuration = self.tmp_ll.read()?;
while configuration.eeprom_busy() {
configuration = self.tmp_ll.read()?;
}
Ok(())
}
fn read_temp_raw(&mut self) -> Result<f32, Error<E>> {
let temp: Temperature = self.tmp_ll.read()?;
let val = (u16::from(temp) as i16) as f32 * CELCIUS_CONVERSION;
Ok(val)
}
fn check_alert(&mut self) -> Result<Alert, Error<E>> {
let config: Configuration = self.tmp_ll.read()?;
if config.high_alert() && config.low_alert() {
Ok(Alert::HighLow)
} else if config.high_alert() {
Ok(Alert::High)
} else if config.low_alert() {
Ok(Alert::Low)
} else {
Ok(Alert::None)
}
}
fn wait_for_data(&mut self) -> Result<(), Error<E>> {
loop {
let config: Configuration = self.tmp_ll.read()?;
if config.data_ready() {
break;
}
}
Ok(())
}
fn wait_for_alert(&mut self) -> Result<Alert, Error<E>> {
loop {
let alert = self.check_alert();
if let Ok(Alert::None) = alert {
continue;
} else {
return alert;
}
}
}
fn set_continuous(
&mut self,
config: ContinuousConfig,
) -> Result<ContinuousHandler<'_, T, E>, Error<E>> {
if let Some(val) = config.high {
let high: HighLimit = ((val / CELCIUS_CONVERSION) as u16).into();
self.tmp_ll.write(high)?;
}
if let Some(val) = config.low {
let low: LowLimit = ((val / CELCIUS_CONVERSION) as u16).into();
self.tmp_ll.write(low)?;
}
if let Some(val) = config.offset {
let off: TemperatureOffset = ((val / CELCIUS_CONVERSION) as u16).into();
self.tmp_ll.write(off)?;
}
self.tmp_ll.edit(|r: &mut Configuration| {
r.set_mode(ConversionMode::Continuous);
r.set_polarity(Polarity::ActiveLow);
r.set_average(config.average);
r.set_conversion(config.conversion);
})?;
Ok(ContinuousHandler { tmp117: self })
}
fn set_oneshot(&mut self, average: Average) -> Result<(), Error<E>> {
self.tmp_ll.edit(|r: &mut Configuration| {
r.set_mode(ConversionMode::OneShot);
r.set_polarity(Polarity::ActiveLow);
r.set_average(average);
})?;
Ok(())
}
fn set_shutdown(&mut self) -> Result<(), Error<E>> {
self.tmp_ll.edit(|r: &mut Configuration| {
r.set_mode(ConversionMode::Shutdown);
})?;
Ok(())
}
pub fn reset<D>(&mut self, delay: &mut D) -> Result<(), Error<E>>
where
D: DelayNs,
{
self.tmp_ll.edit(|r: &mut Configuration| {
r.set_reset(true);
})?;
delay.delay_ms(2);
self.set_shutdown()?;
Ok(())
}
pub fn write_eeprom(&mut self, values: [u16; 3]) -> Result<(), Error<E>> {
self.wait_eeprom()?;
self.tmp_ll.write(UEEPROM1::from(values[0]))?;
self.wait_eeprom()?;
self.tmp_ll.write(UEEPROM2::from(values[1]))?;
self.wait_eeprom()?;
self.tmp_ll.write(UEEPROM3::from(values[2]))?;
Ok(())
}
pub fn read_eeprom(&mut self) -> Result<[u16; 3], Error<E>> {
let u1: UEEPROM1 = self.tmp_ll.read()?;
let u2: UEEPROM2 = self.tmp_ll.read()?;
let u3: UEEPROM3 = self.tmp_ll.read()?;
Ok([u1.into(), u2.into(), u3.into()])
}
pub fn oneshot(&mut self, average: Average) -> Result<f32, Error<E>> {
self.set_oneshot(average)?;
self.wait_for_data()?;
let data = self.read_temp_raw()?;
Ok(data)
}
pub fn continuous<F>(&mut self, config: ContinuousConfig, f: F) -> Result<(), Error<E>>
where
F: FnOnce(ContinuousHandler<'_, T, E>) -> Result<(), Error<E>>,
{
let handler = self.set_continuous(config)?;
f(handler)?;
self.set_shutdown()
}
}
pub struct ContinuousHandler<'a, T, E> {
tmp117: &'a mut Tmp117<T, E>,
}
impl<'a, T, E> ContinuousHandler<'a, T, E>
where
T: I2c<SevenBitAddress, Error = E>,
E: embedded_hal::i2c::Error,
{
pub fn read_temp(&mut self) -> Result<f32, Error<E>> {
let config: Configuration = self.tmp117.tmp_ll.read()?;
if !config.data_ready() {
return Err(Error::DataNotReady);
}
let val = self.tmp117.read_temp_raw()?;
Ok(val)
}
pub fn wait_temp(&mut self) -> Result<f32, Error<E>> {
self.tmp117.wait_for_data()?;
let val = self.tmp117.read_temp_raw()?;
Ok(val)
}
pub fn get_alert(&mut self) -> Result<Alert, Error<E>> {
let val = self.tmp117.check_alert()?;
Ok(val)
}
pub fn wait_alert(&mut self) -> Result<Alert, Error<E>> {
let val = self.tmp117.wait_for_alert()?;
Ok(val)
}
}