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:
Wed Nov 08 10:43:03 2017 +0000
Parent:
14:02f0912e4ce4
Child:
17:1fb08dfef237
Commit message:
Added clock tuning controls

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	Thu Mar 30 11:32:35 2017 +0000
+++ b/DW1000.cpp	Wed Nov 08 10:43:03 2017 +0000
@@ -1,7 +1,7 @@
 #include "DW1000.h"
-
+#include "main.h"
 #define SPIRATE_PLL (10*1000*1000)
-#define SPIRATE_OSC (2*1000*1000)
+#define SPIRATE_OSC (1*1000*1000)
 
 DW1000::DW1000(PinName MOSI, PinName MISO, PinName SCLK, PinName CS, PinName IRQ) : irq(IRQ), spi(MOSI, MISO, SCLK), cs(CS)
 {
@@ -20,6 +20,32 @@
 }
 
 
+void DW1000::setSPISpeed(uint32_t speed) {
+    spi.frequency(speed);
+    }
+
+
+void DW1000::enterRFTestMode() {
+        writeRegister32(DW1000_RF_CONF,0,0x0009A000);
+        wait_ms(1);
+        writeRegister16(DW1000_PMSC,DWPMSC_PMSC_CTRL1,0x0000);
+        wait_ms(1);
+        writeRegister32(DW1000_TX_POWER,0,0x1f1f1f1f);
+        wait_ms(1);
+        uint32_t config = rangingSystem.readRegister32(DW1000_SYS_CFG,0);
+        config |= 1<<18;
+        writeRegister32(DW1000_SYS_CFG,0,config);
+        wait_ms(1);
+        writeRegister16(DW1000_PMSC,DWPMSC_PMSC_CTRL0,0x0222);
+        wait_ms(1);
+        writeRegister32(DW1000_PMSC,DWPMSC_PMSC_TXFSEQ,0x00000000);
+        wait_ms(1);
+        writeRegister32(DW1000_RF_CONF,0,0x005fff00);
+        wait_ms(1);
+        writeRegister8(DW1000_TX_CAL,DWTXCAL_TC_PGTEST,0x13);
+}
+
+
 DW1000Setup* DW1000::getSetup()
 {
     return &systemConfig;
@@ -334,6 +360,15 @@
     writeRegister32(DW1000_CHAN_CTRL, 0, registerValue);
 }
 
+uint8_t DW1000::readXTALTune() {
+  return readRegister8 (DW1000_FS_CTRL, DWFSCTRL_FS_XTALT);               
+    }
+
+void DW1000::setXTALTune(uint8_t value) {
+  value &= 0x1f; // mask reserved bits
+  value |= 0x60; // set reserved bits
+  writeRegister8 (DW1000_FS_CTRL, DWFSCTRL_FS_XTALT,value);                 
+    }
 
 uint8_t DW1000::powerToRegValue(float powerdB)
 {
@@ -387,7 +422,7 @@
 // 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(float normalPowerdB, float boost500, float boost250, float boost125)
 {
-   
+
     if(normalPowerdB > 33.5)
         normalPowerdB = 33.5;
 
@@ -417,7 +452,7 @@
     powerReg |= powerToRegValue(boost250) << 16;
     powerReg |= powerToRegValue(boost125) << 24;
     writeRegister32(DW1000_TX_POWER,0,powerReg);
-    
+
     systemConfig.setSmartTxPower(normalPowerdB,boost500,boost250,boost125); // update the systemConfig
 }
 
@@ -589,7 +624,7 @@
 }
 
 void DW1000::getFullQualityMetrics(uint16_t *std_noise, uint16_t *fp_amp1, uint16_t *fp_amp2, uint16_t *fp_amp3,
-                                        uint16_t *cir_pwr, uint16_t *preAmbleAcc, uint16_t *preAmbleAcc_NoSat)
+                                   uint16_t *cir_pwr, uint16_t *preAmbleAcc, uint16_t *preAmbleAcc_NoSat)
 {
     *fp_amp1 = readRegister16(DW1000_RX_TIME,7);
     *std_noise = readRegister16(DW1000_RX_FQUAL,0);
@@ -600,11 +635,12 @@
     *preAmbleAcc_NoSat = readRegister16(DW1000_DRX_CONF,DWDRX_RXPAC_NOSAT);
 }
 
