DW1000 UWB driver based on work of Matthias Grob & Manuel Stalder - ETH Zürich - 2015
Diff: DW1000.h
- 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);