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:
Mon Apr 18 16:58:27 2016 +0000
Parent:
7:b13881dbb09d
Child:
9:326bf149c8bc
Commit message:
f

Changed in this revision

DW1000.cpp 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
DW1000Registers.h Show annotated file Show diff for this revision Revisions of this file
DW1000Setup.cpp Show annotated file Show diff for this revision Revisions of this file
DW1000Setup.h Show annotated file Show diff for this revision Revisions of this file
--- a/DW1000.cpp	Wed Apr 13 09:07:14 2016 +0000
+++ b/DW1000.cpp	Mon Apr 18 16:58:27 2016 +0000
@@ -6,128 +6,28 @@
 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);
+    DW1000Setup newSetup(DW1000Setup::fastLocationC5);
+    systemConfig.applyConfig(&newSetup);
 
     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
+setupRadio();
+            setTxPower(250,250,250+30,250+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;
+DW1000Setup* DW1000::getSetup() {
+    return &systemConfig;
     }
 
-    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();
@@ -363,10 +263,10 @@
     else
         registerValue |= 0x02 << 18;
 
-    if (systemConfig.getSfd() == DW1000Setup::decaWave) 
+    if (systemConfig.getSfd() == DW1000Setup::decaWave)
         registerValue |= 0x01 << 17; // enable DW own SFD
 
-    if (systemConfig.getSfd() == DW1000Setup::user) {     
+    if (systemConfig.getSfd() == DW1000Setup::user) {
         registerValue |= 0x01 << 20; // enable user set SFD Tx
         registerValue |= 0x01 << 21; // enable user set SFD Rx
     }
@@ -435,6 +335,8 @@
     powerReg |= powerToRegValue(boost500) << 8;
     powerReg |= powerToRegValue(boost250) << 16;
     powerReg |= powerToRegValue(boost125) << 24;
+    writeRegister32(DW1000_TX_POWER, 0, powerReg);
+
 }
 
 void DW1000::setupAnalogRF()
--- a/DW1000.h	Wed Apr 13 09:07:14 2016 +0000
+++ b/DW1000.h	Mon Apr 18 16:58:27 2016 +0000
@@ -5,328 +5,14 @@
 
 #include "mbed.h"
 #include "BurstSPI.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
+#include "DW1000Registers.h"
+#include "DW1000Setup.h"
 
-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, ///< PRF rate of 16MHz. Lower power
-                prf64MHz ///< PRF rate of 64MHz. Higher power but more accurate timing.
-               };
-
-/// enum for data rate options
-    enum dataRate_e {kbps110, ///< Data rate of 110kb/s (non-standard)
-                     kbps850,///< Data rate of 850kb/s
-                     kbps6800///< Data rate of 6.8Mb/s
-                    };
-
-/// enum for SFD options
-    enum sfd_e {standard, ///< IEEE standard SFD
-                decaWave, ///< Decawave defined SFD
-                user ///< user defined SFD
-               };
-
-/// enum for preamble length options
-    enum preamble_e { pre64,///< Preamble is 64 symbols
-                      pre128,///< Preamble is 128 symbols (non-standard)
-                      pre256,///< Preamble is 256 symbols (non-standard)
-                      pre512,///< Preamble is 512 symbols (non-standard)
-                      pre1024,///< Preamble is 1024 symbols
-                      pre1536,///< Preamble is 1536 symbols (non-standard)
-                      pre2048, ///< Preamble is 2048 symbols (non-standard)
-                      pre4096///< Preamble is 4096 symbols
-                    };
-
-    /** 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;
-    };
-    /** Get the current PRF
-    * @return the PRF
-    */
-    enum prf_e getPRF() {
-        return prf;
-    };
-    /** Get the current data rate
-    * @return the data rate
-    */    enum dataRate_e getDataRate() {
-        return dataRate;
-    };
-
-    /** Get the current SFD mode
-    * @return the SFD
-    */    enum sfd_e getSfd() {
-        return sfd;
-    };
-    /** Get the current preamble length
-    * @return the  preamble length
-    */
-        enum preamble_e getPreambleLength() {
-        return preamble;
-    };
-        /** Get the current preamble code
-    * @return the preamble code
-    */
-    unsigned char getPreambleCode() {
-        return preambleCode;
-    };
-        /** Get the current smart power mode
-    * @return true if smartpower is on
-    */
-    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;
-};
+#define TIMEUNITS_TO_US       (1/(128*499.2))               // conversion between the decawave timeunits (ca 15.65ps) to microseconds.
+#define US_TO_TIMEUNITS       ((uint32_t)(128*499.2))                   // conversion between microseconds to the decawave timeunits (ca 15.65ps).
+#define c_mPerS     299792458
+#define c_mmPerTick (c_mPerS * TIMEUNITS_TO_US / 1000)
+#define c_mPerTick  (c_mmPerTick/1000)
 
 
 typedef enum {minPacketSize, tunedDefault, user110k} UWBMode;
