LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File 0001-update-for-new-API-and-multi-XTRX-support.patch of Package gr-osmosdr (Project home:dl8fcl:sdr)

From e239811df16e9bfdbfa904fab1b235d63ea724d8 Mon Sep 17 00:00:00 2001
From: Sergey Kostanbaev <sergey.kostanbaev@gmail.com>
Date: Sun, 30 Dec 2018 20:54:48 +0300
Subject: [PATCH] update for new API and multi XTRX support

---
 lib/xtrx/xtrx_obj.cc      |   7 ++--
 lib/xtrx/xtrx_obj.h       |   2 +
 lib/xtrx/xtrx_sink_c.cc   | 104 ++++++++++++++++++++++++++++++++-------------
 lib/xtrx/xtrx_sink_c.h    |  10 +++++
 lib/xtrx/xtrx_source_c.cc | 105 ++++++++++++++++++++++++++++------------------
 lib/xtrx/xtrx_source_c.h  |   5 +++
 6 files changed, 161 insertions(+), 72 deletions(-)

diff --git a/lib/xtrx/xtrx_obj.cc b/lib/xtrx/xtrx_obj.cc
index 082c833..1d58de5 100644
--- a/lib/xtrx/xtrx_obj.cc
+++ b/lib/xtrx/xtrx_obj.cc
@@ -68,13 +68,15 @@ xtrx_obj::xtrx_obj(const std::string &path, unsigned loglevel, bool lmsreset)
   unsigned xtrxflag = (loglevel & XTRX_O_LOGLVL_MASK) | ((lmsreset) ? XTRX_O_RESET : 0);
   std::cerr << "xtrx_obj::xtrx_obj = " << xtrxflag << std::endl;
 
-  int res = xtrx_open((path.length() == 0) ? NULL : path.c_str(), xtrxflag, &_obj);
-  if (res) {
+  int res = xtrx_open_list(path.c_str(), NULL, &_obj);
+  if (res < 0) {
     std::stringstream message;
     message << "Couldn't open "  ": Error: " << -res;
 
     throw std::runtime_error( message.str() );
   }
+
+  _devices = res;
 }
 
 double xtrx_obj::set_smaplerate(double rate, double master, bool sink, unsigned flags)
@@ -124,7 +126,6 @@ double xtrx_obj::set_smaplerate(double rate, double master, bool sink, unsigned
   return rxrate;
 }
 
-
 xtrx_obj::~xtrx_obj()
 {
   if (_obj) {
diff --git a/lib/xtrx/xtrx_obj.h b/lib/xtrx/xtrx_obj.h
index 5ef666a..e26947d 100644
--- a/lib/xtrx/xtrx_obj.h
+++ b/lib/xtrx/xtrx_obj.h
@@ -44,6 +44,7 @@ public:
   static void clear_all();
 
   xtrx_dev* dev() { return _obj; }
+  unsigned dev_count() { return _devices; }
 
   double set_smaplerate(double rate, double master, bool sink, unsigned flags);
 
@@ -61,6 +62,7 @@ protected:
   double    _source_master;
 
   unsigned  _flags;
+  unsigned  _devices;
 };
 
 #endif // XTRX_OBJ_H
diff --git a/lib/xtrx/xtrx_sink_c.cc b/lib/xtrx/xtrx_sink_c.cc
index 321dbb3..46ce1b0 100644
--- a/lib/xtrx/xtrx_sink_c.cc
+++ b/lib/xtrx/xtrx_sink_c.cc
@@ -55,8 +55,6 @@ static size_t parse_nchan(const std::string &args)
 
   if (nchan < 1)
     nchan = 1;
-  else if (nchan > 2)
-    nchan = 2;
 
   return nchan;
 }
@@ -76,7 +74,9 @@ xtrx_sink_c::xtrx_sink_c(const std::string &args) :
   _dsp(0),
   _auto_gain(false),
   _otw(XTRX_WF_16),
-  _mimo_mode(parse_nchan(args) > 1),
+  _mimo_mode(false),
+  _gain_tx(0),
+  _channels(parse_nchan(args)),
   _ts(8192),
   _swap_ab(false),
   _swap_iq(false),
@@ -91,16 +91,6 @@ xtrx_sink_c::xtrx_sink_c(const std::string &args) :
     _master = boost::lexical_cast< double >( dict["master"]);
   }
 
