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

Dependencies:   BurstSPI

Committer:
AndyA
Date:
Wed Nov 08 11:15:47 2017 +0000
Revision:
17:1fb08dfef237
Parent:
15:6faab70a5b19
Child:
18:6c2ce1749d4a
Moved applySetup() to public, removed unnecessary include

Who changed what in which revision?

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