aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xtools/gr-usrptest/examples/lv_control_example.py81
-rw-r--r--tools/gr-usrptest/python/functions.py30
-rw-r--r--tools/gr-usrptest/python/labview_control/CMakeLists.txt28
-rw-r--r--tools/gr-usrptest/python/labview_control/__init__.py14
-rw-r--r--tools/gr-usrptest/python/labview_control/lv_control.py87
-rw-r--r--tools/gr-usrptest/python/rts_tests/CMakeLists.txt6
-rwxr-xr-x[-rw-r--r--]tools/gr-usrptest/python/rts_tests/test_phasealignment.py93
-rw-r--r--tools/gr-usrptest/python/setup.py13
8 files changed, 329 insertions, 23 deletions
diff --git a/tools/gr-usrptest/examples/lv_control_example.py b/tools/gr-usrptest/examples/lv_control_example.py
new file mode 100755
index 000000000..dc2a7be2f
--- /dev/null
+++ b/tools/gr-usrptest/examples/lv_control_example.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+
+from usrptest.labview_control import lv_control
+import time
+import numpy as np
+import argparse
+import sys
+
+def test00(freq, frange, steps):
+ freqrange = np.arange(freq,freq+frange,steps)
+ source = 'VST-Out'
+ sink = 'X3x0-4-B-RX2'
+ host = 'pollux'
+ base_path = 'C:\Users\sdrtest\git\labview-test\labview\RTS_Control\Host\\'
+ print('connecting to switch')
+ switch = lv_control.executive_switch(host,base_path,'RTSwitch')
+ print('connecting to siggen')
+ siggen = lv_control.vst_siggen(host,base_path,'RIO0')
+ # Configure RF-Switching
+ switch.connect_ports(source, sink)
+
+ # Sweep over freqrange
+ for freq in freqrange:
+ siggen.set_freq(float(freq))
+ time.sleep(1)
+ # Shutdown Siggen
+ siggen.disconnect()
+ switch.disconnect_all()
+
+def test01(freq, frange, steps):
+ freqrange = np.arange(freq,freq+frange,steps)
+ source = 'VST-Out'
+ sink0 = 'X3x0-4-B-RX2'
+ sink1 = 'X3x0-2-B-RX2'
+ host = 'pollux'
+ base_path = 'C:\Users\sdrtest\git\labview-test\labview\RTS_Control\Host\\'
+ print('connecting to switch')
+ switch = lv_control.executive_switch(host,base_path,'RTSwitch')
+ print('connecting to siggen')
+ siggen = lv_control.vst_siggen(host,base_path,'RIO0')
+ for freq in freqrange:
+ siggen.set_freq(float(freq))
+ print('retuning siggen to {freq} MHz'.format(freq=freq/1e6))
+ switch.connect_ports(source,sink0)
+ time.sleep(0.5)
+ switch.connect_ports(source,sink1)
+ time.sleep(0.5)
+ switch.disconnect_all()
+ time.sleep(0.2)
+ siggen.disconnect()
+ switch.disconnect_all()
+
+
+if __name__ == '__main__':
+ thismodule = sys.modules[__name__]
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '-t',
+ '--test',
+ help='which testcase?'
+ )
+ parser.add_argument(
+ '-f',
+ '--freq',
+ type=float,
+ help='which center freq?'
+ )
+ parser.add_argument(
+ '-r',
+ '--range',
+ type=float,
+ help='which freq range?'
+ )
+ parser.add_argument(
+ '--steps',
+ type=float,
+ default=1e6,
+ help='which frequency step size?'
+ )
+ args = parser.parse_args()
+ getattr(thismodule,args.test)(args.freq,args.range,args.steps)
diff --git a/tools/gr-usrptest/python/functions.py b/tools/gr-usrptest/python/functions.py
index e3f7958b1..2ce2ee451 100644
--- a/tools/gr-usrptest/python/functions.py
+++ b/tools/gr-usrptest/python/functions.py
@@ -54,18 +54,42 @@ def setup_tx_phase_alignment_parser(parser):
def setup_rts_phase_alignment_parser(parser):
- rts_group = parser.add_argument_group('RTS Phase alignment specific arguments')
+ rts_group = parser.add_argument_group(
+ 'RTS Phase alignment specific arguments')
rts_group.add_argument(
- '-pd', '--phasedev',
+ '-pd',
+ '--phasedev',
type=float,
default=1.0,
- help='maximum phase standard deviation of dphi in a run which is considered settled (in deg)')
+ 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)')
+ rts_group.add_argument(
+ '--freqlist',
+ type=str,
+ help='comma-separated list of frequencies to test')
+ rts_group.add_argument(
+ '--lv-host',
+ type=str,
+ help='specify this argument if running tests with vst/switch')
+ rts_group.add_argument('--lv-vst-name', type=str, help='vst device name')
+ rts_group.add_argument(
+ '--lv-switch-name', type=str, help='executive switch name')
+ rts_group.add_argument(
+ '--lv-basepath',
+ type=str,
+ help='basepath for LabVIEW VIs on Windows')
+ rts_group.add_argument(
+ '--tx-offset',
+ type=float,
+ help='transmitter frequency offset in VST')
+ rts_group.add_argument(
+ '--lv-switch-ports', type=str, help='comma-separated switch-port pair')
return parser
def setup_manual_phase_alignment_parser(parser):
diff --git a/tools/gr-usrptest/python/labview_control/CMakeLists.txt b/tools/gr-usrptest/python/labview_control/CMakeLists.txt
new file mode 100644
index 000000000..924df5479
--- /dev/null
+++ b/tools/gr-usrptest/python/labview_control/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
+ lv_control.py DESTINATION ${GR_PYTHON_DIR}/usrptest/labview_control
+)
+
diff --git a/tools/gr-usrptest/python/labview_control/__init__.py b/tools/gr-usrptest/python/labview_control/__init__.py
new file mode 100644
index 000000000..28d2fe03b
--- /dev/null
+++ b/tools/gr-usrptest/python/labview_control/__init__.py
@@ -0,0 +1,14 @@
+"""
+usrptest.labview_control
+======================================
+
+Contents
+--------
+
+Subpackages
+-----------
+::
+
+The existance of the file turns the folder into a Python module.
+
+"""
diff --git a/tools/gr-usrptest/python/labview_control/lv_control.py b/tools/gr-usrptest/python/labview_control/lv_control.py
new file mode 100644
index 000000000..27407a07c
--- /dev/null
+++ b/tools/gr-usrptest/python/labview_control/lv_control.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+from labview_automation.client import LabVIEWClient
+
+class vst_siggen:
+ def __init__(self,host,vi_base_path,rio_device):
+ self._host = host
+ self._path = vi_base_path
+ self._rio = rio_device
+ self._caller = lv_caller(host,2552,vi_base_path)
+
+ def __del__(self):
+ self.disconnect()
+
+ def set_freq(self, freq):
+ self._caller.vst_set_freq(self._rio,freq)
+
+ def disconnect(self):
+ try:
+ self._caller.vst_disconnect(self._rio)
+ except:
+ pass
+
+
+class executive_switch:
+ def __init__(self,host,vi_base_path,device_name):
+ self._host = host
+ self._path = vi_base_path
+ self._device = device_name
+ self._caller = lv_caller(host,2552,vi_base_path)
+
+ def __del__(self):
+ self.disconnect_all()
+
+ def connect_ports(self, port0, port1):
+ self._caller.switch_connect_ports(self._device,port0,port1)
+
+ def disconnect_all(self):
+ try:
+ self._caller.switch_disconnect_all(self._device)
+ except:
+ pass
+
+
+
+class lv_caller:
+ def __init__(self, host, port, vi_base_path):
+ self._host = host
+ self._port = port
+ self._client = LabVIEWClient(host, port)
+ self._path = vi_base_path
+
+ def vst_disconnect(self, rio_device):
+ with self._client as c:
+ control_values = {
+ "rio_device": rio_device,
+ }
+ result = c.run_vi_synchronous("".join([self._path,"vst_disconnect.vi"]),control_values)
+ return result
+
+ def vst_set_freq(self, rio_device, freq):
+ with self._client as c:
+ control_values = {
+ "rio_device": rio_device,
+ "cw_freq": freq,
+ "power": 0,
+ }
+ result = c.run_vi_synchronous("".join([self._path,"vst_set_freq.vi"]),control_values)
+ return result
+
+ def switch_connect_ports(self, switch_device, port0, port1):
+ with self._client as c:
+ control_values = {
+ "virtual_switch": switch_device,
+ "chan0": port0,
+ "chan1": port1,
+ }
+ result = c.run_vi_synchronous("".join([self._path,"switch_connect_ports.vi"]),control_values)
+ return result
+
+
+ def switch_disconnect_all(self, switch_device):
+ with self._client as c:
+ control_values = {
+ "virtual_switch": switch_device,
+ }
+ result = c.run_vi_synchronous("".join([self._path,"switch_disconnect.vi"]),control_values)
+ return result
diff --git a/tools/gr-usrptest/python/rts_tests/CMakeLists.txt b/tools/gr-usrptest/python/rts_tests/CMakeLists.txt
index fbe49995a..03111a9bb 100644
--- a/tools/gr-usrptest/python/rts_tests/CMakeLists.txt
+++ b/tools/gr-usrptest/python/rts_tests/CMakeLists.txt
@@ -25,3 +25,9 @@ GR_PYTHON_INSTALL(
__init__.py
test_phasealignment.py DESTINATION ${GR_PYTHON_DIR}/usrptest/rts_tests
)
+
+GR_PYTHON_INSTALL(
+ PROGRAMS
+ test_phasealignment.py
+ DESTINATION bin
+)
diff --git a/tools/gr-usrptest/python/rts_tests/test_phasealignment.py b/tools/gr-usrptest/python/rts_tests/test_phasealignment.py
index 10642f298..12856bbdb 100644..100755
--- a/tools/gr-usrptest/python/rts_tests/test_phasealignment.py
+++ b/tools/gr-usrptest/python/rts_tests/test_phasealignment.py
@@ -21,66 +21,106 @@
import unittest
from tinydb import TinyDB, Query
from usrptest.flowgraphs import phasealignment_fg
-from usrptest.functions import setup_phase_alignment_parser, run_test
+from usrptest.functions import setup_phase_alignment_parser, setup_tx_phase_alignment_parser, setup_rts_phase_alignment_parser, run_test, log_level
+from usrptest.labview_control import lv_control
from gnuradio.uhd.uhd_app import UHDApp
+import logging
+import sys
import numpy as np
import argparse
import time
+import copy
+
class gr_usrp_test(unittest.TestCase):
def __init__(self, methodName='runTest', args=None):
- super(gr_usrp_test,self).__init__(methodName)
+ super(gr_usrp_test, self).__init__(methodName)
self.args = args
+
class qa_phasealignment(gr_usrp_test):
def setUp(self):
+ time.sleep(15) #Wait for devices to settle, just in case
+ if self.args.lv_host is not None:
+ self.siggen = lv_control.vst_siggen(self.args.lv_host,
+ self.args.lv_basepath,
+ self.args.lv_vst_name)
+ self.switch = lv_control.executive_switch(self.args.lv_host,
+ self.args.lv_basepath,
+ self.args.lv_switch_name)
+ self.siggen.set_freq(self.args.freq + self.args.tx_offset)
+ self.switch.connect_ports(
+ *self.args.lv_switch_ports.strip().split(','))
+
self.uhd_app = UHDApp(args=self.args)
+ self.log = logging.getLogger("test_phasealignment")
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
+ if args.lv_host is not None:
+ self.siggen.disconnect()
+ self.switch.disconnect_all()
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:[]}
+ 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']
+ for result in results:
+ fdev = result['first']
+ sdev = result['second']
+ self.log.info('Comparing values for phase difference between {} and {}'.
+ format(fdev, sdev))
+ dphase_list = result['avg']
+ dev_list = result['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))
+ self.log.info(
+ '\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))
+ self.log.info('\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']))
+ self.log.info(
+ '\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.db.insert({
+ 'dev1': fdev,
+ 'dev2': sdev,
+ 'timestamp': self.time_stamp,
+ 'dphase': dphase,
+ 'dphase_dev': dev,
+ 'freq': self.args.freq
+ })
self.tb.stop()
+ self.tb.wait()
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))
+ results = db.search((meas.dev1 == dev1) & (meas.dev2 == dev2) & (meas.freq
+ == freq))
prev_result = dict()
if results:
prev_result = results[0]
@@ -89,9 +129,11 @@ def get_previous_meas(db, dev1, dev2, freq):
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))
+ results = db.search((meas.dev1 == dev1) & (meas.dev2 == dev2) & (meas.freq
+ == freq))
ref_result = dict()
if results:
ref_result = results[0]
@@ -101,21 +143,32 @@ def get_reference_meas(db, dev1, dev2, freq):
return ref_result
-
if __name__ == '__main__':
+ # parse all arguments
parser = argparse.ArgumentParser(conflict_handler='resolve')
parser = setup_phase_alignment_parser(parser)
+ parser = setup_tx_phase_alignment_parser(parser)
+ parser = setup_rts_phase_alignment_parser(parser)
+ logging.basicConfig(stream=sys.stdout)
UHDApp.setup_argparser(parser=parser)
args = parser.parse_args()
- def make_suite(testcase_class):
+ logging.getLogger("test_phasealignment").setLevel(log_level(args.log_level))
+
+ freqlist = args.freqlist.strip().split(',')
+
+ def make_suite(testcase_class, freqlist):
testloader = unittest.TestLoader()
testnames = testloader.getTestCaseNames(testcase_class)
suite = unittest.TestSuite()
for name in testnames:
- suite.addTest(testcase_class(name, args=args))
+ for freq in freqlist:
+ test_args = copy.deepcopy(args)
+ test_args.freq = float(freq)
+ suite.addTest(testcase_class(name, args=test_args))
return suite
# Add tests.
alltests = unittest.TestSuite()
- alltests.addTest(make_suite(qa_phasealignment))
- result = unittest.TextTestRunner(verbosity=2).run(alltests) # Run tests.
+ alltests.addTest(make_suite(qa_phasealignment, freqlist))
+ result = unittest.TextTestRunner(verbosity=2).run(alltests) # Run tests.
+ sys.exit(not result.wasSuccessful())
diff --git a/tools/gr-usrptest/python/setup.py b/tools/gr-usrptest/python/setup.py
new file mode 100644
index 000000000..6969f413d
--- /dev/null
+++ b/tools/gr-usrptest/python/setup.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+try:
+ from setuptools import setup
+except ImportError:
+ from distutils.core import setup
+
+
+setup(name='urptest_automation',
+ version='0.0.1',
+ description='usrptest integration into RTS and Labview',
+ packages=['usrptest_automation'],
+ install_requires=['labview-automation>=15.0.0.dev1','hoplite>=15.0.0.dev1']
+ )