BladeRF xA4/SoapySDR: not receiving full number of samples

Discussions related to embedded firmware, driver, and user mode application software development
Post Reply
AlexFW
Posts: 1
Joined: Tue Oct 12, 2021 5:09 pm

BladeRF xA4/SoapySDR: not receiving full number of samples

Post by AlexFW »

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:

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)
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:

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)
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:

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();]
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?
Post Reply