Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SoapyXTRX RX stream problem #60

Open
rmcleitao opened this issue Jul 2, 2019 · 9 comments
Open

SoapyXTRX RX stream problem #60

rmcleitao opened this issue Jul 2, 2019 · 9 comments

Comments

@rmcleitao
Copy link

rmcleitao commented Jul 2, 2019

I'm using SoapySDR to configure and capture data and I'm getting something strange in the data stream.

The first 3 samples (3x I+Q) from the readStream() come with 0+j0 but this only happens in the first capture. Ignoring this first capture and making the FFT (and FFT shift) of the data I get the following spectrum:

Without a signal:
xtrx_soapy_problem

With a DVB-T signal:
xtrx_soapy_problem_with_signal

I tried with three different wrappers: C, Go and Python. I also captured the raw data and processed in Matlab/Octave with the same results.

If I use a LimeSDR with the same code everything is fine.

Here is the code used in Python:

import SoapySDR
from SoapySDR import * #SOAPY_SDR_ constants
import numpy as np
import time
import os


import numpy as no
import matplotlib.pyplot as plt
import scipy.fftpack
from numpy import array

#=======================
chan=0
ant='LNAL'
gain=15
numSamps = 4096
burstSize = 512
#=======================

#enumerate devices
results = SoapySDR.Device.enumerate()
for result in results: print(result)

#create device instance
#args can be user defined or from the enumeration result
args = dict(driver="xtrx")
sdr = SoapySDR.Device(args)

#query device info
print (sdr.listAntennas(SOAPY_SDR_RX, chan))

print "============================================="

sdr.setSampleRate(SOAPY_SDR_RX, chan, 40e6)
print("Actual Rx Rate %f Msps"%(sdr.getSampleRate(SOAPY_SDR_RX, chan)/1e6))

sdr.setFrequency(SOAPY_SDR_RX, chan, 800e6)
print("Actual Rx Freq %f MHz"%(sdr.getFrequency(SOAPY_SDR_RX, chan)/1e6))

sdr.setAntenna(SOAPY_SDR_RX,chan,ant)
print("Antenna on Channel %i is %s"%(chan,sdr.getAntenna(SOAPY_SDR_RX,chan)))

sdr.setGain(SOAPY_SDR_RX,chan,gain)
print("Actual Rx Gain %f "%(sdr.getGain(SOAPY_SDR_RX, chan)))

sdr.setBandwidth(SOAPY_SDR_RX, chan, 40e6)
print("Actual Rx BW MHz %f "%(sdr.getBandwidth(SOAPY_SDR_RX, chan)/1e6))

print "============================================="

#create rx stream
rxStream = sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CF32, [chan])

#let things settle
time.sleep(1)

#start streaming
sdr.activateStream(rxStream, 0, 0, numSamps)

#create a re-usable buffer for rx samples
rxBuff = np.array([0]*burstSize, np.complex64)

#receive some samples (first samples have the zero)
sr = sdr.readStream(rxStream, [rxBuff], 512)
print rxBuff
#second capture
sr = sdr.readStream(rxStream, [rxBuff], 512)


#cleanup streams
print("Cleanup streams")
sdr.deactivateStream(rxStream) #stop streaming
sdr.closeStream(rxStream)

#print data
print rxBuff
n = len(rxBuff)
print n

#FFT
y = scipy.fftpack.fft(rxBuff)
yf = np.abs(scipy.fftpack.fftshift(y))
yf = 10*np.log10(yf)
xf = np.linspace(0.0, 1.0, n/2)

#plot FFT
fig, ax = plt.subplots()
ax.plot(yf)
plt.show()
@sergforce
Copy link
Contributor

sergforce commented Jul 2, 2019 via email

@rmcleitao
Copy link
Author

That's one of the issues. The spectrum that I'm showing is from the second capture, maybe the issues are related. Can you test the script and see if you have the same problem?

I forgot to mention that the example from libxtrx/examples/xtrx_fft/ and the osmocom block for GNU Radio are working fine.

@yahoo2016
Copy link

I noticed your sampling rate was 40MHz, have you tried lower sampling rates?
I'm having issues with higher sampling rates. There are glitches at higher rates depending on CPU types.

@rmcleitao
Copy link
Author

rmcleitao commented Jul 3, 2019

I'm able to go higher than 40 Msps with other implementations (GNU Radio, gqrx, etc) and my workstation as an AMD Threadripper 1950X. But just to make sure I just ran the script with 10 Msps and the result is the same.
Either it's a bug in SoapyXTRX or some configuration that I'm using (or some configuration is missing).

@rmcleitao
Copy link
Author

rmcleitao commented Jul 16, 2019

So after finding this issue I checked the repositories and saw that I didn't had the latest versions.

After updating everything the data stream seems right (the first samples are no longer zeros) but then I found out a problem with the gain function. And this issue might be the same as this one myriadrf/libxtrx#6

