diff options
Diffstat (limited to 'gr-digital/python')
-rw-r--r-- | gr-digital/python/generic_mod_demod.py | 24 | ||||
-rwxr-xr-x | gr-digital/python/qa_bytes_to_syms.py | 51 | ||||
-rwxr-xr-x | gr-digital/python/qa_chunks_to_symbols.py | 140 | ||||
-rwxr-xr-x | gr-digital/python/qa_correlate_access_code.py | 21 | ||||
-rwxr-xr-x | gr-digital/python/qa_diff_encoder.py | 87 | ||||
-rwxr-xr-x | gr-digital/python/qa_diff_phasor_cc.py | 49 | ||||
-rwxr-xr-x | gr-digital/python/qa_framer_sink.py | 98 | ||||
-rwxr-xr-x | gr-digital/python/qa_glfsr_source.py | 95 | ||||
-rwxr-xr-x | gr-digital/python/qa_map.py | 60 | ||||
-rwxr-xr-x | gr-digital/python/qa_pfb_clock_sync.py | 142 | ||||
-rwxr-xr-x | gr-digital/python/qa_pn_correlator_cc.py | 51 | ||||
-rwxr-xr-x | gr-digital/python/qa_probe_density.py | 71 | ||||
-rwxr-xr-x | gr-digital/python/qa_scrambler.py | 65 | ||||
-rwxr-xr-x | gr-digital/python/qa_simple_framer.py | 59 |
14 files changed, 998 insertions, 15 deletions
diff --git a/gr-digital/python/generic_mod_demod.py b/gr-digital/python/generic_mod_demod.py index ae876e108..a6c4f3445 100644 --- a/gr-digital/python/generic_mod_demod.py +++ b/gr-digital/python/generic_mod_demod.py @@ -28,7 +28,7 @@ Generic modulation and demodulation. from gnuradio import gr from modulation_utils import extract_kwargs_from_options_for_class from utils import mod_codes -import digital_swig +import digital_swig as digital import math # default values (used in __init__ and add_options) @@ -121,12 +121,12 @@ class generic_mod(gr.hier_block2): gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST) if gray_coded == True: - self.symbol_mapper = gr.map_bb(self._constellation.pre_diff_code()) + self.symbol_mapper = digital.map_bb(self._constellation.pre_diff_code()) if differential: - self.diffenc = gr.diff_encoder_bb(arity) + self.diffenc = digital.diff_encoder_bb(arity) - self.chunks2symbols = gr.chunks_to_symbols_bc(self._constellation.points()) + self.chunks2symbols = digital.chunks_to_symbols_bc(self._constellation.points()) # pulse shaping filter nfilts = 32 @@ -269,28 +269,28 @@ class generic_demod(gr.hier_block2): # Frequency correction fll_ntaps = 55 - self.freq_recov = digital_swig.fll_band_edge_cc(self._samples_per_symbol, self._excess_bw, - fll_ntaps, self._freq_bw) + self.freq_recov = digital.fll_band_edge_cc(self._samples_per_symbol, self._excess_bw, + fll_ntaps, self._freq_bw) # symbol timing recovery with RRC data filter taps = gr.firdes.root_raised_cosine(nfilts, nfilts*self._samples_per_symbol, 1.0, self._excess_bw, ntaps) - self.time_recov = gr.pfb_clock_sync_ccf(self._samples_per_symbol, - self._timing_bw, taps, - nfilts, nfilts//2, self._timing_max_dev) + self.time_recov = digital.pfb_clock_sync_ccf(self._samples_per_symbol, + self._timing_bw, taps, + nfilts, nfilts//2, self._timing_max_dev) fmin = -0.25 fmax = 0.25 - self.receiver = digital_swig.constellation_receiver_cb( + self.receiver = digital.constellation_receiver_cb( self._constellation, self._phase_bw, fmin, fmax) # Do differential decoding based on phase change of symbols if differential: - self.diffdec = gr.diff_decoder_bb(arity) + self.diffdec = digital.diff_decoder_bb(arity) if gray_coded: - self.symbol_mapper = gr.map_bb( + self.symbol_mapper = digital.map_bb( mod_codes.invert_code(self._constellation.pre_diff_code())) # unpack the k bit vector into a stream of bits diff --git a/gr-digital/python/qa_bytes_to_syms.py b/gr-digital/python/qa_bytes_to_syms.py new file mode 100755 index 000000000..75475a95b --- /dev/null +++ b/gr-digital/python/qa_bytes_to_syms.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +# +# Copyright 2004,2007,2010,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import digital_swig as digital +import math + +class test_bytes_to_syms (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_bytes_to_syms_001 (self): + src_data = (0x01, 0x80, 0x03) + expected_result = (-1, -1, -1, -1, -1, -1, -1, +1, + +1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, +1, +1) + src = gr.vector_source_b (src_data) + op = digital.bytes_to_syms () + dst = gr.vector_sink_f () + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertEqual (expected_result, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_bytes_to_syms, "test_bytes_to_syms.xml") + diff --git a/gr-digital/python/qa_chunks_to_symbols.py b/gr-digital/python/qa_chunks_to_symbols.py new file mode 100755 index 000000000..63af10d8f --- /dev/null +++ b/gr-digital/python/qa_chunks_to_symbols.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import digital_swig as digital + +class test_chunks_to_symbols(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_bc_001(self): + const = [ 1+0j, 0+1j, + -1+0j, 0-1j] + src_data = (0, 1, 2, 3, 3, 2, 1, 0) + expected_result = (1+0j, 0+1j, -1+0j, 0-1j, + 0-1j, -1+0j, 0+1j, 1+0j) + + src = gr.vector_source_b(src_data) + op = digital.chunks_to_symbols_bc(const) + + dst = gr.vector_sink_c() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + + actual_result = dst.data() + self.assertEqual(expected_result, actual_result) + + def test_bf_002(self): + const = [-3, -1, 1, 3] + src_data = (0, 1, 2, 3, 3, 2, 1, 0) + expected_result = (-3, -1, 1, 3, + 3, 1, -1, -3) + + src = gr.vector_source_b(src_data) + op = digital.chunks_to_symbols_bf(const) + + dst = gr.vector_sink_f() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + + actual_result = dst.data() + self.assertEqual(expected_result, actual_result) + + def test_ic_003(self): + const = [ 1+0j, 0+1j, + -1+0j, 0-1j] + src_data = (0, 1, 2, 3, 3, 2, 1, 0) + expected_result = (1+0j, 0+1j, -1+0j, 0-1j, + 0-1j, -1+0j, 0+1j, 1+0j) + + src = gr.vector_source_i(src_data) + op = digital.chunks_to_symbols_ic(const) + + dst = gr.vector_sink_c() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + + actual_result = dst.data() + self.assertEqual(expected_result, actual_result) + + def test_if_004(self): + const = [-3, -1, 1, 3] + src_data = (0, 1, 2, 3, 3, 2, 1, 0) + expected_result = (-3, -1, 1, 3, + 3, 1, -1, -3) + + src = gr.vector_source_i(src_data) + op = digital.chunks_to_symbols_if(const) + + dst = gr.vector_sink_f() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + + actual_result = dst.data() + self.assertEqual(expected_result, actual_result) + + def test_sc_005(self): + const = [ 1+0j, 0+1j, + -1+0j, 0-1j] + src_data = (0, 1, 2, 3, 3, 2, 1, 0) + expected_result = (1+0j, 0+1j, -1+0j, 0-1j, + 0-1j, -1+0j, 0+1j, 1+0j) + + src = gr.vector_source_s(src_data) + op = digital.chunks_to_symbols_sc(const) + + dst = gr.vector_sink_c() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + + actual_result = dst.data() + self.assertEqual(expected_result, actual_result) + + def test_sf_006(self): + const = [-3, -1, 1, 3] + src_data = (0, 1, 2, 3, 3, 2, 1, 0) + expected_result = (-3, -1, 1, 3, + 3, 1, -1, -3) + + src = gr.vector_source_s(src_data) + op = digital.chunks_to_symbols_sf(const) + + dst = gr.vector_sink_f() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + + actual_result = dst.data() + self.assertEqual(expected_result, actual_result) + +if __name__ == '__main__': + gr_unittest.run(test_chunks_to_symbols, "test_chunks_to_symbols.xml") diff --git a/gr-digital/python/qa_correlate_access_code.py b/gr-digital/python/qa_correlate_access_code.py index 6b6f25051..96246dcfb 100755 --- a/gr-digital/python/qa_correlate_access_code.py +++ b/gr-digital/python/qa_correlate_access_code.py @@ -21,7 +21,7 @@ # from gnuradio import gr, gr_unittest -import digital_swig +import digital_swig as digital import math default_access_code = '\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC' @@ -53,7 +53,7 @@ class test_correlate_access_code(gr_unittest.TestCase): src_data = (1, 0, 1, 1, 1, 1, 0, 1, 1) + pad + (0,) * 7 expected_result = pad + (1, 0, 1, 1, 3, 1, 0, 1, 1, 2) + (0,) * 6 src = gr.vector_source_b (src_data) - op = digital_swig.correlate_access_code_bb("1011", 0) + op = digital.correlate_access_code_bb("1011", 0) dst = gr.vector_sink_b () self.tb.connect (src, op, dst) self.tb.run () @@ -70,13 +70,28 @@ class test_correlate_access_code(gr_unittest.TestCase): src_data = code + (1, 0, 1, 1) + pad expected_result = pad + code + (3, 0, 1, 1) src = gr.vector_source_b (src_data) - op = digital_swig.correlate_access_code_bb(access_code, 0) + op = digital.correlate_access_code_bb(access_code, 0) dst = gr.vector_sink_b () self.tb.connect (src, op, dst) self.tb.run () result_data = dst.data () self.assertEqual (expected_result, result_data) + def test_003(self): + code = tuple(string_to_1_0_list(default_access_code)) + access_code = to_1_0_string(code) + pad = (0,) * 64 + #print code + #print access_code + src_data = code + (1, 0, 1, 1) + pad + expected_result = code + (1, 0, 1, 1) + pad + src = gr.vector_source_b (src_data) + op = digital.correlate_access_code_tag_bb(access_code, 0, "test") + dst = gr.vector_sink_b () + self.tb.connect (src, op, dst) + self.tb.run () + result_data = dst.data () + self.assertEqual (expected_result, result_data) if __name__ == '__main__': diff --git a/gr-digital/python/qa_diff_encoder.py b/gr-digital/python/qa_diff_encoder.py new file mode 100755 index 000000000..e4f5470af --- /dev/null +++ b/gr-digital/python/qa_diff_encoder.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# +# Copyright 2006,2007,2010,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import digital_swig as digital +import math +import random + +def make_random_int_tuple(L, min, max): + result = [] + for x in range(L): + result.append(random.randint(min, max)) + return tuple(result) + + +class test_diff_encoder (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_diff_encdec_000(self): + random.seed(0) + modulus = 2 + src_data = make_random_int_tuple(1000, 0, modulus-1) + expected_result = src_data + src = gr.vector_source_b(src_data) + enc = digital.diff_encoder_bb(modulus) + dec = digital.diff_decoder_bb(modulus) + dst = gr.vector_sink_b() + self.tb.connect(src, enc, dec, dst) + self.tb.run() # run the graph and wait for it to finish + actual_result = dst.data() # fetch the contents of the sink + self.assertEqual(expected_result, actual_result) + + def test_diff_encdec_001(self): + random.seed(0) + modulus = 4 + src_data = make_random_int_tuple(1000, 0, modulus-1) + expected_result = src_data + src = gr.vector_source_b(src_data) + enc = digital.diff_encoder_bb(modulus) + dec = digital.diff_decoder_bb(modulus) + dst = gr.vector_sink_b() + self.tb.connect(src, enc, dec, dst) + self.tb.run() # run the graph and wait for it to finish + actual_result = dst.data() # fetch the contents of the sink + self.assertEqual(expected_result, actual_result) + + def test_diff_encdec_002(self): + random.seed(0) + modulus = 8 + src_data = make_random_int_tuple(40000, 0, modulus-1) + expected_result = src_data + src = gr.vector_source_b(src_data) + enc = digital.diff_encoder_bb(modulus) + dec = digital.diff_decoder_bb(modulus) + dst = gr.vector_sink_b() + self.tb.connect(src, enc, dec, dst) + self.tb.run() # run the graph and wait for it to finish + actual_result = dst.data() # fetch the contents of the sink + self.assertEqual(expected_result, actual_result) + +if __name__ == '__main__': + gr_unittest.run(test_diff_encoder, "test_diff_encoder.xml") + diff --git a/gr-digital/python/qa_diff_phasor_cc.py b/gr-digital/python/qa_diff_phasor_cc.py new file mode 100755 index 000000000..3e7617fe4 --- /dev/null +++ b/gr-digital/python/qa_diff_phasor_cc.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# +# Copyright 2004,2007,2010 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import digital_swig as digital +import math + +class test_diff_phasor (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_diff_phasor_cc (self): + src_data = (0+0j, 1+0j, -1+0j, 3+4j, -3-4j, -3+4j) + expected_result = (0+0j, 0+0j, -1+0j, -3-4j, -25+0j, -7-24j) + src = gr.vector_source_c (src_data) + op = digital.diff_phasor_cc () + dst = gr.vector_sink_c () + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () # run the graph and wait for it to finish + actual_result = dst.data () # fetch the contents of the sink + self.assertComplexTuplesAlmostEqual (expected_result, actual_result) + +if __name__ == '__main__': + gr_unittest.run(test_diff_phasor, "test_diff_phasor.xml") + diff --git a/gr-digital/python/qa_framer_sink.py b/gr-digital/python/qa_framer_sink.py new file mode 100755 index 000000000..bccc86dc7 --- /dev/null +++ b/gr-digital/python/qa_framer_sink.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import digital_swig as digital + +default_access_code = '\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC' + +def string_to_1_0_list(s): + r = [] + for ch in s: + x = ord(ch) + for i in range(8): + t = (x >> i) & 0x1 + r.append(t) + return r + +def to_1_0_string(L): + return ''.join(map(lambda x: chr(x + ord('0')), L)) + +class test_framker_sink(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_001(self): + + code = (1, 1, 0, 1) + access_code = to_1_0_string(code) + header = tuple(2*[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]) # len=1 + pad = (0,) * 100 + src_data = code + header + (0,1,0,0,0,0,0,1) + pad + expected_data = 'A' + + rcvd_pktq = gr.msg_queue() + + src = gr.vector_source_b(src_data) + correlator = digital.correlate_access_code_bb(access_code, 0) + framer_sink = digital.framer_sink_1(rcvd_pktq) + vsnk = gr.vector_sink_b() + + self.tb.connect(src, correlator, framer_sink) + self.tb.connect(correlator, vsnk) + self.tb.run () + + result_data = rcvd_pktq.delete_head() + result_data = result_data.to_string() + self.assertEqual (expected_data, result_data) + + def test_002(self): + + code = tuple(string_to_1_0_list(default_access_code)) + access_code = to_1_0_string(code) + header = tuple(2*[0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0]) # len=2 + pad = (0,) * 100 + src_data = code + header + (0,1,0,0,1,0,0,0) + (0,1,0,0,1,0,0,1) + pad + expected_data = 'HI' + + rcvd_pktq = gr.msg_queue() + + src = gr.vector_source_b(src_data) + correlator = digital.correlate_access_code_bb(access_code, 0) + framer_sink = digital.framer_sink_1(rcvd_pktq) + vsnk = gr.vector_sink_b() + + self.tb.connect(src, correlator, framer_sink) + self.tb.connect(correlator, vsnk) + self.tb.run () + + result_data = rcvd_pktq.delete_head() + result_data = result_data.to_string() + self.assertEqual (expected_data, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_framker_sink, "test_framker_sink.xml") + diff --git a/gr-digital/python/qa_glfsr_source.py b/gr-digital/python/qa_glfsr_source.py new file mode 100755 index 000000000..157520d7f --- /dev/null +++ b/gr-digital/python/qa_glfsr_source.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# +# Copyright 2007,2010,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import digital_swig as digital + +class test_glfsr_source(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_000_make_b(self): + src = digital.glfsr_source_b(16) + self.assertEquals(src.mask(), 0x8016) + self.assertEquals(src.period(), 2**16-1) + + def test_001_degree_b(self): + self.assertRaises(RuntimeError, + lambda: gr.glfsr_source_b(0)) + self.assertRaises(RuntimeError, + lambda: gr.glfsr_source_b(33)) + + def test_002_correlation_b(self): + for degree in range(1,11): # Higher degrees take too long to correlate + src = digital.glfsr_source_b(degree, False) + b2f = digital.chunks_to_symbols_bf((-1.0,1.0), 1) + dst = gr.vector_sink_f() + del self.tb # Discard existing top block + self.tb = gr.top_block() + self.tb.connect(src, b2f, dst) + self.tb.run() + self.tb.disconnect_all() + actual_result = dst.data() + R = auto_correlate(actual_result) + self.assertEqual(R[0], float(len(R))) # Auto-correlation peak at origin + for i in range(len(R)-1): + self.assertEqual(R[i+1], -1.0) # Auto-correlation minimum everywhere else + + def test_003_make_f(self): + src = digital.glfsr_source_f(16) + self.assertEquals(src.mask(), 0x8016) + self.assertEquals(src.period(), 2**16-1) + + def test_004_degree_f(self): + self.assertRaises(RuntimeError, + lambda: gr.glfsr_source_f(0)) + self.assertRaises(RuntimeError, + lambda: gr.glfsr_source_f(33)) + def test_005_correlation_f(self): + for degree in range(1,11): # Higher degrees take too long to correlate + src = digital.glfsr_source_f(degree, False) + dst = gr.vector_sink_f() + del self.tb # Discard existing top block + self.tb = gr.top_block() + self.tb.connect(src, dst) + self.tb.run() + + actual_result = dst.data() + R = auto_correlate(actual_result) + self.assertEqual(R[0], float(len(R))) # Auto-correlation peak at origin + for i in range(len(R)-1): + self.assertEqual(R[i+1], -1.0) # Auto-correlation minimum everywhere else + +def auto_correlate(data): + l = len(data) + R = [0,]*l + for lag in range(l): + for i in range(l): + R[lag] += data[i]*data[i-lag] + return R + +if __name__ == '__main__': + gr_unittest.run(test_glfsr_source, "test_glfsr_source.xml") diff --git a/gr-digital/python/qa_map.py b/gr-digital/python/qa_map.py new file mode 100755 index 000000000..3ad99a2c1 --- /dev/null +++ b/gr-digital/python/qa_map.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import digital_swig as digital + +class test_map(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def helper(self, symbols): + src_data = [0, 1, 2, 3, 0, 1, 2, 3] + expected_data = map(lambda x: symbols[x], src_data) + src = gr.vector_source_b (src_data) + op = digital.map_bb(symbols) + dst = gr.vector_sink_b () + self.tb.connect (src, op, dst) + self.tb.run () + + result_data = list(dst.data()) + self.assertEqual (expected_data, result_data) + + def test_001(self): + symbols = [0, 0, 0, 0] + self.helper(symbols) + + def test_002(self): + symbols = [3, 2, 1, 0] + self.helper(symbols) + + def test_003(self): + symbols = [8-1, 32-1, 128, 256-1] + self.helper(symbols) + +if __name__ == '__main__': + gr_unittest.run(test_map, "test_map.xml") + diff --git a/gr-digital/python/qa_pfb_clock_sync.py b/gr-digital/python/qa_pfb_clock_sync.py new file mode 100755 index 000000000..06c8a60ba --- /dev/null +++ b/gr-digital/python/qa_pfb_clock_sync.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python +# +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import digital_swig as digital +import random, cmath + +class test_pfb_clock_sync(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test01 (self): + # Test BPSK sync + excess_bw = 0.35 + + sps = 4 + loop_bw = cmath.pi/100.0 + nfilts = 32 + init_phase = nfilts/2 + max_rate_deviation = 1.5 + osps = 1 + + ntaps = 11 * int(sps*nfilts) + taps = gr.firdes.root_raised_cosine(nfilts, nfilts*sps, + 1.0, excess_bw, ntaps) + + self.test = digital.pfb_clock_sync_ccf(sps, loop_bw, taps, + nfilts, init_phase, + max_rate_deviation, + osps) + + data = 1000*[complex(1,0), complex(-1,0)] + self.src = gr.vector_source_c(data, False) + + # pulse shaping interpolation filter + rrc_taps = gr.firdes.root_raised_cosine( + nfilts, # gain + nfilts, # sampling rate based on 32 filters in resampler + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + self.rrc_filter = gr.pfb_arb_resampler_ccf(sps, rrc_taps) + + self.snk = gr.vector_sink_c() + + self.tb.connect(self.src, self.rrc_filter, self.test, self.snk) + self.tb.run() + + expected_result = 1000*[complex(-1,0), complex(1,0)] + dst_data = self.snk.data() + + # Only compare last Ncmp samples + Ncmp = 100 + len_e = len(expected_result) + len_d = len(dst_data) + expected_result = expected_result[len_e - Ncmp:] + dst_data = dst_data[len_d - Ncmp:] + + #for e,d in zip(expected_result, dst_data): + # print e, d + + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 1) + + + def test02 (self): + # Test real BPSK sync + excess_bw = 0.35 + + sps = 4 + loop_bw = cmath.pi/100.0 + nfilts = 32 + init_phase = nfilts/2 + max_rate_deviation = 1.5 + osps = 1 + + ntaps = 11 * int(sps*nfilts) + taps = gr.firdes.root_raised_cosine(nfilts, nfilts*sps, + 1.0, excess_bw, ntaps) + + self.test = digital.pfb_clock_sync_fff(sps, loop_bw, taps, + nfilts, init_phase, + max_rate_deviation, + osps) + + data = 1000*[1, -1] + self.src = gr.vector_source_f(data, False) + + # pulse shaping interpolation filter + rrc_taps = gr.firdes.root_raised_cosine( + nfilts, # gain + nfilts, # sampling rate based on 32 filters in resampler + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + self.rrc_filter = gr.pfb_arb_resampler_fff(sps, rrc_taps) + + self.snk = gr.vector_sink_f() + + self.tb.connect(self.src, self.rrc_filter, self.test, self.snk) + self.tb.run() + + expected_result = 1000*[-1, 1] + dst_data = self.snk.data() + + # Only compare last Ncmp samples + Ncmp = 100 + len_e = len(expected_result) + len_d = len(dst_data) + expected_result = expected_result[len_e - Ncmp:] + dst_data = dst_data[len_d - Ncmp:] + + #for e,d in zip(expected_result, dst_data): + # print e, d + + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 1) + + +if __name__ == '__main__': + gr_unittest.run(test_pfb_clock_sync, "test_pfb_clock_sync.xml") diff --git a/gr-digital/python/qa_pn_correlator_cc.py b/gr-digital/python/qa_pn_correlator_cc.py new file mode 100755 index 000000000..377bef5fe --- /dev/null +++ b/gr-digital/python/qa_pn_correlator_cc.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +# +# Copyright 2007,2010,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import digital_swig as digital + +class test_pn_correlator_cc(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block () + + def tearDown(self): + self.tb = None + + def test_000_make(self): + c = digital.pn_correlator_cc(10) + + def test_001_correlate(self): + degree = 10 + length = 2**degree-1 + src = digital.glfsr_source_f(degree) + head = gr.head(gr.sizeof_float, length*length) + f2c = gr.float_to_complex() + corr = digital.pn_correlator_cc(degree) + dst = gr.vector_sink_c() + self.tb.connect(src, head, f2c, corr, dst) + self.tb.run() + data = dst.data() + self.assertEqual(data[-1], (1.0+0j)) + +if __name__ == '__main__': + gr_unittest.run(test_pn_correlator_cc, "test_pn_correlator_cc.xml") diff --git a/gr-digital/python/qa_probe_density.py b/gr-digital/python/qa_probe_density.py new file mode 100755 index 000000000..c5b7e0e7c --- /dev/null +++ b/gr-digital/python/qa_probe_density.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import digital_swig as digital + +class test_probe_density(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_001(self): + src_data = [0, 1, 0, 1] + expected_data = 1 + src = gr.vector_source_b (src_data) + op = digital.probe_density_b(1) + self.tb.connect (src, op) + self.tb.run () + + result_data = op.density() + self.assertEqual (expected_data, result_data) + + + def test_002(self): + src_data = [1, 1, 1, 1] + expected_data = 1 + src = gr.vector_source_b (src_data) + op = digital.probe_density_b(0.01) + self.tb.connect (src, op) + self.tb.run () + + result_data = op.density() + self.assertEqual (expected_data, result_data) + + def test_003(self): + src_data = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1] + expected_data = 0.95243 + src = gr.vector_source_b (src_data) + op = digital.probe_density_b(0.01) + self.tb.connect (src, op) + self.tb.run () + + result_data = op.density() + print result_data + self.assertAlmostEqual (expected_data, result_data, 5) + +if __name__ == '__main__': + gr_unittest.run(test_probe_density, "test_probe_density.xml") + diff --git a/gr-digital/python/qa_scrambler.py b/gr-digital/python/qa_scrambler.py new file mode 100755 index 000000000..f5bd61242 --- /dev/null +++ b/gr-digital/python/qa_scrambler.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# +# Copyright 2008,2010,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import digital_swig as digital + +class test_scrambler(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_scrambler_descrambler(self): + src_data = (1,)*1000 + src = gr.vector_source_b(src_data, False) + scrambler = digital.scrambler_bb(0x8a, 0x7F, 7) # CCSDS 7-bit scrambler + descrambler = digital.descrambler_bb(0x8a, 0x7F, 7) + dst = gr.vector_sink_b() + self.tb.connect(src, scrambler, descrambler, dst) + self.tb.run() + self.assertEqual(tuple(src_data[:-8]), dst.data()[8:]) # skip garbage during synchronization + + def test_additive_scrambler(self): + src_data = (1,)*1000 + src = gr.vector_source_b(src_data, False) + scrambler = digital.additive_scrambler_bb(0x8a, 0x7f, 7) + descrambler = digital.additive_scrambler_bb(0x8a, 0x7f, 7) + dst = gr.vector_sink_b() + self.tb.connect(src, scrambler, descrambler, dst) + self.tb.run() + self.assertEqual(src_data, dst.data()) + + def test_additive_scrambler_reset(self): + src_data = (1,)*1000 + src = gr.vector_source_b(src_data, False) + scrambler = digital.additive_scrambler_bb(0x8a, 0x7f, 7, 100) + descrambler = digital.additive_scrambler_bb(0x8a, 0x7f, 7, 100) + dst = gr.vector_sink_b() + self.tb.connect(src, scrambler, descrambler, dst) + self.tb.run() + self.assertEqual(src_data, dst.data()) + +if __name__ == '__main__': + gr_unittest.run(test_scrambler, "test_scrambler.xml") diff --git a/gr-digital/python/qa_simple_framer.py b/gr-digital/python/qa_simple_framer.py new file mode 100755 index 000000000..09b2d329b --- /dev/null +++ b/gr-digital/python/qa_simple_framer.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# +# Copyright 2004,2007,2010,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import digital_swig as digital +import math + +class test_simple_framer (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_simple_framer_001 (self): + src_data = (0x00, 0x11, 0x22, 0x33, + 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, + 0xcc, 0xdd, 0xee, 0xff) + + expected_result = ( + 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x00, 0x00, 0x11, 0x22, 0x33, 0x55, + 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x01, 0x44, 0x55, 0x66, 0x77, 0x55, + 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x02, 0x88, 0x99, 0xaa, 0xbb, 0x55, + 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x03, 0xcc, 0xdd, 0xee, 0xff, 0x55) + + src = gr.vector_source_b (src_data) + op = digital.simple_framer (4) + dst = gr.vector_sink_b () + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertEqual (expected_result, result_data) + + +if __name__ == '__main__': + gr_unittest.run(test_simple_framer, "test_simple_framer.xml") + |