#include "deca_regs.h" #include "dw1000_hal.h" #include "dw1000_util.h" #include <stdio.h> #include "Trace.h" extern volatile uint32_t global_time; dw1000_local_data_t dw1000local; // Static local device data //----------------------------------------- // map the channel number to the index in the configuration arrays below // 0th element is chan 1, 1st is chan 2, 2nd is chan 3, 3rd is chan 4, 4th is chan 5, 5th is chan 7 const uint8_t chan_idx[NUM_CH_SUPPORTED] = {0, 0, 1, 2, 3, 4, 0, 5}; //----------------------------------------- const uint32_t tx_config[NUM_CH] = { RF_TXCTRL_CH1, /* Tx value match UM */ RF_TXCTRL_CH2, RF_TXCTRL_CH3, RF_TXCTRL_CH4, RF_TXCTRL_CH5, RF_TXCTRL_CH7, }; //RF -> Channel_Specific_Cfg -> Channel_Cfg -> RF_PLL -> RF PLL2 const uint8_t pll2_config[NUM_CH][5] = { { 0x07, 0x04, 0x00, 0x09, 0x1E}, //3.5Ghz { 0x08, 0x05, 0x40, 0x08, 0x26}, //4Ghz { 0x09, 0x10, 0x40, 0x08, 0x56}, //4.5Ghz { 0x08, 0x05, 0x40, 0x08, 0x26}, //4Ghz WBW { 0x1D, 0x04, 0x00, 0x08, 0xA6}, //6.5Ghz { 0x1D, 0x04, 0x00, 0x08, 0xA6} //6.5Ghz WBW }; const uint8_t pll2calcfg = (0x60 | 0x10) ; /* Bits 7:5 must always be set to binary 011. Failure to maintain this value will result in DW1000 malfunction. */ //bandwidth configuration const uint8_t rx_config[NUM_BW] = { 0xD8, //NBW 0xBC //WBW }; //FIXME //const agc_cfg_struct agc_config = //{ // AGC_TUNE2_VAL, // // { AGC_TUNE1_16M , AGC_TUNE1_64M } //adc target //} const uint8_t dwnsSFDlen[NUM_BR] = { 0x40, 0x10, 0x08 }; //DW non-standard SFD length for 110k, 850k and 6.81M // SFD Threshold const uint16_t sftsh[NUM_BR][NUM_SFD] = { //110k { (0x0a), //RX_SFTSH_LONG - standard (0x16) //RX_SFTSH_USR_LONG - non-standard (DW - length specified above dwnsSFDlen) }, //850k { (0x01), //RX_SFTSH_SHORT (0x06), //RX_SFTSH_USR_SHORT - non-standard (DW - length specified above dwnsSFDlen) }, //6.81Mb { (0x01), //RX_SFTSH_SHORT (0x02), //RX_SFTSH_USR_SHORT - non-standard (DW - length specified above dwnsSFDlen) } }; const uint16_t dtune1[NUM_PRF] = { 0x0087, // 16 MHz PRF 0x008D // 64 MHz PRF }; const uint32_t digital_bb_config[NUM_PRF][NUM_PACS] = { //16 PRF { //PAC 8 0x311A002D, //PAC 16 0x331A0052, //PAC 32 0x351A009A, //PAC 64 0x371A011D }, //64 PRF { //PAC 8 0x313B006B, //PAC 16 0x333B00BE, //PAC 32 0x353B015E, //PAC 64 0x373B0296 } }; const uint16_t lde_replicaCoeff[PCODES] = { // 0 (int)(0.0 * 65536), // 1 (int)(0.35 * 65536), // 2 (int)(0.35 * 65536), // 3 (int)(0.32 * 65536), // 4 (int)(0.26 * 65536), // 5 (int)(0.27 * 65536), // 6 (int)(0.18 * 65536), // 7 (int)(0.50 * 65536), // 8 (int)(0.32 * 65536), // 9 (int)(0.16 * 65536), // 10 (int)(0.20 * 65536), // 11 (int)(0.23 * 65536), // 12 (int)(0.24 * 65536), // 13 (int)(0.23 * 65536), // 14 (int)(0.21 * 65536), // 15 (int)(0.17 * 65536), // 16 (int)(0.21 * 65536), // 17 (int)(0.20 * 65536), // 18 (int)(0.21 * 65536), // 19 (int)(0.21 * 65536), // 20 (int)(0.28 * 65536), // 21 (int)(0.23 * 65536), // 22 (int)(0.22 * 65536), // 23 (int)(0.19 * 65536), // 24 (int)(0.22 * 65536) }; void dw1000Util_enableclocks(int clocks) { uint8_t reg[2]; dw1000Hal_readSubRegister(PMSC_ID,PMSC_CTRL0_OFFSET, reg, 2); switch(clocks) { case ENABLE_ALL_SEQ: { reg[0] = 0x00 ; reg[1] = reg[1] & 0xfe; } break; case FORCE_SYS_XTI: { //system and rx reg[0] = 0x01 | (reg[0] & 0xfc); } break; case FORCE_SYS_PLL: { //system reg[0] = 0x02 | (reg[0] & 0xfc); } break; case READ_ACC_ON: { reg[0] = 0x48 | (reg[0] & 0xb3); reg[1] = 0x80 | reg[1]; } break; case READ_ACC_OFF: { reg[0] = reg[0] & 0xb3; reg[1] = 0x7f & reg[1]; } break; case FORCE_OTP_ON: { reg[1] = 0x02 | reg[1]; } break; case FORCE_OTP_OFF: { reg[1] = reg[1] & 0xfd; } break; case FORCE_TX_PLL: { reg[0] = 0x20| (reg[0] & 0xcf); } break; default: break; } //DECA: Need to write lower byte separately before setting the higher byte(s) dw1000Hal_writeSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET, ®[0], 1); dw1000Hal_writeSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET + 1, ®[0], 1); } void dw1000Util_enableRX(){ #ifdef DOUBLE_BUFFER //Align HSRBP and ICRBP if needed (see page 37 in the Usermanual) uint64_t event = 0; dw1000Hal_readRegisterFromIsr(SYS_STATUS_ID, (uint8_t*) &event, SYS_STATUS_LEN); if((event & SYS_STATUS_HSRBP) != (event & SYS_STATUS_ICRBP)){ uint32_t reg; dw1000Hal_readRegisterFromIsr(SYS_CTRL_ID, (uint8_t *)®, SYS_CTRL_LEN); reg |= SYS_CTRL_HSRBTOGGLE; dw1000Hal_writeRegisterFromIsr(SYS_CTRL_ID, (uint8_t *)®, SYS_CTRL_LEN); } #endif uint32_t sys_ctrl = 0; dw1000Hal_readRegisterFromIsr(SYS_CTRL_ID, (uint8_t*) &sys_ctrl, SYS_CTRL_LEN); // switch to rx mode sys_ctrl |= SYS_CTRL_RXENAB; dw1000Hal_writeRegisterFromIsr(SYS_CTRL_ID, (uint8_t*) &sys_ctrl, SYS_CTRL_LEN); } uint32_t dw1000Util_otpread(uint32_t address) { uint8_t buf[4]; uint32_t ret_data; //TODO Wieso buf? Und nicht gleich von address? buf[1] = (address>>8) & 0xff; buf[0] = address & 0xff; // Write the address dw1000Hal_writeSubRegister(OTP_IF_ID, OTP_ADDR, buf, OTP_ADDR_LEN); // Assert OTP Read (self clearing) buf[0] = 0x03; // 0x03 for manual drive of OTP_READ and OTP_READ dw1000Hal_writeSubRegister(OTP_IF_ID, OTP_CTRL, buf, 1); buf[0] = 0x00; // Bit0 is not autoclearing, so clear it (Bit 1 is but we clear it anyway). dw1000Hal_writeSubRegister(OTP_IF_ID, OTP_CTRL, buf, 1); // Read read data, available 40ns after rising edge of OTP_READ dw1000Hal_readSubRegister(OTP_IF_ID,OTP_RDAT, &ret_data, OTP_RDAT_LEN); // Return the 32bit of read data return (ret_data); } void dw1000Util_getRxTimestamp(dw1000_global_time_t *time_buffer){ uint8_t buf[5] = {0}; uint64_t radio_rx_time = 0; // Read rx timestamp from radio dw1000Hal_readSubRegisterFromIsr(RX_TIME_ID, RX_TIME_RX_STAMP_OFFSET, buf, RX_TIME_RX_STAMP_LEN); radio_rx_time = ((uint64_t) buf[4]) << 32 | ((uint64_t) buf[3]) << 24 | ((uint64_t) buf[2]) << 16 | ((uint64_t) buf[1]) << 8 | ((uint64_t) buf[0]) << 0; // multiply by 16 to get picoseconds (actually ~15.65 is right) radio_rx_time <<= 4; // Calculate timestamp in milliseconds and sub-milliseconds parts separately uint64_t ms_buf = global_time * GLOBAL_TIME_TICK_MS + radio_rx_time / 1000000000llu; uint64_t subms_buf = radio_rx_time - (global_time * 1000000000llu); if(ms_buf < dw1000local.last_rx_time.ms) { // The radio timer had an overflow, but the global timer didn't, yet ms_buf += GLOBAL_TIME_TICK_MS; } // Write calculated timestamp to provided structure time_buffer->ms = ms_buf; time_buffer->subms = subms_buf; // Store new timestamp to be able to detect asynchronous overflows dw1000local.last_rx_time.ms = ms_buf; } void lltoa(uint64_t val, char *dest_buf, uint8_t base) { char buf[64] = {0}; uint32_t i = 62; for(; val && i ; --i, val /= base) { buf[i] = "0123456789abcdef"[val % base]; } memcpy(dest_buf, &buf[i + 1], 64); } void dw1000Util_printGlobalTimestamp(dw1000_global_time_t *time) { char ms_buf[64] = {0}; char subms_buf[64] = {0}; // Convert uint64_t timestamp to strings, because printf can't handle 64-bit integers lltoa(time->ms, ms_buf, 10); lltoa(time->subms, subms_buf, 10); printf("RX time = %s.%sms\n", ms_buf, subms_buf); } void dw1000Util_forceTrxOff(void) { uint32_t sys_ctrl = 0; //DECA: decaIrqStatus_t stat ; ??? uint32_t sys_mask; dw1000Hal_readRegisterFromIsr(SYS_MASK_ID, (uint8_t *) &sys_mask, SYS_MASK_LEN); // need to beware of interrupts occurring in the middle of following read modify write cycle // we can disable the radio, but before the status is cleared an interrupt can be set (e.g. the // event has just happened before the radio was disabled) // thus we need to disable interrupt during this operation /// stat = decamutexon() ; DECA: ???:" --> portDISABLE_INTERRUPTS(); //FIXME Eigentlich eher EXTI uint32_t tmp_mask = 0; // No interrupts dw1000Hal_writeRegisterFromIsr(SYS_MASK_ID, (uint8_t *) &tmp_mask, SYS_MASK_LEN); //Disable radio dw1000Hal_readRegisterFromIsr(SYS_CTRL_ID, (uint8_t *) &sys_ctrl, 4); sys_ctrl |= SYS_CTRL_TRXOFF;// Immediately cancel all RX and TX operations, bring radio to IDLE state dw1000Hal_writeRegisterFromIsr(SYS_CTRL_ID, (uint8_t *) &sys_ctrl, 4); uint32_t tmp = (CLEAR_ALLTX_EVENTS | CLEAR_ALLRXERROR_EVENTS | CLEAR_ALLRXGOOD_EVENTS); dw1000Hal_writeRegisterFromIsr(SYS_STATUS_ID,(uint8_t *) &tmp, 4) ; //TODO dwt_syncrxbufptrs(); dw1000Hal_writeRegisterFromIsr(SYS_MASK_ID, (uint8_t *) &sys_mask, SYS_MASK_LEN); portENABLE_INTERRUPTS(); } void dw1000Util_reset(void) { uint32_t subreg; dw1000Hal_readSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET, (uint8_t*) &subreg, PMSC_CTRL0_LEN); subreg |= (1 << 0); // SOFTRESET - Set SYSCLKS to 01 subreg &= ~(1 << 1); // SOFTRESET - Zero everything else dw1000Hal_writeSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET, (uint8_t*) &subreg, PMSC_CTRL0_LEN); dw1000Hal_readSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET, (uint8_t*) &subreg, PMSC_CTRL0_LEN); subreg &= ~(15 << 28); // SOFTRESET - Set all to ZERO dw1000Hal_writeSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET, (uint8_t*) &subreg, PMSC_CTRL0_LEN); dw1000Hal_readSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET, (uint8_t*) &subreg, PMSC_CTRL0_LEN); subreg |= (15 << 28); // SOFTRESET - Set all to ONE dw1000Hal_writeSubRegister(PMSC_ID, PMSC_CTRL0_OFFSET, (uint8_t*) &subreg, PMSC_CTRL0_LEN); } void dw1000Util_resetRxOnly(void) { uint32_t subreg; dw1000Hal_readSubRegisterFromIsr(PMSC_ID, PMSC_CTRL0_OFFSET, (uint8_t*) &subreg, PMSC_CTRL0_LEN); subreg &= ~(1 << 28); // SOFTRESET - Set all to ZERO subreg |= (0xe << 28); dw1000Hal_writeSubRegisterFromIsr(PMSC_ID, PMSC_CTRL0_OFFSET, (uint8_t*) &subreg, PMSC_CTRL0_LEN); // dw1000Hal_readSubRegisterFromIsr(PMSC_ID, PMSC_CTRL0_OFFSET, // (uint8_t*) &subreg, PMSC_CTRL0_LEN); subreg |= (0xf << 28); dw1000Hal_writeSubRegisterFromIsr(PMSC_ID, PMSC_CTRL0_OFFSET, (uint8_t*) &subreg, PMSC_CTRL0_LEN); } #ifdef DEBUG void hexdump(uint8_t * buffer, uint8_t len){ char string [2*len +1]; char * string_ptr = string; for (uint8_t i = 0; i < len; i++) { string_ptr += sprintf(string_ptr, "%02X", (unsigned int)*(buffer+i)); } string[2*len] = '\0'; trace_printf("Ev: %s\n", string); } #endif