# `EtherCAT.DC`
[🔗](https://github.com/sid2baker/ethercat/blob/main/lib/ethercat/dc.ex#L1)

Distributed Clocks initialization and runtime maintenance.

`EtherCAT.DC` is the public boundary for network-wide Distributed Clocks.
One-time clock initialization and periodic FRMW/diagnostic maintenance are
exposed here, while the internal runtime loop owns the active lock state.

## Initialization

`initialize_clocks/2` performs the one-time synchronization sequence used
during startup:

1. trigger receive-time latches on all slaves
2. read one DC snapshot per slave
3. pick the first DC-capable slave as the reference clock
4. build the deterministic offset and propagation-delay plan
5. write offsets and delays back to all DC-capable slaves
6. reset PLL filters

The current topology model is intentionally limited to a linear bus ordered
by scan position.

## Runtime lock states

The DC runtime reports lock state as ordinary runtime data:

- `:disabled` - no DC config
- `:inactive` - DC configured but runtime not started
- `:unavailable` - runtime active with no monitorable stations
- `:locking` - runtime active and converging
- `:locked` - sync diffs are within threshold

# `server`

```elixir
@type server() :: :gen_statem.server_ref()
```

# `t`

```elixir
@type t() :: %EtherCAT.DC{
  bus: EtherCAT.Bus.server(),
  config: EtherCAT.DC.Config.t(),
  cycle_count: non_neg_integer(),
  diagnostic_interval_cycles: pos_integer(),
  fail_count: non_neg_integer(),
  last_sync_check_at_ms: integer() | nil,
  lock_state: EtherCAT.DC.Status.lock_state(),
  max_sync_diff_ns: non_neg_integer() | nil,
  monitored_stations: [non_neg_integer()],
  notify_recovered_on_success?: boolean(),
  ref_station: non_neg_integer(),
  tick_interval_ms: pos_integer()
}
```

# `await_locked`

```elixir
@spec await_locked(server(), pos_integer()) :: :ok | {:error, term()}
```

Wait until the DC runtime reports a locked status.

# `initialize_clocks`

```elixir
@spec initialize_clocks(EtherCAT.Bus.server(), [{non_neg_integer(), binary()}]) ::
  {:ok, non_neg_integer(), [non_neg_integer()]} | {:error, term()}
```

Perform one-time DC clock initialization for the given scanned slave
topology.

# `status`

```elixir
@spec status(server()) :: EtherCAT.DC.Status.t() | {:error, :not_running}
```

Return the current Distributed Clocks runtime status.

Returns `{:error, :not_running}` when the DC runtime process is not active.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
