// per stream processing
for (int i = 0; i < noutput_items / d_D; i++){
- assert (((unsigned int)in[i]*d_D) < d_symbol_table.size());
+ assert (((unsigned int)in[i]*d_D+d_D) <= d_symbol_table.size());
memcpy(out, &d_symbol_table[(unsigned int)in[i]*d_D], d_D*sizeof(@O_TYPE@));
out+=d_D;
}
If you just want to see what these programs do, run each of the following:
-./test_tcm.py fsm_files/awgn1o2_4.fsm 10.0 1000
-./test_tcm1.py fsm_files/awgn1o2_4.fsm 10.0 1000
-./test_tcm_combined.py fsm_files/awgn1o2_4.fsm 10.0 1000
-./test_tcm_parallel.py fsm_files/awgn1o2_4.fsm 10.0 1000
-./test_sccc_hard.py fsm_files/awgn1o2_4.fsm fsm_files/awgn1o2_4.fsm 10.0 1000
+./test_tcm.py fsm_files/awgn1o2_4.fsm 6.0 1000
+./test_tcm1.py fsm_files/awgn1o2_4.fsm 6.0 1000
+./test_tcm2.py 6.0 1000
+./test_tcm_combined.py fsm_files/awgn1o2_4.fsm 6.0 1000
+./test_tcm_parallel.py fsm_files/awgn1o2_4.fsm 6.0 1000
+
+./test_sccc_hard.py fsm_files/awgn1o2_4.fsm fsm_files/awgn1o2_4_msb.fsm 10.0 100
+./test_sccc_soft.py fsm_files/awgn1o2_4.fsm fsm_files/awgn1o2_4_msb.fsm 8.0 100
+./test_sccc_turbo.py fsm_files/awgn1o2_4.fsm fsm_files/awgn1o2_4_msb.fsm 5.0 100
In your terminal you will see something like this:
-[anastas@ernesto channel-coding]$ ./test_tcm.py fsm_files/awgn1o2_4.fsm 6.0 1000
-100 1024 1 103424 10 9.668936e-05
-200 1024 1 205824 21 1.020289e-04
-300 1024 0 308224 40 1.297757e-04
-400 1024 0 410624 1074 2.615531e-03
-500 1024 0 513024 1081 2.107114e-03
-600 1024 0 615424 1090 1.771137e-03
-700 1024 0 717824 1097 1.528230e-03
-800 1024 0 820224 1107 1.349631e-03
-900 1024 0 922624 1120 1.213929e-03
-1024000 1129 1.102539e-03
-
-1.102539e-03 is the error rate estimates by sending 1000 packets of
-1024x16 bits each using an 1/2 4-state convolutional code and QPSK
+$ ./test_tcm.py fsm_files/awgn1o2_4.fsm 6.0 1000
+100 98 9.80e-01 102400 9 8.79e-05
+200 198 9.90e-01 204800 20 9.77e-05
+300 298 9.93e-01 307200 40 1.30e-04
+400 398 9.95e-01 409600 1074 2.62e-03
+500 498 9.96e-01 512000 1081 2.11e-03
+600 598 9.97e-01 614400 1090 1.77e-03
+700 698 9.97e-01 716800 1097 1.53e-03
+800 798 9.98e-01 819200 1107 1.35e-03
+900 898 9.98e-01 921600 1120 1.22e-03
+1000 998 9.98e-01 1024000 1129 1.10e-03
+1000 998 9.98e-01 1024000 1129 1.10e-03
+
+which gives you information about the:
+number of transmitted packets
+number of packets in error
+iestimated packet error rate
+number of transmitted shorts
+number of shorts in error
+estimated (short) error rate
+
+1.10e-03 is the error rate estimate by sending 1000 packets of
+1024 shorts each, using an 1/2 4-state convolutional code and QPSK
modulation through an AWGN with Es/N0 = 6.0 dB
-GM1o2_128=[1+D^3+D^4+D^5+D^6+D^7 1+D+D^2+D^5+D^7]
- =[249 167]
+GM1o2_128=[1+D+D^2+D^5+D^7 1+D^3+D^4+D^5+D^6+D^7]
+ =[11100101 10011111]
+ =[229 159]
-GM1o2_16=[1+D^2+D^3+D^4 1+D+D^4];
+GM1o2_16=[1+D+D^4 1+D^2+D^3+D^4 ] = [25,23] (decimal)
2 1
AWGN CC from Proakis-Salehi pg 779
-GM1o2_4=[1+D+D^2 1+D^2];
-
-
-
+GM1o2_4=[1+D^2, 1+D+D^2] = [5, 7] (in decimal);
1/2 8-state code (Proakis pg. 493)
-GM1o2_8=[ 1+D+D^2+D^3 1+D+D^3];
+GM1o2_8=[ 1+D+D^3 1+D+D^2+D^3] =[13 , 15] (decimal)
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
-
+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
+
+I don't remeber how I generated this one...
+it is a bit better than awgn2o3_4_msb and worse
+than awgn2o3_4_msbG.
+++ /dev/null
-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
-
--- /dev/null
+4 4 8
+
+0 1 2 3
+0 1 2 3
+0 1 2 3
+0 1 2 3
+
+0 5 3 6
+4 1 7 2
+7 2 4 1
+3 6 0 5
+
+
+This is generated by the 1/2 AWGN code (5 7) operated twice, ie,
+(xk+1 xki) [xk-1 xk-2] -> [xk+1 xki].
+We also puncture the first (MSB) bit.
+This code is worse than awgn2o3_4_msbG and slightly worse than
+awgn2o3_4, BUT seems to be a good innner code for sctcm (with 8PSK natural).
+
+intermediate states:
+
+00 21 02 23
+00 21 02 23
+10 31 12 33
+10 31 12 33
+
+output before puncturing:
+
+00 31 03 32
+30 01 33 02
+13 22 10 21
+23 12 20 11
+
+output after punturing the MSB:
+
+00 11 03 12
+10 01 13 02
+13 02 10 01
+03 12 00 11
+
+and in decimal:
+
+0 5 3 6
+4 1 7 2
+7 2 4 1
+3 6 0 5
--- /dev/null
+4 4 8
+
+0 1 2 3
+0 1 2 3
+0 1 2 3
+0 1 2 3
+
+0 4 2 6
+5 1 3 7
+3 7 5 1
+
+
+This is generated by the 1/2 AWGN code (5 7) operated twice, ie,
+(xk+1 xki) [xk-1 xk-2] -> [xk+1 xki].
+We also puncture the first (MSB) bit and Gray map the symbols.
+
+intermediate states:
+
+00 21 02 23
+00 21 02 23
+10 31 12 33
+10 31 12 33
+
+output before puncturing:
+
+00 31 03 32
+30 01 33 02
+13 22 10 21
+23 12 20 11
+
+output after punturing the MSB:
+
+00 11 03 12
+10 01 13 02
+13 02 10 01
+03 12 00 11
+
+and in decimal:
+
+0 5 3 6
+4 1 7 2
+7 2 4 1
+3 6 0 5
+
+After Gray mapping:
+label -> phase
+0 -> 0
+1 -> 0
+2 -> 7
+3 -> 2
+4 -> 5
+5 -> 4
+6 -> 6
+7 -> 3
+
+0 4 2 6
+5 1 3 7
+3 7 5 1
+2 6 0 4
+
-4 4 16
+4 4 16
-0 2 1 3
-0 2 1 3
-0 2 1 3
-0 2 1 3
+0 1 2 3
+0 1 2 3
+0 1 2 3
+0 1 2 3
- 0 3 13 14
-12 15 1 2
- 7 4 10 9
-11 8 6 5
+ 0 13 3 14
+12 1 15 2
+ 7 10 4 9
+11 6 8 5
-generated by the awgn1o2_4.fsm code
-(two steps of the 1o2 code)
+
+This is generated by the 1/2 AWGN code (5 7) operated twice, ie,
+(xk+1 xki) [xk-1 xk-2] -> [xk+1 xki].
+
+intermediate states:
+
+00 21 02 23
+00 21 02 23
+10 31 12 33
+10 31 12 33
+
+output:
+
+00 31 03 32
+30 01 33 02
+13 22 10 21
+23 12 20 11
+
+and in decimal:
+
+ 0 13 3 14
+12 1 15 2
+ 7 10 4 9
+11 6 8 5
--- /dev/null
+1 4 1
+
+1
+0
+3
+2
+
+0
+0
+0
+0
0 7
-1/3 repetition code (with binary input)
+1/3 repetition code (with binary input).
+There is only one state, since this is essentially a memoryless system.
--- /dev/null
+1 4 1
+
+1
+2
+3
+0
+
+0
+0
+0
+0
+
+essentially this fsm has no inputs and no outputs; it ijust cycles through all 4 states.
-
-
-######################################################################
-# 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
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)
+ inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short)
enc_in = trellis.encoder_ss(fi,0) # initial state = 0
mod = gr.chunks_to_symbols_sf(constellation,dimensionality)
# 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)
+ deinter = trellis.permutation(interleaver.K(),interleaver.DEINTER(),1,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
tot_s=0 # total number of transmitted shorts
terr_s=0 # total number of shorts in error
+ terr_p=0 # total number of packets 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)
+ terr_p=terr_p+(terr_s!=0)
+ if ((i+1)%100==0) : # display progress
+ print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((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)
+ print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s)
if __name__ == '__main__':
--- /dev/null
+#!/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(),1,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
+ gnd = gr.vector_source_f([0],True);
+ siso_in = trellis.siso_f(fi,K,0,-1,True,False,trellis.TRELLIS_MIN_SUM) # Put -1 if the Initial/Final states are not set.
+ deinter = trellis.permutation(interleaver.K(),interleaver.DEINTER(),fi.I(),gr.sizeof_float)
+ 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 (gnd,(siso_in,0))
+ fg.connect (metrics_in,(siso_in,1))
+ fg.connect (siso_in,deinter,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
+ terr_p=0 # total number of packets 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
+ terr_p=terr_p+(terr_s!=0)
+ if ((i+1)%100==0) : # display progress
+ print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s)
+ # estimate of the (short or bit) error rate
+ print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s)
+
+
+
+if __name__ == '__main__':
+ main (sys.argv[1:])
--- /dev/null
+#!/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 make_rx(fg,fo,fi,dimensionality,constellation,K,interleaver,IT,Es,N0,type):
+ metrics_in = trellis.metrics_f(fi.O(),dimensionality,constellation,trellis.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for innner Viterbi
+ scale = gr.multiply_const_ff(1.0/N0)
+ gnd = gr.vector_source_f([0],True);
+
+ inter=[]
+ deinter=[]
+ siso_in=[]
+ siso_out=[]
+
+ for it in range(IT-1):
+ inter.append( trellis.permutation(interleaver.K(),interleaver.INTER(),fi.I(),gr.sizeof_float) )
+ siso_in.append( trellis.siso_f(fi,K,0,3,True,False,type) )
+ deinter.append( trellis.permutation(interleaver.K(),interleaver.DEINTER(),fi.I(),gr.sizeof_float) )
+ siso_out.append( trellis.siso_f(fo,K,0,3,False,True,type) )
+ fg.connect (inter[it],(siso_in[it],0))
+ fg.connect (gnd,(siso_out[it],0))
+ fg.connect (siso_in[it],deinter[it],(siso_out[it],1))
+
+ inter.append( trellis.permutation(interleaver.K(),interleaver.INTER(),fi.I(),gr.sizeof_float) )
+ siso_in.append( trellis.siso_f(fi,K,0,-1,True,False,type) )
+ deinter.append( trellis.permutation(interleaver.K(),interleaver.DEINTER(),fi.I(),gr.sizeof_float) )
+ siso_out.append( trellis.viterbi_s(fo,K,0,-1) )
+ fg.connect (inter[IT-1],(siso_in[IT-1],0))
+ fg.connect (siso_in[IT-1],deinter[IT-1],siso_out[IT-1])
+
+ # connect first stage
+ fg.connect (gnd,inter[0])
+ fg.connect (metrics_in,scale)
+ fg.connect (scale,(siso_in[0],1))
+ for it in range(IT-1):
+ fg.connect (siso_out[it],inter[it+1])
+ fg.connect (metrics_in,(siso_in[it+1],1))
+ return (metrics_in,siso_out[IT-1])
+
+
+def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation,Es,N0,IT,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(),1,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
+ (head,tail) = make_rx(fg,fo,fi,dimensionality,constellation,K,interleaver,IT,Es,N0,trellis.TRELLIS_MIN_SUM)
+ #(head,tail) = make_rx(fg,fo,fi,dimensionality,constellation,K,interleaver,IT,Es,N0,trellis.TRELLIS_SUM_PRODUCT)
+ 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,head)
+ fg.connect (tail,fsmi2s,dst)
+
+ fg.run()
+
+ #print enc_out.ST(), enc_in.ST()
+
+ 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
+ IT = 3 # number of turbo iterations
+
+ tot_s=0 # total number of transmitted shorts
+ terr_s=0 # total number of shorts in error
+ terr_p=0 # total number of packets in error
+ for i in range(rep):
+ (s,e)=run_test(fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation,Es,N0,IT,-long(666+i)) # run experiment with different seed to get different noise realizations
+ tot_s=tot_s+s
+ terr_s=terr_s+e
+ terr_p=terr_p+(terr_s!=0)
+ if ((i+1)%10==0): # display progress
+ print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s)
+ # estimate of the (short or bit) error rate
+ print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s)
+
+
+if __name__ == '__main__':
+ main (sys.argv[1:])
tot_s=0 # total number of transmitted shorts
terr_s=0 # total number of shorts in error
+ terr_p=0 # total number of packets 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)
+ terr_p=terr_p+(terr_s!=0)
+ if ((i+1)%100==0) : # display progress
+ print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((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)
+ print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s)
+
if __name__ == '__main__':
Es = Es / (len(constellation)/dimensionality)
N0=Es/pow(10.0,esn0_db/10.0); # noise variance
-
- tot_s=0
- terr_s=0
+ tot_s=0 # total number of transmitted shorts
+ terr_s=0 # total number of shorts in error
+ terr_p=0 # total number of packets 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%1==0) & (i>0):
- print i,s,e,tot_s,terr_s, '%e' % ((1.0*terr_s)/tot_s)
+ terr_p=terr_p+(terr_s!=0)
+ if ((i+1)%1==0) : # display progress
+ print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((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)
+ print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s)
+
if __name__ == '__main__':
--- /dev/null
+#!/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 == 2:
+ esn0_db=float(args[0]) # Es/No in dB
+ rep=int(args[1]) # number of times the experiment is run to collect enough errors
+ else:
+ sys.stderr.write ('usage: test_tcm2.py Es/No_db repetitions\n')
+ sys.exit (1)
+
+ # system parameters
+ f=trellis.fsm(1,2,[5,7]) # generate FSM specification from the generator matrix
+ 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
+ terr_p=0 # total number of packets 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
+ terr_p=terr_p+(terr_s!=0)
+ if ((i+1)%100==0) : # display progress
+ print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s)
+ # estimate of the (short or bit) error rate
+ print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s)
+
+
+if __name__ == '__main__':
+ main (sys.argv[1:])
Es = Es / (len(constellation)/dimensionality)
N0=Es/pow(10.0,esn0_db/10.0); # noise variance
-
- tot_s=0
- terr_s=0
+ tot_s=0 # total number of transmitted shorts
+ terr_s=0 # total number of shorts in error
+ terr_p=0 # total number of packets 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):
- 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)
+ terr_p=terr_p+(terr_s!=0)
+ if ((i+1)%100==0) : # display progress
+ print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s)
+ # estimate of the (short or bit) error rate
+ print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s)
+
if __name__ == '__main__':
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
+ s2p = gr.stream_to_streams(gr.sizeof_short,P) # serial to parallel
enc = trellis.encoder_ss(f,0) # initiali state = 0
mod = gr.chunks_to_symbols_sf(constellation,dimensionality)
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
+ p2s = gr.streams_to_stream(gr.sizeof_short,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()
tot_s=0 # total number of transmitted shorts
terr_s=0 # total number of shorts in error
+ terr_p=0 # total number of packets 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)
+ terr_p=terr_p+(terr_s!=0)
+ if ((i+1)%100==0) : # display progress
+ print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((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)
+ print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s)
if __name__ == '__main__':
+++ /dev/null
-<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Trellis-based algorithms for GNU Radio</title><meta name="generator" content="DocBook XSL Stylesheets V1.65.1"><meta name="description" content="This document provides a description of the
-Finite State Machine (FSM) implementation and the related
-trellis-based encoding and decoding algorithms
-for GNU Radio.
-"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="article" lang="en"><div class="titlepage"><div><div><h1 class="title"><a name="id2753996"></a>Trellis-based algorithms for GNU Radio</h1></div><div><div class="author"><h3 class="author"><span class="firstname">Achilleas</span> <span class="surname">Anastasopoulos</span></h3><div class="affiliation"><div class="address"><p><br>
-Â Â Â Â Â Â Â Â Â Â Â <tt class="email"><<a href="mailto:anastas@umich.edu">anastas@umich.edu</a>></tt><br>
-Â Â Â Â Â Â Â Â </p></div></div></div></div><div><div class="revhistory"><table border="1" width="100%" summary="Revision history"><tr><th align="left" valign="top" colspan="2"><b>Revision History</b></th></tr><tr><td align="left">Revision v0.0</td><td align="left">2006-08-03</td></tr><tr><td align="left" colspan="2">
- First cut.
- </td></tr></table></div></div><div><div class="abstract"><p class="title"><b>Abstract</b></p><p>This document provides a description of the
-Finite State Machine (FSM) implementation and the related
-trellis-based encoding and decoding algorithms
-for GNU Radio.
-</p></div></div></div><div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="#intro">Introduction</a></span></dt><dt><span class="sect1"><a href="#fsm">The FSM class</a></span></dt><dt><span class="sect1"><a href="#tcm">TCM: A Complete Example</a></span></dt><dt><span class="sect1"><a href="#future">Future Work</a></span></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="intro"></a>Introduction</h2></div></div><div></div></div><p>....</p><p>
-The basic goal of the implementation is to have a generic way of
-describing an FSM that is decoupled from whether it describes a
-convolutional
-code (CC), a trellis code (TC), an inter-symbol interference (ISI)
-channel, or any
-other communication system that can be modeled with an FSM.
-To achieve this goal, we need to separate the pure FSM descrition from the
-rest of the model details. For instance, in the case of a rate 2/3 TC,
-the FSM should not involve details about the modulation used (it can
-be an 8-ary PAM, or 8-PSK, etc). Similarly, when attempting maximum likelihood
-sequence detection (MLSD)--using for instance the Viterbi algorithm (VA)--
-the VA implementation should not be concerned with the channel details
-(such as modulations, channel type, hard or soft inputs, etc).
-Clearly, having generality as the primary goal implies some penalty
-on the code efficiency, as compared to fully custom implementations.
-</p><p>
-We will now describe the implementation of the basic ingedient, the FSM.
-</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="fsm"></a>The FSM class</h2></div></div><div></div></div><p>An FSM describes the evolution of a system with inputs
-x<sub>k</sub>, states s<sub>k</sub> and outputs y<sub>k</sub>. At time k the FSM state is s<sub>k</sub>.
-Upon reception of a new input symbol x<sub>k</sub>, it outputs an output symbol
-y<sub>k</sub> which is a function of both x<sub>k</sub> and s<sub>k</sub>.
-It will then move to a next state s<sub>k+1</sub>.
-An FSM has a finite number of states, input and output symbols.
-All these are formally described as follows:
-</p><div class="itemizedlist"><ul type="disc"><li><p>The input alphabet A<sub>I</sub>={0,1,2,...,I-1}, with cardinality I, so that x<sub>k</sub> takes values in A<sub>I</sub>.</p></li><li><p>The state alphabet A<sub>S</sub>={0,1,2,...,S-1}, with cardinality S, so that s<sub>k</sub> takes values in A<sub>S</sub>.</p></li><li><p>The output alphabet A<sub>O</sub>={0,1,2,...,O-1}, with cardinality O, so that y<sub>k</sub> takes values in A<sub>O</sub></p></li><li><p>The "next-state" function NS: A<sub>S</sub> x A<sub>I</sub> --> A<sub>S</sub>,
-with the meaning
-s<sub>k+1</sub> = NS(s<sub>k</sub>, x<sub>k</sub>)</p></li><li><p>The "output-symbol" function OS: A<sub>S</sub> x A<sub>I</sub> --> A<sub>S</sub>,
-with the meaning
-y<sub>k</sub> = OS(s<sub>k</sub>, x<sub>k</sub>)</p></li></ul></div><p>
-Thus, a complete description of the FSM is given by the
-the five-tuple (I,S,O,NS,OS).
-Observe that implementation details are hidden
-in how the outside world interprets these input and output
-integer symbols.
-Here is an example of an FSM describing the (2,1) CC
-with constraint length 3 and generator polynomial matrix
-(1+D+D<sup>2</sup> , 1+D<sup>2</sup>)
-from Proakis-Salehi pg. 779.
-</p><div class="example"><a name="cc_ex"></a><p class="title"><b>Example 1. (2,1) CC with generator polynomials (1+D+D<sup>2</sup> , 1+D<sup>2</sup>)</b></p><p>
-This CC accepts 1 bit at a time, and outputs 2 bits at a time.
-It has a shift register storing the last two input bits.
-In particular,
-b<sub>k</sub>(0)=x<sub>k</sub>+
-x<sub>k-1</sub>+x<sub>k-2</sub>, and
-b<sub>k</sub>(1)=x<sub>k</sub>+
-x<sub>k-2</sub>, where addition is mod-2.
-We can represent the state of this system
-as s<sub>k</sub> = (x<sub>k-1</sub> x<sub>k-2</sub>)<sub>10</sub>. In addition we can represent its
-output symbol as y<sub>k</sub> = (b<sub>k</sub>(1) b<sub>k</sub>(0))<sub>10</sub>.
-Based on the above assumptions, the input alphabet A<sub>I</sub>={0,1}, so I=2;
-the state alphabet A<sub>S</sub>={0,1,2,3}, so S=4; and
-the output alphabet A<sub>O</sub>={0,1,2,3}, so O=4.
-The "next-state" function NS(,) is given by
-</p><pre class="programlisting">
-s<sub>k</sub> x<sub>k</sub> s<sub>k+1</sub>
-0 0 0
-0 1 2
-1 0 0
-1 1 2
-2 0 1
-2 1 3
-3 0 1
-3 1 3
-</pre><p>
-The "output-symbol" function OS(,) can be given by
-</p><pre class="programlisting">
-s<sub>k</sub> x<sub>k</sub> y<sub>k</sub>
-0 0 0
-0 1 3
-1 0 3
-1 1 0
-2 0 1
-2 1 2
-3 0 2
-3 1 1
-</pre><p>
-</p><p>
-Note that although the CC outputs 2 bits per time period, following
-our approach, there is only one (quaternary) output symbol per
-time period (for instance, here we use the decimal representation
-of the 2-bits). Also note that the modulation used is not part of
-the FSM description: it can be BPSK, OOK, BFSK, QPSK with or without Gray mapping, etc;
-it is up to the rest of the program to interpret the meaning of
-the symbol y<sub>k</sub>.
-</p></div><p>
-The C++ implementation of the FSM class keeps private information about
-I,S,O,NS,OS and public methods to read and write them. The NS
-and OS matrices are implemented as STL 1-dimensional vectors.
-</p><pre class="programlisting">
-class fsm {
-private:
- int d_I;
- int d_S;
- int d_O;
- std::vector<int> d_NS;
- std::vector<int> d_OS;
- std::vector<int> d_PS;
- std::vector<int> d_PI;
-public:
- fsm();
- fsm(const fsm &FSM);
- fsm(const int I, const int S, const int O, const std::vector<int> &NS, const std::vector<int> &OS);
- fsm(const char *name);
- fsm(const int mod_size, const int ch_length);
- int I () const { return d_I; }
- int S () const { return d_S; }
- int O () const { return d_O; }
- const std::vector<int> & NS () const { return d_NS; }
- const std::vector<int> & OS () const { return d_OS; }
- const std::vector<int> & PS () const { return d_PS; }
- const std::vector<int> & PI () const { return d_PI; }
-};
-</pre><p>
-As can be seen, other than the trivial and the copy constructor,
-there are three additional
-ways to construct an FSM.
-</p><div class="itemizedlist"><ul type="disc"><li><p>Supplying the parameters I,S,O,NS,OS:</p><pre class="programlisting">
- fsm(const int I, const int S, const int O, const std::vector<int> &NS, const std::vector<int> &OS);
-</pre></li><li><p>Giving a filename containing all the FSM information:</p><pre class="programlisting">
- fsm(const char *name);
-</pre><p>
-This information has to be in the following format:
-</p><pre class="programlisting">
-I S O
-
-NS(0,0) NS(0,1) ... NS(0,I-1)
-NS(1,0) NS(1,1) ... NS(1,I-1)
-...
-NS(S-1,0) NS(S-1,1) ... NS(S-1,I-1)
-
-OS(0,0) OS(0,1) ... OS(0,I-1)
-OS(1,0) OS(1,1) ... OS(1,I-1)
-...
-OS(S-1,0) OS(S-1,1) ... OS(S-1,I-1)
-</pre><p>
-</p><p>
-For instance, the file containing the information for the example mentioned above is of the form:
-</p><pre class="programlisting">
-2 4 4
-
-0 2
-0 2
-1 3
-1 3
-
-0 3
-3 0
-1 2
-2 1
-</pre><p>
-</p></li><li><p>The third way is specific to FSMs resulting from shift registers, and the output symbol being the entire transition (ie, current_state and current_input). These FSMs are usefull when describibg ISI channels. In particular the state is comprised of the.....
-</p><pre class="programlisting">
- fsm(const int mod_size, const int ch_length);
-</pre></li></ul></div><p>
-Finally, as can be seen from the above description, there are
-two more variables included in the FSM class implementation,
-the PS and the PI matrices. These are computed internally
-when an FSM is instantiated and their meaning is as follows.
-Sometimes (eg, in the traceback operation of the VA) we need
-to trace the history of the state or the input sequence.
-To do this we would like to know for a given state s<sub>k</sub>, what are the possible previous states s<sub>k-1</sub>
-and what input symbols x<sub>k-1</sub> will get us from
-s<sub>k-1</sub> to s<sub>k</sub>. This information can be derived from NS; however we want to have it ready in a
-convenient format.
-In the following we assume that for any state,
-the number of incoming transitions is the same as the number of
-outgoing transitions, ie, equal to I. All applications of interest
-have FSMs satisfying this requirement.
-
-If we arbitrarily index the incoming transitions to the current state
-by "i", then as i goes from 0 to I-1, PS(s<sub>k</sub>,i)
-gives all previous states s<sub>k-1</sub>,
-and PI(s<sub>k</sub>,i) gives all previous inputs x<sub>k-1</sub>.
-In other words, for any given s<sub>k</sub> and any index i=0,1,...I-1, starting from
-s<sub>k-1</sub>=PS(s<sub>k</sub>,i)
-with input
-x<sub>k-1</sub>=PI(s<sub>k</sub>,i)
-will get us to the state s<sub>k</sub>.
-More formally, for any i=0,1,...I-1 we have
-s<sub>k</sub> = NS(PS(s<sub>k</sub>,i),PI(s<sub>k</sub>,i)).
-
-</p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="tcm"></a>TCM: A Complete Example</h2></div></div><div></div></div><p>
-We now discuss through a concrete example how
-the above FSM model can be used in GNU Radio.
-
-The communication system that we want to simulate
-consists of a source generating the
-input information in packets, a CC encoding each packet separately,
-a memoryless modulator,
-an additive white Gaussian noise (AWGN) channel, and
-the VA performing MLSD.
-The program source is as follows.
-</p><pre class="programlisting">
- 1 #!/usr/bin/env python
- 2
- 3 from gnuradio import gr
- 4 from gnuradio import audio
- 5 from gnuradio import trellis
- 6 from gnuradio import eng_notation
- 7 import math
- 8 import sys
- 9 import random
- 10 import fsm_utils
- 11
- 12 def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed):
- 13 fg = gr.flow_graph ()
- 14
- 15 # TX
- 16 src = gr.lfsr_32k_source_s()
- 17 src_head = gr.head (gr.sizeof_short,Kb/16) # packet size in shorts
- 18 s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality
- 19 enc = trellis.encoder_ss(f,0) # initial state = 0
- 20 mod = gr.chunks_to_symbols_sf(constellation,dimensionality)
- 21
- 22 # CHANNEL
- 23 add = gr.add_ff()
- 24 noise = gr.noise_source_f(gr.GR_GAUSSIAN,math.sqrt(N0/2),seed)
- 25
- 26 # RX
- 27 metrics = trellis.metrics_f(f.O(),dimensionality,constellation,trellis.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for Viterbi
- 28 va = trellis.viterbi_s(f,K,0,-1) # Put -1 if the Initial/Final states are not set.
- 29 fsmi2s = gr.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts
- 30 dst = gr.check_lfsr_32k_s();
- 31
- 32 fg.connect (src,src_head,s2fsmi,enc,mod)
- 33 fg.connect (mod,(add,0))
- 34 fg.connect (noise,(add,1))
- 35 fg.connect (add,metrics)
- 36 fg.connect (metrics,va,fsmi2s,dst)
- 37
- 38 fg.run()
- 39
- 40 # A bit of cheating: run the program once and print the
- 41 # final encoder state.
- 42 # Then put it as the last argument in the viterbi block
- 43 #print "final state = " , enc.ST()
- 44
- 45 ntotal = dst.ntotal ()
- 46 nright = dst.nright ()
- 47 runlength = dst.runlength ()
- 48 return (ntotal,ntotal-nright)
- 49
- 50
- 51 def main(args):
- 52 nargs = len (args)
- 53 if nargs == 3:
- 54 fname=args[0]
- 55 esn0_db=float(args[1]) # Es/No in dB
- 56 rep=int(args[2]) # number of times the experiment is run to collect enough errors
- 57 else:
- 58 sys.stderr.write ('usage: test_tcm.py fsm_fname Es/No_db repetitions\n')
- 59 sys.exit (1)
- 60
- 61 # system parameters
- 62 f=trellis.fsm(fname) # get the FSM specification from a file (will hopefully be automated in the future...)
- 63 Kb=1024*16 # packet size in bits (make it multiple of 16 so it can be packed in a short)
- 64 bitspersymbol = int(round(math.log(f.I())/math.log(2))) # bits per FSM input symbol
- 65 K=Kb/bitspersymbol # packet size in trellis steps
- 66 modulation = fsm_utils.psk4 # see fsm_utlis.py for available predefined modulations
- 67 dimensionality = modulation[0]
- 68 constellation = modulation[1]
- 69 if len(constellation)/dimensionality != f.O():
- 70 sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n')
- 71 sys.exit (1)
- 72 # calculate average symbol energy
- 73 Es = 0
- 74 for i in range(len(constellation)):
- 75 Es = Es + constellation[i]**2
- 76 Es = Es / (len(constellation)/dimensionality)
- 77 N0=Es/pow(10.0,esn0_db/10.0); # noise variance
- 78
- 79 tot_s=0
- 80 terr_s=0
- 81 for i in range(rep):
- 82 (s,e)=run_test(f,Kb,bitspersymbol,K,dimensionality,constellation,N0,-long(666+i)) # run experiment with different seed to get different noise realizations
- 83 tot_s=tot_s+s
- 84 terr_s=terr_s+e
- 85 if (i%100==0):
- 86 print i,s,e,tot_s,terr_s, '%e' % ((1.0*terr_s)/tot_s)
- 87 # estimate of the (short) error rate
- 88 print tot_s,terr_s, '%e' % ((1.0*terr_s)/tot_s)
- 89
- 90
- 91 if __name__ == '__main__':
- 92 main (sys.argv[1:])
-</pre><p>
-The program is called by
-</p><div class="literallayout"><p><br>
-./test_tcm.py fsm_fname Es/No_db repetitions<br>
-</p></div><p>
-where "fsm_fname" is the file containing the FSM specification of the
-tested TCM code, "Es/No_db" is the SNR in dB, and "repetitions"
-are the number of packets to be transmitted and received in order to
-collect sufficient number of errors for an accurate estimate of the
-error rate.
-</p><p>
-The FSM is first intantiated in "main" by
-</p><pre class="programlisting">
- 62 f=trellis.fsm(fname) # get the FSM specification from a file (will hopefully be automated in the future...)
-</pre><p>
-Each packet has size Kb bits
-(we choose Kb to be a multiple of 16 so that all bits fit nicely into shorts and can be generated by the lfsr GNU Radio).
-Assuming that the FSM input has cardinality I, each input symbol consists
-of bitspersymbol=log<sub>2</sub>( I ). The Kb/16 shorts are now
-unpacked to K=Kb/bitspersymbol input
-symbols that will drive the FSM encoder.
-</p><pre class="programlisting">
- 63 Kb=1024*16 # packet size in bits (make it multiple of 16 so it can be packed in a short)
- 64 bitspersymbol = int(round(math.log(f.I())/math.log(2))) # bits per FSM input symbol
- 65 K=Kb/bitspersymbol # packet size in trellis steps
-</pre><p>
-The FSM will produce K output symbols (remeber the FSM produces always one output symbol for each input symbol). Each of these symbols needs to be modulated. Since we are simulating the communication system, we need not simulate the actual waveforms. An M-ary, N-dimensional
-modulation is completely specified by a set of M, N-dimensional real vectors. In "fsm_utils.py" file we give a number of useful modulations with the following format: modulation = (N,constellation), where
-constellation=[c11,c12,...,c1N,c21,c22,...,c2N,...,cM1,cM2,...cMN].
-The meaning of the above is that every constellation point c_i
-is an N-dimnsional vector c_i=(ci1,ci2,...,ciN)
-For instance, 4-ary PAM is represented as
-(1,[-3, -1, 1, 3]), while QPSK is represented as
-(2,[1, 0, 0, 1, 0, -1, -1, 0]). In our example we choose QPSK modulation.
-Clearly, M should be equal to the cardinality of the FSM output, O.
-Finally the average symbol energy and noise variance are calculated.
-</p><pre class="programlisting">
- 66 modulation = fsm_utils.psk4 # see fsm_utlis.py for available predefined modulations
- 67 dimensionality = modulation[0]
- 68 constellation = modulation[1]
- 69 if len(constellation)/dimensionality != f.O():
- 70 sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n')
- 71 sys.exit (1)
- 72 # calculate average symbol energy
- 73 Es = 0
- 74 for i in range(len(constellation)):
- 75 Es = Es + constellation[i]**2
- 76 Es = Es / (len(constellation)/dimensionality)
- 77 N0=Es/pow(10.0,esn0_db/10.0); # noise variance
-</pre><p>
-Then, "run_test" is called with a different "seed" so that we get
-different noise realizations.
-</p><pre class="programlisting">
- 82 (s,e)=run_test(f,Kb,bitspersymbol,K,dimensionality,constellation,N0,-long(666+i)) # run experiment with different seed to get different noise realizations
-</pre><p>
-Let us examine now the "run_test" function.
-First we set up the transmitter blocks.
-The Kb/16 shorts are first unpacked to
-symbols consistent with the FSM input alphabet.
-The FSm encoder requires the FSM specification,
-and an initial state (which is set to 0 in this example).
-</p><pre class="programlisting">
- 15 # TX
- 16 src = gr.lfsr_32k_source_s()
- 17 src_head = gr.head (gr.sizeof_short,Kb/16) # packet size in shorts
- 18 s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality
- 19 enc = trellis.encoder_ss(f,0) # initial state = 0
-</pre><p>
-We now need to modulate the FSM output symbols.
-The "chunks_to_symbols_sf" is essentially a memoryless mapper which
-for each input symbol y_k
-outputs a sequence of N numbers ci1,ci2,...,ciN representing the
-coordianates of the constellation symbol c_i with i=y_k.
-</p><pre class="programlisting">
- 20 mod = gr.chunks_to_symbols_sf(constellation,dimensionality)
-</pre><p>
-The channel is AWGN with appropriate noise variance.
-For each transmitted symbol c_k=(ck1,ck2,...,ckN) we receive a noisy version
-r_k=(rk1,rk2,...,rkN).
-</p><pre class="programlisting">
- 22 # CHANNEL
- 23 add = gr.add_ff()
- 24 noise = gr.noise_source_f(gr.GR_GAUSSIAN,math.sqrt(N0/2),seed)
-</pre><p>
-Part of the design methodology was to decouple the FSM and VA from
-the details of the modulation, channel, receiver front-end etc.
-In order for the VA to run, we only need to provide it with
-a number representing a cost associated with each transition
-in the trellis. Then the VA will find the sequence with
-the smallest total cost through the trellis.
-The cost associated with a transition (s_k,x_k) is only a function
-of the output y_k = OS(s_k,x_k), and the observation
-vector r_k. Thus, for each time period, k,
-we need to label each of the SxI transitions with such a cost.
-This means that for each time period we need to evaluate
-O such numbers (one for each possible output symbol y_k).
-This is done
-in "metrics_f". In particular, metrics_f is a memoryless device
-taking N inputs at a time and producing O outputs. The N inputs are
-rk1,rk2,...,rkN.
-The O outputs
-are the costs associated with observations rk1,rk2,...,rkN and
-hypothesized output symbols c_1,c_2,...,c_M. For instance,
-if we choose to perform soft-input VA, we need to evaluate
-the Euclidean distance between r_k and each of c_1,c_2,...,c_M,
-for each of the K transmitted symbols.
-Other options are available as well; for instance, we can
-do hard decision demodulation and feed the VA with
-symbol Hamming distances, or even bit Hamming distances, etc.
-These are all implemented in "metrics_f".
-</p><pre class="programlisting">
- 26 # RX
- 27 metrics = trellis.metrics_f(f.O(),dimensionality,constellation,trellis.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for Viterbi
-</pre><p>
-Now the VA can run once it is supplied by the initial and final states.
-The initial state is known to be 0; the final state is usually
-forced to some value by padding the information sequence appropriately.
-In this example, we always send the the same info sequence (we only randomize noise) so we can evaluate off line the final state and then provide it to the VA (a value of -1 signifies that there is no fixed initial
-or final state). The VA outputs the estimates of the symbols x_k which
-are then packed to shorts and compared with the transmitted sequence.
-</p><pre class="programlisting">
- 28 va = trellis.viterbi_s(f,K,0,-1) # Put -1 if the Initial/Final states are not set.
- 29 fsmi2s = gr.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts
- 30 dst = gr.check_lfsr_32k_s();
-</pre><p>
-The function returns the number of shorts and the number of shorts in error. Observe that this way the estimated error rate refers to
-16-bit-symbol error rate.
-</p><pre class="programlisting">
- 48 return (ntotal,ntotal-nright)
-</pre></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="future"></a>Future Work</h2></div></div><div></div></div><div class="itemizedlist"><ul type="disc"><li><p>
-Improve the documentation :-)
-</p></li><li><p>
-automate fsm generation from generator polynomials
-(feedforward or feedback form).
-</p></li><li><p>
-Optimize the VA code.
-</p></li><li><p>
-Provide implementation of soft-input soft-output (SISO) decoders for
-potential use in concatenated systems. Also a host of suboptimal
-decoders, eg, sphere decoding, M- and T- algorithms, sequential decoding, etc.
-can be implemented.
-</p></li><li><p>
-Although turbo decoding is rediculously slow in software,
-we can design it in principle. One question is, whether we should
-use the encoder, and SISO blocks and connect them
-through GNU radio or we should implement turbo-decoding
-as a single block (issues with buffering between blocks).
-</p></li></ul></div></div></div></body></html>
trellis.cc \
fsm.cc \
quicksort_index.cc \
+ base.cc \
interleaver.cc \
trellis_calc_metric.cc \
trellis_permutation.cc \
+ trellis_siso_f.cc \
$(GENERATED_CC)
# magic flags
grinclude_HEADERS = \
fsm.h \
quicksort_index.h \
+ base.h \
interleaver.h \
trellis_metric_type.h \
trellis_calc_metric.h \
trellis_permutation.h \
+ trellis_siso_type.h \
+ trellis_siso_f.h \
$(GENERATED_H)
--- /dev/null
+/* -*- c++ -*- */\r
+/*\r
+ * Copyright 2002 Free Software Foundation, Inc.\r
+ *\r
+ * This file is part of GNU Radio\r
+ *\r
+ * GNU Radio is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2, or (at your option)\r
+ * any later version.\r
+ *\r
+ * GNU Radio is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with GNU Radio; see the file COPYING. If not, write to\r
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,\r
+ * Boston, MA 02111-1307, USA.\r
+ */\r
+\r
+#include <cstdio>\r
+#include <stdexcept>\r
+#include <cmath>\r
+#include "base.h"\r
+\r
+\r
+bool dec2base(unsigned int num, int base, std::vector<int> &s)\r
+{\r
+ int l = s.size();\r
+ unsigned int n=num;\r
+ for(int i=0;i<l;i++) {\r
+ s[l-i-1] = n % base; //MSB first\r
+ n /= base;\r
+ }\r
+ if(n!=0) {\r
+ printf("Number %d requires more than %d digits.",num,l);\r
+ return false;\r
+ }\r
+ else\r
+ return true;\r
+}\r
+\r
+\r
+unsigned int base2dec(const std::vector<int> &s, int base)\r
+{\r
+ int l = s.size();\r
+ unsigned int num=0;\r
+ for(int i=0;i<l;i++)\r
+ num=num*base+s[i];\r
+ return num;\r
+}\r
+\r
+\r
+bool dec2bases(unsigned int num, const std::vector<int> &bases, std::vector<int> &s)\r
+{\r
+ int l = s.size();\r
+ unsigned int n=num;\r
+ for(int i=0;i<l;i++) {\r
+ s[l-i-1] = n % bases[l-i-1];\r
+ n /= bases[l-i-1];\r
+ }\r
+ if(n!=0) {\r
+ printf("Number %d requires more than %d digits.",num,l);\r
+ return false;\r
+ }\r
+ else\r
+ return true;\r
+}\r
+\r
+\r
+\r
+unsigned int bases2dec(const std::vector<int> &s, const std::vector<int> &bases)\r
+{\r
+ int l = s.size();\r
+ unsigned int num=0;\r
+ for(int i=0;i<l;i++)\r
+ num = num * bases[i] + s[i];\r
+ return num;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
--- /dev/null
+/* -*- c++ -*- */\r
+/*\r
+ * Copyright 2002 Free Software Foundation, Inc.\r
+ *\r
+ * This file is part of GNU Radio\r
+ *\r
+ * GNU Radio is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2, or (at your option)\r
+ * any later version.\r
+ *\r
+ * GNU Radio is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with GNU Radio; see the file COPYING. If not, write to\r
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,\r
+ * Boston, MA 02111-1307, USA.\r
+ */\r
+\r
+#ifndef INCLUDED_TRELLIS_BASE_H\r
+#define INCLUDED_TRELLIS_BASE_H\r
+\r
+#include <vector>\r
+\r
+/*!\r
+ * \brief change base\r
+ */\r
+\r
+\r
+bool dec2base(unsigned int num, int base, std::vector<int> &s);\r
+bool dec2bases(unsigned int num, const std::vector<int> &bases, std::vector<int> &s);\r
+unsigned int base2dec(const std::vector<int> &s, int base);\r
+unsigned int bases2dec(const std::vector<int> &s, const std::vector<int> &bases);\r
+\r
+#endif\r
#include <cstdio>\r
#include <stdexcept>\r
#include <cmath>\r
+#include "base.h"\r
#include "fsm.h"\r
\r
+\r
fsm::fsm()\r
{\r
d_I=0;\r
d_OS.resize(0);\r
d_PS.resize(0);\r
d_PI.resize(0);\r
+ d_TMi.resize(0);\r
+ d_TMl.resize(0);\r
}\r
\r
fsm::fsm(const fsm &FSM)\r
d_OS=FSM.OS();\r
d_PS=FSM.PS();\r
d_PI=FSM.PI();\r
+ d_TMi=FSM.TMi();\r
+ d_TMl=FSM.TMl();\r
}\r
\r
-fsm::fsm(const int I, const int S, const int O, const std::vector<int> &NS, const std::vector<int> &OS)\r
+fsm::fsm(int I, int S, int O, const std::vector<int> &NS, const std::vector<int> &OS)\r
{\r
d_I=I;\r
d_S=S;\r
d_O=O;\r
d_NS=NS;\r
d_OS=OS;\r
- d_PS.resize(d_I*d_S);\r
- d_PI.resize(d_I*d_S);\r
- \r
- // generate the PS, PI tables for later use\r
- for(int i=0;i<d_S;i++) {\r
- int j=0;\r
- for(int ii=0;ii<d_S;ii++) for(int jj=0;jj<d_I;jj++) {\r
- if(d_NS[ii*d_I+jj]!=i) continue;\r
- d_PS[i*d_I+j]=ii;\r
- d_PI[i*d_I+j]=jj;\r
- j++;\r
- }\r
- }\r
+ \r
+ generate_PS_PI();\r
+ generate_TM();\r
}\r
\r
//######################################################################\r
FILE *fsmfile;\r
\r
if((fsmfile=fopen(name,"r"))==NULL) \r
- throw std::runtime_error ("file open error in fsm()");\r
+ throw std::runtime_error ("fsm::fsm(const char *name): file open error\n");\r
//printf("file open error in fsm()\n");\r
\r
fscanf(fsmfile,"%d %d %d\n",&d_I,&d_S,&d_O);\r
d_NS.resize(d_I*d_S);\r
d_OS.resize(d_I*d_S);\r
- d_PS.resize(d_I*d_S);\r
- d_PI.resize(d_I*d_S);\r
\r
for(int i=0;i<d_S;i++) {\r
for(int j=0;j<d_I;j++) fscanf(fsmfile,"%d",&(d_NS[i*d_I+j]));\r
for(int i=0;i<d_S;i++) {\r
for(int j=0;j<d_I;j++) fscanf(fsmfile,"%d",&(d_OS[i*d_I+j]));\r
}\r
+ \r
+ generate_PS_PI();\r
+ generate_TM();\r
+}\r
+\r
+\r
+\r
+\r
+//######################################################################\r
+//# Automatically generate the FSM from the generator matrix\r
+//# of a (n,k) binary convolutional code\r
+//######################################################################\r
+fsm::fsm(int k, int n, const std::vector<int> &G)\r
+{\r
+\r
+ // calculate maximum memory requirements for each input stream\r
+ std::vector<int> max_mem_x(k,-1);\r
+ int max_mem = -1;\r
+ for(int i=0;i<k;i++) {\r
+ for(int j=0;j<n;j++) {\r
+ int mem = -1;\r
+ if(G[i*n+j]!=0)\r
+ mem=(int)(log(G[i*n+j])/log(2.0));\r
+ if(mem>max_mem_x[i])\r
+ max_mem_x[i]=mem;\r
+ if(mem>max_mem)\r
+ max_mem=mem;\r
+ }\r
+ }\r
\r
- // generate the PS, PI tables for later use\r
- for(int i=0;i<d_S;i++) {\r
- int j=0;\r
- for(int ii=0;ii<d_S;ii++) for(int jj=0;jj<d_I;jj++) {\r
- if(d_NS[ii*d_I+jj]!=i) continue;\r
- d_PS[i*d_I+j]=ii;\r
- d_PI[i*d_I+j]=jj;\r
- j++;\r
+//printf("max_mem_x\n");\r
+//for(int j=0;j<max_mem_x.size();j++) printf("%d ",max_mem_x[j]); printf("\n");\r
+\r
+ // calculate total memory requirements to set S\r
+ int sum_max_mem = 0;\r
+ for(int i=0;i<k;i++)\r
+ sum_max_mem += max_mem_x[i];\r
+\r
+//printf("sum_max_mem = %d\n",sum_max_mem);\r
+\r
+ d_I=1<<k;\r
+ d_S=1<<sum_max_mem;\r
+ d_O=1<<n;\r
+ \r
+ // binary representation of the G matrix\r
+ std::vector<std::vector<int> > Gb(k*n);\r
+ for(int j=0;j<k*n;j++) {\r
+ Gb[j].resize(max_mem+1);\r
+ dec2base(G[j],2,Gb[j]);\r
+//printf("Gb\n");\r
+//for(int m=0;m<Gb[j].size();m++) printf("%d ",Gb[j][m]); printf("\n");\r
+ }\r
+\r
+ // alphabet size of each shift register \r
+ std::vector<int> bases_x(k);\r
+ for(int j=0;j<k ;j++) \r
+ bases_x[j] = 1 << max_mem_x[j];\r
+//printf("bases_x\n");\r
+//for(int j=0;j<max_mem_x.size();j++) printf("%d ",max_mem_x[j]); printf("\n");\r
+\r
+ d_NS.resize(d_I*d_S);\r
+ d_OS.resize(d_I*d_S);\r
+\r
+ std::vector<int> sx(k);\r
+ std::vector<int> nsx(k);\r
+ std::vector<int> tx(k);\r
+ std::vector<std::vector<int> > tb(k);\r
+ for(int j=0;j<k;j++)\r
+ tb[j].resize(max_mem+1);\r
+ std::vector<int> inb(k);\r
+ std::vector<int> outb(n);\r
+\r
+\r
+ for(int s=0;s<d_S;s++) {\r
+ dec2bases(s,bases_x,sx); // split s into k values, each representing on of the k shift registers\r
+//printf("state = %d \nstates = ",s);\r
+//for(int j=0;j<sx.size();j++) printf("%d ",sx[j]); printf("\n");\r
+ for(int i=0;i<d_I;i++) {\r
+ dec2base(i,2,inb); // input in binary\r
+//printf("input = %d \ninputs = ",i);\r
+//for(int j=0;j<inb.size();j++) printf("%d ",inb[j]); printf("\n");\r
+\r
+ // evaluate next state\r
+ for(int j=0;j<k;j++)\r
+ nsx[j] = (inb[j]*bases_x[j]+sx[j])/2; // next state (for each shift register) MSB first\r
+ d_NS[s*d_I+i]=bases2dec(nsx,bases_x); // collect all values into the new state\r
+\r
+ // evaluate transitions\r
+ for(int j=0;j<k;j++)\r
+ tx[j] = inb[j]*bases_x[j]+sx[j]; // transition (for each shift register)MSB first\r
+ for(int j=0;j<k;j++) {\r
+ dec2base(tx[j],2,tb[j]); // transition in binary\r
+//printf("transition = %d \ntransitions = ",tx[j]);\r
+//for(int m=0;m<tb[j].size();m++) printf("%d ",tb[j][m]); printf("\n");\r
+ }\r
+\r
+ // evaluate outputs\r
+ for(int nn=0;nn<n;nn++) {\r
+ outb[nn] = 0;\r
+ for(int j=0;j<k;j++) {\r
+ for(int m=0;m<max_mem+1;m++)\r
+ outb[nn] = (outb[nn] + Gb[j*n+nn][m]*tb[j][m]) % 2; // careful: polynomial 1+D ir represented as 110, not as 011\r
+//printf("output %d equals %d\n",nn,outb[nn]);\r
+ }\r
+ }\r
+ d_OS[s*d_I+i] = base2dec(outb,2);\r
}\r
}\r
+\r
+ generate_PS_PI();\r
+ generate_TM();\r
}\r
\r
+\r
+\r
+\r
//######################################################################\r
//# Automatically generate an FSM specification describing the \r
//# ISI for a channel\r
//# of length ch_length and a modulation of size mod_size\r
//######################################################################\r
-fsm::fsm(const int mod_size, const int ch_length)\r
+fsm::fsm(int mod_size, int ch_length)\r
{\r
d_I=mod_size;\r
d_S=(int) (pow(1.0*d_I,1.0*ch_length-1)+0.5);\r
\r
d_NS.resize(d_I*d_S);\r
d_OS.resize(d_I*d_S);\r
- d_PS.resize(d_I*d_S);\r
- d_PI.resize(d_I*d_S);\r
\r
for(int s=0;s<d_S;s++) {\r
for(int i=0;i<d_I;i++) { \r
d_OS[s*d_I+i] = t;\r
}\r
}\r
- \r
- // generate the PS, PI tables for later use\r
+ \r
+ generate_PS_PI();\r
+ generate_TM();\r
+}\r
+\r
+\r
+//######################################################################\r
+//# generate the PS and PI tables for later use\r
+//######################################################################\r
+void fsm::generate_PS_PI()\r
+{\r
+ d_PS.resize(d_I*d_S);\r
+ d_PI.resize(d_I*d_S);\r
+\r
for(int i=0;i<d_S;i++) {\r
int j=0;\r
for(int ii=0;ii<d_S;ii++) for(int jj=0;jj<d_I;jj++) {\r
}\r
}\r
}\r
+\r
+\r
+//######################################################################\r
+//# generate the termination matrices TMl and TMi for later use\r
+//######################################################################\r
+void fsm::generate_TM()\r
+{\r
+ d_TMi.resize(d_S*d_S);\r
+ d_TMl.resize(d_S*d_S);\r
+\r
+ for(int i=0;i<d_S*d_S;i++) {\r
+ d_TMi[i] = -1; // no meaning\r
+ d_TMl[i] = d_S; //infinity: you need at most S-1 steps\r
+ if (i/d_S == i%d_S)\r
+ d_TMl[i] = 0;\r
+ }\r
+\r
+ for(int s=0;s<d_S;s++) {\r
+ bool done = false;\r
+ int attempts = 0;\r
+ while (done == false && attempts < d_S-1) {\r
+ done = find_es(s);\r
+ attempts ++;\r
+ }\r
+ if (done == false)\r
+ //throw std::runtime_error ("fsm::generate_TM(): FSM appears to be disconnected\n");\r
+ printf("fsm::generate_TM(): FSM appears to be disconnected\n");\r
+ }\r
+}\r
+\r
+\r
+// find a path from any state to the ending state "es"\r
+bool fsm::find_es(int es)\r
+{\r
+ bool done = true;\r
+ for(int s=0;s<d_S;s++) {\r
+ if(d_TMl[s*d_S+es] < d_S) \r
+ continue;\r
+ int minl=d_S;\r
+ int mini=-1;\r
+ for(int i=0;i<d_I;i++) {\r
+ if( 1 + d_TMl[d_NS[s*d_I+i]*d_S+es] < minl) {\r
+ minl = 1 + d_TMl[d_NS[s*d_I+i]*d_S+es];\r
+ mini = i;\r
+ }\r
+ }\r
+ if (mini != -1) {\r
+ d_TMl[s*d_S+es]=minl;\r
+ d_TMi[s*d_S+es]=mini;\r
+ }\r
+ else\r
+ done = false;\r
+ }\r
+ return done;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
std::vector<int> d_OS;\r
std::vector<int> d_PS;\r
std::vector<int> d_PI;\r
+ std::vector<int> d_TMi;\r
+ std::vector<int> d_TMl;\r
+ void generate_PS_PI ();\r
+ void generate_TM ();\r
+ bool find_es(int es);\r
public:\r
fsm();\r
fsm(const fsm &FSM);\r
- fsm(const int I, const int S, const int O, const std::vector<int> &NS, const std::vector<int> &OS);\r
+ fsm(int I, int S, int O, const std::vector<int> &NS, const std::vector<int> &OS);\r
fsm(const char *name);\r
- fsm(const int mod_size, const int ch_length);\r
+ fsm(int k, int n, const std::vector<int> &G);\r
+ fsm(int mod_size, int ch_length);\r
int I () const { return d_I; }\r
int S () const { return d_S; }\r
int O () const { return d_O; }\r
const std::vector<int> & OS () const { return d_OS; }\r
const std::vector<int> & PS () const { return d_PS; }\r
const std::vector<int> & PI () const { return d_PI; }\r
+ const std::vector<int> & TMi () const { return d_TMi; }\r
+ const std::vector<int> & TMl () const { return d_TMl; }\r
};\r
\r
#endif\r
std::vector<int> d_OS;
std::vector<int> d_PS;
std::vector<int> d_PI;
+ std::vector<int> d_TMi;
+ std::vector<int> d_TMl;
+ void generate_PS_PI ();
+ void generate_TM ();
public:
fsm();
fsm(const fsm &FSM);
- fsm(const int I, const int S, const int O, const std::vector<int> &NS, const std::vector<int> &OS);
+ fsm(int I, int S, int O, const std::vector<int> &NS, const std::vector<int> &OS);
fsm(const char *name);
- fsm(const int mod_size, const int ch_length);
+ fsm(int k, int n, const std::vector<int> &G);
+ fsm(int mod_size, int ch_length);
int I () const { return d_I; }
int S () const { return d_S; }
int O () const { return d_O; }
const std::vector<int> & OS () const { return d_OS; }
const std::vector<int> & PS () const { return d_PS; }
const std::vector<int> & PI () const { return d_PI; }
+ const std::vector<int> & TMi () const { return d_TMi; }
+ const std::vector<int> & TMl () const { return d_TMl; }
};
-
-
-
d_DEINTER=INTERLEAVER.DEINTER();\r
}\r
\r
-interleaver::interleaver(const int K, const std::vector<int> &INTER)\r
+interleaver::interleaver(int K, const std::vector<int> &INTER)\r
{\r
d_K=K;\r
d_INTER=INTER;\r
//######################################################################\r
//# Generate a random interleaver\r
//######################################################################\r
-interleaver::interleaver(const int K, unsigned int seed)\r
+interleaver::interleaver(int K, unsigned int seed)\r
{\r
d_K=K;\r
d_INTER.resize(d_K);\r
public:\r
interleaver();\r
interleaver(const interleaver & INTERLEAVER);\r
- interleaver(const int K, const std::vector<int> & INTER);\r
+ interleaver(int K, const std::vector<int> & INTER);\r
interleaver(const char *name);\r
- interleaver(const int K, unsigned int seed);\r
+ interleaver(int K, unsigned int seed);\r
int K () const { return d_K; }\r
const std::vector<int> & INTER () const { return d_INTER; }\r
const std::vector<int> & DEINTER () const { return d_DEINTER; }\r
public:\r
interleaver();\r
interleaver(const interleaver & INTERLEAVER);\r
- interleaver(const int K, const std::vector<int> & INTER);\r
+ interleaver(int K, const std::vector<int> & INTER);\r
interleaver(const char *name);\r
- interleaver(const int K, unsigned int seed);\r
+ interleaver(int K, unsigned int seed);\r
int K () const { return d_K; }\r
const std::vector<int> & INTER () const { return d_INTER; }\r
const std::vector<int> & DEINTER () const { return d_DEINTER; }\r
#include "fsm.h"
#include "interleaver.h"
#include "trellis_permutation.h"
+#include "trellis_siso_f.h"
#include <stdexcept>
%}
%include "fsm.i"
%include "interleaver.i"
%include "trellis_permutation.i"
+%include "trellis_siso_f.i"
+
%include "trellis_metric_type.h"
+%include "trellis_siso_type.h"
%include "trellis_generated.i"
#include <stdexcept>
#include "trellis_calc_metric.h"
-// soft decisions (Euclidean distance squared)
-void calc_metric_s(const int O, const int D, const std::vector<short> &TABLE, const short *in, float *metric, trellis_metric_type_t type)
+void calc_metric_s(int O, int D, const std::vector<short> &TABLE, const short *in, float *metric, trellis_metric_type_t type)
{
float minm = FLT_MAX;
int minmi = 0;
switch (type){
case TRELLIS_EUCLIDEAN:
for(int o=0;o<O;o++) {
- metric[o]=0.0;
- for (int m=0;m<D;m++) {
- float s=in[m]-TABLE[o*D+m];
- metric[o]+=s*s;
- }
+ metric[o]=0.0;
+ for (int m=0;m<D;m++) {
+ float s=in[m]-TABLE[o*D+m];
+ metric[o]+=s*s;
+ }
}
break;
case TRELLIS_HARD_SYMBOL:
for(int o=0;o<O;o++) {
- metric[o]=0.0;
- for (int m=0;m<D;m++) {
- float s=in[m]-TABLE[o*D+m];
- metric[o]+=s*s;
- }
- if(metric[o]<minm) {
- minm=metric[o];
- minmi=o;
- }
+ metric[o]=0.0;
+ for (int m=0;m<D;m++) {
+ float s=in[m]-TABLE[o*D+m];
+ metric[o]+=s*s;
+ }
+ if(metric[o]<minm) {
+ minm=metric[o];
+ minmi=o;
+ }
}
for(int o=0;o<O;o++) {
metric[o] = (o==minmi?0.0:1.0);
-// soft decisions (Euclidean distance squared)
-void calc_metric_i(const int O, const int D, const std::vector<int> &TABLE, const int *in, float *metric, trellis_metric_type_t type)
+void calc_metric_i(int O, int D, const std::vector<int> &TABLE, const int *in, float *metric, trellis_metric_type_t type)
{
float minm = FLT_MAX;
int minmi = 0;
switch (type){
case TRELLIS_EUCLIDEAN:
for(int o=0;o<O;o++) {
- metric[o]=0.0;
- for (int m=0;m<D;m++) {
- float s=in[m]-TABLE[o*D+m];
- metric[o]+=s*s;
- }
+ metric[o]=0.0;
+ for (int m=0;m<D;m++) {
+ float s=in[m]-TABLE[o*D+m];
+ metric[o]+=s*s;
+ }
}
break;
case TRELLIS_HARD_SYMBOL:
for(int o=0;o<O;o++) {
- metric[o]=0.0;
- for (int m=0;m<D;m++) {
- float s=in[m]-TABLE[o*D+m];
- metric[o]+=s*s;
- }
- if(metric[o]<minm) {
- minm=metric[o];
- minmi=o;
- }
+ metric[o]=0.0;
+ for (int m=0;m<D;m++) {
+ float s=in[m]-TABLE[o*D+m];
+ metric[o]+=s*s;
+ }
+ if(metric[o]<minm) {
+ minm=metric[o];
+ minmi=o;
+ }
}
for(int o=0;o<O;o++) {
metric[o] = (o==minmi?0.0:1.0);
-
-
-
-
-// soft decisions (Euclidean distance squared)
-void calc_metric_f(const int O, const int D, const std::vector<float> &TABLE, const float *in, float *metric, trellis_metric_type_t type)
+void calc_metric_f(int O, int D, const std::vector<float> &TABLE, const float *in, float *metric, trellis_metric_type_t type)
{
float minm = FLT_MAX;
int minmi = 0;
switch (type){
case TRELLIS_EUCLIDEAN:
for(int o=0;o<O;o++) {
- metric[o]=0.0;
- for (int m=0;m<D;m++) {
- float s=in[m]-TABLE[o*D+m];
- metric[o]+=s*s;
- }
+ metric[o]=0.0;
+ for (int m=0;m<D;m++) {
+ float s=in[m]-TABLE[o*D+m];
+ metric[o]+=s*s;
+ }
}
break;
case TRELLIS_HARD_SYMBOL:
for(int o=0;o<O;o++) {
- metric[o]=0.0;
- for (int m=0;m<D;m++) {
- float s=in[m]-TABLE[o*D+m];
- metric[o]+=s*s;
- }
- if(metric[o]<minm) {
- minm=metric[o];
- minmi=o;
- }
+ metric[o]=0.0;
+ for (int m=0;m<D;m++) {
+ float s=in[m]-TABLE[o*D+m];
+ metric[o]+=s*s;
+ }
+ if(metric[o]<minm) {
+ minm=metric[o];
+ minmi=o;
+ }
}
for(int o=0;o<O;o++) {
metric[o] = (o==minmi?0.0:1.0);
}
-// soft decisions (Euclidean distance squared)
-void calc_metric_c(const int O, const int D, const std::vector<gr_complex> &TABLE, const gr_complex *in, float *metric, trellis_metric_type_t type)
+void calc_metric_c(int O, int D, const std::vector<gr_complex> &TABLE, const gr_complex *in, float *metric, trellis_metric_type_t type)
{
float minm = FLT_MAX;
int minmi = 0;
}
}
case TRELLIS_HARD_SYMBOL:
- throw std::runtime_error ("Invalid metric type (not yet implemented).");
+ for(int o=0;o<O;o++) {
+ metric[o]=0.0;
+ for (int m=0;m<D;m++) {
+ gr_complex s=in[m]-TABLE[o*D+m];
+ metric[o]+=s.real()*s.real()+s.imag()*s.imag();
+ }
+ if(metric[o]<minm) {
+ minm=metric[o];
+ minmi=o;
+ }
+ }
+ for(int o=0;o<O;o++) {
+ metric[o] = (o==minmi?0.0:1.0);
+ }
break;
case TRELLIS_HARD_BIT:
throw std::runtime_error ("Invalid metric type (not yet implemented).");
#include <gr_complex.h>
#include <trellis_metric_type.h>
-void calc_metric_s(const int O, const int D, const std::vector<short> &TABLE, const short *in, float *metric, trellis_metric_type_t type);
+void calc_metric_s(int O, int D, const std::vector<short> &TABLE, const short *in, float *metric, trellis_metric_type_t type);
-void calc_metric_i(const int O, const int D, const std::vector<int> &TABLE, const int *in, float *metric, trellis_metric_type_t type);
+void calc_metric_i(int O, int D, const std::vector<int> &TABLE, const int *in, float *metric, trellis_metric_type_t type);
-void calc_metric_f(const int O, const int D, const std::vector<float> &TABLE, const float *in, float *metric, trellis_metric_type_t type);
+void calc_metric_f(int O, int D, const std::vector<float> &TABLE, const float *in, float *metric, trellis_metric_type_t type);
-void calc_metric_c(const int O, const int D, const std::vector<gr_complex> &TABLE, const gr_complex *in, float *metric, trellis_metric_type_t type);
+void calc_metric_c(int O, int D, const std::vector<gr_complex> &TABLE, const gr_complex *in, float *metric, trellis_metric_type_t type);
#endif
#include <iostream>
@SPTR_NAME@
-trellis_make_@BASE_NAME@ (const fsm &FSM, const int ST)
+trellis_make_@BASE_NAME@ (const fsm &FSM, int ST)
{
return @SPTR_NAME@ (new @NAME@ (FSM,ST));
}
-@NAME@::@NAME@ (const fsm &FSM, const int ST)
+@NAME@::@NAME@ (const fsm &FSM, int ST)
: gr_sync_block ("@BASE_NAME@",
gr_make_io_signature (1, -1, sizeof (@I_TYPE@)),
gr_make_io_signature (1, -1, sizeof (@O_TYPE@))),
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
- int d_ST_tmp;
+ int ST_tmp;
assert (input_items.size() == output_items.size());
int nstreams = input_items.size();
-for (int m=0;m<nstreams;m++) {
- const @I_TYPE@ *in = (const @I_TYPE@ *) input_items[m];
- @O_TYPE@ *out = (@O_TYPE@ *) output_items[m];
- d_ST_tmp = d_ST;
+ for (int m=0;m<nstreams;m++) {
+ const @I_TYPE@ *in = (const @I_TYPE@ *) input_items[m];
+ @O_TYPE@ *out = (@O_TYPE@ *) output_items[m];
+ ST_tmp = d_ST;
-// per stream processing
-
- for (int i = 0; i < noutput_items; i++){
- out[i] = (@O_TYPE@) d_FSM.OS()[d_ST_tmp*d_FSM.I()+in[i]]; // direction of time?
- d_ST_tmp = (int) d_FSM.NS()[d_ST_tmp*d_FSM.I()+in[i]];
+ // per stream processing
+ for (int i = 0; i < noutput_items; i++){
+ out[i] = (@O_TYPE@) d_FSM.OS()[ST_tmp*d_FSM.I()+in[i]]; // direction of time?
+ ST_tmp = (int) d_FSM.NS()[ST_tmp*d_FSM.I()+in[i]];
+ }
+ // end per stream processing
}
-
-// end per stream processing
-}
- d_ST = d_ST_tmp;
+ d_ST = ST_tmp;
return noutput_items;
}
class @NAME@;
typedef boost::shared_ptr<@NAME@> @SPTR_NAME@;
-@SPTR_NAME@ trellis_make_@BASE_NAME@ (const fsm &FSM, const int ST);
+@SPTR_NAME@ trellis_make_@BASE_NAME@ (const fsm &FSM, int ST);
/*!
* \brief Convolutional encoder.
class @NAME@ : public gr_sync_block
{
private:
- friend @SPTR_NAME@ trellis_make_@BASE_NAME@ (const fsm &FSM, const int ST);
+ friend @SPTR_NAME@ trellis_make_@BASE_NAME@ (const fsm &FSM, int ST);
fsm d_FSM;
int d_ST;
- @NAME@ (const fsm &FSM, const int ST);
+ @NAME@ (const fsm &FSM, int ST);
public:
fsm FSM () const { return d_FSM; }
GR_SWIG_BLOCK_MAGIC(trellis,@BASE_NAME@);
-@SPTR_NAME@ trellis_make_@BASE_NAME@ (const fsm &FSM, const int ST);
+@SPTR_NAME@ trellis_make_@BASE_NAME@ (const fsm &FSM, int ST);
class @NAME@ : public gr_sync_block
{
private:
- @NAME@ (const fsm &FSM, const int ST);
+ @NAME@ (const fsm &FSM, int ST);
public:
fsm FSM () const { return d_FSM; }
int ST () const { return d_ST; }
#include <iostream>
trellis_encoder_bb_sptr
-trellis_make_encoder_bb (const fsm &FSM, const int ST)
+trellis_make_encoder_bb (const fsm &FSM, int ST)
{
return trellis_encoder_bb_sptr (new trellis_encoder_bb (FSM,ST));
}
-trellis_encoder_bb::trellis_encoder_bb (const fsm &FSM, const int ST)
+trellis_encoder_bb::trellis_encoder_bb (const fsm &FSM, int ST)
: gr_sync_block ("encoder_bb",
gr_make_io_signature (1, -1, sizeof (unsigned char)),
gr_make_io_signature (1, -1, sizeof (unsigned char))),
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
- int d_ST_tmp;
+ int ST_tmp;
assert (input_items.size() == output_items.size());
int nstreams = input_items.size();
-for (int m=0;m<nstreams;m++) {
- const unsigned char *in = (const unsigned char *) input_items[m];
- unsigned char *out = (unsigned char *) output_items[m];
- d_ST_tmp = d_ST;
+ for (int m=0;m<nstreams;m++) {
+ const unsigned char *in = (const unsigned char *) input_items[m];
+ unsigned char *out = (unsigned char *) output_items[m];
+ ST_tmp = d_ST;
-// per stream processing
-
- for (int i = 0; i < noutput_items; i++){
- out[i] = (unsigned char) d_FSM.OS()[d_ST_tmp*d_FSM.I()+in[i]]; // direction of time?
- d_ST_tmp = (int) d_FSM.NS()[d_ST_tmp*d_FSM.I()+in[i]];
+ // per stream processing
+ for (int i = 0; i < noutput_items; i++){
+ out[i] = (unsigned char) d_FSM.OS()[ST_tmp*d_FSM.I()+in[i]]; // direction of time?
+ ST_tmp = (int) d_FSM.NS()[ST_tmp*d_FSM.I()+in[i]];
+ }
+ // end per stream processing
}
-
-// end per stream processing
-}
- d_ST = d_ST_tmp;
+ d_ST = ST_tmp;
return noutput_items;
}
class trellis_encoder_bb;
typedef boost::shared_ptr<trellis_encoder_bb> trellis_encoder_bb_sptr;
-trellis_encoder_bb_sptr trellis_make_encoder_bb (const fsm &FSM, const int ST);
+trellis_encoder_bb_sptr trellis_make_encoder_bb (const fsm &FSM, int ST);
/*!
* \brief Convolutional encoder.
class trellis_encoder_bb : public gr_sync_block
{
private:
- friend trellis_encoder_bb_sptr trellis_make_encoder_bb (const fsm &FSM, const int ST);
+ friend trellis_encoder_bb_sptr trellis_make_encoder_bb (const fsm &FSM, int ST);
fsm d_FSM;
int d_ST;
- trellis_encoder_bb (const fsm &FSM, const int ST);
+ trellis_encoder_bb (const fsm &FSM, int ST);
public:
fsm FSM () const { return d_FSM; }
GR_SWIG_BLOCK_MAGIC(trellis,encoder_bb);
-trellis_encoder_bb_sptr trellis_make_encoder_bb (const fsm &FSM, const int ST);
+trellis_encoder_bb_sptr trellis_make_encoder_bb (const fsm &FSM, int ST);
class trellis_encoder_bb : public gr_sync_block
{
private:
- trellis_encoder_bb (const fsm &FSM, const int ST);
+ trellis_encoder_bb (const fsm &FSM, int ST);
public:
fsm FSM () const { return d_FSM; }
int ST () const { return d_ST; }
#include <iostream>
trellis_encoder_bi_sptr
-trellis_make_encoder_bi (const fsm &FSM, const int ST)
+trellis_make_encoder_bi (const fsm &FSM, int ST)
{
return trellis_encoder_bi_sptr (new trellis_encoder_bi (FSM,ST));
}
-trellis_encoder_bi::trellis_encoder_bi (const fsm &FSM, const int ST)
+trellis_encoder_bi::trellis_encoder_bi (const fsm &FSM, int ST)
: gr_sync_block ("encoder_bi",
gr_make_io_signature (1, -1, sizeof (unsigned char)),
gr_make_io_signature (1, -1, sizeof (int))),
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
- int d_ST_tmp;
+ int ST_tmp;
assert (input_items.size() == output_items.size());
int nstreams = input_items.size();
-for (int m=0;m<nstreams;m++) {
- const unsigned char *in = (const unsigned char *) input_items[m];
- int *out = (int *) output_items[m];
- d_ST_tmp = d_ST;
+ for (int m=0;m<nstreams;m++) {
+ const unsigned char *in = (const unsigned char *) input_items[m];
+ int *out = (int *) output_items[m];
+ ST_tmp = d_ST;
-// per stream processing
-
- for (int i = 0; i < noutput_items; i++){
- out[i] = (int) d_FSM.OS()[d_ST_tmp*d_FSM.I()+in[i]]; // direction of time?
- d_ST_tmp = (int) d_FSM.NS()[d_ST_tmp*d_FSM.I()+in[i]];
+ // per stream processing
+ for (int i = 0; i < noutput_items; i++){
+ out[i] = (int) d_FSM.OS()[ST_tmp*d_FSM.I()+in[i]]; // direction of time?
+ ST_tmp = (int) d_FSM.NS()[ST_tmp*d_FSM.I()+in[i]];
+ }
+ // end per stream processing
}
-
-// end per stream processing
-}
- d_ST = d_ST_tmp;
+ d_ST = ST_tmp;
return noutput_items;
}
class trellis_encoder_bi;
typedef boost::shared_ptr<trellis_encoder_bi> trellis_encoder_bi_sptr;
-trellis_encoder_bi_sptr trellis_make_encoder_bi (const fsm &FSM, const int ST);
+trellis_encoder_bi_sptr trellis_make_encoder_bi (const fsm &FSM, int ST);
/*!
* \brief Convolutional encoder.
class trellis_encoder_bi : public gr_sync_block
{
private:
- friend trellis_encoder_bi_sptr trellis_make_encoder_bi (const fsm &FSM, const int ST);
+ friend trellis_encoder_bi_sptr trellis_make_encoder_bi (const fsm &FSM, int ST);
fsm d_FSM;
int d_ST;
- trellis_encoder_bi (const fsm &FSM, const int ST);
+ trellis_encoder_bi (const fsm &FSM, int ST);
public:
fsm FSM () const { return d_FSM; }
GR_SWIG_BLOCK_MAGIC(trellis,encoder_bi);
-trellis_encoder_bi_sptr trellis_make_encoder_bi (const fsm &FSM, const int ST);
+trellis_encoder_bi_sptr trellis_make_encoder_bi (const fsm &FSM, int ST);
class trellis_encoder_bi : public gr_sync_block
{
private:
- trellis_encoder_bi (const fsm &FSM, const int ST);
+ trellis_encoder_bi (const fsm &FSM, int ST);
public:
fsm FSM () const { return d_FSM; }
int ST () const { return d_ST; }
#include <iostream>
trellis_encoder_bs_sptr
-trellis_make_encoder_bs (const fsm &FSM, const int ST)
+trellis_make_encoder_bs (const fsm &FSM, int ST)
{
return trellis_encoder_bs_sptr (new trellis_encoder_bs (FSM,ST));
}
-trellis_encoder_bs::trellis_encoder_bs (const fsm &FSM, const int ST)
+trellis_encoder_bs::trellis_encoder_bs (const fsm &FSM, int ST)
: gr_sync_block ("encoder_bs",
gr_make_io_signature (1, -1, sizeof (unsigned char)),
gr_make_io_signature (1, -1, sizeof (short))),
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
- int d_ST_tmp;
+ int ST_tmp;
assert (input_items.size() == output_items.size());
int nstreams = input_items.size();
-for (int m=0;m<nstreams;m++) {
- const unsigned char *in = (const unsigned char *) input_items[m];
- short *out = (short *) output_items[m];
- d_ST_tmp = d_ST;
+ for (int m=0;m<nstreams;m++) {
+ const unsigned char *in = (const unsigned char *) input_items[m];
+ short *out = (short *) output_items[m];
+ ST_tmp = d_ST;
-// per stream processing
-
- for (int i = 0; i < noutput_items; i++){
- out[i] = (short) d_FSM.OS()[d_ST_tmp*d_FSM.I()+in[i]]; // direction of time?
- d_ST_tmp = (int) d_FSM.NS()[d_ST_tmp*d_FSM.I()+in[i]];
+ // per stream processing
+ for (int i = 0; i < noutput_items; i++){
+ out[i] = (short) d_FSM.OS()[ST_tmp*d_FSM.I()+in[i]]; // direction of time?
+ ST_tmp = (int) d_FSM.NS()[ST_tmp*d_FSM.I()+in[i]];
+ }
+ // end per stream processing
}
-
-// end per stream processing
-}
- d_ST = d_ST_tmp;
+ d_ST = ST_tmp;
return noutput_items;
}
class trellis_encoder_bs;
typedef boost::shared_ptr<trellis_encoder_bs> trellis_encoder_bs_sptr;
-trellis_encoder_bs_sptr trellis_make_encoder_bs (const fsm &FSM, const int ST);
+trellis_encoder_bs_sptr trellis_make_encoder_bs (const fsm &FSM, int ST);
/*!
* \brief Convolutional encoder.
class trellis_encoder_bs : public gr_sync_block
{
private:
- friend trellis_encoder_bs_sptr trellis_make_encoder_bs (const fsm &FSM, const int ST);
+ friend trellis_encoder_bs_sptr trellis_make_encoder_bs (const fsm &FSM, int ST);
fsm d_FSM;
int d_ST;
- trellis_encoder_bs (const fsm &FSM, const int ST);
+ trellis_encoder_bs (const fsm &FSM, int ST);
public:
fsm FSM () const { return d_FSM; }
GR_SWIG_BLOCK_MAGIC(trellis,encoder_bs);
-trellis_encoder_bs_sptr trellis_make_encoder_bs (const fsm &FSM, const int ST);
+trellis_encoder_bs_sptr trellis_make_encoder_bs (const fsm &FSM, int ST);
class trellis_encoder_bs : public gr_sync_block
{
private:
- trellis_encoder_bs (const fsm &FSM, const int ST);
+ trellis_encoder_bs (const fsm &FSM, int ST);
public:
fsm FSM () const { return d_FSM; }
int ST () const { return d_ST; }
#include <iostream>
trellis_encoder_ii_sptr
-trellis_make_encoder_ii (const fsm &FSM, const int ST)
+trellis_make_encoder_ii (const fsm &FSM, int ST)
{
return trellis_encoder_ii_sptr (new trellis_encoder_ii (FSM,ST));
}
-trellis_encoder_ii::trellis_encoder_ii (const fsm &FSM, const int ST)
+trellis_encoder_ii::trellis_encoder_ii (const fsm &FSM, int ST)
: gr_sync_block ("encoder_ii",
gr_make_io_signature (1, -1, sizeof (int)),
gr_make_io_signature (1, -1, sizeof (int))),
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
- int d_ST_tmp;
+ int ST_tmp;
assert (input_items.size() == output_items.size());
int nstreams = input_items.size();
-for (int m=0;m<nstreams;m++) {
- const int *in = (const int *) input_items[m];
- int *out = (int *) output_items[m];
- d_ST_tmp = d_ST;
+ for (int m=0;m<nstreams;m++) {
+ const int *in = (const int *) input_items[m];
+ int *out = (int *) output_items[m];
+ ST_tmp = d_ST;
-// per stream processing
-
- for (int i = 0; i < noutput_items; i++){
- out[i] = (int) d_FSM.OS()[d_ST_tmp*d_FSM.I()+in[i]]; // direction of time?
- d_ST_tmp = (int) d_FSM.NS()[d_ST_tmp*d_FSM.I()+in[i]];
+ // per stream processing
+ for (int i = 0; i < noutput_items; i++){
+ out[i] = (int) d_FSM.OS()[ST_tmp*d_FSM.I()+in[i]]; // direction of time?
+ ST_tmp = (int) d_FSM.NS()[ST_tmp*d_FSM.I()+in[i]];
+ }
+ // end per stream processing
}
-
-// end per stream processing
-}
- d_ST = d_ST_tmp;
+ d_ST = ST_tmp;
return noutput_items;
}
class trellis_encoder_ii;
typedef boost::shared_ptr<trellis_encoder_ii> trellis_encoder_ii_sptr;
-trellis_encoder_ii_sptr trellis_make_encoder_ii (const fsm &FSM, const int ST);
+trellis_encoder_ii_sptr trellis_make_encoder_ii (const fsm &FSM, int ST);
/*!
* \brief Convolutional encoder.
class trellis_encoder_ii : public gr_sync_block
{
private:
- friend trellis_encoder_ii_sptr trellis_make_encoder_ii (const fsm &FSM, const int ST);
+ friend trellis_encoder_ii_sptr trellis_make_encoder_ii (const fsm &FSM, int ST);
fsm d_FSM;
int d_ST;
- trellis_encoder_ii (const fsm &FSM, const int ST);
+ trellis_encoder_ii (const fsm &FSM, int ST);
public:
fsm FSM () const { return d_FSM; }
GR_SWIG_BLOCK_MAGIC(trellis,encoder_ii);
-trellis_encoder_ii_sptr trellis_make_encoder_ii (const fsm &FSM, const int ST);
+trellis_encoder_ii_sptr trellis_make_encoder_ii (const fsm &FSM, int ST);
class trellis_encoder_ii : public gr_sync_block
{
private:
- trellis_encoder_ii (const fsm &FSM, const int ST);
+ trellis_encoder_ii (const fsm &FSM, int ST);
public:
fsm FSM () const { return d_FSM; }
int ST () const { return d_ST; }
#include <iostream>
trellis_encoder_si_sptr
-trellis_make_encoder_si (const fsm &FSM, const int ST)
+trellis_make_encoder_si (const fsm &FSM, int ST)
{
return trellis_encoder_si_sptr (new trellis_encoder_si (FSM,ST));
}
-trellis_encoder_si::trellis_encoder_si (const fsm &FSM, const int ST)
+trellis_encoder_si::trellis_encoder_si (const fsm &FSM, int ST)
: gr_sync_block ("encoder_si",
gr_make_io_signature (1, -1, sizeof (short)),
gr_make_io_signature (1, -1, sizeof (int))),
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
- int d_ST_tmp;
+ int ST_tmp;
assert (input_items.size() == output_items.size());
int nstreams = input_items.size();
-for (int m=0;m<nstreams;m++) {
- const short *in = (const short *) input_items[m];
- int *out = (int *) output_items[m];
- d_ST_tmp = d_ST;
+ for (int m=0;m<nstreams;m++) {
+ const short *in = (const short *) input_items[m];
+ int *out = (int *) output_items[m];
+ ST_tmp = d_ST;
-// per stream processing
-
- for (int i = 0; i < noutput_items; i++){
- out[i] = (int) d_FSM.OS()[d_ST_tmp*d_FSM.I()+in[i]]; // direction of time?
- d_ST_tmp = (int) d_FSM.NS()[d_ST_tmp*d_FSM.I()+in[i]];
+ // per stream processing
+ for (int i = 0; i < noutput_items; i++){
+ out[i] = (int) d_FSM.OS()[ST_tmp*d_FSM.I()+in[i]]; // direction of time?
+ ST_tmp = (int) d_FSM.NS()[ST_tmp*d_FSM.I()+in[i]];
+ }
+ // end per stream processing
}
-
-// end per stream processing
-}
- d_ST = d_ST_tmp;
+ d_ST = ST_tmp;
return noutput_items;
}
class trellis_encoder_si;
typedef boost::shared_ptr<trellis_encoder_si> trellis_encoder_si_sptr;
-trellis_encoder_si_sptr trellis_make_encoder_si (const fsm &FSM, const int ST);
+trellis_encoder_si_sptr trellis_make_encoder_si (const fsm &FSM, int ST);
/*!
* \brief Convolutional encoder.
class trellis_encoder_si : public gr_sync_block
{
private:
- friend trellis_encoder_si_sptr trellis_make_encoder_si (const fsm &FSM, const int ST);
+ friend trellis_encoder_si_sptr trellis_make_encoder_si (const fsm &FSM, int ST);
fsm d_FSM;
int d_ST;
- trellis_encoder_si (const fsm &FSM, const int ST);
+ trellis_encoder_si (const fsm &FSM, int ST);
public:
fsm FSM () const { return d_FSM; }
GR_SWIG_BLOCK_MAGIC(trellis,encoder_si);
-trellis_encoder_si_sptr trellis_make_encoder_si (const fsm &FSM, const int ST);
+trellis_encoder_si_sptr trellis_make_encoder_si (const fsm &FSM, int ST);
class trellis_encoder_si : public gr_sync_block
{
private:
- trellis_encoder_si (const fsm &FSM, const int ST);
+ trellis_encoder_si (const fsm &FSM, int ST);
public:
fsm FSM () const { return d_FSM; }
int ST () const { return d_ST; }
#include <iostream>
trellis_encoder_ss_sptr
-trellis_make_encoder_ss (const fsm &FSM, const int ST)
+trellis_make_encoder_ss (const fsm &FSM, int ST)
{
return trellis_encoder_ss_sptr (new trellis_encoder_ss (FSM,ST));
}
-trellis_encoder_ss::trellis_encoder_ss (const fsm &FSM, const int ST)
+trellis_encoder_ss::trellis_encoder_ss (const fsm &FSM, int ST)
: gr_sync_block ("encoder_ss",
gr_make_io_signature (1, -1, sizeof (short)),
gr_make_io_signature (1, -1, sizeof (short))),
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
- int d_ST_tmp;
+ int ST_tmp;
assert (input_items.size() == output_items.size());
int nstreams = input_items.size();
-for (int m=0;m<nstreams;m++) {
- const short *in = (const short *) input_items[m];
- short *out = (short *) output_items[m];
- d_ST_tmp = d_ST;
+ for (int m=0;m<nstreams;m++) {
+ const short *in = (const short *) input_items[m];
+ short *out = (short *) output_items[m];
+ ST_tmp = d_ST;
-// per stream processing
-
- for (int i = 0; i < noutput_items; i++){
- out[i] = (short) d_FSM.OS()[d_ST_tmp*d_FSM.I()+in[i]]; // direction of time?
- d_ST_tmp = (int) d_FSM.NS()[d_ST_tmp*d_FSM.I()+in[i]];
+ // per stream processing
+ for (int i = 0; i < noutput_items; i++){
+ out[i] = (short) d_FSM.OS()[ST_tmp*d_FSM.I()+in[i]]; // direction of time?
+ ST_tmp = (int) d_FSM.NS()[ST_tmp*d_FSM.I()+in[i]];
+ }
+ // end per stream processing
}
-
-// end per stream processing
-}
- d_ST = d_ST_tmp;
+ d_ST = ST_tmp;
return noutput_items;
}
class trellis_encoder_ss;
typedef boost::shared_ptr<trellis_encoder_ss> trellis_encoder_ss_sptr;
-trellis_encoder_ss_sptr trellis_make_encoder_ss (const fsm &FSM, const int ST);
+trellis_encoder_ss_sptr trellis_make_encoder_ss (const fsm &FSM, int ST);
/*!
* \brief Convolutional encoder.
class trellis_encoder_ss : public gr_sync_block
{
private:
- friend trellis_encoder_ss_sptr trellis_make_encoder_ss (const fsm &FSM, const int ST);
+ friend trellis_encoder_ss_sptr trellis_make_encoder_ss (const fsm &FSM, int ST);
fsm d_FSM;
int d_ST;
- trellis_encoder_ss (const fsm &FSM, const int ST);
+ trellis_encoder_ss (const fsm &FSM, int ST);
public:
fsm FSM () const { return d_FSM; }
GR_SWIG_BLOCK_MAGIC(trellis,encoder_ss);
-trellis_encoder_ss_sptr trellis_make_encoder_ss (const fsm &FSM, const int ST);
+trellis_encoder_ss_sptr trellis_make_encoder_ss (const fsm &FSM, int ST);
class trellis_encoder_ss : public gr_sync_block
{
private:
- trellis_encoder_ss (const fsm &FSM, const int ST);
+ trellis_encoder_ss (const fsm &FSM, int ST);
public:
fsm FSM () const { return d_FSM; }
int ST () const { return d_ST; }
@SPTR_NAME@
-trellis_make_@BASE_NAME@ (const int O, const int D, const std::vector<@I_TYPE@> &TABLE, trellis_metric_type_t TYPE)
+trellis_make_@BASE_NAME@ (int O, int D, const std::vector<@I_TYPE@> &TABLE, trellis_metric_type_t TYPE)
{
return @SPTR_NAME@ (new @NAME@ (O,D,TABLE,TYPE));
}
-@NAME@::@NAME@ (const int O, const int D, const std::vector<@I_TYPE@> &TABLE, trellis_metric_type_t TYPE)
+@NAME@::@NAME@ (int O, int D, const std::vector<@I_TYPE@> &TABLE, trellis_metric_type_t TYPE)
: gr_block ("@BASE_NAME@",
gr_make_io_signature (1, -1, sizeof (@I_TYPE@)),
gr_make_io_signature (1, -1, sizeof (float))),
class @NAME@;
typedef boost::shared_ptr<@NAME@> @SPTR_NAME@;
-@SPTR_NAME@ trellis_make_@BASE_NAME@ (const int O, const int D, const std::vector<@I_TYPE@> &TABLE, trellis_metric_type_t TYPE);
+@SPTR_NAME@ trellis_make_@BASE_NAME@ (int O, int D, const std::vector<@I_TYPE@> &TABLE, trellis_metric_type_t TYPE);
/*!
* \brief Evaluate metrics for use by the Viterbi algorithm.
trellis_metric_type_t d_TYPE;
std::vector<@I_TYPE@> d_TABLE;
- friend @SPTR_NAME@ trellis_make_@BASE_NAME@ (const int O, const int D, const std::vector<@I_TYPE@> &TABLE, trellis_metric_type_t TYPE);
- @NAME@ (const int O, const int D, const std::vector<@I_TYPE@> &TABLE, trellis_metric_type_t TYPE);
+ friend @SPTR_NAME@ trellis_make_@BASE_NAME@ (int O, int D, const std::vector<@I_TYPE@> &TABLE, trellis_metric_type_t TYPE);
+ @NAME@ (int O, int D, const std::vector<@I_TYPE@> &TABLE, trellis_metric_type_t TYPE);
public:
int O () const { return d_O; }
GR_SWIG_BLOCK_MAGIC(trellis,@BASE_NAME@);
-@SPTR_NAME@ trellis_make_@BASE_NAME@ (const int O, const int D, const std::vector<@I_TYPE@> &TABLE, trellis_metric_type_t TYPE);
+@SPTR_NAME@ trellis_make_@BASE_NAME@ (int O, int D, const std::vector<@I_TYPE@> &TABLE, trellis_metric_type_t TYPE);
class @NAME@ : public gr_block
{
private:
- @NAME@ (const int O, const int D, const std::vector<@I_TYPE@> &TABLE, trellis_metric_type_t TYPE);
+ @NAME@ (int O, int D, const std::vector<@I_TYPE@> &TABLE, trellis_metric_type_t TYPE);
public:
int O () const { return d_O; }
trellis_metrics_c_sptr
-trellis_make_metrics_c (const int O, const int D, const std::vector<gr_complex> &TABLE, trellis_metric_type_t TYPE)
+trellis_make_metrics_c (int O, int D, const std::vector<gr_complex> &TABLE, trellis_metric_type_t TYPE)
{
return trellis_metrics_c_sptr (new trellis_metrics_c (O,D,TABLE,TYPE));
}
-trellis_metrics_c::trellis_metrics_c (const int O, const int D, const std::vector<gr_complex> &TABLE, trellis_metric_type_t TYPE)
+trellis_metrics_c::trellis_metrics_c (int O, int D, const std::vector<gr_complex> &TABLE, trellis_metric_type_t TYPE)
: gr_block ("metrics_c",
gr_make_io_signature (1, -1, sizeof (gr_complex)),
gr_make_io_signature (1, -1, sizeof (float))),
class trellis_metrics_c;
typedef boost::shared_ptr<trellis_metrics_c> trellis_metrics_c_sptr;
-trellis_metrics_c_sptr trellis_make_metrics_c (const int O, const int D, const std::vector<gr_complex> &TABLE, trellis_metric_type_t TYPE);
+trellis_metrics_c_sptr trellis_make_metrics_c (int O, int D, const std::vector<gr_complex> &TABLE, trellis_metric_type_t TYPE);
/*!
* \brief Evaluate metrics for use by the Viterbi algorithm.
trellis_metric_type_t d_TYPE;
std::vector<gr_complex> d_TABLE;
- friend trellis_metrics_c_sptr trellis_make_metrics_c (const int O, const int D, const std::vector<gr_complex> &TABLE, trellis_metric_type_t TYPE);
- trellis_metrics_c (const int O, const int D, const std::vector<gr_complex> &TABLE, trellis_metric_type_t TYPE);
+ friend trellis_metrics_c_sptr trellis_make_metrics_c (int O, int D, const std::vector<gr_complex> &TABLE, trellis_metric_type_t TYPE);
+ trellis_metrics_c (int O, int D, const std::vector<gr_complex> &TABLE, trellis_metric_type_t TYPE);
public:
int O () const { return d_O; }
GR_SWIG_BLOCK_MAGIC(trellis,metrics_c);
-trellis_metrics_c_sptr trellis_make_metrics_c (const int O, const int D, const std::vector<gr_complex> &TABLE, trellis_metric_type_t TYPE);
+trellis_metrics_c_sptr trellis_make_metrics_c (int O, int D, const std::vector<gr_complex> &TABLE, trellis_metric_type_t TYPE);
class trellis_metrics_c : public gr_block
{
private:
- trellis_metrics_c (const int O, const int D, const std::vector<gr_complex> &TABLE, trellis_metric_type_t TYPE);
+ trellis_metrics_c (int O, int D, const std::vector<gr_complex> &TABLE, trellis_metric_type_t TYPE);
public:
int O () const { return d_O; }
trellis_metrics_f_sptr
-trellis_make_metrics_f (const int O, const int D, const std::vector<float> &TABLE, trellis_metric_type_t TYPE)
+trellis_make_metrics_f (int O, int D, const std::vector<float> &TABLE, trellis_metric_type_t TYPE)
{
return trellis_metrics_f_sptr (new trellis_metrics_f (O,D,TABLE,TYPE));
}
-trellis_metrics_f::trellis_metrics_f (const int O, const int D, const std::vector<float> &TABLE, trellis_metric_type_t TYPE)
+trellis_metrics_f::trellis_metrics_f (int O, int D, const std::vector<float> &TABLE, trellis_metric_type_t TYPE)
: gr_block ("metrics_f",
gr_make_io_signature (1, -1, sizeof (float)),
gr_make_io_signature (1, -1, sizeof (float))),
class trellis_metrics_f;
typedef boost::shared_ptr<trellis_metrics_f> trellis_metrics_f_sptr;
-trellis_metrics_f_sptr trellis_make_metrics_f (const int O, const int D, const std::vector<float> &TABLE, trellis_metric_type_t TYPE);
+trellis_metrics_f_sptr trellis_make_metrics_f (int O, int D, const std::vector<float> &TABLE, trellis_metric_type_t TYPE);
/*!
* \brief Evaluate metrics for use by the Viterbi algorithm.
trellis_metric_type_t d_TYPE;
std::vector<float> d_TABLE;
- friend trellis_metrics_f_sptr trellis_make_metrics_f (const int O, const int D, const std::vector<float> &TABLE, trellis_metric_type_t TYPE);
- trellis_metrics_f (const int O, const int D, const std::vector<float> &TABLE, trellis_metric_type_t TYPE);
+ friend trellis_metrics_f_sptr trellis_make_metrics_f (int O, int D, const std::vector<float> &TABLE, trellis_metric_type_t TYPE);
+ trellis_metrics_f (int O, int D, const std::vector<float> &TABLE, trellis_metric_type_t TYPE);
public:
int O () const { return d_O; }
GR_SWIG_BLOCK_MAGIC(trellis,metrics_f);
-trellis_metrics_f_sptr trellis_make_metrics_f (const int O, const int D, const std::vector<float> &TABLE, trellis_metric_type_t TYPE);
+trellis_metrics_f_sptr trellis_make_metrics_f (int O, int D, const std::vector<float> &TABLE, trellis_metric_type_t TYPE);
class trellis_metrics_f : public gr_block
{
private:
- trellis_metrics_f (const int O, const int D, const std::vector<float> &TABLE, trellis_metric_type_t TYPE);
+ trellis_metrics_f (int O, int D, const std::vector<float> &TABLE, trellis_metric_type_t TYPE);
public:
int O () const { return d_O; }
trellis_metrics_i_sptr
-trellis_make_metrics_i (const int O, const int D, const std::vector<int> &TABLE, trellis_metric_type_t TYPE)
+trellis_make_metrics_i (int O, int D, const std::vector<int> &TABLE, trellis_metric_type_t TYPE)
{
return trellis_metrics_i_sptr (new trellis_metrics_i (O,D,TABLE,TYPE));
}
-trellis_metrics_i::trellis_metrics_i (const int O, const int D, const std::vector<int> &TABLE, trellis_metric_type_t TYPE)
+trellis_metrics_i::trellis_metrics_i (int O, int D, const std::vector<int> &TABLE, trellis_metric_type_t TYPE)
: gr_block ("metrics_i",
gr_make_io_signature (1, -1, sizeof (int)),
gr_make_io_signature (1, -1, sizeof (float))),
class trellis_metrics_i;
typedef boost::shared_ptr<trellis_metrics_i> trellis_metrics_i_sptr;
-trellis_metrics_i_sptr trellis_make_metrics_i (const int O, const int D, const std::vector<int> &TABLE, trellis_metric_type_t TYPE);
+trellis_metrics_i_sptr trellis_make_metrics_i (int O, int D, const std::vector<int> &TABLE, trellis_metric_type_t TYPE);
/*!
* \brief Evaluate metrics for use by the Viterbi algorithm.
trellis_metric_type_t d_TYPE;
std::vector<int> d_TABLE;
- friend trellis_metrics_i_sptr trellis_make_metrics_i (const int O, const int D, const std::vector<int> &TABLE, trellis_metric_type_t TYPE);
- trellis_metrics_i (const int O, const int D, const std::vector<int> &TABLE, trellis_metric_type_t TYPE);
+ friend trellis_metrics_i_sptr trellis_make_metrics_i (int O, int D, const std::vector<int> &TABLE, trellis_metric_type_t TYPE);
+ trellis_metrics_i (int O, int D, const std::vector<int> &TABLE, trellis_metric_type_t TYPE);
public:
int O () const { return d_O; }
GR_SWIG_BLOCK_MAGIC(trellis,metrics_i);
-trellis_metrics_i_sptr trellis_make_metrics_i (const int O, const int D, const std::vector<int> &TABLE, trellis_metric_type_t TYPE);
+trellis_metrics_i_sptr trellis_make_metrics_i (int O, int D, const std::vector<int> &TABLE, trellis_metric_type_t TYPE);
class trellis_metrics_i : public gr_block
{
private:
- trellis_metrics_i (const int O, const int D, const std::vector<int> &TABLE, trellis_metric_type_t TYPE);
+ trellis_metrics_i (int O, int D, const std::vector<int> &TABLE, trellis_metric_type_t TYPE);
public:
int O () const { return d_O; }
trellis_metrics_s_sptr
-trellis_make_metrics_s (const int O, const int D, const std::vector<short> &TABLE, trellis_metric_type_t TYPE)
+trellis_make_metrics_s (int O, int D, const std::vector<short> &TABLE, trellis_metric_type_t TYPE)
{
return trellis_metrics_s_sptr (new trellis_metrics_s (O,D,TABLE,TYPE));
}
-trellis_metrics_s::trellis_metrics_s (const int O, const int D, const std::vector<short> &TABLE, trellis_metric_type_t TYPE)
+trellis_metrics_s::trellis_metrics_s (int O, int D, const std::vector<short> &TABLE, trellis_metric_type_t TYPE)
: gr_block ("metrics_s",
gr_make_io_signature (1, -1, sizeof (short)),
gr_make_io_signature (1, -1, sizeof (float))),
class trellis_metrics_s;
typedef boost::shared_ptr<trellis_metrics_s> trellis_metrics_s_sptr;
-trellis_metrics_s_sptr trellis_make_metrics_s (const int O, const int D, const std::vector<short> &TABLE, trellis_metric_type_t TYPE);
+trellis_metrics_s_sptr trellis_make_metrics_s (int O, int D, const std::vector<short> &TABLE, trellis_metric_type_t TYPE);
/*!
* \brief Evaluate metrics for use by the Viterbi algorithm.
trellis_metric_type_t d_TYPE;
std::vector<short> d_TABLE;
- friend trellis_metrics_s_sptr trellis_make_metrics_s (const int O, const int D, const std::vector<short> &TABLE, trellis_metric_type_t TYPE);
- trellis_metrics_s (const int O, const int D, const std::vector<short> &TABLE, trellis_metric_type_t TYPE);
+ friend trellis_metrics_s_sptr trellis_make_metrics_s (int O, int D, const std::vector<short> &TABLE, trellis_metric_type_t TYPE);
+ trellis_metrics_s (int O, int D, const std::vector<short> &TABLE, trellis_metric_type_t TYPE);
public:
int O () const { return d_O; }
GR_SWIG_BLOCK_MAGIC(trellis,metrics_s);
-trellis_metrics_s_sptr trellis_make_metrics_s (const int O, const int D, const std::vector<short> &TABLE, trellis_metric_type_t TYPE);
+trellis_metrics_s_sptr trellis_make_metrics_s (int O, int D, const std::vector<short> &TABLE, trellis_metric_type_t TYPE);
class trellis_metrics_s : public gr_block
{
private:
- trellis_metrics_s (const int O, const int D, const std::vector<short> &TABLE, trellis_metric_type_t TYPE);
+ trellis_metrics_s (int O, int D, const std::vector<short> &TABLE, trellis_metric_type_t TYPE);
public:
int O () const { return d_O; }
#include <iostream>
trellis_permutation_sptr
-trellis_make_permutation (const int K, const std::vector<int> &TABLE, const size_t NBYTES)
+trellis_make_permutation (int K, const std::vector<int> &TABLE, int SYMS_PER_BLOCK, size_t NBYTES_INOUT)
{
- return trellis_permutation_sptr (new trellis_permutation (K,TABLE,NBYTES));
+ return trellis_permutation_sptr (new trellis_permutation (K,TABLE,SYMS_PER_BLOCK,NBYTES_INOUT));
}
-trellis_permutation::trellis_permutation (const int K, const std::vector<int> &TABLE, const size_t NBYTES)
+trellis_permutation::trellis_permutation (int K, const std::vector<int> &TABLE, int SYMS_PER_BLOCK, size_t NBYTES_INOUT)
: gr_sync_block ("permutation",
- gr_make_io_signature (1, -1, NBYTES),
- gr_make_io_signature (1, -1, NBYTES)),
+ gr_make_io_signature (1, -1, NBYTES_INOUT),
+ gr_make_io_signature (1, -1, NBYTES_INOUT)),
d_K (K),
d_TABLE (TABLE),
- d_NBYTES (NBYTES)
+ d_SYMS_PER_BLOCK (SYMS_PER_BLOCK),
+ d_NBYTES_INOUT (NBYTES_INOUT)
{
- set_output_multiple (d_K);
+ set_output_multiple (d_K*SYMS_PER_BLOCK);
//std::cout << d_K << "\n";
}
int nstreams = input_items.size();
assert (input_items.size() == output_items.size());
assert (noutput_items % d_K ==0);
- //std::cout << noutput_items << "\n";
for (int m=0;m<nstreams;m++) {
const char *in = (const char *) input_items[m];
char *out = (char *) output_items[m];
// per stream processing
- for (unsigned int i = 0; i < noutput_items; i++){
- //std::cout << i << " " << i*d_NBYTES << " " << (d_K*(i/d_K)+d_TABLE[i%d_K])*d_NBYTES << "\n";
- memcpy(&(out[i*d_NBYTES]), &(in[(d_K*(i/d_K)+d_TABLE[i%d_K])*d_NBYTES]), d_NBYTES);
+ for (int i = 0; i < noutput_items/d_SYMS_PER_BLOCK; i++){
+ // Index i refers to blocks.
+ // Begining of packet (in blocks)
+ int i0 = d_K*(i/d_K);
+ // position of block within packet (in blocks)
+ int j0 = i%d_K;
+ // new position of block within packet (in blocks)
+ int k0 = d_TABLE[j0];
+ memcpy(&(out[i*d_SYMS_PER_BLOCK*d_NBYTES_INOUT]),
+ &(in[(i0+k0)*d_SYMS_PER_BLOCK*d_NBYTES_INOUT]),
+ d_NBYTES_INOUT*d_SYMS_PER_BLOCK);
}
// end per stream processing
}
class trellis_permutation;
typedef boost::shared_ptr<trellis_permutation> trellis_permutation_sptr;
-trellis_permutation_sptr trellis_make_permutation (const int K, const std::vector<int> &TABLE, const size_t NBYTES);
+trellis_permutation_sptr trellis_make_permutation (int K, const std::vector<int> &TABLE, int SYMS_PER_BLOCK, size_t NBYTES_INOUT);
/*!
* \brief Permutation.
class trellis_permutation : public gr_sync_block
{
private:
- friend trellis_permutation_sptr trellis_make_permutation (const int K, const std::vector<int> &TABLE, const size_t NBYTES);
+ friend trellis_permutation_sptr trellis_make_permutation (int K, const std::vector<int> &TABLE, int SYMS_PER_BLOCK, size_t NBYTES_INOUT);
int d_K;
std::vector<int> d_TABLE;
- size_t d_NBYTES;
- trellis_permutation (const int K, const std::vector<int> &TABLE, const size_t NBYTES);
+ int d_SYMS_PER_BLOCK;
+ size_t d_NBYTES_INOUT;
+ trellis_permutation (int K, const std::vector<int> &TABLE, int SYMS_PER_BLOCK, size_t NBYTES);
public:
int K () const { return d_K; }
const std::vector<int> & TABLE () const { return d_TABLE; }
- size_t NBYTES () const { return d_NBYTES; }
+ int SYMS_PER_BLOCK () const { return d_SYMS_PER_BLOCK; }
+ size_t NBYTES_INOUT () const { return d_NBYTES_INOUT; }
int work (int noutput_items,
gr_vector_const_void_star &input_items,
GR_SWIG_BLOCK_MAGIC(trellis,permutation);
-trellis_permutation_sptr trellis_make_permutation (const int K, const std::vector<int> &TABLE, const size_t NBYTES);
+trellis_permutation_sptr trellis_make_permutation (int K, const std::vector<int> &TABLE, int SYMS_PER_BLOCK, size_t NBYTES_INOUT);
class trellis_permutation : public gr_sync_block
{
private:
int d_K;
std::vector<int> d_TABLE;
- size_t d_NBYTES;
- trellis_permutation (const int K, const std::vector<int> &TABLE, const size_t NBYTES);
+ int d_SYMS_PER_BLOCK;
+ size_t d_NBYTES_INOUT;
+ trellis_permutation (int K, const std::vector<int> &TABLE, int SYMS_PER_BLOCK, size_t NBYTES_INOUT);
public:
int K () const { return d_K; }
const std::vector<int> & TABLE () const { return d_TABLE; }
- size_t NBYTES () const { return d_NBYTES; }
+ int SYMS_PER_BLOCK () const { return d_SYMS_PER_BLOCK; }
+ size_t NBYTES_INOUT () const { return d_NBYTES_INOUT; }
};
--- /dev/null
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <trellis_siso_f.h>
+#include <gr_io_signature.h>
+#include <stdexcept>
+#include <assert.h>
+#include <iostream>
+
+static const float INF = 1.0e9;
+
+trellis_siso_f_sptr
+trellis_make_siso_f (
+ const fsm &FSM,
+ int K,
+ int S0,
+ int SK,
+ bool POSTI,
+ bool POSTO,
+ trellis_siso_type_t SISO_TYPE)
+{
+ return trellis_siso_f_sptr (new trellis_siso_f (FSM,K,S0,SK,POSTI,POSTO,SISO_TYPE));
+}
+
+trellis_siso_f::trellis_siso_f (
+ const fsm &FSM,
+ int K,
+ int S0,
+ int SK,
+ bool POSTI,
+ bool POSTO,
+ trellis_siso_type_t SISO_TYPE)
+ : gr_block ("siso_f",
+ gr_make_io_signature (1, -1, sizeof (float)),
+ gr_make_io_signature (1, -1, sizeof (float))),
+ d_FSM (FSM),
+ d_K (K),
+ d_S0 (S0),
+ d_SK (SK),
+ d_POSTI (POSTI),
+ d_POSTO (POSTO),
+ d_SISO_TYPE (SISO_TYPE),
+ d_alpha(FSM.S()*(K+1)),
+ d_beta(FSM.S()*(K+1))
+{
+ int multiple;
+ if (d_POSTI && d_POSTO)
+ multiple = d_FSM.I()+d_FSM.O();
+ else if(d_POSTI)
+ multiple = d_FSM.I();
+ else if(d_POSTO)
+ multiple = d_FSM.O();
+ else
+ throw std::runtime_error ("Not both POSTI and POSTO can be false.");
+ //printf("constructor: Multiple = %d\n",multiple);
+ set_output_multiple (d_K*multiple);
+ //what is the meaning of relative rate for this?
+ // it was suggested to use the one furthest from 1.0
+ // let's do it.
+ set_relative_rate ( multiple / ((double) d_FSM.I()) );
+}
+
+
+void
+trellis_siso_f::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+{
+ int multiple;
+ if (d_POSTI && d_POSTO)
+ multiple = d_FSM.I()+d_FSM.O();
+ else if(d_POSTI)
+ multiple = d_FSM.I();
+ else if(d_POSTO)
+ multiple = d_FSM.O();
+ else
+ throw std::runtime_error ("Not both POSTI and POSTO can be false.");
+ //printf("forecast: Multiple = %d\n",multiple);
+ assert (noutput_items % (d_K*multiple) == 0);
+ int input_required1 = d_FSM.I() * (noutput_items/multiple) ;
+ int input_required2 = d_FSM.O() * (noutput_items/multiple) ;
+ //printf("forecast: Output requirements: %d\n",noutput_items);
+ //printf("forecast: Input requirements: %d %d\n",input_required1,input_required2);
+ unsigned ninputs = ninput_items_required.size();
+ assert(ninputs % 2 == 0);
+ for (unsigned int i = 0; i < ninputs/2; i++) {
+ ninput_items_required[2*i] = input_required1;
+ ninput_items_required[2*i+1] = input_required2;
+ }
+}
+
+inline float min(float a, float b)
+{
+ return a <= b ? a : b;
+}
+
+inline float min_star(float a, float b)
+{
+ return (a <= b ? a : b)-log(1+exp(a <= b ? a-b : b-a));
+}
+
+void siso_algorithm(int I, int S, int O,
+ const std::vector<int> &NS,
+ const std::vector<int> &OS,
+ const std::vector<int> &PS,
+ const std::vector<int> &PI,
+ int K,
+ int S0,int SK,
+ bool POSTI, bool POSTO,
+ float (*p2mymin)(float,float),
+ const float *priori, const float *prioro, float *post,
+ std::vector<float> &alpha,
+ std::vector<float> &beta)
+{
+ float norm,mm,minm;
+
+
+ if(S0<0) { // initial state not specified
+ for(int i=0;i<S;i++) alpha[0*S+i]=0;
+ }
+ else {
+ for(int i=0;i<S;i++) alpha[0*S+i]=INF;
+ alpha[0*S+S0]=0.0;
+ }
+
+ for(int k=0;k<K;k++) { // forward recursion
+ norm=INF;
+ for(int j=0;j<S;j++) {
+ minm=INF;
+ for(int i=0;i<I;i++) {
+ int i0 = j*I+i;
+ mm=alpha[k*S+PS[i0]]+priori[k*I+PI[i0]]+prioro[k*O+OS[PS[i0]*I+PI[i0]]];
+ minm=(*p2mymin)(minm,mm);
+ }
+ alpha[(k+1)*S+j]=minm;
+ if(minm<norm) norm=minm;
+ }
+ for(int j=0;j<S;j++)
+ alpha[(k+1)*S+j]-=norm; // normalize total metrics so they do not explode
+ }
+
+ if(SK<0) { // final state not specified
+ for(int i=0;i<S;i++) beta[K*S+i]=0;
+ }
+ else {
+ for(int i=0;i<S;i++) beta[K*S+i]=INF;
+ beta[K*S+SK]=0.0;
+ }
+
+ for(int k=K-1;k>=0;k--) { // backward recursion
+ norm=INF;
+ for(int j=0;j<S;j++) {
+ minm=INF;
+ for(int i=0;i<I;i++) {
+ int i0 = j*I+i;
+ mm=beta[(k+1)*S+NS[i0]]+priori[k*I+i]+prioro[k*O+OS[i0]];
+ minm=(*p2mymin)(minm,mm);
+ }
+ beta[k*S+j]=minm;
+ if(minm<norm) norm=minm;
+ }
+ for(int j=0;j<S;j++)
+ beta[k*S+j]-=norm; // normalize total metrics so they do not explode
+ }
+
+
+if (POSTI && POSTO)
+{
+ for(int k=0;k<K;k++) { // input combining
+ norm=INF;
+ for(int i=0;i<I;i++) {
+ minm=INF;
+ for(int j=0;j<S;j++) {
+ mm=alpha[k*S+j]+prioro[k*O+OS[j*I+i]]+beta[(k+1)*S+NS[j*I+i]];
+ minm=(*p2mymin)(minm,mm);
+ }
+ post[k*(I+O)+i]=minm;
+ if(minm<norm) norm=minm;
+ }
+ for(int i=0;i<I;i++)
+ post[k*(I+O)+i]-=norm; // normalize metrics
+ }
+
+
+ for(int k=0;k<K;k++) { // output combining
+ norm=INF;
+ for(int n=0;n<O;n++) {
+ minm=INF;
+ for(int j=0;j<S;j++) {
+ for(int i=0;i<I;i++) {
+ mm= (n==OS[j*I+i] ? alpha[k*S+j]+priori[k*I+i]+beta[(k+1)*S+NS[j*I+i]] : INF);
+ minm=(*p2mymin)(minm,mm);
+ }
+ }
+ post[k*(I+O)+I+n]=minm;
+ if(minm<norm) norm=minm;
+ }
+ for(int n=0;n<O;n++)
+ post[k*(I+O)+I+n]-=norm; // normalize metrics
+ }
+}
+else if(POSTI)
+{
+ for(int k=0;k<K;k++) { // input combining
+ norm=INF;
+ for(int i=0;i<I;i++) {
+ minm=INF;
+ for(int j=0;j<S;j++) {
+ mm=alpha[k*S+j]+prioro[k*O+OS[j*I+i]]+beta[(k+1)*S+NS[j*I+i]];
+ minm=(*p2mymin)(minm,mm);
+ }
+ post[k*I+i]=minm;
+ if(minm<norm) norm=minm;
+ }
+ for(int i=0;i<I;i++)
+ post[k*I+i]-=norm; // normalize metrics
+ }
+}
+else if(POSTO)
+{
+ for(int k=0;k<K;k++) { // output combining
+ norm=INF;
+ for(int n=0;n<O;n++) {
+ minm=INF;
+ for(int j=0;j<S;j++) {
+ for(int i=0;i<I;i++) {
+ mm= (n==OS[j*I+i] ? alpha[k*S+j]+priori[k*I+i]+beta[(k+1)*S+NS[j*I+i]] : INF);
+ minm=(*p2mymin)(minm,mm);
+ }
+ }
+ post[k*O+n]=minm;
+ if(minm<norm) norm=minm;
+ }
+ for(int n=0;n<O;n++)
+ post[k*O+n]-=norm; // normalize metrics
+ }
+}
+else
+ throw std::runtime_error ("Not both POSTI and POSTO can be false.");
+
+}
+
+
+
+
+
+
+int
+trellis_siso_f::general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ assert (input_items.size() == 2*output_items.size());
+ int nstreams = output_items.size();
+ //printf("general_work:Streams: %d\n",nstreams);
+ int multiple;
+ if (d_POSTI && d_POSTO)
+ multiple = d_FSM.I()+d_FSM.O();
+ else if(d_POSTI)
+ multiple = d_FSM.I();
+ else if(d_POSTO)
+ multiple = d_FSM.O();
+ else
+ throw std::runtime_error ("Not both POSTI and POSTO can be false.");
+
+ assert (noutput_items % (d_K*multiple) == 0);
+ int nblocks = noutput_items / (d_K*multiple);
+ //printf("general_work:Blocks: %d\n",nblocks);
+ //for(int i=0;i<ninput_items.size();i++)
+ //printf("general_work:Input items available: %d\n",ninput_items[i]);
+
+ float (*p2min)(float, float) = NULL;
+ if(d_SISO_TYPE == TRELLIS_MIN_SUM)
+ p2min = &min;
+ else if(d_SISO_TYPE == TRELLIS_SUM_PRODUCT)
+ p2min = &min_star;
+
+
+ for (int m=0;m<nstreams;m++) {
+ const float *in1 = (const float *) input_items[2*m];
+ const float *in2 = (const float *) input_items[2*m+1];
+ float *out = (float *) output_items[m];
+ for (int n=0;n<nblocks;n++) {
+ siso_algorithm(d_FSM.I(),d_FSM.S(),d_FSM.O(),
+ d_FSM.NS(),d_FSM.OS(),d_FSM.PS(),d_FSM.PI(),
+ d_K,d_S0,d_SK,
+ d_POSTI,d_POSTO,
+ p2min,
+ &(in1[n*d_K*d_FSM.I()]),&(in2[n*d_K*d_FSM.O()]),
+ &(out[n*d_K*multiple]),
+ d_alpha,d_beta);
+ }
+ }
+
+ for (unsigned int i = 0; i < input_items.size()/2; i++) {
+ consume(2*i,d_FSM.I() * noutput_items / multiple );
+ consume(2*i+1,d_FSM.O() * noutput_items / multiple );
+ }
+
+ return noutput_items;
+}
--- /dev/null
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifndef INCLUDED_TRELLIS_SISO_F_H
+#define INCLUDED_TRELLIS_SISO_F_H
+
+#include "fsm.h"
+#include "trellis_siso_type.h"
+#include <gr_block.h>
+
+class trellis_siso_f;
+typedef boost::shared_ptr<trellis_siso_f> trellis_siso_f_sptr;
+
+trellis_siso_f_sptr trellis_make_siso_f (
+ const fsm &FSM,
+ int K,
+ int S0,
+ int SK,
+ bool POSTI,
+ bool POSTO,
+ trellis_siso_type_t d_SISO_TYPE);
+
+
+
+class trellis_siso_f : public gr_block
+{
+ fsm d_FSM;
+ int d_K;
+ int d_S0;
+ int d_SK;
+ bool d_POSTI;
+ bool d_POSTO;
+ trellis_siso_type_t d_SISO_TYPE;
+ std::vector<float> d_alpha;
+ std::vector<float> d_beta;
+
+ friend trellis_siso_f_sptr trellis_make_siso_f (
+ const fsm &FSM,
+ int K,
+ int S0,
+ int SK,
+ bool POSTI,
+ bool POSTO,
+ trellis_siso_type_t d_SISO_TYPE);
+
+
+ trellis_siso_f (
+ const fsm &FSM,
+ int K,
+ int S0,
+ int SK,
+ bool POSTI,
+ bool POSTO,
+ trellis_siso_type_t d_SISO_TYPE);
+
+
+public:
+ fsm FSM () const { return d_FSM; }
+ int K () const { return d_K; }
+ int S0 () const { return d_S0; }
+ int SK () const { return d_SK; }
+ bool POSTI () const { return d_POSTI; }
+ bool POSTO () const { return d_POSTO; }
+ trellis_siso_type_t SISO_TYPE () const { return d_SISO_TYPE; }
+ void forecast (int noutput_items,
+ gr_vector_int &ninput_items_required);
+ int general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif
--- /dev/null
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(trellis,siso_f);
+
+trellis_siso_f_sptr trellis_make_siso_f (
+ const fsm &FSM,
+ int K,
+ int S0,
+ int SK,
+ bool POSTI,
+ bool POSTO,
+ trellis_siso_type_t SISO_TYPE);
+
+
+class trellis_siso_f : public gr_block
+{
+private:
+ trellis_siso_f (
+ const fsm &FSM,
+ int K,
+ int S0,
+ int SK,
+ bool POSTI,
+ bool POSTO,
+ trellis_siso_type_t SISO_TYPE);
+
+public:
+ fsm FSM () const { return d_FSM; }
+ int K () const { return d_K; }
+ int S0 () const { return d_S0; }
+ int SK () const { return d_SK; }
+ bool POSTI () const { return d_POSTI; }
+ bool POSTO () const { return d_POSTO; }
+ trellis_siso_type_t SISO_TYPE () const { return d_SISO_TYPE; }
+};
--- /dev/null
+# trellis_siso_f.lo - a libtool object file
+# Generated by ltmain.sh - GNU libtool 1.5.6 (1.1220.2.95 2004/04/11 05:50:42)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object='.libs/trellis_siso_f.o'
+
+# Name of the non-PIC object.
+non_pic_object=none
+
--- /dev/null
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+#ifndef INCLUDED_TRELLIS_SISO_TYPE_H
+#define INCLUDED_TRELLIS_SISO_TYPE_H
+
+typedef enum {
+ TRELLIS_MIN_SUM = 200, TRELLIS_SUM_PRODUCT
+} trellis_siso_type_t;
+
+#endif
+
@SPTR_NAME@
trellis_make_@BASE_NAME@ (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK)
+ int K,
+ int S0,
+ int SK)
{
return @SPTR_NAME@ (new @NAME@ (FSM,K,S0,SK));
}
@NAME@::@NAME@ (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK)
+ int K,
+ int S0,
+ int SK)
: gr_block ("@BASE_NAME@",
gr_make_io_signature (1, -1, sizeof (float)),
gr_make_io_signature (1, -1, sizeof (@TYPE@))),
-void viterbi_algorithm(const int I, const int S, const int O,
+void viterbi_algorithm(int I, int S, int O,
const std::vector<int> &NS,
const std::vector<int> &OS,
const std::vector<int> &PS,
const std::vector<int> &PI,
- const int K,
- const int S0,const int SK,
+ int K,
+ int S0,int SK,
const float *in, @TYPE@ *out,
std::vector<int> &trace)
{
@SPTR_NAME@ trellis_make_@BASE_NAME@ (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
friend @SPTR_NAME@ trellis_make_@BASE_NAME@ (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
@NAME@ (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
public:
@SPTR_NAME@ trellis_make_@BASE_NAME@ (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
class @NAME@ : public gr_block
private:
@NAME@ (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
public:
fsm FSM () const { return d_FSM; }
trellis_viterbi_b_sptr
trellis_make_viterbi_b (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK)
+ int K,
+ int S0,
+ int SK)
{
return trellis_viterbi_b_sptr (new trellis_viterbi_b (FSM,K,S0,SK));
}
trellis_viterbi_b::trellis_viterbi_b (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK)
+ int K,
+ int S0,
+ int SK)
: gr_block ("viterbi_b",
gr_make_io_signature (1, -1, sizeof (float)),
gr_make_io_signature (1, -1, sizeof (unsigned char))),
-void viterbi_algorithm(const int I, const int S, const int O,
+void viterbi_algorithm(int I, int S, int O,
const std::vector<int> &NS,
const std::vector<int> &OS,
const std::vector<int> &PS,
const std::vector<int> &PI,
- const int K,
- const int S0,const int SK,
+ int K,
+ int S0,int SK,
const float *in, unsigned char *out,
std::vector<int> &trace)
{
trellis_viterbi_b_sptr trellis_make_viterbi_b (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
friend trellis_viterbi_b_sptr trellis_make_viterbi_b (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
trellis_viterbi_b (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
public:
trellis_viterbi_b_sptr trellis_make_viterbi_b (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
class trellis_viterbi_b : public gr_block
private:
trellis_viterbi_b (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
public:
fsm FSM () const { return d_FSM; }
@SPTR_NAME@
trellis_make_@BASE_NAME@ (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE)
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE)
{
return @SPTR_NAME@ (new @NAME@ (FSM,D,TABLE,K,S0,SK,TYPE));
}
@NAME@::@NAME@ (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE)
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE)
: gr_block ("@BASE_NAME@",
gr_make_io_signature (1, -1, sizeof (float)),
gr_make_io_signature (1, -1, sizeof (@TYPE@))),
-void viterbi_algorithm_combined(const int I, const int S, const int O,
+void viterbi_algorithm_combined(int I, int S, int O,
const std::vector<int> &NS,
const std::vector<int> &OS,
const std::vector<int> &PS,
const std::vector<int> &PI,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,const int SK,
- const trellis_metric_type_t TYPE,
+ int K,
+ int S0,int SK,
+ trellis_metric_type_t TYPE,
const float *in, @TYPE@ *out,
std::vector<int> &trace)
{
@SPTR_NAME@ trellis_make_@BASE_NAME@ (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
class @NAME@ : public gr_block
friend @SPTR_NAME@ trellis_make_@BASE_NAME@ (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
@NAME@ (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
public:
@SPTR_NAME@ trellis_make_@BASE_NAME@ (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
class @NAME@ : public gr_block
private:
@NAME@ (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
public:
fsm FSM () const { return d_FSM; }
trellis_viterbi_combined_b_sptr
trellis_make_viterbi_combined_b (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE)
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE)
{
return trellis_viterbi_combined_b_sptr (new trellis_viterbi_combined_b (FSM,D,TABLE,K,S0,SK,TYPE));
}
trellis_viterbi_combined_b::trellis_viterbi_combined_b (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE)
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE)
: gr_block ("viterbi_combined_b",
gr_make_io_signature (1, -1, sizeof (float)),
gr_make_io_signature (1, -1, sizeof (unsigned char))),
-void viterbi_algorithm_combined(const int I, const int S, const int O,
+void viterbi_algorithm_combined(int I, int S, int O,
const std::vector<int> &NS,
const std::vector<int> &OS,
const std::vector<int> &PS,
const std::vector<int> &PI,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,const int SK,
- const trellis_metric_type_t TYPE,
+ int K,
+ int S0,int SK,
+ trellis_metric_type_t TYPE,
const float *in, unsigned char *out,
std::vector<int> &trace)
{
trellis_viterbi_combined_b_sptr trellis_make_viterbi_combined_b (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
class trellis_viterbi_combined_b : public gr_block
friend trellis_viterbi_combined_b_sptr trellis_make_viterbi_combined_b (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
trellis_viterbi_combined_b (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
public:
trellis_viterbi_combined_b_sptr trellis_make_viterbi_combined_b (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
class trellis_viterbi_combined_b : public gr_block
private:
trellis_viterbi_combined_b (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
public:
fsm FSM () const { return d_FSM; }
trellis_viterbi_combined_i_sptr
trellis_make_viterbi_combined_i (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE)
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE)
{
return trellis_viterbi_combined_i_sptr (new trellis_viterbi_combined_i (FSM,D,TABLE,K,S0,SK,TYPE));
}
trellis_viterbi_combined_i::trellis_viterbi_combined_i (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE)
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE)
: gr_block ("viterbi_combined_i",
gr_make_io_signature (1, -1, sizeof (float)),
gr_make_io_signature (1, -1, sizeof (int))),
-void viterbi_algorithm_combined(const int I, const int S, const int O,
+void viterbi_algorithm_combined(int I, int S, int O,
const std::vector<int> &NS,
const std::vector<int> &OS,
const std::vector<int> &PS,
const std::vector<int> &PI,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,const int SK,
- const trellis_metric_type_t TYPE,
+ int K,
+ int S0,int SK,
+ trellis_metric_type_t TYPE,
const float *in, int *out,
std::vector<int> &trace)
{
trellis_viterbi_combined_i_sptr trellis_make_viterbi_combined_i (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
class trellis_viterbi_combined_i : public gr_block
friend trellis_viterbi_combined_i_sptr trellis_make_viterbi_combined_i (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
trellis_viterbi_combined_i (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
public:
trellis_viterbi_combined_i_sptr trellis_make_viterbi_combined_i (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
class trellis_viterbi_combined_i : public gr_block
private:
trellis_viterbi_combined_i (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
public:
fsm FSM () const { return d_FSM; }
trellis_viterbi_combined_s_sptr
trellis_make_viterbi_combined_s (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE)
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE)
{
return trellis_viterbi_combined_s_sptr (new trellis_viterbi_combined_s (FSM,D,TABLE,K,S0,SK,TYPE));
}
trellis_viterbi_combined_s::trellis_viterbi_combined_s (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE)
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE)
: gr_block ("viterbi_combined_s",
gr_make_io_signature (1, -1, sizeof (float)),
gr_make_io_signature (1, -1, sizeof (short))),
-void viterbi_algorithm_combined(const int I, const int S, const int O,
+void viterbi_algorithm_combined(int I, int S, int O,
const std::vector<int> &NS,
const std::vector<int> &OS,
const std::vector<int> &PS,
const std::vector<int> &PI,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,const int SK,
- const trellis_metric_type_t TYPE,
+ int K,
+ int S0,int SK,
+ trellis_metric_type_t TYPE,
const float *in, short *out,
std::vector<int> &trace)
{
trellis_viterbi_combined_s_sptr trellis_make_viterbi_combined_s (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
class trellis_viterbi_combined_s : public gr_block
friend trellis_viterbi_combined_s_sptr trellis_make_viterbi_combined_s (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
trellis_viterbi_combined_s (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
public:
trellis_viterbi_combined_s_sptr trellis_make_viterbi_combined_s (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
class trellis_viterbi_combined_s : public gr_block
private:
trellis_viterbi_combined_s (
const fsm &FSM,
- const int D,
+ int D,
const std::vector<float> &TABLE,
- const int K,
- const int S0,
- const int SK,
- const trellis_metric_type_t TYPE);
+ int K,
+ int S0,
+ int SK,
+ trellis_metric_type_t TYPE);
public:
fsm FSM () const { return d_FSM; }
trellis_viterbi_i_sptr
trellis_make_viterbi_i (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK)
+ int K,
+ int S0,
+ int SK)
{
return trellis_viterbi_i_sptr (new trellis_viterbi_i (FSM,K,S0,SK));
}
trellis_viterbi_i::trellis_viterbi_i (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK)
+ int K,
+ int S0,
+ int SK)
: gr_block ("viterbi_i",
gr_make_io_signature (1, -1, sizeof (float)),
gr_make_io_signature (1, -1, sizeof (int))),
-void viterbi_algorithm(const int I, const int S, const int O,
+void viterbi_algorithm(int I, int S, int O,
const std::vector<int> &NS,
const std::vector<int> &OS,
const std::vector<int> &PS,
const std::vector<int> &PI,
- const int K,
- const int S0,const int SK,
+ int K,
+ int S0,int SK,
const float *in, int *out,
std::vector<int> &trace)
{
trellis_viterbi_i_sptr trellis_make_viterbi_i (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
friend trellis_viterbi_i_sptr trellis_make_viterbi_i (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
trellis_viterbi_i (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
public:
trellis_viterbi_i_sptr trellis_make_viterbi_i (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
class trellis_viterbi_i : public gr_block
private:
trellis_viterbi_i (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
public:
fsm FSM () const { return d_FSM; }
trellis_viterbi_s_sptr
trellis_make_viterbi_s (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK)
+ int K,
+ int S0,
+ int SK)
{
return trellis_viterbi_s_sptr (new trellis_viterbi_s (FSM,K,S0,SK));
}
trellis_viterbi_s::trellis_viterbi_s (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK)
+ int K,
+ int S0,
+ int SK)
: gr_block ("viterbi_s",
gr_make_io_signature (1, -1, sizeof (float)),
gr_make_io_signature (1, -1, sizeof (short))),
-void viterbi_algorithm(const int I, const int S, const int O,
+void viterbi_algorithm(int I, int S, int O,
const std::vector<int> &NS,
const std::vector<int> &OS,
const std::vector<int> &PS,
const std::vector<int> &PI,
- const int K,
- const int S0,const int SK,
+ int K,
+ int S0,int SK,
const float *in, short *out,
std::vector<int> &trace)
{
trellis_viterbi_s_sptr trellis_make_viterbi_s (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
friend trellis_viterbi_s_sptr trellis_make_viterbi_s (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
trellis_viterbi_s (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
public:
trellis_viterbi_s_sptr trellis_make_viterbi_s (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
class trellis_viterbi_s : public gr_block
private:
trellis_viterbi_s (
const fsm &FSM,
- const int K,
- const int S0,
- const int SK);
+ int K,
+ int S0,
+ int SK);
public:
fsm FSM () const { return d_FSM; }