use embedded_devices_derive::{forward_register_fns, sensor};
use embedded_interfaces::TransportError;
use uom::si::f64::ThermodynamicTemperature;
use uom::si::thermodynamic_temperature::degree_celsius;
pub mod address;
pub mod registers;
use self::registers::{Configuration, Temperature};
#[derive(Debug, embedded_devices_derive::Measurement)]
pub struct Measurement {
#[measurement(Temperature)]
pub temperature: ThermodynamicTemperature,
}
#[maybe_async_cfg::maybe(
idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), RegisterInterface),
sync(feature = "sync"),
async(feature = "async")
)]
pub struct TMP102<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> {
delay: D,
interface: I,
}
pub trait TMP102Register {}
#[maybe_async_cfg::maybe(
idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), I2cDevice),
sync(feature = "sync"),
async(feature = "async")
)]
impl<D, I> TMP102<D, embedded_interfaces::i2c::I2cDevice<I, hal::i2c::SevenBitAddress>>
where
I: hal::i2c::I2c<hal::i2c::SevenBitAddress> + hal::i2c::ErrorType,
D: hal::delay::DelayNs,
{
#[inline]
pub fn new_i2c(delay: D, interface: I, address: self::address::Address) -> Self {
Self {
delay,
interface: embedded_interfaces::i2c::I2cDevice::new(interface, address.into()),
}
}
}
#[forward_register_fns]
#[sensor(Temperature)]
#[maybe_async_cfg::maybe(
idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), RegisterInterface),
sync(feature = "sync"),
async(feature = "async")
)]
impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> TMP102<D, I> {
pub async fn read_temperature(&mut self) -> Result<ThermodynamicTemperature, TransportError<(), I::BusError>> {
let reg_conf = self.read_register::<Configuration>().await?;
let raw_temp = self.read_register::<Temperature>().await?.read_raw_temperature() as i32;
if reg_conf.read_extended() {
Ok(ThermodynamicTemperature::new::<degree_celsius>(raw_temp as f64 / 128.0))
} else {
Ok(ThermodynamicTemperature::new::<degree_celsius>(raw_temp as f64 / 256.0))
}
}
}
#[maybe_async_cfg::maybe(
idents(
hal(sync = "embedded_hal", async = "embedded_hal_async"),
RegisterInterface,
OneshotSensor
),
sync(feature = "sync"),
async(feature = "async")
)]
impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> crate::sensor::OneshotSensor
for TMP102<D, I>
{
type Error = TransportError<(), I::BusError>;
type Measurement = Measurement;
async fn measure(&mut self) -> Result<Self::Measurement, Self::Error> {
let reg_conf = self.read_register::<Configuration>().await?;
self.write_register(reg_conf.with_oneshot(true).with_shutdown(false))
.await?;
self.delay.delay_us(12_500).await;
let raw_temp = self.read_register::<Temperature>().await?.read_raw_temperature() as i32;
if reg_conf.read_extended() {
Ok(Measurement {
temperature: ThermodynamicTemperature::new::<degree_celsius>(raw_temp as f64 / 128.0),
})
} else {
Ok(Measurement {
temperature: ThermodynamicTemperature::new::<degree_celsius>(raw_temp as f64 / 256.0),
})
}
}
}
#[maybe_async_cfg::maybe(
idents(
hal(sync = "embedded_hal", async = "embedded_hal_async"),
RegisterInterface,
ContinuousSensor
),
sync(feature = "sync"),
async(feature = "async")
)]
impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> crate::sensor::ContinuousSensor
for TMP102<D, I>
{
type Error = TransportError<(), I::BusError>;
type Measurement = Measurement;
async fn start_measuring(&mut self) -> Result<(), Self::Error> {
let reg_conf = self.read_register::<Configuration>().await?;
self.write_register(reg_conf.with_oneshot(false).with_shutdown(false))
.await?;
Ok(())
}
async fn stop_measuring(&mut self) -> Result<(), Self::Error> {
let reg_conf = self.read_register::<Configuration>().await?;
self.write_register(reg_conf.with_oneshot(false).with_shutdown(true))
.await?;
Ok(())
}
async fn measurement_interval_us(&mut self) -> Result<u32, Self::Error> {
let reg_conf = self.read_register::<Configuration>().await?;
let conversion_time_us = reg_conf.read_conversion_cycle_time().conversion_time_ms() * 1000;
Ok(conversion_time_us)
}
async fn current_measurement(&mut self) -> Result<Option<Self::Measurement>, Self::Error> {
let raw_temp = self.read_register::<Temperature>().await?.read_raw_temperature() as i32;
let reg_conf = self.read_register::<Configuration>().await?;
if reg_conf.read_extended() {
Ok(Some(Measurement {
temperature: ThermodynamicTemperature::new::<degree_celsius>(raw_temp as f64 / 128.0),
}))
} else {
Ok(Some(Measurement {
temperature: ThermodynamicTemperature::new::<degree_celsius>(raw_temp as f64 / 256.0),
}))
}
}
async fn is_measurement_ready(&mut self) -> Result<bool, Self::Error> {
Ok(true)
}
async fn next_measurement(&mut self) -> Result<Self::Measurement, Self::Error> {
let interval = self.measurement_interval_us().await?;
self.delay.delay_us(interval).await;
self.current_measurement()
.await?
.ok_or_else(|| TransportError::Unexpected("measurement was not ready even though we expected it to be"))
}
}