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 14:31:28 2016 +0000
Parent:
1:dcbd071f38d5
Child:
4:5f1025df5530
Commit message:
Simplified system config.

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
--- a/DW1000.cpp	Tue Apr 05 11:37:23 2016 +0000
+++ b/DW1000.cpp	Thu Apr 07 14:31:28 2016 +0000
@@ -15,71 +15,59 @@
 
     switch (setup) {
         case user110k:  // values from Matthias Grob & Manuel Stalder - ETH Zürich - library
-            //Those values are for the 110kbps mode (5, 16MHz, 1024 Symbols) and are quite complete
-            writeRegister16(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE1, 0x8870);             //AGC_TUNE1 for 16MHz PRF
-            writeRegister32(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE2, 0x2502A907);         //AGC_TUNE2 (Universal)
-            writeRegister16(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE3, 0x0055);             //AGC_TUNE3 (Universal)
-
-            writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x000A);             //DRX_TUNE0b for 110kbps
-            writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1A, 0x0087);             //DRX_TUNE1a for 16MHz PRF
-            writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1B, 0x0064);             //DRX_TUNE1b for 110kbps & > 1024 symbols
-            writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x351A009A);         //PAC size for 1024 symbols preamble & 16MHz PRF
-            //writeRegister32(DW1000_DRX_CONF, 0x08, 0x371A011D);               //PAC size for 2048 symbols preamble
-
-            writeRegister8 (DW1000_LDE_CTRL, DWLDE_LDE_CFG1, 0xD);              //LDE_CFG1
-            writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_CFG2, 0x1607);           //LDE_CFG2 for 16MHz PRF
-
-            writeRegister32(DW1000_TX_POWER, 0, 0x28282828);            //Power for channel 5
 
-            writeRegister8(DW1000_RF_CONF, DWRFCONF_RF_RXCTRLH, 0xD8);                 //RF_RXCTRLH for channel 5
-            writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x001E3FE0);          //RF_TXCTRL for channel 5
-
-            writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0xC0);                 //TC_PGDELAY for channel 5
-
-            writeRegister32 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLCFG, 0x0800041D);         //FS_PLLCFG for channel 5
-            writeRegister8 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLTUNE, 0xBE); // changed from 0xA6                 //FS_PLLTUNE for channel 5
+            systemConfig.channel = 5;
+            systemConfig.prf = prf16MHz;
+            systemConfig.dataRate = kbps110;
+            systemConfig.sfd = standard;
+            systemConfig.preamble = pre1024;
+            systemConfig.preambleCode = 3;
+            systemConfig.enableSmartPower = true;
 
-            loadLDE();                          // important everytime DW1000 initialises/awakes otherwise the LDE algorithm must be turned off or there's receiving malfunction see User Manual LDELOAD on p22 & p158
+            setupRadio();
 
-            // 110kbps CAUTION: a lot of other registers have to be set for an optimized operation on 110kbps
-            writeRegister16(DW1000_TX_FCTRL, 1, 0x0800 | 0x0100 | 0x0080); // use 1024 symbols preamble (0x0800) (previously 2048 - 0x2800), 16MHz pulse repetition frequency (0x0100), 110kbps bit rate (0x0080) see p.69 of DW1000 User Manual
-            writeRegister8(DW1000_SYS_CFG, 2, 0x44);    // enable special receiving option for 110kbps (disable smartTxPower)!! (0x44) see p.64 of DW1000 User Manual [DO NOT enable 1024 byte frames (0x03) becuase it generates disturbance of ranging don't know why...]
+            setTxPower(230); // power = 23dB gain
 
-            writeRegister16(DW1000_TX_ANTD, 0, 16384); // set TX and RX Antenna delay to neutral because we calibrate afterwards
-            writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_RXANTD, 16384); // = 2^14 a quarter of the range of the 16-Bit register which corresponds to zero calibration in a round trip (TX1+RX2+TX2+RX1)
+            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
-            //Those values are for the standard mode (6.8Mbps, 5, 16Mhz, 32 Symbols) and are (may be?) INCOMPLETE!
-            writeRegister16(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE1, 0x8870);
-            writeRegister32(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE2, 0x2502A907);
-            writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x311A002D);
-            writeRegister8(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0001);
-            writeRegister8(DW1000_DRX_CONF, DWDRX_DRX_TUNE1A, 0x0087);
-            writeRegister8(DW1000_DRX_CONF, DWDRX_DRX_TUNE1B, 0x0020);
-            writeRegister8 (DW1000_LDE_CTRL, DWLDE_LDE_CFG1, 0xD);
-            writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_CFG2, 0x1607);
-            writeRegister32(DW1000_TX_POWER, 0, 0x0E082848);
-//            writeRegister32(DW1000_TX_POWER, 0, 0x75757575);
-            writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x001E3FE0);
-            writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0xC0);
-            writeRegister8 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLTUNE, 0xBE);
+        default:
+
+            systemConfig.channel = 5;
+            systemConfig.prf = prf16MHz;
+            systemConfig.dataRate = kbps6800;
+            systemConfig.sfd = standard;
+            systemConfig.preamble = pre128;
+            systemConfig.preambleCode = 3;
+            systemConfig.enableSmartPower = false;;
+
+            setupRadio();
 
