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

Dependencies:   BurstSPI

Revision:
9:326bf149c8bc
Parent:
8:0b408e77b701
Child:
10:f1e3c04080d6
--- a/DW1000.h	Mon Apr 18 16:58:27 2016 +0000
+++ b/DW1000.h	Wed Apr 20 11:03:41 2016 +0000
@@ -15,9 +15,12 @@
 #define c_mPerTick  (c_mmPerTick/1000)
 
 
-typedef enum {minPacketSize, tunedDefault, user110k} UWBMode;
 
 /** A DW1000 driver
+*
+* It is expected that the protocol implimentation above this will inherit this object.
+* If not using this structure then move the protected functions to being public.
+* 
 */
 class DW1000
 {
@@ -25,36 +28,10 @@
 
     /** Constructor.
     *
-    *  @param setup The radio mode to configure the unit to use.
-    *
-    *  Valid setup values are defaultConfig, tunedDefault, user110k
+    *  The radio will default to DW1000Setup::tunedDefault until you call applySetup() with a new configuration.
     */
-    DW1000(UWBMode setup, PinName MOSI, PinName MISO, PinName SCLK, PinName CS, PinName IRQ);              // constructor, uses SPI class
-
-    /**
-    * Sets the callbacks on packet Rx and Tx
-    * @param callbackRX The function to call on packet Rx complete
-    * @param callbackTX The function to call on packet Tx complete
-    *
-    * set either or both to null to disable the appropriate interupt
-    */
-    void setCallbacks(void (*callbackRX)(void), void (*callbackTX)(void));                  // setter for callback functions, automatically enables interrupt, if NULL is passed the coresponding interrupt gets disabled
+    DW1000(PinName MOSI, PinName MISO, PinName SCLK, PinName CS, PinName IRQ);              // constructor, uses SPI class
 
-    /**
-    * c++ version of setCallbacks()
-    * @param tptr object for callbacks
-    * @param mptrRX method to call on packet Rx complete
-    * @param mptrTX method to call on packet Tx complete
-    *
-    */
-    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
     /** Read the device ID
     * @return the device ID (0xDECA0130)
     */
@@ -97,6 +74,132 @@
     */
     uint64_t getStatus();                                                                   // get the 40 bit device status
 
+
+    /** Set receive antenna delay
+    * @param ticks Delay in system clock cycles
+    */
+    void setRxDelay(uint16_t ticks);
+    /** Set transmit antenna delay
+    * @param ticks Delay in system clock cycles
+    */
+    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);
+    };
+
+    /** Read a value from the OTP memory
+    * @param word_address The OTP memory address to read.
+    * @return The 32 bit value at that address.
+    *
+    * See Section 6.3.1 of the user manual for the memory map.
+    */
+    uint32_t readOTP (uint16_t word_address);
+
+    /** Write a value to the OTP memory
+    * @param word_address The OTP memory address to read.
+    * @param data The value to write
+    * @return True if the write was sucessful.
+    *
+    * Writes the supplied data to the OTP memory and then reads it back to verify it was sucessfully programmed.
+    * WARNING - this is a one time operation for each memory address.
+    * See Section 6.3.1 of the user manual for the memory map.
+    * It is recommened that the device is reset or power cycled after programing.
+    */
+    bool writeOTP(uint16_t word_address,uint32_t data);                                          // program a value in the OTP. It is recommended to reset afterwards.
+
+    /** get the current radio configuration
+    * @return A pointer to a DW1000Setup object of the current setup.
+    *
+    * Note to change the setup you must make a copy of the current setup and then pass that to applySetup().
+    */
+    DW1000Setup *getSetup();
+
+    /** Get the current Transmit gain settings.
+    *
+    * @param power Optional, is set to the first power in dBm
+    * @param boost500 Optional, is set to the second power in dBm
+    * @param boost250 Optional, is set to the third power in dBm
+    * @param boost125 Optional, is set to the forth power in dBm
+    * @return The raw transmit gain register value
+    *
+    * If smart power is on then power represents the normal transmit power,
+    * boost500-boost125 indicates the power used for packets of that number of us or less.
+    *
+    * If smart power is off then boost500 represents the gain for the PHY header, boost250 the gain for the main message.
+    * power and boost125 are not used.
+    */
+    uint32_t getTxPower(float *power = NULL, float *boost500 = NULL, float *boost250 = NULL, float *boost125 = NULL);
+
+    /** 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 dB. Gains can be between 0 and 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).
+    * If smart power is disabled then the normal gain is used for all settings.
+    * The values in the internal DW1000Setup are updated to reflect the configured powers.
+    */
+    void setTxPower(float normalPowerdB, float boost500 = 0, float boost250 = 0, float boost125 = 0);
+
+    /** Get the rx signal power for the last packet
+    *
+    * @param direct Is set to the direct path Rx power in dBm
+    * @param total Is set to the total Rx power in dBm
+    *
+    * According to the DW1000 manual if the direct path power is within 6dB of the total then it was probably a LoS measurment.
+    * If there is more than 10dB difference then it's probably an indirect path.
+    */
+    void getRxSignalPower(float *direct, float *total);
+
+    /** Get a metric of timestamp accuracy
+    *
+    * @param sigAmp Optional location to return the raw signal amplitude
+    * @param noiseAmp Optional location to return the raw channel noise level
+    * @return Timestamp quality metric
+    *
+    * The quality metric is a somewhat arbitary number based on channel noise and direct path strength
+    */
+    float getRxQuality(uint16_t *sigAmp = NULL, uint16_t *noiseAmp = NULL);
+
+protected:
+
+    /**
+    * Sets the callbacks on packet Rx and Tx
+    * @param callbackRX The function to call on packet Rx complete
+    * @param callbackTX The function to call on packet Tx complete
+    *
+    * set either or both to null to disable the appropriate interupt
+    */
+    void setCallbacks(void (*callbackRX)(void), void (*callbackTX)(void));                  // setter for callback functions, automatically enables interrupt, if NULL is passed the coresponding interrupt gets disabled
+
+    /**
+    * c++ version of setCallbacks()
+    * @param tptr object for callbacks
+    * @param mptrRX method to call on packet Rx complete
+    * @param mptrTX method to call on packet Tx complete
+    *
+    */
+    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);
+    }
+
     /** Get the last packet recieve time
     * @return the internal time stamp for the last packet Rx
     *
@@ -119,6 +222,8 @@
     *
     * The supplied packet is transmitted as soon as possible and the reciever re-enabled once transmission is complete.
     * Maximum packet size is 125 bytes.
+    *
+    * The receiver is re-activated as soon as packet transmission is complete.
     */
     void sendFrame(uint8_t* message, uint16_t length);                                      // send a raw frame (length in bytes)
 
