forked from sdr/gr-osmosdr
bladerf: initial support for new bladeRF hardware
Relies on some new libbladeRF API calls. Has been tested with gqrx on new bladeRF hardware (as a source) but have not yet tested sink, or existing bladeRF hardware.
This commit is contained in:
parent
0b5c3911f7
commit
56da34f7f2
|
@ -48,6 +48,10 @@ using namespace boost::assign;
|
|||
boost::mutex bladerf_common::_devs_mutex;
|
||||
std::list<boost::weak_ptr<struct bladerf> > 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<boost::mutex> lock(_devs_mutex);
|
||||
|
||||
|
@ -127,6 +132,18 @@ bladerf_sptr bladerf_common::open(const std::string &device_name)
|
|||
|
||||
_devs.push_back(boost::weak_ptr<struct bladerf>(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,6 +209,8 @@ 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;
|
||||
|
@ -198,7 +218,21 @@ bool bladerf_common::start(bladerf_module module)
|
|||
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<std::string>(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<std::string>(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<double> 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<std::string>(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<std::string>(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<std::string> 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<double> &offset, size_t chan)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
|
@ -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<std::string> 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<double> &offset, size_t chan);
|
||||
int set_iq_balance(bladerf_module module, const std::complex<double> &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;
|
||||
|
|
|
@ -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<std::string> 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()
|
||||
|
@ -318,43 +310,17 @@ double bladerf_sink_c::get_sample_rate()
|
|||
|
||||
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)
|
||||
{
|
||||
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<std::string>(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)
|
||||
{
|
||||
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<std::string> 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 )
|
||||
|
|
|
@ -92,6 +92,7 @@ public:
|
|||
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 );
|
||||
|
||||
|
|
|
@ -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<std::string> 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()
|
||||
|
@ -218,43 +208,17 @@ double bladerf_source_c::get_sample_rate()
|
|||
|
||||
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)
|
||||
{
|
||||
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<std::string>(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)
|
||||
{
|
||||
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<std::string> 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)
|
||||
{
|
||||
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 )
|
||||
|
|
|
@ -84,6 +84,7 @@ public:
|
|||
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<std::string> get_clock_sources(const size_t mboard);
|
||||
|
||||
private:
|
||||
osmosdr::gain_range_t _lna_range;
|
||||
};
|
||||
|
||||
#endif /* INCLUDED_BLADERF_SOURCE_C_H */
|
||||
|
|
Loading…
Reference in New Issue