diff options
author | Dimitri Stolnikov <horiz0n@gmx.net> | 2013-04-13 23:12:22 +0200 |
---|---|---|
committer | Dimitri Stolnikov <horiz0n@gmx.net> | 2013-04-13 23:12:22 +0200 |
commit | 448206b2d2a932d583c502a0ba0f55fd9ab1800b (patch) | |
tree | 860fb740ccb3b65ce58cfb91205d86ed34a1404d /lib | |
parent | 7b66bb860a9394c5f4989a9444d7f08eaa53aed9 (diff) |
hackrf: implement full control for RF/IF/BB gain stages
the following named gain stages are available:
RF: MGA-81563, switchable 0 or 14dB
IF: MAX2837 LNA, 0 to 40dB in 8dB steps
BB: MAX2837 VGA, 0 to 62dB in 2dB steps
Diffstat (limited to 'lib')
-rw-r--r-- | lib/hackrf/hackrf_source_c.cc | 148 | ||||
-rw-r--r-- | lib/hackrf/hackrf_source_c.h | 6 | ||||
-rw-r--r-- | lib/osmosdr_source_c_impl.cc | 16 | ||||
-rw-r--r-- | lib/osmosdr_source_c_impl.h | 1 | ||||
-rw-r--r-- | lib/osmosdr_src_iface.h | 12 |
5 files changed, 132 insertions, 51 deletions
diff --git a/lib/hackrf/hackrf_source_c.cc b/lib/hackrf/hackrf_source_c.cc index 0ded9f3..5543ea0 100644 --- a/lib/hackrf/hackrf_source_c.cc +++ b/lib/hackrf/hackrf_source_c.cc @@ -83,7 +83,9 @@ hackrf_source_c::hackrf_source_c (const std::string &args) _center_freq(0), _freq_corr(0), _auto_gain(false), - _if_gain(0), + _amp_gain(0), + _lna_gain(0), + _vga_gain(0), _skipped(0) { int ret; @@ -157,21 +159,17 @@ hackrf_source_c::hackrf_source_c (const std::string &args) << std::endl; } - ret = hackrf_sample_rate_set( _dev, 10000000 ); - if (ret != HACKRF_SUCCESS) - throw std::runtime_error("Failed to set default samplerate."); + set_sample_rate( 5000000 ); - ret = hackrf_set_amp_enable( _dev, 0 ); - if (ret != HACKRF_SUCCESS) - throw std::runtime_error("Failed to disable the RX amplifier."); + set_gain( 0 ); /* disable AMP gain stage */ hackrf_max2837_read( _dev, 8, &val ); val |= 0x3; /* enable LNA & VGA control over SPI */ hackrf_max2837_write( _dev, 8, val ); - set_if_gain( 24 ); /* preset to a reasonable default (non-GRC use case) */ + set_if_gain( 16 ); /* preset to a reasonable default (non-GRC use case) */ - set_gain( 16 ); /* preset to a reasonable default (non-GRC use case) */ + set_bb_gain( 20 ); /* preset to a reasonable default (non-GRC use case) */ _buf = (unsigned short **) malloc(_buf_num * sizeof(unsigned short *)); @@ -365,7 +363,7 @@ double hackrf_source_c::set_sample_rate(double rate) _sample_rate = rate; set_bandwidth( rate ); } else { - throw std::runtime_error( std::string( hackrf_error_name( (hackrf_error) ret ) ) ); + throw std::runtime_error( std::string( __FUNCTION__ ) ); } } @@ -398,7 +396,7 @@ double hackrf_source_c::set_center_freq( double freq, size_t chan ) if ( HACKRF_SUCCESS == ret ) { _center_freq = freq; } else { - throw std::runtime_error( std::string( hackrf_error_name( (hackrf_error) ret ) ) ); + throw std::runtime_error( std::string( __FUNCTION__ ) ); } } @@ -428,28 +426,33 @@ std::vector<std::string> hackrf_source_c::get_gain_names( size_t chan ) { std::vector< std::string > names; - names += "LNA"; + names += "RF"; names += "IF"; + names += "BB"; return names; } osmosdr::gain_range_t hackrf_source_c::get_gain_range( size_t chan ) { - osmosdr::gain_range_t range; - - range += osmosdr::range_t( 0, 40, 8 ); - - return range; + return get_gain_range( "RF", chan ); } osmosdr::gain_range_t hackrf_source_c::get_gain_range( const std::string & name, size_t chan ) { + if ( "RF" == name ) { + return osmosdr::gain_range_t( 0, 14, 14 ); + } + if ( "IF" == name ) { + return osmosdr::gain_range_t( 0, 40, 8 ); + } + + if ( "BB" == name ) { return osmosdr::gain_range_t( 0, 62, 2 ); } - return get_gain_range( chan ); + return osmosdr::gain_range_t(); } bool hackrf_source_c::set_gain_mode( bool automatic, size_t chan ) @@ -466,56 +469,65 @@ bool hackrf_source_c::get_gain_mode( size_t chan ) double hackrf_source_c::set_gain( double gain, size_t chan ) { - osmosdr::gain_range_t rf_gains = get_gain_range( chan ); + osmosdr::gain_range_t rf_gains = get_gain_range( "RF", chan ); if (_dev) { double clip_gain = rf_gains.clip( gain, true ); - double rel_gain = fabs( rf_gains.stop() - clip_gain ); std::map<double, int> reg_vals; reg_vals[ 0 ] = 0; - reg_vals[ 8 ] = 4; - reg_vals[ 16 ] = 2; - reg_vals[ 24 ] = 6; - reg_vals[ 32 ] = 3; - reg_vals[ 40 ] = 7; - - if ( reg_vals.count( rel_gain ) ) { - int value = reg_vals[ rel_gain ]; + reg_vals[ 14 ] = 1; -// std::cerr << "lna gain: " << rel_gain << " value: " << value << std::endl; - - uint16_t val; - hackrf_max2837_read( _dev, 1, &val ); - - val = (val & ~(7 << 2)) | ((value & 7) << 2); - - if ( hackrf_max2837_write( _dev, 1, val ) == HACKRF_SUCCESS ) - _gain = clip_gain; + if ( reg_vals.count( clip_gain ) ) { + int value = reg_vals[ clip_gain ]; +#if 0 + std::cerr << "amp gain: " << gain + << " clip_gain: " << clip_gain + << " value: " << value + << std::endl; +#endif + if ( hackrf_set_amp_enable( _dev, value ) == HACKRF_SUCCESS ) + _amp_gain = clip_gain; } } - return get_gain( chan ); + return _amp_gain; } double hackrf_source_c::set_gain( double gain, const std::string & name, size_t chan) { + if ( "RF" == name ) { + return set_gain( gain, chan ); + } + if ( "IF" == name ) { return set_if_gain( gain, chan ); } + if ( "BB" == name ) { + return set_bb_gain( gain, chan ); + } + return set_gain( gain, chan ); } double hackrf_source_c::get_gain( size_t chan ) { - return _gain; + return _amp_gain; } double hackrf_source_c::get_gain( const std::string & name, size_t chan ) { + if ( "RF" == name ) { + return get_gain( chan ); + } + if ( "IF" == name ) { - return _if_gain; + return _lna_gain; + } + + if ( "BB" == name ) { + return _vga_gain; } return get_gain( chan ); @@ -523,7 +535,45 @@ double hackrf_source_c::get_gain( const std::string & name, size_t chan ) double hackrf_source_c::set_if_gain(double gain, size_t chan) { - osmosdr::gain_range_t if_gains = get_gain_range( "IF", chan ); + osmosdr::gain_range_t rf_gains = get_gain_range( "IF", chan ); + + if (_dev) { + double clip_gain = rf_gains.clip( gain, true ); + double rel_gain = fabs( rf_gains.stop() - clip_gain ); + + std::map<double, int> reg_vals; + reg_vals[ 0 ] = 0; + reg_vals[ 8 ] = 4; + reg_vals[ 16 ] = 2; + reg_vals[ 24 ] = 6; + reg_vals[ 32 ] = 3; + reg_vals[ 40 ] = 7; + + if ( reg_vals.count( rel_gain ) ) { + int value = reg_vals[ rel_gain ]; +#if 0 + std::cerr << "lna gain: " << gain + << " clip_gain: " << clip_gain + << " rel_gain: " << rel_gain + << " value: " << value + << std::endl; +#endif + uint16_t val; + hackrf_max2837_read( _dev, 1, &val ); + + val = (val & ~(7 << 2)) | ((value & 7) << 2); + + if ( hackrf_max2837_write( _dev, 1, val ) == HACKRF_SUCCESS ) + _lna_gain = clip_gain; + } + } + + return _lna_gain; +} + +double hackrf_source_c::set_bb_gain( double gain, size_t chan ) +{ + osmosdr::gain_range_t if_gains = get_gain_range( "BB", chan ); if (_dev) { double clip_gain = if_gains.clip( gain, true ); @@ -536,20 +586,24 @@ double hackrf_source_c::set_if_gain(double gain, size_t chan) if ( reg_vals.count( rel_gain ) ) { int value = reg_vals[ rel_gain ]; - -// std::cerr << "vga gain: " << rel_gain << " value: " << value << std::endl; - +#if 0 + std::cerr << "vga gain: " << gain + << " clip_gain: " << clip_gain + << " rel_gain: " << rel_gain + << " value: " << value + << std::endl; +#endif uint16_t val; hackrf_max2837_read( _dev, 5, &val ); val = (val & ~0x1f) | (value & 0x1f); if ( hackrf_max2837_write( _dev, 5, val ) == HACKRF_SUCCESS ) - _if_gain = clip_gain; + _vga_gain = clip_gain; } } - return gain; + return _vga_gain; } std::vector< std::string > hackrf_source_c::get_antennas( size_t chan ) @@ -586,7 +640,7 @@ void hackrf_source_c::set_bandwidth( double bandwidth, size_t chan ) if ( HACKRF_SUCCESS == ret ) { _bandwidth = bw; } else { - throw std::runtime_error( std::string( hackrf_error_name( (hackrf_error) ret ) ) ); + throw std::runtime_error( std::string( __FUNCTION__ ) ); } } } diff --git a/lib/hackrf/hackrf_source_c.h b/lib/hackrf/hackrf_source_c.h index 8bdb0d3..ea14944 100644 --- a/lib/hackrf/hackrf_source_c.h +++ b/lib/hackrf/hackrf_source_c.h @@ -107,6 +107,7 @@ private: double get_gain( const std::string & name, size_t chan = 0 ); double set_if_gain( double gain, size_t chan = 0 ); + double set_bb_gain( double gain, size_t chan = 0 ); std::vector< std::string > get_antennas( size_t chan = 0 ); std::string set_antenna( const std::string & antenna, size_t chan = 0 ); @@ -145,8 +146,9 @@ private: double _center_freq; double _freq_corr; bool _auto_gain; - double _gain; - double _if_gain; + double _amp_gain; + double _lna_gain; + double _vga_gain; unsigned int _skipped; double _bandwidth; }; diff --git a/lib/osmosdr_source_c_impl.cc b/lib/osmosdr_source_c_impl.cc index b5e34e4..fcac3cb 100644 --- a/lib/osmosdr_source_c_impl.cc +++ b/lib/osmosdr_source_c_impl.cc @@ -541,7 +541,7 @@ double osmosdr_source_c_impl::get_gain( const std::string & name, size_t chan ) return 0; } -double osmosdr_source_c_impl::set_if_gain(double gain, size_t chan) +double osmosdr_source_c_impl::set_if_gain( double gain, size_t chan ) { size_t channel = 0; BOOST_FOREACH( osmosdr_src_iface *dev, _devs ) @@ -555,6 +555,20 @@ double osmosdr_source_c_impl::set_if_gain(double gain, size_t chan) return 0; } +double osmosdr_source_c_impl::set_bb_gain( double gain, size_t chan ) +{ + size_t channel = 0; + BOOST_FOREACH( osmosdr_src_iface *dev, _devs ) + for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++) + if ( chan == channel++ ) + if ( _if_gain[ chan ] != gain ) { + _if_gain[ chan ] = gain; + return dev->set_bb_gain( gain, dev_chan ); + } + + return 0; +} + std::vector< std::string > osmosdr_source_c_impl::get_antennas( size_t chan ) { size_t channel = 0; diff --git a/lib/osmosdr_source_c_impl.h b/lib/osmosdr_source_c_impl.h index 292ca90..92c8d38 100644 --- a/lib/osmosdr_source_c_impl.h +++ b/lib/osmosdr_source_c_impl.h @@ -57,6 +57,7 @@ public: double get_gain( const std::string & name, size_t chan = 0 ); double set_if_gain( double gain, size_t chan = 0 ); + double set_bb_gain( double gain, size_t chan = 0 ); std::vector< std::string > get_antennas( size_t chan = 0 ); std::string set_antenna( const std::string & antenna, size_t chan = 0 ); diff --git a/lib/osmosdr_src_iface.h b/lib/osmosdr_src_iface.h index 8169b3a..6c149f9 100644 --- a/lib/osmosdr_src_iface.h +++ b/lib/osmosdr_src_iface.h @@ -186,6 +186,16 @@ public: virtual double set_if_gain( double gain, size_t chan = 0 ) { return 0; } /*! + * Set the BB gain for the underlying radio hardware. + * This function will automatically distribute the desired gain value over + * available BB gain stages in an appropriate way and return the actual value. + * \param gain the gain in dB + * \param chan the channel index 0 to N-1 + * \return the actual gain in dB + */ + virtual double set_bb_gain( double gain, size_t chan = 0 ) { return 0; } + + /*! * Get the available antennas of the underlying radio hardware. * \param chan the channel index 0 to N-1 * \return a vector of strings containing the names of available antennas @@ -203,7 +213,7 @@ public: /*! * Get the actual underlying radio hardware antenna setting. * \param chan the channel index 0 to N-1 - * \return antenna the actual antenna's name + * \return the actual antenna's name */ virtual std::string get_antenna( size_t chan = 0 ) = 0; }; |