diff options
Diffstat (limited to 'gnuradio-examples/python')
21 files changed, 1380 insertions, 1 deletions
diff --git a/gnuradio-examples/python/Makefile.am b/gnuradio-examples/python/Makefile.am index fa88a980f..ae2c52886 100644 --- a/gnuradio-examples/python/Makefile.am +++ b/gnuradio-examples/python/Makefile.am @@ -19,4 +19,4 @@ # Boston, MA 02111-1307, USA. # -SUBDIRS = audio digital_voice gmsk2 mc4020 multi_usrp usrp +SUBDIRS = audio digital_voice gmsk2 mc4020 multi_usrp usrp channel-coding diff --git a/gnuradio-examples/python/channel-coding/Makefile.am b/gnuradio-examples/python/channel-coding/Makefile.am new file mode 100644 index 000000000..94027dc84 --- /dev/null +++ b/gnuradio-examples/python/channel-coding/Makefile.am @@ -0,0 +1,31 @@ +# +# Copyright 2004 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 2, 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., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +EXTRA_DIST = \ + fsm_utils.py \ + test_tcm.py \ + test_tcm1.py \ + test_tcm_parallel.py \ + test_tcm_combined.py \ + test_sccc_hard.py + + +SUBDIRS = fsm_files diff --git a/gnuradio-examples/python/channel-coding/fsm_files/Makefile.am b/gnuradio-examples/python/channel-coding/fsm_files/Makefile.am new file mode 100644 index 000000000..0a931b660 --- /dev/null +++ b/gnuradio-examples/python/channel-coding/fsm_files/Makefile.am @@ -0,0 +1,33 @@ +# +# Copyright 2004 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 2, 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., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +EXTRA_DIST = \ + awgn1o2_4.fsm \ + awgn1o2_8.fsm \ + awgn1o2_16.fsm \ + awgn1o2_128.fsm \ + awgn2o3_4.fsm \ + awgn2o3_4_1.fsm \ + awgn2o3_16.fsm \ + awgn2o3_8.fsm \ + awgn2o4_4.fsm \ + rep3.fsm \ + rep5.fsm diff --git a/gnuradio-examples/python/channel-coding/fsm_files/awgn1o2_128.fsm b/gnuradio-examples/python/channel-coding/fsm_files/awgn1o2_128.fsm new file mode 100644 index 000000000..9c14d82f3 --- /dev/null +++ b/gnuradio-examples/python/channel-coding/fsm_files/awgn1o2_128.fsm @@ -0,0 +1,264 @@ +2 128 4 + +0 64 +0 64 +1 65 +1 65 +2 66 +2 66 +3 67 +3 67 +4 68 +4 68 +5 69 +5 69 +6 70 +6 70 +7 71 +7 71 +8 72 +8 72 +9 73 +9 73 +10 74 +10 74 +11 75 +11 75 +12 76 +12 76 +13 77 +13 77 +14 78 +14 78 +15 79 +15 79 +16 80 +16 80 +17 81 +17 81 +18 82 +18 82 +19 83 +19 83 +20 84 +20 84 +21 85 +21 85 +22 86 +22 86 +23 87 +23 87 +24 88 +24 88 +25 89 +25 89 +26 90 +26 90 +27 91 +27 91 +28 92 +28 92 +29 93 +29 93 +30 94 +30 94 +31 95 +31 95 +32 96 +32 96 +33 97 +33 97 +34 98 +34 98 +35 99 +35 99 +36 100 +36 100 +37 101 +37 101 +38 102 +38 102 +39 103 +39 103 +40 104 +40 104 +41 105 +41 105 +42 106 +42 106 +43 107 +43 107 +44 108 +44 108 +45 109 +45 109 +46 110 +46 110 +47 111 +47 111 +48 112 +48 112 +49 113 +49 113 +50 114 +50 114 +51 115 +51 115 +52 116 +52 116 +53 117 +53 117 +54 118 +54 118 +55 119 +55 119 +56 120 +56 120 +57 121 +57 121 +58 122 +58 122 +59 123 +59 123 +60 124 +60 124 +61 125 +61 125 +62 126 +62 126 +63 127 +63 127 + +0 3 +3 0 +1 2 +2 1 +3 0 +0 3 +2 1 +1 2 +1 2 +2 1 +0 3 +3 0 +2 1 +1 2 +3 0 +0 3 +1 2 +2 1 +0 3 +3 0 +2 1 +1 2 +3 0 +0 3 +0 3 +3 0 +1 2 +2 1 +3 0 +0 3 +2 1 +1 2 +2 1 +1 2 +3 0 +0 3 +1 2 +2 1 +0 3 +3 0 +3 0 +0 3 +2 1 +1 2 +0 3 +3 0 +1 2 +2 1 +3 0 +0 3 +2 1 +1 2 +0 3 +3 0 +1 2 +2 1 +2 1 +1 2 +3 0 +0 3 +1 2 +2 1 +0 3 +3 0 +2 1 +1 2 +3 0 +0 3 +1 2 +2 1 +0 3 +3 0 +3 0 +0 3 +2 1 +1 2 +0 3 +3 0 +1 2 +2 1 +3 0 +0 3 +2 1 +1 2 +0 3 +3 0 +1 2 +2 1 +2 1 +1 2 +3 0 +0 3 +1 2 +2 1 +0 3 +3 0 +0 3 +3 0 +1 2 +2 1 +3 0 +0 3 +2 1 +1 2 +1 2 +2 1 +0 3 +3 0 +2 1 +1 2 +3 0 +0 3 +1 2 +2 1 +0 3 +3 0 +2 1 +1 2 +3 0 +0 3 +0 3 +3 0 +1 2 +2 1 +3 0 +0 3 +2 1 +1 2 + + + +GM1o2_128=[1+D^3+D^4+D^5+D^6+D^7 1+D+D^2+D^5+D^7] + =[249 167] diff --git a/gnuradio-examples/python/channel-coding/fsm_files/awgn1o2_16.fsm b/gnuradio-examples/python/channel-coding/fsm_files/awgn1o2_16.fsm new file mode 100644 index 000000000..2b000da69 --- /dev/null +++ b/gnuradio-examples/python/channel-coding/fsm_files/awgn1o2_16.fsm @@ -0,0 +1,39 @@ +2 16 4 + +0 8 +0 8 +1 9 +1 9 +2 10 +2 10 +3 11 +3 11 +4 12 +4 12 +5 13 +5 13 +6 14 +6 14 +7 15 +7 15 + +0 3 +3 0 +1 2 +2 1 +1 2 +2 1 +0 3 +3 0 +2 1 +1 2 +3 0 +0 3 +3 0 +0 3 +2 1 +1 2 + + + +GM1o2_16=[1+D^2+D^3+D^4 1+D+D^4]; diff --git a/gnuradio-examples/python/channel-coding/fsm_files/awgn1o2_4.fsm b/gnuradio-examples/python/channel-coding/fsm_files/awgn1o2_4.fsm new file mode 100644 index 000000000..33e5ee315 --- /dev/null +++ b/gnuradio-examples/python/channel-coding/fsm_files/awgn1o2_4.fsm @@ -0,0 +1,17 @@ +2 4 4 + +0 2 +0 2 +1 3 +1 3 + +0 3 +3 0 +1 2 +2 1 + +AWGN CC from Proakis-Salehi pg 779 +GM1o2_4=[1+D+D^2 1+D^2]; + + + diff --git a/gnuradio-examples/python/channel-coding/fsm_files/awgn1o2_8.fsm b/gnuradio-examples/python/channel-coding/fsm_files/awgn1o2_8.fsm new file mode 100644 index 000000000..dd63b1ef5 --- /dev/null +++ b/gnuradio-examples/python/channel-coding/fsm_files/awgn1o2_8.fsm @@ -0,0 +1,24 @@ +2 8 4 + +0 4 +0 4 +1 5 +1 5 +2 6 +2 6 +3 7 +3 7 + + +0 3 +3 0 +1 2 +2 1 +3 0 +0 3 +2 1 +1 2 + + +1/2 8-state code (Proakis pg. 493) +GM1o2_8=[ 1+D+D^2+D^3 1+D+D^3]; diff --git a/gnuradio-examples/python/channel-coding/fsm_files/awgn2o3_16.fsm b/gnuradio-examples/python/channel-coding/fsm_files/awgn2o3_16.fsm new file mode 100644 index 000000000..9630cd9af --- /dev/null +++ b/gnuradio-examples/python/channel-coding/fsm_files/awgn2o3_16.fsm @@ -0,0 +1,40 @@ +4 16 8 + +0 8 4 12 +0 8 4 12 +0 8 4 12 +0 8 4 12 +1 9 5 13 +1 9 5 13 +1 9 5 13 +1 9 5 13 +2 10 6 14 +2 10 6 14 +2 10 6 14 +2 10 6 14 +3 11 7 15 +3 11 7 15 +3 11 7 15 +3 11 7 15 + +0 1 7 6 +6 7 1 0 +3 2 4 5 +5 4 2 3 +2 3 5 4 +4 5 3 2 +1 0 6 7 +7 6 0 1 +4 5 3 2 +2 3 5 4 +7 6 0 1 +1 0 6 7 +6 7 1 0 +0 1 7 6 +5 4 2 3 +3 2 4 5 + + +2/3 code generated from the awgn 1/2 code with 16 states and puncturing the 4th bit. +d_free= + diff --git a/gnuradio-examples/python/channel-coding/fsm_files/awgn2o3_4.fsm b/gnuradio-examples/python/channel-coding/fsm_files/awgn2o3_4.fsm new file mode 100644 index 000000000..567948e78 --- /dev/null +++ b/gnuradio-examples/python/channel-coding/fsm_files/awgn2o3_4.fsm @@ -0,0 +1,44 @@ +4 4 8 + +0 2 1 3 +0 2 1 3 +0 2 1 3 +0 2 1 3 + +0 3 5 6 +4 7 1 2 +7 4 2 1 +3 0 6 5 + + +This is generated by the 1/2 AWGN code (5 7) by puncturing the first (MSB) bit. +--> d_free=3 + +before puncturing: + +00 03 31 32 +30 33 01 02 +13 10 22 21 +23 20 12 11 + +or in decimal representation: + + 0 3 13 14 +12 15 1 2 + 7 4 10 9 +11 8 6 5 + +by punturing the MSB you get (dmin=3) + +0 3 5 6 +4 7 1 2 +7 4 2 1 +3 0 6 5 + +and by puncturing the LSB (something is wrong with this code) + +0 1 6 7 +6 7 0 1 +3 2 5 4 +5 4 3 2 + diff --git a/gnuradio-examples/python/channel-coding/fsm_files/awgn2o3_4_1.fsm b/gnuradio-examples/python/channel-coding/fsm_files/awgn2o3_4_1.fsm new file mode 100644 index 000000000..c5aee6983 --- /dev/null +++ b/gnuradio-examples/python/channel-coding/fsm_files/awgn2o3_4_1.fsm @@ -0,0 +1,42 @@ +4 4 8 + +0 1 2 3 +0 1 2 3 +0 1 2 3 +0 1 2 3 + +0 7 4 3 +3 4 7 0 +5 2 1 6 +6 1 2 5 + + + +This is generated by the 1/2 AWGN code (5 7) by puncturing the first (MSB) bit. +--> d_free=3 + +before puncturing: + + +or in decimal representation: + +0 7 12 11 +3 4 15 8 +13 10 1 6 +14 9 2 5 + +by punturing the MSB you get (dmin=3) + +0 7 4 3 +3 4 7 0 +5 2 1 6 +6 1 2 5 + + +and by puncturing the LSB (something is wrong with this code) + +0 3 6 5 +1 2 7 4 +6 5 0 3 +7 4 1 2 + diff --git a/gnuradio-examples/python/channel-coding/fsm_files/awgn2o3_8.fsm b/gnuradio-examples/python/channel-coding/fsm_files/awgn2o3_8.fsm new file mode 100644 index 000000000..34deeb68c --- /dev/null +++ b/gnuradio-examples/python/channel-coding/fsm_files/awgn2o3_8.fsm @@ -0,0 +1,25 @@ +4 8 8 + +0 4 2 6 +0 4 2 6 +0 4 2 6 +0 4 2 6 +1 5 3 7 +1 5 3 7 +1 5 3 7 +1 5 3 7 + + +0 1 7 6 +6 7 1 0 +3 2 4 5 +5 4 2 3 +6 7 1 0 +0 1 7 6 +5 4 2 3 +3 2 4 5 + + + +This is generated by the 1/2 8-state AWGN code (15 17) by puncturing the fourth bit. +--> d_free=??? diff --git a/gnuradio-examples/python/channel-coding/fsm_files/awgn2o4_4.fsm b/gnuradio-examples/python/channel-coding/fsm_files/awgn2o4_4.fsm new file mode 100644 index 000000000..793d419c5 --- /dev/null +++ b/gnuradio-examples/python/channel-coding/fsm_files/awgn2o4_4.fsm @@ -0,0 +1,14 @@ +4 4 16 + +0 2 1 3 +0 2 1 3 +0 2 1 3 +0 2 1 3 + + 0 3 13 14 +12 15 1 2 + 7 4 10 9 +11 8 6 5 + +generated by the awgn1o2_4.fsm code +(two steps of the 1o2 code) diff --git a/gnuradio-examples/python/channel-coding/fsm_files/foo b/gnuradio-examples/python/channel-coding/fsm_files/foo new file mode 100644 index 000000000..b511c2b01 --- /dev/null +++ b/gnuradio-examples/python/channel-coding/fsm_files/foo @@ -0,0 +1,17 @@ +" Press ? for keyboard shortcuts +" Sorted by name (.bak,~,.o,.h,.info,.swp,.obj at end of list) +"= /home/anastas/gnuradio_svn/gnuradio-examples/python/channel-coding/fsm_files/ +../ +.svn/ +Makefile.am +awgn1o2_128.fsm +awgn1o2_16.fsm +awgn1o2_4.fsm +awgn1o2_8.fsm +awgn2o3_16.fsm +awgn2o3_4.fsm +awgn2o3_4_1.fsm +awgn2o3_8.fsm +awgn2o4_4.fsm +rep3.fsm +rep5.fsm diff --git a/gnuradio-examples/python/channel-coding/fsm_files/rep3.fsm b/gnuradio-examples/python/channel-coding/fsm_files/rep3.fsm new file mode 100644 index 000000000..1930523b3 --- /dev/null +++ b/gnuradio-examples/python/channel-coding/fsm_files/rep3.fsm @@ -0,0 +1,7 @@ +2 1 8 + +0 0 + +0 7 + +1/3 repetition code (with binary input) diff --git a/gnuradio-examples/python/channel-coding/fsm_files/rep5.fsm b/gnuradio-examples/python/channel-coding/fsm_files/rep5.fsm new file mode 100644 index 000000000..581858ec1 --- /dev/null +++ b/gnuradio-examples/python/channel-coding/fsm_files/rep5.fsm @@ -0,0 +1,7 @@ +2 1 8 + +0 0 + +0 7 + +1/3 repetiotion code diff --git a/gnuradio-examples/python/channel-coding/fsm_utils.py b/gnuradio-examples/python/channel-coding/fsm_utils.py new file mode 100755 index 000000000..dc5ee79f1 --- /dev/null +++ b/gnuradio-examples/python/channel-coding/fsm_utils.py @@ -0,0 +1,239 @@ +#!/usr/bin/env python +# +# Copyright 2004 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 2, 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., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +import re +import math +import sys +import operator + + + + +###################################################################### +# Decimal to any base conversion. +# Convert 'num' to a list of 'l' numbers representing 'num' +# to base 'base' (most significant symbol first). +###################################################################### +def dec2base(num,base,l): + s=range(l) + n=num + for i in range(l): + s[l-i-1]=n%base + n=int(n/base) + if n!=0: + print 'Number ', num, ' requires more than ', l, 'digits.' + return s + + +###################################################################### +# Conversion from any base to decimal. +# Convert a list 's' of symbols to a decimal number +# (most significant symbol first) +###################################################################### +def base2dec(s,base): + num=0 + for i in range(len(s)): + num=num*base+s[i] + return num + + + + + + + +###################################################################### +# Automaticaly generate the FSM structure for a binary feed-forward +# convolutional code. +# Input: k x n generator matrix (decimal representation) +###################################################################### +def make_fsm_bin_cc_ff(k,n,GM): + mem=[[]]*k + max_mem_x=[-1]*k + max_mem = -1 + for i in range(k): + memr=[0]*n + for j in range(n): + if GM[i][j]==0: + memr[j]=-1 + else: + memr[j]=int(math.log(GM[i][j],2)) + if memr[j]>max_mem_x[i]: + max_mem_x[i]=memr[j] + if memr[j]>max_mem: + max_mem=memr[j] + mem[i]=memr + + sum_max_mem = 0 + for i in range(k): + sum_max_mem = sum_max_mem+max_mem_x[i] + + + #print mem + #print max_mem_x + #print max_mem + #print sum_max_mem + + I=2**k + S=2**sum_max_mem + O=2**n + + #print I, S, O + + NS=[0]*S*I; + OS=[0]*S*I; + for s in range(S): + for i in range(I): + ss=dec2base(s,2,sum_max_mem) + ind=0 + ss_r=[] + for kk in range(k): + ss1 = [0]*max_mem + ss1[0:max_mem_x[kk]] = ss[ind:ind+max_mem_x[kk]] + ss_r.append(ss1) + ind=ind+max_mem_x[kk] + ii=dec2base(i,2,k) + + tt_r = ss_r + for kk in range(k): + tt_r[kk].insert(0,ii[kk]) + #print tt_r + + ns_r = [] + for kk in range(k): + ns_r.append(tt_r[kk][0:max_mem]) + + ns=[] + for kk in range(k): + ns = ns + ns_r[kk][0:max_mem_x[kk]] + NS[s*I+i]=base2dec(ns,2); + + out_r=[0]*n + for nn in range(n): + out=0; + for kk in range(k): + c=[0]*max_mem + gm = dec2base(GM[kk][nn],2,max_mem_x[kk]+1) + gm.reverse() + c[0:len(gm)] = gm + sy = 0 + for m in range(len(c)): + sy = sy + c[m]*tt_r[kk][m]; + out=operator.mod(out+sy,2); + out_r[nn]=out; + out_r.reverse() + OS[s*I+i] = base2dec(out_r,2); + + #O=max(max(OS))+1; + print I, S, O + print NS + print OS + + return (I,S,O,NS,OS) + + + + + +###################################################################### +# Automatically generate the lookup table that maps the FSM outputs +# to channel inputs corresponding to a channel 'channel' and a modulation +# 'mod'. Optional normalization of channel to unit energy. +# This table is used by the 'metrics' block to translate +# channel outputs to metrics for use with the Viterbi algorithm. +# Limitations: currently supports only one-dimensional modulations. +###################################################################### +def make_isi_lookup(mod,channel,normalize): + dim=mod[0] + constellation = mod[1] + + if normalize: + p = 0 + for i in range(len(channel)): + p = p + channel[i]**2 + for i in range(len(channel)): + channel[i] = channel[i]/math.sqrt(p) + + lookup=range(len(constellation)**len(channel)) + for o in range(len(constellation)**len(channel)): + ss=dec2base(o,len(constellation),len(channel)) + ll=0 + for i in range(len(channel)): + ll=ll+constellation[ss[i]]*channel[i] + lookup[o]=ll + return (1,lookup) + + + + + + +###################################################################### +# A list of common modulations. +# Format: (dimensionality,constellation) +###################################################################### +pam2 = (1,[-1, 1]) +pam4 = (1,[-3, -1, 3, 1]) # includes Gray mapping +pam8 = (1,[-7, -5, -3, -1, 1, 3, 5, 7]) + +psk4=(2,[1, 0, \ + 0, 1, \ + 0, -1,\ + -1, 0]) # includes Gray mapping +psk8=(2,[math.cos(2*math.pi*0/8), math.sin(2*math.pi*0/8), \ + math.cos(2*math.pi*1/8), math.sin(2*math.pi*1/8), \ + math.cos(2*math.pi*2/8), math.sin(2*math.pi*2/8), \ + math.cos(2*math.pi*3/8), math.sin(2*math.pi*3/8), \ + math.cos(2*math.pi*4/8), math.sin(2*math.pi*4/8), \ + math.cos(2*math.pi*5/8), math.sin(2*math.pi*5/8), \ + math.cos(2*math.pi*6/8), math.sin(2*math.pi*6/8), \ + math.cos(2*math.pi*7/8), math.sin(2*math.pi*7/8)]) + +orth2 = (2,[1, 0, \ + 0, 1]) +orth4=(4,[1, 0, 0, 0, \ + 0, 1, 0, 0, \ + 0, 0, 1, 0, \ + 0, 0, 0, 1]) + +###################################################################### +# A list of channels to be tested +###################################################################### + +# C test channel (J. Proakis, Digital Communications, McGraw-Hill Inc., 2001) +c_channel = [0.227, 0.460, 0.688, 0.460, 0.227] + + + + + + + + + + +if __name__ == '__main__': + make_fsm_bin_cc_ff (1,2,[[7,5]]) + print "----------\n" + make_fsm_bin_cc_ff (2,3,[[1,0,2],[0,1,6]]) + diff --git a/gnuradio-examples/python/channel-coding/test_sccc_hard.py b/gnuradio-examples/python/channel-coding/test_sccc_hard.py new file mode 100755 index 000000000..a869e91e1 --- /dev/null +++ b/gnuradio-examples/python/channel-coding/test_sccc_hard.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python + +from gnuradio import gr +from gnuradio import audio +from gnuradio import trellis +from gnuradio import eng_notation +import math +import sys +import random +import fsm_utils + +def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): + fg = gr.flow_graph () + + + # TX + src = gr.lfsr_32k_source_s() + src_head = gr.head (gr.sizeof_short,Kb/16) # packet size in shorts + s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the outer FSM input cardinality + enc_out = trellis.encoder_ss(fo,0) # initial state = 0 + inter = trellis.permutation(interleaver.K(),interleaver.INTER(),gr.sizeof_short) + enc_in = trellis.encoder_ss(fi,0) # initial state = 0 + mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + + # CHANNEL + add = gr.add_ff() + noise = gr.noise_source_f(gr.GR_GAUSSIAN,math.sqrt(N0/2),seed) + + # RX + metrics_in = trellis.metrics_f(fi.O(),dimensionality,constellation,trellis.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for innner Viterbi + va_in = trellis.viterbi_s(fi,K,0,-1) # Put -1 if the Initial/Final states are not set. + deinter = trellis.permutation(interleaver.K(),interleaver.DEINTER(),gr.sizeof_short) + metrics_out = trellis.metrics_s(fo.O(),1,[0,1,2,3],trellis.TRELLIS_HARD_SYMBOL) # data preprocessing to generate metrics for outer Viterbi (hard decisions) + va_out = trellis.viterbi_s(fo,K,0,-1) # Put -1 if the Initial/Final states are not set. + fsmi2s = gr.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts + dst = gr.check_lfsr_32k_s() + + fg.connect (src,src_head,s2fsmi,enc_out,inter,enc_in,mod) + fg.connect (mod,(add,0)) + fg.connect (noise,(add,1)) + fg.connect (add,metrics_in) + fg.connect (metrics_in,va_in,deinter,metrics_out,va_out,fsmi2s,dst) + + fg.run() + + ntotal = dst.ntotal () + nright = dst.nright () + runlength = dst.runlength () + return (ntotal,ntotal-nright) + + +def main(args): + nargs = len (args) + if nargs == 4: + fname_out=args[0] + fname_in=args[1] + esn0_db=float(args[2]) # Es/No in dB + rep=int(args[3]) # number of times the experiment is run to collect enough errors + else: + sys.stderr.write ('usage: test_tcm.py fsm_name_out fsm_fname_in Es/No_db repetitions\n') + sys.exit (1) + + # system parameters + Kb=1024*16 # packet size in bits (make it multiple of 16 so it can be packed in a short) + fo=trellis.fsm(fname_out) # get the outer FSM specification from a file + fi=trellis.fsm(fname_in) # get the innner FSM specification from a file + bitspersymbol = int(round(math.log(fo.I())/math.log(2))) # bits per FSM input symbol + if fo.O() != fi.I(): + sys.stderr.write ('Incompatible cardinality between outer and inner FSM.\n') + sys.exit (1) + K=Kb/bitspersymbol # packet size in trellis steps + interleaver=trellis.interleaver(K,666) # construct a random interleaver + modulation = fsm_utils.psk8 # see fsm_utlis.py for available predefined modulations + dimensionality = modulation[0] + constellation = modulation[1] + if len(constellation)/dimensionality != fi.O(): + sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n') + sys.exit (1) + # calculate average symbol energy + Es = 0 + for i in range(len(constellation)): + Es = Es + constellation[i]**2 + Es = Es / (len(constellation)/dimensionality) + N0=Es/pow(10.0,esn0_db/10.0); # calculate noise variance + + tot_s=0 # total number of transmitted shorts + terr_s=0 # total number of shorts in error + for i in range(rep): + (s,e)=run_test(fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation,N0,-long(666+i)) # run experiment with different seed to get different noise realizations + tot_s=tot_s+s + terr_s=terr_s+e + if (i%100==0) & (i>0): # display progress + print i,s,e,tot_s,terr_s, '%e' % ((1.0*terr_s)/tot_s) + # estimate of the (short or bit) error rate + print tot_s,terr_s, '%e' % ((1.0*terr_s)/tot_s) + + +if __name__ == '__main__': + main (sys.argv[1:]) diff --git a/gnuradio-examples/python/channel-coding/test_tcm.py b/gnuradio-examples/python/channel-coding/test_tcm.py new file mode 100755 index 000000000..0ba2e3c8e --- /dev/null +++ b/gnuradio-examples/python/channel-coding/test_tcm.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python + +from gnuradio import gr +from gnuradio import audio +from gnuradio import trellis +from gnuradio import eng_notation +import math +import sys +import random +import fsm_utils + +def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): + fg = gr.flow_graph () + + + # TX + #packet = [0]*Kb + #for i in range(Kb-1*16): # last 16 bits = 0 to drive the final state to 0 + #packet[i] = random.randint(0, 1) # random 0s and 1s + #src = gr.vector_source_s(packet,False) + src = gr.lfsr_32k_source_s() + src_head = gr.head (gr.sizeof_short,Kb/16) # packet size in shorts + #b2s = gr.unpacked_to_packed_ss(1,gr.GR_MSB_FIRST) # pack bits in shorts + s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality + enc = trellis.encoder_ss(f,0) # initial state = 0 + mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + + # CHANNEL + add = gr.add_ff() + noise = gr.noise_source_f(gr.GR_GAUSSIAN,math.sqrt(N0/2),seed) + + # RX + metrics = trellis.metrics_f(f.O(),dimensionality,constellation,trellis.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for Viterbi + va = trellis.viterbi_s(f,K,0,-1) # Put -1 if the Initial/Final states are not set. + fsmi2s = gr.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts + #s2b = gr.packed_to_unpacked_ss(1,gr.GR_MSB_FIRST) # unpack shorts to bits + #dst = gr.vector_sink_s(); + dst = gr.check_lfsr_32k_s() + + + fg.connect (src,src_head,s2fsmi,enc,mod) + #fg.connect (src,b2s,s2fsmi,enc,mod) + fg.connect (mod,(add,0)) + fg.connect (noise,(add,1)) + fg.connect (add,metrics) + fg.connect (metrics,va,fsmi2s,dst) + #fg.connect (metrics,va,fsmi2s,s2b,dst) + + + fg.run() + + # A bit of cheating: run the program once and print the + # final encoder state.. + # Then put it as the last argument in the viterbi block + #print "final state = " , enc.ST() + + ntotal = dst.ntotal () + nright = dst.nright () + runlength = dst.runlength () + #ntotal = len(packet) + #if len(dst.data()) != ntotal: + #print "Error: not enough data\n" + #nright = 0; + #for i in range(ntotal): + #if packet[i]==dst.data()[i]: + #nright=nright+1 + #else: + #print "Error in ", i + return (ntotal,ntotal-nright) + + + + +def main(args): + nargs = len (args) + if nargs == 3: + fname=args[0] + esn0_db=float(args[1]) # Es/No in dB + rep=int(args[2]) # number of times the experiment is run to collect enough errors + else: + sys.stderr.write ('usage: test_tcm.py fsm_fname Es/No_db repetitions\n') + sys.exit (1) + + # system parameters + f=trellis.fsm(fname) # get the FSM specification from a file + Kb=1*16 # packet size in bits (make it multiple of 16 so it can be packed in a short) + bitspersymbol = int(round(math.log(f.I())/math.log(2))) # bits per FSM input symbol + K=Kb/bitspersymbol # packet size in trellis steps + modulation = fsm_utils.psk4 # see fsm_utlis.py for available predefined modulations + dimensionality = modulation[0] + constellation = modulation[1] + if len(constellation)/dimensionality != f.O(): + sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n') + sys.exit (1) + # calculate average symbol energy + Es = 0 + for i in range(len(constellation)): + Es = Es + constellation[i]**2 + Es = Es / (len(constellation)/dimensionality) + N0=Es/pow(10.0,esn0_db/10.0); # calculate noise variance + + tot_s=0 # total number of transmitted shorts + terr_s=0 # total number of shorts in error + for i in range(rep): + (s,e)=run_test(f,Kb,bitspersymbol,K,dimensionality,constellation,N0,-long(666+i)) # run experiment with different seed to get different noise realizations + tot_s=tot_s+s + terr_s=terr_s+e + if (i%100==0) & (i>0): # display progress + print i,s,e,tot_s,terr_s, '%e' % ((1.0*terr_s)/tot_s) + # estimate of the (short or bit) error rate + print tot_s,terr_s, '%e' % ((1.0*terr_s)/tot_s) + + +if __name__ == '__main__': + main (sys.argv[1:]) diff --git a/gnuradio-examples/python/channel-coding/test_tcm1.py b/gnuradio-examples/python/channel-coding/test_tcm1.py new file mode 100755 index 000000000..e4f88d0b5 --- /dev/null +++ b/gnuradio-examples/python/channel-coding/test_tcm1.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python + +from gnuradio import gr +from gnuradio import audio +from gnuradio import trellis +from gnuradio import eng_notation +import math +import sys +import random +import fsm_utils + +def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): + fg = gr.flow_graph () + + # TX + packet = [0]*Kb + # this for loop is TOO slow!!! + for i in range(Kb-1*16): # last 16 bits = 0 to drive the final state to 0 + packet[i] = random.randint(0, 1) # random 0s and 1s + src = gr.vector_source_s(packet,False) + #src = gr.lfsr_32k_source_s() + #src_head = gr.head (gr.sizeof_short,Kb/16) # packet size in shorts + b2s = gr.unpacked_to_packed_ss(1,gr.GR_MSB_FIRST) # pack bits in shorts + s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality + enc = trellis.encoder_ss(f,0) # initial state = 0 + mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + + + # CHANNEL + add = gr.add_ff() + noise = gr.noise_source_f(gr.GR_GAUSSIAN,math.sqrt(N0/2),seed) + + + # RX + metrics = trellis.metrics_f(f.O(),dimensionality,constellation,trellis.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for Viterbi + va = trellis.viterbi_s(f,K,0,-1) # Put -1 if the Initial/Final states are not set. + fsmi2s = gr.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts + s2b = gr.packed_to_unpacked_ss(1,gr.GR_MSB_FIRST) # unpack shorts to bits + dst = gr.vector_sink_s(); + #dst = gr.check_lfsr_32k_s(); + + + #fg.connect (src,src_head,s2fsmi,enc,mod) + fg.connect (src,b2s,s2fsmi,enc,mod) + fg.connect (mod,(add,0)) + fg.connect (noise,(add,1)) + fg.connect (add,metrics) + #fg.connect (metrics,va,fsmi2s,dst) + fg.connect (metrics,va,fsmi2s,s2b,dst) + + + fg.run() + + # A bit of cheating: run the program once and print the + # final encoder state.. + # Then put it as the last argument in the viterbi block + #print "final state = " , enc.ST() + + #ntotal = dst.ntotal () + #nright = dst.nright () + #runlength = dst.runlength () + ntotal = len(packet) + if len(dst.data()) != ntotal: + print "Error: not enough data\n" + nright = 0; + # this for loop is TOO slow!!! + for i in range(ntotal): + if packet[i]==dst.data()[i]: + nright=nright+1 + #else: + #print "Error in ", i + return (ntotal,ntotal-nright) + + + + +def main(args): + nargs = len (args) + if nargs == 3: + fname=args[0] + esn0_db=float(args[1]) # Es/No in dB + rep=int(args[2]) # number of times the experiment is run to collect enough errors + else: + sys.stderr.write ('usage: test_tcm.py fsm_fname Es/No_db repetitions\n') + sys.exit (1) + + # system parameters + f=trellis.fsm(fname) # get the FSM specification from a file + Kb=1024*16 # packet size in bits (make it multiple of 16 so it can be packed in a short) + bitspersymbol = int(round(math.log(f.I())/math.log(2))) # bits per FSM input symbol + K=Kb/bitspersymbol # packet size in trellis steps + modulation = fsm_utils.psk4 # see fsm_utlis.py for available predefined modulations + dimensionality = modulation[0] + constellation = modulation[1] + if len(constellation)/dimensionality != f.O(): + sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n') + sys.exit (1) + # calculate average symbol energy + Es = 0 + for i in range(len(constellation)): + Es = Es + constellation[i]**2 + Es = Es / (len(constellation)/dimensionality) + N0=Es/pow(10.0,esn0_db/10.0); # noise variance + + + tot_s=0 + terr_s=0 + for i in range(rep): + (s,e)=run_test(f,Kb,bitspersymbol,K,dimensionality,constellation,N0,-long(666+i)) # run experiment with different seed to get different noise realizations + tot_s=tot_s+s + terr_s=terr_s+e + if (i%1==0) & (i>0): + print i,s,e,tot_s,terr_s, '%e' % ((1.0*terr_s)/tot_s) + # estimate of the (short or bit) error rate + print tot_s,terr_s, '%e' % ((1.0*terr_s)/tot_s) + + +if __name__ == '__main__': + main (sys.argv[1:]) diff --git a/gnuradio-examples/python/channel-coding/test_tcm_combined.py b/gnuradio-examples/python/channel-coding/test_tcm_combined.py new file mode 100755 index 000000000..01e092a0d --- /dev/null +++ b/gnuradio-examples/python/channel-coding/test_tcm_combined.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python + +from gnuradio import gr +from gnuradio import audio +from gnuradio import trellis +from gnuradio import eng_notation +import math +import sys +import fsm_utils + +def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): + fg = gr.flow_graph () + + # TX + src = gr.lfsr_32k_source_s() + src_head = gr.head (gr.sizeof_short,K/16) # packet size in shorts + s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality + enc = trellis.encoder_ss(f,0) # initial state = 0 + mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + + + # CHANNEL + add = gr.add_ff() + noise = gr.noise_source_f(gr.GR_GAUSSIAN,math.sqrt(N0/2),seed) + + + # RX + va = trellis.viterbi_combined_s(f,dimensionality,constellation,K/bitspersymbol,0,7,trellis.TRELLIS_EUCLIDEAN) # Put -1 if the Initial/Final states are not set. + fsmi2s = gr.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts + dst = gr.check_lfsr_32k_s(); + + + fg.connect (src,src_head,s2fsmi,enc,mod) + fg.connect (mod,(add,0)) + fg.connect (noise,(add,1)) + fg.connect (add,va,fsmi2s,dst) + + + fg.run() + + # A bit of cheating: run the program once and print the + # final encoder state.. + # Then put it as the last argument in the viterbi block + #print "final state = " , enc.ST() + + ntotal = dst.ntotal () + nright = dst.nright () + runlength = dst.runlength () + + return (ntotal,ntotal-nright) + + + + +def main(args): + nargs = len (args) + if nargs == 3: + fname=args[0] + esn0_db=float(args[1]) # Es/No in dB + rep=int(args[2]) # number of times the experiment is run to collect enough errors + else: + sys.stderr.write ('usage: test_tcm_combined.py fsm_fname Es/No_db repetitions\n') + sys.exit (1) + + # system parameters + f=trellis.fsm(fname) # get the FSM specification from a file (will hopefully be automated in the future...) + Kb=1024*16 # packet size in bits (make it multiple of 16) + bitspersymbol = int(round(math.log(f.I())/math.log(2))) # bits per FSM input symbol + K=Kb/bitspersymbol # packet size in trellis steps + modulation = fsm_utils.psk4 # see fsm_utils.py for available predefined modulations + dimensionality = modulation[0] + constellation = modulation[1] + if len(constellation)/dimensionality != f.O(): + sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n') + sys.exit (1) + # calculate average symbol energy + Es = 0 + for i in range(len(constellation)): + Es = Es + constellation[i]**2 + Es = Es / (len(constellation)/dimensionality) + N0=Es/pow(10.0,esn0_db/10.0); # noise variance + + + tot_s=0 + terr_s=0 + for i in range(rep): + (s,e)=run_test(f,Kb,bitspersymbol,K,dimensionality,constellation,N0,-long(666+i)) # run experiment with different seed to get different noise realizations + tot_s=tot_s+s + terr_s=terr_s+e + if (i%100==0) & (i>0): + print i,s,e,tot_s,terr_s, '%e' % ((1.0*terr_s)/tot_s) + # estimate of the (short) error rate + print tot_s,terr_s, '%e' % ((1.0*terr_s)/tot_s) + + +if __name__ == '__main__': + main (sys.argv[1:]) + diff --git a/gnuradio-examples/python/channel-coding/test_tcm_parallel.py b/gnuradio-examples/python/channel-coding/test_tcm_parallel.py new file mode 100755 index 000000000..230bf4b98 --- /dev/null +++ b/gnuradio-examples/python/channel-coding/test_tcm_parallel.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python + +from gnuradio import gr +from gnuradio import audio +from gnuradio import trellis +from gnuradio import eng_notation +import math +import sys +import fsm_utils + +def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed,P): + fg = gr.flow_graph () + + # TX + src = gr.lfsr_32k_source_s() + src_head = gr.head (gr.sizeof_short,Kb/16*P) # packet size in shorts + s2fsmi=gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality + s2p = gr.stream_to_streams(2,P) # serial to parallel + enc = trellis.encoder_ss(f,0) # initiali state = 0 + mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + + # CHANNEL + add=[] + noise=[] + for i in range(P): + add.append(gr.add_ff()) + noise.append(gr.noise_source_f(gr.GR_GAUSSIAN,math.sqrt(N0/2),seed)) + + + # RX + metrics = trellis.metrics_f(f.O(),dimensionality,constellation,trellis.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for Viterbi + va = trellis.viterbi_s(f,K,0,-1) # Put -1 if the Initial/Final states are not set. + p2s = gr.streams_to_stream(2,P) # parallel to serial + fsmi2s=gr.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts + dst = gr.check_lfsr_32k_s() + + fg.connect (src,src_head,s2fsmi,s2p) + for i in range(P): + fg.connect ((s2p,i),(enc,i),(mod,i)) + fg.connect ((mod,i),(add[i],0)) + fg.connect (noise[i],(add[i],1)) + fg.connect (add[i],(metrics,i)) + fg.connect ((metrics,i),(va,i),(p2s,i)) + fg.connect (p2s,fsmi2s,dst) + + + fg.run() + + # A bit of cheating: run the program once and print the + # final encoder state. + # Then put it as the last argument in the viterbi block + #print "final state = " , enc.ST() + + ntotal = dst.ntotal () + nright = dst.nright () + runlength = dst.runlength () + + return (ntotal,ntotal-nright) + + + +def main(args): + nargs = len (args) + if nargs == 3: + fname=args[0] + esn0_db=float(args[1]) # Es/No in dB + rep=int(args[2]) # number of times the experiment is run to collect enough errors + else: + sys.stderr.write ('usage: test_tcm.py fsm_fname Es/No_db repetitions\n') + sys.exit (1) + + # system parameters + f=trellis.fsm(fname) # get the FSM specification from a file + P=4 # how many parallel streams? + Kb=1024*16 # packet size in bits (make it multiple of 16 so it can be packed in a short) + bitspersymbol = int(round(math.log(f.I())/math.log(2))) # bits per FSM input symbol + K=Kb/bitspersymbol # packet size in trellis steps + modulation = fsm_utils.psk4 # see fsm_utlis.py for available predefined modulations + dimensionality = modulation[0] + constellation = modulation[1] + if len(constellation)/dimensionality != f.O(): + sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n') + sys.exit (1) + # calculate average symbol energy + Es = 0 + for i in range(len(constellation)): + Es = Es + constellation[i]**2 + Es = Es / (len(constellation)/dimensionality) + N0=Es/pow(10.0,esn0_db/10.0); # calculate noise variance + + tot_s=0 # total number of transmitted shorts + terr_s=0 # total number of shorts in error + for i in range(rep): + (s,e)=run_test(f,Kb,bitspersymbol,K,dimensionality,constellation,N0,-long(666+i),P) # run experiment with different seed to get different noise realizations + tot_s=tot_s+s + terr_s=terr_s+e + if (i%10==0) & (i>0): # display progress + print i,s,e,tot_s,terr_s, '%e' % ((1.0*terr_s)/tot_s) + # estimate of the (short or bit) error rate + print tot_s,terr_s, '%e' % ((1.0*terr_s)/tot_s) + + +if __name__ == '__main__': + main (sys.argv[1:]) + |