commit bffb3465f93e69701c9b64dfa833cf7b0a55e690
Author: Thomas Schöpping <tschoepp@cit-ec.uni-bielefeld.de>
Date:   Mon Jan 14 11:15:20 2019 +0100

    Added new periphery hardware (PCAL6524 GPIO extender and AT42QT1050 touch sensor) to the PowerManagement, including unit tests.

diff --git a/modules/PowerManagement_1-1/alldconf.h b/modules/PowerManagement_1-1/alldconf.h
index e233dff..e54b22f 100644
--- a/modules/PowerManagement_1-1/alldconf.h
+++ b/modules/PowerManagement_1-1/alldconf.h
@@ -106,11 +106,31 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #endif /* BOARD_SENSORRING == BOARD_PROXIMITYSENSOR */
 
 #if (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L0X) || defined(__DOXYGEN__)
-// TODO
+
+/**
+ * @brief   Enable flag for the PCAL6524 GPIO extender
+ */
+#define AMIROLLD_CFG_USE_PCAL6524
+
+/**
+ * @brief   Enable flag for the AT42Q1050 touch sensor.
+ */
+#define AMIROLLD_CFG_USE_AT42QT1050
+
 #endif /* BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L0X */
 
 #if (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L1X) || defined(__DOXYGEN__)
-// TODO
+
+/**
+ * @brief   Enable flag for the PCAL6524 GPIO extender
+ */
+#define AMIROLLD_CFG_USE_PCAL6524
+
+/**
+ * @brief   Enable flag for the AT42Q1050 touch sensor.
+ */
+#define AMIROLLD_CFG_USE_AT42QT1050
+
 #endif /* BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L1X */
 
 #endif /* _ALLDCONF_H_ */
