Unreliable delayed transmit

I have a system that is scheduling transmits packets using the delayed transmit feature of the DW1000.

The code is effectively:

uint64_t timeStamp = ReadRXTimestampFromDW();

// 40 bits, 9 0's at the end
uint64_t TxTime = (timeStamp+DelayConstant)& 0x00fffffffe00;

// put message in buffer
writeRegister(DW1000_TX_BUFFER, 0, message, length);      

length += 2;   // including 2 CRC Bytes

uint8_t backup = readRegister8(DW1000_TX_FCTRL, 1);       
length = ((backup & 0xFC) << 8) | (length & 0x03FF); 
writeRegister16(DW1000_TX_FCTRL, 0, length);       // put length of frame

//write the timestamp on which to send the message
writeRegister40(DW1000_DX_TIME, 0, TxTime);       

// trigger sending process by setting the TXSTRT and TXDLYS bit.
// Set Wait4resp bit to automatically enter RX mode after tx.
writeRegister8(DW1000_SYS_CTRL, 0, 0x02 | 0x04 | 0x80); 

My delay time (DelayConstant) is around 0x09240000.
Most of the time this all works perfectly.

However when the value of timeStamp is close to wrapping around (in the region of 0xFFFFFF0000 or more) the transmit time / re-arm Rx doesn’t happen reliably. It will eventually transmit and start receiving again but it takes a while. Sometimes it works after a second or so, other times it can take 10 seconds or more.
During this time I don’t see any packet Rx interrupts for the data being sent to the unit.
The system does however recover and rearm the receive eventually without any special error case handling or manual re-arming of receive.

It’s not all wrap around situations, e.g. I’ve see a receive time of FFFFF0D543 work fine, it’s only when the internal timer is already almost there and has probably already wrapped around by the time I’ve finished reading the data out of the chip.

Since the delay is fairly large and I never see this issue at any other timestamps I don’t have any reason to believe that I’m somehow not getting things set up in time.

If instead of the delayed send command I use a software timer and then a send immediately command everything works fine (but with less accurate timing) so it doesn’t look to be anything in my code not handling the rollover situation. All I’m doing is logging the times so it’s hard to see how it could be my code.

Has anyone seen this before or have any ideas where to look for a fix?

Hi Andy
Could you review our dwt_starttx and example in our API . For further trouble shooting is needed you could you HPDWARN status flag (in 0x0F) after TX delay command to see if you have a “lateness” condition. Would you see HPDWARN flag set?

API is attached, but please check chapter 3.3 on delayed transmission in the User manual.
(the latest UM version 2.16 is now available from our web)
/LeoDW1000_Software_API_Guide_rev2p7.pdf (1.5 MB)

/Leo

OK I’ve found something odd going on.

In my receive interrupt handler for a valid packet (RXFCG set in the system status register, packet size and data match what’s expected) I read the 40 bits of RX_STAMP, add a constant and set DX_TIME to the result applying a suitable mask to allow for roll over.

But some of the time the value I get for DX_TIME is not even remotely close to SYS_TIME.
e.g. for a packet I got RX_TIME as FFFFFF3934 and SYS_TIME was read as 1EB0364000, another time the numbers were FFFFFF9BFD and A2CE0CD600
The status register when this happens is 0x0000006F03.

Just to check for data corruption on the bus I added a check to read RX_TIME a second time, it gives a consistent value.

So it looks like some of the time RX_TIME is giving me a random number. When it does this the number is always over 0xFFFFFF0000. It’s not the previous rx time and it doesn’t appear to have any relation to the current system time.

To answer your previous question HPDWARN is acting exactly as expected, it is set when the set time is more than half a cycle away from SYS_TIME, whether that is the case or not depends on the value of SYS_TIME when the error occurs.

I have a workaround.

I’m simply discarding all packets with an RX_TIME > 0xffffff0000.
This means throwing away legitimate range measurements but only about 1 in every 4 million. To get reliable operation without using the timed transmit currently requires me to drop the range measurement rate by 30% so it’s not a hard choice to make.

It’s far from ideal, I’d rather be able to trust the data from the chip, but it’ll do for now.

Hi Andy,

when you get a “bad” RX timestamp, can you read the un-adjusted RX time (register 0x15:09, 40-bits). This is the time of packet arrival before LDE algorithm makes any adjustments. If this is close to system time, then the error in the adjusted time is due to CIR/1st path analysis/LDE

Regards

Looks like the issue is with the adjustment:

RxTime 0xffffff3f3f RawTime 0x9a5fd10000 SysTime 0x9a60522e00

RxTime 0xffffff93a9 RawTime 0x70fa0b1800 SysTime 0x70fa8c6a00

RxTime 0xffffff7232 RawTime 0xc4e9b7dc00 SysTime 0xc4ea390800

Raw rx time is coming in as around 130 us before the current system time which seems reasonable once you allow for the packet length, interrupt handling and reading data from the device.

ok, this is all normal, as in you can get wrong 1st path detection, all depends how the CIR looks, level of noise, interference etc. you can also look at 1st path index, and compare it to a good case. Usually these “bad” FP indices or errors need to be filtered out (using averaging, or other filters) in the higher level application or using sensor fusion.

(or if you are using auto RX re-enable and if got RX error previously - if accurate timestamping is required, auto RX re-enable must not be used)

It does look like the first path is also coming out wrong, in the couple of hundred region rather than the ~750 you’d expect. I’ve seen this before with odd reflections but in that situation the rx time was still vaguely correct rather than the random number I seem to be getting now.
But it does at least give a simple way to filter for it.

Now I’ve got the correct filters I’m also getting the occasional error when the leading edge time is at first glance sensible and the corrected RX time doesn’t start with ffffff.
I had one with a leading edge time of 700, low but not unheard of, and plausible looking times but the difference between raw and corrected Rx time was around 48 million or 750 us.

I’ve now implemented a check on the difference between raw and corrected rx times and reject measurements where the difference between the two is outside of a specified range. This seems to be catching everything but with the down side that I have to read an extra 5 bytes from the device. I’m running on some fairly tight timing constraints so the extra read isn’t idea but I can live with it.

1 Like