-            loadLDE();                          // important everytime DW1000 initialises/awakes otherwise the LDE algorithm must be turned off or there's receiving malfunction see User Manual LDELOAD on p22 & p158
+            setTxPower(230,260,290); // power = 23dB gain
+            setRxDelay(0);
+            setTxDelay(0);
 
-            writeRegister32(DW1000_GPIO_CTRL,DWGPIO_GPIO_MODE,0x00001400);
-            writeRegister16(DW1000_PMSC,DWPMSC_PMSC_LEDC,0x0120);
+            break;
+        case minPacketSize:
+            systemConfig.channel = 5;
+            systemConfig.prf = prf16MHz;
+            systemConfig.dataRate = kbps6800;
+            systemConfig.sfd = standard;
+            systemConfig.preamble = pre64;
+            systemConfig.preambleCode = 3;
+            systemConfig.enableSmartPower = true;;
 
-//            writeRegister8(DW1000_SYS_CFG, 3, 0x20);    // enable auto RX reenable
+            setupRadio();
+            uint16_t txPower = 25*10; // 25dB gain.
+            // 3 packets per ms max. So can increase TX power of 250us packets by 10log(4/3) dB and 125us packets by 10log(8/3) dB
+            setTxPower(txPower,txPower,txPower+15,txPower+45); // power = 23dB gain
 
             setRxDelay(0);
             setTxDelay(0);
 
             break;
-        case defaultConfig:
-        default:
-            loadLDE();                          // important everytime DW1000 initialises/awakes otherwise the LDE algorithm must be turned off or there's receiving malfunction see User Manual LDELOAD on p22 & p158
-            break;
     }
 
     writeRegister8(DW1000_SYS_CFG, 3, 0x20);    // enable auto reenabling receiver after error
@@ -87,6 +75,455 @@
     irq.rise(this, &DW1000::ISR);       // attach interrupt handler to rising edge of interrupt pin from DW1000
 }
 
