summaryrefslogtreecommitdiff
path: root/gr-uhd/lib
diff options
context:
space:
mode:
Diffstat (limited to 'gr-uhd/lib')
-rw-r--r--gr-uhd/lib/CMakeLists.txt1
-rw-r--r--gr-uhd/lib/usrp_block_impl.cc428
-rw-r--r--gr-uhd/lib/usrp_block_impl.h199
-rw-r--r--gr-uhd/lib/usrp_common.h211
-rw-r--r--gr-uhd/lib/usrp_sink_impl.cc293
-rw-r--r--gr-uhd/lib/usrp_sink_impl.h48
-rw-r--r--gr-uhd/lib/usrp_source_impl.cc270
-rw-r--r--gr-uhd/lib/usrp_source_impl.h47
8 files changed, 660 insertions, 837 deletions
diff --git a/gr-uhd/lib/CMakeLists.txt b/gr-uhd/lib/CMakeLists.txt
index b3ead137af..531bd40b09 100644
--- a/gr-uhd/lib/CMakeLists.txt
+++ b/gr-uhd/lib/CMakeLists.txt
@@ -46,6 +46,7 @@ link_directories(${LOG4CPP_LIBRARY_DIRS})
# Setup library
########################################################################
list(APPEND gr_uhd_sources
+ usrp_block_impl.cc
usrp_source_impl.cc
usrp_sink_impl.cc
amsg_source_impl.cc
diff --git a/gr-uhd/lib/usrp_block_impl.cc b/gr-uhd/lib/usrp_block_impl.cc
new file mode 100644
index 0000000000..be24c57c6e
--- /dev/null
+++ b/gr-uhd/lib/usrp_block_impl.cc
@@ -0,0 +1,428 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "usrp_block_impl.h"
+#include <boost/make_shared.hpp>
+
+using namespace gr::uhd;
+
+const double usrp_block_impl::LOCK_TIMEOUT = 1.5;
+
+/**********************************************************************
+ * Structors
+ *********************************************************************/
+usrp_block::usrp_block(
+ const std::string &name,
+ gr::io_signature::sptr input_signature,
+ gr::io_signature::sptr output_signature
+) : sync_block(name, input_signature, output_signature)
+{
+ // nop
+}
+
+usrp_block_impl::usrp_block_impl(
+ const ::uhd::device_addr_t &device_addr,
+ const ::uhd::stream_args_t &stream_args,
+ const std::string &ts_tag_name
+) : _stream_args(stream_args),
+ _nchan(stream_args.channels.size()),
+ _stream_now(_nchan == 1 and ts_tag_name.empty()),
+ _start_time_set(false),
+ _curr_freq(stream_args.channels.size(), 0.0),
+ _curr_lo_offset(stream_args.channels.size(), 0.0),
+ _curr_gain(stream_args.channels.size(), 0.0),
+ _chans_to_tune(stream_args.channels.size())
+{
+ if(stream_args.cpu_format == "fc32")
+ _type = boost::make_shared< ::uhd::io_type_t >(::uhd::io_type_t::COMPLEX_FLOAT32);
+ if(stream_args.cpu_format == "sc16")
+ _type = boost::make_shared< ::uhd::io_type_t >(::uhd::io_type_t::COMPLEX_INT16);
+ _dev = ::uhd::usrp::multi_usrp::make(device_addr);
+
+ _check_mboard_sensors_locked();
+
+ // Set up message ports:
+ message_port_register_in(pmt::mp("command"));
+ set_msg_handler(
+ pmt::mp("command"),
+ boost::bind(&usrp_block_impl::msg_handler_command, this, _1)
+ );
+}
+
+usrp_block_impl::~usrp_block_impl()
+{
+ // nop
+}
+
+/**********************************************************************
+ * Helpers
+ *********************************************************************/
+void usrp_block_impl::_update_stream_args(const ::uhd::stream_args_t &stream_args_)
+{
+ ::uhd::stream_args_t stream_args(stream_args_);
+ if (stream_args.channels.empty()) {
+ stream_args.channels = _stream_args.channels;
+ }
+ if (stream_args.cpu_format != _stream_args.cpu_format ||
+ stream_args.channels.size() != _stream_args.channels.size()) {
+ throw std::runtime_error("Cannot change I/O signatures while updating stream args!");
+ }
+ _stream_args = stream_args;
+}
+
+bool usrp_block_impl::_wait_for_locked_sensor(
+ std::vector<std::string> sensor_names,
+ const std::string &sensor_name,
+ get_sensor_fn_t get_sensor_fn
+){
+ if (std::find(sensor_names.begin(), sensor_names.end(), sensor_name) == sensor_names.end())
+ return true;
+
+ boost::system_time start = boost::get_system_time();
+ boost::system_time first_lock_time;
+
+ while (true) {
+ if ((not first_lock_time.is_not_a_date_time()) and
+ (boost::get_system_time() > (first_lock_time + boost::posix_time::seconds(LOCK_TIMEOUT)))) {
+ break;
+ }
+
+ if (get_sensor_fn(sensor_name).to_bool()) {
+ if (first_lock_time.is_not_a_date_time())
+ first_lock_time = boost::get_system_time();
+ }
+ else {
+ first_lock_time = boost::system_time(); //reset to 'not a date time'
+
+ if (boost::get_system_time() > (start + boost::posix_time::seconds(LOCK_TIMEOUT))){
+ return false;
+ }
+ }
+
+ boost::this_thread::sleep(boost::posix_time::milliseconds(100));
+ }
+
+ return true;
+}
+
+bool usrp_block_impl::_unpack_chan_command(
+ std::string &command,
+ pmt::pmt_t &cmd_val,
+ int &chan,
+ const pmt::pmt_t &cmd_pmt
+) {
+ try {
+ chan = -1; // Default value
+ if (pmt::is_tuple(cmd_pmt) and (pmt::length(cmd_pmt) == 2 or pmt::length(cmd_pmt) == 3)) {
+ command = pmt::symbol_to_string(pmt::tuple_ref(cmd_pmt, 0));
+ cmd_val = pmt::tuple_ref(cmd_pmt, 1);
+ if (pmt::length(cmd_pmt) == 3) {
+ chan = pmt::to_long(pmt::tuple_ref(cmd_pmt, 2));
+ }
+ }
+ else if (pmt::is_pair(cmd_pmt)) {
+ command = pmt::symbol_to_string(pmt::car(cmd_pmt));
+ cmd_val = pmt::cdr(cmd_pmt);
+ if (pmt::is_pair(cmd_val)) {
+ chan = pmt::to_long(pmt::car(cmd_val));
+ cmd_val = pmt::cdr(cmd_val);
+ }
+ }
+ else {
+ return false;
+ }
+ } catch (pmt::wrong_type w) {
+ return false;
+ }
+ return true;
+}
+
+bool usrp_block_impl::_check_mboard_sensors_locked()
+{
+ bool clocks_locked = true;
+
+ // Check ref lock for all mboards
+ for (size_t mboard_index = 0; mboard_index < _dev->get_num_mboards(); mboard_index++) {
+ std::string sensor_name = "ref_locked";
+ if (_dev->get_clock_source(mboard_index) == "internal") {
+ continue;
+ }
+ else if (_dev->get_clock_source(mboard_index) == "mimo") {
+ sensor_name = "mimo_locked";
+ }
+ if (not _wait_for_locked_sensor(
+ get_mboard_sensor_names(mboard_index),
+ sensor_name,
+ boost::bind(&usrp_block_impl::get_mboard_sensor, this, _1, mboard_index)
+ )) {
+ GR_LOG_WARN(d_logger, boost::format("Sensor '%s' failed to lock within timeout on motherboard %d.") % sensor_name % mboard_index);
+ clocks_locked = false;
+ }
+ }
+
+ return clocks_locked;
+}
+
+void
+usrp_block_impl::_set_center_freq_from_internals_allchans()
+{
+ for (size_t chan = 0; chan < _nchan; chan++) {
+ if (_chans_to_tune[chan]) {
+ _set_center_freq_from_internals(chan);
+ }
+ }
+}
+
+
+/**********************************************************************
+ * Public API calls
+ *********************************************************************/
+::uhd::sensor_value_t
+usrp_block_impl::get_mboard_sensor(const std::string &name,
+ size_t mboard)
+{
+ return _dev->get_mboard_sensor(name, mboard);
+}
+
+std::vector<std::string>
+usrp_block_impl::get_mboard_sensor_names(size_t mboard)
+{
+ return _dev->get_mboard_sensor_names(mboard);
+}
+
+void
+usrp_block_impl::set_clock_config(const ::uhd::clock_config_t &clock_config,
+ size_t mboard)
+{
+ return _dev->set_clock_config(clock_config, mboard);
+}
+
+void
+usrp_block_impl::set_time_source(const std::string &source,
+ const size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
+ return _dev->set_time_source(source, mboard);
+#else
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+std::string
+usrp_block_impl::get_time_source(const size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
+ return _dev->get_time_source(mboard);
+#else
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+std::vector<std::string>
+usrp_block_impl::get_time_sources(const size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
+ return _dev->get_time_sources(mboard);
+#else
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+void
+usrp_block_impl::set_clock_source(const std::string &source,
+ const size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
+ return _dev->set_clock_source(source, mboard);
+#else
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+std::string
+usrp_block_impl::get_clock_source(const size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
+ return _dev->get_clock_source(mboard);
+#else
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+std::vector<std::string>
+usrp_block_impl::get_clock_sources(const size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
+ return _dev->get_clock_sources(mboard);
+#else
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+double
+usrp_block_impl::get_clock_rate(size_t mboard)
+{
+ return _dev->get_master_clock_rate(mboard);
+}
+
+void
+usrp_block_impl::set_clock_rate(double rate, size_t mboard)
+{
+ return _dev->set_master_clock_rate(rate, mboard);
+}
+
+::uhd::time_spec_t
+usrp_block_impl::get_time_now(size_t mboard)
+{
+ return _dev->get_time_now(mboard);
+}
+
+::uhd::time_spec_t
+usrp_block_impl::get_time_last_pps(size_t mboard)
+{
+ return _dev->get_time_last_pps(mboard);
+}
+
+void
+usrp_block_impl::set_time_now(const ::uhd::time_spec_t &time_spec,
+ size_t mboard)
+{
+ return _dev->set_time_now(time_spec, mboard);
+}
+
+void
+usrp_block_impl::set_time_next_pps(const ::uhd::time_spec_t &time_spec)
+{
+ return _dev->set_time_next_pps(time_spec);
+}
+
+void
+usrp_block_impl::set_time_unknown_pps(const ::uhd::time_spec_t &time_spec)
+{
+ return _dev->set_time_unknown_pps(time_spec);
+}
+
+void
+usrp_block_impl::set_command_time(const ::uhd::time_spec_t &time_spec,
+ size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_COMMAND_TIME_API
+ return _dev->set_command_time(time_spec, mboard);
+#else
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+void
+usrp_block_impl::clear_command_time(size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_COMMAND_TIME_API
+ return _dev->clear_command_time(mboard);
+#else
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+void
+usrp_block_impl::set_user_register(const uint8_t addr,
+ const uint32_t data,
+ size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_USER_REGS_API
+ _dev->set_user_register(addr, data, mboard);
+#else
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+::uhd::usrp::multi_usrp::sptr
+usrp_block_impl::get_device(void)
+{
+ return _dev;
+}
+
+/**********************************************************************
+ * External Interfaces
+ *********************************************************************/
+void
+usrp_block_impl::setup_rpc()
+{
+#ifdef GR_CTRLPORT
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_get<usrp_block, double>(
+ alias(), "samp_rate",
+ &usrp_block::get_samp_rate,
+ pmt::mp(100000.0f), pmt::mp(25000000.0f), pmt::mp(1000000.0f),
+ "sps", "Sample Rate", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP))
+ );
+
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_set<usrp_block, double>(
+ alias(), "samp_rate",
+ &usrp_block::set_samp_rate,
+ pmt::mp(100000.0f), pmt::mp(25000000.0f), pmt::mp(1000000.0f),
+ "sps", "Sample Rate",
+ RPC_PRIVLVL_MIN, DISPNULL))
+ );
+#endif /* GR_CTRLPORT */
+}
+
+void usrp_block_impl::msg_handler_command(pmt::pmt_t msg)
+{
+ std::string command;
+ pmt::pmt_t cmd_value;
+ int chan = -1;
+ if (not _unpack_chan_command(command, cmd_value, chan, msg)) {
+ GR_LOG_ALERT(d_logger, boost::format("Error while unpacking command PMT: %s") % msg);
+ return;
+ }
+ GR_LOG_DEBUG(d_debug_logger, boost::format("Received command: %s") % command);
+ try {
+ if (command == "freq") {
+ _chans_to_tune = _update_vector_from_cmd_val<double>(
+ _curr_freq, chan, pmt::to_double(cmd_value), true
+ );
+ _set_center_freq_from_internals_allchans();
+ } else if (command == "lo_offset") {
+ _chans_to_tune = _update_vector_from_cmd_val<double>(
+ _curr_lo_offset, chan, pmt::to_double(cmd_value), true
+ );
+ _set_center_freq_from_internals_allchans();
+ } else if (command == "gain") {
+ boost::dynamic_bitset<> chans_to_change = _update_vector_from_cmd_val<double>(
+ _curr_gain, chan, pmt::to_double(cmd_value), true
+ );
+ if (chans_to_change.any()) {
+ for (size_t i = 0; i < chans_to_change.size(); i++) {
+ if (chans_to_change[i]) {
+ set_gain(_curr_gain[i], i);
+ }
+ }
+ }
+ } else {
+ GR_LOG_ALERT(d_logger, boost::format("Received unknown command: %s") % command);
+ }
+ } catch (pmt::wrong_type &e) {
+ GR_LOG_ALERT(d_logger, boost::format("Received command '%s' with invalid command value: %s") % command % cmd_value);
+ }
+}
diff --git a/gr-uhd/lib/usrp_block_impl.h b/gr-uhd/lib/usrp_block_impl.h
new file mode 100644
index 0000000000..1ca613d1dc
--- /dev/null
+++ b/gr-uhd/lib/usrp_block_impl.h
@@ -0,0 +1,199 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_UHD_BLOCK_IMPL_H
+#define INCLUDED_GR_UHD_BLOCK_IMPL_H
+
+#include <gnuradio/uhd/usrp_block.h>
+#include <pmt/pmt.h>
+#include <uhd/usrp/multi_usrp.hpp>
+#include <boost/dynamic_bitset.hpp>
+
+namespace gr {
+ namespace uhd {
+
+ class usrp_block_impl : virtual public usrp_block
+ {
+ public:
+ typedef boost::function< ::uhd::sensor_value_t (const std::string&)> get_sensor_fn_t;
+
+ static const double LOCK_TIMEOUT;
+
+ /**********************************************************************
+ * Public API calls (see usrp_block.h for docs)
+ **********************************************************************/
+ // Getters
+ ::uhd::sensor_value_t get_mboard_sensor(const std::string &name, size_t mboard);
+ std::vector<std::string> get_mboard_sensor_names(size_t mboard);
+ std::string get_time_source(const size_t mboard);
+ std::vector<std::string> get_time_sources(const size_t mboard);
+ std::string get_clock_source(const size_t mboard);
+ std::vector<std::string> get_clock_sources(const size_t mboard);
+ double get_clock_rate(size_t mboard);
+ ::uhd::time_spec_t get_time_now(size_t mboard = 0);
+ ::uhd::time_spec_t get_time_last_pps(size_t mboard);
+ ::uhd::usrp::multi_usrp::sptr get_device(void);
+
+ // Setters
+ void set_clock_config(const ::uhd::clock_config_t &clock_config, size_t mboard);
+ void set_time_source(const std::string &source, const size_t mboard);
+ void set_clock_source(const std::string &source, const size_t mboard);
+ void set_clock_rate(double rate, size_t mboard);
+ void set_time_now(const ::uhd::time_spec_t &time_spec, size_t mboard);
+ void set_time_next_pps(const ::uhd::time_spec_t &time_spec);
+ void set_time_unknown_pps(const ::uhd::time_spec_t &time_spec);
+ void set_command_time(const ::uhd::time_spec_t &time_spec, size_t mboard);
+ void set_user_register(const uint8_t addr, const uint32_t data, size_t mboard);
+ void clear_command_time(size_t mboard);
+
+ // RPC
+ void setup_rpc();
+
+ /**********************************************************************
+ * Structors
+ * ********************************************************************/
+ virtual ~usrp_block_impl();
+ protected:
+ /*! \brief Components common to USRP sink and source.
+ *
+ * \param device_addr Device address + options
+ * \param stream_args Stream args (cpu format, otw format...)
+ * \param ts_tag_name If this block produces or consumes stream tags, enter the corresponding tag name here
+ */
+ usrp_block_impl(
+ const ::uhd::device_addr_t &device_addr,
+ const ::uhd::stream_args_t &stream_args,
+ const std::string &ts_tag_name
+ );
+
+ /**********************************************************************
+ * Command Interface
+ **********************************************************************/
+ //! Receives commands and handles them
+ void msg_handler_command(pmt::pmt_t msg);
+
+ /**********************************************************************
+ * Helpers
+ **********************************************************************/
+ bool _check_mboard_sensors_locked();
+
+ void _update_stream_args(const ::uhd::stream_args_t &stream_args_);
+
+ /*! \brief Wait until a timeout or a sensor returns 'locked'.
+ *
+ * If a given sensor is not found, this still returns 'true', so we don't throw
+ * errors or warnings if a sensor wasn't implemented.
+ *
+ * \returns true if the sensor locked in time or doesn't exist
+ */
+ bool _wait_for_locked_sensor(
+ std::vector<std::string> sensor_names,
+ const std::string &sensor_name,
+ get_sensor_fn_t get_sensor_fn
+ );
+
+ //! Helper function for msg_handler_command:
+ // - Extracts command and the command value from the command PMT
+ // - Returns true if the command PMT is well formed
+ // - If a channel is given, return that as well, otherwise set the channel to -1
+ static bool _unpack_chan_command(
+ std::string &command,
+ pmt::pmt_t &cmd_val,
+ int &chan,
+ const pmt::pmt_t &cmd_pmt
+ );
+
+ //! Helper function for msg_handler_command:
+ // - Sets a value in vector_to_update to cmd_val, depending on chan
+ // - If chan is a positive integer, it will set vector_to_update[chan]
+ // - If chan is -1, it depends on minus_one_updates_all:
+ // - Either set vector_to_update[0] or
+ // - Set *all* entries in vector_to_update
+ // - Returns a dynamic_bitset, all indexes that where changed in
+ // vector_to_update are set to 1
+ template <typename T>
+ static boost::dynamic_bitset<> _update_vector_from_cmd_val(
+ std::vector<T> &vector_to_update,
+ int chan,
+ const T cmd_val,
+ bool minus_one_updates_all = false
+ ) {
+ boost::dynamic_bitset<> vals_updated(vector_to_update.size());
+ if (chan == -1) {
+ if (minus_one_updates_all) {
+ for (size_t i = 0; i < vector_to_update.size(); i++) {
+ if (vector_to_update[i] != cmd_val) {
+ vals_updated[i] = true;
+ vector_to_update[i] = cmd_val;
+ }
+ }
+ return vals_updated;
+ }
+ chan = 0;
+ }
+ if (vector_to_update[chan] != cmd_val) {
+ vector_to_update[chan] = cmd_val;
+ vals_updated[chan] = true;
+ }
+
+ return vals_updated;
+ }
+
+ //! Like set_center_freq(), but uses _curr_freq and _curr_lo_offset
+ virtual ::uhd::tune_result_t _set_center_freq_from_internals(size_t chan) = 0;
+
+ //! Calls _set_center_freq_from_internals() on all channels
+ void _set_center_freq_from_internals_allchans();
+
+ /**********************************************************************
+ * Members
+ *********************************************************************/
+ //! Shared pointer to the underlying multi_usrp object
+ ::uhd::usrp::multi_usrp::sptr _dev;
+ ::uhd::stream_args_t _stream_args;
+ boost::shared_ptr< ::uhd::io_type_t > _type;
+ //! Number of channels (i.e. number of in- or outputs)
+ size_t _nchan;
+ bool _stream_now;
+ ::uhd::time_spec_t _start_time;
+ bool _start_time_set;
+
+ /****** Command interface related **********/
+ //! Stores a list of commands for later execution
+ std::vector<pmt::pmt_t> _pending_cmds;
+ //! Stores the last value we told the USRP to tune to for every channel
+ // (this is not necessarily the true value the USRP is currently tuned to!).
+ // We could theoretically ask the device, but during streaming, we want to minimize
+ // communication with the USRP.
+ std::vector<double> _curr_freq;
+ //! Stores the last value we told the USRP to have the LO offset for every channel.
+ std::vector<double> _curr_lo_offset;
+ //! Stores the last gain value we told the USRP to have for every channel.
+ std::vector<double> _curr_gain;
+ boost::dynamic_bitset<> _chans_to_tune;
+ };
+
+ } /* namespace uhd */
+} /* namespace gr */
+
+#endif /* INCLUDED_GR_UHD_BLOCK_IMPL_H */
+
diff --git a/gr-uhd/lib/usrp_common.h b/gr-uhd/lib/usrp_common.h
deleted file mode 100644
index 41f443922c..0000000000
--- a/gr-uhd/lib/usrp_common.h
+++ /dev/null
@@ -1,211 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2014 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio 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, or (at your option)
- * any later version.
- *
- * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef INCLUDED_GR_UHD_USRP_COMMON_H
-#define INCLUDED_GR_UHD_USRP_COMMON_H
-
-#include <pmt/pmt.h>
-#include <boost/dynamic_bitset.hpp>
-#include <boost/make_shared.hpp>
-#include <boost/bind.hpp>
-#include <boost/thread.hpp>
-#include <uhd/usrp/multi_usrp.hpp>
-#include <uhd/convert.hpp>
-#include <iostream>
-
-namespace gr {
- namespace uhd {
- typedef boost::function< ::uhd::sensor_value_t (const std::string&)> get_sensor_fn_t;
-
- static const double LOCK_TIMEOUT = 1.5; // s
-
- //! Helper function for msg_handler_command:
- // - Extracts command and the command value from the command PMT
- // - Returns true if the command PMT is well formed
- // - If a channel is given, return that as well, otherwise set the channel to -1
- static bool _unpack_chan_command(
- std::string &command,
- pmt::pmt_t &cmd_val,
- int &chan,
- const pmt::pmt_t &cmd_pmt
- ) {
- try {
- chan = -1; // Default value
- if (pmt::is_tuple(cmd_pmt) and (pmt::length(cmd_pmt) == 2 or pmt::length(cmd_pmt) == 3)) {
- command = pmt::symbol_to_string(pmt::tuple_ref(cmd_pmt, 0));
- cmd_val = pmt::tuple_ref(cmd_pmt, 1);
- if (pmt::length(cmd_pmt) == 3) {
- chan = pmt::to_long(pmt::tuple_ref(cmd_pmt, 2));
- }
- }
- else if (pmt::is_pair(cmd_pmt)) {
- command = pmt::symbol_to_string(pmt::car(cmd_pmt));
- cmd_val = pmt::cdr(cmd_pmt);
- if (pmt::is_pair(cmd_val)) {
- chan = pmt::to_long(pmt::car(cmd_val));
- cmd_val = pmt::cdr(cmd_val);
- }
- }
- else {
- return false;
- }
- } catch (pmt::wrong_type w) {
- return false;
- }
- return true;
- }
-
- //! Helper function for msg_handler_command:
- // - Sets a value in vector_to_update to cmd_val, depending on chan
- // - If chan is a positive integer, it will set vector_to_update[chan]
- // - If chan is -1, it depends on minus_one_updates_all:
- // - Either set vector_to_update[0] or
- // - Set *all* entries in vector_to_update
- // - Returns a dynamic_bitset, all indexes that where changed in
- // vector_to_update are set to 1
- template <typename T>
- static boost::dynamic_bitset<> _update_vector_from_cmd_val(
- std::vector<T> &vector_to_update,
- int chan,
- const T cmd_val,
- bool minus_one_updates_all = false
- ) {
- boost::dynamic_bitset<> vals_updated(vector_to_update.size());
- if (chan == -1) {
- if (minus_one_updates_all) {
- for (size_t i = 0; i < vector_to_update.size(); i++) {
- if (vector_to_update[i] != cmd_val) {
- vals_updated[i] = true;
- vector_to_update[i] = cmd_val;
- }
- }
- return vals_updated;
- }
- chan = 0;
- }
- if (vector_to_update[chan] != cmd_val) {
- vector_to_update[chan] = cmd_val;
- vals_updated[chan] = true;
- }
-
- return vals_updated;
- }
-
-
- /*! \brief Components common to USRP sink and source.
- *
- * \param device_addr Device address + options
- * \param stream_args Stream args (cpu format, otw format...)
- * \param ts_tag_name If this block produces or consumes stream tags, enter the corresponding tag name here
- */
- class usrp_common_impl
- {
- public:
- usrp_common_impl(
- const ::uhd::device_addr_t &device_addr,
- const ::uhd::stream_args_t &stream_args,
- const std::string &ts_tag_name
- ) :
- _stream_args(stream_args),
- _nchan(stream_args.channels.size()),
- _stream_now(_nchan == 1 and ts_tag_name.empty()),
- _start_time_set(false)
- {
- if(stream_args.cpu_format == "fc32")
- _type = boost::make_shared< ::uhd::io_type_t >(::uhd::io_type_t::COMPLEX_FLOAT32);
- if(stream_args.cpu_format == "sc16")
- _type = boost::make_shared< ::uhd::io_type_t >(::uhd::io_type_t::COMPLEX_INT16);
- _dev = ::uhd::usrp::multi_usrp::make(device_addr);
- };
-
- ~usrp_common_impl() {};
-
- protected:
- /*! \brief Wait until a timeout or a sensor returns 'locked'.
- *
- * If a given sensor is not found, this still returns 'true', so we don't throw
- * errors or warnings if a sensor wasn't implemented.
- */
- bool _wait_for_locked_sensor(
- std::vector<std::string> sensor_names,
- const std::string &sensor_name,
- get_sensor_fn_t get_sensor_fn
- ){
- if (std::find(sensor_names.begin(), sensor_names.end(), sensor_name) == sensor_names.end())
- return true;
-
- boost::system_time start = boost::get_system_time();
- boost::system_time first_lock_time;
-
- while (true) {
- if ((not first_lock_time.is_not_a_date_time()) and
- (boost::get_system_time() > (first_lock_time + boost::posix_time::seconds(LOCK_TIMEOUT)))) {
- break;
- }
-
- if (get_sensor_fn(sensor_name).to_bool()) {
- if (first_lock_time.is_not_a_date_time())
- first_lock_time = boost::get_system_time();
- }
- else {
- first_lock_time = boost::system_time(); //reset to 'not a date time'
-
- if (boost::get_system_time() > (start + boost::posix_time::seconds(LOCK_TIMEOUT))){
- return false;
- }
- }
-
- boost::this_thread::sleep(boost::posix_time::milliseconds(100));
- }
-
- return true;
- }
-
- void _update_stream_args(const ::uhd::stream_args_t &stream_args_)
- {
- ::uhd::stream_args_t stream_args(stream_args_);
- if (stream_args.channels.empty()) {
- stream_args.channels = _stream_args.channels;
- }
- if (stream_args.cpu_format != _stream_args.cpu_format ||
- stream_args.channels.size() != _stream_args.channels.size()) {
- throw std::runtime_error("Cannot change I/O signatures while updating stream args!");
- }
- _stream_args = stream_args;
- }
-
- //! Shared pointer to the underlying multi_usrp object
- ::uhd::usrp::multi_usrp::sptr _dev;
- ::uhd::stream_args_t _stream_args;
- boost::shared_ptr< ::uhd::io_type_t > _type;
- //! Number of channels (i.e. number of in- or outputs)
- size_t _nchan;
- bool _stream_now;
- ::uhd::time_spec_t _start_time;
- bool _start_time_set;
- };
-
- } /* namespace uhd */
-} /* namespace gr */
-
-#endif /* INCLUDED_GR_UHD_USRP_COMMON_H */
-
diff --git a/gr-uhd/lib/usrp_sink_impl.cc b/gr-uhd/lib/usrp_sink_impl.cc
index 08896a8bb0..513dfafad7 100644
--- a/gr-uhd/lib/usrp_sink_impl.cc
+++ b/gr-uhd/lib/usrp_sink_impl.cc
@@ -64,53 +64,16 @@ namespace gr {
usrp_sink_impl::usrp_sink_impl(const ::uhd::device_addr_t &device_addr,
const ::uhd::stream_args_t &stream_args,
const std::string &length_tag_name)
- : sync_block("gr uhd usrp sink",
+ : usrp_block("gr uhd usrp sink",
args_to_io_sig(stream_args),
io_signature::make(0, 0, 0)),
- usrp_common_impl(device_addr, stream_args, length_tag_name),
+ usrp_block_impl(device_addr, stream_args, length_tag_name),
_length_tag_key(length_tag_name.empty() ? pmt::PMT_NIL : pmt::string_to_symbol(length_tag_name)),
- _nitems_to_send(0),
- _curr_freq(stream_args.channels.size(), 0.0),
- _curr_lo_offset(stream_args.channels.size(), 0.0),
- _curr_gain(stream_args.channels.size(), 0.0),
- _chans_to_tune(stream_args.channels.size())
+ _nitems_to_send(0)
{
- message_port_register_in(pmt::mp("command"));
- set_msg_handler(
- pmt::mp("command"),
- boost::bind(&usrp_sink_impl::msg_handler_command, this, _1)
- );
-
- _check_sensors_locked();
+ // nop
}
- bool usrp_sink_impl::_check_sensors_locked()
- {
- bool clocks_locked = true;
-
- // Check ref lock for all mboards
- for (size_t mboard_index = 0; mboard_index < _dev->get_num_mboards(); mboard_index++) {
- std::string sensor_name = "ref_locked";
- if (_dev->get_clock_source(mboard_index) == "internal") {
- continue;
- }
- else if (_dev->get_clock_source(mboard_index) == "mimo") {
- sensor_name = "mimo_locked";
- }
- if (not _wait_for_locked_sensor(
- get_mboard_sensor_names(mboard_index),
- sensor_name,
- boost::bind(&usrp_sink_impl::get_mboard_sensor, this, _1, mboard_index)
- )) {
- GR_LOG_WARN(d_logger, boost::format("Sensor '%s' failed to lock within timeout on motherboard %d.") % sensor_name % mboard_index);
- clocks_locked = false;
- }
- }
-
- return clocks_locked;
- }
-
-
usrp_sink_impl::~usrp_sink_impl()
{
}
@@ -184,22 +147,12 @@ namespace gr {
{
_chans_to_tune[chan] = false;
if (_curr_lo_offset[chan] == 0.0) {
- return _dev->set_tx_freq(_curr_freq[chan], _stream_args.channels[chan]);
+ return _dev->set_tx_freq(_curr_freq[chan], _stream_args.channels[chan]);
} else {
- return _dev->set_tx_freq(
- ::uhd::tune_request_t(_curr_freq[chan], _curr_lo_offset[chan]),
- _stream_args.channels[chan]
- );
- }
- }
-
- void
- usrp_sink_impl::_set_center_freq_from_internals_allchans()
- {
- for (size_t chan = 0; chan < _nchan; chan++) {
- if (_chans_to_tune[chan]) {
- _set_center_freq_from_internals(chan);
- }
+ return _dev->set_tx_freq(
+ ::uhd::tune_request_t(_curr_freq[chan], _curr_lo_offset[chan]),
+ _stream_args.channels[chan]
+ );
}
}
@@ -375,152 +328,6 @@ namespace gr {
return _dev->get_tx_sensor_names(chan);
}
- ::uhd::sensor_value_t
- usrp_sink_impl::get_mboard_sensor(const std::string &name,
- size_t mboard)
- {
- return _dev->get_mboard_sensor(name, mboard);
- }
-
- std::vector<std::string>
- usrp_sink_impl::get_mboard_sensor_names(size_t mboard)
- {
- return _dev->get_mboard_sensor_names(mboard);
- }
-
- void
- usrp_sink_impl::set_clock_config(const ::uhd::clock_config_t &clock_config,
- size_t mboard)
- {
- return _dev->set_clock_config(clock_config, mboard);
- }
-
- void
- usrp_sink_impl::set_time_source(const std::string &source,
- const size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
- return _dev->set_time_source(source, mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
- std::string
- usrp_sink_impl::get_time_source(const size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
- return _dev->get_time_source(mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
- std::vector<std::string>
- usrp_sink_impl::get_time_sources(const size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
- return _dev->get_time_sources(mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
- void
- usrp_sink_impl::set_clock_source(const std::string &source,
- const size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
- return _dev->set_clock_source(source, mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
- std::string
- usrp_sink_impl::get_clock_source(const size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
- return _dev->get_clock_source(mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
- std::vector<std::string>
- usrp_sink_impl::get_clock_sources(const size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
- return _dev->get_clock_sources(mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
- double
- usrp_sink_impl::get_clock_rate(size_t mboard)
- {
- return _dev->get_master_clock_rate(mboard);
- }
-
- void
- usrp_sink_impl::set_clock_rate(double rate, size_t mboard)
- {
- return _dev->set_master_clock_rate(rate, mboard);
- }
-
- ::uhd::time_spec_t
- usrp_sink_impl::get_time_now(size_t mboard)
- {
- return _dev->get_time_now(mboard);
- }
-
- ::uhd::time_spec_t
- usrp_sink_impl::get_time_last_pps(size_t mboard)
- {
- return _dev->get_time_last_pps(mboard);
- }
-
- void
- usrp_sink_impl::set_time_now(const ::uhd::time_spec_t &time_spec,
- size_t mboard)
- {
- return _dev->set_time_now(time_spec, mboard);
- }
-
- void
- usrp_sink_impl::set_time_next_pps(const ::uhd::time_spec_t &time_spec)
- {
- return _dev->set_time_next_pps(time_spec);
- }
-
- void
- usrp_sink_impl::set_time_unknown_pps(const ::uhd::time_spec_t &time_spec)
- {
- return _dev->set_time_unknown_pps(time_spec);
- }
-
- void
- usrp_sink_impl::set_command_time(const ::uhd::time_spec_t &time_spec,
- size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_COMMAND_TIME_API
- return _dev->set_command_time(time_spec, mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
- void
- usrp_sink_impl::clear_command_time(size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_COMMAND_TIME_API
- return _dev->clear_command_time(mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
::uhd::usrp::dboard_iface::sptr
usrp_sink_impl::get_dboard_iface(size_t chan)
{
@@ -528,24 +335,6 @@ namespace gr {
return _dev->get_tx_dboard_iface(chan);
}
- ::uhd::usrp::multi_usrp::sptr
- usrp_sink_impl::get_device(void)
- {
- return _dev;
- }
-
- void
- usrp_sink_impl::set_user_register(const uint8_t addr,
- const uint32_t data,
- size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_USER_REGS_API
- _dev->set_user_register(addr, data, mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
void
usrp_sink_impl::set_stream_args(const ::uhd::stream_args_t &stream_args)
{
@@ -843,69 +632,5 @@ namespace gr {
return true;
}
-
- /************** External interfaces (RPC + Message passing) ********************/
- void usrp_sink_impl::msg_handler_command(pmt::pmt_t msg)
- {
- std::string command;
- pmt::pmt_t cmd_value;
- int chan = -1;
- if (not _unpack_chan_command(command, cmd_value, chan, msg)) {
- GR_LOG_ALERT(d_logger, boost::format("Error while unpacking command PMT: %s") % msg);
- return;
- }
- GR_LOG_DEBUG(d_debug_logger, boost::format("Received command: %s") % command);
- try {
- if (command == "freq") {
- _chans_to_tune = _update_vector_from_cmd_val<double>(
- _curr_freq, chan, pmt::to_double(cmd_value), true
- );
- _set_center_freq_from_internals_allchans();
- } else if (command == "lo_offset") {
- _chans_to_tune = _update_vector_from_cmd_val<double>(
- _curr_lo_offset, chan, pmt::to_double(cmd_value), true
- );
- _set_center_freq_from_internals_allchans();
- } else if (command == "gain") {
- boost::dynamic_bitset<> chans_to_change = _update_vector_from_cmd_val<double>(
- _curr_gain, chan, pmt::to_double(cmd_value), true
- );
- if (chans_to_change.any()) {
- for (size_t i = 0; i < chans_to_change.size(); i++) {
- if (chans_to_change[i]) {
- set_gain(_curr_gain[i], i);
- }
- }
- }
- } else {
- GR_LOG_ALERT(d_logger, boost::format("Received unknown command: %s") % command);
- }
- } catch (pmt::wrong_type &e) {
- GR_LOG_ALERT(d_logger, boost::format("Received command '%s' with invalid command value: %s") % command % cmd_value);
- }
- }
-
- void
- usrp_sink_impl::setup_rpc()
- {
-#ifdef GR_CTRLPORT
- add_rpc_variable(
- rpcbasic_sptr(new rpcbasic_register_get<usrp_sink, double>(
- alias(), "samp_rate",
- &usrp_sink::get_samp_rate,
- pmt::mp(100000.0f), pmt::mp(25000000.0f), pmt::mp(1000000.0f),
- "sps", "TX Sample Rate", RPC_PRIVLVL_MIN,
- DISPTIME | DISPOPTSTRIP)));
-
- add_rpc_variable(
- rpcbasic_sptr(new rpcbasic_register_set<usrp_sink, double>(
- alias(), "samp_rate",
- &usrp_sink::set_samp_rate,
- pmt::mp(100000.0f), pmt::mp(25000000.0f), pmt::mp(1000000.0f),
- "sps", "TX Sample Rate",
- RPC_PRIVLVL_MIN, DISPNULL)));
-#endif /* GR_CTRLPORT */
- }
-
} /* namespace uhd */
} /* namespace gr */
diff --git a/gr-uhd/lib/usrp_sink_impl.h b/gr-uhd/lib/usrp_sink_impl.h
index e0cb5a9a60..1575378d21 100644
--- a/gr-uhd/lib/usrp_sink_impl.h
+++ b/gr-uhd/lib/usrp_sink_impl.h
@@ -20,9 +20,9 @@
* Boston, MA 02110-1301, USA.
*/
+#include "usrp_block_impl.h"
#include <gnuradio/uhd/usrp_sink.h>
#include <uhd/convert.hpp>
-#include "usrp_common.h"
static const pmt::pmt_t SOB_KEY = pmt::string_to_symbol("tx_sob");
static const pmt::pmt_t EOB_KEY = pmt::string_to_symbol("tx_eob");
@@ -52,7 +52,7 @@ namespace gr {
/***********************************************************************
* UHD Multi USRP Sink Impl
**********************************************************************/
- class usrp_sink_impl : public usrp_sink, public usrp_common_impl
+ class usrp_sink_impl : public usrp_sink, public usrp_block_impl
{
public:
usrp_sink_impl(const ::uhd::device_addr_t &device_addr,
@@ -60,8 +60,6 @@ namespace gr {
const std::string &length_tag_name);
~usrp_sink_impl();
- void setup_rpc();
-
::uhd::dict<std::string, std::string> get_usrp_info(size_t chan);
double get_samp_rate(void);
::uhd::meta_range_t get_samp_rates(void);
@@ -77,17 +75,7 @@ namespace gr {
std::vector<std::string> get_antennas(size_t chan);
::uhd::sensor_value_t get_sensor(const std::string &name, size_t chan);
std::vector<std::string> get_sensor_names(size_t chan);
- ::uhd::sensor_value_t get_mboard_sensor(const std::string &name, size_t mboard);
- std::vector<std::string> get_mboard_sensor_names(size_t mboard);
- std::string get_time_source(const size_t mboard);
- std::vector<std::string> get_time_sources(const size_t mboard);
- std::string get_clock_source(const size_t mboard);
- std::vector<std::string> get_clock_sources(const size_t mboard);
- double get_clock_rate(size_t mboard);
- ::uhd::time_spec_t get_time_now(size_t mboard = 0);
- ::uhd::time_spec_t get_time_last_pps(size_t mboard);
::uhd::usrp::dboard_iface::sptr get_dboard_iface(size_t chan);
- ::uhd::usrp::multi_usrp::sptr get_device(void);
void set_subdev_spec(const std::string &spec, size_t mboard);
std::string get_subdev_spec(size_t mboard);
@@ -103,16 +91,6 @@ namespace gr {
::uhd::freq_range_t get_bandwidth_range(size_t chan);
void set_dc_offset(const std::complex<double> &offset, size_t chan);
void set_iq_balance(const std::complex<double> &correction, size_t chan);
- void set_clock_config(const ::uhd::clock_config_t &clock_config, size_t mboard);
- void set_time_source(const std::string &source, const size_t mboard);
- void set_clock_source(const std::string &source, const size_t mboard);
- void set_clock_rate(double rate, size_t mboard);
- void set_time_now(const ::uhd::time_spec_t &time_spec, size_t mboard);
- void set_time_next_pps(const ::uhd::time_spec_t &time_spec);
- void set_time_unknown_pps(const ::uhd::time_spec_t &time_spec);
- void set_command_time(const ::uhd::time_spec_t &time_spec, size_t mboard);
- void clear_command_time(size_t mboard);
- void set_user_register(const uint8_t addr, const uint32_t data, size_t mboard);
void set_stream_args(const ::uhd::stream_args_t &stream_args);
void set_start_time(const ::uhd::time_spec_t &time);
@@ -126,14 +104,8 @@ namespace gr {
inline void tag_work(int &ninput_items);
private:
- /*! \brief Run through all 'lock' sensors and make sure they are actually locked.
- */
- bool _check_sensors_locked();
-
//! Like set_center_freq(), but uses _curr_freq and _curr_lo_offset
::uhd::tune_result_t _set_center_freq_from_internals(size_t chan);
- //! Calls _set_center_freq_from_internals() on all channels
- void _set_center_freq_from_internals_allchans();
#ifdef GR_UHD_USE_STREAM_API
::uhd::tx_streamer::sptr _tx_stream;
@@ -141,27 +113,11 @@ namespace gr {
::uhd::tx_metadata_t _metadata;
double _sample_rate;
-
//stream tags related stuff
std::vector<tag_t> _tags;
const pmt::pmt_t _length_tag_key;
long _nitems_to_send;
- /****** Command interface related **********/
- //! Stores a list of commands for later execution
- std::vector<pmt::pmt_t> _pending_cmds;
- //! Receives commands and handles them
- void msg_handler_command(pmt::pmt_t msg);
- //! Stores the last value we told the USRP to tune to for every channel
- // (this is not necessarily the true value the USRP is currently tuned to!).
- // We could theoretically ask the device, but during streaming, we want to minimize
- // communication with the USRP.
- std::vector<double> _curr_freq;
- //! Stores the last value we told the USRP to have the LO offset for every channel.
- std::vector<double> _curr_lo_offset;
- //! Stores the last gain value we told the USRP to have for every channel.
- std::vector<double> _curr_gain;
- boost::dynamic_bitset<> _chans_to_tune;
};
} /* namespace uhd */
diff --git a/gr-uhd/lib/usrp_source_impl.cc b/gr-uhd/lib/usrp_source_impl.cc
index 13457402be..4265535a19 100644
--- a/gr-uhd/lib/usrp_source_impl.cc
+++ b/gr-uhd/lib/usrp_source_impl.cc
@@ -20,10 +20,8 @@
* Boston, MA 02110-1301, USA.
*/
-#include "usrp_common.h"
#include "usrp_source_impl.h"
#include "gr_uhd_common.h"
-#include <gnuradio/io_signature.h>
#include <boost/format.hpp>
#include <boost/thread/thread.hpp>
#include <boost/make_shared.hpp>
@@ -64,49 +62,15 @@ namespace gr {
usrp_source_impl::usrp_source_impl(const ::uhd::device_addr_t &device_addr,
const ::uhd::stream_args_t &stream_args):
- sync_block("gr uhd usrp source",
+ usrp_block("gr uhd usrp source",
io_signature::make(0, 0, 0),
args_to_io_sig(stream_args)),
- usrp_common_impl(device_addr, stream_args, ""),
+ usrp_block_impl(device_addr, stream_args, ""),
_tag_now(false)
{
std::stringstream str;
str << name() << unique_id();
_id = pmt::string_to_symbol(str.str());
-
- message_port_register_in(pmt::mp("command"));
- set_msg_handler(
- pmt::mp("command"),
- boost::bind(&usrp_source_impl::msg_handler_command, this, _1)
- );
-
- _check_sensors_locked();
- }
-
- bool usrp_source_impl::_check_sensors_locked()
- {
- bool clocks_locked = true;
-
- // Check ref lock for all mboards
- for (size_t mboard_index = 0; mboard_index < _dev->get_num_mboards(); mboard_index++) {
- std::string sensor_name = "ref_locked";
- if (_dev->get_clock_source(mboard_index) == "internal") {
- continue;
- }
- else if (_dev->get_clock_source(mboard_index) == "mimo") {
- sensor_name = "mimo_locked";
- }
- if (not _wait_for_locked_sensor(
- get_mboard_sensor_names(mboard_index),
- sensor_name,
- boost::bind(&usrp_source_impl::get_mboard_sensor, this, _1, mboard_index)
- )) {
- GR_LOG_WARN(d_logger, boost::format("Sensor '%s' failed to lock within timeout on motherboard %d.") % sensor_name % mboard_index);
- clocks_locked = false;
- }
- }
-
- return clocks_locked;
}
usrp_source_impl::~usrp_source_impl()
@@ -175,6 +139,20 @@ namespace gr {
return res;
}
+ ::uhd::tune_result_t
+ usrp_source_impl::_set_center_freq_from_internals(size_t chan)
+ {
+ _chans_to_tune[chan] = false;
+ if (_curr_lo_offset[chan] == 0.0) {
+ return _dev->set_rx_freq(_curr_freq[chan], _stream_args.channels[chan]);
+ } else {
+ return _dev->set_rx_freq(
+ ::uhd::tune_request_t(_curr_freq[chan], _curr_lo_offset[chan]),
+ _stream_args.channels[chan]
+ );
+ }
+ }
+
double
usrp_source_impl::get_center_freq(size_t chan)
{
@@ -364,150 +342,6 @@ namespace gr {
return _dev->get_rx_sensor_names(chan);
}
- ::uhd::sensor_value_t
- usrp_source_impl::get_mboard_sensor(const std::string &name, size_t mboard)
- {
- return _dev->get_mboard_sensor(name, mboard);
- }
-
- std::vector<std::string>
- usrp_source_impl::get_mboard_sensor_names(size_t mboard)
- {
- return _dev->get_mboard_sensor_names(mboard);
- }
-
- void
- usrp_source_impl::set_clock_config(const ::uhd::clock_config_t &clock_config,
- size_t mboard)
- {
- return _dev->set_clock_config(clock_config, mboard);
- }
-
- void
- usrp_source_impl::set_time_source(const std::string &source,
- const size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
- return _dev->set_time_source(source, mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
- std::string
- usrp_source_impl::get_time_source(const size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
- return _dev->get_time_source(mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
- std::vector<std::string>
- usrp_source_impl::get_time_sources(const size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
- return _dev->get_time_sources(mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
- void
- usrp_source_impl::set_clock_source(const std::string &source,
- const size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
- return _dev->set_clock_source(source, mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
- std::string
- usrp_source_impl::get_clock_source(const size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
- return _dev->get_clock_source(mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
- std::vector<std::string>
- usrp_source_impl::get_clock_sources(const size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
- return _dev->get_clock_sources(mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
- double
- usrp_source_impl::get_clock_rate(size_t mboard)
- {
- return _dev->get_master_clock_rate(mboard);
- }
-
- void
- usrp_source_impl::set_clock_rate(double rate, size_t mboard)
- {
- return _dev->set_master_clock_rate(rate, mboard);
- }
-
- ::uhd::time_spec_t
- usrp_source_impl::get_time_now(size_t mboard)
- {
- return _dev->get_time_now(mboard);
- }
-
- ::uhd::time_spec_t
- usrp_source_impl::get_time_last_pps(size_t mboard)
- {
- return _dev->get_time_last_pps(mboard);
- }
-
- void
- usrp_source_impl::set_time_now(const ::uhd::time_spec_t &time_spec,
- size_t mboard)
- {
- return _dev->set_time_now(time_spec, mboard);
- }
-
- void
- usrp_source_impl::set_time_next_pps(const ::uhd::time_spec_t &time_spec)
- {
- return _dev->set_time_next_pps(time_spec);
- }
-
- void
- usrp_source_impl::set_time_unknown_pps(const ::uhd::time_spec_t &time_spec)
- {
- return _dev->set_time_unknown_pps(time_spec);
- }
-
- void
- usrp_source_impl::set_command_time(const ::uhd::time_spec_t &time_spec, size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_COMMAND_TIME_API
- return _dev->set_command_time(time_spec, mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
- void
- usrp_source_impl::clear_command_time(size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_COMMAND_TIME_API
- return _dev->clear_command_time(mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
::uhd::usrp::dboard_iface::sptr
usrp_source_impl::get_dboard_iface(size_t chan)
{
@@ -515,24 +349,6 @@ namespace gr {
return _dev->get_rx_dboard_iface(chan);
}
- ::uhd::usrp::multi_usrp::sptr
- usrp_source_impl::get_device(void)
- {
- return _dev;
- }
-
- void
- usrp_source_impl::set_user_register(const uint8_t addr,
- const uint32_t data,
- size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_USER_REGS_API
- _dev->set_user_register(addr, data, mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
void
usrp_source_impl::set_stream_args(const ::uhd::stream_args_t &stream_args)
{
@@ -743,59 +559,5 @@ namespace gr {
return num_samps;
}
-
- /************** External interfaces (RPC + Message passing) ********************/
- void usrp_source_impl::msg_handler_command(pmt::pmt_t msg)
- {
- std::string command;
- pmt::pmt_t cmd_value;
- int chan = -1;
- if (not _unpack_chan_command(command, cmd_value, chan, msg)) {
- GR_LOG_ALERT(d_logger, "Error while unpacking command PMT.");
- }
- if (command == "freq") {
- double freq = pmt::to_double(cmd_value);
- for (size_t i = 0; i < _nchan; i++) {
- if (chan == -1 || chan == int(i)) {
- set_center_freq(freq, i);
- }
- }
- // TODO: implement
- //} else if (command == "lo_offset") {
- //;
- } else if (command == "gain") {
- double gain = pmt::to_double(cmd_value);
- for (size_t i = 0; i < _nchan; i++) {
- if (chan == -1 || chan == int(i)) {
- set_gain(gain, i);
- }
- }
- } else {
- GR_LOG_ALERT(d_logger, boost::format("Received unknown command: %s") % command);
- }
- }
-
- void
- usrp_source_impl::setup_rpc()
- {
-#ifdef GR_CTRLPORT
- add_rpc_variable(
- rpcbasic_sptr(new rpcbasic_register_get<usrp_source, double>(
- alias(), "samp_rate",
- &usrp_source::get_samp_rate,
- pmt::mp(100000.0f), pmt::mp(25000000.0f), pmt::mp(1000000.0f),
- "sps", "RX Sample Rate", RPC_PRIVLVL_MIN,
- DISPTIME | DISPOPTSTRIP)));
-
- add_rpc_variable(
- rpcbasic_sptr(new rpcbasic_register_set<usrp_source, double>(
- alias(), "samp_rate",
- &usrp_source::set_samp_rate,
- pmt::mp(100000.0f), pmt::mp(25000000.0f), pmt::mp(1000000.0f),
- "sps", "RX Sample Rate",
- RPC_PRIVLVL_MIN, DISPNULL)));
-#endif /* GR_CTRLPORT */
- }
-
} /* namespace uhd */
} /* namespace gr */
diff --git a/gr-uhd/lib/usrp_source_impl.h b/gr-uhd/lib/usrp_source_impl.h
index 0cbbe2b16b..9f6fc1a759 100644
--- a/gr-uhd/lib/usrp_source_impl.h
+++ b/gr-uhd/lib/usrp_source_impl.h
@@ -20,10 +20,10 @@
* Boston, MA 02110-1301, USA.
*/
+#include "usrp_block_impl.h"
#include <gnuradio/uhd/usrp_source.h>
#include <uhd/convert.hpp>
#include <boost/thread/mutex.hpp>
-#include "usrp_common.h"
static const pmt::pmt_t TIME_KEY = pmt::string_to_symbol("rx_time");
static const pmt::pmt_t RATE_KEY = pmt::string_to_symbol("rx_rate");
@@ -51,15 +51,13 @@ namespace gr {
/***********************************************************************
* UHD Multi USRP Source Impl
**********************************************************************/
- class usrp_source_impl : public usrp_source, public usrp_common_impl
+ class usrp_source_impl : public usrp_source, public usrp_block_impl
{
public:
usrp_source_impl(const ::uhd::device_addr_t &device_addr,
const ::uhd::stream_args_t &stream_args);
~usrp_source_impl();
- void setup_rpc();
-
// Get Commands
::uhd::dict<std::string, std::string> get_usrp_info(size_t chan);
std::string get_subdev_spec(size_t mboard);
@@ -77,17 +75,7 @@ namespace gr {
std::vector<std::string> get_antennas(size_t chan);
::uhd::sensor_value_t get_sensor(const std::string &name, size_t chan);
std::vector<std::string> get_sensor_names(size_t chan);
- ::uhd::sensor_value_t get_mboard_sensor(const std::string &name, size_t mboard);
- std::vector<std::string> get_mboard_sensor_names(size_t mboard);
- std::string get_time_source(const size_t mboard);
- std::vector<std::string> get_time_sources(const size_t mboard);
- std::string get_clock_source(const size_t mboard);
- std::vector<std::string> get_clock_sources(const size_t mboard);
- double get_clock_rate(size_t mboard);
- ::uhd::time_spec_t get_time_now(size_t mboard = 0);
- ::uhd::time_spec_t get_time_last_pps(size_t mboard);
::uhd::usrp::dboard_iface::sptr get_dboard_iface(size_t chan);
- ::uhd::usrp::multi_usrp::sptr get_device(void);
// Set Commands
void set_subdev_spec(const std::string &spec, size_t mboard);
@@ -105,20 +93,10 @@ namespace gr {
void set_dc_offset(const std::complex<double> &offset, size_t chan);
void set_auto_iq_balance(const bool enable, size_t chan);
void set_iq_balance(const std::complex<double> &correction, size_t chan);
- void set_clock_config(const ::uhd::clock_config_t &clock_config, size_t mboard);
- void set_time_source(const std::string &source, const size_t mboard);
- void set_clock_source(const std::string &source, const size_t mboard);
- void set_clock_rate(double rate, size_t mboard);
- void set_time_now(const ::uhd::time_spec_t &time_spec, size_t mboard);
- void set_time_next_pps(const ::uhd::time_spec_t &time_spec);
- void set_time_unknown_pps(const ::uhd::time_spec_t &time_spec);
- void set_command_time(const ::uhd::time_spec_t &time_spec, size_t mboard);
- void set_user_register(const uint8_t addr, const uint32_t data, size_t mboard);
void set_stream_args(const ::uhd::stream_args_t &stream_args);
void set_start_time(const ::uhd::time_spec_t &time);
void issue_stream_cmd(const ::uhd::stream_cmd_t &cmd);
- void clear_command_time(size_t mboard);
void flush(void);
bool start(void);
bool stop(void);
@@ -129,9 +107,9 @@ namespace gr {
gr_vector_void_star &output_items);
private:
- /*! \brief Run through all 'lock' sensors and make sure they are actually locked.
- */
- bool _check_sensors_locked();
+ //! Like set_center_freq(), but uses _curr_freq and _curr_lo_offset
+ ::uhd::tune_result_t _set_center_freq_from_internals(size_t chan);
+
#ifdef GR_UHD_USE_STREAM_API
::uhd::rx_streamer::sptr _rx_stream;
size_t _samps_per_packet;
@@ -145,21 +123,6 @@ namespace gr {
double _center_freq;
boost::recursive_mutex d_mutex;
-
- /****** Command interface related **********/
- //! Receives commands and handles them
- void msg_handler_command(pmt::pmt_t msg);
- //! Stores the last value we told the USRP to tune to for every channel
- // (this is not necessarily the true value the USRP is currently tuned to!).
- // We could theoretically ask the device, but during streaming, we want to minimize
- // communication with the USRP.
- std::vector<double> _curr_freq;
- //! Stores the last value we told the USRP to have the LO offset for every channel.
- std::vector<double> _curr_lo_offset;
- //! Stores the last gain value we told the USRP to have for every channel.
- std::vector<double> _curr_gain;
- boost::dynamic_bitset<> _chans_to_tune;
- bool _call_tune;
};
} /* namespace uhd */