diff --git a/lib/bladerf/bladerf_common.cc b/lib/bladerf/bladerf_common.cc index bb6746a..2b96740 100644 --- a/lib/bladerf/bladerf_common.cc +++ b/lib/bladerf/bladerf_common.cc @@ -48,6 +48,10 @@ using namespace boost::assign; boost::mutex bladerf_common::_devs_mutex; std::list > bladerf_common::_devs; +// name of system-wide gain +//(internal only, doesn't match any libbladeRF gain stage) +static const char* SYSTEM_GAIN_NAME = "System"; + bladerf_common::bladerf_common() : _conv_buf(NULL), _conv_buf_size(4096), @@ -105,6 +109,7 @@ bladerf_sptr bladerf_common::open(const std::string &device_name) int rv; struct bladerf *raw_dev; struct bladerf_devinfo devinfo; + std::string boardname; boost::unique_lock lock(_devs_mutex); @@ -127,6 +132,18 @@ bladerf_sptr bladerf_common::open(const std::string &device_name) _devs.push_back(boost::weak_ptr(dev)); + // TODO: This does NOT get called if early cached_dev return occurs + boardname = std::string(bladerf_get_board_name(raw_dev)); + + if( "bladerf1" == boardname ) { + _boardtype = BLADERF_REV_1; + } else if( "bladerf2" == boardname ) { + _boardtype = BLADERF_REV_2; + } else { + std::cerr << "board name \"" << boardname << "\" unknown" << std::endl; + _boardtype = BLADERF_REV_INVALID; + }; + return dev; } @@ -135,6 +152,7 @@ void bladerf_common::set_loopback_mode(const std::string &loopback) bladerf_loopback mode; int status; + // TODO: update for bladeRF 2 if (loopback == "bb_txlpf_rxvga2") { mode = BLADERF_LB_BB_TXLPF_RXVGA2; } else if (loopback == "bb_txlpf_rxlpf") { @@ -191,14 +209,30 @@ bool bladerf_common::start(bladerf_module module) { int ret; bladerf_format format; + bladerf_channel_layout layout; + bladerf_direction direction; if (_use_metadata) { - format = BLADERF_FORMAT_SC16_Q11_META; + format = BLADERF_FORMAT_SC16_Q11_META; } else { - format = BLADERF_FORMAT_SC16_Q11; + format = BLADERF_FORMAT_SC16_Q11; } - ret = bladerf_sync_config(_dev.get(), module, format, + // TODO: DRY + // TODO: MIMO + if (BLADERF_MODULE_RX == module) { + layout = BLADERF_RX_X1; + direction = BLADERF_RX; + } else if (BLADERF_MODULE_TX == module) { + layout = BLADERF_TX_X1; + direction = BLADERF_TX; + } else { + std::cerr << _pfx << "invalid module: " + << module << std::endl; + return false; + } + + ret = bladerf_sync_config(_dev.get(), layout, format, _num_buffers, _samples_per_buffer, _num_transfers, _stream_timeout_ms); @@ -208,7 +242,7 @@ bool bladerf_common::start(bladerf_module module) return false; } - ret = bladerf_enable_module(_dev.get(), module, true); + ret = bladerf_enable_module(_dev.get(), direction, true); if ( ret != 0 ) { std::cerr << _pfx << "bladerf_enable_module failed: " << bladerf_strerror(ret) << std::endl; @@ -221,8 +255,21 @@ bool bladerf_common::start(bladerf_module module) bool bladerf_common::stop(bladerf_module module) { int ret; + bladerf_direction direction; - ret = bladerf_enable_module(_dev.get(), module, false); + // TODO: DRY + // TODO: MIMO + if (BLADERF_MODULE_RX == module) { + direction = BLADERF_RX; + } else if (BLADERF_MODULE_TX == module) { + direction = BLADERF_TX; + } else { + std::cerr << _pfx << "invalid module: " + << module << std::endl; + return false; + } + + ret = bladerf_enable_module(_dev.get(), direction, false); if ( ret != 0 ) { std::cerr << _pfx << "bladerf_enable_modue failed: " @@ -491,20 +538,40 @@ void bladerf_common::init(dict_t &dict, bladerf_module module) } } -osmosdr::freq_range_t bladerf_common::freq_range() +osmosdr::freq_range_t bladerf_common::freq_range(bladerf_channel chan) { - /* assuming the same for RX & TX */ - return osmosdr::freq_range_t( _xb_200_attached ? 0 : 280e6, BLADERF_FREQUENCY_MAX ); + struct bladerf_range brf_range; + int ret; + + ret = bladerf_get_frequency_range( _dev.get(), chan, &brf_range ); + + if( ret ) { + throw std::runtime_error( std::string(__FUNCTION__) + " " + + "bladerf_get_frequency_range returned " + + boost::lexical_cast(ret) ); + } else { + return osmosdr::freq_range_t((double)brf_range.min, (double)brf_range.max, (double)brf_range.step); + }; } osmosdr::meta_range_t bladerf_common::sample_rates() { osmosdr::meta_range_t sample_rates; + bladerf_range brf_sample_rates; + int ret; /* assuming the same for RX & TX */ - sample_rates += osmosdr::range_t( 160e3, 200e3, 40e3 ); - sample_rates += osmosdr::range_t( 300e3, 900e3, 100e3 ); - sample_rates += osmosdr::range_t( 1e6, 40e6, 1e6 ); + ret = bladerf_get_sample_rate_range( _dev.get(), BLADERF_CHANNEL_RX(0), &brf_sample_rates ); + + if( ret ) { + throw std::runtime_error( std::string(__FUNCTION__) + " " + + "bladerf_get_sample_rate_range returned " + + boost::lexical_cast(ret) ); + } + + sample_rates += osmosdr::range_t( brf_sample_rates.min, brf_sample_rates.max/4.0, brf_sample_rates.max/16.0 ); + sample_rates += osmosdr::range_t( brf_sample_rates.max/4.0, brf_sample_rates.max/2.0, brf_sample_rates.max/8.0 ); + sample_rates += osmosdr::range_t( brf_sample_rates.max/2.0, brf_sample_rates.max, brf_sample_rates.max/4.0 ); return sample_rates; } @@ -513,14 +580,18 @@ osmosdr::freq_range_t bladerf_common::filter_bandwidths() { /* the same for RX & TX according to the datasheet */ osmosdr::freq_range_t bandwidths; + bladerf_range brf_range; + int ret; - std::vector half_bandwidths; /* in MHz */ - half_bandwidths += \ - 0.75, 0.875, 1.25, 1.375, 1.5, 1.92, 2.5, - 2.75, 3, 3.5, 4.375, 5, 6, 7, 10, 14; + ret = bladerf_get_bandwidth_range( _dev.get(), BLADERF_CHANNEL_RX(0), &brf_range ); - BOOST_FOREACH( double half_bw, half_bandwidths ) - bandwidths += osmosdr::range_t( half_bw * 2e6 ); + if( ret ) { + throw std::runtime_error( std::string(__FUNCTION__) + " " + + "bladerf_get_bandwidth_range returned " + + boost::lexical_cast(ret) ); + } + + bandwidths += osmosdr::range_t(brf_range.min, brf_range.max, brf_range.step); return bandwidths; } @@ -560,6 +631,15 @@ std::vector< std::string > bladerf_common::devices() return ret; } +size_t bladerf_common::get_num_channels(bladerf_module module) +{ + if (BLADERF_REV_2 == _boardtype) { + return 1; // TODO: should be 2 but it ain't working yet + } else { + return 1; + } +} + double bladerf_common::set_sample_rate( bladerf_module module, double rate ) { int status; @@ -601,6 +681,177 @@ double bladerf_common::get_sample_rate( bladerf_module module ) return ret; } +osmosdr::freq_range_t bladerf_common::get_freq_range( size_t chan ) +{ + return freq_range((bladerf_channel)chan); +} + +double bladerf_common::set_center_freq( double freq, size_t chan ) +{ + int ret; + + /* Check frequency range */ + if( freq < get_freq_range( chan ).start() || + freq > get_freq_range( chan ).stop() ) { + std::cerr << "Failed to set out of bound frequency: " << freq << std::endl; + } else { + ret = bladerf_set_frequency( _dev.get(), (bladerf_channel)chan, (uint64_t)freq ); + if( ret ) { + throw std::runtime_error( std::string(__FUNCTION__) + " " + + "failed to set center frequency " + + boost::lexical_cast(freq) + ": " + + std::string(bladerf_strerror(ret)) ); + } + } + + return get_center_freq( chan ); +} + +double bladerf_common::get_center_freq( size_t chan ) +{ + uint64_t freq; + int ret; + + ret = bladerf_get_frequency( _dev.get(), (bladerf_channel)chan, &freq ); + if( ret ) { + throw std::runtime_error( std::string(__FUNCTION__) + " " + + "failed to get center frequency: " + + std::string(bladerf_strerror(ret)) ); + } + + return (double)freq; +} + +std::vector bladerf_common::get_gain_names( size_t chan ) +{ + const size_t max_count = 16; + std::vector< std::string > names; + char *gain_names[max_count]; + int ret; + + memset(&gain_names, 0, sizeof(gain_names)); + + names += SYSTEM_GAIN_NAME; + + ret = bladerf_get_gain_stages( _dev.get(), (bladerf_channel)chan, (const char**)&gain_names, max_count); + + if(ret < 0) { + throw std::runtime_error( std::string(__FUNCTION__) + " " + + "failed to get gain stages: " + + std::string(bladerf_strerror(ret)) ); + } + + for(char **p = gain_names; *p != NULL; ++p) { + char *tmp = *p; + names += std::string(tmp); + }; + + return names; +} + +osmosdr::gain_range_t bladerf_common::get_gain_range( size_t chan ) +{ + /* This is an overall system gain range. */ + return get_gain_range( SYSTEM_GAIN_NAME, chan ); +} + +osmosdr::gain_range_t bladerf_common::get_gain_range( const std::string & name, size_t chan ) +{ + osmosdr::gain_range_t range; + struct bladerf_range brf_range; + int ret; + + if( name == SYSTEM_GAIN_NAME ) { + ret = bladerf_get_gain_range( _dev.get(), (bladerf_channel)chan, &brf_range ); + } else { + ret = bladerf_get_gain_stage_range( _dev.get(), (bladerf_channel)chan, name.c_str(), &brf_range); + } + + if( ret ) { + throw std::runtime_error( std::string(__FUNCTION__) + " " + + "bladerf_get_gain_range " + name + + " error: " + + std::string(bladerf_strerror(ret)) ); + } + + range = osmosdr::gain_range_t( brf_range.min, brf_range.max, brf_range.step ); + + return range; +} + +bool bladerf_common::set_gain_mode( bool automatic, size_t chan ) +{ + return false; +} + +bool bladerf_common::get_gain_mode( size_t chan ) +{ + return false; +} + +double bladerf_common::set_gain( double gain, size_t chan ) +{ + return set_gain( gain, SYSTEM_GAIN_NAME, chan ); +} + +double bladerf_common::set_gain( double gain, const std::string & name, size_t chan ) +{ + int ret = 0; + + if( name == SYSTEM_GAIN_NAME ) { + ret = bladerf_set_gain( _dev.get(), (bladerf_channel)chan, int(gain) ); + } else { + ret = bladerf_set_gain_stage( _dev.get(), (bladerf_channel)chan, name.c_str(), int(gain) ); + } + + /* Check for errors */ + if( ret ) { + std::string errmsg = (std::string(__FUNCTION__) + " " + + "could not set " + name + " gain: " + + std::string(bladerf_strerror(ret))); + if ( BLADERF_ERR_UNSUPPORTED == ret ) { + // unsupported, but not worth crashing out + std::cerr << errmsg << std::endl; + } else { + throw std::runtime_error(errmsg); + } + } + + return get_gain( name, chan ); +} + +double bladerf_common::get_gain( size_t chan ) +{ + /* TODO: This is an overall system gain that has to be set */ + return get_gain( SYSTEM_GAIN_NAME, chan ); +} + +double bladerf_common::get_gain( const std::string & name, size_t chan ) +{ + int g; + int ret = 0; + + if( name == SYSTEM_GAIN_NAME ) { + ret = bladerf_get_gain( _dev.get(), (bladerf_channel)chan, &g ); + } else { + ret = bladerf_get_gain_stage( _dev.get(), (bladerf_channel)chan, name.c_str(), &g ); + } + + /* Check for errors */ + if( ret ) { + throw std::runtime_error( std::string(__FUNCTION__) + " " + + "could not get " + name + " gain: " + + std::string(bladerf_strerror(ret)) ); + } + + return (double)g; +} + +double bladerf_common::set_bb_gain( double gain, size_t chan ) +{ + return set_gain( gain, SYSTEM_GAIN_NAME, chan ); +} + int bladerf_common::set_dc_offset(bladerf_module module, const std::complex &offset, size_t chan) { int ret = 0; diff --git a/lib/bladerf/bladerf_common.h b/lib/bladerf/bladerf_common.h index 9c311f7..6c44765 100644 --- a/lib/bladerf/bladerf_common.h +++ b/lib/bladerf/bladerf_common.h @@ -55,15 +55,39 @@ public: virtual ~bladerf_common(); protected: + typedef enum { + BLADERF_REV_INVALID, + BLADERF_REV_1, + BLADERF_REV_2 + } bladerf_boards; + /* Handle initialized and parameters common to both source & sink */ void init(dict_t &dict, bladerf_module module); bool start(bladerf_module module); bool stop(bladerf_module module); + size_t get_num_channels(bladerf_module module); + double set_sample_rate(bladerf_module module, double rate); double get_sample_rate(bladerf_module module); + osmosdr::freq_range_t get_freq_range(size_t chan = 0); + double set_center_freq(double freq, size_t chan = 0); + double get_center_freq(size_t chan = 0); + + std::vector get_gain_names( size_t chan = 0 ); + osmosdr::gain_range_t get_gain_range( size_t chan = 0 ); + osmosdr::gain_range_t get_gain_range( const std::string & name, size_t chan = 0 ); + bool set_gain_mode( bool automatic, size_t chan = 0 ); + bool get_gain_mode( size_t chan = 0 ); + double set_gain( double gain, size_t chan = 0 ); + double set_gain( double gain, const std::string & name, size_t chan = 0 ); + double get_gain( size_t chan = 0 ); + double get_gain( const std::string & name, size_t chan = 0 ); + + double set_bb_gain( double gain, size_t chan = 0 ); + int set_dc_offset(bladerf_module module, const std::complex &offset, size_t chan); int set_iq_balance(bladerf_module module, const std::complex &balance, size_t chan); @@ -74,7 +98,7 @@ protected: void set_smb_frequency(double frequency); double get_smb_frequency(); - osmosdr::freq_range_t freq_range(); + osmosdr::freq_range_t freq_range(bladerf_channel chan); osmosdr::meta_range_t sample_rates(); osmosdr::freq_range_t filter_bandwidths(); @@ -82,6 +106,8 @@ protected: bladerf_sptr _dev; + bladerf_boards _boardtype; + size_t _num_buffers; size_t _samples_per_buffer; size_t _num_transfers; @@ -92,9 +118,6 @@ protected: bool _use_metadata; - osmosdr::gain_range_t _vga1_range; - osmosdr::gain_range_t _vga2_range; - std::string _pfx; bool _xb_200_attached; diff --git a/lib/bladerf/bladerf_sink_c.cc b/lib/bladerf/bladerf_sink_c.cc index 7019629..8f1fc2f 100644 --- a/lib/bladerf/bladerf_sink_c.cc +++ b/lib/bladerf/bladerf_sink_c.cc @@ -67,11 +67,11 @@ bladerf_sink_c_sptr make_bladerf_sink_c (const std::string &args) * (2nd & 3rd args to gr_block's constructor). The input and * output signatures are used by the runtime system to * check that a valid number and type of inputs and outputs - * are connected to this block. In this case, we accept - * only 0 input and 1 output. + * are connected to this block. In this case, we accept either + * 1 or 2 inputs. */ static const int MIN_IN = 1; // mininum number of input streams -static const int MAX_IN = 1; // maximum number of input streams +static const int MAX_IN = 2; // maximum number of input streams static const int MIN_OUT = 0; // minimum number of output streams static const int MAX_OUT = 0; // maximum number of output streams @@ -87,13 +87,6 @@ bladerf_sink_c::bladerf_sink_c (const std::string &args) /* Perform src/sink agnostic initializations */ init(dict, BLADERF_MODULE_TX); - - /* Set the range of VGA1, VGA1GAINT[7:0] */ - _vga1_range = osmosdr::gain_range_t( -35, -4, 1 ); - - /* Set the range of VGA2, VGA2GAIN[4:0] */ - _vga2_range = osmosdr::gain_range_t( 0, 25, 1 ); - } bool bladerf_sink_c::start() @@ -297,8 +290,7 @@ std::vector bladerf_sink_c::get_devices() size_t bladerf_sink_c::get_num_channels() { - /* We only support a single channel for each bladeRF */ - return 1; + return bladerf_common::get_num_channels(BLADERF_MODULE_RX); } osmosdr::meta_range_t bladerf_sink_c::get_sample_rates() @@ -316,45 +308,19 @@ double bladerf_sink_c::get_sample_rate() return bladerf_common::get_sample_rate(BLADERF_MODULE_TX); } -osmosdr::freq_range_t bladerf_sink_c::get_freq_range( size_t chan ) +osmosdr::freq_range_t bladerf_sink_c::get_freq_range(size_t chan) { - return freq_range(); + return bladerf_common::get_freq_range(chan); } -double bladerf_sink_c::set_center_freq( double freq, size_t chan ) +double bladerf_sink_c::set_center_freq(double freq, size_t chan) { - int ret; - - /* Check frequency range */ - if( freq < get_freq_range( chan ).start() || - freq > get_freq_range( chan ).stop() ) { - std::cerr << "Failed to set out of bound frequency: " << freq << std::endl; - } else { - 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 " + - boost::lexical_cast(freq) + - ":" + std::string(bladerf_strerror(ret))); - } - } - - return get_center_freq( chan ); + return bladerf_common::set_center_freq(freq, chan); } -double bladerf_sink_c::get_center_freq( size_t chan ) +double bladerf_sink_c::get_center_freq(size_t chan) { - uint32_t freq; - int ret; - - ret = bladerf_get_frequency( _dev.get(), BLADERF_MODULE_TX, &freq ); - if( ret ) { - throw std::runtime_error( std::string(__FUNCTION__) + " " + - "Failed to get center frequency:" + - std::string(bladerf_strerror(ret))); - } - - return (double)freq; + return bladerf_common::get_center_freq(chan); } double bladerf_sink_c::set_freq_corr( double ppm, size_t chan ) @@ -371,114 +337,52 @@ double bladerf_sink_c::get_freq_corr( size_t chan ) std::vector bladerf_sink_c::get_gain_names( size_t chan ) { - std::vector< std::string > names; - - names += "VGA1", "VGA2"; - - return names; + return bladerf_common::get_gain_names(chan); } osmosdr::gain_range_t bladerf_sink_c::get_gain_range( size_t chan ) { - /* TODO: This is an overall system gain range. Given the VGA1 and VGA2 - how much total gain can we have in the system */ - return get_gain_range( "VGA2", chan ); /* we use only VGA2 here for now */ + return bladerf_common::get_gain_range(chan); } osmosdr::gain_range_t bladerf_sink_c::get_gain_range( const std::string & name, size_t chan ) { - osmosdr::gain_range_t range; - - if( name == "VGA1" ) { - range = _vga1_range; - } else if( name == "VGA2" ) { - range = _vga2_range; - } else { - throw std::runtime_error( std::string(__FUNCTION__) + " " + - "Requested an invalid gain element " + name ); - } - - return range; + return bladerf_common::get_gain_range(name, chan); } bool bladerf_sink_c::set_gain_mode( bool automatic, size_t chan ) { - return false; + return bladerf_common::set_gain_mode(automatic, chan); } bool bladerf_sink_c::get_gain_mode( size_t chan ) { - return false; + return bladerf_common::get_gain_mode(chan); } double bladerf_sink_c::set_gain( double gain, size_t chan ) { - return set_gain( gain, "VGA2", chan ); /* we use only VGA2 here for now */ + return bladerf_common::set_gain(gain, chan); } double bladerf_sink_c::set_gain( double gain, const std::string & name, size_t chan) { - int ret = 0; - - if( name == "VGA1" ) { - ret = bladerf_set_txvga1( _dev.get(), (int)gain ); - } else if( name == "VGA2" ) { - ret = bladerf_set_txvga2( _dev.get(), (int)gain ); - } else { - throw std::runtime_error( std::string(__FUNCTION__) + " " + - "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 " + - std::string(bladerf_strerror(ret))); - } - - return get_gain( name, chan ); + return bladerf_common::set_gain(gain, name, chan); } double bladerf_sink_c::get_gain( size_t chan ) { - return get_gain( "VGA2", chan ); /* we use only VGA2 here for now */ + return bladerf_common::get_gain(chan); } double bladerf_sink_c::get_gain( const std::string & name, size_t chan ) { - int g; - int ret = 0; - - if( name == "VGA1" ) { - ret = bladerf_get_txvga1( _dev.get(), &g ); - } else if( name == "VGA2" ) { - ret = bladerf_get_txvga2( _dev.get(), &g ); - } else { - throw std::runtime_error( std::string(__FUNCTION__) + " " + - "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 " + - std::string(bladerf_strerror(ret))); - } - - return (double)g; + return bladerf_common::get_gain(name, chan); } double bladerf_sink_c::set_bb_gain( double gain, size_t chan ) { - /* for TX, only VGA1 is in the BB path */ - osmosdr::gain_range_t bb_gains = get_gain_range( "VGA1", chan ); - - double clip_gain = bb_gains.clip( gain, true ); - gain = set_gain( clip_gain, "VGA1", chan ); - - return gain; + return bladerf_common::set_bb_gain(gain, chan); } std::vector< std::string > bladerf_sink_c::get_antennas( size_t chan ) diff --git a/lib/bladerf/bladerf_sink_c.h b/lib/bladerf/bladerf_sink_c.h index 496abf4..20ed9f7 100644 --- a/lib/bladerf/bladerf_sink_c.h +++ b/lib/bladerf/bladerf_sink_c.h @@ -89,9 +89,10 @@ public: double set_sample_rate( double rate ); double get_sample_rate( void ); - osmosdr::freq_range_t get_freq_range( size_t chan = 0 ); - double set_center_freq( double freq, size_t chan = 0 ); - double get_center_freq( size_t chan = 0 ); + osmosdr::freq_range_t get_freq_range(size_t chan = 0); + double set_center_freq(double freq, size_t chan = 0); + double get_center_freq(size_t chan = 0); + double set_freq_corr( double ppm, size_t chan = 0 ); double get_freq_corr( size_t chan = 0 ); diff --git a/lib/bladerf/bladerf_source_c.cc b/lib/bladerf/bladerf_source_c.cc index 17aeacf..042d7ff 100644 --- a/lib/bladerf/bladerf_source_c.cc +++ b/lib/bladerf/bladerf_source_c.cc @@ -59,13 +59,13 @@ bladerf_source_c_sptr make_bladerf_source_c (const std::string &args) * (2nd & 3rd args to gr_block's constructor). The input and * output signatures are used by the runtime system to * check that a valid number and type of inputs and outputs - * are connected to this block. In this case, we accept - * only 0 input and 1 output. + * are connected to this block. In this case, we accept either + * 1 or 2 outputs. */ static const int MIN_IN = 0; // mininum number of input streams static const int MAX_IN = 0; // maximum number of input streams static const int MIN_OUT = 1; // minimum number of output streams -static const int MAX_OUT = 1; // maximum number of output streams +static const int MAX_OUT = 2; // maximum number of output streams /* * The private constructor @@ -103,15 +103,6 @@ bladerf_source_c::bladerf_source_c (const std::string &args) } } - /* Set the range of LNA, G_LNA_RXFE[1:0] */ - _lna_range = osmosdr::gain_range_t( 0, 6, 3 ); - - /* Set the range of VGA1, RFB_TIA_RXFE[6:0], nonlinear mapping done inside the lib */ - _vga1_range = osmosdr::gain_range_t( 5, 30, 1 ); - - /* Set the range of VGA2 VGA2GAIN[4:0], not recommended to be used above 30dB */ - _vga2_range = osmosdr::gain_range_t( 0, 30, 3 ); - /* Warn user about using an old FPGA version, as we no longer strip off the * markers that were pressent in the pre-v0.0.1 FPGA */ if (bladerf_fpga_version( _dev.get(), &fpga_version ) != 0) { @@ -197,8 +188,7 @@ std::vector bladerf_source_c::get_devices() size_t bladerf_source_c::get_num_channels() { - /* We only support a single channel for each bladeRF */ - return 1; + return bladerf_common::get_num_channels(BLADERF_MODULE_RX); } osmosdr::meta_range_t bladerf_source_c::get_sample_rates() @@ -216,45 +206,19 @@ double bladerf_source_c::get_sample_rate() return bladerf_common::get_sample_rate( BLADERF_MODULE_RX ); } -osmosdr::freq_range_t bladerf_source_c::get_freq_range( size_t chan ) +osmosdr::freq_range_t bladerf_source_c::get_freq_range(size_t chan) { - return freq_range(); + return bladerf_common::get_freq_range(chan); } -double bladerf_source_c::set_center_freq( double freq, size_t chan ) +double bladerf_source_c::set_center_freq(double freq, size_t chan) { - int ret; - - /* Check frequency range */ - if( freq < get_freq_range( chan ).start() || - freq > get_freq_range( chan ).stop() ) { - std::cerr << "Failed to set out of bound frequency: " << freq << std::endl; - } else { - 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 " + - boost::lexical_cast(freq) + ": " + - std::string(bladerf_strerror(ret)) ); - } - } - - return get_center_freq( chan ); + return bladerf_common::set_center_freq(freq, chan); } -double bladerf_source_c::get_center_freq( size_t chan ) +double bladerf_source_c::get_center_freq(size_t chan) { - uint32_t freq; - int ret; - - ret = bladerf_get_frequency( _dev.get(), BLADERF_MODULE_RX, &freq ); - if( ret ) { - throw std::runtime_error( std::string(__FUNCTION__) + " " + - "failed to get center frequency: " + - std::string(bladerf_strerror(ret)) ); - } - - return (double)freq; + return bladerf_common::get_center_freq(chan); } double bladerf_source_c::set_freq_corr( double ppm, size_t chan ) @@ -271,150 +235,52 @@ double bladerf_source_c::get_freq_corr( size_t chan ) std::vector bladerf_source_c::get_gain_names( size_t chan ) { - std::vector< std::string > names; - - names += "LNA", "VGA1", "VGA2"; - - return names; + return bladerf_common::get_gain_names(chan); } osmosdr::gain_range_t bladerf_source_c::get_gain_range( size_t chan ) { - /* TODO: This is an overall system gain range. Given the LNA, VGA1 and VGA2 - how much total gain can we have in the system */ - return get_gain_range( "LNA", chan ); /* we use only LNA here for now */ + return bladerf_common::get_gain_range(chan); } osmosdr::gain_range_t bladerf_source_c::get_gain_range( const std::string & name, size_t chan ) { - osmosdr::gain_range_t range; - - if( name == "LNA" ) { - range = _lna_range; - } else if( name == "VGA1" ) { - range = _vga1_range; - } else if( name == "VGA2" ) { - range = _vga2_range; - } else { - throw std::runtime_error( std::string(__FUNCTION__) + " " + - "requested an invalid gain element " + name ); - } - - return range; + return bladerf_common::get_gain_range(name, chan); } bool bladerf_source_c::set_gain_mode( bool automatic, size_t chan ) { - /* TODO: Implement AGC in the FPGA */ - return false; + return bladerf_common::set_gain_mode(automatic, chan); } bool bladerf_source_c::get_gain_mode( size_t chan ) { - /* TODO: Read back AGC mode */ - return false; + return bladerf_common::get_gain_mode(chan); } double bladerf_source_c::set_gain( double gain, size_t chan ) { - /* TODO: This is an overall system gain that has to be set */ - return set_gain( gain, "LNA", chan ); /* we use only LNA here for now */ + return bladerf_common::set_gain(gain, chan); } -double bladerf_source_c::set_gain( double gain, const std::string & name, size_t chan ) +double bladerf_source_c::set_gain( double gain, const std::string & name, size_t chan) { - int ret = 0; - - if( name == "LNA" ) { - bladerf_lna_gain g; - - if ( gain >= 6.0f ) - g = BLADERF_LNA_GAIN_MAX; - else if ( gain >= 3.0f ) - g = BLADERF_LNA_GAIN_MID; - else /* gain < 3.0f */ - g = BLADERF_LNA_GAIN_BYPASS; - - ret = bladerf_set_lna_gain( _dev.get(), g ); - } else if( name == "VGA1" ) { - ret = bladerf_set_rxvga1( _dev.get(), (int)gain ); - } else if( name == "VGA2" ) { - ret = bladerf_set_rxvga2( _dev.get(), (int)gain ); - } else { - throw std::runtime_error( std::string(__FUNCTION__) + " " + - "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: " + - std::string(bladerf_strerror(ret)) ); - } - - return get_gain( name, chan ); + return bladerf_common::set_gain(gain, name, chan); } double bladerf_source_c::get_gain( size_t chan ) { - /* TODO: This is an overall system gain that has to be set */ - return get_gain( "LNA", chan ); /* we use only LNA here for now */ + return bladerf_common::get_gain(chan); } double bladerf_source_c::get_gain( const std::string & name, size_t chan ) { - int g; - int ret = 0; - - if( name == "LNA" ) { - bladerf_lna_gain 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.get(), &g ); - } else if( name == "VGA2" ) { - ret = bladerf_get_rxvga2( _dev.get(), &g ); - } else { - throw std::runtime_error( std::string(__FUNCTION__) + " " + - "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: " + - std::string(bladerf_strerror(ret)) ); - } - - return (double)g; + return bladerf_common::get_gain(name, chan); } double bladerf_source_c::set_bb_gain( double gain, size_t chan ) { - osmosdr::gain_range_t vga1_gains = get_gain_range( "VGA1", chan ); - osmosdr::gain_range_t vga2_gains = get_gain_range( "VGA2", chan ); - - // Gain partitioning from: - // http://www.limemicro.com/download/FAQ_v1.0r10.pdf part 5.18 - - // So: first maximize VGA1 gain, then VGA2 - - if ( gain > vga1_gains.stop() + vga2_gains.start() ) - { - double clip_gain = vga2_gains.clip( gain - vga1_gains.stop(), true ); - - gain = set_gain(vga1_gains.stop(), "VGA1", chan) + set_gain(clip_gain, "VGA2", chan); - } - else - { - double clip_gain = vga1_gains.clip( gain - vga2_gains.start(), true ); - - gain = set_gain(clip_gain , "VGA1", chan) + set_gain(vga2_gains.start(), "VGA2", chan); - } - - return gain; + return bladerf_common::set_bb_gain(gain, chan); } std::vector< std::string > bladerf_source_c::get_antennas( size_t chan ) diff --git a/lib/bladerf/bladerf_source_c.h b/lib/bladerf/bladerf_source_c.h index 131b5ed..d7e8ad5 100644 --- a/lib/bladerf/bladerf_source_c.h +++ b/lib/bladerf/bladerf_source_c.h @@ -81,9 +81,10 @@ public: double set_sample_rate( double rate ); double get_sample_rate( void ); - osmosdr::freq_range_t get_freq_range( size_t chan = 0 ); - double set_center_freq( double freq, size_t chan = 0 ); - double get_center_freq( size_t chan = 0 ); + osmosdr::freq_range_t get_freq_range(size_t chan = 0); + double set_center_freq(double freq, size_t chan = 0); + double get_center_freq(size_t chan = 0); + double set_freq_corr( double ppm, size_t chan = 0 ); double get_freq_corr( size_t chan = 0 ); @@ -118,7 +119,6 @@ public: std::vector get_clock_sources(const size_t mboard); private: - osmosdr::gain_range_t _lna_range; }; #endif /* INCLUDED_BLADERF_SOURCE_C_H */