use crate::commands::CommandId;
use crate::connection::State;
use crate::io::{FromBytes, ToBytes};
use crate::types::Milliseconds;
use crate::{Sen6x, SensorConnectionSync, SensorState, errors};
use core::cell::RefCell;
use embedded_hal::delay::DelayNs;
use embedded_hal::i2c::{I2c, Operation};
impl<'a, I2C, D, E> SensorConnectionSync for Sen6x<'a, RefCell<&'a mut I2C>, D>
where
I2C: I2c<Error = E>,
D: DelayNs,
{
type I2c = I2C;
type Error = E;
type Delay = D;
fn transaction<R>(&self, f: impl FnOnce(&mut I2C) -> R) -> R {
let mut i2c = self.i2c.borrow_mut();
f(&mut i2c)
}
fn delay(&self, delay: Milliseconds) {
self.delay.borrow_mut().delay_ms(delay as u32);
}
}
impl<S, T> crate::connection::Sen6xConnection<S, T::Error> for T
where
T: SensorConnectionSync + SensorState<T::Error>,
S: crate::connection::SensorModel,
{
fn send(
&mut self,
cmd: CommandId,
execution_time: Milliseconds,
valid_in: &[State],
) -> Result<(), crate::Error<T::Error>> {
self.check_state(valid_in)?;
let this = &*self;
this.transaction(move |i2c| {
i2c.write(S::I2C_ADDRESS, &(cmd as u16).to_be_bytes())
.map_err(errors::Error::I2c)?;
this.delay(execution_time);
Ok(())
})
}
fn write<const N: usize, Tx: ToBytes<N>>(
&mut self,
cmd: CommandId,
execution_time: Milliseconds,
data: Tx,
valid_in: &[State],
) -> Result<(), crate::Error<T::Error>> {
self.check_state(valid_in)?;
let this = &*self;
this.transaction(move |i2c| {
i2c.transaction(
S::I2C_ADDRESS,
&mut [
Operation::Write(&(cmd as u16).to_be_bytes()),
Operation::Write(&data.to_bytes()),
],
)
.map_err(errors::Error::I2c)?;
this.delay(execution_time);
Ok(())
})
}
fn read<const N: usize, Rx: FromBytes<N, Rx>>(
&mut self,
cmd: CommandId,
execution_time: Milliseconds,
valid_in: &[State],
) -> Result<Rx, crate::Error<T::Error>> {
self.check_state(valid_in)?;
let this = &*self;
this.transaction(move |i2c| {
i2c.write(S::I2C_ADDRESS, &(cmd as u16).to_be_bytes())
.map_err(errors::Error::I2c)?;
this.delay(execution_time);
let mut buffer = [0u8; N];
i2c.read(S::I2C_ADDRESS, &mut buffer)
.map_err(errors::Error::I2c)?;
Rx::from_bytes_with_crc(&buffer)
})
}
fn fetch<const NT: usize, const NR: usize, Rx: FromBytes<NR, Rx>, Tx: ToBytes<NT>>(
&mut self,
cmd: CommandId,
execution_time: Milliseconds,
data: Tx,
valid_in: &[State],
) -> Result<Rx, crate::Error<T::Error>> {
self.check_state(valid_in)?;
let this = &*self;
this.transaction(move |i2c| {
i2c.transaction(
S::I2C_ADDRESS,
&mut [
Operation::Write(&(cmd as u16).to_be_bytes()),
Operation::Write(&data.to_bytes()),
],
)
.map_err(errors::Error::I2c)?;
this.delay(execution_time);
let mut buffer = [0u8; NR];
i2c.read(S::I2C_ADDRESS, &mut buffer)
.map_err(errors::Error::I2c)?;
Rx::from_bytes_with_crc(&buffer)
})
}
fn update_state(&mut self, state: State) {
*self.state() = state;
}
}