#![no_std]
use core::fmt::{self, Debug, Display};
use embedded_hal::digital::OutputPin;
use embedded_io_async::{ErrorType, Read, ReadReady, Write, WriteReady};
pub struct Max485<RIDO, REDE>
where
RIDO: Read + Write,
REDE: OutputPin,
{
serial: RIDO,
pin: REDE,
begun_transmission: bool,
}
impl<RIDO, REDE> Max485<RIDO, REDE>
where
RIDO: Read + Write,
REDE: OutputPin,
{
pub fn new(serial: RIDO, pin: REDE) -> Self {
Self {
serial,
pin,
begun_transmission: false,
}
}
pub fn into_parts(self) -> (RIDO, REDE) {
(self.serial, self.pin)
}
pub fn inner_mut(&mut self) -> &mut RIDO {
&mut self.serial
}
pub fn begin_transmission(&mut self) -> Result<(), <Self as ErrorType>::Error> {
if !self.begun_transmission {
self.pin.set_high().map_err(Error::Pin)?;
self.begun_transmission = true;
}
Ok(())
}
fn end_transmission_inner(&mut self) -> Result<(), <Self as ErrorType>::Error> {
if self.begun_transmission {
self.pin.set_low().map_err(Error::Pin)?;
self.begun_transmission = false;
}
Ok(())
}
pub async fn end_transmission(&mut self) -> Result<(), <Self as ErrorType>::Error> {
self.serial.flush().await.map_err(Error::Serial)?;
self.end_transmission_inner()
}
}
impl<RIDO, REDE> ErrorType for Max485<RIDO, REDE>
where
RIDO: Read + Write,
REDE: OutputPin,
{
type Error = crate::Error<RIDO::Error, REDE::Error>;
}
impl<RIDO, REDE> Write for Max485<RIDO, REDE>
where
RIDO: Read + Write,
REDE: OutputPin,
{
async fn write(&mut self, bytes: &[u8]) -> Result<usize, Self::Error> {
self.begin_transmission()?;
self.serial.write(bytes).await.map_err(Error::Serial)
}
async fn flush(&mut self) -> Result<(), Self::Error> {
self.begin_transmission()?;
self.serial.flush().await.map_err(Error::Serial)?;
self.end_transmission_inner()
}
}
impl<RIDO, REDE> Read for Max485<RIDO, REDE>
where
RIDO: Read + Write,
REDE: OutputPin,
{
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
self.end_transmission_inner()?;
self.serial.read(buf).await.map_err(Error::Serial)
}
}
impl<RIDO, REDE> ReadReady for Max485<RIDO, REDE>
where
RIDO: Read + Write + ReadReady,
REDE: OutputPin,
{
fn read_ready(&mut self) -> Result<bool, Self::Error> {
Ok(self.serial.read_ready().map_err(Error::Serial)? && !self.begun_transmission)
}
}
impl<RIDO, REDE> WriteReady for Max485<RIDO, REDE>
where
RIDO: Read + Write + WriteReady,
REDE: OutputPin,
{
fn write_ready(&mut self) -> Result<bool, Self::Error> {
self.serial.write_ready().map_err(Error::Serial)
}
}
#[derive(Debug)]
pub enum Error<S, P> {
Serial(S),
Pin(P),
}
impl<S, P> Display for Error<S, P>
where
S: Display,
P: Debug, {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Serial(s) => write!(f, "serial error: {s}"),
Error::Pin(p) => write!(f, "pin error: {p:?}"),
}
}
}
impl<S, P> core::error::Error for Error<S, P>
where
S: core::error::Error,
P: Debug,
{
}
impl<S, P> embedded_io_async::Error for Error<S, P>
where
S: embedded_io_async::Error,
P: Debug,
{
fn kind(&self) -> embedded_io_async::ErrorKind {
match self {
Error::Serial(s) => s.kind(),
Error::Pin(_) => embedded_io_async::ErrorKind::Other,
}
}
}