use super::{Interface, MAX_WRITE_LEN};
use crate::errors::{GyroError, XmError};
use crate::registers::device_constants::{gyro, xm};
use embedded_hal_async::i2c::I2c;
const AUTO_INCREMENT: u8 = 0x80;
pub struct I2cInterface<I2C> {
i2c: I2C,
gyro_addr: u8,
xm_addr: u8,
}
impl<I2C> I2cInterface<I2C> {
pub fn init(i2c: I2C) -> Self {
Self {
i2c,
gyro_addr: gyro::I2C_ADDR_0,
xm_addr: xm::I2C_ADDR_0,
}
}
pub fn init_with_addresses(i2c: I2C, gyro_addr: u8, xm_addr: u8) -> Self {
Self {
i2c,
gyro_addr,
xm_addr,
}
}
pub fn release(self) -> I2C {
self.i2c
}
}
const WRITE_BUFFER_SIZE: usize = MAX_WRITE_LEN + 1;
impl<I2C, E> Interface for I2cInterface<I2C>
where
I2C: I2c<Error = E>,
{
type BusError = E;
async fn write_gyro(&mut self, addr: u8, data: &[u8]) -> Result<(), GyroError<E>> {
debug_assert!(
data.len() <= MAX_WRITE_LEN,
"write() data length {} exceeds MAX_WRITE_LEN ({})",
data.len(),
MAX_WRITE_LEN
);
let mut buffer = [0u8; WRITE_BUFFER_SIZE];
buffer[0] = if data.len() > 1 {
addr | AUTO_INCREMENT
} else {
addr
};
let len = data.len().min(MAX_WRITE_LEN);
buffer[1..=len].copy_from_slice(&data[..len]);
Ok(self.i2c.write(self.gyro_addr, &buffer[..=len]).await?)
}
async fn write_xm(&mut self, addr: u8, data: &[u8]) -> Result<(), XmError<E>> {
debug_assert!(
data.len() <= MAX_WRITE_LEN,
"write() data length {} exceeds MAX_WRITE_LEN ({})",
data.len(),
MAX_WRITE_LEN
);
let mut buffer = [0u8; WRITE_BUFFER_SIZE];
buffer[0] = if data.len() > 1 {
addr | AUTO_INCREMENT
} else {
addr
};
let len = data.len().min(MAX_WRITE_LEN);
buffer[1..=len].copy_from_slice(&data[..len]);
Ok(self.i2c.write(self.xm_addr, &buffer[..=len]).await?)
}
async fn read_gyro(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), GyroError<E>> {
let reg_addr = if buffer.len() > 1 {
addr | AUTO_INCREMENT
} else {
addr
};
Ok(self
.i2c
.write_read(self.gyro_addr, &[reg_addr], buffer)
.await?)
}
async fn read_xm(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), XmError<E>> {
let reg_addr = if buffer.len() > 1 {
addr | AUTO_INCREMENT
} else {
addr
};
Ok(self
.i2c
.write_read(self.xm_addr, &[reg_addr], buffer)
.await?)
}
}