diff --git a/DW1000-arduino-test/DW1000-arduino-basic-test/DW1000-arduino-basic-test.ino b/DW1000-arduino-test/DW1000-arduino-basic-test/DW1000-arduino-basic-test.ino index c1ec555c..d9da28c5 100644 --- a/DW1000-arduino-test/DW1000-arduino-basic-test/DW1000-arduino-basic-test.ino +++ b/DW1000-arduino-test/DW1000-arduino-basic-test/DW1000-arduino-basic-test.ino @@ -16,20 +16,19 @@ // reset line to the chip int RST = 9; -// chip driver instances with chip select and reset -DW1000 dw = DW1000(SS, RST); void setup() { // DEBUG monitoring Serial.begin(9600); // initialize the driver - dw.initialize(); + DW1000.begin(); + DW1000.init(SS, RST, 0); Serial.println("DW1000 initialized ..."); // general configuration - dw.newConfiguration(); - dw.setDeviceAddress(5); - dw.setNetworkId(10); - dw.commitConfiguration(); + DW1000.newConfiguration(); + DW1000.setDeviceAddress(5); + DW1000.setNetworkId(10); + DW1000.commitConfiguration(); Serial.println("Committed configuration ..."); } @@ -37,12 +36,9 @@ void loop() { // wait a bit delay(1000); // DEBUG chip info and registers pretty printed - Serial.print("Device ID: "); Serial.println(dw.getPrintableDeviceIdentifier()); - Serial.print("Unique ID: "); Serial.println(dw.getPrintableExtendedUniqueIdentifier()); - Serial.print("Network ID & Device Address: "); Serial.println(dw.getPrintableNetworkIdAndShortAddress()); - // DEBUG print device tuning results - Serial.println(dw.getPrettyBytes(AGC_TUNE, AGC_TUNE1_SUB, LEN_AGC_TUNE1)); - Serial.println(dw.getPrettyBytes(AGC_TUNE, AGC_TUNE2_SUB, LEN_AGC_TUNE2)); + Serial.print("Device ID: "); Serial.println(DW1000.getPrintableDeviceIdentifier()); + Serial.print("Unique ID: "); Serial.println(DW1000.getPrintableExtendedUniqueIdentifier()); + Serial.print("Network ID & Device Address: "); Serial.println(DW1000.getPrintableNetworkIdAndShortAddress()); // wait a bit delay(10000); } diff --git a/DW1000-arduino-test/DW1000-arduino-receiver-test/DW1000-arduino-receiver-test.ino b/DW1000-arduino-test/DW1000-arduino-receiver-test/DW1000-arduino-receiver-test.ino index db2b29c0..c81744e9 100644 --- a/DW1000-arduino-test/DW1000-arduino-receiver-test/DW1000-arduino-receiver-test.ino +++ b/DW1000-arduino-test/DW1000-arduino-receiver-test/DW1000-arduino-receiver-test.ino @@ -17,67 +17,57 @@ // DEBUG packet sent status and count volatile boolean received = false; volatile int numReceived = 0; +String message; // reset line to the chip int RST = 9; -// chip driver instances with chip select and reset -DW1000 dw = DW1000(SS, RST); void setup() { // DEBUG monitoring Serial.begin(9600); + Serial.println("### DW1000-arduino-receiver-test ###"); // initialize the driver - dw.initialize(); + DW1000.begin(); + DW1000.init(SS, RST, 0); Serial.println("DW1000 initialized ..."); // general configuration - dw.newConfiguration(); - dw.setDefaults(); - dw.setDeviceAddress(6); - dw.setNetworkId(10); - dw.setFrameFilter(false); - dw.interruptOnReceived(true); - dw.commitConfiguration(); + DW1000.newConfiguration(); + DW1000.setDefaults(); + DW1000.setDeviceAddress(6); + DW1000.setNetworkId(10); + DW1000.setFrameFilter(false); + DW1000.commitConfiguration(); Serial.println("Committed configuration ..."); // DEBUG chip info and registers pretty printed - Serial.print("Device ID: "); Serial.println(dw.getPrintableDeviceIdentifier()); - Serial.print("Unique ID: "); Serial.println(dw.getPrintableExtendedUniqueIdentifier()); - Serial.print("Network ID & Device Address: "); Serial.println(dw.getPrintableNetworkIdAndShortAddress()); - Serial.println(dw.getPrettyBytes(SYS_CFG, NO_SUB, LEN_SYS_CFG)); - Serial.println(dw.getPrettyBytes(PANADR, NO_SUB, LEN_PANADR)); - Serial.println(dw.getPrettyBytes(SYS_MASK, NO_SUB, LEN_SYS_MASK)); - // attach interrupt and ISR - pinMode(INT0, INPUT); - attachInterrupt(0, serviceIRQ, FALLING); - Serial.println("Interrupt attached ..."); - // configure as permanent receiver - dw.newReceive(); - dw.setDefaults(); - dw.startReceive(); + Serial.print("Device ID: "); Serial.println(DW1000.getPrintableDeviceIdentifier()); + Serial.print("Unique ID: "); Serial.println(DW1000.getPrintableExtendedUniqueIdentifier()); + Serial.print("Network ID & Device Address: "); Serial.println(DW1000.getPrintableNetworkIdAndShortAddress()); + // attach callback for (successfully) received messages + DW1000.attachReceivedHandler(handleReceived); + // start reception + receiver(); } -void serviceIRQ() { - if(received) { - return; - } - // "NOP" ISR +void handleReceived() { + // status change on reception success received = true; - numReceived++; + // get data as string + DW1000.getData(message); +} + +void receiver() { + DW1000.newReceive(); + DW1000.setDefaults(); + DW1000.startReceive(); } void loop() { // enter on confirmation of ISR status change (successfully received) if(received) { + numReceived++; Serial.print("Received packet ... #"); Serial.println(numReceived); - Serial.print("Bytes available ... "); Serial.println(dw.getDataLength()); - // get data as String - String recv; - dw.getData(recv); - Serial.print("Data is ... "); Serial.println(recv); - + Serial.print("Data is ... "); Serial.println(message); // restart the receiver received = false; - dw.newReceive(); - dw.setDefaults(); - dw.startReceive(); + receiver(); } - //Serial.println(dw.getPrettyBytes(SYS_STATUS, NO_SUB, LEN_SYS_STATUS)); } diff --git a/DW1000-arduino-test/DW1000-arduino-sender-test/DW1000-arduino-sender-test.ino b/DW1000-arduino-test/DW1000-arduino-sender-test/DW1000-arduino-sender-test.ino index e114a120..dec934c4 100644 --- a/DW1000-arduino-test/DW1000-arduino-sender-test/DW1000-arduino-sender-test.ino +++ b/DW1000-arduino-test/DW1000-arduino-sender-test/DW1000-arduino-sender-test.ino @@ -15,74 +15,73 @@ #include // DEBUG packet sent status and count -volatile boolean sent = false; +boolean sent = false; +volatile boolean sentAck = false; +volatile unsigned long delaySent = 0; int sentNum = 0; unsigned long sentTime = 0; // reset line to the chip int RST = 9; -// chip driver instances with chip select and reset -DW1000 dw = DW1000(SS, RST); void setup() { // DEBUG monitoring Serial.begin(9600); + Serial.println("### DW1000-arduino-sender-test ###"); // initialize the driver - dw.initialize(); + DW1000.begin(); + DW1000.init(SS, RST, 0); Serial.println("DW1000 initialized ..."); // general configuration - dw.newConfiguration(); - dw.setDefaults(); - dw.setDeviceAddress(5); - dw.setNetworkId(10); - dw.setFrameFilter(false); - dw.interruptOnSent(true); - dw.commitConfiguration(); + DW1000.newConfiguration(); + DW1000.setDefaults(); + DW1000.setDeviceAddress(5); + DW1000.setNetworkId(10); + DW1000.setFrameFilter(false); + DW1000.commitConfiguration(); Serial.println("Committed configuration ..."); // DEBUG chip info and registers pretty printed - Serial.print("Device ID: "); Serial.println(dw.getPrintableDeviceIdentifier()); - Serial.print("Unique ID: "); Serial.println(dw.getPrintableExtendedUniqueIdentifier()); - Serial.print("Network ID & Device Address: "); Serial.println(dw.getPrintableNetworkIdAndShortAddress()); - Serial.println(dw.getPrettyBytes(SYS_CFG, NO_SUB, LEN_SYS_CFG)); - Serial.println(dw.getPrettyBytes(PANADR, NO_SUB, LEN_PANADR)); - Serial.println(dw.getPrettyBytes(SYS_MASK, NO_SUB, LEN_SYS_MASK)); - // attach interrupt and ISR - pinMode(INT0, INPUT); - attachInterrupt(0, serviceIRQ, FALLING); - Serial.println("Interrupt attached ..."); + Serial.print("Device ID: "); Serial.println(DW1000.getPrintableDeviceIdentifier()); + Serial.print("Unique ID: "); Serial.println(DW1000.getPrintableExtendedUniqueIdentifier()); + Serial.print("Network ID & Device Address: "); Serial.println(DW1000.getPrintableNetworkIdAndShortAddress()); + // attach callback for (successfully) sent messages + DW1000.attachSentHandler(handleSent); + // start a transmission + transmitter(); } -void serviceIRQ() { - if(sent) { - return; - } - // "NOP" ISR - sent = true; +void handleSent() { + // status change on sent success + sentAck = true; +} + +void transmitter() { + // transmit some data + Serial.print("Transmitting packet ... #"); Serial.println(sentNum); + DW1000.newTransmit(); + DW1000.setDefaults(); + String msg = "Hello DW1000, it's #"; msg += sentNum; + DW1000.setData(msg); + //DW1000.delayedTransceive(500, DW1000::MILLISECONDS); + DW1000.startTransmit(); + delaySent = millis(); } void loop() { - if(sent) { - // process confirmation of ISR status change (successfully sent) - sent = false; - if(!dw.isTransmitDone()) { - return; - } - // update and print some information about the sent message - unsigned long newSentTime = dw.getTransmitTimestamp(); - Serial.print("Processed packet ... #"); Serial.println(sentNum); - Serial.print("Sent timestamp ... "); Serial.println(newSentTime); - // NOTE: delta is just for simple demo as not correct on system time counter wrap-around - Serial.print("Delta send time [s] ... "); Serial.println((newSentTime - sentTime) * 1e-9 * 8.01282); - sentTime = newSentTime; - sentNum++; - } else { - // transmit some data - Serial.print("Transmitting packet ... #"); Serial.println(sentNum); - dw.newTransmit(); - dw.setDefaults(); - String msg = "Hello DW1000"; - dw.setData(msg); - dw.startTransmit(); - // wait a bit - delay(500); + if(!sentAck) { + return; } + // continue on success confirmation + sentAck = false; + // update and print some information about the sent message + Serial.print("Delay sent [ms] ... "); Serial.println(millis() - delaySent); + unsigned long newSentTime = DW1000.getTransmitTimestamp(); + Serial.print("Processed packet ... #"); Serial.println(sentNum); + Serial.print("Sent timestamp ... "); Serial.println(newSentTime); + // NOTE: delta is just for simple demo as not correct on system time counter wrap-around + Serial.print("Delta send time [s] ... "); Serial.println((newSentTime - sentTime) * 1.0e-9 * 8.01282); + sentTime = newSentTime; + sentNum++; + // again, transmit some data + transmitter(); + delay(10); } diff --git a/DW1000/DW1000.cpp b/DW1000/DW1000.cpp index fc921591..bad9d9c0 100644 --- a/DW1000/DW1000.cpp +++ b/DW1000/DW1000.cpp @@ -7,40 +7,60 @@ * published by the Free Software Foundation. */ -#ifndef DEBUG #include "pins_arduino.h" -#endif #include "DW1000.h" +DW1000Class DW1000; + /* ########################################################################### - * #### Construction and init ################################################ + * #### Static member variables ############################################## * ######################################################################### */ -DW1000::DW1000(int ss, int rst) { - _ss = ss; - _rst = rst; - _deviceMode = IDLE_MODE; - _extendedFrameLength = false; -#ifndef DEBUG - pinMode(_ss, OUTPUT); - digitalWrite(_ss, HIGH); - pinMode(_rst, OUTPUT); - digitalWrite(_rst, HIGH); +unsigned int DW1000Class::_ss; +unsigned int DW1000Class::_rst; +unsigned int DW1000Class::_irq; +boolean DW1000Class::_handledInterrupt = false; +void (*DW1000Class::_handleSent)(void) = 0; +void (*DW1000Class::_handleReceived)(void) = 0; +char DW1000Class::_msgBuf[1024]; +byte DW1000Class::_syscfg[LEN_SYS_CFG]; +byte DW1000Class::_sysctrl[LEN_SYS_CTRL]; +byte DW1000Class::_sysstatus[LEN_SYS_STATUS]; +byte DW1000Class::_txfctrl[LEN_TX_FCTRL]; +byte DW1000Class::_sysmask[LEN_SYS_MASK]; +byte DW1000Class::_chanctrl[LEN_CHAN_CTRL]; +byte DW1000Class::_networkAndAddress[LEN_PANADR]; +boolean DW1000Class::_extendedFrameLength; +int DW1000Class::_deviceMode; + +/* ########################################################################### + * #### Init and end ####################################################### + * ######################################################################### */ + +void DW1000Class::begin() { SPI.begin(); SPI.setBitOrder(MSBFIRST); SPI.setDataMode(SPI_MODE0); // TODO increase clock speed after chip clock lock (CPLOCK in 0x0f) SPI.setClockDivider(SPI_CLOCK_DIV8); -#endif } -DW1000::~DW1000() { -#ifndef DEBUG +void DW1000Class::end() { SPI.end(); -#endif } -void DW1000::initialize() { +void DW1000Class::init(int ss, int rst, int irq) { + // pin and basic member setup + _ss = ss; + _rst = rst; + _irq = irq; + _handledInterrupt = false; + _deviceMode = IDLE_MODE; + _extendedFrameLength = false; + pinMode(_ss, OUTPUT); + digitalWrite(_ss, HIGH); + pinMode(_rst, OUTPUT); + digitalWrite(_rst, HIGH); // reset chip reset(); // default network and node id @@ -49,7 +69,7 @@ void DW1000::initialize() { // default system configuration memset(_syscfg, 0, LEN_SYS_CFG); setDoubleBuffering(false); - setInterruptPolarity(true); + setInterruptPolarity(false); writeSystemConfigurationRegister(); // default interrupt mask, i.e. no interrupts clearInterrupts(); @@ -66,16 +86,18 @@ void DW1000::initialize() { writeBytes(PMSC_CTRL0, NO_SUB, pmscctrl0, LEN_PMSC_CTRL0); tune(); delay(10); + // attach interrupt + attachInterrupt(_irq, DW1000Class::handleInterrupt, LOW); } -void DW1000::reset() { +void DW1000Class::reset() { digitalWrite(_rst, LOW); delay(10); digitalWrite(_rst, HIGH); delay(10); } -void DW1000::tune() { +void DW1000Class::tune() { // re-tune chip for channel 5 (default) byte agctune1[LEN_AGC_TUNE1]; byte agctune2[LEN_AGC_TUNE2]; @@ -104,22 +126,39 @@ void DW1000::tune() { writeBytes(RF_CONF, RF_TXCTRL_SUB, rftxctrl, LEN_RF_TXCTRL); writeBytes(TX_CAL, TC_PGDELAY_SUB, tcpgdelay, LEN_TC_PGDELAY); writeBytes(FS_CTRL, FS_PLLTUNE_SUB, fsplltune, LEN_FS_PLLTUNE); - - // TODO others as well, RF_TXCTRL, TX_PGDELAY, FS_PLLTUNE, LDOTUNE - // TODO see 2.5.5, p. 21 + // TODO LDOTUNE, see 2.5.5, p. 21 } /* ########################################################################### - * #### Member access ######################################################## + * #### Interrupt handling ################################################### * ######################################################################### */ -// ... +void DW1000Class::handleInterrupt() { + // clear interrupt assertions + clearInterrupts(); + writeSystemEventMaskRegister(); + // debounce + if(_handledInterrupt) { + return; + } + _handledInterrupt = true; + // read current status and handle via callbacks + readSystemEventStatusRegister(); + if(isTransmitDone() && _handleSent != 0) { + (*_handleSent)(); + } else if(isReceiveSuccess() && _handleReceived != 0) { + (*_handleReceived)(); + } + // TODO impl other callbacks + // all status has been handled, so clear + clearAllStatus(); +} /* ########################################################################### - * #### DW1000 operation functions ########################################### + * #### Pretty printed device information #################################### * ######################################################################### */ -char* DW1000::getPrintableDeviceIdentifier() { +char* DW1000Class::getPrintableDeviceIdentifier() { byte data[LEN_DEV_ID]; readBytes(DEV_ID, NO_SUB, data, LEN_DEV_ID); sprintf(_msgBuf, "DECA - model: %d, version: %d, revision: %d", @@ -127,7 +166,7 @@ char* DW1000::getPrintableDeviceIdentifier() { return _msgBuf; } -char* DW1000::getPrintableExtendedUniqueIdentifier() { +char* DW1000Class::getPrintableExtendedUniqueIdentifier() { byte data[LEN_EUI]; readBytes(EUI, NO_SUB, data, LEN_EUI); sprintf(_msgBuf, "EUI: %d:%d:%d:%d:%d, OUI: %d:%d:%d", @@ -135,7 +174,7 @@ char* DW1000::getPrintableExtendedUniqueIdentifier() { return _msgBuf; } -char* DW1000::getPrintableNetworkIdAndShortAddress() { +char* DW1000Class::getPrintableNetworkIdAndShortAddress() { byte data[LEN_PANADR]; readBytes(PANADR, NO_SUB, data, LEN_PANADR); sprintf(_msgBuf, "PAN: %u, Short Address: %u", @@ -143,142 +182,153 @@ char* DW1000::getPrintableNetworkIdAndShortAddress() { return _msgBuf; } -void DW1000::readSystemConfigurationRegister() { +/* ########################################################################### + * #### DW1000 register read/write ########################################### + * ######################################################################### */ + +void DW1000Class::readSystemConfigurationRegister() { readBytes(SYS_CFG, NO_SUB, _syscfg, LEN_SYS_CFG); } -void DW1000::writeSystemConfigurationRegister() { +void DW1000Class::writeSystemConfigurationRegister() { writeBytes(SYS_CFG, NO_SUB, _syscfg, LEN_SYS_CFG); } -void DW1000::readSystemEventStatusRegister() { +void DW1000Class::readSystemEventStatusRegister() { readBytes(SYS_STATUS, NO_SUB, _sysstatus, LEN_SYS_STATUS); } -void DW1000::readNetworkIdAndDeviceAddress() { +void DW1000Class::readNetworkIdAndDeviceAddress() { readBytes(PANADR, NO_SUB, _networkAndAddress, LEN_PANADR); } -void DW1000::writeNetworkIdAndDeviceAddress() { +void DW1000Class::writeNetworkIdAndDeviceAddress() { writeBytes(PANADR, NO_SUB, _networkAndAddress, LEN_PANADR); } -void DW1000::readSystemEventMaskRegister() { +void DW1000Class::readSystemEventMaskRegister() { readBytes(SYS_MASK, NO_SUB, _sysmask, LEN_SYS_MASK); } -void DW1000::writeSystemEventMaskRegister() { +void DW1000Class::writeSystemEventMaskRegister() { writeBytes(SYS_MASK, NO_SUB, _sysmask, LEN_SYS_MASK); } -void DW1000::readChannelControlRegister() { +void DW1000Class::readChannelControlRegister() { readBytes(CHAN_CTRL, NO_SUB, _chanctrl, LEN_CHAN_CTRL); } -void DW1000::writeChannelControlRegister() { +void DW1000Class::writeChannelControlRegister() { writeBytes(CHAN_CTRL, NO_SUB, _chanctrl, LEN_CHAN_CTRL); } -void DW1000::readTransmitFrameControlRegister() { +void DW1000Class::readTransmitFrameControlRegister() { readBytes(TX_FCTRL, NO_SUB, _txfctrl, LEN_TX_FCTRL); } -void DW1000::writeTransmitFrameControlRegister() { +void DW1000Class::writeTransmitFrameControlRegister() { writeBytes(TX_FCTRL, NO_SUB, _txfctrl, LEN_TX_FCTRL); } -void DW1000::setNetworkId(unsigned int val) { +/* ########################################################################### + * #### DW1000 operation functions ########################################### + * ######################################################################### */ + +void DW1000Class::setNetworkId(unsigned int val) { _networkAndAddress[2] = (byte)(val & 0xFF); _networkAndAddress[3] = (byte)((val >> 8) & 0xFF); } -void DW1000::setDeviceAddress(unsigned int val) { +void DW1000Class::setDeviceAddress(unsigned int val) { _networkAndAddress[0] = (byte)(val & 0xFF); _networkAndAddress[1] = (byte)((val >> 8) & 0xFF); } -void DW1000::setFrameFilter(boolean val) { +void DW1000Class::setFrameFilter(boolean val) { setBit(_syscfg, LEN_SYS_CFG, FFEN_BIT, val); } -void DW1000::setDoubleBuffering(boolean val) { +void DW1000Class::setDoubleBuffering(boolean val) { setBit(_syscfg, LEN_SYS_CFG, DIS_DRXB_BIT, !val); } -void DW1000::setInterruptPolarity(boolean val) { +void DW1000Class::setInterruptPolarity(boolean val) { setBit(_syscfg, LEN_SYS_CFG, HIRQ_POL_BIT, val); } -void DW1000::setReceiverAutoReenable(boolean val) { +void DW1000Class::setReceiverAutoReenable(boolean val) { setBit(_syscfg, LEN_SYS_CFG, RXAUTR_BIT, val); } -void DW1000::interruptOnSent(boolean val) { +void DW1000Class::interruptOnSent(boolean val) { setBit(_sysmask, LEN_SYS_MASK, TXFRS_BIT, val); } -void DW1000::interruptOnReceived(boolean val) { +void DW1000Class::interruptOnReceived(boolean val) { setBit(_sysmask, LEN_SYS_MASK, RXDFR_BIT, val); } -void DW1000::interruptOnAutomaticAcknowledgeTrigger(boolean val) { +void DW1000Class::interruptOnAutomaticAcknowledgeTrigger(boolean val) { setBit(_sysmask, LEN_SYS_MASK, AAT_BIT, val); } -void DW1000::clearInterrupts() { +void DW1000Class::clearInterrupts() { memset(_sysmask, 0, LEN_SYS_MASK); } -void DW1000::idle() { +void DW1000Class::idle() { + _handledInterrupt = false; memset(_sysctrl, 0, LEN_SYS_CTRL); setBit(_sysctrl, LEN_SYS_CTRL, TRXOFF_BIT, true); _deviceMode = IDLE_MODE; writeBytes(SYS_CTRL, NO_SUB, _sysctrl, LEN_SYS_CTRL); } -void DW1000::newConfiguration() { +void DW1000Class::newConfiguration() { idle(); readNetworkIdAndDeviceAddress(); readSystemConfigurationRegister(); - readSystemEventMaskRegister(); readChannelControlRegister(); readTransmitFrameControlRegister(); } -void DW1000::commitConfiguration() { +void DW1000Class::commitConfiguration() { writeNetworkIdAndDeviceAddress(); writeSystemConfigurationRegister(); - writeSystemEventMaskRegister(); writeChannelControlRegister(); writeTransmitFrameControlRegister(); } -void DW1000::waitForResponse(boolean val) { +void DW1000Class::waitForResponse(boolean val) { setBit(_sysctrl, LEN_SYS_CTRL, WAIT4RESP_BIT, val); } -void DW1000::suppressFrameCheck(boolean val) { +void DW1000Class::suppressFrameCheck(boolean val) { setBit(_sysctrl, LEN_SYS_CTRL, SFCST_BIT, val); } -boolean DW1000::isSuppressFrameCheck() { +boolean DW1000Class::isSuppressFrameCheck() { return getBit(_sysctrl, LEN_SYS_CTRL, SFCST_BIT); } -void DW1000::delayedTransceive(unsigned long delayNanos) { +unsigned long DW1000Class::delayedTransceive(unsigned int value, unsigned long factorNs) { if(_deviceMode == TX_MODE) { setBit(_sysctrl, LEN_SYS_CTRL, TXDLYS_BIT, true); } else if(_deviceMode == RX_MODE) { setBit(_sysctrl, LEN_SYS_CTRL, RXDLYS_BIT, true); } else { // in idle, ignore - return; + return -1; } byte delayBytes[5]; - // TODO impl 40 bit in DX_TIME register, 9 lower sig. bits are ignored + // TODO consider counter wrap-around + unsigned long tsValue = getSystemTimestamp() + (value * factorNs) / TIME_RES; + writeLongToTimestamp(tsValue, delayBytes); + writeBytes(DX_TIME, NO_SUB, delayBytes, LEN_DX_TIME); + return tsValue; } -void DW1000::dataRate(byte rate) { +void DW1000Class::dataRate(byte rate) { rate &= 0x03; if(rate >= 0x03) { rate = TRX_RATE_850KBPS; @@ -291,7 +341,7 @@ void DW1000::dataRate(byte rate) { } } -void DW1000::pulseFrequency(byte freq) { +void DW1000Class::pulseFrequency(byte freq) { freq &= 0x03; if(freq == 0x00 || freq >= 0x03) { freq = TX_PULSE_FREQ_16MHZ; @@ -310,13 +360,13 @@ void DW1000::pulseFrequency(byte freq) { writeBytes(AGC_TUNE, AGC_TUNE1_SUB, agctune1, LEN_AGC_TUNE1); } -void DW1000::preambleLength(byte prealen) { +void DW1000Class::preambleLength(byte prealen) { prealen &= 0x0F; _txfctrl[2] |= (byte)((prealen << 2) & 0xFF); // TODO set PAC size accordingly for RX (see table 6, page 31) } -void DW1000::extendedFrameLength(boolean val) { +void DW1000Class::extendedFrameLength(boolean val) { byte extLen = 0x00; if(val) { extLen = 0x03; @@ -324,24 +374,40 @@ void DW1000::extendedFrameLength(boolean val) { _sysctrl[3] |= extLen; } -void DW1000::newReceive() { +void DW1000Class::newReceive() { memset(_sysctrl, 0, LEN_SYS_CTRL); clearReceiveStatus(); _deviceMode = RX_MODE; } -void DW1000::startReceive() { +void DW1000Class::startReceive() { + interruptOnReceived(true); + interruptOnAutomaticAcknowledgeTrigger(true); + writeSystemEventMaskRegister(); + _handledInterrupt = false; setBit(_sysctrl, LEN_SYS_CTRL, RXENAB_BIT, true); writeBytes(SYS_CTRL, NO_SUB, _sysctrl, LEN_SYS_CTRL); } -void DW1000::newTransmit() { +void DW1000Class::newTransmit() { memset(_sysctrl, 0, LEN_SYS_CTRL); clearTransmitStatus(); _deviceMode = TX_MODE; } -void DW1000::setDefaults() { +void DW1000Class::startTransmit() { + interruptOnSent(true); + interruptOnAutomaticAcknowledgeTrigger(true); + writeSystemEventMaskRegister(); + _handledInterrupt = false; + // set transmit flag + setBit(_sysctrl, LEN_SYS_CTRL, TXSTRT_BIT, true); + writeBytes(SYS_CTRL, NO_SUB, _sysctrl, LEN_SYS_CTRL); + // reset to idle + _deviceMode = IDLE_MODE; +} + +void DW1000Class::setDefaults() { if(_deviceMode == TX_MODE) { suppressFrameCheck(false); extendedFrameLength(false); @@ -353,19 +419,10 @@ void DW1000::setDefaults() { pulseFrequency(TX_PULSE_FREQ_16MHZ); preambleLength(TX_PREAMBLE_LEN_1024); setReceiverAutoReenable(true);*/ - interruptOnAutomaticAcknowledgeTrigger(true); } } -void DW1000::startTransmit() { - // set transmit flag - setBit(_sysctrl, LEN_SYS_CTRL, TXSTRT_BIT, true); - writeBytes(SYS_CTRL, NO_SUB, _sysctrl, LEN_SYS_CTRL); - // reset to idle - _deviceMode = IDLE_MODE; -} - -void DW1000::setData(byte data[], int n) { +void DW1000Class::setData(byte data[], int n) { if(!isSuppressFrameCheck()) { n+=2; // two bytes CRC-16 } @@ -387,7 +444,7 @@ void DW1000::setData(byte data[], int n) { writeTransmitFrameControlRegister(); } -void DW1000::setData(const String& data) { +void DW1000Class::setData(const String& data) { int n = data.length()+1; byte* dataBytes = (byte*)malloc(n); data.getBytes(dataBytes, n); @@ -396,7 +453,7 @@ void DW1000::setData(const String& data) { } -int DW1000::getDataLength() { +int DW1000Class::getDataLength() { if(_deviceMode == TX_MODE) { // 10 bits of TX frame control register return (((_txfctrl[1] << 8) | _txfctrl[0]) & 0x03FF); @@ -411,14 +468,14 @@ int DW1000::getDataLength() { } } -void DW1000::getData(byte data[], int n) { +void DW1000Class::getData(byte data[], int n) { if(n < 0) { return; } readBytes(RX_BUFFER, NO_SUB, data, n); } -void DW1000::getData(String& data) { +void DW1000Class::getData(String& data) { int i; int n = getDataLength(); // number of bytes w/o the two FCS ones if(n < 0) { @@ -436,25 +493,25 @@ void DW1000::getData(String& data) { free(dataBytes); } -unsigned long DW1000::getTransmitTimestamp() { +unsigned long DW1000Class::getTransmitTimestamp() { byte txTimeBytes[LEN_TX_STAMP]; readBytes(TX_TIME, TX_STAMP_SUB, txTimeBytes, LEN_TX_STAMP); return getTimestampAsLong(txTimeBytes+1); } -unsigned long DW1000::getReceiveTimestamp() { +unsigned long DW1000Class::getReceiveTimestamp() { byte rxTimeBytes[LEN_RX_STAMP]; readBytes(RX_TIME, RX_STAMP_SUB, rxTimeBytes, LEN_RX_STAMP); return getTimestampAsLong(rxTimeBytes+1); } -unsigned long DW1000::getSystemTimestamp() { +unsigned long DW1000Class::getSystemTimestamp() { byte sysTimeBytes[LEN_SYS_TIME]; readBytes(SYS_TIME, NO_SUB, sysTimeBytes, LEN_SYS_TIME); return getTimestampAsLong(sysTimeBytes+1); } -unsigned long DW1000::getTimestampAsLong(byte ts[]) { +unsigned long DW1000Class::getTimestampAsLong(byte ts[]) { unsigned long tsValue = ((unsigned long)ts[0] >> 1); tsValue |= ((unsigned long)ts[1] << 7); tsValue |= ((unsigned long)ts[2] << 15); @@ -462,30 +519,28 @@ unsigned long DW1000::getTimestampAsLong(byte ts[]) { return tsValue; } -// system event register -boolean DW1000::isTransmitDone() { - // read whole register and check bit - readBytes(SYS_STATUS, NO_SUB, _sysstatus, LEN_SYS_STATUS); +void DW1000Class::writeLongToTimestamp(unsigned long tsValue, byte ts[]) { + ts[0] = (byte)0; + ts[1] = (byte)((tsValue << 1) & 0xFF); + ts[2] = (byte)((tsValue >> 7) & 0xFF); + ts[3] = (byte)((tsValue >> 15) & 0xFF); + ts[4] = (byte)((tsValue >> 23) & 0xFF); +} + +boolean DW1000Class::isTransmitDone() { return getBit(_sysstatus, LEN_SYS_STATUS, TXFRS_BIT); } -boolean DW1000::isLDEDone() { - // read whole register and check bit - readBytes(SYS_STATUS,NO_SUB, _sysstatus, LEN_SYS_STATUS); +boolean DW1000Class::isLDEDone() { return getBit(_sysstatus, LEN_SYS_STATUS, LDEDONE_BIT); } -boolean DW1000::isReceiveDone() { - // read whole register and check bit - readBytes(SYS_STATUS, NO_SUB, _sysstatus, LEN_SYS_STATUS); +boolean DW1000Class::isReceiveDone() { return getBit(_sysstatus, LEN_SYS_STATUS, RXDFR_BIT); } -boolean DW1000::isReceiveSuccess() { +boolean DW1000Class::isReceiveSuccess() { boolean ldeDone, ldeErr, rxGood, rxErr, rxDecodeErr; - - // read whole register and check bits - readBytes(SYS_STATUS, NO_SUB, _sysstatus, LEN_SYS_STATUS); // first check for errors ldeErr = getBit(_sysstatus, LEN_SYS_STATUS, LDEERR_BIT); rxErr = getBit(_sysstatus, LEN_SYS_STATUS, RXFCE_BIT); @@ -503,12 +558,12 @@ boolean DW1000::isReceiveSuccess() { return false; } -void DW1000::clearAllStatus() { +void DW1000Class::clearAllStatus() { memset(_sysstatus, 0, LEN_SYS_STATUS); writeBytes(SYS_STATUS, NO_SUB, _sysstatus, LEN_SYS_STATUS); } -void DW1000::clearReceiveStatus() { +void DW1000Class::clearReceiveStatus() { // clear latched RX bits (i.e. write 1 to clear) setBit(_sysstatus, LEN_SYS_STATUS, RXDFR_BIT, true); setBit(_sysstatus, LEN_SYS_STATUS, LDEDONE_BIT, true); @@ -519,7 +574,7 @@ void DW1000::clearReceiveStatus() { writeBytes(SYS_STATUS, NO_SUB, _sysstatus, LEN_SYS_STATUS); } -void DW1000::clearTransmitStatus() { +void DW1000Class::clearTransmitStatus() { // clear latched TX bits setBit(_sysstatus, LEN_SYS_STATUS, TXFRB_BIT, true); setBit(_sysstatus, LEN_SYS_STATUS, TXPRS_BIT, true); @@ -544,7 +599,7 @@ void DW1000::clearTransmitStatus() { * @param val * The boolean value to be set to the given bit position. */ -void DW1000::setBit(byte data[], int n, int bit, boolean val) { +void DW1000Class::setBit(byte data[], int n, int bit, boolean val) { int idx; int shift; @@ -571,7 +626,7 @@ void DW1000::setBit(byte data[], int n, int bit, boolean val) { * @param bit * The position of the bit to be checked. */ -boolean DW1000::getBit(byte data[], int n, int bit) { +boolean DW1000Class::getBit(byte data[], int n, int bit) { int idx; int shift; @@ -585,7 +640,7 @@ boolean DW1000::getBit(byte data[], int n, int bit) { return bitRead(targetByte, shift); } -void DW1000::writeValueToBytes(byte data[], int val, int n) { +void DW1000Class::writeValueToBytes(byte data[], int val, int n) { int i; for(i = 0; i < n; i++) { data[i] = ((val >> (i * 8)) & 0xFF); @@ -601,7 +656,7 @@ void DW1000::writeValueToBytes(byte data[], int val, int n) { * @param n * The number of bytes expected to be received. */ -void DW1000::readBytes(byte cmd, word offset, byte data[], int n) { +void DW1000Class::readBytes(byte cmd, word offset, byte data[], int n) { byte header[3]; int headerLen = 1; int i; @@ -618,24 +673,16 @@ void DW1000::readBytes(byte cmd, word offset, byte data[], int n) { headerLen+=2; } } -#ifndef DEBUG + noInterrupts(); digitalWrite(_ss, LOW); -#endif for(i = 0; i < headerLen; i++) { -#ifndef DEBUG SPI.transfer(header[i]); -#endif } for(i = 0; i < n; i++) { -#ifndef DEBUG data[i] = SPI.transfer(JUNK); -#else - data[i] = debugBuffer[i]; -#endif } -#ifndef DEBUG digitalWrite(_ss,HIGH); -#endif + interrupts(); } /* @@ -651,7 +698,7 @@ void DW1000::readBytes(byte cmd, word offset, byte data[], int n) { * The number of bytes to be written (take care not to go out of bounds of * the register). */ -void DW1000::writeBytes(byte cmd, word offset, byte data[], int n) { +void DW1000Class::writeBytes(byte cmd, word offset, byte data[], int n) { byte header[3]; int headerLen = 1; int i; @@ -669,29 +716,44 @@ void DW1000::writeBytes(byte cmd, word offset, byte data[], int n) { headerLen+=2; } } -#ifndef DEBUG + noInterrupts(); digitalWrite(_ss, LOW); -#endif for(i = 0; i < headerLen; i++) { -#ifndef DEBUG SPI.transfer(header[i]); -#endif } for(i = 0; i < n; i++) { -#ifndef DEBUG SPI.transfer(data[i]); -#else - debugBuffer[i] = data[i]; -#endif } -#ifndef DEBUG delay(1); digitalWrite(_ss,HIGH); + interrupts(); delay(1); -#endif } -char* DW1000::getPrettyBytes(byte cmd, word offset, int n) { +char* DW1000Class::getPrettyBytes(byte data[], int n) { + unsigned int i, j, b; + b = sprintf(_msgBuf, "Data, bytes: %d\nB: 7 6 5 4 3 2 1 0\n", n); + for(i = 0; i < n; i++) { + byte curByte = data[i]; + snprintf(&_msgBuf[b++], 2, "%d", (i + 1)); + _msgBuf[b++] = (char)((i + 1) & 0xFF); _msgBuf[b++] = ':'; _msgBuf[b++] = ' '; + for(j = 0; j < 8; j++) { + _msgBuf[b++] = ((curByte >> (7 - j)) & 0x01) ? '1' : '0'; + if(j < 7) { + _msgBuf[b++] = ' '; + } else if(i < n-1) { + _msgBuf[b++] = '\n'; + } else { + _msgBuf[b++] = '\0'; + } + } + + } + _msgBuf[b++] = '\0'; + return _msgBuf; +} + +char* DW1000Class::getPrettyBytes(byte cmd, word offset, int n) { unsigned int i, j, b; byte* readBuf = (byte*)malloc(n); readBytes(cmd, offset, readBuf, n); @@ -713,6 +775,6 @@ char* DW1000::getPrettyBytes(byte cmd, word offset, int n) { } _msgBuf[b++] = '\0'; - delete[] readBuf; + free(readBuf); return _msgBuf; } diff --git a/DW1000/DW1000.h b/DW1000/DW1000.h index 66af9c67..6fe65b4b 100644 --- a/DW1000/DW1000.h +++ b/DW1000/DW1000.h @@ -173,20 +173,10 @@ #include #include #include -#ifndef DEBUG #include #include "../SPI/SPI.h" -#else -#include -#define boolean uint8_t -#define byte uint8_t -#define word uint16_t -#define bitSet(value, bit) ((value) |= (1UL << (bit))) -#define bitRead(value, bit) (((value) >> (bit)) & 0x01) -#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) -#endif -class DW1000 { +class DW1000Class { public: /* TODO impl: later * - TXBOFFS in TX_FCTRL for offset buffer transmit @@ -197,85 +187,94 @@ class DW1000 { * - replace all |= with bitChange (bitClear + bitSet) */ - // construction with chip select pin number - DW1000(int ss, int rst); - ~DW1000(); - void initialize(); - void reset(); - void tune(); + // construction with chip select, reset and irq pin number + static void begin(); + static void end(); + static void init(int ss, int rst, int irq); + static void reset(); + static void tune(); // device id, address, etc. - char* getPrintableDeviceIdentifier(); - char* getPrintableExtendedUniqueIdentifier(); - char* getPrintableNetworkIdAndShortAddress(); + static char* getPrintableDeviceIdentifier(); + static char* getPrintableExtendedUniqueIdentifier(); + static char* getPrintableNetworkIdAndShortAddress(); // PAN_ID, SHORT_ADDR, device address management - void setNetworkId(unsigned int val); - void setDeviceAddress(unsigned int val); + static void setNetworkId(unsigned int val); + static void setDeviceAddress(unsigned int val); // SYS_CFG, general device configuration - void setFrameFilter(boolean val); - void setDoubleBuffering(boolean val); // NOTE should be set to false - void setReceiverAutoReenable(boolean val); - void setInterruptPolarity(boolean val); + static void setFrameFilter(boolean val); + static void setDoubleBuffering(boolean val); // NOTE should be set to false + static void setReceiverAutoReenable(boolean val); + static void setInterruptPolarity(boolean val); // SYS_CTRL, TX/RX_FCTRL, transmit and receive configuration - void suppressFrameCheck(boolean val); - void delayedTransceive(unsigned long delayNanos); // TODO impl - void dataRate(byte rate); - void pulseFrequency(byte freq); - void preambleLength(byte prealen); - void extendedFrameLength(boolean val); - void waitForResponse(boolean val); - void setData(byte data[], int n); - void setData(const String& data); - void getData(byte data[], int n); - void getData(String& data); - int getDataLength(); - unsigned long getTransmitTimestamp(); - unsigned long getReceiveTimestamp(); - unsigned long getSystemTimestamp(); - boolean isSuppressFrameCheck(); + static void suppressFrameCheck(boolean val); + static unsigned long delayedTransceive(unsigned int value, unsigned long factorNs); + static void dataRate(byte rate); + static void pulseFrequency(byte freq); + static void preambleLength(byte prealen); + static void extendedFrameLength(boolean val); + static void waitForResponse(boolean val); + static void setData(byte data[], int n); + static void setData(const String& data); + static void getData(byte data[], int n); + static void getData(String& data); + static int getDataLength(); + static unsigned long getTransmitTimestamp(); + static unsigned long getReceiveTimestamp(); + static unsigned long getSystemTimestamp(); + static boolean isSuppressFrameCheck(); // RX/TX default settings void setDefaults(); // SYS_STATUS, device status flags - boolean isLDEDone(); - boolean isTransmitDone(); - boolean isReceiveDone(); - boolean isReceiveSuccess(); + static boolean isLDEDone(); + static boolean isTransmitDone(); + static boolean isReceiveDone(); + static boolean isReceiveSuccess(); // SYS_MASK, interrupt handling - void interruptOnSent(boolean val); - void interruptOnReceived(boolean val); - void interruptOnAutomaticAcknowledgeTrigger(boolean val); - void clearInterrupts(); + static void interruptOnSent(boolean val); + static void interruptOnReceived(boolean val); + static void interruptOnAutomaticAcknowledgeTrigger(boolean val); + static void clearInterrupts(); + + static void clearAllStatus(); + static void clearReceiveStatus(); + static void clearTransmitStatus(); // TODO impl - void clearAllStatus(); - void clearReceiveStatus(); - void clearTransmitStatus(); // TODO impl + inline static void attachSentHandler(void (*handleSent)(void)) { + _handleSent = handleSent; + } + + inline static void attachReceivedHandler(void (*handleReceived)(void)) { + _handleReceived = handleReceived; + } // RX_TIME, ..., timing, timestamps, etc. // TODO void readReceiveTimestamp(byte[] timestamp); // idle - void idle(); + static void idle(); // general configuration - void newConfiguration(); - void commitConfiguration(); + static void newConfiguration(); + static void commitConfiguration(); // reception - void newReceive(); - void startReceive(); + static void newReceive(); + static void startReceive(); // transmission - void newTransmit(); - void startTransmit(); + static void newTransmit(); + static void startTransmit(); // debug pretty print registers - char* getPrettyBytes(byte cmd, word offset, int n); + static char* getPrettyBytes(byte cmd, word offset, int n); + static char* getPrettyBytes(byte data[], int n); // transmission/reception bit rate static const byte TRX_RATE_110KBPS = 0x00; @@ -297,64 +296,78 @@ class DW1000 { static const byte TX_PREAMBLE_LEN_2048 = 0x0A; static const byte TX_PREAMBLE_LEN_4096 = 0x03; -#ifdef DEBUG - byte debugBuffer[1024]; - inline void clearDebugBuffer() { - memset(debugBuffer, 0, 1024); - } -#endif + /* Time resolution [ns] of time based registers/values. */ + static const float TIME_RES = 8.012820513; + + /* Time factors (relative to [ns]) for setting delayed transceive. */ + static const unsigned long SECONDS = 1e9; + static const unsigned long MILLISECONDS = 1e6; + static const unsigned long MICROSECONDS = 1e3; + static const unsigned long NANOSECONDS = 1; private: - /* chip select and reset pins. */ - unsigned int _ss; - unsigned int _rst; + /* chip select, reset and interrupt pins. */ + static unsigned int _ss; + static unsigned int _rst; + static unsigned int _irq; + + /* flag for debouncing interrupts. */ + static boolean _handledInterrupt; + + /* callbacks. */ + static void (*_handleSent)(void); + static void (*_handleReceived)(void); /* fixed buffer for printed messages. */ - char _msgBuf[1024]; + static char _msgBuf[1024]; /* register caches. */ - byte _syscfg[LEN_SYS_CFG]; - byte _sysctrl[LEN_SYS_CTRL]; - byte _sysstatus[LEN_SYS_STATUS]; - byte _txfctrl[LEN_TX_FCTRL]; - byte _sysmask[LEN_SYS_MASK]; - byte _chanctrl[LEN_CHAN_CTRL]; + static byte _syscfg[LEN_SYS_CFG]; + static byte _sysctrl[LEN_SYS_CTRL]; + static byte _sysstatus[LEN_SYS_STATUS]; + static byte _txfctrl[LEN_TX_FCTRL]; + static byte _sysmask[LEN_SYS_MASK]; + static byte _chanctrl[LEN_CHAN_CTRL]; /* PAN and short address. */ - byte _networkAndAddress[LEN_PANADR]; + static byte _networkAndAddress[LEN_PANADR]; /* internal helper to determine send mode for set data. */ - boolean _extendedFrameLength; + static boolean _extendedFrameLength; // whether RX or TX is active - int _deviceMode; + static int _deviceMode; + + /* ISR. */ + static void handleInterrupt(); /* internal helper to read/write system registers. */ - void readSystemEventStatusRegister(); - void readSystemConfigurationRegister(); - void writeSystemConfigurationRegister(); - void readNetworkIdAndDeviceAddress(); - void writeNetworkIdAndDeviceAddress(); - void readSystemEventMaskRegister(); - void writeSystemEventMaskRegister(); - void readChannelControlRegister(); - void writeChannelControlRegister(); - void readTransmitFrameControlRegister(); - void writeTransmitFrameControlRegister(); + static void readSystemEventStatusRegister(); + static void readSystemConfigurationRegister(); + static void writeSystemConfigurationRegister(); + static void readNetworkIdAndDeviceAddress(); + static void writeNetworkIdAndDeviceAddress(); + static void readSystemEventMaskRegister(); + static void writeSystemEventMaskRegister(); + static void readChannelControlRegister(); + static void writeChannelControlRegister(); + static void readTransmitFrameControlRegister(); + static void writeTransmitFrameControlRegister(); /* reading and writing bytes from and to DW1000 module. */ - void readBytes(byte cmd, word offset, byte data[], int n); - void writeBytes(byte cmd, word offset, byte data[], int n); + static void readBytes(byte cmd, word offset, byte data[], int n); + static void writeBytes(byte cmd, word offset, byte data[], int n); /* writing numeric values to bytes. */ - void writeValueToBytes(byte data[], int val, int n); + static void writeValueToBytes(byte data[], int val, int n); /* writing DW1000 timestamp values to unsigned long. */ - unsigned long getTimestampAsLong(byte ts[]); + static unsigned long getTimestampAsLong(byte ts[]); + static void writeLongToTimestamp(unsigned long tsValue, byte ts[]); /* internal helper for bit operations on multi-bytes. */ - boolean getBit(byte data[], int n, int bit); - void setBit(byte data[], int n, int bit, boolean val); + static boolean getBit(byte data[], int n, int bit); + static void setBit(byte data[], int n, int bit, boolean val); /* Register is 6 bit, 7 = write, 6 = sub-adressing, 5-0 = register value * Total header with sub-adressing can be 15 bit. */ @@ -362,9 +375,8 @@ class DW1000 { static const byte WRITE_SUB = 0xC0; // write with sub address static const byte READ = 0x00; // regular read static const byte READ_SUB = 0x40; // read with sub address - - /* Time resolution [ns] of time based registers/values. */ - static const float TIME_RES = 8.012820513; }; +extern DW1000Class DW1000; + #endif diff --git a/README.md b/README.md index a7749380..703db151 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Current milestone: Extensive RX/TX config testing with two chips; planned till b Features and design intentions: * Fully encapsulated SPI communication with the chip + * Fully encapsulated interrupt handling by means of custom callback handlers (currently only for sent and received messages, error handling, etc. will shortly follow) * Simple device status querying * Simple and readable RX/TX/config API (docs will follow shortly) @@ -26,7 +27,7 @@ What works so far: * Management of IRQs * byte[] and (Arduino-)String based data RX/TX * RX/TX/config sessions - * Stable transmission of packets between two chips + * Stable transmission of messages between two chips Next on the agenda: * Extensive testing of certain configurations, code cleanup (and bug fixing) @@ -41,22 +42,25 @@ Misc todos: Usage is something like: ``` -DW1000 dw = DW1000(cs_pin, rst_pin); -dw.initialize(); -attachInterrupt(...); +#include ... -dw.newConfiguration(); +// init with chip select, reset and interrupt pin/line +DW1000.init(cs_pin, rst_pin, int_pin); +... +DW1000.newConfiguration(); // configure specific aspects or choose defaults -dw.setDefaults(); -dw.interruptOnSent(true); +DW1000.setDefaults(); +DW1000.interruptOnSent(true); // .. and other stuff. -dw.commitConfiguration(); +DW1000.commitConfiguration(); +... +DW1000.attachSentHandler(some_handler_function); ... -dw.newTransmit(); +DW1000.newTransmit(); // configure specific aspects or choose defaults -dw.setDefaults(); -dw.setData(some_data); -dw.startTransmit(); +DW1000.setDefaults(); +DW1000.setData(some_data); +DW1000.startTransmit(); ... // similar for receiving ```