From 8e9a8464386db03a596e0b88d0714d22723d37d0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 10 Mar 2010 14:47:03 -0800 Subject: Added simple device to handle wrapping general properties up into simple api. Added setting time capability to the usrp2 impl. Messing with props and time specs... --- host/lib/simple_device.cpp | 303 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 host/lib/simple_device.cpp (limited to 'host/lib/simple_device.cpp') diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp new file mode 100644 index 000000000..63a17c52d --- /dev/null +++ b/host/lib/simple_device.cpp @@ -0,0 +1,303 @@ +// +// 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 + +using namespace uhd; + +tune_result_t::tune_result_t(void){ + /* NOP */ +} + +/*********************************************************************** + * Tune Helper Function + **********************************************************************/ +static tune_result_t tune( + double target_freq, + double lo_offset, + wax::obj subdev, + wax::obj dxc, + bool is_tx +){ + wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ]; + bool subdev_quadrature = wax::cast(subdev[SUBDEV_PROP_QUADRATURE]); + bool subdev_spectrum_inverted = wax::cast(subdev[SUBDEV_PROP_SPECTRUM_INVERTED]); + wax::obj dxc_freq_proxy = dxc[std::string("freq")]; + double dxc_sample_rate = wax::cast(dxc[std::string("rate")]); + + // 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 = wax::cast(subdev_freq_proxy); + + // 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 = 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 = wax::cast(dxc_freq_proxy); + + //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; +} + +/*********************************************************************** + * Helper Functions + **********************************************************************/ +static std::string trim(const std::string &in){ + return boost::algorithm::trim_copy(in); +} + +device_addr_t args_to_device_addr(const std::string &args){ + device_addr_t addr; + + //split the args at the semi-colons + std::vector pairs; + boost::split(pairs, args, boost::is_any_of(";")); + BOOST_FOREACH(std::string pair, pairs){ + if (trim(pair) == "") continue; + + //split the key value pairs at the equals + std::vector key_val; + boost::split(key_val, pair, boost::is_any_of("=")); + if (key_val.size() != 2) throw std::runtime_error("invalid args string: "+args); + addr[trim(key_val[0])] = trim(key_val[1]); + } + + return addr; +} + +static std::vector get_xx_rates(wax::obj decerps, wax::obj rate){ + std::vector rates; + BOOST_FOREACH(size_t decerp, wax::cast >(decerps)){ + rates.push_back(wax::cast(rate)/decerp); + } + return rates; +} + +/*********************************************************************** + * Simple Device Implementation + **********************************************************************/ +class simple_device_impl : public simple_device{ +public: + simple_device_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")]; + _rx_subdev = _mboard[MBOARD_PROP_RX_DBOARD][DBOARD_PROP_SUBDEV]; + _tx_subdev = _mboard[MBOARD_PROP_TX_DBOARD][DBOARD_PROP_SUBDEV]; + } + + ~simple_device_impl(void){ + /* NOP */ + } + + device::sptr get_device(void){ + return _dev; + } + + std::string get_name(void){ + return wax::cast(_mboard[MBOARD_PROP_NAME]); + } + + /******************************************************************* + * Streaming + ******************************************************************/ + void set_streaming(bool enb){ + _rx_ddc[std::string("enabled")] = enb; + } + + bool get_streaming(void){ + return wax::cast(_rx_ddc[std::string("enabled")]); + } + + /******************************************************************* + * RX methods + ******************************************************************/ + void set_rx_rate(double rate){ + double samp_rate = wax::cast(_rx_ddc[std::string("rate")]); + 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 = wax::cast(_rx_ddc[std::string("rate")]); + size_t decim = wax::cast(_rx_ddc[std::string("decim")]); + return samp_rate/decim; + } + + std::vector get_rx_rates(void){ + return get_xx_rates(_rx_ddc[std::string("decims")], _rx_ddc[std::string("rate")]); + } + + tune_result_t set_rx_freq(double target_freq, double lo_offset){ + return tune(target_freq, lo_offset, _rx_subdev, _rx_ddc, false/* not tx */); + } + + double get_rx_freq_min(void){ + return wax::cast(_rx_subdev[SUBDEV_PROP_FREQ_MIN]); + } + + double get_rx_freq_max(void){ + return wax::cast(_rx_subdev[SUBDEV_PROP_FREQ_MAX]); + } + + void set_rx_gain(float gain){ + _rx_subdev[SUBDEV_PROP_GAIN] = gain; + } + + float get_rx_gain(void){ + return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN]); + } + + float get_rx_gain_min(void){ + return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN_MIN]); + } + + float get_rx_gain_max(void){ + return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN_MAX]); + } + + float get_rx_gain_step(void){ + return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN_STEP]); + } + + void set_rx_antenna(const std::string &ant){ + _rx_subdev[SUBDEV_PROP_ANTENNA] = ant; + } + + std::string get_rx_antenna(void){ + return wax::cast(_rx_subdev[SUBDEV_PROP_ANTENNA]); + } + + std::vector get_rx_antennas(void){ + return wax::cast >(_rx_subdev[SUBDEV_PROP_ANTENNA_NAMES]); + } + + /******************************************************************* + * TX methods + ******************************************************************/ + void set_tx_rate(double rate){ + double samp_rate = wax::cast(_tx_duc[std::string("rate")]); + 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 = wax::cast(_tx_duc[std::string("rate")]); + size_t interp = wax::cast(_tx_duc[std::string("interp")]); + return samp_rate/interp; + } + + std::vector get_tx_rates(void){ + return get_xx_rates(_tx_duc[std::string("interps")], _tx_duc[std::string("rate")]); + } + + tune_result_t set_tx_freq(double target_freq, double lo_offset){ + return tune(target_freq, lo_offset, _tx_subdev, _tx_duc, true/* is tx */); + } + + double get_tx_freq_min(void){ + return wax::cast(_tx_subdev[SUBDEV_PROP_FREQ_MIN]); + } + + double get_tx_freq_max(void){ + return wax::cast(_tx_subdev[SUBDEV_PROP_FREQ_MAX]); + } + + void set_tx_gain(float gain){ + _tx_subdev[SUBDEV_PROP_GAIN] = gain; + } + + float get_tx_gain(void){ + return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN]); + } + + float get_tx_gain_min(void){ + return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN_MIN]); + } + + float get_tx_gain_max(void){ + return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN_MAX]); + } + + float get_tx_gain_step(void){ + return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN_STEP]); + } + + void set_tx_antenna(const std::string &ant){ + _tx_subdev[SUBDEV_PROP_ANTENNA] = ant; + } + + std::string get_tx_antenna(void){ + return wax::cast(_tx_subdev[SUBDEV_PROP_ANTENNA]); + } + + std::vector get_tx_antennas(void){ + return wax::cast >(_tx_subdev[SUBDEV_PROP_ANTENNA_NAMES]); + } + +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_device::sptr simple_device::make(const std::string &args){ + return sptr(new simple_device_impl(args_to_device_addr(args))); +} -- cgit v1.2.3 From 9c0fb5e15da3c8ccbc1c8537671703411b210fcf Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 10 Mar 2010 19:33:38 -0800 Subject: Filled in dboard code for basics and lf type boards. The dboard is now just a uint16 (dont bother with the enums). The dboard manager now registers subdevs with a name. The basic board code uses a static block to register itself. --- host/include/uhd/simple_device.hpp | 4 +- host/include/uhd/usrp/dboard_base.hpp | 5 +- host/include/uhd/usrp/dboard_id.hpp | 9 +- host/include/uhd/usrp/dboard_manager.hpp | 2 + host/include/uhd/utils.hpp | 5 + host/lib/CMakeLists.txt | 1 - host/lib/simple_device.cpp | 14 +- host/lib/usrp/dboard/basic.cpp | 282 +++++++++++++++++++++++++++++-- host/lib/usrp/dboard/dboards.hpp | 53 ------ host/lib/usrp/dboard_id.cpp | 34 ---- host/lib/usrp/dboard_manager.cpp | 40 ++--- 11 files changed, 307 insertions(+), 142 deletions(-) delete mode 100644 host/lib/usrp/dboard/dboards.hpp delete mode 100644 host/lib/usrp/dboard_id.cpp (limited to 'host/lib/simple_device.cpp') diff --git a/host/include/uhd/simple_device.hpp b/host/include/uhd/simple_device.hpp index 64ec85a5c..69f13a8b5 100644 --- a/host/include/uhd/simple_device.hpp +++ b/host/include/uhd/simple_device.hpp @@ -70,7 +70,7 @@ public: virtual double get_rx_rate(void) = 0; virtual std::vector get_rx_rates(void) = 0; - virtual tune_result_t set_rx_freq(double target_freq, double lo_offset) = 0; + virtual tune_result_t set_rx_freq(double freq) = 0; virtual double get_rx_freq_min(void) = 0; virtual double get_rx_freq_max(void) = 0; @@ -91,7 +91,7 @@ public: virtual double get_tx_rate(void) = 0; virtual std::vector get_tx_rates(void) = 0; - virtual tune_result_t set_tx_freq(double target_freq, double lo_offset) = 0; + virtual tune_result_t set_tx_freq(double freq) = 0; virtual double get_tx_freq_min(void) = 0; virtual double get_tx_freq_max(void) = 0; diff --git a/host/include/uhd/usrp/dboard_base.hpp b/host/include/uhd/usrp/dboard_base.hpp index b5c0d40ed..9048344ac 100644 --- a/host/include/uhd/usrp/dboard_base.hpp +++ b/host/include/uhd/usrp/dboard_base.hpp @@ -56,9 +56,9 @@ protected: dboard_id_t get_tx_id(void); private: - std::string _subdev_name; + std::string _subdev_name; dboard_interface::sptr _dboard_interface; - dboard_id_t _rx_id, _tx_id; + dboard_id_t _rx_id, _tx_id; }; /*! @@ -71,6 +71,7 @@ public: * Create a new xcvr dboard object, override in subclasses. */ xcvr_dboard_base(ctor_args_t const&); + virtual ~xcvr_dboard_base(void); }; diff --git a/host/include/uhd/usrp/dboard_id.hpp b/host/include/uhd/usrp/dboard_id.hpp index 65e3d5707..34406863d 100644 --- a/host/include/uhd/usrp/dboard_id.hpp +++ b/host/include/uhd/usrp/dboard_id.hpp @@ -16,17 +16,16 @@ // #include +#include #ifndef INCLUDED_UHD_USRP_DBOARD_ID_HPP #define INCLUDED_UHD_USRP_DBOARD_ID_HPP namespace uhd{ namespace usrp{ -enum dboard_id_t{ - ID_NONE = 0xffff, - ID_BASIC_TX = 0x0000, - ID_BASIC_RX = 0x0001 -}; +typedef uint16_t dboard_id_t; + +static const dboard_id_t ID_NONE = 0xffff; namespace dboard_id{ std::string to_string(const dboard_id_t &id); diff --git a/host/include/uhd/usrp/dboard_manager.hpp b/host/include/uhd/usrp/dboard_manager.hpp index 042947ac4..cf69675fc 100644 --- a/host/include/uhd/usrp/dboard_manager.hpp +++ b/host/include/uhd/usrp/dboard_manager.hpp @@ -44,11 +44,13 @@ public: * * \param dboard_id the dboard id (rx or tx) * \param dboard_ctor the dboard constructor function pointer + * \param name the canonical name for the dboard represented * \param subdev_names the names of the subdevs on this dboard */ static void register_subdevs( dboard_id_t dboard_id, dboard_ctor_t dboard_ctor, + const std::string &name, const prop_names_t &subdev_names ); diff --git a/host/include/uhd/utils.hpp b/host/include/uhd/utils.hpp index 25a7b5abd..e4cfd098b 100644 --- a/host/include/uhd/utils.hpp +++ b/host/include/uhd/utils.hpp @@ -23,6 +23,11 @@ #include #include +/*! + * Defines a static code block that will be called before main() + */ +#define STATIC_BLOCK(_name, _code) struct _name{_name(void){_code}} _name + /*! * Useful templated functions and classes that I like to pretend are part of stl */ diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index b141d67bb..1d2c5471b 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -30,7 +30,6 @@ SET(libuhd_sources transport/vrt.cpp usrp/dboard/basic.cpp usrp/dboard_base.cpp - usrp/dboard_id.cpp usrp/dboard_interface.cpp usrp/dboard_manager.cpp usrp/usrp2/dboard_impl.cpp diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp index 63a17c52d..76f3c1262 100644 --- a/host/lib/simple_device.cpp +++ b/host/lib/simple_device.cpp @@ -179,7 +179,12 @@ public: return get_xx_rates(_rx_ddc[std::string("decims")], _rx_ddc[std::string("rate")]); } - tune_result_t set_rx_freq(double target_freq, double lo_offset){ + tune_result_t set_rx_freq(double target_freq){ + double lo_offset = 0.0; + //if the local oscillator will be in the passband, use an offset + if (wax::cast(_rx_subdev[SUBDEV_PROP_LO_INTERFERES])){ + lo_offset = get_rx_rate()*2.0; + } return tune(target_freq, lo_offset, _rx_subdev, _rx_ddc, false/* not tx */); } @@ -242,7 +247,12 @@ public: return get_xx_rates(_tx_duc[std::string("interps")], _tx_duc[std::string("rate")]); } - tune_result_t set_tx_freq(double target_freq, double lo_offset){ + tune_result_t set_tx_freq(double target_freq){ + double lo_offset = 0.0; + //if the local oscillator will be in the passband, use an offset + if (wax::cast(_tx_subdev[SUBDEV_PROP_LO_INTERFERES])){ + lo_offset = get_tx_rate()*2.0; + } return tune(target_freq, lo_offset, _tx_subdev, _tx_duc, true/* is tx */); } diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp index f39ebff2f..5e245a8cf 100644 --- a/host/lib/usrp/dboard/basic.cpp +++ b/host/lib/usrp/dboard/basic.cpp @@ -15,42 +15,294 @@ // along with this program. If not, see . // -#include "dboards.hpp" +#include +#include +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; /*********************************************************************** - * Basic RX dboard + * The basic and lf boards: + * They share a common class because only the frequency bounds differ. **********************************************************************/ -basic_rx::basic_rx(ctor_args_t const& args) : rx_dboard_base(args){ - /* NOP */ +class basic_rx : public rx_dboard_base{ +public: + basic_rx(ctor_args_t const& args, freq_t max_freq); + ~basic_rx(void); + + void rx_get(const wax::obj &key, wax::obj &val); + void rx_set(const wax::obj &key, const wax::obj &val); + +private: + freq_t _max_freq; +}; + +class basic_tx : public tx_dboard_base{ +public: + basic_tx(ctor_args_t const& args, freq_t max_freq); + ~basic_tx(void); + + void tx_get(const wax::obj &key, wax::obj &val); + void tx_set(const wax::obj &key, const wax::obj &val); + +private: + freq_t _max_freq; +}; + +/*********************************************************************** + * Register the basic and LF dboards + **********************************************************************/ +static dboard_base::sptr make_basic_rx(dboard_base::ctor_args_t const& args){ + return dboard_base::sptr(new basic_rx(args, 90e9)); +} + +static dboard_base::sptr make_basic_tx(dboard_base::ctor_args_t const& args){ + return dboard_base::sptr(new basic_tx(args, 90e9)); +} + +static dboard_base::sptr make_lf_rx(dboard_base::ctor_args_t const& args){ + return dboard_base::sptr(new basic_rx(args, 32e6)); +} + +static dboard_base::sptr make_lf_tx(dboard_base::ctor_args_t const& args){ + return dboard_base::sptr(new basic_tx(args, 32e6)); +} + +STATIC_BLOCK(reg_dboards, { + dboard_manager::register_subdevs(0x0000, &make_basic_tx, "Basic TX", list_of("")); + dboard_manager::register_subdevs(0x0001, &make_basic_rx, "Basic RX", list_of("a")("b")("ab")); + dboard_manager::register_subdevs(0x000e, &make_lf_tx, "LF TX", list_of("")); + dboard_manager::register_subdevs(0x000f, &make_lf_rx, "LF RX", list_of("a")("b")("ab")); +}); + +/*********************************************************************** + * Basic and LF RX dboard + **********************************************************************/ +basic_rx::basic_rx(ctor_args_t const& args, freq_t max_freq) : rx_dboard_base(args){ + _max_freq = max_freq; + // set the gpios to safe values (all inputs) + get_interface()->set_gpio_ddr(dboard_interface::GPIO_RX_BANK, 0x0000, 0xffff); } basic_rx::~basic_rx(void){ /* NOP */ } -void basic_rx::rx_get(const wax::obj &, wax::obj &){ - /* TODO */ +void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(wax::cast(key)){ + case SUBDEV_PROP_NAME: + val = std::string(str(boost::format("%s:%s") + % dboard_id::to_string(get_rx_id()) + % get_subdev_name() + )); + return; + + case SUBDEV_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_GAIN: + case SUBDEV_PROP_GAIN_MAX: + case SUBDEV_PROP_GAIN_MIN: + case SUBDEV_PROP_GAIN_STEP: + val = gain_t(0); + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_FREQ: + val = freq_t(0); + return; + + case SUBDEV_PROP_FREQ_MAX: + val = +_max_freq; + return; + + case SUBDEV_PROP_FREQ_MIN: + val = -_max_freq; + return; + + case SUBDEV_PROP_ANTENNA: + val = std::string(""); + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = prop_names_t(1, ""); //vector of 1 empty string + return; + + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + + case SUBDEV_PROP_QUADRATURE: + val = (get_subdev_name() == "ab"); //only quadrature in ab mode + return; + + case SUBDEV_PROP_IQ_SWAPPED: + case SUBDEV_PROP_SPECTRUM_INVERTED: + case SUBDEV_PROP_LO_INTERFERES: + val = false; + return; + } } -void basic_rx::rx_set(const wax::obj &, const wax::obj &){ - /* TODO */ +void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(wax::cast(key)){ + + case SUBDEV_PROP_GAIN: + ASSERT_THROW(wax::cast(val) == gain_t(0)); + return; + + case SUBDEV_PROP_ANTENNA: + ASSERT_THROW(wax::cast(val) == std::string("")); + return; + + case SUBDEV_PROP_ENABLED: + return; // it wont do you much good, but you can set it + + case SUBDEV_PROP_NAME: + case SUBDEV_PROP_OTHERS: + case SUBDEV_PROP_GAIN_MAX: + case SUBDEV_PROP_GAIN_MIN: + case SUBDEV_PROP_GAIN_STEP: + case SUBDEV_PROP_GAIN_NAMES: + case SUBDEV_PROP_FREQ: + case SUBDEV_PROP_FREQ_MAX: + case SUBDEV_PROP_FREQ_MIN: + case SUBDEV_PROP_ANTENNA_NAMES: + case SUBDEV_PROP_QUADRATURE: + case SUBDEV_PROP_IQ_SWAPPED: + case SUBDEV_PROP_SPECTRUM_INVERTED: + case SUBDEV_PROP_LO_INTERFERES: + throw std::runtime_error(str(boost::format( + "Error: trying to set read-only property on %s subdev" + ) % dboard_id::to_string(get_rx_id()))); + } } /*********************************************************************** - * Basic TX dboard + * Basic and LF TX dboard **********************************************************************/ -basic_tx::basic_tx(ctor_args_t const& args) : tx_dboard_base(args){ - /* NOP */ +basic_tx::basic_tx(ctor_args_t const& args, freq_t max_freq) : tx_dboard_base(args){ + _max_freq = max_freq; + // set the gpios to safe values (all inputs) + get_interface()->set_gpio_ddr(dboard_interface::GPIO_TX_BANK, 0x0000, 0xffff); } basic_tx::~basic_tx(void){ /* NOP */ } -void basic_tx::tx_get(const wax::obj &, wax::obj &){ - /* TODO */ +void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(wax::cast(key)){ + case SUBDEV_PROP_NAME: + val = dboard_id::to_string(get_tx_id()); + return; + + case SUBDEV_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_GAIN: + case SUBDEV_PROP_GAIN_MAX: + case SUBDEV_PROP_GAIN_MIN: + case SUBDEV_PROP_GAIN_STEP: + val = gain_t(0); + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_FREQ: + val = freq_t(0); + return; + + case SUBDEV_PROP_FREQ_MAX: + val = +_max_freq; + return; + + case SUBDEV_PROP_FREQ_MIN: + val = -_max_freq; + return; + + case SUBDEV_PROP_ANTENNA: + val = std::string(""); + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = prop_names_t(1, ""); //vector of 1 empty string + return; + + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + + case SUBDEV_PROP_QUADRATURE: + val = true; + return; + + case SUBDEV_PROP_IQ_SWAPPED: + case SUBDEV_PROP_SPECTRUM_INVERTED: + case SUBDEV_PROP_LO_INTERFERES: + val = false; + return; + } } -void basic_tx::tx_set(const wax::obj &, const wax::obj &){ - /* TODO */ +void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(wax::cast(key)){ + + case SUBDEV_PROP_GAIN: + ASSERT_THROW(wax::cast(val) == gain_t(0)); + return; + + case SUBDEV_PROP_ANTENNA: + ASSERT_THROW(wax::cast(val) == std::string("")); + return; + + case SUBDEV_PROP_ENABLED: + return; // it wont do you much good, but you can set it + + case SUBDEV_PROP_NAME: + case SUBDEV_PROP_OTHERS: + case SUBDEV_PROP_GAIN_MAX: + case SUBDEV_PROP_GAIN_MIN: + case SUBDEV_PROP_GAIN_STEP: + case SUBDEV_PROP_GAIN_NAMES: + case SUBDEV_PROP_FREQ: + case SUBDEV_PROP_FREQ_MAX: + case SUBDEV_PROP_FREQ_MIN: + case SUBDEV_PROP_ANTENNA_NAMES: + case SUBDEV_PROP_QUADRATURE: + case SUBDEV_PROP_IQ_SWAPPED: + case SUBDEV_PROP_SPECTRUM_INVERTED: + case SUBDEV_PROP_LO_INTERFERES: + throw std::runtime_error(str(boost::format( + "Error: trying to set read-only property on %s subdev" + ) % dboard_id::to_string(get_tx_id()))); + } } diff --git a/host/lib/usrp/dboard/dboards.hpp b/host/lib/usrp/dboard/dboards.hpp deleted file mode 100644 index 79b90d593..000000000 --- a/host/lib/usrp/dboard/dboards.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// 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 . -// - -#ifndef INCLUDED_LOCAL_DBOARDS_HPP -#define INCLUDED_LOCAL_DBOARDS_HPP - -#include - -using namespace uhd::usrp; - -/*********************************************************************** - * The basic boards: - **********************************************************************/ -class basic_rx : public rx_dboard_base{ -public: - static dboard_base::sptr make(ctor_args_t const& args){ - return dboard_base::sptr(new basic_rx(args)); - } - basic_rx(ctor_args_t const& args); - ~basic_rx(void); - - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); -}; - -class basic_tx : public tx_dboard_base{ -public: - static dboard_base::sptr make(ctor_args_t const& args){ - return dboard_base::sptr(new basic_tx(args)); - } - basic_tx(ctor_args_t const& args); - ~basic_tx(void); - - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); - -}; - -#endif /* INCLUDED_LOCAL_DBOARDS_HPP */ diff --git a/host/lib/usrp/dboard_id.cpp b/host/lib/usrp/dboard_id.cpp deleted file mode 100644 index d2ef7cd7d..000000000 --- a/host/lib/usrp/dboard_id.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// -// 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 - -using namespace uhd::usrp; - -std::string dboard_id::to_string(const dboard_id_t &id){ - //map the dboard ids to string representations - uhd::dict id_to_str; - id_to_str[ID_NONE] = "none"; - id_to_str[ID_BASIC_TX] = "basic tx"; - id_to_str[ID_BASIC_RX] = "basic rx"; - - //get the string representation - std::string name = (id_to_str.has_key(id))? id_to_str[id] : "unknown"; - return str(boost::format("%s (0x%.4x)") % name % id); -} diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index cce239f3e..57b449175 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -18,36 +18,12 @@ #include #include #include -#include #include #include #include -#include "dboard/dboards.hpp" using namespace uhd; using namespace uhd::usrp; -using namespace boost::assign; - -/*********************************************************************** - * register internal dboards - * - * Register internal/known dboards located in this build tree. - * Each board should have entries below mapping an id to a constructor. - * The xcvr type boards should register both rx and tx sides. - * - * This function will be called before new boards are registered. - * This allows for internal boards to be externally overridden. - * This function will also be called when creating a new dboard_manager - * to ensure that the maps are filled with the entries below. - **********************************************************************/ -static void register_internal_dboards(void){ - //ensure that this function can only be called once per instance - static bool called = false; - if (called) return; called = true; - //register the known dboards (dboard id, constructor, subdev names) - dboard_manager::register_subdevs(ID_BASIC_TX, &basic_tx::make, list_of("")); - dboard_manager::register_subdevs(ID_BASIC_RX, &basic_rx::make, list_of("a")("b")("ab")); -} /*********************************************************************** * storage and registering for dboards @@ -57,15 +33,24 @@ typedef boost::tuple args_t; //map a dboard id to a dboard constructor static uhd::dict id_to_args_map; +//map a dboard id to a canonical name +static uhd::dict id_to_str; + void dboard_manager::register_subdevs( dboard_id_t dboard_id, dboard_ctor_t dboard_ctor, + const std::string &name, const prop_names_t &subdev_names ){ - register_internal_dboards(); //always call first + id_to_str[dboard_id] = name; id_to_args_map[dboard_id] = args_t(dboard_ctor, subdev_names); } +std::string dboard_id::to_string(const dboard_id_t &id){ + std::string name = (id_to_str.has_key(id))? id_to_str[id] : "unknown"; + return str(boost::format("%s (0x%.4x)") % name % id); +} + /*********************************************************************** * dboard manager implementation class **********************************************************************/ @@ -160,12 +145,12 @@ static args_t get_dboard_args( ){ //special case, its rx and the none id (0xffff) if (xx_type == "rx" and dboard_id == ID_NONE){ - return args_t(&basic_rx::make, list_of("ab")); + return get_dboard_args(0x0001, xx_type); } //special case, its tx and the none id (0xffff) if (xx_type == "tx" and dboard_id == ID_NONE){ - return args_t(&basic_tx::make, list_of("")); + return get_dboard_args(0x0000, xx_type); } //verify that there is a registered constructor for this id @@ -185,7 +170,6 @@ dboard_manager_impl::dboard_manager_impl( dboard_id_t tx_dboard_id, dboard_interface::sptr interface ){ - register_internal_dboards(); //always call first _interface = interface; dboard_ctor_t rx_dboard_ctor; prop_names_t rx_subdevs; -- cgit v1.2.3 From 2147c5f61c2eb6ef1a68419d7b1041a54cbb14a2 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 12 Mar 2010 16:01:01 -0800 Subject: Removed freq min and max and gain min, max, and step... replaced it with gain and freq range tuples. This simplifies the api calls and subdev properties. --- host/include/uhd/gain_handler.hpp | 14 ++---- host/include/uhd/props.hpp | 13 +++-- host/include/uhd/simple_device.hpp | 14 ++---- host/include/uhd/utils.hpp | 5 -- host/lib/gain_handler.cpp | 98 +++++++++++++++----------------------- host/lib/simple_device.cpp | 56 +++++++++------------- host/lib/usrp/dboard/basic.cpp | 44 +++++++---------- host/lib/usrp/dboard_manager.cpp | 13 +++-- host/test/gain_handler_test.cpp | 80 +++++++++++++------------------ 9 files changed, 131 insertions(+), 206 deletions(-) (limited to 'host/lib/simple_device.cpp') diff --git a/host/include/uhd/gain_handler.hpp b/host/include/uhd/gain_handler.hpp index fade86f53..2d3f8a3f4 100644 --- a/host/include/uhd/gain_handler.hpp +++ b/host/include/uhd/gain_handler.hpp @@ -32,13 +32,9 @@ public: /*! * A set of properties for dealing with gains. */ - struct gain_props_t{ - wax::obj gain_val_prop; - wax::obj gain_min_prop; - wax::obj gain_max_prop; - wax::obj gain_step_prop; - wax::obj gain_names_prop; - gain_props_t(void); //default constructor + struct props_t{ + wax::obj value, range, names; + props_t(void); //default constructor }; /*! @@ -47,12 +43,12 @@ public: * It is up to the caller to provide an "is_equal" function that * can tell weather two properties (in a wax obj) are equal. * \param link a link to the wax obj with properties - * \param gain_props a struct of properties keys + * \param props a struct of properties keys * \param is_equal the function that tests for equal properties */ static sptr make( const wax::obj &link, - const gain_props_t &gain_props, + const props_t &props, is_equal_t is_equal ); diff --git a/host/include/uhd/props.hpp b/host/include/uhd/props.hpp index dea2baf52..f2ba1769f 100644 --- a/host/include/uhd/props.hpp +++ b/host/include/uhd/props.hpp @@ -30,6 +30,12 @@ namespace uhd{ typedef float gain_t; typedef double freq_t; + //gain range tuple (min, max, step) + typedef boost::tuple gain_range_t; + + //freq range tuple (min, max) + typedef boost::tuple freq_range_t; + //scalar types (have not used yet, dont uncomment until needed) //typedef int int_scalar_t; //typedef float real_scalar_t; @@ -143,13 +149,10 @@ namespace uhd{ SUBDEV_PROP_NAME, //ro, std::string SUBDEV_PROP_OTHERS, //ro, prop_names_t SUBDEV_PROP_GAIN, //rw, gain_t - SUBDEV_PROP_GAIN_MAX, //ro, gain_t - SUBDEV_PROP_GAIN_MIN, //ro, gain_t - SUBDEV_PROP_GAIN_STEP, //ro, gain_t + SUBDEV_PROP_GAIN_RANGE, //ro, gain_range_t SUBDEV_PROP_GAIN_NAMES, //ro, prop_names_t SUBDEV_PROP_FREQ, //rw, freq_t - SUBDEV_PROP_FREQ_MAX, //ro, freq_t - SUBDEV_PROP_FREQ_MIN, //ro, freq_t + SUBDEV_PROP_FREQ_RANGE, //ro, freq_range_t SUBDEV_PROP_ANTENNA, //rw, std::string SUBDEV_PROP_ANTENNA_NAMES, //ro, prop_names_t SUBDEV_PROP_ENABLED, //rw, bool diff --git a/host/include/uhd/simple_device.hpp b/host/include/uhd/simple_device.hpp index 69f13a8b5..c43155ff2 100644 --- a/host/include/uhd/simple_device.hpp +++ b/host/include/uhd/simple_device.hpp @@ -71,14 +71,11 @@ public: virtual std::vector get_rx_rates(void) = 0; virtual tune_result_t set_rx_freq(double freq) = 0; - virtual double get_rx_freq_min(void) = 0; - virtual double get_rx_freq_max(void) = 0; + virtual std::vector get_rx_freq_range(void) = 0; virtual void set_rx_gain(float gain) = 0; virtual float get_rx_gain(void) = 0; - virtual float get_rx_gain_min(void) = 0; - virtual float get_rx_gain_max(void) = 0; - virtual float get_rx_gain_step(void) = 0; + virtual std::vector get_rx_gain_range(void) = 0; virtual void set_rx_antenna(const std::string &ant) = 0; virtual std::string get_rx_antenna(void) = 0; @@ -92,14 +89,11 @@ public: virtual std::vector get_tx_rates(void) = 0; virtual tune_result_t set_tx_freq(double freq) = 0; - virtual double get_tx_freq_min(void) = 0; - virtual double get_tx_freq_max(void) = 0; + virtual std::vector get_tx_freq_range(void) = 0; virtual void set_tx_gain(float gain) = 0; virtual float get_tx_gain(void) = 0; - virtual float get_tx_gain_min(void) = 0; - virtual float get_tx_gain_max(void) = 0; - virtual float get_tx_gain_step(void) = 0; + virtual std::vector get_tx_gain_range(void) = 0; virtual void set_tx_antenna(const std::string &ant) = 0; virtual std::string get_tx_antenna(void) = 0; diff --git a/host/include/uhd/utils.hpp b/host/include/uhd/utils.hpp index 5d6a18b3a..2f6e4fd87 100644 --- a/host/include/uhd/utils.hpp +++ b/host/include/uhd/utils.hpp @@ -70,11 +70,6 @@ namespace std{ return has(iterable.begin(), iterable.end(), elem); } - template - T sum(const T &a, const T &b){ - return a + b; - } - template T signum(T n){ if (n < 0) return -1; if (n > 0) return 1; diff --git a/host/lib/gain_handler.cpp b/host/lib/gain_handler.cpp index 8f840ae7f..7eb87558c 100644 --- a/host/lib/gain_handler.cpp +++ b/host/lib/gain_handler.cpp @@ -25,16 +25,6 @@ using namespace uhd; -/*********************************************************************** - * helper functions - **********************************************************************/ -static gain_t gain_max(gain_t a, gain_t b){ - return std::max(a, b); -} -static gain_t gain_sum(gain_t a, gain_t b){ - return std::sum(a, b); -} - /*********************************************************************** * gain handler implementation interface **********************************************************************/ @@ -42,7 +32,7 @@ class gain_handler_impl : public gain_handler{ public: gain_handler_impl( const wax::obj &link, - const gain_props_t &gain_props, + const props_t &props, is_equal_t is_equal ); ~gain_handler_impl(void); @@ -51,15 +41,15 @@ public: private: wax::obj _link; - gain_props_t _gain_props; + props_t _props; is_equal_t _is_equal; prop_names_t get_gain_names(void); - std::vector get_gains(const wax::obj &prop_key); gain_t get_overall_gain_val(void); - gain_t get_overall_gain_min(void); - gain_t get_overall_gain_max(void); - gain_t get_overall_gain_step(void); + gain_range_t get_overall_gain_range(void); + template T get_named_prop(const wax::obj &prop, const std::string &name){ + return wax::cast(_link[named_prop_t(prop, name)]); + } }; /*********************************************************************** @@ -67,26 +57,26 @@ private: **********************************************************************/ gain_handler::sptr gain_handler::make( const wax::obj &link, - const gain_props_t &gain_props, + const props_t &props, is_equal_t is_equal ){ - return sptr(new gain_handler_impl(link, gain_props, is_equal)); + return sptr(new gain_handler_impl(link, props, is_equal)); } /*********************************************************************** * gain handler implementation methods **********************************************************************/ -gain_handler::gain_props_t::gain_props_t(void){ +gain_handler::props_t::props_t(void){ /* NOP */ } gain_handler_impl::gain_handler_impl( const wax::obj &link, - const gain_props_t &gain_props, + const props_t &props, is_equal_t is_equal ){ _link = link; - _gain_props = gain_props; + _props = props; _is_equal = is_equal; } @@ -95,31 +85,28 @@ gain_handler_impl::~gain_handler_impl(void){ } prop_names_t gain_handler_impl::get_gain_names(void){ - return wax::cast(_link[_gain_props.gain_names_prop]); + return wax::cast(_link[_props.names]); } -std::vector gain_handler_impl::get_gains(const wax::obj &prop_key){ - std::vector gains; +gain_t gain_handler_impl::get_overall_gain_val(void){ + gain_t gain_val = 0; BOOST_FOREACH(std::string name, get_gain_names()){ - gains.push_back(wax::cast(_link[named_prop_t(prop_key, name)])); + gain_val += get_named_prop(_props.value, name); } - return gains; -} - -gain_t gain_handler_impl::get_overall_gain_val(void){ - return std::reduce(get_gains(_gain_props.gain_val_prop), gain_sum); -} - -gain_t gain_handler_impl::get_overall_gain_min(void){ - return std::reduce(get_gains(_gain_props.gain_min_prop), gain_sum); -} - -gain_t gain_handler_impl::get_overall_gain_max(void){ - return std::reduce(get_gains(_gain_props.gain_max_prop), gain_sum); + return gain_val; } -gain_t gain_handler_impl::get_overall_gain_step(void){ - return std::reduce(get_gains(_gain_props.gain_step_prop), gain_max); +gain_range_t gain_handler_impl::get_overall_gain_range(void){ + gain_t gain_min = 0, gain_max = 0, gain_step = 0; + BOOST_FOREACH(std::string name, get_gain_names()){ + gain_t gain_min_tmp, gain_max_tmp, gain_step_tmp; + boost::tie(gain_min_tmp, gain_max_tmp, gain_step_tmp) = \ + get_named_prop(_props.range, name); + gain_min += gain_min_tmp; + gain_max += gain_max_tmp; + gain_step = std::max(gain_step, gain_step_tmp); + } + return gain_range_t(gain_min, gain_max, gain_step); } /*********************************************************************** @@ -135,23 +122,13 @@ bool gain_handler_impl::intercept_get(const wax::obj &key_, wax::obj &val){ return false; } - if (_is_equal(key, _gain_props.gain_val_prop)){ + if (_is_equal(key, _props.value)){ val = get_overall_gain_val(); return true; } - if (_is_equal(key, _gain_props.gain_min_prop)){ - val = get_overall_gain_min(); - return true; - } - - if (_is_equal(key, _gain_props.gain_max_prop)){ - val = get_overall_gain_max(); - return true; - } - - if (_is_equal(key, _gain_props.gain_step_prop)){ - val = get_overall_gain_step(); + if (_is_equal(key, _props.range)){ + val = get_overall_gain_range(); return true; } @@ -166,15 +143,16 @@ bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val) boost::tie(key, name) = extract_named_prop(key_); //not a gain value key... dont handle - if (not _is_equal(key, _gain_props.gain_val_prop)) return false; + if (not _is_equal(key, _props.value)) return false; gain_t gain_val = wax::cast(val); //not a wildcard... dont handle (but check name and range) if (name != ""){ assert_has(get_gain_names(), name, "gain name"); - gain_t gain_min = wax::cast(_link[named_prop_t(_gain_props.gain_min_prop, name)]); - gain_t gain_max = wax::cast(_link[named_prop_t(_gain_props.gain_max_prop, name)]); + gain_t gain_min, gain_max, gain_step; + boost::tie(gain_min, gain_max, gain_step) = \ + get_named_prop(_props.range, name); if (gain_val > gain_max or gain_val < gain_min) throw std::range_error(str( boost::format("A value of %f for gain %s is out of range of (%f, %f)") % gain_val % name % gain_min % gain_max @@ -185,16 +163,16 @@ bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val) //set the overall gain BOOST_FOREACH(std::string name, get_gain_names()){ //get the min, max, step for this gain name - gain_t gain_min = wax::cast(_link[named_prop_t(_gain_props.gain_min_prop, name)]); - gain_t gain_max = wax::cast(_link[named_prop_t(_gain_props.gain_max_prop, name)]); - gain_t gain_step = wax::cast(_link[named_prop_t(_gain_props.gain_step_prop, name)]); + gain_t gain_min, gain_max, gain_step; + boost::tie(gain_min, gain_max, gain_step) = \ + get_named_prop(_props.range, name); //clip g to be within the allowed range gain_t g = std::min(std::max(gain_val, gain_min), gain_max); //set g to be a multiple of the step size g -= fmod(g, gain_step); //set g to be the new gain - _link[named_prop_t(_gain_props.gain_val_prop, name)] = g; + _link[named_prop_t(_props.value, name)] = g; //subtract g out of the total gain left to apply gain_val -= g; } diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp index 76f3c1262..ac83ffaed 100644 --- a/host/lib/simple_device.cpp +++ b/host/lib/simple_device.cpp @@ -188,12 +188,11 @@ public: return tune(target_freq, lo_offset, _rx_subdev, _rx_ddc, false/* not tx */); } - double get_rx_freq_min(void){ - return wax::cast(_rx_subdev[SUBDEV_PROP_FREQ_MIN]); - } - - double get_rx_freq_max(void){ - return wax::cast(_rx_subdev[SUBDEV_PROP_FREQ_MAX]); + std::vector get_rx_freq_range(void){ + std::vector range(2); + boost::tie(range[0], range[1]) = \ + wax::cast(_rx_subdev[SUBDEV_PROP_FREQ_RANGE]); + return range; } void set_rx_gain(float gain){ @@ -201,19 +200,14 @@ public: } float get_rx_gain(void){ - return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN]); - } - - float get_rx_gain_min(void){ - return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN_MIN]); - } - - float get_rx_gain_max(void){ - return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN_MAX]); + return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN]); } - float get_rx_gain_step(void){ - return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN_STEP]); + std::vector get_rx_gain_range(void){ + std::vector range(3); + boost::tie(range[0], range[1], range[2]) = \ + wax::cast(_rx_subdev[SUBDEV_PROP_GAIN_RANGE]); + return range; } void set_rx_antenna(const std::string &ant){ @@ -256,12 +250,11 @@ public: return tune(target_freq, lo_offset, _tx_subdev, _tx_duc, true/* is tx */); } - double get_tx_freq_min(void){ - return wax::cast(_tx_subdev[SUBDEV_PROP_FREQ_MIN]); - } - - double get_tx_freq_max(void){ - return wax::cast(_tx_subdev[SUBDEV_PROP_FREQ_MAX]); + std::vector get_tx_freq_range(void){ + std::vector range(2); + boost::tie(range[0], range[1]) = \ + wax::cast(_tx_subdev[SUBDEV_PROP_FREQ_RANGE]); + return range; } void set_tx_gain(float gain){ @@ -269,19 +262,14 @@ public: } float get_tx_gain(void){ - return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN]); - } - - float get_tx_gain_min(void){ - return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN_MIN]); - } - - float get_tx_gain_max(void){ - return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN_MAX]); + return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN]); } - float get_tx_gain_step(void){ - return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN_STEP]); + std::vector get_tx_gain_range(void){ + std::vector range(3); + boost::tie(range[0], range[1], range[2]) = \ + wax::cast(_tx_subdev[SUBDEV_PROP_GAIN_RANGE]); + return range; } void set_tx_antenna(const std::string &ant){ diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp index 4b74e4a47..1059feb19 100644 --- a/host/lib/usrp/dboard/basic.cpp +++ b/host/lib/usrp/dboard/basic.cpp @@ -111,12 +111,13 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_GAIN: - case SUBDEV_PROP_GAIN_MAX: - case SUBDEV_PROP_GAIN_MIN: - case SUBDEV_PROP_GAIN_STEP: val = gain_t(0); return; + case SUBDEV_PROP_GAIN_RANGE: + val = gain_range_t(0, 0, 0); + return; + case SUBDEV_PROP_GAIN_NAMES: val = prop_names_t(); //empty return; @@ -125,12 +126,8 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ val = freq_t(0); return; - case SUBDEV_PROP_FREQ_MAX: - val = +_max_freq; - return; - - case SUBDEV_PROP_FREQ_MIN: - val = -_max_freq; + case SUBDEV_PROP_FREQ_RANGE: + val = freq_range_t(+_max_freq, -_max_freq); return; case SUBDEV_PROP_ANTENNA: @@ -177,13 +174,10 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_NAME: case SUBDEV_PROP_OTHERS: - case SUBDEV_PROP_GAIN_MAX: - case SUBDEV_PROP_GAIN_MIN: - case SUBDEV_PROP_GAIN_STEP: + case SUBDEV_PROP_GAIN_RANGE: case SUBDEV_PROP_GAIN_NAMES: case SUBDEV_PROP_FREQ: - case SUBDEV_PROP_FREQ_MAX: - case SUBDEV_PROP_FREQ_MIN: + case SUBDEV_PROP_FREQ_RANGE: case SUBDEV_PROP_ANTENNA_NAMES: case SUBDEV_PROP_QUADRATURE: case SUBDEV_PROP_IQ_SWAPPED: @@ -223,12 +217,13 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_GAIN: - case SUBDEV_PROP_GAIN_MAX: - case SUBDEV_PROP_GAIN_MIN: - case SUBDEV_PROP_GAIN_STEP: val = gain_t(0); return; + case SUBDEV_PROP_GAIN_RANGE: + val = gain_range_t(0, 0, 0); + return; + case SUBDEV_PROP_GAIN_NAMES: val = prop_names_t(); //empty return; @@ -237,12 +232,8 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){ val = freq_t(0); return; - case SUBDEV_PROP_FREQ_MAX: - val = +_max_freq; - return; - - case SUBDEV_PROP_FREQ_MIN: - val = -_max_freq; + case SUBDEV_PROP_FREQ_RANGE: + val = freq_range_t(+_max_freq, -_max_freq); return; case SUBDEV_PROP_ANTENNA: @@ -289,13 +280,10 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_NAME: case SUBDEV_PROP_OTHERS: - case SUBDEV_PROP_GAIN_MAX: - case SUBDEV_PROP_GAIN_MIN: - case SUBDEV_PROP_GAIN_STEP: + case SUBDEV_PROP_GAIN_RANGE: case SUBDEV_PROP_GAIN_NAMES: case SUBDEV_PROP_FREQ: - case SUBDEV_PROP_FREQ_MAX: - case SUBDEV_PROP_FREQ_MIN: + case SUBDEV_PROP_FREQ_RANGE: case SUBDEV_PROP_ANTENNA_NAMES: case SUBDEV_PROP_QUADRATURE: case SUBDEV_PROP_IQ_SWAPPED: diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 08b92e62a..23c2921d2 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -70,16 +70,15 @@ public: subdev_proxy(dboard_base::sptr subdev, type_t type) : _subdev(subdev), _type(type){ //initialize gain props struct - gain_handler::gain_props_t gain_props; - gain_props.gain_val_prop = SUBDEV_PROP_GAIN; - gain_props.gain_min_prop = SUBDEV_PROP_GAIN_MIN; - gain_props.gain_max_prop = SUBDEV_PROP_GAIN_MAX; - gain_props.gain_step_prop = SUBDEV_PROP_GAIN_STEP; - gain_props.gain_names_prop = SUBDEV_PROP_GAIN_NAMES; + gain_handler::props_t gain_props; + gain_props.value = SUBDEV_PROP_GAIN; + gain_props.range = SUBDEV_PROP_GAIN_RANGE; + gain_props.names = SUBDEV_PROP_GAIN_NAMES; //make a new gain handler _gain_handler = gain_handler::make( - this->get_link(), gain_props, boost::bind(&gain_handler::is_equal, _1, _2) + this->get_link(), gain_props, + boost::bind(&gain_handler::is_equal, _1, _2) ); } diff --git a/host/test/gain_handler_test.cpp b/host/test/gain_handler_test.cpp index 9a6a50dab..51497b741 100644 --- a/host/test/gain_handler_test.cpp +++ b/host/test/gain_handler_test.cpp @@ -25,10 +25,8 @@ using namespace uhd; enum prop_t{ - PROP_GAIN, - PROP_GAIN_MIN, - PROP_GAIN_MAX, - PROP_GAIN_STEP, + PROP_GAIN_VALUE, + PROP_GAIN_RANGE, PROP_GAIN_NAMES }; @@ -36,24 +34,19 @@ class gainful_obj : public wax::obj{ public: gainful_obj(void){ //initialize gain props struct - gain_handler::gain_props_t gain_props; - gain_props.gain_val_prop = PROP_GAIN; - gain_props.gain_min_prop = PROP_GAIN_MIN; - gain_props.gain_max_prop = PROP_GAIN_MAX; - gain_props.gain_step_prop = PROP_GAIN_STEP; - gain_props.gain_names_prop = PROP_GAIN_NAMES; + gain_handler::props_t gain_props; + gain_props.value = PROP_GAIN_VALUE; + gain_props.range = PROP_GAIN_RANGE; + gain_props.names = PROP_GAIN_NAMES; //make a new gain handler _gain_handler = gain_handler::make( - this->get_link(), gain_props, boost::bind(&gain_handler::is_equal, _1, _2) + this->get_link(), gain_props, + boost::bind(&gain_handler::is_equal, _1, _2) ); - _gains["g0"] = 0; - _gains["g1"] = 0; - _gains_min["g0"] = -10; - _gains_min["g1"] = 0; - _gains_max["g0"] = 0; - _gains_max["g1"] = 100; - _gains_step["g0"] = .1; - _gains_step["g1"] = 1.5; + _gain_values["g0"] = 0; + _gain_values["g1"] = 0; + _gain_ranges["g0"] = gain_range_t(-10, 0, .1); + _gain_ranges["g1"] = gain_range_t(0, 100, 1.5); } ~gainful_obj(void){} @@ -67,24 +60,16 @@ private: //handle the get request conditioned on the key switch(wax::cast(key)){ - case PROP_GAIN: - val = _gains[name]; + case PROP_GAIN_VALUE: + val = _gain_values[name]; return; - case PROP_GAIN_MIN: - val = _gains_min[name]; - return; - - case PROP_GAIN_MAX: - val = _gains_max[name]; - return; - - case PROP_GAIN_STEP: - val = _gains_step[name]; + case PROP_GAIN_RANGE: + val = _gain_ranges[name]; return; case PROP_GAIN_NAMES: - val = prop_names_t(_gains.get_keys()); + val = _gain_values.get_keys(); return; } } @@ -97,23 +82,19 @@ private: //handle the get request conditioned on the key switch(wax::cast(key)){ - case PROP_GAIN: - _gains[name] = wax::cast(val); + case PROP_GAIN_VALUE: + _gain_values[name] = wax::cast(val); return; - case PROP_GAIN_MIN: - case PROP_GAIN_MAX: - case PROP_GAIN_STEP: + case PROP_GAIN_RANGE: case PROP_GAIN_NAMES: throw std::runtime_error("cannot set this property"); } } gain_handler::sptr _gain_handler; - uhd::dict _gains; - uhd::dict _gains_min; - uhd::dict _gains_max; - uhd::dict _gains_step; + uhd::dict _gain_values; + uhd::dict _gain_ranges; }; @@ -122,17 +103,20 @@ BOOST_AUTO_TEST_CASE(test_gain_handler){ gainful_obj go0; BOOST_CHECK_THROW( - wax::cast(go0[named_prop_t(PROP_GAIN, "fail")]), + wax::cast(go0[named_prop_t(PROP_GAIN_VALUE, "fail")]), std::exception ); std::cout << "verifying the overall min, max, step" << std::endl; - BOOST_CHECK_EQUAL(wax::cast(go0[PROP_GAIN_MIN]), gain_t(-10)); - BOOST_CHECK_EQUAL(wax::cast(go0[PROP_GAIN_MAX]), gain_t(100)); - BOOST_CHECK_EQUAL(wax::cast(go0[PROP_GAIN_STEP]), gain_t(1.5)); + gain_t gain_min, gain_max, gain_step; + boost::tie(gain_min, gain_max, gain_step) = \ + wax::cast(go0[PROP_GAIN_RANGE]); + BOOST_CHECK_EQUAL(gain_min, gain_t(-10)); + BOOST_CHECK_EQUAL(gain_max, gain_t(100)); + BOOST_CHECK_EQUAL(gain_step, gain_t(1.5)); std::cout << "verifying the overall gain" << std::endl; - go0[named_prop_t(PROP_GAIN, "g0")] = gain_t(-5); - go0[named_prop_t(PROP_GAIN, "g1")] = gain_t(30); - BOOST_CHECK_EQUAL(wax::cast(go0[PROP_GAIN]), gain_t(25)); + go0[named_prop_t(PROP_GAIN_VALUE, "g0")] = gain_t(-5); + go0[named_prop_t(PROP_GAIN_VALUE, "g1")] = gain_t(30); + BOOST_CHECK_EQUAL(wax::cast(go0[PROP_GAIN_VALUE]), gain_t(25)); } -- cgit v1.2.3 From fc40ff2f1327d01c72c4d7dbc07a14e473251981 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 15 Mar 2010 17:43:10 -0700 Subject: Replaced uses of wax:cast with the templated as method (like in boost program options). --- host/include/uhd/gain_handler.hpp | 2 +- host/include/uhd/props.hpp | 2 +- host/include/uhd/wax.hpp | 43 ++++++++++------------------- host/lib/gain_handler.cpp | 6 ++--- host/lib/simple_device.cpp | 54 ++++++++++++++++++------------------- host/lib/usrp/dboard/basic.cpp | 16 +++++------ host/lib/usrp/usrp2/dboard_impl.cpp | 4 +-- host/lib/usrp/usrp2/dsp_impl.cpp | 24 ++++++++--------- host/lib/usrp/usrp2/mboard_impl.cpp | 26 +++++++++--------- host/lib/usrp/usrp2/usrp2_impl.cpp | 2 +- host/lib/wax.cpp | 6 ++--- host/test/gain_handler_test.cpp | 12 ++++----- host/test/wax_test.cpp | 15 ++++++----- 13 files changed, 99 insertions(+), 113 deletions(-) (limited to 'host/lib/simple_device.cpp') diff --git a/host/include/uhd/gain_handler.hpp b/host/include/uhd/gain_handler.hpp index 2d3f8a3f4..a71d63c84 100644 --- a/host/include/uhd/gain_handler.hpp +++ b/host/include/uhd/gain_handler.hpp @@ -74,7 +74,7 @@ public: */ template static bool is_equal(const wax::obj &a, const wax::obj &b){ try{ - return wax::cast(a) == wax::cast(b); + return a.as() == b.as(); } catch(const wax::bad_cast &){ return false; diff --git a/host/include/uhd/props.hpp b/host/include/uhd/props.hpp index f2ba1769f..0dddba647 100644 --- a/host/include/uhd/props.hpp +++ b/host/include/uhd/props.hpp @@ -57,7 +57,7 @@ namespace uhd{ */ inline named_prop_t extract_named_prop(const wax::obj &key, const std::string &name = ""){ if (key.type() == typeid(named_prop_t)){ - return wax::cast(key); + return key.as(); } return named_prop_t(key, name); } diff --git a/host/include/uhd/wax.hpp b/host/include/uhd/wax.hpp index 4fd54ba14..0291a06b7 100644 --- a/host/include/uhd/wax.hpp +++ b/host/include/uhd/wax.hpp @@ -19,31 +19,34 @@ #define INCLUDED_WAX_HPP #include -#include /*! * WAX - it's a metaphor! * - * The WAX framework allows object to have generic/anyobj properties. + * The WAX framework allows an object to have generic/anyobj properties. * These properties can be addressed through generic/anyobj identifiers. - * A property of a WAX object may even be another WAX object. * - * When a property is a WAX object, the returned value must be an obj pointer. - * A WAX object provides two objs of pointers: obj::ptr and obj::sptr. - * The choice of pointer vs smart pointer depends on the owner of the memory. + * The WAX object itself is an anytype container much like boost::any. + * To retrieve the value of the appropriate type, use my_obj.as(). * * Proprties may be referenced though the [] overloaded operator. * The [] operator returns a special proxy that allows for assigment. * Also, the [] operators may be chained as in the folowing examples: - * my_obj[prop1][prop2][prop3] = value - * value = my_obj[prop1][prop2][prop3] + * my_obj[prop1][prop2][prop3] = value; + * value = my_obj[prop1][prop2][prop3].as(); * - * Any value returned from an access operation is of wax::obj. - * To use this value, it must be cast with wax::cast(value). + * Property nesting occurs when a WAX object gets another object's link. + * This special link is obtained through a call to my_obj.get_link(). */ namespace wax{ + /*! + * The wax::bad cast will be thrown when + * cast is called with the wrong typeid. + */ + typedef boost::bad_any_cast bad_cast; + /*! * WAX object base class: * @@ -126,7 +129,7 @@ namespace wax{ /*! * Cast this obj into the desired type. - * Usage myobj.as() + * Usage: myobj.as() * * \return an object of the desired type * \throw wax::bad_cast when the cast fails @@ -154,24 +157,6 @@ namespace wax{ }; - /*! - * The wax::bad cast will be thrown when - * cast is called with the wrong typeid. - */ - typedef boost::bad_any_cast bad_cast; - - /*! - * Cast a wax::obj into the desired obj. - * Usage wax::cast(my_value). - * - * \param val the obj to cast - * \return an object of the desired type - * \throw wax::bad_cast when the cast fails - */ - template T cast(const obj &val){ - return val.as(); - } - } //namespace wax #endif /* INCLUDED_WAX_HPP */ diff --git a/host/lib/gain_handler.cpp b/host/lib/gain_handler.cpp index 7eb87558c..847bc0528 100644 --- a/host/lib/gain_handler.cpp +++ b/host/lib/gain_handler.cpp @@ -48,7 +48,7 @@ private: gain_t get_overall_gain_val(void); gain_range_t get_overall_gain_range(void); template T get_named_prop(const wax::obj &prop, const std::string &name){ - return wax::cast(_link[named_prop_t(prop, name)]); + return _link[named_prop_t(prop, name)].as(); } }; @@ -85,7 +85,7 @@ gain_handler_impl::~gain_handler_impl(void){ } prop_names_t gain_handler_impl::get_gain_names(void){ - return wax::cast(_link[_props.names]); + return _link[_props.names].as(); } gain_t gain_handler_impl::get_overall_gain_val(void){ @@ -145,7 +145,7 @@ bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val) //not a gain value key... dont handle if (not _is_equal(key, _props.value)) return false; - gain_t gain_val = wax::cast(val); + gain_t gain_val = val.as(); //not a wildcard... dont handle (but check name and range) if (name != ""){ diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp index ac83ffaed..62a38cb79 100644 --- a/host/lib/simple_device.cpp +++ b/host/lib/simple_device.cpp @@ -42,15 +42,15 @@ static tune_result_t tune( bool is_tx ){ wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ]; - bool subdev_quadrature = wax::cast(subdev[SUBDEV_PROP_QUADRATURE]); - bool subdev_spectrum_inverted = wax::cast(subdev[SUBDEV_PROP_SPECTRUM_INVERTED]); + 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 = wax::cast(dxc[std::string("rate")]); + 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 = wax::cast(subdev_freq_proxy); + double actual_inter_freq = subdev_freq_proxy.as(); // Calculate the DDC setting that will downconvert the baseband from the // daughterboard to our target frequency. @@ -77,7 +77,7 @@ static tune_result_t tune( target_dxc_freq *= (is_tx)? -1.0 : +1.0; dxc_freq_proxy = target_dxc_freq; - double actual_dxc_freq = wax::cast(dxc_freq_proxy); + double actual_dxc_freq = dxc_freq_proxy.as(); //return some kind of tune result tuple/struct tune_result_t tune_result; @@ -117,8 +117,8 @@ device_addr_t args_to_device_addr(const std::string &args){ static std::vector get_xx_rates(wax::obj decerps, wax::obj rate){ std::vector rates; - BOOST_FOREACH(size_t decerp, wax::cast >(decerps)){ - rates.push_back(wax::cast(rate)/decerp); + BOOST_FOREACH(size_t decerp, decerps.as >()){ + rates.push_back(rate.as()/decerp); } return rates; } @@ -146,7 +146,7 @@ public: } std::string get_name(void){ - return wax::cast(_mboard[MBOARD_PROP_NAME]); + return _mboard[MBOARD_PROP_NAME].as(); } /******************************************************************* @@ -157,21 +157,21 @@ public: } bool get_streaming(void){ - return wax::cast(_rx_ddc[std::string("enabled")]); + return _rx_ddc[std::string("enabled")].as(); } /******************************************************************* * RX methods ******************************************************************/ void set_rx_rate(double rate){ - double samp_rate = wax::cast(_rx_ddc[std::string("rate")]); + double samp_rate = _rx_ddc[std::string("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 = wax::cast(_rx_ddc[std::string("rate")]); - size_t decim = wax::cast(_rx_ddc[std::string("decim")]); + double samp_rate = _rx_ddc[std::string("rate")].as(); + size_t decim = _rx_ddc[std::string("decim")].as(); return samp_rate/decim; } @@ -182,7 +182,7 @@ public: tune_result_t set_rx_freq(double target_freq){ double lo_offset = 0.0; //if the local oscillator will be in the passband, use an offset - if (wax::cast(_rx_subdev[SUBDEV_PROP_LO_INTERFERES])){ + if (_rx_subdev[SUBDEV_PROP_LO_INTERFERES].as()){ lo_offset = get_rx_rate()*2.0; } return tune(target_freq, lo_offset, _rx_subdev, _rx_ddc, false/* not tx */); @@ -191,7 +191,7 @@ public: std::vector get_rx_freq_range(void){ std::vector range(2); boost::tie(range[0], range[1]) = \ - wax::cast(_rx_subdev[SUBDEV_PROP_FREQ_RANGE]); + _rx_subdev[SUBDEV_PROP_FREQ_RANGE].as(); return range; } @@ -200,13 +200,13 @@ public: } float get_rx_gain(void){ - return wax::cast(_rx_subdev[SUBDEV_PROP_GAIN]); + return _rx_subdev[SUBDEV_PROP_GAIN].as(); } std::vector get_rx_gain_range(void){ std::vector range(3); boost::tie(range[0], range[1], range[2]) = \ - wax::cast(_rx_subdev[SUBDEV_PROP_GAIN_RANGE]); + _rx_subdev[SUBDEV_PROP_GAIN_RANGE].as(); return range; } @@ -215,25 +215,25 @@ public: } std::string get_rx_antenna(void){ - return wax::cast(_rx_subdev[SUBDEV_PROP_ANTENNA]); + return _rx_subdev[SUBDEV_PROP_ANTENNA].as(); } std::vector get_rx_antennas(void){ - return wax::cast >(_rx_subdev[SUBDEV_PROP_ANTENNA_NAMES]); + return _rx_subdev[SUBDEV_PROP_ANTENNA_NAMES].as >(); } /******************************************************************* * TX methods ******************************************************************/ void set_tx_rate(double rate){ - double samp_rate = wax::cast(_tx_duc[std::string("rate")]); + double samp_rate = _tx_duc[std::string("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 = wax::cast(_tx_duc[std::string("rate")]); - size_t interp = wax::cast(_tx_duc[std::string("interp")]); + double samp_rate = _tx_duc[std::string("rate")].as(); + size_t interp = _tx_duc[std::string("interp")].as(); return samp_rate/interp; } @@ -244,7 +244,7 @@ public: tune_result_t set_tx_freq(double target_freq){ double lo_offset = 0.0; //if the local oscillator will be in the passband, use an offset - if (wax::cast(_tx_subdev[SUBDEV_PROP_LO_INTERFERES])){ + if (_tx_subdev[SUBDEV_PROP_LO_INTERFERES].as()){ lo_offset = get_tx_rate()*2.0; } return tune(target_freq, lo_offset, _tx_subdev, _tx_duc, true/* is tx */); @@ -253,7 +253,7 @@ public: std::vector get_tx_freq_range(void){ std::vector range(2); boost::tie(range[0], range[1]) = \ - wax::cast(_tx_subdev[SUBDEV_PROP_FREQ_RANGE]); + _tx_subdev[SUBDEV_PROP_FREQ_RANGE].as(); return range; } @@ -262,13 +262,13 @@ public: } float get_tx_gain(void){ - return wax::cast(_tx_subdev[SUBDEV_PROP_GAIN]); + return _tx_subdev[SUBDEV_PROP_GAIN].as(); } std::vector get_tx_gain_range(void){ std::vector range(3); boost::tie(range[0], range[1], range[2]) = \ - wax::cast(_tx_subdev[SUBDEV_PROP_GAIN_RANGE]); + _tx_subdev[SUBDEV_PROP_GAIN_RANGE].as(); return range; } @@ -277,11 +277,11 @@ public: } std::string get_tx_antenna(void){ - return wax::cast(_tx_subdev[SUBDEV_PROP_ANTENNA]); + return _tx_subdev[SUBDEV_PROP_ANTENNA].as(); } std::vector get_tx_antennas(void){ - return wax::cast >(_tx_subdev[SUBDEV_PROP_ANTENNA_NAMES]); + return _tx_subdev[SUBDEV_PROP_ANTENNA_NAMES].as >(); } private: diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp index e719950e8..095b77ce1 100644 --- a/host/lib/usrp/dboard/basic.cpp +++ b/host/lib/usrp/dboard/basic.cpp @@ -98,7 +98,7 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case SUBDEV_PROP_NAME: val = std::string(str(boost::format("%s:%s") % dboard_id::to_string(get_rx_id()) @@ -159,14 +159,14 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case SUBDEV_PROP_GAIN: - ASSERT_THROW(wax::cast(val) == gain_t(0)); + ASSERT_THROW(val.as() == gain_t(0)); return; case SUBDEV_PROP_ANTENNA: - ASSERT_THROW(wax::cast(val) == std::string("")); + ASSERT_THROW(val.as() == std::string("")); return; case SUBDEV_PROP_ENABLED: @@ -207,7 +207,7 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){ boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case SUBDEV_PROP_NAME: val = dboard_id::to_string(get_tx_id()); return; @@ -265,14 +265,14 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case SUBDEV_PROP_GAIN: - ASSERT_THROW(wax::cast(val) == gain_t(0)); + ASSERT_THROW(val.as() == gain_t(0)); return; case SUBDEV_PROP_ANTENNA: - ASSERT_THROW(wax::cast(val) == std::string("")); + ASSERT_THROW(val.as() == std::string("")); return; case SUBDEV_PROP_ENABLED: diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index da05c3241..6d957436e 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -71,7 +71,7 @@ void usrp2_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case DBOARD_PROP_NAME: val = std::string("usrp2 dboard (rx unit)"); return; @@ -101,7 +101,7 @@ void usrp2_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case DBOARD_PROP_NAME: val = std::string("usrp2 dboard (tx unit)"); return; diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index cb7f58ec8..7520c1757 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -102,7 +102,7 @@ void usrp2_impl::update_ddc_enabled(void){ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){ //handle the case where the key is an expected dsp property if (key.type() == typeid(dsp_prop_t)){ - switch(wax::cast(key)){ + switch(key.as()){ case DSP_PROP_NAME: val = std::string("usrp2 ddc0"); return; @@ -123,7 +123,7 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){ } //handle string-based properties specific to this dsp - std::string key_name = wax::cast(key); + std::string key_name = key.as(); if (key_name == "rate"){ val = get_master_clock_freq(); return; @@ -152,9 +152,9 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){ //handle string-based properties specific to this dsp - std::string key_name = wax::cast(key); + std::string key_name = key.as(); if (key_name == "decim"){ - size_t new_decim = wax::cast(val); + size_t new_decim = val.as(); assert_has( _allowed_decim_and_interp_rates, new_decim, "usrp2 decimation" @@ -164,7 +164,7 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){ return; } else if (key_name == "freq"){ - freq_t new_freq = wax::cast(val); + freq_t new_freq = val.as(); ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0); ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0); _ddc_freq = new_freq; //shadow @@ -172,13 +172,13 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){ return; } else if (key_name == "enabled"){ - bool new_enabled = wax::cast(val); + bool new_enabled = val.as(); _ddc_enabled = new_enabled; //shadow update_ddc_enabled(); return; } else if (key_name == "stream_at"){ - time_spec_t new_stream_at = wax::cast(val); + time_spec_t new_stream_at = val.as(); _ddc_stream_at = new_stream_at; //shadow //update_ddc_enabled(); //dont update from here return; @@ -236,7 +236,7 @@ void usrp2_impl::update_duc_config(void){ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){ //handle the case where the key is an expected dsp property if (key.type() == typeid(dsp_prop_t)){ - switch(wax::cast(key)){ + switch(key.as()){ case DSP_PROP_NAME: val = std::string("usrp2 duc0"); return; @@ -255,7 +255,7 @@ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){ } //handle string-based properties specific to this dsp - std::string key_name = wax::cast(key); + std::string key_name = key.as(); if (key_name == "rate"){ val = get_master_clock_freq(); return; @@ -280,9 +280,9 @@ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){ void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){ //handle string-based properties specific to this dsp - std::string key_name = wax::cast(key); + std::string key_name = key.as(); if (key_name == "interp"){ - size_t new_interp = wax::cast(val); + size_t new_interp = val.as(); assert_has( _allowed_decim_and_interp_rates, new_interp, "usrp2 interpolation" @@ -292,7 +292,7 @@ void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){ return; } else if (key_name == "freq"){ - freq_t new_freq = wax::cast(val); + freq_t new_freq = val.as(); ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0); ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0); _duc_freq = new_freq; //shadow diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index b66de8262..4b15c7f3e 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -91,7 +91,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ //handle the other props if (key.type() == typeid(std::string)){ - if (wax::cast(key) == "mac-addr"){ + if (key.as() == "mac-addr"){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_MAC_ADDR_BRO); @@ -105,7 +105,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; } - if (wax::cast(key) == "ip-addr"){ + if (key.as() == "ip-addr"){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO); @@ -121,7 +121,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ } //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case MBOARD_PROP_NAME: val = std::string("usrp2 mboard"); return; @@ -208,11 +208,11 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ //handle the other props if (key.type() == typeid(std::string)){ - if (wax::cast(key) == "mac-addr"){ + if (key.as() == "mac-addr"){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_HERE_IS_A_NEW_MAC_ADDR_BRO); - mac_addr_t mac_addr(wax::cast(val)); + mac_addr_t mac_addr(val.as()); std::memcpy(out_data.data.mac_addr, &mac_addr, sizeof(mac_addr_t)); //send and recv @@ -221,11 +221,11 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ return; } - if (wax::cast(key) == "ip-addr"){ + if (key.as() == "ip-addr"){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_HERE_IS_A_NEW_IP_ADDR_BRO); - out_data.data.ip_addr = htonl(boost::asio::ip::address_v4::from_string(wax::cast(val)).to_ulong()); + out_data.data.ip_addr = htonl(boost::asio::ip::address_v4::from_string(val.as()).to_ulong()); //send and recv usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); @@ -235,10 +235,10 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ } //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case MBOARD_PROP_PPS_SOURCE:{ - std::string name = wax::cast(val); + std::string name = val.as(); assert_has(_pps_source_dict.get_keys(), name, "usrp2 pps source"); _pps_source = name; //shadow update_clock_config(); @@ -246,7 +246,7 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ return; case MBOARD_PROP_PPS_POLARITY:{ - std::string name = wax::cast(val); + std::string name = val.as(); assert_has(_pps_polarity_dict.get_keys(), name, "usrp2 pps polarity"); _pps_polarity = name; //shadow update_clock_config(); @@ -254,7 +254,7 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ return; case MBOARD_PROP_REF_SOURCE:{ - std::string name = wax::cast(val); + std::string name = val.as(); assert_has(_ref_source_dict.get_keys(), name, "usrp2 reference source"); _ref_source = name; //shadow update_clock_config(); @@ -262,12 +262,12 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ return; case MBOARD_PROP_TIME_NOW:{ - set_time_spec(wax::cast(val), true); + set_time_spec(val.as(), true); return; } case MBOARD_PROP_TIME_NEXT_PPS:{ - set_time_spec(wax::cast(val), false); + set_time_spec(val.as(), false); return; } diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 850a738d4..22b7e109f 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -184,7 +184,7 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){ boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case DEVICE_PROP_NAME: val = std::string("usrp2 device"); return; diff --git a/host/lib/wax.cpp b/host/lib/wax.cpp index 0348d9a66..0e2e82a3a 100644 --- a/host/lib/wax.cpp +++ b/host/lib/wax.cpp @@ -39,7 +39,7 @@ public: wax::obj & operator()(void) const{ //recursively resolve link args to get at original pointer if (_obj_ptr->type() == typeid(link_args_t)){ - return wax::cast(*_obj_ptr)(); + return _obj_ptr->as()(); } return *const_cast(_obj_ptr); } @@ -61,7 +61,7 @@ public: _obj_link = obj_ptr->get_link(); } wax::obj & operator()(void) const{ - return wax::cast(_obj_link)(); + return _obj_link.as()(); } const wax::obj & key(void) const{ return _key; @@ -94,7 +94,7 @@ wax::obj wax::obj::operator[](const obj &key){ obj val = resolve(); //check if its a special link and call if (val.type() == typeid(link_args_t)){ - return cast(val)()[key]; + return val.as()()[key]; } //unknown obj throw std::runtime_error("cannot use [] on non wax::obj link"); diff --git a/host/test/gain_handler_test.cpp b/host/test/gain_handler_test.cpp index 51497b741..a4005c0de 100644 --- a/host/test/gain_handler_test.cpp +++ b/host/test/gain_handler_test.cpp @@ -59,7 +59,7 @@ private: boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case PROP_GAIN_VALUE: val = _gain_values[name]; return; @@ -81,9 +81,9 @@ private: boost::tie(key, name) = extract_named_prop(key_); //handle the get request conditioned on the key - switch(wax::cast(key)){ + switch(key.as()){ case PROP_GAIN_VALUE: - _gain_values[name] = wax::cast(val); + _gain_values[name] = val.as(); return; case PROP_GAIN_RANGE: @@ -103,14 +103,14 @@ BOOST_AUTO_TEST_CASE(test_gain_handler){ gainful_obj go0; BOOST_CHECK_THROW( - wax::cast(go0[named_prop_t(PROP_GAIN_VALUE, "fail")]), + go0[named_prop_t(PROP_GAIN_VALUE, "fail")].as(), std::exception ); std::cout << "verifying the overall min, max, step" << std::endl; gain_t gain_min, gain_max, gain_step; boost::tie(gain_min, gain_max, gain_step) = \ - wax::cast(go0[PROP_GAIN_RANGE]); + go0[PROP_GAIN_RANGE].as(); BOOST_CHECK_EQUAL(gain_min, gain_t(-10)); BOOST_CHECK_EQUAL(gain_max, gain_t(100)); BOOST_CHECK_EQUAL(gain_step, gain_t(1.5)); @@ -118,5 +118,5 @@ BOOST_AUTO_TEST_CASE(test_gain_handler){ std::cout << "verifying the overall gain" << std::endl; go0[named_prop_t(PROP_GAIN_VALUE, "g0")] = gain_t(-5); go0[named_prop_t(PROP_GAIN_VALUE, "g1")] = gain_t(30); - BOOST_CHECK_EQUAL(wax::cast(go0[PROP_GAIN_VALUE]), gain_t(25)); + BOOST_CHECK_EQUAL(go0[PROP_GAIN_VALUE].as(), gain_t(25)); } diff --git a/host/test/wax_test.cpp b/host/test/wax_test.cpp index e5e1adc25..b793b2690 100644 --- a/host/test/wax_test.cpp +++ b/host/test/wax_test.cpp @@ -17,14 +17,15 @@ #include #include +#include enum opt_a_t{OPTION_A_0, OPTION_A_1}; enum opt_b_t{OPTION_B_0, OPTION_B_1}; BOOST_AUTO_TEST_CASE(test_enums){ wax::obj opta = OPTION_A_0; - BOOST_CHECK_THROW(wax::cast(opta), wax::bad_cast); - BOOST_CHECK_EQUAL(wax::cast(opta), OPTION_A_0); + BOOST_CHECK_THROW(opta.as(), wax::bad_cast); + BOOST_CHECK_EQUAL(opta.as(), OPTION_A_0); } /*********************************************************************** @@ -48,14 +49,14 @@ public: } void get(const wax::obj &key, wax::obj &value){ if (d_subs.size() == 0){ - value = d_nums[wax::cast(key)]; + value = d_nums[key.as()]; }else{ - value = d_subs[wax::cast(key)].get_link(); + value = d_subs[key.as()].get_link(); } } void set(const wax::obj &key, const wax::obj &value){ if (d_subs.size() == 0){ - d_nums[wax::cast(key)] = wax::cast(value); + d_nums[key.as()] = value.as(); }else{ throw std::runtime_error("cant set to a wax demo with sub demos"); } @@ -81,7 +82,7 @@ BOOST_AUTO_TEST_CASE(test_set_get){ float val = i * j * k + i + j + k; //std::cout << i << " " << j << " " << k << std::endl; wd[i][j][k] = val; - BOOST_CHECK_EQUAL(val, wax::cast(wd[i][j][k])); + BOOST_CHECK_EQUAL(val, wd[i][j][k].as()); } } } @@ -94,5 +95,5 @@ BOOST_AUTO_TEST_CASE(test_proxy){ std::cout << "assign proxy" << std::endl; wax::obj a = p[size_t(0)]; - BOOST_CHECK_EQUAL(wax::cast(a), float(5)); + BOOST_CHECK_EQUAL(a.as(), float(5)); } -- cgit v1.2.3 From 83c463d09613b72817a837117c5f0b23975c8def Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 16 Mar 2010 19:42:38 -0700 Subject: changes to get tuning working --- host/lib/simple_device.cpp | 12 ++++++++++-- host/lib/usrp/dboard/basic.cpp | 8 ++++++-- host/lib/usrp/usrp2/io_impl.cpp | 2 +- 3 files changed, 17 insertions(+), 5 deletions(-) (limited to 'host/lib/simple_device.cpp') diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp index 62a38cb79..79b035071 100644 --- a/host/lib/simple_device.cpp +++ b/host/lib/simple_device.cpp @@ -133,8 +133,16 @@ public: _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")]; - _rx_subdev = _mboard[MBOARD_PROP_RX_DBOARD][DBOARD_PROP_SUBDEV]; - _tx_subdev = _mboard[MBOARD_PROP_TX_DBOARD][DBOARD_PROP_SUBDEV]; + + //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_device_impl(void){ diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp index f88faf6a0..02b391244 100644 --- a/host/lib/usrp/dboard/basic.cpp +++ b/host/lib/usrp/dboard/basic.cpp @@ -172,11 +172,13 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; // it wont do you much good, but you can set it + case SUBDEV_PROP_FREQ: + return; // it wont do you much good, but you can set it + case SUBDEV_PROP_NAME: case SUBDEV_PROP_OTHERS: case SUBDEV_PROP_GAIN_RANGE: case SUBDEV_PROP_GAIN_NAMES: - case SUBDEV_PROP_FREQ: case SUBDEV_PROP_FREQ_RANGE: case SUBDEV_PROP_ANTENNA_NAMES: case SUBDEV_PROP_QUADRATURE: @@ -278,11 +280,13 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ case SUBDEV_PROP_ENABLED: return; // it wont do you much good, but you can set it + case SUBDEV_PROP_FREQ: + return; // it wont do you much good, but you can set it + case SUBDEV_PROP_NAME: case SUBDEV_PROP_OTHERS: case SUBDEV_PROP_GAIN_RANGE: case SUBDEV_PROP_GAIN_NAMES: - case SUBDEV_PROP_FREQ: case SUBDEV_PROP_FREQ_RANGE: case SUBDEV_PROP_ANTENNA_NAMES: case SUBDEV_PROP_QUADRATURE: diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index cc7746720..e52c1e576 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -149,7 +149,7 @@ void usrp2_impl::recv_raw(rx_metadata_t &metadata){ //handle the packet count / sequence number size_t expected_packet_count = _rx_stream_id_to_packet_seq[metadata.stream_id]; if (packet_count_out != expected_packet_count){ - std::cerr << "bad packet count: " << packet_count_out << std::endl; + std::cerr << "S" << (packet_count_out - expected_packet_count)%16; } _rx_stream_id_to_packet_seq[metadata.stream_id] = (packet_count_out+1)%16; -- cgit v1.2.3 From d1ecc555e53770f1a5608000352f56f48c36c310 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 21 Mar 2010 00:58:34 -0700 Subject: Moved typedefs from props.hpp into new file types.hpp. Created structs to replace range tuples, and clock config struct. Merged clock config props into one property using config struct. Added templated dict construction to use the assign::map_list_of. Added gcc flag to set visibility to hidden and use the api macro. --- host/CMakeLists.txt | 4 +- host/include/uhd/CMakeLists.txt | 1 + host/include/uhd/dict.hpp | 13 +++ host/include/uhd/props.hpp | 33 ++----- host/include/uhd/simple_device.hpp | 26 +---- host/include/uhd/types.hpp | 83 ++++++++++++++++ host/include/uhd/utils.hpp | 5 +- host/lib/CMakeLists.txt | 3 +- host/lib/gain_handler.cpp | 28 +++--- host/lib/simple_device.cpp | 33 ++----- host/lib/transport/udp_zero_copy_asio.cpp | 154 ++++++++++++++++++++++++++++++ host/lib/transport/udp_zero_copy_none.cpp | 154 ------------------------------ host/lib/types.cpp | 57 +++++++++++ host/lib/usrp/dboard/basic.cpp | 1 + host/lib/usrp/usrp2/mboard_impl.cpp | 74 ++++++-------- host/lib/usrp/usrp2/usrp2_impl.hpp | 11 ++- host/test/gain_handler_test.cpp | 11 +-- 17 files changed, 388 insertions(+), 303 deletions(-) create mode 100644 host/include/uhd/types.hpp create mode 100644 host/lib/transport/udp_zero_copy_asio.cpp delete mode 100644 host/lib/transport/udp_zero_copy_none.cpp create mode 100644 host/lib/types.cpp (limited to 'host/lib/simple_device.cpp') diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 29d721464..2f5d03f7d 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -58,11 +58,13 @@ IF(UNIX) UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-Wextra HAVE_WEXTRA) UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-pedantic HAVE_PEDANTIC) UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-ansi HAVE_ANSI) + #only export symbols that are declared to be part of the uhd api: + UHD_ADD_OPTIONAL_CXX_COMPILER_FLAG(-fvisibility=hidden HAVE_VISIBILITY_HIDDEN) ENDIF(UNIX) IF(WIN32) ADD_DEFINITIONS(-Dnot=! -Dand=&& -Dor=||) #logical operators - ADD_DEFINITIONS(-D_WIN32_WINNT=0x0501) #as requested by vs + ADD_DEFINITIONS(-D_WIN32_WINNT=0x0501) #minimum version required is windows xp ADD_DEFINITIONS(-DNOMINMAX) #disables stupidity and enables std::min and std::max ADD_DEFINITIONS(-D_SCL_SECURE_NO_WARNINGS) #avoid warnings from boost::split ADD_DEFINITIONS(-DBOOST_ALL_DYN_LINK) #setup boost auto-linking in msvc diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index 17c260c24..3d00462cf 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -29,6 +29,7 @@ INSTALL(FILES props.hpp simple_device.hpp time_spec.hpp + types.hpp utils.hpp wax.hpp DESTINATION ${HEADER_DIR}/uhd diff --git a/host/include/uhd/dict.hpp b/host/include/uhd/dict.hpp index 8f7cd5a0f..f08493952 100644 --- a/host/include/uhd/dict.hpp +++ b/host/include/uhd/dict.hpp @@ -39,6 +39,19 @@ namespace uhd{ /* NOP */ } + /*! + * Input iterator constructor: + * Makes boost::assign::map_list_of work. + * \param first the begin iterator + * \param last the end iterator + */ + template + dict(InputIterator first, InputIterator last){ + for(InputIterator it = first; it != last; it++){ + _map.push_back(*it); + } + } + /*! * Destroy this dict. */ diff --git a/host/include/uhd/props.hpp b/host/include/uhd/props.hpp index 7229d4a12..41e0eff63 100644 --- a/host/include/uhd/props.hpp +++ b/host/include/uhd/props.hpp @@ -18,34 +18,14 @@ #ifndef INCLUDED_UHD_PROPS_HPP #define INCLUDED_UHD_PROPS_HPP -#include -#include +#include #include -#include +#include #include +#include namespace uhd{ - //common typedefs for board properties - typedef float gain_t; - typedef double freq_t; - - //gain range tuple (min, max, step) - typedef boost::tuple gain_range_t; - - //freq range tuple (min, max) - typedef boost::tuple freq_range_t; - - //scalar types (have not used yet, dont uncomment until needed) - //typedef int int_scalar_t; - //typedef float real_scalar_t; - //typedef std::complex complex_scalar_t; - - //vector types (have not used yet, dont uncomment until needed) - //typedef std::vector int_vec_t; - //typedef std::vector real_vec_t; - //typedef std::vector complex_vec_t; - //typedef for handling named properties typedef std::vector prop_names_t; typedef boost::tuple named_prop_t; @@ -55,7 +35,8 @@ namespace uhd{ * \param key a reference to the prop object * \param name a reference to the name object */ - inline named_prop_t extract_named_prop(const wax::obj &key, const std::string &name = ""){ + inline UHD_API named_prop_t //must be exported as part of the api to work (TODO move guts to cpp file) + extract_named_prop(const wax::obj &key, const std::string &name = ""){ if (key.type() == typeid(named_prop_t)){ return key.as(); } @@ -94,10 +75,8 @@ namespace uhd{ MBOARD_PROP_RX_DBOARD_NAMES, //ro, prop_names_t MBOARD_PROP_TX_DBOARD, //ro, wax::obj MBOARD_PROP_TX_DBOARD_NAMES, //ro, prop_names_t - MBOARD_PROP_PPS_SOURCE, //rw, std::string (sma, mimo) + MBOARD_PROP_CLOCK_CONFIG, //rw, clock_config_t MBOARD_PROP_PPS_SOURCE_NAMES, //ro, prop_names_t - MBOARD_PROP_PPS_POLARITY, //rw, std::string (pos, neg) - MBOARD_PROP_REF_SOURCE, //rw, std::string (int, sma, mimo) MBOARD_PROP_REF_SOURCE_NAMES, //ro, prop_names_t MBOARD_PROP_TIME_NOW, //wo, time_spec_t MBOARD_PROP_TIME_NEXT_PPS //wo, time_spec_t diff --git a/host/include/uhd/simple_device.hpp b/host/include/uhd/simple_device.hpp index b5d0fe311..ad25eccdc 100644 --- a/host/include/uhd/simple_device.hpp +++ b/host/include/uhd/simple_device.hpp @@ -20,29 +20,13 @@ #include #include +#include #include #include #include namespace uhd{ -/*! - * The tune result struct holds result of a 2-phase tuning: - * The struct hold the result of tuning the dboard as - * the target and actual intermediate frequency. - * The struct hold the result of tuning the DDC/DUC as - * the target and actual digital converter frequency. - * It also tell us weather or not the spectrum is inverted. - */ -struct UHD_API tune_result_t{ - double target_inter_freq; - double actual_inter_freq; - double target_dxc_freq; - double actual_dxc_freq; - bool spectrum_inverted; - tune_result_t(void); -}; - /*! * The simple UHD device class: * A simple device facilitates ease-of-use for most use-case scenarios. @@ -72,11 +56,11 @@ public: virtual std::vector get_rx_rates(void) = 0; virtual tune_result_t set_rx_freq(double freq) = 0; - virtual std::vector get_rx_freq_range(void) = 0; + virtual freq_range_t get_rx_freq_range(void) = 0; virtual void set_rx_gain(float gain) = 0; virtual float get_rx_gain(void) = 0; - virtual std::vector get_rx_gain_range(void) = 0; + virtual gain_range_t get_rx_gain_range(void) = 0; virtual void set_rx_antenna(const std::string &ant) = 0; virtual std::string get_rx_antenna(void) = 0; @@ -90,11 +74,11 @@ public: virtual std::vector get_tx_rates(void) = 0; virtual tune_result_t set_tx_freq(double freq) = 0; - virtual std::vector get_tx_freq_range(void) = 0; + virtual freq_range_t get_tx_freq_range(void) = 0; virtual void set_tx_gain(float gain) = 0; virtual float get_tx_gain(void) = 0; - virtual std::vector get_tx_gain_range(void) = 0; + virtual gain_range_t get_tx_gain_range(void) = 0; virtual void set_tx_antenna(const std::string &ant) = 0; virtual std::string get_tx_antenna(void) = 0; diff --git a/host/include/uhd/types.hpp b/host/include/uhd/types.hpp new file mode 100644 index 000000000..1439f57a1 --- /dev/null +++ b/host/include/uhd/types.hpp @@ -0,0 +1,83 @@ +// +// 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 . +// + +#ifndef INCLUDED_UHD_TYPES_HPP +#define INCLUDED_UHD_TYPES_HPP + +#include +#include + +namespace uhd{ + + typedef float gain_t; //TODO REMOVE + typedef double freq_t; //TODO REMOVE + + /*! + * The gain range struct describes possible gain settings. + * The mimumum gain, maximum gain, and step size are in dB. + */ + struct UHD_API gain_range_t{ + float min, max, step; + gain_range_t(float min = 0.0, float max = 0.0, float step = 0.0); + }; + + /*! + * The frequency range struct describes possible frequency settings. + * Because tuning is very granular (sub-Hz), step size is not listed. + * The mimumum frequency and maximum frequency are in Hz. + */ + struct UHD_API freq_range_t{ + double min, max; + freq_range_t(double min = 0.0, double max = 0.0); + }; + + /*! + * The tune result struct holds result of a 2-phase tuning: + * The struct hold the result of tuning the dboard as + * the target and actual intermediate frequency. + * The struct hold the result of tuning the DDC/DUC as + * the target and actual digital converter frequency. + * It also tell us weather or not the spectrum is inverted. + */ + struct UHD_API tune_result_t{ + double target_inter_freq; + double actual_inter_freq; + double target_dxc_freq; + double actual_dxc_freq; + bool spectrum_inverted; + tune_result_t(void); + }; + + /*! + * Clock configuration settings: + * The source for the 10MHz reference clock. + * The source and polarity for the PPS clock. + * Possible settings for the reference and pps source + * are implementation specific motherboard properties. + * See the MBOARD_PROP_XXX_SOURCE_NAMES properties. + */ + struct clock_config_t{ + enum polarity_t {POLARITY_NEG, POLARITY_POS}; + std::string ref_source; + std::string pps_source; + polarity_t pps_polarity; + clock_config_t(void); + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_HPP */ diff --git a/host/include/uhd/utils.hpp b/host/include/uhd/utils.hpp index 995cb9926..e5333539f 100644 --- a/host/include/uhd/utils.hpp +++ b/host/include/uhd/utils.hpp @@ -18,10 +18,11 @@ #ifndef INCLUDED_UHD_UTILS_HPP #define INCLUDED_UHD_UTILS_HPP -#include -#include +#include #include #include +#include +#include /*! * Defines a function that implements the "construct on first use" idiom diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 875a065af..563ffb340 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -25,6 +25,7 @@ SET(libuhd_sources metadata.cpp simple_device.cpp time_spec.cpp + types.cpp wax.cpp transport/udp_simple.cpp transport/vrt.cpp @@ -44,7 +45,7 @@ SET(libuhd_sources # Conditionally add the udp sources ######################################################################## LIST(APPEND libuhd_sources - transport/udp_zero_copy_none.cpp + transport/udp_zero_copy_asio.cpp ) ######################################################################## diff --git a/host/lib/gain_handler.cpp b/host/lib/gain_handler.cpp index 847bc0528..7dd1547cb 100644 --- a/host/lib/gain_handler.cpp +++ b/host/lib/gain_handler.cpp @@ -17,10 +17,12 @@ #include #include +#include #include #include #include #include +#include #include using namespace uhd; @@ -99,12 +101,10 @@ gain_t gain_handler_impl::get_overall_gain_val(void){ gain_range_t gain_handler_impl::get_overall_gain_range(void){ gain_t gain_min = 0, gain_max = 0, gain_step = 0; BOOST_FOREACH(std::string name, get_gain_names()){ - gain_t gain_min_tmp, gain_max_tmp, gain_step_tmp; - boost::tie(gain_min_tmp, gain_max_tmp, gain_step_tmp) = \ - get_named_prop(_props.range, name); - gain_min += gain_min_tmp; - gain_max += gain_max_tmp; - gain_step = std::max(gain_step, gain_step_tmp); + gain_range_t gain_tmp = get_named_prop(_props.range, name); + gain_min += gain_tmp.min; + gain_max += gain_tmp.max; + gain_step = std::max(gain_step, gain_tmp.step); } return gain_range_t(gain_min, gain_max, gain_step); } @@ -150,12 +150,10 @@ bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val) //not a wildcard... dont handle (but check name and range) if (name != ""){ assert_has(get_gain_names(), name, "gain name"); - gain_t gain_min, gain_max, gain_step; - boost::tie(gain_min, gain_max, gain_step) = \ - get_named_prop(_props.range, name); - if (gain_val > gain_max or gain_val < gain_min) throw std::range_error(str( + gain_range_t gain = get_named_prop(_props.range, name); + if (gain_val > gain.max or gain_val < gain.min) throw std::range_error(str( boost::format("A value of %f for gain %s is out of range of (%f, %f)") - % gain_val % name % gain_min % gain_max + % gain_val % name % gain.min % gain.max )); return false; } @@ -163,14 +161,12 @@ bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val) //set the overall gain BOOST_FOREACH(std::string name, get_gain_names()){ //get the min, max, step for this gain name - gain_t gain_min, gain_max, gain_step; - boost::tie(gain_min, gain_max, gain_step) = \ - get_named_prop(_props.range, name); + gain_range_t gain = get_named_prop(_props.range, name); //clip g to be within the allowed range - gain_t g = std::min(std::max(gain_val, gain_min), gain_max); + gain_t g = std::min(std::max(gain_val, gain.min), gain.max); //set g to be a multiple of the step size - g -= fmod(g, gain_step); + g -= std::fmod(g, gain.step); //set g to be the new gain _link[named_prop_t(_props.value, name)] = g; //subtract g out of the total gain left to apply diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp index 79b035071..045318c6b 100644 --- a/host/lib/simple_device.cpp +++ b/host/lib/simple_device.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -27,10 +28,6 @@ using namespace uhd; -tune_result_t::tune_result_t(void){ - /* NOP */ -} - /*********************************************************************** * Tune Helper Function **********************************************************************/ @@ -196,11 +193,8 @@ public: return tune(target_freq, lo_offset, _rx_subdev, _rx_ddc, false/* not tx */); } - std::vector get_rx_freq_range(void){ - std::vector range(2); - boost::tie(range[0], range[1]) = \ - _rx_subdev[SUBDEV_PROP_FREQ_RANGE].as(); - return range; + freq_range_t get_rx_freq_range(void){ + return _rx_subdev[SUBDEV_PROP_FREQ_RANGE].as(); } void set_rx_gain(float gain){ @@ -211,11 +205,8 @@ public: return _rx_subdev[SUBDEV_PROP_GAIN].as(); } - std::vector get_rx_gain_range(void){ - std::vector range(3); - boost::tie(range[0], range[1], range[2]) = \ - _rx_subdev[SUBDEV_PROP_GAIN_RANGE].as(); - return range; + gain_range_t get_rx_gain_range(void){ + return _rx_subdev[SUBDEV_PROP_GAIN_RANGE].as(); } void set_rx_antenna(const std::string &ant){ @@ -258,11 +249,8 @@ public: return tune(target_freq, lo_offset, _tx_subdev, _tx_duc, true/* is tx */); } - std::vector get_tx_freq_range(void){ - std::vector range(2); - boost::tie(range[0], range[1]) = \ - _tx_subdev[SUBDEV_PROP_FREQ_RANGE].as(); - return range; + freq_range_t get_tx_freq_range(void){ + return _tx_subdev[SUBDEV_PROP_FREQ_RANGE].as(); } void set_tx_gain(float gain){ @@ -273,11 +261,8 @@ public: return _tx_subdev[SUBDEV_PROP_GAIN].as(); } - std::vector get_tx_gain_range(void){ - std::vector range(3); - boost::tie(range[0], range[1], range[2]) = \ - _tx_subdev[SUBDEV_PROP_GAIN_RANGE].as(); - return range; + gain_range_t get_tx_gain_range(void){ + return _tx_subdev[SUBDEV_PROP_GAIN_RANGE].as(); } void set_tx_antenna(const std::string &ant){ diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp new file mode 100644 index 000000000..219ae8720 --- /dev/null +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -0,0 +1,154 @@ +// +// 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 + +using namespace uhd::transport; + +/*********************************************************************** + * Smart buffer implementation for udp zerocopy none + * + * This smart buffer implemention houses a const buffer. + * When the smart buffer is deleted, the buffer is freed. + * The memory in the const buffer is allocated with new [], + * and so the destructor frees the buffer with delete []. + **********************************************************************/ +class smart_buffer_impl : public smart_buffer{ +public: + smart_buffer_impl(const boost::asio::const_buffer &buff){ + _buff = buff; + } + + ~smart_buffer_impl(void){ + delete [] boost::asio::buffer_cast(_buff); + } + + const boost::asio::const_buffer &get(void) const{ + return _buff; + } + +private: + boost::asio::const_buffer _buff; +}; + +/*********************************************************************** + * UDP zero copy implementation class + * + * This is the portable zero copy implementation for systems + * where a faster, platform specific solution is not available. + * + * It uses boost asio udp sockets and the standard recv() class, + * and in-fact, is not actually doing a zero-copy implementation. + **********************************************************************/ +class udp_zero_copy_impl : public udp_zero_copy{ +public: + //structors + udp_zero_copy_impl(const std::string &addr, const std::string &port); + ~udp_zero_copy_impl(void); + + //send/recv + size_t send(const boost::asio::const_buffer &buff); + smart_buffer::sptr recv(void); + +private: + boost::asio::ip::udp::socket *_socket; + boost::asio::io_service _io_service; + + size_t get_recv_buff_size(void); + void set_recv_buff_size(size_t); +}; + +udp_zero_copy_impl::udp_zero_copy_impl(const std::string &addr, const std::string &port){ + //std::cout << boost::format("Creating udp transport for %s %s") % addr % port << std::endl; + + // resolve the address + boost::asio::ip::udp::resolver resolver(_io_service); + boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), addr, port); + boost::asio::ip::udp::endpoint receiver_endpoint = *resolver.resolve(query); + + // Create, open, and connect the socket + _socket = new boost::asio::ip::udp::socket(_io_service); + _socket->open(boost::asio::ip::udp::v4()); + _socket->connect(receiver_endpoint); + + // set the rx socket buffer size: + // pick a huge size, and deal with whatever we get + set_recv_buff_size(size_t(54321e3)); //some big number! + size_t current_buff_size = get_recv_buff_size(); + std::cout << boost::format( + "Current rx socket buffer size: %d\n" + ) % current_buff_size; + if (current_buff_size < size_t(.1e6)) std::cout << boost::format( + "Adjust max rx socket buffer size (linux only):\n" + " sysctl -w net.core.rmem_max=VALUE\n" + ); +} + +udp_zero_copy_impl::~udp_zero_copy_impl(void){ + delete _socket; +} + +size_t udp_zero_copy_impl::send(const boost::asio::const_buffer &buff){ + return _socket->send(boost::asio::buffer(buff)); +} + +smart_buffer::sptr udp_zero_copy_impl::recv(void){ + size_t available = 0; + + //implement timeout through polling and sleeping + boost::asio::deadline_timer timer(_socket->get_io_service()); + timer.expires_from_now(boost::posix_time::milliseconds(50)); + while (not ((available = _socket->available()) or timer.expires_from_now().is_negative())){ + boost::this_thread::sleep(boost::posix_time::milliseconds(1)); + } + + //allocate memory and create buffer + boost::uint32_t *buff_mem = new boost::uint32_t[available/sizeof(boost::uint32_t)]; + boost::asio::mutable_buffer buff(buff_mem, available); + + //receive only if data is available + if (available){ + _socket->receive(boost::asio::buffer(buff)); + } + + //create a new smart buffer to house the data + return smart_buffer::sptr(new smart_buffer_impl(buff)); +} + +size_t udp_zero_copy_impl::get_recv_buff_size(void){ + boost::asio::socket_base::receive_buffer_size option; + _socket->get_option(option); + return option.value(); +} + +void udp_zero_copy_impl::set_recv_buff_size(size_t new_size){ + boost::asio::socket_base::receive_buffer_size option(new_size); + _socket->set_option(option); +} + +/*********************************************************************** + * UDP zero copy make function + **********************************************************************/ +udp_zero_copy::sptr udp_zero_copy::make( + const std::string &addr, const std::string &port +){ + return sptr(new udp_zero_copy_impl(addr, port)); +} diff --git a/host/lib/transport/udp_zero_copy_none.cpp b/host/lib/transport/udp_zero_copy_none.cpp deleted file mode 100644 index 219ae8720..000000000 --- a/host/lib/transport/udp_zero_copy_none.cpp +++ /dev/null @@ -1,154 +0,0 @@ -// -// 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 - -using namespace uhd::transport; - -/*********************************************************************** - * Smart buffer implementation for udp zerocopy none - * - * This smart buffer implemention houses a const buffer. - * When the smart buffer is deleted, the buffer is freed. - * The memory in the const buffer is allocated with new [], - * and so the destructor frees the buffer with delete []. - **********************************************************************/ -class smart_buffer_impl : public smart_buffer{ -public: - smart_buffer_impl(const boost::asio::const_buffer &buff){ - _buff = buff; - } - - ~smart_buffer_impl(void){ - delete [] boost::asio::buffer_cast(_buff); - } - - const boost::asio::const_buffer &get(void) const{ - return _buff; - } - -private: - boost::asio::const_buffer _buff; -}; - -/*********************************************************************** - * UDP zero copy implementation class - * - * This is the portable zero copy implementation for systems - * where a faster, platform specific solution is not available. - * - * It uses boost asio udp sockets and the standard recv() class, - * and in-fact, is not actually doing a zero-copy implementation. - **********************************************************************/ -class udp_zero_copy_impl : public udp_zero_copy{ -public: - //structors - udp_zero_copy_impl(const std::string &addr, const std::string &port); - ~udp_zero_copy_impl(void); - - //send/recv - size_t send(const boost::asio::const_buffer &buff); - smart_buffer::sptr recv(void); - -private: - boost::asio::ip::udp::socket *_socket; - boost::asio::io_service _io_service; - - size_t get_recv_buff_size(void); - void set_recv_buff_size(size_t); -}; - -udp_zero_copy_impl::udp_zero_copy_impl(const std::string &addr, const std::string &port){ - //std::cout << boost::format("Creating udp transport for %s %s") % addr % port << std::endl; - - // resolve the address - boost::asio::ip::udp::resolver resolver(_io_service); - boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), addr, port); - boost::asio::ip::udp::endpoint receiver_endpoint = *resolver.resolve(query); - - // Create, open, and connect the socket - _socket = new boost::asio::ip::udp::socket(_io_service); - _socket->open(boost::asio::ip::udp::v4()); - _socket->connect(receiver_endpoint); - - // set the rx socket buffer size: - // pick a huge size, and deal with whatever we get - set_recv_buff_size(size_t(54321e3)); //some big number! - size_t current_buff_size = get_recv_buff_size(); - std::cout << boost::format( - "Current rx socket buffer size: %d\n" - ) % current_buff_size; - if (current_buff_size < size_t(.1e6)) std::cout << boost::format( - "Adjust max rx socket buffer size (linux only):\n" - " sysctl -w net.core.rmem_max=VALUE\n" - ); -} - -udp_zero_copy_impl::~udp_zero_copy_impl(void){ - delete _socket; -} - -size_t udp_zero_copy_impl::send(const boost::asio::const_buffer &buff){ - return _socket->send(boost::asio::buffer(buff)); -} - -smart_buffer::sptr udp_zero_copy_impl::recv(void){ - size_t available = 0; - - //implement timeout through polling and sleeping - boost::asio::deadline_timer timer(_socket->get_io_service()); - timer.expires_from_now(boost::posix_time::milliseconds(50)); - while (not ((available = _socket->available()) or timer.expires_from_now().is_negative())){ - boost::this_thread::sleep(boost::posix_time::milliseconds(1)); - } - - //allocate memory and create buffer - boost::uint32_t *buff_mem = new boost::uint32_t[available/sizeof(boost::uint32_t)]; - boost::asio::mutable_buffer buff(buff_mem, available); - - //receive only if data is available - if (available){ - _socket->receive(boost::asio::buffer(buff)); - } - - //create a new smart buffer to house the data - return smart_buffer::sptr(new smart_buffer_impl(buff)); -} - -size_t udp_zero_copy_impl::get_recv_buff_size(void){ - boost::asio::socket_base::receive_buffer_size option; - _socket->get_option(option); - return option.value(); -} - -void udp_zero_copy_impl::set_recv_buff_size(size_t new_size){ - boost::asio::socket_base::receive_buffer_size option(new_size); - _socket->set_option(option); -} - -/*********************************************************************** - * UDP zero copy make function - **********************************************************************/ -udp_zero_copy::sptr udp_zero_copy::make( - const std::string &addr, const std::string &port -){ - return sptr(new udp_zero_copy_impl(addr, port)); -} diff --git a/host/lib/types.cpp b/host/lib/types.cpp new file mode 100644 index 000000000..f8a9a9b36 --- /dev/null +++ b/host/lib/types.cpp @@ -0,0 +1,57 @@ +// +// 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 + +using namespace uhd; + +/*********************************************************************** + * gain range + **********************************************************************/ +gain_range_t::gain_range_t(float min_, float max_, float step_){ + min = min_; + max = max_; + step = step_; +} + +/*********************************************************************** + * freq range + **********************************************************************/ +freq_range_t::freq_range_t(double min_, double max_){ + min = min_; + max = max_; +} + +/*********************************************************************** + * tune result + **********************************************************************/ +tune_result_t::tune_result_t(void){ + target_inter_freq = 0.0; + actual_inter_freq = 0.0; + target_dxc_freq = 0.0; + actual_dxc_freq = 0.0; + spectrum_inverted = false; +} + +/*********************************************************************** + * clock config + **********************************************************************/ +clock_config_t::clock_config_t(void){ + ref_source = ""; //not a valid setting + pps_source = ""; //not a valid setting + pps_polarity = POLARITY_NEG; +} diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp index 02b391244..82485ae6a 100644 --- a/host/lib/usrp/dboard/basic.cpp +++ b/host/lib/usrp/dboard/basic.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 4f63e6cc9..cbca8eec7 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -16,7 +16,6 @@ // #include -#include #include "usrp2_impl.hpp" using namespace uhd; @@ -36,21 +35,27 @@ void usrp2_impl::mboard_init(void){ } void usrp2_impl::init_clock_config(void){ + //init the ref source clock config + _ref_source_dict = boost::assign::map_list_of + ("int", USRP2_REF_SOURCE_INT) + ("sma", USRP2_REF_SOURCE_SMA) + ("mimo", USRP2_REF_SOURCE_MIMO) + ; + _clock_config.ref_source = "int"; + //init the pps source clock config - _pps_source_dict["sma"] = USRP2_PPS_SOURCE_SMA; - _pps_source_dict["mimo"] = USRP2_PPS_SOURCE_MIMO; - _pps_source = "sma"; + _pps_source_dict = boost::assign::map_list_of + ("sma", USRP2_PPS_SOURCE_SMA) + ("mimo", USRP2_PPS_SOURCE_MIMO) + ; + _clock_config.pps_source = "sma"; //init the pps polarity clock config - _pps_polarity_dict["pos"] = USRP2_PPS_POLARITY_POS; - _pps_polarity_dict["neg"] = USRP2_PPS_POLARITY_NEG; - _pps_polarity = "neg"; - - //init the ref source clock config - _ref_source_dict["int"] = USRP2_REF_SOURCE_INT; - _ref_source_dict["sma"] = USRP2_REF_SOURCE_SMA; - _ref_source_dict["mimo"] = USRP2_REF_SOURCE_MIMO; - _ref_source = "int"; + _pps_polarity_dict = boost::assign::map_list_of + (clock_config_t::POLARITY_POS, USRP2_PPS_POLARITY_POS) + (clock_config_t::POLARITY_NEG, USRP2_PPS_POLARITY_NEG) + ; + _clock_config.pps_polarity = clock_config_t::POLARITY_NEG; //update the clock config (sends a control packet) update_clock_config(); @@ -60,9 +65,9 @@ void usrp2_impl::update_clock_config(void){ //setup the out data usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_HERES_A_NEW_CLOCK_CONFIG_BRO); - out_data.data.clock_config.pps_source = _pps_source_dict [_pps_source]; - out_data.data.clock_config.pps_polarity = _pps_polarity_dict[_pps_polarity]; - out_data.data.clock_config.ref_source = _ref_source_dict [_ref_source]; + out_data.data.clock_config.ref_source = _ref_source_dict [_clock_config.ref_source]; + out_data.data.clock_config.pps_source = _pps_source_dict [_clock_config.pps_source]; + out_data.data.clock_config.pps_polarity = _pps_polarity_dict[_clock_config.pps_polarity]; //send and recv usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); @@ -175,22 +180,14 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ val = prop_names_t(_tx_dsps.get_keys()); return; - case MBOARD_PROP_PPS_SOURCE: - val = _pps_source; + case MBOARD_PROP_CLOCK_CONFIG: + val = _clock_config; return; case MBOARD_PROP_PPS_SOURCE_NAMES: val = prop_names_t(_pps_source_dict.get_keys()); return; - case MBOARD_PROP_PPS_POLARITY: - val = _pps_polarity; - return; - - case MBOARD_PROP_REF_SOURCE: - val = _ref_source; - return; - case MBOARD_PROP_REF_SOURCE_NAMES: val = prop_names_t(_ref_source_dict.get_keys()); return; @@ -237,26 +234,11 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ //handle the get request conditioned on the key switch(key.as()){ - case MBOARD_PROP_PPS_SOURCE:{ - std::string name = val.as(); - assert_has(_pps_source_dict.get_keys(), name, "usrp2 pps source"); - _pps_source = name; //shadow - update_clock_config(); - } - return; - - case MBOARD_PROP_PPS_POLARITY:{ - std::string name = val.as(); - assert_has(_pps_polarity_dict.get_keys(), name, "usrp2 pps polarity"); - _pps_polarity = name; //shadow - update_clock_config(); - } - return; - - case MBOARD_PROP_REF_SOURCE:{ - std::string name = val.as(); - assert_has(_ref_source_dict.get_keys(), name, "usrp2 reference source"); - _ref_source = name; //shadow + case MBOARD_PROP_CLOCK_CONFIG:{ + clock_config_t clock_config = val.as(); + assert_has(_pps_source_dict.get_keys(), clock_config.pps_source, "usrp2 pps source"); + assert_has(_ref_source_dict.get_keys(), clock_config.ref_source, "usrp2 ref source"); + _clock_config = clock_config; //shadow update_clock_config(); } return; diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 59e23aba5..70420fd49 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -20,11 +20,12 @@ #include #include -#include +#include #include #include #include #include +#include #include #include #include @@ -142,15 +143,15 @@ private: boost::mutex _ctrl_mutex; //methods and shadows for clock configuration - std::string _pps_source, _pps_polarity, _ref_source; + uhd::clock_config_t _clock_config; void init_clock_config(void); void update_clock_config(void); void set_time_spec(const uhd::time_spec_t &time_spec, bool now); //mappings from clock config strings to over the wire enums - uhd::dict _pps_source_dict; - uhd::dict _pps_polarity_dict; - uhd::dict _ref_source_dict; + uhd::dict _ref_source_dict; + uhd::dict _pps_source_dict; + uhd::dict _pps_polarity_dict; //rx and tx dboard methods and objects uhd::usrp::dboard_manager::sptr _dboard_manager; diff --git a/host/test/gain_handler_test.cpp b/host/test/gain_handler_test.cpp index a4005c0de..47acb30f0 100644 --- a/host/test/gain_handler_test.cpp +++ b/host/test/gain_handler_test.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -108,12 +109,10 @@ BOOST_AUTO_TEST_CASE(test_gain_handler){ ); std::cout << "verifying the overall min, max, step" << std::endl; - gain_t gain_min, gain_max, gain_step; - boost::tie(gain_min, gain_max, gain_step) = \ - go0[PROP_GAIN_RANGE].as(); - BOOST_CHECK_EQUAL(gain_min, gain_t(-10)); - BOOST_CHECK_EQUAL(gain_max, gain_t(100)); - BOOST_CHECK_EQUAL(gain_step, gain_t(1.5)); + gain_range_t gain = go0[PROP_GAIN_RANGE].as(); + BOOST_CHECK_EQUAL(gain.min, gain_t(-10)); + BOOST_CHECK_EQUAL(gain.max, gain_t(100)); + BOOST_CHECK_EQUAL(gain.step, gain_t(1.5)); std::cout << "verifying the overall gain" << std::endl; go0[named_prop_t(PROP_GAIN_VALUE, "g0")] = gain_t(-5); -- cgit v1.2.3 From d66efda608db9f6a1c2ab64659556b53810d87b7 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 21 Mar 2010 16:53:50 -0700 Subject: Added ability to load modules at runtime (specified by environment variable path). Added a demo test module as well. --- host/lib/CMakeLists.txt | 21 +++++++- host/lib/load_modules.cpp | 117 +++++++++++++++++++++++++++++++++++++++++++++ host/lib/simple_device.cpp | 1 - host/test/CMakeLists.txt | 11 +++-- host/test/module_test.cpp | 26 ++++++++++ 5 files changed, 171 insertions(+), 5 deletions(-) create mode 100644 host/lib/load_modules.cpp create mode 100644 host/test/module_test.cpp (limited to 'host/lib/simple_device.cpp') diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 563ffb340..22fbde265 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -22,6 +22,7 @@ SET(libuhd_sources device.cpp device_addr.cpp gain_handler.cpp + load_modules.cpp metadata.cpp simple_device.cpp time_spec.cpp @@ -55,12 +56,30 @@ LIST(APPEND libuhd_sources usrp/usrp1e/usrp1e_none.cpp ) +######################################################################## +# Setup defines for module loading +######################################################################## +INCLUDE(CheckIncludeFileCXX) + +CHECK_INCLUDE_FILE_CXX(dlfcn.h HAVE_DLFCN_H) +CHECK_INCLUDE_FILE_CXX(Winbase.h HAVE_WINBASE_H) + +IF(HAVE_DLFCN_H) + MESSAGE(STATUS "Module loading supported through dlopen...") + ADD_DEFINITIONS(-DHAVE_DLFCN_H) +ELSEIF(HAVE_WINBASE_H) + MESSAGE(STATUS "Module loading supported through LoadLibrary...") + ADD_DEFINITIONS(-DHAVE_WINBASE_H) +ELSE(HAVE_DLFCN_H) + MESSAGE(STATUS "Module loading not supported...") +ENDIF(HAVE_DLFCN_H) + ######################################################################## # Setup libuhd library ######################################################################## ADD_LIBRARY(uhd SHARED ${libuhd_sources}) -TARGET_LINK_LIBRARIES(uhd ${Boost_LIBRARIES}) +TARGET_LINK_LIBRARIES(uhd ${Boost_LIBRARIES} ${CMAKE_DL_LIBS}) SET_TARGET_PROPERTIES(uhd PROPERTIES DEFINE_SYMBOL "UHD_DLL_EXPORTS") diff --git a/host/lib/load_modules.cpp b/host/lib/load_modules.cpp new file mode 100644 index 000000000..700afcd3f --- /dev/null +++ b/host/lib/load_modules.cpp @@ -0,0 +1,117 @@ +// +// 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 + +namespace fs = boost::filesystem; + +/*********************************************************************** + * Module Load Function + **********************************************************************/ +#ifdef HAVE_DLFCN_H +#include + +static void load_module(const std::string &file_name){ + if (dlopen(file_name.c_str(), RTLD_LAZY) == NULL){ + throw std::runtime_error(str( + boost::format("dlopen failed to load \"%s\"") % file_name + )); + } +} + +#elif HAVE_WINBASE_H +#include + +static void load_module(const std::string &file_name){ + if (LoadLibrary(file_name.c_str()) == NULL){ + throw std::runtime_error(str( + boost::format("LoadLibrary failed to load \"%s\"") % file_name + )); + } +} + +#else + +static void load_module(const std::string &file_name){ + throw std::runtime_error(str( + boost::format("Module loading not supported: Cannot load \"%s\"") % file_name + )); +} + +#endif + +/*********************************************************************** + * Load Modules + **********************************************************************/ +/*! + * Load all modules in a given path. + * This will recurse into sub-directories. + * Does not throw, prints to std error. + * \param path the filesystem path + */ +static void load_path(const fs::path &path){ + if (not fs::exists(path)){ + std::cerr << boost::format("Module path \"%s\" not found.") % path.file_string() << std::endl; + return; + } + + //try to load the files in this path + if (fs::is_directory(path)){ + for( + fs::directory_iterator dir_itr(path); + dir_itr != fs::directory_iterator(); + ++dir_itr + ){ + load_path(dir_itr->path()); + } + return; + } + + //its not a directory, try to load it + try{ + load_module(path.file_string()); + } + catch(const std::exception &err){ + std::cerr << boost::format("Error: %s") % err.what() << std::endl; + } +} + +/*! + * Load all the modules given by the module path enviroment variable. + * The path variable may be several paths split by path separators. + */ +STATIC_BLOCK(load_modules){ + //get the environment variable module path + char *env_module_path = std::getenv("UHD_MODULE_PATH"); + if (env_module_path == NULL) return; + + //split the path at the path separators + std::vector module_paths; + boost::split(module_paths, env_module_path, boost::is_any_of(":;")); + + //load modules in each path + BOOST_FOREACH(const std::string &module_path, module_paths){ + load_path(fs::system_complete(fs::path(module_path))); + } +} diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp index 045318c6b..ba1966e0d 100644 --- a/host/lib/simple_device.cpp +++ b/host/lib/simple_device.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/host/test/CMakeLists.txt b/host/test/CMakeLists.txt index b1d5924c7..1791d9082 100644 --- a/host/test/CMakeLists.txt +++ b/host/test/CMakeLists.txt @@ -15,7 +15,9 @@ # along with this program. If not, see . # - +######################################################################## +# unit test suite +######################################################################## ADD_EXECUTABLE(main_test main_test.cpp addr_test.cpp @@ -23,7 +25,10 @@ ADD_EXECUTABLE(main_test vrt_test.cpp wax_test.cpp ) - TARGET_LINK_LIBRARIES(main_test uhd) - ADD_TEST(test main_test) + +######################################################################## +# demo of a loadable module +######################################################################## +ADD_LIBRARY(module_test MODULE module_test.cpp) diff --git a/host/test/module_test.cpp b/host/test/module_test.cpp new file mode 100644 index 000000000..71721ef90 --- /dev/null +++ b/host/test/module_test.cpp @@ -0,0 +1,26 @@ +// +// 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 + +STATIC_BLOCK(module_test){ + std::cout << "---------------------------------------" << std::endl; + std::cout << "-- Good news, everyone!" << std::endl; + std::cout << "-- The test module has been loaded." << std::endl; + std::cout << "---------------------------------------" << std::endl; +} -- cgit v1.2.3