This happens in that python script and in C.
I edited the test_xtrx_soapy.c to add the setGain function and this error is happening (it's the same in python):

[FATAL] SoapyXTRX::setGain(, 0, --, 15 dB)

Specifying one of the three available gains (LNA, TIA or PGA) shows the same error:

[FATAL] SoapyXTRX::setGain(, 0, LNA, 15 dB)

Even with this errors the gain seems to change (not for all configurations) but not to the value that we what.

It's complicated to validate the data collected from the stream (my original issue) if we can't control the gain.

Edit: I will try to take a look at the SoapyXTRX source code.

@bkerler
Copy link

bkerler commented Jul 27, 2019

Using the setGain function (with no type name given), it will set only LNA gain.
The fatal message is hardcoded, but does even appear if it works fine (there is no check in the source code for a failure), as you can see here: https://github.com/xtrx-sdr/libxtrx/blob/4f1eb7b5f77c90bc8d0db2a17fe338372e3d4277/soapy/SoapyXTRX.cpp#L287. What do you mean by the gain doesn't change to right "value". Can you give examples for expected values or what gain you try to change ? I couldn't see any issue on that in the source code, that's why I ask.

@rmcleitao
Copy link
Author

For exemple with this code in python:

gain = 20
chan = 0
print("Set Rx Gain: %f "%(gain))
sdr.setGain(SOAPY_SDR_RX, chan, "LNA", gain)
sdr.setGain(SOAPY_SDR_RX, chan, "TIA", 0)
sdr.setGain(SOAPY_SDR_RX, chan, "PGA", 0)
print("Actual Rx LNA Gain %f "%(sdr.getGain(SOAPY_SDR_RX, chan, "LNA")))
print("Actual Rx TIA Gain %f "%(sdr.getGain(SOAPY_SDR_RX, chan, "TIA")))
print("Actual Rx PGA Gain %f "%(sdr.getGain(SOAPY_SDR_RX, chan, "PGA")))
print("Actual Rx Gain %f "%(sdr.getGain(SOAPY_SDR_RX, chan)))

I get this output:

Set Rx Gain: 20.000000 
[FATAL] SoapyXTRX::setGain(, 0, LNA, 20 dB)
09:28:58.474995 INFO:   [LMSF] PCI:/dev/xtrx0: Set gain 20.0 to 0 on 1 channel
09:28:58.475034 INFO:   [LSM7] PCI:/dev/xtrx0: RFE: set_lna(10 -> 12) => 7
[FATAL] SoapyXTRX::setGain(, 0, TIA, 0 dB)
09:28:58.475095 INFO:   [LMSF] PCI:/dev/xtrx0: Set gain 0.0 to 1 on 1 channel
[FATAL] SoapyXTRX::setGain(, 0, PGA, 0 dB)
09:28:58.475116 INFO:   [LMSF] PCI:/dev/xtrx0: Set gain 0.0 to 2 on 1 channel
09:28:58.475127 INFO:   [LSM7] PCI:/dev/xtrx0: RBB: set_pga(12) rcc_ctl -> 23, c_ctl -> 2
Actual Rx LNA Gain 18.000000 
Actual Rx TIA Gain 0.000000 
Actual Rx PGA Gain 0.000000 
Actual Rx Gain 30.000000 

The TIA and PGA gains are correct but the LNA gain is 18 dB instead of 20 dB and the sdr.getGain(SOAPY_SDR_RX, chan) function returns 30 dB.

@bkerler
Copy link

bkerler commented Jul 30, 2019

I reviewed the code. The issue seems to be in the LMS7002M_rfe_set_lna function and looks like expected behaviour. The max gain is 30 and the gain value is substracted by the given value. There is no value for 20, so it takes the next value, which is 18. https://github.com/myriadrf/LMS7002M-driver/blob/90cd8526ac2005ff2dd52e9b3c818b45497f439e/src/LMS7002M_rfe.c#L107-L108

However the Rx Gain is being calculated by adding all gains. Having a look at the implementation: https://github.com/pothosware/SoapySDR/blob/fe8dfd1879a8512aa305045ef1e6657a5a33f3b9/lib/Device.cpp#L313-L314

The issue seems to be this line :
https://github.com/xtrx-sdr/libxtrx/blob/4f1eb7b5f77c90bc8d0db2a17fe338372e3d4277/soapy/SoapyXTRX.cpp#L365
As the minimum is being substracted (here -12). As 18-(-12)=30, the negative value seems to cause the issue. Thus setting the minimum at https://github.com/xtrx-sdr/libxtrx/blob/4f1eb7b5f77c90bc8d0db2a17fe338372e3d4277/soapy/SoapyXTRX.cpp#L365 to 0 instead of -12 does fix that issue.

@rmcleitao
Copy link
Author

You are right, I was convinced that the gain was in 1 dB steps, but checking the datasheet of the LMS7002M it says:

RXLNA gain control consists of 30 dB with 1 dB steps at high gain
settings and 3 dB steps at low gain settings
https://limemicro.com/app/uploads/2017/07/LMS7002M-Data-Sheet-v3.1r00.pdf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants