xtrx-sdr / images

Pre-built XTRX packages and firmware images
https://www.crowdsupply.com/fairwaves/xtrx
44 stars 27 forks source link

SoapyXTRX RX stream problem #60

Open rmcleitao opened 5 years ago

rmcleitao commented 5 years ago

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 commented 5 years ago

So the issue is fist 3 samples right after stream activation are zero, right?

On Tue, Jul 2, 2019, 7:46 AM rmcleitao notifications@github.com wrote:

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: [image: xtrx_soapy_problem] https://user-images.githubusercontent.com/52451242/60509934-0f8f0680-9cc6-11e9-85a3-ceaf2712a206.png

With a DVB-T signal: [image: xtrx_soapy_problem_with_signal] https://user-images.githubusercontent.com/52451242/60509940-1289f700-9cc6-11e9-8775-b1c700c23004.png

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 * #SOAPYSDR 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()

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/xtrx-sdr/images/issues/60?email_source=notifications&email_token=AASAQW2ARRRQ72YZWT4UZWDP5M52DA5CNFSM4H425532YY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4G43TJXQ, or mute the thread https://github.com/notifications/unsubscribe-auth/AASAQW55DHWVCK7FKYE3YRLP5M52DANCNFSM4H42553Q .

rmcleitao commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 https://github.com/xtrx-sdr/libxtrx/issues/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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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