forked from sdr/gr-osmosdr
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
This commit is contained in:
parent
7b66bb860a
commit
448206b2d2
|
@ -36,6 +36,7 @@ self.\$(id).set_iq_balance_mode(\$iq_balance_mode$(n), $n)
|
|||
self.\$(id).set_gain_mode(\$gain_mode$(n), $n)
|
||||
self.\$(id).set_gain(\$gain$(n), $n)
|
||||
self.\$(id).set_if_gain(\$if_gain$(n), $n)
|
||||
self.\$(id).set_bb_gain(\$bb_gain$(n), $n)
|
||||
\#if \$ant$(n)()
|
||||
self.\$(id).set_antenna(\$ant$(n), $n)
|
||||
\#end if
|
||||
|
@ -50,6 +51,7 @@ self.\$(id).set_antenna(\$ant$(n), $n)
|
|||
<callback>set_gain_mode(\$gain_mode$(n), $n)</callback>
|
||||
<callback>set_gain(\$gain$(n), $n)</callback>
|
||||
<callback>set_if_gain(\$if_gain$(n), $n)</callback>
|
||||
<callback>set_bb_gain(\$bb_gain$(n), $n)</callback>
|
||||
<callback>set_antenna(\$ant$(n), $n)</callback>
|
||||
#end for
|
||||
<param>
|
||||
|
@ -155,23 +157,28 @@ The frequency correction factor in parts per million (ppm). Set to 0 if unknown.
|
|||
|
||||
IQ Balance Mode:
|
||||
Controls the behavior of software IQ imbalance corrrection.
|
||||
Off: Disable correction algorithm (pass through)
|
||||
Manual: Keep last estimated correction when switched from Automatic to Manual
|
||||
Automatic: Find the best solution to compensate for image signals.
|
||||
Off: Disable correction algorithm (pass through).
|
||||
Manual: Keep last estimated correction when switched from Automatic to Manual.
|
||||
Automatic: Periodicallly find the best solution to compensate for image signals.
|
||||
|
||||
This functionality depends on http://cgit.osmocom.org/cgit/gr-iqbal/
|
||||
|
||||
Gain Mode:
|
||||
Chooses between the manual (default) and automatic gain mode where appropriate.
|
||||
Currently, only rtlsdr devices support automatic gain mode.
|
||||
To allow manual control of RF/IF/BB gain stages, manual gain mode must be configured.
|
||||
Currently, only RTL-SDR devices support automatic gain mode.
|
||||
|
||||
RF Gain:
|
||||
Overall RF gain of the receiving device. For the new gain value to be applied, the manual gain mode must be enabled first.
|
||||
Overall RF gain of the receiving device.
|
||||
|
||||
IF Gain:
|
||||
Overall IF gain of the receiving device. For the new gain value to be applied, the manual gain mode must be enabled first.
|
||||
Overall intermediate frequency gain of the receiving device.
|
||||
This setting has only effect for RTL-SDR and OsmoSDR devices with E4000 tuners. Observations lead to a reasonable gain range from 15 to 30dB.
|
||||
|
||||
BB Gain:
|
||||
Overall baseband gain of the receiving device.
|
||||
This setting has only effect for HackRF Jawbreaker. Observations lead to a reasonable gain range from 15 to 30dB.
|
||||
|
||||
Antenna:
|
||||
For devices with only one antenna, this may be left blank.
|
||||
Otherwise, the user should specify one of the possible antenna choices.
|
||||
|
@ -243,7 +250,14 @@ PARAMS_TMPL = """
|
|||
<param>
|
||||
<name>Ch$(n): IF Gain (dB)</name>
|
||||
<key>if_gain$(n)</key>
|
||||
<value>24</value>
|
||||
<value>20</value>
|
||||
<type>real</type>
|
||||
<hide>\#if \$nchan() > $n then 'none' else 'all'#</hide>
|
||||
</param>
|
||||
<param>
|
||||
<name>Ch$(n): BB Gain (dB)</name>
|
||||
<key>bb_gain$(n)</key>
|
||||
<value>20</value>
|
||||
<type>real</type>
|
||||
<hide>\#if \$nchan() > $n then 'none' else 'all'#</hide>
|
||||
</param>
|
||||
|
|
|
@ -207,6 +207,16 @@ public:
|
|||
*/
|
||||
virtual double set_if_gain( double gain, size_t chan = 0 ) = 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 ) = 0;
|
||||
|
||||
/*!
|
||||
* Get the available antennas of the underlying radio hardware.
|
||||
* \param chan the channel index 0 to N-1
|
||||
|
@ -226,7 +236,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;
|
||||
|
||||
|
|
|
@ -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,7 +469,73 @@ 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 );
|
||||
|
||||
std::map<double, int> reg_vals;
|
||||
reg_vals[ 0 ] = 0;
|
||||
reg_vals[ 14 ] = 1;
|
||||
|
||||
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 _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 _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 _lna_gain;
|
||||
}
|
||||
|
||||
if ( "BB" == name ) {
|
||||
return _vga_gain;
|
||||
}
|
||||
|
||||
return get_gain( chan );
|
||||
}
|
||||
|
||||
double hackrf_source_c::set_if_gain(double gain, size_t chan)
|
||||
{
|
||||
osmosdr::gain_range_t rf_gains = get_gain_range( "IF", chan );
|
||||
|
||||
if (_dev) {
|
||||
double clip_gain = rf_gains.clip( gain, true );
|
||||
|
@ -482,48 +551,29 @@ double hackrf_source_c::set_gain( double gain, size_t chan )
|
|||
|
||||
if ( reg_vals.count( rel_gain ) ) {
|
||||
int value = reg_vals[ rel_gain ];
|
||||
|
||||
// std::cerr << "lna gain: " << rel_gain << " value: " << value << std::endl;
|
||||
|
||||
#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 )
|
||||
_gain = clip_gain;
|
||||
_lna_gain = clip_gain;
|
||||
}
|
||||
}
|
||||
|
||||
return get_gain( chan );
|
||||
return _lna_gain;
|
||||
}
|
||||
|
||||
double hackrf_source_c::set_gain( double gain, const std::string & name, size_t chan)
|
||||
double hackrf_source_c::set_bb_gain( double gain, size_t chan )
|
||||
{
|
||||
if ( "IF" == name ) {
|
||||
return set_if_gain( gain, chan );
|
||||
}
|
||||
|
||||
return set_gain( gain, chan );
|
||||
}
|
||||
|
||||
double hackrf_source_c::get_gain( size_t chan )
|
||||
{
|
||||
return _gain;
|
||||
}
|
||||
|
||||
double hackrf_source_c::get_gain( const std::string & name, size_t chan )
|
||||
{
|
||||
if ( "IF" == name ) {
|
||||
return _if_gain;
|
||||
}
|
||||
|
||||
return get_gain( 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 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__ ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -185,6 +185,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
|
||||
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue