Application for using the 2 RX channels simultaneously

I want to use the 2 RX channels simultaneously for spectral display and Recording.
The 2 signals are seperate and have a center frequency at 70 MHz.
I tried to use the Osmocom Source but cannot get it working for 2 channels.
Is there an application that uses the LMS API or Soapy API that does the job?
Thank you in advance.


I am not sure if this is too late, or what you are looking for, but I have a portion of code I use for phase difference calculation between a signal received using RX channel A and B using SoapySDR. Still I must warn you that I am currently having a problem with the phase different not being the same between one execution and the other, but at least is illustrative :wink:

SoapySDR::Device *device(nullptr);
device = SoapySDR::Device::make();

device->setBandwidth(SOAPY_SDR_RX, 0, 20e6);
device->setBandwidth(SOAPY_SDR_RX, 1, 20e6);

device->setSampleRate(SOAPY_SDR_RX, 0, sampleRate);
device->setSampleRate(SOAPY_SDR_RX, 1, sampleRate);

std::string format = SOAPY_SDR_CF32;//device->getNativeStreamFormat(SOAPY_SDR_RX, 0, fullScale);
const size_t elemSize = SoapySDR::formatToSize(format);
std::vector<size_t> channel(2);
channel[0] = 0;
channel[1] = 1;
auto rxStream = device->setupStream(SOAPY_SDR_RX, format, channel);

device->setFrequency(SOAPY_SDR_RX, 0, frequency);
device->setAntenna(SOAPY_SDR_RX, 0, "LNAL");
device->setGain(SOAPY_SDR_RX, 0, gain);

device->setFrequency(SOAPY_SDR_RX, 1, frequency);
device->setAntenna(SOAPY_SDR_RX, 1, "LNAL");
device->setGain(SOAPY_SDR_RX, 1, gain);

cout << "Rx 0 Frequency " << device->getFrequency(SOAPY_SDR_RX, 0)*1e-6 << " MHz" << endl;
cout << "Rx 1 Frequency " << device->getFrequency(SOAPY_SDR_RX, 1)*1e-6 << " MHz" << endl;

cout << "Rx 0 Antenna " << device->getAntenna(SOAPY_SDR_RX,0) << endl;
cout << "Rx 1 Antenna " << device->getAntenna(SOAPY_SDR_RX,1) << endl;

cout << "Rx 0 Sampling Rate " << device->getSampleRate(SOAPY_SDR_RX,0)*1e-6 << " Ms" << endl;
cout << "Rx 1 Sampling Rate " << device->getSampleRate(SOAPY_SDR_RX,1)*1e-6 << " Ms" << endl;

cout << "Rx 0 Bw " << device->getBandwidth(SOAPY_SDR_RX,0)*1e-6 << " MHz" << endl;
cout << "Rx 1 Bw " << device->getBandwidth(SOAPY_SDR_RX,1)*1e-6 << " MHz" << endl;

cout << "Clock rate: " << device->getMasterClockRate()*1e-6 << " MHz" << endl;

fftwf_complex *in0 = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * receiveWindow);
fftwf_complex *in1 = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * receiveWindow);

std::vector<void *> rxBuffs(2);
rxBuffs[0] = in0;
rxBuffs[1] = in1;


    int flags(0);
    long long timeNs(0);

    int rxRet = device->readStream(rxStream,, receiveWindow, flags, timeNs);

After this, rxBuffs[0] contains the samples for channel A and rxBuffs[1] the samples for channel B.


1 Like

I have been using GNURadio and UHD to interface to the LimeSDR and have also had issues with the phase between receivers being inconsistent between tests. I’m sorry to hear you have the same issues, but I’m interested in your code and thanks for posting it.

I might be wrong, but I actually think that random initial phase offset between two RX channels is quite normal and expected thing. Such offset should stay constant during operation, though.

I think that one should implement simple proof of concept in GNU Radio to make things clear, such as forcing TDD mode, transmitting some QPSK signal via one TX channel and receiving it via both RX channels at the same frequency. If everything works as expected, we should be able to see non-rotating QPSK constellation of signals obtained from both RX channels (while initial constellation angle may vary for different program runs). Only thing which is non-trivial as it comes to creating such flowgraph in GNU Radio is forcing TDD mode (so that TX and RX chains will be driven by the same LO). @IgnasJ, any ideas how to do this in a simple way?

