uhd: implement dc correction

standalone
Dimitri Stolnikov 10 years ago
parent 656a9a014f
commit 02f38ca908
  1. 64
      grc/gen_osmosdr_blocks.py
  2. 20
      include/osmosdr/sink.h
  3. 35
      include/osmosdr/source.h
  4. 11
      lib/sink_iface.h
  5. 16
      lib/sink_impl.cc
  6. 5
      lib/sink_impl.h
  7. 28
      lib/source_iface.h
  8. 38
      lib/source_impl.cc
  9. 5
      lib/source_impl.h
  10. 10
      lib/uhd/uhd_sink_c.cc
  11. 4
      lib/uhd/uhd_sink_c.h
  12. 34
      lib/uhd/uhd_source_c.cc
  13. 6
      lib/uhd/uhd_source_c.h

@ -32,8 +32,11 @@ self.\$(id).set_sample_rate(\$sample_rate)
\#if \$nchan() > $n
self.\$(id).set_center_freq(\$freq$(n), $n)
self.\$(id).set_freq_corr(\$corr$(n), $n)
#if $sourk == 'source':
self.\$(id).set_dc_offset_mode(\$dc_offset_mode$(n), $n)
self.\$(id).set_iq_balance_mode(\$iq_balance_mode$(n), $n)
self.\$(id).set_gain_mode(\$gain_mode$(n), $n)
#end if
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)
@ -46,8 +49,11 @@ self.\$(id).set_bandwidth(\$bw$(n), $n)
#for $n in range($max_nchan)
<callback>set_center_freq(\$freq$(n), $n)</callback>
<callback>set_freq_corr(\$corr$(n), $n)</callback>
#if $sourk == 'source':
<callback>set_dc_offset_mode(\$dc_offset_mode$(n), $n)</callback>
<callback>set_iq_balance_mode(\$iq_balance_mode$(n), $n)</callback>
<callback>set_gain_mode(\$gain_mode$(n), $n)</callback>
#end if
<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>
@ -104,20 +110,24 @@ self.\$(id).set_bandwidth(\$bw$(n), $n)
<nports>\$nchan</nports>
</$sourk>
<doc>
The osmocom block:
The osmocom $sourk block:
While primarily being developed for the OsmoSDR hardware, this block as well supports:
#if $sourk == 'source':
* FunCube Dongle through libgnuradio-fcd
* sysmocom OsmoSDR Devices through libosmosdr
#end if
* Great Scott Gadgets HackRF through libhackrf
* Ettus USRP Devices through Ettus UHD library
#if $sourk == 'source':
* RTL2832U based DVB-T dongles through librtlsdr
* RTL-TCP spectrum server (see librtlsdr project)
* MSi2500 based DVB-T dongles through libmirisdr
* gnuradio .cfile input through libgnuradio-blocks
#end if
By using the OsmoSDR block you can take advantage of a common software api in your application(s) independent of the underlying radio hardware.
By using the osmocom $sourk 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. Only complex float32 samples are supported at the moment.
@ -131,7 +141,7 @@ Examples:
Optional arguments are placed into [] brackets, remove the brackets before using them! Specific variable values are separated with a |, choose one of them. Variable values containing spaces shall be enclosed in '' as demonstrated in examples section below.
Lines ending with ... mean it's possible to bind devices together by specifying multiple device arguments separated with a space.
Source Mode:
#if $sourk == 'source':
fcd=0
hackrf=0[,buffers=32]
miri=0[,buffers=32] ...
@ -143,10 +153,11 @@ Source Mode:
uhd[,serial=...][,lo_offset=0][,mcr=52e6][,nchan=2][,subdev='\\\\'B:0 A:0\\\\''] ...
osmosdr=0[,buffers=32][,buflen=N*512] ...
file='/path/to/your file',rate=1e6[,freq=100e6][,repeat=true][,throttle=true] ...
Sink Mode:
#end if
#if $sourk == 'sink':
hackrf=0[,buffers=32]
uhd[,serial=...][,lo_offset=0][,mcr=52e6][,nchan=2][,subdev='\\\\'B:0 A:0\\\\''] ...
#end if
Num Channels:
Selects the total number of channels in this multi-device configuration. Required when specifying multiple device arguments.
@ -160,6 +171,15 @@ The center frequency is the frequency the RF chain is tuned to.
Freq. Corr.:
The frequency correction factor in parts per million (ppm). Set to 0 if unknown.
#if $sourk == 'source':
DC Offset Mode:
Controls the behavior of hardware DC offset corrrection.
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 DC offset.
This functionality is available for USRP devices only.
IQ Balance Mode:
Controls the behavior of software IQ imbalance corrrection.
Off: Disable correction algorithm (pass through).
@ -173,16 +193,17 @@ Chooses between the manual (default) and automatic gain mode where appropriate.
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.
#end if
RF Gain:
Overall RF gain of the receiving device.
Overall RF gain of the device.
IF Gain:
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.
Overall intermediate frequency gain of the device.
This setting is available for RTL-SDR and OsmoSDR devices with E4000 tuners and HackRF Jawbreaker in receive and transmit mode. 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.
Overall baseband gain of the device.
This setting is available for HackRF Jawbreaker in receive mode. Observations lead to a reasonable gain range from 15 to 30dB.
Antenna:
For devices with only one antenna, this may be left blank.
@ -214,6 +235,26 @@ PARAMS_TMPL = """
<type>real</type>
<hide>\#if \$nchan() > $n then 'none' else 'all'#</hide>
</param>
#if $sourk == 'source':
<param>
<name>Ch$(n): DC Offset Mode</name>
<key>dc_offset_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): IQ Balance Mode</name>
<key>iq_balance_mode$(n)</key>
@ -248,6 +289,7 @@ PARAMS_TMPL = """
<key>1</key>
</option>
</param>
#end if
<param>
<name>Ch$(n): RF Gain (dB)</name>
<key>gain$(n)</key>
@ -330,7 +372,7 @@ if __name__ == '__main__':
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)])
params = ''.join([parse_tmpl(PARAMS_TMPL, n=n, sourk=sourk) for n in range(max_num_channels)])
open(file, 'w').write(parse_tmpl(MAIN_TMPL,
max_nchan=max_num_channels,
params=params,

@ -234,29 +234,23 @@ public:
*/
virtual std::string get_antenna( size_t chan = 0 ) = 0;
enum IQBalanceMode {
IQBalanceOff = 0,
IQBalanceManual,
IQBalanceAutomatic
};
/*!
* Set the RX frontend IQ balance mode.
* Set the TX frontend DC offset value.
* The value is complex to control both I and Q.
*
* \param mode iq balance correction mode: 0 = Off, 1 = Manual, 2 = Automatic
* \param offset the dc offset (1.0 is full-scale)
* \param chan the channel index 0 to N-1
*/
virtual void set_iq_balance_mode( int mode, size_t chan = 0 ) = 0;
virtual void set_dc_offset( const std::complex<double> &offset, size_t chan = 0 ) = 0;
/*!
* Set the RX frontend IQ balance correction.
* Set the TX frontend IQ balance correction.
* Use this to adjust the magnitude and phase of I and Q.
*
* \param correction the complex correction value
* \param balance the complex correction value
* \param chan the channel index 0 to N-1
*/
virtual void set_iq_balance( const std::complex<double> &correction,
size_t chan = 0 ) = 0;
virtual void set_iq_balance( const std::complex<double> &balance, size_t chan = 0 ) = 0;
/*!
* Set the bandpass filter on the radio frontend.

@ -234,6 +234,36 @@ public:
*/
virtual std::string get_antenna( size_t chan = 0 ) = 0;
enum DCOffsetMode {
DCOffsetOff = 0,
DCOffsetManual,
DCOffsetAutomatic
};
/*!
* Set the RX frontend DC correction mode.
* The automatic correction subtracts out the long-run average.
*
* When disabled, the averaging option operation is reset.
* Once in Manual mode, the average value will be held constant until
* the user re-enables the automatic correction or overrides the
* value by manually setting the offset.
*
* \param mode dc offset correction mode: 0 = Off, 1 = Manual, 2 = Automatic
* \param chan the channel index 0 to N-1
*/
virtual void set_dc_offset_mode( int mode, size_t chan = 0) = 0;
/*!
* Set the RX frontend DC offset value.
* The value is complex to control both I and Q.
* Only set this when automatic correction is disabled.
*
* \param offset the dc offset (1.0 is full-scale)
* \param chan the channel index 0 to N-1
*/
virtual void set_dc_offset( const std::complex<double> &offset, size_t chan = 0 ) = 0;
enum IQBalanceMode {
IQBalanceOff = 0,
IQBalanceManual,
@ -252,11 +282,10 @@ public:
* Set the RX frontend IQ balance correction.
* Use this to adjust the magnitude and phase of I and Q.
*
* \param correction the complex correction value
* \param balance the complex correction value
* \param chan the channel index 0 to N-1
*/
virtual void set_iq_balance( const std::complex<double> &correction,
size_t chan = 0 ) = 0;
virtual void set_iq_balance( const std::complex<double> &balance, size_t chan = 0 ) = 0;
/*!
* Set the bandpass filter on the radio frontend.

@ -214,21 +214,22 @@ public:
virtual std::string get_antenna( size_t chan = 0 ) = 0;
/*!
* Set the TX frontend IQ balance mode.
* Set the TX frontend DC offset value.
* The value is complex to control both I and Q.
*
* \param mode iq balance correction mode: 0 = Off, 1 = Manual, 2 = Automatic
* \param offset the dc offset (1.0 is full-scale)
* \param chan the channel index 0 to N-1
*/
virtual void set_iq_balance_mode( int mode, size_t chan = 0 ) { }
virtual void set_dc_offset( const std::complex<double> &offset, size_t chan = 0 ) { }
/*!
* Set the TX frontend IQ balance correction.
* Use this to adjust the magnitude and phase of I and Q.
*
* \param correction the complex correction value
* \param balance the complex correction value
* \param chan the channel index 0 to N-1
*/
virtual void set_iq_balance( const std::complex<double> &correction, size_t chan = 0 ) { }
virtual void set_iq_balance( const std::complex<double> &balance, size_t chan = 0 ) { }
/*!
* Set the bandpass filter on the radio frontend.

@ -478,14 +478,22 @@ std::string sink_impl::get_antenna( size_t chan )
return "";
}
void sink_impl::set_iq_balance_mode( int mode, size_t chan )
void sink_impl::set_dc_offset( const std::complex<double> &offset, size_t chan )
{
size_t channel = 0;
BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->set_dc_offset( offset, dev_chan );
}
void sink_impl::set_iq_balance( const std::complex<double> &correction, size_t chan )
void sink_impl::set_iq_balance( const std::complex<double> &balance, size_t chan )
{
size_t channel = 0;
BOOST_FOREACH( sink_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->set_iq_balance( balance, dev_chan );
}
double sink_impl::set_bandwidth( double bandwidth, size_t chan )

@ -60,8 +60,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 );
void set_dc_offset( const std::complex<double> &offset, size_t chan = 0 );
void set_iq_balance( const std::complex<double> &balance, size_t chan = 0 );
double set_bandwidth( double bandwidth, size_t chan = 0 );
double get_bandwidth( size_t chan = 0 );

@ -213,6 +213,30 @@ public:
*/
virtual std::string get_antenna( size_t chan = 0 ) = 0;
/*!
* Set the RX frontend DC correction mode.
* The automatic correction subtracts out the long-run average.
*
* When disabled, the averaging option operation is reset.
* Once in Manual mode, the average value will be held constant until
* the user re-enables the automatic correction or overrides the
* value by manually setting the offset.
*
* \param mode dc offset correction mode: 0 = Off, 1 = Manual, 2 = Automatic
* \param chan the channel index 0 to N-1
*/
virtual void set_dc_offset_mode( int mode, size_t chan = 0 ) { }
/*!
* Set a constant DC offset value.
* The value is complex to control both I and Q.
* Only set this when automatic correction is disabled.
*
* \param offset the dc offset (1.0 is full-scale)
* \param chan the channel index 0 to N-1
*/
virtual void set_dc_offset( const std::complex<double> &offset, size_t chan = 0 ) { }
/*!
* Set the RX frontend IQ balance mode.
*
@ -225,10 +249,10 @@ public:
* Set the RX frontend IQ balance correction.
* Use this to adjust the magnitude and phase of I and Q.
*
* \param correction the complex correction value
* \param balance the complex correction value
* \param chan the channel index 0 to N-1
*/
virtual void set_iq_balance( const std::complex<double> &correction, size_t chan = 0 ) { }
virtual void set_iq_balance( const std::complex<double> &balance, size_t chan = 0 ) { }
/*!
* Set the bandpass filter on the radio frontend.

@ -612,10 +612,28 @@ std::string source_impl::get_antenna( size_t chan )
return "";
}
void source_impl::set_dc_offset_mode( int mode, size_t chan )
{
size_t channel = 0;
BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->set_dc_offset_mode( mode, dev_chan );
}
void source_impl::set_dc_offset( const std::complex<double> &offset, size_t chan )
{
size_t channel = 0;
BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->set_dc_offset( offset, dev_chan );
}
void source_impl::set_iq_balance_mode( int mode, size_t chan )
{
#ifdef HAVE_IQBALANCE
size_t channel = 0;
#ifdef HAVE_IQBALANCE
BOOST_FOREACH( source_iface *dev, _devs ) {
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++) {
if ( chan == channel++ ) {
@ -645,13 +663,18 @@ void source_impl::set_iq_balance_mode( int mode, size_t chan )
}
}
}
#else
BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->set_iq_balance_mode( mode, dev_chan );
#endif
}
void source_impl::set_iq_balance( const std::complex<double> &correction, size_t chan )
void source_impl::set_iq_balance( const std::complex<double> &balance, size_t chan )
{
#ifdef HAVE_IQBALANCE
size_t channel = 0;
#ifdef HAVE_IQBALANCE
BOOST_FOREACH( source_iface *dev, _devs ) {
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++) {
if ( chan == channel++ ) {
@ -660,13 +683,18 @@ void source_impl::set_iq_balance( const std::complex<double> &correction, size_t
gr::iqbalance::fix_cc *fix = _iq_fix[chan];
if ( opt->period() == 0 ) { /* automatic optimization desabled */
fix->set_mag( correction.real() );
fix->set_phase( correction.imag() );
fix->set_mag( balance.real() );
fix->set_phase( balance.imag() );
}
}
}
}
}
#else
BOOST_FOREACH( source_iface *dev, _devs )
for (size_t dev_chan = 0; dev_chan < dev->get_num_channels(); dev_chan++)
if ( chan == channel++ )
return dev->set_iq_balance( balance, dev_chan );
#endif
}

