commit 1304b12bd859603ad9f9b68493e1a3257f5e4595
Author: Thomas Schöpping <tschoepp@cit-ec.uni-bielefeld.de>
Date:   Wed Nov 13 13:33:36 2019 +0100

    Revised the realization of AMiRo-LLD interfaces (including periphAL):
     - The periphAL.h file is now part aof AMiRo-LLD and must no be implemented externally.
     - Type definitions, which were described in periphALtypes.h are now included in periphAL.h.
     - Several configuration macros were introduced in order to enable/disable individual modules of periphAL.
     - periphAL version increased to 1.2
     - AMiRo-LLD version increased to 1.1.0
     - README.txt has been updated

diff --git a/README.txt b/README.txt
index f9cf003..ac5b590 100644
--- a/README.txt
+++ b/README.txt
@@ -93,12 +93,17 @@ not present on the AMiRo platform, are highly appreciated.
 The files are structured as follows:
 ./
 │ The project root directory contains this file, a license.html file as well as
-│ a Makefile that allows to easily integrate the project. Furthermore, two
+│ a makefile that allows to easily integrate the project. Furthermore, two
 │ interface headers are provided: amiro-lld.h and periphALtypes.h. These are
 │ entry points for any utilizing superproject, so it is not required (and not
 │ recommended) to include each driver individually.
 │
-├── include/
+├── docs/
+│     UML graphs (using PlantUML; see plantuml.com for further information)
+│     visualize the structure of the AMiRo-LLD project. Doxygen related files
+│     can be used to gererate a documentation of the whole project (wip).
+│
+├── drivers/
 │     For each supported hardware device, there is exactly one directory in this
 │     folder. Further subfolders may contain various versions of a driver (e.g.
 │     'v1/', 'v2/', etc.). By convention the root directory of a driver is named
@@ -107,24 +112,16 @@ The files are structured as follows:
 │     <product_name> is a placeholder for the exact name of the according
 │     hardware, or the product familiy, if the driver is compatible with all
 │     parts.
-│     The root header consequently follows the naming scheme
-│     "alld_<product_name>.h"
-│     and header files within the version folders shall be named like
-│     "alld<product_name>_<driver_version>.h"
-│
-├── source/
-│     Any source files are placed in this directory. Naming conventions for
-│     folders and files are the same as described before for the include
-│     directory, as is the file structure. There is a dedicated folder for each
-│     device and further subfolders for multiple driver versions. Source files
-│     should only be put in these version folders.
+│     Each driver must provide a makefile script, which adds the required
+│     include folders to the AMIROLLD_INC variable and all C source files to the
+│     AMIROLLD_CSRC variable.
 │
 └── templates/
-      AMiRo-LLD requires an implementation of the defined interface and an
-      configuration header to be accessible in the include paths at compile
-      time. Template files for both can be found in this folder. It is
-      recommended to place according implementations of these templated not in
-      the AMiRo-LLD project, but the superproject which includes AMiRo-LLD.
+      AMiRo-LLD expects a configuration header "alldconf.h" to be found in the
+      include paths. An according template for such file can be found here.
+      There is no template for an implementation of periphAL, though. The
+      provided interface header in the root directory (periphAL.h) should give
+      you all required information for such an implementation anyway.
 
 
 
@@ -137,58 +134,67 @@ results, which are portable and maintainable for future use. Whereas the textual
 descriptions of the guides provide additional information about the underlying
 concepts and mechanisms, a short summary is provided at the end of each chapter.
 
+
 3.1  Adding a Device
 --------------------
 
 When adding new device to the project, the very first step is to create the
-according folders in the include/ and source/ directories. For this guide, we
-will add the fictional DEVICE1234. For this example the folders to be created
-are "include/DEVICE1234/" and "source/DEVICE1234/".
-
-The first file should be the root header: "include/DEVICE1234/alld_DEVICE1234.h"
-Have a look at existing drivers and use one of those as template. This header
-should introduce a new configuration to be set in the alldconf.h file and check
-it using the preprocessor. Eventually, another header is included, pointing to
-the selected driver version/implementation.
-
-Such implementations are to be put in further subfolders, e.g.
-"include/DEVICE1234/v1/" and "source/DEVICE1234/v1/". The header and C-source
-files in those folders do not follow a strict scheme, although there are some
-conventions to consider (i.e. naming conventions, cf. chapter 2).
+according folder in the drivers/ directory. For this guide, we will add the
+fictional DEVICE1234. For this example the folders to be created are
+"drivers/DEVICE1234/" and "drivers/DEVICE1234/v1/". In case there already exists
+a driver implementation for this device, but you want to implement another
+version from scratch (not just an update), the version subfolder must be named
+accordingly (e.g. "drivers/DEVICE1234/v42/").
+
+Most drivers will consist of exactly three files:
+ - alld_DEVICE1234.mk
+ - alld_DEVICE1234.h
+ - alld_DEVICE1234.c
+However, some drivers may feature multiple .h and/or .c files or even come with
+additional subfolders. In any case, all those required folders, including the
+driver root folder (i.e. "drivers/DEVICE1234/v1/"), as well as all C source
+files must be added to the according makefile variables AMIROLLD_INC and
+AMIROLLD_CSRC by the makefile script.
+It is highly recommended that files in the driver root directory (i.e.
+"drivers/DEVICE1234/v1/") use the prefix "alld_" in their names. This not only
+helps to achieve an easy to understand file structure, but also prevents
+compilation issues due to naming conflicts of header files.
 
 Summing up, you have to
-1) create device folders.
-2) add a root header.
-3) add further subfolders and implement the driver there.
+1) create device and version folders.
+2) add a makefile script.
+3) add header- and source files as well as subfulders, implementing the diver
 
 
 3.2  Implementing a Driver
 --------------------------
 
-Implementation of a new driver usually is very straight-forward. You most
+Implementation of a new driver usually is very straightforward. You most
 probably have a comprehensive datasheet of the device, or the manufacturer even
 provides a reference driver implementation.
 
 For the former case, you should first write a comprehensive header, containing
 all information like constants, register maps, etc. and according abstract
 access functions (e.g. for reading and writing registers, and convenient access
-to common functionalities). Only the you implement those functions, using
-periphAL to interface any hardware interfaces (e.g. I2C, SPI, etc.).
+to common functionalities). Only then you implement those functions, using
+periphAL to interface any hardware interfaces (e.g. I2C, SPI, etc.) in a
+separate C source file, or 'inline' in the header file itself.
 
 For the latter case, the reference implementation will specify some interface
 functions to interact with the hardware (e.g. I2C, SPI etc.). Even though all
 functionality should be covered by the reference driver, you still need to
-implement those interface functions.
+implement those interface functions and map them to periphAL.
 
 Since AMiRo-LLD does not rely on specific hardware or operating system, the only
 valid way to interact with both is through periphAL. Under no circumstances you
 must use any function of your operating system and directly or indirectly access
 the hardware of your platform. For your driver, there is no knowledge about the
 world beyond periphAL! If periphAL does not provide the function you need, you
-can do the following: 1) Think again if you really need that funcionality or
-whether it can be replicated by existing functions. 2) File a feature request
-to extend periphAL. 3) Write a custom patch that modifies periphAL to meet your
-requirements.
+can do one of the following:
+1) Think again if you really need that funcionality or whether it can be
+   replicated by the existing API.
+2) File a feature request to extend periphAL.
+3) Write a custom patch that modifies periphAL to meet your requirements.
 
 Summing up, you have to
 1) Get and read the datasheet of the device (A) or
diff --git a/amiro-lld.h b/amiro-lld.h
index 06cbfbc..51dc9df 100644
--- a/amiro-lld.h
+++ b/amiro-lld.h
@@ -24,61 +24,95 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #define _AMIRO_LLD_
 
+/*===========================================================================*/
 /**
  * @name   AMiRo-LLD version and relase information.
  * @{
  */
+/*===========================================================================*/
 
 /**
  * @brief   Realease type of this version.
  * @note    Possible values are "pre-alpha", "alpha", "beta", "release candidate", and "release".
  */
