# `EtherCAT.Bus.Datagram`
[🔗](https://github.com/sid2baker/ethercat/blob/main/lib/ethercat/bus/datagram.ex#L1)

An EtherCAT datagram struct and wire-format codec (spec §2.2).

## Wire layout (all little-endian, LSB first)

    Byte  0:     CMD (8 bit)
    Byte  1:     IDX (8 bit)
    Bytes 2–5:   Address (32 bit, layout depends on CMD)
    Bytes 6–7:   Len[10:0] | R[13:11]=0 | C[14] | M[15]
    Bytes 8–9:   IRQ (16 bit)
    Bytes 10…n:  Data (Len bytes)
    Last 2:      WKC (16 bit)

The circulating bit (C) is a slave-side mechanism for detecting frames
that loop in a ring after a cable break (spec §3.5). The master always
sends C=0; a returned C=1 means the frame circulated (error condition).

# `t`

```elixir
@type t() :: %EtherCAT.Bus.Datagram{
  address: &lt;&lt;_::32&gt;&gt;,
  circular: boolean(),
  cmd: 0..14,
  data: binary(),
  idx: byte(),
  irq: non_neg_integer(),
  wkc: non_neg_integer()
}
```

# `decode`

```elixir
@spec decode(binary()) :: {:ok, [t()]} | {:error, atom()}
```

Decode a binary into a list of datagrams.
Trailing padding bytes (after the last datagram where M=0) are ignored.

# `encode`

```elixir
@spec encode([t()]) :: binary()
```

Encode a list of datagrams into a contiguous binary.

Sets the M (more) bit on all but the last datagram.
The C (circulating) bit is always sent as 0.

# `wire_size`

```elixir
@spec wire_size(t()) :: non_neg_integer()
```

Encoded size in bytes: 10-byte header + data + 2-byte WKC.

---

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