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

Dependencies:   BurstSPI

Committer:
AndyA
Date:
Wed Apr 13 09:07:14 2016 +0000
Revision:
7:b13881dbb09d
Parent:
6:2c77afdf7367
Child:
8:0b408e77b701
Switched to Burst SPI and increased clock speed.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AndyA 0:bddb8cd5e7df 1 #include "DW1000.h"
AndyA 0:bddb8cd5e7df 2
AndyA 7:b13881dbb09d 3 #define SPIRATE_PLL (10*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
AndyA 4:5f1025df5530 19 systemConfig.setChannel(5);
AndyA 4:5f1025df5530 20 systemConfig.setPRF(DW1000Setup::prf16MHz);
AndyA 4:5f1025df5530 21 systemConfig.setDataRate(DW1000Setup::kbps110);
AndyA 4:5f1025df5530 22 systemConfig.setSfd(DW1000Setup::standard);
AndyA 4:5f1025df5530 23 systemConfig.setPreambleLength(DW1000Setup::pre1024);
AndyA 4:5f1025df5530 24 systemConfig.setPreambleCode(3);
AndyA 4:5f1025df5530 25 systemConfig.setSmartPower(false);
AndyA 0:bddb8cd5e7df 26
AndyA 3:1459d2aa6b97 27 setupRadio();
AndyA 0:bddb8cd5e7df 28
AndyA 3:1459d2aa6b97 29 setTxPower(230); // power = 23dB gain
AndyA 0:bddb8cd5e7df 30
AndyA 3:1459d2aa6b97 31 setRxDelay(1<<14); // set delays to 2^14 (1/4 of max)
AndyA 3:1459d2aa6b97 32 setTxDelay(1<<14);
AndyA 0:bddb8cd5e7df 33 break;
AndyA 0:bddb8cd5e7df 34
AndyA 0:bddb8cd5e7df 35 case tunedDefault: // User Manual "2.5.5 Default Configurations that should be modified" p. 22
AndyA 3:1459d2aa6b97 36 default:
AndyA 3:1459d2aa6b97 37
AndyA 4:5f1025df5530 38 systemConfig.setChannel(5);
AndyA 4:5f1025df5530 39 systemConfig.setPRF(DW1000Setup::prf16MHz);
AndyA 4:5f1025df5530 40 systemConfig.setDataRate(DW1000Setup::kbps6800);
AndyA 4:5f1025df5530 41 systemConfig.setSfd(DW1000Setup::standard);
AndyA 4:5f1025df5530 42 systemConfig.setPreambleLength(DW1000Setup::pre128);
AndyA 4:5f1025df5530 43 systemConfig.setPreambleCode(3);
AndyA 4:5f1025df5530 44 systemConfig.setSmartPower(false);
AndyA 3:1459d2aa6b97 45
AndyA 3:1459d2aa6b97 46 setupRadio();
AndyA 0:bddb8cd5e7df 47
AndyA 3:1459d2aa6b97 48 setTxPower(230,260,290); // power = 23dB gain
AndyA 3:1459d2aa6b97 49 setRxDelay(0);
AndyA 3:1459d2aa6b97 50 setTxDelay(0);
AndyA 0:bddb8cd5e7df 51
AndyA 3:1459d2aa6b97 52 break;
AndyA 3:1459d2aa6b97 53 case minPacketSize:
AndyA 4:5f1025df5530 54 systemConfig.setChannel(5);
AndyA 4:5f1025df5530 55 systemConfig.setPRF(DW1000Setup::prf64MHz);
AndyA 4:5f1025df5530 56 systemConfig.setDataRate(DW1000Setup::kbps6800);
AndyA 4:5f1025df5530 57 systemConfig.setSfd(DW1000Setup::standard);
AndyA 4:5f1025df5530 58 systemConfig.setPreambleLength(DW1000Setup::pre64);
AndyA 4:5f1025df5530 59 systemConfig.setPreambleCode(10);
AndyA 4:5f1025df5530 60 systemConfig.setSmartPower(true);
AndyA 0:bddb8cd5e7df 61
AndyA 3:1459d2aa6b97 62 setupRadio();
AndyA 3:1459d2aa6b97 63 uint16_t txPower = 25*10; // 25dB gain.
AndyA 4:5f1025df5530 64 // 2 packets per ms max. So can increase TX power of 250us packets by 10log(4/2) dB and 125us packets by 10log(8/2) dB
AndyA 4:5f1025df5530 65 setTxPower(txPower,txPower,txPower+30,txPower+60); // power = 23dB gain
AndyA 0:bddb8cd5e7df 66
AndyA 0:bddb8cd5e7df 67 setRxDelay(0);
AndyA 0:bddb8cd5e7df 68 setTxDelay(0);
AndyA 0:bddb8cd5e7df 69
AndyA 0:bddb8cd5e7df 70 break;
AndyA 0:bddb8cd5e7df 71 }
AndyA 0:bddb8cd5e7df 72
AndyA 0:bddb8cd5e7df 73
AndyA 0:bddb8cd5e7df 74 irq.rise(this, &DW1000::ISR); // attach interrupt handler to rising edge of interrupt pin from DW1000
AndyA 0:bddb8cd5e7df 75 }
AndyA 0:bddb8cd5e7df 76
AndyA 4:5f1025df5530 77 void DW1000::getSetup(char *buffer, int len)
AndyA 4:5f1025df5530 78 {
AndyA 4:5f1025df5530 79
AndyA 4:5f1025df5530 80 char dataRateString[10];
AndyA 4:5f1025df5530 81 if (systemConfig.getDataRate() == DW1000Setup::kbps6800)
AndyA 4:5f1025df5530 82 strcpy(dataRateString,"6.8 Mbps");
AndyA 4:5f1025df5530 83 else if (systemConfig.getDataRate() == DW1000Setup::kbps850)
AndyA 4:5f1025df5530 84 strcpy(dataRateString,"850 kbps");
AndyA 4:5f1025df5530 85 else
AndyA 4:5f1025df5530 86 strcpy(dataRateString,"110 kbps");
AndyA 4:5f1025df5530 87
AndyA 4:5f1025df5530 88 char preambleString[8];
AndyA 4:5f1025df5530 89 switch (systemConfig.getPreambleLength()) {
AndyA 0:bddb8cd5e7df 90 default:
AndyA 4:5f1025df5530 91 strcpy(preambleString,"error");
AndyA 4:5f1025df5530 92 break;
AndyA 4:5f1025df5530 93 case DW1000Setup::pre64:
AndyA 4:5f1025df5530 94 strcpy(preambleString,"64");
AndyA 4:5f1025df5530 95 break;
AndyA 4:5f1025df5530 96 case DW1000Setup::pre128:
AndyA 4:5f1025df5530 97 strcpy(preambleString,"128");
AndyA 4:5f1025df5530 98 break;
AndyA 4:5f1025df5530 99 case DW1000Setup::pre256:
AndyA 4:5f1025df5530 100 strcpy(preambleString,"256");
AndyA 4:5f1025df5530 101 break;
AndyA 4:5f1025df5530 102 case DW1000Setup::pre512:
AndyA 4:5f1025df5530 103 strcpy(preambleString,"512");
AndyA 4:5f1025df5530 104 break;
AndyA 4:5f1025df5530 105 case DW1000Setup::pre1024:
AndyA 4:5f1025df5530 106 strcpy(preambleString,"1024");
AndyA 4:5f1025df5530 107 break;
AndyA 4:5f1025df5530 108 case DW1000Setup::pre1536:
AndyA 4:5f1025df5530 109 strcpy(preambleString,"1536");
AndyA 4:5f1025df5530 110 break;
AndyA 4:5f1025df5530 111 case DW1000Setup::pre2048:
AndyA 4:5f1025df5530 112 strcpy(preambleString,"2048");
AndyA 4:5f1025df5530 113 break;
AndyA 4:5f1025df5530 114 case DW1000Setup::pre4096:
AndyA 4:5f1025df5530 115 strcpy(preambleString,"4096");
AndyA 4:5f1025df5530 116 break;
AndyA 4:5f1025df5530 117 }
AndyA 4:5f1025df5530 118
AndyA 4:5f1025df5530 119 snprintf(buffer,len,"Channel:\t%u\r\nPRF:\t%s\r\nData Rate:\t%s\r\nPreamble length:\t%s\r\nPreamble code:\t%u\r\nSmart power:\t%s\r\nSFD:\t%s\r\n",
AndyA 4:5f1025df5530 120 systemConfig.getChannel(),
AndyA 4:5f1025df5530 121 (systemConfig.getPRF() == DW1000Setup::prf16MHz)?"16 MHz":"64 MHz",
AndyA 4:5f1025df5530 122 dataRateString,
AndyA 4:5f1025df5530 123 preambleString,
AndyA 4:5f1025df5530 124 systemConfig.getPreambleCode(),
AndyA 4:5f1025df5530 125 systemConfig.getSmartPower()?"Enabled":"Disabled",
AndyA 4:5f1025df5530 126 (systemConfig.getSfd() == DW1000Setup::standard)?"Standard":"Non-standard");
AndyA 4:5f1025df5530 127
AndyA 4:5f1025df5530 128 }
AndyA 4:5f1025df5530 129
AndyA 4:5f1025df5530 130
AndyA 3:1459d2aa6b97 131 void DW1000::setupRadio()
AndyA 3:1459d2aa6b97 132 {
AndyA 3:1459d2aa6b97 133 setupAGC();
AndyA 3:1459d2aa6b97 134 setupRxConfig();
AndyA 3:1459d2aa6b97 135 setupLDE();
AndyA 3:1459d2aa6b97 136 setupChannel();
AndyA 3:1459d2aa6b97 137 setupAnalogRF();
AndyA 3:1459d2aa6b97 138 setupFreqSynth();
AndyA 3:1459d2aa6b97 139 setupTxCalibration();
AndyA 3:1459d2aa6b97 140 setupTxFrameCtrl();
AndyA 3:1459d2aa6b97 141 setupSystemConfig();
AndyA 3:1459d2aa6b97 142
AndyA 3:1459d2aa6b97 143 }
AndyA 3:1459d2aa6b97 144
AndyA 3:1459d2aa6b97 145 void DW1000::setupAGC()
AndyA 3:1459d2aa6b97 146 {
AndyA 3:1459d2aa6b97 147
AndyA 3:1459d2aa6b97 148 writeRegister16(DW1000_AGC_CTRL, DWAGCCTRL_AGC_CTRL1, 0x0001);
AndyA 4:5f1025df5530 149 if (systemConfig.getPRF() == DW1000Setup::prf16MHz)
AndyA 3:1459d2aa6b97 150 writeRegister16(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE1, 0x8870);
AndyA 3:1459d2aa6b97 151 else
AndyA 3:1459d2aa6b97 152 writeRegister16(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE1, 0x889B);
AndyA 3:1459d2aa6b97 153
AndyA 3:1459d2aa6b97 154 writeRegister32(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE2, 0x2502A907);
AndyA 3:1459d2aa6b97 155 writeRegister16(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE3, 0x0035);
AndyA 3:1459d2aa6b97 156 }
AndyA 3:1459d2aa6b97 157
AndyA 3:1459d2aa6b97 158 void DW1000::setupSystemConfig()
AndyA 3:1459d2aa6b97 159 {
AndyA 3:1459d2aa6b97 160 uint32_t valueToUse = 0;
AndyA 3:1459d2aa6b97 161 valueToUse |= 1<<9; // IRQ output is active high (default)
AndyA 3:1459d2aa6b97 162 valueToUse |= 1<<12; // Disable double buffered Rx (default)
AndyA 3:1459d2aa6b97 163
AndyA 3:1459d2aa6b97 164 // valueToUse |= 3<<16; // enable long (>125bytes data) packets
AndyA 3:1459d2aa6b97 165
AndyA 4:5f1025df5530 166 if (!systemConfig.getSmartPower())
AndyA 3:1459d2aa6b97 167 valueToUse |= 1<<18; // disable smart power
AndyA 3:1459d2aa6b97 168
AndyA 4:5f1025df5530 169 if (systemConfig.getDataRate() == DW1000Setup::kbps110)
AndyA 3:1459d2aa6b97 170 valueToUse |= 1<<22;
AndyA 3:1459d2aa6b97 171
AndyA 4:5f1025df5530 172 valueToUse |= 1<<29;// enable auto reenabling receiver after error
AndyA 4:5f1025df5530 173
AndyA 4:5f1025df5530 174 writeRegister32(DW1000_SYS_CFG, 0, valueToUse);
AndyA 3:1459d2aa6b97 175 }
AndyA 3:1459d2aa6b97 176
AndyA 3:1459d2aa6b97 177 void DW1000::setupRxConfig()
AndyA 3:1459d2aa6b97 178 {
AndyA 3:1459d2aa6b97 179
AndyA 4:5f1025df5530 180 switch (systemConfig.getDataRate()) {
AndyA 4:5f1025df5530 181 case DW1000Setup::kbps110:
AndyA 4:5f1025df5530 182 if (systemConfig.getSfd() == DW1000Setup::standard)
AndyA 3:1459d2aa6b97 183 writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x000A);
AndyA 3:1459d2aa6b97 184 else
AndyA 3:1459d2aa6b97 185 writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0016);
AndyA 3:1459d2aa6b97 186 break;
AndyA 4:5f1025df5530 187 case DW1000Setup::kbps850:
AndyA 4:5f1025df5530 188 if (systemConfig.getSfd() == DW1000Setup::standard)
AndyA 3:1459d2aa6b97 189 writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0001);
AndyA 3:1459d2aa6b97 190 else
AndyA 3:1459d2aa6b97 191 writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0006);
AndyA 3:1459d2aa6b97 192 break;
AndyA 4:5f1025df5530 193 case DW1000Setup::kbps6800:
AndyA 3:1459d2aa6b97 194 default:
AndyA 4:5f1025df5530 195 if (systemConfig.getSfd() == DW1000Setup::standard)
AndyA 3:1459d2aa6b97 196 writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0001);
AndyA 3:1459d2aa6b97 197 else
AndyA 3:1459d2aa6b97 198 writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0002);
AndyA 3:1459d2aa6b97 199 break;
AndyA 3:1459d2aa6b97 200 }
AndyA 3:1459d2aa6b97 201
AndyA 4:5f1025df5530 202 if (systemConfig.getPRF() == DW1000Setup::prf16MHz)
AndyA 3:1459d2aa6b97 203 writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1A, 0x0087); //DRX_TUNE1a for 16MHz PRF
AndyA 3:1459d2aa6b97 204 else
AndyA 3:1459d2aa6b97 205 writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1A, 0x008D);
AndyA 3:1459d2aa6b97 206
AndyA 4:5f1025df5530 207 switch (systemConfig.getPreambleLength()) {
AndyA 4:5f1025df5530 208 case DW1000Setup::pre1536:
AndyA 4:5f1025df5530 209 case DW1000Setup::pre2048:
AndyA 4:5f1025df5530 210 case DW1000Setup::pre4096:
AndyA 3:1459d2aa6b97 211 writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1B, 0x0064); //DRX_TUNE1b for 110kbps & > 1024 symbols
AndyA 3:1459d2aa6b97 212 break;
AndyA 3:1459d2aa6b97 213 default: // 128 to 1024
AndyA 3:1459d2aa6b97 214 writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1B, 0x0020); //DRX_TUNE1b for 128- 1024 symbols
AndyA 3:1459d2aa6b97 215 break;
AndyA 4:5f1025df5530 216 case DW1000Setup::pre64:
AndyA 3:1459d2aa6b97 217 writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1B, 0x0010); //DRX_TUNE1b for 64 symbols
AndyA 3:1459d2aa6b97 218 break;
AndyA 3:1459d2aa6b97 219 }
AndyA 3:1459d2aa6b97 220
AndyA 4:5f1025df5530 221 switch (systemConfig.getPreambleLength()) {
AndyA 4:5f1025df5530 222 case DW1000Setup::pre64:
AndyA 4:5f1025df5530 223 case DW1000Setup::pre128: // PAC = 8
AndyA 4:5f1025df5530 224 if (systemConfig.getPRF() == DW1000Setup::prf16MHz)
AndyA 3:1459d2aa6b97 225 writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x311A002D); //DRX_TUNE2 PAC 8 for 64MHz PRF
AndyA 3:1459d2aa6b97 226 else
AndyA 3:1459d2aa6b97 227 writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x313B006B); //DRX_TUNE2 PAC 8 for 64MHz PRF
AndyA 3:1459d2aa6b97 228 break;
AndyA 4:5f1025df5530 229 case DW1000Setup::pre256:
AndyA 4:5f1025df5530 230 case DW1000Setup::pre512: // PAC = 16
AndyA 4:5f1025df5530 231 if (systemConfig.getPRF() == DW1000Setup::prf16MHz)
AndyA 3:1459d2aa6b97 232 writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x331A0052); //DRX_TUNE2 PAC 16 for 64MHz PRF
AndyA 3:1459d2aa6b97 233 else
AndyA 3:1459d2aa6b97 234 writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x333B00BE); //DRX_TUNE2 PAC 16 for 64MHz PRF
AndyA 3:1459d2aa6b97 235 break;
AndyA 4:5f1025df5530 236 case DW1000Setup::pre1024: // PAC = 32
AndyA 4:5f1025df5530 237 if (systemConfig.getPRF() == DW1000Setup::prf16MHz)
AndyA 3:1459d2aa6b97 238 writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x351A009A); //DRX_TUNE2 PAC 32 for 64MHz PRF
AndyA 3:1459d2aa6b97 239 else
AndyA 3:1459d2aa6b97 240 writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x353B015E); //DRX_TUNE2 PAC 32 for 64MHz PRF
AndyA 3:1459d2aa6b97 241 break;
AndyA 4:5f1025df5530 242 case DW1000Setup::pre1536:
AndyA 4:5f1025df5530 243 case DW1000Setup::pre2048:
AndyA 4:5f1025df5530 244 case DW1000Setup::pre4096: // PAC = 64
AndyA 4:5f1025df5530 245 if (systemConfig.getPRF() == DW1000Setup::prf16MHz)
AndyA 3:1459d2aa6b97 246 writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x371A011D); //DRX_TUNE2 PAC 64 for 64MHz PRF
AndyA 3:1459d2aa6b97 247 else
AndyA 3:1459d2aa6b97 248 writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x373B0296); //DRX_TUNE2 PAC 64 for 64MHz PRF
AndyA 0:bddb8cd5e7df 249 break;
AndyA 0:bddb8cd5e7df 250 }
AndyA 0:bddb8cd5e7df 251
AndyA 3:1459d2aa6b97 252
AndyA 4:5f1025df5530 253 if (systemConfig.getPreambleLength() == DW1000Setup::pre64)
AndyA 3:1459d2aa6b97 254 writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE4H, 0x0010);
AndyA 3:1459d2aa6b97 255 else
AndyA 3:1459d2aa6b97 256 writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE4H, 0x0028);
AndyA 3:1459d2aa6b97 257
AndyA 3:1459d2aa6b97 258 }
AndyA 3:1459d2aa6b97 259
AndyA 3:1459d2aa6b97 260
AndyA 3:1459d2aa6b97 261 void DW1000::setupLDE()
AndyA 3:1459d2aa6b97 262 {
AndyA 3:1459d2aa6b97 263
AndyA 3:1459d2aa6b97 264 writeRegister8 (DW1000_LDE_CTRL, DWLDE_LDE_CFG1, 0x13 | 0x03<<5); //NTM = 13 (12 may be better in some situations. PMULT = 3
AndyA 3:1459d2aa6b97 265
AndyA 4:5f1025df5530 266 if (systemConfig.getPRF() == DW1000Setup::prf16MHz)
AndyA 3:1459d2aa6b97 267 writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_CFG2, 0x1607); //LDE_CFG2 for 16MHz PRF
AndyA 3:1459d2aa6b97 268 else
AndyA 3:1459d2aa6b97 269 writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_CFG2, 0x0607); //LDE_CFG2 for 64MHz PRF
AndyA 3:1459d2aa6b97 270
AndyA 3:1459d2aa6b97 271 uint16_t replicaCoeff;
AndyA 4:5f1025df5530 272 switch (systemConfig.getPreambleCode()) {
AndyA 3:1459d2aa6b97 273 default:
AndyA 3:1459d2aa6b97 274 case 1:
AndyA 3:1459d2aa6b97 275 case 2:
AndyA 3:1459d2aa6b97 276 replicaCoeff = 0x5998;
AndyA 3:1459d2aa6b97 277 break;
AndyA 3:1459d2aa6b97 278 case 3:
AndyA 3:1459d2aa6b97 279 replicaCoeff = 0x51EA;
AndyA 3:1459d2aa6b97 280 break;
AndyA 3:1459d2aa6b97 281 case 4:
AndyA 3:1459d2aa6b97 282 replicaCoeff = 0x428E;
AndyA 3:1459d2aa6b97 283 break;
AndyA 3:1459d2aa6b97 284 case 5:
AndyA 3:1459d2aa6b97 285 replicaCoeff = 0x451E;
AndyA 3:1459d2aa6b97 286 break;
AndyA 3:1459d2aa6b97 287 case 6:
AndyA 3:1459d2aa6b97 288 replicaCoeff = 0x2E14;
AndyA 3:1459d2aa6b97 289 break;
AndyA 3:1459d2aa6b97 290 case 7:
AndyA 3:1459d2aa6b97 291 replicaCoeff = 0x8000;
AndyA 3:1459d2aa6b97 292 break;
AndyA 3:1459d2aa6b97 293 case 8:
AndyA 3:1459d2aa6b97 294 replicaCoeff = 0x51EA;
AndyA 3:1459d2aa6b97 295 break;
AndyA 3:1459d2aa6b97 296 case 9:
AndyA 3:1459d2aa6b97 297 replicaCoeff = 0x28F4;
AndyA 3:1459d2aa6b97 298 break;
AndyA 3:1459d2aa6b97 299 case 10:
AndyA 3:1459d2aa6b97 300 replicaCoeff = 0x3332;
AndyA 3:1459d2aa6b97 301 break;
AndyA 3:1459d2aa6b97 302 case 11:
AndyA 3:1459d2aa6b97 303 replicaCoeff = 0x3AE0;
AndyA 3:1459d2aa6b97 304 break;
AndyA 3:1459d2aa6b97 305 case 12:
AndyA 3:1459d2aa6b97 306 replicaCoeff = 0x3D70;
AndyA 3:1459d2aa6b97 307 break;
AndyA 3:1459d2aa6b97 308 case 13:
AndyA 3:1459d2aa6b97 309 replicaCoeff = 0x3AE0;
AndyA 3:1459d2aa6b97 310 break;
AndyA 3:1459d2aa6b97 311 case 14:
AndyA 3:1459d2aa6b97 312 replicaCoeff = 0x35C2;
AndyA 3:1459d2aa6b97 313 break;
AndyA 3:1459d2aa6b97 314 case 15:
AndyA 3:1459d2aa6b97 315 replicaCoeff = 0x2B84;
AndyA 3:1459d2aa6b97 316 break;
AndyA 3:1459d2aa6b97 317 case 16:
AndyA 3:1459d2aa6b97 318 replicaCoeff = 0x35C2;
AndyA 3:1459d2aa6b97 319 break;
AndyA 3:1459d2aa6b97 320 case 17:
AndyA 3:1459d2aa6b97 321 replicaCoeff = 0x3332;
AndyA 3:1459d2aa6b97 322 break;
AndyA 3:1459d2aa6b97 323 case 18:
AndyA 3:1459d2aa6b97 324 replicaCoeff = 0x35C2;
AndyA 3:1459d2aa6b97 325 break;
AndyA 3:1459d2aa6b97 326 case 19:
AndyA 3:1459d2aa6b97 327 replicaCoeff = 0x35C2;
AndyA 3:1459d2aa6b97 328 break;
AndyA 3:1459d2aa6b97 329 case 20:
AndyA 3:1459d2aa6b97 330 replicaCoeff = 0x47AE;
AndyA 3:1459d2aa6b97 331 break;
AndyA 3:1459d2aa6b97 332 case 21:
AndyA 3:1459d2aa6b97 333 replicaCoeff = 0x3AE0;
AndyA 3:1459d2aa6b97 334 break;
AndyA 3:1459d2aa6b97 335 case 22:
AndyA 3:1459d2aa6b97 336 replicaCoeff = 0x3850;
AndyA 3:1459d2aa6b97 337 break;
AndyA 3:1459d2aa6b97 338 case 23:
AndyA 3:1459d2aa6b97 339 replicaCoeff = 0x30A2;
AndyA 3:1459d2aa6b97 340 break;
AndyA 3:1459d2aa6b97 341 case 24:
AndyA 3:1459d2aa6b97 342 replicaCoeff = 0x3850;
AndyA 3:1459d2aa6b97 343 break;
AndyA 3:1459d2aa6b97 344 }
AndyA 3:1459d2aa6b97 345
AndyA 4:5f1025df5530 346 if (systemConfig.getDataRate() == DW1000Setup::kbps110)
AndyA 3:1459d2aa6b97 347 replicaCoeff = replicaCoeff>>3;
AndyA 3:1459d2aa6b97 348
AndyA 3:1459d2aa6b97 349 writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_REPC, replicaCoeff);
AndyA 3:1459d2aa6b97 350
AndyA 3:1459d2aa6b97 351 loadLDE();
AndyA 3:1459d2aa6b97 352 }
AndyA 3:1459d2aa6b97 353
AndyA 3:1459d2aa6b97 354 void DW1000::setupChannel()
AndyA 3:1459d2aa6b97 355 {
AndyA 4:5f1025df5530 356 uint32_t registerValue = 0;
AndyA 3:1459d2aa6b97 357
AndyA 4:5f1025df5530 358 registerValue = systemConfig.getChannel(); // set Tx channel
AndyA 4:5f1025df5530 359 registerValue |= systemConfig.getChannel()<<4; // set Rx channel
AndyA 3:1459d2aa6b97 360
AndyA 4:5f1025df5530 361 if (systemConfig.getPRF() == DW1000Setup::prf16MHz) // set PRF (2 bit value 01 or 10)
AndyA 3:1459d2aa6b97 362 registerValue |= 0x01 << 18;
AndyA 3:1459d2aa6b97 363 else
AndyA 3:1459d2aa6b97 364 registerValue |= 0x02 << 18;
AndyA 3:1459d2aa6b97 365
AndyA 4:5f1025df5530 366 if (systemConfig.getSfd() == DW1000Setup::decaWave)
AndyA 3:1459d2aa6b97 367 registerValue |= 0x01 << 17; // enable DW own SFD
AndyA 4:5f1025df5530 368
AndyA 4:5f1025df5530 369 if (systemConfig.getSfd() == DW1000Setup::user) {
AndyA 4:5f1025df5530 370 registerValue |= 0x01 << 20; // enable user set SFD Tx
AndyA 4:5f1025df5530 371 registerValue |= 0x01 << 21; // enable user set SFD Rx
AndyA 3:1459d2aa6b97 372 }
AndyA 3:1459d2aa6b97 373
AndyA 4:5f1025df5530 374 registerValue |= systemConfig.getPreambleCode() << 22; // set Tx preamble code
AndyA 4:5f1025df5530 375 registerValue |= systemConfig.getPreambleCode() << 27; // set Rx preamble code
AndyA 3:1459d2aa6b97 376
AndyA 4:5f1025df5530 377 writeRegister32(DW1000_CHAN_CTRL, 0, registerValue);
AndyA 3:1459d2aa6b97 378 }
AndyA 3:1459d2aa6b97 379
AndyA 3:1459d2aa6b97 380
AndyA 3:1459d2aa6b97 381 uint8_t DW1000::powerToRegValue(uint16_t powercB)
AndyA 3:1459d2aa6b97 382 {
AndyA 3:1459d2aa6b97 383
AndyA 3:1459d2aa6b97 384 // course power control - 0 = 18dB, 6 = 0dB in 3dB steps.
AndyA 3:1459d2aa6b97 385 uint8_t course = powercB / 30;
AndyA 3:1459d2aa6b97 386
AndyA 3:1459d2aa6b97 387 if(course > 6)
AndyA 3:1459d2aa6b97 388 course = 6;
AndyA 3:1459d2aa6b97 389
AndyA 3:1459d2aa6b97 390 // remaining power
AndyA 3:1459d2aa6b97 391 powercB -= course * 30;
AndyA 3:1459d2aa6b97 392
AndyA 3:1459d2aa6b97 393 // value in reg is inverse.
AndyA 3:1459d2aa6b97 394 course = 6-course;
AndyA 3:1459d2aa6b97 395
AndyA 3:1459d2aa6b97 396 // fine control in steps of 0.5dB
AndyA 3:1459d2aa6b97 397 uint8_t fine = powercB / 5;
AndyA 3:1459d2aa6b97 398 if (fine > 31)
AndyA 3:1459d2aa6b97 399 fine = 31;
AndyA 3:1459d2aa6b97 400
AndyA 3:1459d2aa6b97 401
AndyA 3:1459d2aa6b97 402 return (course << 5) | fine;
AndyA 3:1459d2aa6b97 403
AndyA 3:1459d2aa6b97 404 }
AndyA 3:1459d2aa6b97 405
AndyA 3:1459d2aa6b97 406 // transmit power: 0 to 33.5 dB gain in steps of 0.5. Inputs are in 10ths of a dB (0 to 335)
AndyA 3:1459d2aa6b97 407 void DW1000::setTxPower(uint16_t normalPowercB, uint16_t boost500, uint16_t boost250, uint16_t boost125)
AndyA 3:1459d2aa6b97 408 {
AndyA 4:5f1025df5530 409
AndyA 3:1459d2aa6b97 410 if(normalPowercB > 335)
AndyA 3:1459d2aa6b97 411 normalPowercB = 335;
AndyA 3:1459d2aa6b97 412
AndyA 3:1459d2aa6b97 413 if (boost500 < normalPowercB)
AndyA 3:1459d2aa6b97 414 boost500 = normalPowercB;
AndyA 3:1459d2aa6b97 415 if(boost500 > 335)
AndyA 3:1459d2aa6b97 416 boost500 = 335;
AndyA 0:bddb8cd5e7df 417
AndyA 3:1459d2aa6b97 418 if (boost250 < boost500)
AndyA 3:1459d2aa6b97 419 boost250 = boost500;
AndyA 3:1459d2aa6b97 420 if(boost250 > 335)
AndyA 3:1459d2aa6b97 421 boost250 = 335;
AndyA 3:1459d2aa6b97 422
AndyA 3:1459d2aa6b97 423 if (boost125 < boost250)
AndyA 3:1459d2aa6b97 424 boost125 = boost250;
AndyA 3:1459d2aa6b97 425 if(boost125 > 335)
AndyA 3:1459d2aa6b97 426 boost125 = 335;
AndyA 3:1459d2aa6b97 427
AndyA 4:5f1025df5530 428 if (systemConfig.getSmartPower() == false) {
AndyA 4:5f1025df5530 429 boost500 = normalPowercB;
AndyA 4:5f1025df5530 430 boost250 = normalPowercB;
AndyA 4:5f1025df5530 431 boost125 = normalPowercB;
AndyA 4:5f1025df5530 432 }
AndyA 4:5f1025df5530 433
AndyA 3:1459d2aa6b97 434 uint32_t powerReg = powerToRegValue(normalPowercB);
AndyA 3:1459d2aa6b97 435 powerReg |= powerToRegValue(boost500) << 8;
AndyA 3:1459d2aa6b97 436 powerReg |= powerToRegValue(boost250) << 16;
AndyA 3:1459d2aa6b97 437 powerReg |= powerToRegValue(boost125) << 24;
AndyA 3:1459d2aa6b97 438 }
AndyA 3:1459d2aa6b97 439
AndyA 3:1459d2aa6b97 440 void DW1000::setupAnalogRF()
AndyA 3:1459d2aa6b97 441 {
AndyA 4:5f1025df5530 442 switch (systemConfig.getChannel()) {
AndyA 3:1459d2aa6b97 443 case 1:
AndyA 3:1459d2aa6b97 444 writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x00005C40);
AndyA 3:1459d2aa6b97 445 break;
AndyA 3:1459d2aa6b97 446 case 2:
AndyA 3:1459d2aa6b97 447 writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x00045CA0);
AndyA 3:1459d2aa6b97 448 break;
AndyA 3:1459d2aa6b97 449 case 3:
AndyA 3:1459d2aa6b97 450 writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x00086CC0);
AndyA 3:1459d2aa6b97 451 break;
AndyA 3:1459d2aa6b97 452 case 4:
AndyA 3:1459d2aa6b97 453 writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x00045C80);
AndyA 3:1459d2aa6b97 454 break;
AndyA 3:1459d2aa6b97 455 case 5:
AndyA 3:1459d2aa6b97 456 default:
AndyA 3:1459d2aa6b97 457 writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x001E3FE0);
AndyA 3:1459d2aa6b97 458 break;
AndyA 3:1459d2aa6b97 459 case 7:
AndyA 3:1459d2aa6b97 460 writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x001E7DE0);
AndyA 3:1459d2aa6b97 461 break;
AndyA 3:1459d2aa6b97 462 }
AndyA 3:1459d2aa6b97 463
AndyA 4:5f1025df5530 464 switch (systemConfig.getChannel()) {
AndyA 3:1459d2aa6b97 465 case 1:
AndyA 3:1459d2aa6b97 466 case 2:
AndyA 3:1459d2aa6b97 467 case 3:
AndyA 3:1459d2aa6b97 468 case 5:
AndyA 3:1459d2aa6b97 469 default:
AndyA 3:1459d2aa6b97 470 writeRegister8(DW1000_RF_CONF, DWRFCONF_RF_RXCTRLH, 0xD8);
AndyA 3:1459d2aa6b97 471 break;
AndyA 3:1459d2aa6b97 472 case 4:
AndyA 3:1459d2aa6b97 473 case 7:
AndyA 3:1459d2aa6b97 474 writeRegister8(DW1000_RF_CONF, DWRFCONF_RF_RXCTRLH, 0xBC);
AndyA 3:1459d2aa6b97 475 break;
AndyA 3:1459d2aa6b97 476 }
AndyA 3:1459d2aa6b97 477
AndyA 3:1459d2aa6b97 478 loadLDOTUNE();
AndyA 3:1459d2aa6b97 479
AndyA 3:1459d2aa6b97 480 }
AndyA 3:1459d2aa6b97 481
AndyA 3:1459d2aa6b97 482 void DW1000::setupTxCalibration()
AndyA 3:1459d2aa6b97 483 {
AndyA 4:5f1025df5530 484 switch (systemConfig.getChannel()) {
AndyA 3:1459d2aa6b97 485 case 1:
AndyA 3:1459d2aa6b97 486 writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0xC9);
AndyA 3:1459d2aa6b97 487 break;
AndyA 3:1459d2aa6b97 488 case 2:
AndyA 3:1459d2aa6b97 489 writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0xC2);
AndyA 3:1459d2aa6b97 490 break;
AndyA 3:1459d2aa6b97 491 case 3:
AndyA 3:1459d2aa6b97 492 writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0xC5);
AndyA 3:1459d2aa6b97 493 break;
AndyA 3:1459d2aa6b97 494 case 4:
AndyA 3:1459d2aa6b97 495 writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0x95);
AndyA 3:1459d2aa6b97 496 break;
AndyA 3:1459d2aa6b97 497 case 5:
AndyA 3:1459d2aa6b97 498 default:
AndyA 3:1459d2aa6b97 499 writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0xC0);
AndyA 3:1459d2aa6b97 500 break;
AndyA 3:1459d2aa6b97 501 case 7:
AndyA 3:1459d2aa6b97 502 writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0x93);
AndyA 3:1459d2aa6b97 503 break;
AndyA 3:1459d2aa6b97 504 }
AndyA 3:1459d2aa6b97 505 }
AndyA 3:1459d2aa6b97 506
AndyA 3:1459d2aa6b97 507 void DW1000::setupFreqSynth()
AndyA 3:1459d2aa6b97 508 {
AndyA 3:1459d2aa6b97 509
AndyA 4:5f1025df5530 510 switch (systemConfig.getChannel()) {
AndyA 3:1459d2aa6b97 511 case 1:
AndyA 3:1459d2aa6b97 512 writeRegister32 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLCFG, 0x09000407); //FS_PLLCFG for channel 1
AndyA 3:1459d2aa6b97 513 writeRegister8 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLTUNE, 0x1E);
AndyA 3:1459d2aa6b97 514 break;
AndyA 3:1459d2aa6b97 515 case 2:
AndyA 3:1459d2aa6b97 516 case 4:
AndyA 3:1459d2aa6b97 517 writeRegister32 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLCFG, 0x08400508); //FS_PLLCFG for channel 2,4
AndyA 3:1459d2aa6b97 518 writeRegister8 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLTUNE, 0x26);
AndyA 3:1459d2aa6b97 519 break;
AndyA 3:1459d2aa6b97 520 case 3:
AndyA 3:1459d2aa6b97 521 writeRegister32 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLCFG, 0x08401009); //FS_PLLCFG for channel 3
AndyA 3:1459d2aa6b97 522 writeRegister8 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLTUNE, 0x5E);
AndyA 3:1459d2aa6b97 523 break;
AndyA 3:1459d2aa6b97 524 case 5:
AndyA 3:1459d2aa6b97 525 case 7:
AndyA 3:1459d2aa6b97 526 default:
AndyA 3:1459d2aa6b97 527 writeRegister32 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLCFG, 0x0800041D); //FS_PLLCFG for channel 5,7
AndyA 3:1459d2aa6b97 528 writeRegister8 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLTUNE, 0xBE); //FS_PLLTUNE for channel 5
AndyA 3:1459d2aa6b97 529 break;
AndyA 3:1459d2aa6b97 530 }
AndyA 3:1459d2aa6b97 531 }
AndyA 3:1459d2aa6b97 532
AndyA 3:1459d2aa6b97 533 void DW1000::setupTxFrameCtrl()
AndyA 3:1459d2aa6b97 534 {
AndyA 4:5f1025df5530 535 uint32_t frameCtrlValue = 0;
AndyA 4:5f1025df5530 536 switch (systemConfig.getDataRate()) {
AndyA 4:5f1025df5530 537 case DW1000Setup::kbps110:
AndyA 3:1459d2aa6b97 538 break;
AndyA 4:5f1025df5530 539 case DW1000Setup::kbps850:
AndyA 3:1459d2aa6b97 540 frameCtrlValue |= 0x01<<13;
AndyA 3:1459d2aa6b97 541 break;
AndyA 4:5f1025df5530 542 case DW1000Setup::kbps6800:
AndyA 3:1459d2aa6b97 543 default:
AndyA 3:1459d2aa6b97 544 frameCtrlValue |= 0x02<<13;
AndyA 3:1459d2aa6b97 545 break;
AndyA 3:1459d2aa6b97 546 }
AndyA 3:1459d2aa6b97 547 frameCtrlValue |= 0x01<<15;
AndyA 3:1459d2aa6b97 548
AndyA 4:5f1025df5530 549 if (systemConfig.getPRF() == DW1000Setup::prf16MHz)
AndyA 3:1459d2aa6b97 550 frameCtrlValue |= 0x01<<16;
AndyA 3:1459d2aa6b97 551 else
AndyA 3:1459d2aa6b97 552 frameCtrlValue |= 0x02<<16;
AndyA 3:1459d2aa6b97 553
AndyA 4:5f1025df5530 554 switch (systemConfig.getPreambleLength()) {
AndyA 4:5f1025df5530 555 case DW1000Setup::pre64:
AndyA 3:1459d2aa6b97 556 frameCtrlValue |= 0x01<<18; // TXPSR
AndyA 3:1459d2aa6b97 557 frameCtrlValue |= 0x00<<20; // PE
AndyA 3:1459d2aa6b97 558 break;
AndyA 4:5f1025df5530 559 case DW1000Setup::pre128:
AndyA 3:1459d2aa6b97 560 default:
AndyA 3:1459d2aa6b97 561 frameCtrlValue |= 0x01<<18; // TXPSR
AndyA 3:1459d2aa6b97 562 frameCtrlValue |= 0x01<<20; // PE
AndyA 3:1459d2aa6b97 563 break;
AndyA 4:5f1025df5530 564 case DW1000Setup::pre256:
AndyA 3:1459d2aa6b97 565 frameCtrlValue |= 0x01<<18; // TXPSR
AndyA 3:1459d2aa6b97 566 frameCtrlValue |= 0x02<<20; // PE
AndyA 3:1459d2aa6b97 567 break;
AndyA 4:5f1025df5530 568 case DW1000Setup::pre512:
AndyA 3:1459d2aa6b97 569 frameCtrlValue |= 0x01<<18; // TXPSR
AndyA 3:1459d2aa6b97 570 frameCtrlValue |= 0x03<<20; // PE
AndyA 3:1459d2aa6b97 571 break;
AndyA 4:5f1025df5530 572 case DW1000Setup::pre1024:
AndyA 3:1459d2aa6b97 573 frameCtrlValue |= 0x02<<18; // TXPSR
AndyA 3:1459d2aa6b97 574 frameCtrlValue |= 0x00<<20; // PE
AndyA 3:1459d2aa6b97 575 break;
AndyA 4:5f1025df5530 576 case DW1000Setup::pre1536:
AndyA 3:1459d2aa6b97 577 frameCtrlValue |= 0x02<<18; // TXPSR
AndyA 3:1459d2aa6b97 578 frameCtrlValue |= 0x01<<20; // PE
AndyA 3:1459d2aa6b97 579 break;
AndyA 4:5f1025df5530 580 case DW1000Setup::pre2048:
AndyA 3:1459d2aa6b97 581 frameCtrlValue |= 0x02<<18; // TXPSR
AndyA 3:1459d2aa6b97 582 frameCtrlValue |= 0x02<<20; // PE
AndyA 3:1459d2aa6b97 583 break;
AndyA 4:5f1025df5530 584 case DW1000Setup::pre4096:
AndyA 3:1459d2aa6b97 585 frameCtrlValue |= 0x03<<18; // TXPSR
AndyA 3:1459d2aa6b97 586 frameCtrlValue |= 0x00<<20; // PE
AndyA 3:1459d2aa6b97 587 break;
AndyA 3:1459d2aa6b97 588 }
AndyA 4:5f1025df5530 589 writeRegister32(DW1000_TX_FCTRL,0,frameCtrlValue);
AndyA 0:bddb8cd5e7df 590 }
AndyA 0:bddb8cd5e7df 591
AndyA 0:bddb8cd5e7df 592 void DW1000::setRxDelay(uint16_t ticks)
AndyA 0:bddb8cd5e7df 593 {
AndyA 0:bddb8cd5e7df 594 writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_RXANTD, ticks);
AndyA 0:bddb8cd5e7df 595 }
AndyA 0:bddb8cd5e7df 596 void DW1000::setTxDelay(uint16_t ticks)
AndyA 0:bddb8cd5e7df 597 {
AndyA 0:bddb8cd5e7df 598 writeRegister16(DW1000_TX_ANTD, 0, ticks);
AndyA 0:bddb8cd5e7df 599 }
AndyA 0:bddb8cd5e7df 600
AndyA 0:bddb8cd5e7df 601 void DW1000::setCallbacks(void (*callbackRX)(void), void (*callbackTX)(void))
AndyA 0:bddb8cd5e7df 602 {
AndyA 0:bddb8cd5e7df 603 bool RX = false;
AndyA 0:bddb8cd5e7df 604 bool TX = false;
AndyA 0:bddb8cd5e7df 605 if (callbackRX) {
AndyA 0:bddb8cd5e7df 606 DW1000::callbackRX.attach(callbackRX);
AndyA 0:bddb8cd5e7df 607 RX = true;
AndyA 0:bddb8cd5e7df 608 }
AndyA 0:bddb8cd5e7df 609 if (callbackTX) {
AndyA 0:bddb8cd5e7df 610 DW1000::callbackTX.attach(callbackTX);
AndyA 0:bddb8cd5e7df 611 TX = true;
AndyA 0:bddb8cd5e7df 612 }
AndyA 0:bddb8cd5e7df 613 setInterrupt(RX,TX);
AndyA 0:bddb8cd5e7df 614 }
AndyA 0:bddb8cd5e7df 615
AndyA 0:bddb8cd5e7df 616 uint32_t DW1000::getDeviceID()
AndyA 0:bddb8cd5e7df 617 {
AndyA 0:bddb8cd5e7df 618 uint32_t result;
AndyA 0:bddb8cd5e7df 619 readRegister(DW1000_DEV_ID, 0, (uint8_t*)&result, 4);
AndyA 0:bddb8cd5e7df 620 return result;
AndyA 0:bddb8cd5e7df 621 }
AndyA 0:bddb8cd5e7df 622
AndyA 0:bddb8cd5e7df 623 uint64_t DW1000::getEUI()
AndyA 0:bddb8cd5e7df 624 {
AndyA 0:bddb8cd5e7df 625 uint64_t result;
AndyA 0:bddb8cd5e7df 626 readRegister(DW1000_EUI, 0, (uint8_t*)&result, 8);
AndyA 0:bddb8cd5e7df 627 return result;
AndyA 0:bddb8cd5e7df 628 }
AndyA 0:bddb8cd5e7df 629
AndyA 0:bddb8cd5e7df 630 void DW1000::setEUI(uint64_t EUI)
AndyA 0:bddb8cd5e7df 631 {
AndyA 0:bddb8cd5e7df 632 writeRegister(DW1000_EUI, 0, (uint8_t*)&EUI, 8);
AndyA 0:bddb8cd5e7df 633 }
AndyA 0:bddb8cd5e7df 634
AndyA 0:bddb8cd5e7df 635
AndyA 0:bddb8cd5e7df 636 float DW1000::getVoltage()
AndyA 0:bddb8cd5e7df 637 {
AndyA 0:bddb8cd5e7df 638 uint8_t data;
AndyA 0:bddb8cd5e7df 639
AndyA 0:bddb8cd5e7df 640 writeRegister8(DW1000_RF_CONF, 0x11, 0x80);
AndyA 0:bddb8cd5e7df 641 writeRegister8(DW1000_RF_CONF, 0x12, 0x0A);
AndyA 0:bddb8cd5e7df 642 writeRegister8(DW1000_RF_CONF, 0x12, 0x0F);
AndyA 0:bddb8cd5e7df 643 writeRegister8(DW1000_TX_CAL, 0x00, 0x01);
AndyA 0:bddb8cd5e7df 644 writeRegister8(DW1000_TX_CAL, 0x00, 0x00);
AndyA 0:bddb8cd5e7df 645 data = readRegister8(DW1000_TX_CAL, 0x03); // get the 8-Bit reading for Voltage
AndyA 1:dcbd071f38d5 646 float Voltage = (float)(data - (readOTP(0x08)&0x00ff)) *0.00578 + 3.3;
AndyA 0:bddb8cd5e7df 647 return Voltage;
AndyA 0:bddb8cd5e7df 648 }
AndyA 0:bddb8cd5e7df 649
AndyA 0:bddb8cd5e7df 650 float DW1000::getTemperature()
AndyA 0:bddb8cd5e7df 651 {
AndyA 0:bddb8cd5e7df 652 uint8_t data;
AndyA 0:bddb8cd5e7df 653
AndyA 0:bddb8cd5e7df 654 writeRegister8(DW1000_RF_CONF, 0x11, 0x80);
AndyA 0:bddb8cd5e7df 655 writeRegister8(DW1000_RF_CONF, 0x12, 0x0A);
AndyA 0:bddb8cd5e7df 656 writeRegister8(DW1000_RF_CONF, 0x12, 0x0F);
AndyA 0:bddb8cd5e7df 657 writeRegister8(DW1000_TX_CAL, 0x00, 0x01);
AndyA 0:bddb8cd5e7df 658 writeRegister8(DW1000_TX_CAL, 0x00, 0x00);
AndyA 0:bddb8cd5e7df 659 data = readRegister16(DW1000_TX_CAL, 0x04); // get the 8-Bit reading for Temperature
AndyA 1:dcbd071f38d5 660 float temperature = (float)(data - (readOTP(0x09) & 0x00ff))*0.9 + 23;
AndyA 0:bddb8cd5e7df 661 return temperature;
AndyA 0:bddb8cd5e7df 662 }
AndyA 0:bddb8cd5e7df 663
AndyA 0:bddb8cd5e7df 664
AndyA 0:bddb8cd5e7df 665 uint64_t DW1000::getStatus()
AndyA 0:bddb8cd5e7df 666 {
AndyA 0:bddb8cd5e7df 667 return readRegister40(DW1000_SYS_STATUS, 0);
AndyA 0:bddb8cd5e7df 668 }
AndyA 0:bddb8cd5e7df 669
AndyA 0:bddb8cd5e7df 670 uint64_t DW1000::getRXTimestamp()
AndyA 0:bddb8cd5e7df 671 {
AndyA 0:bddb8cd5e7df 672 return readRegister40(DW1000_RX_TIME, 0);
AndyA 0:bddb8cd5e7df 673 }
AndyA 0:bddb8cd5e7df 674
AndyA 0:bddb8cd5e7df 675 uint64_t DW1000::getTXTimestamp()
AndyA 0:bddb8cd5e7df 676 {
AndyA 0:bddb8cd5e7df 677 return readRegister40(DW1000_TX_TIME, 0);
AndyA 0:bddb8cd5e7df 678 }
AndyA 0:bddb8cd5e7df 679
AndyA 0:bddb8cd5e7df 680
AndyA 0:bddb8cd5e7df 681 void DW1000::sendFrame(uint8_t* message, uint16_t length)
AndyA 0:bddb8cd5e7df 682 {
AndyA 0:bddb8cd5e7df 683 //if (length >= 1021) length = 1021; // check for maximim length a frame can have with 1024 Byte frames [not used, see constructor]
AndyA 0:bddb8cd5e7df 684 if (length >= 125) length = 125; // check for maximim length a frame can have with 127 Byte frames
AndyA 0:bddb8cd5e7df 685 uint8_t len_7bit = length;
AndyA 0:bddb8cd5e7df 686 writeRegister(DW1000_TX_BUFFER, 0, message, len_7bit); // fill buffer
AndyA 0:bddb8cd5e7df 687
AndyA 3:1459d2aa6b97 688 /* support for frames over 127 bytes
AndyA 3:1459d2aa6b97 689 uint8_t backup = readRegister8(DW1000_TX_FCTRL, 1); // put length of frame
AndyA 3:1459d2aa6b97 690 length += 2; // including 2 CRC Bytes
AndyA 3:1459d2aa6b97 691 length = ((backup & 0xFC) << 8) | (length & 0x03FF);
AndyA 3:1459d2aa6b97 692 writeRegister16(DW1000_TX_FCTRL, 0, length);
AndyA 3:1459d2aa6b97 693 */
AndyA 0:bddb8cd5e7df 694 len_7bit += 2; // including 2 CRC Bytes
AndyA 0:bddb8cd5e7df 695 writeRegister8(DW1000_TX_FCTRL, 0, len_7bit);
AndyA 0:bddb8cd5e7df 696
AndyA 0:bddb8cd5e7df 697 stopTRX(); // stop receiving
AndyA 0:bddb8cd5e7df 698 writeRegister8(DW1000_SYS_CTRL, 0, 0x02 | 0x80); // trigger sending process by setting the TXSTRT bit
AndyA 0:bddb8cd5e7df 699 // startRX(); // enable receiver again
AndyA 0:bddb8cd5e7df 700 }
AndyA 0:bddb8cd5e7df 701
AndyA 3:1459d2aa6b97 702 void DW1000::setupSyncedFrame(uint8_t* message, uint16_t length)
AndyA 3:1459d2aa6b97 703 {
AndyA 0:bddb8cd5e7df 704 //if (length >= 1021) length = 1021; // check for maximim length a frame can have with 1024 Byte frames [not used, see constructor]
AndyA 0:bddb8cd5e7df 705 if (length >= 125) length = 125; // check for maximim length a frame can have with 127 Byte frames
AndyA 0:bddb8cd5e7df 706 writeRegister(DW1000_TX_BUFFER, 0, message, length); // fill buffer
AndyA 0:bddb8cd5e7df 707
AndyA 0:bddb8cd5e7df 708 uint8_t backup = readRegister8(DW1000_TX_FCTRL, 1); // put length of frame
AndyA 0:bddb8cd5e7df 709 length += 2; // including 2 CRC Bytes
AndyA 0:bddb8cd5e7df 710 length = ((backup & 0xFC) << 8) | (length & 0x03FF);
AndyA 0:bddb8cd5e7df 711 writeRegister16(DW1000_TX_FCTRL, 0, length);
AndyA 0:bddb8cd5e7df 712 }
AndyA 0:bddb8cd5e7df 713
AndyA 3:1459d2aa6b97 714 void DW1000::armSyncedFrame()
AndyA 3:1459d2aa6b97 715 {
AndyA 0:bddb8cd5e7df 716 stopTRX(); // stop receiving
AndyA 0:bddb8cd5e7df 717 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 3:1459d2aa6b97 718 }
AndyA 0:bddb8cd5e7df 719
AndyA 0:bddb8cd5e7df 720 void DW1000::sendDelayedFrame(uint8_t* message, uint16_t length, uint64_t TxTimestamp)
AndyA 0:bddb8cd5e7df 721 {
AndyA 0:bddb8cd5e7df 722 //if (length >= 1021) length = 1021; // check for maximim length a frame can have with 1024 Byte frames [not used, see constructor]
AndyA 0:bddb8cd5e7df 723 if (length >= 125) length = 125; // check for maximim length a frame can have with 127 Byte frames
AndyA 0:bddb8cd5e7df 724 writeRegister(DW1000_TX_BUFFER, 0, message, length); // fill buffer
AndyA 0:bddb8cd5e7df 725
AndyA 0:bddb8cd5e7df 726 uint8_t backup = readRegister8(DW1000_TX_FCTRL, 1); // put length of frame
AndyA 0:bddb8cd5e7df 727 length += 2; // including 2 CRC Bytes
AndyA 0:bddb8cd5e7df 728 length = ((backup & 0xFC) << 8) | (length & 0x03FF);
AndyA 0:bddb8cd5e7df 729 writeRegister16(DW1000_TX_FCTRL, 0, length);
AndyA 0:bddb8cd5e7df 730
AndyA 0:bddb8cd5e7df 731 writeRegister40(DW1000_DX_TIME, 0, TxTimestamp); //write the timestamp on which to send the message
AndyA 0:bddb8cd5e7df 732
AndyA 0:bddb8cd5e7df 733 stopTRX(); // stop receiving
AndyA 0:bddb8cd5e7df 734 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 735 }
AndyA 0:bddb8cd5e7df 736
AndyA 0:bddb8cd5e7df 737 void DW1000::startRX()
AndyA 0:bddb8cd5e7df 738 {
AndyA 0:bddb8cd5e7df 739 writeRegister8(DW1000_SYS_CTRL, 0x01, 0x01); // start listening for preamble by setting the RXENAB bit
AndyA 0:bddb8cd5e7df 740 }
AndyA 0:bddb8cd5e7df 741
AndyA 0:bddb8cd5e7df 742 void DW1000::stopTRX()
AndyA 0:bddb8cd5e7df 743 {
AndyA 0:bddb8cd5e7df 744 writeRegister8(DW1000_SYS_CTRL, 0, 0x40); // disable tranceiver go back to idle mode
AndyA 0:bddb8cd5e7df 745 }
AndyA 0:bddb8cd5e7df 746
AndyA 0:bddb8cd5e7df 747 // PRIVATE Methods ------------------------------------------------------------------------------------
AndyA 0:bddb8cd5e7df 748 void DW1000::loadLDE() // initialise LDE algorithm LDELOAD User Manual p22
AndyA 0:bddb8cd5e7df 749 {
AndyA 0:bddb8cd5e7df 750 spi.frequency(SPIRATE_OSC); // with a 1MHz clock rate (worked up to 49MHz in our Test)
AndyA 0:bddb8cd5e7df 751
AndyA 0:bddb8cd5e7df 752 writeRegister16(DW1000_PMSC, 0, 0x0301); // set clock to XTAL so OTP is reliable
AndyA 0:bddb8cd5e7df 753 writeRegister16(DW1000_OTP_IF, DWOTP_OTP_CTRL, 0x8000); // set LDELOAD bit in OTP
AndyA 0:bddb8cd5e7df 754 wait_us(150);
AndyA 0:bddb8cd5e7df 755 writeRegister16(DW1000_PMSC, 0, 0x0200); // recover to PLL clock
AndyA 0:bddb8cd5e7df 756
AndyA 0:bddb8cd5e7df 757 wait_ms(1);
AndyA 0:bddb8cd5e7df 758
AndyA 0:bddb8cd5e7df 759 spi.frequency(SPIRATE_PLL); // with a 1MHz clock rate (worked up to 49MHz in our Test)
AndyA 0:bddb8cd5e7df 760
AndyA 0:bddb8cd5e7df 761 }
AndyA 0:bddb8cd5e7df 762
AndyA 0:bddb8cd5e7df 763 void DW1000::loadLDOTUNE()
AndyA 0:bddb8cd5e7df 764 {
AndyA 1:dcbd071f38d5 765 uint64_t LDOTuningValue = readOTP(0x0004);
AndyA 1:dcbd071f38d5 766 if (LDOTuningValue != 0) {
AndyA 1:dcbd071f38d5 767 LDOTuningValue = LDOTuningValue | ((uint64_t)(readOTP(0x0005) & 0x00ff) << 32);
AndyA 0:bddb8cd5e7df 768 writeRegister40(DW1000_RF_CONF,DWRFCONF_RF_LDOTUNE,LDOTuningValue);
AndyA 1:dcbd071f38d5 769 }
AndyA 0:bddb8cd5e7df 770 }
AndyA 0:bddb8cd5e7df 771
AndyA 0:bddb8cd5e7df 772 void DW1000::resetRX()
AndyA 0:bddb8cd5e7df 773 {
AndyA 0:bddb8cd5e7df 774 writeRegister8(DW1000_PMSC, 3, 0xE0); // set RX reset
AndyA 0:bddb8cd5e7df 775 writeRegister8(DW1000_PMSC, 3, 0xF0); // clear RX reset
AndyA 0:bddb8cd5e7df 776 }
AndyA 0:bddb8cd5e7df 777
AndyA 0:bddb8cd5e7df 778 void DW1000::resetAll()
AndyA 0:bddb8cd5e7df 779 {
AndyA 0:bddb8cd5e7df 780 spi.frequency(SPIRATE_OSC); // with a 1MHz clock rate (worked up to 49MHz in our Test)
AndyA 0:bddb8cd5e7df 781
AndyA 0:bddb8cd5e7df 782 writeRegister8(DW1000_PMSC, 0, 0x01); // set clock to XTAL
AndyA 0:bddb8cd5e7df 783 writeRegister8(DW1000_PMSC, 3, 0x00); // set All reset
AndyA 0:bddb8cd5e7df 784 wait_us(10); // wait for PLL to lock
AndyA 0:bddb8cd5e7df 785 writeRegister8(DW1000_PMSC, 3, 0xF0); // clear All reset
AndyA 0:bddb8cd5e7df 786
AndyA 0:bddb8cd5e7df 787 wait_ms(1);
AndyA 0:bddb8cd5e7df 788
AndyA 0:bddb8cd5e7df 789 spi.frequency(SPIRATE_PLL); // with a 1MHz clock rate (worked up to 49MHz in our Test)
AndyA 0:bddb8cd5e7df 790 }
AndyA 0:bddb8cd5e7df 791
AndyA 0:bddb8cd5e7df 792 /// After writes have been completed reset the device.
AndyA 1:dcbd071f38d5 793 bool DW1000::writeOTP(uint16_t word_address,uint32_t data)
AndyA 0:bddb8cd5e7df 794 {
AndyA 0:bddb8cd5e7df 795 spi.frequency(SPIRATE_OSC); // with a 1MHz clock rate (worked up to 49MHz in our Test)
AndyA 0:bddb8cd5e7df 796
AndyA 0:bddb8cd5e7df 797 writeRegister8(DW1000_PMSC, 0, 0x01); // set clock to XTAL
AndyA 0:bddb8cd5e7df 798 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x03); //
AndyA 0:bddb8cd5e7df 799 writeRegister16(DW1000_OTP_IF,DWOTP_OTP_WDAT,0x9220); //
AndyA 0:bddb8cd5e7df 800 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x08); //
AndyA 0:bddb8cd5e7df 801 wait_ms(1);
AndyA 0:bddb8cd5e7df 802 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x02); //
AndyA 0:bddb8cd5e7df 803 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x88); //
AndyA 0:bddb8cd5e7df 804 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x80); //
AndyA 0:bddb8cd5e7df 805 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00); //
AndyA 0:bddb8cd5e7df 806
AndyA 0:bddb8cd5e7df 807 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x05); //
AndyA 0:bddb8cd5e7df 808 writeRegister16(DW1000_OTP_IF,DWOTP_OTP_WDAT,0x000E); //
AndyA 0:bddb8cd5e7df 809 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x08); //
AndyA 0:bddb8cd5e7df 810 wait_ms(1);
AndyA 0:bddb8cd5e7df 811 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x04); //
AndyA 0:bddb8cd5e7df 812 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x88); //
AndyA 0:bddb8cd5e7df 813 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x80); //
AndyA 0:bddb8cd5e7df 814 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00); //
AndyA 0:bddb8cd5e7df 815
AndyA 0:bddb8cd5e7df 816 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x01); //
AndyA 0:bddb8cd5e7df 817 writeRegister16(DW1000_OTP_IF,DWOTP_OTP_WDAT,0x1024); //
AndyA 0:bddb8cd5e7df 818 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x08); //
AndyA 0:bddb8cd5e7df 819 wait_ms(1);
AndyA 0:bddb8cd5e7df 820 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x00); //
AndyA 0:bddb8cd5e7df 821
AndyA 0:bddb8cd5e7df 822 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00); //
AndyA 0:bddb8cd5e7df 823 writeRegister32(DW1000_OTP_IF,DWOTP_OTP_WDAT,data); //
AndyA 1:dcbd071f38d5 824 writeRegister16(DW1000_OTP_IF,DWOTP_OTP_ADDR,word_address); //
AndyA 0:bddb8cd5e7df 825 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x40); //
AndyA 0:bddb8cd5e7df 826 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00); //
AndyA 0:bddb8cd5e7df 827 wait_ms(1);
AndyA 0:bddb8cd5e7df 828
AndyA 0:bddb8cd5e7df 829 for (int i=0; i<10; i++) {
AndyA 1:dcbd071f38d5 830 if (readOTP(word_address) == data)
AndyA 0:bddb8cd5e7df 831 return true;
AndyA 0:bddb8cd5e7df 832 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x40); // retry
AndyA 0:bddb8cd5e7df 833 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00);
AndyA 0:bddb8cd5e7df 834 wait_ms(1);
AndyA 0:bddb8cd5e7df 835 }
AndyA 0:bddb8cd5e7df 836 return false;
AndyA 0:bddb8cd5e7df 837 }
AndyA 0:bddb8cd5e7df 838
AndyA 0:bddb8cd5e7df 839
AndyA 1:dcbd071f38d5 840 uint32_t DW1000::readOTP(uint16_t word_address)
AndyA 0:bddb8cd5e7df 841 {
AndyA 1:dcbd071f38d5 842 writeRegister16(DW1000_OTP_IF,DWOTP_OTP_ADDR,word_address); // write address
AndyA 0:bddb8cd5e7df 843 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x03); // read address load
AndyA 0:bddb8cd5e7df 844 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x01); // read
AndyA 0:bddb8cd5e7df 845 uint32_t data = readRegister32(DW1000_OTP_IF,DWOTP_OTP_RDAT);
AndyA 0:bddb8cd5e7df 846 writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00); // OTP idle
AndyA 0:bddb8cd5e7df 847 return data;
AndyA 0:bddb8cd5e7df 848 }
AndyA 0:bddb8cd5e7df 849
AndyA 0:bddb8cd5e7df 850 void DW1000::setInterrupt(bool RX, bool TX)
AndyA 0:bddb8cd5e7df 851 {
AndyA 0:bddb8cd5e7df 852 writeRegister16(DW1000_SYS_MASK, 0, RX*0x4000 | TX*0x0080); // RX good frame 0x4000, TX done 0x0080
AndyA 0:bddb8cd5e7df 853 }
AndyA 0:bddb8cd5e7df 854
AndyA 0:bddb8cd5e7df 855 void DW1000::ISR()
AndyA 0:bddb8cd5e7df 856 {
AndyA 0:bddb8cd5e7df 857 uint64_t status = getStatus();
AndyA 0:bddb8cd5e7df 858 if (status & 0x4000) { // a frame was received
AndyA 0:bddb8cd5e7df 859 callbackRX.call();
AndyA 0:bddb8cd5e7df 860 writeRegister16(DW1000_SYS_STATUS, 0, 0x6F00); // clearing of receiving status bits
AndyA 0:bddb8cd5e7df 861 }
AndyA 0:bddb8cd5e7df 862 if (status & 0x80) { // sending complete
AndyA 0:bddb8cd5e7df 863 callbackTX.call();
AndyA 0:bddb8cd5e7df 864 writeRegister8(DW1000_SYS_STATUS, 0, 0xF8); // clearing of sending status bits
AndyA 0:bddb8cd5e7df 865 }
AndyA 0:bddb8cd5e7df 866 }
AndyA 0:bddb8cd5e7df 867
AndyA 0:bddb8cd5e7df 868 uint16_t DW1000::getFramelength()
AndyA 0:bddb8cd5e7df 869 {
AndyA 0:bddb8cd5e7df 870 uint16_t framelength = readRegister16(DW1000_RX_FINFO, 0); // get framelength
AndyA 0:bddb8cd5e7df 871 framelength = (framelength & 0x03FF) - 2; // take only the right bits and subtract the 2 CRC Bytes
AndyA 0:bddb8cd5e7df 872 return framelength;
AndyA 0:bddb8cd5e7df 873 }
AndyA 0:bddb8cd5e7df 874
AndyA 0:bddb8cd5e7df 875 // SPI Interface ------------------------------------------------------------------------------------
AndyA 0:bddb8cd5e7df 876 uint8_t DW1000::readRegister8(uint8_t reg, uint16_t subaddress)
AndyA 0:bddb8cd5e7df 877 {
AndyA 0:bddb8cd5e7df 878 uint8_t result;
AndyA 0:bddb8cd5e7df 879 readRegister(reg, subaddress, &result, 1);
AndyA 0:bddb8cd5e7df 880 return result;
AndyA 0:bddb8cd5e7df 881 }
AndyA 0:bddb8cd5e7df 882
AndyA 0:bddb8cd5e7df 883 uint16_t DW1000::readRegister16(uint8_t reg, uint16_t subaddress)
AndyA 0:bddb8cd5e7df 884 {
AndyA 0:bddb8cd5e7df 885 uint16_t result;
AndyA 0:bddb8cd5e7df 886 readRegister(reg, subaddress, (uint8_t*)&result, 2);
AndyA 0:bddb8cd5e7df 887 return result;
AndyA 0:bddb8cd5e7df 888 }
AndyA 0:bddb8cd5e7df 889
AndyA 0:bddb8cd5e7df 890 uint32_t DW1000::readRegister32(uint8_t reg, uint16_t subaddress)
AndyA 0:bddb8cd5e7df 891 {
AndyA 0:bddb8cd5e7df 892 uint32_t result;
AndyA 0:bddb8cd5e7df 893 readRegister(reg, subaddress, (uint8_t*)&result, 4);
AndyA 0:bddb8cd5e7df 894 return result;
AndyA 0:bddb8cd5e7df 895 }
AndyA 0:bddb8cd5e7df 896
AndyA 0:bddb8cd5e7df 897
AndyA 0:bddb8cd5e7df 898 uint64_t DW1000::readRegister40(uint8_t reg, uint16_t subaddress)
AndyA 0:bddb8cd5e7df 899 {
AndyA 0:bddb8cd5e7df 900 uint64_t result = 0;
AndyA 0:bddb8cd5e7df 901 readRegister(reg, subaddress, (uint8_t*)&result, 5);
AndyA 0:bddb8cd5e7df 902 return result;
AndyA 0:bddb8cd5e7df 903 }
AndyA 0:bddb8cd5e7df 904 uint64_t DW1000::readRegister64(uint8_t reg, uint16_t subaddress)
AndyA 0:bddb8cd5e7df 905 {
AndyA 0:bddb8cd5e7df 906 uint64_t result;
AndyA 0:bddb8cd5e7df 907 readRegister(reg, subaddress, (uint8_t*)&result, 8);
AndyA 0:bddb8cd5e7df 908 return result;
AndyA 0:bddb8cd5e7df 909 }
AndyA 0:bddb8cd5e7df 910
AndyA 0:bddb8cd5e7df 911 void DW1000::writeRegister8(uint8_t reg, uint16_t subaddress, uint8_t buffer)
AndyA 0:bddb8cd5e7df 912 {
AndyA 0:bddb8cd5e7df 913 writeRegister(reg, subaddress, &buffer, 1);
AndyA 0:bddb8cd5e7df 914 }
AndyA 0:bddb8cd5e7df 915
AndyA 0:bddb8cd5e7df 916 void DW1000::writeRegister16(uint8_t reg, uint16_t subaddress, uint16_t buffer)
AndyA 0:bddb8cd5e7df 917 {
AndyA 0:bddb8cd5e7df 918 writeRegister(reg, subaddress, (uint8_t*)&buffer, 2);
AndyA 0:bddb8cd5e7df 919 }
AndyA 0:bddb8cd5e7df 920
AndyA 0:bddb8cd5e7df 921 void DW1000::writeRegister32(uint8_t reg, uint16_t subaddress, uint32_t buffer)
AndyA 0:bddb8cd5e7df 922 {
AndyA 0:bddb8cd5e7df 923 writeRegister(reg, subaddress, (uint8_t*)&buffer, 4);
AndyA 0:bddb8cd5e7df 924 }
AndyA 0:bddb8cd5e7df 925
AndyA 0:bddb8cd5e7df 926 void DW1000::writeRegister40(uint8_t reg, uint16_t subaddress, uint64_t buffer)
AndyA 0:bddb8cd5e7df 927 {
AndyA 0:bddb8cd5e7df 928 writeRegister(reg, subaddress, (uint8_t*)&buffer, 5);
AndyA 0:bddb8cd5e7df 929 }
AndyA 0:bddb8cd5e7df 930
AndyA 0:bddb8cd5e7df 931 void DW1000::readRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length)
AndyA 0:bddb8cd5e7df 932 {
AndyA 0:bddb8cd5e7df 933 setupTransaction(reg, subaddress, false);
AndyA 0:bddb8cd5e7df 934 for(int i=0; i<length; i++) // get data
AndyA 0:bddb8cd5e7df 935 buffer[i] = spi.write(0x00);
AndyA 0:bddb8cd5e7df 936 deselect();
AndyA 0:bddb8cd5e7df 937 }
AndyA 0:bddb8cd5e7df 938
AndyA 0:bddb8cd5e7df 939 void DW1000::writeRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length)
AndyA 0:bddb8cd5e7df 940 {
AndyA 0:bddb8cd5e7df 941 setupTransaction(reg, subaddress, true);
AndyA 0:bddb8cd5e7df 942 for(int i=0; i<length; i++) // put data
AndyA 0:bddb8cd5e7df 943 spi.write(buffer[i]);
AndyA 0:bddb8cd5e7df 944 deselect();
AndyA 0:bddb8cd5e7df 945 }
AndyA 0:bddb8cd5e7df 946
AndyA 0:bddb8cd5e7df 947 void DW1000::setupTransaction(uint8_t reg, uint16_t subaddress, bool write)
AndyA 0:bddb8cd5e7df 948 {
AndyA 0:bddb8cd5e7df 949 reg |= (write * DW1000_WRITE_FLAG); // set read/write flag
AndyA 0:bddb8cd5e7df 950 select();
AndyA 0:bddb8cd5e7df 951 if (subaddress > 0) { // there's a subadress, we need to set flag and send second header byte
AndyA 0:bddb8cd5e7df 952 spi.write(reg | DW1000_SUBADDRESS_FLAG);
AndyA 0:bddb8cd5e7df 953 if (subaddress > 0x7F) { // sub address too long, we need to set flag and send third header byte
AndyA 0:bddb8cd5e7df 954 spi.write((uint8_t)(subaddress & 0x7F) | DW1000_2_SUBADDRESS_FLAG); // and
AndyA 0:bddb8cd5e7df 955 spi.write((uint8_t)(subaddress >> 7));
AndyA 0:bddb8cd5e7df 956 } else {
AndyA 0:bddb8cd5e7df 957 spi.write((uint8_t)subaddress);
AndyA 0:bddb8cd5e7df 958 }
AndyA 0:bddb8cd5e7df 959 } else {
AndyA 0:bddb8cd5e7df 960 spi.write(reg); // say which register address we want to access
AndyA 0:bddb8cd5e7df 961 }
AndyA 0:bddb8cd5e7df 962 }
AndyA 0:bddb8cd5e7df 963
AndyA 0:bddb8cd5e7df 964 void DW1000::select() // always called to start an SPI transmission
AndyA 0:bddb8cd5e7df 965 {
AndyA 0:bddb8cd5e7df 966 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 967 cs = 0; // set Cable Select pin low to start transmission
AndyA 0:bddb8cd5e7df 968 }
AndyA 0:bddb8cd5e7df 969
AndyA 0:bddb8cd5e7df 970 void DW1000::deselect() // always called to end an SPI transmission
AndyA 0:bddb8cd5e7df 971 {
AndyA 0:bddb8cd5e7df 972 cs = 1; // set Cable Select pin high to stop transmission
AndyA 0:bddb8cd5e7df 973 irq.enable_irq(); // reenable the interrupt handler
AndyA 0:bddb8cd5e7df 974 }