use crate::{MainDevice, error::Error, pdu_loop::ReceivedPdu};
use ethercrab_wire::{EtherCrabWireRead, EtherCrabWireWrite};
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub enum Writes {
Bwr {
address: u16,
register: u16,
},
Apwr {
address: u16,
register: u16,
},
Fpwr {
address: u16,
register: u16,
},
Lwr {
address: u32,
},
Lrw {
address: u32,
},
}
#[derive(Debug, Copy, Clone)]
pub struct WrappedWrite {
pub command: Writes,
wkc: Option<u16>,
len_override: Option<u16>,
}
impl WrappedWrite {
pub(crate) fn new(command: Writes) -> Self {
Self {
command,
wkc: Some(1),
len_override: None,
}
}
pub fn with_len(self, new_len: impl Into<u16>) -> Self {
Self {
len_override: Some(new_len.into()),
..self
}
}
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 send<'maindevice>(
self,
maindevice: &'maindevice MainDevice<'maindevice>,
data: impl EtherCrabWireWrite,
) -> Result<(), Error> {
self.common(maindevice, data, self.len_override).await?;
Ok(())
}
pub async fn send_receive<'maindevice, T>(
self,
maindevice: &'maindevice MainDevice<'maindevice>,
value: impl EtherCrabWireWrite,
) -> Result<T, Error>
where
T: EtherCrabWireRead,
{
self.common(maindevice, value, None)
.await?
.maybe_wkc(self.wkc)
.and_then(|data| Ok(T::unpack_from_slice(&data)?))
}
pub async fn send_receive_slice<'maindevice>(
self,
maindevice: &'maindevice MainDevice<'maindevice>,
value: impl EtherCrabWireWrite,
) -> Result<ReceivedPdu<'maindevice>, Error> {
self.common(maindevice, value, None)
.await?
.maybe_wkc(self.wkc)
}
fn common<'maindevice>(
&self,
maindevice: &'maindevice MainDevice<'maindevice>,
value: impl EtherCrabWireWrite,
len_override: Option<u16>,
) -> impl core::future::Future<Output = Result<ReceivedPdu<'maindevice>, Error>> {
maindevice.single_pdu(self.command.into(), value, len_override)
}
}