-  _channels = parse_nchan(args);
-
-  /*
-  if (dict.count("direct_samp"))
-    direct_samp = boost::lexical_cast< unsigned int >( dict["direct_samp"] );
-
-  if (dict.count("offset_tune"))
-    offset_tune = boost::lexical_cast< unsigned int >( dict["offset_tune"] );
-*/
-
   std::cerr << args.c_str() << std::endl;
 
   int loglevel = 4;
@@ -151,7 +141,11 @@ xtrx_sink_c::xtrx_sink_c(const std::string &args) :
   }
 
   _xtrx = xtrx_obj::get(_dev.c_str(), loglevel, lmsreset);
-
+  if (_xtrx->dev_count() * 2 == _channels) {
+    _mimo_mode = true;
+  } else if (_xtrx->dev_count() != _channels) {
+    throw std::runtime_error("Number of requested channels != number of devices");
+  }
   if (dict.count("refclk")) {
     xtrx_set_ref_clk(_xtrx->dev(), boost::lexical_cast< unsigned >( dict["refclk"] ), XTRX_CLKSRC_INT);
   }
@@ -213,13 +207,14 @@ double xtrx_sink_c::set_center_freq( double freq, size_t chan )
   double corr_freq = (freq)*(1.0 + (_corr) * 0.000001);
 
   std::cerr << "TX Set freq " << freq << std::endl;
+  xtrx_channel_t xchan = (xtrx_channel_t)(XTRX_CH_A << chan);
 
-  int res = xtrx_tune(_xtrx->dev(), (_tdd) ? XTRX_TUNE_TX_AND_RX_TDD : XTRX_TUNE_TX_FDD, corr_freq - _dsp, &_freq);
+  int res = xtrx_tune_ex(_xtrx->dev(), (_tdd) ? XTRX_TUNE_TX_AND_RX_TDD : XTRX_TUNE_TX_FDD, xchan, corr_freq - _dsp, &_freq);
   if (res) {
     std::cerr << "Unable to deliver frequency " << corr_freq << std::endl;
   }
 
-  res = xtrx_tune(_xtrx->dev(), XTRX_TUNE_BB_TX, _dsp, NULL);
+  res = xtrx_tune_ex(_xtrx->dev(), XTRX_TUNE_BB_TX, xchan, _dsp, NULL);
   return get_center_freq(chan);
 }
 
@@ -288,7 +283,7 @@ double xtrx_sink_c::set_gain( double igain, const std::string & name, size_t cha
 
   std::cerr << "Set TX gain: " << igain << std::endl;
 
-  int res = xtrx_set_gain(_xtrx->dev(), /*(chan == 0) ? XTRX_CH_A : XTRX_CH_B*/ XTRX_CH_AB,
+  int res = xtrx_set_gain(_xtrx->dev(), (xtrx_channel_t)(XTRX_CH_A << chan),
                           XTRX_TX_PAD_GAIN, gain, &actual_gain);
   if (res) {
     std::cerr << "Unable to set gain `" << name.c_str() << "`; err=" << res << std::endl;
@@ -320,7 +315,9 @@ double xtrx_sink_c::set_bandwidth( double bandwidth, size_t chan )
     }
   }
 
-  int res = xtrx_tune_tx_bandwidth(_xtrx->dev(), (chan == 0) ? XTRX_CH_A : XTRX_CH_B, bandwidth, &_bandwidth);
+  int res = xtrx_tune_tx_bandwidth(_xtrx->dev(),
+                                   (xtrx_channel_t)(XTRX_CH_A << chan),
+                                   bandwidth, &_bandwidth);
   if (res) {
     std::cerr << "Can't set bandwidth: " << res << std::endl;
   }
@@ -334,13 +331,17 @@ double xtrx_sink_c::get_bandwidth( size_t chan )
 
 
 static const std::map<std::string, xtrx_antenna_t> s_ant_map = boost::assign::map_list_of
-    ("B1", XTRX_TX_L)
-    ("B2", XTRX_TX_W)
-    ;
+  ("AUTO", XTRX_TX_AUTO)
+  ("B1", XTRX_TX_H)
+  ("B2", XTRX_TX_W)
+  ("TXH", XTRX_TX_H)
+  ("TXW", XTRX_TX_W)
+  ;
 static const std::map<xtrx_antenna_t, std::string> s_ant_map_r = boost::assign::map_list_of
-    (XTRX_TX_L, "B1")
-    (XTRX_TX_W, "B2")
-    ;
+  (XTRX_TX_H, "TXH")
+  (XTRX_TX_W, "TXW")
+  (XTRX_TX_AUTO, "AUTO")
+  ;
 
 static xtrx_antenna_t get_ant_type(const std::string& name)
 {
@@ -351,12 +352,12 @@ static xtrx_antenna_t get_ant_type(const std::string& name)
     return it->second;
   }
 
-  return XTRX_RX_W;
+  return XTRX_TX_AUTO;
 }
 
 static const std::vector<std::string> s_ant_list = boost::assign::list_of
-    ("B1")("B2")
-    ;
+  ("AUTO")("TXH")("TXW")
+  ;
 
 
 std::vector< std::string > xtrx_sink_c::get_antennas( size_t chan )
@@ -371,7 +372,9 @@ std::string xtrx_sink_c::set_antenna( const std::string & antenna, size_t chan )
 
   std::cerr << "Set antenna " << antenna << std::endl;
 
-  int res = xtrx_set_antenna(_xtrx->dev(), _ant);
+  int res = xtrx_set_antenna_ex(_xtrx->dev(),
+                                (xtrx_channel_t)(XTRX_CH_A << chan),
+                                _ant);
   if (res) {
     std::cerr << "Can't set antenna: " << antenna << std::endl;
   }
@@ -383,17 +386,60 @@ std::string xtrx_sink_c::get_antenna( size_t chan )
   return s_ant_map_r.find(_ant)->second;
 }
 
+void xtrx_sink_c::tag_process(int ninput_items)
+{
+  std::sort(_tags.begin(), _tags.end(), gr::tag_t::offset_compare);
+
+  const uint64_t samp0_count = this->nitems_read(0);
+  uint64_t max_count = samp0_count + ninput_items;
+
+  bool found_time_tag = false;
+  BOOST_FOREACH(const gr::tag_t &my_tag, _tags) {
+    const uint64_t my_tag_count = my_tag.offset;
+    const pmt::pmt_t &key = my_tag.key;
+    const pmt::pmt_t &value = my_tag.value;
+
+    if (my_tag_count >= max_count) {
+      break;
+    } else if(pmt::equal(key, TIME_KEY)) {
+      //if (my_tag_count != samp0_count) {
+      //    max_count = my_tag_count;
+      //    break;
+      //}
+      found_time_tag = true;
+      //_metadata.has_time_spec = true;
+      //_metadata.time_spec = ::uhd::time_spec_t
+      //      (pmt::to_uint64(pmt::tuple_ref(value, 0)),
+      //       pmt::to_double(pmt::tuple_ref(value, 1)));
+      uint64_t seconds = pmt::to_uint64(pmt::tuple_ref(value, 0));
+      double fractional = pmt::to_double(pmt::tuple_ref(value, 1));
+
+      std::cerr << "TX_TIME: " << seconds << ":" << fractional << std::endl;
+    }
+  } // end foreach
+
+  if (found_time_tag) {
+    //_metadata.has_time_spec = true;
+  }
+}
+
 int xtrx_sink_c::work (int noutput_items,
                        gr_vector_const_void_star &input_items,
                        gr_vector_void_star &output_items)
 {
+  int ninput_items = noutput_items;
+  const uint64_t samp0_count = nitems_read(0);
+  get_tags_in_range(_tags, 0, samp0_count, samp0_count + ninput_items);
+  if (!_tags.empty())
+    tag_process(ninput_items);
+
   xtrx_send_ex_info_t nfo;
   nfo.samples = noutput_items;
   nfo.buffer_count = input_items.size();
   nfo.buffers = &input_items[0];
   nfo.flags = XTRX_TX_DONT_BUFFER;
   if (!_allow_dis)
-	nfo.flags |= XTRX_TX_NO_DISCARD;
+    nfo.flags |= XTRX_TX_NO_DISCARD;
   nfo.ts = _ts;
   nfo.timeout = 0;
 
diff --git a/lib/xtrx/xtrx_sink_c.h b/lib/xtrx/xtrx_sink_c.h
index 2df30a4..8a041e6 100644
--- a/lib/xtrx/xtrx_sink_c.h
+++ b/lib/xtrx/xtrx_sink_c.h
@@ -27,6 +27,13 @@
 #include "sink_iface.h"
 #include "xtrx_obj.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");
+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 COMMAND_KEY = pmt::string_to_symbol("tx_command");
+
 class xtrx_sink_c;
 
 typedef boost::shared_ptr< xtrx_sink_c > xtrx_sink_c_sptr;
@@ -85,8 +92,11 @@ public:
   bool start();
   bool stop();
 
+  void tag_process(int ninput_items);
+
 private:
   xtrx_obj_sptr _xtrx;
+  std::vector<gr::tag_t> _tags;
 
   unsigned _sample_flags;
   double _rate;
diff --git a/lib/xtrx/xtrx_source_c.cc b/lib/xtrx/xtrx_source_c.cc
index e38aedd..9e0db10 100644
--- a/lib/xtrx/xtrx_source_c.cc
+++ b/lib/xtrx/xtrx_source_c.cc
@@ -55,8 +55,6 @@ static size_t parse_nchan(const std::string &args)
 
   if (nchan < 1)
     nchan = 1;
-  else if (nchan > 2)
-    nchan = 2;
 
   return nchan;
 }
@@ -75,12 +73,17 @@ xtrx_source_c::xtrx_source_c(const std::string &args) :
   _bandwidth(0),
   _auto_gain(false),
   _otw(XTRX_WF_16),
-  _mimo_mode(parse_nchan(args) > 1),
+  _mimo_mode(false),
+  _gain_lna(0),
+  _gain_tia(0),
+  _gain_pga(0),
+  _channels(parse_nchan(args)),
   _swap_ab(false),
   _swap_iq(false),
   _loopback(false),
   _tdd(false),
   _fbctrl(false),
+  _timekey(false),
   _dsp(0)
 {
   _id = pmt::string_to_symbol(args);
@@ -104,16 +107,6 @@ xtrx_source_c::xtrx_source_c(const std::string &args) :
     _master = boost::lexical_cast< double >( dict["master"]);
   }
 
-  _channels = parse_nchan(args);
-
-  /*
-  if (dict.count("direct_samp"))
-    direct_samp = boost::lexical_cast< unsigned int >( dict["direct_samp"] );
-
-  if (dict.count("offset_tune"))
-    offset_tune = boost::lexical_cast< unsigned int >( dict["offset_tune"] );
-*/
-
   std::cerr << args.c_str() << std::endl;
 
   int loglevel = 4;
@@ -155,38 +148,47 @@ xtrx_source_c::xtrx_source_c(const std::string &args) :
   }
 
   if (dict.count("dsp")) {
-      _dsp = boost::lexical_cast< double >( dict["dsp"] );
-      std::cerr << "xtrx_source_c: DSP:" << _dsp;
+    _dsp = boost::lexical_cast< double >( dict["dsp"] );
+    std::cerr << "xtrx_source_c: DSP:" << _dsp;
   }
 
   if (dict.count("dev")) {
-      _dev =  dict["dev"];
-      std::cerr << "xtrx_source_c: XTRX device: %s" << _dev.c_str();
+    _dev =  dict["dev"];
+    std::cerr << "xtrx_source_c: XTRX device: %s" << _dev.c_str();
   }
 
   _xtrx = xtrx_obj::get(_dev.c_str(), loglevel, lmsreset);
+  if (_xtrx->dev_count() * 2 == _channels) {
+    _mimo_mode = true;
+  } else if (_xtrx->dev_count() != _channels) {
+    throw std::runtime_error("Number of requested channels != number of devices");
+  }
 
   if (dict.count("refclk")) {
-      xtrx_set_ref_clk(_xtrx->dev(), boost::lexical_cast< unsigned >( dict["refclk"] ), XTRX_CLKSRC_INT);
-    }
+    xtrx_set_ref_clk(_xtrx->dev(), boost::lexical_cast< unsigned >( dict["refclk"] ), XTRX_CLKSRC_INT);
+  }
   if (dict.count("extclk")) {
-      xtrx_set_ref_clk(_xtrx->dev(), boost::lexical_cast< unsigned >( dict["extclk"] ), XTRX_CLKSRC_EXT);
-    }
+    xtrx_set_ref_clk(_xtrx->dev(), boost::lexical_cast< unsigned >( dict["extclk"] ), XTRX_CLKSRC_EXT);
+  }
 
   if (dict.count("vio")) {
-      unsigned vio = boost::lexical_cast< unsigned >( dict["vio"] );
-      _xtrx->set_vio(vio);
-    }
+    unsigned vio = boost::lexical_cast< unsigned >( dict["vio"] );
+    _xtrx->set_vio(vio);
+  }
 
   if (dict.count("dac")) {
-      unsigned dac = boost::lexical_cast< unsigned >( dict["dac"] );
-      xtrx_val_set(_xtrx->dev(), XTRX_TRX, XTRX_CH_AB, XTRX_VCTCXO_DAC_VAL, dac);
-    }
+    unsigned dac = boost::lexical_cast< unsigned >( dict["dac"] );
+    xtrx_val_set(_xtrx->dev(), XTRX_TRX, XTRX_CH_ALL, XTRX_VCTCXO_DAC_VAL, dac);
+  }
 
   if (dict.count("pmode")) {
-      unsigned pmode = boost::lexical_cast< unsigned >( dict["pmode"] );
-      xtrx_val_set(_xtrx->dev(), XTRX_TRX, XTRX_CH_AB, XTRX_LMS7_PWR_MODE, pmode);
-    }
+    unsigned pmode = boost::lexical_cast< unsigned >( dict["pmode"] );
+    xtrx_val_set(_xtrx->dev(), XTRX_TRX, XTRX_CH_ALL, XTRX_LMS7_PWR_MODE, pmode);
+  }
+
+  if (dict.count("timekey")) {
+    _timekey = boost::lexical_cast< bool >( dict["timekey"] );
+  }
 
   std::cerr << "xtrx_source_c::xtrx_source_c()" << std::endl;
   set_alignment(32);
@@ -254,14 +256,16 @@ double xtrx_source_c::set_center_freq( double freq, size_t chan )
   if (_tdd)
     return get_center_freq(chan);
 
+  xtrx_channel_t xchan = (xtrx_channel_t)(XTRX_CH_A << chan);
+
   std::cerr << "Set freq " << freq << std::endl;
 
-  int res = xtrx_tune(_xtrx->dev(), XTRX_TUNE_RX_FDD, corr_freq - _dsp, &_freq);
+  int res = xtrx_tune_ex(_xtrx->dev(), XTRX_TUNE_RX_FDD, xchan, corr_freq - _dsp, &_freq);
   if (res) {
     std::cerr << "Unable to deliver frequency " << corr_freq << std::endl;
   }
 
-  res = xtrx_tune(_xtrx->dev(), XTRX_TUNE_BB_RX, _dsp, NULL);
+  res = xtrx_tune_ex(_xtrx->dev(), XTRX_TUNE_BB_RX, xchan, _dsp, NULL);
 
   return get_center_freq(chan);
 }
@@ -298,14 +302,14 @@ static xtrx_gain_type_t get_gain_type(const std::string& name)
 
   it = s_lna_map.find(name);
   if (it != s_lna_map.end()) {
-    return it->second;
+	return it->second;
   }
 
   return XTRX_RX_LNA_GAIN;
 }
 
 static const std::vector<std::string> s_lna_list = boost::assign::list_of
-    ("LNA")("TIA")("PGA")("LB")
+  ("LNA")("TIA")("PGA")("LB")
     ;
 
 std::vector<std::string> xtrx_source_c::get_gain_names( size_t chan )
@@ -365,7 +369,8 @@ double xtrx_source_c::set_gain( double igain, const std::string & name, size_t c
 
   std::cerr << "Set gain " << name << " (" << gt << "): " << igain << std::endl;
 
-  int res = xtrx_set_gain(_xtrx->dev(), /*(chan == 0) ? XTRX_CH_A : XTRX_CH_B*/ XTRX_CH_AB, gt, gain, &actual_gain);
+  int res = xtrx_set_gain(_xtrx->dev(), (xtrx_channel_t)(XTRX_CH_A << chan),
+                          gt, gain, &actual_gain);
   if (res) {
     std::cerr << "Unable to set gain `" << name.c_str() << "`; err=" << res << std::endl;
   }
@@ -413,7 +418,8 @@ double xtrx_source_c::set_bandwidth( double bandwidth, size_t chan )
     }
   }
 
-  int res = xtrx_tune_rx_bandwidth(_xtrx->dev(), (chan == 0) ? XTRX_CH_A : XTRX_CH_B, bandwidth, &_bandwidth);
+  int res = xtrx_tune_rx_bandwidth(_xtrx->dev(), (xtrx_channel_t)(XTRX_CH_A << chan),
+                                   bandwidth, &_bandwidth);
   if (res) {
     std::cerr << "Can't set bandwidth: " << res << std::endl;
   }
@@ -457,7 +463,7 @@ static xtrx_antenna_t get_ant_type(const std::string& name)
     return it->second;
   }
 
-  return XTRX_RX_W;
+  return XTRX_RX_AUTO;
 }
 
 static const std::vector<std::string> s_ant_list = boost::assign::list_of
@@ -475,9 +481,10 @@ std::string xtrx_source_c::set_antenna( const std::string & antenna, size_t chan
   boost::mutex::scoped_lock lock(_xtrx->mtx);
   _ant = get_ant_type(antenna);
 
-  std::cerr << "Set antenna " << antenna << std::endl;
+  std::cerr << "Set antenna " << antenna << " type:" << _ant << std::endl;
 
-  int res = xtrx_set_antenna(_xtrx->dev(), _ant);
+  int res = xtrx_set_antenna_ex(_xtrx->dev(), (xtrx_channel_t)(XTRX_CH_A << chan),
+                                _ant);
   if (res) {
     std::cerr << "Can't set antenna: " << antenna << std::endl;
   }
@@ -507,6 +514,23 @@ int xtrx_source_c::work (int noutput_items,
     throw std::runtime_error( message.str() );
   }
 
+  if (_timekey) {
+    uint64_t seconds = (ri.out_first_sample / _rate);
+    double fractional = (ri.out_first_sample - (uint64_t)(_rate * seconds)) / _rate;
+
+    //std::cerr << "Time " << seconds << ":" << fractional << std::endl;
+    const pmt::pmt_t val = pmt::make_tuple
+        (pmt::from_uint64(seconds),
+         pmt::from_double(fractional));
+    for(size_t i = 0; i < output_items.size(); i++) {
+      this->add_item_tag(i, nitems_written(0), TIME_KEY,
+                         val, _id);
+      this->add_item_tag(i, nitems_written(0), RATE_KEY,
+                         pmt::from_double(_rate), _id);
+      this->add_item_tag(i, nitems_written(0), FREQ_KEY,
+                         pmt::from_double(this->get_center_freq(i)), _id);
+    }
+  }
   return ri.out_samples;
 }
 
@@ -540,7 +564,7 @@ bool xtrx_source_c::start()
     std::cerr << "Got error: " << res << std::endl;
   }
 
-  res = xtrx_tune(_xtrx->dev(), XTRX_TUNE_BB_RX, _dsp, NULL);
+  res = xtrx_tune_ex(_xtrx->dev(), XTRX_TUNE_BB_RX, XTRX_CH_ALL, _dsp, NULL);
 
   return res == 0;
 }
@@ -557,3 +581,4 @@ bool xtrx_source_c::stop()
 
   return res == 0;
 }
+
diff --git a/lib/xtrx/xtrx_source_c.h b/lib/xtrx/xtrx_source_c.h
index c1c86b1..3189f88 100644
--- a/lib/xtrx/xtrx_source_c.h
+++ b/lib/xtrx/xtrx_source_c.h
@@ -26,6 +26,10 @@
 #include "source_iface.h"
 #include "xtrx_obj.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");
+static const pmt::pmt_t FREQ_KEY = pmt::string_to_symbol("rx_freq");
+
 class xtrx_source_c;
 
 typedef boost::shared_ptr< xtrx_source_c > xtrx_source_c_sptr;
@@ -114,6 +118,7 @@ private:
   bool     _loopback;
   bool     _tdd;
   bool     _fbctrl;
+  bool     _timekey;
 
   double   _dsp;
   std::string _dev;
-- 
2.16.4