commit d37103318f378a1b3ac38a392ee9978f6ca2668d
Author: Cung Sang <csang@techfak.uni-bielefeld.de>
Date:   Fri Feb 8 18:38:14 2019 +0100

    Added unit test for DW1000 v1

diff --git a/periphery-lld/AMiRo-LLD b/periphery-lld/AMiRo-LLD
index c3c5444..33f5421 160000
--- a/periphery-lld/AMiRo-LLD
+++ b/periphery-lld/AMiRo-LLD
@@ -1 +1 @@
-Subproject commit c3c5444e8fe1240ac6f4d7e4922d2525f4dabc39
+Subproject commit 33f542133dd484ad1904f87d0e837020e4f31433
diff --git a/unittests/periphery-lld/inc/ut_alld_dw1000_v1.h b/unittests/periphery-lld/inc/ut_alld_dw1000_v1.h
new file mode 100755
index 0000000..17e5267
--- /dev/null
+++ b/unittests/periphery-lld/inc/ut_alld_dw1000_v1.h
@@ -0,0 +1,84 @@
+/*
+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_DW1000_LLD_H_
+#define _AMIROOS_UT_DW1000_LLD_H_
+
+#include <aos_unittest.h>
+#include <amiro-lld.h>
+
+#if ((AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_DW1000) && (AMIROLLD_CFG_DW1000 == 1)) || defined(__DOXYGEN__)
+
+#include <alld_DW1000.h>
+
+/******************************************************************************/
+/* CONSTANTS                                                                  */
+/******************************************************************************/
+
+/******************************************************************************/
+/* SETTINGS                                                                   */
+/******************************************************************************/
+
+/******************************************************************************/
+/* CHECKS                                                                     */
+/******************************************************************************/
+
+/******************************************************************************/
+/* DATA STRUCTURES AND TYPES                                                  */
+/******************************************************************************/
+
+/******************************************************************************/
+/* MACROS                                                                     */
+/******************************************************************************/
+
+/******************************************************************************/
+/* EXTERN DECLARATIONS                                                        */
+/******************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  aos_utresult_t utAlldDw1000Func(BaseSequentialStream* stream, aos_unittest_t* ut);
+
+  extern uint8_t s1switch;
+  extern int instance_anchaddr;
+  extern int dr_mode;
+  extern int chan, tagaddr, ancaddr;
+  extern int instance_mode;
+  extern DW1000Driver* spiDrv;
+
+  extern int UWB_Init(void);
+  extern uint32_t inittestapplication(uint8_t s1switch);
+  extern int decarangingmode(uint8_t s1switch);
+  extern void addressconfigure(uint8_t s1switch, uint8_t mode);
+  extern void port_SPIx_set_chip_select(void);
+  extern void port_SPIx_clear_chip_select(void);
+  extern void reset_DW1000(void);
+  extern void setHighSpeed_SPI(bool speedValue);
+#ifdef __cplusplus
+}
+#endif
+
+/******************************************************************************/
+/* INLINE FUNCTIONS                                                           */
+/******************************************************************************/
+
+
+#endif /* (AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_DW1000) && (AMIROLLD_CFG_DW1000 == 0) */
+
+#endif /* _AMIROOS_UT_DW1000_LLD_H_ */
diff --git a/unittests/periphery-lld/src/ut_alld_dw1000_v1.c b/unittests/periphery-lld/src/ut_alld_dw1000_v1.c
new file mode 100755
index 0000000..7e9d3e1
--- /dev/null
+++ b/unittests/periphery-lld/src/ut_alld_dw1000_v1.c
@@ -0,0 +1,426 @@
+/*
+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 <amiroos.h>
+
+#if ((AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_DW1000) && (AMIROLLD_CFG_DW1000 == 1)) || defined(__DOXYGEN__)
+
+#include <aos_debug.h>
+#include <chprintf.h>
+#include <aos_thread.h>
+#include <math.h>
+#include <module.h>
+#include <alld_DW1000.h>
+#include <v1/deca_instance_v1.h>
+
+
+/******************************************************************************/
+/* LOCAL DEFINITIONS                                                          */
+/******************************************************************************/
+
+//#define UNIT_TEST_SNIPPETS_DW1000   // switch between unit test and demo apps
+
+#define SWS1_SHF_MODE 0x02  //short frame mode (6.81M)
+#define SWS1_CH5_MODE 0x04  //channel 5 mode
+#define SWS1_ANC_MODE 0x08  //anchor mode
+#define SWS1_A1A_MODE 0x10  //anchor/tag address A1
+#define SWS1_A2A_MODE 0x20  //anchor/tag address A2
+#define SWS1_A3A_MODE 0x40  //anchor/tag address A3
+#define SWS1_USB2SPI_MODE 0x78  //USB to SPI mode
+
+#define S1_SWITCH_ON  (1)
+#define S1_SWITCH_OFF (0)
+
+/******************************************************************************/
+/* EXPORTED VARIABLES                                                         */
+/******************************************************************************/
+
+/******************************************************************************/
+/* LOCAL TYPES                                                                */
+/******************************************************************************/
+
+/******************************************************************************/
+/* LOCAL VARIABLES                                                            */
+/******************************************************************************/
+uint8_t s1switch = 0;
+int instance_anchaddr = 0;
+int dr_mode = 0;
+int chan, tagaddr, ancaddr;
+int instance_mode = ANCHOR;
+
+DW1000Driver* spiDrv;
+
+
+/******************************************************************************/
+/* LOCAL FUNCTIONS                                                            */
+/******************************************************************************/
+
+/*! @brief Change the SPI speed configuration  on the fly */
+void setHighSpeed_SPI(bool speedValue){
+
+  spiStop(&MODULE_HAL_SPI_UWB);
+  //  spiAcquireBus(&MODULE_HAL_SPI_UWB);
+
+  if (speedValue == FALSE){
+    spiStart(&MODULE_HAL_SPI_UWB, &moduleHalSpiUwbLsConfig);  // low speed spi configuration
+  }
+  else{
+    spiStart(&MODULE_HAL_SPI_UWB, &moduleHalSpiUwbHsConfig); // high speed spi configuration
+  }
+}
+/* void setHighSpeed_SPI(bool speedValue){
+
+  spiStop(spiDrv->spid);
+  //  spiAcquireBus(&MODULE_HAL_SPI_UWB);
+
+  if (speedValue == FALSE){
+    spiStart(spiDrv->spid, &moduleHalSpiUwbLsConfig);  // low speed spi configuration
+  }
+  else{
+    spiStart(spiDrv->spid, &moduleHalSpiUwbHsConfig); // high speed spi configuration
+  }
+} */
+
+/*! @brief Manually set the chip select pin of the SPI */
+void port_SPIx_set_chip_select(void){
+  apalGpioWrite(moduleGpioSpiChipSelect.gpio, APAL_GPIO_HIGH);
+}
+
+/*! @brief Manually reset the chip select pin of the SPI */
+void port_SPIx_clear_chip_select(void){
+  apalGpioWrite(moduleGpioSpiChipSelect.gpio, APAL_GPIO_LOW);
+}
+
+/*! @brief Manually reset the DW1000 module  */
+void reset_DW1000(void){
+
+  // Set the pin as output
+  palSetPadMode(moduleGpioDw1000Reset.gpio->port, moduleGpioDw1000Reset.gpio->pad, APAL_GPIO_DIRECTION_OUTPUT);
+
+  //drive the RSTn pin low
+  apalGpioWrite(moduleGpioDw1000Reset.gpio, APAL_GPIO_LOW);
+
+  //put the pin back to tri-state ... as input
+//  palSetPadMode(moduleGpioDw1000Reset.gpio->port, moduleGpioDw1000Reset.gpio->pad, APAL_GPIO_DIRECTION_INPUT); // TODO:
+
+  aosThdMSleep(2);
+}
+
+
+/*! @brief Configure instance tag/anchor/etc... addresses
+ *
+ * */
+void addressconfigure(uint8_t s1switch, uint8_t mode){
+  uint16_t instAddress ;
+
+  instance_anchaddr = (((s1switch & SWS1_A1A_MODE) << 2) + (s1switch & SWS1_A2A_MODE) + ((s1switch & SWS1_A3A_MODE) >> 2)) >> 4;
+
+  if(mode == ANCHOR) {
+    if(instance_anchaddr > 3) {
+      instAddress = GATEWAY_ANCHOR_ADDR | 0x4 ; //listener
+    }
+    else {
+      instAddress = GATEWAY_ANCHOR_ADDR | (uint16_t)instance_anchaddr;
+    }
+  }
+  else{
+    instAddress = (uint16_t)instance_anchaddr;
+  }
+
+  instancesetaddresses(instAddress);
+}
+
+
+/*! @brief returns the use case / operational mode
+ *
+ * */
+int decarangingmode(uint8_t s1switch){
+  int mode = 0;
+
+  if(s1switch & SWS1_SHF_MODE)  {
+    mode = 1;
+  }
+
+  if(s1switch & SWS1_CH5_MODE) {
+    mode = mode + 2;
+  }
+
+  return mode;
+}
+
+/*! @brief Check connection setting and initialize DW1000 module
+ *
+ **/
+uint32_t inittestapplication(uint8_t s1switch){
+  uint32_t devID ;
+  int result;
+
+  setHighSpeed_SPI(FALSE);          //low speed spi max. ~4M
+  devID = instancereaddeviceid() ;
+
+  if(DWT_DEVICE_ID != devID) {
+    port_SPIx_clear_chip_select();
+    Sleep(1);
+    port_SPIx_set_chip_select();
+    Sleep(7);
+    devID = instancereaddeviceid() ;
+    if(DWT_DEVICE_ID != devID){
+      return(-1) ;  // SPI not working or Unsupported Device ID
+    }    
+    dwt_softreset();//clear the sleep bit - so that after the hard reset below the DW does not go into sleep
+  }
+
+    reset_DW1000();  //reset the DW1000 by driving the RSTn line low
+
+  if((s1switch & SWS1_ANC_MODE) == 0){
+    instance_mode = TAG;
+  }
+  else{
+    instance_mode = ANCHOR;
+  }
+
+  result = instance_init(spiDrv) ; // TODO
+//  result = instance_init() ;
+
+  if (0 > result){
+    return(-1) ;
+  }
+
+  setHighSpeed_SPI(TRUE);               // high speed spi max. ~ 20M
+  devID = instancereaddeviceid() ;
+
+  if (DWT_DEVICE_ID != devID){
+    return(-1) ;
+  }
+
+  addressconfigure(s1switch, (uint8_t)instance_mode) ;
+
+  if((instance_mode == ANCHOR) && (instance_anchaddr > 0x3)){
+    instance_mode = LISTENER;
+  }
+
+  instancesetrole(instance_mode) ;       // Set this instance role
+  dr_mode = decarangingmode(s1switch);
+  chan = chConfig[dr_mode].channelNumber ;
+  instance_config(&chConfig[dr_mode], &sfConfig[dr_mode]) ;
+
+  return devID;
+}
+
+/*! @brief Main Entry point to Initialization of UWB DW1000 configuration
+ *
+ * */
+#pragma GCC optimize ("O3")
+int UWB_Init(void){
+
+  /*! Software defined Configurartion for TAG, ANC, and other settings as needed */
+  s1switch = S1_SWITCH_OFF << 1 // is_switch_on(TA_SW1_2) << 2  // (on = 6.8 Mbps, off = 110 kbps)
+                              | S1_SWITCH_OFF << 2  // (on = CH5, off = CH2)
+                              | S1_SWITCH_OFF << 3  // (on = Anchor, off = TAG)
+                              | S1_SWITCH_OFF << 4  // (configure Tag or anchor ID no.)
+                              | S1_SWITCH_OFF << 5  // (configure Tag or anchor ID no.)
+                              | S1_SWITCH_OFF << 6  // (configure Tag or anchor ID no.)
+                              | S1_SWITCH_OFF << 7; // Not use in this demo
+
+
+  port_DisableEXT_IRQ();           //disable ScenSor IRQ until we configure the device
+
+  if((s1switch & SWS1_USB2SPI_MODE) == SWS1_USB2SPI_MODE){
+    return 1;
+  }
+  else{
+    //run RTLS application
+    if(inittestapplication(s1switch) == (uint32_t)-1) {
+      return 0; //error
+    }
+
+    aosThdMSleep(5);
+  }
+
+  port_EnableEXT_IRQ();           //enable ScenSor IRQ before starting
+
+  return 0;
+}
+
+
+/******************************************************************************/
+/* EXPORTED FUNCTIONS                                                         */
+/******************************************************************************/
+
+
+aos_utresult_t utAlldDw1000Func(BaseSequentialStream* stream, aos_unittest_t* ut) {
+
+  aosDbgCheck(ut->data != NULL);
+
+  aos_utresult_t result = {0, 0};
+
+
+  /*! Unit Test snippets for DW1000.
+     * @Note: Passed all 4 unit tests. Event IRQ should be tested separately
+     */
+#ifdef UNIT_TEST_SNIPPETS_DW1000
+
+  uint32_t actual_deviceId;
+
+  chprintf(stream, "init DW1000...\n");
+  dwt_initialise(DWT_LOADUCODE, (DW1000Driver*) ut->data);
+  aosThdMSleep(5);
+
+  port_DisableEXT_IRQ();
+
+  setHighSpeed_SPI(false);
+  chprintf(stream, "expected device ID (LS SPI): 0xDECA0130 \n");
+  aosThdMSleep(5);
+  actual_deviceId = instancereaddeviceid();
+  chprintf(stream, "actual read ID: 0x%x\n", actual_deviceId);
+  aosThdMSleep(5);
+
+  if(DWT_DEVICE_ID != actual_deviceId) //if the read of device ID fails, the DW1000 could be asleep
+  {
+    port_SPIx_clear_chip_select();  //CS low
+    aosThdMSleep(1);   //200 us to wake up then waits 5ms for DW1000 XTAL to stabilise
+    port_SPIx_set_chip_select();  //CS high
+    aosThdMSleep(7);
+    actual_deviceId = instancereaddeviceid() ;
+
+    // SPI not working or Unsupported Device ID
+    if(DWT_DEVICE_ID != actual_deviceId){
+      chprintf(stream, "SPI not working or Unsupported Device ID\n");
+      chprintf(stream, "actual device ID is: 0x%x\n", actual_deviceId);
+      chprintf(stream, "expected device ID: 0xDECA0130 \n");
+      aosThdMSleep(5);
+      //          return(-1) ;
+    }
+
+    //clear the sleep bit - so that after the hard reset below the DW does not go into sleep
+    dwt_softreset();
+  }
+
+  /*! Low speed SPI unit test result */
+  if (actual_deviceId == DWT_DEVICE_ID){
+    aosUtPassed(stream, &result);
+  } else {
+    aosUtFailed(stream, &result);
+  }
+  reset_DW1000();
+
+
+  chprintf(stream, " Initialise instance for DW1000 \n");
+  aosThdSleep(5);
+
+  int x_init = instance_init((DW1000Driver*) ut->data) ;   // TODO
+//  int x_init = instance_init() ;
+
+  if (0 != x_init){
+    chprintf(stream, "Init error with return value: %d \n", x_init);
+    aosThdSleep(5);
+  }
+  else {
+    chprintf(stream, "Init success with return value: %d \n", x_init);
+    aosThdSleep(5);
+  }
+
+
+  /* Initialization unit test result */
+  if (x_init == 0){
+    aosUtPassed(stream, &result);
+  } else {
+    aosUtFailed(stream, &result);
+  }
+
+
+  setHighSpeed_SPI(true);
+
+  chprintf(stream, "expected device ID (HS SPI): 0xDECA0130\n");
+  actual_deviceId = instancereaddeviceid();
+  chprintf(stream, "actual read ID: 0x%x\n", actual_deviceId);
+  aosThdMSleep(5);
+
+  /* High speed SPI unit test result */
+  if (actual_deviceId == DWT_DEVICE_ID){
+    aosUtPassed(stream, &result);
+  } else {
+    aosUtFailed(stream, &result);
+  }
+
+  port_EnableEXT_IRQ();
+  reset_DW1000();
+
+
+
+  chprintf(stream, " Initialise the configuration for UWB application \n");
+  aosThdSleep(5);
+
+  int uwb_init = UWB_Init();
+
+  if (0 != uwb_init){
+    chprintf(stream, "UWB config error with return value: %d \n", uwb_init);
+    aosThdSleep(5);
+  }
+  else {
+    chprintf(stream, "UWB config success with return value: %d \n", uwb_init);
+    aosThdSleep(5);
+  }
+
+  /* UWB configuration unit test.
+   * If all the four unit tests are passed, the module is ready to run.
+   * Note that the interrupt IRQn should be tested separately.
+   */
+  if (uwb_init == 0){
+    aosUtPassed(stream, &result);
+  } else {
+    aosUtFailed(stream, &result);
+  }
+
+  /************** End of UNIT_TEST_SNIPPETS_DW1000*****************/
+
+#else
+
+  // RUN THE STATE MACHINE DEMO APP
+
+  chprintf(stream, " Initialise the State Machine \n");
+  aosThdSleep(2);
+
+  /* Initialize UWB system with the configuration provided in module_uwb_conf.c */
+  int uwb_init = UWB_Init();
+
+  if (0 != uwb_init){
+    chprintf(stream, "UWB config error with return value: %d \n", uwb_init);
+  }
+  else {
+    chprintf(stream, "UWB config success with return value: %d \n", uwb_init);
+  }
+  aosThdSleep(1);
+
+  chprintf(stream, " Running the RTLS demo application \n");
+  aosThdSleep(1);
+
+
+  /* Run the localization system demo app as a thread */
+  while(1){
+    instance_run();
+//    aosThdUSleep(10);
+  }
+
+#endif  /*  UNIT_TEST_SNIPPETS_DW1000 */
+
+  return result;
+}
+
+
+#endif /* (AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_DW1000) && (AMIROLLD_CFG_DW1000 == 1) */