I think you might be considering a different situation @ccsh. I believe you might be thinking of the case where both RX channels are receiving the same signal on two antennas through an open air channel. In this case, yes, your phase offset between the 2 RX will vary randomly. But for both @will_mysky and @Aridane, the situations they are describing are much more predictable conditions - described here and here, respectively. In the case of a direct connection through a splitter or a coupler, like described in those links, the phase offset between the two channels should not vary, seeing as they are running from the same PLL. In essence, it is very similar to how you would measure the properties of a device using a VNA. But despite this, something is not as it should be or something is just not clear yet, seeing as the LimeSDR currently doesn’t work in that way.

I had this same issue some time ago, but haven’t had time to get back to trying to resolve it, until now. It would be really good to get some feedback from the LimeSDR design team on it, as it doesn’t seem to simply be a matter of turning TDD mode on or switching off the DC corrector. The problem I had was able to be circumvented by using the loopback as my second channel, seeing as I just needed a phase measurement - but that option is much, much slower than using the two channels together, as switching the loopback on and off is not a speedy operation.

No, I actually thought about the very same configuration, i.e. wire connection between TX and both RX channels (via splitter or so). I just think that this initial phase offset between both RX channels (different for every program run) may be a typical case, and it will happen for other SDRs like USRP B210. That being said, I am not 100% sure about this, as I have no access to other device to confirm. But what absolutely should not vary is the phase offset between both RX channels during operation.

I can confirm that the USRP B210 does not present this behaviour between runs. Actually, the issues with the LimeSDR have arisen because I was migrating the code we used for a B210 with UHD to a LimeSDR with Soapy, and as seen here we have tested it with both soapy and LimeSuite API.

DOA on Lime, with known issues …
Must be some of members on topic here.

I don’t think this is LimeSDR hardware issue, it just means that detecting and compensating initial phase offset between two RX channels is up to your application, as Collus wrote here. You have all means to do that, (i.e. you can transmit any signal you want after program run, which can be “heared” by both RX channels and thus allow detecting this offset). Of course, I suppose that it could be done automatically in SDR driver and it would be very nice feature, but if it’s not implemented it does not mean that device is not MIMO-capable anymore, it just means that such feature needs to be implemented in user’s software.

I agree, phase compensation is a good suggestion, and it might solve someone’s issues for their particular application. MIMO also works fine, no denying that. Sadly, the problem I am having, and I think some of the above commenters are also having, is a lack of phase coherence, not a lack of MIMO. If you are compensating out the initial phase offset - how will you ever detect a variation in phase between two separate runs? You simply cannot. Sure, you could suggest leaving the LimeSDR on while the event that will cause a phase change occurs, but the event may not be something you have control over.

The bottom line is, this initial phase coherence is something that works in other SDRs and it looks like it should work in the LimeSDR, based on the datasheet - but it currently doesn’t. We just want to find out why and if it is something that can be changed, but phase compensation alone won’t resolve this issue.

Ok, finally I got the problem, I suppose the information that you want to detect events occurring so rare is the key :wink: In that case you are right, the only way to detect them is to leave LimeSDR working all the time after compensating initial phase offset. On the other hand, Collus also wrote that

So I got another question: is that kind of phase offset variation (fraction of degree) really crucial for your application? Or maybe you observe much larger variations?

Yes, I think you’re understanding my issue now :slight_smile: in response to your question, I’m observing much larger variations with the LimeSDR. Variations of completely random, between -pi and pi. Which is exactly the problem - unlike how the AD9361 works, like described by @Collus, the LimeSDR does not seem to have a fixed phase offset between RX channels A and B. It could simply be part of how I’ve set things up with SoapySDR, but it seems others are having this issue also.

I would just like to remark that the variations I am observing are also of great magnitude, like @astancombe, between -pi and pi.

I understand phase coherent dual receive is indeed possible, any issues are likely down to either the driver stack or how it’s being used, and @zack is currently looking into this.


Really looking forward to that :slight_smile:
Please ask him to share that with all of us ASAP

Me too. @zack please share a demo of how to achieve this.

Thank you, guys!

Any update in this topic? @zack @andrewback

1 Like

I’m eagerly awaiting this as well. I have a radio astronomy interferometer application that currently doesn’t work with LimeSDR, due to an apparent lack of channel-to-channel phase coherence. Which is very weird when you consider the shared-LO arrangement. So the “issue” must be somewhere in the digital domain–the ADCs not being simultaneously clocked (and lots of random jitter in there), or some digital compensation in the chip or FPGA producing random phase variations that are uncorrelated, operate at small time-scales, and are large in magnitude.


any update??

@zack @andrewback , it seems to be quite important for a lot of users (mainly because it’s an important feature of LMS7002). Is it possible to have any news?

For me, it’s enough to know if it could be solved or not.
Thank you and regards