diff --git a/conf.py b/conf.py
index 6e6da2cb4e0765b09966210695a9fd38f0f69d7f..082f84bb354d9c1658356ca495132c5505094b18 100644
--- a/conf.py
+++ b/conf.py
@@ -14,7 +14,7 @@ author = 'Martin Teichmann'
 
 release = "0.1"
 version = "0.1.0"
-language = None
+language = "en"
 exclude_patterns = ['_build']
 pygments_style = 'sphinx'
 todo_include_todos = False
diff --git a/ebpfcat/ebpfcat.py b/ebpfcat/ebpfcat.py
index dad8462e5c14022212ddc0a9b163f2c47f375429..5d03c47788b488324332a210af92047d540c41f5 100644
--- a/ebpfcat/ebpfcat.py
+++ b/ebpfcat/ebpfcat.py
@@ -69,8 +69,8 @@ class ProcessDesc:
         in the terminal's documentation
     :param subindex: the subindex, also found in the documentation
     :param size: usually the size is taken from the PDO mapping. A
-        different size as in a `struct` definition may be given here,
-        or the number of a bit for a bit field.
+        different size as in a :mod:`python:struct` definition may be
+        given here, or the number of a bit for a bit field.
     """
     def __init__(self, index, subindex, size=None):
         self.index = index
@@ -150,8 +150,11 @@ class Struct:
     """Define repetitive structures in a PDO
 
     Some terminals, especially multi-channel terminals,
