From 86fffe7f9ed78a682879dd56c26628256f89e6ae Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 29 Mar 2010 00:45:26 -0700 Subject: Added tune helper to utils. Takes a subdevice and dxc properties object and tunes them. Made use of tune helper in simple device. Moved gain handler into utils header dir. --- host/lib/tune_helper.cpp | 125 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 host/lib/tune_helper.cpp (limited to 'host/lib/tune_helper.cpp') diff --git a/host/lib/tune_helper.cpp b/host/lib/tune_helper.cpp new file mode 100644 index 000000000..eeda0b6be --- /dev/null +++ b/host/lib/tune_helper.cpp @@ -0,0 +1,125 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include +#include +#include +#include + +using namespace uhd; + +/*********************************************************************** + * Tune Helper Function + **********************************************************************/ +static tune_result_t tune_xx_subdev_and_dxc( + bool is_tx, + wax::obj subdev, wax::obj dxc, + double target_freq, double lo_offset +){ + wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ]; + bool subdev_quadrature = subdev[SUBDEV_PROP_QUADRATURE].as(); + bool subdev_spectrum_inverted = subdev[SUBDEV_PROP_SPECTRUM_INVERTED].as(); + wax::obj dxc_freq_proxy = dxc[std::string("freq")]; + double dxc_sample_rate = dxc[std::string("rate")].as(); + + // Ask the d'board to tune as closely as it can to target_freq+lo_offset + double target_inter_freq = target_freq + lo_offset; + subdev_freq_proxy = target_inter_freq; + double actual_inter_freq = subdev_freq_proxy.as(); + + // Calculate the DDC setting that will downconvert the baseband from the + // daughterboard to our target frequency. + double delta_freq = target_freq - actual_inter_freq; + double delta_sign = std::signum(delta_freq); + delta_freq *= delta_sign; + delta_freq = std::fmod(delta_freq, dxc_sample_rate); + bool inverted = delta_freq > dxc_sample_rate/2.0; + double target_dxc_freq = inverted? (delta_freq - dxc_sample_rate) : (-delta_freq); + target_dxc_freq *= delta_sign; + + // If the spectrum is inverted, and the daughterboard doesn't do + // quadrature downconversion, we can fix the inversion by flipping the + // sign of the dxc_freq... (This only happens using the basic_rx board) + if (subdev_spectrum_inverted){ + inverted = not inverted; + } + if (inverted and not subdev_quadrature){ + target_dxc_freq *= -1.0; + inverted = not inverted; + } + // down conversion versus up conversion, fight! + // your mother is ugly and your going down... + target_dxc_freq *= (is_tx)? -1.0 : +1.0; + + dxc_freq_proxy = target_dxc_freq; + double actual_dxc_freq = dxc_freq_proxy.as(); + + //return some kind of tune result tuple/struct + tune_result_t tune_result; + tune_result.target_inter_freq = target_inter_freq; + tune_result.actual_inter_freq = actual_inter_freq; + tune_result.target_dxc_freq = target_dxc_freq; + tune_result.actual_dxc_freq = actual_dxc_freq; + tune_result.spectrum_inverted = inverted; + return tune_result; +} + +/*********************************************************************** + * RX Tune + **********************************************************************/ +tune_result_t uhd::tune_rx_subdev_and_ddc( + wax::obj subdev, wax::obj ddc, + double target_freq, double lo_offset +){ + bool is_tx = false; + return tune_xx_subdev_and_dxc(is_tx, subdev, ddc, target_freq, lo_offset); +} + +tune_result_t uhd::tune_rx_subdev_and_ddc( + wax::obj subdev, wax::obj ddc, + double target_freq +){ + double lo_offset = 0.0; + //if the local oscillator will be in the passband, use an offset + if (subdev[SUBDEV_PROP_LO_INTERFERES].as()){ + lo_offset = 2.0*ddc[std::string("rate")].as()/ddc[std::string("decim")].as(); + } + return tune_rx_subdev_and_ddc(subdev, ddc, target_freq, lo_offset); +} + +/*********************************************************************** + * TX Tune + **********************************************************************/ +tune_result_t uhd::tune_tx_subdev_and_duc( + wax::obj subdev, wax::obj duc, + double target_freq, double lo_offset +){ + bool is_tx = true; + return tune_xx_subdev_and_dxc(is_tx, subdev, duc, target_freq, lo_offset); +} + +tune_result_t uhd::tune_tx_subdev_and_duc( + wax::obj subdev, wax::obj duc, + double target_freq +){ + double lo_offset = 0.0; + //if the local oscillator will be in the passband, use an offset + if (subdev[SUBDEV_PROP_LO_INTERFERES].as()){ + lo_offset = 2.0*duc[std::string("rate")].as()/duc[std::string("interp")].as(); + } + return tune_tx_subdev_and_duc(subdev, duc, target_freq, lo_offset); +} -- cgit v1.2.3 From 7396b53e1bdd1aa5f9dcba760c8993a0cf620b6a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 29 Mar 2010 11:16:42 -0700 Subject: use bb_rate and if_rate to handle dxc io rates --- host/include/uhd/utils/tune_helper.hpp | 4 ++-- host/lib/simple_device.cpp | 16 ++++++---------- host/lib/tune_helper.cpp | 6 +++--- host/lib/usrp/usrp2/dsp_impl.cpp | 18 ++++++++++++++---- 4 files changed, 25 insertions(+), 19 deletions(-) (limited to 'host/lib/tune_helper.cpp') diff --git a/host/include/uhd/utils/tune_helper.hpp b/host/include/uhd/utils/tune_helper.hpp index 828575c99..958d1eceb 100644 --- a/host/include/uhd/utils/tune_helper.hpp +++ b/host/include/uhd/utils/tune_helper.hpp @@ -30,7 +30,7 @@ namespace uhd{ * the given target frequency + the LO offset (when applicable). * The ddc cordic is setup to bring the IF down to baseband. * \param subdev the dboard subdevice object with properties - * \param ddc the ddc properties object (with "rate", "decim", "freq") + * \param ddc the ddc properties object (with "if_rate", "bb_rate", "freq") * \param target_freq the desired center frequency * \param lo_offset an offset for the subdevice IF from center * \return a tune result struct @@ -55,7 +55,7 @@ UHD_API tune_result_t tune_rx_subdev_and_ddc( * the given target frequency + the LO offset (when applicable). * The duc cordic is setup to bring the baseband up to IF. * \param subdev the dboard subdevice object with properties - * \param duc the duc properties object (with "rate", "interp", "freq") + * \param duc the duc properties object (with "if_rate", "bb_rate", "freq") * \param target_freq the desired center frequency * \param lo_offset an offset for the subdevice IF from center * \return a tune result struct diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp index d507762a9..2e6bffc9c 100644 --- a/host/lib/simple_device.cpp +++ b/host/lib/simple_device.cpp @@ -116,19 +116,17 @@ public: * RX methods ******************************************************************/ void set_rx_rate(double rate){ - double samp_rate = _rx_ddc[std::string("rate")].as(); + double samp_rate = _rx_ddc[std::string("if_rate")].as(); assert_has(get_rx_rates(), rate, "simple device rx rate"); _rx_ddc[std::string("decim")] = size_t(samp_rate/rate); } double get_rx_rate(void){ - double samp_rate = _rx_ddc[std::string("rate")].as(); - size_t decim = _rx_ddc[std::string("decim")].as(); - return samp_rate/decim; + return _rx_ddc[std::string("bb_rate")].as(); } std::vector get_rx_rates(void){ - return get_xx_rates(_rx_ddc[std::string("decims")], _rx_ddc[std::string("rate")]); + return get_xx_rates(_rx_ddc[std::string("decims")], _rx_ddc[std::string("if_rate")]); } tune_result_t set_rx_freq(double target_freq){ @@ -167,19 +165,17 @@ public: * TX methods ******************************************************************/ void set_tx_rate(double rate){ - double samp_rate = _tx_duc[std::string("rate")].as(); + double samp_rate = _tx_duc[std::string("if_rate")].as(); assert_has(get_tx_rates(), rate, "simple device tx rate"); _tx_duc[std::string("interp")] = size_t(samp_rate/rate); } double get_tx_rate(void){ - double samp_rate = _tx_duc[std::string("rate")].as(); - size_t interp = _tx_duc[std::string("interp")].as(); - return samp_rate/interp; + return _tx_duc[std::string("bb_rate")].as(); } std::vector get_tx_rates(void){ - return get_xx_rates(_tx_duc[std::string("interps")], _tx_duc[std::string("rate")]); + return get_xx_rates(_tx_duc[std::string("interps")], _tx_duc[std::string("if_rate")]); } tune_result_t set_tx_freq(double target_freq){ diff --git a/host/lib/tune_helper.cpp b/host/lib/tune_helper.cpp index eeda0b6be..1e5c4cd0d 100644 --- a/host/lib/tune_helper.cpp +++ b/host/lib/tune_helper.cpp @@ -34,7 +34,7 @@ static tune_result_t tune_xx_subdev_and_dxc( bool subdev_quadrature = subdev[SUBDEV_PROP_QUADRATURE].as(); bool subdev_spectrum_inverted = subdev[SUBDEV_PROP_SPECTRUM_INVERTED].as(); wax::obj dxc_freq_proxy = dxc[std::string("freq")]; - double dxc_sample_rate = dxc[std::string("rate")].as(); + double dxc_sample_rate = dxc[std::string("if_rate")].as(); // Ask the d'board to tune as closely as it can to target_freq+lo_offset double target_inter_freq = target_freq + lo_offset; @@ -96,7 +96,7 @@ tune_result_t uhd::tune_rx_subdev_and_ddc( double lo_offset = 0.0; //if the local oscillator will be in the passband, use an offset if (subdev[SUBDEV_PROP_LO_INTERFERES].as()){ - lo_offset = 2.0*ddc[std::string("rate")].as()/ddc[std::string("decim")].as(); + lo_offset = 2.0*ddc[std::string("bb_rate")].as(); } return tune_rx_subdev_and_ddc(subdev, ddc, target_freq, lo_offset); } @@ -119,7 +119,7 @@ tune_result_t uhd::tune_tx_subdev_and_duc( double lo_offset = 0.0; //if the local oscillator will be in the passband, use an offset if (subdev[SUBDEV_PROP_LO_INTERFERES].as()){ - lo_offset = 2.0*duc[std::string("rate")].as()/duc[std::string("interp")].as(); + lo_offset = 2.0*duc[std::string("bb_rate")].as(); } return tune_tx_subdev_and_duc(subdev, duc, target_freq, lo_offset); } diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 40ef06a8c..0d43fac0e 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -113,7 +113,8 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){ case DSP_PROP_OTHERS:{ prop_names_t others = boost::assign::list_of - ("rate") + ("if_rate") + ("bb_rate") ("decim") ("decims") ("freq") @@ -127,10 +128,14 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){ //handle string-based properties specific to this dsp std::string key_name = key.as(); - if (key_name == "rate"){ + if (key_name == "if_rate"){ val = get_master_clock_freq(); return; } + else if (key_name == "bb_rate"){ + val = get_master_clock_freq()/_ddc_decim; + return; + } else if (key_name == "decim"){ val = _ddc_decim; return; @@ -234,7 +239,8 @@ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){ case DSP_PROP_OTHERS:{ prop_names_t others = boost::assign::list_of - ("rate") + ("if_rate") + ("bb_rate") ("interp") ("interps") ("freq") @@ -247,10 +253,14 @@ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){ //handle string-based properties specific to this dsp std::string key_name = key.as(); - if (key_name == "rate"){ + if (key_name == "if_rate"){ val = get_master_clock_freq(); return; } + else if (key_name == "bb_rate"){ + val = get_master_clock_freq()/_duc_interp; + return; + } else if (key_name == "interp"){ val = _duc_interp; return; -- cgit v1.2.3