use super::{Interface, MAX_WRITE_LEN};
use crate::errors::{GyroError, XmError};
use embedded_hal_async::spi::{Operation, SpiDevice};
const SPI_READ: u8 = 0x80;
const MS_BIT: u8 = 0x40;
pub struct SpiInterface<GSpi, XmSpi>
where
GSpi: SpiDevice,
XmSpi: SpiDevice,
{
g_device: GSpi,
xm_device: XmSpi,
}
impl<GSpi, XmSpi> SpiInterface<GSpi, XmSpi>
where
GSpi: SpiDevice,
XmSpi: SpiDevice,
{
pub fn init(g_device: GSpi, xm_device: XmSpi) -> Self {
Self {
g_device,
xm_device,
}
}
pub fn release(self) -> (GSpi, XmSpi) {
(self.g_device, self.xm_device)
}
}
const WRITE_BUFFER_SIZE: usize = MAX_WRITE_LEN + 1;
impl<GSpi, XmSpi, E> Interface for SpiInterface<GSpi, XmSpi>
where
GSpi: SpiDevice<Error = E>,
XmSpi: SpiDevice<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];
let len = data.len().min(MAX_WRITE_LEN);
buffer[0] = if len > 1 { addr | MS_BIT } else { addr };
buffer[1..=len].copy_from_slice(&data[..len]);
Ok(self.g_device.write(&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];
let len = data.len().min(MAX_WRITE_LEN);
buffer[0] = if len > 1 { addr | MS_BIT } else { addr };
buffer[1..=len].copy_from_slice(&data[..len]);
Ok(self.xm_device.write(&buffer[..=len]).await?)
}
async fn read_gyro(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), GyroError<E>> {
let reg_addr = if buffer.len() > 1 {
SPI_READ | MS_BIT | addr
} else {
SPI_READ | addr
};
Ok(self
.g_device
.transaction(&mut [Operation::Write(&[reg_addr]), Operation::Read(buffer)])
.await?)
}
async fn read_xm(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), XmError<E>> {
let reg_addr = if buffer.len() > 1 {
SPI_READ | MS_BIT | addr
} else {
SPI_READ | addr
};
Ok(self
.xm_device
.transaction(&mut [Operation::Write(&[reg_addr]), Operation::Read(buffer)])
.await?)
}
}