-#define AMIRO_LLD_RELEASE_TYPE     "beta"
+#define AMIROLLD_RELEASE_TYPE                   "beta"
 
 /**
  * @brief   The AMiRo-LLD major version.
  * @note    Changes of the major version imply incompatibilities.
  */
-#define AMIRO_LLD_VERSION_MAJOR    1
+#define AMIROLLD_VERSION_MAJOR                  1
 
 /**
  * @brief   The AMiRo-LLD minor version.
  * @note    A higher minor version implies new functionalty, but all old interfaces are still available.
  */
-#define AMIRO_LLD_VERSION_MINOR    0
+#define AMIROLLD_VERSION_MINOR                  1
 
 /**
  * @brief   The AMiRo-LLD patch level.
  */
-#define AMIRO_LLD_VERSION_PATCH    2
-
-/**
- * @brief   The periphery abstraction layer interface required major version.
- * @note    Any other major version is assumed to be incompatible.
- */
-#define PERIPHAL_REQUIRED_MAJOR    1
-
-/**
- * @brief   The periphery abstraction layer interface required minor version.
- * @note    Higher minor version values are assumed to be compatible, too.
- */
-#define PERIPHAL_REQUIRED_MINOR    1
+#define AMIROLLD_VERSION_PATCH                  0
 
 /** @} */
 
+/******************************************************************************/
+/* CONFIGURATION & VERIFICATION                                               */
+/******************************************************************************/
+
 #include <alldconf.h>
+
 #if !defined(_AMIRO_LLD_CFG_)
-#error "invalid AMiRo-LLD configuration file"
-#elif (AMIRO_LLD_CFG_VERSION_MAJOR != AMIRO_LLD_VERSION_MAJOR) || (AMIRO_LLD_CFG_VERSION_MINOR < AMIRO_LLD_VERSION_MINOR)
-#error "incompatible AMiRo-LLD configuration file"
+  #error "invalid AMiRo-LLD configuration file"
+#elif (AMIRO_LLD_CFG_VERSION_MAJOR != AMIROLLD_VERSION_MAJOR) || (AMIRO_LLD_CFG_VERSION_MINOR < AMIROLLD_VERSION_MINOR)
+  #error "incompatible AMiRo-LLD configuration file"
 #endif
 
-#include "periphALtypes.h"
-#include <periphAL.h>
-#if !defined(PERIPHAL_VERSION_MAJOR) || !defined(PERIPHAL_VERSION_MINOR)
-#error "invalid periphAL implementation"
-#elif (PERIPHAL_VERSION_MAJOR != PERIPHAL_REQUIRED_MAJOR) || (PERIPHAL_VERSION_MINOR < PERIPHAL_REQUIRED_MINOR)
-#error "incompatible periphAL implementation"
+#if !defined(AMIROLLD_CFG_TIME_SIZE)
+  #error "AMIROLLD_CFG_TIME_SIZE not defined in alldconf.h"
+#endif /* !defined(AMIROLLD_CFG_TIME_SIZE) */
+
+#if !defined(AMIROLLD_CFG_DBG)
+  #error "AMIROLLD_CFG_DBG not defined in alldconf.h"
+#endif /* !defined(AMIROLLD_CFG_DBG) */
+
+#if !defined(AMIROLLD_CFG_GPIO)
+  #error "AMIROLLD_CFG_GPIO not defined in alldconf.h"
+#endif /* !defined(AMIROLLD_CFG_GPIO) */
+
+#if !defined(AMIROLLD_CFG_PWM)
+  #error "AMIROLLD_CFG_PWM not defined in alldconf.h"
+#endif /* !defined(AMIROLLD_CFG_PWM) */
+
+#if !defined(AMIROLLD_CFG_QEI)
+  #error "AMIROLLD_CFG_QEI not defined in alldconf.h"
+#endif /* !defined(AMIROLLD_CFG_QEI) */
+
+#if !defined(AMIROLLD_CFG_I2C)
+  #error "AMIROLLD_CFG_I2C not defined in alldconf.h"
+#endif /* !defined(AMIROLLD_CFG_I2C) */
+
+#if !defined(AMIROLLD_CFG_SPI)
+  #error "AMIROLLD_CFG_SPI not defined in alldconf.h"
+#endif /* !defined(AMIROLLD_CFG_SPI) */
+
+#if ((AMIROLLD_CFG_GPIO == true) || \
+     (AMIROLLD_CFG_PWM == true)  || \
+     (AMIROLLD_CFG_QEI == true)  || \
+     (AMIROLLD_CFG_I2C == true)  || \
+     (AMIROLLD_CFG_SPI == true)) && \
+    !defined(AMIROLLD_CFG_PERIPHAL_HEADER)
+  #error "AMIROLLD_CFG_PERIPHAL_HEADER required but not defined in alldconf.h"
 #endif
 
+/******************************************************************************/
+/* PERIPHERY ABSTRACTION LAYER (periphAL)                                     */
+/******************************************************************************/
+
+#if defined(AMIROLLD_CFG_PERIPHAL_HEADER)
+#include AMIROLLD_CFG_PERIPHAL_HEADER
+#endif
+
+#include <periphAL.h>
+
 #endif /* AMIROLLD_H */
