How to transmit bursts with Soapy SDR

Hi all,

I have a Lime in TX only on channel 0 (so no RX). I want to transmit some signals of 5ms at different intervals. I’m transmitting at 5MS/s, so I created a buffer of 5MS/s x 5ms = 25k samples.

  1. Am I right in thinking such a buffer will correspond to a 5ms signal?
  2. Should I send straight the whole buffer, or should I try to divide it in smaller chunks?
  3. Once the whole buffer is sent, will the transmission end, or should I send some empty signal?
  4. Should I use some specific tags if I need to send bursts
  5. The call to SoapySDRDevice_writeStream usually takes less than 0.2ms, but sometimes takes 45ms (eg I see it takes 0.2ms 10 times in a row then it jumps to 25ms then 45ms)? Does it mean the TX buffer is filled too fast? If that were the case I would expect the call to SoapySDRDevice_writeStream to take longer over time, without huge differences.

Maybe @joshblum can bring his expertise on Soapy. Thanks.

Am I right in thinking such a buffer will correspond to a 5ms signal?

seems right

Should I send straight the whole buffer, or should I try to divide it in smaller chunks?

Its probably easiest to submit the entire burst to the API at once. If the burst is too large for the buffer in the Limesuite driver, then you may have to split it up anyway. If you take a look at the setupStream source there should be a way to set the fifo size in the driver.

Once the whole buffer is sent, will the transmission end, or should I send some empty signal?

The FPGA should start sending 0’s into the LMS7’s DIQ bus for transmit. No need to transmit zeros.

Should I use some specific tags if I need to send bursts

Tags or flags? Use the SOAPY_SDR_END_BURST on the last call to writeStream of a burst. That tells the driver to flush everything out rather than hold onto it if a UBS transfer was only partially filled.

The call to SoapySDRDevice_writeStream usually takes less than 0.2ms, but sometimes takes 45ms (eg I see it takes 0.2ms 10 times in a row then it jumps to 25ms then 45ms)? Does it mean the TX buffer is filled too fast? If that were the case I would expect the call to SoapySDRDevice_writeStream to take longer over time, without huge differences.

It way have run out of fifo space and your transmit scheduled time combined with the timeout is allowing the call to block and wait for space as it moves more of your sample stream into the driver’s buffering. So you have options, you can change fifo size through setup stream, you can block, you can use a small timeout and do other processing in the thread before feeding writeStream the rest, etc. Be creative :slight_smile:

Thanks Josh

Here is what I found empirically to answer my questions. This may help others as there doesn’t seem to be any thorough code example to send and receive:

  1. You can send the entire buffer straight, but it seems smaller buffer get transmitted faster (eg a 275000 samples buffer seems to start being transmitted around 200µs later than a 10 times smaller buffer)

  2. The transmission indeed stops once the whole buffer is sent (there used to be a bug in a previous version that required you to send 0s but it’s been fixed). Also just after setting the TX (not even starting the TX stream I think), you’ll see lots of noise at the corresponding central frequency. That noise will decrease dramatically once you’re done sending your 1st signal. Maybe 0s should also be sent automatically?

  1. Concerning the timeouts, my test was wrong indeed as it was filling up the buffers too fast.

In an attempt to transmit as fast as possible after receiving a signal, I played with latency and bufferLength (see Streaming.cpp).

Setting the latency to 1 (meaning max throughput, high latency) or the buffer length to something too big seems to add some latency. Setting latency to 0 and/or the buffer length to something smaller for both RX and TX helps.

The SOAPY_SDR_HAS_TIME flag can be used with writeStream to send a signal in the future at a specific timestamp. That’s the best way to avoid latency, but of course you need to already know the signal to send. It’s also possible to add several messages to be sent at different times next to each other (I think previously there was a bug that made everything be sent at the same time).

@andrewback @Zack I’ve noticed something strange though: it seems that changing the sampling rate of the TX impacts the RX and vice versa, depending on which one is setup last. Is it not possible to use different sampling rates for RX and TX?

Eg if I setup RX and then TX to both use 55MS/s, and I receive blocks of 1360 samples, the timestamp between received blocks is 12,364 as expected. If I setup RX to use 55MS/s and then TX to use 5MS/s, while still receiving blocks of 1360, the timestamp between received blocks is now 136,000, corresponding to RX at 5MS/s. Is this because