├── .DS_Store ├── DW1000.py ├── DW1000Constants.py ├── DW1000DistantDevice.py ├── DW1000Mac.py ├── DW1000Ranging.py ├── DW1000Time.py ├── Examples ├── DW1000RangingAnchor.py ├── DW1000RangingTAG.py ├── PingPong.py ├── Receiver.py └── Sender.py ├── README.md ├── RangingAnchor.py └── RangingTag.py /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedestrian0423/DW1000_Raspi_Python_library/02bfd8bdddf069ba47e0198b8ba7e2568216b536/.DS_Store -------------------------------------------------------------------------------- /DW1000.py: -------------------------------------------------------------------------------- 1 | """ 2 | This python module contains low-level functions to interact 3 | with the DW1000 chip using a Raspberry Pi 3. 4 | It requires the following modules: 5 | math, time, spidev, Rpi.GPIO, random. 6 | """ 7 | import time 8 | import math 9 | from random import randint 10 | import spidev 11 | import RPi.GPIO as GPIO 12 | import DW1000Constants as C 13 | 14 | class DW1000(object): 15 | spi = spidev.SpiDev() 16 | _bus = 0 17 | _device = 0 18 | _ss = 0 19 | 20 | _chipSelect = None 21 | _deviceMode = C.IDLE_MODE 22 | _permanentReceive = False 23 | _operationMode = [None] * 6 24 | # [dataRate, pulseFrequency, pacSize, preambleLength, channel, preacode] 25 | callbacks = {} 26 | 27 | _networkAndAddress = [0] * 4 28 | _sysctrl = [0] * 4 29 | _chanctrl = [0] * 4 30 | _syscfg = [0] * 4 31 | _sysmask = [0] * 4 32 | _txfctrl = [0] * 5 33 | _sysstatus = [0] * 5 34 | 35 | """ 36 | DW1000 general configuration. 37 | """ 38 | def __init__(self, **kwargs): 39 | rst = None 40 | bus = None 41 | device = None 42 | 43 | valid_keys = ["irq", "rst", "bus", "device"] 44 | for key in valid_keys: 45 | self.__dict__[key] = kwargs.get(key) 46 | 47 | self.spi = spidev.SpiDev() 48 | print self.spi 49 | 50 | self.begin(self.irq, self.rst, self.bus, self.device) 51 | 52 | 53 | def __del__(self): 54 | self.close() 55 | 56 | 57 | def begin(self, irq, rst=None, bus=None, device=None): 58 | """ 59 | This function opens the SPI connection available on the Raspberry Pi using the chip select #0. 60 | Normally, spidev can auto enable chip select when necessary. 61 | However, in our case, the dw1000's chip select is connected to GPIO16 so we have to enable/disable it manually. 62 | It also sets up the interrupt detection event on the rising edge of the interrupt pin. 63 | 64 | Args: 65 | irq : The GPIO pin number managing interrupts. 66 | """ 67 | self._bus = 0 68 | self._device = 0 69 | self._rst = None 70 | self._irq = irq 71 | 72 | # Wait 5 us to open spi connection to let the chip enter idle state 73 | # see 2.3.2 of the DW1000 user manual (INIT). 74 | time.sleep(C.INIT_DELAY) 75 | GPIO.setmode(GPIO.BCM) 76 | 77 | if bus is not None: 78 | self._bus = bus 79 | if device is not None: 80 | self._device = device 81 | self.spi.open(self._bus, self._device) 82 | # spi.max_speed_hz = 4000000 83 | self._deviceMode = C.IDLE_MODE 84 | GPIO.setup(self._irq, GPIO.IN, pull_up_down=GPIO.PUD_UP) 85 | 86 | GPIO.add_event_detect(self._irq, GPIO.RISING, callback=self.handleInterrupt) 87 | 88 | # Set reset pin for physical reset 89 | if rst is not None: 90 | self._rst = rst 91 | GPIO.setup(self._rst, GPIO.INPUT) 92 | 93 | 94 | def setup(self, ss): 95 | """ 96 | This function defines the GPIO used for the chip select 97 | by configuring it as an output and by setting its initial state at inactive (HIGH). 98 | It also clears interrupt configuration and performs 99 | a soft reset before applying initial configurations for the chip. 100 | 101 | Args: 102 | ss: The GPIO pin number of the chip enable/select for the SPI bus. 103 | """ 104 | self._chipSelect = ss 105 | GPIO.setup(self._chipSelect, GPIO.OUT) 106 | GPIO.output(self._chipSelect, GPIO.HIGH) 107 | 108 | self.enableClock(C.AUTO_CLOCK) 109 | 110 | self.softReset() 111 | 112 | # Default system configuration 113 | self.setArray(self._syscfg, 4, 0x00) 114 | self.setBit(self._syscfg, 4, C.DIS_DRXB_BIT, True) 115 | self.setBit(self._syscfg, 4, C.HIRQ_POL_BIT, True) 116 | self.writeBytes(C.SYS_CFG, C.NO_SUB, self._syscfg, 4) 117 | 118 | # clear interrupts configuration 119 | self.setArray(self._sysmask, 4, 0x00) 120 | self.writeBytes(C.SYS_MASK, C.NO_SUB, self._sysmask, 4) 121 | 122 | self.enableClock(C.XTI_CLOCK) 123 | self.manageLDE() 124 | self.enableClock(C.AUTO_CLOCK) 125 | 126 | 127 | def handleInterrupt(self, channel): 128 | """ 129 | Callback invoked on the rising edge of the interrupt pin. Handle the configured interruptions. 130 | """ 131 | # print("\nInterrupt!") 132 | self._sysstatus = self.readBytes(C.SYS_STATUS, C.NO_SUB, self._sysstatus, 5) 133 | # print(_sysstatus) 134 | msgReceived = self.getBit(self._sysstatus, 5, C.RXFCG_BIT) 135 | receiveTimeStampAvailable = self.getBit(self._sysstatus, 5, C.LDEDONE_BIT) 136 | transmitDone = self.getBit(self._sysstatus, 5, C.TXFRS_BIT) 137 | if transmitDone: 138 | self.callbacks["handleSent"]() 139 | self.clearTransmitStatus() 140 | if receiveTimeStampAvailable: 141 | self.setBit(self._sysstatus, 5, C.LDEDONE_BIT, True) 142 | self.writeBytes(C.SYS_STATUS, C.NO_SUB, self._sysstatus, 5) 143 | if self.isReceiveFailed(): 144 | self.clearReceiveStatus() 145 | if self._permanentReceive: 146 | self.newReceive() 147 | self.startReceive() 148 | elif self.isReceiveTimeout(): 149 | self.clearReceiveStatus() 150 | if self._permanentReceive: 151 | self.newReceive() 152 | self.startReceive() 153 | elif msgReceived: 154 | self.callbacks["handleReceived"]() 155 | self.clearReceiveStatus() 156 | if self._permanentReceive: 157 | # no need to start a new receive since we enabled the permanent receive mode in the system configuration register. it created an interference causing problem 158 | # with the reception 159 | # newReceive() 160 | self.startReceive() 161 | 162 | self.clearAllStatus() 163 | 164 | 165 | def registerCallback(self, string, callback): 166 | """ 167 | This function saves the callback sent by the script who imports this module for later use. It stores it in a dictionary with the 168 | specified key. 169 | 170 | Args: 171 | string: This is the key used to store the callback in the dictionary. 172 | callback: This is the saved callback. 173 | """ 174 | if callback not in self.callbacks: 175 | self.callbacks[string] = callback 176 | 177 | 178 | def softReset(self): 179 | """ 180 | This function performs a soft reset on the DW1000 chip. 181 | """ 182 | pmscctrl0 = [0] * 4 183 | pmscctrl0 = self.readBytes(C.PMSC, C.PMSC_CTRL0_SUB, pmscctrl0, 4) 184 | pmscctrl0[0] = C.SOFT_RESET_SYSCLKS 185 | self.writeBytes(C.PMSC, C.PMSC_CTRL0_SUB, pmscctrl0, 4) 186 | pmscctrl0[3] = C.SOFT_RESET_CLEAR 187 | self.writeBytes(C.PMSC, C.PMSC_CTRL0_SUB, pmscctrl0, 4) 188 | pmscctrl0[0] = C.SOFT_RESET_CLEAR 189 | pmscctrl0[3] = C.SOFT_RESET_SET 190 | self.writeBytes(C.PMSC, C.PMSC_CTRL0_SUB, pmscctrl0, 4) 191 | self.idle() 192 | 193 | def hardReset(self): 194 | """ 195 | This function performs a hard reset on the DW1000 chip. 196 | """ 197 | GPIO.setup(self._rst, GPIO.output) 198 | GPIO.output(self._rst, GPIO.LOW) 199 | time.sleep(0.002) 200 | GPIO.setup(self._rst, GPIO.input) 201 | time.sleep(0.010) 202 | self.idle() 203 | 204 | 205 | def manageLDE(self): 206 | """ 207 | This function manages the LDE micro-code. It is to setup the power management and system control unit as well as the OTP memory interface. 208 | This is necessary as part of the DW1000 initialisation, since it is important to get timestamp and diagnostic info from received frames. 209 | """ 210 | pmscctrl0 = [None] * 4 211 | otpctrl = [None] * 2 212 | pmscctrl0 = self.readBytes(C.PMSC, C.PMSC_CTRL0_SUB, pmscctrl0, 4) 213 | otpctrl = self.readBytes(C.OTP_IF, C.OTP_CTRL_SUB, otpctrl, 2) 214 | 215 | pmscctrl0[0] = C.LDE_L1STEP1 216 | pmscctrl0[1] = C.LDE_L1STEP2 217 | otpctrl[0] = C.LDE_L2STEP1 218 | otpctrl[1] = C.LDE_L2STEP2 219 | 220 | self.writeBytes(C.PMSC, C.PMSC_CTRL0_SUB, pmscctrl0, 2) 221 | self.writeBytes(C.OTP_IF, C.OTP_CTRL_SUB, otpctrl, 2) 222 | 223 | # wait 150 us before writing the 0x36:00 sub-register, see 2.5.5.10 of the DW1000 user manual. 224 | time.sleep(C.PMSC_CONFIG_DELAY) 225 | 226 | pmscctrl0[0] = C.LDE_L3STEP1 227 | pmscctrl0[1] = C.LDE_L3STEP2 228 | 229 | self.writeBytes(C.PMSC, C.PMSC_CTRL0_SUB, pmscctrl0, 2) 230 | 231 | 232 | def setDefaultConfiguration(self): 233 | """ 234 | This function sets the default mode on the chip initialization : MODE_LONGDATA_RANGE_LOWPOWER and with receive/transmit mask activated when in IDLE mode. 235 | """ 236 | if self._deviceMode == C.TX_MODE: 237 | pass 238 | elif self._deviceMode == C.RX_MODE: 239 | pass 240 | elif self._deviceMode == C.IDLE_MODE: 241 | self._syscfg[2] &= C.ENABLE_MODE_MASK2 242 | self._syscfg[2] |= 0x00 243 | 244 | self.setBit(self._syscfg, 4, C.DIS_STXP_BIT, True) 245 | self.setBit(self._syscfg, 4, C.FFEN_BIT, False) 246 | 247 | # interrupt on sent 248 | self.setBit(self._sysmask, 4, C.MTXFRS_BIT, True) 249 | # interrupt on received 250 | self.setBit(self._sysmask, 4, C.MRXDFR_BIT, True) 251 | self.setBit(self._sysmask, 4, C.MRXFCG_BIT, True) 252 | # interrupt on received failed 253 | self.setBit(self._sysmask, 4, C.MLDEERR_BIT, True) 254 | self.setBit(self._sysmask, 4, C.MRXFCE_BIT, True) 255 | self.setBit(self._sysmask, 4, C.MRXPHE_BIT, True) 256 | self.setBit(self._sysmask, 4, C.MRXRFSL_BIT, True) 257 | # interrupt on receive time stamp available 258 | self.setBit(self._sysmask, 4, C.MLDEDONE_BIT, False) 259 | # interrupt on auto acknowledge trigger 260 | self.setBit(self._sysmask, 4, C.MAAT_BIT, True) 261 | # set receiver auto reenable 262 | self.setBit(self._syscfg, 4, C.RXAUTR_BIT, True) 263 | 264 | self.clearAllStatus() 265 | 266 | self.enableMode(C.MODE_LONGDATA_RANGE_LOWPOWER) 267 | 268 | def enableMode(self, mode): 269 | """ 270 | This function configures the DW1000 chip to perform with a specific mode. It sets up the TRX rate the TX pulse frequency and the preamble length. 271 | """ 272 | 273 | # setDataRate 274 | rate = mode[0] 275 | rate = rate & C.MASK_LS_2BITS 276 | self._txfctrl[1] = self._txfctrl[1] & C.ENABLE_MODE_MASK1 277 | self._txfctrl[1] = self._txfctrl[1] | ((rate << 5) & C.MASK_LS_BYTE) 278 | if rate == C.TRX_RATE_110KBPS: 279 | self.setBit(self._syscfg, 4, C.RXM110K_BIT, True) 280 | else: 281 | self.setBit(self._syscfg, 4, C.RXM110K_BIT, False) 282 | 283 | if rate == C.TRX_RATE_6800KBPS: 284 | self.setBit(self._chanctrl, 4, C.DWSFD_BIT, False) 285 | self.setBit(self._chanctrl, 4, C.TNSSFD_BIT, False) 286 | self.setBit(self._chanctrl, 4, C.RNSSFD_BIT, False) 287 | else: 288 | self.setBit(self._chanctrl, 4, C.DWSFD_BIT, True) 289 | self.setBit(self._chanctrl, 4, C.TNSSFD_BIT, True) 290 | self.setBit(self._chanctrl, 4, C.RNSSFD_BIT, True) 291 | if rate == C.TRX_RATE_850KBPS: 292 | sfdLength = [C.SFD_LENGTH_850KBPS] 293 | elif rate == C.TRX_RATE_6800KBPS: 294 | sfdLength = [C.SFD_LENGTH_6800KBPS] 295 | else: 296 | sfdLength = [C.SFD_LENGTH_OTHER] 297 | self.writeBytes(C.USR_SFD, C.SFD_LENGTH_SUB, sfdLength, 1) 298 | self._operationMode[C.DATA_RATE_BIT] = rate 299 | 300 | # setPulseFreq 301 | freq = mode[1] 302 | freq = freq & C.MASK_LS_2BITS 303 | self._txfctrl[2] = self._txfctrl[2] & C.ENABLE_MODE_MASK2 304 | self._txfctrl[2] = self._txfctrl[2] | (freq & C.MASK_LS_BYTE) 305 | self._chanctrl[2] = self._chanctrl[2] & C.ENABLE_MODE_MASK3 306 | self._chanctrl[2] = self._chanctrl[2] | ((freq << 2) & C.MASK_LS_BYTE) 307 | self._operationMode[C.PULSE_FREQUENCY_BIT] = freq 308 | 309 | # setPreambleLength 310 | prealen = mode[2] 311 | prealen = prealen & C.MASK_NIBBLE 312 | self._txfctrl[2] = self._txfctrl[2] & C.ENABLE_MODE_MASK4 313 | self._txfctrl[2] = self._txfctrl[2] | ((prealen << 2) & C.MASK_LS_BYTE) 314 | if prealen == C.TX_PREAMBLE_LEN_64 or prealen == C.TX_PREAMBLE_LEN_128: 315 | self._operationMode[C.PAC_SIZE_BIT] = C.PAC_SIZE_8 316 | elif prealen == C.TX_PREAMBLE_LEN_256 or prealen == C.TX_PREAMBLE_LEN_512: 317 | self._operationMode[C.PAC_SIZE_BIT] = C.PAC_SIZE_16 318 | elif prealen == C.TX_PREAMBLE_LEN_1024: 319 | self._operationMode[C.PAC_SIZE_BIT] = C.PAC_SIZE_32 320 | else: 321 | self._operationMode[C.PAC_SIZE_BIT] = C.PAC_SIZE_64 322 | self._operationMode[C.PREAMBLE_LENGTH_BIT] = prealen 323 | 324 | # setChannel 325 | self.setChannel(C.CHANNEL_5) 326 | 327 | # setPreambleCode 328 | if mode[1] == C.TX_PULSE_FREQ_16MHZ: 329 | self.setPreambleCode(C.PREAMBLE_CODE_16MHZ_4) 330 | else: 331 | self.setPreambleCode(C.PREAMBLE_CODE_64MHZ_10) 332 | 333 | def newConfiguration(self): 334 | """ 335 | This function resets the DW1000 chip to the idle state mode and reads all the configuration registers to prepare for a new configuration. 336 | """ 337 | self.idle() 338 | self._networkAndAddress = self.readBytes(C.PANADR, C.NO_SUB, self._networkAndAddress, 4) 339 | self._syscfg = self.readBytes(C.SYS_CFG, C.NO_SUB, self._syscfg, 4) 340 | self._chanctrl = self.readBytes(C.CHAN_CTRL, C.NO_SUB, self._chanctrl, 4) 341 | self._txfctrl = self.readBytes(C.TX_FCTRL, C.NO_SUB, self._txfctrl, 5) 342 | self._sysmask = self.readBytes(C.SYS_MASK, C.NO_SUB, self._sysmask, 4) 343 | 344 | def commitConfiguration(self): 345 | """ 346 | This function commits the configuration stored in the arrays previously filled. It writes into the corresponding registers to apply the changes to the DW1000 chip. 347 | It also tunes the chip according to the current enabled mode. 348 | """ 349 | self.writeBytes(C.PANADR, C.NO_SUB, self._networkAndAddress, 4) 350 | self.writeBytes(C.SYS_CFG, C.NO_SUB, self._syscfg, 4) 351 | self.writeBytes(C.CHAN_CTRL, C.NO_SUB, self._chanctrl, 4) 352 | self.writeBytes(C.TX_FCTRL, C.NO_SUB, self._txfctrl, 5) 353 | self.writeBytes(C.SYS_MASK, C.NO_SUB, self._sysmask, 4) 354 | 355 | self.tune() 356 | 357 | 358 | def setAntennaDelay(self, val): 359 | """ 360 | This function sets the DW1000 chip's antenna delay value which needs to be calibrated to have better ranging accuracy. 361 | 362 | Args: 363 | val : The antenna delay value which will be configured into the chip. 364 | """ 365 | antennaDelayBytes = [None] * 5 366 | self.writeValueToBytes(antennaDelayBytes, val, 5) 367 | self.writeBytes(C.TX_ANTD, C.NO_SUB, antennaDelayBytes, 2) 368 | self.writeBytes(C.LDE_CTRL, C.LDE_RXANTD_SUB, antennaDelayBytes, 2) 369 | 370 | 371 | def setEUI(self, currentAddress): 372 | """ 373 | This function sets the extended unique identifier of the chip according to the value specified by the user in setup. 374 | 375 | Args: 376 | currentAddress : the array of bytes containing the EUI 377 | """ 378 | reverseEUI = [0] * 8 379 | for i in range(0, 8): 380 | reverseEUI[i] = currentAddress[8 - i - 1] 381 | self.writeBytes(C.EUI, C.NO_SUB, reverseEUI, 8) 382 | 383 | 384 | def setDeviceAddress(self, value): 385 | """ 386 | This function sets the device's address according to the specified value. 387 | 388 | Args: 389 | value : The address you want to set to the chip. 390 | """ 391 | self._networkAndAddress[0] = value & C.MASK_LS_BYTE 392 | self._networkAndAddress[1] = (value >> 8) & C.MASK_LS_BYTE 393 | 394 | 395 | def setNetworkId(self, value): 396 | """ 397 | This function sets the device's network ID according to the specified value. 398 | 399 | Args: 400 | value : The network id you want to assign to the chip. 401 | """ 402 | self._networkAndAddress[2] = value & C.MASK_LS_BYTE 403 | self._networkAndAddress[3] = (value >> 8) & C.MASK_LS_BYTE 404 | 405 | 406 | def setChannel(self, channel): 407 | """ 408 | This function configures the DW1000 chip to enable a the specified channel of operation. 409 | 410 | Args: 411 | channel : The channel value you want to assign to the chip. 412 | """ 413 | channel = channel & C.MASK_NIBBLE 414 | self._chanctrl[0] = ((channel | (channel << 4)) & C.MASK_LS_BYTE) 415 | self._operationMode[C.CHANNEL_BIT] = channel 416 | 417 | 418 | def setPreambleCode(self, preacode): 419 | """ 420 | This function sets the preamble code used for the frames, depending on the the pulse repetition frequency and the channel used. 421 | 422 | Args: 423 | preacode : The preamble code type you want to assign to the chip. 424 | """ 425 | preacode = preacode & C.PREACODE_MASK1 426 | self._chanctrl[2] = self._chanctrl[2] & C.PREACODE_MASK2 427 | self._chanctrl[2] = self._chanctrl[2] | ((preacode << 6) & C.MASK_LS_BYTE) 428 | self._chanctrl[3] = 0x00 429 | self._chanctrl[3] = ((((preacode >> 2) & C.PREACODE_MASK3) | 430 | (preacode << 3)) & C.MASK_LS_BYTE) 431 | self._operationMode[C.PREAMBLE_CODE_BIT] = preacode 432 | 433 | 434 | def tune(self): 435 | """ 436 | This function tunes/configures dw1000 chip's registers according to the enabled mode. Although the DW1000 will power up in a usable mode for the default configuration, 437 | some of the register defaults are sub optimal and should be overwritten before using the chip in the default mode. See 2.5.5 of the user manual. 438 | """ 439 | agctune1 = [None] * 2 440 | agctune2 = [None] * 4 441 | agctune3 = [None] * 2 442 | drxtune0b = [None] * 2 443 | drxtune1a = [None] * 2 444 | drxtune1b = [None] * 2 445 | drxtune2 = [None] * 4 446 | drxtune4H = [None] * 2 447 | rfrxctrlh = [None] * 1 448 | rftxctrl = [None] * 4 449 | tcpgdelay = [None] * 1 450 | fspllcfg = [None] * 4 451 | fsplltune = [None] * 1 452 | ldecfg1 = [None] * 1 453 | ldecfg2 = [None] * 2 454 | lderepc = [None] * 2 455 | txpower = [None] * 4 456 | fsxtalt = [None] * 1 457 | preambleLength = self._operationMode[C.PREAMBLE_LENGTH_BIT] 458 | channel = self._operationMode[C.CHANNEL_BIT] 459 | 460 | self.tuneAgcTune1(agctune1) 461 | self.writeValueToBytes(agctune2, C.AGC_TUNE2_OP, 4) 462 | self.writeValueToBytes(agctune3, C.AGC_TUNE3_OP, 2) 463 | self.tuneDrxTune0b(drxtune0b) 464 | self.tuneDrxTune1aAndldecfg2(drxtune1a, ldecfg2) 465 | self.tuneDrxtune1b(drxtune1b) 466 | self.tuneDrxTune2(drxtune2) 467 | 468 | if preambleLength == C.TX_PREAMBLE_LEN_64: 469 | self.writeValueToBytes(drxtune4H, C.DRX_TUNE4H_64, 2) 470 | else: 471 | self.writeValueToBytes(drxtune4H, C.DRX_TUNE4H_128, 2) 472 | 473 | if (channel != C.CHANNEL_4 and channel != C.CHANNEL_7): 474 | self.writeValueToBytes(rfrxctrlh, C.RF_RXCTRLH_1235, 1) 475 | else: 476 | self.writeValueToBytes(rfrxctrlh, C.RF_RXCTRLH_147, 1) 477 | 478 | self.tuneAccToChan(rftxctrl, tcpgdelay, fspllcfg, fsplltune, txpower) 479 | 480 | self.writeValueToBytes(ldecfg1, C.LDE_CFG1_OP, 1) 481 | self.tunelderepc(lderepc) 482 | 483 | buf_otp = [None] * 4 484 | buf_otp = self.readBytesOTP(C.OTP_XTAL_ADDRESS, buf_otp) 485 | if buf_otp[0] == 0: 486 | self.writeValueToBytes( 487 | fsxtalt, ((C.TUNE_OPERATION & C.TUNE_MASK1) | C.TUNE_MASK2), 1) 488 | else: 489 | self.writeValueToBytes( 490 | fsxtalt, ((buf_otp[0] & C.TUNE_MASK1) | C.TUNE_MASK2), 1) 491 | 492 | self.writeBytes(C.AGC_CTRL, C.AGC_TUNE1_SUB, agctune1, 2) 493 | self.writeBytes(C.AGC_CTRL, C.AGC_TUNE2_SUB, agctune2, 4) 494 | self.writeBytes(C.AGC_CTRL, C.AGC_TUNE3_SUB, agctune3, 2) 495 | self.writeBytes(C.DRX_CONF, C.DRX_TUNE0b_SUB, drxtune0b, 2) 496 | self.writeBytes(C.DRX_CONF, C.DRX_TUNE1a_SUB, drxtune1a, 2) 497 | self.writeBytes(C.DRX_CONF, C.DRX_TUNE1b_SUB, drxtune1b, 2) 498 | self.writeBytes(C.DRX_CONF, C.DRX_TUNE2_SUB, drxtune2, 4) 499 | self.writeBytes(C.DRX_CONF, C.DRX_TUNE4H_SUB, drxtune4H, 2) 500 | self.writeBytes(C.LDE_CTRL, C.LDE_CFG1_SUB, ldecfg1, 1) 501 | self.writeBytes(C.LDE_CTRL, C.LDE_CFG2_SUB, ldecfg2, 2) 502 | self.writeBytes(C.LDE_CTRL, C.LDE_REPC_SUB, lderepc, 2) 503 | self.writeBytes(C.TX_POWER, C.NO_SUB, txpower, 4) 504 | self.writeBytes(C.RF_CONF, C.RF_RXCTRLH_SUB, rfrxctrlh, 1) 505 | self.writeBytes(C.RF_CONF, C.RF_TXCTRL_SUB, rftxctrl, 4) 506 | self.writeBytes(C.TX_CAL, C.TC_PGDELAY_SUB, tcpgdelay, 1) 507 | self.writeBytes(C.FS_CTRL, C.FS_PLLTUNE_SUB, fsplltune, 1) 508 | self.writeBytes(C.FS_CTRL, C.FS_PLLCFG_SUB, fspllcfg, 4) 509 | self.writeBytes(C.FS_CTRL, C.FS_XTALT_SUB, fsxtalt, 1) 510 | 511 | 512 | def generalConfiguration(self, address, mode): 513 | """ 514 | This function configures the DW1000 chip with general settings. It also defines the address and the network ID used by the device. It finally prints the 515 | configured device. 516 | 517 | Args: 518 | address: The string address you want to set the device to. 519 | """ 520 | currentAddress = self.convertStringToByte(address) 521 | currentShortAddress = [0] * 2 522 | self.setEUI(currentAddress) 523 | currentShortAddress[0] = randint(0, 256) 524 | currentShortAddress[1] = randint(0, 256) 525 | deviceAddress = currentShortAddress[0] * 256 + currentShortAddress[1] 526 | 527 | # configure mode, network 528 | self.newConfiguration() 529 | self.setDefaultConfiguration() 530 | # setDeviceAddress(2) 531 | self.setDeviceAddress(deviceAddress) 532 | # setNetworkId(10) 533 | self.setNetworkId(0xDECA) 534 | self.enableMode(mode) 535 | self.setAntennaDelay(C.ANTENNA_DELAY) 536 | self.commitConfiguration() 537 | 538 | data = [0] * 4 539 | data2 = [0] * 8 540 | data3 = [0] * 4 541 | data = self.readBytes(C.DEV_ID, C.NO_SUB, data, 4) 542 | data2 = self.readBytes(C.EUI, C.NO_SUB, data2, 8) 543 | data3 = self.readBytes(C.PANADR, C.NO_SUB, data3, 4) 544 | print("\nDevice ID %02X - model: %d, version: %d, revision: %d" % 545 | ((data[3] << 8) | data[2], (data[1]), (data[0] >> 4) & C.MASK_NIBBLE, data[0] & C.MASK_NIBBLE)) 546 | print("Unique ID: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X" % ( 547 | data2[7], data2[6], data2[5], data2[4], data2[3], data2[2], data2[1], data2[0])) 548 | print("Network ID & Device Address: PAN: %02X, Short Address: %02X" % 549 | (((data3[3] << 8) | data3[2]), ((data3[1] << 8) | data3[0]))) 550 | self.getDeviceModeInfo() 551 | 552 | 553 | """ 554 | Tuning functions 555 | See tune() for more information 556 | """ 557 | 558 | 559 | def tuneAgcTune1(self, data): 560 | """ 561 | This function fills the array for the tuning of agctune1 according to the datasheet and the enabled mode. 562 | 563 | Args: 564 | data: The array which will store the correct values for agctune1. 565 | 566 | """ 567 | pulseFrequency = self._operationMode[C.PULSE_FREQUENCY_BIT] 568 | if pulseFrequency == C.TX_PULSE_FREQ_16MHZ: 569 | self.writeValueToBytes(data, C.AGC_TUNE1_16MHZ_OP, 2) 570 | elif pulseFrequency == C.TX_PULSE_FREQ_64MHZ: 571 | self.writeValueToBytes(data, C.AGC_TUNE1_DEFAULT_OP, 2) 572 | 573 | 574 | def tuneDrxTune0b(self, data): 575 | """ 576 | This function fills the array for the tuning of drxtune0b according to the datasheet and the enabled mode. 577 | 578 | Args: 579 | data: The array which will store the correct values for drxtune0b. 580 | """ 581 | dataRate = self._operationMode[C.DATA_RATE_BIT] 582 | if dataRate == C.TRX_RATE_110KBPS: 583 | self.writeValueToBytes(data, C.DRX_TUNE0b_110KBPS_NOSTD_OP, 2) 584 | elif dataRate == C.TRX_RATE_850KBPS: 585 | self.writeValueToBytes(data, C.DRX_TUNE0b_850KBPS_NOSTD_OP, 2) 586 | elif dataRate == C.TRX_RATE_6800KBPS: 587 | self.writeValueToBytes(data, C.DRX_TUNE0b_6800KBPS_STD_OP, 2) 588 | 589 | 590 | def tuneDrxTune1aAndldecfg2(self, data, data2): 591 | """ 592 | This function fills the array for the tuning of drxtune1a and ldecfg2 according to the datasheet and the enabled mode. 593 | 594 | Args: 595 | data: The array which will store the correct values for the drxtune1a. 596 | data2: The array which will store the correct values for ldecfg2. 597 | """ 598 | pulseFrequency = self._operationMode[C.PULSE_FREQUENCY_BIT] 599 | if pulseFrequency == C.TX_PULSE_FREQ_16MHZ: 600 | self.writeValueToBytes(data, C.DRX_TUNE1a_16MHZ_OP, 2) 601 | self.writeValueToBytes(data2, C.LDE_CFG2_16MHZ_OP, 2) 602 | elif pulseFrequency == C.TX_PULSE_FREQ_64MHZ: 603 | self.writeValueToBytes(data, C.DRX_TUNE1a_64MHZ_OP, 2) 604 | self.writeValueToBytes(data2, C.LDE_CFG2_64MHZ_OP, 2) 605 | 606 | 607 | def tuneDrxtune1b(self, data): 608 | """ 609 | This function fills the array for the tuning of drxtune1b according to the datasheet and the enabled mode. 610 | 611 | Args: 612 | data: The array which will store the correct values for drxtune1b. 613 | """ 614 | dataRate = self._operationMode[C.DATA_RATE_BIT] 615 | preambleLength = self._operationMode[C.PREAMBLE_LENGTH_BIT] 616 | if (preambleLength == C.TX_PREAMBLE_LEN_1536 or preambleLength == C.TX_PREAMBLE_LEN_2048 or preambleLength == C.TX_PREAMBLE_LEN_4096): 617 | if (dataRate == C.TRX_RATE_110KBPS): 618 | self.writeValueToBytes(data, C.DRX_TUNE1b_M1024, 2) 619 | elif preambleLength != C.TX_PREAMBLE_LEN_64: 620 | if (dataRate == C.TRX_RATE_850KBPS or dataRate == C.TRX_RATE_6800KBPS): 621 | self.writeValueToBytes(data, C.DRX_TUNE1b_L1024, 2) 622 | else: 623 | if dataRate == C.TRX_RATE_6800KBPS: 624 | self.writeValueToBytes(data, C.DRX_TUNE1b_64, 2) 625 | 626 | 627 | def tuneDrxTune2(self, data): 628 | """ 629 | This function fills the array for the tuning of drxtune2 according to the datasheet and the enabled mode. 630 | 631 | Args: 632 | data: The array which will store the correct values for drxtune2. 633 | """ 634 | pacSize = self._operationMode[C.PAC_SIZE_BIT] 635 | pulseFrequency = self._operationMode[C.PULSE_FREQUENCY_BIT] 636 | if pacSize == C.PAC_SIZE_8: 637 | if pulseFrequency == C.TX_PULSE_FREQ_16MHZ: 638 | self.writeValueToBytes(data, C.DRX_TUNE2_8_16MHZ, 4) 639 | elif pulseFrequency == C.TX_PULSE_FREQ_64MHZ: 640 | self.writeValueToBytes(data, C.DRX_TUNE2_8_64MHZ, 4) 641 | elif pacSize == C.PAC_SIZE_16: 642 | if pulseFrequency == C.TX_PULSE_FREQ_16MHZ: 643 | self.writeValueToBytes(data, C.DRX_TUNE2_16_16MHZ, 4) 644 | elif pulseFrequency == C.TX_PULSE_FREQ_64MHZ: 645 | self.writeValueToBytes(data, C.DRX_TUNE2_16_64MHZ, 4) 646 | elif pacSize == C.PAC_SIZE_32: 647 | if pulseFrequency == C.TX_PULSE_FREQ_16MHZ: 648 | self.writeValueToBytes(data, C.DRX_TUNE2_32_16MHZ, 4) 649 | elif pulseFrequency == C.TX_PULSE_FREQ_64MHZ: 650 | self.writeValueToBytes(data, C.DRX_TUNE2_32_64MHZ, 4) 651 | elif pacSize == C.PAC_SIZE_64: 652 | if pulseFrequency == C.TX_PULSE_FREQ_16MHZ: 653 | self.writeValueToBytes(data, C.DRX_TUNE2_64_16MHZ, 4) 654 | elif pulseFrequency == C.TX_PULSE_FREQ_64MHZ: 655 | self.writeValueToBytes(data, C.DRX_TUNE2_64_64MHZ, 4) 656 | 657 | 658 | def tuneAccToChan(self, rftxctrl, tcpgdelay, fspllcfg, fsplltune, txpower): 659 | """ 660 | This function fills the arrays for the tuning of rftxctrl, tcpgdelay, fspllcfg, fsplltune and txpower according to the datasheet and the enabled mode. 661 | """ 662 | channel = self._operationMode[C.CHANNEL_BIT] 663 | pulseFrequency = self._operationMode[C.PULSE_FREQUENCY_BIT] 664 | if channel == C.CHANNEL_1: 665 | self.writeValueToBytes(rftxctrl, C.RF_TXCTRL_1, 4) 666 | self.writeValueToBytes(tcpgdelay, C.TC_PGDELAY_1, 1) 667 | self.writeValueToBytes(fspllcfg, C.FS_PLLCFG_1, 4) 668 | self.writeValueToBytes(fsplltune, C.FS_PLLTUNE_1, 1) 669 | if pulseFrequency == C.TX_PULSE_FREQ_16MHZ: 670 | self.writeValueToBytes(txpower, C.TX_POWER_12_16MHZ, 4) 671 | elif pulseFrequency == C.TX_PULSE_FREQ_64MHZ: 672 | self.writeValueToBytes(txpower, C.TX_POWER_12_64MHZ, 4) 673 | elif channel == C.CHANNEL_2: 674 | self.writeValueToBytes(rftxctrl, C.RF_TXCTRL_2, 4) 675 | self.writeValueToBytes(tcpgdelay, C.TC_PGDELAY_2, 1) 676 | self.writeValueToBytes(fspllcfg, C.FS_PLLCFG_24, 4) 677 | self.writeValueToBytes(fsplltune, C.FS_PLLTUNE_24, 1) 678 | if pulseFrequency == C.TX_PULSE_FREQ_16MHZ: 679 | self.writeValueToBytes(txpower, C.TX_POWER_12_16MHZ, 4) 680 | elif pulseFrequency == C.TX_PULSE_FREQ_64MHZ: 681 | self.writeValueToBytes(txpower, C.TX_POWER_12_64MHZ, 4) 682 | elif channel == C.CHANNEL_3: 683 | self.writeValueToBytes(rftxctrl, C.RF_TXCTRL_3, 4) 684 | self.writeValueToBytes(tcpgdelay, C.TC_PGDELAY_3, 1) 685 | self.writeValueToBytes(fspllcfg, C.FS_PLLCFG_3, 4) 686 | self.writeValueToBytes(fsplltune, C.FS_PLLTUNE_3, 1) 687 | if pulseFrequency == C.TX_PULSE_FREQ_16MHZ: 688 | self.writeValueToBytes(txpower, C.TX_POWER_3_16MHZ, 4) 689 | elif pulseFrequency == C.TX_PULSE_FREQ_64MHZ: 690 | self.writeValueToBytes(txpower, C.TX_POWER_3_64MHZ, 4) 691 | elif channel == C.CHANNEL_4: 692 | self.writeValueToBytes(rftxctrl, C.RF_TXCTRL_4, 4) 693 | self.writeValueToBytes(tcpgdelay, C.TC_PGDELAY_4, 1) 694 | self.writeValueToBytes(fspllcfg, C.FS_PLLCFG_24, 4) 695 | self.writeValueToBytes(fsplltune, C.FS_PLLTUNE_24, 1) 696 | if pulseFrequency == C.TX_PULSE_FREQ_16MHZ: 697 | self.writeValueToBytes(txpower, C.TX_POWER_4_16MHZ, 4) 698 | elif pulseFrequency == C.TX_PULSE_FREQ_64MHZ: 699 | self.writeValueToBytes(txpower, C.TX_POWER_4_64MHZ, 4) 700 | elif channel == C.CHANNEL_5: 701 | self.writeValueToBytes(rftxctrl, C.RF_TXCTRL_5, 4) 702 | self.writeValueToBytes(tcpgdelay, C.TC_PGDELAY_5, 1) 703 | self.writeValueToBytes(fspllcfg, C.FS_PLLCFG_57, 4) 704 | self.writeValueToBytes(fsplltune, C.FS_PLLTUNE_57, 1) 705 | if pulseFrequency == C.TX_PULSE_FREQ_16MHZ: 706 | self.writeValueToBytes(txpower, C.TX_POWER_5_16MHZ, 4) 707 | elif pulseFrequency == C.TX_PULSE_FREQ_64MHZ: 708 | self.writeValueToBytes(txpower, C.TX_POWER_5_64MHZ, 4) 709 | elif channel == C.CHANNEL_7: 710 | self.writeValueToBytes(rftxctrl, C.RF_TXCTRL_7, 4) 711 | self.writeValueToBytes(tcpgdelay, C.TC_PGDELAY_7, 1) 712 | self.writeValueToBytes(fspllcfg, C.FS_PLLCFG_57, 4) 713 | self.writeValueToBytes(fsplltune, C.FS_PLLTUNE_57, 1) 714 | if pulseFrequency == C.TX_PULSE_FREQ_16MHZ: 715 | self.writeValueToBytes(txpower, C.TX_POWER_7_16MHZ, 4) 716 | elif pulseFrequency == C.TX_PULSE_FREQ_64MHZ: 717 | self.writeValueToBytes(txpower, C.TX_POWER_7_64MHZ, 4) 718 | 719 | 720 | def tunelderepc(self, data): 721 | """ 722 | This function fills the arrays for the tuning of lderepc according to the datasheet and the enabled mode. 723 | 724 | Args: 725 | data: The array which will store the correct values for lderepC. 726 | """ 727 | preacode = self._operationMode[C.PREAMBLE_CODE_BIT] 728 | dataRate = self._operationMode[C.DATA_RATE_BIT] 729 | if (preacode == C.PREAMBLE_CODE_16MHZ_1 or preacode == C.PREAMBLE_CODE_16MHZ_2): 730 | if dataRate == C.TRX_RATE_110KBPS: 731 | self.writeValueToBytes( 732 | data, ((C.LDE_REPC_1AND2 >> 3) & C.MASK_LS_2BYTES), 2) 733 | else: 734 | self.writeValueToBytes(data, C.LDE_REPC_1AND2, 2) 735 | elif (preacode == C.PREAMBLE_CODE_16MHZ_3 or preacode == C.PREAMBLE_CODE_16MHZ_8): 736 | if dataRate == C.TRX_RATE_110KBPS: 737 | self.writeValueToBytes( 738 | data, ((C.LDE_REPC_3AND8 >> 3) & C.MASK_LS_2BYTES), 2) 739 | else: 740 | self.writeValueToBytes(data, C.LDE_REPC_3, 2) 741 | elif preacode == C.PREAMBLE_CODE_16MHZ_4: 742 | if dataRate == C.TRX_RATE_110KBPS: 743 | self.writeValueToBytes( 744 | data, ((C.LDE_REPC_4 >> 3) & C.MASK_LS_2BYTES), 2) 745 | else: 746 | self.writeValueToBytes(data, C.LDE_REPC_4, 2) 747 | elif preacode == C.PREAMBLE_CODE_16MHZ_5: 748 | if dataRate == C.TRX_RATE_110KBPS: 749 | self.writeValueToBytes( 750 | data, ((C.LDE_REPC_5 >> 3) & C.MASK_LS_2BYTES), 2) 751 | else: 752 | self.writeValueToBytes(data, C.LDE_REPC_5, 2) 753 | elif preacode == C.PREAMBLE_CODE_16MHZ_6: 754 | if dataRate == C.TRX_RATE_110KBPS: 755 | self.writeValueToBytes( 756 | data, ((C.LDE_REPC_6 >> 3) & C.MASK_LS_2BYTES), 2) 757 | else: 758 | self.writeValueToBytes(data, C.LDE_REPC_6, 2) 759 | elif preacode == C.PREAMBLE_CODE_16MHZ_7: 760 | if dataRate == C.TRX_RATE_110KBPS: 761 | self.writeValueToBytes( 762 | data, ((C.LDE_REPC_7 >> 3) & C.MASK_LS_2BYTES), 2) 763 | else: 764 | self.writeValueToBytes(data, C.LDE_REPC_7, 2) 765 | elif preacode == C.PREAMBLE_CODE_64MHZ_9: 766 | if dataRate == C.TRX_RATE_110KBPS: 767 | self.writeValueToBytes( 768 | data, ((C.LDE_REPC_9 >> 3) & C.MASK_LS_2BYTES), 2) 769 | else: 770 | self.writeValueToBytes(data, C.LDE_REPC_9, 2) 771 | elif preacode == C.PREAMBLE_CODE_64MHZ_10 or preacode == C.PREAMBLE_CODE_64MHZ_17: 772 | if dataRate == C.TRX_RATE_110KBPS: 773 | self.writeValueToBytes( 774 | data, ((C.LDE_REPC_1017 >> 3) & C.MASK_LS_2BYTES), 2) 775 | else: 776 | self.writeValueToBytes(data, C.LDE_REPC_1017, 2) 777 | elif preacode == C.PREAMBLE_CODE_64MHZ_11: 778 | if dataRate == C.TRX_RATE_110KBPS: 779 | self.writeValueToBytes( 780 | data, ((C.LDE_REPC_111321 >> 3) & C.MASK_LS_2BYTES), 2) 781 | else: 782 | self.writeValueToBytes(data, C.LDE_REPC_111321, 2) 783 | elif preacode == C.PREAMBLE_CODE_64MHZ_12: 784 | if dataRate == C.TRX_RATE_110KBPS: 785 | self.writeValueToBytes( 786 | data, ((C.LDE_REPC_12 >> 3) & C.MASK_LS_2BYTES), 2) 787 | else: 788 | self.writeValueToBytes(data, C.LDE_REPC_12, 2) 789 | elif preacode == C.PREAMBLE_CODE_64MHZ_18 or preacode == C.PREAMBLE_CODE_64MHZ_19: 790 | if dataRate == C.TRX_RATE_110KBPS: 791 | self.writeValueToBytes( 792 | data, ((C.LDE_REPC_14161819 >> 3) & C.MASK_LS_2BYTES), 2) 793 | else: 794 | self.writeValueToBytes(data, C.LDE_REPC_14161819, 2) 795 | elif preacode == C.PREAMBLE_CODE_64MHZ_20: 796 | if dataRate == C.TRX_RATE_110KBPS: 797 | self.writeValueToBytes( 798 | data, ((C.LDE_REPC_20 >> 3) & C.MASK_LS_2BYTES), 2) 799 | else: 800 | self.writeValueToBytes(data, C.LDE_REPC_20, 2) 801 | 802 | 803 | def enableClock(self, clock): 804 | """ 805 | This function manages the dw1000 chip's clock by setting up the proper registers to activate the specified clock mode chosen. 806 | 807 | Args: 808 | clock: An hex value corresponding to the clock mode wanted: 809 | AUTO=0x00 810 | XTI=0x01 811 | PLL=0X02. 812 | """ 813 | pmscctrl0 = [None] * 4 814 | pmscctrl0 = self.readBytes(C.PMSC, C.PMSC_CTRL0_SUB, pmscctrl0, 4) 815 | if clock == C.AUTO_CLOCK: 816 | pmscctrl0[0] = C.AUTO_CLOCK 817 | pmscctrl0[1] = pmscctrl0[1] & C.ENABLE_CLOCK_MASK1 818 | elif clock == C.XTI_CLOCK: 819 | pmscctrl0[0] = pmscctrl0[0] & C.ENABLE_CLOCK_MASK2 820 | pmscctrl0[0] = pmscctrl0[0] | 1 821 | self.writeBytes(C.PMSC, C.PMSC_CTRL0_SUB, pmscctrl0, 2) 822 | 823 | 824 | def idle(self): 825 | """ 826 | This function puts the chip into idle mode. 827 | """ 828 | self.setArray(self._sysctrl, 4, 0x00) 829 | self.setBit(self._sysctrl, 4, C.TRXOFF_BIT, True) 830 | self._deviceMode = C.IDLE_MODE 831 | self.writeBytes(C.SYS_CTRL, C.NO_SUB, self._sysctrl, 4) 832 | 833 | 834 | """ 835 | Message reception functions. 836 | """ 837 | 838 | 839 | def newReceive(self): 840 | """ 841 | This function prepares the chip for a new reception. It clears the system control register and also clear the RX latched bits in the SYS_STATUS register. 842 | """ 843 | self.idle() 844 | self.setArray(self._sysctrl, 4, 0x00) 845 | self.clearReceiveStatus() 846 | self._deviceMode = C.RX_MODE 847 | 848 | 849 | def startReceive(self): 850 | """ 851 | This function configures the chip to start the reception of a message sent by another DW1000 chip. 852 | It turns on its receiver by setting RXENAB in the system control register. 853 | """ 854 | self.setBit(self._sysctrl, 4, C.SFCST_BIT, False) 855 | self.setBit(self._sysctrl, 4, C.RXENAB_BIT, True) 856 | self.writeBytes(C.SYS_CTRL, C.NO_SUB, self._sysctrl, 4) 857 | 858 | 859 | def receivePermanently(self): 860 | """ 861 | This function configures the dw1000 chip to receive data permanently. 862 | """ 863 | self._permanentReceive = True 864 | self.setBit(self._syscfg, 4, C.RXAUTR_BIT, True) 865 | self.writeBytes(C.SYS_CFG, C.NO_SUB, self._syscfg, 4) 866 | 867 | 868 | def isReceiveFailed(self): 869 | """ 870 | This function reads the system event status register and checks if the message reception failed. 871 | 872 | Returns: 873 | True if the reception failed. 874 | False otherwise. 875 | """ 876 | ldeErr = self.getBit(self._sysstatus, 5, C.LDEERR_BIT) 877 | rxCRCErr = self.getBit(self._sysstatus, 5, C.RXFCE_BIT) 878 | rxHeaderErr = self.getBit(self._sysstatus, 5, C.RXPHE_BIT) 879 | rxDecodeErr = self.getBit(self._sysstatus, 5, C.RXRFSL_BIT) 880 | if ldeErr or rxCRCErr or rxHeaderErr or rxDecodeErr: 881 | return True 882 | else: 883 | return False 884 | 885 | 886 | def isReceiveTimeout(self): 887 | """ 888 | This function reads the system event status register and checks if there was a timeout in the message reception. 889 | 890 | Returns: 891 | True if there was a timeout in the reception. 892 | False otherwise. 893 | """ 894 | isTimeout = self.getBit(self._sysstatus, 5, C.RXRFTO_BIT) | self.getBit( 895 | self._sysstatus, 5, C.RXPTO_BIT) | self.getBit(self._sysstatus, 5, C.RXSFDTO_BIT) 896 | return isTimeout 897 | 898 | 899 | def clearReceiveStatus(self): 900 | """ 901 | This function clears the system event status register at the bits related to the reception of a message. 902 | """ 903 | self.setBit(self._sysstatus, 5, C.RXDFR_BIT, True) 904 | self.setBit(self._sysstatus, 5, C.LDEDONE_BIT, True) 905 | self.setBit(self._sysstatus, 5, C.LDEERR_BIT, True) 906 | self.setBit(self._sysstatus, 5, C.RXPHE_BIT, True) 907 | self.setBit(self._sysstatus, 5, C.RXFCE_BIT, True) 908 | self.setBit(self._sysstatus, 5, C.RXFCG_BIT, True) 909 | self.setBit(self._sysstatus, 5, C.RXRFSL_BIT, True) 910 | 911 | self.writeBytes(C.SYS_STATUS, C.NO_SUB, self._sysstatus, 5) 912 | 913 | 914 | def getFirstPathPower(self): 915 | """ 916 | This function calculates an estimate of the power in the first path signal. See section 4.7.1 of the DW1000 user manual for further details on the calculations. 917 | 918 | Returns: 919 | The estimated power in the first path signal. 920 | """ 921 | fpAmpl1Bytes = [None] * 2 922 | fpAmpl2Bytes = [None] * 2 923 | fpAmpl3Bytes = [None] * 2 924 | rxFrameInfo = [None] * 4 925 | fpAmpl1Bytes = self.readBytes(C.RX_TIME, C.FP_AMPL1_SUB, fpAmpl1Bytes, 2) 926 | fpAmpl2Bytes = self.readBytes(C.RX_FQUAL, C.FP_AMPL2_SUB, fpAmpl2Bytes, 2) 927 | fpAmpl3Bytes = self.readBytes(C.RX_FQUAL, C.FP_AMPL3_SUB, fpAmpl3Bytes, 2) 928 | rxFrameInfo = self.readBytes(C.RX_FINFO, C.NO_SUB, rxFrameInfo, 4) 929 | f1 = fpAmpl1Bytes[0] | fpAmpl1Bytes[1] << 8 930 | f2 = fpAmpl2Bytes[0] | fpAmpl2Bytes[1] << 8 931 | f3 = fpAmpl3Bytes[0] | fpAmpl3Bytes[1] << 8 932 | N = ((rxFrameInfo[2] >> 4) & C.MASK_LS_BYTE) | (rxFrameInfo[3] << 4) 933 | if self._operationMode[C.PULSE_FREQUENCY_BIT] == C.TX_PULSE_FREQ_16MHZ: 934 | A = C.A_16MHZ 935 | corrFac = C.CORRFAC_16MHZ 936 | else: 937 | A = C.A_64MHZ 938 | corrFac = C.CORRFAC_64MHZ 939 | estFPPower = C.PWR_COEFF2 * \ 940 | math.log10((f1 * f1 + f2 * f2 + f3 * f3) / (N * N)) - A 941 | if estFPPower <= -C.PWR_COEFF: 942 | return estFPPower 943 | else: 944 | estFPPower += (estFPPower + C.PWR_COEFF) * corrFac 945 | return estFPPower 946 | 947 | def getReceivePower(self): 948 | """ 949 | This function calculates an estimate of the receive power level. See section 4.7.2 of the DW1000 user manual for further details on the calculation. 950 | 951 | Returns: 952 | The estimated receive power for the current reception. 953 | """ 954 | cirPwrBytes = [None] * 2 955 | rxFrameInfo = [None] * 4 956 | cirPwrBytes = self.readBytes(C.RX_FQUAL, C.CIR_PWR_SUB, cirPwrBytes, 2) 957 | rxFrameInfo = self.readBytes(C.RX_FINFO, C.NO_SUB, rxFrameInfo, 4) 958 | cir = cirPwrBytes[0] | cirPwrBytes[1] << 8 959 | N = ((rxFrameInfo[2] >> 4) & C.MASK_LS_BYTE) | rxFrameInfo[3] << 4 960 | if self._operationMode[C.PULSE_FREQUENCY_BIT] == C.TX_PULSE_FREQ_16MHZ: 961 | A = C.A_16MHZ 962 | corrFac = C.CORRFAC_16MHZ 963 | else: 964 | A = C.A_64MHZ 965 | corrFac = C.CORRFAC_64MHZ 966 | estRXPower = 0 967 | if (float(cir) * float(C.TWOPOWER17)) / (float(N) * float(N)) > 0: 968 | estRXPower = C.PWR_COEFF2 * math.log10((float(cir) * float(C.TWOPOWER17)) / (float(N) * float(N))) - A 969 | if estRXPower <= -C.PWR_COEFF: 970 | return estRXPower 971 | else: 972 | estRXPower += (estRXPower + C.PWR_COEFF) * corrFac 973 | return estRXPower 974 | 975 | def getReceiveQuality(self): 976 | """ 977 | This function calculates an estimate of the receive quality.abs 978 | 979 | Returns: 980 | The estimated receive quality for the current reception. 981 | """ 982 | noiseBytes = [None] * 2 983 | fpAmpl2Bytes = [None] * 2 984 | noiseBytes = readBytes(C.RX_FQUAL, C.STD_NOISE_SUB, noiseBytes, 2) 985 | fpAmpl2Bytes = readBytes(C.RX_FQUAL, C.FP_AMPL2_SUB, fpAmpl2Bytes, 2) 986 | noise = float(noiseBytes[0] | noiseBytes[1] << 8) 987 | f2 = float(fpAmpl2Bytes[0] | fpAmpl2Bytes[1] << 8) 988 | return f2 / noise 989 | 990 | def getReceiveTimestamp(self): 991 | """ 992 | This function reads the receive timestamp from the register and returns it. 993 | 994 | Returns: 995 | The timestamp value of the startReceive reception. 996 | """ 997 | rxTimeBytes = [0] * 5 998 | rxTimeBytes = self.readBytes(C.RX_TIME, C.RX_STAMP_SUB, rxTimeBytes, 5) 999 | timestamp = 0 1000 | for i in range(0, 5): 1001 | timestamp |= rxTimeBytes[i] << (i * 8) 1002 | timestamp = int(round(self.correctTimestamp(timestamp))) 1003 | 1004 | return timestamp 1005 | 1006 | def correctTimestamp(self, timestamp): 1007 | """ 1008 | This function corrects the timestamp read from the RX buffer. 1009 | 1010 | Args: 1011 | timestamp : the timestamp you want to correct 1012 | 1013 | Returns: 1014 | The corrected timestamp. 1015 | """ 1016 | rxPowerBase = -(self.getReceivePower() + 61.0) * 0.5 1017 | rxPowerBaseLow = int(math.floor(rxPowerBase)) 1018 | rxPowerBaseHigh = rxPowerBaseLow + 1 1019 | 1020 | if rxPowerBaseLow < 0: 1021 | rxPowerBaseLow = 0 1022 | rxPowerBaseHigh = 0 1023 | elif rxPowerBaseHigh > 17: 1024 | rxPowerBaseLow = 17 1025 | rxPowerBaseHigh = 17 1026 | 1027 | if self._operationMode[C.CHANNEL_BIT] == C.CHANNEL_4 or self._operationMode[C.CHANNEL_BIT] == C.CHANNEL_7: 1028 | if self._operationMode[C.PULSE_FREQUENCY_BIT] == C.TX_PULSE_FREQ_16MHZ: 1029 | if rxPowerBaseHigh < C.BIAS_900_16_ZERO: 1030 | rangeBiasHigh = - C.BIAS_900_16[rxPowerBaseHigh] 1031 | else: 1032 | rangeBiasHigh = C.BIAS_900_16[rxPowerBaseHigh] 1033 | rangeBiasHigh <<= 1 1034 | if rxPowerBaseLow < C.BIAS_900_16_ZERO: 1035 | rangeBiasLow = -C.BIAS_900_16[rxPowerBaseLow] 1036 | else: 1037 | rangeBiasLow = C.BIAS_900_16[rxPowerBaseLow] 1038 | rangeBiasLow <<= 1 1039 | elif _operationMode[C.PULSE_FREQUENCY_BIT] == C.TX_PULSE_FREQ_64MHZ: 1040 | if rxPowerBaseHigh < C.BIAS_900_64_ZERO: 1041 | rangeBiasHigh = - C.BIAS_900_64[rxPowerBaseHigh] 1042 | else: 1043 | rangeBiasHigh = C.BIAS_900_64[rxPowerBaseHigh] 1044 | rangeBiasHigh <<= 1 1045 | if rxPowerBaseLow < C.BIAS_900_64_ZERO: 1046 | rangeBiasLow = -C.BIAS_900_64[rxPowerBaseLow] 1047 | else: 1048 | rangeBiasLow = C.BIAS_900_64[rxPowerBaseLow] 1049 | rangeBiasLow <<= 1 1050 | else: 1051 | if self._operationMode[C.PULSE_FREQUENCY_BIT] == C.TX_PULSE_FREQ_16MHZ: 1052 | if rxPowerBaseHigh < C.BIAS_500_16_ZERO: 1053 | rangeBiasHigh = - C.BIAS_500_16[rxPowerBaseHigh] 1054 | else: 1055 | rangeBiasHigh = C.BIAS_500_16[rxPowerBaseHigh] 1056 | rangeBiasHigh <<= 1 1057 | if rxPowerBaseLow < C.BIAS_500_16_ZERO: 1058 | rangeBiasLow = -C.BIAS_500_16[rxPowerBaseLow] 1059 | else: 1060 | rangeBiasLow = C.BIAS_500_16[rxPowerBaseLow] 1061 | rangeBiasLow <<= 1 1062 | elif self._operationMode[C.PULSE_FREQUENCY_BIT] == C.TX_PULSE_FREQ_64MHZ: 1063 | if rxPowerBaseHigh < C.BIAS_500_64_ZERO: 1064 | rangeBiasHigh = - C.BIAS_500_64[rxPowerBaseHigh] 1065 | else: 1066 | rangeBiasHigh = C.BIAS_500_64[rxPowerBaseHigh] 1067 | rangeBiasHigh <<= 1 1068 | if rxPowerBaseLow < C.BIAS_500_64_ZERO: 1069 | rangeBiasLow = -C.BIAS_500_64[rxPowerBaseLow] 1070 | else: 1071 | rangeBiasLow = C.BIAS_500_64[rxPowerBaseLow] 1072 | rangeBiasLow <<= 1 1073 | 1074 | rangeBias = rangeBiasLow + (rxPowerBase - rxPowerBaseLow) * (rangeBiasHigh - rangeBiasLow) 1075 | adjustmentTimeTS = rangeBias * C.DISTANCE_OF_RADIO_INV * C.ADJUSTMENT_TIME_FACTOR 1076 | timestamp += adjustmentTimeTS 1077 | return timestamp 1078 | 1079 | """ 1080 | Message transmission functions. 1081 | """ 1082 | 1083 | def newTransmit(self): 1084 | """ 1085 | This function prepares the chip for a new transmission. It clears the system control register and also clears the TX latched bits in the SYS_STATUS register. 1086 | """ 1087 | self.idle() 1088 | self.setArray(self._sysctrl, 4, 0x00) 1089 | self.clearTransmitStatus() 1090 | self._deviceMode = C.TX_MODE 1091 | 1092 | def startTransmit(self): 1093 | """ 1094 | This function configures the chip to start the transmission of the message previously set in the TX register. It sets TXSTRT bit in the system control register to begin transmission. 1095 | """ 1096 | self.writeBytes(C.TX_FCTRL, C.NO_SUB, self._txfctrl, 5) 1097 | self.setBit(self._sysctrl, 4, C.SFCST_BIT, False) 1098 | self.setBit(self._sysctrl, 4, C.TXSTRT_BIT, True) 1099 | self.writeBytes(C.SYS_CTRL, C.NO_SUB, self._sysctrl, 4) 1100 | if self._permanentReceive: 1101 | self.setArray(self._sysctrl, 4, 0x00) 1102 | self._deviceMode = C.RX_MODE 1103 | self.startReceive() 1104 | else: 1105 | self._deviceMode = C.IDLE_MODE 1106 | 1107 | def clearTransmitStatus(self): 1108 | """ 1109 | This function clears the event status register at the bits related to the transmission of a message. 1110 | """ 1111 | self.setBit(self._sysstatus, 5, C.TXFRB_BIT, True) 1112 | self.setBit(self._sysstatus, 5, C.TXPRS_BIT, True) 1113 | self.setBit(self._sysstatus, 5, C.TXPHS_BIT, True) 1114 | self.setBit(self._sysstatus, 5, C.TXFRS_BIT, True) 1115 | 1116 | self.writeBytes(C.SYS_STATUS, C.NO_SUB, self._sysstatus, 5) 1117 | 1118 | 1119 | def setDelay(self, delay, unit): 1120 | """ 1121 | This function configures the chip to activate a delay between transmissions or receptions. 1122 | 1123 | Args: 1124 | delay: The delay between each transmission/reception 1125 | unit : The unit you want to put the delay in. Microseconds is the base unit. 1126 | 1127 | Returns: 1128 | The timestamp's value with the added delay and antennaDelay. 1129 | """ 1130 | if self._deviceMode == C.TX_MODE: 1131 | self.setBit(self._sysctrl, 4, C.TXDLYS_BIT, True) 1132 | elif self._deviceMode == C.RX_MODE: 1133 | self.setBit(self._sysctrl, 4, C.RXDLYE_BIT, True) 1134 | 1135 | delayBytes = [None] * 5 1136 | sysTimeBytes = [None] * 5 1137 | sysTimeBytes = self.readBytes(C.SYS_TIME, C.NO_SUB, sysTimeBytes, 5) 1138 | futureTimeTS = 0 1139 | for i in range(0, 5): 1140 | futureTimeTS |= sysTimeBytes[i] << (i * 8) 1141 | futureTimeTS += (int)(delay * unit * C.TIME_RES_INV) 1142 | 1143 | self.setArray(delayBytes, 5, 0x00) 1144 | for i in range(0, 5): 1145 | delayBytes[i] = (int)(futureTimeTS >> (i * 8)) & C.MASK_LS_BYTE 1146 | 1147 | delayBytes[0] = 0 1148 | delayBytes[1] &= C.SET_DELAY_MASK 1149 | self.writeBytes(C.DX_TIME, C.NO_SUB, delayBytes, 5) 1150 | 1151 | futureTimeTS = 0 1152 | for i in range(0, 5): 1153 | futureTimeTS |= delayBytes[i] << (i * 8) 1154 | 1155 | futureTimeTS += C.ANTENNA_DELAY 1156 | return futureTimeTS 1157 | 1158 | 1159 | def clearAllStatus(self): 1160 | """ 1161 | This function clears all the status register by writing a 1 to every bits in it. 1162 | """ 1163 | self.setArray(self._sysstatus, 5, 0xFF) 1164 | self.writeBytes(C.SYS_STATUS, C.NO_SUB, self._sysstatus, 5) 1165 | 1166 | 1167 | def getTransmitTimestamp(self): 1168 | """ 1169 | This function reads the transmit timestamp from the register and returns it. 1170 | 1171 | Returns: 1172 | The timestamp value of the last transmission. 1173 | """ 1174 | txTimeBytes = [0] * 5 1175 | txTimeBytes = self.readBytes(C.TX_TIME, C.TX_STAMP_SUB, txTimeBytes, 5) 1176 | timeStamp = 0 1177 | for i in range(0, 5): 1178 | timeStamp |= int(txTimeBytes[i] << (i * 8)) 1179 | return timeStamp 1180 | 1181 | def setTimeStamp(self, data, timeStamp, index): 1182 | """ 1183 | This function sets the specified timestamp into the data that will be sent. 1184 | Args: 1185 | data: The data where you will store the timestamp 1186 | timeStamp = The timestamp's value 1187 | index = The bit from where you will put the timestamp's value 1188 | Returns: 1189 | The data with the timestamp added to it 1190 | """ 1191 | for i in range(0, 5): 1192 | data[i+index] = int((timeStamp >> (i * 8)) & C.MASK_LS_BYTE) 1193 | 1194 | 1195 | def getTimeStamp(self, data, index): 1196 | """ 1197 | This function gets the timestamp's value written inside the specified data and returns it. 1198 | Args: 1199 | data : the data where you want to extract the timestamp from 1200 | index : the index you want to start reading the data from 1201 | Returns: 1202 | The timestamp's value read from the given data. 1203 | """ 1204 | timestamp = 0 1205 | for i in range(0, 5): 1206 | timestamp |= data[i+index] << (i*8) 1207 | return timestamp 1208 | 1209 | 1210 | def wrapTimestamp(self, timestamp): 1211 | """ 1212 | This function converts the negative values of the timestamp due to the overflow into a correct one. 1213 | Args : 1214 | timestamp : the timestamp's value you want to correct. 1215 | 1216 | Returns: 1217 | The corrected timestamp's value. 1218 | """ 1219 | if timestamp < 0: 1220 | timestamp += C.TIME_OVERFLOW 1221 | return timestamp 1222 | 1223 | 1224 | """ 1225 | Data functions 1226 | """ 1227 | 1228 | 1229 | def getDataStr(self): 1230 | """ 1231 | This function reads the RX buffer register to process the received message. First, it reads the length of the message in the RX frame info register, then 1232 | read the RX buffer register and converts the ASCII values into strings. 1233 | 1234 | Returns: 1235 | The data in the RX buffer as a string. 1236 | """ 1237 | len = 0 1238 | if _deviceMode == C.RX_MODE: 1239 | rxFrameInfo = [0] * 4 1240 | rxFrameInfo = readBytes(C.RX_FINFO, C.NO_SUB, rxFrameInfo, 4) 1241 | len = (((rxFrameInfo[1] << 8) | rxFrameInfo[0]) & C.GET_DATA_MASK) 1242 | len = len - 2 1243 | 1244 | dataBytes = [""] * len 1245 | dataBytes = readBytes(C.RX_BUFFER, C.NO_SUB, dataBytes, len) 1246 | data = "".join(chr(i) for i in dataBytes) 1247 | return data 1248 | 1249 | 1250 | def getData(self, datalength): 1251 | """ 1252 | This function reads a number of bytes in the RX buffer register, stores it into an array and return it. 1253 | 1254 | Args: 1255 | datalength = The number of bytes you want to read from the rx buffer. 1256 | 1257 | Returns: 1258 | The data read in the RX buffer as an array byte. 1259 | """ 1260 | data = [0] * datalength 1261 | time.sleep(0.000005) 1262 | data = self.readBytes(C.RX_BUFFER, C.NO_SUB, data, datalength) 1263 | print "DW1000.py 1263:\t ", data 1264 | return data 1265 | 1266 | 1267 | def setDataStr(self, data): 1268 | """ 1269 | This function converts the specified string into an array of bytes and calls the setData function. 1270 | 1271 | Args: 1272 | data: The string message the transmitter will send. 1273 | """ 1274 | dataLength = len(data) + 1 1275 | testData = [0] * dataLength 1276 | for i in range(0, len(data)): 1277 | testData[i] = ord(data[i]) 1278 | setData(testData, dataLength) 1279 | 1280 | 1281 | def setData(self, data, dataLength): 1282 | """ 1283 | This function writes the byte array into the TX buffer register to store the message which will be sent. 1284 | 1285 | Args: 1286 | data: the byte array which contains the data to be written in the register 1287 | dataLength: The size of the data which will be sent. 1288 | """ 1289 | self.writeBytes(C.TX_BUFFER, C.NO_SUB, data, dataLength) 1290 | dataLength += 2 # _frameCheck true, two bytes CRC 1291 | self._txfctrl[0] = (dataLength & C.MASK_LS_BYTE) 1292 | self._txfctrl[1] &= C.SET_DATA_MASK1 1293 | self._txfctrl[1] |= ((dataLength >> 8) & C.SET_DATA_MASK2) 1294 | 1295 | 1296 | def getDeviceModeInfo(self): 1297 | """ 1298 | This function prints the various device mode operating informations such as datarate, pulse frequency, the channel used, etc 1299 | """ 1300 | if self._operationMode[C.PULSE_FREQUENCY_BIT] == C.TX_PULSE_FREQ_16MHZ: 1301 | prf = C.PFREQ_16 1302 | elif self._operationMode[C.PULSE_FREQUENCY_BIT] == C.TX_PULSE_FREQ_64MHZ: 1303 | prf = C.PFREQ_64 1304 | else: 1305 | prf = C.PFREQ_0 1306 | 1307 | if self._operationMode[C.PREAMBLE_LENGTH_BIT] == C.TX_PREAMBLE_LEN_64: 1308 | plen = C.PLEN_64 1309 | elif self._operationMode[C.PREAMBLE_LENGTH_BIT] == C.TX_PREAMBLE_LEN_2048: 1310 | plen = C.PLEN_2048 1311 | else: 1312 | plen = C.PLEN_0 1313 | 1314 | if self._operationMode[C.DATA_RATE_BIT] == C.TRX_RATE_110KBPS: 1315 | dr = C.DATA_RATE_110 1316 | else: 1317 | dr = C.DATA_RATE_0 1318 | 1319 | ch = self._operationMode[C.CHANNEL_BIT] 1320 | pcode = self._operationMode[C.PREAMBLE_CODE_BIT] 1321 | print("Device mode: Data rate %d kb/s, PRF : %d MHz, Preamble: %d symbols (code %d), Channel : %d" % 1322 | (dr, prf, plen, pcode, ch)) 1323 | 1324 | 1325 | """ 1326 | Helper functions 1327 | """ 1328 | 1329 | 1330 | def readBytes(self, cmd, offset, data, n): 1331 | """ 1332 | This function read n bytes from the given registers with an offset and stores them in the array given as a parameter. 1333 | 1334 | Args: 1335 | cmd: The address of the register you want to read. 1336 | offset: The offset for the register. 1337 | data: The array where you want the bytes the be stored. 1338 | n: The number of bytes you want to read from the register. 1339 | """ 1340 | header = [None] * 3 1341 | headerLen = 1 1342 | 1343 | if offset == C.NO_SUB: 1344 | header[0] = C.READ | cmd 1345 | else: 1346 | header[0] = C.READ_SUB | cmd 1347 | if offset < 128: 1348 | header[1] = offset 1349 | headerLen = headerLen + 1 1350 | else: 1351 | header[1] = (C.RW_SUB_EXT | offset) & C.MASK_LS_BYTE 1352 | header[2] = offset >> 7 1353 | headerLen = headerLen + 2 1354 | 1355 | GPIO.output(self._chipSelect, GPIO.LOW) 1356 | for i in range(0, headerLen): 1357 | self.spi.xfer([int(header[i])]) 1358 | 1359 | for i in range(0, n): 1360 | data[i] = self.spi.xfer([C.JUNK])[0] 1361 | 1362 | GPIO.output(self._chipSelect, GPIO.HIGH) 1363 | return data 1364 | 1365 | 1366 | def writeBytes(self, cmd, offset, data, dataSize): 1367 | """ 1368 | This function writes n bytes from the specified array to the register given as a parameter and with an offset value. 1369 | 1370 | Args: 1371 | cmd: The address of the register you want to write into. 1372 | offset: The offset for the register. 1373 | data: The array containing the data you want written. 1374 | dataSize: The number of bytes you want to write into the register. 1375 | """ 1376 | header = [None] * 3 1377 | headerLen = 1 1378 | 1379 | if offset == C.NO_SUB: 1380 | header[0] = C.WRITE | cmd 1381 | else: 1382 | header[0] = C.WRITE_SUB | cmd 1383 | if offset < 128: 1384 | header[1] = offset 1385 | headerLen = headerLen + 1 1386 | else: 1387 | header[1] = (C.RW_SUB_EXT | offset) & C.MASK_LS_BYTE 1388 | header[2] = offset >> 7 1389 | headerLen = headerLen + 2 1390 | 1391 | GPIO.output(self._chipSelect, GPIO.LOW) 1392 | for i in range(0, headerLen): 1393 | self.spi.xfer([int(header[i])]) 1394 | 1395 | for i in range(0, dataSize): 1396 | if (data[i] != None): 1397 | self.spi.xfer([int(data[i])]) 1398 | 1399 | GPIO.output(self._chipSelect, GPIO.HIGH) 1400 | 1401 | 1402 | def setBit(self, data, n, bit, val): 1403 | """ 1404 | This function sets the value of a bit in an array of bytes. 1405 | 1406 | Args: 1407 | data: The array you want to set the bit into. 1408 | n: The number of bytes in the array 1409 | bit: The position of the bit to be set. 1410 | val: The boolean value to be set to the given position 1411 | 1412 | Returns: 1413 | The modified array with the bit set according to the specified value. 1414 | """ 1415 | idx = bit / 8 1416 | if idx >= n: 1417 | return 1418 | shift = bit % 8 1419 | if val: 1420 | mask = 1 << shift 1421 | data[idx] = data[idx] | mask 1422 | else: 1423 | mask = ~(1 << shift) 1424 | data[idx] = data[idx] & mask 1425 | return data 1426 | 1427 | 1428 | def getBit(self, data, n, pos): 1429 | """ 1430 | This function gets the value of a bit in an array of bytes. 1431 | 1432 | Args: 1433 | data: The array you want to get the bit from. 1434 | n: The number of bytes in the array. 1435 | pos: The position of the bit to get. 1436 | 1437 | Returns: 1438 | The bit in the array according to the position. 1439 | """ 1440 | idx = pos / 8 1441 | if idx >= n: 1442 | return 1443 | shift = pos % 8 1444 | data[idx] = (data[idx] >> shift) & 0x01 1445 | return data[idx] 1446 | 1447 | 1448 | def setArray(self, data, size, value): 1449 | """ 1450 | This function sets all the value in an array to the given value. 1451 | 1452 | Args: 1453 | data: The array to be set. 1454 | size: The size of the array. 1455 | value: The value to be set in the array. 1456 | """ 1457 | for i in range(0, size): 1458 | data[i] = value 1459 | 1460 | 1461 | def writeValueToBytes(self, data, val, n): 1462 | """ 1463 | This function writes the value specified and convert it into bytes to write in the array 1464 | 1465 | Args: 1466 | data: The array you want to write the value into. 1467 | val: The value you want to write in the array. 1468 | n: The size of the array. 1469 | 1470 | Return: 1471 | The modified array of bytes. 1472 | """ 1473 | for i in range(0, n): 1474 | data[i] = int(((val >> (i * 8)) & C.MASK_LS_BYTE)) 1475 | return data 1476 | 1477 | 1478 | def readBytesOTP(self, address, data): 1479 | """ 1480 | This function reads a value from the OTP memory following 6.3.3 table 13 of the user manual 1481 | 1482 | Args: 1483 | address: The address to read in the OTP register. 1484 | data: The data that will store the value read. 1485 | """ 1486 | addressBytes = [None] * 2 1487 | addressBytes[0] = address & C.MASK_LS_BYTE 1488 | addressBytes[1] = (address >> 8) & C.MASK_LS_BYTE 1489 | self.writeBytes(C.OTP_IF, C.OTP_ADDR_SUB, addressBytes, 2) 1490 | self.writeBytes(C.OTP_IF, C.OTP_CTRL_SUB, [C.OTP_STEP2], 1) 1491 | self.writeBytes(C.OTP_IF, C.OTP_CTRL_SUB, [C.OTP_STEP3], 1) 1492 | self.data = self.readBytes(C.OTP_IF, C.OTP_RDAT_SUB, data, 4) 1493 | self.writeBytes(C.OTP_IF, C.OTP_CTRL_SUB, [C.OTP_STEP5], 1) 1494 | return data 1495 | 1496 | 1497 | def convertStringToByte(self, string): 1498 | """ 1499 | This function converts the string address used for the EUI into a byte array. 1500 | 1501 | Args: 1502 | string : the string you want to convert into an array of bytes 1503 | 1504 | Returns: 1505 | The array of bytes 1506 | 1507 | """ 1508 | data = [0] * 8 1509 | for i in range(0, 8): 1510 | data[i] = (int(string[i * 3], 16) << 4) + int(string[i * 3 + 1], 16) 1511 | return data 1512 | 1513 | 1514 | def close(self): 1515 | """ 1516 | This function closes the SPI connection and clean up the GPIOs. 1517 | """ 1518 | self.spi.close() 1519 | GPIO.cleanup() 1520 | print("\n Close SPI") 1521 | -------------------------------------------------------------------------------- /DW1000Constants.py: -------------------------------------------------------------------------------- 1 | """ 2 | This python module is used to store every constants relevant for the DW1000 module and scripts. 3 | """ 4 | 5 | ########################################################################################### 6 | #### From DW1000Constants.h 7 | ########################################################################################### 8 | 9 | # Time stamp byte length 10 | LEN_STAMP = 5 11 | 12 | # DW1000 TX/RX Modes 13 | IDLE_MODE = 0x00 14 | RX_MODE = 0x01 15 | TX_MODE = 0x02 16 | 17 | # Used for SPI ready w/o actual writes 18 | JUNK = 0x00 19 | 20 | # No sub-address for register write 21 | NO_SUB = 0xFF 22 | 23 | # Device id register 24 | DEV_ID = 0x00 25 | LEN_DEV_ID = 4 26 | 27 | # Extended unique identifier register 28 | EUI = 0x01 29 | LEN_EUI = 8 30 | 31 | # PAN identifier, short address register 32 | PANADR = 0x03 33 | LEN_PANADR = 4 34 | 35 | # Device configuration register 36 | SYS_CFG = 0x04 37 | LEN_SYS_CFG = 4 38 | # -- 39 | FFEN_BIT = 0 40 | FFBC_BIT = 1 41 | FFAB_BIT = 2 42 | FFAD_BIT = 3 43 | FFAA_BIT = 4 44 | FFAM_BIT = 5 45 | FFAR_BIT = 6 46 | # -- 47 | DIS_STXP_BIT = 18 48 | PHR_MODE_SUB = 16 49 | LEN_PHR_MODE_SUB = 2 50 | # -- System configuration register bits, see 7.2.6 of User Manual. 51 | DIS_DRXB_BIT = 12 52 | HIRQ_POL_BIT = 9 53 | RXM110K_BIT = 22 54 | RXAUTR_BIT = 29 55 | 56 | 57 | # Device control register 58 | SYS_CTRL = 0x0D 59 | LEN_SYS_CTRL = 4 60 | # -- 61 | WAIT4RESP_BIT = 7 62 | # -- System control register bits, see 7.2.15 of User Manual 63 | SFCST_BIT = 0 64 | TXSTRT_BIT = 1 65 | TXDLYS_BIT = 2 66 | TRXOFF_BIT = 6 67 | RXENAB_BIT = 8 68 | RXDLYE_BIT = 9 69 | 70 | # System event status register 71 | SYS_STATUS = 0x0F 72 | LEN_SYS_STATUS = 5 73 | CPLOCK_BIT = 1 74 | AAT_BIT = 3 75 | # -- System event status register bits, see 7.2.17 of User Manual 76 | TXFRB_BIT = 4 77 | TXPRS_BIT = 5 78 | TXPHS_BIT = 6 79 | TXFRS_BIT = 7 80 | # -- System event status register bits, see 7.2.17 of User Manual 81 | LDEDONE_BIT = 10 82 | RXPHE_BIT = 12 83 | RXDFR_BIT = 13 84 | RXFCG_BIT = 14 85 | RXFCE_BIT = 15 86 | RXRFSL_BIT = 16 87 | RXRFTO_BIT = 17 88 | RXPTO_BIT = 21 89 | RXSFDTO_BIT = 26 90 | LDEERR_BIT = 18 91 | # -- 92 | RFPLL_LL_BIT = 24 93 | CLKPLL_LL_BIT = 25 94 | 95 | # system event mask register 96 | # NOTE: uses the bit definitions of SYS_STATUS (below 32) 97 | SYS_MASK = 0x0E 98 | LEN_SYS_MASK = 4 99 | 100 | # System time counter 101 | SYS_TIME = 0x06 102 | LEN_SYS_TIME = LEN_STAMP 103 | 104 | # RX timestamp register 105 | RX_TIME = 0x15 106 | LEN_RX_TIME = 14 107 | # -- RX_TIME subregisters 108 | RX_STAMP_SUB = 0x00 109 | FP_AMPL1_SUB = 0x07 110 | # -- 111 | LEN_RX_STAMP = LEN_STAMP 112 | LEN_FP_AMPL1 = 2 113 | 114 | # RX frame quality 115 | RX_FQUAL = 0x12 116 | LEN_RX_FQUAL = 8 117 | # -- RX_FQUAL subregisters 118 | STD_NOISE_SUB = 0x00 119 | FP_AMPL2_SUB = 0x02 120 | FP_AMPL3_SUB = 0x04 121 | #PP_AMPL3_SUB = 0x04 122 | CIR_PWR_SUB = 0x06 123 | # -- 124 | LEN_STD_NOISE = 2 125 | LEN_FP_AMPL2 = 2 126 | LEN_FP_AMPL3 = 2 127 | LEN_CIR_PWR = 2 128 | 129 | # TX timestamp register 130 | TX_TIME = 0x17 131 | LEN_TX_TIME = 10 132 | # -- TX_TIME subregisters 133 | TX_STAMP_SUB = 0 134 | # -- 135 | LEN_TX_STAMP = LEN_STAMP 136 | 137 | # Timing register (for delayed RX/TX) 138 | DX_TIME = 0x0A 139 | LEN_DX_TIME = LEN_STAMP 140 | 141 | # Transmit data buffer 142 | TX_BUFFER = 0x09 143 | LEN_TX_BUFFER = 1024 144 | LEN_UWB_FRAMES = 127 145 | LEN_EXT_UWB_FRAMES = 1023 146 | 147 | # RX frame info 148 | RX_FINFO = 0x10 149 | LEN_RX_FINFO = 4 150 | 151 | # Receive data buffer 152 | RX_BUFFER = 0x11 153 | LEN_RX_BUFFER = 1024 154 | 155 | # Transmit control 156 | TX_FCTRL = 0x08 157 | LEN_TX_FCTRL = 5 158 | 159 | # Channel control 160 | CHAN_CTRL = 0x1F 161 | LEN_CHAN_CTRL = 4 162 | # -- Channel control register bits, see 7.2.32 of user manual 163 | DWSFD_BIT = 17 164 | TNSSFD_BIT = 20 165 | RNSSFD_BIT = 21 166 | 167 | # user-defined SFD 168 | USR_SFD = 0x21 169 | LEN_USR_SFD = 41 170 | SFD_LENGTH_SUB = 0x00 171 | LEN_SFD_LENGTH = 1 172 | 173 | # OTP control (for LDE micro code loading only) 174 | OTP_IF = 0x2D 175 | # -- OTP_IF subregisters 176 | OTP_ADDR_SUB = 0x04 177 | OTP_CTRL_SUB = 0x06 178 | OTP_RDAT_SUB = 0x0A 179 | # -- 180 | LEN_OTP_ADDR = 2 181 | LEN_OTP_CTRL = 2 182 | LEN_OTP_RDAT = 4 183 | 184 | # AGC_TUNE1/2 (for re-tuning only) 185 | AGC_TUNE = 0x23 186 | # -- AGC_CTRL subregisters 187 | AGC_TUNE1_SUB = 0x04 188 | AGC_TUNE2_SUB = 0x0C 189 | AGC_TUNE3_SUB = 0x12 190 | # -- 191 | LEN_AGC_TUNE1 = 2 192 | LEN_AGC_TUNE2 = 4 193 | LEN_AGC_TUNE3 = 2 194 | 195 | # DRX_TUNE2 (for re-tuning only) 196 | DRX_TUNE = 0x27 197 | # -- DRX_CONF subregisters 198 | DRX_TUNE0b_SUB = 0x02 199 | DRX_TUNE1a_SUB = 0x04 200 | DRX_TUNE1b_SUB = 0x06 201 | DRX_TUNE2_SUB = 0x08 202 | DRX_TUNE4H_SUB = 0x26 203 | # -- 204 | LEN_DRX_TUNE0b = 2 205 | LEN_DRX_TUNE1a = 2 206 | LEN_DRX_TUNE1b = 2 207 | LEN_DRX_TUNE2 = 4 208 | LEN_DRX_TUNE4H = 2 209 | 210 | # LDE_CFG1 (for re-tuning only) 211 | LDE_IF = 0x2E 212 | # -- LDE_IF subregisters 213 | LDE_CFG1_SUB = 0x0806 214 | LDE_RXANTD_SUB = 0x1804 215 | LDE_CFG2_SUB = 0x1806 216 | LDE_REPC_SUB = 0x2804 217 | # -- 218 | LEN_LDE_CFG1 = 1 219 | LEN_LDE_RXANTD = 2 220 | LEN_LDE_CFG2 = 2 221 | LEN_LDE_REPC = 2 222 | 223 | # TX_POWER (for re-tuning only) 224 | TX_POWER = 0x1E 225 | LEN_TX_POWER = 4 226 | 227 | # RF_CONF (for re-tuning only) 228 | RF_CONF = 0x28 229 | # -- RF_CONF subregisters 230 | RF_RXCTRLH_SUB = 0x08 231 | RF_TXCTRL_SUB = 0x0C 232 | # -- 233 | LEN_RF_RXCTRLH = 1 234 | LEN_RF_TXCTRL = 4 235 | 236 | # TX_CAL (for re-tuning only) 237 | TX_CAL = 0x2A 238 | # -- TX_CAL subregisters 239 | TC_PGDELAY_SUB = 0x0B 240 | # -- 241 | LEN_TC_PGDELAY = 1 242 | TC_SARC = 0x00 243 | TC_SARL = 0x03 244 | 245 | # FS_CTRL (for re-tuning only) 246 | FS_CTRL = 0x2B 247 | # -- FS_CTRL subregisters 248 | FS_PLLCFG_SUB = 0x07 249 | FS_PLLTUNE_SUB = 0x0B 250 | FS_XTALT_SUB = 0x0E 251 | # -- 252 | LEN_FS_PLLCFG = 4 253 | LEN_FS_PLLTUNE = 1 254 | LEN_FS_X_TALT = 1 255 | 256 | # AON (#### what is this??) 257 | AON = 0x2C 258 | AON_WCFG_SUB = 0x00 259 | LEN_AON_WCFG = 2 260 | ONW_LDC_BIT = 6 261 | ONW_LDD0_BIT = 12 262 | AON_CTRL_SUB = 0x02 263 | LEN_AON_CTRL = 1 264 | RESTORE_BIT = 0 265 | SAVE_BIT = 1 266 | UPL_CFG_BIT = 2 267 | 268 | AON_CFG0_SUB = 0x06 269 | LEN_AON_CFG0 = 4 270 | SLEEP_EN_BIT = 0 271 | WAKE_PIN_BIT = 1 272 | WAKE_SPI_BIT = 2 273 | WAKE_CNT_BIT = 3 274 | 275 | # PMSC 276 | PMSC = 0x36 277 | # -- Registers offset 278 | PMSC_CTRL0_SUB = 0x00 279 | # -- 280 | PMSC_CTRL1_SUB = 0x04 281 | PMSC_LEDC_SUB = 0x28 282 | LEN_PMSC_CTRL0 = 4 283 | LEN_PMSC_CTRL1 = 4 284 | LEN_PMSC_LEDC = 4 285 | GPDCE_BIT = 18 286 | KHZCLKEN_BIT = 23 287 | BLNKEN = 8 288 | 289 | ATXSLP_BIT = 11 290 | ARXSLP_BIT = 12 291 | 292 | # TX_ANTD Antenna delays 293 | TX_ANTD = 0x18 294 | LEN_TX_ANTD = 2 295 | 296 | # GPIO 297 | GPIO_CTRL = 0x26 298 | GPIO_MODE_SUB = 0x00 299 | LEN_GPIO_MODE = 4 300 | 301 | MSGP0 = 6 302 | MSGP1 = 8 303 | MSGP2 = 10 304 | MSGP3= 12 305 | MSGP4 = 14 306 | MSGP5 = 16 307 | MSGP6 = 18 308 | MSGP7 = 20 309 | MSGP8 = 22 310 | 311 | GPIO_MODE = 0 312 | LED_MODE = 1 313 | 314 | ########################################################################################### 315 | #### FROM DW1000.h 316 | ########################################################################################### 317 | 318 | # transmission/reception bit rate 319 | TRX_RATE_110KBPS = 0x00 320 | TRX_RATE_850KBPS = 0x01 321 | TRX_RATE_6800KBPS = 0x02 322 | 323 | # transmission pulse frequency 324 | # 0x00 is 4MHz, but receiver in DW1000 does not support it (!??) 325 | TX_PULSE_FREQ_16MHZ = 0x01 326 | TX_PULSE_FREQ_64MHZ = 0x02 327 | 328 | # preamble length (PE + TXPSR bits) 329 | TX_PREAMBLE_LEN_64 = 0x01 330 | TX_PREAMBLE_LEN_128 = 0x05 331 | TX_PREAMBLE_LEN_256 = 0x09 332 | TX_PREAMBLE_LEN_512 = 0x0D 333 | TX_PREAMBLE_LEN_1024 = 0x02 334 | TX_PREAMBLE_LEN_1536 = 0x06 335 | TX_PREAMBLE_LEN_2048 = 0x0A 336 | TX_PREAMBLE_LEN_4096 = 0x03 337 | 338 | # PAC size 339 | PAC_SIZE_8 = 8 340 | PAC_SIZE_16 = 16 341 | PAC_SIZE_32 = 32 342 | PAC_SIZE_64 = 64 343 | 344 | # Channel of operation 345 | CHANNEL_1 = 1 346 | CHANNEL_2 = 2 347 | CHANNEL_3 = 3 348 | CHANNEL_4 = 4 349 | CHANNEL_5 = 5 350 | CHANNEL_7 = 7 351 | 352 | # Preamble codes 353 | PREAMBLE_CODE_16MHZ_1 = 1 354 | PREAMBLE_CODE_16MHZ_2 = 2 355 | PREAMBLE_CODE_16MHZ_3 = 3 356 | PREAMBLE_CODE_16MHZ_4 = 4 357 | PREAMBLE_CODE_16MHZ_5 = 5 358 | PREAMBLE_CODE_16MHZ_6 = 6 359 | PREAMBLE_CODE_16MHZ_7 = 7 360 | PREAMBLE_CODE_16MHZ_8 = 8 361 | PREAMBLE_CODE_64MHZ_9 = 9 362 | PREAMBLE_CODE_64MHZ_10 = 10 363 | PREAMBLE_CODE_64MHZ_11 = 11 364 | PREAMBLE_CODE_64MHZ_12 = 12 365 | PREAMBLE_CODE_64MHZ_17 = 17 366 | PREAMBLE_CODE_64MHZ_18 = 18 367 | PREAMBLE_CODE_64MHZ_19 = 19 368 | PREAMBLE_CODE_64MHZ_20 = 20 369 | 370 | # frame length settings 371 | FRAME_LENGTH_NORMAL = 0x00 372 | FRAME_LENGTH_EXTENDED = 0x03 373 | 374 | # pre-defined modes of operation (3 bytes for data rate, pulse frequency and preamble length) 375 | # -- DW1000 Modes of operation 376 | # -- ONLY MODE_LONGDATA_RANGE_LOWPOWER and MODE_LONGDATA_RANGE_ACCURACY is used in original python library. 377 | MODE_LONGDATA_RANGE_LOWPOWER = [TRX_RATE_110KBPS, TX_PULSE_FREQ_16MHZ, TX_PREAMBLE_LEN_2048] 378 | MODE_SHORTDATA_FAST_LOWPOWER = [TRX_RATE_6800KBPS, TX_PULSE_FREQ_16MHZ, TX_PREAMBLE_LEN_128] 379 | MODE_LONGDATA_FAST_LOWPOWER = [TRX_RATE_6800KBPS, TX_PULSE_FREQ_16MHZ, TX_PREAMBLE_LEN_1024] 380 | MODE_SHORTDATA_FAST_ACCURACY = [TRX_RATE_6800KBPS, TX_PULSE_FREQ_64MHZ, TX_PREAMBLE_LEN_128] 381 | MODE_LONGDATA_FAST_ACCURACY = [TRX_RATE_6800KBPS, TX_PULSE_FREQ_64MHZ, TX_PREAMBLE_LEN_1024] 382 | MODE_LONGDATA_RANGE_ACCURACY = [TRX_RATE_110KBPS, TX_PULSE_FREQ_64MHZ, TX_PREAMBLE_LEN_2048] 383 | 384 | # Register is 6 bit, 7 = write, 6 = sub-addressing, 5-0 = register value 385 | # Total header with sub-addressing can be 15-bit. 386 | # -- SPI operations 387 | WRITE = 0x80 388 | WRITE_SUB = 0xC0 389 | READ = 0x00 390 | READ_SUB = 0x40 391 | RW_SUB_EXT = 0x80 392 | 393 | # clocks available 394 | # -- Clocks 395 | AUTO_CLOCK = 0x00 396 | XTI_CLOCK = 0x01 397 | PLL_CLOCK = 0x02 398 | 399 | # range bias tables (500/900 MHz band, 16/64 MHz PRF), -61 to -95 dBm. 400 | # -- correct time stamp 401 | BIAS_500_16_ZERO = 10 402 | BIAS_500_64_ZERO = 8 403 | BIAS_900_16_ZERO = 7 404 | BIAS_900_64_ZERO = 7 405 | 406 | # range bias tables (500 MHz in [mm] and 900 MHz in [2mm] - to fit into bytes) 407 | BIAS_500_16 = [198, 187, 179, 163, 143, 127, 109, 84, 59, 31, 0, 36, 65, 84, 97, 106, 110, 112] 408 | BIAS_500_64 = [110, 105, 100, 93, 82, 69, 51, 27, 0, 21, 35, 42, 49, 62, 71, 76, 81, 86] 409 | BIAS_900_16 = [137, 122, 105, 88, 69, 47, 25, 0, 21, 48, 79, 105, 127, 147, 160, 169, 178, 197] 410 | BIAS_900_64 = [147, 133, 117, 99, 75, 50, 29, 0, 24, 45, 63, 76, 87, 98, 116, 122, 132, 142] 411 | 412 | 413 | ########################################################################################### 414 | #### From DW1000Time.h 415 | ########################################################################################### 416 | 417 | # Time resolution in micro-seconds of time based registers/values. 418 | # Each bit in a timestam counts for a period of approx. 15.65 ps 419 | # -- time resolution in micro seconds of time based registers 420 | TIME_RES = 0.000015650040064103 421 | TIME_RES_INV = 63897.6 422 | 423 | # Speed of radio waves [m/s] * timestamp resolution [~15.65 ps] of DW1000 424 | DISTANCE_OF_RADIO = 0.0046917639786159 425 | DISTANCE_OF_RADIO_INV = 213.139451293 426 | 427 | # Timestamp byte length - 40 bit -> 5 byte 428 | LENGTH_TIMESTAMP = 5 429 | 430 | # Timer/counter overflow (40 bits) -> 4 overflow approx. every 17.2 seconds 431 | TIME_OVERFLOW = 0x10000000000 432 | TIME_MAX = 0xffffffffff 433 | 434 | # Time factors (relative to [us]) for setting delayed transceive 435 | # TODO use non float (?) 436 | SECONDS = 1000000 437 | MILLISECONDS = 1000 438 | MICROSECONDS = 1 439 | NANOSECONDS = 0.001 440 | 441 | ########################################################################################### 442 | #### From DW1000Mac.h 443 | ########################################################################################### 444 | 445 | FC_1_BLINK = 0xC5 446 | FC_1 = 0x41 447 | FC_2 = 0x8C 448 | FC_2_SHORT = 0x88 449 | 450 | PAN_ID_1 = 0xCA 451 | PAN_ID_2 = 0xDE 452 | 453 | # Frame length 454 | LONG_MAC_LEN = 15 455 | SHORT_MAC_LEN = 9 456 | 457 | ########################################################################################### 458 | #### From DW1000Device.h 459 | ########################################################################################### 460 | 461 | INACTIVITY_TIME = 1000 462 | 463 | ########################################################################################### 464 | #### From DW1000Ranging.h 465 | ########################################################################################### 466 | 467 | # Messages used in the ranging protocol 468 | # -- Message types 469 | POLL = 0 470 | POLL_ACK = 1 471 | RANGE = 2 472 | RANGE_REPORT = 3 473 | RANGE_FAILED = 255 474 | BLINK = 4 475 | RANGING_INIT = 5 476 | 477 | LEN_DATA = 90 478 | 479 | # Default Pin for module: 480 | DEFAULT_RST_PIN = 9 481 | DEFAULT_SPI_SS_PIN = 10 482 | 483 | # Default value 484 | # in ms 485 | DEFAULT_RESET_PERIOD = 200 486 | # in us 487 | DEFAULT_REPLY_DELAY_TIME = 7000 488 | 489 | # Default timer delay 490 | DEFAULT_TIMER_DELAY = 80 491 | 492 | ########################################################################################### 493 | #### NOT SORTED 494 | ########################################################################################### 495 | 496 | # Delay 497 | INIT_DELAY = 0.000005 498 | PMSC_CONFIG_DELAY = 0.00015 499 | 500 | # frame length settings 501 | FRAME_LENGTH_NORMAL = 0x00 502 | FRAME_LENGTH_EXTENDED = 0x03 503 | 504 | # Transmission/reception bit rate 505 | DATA_RATE_0 = 0 506 | DATA_RATE_110 = 110 507 | 508 | # Transmission pulse frequency 509 | PFREQ_0 = 0 510 | PFREQ_16 = 16 511 | PFREQ_64 = 64 512 | 513 | # Preamble length 514 | PLEN_0 = 0 515 | PLEN_64 = 64 516 | PLEN_2048 = 2048 517 | 518 | # Registers ID 519 | AGC_CTRL = 0x23 520 | DRX_CONF = 0x27 521 | LDE_CTRL = 0x2E 522 | 523 | # RX_FQUAL subregisters 524 | OTP_XTAL_ADDRESS = 0x01E 525 | 526 | # System event mask register bits, see 7.2.16 of User Manual 527 | MAAT_BIT = 3 528 | MTXFRS_BIT = 7 529 | MLDEDONE_BIT = 10 530 | MRXPHE_BIT = 12 531 | MRXDFR_BIT = 13 532 | MRXFCG_BIT = 14 533 | MRXFCE_BIT = 15 534 | MRXRFSL_BIT = 16 535 | MLDEERR_BIT = 18 536 | 537 | # Enable clock masks 538 | ENABLE_CLOCK_MASK1 = 0xFE 539 | ENABLE_CLOCK_MASK2 = 0xFC 540 | 541 | # PMSC operation data bytes 542 | # SOFTRESET operations, see SOFTRESET section in 7.2.50.1 of the user manual 543 | SOFT_RESET_SYSCLKS = 0x01 544 | SOFT_RESET_CLEAR = 0x00 545 | SOFT_RESET_SET = 0xF0 546 | # Register access operations to load LDE microcode, see table 4 in 2.5.5.10 of the user manual 547 | LDE_L1STEP1 = 0x01 548 | LDE_L1STEP2 = 0x03 549 | LDE_L2STEP1 = 0x00 550 | LDE_L2STEP2 = 0x80 551 | LDE_L3STEP1 = 0x00 552 | LDE_L3STEP2 = 0x02 553 | 554 | # Read OTP memory operation data bytes 555 | OTP_STEP2 = 0x03 556 | OTP_STEP3 = 0x01 557 | OTP_STEP5 = 0x00 558 | 559 | # EnableMode masks 560 | ENABLE_MODE_MASK1 = 0x83 561 | ENABLE_MODE_MASK2 = 0xFC 562 | ENABLE_MODE_MASK3 = 0xF3 563 | ENABLE_MODE_MASK4 = 0xC3 564 | # sfdLength 565 | SFD_LENGTH_850KBPS = 0x10 566 | SFD_LENGTH_6800KBPS = 0x08 567 | SFD_LENGTH_OTHER = 0x40 568 | # preacode masks 569 | PREACODE_MASK1 = 0x1F 570 | PREACODE_MASK2 = 0x3F 571 | PREACODE_MASK3 = 0x07 572 | 573 | # Set delay masks 574 | SET_DELAY_MASK = 0xFE 575 | 576 | # get data masks 577 | GET_DATA_MASK = 0x03FF 578 | 579 | # set data masks 580 | SET_DATA_MASK1 = 0xE0 581 | SET_DATA_MASK2 = 0x03 582 | 583 | # Tune operations 584 | # AGC_TUNE1, see 7.2.36.3 of the user manual 585 | AGC_TUNE1_DEFAULT_OP = 0x889B 586 | AGC_TUNE1_16MHZ_OP = 0x8870 587 | # AGC_TUNE2, see 7.2.63.5 of the user manual 588 | AGC_TUNE2_OP = 0x2502A907 589 | # AGC_TUNE3, see 7.2.36.7 of the user manual 590 | AGC_TUNE3_OP = 0x0035 591 | # DRX_TUNE0b, see 7.2.40.2 of the user manual 592 | DRX_TUNE0b_110KBPS_NOSTD_OP = 0x0016 593 | DRX_TUNE0b_850KBPS_NOSTD_OP = 0x0006 594 | DRX_TUNE0b_6800KBPS_STD_OP = 0x0001 595 | # DRX_TUNE1a, see 7.2.40.3 of the user manual 596 | DRX_TUNE1a_16MHZ_OP = 0x0087 597 | DRX_TUNE1a_64MHZ_OP = 0x008D 598 | # DRX_TUNE1b, see 7.2.40.4 of the user manual 599 | DRX_TUNE1b_M1024 = 0x0064 600 | DRX_TUNE1b_L1024 = 0x0020 601 | DRX_TUNE1b_64 = 0x0010 602 | # DRX_TUNE2, see 7.2.40.5 of the user manual 603 | DRX_TUNE2_8_16MHZ = 0x311A002D 604 | DRX_TUNE2_8_64MHZ = 0x313B006B 605 | DRX_TUNE2_16_16MHZ = 0x331A0052 606 | DRX_TUNE2_16_64MHZ = 0x333B00BE 607 | DRX_TUNE2_32_16MHZ = 0x351A009A 608 | DRX_TUNE2_32_64MHZ = 0x353B015E 609 | DRX_TUNE2_64_16MHZ = 0x371A011D 610 | DRX_TUNE2_64_64MHZ = 0x373B0296 611 | # LDE_CFG2, see 7.2.47.6 of the user manual 612 | LDE_CFG2_16MHZ_OP = 0x1607 613 | LDE_CFG2_64MHZ_OP = 0x0607 614 | # DRX_TUNE4H, see 7.2.40.10 of the user manual 615 | DRX_TUNE4H_64 = 0x0010 616 | DRX_TUNE4H_128 = 0x0028 617 | # RF_RXCTRLH, see 7.2.41.3 of the user manual 618 | RF_RXCTRLH_1235 = 0xD8 619 | RF_RXCTRLH_147 = 0xBC 620 | # RF_TXCTRL, see 7.2.41.4 of the user manual 621 | RF_TXCTRL_1 = 0x00005C40 622 | RF_TXCTRL_2 = 0x00045CA0 623 | RF_TXCTRL_3 = 0x00086CC0 624 | RF_TXCTRL_4 = 0x00045C80 625 | RF_TXCTRL_5 = 0x001E3FE0 626 | RF_TXCTRL_7 = 0x001E7DE0 627 | # TC_PGDELAY, see 7.2.43.4 of the user manual 628 | TC_PGDELAY_1 = 0xC9 629 | TC_PGDELAY_2 = 0xC2 630 | TC_PGDELAY_3 = 0xC5 631 | TC_PGDELAY_4 = 0x95 632 | TC_PGDELAY_5 = 0xC0 633 | TC_PGDELAY_7 = 0x93 634 | # FS_PLLCFG, see 7.2.44.2 of the user manual 635 | FS_PLLCFG_1 = 0x09000407 636 | FS_PLLCFG_24 = 0x08400508 637 | FS_PLLCFG_3 = 0x08401009 638 | FS_PLLCFG_57 = 0x0800041D 639 | # FS_PLLTUNE, see 7.2.44.3 of the user manual 640 | FS_PLLTUNE_1 = 0x1E 641 | FS_PLLTUNE_24 = 0x26 642 | FS_PLLTUNE_3 = 0x5E 643 | FS_PLLTUNE_57 = 0xBE 644 | # TX_POWER, see 7.2.31.3 table 19 of the user manual 645 | TX_POWER_12_16MHZ = 0x75757575 646 | TX_POWER_12_64MHZ = 0x67676767 647 | TX_POWER_3_16MHZ = 0x6F6F6F6F 648 | TX_POWER_3_64MHZ = 0x8B8B8B8B 649 | TX_POWER_4_16MHZ = 0x5F5F5F5F 650 | TX_POWER_4_64MHZ = 0x9A9A9A9A 651 | TX_POWER_5_16MHZ = 0x48484848 652 | TX_POWER_5_64MHZ = 0x85858585 653 | TX_POWER_7_16MHZ = 0x92929292 654 | TX_POWER_7_64MHZ = 0xD1D1D1D1 655 | # LDE_CFG1, see 2.5.5.4 of the user manual 656 | LDE_CFG1_OP = 0xD 657 | # LDE_REPC, see 7.2.47.7 table 48 of the user manual 658 | LDE_REPC_1AND2 = 0x5998 659 | LDE_REPC_3AND8 = 0x51EA 660 | LDE_REPC_4 = 0x428E 661 | LDE_REPC_5 = 0x451E 662 | LDE_REPC_6 = 0x2E14 663 | LDE_REPC_7 = 0x8000 664 | LDE_REPC_9 = 0x28F4 665 | LDE_REPC_1017 = 0x3332 666 | LDE_REPC_111321 = 0x3AE0 667 | LDE_REPC_12 = 0x3D70 668 | LDE_REPC_14161819 = 0x35C2 669 | LDE_REPC_15 = 0x2B84 670 | LDE_REPC_20 = 0x47AE 671 | LDE_REPC_2224 = 0x3850 672 | LDE_REPC_23 = 0x30A2 673 | # Tune masks 674 | TUNE_MASK1 = 0x1F 675 | TUNE_MASK2 = 0x60 676 | TUNE_OPERATION = 0x10 677 | 678 | # signal power in the first path, see 4.7.1 of the user manual and receive signal power, see 4.7.2 of the user manual 679 | A_16MHZ = 115.72 680 | CORRFAC_16MHZ = 2.3334 681 | A_64MHZ = 121.74 682 | CORRFAC_64MHZ = 1.1667 683 | TWOPOWER17 = 131072 684 | PWR_COEFF = 88 685 | PWR_COEFF2 = 10.0 686 | 687 | # Time 688 | ANTENNA_DELAY_RASPI = 16390 689 | ANTENNA_DELAY = 16470 690 | 691 | RESET_PERIOD = 250 692 | 693 | # Bits/Bytes operation 694 | MASK_LS_BYTE = 0xFF 695 | MASK_LS_2BITS = 0x03 696 | MASK_LS_2BYTES = 0xFFFF 697 | MASK_NIBBLE = 0x0F 698 | 699 | # Correct Time stamp 700 | ADJUSTMENT_TIME_FACTOR = 0.001 701 | 702 | # Operation mode bits 703 | DATA_RATE_BIT = 0 704 | PULSE_FREQUENCY_BIT = 1 705 | PAC_SIZE_BIT = 2 706 | PREAMBLE_LENGTH_BIT = 3 707 | CHANNEL_BIT = 4 708 | PREAMBLE_CODE_BIT = 5 709 | 710 | RECEIVER = 0 711 | TRANSMITTER = 1 712 | -------------------------------------------------------------------------------- /DW1000DistantDevice.py: -------------------------------------------------------------------------------- 1 | """ 2 | DW1000Device.py 3 | This python module maintains remote devices to get activity and other information 4 | (range, rx_power, fp_power, quality, last received time) 5 | """ 6 | import random 7 | import time 8 | import DW1000Constants as C 9 | import DW1000Time 10 | import DW1000Mac 11 | 12 | 13 | class DW1000DistantDevice(object): 14 | timePollSent = DW1000Time 15 | timePollReceived = DW1000Time 16 | timePollAckSent = DW1000Time 17 | timePollAckReceived = DW1000Time 18 | timeRangeSent = DW1000Time 19 | timeRangeReceived = DW1000Time 20 | 21 | _own_address = bytearray([0, 0, 0, 0, 0, 0, 0, 0]) 22 | _short_address = bytearray([0, 0]) 23 | _activity = 0 24 | _reply_delay_time_us = 0 25 | _index = 0 26 | 27 | _range = 0 28 | _rx_power = 0 29 | _fp_power = 0 30 | _quality = 0 31 | 32 | def __init__(self, device_address=None, short_address=None): 33 | if device_address is None: 34 | self.random_address() 35 | return 36 | else: 37 | self.set_address(device_address) 38 | if short_address is None: 39 | self.random_short_address() 40 | else: 41 | self.set_short_address(device_address) 42 | 43 | def __del__(self): 44 | return 45 | 46 | # Setters 47 | def set_reply_time(self, reply_delay_time_us): 48 | self._reply_delay_time_us = reply_delay_time_us 49 | 50 | def set_address(self, device_address): 51 | self._own_address = device_address 52 | #DW1000.converToByte(deviceAddress, _ownAddress) 53 | 54 | def set_short_address(self, short_address): 55 | self._short_address = short_address 56 | # memcpy(_shortAddress, deviceAddress, 2) 57 | 58 | def set_range(self, given_range): 59 | self._range = given_range 60 | 61 | def set_rx_power(self, rx_power): 62 | self._rx_power = rx_power 63 | 64 | def set_fp_power(self, fp_power): 65 | self._fp_power = fp_power 66 | 67 | def set_quality(self, quality): 68 | self._quality = quality 69 | 70 | # getter 71 | def get_byte_address(self): 72 | return self._own_address 73 | 74 | def get_byte_short_address(self): 75 | return self._short_address 76 | 77 | def get_short_address(self): 78 | return self._short_address 79 | 80 | def is_address_equal(self, device): 81 | if self.get_byte_address == device.get_byte_address: 82 | return True 83 | else: 84 | return False 85 | 86 | def is_short_address_equal(self, device): 87 | if self.get_byte_short_address == device.get_byte_short_address: 88 | return True 89 | else: 90 | return False 91 | 92 | def get_range(self): 93 | return self._range 94 | 95 | def get_rx_power(self): 96 | return self._rx_power 97 | 98 | def get_fp_power(self): 99 | return self._fp_power 100 | 101 | def get_quality(self): 102 | return self._quality 103 | 104 | def random_short_address(self): 105 | self._short_address[0] = random.uniform(0, 255) 106 | self._short_address[1] = random.uniform(0, 255) 107 | 108 | def random_address(self): 109 | self._own_address[0] = random.uniform(0, 255) 110 | self._own_address[1] = random.uniform(0, 255) 111 | self._own_address[2] = random.uniform(0, 255) 112 | self._own_address[3] = random.uniform(0, 255) 113 | self._own_address[4] = random.uniform(0, 255) 114 | self._own_address[5] = random.uniform(0, 255) 115 | self._own_address[6] = random.uniform(0, 255) 116 | self._own_address[7] = random.uniform(0, 255) 117 | 118 | def note_activity(self): 119 | self._activity = int(round(time.time()*1000)) 120 | 121 | def is_inactive(self): 122 | if (int(round(time.time()*1000))-self._activity) > C.INACTIVITY_TIME: 123 | self._activity = int(round(time.time()*1000)) 124 | return True 125 | else: 126 | return False 127 | -------------------------------------------------------------------------------- /DW1000Mac.py: -------------------------------------------------------------------------------- 1 | """ 2 | This python module deal with medium access control (MAC) of DW1000 3 | """ 4 | 5 | import DW1000Constants as C 6 | import DW1000Ranging 7 | 8 | class DW1000Mac(): 9 | _seq_number = 0 10 | 11 | def __init__(self): 12 | self._seq_number = 0 13 | 14 | def generate_blink_frame(self, source_address, source_short_address): 15 | """ 16 | For poll message, authors use just 2 bytes address 17 | Totla: 12 bytes 18 | """ 19 | # Initialize frame 20 | frame = bytearray() 21 | 22 | # Set constant and sequence number [0] and [1] 23 | frame.append(C.FC_1_BLINK) 24 | frame.append(self._seq_number) 25 | 26 | # Set reversed source address array [2 - 9] 27 | frame.append(source_address[7]) 28 | frame.append(source_address[6]) 29 | frame.append(source_address[5]) 30 | frame.append(source_address[4]) 31 | frame.append(source_address[3]) 32 | frame.append(source_address[2]) 33 | frame.append(source_address[1]) 34 | frame.append(source_address[0]) 35 | 36 | # Set reversed short address array [10 - 11] 37 | frame.append(source_short_address[1]) 38 | frame.append(source_short_address[0]) 39 | 40 | self.increment_seq_number() 41 | 42 | return frame 43 | 44 | def generate_short_mac_frame(self, source_short_address, destination_short_address): 45 | """ 46 | The short frame usually for Resp, Final, or Report 47 | 2 bytes for Destination Address and 2 bytes for Source Address 48 | Total: 9 bytes 49 | """ 50 | 51 | # Init frame 52 | frame = bytearray() 53 | 54 | # Frame control 55 | frame.append(C.FC_1) 56 | frame.append(C.FC_2_SHORT) 57 | # Sequence number modulo 256 58 | frame.append(self._seq_number) 59 | 60 | # PAN ID 61 | frame.append(0xCA) 62 | frame.append(0xDE) 63 | 64 | # Set destination address 65 | frame.append(destination_short_address[1]) 66 | frame.append(destination_short_address[0]) 67 | 68 | # Set source address 69 | frame.append(source_short_address[1]) 70 | frame.append(source_short_address[0]) 71 | 72 | self.increment_seq_number() 73 | 74 | return frame 75 | 76 | def generate_long_mac_frame(self, source_short_address, destination_address): 77 | """ 78 | The long frame for ranging init 79 | 8 bytes for destination address and 2 bytes for source address 80 | Total: 15 bytes 81 | """ 82 | 83 | # Initialize byte array 84 | frame = bytearray() 85 | 86 | frame.append(C.FC_1) # 0 87 | frame.append(C.FC_2) # 1 88 | 89 | frame.append(self._seq_number) # 2 90 | 91 | frame.append(0xCA) # 3 92 | frame.append(0xDE) # 4 93 | 94 | # Destination address (8 bytes, reversed) 95 | frame.append(destination_address[7]) # 5 96 | frame.append(destination_address[6]) # 6 97 | frame.append(destination_address[5]) # 7 98 | frame.append(destination_address[4]) # 8 99 | frame.append(destination_address[3]) # 9 100 | frame.append(destination_address[2]) # 10 101 | frame.append(destination_address[1]) # 11 102 | frame.append(destination_address[0]) # 12 103 | 104 | # Source address (2 bytes, reversed) 105 | frame.append(source_short_address[1]) # 13 106 | frame.append(source_short_address[0]) # 14 107 | 108 | self.increment_seq_number() 109 | 110 | return frame 111 | 112 | def decode_blink_frame(self, frame): 113 | reverse_address = bytearray() 114 | reverse_address.append(frame[9]) 115 | reverse_address.append(frame[8]) 116 | reverse_address.append(frame[7]) 117 | reverse_address.append(frame[6]) 118 | reverse_address.append(frame[5]) 119 | reverse_address.append(frame[4]) 120 | reverse_address.append(frame[3]) 121 | reverse_address.append(frame[2]) 122 | 123 | reverse_short_address = bytearray() 124 | reverse_short_address.append(frame[1]) 125 | reverse_short_address.append(frame[0]) 126 | 127 | return_list = [reverse_address, reverse_short_address] 128 | 129 | return return_list 130 | 131 | def decode_short_mac_frame(self, frame): 132 | address = bytearray() 133 | address.append(frame[1]) 134 | address.append(frame[0]) 135 | 136 | return address 137 | 138 | def decode_long_mac_frame(self, frame): 139 | address = bytearray() 140 | address.append(frame[14]) 141 | address.append(frame[13]) 142 | 143 | return address 144 | 145 | def increment_seq_number(self): 146 | if(self._seq_number == 255): 147 | self._seq_number = 0 148 | else: 149 | self._seq_number += 1 150 | -------------------------------------------------------------------------------- /DW1000Ranging.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedestrian0423/DW1000_Raspi_Python_library/02bfd8bdddf069ba47e0198b8ba7e2568216b536/DW1000Ranging.py -------------------------------------------------------------------------------- /DW1000Time.py: -------------------------------------------------------------------------------- 1 | """ 2 | This python module deal with time/timestamp/distance measurement/management of DW1000 3 | """ 4 | 5 | import DW1000Constants as C 6 | 7 | class DW1000Time(): 8 | """ 9 | This class manages timestamp 10 | """ 11 | 12 | _timestamp = 0 13 | 14 | def __init__(self, data=None, timestamp=None, index=None): 15 | if timestamp is None: 16 | self.timestamp = 0 17 | self.set_timestamp(data, timestamp, index) 18 | 19 | def __del__(self): 20 | self._timestamp = 0 21 | 22 | def set_timestamp(self, data, timestamp, index): 23 | """ 24 | This function sets the specified timestamp into the data that will be sent. 25 | 26 | Args: 27 | data: The data where you will store the timestamp 28 | timeStamp = The timestamp's value 29 | index = The bit from where you will put the timestamp's value 30 | 31 | Returns: 32 | The data with the timestamp added to it 33 | """ 34 | for i in range(0, C.LENGTH_TIMESTAMP): 35 | data[i+index] = int((timestamp >> (i * 8)) & C.MASK_LS_BYTE) 36 | 37 | def get_timestamp(self, data, index): 38 | """ 39 | This function gets the timestamp's value written inside the specified data and returns it. 40 | 41 | Args: 42 | data : the data where you want to extract the timestamp from 43 | index : the index you want to start reading the data from 44 | 45 | Returns: 46 | The timestamp's value read from the given data. 47 | """ 48 | timestamp = 0 49 | for i in range(0, C.LENGTH_TIMESTAMP): 50 | timestamp |= data[i+index] << (i*8) 51 | return timestamp 52 | 53 | def wrap_timestamp(self, timestamp): 54 | """ 55 | This function converts the negative values of the timestamp 56 | due to the overflow into a correct one. 57 | Args : 58 | timestamp : the timestamp's value you want to correct. 59 | Returns: 60 | The corrected timestamp's value. 61 | """ 62 | if timestamp < 0: 63 | timestamp += C.TIME_OVERFLOW 64 | return timestamp 65 | 66 | def get_as_float(self): 67 | """ 68 | This function returns timestamp as microseconds 69 | """ 70 | self.get_as_micro_seconds() 71 | 72 | def get_as_micro_seconds(self): 73 | """ 74 | This function returns timestamp as microseconds 75 | """ 76 | return (self.timestamp % C.TIME_OVERFLOW) * C.TIME_RES 77 | 78 | def get_as_meters(self): 79 | """ 80 | This function returns travel distance as meters with respect to travel time(timestamp) 81 | """ 82 | return (self.timestamp%C.TIME_OVERFLOW)*C.DISTANCE_OF_RADIO 83 | 84 | def is_valid_timestamp(self): 85 | """ 86 | This function check and returns whether timestamp is valid or not 87 | """ 88 | return 0 <= self.timestamp & self.timestamp <= C.TIME_MAX 89 | 90 | ''' 91 | ## Operator overloading 92 | 93 | # assign 94 | def __setattr__(self, assign): 95 | if self == assign: 96 | return self 97 | self.timestamp = assign.get_timestamp() 98 | return self 99 | 100 | # add 101 | def __iadd__(self, add): 102 | self.timestamp += add.get_timestamp() 103 | return self 104 | 105 | def __add__(self, add): 106 | return (self += add) 107 | 108 | # subtract 109 | def __isub__(self, sub): 110 | self.timestamp -= sub.get_timestamp() 111 | return self 112 | 113 | def __sub__(self, sub): 114 | return (self -= sub) 115 | 116 | # multiply 117 | def __imul__(self, factor): 118 | self.timestamp *= factor 119 | return self 120 | 121 | def __mul__(self, factor): 122 | return (self *= factor) 123 | 124 | # divide 125 | def __idiv__(self, factor): 126 | self.timestamp /= factor 127 | return self 128 | 129 | def __div__(self, factor): 130 | return (self /= factor) 131 | ''' 132 | 133 | -------------------------------------------------------------------------------- /Examples/DW1000RangingAnchor.py: -------------------------------------------------------------------------------- 1 | """ 2 | This python script is used to configure the DW1000 chip as an anchor for ranging functionalities. It must be used in conjunction with the RangingTAG script. 3 | It requires the following modules: DW1000, DW1000Constants and monotonic. 4 | """ 5 | 6 | 7 | import DW1000 8 | import monotonic 9 | import DW1000Constants as C 10 | 11 | 12 | lastActivity = 0 13 | expectedMsgId = C.POLL 14 | protocolFailed = False 15 | sentAck = False 16 | receivedAck = False 17 | LEN_DATA = 16 18 | data = [0] * LEN_DATA 19 | timePollAckSentTS = 0 20 | timePollAckReceivedTS = 0 21 | timePollReceivedTS = 0 22 | timeRangeReceivedTS = 0 23 | timePollSentTS = 0 24 | timeRangeSentTS = 0 25 | timeComputedRangeTS = 0 26 | REPLY_DELAY_TIME_US = 7000 27 | 28 | 29 | def millis(): 30 | """ 31 | This function returns the value (in milliseconds) of a clock which never goes backwards. It detects the inactivity of the chip and 32 | is used to avoid having the chip stuck in an undesirable state. 33 | """ 34 | return int(round(monotonic.monotonic() * C.MILLISECONDS)) 35 | 36 | 37 | def handleSent(): 38 | """ 39 | This is a callback called from the module's interrupt handler when a transmission was successful. 40 | It sets the sentAck variable as True so the loop can continue. 41 | """ 42 | global sentAck 43 | sentAck = True 44 | 45 | 46 | def handleReceived(): 47 | """ 48 | This is a callback called from the module's interrupt handler when a reception was successful. 49 | It sets the received receivedAck as True so the loop can continue. 50 | """ 51 | global receivedAck 52 | receivedAck = True 53 | 54 | 55 | def noteActivity(): 56 | """ 57 | This function records the time of the last activity so we can know if the device is inactive or not. 58 | """ 59 | global lastActivity 60 | lastActivity = millis() 61 | 62 | 63 | def resetInactive(): 64 | """ 65 | This function restarts the default polling operation when the device is deemed inactive. 66 | """ 67 | global expectedMsgId 68 | # print("reset inactive") 69 | expectedMsgId = C.POLL 70 | receiver() 71 | noteActivity() 72 | 73 | 74 | def transmitPollAck(): 75 | """ 76 | This function sends the polling acknowledge message which is used to confirm the reception of the polling message. 77 | """ 78 | global data 79 | DW1000.newTransmit() 80 | data[0] = C.POLL_ACK 81 | DW1000.setDelay(REPLY_DELAY_TIME_US, C.MICROSECONDS) 82 | DW1000.setData(data, LEN_DATA) 83 | DW1000.startTransmit() 84 | 85 | 86 | def transmitRangeAcknowledge(): 87 | """ 88 | This functions sends the range acknowledge message which tells the tag that the ranging function was successful and another ranging transmission can begin. 89 | """ 90 | global data 91 | DW1000.newTransmit() 92 | data[0] = C.RANGE_REPORT 93 | DW1000.setData(data, LEN_DATA) 94 | DW1000.startTransmit() 95 | 96 | 97 | def transmitRangeFailed(): 98 | """ 99 | This functions sends the range failed message which tells the tag that the ranging function has failed and to start another ranging transmission. 100 | """ 101 | global data 102 | DW1000.newTransmit() 103 | data[0] = C.RANGE_FAILED 104 | DW1000.setData(data, LEN_DATA) 105 | DW1000.startTransmit() 106 | 107 | 108 | def receiver(): 109 | """ 110 | This function configures the chip to prepare for a message reception. 111 | """ 112 | global data 113 | DW1000.newReceive() 114 | DW1000.receivePermanently() 115 | DW1000.startReceive() 116 | 117 | 118 | def computeRangeAsymmetric(): 119 | """ 120 | This is the function which calculates the timestamp used to determine the range between the devices. 121 | """ 122 | global timeComputedRangeTS 123 | round1 = DW1000.wrapTimestamp(timePollAckReceivedTS - timePollSentTS) 124 | reply1 = DW1000.wrapTimestamp(timePollAckSentTS - timePollReceivedTS) 125 | round2 = DW1000.wrapTimestamp(timeRangeReceivedTS - timePollAckSentTS) 126 | reply2 = DW1000.wrapTimestamp(timeRangeSentTS - timePollAckReceivedTS) 127 | timeComputedRangeTS = (round1 * round2 - reply1 * reply2) / (round1 + round2 + reply1 + reply2) 128 | 129 | 130 | def loop(): 131 | global sentAck, receivedAck, timePollAckSentTS, timePollReceivedTS, timePollSentTS, timePollAckReceivedTS, timeRangeReceivedTS, protocolFailed, data, expectedMsgId, timeRangeSentTS 132 | if (sentAck == False and receivedAck == False): 133 | if ((millis() - lastActivity) > C.RESET_PERIOD): 134 | resetInactive() 135 | return 136 | 137 | if sentAck: 138 | sentAck = False 139 | msgId = data[0] 140 | if msgId == C.POLL_ACK: 141 | timePollAckSentTS = DW1000.getTransmitTimestamp() 142 | noteActivity() 143 | 144 | if receivedAck: 145 | receivedAck = False 146 | data = DW1000.getData(LEN_DATA) 147 | msgId = data[0] 148 | if msgId != expectedMsgId: 149 | protocolFailed = True 150 | if msgId == C.POLL: 151 | protocolFailed = False 152 | timePollReceivedTS = DW1000.getReceiveTimestamp() 153 | expectedMsgId = C.RANGE 154 | transmitPollAck() 155 | noteActivity() 156 | elif msgId == C.RANGE: 157 | timeRangeReceivedTS = DW1000.getReceiveTimestamp() 158 | expectedMsgId = C.POLL 159 | if protocolFailed == False: 160 | timePollSentTS = DW1000.getTimeStamp(data, 1) 161 | timePollAckReceivedTS = DW1000.getTimeStamp(data, 6) 162 | timeRangeSentTS = DW1000.getTimeStamp(data, 11) 163 | computeRangeAsymmetric() 164 | transmitRangeAcknowledge() 165 | distance = (timeComputedRangeTS % C.TIME_OVERFLOW) * C.DISTANCE_OF_RADIO 166 | print("Distance: %.2f m" %(distance)) 167 | 168 | else: 169 | transmitRangeFailed() 170 | 171 | noteActivity() 172 | 173 | 174 | 175 | try: 176 | PIN_IRQ = 19 177 | PIN_SS = 16 178 | DW1000.begin(PIN_IRQ) 179 | DW1000.setup(PIN_SS) 180 | print("DW1000 initialized") 181 | print("############### ANCHOR ##############") 182 | 183 | DW1000.generalConfiguration("82:17:5B:D5:A9:9A:E2:9C", C.MODE_LONGDATA_RANGE_ACCURACY) 184 | DW1000.registerCallback("handleSent", handleSent) 185 | DW1000.registerCallback("handleReceived", handleReceived) 186 | DW1000.setAntennaDelay(C.ANTENNA_DELAY_RASPI) 187 | 188 | receiver() 189 | noteActivity() 190 | while 1: 191 | loop() 192 | 193 | except KeyboardInterrupt: 194 | DW1000.close() 195 | -------------------------------------------------------------------------------- /Examples/DW1000RangingTAG.py: -------------------------------------------------------------------------------- 1 | """ 2 | This python script is used to configure the DW1000 chip as a tag for ranging functionalities. It must be used in conjunction with the RangingAnchor script. 3 | It requires the following modules: DW1000, DW1000Constants and monotonic. 4 | """ 5 | 6 | 7 | import DW1000 8 | import monotonic 9 | import DW1000Constants as C 10 | 11 | LEN_DATA = 16 12 | data = [0] * LEN_DATA 13 | lastActivity = 0 14 | lastPoll = 0 15 | sentAck = False 16 | receivedAck = False 17 | expectedMsgId = C.POLL_ACK 18 | timePollSentTS = 0 19 | timeRangeSentTS = 0 20 | timePollAckReceivedTS = 0 21 | REPLY_DELAY_TIME_US = 7000 22 | # The polling range frequency defines the time interval between every distance poll in milliseconds. Feel free to change its value. 23 | POLL_RANGE_FREQ = 1000 # the distance between the tag and the anchor will be estimated every second. 24 | 25 | 26 | 27 | def millis(): 28 | """ 29 | This function returns the value (in milliseconds) of a clock which never goes backwards. It detects the inactivity of the chip and 30 | is used to avoid having the chip stuck in an undesirable state. 31 | """ 32 | return int(round(monotonic.monotonic()*C.MILLISECONDS)) 33 | 34 | 35 | def handleSent(): 36 | """ 37 | This is a callback called from the module's interrupt handler when a transmission was successful. 38 | It sets the sentAck variable as True so the loop can continue. 39 | """ 40 | global sentAck 41 | sentAck = True 42 | 43 | 44 | def handleReceived(): 45 | """ 46 | This is a callback called from the module's interrupt handler when a reception was successful. 47 | It sets the received receivedAck as True so the loop can continue. 48 | """ 49 | global receivedAck 50 | receivedAck = True 51 | 52 | 53 | def receiver(): 54 | """ 55 | This function configures the chip to prepare for a message reception. 56 | """ 57 | DW1000.newReceive() 58 | DW1000.receivePermanently() 59 | DW1000.startReceive() 60 | 61 | 62 | def noteActivity(): 63 | """ 64 | This function records the time of the last activity so we can know if the device is inactive or not. 65 | """ 66 | global lastActivity 67 | lastActivity = millis() 68 | 69 | 70 | def resetInactive(): 71 | """ 72 | This function restarts the default polling operation when the device is deemed inactive. 73 | """ 74 | global expectedMsgId 75 | # print("Reset inactive") 76 | expectedMsgId = C.POLL_ACK 77 | transmitPoll() 78 | noteActivity() 79 | 80 | 81 | def transmitPoll(): 82 | """ 83 | This function sends the polling message which is the first transaction to enable ranging functionalities. 84 | It checks if an anchor is operational. 85 | """ 86 | global data, lastPoll 87 | while (millis() - lastPoll < POLL_RANGE_FREQ): 88 | pass 89 | DW1000.newTransmit() 90 | data[0] = C.POLL 91 | DW1000.setData(data, LEN_DATA) 92 | DW1000.startTransmit() 93 | lastPoll = millis() 94 | 95 | 96 | def transmitRange(): 97 | """ 98 | This function sends the range message containing the timestamps used to calculate the range between the devices. 99 | """ 100 | global data, timeRangeSentTS 101 | DW1000.newTransmit() 102 | data[0] = C.RANGE 103 | timeRangeSentTS = DW1000.setDelay(REPLY_DELAY_TIME_US, C.MICROSECONDS) 104 | DW1000.setTimeStamp(data, timePollSentTS, 1) 105 | DW1000.setTimeStamp(data, timePollAckReceivedTS, 6) 106 | DW1000.setTimeStamp(data, timeRangeSentTS, 11) 107 | DW1000.setData(data, LEN_DATA) 108 | DW1000.startTransmit() 109 | 110 | 111 | def loop(): 112 | global sentAck, receivedAck, data, timePollAckReceivedTS, timePollSentTS, timeRangeSentTS, expectedMsgId 113 | if (sentAck == False and receivedAck == False): 114 | if ((millis() - lastActivity) > C.RESET_PERIOD): 115 | resetInactive() 116 | return 117 | 118 | if sentAck: 119 | sentAck = False 120 | msgID = data[0] 121 | if msgID == C.POLL: 122 | timePollSentTS = DW1000.getTransmitTimestamp() 123 | elif msgID == C.RANGE: 124 | timeRangeSentTS = DW1000.getTransmitTimestamp() 125 | noteActivity() 126 | 127 | if receivedAck: 128 | receivedAck = False 129 | data = DW1000.getData(LEN_DATA) 130 | msgID = data[0] 131 | if msgID != expectedMsgId: 132 | expectedMsgId = C.POLL_ACK 133 | transmitPoll() 134 | return 135 | if msgID == C.POLL_ACK: 136 | timePollAckReceivedTS = DW1000.getReceiveTimestamp() 137 | expectedMsgId = C.RANGE_REPORT 138 | transmitRange() 139 | noteActivity() 140 | elif msgID == C.RANGE_REPORT: 141 | expectedMsgId = C.POLL_ACK 142 | transmitPoll() 143 | noteActivity() 144 | elif msgID == C.RANGE_FAILED: 145 | expectedMsgId = C.POLL_ACK 146 | transmitPoll() 147 | noteActivity() 148 | 149 | 150 | try: 151 | PIN_IRQ = 19 152 | PIN_SS = 16 153 | DW1000.begin(PIN_IRQ) 154 | DW1000.setup(PIN_SS) 155 | print("DW1000 initialized") 156 | print("############### TAG ##############") 157 | 158 | DW1000.generalConfiguration("7D:00:22:EA:82:60:3B:9C", C.MODE_LONGDATA_RANGE_ACCURACY) 159 | DW1000.registerCallback("handleSent", handleSent) 160 | DW1000.registerCallback("handleReceived", handleReceived) 161 | DW1000.setAntennaDelay(C.ANTENNA_DELAY_RASPI) 162 | 163 | receiver() 164 | transmitPoll() 165 | noteActivity() 166 | while 1: 167 | loop() 168 | 169 | except KeyboardInterrupt: 170 | DW1000.close() 171 | -------------------------------------------------------------------------------- /Examples/PingPong.py: -------------------------------------------------------------------------------- 1 | """ 2 | This python script is used to configure the DW1000 chip as a device to emulate a ping/pong message transmission. 3 | It must be used in conjunction with another PingPong script setup as the opposite trxToggle, meaning that there should be two scripts : Receiver + Transmitter 4 | It requires the following modules: DW1000, DW1000Constants 5 | """ 6 | 7 | 8 | import DW1000 9 | import DW1000Constants as C 10 | 11 | msg = "" 12 | trxAck = False 13 | # Change this value to set the chip as either a receiver or transmitter 14 | trxToggle = C.RECEIVER 15 | 16 | def handleSent(): 17 | """ 18 | This is a callback called from the module's interrupt handler when a transmission was successful. 19 | It sets the sent trxAck as True so the loop can continue. 20 | """ 21 | global trxAck 22 | trxAck = True 23 | 24 | def handleReceived(): 25 | """ 26 | This is a callback called from the module's interrupt handler when a reception was successful. 27 | It sets the received trxAck as True so the loop can continue. 28 | """ 29 | global trxAck 30 | trxAck = True 31 | 32 | def receiver(): 33 | """ 34 | This function configures the chip to prepare for a message reception. 35 | """ 36 | DW1000.newReceive() 37 | DW1000.receivePermanently() 38 | DW1000.startReceive() 39 | 40 | def transmitter(): 41 | """ 42 | This function configures the chip to prepare for a transmission. 43 | It modifies the data that will be sent and start the transmission with the chosen delay. 44 | """ 45 | DW1000.newTransmit() 46 | DW1000.setDataStr(msg) 47 | DW1000.setDelay(2000, C.MILLISECONDS) 48 | DW1000.startTransmit() 49 | 50 | try: 51 | PIN_IRQ = 19 52 | PIN_SS = 16 53 | DW1000.begin(PIN_IRQ) 54 | DW1000.setup(PIN_SS) 55 | print("DW1000 initialized ...") 56 | 57 | DW1000.generalConfiguration("FF:FF:FF:FF:00:00:00:00", C.MODE_LONGDATA_RANGE_LOWPOWER) 58 | DW1000.registerCallback("handleSent", handleSent) 59 | DW1000.registerCallback("handleReceived", handleReceived) 60 | if (trxToggle == C.TRANSMITTER): 61 | msg = "Ping...." 62 | receiver() 63 | transmitter() 64 | else: 65 | msg = "... and Pong" 66 | receiver() 67 | 68 | while 1: 69 | if trxAck: 70 | trxAck = False 71 | trxToggle = not trxToggle 72 | if trxToggle: 73 | rxMsg = DW1000.getDataStr() 74 | print("Received : " + rxMsg) 75 | transmitter() 76 | else: 77 | print("Transmitted: " + msg) 78 | 79 | 80 | except KeyboardInterrupt: 81 | DW1000.close() -------------------------------------------------------------------------------- /Examples/Receiver.py: -------------------------------------------------------------------------------- 1 | """ 2 | This python script is used to configure the DW1000 chip as a receiver and start receiving message permanently. It must be used in conjunction with the Sender script. 3 | It receives the message and then prints it in the console. 4 | It requires the following modules: DW1000, DW1000Constants 5 | """ 6 | 7 | 8 | import DW1000 9 | import DW1000Constants as C 10 | 11 | received = False 12 | 13 | def handleReceived(): 14 | """ 15 | This is a callback called from the module's interrupt handler when a reception was successful. 16 | It sets the received variable as True so the loop can continue. 17 | """ 18 | global received 19 | received = True 20 | 21 | 22 | def receiver(): 23 | """ 24 | This function configures the chip to prepare for a message reception. 25 | """ 26 | DW1000.newReceive() 27 | DW1000.receivePermanently() 28 | DW1000.startReceive() 29 | 30 | 31 | try: 32 | PIN_IRQ = 19 33 | PIN_SS = 16 34 | DW1000.begin(PIN_IRQ) 35 | DW1000.setup(PIN_SS) 36 | print("DW1000 initialized") 37 | 38 | DW1000.generalConfiguration("7D:00:22:EA:82:60:3B:9C", C.MODE_LONGDATA_RANGE_LOWPOWER) 39 | DW1000.registerCallback("handleReceived", handleReceived) 40 | receiver() 41 | while 1: 42 | if received: 43 | fpPwr = DW1000.getFirstPathPower() 44 | rxPwr = DW1000.getReceivePower() 45 | rcvQuality = DW1000.getReceiveQuality() 46 | msg = DW1000.getDataStr() 47 | print(msg) 48 | print("FP power: %f dBm" % (fpPwr)) 49 | print("RX power: %f dBm" % (rxPwr)) 50 | print("Signal quality: %f \n" % (rcvQuality)) 51 | received = False 52 | 53 | except KeyboardInterrupt: 54 | DW1000.close() 55 | -------------------------------------------------------------------------------- /Examples/Sender.py: -------------------------------------------------------------------------------- 1 | """ 2 | This python script is used to configure the DW1000 chip as a sender and start sending message . It must be used in conjunction with the Receiver script. 3 | It sends the custom message with a specified delay (2 sec by default). 4 | It requires the following modules: DW1000, DW1000Constants 5 | """ 6 | 7 | 8 | import DW1000 9 | import DW1000Constants as C 10 | 11 | number = 1 12 | sent = False 13 | SEND_DELAY = 2000 14 | 15 | 16 | def handleSent(): 17 | """ 18 | This is a callback called from the module's interrupt handler when a transmission was successful. 19 | It sets the sent variable as True so the loop can continue. 20 | """ 21 | global sent 22 | sent = True 23 | 24 | def transmitter(): 25 | """ 26 | This function configures the chip to prepare for a transmission. 27 | It modifies the data that will be sent and start the transmission with the chosen delay. 28 | """ 29 | global number 30 | DW1000.newTransmit() 31 | msg = "Hello Raspi3, it's #" + str(number) 32 | DW1000.setDataStr(msg) 33 | DW1000.setDelay(SEND_DELAY, C.MILLISECONDS) 34 | DW1000.startTransmit() 35 | number += 1 36 | 37 | try: 38 | PIN_IRQ = 19 39 | PIN_SS = 16 40 | DW1000.begin(PIN_IRQ) 41 | DW1000.setup(PIN_SS) 42 | print("DW1000 initialized ...") 43 | DW1000.generalConfiguration("7D:00:22:EA:82:60:3B:9C", C.MODE_LONGDATA_RANGE_LOWPOWER) 44 | DW1000.registerCallback("handleSent", handleSent) 45 | transmitter() 46 | while 1: 47 | if sent: 48 | transmitter() 49 | sent=False 50 | 51 | except KeyboardInterrupt: 52 | DW1000.close() 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DW1000 Python Library for Raspberry Pi 2 | 3 | This module provides functions allowing the use of the DW1000 chip with a Raspberry Pi using Python scripts. It is an adaptation in Python language of the [arduino-dw1000] library. 4 | This chip embeds Ultra Wide Band (UWB) technology which can be used for message transmissions and more commonly, ranging functionality. 5 | 6 | The following external python modules/libraries are necessary for its proper use: 7 | * [spidev] : This is a standard python module used to interface SPI devices with the Raspberry Pi via the spidev linux kernel driver. 8 | * [monotonic] (used in the ranging scripts only) : This module provides a function returning the value of a clock which never goes backwards. If you have Python 3 installed on your Raspberry Pi, it is not required since you can use time.monotonic() instead. 9 | * [RPi.GPIO] : This is the standard python module used to interact with the GPIOs available on the Raspberry Pi. 10 | 11 | [arduino-dw1000]: 12 | [monotonic]: 13 | [spidev]: 14 | [RPi.GPIO]: 15 | -------------------------------------------------------------------------------- /RangingAnchor.py: -------------------------------------------------------------------------------- 1 | """ 2 | This python script is used to configure the DW1000 chip as an anchor for ranging functionalities. It must be used in conjunction with the RangingTAG script. 3 | It requires the following modules: DW1000, DW1000Constants and monotonic. 4 | """ 5 | 6 | 7 | import DW1000 8 | import monotonic 9 | import DW1000Constants as C 10 | 11 | class RangingAnchor(object): 12 | dw1000_device = None 13 | 14 | lastActivity = 0 15 | expectedMsgId = C.POLL 16 | protocolFailed = False 17 | sentAck = False 18 | receivedAck = False 19 | LEN_DATA = 18 20 | data = [0] * LEN_DATA 21 | timePollAckSentTS = 0 22 | timePollAckReceivedTS = 0 23 | timePollReceivedTS = 0 24 | timeRangeReceivedTS = 0 25 | timePollSentTS = 0 26 | timeRangeSentTS = 0 27 | timeComputedRangeTS = 0 28 | REPLY_DELAY_TIME_US = 7000 29 | 30 | def __init__(self, **kwargs): 31 | self.dw1000_device = DW1000.DW1000(**kwargs) 32 | 33 | def millis(self): 34 | """ 35 | This function returns the value (in milliseconds) of a clock which never goes backwards. It detects the inactivity of the chip and 36 | is used to avoid having the chip stuck in an undesirable state. 37 | """ 38 | return int(round(monotonic.monotonic() * C.MILLISECONDS)) 39 | 40 | 41 | def handleSent(self): 42 | """ 43 | This is a callback called from the module's interrupt handler when a transmission was successful. 44 | It sets the sentAck variable as True so the loop can continue. 45 | """ 46 | self.sentAck = True 47 | 48 | 49 | def handleReceived(self): 50 | """ 51 | This is a callback called from the module's interrupt handler when a reception was successful. 52 | It sets the received receivedAck as True so the loop can continue. 53 | """ 54 | self.receivedAck = True 55 | 56 | 57 | def noteActivity(self): 58 | """ 59 | This function records the time of the last activity so we can know if the device is inactive or not. 60 | """ 61 | self.lastActivity = self.millis() 62 | 63 | 64 | def resetInactive(self): 65 | """ 66 | This function restarts the default polling operation when the device is deemed inactive. 67 | """ 68 | # print("reset inactive") 69 | self.expectedMsgId = C.POLL 70 | self.receiver() 71 | self.noteActivity() 72 | 73 | 74 | def transmitPollAck(self): 75 | """ 76 | This function sends the polling acknowledge message which is used to confirm the reception of the polling message. 77 | """ 78 | self.dw1000_device.newTransmit() 79 | for i in range(0, self.LEN_DATA): 80 | self.data[i] = 0 81 | self.data[0] = C.POLL_ACK 82 | self.data[1] = 0xEF 83 | self.data[2] = 0x01 84 | self.dw1000_device.setDelay(self.REPLY_DELAY_TIME_US, C.MICROSECONDS) 85 | self.dw1000_device.setData(self.data, self.LEN_DATA) 86 | self.dw1000_device.startTransmit() 87 | 88 | 89 | def transmitRangeAcknowledge(self): 90 | """ 91 | This functions sends the range acknowledge message which tells the tag that the ranging function was successful and another ranging transmission can begin. 92 | """ 93 | self.dw1000_device.newTransmit() 94 | for i in range(0, self.LEN_DATA): 95 | self.data[i] = 0 96 | self.data[0] = C.RANGE_REPORT 97 | self.data[1] = 0xEF 98 | self.data[2] = 0x01 99 | self.dw1000_device.setData(self.data, self.LEN_DATA) 100 | self.dw1000_device.startTransmit() 101 | 102 | 103 | def transmitRangeFailed(self): 104 | """ 105 | This functions sends the range failed message which tells the tag that the ranging function has failed and to start another ranging transmission. 106 | """ 107 | self.dw1000_device.newTransmit() 108 | for i in range(0, self.LEN_DATA): 109 | self.data[i] = 0 110 | self.data[0] = C.RANGE_FAILED 111 | self.dw1000_device.setData(self.data, self.LEN_DATA) 112 | self.dw1000_device.startTransmit() 113 | 114 | 115 | def receiver(self): 116 | """ 117 | This function configures the chip to prepare for a message reception. 118 | """ 119 | self.dw1000_device.newReceive() 120 | self.dw1000_device.receivePermanently() 121 | self.dw1000_device.startReceive() 122 | 123 | 124 | def computeRangeAsymmetric(self): 125 | """ 126 | This is the function which calculates the timestamp used to determine the range between the devices. 127 | """ 128 | round1 = self.dw1000_device.wrapTimestamp(self.timePollAckReceivedTS - self.timePollSentTS) 129 | reply1 = self.dw1000_device.wrapTimestamp(self.timePollAckSentTS - self.timePollReceivedTS) 130 | round2 = self.dw1000_device.wrapTimestamp(self.timeRangeReceivedTS - self.timePollAckSentTS) 131 | reply2 = self.dw1000_device.wrapTimestamp(self.timeRangeSentTS - self.timePollAckReceivedTS) 132 | self.timeComputedRangeTS = (round1 * round2 - reply1 * reply2) / (round1 + round2 + reply1 + reply2) 133 | 134 | 135 | def loop(self): 136 | if (self.sentAck is False and self.receivedAck is False): 137 | if ((self.millis() - self.lastActivity) > C.RESET_PERIOD): 138 | self.resetInactive() 139 | return 140 | 141 | if self.sentAck: 142 | self.sentAck = False 143 | msgId = self.data[0] 144 | if msgId == C.POLL_ACK: 145 | self.timePollAckSentTS = self.dw1000_device.getTransmitTimestamp() 146 | self.noteActivity() 147 | 148 | if self.receivedAck: 149 | self.receivedAck = False 150 | self.data = self.dw1000_device.getData(self.LEN_DATA) 151 | msgId = self.data[0] 152 | if msgId != self.expectedMsgId: 153 | self.protocolFailed = True 154 | 155 | shortAddress = [0] * 2 156 | shortAddress[0] = self.data[1] 157 | shortAddress[1] = self.data[2] 158 | print("Short Address: %02X:%02X" % (shortAddress[1], shortAddress[0])) 159 | 160 | if msgId == C.POLL: 161 | self.protocolFailed = False 162 | self.timePollReceivedTS = self.dw1000_device.getReceiveTimestamp() 163 | self.expectedMsgId = C.RANGE 164 | self.transmitPollAck() 165 | self.noteActivity() 166 | elif msgId == C.RANGE: 167 | self.timeRangeReceivedTS = self.dw1000_device.getReceiveTimestamp() 168 | self.expectedMsgId = C.POLL 169 | if self.protocolFailed == False: 170 | self.timePollSentTS = self.dw1000_device.getTimeStamp(self.data, 3) 171 | self.timePollAckReceivedTS = self.dw1000_device.getTimeStamp(self.data, 8) 172 | self.timeRangeSentTS = self.dw1000_device.getTimeStamp(self.data, 13) 173 | self.computeRangeAsymmetric() 174 | self.transmitRangeAcknowledge() 175 | distance = (self.timeComputedRangeTS % C.TIME_OVERFLOW) * C.DISTANCE_OF_RADIO 176 | print("Distance: %.2f m" %(distance)) 177 | 178 | else: 179 | self.transmitRangeFailed() 180 | 181 | self.noteActivity() 182 | 183 | irq = 5 184 | ss = 6 185 | rst = None 186 | bus = 0 187 | device = 0 188 | 189 | rangingAnchor = RangingAnchor(irq=irq, rst=rst, bus=bus, device=device) 190 | 191 | try: 192 | #PIN_IRQ = 5 193 | #PIN_SS = 6 194 | rangingAnchor.dw1000_device.setup(ss) 195 | print("DW1000 initialized") 196 | print("############### ANCHOR ##############") 197 | 198 | rangingAnchor.dw1000_device.generalConfiguration("82:17:5B:D5:A9:9A:E2:9C", C.MODE_LONGDATA_RANGE_ACCURACY) 199 | rangingAnchor.dw1000_device.registerCallback("handleSent", rangingAnchor.handleSent) 200 | rangingAnchor.dw1000_device.registerCallback("handleReceived", rangingAnchor.handleReceived) 201 | rangingAnchor.dw1000_device.setAntennaDelay(C.ANTENNA_DELAY_RASPI) 202 | 203 | rangingAnchor.receiver() 204 | rangingAnchor.noteActivity() 205 | while 1: 206 | rangingAnchor.loop() 207 | 208 | except KeyboardInterrupt: 209 | rangingAnchor.dw1000_device.close() 210 | -------------------------------------------------------------------------------- /RangingTag.py: -------------------------------------------------------------------------------- 1 | """ 2 | This python script is used to configure the DW1000 chip as a tag for ranging functionalities. It must be used in conjunction with the RangingAnchor script. 3 | It requires the following modules: DW1000, DW1000Constants and monotonic. 4 | """ 5 | 6 | 7 | import DW1000 8 | import monotonic 9 | import DW1000Constants as C 10 | 11 | class RangingTag(): 12 | dw1000_device = None 13 | 14 | LEN_DATA = 18 15 | data = [0] * LEN_DATA 16 | lastActivity = 0 17 | lastPoll = 0 18 | sentAck = False 19 | receivedAck = False 20 | expectedMsgId = C.POLL_ACK 21 | timePollSentTS = 0 22 | timeRangeSentTS = 0 23 | timePollAckReceivedTS = 0 24 | REPLY_DELAY_TIME_US = 7000 25 | 26 | # The polling range frequency defines the time interval between every distance poll in milliseconds. Feel free to change its value. 27 | POLL_RANGE_FREQ = 1000 # the distance between the tag and the anchor will be estimated every second. 28 | 29 | def __init__(self, **kwargs): 30 | self.dw1000_device = DW1000.DW1000(**kwargs) 31 | 32 | 33 | 34 | def millis(self): 35 | """ 36 | This function returns the value (in milliseconds) of a clock which never goes backwards. It detects the inactivity of the chip and 37 | is used to avoid having the chip stuck in an undesirable state. 38 | """ 39 | return int(round(monotonic.monotonic()*C.MILLISECONDS)) 40 | 41 | 42 | def handleSent(self): 43 | """ 44 | This is a callback called from the module's interrupt handler when a transmission was successful. 45 | It sets the sentAck variable as True so the loop can continue. 46 | """ 47 | self.sentAck = True 48 | 49 | 50 | def handleReceived(self): 51 | """ 52 | This is a callback called from the module's interrupt handler when a reception was successful. 53 | It sets the received receivedAck as True so the loop can continue. 54 | """ 55 | self.receivedAck = True 56 | 57 | 58 | def receiver(self): 59 | """ 60 | This function configures the chip to prepare for a message reception. 61 | """ 62 | self.dw1000_device.newReceive() 63 | self.dw1000_device.receivePermanently() 64 | self.dw1000_device.startReceive() 65 | 66 | 67 | def noteActivity(self): 68 | """ 69 | This function records the time of the last activity so we can know if the device is inactive or not. 70 | """ 71 | self.lastActivity = self.millis() 72 | 73 | 74 | def resetInactive(self): 75 | """ 76 | This function restarts the default polling operation when the device is deemed inactive. 77 | """ 78 | # print("Reset inactive") 79 | self.expectedMsgId = C.POLL_ACK 80 | self.transmitPoll() 81 | self.noteActivity() 82 | 83 | 84 | def transmitPoll(self): 85 | """ 86 | This function sends the polling message which is the first transaction to enable ranging functionalities. 87 | It checks if an anchor is operational. 88 | """ 89 | while (self.millis() - self.lastPoll < self.POLL_RANGE_FREQ): 90 | pass 91 | self.dw1000_device.newTransmit() 92 | for i in range(0, self.LEN_DATA): 93 | self.data[i] = 0 94 | self.data[0] = C.POLL 95 | self.data[1] = 0xAB 96 | self.data[2] = 0xCD 97 | self.dw1000_device.setData(self.data, self.LEN_DATA) 98 | self.dw1000_device.startTransmit() 99 | self.lastPoll = self.millis() 100 | 101 | 102 | def transmitRange(self): 103 | """ 104 | This function sends the range message containing the timestamps used to calculate the range between the devices. 105 | """ 106 | self.dw1000_device.newTransmit() 107 | for i in range(0, self.LEN_DATA): 108 | self.data[i] = 0 109 | self.data[0] = C.RANGE 110 | self.data[1] = 0xAB 111 | self.data[2] = 0xCD 112 | self.timeRangeSentTS = self.dw1000_device.setDelay(self.REPLY_DELAY_TIME_US, C.MICROSECONDS) 113 | self.dw1000_device.setTimeStamp(self.data, self.timePollSentTS, 3) 114 | self.dw1000_device.setTimeStamp(self.data, self.timePollAckReceivedTS, 8) 115 | self.dw1000_device.setTimeStamp(self.data, self.timeRangeSentTS, 13) 116 | self.dw1000_device.setData(self.data, self.LEN_DATA) 117 | self.dw1000_device.startTransmit() 118 | 119 | 120 | def loop(self): 121 | global sentAck, receivedAck, data, timePollAckReceivedTS, timePollSentTS, timeRangeSentTS, expectedMsgId 122 | if (self.sentAck == False and self.receivedAck == False): 123 | if ((self.millis() - self.lastActivity) > C.RESET_PERIOD): 124 | self.resetInactive() 125 | return 126 | 127 | if self.sentAck: 128 | self.sentAck = False 129 | msgID = self.data[0] 130 | if msgID == C.POLL: 131 | self.timePollSentTS = self.dw1000_device.getTransmitTimestamp() 132 | elif msgID == C.RANGE: 133 | self.timeRangeSentTS = self.dw1000_device.getTransmitTimestamp() 134 | self.noteActivity() 135 | 136 | if self.receivedAck: 137 | self.receivedAck = False 138 | self.data = self.dw1000_device.getData(self.LEN_DATA) 139 | msgID = self.data[0] 140 | if msgID != self.expectedMsgId: 141 | self.expectedMsgId = C.POLL_ACK 142 | self.transmitPoll() 143 | return 144 | 145 | shortAddress = [0] * 2 146 | shortAddress[0] = self.data[1] 147 | shortAddress[1] = self.data[2] 148 | print("Short Address: %02X:%02X" % (shortAddress[1], shortAddress[0])) 149 | 150 | if msgID == C.POLL_ACK: 151 | self.timePollAckReceivedTS = self.dw1000_device.getReceiveTimestamp() 152 | self.expectedMsgId = C.RANGE_REPORT 153 | self.transmitRange() 154 | self.noteActivity() 155 | elif msgID == C.RANGE_REPORT: 156 | self.expectedMsgId = C.POLL_ACK 157 | # need to add distance information to data 158 | self.transmitPoll() 159 | self.noteActivity() 160 | elif msgID == C.RANGE_FAILED: 161 | self.expectedMsgId = C.POLL_ACK 162 | self.transmitPoll() 163 | self.noteActivity() 164 | 165 | 166 | 167 | 168 | irq = 5 169 | ss = 6 170 | rst = None 171 | bus = 0 172 | device = 0 173 | 174 | rangingTag = RangingTag(irq=irq, rst=rst, bus=bus, device=device) 175 | 176 | try: 177 | rangingTag.dw1000_device.setup(ss) 178 | print("DW1000 initialized") 179 | print("############### TAG ##############") 180 | 181 | rangingTag.dw1000_device.generalConfiguration("7D:00:22:EA:82:60:3B:9C", C.MODE_LONGDATA_RANGE_ACCURACY) 182 | rangingTag.dw1000_device.registerCallback("handleSent", rangingTag.handleSent) 183 | rangingTag.dw1000_device.registerCallback("handleReceived", rangingTag.handleReceived) 184 | rangingTag.dw1000_device.setAntennaDelay(C.ANTENNA_DELAY_RASPI) 185 | 186 | rangingTag.receiver() 187 | rangingTag.transmitPoll() 188 | rangingTag.noteActivity() 189 | while 1: 190 | rangingTag.loop() 191 | 192 | except KeyboardInterrupt: 193 | rangingTag.dw1000_device.close() 194 | --------------------------------------------------------------------------------