summaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2010-03-10 14:47:03 -0800
committerJosh Blum <josh@joshknows.com>2010-03-10 14:47:03 -0800
commit8e9a8464386db03a596e0b88d0714d22723d37d0 (patch)
treede6a35865ba1d54bb4d908d86397aeba459b3e01 /host
parentbb86022d5a5f7055cdeebaeb4a55216e1a056fd4 (diff)
downloaduhd-8e9a8464386db03a596e0b88d0714d22723d37d0.tar.gz
uhd-8e9a8464386db03a596e0b88d0714d22723d37d0.tar.bz2
uhd-8e9a8464386db03a596e0b88d0714d22723d37d0.zip
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...
Diffstat (limited to 'host')
-rw-r--r--host/apps/discover_usrps.cpp2
-rw-r--r--host/include/uhd/CMakeLists.txt1
-rw-r--r--host/include/uhd/props.hpp20
-rw-r--r--host/include/uhd/simple_device.hpp111
-rw-r--r--host/include/uhd/time_spec.hpp19
-rw-r--r--host/include/uhd/utils.hpp105
-rw-r--r--host/lib/CMakeLists.txt2
-rw-r--r--host/lib/simple_device.cpp303
-rw-r--r--host/lib/time_spec.cpp40
-rw-r--r--host/lib/usrp/usrp2/dboard_impl.cpp9
-rw-r--r--host/lib/usrp/usrp2/dsp_impl.cpp21
-rw-r--r--host/lib/usrp/usrp2/fw_common.h8
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp35
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp1
14 files changed, 581 insertions, 96 deletions
diff --git a/host/apps/discover_usrps.cpp b/host/apps/discover_usrps.cpp
index 448095726..d670d1651 100644
--- a/host/apps/discover_usrps.cpp
+++ b/host/apps/discover_usrps.cpp
@@ -63,7 +63,7 @@ int main(int argc, char *argv[]){
std::cout << "-- USRP Device " << i << std::endl;
std::cout << "--------------------------------------------------" << std::endl;
std::cout << device_addrs[i] << std::endl << std::endl;
- //uhd::device::make(device_addrs[i]); //test make
+ uhd::device::make(device_addrs[i]); //test make
}
return 0;
diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt
index f4fb96786..522f43afd 100644
--- a/host/include/uhd/CMakeLists.txt
+++ b/host/include/uhd/CMakeLists.txt
@@ -26,6 +26,7 @@ INSTALL(FILES
gain_handler.hpp
metadata.hpp
props.hpp
+ simple_device.hpp
time_spec.hpp
utils.hpp
wax.hpp
diff --git a/host/include/uhd/props.hpp b/host/include/uhd/props.hpp
index cf301d4bd..dea2baf52 100644
--- a/host/include/uhd/props.hpp
+++ b/host/include/uhd/props.hpp
@@ -116,16 +116,16 @@ namespace uhd{
enum dboard_prop_t{
DBOARD_PROP_NAME, //ro, std::string
DBOARD_PROP_SUBDEV, //ro, wax::obj
- DBOARD_PROP_SUBDEV_NAMES, //ro, prop_names_t
- DBOARD_PROP_CODEC //ro, wax::obj
- };
+ DBOARD_PROP_SUBDEV_NAMES //ro, prop_names_t
+ //DBOARD_PROP_CODEC //ro, wax::obj //----> not sure, dont have to deal with yet
+ };
- /*!
+ /*! ------ not dealing with yet, commented out ------------
* Possible device codec properties:
* A codec is expected to have a rate and gain elements.
* Other properties can be discovered through the others prop.
*/
- enum codec_prop_t{
+ /*enum codec_prop_t{
CODEC_PROP_NAME, //ro, std::string
CODEC_PROP_OTHERS, //ro, prop_names_t
CODEC_PROP_GAIN, //rw, gain_t
@@ -133,8 +133,8 @@ namespace uhd{
CODEC_PROP_GAIN_MIN, //ro, gain_t
CODEC_PROP_GAIN_STEP, //ro, gain_t
CODEC_PROP_GAIN_NAMES, //ro, prop_names_t
- CODEC_PROP_CLOCK_RATE //ro, freq_t
- };
+ //CODEC_PROP_CLOCK_RATE //ro, freq_t //----> not sure we care to know
+ };*/
/*!
* Possible device subdev properties
@@ -156,9 +156,9 @@ namespace uhd{
SUBDEV_PROP_QUADRATURE, //ro, bool
SUBDEV_PROP_IQ_SWAPPED, //ro, bool
SUBDEV_PROP_SPECTRUM_INVERTED, //ro, bool
- SUBDEV_PROP_IS_TX, //ro, bool
- SUBDEV_PROP_RSSI, //ro, gain_t
- SUBDEV_PROP_BANDWIDTH //rw, freq_t
+ SUBDEV_PROP_LO_INTERFERES //ro, bool
+ //SUBDEV_PROP_RSSI, //ro, gain_t //----> not on all boards, use named prop
+ //SUBDEV_PROP_BANDWIDTH //rw, freq_t //----> not on all boards, use named prop
};
} //namespace uhd
diff --git a/host/include/uhd/simple_device.hpp b/host/include/uhd/simple_device.hpp
new file mode 100644
index 000000000..64ec85a5c
--- /dev/null
+++ b/host/include/uhd/simple_device.hpp
@@ -0,0 +1,111 @@
+//
+// 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 <http://www.gnu.org/licenses/>.
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+#include <uhd/device.hpp>
+#include <vector>
+
+#ifndef INCLUDED_UHD_SIMPLE_DEVICE_HPP
+#define INCLUDED_UHD_SIMPLE_DEVICE_HPP
+
+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 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.
+ * The wrapper provides convenience functions to tune the devices
+ * as well as to set the dboard gains, antennas, and other properties.
+ */
+class simple_device : boost::noncopyable{
+public:
+ typedef boost::shared_ptr<simple_device> sptr;
+ static sptr make(const std::string &args);
+
+ virtual device::sptr get_device(void) = 0;
+
+ virtual std::string get_name(void) = 0;
+
+ /*******************************************************************
+ * Streaming
+ ******************************************************************/
+ virtual void set_streaming(bool enb) = 0;
+ virtual bool get_streaming(void) = 0;
+
+ /*******************************************************************
+ * RX methods
+ ******************************************************************/
+ virtual void set_rx_rate(double rate) = 0;
+ virtual double get_rx_rate(void) = 0;
+ virtual std::vector<double> get_rx_rates(void) = 0;
+
+ virtual tune_result_t set_rx_freq(double target_freq, double lo_offset) = 0;
+ virtual double get_rx_freq_min(void) = 0;
+ virtual double get_rx_freq_max(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 void set_rx_antenna(const std::string &ant) = 0;
+ virtual std::string get_rx_antenna(void) = 0;
+ virtual std::vector<std::string> get_rx_antennas(void) = 0;
+
+ /*******************************************************************
+ * TX methods
+ ******************************************************************/
+ virtual void set_tx_rate(double rate) = 0;
+ virtual double get_tx_rate(void) = 0;
+ virtual std::vector<double> get_tx_rates(void) = 0;
+
+ virtual tune_result_t set_tx_freq(double target_freq, double lo_offset) = 0;
+ virtual double get_tx_freq_min(void) = 0;
+ virtual double get_tx_freq_max(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 void set_tx_antenna(const std::string &ant) = 0;
+ virtual std::string get_tx_antenna(void) = 0;
+ virtual std::vector<std::string> get_tx_antennas(void) = 0;
+};
+
+} //namespace uhd
+
+#endif /* INCLUDED_UHD_SIMPLE_DEVICE_HPP */
diff --git a/host/include/uhd/time_spec.hpp b/host/include/uhd/time_spec.hpp
index e5657e555..7e182236b 100644
--- a/host/include/uhd/time_spec.hpp
+++ b/host/include/uhd/time_spec.hpp
@@ -15,6 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
+#include <boost/date_time/posix_time/posix_time.hpp>
#include <stdint.h>
#ifndef INCLUDED_UHD_TIME_SPEC_HPP
@@ -36,20 +37,22 @@ namespace uhd{
* Create a time_spec_t that holds a wildcard time.
* This will have implementation-specific meaning.
*/
- time_spec_t(void){
- secs = ~0;
- ticks = ~0;
- }
+ time_spec_t(void);
/*!
* Create a time_spec_t from seconds and ticks.
* \param new_secs the new seconds
* \param new_ticks the new ticks (default = 0)
*/
- time_spec_t(uint32_t new_secs, uint32_t new_ticks = 0){
- secs = new_secs;
- ticks = new_ticks;
- }
+ time_spec_t(uint32_t new_secs, 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
diff --git a/host/include/uhd/utils.hpp b/host/include/uhd/utils.hpp
index 9bbdc83c9..25a7b5abd 100644
--- a/host/include/uhd/utils.hpp
+++ b/host/include/uhd/utils.hpp
@@ -15,18 +15,14 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#include <uhd/wax.hpp>
-#include <boost/foreach.hpp>
-#include <boost/format.hpp>
-#include <boost/function.hpp>
-#include <stdexcept>
-#include <algorithm>
-#include <vector>
-#include <map>
-
#ifndef INCLUDED_UHD_UTILS_HPP
#define INCLUDED_UHD_UTILS_HPP
+#include <stdexcept>
+#include <algorithm>
+#include <boost/format.hpp>
+#include <boost/current_function.hpp>
+
/*!
* Useful templated functions and classes that I like to pretend are part of stl
*/
@@ -40,7 +36,9 @@ namespace std{
};
#define ASSERT_THROW(_x) if (not (_x)) { \
- throw std::assert_error("Assertion Failed: " + std::string(#_x)); \
+ throw std::assert_error(str(boost::format( \
+ "Assertion Failed:\n %s:%d\n %s\n __/ %s __/" \
+ ) % __FILE__ % __LINE__ % BOOST_CURRENT_FUNCTION % std::string(#_x))); \
}
template<class T, class InputIterator, class Function>
@@ -57,9 +55,9 @@ namespace std{
return last != std::find(first, last, elem);
}
- template<class T, class V>
- bool has(const V &vector, const T &elem){
- return has(vector.begin(), vector.end(), elem);
+ template<class T, class Iterable>
+ bool has(const Iterable &iterable, const T &elem){
+ return has(iterable.begin(), iterable.end(), elem);
}
template<class T>
@@ -75,52 +73,43 @@ namespace std{
}//namespace std
-/*namespace uhd{
-
-inline void tune(
- freq_t target_freq,
- freq_t lo_offset,
- wax::obj subdev_freq_proxy,
- bool subdev_quadrature,
- bool subdev_spectrum_inverted,
- bool subdev_is_tx,
- wax::obj dsp_freq_proxy,
- freq_t dsp_sample_rate
-){
- // Ask the d'board to tune as closely as it can to target_freq+lo_offset
- subdev_freq_proxy = target_freq + lo_offset;
- freq_t inter_freq = wax::cast<freq_t>(subdev_freq_proxy);
-
- // Calculate the DDC setting that will downconvert the baseband from the
- // daughterboard to our target frequency.
- freq_t delta_freq = target_freq - inter_freq;
- freq_t delta_sign = std::signum(delta_freq);
- delta_freq *= delta_sign;
- delta_freq = fmod(delta_freq, dsp_sample_rate);
- bool inverted = delta_freq > dsp_sample_rate/2.0;
- freq_t dxc_freq = inverted? (delta_freq - dsp_sample_rate) : (-delta_freq);
- 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){
- dxc_freq = -dxc_freq;
- inverted = not inverted;
- }
- if (subdev_is_tx){
- dxc_freq = -dxc_freq; // down conversion versus up conversion
+#include <boost/format.hpp>
+#include <boost/foreach.hpp>
+#include <boost/lexical_cast.hpp>
+
+namespace uhd{
+
+ /*!
+ * Check that an element is found in a container.
+ * If not, throw a meaningful assertion error.
+ * The "what" in the error will show what is
+ * being set and a list of known good values.
+ *
+ * \param iterable a list of possible settings
+ * \param elem an element that may be in the list
+ * \param what a description of what is being set
+ * \throw assertion_error when elem not in list
+ */
+ template<class T, class Iterable> void assert_has(
+ const Iterable &iterable,
+ const T &elem,
+ const std::string &what = "unknown"
+ ){
+ if (std::has(iterable, elem)) return;
+ std::string possible_values = "";
+ BOOST_FOREACH(T e, iterable){
+ if (e != iterable.begin()[0]) possible_values += ", ";
+ possible_values += boost::lexical_cast<std::string>(e);
+ }
+ throw std::assert_error(str(boost::format(
+ "Error: %s is not a valid %s. "
+ "Possible values are: [%s]."
+ )
+ % boost::lexical_cast<std::string>(elem)
+ % what % possible_values
+ ));
}
- dsp_freq_proxy = dxc_freq;
- //freq_t actual_dxc_freq = wax::cast<freq_t>(dsp_freq_proxy);
-
- //return some kind of tune result tuple/struct
-}
-
-} //namespace uhd*/
+}//namespace uhd
#endif /* INCLUDED_UHD_UTILS_HPP */
diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt
index b1daf22d1..b141d67bb 100644
--- a/host/lib/CMakeLists.txt
+++ b/host/lib/CMakeLists.txt
@@ -23,6 +23,8 @@ SET(libuhd_sources
device_addr.cpp
gain_handler.cpp
metadata.cpp
+ simple_device.cpp
+ time_spec.cpp
wax.cpp
transport/udp_simple.cpp
transport/vrt.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 <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/simple_device.hpp>
+#include <uhd/device.hpp>
+#include <uhd/utils.hpp>
+#include <uhd/props.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/algorithm/string/trim.hpp>
+#include <boost/foreach.hpp>
+#include <boost/format.hpp>
+#include <stdexcept>
+
+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<bool>(subdev[SUBDEV_PROP_QUADRATURE]);
+ bool subdev_spectrum_inverted = wax::cast<bool>(subdev[SUBDEV_PROP_SPECTRUM_INVERTED]);
+ wax::obj dxc_freq_proxy = dxc[std::string("freq")];
+ double dxc_sample_rate = wax::cast<double>(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<double>(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<double>(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<std::string> 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<std::string> 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<double> get_xx_rates(wax::obj decerps, wax::obj rate){
+ std::vector<double> rates;
+ BOOST_FOREACH(size_t decerp, wax::cast<std::vector<size_t> >(decerps)){
+ rates.push_back(wax::cast<double>(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<std::string>(_mboard[MBOARD_PROP_NAME]);
+ }
+
+ /*******************************************************************
+ * Streaming
+ ******************************************************************/
+ void set_streaming(bool enb){
+ _rx_ddc[std::string("enabled")] = enb;
+ }
+
+ bool get_streaming(void){
+ return wax::cast<bool>(_rx_ddc[std::string("enabled")]);
+ }
+
+ /*******************************************************************
+ * RX methods
+ ******************************************************************/
+ void set_rx_rate(double rate){
+ double samp_rate = wax::cast<double>(_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<double>(_rx_ddc[std::string("rate")]);
+ size_t decim = wax::cast<size_t>(_rx_ddc[std::string("decim")]);
+ return samp_rate/decim;
+ }
+
+ std::vector<double> 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<double>(_rx_subdev[SUBDEV_PROP_FREQ_MIN]);
+ }
+
+ double get_rx_freq_max(void){
+ return wax::cast<double>(_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<float>(_rx_subdev[SUBDEV_PROP_GAIN]);
+ }
+
+ float get_rx_gain_min(void){
+ return wax::cast<float>(_rx_subdev[SUBDEV_PROP_GAIN_MIN]);
+ }
+
+ float get_rx_gain_max(void){
+ return wax::cast<float>(_rx_subdev[SUBDEV_PROP_GAIN_MAX]);
+ }
+
+ float get_rx_gain_step(void){
+ return wax::cast<float>(_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<std::string>(_rx_subdev[SUBDEV_PROP_ANTENNA]);
+ }
+
+ std::vector<std::string> get_rx_antennas(void){
+ return wax::cast<std::vector<std::string> >(_rx_subdev[SUBDEV_PROP_ANTENNA_NAMES]);
+ }
+
+ /*******************************************************************
+ * TX methods
+ ******************************************************************/
+ void set_tx_rate(double rate){
+ double samp_rate = wax::cast<double>(_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<double>(_tx_duc[std::string("rate")]);
+ size_t interp = wax::cast<size_t>(_tx_duc[std::string("interp")]);
+ return samp_rate/interp;
+ }
+
+ std::vector<double> 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<double>(_tx_subdev[SUBDEV_PROP_FREQ_MIN]);
+ }
+
+ double get_tx_freq_max(void){
+ return wax::cast<double>(_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<float>(_tx_subdev[SUBDEV_PROP_GAIN]);
+ }
+
+ float get_tx_gain_min(void){
+ return wax::cast<float>(_tx_subdev[SUBDEV_PROP_GAIN_MIN]);
+ }
+
+ float get_tx_gain_max(void){
+ return wax::cast<float>(_tx_subdev[SUBDEV_PROP_GAIN_MAX]);
+ }
+
+ float get_tx_gain_step(void){
+ return wax::cast<float>(_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<std::string>(_tx_subdev[SUBDEV_PROP_ANTENNA]);
+ }
+
+ std::vector<std::string> get_tx_antennas(void){
+ return wax::cast<std::vector<std::string> >(_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)));
+}
diff --git a/host/lib/time_spec.cpp b/host/lib/time_spec.cpp
new file mode 100644
index 000000000..193441342
--- /dev/null
+++ b/host/lib/time_spec.cpp
@@ -0,0 +1,40 @@
+//
+// 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 <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/time_spec.hpp>
+
+using namespace uhd;
+
+time_spec_t::time_spec_t(void){
+ secs = ~0;
+ ticks = ~0;
+}
+
+time_spec_t::time_spec_t(uint32_t new_secs, 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(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 = td.total_seconds();
+ double time_ticks_per_device_ticks = time_tick_rate/tick_rate;
+ ticks = td.fractional_seconds()/time_ticks_per_device_ticks;
+}
diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp
index 32c64f541..da05c3241 100644
--- a/host/lib/usrp/usrp2/dboard_impl.cpp
+++ b/host/lib/usrp/usrp2/dboard_impl.cpp
@@ -16,6 +16,7 @@
//
#include <uhd/utils.hpp>
+#include <boost/format.hpp>
#include "usrp2_impl.hpp"
#include "dboard_interface.hpp"
@@ -83,8 +84,8 @@ void usrp2_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){
val = _dboard_manager->get_rx_subdev_names();
return;
- case DBOARD_PROP_CODEC:
- throw std::runtime_error("unhandled prop in usrp2 dboard");
+ //case DBOARD_PROP_CODEC:
+ // throw std::runtime_error("unhandled prop in usrp2 dboard");
}
}
@@ -113,8 +114,8 @@ void usrp2_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){
val = _dboard_manager->get_tx_subdev_names();
return;
- case DBOARD_PROP_CODEC:
- throw std::runtime_error("unhandled prop in usrp2 dboard");
+ //case DBOARD_PROP_CODEC:
+ // throw std::runtime_error("unhandled prop in usrp2 dboard");
}
}
diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp
index 7831b7667..cb7f58ec8 100644
--- a/host/lib/usrp/usrp2/dsp_impl.cpp
+++ b/host/lib/usrp/usrp2/dsp_impl.cpp
@@ -16,6 +16,7 @@
//
#include <uhd/utils.hpp>
+#include <boost/format.hpp>
#include <boost/assign/list_of.hpp>
#include "usrp2_impl.hpp"
@@ -110,7 +111,7 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){
prop_names_t others = boost::assign::list_of
("rate")
("decim")
- ("decim_rates")
+ ("decims")
("freq")
("enabled")
("stream_at")
@@ -131,7 +132,7 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){
val = _ddc_decim;
return;
}
- else if (key_name == "decim_rates"){
+ else if (key_name == "decims"){
val = _allowed_decim_and_interp_rates;
return;
}
@@ -154,10 +155,10 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){
std::string key_name = wax::cast<std::string>(key);
if (key_name == "decim"){
size_t new_decim = wax::cast<size_t>(val);
- ASSERT_THROW(std::has(
+ assert_has(
_allowed_decim_and_interp_rates,
- new_decim
- ));
+ new_decim, "usrp2 decimation"
+ );
_ddc_decim = new_decim; //shadow
update_ddc_config();
return;
@@ -244,7 +245,7 @@ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){
prop_names_t others = boost::assign::list_of
("rate")
("interp")
- ("interp_rates")
+ ("interps")
("freq")
;
val = others;
@@ -263,7 +264,7 @@ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){
val = _duc_interp;
return;
}
- else if (key_name == "interp_rates"){
+ else if (key_name == "interps"){
val = _allowed_decim_and_interp_rates;
return;
}
@@ -282,10 +283,10 @@ void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){
std::string key_name = wax::cast<std::string>(key);
if (key_name == "interp"){
size_t new_interp = wax::cast<size_t>(val);
- ASSERT_THROW(std::has(
+ assert_has(
_allowed_decim_and_interp_rates,
- new_interp
- ));
+ new_interp, "usrp2 interpolation"
+ );
_duc_interp = new_interp; //shadow
update_duc_config();
return;
diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h
index 8e4b2ba35..10c1ef8cf 100644
--- a/host/lib/usrp/usrp2/fw_common.h
+++ b/host/lib/usrp/usrp2/fw_common.h
@@ -91,6 +91,9 @@ typedef enum{
USRP2_CTRL_ID_SETUP_THIS_DUC_FOR_ME_BRO,
USRP2_CTRL_ID_TOTALLY_SETUP_THE_DUC_DUDE,
+ USRP2_CTRL_ID_GOT_A_NEW_TIME_FOR_YOU_BRO,
+ USRP2_CTRL_ID_SWEET_I_GOT_THAT_TIME_DUDE,
+
USRP2_CTRL_ID_PEACE_OUT
} usrp2_ctrl_id_t;
@@ -186,6 +189,11 @@ typedef struct{
uint32_t interp;
uint32_t scale_iq;
} duc_args;
+ struct {
+ uint32_t secs;
+ uint32_t ticks;
+ uint8_t now;
+ } time_args;
} data;
} usrp2_ctrl_data_t;
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index 8e682a675..47e22c473 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -28,6 +28,10 @@ void usrp2_impl::mboard_init(void){
boost::bind(&usrp2_impl::mboard_get, this, _1, _2),
boost::bind(&usrp2_impl::mboard_set, this, _1, _2)
);
+
+ //set the time on the usrp2 as close as possible to the system utc time
+ boost::posix_time::ptime now(boost::posix_time::microsec_clock::universal_time());
+ set_time_spec(time_spec_t(now, get_master_clock_freq()), true);
}
void usrp2_impl::init_clock_config(void){
@@ -64,6 +68,19 @@ void usrp2_impl::update_clock_config(void){
ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_GOT_THE_NEW_CLOCK_CONFIG_DUDE);
}
+void usrp2_impl::set_time_spec(const time_spec_t &time_spec, bool now){
+ //setup the out data
+ usrp2_ctrl_data_t out_data;
+ out_data.id = htonl(USRP2_CTRL_ID_GOT_A_NEW_TIME_FOR_YOU_BRO);
+ out_data.data.time_args.secs = htonl(time_spec.secs);
+ out_data.data.time_args.ticks = htonl(time_spec.ticks);
+ out_data.data.time_args.now = (now)? 1 : 0;
+
+ //send and recv
+ usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
+ ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_SWEET_I_GOT_THAT_TIME_DUDE);
+}
+
/***********************************************************************
* MBoard Get Properties
**********************************************************************/
@@ -157,7 +174,7 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){
case MBOARD_PROP_PPS_SOURCE:{
std::string name = wax::cast<std::string>(val);
- ASSERT_THROW(_pps_source_dict.has_key(name));
+ assert_has(_pps_source_dict.get_keys(), name, "usrp2 pps source");
_pps_source = name; //shadow
update_clock_config();
}
@@ -165,7 +182,7 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){
case MBOARD_PROP_PPS_POLARITY:{
std::string name = wax::cast<std::string>(val);
- ASSERT_THROW(_pps_polarity_dict.has_key(name));
+ assert_has(_pps_polarity_dict.get_keys(), name, "usrp2 pps polarity");
_pps_polarity = name; //shadow
update_clock_config();
}
@@ -173,12 +190,22 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){
case MBOARD_PROP_REF_SOURCE:{
std::string name = wax::cast<std::string>(val);
- ASSERT_THROW(_ref_source_dict.has_key(name));
+ assert_has(_ref_source_dict.get_keys(), name, "usrp2 reference source");
_ref_source = name; //shadow
update_clock_config();
}
return;
+ case MBOARD_PROP_TIME_NOW:{
+ set_time_spec(wax::cast<time_spec_t>(val), true);
+ return;
+ }
+
+ case MBOARD_PROP_TIME_NEXT_PPS:{
+ set_time_spec(wax::cast<time_spec_t>(val), false);
+ return;
+ }
+
case MBOARD_PROP_NAME:
case MBOARD_PROP_OTHERS:
case MBOARD_PROP_CLOCK_RATE:
@@ -192,8 +219,6 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){
case MBOARD_PROP_TX_DBOARD_NAMES:
case MBOARD_PROP_PPS_SOURCE_NAMES:
case MBOARD_PROP_REF_SOURCE_NAMES:
- case MBOARD_PROP_TIME_NOW:
- case MBOARD_PROP_TIME_NEXT_PPS:
throw std::runtime_error("Error: trying to set read-only property on usrp2 mboard");
}
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
index f4e6054bd..fc713c2bf 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -135,6 +135,7 @@ private:
std::string _pps_source, _pps_polarity, _ref_source;
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<std::string, usrp2_pps_source_t> _pps_source_dict;