From 359c4e16b2d2748a97ce33073c64502a7f190aa6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 25 Oct 2010 13:41:40 -0700 Subject: uhd: created tune request struct and implemented more fine grained tuning calls --- host/lib/usrp/tune_helper.cpp | 138 ++++++++++++++++++++++++------------------ 1 file changed, 78 insertions(+), 60 deletions(-) (limited to 'host/lib/usrp/tune_helper.cpp') diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp index 7633c67f2..8c57cc428 100644 --- a/host/lib/usrp/tune_helper.cpp +++ b/host/lib/usrp/tune_helper.cpp @@ -28,55 +28,97 @@ using namespace uhd::usrp; /*********************************************************************** * Tune Helper Functions **********************************************************************/ -static tune_result_t tune_xx_subdev_and_dxc( +static tune_result_t tune_xx_subdev_and_dsp( dboard_iface::unit_t unit, - wax::obj subdev, wax::obj dxc, size_t chan, - double target_freq, double lo_offset + wax::obj subdev, wax::obj dsp, size_t chan, + const tune_request_t &tune_request ){ wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ]; - std::string freq_name = dxc[DSP_PROP_FREQ_SHIFT_NAMES].as().at(chan); - wax::obj dxc_freq_proxy = dxc[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)]; - double dxc_sample_rate = dxc[DSP_PROP_CODEC_RATE].as(); + std::string freq_name = dsp[DSP_PROP_FREQ_SHIFT_NAMES].as().at(chan); + wax::obj dsp_freq_proxy = dsp[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)]; + double dsp_sample_rate = dsp[DSP_PROP_CODEC_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(); - - //perform the correction correction for dxc rates outside of nyquist - double delta_freq = std::fmod(target_freq - actual_inter_freq, dxc_sample_rate); - bool outside_of_nyquist = std::abs(delta_freq) > dxc_sample_rate/2.0; - double target_dxc_freq = (outside_of_nyquist)? - boost::math::sign(delta_freq)*dxc_sample_rate - delta_freq : -delta_freq; + //------------------------------------------------------------------ + //-- calculate the LO offset, only used with automatic policy + //------------------------------------------------------------------ + double lo_offset = 0.0; + if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as()){ + //if the local oscillator will be in the passband, use an offset + //TODO make this nicer, use bandwidth property to clip bounds + lo_offset = 2.0*dsp[DSP_PROP_HOST_RATE].as(); + } - //invert the sign on the dxc freq given the following conditions - if (unit == dboard_iface::UNIT_TX) target_dxc_freq *= -1.0; + //------------------------------------------------------------------ + //-- set the intermediate frequency depending upon the IF policy + //------------------------------------------------------------------ + double target_inter_freq = 0.0; + switch (tune_request.inter_freq_policy){ + case tune_request_t::POLICY_AUTO: + target_inter_freq = tune_request.target_freq + lo_offset; + subdev_freq_proxy = target_inter_freq; + break; + + case tune_request_t::POLICY_MANUAL: + target_inter_freq = tune_request.inter_freq; + subdev_freq_proxy = target_inter_freq; + break; + + case tune_request_t::POLICY_NONE: break; //does not set + } + double actual_inter_freq = subdev_freq_proxy.as(); - dxc_freq_proxy = target_dxc_freq; - double actual_dxc_freq = dxc_freq_proxy.as(); + //------------------------------------------------------------------ + //-- calculate the dsp freq, only used with automatic policy + //------------------------------------------------------------------ + double delta_freq = std::fmod(target_inter_freq - actual_inter_freq, dsp_sample_rate); + bool outside_of_nyquist = std::abs(delta_freq) > dsp_sample_rate/2.0; + double target_dsp_freq = (outside_of_nyquist)? + boost::math::sign(delta_freq)*dsp_sample_rate - delta_freq : -delta_freq; + + //invert the sign on the dsp freq given the following conditions + if (unit == dboard_iface::UNIT_TX) target_dsp_freq *= -1.0; + + //------------------------------------------------------------------ + //-- set the dsp frequency depending upon the dsp frequency policy + //------------------------------------------------------------------ + switch (tune_request.dsp_freq_policy){ + case tune_request_t::POLICY_AUTO: + dsp_freq_proxy = target_dsp_freq; + break; + + case tune_request_t::POLICY_MANUAL: + target_dsp_freq = tune_request.dsp_freq; + dsp_freq_proxy = target_dsp_freq; + break; + + case tune_request_t::POLICY_NONE: break; //does not set + } + double actual_dsp_freq = dsp_freq_proxy.as(); - //load and return the tune result + //------------------------------------------------------------------ + //-- load and return the tune result + //------------------------------------------------------------------ tune_result_t tune_result; tune_result.target_inter_freq = target_inter_freq; tune_result.actual_inter_freq = actual_inter_freq; - tune_result.target_dsp_freq = target_dxc_freq; - tune_result.actual_dsp_freq = actual_dxc_freq; + tune_result.target_dsp_freq = target_dsp_freq; + tune_result.actual_dsp_freq = actual_dsp_freq; return tune_result; } -static double derive_freq_from_xx_subdev_and_dxc( +static double derive_freq_from_xx_subdev_and_dsp( dboard_iface::unit_t unit, - wax::obj subdev, wax::obj dxc, size_t chan + wax::obj subdev, wax::obj dsp, size_t chan ){ //extract actual dsp and IF frequencies double actual_inter_freq = subdev[SUBDEV_PROP_FREQ].as(); - std::string freq_name = dxc[DSP_PROP_FREQ_SHIFT_NAMES].as().at(chan); - double actual_dxc_freq = dxc[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)].as(); + std::string freq_name = dsp[DSP_PROP_FREQ_SHIFT_NAMES].as().at(chan); + double actual_dsp_freq = dsp[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)].as(); - //invert the sign on the dxc freq given the following conditions - if (unit == dboard_iface::UNIT_TX) actual_dxc_freq *= -1.0; + //invert the sign on the dsp freq given the following conditions + if (unit == dboard_iface::UNIT_TX) actual_dsp_freq *= -1.0; - return actual_inter_freq - actual_dxc_freq; + return actual_inter_freq - actual_dsp_freq; } /*********************************************************************** @@ -84,27 +126,15 @@ static double derive_freq_from_xx_subdev_and_dxc( **********************************************************************/ tune_result_t usrp::tune_rx_subdev_and_dsp( wax::obj subdev, wax::obj ddc, size_t chan, - double target_freq, double lo_offset -){ - return tune_xx_subdev_and_dxc(dboard_iface::UNIT_RX, subdev, ddc, chan, target_freq, lo_offset); -} - -tune_result_t usrp::tune_rx_subdev_and_dsp( - wax::obj subdev, wax::obj ddc, - size_t chan, double target_freq + const tune_request_t &tune_request ){ - double lo_offset = 0.0; - //if the local oscillator will be in the passband, use an offset - if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as()){ - lo_offset = 2.0*ddc[DSP_PROP_HOST_RATE].as(); - } - return tune_rx_subdev_and_dsp(subdev, ddc, chan, target_freq, lo_offset); + return tune_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc, chan, tune_request); } double usrp::derive_freq_from_rx_subdev_and_dsp( wax::obj subdev, wax::obj ddc, size_t chan ){ - return derive_freq_from_xx_subdev_and_dxc(dboard_iface::UNIT_RX, subdev, ddc, chan); + return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc, chan); } /*********************************************************************** @@ -112,25 +142,13 @@ double usrp::derive_freq_from_rx_subdev_and_dsp( **********************************************************************/ tune_result_t usrp::tune_tx_subdev_and_dsp( wax::obj subdev, wax::obj duc, size_t chan, - double target_freq, double lo_offset + const tune_request_t &tune_request ){ - return tune_xx_subdev_and_dxc(dboard_iface::UNIT_TX, subdev, duc, chan, target_freq, lo_offset); -} - -tune_result_t usrp::tune_tx_subdev_and_dsp( - wax::obj subdev, wax::obj duc, - size_t chan, double target_freq -){ - double lo_offset = 0.0; - //if the local oscillator will be in the passband, use an offset - if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as()){ - lo_offset = 2.0*duc[DSP_PROP_HOST_RATE].as(); - } - return tune_tx_subdev_and_dsp(subdev, duc, chan, target_freq, lo_offset); + return tune_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc, chan, tune_request); } double usrp::derive_freq_from_tx_subdev_and_dsp( wax::obj subdev, wax::obj duc, size_t chan ){ - return derive_freq_from_xx_subdev_and_dxc(dboard_iface::UNIT_TX, subdev, duc, chan); + return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc, chan); } -- cgit v1.2.3 From 2d21958e1b7ecc9ff083f2e60b0b5d06ccb3c638 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 25 Oct 2010 17:04:51 -0700 Subject: uhd: tune helper + request, forgot to use and set target freq --- host/lib/types.cpp | 3 ++- host/lib/usrp/tune_helper.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp/tune_helper.cpp') diff --git a/host/lib/types.cpp b/host/lib/types.cpp index a8062b6ae..4188568aa 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -70,8 +70,9 @@ tune_request_t::tune_request_t(double target_freq): } tune_request_t::tune_request_t(double target_freq, double lo_off): - target_freq(target_freq + lo_off), + target_freq(target_freq), inter_freq_policy(POLICY_MANUAL), + inter_freq(target_freq + lo_off), dsp_freq_policy(POLICY_AUTO) { /* NOP */ diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp index 8c57cc428..a6b615926 100644 --- a/host/lib/usrp/tune_helper.cpp +++ b/host/lib/usrp/tune_helper.cpp @@ -70,7 +70,7 @@ static tune_result_t tune_xx_subdev_and_dsp( //------------------------------------------------------------------ //-- calculate the dsp freq, only used with automatic policy //------------------------------------------------------------------ - double delta_freq = std::fmod(target_inter_freq - actual_inter_freq, dsp_sample_rate); + double delta_freq = std::fmod(tune_request.target_freq - actual_inter_freq, dsp_sample_rate); bool outside_of_nyquist = std::abs(delta_freq) > dsp_sample_rate/2.0; double target_dsp_freq = (outside_of_nyquist)? boost::math::sign(delta_freq)*dsp_sample_rate - delta_freq : -delta_freq; -- cgit v1.2.3 From 0168bff835371140c0d75cc381e3228f8093fe70 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 25 Oct 2010 19:22:51 -0700 Subject: usrp: rework lo offset logic to use bandwidth, add test case --- host/lib/usrp/tune_helper.cpp | 9 +++-- host/test/tune_helper_test.cpp | 79 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 82 insertions(+), 6 deletions(-) (limited to 'host/lib/usrp/tune_helper.cpp') diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp index a6b615926..fa40a8a26 100644 --- a/host/lib/usrp/tune_helper.cpp +++ b/host/lib/usrp/tune_helper.cpp @@ -19,6 +19,7 @@ #include #include #include //unit_t +#include #include #include @@ -43,9 +44,11 @@ static tune_result_t tune_xx_subdev_and_dsp( //------------------------------------------------------------------ double lo_offset = 0.0; if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as()){ - //if the local oscillator will be in the passband, use an offset - //TODO make this nicer, use bandwidth property to clip bounds - lo_offset = 2.0*dsp[DSP_PROP_HOST_RATE].as(); + //If the local oscillator will be in the passband, use an offset. + //But constrain the LO offset by the width of the filter bandwidth. + double rate = dsp[DSP_PROP_HOST_RATE].as(); + double bw = subdev[SUBDEV_PROP_BANDWIDTH].as(); + if (bw > rate) lo_offset = std::min((bw - rate)/2, rate/2); } //------------------------------------------------------------------ diff --git a/host/test/tune_helper_test.cpp b/host/test/tune_helper_test.cpp index 1ef4af330..e0500ae3f 100644 --- a/host/test/tune_helper_test.cpp +++ b/host/test/tune_helper_test.cpp @@ -91,6 +91,44 @@ private: } }; +class dummy_subdev_bw : public wax::obj{ +private: + void get(const wax::obj &key, wax::obj &val){ + switch(key.as()){ + + case SUBDEV_PROP_FREQ: + val = _freq; + return; + + case SUBDEV_PROP_USE_LO_OFFSET: + val = true; + return; + + case SUBDEV_PROP_BANDWIDTH: + val = _bandwidth; + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } + } + + void set(const wax::obj &key, const wax::obj &val){ + switch(key.as()){ + case SUBDEV_PROP_FREQ: + _freq = val.as(); + return; + + case SUBDEV_PROP_BANDWIDTH: + _bandwidth = val.as(); + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } + } + + double _freq, _bandwidth; +}; + class dummy_dsp : public wax::obj{ public: dummy_dsp(double codec_rate): @@ -106,6 +144,10 @@ private: val = _codec_rate; return; + case DSP_PROP_HOST_RATE: + val = _host_rate; + return; + case DSP_PROP_FREQ_SHIFT: val = _freq_shift; return; @@ -125,11 +167,15 @@ private: _freq_shift = val.as(); return; + case DSP_PROP_HOST_RATE: + _host_rate = val.as(); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } - double _codec_rate, _freq_shift; + double _codec_rate, _freq_shift, _host_rate; }; /*********************************************************************** @@ -141,7 +187,7 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx){ dummy_subdev subdev(1e6); dummy_dsp dsp(100e6); - std::cout << "Testing tune helper RX automatic LO offset" << std::endl; + std::cout << "Testing tune helper RX automatic IF offset" << std::endl; tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.3451e9); std::cout << tr.to_pp_string() << std::endl; BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance); @@ -155,7 +201,7 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_tx){ dummy_subdev subdev(1e6); dummy_dsp dsp(100e6); - std::cout << "Testing tune helper TX automatic LO offset" << std::endl; + std::cout << "Testing tune helper TX automatic IF offset" << std::endl; tune_result_t tr = tune_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.3451e9); std::cout << tr.to_pp_string() << std::endl; BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance); @@ -178,3 +224,30 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx_nyquist){ double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0); BOOST_CHECK_CLOSE(freq_derived, -45e6, tolerance); } + +BOOST_AUTO_TEST_CASE(test_tune_helper_rx_lo_off){ + dummy_subdev_bw subdev; + dummy_dsp dsp(100e6); + tune_result_t tr; + + std::cout << "Testing tune helper RX automatic LO offset B >> fs" << std::endl; + subdev[SUBDEV_PROP_BANDWIDTH] = double(40e6); + dsp[DSP_PROP_HOST_RATE] = double(4e6); + tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9); + std::cout << tr.to_pp_string() << std::endl; + BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9+4e6/2, tolerance); + + std::cout << "Testing tune helper RX automatic LO offset B > fs" << std::endl; + subdev[SUBDEV_PROP_BANDWIDTH] = double(40e6); + dsp[DSP_PROP_HOST_RATE] = double(25e6); + tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9); + std::cout << tr.to_pp_string() << std::endl; + BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9+(40e6-25e6)/2, tolerance); + + std::cout << "Testing tune helper RX automatic LO offset B < fs" << std::endl; + subdev[SUBDEV_PROP_BANDWIDTH] = double(20e6); + dsp[DSP_PROP_HOST_RATE] = double(25e6); + tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9); + std::cout << tr.to_pp_string() << std::endl; + BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9, tolerance); +} -- cgit v1.2.3