commit 9466e34d0601c3e9e7c0627a1bf5d8e88bf40a92
Author: Thomas Schöpping <tschoepp@cit-ec.uni-bielefeld.de>
Date:   Mon Jul 15 13:18:52 2019 +0200

    major structure overhaul:
    - Drivers are no longer separated in include/ and source/ folders, but a single drivers/ folder.
    - There is no Makefile anymore. Software, which uses the drivers has to set the according paths individually.
    - (De)Activation of drivers is no longer done via the alldconf.h file, but via Makefiles.

diff --git a/Makefile b/Makefile
deleted file mode 100755
index 7c96028..0000000
--- a/Makefile
+++ /dev/null
@@ -1,35 +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/>.        #
-#                                                                              #
-# This research/work was supported by the Cluster of Excellence Cognitive      #
-# Interaction Technology 'CITEC' (EXC 277) at Bielefeld University, which is   #
-# funded by the German Research Foundation (DFG).                              #
-################################################################################
-
-
-
-# absolute path to this directory
-AMIROLLD_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
-
-# include paths
-AMIROLLD_INC = $(AMIROLLD_DIR) \
-               $(sort $(dir $(wildcard $(AMIROLLD_DIR)include/?*/)))
-
-# C sources
-AMIROLLD_CSRC = $(shell find $(AMIROLLD_DIR)source/ -type f -regex "$(AMIROLLD_DIR)source/.+\.[Cc]")
-
diff --git a/drivers/A3906/v1/alld_A3906.c b/drivers/A3906/v1/alld_A3906.c
new file mode 100644
index 0000000..5f1eb80
--- /dev/null
+++ b/drivers/A3906/v1/alld_A3906.c
@@ -0,0 +1,105 @@
+/*
+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/>.
+*/
+
+/**
+ * @file    alld_A3906.c
+ * @brief   Motor driver functions.
+ *
+ * @addtogroup lld_motor
+ * @{
+ */
+
+#include <alld_A3906.h>
+
+/******************************************************************************/
+/* LOCAL DEFINITIONS                                                          */
+/******************************************************************************/
+
+/******************************************************************************/
+/* EXPORTED VARIABLES                                                         */
+/******************************************************************************/
+
+/******************************************************************************/
+/* LOCAL TYPES                                                                */
+/******************************************************************************/
+
+/******************************************************************************/
+/* LOCAL VARIABLES                                                            */
+/******************************************************************************/
+
+/******************************************************************************/
+/* LOCAL FUNCTIONS                                                            */
+/******************************************************************************/
+
+/******************************************************************************/
+/* EXPORTED FUNCTIONS                                                         */
+/******************************************************************************/
+
+/**
+ * @brief Sets the power state of the A3906.
+ * @param[in]   a3906d      The A3906 driver.
+ * @param[in]   power_state The new power state to set.
+ *
+ * @return The return status indicates whether the function call was successfull.
+ */
+apalExitStatus_t a3906_lld_set_power(const A3906Driver* const a3906, const a3906_lld_power_t power_state)
+{
+  apalDbgAssert(a3906 != NULL);
+
+  // set the output of the pin depending on the activation property
+  return apalControlGpioSet(a3906->power_pin, (power_state == A3906_LLD_POWER_ON) ? APAL_GPIO_ON : APAL_GPIO_OFF);
+}
+
+/**
+ * @brief Gets the current power state of the A3906.
+ *
+ * @param[in]   a3906d        The A3906 driver,
+ * @param[out]  power_state   The currently set power state.
+ *
+ * @return The return status indicates whether the function call was successfull.
+ */
+apalExitStatus_t a3906_lld_get_power(const A3906Driver* const a3906, a3906_lld_power_t* const power_state)
+{
+  apalDbgAssert(a3906 != NULL);
+  apalDbgAssert(power_state != NULL);
+
+  // get current activation state of power gpio
+  apalControlGpioState_t gpio_state;
+  apalExitStatus_t status = apalControlGpioGet(a3906->power_pin, &gpio_state);
+  *power_state = gpio_state == APAL_GPIO_ON ? A3906_LLD_POWER_ON : A3906_LLD_POWER_OFF;
+  return status;
+}
+
+/**
+ * @brief Set the PWM width for one channel.
+ *
+ * @param[in]   pwmd      The PWM driver to use.
+ * @param[in]   channel   The channel of the given PWM driver to set.
+ * @param[in]   width     The new width to set the PWM to.
+ *
+ * @return The return status indicates whether the function call was successfull.
+ */
+apalExitStatus_t a3906_lld_set_pwm(apalPWMDriver_t* pwm, const apalPWMchannel_t channel, const apalPWMwidth_t width)
+{
+  apalDbgAssert(pwm != NULL);
+
+  return apalPWMSet(pwm, channel, width);
+}
+
+/** @} */
+
diff --git a/drivers/A3906/v1/alld_A3906.h b/drivers/A3906/v1/alld_A3906.h
new file mode 100644
index 0000000..f7eeaf5
--- /dev/null
+++ b/drivers/A3906/v1/alld_A3906.h
@@ -0,0 +1,92 @@
+/*
+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/>.
+*/
+
+/**
+ * @file    alld_A3906.h
+ * @brief   Motor driver macros and structures.
+ *
+ * @addtogroup lld_motor
+ * @{
+ */
+
+#ifndef AMIROLLD_A3906_H
+#define AMIROLLD_A3906_H
+
+#include <amiro-lld.h>
+
+/******************************************************************************/
+/* CONSTANTS                                                                  */
+/******************************************************************************/
+
+/**
+ * @brief Active state of power pin.
+ */
+#define A3906_LLD_POWER_PIN_ACTIVE_STATE  APAL_GPIO_ACTIVE_HIGH
+
+/******************************************************************************/
+/* SETTINGS                                                                   */
+/******************************************************************************/
+
+/******************************************************************************/
+/* CHECKS                                                                     */
+/******************************************************************************/
+
+/******************************************************************************/
+/* DATA STRUCTURES AND TYPES                                                  */
+/******************************************************************************/
+
+/**
+ * @brief A3906 driver struct.
+ */
+typedef struct {
+  const apalControlGpio_t* power_pin;   /**< @brief GPIO to enable/disable power of the A3906. */
+} A3906Driver;
+
+/**
+ * @brief Power state of the A3906.
+ */
+typedef enum {
+  A3906_LLD_POWER_OFF = 0x00,   /**< 'power off' state  */
+  A3906_LLD_POWER_ON  = 0x01,   /**< 'power on' state   */
+} a3906_lld_power_t;
+
+/******************************************************************************/
+/* MACROS                                                                     */
+/******************************************************************************/
+
+/******************************************************************************/
+/* EXTERN DECLARATIONS                                                        */
+/******************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  apalExitStatus_t a3906_lld_set_power(const A3906Driver* const a3906, const a3906_lld_power_t power_state);
+  apalExitStatus_t a3906_lld_get_power(const A3906Driver* const a3906, a3906_lld_power_t* const power_state);
+  apalExitStatus_t a3906_lld_set_pwm(apalPWMDriver_t* pwm, const apalPWMchannel_t channel, const apalPWMwidth_t width);
+#ifdef __cplusplus
+}
+#endif
+
+/******************************************************************************/
+/* INLINE FUNCTIONS                                                           */
+/******************************************************************************/
+
+#endif /* AMIROLLD_A3906_H */
+
+/** @} */
diff --git a/drivers/AT24C01B/v1/alld_AT24C01B.c b/drivers/AT24C01B/v1/alld_AT24C01B.c
new file mode 100644
index 0000000..7833000
--- /dev/null
+++ b/drivers/AT24C01B/v1/alld_AT24C01B.c
@@ -0,0 +1,149 @@
+/*
+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/>.
+*/
+
+/**
+ * @file    alld_AT24C01B.c
+ * @brief   EEPROM function implementations.
+ *
+ * @addtogroup lld_eeprom
+ * @{
+ */
+
+#include <alld_AT24C01B.h>
+#include <string.h>
+
+/******************************************************************************/
+/* LOCAL DEFINITIONS                                                          */
+/******************************************************************************/
+
+/******************************************************************************/
+/* EXPORTED VARIABLES                                                         */
+/******************************************************************************/
+
+/******************************************************************************/
+/* LOCAL TYPES                                                                */
+/******************************************************************************/
+
+/******************************************************************************/
+/* LOCAL VARIABLES                                                            */
+/******************************************************************************/
+
+/******************************************************************************/
+/* LOCAL FUNCTIONS                                                            */
+/******************************************************************************/
+
+/******************************************************************************/
+/* EXPORTED FUNCTIONS                                                         */
+/******************************************************************************/
+
+/**
+ * @brief Acknowledgement polling to check if a write operation finished.
+ * @param[in]   at24c01b  The eeprom driver to use.
+ * @param[in]   timeout   Timeout for the function to return (in microseconds)
+ *
+ * @return  The return status indicates whether the function call was succesfull or a timeout occurred.
+ */
+apalExitStatus_t at24c01b_lld_poll_ack(const AT24C01BDriver* const at24c01b, const apalTime_t timeout)
+{
+  apalDbgAssert(at24c01b != NULL);
+
+  uint8_t tmp = 0;
+  return apalI2CMasterReceive(at24c01b->i2cd, (AT24C01B_LLD_I2C_ADDR_FIXED | at24c01b->addr), &tmp, 1, timeout);
+}
+
+/**
+ * @brief Read the data from the eeprom starting at the current address.
+ * @param[in]   at24c01b  The eeprom driver to use.
+ * @param[out]  data      The data read from the AT24C01B.
+ * @param[in]   num       The amount of bytes to read.
+ * @param[in]   timeout   Timeout for the function to return (in microseconds)
+ *
+ * @return  The return status indicates whether the function call was succesfull or a timeout occurred.
+ */
+apalExitStatus_t at24c01b_lld_read_current_address(const AT24C01BDriver* const at24c01b, uint8_t* const data, const uint8_t num, const apalTime_t timeout)
+{
+  apalDbgAssert(at24c01b != NULL);
+  apalDbgAssert(data != NULL);
+
+  return apalI2CMasterReceive(at24c01b->i2cd, (AT24C01B_LLD_I2C_ADDR_FIXED | at24c01b->addr), data, num, timeout);
+}
+
+/**
+ * @brief Read the data from the eeprom starting at a given address.
+ * @param[in]   at24c01b  The eeprom driver to use.
+ * @param[in]   addr      The address to read.
+ * @param[out]  data      The data read from the AT24C01B.
+ * @param[in]   num       The amount of bytes to read.
+ * @param[in]   timeout   Timeout for the function to return (in microseconds)
+ *
+ * @return  The return status indicates whether the function call was succesfull or a timeout occurred.
+ */
+apalExitStatus_t at24c01b_lld_read(const AT24C01BDriver* const at24c01b, const uint8_t addr, uint8_t* const data, const uint8_t num, const apalTime_t timeout)
+{
+  apalDbgAssert(at24c01b != NULL);
+  apalDbgAssert(data != NULL);
+  apalDbgAssert(addr + num <= AT24C01B_LLD_SIZE_BYTES);
+
+  apalExitStatus_t status = apalI2CMasterTransmit(at24c01b->i2cd, (AT24C01B_LLD_I2C_ADDR_FIXED | at24c01b->addr), &addr, 1, NULL, 0, timeout);
+  if (status == APAL_STATUS_OK || status == APAL_STATUS_WARNING) {
+    return apalI2CMasterReceive(at24c01b->i2cd, (AT24C01B_LLD_I2C_ADDR_FIXED | at24c01b->addr), data, num, timeout);
+  } else {
+    return status;
+  }
+}
+
+/**
+ * @brief Write a byte to the eeprom.
+ * @param[in]   at24c01b  The eeprom driver to use.
+ * @param[in]   addr      The address to start writing.
+ * @param[out]  data      The data to be written to the AT24C01BN.
+ * @param[in]   timeout   Timeout for the function to return (in microseconds)
+ *
+ * @return  The return status indicates whether the function call was succesfull or a timeout occurred.
+ */
+apalExitStatus_t at24c01b_lld_write_byte(const AT24C01BDriver* const at24c01b, const uint8_t addr, const uint8_t data, const apalTime_t timeout)
+{
+  apalDbgAssert(at24c01b != NULL);
+
+  const uint8_t writedata[2] = {addr, data};
+  return apalI2CMasterTransmit(at24c01b->i2cd, (AT24C01B_LLD_I2C_ADDR_FIXED | at24c01b->addr), writedata, 2, NULL, 0, timeout);
+}
+
+/**
+ * @brief Write a page to the eeprom.
+ * @param[in]   at24c01b  The eeprom driver to use.
+ * @param[in]   addr      The address to start writing.
+ * @param[in]   data      The data to be written to the AT24C01BN.
+ * @param[in]   num       The amount of bytes to write.
+ * @param[in]   timeout   Timeout for the function to return (in microseconds)
+ *
+ * @return  The return status indicates whether the function call was succesfull or a timeout occurred.
+ */
+apalExitStatus_t at24c01b_lld_write_page(const AT24C01BDriver* const at24c01b, const uint8_t addr, const uint8_t* const data, const uint8_t num, const apalTime_t timeout)
+{
+  apalDbgAssert(at24c01b != NULL);
+  apalDbgAssert(data != NULL);
+
+  uint8_t writedata[num+1];
+  writedata[0] = addr;
+  memcpy(&writedata[1], data, num);
+  return apalI2CMasterTransmit(at24c01b->i2cd, (AT24C01B_LLD_I2C_ADDR_FIXED | at24c01b->addr), writedata, num+1, NULL, 0, timeout);
+}
+
+/** @} */
+
diff --git a/drivers/AT24C01B/v1/alld_AT24C01B.h b/drivers/AT24C01B/v1/alld_AT24C01B.h
new file mode 100644
index 0000000..209ed17
--- /dev/null
+++ b/drivers/AT24C01B/v1/alld_AT24C01B.h
@@ -0,0 +1,125 @@
+/*
+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/>.
+*/
+
+/**
+ * @file    alld_AT24C01B.h
+ * @brief   EEPROM macros and structures.
+ *
+ * @addtogroup lld_eeprom
+ * @{
+ */
+
+#ifndef AMIROLLD_AT24C01B_H
+#define AMIROLLD_AT24C01B_H
+
+#include <amiro-lld.h>
+
+/******************************************************************************/
+/* CONSTANTS                                                                  */
+/******************************************************************************/
+
+/**
+ * @brief Memory size of the EEPROM in bits.
+ */
+#define AT24C01B_LLD_SIZE_BITS              1024
+
+/**
+ * @brief Memory size of the EEPROM in bytes
+ */
+#define AT24C01B_LLD_SIZE_BYTES             128
+
+
+/**
+ * @brief Size of a page in bytes
+ */
+#define AT24C01B_LLD_PAGE_SIZE_BYTES        8
+
+/**
+ * @brief  Time in microseconds a write operation takes to complete (I2C will not respond).
+ * @note   The system should wait slightly longer.
+ */
+#define AT24C01B_LLD_WRITECYCLETIME_US      5000
+
+/**
+ * @brief Maximum I2C frequency.
+ */
+#define AT24C01B_LLD_I2C_MAXFREQUENCY       400000
+
+/**
+ * @brief Maximum I2C frequency at 5V.
+ */
+#define AT24C01B_LLD_I2C_MAXFREQUENCY_5V    1000000
+
+
+/******************************************************************************/
+/* SETTINGS                                                                   */
+/******************************************************************************/
+
+/******************************************************************************/
+/* CHECKS                                                                     */
+/******************************************************************************/
+
+/******************************************************************************/
+/* DATA STRUCTURES AND TYPES                                                  */
+/******************************************************************************/
+
+/**
+ * @brief The AT24C01B driver struct
+ */
+typedef struct {
+  apalI2CDriver_t* i2cd;  /**< @brief The I2C Driver */
+  apalI2Caddr_t addr;     /**< @brief The address of the AT24C01B for I2C communication, which is defined by the wiring of the A0, A1, A2 pins */
+} AT24C01BDriver;
+
+/**
+ * @brief Bitmasks for the I2C address, including the wiring of the A0, A1, A2 pins.
+ */
+enum {
+  AT24C01B_LLD_I2C_ADDR_FIXED       = 0x0050u,
+  AT24C01B_LLD_I2C_ADDR_A0          = 0x0001u,
+  AT24C01B_LLD_I2C_ADDR_A1          = 0x0002u,
+  AT24C01B_LLD_I2C_ADDR_A2          = 0x0004u,
+};
+
+/******************************************************************************/
+/* MACROS                                                                     */
+/******************************************************************************/
+
+/******************************************************************************/
+/* EXTERN DECLARATIONS                                                        */
+/******************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  apalExitStatus_t at24c01b_lld_poll_ack(const AT24C01BDriver* const at24c01b, const apalTime_t timeout);
+  apalExitStatus_t at24c01b_lld_read_current_address(const AT24C01BDriver* const at24c01b, uint8_t* const data, const uint8_t num, const apalTime_t timeout);
+  apalExitStatus_t at24c01b_lld_read(const AT24C01BDriver* const at24c01b, const uint8_t addr, uint8_t* const data, const uint8_t num, const apalTime_t timeout);
+  apalExitStatus_t at24c01b_lld_write_byte(const AT24C01BDriver* const at24c01b, const uint8_t addr, const uint8_t data, const apalTime_t timeout);
+  apalExitStatus_t at24c01b_lld_write_page(const AT24C01BDriver* const at24c01b, const uint8_t addr, const uint8_t* const data, const uint8_t num, const apalTime_t timeout);
+#ifdef __cplusplus
+}
+#endif
+
+/******************************************************************************/
+/* INLINE FUNCTIONS                                                           */
+/******************************************************************************/
+
+#endif /* AMIROLLD_AT24C01BN_H */
+
+/** @} */
diff --git a/drivers/AT42QT1050/v1/alld_AT42QT1050.c b/drivers/AT42QT1050/v1/alld_AT42QT1050.c
new file mode 100644
index 0000000..8c3d569
--- /dev/null
+++ b/drivers/AT42QT1050/v1/alld_AT42QT1050.c
@@ -0,0 +1,231 @@
+/*
+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/>.
+*/
+
+/**
+ * @file    alld_AT42QT1050.c
+ * @brief   Touch sensor function implementations.
+ *
+ * @addtogroup lld_touch
+ * @{
+ */
+
+#include <alld_AT42QT1050.h>
+#include <math.h>
+
+/******************************************************************************/
+/* LOCAL DEFINITIONS                                                          */
+/******************************************************************************/
+#define AT42QT1050_LLD_WATCHDOGTIME_MAX         125000
+#define AT42QT1050_LLD_INITIALIZATION_TIME_MAX   30000  
+
+/******************************************************************************/
+/* EXPORTED VARIABLES                                                         */
+/******************************************************************************/
+
+/******************************************************************************/
+/* LOCAL TYPES                                                                */
+/******************************************************************************/
+
+/******************************************************************************/
+/* LOCAL VARIABLES                                                            */
+/******************************************************************************/
+
+/******************************************************************************/
+/* LOCAL FUNCTIONS                                                            */
+/******************************************************************************/
+
+/******************************************************************************/
+/* EXPORTED FUNCTIONS                                                         */
+/******************************************************************************/
+
+/**
+ * @brief   Read 8bit data from any register.
+ *
+ * @param[in]   at42qt1050d   The AT42QT1050 driver to use.
+ * @param[in]   reg           Register address to read from.
+ * @param[out]  data          Pointer to store the register data to.
+ * @param[in]   timeout       Timeout for the function to return (in microseconds).
+ *
+ * @return    Indicator whether the function call was successful or a timeout occurred.
+ */
+apalExitStatus_t at42qt1050_lld_read_reg(const AT42QT1050Driver* at42qt1050d, const at42qt1050_lld_register_t reg, uint8_t* const data, const apalTime_t timeout)
+{
+  apalDbgAssert(at42qt1050d != NULL && at42qt1050d->i2cd != NULL);
+  apalDbgAssert(data != NULL);
+
+  const uint8_t txbuf = (uint8_t)reg;
+  return apalI2CMasterTransmit(at42qt1050d->i2cd, at42qt1050d->addr, &txbuf, 1, data, 1, timeout);
+}
+
+/**
+ * @brief   Write 8bit data to any (writable) register.
+ *
+ * @param[in]   at42qt1050d   The AT42QT1050 driver to use.
+ * @param[in]   reg           Register address to write to.
+ * @param[in]   data          Data to transmit.
+ * @param[in]   timeout       Timeout for the function to return (in microseconds).
+ *
+ * @return    Indicator whether the function call was successful or a timeout occurred.
+ */
+apalExitStatus_t at42qt1050_lld_write_reg(const AT42QT1050Driver* at42qt1050d, const at42qt1050_lld_register_t reg, const uint8_t data, const apalTime_t timeout)
+{
+  apalDbgAssert(at42qt1050d != NULL && at42qt1050d->i2cd != NULL);
+
+  const uint8_t txbuf[2] = { (uint8_t)reg, data };
+  return apalI2CMasterTransmit(at42qt1050d->i2cd, at42qt1050d->addr, txbuf, 2, NULL, 0, timeout);
+}
+
+/**
+ * @brief   Read signal information of a key.
+ *
+ * @param[in]   at42qt1050d   The AT42QT1050 driver to use.
+ * @param[in]   key           Key to read the signal information of.
+ * @param[out]  signal        Pointer to store the data to.
+ * @param[in]   timeout       Timeout for the function to return (in microseconds).
+ *
+ * @return    Indicator whether the function call was successful or a timeout occurred.
+ */
+apalExitStatus_t at42qt1050_lld_read_keyssignal(const AT42QT1050Driver* at42qt1050d, const uint8_t key, uint16_t* signal, const apalTime_t timeout)
+{
+  apalDbgAssert(at42qt1050d != NULL && at42qt1050d->i2cd != NULL);
+  apalDbgAssert(key < AT42QT1050_LLD_NUM_KEYS);
+  apalDbgAssert(signal != NULL);
+
+  const at42qt1050_lld_register_t txbuf = at42qt1050_lld_addr_calc(AT42QT1050_LLD_REG_KEYSIGNAL_0, key);
+  uint8_t rxbuf[2];
+  const apalExitStatus_t status = apalI2CMasterTransmit(at42qt1050d->i2cd, at42qt1050d->addr, &txbuf, 1, rxbuf, 2, timeout);
+  *signal = (rxbuf[0] << 8) | rxbuf[1];
+  return status;
+}
+
+/**
+ * @brief   Read reference data of a key.
+ *
+ * @param[in]   at42qt1050d   The AT42QT1050 driver to use.
+ * @param[in]   key           Key to read the signal information of.
+ * @param[out]  refdata       Pointer to store the data to.
+ * @param[in]   timeout       Timeout for the function to return (in microseconds).
+ *
+ * @return    Indicator whether the function call was successful or a timeout occurred.
+ */
+apalExitStatus_t at42qt1050_lld_read_referencedata(const AT42QT1050Driver* at42qt1050d, const uint8_t key, uint16_t* refdata, const apalTime_t timeout)
+{
+  apalDbgAssert(at42qt1050d != NULL && at42qt1050d->i2cd != NULL);
+  apalDbgAssert(key < AT42QT1050_LLD_NUM_KEYS);
+  apalDbgAssert(refdata != NULL);
+
+  const at42qt1050_lld_register_t txbuf = at42qt1050_lld_addr_calc(AT42QT1050_LLD_REG_REFERENCEDATA_0, key);
+  uint8_t rxbuf[2];
+  const apalExitStatus_t status = apalI2CMasterTransmit(at42qt1050d->i2cd, at42qt1050d->addr, &txbuf, 1, rxbuf, 2, timeout);
+  *refdata = (rxbuf[0] << 8) | rxbuf[1];
+  return status;
+}
+
+/**
+ * @brief       Soft Reset of the device
+ *
+ * @param[in]   at42qt1050d   The AT42QT1050 driver to use.
+ * @param[in]   timeout       Timeout for the function to return (in microseconds).
+ * @param[in]   wait4wakeup   Wait for device wakeup (timeout must be > 155 ms)
+ *
+ * @return      Indicator whether the function call was successful or a timeout occurred.
+ */
+inline apalExitStatus_t at42qt1050_lld_reset_safe(const AT42QT1050Driver* at42qt1050d, const bool wait4wakeup, const apalTime_t timeout) {
+  if(wait4wakeup)
+    apalDbgAssert(timeout >= AT42QT1050_LLD_WATCHDOGTIME_MAX+AT42QT1050_LLD_INITIALIZATION_TIME_MAX);
+
+  return at42qt1050_lld_reset(at42qt1050d, timeout-(AT42QT1050_LLD_WATCHDOGTIME_MAX+AT42QT1050_LLD_INITIALIZATION_TIME_MAX), wait4wakeup);
+}
+
+/**
+ * @brief       Soft Reset of the device
+ *
+ * @param[in]   at42qt1050d   The AT42QT1050 driver to use.
+ * @param[in]   timeout       Timeout for the i2c call (in microseconds).
+ * @param[in]   wait4wakeup   Wait for device wakeup (155 ms)
+ *
+ * @return      Indicator whether the function call was successful or a timeout occurred.
+ */
+inline apalExitStatus_t at42qt1050_lld_reset(const AT42QT1050Driver* at42qt1050d, const apalTime_t timeout, const bool wait4wakeup) {
+  apalDbgAssert(at42qt1050d != NULL && at42qt1050d->i2cd != NULL);
+
+  const apalExitStatus_t status = at42qt1050_lld_write_reg(
+    at42qt1050d, AT42QT1050_LLD_REG_RESET_CALIBRATE, AT42QT1050_LLD_RESETCALIBRATE_RESET, timeout);
+  if(wait4wakeup)
+    usleep(AT42QT1050_LLD_WATCHDOGTIME_MAX+AT42QT1050_LLD_INITIALIZATION_TIME_MAX+timeout); // watchdog timer+initialization -> datasheet
+  return status;
+}
+
+/**
+ * @brief   Convert a 4 bit pulse value to the representing number of samples.
+ * @details Calculation: <#samples> = 2^(<pulse value>)
+ *
+ * @param[in]   pulse   Pulse value.
+ *
+ * @return    Resulting sample count.
+ */
+uint16_t at42qt1050_lld_pulse2samples(const uint8_t pulse)
+{
+  apalDbgAssert(pulse <= 0x0Fu);
+
+  return (1 << pulse);
+}
+
+/**
+ * @brief   Convert a desired number of samples to the according (theoretical) pulse value.
+ * @details Calculation: <pulse value> = log2(<#samples>)
+ *
+ * @param[in]   samples   Desired number of samples.
+ *
+ * @return    The (theoretical) value to set to the pulse register.
+ */
+float at42qt1050_lld_samples2pulse(const uint16_t samples)
+{
+  return log2f(samples);
+}
+
+/**
+ * @brief   Convert a 4 bit scale value to the accoring scaling factor.
+ * @details Calculation: <scaling factor> = 2^(<scale value>)
+ *
+ * @param[in]   scale   Scale value.
+ *
+ * @return    Resulting scaling factor.
+ */
+uint16_t at42qt1050_lld_scale2scaling(const uint8_t scale)
+{
+  apalDbgAssert(scale <= 0x0Fu);
+
+  return (1 << scale);
+}
+
+/**
+ * @brief   Convert a desired scaling factor to the according (theoretical) scale value.
+ * @details Calculation: <scale value> = log2(<scaling factor>
+ * )
+ * @param[in]   factor    Desired scaling factor.
+ *
+ * @return    The (theoretcial) value to set to the scale register.
+ */
+float at42qt1050_lld_scaling2scale(const uint16_t factor)
+{
+  return log2f(factor);
+}
+
+/** @} */
+
diff --git a/drivers/AT42QT1050/v1/alld_AT42QT1050.h b/drivers/AT42QT1050/v1/alld_AT42QT1050.h
new file mode 100644
index 0000000..489a30f
--- /dev/null
+++ b/drivers/AT42QT1050/v1/alld_AT42QT1050.h
@@ -0,0 +1,299 @@
+/*
+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/>.
+*/
+
+/**
+ * @file    alld_AT42QT1050.h
+ * @brief   Touch sensor macros and structures.
+ *
+ * @addtogroup lld_touch
+ * @{
+ */
+
+#ifndef AMIROLLD_AT42QT1050_H
+#define AMIROLLD_AT42QT1050_H
+
+#include <amiro-lld.h>
+
+/******************************************************************************/
+/* CONSTANTS                                                                  */
+/******************************************************************************/
+
+/**
+ * @brief   Maximum I2C frequency.
+ */
+#define AT42QT1050_LLD_I2C_MAXFREQUENCY         400000
+
+/**
+ * @brief   A falling edge indicats an interrupt.
+ */
+#define AT42QT1050_LLD_INT_EDGE                 APAL_GPIO_EDGE_FALLING
+
+/**
+ * @brief   Number of touch keys supported by AT42QT1050.
+ */
+#define AT42QT1050_LLD_NUM_KEYS                 5
+
+/**
+ * @brief   Maximum time (in microseconds) to acquire all key signals before the overflow bit of the detection status register is set.
+ */
+#define AT42QT1050_LLD_MAX_KEY_ACQUIRATION_TIME 8000
+
+/**
+ * @brief   The chip ID as can be read from the according register (constant).
+ */
+#define AT42QT1050_LLD_CHIPID                   0x46
+
+/******************************************************************************/
+/* SETTINGS                                                                   */
+/******************************************************************************/
+
+/******************************************************************************/
+/* CHECKS                                                                     */
+/******************************************************************************/
+
+/******************************************************************************/
+/* DATA STRUCTURES AND TYPES                                                  */
+/******************************************************************************/
+
+/**
+ * @brief   The AT42QT1050Driver sruct.
+ */
+typedef struct {
+  apalI2CDriver_t* i2cd;
+  apalI2Caddr_t addr;
+} AT42QT1050Driver;
+
+/**
+ * @brief   Possible I2C address configurations.
+ */
+enum {
+  AT42QT1050_LLD_I2C_ADDRSEL_LOW  = 0x0041u,  /**< ADDR_SEL pin is pulled low. */
+  AT42QT1050_LLD_I2C_ADDRSEL_HIGH = 0x0046u,  /**< ADDR_SEL pin is pulled high. */
+};
+
+/**
+ * @brief   Available register addresses of the AT42QT1050.
+ */
+typedef enum {
+  AT42QT1050_LLD_REG_CHIPID               = 0x00u,  /**<  read only */
+  AT42QT1050_LLD_REG_FIRMWAREVERSION      = 0x01u,  /**<  read only */
+  AT42QT1050_LLD_REG_DETECTIONSTATUS      = 0x02u,  /**<  read only */
+  AT42QT1050_LLD_REG_KEYSTATUS            = 0x03u,  /**<  read only */
+  AT42QT1050_LLD_REG_KEYSIGNAL_0          = 0x06u,  /**<  read only */
+  AT42QT1050_LLD_REG_KEYSIGNAL_1          = 0x08u,  /**<  read only */
+  AT42QT1050_LLD_REG_KEYSIGNAL_2          = 0x0Du,  /**<  read only */
+  AT42QT1050_LLD_REG_KEYSIGNAL_3          = 0x0Fu,  /**<  read only */
+  AT42QT1050_LLD_REG_KEYSIGNAL_4          = 0x11u,  /**<  read only */
+  AT42QT1050_LLD_REG_REFERENCEDATA_0      = 0x14u,  /**<  read only */
+  AT42QT1050_LLD_REG_REFERENCEDATA_1      = 0x16u,  /**<  read only */
+  AT42QT1050_LLD_REG_REFERENCEDATA_2      = 0x1Au,  /**<  read only */
+  AT42QT1050_LLD_REG_REFERENCEDATA_3      = 0x1Cu,  /**<  read only */
+  AT42QT1050_LLD_REG_REFERENCEDATA_4      = 0x1Eu,  /**<  read only */
+  AT42QT1050_LLD_REG_NEGATIVETHRESHOLD_0  = 0x21u,  /**< read/write */
+  AT42QT1050_LLD_REG_NEGATIVETHRESHOLD_1  = 0x22u,  /**< read/write */
+  AT42QT1050_LLD_REG_NEGATIVETHRESHOLD_2  = 0x24u,  /**< read/write */
+  AT42QT1050_LLD_REG_NEGATIVETHRESHOLD_3  = 0x25u,  /**< read/write */
+  AT42QT1050_LLD_REG_NEGATIVETHRESHOLD_4  = 0x26u,  /**< read/write */
+  AT42QT1050_LLD_REG_PULSE_SCALE_0        = 0x28u,  /**< read/write */
+  AT42QT1050_LLD_REG_PULSE_SCALE_1        = 0x29u,  /**< read/write */
+  AT42QT1050_LLD_REG_PULSE_SCALE_2        = 0x2Bu,  /**< read/write */
+  AT42QT1050_LLD_REG_PULSE_SCALE_3        = 0x2Cu,  /**< read/write */
+  AT42QT1050_LLD_REG_PULSE_SCALE_4        = 0x2Du,  /**< read/write */
+  AT42QT1050_LLD_REG_INTEGRATOR_AKS_0     = 0x2Fu,  /**< read/write */
+  AT42QT1050_LLD_REG_INTEGRATOR_AKS_1     = 0x30u,  /**< read/write */
+  AT42QT1050_LLD_REG_INTEGRATOR_AKS_2     = 0x32u,  /**< read/write */
+  AT42QT1050_LLD_REG_INTEGRATOR_AKS_3     = 0x33u,  /**< read/write */
+  AT42QT1050_LLD_REG_INTEGRATOR_AKS_4     = 0x34u,  /**< read/write */
+  AT42QT1050_LLD_REG_CHARGESHAREDELAY_0   = 0x36u,  /**< read/write */
+  AT42QT1050_LLD_REG_CHARGESHAREDELAY_1   = 0x37u,  /**< read/write */
+  AT42QT1050_LLD_REG_CHARGESHAREDELAY_2   = 0x39u,  /**< read/write */
+  AT42QT1050_LLD_REG_CHARGESHAREDELAY_3   = 0x3Au,  /**< read/write */
+  AT42QT1050_LLD_REG_CHARGESHAREDELAY_4   = 0x3Bu,  /**< read/write */
+  AT42QT1050_LLD_REG_FINFOUTMAXCALGUARD   = 0x3Cu,  /**< read/write */
+  AT42QT1050_LLD_REG_LOWPOWERMODE         = 0x3Du,  /**< read/write */
+  AT42QT1050_LLD_REG_MAXONDURATION        = 0x3Eu,  /**< read/write */
+  AT42QT1050_LLD_REG_RESET_CALIBRATE      = 0x3Fu,  /**< read/write */
+} at42qt1050_lld_register_t;
+
+/**
+ * @brief   Firmware version register structure.
+ */
+typedef union {
+  uint8_t raw;
+  struct {
+    uint8_t minor : 4;
+    uint8_t major : 4;
+  };
+} at42qt1050_lld_firmwarereg_t;
+
+
+/**
+ * @brief   Relevant bits of the detection status register.
+ */
+typedef enum {
+  AT42QT1050_LLD_DETECTIONSTATUS_TOUCH      = 0x01u,  /**< Set if any keys are in detect.  */
+  AT42QT1050_LLD_DETECTIONSTATUS_OVERFLOW   = 0x40u,  /**< Set if the time to acquire all key signals exceeds 8ms. */
+  AT42QT1050_LLD_DETECTIONSTATUS_CALIBRATE  = 0x80u,  /**< Set during calibration sequence. */
+} at42qt1050_lld_detectionstatusreg_t;
+
+/**
+ * @brief   Key status register masks.
+ */
+typedef enum {
+  AT42QT1050_LLD_KEYSTATUS_KEY0 = 0x02u,
+  AT42QT1050_LLD_KEYSTATUS_KEY1 = 0x04u,
+  AT42QT1050_LLD_KEYSTATUS_KEY2 = 0x10u,
+  AT42QT1050_LLD_KEYSTATUS_KEY3 = 0x20u,
+  AT42QT1050_LLD_KEYSTATUS_KEY4 = 0x40u,
+} at42qt1050_lld_keystatusreg_t;
+
+/**
+ * @brief   Pulse/Scale register structure.
+ */
+typedef union {
+  uint8_t raw;
+  struct {
+    uint8_t scale : 4;
+    uint8_t pulse : 4;
+  };
+} at42qt1050_lld_pulsescalereg_t;
+
+/**
+ * @brief   Detection Integrator (DI) / AKS register structure.
+ */
+typedef union {
+  uint8_t raw;
+  struct {
+    uint8_t aks : 2;
+    uint8_t detection_integrator : 6;
+  };
+} at42qt1050_lld_detectionintegratoraksreg_t;
+
+/**
+ * @brief   Charge share delay constant sclaing factor.
+ * @details Values in the charge share delay registers are multiplied by this factor.
+ *          Unit is microseconds (µs).
+ */
+#define AT42QT1050_LLD_CHARGESHAREDELAY_FACTOR  2.5f
+
+/**
+ * @brief   FastIn / FastOutDI / Max Cal / Guard Channel register masks.
+ */
+typedef enum {
+  AT42QT1050_LLD_FINFOUTMAXCALGUARD_GUARD   = 0x0Fu,
+  AT42QT1050_LLD_FINFOUTMAXCALGUARD_MAXCAL  = 0x10u,
+  AT42QT1050_LLD_FINFOUTMAXCALGUARD_FO      = 0x20u,
+  AT42QT1050_LLD_FINFOUTMAXCALGUARD_FI      = 0x40u,
+} at42qt1050_lld_finfoutmaxcalguardreg_t;
+
+/**
+ * @brief   Low power mode constant scaling factor.
+ * @details The values in the low poer mode register is multiplied by this factor.
+ *          Unit is microseconds (µs).
+ * @note    Setting the power mode scaling register value to zero makes the AT42QT1050 enter deep-sleep mode.
+ */
+#define AT42QT1050_LLD_LOWPOWER_FACTOR          8000
+
+/**
+ * @brief   Man on duration constant scaling factor.
+ * @details The value in the max on duration register is multiplied by this factor.
+ *          Unit is microseconds (µs).
+ */
+#define AT42QT1050_LLD_MAXONDURATION_FACTOR     160000
+
+/**
+ * @brief   RESET / Calibrate register masks.
+ */
+typedef enum {
+  AT42QT1050_LLD_RESETCALIBRATE_CALIBRATE = 0x7Fu,
+  AT42QT1050_LLD_RESETCALIBRATE_RESET     = 0x80u,
+} at42qt1050_lld_resetcalibratereg_t;
+
+/******************************************************************************/
+/* MACROS                                                                     */
+/******************************************************************************/
+
+/******************************************************************************/
+/* EXTERN DECLARATIONS                                                        */
+/******************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  apalExitStatus_t at42qt1050_lld_read_reg(const AT42QT1050Driver* at42qt1050d, const at42qt1050_lld_register_t reg, uint8_t* const data, const apalTime_t timeout);
+  apalExitStatus_t at42qt1050_lld_write_reg(const AT42QT1050Driver* at42qt1050d, const at42qt1050_lld_register_t reg, const uint8_t data, const apalTime_t timeout);
+
+  apalExitStatus_t at42qt1050_lld_read_keyssignal(const AT42QT1050Driver* at42qt1050d, const uint8_t key, uint16_t* signal, const apalTime_t timeout);
+  apalExitStatus_t at42qt1050_lld_read_referencedata(const AT42QT1050Driver* at42qt1050d, const uint8_t key, uint16_t* refdata, const apalTime_t timeout);
+
+  apalExitStatus_t at42qt1050_lld_reset_safe(const AT42QT1050Driver* at42qt1050d, const bool wait4wakeup, const apalTime_t timeout);
+  apalExitStatus_t at42qt1050_lld_reset(const AT42QT1050Driver* at42qt1050d, const apalTime_t timeout, const bool wait4wakeup);
+
+  uint16_t at42qt1050_lld_pulse2samples(const uint8_t pulse);
+  float at42qt1050_lld_samples2pulse(const uint16_t samples);
+  uint16_t at42qt1050_lld_scale2scaling(const uint8_t scale);
+  float at42qt1050_lld_scaling2scale(const uint16_t factor);
+
+
+  /**
+   * @brief   Calculates n-th address based on address of register 0.
+   * @details Calculation: <scale value> = log2(<scaling factor>
+   * )
+   * @param[in]   base    Base address = frist register
+   * @param[in]   inc     Jump to the next register inc times
+   *
+   * @return    Calculated register address
+   */
+  inline at42qt1050_lld_register_t at42qt1050_lld_addr_calc(const at42qt1050_lld_register_t base, const uint8_t inc) {
+    apalDbgAssert(inc < 5);
+
+    uint8_t double_result = 0; //16bit access
+
+    switch (base) {
+      case AT42QT1050_LLD_REG_KEYSIGNAL_0:         //2 4 2 2
+      case AT42QT1050_LLD_REG_REFERENCEDATA_0:     //2 4 2 2
+        double_result = 1;
+        __attribute__((fallthrough));
+      case AT42QT1050_LLD_REG_NEGATIVETHRESHOLD_0: //1 2 1 1
+      case AT42QT1050_LLD_REG_PULSE_SCALE_0:       //1 2 1 1
+      case AT42QT1050_LLD_REG_INTEGRATOR_AKS_0:    //1 2 1 1
+      case AT42QT1050_LLD_REG_CHARGESHAREDELAY_0:  //1 2 1 1
+      {
+        uint8_t increase = ((inc>1)?inc+1:inc);
+        return (at42qt1050_lld_register_t) (((uint8_t) base)+(increase << double_result));
+      }
+      default:
+      {
+        apalDbgPrintf("invalid base register 0x%04X\n", base);
+        return (at42qt1050_lld_register_t) 0xFF; //does not exist
+      }
+    }
+  }
+
+#ifdef __cplusplus
+}
+#endif
+
+/******************************************************************************/
+/* INLINE FUNCTIONS                                                           */
+/******************************************************************************/
+
+#endif /* AMIROLLD_AT42QT1050_H */
+
+/** @} */
+
diff --git a/drivers/DW1000/v1/alld_DW1000.c b/drivers/DW1000/v1/alld_DW1000.c
new file mode 100644
index 0000000..3965c18
--- /dev/null
+++ b/drivers/DW1000/v1/alld_DW1000.c
@@ -0,0 +1,4563 @@
+/*
+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/>.
+*/
+
+/*! ------------------------------------------------------------------------------------------------------------------
+ * @file    deca_device.c
+ * @brief   Decawave device configuration and control functions
+ *
+ * @attention
+ *
+ * Copyright 2013 (c) Decawave Ltd, Dublin, Ireland.
+ *
+ * All rights reserved.
+ *
+ */
+
+#include <alld_DW1000.h>
+#include <alld_DW1000_regs.h>
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+
+// HW dependent implementation (see bottom of file)
+static int writetospi(uint16_t headerLength,
+               const	uint8_t *headerBuffer,
+               uint32_t bodyLength,
+               const	uint8_t *bodyBuffer);
+
+static int readfromspi(uint16_t headerLength,
+                const uint8_t *headerBuffer,
+                uint32_t readlength,
+                uint8_t *readBuffer);
+
+
+// Defines for enable_clocks function
+#define FORCE_SYS_XTI  0
+#define ENABLE_ALL_SEQ 1
+#define FORCE_SYS_PLL  2
+#define READ_ACC_ON    7
+#define READ_ACC_OFF   8
+#define FORCE_OTP_ON   11
+#define FORCE_OTP_OFF  12
+#define FORCE_TX_PLL   13
+#define FORCE_LDE      14
+
+// Defines for ACK request bitmask in DATA and MAC COMMAND frame control (first byte) - Used to detect AAT bit wrongly set.
+#define FCTRL_ACK_REQ_MASK 0x20
+// Frame control maximum length in bytes.
+#define FCTRL_LEN_MAX 2
+
+
+typedef struct {
+    uint32_t lo32;
+    uint16_t target[NUM_PRF];
+} agc_cfg_struct ;
+
+extern const agc_cfg_struct agc_config ;
+
+//SFD threshold settings for 110k, 850k, 6.8Mb standard and non-standard
+extern const uint16_t sftsh[NUM_BR][NUM_SFD];
+
+extern const uint16_t dtune1[NUM_PRF];
+
+#define XMLPARAMS_VERSION   (1.17f)
+
+extern const uint32_t fs_pll_cfg[NUM_CH];
+extern const uint8_t fs_pll_tune[NUM_CH];
+extern const uint8_t rx_config[NUM_BW];
+extern const uint32_t tx_config[NUM_CH];
+extern const uint8_t dwnsSFDlen[NUM_BR]; //length of SFD for each of the bitrates
+extern const uint32_t digital_bb_config[NUM_PRF][NUM_PACS];
+//extern const uint8_t chan_idx[NUM_CH_SUPPORTED]; // move to header file
+extern const double txpwr_compensation[NUM_CH];
+
+#define PEAK_MULTPLIER  (0x60) //3 -> (0x3 * 32) & 0x00E0
+#define N_STD_FACTOR    (13)
+#define LDE_PARAM1      (PEAK_MULTPLIER | N_STD_FACTOR)
+
+#define LDE_PARAM3_16 (0x1607)
+#define LDE_PARAM3_64 (0x0607)
+
+#define MIXER_GAIN_STEP (0.5)
+#define DA_ATTN_STEP    (2.5)
+
+// #define DWT_API_ERROR_CHECK     // define so API checks config input parameters
+
+//-----------------------------------------
+// map the channel number to the index in the configuration arrays below
+// 0th element is chan 1, 1st is chan 2, 2nd is chan 3, 3rd is chan 4, 4th is chan 5, 5th is chan 7
+const uint8_t chan_idx[NUM_CH_SUPPORTED] = {0, 0, 1, 2, 3, 4, 0, 5};
+
+//-----------------------------------------
+const uint32_t tx_config[NUM_CH] =
+{
+    RF_TXCTRL_CH1,
+    RF_TXCTRL_CH2,
+    RF_TXCTRL_CH3,
+    RF_TXCTRL_CH4,
+    RF_TXCTRL_CH5,
+    RF_TXCTRL_CH7,
+};
+
+//Frequency Synthesiser - PLL configuration
+const uint32_t fs_pll_cfg[NUM_CH] =
+{
+    FS_PLLCFG_CH1,
+    FS_PLLCFG_CH2,
+    FS_PLLCFG_CH3,
+    FS_PLLCFG_CH4,
+    FS_PLLCFG_CH5,
+    FS_PLLCFG_CH7
+};
+
+//Frequency Synthesiser - PLL tuning
+const uint8_t fs_pll_tune[NUM_CH] =
+{
+    FS_PLLTUNE_CH1,
+    FS_PLLTUNE_CH2,
+    FS_PLLTUNE_CH3,
+    FS_PLLTUNE_CH4,
+    FS_PLLTUNE_CH5,
+    FS_PLLTUNE_CH7
+};
+
+//bandwidth configuration
+const uint8_t rx_config[NUM_BW] =
+{
+    RF_RXCTRLH_NBW,
+    RF_RXCTRLH_WBW
+};
+
+
+const agc_cfg_struct agc_config =
+{
+    AGC_TUNE2_VAL,
+    { AGC_TUNE1_16M , AGC_TUNE1_64M }  //adc target
+};
+
+//DW non-standard SFD length for 110k, 850k and 6.81M
+const uint8_t dwnsSFDlen[NUM_BR] =
+{
+    DW_NS_SFD_LEN_110K,
+    DW_NS_SFD_LEN_850K,
+    DW_NS_SFD_LEN_6M8
+};
+
+// SFD Threshold
+const uint16_t sftsh[NUM_BR][NUM_SFD] =
+{
+    {
+        DRX_TUNE0b_110K_STD,
+        DRX_TUNE0b_110K_NSTD
+    },
+    {
+        DRX_TUNE0b_850K_STD,
+        DRX_TUNE0b_850K_NSTD
+    },
+    {
+        DRX_TUNE0b_6M8_STD,
+        DRX_TUNE0b_6M8_NSTD
+    }
+};
+
+const uint16_t dtune1[NUM_PRF] =
+{
+    DRX_TUNE1a_PRF16,
+    DRX_TUNE1a_PRF64
+};
+
+const uint32_t digital_bb_config[NUM_PRF][NUM_PACS] =
+{
+    {
+        DRX_TUNE2_PRF16_PAC8,
+        DRX_TUNE2_PRF16_PAC16,
+        DRX_TUNE2_PRF16_PAC32,
+        DRX_TUNE2_PRF16_PAC64
+    },
+    {
+        DRX_TUNE2_PRF64_PAC8,
+        DRX_TUNE2_PRF64_PAC16,
+        DRX_TUNE2_PRF64_PAC32,
+        DRX_TUNE2_PRF64_PAC64
+    }
+};
+
+const uint16_t lde_replicaCoeff[PCODES] =
+{
+    0, // No preamble code 0
+    LDE_REPC_PCODE_1,
+    LDE_REPC_PCODE_2,
+    LDE_REPC_PCODE_3,
+    LDE_REPC_PCODE_4,
+    LDE_REPC_PCODE_5,
+    LDE_REPC_PCODE_6,
+    LDE_REPC_PCODE_7,
+    LDE_REPC_PCODE_8,
+    LDE_REPC_PCODE_9,
+    LDE_REPC_PCODE_10,
+    LDE_REPC_PCODE_11,
+    LDE_REPC_PCODE_12,
+    LDE_REPC_PCODE_13,
+    LDE_REPC_PCODE_14,
+    LDE_REPC_PCODE_15,
+    LDE_REPC_PCODE_16,
+    LDE_REPC_PCODE_17,
+    LDE_REPC_PCODE_18,
+    LDE_REPC_PCODE_19,
+    LDE_REPC_PCODE_20,
+    LDE_REPC_PCODE_21,
+    LDE_REPC_PCODE_22,
+    LDE_REPC_PCODE_23,
+    LDE_REPC_PCODE_24
+};
+
+const double txpwr_compensation[NUM_CH] = {
+    0.0,
+    0.035,
+    0.0,
+    0.0,
+    0.065,
+    0.0
+};
+
+
+const uint8_t chan_idxnb[NUM_CH_SUPPORTED] = {0, 0, 1, 2, 0, 3, 0, 0}; //only channels 1,2,3 and 5 are in the narrow band tables
+const uint8_t chan_idxwb[NUM_CH_SUPPORTED] = {0, 0, 0, 0, 0, 0, 0, 1}; //only channels 4 and 7 are in in the wide band tables
+
+//---------------------------------------------------------------------------------------------------------------------------
+// Range Bias Correction TABLES of range values in integer units of 25 CM, for 8-bit unsigned storage, MUST END IN 255 !!!!!!
+//---------------------------------------------------------------------------------------------------------------------------
+
+// offsets to nearest centimeter for index 0, all rest are +1 cm per value
+
+#define CM_OFFSET_16M_NB    (-23)   // for normal band channels at 16 MHz PRF
+#define CM_OFFSET_16M_WB    (-28)   // for wider  band channels at 16 MHz PRF
+#define CM_OFFSET_64M_NB    (-17)   // for normal band channels at 64 MHz PRF
+#define CM_OFFSET_64M_WB    (-30)   // for wider  band channels at 64 MHz PRF
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// range25cm16PRFnb: Range Bias Correction table for narrow band channels at 16 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
+//---------------------------------------------------------------------------------------------------------------------------
+
+const uint8_t range25cm16PRFnb[4][NUM_16M_OFFSET] =
+{
+    // ch 1 - range25cm16PRFnb
+    {
+           1,
+           3,
+           4,
+           5,
+           7,
+           9,
+          11,
+          12,
+          13,
+          15,
+          18,
+          20,
+          23,
+          25,
+          28,
+          30,
+          33,
+          36,
+          40,
+          43,
+          47,
+          50,
+          54,
+          58,
+          63,
+          66,
+          71,
+          76,
+          82,
+          89,
+          98,
+         109,
+         127,
+         155,
+         222,
+         255,
+         255
+    },
+
+    // ch 2 - range25cm16PRFnb
+    {
+           1,
+           2,
+           4,
+           5,
+           6,
+           8,
+           9,
+          10,
+          12,
+          13,
+          15,
+          18,
+          20,
+          22,
+          24,
+          27,
+          29,
+          32,
+          35,
+          38,
+          41,
+          44,
+          47,
+          51,
+          55,
+          58,
+          62,
+          66,
+          71,
+          78,
+          85,
+          96,
+         111,
+         135,
+         194,
+         240,
+         255
+    },
+
+    // ch 3 - range25cm16PRFnb
+    {
+           1,
+           2,
+           3,
+           4,
+           5,
+           7,
+           8,
+           9,
+          10,
+          12,
+          14,
+          16,
+          18,
+          20,
+          22,
+          24,
+          26,
+          28,
+          31,
+          33,
+          36,
+          39,
+          42,
+          45,
+          49,
+          52,
+          55,
+          59,
+          63,
+          69,
+          76,
+          85,
+          98,
+         120,
+         173,
+         213,
+         255
+    },
+
+    // ch 5 - range25cm16PRFnb
+    {
+           1,
+           1,
+           2,
+           3,
+           4,
+           5,
+           6,
+           6,
+           7,
+           8,
+           9,
+          11,
+          12,
+          14,
+          15,
+          16,
+          18,
+          20,
+          21,
+          23,
+          25,
+          27,
+          29,
+          31,
+          34,
+          36,
+          38,
+          41,
+          44,
+          48,
+          53,
+          59,
+          68,
+          83,
+         120,
+         148,
+         255
+    }
+}; // end range25cm16PRFnb
+
+
+//---------------------------------------------------------------------------------------------------------------------------
+// range25cm16PRFwb: Range Bias Correction table for wide band channels at 16 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
+//---------------------------------------------------------------------------------------------------------------------------
+
+const uint8_t range25cm16PRFwb[2][NUM_16M_OFFSETWB] =
+{
+    // ch 4 - range25cm16PRFwb
+    {
+           7,
+           7,
+           8,
+           9,
+           9,
+          10,
+          11,
+          11,
+          12,
+          13,
+          14,
+          15,
+          16,
+          17,
+          18,
+          19,
+          20,
+          21,
+          22,
+          23,
+          24,
+          26,
+          27,
+          28,
+          30,
+          31,
+          32,
+          34,
+          36,
+          38,
+          40,
+          42,
+          44,
+          46,
+          48,
+          50,
+          52,
+          55,
+          57,
+          59,
+          61,
+          63,
+          66,
+          68,
+          71,
+          74,
+          78,
+          81,
+          85,
+          89,
+          94,
+          99,
+         104,
+         110,
+         116,
+         123,
+         130,
+         139,
+         150,
+         164,
+         182,
+         207,
+         238,
+         255,
+         255,
+         255,
+         255,
+         255
+    },
+
+    // ch 7 - range25cm16PRFwb
+    {
+           4,
+           5,
+           5,
+           5,
+           6,
+           6,
+           7,
+           7,
+           7,
+           8,
+           9,
+           9,
+          10,
+          10,
+          11,
+          11,
+          12,
+          13,
+          13,
+          14,
+          15,
+          16,
+          17,
+          17,
+          18,
+          19,
+          20,
+          21,
+          22,
+          23,
+          25,
+          26,
+          27,
+          29,
+          30,
+          31,
+          32,
+          34,
+          35,
+          36,
+          38,
+          39,
+          40,
+          42,
+          44,
+          46,
+          48,
+          50,
+          52,
+          55,
+          58,
+          61,
+          64,
+          68,
+          72,
+          75,
+          80,
+          85,
+          92,
+         101,
+         112,
+         127,
+         147,
+         168,
+         182,
+         194,
+         205,
+         255
+    }
+}; // end range25cm16PRFwb
+
+//---------------------------------------------------------------------------------------------------------------------------
+// range25cm64PRFnb: Range Bias Correction table for narrow band channels at 64 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
+//---------------------------------------------------------------------------------------------------------------------------
+
+const uint8_t range25cm64PRFnb[4][NUM_64M_OFFSET] =
+{
+    // ch 1 - range25cm64PRFnb
+    {
+           1,
+           2,
+           2,
+           3,
+           4,
+           5,
+           7,
+          10,
+          13,
+          16,
+          19,
+          22,
+          24,
+          27,
+          30,
+          32,
+          35,
+          38,
+          43,
+          48,
+          56,
+          78,
+         101,
+         120,
+         157,
+         255
+    },
+
+    // ch 2 - range25cm64PRFnb
+    {
+           1,
+           2,
+           2,
+           3,
+           4,
+           4,
+           6,
+           9,
+          12,
+          14,
+          17,
+          19,
+          21,
+          24,
+          26,
+          28,
+          31,
+          33,
+          37,
+          42,
+          49,
+          68,
+          89,
+         105,
+         138,
+         255
+    },
+
+    // ch 3 - range25cm64PRFnb
+    {
+           1,
+           1,
+           2,
+           3,
+           3,
+           4,
+           5,
+           8,
+          10,
+          13,
+          15,
+          17,
+          19,
+          21,
+          23,
+          25,
+          27,
+          30,
+          33,
+          37,
+          44,
+          60,
+          79,
+          93,
+         122,
+         255
+    },
+
+    // ch 5 - range25cm64PRFnb
+    {
+           1,
+           1,
+           1,
+           2,
+           2,
+           3,
+           4,
+           6,
+           7,
+           9,
+          10,
+          12,
+          13,
+          15,
+          16,
+          17,
+          19,
+          21,
+          23,
+          26,
+          30,
+          42,
+          55,
+          65,
+          85,
+         255
+    }
+}; // end range25cm64PRFnb
+
+//---------------------------------------------------------------------------------------------------------------------------
+// range25cm64PRFwb: Range Bias Correction table for wide band channels at 64 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
+//---------------------------------------------------------------------------------------------------------------------------
+
+const uint8_t range25cm64PRFwb[2][NUM_64M_OFFSETWB] =
+{
+    // ch 4 - range25cm64PRFwb
+    {
+           7,
+           8,
+           8,
+           9,
+           9,
+          10,
+          11,
+          12,
+          13,
+          13,
+          14,
+          15,
+          16,
+          16,
+          17,
+          18,
+          19,
+          19,
+          20,
+          21,
+          22,
+          24,
+          25,
+          27,
+          28,
+          29,
+          30,
+          32,
+          33,
+          34,
+          35,
+          37,
+          39,
+          41,
+          43,
+          45,
+          48,
+          50,
+          53,
+          56,
+          60,
+          64,
+          68,
+          74,
+          81,
+          89,
+          98,
+         109,
+         122,
+         136,
+         146,
+         154,
+         162,
+         178,
+         220,
+         249,
+         255,
+         255,
+         255
+    },
+
+    // ch 7 - range25cm64PRFwb
+    {
+           4,
+           5,
+           5,
+           5,
+           6,
+           6,
+           7,
+           7,
+           8,
+           8,
+           9,
+           9,
+          10,
+          10,
+          10,
+          11,
+          11,
+          12,
+          13,
+          13,
+          14,
+          15,
+          16,
+          16,
+          17,
+          18,
+          19,
+          19,
+          20,
+          21,
+          22,
+          23,
+          24,
+          25,
+          26,
+          28,
+          29,
+          31,
+          33,
+          35,
+          37,
+          39,
+          42,
+          46,
+          50,
+          54,
+          60,
+          67,
+          75,
+          83,
+          90,
+          95,
+         100,
+         110,
+         135,
+         153,
+         172,
+         192,
+         255
+    }
+}; // end range25cm64PRFwb
+
+
+/*! ------------------------------------------------------------------------------------------------------------------
+ * Function: dwt_getrangebias()
+ *
+ * Description: This function is used to return the range bias correction need for TWR with DW1000 units.
+ *
+ * input parameters:	
+ * @param chan  - specifies the operating channel (e.g. 1, 2, 3, 4, 5, 6 or 7) 
+ * @param range - the calculated distance before correction
+ * @param prf	- this is the PRF e.g. DWT_PRF_16M or DWT_PRF_64M
+ *
+ * output parameters
+ *
+ * returns correction needed in meters
+ */
+double dwt_getrangebias(uint8_t chan, float range, uint8_t prf)
+{
+    //first get the lookup index that corresponds to given range for a particular channel at 16M PRF
+    int i = 0 ;
+    int chanIdx ;
+    int cmoffseti ;                                 // integer number of CM offset
+
+    double mOffset ;                                // final offset result in metres
+
+    // NB: note we may get some small negitive values e.g. up to -50 cm.
+
+    int rangeint25cm = (int) ((double)range * 4.00) ;       // convert range to integer number of 25cm values.
+
+    if (rangeint25cm > 255) rangeint25cm = 255 ;    // make sure it matches largest value in table (all tables end in 255 !!!!)
+
+    if (prf == DWT_PRF_16M)
+    {
+        switch(chan)
+        {
+            case 4:
+            case 7:
+            {
+                chanIdx = chan_idxwb[chan];
+                while (rangeint25cm > range25cm16PRFwb[chanIdx][i]) i++ ;       // find index in table corresponding to range
+                cmoffseti = i + CM_OFFSET_16M_WB ;                              // nearest centimeter correction
+            }
+            break;
+            default:
+            {
+                chanIdx = chan_idxnb[chan];
+                while (rangeint25cm > range25cm16PRFnb[chanIdx][i]) i++ ;       // find index in table corresponding to range
+                cmoffseti = i + CM_OFFSET_16M_NB ;                              // nearest centimeter correction
+            }
+        }//end of switch
+    }
+    else // 64M PRF
+    {
+        switch(chan)
+        {
+            case 4:
+            case 7:
+            {
+                chanIdx = chan_idxwb[chan];
+                while (rangeint25cm > range25cm64PRFwb[chanIdx][i]) i++ ;       // find index in table corresponding to range
+                cmoffseti = i + CM_OFFSET_64M_WB ;                              // nearest centimeter correction
+            }
+            break;
+            default:
+            {
+                chanIdx = chan_idxnb[chan];
+                while (rangeint25cm > range25cm64PRFnb[chanIdx][i]) i++ ;       // find index in table corresponding to range
+                cmoffseti = i + CM_OFFSET_64M_NB ;                              // nearest centimeter correction
+            }
+        }//end of switch
+    } // end else
+
+
+    mOffset = (double) cmoffseti ;                                       // offset result in centimmetres
+
+    mOffset *= 0.01 ;                                                   // convert to metres
+
+    return (mOffset) ;
+}
+
+// -------------------------------------------------------------------------------------------------------------------
+//
+// Internal functions for controlling and configuring the device
+//
+// -------------------------------------------------------------------------------------------------------------------
+
+// Enable and Configure specified clocks
+void _dwt_enableclocks(int clocks) ;
+// Configure the ucode (FP algorithm) parameters
+void _dwt_configlde(int prf);
+// Load ucode from OTP/ROM
+void _dwt_loaducodefromrom(void);
+// Read non-volatile memory
+uint32_t _dwt_otpread(uint32_t address);
+// Program the non-volatile memory
+int32_t _dwt_otpprogword32(uint32_t data, uint16_t address);
+// Upload the device configuration into always on memory
+void _dwt_aonarrayupload(void);
+// -------------------------------------------------------------------------------------------------------------------
+
+/*!
+ * Static data for DW1000 DecaWave Transceiver control
+ */
+
+static dwt_local_data_t dw1000local[DWT_NUM_DW_DEV] ; // Static local device data, can be an array to support multiple DW1000 testing applications/platforms
+static dwt_local_data_t *pdw1000local = dw1000local ; // Static local data structure pointer
+
+
+/*! ------------------------------------------------------------------------------------------------------------------
+ * @fn dwt_setdevicedataptr()
+ *
+ * @brief This function sets the local data structure pointer to point to the structure in the local array as given by the index.
+ *
+ * input parameters
+ * @param index    - selects the array object to point to. Must be within the array bounds, i.e. < DWT_NUM_DW_DEV
+ *
+ * output parameters
+ *
+ * returns DWT_SUCCESS for success, or DWT_ERROR for error
+ */
+int dwt_setdevicedataptr(unsigned int index)
+{
+    // Check the index is within the array bounds
+    if (DWT_NUM_DW_DEV > index) // return error if index outside the array bounds
+    {
+        return DWT_ERROR ;
+    }
+
+    pdw1000local = &dw1000local[index];
+
+    return DWT_SUCCESS ;
+}
+
+/*! ------------------------------------------------------------------------------------------------------------------
+ * @fn dwt_initialise()
+ *
+ * @brief This function initiates communications with the DW1000 transceiver
+ * and reads its DEV_ID register (address 0x00) to verify the IC is one supported
+ * by this software (e.g. DW1000 32-bit device ID value is 0xDECA0130).  Then it
+ * does any initial once only device configurations needed for use and initialises
+ * as necessary any static data items belonging to this low-level driver.
+ *
+ * NOTES:
+ * 1.this function needs to be run before dwt_configuresleep, also the SPI frequency has to be < 3MHz
+ * 2.it also reads and applies LDO tune and crystal trim values from OTP memory
+ *
+ * input parameters
+ * @param config    -   specifies what configuration to load
+ *                  DWT_LOADUCODE     0x1 - load the LDE microcode from ROM - enabled accurate RX timestamp
+ *                  DWT_LOADNONE      0x0 - do not load any values from OTP memory
+ *
+ * output parameters
+ *
+ * returns DWT_SUCCESS for success, or DWT_ERROR for error
+ */
+// OTP addresses definitions
+#define LDOTUNE_ADDRESS (0x04)
+#define PARTID_ADDRESS (0x06)
+#define LOTID_ADDRESS  (0x07)
+#define VBAT_ADDRESS   (0x08)
+#define VTEMP_ADDRESS  (0x09)
+#define XTRIM_ADDRESS  (0x1E)
+
+int dwt_initialise(const uint16_t config, DW1000Driver* drv)
+{
+    uint16_t otp_addr = 0;
+    uint32_t ldo_tune = 0;
+
+    pdw1000local->dblbuffon = 0; // Double buffer mode off by default
+    pdw1000local->wait4resp = 0;
+    pdw1000local->sleep_mode = 0;
+
+    pdw1000local->cbTxDone = NULL;
+    pdw1000local->cbRxOk = NULL;
+    pdw1000local->cbRxTo = NULL;
+    pdw1000local->cbRxErr = NULL;
+
+    pdw1000local->driver = drv;
+
+    // Read and validate device ID return -1 if not recognised
+    if (DWT_DEVICE_ID != dwt_readdevid()) // MP IC ONLY (i.e. DW1000) FOR THIS CODE
+    {
+        return DWT_ERROR ;
+    }
+
+    // Make sure the device is completely reset before starting initialisation
+    dwt_softreset();
+
+    _dwt_enableclocks(FORCE_SYS_XTI); // NOTE: set system clock to XTI - this is necessary to make sure the values read by _dwt_otpread are reliable
+
+    // Configure the CPLL lock detect
+    dwt_write8bitoffsetreg(EXT_SYNC_ID, EC_CTRL_OFFSET, EC_CTRL_PLLLCK);
+
+    // Read OTP revision number
+    otp_addr = _dwt_otpread(XTRIM_ADDRESS) & 0xffff;        // Read 32 bit value, XTAL trim val is in low octet-0 (5 bits)
+    pdw1000local->otprev = (otp_addr >> 8) & 0xff;            // OTP revision is next byte
+
+    // Load LDO tune from OTP and kick it if there is a value actually programmed.
+    ldo_tune = _dwt_otpread(LDOTUNE_ADDRESS);
+    if((ldo_tune & 0xFF) != 0)
+    {
+        // Kick LDO tune
+        dwt_write8bitoffsetreg(OTP_IF_ID, OTP_SF, OTP_SF_LDO_KICK); // Set load LDE kick bit
+        pdw1000local->sleep_mode |= AON_WCFG_ONW_LLDO; // LDO tune must be kicked at wake-up
+    }
+
+    // Load Part and Lot ID from OTP
+    pdw1000local->partID = _dwt_otpread(PARTID_ADDRESS);
+    pdw1000local->lotID = _dwt_otpread(LOTID_ADDRESS);
+
+    // XTAL trim value is set in OTP for DW1000 module and EVK/TREK boards but that might not be the case in a custom design
+    pdw1000local->init_xtrim = otp_addr & 0x1F;
+    if (!pdw1000local->init_xtrim) // A value of 0 means that the crystal has not been trimmed
+    {
+        pdw1000local->init_xtrim = FS_XTALT_MIDRANGE ; // Set to mid-range if no calibration value inside
+    }
+    // Configure XTAL trim
+    dwt_setxtaltrim(pdw1000local->init_xtrim);
+
+    // Load leading edge detect code
+    if(config & DWT_LOADUCODE)
+    {
+        _dwt_loaducodefromrom();
+        pdw1000local->sleep_mode |= AON_WCFG_ONW_LLDE; // microcode must be loaded at wake-up
+    }
+    else // Should disable the LDERUN enable bit in 0x36, 0x4
+    {
+        uint16_t rega = dwt_read16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET+1) ;
+        rega &= 0xFDFF ; // Clear LDERUN bit
+        dwt_write16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET+1, rega) ;
+    }
+
+    _dwt_enableclocks(ENABLE_ALL_SEQ); // Enable clocks for sequencing
+
+    // The 3 bits in AON CFG1 register must be cleared to ensure proper operation of the DW1000 in DEEPSLEEP mode.
+    dwt_write8bitoffsetreg(AON_ID, AON_CFG1_OFFSET, 0x00);
+
+    // Read system register / store local copy
+    pdw1000local->sysCFGreg = dwt_read32bitreg(SYS_CFG_ID) ; // Read sysconfig register
+
+    return DWT_SUCCESS ;
+
+} // end dwt_initialise()
+
+/*! ------------------------------------------------------------------------------------------------------------------
+ * @fn dwt_otprevision()
+ *
+ * @brief This is used to return the read OTP revision
+ *
+ * NOTE: dwt_initialise() must be called prior to this function so that it can return a relevant value.
+ *
+ * input parameters
+ *
+ * output parameters
+ *
+ * returns the read OTP revision value
+ */
+uint8_t dwt_otprevision(void)
+{
+    return pdw1000local->otprev ;
+}
+
+/*! ------------------------------------------------------------------------------------------------------------------
+ * @fn dwt_setfinegraintxseq()
+ *
+ * @brief This function enables/disables the fine grain TX sequencing (enabled by default).
+ *
+ * input parameters
+ * @param enable - 1 to enable fine grain TX sequencing, 0 to disable it.
+ *
+ * output parameters none
+ *
+ * no return value
+ */
+void dwt_setfinegraintxseq(int enable)
+{
+    if (enable)
+    {
+        dwt_write16bitoffsetreg(PMSC_ID, PMSC_TXFINESEQ_OFFSET, PMSC_TXFINESEQ_ENABLE);
+    }
+    else
+    {
+        dwt_write16bitoffsetreg(PMSC_ID, PMSC_TXFINESEQ_OFFSET, PMSC_TXFINESEQ_DISABLE);
+    }
+}
+
+/*! ------------------------------------------------------------------------------------------------------------------
+ * @fn dwt_setlnapamode()
+ *
+ * @brief This is used to enable GPIO for external LNA or PA functionality - HW dependent, consult the DW1000 User Manual.
+ *        This can also be used for debug as enabling TX and RX GPIOs is quite handy to monitor DW1000's activity.
+ *
+ * NOTE: Enabling PA functionality requires that fine grain TX sequencing is deactivated. This can be done using
+ *       dwt_setfinegraintxseq().
+ *
+ * input parameters
+ * @param lna - 1 to enable LNA functionality, 0 to disable it
+ * @param pa - 1 to enable PA functionality, 0 to disable it
+ *
+ * output parameters
+ *
+ * no return value
+ */
+void dwt_setlnapamode(int lna, int pa)
+{
+    uint32_t gpio_mode = dwt_read32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET);
+    gpio_mode &= ~(GPIO_MSGP4_MASK | GPIO_MSGP5_MASK | GPIO_MSGP6_MASK);
+    if (lna)
+    {
+        gpio_mode |= GPIO_PIN6_EXTRXE;
+    }
+    if (pa)
+    {
+        gpio_mode |= (GPIO_PIN5_EXTTXE | GPIO_PIN4_EXTPA);
+    }
+    dwt_write32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET, gpio_mode);
+}
+
+/*! ------------------------------------------------------------------------------------------------------------------
+ * @fn dwt_setgpiodirection()
+ *
+ * @brief This is used to set GPIO direction as an input (1) or output (0)
+ *
+ * input parameters
+ * @param gpioNum    -   this is the GPIO to configure - see GxM0... GxM8 in the deca_regs.h file
+ * @param direction  -   this sets the GPIO direction - see GxP0... GxP8 in the deca_regs.h file
+ *
+ * output parameters
+ *
+ * no return value
+ */
+void dwt_setgpiodirection(uint32_t gpioNum, uint32_t direction)
+{
+    uint8_t buf[GPIO_DIR_LEN];
+    uint32_t command = direction | gpioNum;
+
+    buf[0] = command & 0xff;
+    buf[1] = (command >> 8) & 0xff;
+    buf[2] = (command >> 16) & 0xff;
+
+    dwt_writetodevice(GPIO_CTRL_ID, GPIO_DIR_OFFSET, GPIO_DIR_LEN, buf);
+}
+
+/*! ------------------------------------------------------------------------------------------------------------------
+ * @fn dwt_setgpiovalue()
+ *
+ * @brief This is used to set GPIO value as (1) or (0) only applies if the GPIO is configured as output
+ *
+ * input parameters
+ * @param gpioNum    -   this is the GPIO to configure - see GxM0... GxM8 in the deca_regs.h file
+ * @param value  -   this sets the GPIO value - see GDP0... GDP8 in the deca_regs.h file
+ *
+ * output parameters
+ *
+ * no return value
+ */
+void dwt_setgpiovalue(uint32_t gpioNum, uint32_t value)
+{
+    uint8_t buf[GPIO_DOUT_LEN];
+    uint32_t command = value | gpioNum;
+
+    buf[0] = command & 0xff;
+    buf[1] = (command >> 8) & 0xff;
+    buf[2] = (command >> 16) & 0xff;
+
+    dwt_writetodevice(GPIO_CTRL_ID, GPIO_DOUT_OFFSET, GPIO_DOUT_LEN, buf);
+}
+
+/*! ------------------------------------------------------------------------------------------------------------------
+ * @fn dwt_getpartid()
+ *
+ * @brief This is used to return the read part ID of the device
+ *
+ * NOTE: dwt_initialise() must be called prior to this function so that it can return a relevant value.
+ *
+ * input parameters
+ *
+ * output parameters
+ *
+ * returns the 32 bit part ID value as programmed in the factory
+ */
+uint32_t dwt_getpartid(void)
+{
+    return pdw1000local->partID;
+}
+
+/*! ------------------------------------------------------------------------------------------------------------------
+ * @fn dwt_getlotid()
+ *
+ * @brief This is used to return the read lot ID of the device
+ *
+ * NOTE: dwt_initialise() must be called prior to this function so that it can return a relevant value.
+ *
+ * input parameters
+ *
+ * output parameters
+ *
+ * returns the 32 bit lot ID value as programmed in the factory
+ */
+uint32_t dwt_getlotid(void)
+{
+    return pdw1000local->lotID;
+}
+
+/*! ------------------------------------------------------------------------------------------------------------------
+ * @fn dwt_readdevid()
+ *
+ * @brief This is used to return the read device type and revision information of the DW1000 device (MP part is 0xDECA0130)
+ *
+ * input parameters
+ *
+ * output parameters
+ *
+ * returns the read value which for DW1000 is 0xDECA0130
+ */
+uint32_t dwt_readdevid(void)
+{
+    return dwt_read32bitoffsetreg(DEV_ID_ID,0);
+}
+
+/*! ------------------------------------------------------------------------------------------------------------------
+ * @fn dwt_configuretxrf()
+ *
+ * @brief This function provides the API for the configuration of the TX spectrum
+ * including the power and pulse generator delay. The input is a pointer to the data structure
+ * of type dwt_txconfig_t that holds all the configurable items.
+ *
+ * input parameters
+ * @param config    -   pointer to the txrf configuration structure, which contains the tx rf config data
+ *
+ * output parameters
+ *
+ * no return value
+ */
+void dwt_configuretxrf(dwt_txconfig_t* config)
+{
+
+    // Configure RF TX PG_DELAY
+    dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGDELAY_OFFSET, config->PGdly);
+
+    // Configure TX power
+    dwt_write32bitreg(TX_POWER_ID, config->power);
+
+}
+
+/*! ------------------------------------------------------------------------------------------------------------------
+ * @fn dwt_configure()
+ *
+ * @brief This function provides the main API for the configuration of the
+ * DW1000 and this low-level driver.  The input is a pointer to the data structure
+ * of type dwt_config_t that holds all the conf