diff --git a/periphAL.h b/periphAL.h
new file mode 100644
index 0000000..7987121
--- /dev/null
+++ b/periphAL.h
@@ -0,0 +1,768 @@
+/*
+AMiRo-LLD is a compilation of low-level hardware drivers for the Autonomous Mini Robot (AMiRo) platform.
+Copyright (C) 2016..2019  Thomas Schöpping et al.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef AMIROLLD_PERIPHAL_H
+#define AMIROLLD_PERIPHAL_H
+
+#include <amiro-lld.h>
+
+/*============================================================================*/
+/* VERSION                                                                    */
+/*============================================================================*/
+
+/**
+ * @brief   The periphery abstraction layer interface major version.
+ * @note    Changes of the major version imply incompatibilities.
+ */
+#define PERIPHAL_VERSION_MAJOR    1
+
+/**
+ * @brief   The periphery abstraction layer interface minor version.
+ * @note    A higher minor version implies new functionalty, but all old interfaces are still available.
+ */
+#define PERIPHAL_VERSION_MINOR    2
+
+/*============================================================================*/
+/* DEPENDENCIES                                                               */
+/*============================================================================*/
+
+#include <stdint.h>
+
+/*============================================================================*/
+/* GENERAL                                                                    */
+/*============================================================================*/
+
+/**
+ * @brief Status values used as return value for all (or most) function calls.
+ * @note  The status can be used as mask of flags.
+ */
+typedef int8_t apalExitStatus_t;
+
+/**
+ * @brief   Status value for success (no error or warning occurred).
+ */
+#define APAL_STATUS_OK                          ((apalExitStatus_t)0)
+#define APAL_STATUS_SUCCESS                     ((apalExitStatus_t)0)
+
+/**
+ * @brief   Status value for unspecified failure.
+ */
+#define APAL_STATUS_ERROR                       ((apalExitStatus_t)-1)
+#define APAL_STATUS_FAILURE                     ((apalExitStatus_t)-1)
+
+/**
+ * @brief   Status value for timeout failure.
+ */
+#define APAL_STATUS_TIMEOUT                     ((apalExitStatus_t)-2)
+
+/**
+ * @brief   Status value for failure because of invalid arguments.
+ */
+#define APAL_STATUS_INVALIDARGUMENTS            ((apalExitStatus_t)-4)
+
+/**
+ * @brief   Status value for failure because the function is not available/implemented.
+ */
+#define APAL_STATUS_UNAVAILABLE                 ((apalExitStatus_t)-8)
+
+/**
+ * @brief   Status value for unspecified warning.
+ */
+#define APAL_STATUS_WARNING                     ((apalExitStatus_t)1)
+
+/*============================================================================*/
+/* DEBUG                                                                      */
+/*============================================================================*/
+
+#if (AMIROLLD_CFG_DBG == true) || defined(__DOXYGEN__)
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
+#if !defined(apalDbgAssertMsg) || defined(__DOXYGEN__)
+  /**
+   * @brief Assert function to check a given condition and print a message string.
+   *
+   * @param[in] c     The condition to check.
+   * @param[in] fmt   Formatted message string to print.
+   */
+  void apalDbgAssertMsg(const bool c, const char* fmt, ...);
+#endif
+
+#if !defined(apalDbgPrintf) || defined(__DOXYGEN__)
+  /**
+   * @brief Printf function for messages printed only in debug builds.
+   *
+   * @param[in] fmt   Formatted string to print.
+   *
+   * return   Number of printed characters.
+   */
+  int apalDbgPrintf(const char* fmt, ...);
+#endif
+
+#if defined(__cplusplus)
+}
+#endif /* defined(__cplusplus) */
+
+/**
+ * @brief Assert function to check a given condition.
+ *
+ * @param[in] c     The condition to check.
+ */
+#define apalDbgAssert(c) apalDbgAssertMsg(c, "%s(%u): apalDbgAssert failed", __FILE__, __LINE__)
+
+#endif /* (AMIROLLD_CFG_DBG == true) */
+
+/*============================================================================*/
+/* TIMING                                                                     */
+/*============================================================================*/
+
+/**
+ * @brief Time measurement type (in microseconds).
+ */
+#if (AMIROLLD_CFG_TIME_SIZE == 8)
+  typedef uint8_t   apalTime_t;
+#elif (AMIROLLD_CFG_TIME_SIZE == 16)
+  typedef uint16_t  apalTime_t;
+#elif (AMIROLLD_CFG_TIME_SIZE == 32)
+  typedef uint32_t  apalTime_t;
+#elif (AMIROLLD_CFG_TIME_SIZE == 64)
+  typedef uint64_t  apalTime_t;
+#else
+  #error "AMIROLLD_CFG_TIME_SIZE must be 8, 16, 32 or 64"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(apalSleep) || defined(__DOXYGEN__)
+  /**
+   * @brief Delay execution by a specific number of microseconds.
+   *
+   * @param[in]   us    Time to sleep until execution continues in microseconds.
+   */
+  void apalSleep(apalTime_t us);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*============================================================================*/
+/* GPIO                                                                       */
+/*============================================================================*/
+
+#if (AMIROLLD_CFG_GPIO == true) || defined(__DOXYGEN__)
+
+/*
+ * The following type must be defined by the implementation:
+ *
+ * apalGpio_t
+ *   Type to represent a GPIO object.
+ *   Is only used via pointer by the API.
+ */
+
+/**
+ * @brief Status values to read/write a GPIO port.
+ */
+typedef uint8_t apalGpioState_t;
+
+/**
+ * @brief   GPIO physical low state.
+ */
+#define APAL_GPIO_LOW                           ((apalGpioState_t)0)
+
+/**
+ * @brief   GPIO physical high state.
+ */
+#define APAL_GPIO_HIGH                          ((apalGpioState_t)1)
+
+/**
+ * @brief   Invert a physical GPIO state.
+ *
+ * @param[in] state   GPIO state to invert.
+ *
+ * @return  Inverted physical GPIO state.
+ */
+#define APAL_GPIO_STATE_INVERT(state) (                                       \
+  (apalGpioState_t)state ^ APAL_GPIO_HIGH                                     \
+)
+
+/**
+ * @brief Logical status values to turn a control GPIO 'on' and 'off'.
+ */
+typedef uint8_t apalControlGpioState_t;
+
+/**
+ * @brief   GPIO logical off state.
+ */
+#define APAL_GPIO_OFF                           ((apalControlGpioState_t)0)
+
+/**
+ * @brief   GPIO logical on state.
+ */
+#define APAL_GPIO_ON                            ((apalControlGpioState_t)1)
+
+/**
+ * @brief   Polarity state of the control GPIO.
+ */
+typedef uint8_t apalGpioActive_t;
+
+/**
+ * @brief   The control GPIO is never defined to be 'on' (does not apply).
+ */
+#define APAL_GPIO_ACTIVE_NONE                   ((apalGpioActive_t)0)
+
+/**
+ * @brief   The control GPIO is defined to be 'on' when it is phsically low.
+ */
+#define APAL_GPIO_ACTIVE_LOW                    ((apalGpioActive_t)1)
+
+/**
+ * @brief   The control GPIO is defined to be 'on' when it is physically high.
+ */
+#define APAL_GPIO_ACTIVE_HIGH                   ((apalGpioActive_t)2)
+
+/**
+ * @brief   The control GPIO is defined to be always 'on'.
+ */
+#define APAL_GPIO_ACTIVE_ANY                    ((apalGpioActive_t)3)
+
+/**
+ * @brief   Invert a GPIO active state.
+ * @details The active state is inverted only if it was either low or high.
+ *          In case it was set to none or any, the value is not modified.
+ *
+ * @param[in] active  Active state to be inverted.
+ *
+ * @return  Inverted active state.
+ */
+#define APAL_GPIO_ACTIVE_INVERT(active) (                                     \
+  (((apalGpioActive_t)active & APAL_GPIO_ACTIVE_LOW) ^                        \
+   ((apalGpioActive_t)active & APAL_GPIO_ACTIVE_HIGH)) ?                      \
+  ((apalGpioActive_t)active ^ APAL_GPIO_ACTIVE_ANY) :                         \
+  ((apalGpioActive_t)active)                                                  \
+)
+
+/**
+ * @brief   Signal direction for the control GPIO.
+ */
+typedef uint8_t apalGpioDirection_t;
+
+/**
+ * @brief   Signal direction for the control GPIO is undefined.
+ */
+#define APAL_GPIO_DIRECTION_UNDEFINED           ((apalGpioDirection_t)0)
+
+/**
+ * @brief   Signal direction for the control GPIO is input only.
+ */
+#define APAL_GPIO_DIRECTION_INPUT               ((apalGpioDirection_t)1)
+
+/**
+ * @brief   Signal direction for the control GPIO is output only.
+ */
+#define APAL_GPIO_DIRECTION_OUTPUT              ((apalGpioDirection_t)2)
+
+/**
+ * @brief   Signal direction for the control GPIO is didirectional.
+ */
+#define APAL_GPIO_DIRECTION_BIDIRECTIONAL       ((apalGpioDirection_t)3)
+
+/**
+ * @brief   Informative or effective signal edge for control GPIOs.
+ */
+typedef uint8_t apalGpioEdge_t;
+
+/**
+ * @brief   No edges indicate an interrupt or trigger an action.
+ */
+#define APAL_GPIO_EDGE_NONE                     ((apalGpioEdge_t)0)
+
+/**
+ * @brief   Rising edges indicate an interrupt or trigger an action.
+ */
+#define APAL_GPIO_EDGE_RISING                   ((apalGpioEdge_t)1)
+
+/**
+ * @brief   Falling edges indicate an interrupt or trigger an action.
+ */
+#define APAL_GPIO_EDGE_FALLING                  ((apalGpioEdge_t)2)
+
+/**
+ * @brief   Both rising and falling edges indicate an interrupt or trigger an action.
+ */
+#define APAL_GPIO_EDGE_BOTH                     ((apalGpioEdge_t)3)
+
+/**
+ * @brief   Inverts the value of the informative or effective signal edge for interrupts.
+ * @details Rising edge is inverted to falling and vice versa.
+ *          If none or both edges are enabled, the identical value is returned.
+ */
+#define APAL_GPIO_EDGE_INVERT(edge) (                                         \
+  (((apalGpioEdge_t)edge & APAL_GPIO_EDGE_RISING) ^                           \
+   ((apalGpioEdge_t)edge & APAL_GPIO_EDGE_FALLING)) ?                         \
+  ((apalGpioEdge_t)edge ^ APAL_GPIO_EDGE_BOTH) :                              \
+  ((apalGpioEdge_t)edge)                                                      \
+)
+
+/**
+ * @brief Control GPIO meta information
+ */
+typedef struct {
+  apalGpioDirection_t direction : 2;  /**< Direction configuration for according signals */
+  apalGpioActive_t active       : 2;  /**< Active state of the GPIO */
+  apalGpioEdge_t edge           : 2;  /**< Edge configuration for according signals */
+} apalGpioMeta_t;
+
+/**
+ * @brief Control GPIO type.
+ */
+typedef struct {
+  apalGpio_t* gpio;     /**< The GPIO to use.                 */
+  apalGpioMeta_t meta;  /**< Meta information about the GPIO. */
+} apalControlGpio_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(apalGpioRead) || defined(__DOXYGEN__)
+  /**
+   * @brief Read the current value of a GPIO pin.
+   *
+   * @param[in]   gpio  GPIO to read.
+   * @param[out]  val   Current value of the GPIO.
+   *
+   * @return The status indicates whether the function call was successful.
+   */
+  apalExitStatus_t apalGpioRead(apalGpio_t* gpio, apalGpioState_t* const val);
+#endif
+
+#if !defined(apalGpioWrite) || defined(__DOXYGEN__)
+  /**
+   * @brief Set the value of a GPIO pin.
+   *
+   * @param[in] gpio  GPIO to write.
+   * @param[in] val   Value to set for the GPIO.
+   *
+   * @return The status indicates whether the function call was successful.
+   */
+  apalExitStatus_t apalGpioWrite(apalGpio_t* gpio, const apalGpioState_t val);
+#endif
+
+#if !defined(apalGpioToggle) || defined(__DOXYGEN__)
+  /**
+   * @brief Toggle the output of a GPIO.
+   *
+   * @param[in] gpio  GPIO to toggle.
+   *
+   * @return The status indicates whether the function call was successful.
+   */
+  apalExitStatus_t apalGpioToggle(apalGpio_t* gpio);
+#endif
+
+#if !defined(apalGpioIsInterruptEnabled) || defined(__DOXYGEN__)
+  /**
+   * @brief Return the interrupt enable status of the GPIO.
+   *
+   * @param[in]   gpio      GPIO to check.
+   * @param[out]  enabled   Flag, indicating whether interrupt is enabled for the GPIO.
+   *
+   * @return The status indicates whether the function call was successful.
+   */
+  apalExitStatus_t apalGpioIsInterruptEnabled(apalGpio_t* gpio, bool* const enabled);
+#endif
+
+#if !defined(apalControlGpioGet) || defined(__DOXYGEN__)
+  /**
+   * @brief Get the current on/off state of a control GPIO.
+   *
+   * @param[in]   gpio  Control GPIO to read.
+   * @param[out]  val   Current activation status of the control GPIO.
+   *
+   * @return The status indicates whether the function call was successful.
+   */
+  apalExitStatus_t apalControlGpioGet(const apalControlGpio_t* const cgpio, apalControlGpioState_t* const val);
+#endif
+
+#if !defined(apalControlGpioSet) || defined(__DOXYGEN__)
+  /**
+   * @brief Turn a control GPIO 'on' or 'off' respectively.
+   *
+   * @param[in] gpio  Control GPIO to set.
+   * @param[in] val   Activation value to set for the control GPIO.
+   *
+   * @return The status indicates whether the function call was successful.
+   */
+  apalExitStatus_t apalControlGpioSet(const apalControlGpio_t* const cgpio, const apalControlGpioState_t val);
+#endif
+
+#if !defined(apalControlGpioSetInterrupt) || defined(__DOXYGEN__)
+  /**
+   * @brief   Enable or disable the interrupt event functionality.
+   *
+   * @param[in] cgpio   Control GPIO to set.
+   * @param[in] enable  Flag, indicating whether the interrupt shall be activated (true) or deactivated (false).
+   *
+   * @return The status indicates whether the function call was successful.
+   */
+  apalExitStatus_t apalControlGpioSetInterrupt(const apalControlGpio_t* const cgpio, const bool enable);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* (AMIROLLD_CFG_GPIO == true) */
+
+/*============================================================================*/
+/* PWM                                                                        */
+/*============================================================================*/
+
+#if (AMIROLLD_CFG_PWM == true) || defined(__DOXYGEN__)
+
+/*
+ * The following type must be defined by the implementation:
+ *
+ * apalPWMDriver_t
+ *   Type to represent a PWM driver object.
+ *   Is only used via pointer by the API.
+ */
+
+/**
+ * @brief PWM channel type.
+ */
+typedef uint8_t   apalPWMchannel_t;
+
+/**
+ * @brief PWM width type.
+ */
+typedef uint16_t  apalPWMwidth_t;
+
+/**
+ * @brief PWM frequency type.
+ */
+typedef uint32_t  apalPWMfrequency_t;
+
+/**
+ * @brief PWM period time.
+ */
+typedef uint32_t  apalPWMperiod_t;
+
+/**
+ * @brief   PWM width to turn off the PWM.
+ */
+#define APAL_PWM_WIDTH_OFF                      ((apalPWMwidth_t)0x0000u)
+
+/**
+ * @brief   Minimum allowed PWM width.
+ */
+#define APAL_PWM_WIDTH_MIN                      ((apalPWMwidth_t)0x0000u)
+
+/**
+ * @brief   Maximum allowed PWM width.
+ */
+#define APAL_PWM_WIDTH_MAX                      ((apalPWMwidth_t)0xFFFFu)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(apalPWMSet) || defined(__DOXYGEN__)
+  /**
+   * @brief   Set the PWM with given parameters.
+   *
+   * @param[in] pwm       PWM driver to set.
+   * @param[in] channel   Channel of the PWM driver to set.
+   * @param[in] width     Width to set the channel to.
+   *
+   * @return  The status indicates whether the function call was successful.
+   */
+  apalExitStatus_t apalPWMSet(apalPWMDriver_t* pwm, const apalPWMchannel_t channel, const apalPWMwidth_t width);
+#endif
+
+#if !defined(apalPWMGetFrequency) || defined(__DOXYGEN__)
+  /**
+   * @brief   Retrieve the current frequency of the PWM.
+   *
+   * @param[in]  pwm        PWM driver to read.
+   * @param[out] frequency  The currently set frequency.
+   *
+   * @return  The status indicates whether the function call was successful.
+   */
+  apalExitStatus_t apalPWMGetFrequency(apalPWMDriver_t* pwm, apalPWMfrequency_t* const frequency);
+#endif
+
+#if !defined(apalPWMGetPeriod) || defined(__DOXYGEN__)
+  /**
+   * @brief   Retrieve the current period of the PWM.
+   *
+   * @param[in]   pwm     PWM driver to read.
+   * @param[out]  period  The currently set period.
+   *
+   * @return  The status indicates whether the function call was successful.
+   */
+  apalExitStatus_t apalPWMGetPeriod(apalPWMDriver_t* pwm, apalPWMperiod_t* const period);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* (AMIROLLD_CFG_PWM == true) */
+
+/*============================================================================*/
+/* QEI                                                                        */
+/*============================================================================*/
+
+#if (AMIROLLD_CFG_QEI == true) || defined(__DOXYGEN__)
+
+/*
+ * The following type must be defined by the implementation:
+ *
+ * apalQEIDriver_t
+ *   Type to represent a QEI driver object.
+ *   Is only used via pointer by the API.
+ */
+
+/**
+ * @brief QEI counter type.
+ */
+typedef uint32_t  apalQEICount_t;
+
+/**
+ * @brief Direction of the QEI.
+ */
+typedef uint8_t apalQEIDirection_t;
+
+/*
+ * @brief   QEI counts upwards.
+ */
+#define APAL_QEI_DIRECTION_UP                   ((apalQEIDirection_t)0)
+
+/*
+ * @brief   QEI counts downwards.
+ */
+#define APAL_QEI_DIRECTION_DOWN                 ((apalQEIDirection_t)1)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(apalQEIGetDirection) || defined(__DOXYGEN__)
+  /**
+   * @brief Gets the direction of the last transition.
+   *
+   * @param[in]   qei         The QEI driver to use.
+   * @param[out]  direction   The direction of the last transition.
+   *
+   * @return The status indicates whether the function call was successful.
+   */
+  apalExitStatus_t apalQEIGetDirection(apalQEIDriver_t* qei, apalQEIDirection_t* const direction);
+#endif
+
+#if !defined(apalQEIGetPosition) || defined(__DOXYGEN__)
+  /**
+   * @brief Gets the current position of the ecnoder.
+   *
+   * @param[in]   qei       The QEI driver to use.
+   * @param[out]  position  The current position of the encoder.
+   *
+   * @return The status indicates whether the function call was successful.
+   */
+  apalExitStatus_t apalQEIGetPosition(apalQEIDriver_t* qei, apalQEICount_t* const position);
+#endif
+
+#if !defined(apalQEIGetRange) || defined(__DOXYGEN__)
+  /**
+   * @brief Gets the value range of the encoder.
+   *
+   * @param[in]   qei     The QEI driver to use.
+   * @param[out]  range   The value range of the encoder.
+   *
+   * @return The status indicates whether the function call was successful.
+   */
+  apalExitStatus_t apalQEIGetRange(apalQEIDriver_t* qei, apalQEICount_t* const range);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* (AMIROLLD_CFG_QEI == true) */
+
+/*============================================================================*/
+/* I2C                                                                        */
+/*============================================================================*/
+
+#if (AMIROLLD_CFG_I2C == true) || defined(__DOXYGEN__)
+
+/*
+ * The following type must be defined by the implementation:
+ *
+ * apalI2CDriver_t
+ *   Type to represent a I2C driver object.
+ *   Is only used via pointer by the API.
+ */
+
+/**
+ * @brief I2C address type.
+ */
+typedef uint16_t apalI2Caddr_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(apalI2CMasterTransmit) || defined(__DOXYGEN__)
+  /**
+   * @brief Transmit data and receive a response.
+   *
+   * @param[in]   i2cd      The I2C driver to use.
+   * @param[in]   addr      Address to write to.
+   * @param[in]   txbuf     Buffer containing data to send.
+   * @param[in]   txbytes   Number of bytes to send.
+   * @param[out]  rxbuf     Buffer to store a response to.
+   * @param[in]   rxbytes   Number of bytes to receive.
+   * @param[in]   timeout   Timeout for the function to return (in microseconds).
+   *
+   * @return The status indicates whether the function call was succesful or a timeout occurred.
+   */
+  apalExitStatus_t apalI2CMasterTransmit(apalI2CDriver_t* i2cd, const apalI2Caddr_t addr, const uint8_t* const txbuf, const size_t txbytes, uint8_t* const rxbuf, const size_t rxbytes, const apalTime_t timeout);
+#endif
+
+#if !defined(apalI2CMasterReceive) || defined(__DOXYGEN__)
+  /**
+   * @brief Read data from a specific address.
+   *
+   * @param[in]   i2cd      The I2C driver to use.
+   * @param[in]   addr      Address to read.
+   * @param[out]  rxbuf     Buffer to store the response to.
+   * @param[in]   rxbytes   Number of bytes to receive.
+   * @param[in]   timeout   Timeout for the function to return (in microseconds).
+   *
+   * @return The status indicates whether the function call was succesful or a timeout occurred.
+   */
+  apalExitStatus_t apalI2CMasterReceive(apalI2CDriver_t* i2cd, const apalI2Caddr_t addr, uint8_t* const rxbuf, const size_t rxbytes, const apalTime_t timeout);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* (AMIROLLD_CFG_I2C == true) */
+
+/*============================================================================*/
+/* SPI                                                                        */
+/*============================================================================*/
+
+#if (AMIROLLD_CFG_SPI == true) || defined(__DOXYGEN__)
+
+/*
+ * The following types must be defined by the implementation:
+ *
+ * apalSPIDriver_t
+ *   Type to represent a SPI driver object.
+ *   Is only used via pointer by the API.
+ *
+ * apalSPIConfig_t
+ *   Type to represent SPI a configuration object.
+ *   Is only used via pointer by the API.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(apalSPITransmit) || defined(__DOXYGEN__)
+  /**
+   * @brief Transmit data to SPI.
+   *
+   * @param[in]   spid      The SPI driver to use.
+   * @param[in]   data      Buffer containing data to send.
+   * @param[in]   length    Number of bytes to send.
+   *
+   * @return The status indicates whether the function call was succesful.
+   */
+  apalExitStatus_t apalSPITransmit(apalSPIDriver_t* spid, const uint8_t* const data, const size_t length);
+#endif
+
+#if !defined(apalSPIReceive) || defined(__DOXYGEN__)
+  /**
+   * @brief Receive data from SPI.
+   *
+   * @param[in]   spid      The SPI driver to use.
+   * @param[out]  data      Buffer to store receied data.
+   * @param[in]   length    Number of bytes to receive.
+   *
+   * @return The status indicates whether the function call was succesful.
+   */
+  apalExitStatus_t apalSPIReceive(apalSPIDriver_t* spid, uint8_t* const data, const size_t length);
+#endif
+
+#if !defined(apalSPITransmitAndReceive) || defined(__DOXYGEN__)
+  /**
+   * @brief Transmit data to SPI and receive data afterwards without releasing the bus in between.
+   *
+   * @param[in]   spid        The SPI driver to use.
+   * @param[in]   txData      Transmit data buffer.
+   * @param[in]   rxData      Receive data buffer.
+   * @param[in]   txLength    Number of bytes to send.
+   * @param[in]   rxLength    Number of bytes to receive.
+   *
+   * @return The status indicates whether the function call was succesful.
+   */
+  apalExitStatus_t apalSPITransmitAndReceive(apalSPIDriver_t* spid, const uint8_t* const txData , uint8_t* const rxData, const size_t txLength, const size_t rxLength);
+#endif
+
+#if !defined(apalSPIExchange) || defined(__DOXYGEN__)
+  /**
+   * @brief Transmit and receive data from SPI simultaneously.
+   *
+   * @param[in]   spid      The SPI driver to use.
+   * @param[in]   txData    Buffer containing data to send.
+   * @param[out]  rxData    Buffer to store received data.
+   * @param[in]   length    Number of bytes to send and receive.
+   *
+   * @return The status indicates whether the function call was succesful.
+   */
+  apalExitStatus_t apalSPIExchange(apalSPIDriver_t* spid, const uint8_t* const txData , uint8_t* const rxData, const size_t length);
+#endif
+
+#if !defined(apalSPIReconfigure) || defined(__DOXYGEN__)
+  /**
+   * @brief Reconfigure an SPI driver.
+   *
+   * @param[in] spid    The SPI driver to be reconfigured.
+   * @param[in] config  Configuration to apply.
+   *
+   * @return The status indicates whether the function call was succesful.
+   */
+  apalExitStatus_t apalSPIReconfigure(apalSPIDriver_t* spid, const apalSPIConfig_t* config);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* (AMIROLLD_CFG_SPI == true) */
+
+#endif /* AMIROOS_PERIPHAL_H */
diff --git a/periphALtypes.h b/periphALtypes.h
deleted file mode 100644
index abc5949..0000000
--- a/periphALtypes.h
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
-AMiRo-LLD is a compilation of low-level hardware drivers for the Autonomous Mini Robot (AMiRo) platform.
-Copyright (C) 2016..2019  Thomas Schöpping et al.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef AMIROLLD_PERIPHALTYPES_H
-#define AMIROLLD_PERIPHALTYPES_H
-
-/*============================================================================*/
-/* DEPENDENCIES                                                               */
-/*============================================================================*/
-
-#include <amiro-lld.h>
-#include <stdint.h>
-
-/*============================================================================*/
-/* GENERAL                                                                    */
-/*============================================================================*/
-
-/**
- * @brief Time measurement type (in microseconds).
- */
-#if !defined(AMIROLLD_CFG_TIME_SIZE)
-  #error "AMIROLLD_CFG_TIME_SIZE not defined in alldconf.h"
-#elif (AMIROLLD_CFG_TIME_SIZE == 8)
-  typedef uint8_t     apalTime_t;
-#elif (AMIROLLD_CFG_TIME_SIZE == 16)
-  typedef uint16_t    apalTime_t;
-#elif (AMIROLLD_CFG_TIME_SIZE == 32)
-  typedef uint32_t    apalTime_t;
-#elif (AMIROLLD_CFG_TIME_SIZE == 64)
-  typedef uint64_t    apalTime_t;
-#else
-  #error "AMIROLLD_CFG_TIME_SIZE must be 8, 16, 32 or 64!"
-#endif
-
-/**
- * @brief Status values used as return value for all (or most) function calls.
- * @note  The status can be used as mask of flags.
- */
-typedef int8_t apalExitStatus_t;
-
-/**
- * @brief   Status value for success (no error or warning occurred).
- */
-#define APAL_STATUS_OK                          ((apalExitStatus_t)0)
-#define APAL_STATUS_SUCCESS                     ((apalExitStatus_t)0)
-
-/**
- * @brief   Status value for unspecified failure.
- */
-#define APAL_STATUS_ERROR                       ((apalExitStatus_t)-1)
-#define APAL_STATUS_FAILURE                     ((apalExitStatus_t)-1)
-
-/**
- * @brief   Status value for timeout failure.
- */
-#define APAL_STATUS_TIMEOUT                     ((apalExitStatus_t)-2)
-
-/**
- * @brief   Status value for failure because of invalid arguments.
- */
-#define APAL_STATUS_INVALIDARGUMENTS            ((apalExitStatus_t)-4)
-
-/**
- * @brief   Status value for failure because the function is not available/implemented.
- */
-#define APAL_STATUS_UNAVAILABLE                 ((apalExitStatus_t)-8)
-
-/**
- * @brief   Status value for unspecified warning.
- */
-#define APAL_STATUS_WARNING                     ((apalExitStatus_t)1)
-
-/*============================================================================*/
-/* GPIO                                                                       */
-/*============================================================================*/
-
-/**
- * @brief   Forward declaration.
- * @details Struct must be defined in 'periphAL.h'.
- */
-typedef struct apalGpio_t apalGpio_t;
-
-/**
- * @brief Status values to read/write a GPIO port.
- */
-typedef uint8_t apalGpioState_t;
-
-/**
- * @brief   GPIO physical low state.
- */
-#define APAL_GPIO_LOW                           ((apalGpioState_t)0)
-
-/**
- * @brief   GPIO physical high state.
- */
-#define APAL_GPIO_HIGH                          ((apalGpioState_t)1)
-
-/**
- * @brief   Invert a physical GPIO state.
- *
- * @param[in] state   GPIO state to invert.
- *
- * @return  Inverted physical GPIO state.
- */
-#define APAL_GPIO_STATE_INVERT(state) (                                       \
-  (apalGpioState_t)state ^ APAL_GPIO_HIGH                                     \
-)
-
-/**
- * @brief Logical status values to turn a control GPIO 'on' and 'off'.
- */
-typedef uint8_t apalControlGpioState_t;
-
-/**
- * @brief   GPIO logical off state.
- */
-#define APAL_GPIO_OFF                           ((apalControlGpioState_t)0)
-
-/**
- * @brief   GPIO logical on state.
- */
-#define APAL_GPIO_ON                            ((apalControlGpioState_t)1)
-
-/**
- * @brief   Polarity state of the control GPIO.
- */
-typedef uint8_t apalGpioActive_t;
-
-/**
- * @brief   The control GPIO is never defined to be 'on' (does not apply).
- */
-#define APAL_GPIO_ACTIVE_NONE                   ((apalGpioActive_t)0)
-
-/**
- * @brief   The control GPIO is defined to be 'on' when it is phsically low.
- */
-#define APAL_GPIO_ACTIVE_LOW                    ((apalGpioActive_t)1)
-
-/**
- * @brief   The control GPIO is defined to be 'on' when it is physically high.
- */
-#define APAL_GPIO_ACTIVE_HIGH                   ((apalGpioActive_t)2)
-
-/**
- * @brief   The control GPIO is defined to be always 'on'.
- */
-#define APAL_GPIO_ACTIVE_ANY                    ((apalGpioActive_t)3)
-
-/**
- * @brief   Invert a GPIO active state.
- * @details The active state is inverted only if it was either low or high.
- *          In case it was set to none or any, the value is not modified.
- *
- * @param[in] active  Active state to be inverted.
- *
- * @return  Inverted active state.
- */
-#define APAL_GPIO_ACTIVE_INVERT(active) (                                     \
-  (((apalGpioActive_t)active & APAL_GPIO_ACTIVE_LOW) ^                        \
-   ((apalGpioActive_t)active & APAL_GPIO_ACTIVE_HIGH)) ?                      \
-  ((apalGpioActive_t)active ^ APAL_GPIO_ACTIVE_ANY) :                         \
-  ((apalGpioActive_t)active)                                                  \
-)
-
-/**
- * @brief   Signal direction for the control GPIO.
- */
-typedef uint8_t apalGpioDirection_t;
-
-/**
- * @brief   Signal direction for the control GPIO is undefined.
- */
-#define APAL_GPIO_DIRECTION_UNDEFINED           ((apalGpioDirection_t)0)
-
-/**
- * @brief   Signal direction for the control GPIO is input only.
- */
-#define APAL_GPIO_DIRECTION_INPUT               ((apalGpioDirection_t)1)
-
-/**
- * @brief   Signal direction for the control GPIO is output only.
- */
-#define APAL_GPIO_DIRECTION_OUTPUT              ((apalGpioDirection_t)2)
-
-/**
- * @brief   Signal direction for the control GPIO is didirectional.
- */
-#define APAL_GPIO_DIRECTION_BIDIRECTIONAL       ((apalGpioDirection_t)3)
-
-/**
- * @brief   Informative or effective signal edge for control GPIOs.
- */
-typedef uint8_t apalGpioEdge_t;
-
-/**
- * @brief   No edges indicate an interrupt or trigger an action.
- */
-#define APAL_GPIO_EDGE_NONE                     ((apalGpioEdge_t)0)
-
-/**
- * @brief   Rising edges indicate an interrupt or trigger an action.
- */
-#define APAL_GPIO_EDGE_RISING                   ((apalGpioEdge_t)1)
-
-/**
- * @brief   Falling edges indicate an interrupt or trigger an action.
- */
-#define APAL_GPIO_EDGE_FALLING                  ((apalGpioEdge_t)2)
-
-/**
- * @brief   Both rising and falling edges indicate an interrupt or trigger an action.
- */
-#define APAL_GPIO_EDGE_BOTH                     ((apalGpioEdge_t)3)
-
-/**
- * @brief   Inverts the value of the informative or effective signal edge for interrupts.
- * @details Rising edge is inverted to falling and vice versa.
- *          If none or both edges are enabled, the identical value is returned.
- */
-#define APAL_GPIO_EDGE_INVERT(edge) (                                         \
-  (((apalGpioEdge_t)edge & APAL_GPIO_EDGE_RISING) ^                           \
-   ((apalGpioEdge_t)edge & APAL_GPIO_EDGE_FALLING)) ?                         \
-  ((apalGpioEdge_t)edge ^ APAL_GPIO_EDGE_BOTH) :                              \
-  ((apalGpioEdge_t)edge)                                                      \
-)
-
-/**
- * @brief Control GPIO meta information
- */
-typedef struct {
-  apalGpioDirection_t direction : 2;  /**< Direction configuration for according signals */
-  apalGpioActive_t active       : 2;  /**< Active state of the GPIO */
-  apalGpioEdge_t edge           : 2;  /**< Edge configuration for according signals */
-} apalGpioMeta_t;
-
-/**
- * @brief Control GPIO type.
- */
-typedef struct {
-  apalGpio_t* gpio;     /**< The GPIO to use.                 */
-  apalGpioMeta_t meta;  /**< Meta information about the GPIO. */
-} apalControlGpio_t;
-
-/*============================================================================*/
-/* PWM                                                                        */
-/*============================================================================*/
-
-/**
- * @brief PWM channel type.
- */
-typedef uint8_t   apalPWMchannel_t;
-
-/**
- * @brief PWM width type.
- */
-typedef uint16_t  apalPWMwidth_t;
-
-/**
- * @brief PWM frequency type.
- */
-typedef uint32_t  apalPWMfrequency_t;
-
-/**
- * @brief PWM period time.
- */
-typedef uint32_t  apalPWMperiod_t;
-
-/**
- * @brief   PWM width to turn off the PWM.
- */
-#define APAL_PWM_WIDTH_OFF                      ((apalPWMwidth_t)0x0000u)
-
-/**
- * @brief   Minimum allowed PWM width.
- */
-#define APAL_PWM_WIDTH_MIN                      ((apalPWMwidth_t)0x0000u)
-
-/**
- * @brief   Maximum allowed PWM width.
- */
-#define APAL_PWM_WIDTH_MAX                      ((apalPWMwidth_t)0xFFFFu)
-
-/*============================================================================*/
-/* QEI                                                                        */
-/*============================================================================*/
-
-/**
- * @brief QEI counter type.
- */
-typedef uint32_t  apalQEICount_t;
-
-/**
- * @brief Direction of the QEI.
- */
-typedef uint8_t apalQEIDirection_t;
-
-/*
- * @brief   QEI counts upwards.
- */
-#define APAL_QEI_DIRECTION_UP                   ((apalQEIDirection_t)0)
-
-/*
- * @brief   QEI counts downwards.
- */
-#define APAL_QEI_DIRECTION_DOWN                 ((apalQEIDirection_t)1)
-
-/*============================================================================*/
-/* I2C                                                                        */
-/*============================================================================*/
-
-/**
- * @brief I2C address type.
- */
-typedef uint16_t apalI2Caddr_t;
-
-/*============================================================================*/
-/* SPI                                                                        */
-/*============================================================================*/
-
-/* nothing defined for SPI */
-
-#endif /* AMIROLLD_PERIPHALTYPES_H */
diff --git a/templates/alldconf.h b/templates/alldconf.h
index cf9e19d..8ba340f 100644
--- a/templates/alldconf.h
+++ b/templates/alldconf.h
@@ -19,12 +19,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #ifndef ALLDCONF_H
 #define ALLDCONF_H
 