+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.prf == 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.enableSmartPower)
+        valueToUse |= 1<<18; // disable smart power
+
+    if (systemConfig.dataRate == kbps110)
+        valueToUse |= 1<<22;
+
+    writeRegister8(DW1000_SYS_CFG, 0, valueToUse);
+}
+
+void DW1000::setupRxConfig()
+{
+
+    switch (systemConfig.dataRate) {
+        case kbps110:
+            if (systemConfig.sfd == standard)
+                writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x000A);
+            else
+                writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0016);
+            break;
+        case kbps850:
+            if (systemConfig.sfd == standard)
+                writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0001);
+            else
+                writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0006);
+            break;
+        case kbps6800:
+        default:
+            if (systemConfig.sfd == standard)
+                writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0001);
+            else
+                writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0002);
+            break;
+    }
+
+    if (systemConfig.prf == 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.preamble) {
+        case pre1536:
+        case pre2048:
+        case 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 pre64:
+            writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1B, 0x0010);             //DRX_TUNE1b for 64 symbols
+            break;
+    }
+
+    switch (systemConfig.preamble) {
+        case pre64:
+        case pre128:  // PAC = 8
+            if (systemConfig.prf == 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 pre256:
+        case pre512:
+            if (systemConfig.prf == 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 pre1024:
+            if (systemConfig.prf == 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 pre1536:
+        case pre2048:
+        case pre4096:
+            if (systemConfig.prf == 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.preamble == 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.prf == 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.preambleCode) {
+        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.dataRate == kbps110)
+        replicaCoeff = replicaCoeff>>3;
+
+    writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_REPC, replicaCoeff);
+
+    loadLDE();
+}
+
+void DW1000::setupChannel()
+{
+    uint16_t registerValue = 0;
+
+    registerValue = systemConfig.channel; // set Tx channel
+    registerValue |= systemConfig.channel<<4; // set Rx channel
+
+    if (    systemConfig.prf == prf16MHz) // set PRF (2 bit value 01 or 10)
+        registerValue |= 0x01 << 18;
+    else
+        registerValue |= 0x02 << 18;
+
+    if (systemConfig.sfd == nonStandard)  {
+        registerValue |= 0x01 << 17; // enable DW own SFD
+//    registerValue |= 0x01 << 20; // enable user set SFD Tx
+//    registerValue |= 0x01 << 21; // enable user set SFD Rx
+    }
+
+    registerValue |= systemConfig.preambleCode << 22; // set Tx preamble code
+    registerValue |= systemConfig.preambleCode << 27; // set Rx preamble code
+
+    writeRegister16(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;
+
+    uint32_t powerReg = powerToRegValue(normalPowercB);
+    powerReg |= powerToRegValue(boost500) << 8;
+    powerReg |= powerToRegValue(boost250) << 16;
+    powerReg |= powerToRegValue(boost125) << 24;
+}
+
+void DW1000::setupAnalogRF()
+{
+    switch (systemConfig.channel) {
+        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.channel) {
+        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.channel) {
+        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.channel) {
+        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()
+{
+    uint16_t frameCtrlValue = 0;
+    switch (systemConfig.dataRate) {
+        case kbps110:
+            break;
+        case kbps850:
+            frameCtrlValue |= 0x01<<13;
+            break;
+        case kbps6800:
+        default:
+            frameCtrlValue |= 0x02<<13;
+            break;
+    }
+    frameCtrlValue |= 0x01<<15;
+
+    if (systemConfig.prf == prf16MHz)
+        frameCtrlValue |= 0x01<<16;
+    else
+        frameCtrlValue |= 0x02<<16;
+
+    switch    (systemConfig.preamble)            {
+        case pre64:
+            frameCtrlValue |= 0x01<<18; // TXPSR
+            frameCtrlValue |= 0x00<<20; // PE
+            break;
+        case pre128:
+        default:
+            frameCtrlValue |= 0x01<<18; // TXPSR
+            frameCtrlValue |= 0x01<<20; // PE
+            break;
+        case pre256:
+            frameCtrlValue |= 0x01<<18; // TXPSR
+            frameCtrlValue |= 0x02<<20; // PE
+            break;
+        case pre512:
+            frameCtrlValue |= 0x01<<18; // TXPSR
+            frameCtrlValue |= 0x03<<20; // PE
+            break;
+        case pre1024:
+            frameCtrlValue |= 0x02<<18; // TXPSR
+            frameCtrlValue |= 0x00<<20; // PE
+            break;
+        case pre1536:
+            frameCtrlValue |= 0x02<<18; // TXPSR
+            frameCtrlValue |= 0x01<<20; // PE
+            break;
+        case pre2048:
+            frameCtrlValue |= 0x02<<18; // TXPSR
+            frameCtrlValue |= 0x02<<20; // PE
+            break;
+        case pre4096:
+            frameCtrlValue |= 0x03<<18; // TXPSR
+            frameCtrlValue |= 0x00<<20; // PE
+            break;
+    }
+}
+
 void DW1000::setRxDelay(uint16_t ticks)
 {
     writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_RXANTD, ticks);
@@ -192,12 +629,12 @@
     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);
-*/
+    /* 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);
 
@@ -206,7 +643,8 @@
 //    startRX();                                                      // enable receiver again
 }
 
-void DW1000::setupSyncedFrame(uint8_t* message, uint16_t length) {
+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
@@ -217,10 +655,11 @@
     writeRegister16(DW1000_TX_FCTRL, 0, length);
 }
 
-void DW1000::armSyncedFrame() {
+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)
 {
--- a/DW1000.h	Tue Apr 05 11:37:23 2016 +0000
+++ b/DW1000.h	Thu Apr 07 14:31:28 2016 +0000
@@ -152,7 +152,22 @@
 #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
 
-typedef enum {defaultConfig, tunedDefault, user110k} UWBMode;
+/*
+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
+*/
+
+
+typedef enum {minPacketSize, tunedDefault, user110k} UWBMode;
 
 class DW1000
 {
@@ -204,11 +219,54 @@
     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);
+
+    enum prf_e {prf16MHz,prf64MHz};
+    enum dataRate_e {kbps110,kbps850,kbps6800};
+    enum sfd_e {standard, nonStandard};
+    enum preamble_e { pre64, pre128, pre256, pre512, pre1024, pre1536, pre2048, pre4096};
+
+    struct {
+        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;
+    } systemConfig;
+
 
 
     // Interrupt