DW1000 can't switch from RX to TX

I am having troubles changing the mode of a DW1000 from RX to TX.
What I am doing is the following:

  • After I am done with RX, I set Bit 6 (TRXOFF) in SYS_CTRL register and wait until it is cleared:
    def disableTransceiver(self):
        SYS_CTRL = self.read(reg_addr=0x0D, sub_reg_addr=0x00, len=4)
        SYS_CTRL[0] |= (1 << 6)
        self.write(reg_addr=0x0D, sub_reg_addr=0x00, data=SYS_CTRL)

        while True:
            SYS_CTRL = self.read(reg_addr=0x0D, sub_reg_addr=0x00, len=4)
            TRXOFF = SYS_CTRL[0] & (1 << 6)
            if TRXOFF == 0:
                break
  • I write TX-Data into the buffer and set TX buffer length:
    def writeTXData(self, data):
        self.write(reg_addr=0x09, sub_reg_addr=0x00, data=data)

        data_len = len(data) + 2
        tx_fctrl = self.read(reg_addr=0x08, sub_reg_addr=0x00, len=5)
        tx_fctrl[0] = data_len & 0xFF  # set 7 bit data length
        tx_fctrl[1] |= (data_len >> 8) & 0x03
        tx_fctrl[1] |= (1 << 6)  # set transmit bit rate 6.8Mbps
        self.write(reg_addr=0x08, sub_reg_addr=0x00, data=tx_fctrl)
  • I start transmit and wait until TXFRS bit in SYS_STATUS reg is set:
    def sendTX(self):
        sys_ctrl = self.read(reg_addr=0x0D, sub_reg_addr=0x00, len=4)
        sys_ctrl[0] &= ~0x01  # Disable Suppress auto-FCS
        sys_ctrl[0] |= (1 << 1)  # Transmit Start
        self.write(reg_addr=0x0D, sub_reg_addr=0x00, data=sys_ctrl)

        while True:
            SYS_STATUS = self.read(reg_addr=0x0F, sub_reg_addr=0x00, len=5)
            TXFRB = SYS_STATUS[0] & (1 << 4)
            TXPRS = SYS_STATUS[0] & (1 << 5)
            TXPHS = SYS_STATUS[0] & (1 << 6)
            TXFRS = SYS_STATUS[0] & (1 << 7)
            TXBERR = SYS_STATUS[3] & (1 << 4)
            CLKPLL_LL = SYS_STATUS[3] & (1 << 1)
            if TXFRB != 0:
                print("Transmit Frame Begins.")
            if TXPRS != 0:
                print("Transmit Preamble Sent")
            if TXPHS != 0:
                print("Transmit PHY Header Sent")
            if TXFRS != 0:
                break
            if TXBERR != 0:
                print("Transmit Buffer Error")
            if CLKPLL_LL != 0:
                print("Clock PLL Losing Lock")

Unfortunately, neither TXFRB, TXPRS, TXPHS nor TXFRS get set ever. Do you know what this could be?

Not a direct answer as to what’s wrong but here’s my transmit code:

void Dw1000::sendFrame(uint8_t* message, uint16_t length)
{
#ifdef allowLongFrames
    if (length >= 1021) length = 1021;   
    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);
#else
    if (length >= 125) length = 125; 
    uint8_t len_7bit = length;
    writeRegister(DW1000_TX_BUFFER, 0, message, len_7bit);            // fill buffer
    len_7bit += 2;                                                    // including 2 CRC Bytes
    writeRegister8(DW1000_TX_FCTRL, 0, len_7bit);
#endif

// disable any existing transfers and force to idle
writeRegister8(DW1000_SYS_CTRL, 0, 0x40);

 // trigger sending process by setting the TXSTRT bit.
writeRegister8(DW1000_SYS_CTRL, 0, 1<<TXSTRT | 1<<WAIT4RESP);       
}

My code then returns to the idle state until it gets a transmit done interrupt. While in theory this supports long writes I don’t think I’ve ever tested it with support for packets over 127 bytes enabled. With that caveat this code works reliably.

This is c rather than python but you should be able to follow it, as far as I can tell the basic flow and logic is the same as you have. I can’t see any critical bits you’re missing. The only real difference is that I’m doing the minimal reads/writes rather than pulling the whole register, modifying some bits and writing it all back. And since I’m only writing the minimum needed I can often skip the read part completely.

I don’t know, I just did it like you and it still doesn’t work.
The only way I got this working is by hard-resetting the DW1000. Sometimes it is just annoying…

My mistake, I accidentally disabled the TX clock while reading the channel impulse response register (for that, RX-Clock has to be forced from PLL via PMSC_CTRL0).

1 Like