-void DW1000::getFullLEDMetrics(uint16_t *led_thresh, uint16_t *led_ppindx, uint16_t *led_ppampl) {
+void DW1000::getFullLEDMetrics(uint16_t *led_thresh, uint16_t *led_ppindx, uint16_t *led_ppampl)
+{
     *led_thresh = readRegister16(DW1000_LDE_CTRL,DWLDE_LDE_THRESH);
     *led_ppindx = readRegister16(DW1000_LDE_CTRL,DWLDE_LDE_PPINDX);
-    *led_ppampl = readRegister16(DW1000_LDE_CTRL,DWLDE_LDE_PPAMPL);   
-    }
+    *led_ppampl = readRegister16(DW1000_LDE_CTRL,DWLDE_LDE_PPAMPL);
+}
 
 
 #define SQR(x) ((float)(x) * (float)(x))
@@ -922,10 +958,12 @@
 void DW1000::setInterrupt(bool RX, bool TX)
 {
     writeRegister16(DW1000_SYS_MASK, 0, RX*0x4000 | TX*0x0080);  // RX good frame 0x4000, TX done 0x0080
+//    writeRegister32(DW1000_SYS_MASK, 0, 0x377fff0);  // RX good frame 0x4000, TX done 0x0080
 }
 
 void DW1000::ISR()
 {
+//    led1 = !led1;
     uint64_t status = getStatus();
     if (status & 0x4000) {                                          // a frame was received
         callbackRX.call();
@@ -1044,3 +1082,22 @@
     cs = 1;                 // set Cable Select pin high to stop transmission
     irq.enable_irq();       // reenable the interrupt handler
 }
+
+void DW1000::getRxClockInfo(int32_t *offset, uint8_t* phase, uint8_t* delta)
+{
+    uint64_t data = readRegister40(DW1000_RX_TTCKO,0);
+    *phase = (data >> 32)&0x07f;
+    *delta = data >> 24 & 0x0ff;
+    int32_t RXTofs = data &0x07ffff;
+    if (RXTofs & 0x040000)
+      RXTofs |= 0xfff80000;
+    *offset =  RXTofs;
+
+//    uint32_t RXTTCKI =  0x01FC0000;
+//    if (getSetup()->getPRF() == DW1000Setup::prf16MHz)
+//        RXTTCKI =  0x01F00000;
+
+//    double clockOffset = (1000000.0 * RXTofs) / RXTTCKI;
+//    printf("Clock offset %.4f ppm, re-sample delay %d, phase adjustment %d\n",clockOffset,RSMPDel,RCPhase);
+
+}
--- a/DW1000.h	Thu Mar 30 11:32:35 2017 +0000
+++ b/DW1000.h	Wed Nov 08 10:43:03 2017 +0000
@@ -32,6 +32,8 @@
     */
     DW1000(PinName MOSI, PinName MISO, PinName SCLK, PinName CS, PinName IRQ);              // constructor, uses SPI class
 
+    void setSPISpeed(uint32_t speed);
+
     /** Read the device ID
     * @return the device ID (0xDECA0130)
     */
@@ -172,6 +174,40 @@
 
     void getFullLEDMetrics(uint16_t *led_thresh, uint16_t *led_ppindx, uint16_t *led_ppampl);
 
+    void getRxClockInfo(int32_t *offset, uint8_t* phase, uint8_t* delta);
+
+    /** Read the current crystal tuning value
+    *
+    * Reads the current FX_XTALT value from 0 to 0x1f.
+    * See section 8.1 of the manual for details.
+    *
+    * @return The current value.
+    */
+    uint8_t readXTALTune();
+
+
+    /** Set the crystal tuning value
+    *
+    * Sets the value of the FX_XTALT register.
+    * See section 8.1 of the manual for details.
+    *
+    * Values will be lost on reset, consider programming the final value 
+    * into the OTP memory to store perminently.
+    *
+    * @value The value to use from 0 to 0x1f
+    */
+    void setXTALTune(uint8_t value);
+
+    /** Puts the device into CW test mode
+    *
+    * The radio will be set to output a constant wave at carrier frequency.
+    * Transmit gain will be set to the maximum of 33.5dB but can be chaged by
+    * setting the TX power register
+    * To exit test mode the radio should be reset.
+    */
+    void enterRFTestMode();
+
+        
 protected:
 
     /**
@@ -334,7 +370,12 @@
             return readRegister16(DW1000_LDE_CTRL,DWLDE_LDE_PPAMPL);
         }
 
+
+        
+    #define DW1000_RX_TTCKO             0x14 //     5 Receiver Time Tracking Offset       (in double buffer set)
+
 private:
+
     void resetAll();                                                                        // soft reset the entire DW1000 (some registers stay as they were see User Manual)
 
     void setupRadio();