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 | |
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
-rw-r--r-- | grc/gen_osmosdr_blocks.py | 378 | ||||
-rw-r--r-- | include/osmosdr/osmosdr_source_c.h | 12 | ||||
-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 |
7 files changed, 339 insertions, 234 deletions
diff --git a/grc/gen_osmosdr_blocks.py b/grc/gen_osmosdr_blocks.py index 0cd5ffe..76231aa 100644 --- a/grc/gen_osmosdr_blocks.py +++ b/grc/gen_osmosdr_blocks.py @@ -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) - - 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 - - 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, - )) + 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.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, + )) diff --git a/include/osmosdr/osmosdr_source_c.h b/include/osmosdr/osmosdr_source_c.h index 453f592..dd4505c 100644 --- a/include/osmosdr/osmosdr_source_c.h +++ b/include/osmosdr/osmosdr_source_c.h @@ -208,6 +208,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 * \return a vector of strings containing the names of available antennas @@ -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; 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; }; |