Simple driver for DWM1000 modules.

Committer:
bhepp
Date:
Mon Apr 04 11:19:26 2016 +0000
Revision:
6:028891b5f03b
Parent:
5:c34ebc7f650c
Removed automatic retransmission and added clearing sent flag before delayed transmission.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bhepp 2:12a2907957b8 1 // Adapted from Matthias Grob & Manuel Stalder - ETH Zürich - 2015
bhepp 2:12a2907957b8 2
bhepp 0:2c8820705cdd 3 #include "DW1000.h"
bhepp 0:2c8820705cdd 4
bhepp 0:2c8820705cdd 5 // Change this depending on whether damaged or heatlhy DWM1000 modules are used.
bhepp 0:2c8820705cdd 6 const bool DWM1000_DAMAGED = true;
bhepp 5:c34ebc7f650c 7 //const bool DWM1000_DAMAGED = false;
bhepp 0:2c8820705cdd 8
bhepp 0:2c8820705cdd 9 //#include "PC.h"
bhepp 0:2c8820705cdd 10 //static PC pc(USBTX, USBRX, 115200); // USB UART Terminal
bhepp 0:2c8820705cdd 11
bhepp 5:c34ebc7f650c 12 DW1000::DW1000(SPI& spi, InterruptIn* irq, PinName CS, PinName RESET)
bhepp 2:12a2907957b8 13 : irq(irq), spi(spi), cs(CS), reset(RESET) {
bhepp 5:c34ebc7f650c 14 if (irq != NULL) {
bhepp 5:c34ebc7f650c 15 irq->rise(this, &DW1000::ISR);
bhepp 5:c34ebc7f650c 16 }
bhepp 0:2c8820705cdd 17
bhepp 0:2c8820705cdd 18 setCallbacks(NULL, NULL);
bhepp 0:2c8820705cdd 19
bhepp 0:2c8820705cdd 20 select();
bhepp 0:2c8820705cdd 21 deselect(); // Chip must be deselected first
bhepp 0:2c8820705cdd 22 resetAll(); // we do a soft reset of the DW1000 everytime the driver starts
bhepp 0:2c8820705cdd 23
bhepp 0:2c8820705cdd 24 // Configuration TODO: make method for that
bhepp 0:2c8820705cdd 25 // User Manual "2.5.5 Default Configurations that should be modified" p. 22
bhepp 0:2c8820705cdd 26 //Those values are for the standard mode (6.8Mbps, 5, 16Mhz, 32 Symbols) and are INCOMPLETE!
bhepp 0:2c8820705cdd 27 // writeRegister16(DW1000_AGC_CTRL, 0x04, 0x8870);
bhepp 0:2c8820705cdd 28 // writeRegister32(DW1000_AGC_CTRL, 0x0C, 0x2502A907);
bhepp 0:2c8820705cdd 29 // writeRegister32(DW1000_DRX_CONF, 0x08, 0x311A002D);
bhepp 0:2c8820705cdd 30 // writeRegister8 (DW1000_LDE_CTRL, 0x0806, 0xD);
bhepp 0:2c8820705cdd 31 // writeRegister16(DW1000_LDE_CTRL, 0x1806, 0x1607);
bhepp 0:2c8820705cdd 32 // writeRegister32(DW1000_TX_POWER, 0, 0x0E082848);
bhepp 0:2c8820705cdd 33 // writeRegister32(DW1000_RF_CONF, 0x0C, 0x001E3FE0);
bhepp 0:2c8820705cdd 34 // writeRegister8 (DW1000_TX_CAL, 0x0B, 0xC0);
bhepp 0:2c8820705cdd 35 // writeRegister8 (DW1000_FS_CTRL, 0x0B, 0xA6);
bhepp 0:2c8820705cdd 36
bhepp 0:2c8820705cdd 37
bhepp 0:2c8820705cdd 38 //Those values are for the 110kbps mode (5, 16MHz, 1024 Symbols) and are quite complete
bhepp 0:2c8820705cdd 39 writeRegister16(DW1000_AGC_CTRL, 0x04, 0x8870); //AGC_TUNE1 for 16MHz PRF
bhepp 0:2c8820705cdd 40 writeRegister32(DW1000_AGC_CTRL, 0x0C, 0x2502A907); //AGC_TUNE2 (Universal)
bhepp 0:2c8820705cdd 41 writeRegister16(DW1000_AGC_CTRL, 0x12, 0x0055); //AGC_TUNE3 (Universal)
bhepp 0:2c8820705cdd 42
bhepp 0:2c8820705cdd 43 writeRegister16(DW1000_DRX_CONF, 0x02, 0x000A); //DRX_TUNE0b for 110kbps
bhepp 0:2c8820705cdd 44 writeRegister16(DW1000_DRX_CONF, 0x04, 0x0087); //DRX_TUNE1a for 16MHz PRF
bhepp 0:2c8820705cdd 45 writeRegister16(DW1000_DRX_CONF, 0x06, 0x0064); //DRX_TUNE1b for 110kbps & > 1024 symbols
bhepp 0:2c8820705cdd 46 writeRegister32(DW1000_DRX_CONF, 0x08, 0x351A009A); //PAC size for 1024 symbols preamble & 16MHz PRF
bhepp 0:2c8820705cdd 47 //writeRegister32(DW1000_DRX_CONF, 0x08, 0x371A011D); //PAC size for 2048 symbols preamble
bhepp 0:2c8820705cdd 48
bhepp 0:2c8820705cdd 49 writeRegister8 (DW1000_LDE_CTRL, 0x0806, 0xD); //LDE_CFG1
bhepp 0:2c8820705cdd 50 writeRegister16(DW1000_LDE_CTRL, 0x1806, 0x1607); //LDE_CFG2 for 16MHz PRF
bhepp 0:2c8820705cdd 51
bhepp 0:2c8820705cdd 52 writeRegister32(DW1000_TX_POWER, 0, 0x28282828); //Power for channel 5
bhepp 0:2c8820705cdd 53
bhepp 0:2c8820705cdd 54 writeRegister8(DW1000_RF_CONF, 0x0B, 0xD8); //RF_RXCTRLH for channel 5
bhepp 0:2c8820705cdd 55 writeRegister32(DW1000_RF_CONF, 0x0C, 0x001E3FE0); //RF_TXCTRL for channel 5
bhepp 0:2c8820705cdd 56
bhepp 0:2c8820705cdd 57 writeRegister8 (DW1000_TX_CAL, 0x0B, 0xC0); //TC_PGDELAY for channel 5
bhepp 0:2c8820705cdd 58
bhepp 0:2c8820705cdd 59 writeRegister32 (DW1000_FS_CTRL, 0x07, 0x0800041D); //FS_PLLCFG for channel 5
bhepp 0:2c8820705cdd 60 writeRegister8 (DW1000_FS_CTRL, 0x0B, 0xA6); //FS_PLLTUNE for channel 5
bhepp 0:2c8820705cdd 61
bhepp 0:2c8820705cdd 62 loadLDE(); // important everytime DW1000 initialises/awakes otherwise the LDE algorithm must be turned off or there's receiving malfunction see User Manual LDELOAD on p22 & p158
bhepp 0:2c8820705cdd 63
bhepp 0:2c8820705cdd 64 // 110kbps CAUTION: a lot of other registers have to be set for an optimized operation on 110kbps
bhepp 0:2c8820705cdd 65 writeRegister16(DW1000_TX_FCTRL, 1, 0x0800 | 0x0100 | 0x0080); // use 1024 symbols preamble (0x0800) (previously 2048 - 0x2800), 16MHz pulse repetition frequency (0x0100), 110kbps bit rate (0x0080) see p.69 of DW1000 User Manual
bhepp 0:2c8820705cdd 66 writeRegister8(DW1000_SYS_CFG, 2, 0x44); // enable special receiving option for 110kbps (disable smartTxPower)!! (0x44) see p.64 of DW1000 User Manual [DO NOT enable 1024 byte frames (0x03) becuase it generates disturbance of ranging don't know why...]
bhepp 0:2c8820705cdd 67
bhepp 0:2c8820705cdd 68 writeRegister16(DW1000_TX_ANTD, 0, 16384); // set TX and RX Antenna delay to neutral because we calibrate afterwards
bhepp 0:2c8820705cdd 69 writeRegister16(DW1000_LDE_CTRL, 0x1804, 16384); // = 2^14 a quarter of the range of the 16-Bit register which corresponds to zero calibration in a round trip (TX1+RX2+TX2+RX1)
bhepp 0:2c8820705cdd 70
bhepp 0:2c8820705cdd 71 writeRegister8(DW1000_SYS_CFG, 3, 0x20); // enable auto reenabling receiver after error
bhepp 0:2c8820705cdd 72
bhepp 5:c34ebc7f650c 73 if (irq != NULL) {
bhepp 5:c34ebc7f650c 74 irq->enable_irq();
bhepp 5:c34ebc7f650c 75 }
bhepp 0:2c8820705cdd 76 }
bhepp 0:2c8820705cdd 77
bhepp 0:2c8820705cdd 78 void DW1000::setCallbacks(void (*callbackRX)(void), void (*callbackTX)(void)) {
bhepp 0:2c8820705cdd 79 bool RX = false;
bhepp 0:2c8820705cdd 80 bool TX = false;
bhepp 0:2c8820705cdd 81 if (callbackRX) {
bhepp 0:2c8820705cdd 82 this->callbackRX.attach(callbackRX);
bhepp 0:2c8820705cdd 83 RX = true;
bhepp 0:2c8820705cdd 84 }
bhepp 0:2c8820705cdd 85 if (callbackTX) {
bhepp 0:2c8820705cdd 86 this->callbackTX.attach(callbackTX);
bhepp 0:2c8820705cdd 87 TX = true;
bhepp 0:2c8820705cdd 88 }
bhepp 0:2c8820705cdd 89 setInterrupt(RX, TX);
bhepp 0:2c8820705cdd 90 }
bhepp 0:2c8820705cdd 91
bhepp 0:2c8820705cdd 92 uint32_t DW1000::getDeviceID() {
bhepp 0:2c8820705cdd 93 uint32_t result;
bhepp 0:2c8820705cdd 94 readRegister(DW1000_DEV_ID, 0, (uint8_t*)&result, 4);
bhepp 0:2c8820705cdd 95 return result;
bhepp 0:2c8820705cdd 96 }
bhepp 0:2c8820705cdd 97
bhepp 0:2c8820705cdd 98 uint64_t DW1000::getEUI() {
bhepp 0:2c8820705cdd 99 uint64_t result;
bhepp 0:2c8820705cdd 100 readRegister(DW1000_EUI, 0, (uint8_t*)&result, 8);
bhepp 0:2c8820705cdd 101 return result;
bhepp 0:2c8820705cdd 102 }
bhepp 0:2c8820705cdd 103
bhepp 0:2c8820705cdd 104 void DW1000::setEUI(uint64_t EUI) {
bhepp 0:2c8820705cdd 105 writeRegister(DW1000_EUI, 0, (uint8_t*)&EUI, 8);
bhepp 0:2c8820705cdd 106 }
bhepp 0:2c8820705cdd 107
bhepp 0:2c8820705cdd 108 float DW1000::getVoltage() {
bhepp 0:2c8820705cdd 109 uint8_t buffer[7] = {0x80, 0x0A, 0x0F, 0x01, 0x00}; // algorithm form User Manual p57
bhepp 0:2c8820705cdd 110 writeRegister(DW1000_RF_CONF, 0x11, buffer, 2);
bhepp 0:2c8820705cdd 111 writeRegister(DW1000_RF_CONF, 0x12, &buffer[2], 1);
bhepp 0:2c8820705cdd 112 writeRegister(DW1000_TX_CAL, 0x00, &buffer[3], 1);
bhepp 0:2c8820705cdd 113 writeRegister(DW1000_TX_CAL, 0x00, &buffer[4], 1);
bhepp 0:2c8820705cdd 114 readRegister(DW1000_TX_CAL, 0x03, &buffer[5], 2); // get the 8-Bit readings for Voltage and Temperature
bhepp 0:2c8820705cdd 115 float Voltage = buffer[5] * 0.0057 + 2.3;
bhepp 0:2c8820705cdd 116 //float Temperature = buffer[6] * 1.13 - 113.0; // TODO: getTemperature was always ~35 degree with better formula/calibration
bhepp 0:2c8820705cdd 117 return Voltage;
bhepp 0:2c8820705cdd 118 }
bhepp 0:2c8820705cdd 119
bhepp 0:2c8820705cdd 120 uint64_t DW1000::getStatus() {
bhepp 0:2c8820705cdd 121 return readRegister40(DW1000_SYS_STATUS, 0);
bhepp 0:2c8820705cdd 122 }
bhepp 0:2c8820705cdd 123
bhepp 0:2c8820705cdd 124 bool DW1000::hasReceivedFrame() {
bhepp 0:2c8820705cdd 125 uint64_t status = getStatus();
bhepp 0:2c8820705cdd 126 return status & 0x4000;
bhepp 0:2c8820705cdd 127 }
bhepp 0:2c8820705cdd 128
bhepp 0:2c8820705cdd 129 void DW1000::clearReceivedFlag() {
bhepp 0:2c8820705cdd 130 writeRegister16(DW1000_SYS_STATUS, 0, 0x6F00); // clearing of receiving status bits
bhepp 0:2c8820705cdd 131 }
bhepp 0:2c8820705cdd 132
bhepp 4:faf802b4af85 133 bool DW1000::hasTransmissionStarted() {
bhepp 4:faf802b4af85 134 uint64_t status = getStatus();
bhepp 4:faf802b4af85 135 return status & 0x10;
bhepp 4:faf802b4af85 136 }
bhepp 4:faf802b4af85 137
bhepp 4:faf802b4af85 138 bool DW1000::hasSentPreamble() {
bhepp 4:faf802b4af85 139 uint64_t status = getStatus();
bhepp 4:faf802b4af85 140 return status & 0x20;
bhepp 4:faf802b4af85 141 }
bhepp 4:faf802b4af85 142
bhepp 4:faf802b4af85 143 bool DW1000::hasSentPHYHeader() {
bhepp 4:faf802b4af85 144 uint64_t status = getStatus();
bhepp 4:faf802b4af85 145 return status & 0x40;
bhepp 4:faf802b4af85 146 }
bhepp 4:faf802b4af85 147
bhepp 0:2c8820705cdd 148 bool DW1000::hasSentFrame() {
bhepp 0:2c8820705cdd 149 uint64_t status = getStatus();
bhepp 0:2c8820705cdd 150 return status & 0x80;
bhepp 0:2c8820705cdd 151 }
bhepp 0:2c8820705cdd 152
bhepp 0:2c8820705cdd 153 void DW1000::clearSentFlag() {
bhepp 0:2c8820705cdd 154 writeRegister8(DW1000_SYS_STATUS, 0, 0xF8); // clearing of sending status bits
bhepp 0:2c8820705cdd 155 }
bhepp 0:2c8820705cdd 156
bhepp 2:12a2907957b8 157 uint64_t DW1000::getSYSTimestamp() {
bhepp 2:12a2907957b8 158 return readRegister40(DW1000_SYS_TIME, 0);
bhepp 2:12a2907957b8 159 }
bhepp 2:12a2907957b8 160
bhepp 0:2c8820705cdd 161 uint64_t DW1000::getRXTimestamp() {
bhepp 0:2c8820705cdd 162 return readRegister40(DW1000_RX_TIME, 0);
bhepp 0:2c8820705cdd 163 }
bhepp 0:2c8820705cdd 164
bhepp 0:2c8820705cdd 165 uint64_t DW1000::getTXTimestamp() {
bhepp 0:2c8820705cdd 166 return readRegister40(DW1000_TX_TIME, 0);
bhepp 0:2c8820705cdd 167 }
bhepp 0:2c8820705cdd 168
bhepp 2:12a2907957b8 169 float DW1000::getSYSTimestampUS() {
bhepp 2:12a2907957b8 170 return getSYSTimestamp() * TIMEUNITS_TO_US;
bhepp 2:12a2907957b8 171 }
bhepp 2:12a2907957b8 172
bhepp 2:12a2907957b8 173 float DW1000::getRXTimestampUS() {
bhepp 2:12a2907957b8 174 return getRXTimestamp() * TIMEUNITS_TO_US;
bhepp 2:12a2907957b8 175 }
bhepp 2:12a2907957b8 176
bhepp 2:12a2907957b8 177 float DW1000::getTXTimestampUS() {
bhepp 2:12a2907957b8 178 return getTXTimestamp() * TIMEUNITS_TO_US;
bhepp 2:12a2907957b8 179 }
bhepp 2:12a2907957b8 180
bhepp 0:2c8820705cdd 181 uint16_t DW1000::getStdNoise() {
bhepp 0:2c8820705cdd 182 return readRegister16(DW1000_RX_FQUAL, 0x00);
bhepp 0:2c8820705cdd 183 }
bhepp 0:2c8820705cdd 184
bhepp 0:2c8820705cdd 185 uint16_t DW1000::getPACC() {
bhepp 0:2c8820705cdd 186 uint32_t v = readRegister32(DW1000_RX_FINFO, 0x00);
bhepp 0:2c8820705cdd 187 v >>= 20;
bhepp 0:2c8820705cdd 188 return static_cast<uint16_t>(v);
bhepp 0:2c8820705cdd 189 }
bhepp 0:2c8820705cdd 190
bhepp 0:2c8820705cdd 191 uint16_t DW1000::getFPINDEX() {
bhepp 0:2c8820705cdd 192 return readRegister16(DW1000_RX_TIME, 0x05);
bhepp 0:2c8820705cdd 193 }
bhepp 0:2c8820705cdd 194
bhepp 0:2c8820705cdd 195 uint16_t DW1000::getFPAMPL1() {
bhepp 0:2c8820705cdd 196 return readRegister16(DW1000_RX_TIME, 0x07);
bhepp 0:2c8820705cdd 197 }
bhepp 0:2c8820705cdd 198
bhepp 0:2c8820705cdd 199 uint16_t DW1000::getFPAMPL2() {
bhepp 0:2c8820705cdd 200 return readRegister16(DW1000_RX_FQUAL, 0x02);
bhepp 0:2c8820705cdd 201 }
bhepp 0:2c8820705cdd 202
bhepp 0:2c8820705cdd 203 uint16_t DW1000::getFPAMPL3() {
bhepp 0:2c8820705cdd 204 return readRegister16(DW1000_RX_FQUAL, 0x04);
bhepp 0:2c8820705cdd 205 }
bhepp 0:2c8820705cdd 206
bhepp 0:2c8820705cdd 207 uint16_t DW1000::getCIRPWR() {
bhepp 0:2c8820705cdd 208 return readRegister16(DW1000_RX_FQUAL, 0x06);
bhepp 0:2c8820705cdd 209 }
bhepp 0:2c8820705cdd 210
bhepp 2:12a2907957b8 211 uint8_t DW1000::getPRF()
bhepp 2:12a2907957b8 212 {
bhepp 2:12a2907957b8 213 uint32_t prf_mask = static_cast<uint32_t>(0x1 << 19 | 0x1 << 18);
bhepp 2:12a2907957b8 214 uint32_t prf = readRegister32(DW1000_CHAN_CTRL, 0x00);
bhepp 2:12a2907957b8 215 prf >>= 18;
bhepp 2:12a2907957b8 216 return static_cast<uint8_t>(prf & prf_mask);
bhepp 0:2c8820705cdd 217 }
bhepp 0:2c8820705cdd 218
bhepp 0:2c8820705cdd 219 void DW1000::sendString(char* message) {
bhepp 0:2c8820705cdd 220 sendFrame((uint8_t*)message, strlen(message)+1);
bhepp 0:2c8820705cdd 221 }
bhepp 0:2c8820705cdd 222
bhepp 0:2c8820705cdd 223 void DW1000::receiveString(char* message) {
bhepp 0:2c8820705cdd 224 readRegister(DW1000_RX_BUFFER, 0, (uint8_t*)message, getFramelength()); // get data from buffer
bhepp 0:2c8820705cdd 225 }
bhepp 0:2c8820705cdd 226
bhepp 0:2c8820705cdd 227 void DW1000::sendFrame(uint8_t* message, uint16_t length) {
bhepp 0:2c8820705cdd 228 //if (length >= 1021) length = 1021; // check for maximim length a frame can have with 1024 Byte frames [not used, see constructor]
bhepp 0:2c8820705cdd 229 if (length >= 125) length = 125; // check for maximim length a frame can have with 127 Byte frames
bhepp 5:c34ebc7f650c 230
bhepp 5:c34ebc7f650c 231 Timer timer;
bhepp 5:c34ebc7f650c 232 timer.start();
bhepp 0:2c8820705cdd 233 writeRegister(DW1000_TX_BUFFER, 0, message, length); // fill buffer
bhepp 0:2c8820705cdd 234
bhepp 0:2c8820705cdd 235 uint8_t backup = readRegister8(DW1000_TX_FCTRL, 1); // put length of frame
bhepp 0:2c8820705cdd 236 length += 2; // including 2 CRC Bytes
bhepp 0:2c8820705cdd 237 length = ((backup & 0xFC) << 8) | (length & 0x03FF);
bhepp 0:2c8820705cdd 238 writeRegister16(DW1000_TX_FCTRL, 0, length);
bhepp 0:2c8820705cdd 239
bhepp 0:2c8820705cdd 240 stopTRX(); // stop receiving
bhepp 0:2c8820705cdd 241 writeRegister8(DW1000_SYS_CTRL, 0, 0x02); // trigger sending process by setting the TXSTRT bit
bhepp 0:2c8820705cdd 242 }
bhepp 0:2c8820705cdd 243
bhepp 0:2c8820705cdd 244 void DW1000::sendDelayedFrame(uint8_t* message, uint16_t length, uint64_t TxTimestamp) {
bhepp 5:c34ebc7f650c 245 clearSentFlag(); // This is necessary, otherwise we pick up the transmission time of the previous send
bhepp 5:c34ebc7f650c 246
bhepp 4:faf802b4af85 247 if (TxTimestamp > CONST_2POWER40) {
bhepp 2:12a2907957b8 248 TxTimestamp -= CONST_2POWER40;
bhepp 2:12a2907957b8 249 }
bhepp 2:12a2907957b8 250
bhepp 0:2c8820705cdd 251 //if (length >= 1021) length = 1021; // check for maximim length a frame can have with 1024 Byte frames [not used, see constructor]
bhepp 0:2c8820705cdd 252 if (length >= 125) length = 125; // check for maximim length a frame can have with 127 Byte frames
bhepp 0:2c8820705cdd 253 writeRegister(DW1000_TX_BUFFER, 0, message, length); // fill buffer
bhepp 0:2c8820705cdd 254
bhepp 0:2c8820705cdd 255 uint8_t backup = readRegister8(DW1000_TX_FCTRL, 1); // put length of frame
bhepp 0:2c8820705cdd 256 length += 2; // including 2 CRC Bytes
bhepp 0:2c8820705cdd 257 length = ((backup & 0xFC) << 8) | (length & 0x03FF);
bhepp 0:2c8820705cdd 258 writeRegister16(DW1000_TX_FCTRL, 0, length);
bhepp 0:2c8820705cdd 259
bhepp 0:2c8820705cdd 260 writeRegister40(DW1000_DX_TIME, 0, TxTimestamp); //write the timestamp on which to send the message
bhepp 0:2c8820705cdd 261
bhepp 5:c34ebc7f650c 262 stopTRX(); // stop receiving
bhepp 0:2c8820705cdd 263 writeRegister8(DW1000_SYS_CTRL, 0, 0x02 | 0x04); // trigger sending process by setting the TXSTRT and TXDLYS bit
bhepp 0:2c8820705cdd 264 }
bhepp 0:2c8820705cdd 265
bhepp 0:2c8820705cdd 266 void DW1000::startRX() {
bhepp 0:2c8820705cdd 267 writeRegister8(DW1000_SYS_CTRL, 0x01, 0x01); // start listening for preamble by setting the RXENAB bit
bhepp 5:c34ebc7f650c 268 wait_us(16); // According to page 81 in the user manual (RXENAB bit)
bhepp 0:2c8820705cdd 269 }
bhepp 0:2c8820705cdd 270
bhepp 0:2c8820705cdd 271 void DW1000::stopTRX() {
bhepp 4:faf802b4af85 272 writeRegister8(DW1000_SYS_CTRL, 0, 0x40); // disable tranceiver go back to idle mode by setting the TRXOFF bit
bhepp 0:2c8820705cdd 273 }
bhepp 0:2c8820705cdd 274
bhepp 0:2c8820705cdd 275 // PRIVATE Methods ------------------------------------------------------------------------------------
bhepp 0:2c8820705cdd 276 void DW1000::loadLDE() { // initialise LDE algorithm LDELOAD User Manual p22
bhepp 0:2c8820705cdd 277 writeRegister16(DW1000_PMSC, 0, 0x0301); // set clock to XTAL so OTP is reliable
bhepp 0:2c8820705cdd 278 writeRegister16(DW1000_OTP_IF, 0x06, 0x8000); // set LDELOAD bit in OTP
bhepp 0:2c8820705cdd 279 wait_us(150);
bhepp 0:2c8820705cdd 280 writeRegister16(DW1000_PMSC, 0, 0x0200); // recover to PLL clock
bhepp 0:2c8820705cdd 281 }
bhepp 0:2c8820705cdd 282
bhepp 0:2c8820705cdd 283 void DW1000::resetRX() {
bhepp 0:2c8820705cdd 284 writeRegister8(DW1000_PMSC, 3, 0xE0); // set RX reset
bhepp 0:2c8820705cdd 285 writeRegister8(DW1000_PMSC, 3, 0xF0); // clear RX reset
bhepp 0:2c8820705cdd 286 }
bhepp 0:2c8820705cdd 287
bhepp 0:2c8820705cdd 288 void DW1000::hardwareReset(PinName reset_pin) {
bhepp 5:c34ebc7f650c 289 DigitalInOut reset(reset_pin);
bhepp 5:c34ebc7f650c 290 hardwareReset(reset);
bhepp 5:c34ebc7f650c 291 }
bhepp 5:c34ebc7f650c 292
bhepp 5:c34ebc7f650c 293 void DW1000::hardwareReset(DigitalInOut& reset) {
bhepp 5:c34ebc7f650c 294 if (reset.is_connected()) {
bhepp 5:c34ebc7f650c 295 // DWM1000 RESET logic.
bhepp 5:c34ebc7f650c 296 if (DWM1000_DAMAGED) {
bhepp 5:c34ebc7f650c 297 // The following code works for damaged DWM1000 modules.
bhepp 5:c34ebc7f650c 298 // IMPORTANT: This will damage healthy DWM1000 modules!
bhepp 5:c34ebc7f650c 299 reset.output();
bhepp 5:c34ebc7f650c 300 reset = 1;
bhepp 5:c34ebc7f650c 301 wait_ms(100);
bhepp 5:c34ebc7f650c 302 reset = 0;
bhepp 5:c34ebc7f650c 303 wait_ms(100);
bhepp 5:c34ebc7f650c 304 reset = 1;
bhepp 5:c34ebc7f650c 305 wait_ms(100);
bhepp 5:c34ebc7f650c 306 } else {
bhepp 5:c34ebc7f650c 307 // The following code works for healthy DWM1000 modules
bhepp 5:c34ebc7f650c 308 reset.output();
bhepp 5:c34ebc7f650c 309 reset = 0;
bhepp 5:c34ebc7f650c 310 wait_ms(100);
bhepp 5:c34ebc7f650c 311 reset.input();
bhepp 5:c34ebc7f650c 312 }
bhepp 0:2c8820705cdd 313 }
bhepp 0:2c8820705cdd 314 }
bhepp 0:2c8820705cdd 315
bhepp 5:c34ebc7f650c 316 void DW1000::softwareReset() {
bhepp 5:c34ebc7f650c 317 stopTRX();
bhepp 5:c34ebc7f650c 318 clearReceivedFlag();
bhepp 5:c34ebc7f650c 319 clearSentFlag();
bhepp 5:c34ebc7f650c 320 }
bhepp 5:c34ebc7f650c 321
bhepp 0:2c8820705cdd 322 void DW1000::resetAll() {
bhepp 5:c34ebc7f650c 323 hardwareReset(reset);
bhepp 0:2c8820705cdd 324
bhepp 0:2c8820705cdd 325 writeRegister8(DW1000_PMSC, 0, 0x01); // set clock to XTAL
bhepp 0:2c8820705cdd 326 writeRegister8(DW1000_PMSC, 3, 0x00); // set All reset
bhepp 0:2c8820705cdd 327 wait_us(10); // wait for PLL to lock
bhepp 0:2c8820705cdd 328 writeRegister8(DW1000_PMSC, 3, 0xF0); // clear All reset
bhepp 0:2c8820705cdd 329 }
bhepp 0:2c8820705cdd 330
bhepp 0:2c8820705cdd 331
bhepp 0:2c8820705cdd 332 void DW1000::setInterrupt(bool RX, bool TX) {
bhepp 0:2c8820705cdd 333 writeRegister16(DW1000_SYS_MASK, 0, RX*0x4000 | TX*0x0080); // RX good frame 0x4000, TX done 0x0080
bhepp 0:2c8820705cdd 334 }
bhepp 0:2c8820705cdd 335
bhepp 0:2c8820705cdd 336 void DW1000::ISR() {
bhepp 0:2c8820705cdd 337 uint64_t status = getStatus();
bhepp 0:2c8820705cdd 338 if (status & 0x4000) { // a frame was received
bhepp 0:2c8820705cdd 339 callbackRX.call();
bhepp 0:2c8820705cdd 340 writeRegister16(DW1000_SYS_STATUS, 0, 0x6F00); // clearing of receiving status bits
bhepp 0:2c8820705cdd 341 }
bhepp 0:2c8820705cdd 342 if (status & 0x80) { // sending complete
bhepp 0:2c8820705cdd 343 callbackTX.call();
bhepp 0:2c8820705cdd 344 writeRegister8(DW1000_SYS_STATUS, 0, 0xF8); // clearing of sending status bits
bhepp 0:2c8820705cdd 345 }
bhepp 0:2c8820705cdd 346 }
bhepp 0:2c8820705cdd 347
bhepp 0:2c8820705cdd 348 uint16_t DW1000::getFramelength() {
bhepp 0:2c8820705cdd 349 uint16_t framelength = readRegister16(DW1000_RX_FINFO, 0); // get framelength
bhepp 0:2c8820705cdd 350 framelength = (framelength & 0x03FF) - 2; // take only the right bits and subtract the 2 CRC Bytes
bhepp 0:2c8820705cdd 351 return framelength;
bhepp 0:2c8820705cdd 352 }
bhepp 0:2c8820705cdd 353
bhepp 0:2c8820705cdd 354 // SPI Interface ------------------------------------------------------------------------------------
bhepp 0:2c8820705cdd 355 uint8_t DW1000::readRegister8(uint8_t reg, uint16_t subaddress) {
bhepp 0:2c8820705cdd 356 uint8_t result;
bhepp 0:2c8820705cdd 357 readRegister(reg, subaddress, &result, 1);
bhepp 0:2c8820705cdd 358 return result;
bhepp 0:2c8820705cdd 359 }
bhepp 0:2c8820705cdd 360
bhepp 0:2c8820705cdd 361 uint16_t DW1000::readRegister16(uint8_t reg, uint16_t subaddress) {
bhepp 0:2c8820705cdd 362 uint16_t result;
bhepp 0:2c8820705cdd 363 readRegister(reg, subaddress, (uint8_t*)&result, 2);
bhepp 0:2c8820705cdd 364 return result;
bhepp 0:2c8820705cdd 365 }
bhepp 0:2c8820705cdd 366
bhepp 0:2c8820705cdd 367 uint32_t DW1000::readRegister32(uint8_t reg, uint16_t subaddress) {
bhepp 0:2c8820705cdd 368 uint32_t result;
bhepp 0:2c8820705cdd 369 readRegister(reg, subaddress, (uint8_t*)&result, 4);
bhepp 0:2c8820705cdd 370 return result;
bhepp 0:2c8820705cdd 371 }
bhepp 0:2c8820705cdd 372
bhepp 0:2c8820705cdd 373 uint64_t DW1000::readRegister40(uint8_t reg, uint16_t subaddress) {
bhepp 0:2c8820705cdd 374 uint64_t result;
bhepp 0:2c8820705cdd 375 readRegister(reg, subaddress, (uint8_t*)&result, 5);
bhepp 0:2c8820705cdd 376 result &= 0xFFFFFFFFFF; // only 40-Bit
bhepp 0:2c8820705cdd 377 return result;
bhepp 0:2c8820705cdd 378 }
bhepp 0:2c8820705cdd 379
bhepp 0:2c8820705cdd 380 void DW1000::writeRegister8(uint8_t reg, uint16_t subaddress, uint8_t buffer) {
bhepp 0:2c8820705cdd 381 writeRegister(reg, subaddress, &buffer, 1);
bhepp 0:2c8820705cdd 382 }
bhepp 0:2c8820705cdd 383
bhepp 0:2c8820705cdd 384 void DW1000::writeRegister16(uint8_t reg, uint16_t subaddress, uint16_t buffer) {
bhepp 0:2c8820705cdd 385 writeRegister(reg, subaddress, (uint8_t*)&buffer, 2);
bhepp 0:2c8820705cdd 386 }
bhepp 0:2c8820705cdd 387
bhepp 0:2c8820705cdd 388 void DW1000::writeRegister32(uint8_t reg, uint16_t subaddress, uint32_t buffer) {
bhepp 0:2c8820705cdd 389 writeRegister(reg, subaddress, (uint8_t*)&buffer, 4);
bhepp 0:2c8820705cdd 390 }
bhepp 0:2c8820705cdd 391
bhepp 0:2c8820705cdd 392 void DW1000::writeRegister40(uint8_t reg, uint16_t subaddress, uint64_t buffer) {
bhepp 0:2c8820705cdd 393 writeRegister(reg, subaddress, (uint8_t*)&buffer, 5);
bhepp 0:2c8820705cdd 394 }
bhepp 0:2c8820705cdd 395
bhepp 0:2c8820705cdd 396 void DW1000::readRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length) {
bhepp 0:2c8820705cdd 397 setupTransaction(reg, subaddress, false);
bhepp 0:2c8820705cdd 398 for(int i=0; i<length; i++) // get data
bhepp 0:2c8820705cdd 399 buffer[i] = spi.write(0x00);
bhepp 0:2c8820705cdd 400 deselect();
bhepp 0:2c8820705cdd 401 }
bhepp 0:2c8820705cdd 402
bhepp 0:2c8820705cdd 403 void DW1000::writeRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length) {
bhepp 0:2c8820705cdd 404 setupTransaction(reg, subaddress, true);
bhepp 0:2c8820705cdd 405 for(int i=0; i<length; i++) // put data
bhepp 0:2c8820705cdd 406 spi.write(buffer[i]);
bhepp 0:2c8820705cdd 407 deselect();
bhepp 0:2c8820705cdd 408 }
bhepp 0:2c8820705cdd 409
bhepp 0:2c8820705cdd 410 void DW1000::setupTransaction(uint8_t reg, uint16_t subaddress, bool write) {
bhepp 0:2c8820705cdd 411 reg |= (write * DW1000_WRITE_FLAG); // set read/write flag
bhepp 0:2c8820705cdd 412 select();
bhepp 0:2c8820705cdd 413 if (subaddress > 0) { // there's a subadress, we need to set flag and send second header byte
bhepp 0:2c8820705cdd 414 spi.write(reg | DW1000_SUBADDRESS_FLAG);
bhepp 0:2c8820705cdd 415 if (subaddress > 0x7F) { // sub address too long, we need to set flag and send third header byte
bhepp 0:2c8820705cdd 416 spi.write((uint8_t)(subaddress & 0x7F) | DW1000_2_SUBADDRESS_FLAG); // and
bhepp 0:2c8820705cdd 417 spi.write((uint8_t)(subaddress >> 7));
bhepp 0:2c8820705cdd 418 } else {
bhepp 0:2c8820705cdd 419 spi.write((uint8_t)subaddress);
bhepp 0:2c8820705cdd 420 }
bhepp 0:2c8820705cdd 421 } else {
bhepp 0:2c8820705cdd 422 spi.write(reg); // say which register address we want to access
bhepp 0:2c8820705cdd 423 }
bhepp 0:2c8820705cdd 424 }
bhepp 0:2c8820705cdd 425
bhepp 0:2c8820705cdd 426 void DW1000::select() { // always called to start an SPI transmission
bhepp 5:c34ebc7f650c 427 if (irq != NULL) {
bhepp 5:c34ebc7f650c 428 irq->disable_irq();
bhepp 5:c34ebc7f650c 429 }
bhepp 0:2c8820705cdd 430 cs = 0; // set Cable Select pin low to start transmission
bhepp 0:2c8820705cdd 431 }
bhepp 0:2c8820705cdd 432
bhepp 0:2c8820705cdd 433 void DW1000::deselect() { // always called to end an SPI transmission
bhepp 0:2c8820705cdd 434 cs = 1; // set Cable Select pin high to stop transmission
bhepp 5:c34ebc7f650c 435 if (irq != NULL) {
bhepp 5:c34ebc7f650c 436 irq->enable_irq();
bhepp 5:c34ebc7f650c 437 }
bhepp 0:2c8820705cdd 438 }