diff --git a/modules/PowerManagement_1-1/module.c b/modules/PowerManagement_1-1/module.c
index 1cb6894..11fa65f 100644
--- a/modules/PowerManagement_1-1/module.c
+++ b/modules/PowerManagement_1-1/module.c
@@ -153,11 +153,11 @@ ROMCONST apalControlGpio_t moduleGpioIrInt1 = {
     /* active state   */ (VCNL4020_LLD_INT_EDGE == APAL_GPIO_EDGE_RISING) ? APAL_GPIO_ACTIVE_HIGH : APAL_GPIO_ACTIVE_LOW,
     /* interrupt edge */ VCNL4020_LLD_INT_EDGE,
 #elif (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L0X)
-    /* active state   */ APAL_GPIO_ACTIVE_LOW,
-    /* interrupt edge */ APAL_GPIO_EDGE_NONE,
+    /* active state   */ (PCAL6524_LLD_INT_EDGE == APAL_GPIO_EDGE_RISING) ? APAL_GPIO_ACTIVE_HIGH : APAL_GPIO_ACTIVE_LOW,
+    /* interrupt edge */ PCAL6524_LLD_INT_EDGE,
 #elif (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L1X)
-    /* active state   */ APAL_GPIO_ACTIVE_LOW,
-    /* interrupt edge */ APAL_GPIO_EDGE_NONE,
+    /* active state   */ (PCAL6524_LLD_INT_EDGE == APAL_GPIO_EDGE_RISING) ? APAL_GPIO_ACTIVE_HIGH : APAL_GPIO_ACTIVE_LOW,
+    /* interrupt edge */ PCAL6524_LLD_INT_EDGE,
 #else
     /* active state   */ APAL_GPIO_ACTIVE_LOW,
     /* interrupt edge */ APAL_GPIO_EDGE_NONE,
@@ -356,11 +356,11 @@ ROMCONST apalControlGpio_t moduleGpioIrInt2 = {
     /* active state   */ (VCNL4020_LLD_INT_EDGE == APAL_GPIO_EDGE_RISING) ? APAL_GPIO_ACTIVE_HIGH : APAL_GPIO_ACTIVE_LOW,
     /* interrupt edge */ VCNL4020_LLD_INT_EDGE,
 #elif (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L0X)
-    /* active state   */ APAL_GPIO_ACTIVE_LOW,
-    /* interrupt edge */ APAL_GPIO_EDGE_NONE,
+    /* active state   */ (PCAL6524_LLD_INT_EDGE == APAL_GPIO_EDGE_RISING) ? APAL_GPIO_ACTIVE_HIGH : APAL_GPIO_ACTIVE_LOW,
+    /* interrupt edge */ PCAL6524_LLD_INT_EDGE,
 #elif (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L1X)
-    /* active state   */ APAL_GPIO_ACTIVE_LOW,
-    /* interrupt edge */ APAL_GPIO_EDGE_NONE,
+    /* active state   */ (PCAL6524_LLD_INT_EDGE == APAL_GPIO_EDGE_RISING) ? APAL_GPIO_ACTIVE_HIGH : APAL_GPIO_ACTIVE_LOW,
+    /* interrupt edge */ PCAL6524_LLD_INT_EDGE,
 #else
     /* active state   */ APAL_GPIO_ACTIVE_LOW,
     /* interrupt edge */ APAL_GPIO_EDGE_NONE,
@@ -383,11 +383,11 @@ ROMCONST apalControlGpio_t moduleGpioTouchInt = {
     /* active state   */ (MPR121_LLD_INT_EDGE == APAL_GPIO_EDGE_RISING) ? APAL_GPIO_ACTIVE_HIGH : APAL_GPIO_ACTIVE_LOW,
     /* interrupt edge */ MPR121_LLD_INT_EDGE,
 #elif (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L0X)
-    /* active state   */ APAL_GPIO_ACTIVE_LOW,
-    /* interrupt edge */ APAL_GPIO_EDGE_NONE,
+    /* active state   */ (AT42QT1050_LLD_INT_EDGE == APAL_GPIO_EDGE_RISING) ? APAL_GPIO_ACTIVE_HIGH : APAL_GPIO_ACTIVE_LOW,
+    /* interrupt edge */ AT42QT1050_LLD_INT_EDGE,
 #elif (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L1X)
-    /* active state   */ APAL_GPIO_ACTIVE_LOW,
-    /* interrupt edge */ APAL_GPIO_EDGE_NONE,
+    /* active state   */ (AT42QT1050_LLD_INT_EDGE == APAL_GPIO_EDGE_RISING) ? APAL_GPIO_ACTIVE_HIGH : APAL_GPIO_ACTIVE_LOW,
+    /* interrupt edge */ AT42QT1050_LLD_INT_EDGE,
 #else
     /* active state   */ APAL_GPIO_ACTIVE_LOW,
     /* interrupt edge */ APAL_GPIO_EDGE_NONE,
@@ -667,11 +667,41 @@ VCNL4020Driver moduleLldProximity2 = {
 #endif /* BOARD_SENSORRING == BOARD_PROXIMITYSENSOR */
 
 #if (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L0X) || defined(__DOXYGEN__)
-// TODO
+
+PCAL6524Driver moduleLldGpioExtender1 = {
+  /* I²C driver   */ &MODULE_HAL_I2C_SR_PM18_PM33_GAUGEREAR,
+  /* I²C address  */ PCAL6524_LLD_I2C_ADDR_VDD,
+};
+
+PCAL6524Driver moduleLldGpioExtender2 = {
+  /* I²C driver   */ &MODULE_HAL_I2C_SR_PM42_PM50_PMVDD_EEPROM_GAUGEFRONT,
+  /* I²C address  */ PCAL6524_LLD_I2C_ADDR_VDD,
+};
+
+AT42QT1050Driver moduleLldTouch = {
+  /* I²C driver   */ &MODULE_HAL_I2C_SR_PM42_PM50_PMVDD_EEPROM_GAUGEFRONT,
+  /* I²C address  */ AT42QT1050_LLD_I2C_ADDRSEL_LOW,
+};
+
 #endif /* BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L0X */
 
 #if (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L1X) || defined(__DOXYGEN__)
-// TODO
+
+PCAL6524Driver moduleLldGpioExtender1 = {
+  /* I²C driver   */ &MODULE_HAL_I2C_SR_PM18_PM33_GAUGEREAR,
+  /* I²C address  */ PCAL6524_LLD_I2C_ADDR_VDD,
+};
+
+PCAL6524Driver moduleLldGpioExtender2 = {
+  /* I²C driver   */ &MODULE_HAL_I2C_SR_PM42_PM50_PMVDD_EEPROM_GAUGEFRONT,
+  /* I²C address  */ PCAL6524_LLD_I2C_ADDR_VDD,
+};
+
+AT42QT1050Driver moduleLldTouch = {
+  /* I²C driver   */ &MODULE_HAL_I2C_SR_PM42_PM50_PMVDD_EEPROM_GAUGEFRONT,
+  /* I²C address  */ AT42QT1050_LLD_I2C_ADDRSEL_LOW,
+};
+
 #endif /* BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L1X */
 
 /** @} */
@@ -1290,11 +1320,157 @@ aos_unittest_t moduleUtAlldVcnl4020 = {
 #endif /* BOARD_SENSORRING == BOARD_PROXIMITYSENSOR */
 
 #if (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L0X) || defined(__DOXYGEN__)
-// TODO
+
+/*
+ * PCAL6524 (GPIO extender)
+ */
+static int _utShellCmdCb_AlldPcal6524(BaseSequentialStream* stream, int argc, char* argv[])
+{
+  // evaluate arguments
+  if (argc == 2) {
+    if (strcmp(argv[1], "#1") == 0) {
+      ((ut_pcal6524data_t*)moduleUtAlldPcal6524.data)->pcal6524d = &moduleLldGpioExtender1;
+      aosUtRun(stream, &moduleUtAlldPcal6524, "I2C bus #1");
+      ((ut_pcal6524data_t*)moduleUtAlldPcal6524.data)->pcal6524d = NULL;
+      return AOS_OK;
+    }
+    else if (strcmp(argv[1], "#2") == 0) {
+      ((ut_pcal6524data_t*)moduleUtAlldPcal6524.data)->pcal6524d = &moduleLldGpioExtender2;
+      aosUtRun(stream, &moduleUtAlldPcal6524, "I2C bus #2");
+      ((ut_pcal6524data_t*)moduleUtAlldPcal6524.data)->pcal6524d = NULL;
+      return AOS_OK;
+    }
+  }
+  // print help
+  chprintf(stream, "Usage: %s OPTION\n", argv[0]);
+  chprintf(stream, "Options:\n");
+  chprintf(stream, "  #1\n");
+  chprintf(stream, "    Test the GPIO extender on the I2C bus #1.\n");
+  chprintf(stream, "  #2\n");
+  chprintf(stream, "    Test the GPIO extender on the I2C bus #2.\n");
+  return AOS_INVALID_ARGUMENTS;
+}
+static ut_pcal6524data_t _utAlldPcal6524Data = {
+  /* driver   */ NULL,
+  /* timeout  */ MICROSECONDS_PER_SECOND,
+};
+aos_unittest_t moduleUtAlldPcal6524 = {
+  /* name           */ "PCAL6524",
+  /* info           */ "GPIO extender",
+  /* test function  */ utAlldPcal6524Func,
+  /* shell command  */ {
+    /* name     */ "unittest:GPIOExtender",
+    /* callback */ _utShellCmdCb_AlldPcal6524,
+    /* next     */ NULL,
+  },
+  /* data           */ &_utAlldPcal6524Data,
+};
+
+/*
+ * AT42QT1050 (touch sensor)
+ */
+static int _utShellCmdCb_AlldAt42qt1050(BaseSequentialStream* stream, int argc, char* argv[])
+{
+  (void)argc;
+  (void)argv;
+  aosUtRun(stream, &moduleUtAlldAt42qt1050, NULL);
+  return AOS_OK;
+}
+static ut_at42qt1050data_t _utAlldMpr121Data= {
+  /* AT42QT1050 driver  */ &moduleLldTouch,
+  /* timeout            */ MICROSECONDS_PER_SECOND,
+  /* event source       */ &aos.events.io,
+  /* event flags        */ MODULE_OS_IOEVENTFLAGS_TOUCHINT,
+};
+aos_unittest_t moduleUtAlldAt42qt1050 = {
+  /* name           */ "AT42QT1050",
+  /* info           */ "touch sensor",
+  /* test function  */ utAlldAt42qt1050Func,
+  /* shell command  */ {
+    /* name     */ "unittest:Touch",
+    /* callback */ _utShellCmdCb_AlldAt42qt1050,
+    /* next     */ NULL,
+  },
+  /* data           */ &_utAlldMpr121Data,
+};
+
 #endif /* BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L0X */
 
 #if (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L1X) || defined(__DOXYGEN__)
-// TODO
+
+/*
+ * PCAL6524 (GPIO extender)
+ */
+static int _utShellCmdCb_AlldPcal6524(BaseSequentialStream* stream, int argc, char* argv[])
+{
+  // evaluate arguments
+  if (argc == 2) {
+    if (strcmp(argv[1], "#1") == 0) {
+      ((ut_pcal6524data_t*)moduleUtAlldPcal6524.data)->pcal6524d = &moduleLldGpioExtender1;
+      aosUtRun(stream, &moduleUtAlldPcal6524, "I2C bus #1");
+      ((ut_pcal6524data_t*)moduleUtAlldPcal6524.data)->pcal6524d = NULL;
+      return AOS_OK;
+    }
+    else if (strcmp(argv[1], "#2") == 0) {
+      ((ut_pcal6524data_t*)moduleUtAlldPcal6524.data)->pcal6524d = &moduleLldGpioExtender2;
+      aosUtRun(stream, &moduleUtAlldPcal6524, "I2C bus #2");
+      ((ut_pcal6524data_t*)moduleUtAlldPcal6524.data)->pcal6524d = NULL;
+      return AOS_OK;
+    }
+  }
+  // print help
+  chprintf(stream, "Usage: %s OPTION\n", argv[0]);
+  chprintf(stream, "Options:\n");
+  chprintf(stream, "  #1\n");
+  chprintf(stream, "    Test the GPIO extender on the I2C bus #1.\n");
+  chprintf(stream, "  #2\n");
+  chprintf(stream, "    Test the GPIO extender on the I2C bus #2.\n");
+  return AOS_INVALID_ARGUMENTS;
+}
+static ut_pcal6524data_t _utAlldPcal6524Data = {
+  /* driver   */ NULL,
+  /* timeout  */ MICROSECONDS_PER_SECOND,
+};
+aos_unittest_t moduleUtAlldPcal6524 = {
+  /* name           */ "PCAL6524",
+  /* info           */ "GPIO extender",
+  /* test function  */ utAlldPcal6524Func,
+  /* shell command  */ {
+    /* name     */ "unittest:GPIOExtender",
+    /* callback */ _utShellCmdCb_AlldPcal6524,
+    /* next     */ NULL,
+  },
+  /* data           */ &_utAlldPcal6524Data,
+};
+
+/*
+ * AT42QT1050 (touch sensor)
+ */
+static int _utShellCmdCb_AlldAt42qt1050(BaseSequentialStream* stream, int argc, char* argv[])
+{
+  (void)argc;
+  (void)argv;
+  aosUtRun(stream, &moduleUtAlldAt42qt1050, NULL);
+  return AOS_OK;
+}
+static ut_at42qt1050data_t _utAlldMpr121Data= {
+  /* AT42QT1050 driver  */ &moduleLldTouch,
+  /* timeout            */ MICROSECONDS_PER_SECOND,
+  /* event source       */ &aos.events.io,
+  /* event flags        */ MODULE_OS_IOEVENTFLAGS_TOUCHINT,
+};
+aos_unittest_t moduleUtAlldAt42qt1050 = {
+  /* name           */ "AT42QT1050",
+  /* info           */ "touch sensor",
+  /* test function  */ utAlldAt42qt1050Func,
+  /* shell command  */ {
+    /* name     */ "unittest:Touch",
+    /* callback */ _utShellCmdCb_AlldAt42qt1050,
+    /* next     */ NULL,
+  },
+  /* data           */ &_utAlldMpr121Data,
+};
+
 #endif /* BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L1X */
 
 #endif /* AMIROOS_CFG_TESTS_ENABLE == true */
diff --git a/modules/PowerManagement_1-1/module.h b/modules/PowerManagement_1-1/module.h
index 4e858e1..209474f 100644
--- a/modules/PowerManagement_1-1/module.h
+++ b/modules/PowerManagement_1-1/module.h
@@ -453,11 +453,13 @@ extern ROMCONST char* moduleShellPrompt;
   }
 #elif (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L0X) || defined(__DOXYGEN__)
   #define MODULE_INIT_TEST_SENSORRING() {                                     \
-    /* TODO */                                                                \
+    aosShellAddCommand(&aos.shell, &moduleUtAlldPcal6524.shellcmd);           \
+    aosShellAddCommand(&aos.shell, &moduleUtAlldAt42qt1050.shellcmd);         \
   }
 #elif (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L1X) || defined(__DOXYGEN__)
   #define MODULE_INIT_TEST_SENSORRING() {                                     \
-    /* TODO */                                                                \
+    aosShellAddCommand(&aos.shell, &moduleUtAlldPcal6524.shellcmd);           \
+    aosShellAddCommand(&aos.shell, &moduleUtAlldAt42qt1050.shellcmd);         \
   }
 #else
   #define MODULE_INIT_TEST_SENSORRING()         {}
@@ -499,11 +501,15 @@ extern ROMCONST char* moduleShellPrompt;
   }
 #elif (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L0X) || defined(__DOXYGEN__)
   #define MODULE_INIT_PERIPHERY_COMM_SENSORRING() {                           \
-    /* TODO */                                                                \
+    moduleHalI2cSrPm18Pm33GaugeRearConfig.clock_speed = (PCAL6524_LLD_I2C_MAXFREQUENCY < moduleHalI2cSrPm18Pm33GaugeRearConfig.clock_speed) ? PCAL6524_LLD_I2C_MAXFREQUENCY : moduleHalI2cSrPm18Pm33GaugeRearConfig.clock_speed;  \
+    moduleHalI2cSrPm42Pm50PmVddEepromGaugeFrontConfig.clock_speed = (PCAL6524_LLD_I2C_MAXFREQUENCY < moduleHalI2cSrPm42Pm50PmVddEepromGaugeFrontConfig.clock_speed) ? PCAL6524_LLD_I2C_MAXFREQUENCY : moduleHalI2cSrPm42Pm50PmVddEepromGaugeFrontConfig.clock_speed;  \
+    moduleHalI2cSrPm42Pm50PmVddEepromGaugeFrontConfig.clock_speed = (AT42QT1050_LLD_I2C_MAXFREQUENCY < moduleHalI2cSrPm42Pm50PmVddEepromGaugeFrontConfig.clock_speed) ? AT42QT1050_LLD_I2C_MAXFREQUENCY : moduleHalI2cSrPm42Pm50PmVddEepromGaugeFrontConfig.clock_speed;  \
   }
 #elif (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L1X) || defined(__DOXYGEN__)
   #define MODULE_INIT_PERIPHERY_COMM_SENSORRING() {                           \
