spidev.xfer and spidev.xfer2 return bad data with repeated requests to read a register

I have an spi device attached to a Jetson. The device is detected and works well provided I restrict the calls to spidev.xfer and spidev.xfer2. My device is configured according to its datasheet and works well on Arduino platforms. Connection is done this way:

import spidev    
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 10000000
spi.mode = 0b00

I can confirm connection by doing this test:

# read from address 0, shifting by one and appending the read flag
# add a dummy address of 0x00 to do the reading, expect 0xAD back
addr = [0x00 << 1 | 0x01, 0x00]
print(spi.xfer(addr)[1] == 0xAD) # prints true if found, false if not

I can lazily read the data from the device and it works fine. If I set a loop to read from the device as soon as data is available the data becomes garbled and out of order. For example:

while True:
    status = spi.xfer([0x04 << 1 | 0x01, 0x00])[1]
    # if the first bit is set, then there's data to read
    if (status & 0x01) == 1:
        addr = [0x00] * 10 # number of bytes to read plus 1
        addr[0] = 0x08 << 1 | 0x01
        data = spi.xfer(addr)[1:]

My device is configured to deliver new data at 4 KHz, SPI is set to the device max of 10 MHz. When I count the calls for status and data I can get around 8000 and 5000 respectively per second. This tells me that status is failing at some point, because the device can't report at 5000 Hz. When I look at data itself the values will be inconsistent across the 9 bytes read. The values are integers and should be in an ascending pattern of 3 something like:

[62, 192, 240, 62, 192, 240, 62, 192, 240]

Instead what happens is something like this:

[192, 240, 62, 192, 240, 62, 192, 240, 62]
[240, 62, 192, 240, 62, 192, 240, 62, 192]

The returned result is off by one or 2 places. Over time it becomes impossible to tell what data is missing and since there are more returned values than possible, some must be repeats, or partial repeats or junk. The device manufacturer specifies that reads to the data register are always consistent, so any set of 3 ascending values should always be ascending. Also status being true more than 4000 times per second leads me to believe status is corrupted or junk at some times. My conclusion is that spi.xfer is producing unexpected results.

I have "fixed" it by forcing calls to spi.xfer to be close to the sample frequency of the device by doing this:

import time
import numpy as np
freq = spi.xfer([0x28 << 1 | 0x01, 0x00]) # read the frequency register
addr = [0x00] * 10 # number of bytes to read plus 1
addr[0] = 0x08 << 1 | 0x01
data = np.zeros((int(freq) * 2, 3))
start_time = time.time()
delta_time = 1 / freq
cur_time = start_time - delta_time
count = 0
while count < len(data):
    if ((time.time() - delta_time) > cur_time):
        cur_time = cur_time + delta_time
        data[count] = spi.xfer(addr)[1:]
        count = count + 1

Using this snippet I get consistent data from the device at 4 KHz which is no surprise since it's forced to do it. I can't say that I grabbed all data points because of the timing, although I should have. Using xfer and xfer2 produce the same results. How do I properly poll the status register to read the data when it becomes available?

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum