commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] [gnuradio] 07/11: uhd: Added retune-by-tag and a comma


From: git
Subject: [Commit-gnuradio] [gnuradio] 07/11: uhd: Added retune-by-tag and a command interface via message passing
Date: Sat, 26 Apr 2014 22:34:12 +0000 (UTC)

This is an automated email from the git hooks/post-receive script.

jcorgan pushed a commit to branch master
in repository gnuradio.

commit fe815bdd4f79c0159ebee0361d0d7e15e7b920aa
Author: Martin Braun <address@hidden>
Date:   Fri Apr 4 17:56:25 2014 +0200

    uhd: Added retune-by-tag and a command interface via message passing
---
 gr-uhd/include/gnuradio/uhd/usrp_sink.h |  10 ++-
 gr-uhd/lib/usrp_sink_impl.cc            | 117 +++++++++++++++++++++++++++++++-
 gr-uhd/lib/usrp_sink_impl.h             |  19 ++++++
 3 files changed, 142 insertions(+), 4 deletions(-)

diff --git a/gr-uhd/include/gnuradio/uhd/usrp_sink.h 
b/gr-uhd/include/gnuradio/uhd/usrp_sink.h
index c57524e..cac3e01 100644
--- a/gr-uhd/include/gnuradio/uhd/usrp_sink.h
+++ b/gr-uhd/include/gnuradio/uhd/usrp_sink.h
@@ -72,6 +72,7 @@ namespace gr {
        *  - pmt::string_to_symbol("tx_sob")
        *  - pmt::string_to_symbol("tx_eob")
        *  - pmt::string_to_symbol("tx_time")
+       *  - pmt::string_to_symbol("tx_freq")
        *  - pmt::string_to_symbol(length_tag_name)
        *
        * The sob and eob (start and end of burst) tag values are pmt booleans.
@@ -86,10 +87,13 @@ namespace gr {
        * The timstamp tag value is a pmt tuple of the following:
        * (uint64 seconds, and double fractional seconds).
        *
+       * The tx_freq tag has to be a double, and will re-tune the USRP to the 
given frequency,
+       * if possible.
+       *
        * See the UHD manual for more detailed documentation:
        * http://code.ettus.com/redmine/ettus/projects/uhd/wiki
        *
-       * \param device_addr the address to identify the hardware
+       * \param device_addr the address to identify the hardware (e.g. 
"type=b200", "addr=192.168.10.2")
        * \param io_type the desired input data type
        * \param num_channels number of stream from the device
        * \param length_tag_name the name of the tag identifying tagged stream 
length
@@ -112,6 +116,7 @@ namespace gr {
        *  - pmt::string_to_symbol("tx_sob")
        *  - pmt::string_to_symbol("tx_eob")
        *  - pmt::string_to_symbol("tx_time")
+       *  - pmt::string_to_symbol("tx_freq")
        *  - pmt::string_to_symbol(length_tag_name)
        *
        * The sob and eob (start and end of burst) tag values are pmt booleans.
@@ -126,6 +131,9 @@ namespace gr {
        * The timstamp tag value is a pmt tuple of the following:
        * (uint64 seconds, and double fractional seconds).
        *
+       * The tx_freq tag has to be a double, and will re-tune the USRP to the 
given frequency,
+       * if possible.
+       *
        * See the UHD manual for more detailed documentation:
        * http://code.ettus.com/redmine/ettus/projects/uhd/wiki
        *
diff --git a/gr-uhd/lib/usrp_sink_impl.cc b/gr-uhd/lib/usrp_sink_impl.cc
index 413952a..f55d1f5 100644
--- a/gr-uhd/lib/usrp_sink_impl.cc
+++ b/gr-uhd/lib/usrp_sink_impl.cc
@@ -71,13 +71,27 @@ namespace gr {
         _stream_now(_nchan == 1),
         _start_time_set(false),
         _length_tag_key(length_tag_name.empty() ? pmt::PMT_NIL : 
pmt::string_to_symbol(length_tag_name)),
-        _nitems_to_send(0)
+        _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)
     {
       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);
+
+      message_port_register_in(pmt::mp("command"));
+      set_msg_handler(
+         pmt::mp("command"),
+         boost::bind(&usrp_sink_impl::msg_handler_command, this, _1)
+      );
+      message_port_register_in(pmt::mp("query"));
+      set_msg_handler(
+         pmt::mp("query"),
+         boost::bind(&usrp_sink_impl::msg_handler_query, this, _1)
+      );
     }
 
     usrp_sink_impl::~usrp_sink_impl()
@@ -138,10 +152,29 @@ namespace gr {
     usrp_sink_impl::set_center_freq(const ::uhd::tune_request_t tune_request,
                                     size_t chan)
     {
+      _curr_freq[chan] = tune_request.target_freq;
+      if (tune_request.rf_freq_policy == ::uhd::tune_request_t::POLICY_MANUAL) 
{
+        _curr_lo_offset[chan] = tune_request.rf_freq - 
tune_request.target_freq;
+      } else {
+        _curr_lo_offset[chan] = 0.0;
+      }
       chan = _stream_args.channels[chan];
       return _dev->set_tx_freq(tune_request, chan);
     }
 
+    ::uhd::tune_result_t
+    usrp_sink_impl::_set_center_freq_from_internals(size_t chan)
+    {
+      if (_curr_lo_offset[chan] == 0.0) {
+       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]
+       );
+      }
+    }
+
     double
     usrp_sink_impl::get_center_freq(size_t chan)
     {
@@ -159,6 +192,7 @@ namespace gr {
     void
     usrp_sink_impl::set_gain(double gain, size_t chan)
     {
+      _curr_gain[chan] = gain;
       chan = _stream_args.channels[chan];
       return _dev->set_tx_gain(gain, chan);
     }
@@ -168,6 +202,7 @@ namespace gr {
                              const std::string &name,
                              size_t chan)
     {
+      _curr_gain[chan] = gain;
       chan = _stream_args.channels[chan];
       return _dev->set_tx_gain(gain, name, chan);
     }
@@ -546,6 +581,8 @@ namespace gr {
       //time will not be set unless a time tag is found
       _metadata.has_time_spec = false;
 
+      bool call_tune_loop = false;
+      std::vector<bool> do_tune(_nchan, false);
       //process all of the tags found with the same count as tag0
       BOOST_FOREACH(const tag_t &my_tag, _tags) {
         const uint64_t my_tag_count = my_tag.offset;
@@ -590,8 +627,38 @@ namespace gr {
             (pmt::to_uint64(pmt::tuple_ref(value, 0)),
              pmt::to_double(pmt::tuple_ref(value, 1)));
         }
-      }
-    }
+
+        //set the new tx frequency
+        else if(pmt::equal(key, FREQ_KEY)) {
+          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]) {
+            call_tune_loop = true;
+            do_tune[chan] = true;
+            _curr_freq[chan] = new_freq;
+          }
+        }
+
+        //set the new lo offset
+        else if(pmt::equal(key, LO_OFFS_KEY)) {
+          int chan = pmt::to_long(pmt::tuple_ref(value, 0));
+          double new_lo_offs = pmt::to_double(pmt::tuple_ref(value, 1));
+          if (new_lo_offs != _curr_lo_offset[chan]) {
+            call_tune_loop = true;
+            do_tune[chan] = true;
+            _curr_lo_offset[chan] = new_lo_offs;
+          }
+        }
+      } // end foreach
+      // If there was a freq tag, tune the transmitter(s)
+      if (call_tune_loop) {
+        for (size_t chan = 0; chan < _nchan; chan++) {
+          if (do_tune[chan]) {
+           _set_center_freq_from_internals(chan);
+          }
+        }
+      } // end if call_tune_loop
+    } // end tag_work()
 
     void
     usrp_sink_impl::set_start_time(const ::uhd::time_spec_t &time)
@@ -653,6 +720,50 @@ namespace gr {
       return true;
     }
 
+
+    /************** External interfaces (RPC + Message passing) 
********************/
+    // Helper function for msg_handler_command: Extracts chan and command 
value from
+    // the 2-tuple in cmd_val, updates the value in vector_to_update[chan] and 
returns
+    // true if it was different from the old value.
+    bool _unpack_chan_command(pmt::pmt_t &cmd_val, int &chan, 
std::vector<double> &vector_to_update)
+    {
+      chan = pmt::to_long(pmt::tuple_ref(cmd_val, 0));
+      double new_value = pmt::to_double(pmt::tuple_ref(cmd_val, 1));
+      if (new_value == vector_to_update[chan]) {
+       return false;
+      } else {
+       vector_to_update[chan] = new_value;
+       return true;
+      }
+    }
+
+    void usrp_sink_impl::msg_handler_command(pmt::pmt_t msg)
+    {
+      const std::string command(pmt::symbol_to_string(pmt::car(msg)));
+      pmt::pmt_t value(pmt::cdr(msg));
+      int chan = 0;
+      if (command == "freq") {
+       if (_unpack_chan_command(value, chan, _curr_freq)) {
+         _set_center_freq_from_internals(chan);
+       }
+      } else if (command == "lo_offset") {
+       if (_unpack_chan_command(value, chan, _curr_lo_offset)) {
+         _set_center_freq_from_internals(chan);
+       }
+      } else if (command == "gain") {
+       if (_unpack_chan_command(value, chan, _curr_gain)) {
+         set_gain(_curr_gain[chan], chan);
+       }
+      } else {
+       GR_LOG_ALERT(d_logger, boost::format("Received unknown command: %s") % 
command);
+      }
+    }
+
+    void usrp_sink_impl::msg_handler_query(pmt::pmt_t msg)
+    {
+    
+    }
+
     void
     usrp_sink_impl::setup_rpc()
     {
diff --git a/gr-uhd/lib/usrp_sink_impl.h b/gr-uhd/lib/usrp_sink_impl.h
index ae31b51..c2e488e 100644
--- a/gr-uhd/lib/usrp_sink_impl.h
+++ b/gr-uhd/lib/usrp_sink_impl.h
@@ -26,6 +26,8 @@
 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");
 static const pmt::pmt_t TIME_KEY = pmt::string_to_symbol("tx_time");
+static const pmt::pmt_t FREQ_KEY = pmt::string_to_symbol("tx_freq");
+static const pmt::pmt_t LO_OFFS_KEY = pmt::string_to_symbol("tx_lo_offset");
 
 namespace gr {
   namespace uhd {
@@ -120,6 +122,13 @@ namespace gr {
       inline void tag_work(int &ninput_items);
 
     private:
+      //! Like set_center_freq(), but uses _curr_freq and _curr_lo_offset
+      ::uhd::tune_result_t _set_center_freq_from_internals(size_t chan);
+      //! Receives commands and handles them
+      void msg_handler_command(pmt::pmt_t msg);
+      //! Receives queries and posts a response
+      void msg_handler_query(pmt::pmt_t msg);
+
       ::uhd::usrp::multi_usrp::sptr _dev;
       const ::uhd::stream_args_t _stream_args;
       boost::shared_ptr< ::uhd::io_type_t > _type;
@@ -138,6 +147,16 @@ namespace gr {
       std::vector<tag_t> _tags;
       const pmt::pmt_t _length_tag_key;
       long _nitems_to_send;
+
+      //! 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;
     };
 
   } /* namespace uhd */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]