diff options
author | Derek Kozel <derek.kozel@ettus.com> | 2016-10-25 17:26:25 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2016-10-26 17:20:00 -0700 |
commit | 59aaf137b8c86028c0686258837acc7f37eb9461 (patch) | |
tree | 22dbde74e14cfda3f76041089c5f400edf3f1fcb /host | |
parent | b4d92a97b014b1de26ff658ddeb3f636d8e1ca81 (diff) | |
download | uhd-59aaf137b8c86028c0686258837acc7f37eb9461.tar.gz uhd-59aaf137b8c86028c0686258837acc7f37eb9461.tar.bz2 uhd-59aaf137b8c86028c0686258837acc7f37eb9461.zip |
TwinRX: Use command time to schedule synchronous events
Diffstat (limited to 'host')
-rw-r--r-- | host/lib/usrp/dboard/db_twinrx.cpp | 6 | ||||
-rw-r--r-- | host/lib/usrp/dboard/twinrx/twinrx_experts.cpp | 24 | ||||
-rw-r--r-- | host/lib/usrp/dboard/twinrx/twinrx_experts.hpp | 39 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_radio_ctrl_impl.cpp | 39 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_radio_ctrl_impl.hpp | 2 |
5 files changed, 104 insertions, 6 deletions
diff --git a/host/lib/usrp/dboard/db_twinrx.cpp b/host/lib/usrp/dboard/db_twinrx.cpp index e960f134f..477412de0 100644 --- a/host/lib/usrp/dboard/db_twinrx.cpp +++ b/host/lib/usrp/dboard/db_twinrx.cpp @@ -75,6 +75,11 @@ public: get_rx_subtree()->create<meta_range_t>("bandwidth/range") .set(freq_range_t(BW, BW)); + // Command Time + expert_factory::add_data_node<time_spec_t>(_expert, prepend_ch("time/rx_frontend", _ch_name), time_spec_t(0.0)); + expert_factory::add_prop_node<time_spec_t>(_expert, get_rx_subtree(), + "time/cmd", prepend_ch("time/cmd", _ch_name), time_spec_t(0.0)); + //Frequency Specific get_rx_subtree()->create<meta_range_t>("freq/range") .set(freq_range_t(10e6, 6.0e9)); @@ -263,6 +268,7 @@ public: expert_factory::add_worker_node<twinrx_freq_path_expert>(_expert, _expert->node_retriever(), fe); expert_factory::add_worker_node<twinrx_freq_coercion_expert>(_expert, _expert->node_retriever(), fe); expert_factory::add_worker_node<twinrx_chan_gain_expert>(_expert, _expert->node_retriever(), fe); + expert_factory::add_worker_node<twinrx_scheduling_expert>(_expert, _expert->node_retriever(), fe); expert_factory::add_worker_node<twinrx_nyquist_expert>(_expert, _expert->node_retriever(), fe, _db_iface); } diff --git a/host/lib/usrp/dboard/twinrx/twinrx_experts.cpp b/host/lib/usrp/dboard/twinrx/twinrx_experts.cpp index ddaa4211e..f0f64c7e1 100644 --- a/host/lib/usrp/dboard/twinrx/twinrx_experts.cpp +++ b/host/lib/usrp/dboard/twinrx/twinrx_experts.cpp @@ -30,6 +30,17 @@ using namespace uhd::math; using namespace uhd::usrp::dboard::twinrx; /*!--------------------------------------------------------- + * twinrx_scheduling_expert::resolve + * --------------------------------------------------------- + */ +void twinrx_scheduling_expert::resolve() +{ + // Currently a straight pass-through. To be expanded as needed + // when more advanced scheduling is needed + _rx_frontend_time = _command_time; +} + +/*!--------------------------------------------------------- * twinrx_freq_path_expert::resolve * --------------------------------------------------------- */ @@ -222,6 +233,19 @@ void twinrx_freq_coercion_expert::resolve() */ void twinrx_nyquist_expert::resolve() { + // Do not execute when clear_command_time is called. + // This is a transition of the command time from non-zero to zero. + if (_rx_frontend_time == time_spec_t(0.0) and _cached_cmd_time != time_spec_t(0.0)) { + _cached_cmd_time = _rx_frontend_time; + return; + } + + // Do not execute twice for the same command time unless untimed + if (_rx_frontend_time == _cached_cmd_time and _rx_frontend_time != time_spec_t(0.0)) { + return; + } + _cached_cmd_time = _rx_frontend_time; + double if_freq_sign = 1.0; if (_lo1_inj_side == INJ_HIGH_SIDE) if_freq_sign *= -1.0; if (_lo2_inj_side == INJ_HIGH_SIDE) if_freq_sign *= -1.0; diff --git a/host/lib/usrp/dboard/twinrx/twinrx_experts.hpp b/host/lib/usrp/dboard/twinrx/twinrx_experts.hpp index 1617c9c80..9c83dbfa8 100644 --- a/host/lib/usrp/dboard/twinrx/twinrx_experts.hpp +++ b/host/lib/usrp/dboard/twinrx/twinrx_experts.hpp @@ -52,6 +52,38 @@ static const std::string lo_stage_str(lo_stage_t stage, bool lower = false) { return prefix + ((stage == STAGE_LO1) ? "1" : "2"); } + +/*!--------------------------------------------------------- + * twinrx_scheduling_expert + * + * This expert is responsible for scheduling time sensitive actions + * in other experts. It responds to changes in the command time and + * selectively causes experts to run in order to ensure a synchronized + * system. + * + * --------------------------------------------------------- + */ +class twinrx_scheduling_expert : public experts::worker_node_t { +public: + twinrx_scheduling_expert(const experts::node_retriever_t& db, std::string ch) + : experts::worker_node_t(prepend_ch("twinrx_scheduling_expert", ch)), + _command_time (db, prepend_ch("time/cmd", ch)), + _rx_frontend_time (db, prepend_ch("time/rx_frontend", ch)) + { + bind_accessor(_command_time); + bind_accessor(_rx_frontend_time); + } + +private: + virtual void resolve(); + + //Inputs + experts::data_reader_t<time_spec_t> _command_time; + + //Outputs + experts::data_writer_t<time_spec_t> _rx_frontend_time; +}; + /*!--------------------------------------------------------- * twinrx_freq_path_expert * @@ -271,6 +303,7 @@ public: _if_freq_d (db, prepend_ch("if_freq/desired", ch)), _lo1_inj_side (db, prepend_ch("ch/LO1/inj_side", ch)), _lo2_inj_side (db, prepend_ch("ch/LO2/inj_side", ch)), + _rx_frontend_time (db, prepend_ch("time/rx_frontend", ch)), _if_freq_c (db, prepend_ch("if_freq/coerced", ch)), _db_iface (db_iface) { @@ -280,6 +313,7 @@ public: bind_accessor(_lo1_inj_side); bind_accessor(_lo2_inj_side); bind_accessor(_if_freq_c); + bind_accessor(_rx_frontend_time); } private: @@ -293,9 +327,14 @@ private: experts::data_reader_t<double> _if_freq_d; experts::data_reader_t<lo_inj_side_t> _lo1_inj_side; experts::data_reader_t<lo_inj_side_t> _lo2_inj_side; + experts::data_reader_t<time_spec_t> _rx_frontend_time; + //Outputs experts::data_writer_t<double> _if_freq_c; dboard_iface::sptr _db_iface; + + //Misc + time_spec_t _cached_cmd_time; }; /*!--------------------------------------------------------- diff --git a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp index f14ea3fd9..991b97696 100644 --- a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp +++ b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp @@ -120,6 +120,15 @@ UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(x300_radio_ctrl) _tx_fe_map[i].core->set_dc_offset(tx_frontend_core_200::DEFAULT_DC_OFFSET_VALUE); _tx_fe_map[i].core->set_iq_balance(tx_frontend_core_200::DEFAULT_IQ_BALANCE_VALUE); _tx_fe_map[i].core->populate_subtree(_tree->subtree(_root_path / "tx_fe_corrections" / i)); + + //////////////////////////////////////////////////////////////// + // Bind the daughterboard command time to the motherboard level property + //////////////////////////////////////////////////////////////// + + if (_tree->exists(fs_path("time") / "cmd")) { + _tree->access<time_spec_t>(fs_path("time") / "cmd") + .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::set_fe_cmd_time, this, _1, i)); + } } //////////////////////////////////////////////////////////////// @@ -163,6 +172,13 @@ double x300_radio_ctrl_impl::set_rate(double /* rate */) return get_rate(); } +time_spec_t x300_radio_ctrl_impl::set_fe_cmd_time(const time_spec_t &time, const size_t chan) +{ + return _tree->access<time_spec_t>( + fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "time" / "cmd") + ).set(time).get(); +} + void x300_radio_ctrl_impl::set_tx_antenna(const std::string &ant, const size_t chan) { _tree->access<std::string>( @@ -399,14 +415,25 @@ void x300_radio_ctrl_impl::setup_radio( //bind frontend corrections to the dboard freq props const fs_path db_tx_fe_path = db_path / "tx_frontends"; - BOOST_FOREACH(const std::string &name, _tree->list(db_tx_fe_path)) { - _tree->access<double>(db_tx_fe_path / name / "freq" / "value") - .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::set_tx_fe_corrections, this, db_path, _root_path / "tx_fe_corrections" / name, _1)); + if (not _tx_fe_map.empty()) { + for (size_t i = 0; i < _get_num_radios(); i++) { + if (_tree->exists(db_tx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value")) { + _tree->access<double>(db_tx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value") + .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::set_tx_fe_corrections, this, db_path, + _root_path / "tx_fe_corrections" / _tx_fe_map[i].db_fe_name, _1)); + } + } } const fs_path db_rx_fe_path = db_path / "rx_frontends"; - BOOST_FOREACH(const std::string &name, _tree->list(db_rx_fe_path)) { - _tree->access<double>(db_rx_fe_path / name / "freq" / "value") - .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::set_rx_fe_corrections, this, db_path, _root_path / "rx_fe_corrections" / name,_1)); + if (not _rx_fe_map.empty()) { + for (size_t i = 0; i < _get_num_radios(); i++) { + if (_tree->exists(db_rx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value")) { + _tree->access<double>(db_rx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value") + .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::set_rx_fe_corrections, this, db_path, + _root_path / "rx_fe_corrections" / _tx_fe_map[i].db_fe_name, + _1)); + } + } } //////////////////////////////////////////////////////////////// diff --git a/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp b/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp index 65d4443eb..5b9d47841 100644 --- a/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp +++ b/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp @@ -161,6 +161,8 @@ private: void set_rx_fe_corrections(const uhd::fs_path &db_path, const uhd::fs_path &rx_fe_corr_path, const double lo_freq); void set_tx_fe_corrections(const uhd::fs_path &db_path, const uhd::fs_path &tx_fe_corr_path, const double lo_freq); + time_spec_t set_fe_cmd_time(const time_spec_t &time, const size_t chan); + private: // members enum radio_connection_t { PRIMARY, SECONDARY }; |