diff options
Diffstat (limited to 'gr-trellis/src/python')
-rwxr-xr-x | gr-trellis/src/python/qa_trellis.py | 122 | ||||
-rw-r--r-- | gr-trellis/src/python/run_tests.in | 2 |
2 files changed, 97 insertions, 27 deletions
diff --git a/gr-trellis/src/python/qa_trellis.py b/gr-trellis/src/python/qa_trellis.py index cfeefea06..b50679f27 100755 --- a/gr-trellis/src/python/qa_trellis.py +++ b/gr-trellis/src/python/qa_trellis.py @@ -20,46 +20,50 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest +import math + + +from gnuradio import gr, gr_unittest, blks2 +# It's pretty ugly that we can't import trellis from gnuradio in this test +# but because it runs on the non-installed python code it's all a mess. import trellis -class test_trellis (gr_unittest.TestCase): +import os +import digital_swig - def setUp (self): - self.tb = gr.top_block () +fsm_args = {"awgn1o2_4": (2, 4, 4, + (0, 2, 0, 2, 1, 3, 1, 3), + (0, 3, 3, 0, 1, 2, 2, 1), + ), + "rep2": (2, 1, 4, (0, 0), (0, 3)), + "nothing": (2, 1, 2, (0, 0), (0, 1)), + } - def tearDown (self): - self.tb = None +constells = {2: digital_swig.constellation_bpsk(), + 4: digital_swig.constellation_qpsk(), + } + +class test_trellis (gr_unittest.TestCase): def test_001_fsm (self): - I = 2 - S = 4 - O = 4 - NS = (0, 2, 0, 2, 1, 3, 1, 3) - OS = (0, 3, 3, 0, 1, 2, 2, 1) - f = trellis.fsm(I,S,O,NS,OS) - self.assertEqual((I,S,O,NS,OS),(f.I(),f.S(),f.O(),f.NS(),f.OS())) + f = trellis.fsm(*fsm_args["awgn1o2_4"]) + self.assertEqual(fsm_args["awgn1o2_4"],(f.I(),f.S(),f.O(),f.NS(),f.OS())) def test_002_fsm (self): - I = 2 - S = 4 - O = 4 - NS = (0, 2, 0, 2, 1, 3, 1, 3) - OS = (0, 3, 3, 0, 1, 2, 2, 1) - f = trellis.fsm(I,S,O,NS,OS) + f = trellis.fsm(*fsm_args["awgn1o2_4"]) g = trellis.fsm(f) self.assertEqual((g.I(),g.S(),g.O(),g.NS(),g.OS()),(f.I(),f.S(),f.O(),f.NS(),f.OS())) def test_003_fsm (self): - I = 2 - S = 4 - O = 4 - NS = (0, 2, 0, 2, 1, 3, 1, 3) - OS = (0, 3, 3, 0, 1, 2, 2, 1) + # FIXME: no file "awgn1o2_4.fsm" #f = trellis.fsm("awgn1o2_4.fsm") - #self.assertEqual((I,S,O,NS,OS),(f.I(),f.S(),f.O(),f.NS(),f.OS())) - # temporary fix so that make distcheck does not fail on this - self.assertEqual(0,0) + #self.assertEqual(fsm_args["awgn1o2_4"],(f.I(),f.S(),f.O(),f.NS(),f.OS())) + pass + + def test_004_fsm(self): + """ Test to make sure fsm works with a single state fsm.""" + # Just checking that it initializes properly. + f = trellis.fsm(*fsm_args["rep2"]) def test_001_interleaver (self): K = 5 @@ -68,5 +72,69 @@ class test_trellis (gr_unittest.TestCase): i = trellis.interleaver(K,IN) self.assertEqual((K,IN,DIN),(i.K(),i.INTER(),i.DEINTER())) + def test_001_viterbi(self): + """ + Runs some coding/decoding tests with a few different FSM + specs. + """ + for name, args in fsm_args.items(): + constellation = constells[args[2]] + fsms = trellis.fsm(*args) + noise = 0.1 + tb = trellis_tb(constellation, fsms, noise) + tb.run() + # Make sure all packets succesfully transmitted. + self.assertEqual(tb.dst.ntotal(), tb.dst.nright()) + + +class trellis_tb(gr.top_block): + """ + A simple top block for use testing gr-trellis. + """ + def __init__(self, constellation, f, N0=0.25, seed=-666L): + """ + constellation - a constellation object used for modulation. + f - a finite state machine specification used for coding. + N0 - noise level + seed - random seed + """ + super(trellis_tb, self).__init__() + # packet size in bits (make it multiple of 16 so it can be packed in a short) + packet_size = 1024*16 + # bits per FSM input symbol + bitspersymbol = int(round(math.log(f.I())/math.log(2))) # bits per FSM input symbol + # packet size in trellis steps + K = packet_size/bitspersymbol + + # TX + src = gr.lfsr_32k_source_s() + # packet size in shorts + src_head = gr.head (gr.sizeof_short, packet_size/16) + # unpack shorts to symbols compatible with the FSM input cardinality + s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol, gr.GR_MSB_FIRST) + # initial FSM state = 0 + enc = trellis.encoder_ss(f, 0) + mod = gr.chunks_to_symbols_sc(constellation.points(), 1) + + # CHANNEL + add = gr.add_cc() + noise = gr.noise_source_c(gr.GR_GAUSSIAN,math.sqrt(N0/2),seed) + + # RX + # data preprocessing to generate metrics for Viterbi + metrics = trellis.constellation_metrics_cf(constellation.base(), digital_swig.TRELLIS_EUCLIDEAN) + # Put -1 if the Initial/Final states are not set. + va = trellis.viterbi_s(f, K, 0, -1) + # pack FSM input symbols to shorts + fsmi2s = gr.unpacked_to_packed_ss(bitspersymbol, gr.GR_MSB_FIRST) + # check the output + self.dst = gr.check_lfsr_32k_s() + + self.connect (src, src_head, s2fsmi, enc, mod) + self.connect (mod, (add, 0)) + self.connect (noise, (add, 1)) + self.connect (add, metrics, va, fsmi2s, self.dst) + + if __name__ == '__main__': gr_unittest.run(test_trellis, "test_trellis.xml") diff --git a/gr-trellis/src/python/run_tests.in b/gr-trellis/src/python/run_tests.in index 0da3fc1f1..fcb078663 100644 --- a/gr-trellis/src/python/run_tests.in +++ b/gr-trellis/src/python/run_tests.in @@ -4,6 +4,8 @@ # 2nd parameter is absolute path to component build directory # 3rd parameter is path to Python QA directory +PYTHONPATH=@top_builddir@/gr-digital/swig:@top_builddir@/gr-digital/swig/.libs:@top_srcdir@/gr-digital/swig:$PYTHONPATH + @top_builddir@/run_tests.sh \ @abs_top_srcdir@/gr-trellis \ @abs_top_builddir@/gr-trellis \ |