-    /* TODO */                                                                \
+    moduleHalI2cSrPm18Pm33GaugeRearConfig.clock_speed = (PCAL6524_LLD_I2C_MAXFREQUENCY < moduleHalI2cSrPm18Pm33GaugeRearConfig.clock_speed) ? PCAL6524_LLD_I2C_MAXFREQUENCY : moduleHalI2cSrPm18Pm33GaugeRearConfig.clock_speed;  \
+    moduleHalI2cSrPm42Pm50PmVddEepromGaugeFrontConfig.clock_speed = (PCAL6524_LLD_I2C_MAXFREQUENCY < moduleHalI2cSrPm42Pm50PmVddEepromGaugeFrontConfig.clock_speed) ? PCAL6524_LLD_I2C_MAXFREQUENCY : moduleHalI2cSrPm42Pm50PmVddEepromGaugeFrontConfig.clock_speed;  \
+    moduleHalI2cSrPm42Pm50PmVddEepromGaugeFrontConfig.clock_speed = (AT42QT1050_LLD_I2C_MAXFREQUENCY < moduleHalI2cSrPm42Pm50PmVddEepromGaugeFrontConfig.clock_speed) ? AT42QT1050_LLD_I2C_MAXFREQUENCY : moduleHalI2cSrPm42Pm50PmVddEepromGaugeFrontConfig.clock_speed;  \
   }
 #else
   #define MODULE_INIT_PERIPHERY_COMM_SENSORRING() {}
