bladerf: Added device caching, this enables full-duplex operation.

This commit is contained in:
Daniel Gröber 2013-10-19 18:00:38 +02:00 committed by Dimitri Stolnikov
parent 7394251bd0
commit 54f2e08dd7
5 changed files with 127 additions and 58 deletions

View File

@ -37,4 +37,3 @@ set(bladerf_srcs
########################################################################
list(APPEND gr_osmosdr_srcs ${bladerf_srcs})
list(APPEND gr_osmosdr_libs ${LIBBLADERF_LIBRARIES})

View File

@ -36,6 +36,7 @@
#include <boost/lexical_cast.hpp>
#include <boost/assign.hpp>
#include <boost/foreach.hpp>
#include <boost/shared_ptr.hpp>
#include "bladerf_common.h"
@ -43,6 +44,9 @@
using namespace boost::assign;
boost::mutex bladerf_common::_devs_mutex;
std::list<boost::weak_ptr<struct bladerf> > bladerf_common::_devs;
bladerf_common::bladerf_common() :
_is_running(false)
{
@ -80,6 +84,68 @@ bladerf_common::~bladerf_common()
delete _fifo;
}
bladerf_sptr bladerf_common:: get_cached_device(struct bladerf_devinfo devinfo)
{
/* Lock to _devs must be aquired by caller */
BOOST_FOREACH( boost::weak_ptr<struct bladerf> dev, _devs )
{
struct bladerf_devinfo other_devinfo;
int rv = bladerf_get_devinfo(bladerf_sptr(dev).get(), &other_devinfo);
if (rv < 0)
throw std::runtime_error(std::string(__FUNCTION__) + " " +
"Failed to get devinfo for cached device.");
if (bladerf_devinfo_matches(&devinfo, &other_devinfo)) {
return bladerf_sptr(dev);
}
}
return bladerf_sptr();
}
void bladerf_common::close(void* dev)
{
boost::unique_lock<boost::mutex> lock(_devs_mutex);
std::list<boost::weak_ptr<struct bladerf> >::iterator it;
for (it = _devs.begin(); it != _devs.end(); ++it)
if ( (*it).expired() == 0 )
_devs.erase(it);
bladerf_close((struct bladerf *)dev);
}
bladerf_sptr bladerf_common::open(const std::string &device_name)
{
int rv;
struct bladerf *raw_dev;
struct bladerf_devinfo devinfo;
boost::unique_lock<boost::mutex> lock(_devs_mutex);
rv = bladerf_get_devinfo_from_str(device_name.c_str(), &devinfo);
if (rv < 0)
throw std::runtime_error(std::string(__FUNCTION__) + " " +
"Failed to get devinfo for '" + device_name + "'");
bladerf_sptr cached_dev = get_cached_device(devinfo);
if (cached_dev)
return cached_dev;
rv = bladerf_open_with_devinfo(&raw_dev, &devinfo);
if (rv < 0)
throw std::runtime_error(std::string(__FUNCTION__) + " " +
"Failed to open device for '" + device_name + "'");
bladerf_sptr dev = bladerf_sptr(raw_dev, bladerf_common::close);
_devs.push_back(boost::weak_ptr<struct bladerf>(dev));
return dev;
}
osmosdr::freq_range_t bladerf_common::freq_range()
{
/* assuming the same for RX & TX */

View File

@ -49,6 +49,8 @@
#define BLADERF_SAMPLE_FIFO_MIN_SIZE (3 * BLADERF_SAMPLE_BLOCK_SIZE)
typedef boost::shared_ptr<struct bladerf> bladerf_sptr;
class bladerf_common
{
public:
@ -56,6 +58,8 @@ public:
virtual ~bladerf_common();
protected:
bladerf_sptr open(const std::string &device_name);
osmosdr::freq_range_t freq_range();
osmosdr::meta_range_t sample_rates();
osmosdr::freq_range_t filter_bandwidths();
@ -65,7 +69,7 @@ protected:
bool is_running();
void set_running(bool is_running);
bladerf *_dev;
bladerf_sptr _dev;
void **_buffers;
struct bladerf_stream *_stream;
@ -83,6 +87,12 @@ protected:
private:
bool _is_running;
boost::shared_mutex _state_lock;
static boost::mutex _devs_mutex;
static std::list<boost::weak_ptr<struct bladerf> > _devs;
static bladerf_sptr get_cached_device(struct bladerf_devinfo devinfo);
static void close(void *dev); /* called by shared_ptr */
};
#endif

View File

@ -98,9 +98,9 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args)
device_name = boost::str(boost::format( "libusb:instance=%d" ) % device_number);
/* Open a handle to the device */
ret = bladerf_open( &_dev, device_name.c_str() );
if ( ret != 0 ) {
try {
_dev = bladerf_common::open(device_name);
} catch(...) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"failed to open bladeRF device " + device_name );
}
@ -111,7 +111,7 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args)
std::cerr << "Flashing firmware image " << fw << "..., DO NOT INTERRUPT!"
<< std::endl;
ret = bladerf_flash_firmware( _dev, fw.c_str() );
ret = bladerf_flash_firmware( _dev.get(), fw.c_str() );
if ( ret != 0 )
std::cerr << "bladerf_flash_firmware has failed with " << ret << std::endl;
else
@ -123,7 +123,7 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args)
std::string fpga = dict["fpga"];
std::cerr << "Loading FPGA bitstream " << fpga << "..." << std::endl;
ret = bladerf_load_fpga( _dev, fpga.c_str() );
ret = bladerf_load_fpga( _dev.get(), fpga.c_str() );
if ( ret != 0 && ret != 1 )
std::cerr << "bladerf_load_fpga has failed with " << ret << std::endl;
else
@ -133,19 +133,19 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args)
std::cerr << "Using nuand LLC bladeRF #" << device_number;
char serial[BLADERF_SERIAL_LENGTH];
if ( bladerf_get_serial( _dev, serial ) == 0 )
if ( bladerf_get_serial( _dev.get(), serial ) == 0 )
std::cerr << " SN " << serial;
struct bladerf_version ver;
if ( bladerf_fw_version( _dev, &ver ) == 0 )
if ( bladerf_fw_version( _dev.get(), &ver ) == 0 )
std::cerr << " FW v" << ver.major << "." << ver.minor << "." << ver.patch;
if ( bladerf_fpga_version( _dev, &ver ) == 0 )
if ( bladerf_fpga_version( _dev.get(), &ver ) == 0 )
std::cerr << " FPGA v" << ver.major << "." << ver.minor << "." << ver.patch;
std::cerr << std::endl;
if ( bladerf_is_fpga_configured( _dev ) != 1 )
if ( bladerf_is_fpga_configured( _dev.get() ) != 1 )
{
std::ostringstream oss;
oss << "The FPGA is not configured! "
@ -200,7 +200,7 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args)
}
/* Initialize the stream */
ret = bladerf_init_stream( &_stream, _dev, stream_callback,
ret = bladerf_init_stream( &_stream, _dev.get(), stream_callback,
&_buffers, _num_buffers, BLADERF_FORMAT_SC16_Q12,
_samples_per_buffer, transfers, this );
if ( ret != 0 )
@ -221,7 +221,7 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args)
_filled[i] = false;
}
ret = bladerf_enable_module( _dev, BLADERF_MODULE_TX, true );
ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_TX, true );
if ( ret != 0 )
std::cerr << "bladerf_enable_module has failed with " << ret << std::endl;
@ -246,16 +246,13 @@ bladerf_sink_c::~bladerf_sink_c ()
_thread.join();
ret = bladerf_enable_module( _dev, BLADERF_MODULE_TX, false );
ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_TX, false );
if ( ret != 0 )
std::cerr << "bladerf_enable_module has failed with " << ret << std::endl;
/* Release stream resources */
bladerf_deinit_stream(_stream);
/* Close the device */
bladerf_close( _dev );
delete[] _filled;
}
@ -407,7 +404,7 @@ double bladerf_sink_c::set_sample_rate(double rate)
/* Check to see if the sample rate is an integer */
if( (uint32_t)round(rate) == (uint32_t)rate )
{
ret = bladerf_set_sample_rate( _dev, BLADERF_MODULE_TX, (uint32_t)rate, &actual );
ret = bladerf_set_sample_rate( _dev.get(), BLADERF_MODULE_TX, (uint32_t)rate, &actual );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"has failed to set integer rate, error " +
@ -415,7 +412,7 @@ double bladerf_sink_c::set_sample_rate(double rate)
}
} else {
/* TODO: Fractional sample rate */
ret = bladerf_set_sample_rate( _dev, BLADERF_MODULE_TX, (uint32_t)rate, &actual );
ret = bladerf_set_sample_rate( _dev.get(), BLADERF_MODULE_TX, (uint32_t)rate, &actual );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"has failed to set fractional rate, error " +
@ -431,7 +428,7 @@ double bladerf_sink_c::get_sample_rate()
int ret;
unsigned int rate = 0;
ret = bladerf_get_sample_rate( _dev, BLADERF_MODULE_TX, &rate );
ret = bladerf_get_sample_rate( _dev.get(), BLADERF_MODULE_TX, &rate );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"has failed to get sample rate, error " +
@ -455,7 +452,7 @@ double bladerf_sink_c::set_center_freq( double freq, size_t chan )
freq > get_freq_range( chan ).stop() ) {
std::cerr << "Failed to set out of bound frequency: " << freq << std::endl;
} else {
ret = bladerf_set_frequency( _dev, BLADERF_MODULE_TX, (uint32_t)freq );
ret = bladerf_set_frequency( _dev.get(), BLADERF_MODULE_TX, (uint32_t)freq );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"failed to set center frequency " +
@ -473,7 +470,7 @@ double bladerf_sink_c::get_center_freq( size_t chan )
uint32_t freq;
int ret;
ret = bladerf_get_frequency( _dev, BLADERF_MODULE_TX, &freq );
ret = bladerf_get_frequency( _dev.get(), BLADERF_MODULE_TX, &freq );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"failed to get center frequency, error " +
@ -547,9 +544,9 @@ double bladerf_sink_c::set_gain( double gain, const std::string & name, size_t c
int ret = 0;
if( name == "VGA1" ) {
ret = bladerf_set_txvga1( _dev, (int)gain );
ret = bladerf_set_txvga1( _dev.get(), (int)gain );
} else if( name == "VGA2" ) {
ret = bladerf_set_txvga2( _dev, (int)gain );
ret = bladerf_set_txvga2( _dev.get(), (int)gain );
} else {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"requested to set the gain "
@ -577,9 +574,9 @@ double bladerf_sink_c::get_gain( const std::string & name, size_t chan )
int ret = 0;
if( name == "VGA1" ) {
ret = bladerf_get_txvga1( _dev, &g );
ret = bladerf_get_txvga1( _dev.get(), &g );
} else if( name == "VGA2" ) {
ret = bladerf_get_txvga2( _dev, &g );
ret = bladerf_get_txvga2( _dev.get(), &g );
} else {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"requested to get the gain "
@ -635,7 +632,7 @@ double bladerf_sink_c::set_bandwidth( double bandwidth, size_t chan )
if ( bandwidth == 0.0 ) /* bandwidth of 0 means automatic filter selection */
bandwidth = get_sample_rate() * 0.75; /* select narrower filters to prevent aliasing */
ret = bladerf_set_bandwidth( _dev, BLADERF_MODULE_TX, (uint32_t)bandwidth, &actual );
ret = bladerf_set_bandwidth( _dev.get(), BLADERF_MODULE_TX, (uint32_t)bandwidth, &actual );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"could not set bandwidth, error " +
@ -650,7 +647,7 @@ double bladerf_sink_c::get_bandwidth( size_t chan )
uint32_t bandwidth;
int ret;
ret = bladerf_get_bandwidth( _dev, BLADERF_MODULE_TX, &bandwidth );
ret = bladerf_get_bandwidth( _dev.get(), BLADERF_MODULE_TX, &bandwidth );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"could not get bandwidth, error " +

View File

@ -95,9 +95,9 @@ bladerf_source_c::bladerf_source_c (const std::string &args)
device_name = boost::str(boost::format( "libusb:instance=%d" ) % device_number);
/* Open a handle to the device */
ret = bladerf_open( &_dev, device_name.c_str() );
if ( ret != 0 ) {
try {
_dev = bladerf_common::open(device_name);
} catch(...) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"failed to open bladeRF device " + device_name );
}
@ -108,7 +108,7 @@ bladerf_source_c::bladerf_source_c (const std::string &args)
std::cerr << "Flashing firmware image " << fw << "..., DO NOT INTERRUPT!"
<< std::endl;
ret = bladerf_flash_firmware( _dev, fw.c_str() );
ret = bladerf_flash_firmware( _dev.get(), fw.c_str() );
if ( ret != 0 )
std::cerr << "bladerf_flash_firmware has failed with " << ret << std::endl;
else
@ -120,7 +120,7 @@ bladerf_source_c::bladerf_source_c (const std::string &args)
std::string fpga = dict["fpga"];
std::cerr << "Loading FPGA bitstream " << fpga << "..." << std::endl;
ret = bladerf_load_fpga( _dev, fpga.c_str() );
ret = bladerf_load_fpga( _dev.get(), fpga.c_str() );
if ( ret != 0 && ret != 1 )
std::cerr << "bladerf_load_fpga has failed with " << ret << std::endl;
else
@ -130,19 +130,19 @@ bladerf_source_c::bladerf_source_c (const std::string &args)
std::cerr << "Using nuand LLC bladeRF #" << device_number;
char serial[BLADERF_SERIAL_LENGTH];
if ( bladerf_get_serial( _dev, serial ) == 0 )
if ( bladerf_get_serial( _dev.get(), serial ) == 0 )
std::cerr << " SN " << serial;
struct bladerf_version ver;
if ( bladerf_fw_version( _dev, &ver ) == 0 )
if ( bladerf_fw_version( _dev.get(), &ver ) == 0 )
std::cerr << " FW v" << ver.major << "." << ver.minor << "." << ver.patch;
if ( bladerf_fpga_version( _dev, &ver ) == 0 )
if ( bladerf_fpga_version( _dev.get(), &ver ) == 0 )
std::cerr << " FPGA v" << ver.major << "." << ver.minor << "." << ver.patch;
std::cerr << std::endl;
if ( bladerf_is_fpga_configured( _dev ) != 1 )
if ( bladerf_is_fpga_configured( _dev.get() ) != 1 )
{
std::ostringstream oss;
oss << "The FPGA is not configured! "
@ -157,11 +157,11 @@ bladerf_source_c::bladerf_source_c (const std::string &args)
std::cerr << "Setting bladerf sampling to " << sampling << std::endl;
if( sampling == "internal") {
ret = bladerf_set_sampling( _dev, BLADERF_SAMPLING_INTERNAL );
ret = bladerf_set_sampling( _dev.get(), BLADERF_SAMPLING_INTERNAL );
if ( ret != 0 )
std::cerr << "Problem while setting sampling mode " << ret << std::endl;
} else if( sampling == "external" ) {
ret = bladerf_set_sampling( _dev, BLADERF_SAMPLING_EXTERNAL );
ret = bladerf_set_sampling( _dev.get(), BLADERF_SAMPLING_EXTERNAL );
if ( ret != 0 )
std::cerr << "Problem while setting sampling mode " << ret << std::endl;
} else {
@ -183,13 +183,13 @@ bladerf_source_c::bladerf_source_c (const std::string &args)
const size_t samp_per_buf = 1024 * 10; /* TODO: make it an argument */
/* Initialize the stream */
ret = bladerf_init_stream( &_stream, _dev, stream_callback,
ret = bladerf_init_stream( &_stream, _dev.get(), stream_callback,
&_buffers, _num_buffers, BLADERF_FORMAT_SC16_Q12,
samp_per_buf, _num_buffers, this );
if ( ret != 0 )
std::cerr << "bladerf_init_stream has failed with " << ret << std::endl;
ret = bladerf_enable_module( _dev, BLADERF_MODULE_RX, true );
ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_RX, true );
if ( ret != 0 )
std::cerr << "bladerf_enable_module has failed with " << ret << std::endl;
@ -206,15 +206,12 @@ bladerf_source_c::~bladerf_source_c ()
set_running(false);
_thread.join();
ret = bladerf_enable_module( _dev, BLADERF_MODULE_RX, false );
ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_RX, false );
if ( ret != 0 )
std::cerr << "bladerf_enable_module has failed with " << ret << std::endl;
/* Release stream resources */
bladerf_deinit_stream(_stream);
/* Close the device */
bladerf_close( _dev );
}
void *bladerf_source_c::stream_callback( struct bladerf *dev,
@ -351,7 +348,7 @@ double bladerf_source_c::set_sample_rate( double rate )
/* Check to see if the sample rate is an integer */
if( (uint32_t)round(rate) == (uint32_t)rate )
{
ret = bladerf_set_sample_rate( _dev, BLADERF_MODULE_RX, (uint32_t)rate, &actual );
ret = bladerf_set_sample_rate( _dev.get(), BLADERF_MODULE_RX, (uint32_t)rate, &actual );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"has failed to set integer rate, error " +
@ -359,7 +356,7 @@ double bladerf_source_c::set_sample_rate( double rate )
}
} else {
/* TODO: Fractional sample rate */
ret = bladerf_set_sample_rate( _dev, BLADERF_MODULE_RX, (uint32_t)rate, &actual );
ret = bladerf_set_sample_rate( _dev.get(), BLADERF_MODULE_RX, (uint32_t)rate, &actual );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"has failed to set fractional rate, error " +
@ -375,7 +372,7 @@ double bladerf_source_c::get_sample_rate()
int ret;
unsigned int rate = 0;
ret = bladerf_get_sample_rate( _dev, BLADERF_MODULE_RX, &rate );
ret = bladerf_get_sample_rate( _dev.get(), BLADERF_MODULE_RX, &rate );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"has failed to get sample rate, error " +
@ -399,7 +396,7 @@ double bladerf_source_c::set_center_freq( double freq, size_t chan )
freq > get_freq_range( chan ).stop() ) {
std::cerr << "Failed to set out of bound frequency: " << freq << std::endl;
} else {
ret = bladerf_set_frequency( _dev, BLADERF_MODULE_RX, (uint32_t)freq );
ret = bladerf_set_frequency( _dev.get(), BLADERF_MODULE_RX, (uint32_t)freq );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"failed to set center frequency " +
@ -417,7 +414,7 @@ double bladerf_source_c::get_center_freq( size_t chan )
uint32_t freq;
int ret;
ret = bladerf_get_frequency( _dev, BLADERF_MODULE_RX, &freq );
ret = bladerf_get_frequency( _dev.get(), BLADERF_MODULE_RX, &freq );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"failed to get center frequency, error " +
@ -505,11 +502,11 @@ double bladerf_source_c::set_gain( double gain, const std::string & name, size_t
else /* gain < 3.0f */
g = BLADERF_LNA_GAIN_BYPASS;
ret = bladerf_set_lna_gain( _dev, g );
ret = bladerf_set_lna_gain( _dev.get(), g );
} else if( name == "VGA1" ) {
ret = bladerf_set_rxvga1( _dev, (int)gain );
ret = bladerf_set_rxvga1( _dev.get(), (int)gain );
} else if( name == "VGA2" ) {
ret = bladerf_set_rxvga2( _dev, (int)gain );
ret = bladerf_set_rxvga2( _dev.get(), (int)gain );
} else {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"requested to set the gain "
@ -539,12 +536,12 @@ double bladerf_source_c::get_gain( const std::string & name, size_t chan )
if( name == "LNA" ) {
bladerf_lna_gain lna_g;
ret = bladerf_get_lna_gain( _dev, &lna_g );
ret = bladerf_get_lna_gain( _dev.get(), &lna_g );
g = lna_g == BLADERF_LNA_GAIN_BYPASS ? 0 : lna_g == BLADERF_LNA_GAIN_MID ? 3 : 6;
} else if( name == "VGA1" ) {
ret = bladerf_get_rxvga1( _dev, &g );
ret = bladerf_get_rxvga1( _dev.get(), &g );
} else if( name == "VGA2" ) {
ret = bladerf_get_rxvga2( _dev, &g );
ret = bladerf_get_rxvga2( _dev.get(), &g );
} else {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"requested to get the gain "
@ -600,7 +597,7 @@ double bladerf_source_c::set_bandwidth( double bandwidth, size_t chan )
if ( bandwidth == 0.0 ) /* bandwidth of 0 means automatic filter selection */
bandwidth = get_sample_rate() * 0.75; /* select narrower filters to prevent aliasing */
ret = bladerf_set_bandwidth( _dev, BLADERF_MODULE_RX, (uint32_t)bandwidth, &actual );
ret = bladerf_set_bandwidth( _dev.get(), BLADERF_MODULE_RX, (uint32_t)bandwidth, &actual );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"could not set bandwidth, error " +
@ -615,7 +612,7 @@ double bladerf_source_c::get_bandwidth( size_t chan )
uint32_t bandwidth;
int ret;
ret = bladerf_get_bandwidth( _dev, BLADERF_MODULE_RX, &bandwidth );
ret = bladerf_get_bandwidth( _dev.get(), BLADERF_MODULE_RX, &bandwidth );
if( ret ) {
throw std::runtime_error( std::string(__FUNCTION__) + " " +
"could not get bandwidth, error " +