From 54e8b566f6d1efecfd5fdc2c14bb287fd551089e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 1 Apr 2010 16:01:46 -0700 Subject: Moved usrp specific things into usrp directories and namespaces. Renamed simple device to simple usrp (it was usrp specific). Moved tune helper to usrp dir for same reason. --- host/lib/usrp/simple_usrp.cpp | 207 ++++++++++++++++++++++++++++++++++++++++++ host/lib/usrp/tune_helper.cpp | 126 +++++++++++++++++++++++++ 2 files changed, 333 insertions(+) create mode 100644 host/lib/usrp/simple_usrp.cpp create mode 100644 host/lib/usrp/tune_helper.cpp (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/simple_usrp.cpp b/host/lib/usrp/simple_usrp.cpp new file mode 100644 index 000000000..4bd47dc3f --- /dev/null +++ b/host/lib/usrp/simple_usrp.cpp @@ -0,0 +1,207 @@ +// +// 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 +#include +#include +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; + +/*********************************************************************** + * Helper Functions + **********************************************************************/ +static std::vector get_xx_rates(wax::obj decerps, wax::obj rate){ + std::vector rates; + BOOST_FOREACH(size_t decerp, decerps.as >()){ + rates.push_back(rate.as()/decerp); + } + return rates; +} + +/*********************************************************************** + * Simple Device Implementation + **********************************************************************/ +class simple_usrp_impl : public simple_usrp{ +public: + simple_usrp_impl(const device_addr_t &addr){ + _dev = device::make(addr); + _mboard = (*_dev)[DEVICE_PROP_MBOARD]; + _rx_ddc = _mboard[named_prop_t(MBOARD_PROP_RX_DSP, "ddc0")]; + _tx_duc = _mboard[named_prop_t(MBOARD_PROP_TX_DSP, "duc0")]; + + //extract rx subdevice + wax::obj rx_dboard = _mboard[MBOARD_PROP_RX_DBOARD]; + std::string rx_subdev_in_use = rx_dboard[DBOARD_PROP_USED_SUBDEVS].as().at(0); + _rx_subdev = rx_dboard[named_prop_t(DBOARD_PROP_SUBDEV, rx_subdev_in_use)]; + + //extract tx subdevice + wax::obj tx_dboard = _mboard[MBOARD_PROP_TX_DBOARD]; + std::string tx_subdev_in_use = tx_dboard[DBOARD_PROP_USED_SUBDEVS].as().at(0); + _tx_subdev = tx_dboard[named_prop_t(DBOARD_PROP_SUBDEV, tx_subdev_in_use)]; + } + + ~simple_usrp_impl(void){ + /* NOP */ + } + + device::sptr get_device(void){ + return _dev; + } + + std::string get_name(void){ + return _mboard[MBOARD_PROP_NAME].as(); + } + + /******************************************************************* + * Timing + ******************************************************************/ + void set_time_now(const time_spec_t &time_spec){ + _mboard[MBOARD_PROP_TIME_NOW] = time_spec; + } + + void set_time_next_pps(const time_spec_t &time_spec){ + _mboard[MBOARD_PROP_TIME_NEXT_PPS] = time_spec; + } + + /******************************************************************* + * Streaming + ******************************************************************/ + void issue_stream_cmd(const stream_cmd_t &stream_cmd){ + _rx_ddc[std::string("stream_cmd")] = stream_cmd; + } + + /******************************************************************* + * RX methods + ******************************************************************/ + void set_rx_rate(double rate){ + 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){ + 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("if_rate")]); + } + + tune_result_t set_rx_freq(double target_freq){ + return tune_rx_subdev_and_ddc(_rx_subdev, _rx_ddc, target_freq); + } + + freq_range_t get_rx_freq_range(void){ + return _rx_subdev[SUBDEV_PROP_FREQ_RANGE].as(); + } + + void set_rx_gain(float gain){ + _rx_subdev[SUBDEV_PROP_GAIN] = gain; + } + + float get_rx_gain(void){ + return _rx_subdev[SUBDEV_PROP_GAIN].as(); + } + + gain_range_t get_rx_gain_range(void){ + return _rx_subdev[SUBDEV_PROP_GAIN_RANGE].as(); + } + + void set_rx_antenna(const std::string &ant){ + _rx_subdev[SUBDEV_PROP_ANTENNA] = ant; + } + + std::string get_rx_antenna(void){ + return _rx_subdev[SUBDEV_PROP_ANTENNA].as(); + } + + std::vector get_rx_antennas(void){ + return _rx_subdev[SUBDEV_PROP_ANTENNA_NAMES].as >(); + } + + /******************************************************************* + * TX methods + ******************************************************************/ + void set_tx_rate(double rate){ + 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){ + 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("if_rate")]); + } + + tune_result_t set_tx_freq(double target_freq){ + return tune_tx_subdev_and_duc(_tx_subdev, _tx_duc, target_freq); + } + + freq_range_t get_tx_freq_range(void){ + return _tx_subdev[SUBDEV_PROP_FREQ_RANGE].as(); + } + + void set_tx_gain(float gain){ + _tx_subdev[SUBDEV_PROP_GAIN] = gain; + } + + float get_tx_gain(void){ + return _tx_subdev[SUBDEV_PROP_GAIN].as(); + } + + gain_range_t get_tx_gain_range(void){ + return _tx_subdev[SUBDEV_PROP_GAIN_RANGE].as(); + } + + void set_tx_antenna(const std::string &ant){ + _tx_subdev[SUBDEV_PROP_ANTENNA] = ant; + } + + std::string get_tx_antenna(void){ + return _tx_subdev[SUBDEV_PROP_ANTENNA].as(); + } + + std::vector get_tx_antennas(void){ + return _tx_subdev[SUBDEV_PROP_ANTENNA_NAMES].as >(); + } + +private: + device::sptr _dev; + wax::obj _mboard; + wax::obj _rx_ddc; + wax::obj _tx_duc; + wax::obj _rx_subdev; + wax::obj _tx_subdev; +}; + +/*********************************************************************** + * The Make Function + **********************************************************************/ +simple_usrp::sptr simple_usrp::make(const std::string &args){ + return sptr(new simple_usrp_impl(device_addr_t::from_args_str(args))); +} diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp new file mode 100644 index 000000000..79a6aff7b --- /dev/null +++ b/host/lib/usrp/tune_helper.cpp @@ -0,0 +1,126 @@ +// +// 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; +using namespace uhd::usrp; + +/*********************************************************************** + * 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("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; + 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::usrp::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::usrp::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("bb_rate")].as(); + } + return tune_rx_subdev_and_ddc(subdev, ddc, target_freq, lo_offset); +} + +/*********************************************************************** + * TX Tune + **********************************************************************/ +tune_result_t uhd::usrp::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::usrp::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("bb_rate")].as(); + } + return tune_tx_subdev_and_duc(subdev, duc, target_freq, lo_offset); +} -- cgit v1.2.3