-/*
- * compatibility guards
- */
 #define _AMIRO_LLD_CFG_
 #define AMIRO_LLD_CFG_VERSION_MAJOR         1
-#define AMIRO_LLD_CFG_VERSION_MINOR         0
+#define AMIRO_LLD_CFG_VERSION_MINOR         1
 
 /**
  * @brief   Width of the apalTime_t data type.
@@ -32,6 +29,41 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
  * @details Possible values are 8, 16, 32, and 64 bits.
  *          By definition time is represented ot a microsecond precision.
  */
-#define AMIROLLD_CFG_TIME_SIZE          32
+#define AMIROLLD_CFG_TIME_SIZE                  32
+
+/**
+ * @brief   Flag to enable/disable DBG API.
+ */
+#define AMIROLLD_CFG_DBG                        true
+
+/**
+ * @brief   Flag to enable/disable GPIO API.
+ */
+#define AMIROLLD_CFG_GPIO                       true
+
+/**
+ * @brief   Flag to enable/disable PWM API.
+ */
+#define AMIROLLD_CFG_PWM                        true
+
+/**
+ * @brief   Flag to enable/disable QEI API.
+ */
+#define AMIROLLD_CFG_QEI                        true
+
+/**
+ * @brief   Flag to enable/disable I2C API.
+ */
+#define AMIROLLD_CFG_I2C                        true
+
+/**
+ * @brief   Flag to enable/disable SPI API.
+ */
+#define AMIROLLD_CFG_SPI                        true
+
+/**
+ * @brief   Hook macro to insert a custom header to periphAL.h file.
+ */
+#define AMIROLLD_CFG_PERIPHAL_HEADER            <custom_periphAL.h>
 
 #endif /* ALLDCONF_H */