-    have repetitive structures in their PDO. Use this to group
-    them.
+    have repetitive structures in their PDO. Inherit from this
+    class to create a structure for them. Each instance
+    will then define one channel. It takes one parameter, which
+    is the offset in the CoE address space from the template
+    structure to the one of the channel.
     """
     device = None
 
@@ -241,6 +244,12 @@ class Device(SubProgram):
 
 
 class EBPFTerminal(Terminal):
+    """This is the base class for all supported terminal types
+
+    inheriting classes should define a ``compatibility`` class variable
+    which is a set of tuples, each of which is a pair of Ethercat vendor and
+    product id of all supported terminal types.
+    """
     compatibility = None
     position_offset = {SyncManager.OUT: 0, SyncManager.IN: 0}
     use_fmmu = True
diff --git a/ebpfcat/ethercat.py b/ebpfcat/ethercat.py
index 1eb23e4bdae976d02c05ed33622cd83a8915ed0c..c7d54aa8e917a11fbec4379b7c314ac5de09fd17 100644
--- a/ebpfcat/ethercat.py
+++ b/ebpfcat/ethercat.py
@@ -445,7 +445,7 @@ class EtherCat(Protocol):
 
 
 class Terminal:
-    """Represent one terminal ("slave") in the loop"""
+    """Represent one terminal (*SubDevice* or *slave*) in the loop"""
     def __init__(self, ethercat):
         self.ec = ethercat
 
@@ -733,6 +733,11 @@ class Terminal:
             return b"".join(ret)
 
     async def sdo_read(self, index, subindex=None):
+        """read a single SDO entry
+
+        given an adress for a CoE entry like 6020:12, you may read
+        the value like ``await master.sdo_read(0x6020, 0x12)``.
+        """
         async with self.mbx_lock:
             await self.mbx_send(
                     MBXType.COE, "HBHB4x", CoECmd.SDOREQ.value << 12,
@@ -785,6 +790,13 @@ class Terminal:
             return b"".join(ret)
 
     async def sdo_write(self, data, index, subindex=None):
+        """write a single SDO entry
+
+        given a CoE address like 1200:2, one may write the value as
+        in ``await master.sdo_write(b'abc', 0x1200, 0x2)``. Note that the
+        data needs to already be a binary string matching the binary type of
+        the parameter.
+        """
         if len(data) <= 4 and subindex is not None:
             async with self.mbx_lock:
                 await self.mbx_send(
diff --git a/ebpfcat/ethercat.rst b/ebpfcat/ethercat.rst
index 45be9caddab435da04a8b7794566967e8caac210..9957beffb0d5b71278c262e2aff11d833e86b20a 100644
--- a/ebpfcat/ethercat.rst
+++ b/ebpfcat/ethercat.rst
@@ -89,7 +89,7 @@ Three methods of control
 
 The communication with the terminals can happen in three different ways:
 
-- out-of-order: the communication happens ad-hoc whenever needed. This is
+- asynchronous: the communication happens ad-hoc whenever needed. This is
   done during initialization and for reading and writing configuration data,
   like CoE.
 - slow: the data is sent, received and processed via Python. This is good
@@ -98,6 +98,74 @@ The communication with the terminals can happen in three different ways:
   Kernel. Only very limited operations can be done, but the loop cycle
   frequency exceeds 10 kHz.
 
+Adding new terminals
+--------------------
+
+The elements of an EtherCat loop were used to be called *slaves*, but nowadays
+are referred to as *SubDevices*. As in a typical installation most of them are
+simply terminals, we call them such.
+
+Everything in a terminal is controlled by reading or writing parameters in the
+CoE address space. These addresses are a pair of a 16 bit and an 8 bit number,
+usually seperated by a colon, as in 6010:13. Most terminals allow these
+parameters to be set asynchronously. Some of the parameters may be read or
+written synchronously, so with every communication cycle.
+
+The meaning of all these parameters can usually be found in the documentation of the terminal. Additionally, terminals often have a self-description, which can be read with the command line tool `ec-info`::
+
+    $ ec-info eth0 --terminal -1 --sdo
+
+this reads the first (-1th) terminal's self description (``--sdo``). Add a
+``--value`` to also get the current values of the parameters. This prints out
+all known self descriptions of CoE parameters.
+
+Once we know the meaning of parameters, they may be read or written
+asynchronously using :meth:`~ebpfcat.ethercat.Terminal.sdo_read` and
+:meth:`~ebpfcat.ethercat.Terminal.sdo_write`.
+
+For synchronous data access, a class needs to be defined that defines the
+parameters one want to use synchronously. The parameters available for
+synchronous operations can be found with the ``--pdo`` parameter of the
+``ec-info`` command. The class should inherit from
+:class:`~ebpfcat.ebpfcat.EBPFTerminal` and define a set of tuples called
+``comptibility``. The tuples should be the pairs of Ethercat product and vendor
+id for all terminals supported by this class. Those can be found out with the
+``--ids`` parameter of the ``ec-info`` command.
+
+Within the class, the synchronous parameters are defined via
+:class:`~ebpfcat.ebpfcat.ProcessDesc`. This descriptor takes the two parts of
+the CoE address as parameters, plus an optional size parameter. This is usually
+determined automatically, but this sometimes fails, in which case it may either
+be defined via a format string like in the :mod:`python:struct` module, or it
+is an integer which is then a reference to the position of the bit in the
+parameter to define a boolean flag.
+
+For terminals which have several equivalent channels, one can define a
+structure by inheriting from :class:`~ebpfcat.ebpfcat.Struct`. Within this
+class one defines the first set of parameters the same way one would do it
+without. Once the class is defined, it can be instantiated in the terminal
+class with a single argument which defines the offset in the CoE address space
+for this structure. As an example, if on a two-channel terminal the first
+channel has an address of ``0x6000:12`` and the following two ``0x6010:12`` and
+``0x6020:12``, one would instantiate three structs with arguments ``0``,
+``0x10`` and ``0x20``.
+
+A complete example of a four channel terminal looks as follows::
+
+    class EL3164(EBPFTerminal):
+        compatibility = {(2, 0x0c5c3052)}
+
+        class Channel(Struct):
+            attrs = ProcessDesc(0x6000, 1, 'H') # this is 2 bytes ('H')
+            value = ProcessDesc(0x6000, 0x11)
+            factor = 10/32767  # add bonus information as desired
+            offset = 0
+
+        channel1 = Channel(0)  # adress 0x6000
+        channel2 = Channel(0x10)  # address 0x6010
+        channel3 = Channel(0x20)
+        channel4 = Channel(0x30)
+
 
 Reference Documentation
 -----------------------
@@ -107,3 +175,6 @@ Reference Documentation
 
 .. automodule:: ebpfcat.ethercat
    :members:
+
+.. automodule:: ebpfcat.ebpfcat
+   :members:
diff --git a/ebpfcat/terminals.py b/ebpfcat/terminals.py
index 512d137baad332290a90be1ccea0f67011165e5f..b30dec338d2b274a2e6903b6c96b1c4d617e45db 100644
--- a/ebpfcat/terminals.py
+++ b/ebpfcat/terminals.py
@@ -98,6 +98,8 @@ class EL4104(EBPFTerminal):
 
 
 class EL3164(EBPFTerminal):
+    compatibility = {(2, 0x0c5c3052)}
+
     class Channel(Struct):
         attrs = ProcessDesc(0x6000, 1, 'H')
         value = ProcessDesc(0x6000, 0x11)