mokomoking2501/MoonECAT/protocol does not have a README file

    AddressMode

    pub(all) enum AddressMode {
    AutoIncrement
    ConfiguredStation(UInt)
    Logical(UInt)
    } derive(Eq,
    Debug
    )

    Addressing mode used when communicating with slaves.

    AddressType

    pub(all) enum AddressType {
    AutoIncrement
    Configured
    Broadcast
    Logical
    } derive(Eq,
    Debug
    )

    EtherCAT addressing modes. Auto-increment: slave position relative to first slave (negative offset). Configured: fixed address assigned during configuration. Broadcast: address 0x0000, all slaves respond. Logical: 32-bit address mapped via FMMU.

    DcInitResult

    pub(all) struct DcInitResult {
    reference_station : UInt
    configured_count : Int
    } derive(Eq,
    Debug
    )

    Result of DC initialization.

    DcPortTimes

    pub(all) struct DcPortTimes {
    port0 : UInt
    port1 : UInt
    port2 : UInt
    port3 : UInt
    } derive(Eq,
    Debug
    )

    Per-port DC receive times (all 4 ports).

    DlErrorCounters

    pub(all) struct DlErrorCounters {
    ports : FixedArray[PortErrorCounters]
    ecat_pu_errors : UInt
    pdi_errors : UInt
    } derive(Eq,
    Debug
    )

    DL/Physical layer error counters snapshot (ESC registers 0x0300–0x0313).

    EcCommand

    pub(all) enum EcCommand {
    NOP
    APRD
    APWR
    APRW
    FPRD
    FPWR
    FPRW
    BRD
    BWR
    BRW
    LRD
    LWR
    LRW
    ARMW
    FRMW
    } derive(Eq,
    Debug
    )

    EtherCAT command types as defined in ETG.1000.4.

    EcCommand::from_byte

    EcCommand::to_byte

    fn EcCommand::to_byte(self : EcCommand) -> Byte

    EcFrame

    pub(all) struct EcFrame {
    dst_mac : FixedArray[Byte]
    src_mac : FixedArray[Byte]
    pdus : Array[Pdu]
    } derive(Eq,
    Debug
    )

    EcFrame represents a fully decoded EtherCAT Ethernet frame.

    EcFrame::decode

    Decode an EcFrame from raw Ethernet bytes.

    EcFrame::encode

    fn EcFrame::encode(self : EcFrame) -> Bytes

    Encode an EcFrame into raw Ethernet bytes.

    EsmState

    pub(all) enum EsmState {
    Init
    PreOp
    SafeOp
    Op
    Boot
    } derive(Eq,
    Debug
    )

    EtherCAT Slave Machine (ESM) states as defined in ETG.1000.6.

    EsmState::can_transition

    fn EsmState::can_transition(self : EsmState, target : EsmState) -> Bool

    Check whether the transition from one ESM state to another is valid.

    EsmState::from_byte

    EsmState::to_byte

    fn EsmState::to_byte(self : EsmState) -> Byte

    ESM state register values.

    EsmStateRequestObservation

    pub(all) struct EsmStateRequestObservation {
    state : EsmState
    error_indication : Bool
    status_code : UInt?
    raw_status_code : UInt?
    control_wkc : UInt
    } derive(Eq,
    Debug
    )

    Final observation from a single AL Control state request.

    EsmStatusSnapshot

    pub(all) struct EsmStatusSnapshot {
    state : EsmState
    error_indication : Bool
    status_code : UInt?
    } derive(Eq,
    Debug
    )

    EsmTimeoutPolicy

    Optional per-target ESM transition timeout overrides.

    Fields map to the target state of each transition step. If a field is None, ETG-based default timeout is used.

    FrameBuilder

    pub(all) struct FrameBuilder {
    next_index : Int
    pending : Array[Pdu]
    pending_size : Int
    } derive(
    Debug
    )

    FrameBuilder accumulates PDUs and builds frames efficiently. Uses a running index counter for PDU correlation.

    FrameBuilder::add

    fn FrameBuilder::add(self : FrameBuilder, command : EcCommand, address : UInt, data : Bytes) -> Byte raise
    EcError

    Add a PDU to the pending list. Returns the assigned index for correlation. Raises ConfigError if frame capacity would be exceeded.

    FrameBuilder::build

    fn FrameBuilder::build(self : FrameBuilder) -> EcFrame

    Build and return the assembled EcFrame from pending PDUs. Resets the builder afterward.

    FrameBuilder::is_empty

    fn FrameBuilder::is_empty(self : FrameBuilder) -> Bool

    Check if the builder has no pending PDUs.

    FrameBuilder::length

    fn FrameBuilder::length(self : FrameBuilder) -> Int

    Return the number of pending PDUs.

    FrameBuilder::new

    Create a new FrameBuilder.

    FrameBuilder::reset

    fn FrameBuilder::reset(self : FrameBuilder) -> Unit

    Reset the builder for a new cycle, keeping the index counter.

    MutablePdoContext

    pub(all) struct MutablePdoContext {
    image :
    MutableProcessImage

    mappings : Array[PdoMapping]
    logical_base : UInt
    logical_size : Int
    } derive(
    Debug
    )

    MutablePdoContext combines a MutableProcessImage with PDO mappings for zero-copy exchange. Analogous to PdoContext but uses FixedArray[Byte].

    MutablePdoContext::build

    fn MutablePdoContext::build(slave_mappings : Array[(
    SlaveMapping
    , UInt)], logical_base : UInt) -> MutablePdoContext

    Build a MutablePdoContext from slave mappings, using pre-allocated buffers.

    MutablePdoContext::get_slave_inputs

    fn MutablePdoContext::get_slave_inputs(self : MutablePdoContext, station : UInt) -> FixedArray[Byte] raise
    EcError

    Get input data for a specific slave from the mutable process image. Returns a copy as FixedArray[Byte] (one allocation, but only on user request, not on the hot path).

    MutablePdoContext::set_slave_outputs

    fn MutablePdoContext::set_slave_outputs(self : MutablePdoContext, station : UInt, data : FixedArray[Byte]) -> Unit raise
    EcError

    Set output data for a specific slave in the mutable process image.

    PdoContext

    pub(all) struct PdoContext {
    image : ProcessImage
    mappings : Array[PdoMapping]
    logical_base : UInt
    logical_size : Int
    block_lrw : Bool
    } derive(
    Debug
    )

    PDO exchange context: holds the process image and all mappings.

    PdoContext::build

    fn PdoContext::build(slave_mappings : Array[(
    SlaveMapping
    , UInt)], logical_base : UInt) -> PdoContext

    Build a PdoContext from a list of slave mappings. Each SlaveMapping provides output/input byte counts from FMMU calculation.

    PdoContext::get_slave_inputs

    fn PdoContext::get_slave_inputs(self : PdoContext, station : UInt) -> Bytes raise
    EcError

    Get input data for a specific slave from the process image.

    PdoContext::set_slave_outputs

    fn PdoContext::set_slave_outputs(self : PdoContext, station : UInt, data : Bytes) -> Unit raise
    EcError

    Set output data for a specific slave in the process image.

    PdoExchangeResult

    pub(all) struct PdoExchangeResult {
    wkc : UInt
    irq : UInt
    } derive(Eq,
    Debug
    )

    Result of one PDO exchange, including WKC and datagram IRQ.

    PdoMapping

    pub(all) struct PdoMapping {
    station : UInt
    output_logical : UInt
    output_offset : Int
    output_length : Int
    input_logical : UInt
    input_offset : Int
    input_length : Int
    } derive(Eq,
    Debug
    )

    Per-slave PDO mapping entry, describing where in the process image this slave's data lives.

    Pdu

    pub(all) struct Pdu {
    header : PduHeader
    data : Bytes
    wkc : UInt
    } derive(Eq,
    Debug
    )

    Full PDU including header, data payload, and working counter.

    PduHeader

    pub(all) struct PduHeader {
    command : EcCommand
    index : Byte
    address : UInt
    len_flags : UInt
    irq : UInt
    } derive(Eq,
    Debug
    )

    EtherCAT PDU (Protocol Data Unit) header.

    PortErrorCounters

    pub(all) struct PortErrorCounters {
    frame_errors : UInt
    physical_errors : UInt
    forwarded_rx_errors : UInt
    lost_link_count : UInt
    } derive(Eq,
    Debug
    )

    Per-port error counters from ESC DL registers.

    ProcessImage

    pub(all) struct ProcessImage {
    outputs : Bytes
    inputs : Bytes
    output_size : Int
    input_size : Int
    } derive(
    Debug
    )

    Process data image: a contiguous byte buffer backing all slave I/O.

    ProcessImage::new

    fn ProcessImage::new(output_size : Int, input_size : Int) -> ProcessImage

    ScanResult

    pub(all) struct ScanResult {
    slave_count : Int
    slaves : Array[SlaveInfo]
    } derive(
    Debug
    )

    Result of a bus scan operation.

    SlaveInfo

    pub(all) struct SlaveInfo {
    position : Int
    configured_address : UInt
    identity :
    SlaveIdentity

    al_status : EsmState
    dl_status : UInt
    sii :
    SiiData
    ?
    } derive(
    Debug
    )

    SlaveInfo represents a discovered slave on the network.

    SmWatchdogConfig

    pub(all) struct SmWatchdogConfig {
    divider : UInt
    pdi_time : UInt
    pdata_time : UInt
    pdata_status : Bool
    pdata_counter : UInt
    } derive(Eq,
    Debug
    )

    SM Watchdog configuration snapshot read from ESC registers.

    address_offset

    fn address_offset(addr : UInt) -> UInt

    Extract the offset from a PDU address (high 16 bits).

    address_station

    fn address_station(addr : UInt) -> UInt

    Extract the position or station address from a PDU address (low 16 bits).

    al_status_code_description

    fn al_status_code_description(code : UInt) -> String

    Human-readable description of an AL Status Code per ETG.1000.6 Table 11.

    apply_op_only_policy

    fn[N :
    Nic
    ] apply_op_only_policy(nic : N, station : UInt, target : EsmState, op_only : Bool, output_sm_indices : Array[Int], timeout :
    Duration
    ) -> Unit raise
    EcError

    Apply OpOnly policy for a slave during ESM state transitions. When op_only is true and target state is not Op, disables the output process data SMs (typically SM2). When transitioning to Op, enables them.

    assign_station_address

    fn[N :
    Nic
    ] assign_station_address(nic : N, position : UInt, station_address : UInt, timeout :
    Duration
    ) -> Unit raise
    EcError

    Assign a configured station address to a slave at the given position.

    auto_increment_address

    fn auto_increment_address(position : UInt) -> UInt

    Build a PDU address from auto-increment position (negative offset from first slave). Position 0 = first slave, 1 = second slave, etc.

    broadcast_address

    fn broadcast_address(offset : UInt) -> UInt

    Build a PDU address for broadcast with register/memory offset.

    broadcast_mac

    let broadcast_mac : FixedArray[Byte]

    Broadcast MAC address used as destination for EtherCAT frames.

    broadcast_state

    fn[N :
    Nic
    ] broadcast_state(nic : N, target : EsmState, timeout :
    Duration
    , ack_error? : Bool) -> UInt raise
    EcError

    Request all slaves to transition to a target state via broadcast. Uses BWR to AL Control register. Returns the working counter.

    build_shutdown_path

    fn build_shutdown_path(current : EsmState) -> Array[EsmState]

    Build the safe shutdown path from a current state to Init.

    build_strict_transition_route

    fn build_strict_transition_route(current : EsmState, target : EsmState) -> Array[EsmState]

    Build a strict route that respects ETG-defined legal ESM step directions.

    Callers should use the returned path together with transition_through, or use transition_to_target_strict for a guarded one-shot operation.

    build_transition_path

    fn build_transition_path(target : EsmState) -> Array[EsmState]

    Build the standard forward transition path from Init to a target state.

    build_transition_route

    fn build_transition_route(current : EsmState, target : EsmState) -> Array[EsmState]

    Build a complete transition route from the current state to a target state.

    This reuses direct transitions when possible and otherwise falls back through the standard shutdown and forward startup paths.

    configured_address

    fn configured_address(station : UInt, offset : UInt) -> UInt

    Build a PDU address from configured (fixed) station address and memory offset.

    count_slaves

    Count the number of slaves on the bus by sending a BRD to register 0x0000. The working counter indicates how many slaves responded.

    dc_broadcast_sync_window

    Broadcast read DC System Time Difference (0x092C) across all slaves.

    Per ETG.1500 §5.13.3 (#1103), a BRD to register 0x092C returns the bitwise-OR of all slaves' System Time Difference values. The master compares this against a limit to monitor DC synchronisation quality.

    Returns the ORed 32-bit system time difference value and the working counter (number of DC slaves that responded).

    dc_check_support

    Check whether a slave supports Distributed Clocks. Reads DL Information register (0x0008) bit 2.

    dc_check_sync_window

    fn[N :
    Nic
    ] dc_check_sync_window(nic : N, limit_ns : UInt, timeout :
    Duration
    ) -> Bool raise
    EcError

    Check whether the broadcast sync window is within an acceptable limit.

    The limit_ns parameter is the maximum tolerable clock deviation in nanoseconds. Returns true when the ORed system time difference from all DC slaves is below the limit.

    dc_compensate_cycle

    fn[N :
    Nic
    ] dc_compensate_cycle(nic : N, reference_station : UInt, timeout :
    Duration
    ) -> Unit raise
    EcError

    Send one FRMW DC frame to distribute reference system time.

    dc_configure_linear

    fn[N :
    Nic
    ] dc_configure_linear(nic : N, stations : Array[UInt], cycle_ns : UInt, timeout :
    Duration
    , static_sync_iterations? : Int) -> DcInitResult? raise
    EcError

    Configure DC for a set of configured station addresses. Returns None when station list is empty.

    dc_configure_sync0

    fn[N :
    Nic
    ] dc_configure_sync0(nic : N, station : UInt, cycle_ns : UInt, timeout :
    Duration
    , shift_ns? : Int, sync1_cycle_ns? : UInt) -> Unit raise
    EcError

    Configure SYNC0 output for one slave. Uses full 64-bit DC system time to choose a future aligned start tick. When sync1_cycle_ns > 0, also configures SYNC1 and activates both (activation byte 0x07 instead of 0x03).

    dc_deactivate_sync

    Deactivate DC sync for a single slave. Writes 0 to the sync activation register and clears cycle times.

    dc_deactivate_sync_all

    Broadcast-deactivate DC sync on all slaves.

    dc_latch_times

    Latch DC receive times on all slaves by broadcast-writing to 0x0900.

    dc_read_port_times

    Read all 4 port receive times in a single FPRD (16 bytes from 0x0900).

    dc_read_receive_time

    Read latched DC receive time (port 0 timestamp) of one slave.

    dc_read_sof

    Read the 64-bit DC Start of Frame register (0x0918, 8 bytes).

    dc_read_sync_window

    Read DC sync window / system difference register (0x092C).

    dc_read_system_time_64

    fn[N :
    Nic
    ] dc_read_system_time_64(nic : N, station : UInt, timeout :
    Duration
    ) -> UInt64 raise
    EcError

    Read the full 64-bit DC system time from a slave (0x0910, 8 bytes).

    dc_reestimate_propagation_delays

    fn[N :
    Nic
    ] dc_reestimate_propagation_delays(nic : N, reference_station : UInt, stations : Array[UInt], timeout :
    Duration
    , smoothing_num? : UInt, smoothing_den? : UInt) -> Unit raise
    EcError

    Re-estimate and update propagation delay during runtime. This closes the loop for ETG.1500 #1102 by periodically updating 0x0928.

    dc_static_sync

    fn[N :
    Nic
    ] dc_static_sync(nic : N, reference_station : UInt, iterations : Int, timeout :
    Duration
    ) -> Unit raise
    EcError

    Run static FRMW pre-compensation during startup.

    decode_pdu_response_from

    fn decode_pdu_response_from(buf : FixedArray[Byte], buf_len : Int, target : FixedArray[Byte], target_offset : Int, target_len : Int) -> (UInt, UInt) raise
    EcError

    Decode the first PDU's WKC and data from a received frame in a FixedArray[Byte]. Extracts WKC and copies input data back into the target buffer. Returns (wkc, irq) on success. This is the zero-allocation hot-path decoder for PDO exchange.

    decode_pdu_response_slice

    fn decode_pdu_response_slice(buf : FixedArray[Byte], buf_len : Int, skip : Int, target : FixedArray[Byte], target_offset : Int, target_len : Int) -> (UInt, UInt) raise
    EcError

    Decode the first PDU from a received frame, copying only a sub-range of the PDU data into the target buffer. Used for LRW responses where we only want the input portion (skipping the output echo). Returns (wkc, irq) on success.

    decode_pdu_wkc_only

    fn decode_pdu_wkc_only(buf : FixedArray[Byte], buf_len : Int) -> UInt raise
    EcError

    Decode only the WKC from the first PDU in a received frame. Used for LWR responses where we don't need the response data. Zero allocation.

    default_esm_timeout_policy

    fn default_esm_timeout_policy() -> EsmTimeoutPolicy

    Build a timeout policy that uses ETG-based defaults for all transitions.

    default_master_mac

    let default_master_mac : FixedArray[Byte]

    A default source MAC address for the master.

    dl_control_alias_enable_bit

    let dl_control_alias_enable_bit : Int

    DL Control bit used to enable station alias addressing.

    ecat_frame_type

    let ecat_frame_type : Int

    EtherCAT frame type in the 4-bit type field (always 0x1).

    ecat_header_len

    let ecat_header_len : Int

    EtherCAT frame header length: 2 bytes (length + type).

    eeprom_read

    fn[N :
    Nic
    ] eeprom_read(nic : N, station : UInt, start_word : UInt, word_count : Int, timeout :
    Duration
    ) -> Bytes raise
    EcError

    Read a contiguous range of EEPROM data starting at a word address. Returns word_count * 4 bytes. Each read returns one 32-bit SII data window, so consecutive reads advance by two 16-bit EEPROM words.

    eeprom_read_ap

    fn[N :
    Nic
    ] eeprom_read_ap(nic : N, position : UInt, start_word : UInt, word_count : Int, timeout :
    Duration
    ) -> Bytes raise
    EcError

    Read a contiguous EEPROM range using auto-increment addressing. This is useful during scan while slave positions are stable but configured station addressing may not yet be reliable on all devices.

    eeprom_read_word

    fn[N :
    Nic
    ] eeprom_read_word(nic : N, station : UInt, word_address : UInt, timeout :
    Duration
    ) -> Bytes raise
    EcError

    Read a single 32-bit (4-byte) word from a slave's EEPROM at the given word address. Returns 4 bytes of EEPROM data.

    eeprom_write_word

    fn[N :
    Nic
    ] eeprom_write_word(nic : N, station : UInt, word_address : UInt, data : UInt, timeout :
    Duration
    ) -> Unit raise
    EcError

    Write a single 16-bit word to a slave's EEPROM at the given word address. Implements ETG.1500 #305 (EEPROM Write may).

    Protocol (per SOEM pattern):
    1. Acquire Master ownership
    2. Write 16-bit data to SII data register (0x0508)
    3. Write command (0x0201) + address to SII control register (0x0502)
    4. Wait for busy flag to clear
    5. Restore PDI ownership

    eeprom_write_word_ap

    fn[N :
    Nic
    ] eeprom_write_word_ap(nic : N, position : UInt, word_address : UInt, data : UInt, timeout :
    Duration
    ) -> Unit raise
    EcError

    Write a single 16-bit word to a slave's EEPROM using auto-increment addressing.

    enable_alias_addressing

    fn[N :
    Nic
    ] enable_alias_addressing(nic : N, station : UInt, timeout :
    Duration
    ) -> Unit raise
    EcError

    Set DL Control Bit24 to enable alias addressing for one slave.

    encode_lrw_frame_into

    fn encode_lrw_frame_into(buf : FixedArray[Byte], dst_mac : FixedArray[Byte], src_mac : FixedArray[Byte], index : Byte, logical_addr : UInt, data : FixedArray[Byte], data_offset : Int, data_len : Int) -> Int

    Encode a single LRW PDU frame directly into a FixedArray[Byte] buffer. Returns the total frame length written. This is the zero-allocation hot-path encoder for PDO exchange.

    The frame layout: [Ethernet header 14B] [EtherCAT header 2B] [PDU header 10B] [data] [WKC 2B]

    encode_pdu_frame_into

    fn encode_pdu_frame_into(buf : FixedArray[Byte], dst_mac : FixedArray[Byte], src_mac : FixedArray[Byte], command : EcCommand, index : Byte, address : UInt, data : FixedArray[Byte], data_offset : Int, data_len : Int) -> Int

    Encode a single command PDU frame into a FixedArray[Byte] buffer. More general than encode_lrw_frame_into — supports any EcCommand. Returns the total frame length written.

    encode_zero_data_frame_into

    fn encode_zero_data_frame_into(buf : FixedArray[Byte], dst_mac : FixedArray[Byte], src_mac : FixedArray[Byte], command : EcCommand, index : Byte, address : UInt, data_len : Int) -> Int

    Encode a PDU frame with a zero-filled data payload (no source array needed). Used for LRD requests where the outgoing data is all zeros. Returns the total frame length.

    esm_default_timeout

    fn esm_default_timeout(target : EsmState) ->
    Duration

    Return the baseline ESM transition timeout for a given target state.

    Defaults are aligned with common EtherCAT master practice and can be overridden by SII/ESI-derived values through EsmTimeoutPolicy.

    esm_timeout_for

    Resolve transition timeout for a target state using policy override first, then falling back to ETG-based defaults.

    esm_timeout_policy_from_sii_timeouts

    fn esm_timeout_policy_from_sii_timeouts(timeouts :
    SiiTimeouts
    ?) -> EsmTimeoutPolicy

    Build an EsmTimeoutPolicy from SII-parsed timeouts (ETG.2010 category 41).

    Mapping:
    • preop_timeout_ms → preop (transition TO PreOp)
    • safeop_op_timeout_ms → op (SafeOp→Op transition)
    • back_to_init_timeout_ms → init (transition TO Init)
    • back_to_safeop_timeout_ms → safeop (transition TO SafeOp)
    • boot → None (not specified by SII)

    Returns a default (all-None) policy when timeouts are absent.

    ethernet_header_len

    let ethernet_header_len : Int

    Ethernet II frame header length: dst(6) + src(6) + ethertype(2) = 14 bytes.

    find_pdu_by_index

    fn find_pdu_by_index(frame : EcFrame, index : Byte) -> Pdu?

    Find a PDU in a decoded response frame by its index byte.

    fmmu_entry_size

    let fmmu_entry_size : Int

    FMMU entry size in bytes.

    foe_download

    FoE Download (write file to slave) using FP addressing.

    Flow: Write(filename) → Ack(0) → Data(1) → Ack(1) → ... → Data(N) → Ack(N) EOF is indicated when the last Data segment is shorter than max_data_per_segment. If the data is an exact multiple of max_data_per_segment, an empty Data segment is sent to signal EOF.

    foe_download_ap

    fn[N :
    Nic
    ] foe_download_ap(nic : N, position : UInt, mb_config :
    MailboxConfig
    , rmsm :
    Rmsm
    , filename : String, password : UInt, data : Bytes, timeout :
    Duration
    ) -> Unit raise
    EcError

    FoE Download (write file to slave) using AP addressing.

    foe_upload

    FoE Upload (read file from slave) using FP addressing.

    Flow: Read(filename) → Data(1) → Ack(1) → Data(2) → Ack(2) → ... → Data(N,short) → Ack(N) Returns the assembled file data.

    foe_upload_ap

    FoE Upload (read file from slave) using AP addressing. Returns the assembled file data.

    logical_address

    fn logical_address(addr : UInt) -> UInt

    Build a 32-bit logical address for LRD/LWR/LRW commands.

    mailbox_exchange

    Send a mailbox frame and wait for the response. Combines mailbox_send + mailbox_recv into a single round-trip.

    mailbox_exchange_ap

    Send a mailbox frame and wait for the response using auto-increment addressing.

    mailbox_poll

    Poll a slave's input mailbox (SM In) to check if data is available. Returns true if the mailbox contains data ready to be read.

    mailbox_poll_ap

    Poll a slave's input mailbox using auto-increment addressing. Returns true if the mailbox contains data ready to be read.

    mailbox_read_ap

    Read the current AP mailbox input buffer once without polling.

    mailbox_recv

    Receive a mailbox frame from a slave by reading the SM Input address range. This function:
    1. Polls the SM In status until data is available (up to max_polls attempts).
    2. Reads the full SM In address range via FPRD.
    3. Returns the raw mailbox frame bytes.

    mailbox_recv_ap

    Receive a mailbox frame from a slave using auto-increment addressing.

    mailbox_recv_ap_rmsm

    Receive a mailbox frame using AP addressing and use RMSM Repeat/RepeatAck recovery once when the initial mailbox read times out.

    mailbox_recv_rmsm

    Receive a mailbox frame and use RMSM Repeat/RepeatAck recovery once when the initial mailbox read times out.

    mailbox_send

    Send a mailbox frame to a slave by writing to the SM Output address range. This function:
    1. Checks that the data fits in the slave's mailbox.
    2. Pads the data to the full SM Out size (required by EtherCAT spec).
    3. Writes to the SM Out physical address via FPWR.

    mailbox_send_ap

    Send a mailbox frame to a slave using auto-increment addressing.

    max_pdus_per_frame

    let max_pdus_per_frame : Int

    Maximum number of PDUs that can fit in a single Ethernet frame. Conservative estimate based on max frame size and minimum PDU overhead.

    pdo_exchange

    Execute one PDO cycle: send outputs via LRW, receive inputs. Returns the working counter from the response.

    pdo_exchange_result

    Execute one PDO cycle and return both WKC and IRQ from the response datagram.

    pdo_exchange_zero_copy

    Zero-copy PDO exchange using ZeroCopyNic. The complete hot-path cycle with zero heap allocation:
    1. Acquire TX slot from pool (no alloc)
    2. Encode LRW frame directly into TX buffer (no alloc)
    3. Submit frame to NIC (no alloc)
    4. Receive response into RX slot (no alloc)
    5. Decode response data in-place into MutableProcessImage (no alloc)
    6. Release RX slot (no alloc)

    pdo_read

    Execute a read-only PDO cycle (LRD): fetch inputs without writing outputs.

    pdo_read_zero_copy

    Zero-copy read-only PDO cycle (LRD).

    pdo_write

    Execute a write-only PDO cycle (LWR): send outputs without reading.

    pdo_write_zero_copy

    Zero-copy write-only PDO cycle (LWR).

    pdu_header_len

    let pdu_header_len : Int

    Minimum EtherCAT PDU header length: 10 bytes.

    read_al_status

    Read the current ESM state from a slave.

    read_al_status_ap

    Read the current ESM state using auto-increment addressing.

    read_al_status_code

    Read the AL Status Code from a slave (error code for failed transitions).

    read_al_status_code_ap

    fn[N :
    Nic
    ] read_al_status_code_ap(nic : N, position : UInt, timeout :
    Duration
    ) -> UInt raise
    EcError

    read_al_status_snapshot

    read_al_status_snapshot_ap

    read_command

    fn read_command(addr_type : AddressType) -> EcCommand

    Determine which command to use for a read operation given an address type.

    read_device_emulation

    fn[N :
    Nic
    ] read_device_emulation(nic : N, station : UInt, timeout :
    Duration
    ) -> Bool raise
    EcError

    Read the Type register (0x0000) from a slave and check if the Device Emulation flag (bit 7 of byte 0) is set.

    read_dl_error_counters

    Read DL/Physical layer error counters from ESC registers using configured station addressing. Reads registers 0x0300–0x030D (RX Error, Forwarded RX Error, EPU, PDI) and 0x0310–0x0313 (Lost Link).

    read_dl_error_counters_ap

    Read DL/Physical layer error counters using auto-increment (AP) addressing.

    read_register_ap

    fn[N :
    Nic
    ] read_register_ap(nic : N, position : UInt, register : UInt, length : Int, timeout :
    Duration
    ) -> Pdu raise
    EcError

    Read a register from a slave using auto-increment addressing.

    read_register_fp

    fn[N :
    Nic
    ] read_register_fp(nic : N, station : UInt, register : UInt, length : Int, timeout :
    Duration
    ) -> Pdu raise
    EcError

    Read a register from a slave using configured station addressing.

    read_sii_bytes

    fn[N :
    Nic
    ] read_sii_bytes(nic : N, station : UInt, initial_word_count : Int, timeout :
    Duration
    ) -> Bytes raise
    EcError

    Read a complete SII EEPROM image using the fixed metadata block to expand the initial probe to the EEPROM-declared total byte size.

    read_sii_bytes_ap

    fn[N :
    Nic
    ] read_sii_bytes_ap(nic : N, position : UInt, initial_word_count : Int, timeout :
    Duration
    ) -> Bytes raise
    EcError

    Read a complete SII EEPROM image using auto-increment addressing.

    read_sm_watchdog_config

    Read SM Watchdog configuration from ESC registers.

    read_station_address_ap

    fn[N :
    Nic
    ] read_station_address_ap(nic : N, position : UInt, timeout :
    Duration
    ) -> UInt raise
    EcError

    Read configured station address register (0x0010) using auto-increment addressing.

    read_station_alias

    Read station alias register (0x0012) using configured station addressing.

    readwrite_command

    fn readwrite_command(addr_type : AddressType) -> EcCommand

    Determine which command to use for a read-write operation given an address type.

    recover_al_error_for_transition

    Recover from a pending AL error before the caller selects a new target state. Configuration-stage failures are stabilized by rolling back to Init; other errors are acknowledged in place.

    reg_al_control

    let reg_al_control : UInt

    AL Control register: request ESM state transition.

    reg_al_status

    let reg_al_status : UInt

    AL Status register: current ESM state and error indication.

    reg_al_status_code

    let reg_al_status_code : UInt

    AL Status Code register: error code for failed ESM transitions.

    reg_build

    let reg_build : UInt

    reg_dc_cuc

    let reg_dc_cuc : UInt

    DC control unit register.

    reg_dc_cycle0

    let reg_dc_cycle0 : UInt

    DC SYNC0 cycle time register.

    reg_dc_cycle1

    let reg_dc_cycle1 : UInt

    DC SYNC1 cycle time register.

    reg_dc_sof

    let reg_dc_sof : UInt

    DC receive timestamp register used for offset compensation.

    reg_dc_speed_count

    let reg_dc_speed_count : UInt

    DC speed counter start register (0x0930).

    reg_dc_start0

    let reg_dc_start0 : UInt

    DC SYNC0 start time register.

    reg_dc_sync_act

    let reg_dc_sync_act : UInt

    DC sync activate register.

    reg_dc_system_delay

    let reg_dc_system_delay : UInt

    DC propagation delay register.

    reg_dc_system_diff

    let reg_dc_system_diff : UInt

    DC sync window/system difference register.

    reg_dc_system_offset

    let reg_dc_system_offset : UInt

    DC system time offset register.

    reg_dc_system_time

    let reg_dc_system_time : UInt

    DC system time register.

    reg_dc_time0

    let reg_dc_time0 : UInt

    DC receive time register (port 0). Broadcast write latches all port times.

    reg_dc_time1

    let reg_dc_time1 : UInt

    DC receive time register (port 1).

    reg_dc_time2

    let reg_dc_time2 : UInt

    DC receive time register (port 2).

    reg_dc_time3

    let reg_dc_time3 : UInt

    DC receive time register (port 3).

    reg_dc_time_filter

    let reg_dc_time_filter : UInt

    DC time loop filter register (0x0934).

    reg_dl_control

    let reg_dl_control : UInt

    DL Control register.

    reg_dl_information

    let reg_dl_information : UInt

    DL Information register: supported features (DC, FMMU count, SM count, etc.).

    reg_dl_port

    let reg_dl_port : UInt

    DL Port control register (forwarding / loop-back per port).

    reg_dl_status

    let reg_dl_status : UInt

    DL Status register: link status, loop status, signal detection.

    reg_ecat_pu_error_counter

    let reg_ecat_pu_error_counter : UInt

    EtherCAT Processing Unit Error Counter register (0x030C).

    reg_fmmu_base

    let reg_fmmu_base : UInt

    FMMU base register (FMMU0 starts at 0x0600, each FMMU is 16 bytes).

    reg_fwd_rx_error_counter

    let reg_fwd_rx_error_counter : UInt

    Forwarded RX Error Counter base register (0x0308–0x030B, 4 bytes: one per port).

    reg_irq_mask

    let reg_irq_mask : UInt

    IRQ Mask register (0x0200).
    let reg_lost_link_counter : UInt

    Lost Link Counter base register (0x0310–0x0313, 4 bytes: one per port).

    reg_pdi_error_counter

    let reg_pdi_error_counter : UInt

    PDI Error Counter register (0x030D).

    reg_revision

    let reg_revision : UInt

    reg_rx_error_counter

    let reg_rx_error_counter : UInt

    RX Error Counter base register (0x0300–0x0307, 8 bytes: frame+physical per port).

    reg_sii_address

    let reg_sii_address : UInt

    SII address register (word address for EEPROM read/write).

    reg_sii_config

    let reg_sii_config : UInt

    SII (EEPROM) control/status register.

    reg_sii_control

    let reg_sii_control : UInt

    SII (EEPROM) control/status register.

    reg_sii_data

    let reg_sii_data : UInt

    SII data register (EEPROM data, 4 or 8 bytes depending on operation).

    reg_sm_base

    let reg_sm_base : UInt

    Sync Manager base register (SM0 starts at 0x0800, each SM is 8 bytes).

    reg_station_address

    let reg_station_address : UInt

    Configured Station Address register.

    reg_station_alias

    let reg_station_alias : UInt

    Configured Station Alias register.

    reg_type

    let reg_type : UInt

    EtherCAT register addresses used during discovery and configuration.

    reg_watchdog_counter_pdata

    let reg_watchdog_counter_pdata : UInt

    SM Watchdog Counter register (increments on each watchdog event).

    reg_watchdog_divider

    let reg_watchdog_divider : UInt

    Watchdog Divider register (ESC clock divider for both PDI and SM watchdogs).

    reg_watchdog_status_pdata

    let reg_watchdog_status_pdata : UInt

    SM Watchdog Status register (bit 0: 0=expired, 1=active/reloaded).

    reg_watchdog_time_pdata

    let reg_watchdog_time_pdata : UInt

    SM (Process Data) Watchdog Time register (process data arrival timeout).

    reg_watchdog_time_pdi

    let reg_watchdog_time_pdi : UInt

    PDI Watchdog Time register (master-to-PDI communication timeout).

    request_state_ap

    Request an ESM state transition using auto-increment addressing.

    request_state_aware

    fn[N :
    Nic
    ] request_state_aware(nic : N, station : UInt, target : EsmState, device_emulation? : Bool, timeout :
    Duration
    ) -> EsmState raise
    EcError

    Request an ESM state transition with Device Emulation awareness. For slaves with Device Emulation:
    • Clear Error Indication in AL Control (bit 4) before transition.
    • Write AL Control with Acknowledge bit when in error state. For normal slaves, behaves identically to request_state.

    request_state_observe

    Request an ESM state transition on a specific slave (by configured address). Writes AL Control, then reads AL Status to confirm. Returns the confirmed state or raises an error.

    request_state_with_process_data

    fn[N :
    Nic
    ] request_state_with_process_data(nic : N, station : UInt, target : EsmState, pdo_ctx : PdoContext, timeout :
    Duration
    ) -> EsmState raise
    EcError

    Request an ESM state transition while continuing cyclic PDO exchange.

    This is primarily needed for SAFEOP -> OP on actuator-style devices where the SubDevice only confirms OP once output process data has been received during the confirmation window.

    request_state_with_process_data_observe

    fn[N :
    Nic
    ] request_state_with_process_data_observe(nic : N, station : UInt, target : EsmState, pdo_ctx : PdoContext, timeout :
    Duration
    ) -> EsmStateRequestObservation raise
    EcError

    Request an ESM state transition while continuing cyclic PDO exchange, and return the last confirmed AL snapshot observed during polling.

    request_state_with_process_data_snapshot

    fn[N :
    Nic
    ] request_state_with_process_data_snapshot(nic : N, station : UInt, target : EsmState, pdo_ctx : PdoContext, timeout :
    Duration
    ) -> EsmStatusSnapshot raise
    EcError

    sdo_download

    Execute an SDO Download (write to slave Object Dictionary). Encodes the request, sends via mailbox, waits for response, validates. Supports expedited transfer (data ≤ 4 bytes).

    sdo_download_complete_access

    fn[N :
    Nic
    ] sdo_download_complete_access(nic : N, station : UInt, mb_config :
    MailboxConfig
    , rmsm :
    Rmsm
    , index : UInt, subindex : Byte, data : Bytes, timeout :
    Duration
    ) -> Unit raise
    EcError

    Execute an SDO Download with Complete Access enabled.

    sdo_download_retry

    Execute an SDO Download with RMSM retry support. Retries on MailboxTimeout up to RMSM's max_retries limit.

    sdo_info_get_od_description

    Read SDO Info Get OD (object description) for one object index.

    sdo_info_get_od_list

    Read CoE SDO Info OD list and return object indices.

    sdo_info_get_oe_description

    Read SDO Info Get OE (entry description) for one object entry.

    sdo_upload

    Execute an SDO Upload (read from slave Object Dictionary). Encodes the request, sends via mailbox, waits for response, returns data. Supports expedited transfer (data ≤ 4 bytes).

    sdo_upload_ap

    Execute an SDO Upload using auto-increment mailbox transport.

    sdo_upload_complete_access

    Execute an SDO Upload with Complete Access enabled.

    sdo_upload_retry

    Execute an SDO Upload with RMSM retry support. Retries on MailboxTimeout up to RMSM's max_retries limit.

    sdo_upload_retry_ap

    fn[N :
    Nic
    ] sdo_upload_retry_ap(nic : N, position : UInt, station : UInt, mb_config :
    MailboxConfig
    , rmsm :
    Rmsm
    , index : UInt, subindex : Byte, timeout :
    Duration
    ) -> Bytes raise
    EcError

    Execute an SDO Upload with RMSM retry support using auto-increment transport.

    set_slaves_to_default

    Reset all slaves to a known default state before scanning.

    Broadcasts zero-writes to FMMU, SM, DC, CRC, IRQ, and EEPROM registers, matching the sequence used by SOEM ecx_set_slaves_to_default. This ensures a clean slate regardless of any previous master session state.

    set_sm_enable

    fn[N :
    Nic
    ] set_sm_enable(nic : N, station : UInt, sm_index : Int, enable : Bool, timeout :
    Duration
    ) -> Unit raise
    EcError

    Enable or disable a specific Sync Manager. Used for OpOnly handling: disable output SM when not in Op state.

    SM activate register is at: SM_base + SM_index * 8 + 6

    sm_entry_size

    let sm_entry_size : Int

    Sync Manager entry size in bytes.

    transact

    Perform a single EtherCAT transaction: build a frame with the given PDUs, send it via the NIC, receive the response, and decode it. Returns the decoded response frame.

    transact_pdu

    fn[N :
    Nic
    ] transact_pdu(nic : N, command : EcCommand, address : UInt, data : Bytes, timeout :
    Duration
    ) -> Pdu raise
    EcError

    Send a single PDU transaction and return the response PDU. Convenience wrapper that builds a frame, sends, receives, and locates the PDU by index.

    transact_pdu_retry

    fn[N :
    Nic
    ] transact_pdu_retry(nic : N, command : EcCommand, address : UInt, data : Bytes, timeout :
    Duration
    , max_retries : Int) -> Pdu raise
    EcError

    Send a single PDU and retry up to max_retries times on RecvTimeout.

    transition_through

    Transition a slave through a sequence of ESM states. Each step validates can_transition before issuing the request. On failure it attempts rollback to the previous state.

    transition_through_ap

    transition_through_observe

    Transition through an ESM path and return the final step observation.

    transition_through_with_timeout_policy

    fn[N :
    Nic
    ] transition_through_with_timeout_policy(nic : N, station : UInt, path : Array[EsmState], policy : EsmTimeoutPolicy) -> EsmState raise
    EcError

    Transition through an ESM path using per-target timeout policy.

    Callers may feed SII/ESI-derived timeouts through policy while retaining sane defaults for missing entries.

    transition_through_with_timeout_policy_observe

    fn[N :
    Nic
    ] transition_through_with_timeout_policy_observe(nic : N, station : UInt, path : Array[EsmState], policy : EsmTimeoutPolicy) -> EsmStateRequestObservation? raise
    EcError

    Transition through an ESM path using per-target timeout policy and return the final step observation.

    transition_to_target_strict

    fn[N :
    Nic
    ] transition_to_target_strict(nic : N, station : UInt, target : EsmState, timeout :
    Duration
    ) -> EsmState raise
    EcError

    Strict state transition entry point.

    If AL Error Indication is currently set, this function refuses to guess the recovery policy and requires the caller to recover the error first via recover_al_error_for_transition(...) (or clear_al_error(...) when the caller knows an in-place acknowledge is correct), then explicitly choose the next target state.

    transition_to_target_strict_ap

    fn[N :
    Nic
    ] transition_to_target_strict_ap(nic : N, position : UInt, target : EsmState, timeout :
    Duration
    ) -> EsmState raise
    EcError

    transition_to_target_strict_observe

    Strict state transition entry point that returns the final request observation.

    transition_to_target_strict_with_timeout_policy

    fn[N :
    Nic
    ] transition_to_target_strict_with_timeout_policy(nic : N, station : UInt, target : EsmState, policy : EsmTimeoutPolicy, fallback_timeout :
    Duration
    ) -> EsmState raise
    EcError

    Strict transitions via multi-step route with per-target timeout policy.

    Same as transition_to_target_strict but resolves per-step timeouts from the supplied policy, allowing SII/ESI-derived timeout overrides.

    transition_to_target_strict_with_timeout_policy_observe

    fn[N :
    Nic
    ] transition_to_target_strict_with_timeout_policy_observe(nic : N, station : UInt, target : EsmState, policy : EsmTimeoutPolicy, fallback_timeout :
    Duration
    ) -> EsmStateRequestObservation? raise
    EcError

    Strict transitions via multi-step route with per-target timeout policy, returning the final step observation when a control write was issued.

    wkc_len

    let wkc_len : Int

    Working counter size: 2 bytes per PDU.

    write_command

    fn write_command(addr_type : AddressType) -> EcCommand

    Determine which command to use for a write operation given an address type.

    write_register_ap

    fn[N :
    Nic
    ] write_register_ap(nic : N, position : UInt, register : UInt, data : Bytes, timeout :
    Duration
    ) -> Pdu raise
    EcError

    Write a register to a slave using auto-increment addressing.

    write_register_fp

    fn[N :
    Nic
    ] write_register_fp(nic : N, station : UInt, register : UInt, data : Bytes, timeout :
    Duration
    ) -> Pdu raise
    EcError

    Write a register to a slave using configured station addressing.

    write_sm_watchdog_config

    fn[N :
    Nic
    ] write_sm_watchdog_config(nic : N, station : UInt, divider : UInt, pdi_time : UInt, pdata_time : UInt, timeout :
    Duration
    ) -> Unit raise
    EcError

    Write SM Watchdog configuration to ESC registers. Configures watchdog divider (0x0400), PDI watchdog time (0x0410), and process data watchdog time (0x0420).

    write_station_alias

    fn[N :
    Nic
    ] write_station_alias(nic : N, station : UInt, station_alias : UInt, timeout :
    Duration
    ) -> Unit raise
    EcError

    Write station alias register (0x0012) using configured station addressing.