#[derive(Debug, Copy, Clone, PartialEq, Eq, ethercrab_wire::EtherCrabWireRead)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[repr(u32)]
pub enum CoeAbortCode {
ToggleBit = 0x0503_0000,
SdoTimeout = 0x0504_0000,
InvalidCommand = 0x0504_0001,
OutOfMemory = 0x0504_0005,
UnsupportedAccess = 0x0601_0000,
WriteOnlyRead = 0x0601_0001,
ReadOnlyWrite = 0x0601_0002,
IndexOnly = 0x0601_0003,
NoCompleteAccess = 0x0601_0004,
ObjectTooLarge = 0x0601_0005,
DownloadBlocked = 0x0601_0006,
NotFound = 0x0602_0000,
PdoMappingFailed = 0x0604_0041,
PdoTooSmall = 0x0604_0042,
Incompatible = 0x0604_0043,
Internal = 0x0604_0047,
HardwareFailure = 0x0606_0000,
DataLengthMismatch = 0x0607_0010,
DataTooLong = 0x0607_0012,
DataTooShort = 0x0607_0013,
SubIndexNotFound = 0x0609_0011,
ValueOutOfRange = 0x0609_0030,
ValueTooLarge = 0x0609_0031,
ValueTooSmall = 0x0609_0032,
MaxMin = 0x0609_0036,
General = 0x0800_0000,
TransferFailed = 0x0800_0020,
TransferFailedLocal = 0x0800_0021,
InvalidState = 0x0800_0022,
NoObjectDictionary = 0x0800_0023,
#[wire(catch_all)]
Unknown(u32),
}
impl core::fmt::Display for CoeAbortCode {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let num = u32::from(*self);
f.write_fmt(format_args!("{:#010x}", num))?;
f.write_str(": ")?;
match self {
Self::ToggleBit => f.write_str("Toggle bit not changed"),
Self::SdoTimeout => f.write_str("SDO protocol timeout"),
Self::InvalidCommand => f.write_str("Client/Server command specifier not valid or unknown"),
Self::OutOfMemory => f.write_str("Out of memory"),
Self::UnsupportedAccess => f.write_str("Unsupported access to an object"),
Self::WriteOnlyRead => f.write_str("Attempt to read to a write only object"),
Self::ReadOnlyWrite => f.write_str("Attempt to write to a read only object"),
Self::IndexOnly => f.write_str("Subindex cannot be written, SI0 must be 0 for write access"),
Self::NoCompleteAccess => f.write_str("SDO Complete access not supported for objects of variable length such as ENUM object types"),
Self::ObjectTooLarge => f.write_str("Object length exceeds mailbox size"),
Self::DownloadBlocked => f.write_str("Object mapped to RxPDO, SDO Download blocked"),
Self::NotFound => f.write_str("The object does not exist in the object directory"),
Self::PdoMappingFailed => f.write_str("The object can not be mapped into the PDO"),
Self::PdoTooSmall => f.write_str("The number and length of the objects to be mapped would exceed the PDO length"),
Self::Incompatible => f.write_str("General parameter incompatibility reason"),
Self::Internal => f.write_str("General internal incompatibility in the device"),
Self::HardwareFailure => f.write_str("Access failed due to a hardware error"),
Self::DataLengthMismatch => f.write_str("Data type does not match, length of service parameter does not match"),
Self::DataTooLong => f.write_str("Data type does not match, length of service parameter too high"),
Self::DataTooShort => f.write_str("Data type does not match, length of service parameter too low"),
Self::SubIndexNotFound => f.write_str("Subindex does not exist"),
Self::ValueOutOfRange => f.write_str("Value range of parameter exceeded (only for write access)"),
Self::ValueTooLarge => f.write_str("Value of parameter written too high"),
Self::ValueTooSmall => f.write_str("Value of parameter written too low"),
Self::MaxMin => f.write_str("Maximum value is less than minimum value"),
Self::General => f.write_str("General error"),
Self::TransferFailed => f.write_str("Data cannot be transferred or stored to the application"),
Self::TransferFailedLocal => f.write_str("Data cannot be transferred or stored to the application because of local control"),
Self::InvalidState => f.write_str(" Data cannot be transferred or stored to the application because of the present device state"),
Self::NoObjectDictionary => f.write_str("Object dictionary dynamic generation fails or no object dictionary is present"),
Self::Unknown(_) => f.write_str("Unknown code"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn unknown_code() {
let code = 0x1234_5678u32;
let decoded = CoeAbortCode::from(code);
assert_eq!(decoded, CoeAbortCode::Unknown(0x1234_5678u32));
assert_eq!(decoded.to_string(), "0x12345678: Unknown code");
}
#[test]
fn parse_code() {
let code = 0x06090036;
assert_eq!(CoeAbortCode::from(code), CoeAbortCode::MaxMin);
}
}