@@ -683,11 +689,47 @@ extern VCNL4020Driver moduleLldProximity2;
 #endif /* BOARD_SENSORRING == BOARD_PROXIMITYSENSOR */
 
 #if (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L0X) || defined(__DOXYGEN__)
-// TODO
+
+#include <alld_pcal6524.h>
+#include <alld_at42qt1050.h>
+
+/**
+ * @brief   GPIO extender (I2C #1) driver.
+ */
+extern PCAL6524Driver moduleLldGpioExtender1;
+
+/**
+ * @brief   GPIO extender (I2C #2) driver.
+ */
+extern PCAL6524Driver moduleLldGpioExtender2;
+
+/**
+ * @brief   Touch sensor driver.
+ */
+extern AT42QT1050Driver moduleLldTouch;
+
 #endif /* BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L0X */
 
 #if (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L1X) || defined(__DOXYGEN__)
-// TODO
+
+#include <alld_pcal6524.h>
+#include <alld_at42qt1050.h>
+
+/**
+ * @brief   GPIO extender (I2C #1) driver.
+ */
+extern PCAL6524Driver moduleLldGpioExtender1;
+
+/**
+ * @brief   GPIO extender (I2C #2) driver.
+ */
+extern PCAL6524Driver moduleLldGpioExtender2;
+
+/**
+ * @brief   Touch sensor driver.
+ */
+extern AT42QT1050Driver moduleLldTouch;
+
 #endif /* BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L1X */
 
 /** @} */
@@ -784,11 +826,37 @@ extern aos_unittest_t moduleUtAlldVcnl4020;
 #endif /* BOARD_SENSORRING == BOARD_PROXIMITYSENSOR */
 
 #if (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L0X) || defined(__DOXYGEN__)
-// TODO
+
+#include <ut_alld_pcal6524.h>
+#include <ut_alld_at42qt1050.h>
+
+/**
+ * @brief   PCAL6524 (GPIO extender) unit test object.
+ */
+extern aos_unittest_t moduleUtAlldPcal6524;
+
+/**
+ * @brief   AT42QT1050 (touch sensor) unit test object.
+ */
+extern aos_unittest_t moduleUtAlldAt42qt1050;
+
 #endif /* BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L0X */
 
 #if (BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L1X) || defined(__DOXYGEN__)
-// TODO
+
+#include <ut_alld_pcal6524.h>
+#include <ut_alld_at42qt1050.h>
+
+/**
+ * @brief   PCAL6524 (GPIO extender) unit test object.
+ */
+extern aos_unittest_t moduleUtAlldPcal6524;
+
+/**
+ * @brief   AT42QT1050 (touch sensor) unit test object.
+ */
+extern aos_unittest_t moduleUtAlldAt42qt1050;
+
 #endif /* BOARD_SENSORRING == BOARD_DISTANCESENSOR_VL53L1X */
 
 #endif /* AMIROOS_CFG_TESTS_ENABLE == true */
