CIR data from DWM3000 is very strange

Hello, everyone. I have checked for the formal readaccdata() function, the ACC_CLK and ACC_MCLK clock setting is already done by formal version. And the bits are checked to have been changed by clock setting. My CIR logging is like this:

Blockquote"0800000a0000dcffff0a0000080000050000e6ffffffffffdeffffeeffffe8fffff4ffffdbffff1300000700001b0000ffffff0d00000e00000"

Here, many “ffff” shows up which leads to be readed as very large number like 130000, while transfering 24 bits data into signed 18 bits integer. My transferation function is like this:

def bytesdata_process(high, mid, low):
    
    # if first 6 bits of high byte is 1, then it is a negative number
    if high & 0x80:
        return -((high & 0x03) << 16) | (mid << 8) | low
    else:
        return ((high & 0x03) << 16) | (mid << 8) | low
    

then I use the same magnitude calculating method as in others blogs. That is:

    # Create a int32 array to store the magnitude of each sample
    magnitude = []
    bytes_data = np.array(bytes_data, dtype=np.int32)
    for i in range(0, int(len(bytes_data)/6)*6,6):
        real = bytesdata_process(bytes_data[i+2], (bytes_data[i+1]) , bytes_data[i])
        imaginary = bytesdata_process(bytes_data[i+5], (bytes_data[i+4]), bytes_data[i+3])
        magnitude.append(np.sqrt((float)(real*real+ imaginary*imaginary))))

This methos is the same as one success recorded blogs of –https://forum.qorvo.com/t/dwm3000evb-raw-cir-capture-issues/11659/2

However, using this magnitude calculating method in sqrt() will have a invalid calculation warning in command line, ------" RuntimeWarning: overflow encountered in long scalars". It is reasonable because in python. if real is very big like 130000, real*real + imaginary*imaginary will turns out to be a thousand type number. This is reasonable since real*real+ imaginary*imaginary is still a int32 type.

The resulting CIR figure is like this, seems really like CIR. But is not the correct result:
LOS_1m_04

My question is:

  1. Is there anyone encounter the same logging data as us? like many “ffff” occur?
  2. Is our bytesdata_process method right?

Really hope anyone could come to help me, I will be really appreciated !!!

Negative numbers are twos compliment, simply multiplying the value by -1 doesn’t work.
In c the code would be:

int32_t bytesdata_process(uint8_t high, uint8_t mid, uint8_t low) {
    
  int32_t value = ((int32_t)high << 16) |  ((int32_t)mid<< 8)  | low;

   # if first 6 bits of high byte is 1, then it is a negative number
   if (high & 0x04) // bit 18
      value |= 0xfffc << 16; // set bits 31 to 18

   return value;

I’m not sure what the best way is to do this in python, you may need to use a 4 byte array, set the top byte to 0xff for negative or 0 for positive and then convert that array to an integer.

Or to get the inverse of a 2s compliment number you can always invert all the bits and add 1.
So the code becomes something like:

def bytesdata_process(high, mid, low):
    
    # if first 6 bits of high byte is 1, then it is a negative number
    if high & 0x80:
        invert all 3 bytes (I don't know the python for a bitwise invert)
        # note change in brackets, it's - everything not just the high byte
        value =  -(((high & 0x03) << 16) | (mid << 8) | low)
        return  value -1 # -1 not plus 1 because this is after we've changed the sign on the result.
    else:
        return ((high & 0x03) << 16) | (mid << 8) | low
1 Like

Thank you very much dear Andy! I understand now! I don’t know if this negative rule is writen in User Manual. I also have tried to solve it in a strange way which happens to have the same result as yours!

def bytesdata_process(high, mid, low):
    
# if first 6 bits of high byte is 1, then it is a negative number
    temp = ((high << 16) | (mid << 8) | low)
    
    if temp >= 1<<18:
        temp -= 1<<24
    if temp == 0:
        pass
    if temp < -1<<18:
        temp = 0
    if temp >= 1<<17:
        temp -= 1<<16
    if temp > 1<<15:
        temp -= 1<<16
    return temp

And now I got this result (from index 700), which peak index is same as diagnostics result in API, but the peak amplitude is not the same one. The diagnostics info gives the peak amplitude is almost 4 times of the peak value in the figure. eg: CIR peak value = 1802.4430642880236; diagnostics peak value = 6801; I don’t know if it is a normal occasion or I read something wrong.
图片1

At last, I really appreciate your help, it really explain the error!!~

The user manual doesn’t state that the negative numbers are 2s compliment for the simple reason that this is how almost every computer and digital circuit has represented negative numbers for the last 50 years. Always assume 2s compliment for any signed value unless they say otherwise.

There will be a slight difference in the numbers since the peak values will be using some interpolation and extrapolation between points but it shouldn’t be that big a difference.
Check the units on the peak value, a lot of those registers are in fixed point format and need to be divided by the appropriate power of 2 to give the actual value.

Hi Andy! I see. But after trying to divde the data by any number of 2^n, I did not get proper explanation on this. I did the transformation in the code here:

    # Parse the UWB-CIR info data from the remaining bytes
    ipatovPeakInfo = DATA[3] << 24 | DATA[2] << 16 | DATA[1] << 8 | DATA[0]
    data_dict['cir_info']['PeakAmplitude'] = ipatovPeakInfo # This 21-bit field reports the amplitude of the sample peak
    data_dict['cir_info']['PeakIndex'] = (ipatovPeakInfo >> 21) & 0x000003FF # This 10-bit field reports the index of the sample peak
    data_dict['cir_info']['ipatovPower'] = DATA[7] << 24 | DATA[6] << 16 | DATA[5] << 8 | DATA[4] 
    data_dict['cir_info']['ipatovF1'] = (DATA[11] << 24 | DATA[10] << 16 | DATA[9] << 8 | DATA[8]) >> 2 # It has 2 fractional bits
    data_dict['cir_info']['ipatovF2'] = (DATA[15] << 24 | DATA[14] << 16 | DATA[13] << 8 | DATA[12]) >> 2 # It has 2 fractional bits
    data_dict['cir_info']['ipatovF3'] = (DATA[19] << 24 | DATA[18] << 16 | DATA[17] << 8 | DATA[16]) >> 2 # It has 2 fractional bits
    data_dict['cir_info']['ipatovFpIndex'] = (DATA[21] << 8 | DATA[20]) >> 6 # It has 6 fractional bits
    data_dict['cir_info']['ipatovAccumCount'] = DATA[23] << 8 | DATA[22] & 0xFFF

where DATA is a bytearray. I have no idea of what’s wrong with the amplitude substraction. Sorry for bothering again. I hope you have a nice day!

Given all the other power numbers have two fractional bits then I’d expect the peak amplitude and ipatovPower fields to also have fractional bits.
Make sure you’re using the latest user manual, I’ve seen things like this wrong in the past in their documents. If possible check their example code, that is often more trustworthy than the documents for this sort of thing.

If you have two fractional bits then >>2 will round down to the nearest integer. Dividing by 4 will give the correct magnitude while maintaining the full resolution.
Similarly if a field has 6 fractional bits then divide by 2^6.

Yes, sure. I have tried >>2, but I don’t know if 6801/4 = 1700.25 should be seen a possible approximation of 1802.44. But when checking the CIR data, I guess it might because the peak amplitude in the diagnostics method is using 1 index before or after my calculation on peak amplitude in CIR data.
图片2