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

Dependencies:   BurstSPI

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DW1000.h Source File

DW1000.h

00001 // by Matthias Grob & Manuel Stalder - ETH Zürich - 2015
00002 
00003 #ifndef DW1000_H
00004 #define DW1000_H
00005 
00006 #include "mbed.h"
00007 #include "BurstSPI.h"
00008 #include "DW1000Registers.h"
00009 #include "DW1000Setup.h"
00010 
00011 #define TIMEUNITS_TO_US       (1/(128*499.2))               // conversion between the decawave timeunits (ca 15.65ps) to microseconds.
00012 #define US_TO_TIMEUNITS       ((uint32_t)(128*499.2))                   // conversion between microseconds to the decawave timeunits (ca 15.65ps).
00013 #define c_mPerS     299792458
00014 #define c_mmPerTick (c_mPerS * TIMEUNITS_TO_US / 1000)
00015 #define c_mPerTick  (c_mmPerTick/1000)
00016 
00017 
00018 
00019 /** A DW1000 driver
00020 *
00021 * It is expected that the protocol implimentation above this will inherit this object.
00022 * If not using this structure then move the protected functions to being public.
00023 * 
00024 */
00025 class DW1000
00026 {
00027 public:
00028 
00029     /** Constructor.
00030     *
00031     *  The radio will default to DW1000Setup::tunedDefault until you call applySetup() with a new configuration.
00032     */
00033     DW1000(PinName MOSI, PinName MISO, PinName SCLK, PinName CS, PinName IRQ);              // constructor, uses SPI class
00034 
00035     void setSPISpeed(uint32_t speed);
00036 
00037     /** Read the device ID
00038     * @return the device ID (0xDECA0130)
00039     */
00040     uint32_t getDeviceID();                                                                 // gets the Device ID which should be 0xDECA0130 (good for testing SPI!)
00041 
00042     /** Read the Extended Unique ID
00043     * @return The device EUI as stored in the system registers
00044     */
00045     uint64_t getEUI();
00046 
00047     /** Set the Extended Unique ID
00048     * @param EUI The EUID to use
00049     *
00050     * @note ID is only valid until the next power cycle and overrides the value in the OTP memory.
00051     * To set a value that is automatically loaded on startup set OTP memory addresses 0 and 1.
00052     */
00053     void setEUI(uint64_t EUI);                                                              // sets 64 bit Extended Unique Identifier according to IEEE standard
00054 
00055     /** Read voltage input
00056 
00057     @return the current device voltage
00058 
00059         For accurate ranging the voltage of the device should be taken into account.
00060         User manual give variation as ~5.35cm / V
00061     */
00062     float getVoltage();                                                                     // gets the current chip voltage measurement form the A/D converter
00063 
00064     /** Read on board temperature sensor
00065     @return The temperature in C
00066 
00067     For accurate ranging the temperature of the device should be taken into account.
00068     User manual give variation as ~2.15mm / C
00069     */
00070     float getTemperature();                                                                 // gets the current chip temperature measurement form the A/D converter
00071 
00072     /** Get the status register
00073     * @return The system status register
00074     *
00075     * See user manual section 7.2.17 for details
00076     */
00077     uint64_t getStatus();                                                                   // get the 40 bit device status
00078 
00079 
00080     /** Set receive antenna delay
00081     * @param ticks Delay in system clock cycles
00082     */
00083     void setRxDelay(uint16_t ticks);
00084     /** Set transmit antenna delay
00085     * @param ticks Delay in system clock cycles
00086     */
00087     void setTxDelay(uint16_t ticks);
00088 
00089     /** Set receive antenna delay in meters
00090     * @param errorDistance Delay in meters at speed of light
00091     */
00092     void setRxDelayDistance(double errorDistance) {
00093         setRxDelay(errorDistance/c_mPerTick);
00094     };
00095 
00096     /** Set transmit antenna delay  in meters
00097     * @param errorDistance Delay in meters at speed of light
00098     */
00099     void setTxDelayDistance(double errorDistance) {
00100         setTxDelay(errorDistance/c_mPerTick);
00101     };
00102 
00103     /** Read a value from the OTP memory
00104     * @param word_address The OTP memory address to read.
00105     * @return The 32 bit value at that address.
00106     *
00107     * See Section 6.3.1 of the user manual for the memory map.
00108     */
00109     uint32_t readOTP (uint16_t word_address);
00110 
00111     /** Write a value to the OTP memory
00112     * @param word_address The OTP memory address to read.
00113     * @param data The value to write
00114     * @return True if the write was sucessful.
00115     *
00116     * Writes the supplied data to the OTP memory and then reads it back to verify it was sucessfully programmed.
00117     * @warning This is a one time operation for each memory address.
00118     * See Section 6.3.1 of the user manual for the memory map.
00119     *
00120     * @note It is recommened that the device is reset or power cycled after programing.
00121     */
00122     bool writeOTP(uint16_t word_address,uint32_t data);                                          // program a value in the OTP. It is recommended to reset afterwards.
00123 
00124     /** get the current radio configuration
00125     * @return A pointer to a DW1000Setup object of the current setup.
00126     *
00127     * Note to change the setup you must make a copy of the current setup and then pass that to applySetup().
00128     */
00129     DW1000Setup *getSetup();
00130 
00131     /** Get the current Transmit gain settings.
00132     *
00133     * @param power Optional, is set to the first power in dBm
00134     * @param boost500 Optional, is set to the second power in dBm
00135     * @param boost250 Optional, is set to the third power in dBm
00136     * @param boost125 Optional, is set to the forth power in dBm
00137     * @return The raw transmit gain register value
00138     *
00139     * If smart power is on then power represents the normal transmit power,
00140     * boost500-boost125 indicates the power used for packets of that number of us or less.
00141     *
00142     * If smart power is off then boost500 represents the gain for the PHY header, boost250 the gain for the main message.
00143     * power and boost125 are not used.
00144     */
00145     uint32_t getTxPower(float *power = NULL, float *boost500 = NULL, float *boost250 = NULL, float *boost125 = NULL);
00146 
00147     /** Set Transmit gain
00148     *
00149     * @param normalPowercB Normal transmit gain to use.
00150     * @param boost500 Gain to use for 6.8Mb/s packets of under 500ms.
00151     * @param boost250 Gain to use for 6.8Mb/s packets of under 250ms.
00152     * @param boost125 Gain to use for 6.8Mb/s packets of under 125ms.
00153     *
00154     * All gains are in dB. Gains can be between 0 and 33.5dB.
00155     * 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).
00156     * If smart power is disabled then the normal gain is used for all settings.
00157     * The values in the internal DW1000Setup are updated to reflect the configured powers.
00158     */
00159     void setTxPower(float normalPowerdB, float boost500 = 0, float boost250 = 0, float boost125 = 0);
00160 
00161     /** Get the rx signal power for the last packet
00162     *
00163     * @param direct Is set to the direct path Rx power in dBm
00164     * @param total Is set to the total Rx power in dBm
00165     *
00166     * According to the DW1000 manual if the direct path power is within 6dB of the total then it was probably a LoS measurment.
00167     * If there is more than 10dB difference then it's probably an indirect path.
00168     */
00169     void getRxSignalPower(float *direct, float *total);
00170 
00171 
00172     void getFullQualityMetrics(uint16_t *std_noise, uint16_t *fp_amp1, uint16_t *fp_amp2, uint16_t *fp_amp3,
00173                                uint16_t *cir_pwr, uint16_t *preAmbleAcc, uint16_t *preAmbleAcc_NoSat);
00174 
00175     void getFullLEDMetrics(uint16_t *led_thresh, uint16_t *led_ppindx, uint16_t *led_ppampl);
00176 
00177     void getRxClockInfo(int32_t *offset, uint8_t* phase, uint8_t* delta);
00178 
00179     /** Read the current crystal tuning value
00180     *
00181     * Reads the current FX_XTALT value from 0 to 0x1f.
00182     * See section 8.1 of the manual for details.
00183     *
00184     * @return The current value.
00185     */
00186     uint8_t readXTALTune();
00187 
00188 
00189     /** Set the crystal tuning value
00190     *
00191     * Sets the value of the FX_XTALT register.
00192     * See section 8.1 of the manual for details.
00193     *
00194     * Values will be lost on reset, consider programming the final value 
00195     * into the OTP memory to store perminently.
00196     *
00197     * @value The value to use from 0 to 0x1f
00198     */
00199     void setXTALTune(uint8_t value);
00200 
00201     /** Puts the device into CW test mode
00202     *
00203     * The radio will be set to output a constant wave at carrier frequency.
00204     * Transmit gain will be set to the maximum of 33.5dB but can be chaged by
00205     * setting the TX power register
00206     * To exit test mode the radio should be reset.
00207     */
00208     void enterRFTestMode();
00209 
00210     /** apply a new radio setup to the UWB system
00211     * @param setup The new settings to use
00212     * @return true if the setup was applied.
00213     *
00214     * The setup object supplied is copied and can be disposed of after the call.
00215     * If the supplied setup fails DW1000Setup::check() then it is ignored and the function returns false.
00216     * @note This will reset the radio. You must re-enable interupts, receiver etc. after calling it. 
00217     */
00218     bool applySetup(DW1000Setup *setup);
00219         
00220 protected:
00221 
00222     /**
00223     * Sets the callbacks on packet Rx and Tx
00224     * @param callbackRX The function to call on packet Rx complete
00225     * @param callbackTX The function to call on packet Tx complete
00226     *
00227     * set either or both to null to disable the appropriate interupt
00228     */
00229     void setCallbacks(void (*callbackRX)(void), void (*callbackTX)(void));                  // setter for callback functions, automatically enables interrupt, if NULL is passed the coresponding interrupt gets disabled
00230 
00231     /**
00232     * c++ version of setCallbacks()
00233     * @param tptr object for callbacks
00234     * @param mptrRX method to call on packet Rx complete
00235     * @param mptrTX method to call on packet Tx complete
00236     *
00237     */
00238     template<typename T>
00239     void setCallbacks(T* tptr, void (T::*mptrRX)(void), void (T::*mptrTX)(void)) {      // overloaded setter to treat member function pointers of objects
00240         callbackRX.attach(tptr, mptrRX);                                                    // possible client code: dw.setCallbacks(this, &A::callbackRX, &A::callbackTX);
00241         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
00242         setInterrupt(true,true);
00243     }
00244 
00245     /** Get the last packet recieve time
00246     * @return the internal time stamp for the last packet Rx
00247     *
00248     * Time is counted on a clock running at 499.2MHz * 128 (~15.65ps)
00249     * This value is raw time minus user set Rx antenna delay.
00250     */
00251     uint64_t getRXTimestamp();
00252 
00253     /** Get the last packet transmit time
00254     * @return the internal time stamp for the last packet Tx
00255     *
00256     * Time is counted on a clock running at 499.2MHz * 128 (~15.65ps)
00257     * This value is raw time plus user set Tx antenna delay to give time at the antenna.
00258     */
00259     uint64_t getTXTimestamp();
00260 
00261     /** Send a packet
00262     * @param message A buffer containing the data to send
00263     * @param length The length of the data in bytes.
00264     *
00265     * The supplied packet is transmitted as soon as possible and the reciever re-enabled once transmission is complete.
00266     * Maximum packet size is 125 bytes.
00267     *
00268     * The receiver is re-activated as soon as packet transmission is complete.
00269     */
00270     void sendFrame(uint8_t* message, uint16_t length);                                      // send a raw frame (length in bytes)
00271 
00272     /** Send a packet at a certain time
00273     * @param message A buffer containing the data to send
00274     * @param length The length of the data in bytes.
00275     * @param TxTimestamp The timestamp to send the packet.
00276     *
00277     * The supplied packet is transmitted once the internal clock reaches the specified timestamp.
00278     * Maximum packet size is 125 bytes.
00279     * Rx is disabled as soon as this command is issued and re-enabled once transmission is complete.
00280     * Note - 9 LSBs are ignored so timings are only accurate to ~8ns. For more accurate timing check the
00281     * tx timestamp after transmission is complete.
00282     *
00283     * The receiver is re-activated as soon as packet transmission is complete.
00284     *
00285     */
00286     void sendDelayedFrame(uint8_t* message, uint16_t length, uint64_t TxTimestamp);
00287 
00288     /** Set up data for a transmit on sync
00289     * @param message A buffer containing the data to send
00290     * @param length The length of the data in bytes.
00291     *
00292     * Data is loaded into the transmit buffer but the transmission is not started.
00293     * Maximum packet size is 125 bytes.
00294     */
00295     void setupSyncedFrame(uint8_t* message, uint16_t length);
00296 
00297     /** Transmit on the next sync pulse
00298     *
00299     * On the next rising edge of the sync line the transmitter will be activated.
00300     * The packet must have previously been set up using setupSyncedFrame()
00301     *
00302     * Rx is disabled until transmission is complete and then re-enabled.
00303     */
00304     void armSyncedFrame();
00305 
00306     /** Get last packet size
00307     * @return The length in bytes of the last packet received
00308     */
00309     uint16_t getFramelength();                                                              // to get the framelength of the received frame from the PHY header
00310 
00311     /** Get last recieved packet
00312     * @param buffer The location to put the received data
00313     * @param length The number of bytes to read
00314     */
00315     void readRxBuffer( uint8_t *buffer, int length ) {
00316         readRegister(DW1000_RX_BUFFER, 0, buffer, length);
00317     }
00318 
00319     /** Enable reciever
00320     *
00321     * This is automatically done after each Tx completes but can also be forced manually
00322     */
00323     void startRX();                                                                         // start listening for frames
00324 
00325     /** Disable radio link
00326     *
00327     * Disables both the recieve and transmit systems.
00328     * Any transmissions waiting for a delayed time or sync pulse will be canceled.
00329     */
00330     void stopTRX();                                                                         // disable tranceiver go back to idle mode
00331 
00332     /** Reset the reciever logic
00333     *
00334     * This should be done after any receive errors
00335     */
00336     void resetRX();                                                                         // soft reset only the tranciever part of DW1000
00337 
00338     /** Enable/Disable interrupts
00339     * @param RX true to enable recieve interrupts
00340     * @param TX true to enable transmit interrupts
00341     *
00342     * For c style callbacks simply set the callback to null to disable it.
00343     * When using c++ style callbacks both are enabled as default, this allows a method to disabled one or both.
00344     */
00345     void setInterrupt(bool RX, bool TX);                                                    // set Interrupt for received a good frame (CRC ok) or transmission done
00346 
00347 
00348     /** Get the first path amplitude values
00349     * @param fp_amp2 Will be set to first path second peak amplitude
00350     * @param fp_amp3 Will be set to first path third peak amplitude
00351     *
00352     * Reads the two registers for the last packet recieved. Used for quality metrics.
00353     */
00354     void getFirstPath(uint16_t *fp_amp2,uint16_t *fp_amp3);
00355 
00356 
00357     /** Get the LDE threshold value
00358     * @return the Leading edge detection threshold register value
00359     */
00360     inline uint16_t getLDE_THRESH() {
00361             return readRegister16(DW1000_LDE_CTRL,DWLDE_LDE_THRESH);
00362     }
00363 
00364     /** Get the LDE Peak path amplitude
00365     * @return the Leading edge detection peak path amplitude value
00366     */
00367     inline uint16_t getLDE_PPAMPL() {
00368             return readRegister16(DW1000_LDE_CTRL,DWLDE_LDE_PPAMPL);
00369         }
00370 
00371 
00372         
00373     #define DW1000_RX_TTCKO             0x14 //     5 Receiver Time Tracking Offset       (in double buffer set)
00374 
00375 private:
00376 
00377     void resetAll();                                                                        // soft reset the entire DW1000 (some registers stay as they were see User Manual)
00378 
00379     void setupRadio();
00380 
00381     // system register setup functions
00382     void setupGPIO();
00383     void setupAGC();
00384     void setupRxConfig();
00385     void setupLDE();
00386     void setupChannel();
00387     void setupTxFrameCtrl();
00388     void setupAnalogRF();
00389     void setupFreqSynth();
00390     void setupTxCalibration();
00391     void setupSystemConfig();
00392     void setupPower();
00393     void setupXtalTrim();
00394     
00395     void loadLDE();                                                                         // load the leading edge detection algorithm to RAM, [IMPORTANT because receiving malfunction may occur] see User Manual LDELOAD on p22 & p158
00396     void loadLDOTUNE();                                                                     // load the LDO tuning as set in the factory
00397 
00398     uint8_t powerToRegValue(float powerdB);
00399     float regToPowerValue(uint8_t powerVal);
00400 
00401     DW1000Setup systemConfig;
00402 
00403     // Interrupt
00404     InterruptIn irq;                                                                        // Pin used to handle Events from DW1000 by an Interrupthandler
00405     FunctionPointer callbackRX;                                                             // function pointer to callback which is called when successfull RX took place
00406     FunctionPointer callbackTX;                                                             // function pointer to callback which is called when successfull TX took place
00407     void ISR();                                                                             // interrupt handling method (also calls according callback methods)
00408 
00409     // SPI Inteface
00410     BurstSPI spi;                                                                                // SPI Bus
00411     DigitalOut cs;                                                                          // Slave selector for SPI-Bus (here explicitly needed to start and end SPI transactions also usable to wake up DW1000)
00412 
00413     uint8_t readRegister8(uint8_t reg, uint16_t subaddress);                                // expressive methods to read or write the number of bits written in the name
00414     uint16_t readRegister16(uint8_t reg, uint16_t subaddress);
00415     uint32_t readRegister32(uint8_t reg, uint16_t subaddress);
00416     uint64_t readRegister40(uint8_t reg, uint16_t subaddress);
00417     uint64_t readRegister64(uint8_t reg, uint16_t subaddress);
00418     void writeRegister8(uint8_t reg, uint16_t subaddress, uint8_t buffer);
00419     void writeRegister16(uint8_t reg, uint16_t subaddress, uint16_t buffer);
00420     void writeRegister32(uint8_t reg, uint16_t subaddress, uint32_t buffer);
00421     void writeRegister40(uint8_t reg, uint16_t subaddress, uint64_t buffer);
00422 
00423     void readRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length);       // reads the selected part of a slave register into the buffer memory
00424     void writeRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length);      // writes the buffer memory to the selected slave register
00425     void setupTransaction(uint8_t reg, uint16_t subaddress, bool write);                    // sets up an SPI read or write transaction with correct register address and offset
00426     void select();                                                                          // selects the only slave for a transaction
00427     void deselect();                                                                        // deselects the only slave after transaction
00428 };
00429 
00430 #endif