diff --git a/periphery-lld/AMiRo-LLD b/periphery-lld/AMiRo-LLD
index f125ae0..9e45662 160000
--- a/periphery-lld/AMiRo-LLD
+++ b/periphery-lld/AMiRo-LLD
@@ -1 +1 @@
-Subproject commit f125ae07972ff44a651eb3e4bd2acc2f635066d2
+Subproject commit 9e45662eac51cb2ae4eb48a079f30e5d5c5e80aa
diff --git a/unittests/periphery-lld/inc/ut_alld_at42qt1050.h b/unittests/periphery-lld/inc/ut_alld_at42qt1050.h
new file mode 100644
index 0000000..56ea56b
--- /dev/null
+++ b/unittests/periphery-lld/inc/ut_alld_at42qt1050.h
@@ -0,0 +1,64 @@
+/*
+AMiRo-OS is an operating system designed 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 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _AMIROOS_UT_ALLD_AT42QT1050_H_
+#define _AMIROOS_UT_ALLD_AT42QT1050_H_
+
+#include <aos_unittest.h>
+#include <amiro-lld.h>
+
+#if ((AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_USE_AT42QT1050)) || defined(__DOXYGEN__)
+
+#include <alld_at42qt1050.h>
+
+/**
+ * @brief   Custom data structure for the unit test.
+ */
+typedef struct {
+  /**
+   * @brief   Pointer to the AT42QT1050 driver to use.
+   */
+  AT42QT1050Driver* at42qt1050d;
+
+  /**
+   * @brief   Timeout value (in µs).
+   */
+  apalTime_t timeout;
+
+  /**
+   * @brief   Event source to listen to.
+   */
+  event_source_t* evtsource;
+
+  /**
+   * @brief   Event flags to watch.
+   */
+  eventflags_t evtflags;
+} ut_at42qt1050data_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  aos_utresult_t utAlldAt42qt1050Func(BaseSequentialStream* stream, aos_unittest_t* ut);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* (AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_USE_AT42QT1050) */
+
+#endif /* _AMIROOS_UT_ALLD_AT42QT1050_H_ */
diff --git a/unittests/periphery-lld/inc/ut_alld_pcal6524.h b/unittests/periphery-lld/inc/ut_alld_pcal6524.h
new file mode 100644
index 0000000..3dd64f1
--- /dev/null
+++ b/unittests/periphery-lld/inc/ut_alld_pcal6524.h
@@ -0,0 +1,54 @@
+/*
+AMiRo-OS is an operating system designed 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 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _AMIROOS_UT_PCAL6524_LLD_H_
+#define _AMIROOS_UT_PCAL6524_LLD_H_
+
+#include <aos_unittest.h>
+#include <amiro-lld.h>
+
+#if ((AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_USE_PCAL6524)) || defined(__DOXYGEN__)
+
+#include <alld_pcal6524.h>
+
+/**
+ * @brief   Custom data structure for the unit test.
+ */
+typedef struct {
+  /**
+   * @brief   pointer to the PCAL6524 driver to use.
+   */
+  PCAL6524Driver* pcal6524d;
+
+  /**
+   * @brief   Timeout value (in µs).
+   */
+  apalTime_t timeout;
+} ut_pcal6524data_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  aos_utresult_t utAlldPcal6524Func(BaseSequentialStream* stream, aos_unittest_t *ut);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* (AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_USE_PCAL6524) */
+
+#endif /* _AMIROOS_UT_PCAL6524_LLD_H_ */
diff --git a/unittests/periphery-lld/src/ut_alld_at42qt1050.c b/unittests/periphery-lld/src/ut_alld_at42qt1050.c
new file mode 100644
index 0000000..23ebfd6
--- /dev/null
+++ b/unittests/periphery-lld/src/ut_alld_at42qt1050.c
@@ -0,0 +1,133 @@
+/*
+AMiRo-OS is an operating system designed 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 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <ut_alld_at42qt1050.h>
+
+#if ((AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_USE_AT42QT1050)) || defined(__DOXYGEN__)
+
+#include <aos_debug.h>
+#include <chprintf.h>
+#include <aos_thread.h>
+#include <amiroos.h>
+
+#define INTERRUPT_EVENT_ID            1
+
+aos_utresult_t utAlldAt42qt1050Func(BaseSequentialStream* stream, aos_unittest_t* ut)
+{
+  aosDbgCheck(ut->data != NULL && ((ut_at42qt1050data_t*)ut->data)->at42qt1050d != NULL);
+
+  // local variables
+  aos_utresult_t result = {0, 0};
+  uint32_t status;
+  uint8_t buffer8[4] = {0, 0};
+  uint16_t buffer16[5];
+  event_listener_t event_listener;
+  aos_timestamp_t tstart, tcurrent, tend;
+
+  chprintf(stream, "read register...\n");
+  status = at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_CHIPID, &buffer8[0], ((ut_at42qt1050data_t*)ut->data)->timeout);
+  status |= at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_FIRMWAREVERSION, &buffer8[1], ((ut_at42qt1050data_t*)ut->data)->timeout);
+  chprintf(stream, "\t\tchip ID: 0x%02X\n", buffer8[0]);
+  chprintf(stream, "\t\tfirmware version: %u.%u (0x%02X)\n", ((at42qt1050_lld_firmwarereg_t)buffer8[1]).major, ((at42qt1050_lld_firmwarereg_t)buffer8[1]).minor, buffer8[1]);
+  if (status == APAL_STATUS_SUCCESS && buffer8[0] == AT42QT1050_LLD_CHIPID) {
+    aosUtPassed(stream, &result);
+  } else {
+    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
+  }
+
+  chprintf(stream, "write register...\n");
+  buffer8[1] = (((uint8_t)(at42qt1050_lld_samples2pulse(4096) + 0.5f)) << 4) | ((uint8_t)(at42qt1050_lld_scaling2scale(1024) + 0.5f));
+  status = at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_PULSE_SCALE_1, &buffer8[0], ((ut_at42qt1050data_t*)ut->data)->timeout);
+  status |= at42qt1050_lld_write_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_PULSE_SCALE_1, buffer8[1] , ((ut_at42qt1050data_t*)ut->data)->timeout);
+  status |= at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_PULSE_SCALE_1, &buffer8[2], ((ut_at42qt1050data_t*)ut->data)->timeout);
+  status |= at42qt1050_lld_write_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_PULSE_SCALE_1, buffer8[0] , ((ut_at42qt1050data_t*)ut->data)->timeout);
+  status |= at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_PULSE_SCALE_1, &buffer8[3], ((ut_at42qt1050data_t*)ut->data)->timeout);
+  if (status == APAL_STATUS_SUCCESS &&
+      buffer8[3] == buffer8[0] &&
+      buffer8[2] == buffer8[1] &&
+      at42qt1050_lld_pulse2samples(((at42qt1050_lld_pulsescalereg_t)buffer8[2]).pulse) == 4096 &&
+      at42qt1050_lld_scale2scaling(((at42qt1050_lld_pulsescalereg_t)buffer8[2]).scale) == 1024) {
+    aosUtPassed(stream, &result);
+  } else {
+    aosUtFailedMsg(stream, &result, "0x%08X [0x%02X 0x%02X 0x%02X 0x%02X]\n", status, buffer8[0], buffer8[1], buffer8[2], buffer8[3]);
+  }
+
+  chprintf(stream, "read reference data...\n");
+  status = APAL_STATUS_OK;
+  for (uint8_t key = 0; key < AT42QT1050_LLD_NUM_KEYS; ++key) {
+    status |= at42qt1050_lld_read_referencedata(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, key, &buffer16[key], ((ut_at42qt1050data_t*)ut->data)->timeout);
+    chprintf(stream, "\t\tkey %u: 0x%04X\n", key, buffer16[key]);
+  }
+  if (status == APAL_STATUS_SUCCESS) {
+    aosUtPassed(stream, &result);
+  } else {
+    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
+  }
+
+  chprintf(stream, "read key signal for ten seconds...\n");
+  status = APAL_STATUS_OK;
+  chprintf(stream, "\t\t key 0  key 1  key 2  key 3  key 4\n");
+  for (uint8_t s = 0; s < 10; ++s) {
+    aosThdSSleep(1);
+    for (uint8_t key = 0; key < AT42QT1050_LLD_NUM_KEYS; ++key) {
+      status |= at42qt1050_lld_read_keyssignal(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, key, &buffer16[key], ((ut_at42qt1050data_t*)ut->data)->timeout);
+    }
+    chprintf(stream, "\t\t0x%04X 0x%04X 0x%04X 0x%04X 0x%04X\n", buffer16[0], buffer16[1], buffer16[2], buffer16[3], buffer16[4]);
+  }
+  if (status == APAL_STATUS_SUCCESS) {
+    aosUtPassed(stream, &result);
+  } else {
+    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
+  }
+
+  chprintf(stream, "test interrupts...\n");
+  status = AOS_OK;
+  chEvtRegister(((ut_at42qt1050data_t*)ut->data)->evtsource, &event_listener, INTERRUPT_EVENT_ID);
+  aosSysGetUptime(&tstart);
+  tend = tstart + (30 * MICROSECONDS_PER_SECOND);
+  do {
+    aosSysGetUptime(&tcurrent);
+    const aos_timestamp_t ttimeout = MICROSECONDS_PER_SECOND - ((tcurrent - tstart) % MICROSECONDS_PER_SECOND);
+    const eventmask_t emask = chEvtWaitOneTimeout(EVENT_MASK(INTERRUPT_EVENT_ID), chTimeUS2I(ttimeout));
+    const eventflags_t eflags = chEvtGetAndClearFlags(&event_listener);
+    if (emask == EVENT_MASK(INTERRUPT_EVENT_ID) && eflags == ((ut_at42qt1050data_t*)ut->data)->evtflags) {
+      // interrupt detected
+      chprintf(stream, "\t\tinterrupt detected\n");
+    } // else: timeout
+    status |= at42qt1050_lld_read_reg(((ut_at42qt1050data_t*)ut->data)->at42qt1050d, AT42QT1050_LLD_REG_KEYSTATUS, &buffer8[0], ((ut_at42qt1050data_t*)ut->data)->timeout);
+    chprintf(stream, "\t\tkey status: %u %u %u %u %u\n",
+             (((buffer8[0] & AT42QT1050_LLD_KEYSTATUS_KEY0) == 0) ? 0 : 1),
+             (((buffer8[0] & AT42QT1050_LLD_KEYSTATUS_KEY1) == 0) ? 0 : 1),
+             (((buffer8[0] & AT42QT1050_LLD_KEYSTATUS_KEY2) == 0) ? 0 : 1),
+             (((buffer8[0] & AT42QT1050_LLD_KEYSTATUS_KEY3) == 0) ? 0 : 1),
+             (((buffer8[0] & AT42QT1050_LLD_KEYSTATUS_KEY4) == 0) ? 0 : 1));
+    aosSysGetUptime(&tcurrent);
+  } while (tcurrent < tend);
+  chEvtUnregister(((ut_at42qt1050data_t*)ut->data)->evtsource, &event_listener);
+  if (status == APAL_STATUS_SUCCESS) {
+    aosUtPassed(stream, &result);
+  } else {
+    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
+  }
+
+  aosUtInfoMsg(stream,"driver object memory footprint: %u bytes\n", sizeof(AT42QT1050Driver));
+
+  return result;
+}
+
+#endif /* (AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_USE_AT42QT1050) */
diff --git a/unittests/periphery-lld/src/ut_alld_pcal6524.c b/unittests/periphery-lld/src/ut_alld_pcal6524.c
new file mode 100644
index 0000000..f55af93
--- /dev/null
+++ b/unittests/periphery-lld/src/ut_alld_pcal6524.c
@@ -0,0 +1,141 @@
+/*
+AMiRo-OS is an operating system designed 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 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <ut_alld_pcal6524.h>
+
+#if ((AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_USE_PCAL6524)) || defined(__DOXYGEN__)
+
+#include <chprintf.h>
+#include <string.h>
+
+aos_utresult_t utAlldPcal6524Func(BaseSequentialStream* stream, aos_unittest_t *ut)
+{
+  aosDbgCheck((ut->data != NULL) &&
+              (((ut_pcal6524data_t*)ut->data)->pcal6524d != NULL));
+
+  // local variables
+  aos_utresult_t result = {0, 0};
+  uint32_t status;
+  uint8_t buffer[24];
+  memset(buffer, 0xAA, sizeof(buffer));
+
+// This test is currently not supported. See PCAL6524 driver implementation for further information.
+//  chprintf(stream, "reading device ID...\n");
+//  status = pcal6524_lld_read_id(((ut_pcal6524data_t*)ut->data)->pcal6524d, buffer, ((ut_pcal6524data_t*)ut->data)->timeout);
+//  chprintf(stream, "\t\traw: 0x%02X 0x%02X 0x%02X\n", buffer[0], buffer[1], buffer[2]);
+//  chprintf(stream, "\t\tname:     0x%03X\n", ((pcal6524_lld_deviceid_t*)buffer)->name);
+//  chprintf(stream, "\t\tpart:     0x%03X\n", ((pcal6524_lld_deviceid_t*)buffer)->part);
+//  chprintf(stream, "\t\trevision: 0x%01X\n", ((pcal6524_lld_deviceid_t*)buffer)->revision);
+//  if ((status == APAL_STATUS_OK) || (status == APAL_STATUS_WARNING)) {
+//    aosUtPassed(stream, &result);
+//  } else {
+//    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
+//  }
+
+  chprintf(stream, "reading register...\n");
+  status = pcal6524_lld_read_reg(((ut_pcal6524data_t*)ut->data)->pcal6524d, PCAL6524_LLD_CMD_SWITCHDEBOUNCECOUNT, buffer, ((ut_pcal6524data_t*)ut->data)->timeout);
+  chprintf(stream, "\t\tdebounce count: %u\n", buffer[0]);
+  if ((status == APAL_STATUS_OK) || (status == APAL_STATUS_WARNING)) {
+    aosUtPassed(stream, &result);
+  } else {
+    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
+  }
+
+  chprintf(stream, "writing register...\n");
+  buffer[3] = 0xFF;
+  status = pcal6524_lld_write_reg(((ut_pcal6524data_t*)ut->data)->pcal6524d, PCAL6524_LLD_CMD_SWITCHDEBOUNCECOUNT, buffer[3], ((ut_pcal6524data_t*)ut->data)->timeout);
+  status |= pcal6524_lld_read_reg(((ut_pcal6524data_t*)ut->data)->pcal6524d, PCAL6524_LLD_CMD_SWITCHDEBOUNCECOUNT, &buffer[4], ((ut_pcal6524data_t*)ut->data)->timeout);
+  status |= pcal6524_lld_write_reg(((ut_pcal6524data_t*)ut->data)->pcal6524d, PCAL6524_LLD_CMD_SWITCHDEBOUNCECOUNT, buffer[0], ((ut_pcal6524data_t*)ut->data)->timeout);
+  status |= pcal6524_lld_read_reg(((ut_pcal6524data_t*)ut->data)->pcal6524d, PCAL6524_LLD_CMD_SWITCHDEBOUNCECOUNT, &buffer[1], ((ut_pcal6524data_t*)ut->data)->timeout);
+  if (((status == APAL_STATUS_OK) || (status == APAL_STATUS_WARNING)) &&
+      ((buffer[1] == buffer[0]) && (buffer[4] == buffer[3]))) {
+    aosUtPassed(stream, &result);
+  } else {
+    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
+  }
+
+  chprintf(stream, "reading group...\n");
+  status = pcal6524_lld_read_group(((ut_pcal6524data_t*)ut->data)->pcal6524d, PCAL6524_LLD_CMD_OUTPUTDRIVESTRENGTH_P0A, buffer, ((ut_pcal6524data_t*)ut->data)->timeout);
+  chprintf(stream, "\t\toutput drive strength: 0x%04X 0x%04X 0x%04X\n",
+           (((uint16_t)buffer[0]) << 8) | buffer[1],
+           (((uint16_t)buffer[2]) << 8) | buffer[3],
+           (((uint16_t)buffer[4]) << 8) | buffer[5]);
+  if ((status == APAL_STATUS_OK) || (status == APAL_STATUS_WARNING)) {
+    aosUtPassed(stream, &result);
+  } else {
+    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
+  }
+
+  chprintf(stream, "writing group...\n");
+  memset(&buffer[6], PCAL6524_LL_OUTPUTDRIVESTRENGTH_0_25, 6);
+  status = pcal6524_lld_write_group(((ut_pcal6524data_t*)ut->data)->pcal6524d, PCAL6524_LLD_CMD_OUTPUTDRIVESTRENGTH_P0A, &buffer[6], ((ut_pcal6524data_t*)ut->data)->timeout);
+  status |= pcal6524_lld_read_group(((ut_pcal6524data_t*)ut->data)->pcal6524d, PCAL6524_LLD_CMD_OUTPUTDRIVESTRENGTH_P0A, &buffer[12], ((ut_pcal6524data_t*)ut->data)->timeout);
+  status |= pcal6524_lld_write_group(((ut_pcal6524data_t*)ut->data)->pcal6524d, PCAL6524_LLD_CMD_OUTPUTDRIVESTRENGTH_P0A, &buffer[0], ((ut_pcal6524data_t*)ut->data)->timeout);
+  status |= pcal6524_lld_read_group(((ut_pcal6524data_t*)ut->data)->pcal6524d, PCAL6524_LLD_CMD_OUTPUTDRIVESTRENGTH_P0A, &buffer[18], ((ut_pcal6524data_t*)ut->data)->timeout);
+  if (((status == APAL_STATUS_OK) || (status == APAL_STATUS_WARNING)) &&
+      ((memcmp(&buffer[12], &buffer[6], 6) == 0) && (memcmp(&buffer[18], &buffer[0], 6) == 0))) {
+    aosUtPassed(stream, &result);
+  } else {
+    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
+  }
+
+  chprintf(stream, "reading continuously...\n");
+  // read the following registers continously (24 bytes):
+  // output 0-3 + polarity inversions 0-3 + configuration 0-3 + output drive strength 0A-2B + input latch 0-3 + pupd enable 0-3 + pupd selection 0-3
+  status = pcal6524_lld_read_continuous(((ut_pcal6524data_t*)ut->data)->pcal6524d, PCAL6524_LLD_CMD_OUTPUT_P0, buffer, 24, ((ut_pcal6524data_t*)ut->data)->timeout);
+  chprintf(stream, "\t\toutput: 0x%02X 0x%02X 0x%02X\n", buffer[0], buffer[1], buffer[2]);
+  chprintf(stream, "\t\tpolarity inversion: 0x%02X 0x%02X 0x%02X\n", buffer[3], buffer[4], buffer[5]);
+  chprintf(stream, "\t\tconfiguration: 0x%02X 0x%02X 0x%02X\n", buffer[6], buffer[7], buffer[8]);
+  chprintf(stream, "\t\toutput drive strength: 0x%04X 0x%04X 0x%04X\n",
+           (((uint16_t)buffer[9]) << 8) | buffer[10],
+           (((uint16_t)buffer[11]) << 8) | buffer[12],
+           (((uint16_t)buffer[13]) << 8) | buffer[14]);
+  chprintf(stream, "\t\tinput latch: 0x%02X 0x%02X 0x%02X\n", buffer[15], buffer[16], buffer[17]);
+  chprintf(stream, "\t\tpupd enable: 0x%02X 0x%02X 0x%02X\n", buffer[18], buffer[19], buffer[20]);
+  chprintf(stream, "\t\tpupd selection: 0x%02X 0x%02X 0x%02X\n", buffer[21], buffer[22], buffer[23]);
+  if ((status == APAL_STATUS_OK) || (status == APAL_STATUS_WARNING)) {
+    aosUtPassed(stream, &result);
+  } else {
+    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
+  }
+
+  chprintf(stream, "writing continuously...\n");
+  {
+    uint8_t writebuffer[24];
+    uint8_t readbuffer[2][24];
+    // copy the read configuration but set the output drive strength to factor 0.25
+    memcpy(writebuffer, buffer, sizeof(buffer));
+    memset(&writebuffer[9], PCAL6524_LL_OUTPUTDRIVESTRENGTH_0_25, 6);
+    status = pcal6524_lld_write_continuous(((ut_pcal6524data_t*)ut->data)->pcal6524d, PCAL6524_LLD_CMD_OUTPUT_P0, writebuffer, 24, ((ut_pcal6524data_t*)ut->data)->timeout);
+    status |= pcal6524_lld_read_continuous(((ut_pcal6524data_t*)ut->data)->pcal6524d, PCAL6524_LLD_CMD_OUTPUT_P0, readbuffer[0], 24, ((ut_pcal6524data_t*)ut->data)->timeout);
+    status |= pcal6524_lld_write_continuous(((ut_pcal6524data_t*)ut->data)->pcal6524d, PCAL6524_LLD_CMD_OUTPUT_P0, buffer, 24, ((ut_pcal6524data_t*)ut->data)->timeout);
+    status |= pcal6524_lld_read_continuous(((ut_pcal6524data_t*)ut->data)->pcal6524d, PCAL6524_LLD_CMD_OUTPUT_P0, readbuffer[1], 24, ((ut_pcal6524data_t*)ut->data)->timeout);
+    if (((status == APAL_STATUS_OK) || (status == APAL_STATUS_WARNING)) &&
+        ((memcmp(writebuffer, readbuffer[0], 24) == 0) && (memcmp(buffer, readbuffer[1], 24) == 0))) {
+      aosUtPassed(stream, &result);
+    } else {
+      aosUtFailedMsg(stream, &result, "0x%08X\n", status);
+    }
+  }
+
+  aosUtInfoMsg(stream, "driver object memory footprint: %u bytes\n", sizeof(PCAL6524Driver));
+
+  return result;
+}
+
+#endif /* (AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_USE_PCAL6524) */
diff --git a/unittests/unittests.mk b/unittests/unittests.mk
index 66416a6..01def60 100644
--- a/unittests/unittests.mk
+++ b/unittests/unittests.mk
@@ -34,6 +34,7 @@ UNITTESTSINC = $(UNITTESTS_DIR)lld/inc \
 UNITTESTSCSRC = $(UNITTESTS_DIR)lld/src/ut_lld_adc.c \
                 $(UNITTESTS_DIR)periphery-lld/src/ut_alld_a3906.c \
                 $(UNITTESTS_DIR)periphery-lld/src/ut_alld_at24c01bn-sh-b.c \
+                $(UNITTESTS_DIR)periphery-lld/src/ut_alld_at42qt1050.c \
                 $(UNITTESTS_DIR)periphery-lld/src/ut_alld_bq24103a.c \
                 $(UNITTESTS_DIR)periphery-lld/src/ut_alld_bq27500.c \
                 $(UNITTESTS_DIR)periphery-lld/src/ut_alld_bq27500_bq24103a.c \
@@ -45,6 +46,7 @@ UNITTESTSCSRC = $(UNITTESTS_DIR)lld/src/ut_lld_adc.c \
                 $(UNITTESTS_DIR)periphery-lld/src/ut_alld_ltc4412.c \
                 $(UNITTESTS_DIR)periphery-lld/src/ut_alld_mpr121.c \
                 $(UNITTESTS_DIR)periphery-lld/src/ut_alld_pca9544a.c \
+                $(UNITTESTS_DIR)periphery-lld/src/ut_alld_pcal6524.c \
                 $(UNITTESTS_DIR)periphery-lld/src/ut_alld_pklcs1212e4001.c \
                 $(UNITTESTS_DIR)periphery-lld/src/ut_alld_tlc5947.c \
                 $(UNITTESTS_DIR)periphery-lld/src/ut_alld_tps2051bdbv.c \
