diff options
author | Martin Braun <martin.braun@ettus.com> | 2014-07-04 23:00:08 +0200 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2014-07-07 23:12:09 +0200 |
commit | 691bdaafd602ca24d67fc68ac3e797ea55da48f6 (patch) | |
tree | 8b041cd66d35a2926741c215146f4f54fbbccd5d /gr-uhd | |
parent | 3c42e7952dc9e5dbaf3b43cab37f13cce72dd0bf (diff) |
uhd: Added more type checking and flexibility to commands and tags
Diffstat (limited to 'gr-uhd')
-rwxr-xr-x | gr-uhd/examples/python/freq_hopping.py | 4 | ||||
-rw-r--r-- | gr-uhd/lib/usrp_common.h | 47 | ||||
-rw-r--r-- | gr-uhd/lib/usrp_sink_impl.cc | 141 | ||||
-rw-r--r-- | gr-uhd/lib/usrp_sink_impl.h | 3 |
4 files changed, 107 insertions, 88 deletions
diff --git a/gr-uhd/examples/python/freq_hopping.py b/gr-uhd/examples/python/freq_hopping.py index ba1704309b..5da5efa241 100755 --- a/gr-uhd/examples/python/freq_hopping.py +++ b/gr-uhd/examples/python/freq_hopping.py @@ -105,7 +105,9 @@ class FrequencyHopperSrc(gr.hier_block2): gain_tag.key = pmt.string_to_symbol('tx_command') gain_tag.value = pmt.cons( pmt.intern("gain"), - pmt.to_pmt((0, tx_gain)) + # These are both valid: + #pmt.from_double(tx_gain) + pmt.cons(pmt.to_pmt(0), pmt.to_pmt(tx_gain)) ) tag_list = [gain_tag,] for i in xrange(n_bursts): diff --git a/gr-uhd/lib/usrp_common.h b/gr-uhd/lib/usrp_common.h index f7fead4f5c..732bcef63c 100644 --- a/gr-uhd/lib/usrp_common.h +++ b/gr-uhd/lib/usrp_common.h @@ -28,6 +28,7 @@ #include <boost/make_shared.hpp> #include <uhd/usrp/multi_usrp.hpp> #include <uhd/convert.hpp> +#include <iostream> namespace gr { namespace uhd { @@ -35,27 +36,35 @@ namespace gr { //! 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 return -1 + // - 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 + std::string &command, + pmt::pmt_t &cmd_val, + int &chan, + const pmt::pmt_t &cmd_pmt ) { - 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, 1)); - } - } - else if (pmt::is_pair(cmd_pmt)) { - command = pmt::symbol_to_string(pmt::car(cmd_pmt)); - cmd_val = pmt::car(cmd_pmt); - } - else { - return false; + 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; } diff --git a/gr-uhd/lib/usrp_sink_impl.cc b/gr-uhd/lib/usrp_sink_impl.cc index 42b900e00b..ad96bcb216 100644 --- a/gr-uhd/lib/usrp_sink_impl.cc +++ b/gr-uhd/lib/usrp_sink_impl.cc @@ -555,8 +555,12 @@ namespace gr { _metadata.time_spec += ::uhd::time_spec_t(0, num_sent, _sample_rate); // Some post-processing tasks if we actually transmitted the entire burst - if (_chans_to_tune.any() and num_sent == size_t(ninput_items)) { - _set_center_freq_from_internals_allchans(); + if (not _pending_cmds.empty() and num_sent == size_t(ninput_items)) { + GR_LOG_DEBUG(d_debug_logger, boost::format("Executing %d pending commands.") % _pending_cmds.size()); + BOOST_FOREACH(const pmt::pmt_t &cmd_pmt, _pending_cmds) { + msg_handler_command(cmd_pmt); + } + _pending_cmds.clear(); } return num_sent; @@ -578,10 +582,9 @@ namespace gr { // Go through tag list until something indicates the end of a burst. bool found_time_tag = false; bool found_eob = false; - bool found_freq_tag_in_burst = false; - uint64_t freq_cmd_offset = 0; - double freq_cmd_freq; - int freq_cmd_chan; + // For commands that are in the middle in the burst: + std::vector<pmt::pmt_t> commands_in_burst; // Store the command + uint64_t in_burst_cmd_offset = 0; // Store its position BOOST_FOREACH(const tag_t &my_tag, _tags) { const uint64_t my_tag_count = my_tag.offset; const pmt::pmt_t &key = my_tag.key; @@ -590,11 +593,11 @@ namespace gr { if (my_tag_count >= max_count) { break; } - else if (not pmt::is_null(_length_tag_key) and my_tag_count > samp0_count + _nitems_to_send) { + else if (not pmt::is_null(_length_tag_key) and my_tag_count > samp0_count + _nitems_to_send) { break; - } + } - /* I. Bursts that can only be on the first sample of burst + /* I. Tags that can only be on the first sample of a burst * * This includes: * - tx_time @@ -619,7 +622,7 @@ namespace gr { max_count = my_tag_count; break; } - found_time_tag = true; + found_time_tag = true; _metadata.has_time_spec = true; _metadata.time_spec = ::uhd::time_spec_t (pmt::to_uint64(pmt::tuple_ref(value, 0)), @@ -632,8 +635,8 @@ namespace gr { max_count = my_tag_count; break; } - // Bursty tx will not use time specs, unless a tx_time tag is also given. - _metadata.has_time_spec = false; + // Bursty tx will not use time specs, unless a tx_time tag is also given. + _metadata.has_time_spec = false; _metadata.start_of_burst = pmt::to_bool(value); } @@ -641,49 +644,41 @@ namespace gr { else if(not pmt::is_null(_length_tag_key) and pmt::equal(key, _length_tag_key)) { if (my_tag_count != samp0_count) { max_count = my_tag_count; - break; + break; } //If there are still items left to send, the current burst has been preempted. //Set the items remaining counter to the new burst length. Notify the user of //the tag preemption. - else if(_nitems_to_send > 0) { + else if(_nitems_to_send > 0) { std::cerr << "tP" << std::flush; } _nitems_to_send = pmt::to_long(value); _metadata.start_of_burst = true; } - /* II. Bursts that can be on the first OR last sample of a burst + /* II. Tags that can be on the first OR last sample of a burst * * This includes: - * - tx_freq (tags that don't actually change the frequency are ignored) + * - tx_freq * * With these tags, we check if they're at the start of a burst, and do * the appropriate action. Otherwise, make sure the corresponding sample * is the last one. */ - else if (pmt::equal(key, FREQ_KEY) and my_tag_count == samp0_count) { - int chan = pmt::to_long(pmt::tuple_ref(value, 0)); - double new_freq = pmt::to_double(pmt::tuple_ref(value, 1)); - if (new_freq != _curr_freq[chan]) { - _curr_freq[chan] = new_freq; - _set_center_freq_from_internals(chan); - } - } - - else if(pmt::equal(key, FREQ_KEY) and not found_freq_tag_in_burst) { - int chan = pmt::to_long(pmt::tuple_ref(value, 0)); - double new_freq = pmt::to_double(pmt::tuple_ref(value, 1)); - if (new_freq != _curr_freq[chan]) { - freq_cmd_freq = new_freq; - freq_cmd_chan = chan; - freq_cmd_offset = my_tag_count; - max_count = my_tag_count + 1; - found_freq_tag_in_burst = true; - } + else if (pmt::equal(key, FREQ_KEY) and my_tag_count == samp0_count) { + // If it's on the first sample, immediately do the tune: + GR_LOG_DEBUG(d_debug_logger, boost::format("Received tx_freq on start of burst.")); + msg_handler_command(pmt::cons(pmt::mp("freq"), value)); + } + else if(pmt::equal(key, FREQ_KEY)) { + // If it's not on the first sample, queue this command and only tx until here: + GR_LOG_DEBUG(d_debug_logger, boost::format("Received tx_freq mid-burst.")); + commands_in_burst.push_back(pmt::cons(pmt::mp("freq"), value)); + max_count = my_tag_count + 1; + in_burst_cmd_offset = my_tag_count; } - /* III. Bursts that can only be on the last sample of a burst + /* III. Tags that can only be on the last sample of a burst * * This includes: * - tx_eob @@ -701,19 +696,25 @@ namespace gr { found_eob = true; } - if (found_freq_tag_in_burst) { + // If a command was found in-burst that may appear at the end of burst, + // there's two options: + // 1) The command was actually on the last sample (eob). Then, stash the + // commands for running after work(). + // 2) The command was not on the last sample. In this case, only send() + // until before the tag, so it will be on the first sample of the next run. + if (not commands_in_burst.empty()) { if (not found_eob) { // If it's in the middle of a burst, only send() until before the tag - max_count = freq_cmd_offset; - } else if (freq_cmd_offset < max_count) { - // Otherwise, tune after work() - _curr_freq[freq_cmd_chan] = freq_cmd_freq; - _chans_to_tune[freq_cmd_chan] = true; + max_count = in_burst_cmd_offset; + } else if (in_burst_cmd_offset < max_count) { + BOOST_FOREACH(const pmt::pmt_t &cmd_pmt, commands_in_burst) { + _pending_cmds.push_back(cmd_pmt); + } } } if (found_time_tag) { - _metadata.has_time_spec = true; + _metadata.has_time_spec = true; } // Only transmit up to and including end of burst, @@ -791,31 +792,37 @@ namespace gr { 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."); + GR_LOG_ALERT(d_logger, boost::format("Error while unpacking command PMT: %s") % msg); + return; } - 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); + 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_sink_impl.h b/gr-uhd/lib/usrp_sink_impl.h index 92afb69640..8848fe0712 100644 --- a/gr-uhd/lib/usrp_sink_impl.h +++ b/gr-uhd/lib/usrp_sink_impl.h @@ -141,6 +141,8 @@ namespace gr { 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 @@ -153,7 +155,6 @@ namespace gr { //! 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 */ |