use core::pin::pin;
use embedded_hal_async::{delay::DelayNs, digital::Wait, i2c::I2c};
use crate::{i2c::Device, Register};
pub(crate) async fn has_measurement<I2C>(i2c: &mut Device<I2C>) -> Result<bool, I2C::Error>
where
I2C: I2c,
{
let ctrl = i2c.read_byte(Register::GPIO_HV_MUX_CTRL).await?;
let status = i2c.read_byte(Register::GPIO_TIO_HV_STATUS).await?;
Ok(status & 1 != ctrl >> 4 & 1)
}
pub trait WaitForMeasurement<I2C, DELAY>
where
I2C: I2c,
DELAY: DelayNs,
{
#[allow(async_fn_in_trait)]
async fn wait_for_measurement(
&mut self,
i2c: &mut Device<I2C>,
delay: &mut DELAY,
) -> Result<(), crate::Error<I2C::Error>>;
}
pub struct Poll;
impl<I2C, DELAY> WaitForMeasurement<I2C, DELAY> for Poll
where
I2C: I2c,
DELAY: DelayNs,
{
#[inline]
async fn wait_for_measurement(
&mut self,
i2c: &mut Device<I2C>,
delay: &mut DELAY,
) -> Result<(), crate::Error<I2C::Error>> {
for _ in 0u16..1000 {
if has_measurement(i2c).await? {
return Ok(());
}
delay.delay_ms(1).await;
}
Err(crate::Error::Timeout)
}
}
pub struct Interrupt<PIN>(pub PIN);
impl<PIN, I2C, DELAY> WaitForMeasurement<I2C, DELAY> for Interrupt<PIN>
where
I2C: I2c,
DELAY: DelayNs,
PIN: Wait,
{
#[inline]
async fn wait_for_measurement(
&mut self,
_i2c: &mut Device<I2C>,
delay: &mut DELAY,
) -> Result<(), crate::Error<I2C::Error>> {
use futures_util::future::{select, Either};
match select(pin!(delay.delay_ms(1000)), pin!(self.0.wait_for_low())).await {
Either::Left(_) => Err(crate::Error::Timeout),
Either::Right((Ok(()), _)) => Ok(()),
Either::Right((Err(_gpio_err), _)) => Err(crate::Error::Gpio),
}
}
}