use core::fmt::Debug;
use log::{trace, error};
use embedded_hal::blocking::delay::{DelayMs, DelayUs};
use embedded_hal::blocking::spi::Transactional;
use driver_pal::{Reset, Busy, Ready, PinState, PrefixRead, PrefixWrite};
use driver_pal::{Error as SpiError};
use crate::{Error};
use crate::device::*;
pub trait Hal<
CommsError: Debug + Sync + Send,
PinError: Debug + Sync + Send,
DelayError: Debug + Sync + Send,
> {
fn reset(&mut self) -> Result<(), Error<CommsError, PinError, DelayError>>;
fn get_busy(&mut self) -> Result<PinState, Error<CommsError, PinError, DelayError>>;
fn get_dio(&mut self) -> Result<PinState, Error<CommsError, PinError, DelayError>>;
fn try_delay_ms(&mut self, ms: u32)-> Result<(), DelayError>;
fn try_delay_us(&mut self, us: u32)-> Result<(), DelayError>;
fn write_cmd(&mut self, command: u8, data: &[u8]) -> Result<(), Error<CommsError, PinError, DelayError>>;
fn read_cmd(&mut self, command: u8, data: &mut [u8]) -> Result<(), Error<CommsError, PinError, DelayError>>;
fn write_regs(&mut self, reg: u16, data: &[u8]) -> Result<(), Error<CommsError, PinError, DelayError>>;
fn read_regs(&mut self, reg: u16, data: &mut [u8]) -> Result<(), Error<CommsError, PinError, DelayError>>;
fn write_buff(&mut self, offset: u8, data: &[u8]) -> Result<(), Error<CommsError, PinError, DelayError>>;
fn read_buff(&mut self, offset: u8, data: &mut [u8]) -> Result<(), Error<CommsError, PinError, DelayError>>;
fn wait_busy(&mut self) -> Result<(), Error<CommsError, PinError, DelayError>> {
let mut timeout = 0;
while self.get_busy()? == PinState::High {
self.try_delay_ms(1).map_err(Error::Delay)?;
timeout += 1;
if timeout > BUSY_TIMEOUT_MS {
error!("Busy timeout after {} ms", BUSY_TIMEOUT_MS);
return Err(Error::BusyTimeout)
}
}
Ok(())
}
fn read_reg(&mut self, reg: u16) -> Result<u8, Error<CommsError, PinError, DelayError>> {
let mut incoming = [0u8; 1];
self.read_regs(reg.into(), &mut incoming)?;
Ok(incoming[0])
}
fn write_reg(&mut self, reg: u16, value: u8) -> Result<(), Error<CommsError, PinError, DelayError>> {
self.write_regs(reg.into(), &[value])?;
Ok(())
}
fn update_reg(&mut self, reg: u16, mask: u8, value: u8) -> Result<u8, Error<CommsError, PinError, DelayError>> {
let existing = self.read_reg(reg)?;
let updated = (existing & !mask) | (value & mask);
self.write_reg(reg, updated)?;
Ok(updated)
}
}
impl<T, CommsError, PinError, DelayError> Hal<CommsError, PinError, DelayError> for T
where
T: Transactional<u8, Error=SpiError<CommsError, PinError, DelayError>> + PrefixRead<Error=SpiError<CommsError, PinError, DelayError>> + PrefixWrite<Error=SpiError<CommsError, PinError, DelayError>>,
T: Reset<Error=SpiError<CommsError, PinError, DelayError>>,
T: Busy<Error=SpiError<CommsError, PinError, DelayError>>,
T: Ready<Error=SpiError<CommsError, PinError, DelayError>>,
T: DelayMs<u32, Error=DelayError> + DelayUs<u32, Error=DelayError>,
CommsError: Debug + Sync + Send,
PinError: Debug + Sync + Send,
DelayError: Debug + Sync + Send,
{
fn reset(&mut self) -> Result<(), Error<CommsError, PinError, DelayError>> {
self.try_delay_ms(20).map_err(Error::Delay)?;
self.set_reset(PinState::Low).map_err(|e| Error::from(e) )?;
self.try_delay_ms(50).map_err(Error::Delay)?;
self.set_reset(PinState::High).map_err(|e| Error::from(e) )?;
self.try_delay_ms(20).map_err(Error::Delay)?;
Ok(())
}
fn get_busy(&mut self) -> Result<PinState, Error<CommsError, PinError, DelayError>> {
let busy = self.get_busy()?;
Ok(busy)
}
fn get_dio(&mut self) -> Result<PinState, Error<CommsError, PinError, DelayError>> {
let dio = self.get_ready()?;
Ok(dio)
}
fn try_delay_ms(&mut self, ms: u32) -> Result<(), DelayError> {
DelayMs::try_delay_ms(self, ms)
}
fn try_delay_us(&mut self, ms: u32) -> Result<(), DelayError> {
DelayUs::try_delay_us(self, ms)
}
fn write_cmd(&mut self, command: u8, data: &[u8]) -> Result<(), Error<CommsError, PinError, DelayError>> {
let out_buf: [u8; 1] = [command as u8];
trace!("write_cmd cmd: {:02x?} data: {:02x?}", out_buf, data);
self.wait_busy()?;
let r = self.try_prefix_write(&out_buf, data).map_err(|e| e.into() );
self.wait_busy()?;
r
}
fn read_cmd<'a>(&mut self, command: u8, data: &mut [u8]) -> Result<(), Error<CommsError, PinError, DelayError>> {
let out_buf: [u8; 2] = [command as u8, 0x00];
self.wait_busy()?;
let r = self.try_prefix_read(&out_buf, data).map(|_| () ).map_err(|e| e.into() );
self.wait_busy()?;
trace!("read_cmd cmd: {:02x?} data: {:02x?}", out_buf, data);
r
}
fn write_regs(&mut self, reg: u16, data: &[u8]) -> Result<(), Error<CommsError, PinError, DelayError>> {
let out_buf: [u8; 3] = [
Commands::WiteRegister as u8,
((reg & 0xFF00) >> 8) as u8,
(reg & 0x00FF) as u8,
];
trace!("write_regs cmd: {:02x?} data: {:02x?}", out_buf, data);
self.wait_busy()?;
let r = self.try_prefix_write(&out_buf, data).map_err(|e| e.into() );
self.wait_busy()?;
r
}
fn read_regs<'a>(&mut self, reg: u16, data: &mut [u8]) -> Result<(), Error<CommsError, PinError, DelayError>> {
let out_buf: [u8; 4] = [
Commands::ReadRegister as u8,
((reg & 0xFF00) >> 8) as u8,
(reg & 0x00FF) as u8,
0,
];
self.wait_busy()?;
let r = self.try_prefix_read(&out_buf, data).map(|_| () ).map_err(|e| e.into() );
self.wait_busy()?;
trace!("read_regs cmd: {:02x?} data: {:02x?}", out_buf, data);
r
}
fn write_buff(&mut self, offset: u8, data: &[u8]) -> Result<(), Error<CommsError, PinError, DelayError>> {
let out_buf: [u8; 2] = [
Commands::WriteBuffer as u8,
offset,
];
trace!("write_buff cmd: {:02x?}", out_buf);
self.wait_busy()?;
let r = self.try_prefix_write(&out_buf, data).map_err(|e| e.into() );
self.wait_busy()?;
r
}
fn read_buff<'a>(&mut self, offset: u8, data: &mut [u8]) -> Result<(), Error<CommsError, PinError, DelayError>> {
let out_buf: [u8; 3] = [
Commands::ReadBuffer as u8,
offset,
0
];
trace!(" data: {:02x?}", out_buf);
self.wait_busy()?;
let r = self.try_prefix_read(&out_buf, data).map(|_| () ).map_err(|e| e.into() );
self.wait_busy()?;
trace!("read_buff cmd: {:02x?} data: {:02x?}", out_buf, data);
r
}
}