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

Dependencies:   BurstSPI

Committer:
AndyA
Date:
Tue Apr 05 10:51:00 2016 +0000
Revision:
0:bddb8cd5e7df
Child:
1:dcbd071f38d5
Child:
2:ebbb05cbc417
My version of the DW1000 driver

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AndyA 0:bddb8cd5e7df 1 #include "DW1000.h"
AndyA 0:bddb8cd5e7df 2
AndyA 0:bddb8cd5e7df 3 #define SPIRATE_PLL (5*1000*1000)
AndyA 0:bddb8cd5e7df 4 #define SPIRATE_OSC (2*1000*1000)
AndyA 0:bddb8cd5e7df 5
AndyA 0:bddb8cd5e7df 6 DW1000::DW1000(UWBMode setup, PinName MOSI, PinName MISO, PinName SCLK, PinName CS, PinName IRQ) : irq(IRQ), spi(MOSI, MISO, SCLK), cs(CS)
AndyA 0:bddb8cd5e7df 7 {
AndyA 0:bddb8cd5e7df 8 setCallbacks(NULL, NULL);
AndyA 0:bddb8cd5e7df 9
AndyA 0:bddb8cd5e7df 10 deselect(); // Chip must be deselected first
AndyA 0:bddb8cd5e7df 11 spi.format(8,0); // Setup the spi for standard 8 bit data and SPI-Mode 0 (GPIO5, GPIO6 open circuit or ground on DW1000)
AndyA 0:bddb8cd5e7df 12 spi.frequency(SPIRATE_PLL); // with a 1MHz clock rate (worked up to 49MHz in our Test)
AndyA 0:bddb8cd5e7df 13
AndyA 0:bddb8cd5e7df 14 resetAll(); // we do a soft reset of the DW1000 everytime the driver starts
AndyA 0:bddb8cd5e7df 15
AndyA 0:bddb8cd5e7df 16 switch (setup) {
AndyA 0:bddb8cd5e7df 17 case user110k: // values from Matthias Grob & Manuel Stalder - ETH Zürich - library
AndyA 0:bddb8cd5e7df 18 //Those values are for the 110kbps mode (5, 16MHz, 1024 Symbols) and are quite complete
AndyA 0:bddb8cd5e7df 19 writeRegister16(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE1, 0x8870); //AGC_TUNE1 for 16MHz PRF
AndyA 0:bddb8cd5e7df 20 writeRegister32(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE2, 0x2502A907); //AGC_TUNE2 (Universal)
AndyA 0:bddb8cd5e7df 21 writeRegister16(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE3, 0x0055); //AGC_TUNE3 (Universal)
AndyA 0:bddb8cd5e7df 22
AndyA 0:bddb8cd5e7df 23 writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x000A); //DRX_TUNE0b for 110kbps
AndyA 0:bddb8cd5e7df 24 writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1A, 0x0087); //DRX_TUNE1a for 16MHz PRF
AndyA 0:bddb8cd5e7df 25 writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1B, 0x0064); //DRX_TUNE1b for 110kbps & > 1024 symbols
AndyA 0:bddb8cd5e7df 26 writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x351A009A); //PAC size for 1024 symbols preamble & 16MHz PRF
AndyA 0:bddb8cd5e7df 27 //writeRegister32(DW1000_DRX_CONF, 0x08, 0x371A011D); //PAC size for 2048 symbols preamble
AndyA 0:bddb8cd5e7df 28
AndyA 0:bddb8cd5e7df 29 writeRegister8 (DW1000_LDE_CTRL, DWLDE_LDE_CFG1, 0xD); //LDE_CFG1
AndyA 0:bddb8cd5e7df 30 writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_CFG2, 0x1607); //LDE_CFG2 for 16MHz PRF
AndyA 0:bddb8cd5e7df 31
AndyA 0:bddb8cd5e7df 32 writeRegister32(DW1000_TX_POWER, 0, 0x28282828); //Power for channel 5
AndyA 0:bddb8cd5e7df 33
AndyA 0:bddb8cd5e7df 34 writeRegister8(DW1000_RF_CONF, DWRFCONF_RF_RXCTRLH, 0xD8); //RF_RXCTRLH for channel 5
AndyA 0:bddb8cd5e7df 35 writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x001E3FE0); //RF_TXCTRL for channel 5
AndyA 0:bddb8cd5e7df 36
AndyA 0:bddb8cd5e7df 37 writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0xC0); //TC_PGDELAY for channel 5
AndyA 0:bddb8cd5e7df 38
AndyA 0:bddb8cd5e7df 39 writeRegister32 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLCFG, 0x0800041D); //FS_PLLCFG for channel 5
AndyA 0:bddb8cd5e7df 40 writeRegister8 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLTUNE, 0xBE); // changed from 0xA6 //FS_PLLTUNE for channel 5
AndyA 0:bddb8cd5e7df 41
AndyA 0:bddb8cd5e7df 42 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
AndyA 0:bddb8cd5e7df 43
AndyA 0:bddb8cd5e7df 44 // 110kbps CAUTION: a lot of other registers have to be set for an optimized operation on 110kbps
AndyA 0:bddb8cd5e7df 45 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
AndyA 0:bddb8cd5e7df 46 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...]
AndyA 0:bddb8cd5e7df 47
AndyA 0:bddb8cd5e7df 48 writeRegister16(DW1000_TX_ANTD, 0, 16384); // set TX and RX Antenna delay to neutral because we calibrate afterwards
AndyA 0:bddb8cd5e7df 49 writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_RXANTD, 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)
AndyA 0:bddb8cd5e7df 50 break;
AndyA 0:bddb8cd5e7df 51
AndyA 0:bddb8cd5e7df 52 case tunedDefault: // User Manual "2.5.5 Default Configurations that should be modified" p. 22
AndyA 0:bddb8cd5e7df 53 //Those values are for the standard mode (6.8Mbps, 5, 16Mhz, 32 Symbols) and are (may be?) INCOMPLETE!
AndyA 0:bddb8cd5e7df 54 writeRegister16(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE1, 0x8870);
AndyA 0:bddb8cd5e7df 55 writeRegister32(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE2, 0x2502A907);
AndyA 0:bddb8cd5e7df 56 writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x311A002D);
AndyA 0:bddb8cd5e7df 57 writeRegister8(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0001);
AndyA 0:bddb8cd5e7df 58 writeRegister8(DW1000_DRX_CONF, DWDRX_DRX_TUNE1A, 0x0087);
AndyA 0:bddb8cd5e7df 59 writeRegister8(DW1000_DRX_CONF, DWDRX_DRX_TUNE1B, 0x0020);
AndyA 0:bddb8cd5e7df 60 writeRegister8 (DW1000_LDE_CTRL, DWLDE_LDE_CFG1, 0xD);
AndyA 0:bddb8cd5e7df 61 writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_CFG2, 0x1607);
AndyA 0:bddb8cd5e7df 62 writeRegister32(DW1000_TX_POWER, 0, 0x0E082848);
AndyA 0:bddb8cd5e7df 63 // writeRegister32(DW1000_TX_POWER, 0, 0x75757575);
AndyA 0:bddb8cd5e7df 64 writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x001E3FE0);
AndyA 0:bddb8cd5e7df 65 writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0xC0);
AndyA 0:bddb8cd5e7df 66 writeRegister8 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLTUNE, 0xBE);
AndyA 0:bddb8cd5e7df 67
AndyA 0:bddb8cd5e7df 68 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
AndyA 0:bddb8cd5e7df 69
AndyA 0:bddb8cd5e7df 70 writeRegister32(DW1000_GPIO_CTRL,DWGPIO_GPIO_MODE,0x00001400);
AndyA 0:bddb8cd5e7df 71 writeRegister16(DW1000_PMSC,DWPMSC_PMSC_LEDC,0x0120);
AndyA 0:bddb8cd5e7df 72
AndyA 0:bddb8cd5e7df 73 // writeRegister8(DW1000_SYS_CFG, 3, 0x20); // enable auto RX reenable
AndyA 0:bddb8cd5e7df 74
AndyA 0:bddb8cd5e7df 75 setRxDelay(0);
AndyA 0:bddb8cd5e7df 76 setTxDelay(0);
AndyA 0:bddb8cd5e7df 77
AndyA 0:bddb8cd5e7df 78 break;
AndyA 0:bddb8cd5e7df 79 case defaultConfig:
AndyA 0:bddb8cd5e7df 80 default:
AndyA 0:bddb8cd5e7df 81 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
AndyA 0:bddb8cd5e7df 82 break;
AndyA 0:bddb8cd5e7df 83 }
AndyA 0:bddb8cd5e7df 84
AndyA 0:bddb8cd5e7df 85 writeRegister8(DW1000_SYS_CFG, 3, 0x20); // enable auto reenabling receiver after error
AndyA 0:bddb8cd5e7df 86
AndyA 0:bddb8cd5e7df 87 irq.rise(this, &DW1000::ISR); // attach interrupt handler to rising edge of interrupt pin from DW1000
AndyA 0:bddb8cd5e7df 88 }
AndyA 0:bddb8cd5e7df 89
AndyA 0:bddb8cd5e7df 90 void DW1000::setRxDelay(uint16_t ticks)
AndyA 0:bddb8cd5e7df 91 {
AndyA 0:bddb8cd5e7df 92 writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_RXANTD, ticks);
AndyA 0:bddb8cd5e7df 93 }
AndyA 0:bddb8cd5e7df 94 void DW1000::setTxDelay(uint16_t ticks)
AndyA 0:bddb8cd5e7df 95 {
AndyA 0:bddb8cd5e7df 96 writeRegister16(DW1000_TX_ANTD, 0, ticks);
AndyA 0:bddb8cd5e7df 97 }
AndyA 0:bddb8cd5e7df 98
AndyA 0:bddb8cd5e7df 99 void DW1000::setCallbacks(void (*callbackRX)(void), void (*callbackTX)(void))
AndyA 0:bddb8cd5e7df 100 {
AndyA 0:bddb8cd5e7df 101 bool RX = false;
AndyA 0:bddb8cd5e7df 102 bool TX = false;
AndyA 0:bddb8cd5e7df 103 if (callbackRX) {
AndyA 0:bddb8cd5e7df 104 DW1000::callbackRX.attach(callbackRX);
AndyA 0:bddb8cd5e7df 105 RX = true;
AndyA 0:bddb8cd5e7df 106 }
AndyA 0:bddb8cd5e7df 107 if (callbackTX) {
AndyA 0:bddb8cd5e7df 108 DW1000::callbackTX.attach(callbackTX);
AndyA 0:bddb8cd5e7df 109 TX = true;
AndyA 0:bddb8cd5e7df 110 }
AndyA 0:bddb8cd5e7df 111 setInterrupt(RX,TX);
AndyA 0:bddb8cd5e7df 112 }
AndyA 0:bddb8cd5e7df 113
AndyA 0:bddb8cd5e7df 114 uint32_t DW1000::getDeviceID()
AndyA 0:bddb8cd5e7df 115 {
AndyA 0:bddb8cd5e7df 116 uint32_t result;
AndyA 0:bddb8cd5e7df 117 readRegister(DW1000_DEV_ID, 0, (uint8_t*)&result, 4);
AndyA 0:bddb8cd5e7df 118 return result;
AndyA 0:bddb8cd5e7df 119 }
AndyA 0:bddb8cd5e7df 120
AndyA 0:bddb8cd5e7df 121 uint64_t DW1000::getEUI()
AndyA 0:bddb8cd5e7df 122 {
AndyA 0:bddb8cd5e7df 123 uint64_t result;
AndyA 0:bddb8cd5e7df 124 readRegister(DW1000_EUI, 0, (uint8_t*)&result, 8);
AndyA 0:bddb8cd5e7df 125 return result;
AndyA 0:bddb8cd5e7df 126 }
AndyA 0:bddb8cd5e7df 127
AndyA 0:bddb8cd5e7df 128 void DW1000::setEUI(uint64_t EUI)
AndyA 0:bddb8cd5e7df 129 {
AndyA 0:bddb8cd5e7df 130 writeRegister(DW1000_EUI, 0, (uint8_t*)&EUI, 8);
AndyA 0:bddb8cd5e7df 131 }
AndyA 0:bddb8cd5e7df 132
AndyA 0:bddb8cd5e7df 133
AndyA 0:bddb8cd5e7df 134 float DW1000::getVoltage()
AndyA 0:bddb8cd5e7df 135 {
AndyA 0:bddb8cd5e7df 136 uint8_t data;
AndyA 0:bddb8cd5e7df 137
AndyA 0:bddb8cd5e7df 138 writeRegister8(DW1000_RF_CONF, 0x11, 0x80);
AndyA 0:bddb8cd5e7df 139 writeRegister8(DW1000_RF_CONF, 0x12, 0x0A);
AndyA 0:bddb8cd5e7df 140 writeRegister8(DW1000_RF_CONF, 0x12, 0x0F);
AndyA 0:bddb8cd5e7df 141 writeRegister8(DW1000_TX_CAL, 0x00, 0x01);
AndyA 0:bddb8cd5e7df 142 writeRegister8(DW1000_TX_CAL, 0x00, 0x00);
AndyA 0:bddb8cd5e7df 143 data = readRegister8(DW1000_TX_CAL, 0x03); // get the 8-Bit reading for Voltage
AndyA 0:bddb8cd5e7df 144 float Voltage = (float)(data - readOTP8(0x08)) *0.00578 + 3.3;
AndyA 0:bddb8cd5e7df 145 return Voltage;
AndyA 0:bddb8cd5e7df 146 }
AndyA 0:bddb8cd5e7df 147
AndyA 0:bddb8cd5e7df 148 float DW1000::getTemperature()
AndyA 0:bddb8cd5e7df 149 {
AndyA 0:bddb8cd5e7df 150 uint8_t data;
AndyA 0:bddb8cd5e7df 151
AndyA 0:bddb8cd5e7df 152 writeRegister8(DW1000_RF_CONF, 0x11, 0x80);
AndyA 0:bddb8cd5e7df 153 writeRegister8(DW1000_RF_CONF, 0x12, 0x0A);
AndyA 0:bddb8cd5e7df 154 writeRegister8(DW1000_RF_CONF, 0x12, 0x0F);
AndyA 0:bddb8cd5e7df 155 writeRegister8(DW1000_TX_CAL, 0x00, 0x01);
AndyA 0:bddb8cd5e7df 156 writeRegister8(DW1000_TX_CAL, 0x00, 0x00);
AndyA 0:bddb8cd5e7df 157 data = readRegister16(DW1000_TX_CAL, 0x04); // get the 8-Bit reading for Temperature
AndyA 0:bddb8cd5e7df 158 float temperature = (float)(data - readOTP8(0x09))*0.9 + 23;
AndyA 0:bddb8cd5e7df 159 return temperature;
AndyA 0:bddb8cd5e7df 160 }
AndyA 0:bddb8cd5e7df 161
AndyA 0:bddb8cd5e7df 162
AndyA 0:bddb8cd5e7df 163 uint64_t DW1000::getStatus()
AndyA 0:bddb8cd5e7df 164 {
AndyA 0:bddb8cd5e7df 165 return readRegister40(DW1000_SYS_STATUS, 0);
AndyA 0:bddb8cd5e7df 166 }
AndyA 0:bddb8cd5e7df 167
AndyA 0:bddb8cd5e7df 168 uint64_t DW1000::getRXTimestamp()
AndyA 0:bddb8cd5e7df 169 {
AndyA 0:bddb8cd5e7df 170 return readRegister40(DW1000_RX_TIME, 0);
AndyA 0:bddb8cd5e7df 171 }
AndyA 0:bddb8cd5e7df 172
AndyA 0:bddb8cd5e7df 173 uint64_t DW1000::getTXTimestamp()
AndyA 0:bddb8cd5e7df 174 {
AndyA 0:bddb8cd5e7df 175 return readRegister40(DW1000_TX_TIME, 0);
AndyA 0:bddb8cd5e7df 176 }
AndyA 0:bddb8cd5e7df 177
AndyA 0:bddb8cd5e7df 178 void DW1000::sendString(char* message)
AndyA 0:bddb8cd5e7df 179 {
AndyA 0:bddb8cd5e7df 180 sendFrame((uint8_t*)message, strlen(message)+1);
AndyA 0:bddb8cd5e7df 181 }
AndyA 0:bddb8cd5e7df 182
AndyA 0:bddb8cd5e7df 183 void DW1000::receiveString(char* message)
AndyA 0:bddb8cd5e7df 184 {
AndyA 0:bddb8cd5e7df 185 readRegister(DW1000_RX_BUFFER, 0, (uint8_t*)message, getFramelength()); // get data from buffer
AndyA 0:bddb8cd5e7df 186 }
AndyA 0:bddb8cd5e7df 187
AndyA 0:bddb8cd5e7df 188 void DW1000::sendFrame(uint8_t* message, uint16_t length)
AndyA 0:bddb8cd5e7df 189 {
AndyA 0:bddb8cd5e7df 190 //if (length >= 1021) length = 1021; // check for maximim length a frame can have with 1024 Byte frames [not used, see constructor]
AndyA 0:bddb8cd5e7df 191 if (length >= 125) length = 125; // check for maximim length a frame can have with 127 Byte frames
AndyA 0:bddb8cd5e7df 192 uint8_t len_7bit = length;
AndyA 0:bddb8cd5e7df 193 writeRegister(DW1000_TX_BUFFER, 0, message, len_7bit); // fill buffer
AndyA 0:bddb8cd5e7df 194
AndyA 0:bddb8cd5e7df 195 /* support for frames over 127 bytes
AndyA 0:bddb8cd5e7df 196 uint8_t backup = readRegister8(DW1000_TX_FCTRL, 1); // put length of frame
AndyA 0:bddb8cd5e7df 197 length += 2; // including 2 CRC Bytes
AndyA 0:bddb8cd5e7df 198 length = ((backup & 0xFC) << 8) | (length & 0x03FF);
AndyA 0:bddb8cd5e7df 199 writeRegister16(DW1000_TX_FCTRL, 0, length);
AndyA 0:bddb8cd5e7df 200 */
AndyA 0:bddb8cd5e7df 201 len_7bit += 2; // including 2 CRC Bytes
AndyA 0:bddb8cd5e7df 202 writeRegister8(DW1000_TX_FCTRL, 0, len_7bit);
AndyA 0:bddb8cd5e7df 203
AndyA 0:bddb8cd5e7df 204 stopTRX(); // stop receiving
AndyA 0:bddb8cd5e7df 205 writeRegister8(DW1000_SYS_CTRL, 0, 0x02 | 0x80); // trigger sending process by setting the TXSTRT bit
AndyA 0:bddb8cd5e7df 206 // startRX(); // enable receiver again
AndyA 0:bddb8cd5e7df 207 }
AndyA 0:bddb8cd5e7df 208
AndyA 0:bddb8cd5e7df 209 void DW1000::setupSyncedFrame(uint8_t* message, uint16_t length) {
AndyA 0:bddb8cd5e7df 210 //if (length >= 1021) length = 1021; // check for maximim length a frame can have with 1024 Byte frames [not used, see constructor]
AndyA 0:bddb8cd5e7df 211 if (length >= 125) length = 125; // check for maximim length a frame can have with 127 Byte frames
AndyA 0:bddb8cd5e7df 212 writeRegister(DW1000_TX_BUFFER, 0, message, length); // fill buffer
AndyA 0:bddb8cd5e7df 213
AndyA 0:bddb8cd5e7df 214 uint8_t backup = readRegister8(DW1000_TX_FCTRL, 1); // put length of frame
AndyA 0:bddb8cd5e7df 215 length += 2; // including 2 CRC Bytes
AndyA 0:bddb8cd5e7df 216 length = ((backup & 0xFC) << 8) | (length & 0x03FF);
AndyA 0:bddb8cd5e7df 217 writeRegister16(DW1000_TX_FCTRL, 0, length);
AndyA 0:bddb8cd5e7df 218 }
AndyA 0:bddb8cd5e7df 219
AndyA 0:bddb8cd5e7df 220 void DW1000::armSyncedFrame() {
AndyA 0:bddb8cd5e7df 221 stopTRX(); // stop receiving
AndyA 0:bddb8cd5e7df 222 writeRegister16(DW1000_EXT_SYNC, DWEXTSYNC_EC_CTRL, 33<<3 | 0x01); // Sync register = TX start with a wait of 33 (recomended, value must fulfill wait % 4 = 1)
AndyA 0:bddb8cd5e7df 223 }
AndyA 0:bddb8cd5e7df 224
AndyA 0:bddb8cd5e7df 225 void DW1000::sendDelayedFrame(uint8_t* message, uint16_t length, uint64_t TxTimestamp)
AndyA 0:bddb8cd5e7df 226 {
AndyA 0:bddb8cd5e7df 227 //if (length >= 1021) length = 1021; // check for maximim length a frame can have with 1024 Byte frames [not used, see constructor]
AndyA 0:bddb8cd5e7df 228 if (length >= 125) length = 125; // check for maximim length a frame can have with 127 Byte frames
AndyA 0:bddb8cd5e7df 229 writeRegister(DW1000_TX_BUFFER, 0, message, length); // fill buffer
AndyA 0:bddb8cd5e7df 230
AndyA 0:bddb8cd5e7df 231 uint8_t backup = readRegister8(DW1000_TX_FCTRL, 1); // put length of frame
AndyA 0:bddb8cd5e7df 232 length += 2; // including 2 CRC Bytes
AndyA 0:bddb8cd5e7df 233 length = ((backup & 0xFC) << 8) | (length & 0x03FF);
AndyA 0:bddb8cd5e7df 234 writeRegister16(DW1000_TX_FCTRL, 0, length);
AndyA 0:bddb8cd5e7df 235
AndyA 0:bddb8cd5e7df 236 writeRegister40(DW1000_DX_TIME, 0, TxTimestamp); //write the timestamp on which to send the message
AndyA 0:bddb8cd5e7df 237
AndyA 0:bddb8cd5e7df 238 stopTRX(); // stop receiving
AndyA 0:bddb8cd5e7df 239 writeRegister8(DW1000_SYS_CTRL, 0, 0x02 | 0x04 | 0x80); // trigger sending process by setting the TXSTRT and TXDLYS bit. Set Wait4resp to automatically enter RX mode after tx.
AndyA 0:bddb8cd5e7df 240 }
AndyA 0:bddb8cd5e7df 241
AndyA 0:bddb8cd5e7df 242 void DW1000::startRX()
AndyA 0:bddb8cd5e7df 243 {
AndyA 0:bddb8cd5e7df 244 writeRegister8(DW1000_SYS_CTRL, 0x01, 0x01); // start listening for preamble by setting the RXENAB bit
AndyA 0:bddb8cd5e7df 245 }
AndyA 0:bddb8cd5e7df 246
AndyA 0:bddb8cd5e7df 247 void DW1000::stopTRX()
AndyA 0:bddb8cd5e7df 248 {
AndyA 0:bddb8cd5e7df 249 writeRegister8(DW1000_SYS_CTRL, 0, 0x40); // disable tranceiver go back to idle mode
AndyA 0:bddb8cd5e7df 250 }
AndyA 0:bddb8cd5e7df 251
AndyA 0:bddb8cd5e7df 252 // PRIVATE Methods ------------------------------------------------------------------------------------
AndyA 0:bddb8cd5e7df 253 void DW1000::loadLDE() // initialise LDE algorithm LDELOAD User Manual p22
AndyA 0:bddb8cd5e7df 254 {
AndyA 0:bddb8cd5e7df 255 spi.frequency(SPIRATE_OSC); // with a 1MHz clock rate (worked up to 49MHz in our Test)
AndyA 0:bddb8cd5e7df 256
AndyA 0:bddb8cd5e7df 257 writeRegister16(DW1000_PMSC, 0, 0x0301); // set clock to XTAL so OTP is reliable
AndyA 0:bddb8cd5e7df 258 writeRegister16(DW1000_OTP_IF, DWOTP_OTP_CTRL, 0x8000); // set LDELOAD bit in OTP
AndyA 0:bddb8cd5e7df 259 wait_us(150);
AndyA 0:bddb8cd5e7df 260 writeRegister16(DW1000_PMSC, 0, 0x0200); // recover to PLL clock
AndyA 0:bddb8cd5e7df 261
AndyA 0:bddb8cd5e7df 262 wait_ms(1);
AndyA 0:bddb8cd5e7df 263
AndyA 0:bddb8cd5e7df 264 spi.frequency(SPIRATE_PLL); // with a 1MHz clock rate (worked up to 49MHz in our Test)
AndyA 0:bddb8cd5e7df 265
AndyA 0:bddb8cd5e7df 266 }
AndyA 0:bddb8cd5e7df 267
AndyA 0:bddb8cd5e7df 268 void DW1000::loadLDOTUNE()
AndyA 0:bddb8cd5e7df 269 {
AndyA 0:bddb8cd5e7df 270 uint64_t LDOTuningValue = readOTP40(0x0004);
AndyA 0:bddb8cd5e7df 271 if (LDOTuningValue != 0)
AndyA 0:bddb8cd5e7df 272 writeRegister40(DW1000_RF_CONF,DWRFCONF_RF_LDOTUNE,LDOTuningValue);
AndyA 0:bddb8cd5e7df 273
AndyA 0:bddb8cd5e7df 274 }
AndyA 0:bddb8cd5e7df 275
AndyA 0:bddb8cd5e7df 276 void DW1000::resetRX()
AndyA 0:bddb8cd5e7df 277 {
AndyA 0:bddb8cd5e7df 278 writeRegister8(DW1000_PMSC, 3, 0xE0); // set RX reset
AndyA 0:bddb8cd5e7df 279 writeRegister8(DW1000_PMSC, 3, 0xF0); // clear RX reset
AndyA 0:bddb8cd5e7df 280 }
AndyA 0:bddb8cd5e7df 281
AndyA 0:bddb8cd5e7df 282 void DW1000::resetAll()
AndyA 0:bddb8cd5e7df 283 {
AndyA 0:bddb8cd5e7df 284 spi.frequency(SPIRATE_OSC); // with a 1MHz clock rate (worked up to 49MHz in our Test)
AndyA 0:bddb8cd5e7df 285
AndyA 0:bddb8cd5e7df 286 writeRegister8(DW1000_PMSC, 0, 0x01); // set clock to XTAL
AndyA 0:bddb8cd5e7df 287 writeRegister8(DW1000_PMSC, 3, 0x00); // set All reset
AndyA 0:bddb8cd5e7df 288 wait_us(10); // wait for PLL to lock
AndyA 0:bddb8cd5e7df 289 writeRegister8(DW1000_PMSC, 3, 0xF0); // clear All reset
AndyA 0:bddb8cd5e7df 290
AndyA 0:bddb8cd5e7df 291 wait_ms(1);
AndyA 0:bddb8cd5e7df 292
AndyA 0:bddb8cd5e7df 293 spi.frequency(SPIRATE_PLL); // with a 1MHz clock rate (worked up to 49MHz in our Test)
AndyA 0:bddb8cd5e7df 294 }
AndyA 0:bddb8cd5e7df 295
AndyA 0:bddb8cd5e7df 296 /// After writes have been completed reset the device.
AndyA 0:bddb8cd5e7df 297 bool DW1000::writeOTP(uint16_t address,uint32_t data)
AndyA 0:bddb8cd5e7df 298 {
AndyA 0:bddb8cd5e7df 299 spi.frequency(SPIRATE_OSC); // with a 1MHz clock rate (worked up to 49MHz in our Test)
AndyA 0:bddb8cd5e7df 300
AndyA 0:bddb8cd5e7df 301 writeRegister8(DW1000_PMSC, 0, 0x01); // set clock to XTAL
AndyA 0:bddb8cd5e7df 302 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x03); //
AndyA 0:bddb8cd5e7df 303 writeRegister16(DW1000_OTP_IF,DWOTP_OTP_WDAT,0x9220); //
AndyA 0:bddb8cd5e7df 304 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x08); //
AndyA 0:bddb8cd5e7df 305 wait_ms(1);
AndyA 0:bddb8cd5e7df 306 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x02); //
AndyA 0:bddb8cd5e7df 307 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x88); //
AndyA 0:bddb8cd5e7df 308 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x80); //
AndyA 0:bddb8cd5e7df 309 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00); //
AndyA 0:bddb8cd5e7df 310
AndyA 0:bddb8cd5e7df 311 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x05); //
AndyA 0:bddb8cd5e7df 312 writeRegister16(DW1000_OTP_IF,DWOTP_OTP_WDAT,0x000E); //
AndyA 0:bddb8cd5e7df 313 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x08); //
AndyA 0:bddb8cd5e7df 314 wait_ms(1);
AndyA 0:bddb8cd5e7df 315 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x04); //
AndyA 0:bddb8cd5e7df 316 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x88); //
AndyA 0:bddb8cd5e7df 317 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x80); //
AndyA 0:bddb8cd5e7df 318 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00); //
AndyA 0:bddb8cd5e7df 319
AndyA 0:bddb8cd5e7df 320 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x01); //
AndyA 0:bddb8cd5e7df 321 writeRegister16(DW1000_OTP_IF,DWOTP_OTP_WDAT,0x1024); //
AndyA 0:bddb8cd5e7df 322 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x08); //
AndyA 0:bddb8cd5e7df 323 wait_ms(1);
AndyA 0:bddb8cd5e7df 324 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x00); //
AndyA 0:bddb8cd5e7df 325
AndyA 0:bddb8cd5e7df 326 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00); //
AndyA 0:bddb8cd5e7df 327 writeRegister32(DW1000_OTP_IF,DWOTP_OTP_WDAT,data); //
AndyA 0:bddb8cd5e7df 328 writeRegister16(DW1000_OTP_IF,DWOTP_OTP_ADDR,address); //
AndyA 0:bddb8cd5e7df 329 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x40); //
AndyA 0:bddb8cd5e7df 330 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00); //
AndyA 0:bddb8cd5e7df 331 wait_ms(1);
AndyA 0:bddb8cd5e7df 332
AndyA 0:bddb8cd5e7df 333 for (int i=0; i<10; i++) {
AndyA 0:bddb8cd5e7df 334 if (readOTP32(address) == data)
AndyA 0:bddb8cd5e7df 335 return true;
AndyA 0:bddb8cd5e7df 336 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x40); // retry
AndyA 0:bddb8cd5e7df 337 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00);
AndyA 0:bddb8cd5e7df 338 wait_ms(1);
AndyA 0:bddb8cd5e7df 339 }
AndyA 0:bddb8cd5e7df 340 return false;
AndyA 0:bddb8cd5e7df 341 }
AndyA 0:bddb8cd5e7df 342
AndyA 0:bddb8cd5e7df 343 uint32_t DW1000::readOTP (uint16_t word_address, uint8_t size) {
AndyA 0:bddb8cd5e7df 344 if (size == 1)
AndyA 0:bddb8cd5e7df 345 return readOTP8(word_address);
AndyA 0:bddb8cd5e7df 346 else if (size == 2)
AndyA 0:bddb8cd5e7df 347 return readOTP16(word_address);
AndyA 0:bddb8cd5e7df 348 else
AndyA 0:bddb8cd5e7df 349 return readOTP32(word_address);
AndyA 0:bddb8cd5e7df 350 }
AndyA 0:bddb8cd5e7df 351
AndyA 0:bddb8cd5e7df 352
AndyA 0:bddb8cd5e7df 353 uint32_t DW1000::readOTP32(uint16_t address)
AndyA 0:bddb8cd5e7df 354 {
AndyA 0:bddb8cd5e7df 355 writeRegister16(DW1000_OTP_IF,DWOTP_OTP_ADDR,address); // write address
AndyA 0:bddb8cd5e7df 356 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x03); // read address load
AndyA 0:bddb8cd5e7df 357 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x01); // read
AndyA 0:bddb8cd5e7df 358 uint32_t data = readRegister32(DW1000_OTP_IF,DWOTP_OTP_RDAT);
AndyA 0:bddb8cd5e7df 359 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00); // OTP idle
AndyA 0:bddb8cd5e7df 360 return data;
AndyA 0:bddb8cd5e7df 361 }
AndyA 0:bddb8cd5e7df 362
AndyA 0:bddb8cd5e7df 363 uint8_t DW1000::readOTP8(uint16_t address)
AndyA 0:bddb8cd5e7df 364 {
AndyA 0:bddb8cd5e7df 365 writeRegister16(DW1000_OTP_IF,DWOTP_OTP_ADDR,address); // write address
AndyA 0:bddb8cd5e7df 366 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x03); // read address load
AndyA 0:bddb8cd5e7df 367 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x01); // read
AndyA 0:bddb8cd5e7df 368 uint8_t data = readRegister8(DW1000_OTP_IF,DWOTP_OTP_RDAT);
AndyA 0:bddb8cd5e7df 369 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00); // OTP idle
AndyA 0:bddb8cd5e7df 370 return data;
AndyA 0:bddb8cd5e7df 371 }
AndyA 0:bddb8cd5e7df 372
AndyA 0:bddb8cd5e7df 373 void DW1000::setInterrupt(bool RX, bool TX)
AndyA 0:bddb8cd5e7df 374 {
AndyA 0:bddb8cd5e7df 375 writeRegister16(DW1000_SYS_MASK, 0, RX*0x4000 | TX*0x0080); // RX good frame 0x4000, TX done 0x0080
AndyA 0:bddb8cd5e7df 376 }
AndyA 0:bddb8cd5e7df 377
AndyA 0:bddb8cd5e7df 378 void DW1000::ISR()
AndyA 0:bddb8cd5e7df 379 {
AndyA 0:bddb8cd5e7df 380 uint64_t status = getStatus();
AndyA 0:bddb8cd5e7df 381 if (status & 0x4000) { // a frame was received
AndyA 0:bddb8cd5e7df 382 callbackRX.call();
AndyA 0:bddb8cd5e7df 383 writeRegister16(DW1000_SYS_STATUS, 0, 0x6F00); // clearing of receiving status bits
AndyA 0:bddb8cd5e7df 384 }
AndyA 0:bddb8cd5e7df 385 if (status & 0x80) { // sending complete
AndyA 0:bddb8cd5e7df 386 callbackTX.call();
AndyA 0:bddb8cd5e7df 387 writeRegister8(DW1000_SYS_STATUS, 0, 0xF8); // clearing of sending status bits
AndyA 0:bddb8cd5e7df 388 }
AndyA 0:bddb8cd5e7df 389 }
AndyA 0:bddb8cd5e7df 390
AndyA 0:bddb8cd5e7df 391 uint16_t DW1000::getFramelength()
AndyA 0:bddb8cd5e7df 392 {
AndyA 0:bddb8cd5e7df 393 uint16_t framelength = readRegister16(DW1000_RX_FINFO, 0); // get framelength
AndyA 0:bddb8cd5e7df 394 framelength = (framelength & 0x03FF) - 2; // take only the right bits and subtract the 2 CRC Bytes
AndyA 0:bddb8cd5e7df 395 return framelength;
AndyA 0:bddb8cd5e7df 396 }
AndyA 0:bddb8cd5e7df 397
AndyA 0:bddb8cd5e7df 398 // SPI Interface ------------------------------------------------------------------------------------
AndyA 0:bddb8cd5e7df 399 uint8_t DW1000::readRegister8(uint8_t reg, uint16_t subaddress)
AndyA 0:bddb8cd5e7df 400 {
AndyA 0:bddb8cd5e7df 401 uint8_t result;
AndyA 0:bddb8cd5e7df 402 readRegister(reg, subaddress, &result, 1);
AndyA 0:bddb8cd5e7df 403 return result;
AndyA 0:bddb8cd5e7df 404 }
AndyA 0:bddb8cd5e7df 405
AndyA 0:bddb8cd5e7df 406 uint16_t DW1000::readRegister16(uint8_t reg, uint16_t subaddress)
AndyA 0:bddb8cd5e7df 407 {
AndyA 0:bddb8cd5e7df 408 uint16_t result;
AndyA 0:bddb8cd5e7df 409 readRegister(reg, subaddress, (uint8_t*)&result, 2);
AndyA 0:bddb8cd5e7df 410 return result;
AndyA 0:bddb8cd5e7df 411 }
AndyA 0:bddb8cd5e7df 412
AndyA 0:bddb8cd5e7df 413 uint32_t DW1000::readRegister32(uint8_t reg, uint16_t subaddress)
AndyA 0:bddb8cd5e7df 414 {
AndyA 0:bddb8cd5e7df 415 uint32_t result;
AndyA 0:bddb8cd5e7df 416 readRegister(reg, subaddress, (uint8_t*)&result, 4);
AndyA 0:bddb8cd5e7df 417 return result;
AndyA 0:bddb8cd5e7df 418 }
AndyA 0:bddb8cd5e7df 419
AndyA 0:bddb8cd5e7df 420
AndyA 0:bddb8cd5e7df 421 uint64_t DW1000::readRegister40(uint8_t reg, uint16_t subaddress)
AndyA 0:bddb8cd5e7df 422 {
AndyA 0:bddb8cd5e7df 423 uint64_t result = 0;
AndyA 0:bddb8cd5e7df 424 readRegister(reg, subaddress, (uint8_t*)&result, 5);
AndyA 0:bddb8cd5e7df 425 return result;
AndyA 0:bddb8cd5e7df 426 }
AndyA 0:bddb8cd5e7df 427 uint64_t DW1000::readRegister64(uint8_t reg, uint16_t subaddress)
AndyA 0:bddb8cd5e7df 428 {
AndyA 0:bddb8cd5e7df 429 uint64_t result;
AndyA 0:bddb8cd5e7df 430 readRegister(reg, subaddress, (uint8_t*)&result, 8);
AndyA 0:bddb8cd5e7df 431 return result;
AndyA 0:bddb8cd5e7df 432 }
AndyA 0:bddb8cd5e7df 433
AndyA 0:bddb8cd5e7df 434 void DW1000::writeRegister8(uint8_t reg, uint16_t subaddress, uint8_t buffer)
AndyA 0:bddb8cd5e7df 435 {
AndyA 0:bddb8cd5e7df 436 writeRegister(reg, subaddress, &buffer, 1);
AndyA 0:bddb8cd5e7df 437 }
AndyA 0:bddb8cd5e7df 438
AndyA 0:bddb8cd5e7df 439 void DW1000::writeRegister16(uint8_t reg, uint16_t subaddress, uint16_t buffer)
AndyA 0:bddb8cd5e7df 440 {
AndyA 0:bddb8cd5e7df 441 writeRegister(reg, subaddress, (uint8_t*)&buffer, 2);
AndyA 0:bddb8cd5e7df 442 }
AndyA 0:bddb8cd5e7df 443
AndyA 0:bddb8cd5e7df 444 void DW1000::writeRegister32(uint8_t reg, uint16_t subaddress, uint32_t buffer)
AndyA 0:bddb8cd5e7df 445 {
AndyA 0:bddb8cd5e7df 446 writeRegister(reg, subaddress, (uint8_t*)&buffer, 4);
AndyA 0:bddb8cd5e7df 447 }
AndyA 0:bddb8cd5e7df 448
AndyA 0:bddb8cd5e7df 449 void DW1000::writeRegister40(uint8_t reg, uint16_t subaddress, uint64_t buffer)
AndyA 0:bddb8cd5e7df 450 {
AndyA 0:bddb8cd5e7df 451 writeRegister(reg, subaddress, (uint8_t*)&buffer, 5);
AndyA 0:bddb8cd5e7df 452 }
AndyA 0:bddb8cd5e7df 453
AndyA 0:bddb8cd5e7df 454 void DW1000::readRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length)
AndyA 0:bddb8cd5e7df 455 {
AndyA 0:bddb8cd5e7df 456 setupTransaction(reg, subaddress, false);
AndyA 0:bddb8cd5e7df 457 for(int i=0; i<length; i++) // get data
AndyA 0:bddb8cd5e7df 458 buffer[i] = spi.write(0x00);
AndyA 0:bddb8cd5e7df 459 deselect();
AndyA 0:bddb8cd5e7df 460 }
AndyA 0:bddb8cd5e7df 461
AndyA 0:bddb8cd5e7df 462 void DW1000::writeRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length)
AndyA 0:bddb8cd5e7df 463 {
AndyA 0:bddb8cd5e7df 464 setupTransaction(reg, subaddress, true);
AndyA 0:bddb8cd5e7df 465 for(int i=0; i<length; i++) // put data
AndyA 0:bddb8cd5e7df 466 spi.write(buffer[i]);
AndyA 0:bddb8cd5e7df 467 deselect();
AndyA 0:bddb8cd5e7df 468 }
AndyA 0:bddb8cd5e7df 469
AndyA 0:bddb8cd5e7df 470 void DW1000::setupTransaction(uint8_t reg, uint16_t subaddress, bool write)
AndyA 0:bddb8cd5e7df 471 {
AndyA 0:bddb8cd5e7df 472 reg |= (write * DW1000_WRITE_FLAG); // set read/write flag
AndyA 0:bddb8cd5e7df 473 select();
AndyA 0:bddb8cd5e7df 474 if (subaddress > 0) { // there's a subadress, we need to set flag and send second header byte
AndyA 0:bddb8cd5e7df 475 spi.write(reg | DW1000_SUBADDRESS_FLAG);
AndyA 0:bddb8cd5e7df 476 if (subaddress > 0x7F) { // sub address too long, we need to set flag and send third header byte
AndyA 0:bddb8cd5e7df 477 spi.write((uint8_t)(subaddress & 0x7F) | DW1000_2_SUBADDRESS_FLAG); // and
AndyA 0:bddb8cd5e7df 478 spi.write((uint8_t)(subaddress >> 7));
AndyA 0:bddb8cd5e7df 479 } else {
AndyA 0:bddb8cd5e7df 480 spi.write((uint8_t)subaddress);
AndyA 0:bddb8cd5e7df 481 }
AndyA 0:bddb8cd5e7df 482 } else {
AndyA 0:bddb8cd5e7df 483 spi.write(reg); // say which register address we want to access
AndyA 0:bddb8cd5e7df 484 }
AndyA 0:bddb8cd5e7df 485 }
AndyA 0:bddb8cd5e7df 486
AndyA 0:bddb8cd5e7df 487 void DW1000::select() // always called to start an SPI transmission
AndyA 0:bddb8cd5e7df 488 {
AndyA 0:bddb8cd5e7df 489 irq.disable_irq(); // disable interrupts from DW1000 during SPI becaus this leads to crashes! TODO: if you have other interrupt handlers attached on the micro controller, they could also interfere.
AndyA 0:bddb8cd5e7df 490 cs = 0; // set Cable Select pin low to start transmission
AndyA 0:bddb8cd5e7df 491 }
AndyA 0:bddb8cd5e7df 492
AndyA 0:bddb8cd5e7df 493 void DW1000::deselect() // always called to end an SPI transmission
AndyA 0:bddb8cd5e7df 494 {
AndyA 0:bddb8cd5e7df 495 cs = 1; // set Cable Select pin high to stop transmission
AndyA 0:bddb8cd5e7df 496 irq.enable_irq(); // reenable the interrupt handler
AndyA 0:bddb8cd5e7df 497 }