use crate::Address;
use embedded_hal_async::i2c::I2c;
pub struct Tca9554<I2C> {
i2c: I2C,
address: Address,
}
impl<I2C> Tca9554<I2C> {
pub fn new(i2c: I2C, address: Address) -> Self {
Self { i2c, address }
}
pub fn address(&self) -> Address {
self.address
}
pub fn release(self) -> I2C {
self.i2c
}
}
#[repr(u8)]
enum Register {
Input = 0x00,
Output = 0x01,
Polarity = 0x02,
Direction = 0x03,
}
const OUTPUT_REGISTER_DEFAULT: u8 = 0xFF;
const POLARITY_REGISTER_DEFAULT: u8 = 0x00;
const DIRECTION_REGISTER_DEFAULT: u8 = 0xFF;
impl<I2C, E> Tca9554<I2C>
where
I2C: I2c<Error = E>,
{
pub async fn read_input(&mut self) -> Result<u8, E> {
self.read_register(Register::Input).await
}
pub async fn read_output(&mut self) -> Result<u8, E> {
self.read_register(Register::Output).await
}
pub async fn write_output(&mut self, state: u8) -> Result<(), E> {
self.write_register(Register::Output, state).await
}
pub async fn read_polarity(&mut self) -> Result<u8, E> {
self.read_register(Register::Polarity).await
}
pub async fn write_polarity(&mut self, state: u8) -> Result<(), E> {
self.write_register(Register::Polarity, state).await
}
pub async fn read_direction(&mut self) -> Result<u8, E> {
self.read_register(Register::Direction).await
}
pub async fn write_direction(&mut self, state: u8) -> Result<(), E> {
self.write_register(Register::Direction, state).await
}
pub async fn reset(&mut self) -> Result<(), E> {
self.write_direction(DIRECTION_REGISTER_DEFAULT).await?;
self.write_polarity(POLARITY_REGISTER_DEFAULT).await?;
self.write_output(OUTPUT_REGISTER_DEFAULT).await?;
Ok(())
}
pub async fn is_in_default_state(&mut self) -> Result<bool, E> {
Ok(self.read_direction().await? == DIRECTION_REGISTER_DEFAULT
&& self.read_polarity().await? == POLARITY_REGISTER_DEFAULT
&& self.read_output().await? == OUTPUT_REGISTER_DEFAULT)
}
async fn write_register(&mut self, register: Register, value: u8) -> Result<(), E> {
self.i2c
.write(self.address.into(), &[register as u8, value])
.await?;
Ok(())
}
async fn read_register(&mut self, register: Register) -> Result<u8, E> {
let mut read_buf = [0u8];
self.i2c
.write_read(self.address.into(), &[register as u8], &mut read_buf)
.await?;
Ok(read_buf[0])
}
}