diff --git a/grc/gen_osmosdr_blocks.py b/grc/gen_osmosdr_blocks.py
index 8e9fbc2..d5631ca 100644
--- a/grc/gen_osmosdr_blocks.py
+++ b/grc/gen_osmosdr_blocks.py
@@ -26,7 +26,7 @@ MAIN_TMPL = """\
Sources
1
import osmosdr
- osmosdr.$(sourk)_c( args="nchan=" + str(\$nchan) + " " + \$args )
+ osmosdr.$(sourk)_c( args="nchan=" + str(\$nchan) + " " + \$args )
self.\$(id).set_sample_rate(\$sample_rate)
#for $n in range($max_nchan)
\#if \$nchan() > $n
@@ -34,18 +34,20 @@ self.\$(id).set_center_freq(\$freq$(n), $n)
self.\$(id).set_freq_corr(\$corr$(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)
\#if \$ant$(n)()
self.\$(id).set_antenna(\$ant$(n), $n)
\#end if
\#end if
#end for
-
+
set_sample_rate(\$sample_rate)
#for $n in range($max_nchan)
set_center_freq(\$freq$(n), $n)
set_freq_corr(\$corr$(n), $n)
set_gain_mode(\$gain_mode$(n), $n)
set_gain(\$gain$(n), $n)
+ set_if_gain(\$if_gain$(n), $n)
set_antenna(\$ant$(n), $n)
#end for
@@ -100,18 +102,15 @@ self.\$(id).set_antenna(\$ant$(n), $n)
The OsmoSDR $sourk.title() block:
-While primarily being developed for the OsmoSDR hardware, this block also
-supports the FunCube Dongle, Ettus UHD, rtl-sdr radios and cfile source.
-By using the OsmoSDR block you can take advantage of a common software api in
-your application(s) independent of the underlying radio hardware.
+While primarily being developed for the OsmoSDR hardware, this block also supports the FunCube Dongle, Ettus UHD, rtl-sdr radios and cfile source.
+By using the OsmoSDR block you can take advantage of a common software api in your application(s) independent of the underlying radio hardware.
Output Type:
This parameter controls the data type of the stream in gnuradio.
Device Arguments:
The device argument is a delimited string used to locate devices on your system.
-Use the device id or name (if applicable) to specify a certain device or list
-of devices. If left blank, the first device found will be used.
+Use the device id or name (if applicable) to specify a certain device or list of devices. If left blank, the first device found will be used.
Examples (some arguments may be optional):
fcd=0
@@ -133,14 +132,18 @@ The center frequency is the overall frequency of the RF chain.
Freq. Corr.:
The frequency correction factor in parts per million (ppm). Leave 0 if unknown.
-Gain:
-Overall gain of the device's signal path. For the new gain value to be applied,
-the manual gain mode must be enabled first.
-
Gain Mode:
Chooses between the manual (default) and automatic gain mode where appropriate.
Currently, only rtlsdr devices support automatic gain mode.
+Gain:
+Overall gain of the device's signal path. For the new gain value to be applied, the manual gain mode must be enabled first.
+
+IF Gain:
+Overall IF gain of the device's signal path. For the new gain value to be applied, the manual gain mode must be enabled first.
+This setting has only effect for rtl-sdr and OsmoSDR devices with E4000 tuners.
+Observations lead to an useful 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.
@@ -157,7 +160,7 @@ PARAMS_TMPL = """
Ch$(n): Frequency (Hz)
freq$(n)
- 0
+ 100e6
real
\#if \$nchan() > $n then 'none' else 'all'#
@@ -168,13 +171,6 @@ PARAMS_TMPL = """
real
\#if \$nchan() > $n then 'none' else 'all'#
-
- Ch$(n): Gain (dB)
- gain$(n)
- 0
- real
- \#if \$nchan() > $n then 'none' else 'all'#
-
Ch$(n): Gain Mode
gain_mode$(n)
@@ -190,6 +186,20 @@ PARAMS_TMPL = """
1
+
+ Ch$(n): Gain (dB)
+ gain$(n)
+ 10
+ real
+ \#if \$nchan() > $n then 'none' else 'all'#
+
+
+ Ch$(n): IF Gain (dB)
+ if_gain$(n)
+ 20
+ real
+ \#if \$nchan() > $n then 'none' else 'all'#
+
Ch$(n): Antenna
ant$(n)
diff --git a/include/osmosdr/osmosdr_source_c.h b/include/osmosdr/osmosdr_source_c.h
index 425902d..55a9a0f 100644
--- a/include/osmosdr/osmosdr_source_c.h
+++ b/include/osmosdr/osmosdr_source_c.h
@@ -197,6 +197,16 @@ public:
*/
virtual double get_gain( const std::string & name, size_t chan = 0 ) = 0;
+ /*!
+ * Set the IF gain for the underlying radio hardware.
+ * This function will automatically distribute the desired gain value over
+ * available IF 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_if_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
diff --git a/lib/osmosdr/osmosdr_src_c.cc b/lib/osmosdr/osmosdr_src_c.cc
index bba0550..68c4a27 100644
--- a/lib/osmosdr/osmosdr_src_c.cc
+++ b/lib/osmosdr/osmosdr_src_c.cc
@@ -131,6 +131,8 @@ osmosdr_src_c::osmosdr_src_c (const std::string &args)
if (ret < 0)
throw std::runtime_error("Failed to reset usb buffers.");
+ set_if_gain( 24 ); /* preset to a reasonable default (non-GRC use case) */
+
_buf = (unsigned short **) malloc(_buf_num * sizeof(unsigned short *));
for(unsigned int i = 0; i < _buf_num; ++i)
@@ -410,61 +412,9 @@ bool osmosdr_src_c::get_gain_mode( size_t chan )
double osmosdr_src_c::set_gain( double gain, size_t chan )
{
osmosdr::gain_range_t rf_gains = osmosdr_src_c::get_gain_range( chan );
- std::vector< osmosdr::gain_range_t > if_gains;
- if_gains += osmosdr::gain_range_t(-3, 6, 9);
- if_gains += osmosdr::gain_range_t(0, 9, 3);
- if_gains += osmosdr::gain_range_t(0, 9, 3);
- if_gains += osmosdr::gain_range_t(0, 2, 1);
- if_gains += osmosdr::gain_range_t(3, 15, 3);
- if_gains += osmosdr::gain_range_t(3, 15, 3);
-
- double rf_gain = rf_gains.clip(gain);
- double missing_gain = gain - rf_gain;
-
- std::map< int, double > gains;
-
- /* initialize with min gains */
- for (unsigned int i = 0; i < if_gains.size(); i++) {
- gains[ i + 1 ] = if_gains[ i ].start();
- }
-
- for (int i = if_gains.size() - 1; i >= 0; i--) {
- osmosdr::gain_range_t range = if_gains[ i ];
-
- double error = missing_gain;
-
- for( double g = range.start(); g <= range.stop(); g += range.step() ) {
-
- double sum = 0;
- for (int j = 0; j < int(gains.size()); j++) {
- if ( i == j )
- sum += g;
- else
- sum += gains[ j + 1 ];
- }
-
- double err = abs(missing_gain - sum);
- if (err < error) {
- error = err;
- gains[ i + 1 ] = g;
- }
- }
- }
-#if 0
- std::cerr << missing_gain << " => "; double sum = 0;
- for (unsigned int i = 0; i < gains.size(); i++) {
- sum += gains[ i + 1 ];
- std::cerr << gains[ i + 1 ] << " ";
- }
- std::cerr << " = " << sum << std::endl;
-#endif
if (_dev) {
- osmosdr_set_tuner_gain( _dev, int(rf_gain * 10.0) );
-
- for (unsigned int stage = 1; stage <= gains.size(); stage++) {
- osmosdr_set_tuner_if_gain( _dev, stage, int(gains[ stage ] * 10.0));
- }
+ osmosdr_set_tuner_gain( _dev, int(rf_gains.clip(gain) * 10.0) );
}
return get_gain( chan );
@@ -488,6 +438,63 @@ double osmosdr_src_c::get_gain( const std::string & name, size_t chan )
return get_gain( chan );
}
+double osmosdr_src_c::set_if_gain(double gain, size_t chan)
+{
+ std::vector< osmosdr::gain_range_t > if_gains;
+
+ if_gains += osmosdr::gain_range_t(-3, 6, 9);
+ if_gains += osmosdr::gain_range_t(0, 9, 3);
+ if_gains += osmosdr::gain_range_t(0, 9, 3);
+ if_gains += osmosdr::gain_range_t(0, 2, 1);
+ if_gains += osmosdr::gain_range_t(3, 15, 3);
+ if_gains += osmosdr::gain_range_t(3, 15, 3);
+
+ std::map< int, double > gains;
+
+ /* initialize with min gains */
+ for (unsigned int i = 0; i < if_gains.size(); i++) {
+ gains[ i + 1 ] = if_gains[ i ].start();
+ }
+
+ for (int i = if_gains.size() - 1; i >= 0; i--) {
+ osmosdr::gain_range_t range = if_gains[ i ];
+
+ double error = gain;
+
+ for( double g = range.start(); g <= range.stop(); g += range.step() ) {
+
+ double sum = 0;
+ for (int j = 0; j < int(gains.size()); j++) {
+ if ( i == j )
+ sum += g;
+ else
+ sum += gains[ j + 1 ];
+ }
+
+ double err = abs(gain - sum);
+ if (err < error) {
+ error = err;
+ gains[ i + 1 ] = g;
+ }
+ }
+ }
+#if 0
+ std::cerr << gain << " => "; double sum = 0;
+ for (unsigned int i = 0; i < gains.size(); i++) {
+ sum += gains[ i + 1 ];
+ std::cerr << gains[ i + 1 ] << " ";
+ }
+ std::cerr << " = " << sum << std::endl;
+#endif
+ if (_dev) {
+ for (unsigned int stage = 1; stage <= gains.size(); stage++) {
+ osmosdr_set_tuner_if_gain( _dev, stage, int(gains[ stage ] * 10.0));
+ }
+ }
+
+ return gain;
+}
+
std::vector< std::string > osmosdr_src_c::get_antennas( size_t chan )
{
std::vector< std::string > antennas;
diff --git a/lib/osmosdr/osmosdr_src_c.h b/lib/osmosdr/osmosdr_src_c.h
index 227ccae..9156454 100644
--- a/lib/osmosdr/osmosdr_src_c.h
+++ b/lib/osmosdr/osmosdr_src_c.h
@@ -105,6 +105,8 @@ private:
double get_gain( size_t chan = 0 );
double get_gain( const std::string & name, size_t chan = 0 );
+ double set_if_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 );
std::string get_antenna( size_t chan = 0 );
diff --git a/lib/osmosdr_source_c_impl.cc b/lib/osmosdr_source_c_impl.cc
index 4c5c3f9..5eec5c8 100644
--- a/lib/osmosdr_source_c_impl.cc
+++ b/lib/osmosdr_source_c_impl.cc
@@ -227,7 +227,7 @@ double osmosdr_source_c_impl::set_sample_rate(double rate)
if (_sample_rate != rate) {
BOOST_FOREACH( osmosdr_src_iface *dev, _devs )
- sample_rate = dev->set_sample_rate(rate);
+ sample_rate = dev->set_sample_rate(rate);
_sample_rate = sample_rate;
}
@@ -382,7 +382,7 @@ double osmosdr_source_c_impl::set_gain( double gain, const std::string & name, s
BOOST_FOREACH( osmosdr_src_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
- return dev->set_gain( gain, name, dev_chan );
+ return dev->set_gain( gain, name, dev_chan );
return 0;
}
@@ -409,6 +409,20 @@ 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)
+{
+ 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_if_gain( gain, dev_chan );
+ }
+
+ return 0;
+}
+
std::vector< std::string > osmosdr_source_c_impl::get_antennas( size_t chan )
{
size_t channel = 0;
@@ -427,8 +441,8 @@ std::string osmosdr_source_c_impl::set_antenna( const std::string & antenna, siz
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
if ( _antenna[ chan ] != antenna ) {
- _antenna[ chan ] = antenna;
- return dev->set_antenna( antenna, dev_chan );
+ _antenna[ chan ] = antenna;
+ return dev->set_antenna( antenna, dev_chan );
}
return "";
diff --git a/lib/osmosdr_source_c_impl.h b/lib/osmosdr_source_c_impl.h
index 1bdf6b3..a34bf3b 100644
--- a/lib/osmosdr_source_c_impl.h
+++ b/lib/osmosdr_source_c_impl.h
@@ -51,6 +51,8 @@ public:
double get_gain( size_t chan = 0 );
double get_gain( const std::string & name, size_t chan = 0 );
+ double set_if_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 );
std::string get_antenna( size_t chan = 0 );
@@ -67,6 +69,7 @@ private:
std::map< size_t, double > _freq_corr;
std::map< size_t, bool > _gain_mode;
std::map< size_t, double > _gain;
+ std::map< size_t, double > _if_gain;
std::map< size_t, std::string > _antenna;
std::vector< osmosdr_src_iface * > _devs;
};
diff --git a/lib/osmosdr_src_iface.h b/lib/osmosdr_src_iface.h
index b9ab9f8..a169e0d 100644
--- a/lib/osmosdr_src_iface.h
+++ b/lib/osmosdr_src_iface.h
@@ -175,6 +175,16 @@ public:
*/
virtual double get_gain( const std::string & name, size_t chan = 0 ) = 0;
+ /*!
+ * Set the IF gain for the underlying radio hardware.
+ * This function will automatically distribute the desired gain value over
+ * available IF 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_if_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
diff --git a/lib/rtl/rtl_source_c.cc b/lib/rtl/rtl_source_c.cc
index 3a16bff..18db321 100644
--- a/lib/rtl/rtl_source_c.cc
+++ b/lib/rtl/rtl_source_c.cc
@@ -158,6 +158,8 @@ rtl_source_c::rtl_source_c (const std::string &args)
if (ret < 0)
throw std::runtime_error("Failed to reset usb buffers.");
+ set_if_gain( 24 ); /* preset to a reasonable default (non-GRC use case) */
+
_buf = (unsigned short **) malloc(_buf_num * sizeof(unsigned short *));
for(unsigned int i = 0; i < _buf_num; ++i)
@@ -441,61 +443,9 @@ bool rtl_source_c::get_gain_mode( size_t chan )
double rtl_source_c::set_gain( double gain, size_t chan )
{
osmosdr::gain_range_t rf_gains = rtl_source_c::get_gain_range( chan );
- std::vector< osmosdr::gain_range_t > if_gains;
- if_gains += osmosdr::gain_range_t(-3, 6, 9);
- if_gains += osmosdr::gain_range_t(0, 9, 3);
- if_gains += osmosdr::gain_range_t(0, 9, 3);
- if_gains += osmosdr::gain_range_t(0, 2, 1);
- if_gains += osmosdr::gain_range_t(3, 15, 3);
- if_gains += osmosdr::gain_range_t(3, 15, 3);
-
- double rf_gain = rf_gains.clip(gain);
- double missing_gain = gain - rf_gain;
-
- std::map< int, double > gains;
-
- /* initialize with min gains */
- for (unsigned int i = 0; i < if_gains.size(); i++) {
- gains[ i + 1 ] = if_gains[ i ].start();
- }
-
- for (int i = if_gains.size() - 1; i >= 0; i--) {
- osmosdr::gain_range_t range = if_gains[ i ];
-
- double error = missing_gain;
-
- for( double g = range.start(); g <= range.stop(); g += range.step() ) {
-
- double sum = 0;
- for (int j = 0; j < int(gains.size()); j++) {
- if ( i == j )
- sum += g;
- else
- sum += gains[ j + 1 ];
- }
-
- double err = abs(missing_gain - sum);
- if (err < error) {
- error = err;
- gains[ i + 1 ] = g;
- }
- }
- }
-#if 0
- std::cerr << missing_gain << " => "; double sum = 0;
- for (unsigned int i = 0; i < gains.size(); i++) {
- sum += gains[ i + 1 ];
- std::cerr << gains[ i + 1 ] << " ";
- }
- std::cerr << " = " << sum << std::endl;
-#endif
if (_dev) {
- rtlsdr_set_tuner_gain( _dev, int(rf_gain * 10.0) );
-
- for (unsigned int stage = 1; stage <= gains.size(); stage++) {
- rtlsdr_set_tuner_if_gain( _dev, stage, int(gains[ stage ] * 10.0));
- }
+ rtlsdr_set_tuner_gain( _dev, int(rf_gains.clip(gain) * 10.0) );
}
return get_gain( chan );
@@ -519,6 +469,63 @@ double rtl_source_c::get_gain( const std::string & name, size_t chan )
return get_gain( chan );
}
+double rtl_source_c::set_if_gain(double gain, size_t chan)
+{
+ std::vector< osmosdr::gain_range_t > if_gains;
+
+ if_gains += osmosdr::gain_range_t(-3, 6, 9);
+ if_gains += osmosdr::gain_range_t(0, 9, 3);
+ if_gains += osmosdr::gain_range_t(0, 9, 3);
+ if_gains += osmosdr::gain_range_t(0, 2, 1);
+ if_gains += osmosdr::gain_range_t(3, 15, 3);
+ if_gains += osmosdr::gain_range_t(3, 15, 3);
+
+ std::map< int, double > gains;
+
+ /* initialize with min gains */
+ for (unsigned int i = 0; i < if_gains.size(); i++) {
+ gains[ i + 1 ] = if_gains[ i ].start();
+ }
+
+ for (int i = if_gains.size() - 1; i >= 0; i--) {
+ osmosdr::gain_range_t range = if_gains[ i ];
+
+ double error = gain;
+
+ for( double g = range.start(); g <= range.stop(); g += range.step() ) {
+
+ double sum = 0;
+ for (int j = 0; j < int(gains.size()); j++) {
+ if ( i == j )
+ sum += g;
+ else
+ sum += gains[ j + 1 ];
+ }
+
+ double err = abs(gain - sum);
+ if (err < error) {
+ error = err;
+ gains[ i + 1 ] = g;
+ }
+ }
+ }
+#if 0
+ std::cerr << gain << " => "; double sum = 0;
+ for (unsigned int i = 0; i < gains.size(); i++) {
+ sum += gains[ i + 1 ];
+ std::cerr << gains[ i + 1 ] << " ";
+ }
+ std::cerr << " = " << sum << std::endl;
+#endif
+ if (_dev) {
+ for (unsigned int stage = 1; stage <= gains.size(); stage++) {
+ rtlsdr_set_tuner_if_gain( _dev, stage, int(gains[ stage ] * 10.0));
+ }
+ }
+
+ return gain;
+}
+
std::vector< std::string > rtl_source_c::get_antennas( size_t chan )
{
std::vector< std::string > antennas;
diff --git a/lib/rtl/rtl_source_c.h b/lib/rtl/rtl_source_c.h
index 70dcf0e..5f4ccdd 100644
--- a/lib/rtl/rtl_source_c.h
+++ b/lib/rtl/rtl_source_c.h
@@ -106,6 +106,8 @@ public:
double get_gain( size_t chan = 0 );
double get_gain( const std::string & name, size_t chan = 0 );
+ double set_if_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 );
std::string get_antenna( size_t chan = 0 );