DW1000 UWB driver based on work of Matthias Grob & Manuel Stalder - ETH Zürich - 2015
Revision 8:0b408e77b701, committed 2016-04-18
- Comitter:
- AndyA
- Date:
- Mon Apr 18 16:58:27 2016 +0000
- Parent:
- 7:b13881dbb09d
- Child:
- 9:326bf149c8bc
- Commit message:
- f
Changed in this revision
--- a/DW1000.cpp Wed Apr 13 09:07:14 2016 +0000 +++ b/DW1000.cpp Mon Apr 18 16:58:27 2016 +0000 @@ -6,128 +6,28 @@ DW1000::DW1000(UWBMode setup, PinName MOSI, PinName MISO, PinName SCLK, PinName CS, PinName IRQ) : irq(IRQ), spi(MOSI, MISO, SCLK), cs(CS) { setCallbacks(NULL, NULL); + DW1000Setup newSetup(DW1000Setup::fastLocationC5); + systemConfig.applyConfig(&newSetup); deselect(); // Chip must be deselected first spi.format(8,0); // Setup the spi for standard 8 bit data and SPI-Mode 0 (GPIO5, GPIO6 open circuit or ground on DW1000) spi.frequency(SPIRATE_PLL); // with a 1MHz clock rate (worked up to 49MHz in our Test) resetAll(); // we do a soft reset of the DW1000 everytime the driver starts - - switch (setup) { - case user110k: // values from Matthias Grob & Manuel Stalder - ETH Zürich - library - - systemConfig.setChannel(5); - systemConfig.setPRF(DW1000Setup::prf16MHz); - systemConfig.setDataRate(DW1000Setup::kbps110); - systemConfig.setSfd(DW1000Setup::standard); - systemConfig.setPreambleLength(DW1000Setup::pre1024); - systemConfig.setPreambleCode(3); - systemConfig.setSmartPower(false); - - setupRadio(); - - setTxPower(230); // power = 23dB gain - - setRxDelay(1<<14); // set delays to 2^14 (1/4 of max) - setTxDelay(1<<14); - break; - - case tunedDefault: // User Manual "2.5.5 Default Configurations that should be modified" p. 22 - default: - - systemConfig.setChannel(5); - systemConfig.setPRF(DW1000Setup::prf16MHz); - systemConfig.setDataRate(DW1000Setup::kbps6800); - systemConfig.setSfd(DW1000Setup::standard); - systemConfig.setPreambleLength(DW1000Setup::pre128); - systemConfig.setPreambleCode(3); - systemConfig.setSmartPower(false); - - setupRadio(); - - setTxPower(230,260,290); // power = 23dB gain - setRxDelay(0); - setTxDelay(0); - - break; - case minPacketSize: - systemConfig.setChannel(5); - systemConfig.setPRF(DW1000Setup::prf64MHz); - systemConfig.setDataRate(DW1000Setup::kbps6800); - systemConfig.setSfd(DW1000Setup::standard); - systemConfig.setPreambleLength(DW1000Setup::pre64); - systemConfig.setPreambleCode(10); - systemConfig.setSmartPower(true); - - setupRadio(); - uint16_t txPower = 25*10; // 25dB gain. - // 2 packets per ms max. So can increase TX power of 250us packets by 10log(4/2) dB and 125us packets by 10log(8/2) dB - setTxPower(txPower,txPower,txPower+30,txPower+60); // power = 23dB gain +setupRadio(); + setTxPower(250,250,250+30,250+60); // power = 23dB gain setRxDelay(0); setTxDelay(0); - break; - } - - irq.rise(this, &DW1000::ISR); // attach interrupt handler to rising edge of interrupt pin from DW1000 } -void DW1000::getSetup(char *buffer, int len) -{ - char dataRateString[10]; - if (systemConfig.getDataRate() == DW1000Setup::kbps6800) - strcpy(dataRateString,"6.8 Mbps"); - else if (systemConfig.getDataRate() == DW1000Setup::kbps850) - strcpy(dataRateString,"850 kbps"); - else - strcpy(dataRateString,"110 kbps"); - - char preambleString[8]; - switch (systemConfig.getPreambleLength()) { - default: - strcpy(preambleString,"error"); - break; - case DW1000Setup::pre64: - strcpy(preambleString,"64"); - break; - case DW1000Setup::pre128: - strcpy(preambleString,"128"); - break; - case DW1000Setup::pre256: - strcpy(preambleString,"256"); - break; - case DW1000Setup::pre512: - strcpy(preambleString,"512"); - break; - case DW1000Setup::pre1024: - strcpy(preambleString,"1024"); - break; - case DW1000Setup::pre1536: - strcpy(preambleString,"1536"); - break; - case DW1000Setup::pre2048: - strcpy(preambleString,"2048"); - break; - case DW1000Setup::pre4096: - strcpy(preambleString,"4096"); - break; +DW1000Setup* DW1000::getSetup() { + return &systemConfig; } - snprintf(buffer,len,"Channel:\t%u\r\nPRF:\t%s\r\nData Rate:\t%s\r\nPreamble length:\t%s\r\nPreamble code:\t%u\r\nSmart power:\t%s\r\nSFD:\t%s\r\n", - systemConfig.getChannel(), - (systemConfig.getPRF() == DW1000Setup::prf16MHz)?"16 MHz":"64 MHz", - dataRateString, - preambleString, - systemConfig.getPreambleCode(), - systemConfig.getSmartPower()?"Enabled":"Disabled", - (systemConfig.getSfd() == DW1000Setup::standard)?"Standard":"Non-standard"); - -} - - void DW1000::setupRadio() { setupAGC(); @@ -363,10 +263,10 @@ else registerValue |= 0x02 << 18; - if (systemConfig.getSfd() == DW1000Setup::decaWave) + if (systemConfig.getSfd() == DW1000Setup::decaWave) registerValue |= 0x01 << 17; // enable DW own SFD - if (systemConfig.getSfd() == DW1000Setup::user) { + if (systemConfig.getSfd() == DW1000Setup::user) { registerValue |= 0x01 << 20; // enable user set SFD Tx registerValue |= 0x01 << 21; // enable user set SFD Rx } @@ -435,6 +335,8 @@ powerReg |= powerToRegValue(boost500) << 8; powerReg |= powerToRegValue(boost250) << 16; powerReg |= powerToRegValue(boost125) << 24; + writeRegister32(DW1000_TX_POWER, 0, powerReg); + } void DW1000::setupAnalogRF()
--- a/DW1000.h Wed Apr 13 09:07:14 2016 +0000 +++ b/DW1000.h Mon Apr 18 16:58:27 2016 +0000 @@ -5,328 +5,14 @@ #include "mbed.h" #include "BurstSPI.h" - -// register addresses -// Mnemonic Address Bytes Description -#define DW1000_DEV_ID 0x00 // 4 Device Identifier – includes device type and revision information -#define DW1000_EUI 0x01 // 8 Extended Unique Identifier -#define DW1000_PANADR 0x03 // 4 PAN Identifier and Short Address -#define DW1000_SYS_CFG 0x04 // 4 System Configuration bitmap -#define DW1000_SYS_TIME 0x06 // 5 System Time Counter (40-bit) -#define DW1000_TX_FCTRL 0x08 // 5 Transmit Frame Control -#define DW1000_TX_BUFFER 0x09 // 1024 Transmit Data Buffer -#define DW1000_DX_TIME 0x0A // 5 Delayed Send or Receive Time (40-bit) -#define DW1000_RX_FWTO 0x0C // 2 Receive Frame Wait Timeout Period -#define DW1000_SYS_CTRL 0x0D // 4 System Control Register -#define DW1000_SYS_MASK 0x0E // 4 System Event Mask Register -#define DW1000_SYS_STATUS 0x0F // 5 System Event Status Register -#define DW1000_RX_FINFO 0x10 // 4 RX Frame Information (in double buffer set) -#define DW1000_RX_BUFFER 0x11 // 1024 Receive Data Buffer (in double buffer set) -#define DW1000_RX_FQUAL 0x12 // 8 Rx Frame Quality information (in double buffer set) -#define DW1000_RX_TTCKI 0x13 // 4 Receiver Time Tracking Interval (in double buffer set) -#define DW1000_RX_TTCKO 0x14 // 5 Receiver Time Tracking Offset (in double buffer set) -#define DW1000_RX_TIME 0x15 // 14 Receive Message Time of Arrival (in double buffer set) -#define DW1000_TX_TIME 0x17 // 10 Transmit Message Time of Sending (in double buffer set) -#define DW1000_TX_ANTD 0x18 // 2 16-bit Delay from Transmit to Antenna -#define DW1000_SYS_STATE 0x19 // 5 System State information -#define DW1000_ACK_RESP_T 0x1A // 4 Acknowledgement Time and Response Time -#define DW1000_RX_SNIFF 0x1D // 4 Pulsed Preamble Reception Configuration -#define DW1000_TX_POWER 0x1E // 4 TX Power Control -#define DW1000_CHAN_CTRL 0x1F // 4 Channel Control -#define DW1000_USR_SFD 0x21 // 41 User-specified short/long TX/RX SFD sequences -#define DW1000_AGC_CTRL 0x23 // 32 Automatic Gain Control configuration -#define DW1000_EXT_SYNC 0x24 // 12 External synchronisation control. -#define DW1000_ACC_MEM 0x25 // 4064 Read access to accumulator data -#define DW1000_GPIO_CTRL 0x26 // 44 Peripheral register bus 1 access - GPIO control -#define DW1000_DRX_CONF 0x27 // 44 Digital Receiver configuration -#define DW1000_RF_CONF 0x28 // 58 Analog RF Configuration -#define DW1000_TX_CAL 0x2A // 52 Transmitter calibration block -#define DW1000_FS_CTRL 0x2B // 21 Frequency synthesiser control block -#define DW1000_AON 0x2C // 12 Always-On register set -#define DW1000_OTP_IF 0x2D // 18 One Time Programmable Memory Interface -#define DW1000_LDE_CTRL 0x2E // - Leading edge detection control block -#define DW1000_DIG_DIAG 0x2F // 41 Digital Diagnostics Interface -#define DW1000_PMSC 0x36 // 48 Power Management System Control Block - -// AGC_CTRL sub registers -#define DWAGCCTRL_AGC_CTRL1 0x02 -#define DWAGCCTRL_AGC_TUNE1 0x04 -#define DWAGCCTRL_AGC_TUNE2 0x0C -#define DWAGCCTRL_AGC_TUNE3 0x12 - -// EXT_SYNC sub registers -#define DWEXTSYNC_EC_CTRL 0x00 -#define DWEXTSYNC_EC_RXTC 0x04 -#define DWEXTSYNC_EC_GOLP 0x08 - -// GPIO sub registers -#define DWGPIO_GPIO_MODE 0x00 -#define DWGPIO_GPIO_DIR 0x08 -#define DWGPIO_GPIO_DOUT 0x0C -#define DWGPIO_GPIO_IRQE 0x10 -#define DWGPIO_GPIO_ISEN 0x14 -#define DWGPIO_GPIO_IMODE 0x18 -#define DWGPIO_GPIO_IBES 0x1C -#define DWGPIO_GPIO_ICLR 0x20 -#define DWGPIO_GPIO_IDBE 0x24 -#define DWGPIO_GPIO_RAW 0x28 - -// DRX sub registers -#define DWDRX_DRX_TUNE0B 0x02 -#define DWDRX_DRX_TUNE1A 0x04 -#define DWDRX_DRX_TUNE1B 0x06 -#define DWDRX_DRX_TUNE2 0x08 -#define DWDRX_DRX_SFDTOC 0x20 -#define DWDRX_DRX_PRETOC 0x24 -#define DWDRX_DRX_TUNE4H 0x26 - -//RF conf sub registers -#define DWRFCONF_RF_CONF 0x00 -#define DWRFCONF_RF_RXCTRLH 0x0B -#define DWRFCONF_RF_TXCTRL 0x0C -#define DWRFCONF_RF_STATUS 0x2C -#define DWRFCONF_RF_LDOTUNE 0x30 - -// TX cal sub registers -#define DWTXCAL_TC_SARC 0x00 -#define DWTXCAL_TC_SARL 0x03 -#define DWTXCAL_TC_SARW 0x06 -#define DWTXCAL_TC_PGDELAY 0x0B -#define DWTXCAL_TC_PGTEST 0x0C - -// Freq synth sub registers -#define DWFSCTRL_FS_PLLCFG 0x07 -#define DWFSCTRL_FS_PLLTUNE 0x0B -#define DWFSCTRL_FS_XTALT 0x0E - -// Always on sub registers -#define DWAON_AON_WCFG 0x00 -#define DWAON_AON_CTRL 0x02 -#define DWAON_AON_RDAT 0x03 -#define DWAON_AON_ADDR 0x04 -#define DWAON_AON_CFG0 0x06 -#define DWAON_AON_CFG1 0x0A - -// OTP sub registers -#define DWOTP_OTP_WDAT 0x00 -#define DWOTP_OTP_ADDR 0x04 -#define DWOTP_OTP_CTRL 0x06 -#define DWOTP_OTP_STAT 0x08 -#define DWOTP_OTP_RDAT 0x0A -#define DWOTP_OTP_SRDAT 0x0E -#define DWOTP_OTP_SF 0x12 - -//LDE_IF sub registers -#define DWLDE_LDE_THRESH 0x0000 -#define DWLDE_LDE_CFG1 0x0806 -#define DWLDE_LDE_PPINDX 0x1000 -#define DWLDE_LDE_PPAMPL 0x1002 -#define DWLDE_LDE_RXANTD 0x1804 -#define DWLDE_LDE_CFG2 0x1806 -#define DWLDE_LDE_REPC 0x2804 - -// Dig Diag sub registers -#define DWDIAG_EVC_CTRL 0x00 -#define DWDIAG_EVC_PHE 0x04 -#define DWDIAG_EVC_RSE 0x06 -#define DWDIAG_EVC_FCG 0x08 -#define DWDIAG_EVC_FCE 0x0A -#define DWDIAG_EVC_FFR 0x0C -#define DWDIAG_EVC_OVR 0x0E -#define DWDIAG_EVC_STO 0x10 -#define DWDIAG_EVC_PTO 0x12 -#define DWDIAG_EVC_FWTO 0x14 -#define DWDIAG_EVC_TXFS 0x16 -#define DWDIAG_EVC_HPW 0x18 -#define DWDIAG_EVC_TPW 0x1A -#define DWDIAG_DIAG_TMC 0x24 - -// power control sub registers -#define DWPMSC_PMSC_CTRL0 0x00 -#define DWPMSC_PMSC_CTRL1 0x04 -#define DWPMSC_PMSC_SNOZT 0x0C -#define DWPMSC_PMSC_TXFSEQ 0x26 -#define DWPMSC_PMSC_LEDC 0x28 - - -#define DW1000_WRITE_FLAG 0x80 // First Bit of the address has to be 1 to indicate we want to write -#define DW1000_SUBADDRESS_FLAG 0x40 // if we have a sub address second Bit has to be 1 -#define DW1000_2_SUBADDRESS_FLAG 0x80 // if we have a long sub adress (more than 7 Bit) we set this Bit in the first part - -/* -From user manual 10.5 -Table 59: -DW1000 supported UWB channels and recommended preamble codes +#include "DW1000Registers.h" +#include "DW1000Setup.h" -channel 16MHzPrf 64MHzPrf -1 1,2 9, 10, 11, 12 -2 3, 4 9, 10, 11, 12 -3 5, 6 9, 10, 11, 12 -4 7, 8 17, 18, 19, 20 -5 3, 4 9, 10, 11, 12 -7 7, 8 17, 18, 19, 20 -*/ - - -/** Class for holding DW1000 config options -* -*/ -class DW1000Setup -{ -public: - -/// Constructor - default settings are close to hardware defaults. - DW1000Setup() { - channel = 5; - prf =prf16MHz; - dataRate = kbps850; - sfd = standard; - preamble = pre128; - preambleCode = 3; - enableSmartPower = true; - } - -/// enum for PRF options - enum prf_e {prf16MHz, ///< PRF rate of 16MHz. Lower power - prf64MHz ///< PRF rate of 64MHz. Higher power but more accurate timing. - }; - -/// enum for data rate options - enum dataRate_e {kbps110, ///< Data rate of 110kb/s (non-standard) - kbps850,///< Data rate of 850kb/s - kbps6800///< Data rate of 6.8Mb/s - }; - -/// enum for SFD options - enum sfd_e {standard, ///< IEEE standard SFD - decaWave, ///< Decawave defined SFD - user ///< user defined SFD - }; - -/// enum for preamble length options - enum preamble_e { pre64,///< Preamble is 64 symbols - pre128,///< Preamble is 128 symbols (non-standard) - pre256,///< Preamble is 256 symbols (non-standard) - pre512,///< Preamble is 512 symbols (non-standard) - pre1024,///< Preamble is 1024 symbols - pre1536,///< Preamble is 1536 symbols (non-standard) - pre2048, ///< Preamble is 2048 symbols (non-standard) - pre4096///< Preamble is 4096 symbols - }; - - /** Set the PRF - * @return true if a valid option - */ - bool setPRF(enum prf_e newSetting) { - prf = newSetting; - return true; - }; - - /** Set the Channel - * @return true if a valid option - */ - bool setChannel(unsigned char newChannel) { - if ((channel > 0) && ((channel <= 5) || (channel == 7))) { - channel = newChannel; - return true; - } - return false; - }; - /** Set the SFD - * @return true if a valid option - */ - bool setSfd(enum sfd_e newSetting) { - sfd = newSetting; - return true; - }; - /** Set the Preamble length - * @return true if a valid option - */ - bool setPreambleLength(enum preamble_e newSetting) { - preamble = newSetting; - return true; - }; - /** Set the Data rate - * @return true if a valid option - */ - bool setDataRate(enum dataRate_e newSetting) { - dataRate = newSetting; - return true; - }; - /** Set the Preamble code - * @return true if a valid option - * - * note - not all codes are valid for all channels. Set the channel first. - * TODO - enforce code restrictions - */ - bool setPreambleCode(unsigned char newCode) { - if ((newCode > 0) && (newCode <= 24)) { - preambleCode = newCode; - return true; - } - return false; - }; - /** Set the smartpower state - * @return true if a valid option - * - * only takes effect at 6.8Mb/s - */ - bool setSmartPower(bool enable) { - enableSmartPower = enable; - return true; - }; - - /** Get the current channel - * @return the channel number - */ - unsigned char getChannel() { - return channel; - }; - /** Get the current PRF - * @return the PRF - */ - enum prf_e getPRF() { - return prf; - }; - /** Get the current data rate - * @return the data rate - */ enum dataRate_e getDataRate() { - return dataRate; - }; - - /** Get the current SFD mode - * @return the SFD - */ enum sfd_e getSfd() { - return sfd; - }; - /** Get the current preamble length - * @return the preamble length - */ - enum preamble_e getPreambleLength() { - return preamble; - }; - /** Get the current preamble code - * @return the preamble code - */ - unsigned char getPreambleCode() { - return preambleCode; - }; - /** Get the current smart power mode - * @return true if smartpower is on - */ - bool getSmartPower() { - return enableSmartPower; - }; - -private: - unsigned char channel; // 1-5 , 7 - enum prf_e prf; - enum dataRate_e dataRate; - enum sfd_e sfd; - enum preamble_e preamble; - unsigned char preambleCode; // 1-24. See section 10.5 of user manual for details. - bool enableSmartPower; -}; +#define TIMEUNITS_TO_US (1/(128*499.2)) // conversion between the decawave timeunits (ca 15.65ps) to microseconds. +#define US_TO_TIMEUNITS ((uint32_t)(128*499.2)) // conversion between microseconds to the decawave timeunits (ca 15.65ps). +#define c_mPerS 299792458 +#define c_mmPerTick (c_mPerS * TIMEUNITS_TO_US / 1000) +#define c_mPerTick (c_mmPerTick/1000) typedef enum {minPacketSize, tunedDefault, user110k} UWBMode; @@ -489,6 +175,21 @@ */ void setTxDelay(uint16_t ticks); + + /** Set receive antenna delay in meters + * @param errorDistance Delay in meters at speed of light + */ + void setRxDelayDistance(double errorDistance) { + setRxDelay(errorDistance/c_mPerTick); + }; + + /** Set transmit antenna delay in meters + * @param errorDistance Delay in meters at speed of light + */ + void setTxDelayDistance(double errorDistance) { + setTxDelay(errorDistance/c_mPerTick); + }; + /** Get last packet size * @return The length in bytes of the last packet received */ @@ -522,15 +223,25 @@ */ bool writeOTP(uint16_t word_address,uint32_t data); // program a value in the OTP. It is recommended to reset afterwards. - - /** Get setup description + /** get the current radio configuration + * @return A pointer to a DW1000Setup object of the current setup. * - * @param buffer Data buffer to place description in - * @param len Length of data buffer + * Note to change the setup you must make a copy of the current setup and then pass that to applySetup(). + */ + DW1000Setup *getSetup(); + + /** apply a new radio setup to the UWB system + * @param setup The new settings to use + * @return true if the setup was applied. * - * Places a text string describing the current setup into the suppled buffer. + * The setup object supplied is copied and can be disposed of after the call. + * If the supplied setup fails DW1000Setup::check() then it is ignored and the function returns false. */ - void getSetup(char *buffer, int len); +// bool applySetup(DW1000Setup *setup); + + + uint32_t readRegister32(uint8_t reg, uint16_t subaddress); + void setTxPower(uint16_t normalPowercB, uint16_t boost500 = 0, uint16_t boost250 = 0, uint16_t boost125 = 0); protected: /** Reset the reciever logic @@ -558,8 +269,9 @@ * All gains are in cB (dB * 10). Gains can be between 0 and 335 (33.5dB). * Boost gains are optional, if not specified boost gains are set to the power for the lower rate (e.g. boost125 is set to the boost250 level). */ - void setTxPower(uint16_t normalPowercB, uint16_t boost500 = 0, uint16_t boost250 = 0, uint16_t boost125 = 0); +// void setTxPower(uint16_t normalPowercB, uint16_t boost500 = 0, uint16_t boost250 = 0, uint16_t boost125 = 0); + private: void resetAll(); // soft reset the entire DW1000 (some registers stay as they were see User Manual) @@ -597,7 +309,7 @@ uint8_t readRegister8(uint8_t reg, uint16_t subaddress); // expressive methods to read or write the number of bits written in the name uint16_t readRegister16(uint8_t reg, uint16_t subaddress); - uint32_t readRegister32(uint8_t reg, uint16_t subaddress); +// uint32_t readRegister32(uint8_t reg, uint16_t subaddress); uint64_t readRegister40(uint8_t reg, uint16_t subaddress); uint64_t readRegister64(uint8_t reg, uint16_t subaddress); void writeRegister8(uint8_t reg, uint16_t subaddress, uint8_t buffer);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DW1000Registers.h Mon Apr 18 16:58:27 2016 +0000 @@ -0,0 +1,153 @@ +#ifndef __DWREG_H__ +#define __DWREG_H__ + +// register addresses +// Mnemonic Address Bytes Description +#define DW1000_DEV_ID 0x00 // 4 Device Identifier – includes device type and revision information +#define DW1000_EUI 0x01 // 8 Extended Unique Identifier +#define DW1000_PANADR 0x03 // 4 PAN Identifier and Short Address +#define DW1000_SYS_CFG 0x04 // 4 System Configuration bitmap +#define DW1000_SYS_TIME 0x06 // 5 System Time Counter (40-bit) +#define DW1000_TX_FCTRL 0x08 // 5 Transmit Frame Control +#define DW1000_TX_BUFFER 0x09 // 1024 Transmit Data Buffer +#define DW1000_DX_TIME 0x0A // 5 Delayed Send or Receive Time (40-bit) +#define DW1000_RX_FWTO 0x0C // 2 Receive Frame Wait Timeout Period +#define DW1000_SYS_CTRL 0x0D // 4 System Control Register +#define DW1000_SYS_MASK 0x0E // 4 System Event Mask Register +#define DW1000_SYS_STATUS 0x0F // 5 System Event Status Register +#define DW1000_RX_FINFO 0x10 // 4 RX Frame Information (in double buffer set) +#define DW1000_RX_BUFFER 0x11 // 1024 Receive Data Buffer (in double buffer set) +#define DW1000_RX_FQUAL 0x12 // 8 Rx Frame Quality information (in double buffer set) +#define DW1000_RX_TTCKI 0x13 // 4 Receiver Time Tracking Interval (in double buffer set) +#define DW1000_RX_TTCKO 0x14 // 5 Receiver Time Tracking Offset (in double buffer set) +#define DW1000_RX_TIME 0x15 // 14 Receive Message Time of Arrival (in double buffer set) +#define DW1000_TX_TIME 0x17 // 10 Transmit Message Time of Sending (in double buffer set) +#define DW1000_TX_ANTD 0x18 // 2 16-bit Delay from Transmit to Antenna +#define DW1000_SYS_STATE 0x19 // 5 System State information +#define DW1000_ACK_RESP_T 0x1A // 4 Acknowledgement Time and Response Time +#define DW1000_RX_SNIFF 0x1D // 4 Pulsed Preamble Reception Configuration +#define DW1000_TX_POWER 0x1E // 4 TX Power Control +#define DW1000_CHAN_CTRL 0x1F // 4 Channel Control +#define DW1000_USR_SFD 0x21 // 41 User-specified short/long TX/RX SFD sequences +#define DW1000_AGC_CTRL 0x23 // 32 Automatic Gain Control configuration +#define DW1000_EXT_SYNC 0x24 // 12 External synchronisation control. +#define DW1000_ACC_MEM 0x25 // 4064 Read access to accumulator data +#define DW1000_GPIO_CTRL 0x26 // 44 Peripheral register bus 1 access - GPIO control +#define DW1000_DRX_CONF 0x27 // 44 Digital Receiver configuration +#define DW1000_RF_CONF 0x28 // 58 Analog RF Configuration +#define DW1000_TX_CAL 0x2A // 52 Transmitter calibration block +#define DW1000_FS_CTRL 0x2B // 21 Frequency synthesiser control block +#define DW1000_AON 0x2C // 12 Always-On register set +#define DW1000_OTP_IF 0x2D // 18 One Time Programmable Memory Interface +#define DW1000_LDE_CTRL 0x2E // - Leading edge detection control block +#define DW1000_DIG_DIAG 0x2F // 41 Digital Diagnostics Interface +#define DW1000_PMSC 0x36 // 48 Power Management System Control Block + +// AGC_CTRL sub registers +#define DWAGCCTRL_AGC_CTRL1 0x02 +#define DWAGCCTRL_AGC_TUNE1 0x04 +#define DWAGCCTRL_AGC_TUNE2 0x0C +#define DWAGCCTRL_AGC_TUNE3 0x12 + +// EXT_SYNC sub registers +#define DWEXTSYNC_EC_CTRL 0x00 +#define DWEXTSYNC_EC_RXTC 0x04 +#define DWEXTSYNC_EC_GOLP 0x08 + +// GPIO sub registers +#define DWGPIO_GPIO_MODE 0x00 +#define DWGPIO_GPIO_DIR 0x08 +#define DWGPIO_GPIO_DOUT 0x0C +#define DWGPIO_GPIO_IRQE 0x10 +#define DWGPIO_GPIO_ISEN 0x14 +#define DWGPIO_GPIO_IMODE 0x18 +#define DWGPIO_GPIO_IBES 0x1C +#define DWGPIO_GPIO_ICLR 0x20 +#define DWGPIO_GPIO_IDBE 0x24 +#define DWGPIO_GPIO_RAW 0x28 + +// DRX sub registers +#define DWDRX_DRX_TUNE0B 0x02 +#define DWDRX_DRX_TUNE1A 0x04 +#define DWDRX_DRX_TUNE1B 0x06 +#define DWDRX_DRX_TUNE2 0x08 +#define DWDRX_DRX_SFDTOC 0x20 +#define DWDRX_DRX_PRETOC 0x24 +#define DWDRX_DRX_TUNE4H 0x26 +#define DWDRX_RXPAC_NOSAT 0x2c + + +//RF conf sub registers +#define DWRFCONF_RF_CONF 0x00 +#define DWRFCONF_RF_RXCTRLH 0x0B +#define DWRFCONF_RF_TXCTRL 0x0C +#define DWRFCONF_RF_STATUS 0x2C +#define DWRFCONF_RF_LDOTUNE 0x30 + +// TX cal sub registers +#define DWTXCAL_TC_SARC 0x00 +#define DWTXCAL_TC_SARL 0x03 +#define DWTXCAL_TC_SARW 0x06 +#define DWTXCAL_TC_PGDELAY 0x0B +#define DWTXCAL_TC_PGTEST 0x0C + +// Freq synth sub registers +#define DWFSCTRL_FS_PLLCFG 0x07 +#define DWFSCTRL_FS_PLLTUNE 0x0B +#define DWFSCTRL_FS_XTALT 0x0E + +// Always on sub registers +#define DWAON_AON_WCFG 0x00 +#define DWAON_AON_CTRL 0x02 +#define DWAON_AON_RDAT 0x03 +#define DWAON_AON_ADDR 0x04 +#define DWAON_AON_CFG0 0x06 +#define DWAON_AON_CFG1 0x0A + +// OTP sub registers +#define DWOTP_OTP_WDAT 0x00 +#define DWOTP_OTP_ADDR 0x04 +#define DWOTP_OTP_CTRL 0x06 +#define DWOTP_OTP_STAT 0x08 +#define DWOTP_OTP_RDAT 0x0A +#define DWOTP_OTP_SRDAT 0x0E +#define DWOTP_OTP_SF 0x12 + +//LDE_IF sub registers +#define DWLDE_LDE_THRESH 0x0000 +#define DWLDE_LDE_CFG1 0x0806 +#define DWLDE_LDE_PPINDX 0x1000 +#define DWLDE_LDE_PPAMPL 0x1002 +#define DWLDE_LDE_RXANTD 0x1804 +#define DWLDE_LDE_CFG2 0x1806 +#define DWLDE_LDE_REPC 0x2804 + +// Dig Diag sub registers +#define DWDIAG_EVC_CTRL 0x00 +#define DWDIAG_EVC_PHE 0x04 +#define DWDIAG_EVC_RSE 0x06 +#define DWDIAG_EVC_FCG 0x08 +#define DWDIAG_EVC_FCE 0x0A +#define DWDIAG_EVC_FFR 0x0C +#define DWDIAG_EVC_OVR 0x0E +#define DWDIAG_EVC_STO 0x10 +#define DWDIAG_EVC_PTO 0x12 +#define DWDIAG_EVC_FWTO 0x14 +#define DWDIAG_EVC_TXFS 0x16 +#define DWDIAG_EVC_HPW 0x18 +#define DWDIAG_EVC_TPW 0x1A +#define DWDIAG_DIAG_TMC 0x24 + +// power control sub registers +#define DWPMSC_PMSC_CTRL0 0x00 +#define DWPMSC_PMSC_CTRL1 0x04 +#define DWPMSC_PMSC_SNOZT 0x0C +#define DWPMSC_PMSC_TXFSEQ 0x26 +#define DWPMSC_PMSC_LEDC 0x28 + + +#define DW1000_WRITE_FLAG 0x80 // First Bit of the address has to be 1 to indicate we want to write +#define DW1000_SUBADDRESS_FLAG 0x40 // if we have a sub address second Bit has to be 1 +#define DW1000_2_SUBADDRESS_FLAG 0x80 // if we have a long sub adress (more than 7 Bit) we set this Bit in the first part + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DW1000Setup.cpp Mon Apr 18 16:58:27 2016 +0000 @@ -0,0 +1,262 @@ + +#include "DW1000Setup.h" + +DW1000Setup::DW1000Setup(UWBMode modeToUse) +{ + switch (modeToUse) { + case user110k: // values from Matthias Grob & Manuel Stalder - ETH Zürich - library + + setChannel(5); + setPRF(prf16MHz); + setDataRate(kbps110); + setSfd(standard); + setPreambleLength(pre1024); + setPreambleCode(3); + setSmartPower(false); +// setTxPower(18); + break; + case tunedDefault: // User Manual "2.5.5 Default Configurations that should be modified" p. 22 + default: + setChannel(5); + setPRF(prf16MHz); + setDataRate(kbps6800); + setSfd(standard); + setPreambleLength(pre128); + setPreambleCode(3); + setSmartPower(false); +// setTxPower(18); + break; + case fastLocationC5: + setChannel(5); + setPRF(prf64MHz); + setDataRate(kbps6800); + setSfd(standard); + setPreambleLength(pre64); + setPreambleCode(10); + setSmartPower(true); +// setTxPower(18); + break; + case fastLocationC4: + setChannel(4); + setPRF(prf64MHz); + setDataRate(kbps6800); + setSfd(standard); + setPreambleLength(pre64); + setPreambleCode(18); + setSmartPower(true); +// setTxPower(18); + break; + case rangeRateCompromise: + setChannel(4); + setPRF(prf64MHz); + setDataRate(kbps850); + setSfd(standard); // for some reason decawave doesn't work. + setPreambleLength(pre256); + setPreambleCode(18); + setSmartPower(false); +// setTxPower(18); + break; + } +} + + +DW1000Setup::DW1000Setup(DW1000Setup *orij) { + channel = orij->getChannel(); + prf = orij->getPRF(); + dataRate = orij->getDataRate(); + sfd = orij->getSfd(); + preamble = orij->getPreambleLength(); + preambleCode = orij->getPreambleCode(); + GPIO_Pins = orij->getGPIO(); // 8 = irq, 7 = sync. Others are GPIO + enableSmartPower = orij->getSmartPower(); + memcpy(&powers,orij->getTxPowers(),4*sizeof(float)); + } + + + void DW1000Setup::applyConfig(DW1000Setup *orij) { + channel = orij->getChannel(); + prf = orij->getPRF(); + dataRate = orij->getDataRate(); + sfd = orij->getSfd(); + preamble = orij->getPreambleLength(); + preambleCode = orij->getPreambleCode(); + GPIO_Pins = orij->getGPIO(); // 8 = irq, 7 = sync. Others are GPIO + enableSmartPower = orij->getSmartPower(); + memcpy(&powers,orij->getTxPowers(),4*sizeof(float)); + } + + +bool DW1000Setup::check() +{ + int maxCode = 24; + int minCode = 1; + + if (prf == prf16MHz) + switch (channel) { + case 1: + maxCode = 2; + minCode = 1; + break; + case 2: + case 5: + maxCode = 4; + minCode = 3; + break; + case 3: + maxCode = 6; + minCode = 5; + break; + case 4: + case 7: + maxCode = 8; + minCode = 7; + break; + default: + return false; // invalid channel + } + else + switch (channel) { + case 1: + case 2: + case 3: + case 5: + maxCode = 12; + minCode = 9; + break; + case 4: + case 7: + maxCode = 20; + minCode = 17; + break; + default: + return false; // invalid channel + } + + if ((preambleCode > maxCode) || (preambleCode < minCode)) + return false; + + switch (preamble) { + default: + return false; + case pre64: + case pre128: + if (dataRate != kbps6800) + return false; + break; + case pre256: + if (dataRate == kbps110) + return false; + break; + case pre512: + case pre1024: + case pre1536: + if (dataRate != kbps850) + return false; + break; + case pre2048: + if (dataRate == kbps6800) + return false; + break; + case pre4096: + if (dataRate != kbps110) + return false; + break; + } + + if (enableSmartPower) { + if (dataRate != kbps6800) + return false; + } + return true; +} + +void DW1000Setup::getSetupDescription(char *buffer, int len) +{ + + char dataRateString[10]; + if (dataRate == kbps6800) + strcpy(dataRateString,"6.8 Mbps"); + else if (dataRate == kbps850) + strcpy(dataRateString,"850 kbps"); + else + strcpy(dataRateString,"110 kbps"); + + char preambleString[8]; + switch (preamble) { + default: + strcpy(preambleString,"error"); + break; + case pre64: + strcpy(preambleString,"64"); + break; + case pre128: + strcpy(preambleString,"128"); + break; + case pre256: + strcpy(preambleString,"256"); + break; + case pre512: + strcpy(preambleString,"512"); + break; + case pre1024: + strcpy(preambleString,"1024"); + break; + case pre1536: + strcpy(preambleString,"1536"); + break; + case pre2048: + strcpy(preambleString,"2048"); + break; + case pre4096: + strcpy(preambleString,"4096"); + break; + } + + snprintf(buffer,len,"Channel:\t%u\r\nPRF:\t%s\r\nData Rate:\t%s\r\nPreamble length:\t%s\r\nPreamble code:\t%u\r\nSmart power:\t%s\r\nSFD:\t%s\r\n", + channel, + (prf == prf16MHz)?"16 MHz":"64 MHz", + dataRateString, + preambleString, + preambleCode, + enableSmartPower?"Enabled":"Disabled", + (sfd == standard)?"Standard":"Non-standard"); +} + + bool DW1000Setup::setSmartTxPower(float powerdBm,float power500us,float power250us,float power125us) { + if ((powerdBm < 0) || (powerdBm > 33.5)) + return false; + + powers[0] = powerdBm; + + if ((power500us < powerdBm) || (power500us > 33.5)) + powers[1] = powers[0]; + else + powers[1] = power500us; + + if ((power250us < power500us) || (power250us > 33.5)) + powers[2] = powers[1]; + else + powers[2] = power250us; + + if ((power125us < power250us) || (power125us > 33.5)) + powers[3] = powers[2]; + else + powers[3] = power125us; + + return true; + } + + bool DW1000Setup::setTxPower(float powerdBm,float powerPRF) { + if ((powerdBm < 0) || (powerdBm > 33.5)) + return false; + + powers[0] = powerdBm; + powers[1] = powerdBm; + powers[2] = powerdBm; + powers[3] = powerdBm; + + if ((powerPRF > 0) && (powerPRF < 33.5)) + powers[1] = powerPRF; + + return true; + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DW1000Setup.h Mon Apr 18 16:58:27 2016 +0000 @@ -0,0 +1,278 @@ +#ifndef __DW1000SETUP_H__ +#define __DW1000SETUP_H__ + +#include "mbed.h" +/** Class for holding DW1000 config options +* +* Defaults are channel 5, 16MHz PRF, 850kb/s, standard SFD, 128 symbol preamble, preamble code 3. +* All pins are GPIO other than sync and IRQ. +* Smart power is off. +* +*/ +class DW1000Setup +{ +public: + + /** Supported UWB modes + * + * enum for preset mode combinations + */ + typedef enum {fastLocationC5, ///< maximum data speed, short range. Channel 5 + fastLocationC4, ///< maximum data speed, short range. Channel 5 + tunedDefault, ///< The power up default config with the recomended changes + user110k, ///< 110kb/s settings used by Matthias Grob & Manuel Stalder + rangeRateCompromise ///< 850kb/s settings aimed to give a short packet but with far greater range than the fastLocation options + } UWBMode; + + /** Constructor + * @param modeToUse The operating mode to set the initial settings to. + * + */ + DW1000Setup(UWBMode modeToUse = tunedDefault); + + +/// copy constructor + DW1000Setup(DW1000Setup *orij); + +/// Update this config to match the supplied one + void applyConfig(DW1000Setup *orij); + + +/// enum for PRF options + enum prf_e {prf16MHz, ///< PRF rate of 16MHz. Lower power + prf64MHz ///< PRF rate of 64MHz. Higher power but more accurate timing. + }; + +/// enum for data rate options + enum dataRate_e {kbps110, ///< Data rate of 110kb/s (non-standard) + kbps850,///< Data rate of 850kb/s + kbps6800///< Data rate of 6.8Mb/s + }; + + /** enum for SFD options + * + * To conform to the standard the standard setting should be used. + * The decawave setting claimes to give better performance. Doesn't work for me at 850kb/s but does at 6.8Mb/s + */ + enum sfd_e {standard, ///< IEEE standard SFD + decaWave, ///< Decawave defined SFD + user ///< user defined SFD + }; + +/// enum for preamble length options + enum preamble_e { pre64,///< Preamble is 64 symbols + pre128,///< Preamble is 128 symbols (non-standard) + pre256,///< Preamble is 256 symbols (non-standard) + pre512,///< Preamble is 512 symbols (non-standard) + pre1024,///< Preamble is 1024 symbols + pre1536,///< Preamble is 1536 symbols (non-standard) + pre2048, ///< Preamble is 2048 symbols (non-standard) + pre4096///< Preamble is 4096 symbols + }; + + /** Set the Transmit power for smartpower operation + * @param powerdBm The gain setting in dBm (0-33.5) + * @param power500us The gain setting packets under 500us in dBm (0-33.5) + * @param power250us The gain setting packets under 250us in dBm (0-33.5) + * @param power125us The gain setting packets under 125us in dBm (0-33.5) + * @return true if a valid option + */ + bool setSmartTxPower(float powerdBm,float power500us=0,float power250us=0,float power125us=0) ; + + /** Set the Transmit power for non-smartpower operation + * @param powerdBm The gain setting in dBm for the main packet(0-33.5) + * @param powerPRF The gain setting in dBm for the preamble (0-33.5) + * @return true if a valid option + */ + bool setTxPower(float powerdBm,float powerPRF=0); + + + /** Set the PRF + * @return true if a valid option + */ + bool setPRF(enum prf_e newSetting) { + prf = newSetting; + return true; + }; + + /** Set the Channel + * @return true if a valid option + * + * channels are 1-5 & 7 + */ + bool setChannel(unsigned char newChannel) { + if ((newChannel > 0) && ((newChannel <= 5) || (newChannel == 7))) { + channel = newChannel; + return true; + } + return false; + }; + /** Set the SFD + * @return true if a valid option + */ + bool setSfd(enum sfd_e newSetting) { + sfd = newSetting; + return true; + }; + /** Set the Preamble length + * @return true if a valid option + * + * For 6.8Mb/s it should be 64 to 256 symbols. + * For 850kb/s it should be 256 to 2048 symbols + * For 110kb/s it should be >= 2048 symbols. + */ + bool setPreambleLength(enum preamble_e newSetting) { + preamble = newSetting; + return true; + }; + /** Set the Data rate + * @return true if a valid option + */ + bool setDataRate(enum dataRate_e newSetting) { + dataRate = newSetting; + return true; + }; + /** Set the Preamble code + * @return true if a valid option + * + * note - not all codes are valid for all channels + * + *channel 16MHzPrf 64MHzPrf + 1 1,2 9, 10, 11, 12 + 2 3, 4 9, 10, 11, 12 + 3 5, 6 9, 10, 11, 12 + 4 7, 8 17, 18, 19, 20 + 5 3, 4 9, 10, 11, 12 + 7 7, 8 17, 18, 19, 20 + + */ + bool setPreambleCode(unsigned char newCode) { + if ((newCode > 0) && (newCode <= 24)) { + preambleCode = newCode; + return true; + } + return false; + }; + /** Set the smartpower state + * @return true if a valid option + * + * only takes effect at 6.8Mb/s + */ + bool setSmartPower(bool enable) { + enableSmartPower = enable; + return true; + }; + + + /** Get the current transmit gains + * @return An array containing the power levels + * + * An array of 4 floats is returned. + * For smart power these are the 4 power levels (normal, <500us, <250us, <125us). + * For non-smart power the first and last values are ignored, the second is the power for the phy header, the 3rd is the power for the reaminder of the frame. + */ + const float *getTxPowers() { + return powers; + } + + /** Get the current channel + * @return the channel number + */ + unsigned char getChannel() { + return channel; + }; + /** Get the current PRF + * @return the PRF + */ + enum prf_e getPRF() { + return prf; + }; + /** Get the current data rate + * @return the data rate + */ + enum dataRate_e getDataRate() { + return dataRate; + }; + + /** Get the current SFD mode + * @return the SFD + */ + enum sfd_e getSfd() { + return sfd; + }; + /** Get the current preamble length + * @return the preamble length + */ + enum preamble_e getPreambleLength() { + return preamble; + }; + /** Get the current preamble code + * @return the preamble code + */ + unsigned char getPreambleCode() { + return preambleCode; + }; + /** Get the current smart power mode + * @return true if smartpower is on + */ + bool getSmartPower() { + return enableSmartPower; + }; + + /** Set which pins are GPIO + * + * @param pins A bitmask of which pins are not to be used as GPIO + * + * e.g. 0x01 sets GPIO0 as it's alternative function (RXOKLED) and all other pins to be GPIO. + * + * The default is 0x0180 - GPIO 8 = irq, GPIO 7 = sync. All others are GPIO functionality + */ + void setGPIO(uint16_t pins) { + GPIO_Pins = pins; + }; + + /** Get which pins are GPIO + * + * @return A bitmask of which pins are not to be used as GPIO + * + * e.g. 0x01 Indicates that GPIO0 as it's alternative function (RXOKLED) and all other pins to be GPIO. + * + * The default is 0x0180 - GPIO 8 = irq, GPIO 7 = sync. All others are GPIO functionality + */ + uint16_t getGPIO() { + return GPIO_Pins; + }; + + /** Check that the settings are self consistent + * + * @return true if the settings are valid + * + * Will check the following: + * - Preamble size is sensible for the data rate + * - Preamble code is valid for the channel + * - That smart power is only enabled at 6.8Mb/s + */ + bool check(); + + /** Get setup description + * + * @param buffer Data buffer to place description in + * @param len Length of data buffer + * + * Places a text string describing the current setup into the suppled buffer. + */ + void getSetupDescription(char *buffer, int len); + +private: + float powers[4]; + uint16_t GPIO_Pins; + unsigned char channel; // 1-5 , 7 + enum prf_e prf; + enum dataRate_e dataRate; + enum sfd_e sfd; + enum preamble_e preamble; + unsigned char preambleCode; // 1-24. See section 10.5 of user manual for details. + bool enableSmartPower; +}; + +#endif