diff options
157 files changed, 3100 insertions, 1841 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index dfdca5d9bf..6136cbc22e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ endif(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) ######################################################################## # Make sure this version matches ${GR_CMAKE_MIN_VERSION} (a variable can't be # used here). -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.5.1) project(gnuradio CXX C) enable_testing() @@ -53,9 +53,9 @@ SET(VERSION_INFO_MAINT_VERSION 0) include(GrVersion) #setup version info # Minimum dependency versions for central dependencies: -set(GR_BOOST_MIN_VERSION "1.54") +set(GR_BOOST_MIN_VERSION "1.53") set(GR_SWIG_MIN_VERSION "3.0.8") -set(GR_CMAKE_MIN_VERSION "2.8.12") +set(GR_CMAKE_MIN_VERSION "3.5.1") set(GR_MAKO_MIN_VERSION "0.4.2") set(GR_PYTHON_MIN_VERSION "2.7") set(GR_PYTHON3_MIN_VERSION "3.4") diff --git a/cmake/Modules/FindQwt.cmake b/cmake/Modules/FindQwt.cmake index bfdded88e1..d0694c942c 100644 --- a/cmake/Modules/FindQwt.cmake +++ b/cmake/Modules/FindQwt.cmake @@ -29,7 +29,7 @@ find_path(QWT_INCLUDE_DIRS ) find_library (QWT_LIBRARIES - NAMES qwt6-${QWT_QT_VERSION} qwt-${QWT_QT_VERSION} + NAMES ${PC_QWT_LIBRARIES} qwt6-${QWT_QT_VERSION} qwt-${QWT_QT_VERSION} HINTS ${PC_QWT_LIBDIR} ${CMAKE_INSTALL_PREFIX}/lib diff --git a/gnuradio-runtime/lib/block_executor.cc b/gnuradio-runtime/lib/block_executor.cc index 5f9552415a..40521e10b5 100644 --- a/gnuradio-runtime/lib/block_executor.cc +++ b/gnuradio-runtime/lib/block_executor.cc @@ -147,7 +147,7 @@ namespace gr { for(t = rtags.begin(); t != rtags.end(); t++) { tag_t new_tag = *t; mpz_import(offset.get_mpz_t(), 1, 1, sizeof(new_tag.offset), 0, 0, &new_tag.offset); - offset *= mp_rrate + one_half; + offset = offset * mp_rrate + one_half; new_tag.offset = offset.get_ui(); for(int o = 0; o < d->noutputs(); o++) out_buf[o]->add_item_tag(new_tag); @@ -190,7 +190,7 @@ namespace gr { for(t = rtags.begin(); t != rtags.end(); t++) { tag_t new_tag = *t; mpz_import(offset.get_mpz_t(), 1, 1, sizeof(new_tag.offset), 0, 0, &new_tag.offset); - offset *= mp_rrate + one_half; + offset = offset * mp_rrate + one_half; new_tag.offset = offset.get_ui(); out_buf->add_item_tag(new_tag); } diff --git a/gnuradio-runtime/lib/pmt/pmt_unv.cc b/gnuradio-runtime/lib/pmt/pmt_unv.cc index cda0c085cd..25cd9a3c95 100644 --- a/gnuradio-runtime/lib/pmt/pmt_unv.cc +++ b/gnuradio-runtime/lib/pmt/pmt_unv.cc @@ -474,7 +474,7 @@ u16vector_writable_elements(pmt_t vector, size_t &len) const std::string pmt_u16vector::string_ref(size_t k) const { - return boost::lexical_cast< std::string, uint16_t > (ref(k)); + return std::to_string(ref(k)); } } /* namespace pmt */ @@ -623,7 +623,7 @@ s16vector_writable_elements(pmt_t vector, size_t &len) const std::string pmt_s16vector::string_ref(size_t k) const { - return boost::lexical_cast< std::string, int16_t > (ref(k)); + return std::to_string(ref(k)); } } /* namespace pmt */ @@ -772,7 +772,7 @@ u32vector_writable_elements(pmt_t vector, size_t &len) const std::string pmt_u32vector::string_ref(size_t k) const { - return boost::lexical_cast< std::string, uint32_t > (ref(k)); + return std::to_string(ref(k)); } } /* namespace pmt */ @@ -921,7 +921,7 @@ s32vector_writable_elements(pmt_t vector, size_t &len) const std::string pmt_s32vector::string_ref(size_t k) const { - return boost::lexical_cast< std::string, int32_t > (ref(k)); + return std::to_string(ref(k)); } } /* namespace pmt */ @@ -1070,7 +1070,7 @@ u64vector_writable_elements(pmt_t vector, size_t &len) const std::string pmt_u64vector::string_ref(size_t k) const { - return boost::lexical_cast< std::string, uint64_t > (ref(k)); + return std::to_string(ref(k)); } } /* namespace pmt */ @@ -1219,7 +1219,7 @@ s64vector_writable_elements(pmt_t vector, size_t &len) const std::string pmt_s64vector::string_ref(size_t k) const { - return boost::lexical_cast< std::string, int64_t > (ref(k)); + return std::to_string(ref(k)); } } /* namespace pmt */ diff --git a/gnuradio-runtime/python/gnuradio/CMakeLists.txt b/gnuradio-runtime/python/gnuradio/CMakeLists.txt index 736db499dc..aea94643de 100644 --- a/gnuradio-runtime/python/gnuradio/CMakeLists.txt +++ b/gnuradio-runtime/python/gnuradio/CMakeLists.txt @@ -33,6 +33,5 @@ GR_PYTHON_INSTALL(FILES eng_option.py eng_arg.py gr_unittest.py - gr_xmlrunner.py DESTINATION ${GR_PYTHON_DIR}/gnuradio ) diff --git a/gnuradio-runtime/python/gnuradio/gr_unittest.py b/gnuradio-runtime/python/gnuradio/gr_unittest.py index 190ea63354..57ce9a3761 100644 --- a/gnuradio-runtime/python/gnuradio/gr_unittest.py +++ b/gnuradio-runtime/python/gnuradio/gr_unittest.py @@ -26,13 +26,7 @@ from __future__ import absolute_import from __future__ import unicode_literals from __future__ import division -import os -import stat - import unittest -from . import gr_xmlrunner - - class TestCase(unittest.TestCase): """A subclass of unittest.TestCase that adds additional assertions @@ -41,7 +35,7 @@ class TestCase(unittest.TestCase): assertComplexTuplesAlmostEqual and assertFloatTuplesAlmostEqual """ - def assertComplexAlmostEqual (self, first, second, places=7, msg=None): + def assertComplexAlmostEqual(self, first, second, places=7, msg=None): """Fail if the two complex objects are unequal as determined by their difference rounded to the given number of decimal places (default 7) and comparing to zero. @@ -57,9 +51,11 @@ class TestCase(unittest.TestCase): msg or '%r != %r within %r places' % (first, second, places) ) - def assertComplexAlmostEqual2 (self, ref, x, abs_eps=1e-12, rel_eps=1e-6, msg=None): + + def assertComplexAlmostEqual2(self, ref, x, abs_eps=1e-12, rel_eps=1e-6, msg=None): """ - Fail if the two complex objects are unequal as determined by... + Fail if the two complex objects are unequal as determined by both + absolute delta (abs_eps) and relative delta (rel_eps). """ if abs(ref - x) < abs_eps: return @@ -79,40 +75,52 @@ class TestCase(unittest.TestCase): ) + def assertComplexTuplesAlmostEqual(self, a, b, places=7, msg=None): + """ + Fail if the two complex tuples are not approximately equal. + Approximate equality is determined by specifying the number of decimal + places.0 + """ + self.assertEqual(len(a), len(b)) + return all(( + self.assertComplexAlmostEqual(x, y, places, msg) + for (x, y) in zip(a, b) + )) - def assertComplexTuplesAlmostEqual (self, a, b, places=7, msg=None): - self.assertEqual (len(a), len(b)) - for i in range (len(a)): - self.assertComplexAlmostEqual (a[i], b[i], places, msg) - def assertComplexTuplesAlmostEqual2 (self, ref, x, - abs_eps=1e-12, rel_eps=1e-6, msg=None): - self.assertEqual (len(ref), len(x)) - for i in range (len(ref)): - try: - self.assertComplexAlmostEqual2 (ref[i], x[i], abs_eps, rel_eps, msg) - except self.failureException as e: - #sys.stderr.write("index = %d " % (i,)) - #sys.stderr.write("%r\n" % (e,)) - raise + def assertComplexTuplesAlmostEqual2(self, a, b, + abs_eps=1e-12, rel_eps=1e-6, msg=None): + """ + Fail if the two complex tuples are not approximately equal. + Approximate equality is determined by calling assertComplexAlmostEqual(). + """ + self.assertEqual(len(a), len(b)) + return all(( + self.assertComplexAlmostEqual2(x, y, abs_eps, rel_eps, msg) + for (x, y) in zip(a, b) + )) - def assertFloatTuplesAlmostEqual (self, a, b, places=7, msg=None): - self.assertEqual (len(a), len(b)) - for i in range (len(a)): - self.assertAlmostEqual (a[i], b[i], places, msg) + def assertFloatTuplesAlmostEqual(self, a, b, places=7, msg=None): + """ + Fail if the two real-valued tuples are not approximately equal. + Approximate equality is determined by specifying the number of decimal + places. + """ + self.assertEqual(len(a), len(b)) + return all(( + self.assertAlmostEqual(x, y, places, msg) + for (x, y) in zip(a, b) + )) - def assertFloatTuplesAlmostEqual2 (self, ref, x, - abs_eps=1e-12, rel_eps=1e-6, msg=None): - self.assertEqual (len(ref), len(x)) - for i in range (len(ref)): - try: - self.assertComplexAlmostEqual2 (ref[i], x[i], abs_eps, rel_eps, msg) - except self.failureException as e: - #sys.stderr.write("index = %d " % (i,)) - #sys.stderr.write("%r\n" % (e,)) - raise + def assertFloatTuplesAlmostEqual2(self, a, b, + abs_eps=1e-12, rel_eps=1e-6, msg=None): + self.assertEqual(len(a), len(b)) + return all(( + self.assertComplexAlmostEqual2(x, y, abs_eps, rel_eps, msg) + for (x, y) in zip(a, b) + )) TestResult = unittest.TestResult TestSuite = unittest.TestSuite @@ -125,54 +133,14 @@ main = TestProgram def run(PUT, filename=None, verbosity=1): ''' - Runs the unittest on a TestCase and produces an optional XML report + Runs the unittest on a TestCase PUT: the program under test and should be a gr_unittest.TestCase - filename: an optional filename to save the XML report of the tests - this will live in ./.unittests/python + filename: This argument is here for historical reasons. ''' - - # Run this is given a file name - if(filename is not None): - basepath = "./.unittests" - path = basepath + "/python" - - if not os.path.exists(basepath): - os.makedirs(basepath, mode=0o750) - - xmlrunner = None - # only proceed if .unittests is writable - st = os.stat(basepath)[stat.ST_MODE] - if(st & stat.S_IWUSR > 0): - # Test if path exists; if not, build it - if not os.path.exists(path): - os.makedirs(path, mode=0o750) - - # Just for safety: make sure we can write here, too - st = os.stat(path)[stat.ST_MODE] - if(st & stat.S_IWUSR > 0): - # Create an XML runner to filename - fout = open(path+"/"+filename, "w") - xmlrunner = gr_xmlrunner.XMLTestRunner(fout) - - txtrunner = TextTestRunner(verbosity=verbosity) - - # Run the test; runner also creates XML output file - # FIXME: make xmlrunner output to screen so we don't have to do run and main - suite = TestLoader().loadTestsFromTestCase(PUT) - - # use the xmlrunner if we can write the the directory - if xmlrunner is not None: - xmlrunner.run(suite) - - main(verbosity=verbosity) - - # This will run and fail make check if problem - # but does not output to screen. - #main(testRunner = xmlrunner) - - else: - # If no filename is given, just run the test - main(verbosity=verbosity) + if filename: + print("DEPRECATED: Using filename with gr_unittest does no longer " + "have any effect.") + main(verbosity=verbosity) ############################################################################## diff --git a/gnuradio-runtime/python/gnuradio/gr_xmlrunner.py b/gnuradio-runtime/python/gnuradio/gr_xmlrunner.py deleted file mode 100644 index fccb1b76f0..0000000000 --- a/gnuradio-runtime/python/gnuradio/gr_xmlrunner.py +++ /dev/null @@ -1,421 +0,0 @@ -""" -XML Test Runner for PyUnit -""" -# Written by Sebastian Rittau <srittau@jroger.in-berlin.de> and placed in -# the Public Domain. With contributions by Paolo Borelli and others. -# Added to GNU Radio Oct. 3, 2010 - -from __future__ import unicode_literals - -import os.path -import re -import sys -import time -import unittest -import linecache -from xml.sax.saxutils import escape -from io import StringIO - - -__version__ = "0.1" - - -# inline trackeback.print_tb so that py2 uses unicode literals (py2/3 compat) -def print_tb(tb, limit=None, out=None): - """Print up to 'limit' stack trace entries from the traceback 'tb'. - - If 'limit' is omitted or None, all entries are printed. If 'file' - is omitted or None, the output goes to sys.stderr; otherwise - 'file' should be an open file or file-like object with a write() - method. - """ - def _print(out, s='', terminator='\n'): - out.write(s+terminator) - - if out is None: - out = sys.stderr - if limit is None: - if hasattr(sys, 'tracebacklimit'): - limit = sys.tracebacklimit - n = 0 - while tb is not None and (limit is None or n < limit): - f = tb.tb_frame - lineno = tb.tb_lineno - co = f.f_code - filename = co.co_filename - name = co.co_name - _print(out, ' Out "%s", line %d, in %s' % (filename, lineno, name)) - linecache.checkcache(filename) - line = linecache.getline(filename, lineno, f.f_globals) - if line: - _print(out, ' ' + line.strip()) - tb = tb.tb_next - n = n+1 - - -class _TestInfo(object): - - """Information about a particular test. - - Used by _XMLTestResult. - - """ - - def __init__(self, test, time): - (self._class, self._method) = test.id().rsplit(".", 1) - self._time = time - self._error = None - self._failure = None - - @staticmethod - def create_success(test, time): - """Create a _TestInfo instance for a successful test.""" - return _TestInfo(test, time) - - @staticmethod - def create_failure(test, time, failure): - """Create a _TestInfo instance for a failed test.""" - info = _TestInfo(test, time) - info._failure = failure - return info - - @staticmethod - def create_error(test, time, error): - """Create a _TestInfo instance for an erroneous test.""" - info = _TestInfo(test, time) - info._error = error - return info - - def print_report(self, stream): - """Print information about this test case in XML format to the - supplied stream. - - """ - stream.write(' <testcase classname="%(class)s" name="%(method)s" time="%(time).4f">' % - { - 'class': self._class, - 'method': self._method, - 'time': self._time, - }) - if self._failure is not None: - self._print_error(stream, 'failure', self._failure) - if self._error is not None: - self._print_error(stream, 'error', self._error) - stream.write('</testcase>\n') - - def _print_error(self, stream, tagname, error): - """Print information from a failure or error to the supplied stream.""" - text = escape(str(error[1])) - stream.write('\n') - stream.write(' <%s type="%s">%s\n' - % (tagname, _clsname(error[0]), text)) - tb_stream = StringIO() - print_tb(error[2], None, tb_stream) - stream.write(escape(tb_stream.getvalue())) - stream.write(' </%s>\n' % tagname) - stream.write(' ') - - -def _clsname(cls): - return cls.__module__ + "." + cls.__name__ - - -class _XMLTestResult(unittest.TestResult): - - """A test result class that stores result as XML. - - Used by XMLTestRunner. - - """ - - def __init__(self, classname): - unittest.TestResult.__init__(self) - self._test_name = classname - self._start_time = None - self._tests = [] - self._error = None - self._failure = None - - def startTest(self, test): - unittest.TestResult.startTest(self, test) - self._error = None - self._failure = None - self._start_time = time.time() - - def stopTest(self, test): - time_taken = time.time() - self._start_time - unittest.TestResult.stopTest(self, test) - if self._error: - info = _TestInfo.create_error(test, time_taken, self._error) - elif self._failure: - info = _TestInfo.create_failure(test, time_taken, self._failure) - else: - info = _TestInfo.create_success(test, time_taken) - self._tests.append(info) - - def addError(self, test, err): - unittest.TestResult.addError(self, test, err) - self._error = err - - def addFailure(self, test, err): - unittest.TestResult.addFailure(self, test, err) - self._failure = err - - def print_report(self, stream, time_taken, out, err): - """Prints the XML report to the supplied stream. - - The time the tests took to perform as well as the captured standard - output and standard error streams must be passed in.a - - """ - stream.write('<testsuite errors="%(e)d" failures="%(f)d" ' % - { - "e": len(self.errors), - "f": len(self.failures) - }) - stream.write('name="%(n)s" tests="%(t)d" time="%(time).3f">\n' % - { - "n": self._test_name, - "t": self.testsRun, - "time": time_taken - }) - for info in self._tests: - info.print_report(stream) - stream.write(' <system-out><![CDATA[%s]]></system-out>\n' % out) - stream.write(' <system-err><![CDATA[%s]]></system-err>\n' % err) - stream.write('</testsuite>\n') - - -class XMLTestRunner(object): - - """A test runner that stores results in XML format compatible with JUnit. - - XMLTestRunner(stream=None) -> XML test runner - - The XML file is written to the supplied stream. If stream is None, the - results are stored in a file called TEST-<module>.<class>.xml in the - current working directory (if not overridden with the path property), - where <module> and <class> are the module and class name of the test class. - - """ - - def __init__(self, stream=None): - self._stream = stream - self._path = "." - - def run(self, test): - """Run the given test case or test suite.""" - class_ = test.__class__ - classname = class_.__module__ + "." + class_.__name__ - if self._stream is None: - filename = "TEST-%s.xml" % classname - stream = open(os.path.join(self._path, filename), "w") - stream.write('<?xml version="1.0" encoding="utf-8"?>\n') - else: - stream = self._stream - - result = _XMLTestResult(classname) - start_time = time.time() - - fss = _fake_std_streams() - fss.__enter__() - try: - test(result) - try: - out_s = sys.stdout.getvalue() - except AttributeError: - out_s = "" - try: - err_s = sys.stderr.getvalue() - except AttributeError: - err_s = "" - finally: - fss.__exit__(None, None, None) - - time_taken = time.time() - start_time - result.print_report(stream, time_taken, out_s, err_s) - if self._stream is None: - stream.close() - - return result - - def _set_path(self, path): - self._path = path - - path = property(lambda self: self._path, _set_path, None, - """The path where the XML files are stored. - - This property is ignored when the XML file is written to a file - stream.""") - - -class _fake_std_streams(object): - - def __enter__(self): - self._orig_stdout = sys.stdout - self._orig_stderr = sys.stderr - #sys.stdout = StringIO() - #sys.stderr = StringIO() - - def __exit__(self, exc_type, exc_val, exc_tb): - sys.stdout = self._orig_stdout - sys.stderr = self._orig_stderr - - -class XMLTestRunnerTest(unittest.TestCase): - - def setUp(self): - self._stream = StringIO() - - def _try_test_run(self, test_class, expected): - - """Run the test suite against the supplied test class and compare the - XML result against the expected XML string. Fail if the expected - string doesn't match the actual string. All time attributes in the - expected string should have the value "0.000". All error and failure - messages are reduced to "Foobar". - - """ - - runner = XMLTestRunner(self._stream) - runner.run(unittest.makeSuite(test_class)) - - got = self._stream.getvalue() - # Replace all time="X.YYY" attributes by time="0.000" to enable a - # simple string comparison. - got = re.sub(r'time="\d+\.\d+"', 'time="0.000"', got) - # Likewise, replace all failure and error messages by a simple "Foobar" - # string. - got = re.sub(r'(?s)<failure (.*?)>.*?</failure>', r'<failure \1>Foobar</failure>', got) - got = re.sub(r'(?s)<error (.*?)>.*?</error>', r'<error \1>Foobar</error>', got) - # And finally Python 3 compatibility. - got = got.replace('type="builtins.', 'type="exceptions.') - - self.assertEqual(expected, got) - - def test_no_tests(self): - """Regression test: Check whether a test run without any tests - matches a previous run. - - """ - class TestTest(unittest.TestCase): - pass - self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="0" time="0.000"> - <system-out><![CDATA[]]></system-out> - <system-err><![CDATA[]]></system-err> -</testsuite> -""") - - def test_success(self): - """Regression test: Check whether a test run with a successful test - matches a previous run. - - """ - class TestTest(unittest.TestCase): - def test_foo(self): - pass - self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000"> - <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase> - <system-out><![CDATA[]]></system-out> - <system-err><![CDATA[]]></system-err> -</testsuite> -""") - - def test_failure(self): - """Regression test: Check whether a test run with a failing test - matches a previous run. - - """ - class TestTest(unittest.TestCase): - def test_foo(self): - self.assert_(False) - self._try_test_run(TestTest, """<testsuite errors="0" failures="1" name="unittest.TestSuite" tests="1" time="0.000"> - <testcase classname="__main__.TestTest" name="test_foo" time="0.000"> - <failure type="exceptions.AssertionError">Foobar</failure> - </testcase> - <system-out><![CDATA[]]></system-out> - <system-err><![CDATA[]]></system-err> -</testsuite> -""") - - def test_error(self): - """Regression test: Check whether a test run with a erroneous test - matches a previous run. - - """ - class TestTest(unittest.TestCase): - def test_foo(self): - raise IndexError() - self._try_test_run(TestTest, """<testsuite errors="1" failures="0" name="unittest.TestSuite" tests="1" time="0.000"> - <testcase classname="__main__.TestTest" name="test_foo" time="0.000"> - <error type="exceptions.IndexError">Foobar</error> - </testcase> - <system-out><![CDATA[]]></system-out> - <system-err><![CDATA[]]></system-err> -</testsuite> -""") - - def test_stdout_capture(self): - """Regression test: Check whether a test run with output to stdout - matches a previous run. - - """ - class TestTest(unittest.TestCase): - def test_foo(self): - sys.stdout.write("Test\n") - self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000"> - <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase> - <system-out><![CDATA[Test -]]></system-out> - <system-err><![CDATA[]]></system-err> -</testsuite> -""") - - def test_stderr_capture(self): - """Regression test: Check whether a test run with output to stderr - matches a previous run. - - """ - class TestTest(unittest.TestCase): - def test_foo(self): - sys.stderr.write("Test\n") - self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000"> - <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase> - <system-out><![CDATA[]]></system-out> - <system-err><![CDATA[Test -]]></system-err> -</testsuite> -""") - - class NullStream(object): - """A file-like object that discards everything written to it.""" - def write(self, buffer): - pass - - def test_unittests_changing_stdout(self): - """Check whether the XMLTestRunner recovers gracefully from unit tests - that change stdout, but don't change it back properly. - - """ - class TestTest(unittest.TestCase): - def test_foo(self): - sys.stdout = XMLTestRunnerTest.NullStream() - - runner = XMLTestRunner(self._stream) - runner.run(unittest.makeSuite(TestTest)) - - def test_unittests_changing_stderr(self): - """Check whether the XMLTestRunner recovers gracefully from unit tests - that change stderr, but don't change it back properly. - - """ - class TestTest(unittest.TestCase): - def test_foo(self): - sys.stderr = XMLTestRunnerTest.NullStream() - - runner = XMLTestRunner(self._stream) - runner.run(unittest.makeSuite(TestTest)) - - -if __name__ == "__main__": - unittest.main() diff --git a/gr-analog/CMakeLists.txt b/gr-analog/CMakeLists.txt index d874ae3cf6..c6ca6192dd 100644 --- a/gr-analog/CMakeLists.txt +++ b/gr-analog/CMakeLists.txt @@ -60,10 +60,12 @@ add_subdirectory(docs) if(ENABLE_PYTHON) add_subdirectory(swig) add_subdirectory(python/analog) - add_subdirectory(grc) add_subdirectory(examples) add_subdirectory(examples/tags) endif(ENABLE_PYTHON) +if(ENABLE_GRC) + add_subdirectory(grc) +endif(ENABLE_GRC) ######################################################################## # Create Pkg Config File diff --git a/gr-analog/include/gnuradio/analog/random_uniform_source.h b/gr-analog/include/gnuradio/analog/random_uniform_source.h index 95948cc24e..1cd0f3016d 100644 --- a/gr-analog/include/gnuradio/analog/random_uniform_source.h +++ b/gr-analog/include/gnuradio/analog/random_uniform_source.h @@ -31,7 +31,7 @@ namespace gr { namespace analog { /*! - * \brief Uniform Random Number Generator with @TYPE@ output. + * \brief Uniform Random Number Generator * \ingroup waveform_generators_blk */ template<class T> diff --git a/gr-analog/include/gnuradio/analog/sig_source.h b/gr-analog/include/gnuradio/analog/sig_source.h index 915433a5ab..5d8ee05614 100644 --- a/gr-analog/include/gnuradio/analog/sig_source.h +++ b/gr-analog/include/gnuradio/analog/sig_source.h @@ -50,6 +50,7 @@ template<class T> * \param wave_freq Frequency of waveform (relative to sampling_freq). * \param ampl Signal amplitude. * \param offset offset of signal. + * \param phase Initial phase of the signal */ static sptr make(double sampling_freq, gr::analog::gr_waveform_t waveform, @@ -83,7 +84,7 @@ template<class T> /*! * Sets the amplitude of a signal. - * \param amplitude of the signal + * \param ampl amplitude of the signal */ virtual void set_amplitude(double ampl) = 0; diff --git a/gr-audio/CMakeLists.txt b/gr-audio/CMakeLists.txt index a43a58c6b7..6f373b7b94 100644 --- a/gr-audio/CMakeLists.txt +++ b/gr-audio/CMakeLists.txt @@ -51,11 +51,12 @@ add_subdirectory(docs) if(ENABLE_PYTHON) add_subdirectory(swig) add_subdirectory(python/audio) - add_subdirectory(grc) add_subdirectory(examples/python) add_subdirectory(examples/grc) endif(ENABLE_PYTHON) - +if(ENABLE_GRC) + add_subdirectory(grc) +endif(ENABLE_GRC) if(ENABLE_GR_ANALOG) add_subdirectory(examples/c++) endif(ENABLE_GR_ANALOG) diff --git a/gr-audio/lib/windows/windows_sink.cc b/gr-audio/lib/windows/windows_sink.cc index bd9e0e5660..067c71cbf7 100644 --- a/gr-audio/lib/windows/windows_sink.cc +++ b/gr-audio/lib/windows/windows_sink.cc @@ -38,7 +38,6 @@ #include <stdexcept> #include <string> #include <sstream> -#include "boost/lexical_cast.hpp" namespace gr { namespace audio { diff --git a/gr-audio/lib/windows/windows_source.cc b/gr-audio/lib/windows/windows_source.cc index 372a8ba3a8..9f177462e2 100644 --- a/gr-audio/lib/windows/windows_source.cc +++ b/gr-audio/lib/windows/windows_source.cc @@ -38,8 +38,6 @@ #include <gnuradio/prefs.h> #include <gnuradio/logger.h> -#include "boost/lexical_cast.hpp" - namespace gr { namespace audio { diff --git a/gr-blocks/CMakeLists.txt b/gr-blocks/CMakeLists.txt index 34fac58823..86ad046d16 100644 --- a/gr-blocks/CMakeLists.txt +++ b/gr-blocks/CMakeLists.txt @@ -56,10 +56,12 @@ add_subdirectory(lib) if(ENABLE_PYTHON) add_subdirectory(python/blocks) add_subdirectory(swig) - add_subdirectory(grc) add_subdirectory(docs) add_subdirectory(examples) endif(ENABLE_PYTHON) +if(ENABLE_GRC) + add_subdirectory(grc) +endif(ENABLE_GRC) ######################################################################## # Create Pkg Config File diff --git a/gr-blocks/lib/integrate_impl.cc b/gr-blocks/lib/integrate_impl.cc index 9fa4035726..90f0ef18ce 100644 --- a/gr-blocks/lib/integrate_impl.cc +++ b/gr-blocks/lib/integrate_impl.cc @@ -58,11 +58,11 @@ namespace gr { T *out = (T *)output_items[0]; for (int i = 0; i < noutput_items; i++) { - for (int j = 0; j < d_vlen; ++j) { + for (unsigned int j = 0; j < d_vlen; ++j) { out[i*d_vlen + j] = (T)0; } for (int j = 0; j < d_decim; j++) { - for (int k = 0; k < d_vlen; ++k) { + for (unsigned int k = 0; k < d_vlen; ++k) { out[i*d_vlen + k] += in[i*d_decim*d_vlen + j*d_vlen + k]; } } diff --git a/gr-blocks/lib/tcp_server_sink_impl.h b/gr-blocks/lib/tcp_server_sink_impl.h index ea1aa3e84a..db26b705fe 100644 --- a/gr-blocks/lib/tcp_server_sink_impl.h +++ b/gr-blocks/lib/tcp_server_sink_impl.h @@ -43,7 +43,7 @@ namespace gr { std::set<boost::asio::ip::tcp::socket *> d_sockets; boost::asio::ip::tcp::acceptor d_acceptor; - boost::shared_ptr<uint8_t> d_buf; + boost::shared_ptr<uint8_t[]> d_buf; enum { BUF_SIZE = 256 * 1024, }; diff --git a/gr-blocks/lib/vector_sink_impl.cc b/gr-blocks/lib/vector_sink_impl.cc index dfa6dbb4a5..b09c8e81b7 100644 --- a/gr-blocks/lib/vector_sink_impl.cc +++ b/gr-blocks/lib/vector_sink_impl.cc @@ -94,7 +94,7 @@ namespace gr { // can't touch this (as long as work() is working, the accessors shall not // read the data gr::thread::scoped_lock guard(d_data_mutex); - for(int i = 0; i < noutput_items * d_vlen; i++) + for(unsigned int i = 0; i < noutput_items * d_vlen; i++) d_data.push_back (iptr[i]); std::vector<tag_t> tags; this->get_tags_in_range(tags, 0, this->nitems_read(0), this->nitems_read(0) + noutput_items); diff --git a/gr-blocks/lib/vector_source_impl.cc b/gr-blocks/lib/vector_source_impl.cc index d49c37f5dd..24a21854f2 100644 --- a/gr-blocks/lib/vector_source_impl.cc +++ b/gr-blocks/lib/vector_source_impl.cc @@ -114,7 +114,7 @@ namespace gr { } } else { - for(int i = 0; i < noutput_items*d_vlen; i++) { + for(int i = 0; i < static_cast<int>(noutput_items*d_vlen); i++) { optr[i] = d_data[offset++]; if(offset >= size) { offset = 0; diff --git a/gr-blocks/python/blocks/qa_keep_m_in_n.py b/gr-blocks/python/blocks/qa_keep_m_in_n.py index 14d7863bbd..7ef9ae791d 100644 --- a/gr-blocks/python/blocks/qa_keep_m_in_n.py +++ b/gr-blocks/python/blocks/qa_keep_m_in_n.py @@ -29,7 +29,7 @@ import random class test_keep_m_in_n(gr_unittest.TestCase): def setUp(self): - pass + random.seed(0) def tearDown(self): pass diff --git a/gr-blocks/python/blocks/qa_moving_average.py b/gr-blocks/python/blocks/qa_moving_average.py index 87f8d3015f..fa8383c7c9 100644 --- a/gr-blocks/python/blocks/qa_moving_average.py +++ b/gr-blocks/python/blocks/qa_moving_average.py @@ -41,6 +41,7 @@ def make_random_float_tuple(L, scale=1): class test_moving_average(gr_unittest.TestCase): def setUp(self): + random.seed(0) self.tb = gr.top_block() def tearDown(self): @@ -54,7 +55,6 @@ class test_moving_average(gr_unittest.TestCase): tb = self.tb N = 10000 - seed = 0 data = make_random_float_tuple(N, 1) expected_result = N*[0,] @@ -75,7 +75,6 @@ class test_moving_average(gr_unittest.TestCase): tb = self.tb N = 10000 - seed = 0 data = make_random_complex_tuple(N, 1) expected_result = N*[0,] @@ -99,7 +98,6 @@ class test_moving_average(gr_unittest.TestCase): vlen = 5 N = 10*vlen - seed = 0 data = make_random_float_tuple(N, 2**10) data = [int(d*1000) for d in data] src = blocks.vector_source_i(data, False) diff --git a/gr-blocks/python/blocks/qa_pack_k_bits.py b/gr-blocks/python/blocks/qa_pack_k_bits.py index 28285845b3..c82c025306 100644 --- a/gr-blocks/python/blocks/qa_pack_k_bits.py +++ b/gr-blocks/python/blocks/qa_pack_k_bits.py @@ -28,6 +28,7 @@ from gnuradio import gr, gr_unittest, blocks class test_pack(gr_unittest.TestCase): def setUp(self): + random.seed(0) self.tb = gr.top_block() def tearDown(self): diff --git a/gr-blocks/python/blocks/qa_packed_to_unpacked.py b/gr-blocks/python/blocks/qa_packed_to_unpacked.py index 13e93a7136..ea68b8263c 100644 --- a/gr-blocks/python/blocks/qa_packed_to_unpacked.py +++ b/gr-blocks/python/blocks/qa_packed_to_unpacked.py @@ -28,6 +28,7 @@ import random class test_packing(gr_unittest.TestCase): def setUp(self): + random.seed(0) self.tb = gr.top_block () def tearDown(self): diff --git a/gr-blocks/python/blocks/qa_repack_bits_bb.py b/gr-blocks/python/blocks/qa_repack_bits_bb.py index fa86c0ccac..419630b0c5 100644 --- a/gr-blocks/python/blocks/qa_repack_bits_bb.py +++ b/gr-blocks/python/blocks/qa_repack_bits_bb.py @@ -28,6 +28,7 @@ import pmt class qa_repack_bits_bb (gr_unittest.TestCase): def setUp (self): + random.seed(0) self.tb = gr.top_block () self.tsb_key = "length" diff --git a/gr-blocks/python/blocks/qa_socket_pdu.py b/gr-blocks/python/blocks/qa_socket_pdu.py index 961dc914ea..21f8ead6ec 100644 --- a/gr-blocks/python/blocks/qa_socket_pdu.py +++ b/gr-blocks/python/blocks/qa_socket_pdu.py @@ -29,6 +29,7 @@ import time class qa_socket_pdu (gr_unittest.TestCase): def setUp (self): + random.seed(0) self.tb = gr.top_block () def tearDown (self): diff --git a/gr-blocks/python/blocks/qa_udp_source_sink.py b/gr-blocks/python/blocks/qa_udp_source_sink.py index f0418357fd..fe3fea5d9c 100644 --- a/gr-blocks/python/blocks/qa_udp_source_sink.py +++ b/gr-blocks/python/blocks/qa_udp_source_sink.py @@ -22,9 +22,22 @@ from gnuradio import gr, gr_unittest, blocks +import numpy import os +import socket +import time + +from threading import Timer, Thread + + +def recv_data(sock, result): + while True: + data = sock.recv(4*1000) + if len(data) == 0: + break + real_data = numpy.frombuffer(data, dtype=numpy.float32) + result.extend(list(real_data)) -from threading import Timer class test_udp_sink_source(gr_unittest.TestCase): @@ -52,36 +65,66 @@ class test_udp_sink_source(gr_unittest.TestCase): self.tb_snd.run() udp_snd.disconnect() + udp_snd.connect('localhost', port+1) src.rewind() self.tb_snd.run() - def test_002(self): + + def test_sink_001(self): port = 65520 n_data = 100 src_data = [float(x) for x in range(n_data)] expected_result = tuple(src_data) + + recvsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + recvsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + recvsock.bind(('127.0.0.1', port)) + + result = [] + t = Thread(target=recv_data, args=(recvsock, result)) + t.start() + src = blocks.vector_source_f(src_data, False) - udp_snd = blocks.udp_sink(gr.sizeof_float, 'localhost', port) + udp_snd = blocks.udp_sink(gr.sizeof_float, '127.0.0.1', port) self.tb_snd.connect(src, udp_snd) - udp_rcv = blocks.udp_source(gr.sizeof_float, 'localhost', port) - dst = blocks.vector_sink_f() - self.tb_rcv.connect(udp_rcv, dst) - self.tb_rcv.start() self.tb_snd.run() udp_snd.disconnect() - self.timeout = False - q = Timer(2.0,self.stop_rcv) - q.start() + t.join() + recvsock.close() + + self.assertEqual(expected_result, tuple(result)) + + def test_source_001(self): + port = 65520 + + n_data = 100 + src_data = [float(x) for x in range(n_data)] + expected_result = tuple(src_data) + send_data = numpy.array(src_data, dtype=numpy.float32) + send_data = send_data.tobytes() + + udp_rcv = blocks.udp_source(gr.sizeof_float, '127.0.0.1', port) + dst = blocks.vector_sink_f() + self.tb_rcv.connect(udp_rcv, dst) + self.tb_rcv.start() + time.sleep(1.0) + sendsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sendsock.sendto(send_data, ('127.0.0.1', port)) + time.sleep(1.0) + sendsock.sendto(b'', ('127.0.0.1', port)) + sendsock.sendto(b'', ('127.0.0.1', port)) + sendsock.sendto(b'', ('127.0.0.1', port)) self.tb_rcv.wait() - q.cancel() + sendsock.close() + recv_data = tuple(dst.data()) + + self.assertEqual(expected_result, recv_data) + - result_data = dst.data() - self.assertEqual(expected_result, result_data) - self.assert_(not self.timeout) def test_003(self): port = 65530 @@ -102,6 +145,7 @@ class test_udp_sink_source(gr_unittest.TestCase): self.tb_rcv.connect(udp_rcv, dst) self.tb_rcv.start() + time.sleep(0.1) self.tb_snd.run() udp_snd.disconnect() self.timeout = False @@ -112,7 +156,7 @@ class test_udp_sink_source(gr_unittest.TestCase): result_data = dst.data() self.assertEqual(expected_result, result_data) - self.assert_(self.timeout) # source ignores EOF? + self.assertTrue(self.timeout) # source ignores EOF? def stop_rcv(self): self.timeout = True diff --git a/gr-blocks/python/blocks/qa_unpack_k_bits.py b/gr-blocks/python/blocks/qa_unpack_k_bits.py index f351e75d30..3e2a107b30 100644 --- a/gr-blocks/python/blocks/qa_unpack_k_bits.py +++ b/gr-blocks/python/blocks/qa_unpack_k_bits.py @@ -28,6 +28,7 @@ import random class test_unpack(gr_unittest.TestCase): def setUp(self): + random.seed(0) self.tb = gr.top_block () def tearDown(self): diff --git a/gr-channels/CMakeLists.txt b/gr-channels/CMakeLists.txt index 5d073e1c66..a508362be0 100644 --- a/gr-channels/CMakeLists.txt +++ b/gr-channels/CMakeLists.txt @@ -57,9 +57,11 @@ add_subdirectory(lib) if(ENABLE_PYTHON) add_subdirectory(swig) add_subdirectory(python/channels) - add_subdirectory(grc) add_subdirectory(examples) endif(ENABLE_PYTHON) +if(ENABLE_GRC) + add_subdirectory(grc) +endif(ENABLE_GRC) add_subdirectory(docs) ######################################################################## diff --git a/gr-channels/grc/channels_channel_model.block.yml b/gr-channels/grc/channels_channel_model.block.yml index 53337f6ab0..01701c3610 100644 --- a/gr-channels/grc/channels_channel_model.block.yml +++ b/gr-channels/grc/channels_channel_model.block.yml @@ -28,9 +28,7 @@ parameters: default: 'False' options: ['True', 'False'] option_labels: ['Yes', 'No'] - option_attributes: - hide_block: ['', part] - hide: ${ block_tags.hide_block } + hide: ${ 'none' if block_tags == 'False' else 'part' } inputs: - domain: stream diff --git a/gr-digital/CMakeLists.txt b/gr-digital/CMakeLists.txt index 7de895f09b..bc02e96331 100644 --- a/gr-digital/CMakeLists.txt +++ b/gr-digital/CMakeLists.txt @@ -61,9 +61,11 @@ add_subdirectory(docs) if(ENABLE_PYTHON) add_subdirectory(swig) add_subdirectory(python/digital) - add_subdirectory(grc) add_subdirectory(examples) endif(ENABLE_PYTHON) +if(ENABLE_GRC) + add_subdirectory(grc) +endif(ENABLE_GRC) ######################################################################## # Create Pkg Config File diff --git a/gr-digital/grc/digital_ofdm_cyclic_prefixer.block.yml b/gr-digital/grc/digital_ofdm_cyclic_prefixer.block.yml index cd475a0601..9054be5753 100644 --- a/gr-digital/grc/digital_ofdm_cyclic_prefixer.block.yml +++ b/gr-digital/grc/digital_ofdm_cyclic_prefixer.block.yml @@ -6,7 +6,6 @@ parameters: label: FFT Length dtype: int default: fft_len - hide: ${ 'part' if vlen == 1 else 'none' } - id: cp_len label: CP Length dtype: int @@ -32,7 +31,7 @@ outputs: templates: imports: from gnuradio import digital - make: digital.ofdm_cyclic_prefixer(${input_size}, ${input_size+cp_len}, ${rolloff}, + make: digital.ofdm_cyclic_prefixer(${input_size}, ${input_size} + ${cp_len}, ${rolloff}, ${tagname}) file_format: 1 diff --git a/gr-digital/include/gnuradio/digital/constellation.h b/gr-digital/include/gnuradio/digital/constellation.h index 8ccd576eda..0a90d7e8d3 100644 --- a/gr-digital/include/gnuradio/digital/constellation.h +++ b/gr-digital/include/gnuradio/digital/constellation.h @@ -66,7 +66,8 @@ namespace gr { constellation(std::vector<gr_complex> constell, std::vector<int> pre_diff_code, unsigned int rotational_symmetry, - unsigned int dimensionality); + unsigned int dimensionality, + bool normalize_points=true); constellation(); virtual ~constellation(); @@ -253,11 +254,13 @@ namespace gr { * coding) (order of list matches constell) * \param rotational_symmetry Number of rotations around unit circle that have the same representation. * \param dimensionality Number of dimensions to the constellation. + * \param normalize_points Normalize constellation points to mean(abs(points))=1 (default is true) */ static sptr make(std::vector<gr_complex> constell, std::vector<int> pre_diff_code, unsigned int rotational_symmetry, - unsigned int dimensionality); + unsigned int dimensionality, + bool normalize_points=true); unsigned int decision_maker(const gr_complex *sample); // void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type); @@ -268,7 +271,8 @@ namespace gr { constellation_calcdist(std::vector<gr_complex> constell, std::vector<int> pre_diff_code, unsigned int rotational_symmetry, - unsigned int dimensionality); + unsigned int dimensionality, + bool nomalize_points=true); }; diff --git a/gr-digital/lib/constellation.cc b/gr-digital/lib/constellation.cc index cf7039b313..93fd95da8e 100644 --- a/gr-digital/lib/constellation.cc +++ b/gr-digital/lib/constellation.cc @@ -43,7 +43,8 @@ namespace gr { constellation::constellation(std::vector<gr_complex> constell, std::vector<int> pre_diff_code, unsigned int rotational_symmetry, - unsigned int dimensionality + unsigned int dimensionality, + bool normalize_points ) : d_constellation(constell), d_pre_diff_code(pre_diff_code), @@ -56,16 +57,18 @@ namespace gr { d_lut_precision(0), d_lut_scale(0) { - // Scale constellation points so that average magnitude is 1. - float summed_mag = 0; unsigned int constsize = d_constellation.size(); - for (unsigned int i=0; i<constsize; i++) { - gr_complex c = d_constellation[i]; - summed_mag += sqrt(c.real()*c.real() + c.imag()*c.imag()); - } - d_scalefactor = constsize/summed_mag; - for (unsigned int i=0; i<constsize; i++) { - d_constellation[i] = d_constellation[i]*d_scalefactor; + if (normalize_points) { + // Scale constellation points so that average magnitude is 1. + float summed_mag = 0; + for (unsigned int i=0; i<constsize; i++) { + gr_complex c = d_constellation[i]; + summed_mag += sqrt(c.real()*c.real() + c.imag()*c.imag()); + } + d_scalefactor = constsize/summed_mag; + for (unsigned int i=0; i<constsize; i++) { + d_constellation[i] = d_constellation[i]*d_scalefactor; + } } if(pre_diff_code.size() == 0) d_apply_pre_diff_code = false; @@ -406,19 +409,21 @@ namespace gr { constellation_calcdist::make(std::vector<gr_complex> constell, std::vector<int> pre_diff_code, unsigned int rotational_symmetry, - unsigned int dimensionality) + unsigned int dimensionality, + bool normalize_points) { return constellation_calcdist::sptr( new constellation_calcdist(constell, pre_diff_code, - rotational_symmetry, dimensionality)); + rotational_symmetry, dimensionality, normalize_points)); } constellation_calcdist::constellation_calcdist( std::vector<gr_complex> constell, std::vector<int> pre_diff_code, unsigned int rotational_symmetry, - unsigned int dimensionality) - : constellation(constell, pre_diff_code, rotational_symmetry, dimensionality) + unsigned int dimensionality, + bool normalize_points) + : constellation(constell, pre_diff_code, rotational_symmetry, dimensionality, normalize_points) {} // Chooses points base on shortest distance. diff --git a/gr-digital/lib/crc32_bb_impl.cc b/gr-digital/lib/crc32_bb_impl.cc index ad82aef595..4df1869a70 100644 --- a/gr-digital/lib/crc32_bb_impl.cc +++ b/gr-digital/lib/crc32_bb_impl.cc @@ -108,7 +108,7 @@ namespace gr { } } else{ - for(int i=0; i < d_crc_length; i++){ + for(unsigned int i=0; i < d_crc_length; i++){ if(((crc >> i) & 0x1) != *(in + packet_length - d_crc_length + i)) { // Drop package return 0; } @@ -122,7 +122,7 @@ namespace gr { memcpy((void *) (out + packet_length), &crc, d_crc_length); // FIXME big-endian/little-endian, this might be wrong } else { - for (int i = 0; i < d_crc_length; i++) { // unpack CRC and store in buffer + for (unsigned int i = 0; i < d_crc_length; i++) { // unpack CRC and store in buffer d_buffer[i] = (crc >> i) & 0x1; } memcpy((void *) (out + packet_length), (void *) &d_buffer[0], d_crc_length); diff --git a/gr-digital/lib/crc32_bb_impl.h b/gr-digital/lib/crc32_bb_impl.h index d7316eb548..07a798c8b9 100644 --- a/gr-digital/lib/crc32_bb_impl.h +++ b/gr-digital/lib/crc32_bb_impl.h @@ -35,7 +35,7 @@ namespace gr { bool d_check; bool d_packed; boost::crc_optimal<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true> d_crc_impl; - int d_crc_length; + unsigned int d_crc_length; std::vector<char> d_buffer; unsigned int calculate_crc32(const unsigned char* in, size_t packet_length); diff --git a/gr-digital/python/digital/qa_binary_slicer_fb.py b/gr-digital/python/digital/qa_binary_slicer_fb.py index 0b2879380b..9b18af6d4a 100644 --- a/gr-digital/python/digital/qa_binary_slicer_fb.py +++ b/gr-digital/python/digital/qa_binary_slicer_fb.py @@ -28,6 +28,7 @@ from gnuradio import gr, gr_unittest, digital, blocks class test_binary_slicer_fb(gr_unittest.TestCase): def setUp(self): + random.seed(0) self.tb = gr.top_block() def tearDown(self): diff --git a/gr-digital/python/digital/qa_clock_recovery_mm.py b/gr-digital/python/digital/qa_clock_recovery_mm.py index 0618ec321c..6c7de5b50c 100644 --- a/gr-digital/python/digital/qa_clock_recovery_mm.py +++ b/gr-digital/python/digital/qa_clock_recovery_mm.py @@ -29,6 +29,7 @@ from gnuradio import gr, gr_unittest, digital, blocks class test_clock_recovery_mm(gr_unittest.TestCase): def setUp(self): + random.seed(0) self.tb = gr.top_block() def tearDown(self): diff --git a/gr-digital/python/digital/qa_constellation.py b/gr-digital/python/digital/qa_constellation.py index 3436ce6f45..c21afc03a6 100644 --- a/gr-digital/python/digital/qa_constellation.py +++ b/gr-digital/python/digital/qa_constellation.py @@ -171,6 +171,7 @@ class test_constellation(gr_unittest.TestCase): src_length = 256 def setUp(self): + random.seed(0) # Generate a list of random bits. self.src_data = tuple([random.randint(0,1) for i in range(0, self.src_length)]) diff --git a/gr-digital/python/digital/qa_constellation_receiver.py b/gr-digital/python/digital/qa_constellation_receiver.py index 4850863fa5..ffe7355c32 100644 --- a/gr-digital/python/digital/qa_constellation_receiver.py +++ b/gr-digital/python/digital/qa_constellation_receiver.py @@ -89,6 +89,9 @@ class test_constellation_receiver(gr_unittest.TestCase): max_data_length = DATA_LENGTH * 6 max_num_samples = 1000 + def setUp(self): + random.seed(0) + def test_basic(self): """ Tests a bunch of different constellations by using generic diff --git a/gr-digital/python/digital/qa_constellation_soft_decoder_cf.py b/gr-digital/python/digital/qa_constellation_soft_decoder_cf.py index 629d52c0a4..66151481c6 100644 --- a/gr-digital/python/digital/qa_constellation_soft_decoder_cf.py +++ b/gr-digital/python/digital/qa_constellation_soft_decoder_cf.py @@ -28,6 +28,7 @@ from numpy import random, vectorize class test_constellation_soft_decoder(gr_unittest.TestCase): def setUp(self): + random.seed(0) self.tb = gr.top_block() def tearDown(self): diff --git a/gr-digital/python/digital/qa_costas_loop_cc.py b/gr-digital/python/digital/qa_costas_loop_cc.py index 283a9199df..bd65d7a209 100644 --- a/gr-digital/python/digital/qa_costas_loop_cc.py +++ b/gr-digital/python/digital/qa_costas_loop_cc.py @@ -31,6 +31,7 @@ from gnuradio.digital import psk class test_costas_loop_cc(gr_unittest.TestCase): def setUp(self): + random.seed(0) self.tb = gr.top_block() def tearDown(self): diff --git a/gr-digital/python/digital/qa_crc32.py b/gr-digital/python/digital/qa_crc32.py index 6d3d2fa3ce..6bb00328f6 100644 --- a/gr-digital/python/digital/qa_crc32.py +++ b/gr-digital/python/digital/qa_crc32.py @@ -21,7 +21,6 @@ # -import random import cmath from gnuradio import gr, gr_unittest, digital diff --git a/gr-digital/python/digital/qa_diff_encoder.py b/gr-digital/python/digital/qa_diff_encoder.py index 58d757d0c2..d328020fad 100644 --- a/gr-digital/python/digital/qa_diff_encoder.py +++ b/gr-digital/python/digital/qa_diff_encoder.py @@ -35,6 +35,7 @@ def make_random_int_tuple(L, min, max): class test_diff_encoder(gr_unittest.TestCase): def setUp(self): + random.seed(0) self.tb = gr.top_block() def tearDown(self): diff --git a/gr-digital/python/digital/qa_fll_band_edge.py b/gr-digital/python/digital/qa_fll_band_edge.py index a4859565ec..a9018931ed 100644 --- a/gr-digital/python/digital/qa_fll_band_edge.py +++ b/gr-digital/python/digital/qa_fll_band_edge.py @@ -30,6 +30,7 @@ from gnuradio import gr, gr_unittest, digital, filter, blocks, analog class test_fll_band_edge_cc(gr_unittest.TestCase): def setUp(self): + random.seed(0) self.tb = gr.top_block() def tearDown(self): diff --git a/gr-digital/python/digital/qa_header_payload_demux.py b/gr-digital/python/digital/qa_header_payload_demux.py index d77f7c689d..be1178c4ac 100644 --- a/gr-digital/python/digital/qa_header_payload_demux.py +++ b/gr-digital/python/digital/qa_header_payload_demux.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright 2012-2016 Free Software Foundation, Inc. +# Copyright 2012-2016,2018 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -34,6 +34,7 @@ import pmt def make_tag(key, value, offset): + """Create a gr.tag_t() from key, value, offset.""" tag = gr.tag_t() tag.offset = offset tag.key = pmt.string_to_symbol(key) @@ -46,7 +47,7 @@ class HeaderToMessageBlock(gr.sync_block): Helps with testing the HPD. Receives a header, stores it, posts a predetermined message. """ - def __init__(self, itemsize, header_len, messages, header_is_symbol=False): + def __init__(self, itemsize, header_len, messages): gr.sync_block.__init__( self, name="HeaderToMessageBlock", @@ -59,9 +60,9 @@ class HeaderToMessageBlock(gr.sync_block): self.msg_count = 0 def work(self, input_items, output_items): - for i in range(len(input_items[0]) // self.header_len): + """Where the magic happens.""" + for _ in range(len(input_items[0]) // self.header_len): msg = self.messages[self.msg_count] or False - #print("Sending message: {0}".format(msg)) self.message_port_pub(pmt.intern('header_data'), pmt.to_pmt(msg)) self.msg_count += 1 output_items[0][:] = input_items[0][:] @@ -71,32 +72,35 @@ class HeaderToMessageBlock(gr.sync_block): class qa_header_payload_demux (gr_unittest.TestCase): def setUp (self): + """Runs before every test.""" self.tb = gr.top_block () + random.seed(0) def tearDown (self): + """Runs after every test.""" self.tb = None def connect_all_blocks(self, - data_src, trigger_src, - hpd, - mock_header_demod, - payload_sink, header_sink - ): + data_src, trigger_src, + hpd, + mock_header_demod, + payload_sink, header_sink): """ Connect the standard HPD test flowgraph """ - self.tb.connect(data_src, (hpd, 0)) + self.tb.connect(data_src, (hpd, 0)) if trigger_src is not None: self.tb.connect(trigger_src, (hpd, 1)) self.tb.connect((hpd, 0), mock_header_demod) self.tb.connect(mock_header_demod, header_sink) self.tb.msg_connect( - mock_header_demod, 'header_data', - hpd, 'header_data' + mock_header_demod, 'header_data', + hpd, 'header_data' ) self.tb.connect((hpd, 1), payload_sink) def run_tb(self, payload_sink, payload_len, header_sink, header_len, timeout=30): + """Execute self.tb""" stop_time = time.time() + timeout self.tb.start() while len(payload_sink.data()) < payload_len and \ @@ -106,7 +110,7 @@ class qa_header_payload_demux (gr_unittest.TestCase): self.tb.stop() self.tb.wait() - def test_001_t (self): + def test_001_t(self): """ Simplest possible test: put in zeros, then header, then payload, trigger signal, try to demux. The return signal from the header parser is faked via _post() @@ -127,23 +131,29 @@ class qa_header_payload_demux (gr_unittest.TestCase): # This goes on output 1, item 3: testtag4 = make_tag('tag4', 314, n_zeros + len(header) + 3) data_src = blocks.vector_source_f( - data_signal, - False, - tags=(testtag1, testtag2, testtag3, testtag4) + data_signal, + False, + tags=(testtag1, testtag2, testtag3, testtag4) ) trigger_src = blocks.vector_source_b(trigger_signal, False) hpd = digital.header_payload_demux( len(header), 1, 0, "frame_len", "detect", False, gr.sizeof_float ) mock_header_demod = HeaderToMessageBlock( - numpy.float32, - len(header), - [len(payload)] + numpy.float32, + len(header), + [len(payload)] ) self.assertEqual(pmt.length(hpd.message_ports_in()), 2) #extra system port defined for you payload_sink = blocks.vector_sink_f() header_sink = blocks.vector_sink_f() - self.connect_all_blocks(data_src, trigger_src, hpd, mock_header_demod, payload_sink, header_sink) + self.connect_all_blocks( + data_src, + trigger_src, + hpd, + mock_header_demod, + payload_sink, + header_sink) self.run_tb(payload_sink, len(payload), header_sink, len(header)) self.assertEqual(header_sink.data(), header) self.assertEqual(payload_sink.data(), payload) @@ -152,8 +162,8 @@ class qa_header_payload_demux (gr_unittest.TestCase): ptag = gr.tag_to_python(tag) ptags_header.append({'key': ptag.key, 'offset': ptag.offset}) expected_tags_header = [ - {'key': 'tag2', 'offset': 0}, - {'key': 'tag3', 'offset': 2}, + {'key': 'tag2', 'offset': 0}, + {'key': 'tag3', 'offset': 2}, ] self.assertEqual(expected_tags_header, ptags_header) ptags_payload = [] @@ -161,12 +171,12 @@ class qa_header_payload_demux (gr_unittest.TestCase): ptag = gr.tag_to_python(tag) ptags_payload.append({'key': ptag.key, 'offset': ptag.offset}) expected_tags_payload = [ - {'key': 'frame_len', 'offset': 0}, - {'key': 'tag4', 'offset': 3}, + {'key': 'frame_len', 'offset': 0}, + {'key': 'tag4', 'offset': 3}, ] self.assertEqual(expected_tags_payload, ptags_payload) - def test_001_t_tags (self): + def test_001_t_tags(self): """ Like the previous test, but use a trigger tag instead of a trigger signal. """ @@ -185,9 +195,9 @@ class qa_header_payload_demux (gr_unittest.TestCase): # This goes on output 1, item 3: testtag4 = make_tag('tag4', 314, n_zeros + len(header) + 3) data_src = blocks.vector_source_f( - data_signal, - False, - tags=(trigger_tag, testtag1, testtag2, testtag3, testtag4) + data_signal, + False, + tags=(trigger_tag, testtag1, testtag2, testtag3, testtag4) ) hpd = digital.header_payload_demux( len(header), 1, 0, "frame_len", "detect", False, gr.sizeof_float @@ -196,22 +206,22 @@ class qa_header_payload_demux (gr_unittest.TestCase): header_sink = blocks.vector_sink_f() payload_sink = blocks.vector_sink_f() mock_header_demod = HeaderToMessageBlock( - numpy.float32, - len(header), - [len(payload)] + numpy.float32, + len(header), + [len(payload)] ) self.connect_all_blocks(data_src, None, hpd, mock_header_demod, payload_sink, header_sink) self.run_tb(payload_sink, len(payload), header_sink, len(header)) # Check results - self.assertEqual(header_sink.data(), header) + self.assertEqual(header_sink.data(), header) self.assertEqual(payload_sink.data(), payload) ptags_header = [] for tag in header_sink.tags(): ptag = gr.tag_to_python(tag) ptags_header.append({'key': ptag.key, 'offset': ptag.offset}) expected_tags_header = [ - {'key': 'tag2', 'offset': 0}, - {'key': 'tag3', 'offset': 2}, + {'key': 'tag2', 'offset': 0}, + {'key': 'tag3', 'offset': 2}, ] self.assertEqual(expected_tags_header, ptags_header) ptags_payload = [] @@ -219,8 +229,8 @@ class qa_header_payload_demux (gr_unittest.TestCase): ptag = gr.tag_to_python(tag) ptags_payload.append({'key': ptag.key, 'offset': ptag.offset}) expected_tags_payload = [ - {'key': 'frame_len', 'offset': 0}, - {'key': 'tag4', 'offset': 3}, + {'key': 'frame_len', 'offset': 0}, + {'key': 'tag4', 'offset': 3}, ] self.assertEqual(expected_tags_payload, ptags_payload) @@ -242,9 +252,9 @@ class qa_header_payload_demux (gr_unittest.TestCase): # This goes on output 1, item 3: testtag4 = make_tag('tag4', 314, n_zeros + len(header) + 3) data_src = blocks.vector_source_f( - data_signal, - False, - tags=(testtag1, testtag2, testtag3, testtag4) + data_signal, + False, + tags=(testtag1, testtag2, testtag3, testtag4) ) trigger_src = blocks.vector_source_b(trigger_signal, False) hpd = digital.header_payload_demux( @@ -271,15 +281,15 @@ class qa_header_payload_demux (gr_unittest.TestCase): self.run_tb(payload_sink, len(payload), header_sink, len(header)+2) # Check values # Header now is padded: - self.assertEqual(header_sink.data(), (0,) + header + (payload[0],)) + self.assertEqual(header_sink.data(), (0,) + header + (payload[0],)) self.assertEqual(payload_sink.data(), payload) ptags_header = [] for tag in header_sink.tags(): ptag = gr.tag_to_python(tag) ptags_header.append({'key': ptag.key, 'offset': ptag.offset}) expected_tags_header = [ - {'key': 'tag2', 'offset': 1}, - {'key': 'tag3', 'offset': 3}, + {'key': 'tag2', 'offset': 1}, + {'key': 'tag3', 'offset': 3}, ] self.assertEqual(expected_tags_header, ptags_header) ptags_payload = [] @@ -287,8 +297,8 @@ class qa_header_payload_demux (gr_unittest.TestCase): ptag = gr.tag_to_python(tag) ptags_payload.append({'key': ptag.key, 'offset': ptag.offset}) expected_tags_payload = [ - {'key': 'frame_len', 'offset': 0}, - {'key': 'tag4', 'offset': 3}, + {'key': 'frame_len', 'offset': 0}, + {'key': 'tag4', 'offset': 3}, ] self.assertEqual(expected_tags_payload, ptags_payload) @@ -305,9 +315,9 @@ class qa_header_payload_demux (gr_unittest.TestCase): # This goes on output 1, item 3 + 1 (for payload offset) testtag4 = make_tag('tag4', 314, n_zeros + len(header) + 3) data_src = blocks.vector_source_f( - data_signal, - False, - tags=(testtag4,) + data_signal, + False, + tags=(testtag4,) ) trigger_src = blocks.vector_source_b(trigger_signal, False) hpd = digital.header_payload_demux( @@ -333,8 +343,8 @@ class qa_header_payload_demux (gr_unittest.TestCase): self.tb.start() time.sleep(.2) # Need this, otherwise, the next message is ignored hpd.to_basic_block()._post( - pmt.intern('header_data'), - pmt.to_pmt({'frame_len': len(payload), 'payload_offset': payload_offset}) + pmt.intern('header_data'), + pmt.to_pmt({'frame_len': len(payload), 'payload_offset': payload_offset}) ) while len(payload_sink.data()) < len(payload): time.sleep(.2) @@ -344,22 +354,22 @@ class qa_header_payload_demux (gr_unittest.TestCase): self.assertEqual(header_sink.data(), (0,) + header + (payload[0],)) # Payload is now offset: self.assertEqual( - payload_sink.data(), - data_signal[n_zeros + len(header) + payload_offset:n_zeros + len(header) + payload_offset + len(payload)] + payload_sink.data(), + data_signal[n_zeros + len(header) + payload_offset:n_zeros + len(header) + payload_offset + len(payload)] ) ptags_payload = {} for tag in payload_sink.tags(): ptag = gr.tag_to_python(tag) ptags_payload[ptag.key] = ptag.offset expected_tags_payload = { - 'frame_len': 0, - 'payload_offset': 0, - 'tag4': 3 - payload_offset, + 'frame_len': 0, + 'payload_offset': 0, + 'tag4': 3 - payload_offset, } self.assertEqual(expected_tags_payload, ptags_payload) - def test_002_symbols (self): + def test_002_symbols(self): """ Same as before, but operate on symbols """ @@ -401,8 +411,8 @@ class qa_header_payload_demux (gr_unittest.TestCase): self.tb.start() time.sleep(.2) # Need this, otherwise, the next message is ignored hpd.to_basic_block()._post( - pmt.intern('header_data'), - pmt.from_long(n_symbols) + pmt.intern('header_data'), + pmt.from_long(n_symbols) ) while len(payload_sink.data()) < len(payload) * n_symbols: time.sleep(.2) @@ -415,8 +425,8 @@ class qa_header_payload_demux (gr_unittest.TestCase): ptag = gr.tag_to_python(tag) ptags_header.append({'key': ptag.key, 'offset': ptag.offset}) expected_tags_header = [ - {'key': 'tag2', 'offset': 0}, - {'key': 'tag3', 'offset': 0}, + {'key': 'tag2', 'offset': 0}, + {'key': 'tag3', 'offset': 0}, ] self.assertEqual(expected_tags_header, ptags_header) ptags_payload = [] @@ -424,12 +434,12 @@ class qa_header_payload_demux (gr_unittest.TestCase): ptag = gr.tag_to_python(tag) ptags_payload.append({'key': ptag.key, 'offset': ptag.offset}) expected_tags_payload = [ - {'key': 'frame_len', 'offset': 0}, - {'key': 'tag4', 'offset': 1}, + {'key': 'frame_len', 'offset': 0}, + {'key': 'tag4', 'offset': 1}, ] self.assertEqual(expected_tags_payload, ptags_payload) - def test_003_t (self): + def test_003_t(self): """ Like test 1, but twice, plus one fail """ @@ -448,8 +458,7 @@ class qa_header_payload_demux (gr_unittest.TestCase): print("Triggers at: {0} {1} {2}".format( n_zeros, len(data_signal), - len(data_signal)+len(header_fail)+n_zeros) - ) + len(data_signal)+len(header_fail)+n_zeros)) tx_signal = data_signal + \ header_fail + (0,) * n_zeros + \ header + payload2 + (0,) * 1000 @@ -487,21 +496,21 @@ class qa_header_payload_demux (gr_unittest.TestCase): self.tb.start() time.sleep(.2) # Need this, otherwise, the next message is ignored hpd.to_basic_block()._post( - pmt.intern('header_data'), - pmt.from_long(len(payload1)) + pmt.intern('header_data'), + pmt.from_long(len(payload1)) ) while len(payload_sink.data()) < len(payload1): time.sleep(.2) hpd.to_basic_block()._post( - pmt.intern('header_data'), - pmt.PMT_F + pmt.intern('header_data'), + pmt.PMT_F ) # This next command is a bit of a showstopper, but there's no condition to check upon # to see if the previous msg handling is finished time.sleep(.7) hpd.to_basic_block()._post( - pmt.intern('header_data'), - pmt.from_long(len(payload2)) + pmt.intern('header_data'), + pmt.from_long(len(payload2)) ) while len(payload_sink.data()) < len(payload1) + len(payload2): time.sleep(.2) @@ -552,7 +561,7 @@ class qa_header_payload_demux (gr_unittest.TestCase): indexes = [] burst_sizes = [] total_payload_len = 0 - for burst_count in range(n_bursts): + for _ in range(n_bursts): gap_size = random.randint(0, max_gap) signal += [0] * gap_size is_failure = random.random() < fail_rate @@ -579,11 +588,12 @@ class qa_header_payload_demux (gr_unittest.TestCase): trigger_tags += [make_tag('detect', True, index)] return (trigger_signal, trigger_tags) ### Go, go, go + # Uncomment this if you want true randomness -- good for actual fuzzing # The divide-by-20 means we'll usually get the same random seed # between the first run and the XML run. - random_seed = int(time.time() / 20) - random.seed(random_seed) - print("Random seed: {0}".format(random_seed)) + # random_seed = int(time.time() / 20) + # random.seed(random_seed) + # print("Random seed: {0}".format(random_seed)) n_bursts = 400 header_len = 5 max_gap = 50 @@ -612,9 +622,9 @@ class qa_header_payload_demux (gr_unittest.TestCase): special_tags=('rx_freq',), ) mock_header_demod = HeaderToMessageBlock( - numpy.float32, - header_len, - burst_sizes + numpy.float32, + header_len, + burst_sizes ) header_sink = blocks.vector_sink_f() payload_sink = blocks.vector_sink_f() diff --git a/gr-digital/python/digital/qa_ofdm_chanest_vcvc.py b/gr-digital/python/digital/qa_ofdm_chanest_vcvc.py index e39247da0a..501afd413c 100644 --- a/gr-digital/python/digital/qa_ofdm_chanest_vcvc.py +++ b/gr-digital/python/digital/qa_ofdm_chanest_vcvc.py @@ -45,6 +45,7 @@ def rand_range(min_val, max_val): class qa_ofdm_chanest_vcvc (gr_unittest.TestCase): def setUp (self): + random.seed(0) self.tb = gr.top_block () def tearDown (self): diff --git a/gr-digital/python/digital/qa_ofdm_sync_sc_cfb.py b/gr-digital/python/digital/qa_ofdm_sync_sc_cfb.py index 610d883b6c..5b67d868a0 100644 --- a/gr-digital/python/digital/qa_ofdm_sync_sc_cfb.py +++ b/gr-digital/python/digital/qa_ofdm_sync_sc_cfb.py @@ -22,23 +22,37 @@ from __future__ import division -import numpy import random +import numpy from gnuradio import gr, gr_unittest, blocks, analog, channels from gnuradio import digital from gnuradio.digital.utils import tagged_streams from gnuradio.digital.ofdm_txrx import ofdm_tx +def make_bpsk_burst(fft_len, cp_len, num_bits): + """ Create a burst of a sync symbol and some BPSK bits """ + sync_symbol = [ + (random.randint(0, 1)*2)-1 + for x in range(fft_len // 2) + ] * 2 + sync_symbols = sync_symbol[-cp_len:] + sync_symbol + mod_symbols = [ + (random.randint(0, 1)*2)-1 + for x in range(num_bits) + ] + return sync_symbols + mod_symbols + class qa_ofdm_sync_sc_cfb (gr_unittest.TestCase): - def setUp (self): + def setUp(self): + random.seed(0) self.tb = gr.top_block () - def tearDown (self): + def tearDown(self): self.tb = None - def test_001_detect (self): + def test_001_detect(self): """ Send two bursts, with zeros in between, and check they are both detected at the correct position and no false alarms occur """ @@ -46,15 +60,11 @@ class qa_ofdm_sync_sc_cfb (gr_unittest.TestCase): fft_len = 32 cp_len = 4 sig_len = (fft_len + cp_len) * 10 - sync_symbol = [(random.randint(0, 1)*2)-1 for x in range(fft_len // 2)] * 2 - tx_signal = [0,] * n_zeros + \ - sync_symbol[-cp_len:] + \ - sync_symbol + \ - [(random.randint(0, 1)*2)-1 for x in range(sig_len)] + tx_signal = [0,] * n_zeros + make_bpsk_burst(fft_len, cp_len, sig_len) tx_signal = tx_signal * 2 add = blocks.add_cc() sync = digital.ofdm_sync_sc_cfb(fft_len, cp_len) - sink_freq = blocks.vector_sink_f() + sink_freq = blocks.vector_sink_f() sink_detect = blocks.vector_sink_b() self.tb.connect(blocks.vector_source_c(tx_signal), (add, 0)) self.tb.connect(analog.noise_source_c(analog.GR_GAUSSIAN, .01), (add, 1)) @@ -69,7 +79,7 @@ class qa_ofdm_sync_sc_cfb (gr_unittest.TestCase): self.assertEqual(numpy.sum(sig1_detect), 1) self.assertEqual(numpy.sum(sig2_detect), 1) - def test_002_freq (self): + def test_002_freq(self): """ Add a fine frequency offset and see if that gets detected properly """ fft_len = 32 cp_len = 4 @@ -77,12 +87,9 @@ class qa_ofdm_sync_sc_cfb (gr_unittest.TestCase): max_freq_offset = 2*numpy.pi/fft_len # Otherwise, it's coarse freq_offset = ((2 * random.random()) - 1) * max_freq_offset sig_len = (fft_len + cp_len) * 10 - sync_symbol = [(random.randint(0, 1)*2)-1 for x in range(fft_len // 2)] * 2 - tx_signal = sync_symbol[-cp_len:] + \ - sync_symbol + \ - [(random.randint(0, 1)*2)-1 for x in range(sig_len)] + tx_signal = make_bpsk_burst(fft_len, cp_len, sig_len) sync = digital.ofdm_sync_sc_cfb(fft_len, cp_len, True) - sink_freq = blocks.vector_sink_f() + sink_freq = blocks.vector_sink_f() sink_detect = blocks.vector_sink_b() channel = channels.channel_model(0.005, freq_offset / 2.0 / numpy.pi) self.tb.connect(blocks.vector_source_c(tx_signal), channel, sync) @@ -93,39 +100,45 @@ class qa_ofdm_sync_sc_cfb (gr_unittest.TestCase): est_freq_offset = 2 * phi_hat / fft_len self.assertAlmostEqual(est_freq_offset, freq_offset, places=2) - def test_003_multiburst (self): + def test_003_multiburst(self): """ Send several bursts, see if the number of detects is correct. Burst lengths and content are random. + + The channel is assumed AWGN for this test. """ n_bursts = 42 fft_len = 32 cp_len = 4 tx_signal = [] - for i in range(n_bursts): - sync_symbol = [(random.randint(0, 1)*2)-1 for x in range(fft_len // 2)] * 2 - tx_signal += [0,] * random.randint(0, 2*fft_len) + \ - sync_symbol[-cp_len:] + \ - sync_symbol + \ - [(random.randint(0, 1)*2)-1 for x in range(fft_len * random.randint(5,23))] - add = blocks.add_cc() + for _ in range(n_bursts): + gap = [0,] * random.randint(0, 2*fft_len) + tx_signal += \ + gap + \ + make_bpsk_burst(fft_len, cp_len, fft_len * random.randint(5, 23)) + # Very loose definition of SNR here + snr = 20 # dB + sigma = 10**(-snr/10) + # Add noise -- we don't use the channel model blocks, we want to keep + # this test as self-contained as possible, and all randomness should + # derive from random.seed() above + complex_randn = \ + lambda N: (numpy.random.randn(N) + 1j * numpy.random.randn(N)) * sigma / numpy.sqrt(2) + tx_signal += complex_randn(len(tx_signal)) sync = digital.ofdm_sync_sc_cfb(fft_len, cp_len) - sink_freq = blocks.vector_sink_f() + sink_freq = blocks.vector_sink_f() sink_detect = blocks.vector_sink_b() - channel = channels.channel_model(0.005) - self.tb.connect(blocks.vector_source_c(tx_signal), channel, sync) + self.tb.connect(blocks.vector_source_c(tx_signal), sync) self.tb.connect((sync, 0), sink_freq) self.tb.connect((sync, 1), sink_detect) self.tb.run() n_bursts_detected = numpy.sum(sink_detect.data()) - # We allow for one false alarm or missed burst - self.assertTrue(abs(n_bursts_detected - n_bursts) <= 1, - msg="""Because of statistics, it is possible (though unlikely) -that the number of detected bursts differs slightly. If the number of detects is -off by one or two, run the test again and see what happen. -Detection error was: %d """ % (numpy.sum(sink_detect.data()) - n_bursts) + self.assertEqual( + n_bursts_detected, n_bursts, + msg="Detection error (missed bursts): {}".format( + (numpy.sum(sink_detect.data()) - n_bursts)) ) - def test_004_ofdm_packets (self): + def test_004_ofdm_packets(self): """ Send several bursts using ofdm_tx, see if the number of detects is correct. Burst lengths and content are random. @@ -136,23 +149,20 @@ Detection error was: %d """ % (numpy.sum(sink_detect.data()) - n_bursts) # Here, coarse freq offset is allowed max_freq_offset = 2*numpy.pi/fft_len * 4 freq_offset = ((2 * random.random()) - 1) * max_freq_offset - tx_signal = [] packets = [] tagname = "packet_length" min_packet_length = 10 max_packet_length = 50 - sync_sequence = [random.randint(0, 1)*2-1 for x in range(fft_len // 2)] - for i in range(n_bursts): + for _ in range(n_bursts): packet_length = random.randint(min_packet_length, max_packet_length+1) packet = [random.randint(0, 255) for i in range(packet_length)] packets.append(packet) data, tags = tagged_streams.packets_to_vectors(packets, tagname, vlen=1) - total_length = len(data) src = blocks.vector_source_b(data, False, 1, tags) mod = ofdm_tx(packet_length_tag_key=tagname) sync = digital.ofdm_sync_sc_cfb(fft_len, cp_len) - sink_freq = blocks.vector_sink_f() + sink_freq = blocks.vector_sink_f() sink_detect = blocks.vector_sink_b() noise_level = 0.005 channel = channels.channel_model(noise_level, freq_offset / 2 / numpy.pi) @@ -164,4 +174,3 @@ Detection error was: %d """ % (numpy.sum(sink_detect.data()) - n_bursts) if __name__ == '__main__': gr_unittest.run(qa_ofdm_sync_sc_cfb, "qa_ofdm_sync_sc_cfb.xml") - diff --git a/gr-digital/python/digital/qa_ofdm_txrx.py b/gr-digital/python/digital/qa_ofdm_txrx.py index 2e8d101317..74a836a047 100644 --- a/gr-digital/python/digital/qa_ofdm_txrx.py +++ b/gr-digital/python/digital/qa_ofdm_txrx.py @@ -67,6 +67,7 @@ class ofdm_rx_fg (gr.top_block): class test_ofdm_txrx (gr_unittest.TestCase): def setUp (self): + random.seed(0) self.tb = gr.top_block () def tearDown (self): diff --git a/gr-digital/python/digital/qa_packet_headerparser_b.py b/gr-digital/python/digital/qa_packet_headerparser_b.py index 3e22fa9100..e41cb35599 100644 --- a/gr-digital/python/digital/qa_packet_headerparser_b.py +++ b/gr-digital/python/digital/qa_packet_headerparser_b.py @@ -30,6 +30,7 @@ import pmt class qa_packet_headerparser_b (gr_unittest.TestCase): def setUp (self): + random.seed(0) self.tb = gr.top_block () def tearDown (self): diff --git a/gr-digital/python/digital/qa_pfb_clock_sync.py b/gr-digital/python/digital/qa_pfb_clock_sync.py index 77980d19e5..3f07b328c9 100644 --- a/gr-digital/python/digital/qa_pfb_clock_sync.py +++ b/gr-digital/python/digital/qa_pfb_clock_sync.py @@ -31,6 +31,7 @@ from gnuradio import gr, gr_unittest, filter, digital, blocks class test_pfb_clock_sync(gr_unittest.TestCase): def setUp(self): + random.seed(0) self.tb = gr.top_block() def tearDown(self): diff --git a/gr-dtv/CMakeLists.txt b/gr-dtv/CMakeLists.txt index 11488ac413..119837ace4 100644 --- a/gr-dtv/CMakeLists.txt +++ b/gr-dtv/CMakeLists.txt @@ -57,10 +57,12 @@ add_subdirectory(lib) if(ENABLE_PYTHON) add_subdirectory(swig) add_subdirectory(python/dtv) - add_subdirectory(grc) add_subdirectory(examples) add_subdirectory(apps) endif(ENABLE_PYTHON) +if(ENABLE_GRC) + add_subdirectory(grc) +endif(ENABLE_GRC) add_subdirectory(docs) ######################################################################## diff --git a/gr-dtv/grc/CMakeLists.txt b/gr-dtv/grc/CMakeLists.txt index 3ed47f2311..ef4b37aae1 100644 --- a/gr-dtv/grc/CMakeLists.txt +++ b/gr-dtv/grc/CMakeLists.txt @@ -72,5 +72,6 @@ install(FILES dtv_catv_randomizer_bb.block.yml dtv_catv_frame_sync_enc_bb.block.yml dtv_catv_trellis_enc_bb.block.yml + dtv.tree.yml DESTINATION ${GRC_BLOCKS_DIR} ) diff --git a/gr-dtv/grc/dtv_dvb_bbheader_bb.block.yml b/gr-dtv/grc/dtv_dvb_bbheader_bb.block.yml index 520e5dd4c8..6c3c54df75 100644 --- a/gr-dtv/grc/dtv_dvb_bbheader_bb.block.yml +++ b/gr-dtv/grc/dtv_dvb_bbheader_bb.block.yml @@ -8,8 +8,8 @@ parameters: options: [STANDARD_DVBS2, STANDARD_DVBT2] option_labels: [DVB-S2, DVB-T2] option_attributes: - hide_dvbs2: ['', all] - hide_dvbt2: [all, ''] + hide_dvbs2: [none, all] + hide_dvbt2: [all, none] val: [dtv.STANDARD_DVBS2, dtv.STANDARD_DVBT2] - id: framesize1 label: FECFRAME size @@ -18,8 +18,8 @@ parameters: option_labels: [Normal, Short] option_attributes: hide_medium: [all, all] - hide_normal: ['', all] - hide_short: [all, ''] + hide_normal: [none, all] + hide_short: [all, none] val: [dtv.FECFRAME_NORMAL, dtv.FECFRAME_SHORT] hide: ${ standard.hide_dvbt2 } - id: framesize2 @@ -28,9 +28,9 @@ parameters: options: [FECFRAME_NORMAL, FECFRAME_MEDIUM, FECFRAME_SHORT] option_labels: [Normal, Medium, Short] option_attributes: - hide_medium: [all, '', all] - hide_normal: ['', all, all] - hide_short: [all, all, ''] + hide_medium: [all, none, all] + hide_normal: [none, all, all] + hide_short: [all, all, none] val: [dtv.FECFRAME_NORMAL, dtv.FECFRAME_MEDIUM, dtv.FECFRAME_SHORT] hide: ${ standard.hide_dvbs2 } - id: rate1 @@ -119,7 +119,7 @@ parameters: options: [INBAND_OFF, INBAND_ON] option_labels: ['Off', Type B] option_attributes: - hide_rate: [all, ''] + hide_rate: [all, none] val: [dtv.INBAND_OFF, dtv.INBAND_ON] hide: ${ standard.hide_dvbt2 } - id: fecblocks diff --git a/gr-dtv/grc/dtv_dvb_bbscrambler_bb.block.yml b/gr-dtv/grc/dtv_dvb_bbscrambler_bb.block.yml index 86872688ed..6b9c95cef1 100644 --- a/gr-dtv/grc/dtv_dvb_bbscrambler_bb.block.yml +++ b/gr-dtv/grc/dtv_dvb_bbscrambler_bb.block.yml @@ -8,8 +8,8 @@ parameters: options: [STANDARD_DVBS2, STANDARD_DVBT2] option_labels: [DVB-S2, DVB-T2] option_attributes: - hide_dvbs2: ['', all] - hide_dvbt2: [all, ''] + hide_dvbs2: [none, all] + hide_dvbt2: [all, none] val: [dtv.STANDARD_DVBS2, dtv.STANDARD_DVBT2] - id: framesize1 label: FECFRAME size @@ -18,8 +18,8 @@ parameters: option_labels: [Normal, Short] option_attributes: hide_medium: [all, all] - hide_normal: ['', all] - hide_short: [all, ''] + hide_normal: [none, all] + hide_short: [all, none] val: [dtv.FECFRAME_NORMAL, dtv.FECFRAME_SHORT] hide: ${ standard.hide_dvbt2 } - id: framesize2 @@ -28,9 +28,9 @@ parameters: options: [FECFRAME_NORMAL, FECFRAME_MEDIUM, FECFRAME_SHORT] option_labels: [Normal, Medium, Short] option_attributes: - hide_medium: [all, '', all] - hide_normal: ['', all, all] - hide_short: [all, all, ''] + hide_medium: [all, none, all] + hide_normal: [none, all, all] + hide_short: [all, all, none] val: [dtv.FECFRAME_NORMAL, dtv.FECFRAME_MEDIUM, dtv.FECFRAME_SHORT] hide: ${ standard.hide_dvbs2 } - id: rate1 diff --git a/gr-dtv/grc/dtv_dvb_bch_bb.block.yml b/gr-dtv/grc/dtv_dvb_bch_bb.block.yml index a9b47a52b2..817ee54c5d 100644 --- a/gr-dtv/grc/dtv_dvb_bch_bb.block.yml +++ b/gr-dtv/grc/dtv_dvb_bch_bb.block.yml @@ -8,8 +8,8 @@ parameters: options: [STANDARD_DVBS2, STANDARD_DVBT2] option_labels: [DVB-S2, DVB-T2] option_attributes: - hide_dvbs2: ['', all] - hide_dvbt2: [all, ''] + hide_dvbs2: [none, all] + hide_dvbt2: [all, none] val: [dtv.STANDARD_DVBS2, dtv.STANDARD_DVBT2] - id: framesize1 label: FECFRAME size @@ -18,8 +18,8 @@ parameters: option_labels: [Normal, Short] option_attributes: hide_medium: [all, all] - hide_normal: ['', all] - hide_short: [all, ''] + hide_normal: [none, all] + hide_short: [all, none] val: [dtv.FECFRAME_NORMAL, dtv.FECFRAME_SHORT] hide: ${ standard.hide_dvbt2 } - id: framesize2 @@ -28,9 +28,9 @@ parameters: options: [FECFRAME_NORMAL, FECFRAME_MEDIUM, FECFRAME_SHORT] option_labels: [Normal, Medium, Short] option_attributes: - hide_medium: [all, '', all] - hide_normal: ['', all, all] - hide_short: [all, all, ''] + hide_medium: [all, none, all] + hide_normal: [none, all, all] + hide_short: [all, all, none] val: [dtv.FECFRAME_NORMAL, dtv.FECFRAME_MEDIUM, dtv.FECFRAME_SHORT] hide: ${ standard.hide_dvbs2 } - id: rate1 diff --git a/gr-dtv/grc/dtv_dvb_ldpc_bb.block.yml b/gr-dtv/grc/dtv_dvb_ldpc_bb.block.yml index c8b5df4274..863643ce9b 100644 --- a/gr-dtv/grc/dtv_dvb_ldpc_bb.block.yml +++ b/gr-dtv/grc/dtv_dvb_ldpc_bb.block.yml @@ -8,8 +8,8 @@ parameters: options: [STANDARD_DVBS2, STANDARD_DVBT2] option_labels: [DVB-S2, DVB-T2] option_attributes: - hide_dvbs2: ['', all] - hide_dvbt2: [all, ''] + hide_dvbs2: [none, all] + hide_dvbt2: [all, none] val: [dtv.STANDARD_DVBS2, dtv.STANDARD_DVBT2] - id: framesize1 label: FECFRAME size @@ -18,8 +18,8 @@ parameters: option_labels: [Normal, Short] option_attributes: hide_medium: [all, all] - hide_normal: ['', all] - hide_short: [all, ''] + hide_normal: [none, all] + hide_short: [all, none] val: [dtv.FECFRAME_NORMAL, dtv.FECFRAME_SHORT] hide: ${ standard.hide_dvbt2 } - id: framesize2 @@ -28,9 +28,9 @@ parameters: options: [FECFRAME_NORMAL, FECFRAME_MEDIUM, FECFRAME_SHORT] option_labels: [Normal, Medium, Short] option_attributes: - hide_medium: [all, '', all] - hide_normal: ['', all, all] - hide_short: [all, all, ''] + hide_medium: [all, none, all] + hide_normal: [none, all, all] + hide_short: [all, all, none] val: [dtv.FECFRAME_NORMAL, dtv.FECFRAME_MEDIUM, dtv.FECFRAME_SHORT] hide: ${ standard.hide_dvbs2 } - id: rate1 @@ -119,7 +119,7 @@ templates: make: |- dtv.dvb_ldpc_bb( ${standard.val}, - if str(standard) == 'STANDARD_DVBT2': + % if str(standard) == 'STANDARD_DVBT2': ${framesize1.val}, % else: ${framesize2.val}, diff --git a/gr-dtv/grc/dtv_dvbs2_interleaver_bb.block.yml b/gr-dtv/grc/dtv_dvbs2_interleaver_bb.block.yml index d3a8a77abd..f9ab3446ac 100644 --- a/gr-dtv/grc/dtv_dvbs2_interleaver_bb.block.yml +++ b/gr-dtv/grc/dtv_dvbs2_interleaver_bb.block.yml @@ -8,9 +8,9 @@ parameters: options: [FECFRAME_NORMAL, FECFRAME_MEDIUM, FECFRAME_SHORT] option_labels: [Normal, Medium, Short] option_attributes: - hide_medium: [all, '', all] - hide_normal: ['', all, all] - hide_short: [all, all, ''] + hide_medium: [all, none, all] + hide_normal: [none, all, all] + hide_short: [all, all, none] val: [dtv.FECFRAME_NORMAL, dtv.FECFRAME_MEDIUM, dtv.FECFRAME_SHORT] - id: rate1 label: Code rate diff --git a/gr-dtv/grc/dtv_dvbs2_modulator_bc.block.yml b/gr-dtv/grc/dtv_dvbs2_modulator_bc.block.yml index dee9dba9b0..7935e0d85b 100644 --- a/gr-dtv/grc/dtv_dvbs2_modulator_bc.block.yml +++ b/gr-dtv/grc/dtv_dvbs2_modulator_bc.block.yml @@ -8,9 +8,9 @@ parameters: options: [FECFRAME_NORMAL, FECFRAME_MEDIUM, FECFRAME_SHORT] option_labels: [Normal, Medium, Short] option_attributes: - hide_medium: [all, '', all] - hide_normal: ['', all, all] - hide_short: [all, all, ''] + hide_medium: [all, none, all] + hide_normal: [none, all, all] + hide_short: [all, all, none] val: [dtv.FECFRAME_NORMAL, dtv.FECFRAME_MEDIUM, dtv.FECFRAME_SHORT] hide: ${ constellation.hide_dvb } - id: rate1 @@ -71,8 +71,8 @@ parameters: 64APSK, 8+16+20+20APSK, 4+12+20+28APSK, 128APSK, 256APSK, 64QAM (ITU-T J.83B), 256QAM (ITU-T J.83B), PI/2 BPSK, PI/2 BPSK-SF2, 8VSB (ATSC)] option_attributes: - hide_dvb: ['', '', '', '', '', '', '', '', '', '', '', '', '', all, all, '', - '', all] + hide_dvb: [none, none, none, none, none, none, none, none, none, none, none, none, none, all, all, none, + none, all] val: [dtv.MOD_QPSK, dtv.MOD_8PSK, dtv.MOD_8APSK, dtv.MOD_16APSK, dtv.MOD_8_8APSK, dtv.MOD_32APSK, dtv.MOD_4_12_16APSK, dtv.MOD_4_8_4_16APSK, dtv.MOD_64APSK, dtv.MOD_8_16_20_20APSK, dtv.MOD_4_12_20_28APSK, dtv.MOD_128APSK, dtv.MOD_256APSK, diff --git a/gr-dtv/grc/dtv_dvbs2_physical_cc.block.yml b/gr-dtv/grc/dtv_dvbs2_physical_cc.block.yml index 9872446d08..5aa0fda307 100644 --- a/gr-dtv/grc/dtv_dvbs2_physical_cc.block.yml +++ b/gr-dtv/grc/dtv_dvbs2_physical_cc.block.yml @@ -8,9 +8,9 @@ parameters: options: [FECFRAME_NORMAL, FECFRAME_MEDIUM, FECFRAME_SHORT] option_labels: [Normal, Medium, Short] option_attributes: - hide_medium: [all, '', all] - hide_normal: ['', all, all] - hide_short: [all, all, ''] + hide_medium: [all, none, all] + hide_normal: [none, all, all] + hide_short: [all, all, none] val: [dtv.FECFRAME_NORMAL, dtv.FECFRAME_MEDIUM, dtv.FECFRAME_SHORT] - id: rate1 label: Code rate diff --git a/gr-dtv/grc/dtv_dvbt2_framemapper_cc.block.yml b/gr-dtv/grc/dtv_dvbt2_framemapper_cc.block.yml index bb753e4625..7a11df6680 100644 --- a/gr-dtv/grc/dtv_dvbt2_framemapper_cc.block.yml +++ b/gr-dtv/grc/dtv_dvbt2_framemapper_cc.block.yml @@ -123,8 +123,8 @@ parameters: options: [VERSION_111, VERSION_131] option_labels: [1.1.1, 1.3.1] option_attributes: - hide_111: ['', all] - hide_131: [all, ''] + hide_111: [none, all] + hide_131: [all, none] val: [dtv.VERSION_111, dtv.VERSION_131] - id: preamble1 label: Preamble @@ -132,7 +132,7 @@ parameters: options: [PREAMBLE_T2_SISO, PREAMBLE_T2_MISO] option_labels: [T2 SISO, T2 MISO] option_attributes: - hide_base: ['', ''] + hide_base: [none, none] hide_lite: [all, all] val: [dtv.PREAMBLE_T2_SISO, dtv.PREAMBLE_T2_MISO] hide: ${ version.hide_111 } @@ -142,8 +142,8 @@ parameters: options: [PREAMBLE_T2_SISO, PREAMBLE_T2_MISO, PREAMBLE_T2_LITE_SISO, PREAMBLE_T2_LITE_MISO] option_labels: [T2 SISO, T2 MISO, T2-Lite SISO, T2-Lite MISO] option_attributes: - hide_base: ['', '', all, all] - hide_lite: [all, all, '', ''] + hide_base: [none, none, all, all] + hide_lite: [all, all, none, none] val: [dtv.PREAMBLE_T2_SISO, dtv.PREAMBLE_T2_MISO, dtv.PREAMBLE_T2_LITE_SISO, dtv.PREAMBLE_T2_LITE_MISO] hide: ${ version.hide_131 } diff --git a/gr-dtv/grc/dtv_dvbt2_freqinterleaver_cc.block.yml b/gr-dtv/grc/dtv_dvbt2_freqinterleaver_cc.block.yml index e6977374f0..15d7d80f75 100644 --- a/gr-dtv/grc/dtv_dvbt2_freqinterleaver_cc.block.yml +++ b/gr-dtv/grc/dtv_dvbt2_freqinterleaver_cc.block.yml @@ -64,8 +64,8 @@ parameters: options: [VERSION_111, VERSION_131] option_labels: [1.1.1, 1.3.1] option_attributes: - hide_111: ['', all] - hide_131: [all, ''] + hide_111: [none, all] + hide_131: [all, none] val: [dtv.VERSION_111, dtv.VERSION_131] - id: preamble1 label: Preamble diff --git a/gr-dtv/grc/dtv_dvbt2_miso_cc.block.yml b/gr-dtv/grc/dtv_dvbt2_miso_cc.block.yml index e00a0b047e..d26dae4a2d 100644 --- a/gr-dtv/grc/dtv_dvbt2_miso_cc.block.yml +++ b/gr-dtv/grc/dtv_dvbt2_miso_cc.block.yml @@ -64,8 +64,8 @@ parameters: options: [VERSION_111, VERSION_131] option_labels: [1.1.1, 1.3.1] option_attributes: - hide_111: ['', all] - hide_131: [all, ''] + hide_111: [none, all] + hide_131: [all, none] val: [dtv.VERSION_111, dtv.VERSION_131] inputs: diff --git a/gr-dtv/grc/dtv_dvbt2_p1insertion_cc.block.yml b/gr-dtv/grc/dtv_dvbt2_p1insertion_cc.block.yml index 2749f035d0..42ce872421 100644 --- a/gr-dtv/grc/dtv_dvbt2_p1insertion_cc.block.yml +++ b/gr-dtv/grc/dtv_dvbt2_p1insertion_cc.block.yml @@ -48,8 +48,8 @@ parameters: options: [VERSION_111, VERSION_131] option_labels: [1.1.1, 1.3.1] option_attributes: - hide_111: ['', all] - hide_131: [all, ''] + hide_111: [none, all] + hide_131: [all, none] val: [dtv.VERSION_111, dtv.VERSION_131] - id: preamble1 label: Preamble @@ -57,7 +57,7 @@ parameters: options: [PREAMBLE_T2_SISO, PREAMBLE_T2_MISO] option_labels: [T2 SISO, T2 MISO] option_attributes: - hide_base: ['', ''] + hide_base: [none, none] hide_lite: [all, all] val: [dtv.PREAMBLE_T2_SISO, dtv.PREAMBLE_T2_MISO] hide: ${ version.hide_111 } @@ -67,8 +67,8 @@ parameters: options: [PREAMBLE_T2_SISO, PREAMBLE_T2_MISO, PREAMBLE_T2_LITE_SISO, PREAMBLE_T2_LITE_MISO] option_labels: [T2 SISO, T2 MISO, T2-Lite SISO, T2-Lite MISO] option_attributes: - hide_base: ['', '', all, all] - hide_lite: [all, all, '', ''] + hide_base: [none, none, all, all] + hide_lite: [all, all, none, none] val: [dtv.PREAMBLE_T2_SISO, dtv.PREAMBLE_T2_MISO, dtv.PREAMBLE_T2_LITE_SISO, dtv.PREAMBLE_T2_LITE_MISO] hide: ${ version.hide_131 } @@ -78,7 +78,7 @@ parameters: options: [SHOWLEVELS_OFF, SHOWLEVELS_ON] option_labels: ['Off', 'On'] option_attributes: - hide_vclip: [all, ''] + hide_vclip: [all, none] val: [dtv.SHOWLEVELS_OFF, dtv.SHOWLEVELS_ON] - id: vclip label: Vclip diff --git a/gr-dtv/grc/dtv_dvbt2_paprtr_cc.block.yml b/gr-dtv/grc/dtv_dvbt2_paprtr_cc.block.yml index 646291b1af..1ec6670e36 100644 --- a/gr-dtv/grc/dtv_dvbt2_paprtr_cc.block.yml +++ b/gr-dtv/grc/dtv_dvbt2_paprtr_cc.block.yml @@ -50,7 +50,7 @@ parameters: option_labels: ['Off', Active Constellation Extension, Tone Reservation, Both ACE and TR] option_attributes: - hide_vclip: [all, all, '', ''] + hide_vclip: [all, all, none, none] val: [dtv.PAPR_OFF, dtv.PAPR_ACE, dtv.PAPR_TR, dtv.PAPR_BOTH] hide: ${ version.hide_111 } - id: paprmode2 @@ -60,7 +60,7 @@ parameters: option_labels: [P2 Only, Active Constellation Extension, Tone Reservation, Both ACE and TR] option_attributes: - hide_vclip: [all, all, '', ''] + hide_vclip: [all, all, none, none] val: [dtv.PAPR_OFF, dtv.PAPR_ACE, dtv.PAPR_TR, dtv.PAPR_BOTH] hide: ${ version.hide_131 } - id: version @@ -69,8 +69,8 @@ parameters: options: [VERSION_111, VERSION_131] option_labels: [1.1.1, 1.3.1] option_attributes: - hide_111: ['', all] - hide_131: [all, ''] + hide_111: [none, all] + hide_131: [all, none] val: [dtv.VERSION_111, dtv.VERSION_131] - id: vclip label: Vclip diff --git a/gr-dtv/grc/dtv_dvbt2_pilotgenerator_cc.block.yml b/gr-dtv/grc/dtv_dvbt2_pilotgenerator_cc.block.yml index 1e9d7a9b74..021e7f90ae 100644 --- a/gr-dtv/grc/dtv_dvbt2_pilotgenerator_cc.block.yml +++ b/gr-dtv/grc/dtv_dvbt2_pilotgenerator_cc.block.yml @@ -19,9 +19,8 @@ parameters: option_attributes: val: [dtv.FFTSIZE_1K, dtv.FFTSIZE_2K, dtv.FFTSIZE_4K, dtv.FFTSIZE_8K, dtv.FFTSIZE_8K_T2GI, dtv.FFTSIZE_16K, dtv.FFTSIZE_16K_T2GI, dtv.FFTSIZE_32K, dtv.FFTSIZE_32K_T2GI] - vlength: ['1024', '2048', '4096', '8192', '8192', '16384', '16384', '32768', - '32768'] - hide: ${ 'part' if vlen == 1 else 'none' } + vlength: [1024, 2048, 4096, 8192, 8192, 16384, 16384, 32768, + 32768] - id: pilotpattern label: Pilot Pattern dtype: enum @@ -67,8 +66,8 @@ parameters: options: [VERSION_111, VERSION_131] option_labels: [1.1.1, 1.3.1] option_attributes: - hide_111: ['', all] - hide_131: [all, ''] + hide_111: [none, all] + hide_131: [all, none] val: [dtv.VERSION_111, dtv.VERSION_131] - id: preamble1 label: Preamble @@ -76,7 +75,7 @@ parameters: options: [PREAMBLE_T2_SISO, PREAMBLE_T2_MISO] option_labels: [T2 SISO, T2 MISO] option_attributes: - hide_miso: [all, ''] + hide_miso: [all, none] val: [dtv.PREAMBLE_T2_SISO, dtv.PREAMBLE_T2_MISO] hide: ${ version.hide_111 } - id: preamble2 @@ -85,7 +84,7 @@ parameters: options: [PREAMBLE_T2_SISO, PREAMBLE_T2_MISO, PREAMBLE_T2_LITE_SISO, PREAMBLE_T2_LITE_MISO] option_labels: [T2 SISO, T2 MISO, T2-Lite SISO, T2-Lite MISO] option_attributes: - hide_miso: [all, '', all, ''] + hide_miso: [all, none, all, none] val: [dtv.PREAMBLE_T2_SISO, dtv.PREAMBLE_T2_MISO, dtv.PREAMBLE_T2_LITE_SISO, dtv.PREAMBLE_T2_LITE_MISO] hide: ${ version.hide_131 } @@ -104,7 +103,7 @@ parameters: options: [EQUALIZATION_OFF, EQUALIZATION_ON] option_labels: ['Off', 'On'] option_attributes: - hide_bandwidth: [all, ''] + hide_bandwidth: [all, none] val: [dtv.EQUALIZATION_OFF, dtv.EQUALIZATION_ON] - id: bandwidth label: Bandwidth diff --git a/gr-dtv/lib/dvb/dvb_bbscrambler_bb_impl.cc b/gr-dtv/lib/dvb/dvb_bbscrambler_bb_impl.cc index 8e86eb4f64..c9401258b7 100644 --- a/gr-dtv/lib/dvb/dvb_bbscrambler_bb_impl.cc +++ b/gr-dtv/lib/dvb/dvb_bbscrambler_bb_impl.cc @@ -268,6 +268,8 @@ namespace gr { sr |= 0x4000; } } + bb_randomize64 = (uint64_t*)&bb_randomise[0]; + } int @@ -275,12 +277,13 @@ namespace gr { gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { - const unsigned char *in = (const unsigned char *) input_items[0]; - unsigned char *out = (unsigned char *) output_items[0]; + // noutput_items is multiple of kbch and kbch is always divisible by 8 + const uint64_t *in = (const uint64_t *) input_items[0]; + uint64_t *out = (uint64_t *) output_items[0]; for (int i = 0; i < noutput_items; i += kbch) { - for (int j = 0; j < (int)kbch; ++j) { - out[i + j] = in[i + j] ^ bb_randomise[j]; + for (int j = 0; j < kbch/8; ++j) { + *out++ = *in++ ^ bb_randomize64[j]; } } diff --git a/gr-dtv/lib/dvb/dvb_bbscrambler_bb_impl.h b/gr-dtv/lib/dvb/dvb_bbscrambler_bb_impl.h index d717731502..062e1b68a2 100644 --- a/gr-dtv/lib/dvb/dvb_bbscrambler_bb_impl.h +++ b/gr-dtv/lib/dvb/dvb_bbscrambler_bb_impl.h @@ -30,8 +30,9 @@ namespace gr { class dvb_bbscrambler_bb_impl : public dvb_bbscrambler_bb { private: - unsigned int kbch; + int kbch; unsigned char bb_randomise[FRAME_SIZE_NORMAL]; + uint64_t* bb_randomize64; void init_bb_randomiser(void); public: diff --git a/gr-dtv/lib/dvb/dvb_bch_bb_impl.cc b/gr-dtv/lib/dvb/dvb_bch_bb_impl.cc index 8d89f9b04a..6f184c8e05 100644 --- a/gr-dtv/lib/dvb/dvb_bch_bb_impl.cc +++ b/gr-dtv/lib/dvb/dvb_bch_bb_impl.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2015,2016 Free Software Foundation, Inc. + * Copyright 2015,2016,2018 Free Software Foundation, Inc. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -371,6 +371,24 @@ namespace gr { } } + switch (bch_code) { + case BCH_CODE_N12: + num_parity_bits = 192; + break; + case BCH_CODE_N10: + num_parity_bits = 160; + break; + case BCH_CODE_N8: + num_parity_bits = 128; + break; + case BCH_CODE_M12: + num_parity_bits = 180; + break; + case BCH_CODE_S12: + num_parity_bits = 168; + break; + } + bch_poly_build_tables(); set_output_multiple(nbch); } @@ -415,82 +433,28 @@ namespace gr { return max + 1; } - /* - * Pack the polynomial into a 32 bit array - */ + //precalculate the crc from: http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html - cf. CRC-32 Lookup void - dvb_bch_bb_impl::poly_pack(const int *pin, unsigned int* pout, int len) + dvb_bch_bb_impl::calculate_crc_table(void) { - int lw = len / 32; - int ptr = 0; - unsigned int temp; - if (len % 32) { - lw++; - } - - for (int i = 0; i < lw; i++) { - temp = 0x80000000; - pout[i] = 0; - for (int j = 0; j < 32; j++) { - if (pin[ptr++]) { - pout[i] |= temp; + for (int divident = 0; divident < 256; divident++) { /* iterate over all possible input byte values 0 - 255 */ + std::bitset<MAX_BCH_PARITY_BITS> curByte(divident); + curByte <<= num_parity_bits - 8; + + for (unsigned char bit = 0; bit < 8; bit++) { + if ((curByte[num_parity_bits - 1]) != 0) { + curByte <<= 1; + curByte ^= polynome; + } + else { + curByte <<= 1; } - temp >>= 1; } + crc_table[divident] = curByte; } } void - dvb_bch_bb_impl::poly_reverse(int *pin, int *pout, int len) - { - int c; - c = len - 1; - - for (int i = 0; i < len; i++) { - pout[c--] = pin[i]; - } - } - - /* - *Shift a 128 bit register - */ - inline void - dvb_bch_bb_impl::reg_4_shift(unsigned int *sr) - { - sr[3] = (sr[3] >> 1) | (sr[2] << 31); - sr[2] = (sr[2] >> 1) | (sr[1] << 31); - sr[1] = (sr[1] >> 1) | (sr[0] << 31); - sr[0] = (sr[0] >> 1); - } - - /* - * Shift 160 bits - */ - inline void - dvb_bch_bb_impl::reg_5_shift(unsigned int *sr) - { - sr[4] = (sr[4] >> 1) | (sr[3] << 31); - sr[3] = (sr[3] >> 1) | (sr[2] << 31); - sr[2] = (sr[2] >> 1) | (sr[1] << 31); - sr[1] = (sr[1] >> 1) | (sr[0] << 31); - sr[0] = (sr[0] >> 1); - } - - /* - * Shift 192 bits - */ - inline void - dvb_bch_bb_impl::reg_6_shift(unsigned int *sr) - { - sr[5] = (sr[5] >> 1) | (sr[4] << 31); - sr[4] = (sr[4] >> 1) | (sr[3] << 31); - sr[3] = (sr[3] >> 1) | (sr[2] << 31); - sr[2] = (sr[2] >> 1) | (sr[1] << 31); - sr[1] = (sr[1] >> 1) | (sr[0] << 31); - sr[0] = (sr[0] >> 1); - } - - void dvb_bch_bb_impl::bch_poly_build_tables(void) { // Normal polynomials @@ -538,48 +502,73 @@ namespace gr { int len; int polyout[2][200]; - len = poly_mult(polyn01, 17, polyn02, 17, polyout[0]); - len = poly_mult(polyn03, 17, polyout[0], len, polyout[1]); - len = poly_mult(polyn04, 17, polyout[1], len, polyout[0]); - len = poly_mult(polyn05, 17, polyout[0], len, polyout[1]); - len = poly_mult(polyn06, 17, polyout[1], len, polyout[0]); - len = poly_mult(polyn07, 17, polyout[0], len, polyout[1]); - len = poly_mult(polyn08, 17, polyout[1], len, polyout[0]); - poly_pack(polyout[0], m_poly_n_8, 128); - - len = poly_mult(polyn09, 17, polyout[0], len, polyout[1]); - len = poly_mult(polyn10, 17, polyout[1], len, polyout[0]); - poly_pack(polyout[0], m_poly_n_10, 160); - - len = poly_mult(polyn11, 17, polyout[0], len, polyout[1]); - len = poly_mult(polyn12, 17, polyout[1], len, polyout[0]); - poly_pack(polyout[0], m_poly_n_12, 192); - - len = poly_mult(polys01, 15, polys02, 15, polyout[0]); - len = poly_mult(polys03, 15, polyout[0], len, polyout[1]); - len = poly_mult(polys04, 15, polyout[1], len, polyout[0]); - len = poly_mult(polys05, 15, polyout[0], len, polyout[1]); - len = poly_mult(polys06, 15, polyout[1], len, polyout[0]); - len = poly_mult(polys07, 15, polyout[0], len, polyout[1]); - len = poly_mult(polys08, 15, polyout[1], len, polyout[0]); - len = poly_mult(polys09, 15, polyout[0], len, polyout[1]); - len = poly_mult(polys10, 15, polyout[1], len, polyout[0]); - len = poly_mult(polys11, 15, polyout[0], len, polyout[1]); - len = poly_mult(polys12, 15, polyout[1], len, polyout[0]); - poly_pack(polyout[0], m_poly_s_12, 168); - - len = poly_mult(polym01, 16, polym02, 16, polyout[0]); - len = poly_mult(polym03, 16, polyout[0], len, polyout[1]); - len = poly_mult(polym04, 16, polyout[1], len, polyout[0]); - len = poly_mult(polym05, 16, polyout[0], len, polyout[1]); - len = poly_mult(polym06, 16, polyout[1], len, polyout[0]); - len = poly_mult(polym07, 16, polyout[0], len, polyout[1]); - len = poly_mult(polym08, 16, polyout[1], len, polyout[0]); - len = poly_mult(polym09, 16, polyout[0], len, polyout[1]); - len = poly_mult(polym10, 16, polyout[1], len, polyout[0]); - len = poly_mult(polym11, 16, polyout[0], len, polyout[1]); - len = poly_mult(polym12, 16, polyout[1], len, polyout[0]); - poly_pack(polyout[0], m_poly_m_12, 180); +#define COPY_BCH_POLYNOME \ +for (unsigned int i = 0; i < num_parity_bits; i ++) {\ + polynome[i] = polyout[0][i];\ +} + + switch (bch_code) { + case BCH_CODE_N12: + case BCH_CODE_N10: + case BCH_CODE_N8: + + len = poly_mult(polyn01, 17, polyn02, 17, polyout[0]); + len = poly_mult(polyn03, 17, polyout[0], len, polyout[1]); + len = poly_mult(polyn04, 17, polyout[1], len, polyout[0]); + len = poly_mult(polyn05, 17, polyout[0], len, polyout[1]); + len = poly_mult(polyn06, 17, polyout[1], len, polyout[0]); + len = poly_mult(polyn07, 17, polyout[0], len, polyout[1]); + len = poly_mult(polyn08, 17, polyout[1], len, polyout[0]); + if (bch_code == BCH_CODE_N8) { + COPY_BCH_POLYNOME + } + + len = poly_mult(polyn09, 17, polyout[0], len, polyout[1]); + len = poly_mult(polyn10, 17, polyout[1], len, polyout[0]); + if (bch_code == BCH_CODE_N10) { + COPY_BCH_POLYNOME + } + + len = poly_mult(polyn11, 17, polyout[0], len, polyout[1]); + len = poly_mult(polyn12, 17, polyout[1], len, polyout[0]); + if (bch_code == BCH_CODE_N12) { + COPY_BCH_POLYNOME + } + break; + + case BCH_CODE_S12: + len = poly_mult(polys01, 15, polys02, 15, polyout[0]); + len = poly_mult(polys03, 15, polyout[0], len, polyout[1]); + len = poly_mult(polys04, 15, polyout[1], len, polyout[0]); + len = poly_mult(polys05, 15, polyout[0], len, polyout[1]); + len = poly_mult(polys06, 15, polyout[1], len, polyout[0]); + len = poly_mult(polys07, 15, polyout[0], len, polyout[1]); + len = poly_mult(polys08, 15, polyout[1], len, polyout[0]); + len = poly_mult(polys09, 15, polyout[0], len, polyout[1]); + len = poly_mult(polys10, 15, polyout[1], len, polyout[0]); + len = poly_mult(polys11, 15, polyout[0], len, polyout[1]); + len = poly_mult(polys12, 15, polyout[1], len, polyout[0]); + + COPY_BCH_POLYNOME + break; + + case BCH_CODE_M12: + len = poly_mult(polym01, 16, polym02, 16, polyout[0]); + len = poly_mult(polym03, 16, polyout[0], len, polyout[1]); + len = poly_mult(polym04, 16, polyout[1], len, polyout[0]); + len = poly_mult(polym05, 16, polyout[0], len, polyout[1]); + len = poly_mult(polym06, 16, polyout[1], len, polyout[0]); + len = poly_mult(polym07, 16, polyout[0], len, polyout[1]); + len = poly_mult(polym08, 16, polyout[1], len, polyout[0]); + len = poly_mult(polym09, 16, polyout[0], len, polyout[1]); + len = poly_mult(polym10, 16, polyout[1], len, polyout[0]); + len = poly_mult(polym11, 16, polyout[0], len, polyout[1]); + len = poly_mult(polym12, 16, polyout[1], len, polyout[0]); + + COPY_BCH_POLYNOME + break; + } + calculate_crc_table(); } int @@ -590,143 +579,41 @@ namespace gr { { const unsigned char *in = (const unsigned char *) input_items[0]; unsigned char *out = (unsigned char *) output_items[0]; - unsigned char b, temp; - unsigned int shift[6]; + unsigned char b, temp, msb; + + // We can use a 192 bits long bitset, all higher bits not used by the bch will just be ignored + std::bitset<MAX_BCH_PARITY_BITS> parity_bits; int consumed = 0; - switch (bch_code) { - case BCH_CODE_N12: - for (int i = 0; i < noutput_items; i += nbch) { - //Zero the shift register - memset(shift, 0, sizeof(unsigned int) * 6); - // MSB of the codeword first - for (int j = 0; j < (int)kbch; j++) { - temp = *in++; - *out++ = temp; - consumed++; - b = (temp ^ (shift[5] & 1)); - reg_6_shift(shift); - if (b) { - shift[0] ^= m_poly_n_12[0]; - shift[1] ^= m_poly_n_12[1]; - shift[2] ^= m_poly_n_12[2]; - shift[3] ^= m_poly_n_12[3]; - shift[4] ^= m_poly_n_12[4]; - shift[5] ^= m_poly_n_12[5]; - } - } - // Now add the parity bits to the output - for (int n = 0; n < 192; n++) { - *out++ = (shift[5] & 1); - reg_6_shift(shift); - } - } - break; - case BCH_CODE_N10: - for (int i = 0; i < noutput_items; i += nbch) { - //Zero the shift register - memset(shift, 0, sizeof(unsigned int) * 5); - // MSB of the codeword first - for (int j = 0; j < (int)kbch; j++) { - temp = *in++; - *out++ = temp; - consumed++; - b = (temp ^ (shift[4] & 1)); - reg_5_shift(shift); - if (b) { - shift[0] ^= m_poly_n_10[0]; - shift[1] ^= m_poly_n_10[1]; - shift[2] ^= m_poly_n_10[2]; - shift[3] ^= m_poly_n_10[3]; - shift[4] ^= m_poly_n_10[4]; - } - } - // Now add the parity bits to the output - for( int n = 0; n < 160; n++ ) { - *out++ = (shift[4] & 1); - reg_5_shift(shift); - } - } - break; - case BCH_CODE_N8: - for (int i = 0; i < noutput_items; i += nbch) { - //Zero the shift register - memset(shift, 0, sizeof(unsigned int) * 4); - // MSB of the codeword first - for (int j = 0; j < (int)kbch; j++) { - temp = *in++; - *out++ = temp; - consumed++; - b = temp ^ (shift[3] & 1); - reg_4_shift(shift); - if (b) { - shift[0] ^= m_poly_n_8[0]; - shift[1] ^= m_poly_n_8[1]; - shift[2] ^= m_poly_n_8[2]; - shift[3] ^= m_poly_n_8[3]; - } - } - // Now add the parity bits to the output - for (int n = 0; n < 128; n++) { - *out++ = shift[3] & 1; - reg_4_shift(shift); - } - } - break; - case BCH_CODE_S12: - for (int i = 0; i < noutput_items; i += nbch) { - //Zero the shift register - memset(shift, 0, sizeof(unsigned int) * 6); - // MSB of the codeword first - for (int j = 0; j < (int)kbch; j++) { - temp = *in++; - *out++ = temp; - consumed++; - b = (temp ^ ((shift[5] & 0x01000000) ? 1 : 0)); - reg_6_shift(shift); - if (b) { - shift[0] ^= m_poly_s_12[0]; - shift[1] ^= m_poly_s_12[1]; - shift[2] ^= m_poly_s_12[2]; - shift[3] ^= m_poly_s_12[3]; - shift[4] ^= m_poly_s_12[4]; - shift[5] ^= m_poly_s_12[5]; - } - } - // Now add the parity bits to the output - for (int n = 0; n < 168; n++) { - *out++ = (shift[5] & 0x01000000) ? 1 : 0; - reg_6_shift(shift); - } + for (int i = 0; i < noutput_items; i += nbch) { + for (int j = 0; j < (int)kbch / 8; j++) { + b = 0; + + // calculate the crc using the lookup table, cf. http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html + for (int e = 0; e < 8; e++) { + temp = *in++; + *out++ = temp; + consumed++; + + b |= temp << (7 - e); } - break; - case BCH_CODE_M12: - for (int i = 0; i < noutput_items; i += nbch) { - //Zero the shift register - memset(shift, 0, sizeof(unsigned int) * 6); - // MSB of the codeword first - for (int j = 0; j < (int)kbch; j++) { - temp = *in++; - *out++ = temp; - consumed++; - b = (temp ^ ((shift[5] & 0x00001000) ? 1 : 0)); - reg_6_shift(shift); - if (b) { - shift[0] ^= m_poly_m_12[0]; - shift[1] ^= m_poly_m_12[1]; - shift[2] ^= m_poly_m_12[2]; - shift[3] ^= m_poly_m_12[3]; - shift[4] ^= m_poly_m_12[4]; - shift[5] ^= m_poly_m_12[5]; - } - } - // Now add the parity bits to the output - for (int n = 0; n < 180; n++) { - *out++ = (shift[5] & 0x00001000) ? 1 : 0; - reg_6_shift(shift); - } + + msb = 0; + for (int n = 1; n <= 8; n++) { + temp = parity_bits[num_parity_bits - n]; + msb |= temp << (8 - n); } - break; + /* XOR-in next input byte into MSB of crc and get this MSB, that's our new intermediate divident */ + unsigned char pos = (msb ^ b); + /* Shift out the MSB used for division per lookuptable and XOR with the remainder */ + parity_bits = (parity_bits << 8) ^ crc_table[pos]; + } + + // Now add the parity bits to the output + for (unsigned int n = 0; n < num_parity_bits; n++) { + *out++ = (char) parity_bits[num_parity_bits - 1]; + parity_bits <<= 1; + } } // Tell runtime system how many input items we consumed on diff --git a/gr-dtv/lib/dvb/dvb_bch_bb_impl.h b/gr-dtv/lib/dvb/dvb_bch_bb_impl.h index 56b4772b26..d715161431 100644 --- a/gr-dtv/lib/dvb/dvb_bch_bb_impl.h +++ b/gr-dtv/lib/dvb/dvb_bch_bb_impl.h @@ -23,6 +23,9 @@ #include <gnuradio/dtv/dvb_bch_bb.h> #include "dvb_defines.h" +#include <bitset> + +#define MAX_BCH_PARITY_BITS 192 namespace gr { namespace dtv { @@ -33,17 +36,13 @@ namespace gr { unsigned int kbch; unsigned int nbch; unsigned int bch_code; - unsigned int m_poly_n_8[4]; - unsigned int m_poly_n_10[5]; - unsigned int m_poly_n_12[6]; - unsigned int m_poly_s_12[6]; - unsigned int m_poly_m_12[6]; + + std::bitset<MAX_BCH_PARITY_BITS> crc_table[256]; + unsigned int num_parity_bits; + std::bitset<MAX_BCH_PARITY_BITS> polynome; + + void calculate_crc_table(); int poly_mult(const int*, int, const int*, int, int*); - void poly_pack(const int*, unsigned int*, int); - void poly_reverse(int*, int*, int); - inline void reg_4_shift(unsigned int*); - inline void reg_5_shift(unsigned int*); - inline void reg_6_shift(unsigned int*); void bch_poly_build_tables(void); public: diff --git a/gr-dtv/lib/dvb/dvb_ldpc_bb_impl.cc b/gr-dtv/lib/dvb/dvb_ldpc_bb_impl.cc index 84328e1200..e907bbb499 100644 --- a/gr-dtv/lib/dvb/dvb_ldpc_bb_impl.cc +++ b/gr-dtv/lib/dvb/dvb_ldpc_bb_impl.cc @@ -364,6 +364,8 @@ namespace gr { */ dvb_ldpc_bb_impl::~dvb_ldpc_bb_impl() { + delete[] ldpc_lut[0]; + delete[] ldpc_lut; } void @@ -373,29 +375,48 @@ namespace gr { } #define LDPC_BF(TABLE_NAME, ROWS) \ +for (int row = 0; row < ROWS; row++) { /* count the entries in the table */ \ + max_lut_arraysize += TABLE_NAME[row][0]; \ +} \ +max_lut_arraysize *= 360; /* 360 bits per table entry */ \ +max_lut_arraysize /= pbits; /* spread over all parity bits */ \ +max_lut_arraysize += 2; /* 1 for the size at the start of the array, one as buffer */ \ +\ +/* Allocate a 2D Array with pbits * max_lut_arraysize + * while preserving two-subscript access + * see https://stackoverflow.com/questions/29375797/copy-2d-array-using-memcpy/29375830#29375830 + */ \ +ldpc_lut = new int*[pbits]; \ +ldpc_lut[0] = new int[pbits * max_lut_arraysize]; \ +ldpc_lut[0][0] = 1; \ +for (int i = 1; i < pbits; i++) { \ + ldpc_lut[i] = ldpc_lut[i-1] + max_lut_arraysize; \ + ldpc_lut[i][0] = 1; \ +} \ for (int row = 0; row < ROWS; row++) { \ for (int n = 0; n < 360; n++) { \ for (int col = 1; col <= TABLE_NAME[row][0]; col++) { \ - ldpc_encode.p[index] = (TABLE_NAME[row][col] + (n * q)) % pbits; \ - ldpc_encode.d[index] = im; \ - index++; \ + int current_pbit = (TABLE_NAME[row][col] + (n * q)) % pbits; \ + ldpc_lut[current_pbit][ldpc_lut[current_pbit][0]] = im; \ + ldpc_lut[current_pbit][0]++; \ } \ im++; \ } \ -} +} + /* + * fill the lookup table, for each paritybit it contains + * {number of infobits, infobit1, infobit2, ... ] + * maximum number of infobits is calculated using the entries + * in the ldpc tables + */ void dvb_ldpc_bb_impl::ldpc_lookup_generate(void) { - int im; - int index; - int pbits; - int q; - index = 0; - im = 0; - - pbits = (frame_size_real + Xp) - nbch; //number of parity bits - q = q_val; + int im = 0; + int pbits = (frame_size_real + Xp) - nbch; //number of parity bits + int q = q_val; + int max_lut_arraysize = 0; if (frame_size_type == FECFRAME_NORMAL) { if (code_rate == C1_4) { @@ -593,7 +614,6 @@ for (int row = 0; row < ROWS; row++) { \ LDPC_BF(ldpc_tab_1_3M, 30); } } - ldpc_encode.table_length = index; } int @@ -628,14 +648,20 @@ for (int row = 0; row < ROWS; row++) { \ } // First zero all the parity bits memset(p, 0, sizeof(unsigned char) * plen); - for (int j = 0; j < (int)nbch; j++) { - out[i + j] = in[consumed]; - consumed++; - } + + // copy the information bits + memcpy(&out[i], &in[consumed], sizeof(unsigned char)*nbch); + consumed += nbch; + // now do the parity checking - for (int j = 0; j < ldpc_encode.table_length; j++) { - p[ldpc_encode.p[j]] ^= d[ldpc_encode.d[j]]; + for (int i_p = 0; i_p < plen; i_p++) { + unsigned char pbit = 0; + for (int i_d = 1; i_d < ldpc_lut[i_p][0]; i_d++) { + pbit ^= d[ldpc_lut[i_p][i_d]]; + } + p[i_p] = pbit; } + if (P != 0) { puncture = 0; for (int j = 0; j < plen; j += P) { diff --git a/gr-dtv/lib/dvb/dvb_ldpc_bb_impl.h b/gr-dtv/lib/dvb/dvb_ldpc_bb_impl.h index c8f0fab698..5506411956 100644 --- a/gr-dtv/lib/dvb/dvb_ldpc_bb_impl.h +++ b/gr-dtv/lib/dvb/dvb_ldpc_bb_impl.h @@ -23,12 +23,8 @@ #include <gnuradio/dtv/dvb_ldpc_bb.h> #include "dvb_defines.h" +#include <boost/smart_ptr.hpp> -typedef struct{ - int table_length; - int d[LDPC_ENCODE_TABLE_LENGTH]; - int p[LDPC_ENCODE_TABLE_LENGTH]; -}ldpc_encode_table; namespace gr { namespace dtv { @@ -50,7 +46,8 @@ namespace gr { unsigned char puncturing_buffer[FRAME_SIZE_NORMAL]; unsigned char shortening_buffer[FRAME_SIZE_NORMAL]; void ldpc_lookup_generate(void); - ldpc_encode_table ldpc_encode; + + int** ldpc_lut; const static int ldpc_tab_1_4N[45][13]; const static int ldpc_tab_1_3N[60][13]; diff --git a/gr-dtv/lib/dvbt2/dvbt2_interleaver_bb_impl.cc b/gr-dtv/lib/dvbt2/dvbt2_interleaver_bb_impl.cc index 3e3dc430b6..a0d5fc447b 100644 --- a/gr-dtv/lib/dvbt2/dvbt2_interleaver_bb_impl.cc +++ b/gr-dtv/lib/dvbt2/dvbt2_interleaver_bb_impl.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2015,2016 Free Software Foundation, Inc. + * Copyright 2015,2016,2018 Free Software Foundation, Inc. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -146,6 +146,210 @@ namespace gr { packed_items = frame_size / mod; break; } + generate_lookup(); + } + + inline void + dvbt2_interleaver_bb_impl::interleave_parity_bits(int *tempu, const int *&in) + { + for (int k = 0; k < nbch; k++) { + tempu[k] = *in++; + } + for (int t = 0; t < q_val; t++) { + for (int s = 0; s < 360; s++) { + tempu[nbch + (360 * t) + s] = in[(q_val * s) + t]; + } + } + in = in + (q_val * 360); + } + + inline void + dvbt2_interleaver_bb_impl::twist_interleave_columns(int* tempv, int* tempu, int rows, const int *twist) + { + int index = 0, offset; + for (int col = 0; col < (mod * 2); col++) { + offset = twist[col]; + for (int row = 0; row < rows; row++) { + tempv[offset + (rows * col)] = tempu[index++]; + offset++; + if (offset == rows) { + offset = 0; + } + } + } + } + + void + dvbt2_interleaver_bb_impl::generate_lookup() + { + int rows, index = 0; + int tempv[FRAME_SIZE_NORMAL]; + int tempu[FRAME_SIZE_NORMAL]; + const int *twist; + const int *c1, *c2, *c3, *c4, *c5, *c6, *c7, *c8; + const int *c9, *c10, *c11, *c12, *c13, *c14, *c15, *c16; + + for(int i = 0; i < FRAME_SIZE_NORMAL; i++) { + lookup_table[i] = i; + } + + const int *in = &lookup_table[0]; + + switch (signal_constellation) { + //ignore QPSK, not worth it, as there is no column interleaving + case MOD_16QAM: + rows = frame_size / (mod * 2); + + if (frame_size == FRAME_SIZE_NORMAL) { + twist = &twist16n[0]; + } + else { + twist = &twist16s[0]; + } + + interleave_parity_bits(tempu, in); + + c1 = &tempv[0]; + c2 = &tempv[rows]; + c3 = &tempv[rows * 2]; + c4 = &tempv[rows * 3]; + c5 = &tempv[rows * 4]; + c6 = &tempv[rows * 5]; + c7 = &tempv[rows * 6]; + c8 = &tempv[rows * 7]; + + twist_interleave_columns(tempv, tempu, rows, twist); + + for (int j = 0; j < rows; j++) { + tempu[index++] = c1[j]; + tempu[index++] = c2[j]; + tempu[index++] = c3[j]; + tempu[index++] = c4[j]; + tempu[index++] = c5[j]; + tempu[index++] = c6[j]; + tempu[index++] = c7[j]; + tempu[index++] = c8[j]; + } + break; + + case MOD_64QAM: + rows = frame_size / (mod * 2); + + if (frame_size == FRAME_SIZE_NORMAL) { + twist = twist64n; + } + else { + twist = twist64s; + } + + interleave_parity_bits(tempu, in); + + c1 = &tempv[0]; + c2 = &tempv[rows]; + c3 = &tempv[rows * 2]; + c4 = &tempv[rows * 3]; + c5 = &tempv[rows * 4]; + c6 = &tempv[rows * 5]; + c7 = &tempv[rows * 6]; + c8 = &tempv[rows * 7]; + c9 = &tempv[rows * 8]; + c10 = &tempv[rows * 9]; + c11 = &tempv[rows * 10]; + c12 = &tempv[rows * 11]; + + twist_interleave_columns(tempv, tempu, rows, twist); + + for (int j = 0; j < rows; j++) { + tempu[index++] = c1[j]; + tempu[index++] = c2[j]; + tempu[index++] = c3[j]; + tempu[index++] = c4[j]; + tempu[index++] = c5[j]; + tempu[index++] = c6[j]; + tempu[index++] = c7[j]; + tempu[index++] = c8[j]; + tempu[index++] = c9[j]; + tempu[index++] = c10[j]; + tempu[index++] = c11[j]; + tempu[index++] = c12[j]; + } + break; + + case MOD_256QAM: + if (frame_size == FRAME_SIZE_NORMAL) { + rows = frame_size / (mod * 2); + + interleave_parity_bits(tempu, in); + + c1 = &tempv[0]; + c2 = &tempv[rows]; + c3 = &tempv[rows * 2]; + c4 = &tempv[rows * 3]; + c5 = &tempv[rows * 4]; + c6 = &tempv[rows * 5]; + c7 = &tempv[rows * 6]; + c8 = &tempv[rows * 7]; + c9 = &tempv[rows * 8]; + c10 = &tempv[rows * 9]; + c11 = &tempv[rows * 10]; + c12 = &tempv[rows * 11]; + c13 = &tempv[rows * 12]; + c14 = &tempv[rows * 13]; + c15 = &tempv[rows * 14]; + c16 = &tempv[rows * 15]; + + twist_interleave_columns(tempv, tempu, rows, twist256n); + + for (int j = 0; j < rows; j++) { + tempu[index++] = c1[j]; + tempu[index++] = c2[j]; + tempu[index++] = c3[j]; + tempu[index++] = c4[j]; + tempu[index++] = c5[j]; + tempu[index++] = c6[j]; + tempu[index++] = c7[j]; + tempu[index++] = c8[j]; + tempu[index++] = c9[j]; + tempu[index++] = c10[j]; + tempu[index++] = c11[j]; + tempu[index++] = c12[j]; + tempu[index++] = c13[j]; + tempu[index++] = c14[j]; + tempu[index++] = c15[j]; + tempu[index++] = c16[j]; + } + } + else { //frame_size == FRAME_SIZE_SHORT + rows = frame_size / mod; + + interleave_parity_bits(tempu, in); + + c1 = &tempv[0]; + c2 = &tempv[rows]; + c3 = &tempv[rows * 2]; + c4 = &tempv[rows * 3]; + c5 = &tempv[rows * 4]; + c6 = &tempv[rows * 5]; + c7 = &tempv[rows * 6]; + c8 = &tempv[rows * 7]; + + twist_interleave_columns(tempv, tempu, rows, twist256s); + + for (int j = 0; j < rows; j++) { + tempu[index++] = c1[j]; + tempu[index++] = c2[j]; + tempu[index++] = c3[j]; + tempu[index++] = c4[j]; + tempu[index++] = c5[j]; + tempu[index++] = c6[j]; + tempu[index++] = c7[j]; + tempu[index++] = c8[j]; + } + } + } + + //tempu now has the input indices interleaved correctly, so save it + memcpy(lookup_table, tempu, frame_size * sizeof(int)); } /* @@ -173,7 +377,6 @@ namespace gr { int produced = 0; int rows, offset, index; unsigned int pack; - const int *twist; const int *mux; switch (signal_constellation) { @@ -205,13 +408,8 @@ namespace gr { } } break; + case MOD_16QAM: - if (frame_size == FRAME_SIZE_NORMAL) { - twist = &twist16n[0]; - } - else { - twist = &twist16s[0]; - } if (code_rate == C3_5 && frame_size == FRAME_SIZE_NORMAL) { mux = &mux16_35[0]; } @@ -225,67 +423,22 @@ namespace gr { mux = &mux16[0]; } for (int i = 0; i < noutput_items; i += packed_items) { - rows = frame_size / (mod * 2); - const unsigned char *c1, *c2, *c3, *c4, *c5, *c6, *c7, *c8; - c1 = &tempv[0]; - c2 = &tempv[rows]; - c3 = &tempv[rows * 2]; - c4 = &tempv[rows * 3]; - c5 = &tempv[rows * 4]; - c6 = &tempv[rows * 5]; - c7 = &tempv[rows * 6]; - c8 = &tempv[rows * 7]; - for (int k = 0; k < nbch; k++) { - tempu[k] = *in++; - } - for (int t = 0; t < q_val; t++) { - for (int s = 0; s < 360; s++) { - tempu[nbch + (360 * t) + s] = in[(q_val * s) + t]; - } - } - in = in + (q_val * 360); - index = 0; - for (int col = 0; col < (mod * 2); col++) { - offset = twist[col]; - for (int row = 0; row < rows; row++) { - tempv[offset + (rows * col)] = tempu[index++]; - offset++; - if (offset == rows) { - offset = 0; - } - } - } - index = 0; - for (int j = 0; j < rows; j++) { - tempu[index++] = c1[j]; - tempu[index++] = c2[j]; - tempu[index++] = c3[j]; - tempu[index++] = c4[j]; - tempu[index++] = c5[j]; - tempu[index++] = c6[j]; - tempu[index++] = c7[j]; - tempu[index++] = c8[j]; - } index = 0; for (int d = 0; d < frame_size / (mod * 2); d++) { pack = 0; for (int e = 0; e < (mod * 2); e++) { offset = mux[e]; - pack |= tempu[index++] << (((mod * 2) - 1) - offset); + pack |= in[lookup_table[index++]] << (((mod * 2) - 1) - offset); } out[produced++] = pack >> 4; out[produced++] = pack & 0xf; - consumed += (mod * 2); } + consumed += frame_size; + in += frame_size; } break; + case MOD_64QAM: - if (frame_size == FRAME_SIZE_NORMAL) { - twist = &twist64n[0]; - } - else { - twist = &twist64s[0]; - } if (code_rate == C3_5 && frame_size == FRAME_SIZE_NORMAL) { mux = &mux64_35[0]; } @@ -299,68 +452,21 @@ namespace gr { mux = &mux64[0]; } for (int i = 0; i < noutput_items; i += packed_items) { - rows = frame_size / (mod * 2); - const unsigned char *c1, *c2, *c3, *c4, *c5, *c6, *c7, *c8, *c9, *c10, *c11, *c12; - c1 = &tempv[0]; - c2 = &tempv[rows]; - c3 = &tempv[rows * 2]; - c4 = &tempv[rows * 3]; - c5 = &tempv[rows * 4]; - c6 = &tempv[rows * 5]; - c7 = &tempv[rows * 6]; - c8 = &tempv[rows * 7]; - c9 = &tempv[rows * 8]; - c10 = &tempv[rows * 9]; - c11 = &tempv[rows * 10]; - c12 = &tempv[rows * 11]; - for (int k = 0; k < nbch; k++) { - tempu[k] = *in++; - } - for (int t = 0; t < q_val; t++) { - for (int s = 0; s < 360; s++) { - tempu[nbch + (360 * t) + s] = in[(q_val * s) + t]; - } - } - in = in + (q_val * 360); - index = 0; - for (int col = 0; col < (mod * 2); col++) { - offset = twist[col]; - for (int row = 0; row < rows; row++) { - tempv[offset + (rows * col)] = tempu[index++]; - offset++; - if (offset == rows) { - offset = 0; - } - } - } - index = 0; - for (int j = 0; j < rows; j++) { - tempu[index++] = c1[j]; - tempu[index++] = c2[j]; - tempu[index++] = c3[j]; - tempu[index++] = c4[j]; - tempu[index++] = c5[j]; - tempu[index++] = c6[j]; - tempu[index++] = c7[j]; - tempu[index++] = c8[j]; - tempu[index++] = c9[j]; - tempu[index++] = c10[j]; - tempu[index++] = c11[j]; - tempu[index++] = c12[j]; - } index = 0; for (int d = 0; d < frame_size / (mod * 2); d++) { pack = 0; for (int e = 0; e < (mod * 2); e++) { offset = mux[e]; - pack |= tempu[index++] << (((mod * 2) - 1) - offset); + pack |= in[lookup_table[index++]] << (((mod * 2) - 1) - offset); } out[produced++] = pack >> 6; out[produced++] = pack & 0x3f; - consumed += (mod * 2); } + consumed += frame_size; + in += frame_size; } break; + case MOD_256QAM: if (frame_size == FRAME_SIZE_NORMAL) { if (code_rate == C3_5) { @@ -373,78 +479,22 @@ namespace gr { mux = &mux256[0]; } for (int i = 0; i < noutput_items; i += packed_items) { - rows = frame_size / (mod * 2); - const unsigned char *c1, *c2, *c3, *c4, *c5, *c6, *c7, *c8; - const unsigned char *c9, *c10, *c11, *c12, *c13, *c14, *c15, *c16; - c1 = &tempv[0]; - c2 = &tempv[rows]; - c3 = &tempv[rows * 2]; - c4 = &tempv[rows * 3]; - c5 = &tempv[rows * 4]; - c6 = &tempv[rows * 5]; - c7 = &tempv[rows * 6]; - c8 = &tempv[rows * 7]; - c9 = &tempv[rows * 8]; - c10 = &tempv[rows * 9]; - c11 = &tempv[rows * 10]; - c12 = &tempv[rows * 11]; - c13 = &tempv[rows * 12]; - c14 = &tempv[rows * 13]; - c15 = &tempv[rows * 14]; - c16 = &tempv[rows * 15]; - for (int k = 0; k < nbch; k++) { - tempu[k] = *in++; - } - for (int t = 0; t < q_val; t++) { - for (int s = 0; s < 360; s++) { - tempu[nbch + (360 * t) + s] = in[(q_val * s) + t]; - } - } - in = in + (q_val * 360); - index = 0; - for (int col = 0; col < (mod * 2); col++) { - offset = twist256n[col]; - for (int row = 0; row < rows; row++) { - tempv[offset + (rows * col)] = tempu[index++]; - offset++; - if (offset == rows) { - offset = 0; - } - } - } - index = 0; - for (int j = 0; j < rows; j++) { - tempu[index++] = c1[j]; - tempu[index++] = c2[j]; - tempu[index++] = c3[j]; - tempu[index++] = c4[j]; - tempu[index++] = c5[j]; - tempu[index++] = c6[j]; - tempu[index++] = c7[j]; - tempu[index++] = c8[j]; - tempu[index++] = c9[j]; - tempu[index++] = c10[j]; - tempu[index++] = c11[j]; - tempu[index++] = c12[j]; - tempu[index++] = c13[j]; - tempu[index++] = c14[j]; - tempu[index++] = c15[j]; - tempu[index++] = c16[j]; - } index = 0; for (int d = 0; d < frame_size / (mod * 2); d++) { pack = 0; for (int e = 0; e < (mod * 2); e++) { offset = mux[e]; - pack |= tempu[index++] << (((mod * 2) - 1) - offset); + pack |= in[lookup_table[index++]] << (((mod * 2) - 1) - offset); } out[produced++] = pack >> 8; out[produced++] = pack & 0xff; - consumed += (mod * 2); } + consumed += frame_size; + in += frame_size; } } - else { + + else { //frame_size = FRAME_SIZE_SHORT if (code_rate == C1_3) { mux = &mux256s_13[0]; } @@ -455,57 +505,17 @@ namespace gr { mux = &mux256s[0]; } for (int i = 0; i < noutput_items; i += packed_items) { - rows = frame_size / mod; - const unsigned char *c1, *c2, *c3, *c4, *c5, *c6, *c7, *c8; - c1 = &tempv[0]; - c2 = &tempv[rows]; - c3 = &tempv[rows * 2]; - c4 = &tempv[rows * 3]; - c5 = &tempv[rows * 4]; - c6 = &tempv[rows * 5]; - c7 = &tempv[rows * 6]; - c8 = &tempv[rows * 7]; - for (int k = 0; k < nbch; k++) { - tempu[k] = *in++; - } - for (int t = 0; t < q_val; t++) { - for (int s = 0; s < 360; s++) { - tempu[nbch + (360 * t) + s] = in[(q_val * s) + t]; - } - } - in = in + (q_val * 360); - index = 0; - for (int col = 0; col < mod; col++) { - offset = twist256s[col]; - for (int row = 0; row < rows; row++) { - tempv[offset + (rows * col)] = tempu[index++]; - offset++; - if (offset == rows) { - offset = 0; - } - } - } - index = 0; - for (int j = 0; j < rows; j++) { - tempu[index++] = c1[j]; - tempu[index++] = c2[j]; - tempu[index++] = c3[j]; - tempu[index++] = c4[j]; - tempu[index++] = c5[j]; - tempu[index++] = c6[j]; - tempu[index++] = c7[j]; - tempu[index++] = c8[j]; - } index = 0; for (int d = 0; d < frame_size / mod; d++) { pack = 0; for (int e = 0; e < mod; e++) { offset = mux[e]; - pack |= tempu[index++] << ((mod - 1) - offset); + pack |= in[lookup_table[index++]] << ((mod - 1) - offset); } out[produced++] = pack & 0xff; - consumed += mod; } + consumed += frame_size; + in += frame_size; } } break; diff --git a/gr-dtv/lib/dvbt2/dvbt2_interleaver_bb_impl.h b/gr-dtv/lib/dvbt2/dvbt2_interleaver_bb_impl.h index c737af0716..ef6098d4a3 100644 --- a/gr-dtv/lib/dvbt2/dvbt2_interleaver_bb_impl.h +++ b/gr-dtv/lib/dvbt2/dvbt2_interleaver_bb_impl.h @@ -38,7 +38,11 @@ namespace gr { int mod; int packed_items; unsigned char tempu[FRAME_SIZE_NORMAL]; - unsigned char tempv[FRAME_SIZE_NORMAL]; + int lookup_table[FRAME_SIZE_NORMAL]; + + void generate_lookup(); + inline void interleave_parity_bits(int *tempu, const int *&in); + inline void twist_interleave_columns(int* tempv, int* tempu, int rows, const int *twist); const static int twist16n[8]; const static int twist64n[12]; diff --git a/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.cc b/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.cc index f4d6233b53..d653eae1dc 100644 --- a/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.cc +++ b/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.cc @@ -1113,7 +1113,7 @@ namespace gr { break; } fstep = fs / vlength; - for (int i = 0; i < vlength / 2; i++) { + for (unsigned int i = 0; i < vlength / 2; i++) { x = GR_M_PI * f / fs; if (i == 0) { sinc = 1.0; @@ -1127,7 +1127,7 @@ namespace gr { f = f + fstep; } sincrms = std::sqrt(sincrms / (vlength / 2)); - for (int i = 0; i < vlength; i++) { + for (unsigned int i = 0; i < vlength; i++) { inverse_sinc[i] *= sincrms; } equalization_enable = equalization; @@ -1137,7 +1137,14 @@ namespace gr { GR_LOG_FATAL(d_logger, "Pilot Generator and IFFT, cannot allocate memory for ofdm_fft."); throw std::bad_alloc(); } + num_symbols = numdatasyms + N_P2; + data_carrier_map.resize(num_symbols); + for (std::vector< std::vector<int> >::size_type i = 0; i != data_carrier_map.size(); i++){ + data_carrier_map[i].resize(MAX_CARRIERS); + } + init_pilots(); + set_output_multiple(num_symbols); } @@ -1179,9 +1186,11 @@ namespace gr { } void - dvbt2_pilotgenerator_cc_impl::init_pilots(int symbol) + dvbt2_pilotgenerator_cc_impl::init_pilots() { + for (int symbol = 0; symbol < num_symbols; ++symbol){ int remainder, shift; + std::vector<int> &data_carrier_map = this->data_carrier_map[symbol]; for (int i = 0; i < C_PS; i++) { data_carrier_map[i] = DATA_CARRIER; } @@ -2675,8 +2684,11 @@ namespace gr { break; } } + } } + const gr_complex zero = gr_complex(0.0, 0.0); + int dvbt2_pilotgenerator_cc_impl::general_work (int noutput_items, gr_vector_int &ninput_items, @@ -2685,17 +2697,14 @@ namespace gr { { const gr_complex *in = (const gr_complex *) input_items[0]; gr_complex *out = (gr_complex *) output_items[0]; - gr_complex zero; gr_complex *dst; int L_FC = 0; - zero = gr_complex(0.0, 0.0); if (N_FC != 0) { L_FC = 1; } for (int i = 0; i < noutput_items; i += num_symbols) { for (int j = 0; j < num_symbols; j++) { - init_pilots(j); if (j < N_P2) { for (int n = 0; n < left_nulls; n++) { *out++ = zero; @@ -2745,19 +2754,19 @@ namespace gr { *out++ = zero; } for (int n = 0; n < C_PS; n++) { - if (data_carrier_map[n] == SCATTERED_CARRIER) { + if (data_carrier_map[j][n] == SCATTERED_CARRIER) { *out++ = sp_bpsk[prbs[n + K_OFFSET] ^ pn_sequence[j]]; } - else if (data_carrier_map[n] == SCATTERED_CARRIER_INVERTED) { + else if (data_carrier_map[j][n] == SCATTERED_CARRIER_INVERTED) { *out++ = sp_bpsk_inverted[prbs[n + K_OFFSET] ^ pn_sequence[j]]; } - else if (data_carrier_map[n] == CONTINUAL_CARRIER) { + else if (data_carrier_map[j][n] == CONTINUAL_CARRIER) { *out++ = cp_bpsk[prbs[n + K_OFFSET] ^ pn_sequence[j]]; } - else if (data_carrier_map[n] == CONTINUAL_CARRIER_INVERTED) { + else if (data_carrier_map[j][n] == CONTINUAL_CARRIER_INVERTED) { *out++ = cp_bpsk_inverted[prbs[n + K_OFFSET] ^ pn_sequence[j]]; } - else if (data_carrier_map[n] == TRPAPR_CARRIER) { + else if (data_carrier_map[j][n] == TRPAPR_CARRIER) { *out++ = zero; } else { diff --git a/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.h b/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.h index 6543e26512..9f06721d04 100644 --- a/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.h +++ b/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.h @@ -22,8 +22,9 @@ #define INCLUDED_DTV_DVBT2_PILOTGENERATOR_CC_IMPL_H #include <gnuradio/dtv/dvbt2_pilotgenerator_cc.h> -#include <gnuradio/fft/fft.h> #include "dvb/dvb_defines.h" +#include <gnuradio/fft/fft.h> +#include <vector> #define CHIPS 2624 #define MAX_CARRIERS 27841 @@ -66,7 +67,7 @@ namespace gr { int prbs[MAX_CARRIERS]; int pn_sequence[CHIPS]; int p2_carrier_map[MAX_CARRIERS]; - int data_carrier_map[MAX_CARRIERS]; + std::vector< std::vector<int> > data_carrier_map; int fc_carrier_map[MAX_CARRIERS]; int N_P2; int C_P2; @@ -81,7 +82,7 @@ namespace gr { int miso; int miso_group; void init_prbs(void); - void init_pilots(int); + void init_pilots(void); fft::fft_complex *ofdm_fft; int ofdm_fft_size; diff --git a/gr-fec/CMakeLists.txt b/gr-fec/CMakeLists.txt index adb2a941fd..be554db7ef 100644 --- a/gr-fec/CMakeLists.txt +++ b/gr-fec/CMakeLists.txt @@ -59,8 +59,10 @@ if(ENABLE_PYTHON) add_subdirectory(swig) add_subdirectory(python/fec) add_subdirectory(python/fec/LDPC) - add_subdirectory(grc) endif(ENABLE_PYTHON) +if(ENABLE_GRC) + add_subdirectory(grc) +endif(ENABLE_GRC) add_subdirectory(examples) add_subdirectory(docs) add_subdirectory(ldpc_alist) diff --git a/gr-fec/grc/variable_polar_encoder.block.yml b/gr-fec/grc/variable_polar_encoder.block.yml index dbaa619f5f..10e07cdcb0 100644 --- a/gr-fec/grc/variable_polar_encoder.block.yml +++ b/gr-fec/grc/variable_polar_encoder.block.yml @@ -4,10 +4,8 @@ label: POLAR Encoder Definition parameters: - id: is_packed label: Packed Bits - dtype: enum + dtype: bool default: 'False' - options: ['False', 'True'] - option_labels: ['No', 'Yes'] - id: ndim label: Parallelism dtype: enum diff --git a/gr-fec/lib/polar_common.cc b/gr-fec/lib/polar_common.cc index fcb34c2d35..68d1b97f40 100644 --- a/gr-fec/lib/polar_common.cc +++ b/gr-fec/lib/polar_common.cc @@ -111,7 +111,7 @@ namespace gr { std::copy(d_frozen_bit_values.begin(), d_frozen_bit_values.end(), d_volk_frozen_bits); std::fill(d_volk_frozen_bits + d_frozen_bit_values.size(), d_volk_frozen_bits + nfrozen, 0); - int nfbit = 0; + unsigned int nfbit = 0; for(int i = 0; i < block_size(); i++){ unsigned char m = 0x00; if(nfbit < d_frozen_bit_positions.size() && d_frozen_bit_positions[nfbit] == i){ diff --git a/gr-fft/CMakeLists.txt b/gr-fft/CMakeLists.txt index 992ca5ca86..4bf8263965 100644 --- a/gr-fft/CMakeLists.txt +++ b/gr-fft/CMakeLists.txt @@ -55,8 +55,10 @@ add_subdirectory(lib) if(ENABLE_PYTHON) add_subdirectory(swig) add_subdirectory(python/fft) - add_subdirectory(grc) endif(ENABLE_PYTHON) +if(ENABLE_GRC) + add_subdirectory(grc) +endif(ENABLE_GRC) add_subdirectory(docs) ######################################################################## diff --git a/gr-fft/grc/fft_fft_vxx.block.yml b/gr-fft/grc/fft_fft_vxx.block.yml index 33143f688a..d28bf5ccbe 100644 --- a/gr-fft/grc/fft_fft_vxx.block.yml +++ b/gr-fft/grc/fft_fft_vxx.block.yml @@ -6,14 +6,11 @@ parameters: label: Input Type dtype: enum options: [complex, float] - option_attributes: - hide_shift: ['', all] hide: part - id: fft_size label: FFT Size dtype: int default: '1024' - hide: ${ 'part' if vlen == 1 else 'none' } - id: forward label: Forward/Reverse dtype: enum @@ -28,7 +25,7 @@ parameters: dtype: enum options: ['True', 'False'] option_labels: ['Yes', 'No'] - hide: ${ type.hide_shift } + hide: ${ 'all' if type == 'float' else 'none' } - id: nthreads label: Num. Threads dtype: int diff --git a/gr-fft/include/gnuradio/fft/fft_vcc.h b/gr-fft/include/gnuradio/fft/fft_vcc.h index 28f6d1d0d4..03e82a9989 100644 --- a/gr-fft/include/gnuradio/fft/fft_vcc.h +++ b/gr-fft/include/gnuradio/fft/fft_vcc.h @@ -66,7 +66,7 @@ namespace gr { * \param[in] fft_size N. * \param[in] forward True performs FFT, False performs IFFT. * \param[in] window Window function to be used. - * \param[in] shifted True moves DC carrier to the middle. + * \param[in] shift True moves DC carrier to the middle. * \param[in] nthreads Number of underlying threads. */ static sptr make(int fft_size, bool forward, diff --git a/gr-fft/include/gnuradio/fft/fft_vfc.h b/gr-fft/include/gnuradio/fft/fft_vfc.h index 5639465ab5..e5ec9bf3ee 100644 --- a/gr-fft/include/gnuradio/fft/fft_vfc.h +++ b/gr-fft/include/gnuradio/fft/fft_vfc.h @@ -67,7 +67,6 @@ namespace gr { * \param[in] fft_size N. * \param[in] forward True performs FFT, False performs IFFT. * \param[in] window Window function to be used. - * \param[in] shifted True moves DC carrier to the middle. * \param[in] nthreads Number of underlying threads. */ static sptr make(int fft_size, bool forward, diff --git a/gr-filter/CMakeLists.txt b/gr-filter/CMakeLists.txt index fd5f3cc25c..ed1e52ab91 100644 --- a/gr-filter/CMakeLists.txt +++ b/gr-filter/CMakeLists.txt @@ -60,9 +60,11 @@ if(ENABLE_PYTHON) add_subdirectory(python/filter) add_subdirectory(python/filter/design) add_subdirectory(python/filter/gui) - add_subdirectory(grc) add_subdirectory(apps) endif(ENABLE_PYTHON) +if(ENABLE_GRC) + add_subdirectory(grc) +endif(ENABLE_GRC) add_subdirectory(examples) add_subdirectory(docs) diff --git a/gr-filter/lib/pfb_decimator_ccf_impl.cc b/gr-filter/lib/pfb_decimator_ccf_impl.cc index 75ca47d85b..ff6264ba90 100644 --- a/gr-filter/lib/pfb_decimator_ccf_impl.cc +++ b/gr-filter/lib/pfb_decimator_ccf_impl.cc @@ -98,7 +98,7 @@ namespace gr { pfb_decimator_ccf_impl::~pfb_decimator_ccf_impl() { - delete d_rotator; + delete[] d_rotator; } void diff --git a/gr-filter/python/filter/qa_fft_filter.py b/gr-filter/python/filter/qa_fft_filter.py index 01b225d901..2ab49e7cec 100644 --- a/gr-filter/python/filter/qa_fft_filter.py +++ b/gr-filter/python/filter/qa_fft_filter.py @@ -89,7 +89,7 @@ def print_complex(x): class test_fft_filter(gr_unittest.TestCase): def setUp(self): - pass + random.seed(0) def tearDown(self): pass diff --git a/gr-filter/python/filter/qa_filterbank.py b/gr-filter/python/filter/qa_filterbank.py index 9a99c6832f..036f34498b 100644 --- a/gr-filter/python/filter/qa_filterbank.py +++ b/gr-filter/python/filter/qa_filterbank.py @@ -43,6 +43,7 @@ def convolution(A, B): class test_filterbank_vcvcf(gr_unittest.TestCase): def setUp(self): + random.seed(0) self.tb = gr.top_block() def tearDown(self): diff --git a/gr-qtgui/CMakeLists.txt b/gr-qtgui/CMakeLists.txt index a418f457f3..b0b109f55c 100644 --- a/gr-qtgui/CMakeLists.txt +++ b/gr-qtgui/CMakeLists.txt @@ -80,12 +80,14 @@ add_subdirectory(lib) add_subdirectory(docs) add_subdirectory(examples/c++) if(ENABLE_PYTHON) - add_subdirectory(grc) add_subdirectory(swig) add_subdirectory(python/qtgui) add_subdirectory(examples) add_subdirectory(apps) endif(ENABLE_PYTHON) +if(ENABLE_GRC) + add_subdirectory(grc) +endif(ENABLE_GRC) ######################################################################## # Create Pkg Config File diff --git a/gr-qtgui/grc/qtgui_freq_sink_x.block.yml b/gr-qtgui/grc/qtgui_freq_sink_x.block.yml index 9eb49b8605..d0b7f45eba 100644 --- a/gr-qtgui/grc/qtgui_freq_sink_x.block.yml +++ b/gr-qtgui/grc/qtgui_freq_sink_x.block.yml @@ -375,6 +375,10 @@ inputs: id: freq optional: true hide: ${ showports } +- domain: message + id: bw + optional: true + hide: ${ showports } outputs: - domain: message diff --git a/gr-qtgui/grc/qtgui_time_sink_x.block.yml b/gr-qtgui/grc/qtgui_time_sink_x.block.yml index f97b30e8db..b179020e49 100644 --- a/gr-qtgui/grc/qtgui_time_sink_x.block.yml +++ b/gr-qtgui/grc/qtgui_time_sink_x.block.yml @@ -155,330 +155,657 @@ parameters: hide: part - id: label1 label: Line 1 Label - category: Config dtype: string - hide: ${ ('part' if int(nconnections) >= 1 else 'all') } + default: 'Signal 1' + hide: ${ ('part' if ( + int(nconnections) >= 1 + or (type == "complex" and int(nconnections) >= 1) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: width1 label: Line 1 Width - category: Config - dtype: int - default: '1' - hide: ${ ('part' if int(nconnections) >= 1 else 'all') } + default: 1 + hide: ${ ('part' if ( + int(nconnections) >= 1 + or (type == "complex" and int(nconnections) >= 1) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: color1 label: Line 1 Color - category: Config - dtype: enum - options: ['"blue"', '"red"', '"green"', '"black"', '"cyan"', '"magenta"', '"yellow"', - '"dark red"', '"dark green"', '"Dark Blue"'] - option_labels: [Blue, Red, Green, Black, Cyan, Magenta, Yellow, Dark Red, Dark - Green, Dark Blue] - hide: ${ ('part' if int(nconnections) >= 1 else 'all') } + dtype: string + default: 'blue' + hide: ${ ('part' if ( + int(nconnections) >= 1 + or (type == "complex" and int(nconnections) >= 1) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: style1 label: Line 1 Style - category: Config - dtype: enum - options: ['1', '2', '3', '4', '5', '0'] - option_labels: [Solid, Dash, Dots, Dash-Dot, Dash-Dot-Dot, None] - hide: ${ ('part' if int(nconnections) >= 1 else 'all') } + dtype: int + default: 1 + hide: ${ ('part' if ( + int(nconnections) >= 1 + or (type == "complex" and int(nconnections) >= 1) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: marker1 label: Line 1 Marker - category: Config - dtype: enum - options: ['-1', '0', '1', '2', '3', '4', '6', '7', '8', '9'] - option_labels: [None, Circle, Rectangle, Diamond, Triangle, Down Triangle, Left - Triangle, Right Triangle, Cross, X-Cross] - hide: ${ ('part' if int(nconnections) >= 1 else 'all') } + dtype: int + default: 1 + hide: ${ ('part' if ( + int(nconnections) >= 1 + or (type == "complex" and int(nconnections) >= 1) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: alpha1 label: Line 1 Alpha - category: Config - dtype: float - default: '1.0' - hide: ${ ('part' if int(nconnections) >= 1 else 'all') } + dtype: real + default: 1.0 + hide: ${ ('part' if ( + int(nconnections) >= 1 + or (type == "complex" and int(nconnections) >= 1) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } + - id: label2 label: Line 2 Label + dtype: string + default: 'Signal 2' base_key: label1 - hide: ${ ('part' if (int(nconnections) >= 2 or (type == "complex" and int(nconnections) - >= 1) or (type == "msg_complex")) and (not type == "msg_float") else 'all') + hide: ${ ('part' if ( + int(nconnections) >= 2 + or (type == "complex" and int(nconnections) >= 1) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') } - id: width2 label: Line 2 Width + default: 1 base_key: width1 - hide: ${ ('part' if (int(nconnections) >= 2 or (type == "complex" and int(nconnections) - >= 1) or (type == "msg_complex")) and (not type == "msg_float") else 'all') + hide: ${ ('part' if ( + int(nconnections) >= 2 + or (type == "complex" and int(nconnections) >= 1) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') } - id: color2 label: Line 2 Color + dtype: string + default: 'green' base_key: color1 - default: '"red"' - hide: ${ ('part' if (int(nconnections) >= 2 or (type == "complex" and int(nconnections) - >= 1) or (type == "msg_complex")) and (not type == "msg_float") else 'all') + hide: ${ ('part' if ( + int(nconnections) >= 2 + or (type == "complex" and int(nconnections) >= 1) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') } - id: style2 label: Line 2 Style + dtype: int + default: 1 base_key: style1 - hide: ${ ('part' if (int(nconnections) >= 2 or (type == "complex" and int(nconnections) - >= 1) or (type == "msg_complex")) and (not type == "msg_float") else 'all') + hide: ${ ('part' if ( + int(nconnections) >= 2 + or (type == "complex" and int(nconnections) >= 1) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') } - id: marker2 label: Line 2 Marker + dtype: int + default: 1 base_key: marker1 - hide: ${ ('part' if (int(nconnections) >= 2 or (type == "complex" and int(nconnections) - >= 1) or (type == "msg_complex")) and (not type == "msg_float") else 'all') + hide: ${ ('part' if ( + int(nconnections) >= 2 + or (type == "complex" and int(nconnections) >= 1) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') } - id: alpha2 label: Line 2 Alpha + dtype: real + default: 1.0 base_key: alpha1 - hide: ${ ('part' if (int(nconnections) >= 2 or (type == "complex" and int(nconnections) - >= 1) or (type == "msg_complex")) and (not type == "msg_float") else 'all') + hide: ${ ('part' if ( + int(nconnections) >= 2 + or (type == "complex" and int(nconnections) >= 1) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') } + - id: label3 label: Line 3 Label + dtype: string + default: 'Signal 3' base_key: label1 - hide: ${ ('part' if ((int(nconnections) >= 3 or (type == "complex" and int(nconnections) - >= 2)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 3 + or (type == "complex" and int(nconnections) >= 2) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: width3 label: Line 3 Width + default: 1 base_key: width1 - hide: ${ ('part' if ((int(nconnections) >= 3 or (type == "complex" and int(nconnections) - >= 2)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 3 + or (type == "complex" and int(nconnections) >= 2) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: color3 label: Line 3 Color + dtype: string + default: 'black' base_key: color1 - default: '"green"' - hide: ${ ('part' if ((int(nconnections) >= 3 or (type == "complex" and int(nconnections) - >= 2)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 3 + or (type == "complex" and int(nconnections) >= 2) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: style3 label: Line 3 Style + dtype: int + default: 1 base_key: style1 - hide: ${ ('part' if ((int(nconnections) >= 3 or (type == "complex" and int(nconnections) - >= 2)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 3 + or (type == "complex" and int(nconnections) >= 2) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: marker3 label: Line 3 Marker + dtype: int + default: 1 base_key: marker1 - hide: ${ ('part' if ((int(nconnections) >= 3 or (type == "complex" and int(nconnections) - >= 2)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 3 + or (type == "complex" and int(nconnections) >= 2) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: alpha3 label: Line 3 Alpha + dtype: real + default: 1.0 base_key: alpha1 - hide: ${ ('part' if ((int(nconnections) >= 3 or (type == "complex" and int(nconnections) - >= 2)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 3 + or (type == "complex" and int(nconnections) >= 2) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } + - id: label4 label: Line 4 Label + dtype: string + default: 'Signal 4' base_key: label1 - hide: ${ ('part' if ((int(nconnections) >= 4 or (type == "complex" and int(nconnections) - >= 2)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 4 + or (type == "complex" and int(nconnections) >= 2) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: width4 label: Line 4 Width + default: 1 base_key: width1 - hide: ${ ('part' if ((int(nconnections) >= 4 or (type == "complex" and int(nconnections) - >= 2)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 4 + or (type == "complex" and int(nconnections) >= 2) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: color4 label: Line 4 Color + dtype: string + default: 'cyan' base_key: color1 - default: '"black"' - hide: ${ ('part' if ((int(nconnections) >= 4 or (type == "complex" and int(nconnections) - >= 2)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 4 + or (type == "complex" and int(nconnections) >= 2) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: style4 label: Line 4 Style + dtype: int + default: 1 base_key: style1 - hide: ${ ('part' if ((int(nconnections) >= 4 or (type == "complex" and int(nconnections) - >= 2)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 4 + or (type == "complex" and int(nconnections) >= 2) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: marker4 label: Line 4 Marker + dtype: int + default: 1 base_key: marker1 - hide: ${ ('part' if ((int(nconnections) >= 4 or (type == "complex" and int(nconnections) - >= 2)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 4 + or (type == "complex" and int(nconnections) >= 2) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: alpha4 label: Line 4 Alpha + dtype: real + default: 1.0 base_key: alpha1 - hide: ${ ('part' if ((int(nconnections) >= 4 or (type == "complex" and int(nconnections) - >= 2)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 4 + or (type == "complex" and int(nconnections) >= 2) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } + - id: label5 label: Line 5 Label + dtype: string + default: 'Signal 5' base_key: label1 - hide: ${ ('part' if ((int(nconnections) >= 5 or (type == "complex" and int(nconnections) - >= 3)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 5 + or (type == "complex" and int(nconnections) >= 3) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: width5 label: Line 5 Width + default: 1 base_key: width1 - hide: ${ ('part' if ((int(nconnections) >= 5 or (type == "complex" and int(nconnections) - >= 3)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 5 + or (type == "complex" and int(nconnections) >= 3) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: color5 label: Line 5 Color + dtype: string + default: 'magenta' base_key: color1 - default: '"cyan"' - hide: ${ ('part' if ((int(nconnections) >= 5 or (type == "complex" and int(nconnections) - >= 3)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 5 + or (type == "complex" and int(nconnections) >= 3) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: style5 label: Line 5 Style + dtype: int + default: 1 base_key: style1 - hide: ${ ('part' if ((int(nconnections) >= 5 or (type == "complex" and int(nconnections) - >= 3)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 5 + or (type == "complex" and int(nconnections) >= 3) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: marker5 label: Line 5 Marker + dtype: int + default: 1 base_key: marker1 - hide: ${ ('part' if ((int(nconnections) >= 5 or (type == "complex" and int(nconnections) - >= 3)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 5 + or (type == "complex" and int(nconnections) >= 3) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: alpha5 label: Line 5 Alpha + dtype: real + default: 1.0 base_key: alpha1 - hide: ${ ('part' if ((int(nconnections) >= 5 or (type == "complex" and int(nconnections) - >= 3)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 5 + or (type == "complex" and int(nconnections) >= 3) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } + - id: label6 label: Line 6 Label + dtype: string + default: 'Signal 6' base_key: label1 - hide: ${ ('part' if ((int(nconnections) >= 6 or (type == "complex" and int(nconnections) - >= 3)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 6 + or (type == "complex" and int(nconnections) >= 3) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: width6 label: Line 6 Width + default: 1 base_key: width1 - hide: ${ ('part' if ((int(nconnections) >= 6 or (type == "complex" and int(nconnections) - >= 3)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 6 + or (type == "complex" and int(nconnections) >= 3) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: color6 label: Line 6 Color + dtype: string + default: 'yellow' base_key: color1 - default: '"magenta"' - hide: ${ ('part' if ((int(nconnections) >= 6 or (type == "complex" and int(nconnections) - >= 3)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 6 + or (type == "complex" and int(nconnections) >= 3) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: style6 label: Line 6 Style + dtype: int + default: 1 base_key: style1 - hide: ${ ('part' if ((int(nconnections) >= 6 or (type == "complex" and int(nconnections) - >= 3)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 6 + or (type == "complex" and int(nconnections) >= 3) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: marker6 label: Line 6 Marker + dtype: int + default: 1 base_key: marker1 - hide: ${ ('part' if ((int(nconnections) >= 6 or (type == "complex" and int(nconnections) - >= 3)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 6 + or (type == "complex" and int(nconnections) >= 3) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: alpha6 label: Line 6 Alpha + dtype: real + default: 1.0 base_key: alpha1 - hide: ${ ('part' if ((int(nconnections) >= 6 or (type == "complex" and int(nconnections) - >= 3)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 6 + or (type == "complex" and int(nconnections) >= 3) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } + - id: label7 label: Line 7 Label + dtype: string + default: 'Signal 7' base_key: label1 - hide: ${ ('part' if ((int(nconnections) >= 7 or (type == "complex" and int(nconnections) - >= 4)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 7 + or (type == "complex" and int(nconnections) >= 4) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: width7 label: Line 7 Width + default: 1 base_key: width1 - hide: ${ ('part' if ((int(nconnections) >= 7 or (type == "complex" and int(nconnections) - >= 4)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 7 + or (type == "complex" and int(nconnections) >= 4) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: color7 label: Line 7 Color + dtype: string + default: 'dark red' base_key: color1 - default: '"yellow"' - hide: ${ ('part' if ((int(nconnections) >= 7 or (type == "complex" and int(nconnections) - >= 4)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 7 + or (type == "complex" and int(nconnections) >= 4) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: style7 label: Line 7 Style + dtype: int + default: 1 base_key: style1 - hide: ${ ('part' if ((int(nconnections) >= 7 or (type == "complex" and int(nconnections) - >= 4)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 7 + or (type == "complex" and int(nconnections) >= 4) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: marker7 label: Line 7 Marker + dtype: int + default: 1 base_key: marker1 - hide: ${ ('part' if ((int(nconnections) >= 7 or (type == "complex" and int(nconnections) - >= 4)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 7 + or (type == "complex" and int(nconnections) >= 4) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: alpha7 label: Line 7 Alpha + dtype: real + default: 1.0 base_key: alpha1 - hide: ${ ('part' if ((int(nconnections) >= 7 or (type == "complex" and int(nconnections) - >= 4)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 7 + or (type == "complex" and int(nconnections) >= 4) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } + - id: label8 label: Line 8 Label + dtype: string + default: 'Signal 8' base_key: label1 - hide: ${ ('part' if ((int(nconnections) >= 8 or (type == "complex" and int(nconnections) - >= 4)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 8 + or (type == "complex" and int(nconnections) >= 4) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: width8 label: Line 8 Width + default: 1 base_key: width1 - hide: ${ ('part' if ((int(nconnections) >= 8 or (type == "complex" and int(nconnections) - >= 4)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 8 + or (type == "complex" and int(nconnections) >= 4) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: color8 label: Line 8 Color + dtype: string + default: 'dark green' base_key: color1 - default: '"dark red"' - hide: ${ ('part' if ((int(nconnections) >= 8 or (type == "complex" and int(nconnections) - >= 4)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 8 + or (type == "complex" and int(nconnections) >= 4) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: style8 label: Line 8 Style + dtype: int + default: 1 base_key: style1 - hide: ${ ('part' if ((int(nconnections) >= 8 or (type == "complex" and int(nconnections) - >= 4)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 8 + or (type == "complex" and int(nconnections) >= 4) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: marker8 label: Line 8 Marker + dtype: int + default: 1 base_key: marker1 - hide: ${ ('part' if ((int(nconnections) >= 8 or (type == "complex" and int(nconnections) - >= 4)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 8 + or (type == "complex" and int(nconnections) >= 4) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: alpha8 label: Line 8 Alpha + dtype: real + default: 1.0 base_key: alpha1 - hide: ${ ('part' if ((int(nconnections) >= 8 or (type == "complex" and int(nconnections) - >= 4)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 8 + or (type == "complex" and int(nconnections) >= 4) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } + - id: label9 label: Line 9 Label + dtype: string + default: 'Signal 9' base_key: label1 - hide: ${ ('part' if ((int(nconnections) >= 9 or (type == "complex" and int(nconnections) - >= 5)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 9 + or (type == "complex" and int(nconnections) >= 5) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: width9 label: Line 9 Width + default: 1 base_key: width1 - hide: ${ ('part' if ((int(nconnections) >= 9 or (type == "complex" and int(nconnections) - >= 5)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 9 + or (type == "complex" and int(nconnections) >= 5) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: color9 label: Line 9 Color + dtype: string + default: 'Dark Blue' base_key: color1 - default: '"dark green"' - hide: ${ ('part' if ((int(nconnections) >= 9 or (type == "complex" and int(nconnections) - >= 5)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 9 + or (type == "complex" and int(nconnections) >= 5) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: style9 label: Line 9 Style + dtype: int + default: 1 base_key: style1 - hide: ${ ('part' if ((int(nconnections) >= 9 or (type == "complex" and int(nconnections) - >= 5)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 9 + or (type == "complex" and int(nconnections) >= 5) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: marker9 label: Line 9 Marker + dtype: int + default: 1 base_key: marker1 - hide: ${ ('part' if ((int(nconnections) >= 9 or (type == "complex" and int(nconnections) - >= 5)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 9 + or (type == "complex" and int(nconnections) >= 5) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: alpha9 label: Line 9 Alpha + dtype: real + default: 1.0 base_key: alpha1 - hide: ${ ('part' if ((int(nconnections) >= 9 or (type == "complex" and int(nconnections) - >= 5)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 9 + or (type == "complex" and int(nconnections) >= 5) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } + - id: label10 label: Line 10 Label + dtype: string + default: 'Signal 10' base_key: label1 - hide: ${ ('part' if ((int(nconnections) >= 10 or (type == "complex" and int(nconnections) - >= 5)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 10 + or (type == "complex" and int(nconnections) >= 5) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: width10 label: Line 10 Width + default: 1 base_key: width1 - hide: ${ ('part' if ((int(nconnections) >= 10 or (type == "complex" and int(nconnections) - >= 5)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 10 + or (type == "complex" and int(nconnections) >= 5) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: color10 label: Line 10 Color + dtype: string + default: 'blue' base_key: color1 - default: '"dark blue"' - hide: ${ ('part' if ((int(nconnections) >= 10 or (type == "complex" and int(nconnections) - >= 5)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 10 + or (type == "complex" and int(nconnections) >= 5) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: style10 label: Line 10 Style + dtype: int + default: 1 base_key: style1 - hide: ${ ('part' if ((int(nconnections) >= 10 or (type == "complex" and int(nconnections) - >= 5)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 10 + or (type == "complex" and int(nconnections) >= 5) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: marker10 label: Line 10 Marker + dtype: int + default: 1 base_key: marker1 - hide: ${ ('part' if ((int(nconnections) >= 10 or (type == "complex" and int(nconnections) - >= 5)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 10 + or (type == "complex" and int(nconnections) >= 5) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } - id: alpha10 label: Line 10 Alpha + dtype: real + default: 1.0 base_key: alpha1 - hide: ${ ('part' if ((int(nconnections) >= 10 or (type == "complex" and int(nconnections) - >= 5)) and not type.t == "message") else 'all') } + hide: ${ ('part' if ( + int(nconnections) >= 10 + or (type == "complex" and int(nconnections) >= 5) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + } asserts: - ${nconnections <= (5 if type == 'complex' else 10)} diff --git a/gr-qtgui/grc/qtgui_time_sink_x.block.yml.py b/gr-qtgui/grc/qtgui_time_sink_x.block.yml.py new file mode 100644 index 0000000000..571a5dfba8 --- /dev/null +++ b/gr-qtgui/grc/qtgui_time_sink_x.block.yml.py @@ -0,0 +1,362 @@ +#!/usr/bin/env python + +import math +import re + +EVERYTHING_BEFORE_PARAMS = """id: qtgui_time_sink_x +label: QT GUI Time Sink + +parameters: +- id: type + label: Type + dtype: enum + default: complex + options: [complex, float, msg_complex, msg_float] + option_labels: [Complex, Float, Complex Message, Float Message] + option_attributes: + fcn: [time_sink_c, time_sink_f, time_sink_c, time_sink_f] + t: [complex, float, message, message] + hide: part +- id: name + label: Name + dtype: string + default: '""' + hide: ${ ('none' if len(name) > 0 else 'part') } +- id: ylabel + label: Y Axis Label + dtype: string + default: Amplitude + hide: part +- id: yunit + label: Y Axis Unit + dtype: string + default: '""' + hide: part +- id: size + label: Number of Points + dtype: int + default: '1024' + hide: ${ ('all' if type.startswith('msg') else 'none') } +- id: srate + label: Sample Rate + dtype: float + default: samp_rate +- id: grid + label: Grid + dtype: enum + default: 'False' + options: ['True', 'False'] + option_labels: ['Yes', 'No'] + hide: part +- id: autoscale + label: Autoscale + dtype: enum + default: 'False' + options: ['True', 'False'] + option_labels: ['Yes', 'No'] +- id: ymin + label: Y min + dtype: float + default: '-1' + hide: part +- id: ymax + label: Y max + dtype: float + default: '1' + hide: part +- id: nconnections + label: Number of Inputs + dtype: int + default: '1' + hide: ${ ('all' if type.startswith('msg') else 'part') } +- id: update_time + label: Update Period + dtype: float + default: '0.10' + hide: part +- id: entags + label: Disp. Tags + dtype: enum + default: 'True' + options: ['True', 'False'] + option_labels: ['Yes', 'No'] + hide: ${ ('all' if type.startswith('msg') else 'part') } +- id: gui_hint + label: GUI Hint + dtype: gui_hint + hide: part +- id: tr_mode + label: Trigger Mode + category: Trigger + dtype: enum + default: qtgui.TRIG_MODE_FREE + options: [qtgui.TRIG_MODE_FREE, qtgui.TRIG_MODE_AUTO, qtgui.TRIG_MODE_NORM, qtgui.TRIG_MODE_TAG] + option_labels: [Free, Auto, Normal, Tag] + hide: part +- id: tr_slope + label: Trigger Slope + category: Trigger + dtype: enum + default: qtgui.TRIG_MODE_POS + options: [qtgui.TRIG_SLOPE_POS, qtgui.TRIG_SLOPE_NEG] + option_labels: [Positive, Negative] + hide: part +- id: tr_level + label: Trigger Level + category: Trigger + dtype: float + default: '0.0' + hide: part +- id: tr_delay + label: Trigger Delay + category: Trigger + dtype: float + default: '0' + hide: part +- id: tr_chan + label: Trigger Channel + category: Trigger + dtype: int + default: '0' + hide: part +- id: tr_tag + label: Trigger Tag Key + category: Trigger + dtype: string + default: '""' + hide: part +- id: ctrlpanel + label: Control Panel + category: Config + dtype: enum + default: 'False' + options: ['True', 'False'] + option_labels: ['Yes', 'No'] + hide: part +- id: legend + label: Legend + category: Config + dtype: enum + default: 'True' + options: ['True', 'False'] + option_labels: ['Yes', 'No'] + hide: part +- id: axislabels + label: Axis Labels + category: Config + dtype: enum + default: 'True' + options: ['True', 'False'] + option_labels: ['Yes', 'No'] + hide: part +- id: stemplot + label: Stem Plot + category: Config + dtype: enum + default: 'False' + options: ['True', 'False'] + option_labels: ['Yes', 'No'] + hide: part""" + +LINE_PARAMS = """ +- id: label{i} + label: Line {i} Label + dtype: string + default: 'Signal {i}' + base_key: label1 + hide: ${{ ('part' if ( + int(nconnections) >= {i} + or (type == "complex" and int(nconnections) >= {i_cplx}) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + }} +- id: width{i} + label: Line {i} Width + default: 1 + base_key: width1 + hide: ${{ ('part' if ( + int(nconnections) >= {i} + or (type == "complex" and int(nconnections) >= {i_cplx}) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + }} +- id: color{i} + label: Line {i} Color + dtype: string + default: '{i_color}' + base_key: color1 + hide: ${{ ('part' if ( + int(nconnections) >= {i} + or (type == "complex" and int(nconnections) >= {i_cplx}) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + }} +- id: style{i} + label: Line {i} Style + dtype: int + default: 1 + base_key: style1 + hide: ${{ ('part' if ( + int(nconnections) >= {i} + or (type == "complex" and int(nconnections) >= {i_cplx}) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + }} +- id: marker{i} + label: Line {i} Marker + dtype: int + default: 1 + base_key: marker1 + hide: ${{ ('part' if ( + int(nconnections) >= {i} + or (type == "complex" and int(nconnections) >= {i_cplx}) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + }} +- id: alpha{i} + label: Line {i} Alpha + dtype: real + default: 1.0 + base_key: alpha1 + hide: ${{ ('part' if ( + int(nconnections) >= {i} + or (type == "complex" and int(nconnections) >= {i_cplx}) + or (type == "msg_complex")) and (not type == "msg_float") + else 'all') + }} +""" + +EVERYTHING_AFTER_PARAMS = """ +asserts: +- ${nconnections <= (5 if type == 'complex' else 10)} + +inputs: +- domain: stream + dtype: ${ type.t } + multiplicity: ${ (0 if type.startswith('msg') else nconnections) } + optional: true + +templates: + imports: |- + from PyQt5 import Qt + from gnuradio import qtgui + from gnuradio.filter import firdes + import sip + callbacks: + - set_time_domain_axis(${min}, ${max}) + - set_update_time(${update_time}) + - set_y_axis(${ymin}, ${ymax}) + - set_samp_rate(${srate}) + - self.${id}.set_trigger_mode(${tr_mode}, ${tr_slope}, ${tr_level}, ${tr_delay}, + ${tr_chan}, ${tr_tag}) + make: |- + <% + win = 'self._%s_win'%id + %>\\ + qtgui.${type.fcn}( + ${size}, #size + ${srate}, #samp_rate + ${name}, #name + ${0 if type.startswith('msg') else nconnections} #number of inputs + ) + self.${id}.set_update_time(${update_time}) + self.${id}.set_y_axis(${ymin}, ${ymax}) + + self.${id}.set_y_label(${ylabel}, ${yunit}) + + self.${id}.enable_tags(${entags}) + self.${id}.set_trigger_mode(${tr_mode}, ${tr_slope}, ${tr_level}, ${tr_delay}, ${tr_chan}, ${tr_tag}) + self.${id}.enable_autoscale(${autoscale}) + self.${id}.enable_grid(${grid}) + self.${id}.enable_axis_labels(${axislabels}) + self.${id}.enable_control_panel(${ctrlpanel}) + self.${id}.enable_stem_plot(${stemplot}) + + % if legend == "False": + self.${id}.disable_legend() + % endif + + labels = [${label1}, ${label2}, ${label3}, ${label4}, ${label5}, + ${label6}, ${label7}, ${label8}, ${label9}, ${label10}] + widths = [${width1}, ${width2}, ${width3}, ${width4}, ${width5}, + ${width6}, ${width7}, ${width8}, ${width9}, ${width10}] + colors = [${color1}, ${color2}, ${color3}, ${color4}, ${color5}, + ${color6}, ${color7}, ${color8}, ${color9}, ${color10}] + alphas = [${alpha1}, ${alpha2}, ${alpha3}, ${alpha4}, ${alpha5}, + ${alpha6}, ${alpha7}, ${alpha8}, ${alpha9}, ${alpha10}] + styles = [${style1}, ${style2}, ${style3}, ${style4}, ${style5}, + ${style6}, ${style7}, ${style8}, ${style9}, ${style10}] + markers = [${marker1}, ${marker2}, ${marker3}, ${marker4}, ${marker5}, + ${marker6}, ${marker7}, ${marker8}, ${marker9}, ${marker10}] + + + % if type.endswith('complex'): + for i in range(${2 if type.startswith('msg') else 2*int(nconnections)}): + if len(labels[i]) == 0: + if (i % 2 == 0): + self.${id}.set_line_label(i, "Re{{Data {0}}}".format(i/2)) + else: + self.${id}.set_line_label(i, "Im{{Data {0}}}".format(i/2)) + else: + self.${id}.set_line_label(i, labels[i]) + self.${id}.set_line_width(i, widths[i]) + self.${id}.set_line_color(i, colors[i]) + self.${id}.set_line_style(i, styles[i]) + self.${id}.set_line_marker(i, markers[i]) + self.${id}.set_line_alpha(i, alphas[i]) + % else: + for i in range(${1 if type.startswith('msg') else int(nconnections)}): + if len(labels[i]) == 0: + self.${id}.set_line_label(i, "Data {0}".format(i)) + else: + self.${id}.set_line_label(i, labels[i]) + self.${id}.set_line_width(i, widths[i]) + self.${id}.set_line_color(i, colors[i]) + self.${id}.set_line_style(i, styles[i]) + self.${id}.set_line_marker(i, markers[i]) + self.${id}.set_line_alpha(i, alphas[i]) + % endif + + ${win} = sip.wrapinstance(self.${id}.pyqwidget(), Qt.QWidget) + ${gui_hint() % win} + +documentation: |- + The GUI hint can be used to position the widget within the application. The hint is of the form [tab_id@tab_index]: [row, col, row_span, col_span]. Both the tab specification and the grid position are optional. + +file_format: 1 +""" + +def make_yml(): + """Return the YML file as a string""" + default_colors = [ + 'blue', 'red', 'green', 'black', 'cyan', 'magenta', 'yellow', + 'dark red', 'dark green', 'Dark Blue' + ] + line_params_1 = LINE_PARAMS.format(i=1, i_cplx=1, i_color=default_colors[0]) + line_params_1 = re.sub(r' base_key:.*\n', '', line_params_1) + line_params_n = ''.join([ + LINE_PARAMS.format( + i=i, + i_cplx=int(math.ceil(float(i)/2)), + i_color=default_colors[i % len(default_colors)], + ) + for i in range(2, 11) + ]) + return ''.join(( + EVERYTHING_BEFORE_PARAMS, + line_params_1, + line_params_n, + EVERYTHING_AFTER_PARAMS, + )) + + +if __name__ == '__main__': + import sys + try: + filename = sys.argv[1] + except IndexError: + filename = __file__[:-3] + data = make_yml() + with open(filename, 'wb') as fp: + fp.write(data.encode()) + diff --git a/gr-qtgui/grc/qtgui_waterfall_sink_x.block.yml b/gr-qtgui/grc/qtgui_waterfall_sink_x.block.yml index 75fd432a35..add262f507 100644 --- a/gr-qtgui/grc/qtgui_waterfall_sink_x.block.yml +++ b/gr-qtgui/grc/qtgui_waterfall_sink_x.block.yml @@ -237,6 +237,10 @@ inputs: id: freq optional: true hide: ${ showports } +- domain: message + id: bw + optional: true + hide: ${ showports } outputs: - domain: message diff --git a/gr-qtgui/include/gnuradio/qtgui/freq_sink_c.h b/gr-qtgui/include/gnuradio/qtgui/freq_sink_c.h index 0adc85eda9..c96185da54 100644 --- a/gr-qtgui/include/gnuradio/qtgui/freq_sink_c.h +++ b/gr-qtgui/include/gnuradio/qtgui/freq_sink_c.h @@ -62,12 +62,17 @@ namespace gr { * Message Ports: * * - freq (input): - * Receives a PMT pair: (intern("freq"), double(frequency). + * Receives a PMT pair: (intern("freq"), double(frequency)). * This is used to retune the center frequency of the * display's x-axis. + * + * - bw (input): + * Receives a PMT pair: (intern("bw"), double(bandwidth)). + * This is used to programmatically change the bandwidth of + * of the display's x-axis. * * - freq (output): - * Produces a PMT pair with (intern("freq"), double(frequency). + * Produces a PMT pair with (intern("freq"), double(frequency)). * When a user double-clicks on the display, the block * produces and emits a message containing the frequency of * where on the x-axis the user clicked. This value can be diff --git a/gr-qtgui/include/gnuradio/qtgui/freq_sink_f.h b/gr-qtgui/include/gnuradio/qtgui/freq_sink_f.h index 0dc1f7700d..5e621a4f82 100644 --- a/gr-qtgui/include/gnuradio/qtgui/freq_sink_f.h +++ b/gr-qtgui/include/gnuradio/qtgui/freq_sink_f.h @@ -62,12 +62,17 @@ namespace gr { * Message Ports: * * - freq (input): - * Receives a PMT pair: (intern("freq"), double(frequency). + * Receives a PMT pair: (intern("freq"), double(frequency)). * This is used to retune the center frequency of the * display's x-axis. + * + * - bw (input): + * Receives a PMT pair: (intern("bw"), double(bandwidth)). + * This is used to programmatically change the bandwidth of + * of the display's x-axis. * * - freq (output): - * Produces a PMT pair with (intern("freq"), double(frequency). + * Produces a PMT pair with (intern("freq"), double(frequency)). * When a user double-clicks on the display, the block * produces and emits a message containing the frequency of * where on the x-axis the user clicked. This value can be diff --git a/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_c.h b/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_c.h index 8891529753..d90851e602 100644 --- a/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_c.h +++ b/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_c.h @@ -70,7 +70,12 @@ namespace gr { * Receives a PMT pair: (intern("freq"), double(frequency)). * This is used to retune the center frequency of the * display's x-axis. - * + * + * - bw (input): + * Receives a PMT pair: (intern("bw"), double(bandwidth)). + * This is used to programmatically change the bandwidth of + * of the display's x-axis. + * * - freq (output): * Produces a PMT pair with (intern("freq"), double(frequency)). * When a user double-clicks on the display, the block diff --git a/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h b/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h index e8c659cb09..8f4a88db9c 100644 --- a/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h +++ b/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h @@ -68,12 +68,17 @@ namespace gr { * Message Ports: * * - freq (input): - * Receives a PMT pair: (intern("freq"), double(frequency). + * Receives a PMT pair: (intern("freq"), double(frequency)). * This is used to retune the center frequency of the * display's x-axis. + * + * - bw (input): + * Receives a PMT pair: (intern("bw"), double(bandwidth)). + * This is used to programmatically change the bandwidth of + * of the display's x-axis. * * - freq (output): - * Produces a PMT pair with (intern("freq"), double(frequency). + * Produces a PMT pair with (intern("freq"), double(frequency)). * When a user double-clicks on the display, the block * produces and emits a message containing the frequency of * where on the x-axis the user clicked. This value can be diff --git a/gr-qtgui/lib/freq_sink_c_impl.cc b/gr-qtgui/lib/freq_sink_c_impl.cc index 1acbb9d001..36a9fca07d 100644 --- a/gr-qtgui/lib/freq_sink_c_impl.cc +++ b/gr-qtgui/lib/freq_sink_c_impl.cc @@ -64,6 +64,7 @@ namespace gr { d_center_freq(fc), d_bandwidth(bw), d_name(name), d_nconnections(nconnections), d_port(pmt::mp("freq")), + d_port_bw(pmt::mp("bw")), d_parent(parent) { // Required now for Qt; argc must be greater than 0 and argv @@ -74,6 +75,11 @@ namespace gr { d_argv = new char; d_argv[0] = '\0'; + // setup bw input port + message_port_register_in(d_port_bw); + set_msg_handler(d_port_bw, + boost::bind(&freq_sink_c_impl::handle_set_bw, this, _1)); + // setup output message port to post frequency when display is // double-clicked message_port_register_out(d_port); @@ -610,6 +616,19 @@ namespace gr { } void + freq_sink_c_impl::handle_set_bw(pmt::pmt_t msg) + { + if(pmt::is_pair(msg)) { + pmt::pmt_t x = pmt::cdr(msg); + if(pmt::is_real(x)) { + d_bandwidth = pmt::to_double(x); + d_qApplication->postEvent(d_main_gui, + new SetFreqEvent(d_center_freq, d_bandwidth)); + } + } + } + + void freq_sink_c_impl::_gui_update_trigger() { trigger_mode new_trigger_mode = d_main_gui->getTriggerMode(); diff --git a/gr-qtgui/lib/freq_sink_c_impl.h b/gr-qtgui/lib/freq_sink_c_impl.h index d5b32e0cf4..842b525193 100644 --- a/gr-qtgui/lib/freq_sink_c_impl.h +++ b/gr-qtgui/lib/freq_sink_c_impl.h @@ -49,6 +49,7 @@ namespace gr { int d_nconnections; const pmt::pmt_t d_port; + const pmt::pmt_t d_port_bw; bool d_shift; fft::fft_complex *d_fft; @@ -74,6 +75,10 @@ namespace gr { void check_clicked(); void fft(float *data_out, const gr_complex *data_in, int size); + // Handles message input port for setting new bandwidth + // The message is a PMT pair (intern('bw'), double(bw)) + void handle_set_bw(pmt::pmt_t msg); + // Handles message input port for setting new center frequency. // The message is a PMT pair (intern('freq'), double(frequency)). void handle_set_freq(pmt::pmt_t msg); diff --git a/gr-qtgui/lib/freq_sink_f_impl.cc b/gr-qtgui/lib/freq_sink_f_impl.cc index 2b14f02d72..8f4728be0a 100644 --- a/gr-qtgui/lib/freq_sink_f_impl.cc +++ b/gr-qtgui/lib/freq_sink_f_impl.cc @@ -62,8 +62,10 @@ namespace gr { d_fftsize(fftsize), d_fftavg(1.0), d_wintype((filter::firdes::win_type)(wintype)), d_center_freq(fc), d_bandwidth(bw), d_name(name), - d_nconnections(nconnections), d_parent(parent), - d_port(pmt::mp("freq")) + d_nconnections(nconnections), + d_port(pmt::mp("freq")), + d_port_bw(pmt::mp("bw")), + d_parent(parent) { // Required now for Qt; argc must be greater than 0 and argv // must have at least one valid character. Must be valid through @@ -73,6 +75,11 @@ namespace gr { d_argv = new char; d_argv[0] = '\0'; + // setup bw input port + message_port_register_in(d_port_bw); + set_msg_handler(d_port_bw, + boost::bind(&freq_sink_f_impl::handle_set_bw, this, _1)); + // setup output message port to post frequency when display is // double-clicked message_port_register_out(d_port); @@ -614,6 +621,19 @@ namespace gr { } void + freq_sink_f_impl::handle_set_bw(pmt::pmt_t msg) + { + if(pmt::is_pair(msg)) { + pmt::pmt_t x = pmt::cdr(msg); + if(pmt::is_real(x)) { + d_bandwidth = pmt::to_double(x); + d_qApplication->postEvent(d_main_gui, + new SetFreqEvent(d_center_freq, d_bandwidth)); + } + } + } + + void freq_sink_f_impl::_gui_update_trigger() { trigger_mode new_trigger_mode = d_main_gui->getTriggerMode(); diff --git a/gr-qtgui/lib/freq_sink_f_impl.h b/gr-qtgui/lib/freq_sink_f_impl.h index 31fa768b13..9b656f6e57 100644 --- a/gr-qtgui/lib/freq_sink_f_impl.h +++ b/gr-qtgui/lib/freq_sink_f_impl.h @@ -49,6 +49,7 @@ namespace gr { int d_nconnections; const pmt::pmt_t d_port; + const pmt::pmt_t d_port_bw; bool d_shift; fft::fft_complex *d_fft; @@ -74,6 +75,10 @@ namespace gr { void check_clicked(); void fft(float *data_out, const float *data_in, int size); + // Handles message input port for setting new bandwidth + // The message is a PMT pair (intern('bw'), double(bw)) + void handle_set_bw(pmt::pmt_t msg); + // Handles message input port for setting new center frequency. // The message is a PMT pair (intern('freq'), double(frequency)). void handle_set_freq(pmt::pmt_t msg); diff --git a/gr-qtgui/lib/time_sink_c_impl.cc b/gr-qtgui/lib/time_sink_c_impl.cc index ead8764a10..31c17f3a9c 100644 --- a/gr-qtgui/lib/time_sink_c_impl.cc +++ b/gr-qtgui/lib/time_sink_c_impl.cc @@ -127,7 +127,7 @@ namespace gr { bool time_sink_c_impl::check_topology(int ninputs, int noutputs) { - return 2*ninputs == d_nconnections; + return (unsigned int) (2*ninputs) == d_nconnections; } void diff --git a/gr-qtgui/lib/time_sink_f_impl.cc b/gr-qtgui/lib/time_sink_f_impl.cc index 6b32d71e95..4fbd0705f7 100644 --- a/gr-qtgui/lib/time_sink_f_impl.cc +++ b/gr-qtgui/lib/time_sink_f_impl.cc @@ -122,7 +122,7 @@ namespace gr { bool time_sink_f_impl::check_topology(int ninputs, int noutputs) { - return ninputs == d_nconnections; + return (unsigned int)(ninputs) == d_nconnections; } void diff --git a/gr-qtgui/lib/vector_sink_f_impl.cc b/gr-qtgui/lib/vector_sink_f_impl.cc index 705482266e..b1789354b0 100644 --- a/gr-qtgui/lib/vector_sink_f_impl.cc +++ b/gr-qtgui/lib/vector_sink_f_impl.cc @@ -80,9 +80,9 @@ namespace gr { d_vecavg(1.0), d_name(name), d_nconnections(nconnections), + d_port(pmt::mp(MSG_PORT_OUT_XVAL)), d_msg(pmt::mp("x")), - d_parent(parent), - d_port(pmt::mp(MSG_PORT_OUT_XVAL)) + d_parent(parent) { // Required now for Qt; argc must be greater than 0 and argv // must have at least one valid character. Must be valid through @@ -421,7 +421,7 @@ namespace gr { if(gr::high_res_timer_now() - d_last_time > d_update_time) { for(int n = 0; n < d_nconnections; n++) { in = ((const float*)input_items[n]) + d_vlen; - for(int x = 0; x < d_vlen; x++) { + for(unsigned int x = 0; x < d_vlen; x++) { d_magbufs[n][x] = (double)((1.0-d_vecavg)*d_magbufs[n][x] + (d_vecavg)*in[x]); } } diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.cc b/gr-qtgui/lib/waterfall_sink_c_impl.cc index f9a4ad3e5e..8945cda214 100644 --- a/gr-qtgui/lib/waterfall_sink_c_impl.cc +++ b/gr-qtgui/lib/waterfall_sink_c_impl.cc @@ -68,6 +68,7 @@ namespace gr { d_nconnections(nconnections), d_nrows(200), d_port(pmt::mp("freq")), + d_port_bw(pmt::mp("bw")), d_parent(parent) { // Required now for Qt; argc must be greater than 0 and argv @@ -112,6 +113,11 @@ namespace gr { initialize(); + // setup bw input port + message_port_register_in(d_port_bw); + set_msg_handler(d_port_bw, + boost::bind(&waterfall_sink_c_impl::handle_set_bw, this, _1)); + // setup output message port to post frequency when display is // double-clicked message_port_register_out(d_port); @@ -513,6 +519,19 @@ namespace gr { } void + waterfall_sink_c_impl::handle_set_bw(pmt::pmt_t msg) + { + if(pmt::is_pair(msg)) { + pmt::pmt_t x = pmt::cdr(msg); + if(pmt::is_real(x)) { + d_bandwidth = pmt::to_double(x); + d_qApplication->postEvent(d_main_gui, + new SetFreqEvent(d_center_freq, d_bandwidth)); + } + } + } + + void waterfall_sink_c_impl::set_time_per_fft(double t) { d_main_gui->setTimePerFFT(t); diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.h b/gr-qtgui/lib/waterfall_sink_c_impl.h index 5cd65d40a7..e0d421e36b 100644 --- a/gr-qtgui/lib/waterfall_sink_c_impl.h +++ b/gr-qtgui/lib/waterfall_sink_c_impl.h @@ -51,7 +51,8 @@ namespace gr { int d_nrows; const pmt::pmt_t d_port; - + const pmt::pmt_t d_port_bw; + bool d_shift; fft::fft_complex *d_fft; @@ -75,6 +76,10 @@ namespace gr { void check_clicked(); void fft(float *data_out, const gr_complex *data_in, int size); + // Handles message input port for setting new bandwidth + // The message is a PMT pair (intern('bw'), double(bw)) + void handle_set_bw(pmt::pmt_t msg); + // Handles message input port for setting new center frequency. // The message is a PMT pair (intern('freq'), double(frequency)). void handle_set_freq(pmt::pmt_t msg); diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.cc b/gr-qtgui/lib/waterfall_sink_f_impl.cc index 5a5d72ddc9..eb5dcf1822 100644 --- a/gr-qtgui/lib/waterfall_sink_f_impl.cc +++ b/gr-qtgui/lib/waterfall_sink_f_impl.cc @@ -63,8 +63,9 @@ namespace gr { d_wintype((filter::firdes::win_type)(wintype)), d_center_freq(fc), d_bandwidth(bw), d_name(name), d_nconnections(nconnections), d_nrows(200), - d_parent(parent), - d_port(pmt::mp("freq")) + d_port(pmt::mp("freq")), + d_port_bw(pmt::mp("bw")), + d_parent(parent) { // Required now for Qt; argc must be greater than 0 and argv // must have at least one valid character. Must be valid through @@ -108,6 +109,11 @@ namespace gr { initialize(); + // setup bw input port + message_port_register_in(d_port_bw); + set_msg_handler(d_port_bw, + boost::bind(&waterfall_sink_f_impl::handle_set_bw, this, _1)); + // setup output message port to post frequency when display is // double-clicked message_port_register_out(d_port); @@ -517,6 +523,19 @@ namespace gr { } void + waterfall_sink_f_impl::handle_set_bw(pmt::pmt_t msg) + { + if(pmt::is_pair(msg)) { + pmt::pmt_t x = pmt::cdr(msg); + if(pmt::is_real(x)) { + d_bandwidth = pmt::to_double(x); + d_qApplication->postEvent(d_main_gui, + new SetFreqEvent(d_center_freq, d_bandwidth)); + } + } + } + + void waterfall_sink_f_impl::set_time_per_fft(double t) { d_main_gui->setTimePerFFT(t); diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.h b/gr-qtgui/lib/waterfall_sink_f_impl.h index c320c628eb..aca87b187a 100644 --- a/gr-qtgui/lib/waterfall_sink_f_impl.h +++ b/gr-qtgui/lib/waterfall_sink_f_impl.h @@ -51,6 +51,7 @@ namespace gr { int d_nrows; const pmt::pmt_t d_port; + const pmt::pmt_t d_port_bw; bool d_shift; fft::fft_complex *d_fft; @@ -75,6 +76,10 @@ namespace gr { void check_clicked(); void fft(float *data_out, const float *data_in, int size); + // Handles message input port for setting new bandwidth + // The message is a PMT pair (intern('bw'), double(bw)) + void handle_set_bw(pmt::pmt_t msg); + // Handles message input port for setting new center frequency. // The message is a PMT pair (intern('freq'), double(frequency)). void handle_set_freq(pmt::pmt_t msg); diff --git a/gr-trellis/CMakeLists.txt b/gr-trellis/CMakeLists.txt index 2de5c04a0a..af4d94ae66 100644 --- a/gr-trellis/CMakeLists.txt +++ b/gr-trellis/CMakeLists.txt @@ -61,8 +61,10 @@ if(ENABLE_PYTHON) add_subdirectory(python/trellis) add_subdirectory(examples/python) add_subdirectory(examples/grc) - add_subdirectory(grc) endif(ENABLE_PYTHON) +if(ENABLE_GRC) + add_subdirectory(grc) +endif(ENABLE_GRC) ######################################################################## # Create Pkg Config File diff --git a/gr-trellis/include/gnuradio/trellis/interleaver.h b/gr-trellis/include/gnuradio/trellis/interleaver.h index 4dd0beb3a1..9e30c75e95 100644 --- a/gr-trellis/include/gnuradio/trellis/interleaver.h +++ b/gr-trellis/include/gnuradio/trellis/interleaver.h @@ -37,17 +37,17 @@ namespace gr { class TRELLIS_API interleaver { private: - int d_K; + unsigned int d_K; std::vector<int> d_INTER; std::vector<int> d_DEINTER; public: interleaver(); interleaver(const interleaver & INTERLEAVER); - interleaver(int K, const std::vector<int> & INTER); + interleaver(unsigned int K, const std::vector<int> & INTER); interleaver(const char *name); - interleaver(int K, int seed); - int K () const { return d_K; } + interleaver(unsigned int K, int seed); + unsigned int K () const { return d_K; } const std::vector<int> & INTER() const { return d_INTER; } const std::vector<int> & DEINTER() const { return d_DEINTER; } void write_interleaver_txt(std::string filename); diff --git a/gr-trellis/lib/interleaver.cc b/gr-trellis/lib/interleaver.cc index eb7998b8ce..72bb296e5f 100644 --- a/gr-trellis/lib/interleaver.cc +++ b/gr-trellis/lib/interleaver.cc @@ -48,14 +48,14 @@ namespace gr { d_DEINTER=INTERLEAVER.DEINTER(); } - interleaver::interleaver(int K, const std::vector<int> &INTER) + interleaver::interleaver(unsigned int K, const std::vector<int> &INTER) { d_K=K; d_INTER=INTER; d_DEINTER.resize(d_K); // generate DEINTER table - for(int i=0;i<d_K;i++) { + for(unsigned int i = 0; i < d_K; i++) { d_DEINTER[d_INTER[i]]=i; } } @@ -84,16 +84,17 @@ namespace gr { d_INTER.resize(d_K); d_DEINTER.resize(d_K); - for(int i=0;i<d_K;i++) { - if(fscanf(interleaverfile,"%d",&(d_INTER[i])) == EOF) { - if(ferror(interleaverfile) != 0) - throw std::runtime_error("interleaver::interleaver(const char *name): file read error\n"); - } + for (unsigned int i = 0; i < d_K; i++) { + if (fscanf(interleaverfile, "%d", &(d_INTER[i])) == EOF) { + if (ferror(interleaverfile) != 0) + throw std::runtime_error( + "interleaver::interleaver(const char *name): file read error\n"); + } } // generate DEINTER table - for(int i=0;i<d_K;i++) { - d_DEINTER[d_INTER[i]]=i; + for (unsigned int i = 0; i < d_K; i++) { + d_DEINTER[d_INTER[i]] = i; } fclose(interleaverfile); @@ -102,7 +103,7 @@ namespace gr { //###################################################################### //# Generate a random interleaver //###################################################################### - interleaver::interleaver(int K, int seed) + interleaver::interleaver(unsigned int K, int seed) { d_K=K; d_INTER.resize(d_K); @@ -123,13 +124,13 @@ namespace gr { bytes[idx] = *valptr++; } } - for(int i=0;i<d_K;i++) { - d_INTER[i]=i; + for (unsigned int i = 0; i < d_K; i++) { + d_INTER[i] = i; } quicksort_index <int> (tmp,d_INTER,0,d_K-1); // generate DEINTER table - for(int i=0;i<d_K;i++) { + for(unsigned int i=0;i<d_K;i++) { d_DEINTER[d_INTER[i]]=i; } } @@ -151,7 +152,7 @@ namespace gr { } interleaver_fname << d_K << std::endl; interleaver_fname << std::endl; - for(int i=0;i<d_K;i++) + for(unsigned int i=0;i<d_K;i++) interleaver_fname << d_INTER[i] << ' '; interleaver_fname << std::endl; interleaver_fname.close(); diff --git a/gr-uhd/CMakeLists.txt b/gr-uhd/CMakeLists.txt index 74c8159274..e136d4f97f 100644 --- a/gr-uhd/CMakeLists.txt +++ b/gr-uhd/CMakeLists.txt @@ -59,10 +59,12 @@ add_subdirectory(examples/c++) if(ENABLE_PYTHON) add_subdirectory(swig) add_subdirectory(python/uhd) - add_subdirectory(grc) add_subdirectory(apps) add_subdirectory(examples/grc) endif(ENABLE_PYTHON) +if(ENABLE_GRC) + add_subdirectory(grc) +endif(ENABLE_GRC) ######################################################################## # Create Pkg Config File diff --git a/gr-uhd/grc/CMakeLists.txt b/gr-uhd/grc/CMakeLists.txt index 72a6543df3..0f4ef3678a 100644 --- a/gr-uhd/grc/CMakeLists.txt +++ b/gr-uhd/grc/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2011 Free Software Foundation, Inc. +# Copyright 2011,2018 Free Software Foundation, Inc. # # This file is part of GNU Radio # diff --git a/gr-uhd/grc/gen_uhd_usrp_blocks.py b/gr-uhd/grc/gen_uhd_usrp_blocks.py index a969ab95d1..96ba6dbf3f 100644 --- a/gr-uhd/grc/gen_uhd_usrp_blocks.py +++ b/gr-uhd/grc/gen_uhd_usrp_blocks.py @@ -18,6 +18,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ +import sys + MAIN_TMPL = """\ id: uhd_usrp_${sourk} label: 'UHD: USRP ${sourk.title()}' @@ -62,8 +64,8 @@ parameters: - id: sync label: Sync dtype: enum - options: [sync, pc_clock, ''] - option_labels: [unknown PPS, PC Clock, don't sync] + options: [sync, pc_clock, none] + option_labels: [Unknown PPS, PC Clock, No Sync] hide: ${'$'}{ 'none' if sync else 'part'} - id: clock_rate label: Clock Rate (Hz) @@ -112,16 +114,20 @@ inputs: - domain: message id: command optional: true - hide: ${'$'}{hide_cmd_port} -% if sourk == 'sink': -- domain: stream -% else: +% if sourk == 'source': outputs: -- domain: stream % endif +- domain: stream dtype: ${'$'}{type.type} multiplicity: ${'$'}{nchan} +% if sourk == 'sink': + +outputs: +- domain: message + id: async_msgs + optional: true +% endif templates: imports: |- @@ -133,7 +139,7 @@ templates: uhd.stream_args( cpu_format="${'$'}{type}", ${'%'} if otw: - otw_format=${'$'}{otw}, + otw_format="${'$'}{otw}", ${'%'} endif ${'%'} if stream_args: args=${'$'}{stream_args}, @@ -148,6 +154,37 @@ templates: ${'$'}{len_tag_name}, ${'%'} endif ) + % for m in range(max_mboards): + ${'%'} if context.get('num_mboards')() > ${m}: + ${'%'} if context.get('sd_spec${m}')(): + self.${'$'}{id}.set_subdev_spec(${'$'}{${'sd_spec' + str(m)}}, ${m}) + ${'%'} endif + ${'%'} if context.get('time_source${m}')(): + self.${'$'}{id}.set_time_source(${'$'}{${'time_source' + str(m)}}, ${m}) + ${'%'} endif + ${'%'} if context.get('clock_source${m}')(): + self.${'$'}{id}.set_clock_source(${'$'}{${'clock_source' + str(m)}}, ${m}) + ${'%'} endif + ${'%'} endif + % endfor + % for n in range(max_nchan): + ${'%'} if context.get('nchan')() > ${n}: + self.${'$'}{id}.set_center_freq(${'$'}{${'center_freq' + str(n)}}, ${n}) + ${'%'} if bool(eval(context.get('norm_gain' + '${n}')())): + self.${'$'}{id}.set_normalized_gain(${'$'}{${'gain' + str(n)}}, ${n}) + ${'%'} else: + self.${'$'}{id}.set_gain(${'$'}{${'gain' + str(n)}}, ${n}) + ${'%'} endif + self.${'$'}{id}.set_antenna(${'$'}{${'ant' + str(n)}}, ${n}) + ${'%'} if context.get('bw${n}')(): + self.${'$'}{id}.set_bandwidth(${'$'}{${'bw' + str(n)}}, ${n}) + ${'%'} endif + ${'%'} if context.get('show_lo_controls')(): + self.${'$'}{id}.set_lo_source(${'$'}{${'lo_source' + str(n)}}, uhd.ALL_LOS, ${n}) + self.${'$'}{id}.set_lo_export_enabled(${'$'}{${'lo_export' + str(n)}}, uhd.ALL_LOS, ${n}) + ${'%'} endif + ${'%'} endif + % endfor ${'%'} if clock_rate(): self.${'$'}{id}.set_clock_rate(${'$'}{clock_rate}, uhd.ALL_MBOARDS) ${'%'} endif @@ -156,16 +193,18 @@ templates: self.${'$'}{id}.set_time_unknown_pps(uhd.time_spec()) ${'%'} elif sync == 'pc_clock': self.${'$'}{id}.set_time_now(uhd.time_spec(time.time()), uhd.ALL_MBOARDS) + ${'%'} else: + # No synchronization enforced. ${'%'} endif callbacks: - set_samp_rate(${'$'}{samp_rate}) % for n in range(max_nchan): - - set_center_freq(${'center_freq' + str(n)}, ${n}) - - self.${'$'}{id}.set_${'$'}{'normalized_' if norm_gain${n} else ''}gain(gain${n}, ${n}) - - ${'$'}{'set_lo_source(lo_source${n}, uhd.ALL_LOS, ${n})' if show_lo_controls else ''} - - ${'$'}{'set_lo_export_enabled(lo_export${n}, uhd.ALL_LOS, ${n})' if show_lo_controls else ''} - - set_antenna(${'ant' + str(n)}, ${n}) - - set_bandwidth(${'bw' + str(n)}, ${n}) + - set_center_freq(${'$'}{${'center_freq' + str(n)}}, ${n}) + - self.${'$'}{id}.set_${'$'}{'normalized_' if bool(eval(context.get('norm_gain${n}')())) else ''}gain(${'$'}{${'gain' + str(n)}}, ${n}) + - ${'$'}{'set_lo_source(' + lo_source${n} + ', uhd.ALL_LOS, ${n})' if show_lo_controls else ''} + - ${'$'}{'set_lo_export_enabled(' + lo_export${n} + ', uhd.ALL_LOS, ${n})' if show_lo_controls else ''} + - set_antenna(${'$'}{${'ant' + str(n)}}, ${n}) + - set_bandwidth(${'$'}{${'bw' + str(n)}}, ${n}) % endfor @@ -288,7 +327,6 @@ PARAMS_TMPL = """ dtype: real default: '0' hide: ${'$'}{ 'all' if not nchan > ${n} else ('none' if eval('bw' + str(${n})) else 'part')} -% if sourk == 'source': - id: lo_source${n} label: 'Ch${n}: LO Source' category: RF Options @@ -303,6 +341,7 @@ PARAMS_TMPL = """ default: 'False' options: ['True', 'False'] hide: ${'$'}{ 'all' if not nchan > ${n} else ('none' if show_lo_controls else 'all')} +% if sourk == 'source': - id: dc_offs_enb${n} label: 'Ch${n}: Enable DC Offset Correction' category: FE Corrections @@ -318,17 +357,6 @@ PARAMS_TMPL = """ % endif """ -SHOW_CMD_PORT_PARAM = """ -- id: hide_cmd_port - label: Show Command Port - category: Advanced - dtype: enum - default: 'False' - options: ['False', 'True'] - option_labels: ['Yes', 'No'] - hide: part -""" - SHOW_LO_CONTROLS_PARAM = """ - id: show_lo_controls label: Show LO Controls @@ -361,7 +389,6 @@ MAX_NUM_MBOARDS = 8 MAX_NUM_CHANNELS = MAX_NUM_MBOARDS*4 if __name__ == '__main__': - import sys for file in sys.argv[1:]: if file.endswith('source.block.yml'): sourk = 'source' @@ -375,7 +402,6 @@ if __name__ == '__main__': parse_tmpl(PARAMS_TMPL, n=n, sourk=sourk) for n in range(MAX_NUM_CHANNELS) ]) - params += SHOW_CMD_PORT_PARAM params += SHOW_LO_CONTROLS_PARAM if sourk == 'sink': params += TSBTAG_PARAM diff --git a/gr-uhd/lib/usrp_block_impl.cc b/gr-uhd/lib/usrp_block_impl.cc index bbdb347a1f..8fc4a83e73 100644 --- a/gr-uhd/lib/usrp_block_impl.cc +++ b/gr-uhd/lib/usrp_block_impl.cc @@ -132,11 +132,6 @@ usrp_block_impl::usrp_block_impl( _curr_tune_req(stream_args.channels.size(), ::uhd::tune_request_t()), _chans_to_tune(stream_args.channels.size()) { - // TODO remove this when we update UHD - if(stream_args.cpu_format == "fc32") - _type = boost::make_shared< ::uhd::io_type_t >(::uhd::io_type_t::COMPLEX_FLOAT32); - if(stream_args.cpu_format == "sc16") - _type = boost::make_shared< ::uhd::io_type_t >(::uhd::io_type_t::COMPLEX_INT16); _dev = ::uhd::usrp::multi_usrp::make(device_addr); _check_mboard_sensors_locked(); diff --git a/gr-uhd/lib/usrp_block_impl.h b/gr-uhd/lib/usrp_block_impl.h index 75706fbf85..efae28074e 100644 --- a/gr-uhd/lib/usrp_block_impl.h +++ b/gr-uhd/lib/usrp_block_impl.h @@ -33,8 +33,6 @@ namespace gr { namespace uhd { - static const size_t ALL_MBOARDS = ::uhd::usrp::multi_usrp::ALL_MBOARDS; - static const size_t ALL_CHANS = ::uhd::usrp::multi_usrp::ALL_CHANS; static const std::string ALL_GAINS = ::uhd::usrp::multi_usrp::ALL_GAINS; #ifdef UHD_USRP_MULTI_USRP_LO_CONFIG_API @@ -218,7 +216,6 @@ namespace gr { //! Shared pointer to the underlying multi_usrp object ::uhd::usrp::multi_usrp::sptr _dev; ::uhd::stream_args_t _stream_args; - boost::shared_ptr< ::uhd::io_type_t > _type; //! Number of channels (i.e. number of in- or outputs) size_t _nchan; bool _stream_now; diff --git a/gr-uhd/lib/usrp_sink_impl.cc b/gr-uhd/lib/usrp_sink_impl.cc index 2b393443c4..92ff805191 100644 --- a/gr-uhd/lib/usrp_sink_impl.cc +++ b/gr-uhd/lib/usrp_sink_impl.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2010-2016 Free Software Foundation, Inc. + * Copyright 2010-2016,2018 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -47,13 +47,20 @@ namespace gr { io_signature::make(0, 0, 0)), usrp_block_impl(device_addr, stream_args, length_tag_name), _length_tag_key(length_tag_name.empty() ? pmt::PMT_NIL : pmt::string_to_symbol(length_tag_name)), - _nitems_to_send(0) + _nitems_to_send(0), + _async_event_loop_running(true) { + message_port_register_out(ASYNC_MSGS_PORT_KEY); + _async_event_thread = gr::thread::thread([this](){ + this->async_event_loop(); + }); _sample_rate = get_samp_rate(); } usrp_sink_impl::~usrp_sink_impl() { + _async_event_loop_running = false; + _async_event_thread.join(); } ::uhd::dict<std::string, std::string> @@ -702,5 +709,55 @@ namespace gr { #endif /* GR_CTRLPORT */ } + void + usrp_sink_impl::async_event_loop() + { + typedef ::uhd::async_metadata_t md_t; + md_t metadata; + + while(_async_event_loop_running) { + while(!_dev->get_device()->recv_async_msg(metadata, 0.1)) { + if(!_async_event_loop_running){ + return; + } + } + + pmt::pmt_t event_list = pmt::PMT_NIL; + + if(metadata.event_code & md_t::EVENT_CODE_BURST_ACK){ + event_list = pmt::list_add(event_list, BURST_ACK_KEY); + } + if(metadata.event_code & md_t::EVENT_CODE_UNDERFLOW){ + event_list = pmt::list_add(event_list, UNDERFLOW_KEY); + } + if(metadata.event_code & md_t::EVENT_CODE_UNDERFLOW_IN_PACKET){ + event_list = pmt::list_add(event_list, UNDERFLOW_IN_PACKET_KEY); + } + if(metadata.event_code & md_t::EVENT_CODE_SEQ_ERROR){ + event_list = pmt::list_add(event_list, SEQ_ERROR_KEY); + } + if(metadata.event_code & md_t::EVENT_CODE_SEQ_ERROR_IN_BURST){ + event_list = pmt::list_add(event_list, SEQ_ERROR_IN_BURST_KEY); + } + if(metadata.event_code & md_t::EVENT_CODE_TIME_ERROR){ + event_list = pmt::list_add(event_list, TIME_ERROR_KEY); + } + + if(!pmt::eq(event_list, pmt::PMT_NIL)){ + pmt::pmt_t value = pmt::dict_add(pmt::make_dict(), EVENT_CODE_KEY, event_list); + if(metadata.has_time_spec){ + pmt::pmt_t time_spec = pmt::cons( + pmt::from_long(metadata.time_spec.get_full_secs()), + pmt::from_double(metadata.time_spec.get_frac_secs()) + ); + value = pmt::dict_add(value, TIME_SPEC_KEY, time_spec); + } + value = pmt::dict_add(value, CHANNEL_KEY, pmt::from_uint64(metadata.channel)); + pmt::pmt_t msg = pmt::cons(ASYNC_MSG_KEY, value); + message_port_pub(ASYNC_MSGS_PORT_KEY, msg); + } + } + } + } /* namespace uhd */ } /* namespace gr */ diff --git a/gr-uhd/lib/usrp_sink_impl.h b/gr-uhd/lib/usrp_sink_impl.h index 10f55848ec..774baf1f24 100644 --- a/gr-uhd/lib/usrp_sink_impl.h +++ b/gr-uhd/lib/usrp_sink_impl.h @@ -30,6 +30,20 @@ static const pmt::pmt_t TIME_KEY = pmt::string_to_symbol("tx_time"); static const pmt::pmt_t FREQ_KEY = pmt::string_to_symbol("tx_freq"); static const pmt::pmt_t COMMAND_KEY = pmt::string_to_symbol("tx_command"); +//Asynchronous message handling related PMTs +static const pmt::pmt_t ASYNC_MSG_KEY = pmt::string_to_symbol("uhd_async_msg"); +static const pmt::pmt_t CHANNEL_KEY = pmt::string_to_symbol("channel"); +static const pmt::pmt_t TIME_SPEC_KEY = pmt::string_to_symbol("time_spec"); +static const pmt::pmt_t EVENT_CODE_KEY = pmt::string_to_symbol("event_code"); +static const pmt::pmt_t BURST_ACK_KEY = pmt::string_to_symbol("burst_ack"); +static const pmt::pmt_t UNDERFLOW_KEY = pmt::string_to_symbol("underflow"); +static const pmt::pmt_t UNDERFLOW_IN_PACKET_KEY = pmt::string_to_symbol("underflow_in_packet"); +static const pmt::pmt_t SEQ_ERROR_KEY = pmt::string_to_symbol("seq_error"); +static const pmt::pmt_t SEQ_ERROR_IN_BURST_KEY = pmt::string_to_symbol("seq_error_in_burst"); +static const pmt::pmt_t TIME_ERROR_KEY = pmt::string_to_symbol("time_error"); +static const pmt::pmt_t ASYNC_MSGS_PORT_KEY = pmt::string_to_symbol("async_msgs"); + + namespace gr { namespace uhd { @@ -119,6 +133,10 @@ namespace gr { const pmt::pmt_t _length_tag_key; long _nitems_to_send; + //asynchronous messages related stuff + bool _async_event_loop_running; + void async_event_loop(); + gr::thread::thread _async_event_thread; }; } /* namespace uhd */ diff --git a/gr-uhd/python/uhd/__init__.py b/gr-uhd/python/uhd/__init__.py index c5c05ddb2e..d88cd4b32d 100644 --- a/gr-uhd/python/uhd/__init__.py +++ b/gr-uhd/python/uhd/__init__.py @@ -113,7 +113,6 @@ def _prepare_uhd_swig(): kwargs = dict(kwargs) for index, key, cast in ( (0, 'device_addr', device_addr), - (1, 'io_type', io_type), ): if len(args) > index: args[index] = cast(args[index]) diff --git a/gr-uhd/swig/uhd_swig.i b/gr-uhd/swig/uhd_swig.i index 2852447c80..fb9a8e58fb 100644 --- a/gr-uhd/swig/uhd_swig.i +++ b/gr-uhd/swig/uhd_swig.i @@ -79,8 +79,6 @@ %include <uhd/types/device_addr.hpp> -%include <uhd/types/io_type.hpp> - %template(range_vector_t) std::vector<uhd::range_t>; //define before range %include <uhd/types/ranges.hpp> @@ -88,8 +86,6 @@ %include <uhd/types/tune_result.hpp> -%include <uhd/types/io_type.hpp> - %include <uhd/types/time_spec.hpp> %extend uhd::time_spec_t{ diff --git a/gr-utils/python/modtool/gr-newmod/CMakeLists.txt b/gr-utils/python/modtool/gr-newmod/CMakeLists.txt index 0496ceeaa4..e03d787828 100644 --- a/gr-utils/python/modtool/gr-newmod/CMakeLists.txt +++ b/gr-utils/python/modtool/gr-newmod/CMakeLists.txt @@ -190,11 +190,13 @@ add_custom_target(uninstall ######################################################################## add_subdirectory(include/howto) add_subdirectory(lib) -add_subdirectory(swig) -add_subdirectory(python) -add_subdirectory(grc) add_subdirectory(apps) add_subdirectory(docs) +add_subdirectory(swig) +add_subdirectory(python) +if(ENABLE_GRC) + add_subdirectory(grc) +endif(ENABLE_GRC) ######################################################################## # Install cmake search helper for this library diff --git a/gr-video-sdl/CMakeLists.txt b/gr-video-sdl/CMakeLists.txt index a171535c37..4067006dfe 100644 --- a/gr-video-sdl/CMakeLists.txt +++ b/gr-video-sdl/CMakeLists.txt @@ -50,10 +50,12 @@ if(ENABLE_GR_VIDEO_SDL) add_subdirectory(include/gnuradio/video_sdl) add_subdirectory(lib) if(ENABLE_PYTHON) - add_subdirectory(grc) add_subdirectory(swig) add_subdirectory(python/video_sdl) endif(ENABLE_PYTHON) +if(ENABLE_GRC) + add_subdirectory(grc) +endif(ENABLE_GRC) ######################################################################## # Create Pkg Config File diff --git a/gr-vocoder/CMakeLists.txt b/gr-vocoder/CMakeLists.txt index e90ba29727..cab10fdf84 100644 --- a/gr-vocoder/CMakeLists.txt +++ b/gr-vocoder/CMakeLists.txt @@ -80,9 +80,11 @@ add_subdirectory(docs) if(ENABLE_PYTHON) add_subdirectory(swig) add_subdirectory(python/vocoder) - add_subdirectory(grc) add_subdirectory(examples) endif(ENABLE_PYTHON) +if(ENABLE_GRC) + add_subdirectory(grc) +endif(ENABLE_GRC) ######################################################################## # Create Pkg Config File diff --git a/gr-zeromq/CMakeLists.txt b/gr-zeromq/CMakeLists.txt index 1ebd0ff4f5..39977ce45e 100644 --- a/gr-zeromq/CMakeLists.txt +++ b/gr-zeromq/CMakeLists.txt @@ -55,9 +55,11 @@ add_subdirectory(lib) if(ENABLE_PYTHON) add_subdirectory(swig) add_subdirectory(python/zeromq) - add_subdirectory(grc) add_subdirectory(examples) endif(ENABLE_PYTHON) +if(ENABLE_GRC) + add_subdirectory(grc) +endif(ENABLE_GRC) ######################################################################## # Create Pkg Config File diff --git a/gr-zeromq/include/gnuradio/zeromq/pub_msg_sink.h b/gr-zeromq/include/gnuradio/zeromq/pub_msg_sink.h index fb046ca84b..cb79dacc01 100644 --- a/gr-zeromq/include/gnuradio/zeromq/pub_msg_sink.h +++ b/gr-zeromq/include/gnuradio/zeromq/pub_msg_sink.h @@ -52,6 +52,11 @@ namespace gr { * \param timeout Receive timeout in milliseconds, default is 100ms, 1us increments */ static sptr make(char *address, int timeout=100); + + /*! + * \brief Return a std::string of ZMQ_LAST_ENDPOINT from the underlying ZMQ socket. + */ + virtual std::string last_endpoint() = 0; }; } // namespace zeromq diff --git a/gr-zeromq/include/gnuradio/zeromq/pub_sink.h b/gr-zeromq/include/gnuradio/zeromq/pub_sink.h index 3fecc10b59..d6a03c7f89 100644 --- a/gr-zeromq/include/gnuradio/zeromq/pub_sink.h +++ b/gr-zeromq/include/gnuradio/zeromq/pub_sink.h @@ -57,6 +57,11 @@ namespace gr { */ static sptr make(size_t itemsize, size_t vlen, char *address, int timeout=100, bool pass_tags=false, int hwm=-1); + + /*! + * \brief Return a std::string of ZMQ_LAST_ENDPOINT from the underlying ZMQ socket. + */ + virtual std::string last_endpoint() = 0; }; } // namespace zeromq diff --git a/gr-zeromq/include/gnuradio/zeromq/pull_msg_source.h b/gr-zeromq/include/gnuradio/zeromq/pull_msg_source.h index 13857ead5f..a0fe8e880f 100644 --- a/gr-zeromq/include/gnuradio/zeromq/pull_msg_source.h +++ b/gr-zeromq/include/gnuradio/zeromq/pull_msg_source.h @@ -50,6 +50,11 @@ namespace gr { * */ static sptr make(char *address, int timeout=100); + + /*! + * \brief Return a std::string of ZMQ_LAST_ENDPOINT from the underlying ZMQ socket. + */ + virtual std::string last_endpoint() = 0; }; } // namespace zeromq diff --git a/gr-zeromq/include/gnuradio/zeromq/pull_source.h b/gr-zeromq/include/gnuradio/zeromq/pull_source.h index ecfe508b0a..47628cf20d 100644 --- a/gr-zeromq/include/gnuradio/zeromq/pull_source.h +++ b/gr-zeromq/include/gnuradio/zeromq/pull_source.h @@ -54,6 +54,11 @@ namespace gr { */ static sptr make(size_t itemsize, size_t vlen, char *address, int timeout=100, bool pass_tags=false, int hwm=-1); + + /*! + * \brief Return a std::string of ZMQ_LAST_ENDPOINT from the underlying ZMQ socket. + */ + virtual std::string last_endpoint() = 0; }; } // namespace zeromq diff --git a/gr-zeromq/include/gnuradio/zeromq/push_msg_sink.h b/gr-zeromq/include/gnuradio/zeromq/push_msg_sink.h index 941ad549f5..d13ddfe708 100644 --- a/gr-zeromq/include/gnuradio/zeromq/push_msg_sink.h +++ b/gr-zeromq/include/gnuradio/zeromq/push_msg_sink.h @@ -52,6 +52,11 @@ namespace gr { * */ static sptr make(char *address, int timeout=100); + + /*! + * \brief Return a std::string of ZMQ_LAST_ENDPOINT from the underlying ZMQ socket. + */ + virtual std::string last_endpoint() = 0; }; } // namespace zeromq diff --git a/gr-zeromq/include/gnuradio/zeromq/push_sink.h b/gr-zeromq/include/gnuradio/zeromq/push_sink.h index f81dcaa941..3cb52535f9 100644 --- a/gr-zeromq/include/gnuradio/zeromq/push_sink.h +++ b/gr-zeromq/include/gnuradio/zeromq/push_sink.h @@ -58,6 +58,11 @@ namespace gr { */ static sptr make(size_t itemsize, size_t vlen, char *address, int timeout=100, bool pass_tags=false, int hwm=-1); + + /*! + * \brief Return a std::string of ZMQ_LAST_ENDPOINT from the underlying ZMQ socket. + */ + virtual std::string last_endpoint() = 0; }; } // namespace zeromq diff --git a/gr-zeromq/include/gnuradio/zeromq/rep_msg_sink.h b/gr-zeromq/include/gnuradio/zeromq/rep_msg_sink.h index d11550d149..e84964a74b 100644 --- a/gr-zeromq/include/gnuradio/zeromq/rep_msg_sink.h +++ b/gr-zeromq/include/gnuradio/zeromq/rep_msg_sink.h @@ -52,6 +52,11 @@ namespace gr { * */ static sptr make(char *address, int timeout=100); + + /*! + * \brief Return a std::string of ZMQ_LAST_ENDPOINT from the underlying ZMQ socket. + */ + virtual std::string last_endpoint() = 0; }; } // namespace zeromq diff --git a/gr-zeromq/include/gnuradio/zeromq/rep_sink.h b/gr-zeromq/include/gnuradio/zeromq/rep_sink.h index c1d2d370fc..138d0f13da 100644 --- a/gr-zeromq/include/gnuradio/zeromq/rep_sink.h +++ b/gr-zeromq/include/gnuradio/zeromq/rep_sink.h @@ -56,6 +56,11 @@ namespace gr { */ static sptr make(size_t itemsize, size_t vlen, char *address, int timeout=100, bool pass_tags=false, int hwm=-1); + + /*! + * \brief Return a std::string of ZMQ_LAST_ENDPOINT from the underlying ZMQ socket. + */ + virtual std::string last_endpoint() = 0; }; } // namespace zeromq diff --git a/gr-zeromq/include/gnuradio/zeromq/req_msg_source.h b/gr-zeromq/include/gnuradio/zeromq/req_msg_source.h index 28ac9f84f3..80a6ae559e 100644 --- a/gr-zeromq/include/gnuradio/zeromq/req_msg_source.h +++ b/gr-zeromq/include/gnuradio/zeromq/req_msg_source.h @@ -50,6 +50,11 @@ namespace gr { * */ static sptr make(char *address, int timeout=100); + + /*! + * \brief Return a std::string of ZMQ_LAST_ENDPOINT from the underlying ZMQ socket. + */ + virtual std::string last_endpoint() = 0; }; } // namespace zeromq diff --git a/gr-zeromq/include/gnuradio/zeromq/req_source.h b/gr-zeromq/include/gnuradio/zeromq/req_source.h index 103da90f71..dfe3929ebf 100644 --- a/gr-zeromq/include/gnuradio/zeromq/req_source.h +++ b/gr-zeromq/include/gnuradio/zeromq/req_source.h @@ -54,6 +54,11 @@ namespace gr { */ static sptr make(size_t itemsize, size_t vlen, char *address, int timeout=100, bool pass_tags=false, int hwm=-1); + + /*! + * \brief Return a std::string of ZMQ_LAST_ENDPOINT from the underlying ZMQ socket. + */ + virtual std::string last_endpoint() = 0; }; } // namespace zeromq diff --git a/gr-zeromq/include/gnuradio/zeromq/sub_msg_source.h b/gr-zeromq/include/gnuradio/zeromq/sub_msg_source.h index 5c91d1e1ed..ac68e8aa59 100644 --- a/gr-zeromq/include/gnuradio/zeromq/sub_msg_source.h +++ b/gr-zeromq/include/gnuradio/zeromq/sub_msg_source.h @@ -50,6 +50,11 @@ namespace gr { * */ static sptr make(char *address, int timeout=100); + + /*! + * \brief Return a std::string of ZMQ_LAST_ENDPOINT from the underlying ZMQ socket. + */ + virtual std::string last_endpoint() = 0; }; } // namespace zeromq diff --git a/gr-zeromq/include/gnuradio/zeromq/sub_source.h b/gr-zeromq/include/gnuradio/zeromq/sub_source.h index 990c74cabd..874730403f 100644 --- a/gr-zeromq/include/gnuradio/zeromq/sub_source.h +++ b/gr-zeromq/include/gnuradio/zeromq/sub_source.h @@ -54,6 +54,11 @@ namespace gr { */ static sptr make(size_t itemsize, size_t vlen, char *address, int timeout=100, bool pass_tags=false, int hwm=-1); + + /*! + * \brief Return a std::string of ZMQ_LAST_ENDPOINT from the underlying ZMQ socket. + */ + virtual std::string last_endpoint() = 0; }; } // namespace zeromq diff --git a/gr-zeromq/lib/base_impl.cc b/gr-zeromq/lib/base_impl.cc index 20c5d3845d..0465ec3abb 100644 --- a/gr-zeromq/lib/base_impl.cc +++ b/gr-zeromq/lib/base_impl.cc @@ -54,6 +54,15 @@ namespace gr { delete d_context; } + std::string + base_impl::last_endpoint() + { + char addr[256]; + size_t addr_len = sizeof(addr); + d_socket->getsockopt(ZMQ_LAST_ENDPOINT, addr, &addr_len); + return std::string(addr, addr_len-1); + } + base_sink_impl::base_sink_impl(int type, size_t itemsize, size_t vlen, char *address, int timeout, bool pass_tags, int hwm) : base_impl(type, itemsize, vlen, timeout, pass_tags) diff --git a/gr-zeromq/lib/base_impl.h b/gr-zeromq/lib/base_impl.h index ed1695102e..e09e652768 100644 --- a/gr-zeromq/lib/base_impl.h +++ b/gr-zeromq/lib/base_impl.h @@ -37,6 +37,7 @@ namespace gr { virtual ~base_impl(); protected: + std::string last_endpoint(); zmq::context_t *d_context; zmq::socket_t *d_socket; size_t d_vsize; diff --git a/gr-zeromq/lib/pub_msg_sink_impl.h b/gr-zeromq/lib/pub_msg_sink_impl.h index 747ac7ee85..0cedfed482 100644 --- a/gr-zeromq/lib/pub_msg_sink_impl.h +++ b/gr-zeromq/lib/pub_msg_sink_impl.h @@ -41,6 +41,12 @@ namespace gr { ~pub_msg_sink_impl(); void handler(pmt::pmt_t msg); + std::string last_endpoint() override { + char addr[256]; + size_t addr_len = sizeof(addr); + d_socket->getsockopt(ZMQ_LAST_ENDPOINT, addr, &addr_len); + return std::string(addr, addr_len-1); + } }; } // namespace zeromq diff --git a/gr-zeromq/lib/pub_sink_impl.h b/gr-zeromq/lib/pub_sink_impl.h index 8637c3565a..78b5c1e1bd 100644 --- a/gr-zeromq/lib/pub_sink_impl.h +++ b/gr-zeromq/lib/pub_sink_impl.h @@ -39,6 +39,7 @@ namespace gr { int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + std::string last_endpoint() override {return base_sink_impl::last_endpoint();} }; } // namespace zeromq diff --git a/gr-zeromq/lib/pull_msg_source_impl.h b/gr-zeromq/lib/pull_msg_source_impl.h index 972dab5aff..25cd2dee31 100644 --- a/gr-zeromq/lib/pull_msg_source_impl.h +++ b/gr-zeromq/lib/pull_msg_source_impl.h @@ -48,6 +48,13 @@ namespace gr { bool start(); bool stop(); + + std::string last_endpoint() override { + char addr[256]; + size_t addr_len = sizeof(addr); + d_socket->getsockopt(ZMQ_LAST_ENDPOINT, addr, &addr_len); + return std::string(addr, addr_len-1); + } }; } // namespace zeromq diff --git a/gr-zeromq/lib/pull_source_impl.h b/gr-zeromq/lib/pull_source_impl.h index 7d8ab53bd0..c08ab0521b 100644 --- a/gr-zeromq/lib/pull_source_impl.h +++ b/gr-zeromq/lib/pull_source_impl.h @@ -39,6 +39,7 @@ namespace gr { int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + std::string last_endpoint() override {return base_source_impl::last_endpoint();} }; } // namespace zeromq diff --git a/gr-zeromq/lib/push_msg_sink_impl.h b/gr-zeromq/lib/push_msg_sink_impl.h index d669d327cb..0d0503cd55 100644 --- a/gr-zeromq/lib/push_msg_sink_impl.h +++ b/gr-zeromq/lib/push_msg_sink_impl.h @@ -41,6 +41,12 @@ namespace gr { ~push_msg_sink_impl(); void handler(pmt::pmt_t msg); + std::string last_endpoint() override { + char addr[256]; + size_t addr_len = sizeof(addr); + d_socket->getsockopt(ZMQ_LAST_ENDPOINT, addr, &addr_len); + return std::string(addr, addr_len-1); + } }; } // namespace zeromq diff --git a/gr-zeromq/lib/push_sink_impl.h b/gr-zeromq/lib/push_sink_impl.h index 0a5de10787..73480e1047 100644 --- a/gr-zeromq/lib/push_sink_impl.h +++ b/gr-zeromq/lib/push_sink_impl.h @@ -39,6 +39,8 @@ namespace gr { int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + + std::string last_endpoint() override {return base_sink_impl::last_endpoint();} }; } // namespace zeromq diff --git a/gr-zeromq/lib/rep_msg_sink_impl.h b/gr-zeromq/lib/rep_msg_sink_impl.h index a8485304d7..6f788690c9 100644 --- a/gr-zeromq/lib/rep_msg_sink_impl.h +++ b/gr-zeromq/lib/rep_msg_sink_impl.h @@ -48,6 +48,13 @@ namespace gr { bool start(); bool stop(); + + std::string last_endpoint() override { + char addr[256]; + size_t addr_len = sizeof(addr); + d_socket->getsockopt(ZMQ_LAST_ENDPOINT, addr, &addr_len); + return std::string(addr, addr_len-1); + } }; } // namespace zeromq diff --git a/gr-zeromq/lib/rep_sink_impl.h b/gr-zeromq/lib/rep_sink_impl.h index 012fc45e7b..b9451cfeaf 100644 --- a/gr-zeromq/lib/rep_sink_impl.h +++ b/gr-zeromq/lib/rep_sink_impl.h @@ -39,6 +39,7 @@ namespace gr { int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + std::string last_endpoint() override {return base_sink_impl::last_endpoint();} }; } // namespace zeromq diff --git a/gr-zeromq/lib/req_msg_source_impl.h b/gr-zeromq/lib/req_msg_source_impl.h index 322ce4cf51..c9e81efc5d 100644 --- a/gr-zeromq/lib/req_msg_source_impl.h +++ b/gr-zeromq/lib/req_msg_source_impl.h @@ -48,6 +48,13 @@ namespace gr { bool start(); bool stop(); + + std::string last_endpoint() override { + char addr[256]; + size_t addr_len = sizeof(addr); + d_socket->getsockopt(ZMQ_LAST_ENDPOINT, addr, &addr_len); + return std::string(addr, addr_len-1); + } }; } // namespace zeromq diff --git a/gr-zeromq/lib/req_source_impl.h b/gr-zeromq/lib/req_source_impl.h index 8bdbd33459..ec87832518 100644 --- a/gr-zeromq/lib/req_source_impl.h +++ b/gr-zeromq/lib/req_source_impl.h @@ -40,6 +40,7 @@ namespace gr { gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + std::string last_endpoint() override {return base_source_impl::last_endpoint();} private: bool d_req_pending; }; diff --git a/gr-zeromq/lib/sub_msg_source_impl.h b/gr-zeromq/lib/sub_msg_source_impl.h index 4cf85d10ba..f0367c6c70 100644 --- a/gr-zeromq/lib/sub_msg_source_impl.h +++ b/gr-zeromq/lib/sub_msg_source_impl.h @@ -48,6 +48,13 @@ namespace gr { bool start(); bool stop(); + + std::string last_endpoint() override { + char addr[256]; + size_t addr_len = sizeof(addr); + d_socket->getsockopt(ZMQ_LAST_ENDPOINT, addr, &addr_len); + return std::string(addr, addr_len-1); + } }; } // namespace zeromq diff --git a/gr-zeromq/lib/sub_source_impl.h b/gr-zeromq/lib/sub_source_impl.h index 8f82a9ab94..727d76d6a2 100644 --- a/gr-zeromq/lib/sub_source_impl.h +++ b/gr-zeromq/lib/sub_source_impl.h @@ -39,6 +39,8 @@ namespace gr { int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + + std::string last_endpoint() override {return base_source_impl::last_endpoint();} }; } // namespace zeromq diff --git a/gr-zeromq/python/zeromq/qa_zeromq_pub.py b/gr-zeromq/python/zeromq/qa_zeromq_pub.py index 01f32c5e7f..0eb5c86eb4 100644 --- a/gr-zeromq/python/zeromq/qa_zeromq_pub.py +++ b/gr-zeromq/python/zeromq/qa_zeromq_pub.py @@ -40,10 +40,11 @@ class qa_zeromq_pub (gr_unittest.TestCase): self.rx_data = None src_data = list(range(vlen))*100 src = blocks.vector_source_f(src_data, False, vlen) - zeromq_pub_sink = zeromq.pub_sink(gr.sizeof_float, vlen, "tcp://127.0.0.1:5555") + zeromq_pub_sink = zeromq.pub_sink(gr.sizeof_float, vlen, "tcp://127.0.0.1:0") + address = zeromq_pub_sink.last_endpoint() self.tb.connect(src, zeromq_pub_sink) self.probe_manager = zeromq.probe_manager() - self.probe_manager.add_socket("tcp://127.0.0.1:5555", 'float32', self.recv_data) + self.probe_manager.add_socket(address, 'float32', self.recv_data) zmq_pull_t = threading.Thread(target=self.probe_manager.watcher) zmq_pull_t.daemon = True zmq_pull_t.start() diff --git a/gr-zeromq/python/zeromq/qa_zeromq_pubsub.py b/gr-zeromq/python/zeromq/qa_zeromq_pubsub.py index 81b081bde3..94a709bba5 100644 --- a/gr-zeromq/python/zeromq/qa_zeromq_pubsub.py +++ b/gr-zeromq/python/zeromq/qa_zeromq_pubsub.py @@ -40,8 +40,9 @@ class qa_zeromq_pubsub (gr_unittest.TestCase): vlen = 10 src_data = list(range(vlen))*100 src = blocks.vector_source_f(src_data, False, vlen) - zeromq_pub_sink = zeromq.pub_sink(gr.sizeof_float, vlen, "tcp://127.0.0.1:5556", 0) - zeromq_sub_source = zeromq.sub_source(gr.sizeof_float, vlen, "tcp://127.0.0.1:5556", 0) + zeromq_pub_sink = zeromq.pub_sink(gr.sizeof_float, vlen, "tcp://127.0.0.1:0", 0) + address = zeromq_pub_sink.last_endpoint() + zeromq_sub_source = zeromq.sub_source(gr.sizeof_float, vlen, address, 0) sink = blocks.vector_sink_f(vlen) self.send_tb.connect(src, zeromq_pub_sink) self.recv_tb.connect(zeromq_sub_source, sink) diff --git a/gr-zeromq/python/zeromq/qa_zeromq_pushpull.py b/gr-zeromq/python/zeromq/qa_zeromq_pushpull.py index 35e4e2de25..41c937358a 100644 --- a/gr-zeromq/python/zeromq/qa_zeromq_pushpull.py +++ b/gr-zeromq/python/zeromq/qa_zeromq_pushpull.py @@ -38,8 +38,9 @@ class qa_zeromq_pushpull (gr_unittest.TestCase): vlen = 10 src_data = list(range(vlen))*100 src = blocks.vector_source_f(src_data, False, vlen) - zeromq_push_sink = zeromq.push_sink(gr.sizeof_float, vlen, "tcp://127.0.0.1:5557") - zeromq_pull_source = zeromq.pull_source(gr.sizeof_float, vlen, "tcp://127.0.0.1:5557", 0) + zeromq_push_sink = zeromq.push_sink(gr.sizeof_float, vlen, "tcp://127.0.0.1:0") + address = zeromq_push_sink.last_endpoint() + zeromq_pull_source = zeromq.pull_source(gr.sizeof_float, vlen, address, 0) sink = blocks.vector_sink_f(vlen) self.send_tb.connect(src, zeromq_push_sink) self.recv_tb.connect(zeromq_pull_source, sink) diff --git a/gr-zeromq/python/zeromq/qa_zeromq_reqrep.py b/gr-zeromq/python/zeromq/qa_zeromq_reqrep.py index 6f08368577..bbe2904950 100644 --- a/gr-zeromq/python/zeromq/qa_zeromq_reqrep.py +++ b/gr-zeromq/python/zeromq/qa_zeromq_reqrep.py @@ -41,8 +41,9 @@ class qa_zeromq_reqrep (gr_unittest.TestCase): vlen = 10 src_data = list(range(vlen))*100 src = blocks.vector_source_f(src_data, False, vlen) - zeromq_rep_sink = zeromq.rep_sink(gr.sizeof_float, vlen, "tcp://127.0.0.1:5558", 0) - zeromq_req_source = zeromq.req_source(gr.sizeof_float, vlen, "tcp://127.0.0.1:5558", 0) + zeromq_rep_sink = zeromq.rep_sink(gr.sizeof_float, vlen, "tcp://127.0.0.1:0", 0) + address = zeromq_rep_sink.last_endpoint() + zeromq_req_source = zeromq.req_source(gr.sizeof_float, vlen, address, 0) sink = blocks.vector_sink_f(vlen) self.send_tb.connect(src, zeromq_rep_sink) self.recv_tb.connect(zeromq_req_source, sink) diff --git a/gr-zeromq/python/zeromq/qa_zeromq_sub.py b/gr-zeromq/python/zeromq/qa_zeromq_sub.py index 684bb211c0..d3d18eb0dd 100755 --- a/gr-zeromq/python/zeromq/qa_zeromq_sub.py +++ b/gr-zeromq/python/zeromq/qa_zeromq_sub.py @@ -35,7 +35,8 @@ class qa_zeromq_sub (gr_unittest.TestCase): self.tb = gr.top_block () self.zmq_context = zmq.Context() self.pub_socket = self.zmq_context.socket(zmq.PUB) - self.pub_socket.bind("tcp://127.0.0.1:5559") + self.pub_socket.bind("tcp://127.0.0.1:0") + self._address = self.pub_socket.getsockopt(zmq.LAST_ENDPOINT).decode() def tearDown (self): self.pub_socket.close() @@ -45,7 +46,7 @@ class qa_zeromq_sub (gr_unittest.TestCase): def test_001 (self): vlen = 10 src_data = numpy.array(list(range(vlen))*100, 'float32') - zeromq_sub_source = zeromq.sub_source(gr.sizeof_float, vlen, "tcp://127.0.0.1:5559") + zeromq_sub_source = zeromq.sub_source(gr.sizeof_float, vlen, self._address) sink = blocks.vector_sink_f(vlen) self.tb.connect(zeromq_sub_source, sink) @@ -63,7 +64,7 @@ class qa_zeromq_sub (gr_unittest.TestCase): # Construct multipart source data to publish raw_data = [numpy.array(range(vlen), 'float32')*100, numpy.array(range(vlen, 2*vlen), 'float32')*100] src_data = [a.tostring() for a in raw_data] - zeromq_sub_source = zeromq.sub_source(gr.sizeof_float, vlen, "tcp://127.0.0.1:5559") + zeromq_sub_source = zeromq.sub_source(gr.sizeof_float, vlen, self._address) sink = blocks.vector_sink_f(vlen) self.tb.connect(zeromq_sub_source, sink) diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 77c8d4c00d..9e5341bc17 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -45,12 +45,6 @@ GR_PYTHON_CHECK_MODULE_RAW( ) GR_PYTHON_CHECK_MODULE_RAW( - "lxml >= 1.3.6" - "import lxml.etree; assert lxml.etree.LXML_VERSION >= (1, 3, 6, 0)" - LXML_FOUND -) - -GR_PYTHON_CHECK_MODULE_RAW( "pygobject >= 2.28.6" "import gi; assert gi.version_info >= (2, 28, 6)" PYGI_FOUND @@ -90,7 +84,6 @@ if(NOT CMAKE_CROSSCOMPILING) PYTHON_MIN_VER_FOUND PYYAML_FOUND MAKO_FOUND - LXML_FOUND PYGI_FOUND GTK_GI_FOUND CAIRO_GI_FOUND diff --git a/grc/core/FlowGraph.py b/grc/core/FlowGraph.py index 6786bbee30..bf26225e48 100644 --- a/grc/core/FlowGraph.py +++ b/grc/core/FlowGraph.py @@ -191,8 +191,13 @@ class FlowGraph(Element): for expr in self.imports(): try: exec(expr, namespace) + except ImportError: + # We do not have a good way right now to determine if an import is for a + # hier block, these imports will fail as they are not in the search path + # this is ok behavior, unfortunately we could be hiding other import bugs + pass except Exception: - log.exception('Failed to evaluate expression in namespace', exc_info=True) + log.exception('Failed to evaluate import expression "{0}"'.format(expr), exc_info=True) pass for id, expr in self.get_python_modules(): diff --git a/grc/core/ParseXML.py b/grc/core/ParseXML.py deleted file mode 100644 index 430ba5b474..0000000000 --- a/grc/core/ParseXML.py +++ /dev/null @@ -1,185 +0,0 @@ -""" -Copyright 2008, 2015 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion 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 2 -of the License, or (at your option) any later version. - -GNU Radio Companion 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 program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from __future__ import absolute_import - -from lxml import etree - -import six -from six.moves import map - - -xml_failures = {} -etree.set_default_parser(etree.XMLParser(remove_comments=True)) - - -class XMLSyntaxError(Exception): - def __init__(self, error_log): - self._error_log = error_log - xml_failures[error_log.last_error.filename] = error_log - - def __str__(self): - return '\n'.join(map(str, self._error_log.filter_from_errors())) - - -def validate_dtd(xml_file, dtd_file=None): - """ - Validate an xml file against its dtd. - - Args: - xml_file: the xml file - dtd_file: the optional dtd file - @throws Exception validation fails - """ - # Perform parsing, use dtd validation if dtd file is not specified - parser = etree.XMLParser(dtd_validation=not dtd_file) - try: - xml = etree.parse(xml_file, parser=parser) - except etree.LxmlError: - pass - if parser.error_log: - raise XMLSyntaxError(parser.error_log) - - # Perform dtd validation if the dtd file is specified - if not dtd_file: - return - try: - dtd = etree.DTD(dtd_file) - if not dtd.validate(xml.getroot()): - raise XMLSyntaxError(dtd.error_log) - except etree.LxmlError: - raise XMLSyntaxError(dtd.error_log) - - -def from_file(xml_file): - """ - Create nested data from an xml file using the from xml helper. - Also get the grc version information. - - Args: - xml_file: the xml file path - - Returns: - the nested data with grc version information - """ - xml = etree.parse(xml_file) - - tag, nested_data = _from_file(xml.getroot()) - nested_data = {tag: nested_data, '_instructions': {}} - - # Get the embedded instructions and build a dictionary item - xml_instructions = xml.xpath('/processing-instruction()') - for inst in xml_instructions: - if inst.target != 'grc': - continue - nested_data['_instructions'] = dict(inst.attrib) - return nested_data - - -WANT_A_LIST = { - '/block': 'import callback param check sink source'.split(), - '/block/param_tab_order': 'tab'.split(), - '/block/param': 'option'.split(), - '/block/param/option': 'opt'.split(), - '/flow_graph': 'block connection'.split(), - '/flow_graph/block': 'param'.split(), - '/cat': 'cat block'.split(), - '/cat/cat': 'cat block'.split(), - '/cat/cat/cat': 'cat block'.split(), - '/cat/cat/cat/cat': 'cat block'.split(), - '/domain': 'connection'.split(), -} - - -def _from_file(xml, parent_tag=''): - """ - Recursively parse the xml tree into nested data format. - - Args: - xml: the xml tree - - Returns: - the nested data - """ - tag = xml.tag - tag_path = parent_tag + '/' + tag - - if not len(xml): - return tag, xml.text or '' # store empty tags (text is None) as empty string - - nested_data = {} - for elem in xml: - key, value = _from_file(elem, tag_path) - - if key in WANT_A_LIST.get(tag_path, []): - try: - nested_data[key].append(value) - except KeyError: - nested_data[key] = [value] - else: - nested_data[key] = value - - return tag, nested_data - - -def to_file(nested_data, xml_file): - """ - Write to an xml file and insert processing instructions for versioning - - Args: - nested_data: the nested data - xml_file: the xml file path - """ - xml_data = "" - instructions = nested_data.pop('_instructions', None) - # Create the processing instruction from the array - if instructions: - xml_data += etree.tostring(etree.ProcessingInstruction( - 'grc', ' '.join( - "{0}='{1}'".format(*item) for item in six.iteritems(instructions)) - ), xml_declaration=True, pretty_print=True, encoding='utf-8') - xml_data += etree.tostring(_to_file(nested_data)[0], - pretty_print=True, encoding='utf-8') - with open(xml_file, 'wb') as fp: - fp.write(xml_data) - - -def _to_file(nested_data): - """ - Recursively parse the nested data into xml tree format. - - Args: - nested_data: the nested data - - Returns: - the xml tree filled with child nodes - """ - nodes = list() - for key, values in six.iteritems(nested_data): - # Listify the values if not a list - if not isinstance(values, (list, set, tuple)): - values = [values] - for value in values: - node = etree.Element(key) - if isinstance(value, (str, six.text_type)): - node.text = six.text_type(value) - else: - node.extend(_to_file(value)) - nodes.append(node) - return nodes diff --git a/grc/gui/Application.py b/grc/gui/Application.py index 2a42a0b345..698f1f109d 100644 --- a/grc/gui/Application.py +++ b/grc/gui/Application.py @@ -213,10 +213,6 @@ class Application(Gtk.Application): main.update_panel_visibility(main.CONSOLE, Actions.TOGGLE_CONSOLE_WINDOW.get_active()) main.update_panel_visibility(main.VARIABLES, Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR.get_active()) - #if ParseXML.xml_failures: - # Messages.send_xml_errors_if_any(ParseXML.xml_failures) - # Actions.XML_PARSER_ERRORS_DISPLAY.set_enabled(True) - # Force an update on the current page to match loaded preferences. # In the future, change the __init__ order to load preferences first page = main.current_page @@ -264,132 +260,141 @@ class Application(Gtk.Application): flow_graph_update() page.state_cache.save_new_state(flow_graph.export_data()) page.saved = False - ################################################## - # Create heir block - ################################################## + ################################################## + # Create hier block + ################################################## elif action == Actions.BLOCK_CREATE_HIER: - # keeping track of coordinates for pasting later - coords = flow_graph.selected_blocks()[0].coordinate - x,y = coords - x_min = x - y_min = y - - pads = []; - params = []; - - # Save the state of the leaf blocks - for block in flow_graph.selected_blocks(): - - # Check for string variables within the blocks - for param in block.params.values(): - for variable in flow_graph.get_variables(): - # If a block parameter exists that is a variable, create a parameter for it - if param.get_value() == variable.name: - params.append(param.get_value()) - for flow_param in flow_graph.get_parameters(): - # If a block parameter exists that is a parameter, create a parameter for it - if param.get_value() == flow_param.name: - params.append(param.get_value()) - - - # keep track of x,y mins for pasting later - (x,y) = block.coordinate - if x < x_min: - x_min = x - if y < y_min: - y_min = y - - for connection in block.connections: - - # Get id of connected blocks - source_id = connection.source_block.name - sink_id = connection.sink_block.name - - # If connected block is not in the list of selected blocks create a pad for it - if flow_graph.get_block(source_id) not in flow_graph.selected_blocks(): - pads.append({'key': connection.sink_port.key, 'coord': connection.source_port.coordinate, 'block_id' : block.name, 'direction': 'source'}) - - if flow_graph.get_block(sink_id) not in flow_graph.selected_blocks(): - pads.append({'key': connection.source_port.key, 'coord': connection.sink_port.coordinate, 'block_id' : block.name, 'direction': 'sink'}) - - - # Copy the selected blocks and paste them into a new page - # then move the flowgraph to a reasonable position - Actions.BLOCK_COPY() - main.new_page() - Actions.BLOCK_PASTE() - coords = (x_min,y_min) - flow_graph.move_selected(coords) + # keeping track of coordinates for pasting later + coords = flow_graph.selected_blocks()[0].coordinate + x,y = coords + x_min = x + y_min = y + + pads = [] + params = [] + + # Save the state of the leaf blocks + for block in flow_graph.selected_blocks(): + + # Check for string variables within the blocks + for param in block.params.values(): + for variable in flow_graph.get_variables(): + # If a block parameter exists that is a variable, create a parameter for it + if param.get_value() == variable.name: + params.append(param.get_value()) + for flow_param in flow_graph.get_parameters(): + # If a block parameter exists that is a parameter, create a parameter for it + if param.get_value() == flow_param.name: + params.append(param.get_value()) + + # keep track of x,y mins for pasting later + (x,y) = block.coordinate + if x < x_min: + x_min = x + if y < y_min: + y_min = y + + for connection in block.connections: + + # Get id of connected blocks + source_id = connection.source_block.name + sink_id = connection.sink_block.name + + # If connected block is not in the list of selected blocks create a pad for it + if flow_graph.get_block( + source_id) not in flow_graph.selected_blocks(): + pads.append({ + 'key': + connection.sink_port.key, + 'coord': + connection.source_port.coordinate, + 'block_id': + block.name, + 'direction': + 'source' + }) + + if flow_graph.get_block(sink_id) not in flow_graph.selected_blocks(): + pads.append({'key': connection.source_port.key, 'coord': connection.sink_port.coordinate, 'block_id' : block.name, 'direction': 'sink'}) + + + # Copy the selected blocks and paste them into a new page + # then move the flowgraph to a reasonable position + Actions.BLOCK_COPY() + main.new_page() + Actions.BLOCK_PASTE() + coords = (x_min,y_min) + flow_graph.move_selected(coords) - # Set flow graph to heir block type - top_block = flow_graph.get_block("top_block") - top_block.params['generate_options'].set_value('hb') + # Set flow graph to heir block type + top_block = flow_graph.get_block("top_block") + top_block.params['generate_options'].set_value('hb') - # this needs to be a unique name - top_block.params['id'].set_value('new_heir') + # this needs to be a unique name + top_block.params['id'].set_value('new_heir') - # Remove the default samp_rate variable block that is created - remove_me = flow_graph.get_block("samp_rate") - flow_graph.remove_element(remove_me) + # Remove the default samp_rate variable block that is created + remove_me = flow_graph.get_block("samp_rate") + flow_graph.remove_element(remove_me) - # Add the param blocks along the top of the window - x_pos = 150 - for param in params: - param_id = flow_graph.add_new_block('parameter',(x_pos,10)) - param_block = flow_graph.get_block(param_id) - param_block.params['id'].set_value(param) - x_pos = x_pos + 100 + # Add the param blocks along the top of the window + x_pos = 150 + for param in params: + param_id = flow_graph.add_new_block('parameter',(x_pos,10)) + param_block = flow_graph.get_block(param_id) + param_block.params['id'].set_value(param) + x_pos = x_pos + 100 - for pad in pads: - # Add the pad sources and sinks within the new heir block - if pad['direction'] == 'sink': + for pad in pads: + # Add the pad sources and sinks within the new heir block + if pad['direction'] == 'sink': - # Add new PAD_SINK block to the canvas - pad_id = flow_graph.add_new_block('pad_sink', pad['coord']) + # Add new PAD_SINK block to the canvas + pad_id = flow_graph.add_new_block('pad_sink', pad['coord']) - # setup the references to the sink and source - pad_block = flow_graph.get_block(pad_id) - pad_sink = pad_block.sinks[0] + # setup the references to the sink and source + pad_block = flow_graph.get_block(pad_id) + pad_sink = pad_block.sinks[0] - source_block = flow_graph.get_block(pad['block_id']) - source = source_block.get_source(pad['key']) + source_block = flow_graph.get_block(pad['block_id']) + source = source_block.get_source(pad['key']) - # Ensure the port types match - while pad_sink.dtype != source.dtype: + # Ensure the port types match + while pad_sink.dtype != source.dtype: - # Special case for some blocks that have non-standard type names, e.g. uhd - if pad_sink.dtype == 'complex' and source.dtype == 'fc32': - break; - pad_block.type_controller_modify(1) + # Special case for some blocks that have non-standard type names, e.g. uhd + if pad_sink.dtype == 'complex' and source.dtype == 'fc32': + break; + pad_block.type_controller_modify(1) - # Connect the pad to the proper sinks - new_connection = flow_graph.connect(source,pad_sink) + # Connect the pad to the proper sinks + new_connection = flow_graph.connect(source,pad_sink) - elif pad['direction'] == 'source': - pad_id = flow_graph.add_new_block('pad_source', pad['coord']) + elif pad['direction'] == 'source': + pad_id = flow_graph.add_new_block('pad_source', pad['coord']) - # setup the references to the sink and source - pad_block = flow_graph.get_block(pad_id) - pad_source = pad_block.sources[0] + # setup the references to the sink and source + pad_block = flow_graph.get_block(pad_id) + pad_source = pad_block.sources[0] - sink_block = flow_graph.get_block(pad['block_id']) - sink = sink_block.get_sink(pad['key']) + sink_block = flow_graph.get_block(pad['block_id']) + sink = sink_block.get_sink(pad['key']) - # Ensure the port types match - while sink.dtype != pad_source.dtype: - # Special case for some blocks that have non-standard type names, e.g. uhd - if pad_source.dtype == 'complex' and sink.dtype == 'fc32': - break; - pad_block.type_controller_modify(1) + # Ensure the port types match + while sink.dtype != pad_source.dtype: + # Special case for some blocks that have non-standard type names, e.g. uhd + if pad_source.dtype == 'complex' and sink.dtype == 'fc32': + break + pad_block.type_controller_modify(1) - # Connect the pad to the proper sinks - new_connection = flow_graph.connect(pad_source,sink) + # Connect the pad to the proper sinks + new_connection = flow_graph.connect(pad_source, sink) - # update the new heir block flow graph - flow_graph_update() + # update the new heir block flow graph + flow_graph_update() ################################################## @@ -575,7 +580,6 @@ class Application(Gtk.Application): # View Parser Errors ################################################## elif action == Actions.XML_PARSER_ERRORS_DISPLAY: - # ParserErrorsDialog(ParseXML.xml_failures).run() pass ################################################## # Undo/Redo @@ -627,7 +631,7 @@ class Application(Gtk.Application): elif action == Actions.FLOW_GRAPH_OPEN_RECENT: file_path = str(args[0])[1:-1] main.new_page(file_path, show=True) - main.tool_bar.refresh_submenus() + main.tool_bar.refresh_submenus() elif action == Actions.FLOW_GRAPH_SAVE: #read-only or undefined file path, do save-as if page.get_read_only() or not page.file_path: @@ -730,8 +734,6 @@ class Application(Gtk.Application): main.btwin.repopulate() #todo: implement parser error dialog for YAML - #Actions.XML_PARSER_ERRORS_DISPLAY.set_enabled(bool(ParseXML.xml_failures)) - #Messages.send_xml_errors_if_any(ParseXML.xml_failures) # Force a redraw of the graph, by getting the current state and re-importing it main.update_pages() diff --git a/tools/clang_format.py b/tools/clang_format.py new file mode 100755 index 0000000000..67c4c16ac1 --- /dev/null +++ b/tools/clang_format.py @@ -0,0 +1,826 @@ +#!/usr/bin/env python +# Copyright (C) 2015,2016 MongoDB Inc. +# Copyright (C) 2018 Free Software Foundation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License, version 3, +# as published by the Free Software Foundation. +# +# This program 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +""" +A script that provides: +1. Validates clang-format is the right version. +2. Has support for checking which files are to be checked. +3. Supports validating and updating a set of files to the right coding style. +""" +from __future__ import print_function, absolute_import + +import queue +import difflib +import glob +import itertools +import os +import re +import subprocess +from subprocess import check_output, CalledProcessError +import sys +import threading +import time +from distutils import spawn +from argparse import ArgumentParser +from multiprocessing import cpu_count + +# Get relative imports to work when +# the package is not installed on the PYTHONPATH. +if __name__ == "__main__" and __package__ is None: + sys.path.append( + os.path.dirname( + os.path.dirname(os.path.abspath(os.path.realpath(__file__))))) + +############################################################################## +# +# Constants for clang-format +# +# + +# Expected version of clang-format +CLANG_FORMAT_VERSION = "4.0.1" +CLANG_FORMAT_SHORT_VERSION = "4.0" + +# Name of clang-format as a binary +CLANG_FORMAT_PROGNAME = "clang-format" +# only valid c/c++ implementations and headers +files_match = re.compile('\\.(h|cc|c)$') + +############################################################################## + + +def callo(args): + """Call a program, and capture its output + """ + return check_output(args).decode('utf-8') + + +class ClangFormat(object): + """Class encapsulates finding a suitable copy of clang-format, + and linting/formating an individual file + """ + + def __init__(self, path): + self.path = None + clang_format_progname_ext = "" + + if sys.platform == "win32": + clang_format_progname_ext += ".exe" + + # Check the clang-format the user specified + if path is not None: + if os.path.isfile(path): + self.path = path + else: + print("WARNING: Could not find clang-format %s" % (path)) + + # Check the users' PATH environment variable now + if self.path is None: + # Check for various versions staring with binaries with version specific suffixes in the + # user's path + programs = [ + CLANG_FORMAT_PROGNAME + "-" + CLANG_FORMAT_VERSION, + CLANG_FORMAT_PROGNAME + "-" + CLANG_FORMAT_SHORT_VERSION, + CLANG_FORMAT_PROGNAME, + ] + + if sys.platform == "win32": + for i in range(len(programs)): + programs[i] += '.exe' + + for program in programs: + self.path = spawn.find_executable(program) + + if self.path: + if not self._validate_version(): + self.path = None + else: + break + + # If Windows, try to grab it from Program Files + # Check both native Program Files and WOW64 version + if sys.platform == "win32": + programfiles = [ + os.environ["ProgramFiles"], + os.environ["ProgramFiles(x86)"], + ] + + for programfile in programfiles: + win32bin = os.path.join(programfile, + "LLVM\\bin\\clang-format.exe") + if os.path.exists(win32bin): + self.path = win32bin + break + + if self.path is None or not os.path.isfile( + self.path) or not self._validate_version(): + print( + "ERROR:clang-format not found in $PATH, please install clang-format " + + CLANG_FORMAT_VERSION) + raise NameError("No suitable clang-format found") + self.print_lock = threading.Lock() + + def _validate_version(self): + """Validate clang-format is the expected version + """ + cf_version = callo([self.path, "--version"]) + + if CLANG_FORMAT_VERSION in cf_version: + return True + + print( + "WARNING: clang-format found in path, but incorrect version found at " + + self.path + " with version: " + cf_version) + + return False + + def _lint(self, file_name, print_diff): + """Check the specified file has the correct format + """ + with open(file_name, 'rb') as original_text: + original_file = original_text.read().decode("utf-8") + + # Get formatted file as clang-format would format the file + formatted_file = callo([self.path, "--style=file", file_name]) + + if original_file != formatted_file: + if print_diff: + original_lines = original_file.splitlines() + formatted_lines = formatted_file.splitlines() + result = difflib.unified_diff(original_lines, formatted_lines) + + # Take a lock to ensure diffs do not get mixed when printed to the screen + with self.print_lock: + print("ERROR: Found diff for " + file_name) + print("To fix formatting errors, run %s --style=file -i %s" + % (self.path, file_name)) + for line in result: + print(line.rstrip()) + + return False + + return True + + def lint(self, file_name): + """Check the specified file has the correct format + """ + return self._lint(file_name, print_diff=True) + + def format(self, file_name): + """Update the format of the specified file + """ + if self._lint(file_name, print_diff=False): + return True + + # Update the file with clang-format + formatted = not subprocess.call( + [self.path, "--style=file", "-i", file_name]) + + # Version 3.8 generates files like foo.cpp~RF83372177.TMP when it formats foo.cpp + # on Windows, we must clean these up + if sys.platform == "win32": + glob_pattern = file_name + "*.TMP" + for fglob in glob.glob(glob_pattern): + os.unlink(fglob) + + return formatted + + +def parallel_process(items, func): + """Run a set of work items to completion + """ + try: + cpus = cpu_count() + except NotImplementedError: + cpus = 1 + + task_queue = queue.Queue() + + # Use a list so that worker function will capture this variable + pp_event = threading.Event() + pp_result = [True] + + def worker(): + """Worker thread to process work items in parallel + """ + while not pp_event.is_set(): + try: + item = task_queue.get_nowait() + except queue.Empty: + # if the queue is empty, exit the worker thread + pp_event.set() + return + + try: + ret = func(item) + finally: + # Tell the queue we finished with the item + task_queue.task_done() + + # Return early if we fail, and signal we are done + if not ret: + # with pp_lock: + # pp_result[0] = False + print("{} failed on item {}".format(func, item)) + + # pp_event.set() + return + + # Enqueue all the work we want to process + for item in items: + task_queue.put(item) + + # Process all the work + threads = [] + for cpu in range(cpus): + thread = threading.Thread(target=worker) + + thread.daemon = True + thread.start() + threads.append(thread) + + # Wait for the threads to finish + # Loop with a timeout so that we can process Ctrl-C interrupts + # Note: On Python 2.6 wait always returns None so we check is_set also, + # This works because we only set the event once, and never reset it + while not pp_event.wait(1) and not pp_event.is_set(): + time.sleep(1) + + for thread in threads: + thread.join() + + return pp_result[0] + + +def get_base_dir(): + """Get the base directory for mongo repo. + This script assumes that it is running in buildscripts/, and uses + that to find the base directory. + """ + try: + return subprocess.check_output( + ['git', 'rev-parse', '--show-toplevel']).rstrip().decode('utf-8') + except CalledProcessError: + # We are not in a valid git directory. Use the script path instead. + return os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + + +def get_repos(): + """Get a list of Repos to check clang-format for + """ + base_dir = get_base_dir() + + # Get a list of modules + # GNU Radio is a single-git repo + + # paths = [os.path.join(base_dir, MODULE_DIR, m) for m in gnuradio_modules] + + paths = [base_dir] + + return [Repo(p) for p in paths] + + +class Repo(object): + """Class encapsulates all knowledge about a git repository, and its metadata + to run clang-format. + """ + + def __init__(self, path): + self.path = path + + self.root = self._get_root() + + def _callgito(self, args): + """Call git for this repository, and return the captured output + """ + # These two flags are the equivalent of -C in newer versions of Git + # but we use these to support versions pre 1.8.5 but it depends on the command + # and what the current directory is + return callo([ + 'git', '--git-dir', os.path.join(self.path, ".git"), '--work-tree', + self.path + ] + args) + + def _callgit(self, args): + """Call git for this repository without capturing output + This is designed to be used when git returns non-zero exit codes. + """ + # These two flags are the equivalent of -C in newer versions of Git + # but we use these to support versions pre 1.8.5 but it depends on the command + # and what the current directory is + return subprocess.call([ + 'git', '--git-dir', os.path.join(self.path, ".git"), '--work-tree', + self.path + ] + args) + + def _get_local_dir(self, path): + """Get a directory path relative to the git root directory + """ + if os.path.isabs(path): + return os.path.relpath(path, self.root) + return path + + def get_candidates(self, candidates): + """Get the set of candidate files to check by querying the repository + + Returns the full path to the file for clang-format to consume. + """ + if candidates is not None and len(candidates) > 0: + candidates = [self._get_local_dir(f) for f in candidates] + valid_files = list( + set(candidates).intersection(self.get_candidate_files())) + else: + valid_files = list(self.get_candidate_files()) + + # Get the full file name here + valid_files = [ + os.path.normpath(os.path.join(self.root, f)) for f in valid_files + ] + + return valid_files + + def get_root(self): + """Get the root directory for this repository + """ + return self.root + + def _get_root(self): + """Gets the root directory for this repository from git + """ + gito = self._callgito(['rev-parse', '--show-toplevel']) + + return gito.rstrip() + + def _git_ls_files(self, cmd): + """Run git-ls-files and filter the list of files to a valid candidate list + """ + gito = self._callgito(cmd) + + # This allows us to pick all the interesting files + # in the mongo and mongo-enterprise repos + file_list = [ + line.rstrip() + for line in gito.splitlines() + # TODO: exclude directories if needed + # We don't want to lint volk + if not "volk" in line + ] + + file_list = [a for a in file_list if files_match.search(a)] + + return file_list + + def get_candidate_files(self): + """Query git to get a list of all files in the repo to consider for analysis + """ + return self._git_ls_files(["ls-files", "--cached"]) + + def get_working_tree_candidate_files(self): + """Query git to get a list of all files in the working tree to consider for analysis + """ + return self._git_ls_files(["ls-files", "--cached", "--others"]) + + def get_working_tree_candidates(self): + """Get the set of candidate files to check by querying the repository + + Returns the full path to the file for clang-format to consume. + """ + valid_files = list(self.get_working_tree_candidate_files()) + + # Get the full file name here + valid_files = [ + os.path.normpath(os.path.join(self.root, f)) for f in valid_files + ] + + return valid_files + + def is_detached(self): + """Is the current working tree in a detached HEAD state? + """ + # symbolic-ref returns 1 if the repo is in a detached HEAD state + return self._callgit(["symbolic-ref", "--quiet", "HEAD"]) + + def is_ancestor(self, parent, child): + """Is the specified parent hash an ancestor of child hash? + """ + # merge base returns 0 if parent is an ancestor of child + return not self._callgit( + ["merge-base", "--is-ancestor", parent, child]) + + def is_commit(self, sha1): + """Is the specified hash a valid git commit? + """ + # cat-file -e returns 0 if it is a valid hash + return not self._callgit(["cat-file", "-e", "%s^{commit}" % sha1]) + + def is_working_tree_dirty(self): + """Does the current working tree have changes? + """ + # diff returns 1 if the working tree has local changes + return self._callgit(["diff", "--quiet"]) + + def does_branch_exist(self, branch): + """Does the branch exist? + """ + # rev-parse returns 0 if the branch exists + return not self._callgit(["rev-parse", "--verify", branch]) + + def get_merge_base(self, commit): + """Get the merge base between 'commit' and HEAD + """ + return self._callgito(["merge-base", "HEAD", commit]).rstrip() + + def get_branch_name(self): + """Get the current branch name, short form + This returns "master", not "refs/head/master" + Will not work if the current branch is detached + """ + branch = self.rev_parse(["--abbrev-ref", "HEAD"]) + if branch == "HEAD": + raise ValueError("Branch is currently detached") + + return branch + + def add(self, command): + """git add wrapper + """ + return self._callgito(["add"] + command) + + def checkout(self, command): + """git checkout wrapper + """ + return self._callgito(["checkout"] + command) + + def commit(self, command): + """git commit wrapper + """ + return self._callgito(["commit"] + command) + + def diff(self, command): + """git diff wrapper + """ + return self._callgito(["diff"] + command) + + def log(self, command): + """git log wrapper + """ + return self._callgito(["log"] + command) + + def rev_parse(self, command): + """git rev-parse wrapper + """ + return self._callgito(["rev-parse"] + command).rstrip() + + def rm(self, command): + """git rm wrapper + """ + return self._callgito(["rm"] + command) + + def show(self, command): + """git show wrapper + """ + return self._callgito(["show"] + command) + + +def get_list_from_lines(lines): + """"Convert a string containing a series of lines into a list of strings + """ + return [line.rstrip() for line in lines.splitlines()] + + +def get_files_to_check_working_tree(): + """Get a list of files to check form the working tree. + This will pick up files not managed by git. + """ + repos = get_repos() + + valid_files = list( + itertools.chain.from_iterable( + [r.get_working_tree_candidates() for r in repos])) + return valid_files + + +def get_files_to_check(): + """Get a list of files that need to be checked + based on which files are managed by git. + """ + repos = get_repos() + + valid_files = list( + itertools.chain.from_iterable([r.get_candidates(None) for r in repos])) + + return valid_files + + +def get_files_to_check_from_patch(patches): + """ + Take a patch file generated by git diff, + and scan the patch for a list of files to check. + """ + candidates = [] + + # Get a list of candidate_files + check = re.compile( + r"^diff --git a\/([a-z\/\.\-_0-9]+) b\/[a-z\/\.\-_0-9]+") + + candidates = [] + for patch in patches: + if patch == "-": + infile = sys.stdin + else: + infile = open(patch, "rb") + candidates.extend([ + check.match(line).group(1) for line in infile.readlines() + if check.match(line) + ]) + infile.close() + + repos = get_repos() + + valid_files = list( + itertools.chain.from_iterable( + [r.get_candidates(candidates) for r in repos])) + + return valid_files + + +def _lint_files(clang_format, files): + """Lint a list of files with clang-format + """ + try: + clang_format = ClangFormat(clang_format) + except NameError as e: + print(e) + return False + + lint_clean = parallel_process([os.path.abspath(f) for f in files], + clang_format.lint) + + if not lint_clean: + print("ERROR: Code Style does not match coding style") + sys.exit(1) + + +def lint(args): + """Lint files command entry point + """ + if args.patch and args.all: + print("Only specify patch or all, but not both!") + return False + if args.patch: + files = get_files_to_check_from_patch(args.patch) + elif args.all: + files = get_files_to_check_working_tree() + else: + files = get_files_to_check() + + if files: + _lint_files(args.clang_format, files) + + return True + + +def _format_files(clang_format, files): + """Format a list of files with clang-format + """ + try: + clang_format = ClangFormat(clang_format) + except NameError as e: + print(e) + return (False) + + format_clean = parallel_process([os.path.abspath(f) for f in files], + clang_format.format) + + if not format_clean: + print("ERROR: failed to format files") + sys.exit(1) + + +def _reformat_branch(clang_format, commit_prior_to_reformat, + commit_after_reformat): + """Reformat a branch made before a clang-format run + """ + try: + clang_format = ClangFormat(clang_format) + except NameError as e: + print(e) + return False + + if os.getcwd() != get_base_dir(): + raise ValueError("reformat-branch must be run from the repo root") + + repo = Repo(get_base_dir()) + + # Validate that user passes valid commits + if not repo.is_commit(commit_prior_to_reformat): + raise ValueError( + "Commit Prior to Reformat '%s' is not a valid commit in this repo" + % commit_prior_to_reformat) + + if not repo.is_commit(commit_after_reformat): + raise ValueError( + "Commit After Reformat '%s' is not a valid commit in this repo" % + commit_after_reformat) + + if not repo.is_ancestor(commit_prior_to_reformat, commit_after_reformat): + raise ValueError(( + "Commit Prior to Reformat '%s' is not a valid ancestor of Commit After" + + " Reformat '%s' in this repo") % (commit_prior_to_reformat, + commit_after_reformat)) + + # Validate the user is on a local branch that has the right merge base + if repo.is_detached(): + raise ValueError( + "You must not run this script in a detached HEAD state") + + # Validate the user has no pending changes + if repo.is_working_tree_dirty(): + raise ValueError( + "Your working tree has pending changes. You must have a clean working tree before proceeding." + ) + + merge_base = repo.get_merge_base(commit_prior_to_reformat) + + if not merge_base == commit_prior_to_reformat: + raise ValueError( + "Please rebase to '%s' and resolve all conflicts before running this script" + % (commit_prior_to_reformat)) + + # We assume the target branch is master, it could be a different branch if needed for testing + merge_base = repo.get_merge_base("master") + + if not merge_base == commit_prior_to_reformat: + raise ValueError( + "This branch appears to already have advanced too far through the merge process" + ) + + # Everything looks good so lets start going through all the commits + branch_name = repo.get_branch_name() + new_branch = "%s-reformatted" % branch_name + + if repo.does_branch_exist(new_branch): + raise ValueError( + "The branch '%s' already exists. Please delete the branch '%s', or rename the current branch." + % (new_branch, new_branch)) + + commits = get_list_from_lines( + repo.log([ + "--reverse", "--pretty=format:%H", "%s..HEAD" % + commit_prior_to_reformat + ])) + + previous_commit_base = commit_after_reformat + + # Go through all the commits the user made on the local branch and migrate to a new branch + # that is based on post_reformat commits instead + for commit_hash in commits: + repo.checkout(["--quiet", commit_hash]) + + deleted_files = [] + + # Format each of the files by checking out just a single commit from the user's branch + commit_files = get_list_from_lines(repo.diff(["HEAD~", "--name-only"])) + + for commit_file in commit_files: + + # Format each file needed if it was not deleted + if not os.path.exists(commit_file): + print( + "Skipping file '%s' since it has been deleted in commit '%s'" + % (commit_file, commit_hash)) + deleted_files.append(commit_file) + continue + + if files_match.search(commit_file): + clang_format.format(commit_file) + else: + print( + "Skipping file '%s' since it is not a file clang_format should format" + % commit_file) + + # Check if anything needed reformatting, and if so amend the commit + if not repo.is_working_tree_dirty(): + print("Commit %s needed no reformatting" % commit_hash) + else: + repo.commit(["--all", "--amend", "--no-edit"]) + + # Rebase our new commit on top the post-reformat commit + previous_commit = repo.rev_parse(["HEAD"]) + + # Checkout the new branch with the reformatted commits + # Note: we will not name as a branch until we are done with all commits on the local branch + repo.checkout(["--quiet", previous_commit_base]) + + # Copy each file from the reformatted commit on top of the post reformat + diff_files = get_list_from_lines( + repo.diff([ + "%s~..%s" % (previous_commit, previous_commit), "--name-only" + ])) + + for diff_file in diff_files: + # If the file was deleted in the commit we are reformatting, we need to delete it again + if diff_file in deleted_files: + repo.rm([diff_file]) + continue + + if "volk" in diff_file: + continue + # The file has been added or modified, continue as normal + file_contents = repo.show(["%s:%s" % (previous_commit, diff_file)]) + + root_dir = os.path.dirname(diff_file) + if root_dir and not os.path.exists(root_dir): + os.makedirs(root_dir) + + with open(diff_file, "w+") as new_file: + new_file.write(file_contents) + + repo.add([diff_file]) + + # Create a new commit onto clang-formatted branch + repo.commit(["--reuse-message=%s" % previous_commit]) + + previous_commit_base = repo.rev_parse(["HEAD"]) + + # Create a new branch to mark the hashes we have been using + repo.checkout(["-b", new_branch]) + + print("reformat-branch is done running.\n") + print( + "A copy of your branch has been made named '%s', and formatted with clang-format.\n" + % new_branch) + print("The original branch has been left unchanged.") + print("The next step is to rebase the new branch on 'master'.") + + +def format_func(args): + """Format files command entry point + """ + if args.all and args.branch is not None: + print("Only specify branch or all, but not both!") + return False + if not args.branch: + if args.all: + files = get_files_to_check_working_tree() + else: + files = get_files_to_check() + _format_files(args.clang_format, files) + else: + _reformat_branch(args.clang_format, *args.branch) + + +def parse_args(): + """ + Parse commandline arguments + """ + parser = ArgumentParser() + parser.add_argument( + "-c", + "--clang-format", + default="clang-format", + help="clang-format binary") + subparsers = parser.add_subparsers(help="clang-format action", dest="action") + subparsers.required = True + lint_parser = subparsers.add_parser( + "lint", help="Lint-only (no modifications)") + lint_parser.add_argument("-a", "--all", action="store_true") + lint_parser.add_argument("-p", "--patch", help="patch to check") + lint_parser.set_defaults(func=lint) + + format_parser = subparsers.add_parser( + "format", help="Format files in place") + format_parser.add_argument( + "-b", + "--branch", + nargs=2, + default=None, + help="specify the commit hash before the format and after the format has been done" + ) + format_parser.add_argument("-a", "--all", action="store_true") + format_parser.set_defaults(func=format_func) + return parser.parse_args() + + +def main(): + """Main entry point + """ + args = parse_args() + if hasattr(args, "func"): + args.func(args) + + +if __name__ == "__main__": + main() |