DW1000 UWB driver based on work of Matthias Grob & Manuel Stalder - ETH Zürich - 2015

Dependencies:   BurstSPI

Files at this revision

API Documentation at this revision

Comitter:
AndyA
Date:
Thu Apr 07 16:27:51 2016 +0000
Parent:
4:5f1025df5530
Parent:
2:ebbb05cbc417
Child:
6:2c77afdf7367
Commit message:
merged

Changed in this revision

DW1000.cpp Show annotated file Show diff for this revision Revisions of this file
DW1000.cpp.orig Show annotated file Show diff for this revision Revisions of this file
DW1000.h Show annotated file Show diff for this revision Revisions of this file
DW1000.h.orig Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DW1000.cpp.orig	Thu Apr 07 16:27:51 2016 +0000
@@ -0,0 +1,983 @@
+#include "DW1000.h"
+
+#define SPIRATE_PLL (5*1000*1000)
+#define SPIRATE_OSC (2*1000*1000)
+
+DW1000::DW1000(UWBMode setup, PinName MOSI, PinName MISO, PinName SCLK, PinName CS, PinName IRQ) : irq(IRQ), spi(MOSI, MISO, SCLK), cs(CS)
+{
+    setCallbacks(NULL, NULL);
+
+    deselect();                         // Chip must be deselected first
+    spi.format(8,0);                    // Setup the spi for standard 8 bit data and SPI-Mode 0 (GPIO5, GPIO6 open circuit or ground on DW1000)
+    spi.frequency(SPIRATE_PLL);             // with a 1MHz clock rate (worked up to 49MHz in our Test)
+
+    resetAll();                         // we do a soft reset of the DW1000 everytime the driver starts
+
+    switch (setup) {
+        case user110k:  // values from Matthias Grob & Manuel Stalder - ETH Zürich - library
+
+            systemConfig.setChannel(5);
+            systemConfig.setPRF(DW1000Setup::prf16MHz);
+            systemConfig.setDataRate(DW1000Setup::kbps110);
+            systemConfig.setSfd(DW1000Setup::standard);
+            systemConfig.setPreambleLength(DW1000Setup::pre1024);
+            systemConfig.setPreambleCode(3);
+            systemConfig.setSmartPower(false);
+
+            setupRadio();
+
+            setTxPower(230); // power = 23dB gain
+
+            setRxDelay(1<<14); // set delays to 2^14 (1/4 of max)
+            setTxDelay(1<<14);
+            break;
+
+        case tunedDefault:    // User Manual "2.5.5 Default Configurations that should be modified" p. 22
+        default:
+
+            systemConfig.setChannel(5);
+            systemConfig.setPRF(DW1000Setup::prf16MHz);
+            systemConfig.setDataRate(DW1000Setup::kbps6800);
+            systemConfig.setSfd(DW1000Setup::standard);
+            systemConfig.setPreambleLength(DW1000Setup::pre128);
+            systemConfig.setPreambleCode(3);
+            systemConfig.setSmartPower(false);
+
+            setupRadio();
+
+            setTxPower(230,260,290); // power = 23dB gain
+            setRxDelay(0);
+            setTxDelay(0);
+
+            break;
+        case minPacketSize:
+            systemConfig.setChannel(5);
+            systemConfig.setPRF(DW1000Setup::prf64MHz);
+            systemConfig.setDataRate(DW1000Setup::kbps6800);
+            systemConfig.setSfd(DW1000Setup::standard);
+            systemConfig.setPreambleLength(DW1000Setup::pre64);
+            systemConfig.setPreambleCode(10);
+            systemConfig.setSmartPower(true);
+
+            setupRadio();
+            uint16_t txPower = 25*10; // 25dB gain.
+            // 2 packets per ms max. So can increase TX power of 250us packets by 10log(4/2) dB and 125us packets by 10log(8/2) dB
+            setTxPower(txPower,txPower,txPower+30,txPower+60); // power = 23dB gain
+
+            setRxDelay(0);
+            setTxDelay(0);
+
+            break;
+    }
+
+
+    irq.rise(this, &DW1000::ISR);       // attach interrupt handler to rising edge of interrupt pin from DW1000
+}
+
+void DW1000::getSetup(char *buffer, int len)
+{
+
+    char dataRateString[10];
+    if (systemConfig.getDataRate() == DW1000Setup::kbps6800)
+        strcpy(dataRateString,"6.8 Mbps");
+    else if (systemConfig.getDataRate() == DW1000Setup::kbps850)
+        strcpy(dataRateString,"850 kbps");
+    else
+        strcpy(dataRateString,"110 kbps");
+
+    char preambleString[8];
+    switch (systemConfig.getPreambleLength()) {
+        default:
+            strcpy(preambleString,"error");
+            break;
+        case DW1000Setup::pre64:
+            strcpy(preambleString,"64");
+            break;
+        case DW1000Setup::pre128:
+            strcpy(preambleString,"128");
+            break;
+        case DW1000Setup::pre256:
+            strcpy(preambleString,"256");
+            break;
+        case DW1000Setup::pre512:
+            strcpy(preambleString,"512");
+            break;
+        case DW1000Setup::pre1024:
+            strcpy(preambleString,"1024");
+            break;
+        case DW1000Setup::pre1536:
+            strcpy(preambleString,"1536");
+            break;
+        case DW1000Setup::pre2048:
+            strcpy(preambleString,"2048");
+            break;
+        case DW1000Setup::pre4096:
+            strcpy(preambleString,"4096");
+            break;
+    }
+
+    snprintf(buffer,len,"Channel:\t%u\r\nPRF:\t%s\r\nData Rate:\t%s\r\nPreamble length:\t%s\r\nPreamble code:\t%u\r\nSmart power:\t%s\r\nSFD:\t%s\r\n",
+             systemConfig.getChannel(),
+             (systemConfig.getPRF() == DW1000Setup::prf16MHz)?"16 MHz":"64 MHz",
+             dataRateString,
+             preambleString,
+             systemConfig.getPreambleCode(),
+             systemConfig.getSmartPower()?"Enabled":"Disabled",
+             (systemConfig.getSfd() == DW1000Setup::standard)?"Standard":"Non-standard");
+
+}
+
+
+void DW1000::setupRadio()
+{
+    setupAGC();
+    setupRxConfig();
+    setupLDE();
+    setupChannel();
+    setupAnalogRF();
+    setupFreqSynth();
+    setupTxCalibration();
+    setupTxFrameCtrl();
+    setupSystemConfig();
+
+}
+
+void DW1000::setupAGC()
+{
+
+    writeRegister16(DW1000_AGC_CTRL, DWAGCCTRL_AGC_CTRL1, 0x0001);
+    if (systemConfig.getPRF() == DW1000Setup::prf16MHz)
+        writeRegister16(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE1, 0x8870);
+    else
+        writeRegister16(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE1, 0x889B);
+
+    writeRegister32(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE2, 0x2502A907);
+    writeRegister16(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE3, 0x0035);
+}
+
+void DW1000::setupSystemConfig()
+{
+    uint32_t valueToUse = 0;
+    valueToUse |= 1<<9; // IRQ output is active high (default)
+    valueToUse |= 1<<12; // Disable double buffered Rx (default)
+
+//    valueToUse |= 3<<16; // enable long (>125bytes data) packets
+
+    if (!systemConfig.getSmartPower())
+        valueToUse |= 1<<18; // disable smart power
+
+    if (systemConfig.getDataRate() == DW1000Setup::kbps110)
+        valueToUse |= 1<<22;
+
+    valueToUse |= 1<<29;// enable auto reenabling receiver after error
+
+    writeRegister32(DW1000_SYS_CFG, 0, valueToUse);
+}
+
+void DW1000::setupRxConfig()
+{
+
+    switch (systemConfig.getDataRate()) {
+        case DW1000Setup::kbps110:
+            if (systemConfig.getSfd() == DW1000Setup::standard)
+                writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x000A);
+            else
+                writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0016);
+            break;
+        case DW1000Setup::kbps850:
+            if (systemConfig.getSfd() == DW1000Setup::standard)
+                writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0001);
+            else
+                writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0006);
+            break;
+        case DW1000Setup::kbps6800:
+        default:
+            if (systemConfig.getSfd() == DW1000Setup::standard)
+                writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0001);
+            else
+                writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0002);
+            break;
+    }
+
+    if (systemConfig.getPRF() == DW1000Setup::prf16MHz)
+        writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1A, 0x0087);             //DRX_TUNE1a for 16MHz PRF
+    else
+        writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1A, 0x008D);
+
+    switch (systemConfig.getPreambleLength()) {
+        case DW1000Setup::pre1536:
+        case DW1000Setup::pre2048:
+        case DW1000Setup::pre4096:
+            writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1B, 0x0064);             //DRX_TUNE1b for 110kbps & > 1024 symbols
+            break;
+        default: // 128 to 1024
+            writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1B, 0x0020);             //DRX_TUNE1b for 128- 1024 symbols
+            break;
+        case DW1000Setup::pre64:
+            writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1B, 0x0010);             //DRX_TUNE1b for 64 symbols
+            break;
+    }
+
+    switch (systemConfig.getPreambleLength()) {
+        case DW1000Setup::pre64:
+        case DW1000Setup::pre128:  // PAC = 8
+            if (systemConfig.getPRF() == DW1000Setup::prf16MHz)
+                writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x311A002D);             //DRX_TUNE2 PAC 8 for 64MHz PRF
+            else
+                writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x313B006B);        //DRX_TUNE2 PAC 8 for 64MHz PRF
+            break;
+        case DW1000Setup::pre256:
+        case DW1000Setup::pre512: // PAC = 16
+            if (systemConfig.getPRF() == DW1000Setup::prf16MHz)
+                writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x331A0052);             //DRX_TUNE2 PAC 16 for 64MHz PRF
+            else
+                writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x333B00BE);        //DRX_TUNE2 PAC 16 for 64MHz PRF
+            break;
+        case DW1000Setup::pre1024: // PAC = 32
+            if (systemConfig.getPRF() == DW1000Setup::prf16MHz)
+                writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x351A009A);             //DRX_TUNE2 PAC 32 for 64MHz PRF
+            else
+                writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x353B015E);        //DRX_TUNE2 PAC 32 for 64MHz PRF
+            break;
+        case DW1000Setup::pre1536:
+        case DW1000Setup::pre2048:
+        case DW1000Setup::pre4096: // PAC = 64
+            if (systemConfig.getPRF() == DW1000Setup::prf16MHz)
+                writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x371A011D);             //DRX_TUNE2 PAC 64 for 64MHz PRF
+            else
+                writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x373B0296);        //DRX_TUNE2 PAC 64 for 64MHz PRF
+            break;
+    }
+
+
+    if (systemConfig.getPreambleLength() == DW1000Setup::pre64)
+        writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE4H, 0x0010);
+    else
+        writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE4H, 0x0028);
+
+}
+
+
+void DW1000::setupLDE()
+{
+
+    writeRegister8 (DW1000_LDE_CTRL, DWLDE_LDE_CFG1, 0x13 | 0x03<<5);  //NTM = 13 (12 may be better in some situations. PMULT = 3
+
+    if (systemConfig.getPRF() == DW1000Setup::prf16MHz)
+        writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_CFG2, 0x1607);           //LDE_CFG2 for 16MHz PRF
+    else
+        writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_CFG2, 0x0607);           //LDE_CFG2 for 64MHz PRF
+
+    uint16_t replicaCoeff;
+    switch (systemConfig.getPreambleCode()) {
+        default:
+        case 1:
+        case 2:
+            replicaCoeff = 0x5998;
+            break;
+        case 3:
+            replicaCoeff = 0x51EA;
+            break;
+        case 4:
+            replicaCoeff = 0x428E;
+            break;
+        case 5:
+            replicaCoeff = 0x451E;
+            break;
+        case 6:
+            replicaCoeff = 0x2E14;
+            break;
+        case 7:
+            replicaCoeff = 0x8000;
+            break;
+        case 8:
+            replicaCoeff = 0x51EA;
+            break;
+        case 9:
+            replicaCoeff = 0x28F4;
+            break;
+        case 10:
+            replicaCoeff = 0x3332;
+            break;
+        case 11:
+            replicaCoeff = 0x3AE0;
+            break;
+        case 12:
+            replicaCoeff = 0x3D70;
+            break;
+        case 13:
+            replicaCoeff = 0x3AE0;
+            break;
+        case 14:
+            replicaCoeff = 0x35C2;
+            break;
+        case 15:
+            replicaCoeff = 0x2B84;
+            break;
+        case 16:
+            replicaCoeff = 0x35C2;
+            break;
+        case 17:
+            replicaCoeff = 0x3332;
+            break;
+        case 18:
+            replicaCoeff = 0x35C2;
+            break;
+        case 19:
+            replicaCoeff = 0x35C2;
+            break;
+        case 20:
+            replicaCoeff = 0x47AE;
+            break;
+        case 21:
+            replicaCoeff = 0x3AE0;
+            break;
+        case 22:
+            replicaCoeff = 0x3850;
+            break;
+        case 23:
+            replicaCoeff = 0x30A2;
+            break;
+        case 24:
+            replicaCoeff = 0x3850;
+            break;
+    }
+
+    if (systemConfig.getDataRate() == DW1000Setup::kbps110)
+        replicaCoeff = replicaCoeff>>3;
+
+    writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_REPC, replicaCoeff);
+
+    loadLDE();
+}
+
+void DW1000::setupChannel()
+{
+    uint32_t registerValue = 0;
+
+    registerValue = systemConfig.getChannel(); // set Tx channel
+    registerValue |= systemConfig.getChannel()<<4; // set Rx channel
+
+    if (systemConfig.getPRF() == DW1000Setup::prf16MHz) // set PRF (2 bit value 01 or 10)
+        registerValue |= 0x01 << 18;
+    else
+        registerValue |= 0x02 << 18;
+
+    if (systemConfig.getSfd() == DW1000Setup::decaWave) 
+        registerValue |= 0x01 << 17; // enable DW own SFD
+
+    if (systemConfig.getSfd() == DW1000Setup::user) {     
+        registerValue |= 0x01 << 20; // enable user set SFD Tx
+        registerValue |= 0x01 << 21; // enable user set SFD Rx
+    }
+
+    registerValue |= systemConfig.getPreambleCode() << 22; // set Tx preamble code
+    registerValue |= systemConfig.getPreambleCode() << 27; // set Rx preamble code
+
+    writeRegister32(DW1000_CHAN_CTRL, 0, registerValue);
+}
+
+
+uint8_t DW1000::powerToRegValue(uint16_t powercB)
+{
+
+    // course power control - 0 = 18dB, 6 = 0dB in 3dB steps.
+    uint8_t course = powercB / 30;
+
+    if(course > 6)
+        course = 6;
+
+    // remaining power
+    powercB -= course * 30;
+
+    // value in reg is inverse.
+    course = 6-course;
+
+    // fine control in steps of 0.5dB
+    uint8_t fine =  powercB / 5;
+    if (fine > 31)
+        fine = 31;
+
+
+    return (course << 5) | fine;
+
+}
+
+// transmit power: 0 to 33.5 dB gain in steps of 0.5. Inputs are in 10ths of a dB (0 to 335)
+void DW1000::setTxPower(uint16_t normalPowercB, uint16_t boost500, uint16_t boost250, uint16_t boost125)
+{
+
+    if(normalPowercB > 335)
+        normalPowercB = 335;
+
+    if (boost500 < normalPowercB)
+        boost500 = normalPowercB;
+    if(boost500 > 335)
+        boost500 = 335;
+
+    if (boost250 < boost500)
+        boost250 = boost500;
+    if(boost250 > 335)
+        boost250 = 335;
+
+    if (boost125 < boost250)
+        boost125 = boost250;
+    if(boost125 > 335)
+        boost125 = 335;
+
+    if (systemConfig.getSmartPower() == false) {
+        boost500 = normalPowercB;
+        boost250 = normalPowercB;
+        boost125 = normalPowercB;
+    }
+
+    uint32_t powerReg = powerToRegValue(normalPowercB);
+    powerReg |= powerToRegValue(boost500) << 8;
+    powerReg |= powerToRegValue(boost250) << 16;
+    powerReg |= powerToRegValue(boost125) << 24;
+}
+
+void DW1000::setupAnalogRF()
+{
+    switch (systemConfig.getChannel()) {
+        case 1:
+            writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x00005C40);
+            break;
+        case 2:
+            writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x00045CA0);
+            break;
+        case 3:
+            writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x00086CC0);
+            break;
+        case 4:
+            writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x00045C80);
+            break;
+        case 5:
+        default:
+            writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x001E3FE0);
+            break;
+        case 7:
+            writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x001E7DE0);
+            break;
+    }
+
+    switch (systemConfig.getChannel()) {
+        case 1:
+        case 2:
+        case 3:
+        case 5:
+        default:
+            writeRegister8(DW1000_RF_CONF, DWRFCONF_RF_RXCTRLH, 0xD8);
+            break;
+        case 4:
+        case 7:
+            writeRegister8(DW1000_RF_CONF, DWRFCONF_RF_RXCTRLH, 0xBC);
+            break;
+    }
+
+    loadLDOTUNE();
+
+}
+
+void DW1000::setupTxCalibration()
+{
+    switch (systemConfig.getChannel()) {
+        case 1:
+            writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0xC9);
+            break;
+        case 2:
+            writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0xC2);
+            break;
+        case 3:
+            writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0xC5);
+            break;
+        case 4:
+            writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0x95);
+            break;
+        case 5:
+        default:
+            writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0xC0);
+            break;
+        case 7:
+            writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0x93);
+            break;
+    }
+}
+
+void DW1000::setupFreqSynth()
+{
+
+    switch (systemConfig.getChannel()) {
+        case 1:
+            writeRegister32 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLCFG, 0x09000407);         //FS_PLLCFG for channel 1
+            writeRegister8 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLTUNE, 0x1E);
+            break;
+        case 2:
+        case 4:
+            writeRegister32 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLCFG, 0x08400508);         //FS_PLLCFG for channel 2,4
+            writeRegister8 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLTUNE, 0x26);
+            break;
+        case 3:
+            writeRegister32 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLCFG, 0x08401009);         //FS_PLLCFG for channel 3
+            writeRegister8 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLTUNE, 0x5E);
+            break;
+        case 5:
+        case 7:
+        default:
+            writeRegister32 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLCFG, 0x0800041D);         //FS_PLLCFG for channel 5,7
+            writeRegister8 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLTUNE, 0xBE);                //FS_PLLTUNE for channel 5
+            break;
+    }
+}
+
+void DW1000::setupTxFrameCtrl()
+{
+    uint32_t frameCtrlValue = 0;
+    switch (systemConfig.getDataRate()) {
+        case DW1000Setup::kbps110:
+            break;
+        case DW1000Setup::kbps850:
+            frameCtrlValue |= 0x01<<13;
+            break;
+        case DW1000Setup::kbps6800:
+        default:
+            frameCtrlValue |= 0x02<<13;
+            break;
+    }
+    frameCtrlValue |= 0x01<<15;
+
+    if (systemConfig.getPRF() == DW1000Setup::prf16MHz)
+        frameCtrlValue |= 0x01<<16;
+    else
+        frameCtrlValue |= 0x02<<16;
+
+    switch    (systemConfig.getPreambleLength())            {
+        case DW1000Setup::pre64:
+            frameCtrlValue |= 0x01<<18; // TXPSR
+            frameCtrlValue |= 0x00<<20; // PE
+            break;
+        case DW1000Setup::pre128:
+        default:
+            frameCtrlValue |= 0x01<<18; // TXPSR
+            frameCtrlValue |= 0x01<<20; // PE
+            break;
+        case DW1000Setup::pre256:
+            frameCtrlValue |= 0x01<<18; // TXPSR
+            frameCtrlValue |= 0x02<<20; // PE
+            break;
+        case DW1000Setup::pre512:
+            frameCtrlValue |= 0x01<<18; // TXPSR
+            frameCtrlValue |= 0x03<<20; // PE
+            break;
+        case DW1000Setup::pre1024:
+            frameCtrlValue |= 0x02<<18; // TXPSR
+            frameCtrlValue |= 0x00<<20; // PE
+            break;
+        case DW1000Setup::pre1536:
+            frameCtrlValue |= 0x02<<18; // TXPSR
+            frameCtrlValue |= 0x01<<20; // PE
+            break;
+        case DW1000Setup::pre2048:
+            frameCtrlValue |= 0x02<<18; // TXPSR
+            frameCtrlValue |= 0x02<<20; // PE
+            break;
+        case DW1000Setup::pre4096:
+            frameCtrlValue |= 0x03<<18; // TXPSR
+            frameCtrlValue |= 0x00<<20; // PE
+            break;
+    }
+    writeRegister32(DW1000_TX_FCTRL,0,frameCtrlValue);
+}
+
+void DW1000::setRxDelay(uint16_t ticks)
+{
+    writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_RXANTD, ticks);
+}
+void DW1000::setTxDelay(uint16_t ticks)
+{
+    writeRegister16(DW1000_TX_ANTD, 0, ticks);
+}
+
+void DW1000::setCallbacks(void (*callbackRX)(void), void (*callbackTX)(void))
+{
+    bool RX = false;
+    bool TX = false;
+    if (callbackRX) {
+        DW1000::callbackRX.attach(callbackRX);
+        RX = true;
+    }
+    if (callbackTX) {
+        DW1000::callbackTX.attach(callbackTX);
+        TX = true;
+    }
+    setInterrupt(RX,TX);
+}
+
+uint32_t DW1000::getDeviceID()
+{
+    uint32_t result;
+    readRegister(DW1000_DEV_ID, 0, (uint8_t*)&result, 4);
+    return result;
+}
+
+uint64_t DW1000::getEUI()
+{
+    uint64_t result;
+    readRegister(DW1000_EUI, 0, (uint8_t*)&result, 8);
+    return result;
+}
+
+void DW1000::setEUI(uint64_t EUI)
+{
+    writeRegister(DW1000_EUI, 0, (uint8_t*)&EUI, 8);
+}
+
+
+float DW1000::getVoltage()
+{
+    uint8_t data;
+
+    writeRegister8(DW1000_RF_CONF, 0x11, 0x80);
+    writeRegister8(DW1000_RF_CONF, 0x12, 0x0A);
+    writeRegister8(DW1000_RF_CONF, 0x12, 0x0F);
+    writeRegister8(DW1000_TX_CAL, 0x00, 0x01);
+    writeRegister8(DW1000_TX_CAL, 0x00, 0x00);
+    data = readRegister8(DW1000_TX_CAL, 0x03);               // get the 8-Bit reading for Voltage
+    float Voltage = (float)(data - (readOTP(0x08)&0x00ff)) *0.00578 + 3.3;
+    return Voltage;
+}
+
+float DW1000::getTemperature()
+{
+    uint8_t data;
+
+    writeRegister8(DW1000_RF_CONF, 0x11, 0x80);
+    writeRegister8(DW1000_RF_CONF, 0x12, 0x0A);
+    writeRegister8(DW1000_RF_CONF, 0x12, 0x0F);
+    writeRegister8(DW1000_TX_CAL, 0x00, 0x01);
+    writeRegister8(DW1000_TX_CAL, 0x00, 0x00);
+    data = readRegister16(DW1000_TX_CAL, 0x04);               // get the 8-Bit reading for Temperature
+    float temperature =  (float)(data - (readOTP(0x09) & 0x00ff))*0.9 + 23;
+    return temperature;
+}
+
+
+uint64_t DW1000::getStatus()
+{
+    return readRegister40(DW1000_SYS_STATUS, 0);
+}
+
+uint64_t DW1000::getRXTimestamp()
+{
+    return readRegister40(DW1000_RX_TIME, 0);
+}
+
+uint64_t DW1000::getTXTimestamp()
+{
+    return readRegister40(DW1000_TX_TIME, 0);
+}
+
+void DW1000::sendString(char* message)
+{
+    sendFrame((uint8_t*)message, strlen(message)+1);
+}
+
+void DW1000::receiveString(char* message)
+{
+    readRegister(DW1000_RX_BUFFER, 0, (uint8_t*)message, getFramelength());  // get data from buffer
+}
+
+void DW1000::sendFrame(uint8_t* message, uint16_t length)
+{
+    //if (length >= 1021) length = 1021;                            // check for maximim length a frame can have with 1024 Byte frames [not used, see constructor]
+    if (length >= 125) length = 125;                                // check for maximim length a frame can have with 127 Byte frames
+    uint8_t len_7bit = length;
+    writeRegister(DW1000_TX_BUFFER, 0, message, len_7bit);            // fill buffer
+
+    /* support for frames over 127 bytes
+        uint8_t backup = readRegister8(DW1000_TX_FCTRL, 1);             // put length of frame
+        length += 2;                                                    // including 2 CRC Bytes
+        length = ((backup & 0xFC) << 8) | (length & 0x03FF);
+        writeRegister16(DW1000_TX_FCTRL, 0, length);
+    */
+    len_7bit += 2;                                                    // including 2 CRC Bytes
+    writeRegister8(DW1000_TX_FCTRL, 0, len_7bit);
+
+    stopTRX();                                                      // stop receiving
+    writeRegister8(DW1000_SYS_CTRL, 0, 0x02 | 0x80);                       // trigger sending process by setting the TXSTRT bit
+//    startRX();                                                      // enable receiver again
+}
+
+void DW1000::setupSyncedFrame(uint8_t* message, uint16_t length)
+{
+    //if (length >= 1021) length = 1021;                            // check for maximim length a frame can have with 1024 Byte frames [not used, see constructor]
+    if (length >= 125) length = 125;                                // check for maximim length a frame can have with 127 Byte frames
+    writeRegister(DW1000_TX_BUFFER, 0, message, length);            // fill buffer
+
+    uint8_t backup = readRegister8(DW1000_TX_FCTRL, 1);             // put length of frame
+    length += 2;                                                    // including 2 CRC Bytes
+    length = ((backup & 0xFC) << 8) | (length & 0x03FF);
+    writeRegister16(DW1000_TX_FCTRL, 0, length);
+}
+
+void DW1000::armSyncedFrame()
+{
+    stopTRX();                                                      // stop receiving
+    writeRegister16(DW1000_EXT_SYNC, DWEXTSYNC_EC_CTRL, 33<<3 | 0x01);                       // Sync register = TX start with a wait of 33 (recomended, value must fulfill wait % 4 = 1)
+}
+
+void DW1000::sendDelayedFrame(uint8_t* message, uint16_t length, uint64_t TxTimestamp)
+{
+    //if (length >= 1021) length = 1021;                            // check for maximim length a frame can have with 1024 Byte frames [not used, see constructor]
+    if (length >= 125) length = 125;                                // check for maximim length a frame can have with 127 Byte frames
+    writeRegister(DW1000_TX_BUFFER, 0, message, length);            // fill buffer
+
+    uint8_t backup = readRegister8(DW1000_TX_FCTRL, 1);             // put length of frame
+    length += 2;                                                    // including 2 CRC Bytes
+    length = ((backup & 0xFC) << 8) | (length & 0x03FF);
+    writeRegister16(DW1000_TX_FCTRL, 0, length);
+
+    writeRegister40(DW1000_DX_TIME, 0, TxTimestamp);                //write the timestamp on which to send the message
+
+    stopTRX();                                                      // stop receiving
+    writeRegister8(DW1000_SYS_CTRL, 0, 0x02 | 0x04 | 0x80);         // trigger sending process by setting the TXSTRT and TXDLYS bit. Set Wait4resp to automatically enter RX mode after tx.
+}
+
+void DW1000::startRX()
+{
+    writeRegister8(DW1000_SYS_CTRL, 0x01, 0x01);                    // start listening for preamble by setting the RXENAB bit
+}
+
+void DW1000::stopTRX()
+{
+    writeRegister8(DW1000_SYS_CTRL, 0, 0x40);                       // disable tranceiver go back to idle mode
+}
+
+// PRIVATE Methods ------------------------------------------------------------------------------------
+void DW1000::loadLDE()                                              // initialise LDE algorithm LDELOAD User Manual p22
+{
+    spi.frequency(SPIRATE_OSC);             // with a 1MHz clock rate (worked up to 49MHz in our Test)
+
+    writeRegister16(DW1000_PMSC, 0, 0x0301);                        // set clock to XTAL so OTP is reliable
+    writeRegister16(DW1000_OTP_IF, DWOTP_OTP_CTRL, 0x8000);                   // set LDELOAD bit in OTP
+    wait_us(150);
+    writeRegister16(DW1000_PMSC, 0, 0x0200);                        // recover to PLL clock
+
+    wait_ms(1);
+
+    spi.frequency(SPIRATE_PLL);             // with a 1MHz clock rate (worked up to 49MHz in our Test)
+
+}
+
+void DW1000::loadLDOTUNE()
+{
+    uint64_t LDOTuningValue = readOTP(0x0004);
+    if (LDOTuningValue != 0) {
+        LDOTuningValue = LDOTuningValue | ((uint64_t)(readOTP(0x0005) & 0x00ff) << 32);
+        writeRegister40(DW1000_RF_CONF,DWRFCONF_RF_LDOTUNE,LDOTuningValue);
+    }
+}
+
+void DW1000::resetRX()
+{
+    writeRegister8(DW1000_PMSC, 3, 0xE0);   // set RX reset
+    writeRegister8(DW1000_PMSC, 3, 0xF0);   // clear RX reset
+}
+
+void DW1000::resetAll()
+{
+    spi.frequency(SPIRATE_OSC);             // with a 1MHz clock rate (worked up to 49MHz in our Test)
+
+    writeRegister8(DW1000_PMSC, 0, 0x01);   // set clock to XTAL
+    writeRegister8(DW1000_PMSC, 3, 0x00);   // set All reset
+    wait_us(10);                            // wait for PLL to lock
+    writeRegister8(DW1000_PMSC, 3, 0xF0);   // clear All reset
+
+    wait_ms(1);
+
+    spi.frequency(SPIRATE_PLL);             // with a 1MHz clock rate (worked up to 49MHz in our Test)
+}
+
+/// After writes have been completed reset the device.
+bool DW1000::writeOTP(uint16_t word_address,uint32_t data)
+{
+    spi.frequency(SPIRATE_OSC);             // with a 1MHz clock rate (worked up to 49MHz in our Test)
+
+    writeRegister8(DW1000_PMSC, 0, 0x01);   // set clock to XTAL
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x03);  //
+    writeRegister16(DW1000_OTP_IF,DWOTP_OTP_WDAT,0x9220);  //
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x08);  //
+    wait_ms(1);
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x02);  //
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x88);  //
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x80);  //
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00);  //
+
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x05);  //
+    writeRegister16(DW1000_OTP_IF,DWOTP_OTP_WDAT,0x000E);  //
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x08);  //
+    wait_ms(1);
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x04);  //
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x88);  //
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x80);  //
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00);  //
+
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x01);  //
+    writeRegister16(DW1000_OTP_IF,DWOTP_OTP_WDAT,0x1024);  //
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x08);  //
+    wait_ms(1);
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x00);  //
+
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00);  //
+    writeRegister32(DW1000_OTP_IF,DWOTP_OTP_WDAT,data);  //
+    writeRegister16(DW1000_OTP_IF,DWOTP_OTP_ADDR,word_address);  //
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x40);  //
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00);  //
+    wait_ms(1);
+
+    for (int i=0; i<10; i++) {
+        if (readOTP(word_address) == data)
+            return true;
+        writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x40);  // retry
+        writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00);
+        wait_ms(1);
+    }
+    return false;
+}
+
+
+uint32_t DW1000::readOTP(uint16_t word_address)
+{
+    writeRegister16(DW1000_OTP_IF,DWOTP_OTP_ADDR,word_address); // write address
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x03);  // read address load
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x01);  // read
+    uint32_t data = readRegister32(DW1000_OTP_IF,DWOTP_OTP_RDAT);
+    writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00);  // OTP idle
+    return data;
+}
+
+void DW1000::setInterrupt(bool RX, bool TX)
+{
+    writeRegister16(DW1000_SYS_MASK, 0, RX*0x4000 | TX*0x0080);  // RX good frame 0x4000, TX done 0x0080
+}
+
+void DW1000::ISR()
+{
+    uint64_t status = getStatus();
+    if (status & 0x4000) {                                          // a frame was received
+        callbackRX.call();
+        writeRegister16(DW1000_SYS_STATUS, 0, 0x6F00);              // clearing of receiving status bits
+    }
+    if (status & 0x80) {                                            // sending complete
+        callbackTX.call();
+        writeRegister8(DW1000_SYS_STATUS, 0, 0xF8);                 // clearing of sending status bits
+    }
+}
+
+uint16_t DW1000::getFramelength()
+{
+    uint16_t framelength = readRegister16(DW1000_RX_FINFO, 0);      // get framelength
+    framelength = (framelength & 0x03FF) - 2;                       // take only the right bits and subtract the 2 CRC Bytes
+    return framelength;
+}
+
+// SPI Interface ------------------------------------------------------------------------------------
+uint8_t DW1000::readRegister8(uint8_t reg, uint16_t subaddress)
+{
+    uint8_t result;
+    readRegister(reg, subaddress, &result, 1);
+    return result;
+}
+
+uint16_t DW1000::readRegister16(uint8_t reg, uint16_t subaddress)
+{
+    uint16_t result;
+    readRegister(reg, subaddress, (uint8_t*)&result, 2);
+    return result;
+}
+
+uint32_t DW1000::readRegister32(uint8_t reg, uint16_t subaddress)
+{
+    uint32_t result;
+    readRegister(reg, subaddress, (uint8_t*)&result, 4);
+    return result;
+}
+
+
+uint64_t DW1000::readRegister40(uint8_t reg, uint16_t subaddress)
+{
+    uint64_t result = 0;
+    readRegister(reg, subaddress, (uint8_t*)&result, 5);
+    return result;
+}
+uint64_t DW1000::readRegister64(uint8_t reg, uint16_t subaddress)
+{
+    uint64_t result;
+    readRegister(reg, subaddress, (uint8_t*)&result, 8);
+    return result;
+}
+
+void DW1000::writeRegister8(uint8_t reg, uint16_t subaddress, uint8_t buffer)
+{
+    writeRegister(reg, subaddress, &buffer, 1);
+}
+
+void DW1000::writeRegister16(uint8_t reg, uint16_t subaddress, uint16_t buffer)
+{
+    writeRegister(reg, subaddress, (uint8_t*)&buffer, 2);
+}
+
+void DW1000::writeRegister32(uint8_t reg, uint16_t subaddress, uint32_t buffer)
+{
+    writeRegister(reg, subaddress, (uint8_t*)&buffer, 4);
+}
+
+void DW1000::writeRegister40(uint8_t reg, uint16_t subaddress, uint64_t buffer)
+{
+    writeRegister(reg, subaddress, (uint8_t*)&buffer, 5);
+}
+
+void DW1000::readRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length)
+{
+    setupTransaction(reg, subaddress, false);
+    for(int i=0; i<length; i++)                             // get data
+        buffer[i] = spi.write(0x00);
+    deselect();
+}
+
+void DW1000::writeRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length)
+{
+    setupTransaction(reg, subaddress, true);
+    for(int i=0; i<length; i++)                             // put data
+        spi.write(buffer[i]);
+    deselect();
+}
+
+void DW1000::setupTransaction(uint8_t reg, uint16_t subaddress, bool write)
+{
+    reg |=  (write * DW1000_WRITE_FLAG);                                        // set read/write flag
+    select();
+    if (subaddress > 0) {                                                       // there's a subadress, we need to set flag and send second header byte
+        spi.write(reg | DW1000_SUBADDRESS_FLAG);
+        if (subaddress > 0x7F) {                                                // sub address too long, we need to set flag and send third header byte
+            spi.write((uint8_t)(subaddress & 0x7F) | DW1000_2_SUBADDRESS_FLAG); // and
+            spi.write((uint8_t)(subaddress >> 7));
+        } else {
+            spi.write((uint8_t)subaddress);
+        }
+    } else {
+        spi.write(reg);                                                         // say which register address we want to access
+    }
+}
+
+void DW1000::select()       // always called to start an SPI transmission
+{
+    irq.disable_irq();      // disable interrupts from DW1000 during SPI becaus this leads to crashes!      TODO: if you have other interrupt handlers attached on the micro controller, they could also interfere.
+    cs = 0;                 // set Cable Select pin low to start transmission
+}
+
+void DW1000::deselect()     // always called to end an SPI transmission
+{
+    cs = 1;                 // set Cable Select pin high to stop transmission
+    irq.enable_irq();       // reenable the interrupt handler
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DW1000.h.orig	Thu Apr 07 16:27:51 2016 +0000
@@ -0,0 +1,424 @@
+// by Matthias Grob & Manuel Stalder - ETH Zürich - 2015
+
+#ifndef DW1000_H
+#define DW1000_H
+
+#include "mbed.h"
+
+// register addresses
+//      Mnemonic                    Address Bytes Description
+#define DW1000_DEV_ID               0x00 //     4 Device Identifier – includes device type and revision information
+#define DW1000_EUI                  0x01 //     8 Extended Unique Identifier
+#define DW1000_PANADR               0x03 //     4 PAN Identifier and Short Address
+#define DW1000_SYS_CFG              0x04 //     4 System Configuration bitmap
+#define DW1000_SYS_TIME             0x06 //     5 System Time Counter (40-bit)
+#define DW1000_TX_FCTRL             0x08 //     5 Transmit Frame Control
+#define DW1000_TX_BUFFER            0x09 //  1024 Transmit Data Buffer
+#define DW1000_DX_TIME              0x0A //     5 Delayed Send or Receive Time (40-bit)
+#define DW1000_RX_FWTO              0x0C //     2 Receive Frame Wait Timeout Period
+#define DW1000_SYS_CTRL             0x0D //     4 System Control Register
+#define DW1000_SYS_MASK             0x0E //     4 System Event Mask Register
+#define DW1000_SYS_STATUS           0x0F //     5 System Event Status Register
+#define DW1000_RX_FINFO             0x10 //     4 RX Frame Information                (in double buffer set)
+#define DW1000_RX_BUFFER            0x11 //  1024 Receive Data Buffer                 (in double buffer set)
+#define DW1000_RX_FQUAL             0x12 //     8 Rx Frame Quality information        (in double buffer set)
+#define DW1000_RX_TTCKI             0x13 //     4 Receiver Time Tracking Interval     (in double buffer set)
+#define DW1000_RX_TTCKO             0x14 //     5 Receiver Time Tracking Offset       (in double buffer set)
+#define DW1000_RX_TIME              0x15 //    14 Receive Message Time of Arrival     (in double buffer set)
+#define DW1000_TX_TIME              0x17 //    10 Transmit Message Time of Sending    (in double buffer set)
+#define DW1000_TX_ANTD              0x18 //     2 16-bit Delay from Transmit to Antenna
+#define DW1000_SYS_STATE            0x19 //     5 System State information
+#define DW1000_ACK_RESP_T           0x1A //     4 Acknowledgement Time and Response Time
+#define DW1000_RX_SNIFF             0x1D //     4 Pulsed Preamble Reception Configuration
+#define DW1000_TX_POWER             0x1E //     4 TX Power Control
+#define DW1000_CHAN_CTRL            0x1F //     4 Channel Control
+#define DW1000_USR_SFD              0x21 //    41 User-specified short/long TX/RX SFD sequences
+#define DW1000_AGC_CTRL             0x23 //    32 Automatic Gain Control configuration
+#define DW1000_EXT_SYNC             0x24 //    12 External synchronisation control.
+#define DW1000_ACC_MEM              0x25 //  4064 Read access to accumulator data
+#define DW1000_GPIO_CTRL            0x26 //    44 Peripheral register bus 1 access - GPIO control
+#define DW1000_DRX_CONF             0x27 //    44 Digital Receiver configuration
+#define DW1000_RF_CONF              0x28 //    58 Analog RF Configuration
+#define DW1000_TX_CAL               0x2A //    52 Transmitter calibration block
+#define DW1000_FS_CTRL              0x2B //    21 Frequency synthesiser control block
+#define DW1000_AON                  0x2C //    12 Always-On register set
+#define DW1000_OTP_IF               0x2D //    18 One Time Programmable Memory Interface
+#define DW1000_LDE_CTRL             0x2E //     - Leading edge detection control block
+#define DW1000_DIG_DIAG             0x2F //    41 Digital Diagnostics Interface
+#define DW1000_PMSC                 0x36 //    48 Power Management System Control Block
+
+// AGC_CTRL sub registers
+#define DWAGCCTRL_AGC_CTRL1         0x02
+#define DWAGCCTRL_AGC_TUNE1         0x04
+#define DWAGCCTRL_AGC_TUNE2         0x0C
+#define DWAGCCTRL_AGC_TUNE3         0x12
+
+// EXT_SYNC sub registers
+#define DWEXTSYNC_EC_CTRL           0x00
+#define DWEXTSYNC_EC_RXTC           0x04
+#define DWEXTSYNC_EC_GOLP           0x08
+
+// GPIO sub registers
+#define DWGPIO_GPIO_MODE           0x00
+#define DWGPIO_GPIO_DIR            0x08
+#define DWGPIO_GPIO_DOUT           0x0C
+#define DWGPIO_GPIO_IRQE           0x10
+#define DWGPIO_GPIO_ISEN           0x14
+#define DWGPIO_GPIO_IMODE          0x18
+#define DWGPIO_GPIO_IBES           0x1C
+#define DWGPIO_GPIO_ICLR           0x20
+#define DWGPIO_GPIO_IDBE           0x24
+#define DWGPIO_GPIO_RAW            0x28
+
+// DRX sub registers
+#define DWDRX_DRX_TUNE0B            0x02
+#define DWDRX_DRX_TUNE1A            0x04
+#define DWDRX_DRX_TUNE1B            0x06
+#define DWDRX_DRX_TUNE2             0x08
+#define DWDRX_DRX_SFDTOC            0x20
+#define DWDRX_DRX_PRETOC            0x24
+#define DWDRX_DRX_TUNE4H            0x26
+
+//RF conf sub registers
+#define DWRFCONF_RF_CONF            0x00
+#define DWRFCONF_RF_RXCTRLH         0x0B
+#define DWRFCONF_RF_TXCTRL          0x0C
+#define DWRFCONF_RF_STATUS          0x2C
+#define DWRFCONF_RF_LDOTUNE         0x30
+
+// TX cal sub registers
+#define DWTXCAL_TC_SARC             0x00
+#define DWTXCAL_TC_SARL             0x03
+#define DWTXCAL_TC_SARW             0x06
+#define DWTXCAL_TC_PGDELAY          0x0B
+#define DWTXCAL_TC_PGTEST           0x0C
+
+// Freq synth sub registers
+#define DWFSCTRL_FS_PLLCFG          0x07
+#define DWFSCTRL_FS_PLLTUNE         0x0B
+#define DWFSCTRL_FS_XTALT           0x0E
+
+// Always on sub registers
+#define DWAON_AON_WCFG              0x00
+#define DWAON_AON_CTRL              0x02
+#define DWAON_AON_RDAT              0x03
+#define DWAON_AON_ADDR              0x04
+#define DWAON_AON_CFG0              0x06
+#define DWAON_AON_CFG1              0x0A
+
+// OTP sub registers
+#define DWOTP_OTP_WDAT              0x00
+#define DWOTP_OTP_ADDR              0x04
+#define DWOTP_OTP_CTRL              0x06
+#define DWOTP_OTP_STAT              0x08
+#define DWOTP_OTP_RDAT              0x0A
+#define DWOTP_OTP_SRDAT             0x0E
+#define DWOTP_OTP_SF                0x12
+
+//LDE_IF sub registers
+#define DWLDE_LDE_THRESH            0x0000
+#define DWLDE_LDE_CFG1              0x0806
+#define DWLDE_LDE_PPINDX            0x1000
+#define DWLDE_LDE_PPAMPL            0x1002
+#define DWLDE_LDE_RXANTD            0x1804
+#define DWLDE_LDE_CFG2              0x1806
+#define DWLDE_LDE_REPC              0x2804
+
+// Dig Diag sub registers
+#define DWDIAG_EVC_CTRL             0x00
+#define DWDIAG_EVC_PHE              0x04
+#define DWDIAG_EVC_RSE              0x06
+#define DWDIAG_EVC_FCG              0x08
+#define DWDIAG_EVC_FCE              0x0A
+#define DWDIAG_EVC_FFR              0x0C
+#define DWDIAG_EVC_OVR              0x0E
+#define DWDIAG_EVC_STO              0x10
+#define DWDIAG_EVC_PTO              0x12
+#define DWDIAG_EVC_FWTO             0x14
+#define DWDIAG_EVC_TXFS             0x16
+#define DWDIAG_EVC_HPW              0x18
+#define DWDIAG_EVC_TPW              0x1A
+#define DWDIAG_DIAG_TMC             0x24
+
+// power control sub registers
+#define DWPMSC_PMSC_CTRL0           0x00
+#define DWPMSC_PMSC_CTRL1           0x04
+#define DWPMSC_PMSC_SNOZT           0x0C
+#define DWPMSC_PMSC_TXFSEQ          0x26
+#define DWPMSC_PMSC_LEDC            0x28
+
+
+#define DW1000_WRITE_FLAG           0x80 // First Bit of the address has to be 1 to indicate we want to write
+#define DW1000_SUBADDRESS_FLAG      0x40 // if we have a sub address second Bit has to be 1
+#define DW1000_2_SUBADDRESS_FLAG    0x80 // if we have a long sub adress (more than 7 Bit) we set this Bit in the first part
+
+/*
+From user manual 10.5
+Table 59:
+DW1000 supported UWB channels and recommended preamble codes
+
+channel 16MHzPrf    64MHzPrf
+1       1,2         9, 10, 11, 12
+2       3, 4        9, 10, 11, 12
+3       5, 6        9, 10, 11, 12
+4       7, 8        17, 18, 19, 20
+5       3, 4        9, 10, 11, 12
+7       7, 8        17, 18, 19, 20
+*/
+
+
+/** Class for holding DW1000 config options
+*
+*/
+class DW1000Setup
+{
+public:
+
+/// Constructor - default settings are close to hardware defaults.
+    DW1000Setup() {
+        channel = 5;
+        prf =prf16MHz;
+        dataRate = kbps850;
+        sfd = standard;
+        preamble = pre128;
+        preambleCode = 3;
+        enableSmartPower = true;
+    }
+
+/// enum for PRF options
+    enum prf_e {prf16MHz,prf64MHz};
+
+/// enum for data rate options    
+    enum dataRate_e {kbps110,kbps850,kbps6800};
+    
+/// enum for SFD options    
+    enum sfd_e {standard, decaWave, user};
+    
+/// enum for preamble length options    
+    enum preamble_e { pre64, pre128, pre256, pre512, pre1024, pre1536, pre2048, pre4096};
+
+/** Set the PRF
+* @return true if a valid option
+*/
+    bool setPRF(enum prf_e newSetting) {
+        prf = newSetting;
+        return true;
+    };
+
+/** Set the Channel
+* @return true if a valid option
+*/
+    bool setChannel(unsigned char newChannel) {
+        if ((channel > 0) && ((channel <= 5) || (channel == 7))) {
+            channel = newChannel;
+            return true;
+        }
+        return false;
+    };
+/** Set the SFD
+* @return true if a valid option
+*/
+    bool setSfd(enum sfd_e newSetting) {
+        sfd = newSetting;
+        return true;
+    };
+/** Set the Preamble length
+* @return true if a valid option
+*/
+    bool setPreambleLength(enum preamble_e newSetting) {
+        preamble = newSetting;
+        return true;
+    };
+/** Set the Data rate
+* @return true if a valid option
+*/
+    bool setDataRate(enum dataRate_e newSetting)  {
+        dataRate = newSetting;
+        return true;
+    };
+/** Set the Preamble code
+* @return true if a valid option
+*
+* note - not all codes are valid for all channels. Set the channel first.
+* TODO - enforce code restrictions
+*/
+    bool setPreambleCode(unsigned char newCode) {
+        if ((newCode > 0) && (newCode <= 24)) {
+            preambleCode = newCode;
+            return true;
+        }
+        return false;
+    };
+/** Set the smartpower state
+* @return true if a valid option
+*
+* only takes effect at 6.8Mb/s
+*/
+    bool setSmartPower(bool enable) {
+        enableSmartPower = enable;
+        return true;
+    };
+
+/** Get the current channel
+* @return the channel number
+*/
+    unsigned char getChannel() {
+        return channel;
+    };
+    enum prf_e getPRF() {
+        return prf;
+    };
+    enum dataRate_e getDataRate() {
+        return dataRate;
+    };
+    
+    enum sfd_e getSfd() {return sfd;};
+    enum preamble_e getPreambleLength() {
+        return preamble;
+    };
+    unsigned char getPreambleCode() {
+        return preambleCode;
+    };
+    bool getSmartPower() {
+        return  enableSmartPower;
+    };
+
+private:
+    unsigned char channel; // 1-5 , 7
+    enum prf_e prf;
+    enum dataRate_e dataRate;
+    enum sfd_e sfd;
+    enum preamble_e preamble;
+    unsigned char preambleCode; // 1-24. See section 10.5 of user manual for details.
+    bool enableSmartPower;
+};
+
+
+typedef enum {minPacketSize, tunedDefault, user110k} UWBMode;
+
+/** A DW1000 driver
+*/
+class DW1000
+{
+public:
+
+    DW1000(UWBMode setup, PinName MOSI, PinName MISO, PinName SCLK, PinName CS, PinName IRQ);              // constructor, uses SPI class
+    void setCallbacks(void (*callbackRX)(void), void (*callbackTX)(void));                  // setter for callback functions, automatically enables interrupt, if NULL is passed the coresponding interrupt gets disabled
+    template<typename T>
+    void setCallbacks(T* tptr, void (T::*mptrRX)(void), void (T::*mptrTX)(void)) {      // overloaded setter to treat member function pointers of objects
+        callbackRX.attach(tptr, mptrRX);                                                    // possible client code: dw.setCallbacks(this, &A::callbackRX, &A::callbackTX);
+        callbackTX.attach(tptr, mptrTX);                                                    // concept seen in line 100 of http://developer.mbed.org/users/mbed_official/code/mbed/docs/4fc01daae5a5/InterruptIn_8h_source.html
+        setInterrupt(true,true);
+    }
+
+    // Device API
+    uint32_t getDeviceID();                                                                 // gets the Device ID which should be 0xDECA0130 (good for testing SPI!)
+    uint64_t getEUI();                                                                      // gets 64 bit Extended Unique Identifier according to IEEE standard
+    void setEUI(uint64_t EUI);                                                              // sets 64 bit Extended Unique Identifier according to IEEE standard
+    float getVoltage();                                                                     // gets the current chip voltage measurement form the A/D converter
+    float getTemperature();                                                                 // gets the current chip temperature measurement form the A/D converter
+    uint64_t getStatus();                                                                   // get the 40 bit device status
+    uint64_t getRXTimestamp();
+    uint64_t getTXTimestamp();
+
+    void sendString(char* message);                                                         // to send String with arbitrary length
+    void receiveString(char* message);                                                      // to receive char string (length of the buffer must be 1021 to be safe)
+    void sendFrame(uint8_t* message, uint16_t length);                                      // send a raw frame (length in bytes)
+    void sendDelayedFrame(uint8_t* message, uint16_t length, uint64_t TxTimestamp);
+
+    void setupSyncedFrame(uint8_t* message, uint16_t length);
+    void armSyncedFrame();
+
+    void startRX();                                                                         // start listening for frames
+    void stopTRX();                                                                         // disable tranceiver go back to idle mode
+
+    void setRxDelay(uint16_t ticks);
+    void setTxDelay(uint16_t ticks);
+
+    uint16_t getFramelength();                                                              // to get the framelength of the received frame from the PHY header
+
+    void readRxBuffer( uint8_t *buffer, int length ) {
+        readRegister(DW1000_RX_BUFFER, 0, buffer, length);
+    }
+
+    uint32_t readOTP (uint16_t word_address);
+    bool writeOTP(uint16_t word_address,uint32_t data);                                          // program a value in the OTP. It is recommended to reset afterwards.
+
+    /** Get setup description
+    *
+    * @param buffer Data buffer to place description in
+    * @param len Length of data buffer
+    *
+    * Places a text string describing the current setup into the suppled buffer.
+    */
+    void getSetup(char *buffer, int len);
+
+protected:
+    void resetRX();                                                                         // soft reset only the tranciever part of DW1000
+    void setInterrupt(bool RX, bool TX);                                                    // set Interrupt for received a good frame (CRC ok) or transmission done
+
+    /** Set Transmit gain
+    *
+    * @param normalPowercB Normal transmit gain to use.
+    * @param boost500 Gain to use for 6.8Mb/s packets of under 500ms.
+    * @param boost250 Gain to use for 6.8Mb/s packets of under 250ms.
+    * @param boost125 Gain to use for 6.8Mb/s packets of under 125ms.
+    *
+    * All gains are in cB (dB * 10). Gains can be between 0 and 335 (33.5dB).
+    * Boost gains are optional, if not specified boost gains are set to the power for the lower rate (e.g. boost125 is set to the boost250 level).
+    */
+    void setTxPower(uint16_t normalPowercB, uint16_t boost500 = 0, uint16_t boost250 = 0, uint16_t boost125 = 0);
+
+
+private:
+    void resetAll();                                                                        // soft reset the entire DW1000 (some registers stay as they were see User Manual)
+
+    void setupRadio();
+
+    // system register setup functions
+    void setupAGC();
+    void setupRxConfig();
+    void setupLDE();
+    void setupChannel();
+    void setupTxFrameCtrl();
+    void setupAnalogRF();
+    void setupFreqSynth();
+    void setupTxCalibration();
+    void setupSystemConfig();
+    void loadLDE();                                                                         // load the leading edge detection algorithm to RAM, [IMPORTANT because receiving malfunction may occur] see User Manual LDELOAD on p22 & p158
+    void loadLDOTUNE();                                                                     // load the LDO tuning as set in the factory
+
+    uint8_t powerToRegValue(uint16_t powercB);
+
+    DW1000Setup systemConfig;
+
+
+
+    // Interrupt
+    InterruptIn irq;                                                                        // Pin used to handle Events from DW1000 by an Interrupthandler
+    FunctionPointer callbackRX;                                                             // function pointer to callback which is called when successfull RX took place
+    FunctionPointer callbackTX;                                                             // function pointer to callback which is called when successfull TX took place
+    void ISR();                                                                             // interrupt handling method (also calls according callback methods)
+
+    // SPI Inteface
+    SPI spi;                                                                                // SPI Bus
+    DigitalOut cs;                                                                          // Slave selector for SPI-Bus (here explicitly needed to start and end SPI transactions also usable to wake up DW1000)
+
+    uint8_t readRegister8(uint8_t reg, uint16_t subaddress);                                // expressive methods to read or write the number of bits written in the name
+    uint16_t readRegister16(uint8_t reg, uint16_t subaddress);
+    uint32_t readRegister32(uint8_t reg, uint16_t subaddress);
+    uint64_t readRegister40(uint8_t reg, uint16_t subaddress);
+    uint64_t readRegister64(uint8_t reg, uint16_t subaddress);
+    void writeRegister8(uint8_t reg, uint16_t subaddress, uint8_t buffer);
+    void writeRegister16(uint8_t reg, uint16_t subaddress, uint16_t buffer);
+    void writeRegister32(uint8_t reg, uint16_t subaddress, uint32_t buffer);
+    void writeRegister40(uint8_t reg, uint16_t subaddress, uint64_t buffer);
+
+    void readRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length);       // reads the selected part of a slave register into the buffer memory
+    void writeRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length);      // writes the buffer memory to the selected slave register
+    void setupTransaction(uint8_t reg, uint16_t subaddress, bool write);                    // sets up an SPI read or write transaction with correct register address and offset
+    void select();                                                                          // selects the only slave for a transaction
+    void deselect();                                                                        // deselects the only slave after transaction
+};
+
+#endif
\ No newline at end of file