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}