@@ -489,6 +175,21 @@
     */
     void setTxDelay(uint16_t ticks);
 
+
+    /** Set receive antenna delay in meters
+    * @param errorDistance Delay in meters at speed of light
+    */
+    void setRxDelayDistance(double errorDistance) {
+        setRxDelay(errorDistance/c_mPerTick);
+    };
+
+    /** Set transmit antenna delay  in meters
+    * @param errorDistance Delay in meters at speed of light
+    */
+    void setTxDelayDistance(double errorDistance) {
+        setTxDelay(errorDistance/c_mPerTick);
+    };
+
     /** Get last packet size
     * @return The length in bytes of the last packet received
     */
@@ -522,15 +223,25 @@
     */
     bool writeOTP(uint16_t word_address,uint32_t data);                                          // program a value in the OTP. It is recommended to reset afterwards.
 
-
-    /** Get setup description
+    /** get the current radio configuration
+    * @return A pointer to a DW1000Setup object of the current setup.
     *
-    * @param buffer Data buffer to place description in
-    * @param len Length of data buffer
+    * Note to change the setup you must make a copy of the current setup and then pass that to applySetup().
+    */
+    DW1000Setup *getSetup();
+
+    /** apply a new radio setup to the UWB system
+    * @param setup The new settings to use
+    * @return true if the setup was applied.
     *
-    * Places a text string describing the current setup into the suppled buffer.
+    * The setup object supplied is copied and can be disposed of after the call.
+    * If the supplied setup fails DW1000Setup::check() then it is ignored and the function returns false.
     */
