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

Dependencies:   BurstSPI

Committer:
AndyA
Date:
Mon Aug 01 08:45:36 2016 +0000
Revision:
10:f1e3c04080d6
Parent:
9:326bf149c8bc
Child:
13:8718966cd81e

        

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