///|
/// SII category types (Slave Information Interface).
pub(all) enum SiiCategory {
Strings
DataTypes
General
Fmmu
SyncManager
FmmuEx
SyncUnit
TxPdo
RxPdo
Dc
Timeouts
Dictionary
Hardware
VendorInformation
Images
Raw
} derive(Eq, Debug)
///|
/// Stable export classification for SII categories.
pub(all) enum SiiCategoryClass {
StandardKnown
StandardUnknown
DeviceSpecific
VendorSpecific
ApplicationSpecific
} derive(Eq, Debug)
///|
/// Dispatch scope for future typed overlays on raw SII categories.
pub(all) enum SiiOverlayScope {
DeviceSpecific
VendorSpecific
ApplicationSpecific
} derive(Eq, Debug)
///|
pub(all) struct SiiOverlayCandidate {
scope : SiiOverlayScope
type_code : UInt
data : BytesView
} derive(Eq, Debug)
///|
pub fn SiiCategoryClass::label(self : SiiCategoryClass) -> String {
match self {
StandardKnown => "standard-known"
StandardUnknown => "standard-unknown"
DeviceSpecific => "device-specific"
VendorSpecific => "vendor-specific"
ApplicationSpecific => "application-specific"
}
}
///|
pub fn SiiOverlayScope::label(self : SiiOverlayScope) -> String {
match self {
DeviceSpecific => "device-specific"
VendorSpecific => "vendor-specific"
ApplicationSpecific => "application-specific"
}
}
///|
fn hex_digit(value : UInt) -> String {
match value {
0U => "0"
1U => "1"
2U => "2"
3U => "3"
4U => "4"
5U => "5"
6U => "6"
7U => "7"
8U => "8"
9U => "9"
10U => "A"
11U => "B"
12U => "C"
13U => "D"
14U => "E"
_ => "F"
}
}
///|
fn format_hex4(value : UInt) -> String {
hex_digit((value >> 12) & 0x0FU) +
hex_digit((value >> 8) & 0x0FU) +
hex_digit((value >> 4) & 0x0FU) +
hex_digit(value & 0x0FU)
}
///|
pub fn SiiOverlayCandidate::dispatch_key(self : SiiOverlayCandidate) -> String {
self.scope.label() + ":" + format_hex4(self.type_code)
}
///|
pub fn SiiOverlayCandidate::decoder_name(self : SiiOverlayCandidate) -> String? {
match self.dispatch_key() {
_ => None
}
}
///|
pub fn SiiOverlayCandidate::status_label(self : SiiOverlayCandidate) -> String {
match self.decoder_name() {
Some(_) => "registered"
None => "opaque"
}
}
///|
pub fn SiiCategoryEntry::category_class(
self : SiiCategoryEntry,
) -> SiiCategoryClass {
if self.category != Raw {
return StandardKnown
}
let type_code = self.type_code
if type_code >= 1U && type_code <= 9U {
return DeviceSpecific
}
if type_code >= 0x2000U && type_code <= 0x2FFFU {
return ApplicationSpecific
}
if (type_code >= 0x0800U && type_code <= 0x1FFFU) ||
(type_code >= 0x3000U && type_code <= 0xFFFEU) {
return VendorSpecific
}
StandardUnknown
}
///|
pub fn SiiCategoryEntry::overlay_candidate(
self : SiiCategoryEntry,
) -> SiiOverlayCandidate? {
match self.category_class() {
DeviceSpecific =>
Some({
scope: SiiOverlayScope::DeviceSpecific,
type_code: self.type_code,
data: self.data,
})
VendorSpecific =>
Some({
scope: SiiOverlayScope::VendorSpecific,
type_code: self.type_code,
data: self.data,
})
ApplicationSpecific =>
Some({
scope: SiiOverlayScope::ApplicationSpecific,
type_code: self.type_code,
data: self.data,
})
_ => None
}
}
///|
/// Basic SII data read from slave EEPROM.
pub(all) struct SiiData {
vendor_id : UInt
product_code : UInt
revision : UInt
serial : UInt
bootstrap_rx_offset : UInt
bootstrap_rx_size : UInt
bootstrap_tx_offset : UInt
bootstrap_tx_size : UInt
mailbox_rx_offset : UInt
mailbox_rx_size : UInt
mailbox_tx_offset : UInt
mailbox_tx_size : UInt
mailbox_protocols : UInt
firmware_version : UInt
hardware_version : UInt
production_date_raw : UInt
pdi_control_1 : Byte
esc_config_b0 : Byte
pdi_config_1 : UInt
pdi_config_1_ext : UInt
esc_config_b4 : UInt
esc_config_b5 : UInt
esc_config_b6 : UInt
checksum_b : UInt
esc_config_b_present : Bool
} derive(Eq, Debug)
///|
pub fn SiiData::production_year(self : SiiData) -> Int {
2000 + (self.production_date_raw & 0x7FU).reinterpret_as_int()
}
///|
pub fn SiiData::production_weekday(self : SiiData) -> Int {
((self.production_date_raw >> 7) & 0x07U).reinterpret_as_int()
}
///|
pub fn SiiData::production_week(self : SiiData) -> Int {
((self.production_date_raw >> 10) & 0x3FU).reinterpret_as_int()
}
///|
/// Fixed SII preamble loaded by the ESC during startup.
pub(all) struct SiiPreamble {
pdi_control : UInt
pdi_config : UInt
sync_impulse_length_raw : UInt
pdi_config2 : UInt
configured_station_alias : UInt
checksum : UInt
checksum_ok : Bool
} derive(Eq, Debug)
///|
pub fn SiiPreamble::sync_impulse_length_ns(self : SiiPreamble) -> UInt {
self.sync_impulse_length_raw * 10U
}
///|
/// Additional fixed metadata stored after the standard SII config block.
pub(all) struct SiiStandardMetadata {
eeprom_size_raw : UInt
version : UInt
} derive(Eq, Debug)
///|
pub fn SiiStandardMetadata::eeprom_size_bytes(
self : SiiStandardMetadata,
) -> UInt {
(self.eeprom_size_raw << 7) + 0x80U
}
///|
/// Parsed DC clock category entry.
/// This follows the field layout siitool uses for category 0x3c.
pub(all) struct SiiDcClock {
cycle_time_0 : UInt
shift_time_0 : UInt
shift_time_1 : UInt
sync1_cycle_factor : Int
assign_activate : UInt
sync0_cycle_factor : Int
name_idx : Byte
description_idx : Byte
} derive(Eq, Debug)
///|
/// Parsed SII PDO descriptor (TxPdo/RxPdo category).
pub(all) struct SiiPdo {
pdo_index : UInt
entry_count : Byte
sync_manager : Byte
synchronization : Byte
name_idx : Byte
flags : UInt
entries : Array[SiiPdoEntry]
} derive(Eq, Debug)
///|
/// Single entry within a PDO descriptor.
pub(all) struct SiiPdoEntry {
entry_index : UInt
subindex : Byte
name_idx : Byte
data_type : Byte
bit_length : Byte
flags : UInt
} derive(Eq, Debug)
///|
/// Parsed SII timeout category (ETG.2010 Table 13), values in milliseconds.
pub(all) struct SiiTimeouts {
preop_timeout_ms : UInt
safeop_op_timeout_ms : UInt
back_to_init_timeout_ms : UInt
back_to_safeop_timeout_ms : UInt
mailbox_request_timeout_ms : UInt
mailbox_response_timeout_ms : UInt
} derive(Eq, Debug)
///|
/// Parsed SII FMMU_EX category element (ETG.2010 Table 10).
pub(all) struct SiiFmmuEx {
op_only : Bool
sm_defined : Bool
su_defined : Bool
sync_manager : Byte
sync_unit : Byte
} derive(Eq, Debug)
///|
/// Parsed SII SyncUnit category element (ETG.2010 Table 14).
pub(all) struct SiiSyncUnit {
separate_su : Bool
separate_frame : Bool
depend_on_input_state : Bool
frame_repeat_support : Bool
raw_flags : Byte
} derive(Eq, Debug)
///|
/// A parsed SII category with its type tag and raw data.
pub(all) struct SiiCategoryEntry {
category : SiiCategory
type_code : UInt
data : BytesView
} derive(Eq, Debug)
///|
/// Aggregated SII view shared by CLI, runtime, and offline projection paths.
pub(all) struct SiiFullInfo {
eeprom : BytesView
preamble : SiiPreamble
standard : SiiStandardMetadata
header : SiiData
categories : Array[SiiCategoryEntry]
strings : Array[String]
general : SiiGeneral?
timeouts : SiiTimeouts?
fmmu : Array[FmmuDirection]
fmmu_ex : Array[SiiFmmuEx]
sync_managers : Array[SiiSmEntry]
sync_units : Array[SiiSyncUnit]
tx_pdo : Array[SiiPdo]
rx_pdo : Array[SiiPdo]
dc_clocks : Array[SiiDcClock]
} derive(Debug)