Problem with TX after RX

Hey all, sorry for not introducing myself before—I’m a PhD student at UCLA, and I’m planning on using the DW for some fun ranging projects in the (very) near future. I’ve run into a problem I can’t seem to figure out, and I was hoping someone here could shed some light on it. I’ve kept the provided decawave drivers for the most part, but I’ve written completely new application code around it (and I no longer use the provided ISR function, etc.) I’m running into the following problem: I have one node sending a message at 1 Hz and another node receiving and trying to reply. It receives just fine, and it can independently transmit just fine as well. If, however, I try to respond to the first node after having received a message from it, I no longer receive good RX frames. I can perform one RX and one TX, and then things seem to break. I can reset the transceiver, and that seems to fix things, but I’d have to do this every time I transmit and I’d lose tons of packets. Oddly enough, I still receive interrupts at the expected time (when the first node is transmitting to me), but it appears that no bit is set in the system status register, so my program is unsure what “event” has occurred to trigger the interrupt.

I’ve noticed some bug fixes in the source code, including one about the LDE flag getting latched when there was a bad frame, but that didn’t seem to apply. I’m using delayed tx commands and “expect rx” flags as well, but the problem seems to persist even if I transmit immediately, manually enable listening, etc. Have I overlooked something?

Thanks in advance, and let me know if more information would help!



do you have acknowlegement response disabled? If no, you wont receive next data frame, just the ack :slight_smile: To see what is happening in your system, investigate SYS_STATUS_ID. What do you mean you dont use ISR function? You dont use the piece of software written by Deca, or you are just not usint interrupt feature at all?

In my application (entire code wrote by maself) I am constantly polling a slave hundred times per second and I get bad frame maybe once per minute so I think it works :slight_smile:
The schema is simple:
transmit frame -> enable RX (SYS_CTRL_ID;RXENAB) ->
–if I receive, I am clearing interrupt bit(SYS_STATUS_ID;SYS_STATUS_RXDFR) and turning off the transceiver (SYS_CTRL_ID;TRXOFF) , processing data and transmit again
–if I don’t receive(software timeout timer): turn off transceiver (TRXOFF) , then PMSC_ID RX_Reset then RX_Set and then SYS_CTRL_ID RXENAB.

For detecting received and sent frames I use interrupts provided by Deca module. Also, I have enabled RX ReEnable after receiving failure (SYS_CFG_ID;SYS_CFG_RXAUTR)

Hey Bartosz,

Thanks for the quick reply. I have ACKs disabled. I’ve also looked at SYS_STATUS_ID, but the odd thing is that no bit in that register is set after my DW gets into a bad state, even though i’m still getting interrupts. And I meant that I’m not using the decawave-provided IRQ (in deca_device.c). I’m still handling the interrupts by myself, but I’m starting to think I must have overlooked something that is done in the provided ISR.

Here’s some more details on what I’m doing:
I’m only allowint RFCG and TFRS interrupts, and only IEEE Data Frames
RX mode is normal and RXENAB is set
One node sends a “RANGE_INIT” message at 1 Hz. The other is supposed to receive and re-transmit a “RANGE_RESP” message. These are custom messages I’ve defined, fitting into an ieee data frame.
I tried a force turn off of the transceiver if I RXed a frame, like you suggested, but then I was unable to transmit afterwards.
Here’s the skeleton of my ISR:

void deca_ranging_isr()
// Let user know an IRQ was triggered
dw_debug(DWRANGE_EVENT_IRQ); // <-- this is always triggering correctly

// Read the event status
int status = dwt_read32bitreg(SYS_STATUS_ID);

// Handle received, error-free packets
if(status & SYS_STATUS_RXFCG)
dw_debug(DWRANGE_EVENT_RXGOOD); // <-- this stops triggering

 // process frame and custom message

 switch( msg->msgType )
     case MSG_RANGE_INIT:
         // send delayed response with response expected
     case MSG_RANGE_RESP:
         // process data


// Handle completed transmissions
else if(status & DWT_INT_TFRS)
// let the user know the transmission was successful

else if(status & (0xFFFFFFFF) )
dw_debug(DWRANGE_EVENT_BADFRAME); //<-- Even this stops triggering, even though IRQ triggers!

// clear the interrupt bit(s)

Folowup: I’ve noticed that there’s also a problem with the reception alone, even if I don’t transmit anything back. Again, I get the correct IRQ, but about 1/3 to 1/2 of the IRQs are not associated with an RXFCG flag. I’ve also incorporated most of the error checking from the decawave-provided ISR now. I’m not sure why system status appeared zero before, but I’m now reading the SYS_STATUS register, and here’s what I see on the different interrupts:

Good interrupts: SYS_STATUS[3:0] = 2, 128, 111, 3
Bad interrupts: SYS_STATUS[3:0] = 2, 128, 0, 2

Which from my understanding means the good frames are getting RXPRD,SFDP, LDEDONE, RXPHE, RXDFR, RXFCG, etc. Bytes 2 and 3 appear to have GPIOIRQ and CLKPLL_LL, but I’d assume these happened early on when powering on and never got cleared, so that’s ok. The bad frames, then, have no RX-related flags at all, even though I know by watching the LEDs on my hardware that clearly the interrupt is coming when it’s receiving something from another device.


One question folowed by a suggestion :slight_smile:
What are the transmission parameters? PRF, Preamble length?
Secondly, the ISR function should always be as short as possible:
void deca_ranging_isr()

///here handle an interrupt!

So sorry for the slow response—I had to do some last minute teaching for high school students this week.
Let me address your suggestion first: I know ISRs should be kept short, but I’m currently keeping mine longer
than I normally would right now so that I can schedule my reply transmissions ASAP. The reason I’m doing this
is because I plan to deploy my code on a platform soon that is already running an RTOS with a 1 ms tick, and
I don’t want to have to wait 1+ ms before my reply is scheduled.

Second, an update: My full ranging is working right now–didn’t change anything too serious in my code, but I started
being more careful about when and where I turned my TRX off and re-enabled RX, as per your suggestions. I still do
get a decent amount of packet loss when I’m more than a couple of meters away though. Maybe this is because of
my TX parameters?

As for TX parameters, I’m trying to deploy this in a room where I’ll eventually have 10 nodes each performing distance
measurements to 16 anchors at 10 Hz each, which is a lot of RF traffic. Because of that, I’m currently using:

Channel 2
RX/TX Code: 9
Rate: 6.8M
Preamble len: 64
PAC: 8
standard SFD
standard PHR mode
no smart power
PG delay 0xC2
power 0x07274767 (0x67 repeating without smart power)
Does that seem reasonable? Essentially as fast a transmission as I can, but I do realize this will result in higher packet loss.


Try to extend preamble to 256, or at least 128. And if u r not using external amp, for the debugging time use full power :slight_smile:

Bartosz Kawłatow

I’ve got my preamble at 256 and PAC at 16 with full power tx as you suggested, and it looks like my throughput is good enough for my purposes now. Thanks
for all the help—I really appreciate it!


On right settings, you should have 0% of miss RX, bad frames etc.


I found no bit in the status register was set too when the IRQ was trigged. I call dwt_forcetrxoff() before enabling Rx, and I find it doesn’t happen again.