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
|
@ -21,12 +21,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|||
MAIN_TMPL = """\
|
||||
<?xml version="1.0"?>
|
||||
<block>
|
||||
<name>$(title) $sourk.title()</name>
|
||||
<key>$(prefix)_$(sourk)_c</key>
|
||||
<category>Sources</category>
|
||||
<throttle>1</throttle>
|
||||
<import>import osmosdr</import>
|
||||
<make>osmosdr.$(sourk)_c( args="nchan=" + str(\$nchan) + " " + \$args )
|
||||
<name>$(title) $sourk.title()</name>
|
||||
<key>$(prefix)_$(sourk)_c</key>
|
||||
<category>Sources</category>
|
||||
<throttle>1</throttle>
|
||||
<import>import osmosdr</import>
|
||||
<make>osmosdr.$(sourk)_c( args="nchan=" + str(\$nchan) + " " + \$args )
|
||||
self.\$(id).set_sample_rate(\$sample_rate)
|
||||
#for $n in range($max_nchan)
|
||||
\#if \$nchan() > $n
|
||||
|
@ -36,72 +36,74 @@ 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
|
||||
\#end if
|
||||
#end for
|
||||
</make>
|
||||
<callback>set_sample_rate(\$sample_rate)</callback>
|
||||
#for $n in range($max_nchan)
|
||||
<callback>set_center_freq(\$freq$(n), $n)</callback>
|
||||
<callback>set_freq_corr(\$corr$(n), $n)</callback>
|
||||
<callback>set_iq_balance_mode(\$iq_balance_mode$(n), $n)</callback>
|
||||
<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_antenna(\$ant$(n), $n)</callback>
|
||||
#end for
|
||||
<param>
|
||||
<name>$(dir.title())put Type</name>
|
||||
<key>type</key>
|
||||
<type>enum</type>
|
||||
<option>
|
||||
<name>Complex float32</name>
|
||||
<key>fc32</key>
|
||||
<opt>type:fc32</opt>
|
||||
</option>
|
||||
</param>
|
||||
<param>
|
||||
<name>Device Arguments</name>
|
||||
<key>args</key>
|
||||
<value></value>
|
||||
<type>string</type>
|
||||
<hide>
|
||||
\#if \$args()
|
||||
none
|
||||
\#else
|
||||
part
|
||||
\#end if
|
||||
</hide>
|
||||
</param>
|
||||
<param>
|
||||
<name>Num Channels</name>
|
||||
<key>nchan</key>
|
||||
<value>1</value>
|
||||
<type>int</type>
|
||||
#for $n in range(1, $max_nchan+1)
|
||||
<option>
|
||||
<name>$(n)</name>
|
||||
<key>$n</key>
|
||||
</option>
|
||||
#end for
|
||||
</param>
|
||||
<param>
|
||||
<name>Sample Rate (sps)</name>
|
||||
<key>sample_rate</key>
|
||||
<value>samp_rate</value>
|
||||
<type>real</type>
|
||||
</param>
|
||||
$params
|
||||
<check>$max_nchan >= \$nchan</check>
|
||||
<check>\$nchan > 0</check>
|
||||
<$sourk>
|
||||
<name>$dir</name>
|
||||
<type>\$type.type</type>
|
||||
<nports>\$nchan</nports>
|
||||
</$sourk>
|
||||
<doc>
|
||||
</make>
|
||||
<callback>set_sample_rate(\$sample_rate)</callback>
|
||||
#for $n in range($max_nchan)
|
||||
<callback>set_center_freq(\$freq$(n), $n)</callback>
|
||||
<callback>set_freq_corr(\$corr$(n), $n)</callback>
|
||||
<callback>set_iq_balance_mode(\$iq_balance_mode$(n), $n)</callback>
|
||||
<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>
|
||||
<name>$(dir.title())put Type</name>
|
||||
<key>type</key>
|
||||
<type>enum</type>
|
||||
<option>
|
||||
<name>Complex float32</name>
|
||||
<key>fc32</key>
|
||||
<opt>type:fc32</opt>
|
||||
</option>
|
||||
</param>
|
||||
<param>
|
||||
<name>Device Arguments</name>
|
||||
<key>args</key>
|
||||
<value></value>
|
||||
<type>string</type>
|
||||
<hide>
|
||||
\#if \$args()
|
||||
none
|
||||
\#else
|
||||
part
|
||||
\#end if
|
||||
</hide>
|
||||
</param>
|
||||
<param>
|
||||
<name>Num Channels</name>
|
||||
<key>nchan</key>
|
||||
<value>1</value>
|
||||
<type>int</type>
|
||||
#for $n in range(1, $max_nchan+1)
|
||||
<option>
|
||||
<name>$(n)</name>
|
||||
<key>$n</key>
|
||||
</option>
|
||||
#end for
|
||||
</param>
|
||||
<param>
|
||||
<name>Sample Rate (sps)</name>
|
||||
<key>sample_rate</key>
|
||||
<value>samp_rate</value>
|
||||
<type>real</type>
|
||||
</param>
|
||||
$params
|
||||
<check>$max_nchan >= \$nchan</check>
|
||||
<check>\$nchan > 0</check>
|
||||
<$sourk>
|
||||
<name>$dir</name>
|
||||
<type>\$type.type</type>
|
||||
<nports>\$nchan</nports>
|
||||
</$sourk>
|
||||
<doc>
|
||||
The OsmoSDR $sourk.title() block:
|
||||
|
||||
While primarily being developed for the OsmoSDR hardware, this block as well supports:
|
||||
|
@ -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.
|
||||
|
@ -180,125 +187,132 @@ See the OsmoSDR project page for more detailed documentation:
|
|||
http://sdr.osmocom.org/trac/
|
||||
http://sdr.osmocom.org/trac/wiki/rtl-sdr
|
||||
http://sdr.osmocom.org/trac/wiki/GrOsmoSDR
|
||||
</doc>
|
||||
</doc>
|
||||
</block>
|
||||
"""
|
||||
|
||||
PARAMS_TMPL = """
|
||||
<param>
|
||||
<name>Ch$(n): Frequency (Hz)</name>
|
||||
<key>freq$(n)</key>
|
||||
<value>100e6</value>
|
||||
<type>real</type>
|
||||
<hide>\#if \$nchan() > $n then 'none' else 'all'#</hide>
|
||||
</param>
|
||||
<param>
|
||||
<name>Ch$(n): Freq. Corr. (ppm)</name>
|
||||
<key>corr$(n)</key>
|
||||
<value>0</value>
|
||||
<type>real</type>
|
||||
<hide>\#if \$nchan() > $n then 'none' else 'all'#</hide>
|
||||
</param>
|
||||
<param>
|
||||
<name>Ch$(n): IQ Balance Mode</name>
|
||||
<key>iq_balance_mode$(n)</key>
|
||||
<value>0</value>
|
||||
<type>int</type>
|
||||
<hide>\#if \$nchan() > $n then 'none' else 'all'#</hide>
|
||||
<option>
|
||||
<name>Off</name>
|
||||
<key>0</key>
|
||||
</option>
|
||||
<option>
|
||||
<name>Manual</name>
|
||||
<key>1</key>
|
||||
</option>
|
||||
<option>
|
||||
<name>Automatic</name>
|
||||
<key>2</key>
|
||||
</option>
|
||||
</param>
|
||||
<param>
|
||||
<name>Ch$(n): Gain Mode</name>
|
||||
<key>gain_mode$(n)</key>
|
||||
<value>0</value>
|
||||
<type>int</type>
|
||||
<hide>\#if \$nchan() > $n then 'none' else 'all'#</hide>
|
||||
<option>
|
||||
<name>Manual</name>
|
||||
<key>0</key>
|
||||
</option>
|
||||
<option>
|
||||
<name>Automatic</name>
|
||||
<key>1</key>
|
||||
</option>
|
||||
</param>
|
||||
<param>
|
||||
<name>Ch$(n): RF Gain (dB)</name>
|
||||
<key>gain$(n)</key>
|
||||
<value>10</value>
|
||||
<type>real</type>
|
||||
<hide>\#if \$nchan() > $n then 'none' else 'all'#</hide>
|
||||
</param>
|
||||
<param>
|
||||
<name>Ch$(n): IF Gain (dB)</name>
|
||||
<key>if_gain$(n)</key>
|
||||
<value>24</value>
|
||||
<type>real</type>
|
||||
<hide>\#if \$nchan() > $n then 'none' else 'all'#</hide>
|
||||
</param>
|
||||
<param>
|
||||
<name>Ch$(n): Antenna</name>
|
||||
<key>ant$(n)</key>
|
||||
<value></value>
|
||||
<type>string</type>
|
||||
<hide>
|
||||
\#if not \$nchan() > $n
|
||||
all
|
||||
\#elif \$ant$(n)()
|
||||
none
|
||||
\#else
|
||||
part
|
||||
\#end if
|
||||
</hide>
|
||||
</param>
|
||||
<param>
|
||||
<name>Ch$(n): Frequency (Hz)</name>
|
||||
<key>freq$(n)</key>
|
||||
<value>100e6</value>
|
||||
<type>real</type>
|
||||
<hide>\#if \$nchan() > $n then 'none' else 'all'#</hide>
|
||||
</param>
|
||||
<param>
|
||||
<name>Ch$(n): Freq. Corr. (ppm)</name>
|
||||
<key>corr$(n)</key>
|
||||
<value>0</value>
|
||||
<type>real</type>
|
||||
<hide>\#if \$nchan() > $n then 'none' else 'all'#</hide>
|
||||
</param>
|
||||
<param>
|
||||
<name>Ch$(n): IQ Balance Mode</name>
|
||||
<key>iq_balance_mode$(n)</key>
|
||||
<value>0</value>
|
||||
<type>int</type>
|
||||
<hide>\#if \$nchan() > $n then 'none' else 'all'#</hide>
|
||||
<option>
|
||||
<name>Off</name>
|
||||
<key>0</key>
|
||||
</option>
|
||||
<option>
|
||||
<name>Manual</name>
|
||||
<key>1</key>
|
||||
</option>
|
||||
<option>
|
||||
<name>Automatic</name>
|
||||
<key>2</key>
|
||||
</option>
|
||||
</param>
|
||||
<param>
|
||||
<name>Ch$(n): Gain Mode</name>
|
||||
<key>gain_mode$(n)</key>
|
||||
<value>0</value>
|
||||
<type>int</type>
|
||||
<hide>\#if \$nchan() > $n then 'none' else 'all'#</hide>
|
||||
<option>
|
||||
<name>Manual</name>
|
||||
<key>0</key>
|
||||
</option>
|
||||
<option>
|
||||
<name>Automatic</name>
|
||||
<key>1</key>
|
||||
</option>
|
||||
</param>
|
||||
<param>
|
||||
<name>Ch$(n): RF Gain (dB)</name>
|
||||
<key>gain$(n)</key>
|
||||
<value>10</value>
|
||||
<type>real</type>
|
||||
<hide>\#if \$nchan() > $n then 'none' else 'all'#</hide>
|
||||
</param>
|
||||
<param>
|
||||
<name>Ch$(n): IF Gain (dB)</name>
|
||||
<key>if_gain$(n)</key>
|
||||
<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>
|
||||
<param>
|
||||
<name>Ch$(n): Antenna</name>
|
||||
<key>ant$(n)</key>
|
||||
<value></value>
|
||||
<type>string</type>
|
||||
<hide>
|
||||
\#if not \$nchan() > $n
|
||||
all
|
||||
\#elif \$ant$(n)()
|
||||
none
|
||||
\#else
|
||||
part
|
||||
\#end if
|
||||
</hide>
|
||||
</param>
|
||||
"""
|
||||
|
||||
def parse_tmpl(_tmpl, **kwargs):
|
||||
from Cheetah import Template
|
||||
return str(Template.Template(_tmpl, kwargs))
|
||||
from Cheetah import Template
|
||||
return str(Template.Template(_tmpl, kwargs))
|
||||
|
||||
max_num_channels = 5
|
||||
|
||||
import os.path
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
for file in sys.argv[1:]:
|
||||
head, tail = os.path.split(file)
|
||||
import sys
|
||||
for file in sys.argv[1:]:
|
||||
head, tail = os.path.split(file)
|
||||
|
||||
if tail.startswith('rtlsdr'):
|
||||
title = 'RTLSDR'
|
||||
prefix = 'rtlsdr'
|
||||
elif tail.startswith('osmosdr'):
|
||||
title = 'OsmoSDR'
|
||||
prefix = 'osmosdr'
|
||||
else: raise Exception, 'file %s has wrong syntax!'%tail
|
||||
if tail.startswith('rtlsdr'):
|
||||
title = 'RTLSDR'
|
||||
prefix = 'rtlsdr'
|
||||
elif tail.startswith('osmosdr'):
|
||||
title = 'OsmoSDR'
|
||||
prefix = 'osmosdr'
|
||||
else: raise Exception, 'file %s has wrong syntax!'%tail
|
||||
|
||||
if tail.endswith ('source_c.xml'):
|
||||
sourk = 'source'
|
||||
dir = 'out'
|
||||
elif tail.endswith ('sink_c.xml'):
|
||||
sourk = 'sink'
|
||||
dir = 'in'
|
||||
else: raise Exception, 'is %s a source or sink?'%file
|
||||
if tail.endswith ('source_c.xml'):
|
||||
sourk = 'source'
|
||||
dir = 'out'
|
||||
elif tail.endswith ('sink_c.xml'):
|
||||
sourk = 'sink'
|
||||
dir = 'in'
|
||||
else: raise Exception, 'is %s a source or sink?'%file
|
||||
|
||||
params = ''.join([parse_tmpl(PARAMS_TMPL, n=n) for n in range(max_num_channels)])
|
||||
open(file, 'w').write(parse_tmpl(MAIN_TMPL,
|
||||
max_nchan=max_num_channels,
|
||||
params=params,
|
||||
title=title,
|
||||
prefix=prefix,
|
||||
sourk=sourk,
|
||||
dir=dir,
|
||||
))
|
||||
params = ''.join([parse_tmpl(PARAMS_TMPL, n=n) for n in range(max_num_channels)])
|
||||
open(file, 'w').write(parse_tmpl(MAIN_TMPL,
|
||||
max_nchan=max_num_channels,
|
||||
params=params,
|
||||
title=title,
|
||||
prefix=prefix,
|
||||
sourk=sourk,
|
||||
dir=dir,
|
||||
))
|
||||
|
|
|
@ -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