The mailbox of a SubDevice: two areas of its memory behind sync managers 0 and 1, one the MainDevice writes and one it reads, each holding one message at a time (ETG.1000.4, 5.6 and 7.2).
A message is a header of six bytes, then its service data:
- the length of the service data
- a station address, the MainDevice's own (0) in what it sends
- a channel and priority, both 0 here
- the type, as
:coe, and a counter from 1 to 7 that tells a new message from a repeated one
A write that the SubDevice doesn't take, because it hasn't read the last one yet, comes back with a working counter of 0 and is sent again. A read of an empty mailbox likewise; so the MainDevice reads the status of sync manager 1 until it says the mailbox is full, then the mailbox.
Only one exchange goes on with a SubDevice's mailbox at once: transaction/4 waits its turn for
the mailbox, from the EtherCAT.MainDevice, and runs in the caller.
Summary
Types
A SubDevice's mailbox while it's the caller's: its station address, its two areas, an offset and a size each, and the counter of the next message.
A mailbox protocol.
Functions
A message read from a mailbox, its type, counter and service data, the rest of the mailbox passed
over; or {:error, :invalid_length} for a length that runs past it.
A message, its header and service data, padded with zeros to size, the size of the mailbox.
What an error reply's detail means (ETG.1000.4, Table 30).
Reads the next message from a SubDevice's mailbox, waiting until there is one: {:ok, {type, counter, address, data}, mailbox}, or {:error, :timeout}.
Runs fun with a SubDevice's mailbox once it's the caller's, and gives it back after. fun returns
its result with the mailbox as write/5 and read/3 left it, so that the counter goes on from
there. The result is that of fun, or {:error, :no_mailbox} for a SubDevice without one, or one
that wasn't scanned.
Writes a message to a SubDevice's mailbox, waiting until it takes it: the mailbox with its counter moved on, or why not.
Types
@type t() :: %{ station: 0..65535, receive: {0..65535, 0..65535}, send: {0..65535, 0..65535}, counter: 1..7, seen: [{type(), binary()}] }
A SubDevice's mailbox while it's the caller's: its station address, its two areas, an offset and a size each, and the counter of the next message.
@type type() :: :error | :aoe | :eoe | :coe | :foe | :soe | :voe | 0..15
A mailbox protocol.
Functions
A message read from a mailbox, its type, counter and service data, the rest of the mailbox passed
over; or {:error, :invalid_length} for a length that runs past it.
@spec encode(type(), 1..7, binary(), pos_integer()) :: binary()
A message, its header and service data, padded with zeros to size, the size of the mailbox.
@spec error(0..65535) :: atom() | 0..65535
What an error reply's detail means (ETG.1000.4, Table 30).
@spec read(EtherCAT.MainDevice.t(), t(), keyword()) :: {:ok, {type(), 0..7, 0..65535, binary()}, t()} | {:error, term()}
Reads the next message from a SubDevice's mailbox, waiting until there is one: {:ok, {type, counter, address, data}, mailbox}, or {:error, :timeout}.
@spec transaction( EtherCAT.MainDevice.t(), 0..65535, (t() -> {result, t()}), keyword() ) :: result | {:error, term()} when result: term()
Runs fun with a SubDevice's mailbox once it's the caller's, and gives it back after. fun returns
its result with the mailbox as write/5 and read/3 left it, so that the counter goes on from
there. The result is that of fun, or {:error, :no_mailbox} for a SubDevice without one, or one
that wasn't scanned.
@spec write(EtherCAT.MainDevice.t(), t(), type(), binary(), keyword()) :: {:ok, t()} | {:error, term()}
Writes a message to a SubDevice's mailbox, waiting until it takes it: the mailbox with its counter moved on, or why not.