commit-gnuradio
[Top][All Lists]
Advanced

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

[Commit-gnuradio] [gnuradio] 01/03: uhd: Refactored usrp_{sink, source}


From: git
Subject: [Commit-gnuradio] [gnuradio] 01/03: uhd: Refactored usrp_{sink, source} blocks
Date: Thu, 30 Apr 2015 23:01:13 +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 abd0b89f1cd73f93511514270a9b6a657e769fb3
Author: Martin Braun <address@hidden>
Date:   Wed Apr 29 10:14:59 2015 -0700

    uhd: Refactored usrp_{sink,source} blocks
---
 gr-uhd/examples/grc/uhd_msg_tune.grc               | 451 +++++++++++++++------
 gr-uhd/include/gnuradio/uhd/CMakeLists.txt         |   1 +
 .../gnuradio/uhd/{usrp_sink.h => usrp_block.h}     | 276 ++++---------
 gr-uhd/include/gnuradio/uhd/usrp_sink.h            | 417 +------------------
 gr-uhd/include/gnuradio/uhd/usrp_source.h          | 420 +------------------
 gr-uhd/lib/CMakeLists.txt                          |   1 +
 gr-uhd/lib/usrp_block_impl.cc                      | 428 +++++++++++++++++++
 gr-uhd/lib/usrp_block_impl.h                       | 199 +++++++++
 gr-uhd/lib/usrp_common.h                           | 211 ----------
 gr-uhd/lib/usrp_sink_impl.cc                       | 293 +------------
 gr-uhd/lib/usrp_sink_impl.h                        |  48 +--
 gr-uhd/lib/usrp_source_impl.cc                     | 270 +-----------
 gr-uhd/lib/usrp_source_impl.h                      |  47 +--
 gr-uhd/swig/uhd_swig.i                             |   2 +
 14 files changed, 1081 insertions(+), 1983 deletions(-)

diff --git a/gr-uhd/examples/grc/uhd_msg_tune.grc 
b/gr-uhd/examples/grc/uhd_msg_tune.grc
index 8902227..1d0a953 100644
--- a/gr-uhd/examples/grc/uhd_msg_tune.grc
+++ b/gr-uhd/examples/grc/uhd_msg_tune.grc
@@ -1,74 +1,12 @@
 <?xml version='1.0' encoding='ASCII'?>
+<?grc format='1' created='3.7.8'?>
 <flow_graph>
   <timestamp>Tue Jul  8 12:08:19 2014</timestamp>
   <block>
-    <key>options</key>
-    <param>
-      <key>id</key>
-      <value>uhd_tune_msg</value>
-    </param>
-    <param>
-      <key>_enabled</key>
-      <value>True</value>
-    </param>
-    <param>
-      <key>title</key>
-      <value>UHD Message Tuner</value>
-    </param>
-    <param>
-      <key>author</key>
-      <value></value>
-    </param>
-    <param>
-      <key>description</key>
-      <value>Tune a UHD source from a QT sink via messages.</value>
-    </param>
-    <param>
-      <key>window_size</key>
-      <value>1280, 1024</value>
-    </param>
-    <param>
-      <key>generate_options</key>
-      <value>qt_gui</value>
-    </param>
-    <param>
-      <key>category</key>
-      <value>Custom</value>
-    </param>
-    <param>
-      <key>run_options</key>
-      <value>prompt</value>
-    </param>
-    <param>
-      <key>run</key>
-      <value>True</value>
-    </param>
-    <param>
-      <key>max_nouts</key>
-      <value>0</value>
-    </param>
-    <param>
-      <key>realtime_scheduling</key>
-      <value></value>
-    </param>
-    <param>
-      <key>alias</key>
-      <value></value>
-    </param>
-    <param>
-      <key>_coordinate</key>
-      <value>(-1, -2)</value>
-    </param>
-    <param>
-      <key>_rotation</key>
-      <value>0</value>
-    </param>
-  </block>
-  <block>
     <key>variable</key>
     <param>
       <key>id</key>
-      <value>initial_fc</value>
+      <value>samp_rate</value>
     </param>
     <param>
       <key>_enabled</key>
@@ -76,37 +14,14 @@
     </param>
     <param>
       <key>value</key>
-      <value>100e6</value>
+      <value>2e6</value>
     </param>
     <param>
       <key>alias</key>
       <value></value>
     </param>
     <param>
-      <key>_coordinate</key>
-      <value>(-2, 172)</value>
-    </param>
-    <param>
-      <key>_rotation</key>
-      <value>0</value>
-    </param>
-  </block>
-  <block>
-    <key>variable</key>
-    <param>
-      <key>id</key>
-      <value>samp_rate</value>
-    </param>
-    <param>
-      <key>_enabled</key>
-      <value>True</value>
-    </param>
-    <param>
-      <key>value</key>
-      <value>2e6</value>
-    </param>
-    <param>
-      <key>alias</key>
+      <key>comment</key>
       <value></value>
     </param>
     <param>
@@ -119,58 +34,30 @@
     </param>
   </block>
   <block>
-    <key>variable_qtgui_range</key>
+    <key>variable</key>
     <param>
       <key>id</key>
-      <value>gain</value>
+      <value>initial_fc</value>
     </param>
     <param>
       <key>_enabled</key>
       <value>True</value>
     </param>
     <param>
-      <key>label</key>
-      <value></value>
-    </param>
-    <param>
       <key>value</key>
-      <value>20</value>
-    </param>
-    <param>
-      <key>start</key>
-      <value>0</value>
-    </param>
-    <param>
-      <key>stop</key>
-      <value>60</value>
-    </param>
-    <param>
-      <key>step</key>
-      <value>1</value>
-    </param>
-    <param>
-      <key>widget</key>
-      <value>counter_slider</value>
-    </param>
-    <param>
-      <key>orient</key>
-      <value>Qt.Horizontal</value>
-    </param>
-    <param>
-      <key>min_len</key>
-      <value>200</value>
+      <value>100e6</value>
     </param>
     <param>
-      <key>gui_hint</key>
+      <key>alias</key>
       <value></value>
     </param>
     <param>
-      <key>alias</key>
+      <key>comment</key>
       <value></value>
     </param>
     <param>
       <key>_coordinate</key>
-      <value>(103, 99)</value>
+      <value>(-2, 172)</value>
     </param>
     <param>
       <key>_rotation</key>
@@ -336,6 +223,10 @@
       <value>gain</value>
     </param>
     <param>
+      <key>norm_gain0</key>
+      <value>True</value>
+    </param>
+    <param>
       <key>ant0</key>
       <value></value>
     </param>
@@ -352,6 +243,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain1</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant1</key>
       <value></value>
     </param>
@@ -368,6 +263,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain2</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant2</key>
       <value></value>
     </param>
@@ -384,6 +283,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain3</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant3</key>
       <value></value>
     </param>
@@ -400,6 +303,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain4</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant4</key>
       <value></value>
     </param>
@@ -416,6 +323,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain5</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant5</key>
       <value></value>
     </param>
@@ -432,6 +343,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain6</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant6</key>
       <value></value>
     </param>
@@ -448,6 +363,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain7</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant7</key>
       <value></value>
     </param>
@@ -464,6 +383,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain8</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant8</key>
       <value></value>
     </param>
@@ -480,6 +403,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain9</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant9</key>
       <value></value>
     </param>
@@ -496,6 +423,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain10</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant10</key>
       <value></value>
     </param>
@@ -512,6 +443,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain11</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant11</key>
       <value></value>
     </param>
@@ -528,6 +463,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain12</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant12</key>
       <value></value>
     </param>
@@ -544,6 +483,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain13</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant13</key>
       <value></value>
     </param>
@@ -560,6 +503,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain14</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant14</key>
       <value></value>
     </param>
@@ -576,6 +523,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain15</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant15</key>
       <value></value>
     </param>
@@ -592,6 +543,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain16</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant16</key>
       <value></value>
     </param>
@@ -608,6 +563,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain17</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant17</key>
       <value></value>
     </param>
@@ -624,6 +583,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain18</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant18</key>
       <value></value>
     </param>
@@ -640,6 +603,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain19</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant19</key>
       <value></value>
     </param>
@@ -656,6 +623,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain20</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant20</key>
       <value></value>
     </param>
@@ -672,6 +643,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain21</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant21</key>
       <value></value>
     </param>
@@ -688,6 +663,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain22</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant22</key>
       <value></value>
     </param>
@@ -704,6 +683,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain23</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant23</key>
       <value></value>
     </param>
@@ -720,6 +703,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain24</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant24</key>
       <value></value>
     </param>
@@ -736,6 +723,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain25</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant25</key>
       <value></value>
     </param>
@@ -752,6 +743,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain26</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant26</key>
       <value></value>
     </param>
@@ -768,6 +763,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain27</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant27</key>
       <value></value>
     </param>
@@ -784,6 +783,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain28</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant28</key>
       <value></value>
     </param>
@@ -800,6 +803,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain29</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant29</key>
       <value></value>
     </param>
@@ -816,6 +823,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain30</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant30</key>
       <value></value>
     </param>
@@ -832,6 +843,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>norm_gain31</key>
+      <value>False</value>
+    </param>
+    <param>
       <key>ant31</key>
       <value></value>
     </param>
@@ -856,6 +871,10 @@
       <value>0</value>
     </param>
     <param>
+      <key>comment</key>
+      <value></value>
+    </param>
+    <param>
       <key>_coordinate</key>
       <value>(336, 8)</value>
     </param>
@@ -887,6 +906,10 @@
       <value>1024</value>
     </param>
     <param>
+      <key>freqhalf</key>
+      <value>True</value>
+    </param>
+    <param>
       <key>wintype</key>
       <value>firdes.WIN_BLACKMAN_hARRIS</value>
     </param>
@@ -899,20 +922,24 @@
       <value>samp_rate</value>
     </param>
     <param>
+      <key>grid</key>
+      <value>True</value>
+    </param>
+    <param>
       <key>autoscale</key>
       <value>False</value>
     </param>
     <param>
       <key>average</key>
-      <value>1.0</value>
+      <value>0.1</value>
     </param>
     <param>
       <key>ymin</key>
-      <value>-140</value>
+      <value>-120</value>
     </param>
     <param>
       <key>ymax</key>
-      <value>10</value>
+      <value>-40</value>
     </param>
     <param>
       <key>nconnections</key>
@@ -927,6 +954,34 @@
       <value></value>
     </param>
     <param>
+      <key>showports</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>tr_mode</key>
+      <value>qtgui.TRIG_MODE_FREE</value>
+    </param>
+    <param>
+      <key>tr_level</key>
+      <value>0.0</value>
+    </param>
+    <param>
+      <key>tr_chan</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>tr_tag</key>
+      <value>""</value>
+    </param>
+    <param>
+      <key>ctrlpanel</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>legend</key>
+      <value>True</value>
+    </param>
+    <param>
       <key>label1</key>
       <value></value>
     </param>
@@ -1103,14 +1158,156 @@
       <value>0</value>
     </param>
     <param>
+      <key>comment</key>
+      <value></value>
+    </param>
+    <param>
       <key>_coordinate</key>
-      <value>(330, 104)</value>
+      <value>(344, 139)</value>
     </param>
     <param>
       <key>_rotation</key>
       <value>180</value>
     </param>
   </block>
+  <block>
+    <key>variable_qtgui_range</key>
+    <param>
+      <key>id</key>
+      <value>gain</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>Gain</value>
+    </param>
+    <param>
+      <key>rangeType</key>
+      <value>float</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>.8</value>
+    </param>
+    <param>
+      <key>start</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>stop</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>step</key>
+      <value>.01</value>
+    </param>
+    <param>
+      <key>widget</key>
+      <value>counter_slider</value>
+    </param>
+    <param>
+      <key>orient</key>
+      <value>Qt.Horizontal</value>
+    </param>
+    <param>
+      <key>min_len</key>
+      <value>200</value>
+    </param>
+    <param>
+      <key>gui_hint</key>
+      <value></value>
+    </param>
+    <param>
+      <key>alias</key>
+      <value></value>
+    </param>
+    <param>
+      <key>comment</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(103, 99)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>options</key>
+    <param>
+      <key>id</key>
+      <value>uhd_tune_msg</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>UHD Message Tuner</value>
+    </param>
+    <param>
+      <key>author</key>
+      <value></value>
+    </param>
+    <param>
+      <key>description</key>
+      <value>Tune a UHD source from a QT sink via messages (double-click a 
frequency to tune)</value>
+    </param>
+    <param>
+      <key>window_size</key>
+      <value>1280, 1024</value>
+    </param>
+    <param>
+      <key>generate_options</key>
+      <value>qt_gui</value>
+    </param>
+    <param>
+      <key>category</key>
+      <value>Custom</value>
+    </param>
+    <param>
+      <key>run_options</key>
+      <value>prompt</value>
+    </param>
+    <param>
+      <key>run</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>max_nouts</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>realtime_scheduling</key>
+      <value></value>
+    </param>
+    <param>
+      <key>thread_safe_setters</key>
+      <value></value>
+    </param>
+    <param>
+      <key>alias</key>
+      <value></value>
+    </param>
+    <param>
+      <key>comment</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(-1, -2)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
   <connection>
     <source_block_id>uhd_usrp_source_0</source_block_id>
     <sink_block_id>qtgui_freq_sink_x_0</sink_block_id>
