aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDimitri Stolnikov <horiz0n@gmx.net>2013-03-03 18:06:48 +0100
committerDimitri Stolnikov <horiz0n@gmx.net>2013-03-11 21:06:13 +0100
commite415d843c7588d3cd018fe43f139c5429a6a6c18 (patch)
treefeecc7b7d61821902922ef404521ec22a4d4c1e2 /lib
parentede9c80455d64d0286c68ce9faaaa7da69aeefd1 (diff)
add support for software IQ imbalance correction
this functionality depend on the gr-iqbal blocks developed by Sylvain Munaut and is a compile time dependency: http://cgit.osmocom.org/cgit/gr-iqbal
Diffstat (limited to 'lib')
-rw-r--r--lib/CMakeLists.txt7
-rw-r--r--lib/osmosdr_source_c_impl.cc131
-rw-r--r--lib/osmosdr_source_c_impl.h13
3 files changed, 129 insertions, 22 deletions
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 494d498..4f9d7d3 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -47,6 +47,13 @@ GR_OSMOSDR_APPEND_LIBS(
${GNURADIO_CORE_LIBRARIES}
)
+if(GNURADIO_IQBALANCE_FOUND)
+ message(STATUS "Will build with gnuradio iqbalance support.")
+ add_definitions(-DHAVE_IQBALANCE=1)
+ include_directories(APPEND ${GNURADIO_IQBALANCE_INCLUDE_DIRS})
+ GR_OSMOSDR_APPEND_LIBS(${GNURADIO_IQBALANCE_LIBRARIES})
+endif()
+
########################################################################
# Setup OsmoSDR component
########################################################################
diff --git a/lib/osmosdr_source_c_impl.cc b/lib/osmosdr_source_c_impl.cc
index ba17a83..708831c 100644
--- a/lib/osmosdr_source_c_impl.cc
+++ b/lib/osmosdr_source_c_impl.cc
@@ -173,70 +173,81 @@ osmosdr_source_c_impl::osmosdr_source_c_impl (const std::string &args)
// BOOST_FOREACH( dict_t::value_type &entry, dict )
// std::cerr << "'" << entry.first << "' = '" << entry.second << "'" << std::endl;
+ osmosdr_src_iface *iface = NULL;
+ gr_basic_block_sptr block;
+
#ifdef ENABLE_OSMOSDR
if ( dict.count("osmosdr") ) {
osmosdr_src_c_sptr src = osmosdr_make_src_c( arg );
-
- for (size_t i = 0; i < src->get_num_channels(); i++)
- connect(src, i, self(), channel++);
-
- _devs.push_back( src.get() );
+ block = src; iface = src.get();
}
#endif
#ifdef ENABLE_FCD
if ( dict.count("fcd") ) {
fcd_source_sptr src = make_fcd_source( arg );
- connect(src, 0, self(), channel++);
- _devs.push_back( src.get() );
+ block = src; iface = src.get();
}
#endif
#ifdef ENABLE_FILE
if ( dict.count("file") ) {
file_source_c_sptr src = make_file_source_c( arg );
- connect(src, 0, self(), channel++);
- _devs.push_back( src.get() );
+ block = src; iface = src.get();
}
#endif
#ifdef ENABLE_RTL
if ( dict.count("rtl") ) {
rtl_source_c_sptr src = make_rtl_source_c( arg );
- connect(src, 0, self(), channel++);
- _devs.push_back( src.get() );
+ block = src; iface = src.get();
}
#endif
#ifdef ENABLE_RTL_TCP
if ( dict.count("rtl_tcp") ) {
rtl_tcp_source_c_sptr src = make_rtl_tcp_source_c( arg );
- connect(src, 0, self(), channel++);
- _devs.push_back( src.get() );
+ block = src; iface = src.get();
}
#endif
#ifdef ENABLE_UHD
if ( dict.count("uhd") ) {
uhd_source_c_sptr src = make_uhd_source_c( arg );
-
- for (size_t i = 0; i < src->get_num_channels(); i++)
- connect(src, i, self(), channel++);
-
- _devs.push_back( src.get() );
+ block = src; iface = src.get();
}
#endif
#ifdef ENABLE_MIRI
if ( dict.count("miri") ) {
miri_source_c_sptr src = make_miri_source_c( arg );
+ block = src; iface = src.get();
+ }
+#endif
- for (size_t i = 0; i < src->get_num_channels(); i++)
- connect(src, i, self(), channel++);
+ if ( iface != NULL && long(block.get()) != 0 ) {
+ _devs.push_back( iface );
- _devs.push_back( src.get() );
- }
+ for (size_t i = 0; i < iface->get_num_channels(); i++) {
+#ifdef HAVE_IQBALANCE
+ iqbalance_optimize_c_sptr iq_opt = iqbalance_make_optimize_c( 0 );
+ iqbalance_fix_cc_sptr iq_fix = iqbalance_make_fix_cc();
+
+ connect(block, i, iq_fix, 0);
+ connect(iq_fix, 0, self(), channel++);
+
+ connect(block, i, iq_opt, 0);
+ msg_connect(iq_opt, "iqbal_corr", iq_fix, "iqbal_corr");
+
+ _iq_opt.push_back( iq_opt.get() );
+ _iq_fix.push_back( iq_fix.get() );
+#else
+ connect(block, i, self(), channel++);
#endif
+ }
+ } else if ( (iface != NULL) || (long(block.get()) != 0) )
+ throw std::runtime_error("Eitner iface or block are NULL.");
+
}
if (!_devs.size())
@@ -305,6 +316,24 @@ double osmosdr_source_c_impl::set_sample_rate(double rate)
BOOST_FOREACH( osmosdr_src_iface *dev, _devs )
sample_rate = dev->set_sample_rate(rate);
+#ifdef HAVE_IQBALANCE
+ 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 ( channel < _iq_opt.size() ) {
+ iqbalance_optimize_c *opt = _iq_opt[channel];
+
+ if ( opt->period() > 0 ) { /* optimize is enabled */
+ opt->set_period( dev->get_sample_rate() / 5 );
+ opt->reset();
+ }
+ }
+
+ channel++;
+ }
+ }
+#endif
+
_sample_rate = sample_rate;
}
@@ -542,3 +571,61 @@ std::string osmosdr_source_c_impl::get_antenna( size_t chan )
return "";
}
+
+void osmosdr_source_c_impl::set_iq_balance_mode( int mode, size_t chan )
+{
+#ifdef HAVE_IQBALANCE
+ 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 ( chan < _iq_opt.size() && chan < _iq_fix.size() ) {
+ iqbalance_optimize_c *opt = _iq_opt[chan];
+ iqbalance_fix_cc *fix = _iq_fix[chan];
+
+ if ( IQBalanceOff == mode ) {
+ opt->set_period( 0 );
+ /* store current values in order to be able to restore them later */
+ _vals[ chan ] = std::pair< float, float >( fix->mag(), fix->phase() );
+ fix->set_mag( 0.0f );
+ fix->set_phase( 0.0f );
+ } else if ( IQBalanceManual == mode ) {
+ if ( opt->period() == 0 ) { /* transition from Off to Manual */
+ /* restore previous values */
+ std::pair< float, float > val = _vals[ chan ];
+ fix->set_mag( val.first );
+ fix->set_phase( val.second );
+ }
+ opt->set_period( 0 );
+ } else if ( IQBalanceAutomatic == mode ) {
+ opt->set_period( dev->get_sample_rate() / 5 );
+ opt->reset();
+ }
+ }
+ }
+ }
+ }
+#endif
+}
+
+void osmosdr_source_c_impl::set_iq_balance( const std::complex<double> &correction, size_t chan )
+{
+#ifdef HAVE_IQBALANCE
+ 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 ( chan < _iq_opt.size() && chan < _iq_fix.size() ) {
+ iqbalance_optimize_c *opt = _iq_opt[chan];
+ iqbalance_fix_cc *fix = _iq_fix[chan];
+
+ if ( opt->period() == 0 ) { /* automatic optimization desabled */
+ fix->set_mag( correction.real() );
+ fix->set_phase( correction.imag() );
+ }
+ }
+ }
+ }
+ }
+#endif
+}
diff --git a/lib/osmosdr_source_c_impl.h b/lib/osmosdr_source_c_impl.h
index a34bf3b..47d6695 100644
--- a/lib/osmosdr_source_c_impl.h
+++ b/lib/osmosdr_source_c_impl.h
@@ -22,6 +22,11 @@
#include <osmosdr_source_c.h>
+#ifdef HAVE_IQBALANCE
+#include <iqbalance_optimize_c.h>
+#include <iqbalance_fix_cc.h>
+#endif
+
#include <osmosdr_src_iface.h>
#include <map>
@@ -57,6 +62,9 @@ public:
std::string set_antenna( const std::string & antenna, size_t chan = 0 );
std::string get_antenna( size_t chan = 0 );
+ void set_iq_balance_mode( int mode, size_t chan = 0 );
+ void set_iq_balance( const std::complex<double> &correction, size_t chan = 0 );
+
private:
osmosdr_source_c_impl (const std::string & args); // private constructor
@@ -72,6 +80,11 @@ private:
std::map< size_t, double > _if_gain;
std::map< size_t, std::string > _antenna;
std::vector< osmosdr_src_iface * > _devs;
+#ifdef HAVE_IQBALANCE
+ std::vector< iqbalance_fix_cc * > _iq_fix;
+ std::vector< iqbalance_optimize_c * > _iq_opt;
+ std::map< size_t, std::pair<float, float> > _vals;
+#endif
};
#endif /* INCLUDED_OSMOSDR_SOURCE_C_IMPL_H */