# `EtherCAT.CoE`
[🔗](https://github.com/tallakt/yaethercat/blob/v0.1.0/lib/ethercat/coe.ex#L1)

CoE, the CAN application protocol over EtherCAT, through a SubDevice's mailbox (ETG.1000.6, 5.6):
SDO uploads and downloads, which read and write the entries of its object dictionary, by index and
subindex.

    {:ok, <<vendor_id::little-32>>} = EtherCAT.CoE.upload(main, 0x1001, 0x1018, 0x01)
    :ok = EtherCAT.CoE.download(main, 0x1001, 0x8000, 0x06, <<1>>)

Values are the bytes of the entry, little-endian, as the object dictionary has them. Up to four go
in the request itself (expedited); more go in one normal transfer, and in segments after it when
they don't fit the mailbox.

With `complete_access: true` the whole object is read or written at once, from subindex 0, or 1
to leave out the count there.

A SubDevice that refuses aborts the transfer with a code: `{:error, {:abort, code}}`, which
`describe_abort/1` explains. An upload bigger than `max_size:` is refused before it's read:
`{:error, {:too_big, size}}`. Emergency messages that come while waiting for an answer are kept,
and `emergencies/2` gives the latest of them.

# `error`

```elixir
@type error() ::
  {:abort, 0..4_294_967_295}
  | {:too_big, non_neg_integer()}
  | {:mailbox, atom() | 0..65535}
  | :timeout
  | :no_mailbox
  | {:invalid_response, binary()}
  | term()
```

Why a transfer failed.

# `data_type_name`

```elixir
@spec data_type_name(0..65535) :: String.t()
```

The name of a CoE data type, by its index in the object dictionary's data type area
(ETG.1000.6, 5.6.7.3).

    iex> EtherCAT.CoE.data_type_name(0x0003)
    "INTEGER16"
    iex> EtherCAT.CoE.data_type_name(0x0800)
    "0x0800"

# `decode_emergency`

```elixir
@spec decode_emergency(binary()) :: %{
  error_code: 0..65535,
  error_register: byte(),
  data: binary()
}
```

An emergency message's error code, error register and data (ETG.1000.6, 5.6.4).

    iex> EtherCAT.CoE.decode_emergency(<<0x01, 0xA0, 0x11, 1, 2, 3, 4, 5>>)
    %{error_code: 0xA001, error_register: 0x11, data: <<1, 2, 3, 4, 5>>}

# `describe_abort`

```elixir
@spec describe_abort(0..4_294_967_295) :: String.t()
```

What an SDO abort code means, in a few words.

    iex> EtherCAT.CoE.describe_abort(0x06020000)
    "No such object"

# `download`

```elixir
@spec download(
  EtherCAT.MainDevice.t(),
  0..65535,
  0..65535,
  byte(),
  binary(),
  keyword()
) ::
  :ok | {:error, error()}
```

Writes an entry of a SubDevice's object dictionary, by station address.

Options: `complete_access: true`, and `timeout:` (1 second) for each answer.

# `emergencies`

```elixir
@spec emergencies(EtherCAT.MainDevice.t(), 0..65535) :: [map()]
```

The latest emergency messages a SubDevice sent, newest first.

# `upload`

```elixir
@spec upload(EtherCAT.MainDevice.t(), 0..65535, 0..65535, byte(), keyword()) ::
  {:ok, binary()} | {:error, error()}
```

Reads an entry of a SubDevice's object dictionary, by station address.

Options: `complete_access: true`, `max_size:` (1 MiB), the most it takes, and `timeout:` (1
second) for each answer.

---

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