DW1000 UWB driver based on work of Matthias Grob & Manuel Stalder - ETH Zürich - 2015
Revision 6:2c77afdf7367, committed 2016-04-11
- Comitter:
- AndyA
- Date:
- Mon Apr 11 14:45:44 2016 +0000
- Parent:
- 5:68ffaa5962d1
- Child:
- 7:b13881dbb09d
- Commit message:
- Improved comments.;
Changed in this revision
--- a/DW1000.cpp Thu Apr 07 16:27:51 2016 +0000 +++ b/DW1000.cpp Mon Apr 11 14:45:44 2016 +0000 @@ -677,15 +677,6 @@ return readRegister40(DW1000_TX_TIME, 0); } -void DW1000::sendString(char* message) -{ - sendFrame((uint8_t*)message, strlen(message)+1); -} - -void DW1000::receiveString(char* message) -{ - readRegister(DW1000_RX_BUFFER, 0, (uint8_t*)message, getFramelength()); // get data from buffer -} void DW1000::sendFrame(uint8_t* message, uint16_t length) {
--- a/DW1000.cpp.orig Thu Apr 07 16:27:51 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,983 +0,0 @@ -#include "DW1000.h" - -#define SPIRATE_PLL (5*1000*1000) -#define SPIRATE_OSC (2*1000*1000) - -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); - - 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 - - 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; - } - - 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(); - setupRxConfig(); - setupLDE(); - setupChannel(); - setupAnalogRF(); - setupFreqSynth(); - setupTxCalibration(); - setupTxFrameCtrl(); - setupSystemConfig(); - -} - -void DW1000::setupAGC() -{ - - writeRegister16(DW1000_AGC_CTRL, DWAGCCTRL_AGC_CTRL1, 0x0001); - if (systemConfig.getPRF() == DW1000Setup::prf16MHz) - writeRegister16(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE1, 0x8870); - else - writeRegister16(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE1, 0x889B); - - writeRegister32(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE2, 0x2502A907); - writeRegister16(DW1000_AGC_CTRL, DWAGCCTRL_AGC_TUNE3, 0x0035); -} - -void DW1000::setupSystemConfig() -{ - uint32_t valueToUse = 0; - valueToUse |= 1<<9; // IRQ output is active high (default) - valueToUse |= 1<<12; // Disable double buffered Rx (default) - -// valueToUse |= 3<<16; // enable long (>125bytes data) packets - - if (!systemConfig.getSmartPower()) - valueToUse |= 1<<18; // disable smart power - - if (systemConfig.getDataRate() == DW1000Setup::kbps110) - valueToUse |= 1<<22; - - valueToUse |= 1<<29;// enable auto reenabling receiver after error - - writeRegister32(DW1000_SYS_CFG, 0, valueToUse); -} - -void DW1000::setupRxConfig() -{ - - switch (systemConfig.getDataRate()) { - case DW1000Setup::kbps110: - if (systemConfig.getSfd() == DW1000Setup::standard) - writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x000A); - else - writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0016); - break; - case DW1000Setup::kbps850: - if (systemConfig.getSfd() == DW1000Setup::standard) - writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0001); - else - writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0006); - break; - case DW1000Setup::kbps6800: - default: - if (systemConfig.getSfd() == DW1000Setup::standard) - writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0001); - else - writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE0B, 0x0002); - break; - } - - if (systemConfig.getPRF() == DW1000Setup::prf16MHz) - writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1A, 0x0087); //DRX_TUNE1a for 16MHz PRF - else - writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1A, 0x008D); - - switch (systemConfig.getPreambleLength()) { - case DW1000Setup::pre1536: - case DW1000Setup::pre2048: - case DW1000Setup::pre4096: - writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1B, 0x0064); //DRX_TUNE1b for 110kbps & > 1024 symbols - break; - default: // 128 to 1024 - writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1B, 0x0020); //DRX_TUNE1b for 128- 1024 symbols - break; - case DW1000Setup::pre64: - writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE1B, 0x0010); //DRX_TUNE1b for 64 symbols - break; - } - - switch (systemConfig.getPreambleLength()) { - case DW1000Setup::pre64: - case DW1000Setup::pre128: // PAC = 8 - if (systemConfig.getPRF() == DW1000Setup::prf16MHz) - writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x311A002D); //DRX_TUNE2 PAC 8 for 64MHz PRF - else - writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x313B006B); //DRX_TUNE2 PAC 8 for 64MHz PRF - break; - case DW1000Setup::pre256: - case DW1000Setup::pre512: // PAC = 16 - if (systemConfig.getPRF() == DW1000Setup::prf16MHz) - writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x331A0052); //DRX_TUNE2 PAC 16 for 64MHz PRF - else - writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x333B00BE); //DRX_TUNE2 PAC 16 for 64MHz PRF - break; - case DW1000Setup::pre1024: // PAC = 32 - if (systemConfig.getPRF() == DW1000Setup::prf16MHz) - writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x351A009A); //DRX_TUNE2 PAC 32 for 64MHz PRF - else - writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x353B015E); //DRX_TUNE2 PAC 32 for 64MHz PRF - break; - case DW1000Setup::pre1536: - case DW1000Setup::pre2048: - case DW1000Setup::pre4096: // PAC = 64 - if (systemConfig.getPRF() == DW1000Setup::prf16MHz) - writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x371A011D); //DRX_TUNE2 PAC 64 for 64MHz PRF - else - writeRegister32(DW1000_DRX_CONF, DWDRX_DRX_TUNE2, 0x373B0296); //DRX_TUNE2 PAC 64 for 64MHz PRF - break; - } - - - if (systemConfig.getPreambleLength() == DW1000Setup::pre64) - writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE4H, 0x0010); - else - writeRegister16(DW1000_DRX_CONF, DWDRX_DRX_TUNE4H, 0x0028); - -} - - -void DW1000::setupLDE() -{ - - writeRegister8 (DW1000_LDE_CTRL, DWLDE_LDE_CFG1, 0x13 | 0x03<<5); //NTM = 13 (12 may be better in some situations. PMULT = 3 - - if (systemConfig.getPRF() == DW1000Setup::prf16MHz) - writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_CFG2, 0x1607); //LDE_CFG2 for 16MHz PRF - else - writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_CFG2, 0x0607); //LDE_CFG2 for 64MHz PRF - - uint16_t replicaCoeff; - switch (systemConfig.getPreambleCode()) { - default: - case 1: - case 2: - replicaCoeff = 0x5998; - break; - case 3: - replicaCoeff = 0x51EA; - break; - case 4: - replicaCoeff = 0x428E; - break; - case 5: - replicaCoeff = 0x451E; - break; - case 6: - replicaCoeff = 0x2E14; - break; - case 7: - replicaCoeff = 0x8000; - break; - case 8: - replicaCoeff = 0x51EA; - break; - case 9: - replicaCoeff = 0x28F4; - break; - case 10: - replicaCoeff = 0x3332; - break; - case 11: - replicaCoeff = 0x3AE0; - break; - case 12: - replicaCoeff = 0x3D70; - break; - case 13: - replicaCoeff = 0x3AE0; - break; - case 14: - replicaCoeff = 0x35C2; - break; - case 15: - replicaCoeff = 0x2B84; - break; - case 16: - replicaCoeff = 0x35C2; - break; - case 17: - replicaCoeff = 0x3332; - break; - case 18: - replicaCoeff = 0x35C2; - break; - case 19: - replicaCoeff = 0x35C2; - break; - case 20: - replicaCoeff = 0x47AE; - break; - case 21: - replicaCoeff = 0x3AE0; - break; - case 22: - replicaCoeff = 0x3850; - break; - case 23: - replicaCoeff = 0x30A2; - break; - case 24: - replicaCoeff = 0x3850; - break; - } - - if (systemConfig.getDataRate() == DW1000Setup::kbps110) - replicaCoeff = replicaCoeff>>3; - - writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_REPC, replicaCoeff); - - loadLDE(); -} - -void DW1000::setupChannel() -{ - uint32_t registerValue = 0; - - registerValue = systemConfig.getChannel(); // set Tx channel - registerValue |= systemConfig.getChannel()<<4; // set Rx channel - - if (systemConfig.getPRF() == DW1000Setup::prf16MHz) // set PRF (2 bit value 01 or 10) - registerValue |= 0x01 << 18; - else - registerValue |= 0x02 << 18; - - if (systemConfig.getSfd() == DW1000Setup::decaWave) - registerValue |= 0x01 << 17; // enable DW own SFD - - if (systemConfig.getSfd() == DW1000Setup::user) { - registerValue |= 0x01 << 20; // enable user set SFD Tx - registerValue |= 0x01 << 21; // enable user set SFD Rx - } - - registerValue |= systemConfig.getPreambleCode() << 22; // set Tx preamble code - registerValue |= systemConfig.getPreambleCode() << 27; // set Rx preamble code - - writeRegister32(DW1000_CHAN_CTRL, 0, registerValue); -} - - -uint8_t DW1000::powerToRegValue(uint16_t powercB) -{ - - // course power control - 0 = 18dB, 6 = 0dB in 3dB steps. - uint8_t course = powercB / 30; - - if(course > 6) - course = 6; - - // remaining power - powercB -= course * 30; - - // value in reg is inverse. - course = 6-course; - - // fine control in steps of 0.5dB - uint8_t fine = powercB / 5; - if (fine > 31) - fine = 31; - - - return (course << 5) | fine; - -} - -// transmit power: 0 to 33.5 dB gain in steps of 0.5. Inputs are in 10ths of a dB (0 to 335) -void DW1000::setTxPower(uint16_t normalPowercB, uint16_t boost500, uint16_t boost250, uint16_t boost125) -{ - - if(normalPowercB > 335) - normalPowercB = 335; - - if (boost500 < normalPowercB) - boost500 = normalPowercB; - if(boost500 > 335) - boost500 = 335; - - if (boost250 < boost500) - boost250 = boost500; - if(boost250 > 335) - boost250 = 335; - - if (boost125 < boost250) - boost125 = boost250; - if(boost125 > 335) - boost125 = 335; - - if (systemConfig.getSmartPower() == false) { - boost500 = normalPowercB; - boost250 = normalPowercB; - boost125 = normalPowercB; - } - - uint32_t powerReg = powerToRegValue(normalPowercB); - powerReg |= powerToRegValue(boost500) << 8; - powerReg |= powerToRegValue(boost250) << 16; - powerReg |= powerToRegValue(boost125) << 24; -} - -void DW1000::setupAnalogRF() -{ - switch (systemConfig.getChannel()) { - case 1: - writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x00005C40); - break; - case 2: - writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x00045CA0); - break; - case 3: - writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x00086CC0); - break; - case 4: - writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x00045C80); - break; - case 5: - default: - writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x001E3FE0); - break; - case 7: - writeRegister32(DW1000_RF_CONF, DWRFCONF_RF_TXCTRL, 0x001E7DE0); - break; - } - - switch (systemConfig.getChannel()) { - case 1: - case 2: - case 3: - case 5: - default: - writeRegister8(DW1000_RF_CONF, DWRFCONF_RF_RXCTRLH, 0xD8); - break; - case 4: - case 7: - writeRegister8(DW1000_RF_CONF, DWRFCONF_RF_RXCTRLH, 0xBC); - break; - } - - loadLDOTUNE(); - -} - -void DW1000::setupTxCalibration() -{ - switch (systemConfig.getChannel()) { - case 1: - writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0xC9); - break; - case 2: - writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0xC2); - break; - case 3: - writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0xC5); - break; - case 4: - writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0x95); - break; - case 5: - default: - writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0xC0); - break; - case 7: - writeRegister8 (DW1000_TX_CAL, DWTXCAL_TC_PGDELAY, 0x93); - break; - } -} - -void DW1000::setupFreqSynth() -{ - - switch (systemConfig.getChannel()) { - case 1: - writeRegister32 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLCFG, 0x09000407); //FS_PLLCFG for channel 1 - writeRegister8 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLTUNE, 0x1E); - break; - case 2: - case 4: - writeRegister32 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLCFG, 0x08400508); //FS_PLLCFG for channel 2,4 - writeRegister8 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLTUNE, 0x26); - break; - case 3: - writeRegister32 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLCFG, 0x08401009); //FS_PLLCFG for channel 3 - writeRegister8 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLTUNE, 0x5E); - break; - case 5: - case 7: - default: - writeRegister32 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLCFG, 0x0800041D); //FS_PLLCFG for channel 5,7 - writeRegister8 (DW1000_FS_CTRL, DWFSCTRL_FS_PLLTUNE, 0xBE); //FS_PLLTUNE for channel 5 - break; - } -} - -void DW1000::setupTxFrameCtrl() -{ - uint32_t frameCtrlValue = 0; - switch (systemConfig.getDataRate()) { - case DW1000Setup::kbps110: - break; - case DW1000Setup::kbps850: - frameCtrlValue |= 0x01<<13; - break; - case DW1000Setup::kbps6800: - default: - frameCtrlValue |= 0x02<<13; - break; - } - frameCtrlValue |= 0x01<<15; - - if (systemConfig.getPRF() == DW1000Setup::prf16MHz) - frameCtrlValue |= 0x01<<16; - else - frameCtrlValue |= 0x02<<16; - - switch (systemConfig.getPreambleLength()) { - case DW1000Setup::pre64: - frameCtrlValue |= 0x01<<18; // TXPSR - frameCtrlValue |= 0x00<<20; // PE - break; - case DW1000Setup::pre128: - default: - frameCtrlValue |= 0x01<<18; // TXPSR - frameCtrlValue |= 0x01<<20; // PE - break; - case DW1000Setup::pre256: - frameCtrlValue |= 0x01<<18; // TXPSR - frameCtrlValue |= 0x02<<20; // PE - break; - case DW1000Setup::pre512: - frameCtrlValue |= 0x01<<18; // TXPSR - frameCtrlValue |= 0x03<<20; // PE - break; - case DW1000Setup::pre1024: - frameCtrlValue |= 0x02<<18; // TXPSR - frameCtrlValue |= 0x00<<20; // PE - break; - case DW1000Setup::pre1536: - frameCtrlValue |= 0x02<<18; // TXPSR - frameCtrlValue |= 0x01<<20; // PE - break; - case DW1000Setup::pre2048: - frameCtrlValue |= 0x02<<18; // TXPSR - frameCtrlValue |= 0x02<<20; // PE - break; - case DW1000Setup::pre4096: - frameCtrlValue |= 0x03<<18; // TXPSR - frameCtrlValue |= 0x00<<20; // PE - break; - } - writeRegister32(DW1000_TX_FCTRL,0,frameCtrlValue); -} - -void DW1000::setRxDelay(uint16_t ticks) -{ - writeRegister16(DW1000_LDE_CTRL, DWLDE_LDE_RXANTD, ticks); -} -void DW1000::setTxDelay(uint16_t ticks) -{ - writeRegister16(DW1000_TX_ANTD, 0, ticks); -} - -void DW1000::setCallbacks(void (*callbackRX)(void), void (*callbackTX)(void)) -{ - bool RX = false; - bool TX = false; - if (callbackRX) { - DW1000::callbackRX.attach(callbackRX); - RX = true; - } - if (callbackTX) { - DW1000::callbackTX.attach(callbackTX); - TX = true; - } - setInterrupt(RX,TX); -} - -uint32_t DW1000::getDeviceID() -{ - uint32_t result; - readRegister(DW1000_DEV_ID, 0, (uint8_t*)&result, 4); - return result; -} - -uint64_t DW1000::getEUI() -{ - uint64_t result; - readRegister(DW1000_EUI, 0, (uint8_t*)&result, 8); - return result; -} - -void DW1000::setEUI(uint64_t EUI) -{ - writeRegister(DW1000_EUI, 0, (uint8_t*)&EUI, 8); -} - - -float DW1000::getVoltage() -{ - uint8_t data; - - writeRegister8(DW1000_RF_CONF, 0x11, 0x80); - writeRegister8(DW1000_RF_CONF, 0x12, 0x0A); - writeRegister8(DW1000_RF_CONF, 0x12, 0x0F); - writeRegister8(DW1000_TX_CAL, 0x00, 0x01); - writeRegister8(DW1000_TX_CAL, 0x00, 0x00); - data = readRegister8(DW1000_TX_CAL, 0x03); // get the 8-Bit reading for Voltage - float Voltage = (float)(data - (readOTP(0x08)&0x00ff)) *0.00578 + 3.3; - return Voltage; -} - -float DW1000::getTemperature() -{ - uint8_t data; - - writeRegister8(DW1000_RF_CONF, 0x11, 0x80); - writeRegister8(DW1000_RF_CONF, 0x12, 0x0A); - writeRegister8(DW1000_RF_CONF, 0x12, 0x0F); - writeRegister8(DW1000_TX_CAL, 0x00, 0x01); - writeRegister8(DW1000_TX_CAL, 0x00, 0x00); - data = readRegister16(DW1000_TX_CAL, 0x04); // get the 8-Bit reading for Temperature - float temperature = (float)(data - (readOTP(0x09) & 0x00ff))*0.9 + 23; - return temperature; -} - - -uint64_t DW1000::getStatus() -{ - return readRegister40(DW1000_SYS_STATUS, 0); -} - -uint64_t DW1000::getRXTimestamp() -{ - return readRegister40(DW1000_RX_TIME, 0); -} - -uint64_t DW1000::getTXTimestamp() -{ - return readRegister40(DW1000_TX_TIME, 0); -} - -void DW1000::sendString(char* message) -{ - sendFrame((uint8_t*)message, strlen(message)+1); -} - -void DW1000::receiveString(char* message) -{ - readRegister(DW1000_RX_BUFFER, 0, (uint8_t*)message, getFramelength()); // get data from buffer -} - -void DW1000::sendFrame(uint8_t* message, uint16_t length) -{ - //if (length >= 1021) length = 1021; // check for maximim length a frame can have with 1024 Byte frames [not used, see constructor] - if (length >= 125) length = 125; // check for maximim length a frame can have with 127 Byte frames - uint8_t len_7bit = length; - writeRegister(DW1000_TX_BUFFER, 0, message, len_7bit); // fill buffer - - /* support for frames over 127 bytes - uint8_t backup = readRegister8(DW1000_TX_FCTRL, 1); // put length of frame - length += 2; // including 2 CRC Bytes - length = ((backup & 0xFC) << 8) | (length & 0x03FF); - writeRegister16(DW1000_TX_FCTRL, 0, length); - */ - len_7bit += 2; // including 2 CRC Bytes - writeRegister8(DW1000_TX_FCTRL, 0, len_7bit); - - stopTRX(); // stop receiving - writeRegister8(DW1000_SYS_CTRL, 0, 0x02 | 0x80); // trigger sending process by setting the TXSTRT bit -// startRX(); // enable receiver again -} - -void DW1000::setupSyncedFrame(uint8_t* message, uint16_t length) -{ - //if (length >= 1021) length = 1021; // check for maximim length a frame can have with 1024 Byte frames [not used, see constructor] - if (length >= 125) length = 125; // check for maximim length a frame can have with 127 Byte frames - writeRegister(DW1000_TX_BUFFER, 0, message, length); // fill buffer - - uint8_t backup = readRegister8(DW1000_TX_FCTRL, 1); // put length of frame - length += 2; // including 2 CRC Bytes - length = ((backup & 0xFC) << 8) | (length & 0x03FF); - writeRegister16(DW1000_TX_FCTRL, 0, length); -} - -void DW1000::armSyncedFrame() -{ - stopTRX(); // stop receiving - writeRegister16(DW1000_EXT_SYNC, DWEXTSYNC_EC_CTRL, 33<<3 | 0x01); // Sync register = TX start with a wait of 33 (recomended, value must fulfill wait % 4 = 1) -} - -void DW1000::sendDelayedFrame(uint8_t* message, uint16_t length, uint64_t TxTimestamp) -{ - //if (length >= 1021) length = 1021; // check for maximim length a frame can have with 1024 Byte frames [not used, see constructor] - if (length >= 125) length = 125; // check for maximim length a frame can have with 127 Byte frames - writeRegister(DW1000_TX_BUFFER, 0, message, length); // fill buffer - - uint8_t backup = readRegister8(DW1000_TX_FCTRL, 1); // put length of frame - length += 2; // including 2 CRC Bytes - length = ((backup & 0xFC) << 8) | (length & 0x03FF); - writeRegister16(DW1000_TX_FCTRL, 0, length); - - writeRegister40(DW1000_DX_TIME, 0, TxTimestamp); //write the timestamp on which to send the message - - stopTRX(); // stop receiving - writeRegister8(DW1000_SYS_CTRL, 0, 0x02 | 0x04 | 0x80); // trigger sending process by setting the TXSTRT and TXDLYS bit. Set Wait4resp to automatically enter RX mode after tx. -} - -void DW1000::startRX() -{ - writeRegister8(DW1000_SYS_CTRL, 0x01, 0x01); // start listening for preamble by setting the RXENAB bit -} - -void DW1000::stopTRX() -{ - writeRegister8(DW1000_SYS_CTRL, 0, 0x40); // disable tranceiver go back to idle mode -} - -// PRIVATE Methods ------------------------------------------------------------------------------------ -void DW1000::loadLDE() // initialise LDE algorithm LDELOAD User Manual p22 -{ - spi.frequency(SPIRATE_OSC); // with a 1MHz clock rate (worked up to 49MHz in our Test) - - writeRegister16(DW1000_PMSC, 0, 0x0301); // set clock to XTAL so OTP is reliable - writeRegister16(DW1000_OTP_IF, DWOTP_OTP_CTRL, 0x8000); // set LDELOAD bit in OTP - wait_us(150); - writeRegister16(DW1000_PMSC, 0, 0x0200); // recover to PLL clock - - wait_ms(1); - - spi.frequency(SPIRATE_PLL); // with a 1MHz clock rate (worked up to 49MHz in our Test) - -} - -void DW1000::loadLDOTUNE() -{ - uint64_t LDOTuningValue = readOTP(0x0004); - if (LDOTuningValue != 0) { - LDOTuningValue = LDOTuningValue | ((uint64_t)(readOTP(0x0005) & 0x00ff) << 32); - writeRegister40(DW1000_RF_CONF,DWRFCONF_RF_LDOTUNE,LDOTuningValue); - } -} - -void DW1000::resetRX() -{ - writeRegister8(DW1000_PMSC, 3, 0xE0); // set RX reset - writeRegister8(DW1000_PMSC, 3, 0xF0); // clear RX reset -} - -void DW1000::resetAll() -{ - spi.frequency(SPIRATE_OSC); // with a 1MHz clock rate (worked up to 49MHz in our Test) - - writeRegister8(DW1000_PMSC, 0, 0x01); // set clock to XTAL - writeRegister8(DW1000_PMSC, 3, 0x00); // set All reset - wait_us(10); // wait for PLL to lock - writeRegister8(DW1000_PMSC, 3, 0xF0); // clear All reset - - wait_ms(1); - - spi.frequency(SPIRATE_PLL); // with a 1MHz clock rate (worked up to 49MHz in our Test) -} - -/// After writes have been completed reset the device. -bool DW1000::writeOTP(uint16_t word_address,uint32_t data) -{ - spi.frequency(SPIRATE_OSC); // with a 1MHz clock rate (worked up to 49MHz in our Test) - - writeRegister8(DW1000_PMSC, 0, 0x01); // set clock to XTAL - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x03); // - writeRegister16(DW1000_OTP_IF,DWOTP_OTP_WDAT,0x9220); // - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x08); // - wait_ms(1); - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x02); // - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x88); // - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x80); // - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00); // - - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x05); // - writeRegister16(DW1000_OTP_IF,DWOTP_OTP_WDAT,0x000E); // - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x08); // - wait_ms(1); - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x04); // - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x88); // - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x80); // - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00); // - - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x01); // - writeRegister16(DW1000_OTP_IF,DWOTP_OTP_WDAT,0x1024); // - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x08); // - wait_ms(1); - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL+1,0x00); // - - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00); // - writeRegister32(DW1000_OTP_IF,DWOTP_OTP_WDAT,data); // - writeRegister16(DW1000_OTP_IF,DWOTP_OTP_ADDR,word_address); // - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x40); // - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00); // - wait_ms(1); - - for (int i=0; i<10; i++) { - if (readOTP(word_address) == data) - return true; - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x40); // retry - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00); - wait_ms(1); - } - return false; -} - - -uint32_t DW1000::readOTP(uint16_t word_address) -{ - writeRegister16(DW1000_OTP_IF,DWOTP_OTP_ADDR,word_address); // write address - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x03); // read address load - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x01); // read - uint32_t data = readRegister32(DW1000_OTP_IF,DWOTP_OTP_RDAT); - writeRegister8(DW1000_OTP_IF,DWOTP_OTP_CTRL,0x00); // OTP idle - return data; -} - -void DW1000::setInterrupt(bool RX, bool TX) -{ - writeRegister16(DW1000_SYS_MASK, 0, RX*0x4000 | TX*0x0080); // RX good frame 0x4000, TX done 0x0080 -} - -void DW1000::ISR() -{ - uint64_t status = getStatus(); - if (status & 0x4000) { // a frame was received - callbackRX.call(); - writeRegister16(DW1000_SYS_STATUS, 0, 0x6F00); // clearing of receiving status bits - } - if (status & 0x80) { // sending complete - callbackTX.call(); - writeRegister8(DW1000_SYS_STATUS, 0, 0xF8); // clearing of sending status bits - } -} - -uint16_t DW1000::getFramelength() -{ - uint16_t framelength = readRegister16(DW1000_RX_FINFO, 0); // get framelength - framelength = (framelength & 0x03FF) - 2; // take only the right bits and subtract the 2 CRC Bytes - return framelength; -} - -// SPI Interface ------------------------------------------------------------------------------------ -uint8_t DW1000::readRegister8(uint8_t reg, uint16_t subaddress) -{ - uint8_t result; - readRegister(reg, subaddress, &result, 1); - return result; -} - -uint16_t DW1000::readRegister16(uint8_t reg, uint16_t subaddress) -{ - uint16_t result; - readRegister(reg, subaddress, (uint8_t*)&result, 2); - return result; -} - -uint32_t DW1000::readRegister32(uint8_t reg, uint16_t subaddress) -{ - uint32_t result; - readRegister(reg, subaddress, (uint8_t*)&result, 4); - return result; -} - - -uint64_t DW1000::readRegister40(uint8_t reg, uint16_t subaddress) -{ - uint64_t result = 0; - readRegister(reg, subaddress, (uint8_t*)&result, 5); - return result; -} -uint64_t DW1000::readRegister64(uint8_t reg, uint16_t subaddress) -{ - uint64_t result; - readRegister(reg, subaddress, (uint8_t*)&result, 8); - return result; -} - -void DW1000::writeRegister8(uint8_t reg, uint16_t subaddress, uint8_t buffer) -{ - writeRegister(reg, subaddress, &buffer, 1); -} - -void DW1000::writeRegister16(uint8_t reg, uint16_t subaddress, uint16_t buffer) -{ - writeRegister(reg, subaddress, (uint8_t*)&buffer, 2); -} - -void DW1000::writeRegister32(uint8_t reg, uint16_t subaddress, uint32_t buffer) -{ - writeRegister(reg, subaddress, (uint8_t*)&buffer, 4); -} - -void DW1000::writeRegister40(uint8_t reg, uint16_t subaddress, uint64_t buffer) -{ - writeRegister(reg, subaddress, (uint8_t*)&buffer, 5); -} - -void DW1000::readRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length) -{ - setupTransaction(reg, subaddress, false); - for(int i=0; i<length; i++) // get data - buffer[i] = spi.write(0x00); - deselect(); -} - -void DW1000::writeRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length) -{ - setupTransaction(reg, subaddress, true); - for(int i=0; i<length; i++) // put data - spi.write(buffer[i]); - deselect(); -} - -void DW1000::setupTransaction(uint8_t reg, uint16_t subaddress, bool write) -{ - reg |= (write * DW1000_WRITE_FLAG); // set read/write flag - select(); - if (subaddress > 0) { // there's a subadress, we need to set flag and send second header byte - spi.write(reg | DW1000_SUBADDRESS_FLAG); - if (subaddress > 0x7F) { // sub address too long, we need to set flag and send third header byte - spi.write((uint8_t)(subaddress & 0x7F) | DW1000_2_SUBADDRESS_FLAG); // and - spi.write((uint8_t)(subaddress >> 7)); - } else { - spi.write((uint8_t)subaddress); - } - } else { - spi.write(reg); // say which register address we want to access - } -} - -void DW1000::select() // always called to start an SPI transmission -{ - irq.disable_irq(); // disable interrupts from DW1000 during SPI becaus this leads to crashes! TODO: if you have other interrupt handlers attached on the micro controller, they could also interfere. - cs = 0; // set Cable Select pin low to start transmission -} - -void DW1000::deselect() // always called to end an SPI transmission -{ - cs = 1; // set Cable Select pin high to stop transmission - irq.enable_irq(); // reenable the interrupt handler -}
--- a/DW1000.h Thu Apr 07 16:27:51 2016 +0000 +++ b/DW1000.h Mon Apr 11 14:45:44 2016 +0000 @@ -186,28 +186,44 @@ } /// enum for PRF options - enum prf_e {prf16MHz,prf64MHz}; + 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 data rate options - enum dataRate_e {kbps110,kbps850,kbps6800}; - -/// enum for SFD options - enum sfd_e {standard, decaWave, user}; - -/// enum for preamble length options - enum preamble_e { pre64, pre128, pre256, pre512, pre1024, pre1536, pre2048, pre4096}; +/// enum for SFD options + enum sfd_e {standard, ///< IEEE standard SFD + decaWave, ///< Decawave defined SFD + user ///< user defined SFD + }; -/** Set the PRF -* @return true if a valid option -*/ +/// 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 -*/ + /** Set the Channel + * @return true if a valid option + */ bool setChannel(unsigned char newChannel) { if ((channel > 0) && ((channel <= 5) || (channel == 7))) { channel = newChannel; @@ -215,33 +231,33 @@ } return false; }; -/** Set the SFD -* @return true if a valid option -*/ + /** 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 -*/ + /** 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 -*/ + /** 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 -*/ + /** 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; @@ -249,36 +265,54 @@ } return false; }; -/** Set the smartpower state -* @return true if a valid option -* -* only takes effect at 6.8Mb/s -*/ + /** 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 -*/ + /** 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; }; - enum dataRate_e getDataRate() { + /** Get the current data rate + * @return the data rate + */ enum dataRate_e getDataRate() { return dataRate; }; - - enum sfd_e getSfd() {return sfd;}; - enum preamble_e getPreambleLength() { + + /** 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; }; @@ -302,8 +336,30 @@ { public: + /** Constructor. + * + * @param setup The radio mode to configure the unit to use. + * + * Valid setup values are defaultConfig, tunedDefault, user110k + */ DW1000(UWBMode setup, PinName MOSI, PinName MISO, PinName SCLK, PinName CS, PinName IRQ); // constructor, uses SPI class + + /** + * Sets the callbacks on packet Rx and Tx + * @param callbackRX The function to call on packet Rx complete + * @param callbackTX The function to call on packet Tx complete + * + * set either or both to null to disable the appropriate interupt + */ void setCallbacks(void (*callbackRX)(void), void (*callbackTX)(void)); // setter for callback functions, automatically enables interrupt, if NULL is passed the coresponding interrupt gets disabled + + /** + * c++ version of setCallbacks() + * @param tptr object for callbacks + * @param mptrRX method to call on packet Rx complete + * @param mptrTX method to call on packet Tx complete + * + */ template<typename T> void setCallbacks(T* tptr, void (T::*mptrRX)(void), void (T::*mptrTX)(void)) { // overloaded setter to treat member function pointers of objects callbackRX.attach(tptr, mptrRX); // possible client code: dw.setCallbacks(this, &A::callbackRX, &A::callbackTX); @@ -312,38 +368,160 @@ } // Device API + /** Read the device ID + * @return the device ID (0xDECA0130) + */ uint32_t getDeviceID(); // gets the Device ID which should be 0xDECA0130 (good for testing SPI!) - uint64_t getEUI(); // gets 64 bit Extended Unique Identifier according to IEEE standard + + /** Read the Extended Unique ID + * @return The device EUI as stored in the system registers + */ + uint64_t getEUI(); + + /** Set the Extended Unique ID + * @param EUI The EUID to use + * + * Note - ID is only valid until the next power cycle and overrides the value in the OTP memory. + * To set a value that is automatically loaded on startup set OTP memory addresses 0 and 1. + */ void setEUI(uint64_t EUI); // sets 64 bit Extended Unique Identifier according to IEEE standard + + /** Read voltage input + + @return the current device voltage + + For accurate ranging the voltage of the device should be taken into account. + User manual give variation as ~5.35cm / V + */ float getVoltage(); // gets the current chip voltage measurement form the A/D converter + + /** Read on board temperature sensor + @return The temperature in C + + For accurate ranging the temperature of the device should be taken into account. + User manual give variation as ~2.15mm / C + */ float getTemperature(); // gets the current chip temperature measurement form the A/D converter + + /** Get the status register + * @return The system status register + * + * See user manual section 7.2.17 for details + */ uint64_t getStatus(); // get the 40 bit device status + + /** Get the last packet recieve time + * @return the internal time stamp for the last packet Rx + * + * Time is counted on a clock running at 499.2MHz * 128 (~15.65ps) + * This value is raw time minus user set Rx antenna delay. + */ uint64_t getRXTimestamp(); + + /** Get the last packet transmit time + * @return the internal time stamp for the last packet Tx + * + * Time is counted on a clock running at 499.2MHz * 128 (~15.65ps) + * This value is raw time plus user set Tx antenna delay to give time at the antenna. + */ uint64_t getTXTimestamp(); - void sendString(char* message); // to send String with arbitrary length - void receiveString(char* message); // to receive char string (length of the buffer must be 1021 to be safe) + /** Send a packet + * @param message A buffer containing the data to send + * @param length The length of the data in bytes. + * + * The supplied packet is transmitted as soon as possible and the reciever re-enabled once transmission is complete. + * Maximum packet size is 125 bytes. + */ void sendFrame(uint8_t* message, uint16_t length); // send a raw frame (length in bytes) + + /** Send a packet at a certain time + * @param message A buffer containing the data to send + * @param length The length of the data in bytes. + * @param TxTimestamp The timestamp to send the packet. + * + * The supplied packet is transmitted once the internal clock reaches the specified timestamp. + * Maximum packet size is 125 bytes. + * Rx is disabled as soon as this command is issued and re-enabled once transmission is complete. + * Note - 9 LSBs are ignored so timings are only accurate to ~8ns. For more accurate timing check the + * tx timestamp after transmission is complete. + */ void sendDelayedFrame(uint8_t* message, uint16_t length, uint64_t TxTimestamp); + /** Set up data for a transmit on sync + * @param message A buffer containing the data to send + * @param length The length of the data in bytes. + * + * Data is loaded into the transmit buffer but the transmission is not started. + * Maximum packet size is 125 bytes. + */ void setupSyncedFrame(uint8_t* message, uint16_t length); + + /** Transmit on the next sync pulse + * + * On the next rising edge of the sync line the transmitter will be activated. + * The packet must have previously been set up using setupSyncedFrame() + * + * Rx is disabled until transmission is complete. + */ void armSyncedFrame(); + /** Enable reciever + * + * This is automatically done after each Tx completes but can also be forced manually + */ void startRX(); // start listening for frames + + /** Disable radio link + * + * Disables both the recieve and transmit systems. + * Any transmissions waiting for a delayed time or sync pulse will be canceled. + */ void stopTRX(); // disable tranceiver go back to idle mode + /** Set receive antenna delay + * @param ticks Delay in system clock cycles + */ void setRxDelay(uint16_t ticks); + /** Set transmit antenna delay + * @param ticks Delay in system clock cycles + */ void setTxDelay(uint16_t ticks); + /** Get last packet size + * @return The length in bytes of the last packet received + */ uint16_t getFramelength(); // to get the framelength of the received frame from the PHY header + /** Get last recieved packet + * @param buffer The location to put the received data + * @param length The number of bytes to read + */ void readRxBuffer( uint8_t *buffer, int length ) { readRegister(DW1000_RX_BUFFER, 0, buffer, length); } + /** Read a value from the OTP memory + * @param word_address The OTP memory address to read. + * @return The 32 bit value at that address. + * + * See Section 6.3.1 of the user manual for the memory map. + */ uint32_t readOTP (uint16_t word_address); + + /** Write a value to the OTP memory + * @param word_address The OTP memory address to read. + * @param data The value to write + * @return True if the write was sucessful. + * + * Writes the supplied data to the OTP memory and then reads it back to verify it was sucessfully programmed. + * Note - this is a one time operation for each memory address. + * See Section 6.3.1 of the user manual for the memory map. + * It is recommened that the device is reset or power cycled after programing. + */ bool writeOTP(uint16_t word_address,uint32_t data); // program a value in the OTP. It is recommended to reset afterwards. + /** Get setup description * * @param buffer Data buffer to place description in @@ -354,7 +532,19 @@ void getSetup(char *buffer, int len); protected: + /** Reset the reciever logic + * + * This should be done after any receive errors + */ void resetRX(); // soft reset only the tranciever part of DW1000 + + /** Enable/Disable interrupts + * @param RX true to enable recieve interrupts + * @param TX true to enable transmit interrupts + * + * For c style callbacks simply set the callback to null to disable it. + * When using c++ style callbacks both are enabled as default, this allows a method to disabled one or both. + */ void setInterrupt(bool RX, bool TX); // set Interrupt for received a good frame (CRC ok) or transmission done /** Set Transmit gain
--- a/DW1000.h.orig Thu Apr 07 16:27:51 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,424 +0,0 @@ -// by Matthias Grob & Manuel Stalder - ETH Zürich - 2015 - -#ifndef DW1000_H -#define DW1000_H - -#include "mbed.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 - -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,prf64MHz}; - -/// enum for data rate options - enum dataRate_e {kbps110,kbps850,kbps6800}; - -/// enum for SFD options - enum sfd_e {standard, decaWave, user}; - -/// enum for preamble length options - enum preamble_e { pre64, pre128, pre256, pre512, pre1024, pre1536, pre2048, pre4096}; - -/** 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; - }; - enum prf_e getPRF() { - return prf; - }; - enum dataRate_e getDataRate() { - return dataRate; - }; - - enum sfd_e getSfd() {return sfd;}; - enum preamble_e getPreambleLength() { - return preamble; - }; - unsigned char getPreambleCode() { - return preambleCode; - }; - 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; -}; - - -typedef enum {minPacketSize, tunedDefault, user110k} UWBMode; - -/** A DW1000 driver -*/ -class DW1000 -{ -public: - - DW1000(UWBMode setup, PinName MOSI, PinName MISO, PinName SCLK, PinName CS, PinName IRQ); // constructor, uses SPI class - void setCallbacks(void (*callbackRX)(void), void (*callbackTX)(void)); // setter for callback functions, automatically enables interrupt, if NULL is passed the coresponding interrupt gets disabled - template<typename T> - void setCallbacks(T* tptr, void (T::*mptrRX)(void), void (T::*mptrTX)(void)) { // overloaded setter to treat member function pointers of objects - callbackRX.attach(tptr, mptrRX); // possible client code: dw.setCallbacks(this, &A::callbackRX, &A::callbackTX); - callbackTX.attach(tptr, mptrTX); // concept seen in line 100 of http://developer.mbed.org/users/mbed_official/code/mbed/docs/4fc01daae5a5/InterruptIn_8h_source.html - setInterrupt(true,true); - } - - // Device API - uint32_t getDeviceID(); // gets the Device ID which should be 0xDECA0130 (good for testing SPI!) - uint64_t getEUI(); // gets 64 bit Extended Unique Identifier according to IEEE standard - void setEUI(uint64_t EUI); // sets 64 bit Extended Unique Identifier according to IEEE standard - float getVoltage(); // gets the current chip voltage measurement form the A/D converter - float getTemperature(); // gets the current chip temperature measurement form the A/D converter - uint64_t getStatus(); // get the 40 bit device status - uint64_t getRXTimestamp(); - uint64_t getTXTimestamp(); - - void sendString(char* message); // to send String with arbitrary length - void receiveString(char* message); // to receive char string (length of the buffer must be 1021 to be safe) - void sendFrame(uint8_t* message, uint16_t length); // send a raw frame (length in bytes) - void sendDelayedFrame(uint8_t* message, uint16_t length, uint64_t TxTimestamp); - - void setupSyncedFrame(uint8_t* message, uint16_t length); - void armSyncedFrame(); - - void startRX(); // start listening for frames - void stopTRX(); // disable tranceiver go back to idle mode - - void setRxDelay(uint16_t ticks); - void setTxDelay(uint16_t ticks); - - uint16_t getFramelength(); // to get the framelength of the received frame from the PHY header - - void readRxBuffer( uint8_t *buffer, int length ) { - readRegister(DW1000_RX_BUFFER, 0, buffer, length); - } - - uint32_t readOTP (uint16_t word_address); - bool writeOTP(uint16_t word_address,uint32_t data); // program a value in the OTP. It is recommended to reset afterwards. - - /** 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 getSetup(char *buffer, int len); - -protected: - void resetRX(); // soft reset only the tranciever part of DW1000 - void setInterrupt(bool RX, bool TX); // set Interrupt for received a good frame (CRC ok) or transmission done - - /** Set Transmit gain - * - * @param normalPowercB Normal transmit gain to use. - * @param boost500 Gain to use for 6.8Mb/s packets of under 500ms. - * @param boost250 Gain to use for 6.8Mb/s packets of under 250ms. - * @param boost125 Gain to use for 6.8Mb/s packets of under 125ms. - * - * 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); - - -private: - void resetAll(); // soft reset the entire DW1000 (some registers stay as they were see User Manual) - - void setupRadio(); - - // system register setup functions - void setupAGC(); - void setupRxConfig(); - void setupLDE(); - void setupChannel(); - void setupTxFrameCtrl(); - void setupAnalogRF(); - void setupFreqSynth(); - void setupTxCalibration(); - void setupSystemConfig(); - void loadLDE(); // load the leading edge detection algorithm to RAM, [IMPORTANT because receiving malfunction may occur] see User Manual LDELOAD on p22 & p158 - void loadLDOTUNE(); // load the LDO tuning as set in the factory - - uint8_t powerToRegValue(uint16_t powercB); - - DW1000Setup systemConfig; - - - - // Interrupt - InterruptIn irq; // Pin used to handle Events from DW1000 by an Interrupthandler - FunctionPointer callbackRX; // function pointer to callback which is called when successfull RX took place - FunctionPointer callbackTX; // function pointer to callback which is called when successfull TX took place - void ISR(); // interrupt handling method (also calls according callback methods) - - // SPI Inteface - SPI spi; // SPI Bus - DigitalOut cs; // Slave selector for SPI-Bus (here explicitly needed to start and end SPI transactions also usable to wake up DW1000) - - 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); - 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); - void writeRegister16(uint8_t reg, uint16_t subaddress, uint16_t buffer); - void writeRegister32(uint8_t reg, uint16_t subaddress, uint32_t buffer); - void writeRegister40(uint8_t reg, uint16_t subaddress, uint64_t buffer); - - void readRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length); // reads the selected part of a slave register into the buffer memory - void writeRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length); // writes the buffer memory to the selected slave register - void setupTransaction(uint8_t reg, uint16_t subaddress, bool write); // sets up an SPI read or write transaction with correct register address and offset - void select(); // selects the only slave for a transaction - void deselect(); // deselects the only slave after transaction -}; - -#endif \ No newline at end of file