use embassy_time::{Duration, Timer};
use embedded_hal::digital::OutputPin;
use embedded_hal_async::spi::SpiDevice;
use crate::error::{Error, Result};
use crate::types::MAX_SPI_XFER;
pub struct SpiTransport<SPI, CS>
where
SPI: SpiDevice,
CS: OutputPin,
{
spi: SPI,
cs: CS,
}
impl<SPI, CS> SpiTransport<SPI, CS>
where
SPI: SpiDevice,
CS: OutputPin,
{
pub fn new(spi: SPI, cs: CS) -> Self {
Self { spi, cs }
}
pub async fn write(&mut self, data: &[u8]) -> Result<()> {
if data.len() > MAX_SPI_XFER {
return Err(Error::BufferTooSmall);
}
self.cs.set_low().map_err(|_| Error::Spi)?;
Timer::after(Duration::from_micros(10)).await;
let result = self.spi.write(data).await.map_err(|_| Error::Spi);
Timer::after(Duration::from_micros(10)).await;
self.cs.set_high().map_err(|_| Error::Spi)?;
result
}
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<usize> {
if buffer.len() > MAX_SPI_XFER {
return Err(Error::BufferTooSmall);
}
self.cs.set_low().map_err(|_| Error::Spi)?;
Timer::after(Duration::from_micros(10)).await;
let result = self.spi.read(buffer).await.map_err(|_| Error::Spi);
Timer::after(Duration::from_micros(10)).await;
self.cs.set_high().map_err(|_| Error::Spi)?;
result?;
Ok(buffer.len())
}
pub async fn transfer(&mut self, tx_buffer: &[u8], rx_buffer: &mut [u8]) -> Result<()> {
if tx_buffer.len() > MAX_SPI_XFER || rx_buffer.len() > MAX_SPI_XFER {
return Err(Error::BufferTooSmall);
}
self.cs.set_low().map_err(|_| Error::Spi)?;
Timer::after(Duration::from_micros(10)).await;
let result = self
.spi
.transfer(rx_buffer, tx_buffer)
.await
.map_err(|_| Error::Spi);
Timer::after(Duration::from_micros(10)).await;
self.cs.set_high().map_err(|_| Error::Spi)?;
result
}
pub async fn data_available(&mut self) -> Result<bool> {
Ok(true)
}
pub async fn flush(&mut self) -> Result<()> {
Ok(())
}
}
pub struct SpiTransportAuto<SPI>
where
SPI: SpiDevice,
{
spi: SPI,
}
impl<SPI> SpiTransportAuto<SPI>
where
SPI: SpiDevice,
{
pub fn new(spi: SPI) -> Self {
Self { spi }
}
pub async fn write(&mut self, data: &[u8]) -> Result<()> {
if data.len() > MAX_SPI_XFER {
return Err(Error::BufferTooSmall);
}
self.spi.write(data).await.map_err(|_| Error::Spi)
}
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<usize> {
if buffer.len() > MAX_SPI_XFER {
return Err(Error::BufferTooSmall);
}
self.spi.read(buffer).await.map_err(|_| Error::Spi)?;
Ok(buffer.len())
}
pub async fn transfer(&mut self, tx_buffer: &[u8], rx_buffer: &mut [u8]) -> Result<()> {
if tx_buffer.len() > MAX_SPI_XFER || rx_buffer.len() > MAX_SPI_XFER {
return Err(Error::BufferTooSmall);
}
self.spi
.transfer(rx_buffer, tx_buffer)
.await
.map_err(|_| Error::Spi)
}
pub async fn data_available(&mut self) -> Result<bool> {
Ok(true)
}
pub async fn flush(&mut self) -> Result<()> {
Ok(())
}
}