diff options
Diffstat (limited to 'gr-trellis')
66 files changed, 3843 insertions, 370 deletions
diff --git a/gr-trellis/doc/Makefile.am b/gr-trellis/doc/Makefile.am index 559d271dc..9e6b81ac0 100644 --- a/gr-trellis/doc/Makefile.am +++ b/gr-trellis/doc/Makefile.am @@ -30,7 +30,7 @@ endif all: $(HTML_FILES) -EXTRA_DIST = \ +EXTRA_DIST += \ gr-trellis.xml \ make_numbered_listing.py \ test_tcm.py \ diff --git a/gr-trellis/doc/gr-trellis.xml b/gr-trellis/doc/gr-trellis.xml index ed53715a8..5f1921343 100644 --- a/gr-trellis/doc/gr-trellis.xml +++ b/gr-trellis/doc/gr-trellis.xml @@ -279,6 +279,15 @@ The fourth way is specific to FSMs resulting from shift registers, and the outpu </programlisting> </listitem> +<listitem> +<para> +I have added other constructors as well, eg, one that constructs an FSM appropriate for modeling an arbitrary CPM scheme; one that constructs the radix-n version of a given FSM; one that constructs the "concatenation" of two FSMs, etc. +</para> +</listitem> + + + + </itemizedlist> @@ -397,8 +406,8 @@ r<subscript>k</subscript>= evaluates </para> <para> -i<subscript>0</subscript>= argmax<subscript>i</subscript> ||r<subscript>k</subscript>-c<subscript>i</subscript>||<superscript>2</superscript> = -argmax<subscript>i</subscript> sum<subscript>j=1</subscript><superscript>D</superscript> |r<subscript>k,j</subscript>-c<subscript>i,j</subscript>|<superscript>2</superscript> +i<subscript>0</subscript>= argmin<subscript>i</subscript> ||r<subscript>k</subscript>-c<subscript>i</subscript>||<superscript>2</superscript> = +argmin<subscript>i</subscript> sum<subscript>j=1</subscript><superscript>D</superscript> |r<subscript>k,j</subscript>-c<subscript>i,j</subscript>|<superscript>2</superscript> </para> <para> and outputs a sequence of O floats of the form (0,...,0,1,0,...,0), where the @@ -413,8 +422,8 @@ r<subscript>k</subscript>= evaluates </para> <para> -i<subscript>0</subscript>= argmax<subscript>i</subscript> ||r<subscript>k</subscript>-c<subscript>i</subscript>||<superscript>2</superscript> = -argmax<subscript>i</subscript> sum<subscript>j=1</subscript><superscript>D</superscript> (r<subscript>k,j</subscript>-c<subscript>i,j</subscript>)<superscript>2</superscript> +i<subscript>0</subscript>= argmin<subscript>i</subscript> ||r<subscript>k</subscript>-c<subscript>i</subscript>||<superscript>2</superscript> = +argmin<subscript>i</subscript> sum<subscript>j=1</subscript><superscript>D</superscript> (r<subscript>k,j</subscript>-c<subscript>i,j</subscript>)<superscript>2</superscript> </para> <para> and outputs a sequence of O floats of the form (d<subscript>1</subscript>,d<subscript>2</subscript>,...,d<subscript>O</subscript>), where the @@ -813,7 +822,7 @@ The modulated symbols are filtered by the ISI channel and AWGN with appropriate <para> Since the output alphabet of the equivalent FSM is quite large (1024) we chose to utilize the combined metrics calculator and Viterbi algorithm block. -also note that the first L observations are irrelevant and tus can be skipped. +Also note that the first L observations are irrelevant and thus can be skipped. </para> <programlisting> 33 # RX @@ -863,7 +872,20 @@ The function returns the number of symbols and the number of symbols in error. O <sect1 id="turbo"><title>Support for Concatenated Coding and Turbo Decoding</title> <para> -To do... +Soft versions of the algorithms have been implemented. +Also examples of turbo equalization/decoding and of sccc can +be found in the examples directory. + +Recently we added gnuradio blocks for sccc and pccc encoders and +turbo decoders. +Although these can be generated by existing gr-trellis blocks (in particular, +the SISO blocks, as done in some of the python examples) there is an advantage +in having this functionality as a single block. To see why, think of a turbo decoder with 10 iterations. Previously we needed to concatenate 10 x 2 SISO blocks +(for a sccc decoder) to emulate the passing of soft information between SISOs over 10 iterartions. With the new block however, only a single such block is needed that internally loops through 10 iterations; this results in space savings +and possibly time saving as well (since queueing at the input/ouput of the gr-blocks is avoided). + + +Still need to document them... </para> diff --git a/gr-trellis/src/examples/Makefile.am b/gr-trellis/src/examples/Makefile.am index 8fb727acd..92aeadfad 100644 --- a/gr-trellis/src/examples/Makefile.am +++ b/gr-trellis/src/examples/Makefile.am @@ -31,8 +31,6 @@ dist_ourdata_DATA = \ dist_ourdata_SCRIPTS = \ fsm_utils.py \ test_tcm.py \ - test_tcm1.py \ - test_tcm2.py \ test_tcm_parallel.py \ test_tcm_combined.py \ test_sccc_hard.py \ diff --git a/gr-trellis/src/examples/README b/gr-trellis/src/examples/README index d5bad85f5..bd28e3d61 100644 --- a/gr-trellis/src/examples/README +++ b/gr-trellis/src/examples/README @@ -6,28 +6,10 @@ fsm_utils.py contains several useful functions. fsm_files is a directory with some FSM definitions -If you just want to see what these programs do, run each of the following: +If you just want to see what these programs do run them; +in your terminal you will see something like this: -./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/awgn2o3_4_msb.fsm 10.0 100 -./test_sccc_soft.py fsm_files/awgn1o2_4.fsm fsm_files/awgn2o3_4_msb.fsm 8.0 100 -./test_sccc_turbo.py fsm_files/awgn1o2_4.fsm fsm_files/awgn2o3_4_msb.fsm 5.0 100 - -./test_viterbi_equalization.py 12.0 100 -./test_viterbi_equalization1.py 12.0 100 -./test_turbo_equalization1.py fsm_files/awgn1o2_4.fsm 8.0 100 -./test_turbo_equalization2.py fsm_files/awgn1o2_4.fsm 8.0 100 - - -In your terminal you will see something like this: - - -$ ./test_tcm.py fsm_files/awgn1o2_4.fsm 6.0 1000 +$ ./test_tcm.py --esn0 6.0 --repetitions 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 diff --git a/gr-trellis/src/examples/test_pccc_turbo1.py b/gr-trellis/src/examples/test_pccc_turbo1.py new file mode 100755 index 000000000..1173d0734 --- /dev/null +++ b/gr-trellis/src/examples/test_pccc_turbo1.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python + +from gnuradio import gr +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,Es,N0,IT,seed): + tb = gr.top_block () + + + # 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 + #src = gr.vector_source_s([0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],False) + enc = trellis.pccc_encoder_ss(fo,0,fi,0,interleaver,K) + code = gr.vector_sink_s() + 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()*fo.O(),dimensionality,constellation,trellis.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for innner SISO + scale = gr.multiply_const_ff(1.0/N0) + dec = trellis.pccc_decoder_s(fo,0,-1,fi,0,-1,interleaver,K,IT,trellis.TRELLIS_MIN_SUM) + + fsmi2s = gr.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts + dst = gr.check_lfsr_32k_s() + + tb.connect (src,src_head,s2fsmi,enc,mod) + #tb.connect (src,enc,mod) + #tb.connect(enc,code) + tb.connect (mod,(add,0)) + tb.connect (noise,(add,1)) + tb.connect (add,metrics_in,scale,dec,fsmi2s,dst) + + tb.run() + + #print code.data() + + ntotal = dst.ntotal () + nright = dst.nright () + runlength = dst.runlength () + return (ntotal,ntotal-nright) + + +def main(args): + nargs = len (args) + if nargs == 5: + fname_out=args[0] + fname_in=args[1] + esn0_db=float(args[2]) # Es/No in dB + IT=int(args[3]) + rep=int(args[4]) # number of times the experiment is run to collect enough errors + else: + sys.stderr.write ('usage: test_pccc_turbo.py fsm_name_1 fsm_fname_2 Es/No_db iterations 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.I() != fi.I(): + sys.stderr.write ('Incompatible input cardinality between two FSMs.\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 = 4 + constellation = [ 1, 0, 1, 0,\ + 1, 0,-1, 0,\ + 1, 0, 0, 1,\ + 1, 0, 0,-1,\ + -1, 0, 1, 0,\ + -1, 0,-1, 0,\ + -1, 0, 0, 1,\ + -1, 0, 0,-1,\ + 0, 1, 1, 0,\ + 0, 1,-1, 0,\ + 0, 1, 0, 1,\ + 0, 1, 0,-1,\ + 0,-1, 1, 0,\ + 0,-1,-1, 0,\ + 0,-1, 0, 1,\ + 0,-1, 0,-1,] # equivalent to 2 QPSK symbols + if len(constellation)/dimensionality != fi.O()*fo.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,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:]) diff --git a/gr-trellis/src/examples/test_sccc_hard.py b/gr-trellis/src/examples/test_sccc_hard.py index a7933a18e..1a81bc59b 100755 --- a/gr-trellis/src/examples/test_sccc_hard.py +++ b/gr-trellis/src/examples/test_sccc_hard.py @@ -1,7 +1,6 @@ #!/usr/bin/env python from gnuradio import gr -from gnuradio import audio from gnuradio import trellis from gnuradio import eng_notation import math diff --git a/gr-trellis/src/examples/test_sccc_soft.py b/gr-trellis/src/examples/test_sccc_soft.py index d96d36e3f..ea296e1e9 100755 --- a/gr-trellis/src/examples/test_sccc_soft.py +++ b/gr-trellis/src/examples/test_sccc_soft.py @@ -1,7 +1,6 @@ #!/usr/bin/env python from gnuradio import gr -from gnuradio import audio from gnuradio import trellis from gnuradio import eng_notation import math diff --git a/gr-trellis/src/examples/test_sccc_turbo.py b/gr-trellis/src/examples/test_sccc_turbo.py index f3a856de7..703ee410b 100755 --- a/gr-trellis/src/examples/test_sccc_turbo.py +++ b/gr-trellis/src/examples/test_sccc_turbo.py @@ -1,7 +1,6 @@ #!/usr/bin/env python from gnuradio import gr -from gnuradio import audio from gnuradio import trellis from gnuradio import eng_notation import math @@ -92,13 +91,14 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation, def main(args): nargs = len (args) - if nargs == 4: + if nargs == 5: 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 + IT=int(args[3]) + rep=int(args[4]) # 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.stderr.write ('usage: test_sccc_turbo.py fsm_name_out fsm_fname_in Es/No_db iterations repetitions\n') sys.exit (1) # system parameters @@ -123,7 +123,6 @@ def main(args): 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 diff --git a/gr-trellis/src/examples/test_tcm2.py b/gr-trellis/src/examples/test_sccc_turbo1.py index e527fc5ed..8a630c0d4 100755 --- a/gr-trellis/src/examples/test_tcm2.py +++ b/gr-trellis/src/examples/test_sccc_turbo1.py @@ -1,7 +1,6 @@ #!/usr/bin/env python from gnuradio import gr -from gnuradio import audio from gnuradio import trellis from gnuradio import eng_notation import math @@ -9,20 +8,15 @@ import sys import random import fsm_utils -def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): - tb = gr.top_block () +def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation,Es,N0,IT,seed): + tb = gr.top_block () # 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 + s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the outer FSM input cardinality + enc = trellis.sccc_encoder_ss(fo,0,fi,0,interleaver,K) mod = gr.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL @@ -30,65 +24,54 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): 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. + dec = trellis.sccc_decoder_combined_fs(fo,0,-1,fi,0,-1,interleaver,K,IT,trellis.TRELLIS_MIN_SUM,dimensionality,constellation,trellis.TRELLIS_EUCLIDEAN,1.0) 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() - + #tb.connect (src,src_head,s2fsmi,enc_out,inter,enc_in,mod) tb.connect (src,src_head,s2fsmi,enc,mod) - #tb.connect (src,b2s,s2fsmi,enc,mod) tb.connect (mod,(add,0)) tb.connect (noise,(add,1)) - tb.connect (add,metrics) - tb.connect (metrics,va,fsmi2s,dst) - #tb.connect (metrics,va,fsmi2s,s2b,dst) - + #tb.connect (add,head) + #tb.connect (tail,fsmi2s,dst) + tb.connect (add,dec,fsmi2s,dst) tb.run() + + #print enc_out.ST(), enc_in.ST() - # 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 + if nargs == 5: + fname_out=args[0] + fname_in=args[1] + esn0_db=float(args[2]) # Es/No in dB + IT=int(args[3]) + rep=int(args[4]) # 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.stderr.write ('usage: test_tcm.py fsm_name_out fsm_fname_in Es/No_db iterations 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 + 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 - modulation = fsm_utils.psk4 # see fsm_utlis.py for available predefined modulations + 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 != f.O(): + if len(constellation)/dimensionality != fi.O(): sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n') sys.exit (1) # calculate average symbol energy @@ -102,11 +85,11 @@ def main(args): 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 + (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)%100==0) : # display progress + 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) diff --git a/gr-trellis/src/examples/test_sccc_turbo2.py b/gr-trellis/src/examples/test_sccc_turbo2.py new file mode 100755 index 000000000..a47f6400e --- /dev/null +++ b/gr-trellis/src/examples/test_sccc_turbo2.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python + +from gnuradio import gr +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,Es,N0,IT,seed): + tb = gr.top_block () + + # 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 = trellis.sccc_encoder_ss(fo,0,fi,0,interleaver,K) + 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 SISO + scale = gr.multiply_const_ff(1.0/N0) + dec = trellis.sccc_decoder_s(fo,0,-1,fi,0,-1,interleaver,K,IT,trellis.TRELLIS_MIN_SUM) + fsmi2s = gr.unpacked_to_packed_ss(bitspersymbol,gr.GR_MSB_FIRST) # pack FSM input symbols to shorts + dst = gr.check_lfsr_32k_s() + + #tb.connect (src,src_head,s2fsmi,enc_out,inter,enc_in,mod) + tb.connect (src,src_head,s2fsmi,enc,mod) + tb.connect (mod,(add,0)) + tb.connect (noise,(add,1)) + #tb.connect (add,head) + #tb.connect (tail,fsmi2s,dst) + tb.connect (add,metrics_in,scale,dec,fsmi2s,dst) + + tb.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 == 5: + fname_out=args[0] + fname_in=args[1] + esn0_db=float(args[2]) # Es/No in dB + IT=int(args[3]) + rep=int(args[4]) # 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 iterations 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,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:]) diff --git a/gr-trellis/src/examples/test_tcm.py b/gr-trellis/src/examples/test_tcm.py index 62e0c413a..d2e3c6271 100755 --- a/gr-trellis/src/examples/test_tcm.py +++ b/gr-trellis/src/examples/test_tcm.py @@ -1,13 +1,14 @@ #!/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 +from gnuradio.eng_option import eng_option +from optparse import OptionParser def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): tb = gr.top_block () @@ -71,18 +72,25 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): -def main(args): - nargs = len (args) - if nargs == 3: - fname=args[0] - esn0_db=float(args[1]) # Es/No in dB - rep=int(args[2]) # number of times the experiment is run to collect enough errors - else: - sys.stderr.write ('usage: test_tcm.py fsm_fname Es/No_db repetitions\n') - sys.exit (1) +def main(): + parser = OptionParser(option_class=eng_option) + parser.add_option("-f", "--fsm_file", type="string", default="fsm_files/awgn1o2_4.fsm", help="Filename containing the fsm specification, e.g. -f fsm_files/awgn1o2_4.fsm (default=fsm_files/awgn1o2_4.fsm)") + parser.add_option("-e", "--esn0", type="eng_float", default=10.0, help="Symbol energy to noise PSD level ratio in dB, e.g., -e 10.0 (default=10.0)") + parser.add_option("-r", "--repetitions", type="int", default=100, help="Number of packets to be generated for the simulation, e.g., -r 100 (default=100)") + + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + fname=options.fsm_file + esn0_db=float(options.esn0) + rep=int(options.repetitions) # system parameters f=trellis.fsm(fname) # get the FSM specification from a file + # alternatively you can specify the fsm from its generator matrix + #f=trellis.fsm(1,2,[5,7]) 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 @@ -115,4 +123,4 @@ def main(args): if __name__ == '__main__': - main (sys.argv[1:]) + main() diff --git a/gr-trellis/src/examples/test_tcm1.py b/gr-trellis/src/examples/test_tcm_bit.py index 746bd9336..008e1e6f0 100755 --- a/gr-trellis/src/examples/test_tcm1.py +++ b/gr-trellis/src/examples/test_tcm_bit.py @@ -1,13 +1,15 @@ #!/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 +from gnuradio.eng_option import eng_option +from optparse import OptionParser + def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): tb = gr.top_block () @@ -74,15 +76,21 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): -def main(args): - nargs = len (args) - if nargs == 3: - fname=args[0] - esn0_db=float(args[1]) # Es/No in dB - rep=int(args[2]) # number of times the experiment is run to collect enough errors - else: - sys.stderr.write ('usage: test_tcm.py fsm_fname Es/No_db repetitions\n') - sys.exit (1) +def main(): + parser = OptionParser(option_class=eng_option) + parser.add_option("-f", "--fsm_file", type="string", default="fsm_files/awgn1o2_4.fsm", help="Filename containing the fsm specification, e.g. -f fsm_files/awgn1o2_4.fsm (default=fsm_files/awgn1o2_4.fsm)") + parser.add_option("-e", "--esn0", type="eng_float", default=10.0, help="Symbol energy to noise PSD level ratio in dB, e.g., -e 10.0 (default=10.0)") + parser.add_option("-r", "--repetitions", type="int", default=100, help="Number of packets to be generated for the simulation, e.g., -r 100 (default=100)") + + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + fname=options.fsm_file + esn0_db=float(options.esn0) + rep=int(options.repetitions) + # system parameters f=trellis.fsm(fname) # get the FSM specification from a file @@ -100,7 +108,7 @@ def main(args): for i in range(len(constellation)): Es = Es + constellation[i]**2 Es = Es / (len(constellation)/dimensionality) - N0=Es/pow(10.0,esn0_db/10.0); # noise variance + 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 @@ -118,4 +126,4 @@ def main(args): if __name__ == '__main__': - main (sys.argv[1:]) + main() diff --git a/gr-trellis/src/examples/test_tcm_combined.py b/gr-trellis/src/examples/test_tcm_combined.py index d2d42b40b..f9b698ae9 100755 --- a/gr-trellis/src/examples/test_tcm_combined.py +++ b/gr-trellis/src/examples/test_tcm_combined.py @@ -1,12 +1,14 @@ #!/usr/bin/env python from gnuradio import gr -from gnuradio import audio from gnuradio import trellis from gnuradio import eng_notation import math import sys import fsm_utils +from gnuradio.eng_option import eng_option +from optparse import OptionParser + def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): tb = gr.top_block () @@ -52,15 +54,20 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): -def main(args): - nargs = len (args) - if nargs == 3: - fname=args[0] - esn0_db=float(args[1]) # Es/No in dB - rep=int(args[2]) # number of times the experiment is run to collect enough errors - else: - sys.stderr.write ('usage: test_tcm_combined.py fsm_fname Es/No_db repetitions\n') - sys.exit (1) +def main(): + parser = OptionParser(option_class=eng_option) + parser.add_option("-f", "--fsm_file", type="string", default="fsm_files/awgn1o2_4.fsm", help="Filename containing the fsm specification, e.g. -f fsm_files/awgn1o2_4.fsm (default=fsm_files/awgn1o2_4.fsm)") + parser.add_option("-e", "--esn0", type="eng_float", default=10.0, help="Symbol energy to noise PSD level ratio in dB, e.g., -e 10.0 (default=10.0)") + parser.add_option("-r", "--repetitions", type="int", default=100, help="Number of packets to be generated for the simulation, e.g., -r 100 (default=100)") + + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + fname=options.fsm_file + esn0_db=float(options.esn0) + rep=int(options.repetitions) # system parameters f=trellis.fsm(fname) # get the FSM specification from a file (will hopefully be automated in the future...) @@ -96,5 +103,5 @@ def main(args): if __name__ == '__main__': - main (sys.argv[1:]) + main() diff --git a/gr-trellis/src/examples/test_tcm_parallel.py b/gr-trellis/src/examples/test_tcm_parallel.py index 8e2f5a230..94761fd01 100755 --- a/gr-trellis/src/examples/test_tcm_parallel.py +++ b/gr-trellis/src/examples/test_tcm_parallel.py @@ -1,12 +1,14 @@ #!/usr/bin/env python from gnuradio import gr -from gnuradio import audio from gnuradio import trellis from gnuradio import eng_notation import math import sys import fsm_utils +from gnuradio.eng_option import eng_option +from optparse import OptionParser + def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed,P): tb = gr.top_block () @@ -58,15 +60,20 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed,P): -def main(args): - nargs = len (args) - if nargs == 3: - fname=args[0] - esn0_db=float(args[1]) # Es/No in dB - rep=int(args[2]) # number of times the experiment is run to collect enough errors - else: - sys.stderr.write ('usage: test_tcm.py fsm_fname Es/No_db repetitions\n') - sys.exit (1) +def main(): + parser = OptionParser(option_class=eng_option) + parser.add_option("-f", "--fsm_file", type="string", default="fsm_files/awgn1o2_4.fsm", help="Filename containing the fsm specification, e.g. -f fsm_files/awgn1o2_4.fsm (default=fsm_files/awgn1o2_4.fsm)") + parser.add_option("-e", "--esn0", type="eng_float", default=10.0, help="Symbol energy to noise PSD level ratio in dB, e.g., -e 10.0 (default=10.0)") + parser.add_option("-r", "--repetitions", type="int", default=100, help="Number of packets to be generated for the simulation, e.g., -r 100 (default=100)") + + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + fname=options.fsm_file + esn0_db=float(options.esn0) + rep=int(options.repetitions) # system parameters f=trellis.fsm(fname) # get the FSM specification from a file @@ -102,5 +109,5 @@ def main(args): if __name__ == '__main__': - main (sys.argv[1:]) + main() diff --git a/gr-trellis/src/examples/test_turbo_equalization.py b/gr-trellis/src/examples/test_turbo_equalization.py index 612f6951c..0bf691222 100755 --- a/gr-trellis/src/examples/test_turbo_equalization.py +++ b/gr-trellis/src/examples/test_turbo_equalization.py @@ -1,7 +1,6 @@ #!/usr/bin/env python from gnuradio import gr -from gnuradio import audio from gnuradio import trellis from gnuradio import eng_notation import math diff --git a/gr-trellis/src/examples/test_turbo_equalization1.py b/gr-trellis/src/examples/test_turbo_equalization1.py index 8d2feec8a..feae4ce89 100755 --- a/gr-trellis/src/examples/test_turbo_equalization1.py +++ b/gr-trellis/src/examples/test_turbo_equalization1.py @@ -1,7 +1,6 @@ #!/usr/bin/env python from gnuradio import gr -from gnuradio import audio from gnuradio import trellis from gnuradio import eng_notation import math diff --git a/gr-trellis/src/examples/test_turbo_equalization2.py b/gr-trellis/src/examples/test_turbo_equalization2.py index f1731016e..ff14299c6 100755 --- a/gr-trellis/src/examples/test_turbo_equalization2.py +++ b/gr-trellis/src/examples/test_turbo_equalization2.py @@ -1,7 +1,6 @@ #!/usr/bin/env python from gnuradio import gr -from gnuradio import audio from gnuradio import trellis from gnuradio import eng_notation import math diff --git a/gr-trellis/src/examples/test_viterbi_equalization.py b/gr-trellis/src/examples/test_viterbi_equalization.py index 86fc00674..eda692024 100755 --- a/gr-trellis/src/examples/test_viterbi_equalization.py +++ b/gr-trellis/src/examples/test_viterbi_equalization.py @@ -1,7 +1,6 @@ #!/usr/bin/env python from gnuradio import gr -from gnuradio import audio from gnuradio import trellis from gnuradio import eng_notation import math diff --git a/gr-trellis/src/examples/test_viterbi_equalization1.py b/gr-trellis/src/examples/test_viterbi_equalization1.py index d26f73bc0..3a65b9363 100755 --- a/gr-trellis/src/examples/test_viterbi_equalization1.py +++ b/gr-trellis/src/examples/test_viterbi_equalization1.py @@ -1,7 +1,6 @@ #!/usr/bin/env python from gnuradio import gr -from gnuradio import audio from gnuradio import trellis from gnuradio import eng_notation import math diff --git a/gr-trellis/src/lib/.gitignore b/gr-trellis/src/lib/.gitignore index 8932c3611..816b0aab8 100644 --- a/gr-trellis/src/lib/.gitignore +++ b/gr-trellis/src/lib/.gitignore @@ -57,6 +57,24 @@ /trellis_viterbi_i.cc /trellis_encoder_bb.h /trellis_encoder_bb.i +/trellis_sccc_encoder_bb.cc +/trellis_sccc_encoder_bb.h +/trellis_sccc_encoder_bb.i +/trellis_sccc_encoder_bi.cc +/trellis_sccc_encoder_bi.h +/trellis_sccc_encoder_bi.i +/trellis_sccc_encoder_bs.cc +/trellis_sccc_encoder_bs.h +/trellis_sccc_encoder_bs.i +/trellis_sccc_encoder_ii.cc +/trellis_sccc_encoder_ii.h +/trellis_sccc_encoder_ii.i +/trellis_sccc_encoder_si.cc +/trellis_sccc_encoder_si.h +/trellis_sccc_encoder_si.i +/trellis_sccc_encoder_ss.cc +/trellis_sccc_encoder_ss.h +/trellis_sccc_encoder_ss.i /trellis_metrics_s.cc /trellis_viterbi_combined_fs.h /trellis_viterbi_combined_fs.i @@ -94,6 +112,64 @@ /trellis_viterbi_combined_ss.i /trellis_viterbi_combined_ib.cc /trellis_viterbi_combined_sb.cc +/trellis_sccc_decoder_combined_fb.h +/trellis_sccc_decoder_combined_fb.i +/trellis_sccc_decoder_combined_fb.cc +/trellis_sccc_decoder_combined_fs.h +/trellis_sccc_decoder_combined_fs.i +/trellis_sccc_decoder_combined_fs.cc +/trellis_sccc_decoder_combined_fi.h +/trellis_sccc_decoder_combined_fi.i +/trellis_sccc_decoder_combined_fi.cc +/trellis_sccc_decoder_combined_cb.h +/trellis_sccc_decoder_combined_cb.i +/trellis_sccc_decoder_combined_cb.cc +/trellis_sccc_decoder_combined_cs.h +/trellis_sccc_decoder_combined_cs.i +/trellis_sccc_decoder_combined_cs.cc +/trellis_sccc_decoder_combined_ci.h +/trellis_sccc_decoder_combined_ci.i +/trellis_sccc_decoder_combined_ci.cc +/trellis_sccc_decoder_b.h +/trellis_sccc_decoder_b.i +/trellis_sccc_decoder_b.cc +/trellis_sccc_decoder_s.h +/trellis_sccc_decoder_s.i +/trellis_sccc_decoder_s.cc +/trellis_sccc_decoder_i.h +/trellis_sccc_decoder_i.i +/trellis_sccc_decoder_i.cc +/trellis_pccc_decoder_b.h +/trellis_pccc_decoder_b.i +/trellis_pccc_decoder_b.cc +/trellis_pccc_decoder_s.h +/trellis_pccc_decoder_s.i +/trellis_pccc_decoder_s.cc +/trellis_pccc_decoder_i.h +/trellis_pccc_decoder_i.i +/trellis_pccc_decoder_i.cc +/trellis_pccc_encoder_bb.cc +/trellis_pccc_encoder_bb.h +/trellis_pccc_encoder_bb.i +/trellis_pccc_encoder_bi.cc +/trellis_pccc_encoder_bi.h +/trellis_pccc_encoder_bi.i +/trellis_pccc_encoder_bs.cc +/trellis_pccc_encoder_bs.h +/trellis_pccc_encoder_bs.i +/trellis_pccc_encoder_ii.cc +/trellis_pccc_encoder_ii.h +/trellis_pccc_encoder_ii.i +/trellis_pccc_encoder_si.cc +/trellis_pccc_encoder_si.h +/trellis_pccc_encoder_si.i +/trellis_pccc_encoder_ss.cc +/trellis_pccc_encoder_ss.h +/trellis_pccc_encoder_ss.i /trellis_generated.i /generate-stamp /stamp-* +/run_guile_tests +/gnuradio +/guile +/python diff --git a/gr-trellis/src/lib/Makefile.am b/gr-trellis/src/lib/Makefile.am index 3e1803554..795ac28b4 100644 --- a/gr-trellis/src/lib/Makefile.am +++ b/gr-trellis/src/lib/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. +# Copyright 2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -20,8 +20,17 @@ # include $(top_srcdir)/Makefile.common +include $(top_srcdir)/Makefile.swig + +TESTS = + +EXTRA_DIST += \ + run_guile_tests.in \ + trellis.test -AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) $(WITH_INCLUDES) + +AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) $(WITH_INCLUDES) \ + -I$(abs_top_srcdir)/gr-digital/lib -I/home # ---------------------------------------------------------------- # these scripts generate trellis codes from template files @@ -32,12 +41,27 @@ core_generator = \ trellis_encoder_XX.cc.t \ trellis_encoder_XX.h.t \ trellis_encoder_XX.i.t \ + trellis_sccc_encoder_XX.cc.t \ + trellis_sccc_encoder_XX.h.t \ + trellis_sccc_encoder_XX.i.t \ + trellis_pccc_encoder_XX.cc.t \ + trellis_pccc_encoder_XX.h.t \ + trellis_pccc_encoder_XX.i.t \ trellis_metrics_X.cc.t \ trellis_metrics_X.h.t \ trellis_metrics_X.i.t \ trellis_viterbi_combined_XX.cc.t \ trellis_viterbi_combined_XX.h.t \ trellis_viterbi_combined_XX.i.t \ + trellis_sccc_decoder_combined_XX.cc.t \ + trellis_sccc_decoder_combined_XX.h.t \ + trellis_sccc_decoder_combined_XX.i.t \ + trellis_sccc_decoder_X.cc.t \ + trellis_sccc_decoder_X.h.t \ + trellis_sccc_decoder_X.i.t \ + trellis_pccc_decoder_X.cc.t \ + trellis_pccc_decoder_X.h.t \ + trellis_pccc_decoder_X.i.t \ trellis_viterbi_X.cc.t \ trellis_viterbi_X.h.t \ trellis_viterbi_X.i.t @@ -49,7 +73,7 @@ python_built_sources = \ $(GENERATED_CC) \ trellis_generated.i -EXTRA_DIST = \ +EXTRA_DIST += \ $(core_generator) # These headers get installed in ${prefix}/include/gnuradio @@ -58,12 +82,13 @@ grinclude_HEADERS = \ quicksort_index.h \ base.h \ interleaver.h \ - trellis_metric_type.h \ - trellis_calc_metric.h \ + calc_metric.h \ + core_algorithms.h \ trellis_permutation.h \ - trellis_siso_type.h \ + siso_type.h \ trellis_siso_f.h \ trellis_siso_combined_f.h \ + trellis_constellation_metrics_cf.h \ $(GENERATED_H) lib_LTLIBRARIES = libgnuradio-trellis.la @@ -73,10 +98,12 @@ libgnuradio_trellis_la_SOURCES = \ quicksort_index.cc \ base.cc \ interleaver.cc \ - trellis_calc_metric.cc \ + calc_metric.cc \ + core_algorithms.cc \ trellis_permutation.cc \ trellis_siso_f.cc \ trellis_siso_combined_f.cc \ + trellis_constellation_metrics_cf.cc \ $(GENERATED_CC) libgnuradio_trellis_la_LIBADD = \ @@ -84,8 +111,8 @@ libgnuradio_trellis_la_LIBADD = \ libgnuradio_trellis_la_LDFLAGS = $(NO_UNDEFINED) $(LTVERSIONFLAGS) +trellis.py trellis.scm: trellis_generated.i -if PYTHON ################################# # SWIG interface and library @@ -111,6 +138,7 @@ trellis_swiginclude_headers = \ trellis_permutation.i \ trellis_siso_f.i \ trellis_siso_combined_f.i \ + trellis_constellation_metrics_cf.i \ trellis_generated.i # Do creation and inclusion of other Makefiles last @@ -130,13 +158,13 @@ gen_sources_deps = $(core_generator) par_gen_command = PYTHONPATH=$(top_srcdir)/gnuradio-core/src/python srcdir=$(srcdir) $(PYTHON) $(srcdir)/generate_all.py include $(top_srcdir)/Makefile.par.gen -include $(top_srcdir)/Makefile.swig +BUILT_SOURCES += $(python_built_sources) -# add some of the variables generated inside the Makefile.swig.gen -BUILT_SOURCES = \ - $(python_built_sources) \ - $(swig_built_sources) +# Location of non-standard SWIG interface files +trellis_swig_args = \ + -I$(top_srcdir)/gr-digital/lib \ + -I$(top_srcdir)/gr-digital/swig -# Do not distribute the output of SWIG -no_dist_files = $(swig_built_sources) +if GUILE +TESTS += run_guile_tests endif diff --git a/gr-trellis/src/lib/Makefile.gen b/gr-trellis/src/lib/Makefile.gen index 6a3f83387..534a7466e 100644 --- a/gr-trellis/src/lib/Makefile.gen +++ b/gr-trellis/src/lib/Makefile.gen @@ -12,6 +12,30 @@ GENERATED_H = \ trellis_metrics_f.h \ trellis_metrics_i.h \ trellis_metrics_s.h \ + trellis_pccc_decoder_b.h \ + trellis_pccc_decoder_i.h \ + trellis_pccc_decoder_s.h \ + trellis_pccc_encoder_bb.h \ + trellis_pccc_encoder_bi.h \ + trellis_pccc_encoder_bs.h \ + trellis_pccc_encoder_ii.h \ + trellis_pccc_encoder_si.h \ + trellis_pccc_encoder_ss.h \ + trellis_sccc_decoder_b.h \ + trellis_sccc_decoder_combined_cb.h \ + trellis_sccc_decoder_combined_ci.h \ + trellis_sccc_decoder_combined_cs.h \ + trellis_sccc_decoder_combined_fb.h \ + trellis_sccc_decoder_combined_fi.h \ + trellis_sccc_decoder_combined_fs.h \ + trellis_sccc_decoder_i.h \ + trellis_sccc_decoder_s.h \ + trellis_sccc_encoder_bb.h \ + trellis_sccc_encoder_bi.h \ + trellis_sccc_encoder_bs.h \ + trellis_sccc_encoder_ii.h \ + trellis_sccc_encoder_si.h \ + trellis_sccc_encoder_ss.h \ trellis_viterbi_b.h \ trellis_viterbi_combined_cb.h \ trellis_viterbi_combined_ci.h \ @@ -39,6 +63,30 @@ GENERATED_I = \ trellis_metrics_f.i \ trellis_metrics_i.i \ trellis_metrics_s.i \ + trellis_pccc_decoder_b.i \ + trellis_pccc_decoder_i.i \ + trellis_pccc_decoder_s.i \ + trellis_pccc_encoder_bb.i \ + trellis_pccc_encoder_bi.i \ + trellis_pccc_encoder_bs.i \ + trellis_pccc_encoder_ii.i \ + trellis_pccc_encoder_si.i \ + trellis_pccc_encoder_ss.i \ + trellis_sccc_decoder_b.i \ + trellis_sccc_decoder_combined_cb.i \ + trellis_sccc_decoder_combined_ci.i \ + trellis_sccc_decoder_combined_cs.i \ + trellis_sccc_decoder_combined_fb.i \ + trellis_sccc_decoder_combined_fi.i \ + trellis_sccc_decoder_combined_fs.i \ + trellis_sccc_decoder_i.i \ + trellis_sccc_decoder_s.i \ + trellis_sccc_encoder_bb.i \ + trellis_sccc_encoder_bi.i \ + trellis_sccc_encoder_bs.i \ + trellis_sccc_encoder_ii.i \ + trellis_sccc_encoder_si.i \ + trellis_sccc_encoder_ss.i \ trellis_viterbi_b.i \ trellis_viterbi_combined_cb.i \ trellis_viterbi_combined_ci.i \ @@ -66,6 +114,30 @@ GENERATED_CC = \ trellis_metrics_f.cc \ trellis_metrics_i.cc \ trellis_metrics_s.cc \ + trellis_pccc_decoder_b.cc \ + trellis_pccc_decoder_i.cc \ + trellis_pccc_decoder_s.cc \ + trellis_pccc_encoder_bb.cc \ + trellis_pccc_encoder_bi.cc \ + trellis_pccc_encoder_bs.cc \ + trellis_pccc_encoder_ii.cc \ + trellis_pccc_encoder_si.cc \ + trellis_pccc_encoder_ss.cc \ + trellis_sccc_decoder_b.cc \ + trellis_sccc_decoder_combined_cb.cc \ + trellis_sccc_decoder_combined_ci.cc \ + trellis_sccc_decoder_combined_cs.cc \ + trellis_sccc_decoder_combined_fb.cc \ + trellis_sccc_decoder_combined_fi.cc \ + trellis_sccc_decoder_combined_fs.cc \ + trellis_sccc_decoder_i.cc \ + trellis_sccc_decoder_s.cc \ + trellis_sccc_encoder_bb.cc \ + trellis_sccc_encoder_bi.cc \ + trellis_sccc_encoder_bs.cc \ + trellis_sccc_encoder_ii.cc \ + trellis_sccc_encoder_si.cc \ + trellis_sccc_encoder_ss.cc \ trellis_viterbi_b.cc \ trellis_viterbi_combined_cb.cc \ trellis_viterbi_combined_ci.cc \ diff --git a/gr-trellis/src/lib/Makefile.swig.gen b/gr-trellis/src/lib/Makefile.swig.gen index 1a9656b8f..2d014b946 100644 --- a/gr-trellis/src/lib/Makefile.swig.gen +++ b/gr-trellis/src/lib/Makefile.swig.gen @@ -38,6 +38,16 @@ trellis_pylibdir_category ?= $(trellis_pythondir_category) trellis_pythondir = $(pythondir)/$(trellis_pythondir_category) trellis_pylibdir = $(pyexecdir)/$(trellis_pylibdir_category) +# The .so libraries for the guile modules get installed whereever guile +# is installed, usually /usr/lib/guile/gnuradio/ +# FIXME: determince whether these should be installed with gnuradio. +trellis_scmlibdir = $(libdir) + +# The scm files for the guile modules get installed where ever guile +# is installed, usually /usr/share/guile/site/trellis +# FIXME: determince whether these should be installed with gnuradio. +trellis_scmdir = $(guiledir) + ## SWIG headers are always installed into the same directory. trellis_swigincludedir = $(swigincludedir) @@ -57,23 +67,10 @@ trellis_swigincludedir = $(swigincludedir) ## right thing. For more info, see < ## http://sources.redhat.com/automake/automake.html#Multiple-Outputs > -## Stamps used to ensure parallel make does the right thing. These -## are removed by "make clean", but otherwise unused except during the -## parallel built. These will not be included in a tarball, because -## the SWIG-generated files will be removed from the distribution. - -STAMPS += $(DEPDIR)/trellis-generate-* - ## Other cleaned files: dependency files generated by SWIG or this Makefile MOSTLYCLEANFILES += $(DEPDIR)/*.S* -## Add the .py and .cc files to the list of SWIG built sources. The -## .h file is sometimes built, but not always ... so that one has to -## be added manually by the including Makefile.am . - -swig_built_sources += trellis.py trellis.cc - ## Various SWIG variables. These can be overloaded in the including ## Makefile.am by setting the variable value there, then including ## Makefile.swig . @@ -82,13 +79,18 @@ trellis_swiginclude_HEADERS = \ trellis.i \ $(trellis_swiginclude_headers) +if PYTHON trellis_pylib_LTLIBRARIES = \ _trellis.la _trellis_la_SOURCES = \ - trellis.cc \ + python/trellis.cc \ $(trellis_la_swig_sources) +trellis_python_PYTHON = \ + trellis.py \ + $(trellis_python) + _trellis_la_LIBADD = \ $(STD_SWIG_LA_LIB_ADD) \ $(trellis_la_swig_libadd) @@ -99,161 +101,45 @@ _trellis_la_LDFLAGS = \ _trellis_la_CXXFLAGS = \ $(STD_SWIG_CXX_FLAGS) \ + -I$(top_builddir) \ $(trellis_la_swig_cxxflags) -trellis_python_PYTHON = \ - trellis.py \ - $(trellis_python) +python/trellis.cc: trellis.py +trellis.py: trellis.i -## Entry rule for running SWIG +# Include the python dependencies for this file +-include python/trellis.d -trellis.h trellis.py trellis.cc: trellis.i -## This rule will get called only when MAKE decides that one of the -## targets needs to be created or re-created, because: -## -## * The .i file is newer than any or all of the generated files; -## -## * Any or all of the .cc, .h, or .py files does not exist and is -## needed (in the case this file is not needed, the rule for it is -## ignored); or -## -## * Some SWIG-based dependecy of the .cc file isn't met and hence the -## .cc file needs be be regenerated. Explanation: Because MAKE -## knows how to handle dependencies for .cc files (regardless of -## their name or extension), then the .cc file is used as a target -## instead of the .i file -- but with the dependencies of the .i -## file. It is this last reason why the line: -## -## if test -f $@; then :; else -## -## cannot be used in this case: If a .i file dependecy is not met, -## then the .cc file needs to be rebuilt. But if the stamp is newer -## than the .cc file, and the .cc file exists, then in the original -## version (with the 'test' above) the internal MAKE call will not -## be issued and hence the .cc file will not be rebuilt. -## -## Once execution gets to here, it should always proceed no matter the -## state of a stamp (as discussed in link above). The -## $(DEPDIR)/trellis-generate stuff is used to allow for parallel -## builds to "do the right thing". The stamp has no relationship with -## either the target files or dependency file; it is used solely for -## the protection of multiple builds during a given call to MAKE. -## -## Catch signals SIGHUP (1), SIGINT (2), SIGPIPE (13), and SIGTERM -## (15). At a caught signal, the quoted command will be issued before -## exiting. In this case, remove any stamp, whether temporary of not. -## The trap is valid until the process exits; the process includes all -## commands appended via "\"s. -## - trap 'rm -rf $(DEPDIR)/trellis-generate-*' 1 2 13 15; \ -## -## Create a temporary directory, which acts as a lock. The first -## process to create the directory will succeed and issue the MAKE -## command to do the actual work, while all subsequent processes will -## fail -- leading them to wait for the first process to finish. -## - if mkdir $(DEPDIR)/trellis-generate-lock 2>/dev/null; then \ -## -## This code is being executed by the first process to succeed in -## creating the directory lock. -## -## Remove the stamp associated with this filename. -## - rm -f $(DEPDIR)/trellis-generate-stamp; \ -## -## Tell MAKE to run the rule for creating this stamp. -## - $(MAKE) $(AM_MAKEFLAGS) $(DEPDIR)/trellis-generate-stamp WHAT=$<; \ -## -## Now that the .cc, .h, and .py files have been (re)created from the -## .i file, future checking of this rule during the same MAKE -## execution will come back that the rule doesn't need to be executed -## because none of the conditions mentioned at the start of this rule -## will be positive. Remove the the directory lock, which frees up -## any waiting process(es) to continue. -## - rmdir $(DEPDIR)/trellis-generate-lock; \ - else \ -## -## This code is being executed by any follower processes while the -## directory lock is in place. -## -## Wait until the first process is done, testing once per second. -## - while test -d $(DEPDIR)/trellis-generate-lock; do \ - sleep 1; \ - done; \ -## -## Succeed if and only if the first process succeeded; exit this -## process returning the status of the generated stamp. -## - test -f $(DEPDIR)/trellis-generate-stamp; \ - exit $$?; \ - fi; +endif # end of if python -$(DEPDIR)/trellis-generate-stamp: -## This rule will be called only by the first process issuing the -## above rule to succeed in creating the lock directory, after -## removing the actual stamp file in order to guarantee that MAKE will -## execute this rule. -## -## Call SWIG to generate the various output files; special -## post-processing on 'mingw32' host OS for the dependency file. -## - if $(SWIG) $(STD_SWIG_PYTHON_ARGS) $(trellis_swig_args) \ - -MD -MF $(DEPDIR)/trellis.Std \ - -module trellis -o trellis.cc $(WHAT); then \ - if test $(host_os) = mingw32; then \ - $(RM) $(DEPDIR)/trellis.Sd; \ - $(SED) 's,\\\\,/,g' < $(DEPDIR)/trellis.Std \ - > $(DEPDIR)/trellis.Sd; \ - $(RM) $(DEPDIR)/trellis.Std; \ - $(MV) $(DEPDIR)/trellis.Sd $(DEPDIR)/trellis.Std; \ - fi; \ - else \ - $(RM) $(DEPDIR)/trellis.S*; exit 1; \ - fi; -## -## Mess with the SWIG output .Std dependency file, to create a -## dependecy file valid for the input .i file: Basically, simulate the -## dependency file created for libraries by GNU's libtool for C++, -## where all of the dependencies for the target are first listed, then -## each individual dependency is listed as a target with no further -## dependencies. -## -## (1) remove the current dependency file -## - $(RM) $(DEPDIR)/trellis.d -## -## (2) Copy the whole SWIG file: -## - cp $(DEPDIR)/trellis.Std $(DEPDIR)/trellis.d -## -## (3) all a carriage return to the end of the dependency file. -## - echo "" >> $(DEPDIR)/trellis.d -## -## (4) from the SWIG file, remove the first line (the target); remove -## trailing " \" and " " from each line. Append ":" to each line, -## followed by 2 carriage returns, then append this to the end of -## the dependency file. -## - $(SED) -e '1d;s, \\,,g;s, ,,g' < $(DEPDIR)/trellis.Std | \ - awk '{ printf "%s:\n\n", $$0 }' >> $(DEPDIR)/trellis.d -## -## (5) remove the SWIG-generated file -## - $(RM) $(DEPDIR)/trellis.Std -## -## Create the stamp for this filename generation, to signal success in -## executing this rule; allows other threads waiting on this process -## to continue. -## - touch $(DEPDIR)/trellis-generate-stamp +if GUILE + +trellis_scmlib_LTLIBRARIES = \ + libguile-gnuradio-trellis.la +libguile_gnuradio_trellis_la_SOURCES = \ + guile/trellis.cc \ + $(trellis_la_swig_sources) +nobase_trellis_scm_DATA = \ + gnuradio/trellis.scm \ + gnuradio/trellis-primitive.scm +libguile_gnuradio_trellis_la_LIBADD = \ + $(STD_SWIG_LA_LIB_ADD) \ + $(trellis_la_swig_libadd) +libguile_gnuradio_trellis_la_LDFLAGS = \ + $(STD_SWIG_LA_LD_FLAGS) \ + $(trellis_la_swig_ldflags) +libguile_gnuradio_trellis_la_CXXFLAGS = \ + $(STD_SWIG_CXX_FLAGS) \ + -I$(top_builddir) \ + $(trellis_la_swig_cxxflags) + +guile/trellis.cc: gnuradio/trellis.scm +gnuradio/trellis.scm: trellis.i +gnuradio/trellis-primitive.scm: gnuradio/trellis.scm + +# Include the guile dependencies for this file +-include guile/trellis.d -# KLUDGE: Force runtime include of a SWIG dependency file. This is -# not guaranteed to be portable, but will probably work. If it works, -# we have accurate dependencies for our swig stuff, which is good. +endif # end of GUILE -@am__include@ @am__quote@./$(DEPDIR)/trellis.d@am__quote@ diff --git a/gr-trellis/src/lib/trellis_calc_metric.cc b/gr-trellis/src/lib/calc_metric.cc index 0d03fd1a7..0e8f9c2d5 100644 --- a/gr-trellis/src/lib/trellis_calc_metric.cc +++ b/gr-trellis/src/lib/calc_metric.cc @@ -22,7 +22,7 @@ #include <float.h> #include <stdexcept> -#include "trellis_calc_metric.h" +#include "calc_metric.h" diff --git a/gr-trellis/src/lib/trellis_calc_metric.h b/gr-trellis/src/lib/calc_metric.h index fabf4e145..fd20f8d36 100644 --- a/gr-trellis/src/lib/trellis_calc_metric.h +++ b/gr-trellis/src/lib/calc_metric.h @@ -20,12 +20,12 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_TRELLIS_CALC_METRIC_H -#define INCLUDED_TRELLIS_CALC_METRIC_H +#ifndef INCLUDED_CALC_METRIC_H +#define INCLUDED_CALC_METRIC_H #include <vector> #include <gr_complex.h> -#include <trellis_metric_type.h> +#include <digital_metric_type.h> template <class T> diff --git a/gr-trellis/src/lib/core_algorithms.cc b/gr-trellis/src/lib/core_algorithms.cc new file mode 100644 index 000000000..91ac8fbdf --- /dev/null +++ b/gr-trellis/src/lib/core_algorithms.cc @@ -0,0 +1,1239 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <cstring> +#include <stdexcept> +//#include <cstdio> +#include <iostream> +#include "core_algorithms.h" +#include "calc_metric.h" + +static const float INF = 1.0e9; + +float min(float a, float b) +{ + return a <= b ? a : b; +} + +float min_star(float a, float b) +{ + return (a <= b ? a : b)-log(1+exp(a <= b ? a-b : b-a)); +} + + + + +template <class T> +void viterbi_algorithm(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + const float *in, T *out)//, + //std::vector<int> &trace) +{ + std::vector<int> trace(S*K); + std::vector<float> alpha(S*2); + int alphai; + float norm,mm,minm; + int minmi; + int st; + + + 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; + } + + alphai=0; + for(int k=0;k<K;k++) { + norm=INF; + for(int j=0;j<S;j++) { // for each next state do ACS + minm=INF; + minmi=0; + for(unsigned int i=0;i<PS[j].size();i++) { + //int i0 = j*I+i; + if((mm=alpha[alphai*S+PS[j][i]]+in[k*O+OS[PS[j][i]*I+PI[j][i]]])<minm) + minm=mm,minmi=i; + } + trace[k*S+j]=minmi; + alpha[((alphai+1)%2)*S+j]=minm; + if(minm<norm) norm=minm; + } + for(int j=0;j<S;j++) + alpha[((alphai+1)%2)*S+j]-=norm; // normalize total metrics so they do not explode + alphai=(alphai+1)%2; + } + + if(SK<0) { // final state not specified + minm=INF; + minmi=0; + for(int i=0;i<S;i++) + if((mm=alpha[alphai*S+i])<minm) minm=mm,minmi=i; + st=minmi; + } + else { + st=SK; + } + + for(int k=K-1;k>=0;k--) { // traceback + int i0=trace[k*S+st]; + out[k]= (T) PI[st][i0]; + st=PS[st][i0]; + } + +} + + +template +void viterbi_algorithm<unsigned char>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + const float *in, unsigned char *out); + + +template +void viterbi_algorithm<short>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + const float *in, short *out); + +template +void viterbi_algorithm<int>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + const float *in, int *out); + + + +//============================================== + +template <class Ti, class To> +void viterbi_algorithm_combined(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<Ti> &TABLE, + trellis_metric_type_t TYPE, + const Ti *in, To *out +) +{ + std::vector<int> trace(S*K); + std::vector<float> alpha(S*2); + float *metric = new float[O]; + int alphai; + float norm,mm,minm; + int minmi; + int st; + + 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; + } + + alphai=0; + for(int k=0;k<K;k++) { + calc_metric(O, D, TABLE, &(in[k*D]), metric,TYPE); // calc metrics + norm=INF; + for(int j=0;j<S;j++) { // for each next state do ACS + minm=INF; + minmi=0; + for(unsigned int i=0;i<PS[j].size();i++) { + //int i0 = j*I+i; + if((mm=alpha[alphai*S+PS[j][i]]+metric[OS[PS[j][i]*I+PI[j][i]]])<minm) + minm=mm,minmi=i; + } + trace[k*S+j]=minmi; + alpha[((alphai+1)%2)*S+j]=minm; + if(minm<norm) norm=minm; + } + for(int j=0;j<S;j++) + alpha[((alphai+1)%2)*S+j]-=norm; // normalize total metrics so they do not explode + alphai=(alphai+1)%2; + } + + if(SK<0) { // final state not specified + minm=INF; + minmi=0; + for(int i=0;i<S;i++) + if((mm=alpha[alphai*S+i])<minm) minm=mm,minmi=i; + st=minmi; + } + else { + st=SK; + } + + for(int k=K-1;k>=0;k--) { // traceback + int i0=trace[k*S+st]; + out[k]= (To) PI[st][i0]; + st=PS[st][i0]; + } + + delete [] metric; + +} + +// Ti = s i f c +// To = b s i + +//--------------- + +template +void viterbi_algorithm_combined<short,unsigned char>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<short> &TABLE, + trellis_metric_type_t TYPE, + const short *in, unsigned char *out +); + +template +void viterbi_algorithm_combined<int,unsigned char>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<int> &TABLE, + trellis_metric_type_t TYPE, + const int *in, unsigned char *out +); + +template +void viterbi_algorithm_combined<float,unsigned char>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<float> &TABLE, + trellis_metric_type_t TYPE, + const float *in, unsigned char *out +); + +template +void viterbi_algorithm_combined<gr_complex,unsigned char>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<gr_complex> &TABLE, + trellis_metric_type_t TYPE, + const gr_complex *in, unsigned char *out +); + +//--------------- + +template +void viterbi_algorithm_combined<short,short>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<short> &TABLE, + trellis_metric_type_t TYPE, + const short *in, short *out +); + +template +void viterbi_algorithm_combined<int,short>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<int> &TABLE, + trellis_metric_type_t TYPE, + const int *in, short *out +); + +template +void viterbi_algorithm_combined<float,short>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<float> &TABLE, + trellis_metric_type_t TYPE, + const float *in, short *out +); + +template +void viterbi_algorithm_combined<gr_complex,short>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<gr_complex> &TABLE, + trellis_metric_type_t TYPE, + const gr_complex *in, short *out +); + +//-------------- + +template +void viterbi_algorithm_combined<short,int>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<short> &TABLE, + trellis_metric_type_t TYPE, + const short *in, int *out +); + +template +void viterbi_algorithm_combined<int,int>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<int> &TABLE, + trellis_metric_type_t TYPE, + const int *in, int *out +); + +template +void viterbi_algorithm_combined<float,int>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<float> &TABLE, + trellis_metric_type_t TYPE, + const float *in, int *out +); + +template +void viterbi_algorithm_combined<gr_complex,int>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<gr_complex> &TABLE, + trellis_metric_type_t TYPE, + const gr_complex *in, int *out +); + + + + + + + + + + + + + + + + + + + + +//=============================================== + + +void siso_algorithm(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< 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; + std::vector<float> alpha(S*(K+1)); + std::vector<float> beta(S*(K+1)); + + + 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(unsigned int i=0;i<PS[j].size();i++) { + //int i0 = j*I+i; + mm=alpha[k*S+PS[j][i]]+priori[k*I+PI[j][i]]+prioro[k*O+OS[PS[j][i]*I+PI[j][i]]]; + 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."); + +} + + +//=========================================================== + +template <class T> +void siso_algorithm_combined(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + bool POSTI, bool POSTO, + float (*p2mymin)(float,float), + int D, + const std::vector<T> &TABLE, + trellis_metric_type_t TYPE, + const float *priori, const T *observations, float *post +) +{ + float norm,mm,minm; + std::vector<float> alpha(S*(K+1)); + std::vector<float> beta(S*(K+1)); + float *prioro = new float[O*K]; + + + 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 + calc_metric(O, D, TABLE, &(observations[k*D]), &(prioro[k*O]),TYPE); // calc metrics + norm=INF; + for(int j=0;j<S;j++) { + minm=INF; + for(unsigned int i=0;i<PS[j].size();i++) { + //int i0 = j*I+i; + mm=alpha[k*S+PS[j][i]]+priori[k*I+PI[j][i]]+prioro[k*O+OS[PS[j][i]*I+PI[j][i]]]; + 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."); + + delete [] prioro; + +} + +//--------- + +template +void siso_algorithm_combined<short>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + bool POSTI, bool POSTO, + float (*p2mymin)(float,float), + int D, + const std::vector<short> &TABLE, + trellis_metric_type_t TYPE, + const float *priori, const short *observations, float *post +); + +template +void siso_algorithm_combined<int>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + bool POSTI, bool POSTO, + float (*p2mymin)(float,float), + int D, + const std::vector<int> &TABLE, + trellis_metric_type_t TYPE, + const float *priori, const int *observations, float *post +); + +template +void siso_algorithm_combined<float>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + bool POSTI, bool POSTO, + float (*p2mymin)(float,float), + int D, + const std::vector<float> &TABLE, + trellis_metric_type_t TYPE, + const float *priori, const float *observations, float *post +); + +template +void siso_algorithm_combined<gr_complex>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + bool POSTI, bool POSTO, + float (*p2mymin)(float,float), + int D, + const std::vector<gr_complex> &TABLE, + trellis_metric_type_t TYPE, + const float *priori, const gr_complex *observations, float *post +); + +//========================================================= + +template<class Ti, class To> +void sccc_decoder_combined( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, int repetitions, + float (*p2mymin)(float,float), + int D, const std::vector<Ti> &TABLE, + trellis_metric_type_t METRIC_TYPE, + float scaling, + const Ti *observations, To *data +) +{ + +//allocate space for priori, prioro and posti of inner FSM +std::vector<float> ipriori(blocklength*FSMi.I(),0.0); +std::vector<float> iprioro(blocklength*FSMi.O()); +std::vector<float> iposti(blocklength*FSMi.I()); + +//allocate space for priori, prioro and posto of outer FSM +std::vector<float> opriori(blocklength*FSMo.I(),0.0); +std::vector<float> oprioro(blocklength*FSMo.O()); +std::vector<float> oposti(blocklength*FSMo.I()); +std::vector<float> oposto(blocklength*FSMo.O()); + +// turn observations to neg-log-priors +for(int k=0;k<blocklength;k++) { + calc_metric(FSMi.O(), D, TABLE, &(observations[k*D]), &(iprioro[k*FSMi.O()]),METRIC_TYPE); + iprioro[k*FSMi.O()] *= scaling; +} + +for(int rep=0;rep<repetitions;rep++) { + // run inner SISO + siso_algorithm(FSMi.I(),FSMi.S(),FSMi.O(), + FSMi.NS(), FSMi.OS(), FSMi.PS(), FSMi.PI(), + blocklength, + STi0,STiK, + true, false, + p2mymin, + &(ipriori[0]), &(iprioro[0]), &(iposti[0]) + ); + + //interleave soft info inner -> outer + for(int k=0;k<blocklength;k++) { + int ki = INTERLEAVER.DEINTER()[k]; + //for(int i=0;i<FSMi.I();i++) { + //oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i]; + //} + memcpy(&(oprioro[k*FSMi.I()]),&(iposti[ki*FSMi.I()]),FSMi.I()*sizeof(float)); + } + + // run outer SISO + + if(rep<repetitions-1) { // do not produce posti + siso_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), + FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), + blocklength, + STo0,SToK, + false, true, + p2mymin, + &(opriori[0]), &(oprioro[0]), &(oposto[0]) + ); + + //interleave soft info outer --> inner + for(int k=0;k<blocklength;k++) { + int ki = INTERLEAVER.DEINTER()[k]; + //for(int i=0;i<FSMi.I();i++) { + //ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i]; + //} + memcpy(&(ipriori[ki*FSMi.I()]),&(oposto[k*FSMi.I()]),FSMi.I()*sizeof(float)); + } + } + else // produce posti but not posto + + siso_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), + FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), + blocklength, + STo0,SToK, + true, false, + p2mymin, + &(opriori[0]), &(oprioro[0]), &(oposti[0]) + ); + + /* + viterbi_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), + FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), + blocklength, + STo0,SToK, + &(oprioro[0]), data + ); + */ + +} + + +// generate hard decisions +for(int k=0;k<blocklength;k++) { + float min=INF; + int mini=0; + for(int i=0;i<FSMo.I();i++) { + if(oposti[k*FSMo.I()+i]<min) { + min=oposti[k*FSMo.I()+i]; + mini=i; + } + } + data[k]=(To)mini; +} + + + +} + +//------- + +template +void sccc_decoder_combined<float,unsigned char>( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, int repetitions, + float (*p2mymin)(float,float), + int D, const std::vector<float> &TABLE, + trellis_metric_type_t METRIC_TYPE, + float scaling, + const float *observations, unsigned char *data +); + +template +void sccc_decoder_combined<float,short>( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, int repetitions, + float (*p2mymin)(float,float), + int D, const std::vector<float> &TABLE, + trellis_metric_type_t METRIC_TYPE, + float scaling, + const float *observations, short *data +); + +template +void sccc_decoder_combined<float,int>( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, int repetitions, + float (*p2mymin)(float,float), + int D, const std::vector<float> &TABLE, + trellis_metric_type_t METRIC_TYPE, + float scaling, + const float *observations, int *data +); + +template +void sccc_decoder_combined<gr_complex,unsigned char>( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, int repetitions, + float (*p2mymin)(float,float), + int D, const std::vector<gr_complex> &TABLE, + trellis_metric_type_t METRIC_TYPE, + float scaling, + const gr_complex *observations, unsigned char *data +); + +template +void sccc_decoder_combined<gr_complex,short>( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, int repetitions, + float (*p2mymin)(float,float), + int D, const std::vector<gr_complex> &TABLE, + trellis_metric_type_t METRIC_TYPE, + float scaling, + const gr_complex *observations, short *data +); + +template +void sccc_decoder_combined<gr_complex,int>( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, int repetitions, + float (*p2mymin)(float,float), + int D, const std::vector<gr_complex> &TABLE, + trellis_metric_type_t METRIC_TYPE, + float scaling, + const gr_complex *observations, int *data +); + + + +//========================================================= + +template<class T> +void sccc_decoder( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, int repetitions, + float (*p2mymin)(float,float), + const float *iprioro, T *data +) +{ + //allocate space for priori, and posti of inner FSM + std::vector<float> ipriori(blocklength*FSMi.I(),0.0); + std::vector<float> iposti(blocklength*FSMi.I()); + + //allocate space for priori, prioro and posto of outer FSM + std::vector<float> opriori(blocklength*FSMo.I(),0.0); + std::vector<float> oprioro(blocklength*FSMo.O()); + std::vector<float> oposti(blocklength*FSMo.I()); + std::vector<float> oposto(blocklength*FSMo.O()); + + for(int rep=0;rep<repetitions;rep++) { + // run inner SISO + siso_algorithm(FSMi.I(),FSMi.S(),FSMi.O(), + FSMi.NS(), FSMi.OS(), FSMi.PS(), FSMi.PI(), + blocklength, + STi0,STiK, + true, false, + p2mymin, + &(ipriori[0]), &(iprioro[0]), &(iposti[0]) + ); + + //interleave soft info inner -> outer + for(int k=0;k<blocklength;k++) { + int ki = INTERLEAVER.DEINTER()[k]; + //for(int i=0;i<FSMi.I();i++) { + //oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i]; + //} + memcpy(&(oprioro[k*FSMi.I()]),&(iposti[ki*FSMi.I()]),FSMi.I()*sizeof(float)); + } + + // run outer SISO + + if(rep<repetitions-1) { // do not produce posti + siso_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), + FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), + blocklength, + STo0,SToK, + false, true, + p2mymin, + &(opriori[0]), &(oprioro[0]), &(oposto[0]) + ); + + //interleave soft info outer --> inner + for(int k=0;k<blocklength;k++) { + int ki = INTERLEAVER.DEINTER()[k]; + //for(int i=0;i<FSMi.I();i++) { + //ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i]; + //} + memcpy(&(ipriori[ki*FSMi.I()]),&(oposto[k*FSMi.I()]),FSMi.I()*sizeof(float)); + } + } + else {// produce posti but not posto + + siso_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), + FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), + blocklength, + STo0,SToK, + true, false, + p2mymin, + &(opriori[0]), &(oprioro[0]), &(oposti[0]) + ); + + /* + viterbi_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), + FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), + blocklength, + STo0,SToK, + &(oprioro[0]), data + ); + */ + } + + } // end repetitions + + // generate hard decisions + for(int k=0;k<blocklength;k++) { + float min=INF; + int mini=0; + for(int i=0;i<FSMo.I();i++) { + if(oposti[k*FSMo.I()+i]<min) { + min=oposti[k*FSMo.I()+i]; + mini=i; + } + } + data[k]=(T)mini; + } + + + +} + +//------- + +template +void sccc_decoder<unsigned char>( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, int repetitions, + float (*p2mymin)(float,float), + const float *iprioro, unsigned char *data +); + +template +void sccc_decoder<short>( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, int repetitions, + float (*p2mymin)(float,float), + const float *iprioro, short *data +); + +template +void sccc_decoder<int>( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, int repetitions, + float (*p2mymin)(float,float), + const float *iprioro, int *data +); + + +//==================================================== + +template<class T> +void pccc_decoder( + const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, int blocklength, int repetitions, + float (*p2mymin)(float,float), + const float *cprioro, T *data +) +{ + + //allocate space for priori, prioro and posti of FSM1 + std::vector<float> priori1(blocklength*FSM1.I(),0.0); + std::vector<float> prioro1(blocklength*FSM1.O()); + std::vector<float> posti1(blocklength*FSM1.I()); + + //allocate space for priori, prioro and posti of FSM2 + std::vector<float> priori2(blocklength*FSM2.I(),0.0); + std::vector<float> prioro2(blocklength*FSM2.O()); + std::vector<float> posti2(blocklength*FSM2.I()); + + //generate prioro1,2 (metrics are not updated per iteration: this is not the best you can do...) + for (int k=0;k<blocklength;k++) { + //std::cout << k << std::endl; + for(int i=0;i<FSM1.O();i++) { + float x=cprioro[k*FSM1.O()*FSM2.O()+i*FSM1.O()+0]; + for(int j=1;j<FSM2.O();j++) + x = (*p2mymin)(x,cprioro[k*FSM1.O()*FSM2.O()+i*FSM1.O()+j]); + prioro1[k*FSM1.O()+i]=x; + //std::cout << prioro1[k*FSM1.O()+i] << ", "; + } + //std::cout << std::endl; + for(int i=0;i<FSM2.O();i++) { + float x=cprioro[k*FSM1.O()*FSM2.O()+0*FSM1.O()+i]; + for(int j=1;j<FSM1.O();j++) + x = (*p2mymin)(x,cprioro[k*FSM1.O()*FSM2.O()+j*FSM1.O()+i]); + prioro2[k*FSM2.O()+i]=x; + } + } + + for(int rep=0;rep<repetitions;rep++) { + // run SISO 1 + siso_algorithm(FSM1.I(),FSM1.S(),FSM1.O(), + FSM1.NS(), FSM1.OS(), FSM1.PS(), FSM1.PI(), + blocklength, + ST10,ST1K, + true, false, + p2mymin, + &(priori1[0]), &(prioro1[0]), &(posti1[0]) + ); + + //for(int k=0;k<blocklength;k++){ + //for(int i=0;i<FSM1.I();i++) + //std::cout << posti1[k*FSM1.I()+i] << ", "; + //std::cout << std::endl; + //} + + //interleave soft info 1 -> 2 + for(int k=0;k<blocklength;k++) { + int ki = INTERLEAVER.INTER()[k]; + //for(int i=0;i<FSMi.I();i++) { + //oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i]; + //} + memcpy(&(priori2[k*FSM2.I()]),&(posti1[ki*FSM1.I()]),FSM1.I()*sizeof(float)); + } + + // run SISO 2 + siso_algorithm(FSM2.I(),FSM2.S(),FSM2.O(), + FSM2.NS(), FSM2.OS(), FSM2.PS(), FSM2.PI(), + blocklength, + ST20,ST2K, + true, false, + p2mymin, + &(priori2[0]), &(prioro2[0]), &(posti2[0]) + ); + + //interleave soft info 2 --> 1 + for(int k=0;k<blocklength;k++) { + int ki = INTERLEAVER.INTER()[k]; + //for(int i=0;i<FSMi.I();i++) { + //ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i]; + //} + memcpy(&(priori1[ki*FSM1.I()]),&(posti2[k*FSM2.I()]),FSM1.I()*sizeof(float)); + } + + } // end repetitions + + // generate hard decisions + for(int k=0;k<blocklength;k++) { + for(int i=0;i<FSM1.I();i++) + posti1[k*FSM1.I()+i] = (*p2mymin)(priori1[k*FSM1.I()+i],posti1[k*FSM1.I()+i]); + float min=INF; + int mini=0; + for(int i=0;i<FSM1.I();i++) { + if(posti1[k*FSM1.I()+i]<min) { + min=posti1[k*FSM1.I()+i]; + mini=i; + } + } + data[k]=(T)mini; + //std::cout << data[k] << ", "<< std::endl; + } + //std::cout << std::endl; + + + +} + +//---------------- + +template +void pccc_decoder<unsigned char>( + const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, int blocklength, int repetitions, + float (*p2mymin)(float,float), + const float *cprioro, unsigned char *data +); + +template +void pccc_decoder<short>( + const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, int blocklength, int repetitions, + float (*p2mymin)(float,float), + const float *cprioro, short *data +); + +template +void pccc_decoder<int>( + const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, int blocklength, int repetitions, + float (*p2mymin)(float,float), + const float *cprioro, int *data +); + diff --git a/gr-trellis/src/lib/core_algorithms.h b/gr-trellis/src/lib/core_algorithms.h new file mode 100644 index 000000000..fd45844c0 --- /dev/null +++ b/gr-trellis/src/lib/core_algorithms.h @@ -0,0 +1,128 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_CORE_ALGORITHMS_H +#define INCLUDED_CORE_ALGORITHMS_H + +#include <cmath> +#include <vector> +//#include <gr_complex.h> +#include "digital_metric_type.h" +#include "fsm.h" +#include "interleaver.h" + + +float min(float a, float b); +float min_star(float a, float b); + +template <class T> +void viterbi_algorithm(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + const float *in, T *out +); + +template <class Ti, class To> +void viterbi_algorithm_combined(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<Ti> &TABLE, + trellis_metric_type_t TYPE, + const Ti *in, To *out +); + + + +void siso_algorithm(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< 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 +); + + +template <class T> +void siso_algorithm_combined(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + bool POSTI, bool POSTO, + float (*p2mymin)(float,float), + int D, + const std::vector<T> &TABLE, + trellis_metric_type_t TYPE, + const float *priori, const T *observations, float *post +); + + +template<class Ti, class To> +void sccc_decoder_combined( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, int repetitions, + float (*p2mymin)(float,float), + int D, const std::vector<Ti> &TABLE, + trellis_metric_type_t METRIC_TYPE, + float scaling, + const Ti *observations, To *data +); + + +template<class T> +void sccc_decoder( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, int repetitions, + float (*p2mymin)(float,float), + const float *iprioro, T *data +); + + +template<class T> +void pccc_decoder( + const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, int blocklength, int repetitions, + float (*p2mymin)(float,float), + const float *cprioro, T *data +); + + + +#endif diff --git a/gr-trellis/src/lib/fsm.cc b/gr-trellis/src/lib/fsm.cc index 5950b56b9..889a3918b 100644 --- a/gr-trellis/src/lib/fsm.cc +++ b/gr-trellis/src/lib/fsm.cc @@ -417,7 +417,7 @@ void fsm::generate_TM() done = find_es(s); attempts ++; } - if (done == false) { + if (done == false and d_S > 1) { //throw std::runtime_error ("fsm::generate_TM(): FSM appears to be disconnected\n"); printf("fsm::generate_TM(): FSM appears to be disconnected\n"); printf("state %d cannot be reached from all other states\n",s); diff --git a/gr-trellis/src/lib/fsm.h b/gr-trellis/src/lib/fsm.h index 0a90b2cd3..8bae91754 100644 --- a/gr-trellis/src/lib/fsm.h +++ b/gr-trellis/src/lib/fsm.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2002 Free Software Foundation, Inc. + * Copyright 2002,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -27,31 +27,114 @@ #include <iosfwd> /*! - * \brief FSM class + * \brief Finite State Machine Specification class. + * + * An instance of this class represents a finite state machine specification (FSMS) + * rather than the FSM itself. It particular the state of the FSM + * is not stored within an instance of this class. */ class fsm { private: + // Input alphabet cardinality. int d_I; + // Number of states. int d_S; + // Output alphabet cardinality. int d_O; + // NS means Next State. + // next_state = d_NS[current_state * d_I + input_symbol] std::vector<int> d_NS; + // OS means Output Symbol. + // output_symbol = d_OS[current_state * d_I + input_symbol] std::vector<int> d_OS; + // PS means Previous State. std::vector< std::vector<int> > d_PS; + // PI means Previous Input Symbol. + // d_PS[current_state][k] and d_PI[current_state][k], is a pair of the form + // (previous_state, previous_input_symbol) that could have produced the + // current state. std::vector< std::vector<int> > d_PI; - std::vector<int> d_TMi; + // TM means Termination matrix. + // d_TMl[s*d_S+es] is the shortest number of steps to get from state s to + // state es. std::vector<int> d_TMl; + // d_TMi[s*d_S+es] is the input symbol required to set off on the shortest + // path from state s to es. + std::vector<int> d_TMi; void generate_PS_PI (); void generate_TM (); bool find_es(int es); public: + /*! + * \brief Constructor to create an uninitialized FSMS. + */ fsm(); + /*! + * \brief Constructor to copy an FSMS. + */ fsm(const fsm &FSM); + /*! + * \brief Constructor to to create an FSMS. + * + * \param I The number of possible input symbols. + * \param S The number of possible FSM states. + * \param O The number of possible output symbols. + * \param NS A mapping from (current state, input symbol) to next state. + * next_state = NS[current_state * I + input_symbol] + * \param OS A mapping from (current state, input symbol) to output symbol. + * output_symbol = OS[current_state * I + input_symbol] + * + */ fsm(int I, int S, int O, const std::vector<int> &NS, const std::vector<int> &OS); + /*! + * \brief Constructor to create an FSMS from file contents. + * + * \param name filename + * + */ fsm(const char *name); + /*! + * \brief Creates an FSMS from the generator matrix of a (n, k) binary convolutional code. + * + * \param k ??? + * \param n ??? + * \param G ??? + * + */ fsm(int k, int n, const std::vector<int> &G); + /*! + * \brief Creates an FSMS describing ISI. + * + * \param mod_size modulation size + * \param ch_lenth channel length + * + */ fsm(int mod_size, int ch_length); + /*! + * \brief Creates an FSMS describing the trellis for a CPM. + * + * \param P ???? h=K/P (relatively prime) + * \param M alphabet size + * \param L pulse duration + * + * This FSM is based on the paper by B. Rimoldi + * "A decomposition approach to CPM", IEEE Trans. Info Theory, March 1988 + * See also my own notes at http://www.eecs.umich.edu/~anastas/docs/cpm.pdf + */ fsm(int P, int M, int L); + /*! + * \brief Creates an FSMS describing the joint trellis of two FSMs. + * + * \param fsm1 first FSMS + * \param fsm2 second FSMS + */ fsm(const fsm &FSM1, const fsm &FSM2); + /*! + * \brief Creates an FSMS representing n stages through the originial FSM (AKA radix-n FSM). + * + * \param original FSMS + * \param n Number of stages. + */ fsm(const fsm &FSM, int n); int I () const { return d_I; } int S () const { return d_S; } @@ -62,7 +145,20 @@ public: const std::vector< 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; } + /*! + * \brief Creates an svg image of the trellis representation. + * + * \param filename filename + * \param number_stages ???? + * + */ void write_trellis_svg(std::string filename ,int number_stages); + /*! + * \brief Write the FSMS to a file. + * + * \param filename filename + * + */ void write_fsm_txt(std::string filename); }; diff --git a/gr-trellis/src/lib/generate_trellis.py b/gr-trellis/src/lib/generate_trellis.py index a4206d268..9f845f74a 100644 --- a/gr-trellis/src/lib/generate_trellis.py +++ b/gr-trellis/src/lib/generate_trellis.py @@ -28,16 +28,26 @@ import re other_roots = [ 'trellis_encoder_XX', + 'trellis_sccc_encoder_XX', + 'trellis_pccc_encoder_XX', 'trellis_metrics_X', 'trellis_viterbi_X', 'trellis_viterbi_combined_XX', + 'trellis_sccc_decoder_combined_XX', + 'trellis_sccc_decoder_X', + 'trellis_pccc_decoder_X', ] other_signatures = ( ['bb','bs','bi','ss','si','ii'], + ['bb','bs','bi','ss','si','ii'], + ['bb','bs','bi','ss','si','ii'], ['s','i','f','c'], ['b','s','i'], ['sb','ss','si','ib','is','ii','fb','fs','fi','cb','cs','ci'], + ['fb','fs','fi','cb','cs','ci'], + ['b','s','i'], + ['b','s','i'], ) diff --git a/gr-trellis/src/lib/interleaver.cc b/gr-trellis/src/lib/interleaver.cc index ff15eeadc..131dcb07b 100644 --- a/gr-trellis/src/lib/interleaver.cc +++ b/gr-trellis/src/lib/interleaver.cc @@ -124,7 +124,7 @@ interleaver::interleaver(int K, int seed) //###################################################################### -//# Write an INTERLEAVER specification from a file. +//# Write an INTERLEAVER specification to a file. //# Format //# K //# blank line diff --git a/gr-trellis/src/lib/run_guile_tests.in b/gr-trellis/src/lib/run_guile_tests.in new file mode 100644 index 000000000..5d08b0dd5 --- /dev/null +++ b/gr-trellis/src/lib/run_guile_tests.in @@ -0,0 +1,14 @@ +#!/bin/sh + +. @top_builddir@/setup_guile_test_env + +# 1st argument is absolute path to hand coded guile source directory +# 2nd argument is absolute path to component C++ shared library build directory +# 3nd argument is absolute path to component SWIG build directory + +add_local_paths \ + @srcdir@ \ + @abs_builddir@ \ + @abs_builddir@ + +@GUILE@ -e main -c '(use-modules (gnuradio test-suite guile-test))' -t @srcdir@ diff --git a/gr-trellis/src/lib/trellis_siso_type.h b/gr-trellis/src/lib/siso_type.h index 3a7163d02..3a7163d02 100644 --- a/gr-trellis/src/lib/trellis_siso_type.h +++ b/gr-trellis/src/lib/siso_type.h diff --git a/gr-trellis/src/lib/trellis.i b/gr-trellis/src/lib/trellis.i index ed1fe29ca..d01ab529a 100644 --- a/gr-trellis/src/lib/trellis.i +++ b/gr-trellis/src/lib/trellis.i @@ -28,8 +28,11 @@ #include "trellis_permutation.h" #include "trellis_siso_f.h" #include "trellis_siso_combined_f.h" +#include "trellis_constellation_metrics_cf.h" +#include "digital_constellation.h" %} + // ---------------------------------------------------------------- %include "fsm.i" @@ -38,9 +41,25 @@ %include "trellis_siso_f.i" %include "trellis_siso_combined_f.i" -%include "trellis_metric_type.h" -%include "trellis_siso_type.h" +%include "siso_type.h" +%include "trellis_constellation_metrics_cf.i" %include "trellis_generated.i" +%import "digital_metric_type.h" +%import "digital_constellation.i" + + //%pythoncode %{ + // from gnuradio.gr import TRELLIS_EUCLIDEAN, TRELLIS_HARD_SYMBOL, TRELLIS_HARD_BIT + // %} + +#if SWIGGUILE +%scheme %{ +(load-extension-global "libguile-gnuradio-trellis" "scm_init_gnuradio_trellis_module") +%} + +%goops %{ +(use-modules (gnuradio gnuradio_core_runtime)) +%} +#endif diff --git a/gr-trellis/src/lib/trellis.test b/gr-trellis/src/lib/trellis.test new file mode 100644 index 000000000..d370ab18c --- /dev/null +++ b/gr-trellis/src/lib/trellis.test @@ -0,0 +1,53 @@ +;;; -*- Scheme -*- +;;; +;;; Copyright 2010 Free Software Foundation, Inc. +;;; +;;; This file is part of GNU Radio +;;; +;;; GNU Radio is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3, or (at your option) +;;; any later version. +;;; +;;; GNU Radio is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;; + +;;; If you're using Emacs's Scheme mode: +;;; (put 'with-test-prefix 'scheme-indent-function 1) + +;;; See the comments in gnuradio/test-suite/lib.scm for info on writing tests. +;;; See also the very end of the file, where the test-equal, test-eqv +;;; and test-eq macros are defined. + +(define-module (test-module) + #:use-module (oop goops) + #:use-module (gnuradio core) + #:use-module (gnuradio test-suite lib) + #:duplicates (merge-generics replace check)) + + +;;; See if we can import the module... +(use-modules (gnuradio trellis)) + +;;; Now do some real testing, like that in ../python/qa_trellis.py +;;; FIXME later. Other problems to deal with. Looks like +;;; I don't understand the constructor to <fsm> + +(read-set! keywords 'prefix) + +'(with-test-prefix "test-001-fsm" + (let* ((I 2) + (S 4) + (O 4) + (NS #(0 2 0 2 1 3 1 3)) + (OS #(0 3 3 0 1 2 2 1)) + (f (make <fsm> :I I :S S :O O :NS NS :OS OS))) + (test-equal (list I S O NS OS) + (list (gr:I f) (gr:S f) (gr:O f) (gr:NS f) (gr:OS f))))) + diff --git a/gr-trellis/src/lib/trellis_constellation_metrics_cf.cc b/gr-trellis/src/lib/trellis_constellation_metrics_cf.cc new file mode 100644 index 000000000..1d03886f1 --- /dev/null +++ b/gr-trellis/src/lib/trellis_constellation_metrics_cf.cc @@ -0,0 +1,92 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// WARNING: this file is machine generated. Edits will be over written + +#ifndef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <trellis_constellation_metrics_cf.h> +#include <gr_io_signature.h> +#include <assert.h> +#include <stdexcept> +#include <iostream> + + + +trellis_constellation_metrics_cf_sptr +trellis_make_constellation_metrics_cf (digital_constellation_sptr constellation, trellis_metric_type_t TYPE) +{ + return gnuradio::get_initial_sptr (new trellis_constellation_metrics_cf (constellation, TYPE)); +} + + + +trellis_constellation_metrics_cf::trellis_constellation_metrics_cf (digital_constellation_sptr constellation, trellis_metric_type_t TYPE) + : gr_block ("constellation_metrics_cf", + gr_make_io_signature (1, -1, sizeof (gr_complex)), + gr_make_io_signature (1, -1, sizeof (float))), + d_constellation (constellation), + d_TYPE (TYPE), + d_O (constellation->arity()), + d_D (constellation->dimensionality()) +{ + set_relative_rate (1.0 * d_O / ((double) d_D)); + set_output_multiple ((int)d_O); +} + +void +trellis_constellation_metrics_cf::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + assert (noutput_items % d_O == 0); + unsigned int input_required = d_D * noutput_items / d_O; + unsigned int ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) + ninput_items_required[i] = input_required; +} + + + +int +trellis_constellation_metrics_cf::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + + assert (noutput_items % d_O == 0); + assert (input_items.size() == output_items.size()); + unsigned int nstreams = input_items.size(); + +for (unsigned int m=0;m<nstreams;m++) { + const gr_complex *in = (gr_complex *) input_items[m]; + float *out = (float *) output_items[m]; + + for (unsigned int i = 0; i < noutput_items / d_O ; i++){ + d_constellation->calc_metric(&(in[i*d_D]), &(out[i*d_O]), d_TYPE); + } +} + + consume_each (d_D * noutput_items / d_O); + return noutput_items; +} diff --git a/gr-trellis/src/lib/trellis_constellation_metrics_cf.h b/gr-trellis/src/lib/trellis_constellation_metrics_cf.h new file mode 100644 index 000000000..a34c335ec --- /dev/null +++ b/gr-trellis/src/lib/trellis_constellation_metrics_cf.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_TRELLIS_CONSTELLATION_METRICS_CF_H +#define INCLUDED_TRELLIS_CONSTELLATION_METRICS_CF_H + +#include <gr_block.h> +#include <digital_constellation.h> +#include <digital_metric_type.h> + +class trellis_constellation_metrics_cf; +typedef boost::shared_ptr<trellis_constellation_metrics_cf> trellis_constellation_metrics_cf_sptr; + +trellis_constellation_metrics_cf_sptr trellis_make_constellation_metrics_cf (digital_constellation_sptr constellation, trellis_metric_type_t TYPE); + +/*! + * \brief Evaluate metrics for use by the Viterbi algorithm. + * \ingroup coding_blk + */ +class trellis_constellation_metrics_cf : public gr_block +{ + public: + 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); + protected: + trellis_constellation_metrics_cf (digital_constellation_sptr constellation, trellis_metric_type_t TYPE); + + private: + digital_constellation_sptr d_constellation; + trellis_metric_type_t d_TYPE; + unsigned int d_O; + unsigned int d_D; + friend trellis_constellation_metrics_cf_sptr trellis_make_constellation_metrics_cf (digital_constellation_sptr constellation, trellis_metric_type_t TYPE); + +}; + + +#endif diff --git a/gr-trellis/src/lib/trellis_metric_type.h b/gr-trellis/src/lib/trellis_constellation_metrics_cf.i index a1040f108..c17522b11 100644 --- a/gr-trellis/src/lib/trellis_metric_type.h +++ b/gr-trellis/src/lib/trellis_constellation_metrics_cf.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2011 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,12 +20,14 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_TRELLIS_METRIC_TYPE_H -#define INCLUDED_TRELLIS_METRIC_TYPE_H +// WARNING: this file is machine generated. Edits will be over written -typedef enum { - TRELLIS_EUCLIDEAN = 200, TRELLIS_HARD_SYMBOL, TRELLIS_HARD_BIT -} trellis_metric_type_t; +GR_SWIG_BLOCK_MAGIC(trellis,constellation_metrics_cf); -#endif +trellis_constellation_metrics_cf_sptr trellis_make_constellation_metrics_cf (digital_constellation_sptr constellation, trellis_metric_type_t TYPE); +class trellis_constellation_metrics_cf : public gr_block +{ +private: + trellis_constellation_metrics_cf (digital_constellation_sptr constellation, trellis_metric_type_t TYPE); +}; diff --git a/gr-trellis/src/lib/trellis_metrics_X.cc.t b/gr-trellis/src/lib/trellis_metrics_X.cc.t index 4bdaabc22..cd66df6fb 100644 --- a/gr-trellis/src/lib/trellis_metrics_X.cc.t +++ b/gr-trellis/src/lib/trellis_metrics_X.cc.t @@ -22,7 +22,7 @@ // @WARNING@ -#ifndef HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H #include "config.h" #endif diff --git a/gr-trellis/src/lib/trellis_metrics_X.h.t b/gr-trellis/src/lib/trellis_metrics_X.h.t index f862a032d..45d4ace10 100644 --- a/gr-trellis/src/lib/trellis_metrics_X.h.t +++ b/gr-trellis/src/lib/trellis_metrics_X.h.t @@ -26,7 +26,7 @@ #define @GUARD_NAME@ #include <gr_block.h> -#include "trellis_calc_metric.h" +#include "calc_metric.h" class @NAME@; typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; diff --git a/gr-trellis/src/lib/trellis_pccc_decoder_X.cc.t b/gr-trellis/src/lib/trellis_pccc_decoder_X.cc.t new file mode 100644 index 000000000..34dd2eb87 --- /dev/null +++ b/gr-trellis/src/lib/trellis_pccc_decoder_X.cc.t @@ -0,0 +1,124 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> +#include <assert.h> +#include <iostream> +#include "core_algorithms.h" + + +static const float INF = 1.0e9; + +@SPTR_NAME@ +trellis_make_@BASE_NAME@ ( + const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE +) +{ + return gnuradio::get_initial_sptr (new @NAME@ ( + FSM1, ST10, ST1K, + FSM2, ST20, ST2K, + INTERLEAVER, + blocklength, + repetitions, + SISO_TYPE + )); +} + +@NAME@::@NAME@ ( + const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE +) + : gr_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_FSM1 (FSM1), d_ST10 (ST10), d_ST1K (ST1K), + d_FSM2 (FSM2), d_ST20 (ST20), d_ST2K (ST2K), + d_INTERLEAVER (INTERLEAVER), + d_blocklength (blocklength), + d_repetitions (repetitions), + d_SISO_TYPE (SISO_TYPE) +{ + assert(d_FSM1.I() == d_FSM2.I()); + set_relative_rate (1.0 / ((double) d_FSM1.O() * d_FSM2.O())); + set_output_multiple (d_blocklength); +} + + +void +@NAME@::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + assert (noutput_items % d_blocklength == 0); + int input_required = d_FSM1.O() * d_FSM2.O() * noutput_items ; + ninput_items_required[0] = input_required; +} + + + +//=========================================================== + +int +@NAME@::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + assert (noutput_items % d_blocklength == 0); + int nblocks = noutput_items / d_blocklength; + + 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; + + + const float *in = (const float *) input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]; + for (int n=0;n<nblocks;n++) { + pccc_decoder( + d_FSM1, d_ST10, d_ST1K, + d_FSM2, d_ST20, d_ST2K, + d_INTERLEAVER, d_blocklength, d_repetitions, + p2min, + &(in[n*d_blocklength*d_FSM1.O()*d_FSM2.O()]),&(out[n*d_blocklength]) + ); + } + + consume_each (d_FSM1.O() * d_FSM2.O() * noutput_items ); + return noutput_items; +} diff --git a/gr-trellis/src/lib/trellis_pccc_decoder_X.h.t b/gr-trellis/src/lib/trellis_pccc_decoder_X.h.t new file mode 100644 index 000000000..ff4b7a1f8 --- /dev/null +++ b/gr-trellis/src/lib/trellis_pccc_decoder_X.h.t @@ -0,0 +1,102 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include "fsm.h" +#include "interleaver.h" +#include <gr_block.h> +#include <vector> +#include "siso_type.h" + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ trellis_make_@BASE_NAME@ ( + const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE // perform "min-sum" or "sum-product" combining +); + + +/*! + * \ingroup coding_blk + */ +class @NAME@ : public gr_block +{ + fsm d_FSM1; + fsm d_FSM2; + int d_ST10; + int d_ST1K; + int d_ST20; + int d_ST2K; + interleaver d_INTERLEAVER; + int d_blocklength; + int d_repetitions; + trellis_siso_type_t d_SISO_TYPE; + std::vector<float> d_buffer; + + friend @SPTR_NAME@ trellis_make_@BASE_NAME@ ( + const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE + ); + + @NAME@ ( + const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE + ); + +public: + fsm FSM1 () const { return d_FSM1; } + fsm FSM2 () const { return d_FSM2; } + int ST10 () const { return d_ST10; } + int ST1K () const { return d_ST1K; } + int ST20 () const { return d_ST20; } + int ST2K () const { return d_ST2K; } + interleaver INTERLEAVER () const { return d_INTERLEAVER; } + int blocklength () const { return d_blocklength; } + int repetitions () const { return d_repetitions; } + 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 diff --git a/gr-trellis/src/lib/trellis_pccc_decoder_X.i.t b/gr-trellis/src/lib/trellis_pccc_decoder_X.i.t new file mode 100644 index 000000000..83d7fe969 --- /dev/null +++ b/gr-trellis/src/lib/trellis_pccc_decoder_X.i.t @@ -0,0 +1,60 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(trellis,@BASE_NAME@); + +@SPTR_NAME@ trellis_make_@BASE_NAME@ ( + const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE +); + + +class @NAME@ : public gr_block +{ +private: + @NAME@ ( + const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE + ); + +public: + fsm FSM1 () const { return d_FSM1; } + fsm FSM2 () const { return d_FSM2; } + int ST10 () const { return d_ST10; } + int ST1K () const { return d_ST1K; } + int ST20 () const { return d_ST20; } + int ST2K () const { return d_ST2K; } + interleaver INTERLEAVER () const { return d_INTERLEAVER; } + int blocklength () const { return d_blocklength; } + int repetitions () const { return d_repetitions; } + trellis_siso_type_t SISO_TYPE () const { return d_SISO_TYPE; } +}; diff --git a/gr-trellis/src/lib/trellis_pccc_encoder_XX.cc.t b/gr-trellis/src/lib/trellis_pccc_encoder_XX.cc.t new file mode 100644 index 000000000..40dcd4105 --- /dev/null +++ b/gr-trellis/src/lib/trellis_pccc_encoder_XX.cc.t @@ -0,0 +1,90 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> +#include <iostream> + +@SPTR_NAME@ +trellis_make_@BASE_NAME@ ( + const fsm &FSM1, int ST1, + const fsm &FSM2, int ST2, + const interleaver &INTERLEAVER, + int blocklength +) +{ + return gnuradio::get_initial_sptr (new @NAME@ (FSM1,ST1,FSM2,ST2,INTERLEAVER,blocklength)); +} + +@NAME@::@NAME@ ( + const fsm &FSM1, int ST1, + const fsm &FSM2, int ST2, + const interleaver &INTERLEAVER, + int blocklength +) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_FSM1 (FSM1), + d_ST1 (ST1), + d_FSM2 (FSM2), + d_ST2 (ST2), + d_INTERLEAVER (INTERLEAVER), + d_blocklength (blocklength) +{ + assert(d_FSM1.I() == d_FSM2.I()); + set_output_multiple(d_blocklength); + d_buffer.resize(d_blocklength); +} + + + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + assert(noutput_items%d_blocklength ==0); + for (int b = 0 ; b<noutput_items/d_blocklength; b++) { + const @I_TYPE@ *in = (const @I_TYPE@ *) input_items[0]+b*d_blocklength; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]+b*d_blocklength; + + int ST1_tmp = d_ST1; + int ST2_tmp = d_ST2; + for (int i = 0; i < d_blocklength; i++){ + int k = d_INTERLEAVER.INTER()[i]; + int o1 = d_FSM1.OS()[ST1_tmp*d_FSM1.I()+in[i]]; + ST1_tmp = (int) d_FSM1.NS()[ST1_tmp*d_FSM1.I()+in[i]]; + int o2 = d_FSM2.OS()[ST2_tmp*d_FSM2.I()+in[k]]; + ST2_tmp = (int) d_FSM2.NS()[ST2_tmp*d_FSM2.I()+in[k]]; + out[i] = (@O_TYPE@) (o1*d_FSM1.O() + o2); + } + } + return noutput_items; +} + diff --git a/gr-trellis/src/lib/trellis_pccc_encoder_XX.h.t b/gr-trellis/src/lib/trellis_pccc_encoder_XX.h.t new file mode 100644 index 000000000..68ccf75db --- /dev/null +++ b/gr-trellis/src/lib/trellis_pccc_encoder_XX.h.t @@ -0,0 +1,83 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <vector> +#include "fsm.h" +#include "interleaver.h" +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ trellis_make_@BASE_NAME@ ( + const fsm &FSM1, int ST1, + const fsm &FSM2, int ST2, + const interleaver &INTERLEAVER, + int blocklength +); + +/*! + * \brief SCCC encoder. + * \ingroup coding_blk + */ +class @NAME@ : public gr_sync_block +{ +private: + friend @SPTR_NAME@ trellis_make_@BASE_NAME@ ( + const fsm &FSM1, int ST1, + const fsm &FSM2, int ST2, + const interleaver &INTERLEAVER, + int blocklength + ); + fsm d_FSM1; + int d_ST1; + fsm d_FSM2; + int d_ST2; + interleaver d_INTERLEAVER; + int d_blocklength; + std::vector<int> d_buffer; + @NAME@ ( + const fsm &FSM1, int ST1, + const fsm &FSM2, int ST2, + const interleaver &INTERLEAVER, + int blocklength + ); + +public: + fsm FSM1 () const { return d_FSM1; } + int ST1 () const { return d_ST1; } + fsm FSM2 () const { return d_FSM2; } + int ST2 () const { return d_ST2; } + interleaver INTERLEAVER () const { return d_INTERLEAVER; } + int blocklength () const { return d_blocklength; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gr-trellis/src/lib/trellis_pccc_encoder_XX.i.t b/gr-trellis/src/lib/trellis_pccc_encoder_XX.i.t new file mode 100644 index 000000000..c02ee428a --- /dev/null +++ b/gr-trellis/src/lib/trellis_pccc_encoder_XX.i.t @@ -0,0 +1,50 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(trellis,@BASE_NAME@); + +@SPTR_NAME@ trellis_make_@BASE_NAME@ ( + const fsm &FSM1, int ST1, + const fsm &FSM2, int ST2, + const interleaver &INTERLEAVER, + int blocklength +); + +class @NAME@ : public gr_sync_block +{ +private: + @NAME@ ( + const fsm &FSM1, int ST1, + const fsm &FSM2, int ST2, + const interleaver &INTERLEAVER, + int blocklength + ); +public: + fsm FSM1 () const { return d_FSM1; } + int ST1 () const { return d_ST1; } + fsm FSM2 () const { return d_FSM2; } + int ST2 () const { return d_ST2; } + interleaver INTERLEAVER () const { return d_INTERLEAVER; } + int blocklength () const { return d_blocklength; } +}; diff --git a/gr-trellis/src/lib/trellis_sccc_decoder_X.cc.t b/gr-trellis/src/lib/trellis_sccc_decoder_X.cc.t new file mode 100644 index 000000000..4a0f471fa --- /dev/null +++ b/gr-trellis/src/lib/trellis_sccc_decoder_X.cc.t @@ -0,0 +1,124 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> +#include <assert.h> +#include <iostream> +#include "core_algorithms.h" + + +static const float INF = 1.0e9; + +@SPTR_NAME@ +trellis_make_@BASE_NAME@ ( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE +) +{ + return gnuradio::get_initial_sptr (new @NAME@ ( + FSMo, STo0, SToK, + FSMi, STi0, STiK, + INTERLEAVER, + blocklength, + repetitions, + SISO_TYPE + )); +} + +@NAME@::@NAME@ ( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE +) + : gr_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_FSMo (FSMo), d_STo0 (STo0), d_SToK (SToK), + d_FSMi (FSMi), d_STi0 (STi0), d_STiK (STiK), + d_INTERLEAVER (INTERLEAVER), + d_blocklength (blocklength), + d_repetitions (repetitions), + d_SISO_TYPE (SISO_TYPE) +{ + assert(d_FSMo.O() == d_FSMi.I()); + set_relative_rate (1.0 / ((double) d_FSMi.O())); + set_output_multiple (d_blocklength); +} + + +void +@NAME@::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + assert (noutput_items % d_blocklength == 0); + int input_required = d_FSMi.O() * noutput_items ; + ninput_items_required[0] = input_required; +} + + + +//=========================================================== + +int +@NAME@::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + assert (noutput_items % d_blocklength == 0); + int nblocks = noutput_items / d_blocklength; + + 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; + + + const float *in = (const float *) input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]; + for (int n=0;n<nblocks;n++) { + sccc_decoder( + d_FSMo, d_STo0, d_SToK, + d_FSMi, d_STi0, d_STiK, + d_INTERLEAVER, d_blocklength, d_repetitions, + p2min, + &(in[n*d_blocklength*d_FSMi.O()]),&(out[n*d_blocklength]) + ); + } + + consume_each (d_FSMi.O() * noutput_items ); + return noutput_items; +} diff --git a/gr-trellis/src/lib/trellis_sccc_decoder_X.h.t b/gr-trellis/src/lib/trellis_sccc_decoder_X.h.t new file mode 100644 index 000000000..3adb8a5b7 --- /dev/null +++ b/gr-trellis/src/lib/trellis_sccc_decoder_X.h.t @@ -0,0 +1,102 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include "fsm.h" +#include "interleaver.h" +#include <gr_block.h> +#include <vector> +#include "siso_type.h" + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ trellis_make_@BASE_NAME@ ( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE // perform "min-sum" or "sum-product" combining +); + + +/*! + * \ingroup coding_blk + */ +class @NAME@ : public gr_block +{ + fsm d_FSMo; + fsm d_FSMi; + int d_STo0; + int d_SToK; + int d_STi0; + int d_STiK; + interleaver d_INTERLEAVER; + int d_blocklength; + int d_repetitions; + trellis_siso_type_t d_SISO_TYPE; + std::vector<float> d_buffer; + + friend @SPTR_NAME@ trellis_make_@BASE_NAME@ ( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE + ); + + @NAME@ ( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE + ); + +public: + fsm FSMo () const { return d_FSMo; } + fsm FSMi () const { return d_FSMi; } + int STo0 () const { return d_STo0; } + int SToK () const { return d_SToK; } + int STi0 () const { return d_STi0; } + int STiK () const { return d_STiK; } + interleaver INTERLEAVER () const { return d_INTERLEAVER; } + int blocklength () const { return d_blocklength; } + int repetitions () const { return d_repetitions; } + 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 diff --git a/gr-trellis/src/lib/trellis_sccc_decoder_X.i.t b/gr-trellis/src/lib/trellis_sccc_decoder_X.i.t new file mode 100644 index 000000000..a4392ee6f --- /dev/null +++ b/gr-trellis/src/lib/trellis_sccc_decoder_X.i.t @@ -0,0 +1,60 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(trellis,@BASE_NAME@); + +@SPTR_NAME@ trellis_make_@BASE_NAME@ ( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE +); + + +class @NAME@ : public gr_block +{ +private: + @NAME@ ( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE + ); + +public: + fsm FSMo () const { return d_FSMo; } + fsm FSMi () const { return d_FSMi; } + int STo0 () const { return d_STo0; } + int SToK () const { return d_SToK; } + int STi0 () const { return d_STi0; } + int STiK () const { return d_STiK; } + interleaver INTERLEAVER () const { return d_INTERLEAVER; } + int blocklength () const { return d_blocklength; } + int repetitions () const { return d_repetitions; } + trellis_siso_type_t SISO_TYPE () const { return d_SISO_TYPE; } +}; diff --git a/gr-trellis/src/lib/trellis_sccc_decoder_combined_XX.cc.t b/gr-trellis/src/lib/trellis_sccc_decoder_combined_XX.cc.t new file mode 100644 index 000000000..2927e3fe3 --- /dev/null +++ b/gr-trellis/src/lib/trellis_sccc_decoder_combined_XX.cc.t @@ -0,0 +1,147 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> +#include <assert.h> +#include <iostream> +#include "core_algorithms.h" + + +static const float INF = 1.0e9; + +@SPTR_NAME@ +trellis_make_@BASE_NAME@ ( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE, + int D, + const std::vector<@I_TYPE@> &TABLE, + trellis_metric_type_t METRIC_TYPE, + float scaling +) +{ + return gnuradio::get_initial_sptr (new @NAME@ ( + FSMo, STo0, SToK, + FSMi, STi0, STiK, + INTERLEAVER, + blocklength, + repetitions, + SISO_TYPE, + D, + TABLE,METRIC_TYPE, + scaling + )); +} + +@NAME@::@NAME@ ( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE, + int D, + const std::vector<@I_TYPE@> &TABLE, + trellis_metric_type_t METRIC_TYPE, + float scaling +) + : gr_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_FSMo (FSMo), d_STo0 (STo0), d_SToK (SToK), + d_FSMi (FSMi), d_STi0 (STi0), d_STiK (STiK), + d_INTERLEAVER (INTERLEAVER), + d_blocklength (blocklength), + d_repetitions (repetitions), + d_SISO_TYPE (SISO_TYPE), + d_D (D), + d_TABLE (TABLE), + d_METRIC_TYPE (METRIC_TYPE), + d_scaling (scaling) +{ + assert(d_FSMo.O() == d_FSMi.I()); + set_relative_rate (1.0 / ((double) d_D)); + set_output_multiple (d_blocklength); +} + +void @NAME@::set_scaling(float scaling) +{ + d_scaling = scaling; +} + + +void +@NAME@::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + assert (noutput_items % d_blocklength == 0); + int input_required = d_D * noutput_items ; + ninput_items_required[0] = input_required; +} + + + +//=========================================================== + +int +@NAME@::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + assert (noutput_items % d_blocklength == 0); + int nblocks = noutput_items / d_blocklength; + + 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; + + + const @I_TYPE@ *in = (const @I_TYPE@ *) input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]; + for (int n=0;n<nblocks;n++) { + sccc_decoder_combined( + d_FSMo, d_STo0, d_SToK, + d_FSMi, d_STi0, d_STiK, + d_INTERLEAVER, d_blocklength, d_repetitions, + p2min, + d_D,d_TABLE, + d_METRIC_TYPE, + d_scaling, + &(in[n*d_blocklength*d_D]),&(out[n*d_blocklength]) + ); + } + + consume_each (d_D * noutput_items ); + return noutput_items; +} diff --git a/gr-trellis/src/lib/trellis_sccc_decoder_combined_XX.h.t b/gr-trellis/src/lib/trellis_sccc_decoder_combined_XX.h.t new file mode 100644 index 000000000..146c26516 --- /dev/null +++ b/gr-trellis/src/lib/trellis_sccc_decoder_combined_XX.h.t @@ -0,0 +1,124 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include "fsm.h" +#include "interleaver.h" +#include <gr_block.h> +#include <vector> +#include "calc_metric.h" +#include "siso_type.h" + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ trellis_make_@BASE_NAME@ ( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE, // perform "min-sum" or "sum-product" combining + int D, + const std::vector<@I_TYPE@> &TABLE, + trellis_metric_type_t METRIC_TYPE, + float scaling +); + + +/*! + * \ingroup coding_blk + */ +class @NAME@ : public gr_block +{ + fsm d_FSMo; + fsm d_FSMi; + int d_STo0; + int d_SToK; + int d_STi0; + int d_STiK; + interleaver d_INTERLEAVER; + int d_blocklength; + int d_repetitions; + trellis_siso_type_t d_SISO_TYPE; + int d_D; + std::vector<@I_TYPE@> d_TABLE; + trellis_metric_type_t d_METRIC_TYPE; + float d_scaling; + std::vector<float> d_buffer; + + friend @SPTR_NAME@ trellis_make_@BASE_NAME@ ( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE, + int D, + const std::vector<@I_TYPE@> &TABLE, + trellis_metric_type_t METRIC_TYPE, + float scaling + ); + + @NAME@ ( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE, + int D, + const std::vector<@I_TYPE@> &TABLE, + trellis_metric_type_t METRIC_TYPE, + float scaling + ); + +public: + fsm FSMo () const { return d_FSMo; } + fsm FSMi () const { return d_FSMi; } + int STo0 () const { return d_STo0; } + int SToK () const { return d_SToK; } + int STi0 () const { return d_STi0; } + int STiK () const { return d_STiK; } + interleaver INTERLEAVER () const { return d_INTERLEAVER; } + int blocklength () const { return d_blocklength; } + int repetitions () const { return d_repetitions; } + int D () const { return d_D; } + std::vector<@I_TYPE@> TABLE () const { return d_TABLE; } + trellis_metric_type_t METRIC_TYPE () const { return d_METRIC_TYPE; } + trellis_siso_type_t SISO_TYPE () const { return d_SISO_TYPE; } + float scaling () const { return d_scaling; } + void set_scaling (float scaling); + + 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 diff --git a/gr-trellis/src/lib/trellis_sccc_decoder_combined_XX.i.t b/gr-trellis/src/lib/trellis_sccc_decoder_combined_XX.i.t new file mode 100644 index 000000000..84f2eb07d --- /dev/null +++ b/gr-trellis/src/lib/trellis_sccc_decoder_combined_XX.i.t @@ -0,0 +1,73 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(trellis,@BASE_NAME@); + +@SPTR_NAME@ trellis_make_@BASE_NAME@ ( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE, + int D, + const std::vector<@I_TYPE@> &TABLE, + trellis_metric_type_t METRIC_TYPE, + float scaling +); + + +class @NAME@ : public gr_block +{ +private: + @NAME@ ( + const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + trellis_siso_type_t SISO_TYPE, + int D, + const std::vector<@I_TYPE@> &TABLE, + trellis_metric_type_t METRIC_TYPE, + float scaling + ); + +public: + fsm FSMo () const { return d_FSMo; } + fsm FSMi () const { return d_FSMi; } + int STo0 () const { return d_STo0; } + int SToK () const { return d_SToK; } + int STi0 () const { return d_STi0; } + int STiK () const { return d_STiK; } + interleaver INTERLEAVER () const { return d_INTERLEAVER; } + int blocklength () const { return d_blocklength; } + int repetitions () const { return d_repetitions; } + int D () const { return d_D; } + std::vector<@I_TYPE@> TABLE () const { return d_TABLE; } + trellis_metric_type_t METRIC_TYPE () const { return d_METRIC_TYPE; } + trellis_siso_type_t SISO_TYPE () const { return d_SISO_TYPE; } + float scaling() const { return d_scaling; } + void set_scaling (float scaling); +}; diff --git a/gr-trellis/src/lib/trellis_sccc_encoder_XX.cc.t b/gr-trellis/src/lib/trellis_sccc_encoder_XX.cc.t new file mode 100644 index 000000000..b1a46ca60 --- /dev/null +++ b/gr-trellis/src/lib/trellis_sccc_encoder_XX.cc.t @@ -0,0 +1,91 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> +#include <iostream> + +@SPTR_NAME@ +trellis_make_@BASE_NAME@ ( + const fsm &FSMo, int STo, + const fsm &FSMi, int STi, + const interleaver &INTERLEAVER, + int blocklength +) +{ + return gnuradio::get_initial_sptr (new @NAME@ (FSMo,STo,FSMi,STi,INTERLEAVER,blocklength)); +} + +@NAME@::@NAME@ ( + const fsm &FSMo, int STo, + const fsm &FSMi, int STi, + const interleaver &INTERLEAVER, + int blocklength +) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_FSMo (FSMo), + d_STo (STo), + d_FSMi (FSMi), + d_STi (STi), + d_INTERLEAVER (INTERLEAVER), + d_blocklength (blocklength) +{ + assert(d_FSMo.O() == d_FSMi.I()); + set_output_multiple(d_blocklength); + d_buffer.resize(d_blocklength); +} + + + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + assert(noutput_items%d_blocklength ==0); + for (int b = 0 ; b<noutput_items/d_blocklength; b++) { + const @I_TYPE@ *in = (const @I_TYPE@ *) input_items[0]+b*d_blocklength; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]+b*d_blocklength; + + int STo_tmp = d_STo; + for (int i = 0; i < d_blocklength; i++){ + d_buffer[i] = d_FSMo.OS()[STo_tmp*d_FSMo.I()+in[i]]; + STo_tmp = (int) d_FSMo.NS()[STo_tmp*d_FSMo.I()+in[i]]; + } + int STi_tmp = d_STi; + for (int i = 0; i < d_blocklength; i++){ + int k = d_INTERLEAVER.INTER()[i]; + out[i] = (@O_TYPE@) d_FSMi.OS()[STi_tmp*d_FSMi.I()+d_buffer[k]]; + STi_tmp = (int) d_FSMi.NS()[STi_tmp*d_FSMi.I()+d_buffer[k]]; + } + } + return noutput_items; +} + diff --git a/gr-trellis/src/lib/trellis_sccc_encoder_XX.h.t b/gr-trellis/src/lib/trellis_sccc_encoder_XX.h.t new file mode 100644 index 000000000..a9e4dc454 --- /dev/null +++ b/gr-trellis/src/lib/trellis_sccc_encoder_XX.h.t @@ -0,0 +1,83 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <vector> +#include "fsm.h" +#include "interleaver.h" +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ trellis_make_@BASE_NAME@ ( + const fsm &FSMo, int STo, + const fsm &FSMi, int STi, + const interleaver &INTERLEAVER, + int blocklength +); + +/*! + * \brief SCCC encoder. + * \ingroup coding_blk + */ +class @NAME@ : public gr_sync_block +{ +private: + friend @SPTR_NAME@ trellis_make_@BASE_NAME@ ( + const fsm &FSMo, int STo, + const fsm &FSMi, int STi, + const interleaver &INTERLEAVER, + int blocklength + ); + fsm d_FSMo; + int d_STo; + fsm d_FSMi; + int d_STi; + interleaver d_INTERLEAVER; + int d_blocklength; + std::vector<int> d_buffer; + @NAME@ ( + const fsm &FSMo, int STo, + const fsm &FSMi, int STi, + const interleaver &INTERLEAVER, + int blocklength + ); + +public: + fsm FSMo () const { return d_FSMo; } + int STo () const { return d_STo; } + fsm FSMi () const { return d_FSMi; } + int STi () const { return d_STi; } + interleaver INTERLEAVER () const { return d_INTERLEAVER; } + int blocklength () const { return d_blocklength; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gr-trellis/src/lib/trellis_sccc_encoder_XX.i.t b/gr-trellis/src/lib/trellis_sccc_encoder_XX.i.t new file mode 100644 index 000000000..ca6b56199 --- /dev/null +++ b/gr-trellis/src/lib/trellis_sccc_encoder_XX.i.t @@ -0,0 +1,50 @@ +/* -*- 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 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(trellis,@BASE_NAME@); + +@SPTR_NAME@ trellis_make_@BASE_NAME@ ( + const fsm &FSMo, int STo, + const fsm &FSMi, int STi, + const interleaver &INTERLEAVER, + int blocklength +); + +class @NAME@ : public gr_sync_block +{ +private: + @NAME@ ( + const fsm &FSMo, int STo, + const fsm &FSMi, int STi, + const interleaver &INTERLEAVER, + int blocklength + ); +public: + fsm FSMo () const { return d_FSMo; } + int STo () const { return d_STo; } + fsm FSMi () const { return d_FSMi; } + int STi () const { return d_STi; } + interleaver INTERLEAVER () const { return d_INTERLEAVER; } + int blocklength () const { return d_blocklength; } +}; diff --git a/gr-trellis/src/lib/trellis_siso_combined_f.cc b/gr-trellis/src/lib/trellis_siso_combined_f.cc index 708608b16..2a4cfa123 100644 --- a/gr-trellis/src/lib/trellis_siso_combined_f.cc +++ b/gr-trellis/src/lib/trellis_siso_combined_f.cc @@ -125,6 +125,13 @@ trellis_siso_combined_f::forecast (int noutput_items, gr_vector_int &ninput_item } } + + + + +/* + + inline float min(float a, float b) { return a <= b ? a : b; @@ -286,7 +293,7 @@ void siso_algorithm_combined(int I, int S, int O, } - +*/ diff --git a/gr-trellis/src/lib/trellis_siso_combined_f.h b/gr-trellis/src/lib/trellis_siso_combined_f.h index 6432c2262..786e79386 100644 --- a/gr-trellis/src/lib/trellis_siso_combined_f.h +++ b/gr-trellis/src/lib/trellis_siso_combined_f.h @@ -24,8 +24,9 @@ #define INCLUDED_TRELLIS_SISO_COMBINED_F_H #include "fsm.h" -#include "trellis_siso_type.h" -#include "trellis_calc_metric.h" +#include "siso_type.h" +#include "calc_metric.h" +#include "core_algorithms.h" #include <gr_block.h> class trellis_siso_combined_f; diff --git a/gr-trellis/src/lib/trellis_siso_f.cc b/gr-trellis/src/lib/trellis_siso_f.cc index c8fa8231d..d478c13a3 100644 --- a/gr-trellis/src/lib/trellis_siso_f.cc +++ b/gr-trellis/src/lib/trellis_siso_f.cc @@ -116,6 +116,11 @@ trellis_siso_f::forecast (int noutput_items, gr_vector_int &ninput_items_require } } + + + +/* Moved it to "core_algorithms.cc" */ +/* inline float min(float a, float b) { return a <= b ? a : b; @@ -270,7 +275,7 @@ else } - +*/ diff --git a/gr-trellis/src/lib/trellis_siso_f.h b/gr-trellis/src/lib/trellis_siso_f.h index 3e2c2498b..0e2cba67a 100644 --- a/gr-trellis/src/lib/trellis_siso_f.h +++ b/gr-trellis/src/lib/trellis_siso_f.h @@ -24,7 +24,8 @@ #define INCLUDED_TRELLIS_SISO_F_H #include "fsm.h" -#include "trellis_siso_type.h" +#include "siso_type.h" +#include "core_algorithms.h" #include <gr_block.h> class trellis_siso_f; diff --git a/gr-trellis/src/lib/trellis_viterbi_X.cc.t b/gr-trellis/src/lib/trellis_viterbi_X.cc.t index 178215362..2254f6450 100644 --- a/gr-trellis/src/lib/trellis_viterbi_X.cc.t +++ b/gr-trellis/src/lib/trellis_viterbi_X.cc.t @@ -73,9 +73,22 @@ void } } +/* +template +void viterbi_algorithm<@O_TYPE@>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + const float *in, @O_TYPE@ *out); +*/ +/* Moved it to "core_algorithms.cc" */ +/* void viterbi_algorithm(int I, int S, int O, const std::vector<int> &NS, const std::vector<int> &OS, @@ -141,7 +154,7 @@ void viterbi_algorithm(int I, int S, int O, } - +*/ diff --git a/gr-trellis/src/lib/trellis_viterbi_X.h.t b/gr-trellis/src/lib/trellis_viterbi_X.h.t index 67b46a8ee..362d3f57e 100644 --- a/gr-trellis/src/lib/trellis_viterbi_X.h.t +++ b/gr-trellis/src/lib/trellis_viterbi_X.h.t @@ -27,6 +27,7 @@ #include "fsm.h" #include <gr_block.h> +#include "core_algorithms.h" class @NAME@; typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; @@ -78,4 +79,12 @@ public: gr_vector_void_star &output_items); }; + + + + + + + + #endif diff --git a/gr-trellis/src/lib/trellis_viterbi_combined_XX.cc.t b/gr-trellis/src/lib/trellis_viterbi_combined_XX.cc.t index d365de75f..e883a0ba7 100644 --- a/gr-trellis/src/lib/trellis_viterbi_combined_XX.cc.t +++ b/gr-trellis/src/lib/trellis_viterbi_combined_XX.cc.t @@ -90,6 +90,7 @@ void +/* void viterbi_algorithm_combined(int I, int S, int O, const std::vector<int> &NS, const std::vector<int> &OS, @@ -162,7 +163,7 @@ void viterbi_algorithm_combined(int I, int S, int O, } - +*/ diff --git a/gr-trellis/src/lib/trellis_viterbi_combined_XX.h.t b/gr-trellis/src/lib/trellis_viterbi_combined_XX.h.t index 21307d0e3..35e6c4ce0 100644 --- a/gr-trellis/src/lib/trellis_viterbi_combined_XX.h.t +++ b/gr-trellis/src/lib/trellis_viterbi_combined_XX.h.t @@ -27,7 +27,8 @@ #include "fsm.h" #include <gr_block.h> -#include "trellis_calc_metric.h" +#include "calc_metric.h" +#include "core_algorithms.h" class @NAME@; typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; diff --git a/gr-trellis/src/python/Makefile.am b/gr-trellis/src/python/Makefile.am index 76ec9d0c1..808ac4fb7 100644 --- a/gr-trellis/src/python/Makefile.am +++ b/gr-trellis/src/python/Makefile.am @@ -21,12 +21,11 @@ include $(top_srcdir)/Makefile.common -EXTRA_DIST = run_tests.in \ +EXTRA_DIST += run_tests.in \ awgn1o2_4.fsm -TESTS = \ - run_tests +TESTS = run_tests noinst_PYTHON = \ diff --git a/gr-trellis/src/python/qa_trellis.py b/gr-trellis/src/python/qa_trellis.py index cfeefea06..b50679f27 100755 --- a/gr-trellis/src/python/qa_trellis.py +++ b/gr-trellis/src/python/qa_trellis.py @@ -20,46 +20,50 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest +import math + + +from gnuradio import gr, gr_unittest, blks2 +# It's pretty ugly that we can't import trellis from gnuradio in this test +# but because it runs on the non-installed python code it's all a mess. import trellis -class test_trellis (gr_unittest.TestCase): +import os +import digital_swig - def setUp (self): - self.tb = gr.top_block () +fsm_args = {"awgn1o2_4": (2, 4, 4, + (0, 2, 0, 2, 1, 3, 1, 3), + (0, 3, 3, 0, 1, 2, 2, 1), + ), + "rep2": (2, 1, 4, (0, 0), (0, 3)), + "nothing": (2, 1, 2, (0, 0), (0, 1)), + } - def tearDown (self): - self.tb = None +constells = {2: digital_swig.constellation_bpsk(), + 4: digital_swig.constellation_qpsk(), + } + +class test_trellis (gr_unittest.TestCase): def test_001_fsm (self): - I = 2 - S = 4 - O = 4 - NS = (0, 2, 0, 2, 1, 3, 1, 3) - OS = (0, 3, 3, 0, 1, 2, 2, 1) - f = trellis.fsm(I,S,O,NS,OS) - self.assertEqual((I,S,O,NS,OS),(f.I(),f.S(),f.O(),f.NS(),f.OS())) + f = trellis.fsm(*fsm_args["awgn1o2_4"]) + self.assertEqual(fsm_args["awgn1o2_4"],(f.I(),f.S(),f.O(),f.NS(),f.OS())) def test_002_fsm (self): - I = 2 - S = 4 - O = 4 - NS = (0, 2, 0, 2, 1, 3, 1, 3) - OS = (0, 3, 3, 0, 1, 2, 2, 1) - f = trellis.fsm(I,S,O,NS,OS) + f = trellis.fsm(*fsm_args["awgn1o2_4"]) g = trellis.fsm(f) self.assertEqual((g.I(),g.S(),g.O(),g.NS(),g.OS()),(f.I(),f.S(),f.O(),f.NS(),f.OS())) def test_003_fsm (self): - I = 2 - S = 4 - O = 4 - NS = (0, 2, 0, 2, 1, 3, 1, 3) - OS = (0, 3, 3, 0, 1, 2, 2, 1) + # FIXME: no file "awgn1o2_4.fsm" #f = trellis.fsm("awgn1o2_4.fsm") - #self.assertEqual((I,S,O,NS,OS),(f.I(),f.S(),f.O(),f.NS(),f.OS())) - # temporary fix so that make distcheck does not fail on this - self.assertEqual(0,0) + #self.assertEqual(fsm_args["awgn1o2_4"],(f.I(),f.S(),f.O(),f.NS(),f.OS())) + pass + + def test_004_fsm(self): + """ Test to make sure fsm works with a single state fsm.""" + # Just checking that it initializes properly. + f = trellis.fsm(*fsm_args["rep2"]) def test_001_interleaver (self): K = 5 @@ -68,5 +72,69 @@ class test_trellis (gr_unittest.TestCase): i = trellis.interleaver(K,IN) self.assertEqual((K,IN,DIN),(i.K(),i.INTER(),i.DEINTER())) + def test_001_viterbi(self): + """ + Runs some coding/decoding tests with a few different FSM + specs. + """ + for name, args in fsm_args.items(): + constellation = constells[args[2]] + fsms = trellis.fsm(*args) + noise = 0.1 + tb = trellis_tb(constellation, fsms, noise) + tb.run() + # Make sure all packets succesfully transmitted. + self.assertEqual(tb.dst.ntotal(), tb.dst.nright()) + + +class trellis_tb(gr.top_block): + """ + A simple top block for use testing gr-trellis. + """ + def __init__(self, constellation, f, N0=0.25, seed=-666L): + """ + constellation - a constellation object used for modulation. + f - a finite state machine specification used for coding. + N0 - noise level + seed - random seed + """ + super(trellis_tb, self).__init__() + # packet size in bits (make it multiple of 16 so it can be packed in a short) + packet_size = 1024*16 + # bits per FSM input symbol + bitspersymbol = int(round(math.log(f.I())/math.log(2))) # bits per FSM input symbol + # packet size in trellis steps + K = packet_size/bitspersymbol + + # TX + src = gr.lfsr_32k_source_s() + # packet size in shorts + src_head = gr.head (gr.sizeof_short, packet_size/16) + # unpack shorts to symbols compatible with the FSM input cardinality + s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol, gr.GR_MSB_FIRST) + # initial FSM state = 0 + enc = trellis.encoder_ss(f, 0) + mod = gr.chunks_to_symbols_sc(constellation.points(), 1) + + # CHANNEL + add = gr.add_cc() + noise = gr.noise_source_c(gr.GR_GAUSSIAN,math.sqrt(N0/2),seed) + + # RX + # data preprocessing to generate metrics for Viterbi + metrics = trellis.constellation_metrics_cf(constellation.base(), digital_swig.TRELLIS_EUCLIDEAN) + # Put -1 if the Initial/Final states are not set. + va = trellis.viterbi_s(f, K, 0, -1) + # pack FSM input symbols to shorts + fsmi2s = gr.unpacked_to_packed_ss(bitspersymbol, gr.GR_MSB_FIRST) + # check the output + self.dst = gr.check_lfsr_32k_s() + + self.connect (src, src_head, s2fsmi, enc, mod) + self.connect (mod, (add, 0)) + self.connect (noise, (add, 1)) + self.connect (add, metrics, va, fsmi2s, self.dst) + + if __name__ == '__main__': gr_unittest.run(test_trellis, "test_trellis.xml") diff --git a/gr-trellis/src/python/run_tests.in b/gr-trellis/src/python/run_tests.in index 0da3fc1f1..fcb078663 100644 --- a/gr-trellis/src/python/run_tests.in +++ b/gr-trellis/src/python/run_tests.in @@ -4,6 +4,8 @@ # 2nd parameter is absolute path to component build directory # 3rd parameter is path to Python QA directory +PYTHONPATH=@top_builddir@/gr-digital/swig:@top_builddir@/gr-digital/swig/.libs:@top_srcdir@/gr-digital/swig:$PYTHONPATH + @top_builddir@/run_tests.sh \ @abs_top_srcdir@/gr-trellis \ @abs_top_builddir@/gr-trellis \ |