pub mod constants {
pub const ECT_MBXPROT_AOE: u16 = 0x0001;
pub const ECT_MBXPROT_EOE: u16 = 0x0002;
pub const ECT_MBXPROT_COE: u16 = 0x0004;
pub const ECT_MBXPROT_FOE: u16 = 0x0008;
pub const ECT_MBXPROT_SOE: u16 = 0x0010;
pub const ECT_MBXPROT_VOE: u16 = 0x0020;
pub const ECT_COEDET_SDO: u8 = 0x01;
pub const ECT_COEDET_SDOINFO: u8 = 0x02;
pub const ECT_COEDET_PDOASSIGN: u8 = 0x04;
pub const ECT_COEDET_PDOCONFIG: u8 = 0x08;
pub const ECT_COEDET_UPLOAD: u8 = 0x10;
pub const ECT_COEDET_SDOCA: u8 = 0x20;
}
#[derive(Clone, Debug, Default)]
#[repr(C, packed)]
pub struct PdoStats {
pub read_count: u32,
pub write_count: u32,
pub error_count: u32,
pub total_bytes_read: u32,
pub total_bytes_written: u32,
pub last_cycle_time_ns: u64,
pub min_cycle_time_ns: u64,
pub max_cycle_time_ns: u64,
pub avg_cycle_time_ns: u64,
}
#[derive(Clone, Debug)]
#[repr(C, packed)]
pub struct PdoMappingEntry {
pub index: u16,
pub sub_index: u8,
pub bit_length: u8,
pub bit_offset: u16,
pub name: [u8; 64],
pub unit: [u8; 16],
pub readable: u8,
pub writable: u8,
}
#[derive(Clone, Debug, Default)]
#[repr(C, packed)]
pub struct CommunicationStatsLocal {
pub total_cycles: u32,
pub successful_cycles: u32,
pub failed_cycles: u32,
pub timeout_cycles: u32,
pub average_cycle_time_us: f64,
pub max_cycle_time_us: f64,
pub min_cycle_time_us: f64,
}
#[derive(Clone, Debug, Default)]
pub struct SlaveInfo {
pub vendor_id: u32,
pub product_code: u32,
pub revision_number: u32,
pub serial_number: u32,
pub device_name: String,
pub vendor_name: String,
pub sync_manager_count: u16,
pub fmmu_count: u16,
pub supports_coe: bool,
pub supports_foe: bool,
pub supports_eoe: bool,
pub supports_soe: bool,
}
#[derive(Clone, Debug, Default)]
#[repr(C, packed)]
pub struct RealtimeStats {
pub current_cycle_time_us: f64,
pub jitter_us: f64,
pub lost_frames: u32,
pub corrupted_frames: u32,
pub bus_utilization: f64,
}
#[derive(Clone, Debug)]
#[repr(C, packed)]
pub struct NetworkInfo {
pub name: [u8; 128],
pub desc: [u8; 128],
pub slave_num: i16,
pub redundant_slave_num: i16,
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C, packed)]
pub struct EcSmt {
pub start_addr: u16,
pub sm_length: u16,
pub sm_flags: u32,
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C, packed)]
pub struct EcFmmut {
pub log_start: u32,
pub log_length: u16,
pub log_start_bit: u8,
pub log_end_bit: u8,
pub phys_start: u16,
pub phys_start_bit: u8,
pub fmmu_type: u8,
pub fmmu_active: u8,
pub unused1: u8,
pub unused2: u16,
}
#[derive(Clone, Debug)]
#[repr(C)]
pub struct EcSlave {
pub state: u16,
pub al_status_code: u16,
pub config_addr: u16,
pub alias_addr: u16,
pub eep_man: u32,
pub eep_id: u32,
pub eep_rev: u32,
pub eep_ser: u32,
pub itype: u16,
pub dtype: u16,
pub obits: u16,
pub _padding1: u16,
pub obytes: u32,
pub _padding2: u32,
pub outputs: usize,
pub ooffset: u32,
pub ostartbit: u8,
pub _padding3: u8,
pub ibits: u16,
pub ibytes: u32,
pub _padding4: u32,
pub inputs: usize,
pub ioffset: u32,
pub istartbit: u8,
pub sm: [EcSmt; 8],
pub sm_type: [u8; 8],
pub fmmu: [EcFmmut; 4],
pub fmmu0_func: u8,
pub fmmu1_func: u8,
pub fmmu2_func: u8,
pub fmmu3_func: u8,
pub mbx_l: u16,
pub mbx_wo: u16,
pub mbx_rl: u16,
pub mbx_ro: u16,
pub mbx_proto: u16,
pub mbx_cnt: u8,
pub hasdc: u8,
pub ptype: u8,
pub topology: u8,
pub activeports: u8,
pub consumedports: u8,
pub parent: u16,
pub parentport: u8,
pub entryport: u8,
pub dc_rt_a: i32,
pub dc_rt_b: i32,
pub dc_rt_c: i32,
pub dc_rt_d: i32,
pub pdelay: i32,
pub dc_next: u16,
pub dc_previous: u16,
pub dc_cycle: i32,
pub dc_cycle1: i32,
pub dc_shift: i32,
pub dc_active: u16,
pub sii_index: u16,
pub eep_8byte: u8,
pub eep_pdi: u8,
pub coe_details: u8,
pub foe_details: u8,
pub eoe_details: u8,
pub soe_details: u8,
pub ebus_current: i16,
pub block_lrw: u8,
pub group: u8,
pub fmmu_unused: u8,
pub islost: u8,
pub po2so_config: usize,
pub mbx_handler_state: i32,
pub mbx_rmp_state: i32,
pub mbx_in_state_ex: u16,
pub _padding8a: u16,
pub _padding8b: u32,
pub coe_mbx_in: usize,
pub coe_mbx_in_full: u8,
pub _padding9a: u8,
pub _padding9b: u16,
pub coe_mbx_overrun: i32,
pub soe_mbx_in: usize,
pub soe_mbx_in_full: u8,
pub _padding10a: u8,
pub _padding10b: u16,
pub soe_mbx_overrun: i32,
pub foe_mbx_in: usize,
pub foe_mbx_in_full: u8,
pub _padding11a: u8,
pub _padding11b: u16,
pub foe_mbx_overrun: i32,
pub eoe_mbx_in: usize,
pub eoe_mbx_in_full: u8,
pub _padding12a: u8,
pub _padding12b: u16,
pub eoe_mbx_overrun: i32,
pub voe_mbx_in: usize,
pub voe_mbx_in_full: u8,
pub _padding13a: u8,
pub _padding13b: u16,
pub voe_mbx_overrun: i32,
pub aoe_mbx_in: usize,
pub aoe_mbx_in_full: u8,
pub _padding14a: u8,
pub _padding14b: u16,
pub aoe_mbx_overrun: i32,
pub mbx_status: usize,
pub group_name: [u8; 41],
pub device_name: [u8; 41],
pub sync_manager_count: u16,
pub fsoe_capable: u8,
pub _padding15a: u8,
pub _padding15b: u16,
pub fsoe_connection: usize,
pub fsoe_sm_context: usize,
pub fsoe_connection_id: u16,
pub fsoe_safety_address: u16,
pub fsoe_safe_input_size: u16,
pub fsoe_safe_output_size: u16,
pub fsoe_pdo_input_offset: u32,
pub fsoe_pdo_output_offset: u32,
pub pdo_assignment_enabled: u8,
pub pdo_configuration_enabled: u8,
pub pdo_config_initialized: u8,
pub supports_complete_access: u8,
}
#[derive(Clone, Debug)]
#[repr(C)]
pub struct EcState {
pub state: u16,
pub al_status_code: u16,
pub slave_count: i32,
pub loop_cycle: u32,
pub dc_cycle: u32,
pub dc_time: i64,
pub iomap: [u8; 65536],
pub iomap_mutex: usize,
pub iomap_buffer: [u8; 65536],
pub buffer_version: u32,
pub buffer_dirty: u8,
pub mutex_protection: u8,
pub pdo_cpu_affinity: i8,
pub dc_auto_shift_enabled: u8,
pub use_udp: u8,
pub adaptive_timeout_enabled: u8,
pub overlapping_groups: u8,
pub packed_mode: u8,
pub frame_high_priority: u8,
pub vlan_id: u16,
pub vlan_priority: u8,
pub timeout_init_to_preop: u32,
pub timeout_preop_to_safeop: u32,
pub timeout_safeop_to_op: u32,
pub wd_pd_timeout_ms: u16,
pub wd_pdi_timeout_ms: u16,
pub filter_threshold: u32,
pub frame_repeat_count: u8,
pub active_group_count: u8,
pub _group_pad: [u8; 2],
pub group_config_raw: [u8; 64],
}
#[derive(Clone, Debug)]
#[repr(C)]
pub struct InternalDiagnostics {
pub cache_cnt: u32,
pub rt_cnt: u32,
pub cycle_count: u32,
pub error_cache_cnt: u32,
pub error_cnt: u32,
pub wkc: u16,
pub expected_wkc: u16,
pub cycle_time_span: u32,
pub frame_errors: u32,
pub lost_frames: u32,
pub out_of_order_frames: u32,
pub checksum_errors: u32,
pub timeout_frames: u32,
pub rx_error_count: [u32; 512],
pub tx_error_count: [u32; 512],
pub lost_link_count: [u16; 512],
pub invalid_frame_count: [u16; 512],
pub working_counter_errors: u16,
pub consecutive_wkc_errors: u16,
pub total_wkc_mismatches: u32,
pub cycle_start_time: u64,
pub cycle_time_accumulator: f64,
pub last_snapshot_time: u64,
pub snapshot_cycle_count: u32,
pub last_cycle_time_us: f64,
pub jitter_accumulator: f64,
pub max_jitter_in_second: f64,
pub jitter_sample_count: u32,
pub avg_jitter_us: f64,
pub max_jitter_us: f64,
pub cycle_time_sample_count: u32,
pub primary_port_tx_count: u32,
pub primary_port_rx_count: u32,
pub secondary_port_tx_count: u32,
pub secondary_port_rx_count: u32,
pub primary_port_errors: u32,
pub secondary_port_errors: u32,
pub link_quality_percent: [i16; 512],
pub last_good_frame_time: [u32; 512],
pub initialized: i32,
pub enabled: i32,
pub win_frame_errors: [u32; 5],
pub win_lost_frames: [u32; 5],
pub win_out_of_order: [u32; 5],
pub win_checksum_errors: [u32; 5],
pub win_timeout_frames: [u32; 5],
pub win_wkc_errors: [u16; 5],
pub win_wkc_mismatches: [u32; 5],
pub win_primary_errors: [u32; 5],
pub win_secondary_errors: [u32; 5],
pub win_head: i32,
pub win_filled: i32,
}
#[derive(Clone, Debug)]
#[repr(C, packed)]
pub struct EcAdapterEnhanced {
pub name: [u8; 128],
pub desc: [u8; 128],
pub next: usize,
}
#[derive(Clone, Debug)]
#[repr(C, packed)]
pub struct EcStartupParam {
pub index: u16,
pub subindex: u8,
pub data: usize,
pub data_length: u32,
pub phase: u8,
pub priority: u8,
pub is_read: u8,
}
#[derive(Clone, Debug)]
#[repr(C, packed)]
pub struct EcConfigListEnhanced {
pub man: u32,
pub id: u32,
pub index: u16,
pub name: [u8; 41],
pub dtype: u8,
pub ibits: u16,
pub obits: u16,
pub sm2a: u16,
pub sm2f: u32,
pub sm3a: u16,
pub sm3f: u32,
pub fm0ac: u8,
pub fm1ac: u8,
}
#[derive(Clone, Debug)]
#[repr(C, packed)]
pub struct EcStartupListEnhanced {
pub man: u32,
pub id: u32,
pub index: u16,
pub sdo_index: u16,
pub sdo_index2: u16,
pub length: u8,
pub data: [u8; 1486],
}
#[derive(Clone, Debug)]
#[repr(C, packed)]
pub struct EcDcListEnhanced {
pub man: u32,
pub id: u32,
pub config_addr: u16,
pub sync_s: i32,
pub sync0: u32,
pub sync1: u32,
}
#[derive(Clone, Debug)]
pub struct FoEOptionsLocal {
pub enable_crc: bool,
pub strict_mode: bool,
pub auto_append_crc: bool,
pub expected_crc: u32,
}
impl Default for FoEOptionsLocal {
fn default() -> Self {
Self {
enable_crc: false,
strict_mode: true,
auto_append_crc: true,
expected_crc: 0,
}
}
}
pub struct EcGroupConfigHelper;
impl EcGroupConfigHelper {
const GROUP_CONFIG_SIZE: usize = 8;
pub fn get_group_enabled(raw: &[u8], group: u8) -> bool {
if group >= 8 { return false; }
raw[group as usize * Self::GROUP_CONFIG_SIZE] != 0
}
pub fn set_group_enabled(raw: &mut [u8], group: u8, enabled: bool) {
if group >= 8 { return; }
raw[group as usize * Self::GROUP_CONFIG_SIZE] = if enabled { 1 } else { 0 };
}
pub fn get_group_cycle_divider(raw: &[u8], group: u8) -> u8 {
if group >= 8 { return 0; }
raw[group as usize * Self::GROUP_CONFIG_SIZE + 1]
}
pub fn set_group_cycle_divider(raw: &mut [u8], group: u8, divider: u8) {
if group >= 8 { return; }
raw[group as usize * Self::GROUP_CONFIG_SIZE + 1] = divider;
}
pub fn get_group_expected_wkc(raw: &[u8], group: u8) -> u16 {
if group >= 8 { return 0; }
let off = group as usize * Self::GROUP_CONFIG_SIZE + 2;
u16::from_le_bytes([raw[off], raw[off + 1]])
}
pub fn get_group_slave_count(raw: &[u8], group: u8) -> u16 {
if group >= 8 { return 0; }
let off = group as usize * Self::GROUP_CONFIG_SIZE + 4;
u16::from_le_bytes([raw[off], raw[off + 1]])
}
pub fn get_group_frame_repeat_eligible(raw: &[u8], group: u8) -> bool {
if group >= 8 { return false; }
raw[group as usize * Self::GROUP_CONFIG_SIZE + 6] != 0
}
pub fn set_group_frame_repeat_eligible(raw: &mut [u8], group: u8, eligible: bool) {
if group >= 8 { return; }
raw[group as usize * Self::GROUP_CONFIG_SIZE + 6] = if eligible { 1 } else { 0 };
}
}