diff options
author | Martin Braun <martin.braun@ettus.com> | 2014-07-07 18:06:20 +0200 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2014-07-08 12:10:22 +0200 |
commit | 12523cdb3218be85565c3c3bcb49d113e6bac518 (patch) | |
tree | 94960d3ed62cf265d6c1966a3a9a628f449af4f4 /gr-uhd | |
parent | af0a33196d7a39d27df7f1810f395e6f64cf43b6 (diff) |
uhd: Added checks for lock sensors.
When operating with an external ref, in MIMO mode or with a GPSDO,
the constructor now waits until the lock sensors report succesful
locking.
If this fails, a warning is displayed using the logger interface,
to keep backward compatibility.
Diffstat (limited to 'gr-uhd')
-rw-r--r-- | gr-uhd/lib/usrp_common.h | 50 | ||||
-rw-r--r-- | gr-uhd/lib/usrp_sink_impl.cc | 42 | ||||
-rw-r--r-- | gr-uhd/lib/usrp_sink_impl.h | 4 | ||||
-rw-r--r-- | gr-uhd/lib/usrp_source_impl.cc | 41 | ||||
-rw-r--r-- | gr-uhd/lib/usrp_source_impl.h | 3 |
5 files changed, 139 insertions, 1 deletions
diff --git a/gr-uhd/lib/usrp_common.h b/gr-uhd/lib/usrp_common.h index 732bcef63c..29caa585cf 100644 --- a/gr-uhd/lib/usrp_common.h +++ b/gr-uhd/lib/usrp_common.h @@ -26,12 +26,17 @@ #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 @@ -105,8 +110,12 @@ namespace gr { 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 { @@ -130,8 +139,47 @@ namespace gr { ~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; + } + //! Shared pointer to the underlying multi_usrp object ::uhd::usrp::multi_usrp::sptr _dev; const ::uhd::stream_args_t _stream_args; diff --git a/gr-uhd/lib/usrp_sink_impl.cc b/gr-uhd/lib/usrp_sink_impl.cc index ad96bcb216..cdbe7b58f4 100644 --- a/gr-uhd/lib/usrp_sink_impl.cc +++ b/gr-uhd/lib/usrp_sink_impl.cc @@ -80,8 +80,50 @@ namespace gr { pmt::mp("command"), boost::bind(&usrp_sink_impl::msg_handler_command, this, _1) ); + + _check_sensors_locked(); + } + + bool usrp_sink_impl::_check_sensors_locked() + { + bool clocks_locked = true; + + // 1) 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; + } + } + + // 2) Check LO for all channels + for (size_t i = 0; i < _nchan; i++) { + size_t chan_index = _stream_args.channels[i]; + if (not _wait_for_locked_sensor( + get_sensor_names(chan_index), + "lo_locked", + boost::bind(&usrp_sink_impl::get_sensor, this, _1, chan_index) + )) { + GR_LOG_WARN(d_logger, boost::format("Sensor 'lo_locked' failed to lock within timeout on channel %d.") % chan_index); + clocks_locked = false; + } + } + + return clocks_locked; } + usrp_sink_impl::~usrp_sink_impl() { } diff --git a/gr-uhd/lib/usrp_sink_impl.h b/gr-uhd/lib/usrp_sink_impl.h index 8848fe0712..21bb991b92 100644 --- a/gr-uhd/lib/usrp_sink_impl.h +++ b/gr-uhd/lib/usrp_sink_impl.h @@ -123,6 +123,10 @@ 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 diff --git a/gr-uhd/lib/usrp_source_impl.cc b/gr-uhd/lib/usrp_source_impl.cc index b85b45b16b..53038bf202 100644 --- a/gr-uhd/lib/usrp_source_impl.cc +++ b/gr-uhd/lib/usrp_source_impl.cc @@ -79,6 +79,47 @@ namespace gr { 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; + + // 1) 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; + } + } + + // 2) Check LO for all channels + for (size_t i = 0; i < _nchan; i++) { + size_t chan_index = _stream_args.channels[i]; + if (not _wait_for_locked_sensor( + get_sensor_names(chan_index), + "lo_locked", + boost::bind(&usrp_source_impl::get_sensor, this, _1, chan_index) + )) { + GR_LOG_WARN(d_logger, boost::format("Sensor 'lo_locked' failed to lock within timeout on channel %d.") % chan_index); + clocks_locked = false; + } + } + + return clocks_locked; } usrp_source_impl::~usrp_source_impl() diff --git a/gr-uhd/lib/usrp_source_impl.h b/gr-uhd/lib/usrp_source_impl.h index faceb5a177..6de4c9c6a3 100644 --- a/gr-uhd/lib/usrp_source_impl.h +++ b/gr-uhd/lib/usrp_source_impl.h @@ -125,6 +125,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(); #ifdef GR_UHD_USE_STREAM_API ::uhd::rx_streamer::sptr _rx_stream; size_t _samps_per_packet; |