-    void getSetup(char *buffer, int len);
+//    bool applySetup(DW1000Setup *setup);
+
+
+    uint32_t readRegister32(uint8_t reg, uint16_t subaddress);
+    void setTxPower(uint16_t normalPowercB, uint16_t boost500 = 0, uint16_t boost250 = 0, uint16_t boost125 = 0);
 
 protected:
     /** Reset the reciever logic
@@ -558,8 +269,9 @@
     * 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);
+//    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)
@@ -597,7 +309,7 @@
 
     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);
+//    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);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DW1000Registers.h	Mon Apr 18 16:58:27 2016 +0000
@@ -0,0 +1,153 @@
+#ifndef __DWREG_H__
+#define __DWREG_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
+#define DWDRX_RXPAC_NOSAT           0x2c
+
+
+//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
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DW1000Setup.cpp	Mon Apr 18 16:58:27 2016 +0000
@@ -0,0 +1,262 @@
+
+#include "DW1000Setup.h"
+
+DW1000Setup::DW1000Setup(UWBMode modeToUse)
+{
+    switch (modeToUse) {
+        case user110k:  // values from Matthias Grob & Manuel Stalder - ETH Zürich - library
+
+            setChannel(5);
+            setPRF(prf16MHz);
+            setDataRate(kbps110);
+            setSfd(standard);
+            setPreambleLength(pre1024);
+            setPreambleCode(3);
+            setSmartPower(false);
+//            setTxPower(18);
+            break;
+        case tunedDefault:    // User Manual "2.5.5 Default Configurations that should be modified" p. 22
+        default:
+            setChannel(5);
+            setPRF(prf16MHz);
+            setDataRate(kbps6800);
+            setSfd(standard);
+            setPreambleLength(pre128);
+            setPreambleCode(3);
+            setSmartPower(false);
+//            setTxPower(18);
+            break;
+        case fastLocationC5:
+            setChannel(5);
+            setPRF(prf64MHz);
+            setDataRate(kbps6800);
+            setSfd(standard);
+            setPreambleLength(pre64);
+            setPreambleCode(10);
+            setSmartPower(true);
+//            setTxPower(18);
+            break;
+        case fastLocationC4:
+            setChannel(4);
+            setPRF(prf64MHz);
+            setDataRate(kbps6800);
+            setSfd(standard);
+            setPreambleLength(pre64);
+            setPreambleCode(18);
+            setSmartPower(true);
+//            setTxPower(18);
+            break;
+        case rangeRateCompromise:
+            setChannel(4);
+            setPRF(prf64MHz);
+            setDataRate(kbps850);
+            setSfd(standard);  // for some reason decawave doesn't work.
+            setPreambleLength(pre256);
+            setPreambleCode(18);
+            setSmartPower(false);
+//            setTxPower(18);
+            break;
+    }
+}
+
+
+DW1000Setup::DW1000Setup(DW1000Setup *orij) {
+        channel = orij->getChannel();
+        prf = orij->getPRF();
+        dataRate = orij->getDataRate();
+        sfd = orij->getSfd();
+        preamble = orij->getPreambleLength();
+        preambleCode = orij->getPreambleCode();
+        GPIO_Pins = orij->getGPIO(); // 8 = irq, 7 = sync. Others are GPIO
+        enableSmartPower = orij->getSmartPower();
+        memcpy(&powers,orij->getTxPowers(),4*sizeof(float));
+    }
+
+
+    void DW1000Setup::applyConfig(DW1000Setup *orij) {
+        channel = orij->getChannel();
+        prf = orij->getPRF();
+        dataRate = orij->getDataRate();
+        sfd = orij->getSfd();
+        preamble = orij->getPreambleLength();
+        preambleCode = orij->getPreambleCode();
+        GPIO_Pins = orij->getGPIO(); // 8 = irq, 7 = sync. Others are GPIO
+        enableSmartPower = orij->getSmartPower();
+        memcpy(&powers,orij->getTxPowers(),4*sizeof(float));
+    }
+
+
+bool DW1000Setup::check()
+{
+    int maxCode = 24;
+    int minCode = 1;
+
+    if (prf == prf16MHz)
+        switch (channel) {
+            case 1:
+                maxCode = 2;
+                minCode = 1;
+                break;
+            case 2:
+            case 5:
+                maxCode = 4;
+                minCode = 3;
+                break;
+            case 3:
+                maxCode = 6;
+                minCode = 5;
+                break;
+            case 4:
+            case 7:
+                maxCode = 8;
+                minCode = 7;
+                break;
+            default:
+                return false; // invalid channel
+        }
+    else
+        switch (channel) {
+            case 1:
+            case 2:
+            case 3:
+            case 5:
+                maxCode = 12;
+                minCode = 9;
+                break;
+            case 4:
+            case 7:
+                maxCode = 20;
+                minCode = 17;
+                break;
+            default:
+                return false; // invalid channel
+        }
+
+    if ((preambleCode > maxCode) || (preambleCode < minCode))
+        return false;
+
+    switch (preamble) {
+        default:
+            return false;
+        case pre64:
+        case pre128:
+            if (dataRate != kbps6800)
+                return false;
+            break;
+        case pre256:
+            if (dataRate == kbps110)
+                return false;
+            break;
+        case pre512:
+        case pre1024:
+        case pre1536:
+            if (dataRate != kbps850)
+                return false;
+            break;
+        case pre2048:
+            if (dataRate == kbps6800)
+                return false;
+            break;
+        case pre4096:
+            if (dataRate != kbps110)
+                return false;
+            break;
+    }
+
+    if (enableSmartPower) {
+        if (dataRate != kbps6800)
+            return false;
+    }
+    return true;
+}
+
+void DW1000Setup::getSetupDescription(char *buffer, int len)
+{
+
+    char dataRateString[10];
+    if (dataRate == kbps6800)
+        strcpy(dataRateString,"6.8 Mbps");
+    else if (dataRate == kbps850)
+        strcpy(dataRateString,"850 kbps");
+    else
+        strcpy(dataRateString,"110 kbps");
+
+    char preambleString[8];
+    switch (preamble) {
+        default:
+            strcpy(preambleString,"error");
+            break;
+        case pre64:
+            strcpy(preambleString,"64");
+            break;
+        case pre128:
+            strcpy(preambleString,"128");
+            break;
+        case pre256:
+            strcpy(preambleString,"256");
+            break;
+        case pre512:
+            strcpy(preambleString,"512");
+            break;
+        case pre1024:
+            strcpy(preambleString,"1024");
+            break;
+        case pre1536:
+            strcpy(preambleString,"1536");
+            break;
+        case pre2048:
+            strcpy(preambleString,"2048");
+            break;
+        case 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",
+             channel,
+             (prf == prf16MHz)?"16 MHz":"64 MHz",
+             dataRateString,
+             preambleString,
+             preambleCode,
+             enableSmartPower?"Enabled":"Disabled",
+             (sfd == standard)?"Standard":"Non-standard");
+}
+
+    bool DW1000Setup::setSmartTxPower(float powerdBm,float power500us,float power250us,float power125us) {
+        if ((powerdBm < 0) || (powerdBm > 33.5))
+            return false;
+
+        powers[0] = powerdBm;
+
+        if ((power500us < powerdBm) || (power500us > 33.5))
+            powers[1] = powers[0];
+        else
+            powers[1] = power500us;
+
+        if ((power250us < power500us) || (power250us > 33.5))
+            powers[2] = powers[1];
+        else
+            powers[2] = power250us;
+
+        if ((power125us < power250us) || (power125us > 33.5))
+            powers[3] = powers[2];
+        else
+            powers[3] = power125us;
+
+        return true;
+    }
+
+    bool DW1000Setup::setTxPower(float powerdBm,float powerPRF) {
+        if ((powerdBm < 0) || (powerdBm > 33.5))
+            return false;
+
+        powers[0] = powerdBm;
+        powers[1] = powerdBm;
+        powers[2] = powerdBm;
+        powers[3] = powerdBm;
+
+        if ((powerPRF > 0) && (powerPRF < 33.5))
+            powers[1] = powerPRF;
+
+        return true;
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DW1000Setup.h	Mon Apr 18 16:58:27 2016 +0000
@@ -0,0 +1,278 @@
+#ifndef __DW1000SETUP_H__
+#define __DW1000SETUP_H__
+
+#include "mbed.h"
+/** Class for holding DW1000 config options
+*
+* Defaults are channel 5, 16MHz PRF, 850kb/s, standard SFD, 128 symbol preamble, preamble code 3.
+* All pins are GPIO other than sync and IRQ.
+* Smart power is off.
+*
+*/
+class DW1000Setup
+{
+public:
+
+    /** Supported UWB modes
+    *
+    *  enum for preset mode combinations
+    */
+    typedef enum {fastLocationC5, ///< maximum data speed, short range. Channel 5
+                  fastLocationC4, ///< maximum data speed, short range. Channel 5
+                  tunedDefault,   ///< The power up default config with the recomended changes
+                  user110k,       ///< 110kb/s settings used by Matthias Grob & Manuel Stalder
+                  rangeRateCompromise ///< 850kb/s settings aimed to give a short packet but with far greater range than the fastLocation options
+                 } UWBMode;
+
+    /** Constructor
+    * @param modeToUse The operating mode to set the initial settings to.
+    *
+    */
+    DW1000Setup(UWBMode modeToUse = tunedDefault);
+
+
+/// copy constructor
+    DW1000Setup(DW1000Setup *orij);
+
+/// Update this config to match the supplied one
+    void applyConfig(DW1000Setup *orij);
+
+
+/// enum for PRF options
+    enum prf_e {prf16MHz, ///< PRF rate of 16MHz. Lower power
+                prf64MHz ///< PRF rate of 64MHz. Higher power but more accurate timing.
+               };
+
+/// enum for data rate options
+    enum dataRate_e {kbps110, ///< Data rate of 110kb/s (non-standard)
+                     kbps850,///< Data rate of 850kb/s
+                     kbps6800///< Data rate of 6.8Mb/s
+                    };
+
+    /** enum for SFD options
+    *
+    * To conform to the standard the standard setting should be used.
+    * The decawave setting claimes to give better performance. Doesn't work for me at 850kb/s but does at 6.8Mb/s
+    */
+    enum sfd_e {standard, ///< IEEE standard SFD
+                decaWave, ///< Decawave defined SFD
+                user ///< user defined SFD
+               };
+
+/// enum for preamble length options
+    enum preamble_e { pre64,///< Preamble is 64 symbols
+                      pre128,///< Preamble is 128 symbols (non-standard)
+                      pre256,///< Preamble is 256 symbols (non-standard)
+                      pre512,///< Preamble is 512 symbols (non-standard)
+                      pre1024,///< Preamble is 1024 symbols
+                      pre1536,///< Preamble is 1536 symbols (non-standard)
+                      pre2048, ///< Preamble is 2048 symbols (non-standard)
+                      pre4096///< Preamble is 4096 symbols
+                    };
+
+    /** Set the Transmit power for smartpower operation
+    * @param powerdBm The gain setting in dBm (0-33.5)
+    * @param power500us The gain setting packets under 500us in dBm (0-33.5)
+    * @param power250us The gain setting packets under 250us in dBm (0-33.5)
+    * @param power125us The gain setting packets under 125us in dBm (0-33.5)
+    * @return true if a valid option
+    */
+    bool setSmartTxPower(float powerdBm,float power500us=0,float power250us=0,float power125us=0) ;
+
+    /** Set the Transmit power for non-smartpower operation
+    * @param powerdBm The gain setting in dBm for the main packet(0-33.5)
+    * @param powerPRF The gain setting in dBm for the preamble (0-33.5)
+    * @return true if a valid option
+    */
+    bool setTxPower(float powerdBm,float powerPRF=0);
+
+
+    /** 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
+    *
+    * channels are 1-5 & 7
+    */
+    bool setChannel(unsigned char newChannel) {
+        if ((newChannel > 0) && ((newChannel <= 5) || (newChannel == 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
+    *
+    * For 6.8Mb/s it should be 64 to 256 symbols.
+    * For 850kb/s it should be 256 to 2048 symbols
+    * For 110kb/s it should be >= 2048 symbols.
+    */
+    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
+    *
+    *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
+
+    */
+    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 transmit gains
+    * @return An array containing the power levels
+    *
+    * An array of 4 floats is returned.
+    * For smart power these are the 4 power levels (normal, <500us, <250us, <125us).
+    * For non-smart power the first and last values are ignored, the second is the power for the phy header, the 3rd is the power for the reaminder of the frame.
+    */
+    const float *getTxPowers() {
+        return powers;
+    }
+
+    /** Get the current channel
+    * @return the channel number
+    */
+    unsigned char getChannel() {
+        return channel;
+    };
+    /** Get the current PRF
+    * @return the PRF
+    */
+    enum prf_e getPRF() {
+        return prf;
+    };
+    /** Get the current data rate
+    * @return the data rate
+    */
+    enum dataRate_e getDataRate() {
+        return dataRate;
+    };
+
+    /** Get the current SFD mode
+    * @return the SFD
+    */
+    enum sfd_e getSfd() {
+        return sfd;
+    };
+    /** Get the current preamble length
+    * @return the  preamble length
+    */
+    enum preamble_e getPreambleLength() {
+        return preamble;
+    };
+    /** Get the current preamble code
+    * @return the preamble code
+    */
+    unsigned char getPreambleCode() {
+        return preambleCode;
+    };
+    /** Get the current smart power mode
+    * @return true if smartpower is on
+    */
+    bool getSmartPower() {
+        return  enableSmartPower;
+    };
+
+    /** Set which pins are GPIO
+    *
+    *  @param pins A bitmask of which pins are not to be used as GPIO
+    *
+    *  e.g. 0x01 sets GPIO0 as it's alternative function (RXOKLED) and all other pins to be GPIO.
+    *
+    *  The default is 0x0180 - GPIO 8 = irq, GPIO 7 = sync. All others are GPIO functionality
+    */
+    void setGPIO(uint16_t pins) {
+        GPIO_Pins = pins;
+    };
+
+    /** Get which pins are GPIO
+    *
+    *  @return A bitmask of which pins are not to be used as GPIO
+    *
+    *  e.g. 0x01 Indicates that GPIO0 as it's alternative function (RXOKLED) and all other pins to be GPIO.
+    *
+    *  The default is 0x0180 - GPIO 8 = irq, GPIO 7 = sync. All others are GPIO functionality
+    */
+    uint16_t getGPIO() {
+        return GPIO_Pins;
+    };
+
+    /** Check that the settings are self consistent
+    *
+    * @return true if the settings are valid
+    *
+    * Will check the following:
+    *  - Preamble size is sensible for the data rate
+    *  - Preamble code is valid for the channel
+    *  - That smart power is only enabled at 6.8Mb/s
+    */
+    bool check();
+
+    /** 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 getSetupDescription(char *buffer, int len);
+
+private:
+    float powers[4];
+    uint16_t GPIO_Pins;
+    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;
+};
+
+#endif