DW1000 UWB driver based on work of Matthias Grob & Manuel Stalder - ETH Zürich - 2015
DW1000.h@18:6c2ce1749d4a, 2017-11-13 (annotated)
- Committer:
- AndyA
- Date:
- Mon Nov 13 14:29:41 2017 +0000
- Revision:
- 18:6c2ce1749d4a
- Parent:
- 17:1fb08dfef237
Auto apply crystal trim on startup
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AndyA | 0:bddb8cd5e7df | 1 | // by Matthias Grob & Manuel Stalder - ETH Zürich - 2015 |
AndyA | 0:bddb8cd5e7df | 2 | |
AndyA | 0:bddb8cd5e7df | 3 | #ifndef DW1000_H |
AndyA | 0:bddb8cd5e7df | 4 | #define DW1000_H |
AndyA | 0:bddb8cd5e7df | 5 | |
AndyA | 0:bddb8cd5e7df | 6 | #include "mbed.h" |
AndyA | 7:b13881dbb09d | 7 | #include "BurstSPI.h" |
AndyA | 8:0b408e77b701 | 8 | #include "DW1000Registers.h" |
AndyA | 8:0b408e77b701 | 9 | #include "DW1000Setup.h" |
AndyA | 3:1459d2aa6b97 | 10 | |
AndyA | 8:0b408e77b701 | 11 | #define TIMEUNITS_TO_US (1/(128*499.2)) // conversion between the decawave timeunits (ca 15.65ps) to microseconds. |
AndyA | 8:0b408e77b701 | 12 | #define US_TO_TIMEUNITS ((uint32_t)(128*499.2)) // conversion between microseconds to the decawave timeunits (ca 15.65ps). |
AndyA | 8:0b408e77b701 | 13 | #define c_mPerS 299792458 |
AndyA | 8:0b408e77b701 | 14 | #define c_mmPerTick (c_mPerS * TIMEUNITS_TO_US / 1000) |
AndyA | 8:0b408e77b701 | 15 | #define c_mPerTick (c_mmPerTick/1000) |
AndyA | 4:5f1025df5530 | 16 | |
AndyA | 4:5f1025df5530 | 17 | |
AndyA | 0:bddb8cd5e7df | 18 | |
AndyA | 4:5f1025df5530 | 19 | /** A DW1000 driver |
AndyA | 9:326bf149c8bc | 20 | * |
AndyA | 9:326bf149c8bc | 21 | * It is expected that the protocol implimentation above this will inherit this object. |
AndyA | 9:326bf149c8bc | 22 | * If not using this structure then move the protected functions to being public. |
AndyA | 9:326bf149c8bc | 23 | * |
AndyA | 4:5f1025df5530 | 24 | */ |
AndyA | 0:bddb8cd5e7df | 25 | class DW1000 |
AndyA | 0:bddb8cd5e7df | 26 | { |
AndyA | 0:bddb8cd5e7df | 27 | public: |
AndyA | 0:bddb8cd5e7df | 28 | |
AndyA | 6:2c77afdf7367 | 29 | /** Constructor. |
AndyA | 6:2c77afdf7367 | 30 | * |
AndyA | 9:326bf149c8bc | 31 | * The radio will default to DW1000Setup::tunedDefault until you call applySetup() with a new configuration. |
AndyA | 6:2c77afdf7367 | 32 | */ |
AndyA | 9:326bf149c8bc | 33 | DW1000(PinName MOSI, PinName MISO, PinName SCLK, PinName CS, PinName IRQ); // constructor, uses SPI class |
AndyA | 6:2c77afdf7367 | 34 | |
AndyA | 15:6faab70a5b19 | 35 | void setSPISpeed(uint32_t speed); |
AndyA | 15:6faab70a5b19 | 36 | |
AndyA | 6:2c77afdf7367 | 37 | /** Read the device ID |
AndyA | 6:2c77afdf7367 | 38 | * @return the device ID (0xDECA0130) |
AndyA | 6:2c77afdf7367 | 39 | */ |
AndyA | 0:bddb8cd5e7df | 40 | uint32_t getDeviceID(); // gets the Device ID which should be 0xDECA0130 (good for testing SPI!) |
AndyA | 6:2c77afdf7367 | 41 | |
AndyA | 6:2c77afdf7367 | 42 | /** Read the Extended Unique ID |
AndyA | 6:2c77afdf7367 | 43 | * @return The device EUI as stored in the system registers |
AndyA | 6:2c77afdf7367 | 44 | */ |
AndyA | 6:2c77afdf7367 | 45 | uint64_t getEUI(); |
AndyA | 6:2c77afdf7367 | 46 | |
AndyA | 6:2c77afdf7367 | 47 | /** Set the Extended Unique ID |
AndyA | 6:2c77afdf7367 | 48 | * @param EUI The EUID to use |
AndyA | 6:2c77afdf7367 | 49 | * |
AndyA | 10:f1e3c04080d6 | 50 | * @note ID is only valid until the next power cycle and overrides the value in the OTP memory. |
AndyA | 6:2c77afdf7367 | 51 | * To set a value that is automatically loaded on startup set OTP memory addresses 0 and 1. |
AndyA | 6:2c77afdf7367 | 52 | */ |
AndyA | 0:bddb8cd5e7df | 53 | void setEUI(uint64_t EUI); // sets 64 bit Extended Unique Identifier according to IEEE standard |
AndyA | 6:2c77afdf7367 | 54 | |
AndyA | 6:2c77afdf7367 | 55 | /** Read voltage input |
AndyA | 6:2c77afdf7367 | 56 | |
AndyA | 6:2c77afdf7367 | 57 | @return the current device voltage |
AndyA | 6:2c77afdf7367 | 58 | |
AndyA | 6:2c77afdf7367 | 59 | For accurate ranging the voltage of the device should be taken into account. |
AndyA | 6:2c77afdf7367 | 60 | User manual give variation as ~5.35cm / V |
AndyA | 6:2c77afdf7367 | 61 | */ |
AndyA | 0:bddb8cd5e7df | 62 | float getVoltage(); // gets the current chip voltage measurement form the A/D converter |
AndyA | 6:2c77afdf7367 | 63 | |
AndyA | 6:2c77afdf7367 | 64 | /** Read on board temperature sensor |
AndyA | 6:2c77afdf7367 | 65 | @return The temperature in C |
AndyA | 6:2c77afdf7367 | 66 | |
AndyA | 6:2c77afdf7367 | 67 | For accurate ranging the temperature of the device should be taken into account. |
AndyA | 6:2c77afdf7367 | 68 | User manual give variation as ~2.15mm / C |
AndyA | 6:2c77afdf7367 | 69 | */ |
AndyA | 0:bddb8cd5e7df | 70 | float getTemperature(); // gets the current chip temperature measurement form the A/D converter |
AndyA | 6:2c77afdf7367 | 71 | |
AndyA | 6:2c77afdf7367 | 72 | /** Get the status register |
AndyA | 6:2c77afdf7367 | 73 | * @return The system status register |
AndyA | 6:2c77afdf7367 | 74 | * |
AndyA | 6:2c77afdf7367 | 75 | * See user manual section 7.2.17 for details |
AndyA | 6:2c77afdf7367 | 76 | */ |
AndyA | 0:bddb8cd5e7df | 77 | uint64_t getStatus(); // get the 40 bit device status |
AndyA | 6:2c77afdf7367 | 78 | |
AndyA | 9:326bf149c8bc | 79 | |
AndyA | 9:326bf149c8bc | 80 | /** Set receive antenna delay |
AndyA | 9:326bf149c8bc | 81 | * @param ticks Delay in system clock cycles |
AndyA | 9:326bf149c8bc | 82 | */ |
AndyA | 9:326bf149c8bc | 83 | void setRxDelay(uint16_t ticks); |
AndyA | 9:326bf149c8bc | 84 | /** Set transmit antenna delay |
AndyA | 9:326bf149c8bc | 85 | * @param ticks Delay in system clock cycles |
AndyA | 9:326bf149c8bc | 86 | */ |
AndyA | 9:326bf149c8bc | 87 | void setTxDelay(uint16_t ticks); |
AndyA | 9:326bf149c8bc | 88 | |
AndyA | 9:326bf149c8bc | 89 | /** Set receive antenna delay in meters |
AndyA | 9:326bf149c8bc | 90 | * @param errorDistance Delay in meters at speed of light |
AndyA | 9:326bf149c8bc | 91 | */ |
AndyA | 9:326bf149c8bc | 92 | void setRxDelayDistance(double errorDistance) { |
AndyA | 9:326bf149c8bc | 93 | setRxDelay(errorDistance/c_mPerTick); |
AndyA | 9:326bf149c8bc | 94 | }; |
AndyA | 9:326bf149c8bc | 95 | |
AndyA | 9:326bf149c8bc | 96 | /** Set transmit antenna delay in meters |
AndyA | 9:326bf149c8bc | 97 | * @param errorDistance Delay in meters at speed of light |
AndyA | 9:326bf149c8bc | 98 | */ |
AndyA | 9:326bf149c8bc | 99 | void setTxDelayDistance(double errorDistance) { |
AndyA | 9:326bf149c8bc | 100 | setTxDelay(errorDistance/c_mPerTick); |
AndyA | 9:326bf149c8bc | 101 | }; |
AndyA | 9:326bf149c8bc | 102 | |
AndyA | 9:326bf149c8bc | 103 | /** Read a value from the OTP memory |
AndyA | 9:326bf149c8bc | 104 | * @param word_address The OTP memory address to read. |
AndyA | 9:326bf149c8bc | 105 | * @return The 32 bit value at that address. |
AndyA | 9:326bf149c8bc | 106 | * |
AndyA | 9:326bf149c8bc | 107 | * See Section 6.3.1 of the user manual for the memory map. |
AndyA | 9:326bf149c8bc | 108 | */ |
AndyA | 9:326bf149c8bc | 109 | uint32_t readOTP (uint16_t word_address); |
AndyA | 9:326bf149c8bc | 110 | |
AndyA | 9:326bf149c8bc | 111 | /** Write a value to the OTP memory |
AndyA | 9:326bf149c8bc | 112 | * @param word_address The OTP memory address to read. |
AndyA | 9:326bf149c8bc | 113 | * @param data The value to write |
AndyA | 9:326bf149c8bc | 114 | * @return True if the write was sucessful. |
AndyA | 9:326bf149c8bc | 115 | * |
AndyA | 9:326bf149c8bc | 116 | * Writes the supplied data to the OTP memory and then reads it back to verify it was sucessfully programmed. |
AndyA | 10:f1e3c04080d6 | 117 | * @warning This is a one time operation for each memory address. |
AndyA | 9:326bf149c8bc | 118 | * See Section 6.3.1 of the user manual for the memory map. |
AndyA | 10:f1e3c04080d6 | 119 | * |
AndyA | 10:f1e3c04080d6 | 120 | * @note It is recommened that the device is reset or power cycled after programing. |
AndyA | 9:326bf149c8bc | 121 | */ |
AndyA | 9:326bf149c8bc | 122 | bool writeOTP(uint16_t word_address,uint32_t data); // program a value in the OTP. It is recommended to reset afterwards. |
AndyA | 9:326bf149c8bc | 123 | |
AndyA | 9:326bf149c8bc | 124 | /** get the current radio configuration |
AndyA | 9:326bf149c8bc | 125 | * @return A pointer to a DW1000Setup object of the current setup. |
AndyA | 9:326bf149c8bc | 126 | * |
AndyA | 9:326bf149c8bc | 127 | * Note to change the setup you must make a copy of the current setup and then pass that to applySetup(). |
AndyA | 9:326bf149c8bc | 128 | */ |
AndyA | 9:326bf149c8bc | 129 | DW1000Setup *getSetup(); |
AndyA | 9:326bf149c8bc | 130 | |
AndyA | 9:326bf149c8bc | 131 | /** Get the current Transmit gain settings. |
AndyA | 9:326bf149c8bc | 132 | * |
AndyA | 9:326bf149c8bc | 133 | * @param power Optional, is set to the first power in dBm |
AndyA | 9:326bf149c8bc | 134 | * @param boost500 Optional, is set to the second power in dBm |
AndyA | 9:326bf149c8bc | 135 | * @param boost250 Optional, is set to the third power in dBm |
AndyA | 9:326bf149c8bc | 136 | * @param boost125 Optional, is set to the forth power in dBm |
AndyA | 9:326bf149c8bc | 137 | * @return The raw transmit gain register value |
AndyA | 9:326bf149c8bc | 138 | * |
AndyA | 9:326bf149c8bc | 139 | * If smart power is on then power represents the normal transmit power, |
AndyA | 9:326bf149c8bc | 140 | * boost500-boost125 indicates the power used for packets of that number of us or less. |
AndyA | 9:326bf149c8bc | 141 | * |
AndyA | 9:326bf149c8bc | 142 | * If smart power is off then boost500 represents the gain for the PHY header, boost250 the gain for the main message. |
AndyA | 9:326bf149c8bc | 143 | * power and boost125 are not used. |
AndyA | 9:326bf149c8bc | 144 | */ |
AndyA | 9:326bf149c8bc | 145 | uint32_t getTxPower(float *power = NULL, float *boost500 = NULL, float *boost250 = NULL, float *boost125 = NULL); |
AndyA | 9:326bf149c8bc | 146 | |
AndyA | 9:326bf149c8bc | 147 | /** Set Transmit gain |
AndyA | 9:326bf149c8bc | 148 | * |
AndyA | 9:326bf149c8bc | 149 | * @param normalPowercB Normal transmit gain to use. |
AndyA | 9:326bf149c8bc | 150 | * @param boost500 Gain to use for 6.8Mb/s packets of under 500ms. |
AndyA | 9:326bf149c8bc | 151 | * @param boost250 Gain to use for 6.8Mb/s packets of under 250ms. |
AndyA | 9:326bf149c8bc | 152 | * @param boost125 Gain to use for 6.8Mb/s packets of under 125ms. |
AndyA | 9:326bf149c8bc | 153 | * |
AndyA | 9:326bf149c8bc | 154 | * All gains are in dB. Gains can be between 0 and 33.5dB. |
AndyA | 9:326bf149c8bc | 155 | * 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). |
AndyA | 9:326bf149c8bc | 156 | * If smart power is disabled then the normal gain is used for all settings. |
AndyA | 9:326bf149c8bc | 157 | * The values in the internal DW1000Setup are updated to reflect the configured powers. |
AndyA | 9:326bf149c8bc | 158 | */ |
AndyA | 9:326bf149c8bc | 159 | void setTxPower(float normalPowerdB, float boost500 = 0, float boost250 = 0, float boost125 = 0); |
AndyA | 9:326bf149c8bc | 160 | |
AndyA | 9:326bf149c8bc | 161 | /** Get the rx signal power for the last packet |
AndyA | 9:326bf149c8bc | 162 | * |
AndyA | 9:326bf149c8bc | 163 | * @param direct Is set to the direct path Rx power in dBm |
AndyA | 9:326bf149c8bc | 164 | * @param total Is set to the total Rx power in dBm |
AndyA | 9:326bf149c8bc | 165 | * |
AndyA | 9:326bf149c8bc | 166 | * According to the DW1000 manual if the direct path power is within 6dB of the total then it was probably a LoS measurment. |
AndyA | 9:326bf149c8bc | 167 | * If there is more than 10dB difference then it's probably an indirect path. |
AndyA | 9:326bf149c8bc | 168 | */ |
AndyA | 9:326bf149c8bc | 169 | void getRxSignalPower(float *direct, float *total); |
AndyA | 9:326bf149c8bc | 170 | |
AndyA | 10:f1e3c04080d6 | 171 | |
AndyA | 10:f1e3c04080d6 | 172 | void getFullQualityMetrics(uint16_t *std_noise, uint16_t *fp_amp1, uint16_t *fp_amp2, uint16_t *fp_amp3, |
AndyA | 10:f1e3c04080d6 | 173 | uint16_t *cir_pwr, uint16_t *preAmbleAcc, uint16_t *preAmbleAcc_NoSat); |
AndyA | 10:f1e3c04080d6 | 174 | |
AndyA | 13:8718966cd81e | 175 | void getFullLEDMetrics(uint16_t *led_thresh, uint16_t *led_ppindx, uint16_t *led_ppampl); |
AndyA | 9:326bf149c8bc | 176 | |
AndyA | 15:6faab70a5b19 | 177 | void getRxClockInfo(int32_t *offset, uint8_t* phase, uint8_t* delta); |
AndyA | 15:6faab70a5b19 | 178 | |
AndyA | 15:6faab70a5b19 | 179 | /** Read the current crystal tuning value |
AndyA | 15:6faab70a5b19 | 180 | * |
AndyA | 15:6faab70a5b19 | 181 | * Reads the current FX_XTALT value from 0 to 0x1f. |
AndyA | 15:6faab70a5b19 | 182 | * See section 8.1 of the manual for details. |
AndyA | 15:6faab70a5b19 | 183 | * |
AndyA | 15:6faab70a5b19 | 184 | * @return The current value. |
AndyA | 15:6faab70a5b19 | 185 | */ |
AndyA | 15:6faab70a5b19 | 186 | uint8_t readXTALTune(); |
AndyA | 15:6faab70a5b19 | 187 | |
AndyA | 15:6faab70a5b19 | 188 | |
AndyA | 15:6faab70a5b19 | 189 | /** Set the crystal tuning value |
AndyA | 15:6faab70a5b19 | 190 | * |
AndyA | 15:6faab70a5b19 | 191 | * Sets the value of the FX_XTALT register. |
AndyA | 15:6faab70a5b19 | 192 | * See section 8.1 of the manual for details. |
AndyA | 15:6faab70a5b19 | 193 | * |
AndyA | 15:6faab70a5b19 | 194 | * Values will be lost on reset, consider programming the final value |
AndyA | 15:6faab70a5b19 | 195 | * into the OTP memory to store perminently. |
AndyA | 15:6faab70a5b19 | 196 | * |
AndyA | 15:6faab70a5b19 | 197 | * @value The value to use from 0 to 0x1f |
AndyA | 15:6faab70a5b19 | 198 | */ |
AndyA | 15:6faab70a5b19 | 199 | void setXTALTune(uint8_t value); |
AndyA | 15:6faab70a5b19 | 200 | |
AndyA | 15:6faab70a5b19 | 201 | /** Puts the device into CW test mode |
AndyA | 15:6faab70a5b19 | 202 | * |
AndyA | 15:6faab70a5b19 | 203 | * The radio will be set to output a constant wave at carrier frequency. |
AndyA | 15:6faab70a5b19 | 204 | * Transmit gain will be set to the maximum of 33.5dB but can be chaged by |
AndyA | 15:6faab70a5b19 | 205 | * setting the TX power register |
AndyA | 15:6faab70a5b19 | 206 | * To exit test mode the radio should be reset. |
AndyA | 15:6faab70a5b19 | 207 | */ |
AndyA | 15:6faab70a5b19 | 208 | void enterRFTestMode(); |
AndyA | 15:6faab70a5b19 | 209 | |
AndyA | 17:1fb08dfef237 | 210 | /** apply a new radio setup to the UWB system |
AndyA | 17:1fb08dfef237 | 211 | * @param setup The new settings to use |
AndyA | 17:1fb08dfef237 | 212 | * @return true if the setup was applied. |
AndyA | 17:1fb08dfef237 | 213 | * |
AndyA | 17:1fb08dfef237 | 214 | * The setup object supplied is copied and can be disposed of after the call. |
AndyA | 17:1fb08dfef237 | 215 | * If the supplied setup fails DW1000Setup::check() then it is ignored and the function returns false. |
AndyA | 17:1fb08dfef237 | 216 | * @note This will reset the radio. You must re-enable interupts, receiver etc. after calling it. |
AndyA | 17:1fb08dfef237 | 217 | */ |
AndyA | 17:1fb08dfef237 | 218 | bool applySetup(DW1000Setup *setup); |
AndyA | 15:6faab70a5b19 | 219 | |
AndyA | 9:326bf149c8bc | 220 | protected: |
AndyA | 9:326bf149c8bc | 221 | |
AndyA | 9:326bf149c8bc | 222 | /** |
AndyA | 9:326bf149c8bc | 223 | * Sets the callbacks on packet Rx and Tx |
AndyA | 9:326bf149c8bc | 224 | * @param callbackRX The function to call on packet Rx complete |
AndyA | 9:326bf149c8bc | 225 | * @param callbackTX The function to call on packet Tx complete |
AndyA | 9:326bf149c8bc | 226 | * |
AndyA | 9:326bf149c8bc | 227 | * set either or both to null to disable the appropriate interupt |
AndyA | 9:326bf149c8bc | 228 | */ |
AndyA | 9:326bf149c8bc | 229 | void setCallbacks(void (*callbackRX)(void), void (*callbackTX)(void)); // setter for callback functions, automatically enables interrupt, if NULL is passed the coresponding interrupt gets disabled |
AndyA | 9:326bf149c8bc | 230 | |
AndyA | 9:326bf149c8bc | 231 | /** |
AndyA | 9:326bf149c8bc | 232 | * c++ version of setCallbacks() |
AndyA | 9:326bf149c8bc | 233 | * @param tptr object for callbacks |
AndyA | 9:326bf149c8bc | 234 | * @param mptrRX method to call on packet Rx complete |
AndyA | 9:326bf149c8bc | 235 | * @param mptrTX method to call on packet Tx complete |
AndyA | 9:326bf149c8bc | 236 | * |
AndyA | 9:326bf149c8bc | 237 | */ |
AndyA | 9:326bf149c8bc | 238 | template<typename T> |
AndyA | 9:326bf149c8bc | 239 | void setCallbacks(T* tptr, void (T::*mptrRX)(void), void (T::*mptrTX)(void)) { // overloaded setter to treat member function pointers of objects |
AndyA | 9:326bf149c8bc | 240 | callbackRX.attach(tptr, mptrRX); // possible client code: dw.setCallbacks(this, &A::callbackRX, &A::callbackTX); |
AndyA | 9:326bf149c8bc | 241 | 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 |
AndyA | 9:326bf149c8bc | 242 | setInterrupt(true,true); |
AndyA | 9:326bf149c8bc | 243 | } |
AndyA | 9:326bf149c8bc | 244 | |
AndyA | 6:2c77afdf7367 | 245 | /** Get the last packet recieve time |
AndyA | 6:2c77afdf7367 | 246 | * @return the internal time stamp for the last packet Rx |
AndyA | 6:2c77afdf7367 | 247 | * |
AndyA | 6:2c77afdf7367 | 248 | * Time is counted on a clock running at 499.2MHz * 128 (~15.65ps) |
AndyA | 6:2c77afdf7367 | 249 | * This value is raw time minus user set Rx antenna delay. |
AndyA | 6:2c77afdf7367 | 250 | */ |
AndyA | 0:bddb8cd5e7df | 251 | uint64_t getRXTimestamp(); |
AndyA | 6:2c77afdf7367 | 252 | |
AndyA | 6:2c77afdf7367 | 253 | /** Get the last packet transmit time |
AndyA | 6:2c77afdf7367 | 254 | * @return the internal time stamp for the last packet Tx |
AndyA | 6:2c77afdf7367 | 255 | * |
AndyA | 6:2c77afdf7367 | 256 | * Time is counted on a clock running at 499.2MHz * 128 (~15.65ps) |
AndyA | 6:2c77afdf7367 | 257 | * This value is raw time plus user set Tx antenna delay to give time at the antenna. |
AndyA | 6:2c77afdf7367 | 258 | */ |
AndyA | 0:bddb8cd5e7df | 259 | uint64_t getTXTimestamp(); |
AndyA | 0:bddb8cd5e7df | 260 | |
AndyA | 6:2c77afdf7367 | 261 | /** Send a packet |
AndyA | 6:2c77afdf7367 | 262 | * @param message A buffer containing the data to send |
AndyA | 6:2c77afdf7367 | 263 | * @param length The length of the data in bytes. |
AndyA | 6:2c77afdf7367 | 264 | * |
AndyA | 6:2c77afdf7367 | 265 | * The supplied packet is transmitted as soon as possible and the reciever re-enabled once transmission is complete. |
AndyA | 6:2c77afdf7367 | 266 | * Maximum packet size is 125 bytes. |
AndyA | 9:326bf149c8bc | 267 | * |
AndyA | 9:326bf149c8bc | 268 | * The receiver is re-activated as soon as packet transmission is complete. |
AndyA | 6:2c77afdf7367 | 269 | */ |
AndyA | 0:bddb8cd5e7df | 270 | void sendFrame(uint8_t* message, uint16_t length); // send a raw frame (length in bytes) |
AndyA | 6:2c77afdf7367 | 271 | |
AndyA | 6:2c77afdf7367 | 272 | /** Send a packet at a certain time |
AndyA | 6:2c77afdf7367 | 273 | * @param message A buffer containing the data to send |
AndyA | 6:2c77afdf7367 | 274 | * @param length The length of the data in bytes. |
AndyA | 6:2c77afdf7367 | 275 | * @param TxTimestamp The timestamp to send the packet. |
AndyA | 6:2c77afdf7367 | 276 | * |
AndyA | 6:2c77afdf7367 | 277 | * The supplied packet is transmitted once the internal clock reaches the specified timestamp. |
AndyA | 6:2c77afdf7367 | 278 | * Maximum packet size is 125 bytes. |
AndyA | 6:2c77afdf7367 | 279 | * Rx is disabled as soon as this command is issued and re-enabled once transmission is complete. |
AndyA | 6:2c77afdf7367 | 280 | * Note - 9 LSBs are ignored so timings are only accurate to ~8ns. For more accurate timing check the |
AndyA | 6:2c77afdf7367 | 281 | * tx timestamp after transmission is complete. |
AndyA | 9:326bf149c8bc | 282 | * |
AndyA | 9:326bf149c8bc | 283 | * The receiver is re-activated as soon as packet transmission is complete. |
AndyA | 9:326bf149c8bc | 284 | * |
AndyA | 6:2c77afdf7367 | 285 | */ |
AndyA | 0:bddb8cd5e7df | 286 | void sendDelayedFrame(uint8_t* message, uint16_t length, uint64_t TxTimestamp); |
AndyA | 0:bddb8cd5e7df | 287 | |
AndyA | 6:2c77afdf7367 | 288 | /** Set up data for a transmit on sync |
AndyA | 6:2c77afdf7367 | 289 | * @param message A buffer containing the data to send |
AndyA | 6:2c77afdf7367 | 290 | * @param length The length of the data in bytes. |
AndyA | 6:2c77afdf7367 | 291 | * |
AndyA | 6:2c77afdf7367 | 292 | * Data is loaded into the transmit buffer but the transmission is not started. |
AndyA | 6:2c77afdf7367 | 293 | * Maximum packet size is 125 bytes. |
AndyA | 6:2c77afdf7367 | 294 | */ |
AndyA | 0:bddb8cd5e7df | 295 | void setupSyncedFrame(uint8_t* message, uint16_t length); |
AndyA | 6:2c77afdf7367 | 296 | |
AndyA | 6:2c77afdf7367 | 297 | /** Transmit on the next sync pulse |
AndyA | 6:2c77afdf7367 | 298 | * |
AndyA | 6:2c77afdf7367 | 299 | * On the next rising edge of the sync line the transmitter will be activated. |
AndyA | 6:2c77afdf7367 | 300 | * The packet must have previously been set up using setupSyncedFrame() |
AndyA | 6:2c77afdf7367 | 301 | * |
AndyA | 9:326bf149c8bc | 302 | * Rx is disabled until transmission is complete and then re-enabled. |
AndyA | 6:2c77afdf7367 | 303 | */ |
AndyA | 0:bddb8cd5e7df | 304 | void armSyncedFrame(); |
AndyA | 0:bddb8cd5e7df | 305 | |
AndyA | 9:326bf149c8bc | 306 | /** Get last packet size |
AndyA | 9:326bf149c8bc | 307 | * @return The length in bytes of the last packet received |
AndyA | 9:326bf149c8bc | 308 | */ |
AndyA | 9:326bf149c8bc | 309 | uint16_t getFramelength(); // to get the framelength of the received frame from the PHY header |
AndyA | 9:326bf149c8bc | 310 | |
AndyA | 9:326bf149c8bc | 311 | /** Get last recieved packet |
AndyA | 9:326bf149c8bc | 312 | * @param buffer The location to put the received data |
AndyA | 9:326bf149c8bc | 313 | * @param length The number of bytes to read |
AndyA | 9:326bf149c8bc | 314 | */ |
AndyA | 9:326bf149c8bc | 315 | void readRxBuffer( uint8_t *buffer, int length ) { |
AndyA | 9:326bf149c8bc | 316 | readRegister(DW1000_RX_BUFFER, 0, buffer, length); |
AndyA | 9:326bf149c8bc | 317 | } |
AndyA | 9:326bf149c8bc | 318 | |
AndyA | 6:2c77afdf7367 | 319 | /** Enable reciever |
AndyA | 6:2c77afdf7367 | 320 | * |
AndyA | 6:2c77afdf7367 | 321 | * This is automatically done after each Tx completes but can also be forced manually |
AndyA | 6:2c77afdf7367 | 322 | */ |
AndyA | 0:bddb8cd5e7df | 323 | void startRX(); // start listening for frames |
AndyA | 6:2c77afdf7367 | 324 | |
AndyA | 6:2c77afdf7367 | 325 | /** Disable radio link |
AndyA | 6:2c77afdf7367 | 326 | * |
AndyA | 6:2c77afdf7367 | 327 | * Disables both the recieve and transmit systems. |
AndyA | 6:2c77afdf7367 | 328 | * Any transmissions waiting for a delayed time or sync pulse will be canceled. |
AndyA | 6:2c77afdf7367 | 329 | */ |
AndyA | 0:bddb8cd5e7df | 330 | void stopTRX(); // disable tranceiver go back to idle mode |
AndyA | 0:bddb8cd5e7df | 331 | |
AndyA | 6:2c77afdf7367 | 332 | /** Reset the reciever logic |
AndyA | 6:2c77afdf7367 | 333 | * |
AndyA | 6:2c77afdf7367 | 334 | * This should be done after any receive errors |
AndyA | 6:2c77afdf7367 | 335 | */ |
AndyA | 0:bddb8cd5e7df | 336 | void resetRX(); // soft reset only the tranciever part of DW1000 |
AndyA | 6:2c77afdf7367 | 337 | |
AndyA | 6:2c77afdf7367 | 338 | /** Enable/Disable interrupts |
AndyA | 6:2c77afdf7367 | 339 | * @param RX true to enable recieve interrupts |
AndyA | 6:2c77afdf7367 | 340 | * @param TX true to enable transmit interrupts |
AndyA | 6:2c77afdf7367 | 341 | * |
AndyA | 6:2c77afdf7367 | 342 | * For c style callbacks simply set the callback to null to disable it. |
AndyA | 6:2c77afdf7367 | 343 | * When using c++ style callbacks both are enabled as default, this allows a method to disabled one or both. |
AndyA | 6:2c77afdf7367 | 344 | */ |
AndyA | 0:bddb8cd5e7df | 345 | void setInterrupt(bool RX, bool TX); // set Interrupt for received a good frame (CRC ok) or transmission done |
AndyA | 0:bddb8cd5e7df | 346 | |
AndyA | 10:f1e3c04080d6 | 347 | |
AndyA | 10:f1e3c04080d6 | 348 | /** Get the first path amplitude values |
AndyA | 10:f1e3c04080d6 | 349 | * @param fp_amp2 Will be set to first path second peak amplitude |
AndyA | 10:f1e3c04080d6 | 350 | * @param fp_amp3 Will be set to first path third peak amplitude |
AndyA | 10:f1e3c04080d6 | 351 | * |
AndyA | 10:f1e3c04080d6 | 352 | * Reads the two registers for the last packet recieved. Used for quality metrics. |
AndyA | 10:f1e3c04080d6 | 353 | */ |
AndyA | 10:f1e3c04080d6 | 354 | void getFirstPath(uint16_t *fp_amp2,uint16_t *fp_amp3); |
AndyA | 10:f1e3c04080d6 | 355 | |
AndyA | 12:da4b09aff6af | 356 | |
AndyA | 12:da4b09aff6af | 357 | /** Get the LDE threshold value |
AndyA | 12:da4b09aff6af | 358 | * @return the Leading edge detection threshold register value |
AndyA | 12:da4b09aff6af | 359 | */ |
AndyA | 12:da4b09aff6af | 360 | inline uint16_t getLDE_THRESH() { |
AndyA | 12:da4b09aff6af | 361 | return readRegister16(DW1000_LDE_CTRL,DWLDE_LDE_THRESH); |
AndyA | 12:da4b09aff6af | 362 | } |
AndyA | 12:da4b09aff6af | 363 | |
AndyA | 12:da4b09aff6af | 364 | /** Get the LDE Peak path amplitude |
AndyA | 12:da4b09aff6af | 365 | * @return the Leading edge detection peak path amplitude value |
AndyA | 12:da4b09aff6af | 366 | */ |
AndyA | 12:da4b09aff6af | 367 | inline uint16_t getLDE_PPAMPL() { |
AndyA | 12:da4b09aff6af | 368 | return readRegister16(DW1000_LDE_CTRL,DWLDE_LDE_PPAMPL); |
AndyA | 12:da4b09aff6af | 369 | } |
AndyA | 12:da4b09aff6af | 370 | |
AndyA | 15:6faab70a5b19 | 371 | |
AndyA | 15:6faab70a5b19 | 372 | |
AndyA | 15:6faab70a5b19 | 373 | #define DW1000_RX_TTCKO 0x14 // 5 Receiver Time Tracking Offset (in double buffer set) |
AndyA | 15:6faab70a5b19 | 374 | |
AndyA | 0:bddb8cd5e7df | 375 | private: |
AndyA | 15:6faab70a5b19 | 376 | |
AndyA | 0:bddb8cd5e7df | 377 | void resetAll(); // soft reset the entire DW1000 (some registers stay as they were see User Manual) |
AndyA | 3:1459d2aa6b97 | 378 | |
AndyA | 3:1459d2aa6b97 | 379 | void setupRadio(); |
AndyA | 3:1459d2aa6b97 | 380 | |
AndyA | 4:5f1025df5530 | 381 | // system register setup functions |
AndyA | 9:326bf149c8bc | 382 | void setupGPIO(); |
AndyA | 3:1459d2aa6b97 | 383 | void setupAGC(); |
AndyA | 3:1459d2aa6b97 | 384 | void setupRxConfig(); |
AndyA | 3:1459d2aa6b97 | 385 | void setupLDE(); |
AndyA | 3:1459d2aa6b97 | 386 | void setupChannel(); |
AndyA | 3:1459d2aa6b97 | 387 | void setupTxFrameCtrl(); |
AndyA | 3:1459d2aa6b97 | 388 | void setupAnalogRF(); |
AndyA | 3:1459d2aa6b97 | 389 | void setupFreqSynth(); |
AndyA | 3:1459d2aa6b97 | 390 | void setupTxCalibration(); |
AndyA | 3:1459d2aa6b97 | 391 | void setupSystemConfig(); |
AndyA | 9:326bf149c8bc | 392 | void setupPower(); |
AndyA | 18:6c2ce1749d4a | 393 | void setupXtalTrim(); |
AndyA | 18:6c2ce1749d4a | 394 | |
AndyA | 0:bddb8cd5e7df | 395 | void loadLDE(); // load the leading edge detection algorithm to RAM, [IMPORTANT because receiving malfunction may occur] see User Manual LDELOAD on p22 & p158 |
AndyA | 0:bddb8cd5e7df | 396 | void loadLDOTUNE(); // load the LDO tuning as set in the factory |
AndyA | 0:bddb8cd5e7df | 397 | |
AndyA | 9:326bf149c8bc | 398 | uint8_t powerToRegValue(float powerdB); |
AndyA | 9:326bf149c8bc | 399 | float regToPowerValue(uint8_t powerVal); |
AndyA | 3:1459d2aa6b97 | 400 | |
AndyA | 4:5f1025df5530 | 401 | DW1000Setup systemConfig; |
AndyA | 3:1459d2aa6b97 | 402 | |
AndyA | 0:bddb8cd5e7df | 403 | // Interrupt |
AndyA | 0:bddb8cd5e7df | 404 | InterruptIn irq; // Pin used to handle Events from DW1000 by an Interrupthandler |
AndyA | 0:bddb8cd5e7df | 405 | FunctionPointer callbackRX; // function pointer to callback which is called when successfull RX took place |
AndyA | 0:bddb8cd5e7df | 406 | FunctionPointer callbackTX; // function pointer to callback which is called when successfull TX took place |
AndyA | 0:bddb8cd5e7df | 407 | void ISR(); // interrupt handling method (also calls according callback methods) |
AndyA | 0:bddb8cd5e7df | 408 | |
AndyA | 0:bddb8cd5e7df | 409 | // SPI Inteface |
AndyA | 7:b13881dbb09d | 410 | BurstSPI spi; // SPI Bus |
AndyA | 0:bddb8cd5e7df | 411 | DigitalOut cs; // Slave selector for SPI-Bus (here explicitly needed to start and end SPI transactions also usable to wake up DW1000) |
AndyA | 0:bddb8cd5e7df | 412 | |
AndyA | 0:bddb8cd5e7df | 413 | uint8_t readRegister8(uint8_t reg, uint16_t subaddress); // expressive methods to read or write the number of bits written in the name |
AndyA | 0:bddb8cd5e7df | 414 | uint16_t readRegister16(uint8_t reg, uint16_t subaddress); |
AndyA | 9:326bf149c8bc | 415 | uint32_t readRegister32(uint8_t reg, uint16_t subaddress); |
AndyA | 0:bddb8cd5e7df | 416 | uint64_t readRegister40(uint8_t reg, uint16_t subaddress); |
AndyA | 0:bddb8cd5e7df | 417 | uint64_t readRegister64(uint8_t reg, uint16_t subaddress); |
AndyA | 0:bddb8cd5e7df | 418 | void writeRegister8(uint8_t reg, uint16_t subaddress, uint8_t buffer); |
AndyA | 0:bddb8cd5e7df | 419 | void writeRegister16(uint8_t reg, uint16_t subaddress, uint16_t buffer); |
AndyA | 0:bddb8cd5e7df | 420 | void writeRegister32(uint8_t reg, uint16_t subaddress, uint32_t buffer); |
AndyA | 0:bddb8cd5e7df | 421 | void writeRegister40(uint8_t reg, uint16_t subaddress, uint64_t buffer); |
AndyA | 0:bddb8cd5e7df | 422 | |
AndyA | 0:bddb8cd5e7df | 423 | 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 |
AndyA | 0:bddb8cd5e7df | 424 | void writeRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length); // writes the buffer memory to the selected slave register |
AndyA | 0:bddb8cd5e7df | 425 | void setupTransaction(uint8_t reg, uint16_t subaddress, bool write); // sets up an SPI read or write transaction with correct register address and offset |
AndyA | 0:bddb8cd5e7df | 426 | void select(); // selects the only slave for a transaction |
AndyA | 0:bddb8cd5e7df | 427 | void deselect(); // deselects the only slave after transaction |
AndyA | 0:bddb8cd5e7df | 428 | }; |
AndyA | 0:bddb8cd5e7df | 429 | |
AndyA | 0:bddb8cd5e7df | 430 | #endif |