@ -65,8 +65,11 @@ public:
std::string set_antenna( const std::string & antenna, size_t chan = 0 );
std::string get_antenna( size_t chan = 0 );
void set_dc_offset_mode( int mode, size_t chan = 0 );
void set_dc_offset( const std::complex<double> &offset, 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 );
void set_iq_balance( const std::complex<double> &balance, size_t chan = 0 );
double set_bandwidth( double bandwidth, size_t chan = 0 );
double get_bandwidth( size_t chan = 0 );

@ -263,6 +263,16 @@ std::string uhd_sink_c::get_antenna( size_t chan )
return _snk->get_antenna(chan);
}
void uhd_sink_c::set_dc_offset( const std::complex<double> &offset, size_t chan )
{
_snk->set_dc_offset( offset, chan );
}
void uhd_sink_c::set_iq_balance( const std::complex<double> &balance, size_t chan )
{
_snk->set_iq_balance( balance, chan );
}
double uhd_sink_c::set_bandwidth( double bandwidth, size_t chan )
{
_snk->set_bandwidth(bandwidth, chan);

@ -71,6 +71,10 @@ public:
std::string set_antenna( const std::string & antenna, size_t chan = 0 );
std::string get_antenna( size_t chan = 0 );
void set_dc_offset( const std::complex<double> &offset, size_t chan = 0 );
void set_iq_balance( const std::complex<double> &balance, size_t chan = 0 );
double set_bandwidth( double bandwidth, size_t chan = 0 );
double get_bandwidth( size_t chan = 0 );
osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0 );

