Skip to main content

darra_ethercat/data/
types.rs

1
2use std::fmt;
3
4#[repr(i32)]
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum EcErr {
7
8    Ok = 0,
9
10    AlreadyInitialized = 1,
11
12    NotInitialized = 2,
13
14    Timeout = 3,
15
16    NoSlaves = 4,
17
18    Nok = 5,
19}
20
21#[repr(u8)]
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum EcState {
24
25    None = 0x00,
26
27    Init = 0x01,
28
29    PreOp = 0x02,
30
31    Boot = 0x03,
32
33    SafeOp = 0x04,
34
35    OP = 0x08,
36
37    Ack = 0x10,
38}
39
40impl EcState {
41
42    pub fn from_value(v: u8) -> Self {
43        match v & 0x0F {
44            0x00 => Self::None,
45            0x01 => Self::Init,
46            0x02 => Self::PreOp,
47            0x03 => Self::Boot,
48            0x04 => Self::SafeOp,
49            0x08 => Self::OP,
50            _ => Self::None,
51        }
52    }
53
54    pub fn has_error(raw: u8) -> bool {
55        (raw & 0x10) != 0
56    }
57
58    pub fn format(raw: u8) -> String {
59        let base = Self::from_value(raw);
60        let name = match base {
61            Self::None => "None",
62            Self::Init => "Init",
63            Self::PreOp => "PreOp",
64            Self::Boot => "Boot",
65            Self::SafeOp => "SafeOp",
66            Self::OP => "OP",
67            Self::Ack => "Ack",
68        };
69        if Self::has_error(raw) {
70            format!("{}+Error", name)
71        } else {
72            name.to_string()
73        }
74    }
75}
76
77#[repr(u8)]
78#[derive(Debug, Clone, Copy, PartialEq, Eq)]
79pub enum EcLinkState {
80
81    Disconnected = 0,
82
83    Connected = 1,
84
85    PrimaryOnly = 3,
86
87    SecondaryOnly = 4,
88}
89
90impl EcLinkState {
91
92    pub fn from_value(v: u8) -> Self {
93        match v {
94            0 => Self::Disconnected,
95            1 => Self::Connected,
96            3 => Self::PrimaryOnly,
97            4 => Self::SecondaryOnly,
98            _ => Self::Disconnected,
99        }
100    }
101}
102
103#[repr(i32)]
104#[derive(Debug, Clone, Copy, PartialEq, Eq)]
105pub enum RingMode {
106
107    Inactive = 0,
108
109    Dual = 1,
110
111    Degraded = 2,
112}
113
114impl RingMode {
115
116    pub fn from_value(v: i32) -> Self {
117        match v {
118            0 => Self::Inactive,
119            1 => Self::Dual,
120            2 => Self::Degraded,
121            _ => Self::Inactive,
122        }
123    }
124}
125
126#[repr(i32)]
127#[derive(Debug, Clone, Copy, PartialEq, Eq)]
128pub enum EcBufState {
129
130    Empty = 0x00,
131
132    Alloc = 0x01,
133
134    Tx = 0x02,
135
136    Rcvd = 0x03,
137
138    Complete = 0x04,
139}
140
141#[repr(u16)]
142#[derive(Debug, Clone, Copy, PartialEq, Eq)]
143pub enum EcDataType {
144
145    Boolean = 0x0001,
146
147    Integer8 = 0x0002,
148
149    Integer16 = 0x0003,
150
151    Integer32 = 0x0004,
152
153    Unsigned8 = 0x0005,
154
155    Unsigned16 = 0x0006,
156
157    Unsigned32 = 0x0007,
158
159    Real32 = 0x0008,
160
161    VisibleString = 0x0009,
162
163    OctetString = 0x000A,
164
165    UnicodeString = 0x000B,
166
167    TimeOfDay = 0x000C,
168
169    TimeDifference = 0x000D,
170
171    Domain = 0x000F,
172
173    Integer24 = 0x0010,
174
175    Real64 = 0x0011,
176
177    Integer40 = 0x0012,
178
179    Integer48 = 0x0013,
180
181    Integer56 = 0x0014,
182
183    Integer64 = 0x0015,
184
185    Unsigned24 = 0x0016,
186
187    Unsigned40 = 0x0018,
188
189    Unsigned48 = 0x0019,
190
191    Unsigned56 = 0x001A,
192
193    Unsigned64 = 0x001B,
194
195    Bit1 = 0x0030,
196
197    Bit2 = 0x0031,
198
199    Bit3 = 0x0032,
200
201    Bit4 = 0x0033,
202
203    Bit5 = 0x0034,
204
205    Bit6 = 0x0035,
206
207    Bit7 = 0x0036,
208
209    Bit8 = 0x0037,
210}
211
212#[repr(i32)]
213#[derive(Debug, Clone, Copy, PartialEq, Eq)]
214pub enum EcCmdType {
215
216    Nop = 0x00,
217
218    Aprd = 0x01,
219
220    Apwr = 0x02,
221
222    Aprw = 0x03,
223
224    Fprd = 0x04,
225
226    Fpwr = 0x05,
227
228    Fprw = 0x06,
229
230    Brd = 0x07,
231
232    Bwr = 0x08,
233
234    Brw = 0x09,
235
236    Lrd = 0x0A,
237
238    Lwr = 0x0B,
239
240    Lrw = 0x0C,
241
242    Armw = 0x0D,
243
244    Frmw = 0x0E,
245}
246
247#[repr(i32)]
248#[derive(Debug, Clone, Copy, PartialEq, Eq)]
249pub enum EcEcmdType {
250
251    Nop = 0x0000,
252
253    Read = 0x0100,
254
255    Write = 0x0201,
256
257    Reload = 0x0300,
258}
259
260#[repr(i32)]
261#[derive(Debug, Clone, Copy, PartialEq, Eq)]
262pub enum LogLevel {
263
264    Info = 0,
265
266    Debug = 1,
267
268    Warn = 2,
269
270    Error = 3,
271
272    Fatal = 4,
273}
274
275#[repr(i32)]
276#[derive(Debug, Clone, Copy, PartialEq, Eq)]
277pub enum EcALState {
278
279    NoError = 0x0000,
280
281    UnspecifiedError = 0x0001,
282
283    NoMemory = 0x0002,
284
285    InvalidDeviceSetup = 0x0003,
286
287    InvalidRevision = 0x0004,
288
289    SiiEepromMismatch = 0x0006,
290
291    FirmwareUpdateFailed = 0x0007,
292
293    LicenseError = 0x000E,
294
295    InvalidStateChange = 0x0011,
296
297    UnknownRequestedState = 0x0012,
298
299    BootstrapNotSupported = 0x0013,
300
301    NoValidFirmware = 0x0014,
302
303    InvalidMailboxConfig = 0x0015,
304
305    InvalidMailBoxConfig = 0x0016,
306
307    InvalidSyncManagerConfig = 0x0017,
308
309    NoValidInputs = 0x0018,
310
311    NoValidOutputs = 0x0019,
312
313    SyncError = 0x001A,
314
315    SyncManagerWatchdog = 0x001B,
316
317    InvalidSyncManagerTypes = 0x001C,
318
319    InvalidOutputConfig = 0x001D,
320
321    InvalidInputConfig = 0x001E,
322
323    InvalidWatchdogConfig = 0x001F,
324
325    NeedsColdStart = 0x0020,
326
327    NeedsInit = 0x0021,
328
329    NeedsPreOp = 0x0022,
330
331    NeedsSafeOp = 0x0023,
332
333    InvalidInputMapping = 0x0024,
334
335    InvalidOutputMapping = 0x0025,
336
337    InconsistentSettings = 0x0026,
338
339    FreerunNotSupported = 0x0027,
340
341    SyncNotSupported = 0x0028,
342
343    FreerunNeeds3Buffer = 0x0029,
344
345    BackgroundWatchdog = 0x002A,
346
347    NoValidIO = 0x002B,
348
349    FatalSyncError = 0x002C,
350
351    NoSyncError = 0x002D,
352
353    CycleTimeTooSmall = 0x002E,
354
355    InvalidDcSyncConfig = 0x0030,
356
357    InvalidDcLatch = 0x0031,
358
359    PllError = 0x0032,
360
361    DcSyncIOError = 0x0033,
362
363    DcSyncTimeout = 0x0034,
364
365    InvalidDcSyncCycle = 0x0035,
366
367    InvalidSync0Cycle = 0x0036,
368
369    InvalidSync1Cycle = 0x0037,
370
371    MailboxAoe = 0x0041,
372
373    MailboxEoe = 0x0042,
374
375    MailboxCoe = 0x0043,
376
377    MailboxFoe = 0x0044,
378
379    MailboxSoe = 0x0045,
380
381    MailboxVoe = 0x004F,
382
383    EepromNoAccess = 0x0050,
384
385    EepromError = 0x0051,
386
387    ExternalHardwareNotReady = 0x0052,
388
389    SlaveRestarted = 0x0060,
390
391    DeviceIdUpdated = 0x0061,
392
393    ModuleIdentListMismatch = 0x0070,
394
395    SupplyVoltageTooLow = 0x0080,
396
397    SupplyVoltageTooHigh = 0x0081,
398
399    TemperatureTooLow = 0x0082,
400
401    TemperatureTooHigh = 0x0083,
402
403    AppControllerAvailable = 0x00F0,
404
405    Unknown = 0xFFFF,
406}
407
408impl EcALState {
409
410    pub fn from_value(v: i32) -> Self {
411        match v {
412            0x0000 => Self::NoError,
413            0x0001 => Self::UnspecifiedError,
414            0x0002 => Self::NoMemory,
415            0x0003 => Self::InvalidDeviceSetup,
416            0x0004 => Self::InvalidRevision,
417            0x0006 => Self::SiiEepromMismatch,
418            0x0007 => Self::FirmwareUpdateFailed,
419            0x000E => Self::LicenseError,
420            0x0011 => Self::InvalidStateChange,
421            0x0012 => Self::UnknownRequestedState,
422            0x0013 => Self::BootstrapNotSupported,
423            0x0014 => Self::NoValidFirmware,
424            0x0015 => Self::InvalidMailboxConfig,
425            0x0016 => Self::InvalidMailBoxConfig,
426            0x0017 => Self::InvalidSyncManagerConfig,
427            0x0018 => Self::NoValidInputs,
428            0x0019 => Self::NoValidOutputs,
429            0x001A => Self::SyncError,
430            0x001B => Self::SyncManagerWatchdog,
431            0x001C => Self::InvalidSyncManagerTypes,
432            0x001D => Self::InvalidOutputConfig,
433            0x001E => Self::InvalidInputConfig,
434            0x001F => Self::InvalidWatchdogConfig,
435            0x0020 => Self::NeedsColdStart,
436            0x0021 => Self::NeedsInit,
437            0x0022 => Self::NeedsPreOp,
438            0x0023 => Self::NeedsSafeOp,
439            0x0024 => Self::InvalidInputMapping,
440            0x0025 => Self::InvalidOutputMapping,
441            0x0026 => Self::InconsistentSettings,
442            0x0027 => Self::FreerunNotSupported,
443            0x0028 => Self::SyncNotSupported,
444            0x0029 => Self::FreerunNeeds3Buffer,
445            0x002A => Self::BackgroundWatchdog,
446            0x002B => Self::NoValidIO,
447            0x002C => Self::FatalSyncError,
448            0x002D => Self::NoSyncError,
449            0x002E => Self::CycleTimeTooSmall,
450            0x0030 => Self::InvalidDcSyncConfig,
451            0x0031 => Self::InvalidDcLatch,
452            0x0032 => Self::PllError,
453            0x0033 => Self::DcSyncIOError,
454            0x0034 => Self::DcSyncTimeout,
455            0x0035 => Self::InvalidDcSyncCycle,
456            0x0036 => Self::InvalidSync0Cycle,
457            0x0037 => Self::InvalidSync1Cycle,
458            0x0041 => Self::MailboxAoe,
459            0x0042 => Self::MailboxEoe,
460            0x0043 => Self::MailboxCoe,
461            0x0044 => Self::MailboxFoe,
462            0x0045 => Self::MailboxSoe,
463            0x004F => Self::MailboxVoe,
464            0x0050 => Self::EepromNoAccess,
465            0x0051 => Self::EepromError,
466            0x0052 => Self::ExternalHardwareNotReady,
467            0x0060 => Self::SlaveRestarted,
468            0x0061 => Self::DeviceIdUpdated,
469            0x0070 => Self::ModuleIdentListMismatch,
470            0x0080 => Self::SupplyVoltageTooLow,
471            0x0081 => Self::SupplyVoltageTooHigh,
472            0x0082 => Self::TemperatureTooLow,
473            0x0083 => Self::TemperatureTooHigh,
474            0x00F0 => Self::AppControllerAvailable,
475            _ => Self::Unknown,
476        }
477    }
478}
479
480#[derive(Debug, Clone, Copy, PartialEq, Eq)]
481pub enum ALErrorCategory {
482
483    None,
484
485    Transient,
486
487    Configuration,
488
489    Hardware,
490
491    Unknown,
492}
493
494pub fn classify_al_error(code: u16) -> ALErrorCategory {
495    match code {
496        0x0000 => ALErrorCategory::None,
497
498        0x0011 |
499        0x001B |
500        0x001D |
501        0x0032 |
502        0x0033 |
503        0x0034
504            => ALErrorCategory::Transient,
505
506        0x0015 |
507        0x0016 |
508        0x0017 |
509        0x0018 |
510        0x0019 |
511        0x001A |
512        0x001C |
513        0x001E |
514        0x001F |
515        0x0030 |
516        0x0031
517            => ALErrorCategory::Configuration,
518
519        0x0042 |
520        0x0043 |
521        0x0050 |
522        0x0051 |
523        0x0060
524            => ALErrorCategory::Hardware,
525        _ => {
526            if code >= 0x0040 && code <= 0x005F {
527                ALErrorCategory::Hardware
528            } else {
529                ALErrorCategory::Unknown
530            }
531        }
532    }
533}
534
535#[derive(Debug, Clone)]
536pub struct DiagnosticMessage {
537
538    pub sub_index: u8,
539
540    pub diag_code: u32,
541
542    pub flags: u16,
543
544    pub text_index: u16,
545
546    pub raw_data: Vec<u8>,
547}
548
549impl fmt::Display for DiagnosticMessage {
550    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
551        write!(f, "Diag[{}]: Code=0x{:08X}, Flags=0x{:04X}",
552            self.sub_index, self.diag_code, self.flags)
553    }
554}
555
556#[derive(Debug, Clone, Default)]
557pub struct SlaveErrorCounters {
558
559    pub slave_index: i32,
560
561    pub port0_crc_errors: u32,
562
563    pub port1_crc_errors: u32,
564
565    pub port2_crc_errors: u32,
566
567    pub port3_crc_errors: u32,
568
569    pub frame_errors: u32,
570
571    pub lost_frames: u32,
572}
573
574#[repr(u16)]
575#[derive(Debug, Clone, Copy, PartialEq, Eq)]
576pub enum MailboxError {
577
578    NoError = 0x0000,
579
580    SyntaxError = 0x0001,
581
582    ProtocolNotSupported = 0x0002,
583
584    WrongChannelField = 0x0003,
585
586    ServiceNotSupported = 0x0004,
587
588    InvalidMailboxHeader = 0x0005,
589
590    DataTooShort = 0x0006,
591
592    NoMemoryInSlave = 0x0007,
593
594    InconsistentDataLength = 0x0008,
595
596    UnknownError = 0xFFFF,
597}
598
599#[repr(u16)]
600#[derive(Debug, Clone, Copy, PartialEq, Eq)]
601pub enum MailboxType {
602
603    ErrorMailbox = 0x00,
604
605    ADSOverEtherCAT = 0x01,
606
607    EthernetOverEtherCAT = 0x02,
608
609    CANopenOverEtherCAT = 0x03,
610
611    FileOverEtherCAT = 0x04,
612
613    ServoOverEtherCAT = 0x05,
614
615    VendorOverEtherCAT = 0x0F,
616}
617
618#[derive(Debug, Clone, Copy, PartialEq, Eq)]
619pub struct CoEObjectAccess(pub u16);
620
621impl CoEObjectAccess {
622
623    pub const NONE: Self = Self(0x00);
624
625    pub const READ_PRE_OP: Self = Self(0x01);
626
627    pub const READ_SAFE_OP: Self = Self(0x02);
628
629    pub const READ_OP: Self = Self(0x04);
630
631    pub const WRITE_PRE_OP: Self = Self(0x08);
632
633    pub const WRITE_SAFE_OP: Self = Self(0x10);
634
635    pub const WRITE_OP: Self = Self(0x20);
636
637    pub const READ_ANY: Self = Self(0x07);
638
639    pub const WRITE_ANY: Self = Self(0x38);
640
641    pub const READ_WRITE_ALL: Self = Self(0x3F);
642
643    pub fn contains(self, other: Self) -> bool {
644        (self.0 & other.0) == other.0
645    }
646
647    pub fn union(self, other: Self) -> Self {
648        Self(self.0 | other.0)
649    }
650}
651
652#[repr(u32)]
653#[derive(Debug, Clone, Copy, PartialEq, Eq)]
654pub enum SDOError {
655
656    NoError = 0x00000000,
657
658    ToggleBitNotChanged = 0x05030000,
659
660    SDOProtocolTimeout = 0x05040000,
661
662    InvalidCommandSpecifier = 0x05040001,
663
664    OutOfMemory = 0x05040005,
665
666    UnsupportedAccess = 0x06010000,
667
668    ReadWriteOnlyError = 0x06010001,
669
670    WriteReadOnlyError = 0x06010002,
671
672    SubindexWriteError = 0x06010003,
673
674    CompleteAccessNotSupported = 0x06010004,
675
676    ObjectLengthExceeded = 0x06010005,
677
678    ObjectMappedToRxPDO = 0x06010006,
679
680    ObjectDoesNotExist = 0x06020000,
681
682    CannotBeMappedToPDO = 0x06040041,
683
684    ExceedsPDOLength = 0x06040042,
685
686    ParameterIncompatibility = 0x06040043,
687
688    InternalIncompatibility = 0x06040047,
689
690    HardwareAccessError = 0x06060000,
691
692    DataTypeMismatch = 0x06070010,
693
694    DataTypeTooHigh = 0x06070012,
695
696    DataTypeTooLow = 0x06070013,
697
698    SubindexDoesNotExist = 0x06090011,
699
700    ValueRangeExceeded = 0x06090030,
701
702    ValueTooHigh = 0x06090031,
703
704    ValueTooLow = 0x06090032,
705
706    ModuleIdentListMismatch = 0x06090033,
707
708    MaxLessThanMin = 0x06090036,
709
710    GeneralError = 0x08000000,
711
712    DataTransferError = 0x08000020,
713
714    LocalControlError = 0x08000021,
715
716    DeviceStateError = 0x08000022,
717
718    DictionaryError = 0x08000023,
719
720    UnknownError = 0xFFFFFFFF,
721}
722
723impl SDOError {
724
725    pub fn from_u32(val: u32) -> Self {
726        match val {
727            0x00000000 => Self::NoError,
728            0x05030000 => Self::ToggleBitNotChanged,
729            0x05040000 => Self::SDOProtocolTimeout,
730            0x05040001 => Self::InvalidCommandSpecifier,
731            0x05040005 => Self::OutOfMemory,
732            0x06010000 => Self::UnsupportedAccess,
733            0x06010001 => Self::ReadWriteOnlyError,
734            0x06010002 => Self::WriteReadOnlyError,
735            0x06010003 => Self::SubindexWriteError,
736            0x06010004 => Self::CompleteAccessNotSupported,
737            0x06010005 => Self::ObjectLengthExceeded,
738            0x06010006 => Self::ObjectMappedToRxPDO,
739            0x06020000 => Self::ObjectDoesNotExist,
740            0x06040041 => Self::CannotBeMappedToPDO,
741            0x06040042 => Self::ExceedsPDOLength,
742            0x06040043 => Self::ParameterIncompatibility,
743            0x06040047 => Self::InternalIncompatibility,
744            0x06060000 => Self::HardwareAccessError,
745            0x06070010 => Self::DataTypeMismatch,
746            0x06070012 => Self::DataTypeTooHigh,
747            0x06070013 => Self::DataTypeTooLow,
748            0x06090011 => Self::SubindexDoesNotExist,
749            0x06090030 => Self::ValueRangeExceeded,
750            0x06090031 => Self::ValueTooHigh,
751            0x06090032 => Self::ValueTooLow,
752            0x06090033 => Self::ModuleIdentListMismatch,
753            0x06090036 => Self::MaxLessThanMin,
754            0x08000000 => Self::GeneralError,
755            0x08000020 => Self::DataTransferError,
756            0x08000021 => Self::LocalControlError,
757            0x08000022 => Self::DeviceStateError,
758            0x08000023 => Self::DictionaryError,
759            _ => Self::UnknownError,
760        }
761    }
762}
763
764#[repr(u16)]
765#[derive(Debug, Clone, Copy, PartialEq, Eq)]
766pub enum SoEError {
767
768    NoError = 0x0000,
769
770    NoIDN = 0x1001,
771
772    InvalidAccessToElement1 = 0x1009,
773
774    NoName = 0x2001,
775
776    NameTransmissionTooShort = 0x2002,
777
778    NameTransmissionTooLong = 0x2003,
779
780    NameCannotBeChanged = 0x2004,
781
782    NameWriteProtected = 0x2005,
783
784    AttributeTransmissionTooShort = 0x3002,
785
786    AttributeTransmissionTooLong = 0x3003,
787
788    AttributeCannotBeChanged = 0x3004,
789
790    AttributeWriteProtected = 0x3005,
791
792    NoUnits = 0x4001,
793
794    UnitTransmissionTooShort = 0x4002,
795
796    UnitTransmissionTooLong = 0x4003,
797
798    UnitCannotBeChanged = 0x4004,
799
800    UnitWriteProtected = 0x4005,
801
802    NoMinimumInputValue = 0x5001,
803
804    MinimumInputValueTransmissionTooShort = 0x5002,
805
806    MinimumInputValueTransmissionTooLong = 0x5003,
807
808    MinimumInputValueCannotBeChanged = 0x5004,
809
810    MinimumInputValueWriteProtected = 0x5005,
811
812    NoMaximumInputValue = 0x6001,
813
814    MaximumInputValueTransmissionTooShort = 0x6002,
815
816    MaximumInputValueTransmissionTooLong = 0x6003,
817
818    MaximumInputValueCannotBeChanged = 0x6004,
819
820    MaximumInputValueWriteProtected = 0x6005,
821
822    NoOperationData = 0x7001,
823
824    OperationDataTransmissionTooShort = 0x7002,
825
826    OperationDataTransmissionTooLong = 0x7003,
827
828    OperationDataCannotBeChanged = 0x7004,
829
830    OperationDataWriteProtectedByState = 0x7005,
831
832    OperationDataSmallerThanMinimum = 0x7006,
833
834    OperationDataGreaterThanMaximum = 0x7007,
835
836    InvalidOperationDataConfiguredIDNNotSupported = 0x7008,
837
838    OperationDataWriteProtectedByPassword = 0x7009,
839
840    OperationDataCyclicallyWriteProtected = 0x700A,
841
842    InvalidIndirectAddressing = 0x700B,
843
844    OperationDataWriteProtectedBySettings = 0x700C,
845
846    Reserved700D = 0x700D,
847
848    ProcedureCommandAlreadyActive = 0x7010,
849
850    ProcedureCommandNotInterruptible = 0x7011,
851
852    ProcedureCommandNotExecutableState = 0x7012,
853
854    ProcedureCommandNotExecutableInvalidParameters = 0x7013,
855
856    NoDataState = 0x7014,
857
858    NoDefaultValue = 0x8001,
859
860    DefaultValueTransmissionTooLong = 0x8002,
861
862    DefaultValueTransmissionTooShort = 0x8003,
863
864    DefaultValueCannotBeChanged = 0x8004,
865
866    DefaultValueWriteProtected = 0x8005,
867
868    InvalidDriveNumber = 0x800A,
869
870    GeneralError = 0x800B,
871
872    NoElementAddressed = 0x800C,
873
874    Unknown = 0xFFFF,
875}
876
877#[repr(i32)]
878#[derive(Debug, Clone, Copy, PartialEq, Eq)]
879pub enum EcCommType {
880
881    MailboxTx = 0,
882
883    MailboxRx = 1,
884
885    SdoRead = 2,
886
887    SdoWrite = 3,
888
889    Pdo = 4,
890
891    Register = 5,
892
893    Eeprom = 6,
894
895    Dc = 7,
896
897    Count = 8,
898}
899
900#[repr(u8)]
901#[derive(Debug, Clone, Copy, PartialEq, Eq)]
902pub enum EcPortType {
903
904    NotUsed = 0,
905
906    MII = 1,
907
908    EBUS = 2,
909
910    EBUSEnhanced = 3,
911}
912
913impl fmt::Display for EcPortType {
914    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
915        let desc = match self {
916            Self::NotUsed => "未使用",
917            Self::MII => "MII",
918            Self::EBUS => "EBUS",
919            Self::EBUSEnhanced => "EBUS+",
920        };
921        write!(f, "{}", desc)
922    }
923}
924
925#[repr(u8)]
926#[derive(Debug, Clone, Copy, PartialEq, Eq)]
927pub enum EcTopologyType {
928
929    NoLink = 0,
930
931    EndPoint = 1,
932
933    Line = 2,
934
935    Fork = 3,
936
937    Cross = 4,
938}
939
940impl fmt::Display for EcTopologyType {
941    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
942        let desc = match self {
943            Self::NoLink => "无链接 (No Link)",
944            Self::EndPoint => "端点 (End Point)",
945            Self::Line => "中间节点 (Line)",
946            Self::Fork => "分支点 (Fork)",
947            Self::Cross => "交叉点 (Cross)",
948        };
949        write!(f, "{}", desc)
950    }
951}
952
953#[repr(u8)]
954#[derive(Debug, Clone, Copy, PartialEq, Eq)]
955pub enum EcPdiType {
956
957    None = 0x00,
958
959    DigitalInput4 = 0x01,
960
961    DigitalOutput4 = 0x02,
962
963    DigitalIO2x2 = 0x03,
964
965    DigitalIO = 0x04,
966
967    SPISlave = 0x05,
968
969    OverloadOutput = 0x06,
970
971    EscSyncManager = 0x07,
972
973    UCAsync16 = 0x08,
974
975    UCAsync8 = 0x09,
976
977    UCSync16 = 0x0A,
978
979    UCSync8 = 0x0B,
980
981    DigitalIO32 = 0x10,
982
983    DigitalIO24x8 = 0x11,
984
985    DigitalIO16x16 = 0x12,
986
987    DigitalIO8x24 = 0x13,
988
989    OnChipBus = 0x80,
990
991    Unknown = 0xFF,
992}
993
994impl fmt::Display for EcPdiType {
995    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
996        let desc = match self {
997            Self::None => "无PDI (Interface deactivated)",
998            Self::DigitalInput4 => "4个数字输入",
999            Self::DigitalOutput4 => "4个数字输出",
1000            Self::DigitalIO2x2 => "2个数字输入 + 2个数字输出",
1001            Self::DigitalIO => "数字I/O",
1002            Self::SPISlave => "SPI从站",
1003            Self::OverloadOutput => "过载保护输出",
1004            Self::EscSyncManager => "ESC同步管理器",
1005            Self::UCAsync16 => "uC async. 16bit",
1006            Self::UCAsync8 => "uC async. 8bit",
1007            Self::UCSync16 => "uC sync. 16bit",
1008            Self::UCSync8 => "uC sync. 8bit",
1009            Self::DigitalIO32 => "32个数字输入/输出",
1010            Self::DigitalIO24x8 => "24个数字输入 + 8个数字输出",
1011            Self::DigitalIO16x16 => "16个数字输入 + 16个数字输出",
1012            Self::DigitalIO8x24 => "8个数字输入 + 24个数字输出",
1013            Self::OnChipBus => "On-chip bus",
1014            Self::Unknown => "未知类型",
1015        };
1016        write!(f, "{}", desc)
1017    }
1018}
1019
1020#[repr(u16)]
1021#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1022pub enum EcDeviceType {
1023
1024    Undefined = 0,
1025
1026    Static = 1,
1027
1028    InputNoMailbox = 2,
1029
1030    OutputNoMailbox = 3,
1031
1032    InputWithMailbox = 4,
1033
1034    OutputWithMailbox = 5,
1035
1036    IONoMailbox = 6,
1037
1038    IOWithMailbox = 7,
1039}
1040
1041impl fmt::Display for EcDeviceType {
1042    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1043        let desc = match self {
1044            Self::Undefined => "未定义",
1045            Self::Static => "静态设备(无IO映射)",
1046            Self::InputNoMailbox => "输入设备(无邮箱)",
1047            Self::OutputNoMailbox => "输出设备(无邮箱)",
1048            Self::InputWithMailbox => "输入设备(有邮箱)",
1049            Self::OutputWithMailbox => "输出设备(有邮箱)",
1050            Self::IONoMailbox => "输入输出设备(无邮箱)",
1051            Self::IOWithMailbox => "输入输出设备(有邮箱)",
1052        };
1053        write!(f, "{}", desc)
1054    }
1055}
1056
1057#[repr(u8)]
1058#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1059pub enum EcSyncManagerType {
1060
1061    NotUsed = 0,
1062
1063    MailboxOut = 1,
1064
1065    MailboxIn = 2,
1066
1067    ProcessDataOut = 3,
1068
1069    ProcessDataIn = 4,
1070}
1071
1072impl fmt::Display for EcSyncManagerType {
1073    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1074        let desc = match self {
1075            Self::NotUsed => "未使用",
1076            Self::MailboxOut => "邮箱输出",
1077            Self::MailboxIn => "邮箱输入",
1078            Self::ProcessDataOut => "过程数据输出",
1079            Self::ProcessDataIn => "过程数据输入",
1080        };
1081        write!(f, "{}", desc)
1082    }
1083}
1084
1085#[repr(u8)]
1086#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1087pub enum EcFmmuType {
1088
1089    NotUsed = 0,
1090
1091    Output = 1,
1092
1093    Input = 2,
1094
1095    SyncManagerStatus = 3,
1096}
1097
1098impl fmt::Display for EcFmmuType {
1099    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1100        let desc = match self {
1101            Self::NotUsed => "未使用",
1102            Self::Output => "输出",
1103            Self::Input => "输入",
1104            Self::SyncManagerStatus => "同步管理器状态",
1105        };
1106        write!(f, "{}", desc)
1107    }
1108}
1109
1110#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1111pub struct EcCoEDetails(pub u8);
1112
1113impl EcCoEDetails {
1114
1115    pub const NONE: Self = Self(0x00);
1116
1117    pub const SDO: Self = Self(0x01);
1118
1119    pub const SDO_INFO: Self = Self(0x02);
1120
1121    pub const PDO_ASSIGN: Self = Self(0x04);
1122
1123    pub const PDO_CONFIG: Self = Self(0x08);
1124
1125    pub const STARTUP: Self = Self(0x10);
1126
1127    pub const COMPLETE_ACCESS: Self = Self(0x20);
1128
1129    pub fn contains(self, other: Self) -> bool {
1130        (self.0 & other.0) == other.0
1131    }
1132
1133    pub fn union(self, other: Self) -> Self {
1134        Self(self.0 | other.0)
1135    }
1136}
1137
1138#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1139pub struct EcEoEDetails(pub u8);
1140
1141impl EcEoEDetails {
1142
1143    pub const NONE: Self = Self(0x00);
1144
1145    pub const SEND_FRAME: Self = Self(0x01);
1146
1147    pub const RECEIVE_FRAME: Self = Self(0x02);
1148
1149    pub const SET_IP_PARAM: Self = Self(0x04);
1150
1151    pub const GET_IP_PARAM: Self = Self(0x08);
1152
1153    pub fn contains(self, other: Self) -> bool {
1154        (self.0 & other.0) == other.0
1155    }
1156
1157    pub fn union(self, other: Self) -> Self {
1158        Self(self.0 | other.0)
1159    }
1160}
1161
1162#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1163pub enum EcStateFormat {
1164
1165    Short,
1166
1167    Long,
1168
1169    WithHex,
1170}
1171
1172pub fn format_ec_state(state: u8, format: EcStateFormat) -> String {
1173    let (short, long) = match state & 0x0F {
1174        0x01 => ("INIT", "Init"),
1175        0x02 => ("PREOP", "Pre-Operational"),
1176        0x03 => ("BOOT", "Bootstrap"),
1177        0x04 => ("SAFEOP", "Safe-Operational"),
1178        0x08 => ("OP", "Operational"),
1179        _ => ("???", "Unknown"),
1180    };
1181    let err = if state & 0x10 != 0 { "+ERR" } else { "" };
1182    match format {
1183        EcStateFormat::Short => format!("{}{}", short, err),
1184        EcStateFormat::Long => format!("{}{}", long, err),
1185        EcStateFormat::WithHex => format!("{}{} (0x{:02X})", short, err, state),
1186    }
1187}
1188
1189#[repr(i32)]
1190#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1191pub enum DcSyncMode {
1192
1193    FreeRun = 0,
1194
1195    SmSynchron = 1,
1196
1197    DcSynchron = 2,
1198
1199    DcSynchron01 = 3,
1200}
1201
1202#[repr(i32)]
1203#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1204pub enum StartupTransition {
1205
1206    IP = 0,
1207
1208    PS = 1,
1209
1210    SO = 2,
1211
1212    OS = 3,
1213
1214    SP = 4,
1215
1216    PI = 5,
1217}
1218
1219#[repr(i32)]
1220#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1221pub enum StartupWriteTiming {
1222
1223    BeforeTransition = 0,
1224
1225    AfterTransition = 1,
1226}
1227
1228pub mod esm_timeouts {
1229
1230    pub const INIT_TO_PRE_OP: i32 = 2000;
1231
1232    pub const PRE_OP_TO_SAFE_OP: i32 = 3000;
1233
1234    pub const SAFE_OP_TO_OP: i32 = 8000;
1235
1236    pub const OP_TO_SAFE_OP: i32 = 200;
1237
1238    pub const SAFE_OP_TO_PRE_OP: i32 = 200;
1239
1240    pub const PRE_OP_TO_INIT: i32 = 200;
1241
1242    pub const TO_BOOT: i32 = 3000;
1243
1244    pub const BOOT_TO_INIT: i32 = 3000;
1245
1246    pub const SDO_TIMEOUT: i32 = 3000;
1247
1248    pub const MAILBOX_TIMEOUT: i32 = 5000;
1249
1250    pub const STATE_STABILIZE_DELAY: i32 = 100;
1251
1252    pub fn get_transition_timeout(current: u8, target: u8) -> i32 {
1253        match (current, target) {
1254            (0x01, 0x02) => INIT_TO_PRE_OP,
1255            (0x02, 0x04) => PRE_OP_TO_SAFE_OP,
1256            (0x04, 0x08) => SAFE_OP_TO_OP,
1257            (0x08, 0x04) => OP_TO_SAFE_OP,
1258            (0x04, 0x02) => SAFE_OP_TO_PRE_OP,
1259            (0x02, 0x01) => PRE_OP_TO_INIT,
1260            (_, 0x03) => TO_BOOT,
1261            (0x03, 0x01) => BOOT_TO_INIT,
1262            _ => 3000,
1263        }
1264    }
1265}
1266
1267#[repr(i32)]
1268#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1269pub enum StateCiA402 {
1270
1271    NotReadyToSwitchOn = 0,
1272
1273    SwitchOnDisabled = 1,
1274
1275    ReadyToSwitchOn = 2,
1276
1277    SwitchedOn = 3,
1278
1279    OperationEnabled = 4,
1280
1281    QuickStopActive = 5,
1282
1283    FaultReactionActive = 6,
1284
1285    Fault = 7,
1286
1287    Unknown = 99,
1288}
1289
1290#[repr(i8)]
1291#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1292pub enum ModeCiA402 {
1293
1294    PP = 1,
1295
1296    VL = 2,
1297
1298    PV = 3,
1299
1300    PT = 4,
1301
1302    HM = 6,
1303
1304    IP = 7,
1305
1306    CSP = 8,
1307
1308    CSV = 9,
1309
1310    CST = 10,
1311
1312    CSTCA = 11,
1313}
1314
1315#[repr(i32)]
1316#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1317pub enum LogCategory {
1318
1319    Error = 0,
1320
1321    Warning = 1,
1322
1323    Message = 2,
1324
1325    Mailbox = 3,
1326
1327    PDO = 4,
1328
1329    Debug = 5,
1330
1331    Local = 6,
1332}
1333
1334#[repr(i32)]
1335#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1336pub enum LicenseStatus {
1337
1338    NotVerified = 0,
1339
1340    Verifying = 1,
1341
1342    Verified = 2,
1343
1344    Failed = 3,
1345
1346    Expired = 4,
1347
1348    MachineIdMismatch = 5,
1349}