diff --git a/gr-uhd/include/gnuradio/uhd/CMakeLists.txt 
b/gr-uhd/include/gnuradio/uhd/CMakeLists.txt
index 71c17b8..b1f3345 100644
--- a/gr-uhd/include/gnuradio/uhd/CMakeLists.txt
+++ b/gr-uhd/include/gnuradio/uhd/CMakeLists.txt
@@ -22,6 +22,7 @@
 ########################################################################
 install(FILES
     api.h
+    usrp_block.h
     usrp_source.h
     usrp_sink.h
     amsg_source.h
diff --git a/gr-uhd/include/gnuradio/uhd/usrp_sink.h 
b/gr-uhd/include/gnuradio/uhd/usrp_block.h
similarity index 68%
copy from gr-uhd/include/gnuradio/uhd/usrp_sink.h
copy to gr-uhd/include/gnuradio/uhd/usrp_block.h
index dd1bd6a..656bb8a 100644
--- a/gr-uhd/include/gnuradio/uhd/usrp_sink.h
+++ b/gr-uhd/include/gnuradio/uhd/usrp_block.h
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2010-2015 Free Software Foundation, Inc.
+ * Copyright 2015 Free Software Foundation, Inc.
  *
  * This file is part of GNU Radio
  *
@@ -20,189 +20,81 @@
  * Boston, MA 02110-1301, USA.
  */
 
-#ifndef INCLUDED_GR_UHD_USRP_SINK_H
-#define INCLUDED_GR_UHD_USRP_SINK_H
+#ifndef INCLUDED_GR_UHD_USRP_BLOCK_H
+#define INCLUDED_GR_UHD_USRP_BLOCK_H
 
 #include <gnuradio/uhd/api.h>
 #include <gnuradio/sync_block.h>
 #include <uhd/usrp/multi_usrp.hpp>
 
-// TODO In 3.8, UHD 3.4 will be required and we can remove all these ifdefs
-#ifndef INCLUDED_UHD_STREAM_HPP
-namespace uhd {
-  struct GR_UHD_API stream_args_t
-  {
-    stream_args_t(const std::string &cpu = "",
-                  const std::string &otw = "")
-      {
-        cpu_format = cpu;
-        otw_format = otw;
-      }
-    std::string cpu_format;
-    std::string otw_format;
-    device_addr_t args;
-    std::vector<size_t> channels;
-  };
-}
-#  define INCLUDED_UHD_STREAM_HPP
-#else
-#  define GR_UHD_USE_STREAM_API
-#endif
-
 namespace gr {
   namespace uhd {
 
-    class uhd_usrp_sink;
-
-    class GR_UHD_API usrp_sink : virtual public sync_block
+    class GR_UHD_API usrp_block : public gr::sync_block
     {
-    public:
-      // gr::uhd::usrp_sink::sptr
-      typedef boost::shared_ptr<usrp_sink> sptr;
-
-      /*!
-       * \brief DEPRECATED Make a new USRP sink block using the deprecated 
io_type_t.
-       * \ingroup uhd_blk
-       *
-       * This function will be removed in the future. Please use the other 
make function,
-       * gr::uhd::usrp_sink::make(const ::uhd::device_addr_t, const 
::uhd::stream_args_t, const std::string).
-       */
-      static sptr make(const ::uhd::device_addr_t &device_addr,
-                      const ::uhd::io_type_t &io_type,
-                      size_t num_channels);
-
-      /*!
-       * \brief Make a new USRP sink block (usually a radio transmitter).
-       *
-       * The USRP sink block reads a stream and transmits the samples.
-       * The sink block also provides API calls for transmitter settings.
-       *
-       * \section uhd_tx_tagging TX Stream tagging
-       *
-       * The following tag keys will be consumed by the work function:
-       *  - 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("tx_command")
-       *  - pmt::string_to_symbol(tsb_tag_name)
-       *
-       * Any other tag will be ignored.
-       *
-       * The sob and eob (start and end of burst) tag values are pmt booleans.
-       * When present, burst tags should be set to true (pmt::PMT_T).
-       *
-       * If `tsb_tag_name` is not an empty string, all "tx_sob" and "tx_eob"
-       * tags will be ignored, and the input is assumed to a tagged stream,
-       * as described in \ref page_tagged_stream_blocks.
-       *
-       * If sob/eob tags or length tags are used, this block understands that
-       * the data is bursty, and will configure the USRP to make sure there's
-       * no underruns after transmitting the final sample of a burst.
-       *
-       * The timestamp tag value is a PMT tuple of the following:
-       * (uint64 seconds, double fractional seconds).
-       *
-       * The tx_freq tag has to be a double or a pair of form (channel, 
frequency),
-       * with frequency being a double and channel being an integer.
-       * This tag will trigger a tune command to the USRP
-       * to the given frequency, if possible. Note that oscillators need some 
time
-       * to stabilize after this! Don't expect clean data to be sent 
immediately after this command.
-       * If channel is omitted, and only a double is given, it will set this 
frequency to all
-       * channels.
-       *
-       * The command tag can carry a PMT command. See the following section.
-       *
-       * \section uhd_tx_commands Command interface
-       *
-       * There are two ways of passing commands to this block:
-       * 1. tx_command tag. The command is attached to a sample, and will 
executed
-       *    before the sample is transmitted, and after the previous sample.
-       * 2. The 'command' message port. The command is executed asynchronously,
-       *    as soon as possible.
-       *
-       * In both cases, the payload of the command is a PMT command, as 
described
-       * in Section \ref uhd_command_syntax.
-       *
-       * For a more general description of the gr-uhd components, see \ref 
page_uhd.
-       *
-       * \param device_addr the address to identify the hardware
-       * \param stream_args the IO format and channel specification
-       * \param tsb_tag_name the name of the tag identifying tagged stream 
length
-       * \return a new USRP sink block object
-       */
-      static sptr make(const ::uhd::device_addr_t &device_addr,
-                       const ::uhd::stream_args_t &stream_args,
-                       const std::string &tsb_tag_name = "");
-
-      /*!
-       * Set the start time for outgoing samples.
-       * To control when samples are transmitted,
-       * set this value before starting the flow graph.
-       * The value is cleared after each run.
-       * When not specified, the start time will be:
-       *  - Immediately for the one channel case
-       *  - in the near future for multi-channel
-       *
-       * \param time the absolute time for transmission to begin
-       */
-      virtual void set_start_time(const ::uhd::time_spec_t &time) = 0;
-
-      /*!
-       * Returns identifying information about this USRP's configuration.
-       * Returns motherboard ID, name, and serial.
-       * Returns daughterboard TX ID, subdev name and spec, serial, and 
antenna.
-       * \param chan channel index 0 to N-1
-       * \return TX info
-       */
-      virtual ::uhd::dict<std::string, std::string> get_usrp_info(size_t chan 
= 0) = 0;
-
+     protected:
+      usrp_block() {}; // For virtual sub-classing
+      usrp_block(const std::string &name,
+                 gr::io_signature::sptr input_signature,
+                 gr::io_signature::sptr output_signature);
+     public:
       /*!
        * Set the frontend specification.
+       *
        * \param spec the subdev spec markup string
        * \param mboard the motherboard index 0 to M-1
        */
       virtual void set_subdev_spec(const std::string &spec, size_t mboard = 0) 
= 0;
 
       /*!
-       * Get the TX frontend specification.
+       * Get the frontend specification.
+       *
        * \param mboard the motherboard index 0 to M-1
        * \return the frontend specification in use
        */
-      virtual std::string get_subdev_spec (size_t mboard = 0) = 0;
+      virtual std::string get_subdev_spec(size_t mboard = 0) = 0;
 
       /*!
-       * Set the sample rate for the usrp device.
+       * Set the sample rate for this connection to the USRP.
+       *
        * \param rate a new rate in Sps
        */
       virtual void set_samp_rate(double rate) = 0;
 
       /*!
-       * Get the sample rate for the usrp device.
+       * Get the sample rate for this connection to the USRP.
        * This is the actual sample rate and may differ from the rate set.
+       *
        * \return the actual rate in Sps
        */
       virtual double get_samp_rate(void) = 0;
 
       /*!
-       * Get the possible sample rates for the usrp device.
+       * Get the possible sample rates for this connection.
+       *
        * \return a range of rates in Sps
        */
       virtual ::uhd::meta_range_t get_samp_rates(void) = 0;
 
       /*!
-       * Tune the usrp device to the desired center frequency.
+       * Tune the selected channel to the desired center frequency.
+       *
        * \param tune_request the tune request instructions
        * \param chan the channel index 0 to N-1
        * \return a tune result with the actual frequencies
        */
-      virtual ::uhd::tune_result_t set_center_freq
-        (const ::uhd::tune_request_t tune_request, size_t chan = 0) = 0;
+      virtual ::uhd::tune_result_t set_center_freq(
+          const ::uhd::tune_request_t tune_request,
+          size_t chan = 0
+      ) = 0;
 
       /*!
-       * Tune the usrp device to the desired center frequency.
-       * This is a wrapper around set center freq so that in this case,
-       * the user can pass a single frequency in the call through swig.
+       * Tune the the selected channel to the desired center frequency.
+       *
+       * This is a wrapper around set_center_freq() so that in this case,
+       * the user can pass a single frequency in the call instead of
+       * having to generate a tune_request_t object.
+       *
        * \param freq the desired frequency in Hz
        * \param chan the channel index 0 to N-1
        * \return a tune result with the actual frequencies
@@ -214,6 +106,7 @@ namespace gr {
 
       /*!
        * Get the center frequency.
+       *
        * \param chan the channel index 0 to N-1
        * \return the frequency in Hz
        */
@@ -221,13 +114,15 @@ namespace gr {
 
       /*!
        * Get the tunable frequency range.
+       *
        * \param chan the channel index 0 to N-1
        * \return the frequency range in Hz
        */
       virtual ::uhd::freq_range_t get_freq_range(size_t chan = 0) = 0;
 
       /*!
-       * Set the gain for the dboard.
+       * Set the gain for the selected channel.
+       *
        * \param gain the gain in dB
        * \param chan the channel index 0 to N-1
        */
@@ -235,6 +130,7 @@ namespace gr {
 
       /*!
        * Set the named gain on the dboard.
+       *
        * \param gain the gain in dB
        * \param name the name of the gain stage
        * \param chan the channel index 0 to N-1
@@ -263,6 +159,7 @@ namespace gr {
 
       /*!
        * Get the actual dboard gain setting.
+       *
        * \param chan the channel index 0 to N-1
        * \return the actual gain in dB
        */
@@ -270,6 +167,7 @@ namespace gr {
 
       /*!
        * Get the actual dboard gain setting of named stage.
+       *
        * \param name the name of the gain stage
        * \param chan the channel index 0 to N-1
        * \return the actual gain in dB
@@ -283,8 +181,8 @@ namespace gr {
        * The normalized gain is always in [0, 1], regardless of the device.
        * See also set_normalized_gain().
        *
-       * Note that it is not possible to specify a gain name for this function,
-       * the result is over the entire gain chain.
+       * Note that it is not possible to specify a gain name for
+       * this function, the result is over the entire gain chain.
        *
        * \param chan the channel index 0 to N-1
        */
@@ -292,6 +190,7 @@ namespace gr {
 
       /*!
        * Get the actual dboard gain setting of named stage.
+       *
        * \param chan the channel index 0 to N-1
        * \return the actual gain in dB
        */
@@ -299,6 +198,7 @@ namespace gr {
 
       /*!
        * Get the settable gain range.
+       *
        * \param chan the channel index 0 to N-1
        * \return the gain range in dB
        */
@@ -306,6 +206,7 @@ namespace gr {
 
       /*!
        * Get the settable gain range.
+       *
        * \param name the name of the gain stage
        * \param chan the channel index 0 to N-1
        * \return the gain range in dB
@@ -314,7 +215,8 @@ namespace gr {
                                                  size_t chan = 0) = 0;
 
       /*!
-       * Set the antenna to use.
+       * Set the antenna to use for a given channel.
+       *
        * \param ant the antenna string
        * \param chan the channel index 0 to N-1
        */
@@ -323,13 +225,15 @@ namespace gr {
 
       /*!
        * Get the antenna in use.
+       *
        * \param chan the channel index 0 to N-1
        * \return the antenna string
        */
       virtual std::string get_antenna(size_t chan = 0) = 0;
 
       /*!
-       * Get a list of possible antennas.
+       * Get a list of possible antennas on a given channel.
+       *
        * \param chan the channel index 0 to N-1
        * \return a vector of antenna strings
        */
@@ -337,6 +241,7 @@ namespace gr {
 
       /*!
        * Set the bandpass filter on the RF frontend.
+       *
        * \param bandwidth the filter bandwidth in Hz
        * \param chan the channel index 0 to N-1
        */
@@ -344,6 +249,7 @@ namespace gr {
 
       /*!
        * Get the bandpass filter setting on the RF frontend.
+       *
        * \param chan the channel index 0 to N-1
        * \return bandwidth of the filter in Hz
        */
@@ -351,31 +257,13 @@ namespace gr {
 
       /*!
        * Get the bandpass filter range of the RF frontend.
+       *
        * \param chan the channel index 0 to N-1
        * \return the range of the filter bandwidth in Hz
        */
       virtual ::uhd::freq_range_t get_bandwidth_range(size_t chan = 0) = 0;
 
       /*!
-       * Set a constant DC offset value.
-       * The value is complex to control both I and Q.
-       * \param offset the dc offset (1.0 is full-scale)
-       * \param chan the channel index 0 to N-1
-       */
-      virtual void set_dc_offset(const std::complex<double> &offset,
-                                 size_t chan = 0) = 0;
-
-      /*!
-       * Set the RX frontend IQ imbalance correction.
-       * Use this to adjust the magnitude and phase of I and Q.
-       *
-       * \param correction the complex correction (1.0 is full-scale)
-       * \param chan the channel index 0 to N-1
-       */
-      virtual void set_iq_balance(const std::complex<double> &correction,
-                                  size_t chan = 0) = 0;
-
-      /*!
        * Get an RF frontend sensor value.
        * \param name the name of the sensor
        * \param chan the channel index 0 to N-1
@@ -406,6 +294,7 @@ namespace gr {
 
       /*!
        * Get a motherboard sensor value.
+       *
        * \param name the name of the sensor
        * \param mboard the motherboard index 0 to M-1
        * \return a sensor value object
@@ -415,33 +304,15 @@ namespace gr {
 
       /*!
        * Get a list of possible motherboard sensor names.
+       *
        * \param mboard the motherboard index 0 to M-1
        * \return a vector of sensor names
        */
       virtual std::vector<std::string> get_mboard_sensor_names(size_t mboard = 
0) = 0;
 
       /*!
-       * Set the clock configuration.
-       * DEPRECATED for set_time/clock_source.
-       * \param clock_config the new configuration
-       * \param mboard the motherboard index 0 to M-1
-       */
-      virtual void set_clock_config(const ::uhd::clock_config_t &clock_config,
-                                    size_t mboard = 0) = 0;
-
-      /*!
-       * Set the time source for the usrp device.
-       * This sets the method of time synchronization,
-       * typically a pulse per second or an encoded time.
-       * Typical options for source: external, MIMO.
-       * \param source a string representing the time source
-       * \param mboard which motherboard to set the config
-       */
-      virtual void set_time_source(const std::string &source,
-                                   const size_t mboard = 0) = 0;
-
-      /*!
        * Get the currently set time source.
+       *
        * \param mboard which motherboard to get the config
        * \return the string representing the time source
        */
@@ -449,6 +320,7 @@ namespace gr {
 
       /*!
        * Get a list of possible time sources.
+       *
        * \param mboard which motherboard to get the list
        * \return a vector of strings for possible settings
        */
@@ -456,8 +328,10 @@ namespace gr {
 
       /*!
        * Set the clock source for the usrp device.
-       * This sets the source for a 10 Mhz reference clock.
+       *
+       * This sets the source for a 10 MHz reference clock.
        * Typical options for source: internal, external, MIMO.
+       *
        * \param source a string representing the clock source
        * \param mboard which motherboard to set the config
        */
@@ -466,6 +340,7 @@ namespace gr {
 
       /*!
        * Get the currently set clock source.
+       *
        * \param mboard which motherboard to get the config
        * \return the string representing the clock source
        */
@@ -473,6 +348,7 @@ namespace gr {
 
       /*!
        * Get a list of possible clock sources.
+       *
        * \param mboard which motherboard to get the list
        * \return a vector of strings for possible settings
        */
@@ -480,6 +356,7 @@ namespace gr {
 
       /*!
        * Get the master clock rate.
+       *
        * \param mboard the motherboard index 0 to M-1
        * \return the clock rate in Hz
        */
@@ -487,6 +364,7 @@ namespace gr {
 
       /*!
        * Set the master clock rate.
+       *
        * \param rate the new rate in Hz
        * \param mboard the motherboard index 0 to M-1
        */
@@ -494,6 +372,7 @@ namespace gr {
 
       /*!
        * Get the current time registers.
+       *
        * \param mboard the motherboard index 0 to M-1
        * \return the current usrp time
        */
@@ -547,6 +426,7 @@ namespace gr {
 
       /*!
        * Get access to the underlying uhd dboard iface object.
+       *
        * \return the dboard_iface object
        */
       virtual ::uhd::usrp::dboard_iface::sptr get_dboard_iface(size_t chan = 
0) = 0;
@@ -563,6 +443,7 @@ namespace gr {
        * Perform write on the user configuration register bus. These
        * only exist if the user has implemented custom setting
        * registers in the device FPGA.
+       *
        * \param addr 8-bit register address
        * \param data 32-bit register value
        * \param mboard which motherboard to set the user register
@@ -572,6 +453,28 @@ namespace gr {
                                      size_t mboard = 0) = 0;
 
       /*!
+       * Set the clock configuration.
+       *
+       * DEPRECATED for set_time/clock_source.
+       * \param clock_config the new configuration
+       * \param mboard the motherboard index 0 to M-1
+       */
+      virtual void set_clock_config(const ::uhd::clock_config_t &clock_config,
+                                    size_t mboard = 0) = 0;
+
+      /*!
+       * Set the time source for the USRP device.
+       *
+       * This sets the method of time synchronization,
+       * typically a pulse per second or an encoded time.
+       * Typical options for source: external, MIMO.
+       * \param source a string representing the time source
+       * \param mboard which motherboard to set the config
+       */
+      virtual void set_time_source(const std::string &source,
+                                   const size_t mboard = 0) = 0;
+
+      /*!
        * Update the stream args for this device.
        *
        * This update will only take effect after a restart of the
@@ -587,9 +490,10 @@ namespace gr {
        * \throws std::runtime_error if new settings are invalid.
        */
       virtual void set_stream_args(const ::uhd::stream_args_t &stream_args) = 
0;
+
     };
 
   } /* namespace uhd */
 } /* namespace gr */
 
-#endif /* INCLUDED_GR_UHD_USRP_SINK_H */
+#endif /* INCLUDED_GR_UHD_USRP_BLOCK_H */
diff --git a/gr-uhd/include/gnuradio/uhd/usrp_sink.h 
b/gr-uhd/include/gnuradio/uhd/usrp_sink.h
index dd1bd6a..405922b 100644
--- a/gr-uhd/include/gnuradio/uhd/usrp_sink.h
+++ b/gr-uhd/include/gnuradio/uhd/usrp_sink.h
@@ -23,9 +23,7 @@
 #ifndef INCLUDED_GR_UHD_USRP_SINK_H
 #define INCLUDED_GR_UHD_USRP_SINK_H
 
-#include <gnuradio/uhd/api.h>
-#include <gnuradio/sync_block.h>
-#include <uhd/usrp/multi_usrp.hpp>
+#include <gnuradio/uhd/usrp_block.h>
 
 // TODO In 3.8, UHD 3.4 will be required and we can remove all these ifdefs
 #ifndef INCLUDED_UHD_STREAM_HPP
@@ -54,7 +52,7 @@ namespace gr {
 
     class uhd_usrp_sink;
 
-    class GR_UHD_API usrp_sink : virtual public sync_block
+    class GR_UHD_API usrp_sink : virtual public usrp_block
     {
     public:
       // gr::uhd::usrp_sink::sptr
@@ -158,205 +156,6 @@ namespace gr {
       virtual ::uhd::dict<std::string, std::string> get_usrp_info(size_t chan 
= 0) = 0;
 
       /*!
-       * Set the frontend specification.
-       * \param spec the subdev spec markup string
-       * \param mboard the motherboard index 0 to M-1
-       */
-      virtual void set_subdev_spec(const std::string &spec, size_t mboard = 0) 
= 0;
-
-      /*!
-       * Get the TX frontend specification.
-       * \param mboard the motherboard index 0 to M-1
-       * \return the frontend specification in use
-       */
-      virtual std::string get_subdev_spec (size_t mboard = 0) = 0;
-
-      /*!
-       * Set the sample rate for the usrp device.
-       * \param rate a new rate in Sps
-       */
-      virtual void set_samp_rate(double rate) = 0;
-
-      /*!
-       * Get the sample rate for the usrp device.
-       * This is the actual sample rate and may differ from the rate set.
-       * \return the actual rate in Sps
-       */
-      virtual double get_samp_rate(void) = 0;
-
-      /*!
-       * Get the possible sample rates for the usrp device.
-       * \return a range of rates in Sps
-       */
-      virtual ::uhd::meta_range_t get_samp_rates(void) = 0;
-
-      /*!
-       * Tune the usrp device to the desired center frequency.
-       * \param tune_request the tune request instructions
-       * \param chan the channel index 0 to N-1
-       * \return a tune result with the actual frequencies
-       */
-      virtual ::uhd::tune_result_t set_center_freq
-        (const ::uhd::tune_request_t tune_request, size_t chan = 0) = 0;
-
-      /*!
-       * Tune the usrp device to the desired center frequency.
-       * This is a wrapper around set center freq so that in this case,
-       * the user can pass a single frequency in the call through swig.
-       * \param freq the desired frequency in Hz
-       * \param chan the channel index 0 to N-1
-       * \return a tune result with the actual frequencies
-       */
-      ::uhd::tune_result_t set_center_freq(double freq, size_t chan = 0)
-      {
-        return set_center_freq(::uhd::tune_request_t(freq), chan);
-      }
-
-      /*!
-       * Get the center frequency.
-       * \param chan the channel index 0 to N-1
-       * \return the frequency in Hz
-       */
-      virtual double get_center_freq(size_t chan = 0) = 0;
-
-      /*!
-       * Get the tunable frequency range.
-       * \param chan the channel index 0 to N-1
-       * \return the frequency range in Hz
-       */
-      virtual ::uhd::freq_range_t get_freq_range(size_t chan = 0) = 0;
-
-      /*!
-       * Set the gain for the dboard.
-       * \param gain the gain in dB
-       * \param chan the channel index 0 to N-1
-       */
-      virtual void set_gain(double gain, size_t chan = 0) = 0;
-
-      /*!
-       * Set the named gain on the dboard.
-       * \param gain the gain in dB
-       * \param name the name of the gain stage
-       * \param chan the channel index 0 to N-1
-       */
-      virtual void set_gain(double gain,
-                            const std::string &name,
-                            size_t chan = 0) = 0;
-
-      /*!
-       * Set the normalized gain.
-       *
-       * The normalized gain is always in [0, 1], regardless of the device.
-       * 0 corresponds to minimum gain (usually 0 dB, but make sure to read 
the device
-       * notes in the UHD manual) and 1 corresponds to maximum gain.
-       * This will work for any UHD device. Use get_gain() to see which dB 
value
-       * the normalized gain value corresponds to.
-       *
-       * Note that it is not possible to specify a gain name for this function.
-       *
-       * \throws A runtime_error if \p norm_gain is not within the valid range.
-       *
-       * \param norm_gain the gain in fractions of the gain range (must be 0 
<= norm_gain <= 1)
-       * \param chan the channel index 0 to N-1
-       */
-      virtual void set_normalized_gain(double norm_gain, size_t chan = 0) = 0;
-
-      /*!
-       * Get the actual dboard gain setting.
-       * \param chan the channel index 0 to N-1
-       * \return the actual gain in dB
-       */
-      virtual double get_gain(size_t chan = 0) = 0;
-
-      /*!
-       * Get the actual dboard gain setting of named stage.
-       * \param name the name of the gain stage
-       * \param chan the channel index 0 to N-1
-       * \return the actual gain in dB
-       */
-      virtual double get_gain(const std::string &name,
-                              size_t chan = 0) = 0;
-
-      /*!
-       * Returns the normalized gain.
-       *
-       * The normalized gain is always in [0, 1], regardless of the device.
-       * See also set_normalized_gain().
-       *
-       * Note that it is not possible to specify a gain name for this function,
-       * the result is over the entire gain chain.
-       *
-       * \param chan the channel index 0 to N-1
-       */
-      virtual double get_normalized_gain(size_t chan = 0) = 0;
-
-      /*!
-       * Get the actual dboard gain setting of named stage.
-       * \param chan the channel index 0 to N-1
-       * \return the actual gain in dB
-       */
-      virtual std::vector<std::string> get_gain_names(size_t chan = 0) = 0;
-
-      /*!
-       * Get the settable gain range.
-       * \param chan the channel index 0 to N-1
-       * \return the gain range in dB
-       */
-      virtual ::uhd::gain_range_t get_gain_range(size_t chan = 0) = 0;
-
-      /*!
-       * Get the settable gain range.
-       * \param name the name of the gain stage
-       * \param chan the channel index 0 to N-1
-       * \return the gain range in dB
-       */
-      virtual ::uhd::gain_range_t get_gain_range(const std::string &name,
-                                                 size_t chan = 0) = 0;
-
-      /*!
-       * Set the antenna to use.
-       * \param ant the antenna string
-       * \param chan the channel index 0 to N-1
-       */
-      virtual void set_antenna(const std::string &ant,
-                               size_t chan = 0) = 0;
-
-      /*!
-       * Get the antenna in use.
-       * \param chan the channel index 0 to N-1
-       * \return the antenna string
-       */
-      virtual std::string get_antenna(size_t chan = 0) = 0;
-
-      /*!
-       * Get a list of possible antennas.
-       * \param chan the channel index 0 to N-1
-       * \return a vector of antenna strings
-       */
-      virtual std::vector<std::string> get_antennas(size_t chan = 0) = 0;
-
-      /*!
-       * Set the bandpass filter on the RF frontend.
-       * \param bandwidth the filter bandwidth in Hz
-       * \param chan the channel index 0 to N-1
-       */
-      virtual void set_bandwidth(double bandwidth, size_t chan = 0) = 0;
-
-      /*!
-       * Get the bandpass filter setting on the RF frontend.
-       * \param chan the channel index 0 to N-1
-       * \return bandwidth of the filter in Hz
-       */
-      virtual double get_bandwidth(size_t chan = 0) = 0;
-
-      /*!
-       * Get the bandpass filter range of the RF frontend.
-       * \param chan the channel index 0 to N-1
-       * \return the range of the filter bandwidth in Hz
-       */
-      virtual ::uhd::freq_range_t get_bandwidth_range(size_t chan = 0) = 0;
-
-      /*!
        * Set a constant DC offset value.
        * The value is complex to control both I and Q.
        * \param offset the dc offset (1.0 is full-scale)
@@ -375,218 +174,6 @@ namespace gr {
       virtual void set_iq_balance(const std::complex<double> &correction,
                                   size_t chan = 0) = 0;
 
-      /*!
-       * Get an RF frontend sensor value.
-       * \param name the name of the sensor
-       * \param chan the channel index 0 to N-1
-       * \return a sensor value object
-       */
-      virtual ::uhd::sensor_value_t get_sensor(const std::string &name,
-                                               size_t chan = 0) = 0;
-
-      /*!
-       * Get a list of possible RF frontend sensor names.
-       * \param chan the channel index 0 to N-1
-       * \return a vector of sensor names
-       */
-      virtual std::vector<std::string> get_sensor_names(size_t chan = 0) = 0;
-
-      //! DEPRECATED use get_sensor
-      ::uhd::sensor_value_t get_dboard_sensor(const std::string &name,
-                                              size_t chan = 0)
-      {
-        return this->get_sensor(name, chan);
-      }
-
-      //! DEPRECATED use get_sensor_names
-      std::vector<std::string> get_dboard_sensor_names(size_t chan = 0)
-      {
-        return this->get_sensor_names(chan);
-      }
-
-      /*!
-       * Get a motherboard sensor value.
-       * \param name the name of the sensor
-       * \param mboard the motherboard index 0 to M-1
-       * \return a sensor value object
-       */
-      virtual ::uhd::sensor_value_t get_mboard_sensor(const std::string &name,
-                                                      size_t mboard = 0) = 0;
-
-      /*!
-       * Get a list of possible motherboard sensor names.
-       * \param mboard the motherboard index 0 to M-1
-       * \return a vector of sensor names
-       */
-      virtual std::vector<std::string> get_mboard_sensor_names(size_t mboard = 
0) = 0;
-
-      /*!
-       * Set the clock configuration.
-       * DEPRECATED for set_time/clock_source.
-       * \param clock_config the new configuration
-       * \param mboard the motherboard index 0 to M-1
-       */
-      virtual void set_clock_config(const ::uhd::clock_config_t &clock_config,
-                                    size_t mboard = 0) = 0;
-
-      /*!
-       * Set the time source for the usrp device.
-       * This sets the method of time synchronization,
-       * typically a pulse per second or an encoded time.
-       * Typical options for source: external, MIMO.
-       * \param source a string representing the time source
-       * \param mboard which motherboard to set the config
-       */
-      virtual void set_time_source(const std::string &source,
-                                   const size_t mboard = 0) = 0;
-
-      /*!
-       * Get the currently set time source.
-       * \param mboard which motherboard to get the config
-       * \return the string representing the time source
-       */
-      virtual std::string get_time_source(const size_t mboard) = 0;
-
-      /*!
-       * Get a list of possible time sources.
-       * \param mboard which motherboard to get the list
-       * \return a vector of strings for possible settings
-       */
-      virtual std::vector<std::string> get_time_sources(const size_t mboard) = 
0;
-
-      /*!
-       * Set the clock source for the usrp device.
-       * This sets the source for a 10 Mhz reference clock.
-       * Typical options for source: internal, external, MIMO.
-       * \param source a string representing the clock source
-       * \param mboard which motherboard to set the config
-       */
-      virtual void set_clock_source(const std::string &source,
-                                    const size_t mboard = 0) = 0;
-
-      /*!
-       * Get the currently set clock source.
-       * \param mboard which motherboard to get the config
-       * \return the string representing the clock source
-       */
-      virtual std::string get_clock_source(const size_t mboard) = 0;
-
-      /*!
-       * Get a list of possible clock sources.
-       * \param mboard which motherboard to get the list
-       * \return a vector of strings for possible settings
-       */
-      virtual std::vector<std::string> get_clock_sources(const size_t mboard) 
= 0;
-
-      /*!
-       * Get the master clock rate.
-       * \param mboard the motherboard index 0 to M-1
-       * \return the clock rate in Hz
-       */
-      virtual double get_clock_rate(size_t mboard = 0) = 0;
-
-      /*!
-       * Set the master clock rate.
-       * \param rate the new rate in Hz
-       * \param mboard the motherboard index 0 to M-1
-       */
-      virtual void set_clock_rate(double rate, size_t mboard = 0) = 0;
-
-      /*!
-       * Get the current time registers.
-       * \param mboard the motherboard index 0 to M-1
-       * \return the current usrp time
-       */
-      virtual ::uhd::time_spec_t get_time_now(size_t mboard = 0) = 0;
-
-      /*!
-       * Get the time when the last pps pulse occured.
-       * \param mboard the motherboard index 0 to M-1
-       * \return the current usrp time
-       */
-      virtual ::uhd::time_spec_t get_time_last_pps(size_t mboard = 0) = 0;
-
-      /*!
-       * Sets the time registers immediately.
-       * \param time_spec the new time
-       * \param mboard the motherboard index 0 to M-1
-       */
-      virtual void set_time_now(const ::uhd::time_spec_t &time_spec, size_t 
mboard = 0) = 0;
-
-      /*!
-       * Set the time registers at the next pps.
-       * \param time_spec the new time
-       */
-      virtual void set_time_next_pps(const ::uhd::time_spec_t &time_spec) = 0;
-
-      /*!
-       * Sync the time registers with an unknown pps edge.
-       * \param time_spec the new time
-       */
-      virtual void set_time_unknown_pps(const ::uhd::time_spec_t &time_spec) = 
0;
-
-      /*!
-       * Set the time at which the control commands will take effect.
-       *
-       * A timed command will back-pressure all subsequent timed commands,
-       * assuming that the subsequent commands occur within the time-window.
-       * If the time spec is late, the command will be activated upon arrival.
-       *
-       * \param time_spec the time at which the next command will activate
-       * \param mboard which motherboard to set the config
-       */
-      virtual void set_command_time(const ::uhd::time_spec_t &time_spec,
-                                    size_t mboard = 0) = 0;
-
-      /*!
-       * Clear the command time so future commands are sent ASAP.
-       *
-       * \param mboard which motherboard to set the config
-       */
-      virtual void clear_command_time(size_t mboard = 0) = 0;
-
-      /*!
-       * Get access to the underlying uhd dboard iface object.
-       * \return the dboard_iface object
-       */
-      virtual ::uhd::usrp::dboard_iface::sptr get_dboard_iface(size_t chan = 
0) = 0;
-
-      /*!
-       * Get access to the underlying uhd device object.
-       *
-       * NOTE: This function is only available in C++.
-       * \return the multi usrp device object
-       */
-      virtual ::uhd::usrp::multi_usrp::sptr get_device(void) = 0;
-
-      /*!
-       * Perform write on the user configuration register bus. These
-       * only exist if the user has implemented custom setting
-       * registers in the device FPGA.
-       * \param addr 8-bit register address
-       * \param data 32-bit register value
-       * \param mboard which motherboard to set the user register
-       */
-      virtual void set_user_register(const uint8_t addr,
-                                     const uint32_t data,
-                                     size_t mboard = 0) = 0;
-
-      /*!
-       * Update the stream args for this device.
-       *
-       * This update will only take effect after a restart of the
-       * streaming, or before streaming and after construction.
-       * This will also delete the current streamer.
-       * Note you cannot change the I/O signature of this block using
-       * this function, or it will throw.
-       *
-       * It is possible to leave the 'channels' fields of \p stream_args
-       * unset. In this case, the previous channels field is used.
-       *
-       * \param stream_args New stream args.
-       * \throws std::runtime_error if new settings are invalid.
-       */
-      virtual void set_stream_args(const ::uhd::stream_args_t &stream_args) = 
0;
     };
 
   } /* namespace uhd */
diff --git a/gr-uhd/include/gnuradio/uhd/usrp_source.h 
b/gr-uhd/include/gnuradio/uhd/usrp_source.h
index 7da3968..5a9c81a 100644
--- a/gr-uhd/include/gnuradio/uhd/usrp_source.h
+++ b/gr-uhd/include/gnuradio/uhd/usrp_source.h
@@ -23,9 +23,7 @@
 #ifndef INCLUDED_GR_UHD_USRP_SOURCE_H
 #define INCLUDED_GR_UHD_USRP_SOURCE_H
 
-#include <gnuradio/uhd/api.h>
-#include <gnuradio/sync_block.h>
-#include <uhd/usrp/multi_usrp.hpp>
+#include <gnuradio/uhd/usrp_block.h>
 
 // TODO In 3.8, UHD 3.4 will be required and we can remove all these ifdefs
 #ifndef INCLUDED_UHD_STREAM_HPP
@@ -54,7 +52,7 @@ namespace gr {
 
     class uhd_usrp_source;
 
-    class GR_UHD_API usrp_source : virtual public sync_block
+    class GR_UHD_API usrp_source : virtual public usrp_block
     {
     public:
       // gr::uhd::usrp_source::sptr
@@ -137,205 +135,6 @@ namespace gr {
       virtual ::uhd::dict<std::string, std::string> get_usrp_info(size_t chan 
= 0) = 0;
 
       /*!
-       * Set the frontend specification.
-       * \param spec the subdev spec markup string
-       * \param mboard the motherboard index 0 to M-1
-       */
-      virtual void set_subdev_spec(const std::string &spec, size_t mboard = 0) 
= 0;
-
-      /*!
-       * Get the RX frontend specification.
-       * \param mboard the motherboard index 0 to M-1
-       * \return the frontend specification in use
-       */
-      virtual std::string get_subdev_spec(size_t mboard = 0) = 0;
-
-      /*!
-       * Set the sample rate for the usrp device.
-       * \param rate a new rate in Sps
-       */
-      virtual void set_samp_rate(double rate) = 0;
-
-      /*!
-       * Get the sample rate for the usrp device.
-       * This is the actual sample rate and may differ from the rate set.
-       * \return the actual rate in Sps
-       */
-      virtual double get_samp_rate(void) = 0;
-
-      /*!
-       * Get the possible sample rates for the usrp device.
-       * \return a range of rates in Sps
-       */
-      virtual ::uhd::meta_range_t get_samp_rates(void) = 0;
-
-      /*!
-       * Tune the usrp device to the desired center frequency.
-       * \param tune_request the tune request instructions
-       * \param chan the channel index 0 to N-1
-       * \return a tune result with the actual frequencies
-       */
-      virtual ::uhd::tune_result_t set_center_freq
-        (const ::uhd::tune_request_t tune_request, size_t chan = 0) = 0;
-
-      /*!
-       * Tune the usrp device to the desired center frequency.
-       * This is a wrapper around set center freq so that in this case,
-       * the user can pass a single frequency in the call through swig.
-       * \param freq the desired frequency in Hz
-       * \param chan the channel index 0 to N-1
-       * \return a tune result with the actual frequencies
-       */
-      ::uhd::tune_result_t set_center_freq(double freq, size_t chan = 0)
-      {
-        return set_center_freq(::uhd::tune_request_t(freq), chan);
-      }
-
-      /*!
-       * Get the center frequency.
-       * \param chan the channel index 0 to N-1
-       * \return the frequency in Hz
-       */
-      virtual double get_center_freq(size_t chan = 0) = 0;
-
-      /*!
-       * Get the tunable frequency range.
-       * \param chan the channel index 0 to N-1
-       * \return the frequency range in Hz
-       */
-      virtual ::uhd::freq_range_t get_freq_range(size_t chan = 0) = 0;
-
-      /*!
-       * Set the gain for the dboard.
-       * \param gain the gain in dB
-       * \param chan the channel index 0 to N-1
-       */
-      virtual void set_gain(double gain, size_t chan = 0) = 0;
-
-      /*!
-       * Set the named gain on the dboard.
-       * \param gain the gain in dB
-       * \param name the name of the gain stage
-       * \param chan the channel index 0 to N-1
-       */
-      virtual void set_gain(double gain,
-                            const std::string &name,
-                            size_t chan = 0) = 0;
-
-      /*!
-       * Set the normalized gain.
-       *
-       * The normalized gain is always in [0, 1], regardless of the device.
-       * 0 corresponds to minimum gain (usually 0 dB, but make sure to read 
the device
-       * notes in the UHD manual) and 1 corresponds to maximum gain.
-       * This will work for any UHD device. Use get_gain() to see which dB 
value
-       * the normalized gain value corresponds to.
-       *
-       * Note that it is not possible to specify a gain name for this function.
-       *
-       * \throws A runtime_error if \p norm_gain is not within the valid range.
-       *
-       * \param norm_gain the gain in fractions of the gain range (must be 0 
<= norm_gain <= 1)
-       * \param chan the channel index 0 to N-1
-       */
-      virtual void set_normalized_gain(double norm_gain, size_t chan = 0) = 0;
-
-      /*!
-       * Get the actual dboard gain setting.
-       * \param chan the channel index 0 to N-1
-       * \return the actual gain in dB
-       */
-      virtual double get_gain(size_t chan = 0) = 0;
-
-      /*!
-       * Get the actual dboard gain setting of named stage.
-       * \param name the name of the gain stage
-       * \param chan the channel index 0 to N-1
-       * \return the actual gain in dB
-       */
-      virtual double get_gain(const std::string &name,
-                              size_t chan = 0) = 0;
-
-      /*!
-       * Returns the normalized gain.
-       *
-       * The normalized gain is always in [0, 1], regardless of the device.
-       * See also set_normalized_gain().
-       *
-       * Note that it is not possible to specify a gain name for this function,
-       * the result is over the entire gain chain.
-       *
-       * \param chan the channel index 0 to N-1
-       */
-      virtual double get_normalized_gain(size_t chan = 0) = 0;
-
-      /*!
-       * Get the actual dboard gain setting of named stage.
-       * \param chan the channel index 0 to N-1
-       * \return the actual gain in dB
-       */
-      virtual std::vector<std::string> get_gain_names(size_t chan = 0) = 0;
-
-      /*!
-       * Get the settable gain range.
-       * \param chan the channel index 0 to N-1
-       * \return the gain range in dB
-       */
-      virtual ::uhd::gain_range_t get_gain_range(size_t chan = 0) = 0;
-
-      /*!
-       * Get the settable gain range.
-       * \param name the name of the gain stage
-       * \param chan the channel index 0 to N-1
-       * \return the gain range in dB
-       */
-      virtual ::uhd::gain_range_t get_gain_range(const std::string &name,
-                                               size_t chan = 0) = 0;
-
-      /*!
-       * Set the antenna to use.
-       * \param ant the antenna string
-       * \param chan the channel index 0 to N-1
-       */
-      virtual void set_antenna(const std::string &ant,
-                               size_t chan = 0) = 0;
-
-      /*!
-       * Get the antenna in use.
-       * \param chan the channel index 0 to N-1
-       * \return the antenna string
-       */
-      virtual std::string get_antenna(size_t chan = 0) = 0;
-
-      /*!
-       * Get a list of possible antennas.
-       * \param chan the channel index 0 to N-1
-       * \return a vector of antenna strings
-       */
-      virtual std::vector<std::string> get_antennas(size_t chan = 0) = 0;
-
-      /*!
-       * Set the bandpass filter on the RF frontend.
-       * \param bandwidth the filter bandwidth in Hz
-       * \param chan the channel index 0 to N-1
-       */
-      virtual void set_bandwidth(double bandwidth, size_t chan = 0) = 0;
-
-      /*!
-       * Get the bandpass filter setting on the RF frontend.
-       * \param chan the channel index 0 to N-1
-       * \return bandwidth of the filter in Hz
-       */
-      virtual double get_bandwidth(size_t chan = 0) = 0;
-
-      /*!
-       * Get the bandpass filter range of the RF frontend.
-       * \param chan the channel index 0 to N-1
-       * \return the range of the filter bandwidth in Hz
-       */
-      virtual ::uhd::freq_range_t get_bandwidth_range(size_t chan = 0) = 0;
-
-      /*!
        * Enable/disable the automatic DC offset correction.
        * The automatic correction subtracts out the long-run average.
        *
@@ -377,221 +176,6 @@ namespace gr {
                                   size_t chan = 0) = 0;
 
       /*!
-       * Get a RF frontend sensor value.
-       * \param name the name of the sensor
-       * \param chan the channel index 0 to N-1
-       * \return a sensor value object
-       */
-      virtual ::uhd::sensor_value_t get_sensor(const std::string &name,
-                                               size_t chan = 0) = 0;
-
-      /*!
-       * Get a list of possible RF frontend sensor names.
-       * \param chan the channel index 0 to N-1
-       * \return a vector of sensor names
-       */
-      virtual std::vector<std::string> get_sensor_names(size_t chan = 0) = 0;
-
-      //! DEPRECATED use get_sensor
-      ::uhd::sensor_value_t get_dboard_sensor(const std::string &name,
-                                            size_t chan = 0)
-      {
-        return this->get_sensor(name, chan);
-      }
-
-      //! DEPRECATED use get_sensor_names
-      std::vector<std::string> get_dboard_sensor_names(size_t chan = 0)
-      {
-        return this->get_sensor_names(chan);
-      }
-
-      /*!
-       * Get a motherboard sensor value.
-       * \param name the name of the sensor
-       * \param mboard the motherboard index 0 to M-1
-       * \return a sensor value object
-       */
-      virtual ::uhd::sensor_value_t get_mboard_sensor(const std::string &name,
-                                                      size_t mboard = 0) = 0;
-
-      /*!
-       * Get a list of possible motherboard sensor names.
-       * \param mboard the motherboard index 0 to M-1
-       * \return a vector of sensor names
-       */
-      virtual std::vector<std::string> get_mboard_sensor_names(size_t mboard = 
0) = 0;
-
-      /*!
-       * Set the clock configuration.
-       * DEPRECATED for set_time/clock_source.
-       * \param clock_config the new configuration
-       * \param mboard the motherboard index 0 to M-1
-       */
-      virtual void set_clock_config(const ::uhd::clock_config_t &clock_config,
-                                    size_t mboard = 0) = 0;
-
-      /*!
-       * Set the time source for the usrp device.
-       * This sets the method of time synchronization,
-       * typically a pulse per second or an encoded time.
-       * Typical options for source: external, MIMO.
-       * \param source a string representing the time source
-       * \param mboard which motherboard to set the config
-       */
-      virtual void set_time_source(const std::string &source,
-                                   const size_t mboard = 0) = 0;
-
-      /*!
-       * Get the currently set time source.
-       * \param mboard which motherboard to get the config
-       * \return the string representing the time source
-       */
-      virtual std::string get_time_source(const size_t mboard) = 0;
-
-      /*!
-       * Get a list of possible time sources.
-       * \param mboard which motherboard to get the list
-       * \return a vector of strings for possible settings
-       */
-      virtual std::vector<std::string> get_time_sources(const size_t mboard) = 
0;
-
-      /*!
-       * Set the clock source for the usrp device.
-       * This sets the source for a 10 Mhz reference clock.
-       * Typical options for source: internal, external, MIMO.
-       * \param source a string representing the clock source
-       * \param mboard which motherboard to set the config
-       */
-      virtual void set_clock_source(const std::string &source,
-                                    const size_t mboard = 0) = 0;
-
-      /*!
-       * Get the currently set clock source.
-       * \param mboard which motherboard to get the config
-       * \return the string representing the clock source
-       */
-      virtual std::string get_clock_source(const size_t mboard) = 0;
-
-      /*!
-       * Get a list of possible clock sources.
-       * \param mboard which motherboard to get the list
-       * \return a vector of strings for possible settings
-       */
-      virtual std::vector<std::string> get_clock_sources(const size_t mboard) 
= 0;
-
-      /*!
-       * Get the master clock rate.
-       * \param mboard the motherboard index 0 to M-1
-       * \return the clock rate in Hz
-       */
-      virtual double get_clock_rate(size_t mboard = 0) = 0;
-
-      /*!
-       * Set the master clock rate.
-       * \param rate the new rate in Hz
-       * \param mboard the motherboard index 0 to M-1
-       */
-      virtual void set_clock_rate(double rate, size_t mboard = 0) = 0;
-
-      /*!
-       * Get the current time registers.
-       * \param mboard the motherboard index 0 to M-1
-       * \return the current usrp time
-       */
-      virtual ::uhd::time_spec_t get_time_now(size_t mboard = 0) = 0;
-
-      /*!
-       * Get the time when the last pps pulse occured.
-       * \param mboard the motherboard index 0 to M-1
-       * \return the current usrp time
-       */
-      virtual ::uhd::time_spec_t get_time_last_pps(size_t mboard = 0) = 0;
-
-      /*!
-       * Sets the time registers immediately.
-       * \param time_spec the new time
-       * \param mboard the motherboard index 0 to M-1
-       */
-      virtual void set_time_now(const ::uhd::time_spec_t &time_spec,
-                                size_t mboard = 0) = 0;
-
-      /*!
-       * Set the time registers at the next pps.
-       * \param time_spec the new time
-       */
-      virtual void set_time_next_pps(const ::uhd::time_spec_t &time_spec) = 0;
-
-      /*!
-       * Sync the time registers with an unknown pps edge.
-       * \param time_spec the new time
-       */
-      virtual void set_time_unknown_pps(const ::uhd::time_spec_t &time_spec) = 
0;
-
-      /*!
-       * Set the time at which the control commands will take effect.
-       *
-       * A timed command will back-pressure all subsequent timed
-       * commands, assuming that the subsequent commands occur within
-       * the time-window. If the time spec is late, the command will
-       * be activated upon arrival.
-       *
-       * \param time_spec the time at which the next command will activate
-       * \param mboard which motherboard to set the config
-       */
-      virtual void set_command_time(const ::uhd::time_spec_t &time_spec,
-                                    size_t mboard = 0) = 0;
-
-      /*!
-       * Clear the command time so future commands are sent ASAP.
-       *
-       * \param mboard which motherboard to set the config
-       */
-      virtual void clear_command_time(size_t mboard = 0) = 0;
-
-      /*!
-       * Get access to the underlying uhd dboard iface object.
-       * \return the dboard_iface object
-       */
-      virtual ::uhd::usrp::dboard_iface::sptr get_dboard_iface(size_t chan = 
0) = 0;
-
-      /*!
-       * Get access to the underlying uhd device object.
-       *
-       * NOTE: This function is only available in C++.
-       * \return the multi usrp device object
-       */
-      virtual ::uhd::usrp::multi_usrp::sptr get_device(void) = 0;
-
-      /*!
-       * Perform write on the user configuration register bus. These
-       * only exist if the user has implemented custom setting
-       * registers in the device FPGA.
-       * \param addr 8-bit register address
-       * \param data 32-bit register value
-       * \param mboard which motherboard to set the user register
-       */
-      virtual void set_user_register(const uint8_t addr,
-                                     const uint32_t data,
-                                     size_t mboard = 0) = 0;
-
-      /*!
-       * Update the stream args for this device.
-       *
-       * This update will only take effect after a restart of the
-       * streaming, or before streaming and after construction.
-       * This will also delete the current streamer.
-       * Note you cannot change the I/O signature of this block using
-       * this function, or it will throw.
-       *
-       * It is possible to leave the 'channels' fields of \p stream_args
-       * unset. In this case, the previous channels field is used.
-       *
-       * \param stream_args New stream args.
-       * \throws std::runtime_error if new settings are invalid.
-       */
-      virtual void set_stream_args(const ::uhd::stream_args_t &stream_args) = 
0;
-
-      /*!
        * Convenience function for finite data acquisition.
        * This is not to be used with the scheduler; rather,
        * one can request samples from the USRP in python.
diff --git a/gr-uhd/lib/CMakeLists.txt b/gr-uhd/lib/CMakeLists.txt
index b3ead13..531bd40 100644
--- a/gr-uhd/lib/CMakeLists.txt
+++ b/gr-uhd/lib/CMakeLists.txt
@@ -46,6 +46,7 @@ link_directories(${LOG4CPP_LIBRARY_DIRS})
 # Setup library
 ########################################################################
 list(APPEND gr_uhd_sources
+    usrp_block_impl.cc
     usrp_source_impl.cc
     usrp_sink_impl.cc
     amsg_source_impl.cc
diff --git a/gr-uhd/lib/usrp_block_impl.cc b/gr-uhd/lib/usrp_block_impl.cc
new file mode 100644
index 0000000..be24c57
--- /dev/null
+++ b/gr-uhd/lib/usrp_block_impl.cc
@@ -0,0 +1,428 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "usrp_block_impl.h"
+#include <boost/make_shared.hpp>
+
+using namespace gr::uhd;
+
+const double usrp_block_impl::LOCK_TIMEOUT = 1.5;
+
+/**********************************************************************
+ * Structors
+ *********************************************************************/
+usrp_block::usrp_block(
+    const std::string &name,
+    gr::io_signature::sptr input_signature,
+    gr::io_signature::sptr output_signature
+) : sync_block(name, input_signature, output_signature)
+{
+  // nop
+}
+
+usrp_block_impl::usrp_block_impl(
+  const ::uhd::device_addr_t &device_addr,
+  const ::uhd::stream_args_t &stream_args,
+  const std::string &ts_tag_name
+) : _stream_args(stream_args),
+    _nchan(stream_args.channels.size()),
+    _stream_now(_nchan == 1 and ts_tag_name.empty()),
+    _start_time_set(false),
+    _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),
+    _chans_to_tune(stream_args.channels.size())
+{
+  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);
+
+  _check_mboard_sensors_locked();
+
+  // Set up message ports:
+  message_port_register_in(pmt::mp("command"));
+  set_msg_handler(
+      pmt::mp("command"),
+      boost::bind(&usrp_block_impl::msg_handler_command, this, _1)
+  );
+}
+
+usrp_block_impl::~usrp_block_impl()
+{
+  // nop
+}
+
+/**********************************************************************
+ * Helpers
+ *********************************************************************/
+void usrp_block_impl::_update_stream_args(const ::uhd::stream_args_t 
&stream_args_)
+{
+  ::uhd::stream_args_t stream_args(stream_args_);
+  if (stream_args.channels.empty()) {
+    stream_args.channels = _stream_args.channels;
+  }
+  if (stream_args.cpu_format != _stream_args.cpu_format ||
+      stream_args.channels.size() != _stream_args.channels.size()) {
+    throw std::runtime_error("Cannot change I/O signatures while updating 
stream args!");
+  }
+  _stream_args = stream_args;
+}
+
+bool usrp_block_impl::_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;
+}
+
+bool usrp_block_impl::_unpack_chan_command(
+    std::string &command,
+    pmt::pmt_t &cmd_val,
+    int &chan,
+    const pmt::pmt_t &cmd_pmt
+) {
+  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;
+}
+
+bool usrp_block_impl::_check_mboard_sensors_locked()
+{
+  bool clocks_locked = true;
+
+  // 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_block_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;
+    }
+  }
+
+  return clocks_locked;
+}
+
+void
+usrp_block_impl::_set_center_freq_from_internals_allchans()
+{
+  for (size_t chan = 0; chan < _nchan; chan++) {
+    if (_chans_to_tune[chan]) {
+      _set_center_freq_from_internals(chan);
+    }
+  }
+}
+
+
+/**********************************************************************
+ * Public API calls
+ *********************************************************************/
+::uhd::sensor_value_t
+usrp_block_impl::get_mboard_sensor(const std::string &name,
+                                   size_t mboard)
+{
+  return _dev->get_mboard_sensor(name, mboard);
+}
+
+std::vector<std::string>
+usrp_block_impl::get_mboard_sensor_names(size_t mboard)
+{
+  return _dev->get_mboard_sensor_names(mboard);
+}
+
+void
+usrp_block_impl::set_clock_config(const ::uhd::clock_config_t &clock_config,
+                                 size_t mboard)
+{
+  return _dev->set_clock_config(clock_config, mboard);
+}
+
+void
+usrp_block_impl::set_time_source(const std::string &source,
+                                const size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
+  return _dev->set_time_source(source, mboard);
+#else
+  throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+std::string
+usrp_block_impl::get_time_source(const size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
+  return _dev->get_time_source(mboard);
+#else
+  throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+std::vector<std::string>
+usrp_block_impl::get_time_sources(const size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
+  return _dev->get_time_sources(mboard);
+#else
+  throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+void
+usrp_block_impl::set_clock_source(const std::string &source,
+                                 const size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
+  return _dev->set_clock_source(source, mboard);
+#else
+  throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+std::string
+usrp_block_impl::get_clock_source(const size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
+  return _dev->get_clock_source(mboard);
+#else
+  throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+std::vector<std::string>
+usrp_block_impl::get_clock_sources(const size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
+  return _dev->get_clock_sources(mboard);
+#else
+  throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+double
+usrp_block_impl::get_clock_rate(size_t mboard)
+{
+  return _dev->get_master_clock_rate(mboard);
+}
+
+void
+usrp_block_impl::set_clock_rate(double rate, size_t mboard)
+{
+  return _dev->set_master_clock_rate(rate, mboard);
+}
+
+::uhd::time_spec_t
+usrp_block_impl::get_time_now(size_t mboard)
+{
+  return _dev->get_time_now(mboard);
+}
+
+::uhd::time_spec_t
+usrp_block_impl::get_time_last_pps(size_t mboard)
+{
+  return _dev->get_time_last_pps(mboard);
+}
+
+void
+usrp_block_impl::set_time_now(const ::uhd::time_spec_t &time_spec,
+                             size_t mboard)
+{
+  return _dev->set_time_now(time_spec, mboard);
+}
+
+void
+usrp_block_impl::set_time_next_pps(const ::uhd::time_spec_t &time_spec)
+{
+  return _dev->set_time_next_pps(time_spec);
+}
+
+void
+usrp_block_impl::set_time_unknown_pps(const ::uhd::time_spec_t &time_spec)
+{
+  return _dev->set_time_unknown_pps(time_spec);
+}
+
+void
+usrp_block_impl::set_command_time(const ::uhd::time_spec_t &time_spec,
+                                 size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_COMMAND_TIME_API
+  return _dev->set_command_time(time_spec, mboard);
+#else
+  throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+void
+usrp_block_impl::clear_command_time(size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_COMMAND_TIME_API
+  return _dev->clear_command_time(mboard);
+#else
+  throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+void
+usrp_block_impl::set_user_register(const uint8_t addr,
+                                    const uint32_t data,
+                                    size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_USER_REGS_API
+  _dev->set_user_register(addr, data, mboard);
+#else
+  throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+::uhd::usrp::multi_usrp::sptr
+usrp_block_impl::get_device(void)
+{
+  return _dev;
+}
+
+/**********************************************************************
+ * External Interfaces
+ *********************************************************************/
+void
+usrp_block_impl::setup_rpc()
+{
+#ifdef GR_CTRLPORT
+  add_rpc_variable(
+    rpcbasic_sptr(new rpcbasic_register_get<usrp_block, double>(
+      alias(), "samp_rate",
+      &usrp_block::get_samp_rate,
+      pmt::mp(100000.0f), pmt::mp(25000000.0f), pmt::mp(1000000.0f),
+      "sps", "Sample Rate", RPC_PRIVLVL_MIN,
+      DISPTIME | DISPOPTSTRIP))
+  );
+
+  add_rpc_variable(
+    rpcbasic_sptr(new rpcbasic_register_set<usrp_block, double>(
+      alias(), "samp_rate",
+      &usrp_block::set_samp_rate,
+      pmt::mp(100000.0f), pmt::mp(25000000.0f), pmt::mp(1000000.0f),
+      "sps", "Sample Rate",
+      RPC_PRIVLVL_MIN, DISPNULL))
+  );
+#endif /* GR_CTRLPORT */
+}
+
+void usrp_block_impl::msg_handler_command(pmt::pmt_t msg)
+{
+  std::string command;
+  pmt::pmt_t cmd_value;
+  int chan = -1;
+  if (not _unpack_chan_command(command, cmd_value, chan, msg)) {
+    GR_LOG_ALERT(d_logger, boost::format("Error while unpacking command PMT: 
%s") % msg);
+    return;
+  }
+  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_block_impl.h b/gr-uhd/lib/usrp_block_impl.h
new file mode 100644
index 0000000..1ca613d
--- /dev/null
+++ b/gr-uhd/lib/usrp_block_impl.h
@@ -0,0 +1,199 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_UHD_BLOCK_IMPL_H
+#define INCLUDED_GR_UHD_BLOCK_IMPL_H
+
+#include <gnuradio/uhd/usrp_block.h>
+#include <pmt/pmt.h>
+#include <uhd/usrp/multi_usrp.hpp>
+#include <boost/dynamic_bitset.hpp>
+
+namespace gr {
+  namespace uhd {
+
+    class usrp_block_impl : virtual public usrp_block
+    {
+     public:
+      typedef boost::function< ::uhd::sensor_value_t (const std::string&)> 
get_sensor_fn_t;
+
+      static const double LOCK_TIMEOUT;
+
+      /**********************************************************************
+       * Public API calls (see usrp_block.h for docs)
+       **********************************************************************/
+      // Getters
+      ::uhd::sensor_value_t get_mboard_sensor(const std::string &name, size_t 
mboard);
+      std::vector<std::string> get_mboard_sensor_names(size_t mboard);
+      std::string get_time_source(const size_t mboard);
+      std::vector<std::string> get_time_sources(const size_t mboard);
+      std::string get_clock_source(const size_t mboard);
+      std::vector<std::string> get_clock_sources(const size_t mboard);
+      double get_clock_rate(size_t mboard);
+      ::uhd::time_spec_t get_time_now(size_t mboard = 0);
+      ::uhd::time_spec_t get_time_last_pps(size_t mboard);
+      ::uhd::usrp::multi_usrp::sptr get_device(void);
+
+      // Setters
+      void set_clock_config(const ::uhd::clock_config_t &clock_config, size_t 
mboard);
+      void set_time_source(const std::string &source, const size_t mboard);
+      void set_clock_source(const std::string &source, const size_t mboard);
+      void set_clock_rate(double rate, size_t mboard);
+      void set_time_now(const ::uhd::time_spec_t &time_spec, size_t mboard);
+      void set_time_next_pps(const ::uhd::time_spec_t &time_spec);
+      void set_time_unknown_pps(const ::uhd::time_spec_t &time_spec);
+      void set_command_time(const ::uhd::time_spec_t &time_spec, size_t 
mboard);
+      void set_user_register(const uint8_t addr, const uint32_t data, size_t 
mboard);
+      void clear_command_time(size_t mboard);
+
+      // RPC
+      void setup_rpc();
+
+      /**********************************************************************
+       * Structors
+       * ********************************************************************/
+      virtual ~usrp_block_impl();
+     protected:
+      /*! \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
+       */
+      usrp_block_impl(
+          const ::uhd::device_addr_t &device_addr,
+          const ::uhd::stream_args_t &stream_args,
+          const std::string &ts_tag_name
+      );
+
+      /**********************************************************************
+       * Command Interface
+       **********************************************************************/
+      //! Receives commands and handles them
+      void msg_handler_command(pmt::pmt_t msg);
+
+      /**********************************************************************
+       * Helpers
+       **********************************************************************/
+      bool _check_mboard_sensors_locked();
+
+      void _update_stream_args(const ::uhd::stream_args_t &stream_args_);
+
+      /*! \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.
+       *
+       * \returns true if the sensor locked in time or doesn't exist
+       */
+      bool _wait_for_locked_sensor(
+          std::vector<std::string> sensor_names,
+          const std::string &sensor_name,
+          get_sensor_fn_t get_sensor_fn
+      );
+
+      //! 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 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
+      );
+
+      //! Helper function for msg_handler_command:
+      // - Sets a value in vector_to_update to cmd_val, depending on chan
+      // - If chan is a positive integer, it will set vector_to_update[chan]
+      // - If chan is -1, it depends on minus_one_updates_all:
+      //   - Either set vector_to_update[0] or
+      //   - Set *all* entries in vector_to_update
+      // - Returns a dynamic_bitset, all indexes that where changed in
+      //   vector_to_update are set to 1
+      template <typename T>
+      static boost::dynamic_bitset<> _update_vector_from_cmd_val(
+          std::vector<T> &vector_to_update,
+          int chan,
+          const T cmd_val,
+          bool minus_one_updates_all = false
+      ) {
+        boost::dynamic_bitset<> vals_updated(vector_to_update.size());
+        if (chan == -1) {
+          if (minus_one_updates_all) {
+            for (size_t i = 0; i < vector_to_update.size(); i++) {
+              if (vector_to_update[i] != cmd_val) {
+                vals_updated[i] = true;
+                vector_to_update[i] = cmd_val;
+              }
+            }
+            return vals_updated;
+          }
+          chan = 0;
+        }
+        if (vector_to_update[chan] != cmd_val) {
+          vector_to_update[chan] = cmd_val;
+          vals_updated[chan] = true;
+        }
+
+        return vals_updated;
+      }
+
+      //! Like set_center_freq(), but uses _curr_freq and _curr_lo_offset
+      virtual ::uhd::tune_result_t _set_center_freq_from_internals(size_t 
chan) = 0;
+
+      //! Calls _set_center_freq_from_internals() on all channels
+      void _set_center_freq_from_internals_allchans();
+
+      /**********************************************************************
+       * Members
+       *********************************************************************/
+      //! Shared pointer to the underlying multi_usrp object
+      ::uhd::usrp::multi_usrp::sptr _dev;
+      ::uhd::stream_args_t _stream_args;
+      boost::shared_ptr< ::uhd::io_type_t > _type;
+      //! Number of channels (i.e. number of in- or outputs)
+      size_t _nchan;
+      bool _stream_now;
+      ::uhd::time_spec_t _start_time;
+      bool _start_time_set;
+
+      /****** Command interface related **********/
+      //! Stores a list of commands for later execution
+      std::vector<pmt::pmt_t> _pending_cmds;
+      //! 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;
+      boost::dynamic_bitset<> _chans_to_tune;
+    };
+
+  } /* namespace uhd */
+} /* namespace gr */
+
+#endif /* INCLUDED_GR_UHD_BLOCK_IMPL_H */
+
diff --git a/gr-uhd/lib/usrp_common.h b/gr-uhd/lib/usrp_common.h
deleted file mode 100644
index 41f4439..0000000
--- a/gr-uhd/lib/usrp_common.h
+++ /dev/null
@@ -1,211 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2014 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef INCLUDED_GR_UHD_USRP_COMMON_H
-#define INCLUDED_GR_UHD_USRP_COMMON_H
-
-#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
-    // - Returns true if the command PMT is well formed
-    // - 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
-    ) {
-      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;
-    }
-
-    //! Helper function for msg_handler_command:
-    // - Sets a value in vector_to_update to cmd_val, depending on chan
-    // - If chan is a positive integer, it will set vector_to_update[chan]
-    // - If chan is -1, it depends on minus_one_updates_all:
-    //   - Either set vector_to_update[0] or
-    //   - Set *all* entries in vector_to_update
-    // - Returns a dynamic_bitset, all indexes that where changed in
-    //   vector_to_update are set to 1
-    template <typename T>
-    static boost::dynamic_bitset<> _update_vector_from_cmd_val(
-        std::vector<T> &vector_to_update,
-        int chan,
-        const T cmd_val,
-        bool minus_one_updates_all = false
-    ) {
-      boost::dynamic_bitset<> vals_updated(vector_to_update.size());
-      if (chan == -1) {
-        if (minus_one_updates_all) {
-          for (size_t i = 0; i < vector_to_update.size(); i++) {
-            if (vector_to_update[i] != cmd_val) {
-              vals_updated[i] = true;
-              vector_to_update[i] = cmd_val;
-            }
-          }
-          return vals_updated;
-        }
-        chan = 0;
-      }
-      if (vector_to_update[chan] != cmd_val) {
-        vector_to_update[chan] = cmd_val;
-        vals_updated[chan] = true;
-      }
-
-      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
-    {
-    public:
-      usrp_common_impl(
-          const ::uhd::device_addr_t &device_addr,
-          const ::uhd::stream_args_t &stream_args,
-          const std::string &ts_tag_name
-      ) :
-        _stream_args(stream_args),
-        _nchan(stream_args.channels.size()),
-        _stream_now(_nchan == 1 and ts_tag_name.empty()),
-        _start_time_set(false)
-      {
-        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);
-      };
-
-      ~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;
-      }
-
-      void _update_stream_args(const ::uhd::stream_args_t &stream_args_)
-      {
-        ::uhd::stream_args_t stream_args(stream_args_);
-        if (stream_args.channels.empty()) {
-          stream_args.channels = _stream_args.channels;
-        }
-        if (stream_args.cpu_format != _stream_args.cpu_format ||
-            stream_args.channels.size() != _stream_args.channels.size()) {
-          throw std::runtime_error("Cannot change I/O signatures while 
updating stream args!");
-        }
-        _stream_args = stream_args;
-      }
-
-      //! Shared pointer to the underlying multi_usrp object
-      ::uhd::usrp::multi_usrp::sptr _dev;
-      ::uhd::stream_args_t _stream_args;
-      boost::shared_ptr< ::uhd::io_type_t > _type;
-      //! Number of channels (i.e. number of in- or outputs)
-      size_t _nchan;
-      bool _stream_now;
-      ::uhd::time_spec_t _start_time;
-      bool _start_time_set;
-    };
-
-  } /* namespace uhd */
-} /* namespace gr */
-
-#endif /* INCLUDED_GR_UHD_USRP_COMMON_H */
-
diff --git a/gr-uhd/lib/usrp_sink_impl.cc b/gr-uhd/lib/usrp_sink_impl.cc
index 08896a8..513dfaf 100644
--- a/gr-uhd/lib/usrp_sink_impl.cc
+++ b/gr-uhd/lib/usrp_sink_impl.cc
@@ -64,53 +64,16 @@ namespace gr {
     usrp_sink_impl::usrp_sink_impl(const ::uhd::device_addr_t &device_addr,
                                    const ::uhd::stream_args_t &stream_args,
                                    const std::string &length_tag_name)
-      : sync_block("gr uhd usrp sink",
+      : usrp_block("gr uhd usrp sink",
                       args_to_io_sig(stream_args),
                       io_signature::make(0, 0, 0)),
-        usrp_common_impl(device_addr, stream_args, length_tag_name),
+        usrp_block_impl(device_addr, stream_args, length_tag_name),
         _length_tag_key(length_tag_name.empty() ? pmt::PMT_NIL : 
pmt::string_to_symbol(length_tag_name)),
-        _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),
-        _chans_to_tune(stream_args.channels.size())
+        _nitems_to_send(0)
     {
-      message_port_register_in(pmt::mp("command"));
-      set_msg_handler(
-          pmt::mp("command"),
-          boost::bind(&usrp_sink_impl::msg_handler_command, this, _1)
-      );
-
-      _check_sensors_locked();
+      // nop
     }
 
-    bool usrp_sink_impl::_check_sensors_locked()
-    {
-      bool clocks_locked = true;
-
-      // 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;
-        }
-      }
-
-      return clocks_locked;
-    }
-
-
     usrp_sink_impl::~usrp_sink_impl()
     {
     }
@@ -184,22 +147,12 @@ namespace gr {
     {
       _chans_to_tune[chan] = false;
       if (_curr_lo_offset[chan] == 0.0) {
-       return _dev->set_tx_freq(_curr_freq[chan], _stream_args.channels[chan]);
+        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]
-       );
-      }
-    }
-
-    void
-    usrp_sink_impl::_set_center_freq_from_internals_allchans()
-    {
-      for (size_t chan = 0; chan < _nchan; chan++) {
-        if (_chans_to_tune[chan]) {
-          _set_center_freq_from_internals(chan);
-        }
+        return _dev->set_tx_freq(
+            ::uhd::tune_request_t(_curr_freq[chan], _curr_lo_offset[chan]),
+            _stream_args.channels[chan]
+            );
       }
     }
 
@@ -375,152 +328,6 @@ namespace gr {
       return _dev->get_tx_sensor_names(chan);
     }
 
-    ::uhd::sensor_value_t
-    usrp_sink_impl::get_mboard_sensor(const std::string &name,
-                                       size_t mboard)
-    {
-      return _dev->get_mboard_sensor(name, mboard);
-    }
-
-    std::vector<std::string>
-    usrp_sink_impl::get_mboard_sensor_names(size_t mboard)
-    {
-      return _dev->get_mboard_sensor_names(mboard);
-    }
-
-    void
-    usrp_sink_impl::set_clock_config(const ::uhd::clock_config_t &clock_config,
-                                     size_t mboard)
-    {
-      return _dev->set_clock_config(clock_config, mboard);
-    }
-
-    void
-    usrp_sink_impl::set_time_source(const std::string &source,
-                                    const size_t mboard)
-    {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
-      return _dev->set_time_source(source, mboard);
-#else
-      throw std::runtime_error("not implemented in this version");
-#endif
-    }
-
-    std::string
-    usrp_sink_impl::get_time_source(const size_t mboard)
-    {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
-      return _dev->get_time_source(mboard);
-#else
-      throw std::runtime_error("not implemented in this version");
-#endif
-    }
-
-    std::vector<std::string>
-    usrp_sink_impl::get_time_sources(const size_t mboard)
-    {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
-      return _dev->get_time_sources(mboard);
-#else
-      throw std::runtime_error("not implemented in this version");
-#endif
-    }
-
-    void
-    usrp_sink_impl::set_clock_source(const std::string &source,
-                                     const size_t mboard)
-    {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
-      return _dev->set_clock_source(source, mboard);
-#else
-      throw std::runtime_error("not implemented in this version");
-#endif
-    }
-
-    std::string
-    usrp_sink_impl::get_clock_source(const size_t mboard)
-    {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
-      return _dev->get_clock_source(mboard);
-#else
-      throw std::runtime_error("not implemented in this version");
-#endif
-    }
-
-    std::vector<std::string>
-    usrp_sink_impl::get_clock_sources(const size_t mboard)
-    {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
-      return _dev->get_clock_sources(mboard);
-#else
-      throw std::runtime_error("not implemented in this version");
-#endif
-    }
-
-    double
-    usrp_sink_impl::get_clock_rate(size_t mboard)
-    {
-      return _dev->get_master_clock_rate(mboard);
-    }
-
-    void
-    usrp_sink_impl::set_clock_rate(double rate, size_t mboard)
-    {
-      return _dev->set_master_clock_rate(rate, mboard);
-    }
-
-    ::uhd::time_spec_t
-    usrp_sink_impl::get_time_now(size_t mboard)
-    {
-      return _dev->get_time_now(mboard);
-    }
-
-    ::uhd::time_spec_t
-    usrp_sink_impl::get_time_last_pps(size_t mboard)
-    {
-      return _dev->get_time_last_pps(mboard);
-    }
-
-    void
-    usrp_sink_impl::set_time_now(const ::uhd::time_spec_t &time_spec,
-                                 size_t mboard)
-    {
-      return _dev->set_time_now(time_spec, mboard);
-    }
-
-    void
-    usrp_sink_impl::set_time_next_pps(const ::uhd::time_spec_t &time_spec)
-    {
-      return _dev->set_time_next_pps(time_spec);
-    }
-
-    void
-    usrp_sink_impl::set_time_unknown_pps(const ::uhd::time_spec_t &time_spec)
-    {
-      return _dev->set_time_unknown_pps(time_spec);
-    }
-
-    void
-    usrp_sink_impl::set_command_time(const ::uhd::time_spec_t &time_spec,
-                                     size_t mboard)
-    {
-#ifdef UHD_USRP_MULTI_USRP_COMMAND_TIME_API
-      return _dev->set_command_time(time_spec, mboard);
-#else
-      throw std::runtime_error("not implemented in this version");
-#endif
-    }
-
-    void
-    usrp_sink_impl::clear_command_time(size_t mboard)
-    {
-#ifdef UHD_USRP_MULTI_USRP_COMMAND_TIME_API
-      return _dev->clear_command_time(mboard);
-#else
-      throw std::runtime_error("not implemented in this version");
-#endif
-    }
-
     ::uhd::usrp::dboard_iface::sptr
     usrp_sink_impl::get_dboard_iface(size_t chan)
     {
@@ -528,24 +335,6 @@ namespace gr {
       return _dev->get_tx_dboard_iface(chan);
     }
 
-    ::uhd::usrp::multi_usrp::sptr
-    usrp_sink_impl::get_device(void)
-    {
-      return _dev;
-    }
-
-    void
-    usrp_sink_impl::set_user_register(const uint8_t addr,
-                                      const uint32_t data,
-                                      size_t mboard)
-    {
-#ifdef UHD_USRP_MULTI_USRP_USER_REGS_API
-      _dev->set_user_register(addr, data, mboard);
-#else
-      throw std::runtime_error("not implemented in this version");
-#endif
-    }
-
     void
     usrp_sink_impl::set_stream_args(const ::uhd::stream_args_t &stream_args)
     {
@@ -843,69 +632,5 @@ namespace gr {
       return true;
     }
 
-
-    /************** External interfaces (RPC + Message passing) 
********************/
-    void usrp_sink_impl::msg_handler_command(pmt::pmt_t msg)
-    {
-      std::string command;
-      pmt::pmt_t cmd_value;
-      int chan = -1;
-      if (not _unpack_chan_command(command, cmd_value, chan, msg)) {
-        GR_LOG_ALERT(d_logger, boost::format("Error while unpacking command 
PMT: %s") % msg);
-        return;
-      }
-      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);
-      }
-    }
-
-    void
-    usrp_sink_impl::setup_rpc()
-    {
-#ifdef GR_CTRLPORT
-      add_rpc_variable(
-        rpcbasic_sptr(new rpcbasic_register_get<usrp_sink, double>(
-         alias(), "samp_rate",
-         &usrp_sink::get_samp_rate,
-         pmt::mp(100000.0f), pmt::mp(25000000.0f), pmt::mp(1000000.0f),
-         "sps", "TX Sample Rate", RPC_PRIVLVL_MIN,
-          DISPTIME | DISPOPTSTRIP)));
-
-      add_rpc_variable(
-        rpcbasic_sptr(new rpcbasic_register_set<usrp_sink, double>(
-         alias(), "samp_rate",
-         &usrp_sink::set_samp_rate,
-         pmt::mp(100000.0f), pmt::mp(25000000.0f), pmt::mp(1000000.0f),
-         "sps", "TX Sample Rate",
-         RPC_PRIVLVL_MIN, DISPNULL)));
-#endif /* GR_CTRLPORT */
-    }
-
   } /* namespace uhd */
 } /* namespace gr */
diff --git a/gr-uhd/lib/usrp_sink_impl.h b/gr-uhd/lib/usrp_sink_impl.h
index e0cb5a9..1575378 100644
--- a/gr-uhd/lib/usrp_sink_impl.h
+++ b/gr-uhd/lib/usrp_sink_impl.h
@@ -20,9 +20,9 @@
  * Boston, MA 02110-1301, USA.
  */
 
+#include "usrp_block_impl.h"
 #include <gnuradio/uhd/usrp_sink.h>
 #include <uhd/convert.hpp>
-#include "usrp_common.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");
@@ -52,7 +52,7 @@ namespace gr {
     /***********************************************************************
      * UHD Multi USRP Sink Impl
      **********************************************************************/
-    class usrp_sink_impl : public usrp_sink, public usrp_common_impl
+    class usrp_sink_impl : public usrp_sink, public usrp_block_impl
     {
     public:
        usrp_sink_impl(const ::uhd::device_addr_t &device_addr,
@@ -60,8 +60,6 @@ namespace gr {
                       const std::string &length_tag_name);
       ~usrp_sink_impl();
 
-      void setup_rpc();
-
       ::uhd::dict<std::string, std::string> get_usrp_info(size_t chan);
       double get_samp_rate(void);
       ::uhd::meta_range_t get_samp_rates(void);
@@ -77,17 +75,7 @@ namespace gr {
       std::vector<std::string> get_antennas(size_t chan);
       ::uhd::sensor_value_t get_sensor(const std::string &name, size_t chan);
       std::vector<std::string> get_sensor_names(size_t chan);
-      ::uhd::sensor_value_t get_mboard_sensor(const std::string &name, size_t 
mboard);
-      std::vector<std::string> get_mboard_sensor_names(size_t mboard);
-      std::string get_time_source(const size_t mboard);
-      std::vector<std::string> get_time_sources(const size_t mboard);
-      std::string get_clock_source(const size_t mboard);
-      std::vector<std::string> get_clock_sources(const size_t mboard);
-      double get_clock_rate(size_t mboard);
-      ::uhd::time_spec_t get_time_now(size_t mboard = 0);
-      ::uhd::time_spec_t get_time_last_pps(size_t mboard);
       ::uhd::usrp::dboard_iface::sptr get_dboard_iface(size_t chan);
-      ::uhd::usrp::multi_usrp::sptr get_device(void);
 
       void set_subdev_spec(const std::string &spec, size_t mboard);
       std::string get_subdev_spec(size_t mboard);
@@ -103,16 +91,6 @@ namespace gr {
       ::uhd::freq_range_t get_bandwidth_range(size_t chan);
       void set_dc_offset(const std::complex<double> &offset, size_t chan);
       void set_iq_balance(const std::complex<double> &correction, size_t chan);
-      void set_clock_config(const ::uhd::clock_config_t &clock_config, size_t 
mboard);
-      void set_time_source(const std::string &source, const size_t mboard);
-      void set_clock_source(const std::string &source, const size_t mboard);
-      void set_clock_rate(double rate, size_t mboard);
-      void set_time_now(const ::uhd::time_spec_t &time_spec, size_t mboard);
-      void set_time_next_pps(const ::uhd::time_spec_t &time_spec);
-      void set_time_unknown_pps(const ::uhd::time_spec_t &time_spec);
-      void set_command_time(const ::uhd::time_spec_t &time_spec, size_t 
mboard);
-      void clear_command_time(size_t mboard);
-      void set_user_register(const uint8_t addr, const uint32_t data, size_t 
mboard);
       void set_stream_args(const ::uhd::stream_args_t &stream_args);
       void set_start_time(const ::uhd::time_spec_t &time);
 
@@ -126,14 +104,8 @@ 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
-      void _set_center_freq_from_internals_allchans();
 
 #ifdef GR_UHD_USE_STREAM_API
       ::uhd::tx_streamer::sptr _tx_stream;
@@ -141,27 +113,11 @@ namespace gr {
       ::uhd::tx_metadata_t _metadata;
       double _sample_rate;
 
-
       //stream tags related stuff
       std::vector<tag_t> _tags;
       const pmt::pmt_t _length_tag_key;
       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
-      // (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;
-      boost::dynamic_bitset<> _chans_to_tune;
     };
 
   } /* namespace uhd */
diff --git a/gr-uhd/lib/usrp_source_impl.cc b/gr-uhd/lib/usrp_source_impl.cc
index 1345740..4265535 100644
--- a/gr-uhd/lib/usrp_source_impl.cc
+++ b/gr-uhd/lib/usrp_source_impl.cc
@@ -20,10 +20,8 @@
  * Boston, MA 02110-1301, USA.
  */
 
-#include "usrp_common.h"
 #include "usrp_source_impl.h"
 #include "gr_uhd_common.h"
-#include <gnuradio/io_signature.h>
 #include <boost/format.hpp>
 #include <boost/thread/thread.hpp>
 #include <boost/make_shared.hpp>
@@ -64,49 +62,15 @@ namespace gr {
 
     usrp_source_impl::usrp_source_impl(const ::uhd::device_addr_t &device_addr,
                                        const ::uhd::stream_args_t 
&stream_args):
-      sync_block("gr uhd usrp source",
+      usrp_block("gr uhd usrp source",
                     io_signature::make(0, 0, 0),
                     args_to_io_sig(stream_args)),
-      usrp_common_impl(device_addr, stream_args, ""),
+      usrp_block_impl(device_addr, stream_args, ""),
       _tag_now(false)
     {
       std::stringstream str;
       str << name() << unique_id();
       _id = pmt::string_to_symbol(str.str());
-
-      message_port_register_in(pmt::mp("command"));
-      set_msg_handler(
-          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;
-
-      // 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;
-        }
-      }
-
-      return clocks_locked;
     }
 
     usrp_source_impl::~usrp_source_impl()
@@ -175,6 +139,20 @@ namespace gr {
       return res;
     }
 
+    ::uhd::tune_result_t
+    usrp_source_impl::_set_center_freq_from_internals(size_t chan)
+    {
+      _chans_to_tune[chan] = false;
+      if (_curr_lo_offset[chan] == 0.0) {
+        return _dev->set_rx_freq(_curr_freq[chan], 
_stream_args.channels[chan]);
+      } else {
+        return _dev->set_rx_freq(
+            ::uhd::tune_request_t(_curr_freq[chan], _curr_lo_offset[chan]),
+            _stream_args.channels[chan]
+        );
+      }
+    }
+
     double
     usrp_source_impl::get_center_freq(size_t chan)
     {
@@ -364,150 +342,6 @@ namespace gr {
       return _dev->get_rx_sensor_names(chan);
     }
 
-    ::uhd::sensor_value_t
-    usrp_source_impl::get_mboard_sensor(const std::string &name, size_t mboard)
-    {
-      return _dev->get_mboard_sensor(name, mboard);
-    }
-
-    std::vector<std::string>
-    usrp_source_impl::get_mboard_sensor_names(size_t mboard)
-    {
-      return _dev->get_mboard_sensor_names(mboard);
-    }
-
-    void
-    usrp_source_impl::set_clock_config(const ::uhd::clock_config_t 
&clock_config,
-                                       size_t mboard)
-    {
-      return _dev->set_clock_config(clock_config, mboard);
-    }
-
-    void
-    usrp_source_impl::set_time_source(const std::string &source,
-                                      const size_t mboard)
-    {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
-      return _dev->set_time_source(source, mboard);
-#else
-      throw std::runtime_error("not implemented in this version");
-#endif
-    }
-
-    std::string
-    usrp_source_impl::get_time_source(const size_t mboard)
-    {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
-      return _dev->get_time_source(mboard);
-#else
-      throw std::runtime_error("not implemented in this version");
-#endif
-    }
-
-    std::vector<std::string>
-    usrp_source_impl::get_time_sources(const size_t mboard)
-    {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
-      return _dev->get_time_sources(mboard);
-#else
-      throw std::runtime_error("not implemented in this version");
-#endif
-    }
-
-    void
-    usrp_source_impl::set_clock_source(const std::string &source,
-                                       const size_t mboard)
-    {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
-      return _dev->set_clock_source(source, mboard);
-#else
-      throw std::runtime_error("not implemented in this version");
-#endif
-    }
-
-    std::string
-    usrp_source_impl::get_clock_source(const size_t mboard)
-    {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
-      return _dev->get_clock_source(mboard);
-#else
-      throw std::runtime_error("not implemented in this version");
-#endif
-    }
-
-    std::vector<std::string>
-    usrp_source_impl::get_clock_sources(const size_t mboard)
-    {
-#ifdef UHD_USRP_MULTI_USRP_REF_SOURCES_API
-      return _dev->get_clock_sources(mboard);
-#else
-      throw std::runtime_error("not implemented in this version");
-#endif
-    }
-
-    double
-    usrp_source_impl::get_clock_rate(size_t mboard)
-    {
-      return _dev->get_master_clock_rate(mboard);
-    }
-
-    void
-    usrp_source_impl::set_clock_rate(double rate, size_t mboard)
-    {
-      return _dev->set_master_clock_rate(rate, mboard);
-    }
-
-    ::uhd::time_spec_t
-    usrp_source_impl::get_time_now(size_t mboard)
-    {
-      return _dev->get_time_now(mboard);
-    }
-
-    ::uhd::time_spec_t
-    usrp_source_impl::get_time_last_pps(size_t mboard)
-    {
-      return _dev->get_time_last_pps(mboard);
-    }
-
-    void
-    usrp_source_impl::set_time_now(const ::uhd::time_spec_t &time_spec,
-                                   size_t mboard)
-    {
-      return _dev->set_time_now(time_spec, mboard);
-    }
-
-    void
-    usrp_source_impl::set_time_next_pps(const ::uhd::time_spec_t &time_spec)
-    {
-      return _dev->set_time_next_pps(time_spec);
-    }
-
-    void
-    usrp_source_impl::set_time_unknown_pps(const ::uhd::time_spec_t &time_spec)
-    {
-      return _dev->set_time_unknown_pps(time_spec);
-    }
-
-    void
-    usrp_source_impl::set_command_time(const ::uhd::time_spec_t &time_spec, 
size_t mboard)
-    {
-#ifdef UHD_USRP_MULTI_USRP_COMMAND_TIME_API
-      return _dev->set_command_time(time_spec, mboard);
-#else
-      throw std::runtime_error("not implemented in this version");
-#endif
-    }
-
-    void
-    usrp_source_impl::clear_command_time(size_t mboard)
-    {
-#ifdef UHD_USRP_MULTI_USRP_COMMAND_TIME_API
-      return _dev->clear_command_time(mboard);
-#else
-      throw std::runtime_error("not implemented in this version");
-#endif
-    }
-
     ::uhd::usrp::dboard_iface::sptr
     usrp_source_impl::get_dboard_iface(size_t chan)
     {
@@ -515,24 +349,6 @@ namespace gr {
       return _dev->get_rx_dboard_iface(chan);
     }
 
-    ::uhd::usrp::multi_usrp::sptr
-    usrp_source_impl::get_device(void)
-    {
-      return _dev;
-    }
-
-    void
-    usrp_source_impl::set_user_register(const uint8_t addr,
-                                        const uint32_t data,
-                                        size_t mboard)
-    {
-#ifdef UHD_USRP_MULTI_USRP_USER_REGS_API
-      _dev->set_user_register(addr, data, mboard);
-#else
-      throw std::runtime_error("not implemented in this version");
-#endif
-    }
-
     void
     usrp_source_impl::set_stream_args(const ::uhd::stream_args_t &stream_args)
     {
@@ -743,59 +559,5 @@ namespace gr {
       return num_samps;
     }
 
-
-    /************** External interfaces (RPC + Message passing) 
********************/
-    void usrp_source_impl::msg_handler_command(pmt::pmt_t msg)
-    {
-      std::string command;
-      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.");
-      }
-      if (command == "freq") {
-       double freq = pmt::to_double(cmd_value);
-       for (size_t i = 0; i < _nchan; i++) {
-         if (chan == -1 || chan == int(i)) {
-           set_center_freq(freq, i);
-         }
-       }
-       // TODO: implement
-      //} else if (command == "lo_offset") {
-       //;
-      } else if (command == "gain") {
-       double gain = pmt::to_double(cmd_value);
-       for (size_t i = 0; i < _nchan; i++) {
-         if (chan == -1 || chan == int(i)) {
-           set_gain(gain, i);
-         }
-       }
-      } else {
-       GR_LOG_ALERT(d_logger, boost::format("Received unknown command: %s") % 
command);
-      }
-    }
-
-    void
-    usrp_source_impl::setup_rpc()
-    {
-#ifdef GR_CTRLPORT
-      add_rpc_variable(
-        rpcbasic_sptr(new rpcbasic_register_get<usrp_source, double>(
-         alias(), "samp_rate",
-         &usrp_source::get_samp_rate,
-         pmt::mp(100000.0f), pmt::mp(25000000.0f), pmt::mp(1000000.0f),
-         "sps", "RX Sample Rate", RPC_PRIVLVL_MIN,
-          DISPTIME | DISPOPTSTRIP)));
-
-      add_rpc_variable(
-        rpcbasic_sptr(new rpcbasic_register_set<usrp_source, double>(
-         alias(), "samp_rate",
-         &usrp_source::set_samp_rate,
-         pmt::mp(100000.0f), pmt::mp(25000000.0f), pmt::mp(1000000.0f),
-         "sps", "RX Sample Rate",
-         RPC_PRIVLVL_MIN, DISPNULL)));
-#endif /* GR_CTRLPORT */
-    }
-
   } /* namespace uhd */
 } /* namespace gr */
diff --git a/gr-uhd/lib/usrp_source_impl.h b/gr-uhd/lib/usrp_source_impl.h
index 0cbbe2b..9f6fc1a 100644
--- a/gr-uhd/lib/usrp_source_impl.h
+++ b/gr-uhd/lib/usrp_source_impl.h
@@ -20,10 +20,10 @@
  * Boston, MA 02110-1301, USA.
  */
 
+#include "usrp_block_impl.h"
 #include <gnuradio/uhd/usrp_source.h>
 #include <uhd/convert.hpp>
 #include <boost/thread/mutex.hpp>
-#include "usrp_common.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");
@@ -51,15 +51,13 @@ namespace gr {
     /***********************************************************************
      * UHD Multi USRP Source Impl
      **********************************************************************/
-    class usrp_source_impl : public usrp_source, public usrp_common_impl
+    class usrp_source_impl : public usrp_source, public usrp_block_impl
     {
     public:
       usrp_source_impl(const ::uhd::device_addr_t &device_addr,
                        const ::uhd::stream_args_t &stream_args);
       ~usrp_source_impl();
 
-      void setup_rpc();
-
       // Get Commands
       ::uhd::dict<std::string, std::string> get_usrp_info(size_t chan);
       std::string get_subdev_spec(size_t mboard);
@@ -77,17 +75,7 @@ namespace gr {
       std::vector<std::string> get_antennas(size_t chan);
       ::uhd::sensor_value_t get_sensor(const std::string &name, size_t chan);
       std::vector<std::string> get_sensor_names(size_t chan);
-      ::uhd::sensor_value_t get_mboard_sensor(const std::string &name, size_t 
mboard);
-      std::vector<std::string> get_mboard_sensor_names(size_t mboard);
-      std::string get_time_source(const size_t mboard);
-      std::vector<std::string> get_time_sources(const size_t mboard);
-      std::string get_clock_source(const size_t mboard);
-      std::vector<std::string> get_clock_sources(const size_t mboard);
-      double get_clock_rate(size_t mboard);
-      ::uhd::time_spec_t get_time_now(size_t mboard = 0);
-      ::uhd::time_spec_t get_time_last_pps(size_t mboard);
       ::uhd::usrp::dboard_iface::sptr get_dboard_iface(size_t chan);
-      ::uhd::usrp::multi_usrp::sptr get_device(void);
 
       // Set Commands
       void set_subdev_spec(const std::string &spec, size_t mboard);
@@ -105,20 +93,10 @@ namespace gr {
       void set_dc_offset(const std::complex<double> &offset, size_t chan);
       void set_auto_iq_balance(const bool enable, size_t chan);
       void set_iq_balance(const std::complex<double> &correction, size_t chan);
-      void set_clock_config(const ::uhd::clock_config_t &clock_config, size_t 
mboard);
-      void set_time_source(const std::string &source, const size_t mboard);
-      void set_clock_source(const std::string &source, const size_t mboard);
-      void set_clock_rate(double rate, size_t mboard);
-      void set_time_now(const ::uhd::time_spec_t &time_spec, size_t mboard);
-      void set_time_next_pps(const ::uhd::time_spec_t &time_spec);
-      void set_time_unknown_pps(const ::uhd::time_spec_t &time_spec);
-      void set_command_time(const ::uhd::time_spec_t &time_spec, size_t 
mboard);
-      void set_user_register(const uint8_t addr, const uint32_t data, size_t 
mboard);
       void set_stream_args(const ::uhd::stream_args_t &stream_args);
       void set_start_time(const ::uhd::time_spec_t &time);
 
       void issue_stream_cmd(const ::uhd::stream_cmd_t &cmd);
-      void clear_command_time(size_t mboard);
       void flush(void);
       bool start(void);
       bool stop(void);
@@ -129,9 +107,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();
+      //! Like set_center_freq(), but uses _curr_freq and _curr_lo_offset
+      ::uhd::tune_result_t _set_center_freq_from_internals(size_t chan);
+
 #ifdef GR_UHD_USE_STREAM_API
       ::uhd::rx_streamer::sptr _rx_stream;
       size_t _samps_per_packet;
@@ -145,21 +123,6 @@ namespace gr {
       double _center_freq;
 
       boost::recursive_mutex d_mutex;
-
-      /****** Command interface related **********/
-      //! 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
-      // (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;
-      boost::dynamic_bitset<> _chans_to_tune;
-      bool _call_tune;
     };
 
   } /* namespace uhd */
diff --git a/gr-uhd/swig/uhd_swig.i b/gr-uhd/swig/uhd_swig.i
index a4b1528..108f544 100644
--- a/gr-uhd/swig/uhd_swig.i
+++ b/gr-uhd/swig/uhd_swig.i
@@ -54,6 +54,8 @@
 #include <gnuradio/uhd/amsg_source.h>
 %}
 
+%include "gnuradio/uhd/usrp_block.h"
+
 ////////////////////////////////////////////////////////////////////////
 // used types
 ////////////////////////////////////////////////////////////////////////



reply via email to

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