From af586ae149fe6f7aa12d4d6766e4216f3f00d1c0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 25 Mar 2010 18:36:16 -0700 Subject: Overhaullllllled the way we do streaming. There is an odd bug where a zero length command (now, no chain) used to stop the streaming. Now it seems to do the reverse... must investigate. Made all clock configuration into enums. The strings were painful and there cant be that many variations that enums cant cover them. The enums will make more sense to developers than mystery strings. --- host/lib/types.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'host/lib/types.cpp') diff --git a/host/lib/types.cpp b/host/lib/types.cpp index f8a9a9b36..273f87a2d 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -51,7 +51,16 @@ tune_result_t::tune_result_t(void){ * 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; + ref_source = REF_INT, + pps_source = PPS_INT, + pps_polarity = PPS_NEG; +} + +/*********************************************************************** + * stream command + **********************************************************************/ +stream_cmd_t::stream_cmd_t(void){ + stream_now = true; + continuous = false; + num_samps = 0; } -- cgit v1.2.3 From b71d0cbea9e1e107eeb1da51ef14fe6b9e983ee6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 27 Mar 2010 14:27:55 -0700 Subject: refactored types.hpp into types directory --- host/include/uhd/CMakeLists.txt | 6 +- host/include/uhd/device.hpp | 4 +- host/include/uhd/device_addr.hpp | 69 -------------- host/include/uhd/dict.hpp | 154 -------------------------------- host/include/uhd/metadata.hpp | 61 ------------- host/include/uhd/simple_device.hpp | 4 +- host/include/uhd/time_spec.hpp | 55 ------------ host/include/uhd/transport/vrt.hpp | 2 +- host/include/uhd/types.hpp | 119 ------------------------ host/include/uhd/types/CMakeLists.txt | 30 +++++++ host/include/uhd/types/clock_config.hpp | 50 +++++++++++ host/include/uhd/types/device_addr.hpp | 45 ++++++++++ host/include/uhd/types/dict.hpp | 154 ++++++++++++++++++++++++++++++++ host/include/uhd/types/mac_addr.hpp | 39 ++++++++ host/include/uhd/types/metadata.hpp | 61 +++++++++++++ host/include/uhd/types/ranges.hpp | 46 ++++++++++ host/include/uhd/types/stream_cmd.hpp | 56 ++++++++++++ host/include/uhd/types/time_spec.hpp | 55 ++++++++++++ host/include/uhd/types/tune_result.hpp | 44 +++++++++ host/lib/CMakeLists.txt | 3 - host/lib/device.cpp | 6 +- host/lib/device_addr.cpp | 86 ------------------ host/lib/gain_handler.cpp | 24 ++--- host/lib/metadata.cpp | 37 -------- host/lib/simple_device.cpp | 5 +- host/lib/time_spec.cpp | 35 -------- host/lib/types.cpp | 113 +++++++++++++++++++++-- host/lib/usrp/dboard/basic.cpp | 26 +++--- host/lib/usrp/dboard_manager.cpp | 2 +- host/lib/usrp/usrp2/dboard_impl.cpp | 1 + host/lib/usrp/usrp2/dsp_impl.cpp | 6 +- host/lib/usrp/usrp2/mboard_impl.cpp | 3 +- host/lib/usrp/usrp2/usrp2_impl.hpp | 10 +-- host/test/addr_test.cpp | 5 +- host/test/gain_handler_test.cpp | 22 ++--- host/utils/discover_usrps.cpp | 2 +- 36 files changed, 752 insertions(+), 688 deletions(-) delete mode 100644 host/include/uhd/device_addr.hpp delete mode 100644 host/include/uhd/dict.hpp delete mode 100644 host/include/uhd/metadata.hpp delete mode 100644 host/include/uhd/time_spec.hpp delete mode 100644 host/include/uhd/types.hpp create mode 100644 host/include/uhd/types/CMakeLists.txt create mode 100644 host/include/uhd/types/clock_config.hpp create mode 100644 host/include/uhd/types/device_addr.hpp create mode 100644 host/include/uhd/types/dict.hpp create mode 100644 host/include/uhd/types/mac_addr.hpp create mode 100644 host/include/uhd/types/metadata.hpp create mode 100644 host/include/uhd/types/ranges.hpp create mode 100644 host/include/uhd/types/stream_cmd.hpp create mode 100644 host/include/uhd/types/time_spec.hpp create mode 100644 host/include/uhd/types/tune_result.hpp delete mode 100644 host/lib/device_addr.cpp delete mode 100644 host/lib/metadata.cpp delete mode 100644 host/lib/time_spec.cpp (limited to 'host/lib/types.cpp') diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index 2203ea83e..0cebea095 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -17,20 +17,16 @@ ADD_SUBDIRECTORY(transport) +ADD_SUBDIRECTORY(types) ADD_SUBDIRECTORY(usrp) ADD_SUBDIRECTORY(utils) INSTALL(FILES config.hpp device.hpp - device_addr.hpp - dict.hpp gain_handler.hpp - metadata.hpp props.hpp simple_device.hpp - time_spec.hpp - types.hpp wax.hpp DESTINATION ${INCLUDE_DIR}/uhd ) diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index 13b40febe..bab8afca6 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -19,9 +19,9 @@ #define INCLUDED_UHD_DEVICE_HPP #include -#include +#include +#include #include -#include #include #include #include diff --git a/host/include/uhd/device_addr.hpp b/host/include/uhd/device_addr.hpp deleted file mode 100644 index 7673faff0..000000000 --- a/host/include/uhd/device_addr.hpp +++ /dev/null @@ -1,69 +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_UHD_DEVICE_ADDR_HPP -#define INCLUDED_UHD_DEVICE_ADDR_HPP - -#include -#include -#include -#include -#include -#include - -namespace uhd{ - - /*! - * Wrapper for an ethernet mac address. - * Provides conversion between string and binary formats. - */ - struct UHD_API mac_addr_t{ - boost::uint8_t mac_addr[6]; - mac_addr_t(const std::string &mac_addr_str = "00:00:00:00:00:00"); - std::string to_string(void) const; - }; - - /*! - * The device address args are just a mapping of key/value string pairs. - * When left empty, the discovery routine will try to find all usrps. - * The discovery can be narrowed down by specifying the transport type arguments. - * - * For example, to access a specific usrp2 one would specify the transport type - * ("type", "udp") and the transport args ("addr", ""). - */ - typedef dict device_addr_t; - typedef std::vector device_addrs_t; - - /*! - * Function to turn a device address into a string. - * Just having the operator<< below should be sufficient. - * However, boost format seems to complain with the % - * and this is just easier because it works. - * \param device_addr a device address instance - * \return the string representation - */ - namespace device_addr{ - UHD_API std::string to_string(const device_addr_t &device_addr); - } - -} //namespace uhd - -//ability to use types with stream operators -UHD_API std::ostream& operator<<(std::ostream &, const uhd::device_addr_t &); -UHD_API std::ostream& operator<<(std::ostream &, const uhd::mac_addr_t &); - -#endif /* INCLUDED_UHD_DEVICE_ADDR_HPP */ diff --git a/host/include/uhd/dict.hpp b/host/include/uhd/dict.hpp deleted file mode 100644 index f08493952..000000000 --- a/host/include/uhd/dict.hpp +++ /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 . -// - -#ifndef INCLUDED_UHD_DICT_HPP -#define INCLUDED_UHD_DICT_HPP - -#include -#include -#include -#include - -namespace uhd{ - - /*! - * A templated dictionary class with a python-like interface. - */ - template class dict{ - public: - typedef std::pair pair_t; - - /*! - * Create a new empty dictionary. - */ - dict(void){ - /* 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. - */ - ~dict(void){ - /* NOP */ - } - - /*! - * Get the number of elements in this dict. - * \param the number of elements - */ - std::size_t size(void) const{ - return _map.size(); - } - - /*! - * Get a list of the keys in this dict. - * Key order depends on insertion precedence. - * \return vector of keys - */ - std::vector get_keys(void) const{ - std::vector keys; - BOOST_FOREACH(const pair_t &p, _map){ - keys.push_back(p.first); - } - return keys; - } - - /*! - * Get a list of the values in this dict. - * Value order depends on insertion precedence. - * \return vector of values - */ - std::vector get_vals(void) const{ - std::vector vals; - BOOST_FOREACH(const pair_t &p, _map){ - vals.push_back(p.second); - } - return vals; - } - - /*! - * Does the dictionary contain this key? - * \param key the key to look for - * \return true if found - */ - bool has_key(const Key &key) const{ - BOOST_FOREACH(const pair_t &p, _map){ - if (p.first == key) return true; - } - return false; - } - - /*! - * Get a value for the given key if it exists. - * If the key is not found throw an error. - * \param key the key to look for - * \return the value at the key - * \throw an exception when not found - */ - const Val &operator[](const Key &key) const{ - BOOST_FOREACH(const pair_t &p, _map){ - if (p.first == key) return p.second; - } - throw std::invalid_argument("key not found in dict"); - } - - /*! - * Set a value for the given key, however, in reality - * it really returns a reference which can be assigned to. - * \param key the key to set to - * \return a reference to the value - */ - Val &operator[](const Key &key){ - BOOST_FOREACH(pair_t &p, _map){ - if (p.first == key) return p.second; - } - _map.push_back(pair_t(key, Val())); - return _map.back().second; - } - - /*! - * Pop an item out of the dictionary. - * \param key the item key - * \return the value of the item - * \throw an exception when not found - */ - Val pop(const Key &key){ - Val val = (*this)[key]; - _map.remove(pair_t(key, val)); - return val; - } - - private: - std::list _map; //private container - }; - -} //namespace uhd - -#endif /* INCLUDED_UHD_DICT_HPP */ diff --git a/host/include/uhd/metadata.hpp b/host/include/uhd/metadata.hpp deleted file mode 100644 index 6d80f070d..000000000 --- a/host/include/uhd/metadata.hpp +++ /dev/null @@ -1,61 +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_UHD_METADATA_HPP -#define INCLUDED_UHD_METADATA_HPP - -#include -#include - -namespace uhd{ - -/*! - * RX metadata structure for describing sent IF data. - * Includes stream ID, time specification, and fragmentation flags. - * The receive routines will convert IF data headers into metadata. - */ -struct UHD_API rx_metadata_t{ - boost::uint32_t stream_id; - time_spec_t time_spec; - bool has_stream_id; - bool has_time_spec; - bool is_fragment; - - //default constructor - rx_metadata_t(void); -}; - -/*! - * TX metadata structure for describing received IF data. - * Includes stream ID, time specification, and burst flags. - * The send routines will convert the metadata to IF data headers. - */ -struct UHD_API tx_metadata_t{ - boost::uint32_t stream_id; - time_spec_t time_spec; - bool has_stream_id; - bool has_time_spec; - bool start_of_burst; - bool end_of_burst; - - //default constructor - tx_metadata_t(void); -}; - -} //namespace uhd - -#endif /* INCLUDED_UHD_METADATA_HPP */ diff --git a/host/include/uhd/simple_device.hpp b/host/include/uhd/simple_device.hpp index bbe0258c7..52928367a 100644 --- a/host/include/uhd/simple_device.hpp +++ b/host/include/uhd/simple_device.hpp @@ -20,7 +20,9 @@ #include #include -#include +#include +#include +#include #include #include #include diff --git a/host/include/uhd/time_spec.hpp b/host/include/uhd/time_spec.hpp deleted file mode 100644 index e863746ba..000000000 --- a/host/include/uhd/time_spec.hpp +++ /dev/null @@ -1,55 +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_UHD_TIME_SPEC_HPP -#define INCLUDED_UHD_TIME_SPEC_HPP - -#include -#include -#include - -namespace uhd{ - - /*! - * A time_spec_t holds a seconds and ticks time value. - * The temporal width of a tick depends on the device's clock rate. - * The time_spec_t can be used when setting the time on devices - * and for controlling the start of streaming for applicable dsps. - */ - struct UHD_API time_spec_t{ - boost::uint32_t secs; - boost::uint32_t ticks; - - /*! - * Create a time_spec_t from seconds and ticks. - * \param new_secs the new seconds (default = 0) - * \param new_ticks the new ticks (default = 0) - */ - time_spec_t(boost::uint32_t new_secs = 0, boost::uint32_t new_ticks = 0); - - /*! - * Create a time_spec_t from boost posix time. - * \param time fine-grained boost posix time - * \param tick_rate the rate of ticks per second - */ - time_spec_t(boost::posix_time::ptime time, double tick_rate); - - }; - -} //namespace uhd - -#endif /* INCLUDED_UHD_TIME_SPEC_HPP */ diff --git a/host/include/uhd/transport/vrt.hpp b/host/include/uhd/transport/vrt.hpp index db2c57eba..04945b347 100644 --- a/host/include/uhd/transport/vrt.hpp +++ b/host/include/uhd/transport/vrt.hpp @@ -19,7 +19,7 @@ #define INCLUDED_UHD_TRANSPORT_VRT_HPP #include -#include +#include #include namespace uhd{ namespace transport{ diff --git a/host/include/uhd/types.hpp b/host/include/uhd/types.hpp deleted file mode 100644 index 3ad3dae82..000000000 --- a/host/include/uhd/types.hpp +++ /dev/null @@ -1,119 +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_UHD_TYPES_HPP -#define INCLUDED_UHD_TYPES_HPP - -#include -#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. - */ - struct UHD_API clock_config_t{ - enum ref_source_t { - REF_INT, //internal reference - REF_SMA, //external sma port - REF_MIMO //mimo cable (usrp2 only) - } ref_source; - enum pps_source_t { - PPS_INT, //there is no internal - PPS_SMA, //external sma port - PPS_MIMO //mimo cable (usrp2 only) - } pps_source; - enum pps_polarity_t { - PPS_NEG, //negative edge - PPS_POS //positive edge - } pps_polarity; - clock_config_t(void); - }; - - /*! - * Command struct for configuration and control of streaming: - * - * A stream command defines how the device sends samples to the host. - * Streaming is controlled by submitting a stream command to the rx dsp. - * Granular control over what the device streams to the host can be - * achieved through submission of multiple (carefully-crafted) commands. - * - * The stream_now parameter controls when the stream begins. - * When true, the device will begin streaming ASAP. When false, - * the device will begin streaming at a time specified by time_spec. - * - * The continuous parameter controls the number of samples received. - * When true, the device continues streaming indefinitely. When false, - * the device will stream the number of samples specified by num_samps. - * - * Standard usage case: - * To start continuous streaming, set stream_now to true and continuous to true. - * To end continuous streaming, set stream_now to true and continuous to false. - */ - struct UHD_API stream_cmd_t{ - bool stream_now; - time_spec_t time_spec; - bool continuous; - size_t num_samps; - stream_cmd_t(void); - }; - -} //namespace uhd - -#endif /* INCLUDED_UHD_TYPES_HPP */ diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt new file mode 100644 index 000000000..10262dd65 --- /dev/null +++ b/host/include/uhd/types/CMakeLists.txt @@ -0,0 +1,30 @@ +# +# 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 . +# + + +INSTALL(FILES + clock_config.hpp + device_addr.hpp + dict.hpp + mac_addr.hpp + metadata.hpp + ranges.hpp + stream_cmd.hpp + time_spec.hpp + tune_result.hpp + DESTINATION ${INCLUDE_DIR}/uhd/types +) diff --git a/host/include/uhd/types/clock_config.hpp b/host/include/uhd/types/clock_config.hpp new file mode 100644 index 000000000..8b2fea016 --- /dev/null +++ b/host/include/uhd/types/clock_config.hpp @@ -0,0 +1,50 @@ +// +// 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_CLOCK_CONFIG_HPP +#define INCLUDED_UHD_TYPES_CLOCK_CONFIG_HPP + +#include + +namespace uhd{ + + /*! + * Clock configuration settings: + * The source for the 10MHz reference clock. + * The source and polarity for the PPS clock. + */ + struct UHD_API clock_config_t{ + enum ref_source_t { + REF_INT, //internal reference + REF_SMA, //external sma port + REF_MIMO //mimo cable (usrp2 only) + } ref_source; + enum pps_source_t { + PPS_INT, //there is no internal + PPS_SMA, //external sma port + PPS_MIMO //mimo cable (usrp2 only) + } pps_source; + enum pps_polarity_t { + PPS_NEG, //negative edge + PPS_POS //positive edge + } pps_polarity; + clock_config_t(void); + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_CLOCK_CONFIG_HPP */ diff --git a/host/include/uhd/types/device_addr.hpp b/host/include/uhd/types/device_addr.hpp new file mode 100644 index 000000000..d32dfa77e --- /dev/null +++ b/host/include/uhd/types/device_addr.hpp @@ -0,0 +1,45 @@ +// +// 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_DEVICE_ADDR_HPP +#define INCLUDED_UHD_TYPES_DEVICE_ADDR_HPP + +#include +#include +#include +#include + +namespace uhd{ + + /*! + * The device address args are just a mapping of key/value string pairs. + * When left empty, the discovery routine will try to find all usrps. + * The discovery can be narrowed down by specifying the transport type arguments. + * + * For example, to access a specific usrp2 one would specify the transport type + * ("type", "udp") and the transport args ("addr", ""). + */ + class UHD_API device_addr_t : public dict{ + public: std::string to_string(void) const; + }; + + //handy typedef for a vector of device addresses + typedef std::vector device_addrs_t; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_DEVICE_ADDR_HPP */ diff --git a/host/include/uhd/types/dict.hpp b/host/include/uhd/types/dict.hpp new file mode 100644 index 000000000..5b9883704 --- /dev/null +++ b/host/include/uhd/types/dict.hpp @@ -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 . +// + +#ifndef INCLUDED_UHD_TYPES_DICT_HPP +#define INCLUDED_UHD_TYPES_DICT_HPP + +#include +#include +#include +#include + +namespace uhd{ + + /*! + * A templated dictionary class with a python-like interface. + */ + template class dict{ + public: + typedef std::pair pair_t; + + /*! + * Create a new empty dictionary. + */ + dict(void){ + /* 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. + */ + ~dict(void){ + /* NOP */ + } + + /*! + * Get the number of elements in this dict. + * \param the number of elements + */ + std::size_t size(void) const{ + return _map.size(); + } + + /*! + * Get a list of the keys in this dict. + * Key order depends on insertion precedence. + * \return vector of keys + */ + std::vector get_keys(void) const{ + std::vector keys; + BOOST_FOREACH(const pair_t &p, _map){ + keys.push_back(p.first); + } + return keys; + } + + /*! + * Get a list of the values in this dict. + * Value order depends on insertion precedence. + * \return vector of values + */ + std::vector get_vals(void) const{ + std::vector vals; + BOOST_FOREACH(const pair_t &p, _map){ + vals.push_back(p.second); + } + return vals; + } + + /*! + * Does the dictionary contain this key? + * \param key the key to look for + * \return true if found + */ + bool has_key(const Key &key) const{ + BOOST_FOREACH(const pair_t &p, _map){ + if (p.first == key) return true; + } + return false; + } + + /*! + * Get a value for the given key if it exists. + * If the key is not found throw an error. + * \param key the key to look for + * \return the value at the key + * \throw an exception when not found + */ + const Val &operator[](const Key &key) const{ + BOOST_FOREACH(const pair_t &p, _map){ + if (p.first == key) return p.second; + } + throw std::invalid_argument("key not found in dict"); + } + + /*! + * Set a value for the given key, however, in reality + * it really returns a reference which can be assigned to. + * \param key the key to set to + * \return a reference to the value + */ + Val &operator[](const Key &key){ + BOOST_FOREACH(pair_t &p, _map){ + if (p.first == key) return p.second; + } + _map.push_back(pair_t(key, Val())); + return _map.back().second; + } + + /*! + * Pop an item out of the dictionary. + * \param key the item key + * \return the value of the item + * \throw an exception when not found + */ + Val pop(const Key &key){ + Val val = (*this)[key]; + _map.remove(pair_t(key, val)); + return val; + } + + private: + std::list _map; //private container + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_DICT_HPP */ diff --git a/host/include/uhd/types/mac_addr.hpp b/host/include/uhd/types/mac_addr.hpp new file mode 100644 index 000000000..2cac7d343 --- /dev/null +++ b/host/include/uhd/types/mac_addr.hpp @@ -0,0 +1,39 @@ +// +// 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_MAC_ADDR_HPP +#define INCLUDED_UHD_TYPES_MAC_ADDR_HPP + +#include +#include +#include + +namespace uhd{ + + /*! + * Wrapper for an ethernet mac address. + * Provides conversion between string and binary formats. + */ + struct UHD_API mac_addr_t{ + boost::uint8_t mac_addr[6]; + mac_addr_t(const std::string &mac_addr_str = "00:00:00:00:00:00"); + std::string to_string(void) const; + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_MAC_ADDR_HPP */ diff --git a/host/include/uhd/types/metadata.hpp b/host/include/uhd/types/metadata.hpp new file mode 100644 index 000000000..6e93040d9 --- /dev/null +++ b/host/include/uhd/types/metadata.hpp @@ -0,0 +1,61 @@ +// +// 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_METADATA_HPP +#define INCLUDED_UHD_TYPES_METADATA_HPP + +#include +#include + +namespace uhd{ + + /*! + * RX metadata structure for describing sent IF data. + * Includes stream ID, time specification, and fragmentation flags. + * The receive routines will convert IF data headers into metadata. + */ + struct UHD_API rx_metadata_t{ + boost::uint32_t stream_id; + time_spec_t time_spec; + bool has_stream_id; + bool has_time_spec; + bool is_fragment; + + //default constructor + rx_metadata_t(void); + }; + + /*! + * TX metadata structure for describing received IF data. + * Includes stream ID, time specification, and burst flags. + * The send routines will convert the metadata to IF data headers. + */ + struct UHD_API tx_metadata_t{ + boost::uint32_t stream_id; + time_spec_t time_spec; + bool has_stream_id; + bool has_time_spec; + bool start_of_burst; + bool end_of_burst; + + //default constructor + tx_metadata_t(void); + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_METADATA_HPP */ diff --git a/host/include/uhd/types/ranges.hpp b/host/include/uhd/types/ranges.hpp new file mode 100644 index 000000000..a2057d1c8 --- /dev/null +++ b/host/include/uhd/types/ranges.hpp @@ -0,0 +1,46 @@ +// +// 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_RANGES_HPP +#define INCLUDED_UHD_TYPES_RANGES_HPP + +#include + +namespace uhd{ + + /*! + * 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); + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_RANGES_HPP */ diff --git a/host/include/uhd/types/stream_cmd.hpp b/host/include/uhd/types/stream_cmd.hpp new file mode 100644 index 000000000..97a6b73ce --- /dev/null +++ b/host/include/uhd/types/stream_cmd.hpp @@ -0,0 +1,56 @@ +// +// 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_STREAM_CMD_HPP +#define INCLUDED_UHD_TYPES_STREAM_CMD_HPP + +#include +#include + +namespace uhd{ + + /*! + * Command struct for configuration and control of streaming: + * + * A stream command defines how the device sends samples to the host. + * Streaming is controlled by submitting a stream command to the rx dsp. + * Granular control over what the device streams to the host can be + * achieved through submission of multiple (carefully-crafted) commands. + * + * The stream_now parameter controls when the stream begins. + * When true, the device will begin streaming ASAP. When false, + * the device will begin streaming at a time specified by time_spec. + * + * The continuous parameter controls the number of samples received. + * When true, the device continues streaming indefinitely. When false, + * the device will stream the number of samples specified by num_samps. + * + * Standard usage case: + * To start continuous streaming, set stream_now to true and continuous to true. + * To end continuous streaming, set stream_now to true and continuous to false. + */ + struct UHD_API stream_cmd_t{ + bool stream_now; + time_spec_t time_spec; + bool continuous; + size_t num_samps; + stream_cmd_t(void); + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_STREAM_CMD_HPP */ diff --git a/host/include/uhd/types/time_spec.hpp b/host/include/uhd/types/time_spec.hpp new file mode 100644 index 000000000..8c8f2bc25 --- /dev/null +++ b/host/include/uhd/types/time_spec.hpp @@ -0,0 +1,55 @@ +// +// 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_TIME_SPEC_HPP +#define INCLUDED_UHD_TYPES_TIME_SPEC_HPP + +#include +#include +#include + +namespace uhd{ + + /*! + * A time_spec_t holds a seconds and ticks time value. + * The temporal width of a tick depends on the device's clock rate. + * The time_spec_t can be used when setting the time on devices + * and for controlling the start of streaming for applicable dsps. + */ + struct UHD_API time_spec_t{ + boost::uint32_t secs; + boost::uint32_t ticks; + + /*! + * Create a time_spec_t from seconds and ticks. + * \param new_secs the new seconds (default = 0) + * \param new_ticks the new ticks (default = 0) + */ + time_spec_t(boost::uint32_t new_secs = 0, boost::uint32_t new_ticks = 0); + + /*! + * Create a time_spec_t from boost posix time. + * \param time fine-grained boost posix time + * \param tick_rate the rate of ticks per second + */ + time_spec_t(boost::posix_time::ptime time, double tick_rate); + + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_TIME_SPEC_HPP */ diff --git a/host/include/uhd/types/tune_result.hpp b/host/include/uhd/types/tune_result.hpp new file mode 100644 index 000000000..31742e1af --- /dev/null +++ b/host/include/uhd/types/tune_result.hpp @@ -0,0 +1,44 @@ +// +// 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_TUNE_RESULT_HPP +#define INCLUDED_UHD_TYPES_TUNE_RESULT_HPP + +#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); + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_TUNE_RESULT_HPP */ diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 170d1d3bf..1eceb53ea 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -20,12 +20,9 @@ ######################################################################## SET(libuhd_sources device.cpp - device_addr.cpp gain_handler.cpp load_modules.cpp - metadata.cpp simple_device.cpp - time_spec.cpp types.cpp wax.cpp transport/if_addrs.cpp diff --git a/host/lib/device.cpp b/host/lib/device.cpp index 0bdbf5f23..833e7a0da 100644 --- a/host/lib/device.cpp +++ b/host/lib/device.cpp @@ -16,7 +16,7 @@ // #include -#include +#include #include #include #include @@ -110,14 +110,14 @@ device::sptr device::make(const device_addr_t &hint, size_t which){ //check that we found any devices if (dev_addr_makers.size() == 0){ throw std::runtime_error(str( - boost::format("No devices found for ----->\n%s") % device_addr::to_string(hint) + boost::format("No devices found for ----->\n%s") % hint.to_string() )); } //check that the which index is valid if (dev_addr_makers.size() <= which){ throw std::runtime_error(str( - boost::format("No device at index %d for ----->\n%s") % which % device_addr::to_string(hint) + boost::format("No device at index %d for ----->\n%s") % which % hint.to_string() )); } diff --git a/host/lib/device_addr.cpp b/host/lib/device_addr.cpp deleted file mode 100644 index d26bb4b9d..000000000 --- a/host/lib/device_addr.cpp +++ /dev/null @@ -1,86 +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 -#include -#include - -//----------------------- u2 mac addr wrapper ------------------------// -uhd::mac_addr_t::mac_addr_t(const std::string &mac_addr_str_){ - std::string mac_addr_str = (mac_addr_str_ == "")? "ff:ff:ff:ff:ff:ff" : mac_addr_str_; - - //ether_aton_r(str.c_str(), &mac_addr); - boost::uint8_t p[6] = {0x00, 0x50, 0xC2, 0x85, 0x30, 0x00}; // Matt's IAB - - try{ - //only allow patterns of xx:xx or xx:xx:xx:xx:xx:xx - //the IAB above will fill in for the shorter pattern - if (mac_addr_str.size() != 5 and mac_addr_str.size() != 17) - throw std::runtime_error("expected exactly 5 or 17 characters"); - - //split the mac addr hex string at the colons - std::vector hex_strs; - boost::split(hex_strs, mac_addr_str, boost::is_any_of(":")); - for (size_t i = 0; i < hex_strs.size(); i++){ - int hex_num; - std::istringstream iss(hex_strs[i]); - iss >> std::hex >> hex_num; - p[i] = boost::uint8_t(hex_num); - } - - } - catch(std::exception const& e){ - throw std::runtime_error(str( - boost::format("Invalid mac address: %s\n\t%s") % mac_addr_str % e.what() - )); - } - - memcpy(&mac_addr, p, sizeof(mac_addr)); -} - -std::string uhd::mac_addr_t::to_string(void) const{ - //ether_ntoa_r(&mac_addr, addr_buf); - const boost::uint8_t *p = reinterpret_cast(&mac_addr); - return str( - boost::format("%02x:%02x:%02x:%02x:%02x:%02x") - % int(p[0]) % int(p[1]) % int(p[2]) - % int(p[3]) % int(p[4]) % int(p[5]) - ); -} - -std::ostream& operator<<(std::ostream &os, const uhd::mac_addr_t &x){ - os << x.to_string(); - return os; -} - -//----------------------- usrp device_addr_t wrapper -------------------------// -std::string uhd::device_addr::to_string(const uhd::device_addr_t &device_addr){ - std::stringstream ss; - BOOST_FOREACH(std::string key, device_addr.get_keys()){ - ss << boost::format("%s: %s") % key % device_addr[key] << std::endl; - } - return ss.str(); -} - -std::ostream& operator<<(std::ostream &os, const uhd::device_addr_t &device_addr){ - os << uhd::device_addr::to_string(device_addr); - return os; -} diff --git a/host/lib/gain_handler.cpp b/host/lib/gain_handler.cpp index 7b3dd266c..a6ae06c50 100644 --- a/host/lib/gain_handler.cpp +++ b/host/lib/gain_handler.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -47,7 +47,7 @@ private: is_equal_t _is_equal; prop_names_t get_gain_names(void); - gain_t get_overall_gain_val(void); + float 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 _link[named_prop_t(prop, name)].as(); @@ -90,21 +90,21 @@ prop_names_t gain_handler_impl::get_gain_names(void){ return _link[_props.names].as(); } -gain_t gain_handler_impl::get_overall_gain_val(void){ - gain_t gain_val = 0; +float gain_handler_impl::get_overall_gain_val(void){ + float gain_val = 0; BOOST_FOREACH(std::string name, get_gain_names()){ - gain_val += get_named_prop(_props.value, name); + gain_val += get_named_prop(_props.value, name); } return gain_val; } gain_range_t gain_handler_impl::get_overall_gain_range(void){ - gain_t gain_min = 0, gain_max = 0, gain_step = 0; + float gain_min = 0, gain_max = 0, gain_step = 0; BOOST_FOREACH(std::string name, get_gain_names()){ - 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); + gain_range_t floatmp = get_named_prop(_props.range, name); + gain_min += floatmp.min; + gain_max += floatmp.max; + gain_step = std::max(gain_step, floatmp.step); } return gain_range_t(gain_min, gain_max, gain_step); } @@ -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 = val.as(); + float gain_val = val.as(); //not a wildcard... dont handle (but check name and range) if (name != ""){ @@ -164,7 +164,7 @@ bool gain_handler_impl::intercept_set(const wax::obj &key_, const wax::obj &val) 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); + float g = std::min(std::max(gain_val, gain.min), gain.max); //set g to be a multiple of the step size g -= std::fmod(g, gain.step); //set g to be the new gain diff --git a/host/lib/metadata.cpp b/host/lib/metadata.cpp deleted file mode 100644 index 40fdb7c73..000000000 --- a/host/lib/metadata.cpp +++ /dev/null @@ -1,37 +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 - -using namespace uhd; - -rx_metadata_t::rx_metadata_t(void){ - stream_id = 0; - has_stream_id = false; - time_spec = time_spec_t(); - has_time_spec = false; - is_fragment = false; -} - -tx_metadata_t::tx_metadata_t(void){ - stream_id = 0; - has_stream_id = false; - time_spec = time_spec_t(); - has_time_spec = false; - start_of_burst = false; - end_of_burst = false; -} diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp index 0eb69d9fa..95bc8fecc 100644 --- a/host/lib/simple_device.cpp +++ b/host/lib/simple_device.cpp @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -208,7 +207,7 @@ public: } float get_rx_gain(void){ - return _rx_subdev[SUBDEV_PROP_GAIN].as(); + return _rx_subdev[SUBDEV_PROP_GAIN].as(); } gain_range_t get_rx_gain_range(void){ @@ -264,7 +263,7 @@ public: } float get_tx_gain(void){ - return _tx_subdev[SUBDEV_PROP_GAIN].as(); + return _tx_subdev[SUBDEV_PROP_GAIN].as(); } gain_range_t get_tx_gain_range(void){ diff --git a/host/lib/time_spec.cpp b/host/lib/time_spec.cpp deleted file mode 100644 index 98bf28077..000000000 --- a/host/lib/time_spec.cpp +++ /dev/null @@ -1,35 +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 - -using namespace uhd; - -time_spec_t::time_spec_t(boost::uint32_t new_secs, boost::uint32_t new_ticks){ - secs = new_secs; - ticks = new_ticks; -} - -static const boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1)); -static double time_tick_rate = double(boost::posix_time::time_duration::ticks_per_second()); - -time_spec_t::time_spec_t(boost::posix_time::ptime time, double tick_rate){ - boost::posix_time::time_duration td = time - epoch; - secs = boost::uint32_t(td.total_seconds()); - double time_ticks_per_device_ticks = time_tick_rate/tick_rate; - ticks = boost::uint32_t(td.fractional_seconds()/time_ticks_per_device_ticks); -} diff --git a/host/lib/types.cpp b/host/lib/types.cpp index 273f87a2d..bd5dc8e26 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -15,12 +15,23 @@ // along with this program. If not, see . // -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace uhd; /*********************************************************************** - * gain range + * ranges **********************************************************************/ gain_range_t::gain_range_t(float min_, float max_, float step_){ min = min_; @@ -28,9 +39,6 @@ gain_range_t::gain_range_t(float min_, float max_, float step_){ step = step_; } -/*********************************************************************** - * freq range - **********************************************************************/ freq_range_t::freq_range_t(double min_, double max_){ min = min_; max = max_; @@ -64,3 +72,98 @@ stream_cmd_t::stream_cmd_t(void){ continuous = false; num_samps = 0; } + +/*********************************************************************** + * metadata + **********************************************************************/ +rx_metadata_t::rx_metadata_t(void){ + stream_id = 0; + has_stream_id = false; + time_spec = time_spec_t(); + has_time_spec = false; + is_fragment = false; +} + +tx_metadata_t::tx_metadata_t(void){ + stream_id = 0; + has_stream_id = false; + time_spec = time_spec_t(); + has_time_spec = false; + start_of_burst = false; + end_of_burst = false; +} + +/*********************************************************************** + * time spec + **********************************************************************/ +time_spec_t::time_spec_t(boost::uint32_t new_secs, boost::uint32_t new_ticks){ + secs = new_secs; + ticks = new_ticks; +} + +static const boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1)); +static double time_tick_rate = double(boost::posix_time::time_duration::ticks_per_second()); + +time_spec_t::time_spec_t(boost::posix_time::ptime time, double tick_rate){ + boost::posix_time::time_duration td = time - epoch; + secs = boost::uint32_t(td.total_seconds()); + double time_ticks_per_device_ticks = time_tick_rate/tick_rate; + ticks = boost::uint32_t(td.fractional_seconds()/time_ticks_per_device_ticks); +} + +/*********************************************************************** + * device addr + **********************************************************************/ +std::string device_addr_t::to_string(void) const{ + const device_addr_t &device_addr = *this; + std::stringstream ss; + BOOST_FOREACH(std::string key, device_addr.get_keys()){ + ss << boost::format("%s: %s") % key % device_addr[key] << std::endl; + } + return ss.str(); +} + +/*********************************************************************** + * mac addr + **********************************************************************/ +uhd::mac_addr_t::mac_addr_t(const std::string &mac_addr_str_){ + std::string mac_addr_str = (mac_addr_str_ == "")? "ff:ff:ff:ff:ff:ff" : mac_addr_str_; + + //ether_aton_r(str.c_str(), &mac_addr); + boost::uint8_t p[6] = {0x00, 0x50, 0xC2, 0x85, 0x30, 0x00}; // Matt's IAB + + try{ + //only allow patterns of xx:xx or xx:xx:xx:xx:xx:xx + //the IAB above will fill in for the shorter pattern + if (mac_addr_str.size() != 5 and mac_addr_str.size() != 17) + throw std::runtime_error("expected exactly 5 or 17 characters"); + + //split the mac addr hex string at the colons + std::vector hex_strs; + boost::split(hex_strs, mac_addr_str, boost::is_any_of(":")); + for (size_t i = 0; i < hex_strs.size(); i++){ + int hex_num; + std::istringstream iss(hex_strs[i]); + iss >> std::hex >> hex_num; + p[i] = boost::uint8_t(hex_num); + } + + } + catch(std::exception const& e){ + throw std::runtime_error(str( + boost::format("Invalid mac address: %s\n\t%s") % mac_addr_str % e.what() + )); + } + + memcpy(&mac_addr, p, sizeof(mac_addr)); +} + +std::string uhd::mac_addr_t::to_string(void) const{ + //ether_ntoa_r(&mac_addr, addr_buf); + const boost::uint8_t *p = reinterpret_cast(&mac_addr); + return str( + boost::format("%02x:%02x:%02x:%02x:%02x:%02x") + % int(p[0]) % int(p[1]) % int(p[2]) + % int(p[3]) % int(p[4]) % int(p[5]) + ); +} diff --git a/host/lib/usrp/dboard/basic.cpp b/host/lib/usrp/dboard/basic.cpp index 07cb8d11c..2f29c8e0c 100644 --- a/host/lib/usrp/dboard/basic.cpp +++ b/host/lib/usrp/dboard/basic.cpp @@ -16,7 +16,7 @@ // #include -#include +#include #include #include #include @@ -34,26 +34,26 @@ using namespace boost::assign; **********************************************************************/ class basic_rx : public rx_dboard_base{ public: - basic_rx(ctor_args_t const& args, freq_t max_freq); + basic_rx(ctor_args_t const& args, double 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; + double _max_freq; }; class basic_tx : public tx_dboard_base{ public: - basic_tx(ctor_args_t const& args, freq_t max_freq); + basic_tx(ctor_args_t const& args, double 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; + double _max_freq; }; /*********************************************************************** @@ -85,7 +85,7 @@ UHD_STATIC_BLOCK(reg_dboards){ /*********************************************************************** * Basic and LF RX dboard **********************************************************************/ -basic_rx::basic_rx(ctor_args_t const& args, freq_t max_freq) : rx_dboard_base(args){ +basic_rx::basic_rx(ctor_args_t const& args, double 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); @@ -113,7 +113,7 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_GAIN: - val = gain_t(0); + val = float(0); return; case SUBDEV_PROP_GAIN_RANGE: @@ -125,7 +125,7 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_FREQ: - val = freq_t(0); + val = double(0); return; case SUBDEV_PROP_FREQ_RANGE: @@ -164,7 +164,7 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ switch(key.as()){ case SUBDEV_PROP_GAIN: - ASSERT_THROW(val.as() == gain_t(0)); + ASSERT_THROW(val.as() == float(0)); return; case SUBDEV_PROP_ANTENNA: @@ -196,7 +196,7 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ /*********************************************************************** * Basic and LF TX dboard **********************************************************************/ -basic_tx::basic_tx(ctor_args_t const& args, freq_t max_freq) : tx_dboard_base(args){ +basic_tx::basic_tx(ctor_args_t const& args, double 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); @@ -221,7 +221,7 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_GAIN: - val = gain_t(0); + val = float(0); return; case SUBDEV_PROP_GAIN_RANGE: @@ -233,7 +233,7 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){ return; case SUBDEV_PROP_FREQ: - val = freq_t(0); + val = double(0); return; case SUBDEV_PROP_FREQ_RANGE: @@ -272,7 +272,7 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ switch(key.as()){ case SUBDEV_PROP_GAIN: - ASSERT_THROW(val.as() == gain_t(0)); + ASSERT_THROW(val.as() == float(0)); return; case SUBDEV_PROP_ANTENNA: diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 0f2189cd1..bc9bfbf14 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index 6b49ff29d..fd72aeaa4 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -16,6 +16,7 @@ // #include +#include #include #include "usrp2_impl.hpp" diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 654096d14..40ef06a8c 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -35,7 +35,7 @@ template T log2(T num){ /*********************************************************************** * DDC Helper Methods **********************************************************************/ -static boost::uint32_t calculate_freq_word_and_update_actual_freq(freq_t &freq, freq_t clock_freq){ +static boost::uint32_t calculate_freq_word_and_update_actual_freq(double &freq, double clock_freq){ double scale_factor = std::pow(2.0, 32); //calculate the freq register word @@ -163,7 +163,7 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){ return; } else if (key_name == "freq"){ - freq_t new_freq = val.as(); + double 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 @@ -283,7 +283,7 @@ void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){ return; } else if (key_name == "freq"){ - freq_t new_freq = val.as(); + double 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 e4706dcf0..b6919a738 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -16,6 +16,7 @@ // #include +#include #include "usrp2_impl.hpp" using namespace uhd; @@ -168,7 +169,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ return; case MBOARD_PROP_CLOCK_RATE: - val = freq_t(get_master_clock_freq()); + val = double(get_master_clock_freq()); return; case MBOARD_PROP_RX_DSP: diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 3a2963c5a..6535e7049 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -19,9 +19,9 @@ #define INCLUDED_USRP2_IMPL_HPP #include -#include -#include -#include +#include +#include +#include #include #include #include @@ -173,14 +173,14 @@ private: //methods and shadows for the ddc dsp std::vector _allowed_decim_and_interp_rates; size_t _ddc_decim; - uhd::freq_t _ddc_freq; + double _ddc_freq; void init_ddc_config(void); void update_ddc_config(void); void issue_ddc_stream_cmd(const uhd::stream_cmd_t &stream_cmd); //methods and shadows for the duc dsp size_t _duc_interp; - uhd::freq_t _duc_freq; + double _duc_freq; void init_duc_config(void); void update_duc_config(void); diff --git a/host/test/addr_test.cpp b/host/test/addr_test.cpp index 148aee015..0c8f63b0a 100644 --- a/host/test/addr_test.cpp +++ b/host/test/addr_test.cpp @@ -16,13 +16,14 @@ // #include -#include +#include +#include BOOST_AUTO_TEST_CASE(test_mac_addr){ std::cout << "Testing mac addr..." << std::endl; const std::string mac_addr_str("00:01:23:45:67:89"); uhd::mac_addr_t mac_addr(mac_addr_str); std::cout << "Input: " << mac_addr_str << std::endl; - std::cout << "Output: " << mac_addr << std::endl; + std::cout << "Output: " << mac_addr.to_string() << std::endl; BOOST_CHECK_EQUAL(mac_addr_str, mac_addr.to_string()); } diff --git a/host/test/gain_handler_test.cpp b/host/test/gain_handler_test.cpp index 47acb30f0..e13063e06 100644 --- a/host/test/gain_handler_test.cpp +++ b/host/test/gain_handler_test.cpp @@ -17,9 +17,9 @@ #include #include -#include +#include +#include #include -#include #include #include @@ -84,7 +84,7 @@ private: //handle the get request conditioned on the key switch(key.as()){ case PROP_GAIN_VALUE: - _gain_values[name] = val.as(); + _gain_values[name] = val.as(); return; case PROP_GAIN_RANGE: @@ -94,7 +94,7 @@ private: } gain_handler::sptr _gain_handler; - uhd::dict _gain_values; + uhd::dict _gain_values; uhd::dict _gain_ranges; }; @@ -104,18 +104,18 @@ BOOST_AUTO_TEST_CASE(test_gain_handler){ gainful_obj go0; BOOST_CHECK_THROW( - go0[named_prop_t(PROP_GAIN_VALUE, "fail")].as(), + go0[named_prop_t(PROP_GAIN_VALUE, "fail")].as(), std::exception ); std::cout << "verifying the overall min, max, step" << std::endl; 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)); + BOOST_CHECK_EQUAL(gain.min, float(-10)); + BOOST_CHECK_EQUAL(gain.max, float(100)); + BOOST_CHECK_EQUAL(gain.step, float(1.5)); 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(go0[PROP_GAIN_VALUE].as(), gain_t(25)); + go0[named_prop_t(PROP_GAIN_VALUE, "g0")] = float(-5); + go0[named_prop_t(PROP_GAIN_VALUE, "g1")] = float(30); + BOOST_CHECK_EQUAL(go0[PROP_GAIN_VALUE].as(), float(25)); } diff --git a/host/utils/discover_usrps.cpp b/host/utils/discover_usrps.cpp index dc2b845bc..72c5b8822 100644 --- a/host/utils/discover_usrps.cpp +++ b/host/utils/discover_usrps.cpp @@ -63,7 +63,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::cout << "--------------------------------------------------" << std::endl; std::cout << "-- USRP Device " << i << std::endl; std::cout << "--------------------------------------------------" << std::endl; - std::cout << device_addrs[i] << std::endl << std::endl; + std::cout << device_addrs[i].to_string() << std::endl << std::endl; uhd::device::make(device_addrs[i]); //test make } -- cgit v1.2.3 From 1295df8cbba76c088a36f9d546a68c1d00e7a1a8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 29 Mar 2010 12:58:06 -0700 Subject: Added utility methods to device addr and mac addr to make them more usable. --- host/include/uhd/types/device_addr.hpp | 37 ++++++++++++++++---- host/include/uhd/types/dict.hpp | 7 ++-- host/include/uhd/types/mac_addr.hpp | 35 +++++++++++++++++-- host/lib/device.cpp | 8 ++--- host/lib/simple_device.cpp | 26 +------------- host/lib/types.cpp | 63 ++++++++++++++++++++++++++++------ host/lib/usrp/dboard_manager.cpp | 6 ++-- host/lib/usrp/usrp2/mboard_impl.cpp | 6 ++-- host/test/addr_test.cpp | 2 +- host/utils/usrp2_burner.cpp | 17 +++++---- 10 files changed, 143 insertions(+), 64 deletions(-) (limited to 'host/lib/types.cpp') diff --git a/host/include/uhd/types/device_addr.hpp b/host/include/uhd/types/device_addr.hpp index d32dfa77e..1162884fb 100644 --- a/host/include/uhd/types/device_addr.hpp +++ b/host/include/uhd/types/device_addr.hpp @@ -26,15 +26,40 @@ namespace uhd{ /*! - * The device address args are just a mapping of key/value string pairs. - * When left empty, the discovery routine will try to find all usrps. - * The discovery can be narrowed down by specifying the transport type arguments. + * Mapping of key/value pairs for locating devices on the system. + * When left empty, the device discovery routines will search + * all available transports on the system (ethernet, usb...). * - * For example, to access a specific usrp2 one would specify the transport type - * ("type", "udp") and the transport args ("addr", ""). + * To narrow down the discovery process to a particular device, + * specify a transport key/value pair specific to your device. + * Ex, to find a usrp2: my_dev_addr["addr"] = + * + * The device address can also be used to pass arguments into + * the transport layer control to set (for example) buffer sizes. */ class UHD_API device_addr_t : public dict{ - public: std::string to_string(void) const; + public: + + /*! + * Convert a device address into a printable string. + * \return string good for use with std::cout << + */ + std::string to_string(void) const; + + /*! + * Convert the device address into an args string. + * The args string contains delimiter symbols. + * \return a string with delimiter markup + */ + std::string to_args_str(void) const; + + /*! + * Make a device address from an args string. + * The args string contains delimiter symbols. + * \param args_str the arguments string + * \return the new device address + */ + static device_addr_t from_args_str(const std::string &args_str); }; //handy typedef for a vector of device addresses diff --git a/host/include/uhd/types/dict.hpp b/host/include/uhd/types/dict.hpp index 5b9883704..7fb712e76 100644 --- a/host/include/uhd/types/dict.hpp +++ b/host/include/uhd/types/dict.hpp @@ -18,10 +18,11 @@ #ifndef INCLUDED_UHD_TYPES_DICT_HPP #define INCLUDED_UHD_TYPES_DICT_HPP -#include -#include -#include +#include #include +#include +#include +#include namespace uhd{ diff --git a/host/include/uhd/types/mac_addr.hpp b/host/include/uhd/types/mac_addr.hpp index 2cac7d343..3cd1fe86b 100644 --- a/host/include/uhd/types/mac_addr.hpp +++ b/host/include/uhd/types/mac_addr.hpp @@ -28,10 +28,39 @@ namespace uhd{ * Wrapper for an ethernet mac address. * Provides conversion between string and binary formats. */ - struct UHD_API mac_addr_t{ - boost::uint8_t mac_addr[6]; - mac_addr_t(const std::string &mac_addr_str = "00:00:00:00:00:00"); + class UHD_API mac_addr_t{ + public: + static const size_t hlen = 6; + + /*! + * Create a mac address a byte array. + * \param bytes a pointer for the byte array + * \return a new mac address + */ + static mac_addr_t from_bytes(const boost::uint8_t *bytes); + + /*! + * Create a mac address from a string. + * \param mac_addr_str the string with delimiters + * \return a new mac address + */ + static mac_addr_t from_string(const std::string &mac_addr_str); + + /*! + * Get the byte representation of the mac address. + * \return a pointer to the internal byte array + */ + const boost::uint8_t *to_bytes(void) const; + + /*! + * Get the string representation of this mac address. + * \return a string with delimiters + */ std::string to_string(void) const; + + private: + mac_addr_t(const boost::uint8_t *bytes); //private constructor + boost::uint8_t _bytes[hlen]; //internal representation }; } //namespace uhd diff --git a/host/lib/device.cpp b/host/lib/device.cpp index 833e7a0da..ca45d0795 100644 --- a/host/lib/device.cpp +++ b/host/lib/device.cpp @@ -47,7 +47,7 @@ static size_t hash_device_addr( //combine the hashes of sorted keys/value pairs size_t hash = 0; - BOOST_FOREACH(std::string key, keys){ + BOOST_FOREACH(const std::string &key, keys){ boost::hash_combine(hash, key); boost::hash_combine(hash, dev_addr[key]); } @@ -76,7 +76,7 @@ void device::register_device( device_addrs_t device::discover(const device_addr_t &hint){ device_addrs_t device_addrs; - BOOST_FOREACH(dev_fcn_reg_t fcn, get_dev_fcn_regs()){ + BOOST_FOREACH(const dev_fcn_reg_t &fcn, get_dev_fcn_regs()){ device_addrs_t discovered_addrs = fcn.get<0>()(hint); device_addrs.insert( device_addrs.begin(), @@ -95,11 +95,11 @@ device::sptr device::make(const device_addr_t &hint, size_t which){ typedef boost::tuple dev_addr_make_t; std::vector dev_addr_makers; - BOOST_FOREACH(dev_fcn_reg_t fcn, get_dev_fcn_regs()){ + BOOST_FOREACH(const dev_fcn_reg_t &fcn, get_dev_fcn_regs()){ BOOST_FOREACH(device_addr_t dev_addr, fcn.get<0>()(hint)){ //copy keys that were in hint but not in dev_addr //this way, we can pass additional transport arguments - BOOST_FOREACH(std::string key, hint.get_keys()){ + BOOST_FOREACH(const std::string &key, hint.get_keys()){ if (not dev_addr.has_key(key)) dev_addr[key] = hint[key]; } //append the discovered address and its factory function diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp index 2e6bffc9c..25beb45a9 100644 --- a/host/lib/simple_device.cpp +++ b/host/lib/simple_device.cpp @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -29,29 +28,6 @@ using namespace uhd; /*********************************************************************** * 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, decerps.as >()){ @@ -223,5 +199,5 @@ private: * The Make Function **********************************************************************/ simple_device::sptr simple_device::make(const std::string &args){ - return sptr(new simple_device_impl(args_to_device_addr(args))); + return sptr(new simple_device_impl(device_addr_t::from_args_str(args))); } diff --git a/host/lib/types.cpp b/host/lib/types.cpp index bd5dc8e26..3fde40596 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -123,14 +123,55 @@ std::string device_addr_t::to_string(void) const{ return ss.str(); } +static const std::string arg_delim = ";"; +static const std::string pair_delim = "="; + +static std::string trim(const std::string &in){ + return boost::algorithm::trim_copy(in); +} + +std::string device_addr_t::to_args_str(void) const{ + std::string args_str; + const device_addr_t &device_addr = *this; + BOOST_FOREACH(const std::string &key, device_addr.get_keys()){ + args_str += key + pair_delim + device_addr[key] + arg_delim; + } + return args_str; +} + +device_addr_t device_addr_t::from_args_str(const std::string &args_str){ + device_addr_t addr; + + //split the args at the semi-colons + std::vector pairs; + boost::split(pairs, args_str, boost::is_any_of(arg_delim)); + BOOST_FOREACH(const 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(pair_delim)); + if (key_val.size() != 2) throw std::runtime_error("invalid args string: "+args_str); + addr[trim(key_val[0])] = trim(key_val[1]); + } + + return addr; +} + /*********************************************************************** * mac addr **********************************************************************/ -uhd::mac_addr_t::mac_addr_t(const std::string &mac_addr_str_){ - std::string mac_addr_str = (mac_addr_str_ == "")? "ff:ff:ff:ff:ff:ff" : mac_addr_str_; +mac_addr_t::mac_addr_t(const boost::uint8_t *bytes){ + std::copy(bytes, bytes+hlen, _bytes); +} - //ether_aton_r(str.c_str(), &mac_addr); - boost::uint8_t p[6] = {0x00, 0x50, 0xC2, 0x85, 0x30, 0x00}; // Matt's IAB +mac_addr_t mac_addr_t::from_bytes(const boost::uint8_t *bytes){ + return mac_addr_t(bytes); +} + +mac_addr_t mac_addr_t::from_string(const std::string &mac_addr_str){ + + boost::uint8_t p[hlen] = {0x00, 0x50, 0xC2, 0x85, 0x30, 0x00}; // Matt's IAB try{ //only allow patterns of xx:xx or xx:xx:xx:xx:xx:xx @@ -155,15 +196,17 @@ uhd::mac_addr_t::mac_addr_t(const std::string &mac_addr_str_){ )); } - memcpy(&mac_addr, p, sizeof(mac_addr)); + return from_bytes(p); +} + +const boost::uint8_t *mac_addr_t::to_bytes(void) const{ + return _bytes; } -std::string uhd::mac_addr_t::to_string(void) const{ - //ether_ntoa_r(&mac_addr, addr_buf); - const boost::uint8_t *p = reinterpret_cast(&mac_addr); +std::string mac_addr_t::to_string(void) const{ return str( boost::format("%02x:%02x:%02x:%02x:%02x:%02x") - % int(p[0]) % int(p[1]) % int(p[2]) - % int(p[3]) % int(p[4]) % int(p[5]) + % int(to_bytes()[0]) % int(to_bytes()[1]) % int(to_bytes()[2]) + % int(to_bytes()[3]) % int(to_bytes()[4]) % int(to_bytes()[5]) ); } diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index f86545696..424626023 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -204,7 +204,7 @@ dboard_manager_impl::dboard_manager_impl( //make xcvr subdevs (make one subdev for both rx and tx dboards) if (rx_dboard_ctor == tx_dboard_ctor){ ASSERT_THROW(rx_subdevs == tx_subdevs); - BOOST_FOREACH(std::string subdev, rx_subdevs){ + BOOST_FOREACH(const std::string &subdev, rx_subdevs){ dboard_base::sptr xcvr_dboard = rx_dboard_ctor( dboard_base::ctor_args_t(subdev, interface, rx_dboard_id, tx_dboard_id) ); @@ -222,7 +222,7 @@ dboard_manager_impl::dboard_manager_impl( //make tx and rx subdevs (separate subdevs for rx and tx dboards) else{ //make the rx subdevs - BOOST_FOREACH(std::string subdev, rx_subdevs){ + BOOST_FOREACH(const std::string &subdev, rx_subdevs){ dboard_base::sptr rx_dboard = rx_dboard_ctor( dboard_base::ctor_args_t(subdev, interface, rx_dboard_id, dboard_id::NONE) ); @@ -232,7 +232,7 @@ dboard_manager_impl::dboard_manager_impl( ); } //make the tx subdevs - BOOST_FOREACH(std::string subdev, tx_subdevs){ + BOOST_FOREACH(const std::string &subdev, tx_subdevs){ dboard_base::sptr tx_dboard = tx_dboard_ctor( dboard_base::ctor_args_t(subdev, interface, dboard_id::NONE, tx_dboard_id) ); diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index b6919a738..35dfd6287 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -116,7 +116,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE); //extract the address - val = reinterpret_cast(in_data.data.mac_addr)->to_string(); + val = mac_addr_t::from_bytes(in_data.data.mac_addr).to_string(); return; } @@ -211,8 +211,8 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ //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(val.as()); - std::memcpy(out_data.data.mac_addr, &mac_addr, sizeof(mac_addr_t)); + mac_addr_t mac_addr = mac_addr_t::from_string(val.as()); + std::copy(mac_addr.to_bytes(), mac_addr.to_bytes()+mac_addr_t::hlen, out_data.data.mac_addr); //send and recv usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); diff --git a/host/test/addr_test.cpp b/host/test/addr_test.cpp index 0c8f63b0a..a75804949 100644 --- a/host/test/addr_test.cpp +++ b/host/test/addr_test.cpp @@ -22,7 +22,7 @@ BOOST_AUTO_TEST_CASE(test_mac_addr){ std::cout << "Testing mac addr..." << std::endl; const std::string mac_addr_str("00:01:23:45:67:89"); - uhd::mac_addr_t mac_addr(mac_addr_str); + uhd::mac_addr_t mac_addr = uhd::mac_addr_t::from_string(mac_addr_str); std::cout << "Input: " << mac_addr_str << std::endl; std::cout << "Output: " << mac_addr.to_string() << std::endl; BOOST_CHECK_EQUAL(mac_addr_str, mac_addr.to_string()); diff --git a/host/utils/usrp2_burner.cpp b/host/utils/usrp2_burner.cpp index ff6d4426f..b24425316 100644 --- a/host/utils/usrp2_burner.cpp +++ b/host/utils/usrp2_burner.cpp @@ -57,27 +57,32 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::device::sptr u2_dev = uhd::usrp::usrp2::make(device_addr); //FIXME usees the default mboard for now (until the mimo link is supported) wax::obj u2_mb = (*u2_dev)[uhd::DEVICE_PROP_MBOARD]; + std::cout << std::endl; + + //fetch and print current settings + std::cout << "Fetching current settings from usrp2 eeprom:" << std::endl; + std::string curr_ip = u2_mb[std::string("ip-addr")].as(); + std::cout << boost::format(" Current IP Address: %s") % curr_ip << std::endl; + std::string curr_mac = u2_mb[std::string("mac-addr")].as(); + std::cout << boost::format(" Current MAC Address: %s") % curr_mac << std::endl; + std::cout << " Done" << std::endl << std::endl; //try to set the new ip (if provided) if (vm.count("new-ip")){ std::cout << "Burning a new ip address into the usrp2 eeprom:" << std::endl; - std::string old_ip = u2_mb[std::string("ip-addr")].as(); - std::cout << boost::format(" Old IP Address: %s") % old_ip << std::endl; std::string new_ip = vm["new-ip"].as(); std::cout << boost::format(" New IP Address: %s") % new_ip << std::endl; u2_mb[std::string("ip-addr")] = new_ip; - std::cout << " Done" << std::endl; + std::cout << " Done" << std::endl << std::endl; } //try to set the new mac (if provided) if (vm.count("new-mac")){ std::cout << "Burning a new mac address into the usrp2 eeprom:" << std::endl; - std::string old_mac = u2_mb[std::string("mac-addr")].as(); - std::cout << boost::format(" Old MAC Address: %s") % old_mac << std::endl; std::string new_mac = vm["new-mac"].as(); std::cout << boost::format(" New MAC Address: %s") % new_mac << std::endl; u2_mb[std::string("mac-addr")] = new_mac; - std::cout << " Done" << std::endl; + std::cout << " Done" << std::endl << std::endl; } std::cout << "Power-cycle the usrp2 for the changes to take effect." << std::endl; -- cgit v1.2.3 From f9be69cae7c0fd9bca8b310ff79dd6aad958dc2b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 30 Mar 2010 14:07:19 -0700 Subject: Added io type and otw type for describing types. --- host/examples/rx_timed_samples.cpp | 5 ++- host/include/uhd/device.hpp | 10 ++--- host/include/uhd/types/CMakeLists.txt | 2 + host/include/uhd/types/clock_config.hpp | 16 ++++---- host/include/uhd/types/io_type.hpp | 69 +++++++++++++++++++++++++++++++++ host/include/uhd/types/otw_type.hpp | 63 ++++++++++++++++++++++++++++++ host/lib/types.cpp | 35 +++++++++++++++++ host/lib/usrp/usrp2/io_impl.cpp | 68 ++++++++++++++++---------------- host/lib/usrp/usrp2/usrp2_impl.hpp | 4 +- 9 files changed, 221 insertions(+), 51 deletions(-) create mode 100644 host/include/uhd/types/io_type.hpp create mode 100644 host/include/uhd/types/otw_type.hpp (limited to 'host/lib/types.cpp') diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index 5d4b5a68d..88e112584 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -80,7 +80,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ while(num_acc_samps < total_num_samps){ uhd::rx_metadata_t md; std::complex buff[1000]; - size_t num_rx_samps = dev->recv(boost::asio::buffer(buff, sizeof(buff)), md, "32fc"); + size_t num_rx_samps = dev->recv( + boost::asio::buffer(buff, sizeof(buff)), + md, uhd::io_type_t::COMPLEX_FLOAT32 + ); if (num_rx_samps == 0) continue; //wait for packets with contents std::cout << boost::format("Got packet: %u samples, %u secs, %u ticks") diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index bab8afca6..1d0360799 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -91,13 +91,13 @@ public: * * \param buff a buffer pointing to some read-only memory * \param metadata data describing the buffer's contents - * \param the type of data loaded in the buffer (32fc, 16sc) + * \param io_type the type of data loaded in the buffer * \return the number of samples sent */ virtual size_t send( const boost::asio::const_buffer &buff, const tx_metadata_t &metadata, - const std::string &type = "32fc" + const io_type_t &io_type ) = 0; /*! @@ -123,13 +123,13 @@ public: * * \param buff the buffer to fill with IF data * \param metadata data to fill describing the buffer - * \param the type of data to fill into the buffer (32fc, 16sc) + * \param io_type the type of data to fill into the buffer * \return the number of samples received */ virtual size_t recv( const boost::asio::mutable_buffer &buff, rx_metadata_t &metadata, - const std::string &type = "32fc" + const io_type_t &io_type ) = 0; }; diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt index 10262dd65..e4cdf2cef 100644 --- a/host/include/uhd/types/CMakeLists.txt +++ b/host/include/uhd/types/CMakeLists.txt @@ -20,8 +20,10 @@ INSTALL(FILES clock_config.hpp device_addr.hpp dict.hpp + io_type.hpp mac_addr.hpp metadata.hpp + otw_type.hpp ranges.hpp stream_cmd.hpp time_spec.hpp diff --git a/host/include/uhd/types/clock_config.hpp b/host/include/uhd/types/clock_config.hpp index 8b2fea016..42d74ad90 100644 --- a/host/include/uhd/types/clock_config.hpp +++ b/host/include/uhd/types/clock_config.hpp @@ -29,18 +29,18 @@ namespace uhd{ */ struct UHD_API clock_config_t{ enum ref_source_t { - REF_INT, //internal reference - REF_SMA, //external sma port - REF_MIMO //mimo cable (usrp2 only) + REF_INT = 'i', //internal reference + REF_SMA = 's', //external sma port + REF_MIMO = 'm' //mimo cable (usrp2 only) } ref_source; enum pps_source_t { - PPS_INT, //there is no internal - PPS_SMA, //external sma port - PPS_MIMO //mimo cable (usrp2 only) + PPS_INT = 'i', //there is no internal + PPS_SMA = 's', //external sma port + PPS_MIMO = 'm' //mimo cable (usrp2 only) } pps_source; enum pps_polarity_t { - PPS_NEG, //negative edge - PPS_POS //positive edge + PPS_NEG = 'n', //negative edge + PPS_POS = 'p' //positive edge } pps_polarity; clock_config_t(void); }; diff --git a/host/include/uhd/types/io_type.hpp b/host/include/uhd/types/io_type.hpp new file mode 100644 index 000000000..930394d1b --- /dev/null +++ b/host/include/uhd/types/io_type.hpp @@ -0,0 +1,69 @@ +// +// 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_IO_TYPE_HPP +#define INCLUDED_UHD_TYPES_IO_TYPE_HPP + +#include + +namespace uhd{ + + /*! + * Used to specify the IO type with device send/recv. + */ + class UHD_API io_type_t{ + public: + + /*! + * Built in IO types known to the system. + */ + enum tid_t{ + CUSTOM_TYPE = '?', + COMPLEX_FLOAT32 = 'f', + COMPLEX_INT16 = 's', + COMPLEX_INT8 = 'b' + }; + + /*! + * The size of this io type in bytes. + */ + const size_t size; + + /*! + * The type id of this io type. + * Good for using with switch statements. + */ + const tid_t tid; + + /*! + * Create an io type from a built-in type id. + * \param tid a type id known to the system + */ + io_type_t(tid_t tid); + + /*! + * Create an io type from attributes. + * The tid will be set to custom. + * \param size the size in bytes + */ + io_type_t(size_t size); + + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_IO_TYPE_HPP */ diff --git a/host/include/uhd/types/otw_type.hpp b/host/include/uhd/types/otw_type.hpp new file mode 100644 index 000000000..f10664584 --- /dev/null +++ b/host/include/uhd/types/otw_type.hpp @@ -0,0 +1,63 @@ +// +// 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_OTW_TYPE_HPP +#define INCLUDED_UHD_TYPES_OTW_TYPE_HPP + +#include + +namespace uhd{ + + /*! + * Description for over-the-wire integers: + * The DSP units in the FPGA deal with signed 16-bit integers. + * The width and shift define the translation between OTW and DSP, + * defined by the following relation: otw_int = dsp_int >> shift + * + * Note: possible combinations of width, shift, and byteorder + * depend on the internals of the FPGA. Not all are supported! + */ + struct UHD_API otw_type_t{ + + /*! + * Width of an over-the-wire integer in bits. + */ + size_t width; //in bits + + /*! + * Shift of an over-the-wire integer in bits. + * otw_int = dsp_int >> shift + * dsp_int = otw_int << shift + */ + size_t shift; //in bits + + /*! + * Constants for byte order (borrowed from numpy's dtype) + */ + enum /*bo_t*/ { + BO_NATIVE = '=', + BO_LITTLE_ENDIAN = '<', + BO_BIG_ENDIAN = '>', + BO_NOT_APPLICABLE = '|' + } byteorder; + + otw_type_t(void); + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_OTW_TYPE_HPP */ diff --git a/host/lib/types.cpp b/host/lib/types.cpp index 3fde40596..bf9f8b895 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -23,10 +23,14 @@ #include #include #include +#include +#include #include #include #include +#include #include +#include using namespace uhd; @@ -210,3 +214,34 @@ std::string mac_addr_t::to_string(void) const{ % int(to_bytes()[3]) % int(to_bytes()[4]) % int(to_bytes()[5]) ); } + +/*********************************************************************** + * otw type + **********************************************************************/ +otw_type_t::otw_type_t(void){ + width = 0; + shift = 0; + byteorder = BO_NATIVE; +} + +/*********************************************************************** + * io type + **********************************************************************/ +static size_t tid_to_size(io_type_t::tid_t tid){ + switch(tid){ + case io_type_t::COMPLEX_FLOAT32: return sizeof(std::complex); + case io_type_t::COMPLEX_INT16: return sizeof(std::complex); + case io_type_t::COMPLEX_INT8: return sizeof(std::complex); + default: throw std::runtime_error("unknown io type tid"); + } +} + +io_type_t::io_type_t(tid_t tid) +: size(tid_to_size(tid)), tid(tid){ + /* NOP */ +} + +io_type_t::io_type_t(size_t size) +: size(size), tid(CUSTOM_TYPE){ + /* NOP */ +} diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 280f124d2..c87884ebb 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -172,46 +172,43 @@ void usrp2_impl::recv_raw(rx_metadata_t &metadata){ size_t usrp2_impl::send( const asio::const_buffer &buff, const tx_metadata_t &metadata, - const std::string &type + const io_type_t &io_type ){ boost::uint32_t tx_mem[_mtu/sizeof(boost::uint32_t)]; - boost::uint32_t *items = tx_mem + vrt::max_header_words32; //offset for data - size_t num_samps = _max_tx_samples_per_packet; - - //calculate the number of samples to be copied - //and copy the samples into the send buffer - if (type == "32fc"){ - num_samps = std::min(asio::buffer_size(buff)/sizeof(fc32_t), num_samps); - host_floats_to_usrp2_items(items, asio::buffer_cast(buff), num_samps); - } - else if (type == "16sc"){ - num_samps = std::min(asio::buffer_size(buff)/sizeof(sc16_t), num_samps); - host_items_to_usrp2_items(items, asio::buffer_cast(buff), num_samps); - } - else{ - throw std::runtime_error(str(boost::format("usrp2 send: cannot handle type \"%s\"") % type)); - } + size_t num_samps = std::min( + asio::buffer_size(buff)/io_type.size, + size_t(_max_tx_samples_per_packet) + ); - boost::uint32_t vrt_hdr[vrt::max_header_words32]; size_t num_header_words32, num_packet_words32; size_t packet_count = _tx_stream_id_to_packet_seq[metadata.stream_id]++; //pack metadata into a vrt header vrt::pack( metadata, //input - vrt_hdr, //output + tx_mem, //output num_header_words32, //output num_samps, //input num_packet_words32, //output packet_count //input ); - //copy in the vrt header (yes we left space) - items -= num_header_words32; - std::memcpy(items, vrt_hdr, num_header_words32*sizeof(boost::uint32_t)); + boost::uint32_t *items = tx_mem + num_header_words32; //offset for data + + //copy the samples into the send buffer + switch(io_type.tid){ + case io_type_t::COMPLEX_FLOAT32: + host_floats_to_usrp2_items(items, asio::buffer_cast(buff), num_samps); + break; + case io_type_t::COMPLEX_INT16: + host_items_to_usrp2_items(items, asio::buffer_cast(buff), num_samps); + break; + default: + throw std::runtime_error(str(boost::format("usrp2 send: cannot handle type \"%c\"") % io_type.tid)); + } //send and return number of samples - _data_transport->send(asio::buffer(items, num_packet_words32*sizeof(boost::uint32_t))); + _data_transport->send(asio::buffer(tx_mem, num_packet_words32*sizeof(boost::uint32_t))); return num_samps; } @@ -221,7 +218,7 @@ size_t usrp2_impl::send( size_t usrp2_impl::recv( const asio::mutable_buffer &buff, rx_metadata_t &metadata, - const std::string &type + const io_type_t &io_type ){ //perform a receive if no rx data is waiting to be copied if (asio::buffer_size(_rx_copy_buff) == 0){ @@ -237,21 +234,22 @@ size_t usrp2_impl::recv( //and a pointer into the usrp2 received items memory size_t bytes_to_copy = asio::buffer_size(_rx_copy_buff); if (bytes_to_copy == 0) return 0; //nothing to receive - size_t num_samps = bytes_to_copy/sizeof(boost::uint32_t); + size_t num_samps = std::min( + asio::buffer_size(buff)/io_type.size, + bytes_to_copy/sizeof(boost::uint32_t) + ); const boost::uint32_t *items = asio::buffer_cast(_rx_copy_buff); - //calculate the number of samples to be copied - //and copy the samples from the recv buffer - if (type == "32fc"){ - num_samps = std::min(asio::buffer_size(buff)/sizeof(fc32_t), num_samps); + //copy the samples from the recv buffer + switch(io_type.tid){ + case io_type_t::COMPLEX_FLOAT32: usrp2_items_to_host_floats(asio::buffer_cast(buff), items, num_samps); - } - else if (type == "16sc"){ - num_samps = std::min(asio::buffer_size(buff)/sizeof(sc16_t), num_samps); + break; + case io_type_t::COMPLEX_INT16: usrp2_items_to_host_items(asio::buffer_cast(buff), items, num_samps); - } - else{ - throw std::runtime_error(str(boost::format("usrp2 recv: cannot handle type \"%s\"") % type)); + break; + default: + throw std::runtime_error(str(boost::format("usrp2 recv: cannot handle type \"%c\"") % io_type.tid)); } //update the rx copy buffer to reflect the bytes copied diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 6535e7049..3468a0cf1 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -106,8 +106,8 @@ public: double get_master_clock_freq(void); //the io interface - size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const std::string &); - size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const std::string &); + size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const uhd::io_type_t &); + size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const uhd::io_type_t &); private: //device properties interface -- cgit v1.2.3