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