BladeRF xA4/SoapySDR: not receiving full number of samples
Posted: Tue Oct 12, 2021 5:25 pm
Hi - I am attempting to receive samples from both RX channels simultaneously from a BladeRF 2.0 Micro xA4 with SoapySDR. My device firmware version is 2.4, and I'm running the most recent commit of libbladerf. The single-channel Python code below works very well with no problems:
I have verified that the data this collects looks good. I then attempted to modify this code to make it work with both RX channels:
When I run this, I can only ever get 254 samples in a single transfer, and the rest of the values in the numpy array remain zero. I can verify in the BladeRF SoapySDR module that the USB transfer only ever returns 254 bytes. The transfer happens in bladeRF_SoapySDR::read_stream on the following lines:
In the last line, numElems is updated from the correct desired value of 4096 to 254. Additionally, half of the time, read_stream will fail with an RX overflow error. What's going on here? Is my multi-channel code incorrect in some way? Is something going wrong with my device?
Code: Select all
import SoapySDR
from SoapySDR import *
import numpy as np
import time
fsamp = 8e6
fcenter = 107.9e6
nsamp = 2**20
# Apparently it takes AGC a while to settle in?
throwaway_time = 0.004
args = dict(driver="bladerf")
sdr = SoapySDR.Device(args)
# Setup device
sdr.setSampleRate(SOAPY_SDR_RX, 0, fsamp)
sdr.setFrequency(SOAPY_SDR_RX, 0, fcenter)
sdr.setGainMode(SOAPY_SDR_RX, 0, True)
# Make stream and buffers
rx = sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CF32, [0])
mtu = int(sdr.getStreamMTU(rx))
samps = np.array([0]*nsamp, np.complex64)
xfer_buff = np.array([0]*mtu, np.complex64)
sdr.activateStream(rx)
throwaway_chunks = int(throwaway_time*fsamp/mtu+1)
for idx in range(int(nsamp/mtu+1)+throwaway_chunks):
ret = sdr.readStream(rx, [xfer_buff], mtu)
if idx < throwaway_chunks:
continue
i = idx-throwaway_chunks
if i == int(nsamp/mtu):
samps[i*mtu:] = xfer_buff[:nsamp%mtu]
else:
samps[i*mtu:(i+1)*mtu] = xfer_buff
sdr.deactivateStream(rx)
Code: Select all
import SoapySDR
from SoapySDR import *
import numpy as np
import time
fsamp = 8e6
fcenter = 107.9e6
nsamp = 2**20
# Apparently it takes AGC a while to settle in?
throwaway_time = 0.1
args = dict(driver="bladerf")
sdr = SoapySDR.Device(args)
# Setup device
sdr.setSampleRate(SOAPY_SDR_RX, 0, fsamp)
sdr.setSampleRate(SOAPY_SDR_RX, 1, fsamp)
sdr.setFrequency(SOAPY_SDR_RX, 0, fcenter)
sdr.setFrequency(SOAPY_SDR_RX, 1, fcenter)
sdr.setGainMode(SOAPY_SDR_RX, 0, True)
sdr.setGainMode(SOAPY_SDR_RX, 1, True)
# Make stream and buffers
rx = sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CF32, [0, 1])
mtu = int(sdr.getStreamMTU(rx))
samps = np.zeros((nsamp,2), dtype=np.complex64)
buff0 = np.array([0]*mtu, np.complex64)
buff1 = np.array([0]*mtu, np.complex64)
sdr.activateStream(rx)
throwaway_chunks = int(throwaway_time*fsamp/mtu+1)
for idx in range(int(nsamp/mtu+1)+throwaway_chunks):
ret = sdr.readStream(rx, [buff0, buff1], mtu)
print(ret)
if idx < throwaway_chunks:
continue
i = idx-throwaway_chunks
if i == int(nsamp/mtu):
samps[i*mtu:,0] = buff0[:nsamp%mtu]
samps[i*mtu:,1] = buff1[:nsamp%mtu]
else:
samps[i*mtu:(i+1)*mtu,0] = buff0
samps[i*mtu:(i+1)*mtu,1] = buff1
sdr.deactivateStream(rx)
Code: Select all
//recv the rx samples
const long timeoutMs = std::max(_rxMinTimeoutMs, timeoutUs/1000);
int ret = bladerf_sync_rx(_dev, samples, numElems*_rxChans.size(), &md, timeoutMs);
if (ret == BLADERF_ERR_TIMEOUT) return SOAPY_SDR_TIMEOUT;
if (ret == BLADERF_ERR_TIME_PAST) return SOAPY_SDR_TIME_ERROR;
if (ret != 0)
{
//any error when this is a finite burst causes the command to be removed
if (cmd.numElems > 0) _rxCmds.pop();
SoapySDR::logf(SOAPY_SDR_ERROR, "bladerf_sync_rx() returned %s", _err2str(ret).c_str());
return SOAPY_SDR_STREAM_ERROR;
}
//actual count is number of samples in total all channels
numElems = md.actual_count / _rxChans.size();]