diff --git a/templates/periphAL.h b/templates/periphAL.h
deleted file mode 100644
index 18f7197..0000000
--- a/templates/periphAL.h
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
-AMiRo-LLD is a compilation of low-level hardware drivers for the Autonomous Mini Robot (AMiRo) platform.
-Copyright (C) 2016..2019  Thomas Schöpping et al.
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef AMIROLLD_PERIPHAL_H
-#define AMIROLLD_PERIPHAL_H
-
-#include <amiro-lld.h>
-
-/*============================================================================*/
-/* VERSION                                                                    */
-/*============================================================================*/
-
-/**
- * @brief   The periphery abstraction layer interface major version.
- * @note    Changes of the major version imply incompatibilities.
- */
-#define PERIPHAL_VERSION_MAJOR    1
-
-/**
- * @brief   The periphery abstraction layer interface minor version.
- * @note    A higher minor version implies new functionalty, but all old interfaces are still available.
- */
-#define PERIPHAL_VERSION_MINOR    1
-
-/*============================================================================*/
-/* DEPENDENCIES                                                               */
-/*============================================================================*/
-
-/*============================================================================*/
-/* GENERAL                                                                    */
-/*============================================================================*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @brief Delay execution by a specific number of microseconds.
- *
- * @param[in]   us    Time to sleep until execution continues in microseconds.
- */
-void apalSleep(apalTime_t us);
-
-#ifdef __cplusplus
-}
-#endif
-
-/*============================================================================*/
-/* GPIO                                                                       */
-/*============================================================================*/
-
-typedef osGpio_t apalGpio_t;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @brief Read the current value of a GPIO pin.
- *
- * @param[in]   gpio  GPIO to read.
- * @param[out]  val   Current value of the GPIO.
- *
- * @return The status indicates whether the function call was successful.
- */
-apalExitStatus_t apalGpioRead(apalGpio_t* gpio, apalGpioState_t* const val);
-
-/**
- * @brief Set the value of a GPIO pin.
- *
- * @param[in] gpio  GPIO to write.
- * @param[in] val   Value to set for the GPIO.
- *
- * @return The status indicates whether the function call was successful.
- */
-apalExitStatus_t apalGpioWrite(apalGpio_t* gpio, const apalGpioState_t val);
-
-/**
- * @brief Toggle the output of a GPIO.
- *
- * @param[in] gpio  GPIO to toggle.
- *
- * @return The status indicates whether the function call was successful.
- */
-apalExitStatus_t apalGpioToggle(apalGpio_t* gpio);
-
-/**
- * @brief Return the interrupt enable status of the GPIO.
- *
- * @param[in]   gpio      GPIO to check.
- * @param[out]  enabled   Flag, indicating whether interrupt is enabled for the GPIO.
- *
- * @return The status indicates whether the function call was successful.
- */
-static inline apalExitStatus_t apalGpioIsInterruptEnabled(apalGpio_t* gpio, bool* const enabled)
-
-/**
- * @brief Get the current on/off state of a control GPIO.
- *
- * @param[in]   gpio  Control GPIO to read.
- * @param[out]  val   Current activation status of the control GPIO.
- *
- * @return The status indicates whether the function call was successful.
- */
-apalExitStatus_t apalControlGpioGet(const apalControlGpio_t* const cgpio, apalControlGpioState_t* const val);
-
-/**
- * @brief Turn a control GPIO 'on' or 'off' respectively.
- *
- * @param[in] gpio  Control GPIO to set.
- * @param[in] val   Activation value to set for the control GPIO.
- *
- * @return The status indicates whether the function call was successful.
- */
-apalExitStatus_t apalControlGpioSet(const apalControlGpio_t* const cgpio, const apalControlGpioState_t val);
-
-/**
- * @brief   Enable or disable the interrupt event functionality.
- *
- * @param[in] cgpio   Control GPIO to set.
- * @param[in] enable  Flag, indicating whether the interrupt shall be activated (true) or deactivated (false).
- *
- * @return The status indicates whether the function call was successful.
- */
-apalExitStatus_t apalControlGpioSetInterrupt(apalControlGpio_t* const cgpio, const bool enable);
-
-#ifdef __cplusplus
-}
-#endif
-
-/*============================================================================*/
-/* PWM                                                                        */
-/*============================================================================*/
-
-/**
- * @brief PWM driver type.
- */
-typedef osPWMDriver_t apalPWMDriver_t;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @brief   Set the PWM with given parameters.
- *
- * @param[in] pwm       PWM driver to set.
- * @param[in] channel   Channel of the PWM driver to set.
- * @param[in] width     Width to set the channel to.
- *
- * @return  The status indicates whether the function call was successful.
- */
-apalExitStatus_t apalPWMSet(apalPWMDriver_t* pwm, const apalPWMchannel_t channel, const apalPWMwidth_t width);
-
-/**
- * @brief   Retrieve the current frequency of the PWM.
- *
- * @param[in]  pwm        PWM driver to read.
- * @param[out] frequency  The currently set frequency.
- *
- * @return  The status indicates whether the function call was successful.
- */
-apalExitStatus_t apalPWMGetFrequency(apalPWMDriver_t* pwm, apalPWMfrequency_t* const frequency);
-
-/**
- * @brief   Retrieve the current period of the PWM.
- *
- * @param[in]   pwm     PWM driver to read.
- * @param[out]  period  The currently set period.
- *
- * @return  The status indicates whether the function call was successful.
- */
-apalExitStatus_t apalPWMGetPeriod(apalPWMDriver_t* pwm, apalPWMperiod_t* const period);
-
-#ifdef __cplusplus
-}
-#endif
-
-/*============================================================================*/
-/* QEI                                                                        */
-/*============================================================================*/
-
-/**
- * @brief QEI driver type.
- */
-typedef osQEIDriver_t apaQEIDriver_t;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @brief Gets the direction of the last transition.
- *
- * @param[in]   qei         The QEI driver to use.
- * @param[out]  direction   The direction of the last transition.
- *
- * @return The status indicates whether the function call was successful.
- */
-apalExitStatus_t apalQEIGetDirection(apalQEIDriver_t* qei, apalQEIDirection_t* const direction);
-
-/**
- * @brief Gets the current position of the ecnoder.
- *
- * @param[in]   qei       The QEI driver to use.
- * @param[out]  position  The current position of the encoder.
- *
- * @return The status indicates whether the function call was successful.
- */
-apalExitStatus_t apalQEIGetPosition(apalQEIDriver_t* qei, apalQEICount_t* const position);
-
-/**
- * @brief Gets the value range of the encoder.
- *
- * @param[in]   qei     The QEI driver to use.
- * @param[out]  range   The value range of the encoder.
- *
- * @return The status indicates whether the function call was successful.
- */
-apalExitStatus_t apalQEIGetRange(apalQEIDriver_t* qei, apalQEICount_t* const range);
-
-#ifdef __cplusplus
-}
-#endif
-
-/*============================================================================*/
-/* I2C                                                                        */
-/*============================================================================*/
-
-/**
- * @brief I2C driver type.
- */
-typedef osI2CDriver_t apalI2CDriver_t;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @brief Transmit data and receive a response.
- *
- * @param[in]   i2cd      The I2C driver to use.
- * @param[in]   addr      Address to write to.
- * @param[in]   txbuf     Buffer containing data to send.
- * @param[in]   txbytes   Number of bytes to send.
- * @param[out]  rxbuf     Buffer to store a response to.
- * @param[in]   rxbytes   Number of bytes to receive.
- * @param[in]   timeout   Timeout for the function to return (in microseconds).
- *
- * @return The status indicates whether the function call was succesful or a timeout occurred.
- */
-apalExitStatus_t apalI2CMasterTransmit(apalI2CDriver_t* i2cd, const apalI2Caddr_t addr, const uint8_t* const txbuf, const size_t txbytes, uint8_t* const rxbuf, const size_t rxbytes, const apalTime_t timeout);
-
-/**
- * @brief Read data from a specific address.
- *
- * @param[in]   i2cd      The I2C driver to use.
- * @param[in]   addr      Address to read.
- * @param[out]  rxbuf     Buffer to store the response to.
- * @param[in]   rxbytes   Number of bytes to receive.
- * @param[in]   timeout   Timeout for the function to return (in microseconds).
- *
- * @return The status indicates whether the function call was succesful or a timeout occurred.
- */
-apalExitStatus_t apalI2CMasterReceive(apalI2CDriver_t* i2cd, const apalI2Caddr_t addr, uint8_t* const rxbuf, const size_t rxbytes, const apalTime_t timeout);
-
-#ifdef __cplusplus
-}
-#endif
-
-/*============================================================================*/
-/* SPI                                                                        */
-/*============================================================================*/
-
-/**
- * @brief SPI driver type.
- */
-typedef osSPIDriver_t apalSPIDriver_t;
-
-/**
- * @brief SPI confguration type.
- */
-typedef osSPIConfig apalSPIConfig_t;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @brief Reconfigure an SPI driver.
- *
- * @param[in] spid    The SPI driver to be reconfigured.
- * @param[in] config  Configuration to apply.
- *
- * @return The status indicates whether the function call was succesful.
- */
-static inline apalExitStatus_t apalSPIReconfigure(apalSPIDriver_t* spid, const apalSPIConfig_t* config);
-
-/**
- * @brief Transmit and receive data from SPI
- *
- * @param[in]   spid      The SPI driver to use.
- * @param[in]   txData    Buffer containing data to send.
- * @param[out]  rxData    Buffer to store.
- * @param[in]   length    Number of bytes to send.
- *
- * @return The status indicates whether the function call was succesful.
- */
-apalExitStatus_t apalSPIExchange(apalSPIDriver_t* spid, const uint8_t* const txData , uint8_t* const rxData, const size_t length);
-
-/**
- * @brief Receive data from SPI
- *
- * @param[in]   spid      The SPI driver to use.
- * @param[out]  data      Buffer to store.
- * @param[in]   length    Number of bytes to send.
- *
- * @return The status indicates whether the function call was succesful.
- */
-apalExitStatus_t apalSPIReceive(apalSPIDriver_t* spid, uint8_t* const data, const size_t length);
-
-/**
- * @brief Transmit data to SPI
- *
- * @param[in]   spid      The SPI driver to use.
- * @param[in]   data      Buffer containing data to send.
- * @param[in]   length    Number of bytes to send.
- *
- * @return The status indicates whether the function call was succesful.
- */
-apalExitStatus_t apalSPITransmit(apalSPIDriver_t* spid, const uint8_t* const data, const size_t length);
-
-/**
- * @brief Transmit data to SPI and receive data afterwards without releasing the bus in between.
- *
- * @param[in]   spid        The SPI driver to use.
- * @param[in]   txData      Transmit data buffer.
- * @param[in]   rxData      Receive data buffer.
- * @param[in]   txLength    Number of bytes to send.
- * @param[in]   rxLength    Number of bytes to receive.
- *
- * @return The status indicates whether the function call was succesful.
- */
-static inline apalExitStatus_t apalSPITransmitAndReceive(apalSPIDriver_t* spid, const uint8_t* const txData , uint8_t* const rxData, const size_t txLength, const size_t rxLength);
-
-#ifdef __cplusplus
-}
-#endif
-
-/*============================================================================*/
-/* DEBUG                                                                      */
-/*============================================================================*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @brief Assert function to check a given condition.
- * @note  Using a macro is preferable.
- *
- * @param[in] c   The condition to check.
- */
-void apalDbgAssert(bool c);
-
-/**
- * @brief Printf function for messages printed only in debug builds.
- *
- * @param[in] fmt   Formatted string to print.
- */
-void apalDbgPrintf(fmt, ...);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AMIROOS_PERIPHAL_H */
-