@@ -132,6 +237,9 @@
     * Rx is disabled as soon as this command is issued and re-enabled once transmission is complete.
     * Note - 9 LSBs are ignored so timings are only accurate to ~8ns. For more accurate timing check the
     * tx timestamp after transmission is complete.
+    *
+    * The receiver is re-activated as soon as packet transmission is complete.
+    *
     */
     void sendDelayedFrame(uint8_t* message, uint16_t length, uint64_t TxTimestamp);
 
@@ -149,10 +257,23 @@
     * On the next rising edge of the sync line the transmitter will be activated.
     * The packet must have previously been set up using setupSyncedFrame()
     *
-    * Rx is disabled until transmission is complete.
+    * Rx is disabled until transmission is complete and then re-enabled.
     */
     void armSyncedFrame();
 
+    /** Get last packet size
+    * @return The length in bytes of the last packet received
+    */
+    uint16_t getFramelength();                                                              // to get the framelength of the received frame from the PHY header
+
+    /** Get last recieved packet
+    * @param buffer The location to put the received data
+    * @param length The number of bytes to read
+    */
+    void readRxBuffer( uint8_t *buffer, int length ) {
+        readRegister(DW1000_RX_BUFFER, 0, buffer, length);
+    }
+
     /** Enable reciever
     *
     * This is automatically done after each Tx completes but can also be forced manually
@@ -166,84 +287,6 @@
     */
     void stopTRX();                                                                         // disable tranceiver go back to idle mode
 
-    /** Set receive antenna delay
-    * @param ticks Delay in system clock cycles
-    */
-    void setRxDelay(uint16_t ticks);
-    /** Set transmit antenna delay
-    * @param ticks Delay in system clock cycles
-    */
-    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
-    */
-    uint16_t getFramelength();                                                              // to get the framelength of the received frame from the PHY header
-
-    /** Get last recieved packet
-    * @param buffer The location to put the received data
-    * @param length The number of bytes to read
-    */
-    void readRxBuffer( uint8_t *buffer, int length ) {
-        readRegister(DW1000_RX_BUFFER, 0, buffer, length);
-    }
-
-    /** Read a value from the OTP memory
-    * @param word_address The OTP memory address to read.
-    * @return The 32 bit value at that address.
-    *
-    * See Section 6.3.1 of the user manual for the memory map.
-    */
-    uint32_t readOTP (uint16_t word_address);
-
-    /** Write a value to the OTP memory
-    * @param word_address The OTP memory address to read.
-    * @param data The value to write
-    * @return True if the write was sucessful.
-    *
-    * Writes the supplied data to the OTP memory and then reads it back to verify it was sucessfully programmed.
-    * Note - this is a one time operation for each memory address.
-    * See Section 6.3.1 of the user manual for the memory map.
-    * It is recommened that the device is reset or power cycled after programing.
-    */
-    bool writeOTP(uint16_t word_address,uint32_t data);                                          // program a value in the OTP. It is recommended to reset afterwards.
-
-    /** get the current radio configuration
-    * @return A pointer to a DW1000Setup object of the current setup.
-    *
-    * 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.
-    *
-    * 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.
-    */
-//    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
     *
     * This should be done after any receive errors
@@ -259,19 +302,16 @@
     */
     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.
+   
+    /** apply a new radio setup to the UWB system
+    * @param setup The new settings to use
+    * @return true if the setup was applied.
     *
-    * 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).
+    * 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.
+    * Note - this will reset the radio. You must re-enable interupts, receiver etc. after calling it. 
     */
-//    void setTxPower(uint16_t normalPowercB, uint16_t boost500 = 0, uint16_t boost250 = 0, uint16_t boost125 = 0);
-
-    
+    bool applySetup(DW1000Setup *setup);
 
 private:
     void resetAll();                                                                        // soft reset the entire DW1000 (some registers stay as they were see User Manual)
@@ -279,6 +319,7 @@
     void setupRadio();
 
     // system register setup functions
+    void setupGPIO();
     void setupAGC();
     void setupRxConfig();
     void setupLDE();
@@ -288,15 +329,16 @@
     void setupFreqSynth();
     void setupTxCalibration();
     void setupSystemConfig();
+    void setupPower();
+
     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);
+    uint8_t powerToRegValue(float powerdB);
+    float regToPowerValue(uint8_t powerVal);
 
     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
@@ -309,7 +351,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);