@ -27,6 +27,7 @@
#include "arg_helpers.h"
#include "uhd_source_c.h"
#include "osmosdr/source.h"
using namespace boost::assign;
@ -263,6 +264,39 @@ std::string uhd_source_c::get_antenna( size_t chan )
return _src->get_antenna(chan);
}
void uhd_source_c::set_dc_offset_mode( int mode, size_t chan )
{
if ( osmosdr::source::DCOffsetOff == mode ) {
_src->set_auto_dc_offset( false, chan );
_src->set_dc_offset( std::complex<double>(0.0, 0.0), chan ); /* uhd default */
} else if ( osmosdr::source::DCOffsetManual == mode ) {
_src->set_auto_dc_offset( false, chan );
} else if ( osmosdr::source::DCOffsetAutomatic == mode ) {
_src->set_auto_dc_offset( true, chan );
}
}
void uhd_source_c::set_dc_offset( const std::complex<double> &offset, size_t chan )
{
_src->set_dc_offset( offset, chan );
}
void uhd_source_c::set_iq_balance_mode( int mode, size_t chan )
{
if ( osmosdr::source::IQBalanceOff == mode ) {
_src->set_iq_balance( std::complex<double>(0.0, 0.0), chan ); /* uhd default */
} else if ( osmosdr::source::IQBalanceManual == mode ) {
/* nothing to do */
} else if ( osmosdr::source::IQBalanceAutomatic == mode ) {
throw std::runtime_error("Automatic IQ imbalance correction not implemented");
}
}
void uhd_source_c::set_iq_balance( const std::complex<double> &balance, size_t chan )
{
_src->set_iq_balance( balance, chan );
}
double uhd_source_c::set_bandwidth( double bandwidth, size_t chan )
{
_src->set_bandwidth(bandwidth, chan);

@ -71,6 +71,12 @@ public:
std::string set_antenna( const std::string & antenna, size_t chan = 0 );
std::string get_antenna( size_t chan = 0 );
void set_dc_offset_mode( int mode, size_t chan = 0 );
void set_dc_offset( const std::complex<double> &offset, size_t chan = 0 );
void set_iq_balance_mode( int mode, size_t chan = 0 );
void set_iq_balance( const std::complex<double> &balance, size_t chan = 0 );
double set_bandwidth( double bandwidth, size_t chan = 0 );
double get_bandwidth( size_t chan = 0 );
osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0 );

Loading…
Cancel
Save