use crate::{MainDevice, error::Error, pdu_loop::ReceivedPdu};
use ethercrab_wire::{EtherCrabWireRead, EtherCrabWireSized};
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub enum Reads {
Aprd {
address: u16,
register: u16,
},
Fprd {
address: u16,
register: u16,
},
Brd {
address: u16,
register: u16,
},
Lrd {
address: u32,
},
Frmw {
address: u16,
register: u16,
},
}
impl Reads {
pub fn wrap(self) -> WrappedRead {
WrappedRead::new(self)
}
}
#[derive(Debug, Copy, Clone)]
pub struct WrappedRead {
pub command: Reads,
wkc: Option<u16>,
}
impl WrappedRead {
pub(crate) fn new(command: Reads) -> Self {
Self {
command,
wkc: Some(1),
}
}
pub fn ignore_wkc(self) -> Self {
Self { wkc: None, ..self }
}
pub fn with_wkc(self, wkc: u16) -> Self {
Self {
wkc: Some(wkc),
..self
}
}
pub async fn receive<'maindevice, T>(
self,
maindevice: &'maindevice MainDevice<'maindevice>,
) -> Result<T, Error>
where
T: EtherCrabWireRead + EtherCrabWireSized,
{
self.common(maindevice, T::PACKED_LEN as u16)
.await?
.maybe_wkc(self.wkc)
.and_then(|data| Ok(T::unpack_from_slice(&data)?))
}
pub async fn receive_slice<'maindevice>(
self,
maindevice: &'maindevice MainDevice<'maindevice>,
len: u16,
) -> Result<ReceivedPdu<'maindevice>, Error> {
self.common(maindevice, len).await?.maybe_wkc(self.wkc)
}
pub(crate) async fn receive_wkc<'maindevice, T>(
&self,
maindevice: &'maindevice MainDevice<'maindevice>,
) -> Result<u16, Error>
where
T: EtherCrabWireRead + EtherCrabWireSized,
{
self.common(maindevice, T::PACKED_LEN as u16)
.await
.map(|res| res.working_counter)
}
fn common<'maindevice>(
&self,
maindevice: &'maindevice MainDevice<'maindevice>,
len: u16,
) -> impl core::future::Future<Output = Result<ReceivedPdu<'maindevice>, Error>> {
maindevice.single_pdu(self.command.into(), (), Some(len))
}
}