// DecaDuino.cpp // // Another DecaWave DW1000 driver for Arduino // See the README file in this directory for documentation #include #include "DecaDuino.h" #include DecaDuino* DecaDuino::_DecaDuinoInterrupt[MAX_NB_DW1000_FOR_INTERRUPTS] = {0, 0, 0}; DecaDuino::DecaDuino(uint8_t slaveSelectPin, uint8_t interruptPin) { _slaveSelectPin = slaveSelectPin; _interruptPin = interruptPin; } boolean DecaDuino::init() { // Call init with 0xFFFF for both Short Address and PanId (no address/panid identification: Promiscuous mode) return init(0xFFFFFFFF); } boolean DecaDuino::init ( uint32_t shortAddressAndPanId ) { uint8_t buf[8]; uint16_t ui16t; uint32_t ui32t; // Initialise the IRQ and Slave Select pin pinMode(_interruptPin, INPUT); pinMode(_slaveSelectPin, OUTPUT); digitalWrite(_slaveSelectPin, HIGH); SPI.begin(); // Initialise the RX pointers rxDataAvailable = false; rxData = NULL; rxDataLen = NULL; // Wait for DW1000 POR (up to 5msec) delay(5); #ifdef DECADUINO_DEBUG delay(3000); // delay to see next messages on console for debug Serial.println("DecaDuino Debug is active!"); #endif // Reset the DW1000 now resetDW1000(); // Check the device type if ( readSpiUint32(DW1000_REGISTER_DEV_ID) != 0xdeca0130 ) return false; // Load Extended Unique Identifier – the 64-bit IEEE device address - in memory euid = getEuid(); // Attach interrupt handler if (_interruptPin == DW1000_IRQ0_PIN) { _DecaDuinoInterrupt[DW1000_IRQ0_PIN] = this; attachInterrupt(_interruptPin, DecaDuino::isr0, HIGH); } else if (_interruptPin == DW1000_IRQ1_PIN) { _DecaDuinoInterrupt[DW1000_IRQ1_PIN] = this; attachInterrupt(_interruptPin, DecaDuino::isr1, HIGH); } else if (_interruptPin == DW1000_IRQ2_PIN) { _DecaDuinoInterrupt[DW1000_IRQ2_PIN] = this; attachInterrupt(_interruptPin, DecaDuino::isr2, HIGH); } else return false; // --- Configure DW1000 ----------------------------------------------------------------------------------------- // System Configuration Register ui32t = readSpiUint32(DW1000_REGISTER_SYS_CFG); ui32t |= DW1000_REGISTER_SYS_CFG_RXAUTR_MASK; // RXAUTR: Receiver Auto-Re-enable after a RX failure writeSpiUint32(DW1000_REGISTER_SYS_CFG,ui32t); #ifdef DECADUINO_DEBUG sprintf((char*)debugStr,"SYS_CFG=%08lx", ui32t); Serial.println((char*)debugStr); #endif // System Event Mask Register ui32t = readSpiUint32(DW1000_REGISTER_SYS_MASK); ui32t |= DW1000_REGISTER_SYS_MASK_MRXFCG_MASK; // MRXFCG: interrupt when good frame (FCS OK) received ui32t |= DW1000_REGISTER_SYS_MASK_MTXFRS_MASK; writeSpiUint32(DW1000_REGISTER_SYS_MASK, ui32t); #ifdef DECADUINO_DEBUG sprintf((char*)debugStr,"SYS_MASK=%08lx", ui32t); Serial.println((char*)debugStr); #endif // Enable frame filtering on addressing fields if init() is called with a shortAddressAndPanId != 0xFFFFFFFF if ( shortAddressAndPanId != 0xFFFFFFFF ) { ui32t = readSpiUint32(DW1000_REGISTER_SYS_CFG); ui32t |= 0x0000003D; writeSpiUint32(DW1000_REGISTER_SYS_CFG,ui32t); setShortAddressAndPanId(shortAddressAndPanId); } // Set default antenna delay value setAntennaDelay(DWM1000_DEFAULT_ANTENNA_DELAY_VALUE); // --- End of DW1000 configuration ------------------------------------------------------------------------------ lastTxOK = false; // Return true if everything OK return true; } // End of init() void DecaDuino::resetDW1000() { uint8_t buf[8]; uint32_t ui32t; // Initialise the SPI port currentSPISettings = SPISettings(500000, MSBFIRST, SPI_MODE0); delay(100); // Getting PMSC_CTRL0 register ui32t = readSpiUint32(DW1000_REGISTER_PMSC_CTRL0); #ifdef DECADUINO_DEBUG sprintf((char*)debugStr,"PMSC_CTRL0=%08lx", ui32t); Serial.println((char*)debugStr); #endif // Set SYSCLKS bits to 01 ui32t = ( ui32t & 0xFFFFFFFC ) | 1; writeSpiUint32(DW1000_REGISTER_PMSC_CTRL0, ui32t); delay(1); // Clear SOFTRESET bits ui32t &= 0x0FFFFFFF; writeSpiUint32(DW1000_REGISTER_PMSC_CTRL0, ui32t); delay(1); #ifdef DECADUINO_DEBUG sprintf((char*)debugStr,"PMSC_CTRL0=%08lx", ui32t); Serial.println((char*)debugStr); #endif // Set SOFTRESET bits ui32t |= 0xF0000000; ui32t &= 0xFFFFFFFC; writeSpiUint32(DW1000_REGISTER_PMSC_CTRL0, ui32t); delay(5); // Load the LDE algorithm microcode into LDE RAM or disable LDE execution (clear LDERUNE) // Load the LDE algorithm microcode into LDE RAM (procedure p.22 DW1000 User Manual + comment p.21) ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { SPI.beginTransaction(currentSPISettings); digitalWrite(_slaveSelectPin, LOW); buf[0] = 0xF6; buf[1] = 0x00; buf[2] = 0x01; buf[3] = 0x03; spi_send(buf,4); digitalWrite(_slaveSelectPin, HIGH); SPI.endTransaction(); SPI.beginTransaction(currentSPISettings); digitalWrite(_slaveSelectPin, LOW); buf[0] = 0xED; buf[1] = 0x06; buf[2] = 0x00; buf[3] = 0x80; spi_send(buf,4); digitalWrite(_slaveSelectPin, HIGH); SPI.endTransaction(); delayMicroseconds(160); SPI.beginTransaction(currentSPISettings); digitalWrite(_slaveSelectPin, LOW); buf[0] = 0xF6; buf[1] = 0x00; buf[2] = 0x00; buf[3] = 0x02; spi_send(buf,4); digitalWrite(_slaveSelectPin, HIGH); SPI.endTransaction(); } // Initialise the SPI port currentSPISettings = SPISettings(6000000, MSBFIRST, SPI_MODE0); delay(1); #ifdef DECADUINO_DEBUG ui32t = readSpiUint32(DW1000_REGISTER_PMSC_CTRL0); sprintf((char*)debugStr,"PMSC_CTRL0=%08lx", ui32t); Serial.println((char*)debugStr); #endif trxStatus = DW1000_TRX_STATUS_IDLE; } void DecaDuino::isr0() { #ifdef DECADUINO_DEBUG //Serial.println("\n###isr0###"); #endif if (_DecaDuinoInterrupt[DW1000_IRQ0_PIN]) _DecaDuinoInterrupt[DW1000_IRQ0_PIN]->handleInterrupt(); } void DecaDuino::isr1() { #ifdef DECADUINO_DEBUG //Serial.println("\n###isr1###"); #endif if (_DecaDuinoInterrupt[DW1000_IRQ1_PIN]) _DecaDuinoInterrupt[DW1000_IRQ1_PIN]->handleInterrupt(); } void DecaDuino::isr2() { #ifdef DECADUINO_DEBUG //Serial.println("\n###isr2###"); #endif if (_DecaDuinoInterrupt[DW1000_IRQ2_PIN]) _DecaDuinoInterrupt[DW1000_IRQ2_PIN]->handleInterrupt(); } void DecaDuino::handleInterrupt() { uint8_t buf[8]; uint32_t sysStatusReg, ack, ui32t; double rxtofs, rxttcki; ack = 0; // Read System Event Status Register sysStatusReg = readSpiUint32(DW1000_REGISTER_SYS_STATUS); // If IRQS is cleared, no enabled interrupt (SYS_MASK) have assert the IRQ pin: exit if ( ! ( sysStatusReg & DW1000_REGISTER_SYS_STATUS_IRQS_MASK ) ) return; #ifdef DECADUINO_DEBUG // Serial.print("\n###isr### "); //ui32t = readSpiUint32(DW1000_REGISTER_SYS_MASK); //sprintf((char*)debugStr,"SYS_MASK =%08x", ui32t); //Serial.println((char*)debugStr); //sprintf((char*)debugStr,"SYS_STATUS=%08x ", sysStatusReg); //Serial.print((char*)debugStr); #endif // Checking RX frame interrupt if ( sysStatusReg & DW1000_REGISTER_SYS_STATUS_RXDFR_MASK ) { // RXDFR trxStatus = DW1000_TRX_STATUS_IDLE; #ifdef DECADUINO_DEBUG // Serial.print("RXDFR "); #endif // Good frame if ( sysStatusReg & DW1000_REGISTER_SYS_STATUS_RXFCG_MASK ) { // RXFCG #ifdef DECADUINO_DEBUG //Serial.print("RXFCG "); #endif if ( rxData == NULL ) { #ifdef DECADUINO_DEBUG Serial.print("Error: no RX buffer set"); #endif } else { // get frame length ui32t = (readSpiUint32(DW1000_REGISTER_RX_FINFO) & DW1000_REGISTER_RX_FINFO_RXFLEN_MASK) - 2; // FCS is 2-bytes long. Avoid it in the len. *rxDataLen = (uint16_t)ui32t; #ifdef DECADUINO_DEBUG //sprintf((char*)debugStr,"length=%dbytes ", *rxDataLen); // Serial.print((char*)debugStr); #endif // get frame data if ( rxDataLenMax != 0 ) { // Put frame data at the end of the buffer readSpi(DW1000_REGISTER_RX_BUFFER, rxData+rxDataLenMax-*rxDataLen, *rxDataLen); } else { // Put frame data at the begin of the buffer readSpi(DW1000_REGISTER_RX_BUFFER, rxData, *rxDataLen); } // rxDataAvailable = true; if ( sysStatusReg & DW1000_REGISTER_SYS_STATUS_LDEDONE_MASK ) { // Get RX timestamp encodeUint64(0, buf); // init buffer the 64-bit buffer readSpi(DW1000_REGISTER_RX_TIME, buf, 5); lastRxTimestamp = decodeUint64(buf); // Get transmitter-receiver skew (clock offset or crystal offset between the local receiver and the remote end transmitter device) readSpi(DW1000_REGISTER_RX_TTCKO, buf, 3); /* Commented by Adrien on 20150906 ui32t = decodeUint32(buf) & 0x0007FFFF; // Clock offset is a 19-bit signed integer if ( ui32t & 0x00080000 ) ui32t |= 0xFFF80000; // negative value ui32t = 0x01F00000/ui32t; */ // Drien 20150906: should we read rxttcki value in DW1000_REGISTER_RX_TTCKI? rxttcki = 32505856; // Turn rxtofs to a signed double value (RD032014) if (buf[2] & 0x04 ) { // rxtofs is negative buf[2] |= 0xF8; buf[2] = ~buf[2]; buf[1] = ~buf[1]; buf[0] = ~buf[0]; rxtofs = buf[2] * 256*256 + buf[1] * 256 + buf[0]; rxtofs = rxtofs+1; rxtofs = rxtofs*-1; } else { rxtofs = buf[2] * 256*256 + buf[1] * 256 + buf[0]; } clkOffset = rxtofs * 1000000 / rxttcki; rxDataAvailable = true; // Serial.print("clock offset="); // Serial.println(ui32t, HEX); // Serial.println(offseti); // Serial.print("RXTOFS=0x"); // Serial.println(ui32t, HEX); // ui32t = 0x01F00000/ui32t; // Serial.print("clock offset=0x"); // Serial.println(ui32t, HEX); #ifdef DECADUINO_DEBUG Serial.print("RX Frame timestamp="); printUint64(lastRxTimestamp); Serial.print(", skew="); Serial.println(clkOffset); #endif } } // Clearing the RXFCG bit (it clears the interrupt if enabled) ack |= DW1000_REGISTER_SYS_STATUS_RXFCG_MASK; } // Bad frame (FCS error) if ( sysStatusReg & DW1000_REGISTER_SYS_STATUS_RXFCE_MASK ) { // RXFCE #ifdef DECADUINO_DEBUG Serial.println("RXFCG (FCS error)"); #endif // Clearing the RXFCG bit (it clears the interrupt if enabled) ack |= DW1000_REGISTER_SYS_STATUS_RXFCE_MASK; } // Clearing the RXDFR bit (it clears the interrupt if enabled) ack |= DW1000_REGISTER_SYS_STATUS_RXDFR_MASK; } // Manage TX completion interrupt if ( sysStatusReg & DW1000_REGISTER_SYS_STATUS_TXFRS_MASK ) { // TXFRS trxStatus = DW1000_TRX_STATUS_IDLE; // Read TX timestamp encodeUint64(0, buf); // // init buffer the 64-bit buffer readSpi(DW1000_REGISTER_TX_TIME, buf, 5); lastTxTimestamp = decodeUint64(buf); lastTxOK = true; #ifdef DECADUINO_DEBUG Serial.print("TX Frame OK. Tx timestamp="); printUint64(lastTxTimestamp); #endif ack |= DW1000_REGISTER_SYS_STATUS_TXFRS_MASK; } // Acknoledge by writing '1' in all set bits in the System Event Status Register writeSpiUint32(DW1000_REGISTER_SYS_STATUS, ack); #ifdef DECADUINO_DEBUG Serial.println(); #endif } bool DecaDuino::hasTxSucceeded() { return lastTxOK; } uint64_t DecaDuino::alignDelayedTransmission ( uint64_t wantedDelay ) { return ((getSystemTimeCounter() + wantedDelay) & 0xFFFFFFFE00) + getAntennaDelay(); } uint8_t DecaDuino::pdDataRequest(uint8_t* buf, uint16_t len) { return pdDataRequest(buf, len, false, 0); } uint8_t DecaDuino::pdDataRequest(uint8_t* buf, uint16_t len, uint8_t delayed, uint64_t time) { uint32_t ui32t; uint8_t tempbuf[8]; #ifdef DECADUINO_DEBUG sprintf((char*)debugStr,"Request to send %dbyte(s): |", len); Serial.print((char*)debugStr); for (int i=0;i> 8; to[0] = from & 0xFF; } uint32_t DecaDuino::decodeUint32 ( uint8_t *data ) { return 0 | (data[3] << 24) | (data[2] << 16) | (data[1] << 8) | data[0]; } void DecaDuino::encodeUint32 ( uint32_t from, uint8_t *to ) { to[3] = (from & 0xFF000000) >> 24; to[2] = (from & 0xFF0000) >> 16; to[1] = (from & 0xFF00) >> 8; to[0] = from & 0xFF; } uint64_t DecaDuino::decodeUint40 ( uint8_t *data ) { uint64_t tmp = 0; tmp = data[4]; tmp = tmp << 32; tmp = tmp | decodeUint32(data); return tmp; } void DecaDuino::encodeUint40 ( uint64_t from, uint8_t *to ) { to[4] = (from & 0xFF00000000) >> 32; to[3] = (from & 0xFF000000) >> 24; to[2] = (from & 0xFF0000) >> 16; to[1] = (from & 0xFF00) >> 8; to[0] = from & 0xFF; } uint64_t DecaDuino::decodeUint64 ( uint8_t *data ) { uint64_t tmp = 0; tmp = decodeUint32(&data[4]); // | decodeUint32(data); tmp = tmp << 32; tmp = tmp | decodeUint32(data); return tmp; } void DecaDuino::encodeUint64 ( uint64_t from, uint8_t *to ) { to[7] = (from & 0xFF00000000000000) >> 56; to[6] = (from & 0xFF000000000000) >> 48; to[5] = (from & 0xFF0000000000) >> 40; to[4] = (from & 0xFF00000000) >> 32; to[3] = (from & 0xFF000000) >> 24; to[2] = (from & 0xFF0000) >> 16; to[1] = (from & 0xFF00) >> 8; to[0] = from & 0xFF; } float DecaDuino::decodeFloat ( uint8_t *data ) { typedef union _data { float f; char s[4]; } myData; myData q; q.s[0] = data[0]; q.s[1] = data[1]; q.s[2] = data[2]; q.s[3] = data[3]; return q.f; } void DecaDuino::encodeFloat ( float from, uint8_t *to ) { typedef union _data { float f; char s[4]; } myData; myData q; q.f = from; to[0] = q.s[0]; to[1] = q.s[1]; to[2] = q.s[2]; to[3] = q.s[3]; } void DecaDuino::printUint64 ( uint64_t ui64 ) { uint8_t buf[8]; encodeUint64(ui64, buf); sprintf((char*)debugStr, "%08lx%08lx", decodeUint32(&buf[4]), decodeUint32(buf)); Serial.print((char*)debugStr); } void DecaDuino::getSystemTimeCounter ( uint64_t *p ) { uint8_t buf[8]; encodeUint64(0, buf); // init buffer the 64-bit buffer readSpi(DW1000_REGISTER_SYS_TIME, buf, 5); *p = decodeUint64(buf); } void DecaDuino::setPHRMode(uint8_t mode) { uint32_t ui32t; ui32t = readSpiUint32(DW1000_REGISTER_SYS_CFG); ui32t = ui32t & (~DW1000_REGISTER_SYS_CFG_PHR_MODE_MASK); ui32t |= mode << DW1000_REGISTER_SYS_CFG_PHR_MODE_SHIFT; writeSpiUint32(DW1000_REGISTER_SYS_CFG,ui32t); } uint8_t DecaDuino::getPHRMode(void) { uint32_t ui32t; ui32t = readSpiUint32(DW1000_REGISTER_SYS_CFG); ui32t = (ui32t & DW1000_REGISTER_SYS_CFG_PHR_MODE_MASK) >> DW1000_REGISTER_SYS_CFG_PHR_MODE_SHIFT; return (uint8_t)ui32t; } uint64_t DecaDuino::getSystemTimeCounter ( void ) { uint64_t p; getSystemTimeCounter(&p); return p; } uint64_t DecaDuino::getLastTxTimestamp() { return lastTxTimestamp; } uint64_t DecaDuino::getLastRxTimestamp() { return lastRxTimestamp; } double DecaDuino::getLastRxSkew() { return clkOffset; } uint16_t DecaDuino::getPanId() { uint8_t buf[2]; readSpiSubAddress(DW1000_REGISTER_PANADR, DW1000_REGISTER_PANADR_PANID_OFFSET, buf, 2); return decodeUint16(buf); } uint16_t DecaDuino::getShortAddress() { uint8_t buf[2]; readSpiSubAddress(DW1000_REGISTER_PANADR, DW1000_REGISTER_PANADR_SHORT_ADDRESS_OFFSET, buf, 2); return decodeUint16(buf); } uint64_t DecaDuino::getEuid() { uint8_t buf[8]; readSpi(DW1000_REGISTER_EUI, buf, 8); return decodeUint64(buf); } void DecaDuino::setPanId(uint16_t panId) { uint8_t buf[2]; encodeUint16(panId, buf); writeSpiSubAddress(DW1000_REGISTER_PANADR, DW1000_REGISTER_PANADR_PANID_OFFSET, buf, 2); } void DecaDuino::setShortAddress(uint16_t shortAddress) { uint8_t buf[2]; encodeUint16(shortAddress, buf); writeSpiSubAddress(DW1000_REGISTER_PANADR, DW1000_REGISTER_PANADR_SHORT_ADDRESS_OFFSET, buf, 2); } void DecaDuino::setShortAddressAndPanId(uint16_t shortAddress, uint16_t panId) { setPanId(panId); setShortAddress(shortAddress); } int DecaDuino::setShortAddressAndPanId(uint32_t shortAddressPanId) { uint32_t ret; writeSpiUint32(0x03, shortAddressPanId); ret = readSpiUint32(0x03); if ( ret != shortAddressPanId ) { #ifdef DECADUINO_DEBUG Serial.println("Setting Short Address and PanId OK\n"); #endif return false; } else { #ifdef DECADUINO_DEBUG Serial.println("Error while Setting Short Address and PanId\n"); #endif return true; } } uint8_t DecaDuino::getChannelRaw(void) { uint8_t buf; readSpiSubAddress(DW1000_REGISTER_CHAN_CTRL, 0, &buf, 1); return buf; } uint8_t DecaDuino::getChannel(void) { return getChannelRaw() & 0x0F; } uint8_t DecaDuino::getRxPrf(void) { uint32_t ui32t; ui32t = readSpiUint32(DW1000_REGISTER_CHAN_CTRL); ui32t = ( ui32t & DW1000_REGISTER_CHAN_CTRL_RXPRF_MASK) >> 18; return (uint8_t)ui32t; } uint8_t DecaDuino::getTxPcode(void) { uint32_t ui32t; ui32t = readSpiUint32(DW1000_REGISTER_CHAN_CTRL); ui32t = ( ui32t & DW1000_REGISTER_CHAN_CTRL_TX_PCODE_MASK) >> 22; return (uint8_t)ui32t; } uint8_t DecaDuino::getRxPcode(void) { uint32_t ui32t; ui32t = readSpiUint32(DW1000_REGISTER_CHAN_CTRL); ui32t = ( ui32t & DW1000_REGISTER_CHAN_CTRL_RX_PCODE_MASK) >> 27; return (uint8_t)ui32t; } bool DecaDuino::setChannel(uint8_t channel) { uint32_t ui32t; if ( ( channel != 6 ) && ( channel <= 7 ) && ( channel >= 1 ) ) { channel = channel + (channel << 4); ui32t = readSpiUint32(DW1000_REGISTER_CHAN_CTRL); ui32t = ui32t & 0xFFFFFF00; ui32t |= channel; // set rx and tx channel writeSpiUint32(DW1000_REGISTER_CHAN_CTRL, ui32t); if ( getChannelRaw() == channel ) return true; } return false; } bool DecaDuino::setRxPrf(uint8_t prf) { uint32_t ui32t; if ( ( prf == 1 ) || ( prf == 2 ) ) { ui32t = readSpiUint32(DW1000_REGISTER_CHAN_CTRL); ui32t = ui32t & (~DW1000_REGISTER_CHAN_CTRL_RXPRF_MASK); ui32t |= prf << 18; writeSpiUint32(DW1000_REGISTER_CHAN_CTRL, ui32t); return true; } else return false; } bool DecaDuino::setTxPcode(uint8_t pcode) { uint32_t ui32t; if ( ( pcode > 0 ) && ( pcode <= 20 ) ) { ui32t = readSpiUint32(DW1000_REGISTER_CHAN_CTRL); ui32t = ui32t & (~DW1000_REGISTER_CHAN_CTRL_TX_PCODE_MASK); ui32t |= pcode << 22; writeSpiUint32(DW1000_REGISTER_CHAN_CTRL, ui32t); return true; } else return false; } bool DecaDuino::setRxPcode(uint8_t pcode) { uint32_t ui32t; if ( ( pcode > 0 ) && ( pcode <= 20 ) ) { ui32t = readSpiUint32(DW1000_REGISTER_CHAN_CTRL); ui32t = ui32t & (~DW1000_REGISTER_CHAN_CTRL_RX_PCODE_MASK); ui32t |= pcode << 27; writeSpiUint32(DW1000_REGISTER_CHAN_CTRL, ui32t); return true; } else return false; } int DecaDuino::getPreambleLength(void) { uint32_t ui32t; uint32_t mask; int plength; mask = 0x003C0000; // bits 21, 20, 19 and 18 from DW1000_REGISTER_TX_FCTRL ui32t = readSpiUint32(DW1000_REGISTER_TX_FCTRL); ui32t = ui32t & mask; ui32t = ui32t >> 18; // Preamble length selection (Table 15, Page 73 from DW1000 User Manual) switch(ui32t){ case 0x00000001: plength = 64; break; case 0x00000005: plength = 128; break; case 0x00000009: plength = 256; break; case 0x0000000D: plength = 512; break; case 0x00000002: plength = 1024; break; case 0x00000006: plength = 1536; break; case 0x0000000A: plength = 2048; break; case 0x00000003: plength = 4096; break; default: plength = 128; break; } #ifdef DECADUINO_DEBUG sprintf((char*)debugStr,"TX_FCTRL=%08x\n", ui32t); Serial.print((char*)debugStr); #endif return plength; } bool DecaDuino::setPreambleLength (int plength) { uint32_t ui32t; uint32_t mask; switch(plength){ case 64: mask = 0x00040000; break; case 128: mask = 0x00140000; break; case 256: mask = 0x00240000; break; case 512: mask = 0x00340000; break; case 1024: mask = 0x00080000; break; case 1536: mask = 0x00180000; break; case 2048: mask = 0x00280000; break; case 4096: mask = 0x000C0000; break; default: return false; } ui32t = readSpiUint32(DW1000_REGISTER_TX_FCTRL); ui32t = ui32t & 0xFFC3FFFF; // bits 21, 20, 19, 18 to zero ui32t |= mask; writeSpiUint32(DW1000_REGISTER_TX_FCTRL, ui32t); return true; } uint16_t DecaDuino::getAntennaDelay() { return antennaDelay; } void DecaDuino::setAntennaDelay(uint16_t newAntennaDelay) { setAntennaDelayReg(newAntennaDelay); antennaDelay = newAntennaDelay; } uint16_t DecaDuino::getAntennaDelayReg(){ uint8_t buf[2]; readSpi(DW1000_REGISTER_TX_ANTD, buf, 2); return decodeUint16(buf); } void DecaDuino::setAntennaDelayReg(uint16_t newAntennaDelay) { uint8_t buf[2]; encodeUint16(newAntennaDelay, buf); writeSpi(DW1000_REGISTER_TX_ANTD, buf, 2); } uint8_t DecaDuino::getTemperatureRaw() { uint8_t u8t; ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { u8t = 0x80; writeSpiSubAddress(0x28, 0x11, &u8t, 1); // 1. Write Sub-Register 28:11 1byte 0x80 u8t = 0x0A; writeSpiSubAddress(0x28, 0x12, &u8t, 1); // 2. Write Sub-Register 28:12 1byte 0x0A u8t = 0x0F; writeSpiSubAddress(0x28, 0x12, &u8t, 1); // 3. Write Sub-Register 28:12 1byte 0x0F u8t = 0x01; writeSpiSubAddress(0x2A, 0x00, &u8t, 1); // 4. Write Register 2A:00 1byte 0x01 u8t = 0x00; writeSpiSubAddress(0x2A, 0x00, &u8t, 1); // 5. Write Register 2A:00 1byte 0x00 readSpiSubAddress(0x2A, 0x04, &u8t, 1); // 6. Read Register 2A:04 1byte 8 bit Temperature reading } return u8t; } uint8_t DecaDuino::getVoltageRaw() { uint8_t u8t; ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { u8t = 0x80; writeSpiSubAddress(0x28, 0x11, &u8t, 1); // 1. Write Sub-Register 28:11 1byte 0x80 u8t = 0x0A; writeSpiSubAddress(0x28, 0x12, &u8t, 1); // 2. Write Sub-Register 28:12 1byte 0x0A u8t = 0x0F; writeSpiSubAddress(0x28, 0x12, &u8t, 1); // 3. Write Sub-Register 28:12 1byte 0x0F u8t = 0x01; writeSpiSubAddress(0x2A, 0x00, &u8t, 1); // 4. Write Register 2A:00 1byte 0x01 u8t = 0x00; writeSpiSubAddress(0x2A, 0x00, &u8t, 1); // 5. Write Register 2A:00 1byte 0x00 readSpiSubAddress(0x2A, 0x03, &u8t, 1); // 6. Read Register 2A:03 1byte 8 bit Voltage reading } return u8t; } float DecaDuino::getTemperature(void) { // Temperature (°C )= (SAR_LTEMP - (OTP_READ(Vtemp @ 23°C )) x 1.14) + 23 // Todo: what is OTP_READ(Vtemp @ 23°C ) ? return 0; } float DecaDuino::getVoltage(void) { // Voltage (volts) = (SAR_LVBAT- (OTP_READ(Vmeas @ 3.3 V )) /173) + 3.3 // Todo: what is OTP_READ(Vmeas @ 3.3 V ) ? return 0; } void DecaDuino::sleepRequest(void) { uint8_t ui8t; #ifdef DECADUINO_DEBUG sprintf((char*)debugStr,"sleep request"); Serial.println((char*)debugStr); #endif readSpiSubAddress(DW1000_REGISTER_AON_CFG0, DW1000_REGISTER_OFFSET_AON_CFG0, &ui8t, 1); ui8t |= DW1000_REGISTER_AON_CFG0_SLEEP_EN_MASK; writeSpiSubAddress(DW1000_REGISTER_AON_CFG0, DW1000_REGISTER_OFFSET_AON_CFG0, &ui8t, 1); readSpiSubAddress(DW1000_REGISTER_AON_CTRL, DW1000_REGISTER_OFFSET_AON_CTRL, &ui8t, 1); ui8t |= DW1000_REGISTER_AON_CTRL_UPL_CFG_MASK; writeSpiSubAddress(DW1000_REGISTER_AON_CTRL, DW1000_REGISTER_OFFSET_AON_CTRL, &ui8t, 1); delay(1); // The DWM1000 is now sleepping trxStatus = DW1000_TRX_STATUS_SLEEP; }