use embedded_hal::i2c::I2c;
use embedded_hal::spi::{Operation, SpiDevice};
use embedded_hal_async::i2c::I2c as AsyncI2c;
use embedded_hal_async::spi::SpiDevice as AsyncSpiDevice;
use crate::{Bmi323, Bmi323Async};
pub struct SyncI2cTransport<I2C> {
pub(crate) bus: I2C,
pub(crate) address: u8,
}
pub struct SyncSpiTransport<SPI> {
pub(crate) bus: SPI,
}
pub struct AsyncI2cTransport<I2C> {
pub(crate) bus: I2C,
pub(crate) address: u8,
}
pub struct AsyncSpiTransport<SPI> {
pub(crate) bus: SPI,
}
pub trait SyncAccess {
type BusError;
fn read_word(&mut self, reg: u8) -> Result<u16, Self::BusError>;
fn write_word(&mut self, reg: u8, word: u16) -> Result<(), Self::BusError>;
fn read_words(&mut self, reg: u8, words: &mut [u16]) -> Result<(), Self::BusError>;
}
#[allow(async_fn_in_trait)]
pub trait AsyncAccess {
type BusError;
async fn read_word(&mut self, reg: u8) -> Result<u16, Self::BusError>;
async fn write_word(&mut self, reg: u8, word: u16) -> Result<(), Self::BusError>;
async fn read_words(&mut self, reg: u8, words: &mut [u16]) -> Result<(), Self::BusError>;
}
impl<I2C> SyncAccess for Bmi323<SyncI2cTransport<I2C>>
where
I2C: I2c,
{
type BusError = I2C::Error;
fn read_word(&mut self, reg: u8) -> Result<u16, Self::BusError> {
let mut bytes = [0u8; 4];
self.transport
.bus
.write_read(self.transport.address, &[reg], &mut bytes)?;
Ok(u16::from_le_bytes([bytes[2], bytes[3]]))
}
fn write_word(&mut self, reg: u8, word: u16) -> Result<(), Self::BusError> {
let [lo, hi] = word.to_le_bytes();
self.transport
.bus
.write(self.transport.address, &[reg, lo, hi])
}
fn read_words(&mut self, reg: u8, words: &mut [u16]) -> Result<(), Self::BusError> {
let mut bytes = [0u8; 2 * 64 + 2];
let byte_len = words.len() * 2 + 2;
self.transport
.bus
.write_read(self.transport.address, &[reg], &mut bytes[..byte_len])?;
for (index, word) in words.iter_mut().enumerate() {
let offset = 2 + index * 2;
*word = u16::from_le_bytes([bytes[offset], bytes[offset + 1]]);
}
Ok(())
}
}
impl<SPI> SyncAccess for Bmi323<SyncSpiTransport<SPI>>
where
SPI: SpiDevice<u8>,
{
type BusError = SPI::Error;
fn read_word(&mut self, reg: u8) -> Result<u16, Self::BusError> {
let cmd = 0x80 | (reg & 0x7F);
let mut bytes = [0u8; 3];
let mut ops = [Operation::Write(&[cmd]), Operation::Read(&mut bytes)];
self.transport.bus.transaction(&mut ops)?;
Ok(u16::from_le_bytes([bytes[1], bytes[2]]))
}
fn write_word(&mut self, reg: u8, word: u16) -> Result<(), Self::BusError> {
let [lo, hi] = word.to_le_bytes();
let payload = [reg & 0x7F, lo, hi];
self.transport.bus.write(&payload)
}
fn read_words(&mut self, reg: u8, words: &mut [u16]) -> Result<(), Self::BusError> {
let cmd = 0x80 | (reg & 0x7F);
let mut bytes = [0u8; 2 * 64 + 1];
let byte_len = words.len() * 2 + 1;
let mut ops = [
Operation::Write(&[cmd]),
Operation::Read(&mut bytes[..byte_len]),
];
self.transport.bus.transaction(&mut ops)?;
for (index, word) in words.iter_mut().enumerate() {
let offset = 1 + index * 2;
*word = u16::from_le_bytes([bytes[offset], bytes[offset + 1]]);
}
Ok(())
}
}
impl<I2C> AsyncAccess for Bmi323Async<AsyncI2cTransport<I2C>>
where
I2C: AsyncI2c,
{
type BusError = I2C::Error;
async fn read_word(&mut self, reg: u8) -> Result<u16, Self::BusError> {
let mut bytes = [0u8; 4];
self.transport
.bus
.write_read(self.transport.address, &[reg], &mut bytes)
.await?;
Ok(u16::from_le_bytes([bytes[2], bytes[3]]))
}
async fn write_word(&mut self, reg: u8, word: u16) -> Result<(), Self::BusError> {
let [lo, hi] = word.to_le_bytes();
self.transport
.bus
.write(self.transport.address, &[reg, lo, hi])
.await
}
async fn read_words(&mut self, reg: u8, words: &mut [u16]) -> Result<(), Self::BusError> {
let mut bytes = [0u8; 2 * 64 + 2];
let byte_len = words.len() * 2 + 2;
self.transport
.bus
.write_read(self.transport.address, &[reg], &mut bytes[..byte_len])
.await?;
for (index, word) in words.iter_mut().enumerate() {
let offset = 2 + index * 2;
*word = u16::from_le_bytes([bytes[offset], bytes[offset + 1]]);
}
Ok(())
}
}
impl<SPI> AsyncAccess for Bmi323Async<AsyncSpiTransport<SPI>>
where
SPI: AsyncSpiDevice<u8>,
{
type BusError = SPI::Error;
async fn read_word(&mut self, reg: u8) -> Result<u16, Self::BusError> {
let cmd = 0x80 | (reg & 0x7F);
let mut bytes = [0u8; 3];
let mut ops = [Operation::Write(&[cmd]), Operation::Read(&mut bytes)];
self.transport.bus.transaction(&mut ops).await?;
Ok(u16::from_le_bytes([bytes[1], bytes[2]]))
}
async fn write_word(&mut self, reg: u8, word: u16) -> Result<(), Self::BusError> {
let [lo, hi] = word.to_le_bytes();
let payload = [reg & 0x7F, lo, hi];
self.transport.bus.write(&payload).await
}
async fn read_words(&mut self, reg: u8, words: &mut [u16]) -> Result<(), Self::BusError> {
let cmd = 0x80 | (reg & 0x7F);
let mut bytes = [0u8; 2 * 64 + 1];
let byte_len = words.len() * 2 + 1;
let mut ops = [
Operation::Write(&[cmd]),
Operation::Read(&mut bytes[..byte_len]),
];
self.transport.bus.transaction(&mut ops).await?;
for (index, word) in words.iter_mut().enumerate() {
let offset = 1 + index * 2;
*word = u16::from_le_bytes([bytes[offset], bytes[offset + 1]]);
}
Ok(())
}
}