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

The process data of a segment as one image in logical memory: the outputs of every SubDevice, then
their inputs, each SubDevice's part mapped to its sync manager by an FMMU.

`EtherCAT.MainDevice.map/2` makes it, and `EtherCAT.MainDevice.exchange/3` sends the outputs and
gives back the inputs, both as binaries of the sizes the image says. In them, an entry of a
SubDevice's PDOs is found by its station address and the object it maps:

    outputs = EtherCAT.ProcessImage.outputs(image)
    outputs = EtherCAT.ProcessImage.put(image, outputs, 0x1008, {0x7000, 0x01}, true)
    {:ok, inputs} = EtherCAT.MainDevice.exchange(main, outputs)
    true = EtherCAT.ProcessImage.get(image, inputs, 0x1004, {0x6000, 0x01})

A value is what the entry's data type makes it, the type its SubDevice's SII gives: a boolean for
one bit; a signed or unsigned integer; a float for REAL32 and REAL64; a binary for strings. An entry
of no known type is an unsigned integer of its bits.

A SubDevice's part takes whole bytes when it's a byte or more, and is packed in with others, bit by
bit, when it's less and its controller's FMMUs map single bits.

# `entry`

```elixir
@type entry() :: %{
  direction: :outputs | :inputs,
  offset: non_neg_integer(),
  bits: pos_integer(),
  data_type: 0..65535,
  name: String.t() | nil,
  pdo: 0..65535
}
```

Where an entry is, in the outputs or the inputs, from bit 0.

# `t`

```elixir
@type t() :: %EtherCAT.ProcessImage{
  address: 0..4_294_967_295,
  entries: %{required({0..65535, {0..65535, byte()}}) =&gt; entry()},
  inputs_size: non_neg_integer(),
  outputs_size: non_neg_integer(),
  subdevices: %{
    required(0..65535) =&gt; %{
      outputs: {non_neg_integer(), non_neg_integer()},
      inputs: {non_neg_integer(), non_neg_integer()}
    }
  }
}
```

The image: the bytes of its outputs and inputs, its logical address, its entries by station and
object, and each SubDevice's part, as bits from where in the outputs and the inputs.

# `entries`

```elixir
@spec entries(t(), 0..65535) :: [{{0..65535, byte()}, entry()}]
```

The entries of a SubDevice, by object, in the order they are in.

# `get`

```elixir
@spec get(t(), binary(), 0..65535, {0..65535, byte()}) :: term()
```

The value of an input entry in `inputs`, or of an output entry in `outputs`, as `exchange` gives
and takes them. Raises `ArgumentError` for an entry the image doesn't have.

# `outputs`

```elixir
@spec outputs(t()) :: binary()
```

Outputs of all zeros, the size of the image's.

# `put`

```elixir
@spec put(t(), binary(), 0..65535, {0..65535, byte()}, term()) :: binary()
```

`outputs` with an output entry set to `value`, which must fit the entry's data type. Raises
`ArgumentError` for an entry the image doesn't have, an input entry, or a value that doesn't fit.

---

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