aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorAndrej Rode <andrej.rode@ettus.com>2016-10-24 10:25:42 -0700
committerMartin Braun <martin.braun@ettus.com>2017-05-26 16:01:37 -0700
commit76e9e6393fe1d5a0ccc9e05deb431694921850ec (patch)
treeb7f1097a04fd7a7d0a423a353fbeba037746b782 /tools
parent06ff34eaa9e147b11d2698308fa91a5260fee2d2 (diff)
downloaduhd-76e9e6393fe1d5a0ccc9e05deb431694921850ec.tar.gz
uhd-76e9e6393fe1d5a0ccc9e05deb431694921850ec.tar.bz2
uhd-76e9e6393fe1d5a0ccc9e05deb431694921850ec.zip
gr-usrptest: Initial creation
- new OOT-blocks: phase_calc_ccf hier-block, measurement_sink_f - new python submodules: flowgraphs, functions, rts_tests - new apps: usrp_phasealignment.py - cmdline example for manual testing OOT-Blocks: - phase_calc_ccf takes two complex input streams and conjugate multiplys them and extracts the phase from the result and converts it to degree scale - measurement_sink_f: takes a float input stream and calculates average and stddev for a specified number of samples. Start of a measurement is invoked by a call of start_run() on the block. After a couple of runs average and stddev can be extracted. Python modules: - flowgrahps contains reconfigurable flowgraphs for different GNU Radio RF test cases - functions contains functions which are used in different apps/RTS scripts - rts_tests contains test cases which are meant to be executed from the RTS system. Depends on TinyDB, labview_automation Apps: - usrp_phasealignment.py is an example how to use the underlying flowgraph to measure phase differences. Commandline arguments of uhd_app can be used and several additional arguments can/have to be specified. Runs a phase difference measurement --runs number of times and averages phase difference over --duration seconds. Between measurements USRP sinks are retuned to random frequencies in daughterboard range. Results are displayed using motherboard serial and daughterboard serial
Diffstat (limited to 'tools')
-rw-r--r--tools/gr-usrptest/TODO21
-rw-r--r--tools/gr-usrptest/apps/CMakeLists.txt1
-rwxr-xr-xtools/gr-usrptest/apps/usrp_phasealignment.py72
-rwxr-xr-xtools/gr-usrptest/apps/usrp_selftest.py17
-rw-r--r--tools/gr-usrptest/examples/phase_diff_x310_ubx_example.grc3296
-rw-r--r--tools/gr-usrptest/grc/usrptest_measurement_sink_f.xml38
-rw-r--r--tools/gr-usrptest/grc/usrptest_phase_calc_ccf.xml20
-rw-r--r--tools/gr-usrptest/include/usrptest/CMakeLists.txt2
-rw-r--r--tools/gr-usrptest/include/usrptest/measurement_sink_f.h61
-rw-r--r--tools/gr-usrptest/lib/CMakeLists.txt1
-rw-r--r--tools/gr-usrptest/lib/measurement_sink_f_impl.cc124
-rw-r--r--tools/gr-usrptest/lib/measurement_sink_f_impl.h62
-rw-r--r--tools/gr-usrptest/lib/qa_usrptest.cc36
-rw-r--r--tools/gr-usrptest/lib/qa_usrptest.h38
-rw-r--r--tools/gr-usrptest/lib/test_usrptest.cc48
-rw-r--r--tools/gr-usrptest/python/CMakeLists.txt10
-rw-r--r--tools/gr-usrptest/python/flowgraphs/CMakeLists.txt28
-rw-r--r--tools/gr-usrptest/python/flowgraphs/__init__.py14
-rw-r--r--tools/gr-usrptest/python/flowgraphs/phasealignment_fg.py119
-rw-r--r--tools/gr-usrptest/python/flowgraphs/selftest_fg.py122
-rw-r--r--tools/gr-usrptest/python/functions.py133
-rw-r--r--tools/gr-usrptest/python/phase_calc_ccf.py47
-rwxr-xr-xtools/gr-usrptest/python/qa_measurement_sink_f.py41
-rw-r--r--tools/gr-usrptest/python/rts_tests/CMakeLists.txt27
-rw-r--r--tools/gr-usrptest/python/rts_tests/__init__.py14
-rw-r--r--tools/gr-usrptest/python/rts_tests/test_phasealignment.py121
-rw-r--r--tools/gr-usrptest/swig/usrptest_swig.i3
27 files changed, 4513 insertions, 3 deletions
diff --git a/tools/gr-usrptest/TODO b/tools/gr-usrptest/TODO
new file mode 100644
index 000000000..0a56a49c3
--- /dev/null
+++ b/tools/gr-usrptest/TODO
@@ -0,0 +1,21 @@
+
+- Measure & Report phase alignment and phase stability of USRPs
+ - Wire diagram:
+
+ ______________ ______________
+ | | | |
+ | USRP 1 | | USRP 2 |
+ |______________| |______________|
+ ^ |______^ |_________^ |
+ |_______________________|
+
+ - USRP 1: send tone from first to second daughterboard - delta_phi_1
+ - USRP 1: send tone from second daughterboard to USPR 2 - delta_phi_2
+ - USRP 2: send tone to first daughterboard (USRP1) - delta_phi_3
+
+ Arbitrary number of RX-USRPs and TX-USRPs possible.
+
+ test_signal = sin(2*pi*f*t + phi)
+ reference = sin(2*pi*f*t)
+
+
diff --git a/tools/gr-usrptest/apps/CMakeLists.txt b/tools/gr-usrptest/apps/CMakeLists.txt
index c837d77f6..a40192924 100644
--- a/tools/gr-usrptest/apps/CMakeLists.txt
+++ b/tools/gr-usrptest/apps/CMakeLists.txt
@@ -21,5 +21,6 @@ include(GrPython)
GR_PYTHON_INSTALL(
PROGRAMS
+ usrp_phasealignment.py
DESTINATION bin
)
diff --git a/tools/gr-usrptest/apps/usrp_phasealignment.py b/tools/gr-usrptest/apps/usrp_phasealignment.py
new file mode 100755
index 000000000..928788be4
--- /dev/null
+++ b/tools/gr-usrptest/apps/usrp_phasealignment.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+
+from gnuradio.uhd.uhd_app import UHDApp
+from usrptest.flowgraphs import phasealignment_fg
+from usrptest.functions import run_test, setup_phase_alignment_parser, setup_tx_phase_alignment_parser, setup_manual_phase_alignment_parser
+import time
+import argparse
+
+
+def plot_results(results):
+ import matplotlib.pyplot as plt
+ ax = plt.axes()
+ ax.set_ylim(-180, 180)
+ for result in results:
+ plt.errorbar(
+ range(len(result['avg'])),
+ result["avg"],
+ result["stddev"],
+ label="{} - {}".format(result["first"], result["second"]),
+ axes=ax)
+ ax.legend(loc='upper left', bbox_to_anchor=(0.0, 0.0))
+ plt.show()
+
+
+def print_results(results):
+ for result in results:
+ print('Results for: {first} - {second}'.format(
+ first=result['first'], second=result['second']))
+ for i, (avg,
+ stddev) in enumerate(zip(result['avg'], result['stddev'])):
+ print('\t {}. run avg: {}, stddev: {}'.format(i + 1, avg, stddev))
+
+
+def main():
+ parser = argparse.ArgumentParser(conflict_handler='resolve')
+ UHDApp.setup_argparser(parser=parser)
+ parser = setup_phase_alignment_parser(parser)
+ parser = setup_tx_phase_alignment_parser(parser)
+ parser = setup_manual_phase_alignment_parser(parser)
+ args = parser.parse_args()
+ test_app = UHDApp(args=args)
+ if args.auto and args.start_freq and args.stop_freq:
+ from random import uniform
+ bw = (args.stop_freq - args.start_freq) / args.freq_bands
+ for nband in range(args.freq_bands):
+ freq1 = args.start_freq + nband * bw
+ new_freq = uniform(freq1, freq1 + bw)
+ test_app.args.freq = new_freq
+ raw_input(
+ "New test frequency: {:f} MHz. Adjust your signal generator and press ENTER to start measurement.".
+ format(new_freq / 1e6))
+ fg = phasealignment_fg.phasealignment_fg(test_app)
+ fg.start()
+ results = run_test(fg, args.runs)
+ fg.stop()
+ fg.wait()
+ if args.plot:
+ plot_results(results)
+ print_results(results)
+ else:
+ fg = phasealignment_fg.phasealignment_fg(test_app)
+ fg.start()
+ results = run_test(fg, args.runs)
+ fg.stop()
+ fg.wait()
+ if args.plot:
+ plot_results(results)
+ print_results(results)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/tools/gr-usrptest/apps/usrp_selftest.py b/tools/gr-usrptest/apps/usrp_selftest.py
new file mode 100755
index 000000000..3dcd4e6ca
--- /dev/null
+++ b/tools/gr-usrptest/apps/usrp_selftest.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+
+import argparse
+from usrptest import parsers
+from usrptest.flowgraphs import selftest_fg
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser = parsers.add_core_args(parser)
+ parser = parsers.add_selftest_args(parser)
+ args = parser.parse_args()
+ my_flowgraph = selftest_fg.selftest_fg(args.frequency, args.samp_rate, args.dphase ,args.devices)
+ results = my_flowgraph.run()
+ print(results)
+if __name__ == '__main__':
+ main()
diff --git a/tools/gr-usrptest/examples/phase_diff_x310_ubx_example.grc b/tools/gr-usrptest/examples/phase_diff_x310_ubx_example.grc
new file mode 100644
index 000000000..f6cbe3d83
--- /dev/null
+++ b/tools/gr-usrptest/examples/phase_diff_x310_ubx_example.grc
@@ -0,0 +1,3296 @@
+<?xml version='1.0' encoding='utf-8'?>
+<?grc format='1' created='3.7.11'?>
+<flow_graph>
+ <timestamp>Thu Oct 6 14:49:17 2016</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value></value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>[GRC Hier Blocks]</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 8)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>qt_gui</value>
+ </param>
+ <param>
+ <key>hier_block_src_path</key>
+ <value>.:</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>phase_difference_x3x0_example</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>qt_qss_theme</key>
+ <value></value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>run_command</key>
+ <value>{python} -u {filename}</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>thread_safe_setters</key>
+ <value></value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 100)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>baseband</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>3e9</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_qtgui_range</key>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>10e6</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(200, 112)</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>rx_base</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value></value>
+ </param>
+ <param>
+ <key>min_len</key>
+ <value>200</value>
+ </param>
+ <param>
+ <key>orient</key>
+ <value>Qt.Horizontal</value>
+ </param>
+ <param>
+ <key>start</key>
+ <value>10e6</value>
+ </param>
+ <param>
+ <key>step</key>
+ <value>50e6</value>
+ </param>
+ <param>
+ <key>stop</key>
+ <value>6e9</value>
+ </param>
+ <param>
+ <key>rangeType</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>widget</key>
+ <value>counter_slider</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 160)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>10e6</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_qtgui_range</key>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>10e6</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(168, 240)</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>tx_base</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value></value>
+ </param>
+ <param>
+ <key>min_len</key>
+ <value>200</value>
+ </param>
+ <param>
+ <key>orient</key>
+ <value>Qt.Horizontal</value>
+ </param>
+ <param>
+ <key>start</key>
+ <value>10e6</value>
+ </param>
+ <param>
+ <key>step</key>
+ <value>50e6</value>
+ </param>
+ <param>
+ <key>stop</key>
+ <value>6e9</value>
+ </param>
+ <param>
+ <key>rangeType</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>widget</key>
+ <value>counter_slider</value>
+ </param>
+ </block>
+ <block>
+ <key>analog_sig_source_x</key>
+ <param>
+ <key>amp</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>freq</key>
+ <value>100e3</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(440, 112)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>analog_sig_source_x_1</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>offset</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>waveform</key>
+ <value>analog.GR_COS_WAVE</value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_time_sink_x</key>
+ <param>
+ <key>autoscale</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>axislabels</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>ctrlpanel</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>entags</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(768, 404)</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>grid</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>qtgui_time_sink_x_0</value>
+ </param>
+ <param>
+ <key>legend</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>alpha1</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color1</key>
+ <value>"blue"</value>
+ </param>
+ <param>
+ <key>label1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker1</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style1</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width1</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha10</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color10</key>
+ <value>"blue"</value>
+ </param>
+ <param>
+ <key>label10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker10</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style10</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width10</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha2</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color2</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>label2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker2</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style2</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width2</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha3</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color3</key>
+ <value>"green"</value>
+ </param>
+ <param>
+ <key>label3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker3</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha4</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color4</key>
+ <value>"black"</value>
+ </param>
+ <param>
+ <key>label4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker4</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style4</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width4</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha5</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color5</key>
+ <value>"cyan"</value>
+ </param>
+ <param>
+ <key>label5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker5</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style5</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width5</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha6</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color6</key>
+ <value>"magenta"</value>
+ </param>
+ <param>
+ <key>label6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker6</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style6</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width6</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha7</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color7</key>
+ <value>"yellow"</value>
+ </param>
+ <param>
+ <key>label7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker7</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style7</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width7</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha8</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color8</key>
+ <value>"dark red"</value>
+ </param>
+ <param>
+ <key>label8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker8</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style8</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width8</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha9</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color9</key>
+ <value>"dark green"</value>
+ </param>
+ <param>
+ <key>label9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker9</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style9</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width9</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>nconnections</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>srate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>tr_chan</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_delay</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_level</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_FREE</value>
+ </param>
+ <param>
+ <key>tr_slope</key>
+ <value>qtgui.TRIG_SLOPE_POS</value>
+ </param>
+ <param>
+ <key>tr_tag</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>ylabel</key>
+ <value>Amplitude</value>
+ </param>
+ <param>
+ <key>yunit</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>ymax</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>ymin</key>
+ <value>-1</value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_time_sink_x</key>
+ <param>
+ <key>autoscale</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>axislabels</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>ctrlpanel</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>entags</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(664, 280)</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>grid</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>qtgui_time_sink_x_1</value>
+ </param>
+ <param>
+ <key>legend</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>alpha1</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color1</key>
+ <value>"blue"</value>
+ </param>
+ <param>
+ <key>label1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker1</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style1</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width1</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha10</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color10</key>
+ <value>"blue"</value>
+ </param>
+ <param>
+ <key>label10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker10</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style10</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width10</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha2</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color2</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>label2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker2</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style2</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width2</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha3</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color3</key>
+ <value>"green"</value>
+ </param>
+ <param>
+ <key>label3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker3</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha4</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color4</key>
+ <value>"black"</value>
+ </param>
+ <param>
+ <key>label4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker4</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style4</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width4</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha5</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color5</key>
+ <value>"cyan"</value>
+ </param>
+ <param>
+ <key>label5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker5</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style5</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width5</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha6</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color6</key>
+ <value>"magenta"</value>
+ </param>
+ <param>
+ <key>label6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker6</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style6</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width6</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha7</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color7</key>
+ <value>"yellow"</value>
+ </param>
+ <param>
+ <key>label7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker7</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style7</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width7</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha8</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color8</key>
+ <value>"dark red"</value>
+ </param>
+ <param>
+ <key>label8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker8</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style8</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width8</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha9</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color9</key>
+ <value>"dark green"</value>
+ </param>
+ <param>
+ <key>label9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>marker9</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>style9</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>width9</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>nconnections</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>srate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>tr_chan</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_delay</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_level</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_FREE</value>
+ </param>
+ <param>
+ <key>tr_slope</key>
+ <value>qtgui.TRIG_SLOPE_POS</value>
+ </param>
+ <param>
+ <key>tr_tag</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>ylabel</key>
+ <value>Amplitude</value>
+ </param>
+ <param>
+ <key>yunit</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>ymax</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>ymin</key>
+ <value>-1</value>
+ </param>
+ </block>
+ <block>
+ <key>uhd_usrp_sink</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>ant0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw0</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq0</key>
+ <value>tx_base</value>
+ </param>
+ <param>
+ <key>norm_gain0</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain0</key>
+ <value>15</value>
+ </param>
+ <param>
+ <key>ant10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain10</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant11</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain11</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant12</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain12</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant13</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain13</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant14</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain14</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant15</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain15</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant16</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain16</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant17</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain17</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant18</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain18</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant19</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain19</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq1</key>
+ <value>tx_base</value>
+ </param>
+ <param>
+ <key>norm_gain1</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain1</key>
+ <value>15</value>
+ </param>
+ <param>
+ <key>ant20</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain20</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant21</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain21</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant22</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain22</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant23</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain23</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant24</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain24</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant25</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain25</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant26</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain26</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant27</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain27</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant28</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain28</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant29</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain29</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain2</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant30</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain30</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant31</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain31</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain3</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain4</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain5</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain6</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain7</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain8</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain9</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>clock_rate</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>dev_addr</key>
+ <value>"addr=192.168.10.2"</value>
+ </param>
+ <param>
+ <key>dev_args</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(816, 104)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>uhd_usrp_sink_1</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>fc32</value>
+ </param>
+ <param>
+ <key>clock_source0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec0</key>
+ <value>"A:0 B:0"</value>
+ </param>
+ <param>
+ <key>time_source0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>nchan</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>num_mboards</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>hide_cmd_port</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>hide_lo_controls</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>stream_args</key>
+ <value></value>
+ </param>
+ <param>
+ <key>stream_chans</key>
+ <value>[]</value>
+ </param>
+ <param>
+ <key>sync</key>
+ <value></value>
+ </param>
+ <param>
+ <key>len_tag_name</key>
+ <value></value>
+ </param>
+ <param>
+ <key>otw</key>
+ <value></value>
+ </param>
+ </block>
+ <block>
+ <key>uhd_usrp_source</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>ant0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw0</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq0</key>
+ <value>rx_base</value>
+ </param>
+ <param>
+ <key>dc_offs_enb0</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb0</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain0</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain0</key>
+ <value>15</value>
+ </param>
+ <param>
+ <key>lo_export0</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source0</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb10</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb10</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain10</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export10</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source10</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant11</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb11</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb11</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain11</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export11</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source11</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant12</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb12</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb12</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain12</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export12</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source12</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant13</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb13</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb13</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain13</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export13</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source13</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant14</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb14</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb14</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain14</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export14</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source14</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant15</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb15</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb15</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain15</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export15</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source15</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant16</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb16</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb16</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain16</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export16</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source16</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant17</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb17</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb17</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain17</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export17</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source17</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant18</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb18</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb18</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain18</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export18</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source18</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant19</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb19</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb19</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain19</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export19</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source19</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq1</key>
+ <value>rx_base</value>
+ </param>
+ <param>
+ <key>dc_offs_enb1</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb1</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain1</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain1</key>
+ <value>15</value>
+ </param>
+ <param>
+ <key>lo_export1</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source1</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant20</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb20</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb20</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain20</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export20</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source20</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant21</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb21</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb21</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain21</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export21</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source21</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant22</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb22</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb22</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain22</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export22</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source22</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant23</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb23</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb23</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain23</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export23</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source23</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant24</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb24</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb24</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain24</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export24</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source24</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant25</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb25</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb25</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain25</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export25</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source25</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant26</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb26</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb26</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain26</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export26</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source26</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant27</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb27</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb27</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain27</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export27</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source27</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant28</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb28</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb28</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain28</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export28</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source28</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant29</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb29</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb29</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain29</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export29</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source29</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb2</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb2</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain2</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export2</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source2</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant30</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb30</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb30</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain30</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export30</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source30</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant31</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb31</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb31</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain31</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export31</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source31</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb3</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb3</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain3</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export3</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source3</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb4</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb4</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain4</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export4</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source4</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb5</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb5</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain5</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export5</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source5</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb6</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb6</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain6</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export6</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source6</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb7</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb7</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain7</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export7</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source7</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb8</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb8</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain8</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export8</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source8</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>ant9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>dc_offs_enb9</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>iq_imbal_enb9</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>norm_gain9</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>lo_export9</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>lo_source9</key>
+ <value>internal</value>
+ </param>
+ <param>
+ <key>clock_rate</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>dev_addr</key>
+ <value>"addr=192.168.10.2"</value>
+ </param>
+ <param>
+ <key>dev_args</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(320, 376)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>uhd_usrp_source_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>clock_source0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec0</key>
+ <value>"A:0 B:0"</value>
+ </param>
+ <param>
+ <key>time_source0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>nchan</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>num_mboards</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>fc32</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>hide_cmd_port</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>hide_lo_controls</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>stream_args</key>
+ <value></value>
+ </param>
+ <param>
+ <key>stream_chans</key>
+ <value>[]</value>
+ </param>
+ <param>
+ <key>sync</key>
+ <value></value>
+ </param>
+ <param>
+ <key>otw</key>
+ <value></value>
+ </param>
+ </block>
+ <block>
+ <key>usrptest_phase_calc_ccf</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(568, 408)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>usrptest_phase_calc_ccf_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>analog_sig_source_x_1</source_block_id>
+ <sink_block_id>uhd_usrp_sink_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>analog_sig_source_x_1</source_block_id>
+ <sink_block_id>uhd_usrp_sink_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>uhd_usrp_source_0</source_block_id>
+ <sink_block_id>qtgui_time_sink_x_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>uhd_usrp_source_0</source_block_id>
+ <sink_block_id>usrptest_phase_calc_ccf_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>uhd_usrp_source_0</source_block_id>
+ <sink_block_id>qtgui_time_sink_x_1</sink_block_id>
+ <source_key>1</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>uhd_usrp_source_0</source_block_id>
+ <sink_block_id>usrptest_phase_calc_ccf_0</sink_block_id>
+ <source_key>1</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>usrptest_phase_calc_ccf_0</source_block_id>
+ <sink_block_id>qtgui_time_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/tools/gr-usrptest/grc/usrptest_measurement_sink_f.xml b/tools/gr-usrptest/grc/usrptest_measurement_sink_f.xml
new file mode 100644
index 000000000..c681e457f
--- /dev/null
+++ b/tools/gr-usrptest/grc/usrptest_measurement_sink_f.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<block>
+ <name>measurement_sink_f</name>
+ <key>usrptest_measurement_sink_f</key>
+ <category>[usrptest]</category>
+ <import>import usrptest</import>
+ <make>usrptest.measurement_sink_f($num_samples, $)</make>
+ <!-- Make one 'param' node for every Parameter you want settable from the GUI.
+ Sub-nodes:
+ * name
+ * key (makes the value accessible as $keyname, e.g. in the make node)
+ * type -->
+ <param>
+ <name>...</name>
+ <key>...</key>
+ <type>...</type>
+ </param>
+
+ <!-- Make one 'sink' node per input. Sub-nodes:
+ * name (an identifier for the GUI)
+ * type
+ * vlen
+ * optional (set to 1 for optional inputs) -->
+ <sink>
+ <name>in</name>
+ <type><!-- e.g. int, float, complex, byte, short, xxx_vector, ...--></type>
+ </sink>
+
+ <!-- Make one 'source' node per output. Sub-nodes:
+ * name (an identifier for the GUI)
+ * type
+ * vlen
+ * optional (set to 1 for optional inputs) -->
+ <source>
+ <name>out</name>
+ <type><!-- e.g. int, float, complex, byte, short, xxx_vector, ...--></type>
+ </source>
+</block>
diff --git a/tools/gr-usrptest/grc/usrptest_phase_calc_ccf.xml b/tools/gr-usrptest/grc/usrptest_phase_calc_ccf.xml
new file mode 100644
index 000000000..4c98f56eb
--- /dev/null
+++ b/tools/gr-usrptest/grc/usrptest_phase_calc_ccf.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<block>
+ <name>Calculate phase diff</name>
+ <key>usrptest_phase_calc_ccf</key>
+ <category>[usrptest]</category>
+ <import>import usrptest</import>
+ <make>usrptest.phase_calc_ccf()</make>
+ <sink>
+ <name>in1</name>
+ <type>complex</type>
+ </sink>
+ <sink>
+ <name>in2</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>float</type>
+ </source>
+</block>
diff --git a/tools/gr-usrptest/include/usrptest/CMakeLists.txt b/tools/gr-usrptest/include/usrptest/CMakeLists.txt
index 2d5ed3975..761a8bee4 100644
--- a/tools/gr-usrptest/include/usrptest/CMakeLists.txt
+++ b/tools/gr-usrptest/include/usrptest/CMakeLists.txt
@@ -22,5 +22,5 @@
########################################################################
install(FILES
api.h
- DESTINATION include/usrptest
+ measurement_sink_f.h DESTINATION include/usrptest
)
diff --git a/tools/gr-usrptest/include/usrptest/measurement_sink_f.h b/tools/gr-usrptest/include/usrptest/measurement_sink_f.h
new file mode 100644
index 000000000..aaf1fb9d1
--- /dev/null
+++ b/tools/gr-usrptest/include/usrptest/measurement_sink_f.h
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 Ettus Research LLC.
+ *
+ * This 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.
+ *
+ * This software 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 this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_USRPTEST_MEASUREMENT_SINK_F_H
+#define INCLUDED_USRPTEST_MEASUREMENT_SINK_F_H
+
+#include <usrptest/api.h>
+#include <gnuradio/sync_block.h>
+
+namespace gr {
+ namespace usrptest {
+
+ /*!
+ * \brief <+description of block+>
+ * \ingroup usrptest
+ *
+ */
+ class USRPTEST_API measurement_sink_f : virtual public gr::sync_block
+ {
+ public:
+ typedef boost::shared_ptr<measurement_sink_f> sptr;
+
+ /*!
+ * \brief Return a shared_ptr to a new instance of usrptest::measurement_sink_f.
+ *
+ * To avoid accidental use of raw pointers, usrptest::measurement_sink_f's
+ * constructor is in a private implementation
+ * class. usrptest::measurement_sink_f::make is the public interface for
+ * creating new instances.
+ */
+ static sptr make(int num_samples,int runs);
+ virtual std::vector<float> get_avg() const = 0;
+ virtual std::vector<float> get_stddev() const = 0;
+ virtual int get_run() const = 0;
+ virtual void start_run() = 0;
+
+ };
+
+ } // namespace usrptest
+} // namespace gr
+
+#endif /* INCLUDED_USRPTEST_MEASUREMENT_SINK_F_H */
+
diff --git a/tools/gr-usrptest/lib/CMakeLists.txt b/tools/gr-usrptest/lib/CMakeLists.txt
index dd44b7f26..2d8f0fe16 100644
--- a/tools/gr-usrptest/lib/CMakeLists.txt
+++ b/tools/gr-usrptest/lib/CMakeLists.txt
@@ -26,6 +26,7 @@ include_directories(${Boost_INCLUDE_DIR})
link_directories(${Boost_LIBRARY_DIRS})
list(APPEND usrptest_sources
+ measurement_sink_f_impl.cc
)
set(usrptest_sources "${usrptest_sources}" PARENT_SCOPE)
diff --git a/tools/gr-usrptest/lib/measurement_sink_f_impl.cc b/tools/gr-usrptest/lib/measurement_sink_f_impl.cc
new file mode 100644
index 000000000..58faccb9a
--- /dev/null
+++ b/tools/gr-usrptest/lib/measurement_sink_f_impl.cc
@@ -0,0 +1,124 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 Ettus Research LLC.
+ *
+ * This 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.
+ *
+ * This software 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 this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "measurement_sink_f_impl.h"
+
+namespace gr {
+ namespace usrptest {
+
+ measurement_sink_f::sptr
+ measurement_sink_f::make(int num_samples, int runs)
+ {
+ return gnuradio::get_initial_sptr
+ (new measurement_sink_f_impl(num_samples, runs));
+
+ }
+
+ /*
+ * The private constructor
+ */
+ measurement_sink_f_impl::measurement_sink_f_impl(int num_samples, int runs)
+ : gr::sync_block("measurement_sink_f",
+ gr::io_signature::make(1, 1, sizeof(float)),
+ gr::io_signature::make(0, 0, 0)),
+ d_runs(runs),
+ d_nsamples(num_samples)
+ {
+ d_curr_run = 0; // number of completed measurement runs
+ d_curr_avg = 0.0f; // accumulated average
+ d_curr_M2 = 0.0f; // accumulated M2
+ d_run = false; // true if a measurement is currently recorded
+ d_curr_sample = 0; // current sample count
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ measurement_sink_f_impl::~measurement_sink_f_impl()
+ {
+ }
+
+ int
+ measurement_sink_f_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const float *in = (const float *) input_items[0];
+ if ((d_curr_run < d_runs)&&d_run){ //check if we need to record data
+ const int max_items = std::min(noutput_items, d_nsamples-d_curr_sample); // calculate number of samples we have to take into account
+ for (int item=0; item < max_items;++item){
+ ++d_curr_sample;
+ inc_both(in[item]);
+ }
+ if (d_curr_sample == d_nsamples) {
+ d_avg.push_back(d_curr_avg);
+ d_stddev.push_back(std::sqrt(d_curr_M2/(float)(d_curr_sample - 1)));
+ ++d_curr_run;
+ d_run = false;
+ d_curr_sample = 0;
+ d_curr_avg = 0.0f;
+ d_curr_M2 = 0.0f;
+ }
+ }
+ return noutput_items;
+ }
+
+
+ void
+ measurement_sink_f_impl::inc_both(const float new_val)
+ {
+ float delta = new_val - d_curr_avg;
+ d_curr_avg = d_curr_avg + delta/(float)(d_curr_sample);
+ d_curr_M2 = d_curr_M2 + delta*(new_val - d_curr_avg);
+ }
+
+
+ void
+ measurement_sink_f_impl::start_run()
+ {
+ d_run = true;
+ }
+
+ std::vector<float>
+ measurement_sink_f_impl::get_avg() const
+ {
+ return d_avg;
+ }
+
+ std::vector<float>
+ measurement_sink_f_impl::get_stddev() const
+ {
+ return d_stddev;
+ }
+
+ int
+ measurement_sink_f_impl::get_run() const
+ {
+ return d_curr_run;
+ }
+
+ } /* namespace usrptest */
+} /* namespace gr */
+
diff --git a/tools/gr-usrptest/lib/measurement_sink_f_impl.h b/tools/gr-usrptest/lib/measurement_sink_f_impl.h
new file mode 100644
index 000000000..4d63adfa2
--- /dev/null
+++ b/tools/gr-usrptest/lib/measurement_sink_f_impl.h
@@ -0,0 +1,62 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 Ettus Research LLC.
+ *
+ * This 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.
+ *
+ * This software 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 this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_USRPTEST_MEASUREMENT_SINK_F_IMPL_H
+#define INCLUDED_USRPTEST_MEASUREMENT_SINK_F_IMPL_H
+
+#include <usrptest/measurement_sink_f.h>
+
+namespace gr {
+ namespace usrptest {
+
+ class measurement_sink_f_impl : public measurement_sink_f
+ {
+ private:
+ std::vector< float > d_avg;
+ std::vector< float > d_stddev;
+ bool d_run;
+ int d_runs;
+ int d_nsamples;
+ int d_curr_sample;
+ int d_curr_run;
+ float d_curr_avg;
+ float d_curr_M2;
+ void inc_both(const float new_val);
+
+
+ public:
+ measurement_sink_f_impl(int num_samples, int runs);
+ ~measurement_sink_f_impl();
+ std::vector<float> get_avg() const;
+ std::vector<float> get_stddev() const;
+ int get_run() const;
+ void start_run();
+
+ // Where all the action really happens
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace usrptest
+} // namespace gr
+
+#endif /* INCLUDED_USRPTEST_MEASUREMENT_SINK_F_IMPL_H */
+
diff --git a/tools/gr-usrptest/lib/qa_usrptest.cc b/tools/gr-usrptest/lib/qa_usrptest.cc
new file mode 100644
index 000000000..c8e6495ae
--- /dev/null
+++ b/tools/gr-usrptest/lib/qa_usrptest.cc
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012 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.
+ */
+
+/*
+ * This class gathers together all the test cases for the gr-filter
+ * directory into a single test suite. As you create new test cases,
+ * add them here.
+ */
+
+#include "qa_usrptest.h"
+
+CppUnit::TestSuite *
+qa_usrptest::suite()
+{
+ CppUnit::TestSuite *s = new CppUnit::TestSuite("usrptest");
+
+ return s;
+}
diff --git a/tools/gr-usrptest/lib/qa_usrptest.h b/tools/gr-usrptest/lib/qa_usrptest.h
new file mode 100644
index 000000000..94ce3f33b
--- /dev/null
+++ b/tools/gr-usrptest/lib/qa_usrptest.h
@@ -0,0 +1,38 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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 _QA_USRPTEST_H_
+#define _QA_USRPTEST_H_
+
+#include <gnuradio/attributes.h>
+#include <cppunit/TestSuite.h>
+
+//! collect all the tests for the gr-filter directory
+
+class __GR_ATTR_EXPORT qa_usrptest
+{
+ public:
+ //! return suite of tests for all of gr-filter directory
+ static CppUnit::TestSuite *suite();
+};
+
+#endif /* _QA_USRPTEST_H_ */
diff --git a/tools/gr-usrptest/lib/test_usrptest.cc b/tools/gr-usrptest/lib/test_usrptest.cc
new file mode 100644
index 000000000..808638cdf
--- /dev/null
+++ b/tools/gr-usrptest/lib/test_usrptest.cc
@@ -0,0 +1,48 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2012 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <cppunit/TextTestRunner.h>
+#include <cppunit/XmlOutputter.h>
+
+#include <gnuradio/unittests.h>
+#include "qa_usrptest.h"
+#include <iostream>
+#include <fstream>
+
+int
+main (int argc, char **argv)
+{
+ CppUnit::TextTestRunner runner;
+ std::ofstream xmlfile(get_unittest_path("usrptest.xml").c_str());
+ CppUnit::XmlOutputter *xmlout = new CppUnit::XmlOutputter(&runner.result(), xmlfile);
+
+ runner.addTest(qa_usrptest::suite());
+ runner.setOutputter(xmlout);
+
+ bool was_successful = runner.run("", false);
+
+ return was_successful ? 0 : 1;
+}
diff --git a/tools/gr-usrptest/python/CMakeLists.txt b/tools/gr-usrptest/python/CMakeLists.txt
index 4afda600e..ba3d12394 100644
--- a/tools/gr-usrptest/python/CMakeLists.txt
+++ b/tools/gr-usrptest/python/CMakeLists.txt
@@ -31,15 +31,21 @@ endif()
GR_PYTHON_INSTALL(
FILES
__init__.py
- parsers.py
- selftest_fg.py
+ functions.py
phase_calc_ccf.py DESTINATION ${GR_PYTHON_DIR}/usrptest
)
+add_subdirectory(flowgraphs)
+add_subdirectory(labview_control)
+add_subdirectory(rts_tests)
+
########################################################################
# Handle the unit tests
########################################################################
include(GrTest)
+GR_ADD_TEST(qa_phasealignment ${PYTHON_EXECUTABLE}
+ ${CMAKE_CURRENT_SOURCE_DIR}/qa_phasealignment.py)
set(GR_TEST_TARGET_DEPS gnuradio-usrptest)
set(GR_TEST_PYTHON_DIRS ${CMAKE_BINARY_DIR}/swig)
+GR_ADD_TEST(qa_measurement_sink_f ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_measurement_sink_f.py)
diff --git a/tools/gr-usrptest/python/flowgraphs/CMakeLists.txt b/tools/gr-usrptest/python/flowgraphs/CMakeLists.txt
new file mode 100644
index 000000000..7ea94b505
--- /dev/null
+++ b/tools/gr-usrptest/python/flowgraphs/CMakeLists.txt
@@ -0,0 +1,28 @@
+# Copyright 2011 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.
+
+########################################################################
+# Install python sources
+########################################################################
+GR_PYTHON_INSTALL(
+ FILES
+ __init__.py
+ selftest_fg.py
+ phasealignment_fg.py DESTINATION ${GR_PYTHON_DIR}/usrptest/flowgraphs
+)
diff --git a/tools/gr-usrptest/python/flowgraphs/__init__.py b/tools/gr-usrptest/python/flowgraphs/__init__.py
new file mode 100644
index 000000000..048e5638a
--- /dev/null
+++ b/tools/gr-usrptest/python/flowgraphs/__init__.py
@@ -0,0 +1,14 @@
+"""
+usrptest.flowgraphs
+======================================
+
+Contents
+--------
+
+Subpackages
+-----------
+::
+
+The existance of the file turns the folder into a Python module.
+
+"""
diff --git a/tools/gr-usrptest/python/flowgraphs/phasealignment_fg.py b/tools/gr-usrptest/python/flowgraphs/phasealignment_fg.py
new file mode 100644
index 000000000..f120e2421
--- /dev/null
+++ b/tools/gr-usrptest/python/flowgraphs/phasealignment_fg.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python2
+
+from gnuradio import gr
+from gnuradio import uhd
+from gnuradio import analog
+from usrptest import phase_calc_ccf, measurement_sink_f
+from usrptest.functions import log_level
+from random import uniform
+from ast import literal_eval
+import copy
+import logging
+import sys
+
+
+class phasealignment_fg(gr.top_block):
+ def __init__(self, uhd_app):
+ gr.top_block.__init__(self, "Calculate dphi for all USRPs (Rx only)")
+ ##############################
+ # Block dicts
+ ##############################
+ self.log = logging.getLogger(__name__)
+ [self.log.removeHandler(h) for h in self.log.handlers]
+ self.log.addHandler(logging.StreamHandler(sys.stdout))
+ self.log.setLevel(log_level(uhd_app.args.log_level))
+ self.rx_streams = list()
+ self.phase_diff_calc = list()
+ self.measurement_sink = list()
+ self.uhd_app = copy.copy(uhd_app)
+ self.tx_app = copy.copy(uhd_app)
+ self.samp_rate = uhd_app.args.samp_rate
+ # Create all devices specified in --receiver
+ # Create all remaining blocks and connect devices to the first port and
+ # sink
+ self.uhd_app.args.num_chan = len(self.uhd_app.args.channels)
+ self.log.info('setting up usrp....')
+ ##############################
+ # Setup RX
+ ##############################
+ self.log.debug("RX-Setup with args: {}".format(self.uhd_app.args))
+ self.uhd_app.setup_usrp(uhd.usrp_source, self.uhd_app.args)
+ if self.uhd_app.args.measurement_setup is not None:
+ self.measurement_channels = self.uhd_app.args.measurement_setup.strip(
+ ).split(',')
+ # make sure every channels is listed in measurement_channels at least once
+ if len(set(
+ self.measurement_channels)) != self.uhd_apps.args.num_chan:
+ self.uhd_app.vprint(
+ "[{prefix}] Number of measurement channels has to be the number of used channels."
+ )
+ self.uhd_app.exit(1)
+ self.measurement_channels = [self.uhd_app.args.channels.index(m) for m in self.measurement_channels]
+ else:
+ self.measurement_channels = range(self.uhd_app.args.num_chan)
+
+ self.measurement_channels_names = list()
+ for chan in self.measurement_channels:
+ usrp_info = self.uhd_app.usrp.get_usrp_info(chan)
+ self.measurement_channels_names.append("_".join(
+ [usrp_info['mboard_serial'], usrp_info['rx_serial']]))
+
+ #Connect channels to first port of d_phi_calc_block and to measurement_sink
+ for num, chan in enumerate(self.measurement_channels[:-1]):
+ self.phase_diff_calc.append(phase_calc_ccf())
+ self.measurement_sink.append(
+ measurement_sink_f(
+ int(self.uhd_app.args.samp_rate *
+ self.uhd_app.args.duration), self.uhd_app.args.runs))
+ self.connect((self.uhd_app.usrp, chan),
+ (self.phase_diff_calc[num], 0))
+ self.connect((self.phase_diff_calc[num], 0),
+ (self.measurement_sink[num], 0))
+ # Connect devices to second port of d_phi_block
+ for num, chan in enumerate(self.measurement_channels[1:]):
+ self.connect((self.uhd_app.usrp, chan),
+ (self.phase_diff_calc[num], 1))
+ ##############################
+ # Setup TX
+ ##############################
+ if self.uhd_app.args.tx_channels is not None:
+ self.tx_app.args.antenna = self.tx_app.args.tx_antenna
+ self.tx_app.args.channels = [
+ int(chan.strip())
+ for chan in self.tx_app.args.tx_channels.split(',')
+ ]
+ self.tx_app.usrp = None
+ self.log.debug("TX-Setup with args: {}".format(self.tx_app.args))
+ self.tx_app.setup_usrp(uhd.usrp_sink, self.tx_app.args)
+ self.siggen = analog.sig_source_c(self.samp_rate,
+ analog.GR_COS_WAVE,
+ self.tx_app.args.tx_offset, 1.0)
+ for chan in range(len(self.tx_app.channels)):
+ self.connect((self.siggen, 0), (self.tx_app.usrp, chan))
+
+
+ def get_samp_rate(self):
+ return self.samp_rate
+
+ def set_samp_rate(self, samp_rate):
+ self.samp_rate = samp_rate
+
+ def retune_frequency(self, band_num=1, bands=1):
+ ref_chan = self.uhd_app.channels[0]
+ freq_range = literal_eval(
+ self.uhd_app.usrp.get_freq_range(ref_chan).__str__(
+ )) # returns tuple with (start_freq, end_freq, step)
+
+ if bands > 1:
+ bw = (freq_range[1] - freq_range[0])/bands
+ freq_range = list(freq_range)
+ freq_range[0] = freq_range[0] + ((band_num-1) % bands)*bw
+ freq_range[1] = freq_range[0] + bw
+
+ retune_freq = uniform(freq_range[0], freq_range[1])
+ self.log.info('tune all channels to: {:f} MHz'.format(retune_freq /
+ 1e6))
+ self.uhd_app.set_freq(retune_freq)
+ self.log.info('tune all channels to: {:f} MHz'.format(
+ self.uhd_app.args.freq / 1e6))
+ self.uhd_app.set_freq(self.uhd_app.args.freq)
diff --git a/tools/gr-usrptest/python/flowgraphs/selftest_fg.py b/tools/gr-usrptest/python/flowgraphs/selftest_fg.py
new file mode 100644
index 000000000..cdfc35e74
--- /dev/null
+++ b/tools/gr-usrptest/python/flowgraphs/selftest_fg.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+
+from gnuradio import blocks
+from gnuradio import gr
+from gnuradio import uhd
+from usrptest import phase_calc_ccf
+from gnuradio.uhd.uhd_app import UHDApp
+import numpy as np
+
+class selftest_fg(gr.top_block):
+
+ def __init__(self, freq, samp_rate, dphase, devices=list()):
+ gr.top_block.__init__(self, "Generate Signal extract phase")
+
+ ##################################################
+ # Variables
+ ##################################################
+ self.samp_rate = samp_rate
+ self.freq = 10e3
+ self.devices = devices
+ self.dphase = dphase
+ self.tx_gain = 50
+ self.rx_gain = 50
+ self.center_freq = freq
+ self.omega = 2*np.pi*self.freq
+ self.steps = np.arange(
+ self.samp_rate)*float(self.omega)/float(self.samp_rate)
+ self.reference = self.complex_sine(self.steps)
+ self.test_signal = self.complex_sine(self.steps+0.5*np.pi)
+ self.device_test = False
+
+ ##################################################
+ # Block dicts
+ ##################################################
+ self.rx_devices = dict()
+ self.tx_devices = dict()
+ self.sink_dict = dict()
+ self.phase_dict = dict()
+ self.reference_source = blocks.vector_source_c(self.reference)
+
+ if len(self.devices):
+ ##################################################
+ # Devices
+ ##################################################
+ self.device_test = True
+ #To reuse existing setup_usrp() command
+ for device in self.devices:
+ # Create and configure all devices
+ self.rx_devices[device] = uhd.usrp_source(
+ device, uhd.stream_args(
+ cpu_format="fc32", channel=range(1)))
+ self.tx_devices[device] = uhd.usrp_sink(
+ device, uhd.stream_args(
+ cpu_format="fc32", channel=range(1)))
+ self.rx_devices[device].set_samp_rate(self.samp_rate)
+ self.rx_devices[device].set_center_freq(self.center_freq, 0)
+ self.rx_devices[device].set_gain(self.rx_gain, 0)
+ self.tx_devices[device].set_samp_rate(self.samp_rate)
+ self.tx_devices[device].set_center_freq(self.center_freq, 0)
+ self.tx_devices[device].set_gain(self.tx_gain, 0)
+ self.sink_dict[device] = blocks.vector_sink_f()
+ self.phase_dict[device] = phase_calc_ccf(
+ self.samp_rate, self.freq)
+ for device in self.tx_devices.values():
+ self.connect((self.reference_source, 0), (device, 0))
+
+ for device_key in self.rx_devices.keys():
+ self.connect(
+ (self.rx_devices[device_key], 0), (self.phase_dict[device_key], 0))
+ self.connect((self.reference_source, 0),
+ (self.phase_dict[device_key], 1))
+ self.connect(
+ (self.phase_dict[device_key], 0), (self.sink_dict[device_key], 0))
+ # Debug options
+ # self.sink_list.append(blocks.vector_sink_c())
+ #self.connect((device, 0), (self.sink_list[-1], 0))
+ # self.sink_list.append(blocks.vector_sink_c())
+ #self.connect((self.reference_source, 0), (self.sink_list[-1], 0))
+ else:
+ ##################################################
+ # Blocks
+ ##################################################
+ self.result = blocks.vector_sink_f(1)
+ self.test_source = blocks.vector_source_c(self.test_signal)
+ self.block_phase_calc = phase_calc_ccf(
+ self.samp_rate, self.freq)
+
+ ##################################################
+ # Connections
+ ##################################################
+ self.connect((self.reference_source, 0), (self.block_phase_calc, 1))
+ self.connect((self.test_source, 0), (self.block_phase_calc, 0))
+ self.connect((self.block_phase_calc, 0), (self.result, 0))
+ def complex_sine(self, steps):
+ return np.exp(1j*steps)
+
+ def get_samp_rate(self):
+ return self.samp_rate
+
+ def set_samp_rate(self, samp_rate):
+ self.samp_rate = samp_rate
+
+ def run(self):
+ self.start()
+ self.wait()
+ if self.device_test:
+ data = dict()
+ for device_key in self.sink_dict.keys():
+ curr_data = self.sink_dict[device_key].data()
+ curr_data = curr_data[int(0.2*self.samp_rate):-int(0.2*self.samp_rate)]
+ phase_avg = np.average(curr_data)
+ if (np.max(curr_data) < phase_avg+self.dphase*0.5) and (np.min(curr_data) > phase_avg-self.dphase*0.5):
+ data[device_key] = phase_avg
+ else:
+ print("Error phase not settled")
+
+ #Debug
+ # plt.ylim(-1, 1)
+ # plt.xlim(self.samp_rate/2.), (self.samp_rate/2.)+1000)
+ #for key in data:
+ # plt.plot(data[key])
+ return data
diff --git a/tools/gr-usrptest/python/functions.py b/tools/gr-usrptest/python/functions.py
new file mode 100644
index 000000000..e3f7958b1
--- /dev/null
+++ b/tools/gr-usrptest/python/functions.py
@@ -0,0 +1,133 @@
+#!/usr/bin/env python2
+import numpy as np
+import time
+import copy
+import logging
+
+
+def setup_phase_alignment_parser(parser):
+ test_group = parser.add_argument_group(
+ 'Phase alignment specific arguments')
+ test_group.add_argument(
+ '--runs',
+ default=10,
+ type=int,
+ help='Number of times to retune and measure d_phi')
+ test_group.add_argument(
+ '--duration',
+ default=5.0,
+ type=float,
+ help='Duration of a measurement run')
+ test_group.add_argument(
+ '--measurement-setup',
+ type=str,
+ help='Comma-seperated list of channel ids. Phase difference will be calculated between consecutive channels. default=(0,1,2,..,M-1) M: num_chan'
+ )
+ test_group.add_argument(
+ '--log-level',
+ type=str,
+ choices=["critical", "error", "warning", "info", "debug"],
+ default="info")
+ test_group.add_argument(
+ '--freq-bands',
+ type=int,
+ help="Number of frequency bands in daughterboard range to randomly retune to",
+ default=1)
+ return parser
+
+
+def setup_tx_phase_alignment_parser(parser):
+ tx_group = parser.add_argument_group(
+ 'TX Phase alignment specific arguments.')
+ tx_group.add_argument(
+ '--tx-channels', type=str, help='which channels to use')
+ tx_group.add_argument(
+ '--tx-antenna',
+ type=str,
+ help='comma-separated list of channel antennas for tx')
+ tx_group.add_argument(
+ '--tx-offset',
+ type=float,
+ help='frequency offset in Hz which should be added to center frequency for transmission'
+ )
+ return parser
+
+
+def setup_rts_phase_alignment_parser(parser):
+ rts_group = parser.add_argument_group('RTS Phase alignment specific arguments')
+ rts_group.add_argument(
+ '-pd', '--phasedev',
+ type=float,
+ default=1.0,
+ help='maximum phase standard deviation of dphi in a run which is considered settled (in deg)')
+ rts_group.add_argument(
+ '-dp',
+ '--dphi',
+ type=float,
+ default=2.0,
+ help='maximum allowed d_phase deviation between runs (in deg)')
+ return parser
+
+def setup_manual_phase_alignment_parser(parser):
+ manual_group = parser.add_argument_group(
+ 'Manual Phase alignment specific arguments')
+ manual_group.add_argument(
+ '--plot',
+ dest='plot',
+ action='store_true',
+ help='Set this argument to enable plotting results with matplotlib'
+ )
+ manual_group.add_argument(
+ '--auto',
+ action='store_true',
+ help='Set this argument to enable automatic selection of test frequencies'
+ )
+ manual_group.add_argument(
+ '--start-freq',
+ type=float,
+ default=0.0,
+ help='Start frequency for automatic selection'
+ ),
+ manual_group.add_argument(
+ '--stop-freq',
+ type=float,
+ default=0.0,
+ help='Stop frequency for automatic selection')
+
+ parser.set_defaults(plot=False,auto=False)
+ return parser
+
+
+def process_measurement_sinks(top_block):
+ data = list()
+ curr_data = dict()
+ for num, chan in enumerate(top_block.measurement_channels[:-1]):
+ curr_data['avg'] = list(top_block.measurement_sink[num].get_avg())
+ curr_data['stddev'] = list(top_block.measurement_sink[num].get_stddev(
+ ))
+ curr_data['first'] = top_block.measurement_channels_names[num]
+ curr_data['second'] = top_block.measurement_channels_names[num + 1]
+ data.append(copy.copy(curr_data))
+ return data
+
+
+def run_test(top_block, ntimes):
+ results = dict()
+ num_sinks = len(top_block.measurement_sink)
+ for i in xrange(ntimes):
+ #tune frequency to random position and back to specified frequency
+ top_block.retune_frequency(bands=top_block.uhd_app.args.freq_bands,band_num=i+1)
+ time.sleep(2)
+ #trigger start in all measurement_sinks
+ for sink in top_block.measurement_sink:
+ sink.start_run()
+ #wait until every measurement_sink is ready with the current run
+ while (sum([ms.get_run() for ms in top_block.measurement_sink]) < (
+ (i + 1) * num_sinks)):
+ time.sleep(1)
+ results = process_measurement_sinks(top_block)
+ return results
+
+
+def log_level(string):
+ return getattr(logging, string.upper())
diff --git a/tools/gr-usrptest/python/phase_calc_ccf.py b/tools/gr-usrptest/python/phase_calc_ccf.py
new file mode 100644
index 000000000..fe3cf55a8
--- /dev/null
+++ b/tools/gr-usrptest/python/phase_calc_ccf.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2016 Ettus Research LLC.
+#
+# This 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.
+#
+# This software 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 this software; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr
+from gnuradio import blocks
+import numpy as np
+
+
+class phase_calc_ccf(gr.hier_block2):
+ """
+ docstring for block phase_calc_ccf
+ """
+
+ def __init__(self):
+ gr.hier_block2.__init__(
+ self,
+ "phase_calc_ccf",
+ gr.io_signature(2, 2, gr.sizeof_gr_complex), # Input signature
+ gr.io_signature(1, 1, gr.sizeof_float)) # Output signature
+ self.block = dict()
+ self.block['mult_conj'] = blocks.multiply_conjugate_cc()
+ self.block['arg'] = blocks.complex_to_arg()
+ self.block['mult_const'] = blocks.multiply_const_ff(180.0 / np.pi)
+
+ self.connect((self, 0), (self.block['mult_conj'], 0))
+ self.connect((self, 1), (self.block['mult_conj'], 1))
+ self.connect((self.block['mult_conj'], 0), (self.block['arg'], 0))
+ self.connect((self.block['arg'], 0), (self.block['mult_const'], 0))
+ self.connect((self.block['mult_const'], 0), (self, 0))
diff --git a/tools/gr-usrptest/python/qa_measurement_sink_f.py b/tools/gr-usrptest/python/qa_measurement_sink_f.py
new file mode 100755
index 000000000..ceb9913ae
--- /dev/null
+++ b/tools/gr-usrptest/python/qa_measurement_sink_f.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2016 Ettus Research LLC.
+#
+# This 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.
+#
+# This software 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 this software; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+from gnuradio import blocks
+import usrptest_swig as usrptest
+
+class qa_measurement_sink_f (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001_t (self):
+ # set up fg
+ self.tb.run ()
+ # check data
+
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_measurement_sink_f, "qa_measurement_sink_f.xml")
diff --git a/tools/gr-usrptest/python/rts_tests/CMakeLists.txt b/tools/gr-usrptest/python/rts_tests/CMakeLists.txt
new file mode 100644
index 000000000..fbe49995a
--- /dev/null
+++ b/tools/gr-usrptest/python/rts_tests/CMakeLists.txt
@@ -0,0 +1,27 @@
+# Copyright 2011 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.
+
+########################################################################
+# Install python sources
+########################################################################
+GR_PYTHON_INSTALL(
+ FILES
+ __init__.py
+ test_phasealignment.py DESTINATION ${GR_PYTHON_DIR}/usrptest/rts_tests
+)
diff --git a/tools/gr-usrptest/python/rts_tests/__init__.py b/tools/gr-usrptest/python/rts_tests/__init__.py
new file mode 100644
index 000000000..048e5638a
--- /dev/null
+++ b/tools/gr-usrptest/python/rts_tests/__init__.py
@@ -0,0 +1,14 @@
+"""
+usrptest.flowgraphs
+======================================
+
+Contents
+--------
+
+Subpackages
+-----------
+::
+
+The existance of the file turns the folder into a Python module.
+
+"""
diff --git a/tools/gr-usrptest/python/rts_tests/test_phasealignment.py b/tools/gr-usrptest/python/rts_tests/test_phasealignment.py
new file mode 100644
index 000000000..10642f298
--- /dev/null
+++ b/tools/gr-usrptest/python/rts_tests/test_phasealignment.py
@@ -0,0 +1,121 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2016 Ettus Research LLC.
+#
+# This 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.
+#
+# This software 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 this software; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+import unittest
+from tinydb import TinyDB, Query
+from usrptest.flowgraphs import phasealignment_fg
+from usrptest.functions import setup_phase_alignment_parser, run_test
+from gnuradio.uhd.uhd_app import UHDApp
+import numpy as np
+import argparse
+import time
+
+class gr_usrp_test(unittest.TestCase):
+ def __init__(self, methodName='runTest', args=None):
+ super(gr_usrp_test,self).__init__(methodName)
+ self.args = args
+
+class qa_phasealignment(gr_usrp_test):
+ def setUp(self):
+ self.uhd_app = UHDApp(args=self.args)
+ self.tb = phasealignment_fg.phasealignment_fg(self.uhd_app)
+ self.db = TinyDB('phase_db.json')
+
+ def tearDown(self):
+ self.uhd_app = None
+ self.tb = None
+
+ def test_001(self):
+ self.tb.start()
+ time.sleep(2)
+ results = run_test(self.tb,self.args.runs) # dict key:dev, value: dict{dphase:[],stddev:[]}
+ time.sleep(1)
+ self.first_device = self.tb.measurement_channels_names[:-1]
+ self.second_device = self.tb.measurement_channels_names[1:]
+ #self.tb.stop()
+ #self.tb.wait()
+ self.time_stamp = time.strftime('%Y%m%d%H%M')
+ self.passed = True
+ for fdev, sdev in zip(self.first_device,self.second_device):
+ print('Comparing values for phase difference between {} and {}'.format(fdev, sdev))
+ dphase_list = results[fdev]['avg']
+ dev_list = results[fdev]['stddev']
+ dphase = np.average(dphase_list)
+ dev = np.average(dev_list)
+ ref_meas = get_reference_meas(self.db, fdev, sdev, self.args.freq)
+ for dphase_i in dphase_list:
+ passed = True
+ if abs(dphase_i - dphase) > self.args.dphi and passed:
+ print('\t dPhase of a measurement_run differs from average dhpase. dphase_run: {}, dphase_avg: {}'.format(dphase_i, dphase))
+ passed = False
+ if dev > self.args.phasedev:
+ print('\t dPhase deviates during measurement. stddev: {}'.format(dev))
+ passed = False
+ if ref_meas:
+ if abs(ref_meas['dphase'] - dphase) > self.args.dphi:
+ print('\t dPhase differs from reference measurement. Now: {}, reference: {}'.format(dphase, ref_meas['dphase']))
+ if not passed:
+ self.passed = False
+ else:
+ self.db.insert({'dev1':fdev, 'dev2':sdev, 'timestamp':self.time_stamp, 'dphase':dphase, 'dphase_dev': dev, 'freq': self.args.freq})
+ self.tb.stop()
+ self.assertTrue(self.passed)
+
+def get_previous_meas(db, dev1, dev2, freq):
+ meas = Query()
+ results = db.search((meas.dev1 == dev1) & (meas.dev2 == dev2) & (meas.freq == freq))
+ prev_result = dict()
+ if results:
+ prev_result = results[0]
+ for result in results:
+ if result['timestamp'] > prev_result['timestamp']:
+ prev_result = result
+ return prev_result
+
+def get_reference_meas(db, dev1, dev2, freq):
+ meas = Query()
+ results = db.search((meas.dev1 == dev1) & (meas.dev2 == dev2) & (meas.freq == freq))
+ ref_result = dict()
+ if results:
+ ref_result = results[0]
+ for result in results:
+ if result['timestamp'] < ref_result['timestamp']:
+ ref_result = result
+ return ref_result
+
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(conflict_handler='resolve')
+ parser = setup_phase_alignment_parser(parser)
+ UHDApp.setup_argparser(parser=parser)
+ args = parser.parse_args()
+ def make_suite(testcase_class):
+ testloader = unittest.TestLoader()
+ testnames = testloader.getTestCaseNames(testcase_class)
+ suite = unittest.TestSuite()
+ for name in testnames:
+ suite.addTest(testcase_class(name, args=args))
+ return suite
+
+ # Add tests.
+ alltests = unittest.TestSuite()
+ alltests.addTest(make_suite(qa_phasealignment))
+ result = unittest.TextTestRunner(verbosity=2).run(alltests) # Run tests.
diff --git a/tools/gr-usrptest/swig/usrptest_swig.i b/tools/gr-usrptest/swig/usrptest_swig.i
index c6988262e..273b7c866 100644
--- a/tools/gr-usrptest/swig/usrptest_swig.i
+++ b/tools/gr-usrptest/swig/usrptest_swig.i
@@ -8,6 +8,9 @@
%include "usrptest_swig_doc.i"
%{
+#include "usrptest/measurement_sink_f.h"
%}
+%include "usrptest/measurement_sink_f.h"
+GR_SWIG_BLOCK_MAGIC2(usrptest, measurement_sink_f);