use ethercrab_wire::EtherCrabWireReadSized;
#[derive(Clone, Copy, Debug, PartialEq, Eq, ethercrab_wire::EtherCrabWireReadWrite)]
#[cfg_attr(test, derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u8)]
pub enum CoeService {
Emergency = 0x01,
SdoRequest = 0x02,
SdoResponse = 0x03,
TxPdo = 0x04,
RxPdo = 0x05,
TxPdoRemoteRequest = 0x06,
RxPdoRemoteRequest = 0x07,
SdoInformation = 0x08,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, ethercrab_wire::EtherCrabWireReadWrite)]
#[wire(bytes = 2)]
pub struct CoeHeader {
#[wire(pre_skip = 12, bits = 4)]
pub service: CoeService,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, ethercrab_wire::EtherCrabWireReadWrite)]
#[wire(bits = 3)]
#[repr(u8)]
pub enum CoeCommand {
Download = 0x01,
Upload = 0x02,
Abort = 0x04,
UploadSegment = 0x03,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, ethercrab_wire::EtherCrabWireReadWrite)]
#[wire(bytes = 4)]
pub struct SdoHeader {
#[wire(bits = 1)]
pub size_indicator: bool,
#[wire(bits = 1)]
pub expedited_transfer: bool,
#[wire(bits = 2)]
pub size: u8,
#[wire(bits = 1)]
pub complete_access: bool,
#[wire(bits = 3)]
pub command: CoeCommand,
#[wire(bytes = 2)]
pub index: u16,
#[wire(bytes = 1)]
pub sub_index: u8,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, ethercrab_wire::EtherCrabWireReadWrite)]
#[wire(bytes = 1)]
pub struct SdoHeaderSegmented {
#[wire(bits = 1)]
pub is_last_segment: bool,
#[wire(bits = 3)]
pub segment_data_size: u8,
#[wire(bits = 1)]
pub toggle: bool,
#[wire(bits = 3)]
pub(in crate::mailbox::coe) command: CoeCommand,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, ethercrab_wire::EtherCrabWireReadWrite)]
#[wire(bytes = 4)]
pub struct SdoInfoHeader {
#[wire(bits = 7)]
pub op_code: SdoInfoOpCode,
#[wire(bits = 1)]
pub incomplete: bool,
#[wire(pre_skip = 8, bytes = 2)]
pub fragments_left: u16,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, ethercrab_wire::EtherCrabWireReadWrite)]
#[repr(u8)]
pub enum SdoInfoOpCode {
GetObjectDescriptionListRequest = 0x01,
GetObjectDescriptionListResponse = 0x02,
GetObjectDescriptionRequest = 0x03,
GetObjectDescriptionResponse = 0x04,
GetEntryDescriptionRequest = 0x05,
GetEntryDescriptionResponse = 0x06,
SdoInfoErrorRequest = 0x07,
}
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum SubIndex {
Complete,
Index(u8),
}
impl SubIndex {
pub(crate) fn complete_access(&self) -> bool {
matches!(self, Self::Complete)
}
pub(crate) fn sub_index(&self) -> u8 {
match self {
SubIndex::Complete => 1,
SubIndex::Index(idx) => *idx,
}
}
}
impl From<u8> for SubIndex {
fn from(value: u8) -> Self {
Self::Index(value)
}
}
pub(crate) trait SdoExpeditedPayload: EtherCrabWireReadSized {}
impl SdoExpeditedPayload for u8 {}
impl SdoExpeditedPayload for u16 {}
impl SdoExpeditedPayload for u32 {}
#[cfg(test)]
mod tests {
pub use super::*;
use ethercrab_wire::{EtherCrabWireRead, EtherCrabWireWriteSized};
#[test]
fn sanity_coe_service() {
assert_eq!(CoeService::SdoRequest.pack(), [0x02]);
assert_eq!(
CoeService::unpack_from_slice(&[0x02]),
Ok(CoeService::SdoRequest)
);
}
}