diff --git a/lib/bladerf/bladerf_common.cc b/lib/bladerf/bladerf_common.cc index fb49158..3833f34 100644 --- a/lib/bladerf/bladerf_common.cc +++ b/lib/bladerf/bladerf_common.cc @@ -40,6 +40,9 @@ #include "bladerf_common.h" +#define NUM_BUFFERS 32 +#define NUM_SAMPLES_PER_BUFFER (4 * 1024) + using namespace boost::assign; boost::mutex bladerf_common::_devs_mutex; @@ -110,6 +113,121 @@ bladerf_sptr bladerf_common::open(const std::string &device_name) return dev; } +void bladerf_common::init(dict_t &dict, const char *type) +{ + int ret; + unsigned int device_number = 0; + std::string device_name; + struct bladerf_version ver; + char serial[BLADERF_SERIAL_LENGTH]; + + _pfx = std::string("[bladeRF ") + std::string(type) + std::string("] "); + + if (dict.count("bladerf")) + { + std::string value = dict["bladerf"]; + if ( value.length() ) + { + try { + device_number = boost::lexical_cast< unsigned int >( value ); + } catch ( std::exception &ex ) { + throw std::runtime_error( _pfx + "Failed to use '" + value + + "' as device number: " + ex.what()); + } + } + } + + device_name = boost::str(boost::format( "libusb:instance=%d" ) % device_number); + + try { + _dev = open(device_name); + } catch(...) { + throw std::runtime_error( _pfx + "Failed to open bladeRF device " + + device_name ); + } + + /* Load an FPGA */ + if ( dict.count("fpga") ) + { + std::string fpga = dict["fpga"]; + + std::cerr << _pfx << "Loading FPGA bitstream " << fpga << "..." << std::endl; + ret = bladerf_load_fpga( _dev.get(), fpga.c_str() ); + if ( ret != 0 ) + std::cerr << _pfx << "bladerf_load_fpga has failed with " << ret << std::endl; + else + std::cerr << _pfx << "The FPGA bitstream has been successfully loaded." << std::endl; + } + + if ( bladerf_is_fpga_configured( _dev.get() ) != 1 ) + { + std::ostringstream oss; + oss << _pfx << "The FPGA is not configured! " + << "Provide device argument fpga=/path/to/the/bitstream.rbf to load it."; + + throw std::runtime_error( oss.str() ); + } + + + /* Show some info about the device we've opened */ + std::cerr << _pfx << "Using nuand LLC bladeRF #" << device_number; + + if ( bladerf_get_serial( _dev.get(), serial ) == 0 ) + std::cerr << " SN " << serial; + + if ( bladerf_fw_version( _dev.get(), &ver ) == 0 ) + std::cerr << " FW v" << ver.major << "." << ver.minor << "." << ver.patch; + + if ( bladerf_fpga_version( _dev.get(), &ver ) == 0 ) + std::cerr << " FPGA v" << ver.major << "." << ver.minor << "." << ver.patch; + + std::cerr << std::endl; + + /* Initialize buffer and sample configuration */ + _num_buffers = 0; + if (dict.count("buffers")) { + _num_buffers = boost::lexical_cast< size_t >( dict["buffers"] ); + } + + _samples_per_buffer = 0; + if (dict.count("buflen")) { + _samples_per_buffer = boost::lexical_cast< size_t >( dict["buflen"] ); + } + + _num_transfers = 0; + if (dict.count("transfers")) { + _num_transfers = boost::lexical_cast< size_t >( dict["transfers"] ); + } + + /* Require value to be >= 2 so we can ensure we have twice as many + * buffers as transfers */ + if (_num_buffers <= 1) { + _num_buffers = NUM_BUFFERS; + } + + if (0 == _samples_per_buffer) { + _samples_per_buffer = NUM_SAMPLES_PER_BUFFER; + } else { + if (_samples_per_buffer < 1024 || _samples_per_buffer % 1024 != 0) { + + /* 0 likely implies the user did not specify this, so don't warn */ + if (_samples_per_buffer != 0 ) { + std::cerr << _pfx << "Invalid \"buflen\" value. " + << "A multiple of 1024 is required. Defaulting to " + << NUM_SAMPLES_PER_BUFFER << std::endl; + } + + _samples_per_buffer = NUM_SAMPLES_PER_BUFFER; + } + } + + + + if (_num_transfers == 0 || _num_transfers > (_num_buffers / 2)) { + _num_transfers = _num_buffers / 2; + } +} + osmosdr::freq_range_t bladerf_common::freq_range() { /* assuming the same for RX & TX */ diff --git a/lib/bladerf/bladerf_common.h b/lib/bladerf/bladerf_common.h index 7eb7da5..41f5028 100644 --- a/lib/bladerf/bladerf_common.h +++ b/lib/bladerf/bladerf_common.h @@ -28,6 +28,9 @@ #include #include #include +#include +#include +#include #include #include @@ -35,6 +38,7 @@ #include #include "osmosdr/ranges.h" +#include "arg_helpers.h" /* We currently read/write 1024 samples (pairs of 16-bit signed ints) */ #define BLADERF_SAMPLE_BLOCK_SIZE (1024) @@ -48,7 +52,8 @@ public: virtual ~bladerf_common(); protected: - bladerf_sptr open(const std::string &device_name); + /* Handle initialized and parameters common to both source & sink */ + void init(dict_t &dict, const char *type); osmosdr::freq_range_t freq_range(); osmosdr::meta_range_t sample_rates(); @@ -65,13 +70,19 @@ protected: struct bladerf_stream *_stream; size_t _num_buffers; size_t _buf_index; + size_t _samples_per_buffer; + size_t _num_transfers; gr::thread::thread _thread; osmosdr::gain_range_t _vga1_range; osmosdr::gain_range_t _vga2_range; + std::string _pfx; + private: + bladerf_sptr open(const std::string &device_name); + bool _is_running; boost::shared_mutex _state_lock; diff --git a/lib/bladerf/bladerf_sink_c.cc b/lib/bladerf/bladerf_sink_c.cc index f6f09b8..88a80c1 100644 --- a/lib/bladerf/bladerf_sink_c.cc +++ b/lib/bladerf/bladerf_sink_c.cc @@ -39,9 +39,6 @@ #include "arg_helpers.h" #include "bladerf_sink_c.h" -#define NUM_BUFFERS 32 -#define NUM_SAMPLES_PER_BUFFER 4096 - using namespace boost::assign; /* @@ -76,82 +73,11 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args) gr::io_signature::make (MIN_OUT, MAX_OUT, sizeof (gr_complex))) { int ret; - unsigned int device_number = 0; - std::string device_name; dict_t dict = params_to_dict(args); - if (dict.count("bladerf")) - { - std::string value = dict["bladerf"]; - if ( value.length() ) - { - try { - device_number = boost::lexical_cast< unsigned int >( value ); - } catch ( std::exception &ex ) { - throw std::runtime_error( - "Failed to use '" + value + "' as device number: " + ex.what()); - } - } - } - - device_name = boost::str(boost::format( "libusb:instance=%d" ) % device_number); - - try { - _dev = bladerf_common::open(device_name); - } catch(...) { - throw std::runtime_error( std::string(__FUNCTION__) + " " + - "failed to open bladeRF device " + device_name ); - } - - if (dict.count("fw")) - { - std::string fw = dict["fw"]; - - std::cerr << "Flashing firmware image " << fw << "..., DO NOT INTERRUPT!" - << std::endl; - ret = bladerf_flash_firmware( _dev.get(), fw.c_str() ); - if ( ret != 0 ) - std::cerr << "bladerf_flash_firmware has failed with " << ret << std::endl; - else - std::cerr << "The firmware has been successfully flashed." << std::endl; - } - - if (dict.count("fpga")) - { - std::string fpga = dict["fpga"]; - - std::cerr << "Loading FPGA bitstream " << fpga << "..." << std::endl; - 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 - std::cerr << "The FPGA bitstream has been successfully loaded." << std::endl; - } - - std::cerr << "Using nuand LLC bladeRF #" << device_number; - - char serial[BLADERF_SERIAL_LENGTH]; - if ( bladerf_get_serial( _dev.get(), serial ) == 0 ) - std::cerr << " SN " << serial; - - struct bladerf_version ver; - if ( bladerf_fw_version( _dev.get(), &ver ) == 0 ) - std::cerr << " FW v" << ver.major << "." << ver.minor << "." << ver.patch; - - 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.get() ) != 1 ) - { - std::ostringstream oss; - oss << "The FPGA is not configured! " - << "Provide device argument fpga=/path/to/the/bitstream.rbf to load it."; - - throw std::runtime_error( oss.str() ); - } + /* Perform src/sink agnostic initializations */ + init(dict, "source"); /* Set the range of VGA1, VGA1GAINT[7:0] */ _vga1_range = osmosdr::gain_range_t( -35, -4, 1 ); @@ -159,51 +85,13 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args) /* Set the range of VGA2, VGA2GAIN[4:0] */ _vga2_range = osmosdr::gain_range_t( 0, 25, 1 ); - _num_buffers = _samples_per_buffer = 0; - - /* Initialize buffer and sample configuration */ - if (dict.count("buffers")) { - _num_buffers = boost::lexical_cast< size_t >( dict["buffers"] ); - } - - if (dict.count("buflen")) { - _samples_per_buffer = boost::lexical_cast< size_t >( dict["buflen"] ); - } - - unsigned int transfers = 0; - if (dict.count("transfers")) { - transfers = boost::lexical_cast< size_t >( dict["transfers"] ); - } - - /* Require value to be >= 2 so we can ensure we have twice as many - * buffers as transfers */ - if (_num_buffers <= 1) { - _num_buffers = NUM_BUFFERS; - } - - if (0 == _samples_per_buffer) { - _samples_per_buffer = NUM_SAMPLES_PER_BUFFER; - } else { - /* For SC16_Q12, 1 sample = 2 int16_t's */ - _samples_per_buffer /= 2 * sizeof(int16_t); - - if (_samples_per_buffer < 1024 || _samples_per_buffer % 1024 != 0) - _samples_per_buffer = NUM_SAMPLES_PER_BUFFER; - } - - - - if (transfers == 0 || transfers > (_num_buffers / 2)) { - transfers = _num_buffers / 2; - - } - /* Initialize the stream */ ret = bladerf_init_stream( &_stream, _dev.get(), stream_callback, &_buffers, _num_buffers, BLADERF_FORMAT_SC16_Q12, - _samples_per_buffer, transfers, this ); + _samples_per_buffer, _num_transfers, this ); if ( ret != 0 ) - std::cerr << "bladerf_init_stream has failed with " << ret << std::endl; + std::cerr << _pfx << "bladerf_init_stream failed:" + << bladerf_strerror(ret) << std::endl; /* Initialize buffer management */ _buf_index = _next_to_tx = 0; @@ -212,8 +100,8 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args) _filled = new bool[_num_buffers]; if (!_filled) { - throw std::runtime_error( std::string(__FUNCTION__) + ": " + - "Failed to allocate _filled[]"); + throw std::runtime_error( std::string(__FUNCTION__) + " " + + "Failed to allocate _filled[]" ); } for (size_t i = 0; i < _num_buffers; ++i) { @@ -222,7 +110,8 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args) ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_TX, true ); if ( ret != 0 ) - std::cerr << "bladerf_enable_module has failed with " << ret << std::endl; + std::cerr << _pfx << "bladerf_enable_module has failed:" + << bladerf_strerror(ret) << std::endl; set_running( true ); _thread = gr::thread::thread( boost::bind(&bladerf_sink_c::write_task, this) ); @@ -247,7 +136,8 @@ bladerf_sink_c::~bladerf_sink_c () ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_TX, false ); if ( ret != 0 ) - std::cerr << "bladerf_enable_module has failed with " << ret << std::endl; + std::cerr << _pfx << "bladerf_enable_module failed:" + << bladerf_strerror(ret) << std::endl; /* Release stream resources */ bladerf_deinit_stream(_stream); @@ -317,8 +207,16 @@ void bladerf_sink_c::write_task() /* Start stream and stay there until we kill the stream */ status = bladerf_stream(_stream, BLADERF_MODULE_TX); - if (status < 0) - std::cerr << "Sink stream error: " << bladerf_strerror(status) << std::endl; + if ( status < 0 ) { + std::cerr << _pfx << "Sink stream error: " + << bladerf_strerror(status) << std::endl; + + if ( status == BLADERF_ERR_TIMEOUT ) { + std::cerr << _pfx << "Try adjusting your sample rate or the " + << "\"buffers\", \"buflen\", and \"transfers\" parameters. " + << std::endl; + } + } set_running( false ); } @@ -406,16 +304,16 @@ double bladerf_sink_c::set_sample_rate(double rate) 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 " + - boost::lexical_cast(ret) ); + "Failed to set integer rate:" + + std::string(bladerf_strerror(ret))); } } else { /* TODO: Fractional sample rate */ 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 " + - boost::lexical_cast(ret) ); + "Failed to set fractional rate: " + + std::string(bladerf_strerror(ret))); } } @@ -429,9 +327,9 @@ double bladerf_sink_c::get_sample_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 " + - boost::lexical_cast(ret) ); + throw std::runtime_error( std::string(__FUNCTION__) + + "Failed to get sample rate:" + + std::string(bladerf_strerror(ret))); } return (double)rate; @@ -454,10 +352,9 @@ double bladerf_sink_c::set_center_freq( double freq, size_t chan ) 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 " + + "Failed to set center frequency " + boost::lexical_cast(freq) + - ", error " + - boost::lexical_cast(ret) ); + ":" + std::string(bladerf_strerror(ret))); } } @@ -472,8 +369,8 @@ double bladerf_sink_c::get_center_freq( size_t chan ) 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 " + - boost::lexical_cast(ret) ); + "Failed to get center frequency:" + + std::string(bladerf_strerror(ret))); } return (double)freq; @@ -517,7 +414,7 @@ osmosdr::gain_range_t bladerf_sink_c::get_gain_range( const std::string & name, range = _vga2_range; } else { throw std::runtime_error( std::string(__FUNCTION__) + " " + - "requested an invalid gain element " + name ); + "Requested an invalid gain element " + name ); } return range; @@ -548,15 +445,15 @@ double bladerf_sink_c::set_gain( double gain, const std::string & name, size_t c ret = bladerf_set_txvga2( _dev.get(), (int)gain ); } else { throw std::runtime_error( std::string(__FUNCTION__) + " " + - "requested to set the gain " + "Requested to set the gain " + "of an unknown gain element " + name ); } /* Check for errors */ if( ret ) { - throw std::runtime_error( std::string(__FUNCTION__) + " " + - "could not set " + name + " gain, error " + - boost::lexical_cast(ret) ); + throw std::runtime_error(std::string(__FUNCTION__) + " " + + "Could not set " + name + " gain, error " + + std::string(bladerf_strerror(ret))); } return get_gain( name, chan ); @@ -578,15 +475,15 @@ double bladerf_sink_c::get_gain( const std::string & name, size_t chan ) ret = bladerf_get_txvga2( _dev.get(), &g ); } else { throw std::runtime_error( std::string(__FUNCTION__) + " " + - "requested to get the gain " + "Requested to get the gain " + "of an unknown gain element " + name ); } /* Check for errors */ if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + - "could not get " + name + " gain, error " + - boost::lexical_cast(ret) ); + "Could not get " + name + " gain, error " + + std::string(bladerf_strerror(ret))); } return (double)g; @@ -634,7 +531,7 @@ double bladerf_sink_c::set_bandwidth( double bandwidth, size_t chan ) 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 " + + "Could not set bandwidth, error " + boost::lexical_cast(ret) ); } @@ -649,7 +546,7 @@ double bladerf_sink_c::get_bandwidth( size_t chan ) ret = bladerf_get_bandwidth( _dev.get(), BLADERF_MODULE_TX, &bandwidth ); if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + - "could not get bandwidth, error " + + "Could not get bandwidth, error " + boost::lexical_cast(ret) ); } diff --git a/lib/bladerf/bladerf_sink_c.h b/lib/bladerf/bladerf_sink_c.h index d969264..ca43e26 100644 --- a/lib/bladerf/bladerf_sink_c.h +++ b/lib/bladerf/bladerf_sink_c.h @@ -120,8 +120,6 @@ private: /* functions */ private: /* members */ - size_t _samples_per_buffer; - /* Array denoting whether each buffer is filled with data and ready to TX */ bool *_filled; diff --git a/lib/bladerf/bladerf_source_c.cc b/lib/bladerf/bladerf_source_c.cc index 451ba0e..7e50efc 100644 --- a/lib/bladerf/bladerf_source_c.cc +++ b/lib/bladerf/bladerf_source_c.cc @@ -81,122 +81,52 @@ bladerf_source_c::bladerf_source_c (const std::string &args) gr::io_signature::make (MIN_OUT, MAX_OUT, sizeof (gr_complex))) { int ret; - unsigned int device_number = 0; size_t fifo_size; std::string device_name; dict_t dict = params_to_dict(args); - if (dict.count("bladerf")) - { - std::string value = dict["bladerf"]; - if ( value.length() ) - { - try { - device_number = boost::lexical_cast< unsigned int >( value ); - } catch ( std::exception &ex ) { - throw std::runtime_error( - "Failed to use '" + value + "' as device number: " + ex.what()); - } - } - } + init(dict, "source"); - device_name = boost::str(boost::format( "libusb:instance=%d" ) % device_number); - - try { - _dev = bladerf_common::open(device_name); - } catch(...) { - throw std::runtime_error( std::string(__FUNCTION__) + " " + - "failed to open bladeRF device " + device_name ); - } - - /* Size of FIFO gr_complex samples, in # samples. */ fifo_size = BLADERF_SAMPLE_FIFO_SIZE; if (dict.count("fifo")) { try { fifo_size = boost::lexical_cast(dict["fifo"]); } catch (const boost::bad_lexical_cast &e) { - std::cerr << "Warning: \"fifo\" value is invalid. Defaulting to " + std::cerr << _pfx << "Warning: \"fifo\" value is invalid. Defaulting to " << fifo_size; } if (fifo_size < BLADERF_SAMPLE_FIFO_MIN_SIZE) { fifo_size = BLADERF_SAMPLE_FIFO_MIN_SIZE; - std::cerr << "Warning: \"fifo\" value is too small. Defaulting to " + std::cerr << _pfx << "Warning: \"fifo\" value is too small. Defaulting to " << BLADERF_SAMPLE_FIFO_MIN_SIZE; } } _fifo = new boost::circular_buffer(fifo_size); if (!_fifo) { - throw std::runtime_error( std::string(__FUNCTION__) + - " has failed to allocate a sample FIFO!" ); - } - - if (dict.count("fw")) - { - std::string fw = dict["fw"]; - - std::cerr << "Flashing firmware image " << fw << "..., DO NOT INTERRUPT!" - << std::endl; - ret = bladerf_flash_firmware( _dev.get(), fw.c_str() ); - if ( ret != 0 ) - std::cerr << "bladerf_flash_firmware has failed with " << ret << std::endl; - else - std::cerr << "The firmware has been successfully flashed." << std::endl; - } - - if (dict.count("fpga")) - { - std::string fpga = dict["fpga"]; - - std::cerr << "Loading FPGA bitstream " << fpga << "..." << std::endl; - 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 - std::cerr << "The FPGA bitstream has been successfully loaded." << std::endl; - } - - std::cerr << "Using nuand LLC bladeRF #" << device_number; - - char serial[BLADERF_SERIAL_LENGTH]; - if ( bladerf_get_serial( _dev.get(), serial ) == 0 ) - std::cerr << " SN " << serial; - - struct bladerf_version ver; - if ( bladerf_fw_version( _dev.get(), &ver ) == 0 ) - std::cerr << " FW v" << ver.major << "." << ver.minor << "." << ver.patch; - - 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.get() ) != 1 ) - { - std::ostringstream oss; - oss << "The FPGA is not configured! " - << "Provide device argument fpga=/path/to/the/bitstream.rbf to load it."; - - throw std::runtime_error( oss.str() ); + throw std::runtime_error( std::string(__FUNCTION__) + " " + + "Failed to allocate a sample FIFO!" ); } if (dict.count("sampling")) { std::string sampling = dict["sampling"]; - std::cerr << "Setting bladerf sampling to " << sampling << std::endl; + std::cerr << _pfx << "Setting bladerf sampling to " << sampling << std::endl; if( sampling == "internal") { ret = bladerf_set_sampling( _dev.get(), BLADERF_SAMPLING_INTERNAL ); if ( ret != 0 ) - std::cerr << "Problem while setting sampling mode " << ret << std::endl; + std::cerr << _pfx << "Problem while setting sampling mode:" + << bladerf_strerror(ret) << std::endl; } else if( sampling == "external" ) { ret = bladerf_set_sampling( _dev.get(), BLADERF_SAMPLING_EXTERNAL ); if ( ret != 0 ) - std::cerr << "Problem while setting sampling mode " << ret << std::endl; + std::cerr << _pfx << "Problem while setting sampling mode:" + << bladerf_strerror(ret) << std::endl; } else { - std::cerr << "Invalid sampling mode " << sampling << std::endl; + std::cerr << _pfx << "Invalid sampling mode " << sampling << std::endl; } } @@ -209,20 +139,19 @@ bladerf_source_c::bladerf_source_c (const std::string &args) /* Set the range of VGA2 VGA2GAIN[4:0], not recommended to be used above 30dB */ _vga2_range = osmosdr::gain_range_t( 0, 60, 3 ); - _buf_index = 0; - _num_buffers = 8; /* TODO: make it an argument */ - const size_t samp_per_buf = 1024 * 10; /* TODO: make it an argument */ - /* Initialize the stream */ + _buf_index = 0; ret = bladerf_init_stream( &_stream, _dev.get(), stream_callback, &_buffers, _num_buffers, BLADERF_FORMAT_SC16_Q12, - samp_per_buf, _num_buffers, this ); + _samples_per_buffer, _num_buffers, this ); if ( ret != 0 ) - std::cerr << "bladerf_init_stream has failed with " << ret << std::endl; + std::cerr << _pfx << "bladerf_init_stream failed: " + << bladerf_strerror(ret) << std::endl; ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_RX, true ); if ( ret != 0 ) - std::cerr << "bladerf_enable_module has failed with " << ret << std::endl; + std::cerr << _pfx << "bladerf_enable_module failed:" + << bladerf_strerror(ret) << std::endl; _thread = gr::thread::thread( boost::bind(&bladerf_source_c::read_task, this) ); } @@ -239,7 +168,8 @@ bladerf_source_c::~bladerf_source_c () ret = bladerf_enable_module( _dev.get(), BLADERF_MODULE_RX, false ); if ( ret != 0 ) - std::cerr << "bladerf_enable_module has failed with " << ret << std::endl; + std::cerr << _pfx << "bladerf_enable_module failed: " + << bladerf_strerror(ret) << std::endl; /* Release stream resources */ bladerf_deinit_stream(_stream); @@ -318,9 +248,16 @@ void bladerf_source_c::read_task() /* Start stream and stay there until we kill the stream */ status = bladerf_stream(_stream, BLADERF_MODULE_RX); - if (status < 0) + if ( status < 0 ) { std::cerr << "Source stream error: " << bladerf_strerror(status) << std::endl; + if ( status == BLADERF_ERR_TIMEOUT ) { + std::cerr << _pfx << "Try adjusting your sample rate or the " + << "\"buffers\", \"buflen\", and \"transfers\" parameters. " + << std::endl; + } + } + set_running( false ); } @@ -384,16 +321,16 @@ double bladerf_source_c::set_sample_rate( double rate ) 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 " + - boost::lexical_cast(ret) ); + "has failed to set integer rate: " + + std::string(bladerf_strerror(ret)) ); } } else { /* TODO: Fractional sample rate */ 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 " + - boost::lexical_cast(ret) ); + "has failed to set fractional rate: " + + std::string(bladerf_strerror(ret)) ); } } @@ -409,7 +346,7 @@ double bladerf_source_c::get_sample_rate() if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + "has failed to get sample rate, error " + - boost::lexical_cast(ret) ); + std::string(bladerf_strerror(ret)) ); } return (double)rate; @@ -433,9 +370,8 @@ double bladerf_source_c::set_center_freq( double freq, size_t chan ) if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + "failed to set center frequency " + - boost::lexical_cast(freq) + - ", error " + - boost::lexical_cast(ret) ); + boost::lexical_cast(freq) + ": " + + std::string(bladerf_strerror(ret)) ); } } @@ -450,8 +386,8 @@ double bladerf_source_c::get_center_freq( size_t chan ) 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 " + - boost::lexical_cast(ret) ); + "failed to get center frequency: " + + std::string(bladerf_strerror(ret)) ); } return (double)freq; @@ -549,8 +485,8 @@ double bladerf_source_c::set_gain( double gain, const std::string & name, size_t /* Check for errors */ if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + - "could not set " + name + " gain, error " + - boost::lexical_cast(ret) ); + "could not set " + name + " gain: " + + std::string(bladerf_strerror(ret)) ); } return get_gain( name, chan ); @@ -584,8 +520,8 @@ double bladerf_source_c::get_gain( const std::string & name, size_t chan ) /* Check for errors */ if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + - "could not get " + name + " gain, error " + - boost::lexical_cast(ret) ); + "could not get " + name + " gain: " + + std::string(bladerf_strerror(ret)) ); } return (double)g; @@ -633,8 +569,8 @@ double bladerf_source_c::set_bandwidth( double bandwidth, size_t chan ) 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 " + - boost::lexical_cast(ret) ); + "could not set bandwidth: " + + std::string(bladerf_strerror(ret)) ); } return get_bandwidth(); @@ -648,8 +584,8 @@ double bladerf_source_c::get_bandwidth( size_t chan ) ret = bladerf_get_bandwidth( _dev.get(), BLADERF_MODULE_RX, &bandwidth ); if( ret ) { throw std::runtime_error( std::string(__FUNCTION__) + " " + - "could not get bandwidth, error " + - boost::lexical_cast(ret) ); + "could not get bandwidth:" + + std::string(bladerf_strerror(ret)) ); } return (double)bandwidth;