Post Go back to editing

IIO: RX buffer is chopped and filled with zeros. RX/TX synchronization.


First, thank you for Pluto! I think it's great, and it's a very affordable way to learn SDR. 

After some initial tests with Gnu-Radio, I went for IIO and tried to run a simple test of TX + RX with digital loopback enabled. I would like to send a TX  buffer and receive it into RX buffer. Maybe in the end I would like to get a simple VNA scenario to work. I have some issues I can't resolve. So first I will write my questions and then I will explain the details.

- How should I call IIO push/refill functions from a single thread (or I shouldn't do that)? My RX buffer gets "chopped" and filled with zeros.

- Can I synchronize TX/RX in such a way that I will know what is a delay between buffers (in terms of number of samples)?

The scenario I run is:

1. Open RX and TX on the same LO frequency with the same sampling rate.

2. Create channels/buffers needed. 

3. Enable digital loopback.

4. Prepare a sinewave using inverse fft.

5. Push TX buffer, refill RX buffer in a loop. Currently 20 iterations. 

6. Catch 10th iteration RX buffer into an array, so I can analyze it later. The idea is that it should contain TX buffer, OR TX buffer shifted by some constant offset + beginning of next TX buffer. Catching 10th iteration should neglect any effects of first/last buffers.

7. Print TX and 10th RX buffer for comparison.

(Additionally I calculate amplitude+phase of both TX and RX).

Code used:

Link it with v3 FFTW and IIO, obviously.

What I get:

As you may see in the file, the RX is offset by around 10k samples. RX contains samples starting from 10k upto 32k of TX and then 10k zeros. I didn't expect zeros there! Any ideas why is that?

Should I call push/refill from two threads for it to work? I thought that there were some internal buffers that are swapped with the buffer I push/refill so that would be short call. I know that refill/push calls may block, but is that the issue here?

Another thing: Can I synchronize TX/RX so I have a constant phase shift? It changes every time I run the code.

NOTE: In the code I use 1/4th of RX buffer to calculate amplitude/phase to reduce the "zeros" effect on those, but it's not a solution of the root cause.

  • The main issue here is the sample rate you are selecting. You cannot set the sample rate below 2.08 MHz without loading an FIR. The radio is probably running at 30 or 60 MHz, which will cause underflows (starvation) and overflows (dropped data) on the TX and RX respectively. This is where the zeros come from.  We have a special functions for loading filters.  The easiest is here:

    In general the latency between buffers will be fixed for a given simulation if you can keep up with the data streaming in. Otherwise you will have dropped some data on the floor and have no idea how much was lost. To help with things on the TX side I would recommend using cyclic buffers. That way you don't have to keep passing new data into the TX buffers.

    Also know that you will have precision loss in your data since the part and HDL only use 12bits. Please this page about how data is cast inside the FPGA:


  • Buffer push and fill are both blocking.

    Either you create two processes. Or you pre-push some tx buffers, to fill the pipeline. Then create the rx buffer (since it's filling them once created) and then you enter your loop. 


  • Hello Michael,

    I knew that push and refill are both blocking. I assumed that when I call refill, it uses data it already gathered in some internal buffer, and just returns that buffer in a short time. I assumed that only if I called the refill again, that would block until I got enough samples. I see that I didn't understand the idea fully.

    The information that the buffer is being filled right after it was created is an important one. It may be a reason of my phase shift jumping around - I create a RX buffer somewhere in the code without care.

    But even if I use two processes, or pre-fill the TX pipeline, I don't see a good way to more or less synchronize TX and RX. If I understand correctly, whatever I do at the API level is several (not sure how many) buffers away from the AD936X digital interface. 

    It would be nice to have IIO parameter to "hold" buffers on TX and "refilling" of RX buffers if set. That way I could prefill TX without pushing that out, then ask for RX buffer, and kick the parameter to start both RX and TX at the same time. I guess that would need to be done on hdl level?

    I will start with pre-filling TX as you suggested. Any ideas how many buffers should I push on start?

    Thank you a lot for your help,


  • Its not really how many buffers, its more about the data. The max buffer is 2^24 by default, which should keep the DMA busy for awhile.


Reply Children
No Data