commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] gr-error-correcting-codes/src/lib Makefile.am e...


From: Michael Dickens
Subject: [Commit-gnuradio] gr-error-correcting-codes/src/lib Makefile.am e...
Date: Wed, 05 Jul 2006 17:49:59 +0000

CVSROOT:        /sources/gnuradio
Module name:    gr-error-correcting-codes
Changes by:     Michael Dickens <michaelld>     06/07/05 17:49:58

Modified files:
        src/lib        : Makefile.am ecc.i gr_syms_to_metrics.cc 
        src/lib/libecc : Makefile.am code_metrics.cc decoder.h 
                         encoder_convolutional_ic1_ic1.h 
Added files:
        src/lib        : gr_decoder_viterbi_block_full.cc 
                         gr_decoder_viterbi_block_full.h 
                         gr_decoder_viterbi_block_full.i 
        src/lib/libecc : decoder.cc decoder_viterbi.cc decoder_viterbi.h 
                         decoder_viterbi_block_full.cc 
                         decoder_viterbi_block_full.h 
                         decoder_viterbi_block_full_ic1.h 
Removed files:
        src/lib        : gr_decoder_viterbi_block_soft_full.cc 
                         gr_decoder_viterbi_block_soft_full.h 
                         gr_decoder_viterbi_block_soft_full.i 
        src/lib/libecc : decoder_viterbi_base.h 
                         encoder_convolutional_base.cc 
                         encoder_convolutional_base.h 

Log message:
        Work in progress.  Creating decoder classes & updating .am and .i
        files for these additions.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/Makefile.am?cvsroot=gnuradio&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/ecc.i?cvsroot=gnuradio&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/gr_syms_to_metrics.cc?cvsroot=gnuradio&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/gr_decoder_viterbi_block_full.cc?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/gr_decoder_viterbi_block_full.h?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/gr_decoder_viterbi_block_full.i?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/gr_decoder_viterbi_block_soft_full.cc?cvsroot=gnuradio&r1=1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/gr_decoder_viterbi_block_soft_full.h?cvsroot=gnuradio&r1=1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/gr_decoder_viterbi_block_soft_full.i?cvsroot=gnuradio&r1=1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/Makefile.am?cvsroot=gnuradio&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/code_metrics.cc?cvsroot=gnuradio&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/decoder.h?cvsroot=gnuradio&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.h?cvsroot=gnuradio&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/decoder.cc?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.cc?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.h?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_block_full.cc?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_block_full.h?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_block_full_ic1.h?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_base.h?cvsroot=gnuradio&r1=1.2&r2=0
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_base.cc?cvsroot=gnuradio&r1=1.2&r2=0
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_base.h?cvsroot=gnuradio&r1=1.2&r2=0

Patches:
Index: Makefile.am
===================================================================
RCS file: /sources/gnuradio/gr-error-correcting-codes/src/lib/Makefile.am,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- Makefile.am 3 Jul 2006 02:12:53 -0000       1.1
+++ Makefile.am 5 Jul 2006 17:49:58 -0000       1.2
@@ -44,7 +44,7 @@
 
 LOCAL_IFILES =                                         \
        gr_syms_to_metrics.i                    \
-       gr_decoder_viterbi_block_soft_full.i    \
+       gr_decoder_viterbi_block_full.i         \
        gr_streams_encode_convolutional.i       \
        ecc.i
 
@@ -66,7 +66,7 @@
 # These are the source files that go into the shared library
 _ecc_la_SOURCES =              \
        gr_syms_to_metrics.cc                   \
-       gr_decoder_viterbi_block_soft_full.cc   \
+       gr_decoder_viterbi_block_full.cc        \
        gr_streams_encode_convolutional.cc      \
        ecc.cc
 
@@ -85,7 +85,7 @@
 # These headers get installed in ${prefix}/include/gnuradio
 grinclude_HEADERS =                            \
        gr_syms_to_metrics.h                    \
-       gr_decoder_viterbi_block_soft_full.h    \
+       gr_decoder_viterbi_block_full.h         \
        gr_streams_encode_convolutional.h
 
 # These swig headers get installed in ${prefix}/include/gnuradio/swig

Index: ecc.i
===================================================================
RCS file: /sources/gnuradio/gr-error-correcting-codes/src/lib/ecc.i,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- ecc.i       3 Jul 2006 02:12:53 -0000       1.1
+++ ecc.i       5 Jul 2006 17:49:58 -0000       1.2
@@ -28,12 +28,12 @@
 
 #include "gnuradio_swig_bug_workaround.h"      // mandatory bug fix
 #include <gr_streams_encode_convolutional.h>
-#include <gr_decoder_viterbi_block_soft_full.h>
+#include <gr_decoder_viterbi_block_full.h>
 #include <gr_syms_to_metrics.h>
 #include <stdexcept>
 
 %}
 
 %include "gr_streams_encode_convolutional.i"
-%include "gr_decoder_viterbi_block_soft_full.i"
+%include "gr_decoder_viterbi_block_full.i"
 %include "gr_syms_to_metrics.i"

Index: gr_syms_to_metrics.cc
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/lib/gr_syms_to_metrics.cc,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- gr_syms_to_metrics.cc       3 Jul 2006 02:12:53 -0000       1.1
+++ gr_syms_to_metrics.cc       5 Jul 2006 17:49:58 -0000       1.2
@@ -45,8 +45,10 @@
                             sample_precision));
 }
 
-// dummy functions to get the float(*)(float) function to work
-// properly with the gr_feval_XX stuff.
+/*
+ * dummy functions and variables to get the float(*)(float) function
+ * to work properly with the gr_feval_XX stuff.
+ */
 
 static gr_feval_ff* l_pdf_fcn_0_bit;
 static gr_feval_ff* l_pdf_fcn_1_bit;
@@ -82,16 +84,16 @@
   l_pdf_fcn_1_bit = pdf_fcn_1_bit;
 
   if (sample_precision == 0) {
-// float
-    d_out_item_size_bytes = 4;
+    // float
+    d_out_item_size_bytes = sizeof (float);
     d_code_metrics = new code_metric_ff (&pdf_fcn_0,
                                         &pdf_fcn_1,
                                         n_samples,
                                         min_sample,
                                         max_sample);
   } else if (sample_precision <= 8) {
-// use char 
-    d_out_item_size_bytes = 1;
+    // use char
+    d_out_item_size_bytes = sizeof (char);
     d_code_metrics = new code_metric_fb (&pdf_fcn_0,
                                         &pdf_fcn_1,
                                         n_samples,
@@ -99,8 +101,8 @@
                                         max_sample,
                                         sample_precision);
   } else if (sample_precision <= 16) {
-// use short 
-    d_out_item_size_bytes = 2;
+    // use short
+    d_out_item_size_bytes = sizeof (short);
     d_code_metrics = new code_metric_fs (&pdf_fcn_0,
                                         &pdf_fcn_1,
                                         n_samples,
@@ -108,8 +110,8 @@
                                         max_sample,
                                         sample_precision);
   } else {
-// use long 
-    d_out_item_size_bytes = 4;
+    // use long
+    d_out_item_size_bytes = sizeof (long);
     d_code_metrics = new code_metric_fl (&pdf_fcn_0,
                                         &pdf_fcn_1,
                                         n_samples,
@@ -131,14 +133,15 @@
 (int noutput_items,
  gr_vector_int &ninput_items_required)
 {
-// always 1:1, for all streams
+  // always 1:1, for all streams
   for (size_t n = 0; n < ninput_items_required.size(); n++) {
     ninput_items_required[n] = noutput_items;
   }
 }
 
 int
-gr_syms_to_metrics::general_work (int noutput_items,
+gr_syms_to_metrics::general_work
+(int noutput_items,
                                  gr_vector_int &ninput_items,
                                  gr_vector_const_void_star &input_items,
                                  gr_vector_void_star &output_items)
@@ -154,9 +157,11 @@
                             t_out_buf_0_bit, t_out_buf_1_bit);
   }
 
-// consume the number of used input items on all input streams
+  // consume the number of used input items on all input streams
+
   consume_each (noutput_items);
 
-// returns number of items written to each output stream
+  // returns number of items written to each output stream
+
   return (noutput_items);
 }

Index: libecc/Makefile.am
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/lib/libecc/Makefile.am,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- libecc/Makefile.am  4 Jul 2006 20:57:32 -0000       1.3
+++ libecc/Makefile.am  5 Jul 2006 17:49:58 -0000       1.4
@@ -29,14 +29,18 @@
 
 libecc_la_SOURCES =                            \
        encoder.cc code_metrics.cc              \
-       encoder_convolutional_base.cc           \
-       encoder_convolutional_ic1_ic1.cc
+       encoder_convolutional.cc                \
+       encoder_convolutional_ic1_ic1.cc        \
+       decoder.cc decoder_viterbi.cc           \
+       decoder_viterbi_block_full.cc
 
 noinst_HEADERS =                               \
        encoder.h code_metrics.h                \
-       encoder_convolutional_base.h            \
+       encoder_convolutional.h                 \
        encoder_convolutional_ic1_ic1.h         \
-       decoder.h decoder_viterbi_base.h
+       decoder.h decoder_viterbi.h             \
+       decoder_viterbi_block_full.h            \
+       decoder_viterbi_block_full_ic1.h
 
 # link the library against the c++ standard library
 libecc_la_LIBADD =             \

Index: libecc/code_metrics.cc
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/lib/libecc/code_metrics.cc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- libecc/code_metrics.cc      4 Jul 2006 20:57:32 -0000       1.2
+++ libecc/code_metrics.cc      5 Jul 2006 17:49:58 -0000       1.3
@@ -28,7 +28,8 @@
 #include <iostream>
 #include <math.h>
 
-code_metric_ff::code_metric_ff (pdf_fcn_t pdf_fcn_0_bit,
+code_metric_ff::code_metric_ff
+(pdf_fcn_t pdf_fcn_0_bit,
                                  pdf_fcn_t pdf_fcn_1_bit,
                                  size_t n_samples,
                                  pdf_fcn_io_t min_sample,
@@ -109,7 +110,8 @@
     lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++);
 }
 
-code_metric_fl::code_metric_fl (pdf_fcn_t pdf_fcn_0_bit,
+code_metric_fl::code_metric_fl
+(pdf_fcn_t pdf_fcn_0_bit,
                                  pdf_fcn_t pdf_fcn_1_bit,
                                  size_t n_samples,
                                  pdf_fcn_io_t min_sample,
@@ -152,10 +154,10 @@
   d_metric_table_0_bit.assign (n_samples, 0);
   d_metric_table_1_bit.assign (n_samples, 0);
 
-// get the scale factor for converting from float to sample_precision
-// maps:
-//    logf (pdf_fcn_0_bit->eval (d_min_sample))  ->  l_min_map
-//    logf (pdf_fcn_0_bit->eval (d_max_sample))  ->  l_max_map
+  // get the scale factor for converting from float to sample_precision
+  // maps:
+  //    logf (pdf_fcn_0_bit->eval (d_min_sample))  ->  l_min_map
+  //    logf (pdf_fcn_0_bit->eval (d_max_sample))  ->  l_max_map
 
   metric_t l_min_map = - (1 << (sample_precision - 1));
 
@@ -219,7 +221,8 @@
     lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++);
 }
 
-code_metric_fs::code_metric_fs (pdf_fcn_t pdf_fcn_0_bit,
+code_metric_fs::code_metric_fs
+(pdf_fcn_t pdf_fcn_0_bit,
                                  pdf_fcn_t pdf_fcn_1_bit,
                                  size_t n_samples,
                                  pdf_fcn_io_t min_sample,
@@ -262,10 +265,10 @@
   d_metric_table_0_bit.assign (n_samples, 0);
   d_metric_table_1_bit.assign (n_samples, 0);
 
-// get the scale factor for converting from float to sample_precision
-// maps:
-//    logf (pdf_fcn_0_bit->eval (d_min_sample))  ->  l_min_map
-//    logf (pdf_fcn_0_bit->eval (d_max_sample))  ->  l_max_map
+  // get the scale factor for converting from float to sample_precision
+  // maps:
+  //    logf (pdf_fcn_0_bit->eval (d_min_sample))  ->  l_min_map
+  //    logf (pdf_fcn_0_bit->eval (d_max_sample))  ->  l_max_map
 
   metric_t l_min_map = - (1 << (sample_precision - 1));
 
@@ -329,7 +332,8 @@
     lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++);
 }
 
-code_metric_fb::code_metric_fb (pdf_fcn_t pdf_fcn_0_bit,
+code_metric_fb::code_metric_fb
+(pdf_fcn_t pdf_fcn_0_bit,
                                  pdf_fcn_t pdf_fcn_1_bit,
                                  size_t n_samples,
                                  pdf_fcn_io_t min_sample,
@@ -372,10 +376,10 @@
   d_metric_table_0_bit.assign (n_samples, 0);
   d_metric_table_1_bit.assign (n_samples, 0);
 
-// get the scale factor for converting from float to sample_precision
-// maps:
-//    logf (pdf_fcn_0_bit->eval (d_min_sample))  ->  l_min_map
-//    logf (pdf_fcn_0_bit->eval (d_max_sample))  ->  l_max_map
+  // get the scale factor for converting from float to sample_precision
+  // maps:
+  //    logf (pdf_fcn_0_bit->eval (d_min_sample))  ->  l_min_map
+  //    logf (pdf_fcn_0_bit->eval (d_max_sample))  ->  l_max_map
 
   metric_t l_min_map = - (1 << (sample_precision - 1));
 

Index: libecc/decoder.h
===================================================================
RCS file: /sources/gnuradio/gr-error-correcting-codes/src/lib/libecc/decoder.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- libecc/decoder.h    4 Jul 2006 20:57:32 -0000       1.2
+++ libecc/decoder.h    5 Jul 2006 17:49:58 -0000       1.3
@@ -47,11 +47,17 @@
                         size_t n_bits_to_input,
                         char** out_buf) = 0;
 
+protected:
+  virtual void decode_private (const char** in_buf, char** out_buf) = 0;
+  virtual char get_next_input (const char** in_buf, size_t code_input_n) = 0;
+  virtual void output_bit (char t_out_bit, char** out_buf,
+                          size_t t_output_stream) = 0;
+
   size_t d_frame_size_bits, d_n_code_inputs, d_n_code_outputs;
-  size_t d_max_memory, d_n_enc_bits;
+  size_t d_max_memory, d_n_enc_bits, d_sample_precision;
   memory_t d_max_mem_mask;
   memory_t d_in_buf_ndx, d_out_buf_ndx;
-  memory_t d_in_bit_shift, d_out_bit_shift;
+  memory_t d_out_bit_shift;
   size_t d_n_input_bits_left, d_n_output_bits_left;
 };
 

Index: libecc/encoder_convolutional_ic1_ic1.h
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- libecc/encoder_convolutional_ic1_ic1.h      4 Jul 2006 20:57:32 -0000       
1.1
+++ libecc/encoder_convolutional_ic1_ic1.h      5 Jul 2006 17:49:58 -0000       
1.2
@@ -23,11 +23,13 @@
 #ifndef INCLUDED_ENCODER_CONVOLUTIONAL_IC1_IC1_H
 #define INCLUDED_ENCODER_CONVOLUTIONAL_IC1_IC1_H
 
-#include <vector>
-#include "encoder_convolutional_base.h"
+#include "encoder_convolutional.h"
 
+class encoder_convolutional_ic1_ic1 : public encoder_convolutional
+{
+public:
 /*!
- * class encoder_convolutional_ic1_ic1 : public encoder_convolutional_base
+ * class encoder_convolutional_ic1_ic1 : public encoder_convolutional
  *
  * Encode the incoming streams using a convolutional encoder,
  *     "feedforward" or feedback.  Optional termination, data
@@ -42,9 +44,6 @@
  *     the single output bit per output item.
  */
 
-class encoder_convolutional_ic1_ic1 : public encoder_convolutional_base
-{
-public:
   inline encoder_convolutional_ic1_ic1 (int frame_size_bits,
                                        int n_code_inputs,
                                        int n_code_outputs,
@@ -52,7 +51,7 @@
                                        bool do_termination = true,
                                        int start_memory_state = 0,
                                        int end_memory_state = 0)
-    : encoder_convolutional_base (frame_size_bits,
+    : encoder_convolutional (frame_size_bits,
                                  n_code_inputs,
                                  n_code_outputs,
                                  code_generators,
@@ -68,7 +67,7 @@
                                        bool do_termination = true,
                                        int start_memory_state = 0,
                                        int end_memory_state = 0)
-    : encoder_convolutional_base (frame_size_bits,
+    : encoder_convolutional (frame_size_bits,
                                  n_code_inputs,
                                  n_code_outputs,
                                  code_generators,

Index: gr_decoder_viterbi_block_full.cc
===================================================================
RCS file: gr_decoder_viterbi_block_full.cc
diff -N gr_decoder_viterbi_block_full.cc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ gr_decoder_viterbi_block_full.cc    5 Jul 2006 17:49:58 -0000       1.1
@@ -0,0 +1,208 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio.
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_decoder_viterbi_block_full.h>
+#include <gr_io_signature.h>
+#include <assert.h>
+#include <iostream>
+
+gr_decoder_viterbi_block_full_sptr
+gr_make_decoder_viterbi_block_full
+(int sample_precision,
+ int frame_size_bits,
+ int n_code_inputs,
+ int n_code_outputs,
+ std::vector<int> code_generator,
+ bool do_termination,
+ int start_memory_state,
+ int end_memory_state)
+{
+  return gr_decoder_viterbi_block_full_sptr
+    (new gr_decoder_viterbi_block_full (sample_precision,
+                                       frame_size_bits,
+                                       n_code_inputs,
+                                       n_code_outputs,
+                                       code_generator,
+                                       do_termination,
+                                       start_memory_state,
+                                       end_memory_state));
+}
+
+gr_decoder_viterbi_block_full_sptr
+gr_make_decoder_viterbi_block_full
+(int sample_precision,
+ int frame_size_bits,
+ int n_code_inputs,
+ int n_code_outputs,
+ std::vector<int> code_generator,
+ std::vector<int> code_feedback,
+ bool do_termination,
+ int start_memory_state,
+ int end_memory_state)
+{
+  return gr_decoder_viterbi_block_full_sptr
+    (new gr_decoder_viterbi_block_full (sample_precision,
+                                       frame_size_bits,
+                                       n_code_inputs,
+                                       n_code_outputs,
+                                       code_generator,
+                                       code_feedback,
+                                       do_termination,
+                                       start_memory_state,
+                                       end_memory_state));
+}
+
+gr_decoder_viterbi_block_full::gr_decoder_viterbi_block_full
+(int sample_precision,
+ int frame_size_bits,
+ int num_input_streams,
+ int num_output_streams,
+ std::vector<int> code_generator,
+ bool do_termination,
+ int start_memory_state,
+ int end_memory_state)
+  : gr_block ("decoder_viterbi_block_full",
+             gr_make_io_signature (0, 0, 0),
+             gr_make_io_signature (0, 0, 0))
+{
+  d_encoder = new encoder_convolutional_ic1_ic1 (frame_size_bits,
+                                                n_code_inputs,
+                                                n_code_outputs,
+                                                code_generator,
+                                                do_termination,
+                                                start_memory_state,
+                                                end_memory_state);
+
+  d_n_code_inputs = n_code_inputs;
+  d_n_code_outputs = n_code_outputs;
+
+  d_decoder = new decoder_viterbi_block_ic1_ic1 (sample_precision,
+                                                d_encoder);
+
+  setup_io_signatures (sample_precision);
+}
+
+gr_decoder_viterbi_block_full::gr_decoder_viterbi_block_full
+(int sample_precision,
+ int frame_size_bits,
+ int num_input_streams,
+ int num_output_streams,
+ std::vector<int> code_generator,
+ std::vector<int> code_feedback,
+ bool do_termination,
+ int start_memory_state,
+ int end_memory_state)
+  : gr_block ("decoder_viterbi_block_full",
+             gr_make_io_signature (0, 0, 0),
+             gr_make_io_signature (0, 0, 0))
+{
+  d_encoder = new encoder_convolutional_ic1_ic1 (frame_size_bits,
+                                                n_code_inputs,
+                                                n_code_outputs,
+                                                code_generator,
+                                                code_feedback,
+                                                do_termination,
+                                                start_memory_state,
+                                                end_memory_state);
+
+  d_n_code_inputs = n_code_inputs;
+  d_n_code_outputs = n_code_outputs;
+
+  d_decoder = new decoder_viterbi_block_full_ic1_ic1 (sample_precision,
+                                                     d_encoder);
+
+  setup_io_signatures (sample_precision);
+}
+
+gr_decoder_viterbi_block_full::~gr_decoder_viterbi_block_full
+()
+{
+  delete d_decoder;
+  delete d_encoder;
+}
+
+void
+gr_decoder_viterbi_block_full::setup_io_signatures
+(int sample_precision)
+{
+  if ((sample_precision < 0) | (sample_precision > 32)) {
+    std::cerr << "gr_decoder_viterbi_block_full: "
+      "The provided sample_precision (" << sample_precision <<
+      ") must be between 0 and 32.\n";
+    assert (0);
+  }
+
+  // output signature is always the same:
+  // sizeof (char) with 1 bit per char as the LSB
+
+  set_output_signature (gr_make_io_signature (d_n_code_inputs,
+                                             d_n_code_inputs,
+                                             sizeof (char)));
+
+  // determine the input signature element size
+  size_t l_input_item_size_bytes
+  if (sample_precision == 0) {
+    // float
+    l_input_item_size_bytes = sizeof (float);
+  } else if (sample_precision <= 8) {
+    // use char 
+    l_input_item_size_bytes = sizeof (char);
+  } else if (sample_precision <= 16) {
+    // use short 
+    l_input_item_size_bytes = sizeof (short);
+  } else {
+    // use long 
+    l_input_item_size_bytes = sizeof (long);
+  }
+
+  set_input_signature (gr_make_io_signature (2*d_n_code_outputs,
+                                            2*d_n_code_outputs,
+                                            l_input_item_size_bytes));
+}
+
+void gr_decoder_viterbi_block_full::forecast
+(int noutput_items,
+ gr_vector_int &ninput_items_required)
+{
+  int ninput_items = d_decoder->compute_n_input_bits (noutput_items);
+  size_t ninputs = ninput_items_required.size();
+  for (size_t n = 0; n < ninputs; n++)
+    ninput_items_required[n] = ninput_items;
+}
+
+int
+gr_decoder_viterbi_block_full::general_work
+(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+  size_t 
+
+
+// returns number of items written to each output stream
+  return (t_noutput_items);
+}

Index: gr_decoder_viterbi_block_full.h
===================================================================
RCS file: gr_decoder_viterbi_block_full.h
diff -N gr_decoder_viterbi_block_full.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ gr_decoder_viterbi_block_full.h     5 Jul 2006 17:49:58 -0000       1.1
@@ -0,0 +1,120 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef INCLUDED_GR_DECODER_VITERBI_BLOCK_FULL_H
+#define INCLUDED_GR_DECODER_VITERBI_BLOCK_FULL_H
+
+#include <gr_block.h>
+#include <vector>
+#include <sys/types.h>
+#include <libecc/decoder_viterbi_block_full_ic1.h>
+
+class gr_decoder_viterbi_block_full;
+typedef boost::shared_ptr<gr_decoder_viterbi_block_full>
+gr_decoder_viterbi_block_full_sptr;
+
+gr_decoder_viterbi_block_full_sptr gr_make_decoder_viterbi_block_full
+(int frame_size_bits,
+ int n_code_inputs,
+ int n_code_outputs,
+ std::vector<int> code_generator,
+ bool do_termination = true,
+ int start_memory_state = 0,
+ int end_memory_state = 0);
+
+/*!
+ * \brief Decode the incoming streams using a Viterbi-style decoder
+ *
+ * input: encoded data as soft symbols, either as individual
+ *     streams or mux'ed into 1 stream.
+ *
+ * output: stream(s) of user-defined element size.
+ */
+
+class gr_decoder_viterbi_block_full : public gr_block
+{
+  friend gr_decoder_viterbi_block_full_sptr
+  gr_make_decoder_viterbi_block_full (int frame_size_bits,
+                                          int n_code_inputs,
+                                          int n_code_outputs,
+                                          std::vector<int> code_generator,
+                                          bool do_termination = true,
+                                          int start_memory_state = 0,
+                                          int end_memory_state = 0);
+/*
+ * frame_size_bits: if == 0, then do streaming decoding (infinite
+ *     trellis); otherwise this is the block size to decode before
+ *     terminating the trellis.
+ *
+ * code_generator: vector of integers (32 bit) representing the code
+ *     to be implemented in octal form.  E.g. "04" in binary is "100",
+ *     which would be "D^2" for code generation.  "06" == 110b == "D^2 + D"
+ *  ==> The vector is listed in order for each input stream, so if there
+ *     are 2 input streams (I1, I2) [specified in "n_code_inputs"]
+ *     and 2 output streams (O1, O2) [specified in "n_code_outputs"],
+ *     then the vector would be the code generator for:
+ *       [I1->O1, I1->O2, I2->O1, I2->O2]
+ *     with each element being the octal representation of the code.
+ *
+ * do_termination is valid only if frame_size_bits != 0, and defines
+ *     whether or not to to trellis termination.
+ *
+ * do_mux_input: is true, then the one input stream will be
+ *     interpreted as the multiplexing all of the input bits.  For
+ *     example for a 3 input decoder, the input stream would be
+ *     [I1[k], I2[k], I3[k], I1[k+1], I2[k+1], ...], where "k" is the
+ *     input sample time, and "I1" through "I3" are the 3 input
+ *     streams.
+ *
+ * n_code_inputs: the number of decoder-input (encoder-output)
+ *     streams, no matter if separate or mux'ed
+ *
+ * n_code_outputs: the number of decoder-output (encoder-input) streams
+ */
+
+  gr_decoder_viterbi_block_full (int frame_size_bits,
+                                int n_code_inputs,
+                                int n_code_outputs,
+                                std::vector<int> code_generator,
+                                bool do_termination = true,
+                                int start_memory_state = 0,
+                                int end_memory_state = 0);
+
+public:
+  ~gr_decoder_viterbi_block_full ();
+
+  virtual void forecast (int noutput_items,
+                        gr_vector_int &ninput_items_required);
+
+  virtual 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:
+  int d_n_code_inputs, d_n_code_outputs;
+
+  decoder* d_decoder;
+  encoder* d_encoder;
+};
+
+#endif /* INCLUDED_GR_DECODER_VITERBI_BLOCK_FULL_H */

Index: gr_decoder_viterbi_block_full.i
===================================================================
RCS file: gr_decoder_viterbi_block_full.i
diff -N gr_decoder_viterbi_block_full.i
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ gr_decoder_viterbi_block_full.i     5 Jul 2006 17:49:58 -0000       1.1
@@ -0,0 +1,43 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,decoder_viterbi_block_soft_full);
+
+gr_decoder_viterbi_block_soft_full_sptr
+gr_make_decoder_viterbi_block_soft_full (int frame_size_bits,
+                                        int n_code_inputs,
+                                        int n_code_outputs,
+                                        std::vector<int> code_generator,
+                                        bool do_termination,
+                                        int start_memory_state,
+                                        int end_memory_state);
+
+class gr_decoder_viterbi_block_soft_full : public gr_block
+{
+  gr_decoder_viterbi_block_soft_full (int frame_size_bits,
+                                     int n_code_inputs,
+                                     int n_code_outputs,
+                                     std::vector<int> code_generator,
+                                     bool do_termination,
+                                     int start_memory_state,
+                                     int end_memory_state);
+};

Index: libecc/decoder.cc
===================================================================
RCS file: libecc/decoder.cc
diff -N libecc/decoder.cc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libecc/decoder.cc   5 Jul 2006 17:49:58 -0000       1.1
@@ -0,0 +1,104 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <decoder.h>
+#include <assert.h>
+#include <iostream>
+
+#define DO_PRINT_DEBUG 1
+
+#if DO_PRINT_DEBUG
+#include <mld/n2bs.h>
+#endif
+
+size_t
+decoder::decode
+(const char** in_buf,
+ char** out_buf,
+ size_t n_bits_to_output)
+{
+// set the class-internal number of input and
+// output bits left to decode
+  size_t saved_n_input_bits;
+  saved_n_input_bits = d_n_input_bits_left =
+    compute_n_input_bits (n_bits_to_output);
+  d_n_output_bits_left = n_bits_to_output;
+
+// call the private decode function
+  decode_private (in_buf, out_buf);
+
+#ifdef DO_PRINT_DEBUG
+  std::cout << "n_input_bits_used = " <<
+    (saved_n_input_bits - d_n_input_bits_left) << '\n';
+  std::cout << "n_output_bits_used = " <<
+    (n_bits_to_output - d_n_output_bits_left) << '\n';
+
+  assert (d_out_buf_ndx == n_bits_to_output);
+#endif
+
+// return the actual number of input bits used
+  return (saved_n_input_bits - d_n_input_bits_left);
+}
+
+/*
+ * decode a certain number of input bits
+ *
+ * the 'in_buf' and 'out_buf' must have enough memory to handle the
+ * number of input and output bits; no error checking is done!
+ *
+ * n_bits_to_input: is the number of input bits per input stream to decode
+ *
+ * returns the number of actual bits written to the output stream(s)
+ */
+
+size_t
+decoder::decode
+(const char** in_buf,  
+ size_t n_bits_to_input,
+ char** out_buf)
+{
+// set the class-internal number of input and
+// output bits left to decode
+  size_t saved_n_output_bits;
+  saved_n_output_bits = d_n_output_bits_left =
+    compute_n_output_bits (n_bits_to_input);
+  d_n_input_bits_left = n_bits_to_input;
+
+// call the private decode function
+  decode_private (in_buf, out_buf);
+
+#ifdef DO_PRINT_DEBUG
+  std::cout << "n_input_bits_used = " <<
+    (n_bits_to_input - d_n_input_bits_left) << '\n';
+  std::cout << "n_output_bits_used = " <<
+    (saved_n_output_bits - d_n_output_bits_left) << '\n';
+
+  assert (d_in_buf_ndx == n_bits_to_input);
+#endif
+
+// return the actual number of input bits used
+  return (saved_n_output_bits - d_n_output_bits_left);
+}

Index: libecc/decoder_viterbi.cc
===================================================================
RCS file: libecc/decoder_viterbi.cc
diff -N libecc/decoder_viterbi.cc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libecc/decoder_viterbi.cc   5 Jul 2006 17:49:58 -0000       1.1
@@ -0,0 +1,1481 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <decoder_viterbi.h>
+#include <assert.h>
+#include <iostream>
+
+const int g_max_frame_size_bits = 10000000;
+const int g_max_num_streams = 10;
+const int g_num_bits_per_byte = 8;
+
+#define DO_TIME_THOUGHPUT 0
+#define DO_PRINT_DEBUG_INST 0
+#define DO_PRINT_DEBUG_INST_0 0
+#define DO_PRINT_DEBUG_INST_1 0
+#define DO_PRINT_DEBUG_INST_2 0
+#define DO_PRINT_DEBUG_FSM 0
+#define DO_PRINT_DEBUG_INIT 0
+#define DO_PRINT_DEBUG_UP 0
+#define DO_PRINT_DEBUG_UP_0 0
+#define DO_PRINT_DEBUG_UP_1 0
+#define DO_PRINT_DEBUG_MIDDLE 0
+#define DO_PRINT_DEBUG_MIDDLE_0 0
+#define DO_PRINT_DEBUG_MIDDLE_1 0
+#define DO_PRINT_DEBUG_TERM 0
+#define DO_PRINT_DEBUG_TERM_1 0
+#define DO_PRINT_DEBUG_OUTPUT 0
+#define DO_PRINT_DEBUG_OUTPUT_0 0
+#define DO_PRINT_DEBUG_EXIT 0
+#define DO_PRINT_DEBUG 0
+
+#if DO_TIME_THOUGHPUT
+#include <mld/mld_timer.h>
+#endif
+#if DO_PRINT_DEBUG
+#include <mld/n2bs.h>
+#endif
+
+decoder_viterbi::decoder_viterbi
+(int sample_precision,
+ int frame_size_bits,
+ int n_code_inputs,
+ int n_code_outputs,
+ std::vector<int> &code_generators,
+ bool do_termination = true,
+ int start_memory_state = 0,
+ int end_memory_state = 0)
+{
+  // make sure the sample precitions makes sense
+
+  if ((sample_precision < 0) | (sample_precision > 32)) {
+    std::cerr << "decoder_viterbi: "
+      "Requested sample_precision (" << sample_precision <<
+      "must be between 0 and 32.\n";
+    assert (0);
+  }
+
+  // the rest is handled by the encoder, but which encoder to use?
+
+
+
+  // make sure the frame length makes sense, #1 - more later
+
+  if (frame_size_bits > g_max_frame_size_bits) {
+    std::cerr << "decoder_viterbi: " <<
+      "Requested frame length (" << frame_size_bits <<
+      " bits) must be at most " << g_max_frame_size_bits << " bits.\n";
+    assert (0);
+  }
+
+// check to make sure the number of input streams makes sense
+  if ((n_code_inputs <= 0) | (n_code_inputs > g_max_num_streams)) {
+    std::cerr << "gr_decoder_viterbi_block_soft_full: " <<
+      "Requested number of input streams (" <<
+      n_code_inputs << ") must be between 1 and " <<
+      g_max_num_streams << ".\n";
+    assert (0);
+  }
+
+// check to make sure the number of output streams makes sense
+  if ((n_code_outputs <= 0) | (n_code_outputs > g_max_num_streams)) {
+    std::cerr << "gr_decoder_viterbi_block_soft_full: " <<
+      "Requested number of output streams (" <<
+      n_code_outputs << ") must be between 1 and " <<
+      g_max_num_streams << ".\n";
+    assert (0);
+  }
+
+// make sure the code_generator is the correct length
+  if (code_generators.size () !=
+      ((size_t)(n_code_inputs * n_code_outputs))) {
+    std::cerr << "gr_decoder_viterbi_block_soft_full: " <<
+      "Number of code generator entries (" << code_generators.size () <<
+      ") is not equal to the product of the number of input and output" <<
+      " streams (" << (n_code_inputs * n_code_outputs) << ").\n";
+    assert (0);
+  }
+
+// create the class frame variables
+  d_frame_size_bits = frame_size_bits;
+  d_out_stream_el_size_bytes = out_stream_el_size_bytes;
+  d_n_code_inputs = n_code_inputs;
+  d_n_code_outputs = n_code_outputs;
+  d_do_streaming = (frame_size_bits == 0);
+  d_do_termination = (d_do_streaming == true) ? false : do_termination;
+  d_do_mux_inputs = do_mux_inputs;
+
+// allocate the vectors for doing the encoding.  use 32-bit int's
+// actual bits to represent memory and the code, as it makes the
+// operations quite simple the state vectors.
+// code generates are for each I/O combination
+
+  d_code_generators.resize (d_n_code_inputs * d_n_code_outputs, 0);
+
+// check the input code_generator for correctness & find the memory order
+// t_max_mem will be the mamimum number of memories used by the generator
+// t_code_ndx is a counter over all input code_generator elements
+  int t_max_mem = 0, t_code_ndx = d_code_generators.size() - 1;
+// loop over all input streams first, output streams second
+  for (int n = d_n_code_outputs - 1; n >= 0; n--) {
+    int t_all_inputs_zero = 0;
+    for (int m = d_n_code_inputs - 1; m >= 0; m--) {
+      int t_in_code = code_generators[t_code_ndx];
+      t_all_inputs_zero |= t_in_code;
+      int t_code_mem = 0;
+// find the memory requirement for this code generator
+      while (t_in_code != 0) {
+       t_in_code >>= 1;
+       t_code_mem++;
+      }
+      if (t_code_mem > t_max_mem)
+       t_max_mem = t_code_mem;
+// store in d_code_generators in output-first ordering
+      d_code_generators[(m*d_n_code_outputs) + n] =
+       code_generators[t_code_ndx--];
+    }
+    if (t_all_inputs_zero == 0) {
+      std::cerr << "gr_decoder_viterbi_block_soft_full: " <<
+       "At least 1 generator code for encode-output " << n+1 <<
+       " must be non-0.\n";
+      assert (0);
+    }
+  }
+
+// store the maximum memory order (e.g. "2" -> D^2)
+  d_max_memory = t_max_mem - 1;
+
+// make sure the frame length makes sense, #2
+  if (d_frame_size_bits < d_max_memory) {
+    std::cerr << "gr_decoder_viterbi_block_soft_full: " <<
+      "Requested frame length (" << d_frame_size_bits <<
+      " bit" << (d_frame_size_bits > 1 ? "s" : "") <<
+      ") must be at least 1 memory length (" << d_max_memory <<
+      " bit" << (d_max_memory > 1 ? "s" : "") <<
+      " for this code).\n";
+    assert (0);
+  }
+
+// NOTE: d_n_states is a 'u_long', and thus is quite limited in terms
+// of max memory and # of input streams to 2^32 states
+// This is OK, since that many states would be impossibly slow to decode!
+// might make this a "long long" (64 bits) in the future
+  d_n_states = 1 << (d_max_memory * d_n_code_inputs);
+  d_n_input_combinations = 1 << d_n_code_inputs;
+
+#if DO_PRINT_DEBUG_INST_0
+  std::cout << "Init:\n" <<
+    "d_frame_size_bits          = " << d_frame_size_bits << "\n" <<
+    "d_out_stream_el_size_bytes = " << d_out_stream_el_size_bytes << "\n" <<
+    "d_n_code_inputs            = " << d_n_code_inputs << "\n" <<
+    "d_n_code_outputs           = " << d_n_code_outputs << "\n" <<
+    "d_do_streaming             = " <<
+    ((d_do_streaming == true) ? "true" : "false") << "\n" <<
+    "d_do_termination           = " <<
+    ((d_do_termination == true) ? "true" : "false") << "\n" <<
+    "d_do_mux_inputs            = " <<
+    ((d_do_mux_inputs == true) ? "true" : "false") << "\n" <<
+    "d_max_memory               = " << d_max_memory << "\n" <<
+    "d_n_states                 = " << d_n_states << "\n" <<
+    "d_n_input_combinations     = " << d_n_input_combinations << "\n";
+#endif
+
+// leave the output multiple at 1 (element); will save any incomplete
+// output data (int's) in "d_save_buffer"; all input data will be consumed
+
+// create the correct input signature
+  int t_n_input_streams = ((d_do_mux_inputs == true) ?
+                          1 : n_code_outputs);
+
+  set_input_signature (gr_make_io_signature (t_n_input_streams,
+                                            t_n_input_streams,
+                                            sizeof (float)));
+// create the correct output signature
+  set_output_signature (gr_make_io_signature (n_code_inputs,
+                                             n_code_inputs,
+                                             d_out_stream_el_size_bytes));
+#if DO_PRINT_DEBUG_INST_0
+  std::cout <<
+    "input_signature            = [" << t_n_input_streams << ", " <<
+    t_n_input_streams << ", " << sizeof (float) << "]\n" <<
+    "output_signature           = [" << n_code_outputs << ", " <<
+    n_code_outputs << ", " << d_out_stream_el_size_bytes << "]\n";
+#endif
+
+// always start the fsm in the "init" state
+  d_fsm = fsm_dec_init;
+
+// create a vector of indexes to states when doing "up" or "termination";
+  d_up_term_states_ndx[0] = new size_t [d_n_states];
+  d_up_term_states_ndx[1] = new size_t [d_n_states];
+
+// create the traceback buffers
+// get the total number of out bits per stream
+  d_n_total_input_bits_per_stream = d_frame_size_bits;
+  if (d_do_termination == true)
+    d_n_total_input_bits_per_stream += d_max_memory;
+  d_n_traceback_els = d_n_total_input_bits_per_stream + 1;
+// create the output buffers:
+// this is a 2d matrix structure, where the first dimension
+// is the number of output bits; the second dimension is
+// the number of states.
+// When doing full frames (no tau), each bit-time's state's traceback
+// contains just the pointer to the previous bit-time's state's traceback
+// as well as the inputs for that connection.
+// No further work is required because each reverse-path is unique
+// once a given end-bit-time's state is determined to be "the one"
+  traceback_t_hdl t_out_buf =
+    d_out_buf = new traceback_t_ptr [d_n_traceback_els];
+  for (size_t n = d_n_traceback_els; n > 0; n--) {
+    (*t_out_buf++) = new traceback_t [d_n_states];
+  }
+
+  // create the save buffers
+  char** t_save_buffer = d_save_buffer = new char* [d_n_code_inputs];
+  size_t t_n_out_bytes = ((d_frame_size_bits / g_num_bits_per_byte) +
+                         ((d_frame_size_bits % g_num_bits_per_byte) ? 1 : 0));
+  for (size_t n = 0; n < d_n_code_inputs; n++) {
+    (*t_save_buffer++) = new char [t_n_out_bytes];
+  }
+
+// reset the number of saved bits
+  d_n_saved_bits_start_ndx = d_n_saved_bits = 0;
+
+// setup the internal structures for exiting and entering states
+
+#if DO_PRINT_DEBUG_INST_0
+  std::cout <<
+    "d_n_total in bits / stream = " << d_n_total_input_bits_per_stream << "\n" 
<<
+    "d_n_traceback_els          = " << d_n_traceback_els << "\n" <<
+    "t_n_out_bytes / stream     = " << t_n_out_bytes << "\n";
+#endif
+
+// Find the approximate output rate / input rate
+// each input item produces 1 bit of an output item w/o termination
+  double t_rel_rate = (double)(d_out_stream_el_size_bytes * 
g_num_bits_per_byte);
+  if (d_do_termination == true) {
+// include termination bits
+    t_rel_rate *= (((double) d_frame_size_bits) /
+                  ((double) d_n_total_input_bits_per_stream));
+  }
+// Set the approximate output rate / input rate
+  set_relative_rate (t_rel_rate);
+
+// 'new' everything first; no connections yet
+  state_t_ptr t_state = d_states[0] = new state_t [d_n_states];
+  for (size_t n = d_n_states; n > 0; n--, t_state++) {
+    connection_t_ptr t_connection = t_state->d_connections
+      = new connection_t [d_n_input_combinations];
+    for (size_t m = d_n_input_combinations; m > 0; m--, t_connection++) {
+      t_connection->d_output_bits = new float [d_n_code_outputs];
+    }
+  }
+
+// 'new' everything first; no connections yet
+  t_state = d_states[1] = new state_t [d_n_states];
+  for (size_t n = d_n_states; n > 0; n--, t_state++) {
+    connection_t_ptr t_connection = t_state->d_connections
+      = new connection_t [d_n_input_combinations];
+    for (size_t m = d_n_input_combinations; m > 0; m--, t_connection++) {
+      t_connection->d_output_bits = new float [d_n_code_outputs];
+    }
+  }
+
+// temporary memory and mask for output bit computations
+  size_t t_memory[d_n_code_inputs];
+  size_t t_memory_mask = ((2 << d_max_memory) - 1) ^ 1;
+
+#if DO_PRINT_DEBUG
+  size_t t_state_print_bits = (d_max_memory * d_n_code_inputs) + 1;
+  size_t t_mem_print_bits = d_max_memory + 2;
+
+  std::cout << "Setting States and Connections\n";
+#endif
+
+// loop over all possible memory states
+  state_t_ptr t_state0 = d_states[0];
+  state_t_ptr t_state1 = d_states[1];
+  for (size_t n = 0; n < d_n_states; n++, t_state0++, t_state1++) {
+#if DO_PRINT_DEBUG_INST_1
+    std::cout << "Starting state # " << n << " == " <<
+      n2bs (n, t_state_print_bits) << "\n";
+#endif
+// retrieve the memory values for this state
+// probably a faster way to do this, but since this is
+// executed only upon instantiation, whatever.
+    size_t* t_mem_ptr = t_memory;
+    for (size_t p = 0; p < d_n_code_inputs; p++) {
+      int t_mem = state_get_from (n, p, d_max_memory);
+#if DO_PRINT_DEBUG_INST_1
+      std::cout << "s_g_f (" <<
+       n2bs (n, t_state_print_bits) << ", " <<
+       p << ", " << d_max_memory << ") => t_m = " <<
+       n2bs (t_mem, t_mem_print_bits) << "\n";
+#endif
+// shift them by 1 (and mask) to make updating for all inputs simple
+      (*t_mem_ptr++) = t_mem << 1;
+#if DO_PRINT_DEBUG_INST_1
+      std::cout << "t_m_p[" << p << "] = " <<
+       n2bs (t_mem << 1, t_mem_print_bits) << " == (" <<
+       n2bs (t_mem, t_mem_print_bits) << " << 1)\n";
+#endif
+    }
+
+// loop over all possible input values, 1 bit per input stream
+    connection_t_ptr t_connection0 = t_state0->d_connections;
+    connection_t_ptr t_connection1 = t_state1->d_connections;
+    for (size_t q = 0; q < d_n_input_combinations;
+        q++, t_connection0++, t_connection1++) {
+#if DO_PRINT_DEBUG_INST_1
+      std::cout << "Starting inputs " << q << " == " <<
+       n2bs (q, d_n_code_inputs + 1) << "\n";
+#endif
+
+// update memory for this set of inputs
+      t_mem_ptr = t_memory;
+      size_t t_this_input = q;
+
+// loop over all code inputs, and update just the single input bit
+      for (size_t r = d_n_code_inputs; r > 0; r--) {
+       int t_mem = (*t_mem_ptr) & t_memory_mask;
+#if DO_PRINT_DEBUG_INST_1
+       std::cout << "t_m = " << n2bs (t_mem, t_mem_print_bits) <<
+         " == " << n2bs (*t_mem_ptr, t_mem_print_bits) <<
+         " & " << n2bs (t_memory_mask, t_mem_print_bits) << "\n";
+#endif
+       (*t_mem_ptr++) = t_mem | (t_this_input & 1);
+#if DO_PRINT_DEBUG_INST_1
+       std::cout << "t_m_p[" << (d_n_code_inputs - r) << "] = " <<
+         n2bs (t_mem | (t_this_input & 1), t_mem_print_bits) <<
+         " == t_m | " << (t_this_input & 1) << "\n";
+#endif
+       t_this_input >>= 1;
+      }
+
+// got the updated memory for this particular state & inputs
+// recreate the "to" state from the updated memory
+      t_mem_ptr = t_memory;
+      size_t t_out_state = 0;
+      for (size_t p = 0; p < d_n_code_inputs; p++) {
+#if DO_PRINT_DEBUG_INST_1
+       std::cout << "s_a_t (" <<
+         n2bs (t_out_state, t_state_print_bits) <<
+         ", " << n2bs (*t_mem_ptr, t_mem_print_bits) << ", " << p <<
+         ", " << d_max_memory << ") ==> t_o_s out = ";
+#endif
+       state_add_to (t_out_state, *t_mem_ptr++, p, d_max_memory);
+#if DO_PRINT_DEBUG_INST_1
+       std::cout << n2bs (t_out_state, t_state_print_bits) << "\n";
+#endif
+      }
+
+// get the "to" state pointers from d_states[0] to [1]
+      state_t_ptr t_to_state = &(d_states[1][t_out_state]);
+      t_connection0->d_to = t_to_state;
+      t_connection0->d_to_ndx = t_out_state;
+      float* t_output_bit0 = t_connection0->d_output_bits;
+
+// get the "to" state pointers from d_states[1] to [0]
+      t_to_state = &(d_states[0][t_out_state]);
+      t_connection1->d_to = t_to_state;
+      t_connection1->d_to_ndx = t_out_state;
+      float* t_output_bit1 = t_connection1->d_output_bits;
+
+// determine the ideal output values: loop over all outputs
+      size_t t_vec_ctr = 0;
+      for (size_t s = 0; s < d_n_code_outputs; s++) {
+
+// loop over all inputs, xor'ing the result each time
+       int t_out_result = 0;
+       t_mem_ptr = t_memory;
+       for (size_t t = 0; t < d_n_code_inputs; t++) {
+#if DO_PRINT_DEBUG_INST_1
+         std::cout << "b_i = " << n2bs (t_out_result, t_mem_print_bits) <<
+           ", st[" << t << "] = " << n2bs ((*t_mem_ptr), t_mem_print_bits) <<
+           ", cg[" << t_vec_ctr << "] = " <<
+           n2bs (d_code_generators[t_vec_ctr], t_mem_print_bits) <<
+           ", st[] & cg[] = " << n2bs ((*t_mem_ptr) &
+                                       d_code_generators[t_vec_ctr],
+                                       t_mem_print_bits);
+#endif
+         t_out_result ^= ((*t_mem_ptr++) &
+                          d_code_generators[t_vec_ctr++]);
+#if DO_PRINT_DEBUG_INST_1
+         std::cout << ", b_o = " <<
+           n2bs (t_out_result, t_mem_print_bits) << '\n';
+#endif
+       }
+#if DO_PRINT_DEBUG_INST_1
+       std::cout << "b_r = " << n2bs (t_out_result, t_mem_print_bits);
+#endif
+// sum the number of set bits, mod 2, for the output bit
+       size_t t_out_bit = t_out_result & 1;
+       for (size_t v = d_max_memory; v > 0; v--) {
+         t_out_result >>= 1;
+         t_out_bit ^= (t_out_result & 1);
+       }
+
+// store the result for this particular output stream,
+// converting the bit 1 -> +1.0, and 0 -> -1.0
+        float t_out_value = (float)(((int)(t_out_bit << 1)) - 1);
+       *t_output_bit0++ = t_out_value;
+       *t_output_bit1++ = t_out_value;
+#if DO_PRINT_DEBUG_INST_1
+       std::cout << ", o_v = " << t_out_value << "\n";
+#endif
+
+// finished (for) all output values
+      }
+// finished (for) over all possible input values
+    }
+// finished (for) over all possible states
+  }
+
+// so now d_states is/are completely populated!
+// These make for simple access to looping over all possible inputs or
+// outputs for a given state to determine what the path with the best
+// metric is.
+
+#if DO_PRINT_DEBUG_INST_2
+// loop over all possible memory states
+  std::cout << "State Tables\n";
+  t_state0 = d_states[0];
+  t_state1 = d_states[1];
+  for (size_t n = 0; n < d_n_states; n++, t_state0++, t_state1++) {
+    std::cout << "d_s[0][" << n << "] = " << t_state0 << "\n";
+// loop over all possible input values, 1 bit per input stream
+    connection_t_ptr t_connection0 = t_state0->d_connections;
+    for (size_t q = 0; q < d_n_input_combinations; q++, t_connection0++) {
+      std::cout << "s0[" << n2bs (n, t_state_print_bits) << "][" <<
+       n2bs (q, d_n_code_inputs+1) << "] = " << t_connection0 <<
+       " -> s1[" << n2bs (t_connection0->d_to_ndx, t_state_print_bits) <<
+       "] = " << t_connection0->d_to << "\n";
+    }
+    std::cout << "d_s[1][" << n << "] = " << t_state1 << "\n";
+    connection_t_ptr t_connection1 = t_state1->d_connections;
+    for (size_t q = 0; q < d_n_input_combinations; q++, t_connection1++) {
+      std::cout << "s1[" << n2bs (n, t_state_print_bits) << "][" <<
+       n2bs (q, d_n_code_inputs+1) << "] = " << t_connection1 <<
+       " -> s0[" << n2bs (t_connection1->d_to_ndx, t_state_print_bits) <<
+       "] = " << t_connection1->d_to << "\n";
+    }
+  }
+
+  traceback_t_hdl t_out_bufs = d_out_buf;
+  for (size_t n = 0; n < d_n_traceback_els; n++, *t_out_bufs++) {
+    traceback_t_ptr t_out_buf = *t_out_bufs;
+    for (size_t m = 0; m < d_n_states; m++, t_out_buf++) {
+      std::cout << "tb[" << n << "] = " << t_out_bufs <<
+       ", &tb[" << n << "][" << m << "] = " << (&d_out_buf[n][m]) <<
+       ", tb[" << n << "," << m << "] = " << t_out_buf << "\n";
+    }
+  }
+
+  std::cout << "Done with instantiation.\n";
+#endif
+}
+
+gr_decoder_viterbi_block_soft_full::~gr_decoder_viterbi_block_soft_full
+()
+{
+// reverse over from allocation
+
+  delete [] d_up_term_states_ndx[0];
+  delete [] d_up_term_states_ndx[1];
+
+// delete the state's structures
+  state_t_ptr t_state = d_states[0];
+  for (size_t n = d_n_states; n > 0; n--, t_state++) {
+    connection_t_ptr t_connection = t_state->d_connections;
+    for (size_t m = d_n_input_combinations; m > 0; m--, t_connection++) {
+      delete [] t_connection->d_output_bits;
+    }
+    delete [] t_state->d_connections;
+  }
+  delete [] d_states[0];
+
+  t_state = d_states[1];
+  for (size_t n = d_n_states; n > 0; n--, t_state++) {
+    connection_t_ptr t_connection = t_state->d_connections;
+    for (size_t m = d_n_input_combinations; m > 0; m--, t_connection++) {
+      delete [] t_connection->d_output_bits;
+    }
+    delete [] t_state->d_connections;
+  }
+  delete [] d_states[1];
+
+// delete the save buffer
+  char** t_save_buffer = d_save_buffer;
+  for (size_t n = 0; n < d_n_code_inputs; n++) {
+    delete [] (*t_save_buffer++);
+  }
+  delete [] d_save_buffer;
+
+// delete the output buffer
+  traceback_t_hdl t_out_buf = d_out_buf;
+  for (size_t n = d_n_traceback_els; n > 0; n--) {
+    delete [] (*t_out_buf++);
+  }
+  delete [] d_out_buf;
+}
+
+void gr_decoder_viterbi_block_soft_full::reset_metrics (u_char which)
+{
+  state_t_ptr t_state = d_states[which&1];
+  for (size_t n = d_n_states; n > 0; n--, t_state++) {
+    t_state->d_max_metric = -1e10;
+#if 0
+// probably don't need to do these, try removing them later
+    t_state->d_max_state_ndx = 0;
+    t_state->d_max_input = -1;
+#endif
+  }
+}
+
+void gr_decoder_viterbi_block_soft_full::zero_metrics (u_char which)
+{
+  state_t_ptr t_state = d_states[which&1];
+  for (size_t n = d_n_states; n > 0; n--, t_state++) {
+    t_state->d_max_metric = 0;
+#if 0
+// probably don't need to do these, try removing them later
+    t_state->d_max_state_ndx = -1;
+    t_state->d_max_input = -1;
+#endif
+  }
+}
+
+void gr_decoder_viterbi_block_soft_full::forecast
+(int noutput_items,
+ gr_vector_int &ninput_items_required)
+{
+  int ninput_items = fixed_rate_noutput_to_ninput (noutput_items);
+
+  int ninputs = ninput_items_required.size();
+  for (int n = 0; n < ninputs; n++)
+    ninput_items_required[n] = ninput_items;
+}
+
+/*
+ * Compute the number of input items (soft symbols [floats]) needed to produce
+ * 'noutput' items (elements).  For convolutional decoders, there is 1
+ * bit output per bit input per stream, with the addition of a some
+ * bits for trellis termination if selected.  Without termination,
+ * there is exactly 1:1 input to output (1 symbol in to 1 bit out),
+ * no matter the encoding type.
+ *
+ * if (not terminating), then get the number of output bytes.
+ *
+ * otherwise, find the number of frames (not necessarily and integer),
+ * and then compute the number of input bits (including termination)
+ * required to produce those frames.  Subtract the number of bits
+ * leftover from the previous computation, then find the number of input
+ * elements (soft symbols), ceil'd to make sure there are enough.
+ *
+ * finally, if the input streams are mux'ed, then multiply by the
+ * number of inputs.
+ */
+
+int
+gr_decoder_viterbi_block_soft_full::fixed_rate_noutput_to_ninput
+(int noutput_items)
+{
+  int t_ninput_items = 0;
+  int t_noutput_bits = (noutput_items * d_out_stream_el_size_bytes *
+                        g_num_bits_per_byte) - d_n_saved_bits;
+// if there are enough saved bits, just use those, no inputs required
+  if (t_noutput_bits <= 0)
+    return (t_ninput_items);
+
+// remove any bits already in the decoding trellis
+  if (d_time_count != 0) {
+    int t_time_bits = ((d_time_count > d_frame_size_bits) ? 0 :
+                      d_frame_size_bits - d_time_count);
+    t_noutput_bits -= t_time_bits;
+    t_ninput_items += t_time_bits;
+  }
+// if completing this trellis doesn't create enough outputs ...
+  if (t_noutput_bits > 0) {
+
+// there is a 1:1 ratio between input symbols and output bits (per
+// stream), except for termination bits which are already taken into
+// account in the total # of input bits per stream class variable;
+// need to round the # output bits to the
+
+// find the number of frames, ceil'd to the next higher integer
+    int t_nframes = (int) ceilf (((float) t_noutput_bits) /
+                                ((float) d_frame_size_bits));
+// find the number of required input bits
+    t_ninput_items += t_nframes * d_n_total_input_bits_per_stream;
+  }
+
+// if doing mux'ing, there are more elements in the single input
+  if (d_do_mux_inputs == true) {
+    t_ninput_items *= d_n_code_outputs;
+  }
+  return (t_ninput_items);
+}
+
+int
+gr_decoder_viterbi_block_soft_full::general_work
+(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+#if DO_TIME_THOUGHPUT
+  struct timeval t_tp;
+  start_timer (&t_tp);
+#endif
+#if DO_PRINT_DEBUG
+  size_t t_state_print_bits = (d_max_memory * d_n_code_inputs) + 1;
+  size_t t_mem_print_bits = d_max_memory + 2;
+#endif
+// setup variables for quicker access
+  const float **in_buf = (const float **) &input_items[0];
+  char **out_buf = (char **) &output_items[0];
+  int t_in_buf_ndx = 0, t_out_buf_ndx = 0;
+  int t_out_bit_shift = 0;
+  int t_ninput_items = fixed_rate_noutput_to_ninput (noutput_items);
+  int t_noutput_bytes = noutput_items * d_out_stream_el_size_bytes;
+
+#if DO_PRINT_DEBUG_INST
+  std::cout << "# output items = " << noutput_items << " (" <<
+    t_noutput_bytes << " Bytes, " << (t_noutput_bytes * g_num_bits_per_byte) <<
+    " bits), # input items = " << t_ninput_items << " Symbols\n";
+  for (size_t n = 0; n < ninput_items.size(); n++) {
+    std::cout << "# input items [" << n << "] = " << ninput_items[n] << "\n";
+  }
+#endif
+
+// put any leftover bits into the output
+  if (d_n_saved_bits != 0) {
+// copy the leftover from the save buffer
+// check to make sure it will all fit
+    size_t t_noutput_bits = t_noutput_bytes * g_num_bits_per_byte;
+    size_t t_n_copy;
+    if (t_noutput_bits < d_n_saved_bits) {
+// asking for fewer bits than available; set to copy
+// just what's being asked for
+      t_n_copy = t_noutput_bytes;
+    } else {
+// asking for at least as many bits as available; set to copy all
+      t_out_buf_ndx = d_n_saved_bits / g_num_bits_per_byte;
+      t_out_bit_shift = d_n_saved_bits % g_num_bits_per_byte;
+      t_n_copy = t_out_buf_ndx + (t_out_bit_shift != 0 ? 1 : 0);
+    }
+// do the copy for all output streams (code inputs)
+// copy starting at save buffer index "start"
+    for (size_t n = 0; n < d_n_code_inputs; n++)
+      bcopy (&(d_save_buffer[n][d_n_saved_bits_start_ndx]),
+            out_buf[n], t_n_copy);
+#if DO_PRINT_DEBUG_INST
+    std::cout << "Copied " << t_n_copy << " Byte" <<
+      (t_n_copy != 1 ? "s" : "") << ": s_b[][" <<
+      d_n_saved_bits_start_ndx << "] => o_b[][0]\n" <<
+      "# saved bits = " << d_n_saved_bits <<
+      ", o_b_ndx = " << t_out_buf_ndx <<
+      ", bit shift = " << t_out_bit_shift << "\n";
+#endif
+//  update the number of saved bits and start
+    if (t_noutput_bits < d_n_saved_bits) {
+// asking for fewer bit than available: update
+// the number of saved bits and their starting index
+      d_n_saved_bits_start_ndx += t_noutput_bytes;
+      d_n_saved_bits -= (t_noutput_bytes * g_num_bits_per_byte);
+#if DO_PRINT_DEBUG_INST
+      std::cout << "Updated # saved bits = " << d_n_saved_bits <<
+       ", index = " << d_n_saved_bits_start_ndx << "\n";
+#endif
+// nothing to consume; return the desired number of output items
+      return (noutput_items);
+    } else {
+      d_n_saved_bits_start_ndx = d_n_saved_bits = 0;
+    }
+  }
+#if DO_PRINT_DEBUG_INST
+  std::cout << "Starting FSM in state: " <<
+    (d_fsm == fsm_dec_init ? "init" :
+     (d_fsm == fsm_dec_doing_up ? "up" :
+      (d_fsm == fsm_dec_doing_middle ? "middle" :
+       (d_fsm == fsm_dec_doing_term ? "term" :
+       (d_fsm == fsm_dec_output ? "output" : "unknown"))))) << "\n";
+#endif
+
+// while there are input items to create
+  while (t_out_buf_ndx < t_noutput_bytes) {
+#if DO_PRINT_DEBUG_FMS
+    std::cout << "Starting 'while': processing " << t_in_buf_ndx << " of " <<
+      t_ninput_items << " items.\nJumping to state '" <<
+      (d_fsm == fsm_dec_init ? "init" :
+       (d_fsm == fsm_dec_doing_up ? "up" :
+       (d_fsm == fsm_dec_doing_middle ? "middle" :
+        (d_fsm == fsm_dec_doing_term ? "term" :
+         (d_fsm == fsm_dec_output ? "output" : "unknown"))))) << "'\n";
+#endif
+// jump to the correct state in the fsm
+    switch (d_fsm) {
+    case fsm_dec_doing_up:
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Starting fsm_dec_doing_up\n";
+#endif
+// set the number of up_down indices
+      size_t t_n_up_down_ndx = 1 << (d_n_code_inputs *
+                                    d_time_count);
+// stay in this state until the correct number of input symbols are
+// reached; exit also if we run out of input symbols to process
+      while ((d_time_count < d_max_memory) &
+            (t_in_buf_ndx < t_ninput_items)) {
+#if DO_PRINT_DEBUG_UP_0
+       std::cout << "Doing 'while' loop:\n" <<
+         "t_n_up_down_ndx    = " << t_n_up_down_ndx << "\n" <<
+         "d_time_count       = " << d_time_count << "\n" <<
+         "d_max_memory       = " << d_max_memory << "\n" <<
+         "t_in_buf_ndx       = " << t_in_buf_ndx << "\n" <<
+         "t_ninput_items     = " << t_ninput_items << "\n";
+#endif
+// use the "from" states, loop over all inputs and compute the metric for
+// each & store it in the "to" state at the end of the connection.
+// no need to compare metrics yet, since none join into any given state
+
+#if 0
+// reset the "to" state's metrics
+// probably don't need to do this; try removing later
+        reset_metrics (d_states_ndx ^ 1);
+#if DO_PRINT_DEBUG_UP
+       std::cout << "Reset Metrics\n";
+#endif
+#endif
+
+// reset the state's index for each set of new inputs
+       size_t* t_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx];
+       size_t* t_next_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx ^ 1];
+// loop over all current stored "up" states
+       for (size_t n = 0; n < t_n_up_down_ndx; n++) {
+         size_t t_state_ndx = *t_state_ndx_ptr++;
+// get a pointer to this state's structure
+         state_t_ptr t_state = &(d_states[d_states_ndx][t_state_ndx]);
+// get the connections for all inputs
+         connection_t_ptr t_connection = t_state->d_connections;
+#if DO_PRINT_DEBUG_UP_0
+         std::cout << "Looping over all 'up' states:\n" <<
+           "n                  = " << n << "\n" <<
+           "t_n_up_down_ndx    = " << t_n_up_down_ndx << "\n" <<
+           "d_states_ndx       = " << d_states_ndx << "\n" <<
+           "t_state_ndx        = " << t_state_ndx << "\n" <<
+           "d_n_input_combs    = " << d_n_input_combinations << "\n" <<
+           "t_state            = " << t_state << "\n" <<
+           "t_connection       = " << t_connection << "\n";
+#endif
+// loop over all possible input values, 1 bit per input stream
+         for (size_t q = 0; q < d_n_input_combinations; q++, t_connection++) {
+// find the "to" state for this connection
+           state_t_ptr t_to_state = t_connection->d_to;
+// get the output bits for this connection
+           float* t_output_bit = t_connection->d_output_bits;
+// start with this state's metric
+           float t_metric = t_state->d_max_metric;
+#if DO_PRINT_DEBUG_UP_0
+           std::cout <<
+             "to state index     = " << t_connection->d_to_ndx << "\n" <<
+             "current metric     = " << t_metric << "\n";
+#endif
+           if (d_do_mux_inputs == true) {
+// if using mux'ed input streams, handle differently
+              const float* t_in_buf = &(in_buf[0][t_in_buf_ndx]);
+// loop over all encoder-output values
+             for (size_t r = d_n_code_outputs; r > 0; r--) {
+#if DO_PRINT_DEBUG_UP
+               std::cout << "in_sym = " << *t_in_buf << ", code_out_bit = " <<
+                 *t_output_bit << " ==> metric -> ";
+#endif
+               t_metric += ((*t_in_buf++) * (*t_output_bit++));
+#if DO_PRINT_DEBUG_UP
+               std::cout << t_metric << "\n";
+#endif
+             }
+           } else {
+// loop over all encoder-output values
+             for (size_t r = 0; r < d_n_code_outputs; r++) {
+#if DO_PRINT_DEBUG_UP
+               std::cout << "in_sym = " << in_buf[r][t_in_buf_ndx] <<
+                 ", code_out_bit = " << *t_output_bit << " ==> metric -> ";
+#endif
+               t_metric += (in_buf[r][t_in_buf_ndx] * (*t_output_bit++));
+#if DO_PRINT_DEBUG_UP
+               std::cout << t_metric << "\n";
+#endif
+             }
+           }
+// get the "to" state index
+           size_t t_to_ndx = t_connection->d_to_ndx;
+// store the metric in the "to" state; should not have been used before
+           t_to_state->d_max_metric = t_metric;
+// add the "to" state index to the "up" state list
+           *t_next_state_ndx_ptr++ = t_to_ndx;
+// update the traceback structure, depending on which variety it is
+// doing full trellis before decoding; use d_out_buf
+// simple: get the current state & output state
+           traceback_t_ptr t_out_buf = &(d_out_buf[d_time_count]
+                                         [t_state_ndx]);
+           traceback_t_ptr t_next_out_buf = &(d_out_buf[d_time_count+1]
+                                              [t_to_ndx]);
+#if DO_PRINT_DEBUG_UP_1
+           std::cout << "d_o_b[" << d_time_count+1 << "] => d_o_b prev\n" <<
+             "ndx[" << n << "] == " << t_state_ndx <<
+             ", s[" << n2bs(t_state_ndx,t_state_print_bits) <<
+             "]: max_ndx = " <<
+             n2bs(t_state->d_max_state_ndx,t_state_print_bits) <<
+             ", input = " << n2bs(q, d_n_code_inputs+1) <<
+             ": " << t_next_out_buf << " => " << t_out_buf << "\n";
+#endif
+// and connect output to the current, set inputs on output
+           t_next_out_buf->d_prev = t_out_buf;
+           t_next_out_buf->d_inputs = q;
+// finished (for) this input value
+         }
+// finished (for) this "up_term" state
+       }
+// increment the in_buf index, depending on mux'ing or not
+       t_in_buf_ndx += (d_do_mux_inputs == false) ? 1 : d_n_code_outputs;
+// increment the time counter
+        d_time_count++;
+// update the number of "up_term" states
+        d_up_term_ndx ^= 1;
+// increase the number of using states
+        t_n_up_down_ndx <<= d_n_code_inputs;
+// change which d_states' index to use as starting
+        d_states_ndx ^= 1;
+// finished (while) staying in this fsm state or not
+      }
+// if reached the end of doing the "up" part of the trellis,
+// switch states into the middle
+      if (d_time_count == d_max_memory) {
+#if DO_PRINT_DEBUG_FSM
+       std::cout << "Setting FSM to fsm_dec_doing_middle\n";
+#endif
+        d_fsm = fsm_dec_doing_middle;
+      }
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Exited fsm_dec_doing_up\n";
+#endif
+      break;
+    case (fsm_dec_doing_middle):
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Entered fsm_dec_doing_middle\n";
+#endif
+// stay in this state until the correct number of input symbols is
+// reached (if doing block coding), or until there are no more input
+// symbols to parse
+      while (((d_frame_size_bits != 0) &
+             (d_time_count < d_frame_size_bits) &
+             (t_in_buf_ndx < t_ninput_items)) |
+            ((d_frame_size_bits == 0) &
+             (t_in_buf_ndx < t_ninput_items))) {
+// use all states, loop over all inputs, compute the metric for
+// each; compare the current metric with all previous stored metric in the
+// endpoint of the connection to find the highest one.
+
+// reset the "to" state's metrics
+        reset_metrics (d_states_ndx ^ 1);
+// get the state's index for each set of new inputs
+       state_t_ptr t_state = d_states[d_states_ndx];
+#if DO_PRINT_DEBUG_MIDDLE
+       std::cout << "Time Count " << (d_time_count+1) << " of " <<
+         d_frame_size_bits << "\n" <<
+         "d_states_ndx = " << d_states_ndx << "\n";;
+#endif
+// loop over all current states
+       for (size_t n = 0; n < d_n_states; n++, t_state++) {
+// loop over all possible input values, 1 bit per input stream
+         connection_t_ptr t_connection = t_state->d_connections;
+#if DO_PRINT_DEBUG_MIDDLE_0
+         std::cout << "Looping over all 'middle' states: " <<
+           n << " of " << d_n_states << "\n";
+#endif
+         for (size_t q = 0; q < d_n_input_combinations; q++, t_connection++) {
+#if DO_PRINT_DEBUG_MIDDLE_0
+           std::cout << "Input = " << n2bs(q, d_n_code_inputs+1) << "\n";
+#endif
+// start with this state's metric
+           float t_metric = t_state->d_max_metric;
+// get the "to" state
+            state_t_ptr t_to_state = t_connection->d_to;
+// get that state's metric
+            float t_to_metric = t_to_state->d_max_metric;
+// see if the computation is even needed;
+// maximum change is d_n_code_outputs if all bits match exactly
+            if ((t_to_metric - t_metric) > ((float) 2*d_n_code_outputs)) {
+#if DO_PRINT_DEBUG_MIDDLE_0
+             std::cout << "!not computing metric!\n";
+#endif
+              continue;
+           }
+// metrics are close enough; do the computation and the compare
+// get the output bits for this connection
+           float* t_output_bit = t_connection->d_output_bits;
+           if (d_do_mux_inputs == true) {
+// if using mux'ed input streams, handle differently
+              const float* t_in_buf = &(in_buf[0][t_in_buf_ndx]);
+// loop over all encoder-output values
+             for (size_t r = d_n_code_outputs; r > 0; r--) {
+#if DO_PRINT_DEBUG_MIDDLE_0
+               std::cout << "in_sym = " << *t_in_buf << ", code_out_bit = " <<
+                 *t_output_bit << " ==> metric -> ";
+#endif
+               t_metric += ((*t_in_buf++) * (*t_output_bit++));
+#if DO_PRINT_DEBUG_MIDDLE_0
+               std::cout << t_metric << "\n";
+#endif
+             }
+           } else {
+// loop over all encoder-output values
+             for (size_t r = 0; r < d_n_code_outputs; r++) {
+#if DO_PRINT_DEBUG_MIDDLE_0
+               std::cout << "in_sym = " << in_buf[r][t_in_buf_ndx] <<
+                 ", code_out_bit = " << *t_output_bit << " ==> metric -> ";
+#endif
+               t_metric += (in_buf[r][t_in_buf_ndx] * (*t_output_bit++));
+#if DO_PRINT_DEBUG_MIDDLE_0
+               std::cout << t_metric << "\n";
+#endif
+             }
+           }
+// done with this input value; compare old and new metrics
+            if (t_metric > t_to_metric) {
+#if DO_PRINT_DEBUG_MIDDLE
+             std::cout << "New Metric to s[" <<
+               n2bs (t_connection->d_to_ndx,t_state_print_bits) << "]: ";
+             if (t_to_state->d_max_metric == -1e10) {
+               std::cout << "setting to ";
+             } else {
+               std::cout << "was s[" <<
+                 n2bs(t_to_state->d_max_state_ndx,t_state_print_bits) <<
+                 "]i[" << n2bs (t_to_state->d_max_input, d_n_code_inputs+1) <<
+                 "]@ " << t_to_state->d_max_metric << "  now ";
+             }
+             std::cout << "s[" << n2bs(n,t_state_print_bits) << "] i[" <<
+               n2bs (q, d_n_code_inputs+1) << "]@ " << t_metric << "\n";
+#endif
+// new metric is better; copy that info into the "to" state
+              t_to_state->d_max_metric = t_metric;
+              t_to_state->d_max_state_ndx = n;
+              t_to_state->d_max_input = q;
+            }
+// finished (for) this input value
+         }
+// finished (for) this state
+       }
+// done with all states and all inputs; now update the traceback structure
+// change which d_states' index to use as starting
+        d_states_ndx ^= 1;
+// get the state's index for the "to" set of new inputs to get the
+// "max" stuff from
+       t_state = d_states[d_states_ndx];
+// update the traceback structure
+// loop over all current states
+       traceback_t_ptr t_prev_out_bufs = d_out_buf[d_time_count];
+       traceback_t_ptr t_out_bufs = d_out_buf[d_time_count+1];
+#if DO_PRINT_DEBUG_MIDDLE_1
+       std::cout << "d_o_b[" << d_time_count+1 << "] => d_o_b prev\n";
+#endif
+       for (size_t n = d_n_states; n > 0; n--, t_state++) {
+// simple: get the current state & output state
+// and connect output to the current, set inputs on output
+         traceback_t_ptr t_out_buf = t_out_bufs++;
+         traceback_t_ptr t_prev_out_buf =
+           &(t_prev_out_bufs[t_state->d_max_state_ndx]);
+#if DO_PRINT_DEBUG_MIDDLE_1
+         std::cout << "s[" << n2bs(d_n_states-n,t_state_print_bits) <<
+           "]: max_ndx = " <<
+           n2bs(t_state->d_max_state_ndx,t_state_print_bits) <<
+           ", input = " << n2bs(t_state->d_max_input, d_n_code_inputs+1) <<
+           ": " << t_out_buf << " => " << t_prev_out_buf << "\n";
+#endif
+         t_out_buf->d_prev = t_prev_out_buf;
+         t_out_buf->d_inputs = t_state->d_max_input;
+// finished doing this state
+       }
+// increment the in_buf index, depending on mux'ing or not
+       t_in_buf_ndx += (d_do_mux_inputs == false) ? 1 : d_n_code_outputs;
+// increment the time counter
+        d_time_count++;
+// finished (while) staying in this fsm state or not
+      }
+      if ((d_frame_size_bits != 0) &
+          (d_time_count == d_frame_size_bits)) {
+#if DO_PRINT_DEBUG_FSM
+       std::cout << "Setting FSM to fsm_dec_doing_term\n";
+#endif
+        d_fsm = fsm_dec_doing_term;
+      }
+      break;
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Exited fsm_dec_doing_middle\n";
+#endif
+    case (fsm_dec_doing_term):
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Entered fsm_dec_doing_term\n";
+#endif
+// set the "next" up_down index to the end of their states
+      size_t t_time_count = d_max_memory - (d_time_count - d_frame_size_bits);
+      t_n_up_down_ndx = 1 << (d_n_code_inputs * t_time_count);
+// stay in this state until the correct number of input symbols are
+// reached; exit also if we run out of input symbols to process
+      while ((t_time_count > 0) &
+            (t_in_buf_ndx < t_ninput_items)) {
+#if DO_PRINT_DEBUG_TERM
+       std::cout << "Doing time " << (d_max_memory - t_time_count + 1) <<
+         " of " << d_max_memory << "; starting buf[" << t_in_buf_ndx <<
+         "] of [" << t_ninput_items << "]\n";
+#endif
+// use the "to" states,
+// FIXME: loop over just the "0" inputs
+// and compute the metric for
+// each, compare & store it in the "to" state at the end of the connection.
+
+// reset the "to" state's metrics
+        reset_metrics (d_states_ndx ^ 1);
+// reset the state's index for each set of new inputs
+       size_t* t_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx];
+       size_t* t_next_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx ^ 1];
+// loop over all current stored "term" state indeces
+       for (size_t n = 0; n < t_n_up_down_ndx; n++) {
+         size_t t_state_ndx = *t_state_ndx_ptr++;
+         state_t_ptr t_state = &(d_states[d_states_ndx][t_state_ndx]);
+// loop over just the all 0 input value (d_connections[0])
+         connection_t_ptr t_connection = t_state->d_connections;
+// get the "to" state
+          state_t_ptr t_to_state = t_connection->d_to;
+// start with this state's metric
+          float t_metric = t_state->d_max_metric;
+// get that state's metric
+          float t_to_metric = t_to_state->d_max_metric;
+#if DO_PRINT_DEBUG_TERM
+         std::cout << "Term state " << (n+1) << " of " << t_n_up_down_ndx <<
+           "; using d_s[" << d_states_ndx << "][" <<
+           n2bs(t_state_ndx,t_state_print_bits) << "]\n";
+#endif
+// see if the computation is even needed;
+// maximum change is d_n_code_outputs if all bits match exactly
+          if ((t_to_metric - t_metric) > ((float) 2*d_n_code_outputs)) {
+#if DO_PRINT_DEBUG_TERM
+           std::cout << "!not computing metric!\n";
+#endif
+           continue;
+         }
+// metrics are close enough; do the computation and the compare
+// get the output bits for this connection
+          float* t_output_bit = t_connection->d_output_bits;
+         if (d_do_mux_inputs == true) {
+// if using mux'ed input streams, handle differently
+            const float* t_in_buf = &(in_buf[0][t_in_buf_ndx]);
+// loop over all encoder-output values
+           for (size_t r = d_n_code_outputs; r > 0; r--) {
+             t_metric += ((*t_in_buf++) * (*t_output_bit++));
+           }
+         } else {
+// loop over all encoder-output values
+           for (size_t r = 0; r < d_n_code_outputs; r++) {
+              t_metric += (in_buf[r][t_in_buf_ndx] * (*t_output_bit++));
+           }
+         }
+// done with this input value; compare old and new metrics
+// see if it's the best metric
+          if (t_metric > t_to_metric) {
+#if DO_PRINT_DEBUG_TERM
+           std::cout << "New Metric to s[" <<
+             n2bs (t_connection->d_to_ndx,t_state_print_bits) << "]: ";
+           if (t_to_state->d_max_metric == -1e10) {
+             std::cout << "setting to ";
+           } else {
+             std::cout << "was s[" <<
+               n2bs(t_to_state->d_max_state_ndx,t_state_print_bits) <<
+               "]i[" << n2bs (t_to_state->d_max_input, d_n_code_inputs+1) <<
+               "]@ " << t_to_state->d_max_metric << "  now ";
+           }
+           std::cout << "s[" << n2bs(t_state_ndx,t_state_print_bits) <<
+             "] i[" << n2bs (0, d_n_code_inputs+1) << "]@ " << t_metric << 
"\n";
+#endif
+            t_to_state->d_max_metric = t_metric;
+            t_to_state->d_max_state_ndx = t_state_ndx;
+            t_to_state->d_max_input = 0;
+         }
+// add the "to" state's index to the "next" set of state's indices list
+          *t_next_state_ndx_ptr++ = t_connection->d_to_ndx;
+// finished (for) this state
+       }
+// done with all states and all inputs; now update the traceback structure
+// change which d_states' index to use as starting
+        d_states_ndx ^= 1;
+// update the number of "up_term" states
+        d_up_term_ndx ^= 1;
+// reduce the number of using states
+        t_n_up_down_ndx >>= d_n_code_inputs;
+// reset the state's index for each set of new inputs
+       t_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx];
+// update the traceback structure
+// loop over all current states
+       traceback_t_ptr t_prev_out_bufs = d_out_buf[d_time_count];
+       traceback_t_ptr t_out_bufs = d_out_buf[d_time_count+1];
+#if DO_PRINT_DEBUG_TERM_1
+       std::cout << "d_o_b[" << d_time_count+1 << "] => d_o_b prev\n";
+#endif
+// loop over all current stored "term" state indices
+       for (size_t n = 0; n < t_n_up_down_ndx; n++) {
+// get the start index and then pointer to each of the "to" states,
+// which hold the newest "max" stuff
+         size_t t_state_ndx = *t_state_ndx_ptr++;
+         state_t_ptr t_state = &(d_states[d_states_ndx][t_state_ndx]);
+// simple: get the current state & output state
+// and connect output to the current, set inputs on output
+         traceback_t_ptr t_out_buf = &(t_out_bufs[t_state_ndx]);
+         traceback_t_ptr t_prev_out_buf =
+           &(t_prev_out_bufs[t_state->d_max_state_ndx]);
+#if DO_PRINT_DEBUG_TERM_1
+         std::cout << "ndx[" << n << "] == " << t_state_ndx <<
+           ", s[" << n2bs(t_state_ndx,t_state_print_bits) <<
+           "]: max_ndx = " <<
+           n2bs(t_state->d_max_state_ndx,t_state_print_bits) <<
+           ", input = " << n2bs(t_state->d_max_input, d_n_code_inputs+1) <<
+           ": " << t_out_buf << " => " << t_prev_out_buf << "\n";
+#endif
+         t_out_buf->d_prev = t_prev_out_buf;
+         t_out_buf->d_inputs = t_state->d_max_input;
+// finished (for) this state
+       }
+// increment the in_buf index, depending on mux'ing or not
+       t_in_buf_ndx += (d_do_mux_inputs == false) ? 1 : d_n_code_outputs;
+// increment the time counters
+        t_time_count--;
+        d_time_count++;
+// finished (while) staying in this fsm state or not
+      }
+      if (t_time_count == 0) {
+// finished this trellis, now move as much of the decoded input to the
+// output buffer as possible
+#if DO_PRINT_DEBUG_FSM
+       std::cout << "Setting FSM to fsm_dec_output\n";
+#endif
+       d_fsm = fsm_dec_output;
+      }
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Exited fsm_dec_doing_term\n";
+#endif
+      break;
+    case (fsm_dec_output):
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Entered fsm_dec_output.\n";
+#endif
+// this is done in reverse bit order (last time to first time)
+// using the traceback structure in d_out_buf, starting with
+// the maximum valued one in the last time slot, then using
+// the traceback's "d_prev" link to trace the trellis back
+
+// see where the output data will terminate
+      int t_next_out_buf_ndx = (t_out_buf_ndx +
+                               (d_frame_size_bits / g_num_bits_per_byte));
+      int t_next_out_bit_shift = (t_out_bit_shift +
+                                 (d_frame_size_bits % g_num_bits_per_byte));
+      if (t_next_out_bit_shift >= g_num_bits_per_byte) {
+       t_next_out_bit_shift -= g_num_bits_per_byte;
+       t_next_out_buf_ndx++;
+      }
+#if DO_PRINT_DEBUG_OUTPUT
+      std::cout << "First bit in at out[][" << t_out_buf_ndx << "].[" <<
+       t_out_bit_shift << "] -> " << d_frame_size_bits << " bits == " <<
+       (d_frame_size_bits / g_num_bits_per_byte) << " Byte" <<
+       ((d_frame_size_bits / g_num_bits_per_byte) != 1 ? "s" : "") <<
+       " + " << (d_frame_size_bits % g_num_bits_per_byte) << " bit" <<
+       ((d_frame_size_bits % g_num_bits_per_byte) != 1 ? "s" : "") <<
+       "\nNext set of bits start at out[][" << t_next_out_buf_ndx <<
+       "].[" << t_next_out_bit_shift << "]\n";
+#endif
+// find the starting traceback structure
+      traceback_t_ptr t_out_buf;
+      if (d_do_termination == true) {
+// FIXME: assume termination state == 0
+#if DO_PRINT_DEBUG_OUTPUT_0
+       std::cout << "Using termination; going through trellis for " <<
+         d_max_memory << " bit" <<
+         ((d_max_memory != 1) ? "s" : "") << "\n";
+#endif
+       t_out_buf = &(d_out_buf[d_time_count][0]);
+#if DO_PRINT_DEBUG_OUTPUT_0
+       std::cout << "Starting traceback ptr " << t_out_buf << "\n";
+#endif
+// skip over the termination bits
+       for (size_t n = d_max_memory; n > 0; n--) {
+         t_out_buf = t_out_buf->d_prev;
+#if DO_PRINT_DEBUG_OUTPUT_0
+         std::cout << "Next traceback ptr " << t_out_buf << "\n";
+#endif
+       }
+      } else {
+// no termination but doing block coding;
+// FIXME: use the state with the bext metric
+// get the state's index for each set of new inputs
+       state_t_ptr t_state = d_states[d_states_ndx];
+       float t_max_metric = t_state->d_max_metric;
+       size_t t_max_state_ndx = 0;
+       t_state++;
+// loop over all current states
+       for (size_t n = 1; n < d_n_states; n++, t_state++) {
+// start with this state's metric
+         float t_metric = t_state->d_max_metric;
+// compare with current max
+         if (t_metric > t_max_metric) {
+           t_max_metric = t_metric;
+           t_max_state_ndx = n;
+         }
+       }
+// get the correct out_buf reference to start with
+       t_out_buf = &(d_out_buf[d_time_count][t_max_state_ndx]);
+      }
+#if DO_PRINT_DEBUG_OUTPUT
+      std::cout << "Found starting traceback ptr " << t_out_buf <<
+       "; getting all " << d_frame_size_bits << " bits per stream.\n";
+#endif
+// now we've got the starting traceback structure address;
+// check to make sure there is enough space in each output buffer
+      size_t t_frame_bit_ndx = d_frame_size_bits;
+      if ((t_next_out_buf_ndx > t_noutput_bytes) |
+         ((t_next_out_buf_ndx == t_noutput_bytes) &
+          (t_next_out_bit_shift != 0))) {
+// not enough space for all output bits;
+// find the number of extra bits to save
+       size_t t_save_buf_ndx = t_next_out_buf_ndx - t_noutput_bytes;
+       size_t t_n_extra_bits = ((t_save_buf_ndx * g_num_bits_per_byte) +
+                                t_next_out_bit_shift);
+// set the number of saved bits
+       d_n_saved_bits = t_n_extra_bits;
+// remove the extra bits from the number to copy to the output buffer
+       t_frame_bit_ndx -= t_n_extra_bits;
+// find the actual output buf index, once we get there
+       t_next_out_buf_ndx -= t_save_buf_ndx;
+#if DO_PRINT_DEBUG_OUTPUT
+       std::cout << "Not enough output buffer space:\n" <<
+         "len (o_b) = " << t_noutput_bytes << " ==> " <<
+         t_n_extra_bits << " extra bit" <<
+         (t_n_extra_bits != 1 ? "s" : "") << " == " <<
+         t_save_buf_ndx << " Byte" <<
+         (t_save_buf_ndx != 1 ? "s" : "") << ", " <<
+         t_next_out_bit_shift << " bit" <<
+         (t_next_out_bit_shift != 1 ? "s" : "") << "\n";
+#endif
+// zero each output buffers' bytes
+       size_t t_n_zero = t_save_buf_ndx + (t_next_out_bit_shift ? 1 : 0);
+#if DO_PRINT_DEBUG_OUTPUT
+       size_t t_n_out_bytes = ((d_frame_size_bits / g_num_bits_per_byte) +
+                               ((d_frame_size_bits % g_num_bits_per_byte) ? 1 
: 0));
+       std::cout << "Zeroing save buffer from for " << t_n_zero <<
+         " Byte" << (t_n_zero != 1 ? "s" : "") << " (of " <<
+         d_frame_size_bits << " bit" <<
+         (d_frame_size_bits != 1 ? "s" : "") << " == " << t_n_out_bytes <<
+         " Byte" << (t_n_out_bytes != 1 ? "s" : "") << ")\n";
+#endif
+       for (size_t m = 0; m < d_n_code_inputs; m++)
+         bzero (d_save_buffer[m], t_n_zero);
+// loop over all extra bits
+       for (size_t n = t_n_extra_bits; n > 0; n--) {
+// first decrement the output bit & byte as necessary
+         if (--t_next_out_bit_shift < 0) {
+           t_next_out_bit_shift += g_num_bits_per_byte;
+           t_save_buf_ndx--;
+         }
+// get the encoder inputs to output
+         size_t t_inputs = t_out_buf->d_inputs;
+// loop over all code inputs (decoder-outputs), 1 bit per stream
+         for (size_t m = 0; m < d_n_code_inputs; m++) {
+           d_save_buffer[m][t_save_buf_ndx] |=
+             ((t_inputs & 1) << t_next_out_bit_shift);
+           t_inputs >>= 1;
+         }
+         t_out_buf = t_out_buf->d_prev;
+#if DO_PRINT_DEBUG_OUTPUT_0
+         std::cout << "Next traceback ptr " << t_out_buf << "\n";
+#endif
+       }
+// at exit, "t_out_buf_ndx" should be == t_noutput_bytes, and
+// "t_out_bit_shift" should be 0; check these!
+#if DO_PRINT_DEBUG_OUTPUT
+       std::cout << "n_o_b_ndx (" << t_next_out_buf_ndx << ") ?=? " <<
+         "#o_B (" << t_noutput_bytes << ") & t_o_b_sh (" <<
+         t_next_out_bit_shift << ") ?=? 0\n";
+       assert (t_next_out_buf_ndx == t_noutput_bytes);
+       assert (t_next_out_bit_shift == 0);
+#endif
+      }
+// set the correct output buffer index and bit shift
+      t_out_bit_shift = t_next_out_bit_shift;
+      t_out_buf_ndx = t_next_out_buf_ndx;
+// copy any remaining bits looping backwards in bit-time
+// through the traceback trellis
+      for (size_t n = t_frame_bit_ndx; n > 0; n--) {
+// first decrement the output bit & byte as necessary
+       if (--t_out_bit_shift < 0) {
+         t_out_bit_shift += g_num_bits_per_byte;
+         t_out_buf_ndx--;
+       }
+// get the encoder inputs to output
+       size_t t_inputs = t_out_buf->d_inputs;
+// loop over all code inputs (decoder-outputs), 1 bit per stream
+       for (size_t m = 0; m < d_n_code_inputs; m++) {
+         out_buf[m][t_out_buf_ndx] |= ((t_inputs & 1) << t_out_bit_shift);
+         t_inputs >>= 1;
+       }
+       t_out_buf = t_out_buf->d_prev;
+#if DO_PRINT_DEBUG_OUTPUT_0
+       std::cout << "Next traceback ptr " << t_out_buf << "\n";
+#endif
+      }
+// set the next output byte and bit-shift
+      t_out_bit_shift = t_next_out_bit_shift;
+      t_out_buf_ndx = t_next_out_buf_ndx;
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Set FSM to fsm_dec_init\n";
+#endif
+      d_fsm = fsm_dec_init;
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Exited fsm_dec_output\n";
+#endif
+      break;
+    case (fsm_dec_init):
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Entered fsm_dec_init\n";
+#endif
+// this is called immediately (first input bit upon startup),
+// or after termination of a trellis.
+
+// reset states to the 0'th one
+      d_up_term_ndx = d_states_ndx = 0;
+// zero the metrics for those states
+      zero_metrics (0);
+#if 0
+// might not need to do this; check and see after it works
+// reset up_term states and number so that there is 1 item, the "0" state.
+      bzero (d_up_term_states_ndx[0], sizeof (size_t) * d_n_states);
+      bzero (d_up_term_states_ndx[1], sizeof (size_t) * d_n_states);
+#else
+      d_up_term_states_ndx[0][0] = 0;
+#endif
+// reset time count back to the start
+      d_time_count = 0;
+#if 0
+// reset the traceback structures
+// might not need to do this; check and see after it works
+      traceback_t_hdl t_out_bufs = d_out_buf;
+      for (size_t n = d_n_traceback_els; n > 0; n--) {
+       traceback_t_ptr t_out_buf = (*t_out_bufs++);
+       for (size_t m = d_n_states; m > 0; m--, t_out_buf++) {
+         t_out_buf->d_prev = NULL;
+         t_out_buf->d_inputs = -1;
+       }
+      }
+#endif
+// set the fsm to "doing up"
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Set FSM to fsm_dec_doing_up\n";
+#endif
+      d_fsm = fsm_dec_doing_up;
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Exited fsm_dec_init\n";
+#endif
+      break;
+// should never get here!
+    default:
+      assert (0);
+// done (switch) with FSM
+    }
+// done (while) there are inputs
+  }
+
+// consume all of the input items on all input streams
+// "ninput_items[]" doesn't seem to be reliable,
+// so compute this from the actual number of frames processed
+#if DO_PRINT_DEBUG_EXIT
+  std::cout << "Exiting FSM in state: " <<
+    (d_fsm == fsm_dec_init ? "init" :
+     (d_fsm == fsm_dec_doing_up ? "up" :
+      (d_fsm == fsm_dec_doing_middle ? "middle" :
+       (d_fsm == fsm_dec_doing_term ? "term" :
+       (d_fsm == fsm_dec_output ? "output" : "unknown"))))) << "\n" <<
+    "Consuming " << t_in_buf_ndx <<
+    " input items on each input stream (of " << t_ninput_items << ").\n";
+#endif
+  consume_each (t_in_buf_ndx);
+
+// make sure the number of output items makes sense
+// t_out_buf_ndx always points to the current index
+// t_out_bit_shift always points to the next bit position to be written
+  int t_leftover_bytes = t_out_buf_ndx % d_out_stream_el_size_bytes;
+  int t_leftover_bits = ((t_leftover_bytes * g_num_bits_per_byte) +
+                        t_out_bit_shift);
+  int t_noutput_items = noutput_items;
+#if DO_PRINT_DEBUG_EXIT
+  std::cout << "Final o_b[" << t_out_buf_ndx << "][" <<
+    t_out_bit_shift << "] of " << t_noutput_bytes <<
+    ", el_size = " << d_out_stream_el_size_bytes <<
+    ", lo_Bytes = " << t_leftover_bytes <<
+    ", t_lo_bits = " << t_leftover_bits << "\n" <<
+    "Desired # output items = " << noutput_items << "\n";
+#endif
+  if (t_leftover_bits != 0) {
+    // should never get here!
+#if 1
+    assert (0);
+#else
+    int t_ndx = t_out_buf_ndx - t_leftover_bytes;
+    size_t t_n_copy = t_leftover_bytes + ((t_out_bit_shift != 0) ? 1 : 0);
+    assert (t_n_copy <= d_out_stream_el_size_bytes);
+// copy the leftover into the save buffer
+    for (size_t n = 0; n < d_n_code_inputs; n++) {
+      bcopy (&(out_buf[n][t_ndx]), d_save_buffer[n], t_n_copy);
+    }
+    t_noutput_items = t_ndx / d_out_stream_el_size_bytes;
+    d_n_saved_bits = t_leftover_bits;
+#if DO_PRINT_DEBUG_EXIT
+    std::cout << "Copied " << t_n_copy << " Byte" <<
+      (t_n_copy != 1 ? "s" : "") << " from o_b[][" << t_ndx <<
+      "] into each save buffer.\n" <<
+      "Actual #output items = " << t_noutput_items <<
+      ", # saved bit(s) = " << d_n_saved_bits << "\n";
+#endif
+#endif
+  }
+
+#if DO_TIME_THOUGHPUT
+  u_long d_t = end_timer (&t_tp);
+
+  std::cout << "dec_blk_conv_soft_full: Completed " << t_ninput_items <<
+    " bits in " << d_t << " usec => " <<
+    1e6*(((double)(t_ninput_items))/((double) d_t)) <<
+    " b/s\n";
+#endif
+
+// returns number of items written to each output stream
+  return (t_noutput_items);
+}

Index: libecc/decoder_viterbi.h
===================================================================
RCS file: libecc/decoder_viterbi.h
diff -N libecc/decoder_viterbi.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libecc/decoder_viterbi.h    5 Jul 2006 17:49:58 -0000       1.1
@@ -0,0 +1,112 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef INCLUDED_DECODER_VITERBI_H
+#define INCLUDED_DECODER_VITERBI_H
+
+#include <vector>
+#include "decoder.h"
+#include "encoder.h"
+
+class decoder_viterbi : public decoder
+{
+public:
+/*!
+ * \brief Decode the incoming metrics streams using the Viterbi algorithm.
+ *
+ * input: streams of metrics, 2 streams per n_code_outputs - one each for
+ *     a 0- and 1-bit metric.
+ *
+ * output: streams of char, one stream per n_code_inputs, using only
+ *     the right-most justified bit as the single bit per output item.
+ *
+ * sample_precision: precision of the incoming metrics
+ *     if == 0, then use soft precision (32 bit float);
+ *     otherwise, use an integer up to 32 bits, already sign-extended
+ *     to the nearest power-of-2-sized type (char, short, long).
+ *
+ * l_encoder: pointer to an encoder class from which to determine the
+ *     trellis transitions (states and i/o bits).
+ */
+
+  decoder_viterbi (int sample_precision,
+                  encoder* l_encoder);
+
+  virtual ~decoder_viterbi () {};
+
+protected:
+/*
+ * fsm_dec_viterbi_t: finite state machine for the convolutional decoder;
+ *     output happens all the time, so that's built-in to each state.
+ *
+ * fsm_dec_viterbi_init: initialize for a new frame / block; this is already
+ *     done at instantiation, so do it only at the end of a block.
+ *
+ * fsm_dec_viterbi_doing_up: encoding at the start of a block
+ *
+ * fsm_dec_viterbi_doing_middle: doing encoding inside the trellis
+ *
+ * fsm_dec_viterbi_doing_term: termination trellis, if requested
+ */
+
+  enum fsm_dec_viterbi_t {
+    fsm_dec_viterbi_init, fsm_dec_viterbi_doing_up,
+    fsm_dec_viterbi_doing_middle, fsm_dec_viterbi_doing_term
+  };
+
+  virtual void decode_private (const char** in_buf, char** out_buf);
+  virtual void decode_loop (const char** in_buf, char** out_buf,
+                           size_t* which_counter, size_t how_many);
+  virtual char get_next_input (const char** in_buf, size_t code_input_n);
+  virtual char get_next_input__up (const char** in_buf,
+                                     size_t code_input_n);
+  virtual char get_next_input__middle (const char** in_buf,
+                                         size_t code_input_n);
+  virtual char get_next_input__term (size_t code_input_n);
+  virtual void increment_counters (bool while_decoding);
+
+  fsm_dec_viterbi_t d_fsm_state;
+  bool d_do_streaming, d_do_termination;
+  std::vector<memory_t> d_states, d_init_states, d_term_states;
+
+  void reset_metrics (u_char which);
+  void zero_metrics (u_char which);
+
+/*
+ * d_n_total_input_bits_per_stream: how many bits to store for each
+ *     state to determine the best decoder-output (encoder-input) bits 
+ */
+  size_t d_frame_size_bits;
+  size_t d_n_code_outputs, d_n_code_inputs, d_max_memory;
+  size_t d_time_count, d_n_total_input_bits_per_stream;
+  size_t d_n_saved_bits, d_n_saved_bits_start_ndx, d_n_traceback_els;
+  size_t d_n_states, d_n_input_combinations;
+  size_t d_states_ndx, d_up_term_ndx;
+  bool d_do_streaming, d_do_termination, d_do_mux_inputs;
+  char **d_save_buffer;
+  state_t_ptr d_states[2];
+  fsm_dec_t d_fsm;
+  size_t* d_up_term_states_ndx[2];
+  traceback_t_hdl d_out_buf;
+};
+
+#endif /* INCLUDED_DECODER_VITERBI_H */

Index: libecc/decoder_viterbi_block_full.cc
===================================================================
RCS file: libecc/decoder_viterbi_block_full.cc
diff -N libecc/decoder_viterbi_block_full.cc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libecc/decoder_viterbi_block_full.cc        5 Jul 2006 17:49:58 -0000       
1.1
@@ -0,0 +1,1484 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_dec_blk_conv_soft_full.h>
+#include <gr_io_signature.h>
+#include <assert.h>
+#include <iostream>
+
+const int g_max_frame_size_bits = 10000000;
+const int g_max_num_streams = 10;
+const int g_num_bits_per_byte = 8;
+
+#define DO_TIME_THOUGHPUT 0
+#define DO_PRINT_DEBUG_INST 0
+#define DO_PRINT_DEBUG_INST_0 0
+#define DO_PRINT_DEBUG_INST_1 0
+#define DO_PRINT_DEBUG_INST_2 0
+#define DO_PRINT_DEBUG_FSM 0
+#define DO_PRINT_DEBUG_INIT 0
+#define DO_PRINT_DEBUG_UP 0
+#define DO_PRINT_DEBUG_UP_0 0
+#define DO_PRINT_DEBUG_UP_1 0
+#define DO_PRINT_DEBUG_MIDDLE 0
+#define DO_PRINT_DEBUG_MIDDLE_0 0
+#define DO_PRINT_DEBUG_MIDDLE_1 0
+#define DO_PRINT_DEBUG_TERM 0
+#define DO_PRINT_DEBUG_TERM_1 0
+#define DO_PRINT_DEBUG_OUTPUT 0
+#define DO_PRINT_DEBUG_OUTPUT_0 0
+#define DO_PRINT_DEBUG_EXIT 0
+#define DO_PRINT_DEBUG 0
+
+#if DO_TIME_THOUGHPUT
+#include <mld/mld_timer.h>
+#endif
+#if DO_PRINT_DEBUG
+#include <mld/n2bs.h>
+#endif
+
+gr_decoder_viterbi_block_soft_full_sptr
+gr_make_dec_blk_conv_soft_full
+(int frame_size_bits,
+ int num_input_streams,
+ int num_output_streams,
+ std::vector<int> code_generator,
+ bool do_termination)
+{
+  return gr_decoder_viterbi_block_soft_full_sptr
+    (new gr_decoder_viterbi_block_soft_full (frame_size_bits,
+                                            num_input_streams,
+                                            num_output_streams,
+                                            code_generator,
+                                            do_termination));
+}
+
+gr_decoder_viterbi_block_soft_full::gr_decoder_viterbi_block_soft_full
+(int frame_size_bits,
+ int num_input_streams,
+ int num_output_streams,
+ std::vector<int> code_generator,
+ bool do_termination)
+  : gr_block ("dec_blk_conv_soft_full",
+             gr_make_io_signature (0, 0, 0),
+             gr_make_io_signature (0, 0, 0))
+{
+// make sure the frame length makes sense, #1 - more later
+  if (frame_size_bits > g_max_frame_size_bits) {
+    std::cerr << "gr_decoder_viterbi_block_soft_full: " <<
+      "Requested frame length (" << frame_size_bits <<
+      " bits) must be at most " << g_max_frame_size_bits << " bits.\n";
+    assert (0);
+  }
+
+// check to make sure the number of input streams makes sense
+  if ((n_code_inputs <= 0) | (n_code_inputs > g_max_num_streams)) {
+    std::cerr << "gr_decoder_viterbi_block_soft_full: " <<
+      "Requested number of input streams (" <<
+      n_code_inputs << ") must be between 1 and " <<
+      g_max_num_streams << ".\n";
+    assert (0);
+  }
+
+// check to make sure the number of output streams makes sense
+  if ((n_code_outputs <= 0) | (n_code_outputs > g_max_num_streams)) {
+    std::cerr << "gr_decoder_viterbi_block_soft_full: " <<
+      "Requested number of output streams (" <<
+      n_code_outputs << ") must be between 1 and " <<
+      g_max_num_streams << ".\n";
+    assert (0);
+  }
+
+// make sure the code_generator is the correct length
+  if (code_generators.size () !=
+      ((size_t)(n_code_inputs * n_code_outputs))) {
+    std::cerr << "gr_decoder_viterbi_block_soft_full: " <<
+      "Number of code generator entries (" << code_generators.size () <<
+      ") is not equal to the product of the number of input and output" <<
+      " streams (" << (n_code_inputs * n_code_outputs) << ").\n";
+    assert (0);
+  }
+
+// create the class frame variables
+  d_frame_size_bits = frame_size_bits;
+  d_out_stream_el_size_bytes = out_stream_el_size_bytes;
+  d_n_code_inputs = n_code_inputs;
+  d_n_code_outputs = n_code_outputs;
+  d_do_streaming = (frame_size_bits == 0);
+  d_do_termination = (d_do_streaming == true) ? false : do_termination;
+  d_do_mux_inputs = do_mux_inputs;
+
+// allocate the vectors for doing the encoding.  use 32-bit int's
+// actual bits to represent memory and the code, as it makes the
+// operations quite simple the state vectors.
+// code generates are for each I/O combination
+
+  d_code_generators.resize (d_n_code_inputs * d_n_code_outputs, 0);
+
+// check the input code_generator for correctness & find the memory order
+// t_max_mem will be the mamimum number of memories used by the generator
+// t_code_ndx is a counter over all input code_generator elements
+  int t_max_mem = 0, t_code_ndx = d_code_generators.size() - 1;
+// loop over all input streams first, output streams second
+  for (int n = d_n_code_outputs - 1; n >= 0; n--) {
+    int t_all_inputs_zero = 0;
+    for (int m = d_n_code_inputs - 1; m >= 0; m--) {
+      int t_in_code = code_generators[t_code_ndx];
+      t_all_inputs_zero |= t_in_code;
+      int t_code_mem = 0;
+// find the memory requirement for this code generator
+      while (t_in_code != 0) {
+       t_in_code >>= 1;
+       t_code_mem++;
+      }
+      if (t_code_mem > t_max_mem)
+       t_max_mem = t_code_mem;
+// store in d_code_generators in output-first ordering
+      d_code_generators[(m*d_n_code_outputs) + n] =
+       code_generators[t_code_ndx--];
+    }
+    if (t_all_inputs_zero == 0) {
+      std::cerr << "gr_decoder_viterbi_block_soft_full: " <<
+       "At least 1 generator code for encode-output " << n+1 <<
+       " must be non-0.\n";
+      assert (0);
+    }
+  }
+
+// store the maximum memory order (e.g. "2" -> D^2)
+  d_max_memory = t_max_mem - 1;
+
+// make sure the frame length makes sense, #2
+  if (d_frame_size_bits < d_max_memory) {
+    std::cerr << "gr_decoder_viterbi_block_soft_full: " <<
+      "Requested frame length (" << d_frame_size_bits <<
+      " bit" << (d_frame_size_bits > 1 ? "s" : "") <<
+      ") must be at least 1 memory length (" << d_max_memory <<
+      " bit" << (d_max_memory > 1 ? "s" : "") <<
+      " for this code).\n";
+    assert (0);
+  }
+
+// NOTE: d_n_states is a 'u_long', and thus is quite limited in terms
+// of max memory and # of input streams to 2^32 states
+// This is OK, since that many states would be impossibly slow to decode!
+// might make this a "long long" (64 bits) in the future
+  d_n_states = 1 << (d_max_memory * d_n_code_inputs);
+  d_n_input_combinations = 1 << d_n_code_inputs;
+
+#if DO_PRINT_DEBUG_INST_0
+  std::cout << "Init:\n" <<
+    "d_frame_size_bits          = " << d_frame_size_bits << "\n" <<
+    "d_out_stream_el_size_bytes = " << d_out_stream_el_size_bytes << "\n" <<
+    "d_n_code_inputs            = " << d_n_code_inputs << "\n" <<
+    "d_n_code_outputs           = " << d_n_code_outputs << "\n" <<
+    "d_do_streaming             = " <<
+    ((d_do_streaming == true) ? "true" : "false") << "\n" <<
+    "d_do_termination           = " <<
+    ((d_do_termination == true) ? "true" : "false") << "\n" <<
+    "d_do_mux_inputs            = " <<
+    ((d_do_mux_inputs == true) ? "true" : "false") << "\n" <<
+    "d_max_memory               = " << d_max_memory << "\n" <<
+    "d_n_states                 = " << d_n_states << "\n" <<
+    "d_n_input_combinations     = " << d_n_input_combinations << "\n";
+#endif
+
+// leave the output multiple at 1 (element); will save any incomplete
+// output data (int's) in "d_save_buffer"; all input data will be consumed
+
+// create the correct input signature
+  int t_n_input_streams = ((d_do_mux_inputs == true) ?
+                          1 : n_code_outputs);
+
+  set_input_signature (gr_make_io_signature (t_n_input_streams,
+                                            t_n_input_streams,
+                                            sizeof (float)));
+// create the correct output signature
+  set_output_signature (gr_make_io_signature (n_code_inputs,
+                                             n_code_inputs,
+                                             d_out_stream_el_size_bytes));
+#if DO_PRINT_DEBUG_INST_0
+  std::cout <<
+    "input_signature            = [" << t_n_input_streams << ", " <<
+    t_n_input_streams << ", " << sizeof (float) << "]\n" <<
+    "output_signature           = [" << n_code_outputs << ", " <<
+    n_code_outputs << ", " << d_out_stream_el_size_bytes << "]\n";
+#endif
+
+// always start the fsm in the "init" state
+  d_fsm = fsm_dec_init;
+
+// create a vector of indexes to states when doing "up" or "termination";
+  d_up_term_states_ndx[0] = new size_t [d_n_states];
+  d_up_term_states_ndx[1] = new size_t [d_n_states];
+
+// create the traceback buffers
+// get the total number of out bits per stream
+  d_n_total_input_bits_per_stream = d_frame_size_bits;
+  if (d_do_termination == true)
+    d_n_total_input_bits_per_stream += d_max_memory;
+  d_n_traceback_els = d_n_total_input_bits_per_stream + 1;
+// create the output buffers:
+// this is a 2d matrix structure, where the first dimension
+// is the number of output bits; the second dimension is
+// the number of states.
+// When doing full frames (no tau), each bit-time's state's traceback
+// contains just the pointer to the previous bit-time's state's traceback
+// as well as the inputs for that connection.
+// No further work is required because each reverse-path is unique
+// once a given end-bit-time's state is determined to be "the one"
+  traceback_t_hdl t_out_buf =
+    d_out_buf = new traceback_t_ptr [d_n_traceback_els];
+  for (size_t n = d_n_traceback_els; n > 0; n--) {
+    (*t_out_buf++) = new traceback_t [d_n_states];
+  }
+
+  // create the save buffers
+  char** t_save_buffer = d_save_buffer = new char* [d_n_code_inputs];
+  size_t t_n_out_bytes = ((d_frame_size_bits / g_num_bits_per_byte) +
+                         ((d_frame_size_bits % g_num_bits_per_byte) ? 1 : 0));
+  for (size_t n = 0; n < d_n_code_inputs; n++) {
+    (*t_save_buffer++) = new char [t_n_out_bytes];
+  }
+
+// reset the number of saved bits
+  d_n_saved_bits_start_ndx = d_n_saved_bits = 0;
+
+// setup the internal structures for exiting and entering states
+
+#if DO_PRINT_DEBUG_INST_0
+  std::cout <<
+    "d_n_total in bits / stream = " << d_n_total_input_bits_per_stream << "\n" 
<<
+    "d_n_traceback_els          = " << d_n_traceback_els << "\n" <<
+    "t_n_out_bytes / stream     = " << t_n_out_bytes << "\n";
+#endif
+
+// Find the approximate output rate / input rate
+// each input item produces 1 bit of an output item w/o termination
+  double t_rel_rate = (double)(d_out_stream_el_size_bytes * 
g_num_bits_per_byte);
+  if (d_do_termination == true) {
+// include termination bits
+    t_rel_rate *= (((double) d_frame_size_bits) /
+                  ((double) d_n_total_input_bits_per_stream));
+  }
+// Set the approximate output rate / input rate
+  set_relative_rate (t_rel_rate);
+
+// 'new' everything first; no connections yet
+  state_t_ptr t_state = d_states[0] = new state_t [d_n_states];
+  for (size_t n = d_n_states; n > 0; n--, t_state++) {
+    connection_t_ptr t_connection = t_state->d_connections
+      = new connection_t [d_n_input_combinations];
+    for (size_t m = d_n_input_combinations; m > 0; m--, t_connection++) {
+      t_connection->d_output_bits = new float [d_n_code_outputs];
+    }
+  }
+
+// 'new' everything first; no connections yet
+  t_state = d_states[1] = new state_t [d_n_states];
+  for (size_t n = d_n_states; n > 0; n--, t_state++) {
+    connection_t_ptr t_connection = t_state->d_connections
+      = new connection_t [d_n_input_combinations];
+    for (size_t m = d_n_input_combinations; m > 0; m--, t_connection++) {
+      t_connection->d_output_bits = new float [d_n_code_outputs];
+    }
+  }
+
+// temporary memory and mask for output bit computations
+  size_t t_memory[d_n_code_inputs];
+  size_t t_memory_mask = ((2 << d_max_memory) - 1) ^ 1;
+
+#if DO_PRINT_DEBUG
+  size_t t_state_print_bits = (d_max_memory * d_n_code_inputs) + 1;
+  size_t t_mem_print_bits = d_max_memory + 2;
+
+  std::cout << "Setting States and Connections\n";
+#endif
+
+// loop over all possible memory states
+  state_t_ptr t_state0 = d_states[0];
+  state_t_ptr t_state1 = d_states[1];
+  for (size_t n = 0; n < d_n_states; n++, t_state0++, t_state1++) {
+#if DO_PRINT_DEBUG_INST_1
+    std::cout << "Starting state # " << n << " == " <<
+      n2bs (n, t_state_print_bits) << "\n";
+#endif
+// retrieve the memory values for this state
+// probably a faster way to do this, but since this is
+// executed only upon instantiation, whatever.
+    size_t* t_mem_ptr = t_memory;
+    for (size_t p = 0; p < d_n_code_inputs; p++) {
+      int t_mem = state_get_from (n, p, d_max_memory);
+#if DO_PRINT_DEBUG_INST_1
+      std::cout << "s_g_f (" <<
+       n2bs (n, t_state_print_bits) << ", " <<
+       p << ", " << d_max_memory << ") => t_m = " <<
+       n2bs (t_mem, t_mem_print_bits) << "\n";
+#endif
+// shift them by 1 (and mask) to make updating for all inputs simple
+      (*t_mem_ptr++) = t_mem << 1;
+#if DO_PRINT_DEBUG_INST_1
+      std::cout << "t_m_p[" << p << "] = " <<
+       n2bs (t_mem << 1, t_mem_print_bits) << " == (" <<
+       n2bs (t_mem, t_mem_print_bits) << " << 1)\n";
+#endif
+    }
+
+// loop over all possible input values, 1 bit per input stream
+    connection_t_ptr t_connection0 = t_state0->d_connections;
+    connection_t_ptr t_connection1 = t_state1->d_connections;
+    for (size_t q = 0; q < d_n_input_combinations;
+        q++, t_connection0++, t_connection1++) {
+#if DO_PRINT_DEBUG_INST_1
+      std::cout << "Starting inputs " << q << " == " <<
+       n2bs (q, d_n_code_inputs + 1) << "\n";
+#endif
+
+// update memory for this set of inputs
+      t_mem_ptr = t_memory;
+      size_t t_this_input = q;
+
+// loop over all code inputs, and update just the single input bit
+      for (size_t r = d_n_code_inputs; r > 0; r--) {
+       int t_mem = (*t_mem_ptr) & t_memory_mask;
+#if DO_PRINT_DEBUG_INST_1
+       std::cout << "t_m = " << n2bs (t_mem, t_mem_print_bits) <<
+         " == " << n2bs (*t_mem_ptr, t_mem_print_bits) <<
+         " & " << n2bs (t_memory_mask, t_mem_print_bits) << "\n";
+#endif
+       (*t_mem_ptr++) = t_mem | (t_this_input & 1);
+#if DO_PRINT_DEBUG_INST_1
+       std::cout << "t_m_p[" << (d_n_code_inputs - r) << "] = " <<
+         n2bs (t_mem | (t_this_input & 1), t_mem_print_bits) <<
+         " == t_m | " << (t_this_input & 1) << "\n";
+#endif
+       t_this_input >>= 1;
+      }
+
+// got the updated memory for this particular state & inputs
+// recreate the "to" state from the updated memory
+      t_mem_ptr = t_memory;
+      size_t t_out_state = 0;
+      for (size_t p = 0; p < d_n_code_inputs; p++) {
+#if DO_PRINT_DEBUG_INST_1
+       std::cout << "s_a_t (" <<
+         n2bs (t_out_state, t_state_print_bits) <<
+         ", " << n2bs (*t_mem_ptr, t_mem_print_bits) << ", " << p <<
+         ", " << d_max_memory << ") ==> t_o_s out = ";
+#endif
+       state_add_to (t_out_state, *t_mem_ptr++, p, d_max_memory);
+#if DO_PRINT_DEBUG_INST_1
+       std::cout << n2bs (t_out_state, t_state_print_bits) << "\n";
+#endif
+      }
+
+// get the "to" state pointers from d_states[0] to [1]
+      state_t_ptr t_to_state = &(d_states[1][t_out_state]);
+      t_connection0->d_to = t_to_state;
+      t_connection0->d_to_ndx = t_out_state;
+      float* t_output_bit0 = t_connection0->d_output_bits;
+
+// get the "to" state pointers from d_states[1] to [0]
+      t_to_state = &(d_states[0][t_out_state]);
+      t_connection1->d_to = t_to_state;
+      t_connection1->d_to_ndx = t_out_state;
+      float* t_output_bit1 = t_connection1->d_output_bits;
+
+// determine the ideal output values: loop over all outputs
+      size_t t_vec_ctr = 0;
+      for (size_t s = 0; s < d_n_code_outputs; s++) {
+
+// loop over all inputs, xor'ing the result each time
+       int t_out_result = 0;
+       t_mem_ptr = t_memory;
+       for (size_t t = 0; t < d_n_code_inputs; t++) {
+#if DO_PRINT_DEBUG_INST_1
+         std::cout << "b_i = " << n2bs (t_out_result, t_mem_print_bits) <<
+           ", st[" << t << "] = " << n2bs ((*t_mem_ptr), t_mem_print_bits) <<
+           ", cg[" << t_vec_ctr << "] = " <<
+           n2bs (d_code_generators[t_vec_ctr], t_mem_print_bits) <<
+           ", st[] & cg[] = " << n2bs ((*t_mem_ptr) &
+                                       d_code_generators[t_vec_ctr],
+                                       t_mem_print_bits);
+#endif
+         t_out_result ^= ((*t_mem_ptr++) &
+                          d_code_generators[t_vec_ctr++]);
+#if DO_PRINT_DEBUG_INST_1
+         std::cout << ", b_o = " <<
+           n2bs (t_out_result, t_mem_print_bits) << '\n';
+#endif
+       }
+#if DO_PRINT_DEBUG_INST_1
+       std::cout << "b_r = " << n2bs (t_out_result, t_mem_print_bits);
+#endif
+// sum the number of set bits, mod 2, for the output bit
+       size_t t_out_bit = t_out_result & 1;
+       for (size_t v = d_max_memory; v > 0; v--) {
+         t_out_result >>= 1;
+         t_out_bit ^= (t_out_result & 1);
+       }
+
+// store the result for this particular output stream,
+// converting the bit 1 -> +1.0, and 0 -> -1.0
+        float t_out_value = (float)(((int)(t_out_bit << 1)) - 1);
+       *t_output_bit0++ = t_out_value;
+       *t_output_bit1++ = t_out_value;
+#if DO_PRINT_DEBUG_INST_1
+       std::cout << ", o_v = " << t_out_value << "\n";
+#endif
+
+// finished (for) all output values
+      }
+// finished (for) over all possible input values
+    }
+// finished (for) over all possible states
+  }
+
+// so now d_states is/are completely populated!
+// These make for simple access to looping over all possible inputs or
+// outputs for a given state to determine what the path with the best
+// metric is.
+
+#if DO_PRINT_DEBUG_INST_2
+// loop over all possible memory states
+  std::cout << "State Tables\n";
+  t_state0 = d_states[0];
+  t_state1 = d_states[1];
+  for (size_t n = 0; n < d_n_states; n++, t_state0++, t_state1++) {
+    std::cout << "d_s[0][" << n << "] = " << t_state0 << "\n";
+// loop over all possible input values, 1 bit per input stream
+    connection_t_ptr t_connection0 = t_state0->d_connections;
+    for (size_t q = 0; q < d_n_input_combinations; q++, t_connection0++) {
+      std::cout << "s0[" << n2bs (n, t_state_print_bits) << "][" <<
+       n2bs (q, d_n_code_inputs+1) << "] = " << t_connection0 <<
+       " -> s1[" << n2bs (t_connection0->d_to_ndx, t_state_print_bits) <<
+       "] = " << t_connection0->d_to << "\n";
+    }
+    std::cout << "d_s[1][" << n << "] = " << t_state1 << "\n";
+    connection_t_ptr t_connection1 = t_state1->d_connections;
+    for (size_t q = 0; q < d_n_input_combinations; q++, t_connection1++) {
+      std::cout << "s1[" << n2bs (n, t_state_print_bits) << "][" <<
+       n2bs (q, d_n_code_inputs+1) << "] = " << t_connection1 <<
+       " -> s0[" << n2bs (t_connection1->d_to_ndx, t_state_print_bits) <<
+       "] = " << t_connection1->d_to << "\n";
+    }
+  }
+
+  traceback_t_hdl t_out_bufs = d_out_buf;
+  for (size_t n = 0; n < d_n_traceback_els; n++, *t_out_bufs++) {
+    traceback_t_ptr t_out_buf = *t_out_bufs;
+    for (size_t m = 0; m < d_n_states; m++, t_out_buf++) {
+      std::cout << "tb[" << n << "] = " << t_out_bufs <<
+       ", &tb[" << n << "][" << m << "] = " << (&d_out_buf[n][m]) <<
+       ", tb[" << n << "," << m << "] = " << t_out_buf << "\n";
+    }
+  }
+
+  std::cout << "Done with instantiation.\n";
+#endif
+}
+
+gr_decoder_viterbi_block_soft_full::~gr_decoder_viterbi_block_soft_full
+()
+{
+// reverse over from allocation
+
+  delete [] d_up_term_states_ndx[0];
+  delete [] d_up_term_states_ndx[1];
+
+// delete the state's structures
+  state_t_ptr t_state = d_states[0];
+  for (size_t n = d_n_states; n > 0; n--, t_state++) {
+    connection_t_ptr t_connection = t_state->d_connections;
+    for (size_t m = d_n_input_combinations; m > 0; m--, t_connection++) {
+      delete [] t_connection->d_output_bits;
+    }
+    delete [] t_state->d_connections;
+  }
+  delete [] d_states[0];
+
+  t_state = d_states[1];
+  for (size_t n = d_n_states; n > 0; n--, t_state++) {
+    connection_t_ptr t_connection = t_state->d_connections;
+    for (size_t m = d_n_input_combinations; m > 0; m--, t_connection++) {
+      delete [] t_connection->d_output_bits;
+    }
+    delete [] t_state->d_connections;
+  }
+  delete [] d_states[1];
+
+// delete the save buffer
+  char** t_save_buffer = d_save_buffer;
+  for (size_t n = 0; n < d_n_code_inputs; n++) {
+    delete [] (*t_save_buffer++);
+  }
+  delete [] d_save_buffer;
+
+// delete the output buffer
+  traceback_t_hdl t_out_buf = d_out_buf;
+  for (size_t n = d_n_traceback_els; n > 0; n--) {
+    delete [] (*t_out_buf++);
+  }
+  delete [] d_out_buf;
+}
+
+void gr_decoder_viterbi_block_soft_full::reset_metrics (u_char which)
+{
+  state_t_ptr t_state = d_states[which&1];
+  for (size_t n = d_n_states; n > 0; n--, t_state++) {
+    t_state->d_max_metric = -1e10;
+#if 0
+// probably don't need to do these, try removing them later
+    t_state->d_max_state_ndx = 0;
+    t_state->d_max_input = -1;
+#endif
+  }
+}
+
+void gr_decoder_viterbi_block_soft_full::zero_metrics (u_char which)
+{
+  state_t_ptr t_state = d_states[which&1];
+  for (size_t n = d_n_states; n > 0; n--, t_state++) {
+    t_state->d_max_metric = 0;
+#if 0
+// probably don't need to do these, try removing them later
+    t_state->d_max_state_ndx = -1;
+    t_state->d_max_input = -1;
+#endif
+  }
+}
+
+void gr_decoder_viterbi_block_soft_full::forecast
+(int noutput_items,
+ gr_vector_int &ninput_items_required)
+{
+  int ninput_items = fixed_rate_noutput_to_ninput (noutput_items);
+
+  int ninputs = ninput_items_required.size();
+  for (int n = 0; n < ninputs; n++)
+    ninput_items_required[n] = ninput_items;
+}
+
+/*
+ * Compute the number of input items (soft symbols [floats]) needed to produce
+ * 'noutput' items (elements).  For convolutional decoders, there is 1
+ * bit output per bit input per stream, with the addition of a some
+ * bits for trellis termination if selected.  Without termination,
+ * there is exactly 1:1 input to output (1 symbol in to 1 bit out),
+ * no matter the encoding type.
+ *
+ * if (not terminating), then get the number of output bytes.
+ *
+ * otherwise, find the number of frames (not necessarily and integer),
+ * and then compute the number of input bits (including termination)
+ * required to produce those frames.  Subtract the number of bits
+ * leftover from the previous computation, then find the number of input
+ * elements (soft symbols), ceil'd to make sure there are enough.
+ *
+ * finally, if the input streams are mux'ed, then multiply by the
+ * number of inputs.
+ */
+
+int
+gr_decoder_viterbi_block_soft_full::fixed_rate_noutput_to_ninput
+(int noutput_items)
+{
+  int t_ninput_items = 0;
+  int t_noutput_bits = (noutput_items * d_out_stream_el_size_bytes *
+                        g_num_bits_per_byte) - d_n_saved_bits;
+// if there are enough saved bits, just use those, no inputs required
+  if (t_noutput_bits <= 0)
+    return (t_ninput_items);
+
+// remove any bits already in the decoding trellis
+  if (d_time_count != 0) {
+    int t_time_bits = ((d_time_count > d_frame_size_bits) ? 0 :
+                      d_frame_size_bits - d_time_count);
+    t_noutput_bits -= t_time_bits;
+    t_ninput_items += t_time_bits;
+  }
+// if completing this trellis doesn't create enough outputs ...
+  if (t_noutput_bits > 0) {
+
+// there is a 1:1 ratio between input symbols and output bits (per
+// stream), except for termination bits which are already taken into
+// account in the total # of input bits per stream class variable;
+// need to round the # output bits to the
+
+// find the number of frames, ceil'd to the next higher integer
+    int t_nframes = (int) ceilf (((float) t_noutput_bits) /
+                                ((float) d_frame_size_bits));
+// find the number of required input bits
+    t_ninput_items += t_nframes * d_n_total_input_bits_per_stream;
+  }
+
+// if doing mux'ing, there are more elements in the single input
+  if (d_do_mux_inputs == true) {
+    t_ninput_items *= d_n_code_outputs;
+  }
+  return (t_ninput_items);
+}
+
+int
+gr_decoder_viterbi_block_soft_full::general_work
+(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+#if DO_TIME_THOUGHPUT
+  struct timeval t_tp;
+  start_timer (&t_tp);
+#endif
+#if DO_PRINT_DEBUG
+  size_t t_state_print_bits = (d_max_memory * d_n_code_inputs) + 1;
+  size_t t_mem_print_bits = d_max_memory + 2;
+#endif
+// setup variables for quicker access
+  const float **in_buf = (const float **) &input_items[0];
+  char **out_buf = (char **) &output_items[0];
+  int t_in_buf_ndx = 0, t_out_buf_ndx = 0;
+  int t_out_bit_shift = 0;
+  int t_ninput_items = fixed_rate_noutput_to_ninput (noutput_items);
+  int t_noutput_bytes = noutput_items * d_out_stream_el_size_bytes;
+
+#if DO_PRINT_DEBUG_INST
+  std::cout << "# output items = " << noutput_items << " (" <<
+    t_noutput_bytes << " Bytes, " << (t_noutput_bytes * g_num_bits_per_byte) <<
+    " bits), # input items = " << t_ninput_items << " Symbols\n";
+  for (size_t n = 0; n < ninput_items.size(); n++) {
+    std::cout << "# input items [" << n << "] = " << ninput_items[n] << "\n";
+  }
+#endif
+
+// put any leftover bits into the output
+  if (d_n_saved_bits != 0) {
+// copy the leftover from the save buffer
+// check to make sure it will all fit
+    size_t t_noutput_bits = t_noutput_bytes * g_num_bits_per_byte;
+    size_t t_n_copy;
+    if (t_noutput_bits < d_n_saved_bits) {
+// asking for fewer bits than available; set to copy
+// just what's being asked for
+      t_n_copy = t_noutput_bytes;
+    } else {
+// asking for at least as many bits as available; set to copy all
+      t_out_buf_ndx = d_n_saved_bits / g_num_bits_per_byte;
+      t_out_bit_shift = d_n_saved_bits % g_num_bits_per_byte;
+      t_n_copy = t_out_buf_ndx + (t_out_bit_shift != 0 ? 1 : 0);
+    }
+// do the copy for all output streams (code inputs)
+// copy starting at save buffer index "start"
+    for (size_t n = 0; n < d_n_code_inputs; n++)
+      bcopy (&(d_save_buffer[n][d_n_saved_bits_start_ndx]),
+            out_buf[n], t_n_copy);
+#if DO_PRINT_DEBUG_INST
+    std::cout << "Copied " << t_n_copy << " Byte" <<
+      (t_n_copy != 1 ? "s" : "") << ": s_b[][" <<
+      d_n_saved_bits_start_ndx << "] => o_b[][0]\n" <<
+      "# saved bits = " << d_n_saved_bits <<
+      ", o_b_ndx = " << t_out_buf_ndx <<
+      ", bit shift = " << t_out_bit_shift << "\n";
+#endif
+//  update the number of saved bits and start
+    if (t_noutput_bits < d_n_saved_bits) {
+// asking for fewer bit than available: update
+// the number of saved bits and their starting index
+      d_n_saved_bits_start_ndx += t_noutput_bytes;
+      d_n_saved_bits -= (t_noutput_bytes * g_num_bits_per_byte);
+#if DO_PRINT_DEBUG_INST
+      std::cout << "Updated # saved bits = " << d_n_saved_bits <<
+       ", index = " << d_n_saved_bits_start_ndx << "\n";
+#endif
+// nothing to consume; return the desired number of output items
+      return (noutput_items);
+    } else {
+      d_n_saved_bits_start_ndx = d_n_saved_bits = 0;
+    }
+  }
+#if DO_PRINT_DEBUG_INST
+  std::cout << "Starting FSM in state: " <<
+    (d_fsm == fsm_dec_init ? "init" :
+     (d_fsm == fsm_dec_doing_up ? "up" :
+      (d_fsm == fsm_dec_doing_middle ? "middle" :
+       (d_fsm == fsm_dec_doing_term ? "term" :
+       (d_fsm == fsm_dec_output ? "output" : "unknown"))))) << "\n";
+#endif
+
+// while there are input items to create
+  while (t_out_buf_ndx < t_noutput_bytes) {
+#if DO_PRINT_DEBUG_FMS
+    std::cout << "Starting 'while': processing " << t_in_buf_ndx << " of " <<
+      t_ninput_items << " items.\nJumping to state '" <<
+      (d_fsm == fsm_dec_init ? "init" :
+       (d_fsm == fsm_dec_doing_up ? "up" :
+       (d_fsm == fsm_dec_doing_middle ? "middle" :
+        (d_fsm == fsm_dec_doing_term ? "term" :
+         (d_fsm == fsm_dec_output ? "output" : "unknown"))))) << "'\n";
+#endif
+// jump to the correct state in the fsm
+    switch (d_fsm) {
+    case fsm_dec_doing_up:
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Starting fsm_dec_doing_up\n";
+#endif
+// set the number of up_down indices
+      size_t t_n_up_down_ndx = 1 << (d_n_code_inputs *
+                                    d_time_count);
+// stay in this state until the correct number of input symbols are
+// reached; exit also if we run out of input symbols to process
+      while ((d_time_count < d_max_memory) &
+            (t_in_buf_ndx < t_ninput_items)) {
+#if DO_PRINT_DEBUG_UP_0
+       std::cout << "Doing 'while' loop:\n" <<
+         "t_n_up_down_ndx    = " << t_n_up_down_ndx << "\n" <<
+         "d_time_count       = " << d_time_count << "\n" <<
+         "d_max_memory       = " << d_max_memory << "\n" <<
+         "t_in_buf_ndx       = " << t_in_buf_ndx << "\n" <<
+         "t_ninput_items     = " << t_ninput_items << "\n";
+#endif
+// use the "from" states, loop over all inputs and compute the metric for
+// each & store it in the "to" state at the end of the connection.
+// no need to compare metrics yet, since none join into any given state
+
+#if 0
+// reset the "to" state's metrics
+// probably don't need to do this; try removing later
+        reset_metrics (d_states_ndx ^ 1);
+#if DO_PRINT_DEBUG_UP
+       std::cout << "Reset Metrics\n";
+#endif
+#endif
+
+// reset the state's index for each set of new inputs
+       size_t* t_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx];
+       size_t* t_next_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx ^ 1];
+// loop over all current stored "up" states
+       for (size_t n = 0; n < t_n_up_down_ndx; n++) {
+         size_t t_state_ndx = *t_state_ndx_ptr++;
+// get a pointer to this state's structure
+         state_t_ptr t_state = &(d_states[d_states_ndx][t_state_ndx]);
+// get the connections for all inputs
+         connection_t_ptr t_connection = t_state->d_connections;
+#if DO_PRINT_DEBUG_UP_0
+         std::cout << "Looping over all 'up' states:\n" <<
+           "n                  = " << n << "\n" <<
+           "t_n_up_down_ndx    = " << t_n_up_down_ndx << "\n" <<
+           "d_states_ndx       = " << d_states_ndx << "\n" <<
+           "t_state_ndx        = " << t_state_ndx << "\n" <<
+           "d_n_input_combs    = " << d_n_input_combinations << "\n" <<
+           "t_state            = " << t_state << "\n" <<
+           "t_connection       = " << t_connection << "\n";
+#endif
+// loop over all possible input values, 1 bit per input stream
+         for (size_t q = 0; q < d_n_input_combinations; q++, t_connection++) {
+// find the "to" state for this connection
+           state_t_ptr t_to_state = t_connection->d_to;
+// get the output bits for this connection
+           float* t_output_bit = t_connection->d_output_bits;
+// start with this state's metric
+           float t_metric = t_state->d_max_metric;
+#if DO_PRINT_DEBUG_UP_0
+           std::cout <<
+             "to state index     = " << t_connection->d_to_ndx << "\n" <<
+             "current metric     = " << t_metric << "\n";
+#endif
+           if (d_do_mux_inputs == true) {
+// if using mux'ed input streams, handle differently
+              const float* t_in_buf = &(in_buf[0][t_in_buf_ndx]);
+// loop over all encoder-output values
+             for (size_t r = d_n_code_outputs; r > 0; r--) {
+#if DO_PRINT_DEBUG_UP
+               std::cout << "in_sym = " << *t_in_buf << ", code_out_bit = " <<
+                 *t_output_bit << " ==> metric -> ";
+#endif
+               t_metric += ((*t_in_buf++) * (*t_output_bit++));
+#if DO_PRINT_DEBUG_UP
+               std::cout << t_metric << "\n";
+#endif
+             }
+           } else {
+// loop over all encoder-output values
+             for (size_t r = 0; r < d_n_code_outputs; r++) {
+#if DO_PRINT_DEBUG_UP
+               std::cout << "in_sym = " << in_buf[r][t_in_buf_ndx] <<
+                 ", code_out_bit = " << *t_output_bit << " ==> metric -> ";
+#endif
+               t_metric += (in_buf[r][t_in_buf_ndx] * (*t_output_bit++));
+#if DO_PRINT_DEBUG_UP
+               std::cout << t_metric << "\n";
+#endif
+             }
+           }
+// get the "to" state index
+           size_t t_to_ndx = t_connection->d_to_ndx;
+// store the metric in the "to" state; should not have been used before
+           t_to_state->d_max_metric = t_metric;
+// add the "to" state index to the "up" state list
+           *t_next_state_ndx_ptr++ = t_to_ndx;
+// update the traceback structure, depending on which variety it is
+// doing full trellis before decoding; use d_out_buf
+// simple: get the current state & output state
+           traceback_t_ptr t_out_buf = &(d_out_buf[d_time_count]
+                                         [t_state_ndx]);
+           traceback_t_ptr t_next_out_buf = &(d_out_buf[d_time_count+1]
+                                              [t_to_ndx]);
+#if DO_PRINT_DEBUG_UP_1
+           std::cout << "d_o_b[" << d_time_count+1 << "] => d_o_b prev\n" <<
+             "ndx[" << n << "] == " << t_state_ndx <<
+             ", s[" << n2bs(t_state_ndx,t_state_print_bits) <<
+             "]: max_ndx = " <<
+             n2bs(t_state->d_max_state_ndx,t_state_print_bits) <<
+             ", input = " << n2bs(q, d_n_code_inputs+1) <<
+             ": " << t_next_out_buf << " => " << t_out_buf << "\n";
+#endif
+// and connect output to the current, set inputs on output
+           t_next_out_buf->d_prev = t_out_buf;
+           t_next_out_buf->d_inputs = q;
+// finished (for) this input value
+         }
+// finished (for) this "up_term" state
+       }
+// increment the in_buf index, depending on mux'ing or not
+       t_in_buf_ndx += (d_do_mux_inputs == false) ? 1 : d_n_code_outputs;
+// increment the time counter
+        d_time_count++;
+// update the number of "up_term" states
+        d_up_term_ndx ^= 1;
+// increase the number of using states
+        t_n_up_down_ndx <<= d_n_code_inputs;
+// change which d_states' index to use as starting
+        d_states_ndx ^= 1;
+// finished (while) staying in this fsm state or not
+      }
+// if reached the end of doing the "up" part of the trellis,
+// switch states into the middle
+      if (d_time_count == d_max_memory) {
+#if DO_PRINT_DEBUG_FSM
+       std::cout << "Setting FSM to fsm_dec_doing_middle\n";
+#endif
+        d_fsm = fsm_dec_doing_middle;
+      }
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Exited fsm_dec_doing_up\n";
+#endif
+      break;
+    case (fsm_dec_doing_middle):
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Entered fsm_dec_doing_middle\n";
+#endif
+// stay in this state until the correct number of input symbols is
+// reached (if doing block coding), or until there are no more input
+// symbols to parse
+      while (((d_frame_size_bits != 0) &
+             (d_time_count < d_frame_size_bits) &
+             (t_in_buf_ndx < t_ninput_items)) |
+            ((d_frame_size_bits == 0) &
+             (t_in_buf_ndx < t_ninput_items))) {
+// use all states, loop over all inputs, compute the metric for
+// each; compare the current metric with all previous stored metric in the
+// endpoint of the connection to find the highest one.
+
+// reset the "to" state's metrics
+        reset_metrics (d_states_ndx ^ 1);
+// get the state's index for each set of new inputs
+       state_t_ptr t_state = d_states[d_states_ndx];
+#if DO_PRINT_DEBUG_MIDDLE
+       std::cout << "Time Count " << (d_time_count+1) << " of " <<
+         d_frame_size_bits << "\n" <<
+         "d_states_ndx = " << d_states_ndx << "\n";;
+#endif
+// loop over all current states
+       for (size_t n = 0; n < d_n_states; n++, t_state++) {
+// loop over all possible input values, 1 bit per input stream
+         connection_t_ptr t_connection = t_state->d_connections;
+#if DO_PRINT_DEBUG_MIDDLE_0
+         std::cout << "Looping over all 'middle' states: " <<
+           n << " of " << d_n_states << "\n";
+#endif
+         for (size_t q = 0; q < d_n_input_combinations; q++, t_connection++) {
+#if DO_PRINT_DEBUG_MIDDLE_0
+           std::cout << "Input = " << n2bs(q, d_n_code_inputs+1) << "\n";
+#endif
+// start with this state's metric
+           float t_metric = t_state->d_max_metric;
+// get the "to" state
+            state_t_ptr t_to_state = t_connection->d_to;
+// get that state's metric
+            float t_to_metric = t_to_state->d_max_metric;
+// see if the computation is even needed;
+// maximum change is d_n_code_outputs if all bits match exactly
+            if ((t_to_metric - t_metric) > ((float) 2*d_n_code_outputs)) {
+#if DO_PRINT_DEBUG_MIDDLE_0
+             std::cout << "!not computing metric!\n";
+#endif
+              continue;
+           }
+// metrics are close enough; do the computation and the compare
+// get the output bits for this connection
+           float* t_output_bit = t_connection->d_output_bits;
+           if (d_do_mux_inputs == true) {
+// if using mux'ed input streams, handle differently
+              const float* t_in_buf = &(in_buf[0][t_in_buf_ndx]);
+// loop over all encoder-output values
+             for (size_t r = d_n_code_outputs; r > 0; r--) {
+#if DO_PRINT_DEBUG_MIDDLE_0
+               std::cout << "in_sym = " << *t_in_buf << ", code_out_bit = " <<
+                 *t_output_bit << " ==> metric -> ";
+#endif
+               t_metric += ((*t_in_buf++) * (*t_output_bit++));
+#if DO_PRINT_DEBUG_MIDDLE_0
+               std::cout << t_metric << "\n";
+#endif
+             }
+           } else {
+// loop over all encoder-output values
+             for (size_t r = 0; r < d_n_code_outputs; r++) {
+#if DO_PRINT_DEBUG_MIDDLE_0
+               std::cout << "in_sym = " << in_buf[r][t_in_buf_ndx] <<
+                 ", code_out_bit = " << *t_output_bit << " ==> metric -> ";
+#endif
+               t_metric += (in_buf[r][t_in_buf_ndx] * (*t_output_bit++));
+#if DO_PRINT_DEBUG_MIDDLE_0
+               std::cout << t_metric << "\n";
+#endif
+             }
+           }
+// done with this input value; compare old and new metrics
+            if (t_metric > t_to_metric) {
+#if DO_PRINT_DEBUG_MIDDLE
+             std::cout << "New Metric to s[" <<
+               n2bs (t_connection->d_to_ndx,t_state_print_bits) << "]: ";
+             if (t_to_state->d_max_metric == -1e10) {
+               std::cout << "setting to ";
+             } else {
+               std::cout << "was s[" <<
+                 n2bs(t_to_state->d_max_state_ndx,t_state_print_bits) <<
+                 "]i[" << n2bs (t_to_state->d_max_input, d_n_code_inputs+1) <<
+                 "]@ " << t_to_state->d_max_metric << "  now ";
+             }
+             std::cout << "s[" << n2bs(n,t_state_print_bits) << "] i[" <<
+               n2bs (q, d_n_code_inputs+1) << "]@ " << t_metric << "\n";
+#endif
+// new metric is better; copy that info into the "to" state
+              t_to_state->d_max_metric = t_metric;
+              t_to_state->d_max_state_ndx = n;
+              t_to_state->d_max_input = q;
+            }
+// finished (for) this input value
+         }
+// finished (for) this state
+       }
+// done with all states and all inputs; now update the traceback structure
+// change which d_states' index to use as starting
+        d_states_ndx ^= 1;
+// get the state's index for the "to" set of new inputs to get the
+// "max" stuff from
+       t_state = d_states[d_states_ndx];
+// update the traceback structure
+// loop over all current states
+       traceback_t_ptr t_prev_out_bufs = d_out_buf[d_time_count];
+       traceback_t_ptr t_out_bufs = d_out_buf[d_time_count+1];
+#if DO_PRINT_DEBUG_MIDDLE_1
+       std::cout << "d_o_b[" << d_time_count+1 << "] => d_o_b prev\n";
+#endif
+       for (size_t n = d_n_states; n > 0; n--, t_state++) {
+// simple: get the current state & output state
+// and connect output to the current, set inputs on output
+         traceback_t_ptr t_out_buf = t_out_bufs++;
+         traceback_t_ptr t_prev_out_buf =
+           &(t_prev_out_bufs[t_state->d_max_state_ndx]);
+#if DO_PRINT_DEBUG_MIDDLE_1
+         std::cout << "s[" << n2bs(d_n_states-n,t_state_print_bits) <<
+           "]: max_ndx = " <<
+           n2bs(t_state->d_max_state_ndx,t_state_print_bits) <<
+           ", input = " << n2bs(t_state->d_max_input, d_n_code_inputs+1) <<
+           ": " << t_out_buf << " => " << t_prev_out_buf << "\n";
+#endif
+         t_out_buf->d_prev = t_prev_out_buf;
+         t_out_buf->d_inputs = t_state->d_max_input;
+// finished doing this state
+       }
+// increment the in_buf index, depending on mux'ing or not
+       t_in_buf_ndx += (d_do_mux_inputs == false) ? 1 : d_n_code_outputs;
+// increment the time counter
+        d_time_count++;
+// finished (while) staying in this fsm state or not
+      }
+      if ((d_frame_size_bits != 0) &
+          (d_time_count == d_frame_size_bits)) {
+#if DO_PRINT_DEBUG_FSM
+       std::cout << "Setting FSM to fsm_dec_doing_term\n";
+#endif
+        d_fsm = fsm_dec_doing_term;
+      }
+      break;
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Exited fsm_dec_doing_middle\n";
+#endif
+    case (fsm_dec_doing_term):
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Entered fsm_dec_doing_term\n";
+#endif
+// set the "next" up_down index to the end of their states
+      size_t t_time_count = d_max_memory - (d_time_count - d_frame_size_bits);
+      t_n_up_down_ndx = 1 << (d_n_code_inputs * t_time_count);
+// stay in this state until the correct number of input symbols are
+// reached; exit also if we run out of input symbols to process
+      while ((t_time_count > 0) &
+            (t_in_buf_ndx < t_ninput_items)) {
+#if DO_PRINT_DEBUG_TERM
+       std::cout << "Doing time " << (d_max_memory - t_time_count + 1) <<
+         " of " << d_max_memory << "; starting buf[" << t_in_buf_ndx <<
+         "] of [" << t_ninput_items << "]\n";
+#endif
+// use the "to" states,
+// FIXME: loop over just the "0" inputs
+// and compute the metric for
+// each, compare & store it in the "to" state at the end of the connection.
+
+// reset the "to" state's metrics
+        reset_metrics (d_states_ndx ^ 1);
+// reset the state's index for each set of new inputs
+       size_t* t_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx];
+       size_t* t_next_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx ^ 1];
+// loop over all current stored "term" state indeces
+       for (size_t n = 0; n < t_n_up_down_ndx; n++) {
+         size_t t_state_ndx = *t_state_ndx_ptr++;
+         state_t_ptr t_state = &(d_states[d_states_ndx][t_state_ndx]);
+// loop over just the all 0 input value (d_connections[0])
+         connection_t_ptr t_connection = t_state->d_connections;
+// get the "to" state
+          state_t_ptr t_to_state = t_connection->d_to;
+// start with this state's metric
+          float t_metric = t_state->d_max_metric;
+// get that state's metric
+          float t_to_metric = t_to_state->d_max_metric;
+#if DO_PRINT_DEBUG_TERM
+         std::cout << "Term state " << (n+1) << " of " << t_n_up_down_ndx <<
+           "; using d_s[" << d_states_ndx << "][" <<
+           n2bs(t_state_ndx,t_state_print_bits) << "]\n";
+#endif
+// see if the computation is even needed;
+// maximum change is d_n_code_outputs if all bits match exactly
+          if ((t_to_metric - t_metric) > ((float) 2*d_n_code_outputs)) {
+#if DO_PRINT_DEBUG_TERM
+           std::cout << "!not computing metric!\n";
+#endif
+           continue;
+         }
+// metrics are close enough; do the computation and the compare
+// get the output bits for this connection
+          float* t_output_bit = t_connection->d_output_bits;
+         if (d_do_mux_inputs == true) {
+// if using mux'ed input streams, handle differently
+            const float* t_in_buf = &(in_buf[0][t_in_buf_ndx]);
+// loop over all encoder-output values
+           for (size_t r = d_n_code_outputs; r > 0; r--) {
+             t_metric += ((*t_in_buf++) * (*t_output_bit++));
+           }
+         } else {
+// loop over all encoder-output values
+           for (size_t r = 0; r < d_n_code_outputs; r++) {
+              t_metric += (in_buf[r][t_in_buf_ndx] * (*t_output_bit++));
+           }
+         }
+// done with this input value; compare old and new metrics
+// see if it's the best metric
+          if (t_metric > t_to_metric) {
+#if DO_PRINT_DEBUG_TERM
+           std::cout << "New Metric to s[" <<
+             n2bs (t_connection->d_to_ndx,t_state_print_bits) << "]: ";
+           if (t_to_state->d_max_metric == -1e10) {
+             std::cout << "setting to ";
+           } else {
+             std::cout << "was s[" <<
+               n2bs(t_to_state->d_max_state_ndx,t_state_print_bits) <<
+               "]i[" << n2bs (t_to_state->d_max_input, d_n_code_inputs+1) <<
+               "]@ " << t_to_state->d_max_metric << "  now ";
+           }
+           std::cout << "s[" << n2bs(t_state_ndx,t_state_print_bits) <<
+             "] i[" << n2bs (0, d_n_code_inputs+1) << "]@ " << t_metric << 
"\n";
+#endif
+            t_to_state->d_max_metric = t_metric;
+            t_to_state->d_max_state_ndx = t_state_ndx;
+            t_to_state->d_max_input = 0;
+         }
+// add the "to" state's index to the "next" set of state's indices list
+          *t_next_state_ndx_ptr++ = t_connection->d_to_ndx;
+// finished (for) this state
+       }
+// done with all states and all inputs; now update the traceback structure
+// change which d_states' index to use as starting
+        d_states_ndx ^= 1;
+// update the number of "up_term" states
+        d_up_term_ndx ^= 1;
+// reduce the number of using states
+        t_n_up_down_ndx >>= d_n_code_inputs;
+// reset the state's index for each set of new inputs
+       t_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx];
+// update the traceback structure
+// loop over all current states
+       traceback_t_ptr t_prev_out_bufs = d_out_buf[d_time_count];
+       traceback_t_ptr t_out_bufs = d_out_buf[d_time_count+1];
+#if DO_PRINT_DEBUG_TERM_1
+       std::cout << "d_o_b[" << d_time_count+1 << "] => d_o_b prev\n";
+#endif
+// loop over all current stored "term" state indices
+       for (size_t n = 0; n < t_n_up_down_ndx; n++) {
+// get the start index and then pointer to each of the "to" states,
+// which hold the newest "max" stuff
+         size_t t_state_ndx = *t_state_ndx_ptr++;
+         state_t_ptr t_state = &(d_states[d_states_ndx][t_state_ndx]);
+// simple: get the current state & output state
+// and connect output to the current, set inputs on output
+         traceback_t_ptr t_out_buf = &(t_out_bufs[t_state_ndx]);
+         traceback_t_ptr t_prev_out_buf =
+           &(t_prev_out_bufs[t_state->d_max_state_ndx]);
+#if DO_PRINT_DEBUG_TERM_1
+         std::cout << "ndx[" << n << "] == " << t_state_ndx <<
+           ", s[" << n2bs(t_state_ndx,t_state_print_bits) <<
+           "]: max_ndx = " <<
+           n2bs(t_state->d_max_state_ndx,t_state_print_bits) <<
+           ", input = " << n2bs(t_state->d_max_input, d_n_code_inputs+1) <<
+           ": " << t_out_buf << " => " << t_prev_out_buf << "\n";
+#endif
+         t_out_buf->d_prev = t_prev_out_buf;
+         t_out_buf->d_inputs = t_state->d_max_input;
+// finished (for) this state
+       }
+// increment the in_buf index, depending on mux'ing or not
+       t_in_buf_ndx += (d_do_mux_inputs == false) ? 1 : d_n_code_outputs;
+// increment the time counters
+        t_time_count--;
+        d_time_count++;
+// finished (while) staying in this fsm state or not
+      }
+      if (t_time_count == 0) {
+// finished this trellis, now move as much of the decoded input to the
+// output buffer as possible
+#if DO_PRINT_DEBUG_FSM
+       std::cout << "Setting FSM to fsm_dec_output\n";
+#endif
+       d_fsm = fsm_dec_output;
+      }
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Exited fsm_dec_doing_term\n";
+#endif
+      break;
+    case (fsm_dec_output):
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Entered fsm_dec_output.\n";
+#endif
+// this is done in reverse bit order (last time to first time)
+// using the traceback structure in d_out_buf, starting with
+// the maximum valued one in the last time slot, then using
+// the traceback's "d_prev" link to trace the trellis back
+
+// see where the output data will terminate
+      int t_next_out_buf_ndx = (t_out_buf_ndx +
+                               (d_frame_size_bits / g_num_bits_per_byte));
+      int t_next_out_bit_shift = (t_out_bit_shift +
+                                 (d_frame_size_bits % g_num_bits_per_byte));
+      if (t_next_out_bit_shift >= g_num_bits_per_byte) {
+       t_next_out_bit_shift -= g_num_bits_per_byte;
+       t_next_out_buf_ndx++;
+      }
+#if DO_PRINT_DEBUG_OUTPUT
+      std::cout << "First bit in at out[][" << t_out_buf_ndx << "].[" <<
+       t_out_bit_shift << "] -> " << d_frame_size_bits << " bits == " <<
+       (d_frame_size_bits / g_num_bits_per_byte) << " Byte" <<
+       ((d_frame_size_bits / g_num_bits_per_byte) != 1 ? "s" : "") <<
+       " + " << (d_frame_size_bits % g_num_bits_per_byte) << " bit" <<
+       ((d_frame_size_bits % g_num_bits_per_byte) != 1 ? "s" : "") <<
+       "\nNext set of bits start at out[][" << t_next_out_buf_ndx <<
+       "].[" << t_next_out_bit_shift << "]\n";
+#endif
+// find the starting traceback structure
+      traceback_t_ptr t_out_buf;
+      if (d_do_termination == true) {
+// FIXME: assume termination state == 0
+#if DO_PRINT_DEBUG_OUTPUT_0
+       std::cout << "Using termination; going through trellis for " <<
+         d_max_memory << " bit" <<
+         ((d_max_memory != 1) ? "s" : "") << "\n";
+#endif
+       t_out_buf = &(d_out_buf[d_time_count][0]);
+#if DO_PRINT_DEBUG_OUTPUT_0
+       std::cout << "Starting traceback ptr " << t_out_buf << "\n";
+#endif
+// skip over the termination bits
+       for (size_t n = d_max_memory; n > 0; n--) {
+         t_out_buf = t_out_buf->d_prev;
+#if DO_PRINT_DEBUG_OUTPUT_0
+         std::cout << "Next traceback ptr " << t_out_buf << "\n";
+#endif
+       }
+      } else {
+// no termination but doing block coding;
+// FIXME: use the state with the bext metric
+// get the state's index for each set of new inputs
+       state_t_ptr t_state = d_states[d_states_ndx];
+       float t_max_metric = t_state->d_max_metric;
+       size_t t_max_state_ndx = 0;
+       t_state++;
+// loop over all current states
+       for (size_t n = 1; n < d_n_states; n++, t_state++) {
+// start with this state's metric
+         float t_metric = t_state->d_max_metric;
+// compare with current max
+         if (t_metric > t_max_metric) {
+           t_max_metric = t_metric;
+           t_max_state_ndx = n;
+         }
+       }
+// get the correct out_buf reference to start with
+       t_out_buf = &(d_out_buf[d_time_count][t_max_state_ndx]);
+      }
+#if DO_PRINT_DEBUG_OUTPUT
+      std::cout << "Found starting traceback ptr " << t_out_buf <<
+       "; getting all " << d_frame_size_bits << " bits per stream.\n";
+#endif
+// now we've got the starting traceback structure address;
+// check to make sure there is enough space in each output buffer
+      size_t t_frame_bit_ndx = d_frame_size_bits;
+      if ((t_next_out_buf_ndx > t_noutput_bytes) |
+         ((t_next_out_buf_ndx == t_noutput_bytes) &
+          (t_next_out_bit_shift != 0))) {
+// not enough space for all output bits;
+// find the number of extra bits to save
+       size_t t_save_buf_ndx = t_next_out_buf_ndx - t_noutput_bytes;
+       size_t t_n_extra_bits = ((t_save_buf_ndx * g_num_bits_per_byte) +
+                                t_next_out_bit_shift);
+// set the number of saved bits
+       d_n_saved_bits = t_n_extra_bits;
+// remove the extra bits from the number to copy to the output buffer
+       t_frame_bit_ndx -= t_n_extra_bits;
+// find the actual output buf index, once we get there
+       t_next_out_buf_ndx -= t_save_buf_ndx;
+#if DO_PRINT_DEBUG_OUTPUT
+       std::cout << "Not enough output buffer space:\n" <<
+         "len (o_b) = " << t_noutput_bytes << " ==> " <<
+         t_n_extra_bits << " extra bit" <<
+         (t_n_extra_bits != 1 ? "s" : "") << " == " <<
+         t_save_buf_ndx << " Byte" <<
+         (t_save_buf_ndx != 1 ? "s" : "") << ", " <<
+         t_next_out_bit_shift << " bit" <<
+         (t_next_out_bit_shift != 1 ? "s" : "") << "\n";
+#endif
+// zero each output buffers' bytes
+       size_t t_n_zero = t_save_buf_ndx + (t_next_out_bit_shift ? 1 : 0);
+#if DO_PRINT_DEBUG_OUTPUT
+       size_t t_n_out_bytes = ((d_frame_size_bits / g_num_bits_per_byte) +
+                               ((d_frame_size_bits % g_num_bits_per_byte) ? 1 
: 0));
+       std::cout << "Zeroing save buffer from for " << t_n_zero <<
+         " Byte" << (t_n_zero != 1 ? "s" : "") << " (of " <<
+         d_frame_size_bits << " bit" <<
+         (d_frame_size_bits != 1 ? "s" : "") << " == " << t_n_out_bytes <<
+         " Byte" << (t_n_out_bytes != 1 ? "s" : "") << ")\n";
+#endif
+       for (size_t m = 0; m < d_n_code_inputs; m++)
+         bzero (d_save_buffer[m], t_n_zero);
+// loop over all extra bits
+       for (size_t n = t_n_extra_bits; n > 0; n--) {
+// first decrement the output bit & byte as necessary
+         if (--t_next_out_bit_shift < 0) {
+           t_next_out_bit_shift += g_num_bits_per_byte;
+           t_save_buf_ndx--;
+         }
+// get the encoder inputs to output
+         size_t t_inputs = t_out_buf->d_inputs;
+// loop over all code inputs (decoder-outputs), 1 bit per stream
+         for (size_t m = 0; m < d_n_code_inputs; m++) {
+           d_save_buffer[m][t_save_buf_ndx] |=
+             ((t_inputs & 1) << t_next_out_bit_shift);
+           t_inputs >>= 1;
+         }
+         t_out_buf = t_out_buf->d_prev;
+#if DO_PRINT_DEBUG_OUTPUT_0
+         std::cout << "Next traceback ptr " << t_out_buf << "\n";
+#endif
+       }
+// at exit, "t_out_buf_ndx" should be == t_noutput_bytes, and
+// "t_out_bit_shift" should be 0; check these!
+#if DO_PRINT_DEBUG_OUTPUT
+       std::cout << "n_o_b_ndx (" << t_next_out_buf_ndx << ") ?=? " <<
+         "#o_B (" << t_noutput_bytes << ") & t_o_b_sh (" <<
+         t_next_out_bit_shift << ") ?=? 0\n";
+       assert (t_next_out_buf_ndx == t_noutput_bytes);
+       assert (t_next_out_bit_shift == 0);
+#endif
+      }
+// set the correct output buffer index and bit shift
+      t_out_bit_shift = t_next_out_bit_shift;
+      t_out_buf_ndx = t_next_out_buf_ndx;
+// copy any remaining bits looping backwards in bit-time
+// through the traceback trellis
+      for (size_t n = t_frame_bit_ndx; n > 0; n--) {
+// first decrement the output bit & byte as necessary
+       if (--t_out_bit_shift < 0) {
+         t_out_bit_shift += g_num_bits_per_byte;
+         t_out_buf_ndx--;
+       }
+// get the encoder inputs to output
+       size_t t_inputs = t_out_buf->d_inputs;
+// loop over all code inputs (decoder-outputs), 1 bit per stream
+       for (size_t m = 0; m < d_n_code_inputs; m++) {
+         out_buf[m][t_out_buf_ndx] |= ((t_inputs & 1) << t_out_bit_shift);
+         t_inputs >>= 1;
+       }
+       t_out_buf = t_out_buf->d_prev;
+#if DO_PRINT_DEBUG_OUTPUT_0
+       std::cout << "Next traceback ptr " << t_out_buf << "\n";
+#endif
+      }
+// set the next output byte and bit-shift
+      t_out_bit_shift = t_next_out_bit_shift;
+      t_out_buf_ndx = t_next_out_buf_ndx;
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Set FSM to fsm_dec_init\n";
+#endif
+      d_fsm = fsm_dec_init;
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Exited fsm_dec_output\n";
+#endif
+      break;
+    case (fsm_dec_init):
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Entered fsm_dec_init\n";
+#endif
+// this is called immediately (first input bit upon startup),
+// or after termination of a trellis.
+
+// reset states to the 0'th one
+      d_up_term_ndx = d_states_ndx = 0;
+// zero the metrics for those states
+      zero_metrics (0);
+#if 0
+// might not need to do this; check and see after it works
+// reset up_term states and number so that there is 1 item, the "0" state.
+      bzero (d_up_term_states_ndx[0], sizeof (size_t) * d_n_states);
+      bzero (d_up_term_states_ndx[1], sizeof (size_t) * d_n_states);
+#else
+      d_up_term_states_ndx[0][0] = 0;
+#endif
+// reset time count back to the start
+      d_time_count = 0;
+#if 0
+// reset the traceback structures
+// might not need to do this; check and see after it works
+      traceback_t_hdl t_out_bufs = d_out_buf;
+      for (size_t n = d_n_traceback_els; n > 0; n--) {
+       traceback_t_ptr t_out_buf = (*t_out_bufs++);
+       for (size_t m = d_n_states; m > 0; m--, t_out_buf++) {
+         t_out_buf->d_prev = NULL;
+         t_out_buf->d_inputs = -1;
+       }
+      }
+#endif
+// set the fsm to "doing up"
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Set FSM to fsm_dec_doing_up\n";
+#endif
+      d_fsm = fsm_dec_doing_up;
+#if DO_PRINT_DEBUG_FSM
+      std::cout << "Exited fsm_dec_init\n";
+#endif
+      break;
+// should never get here!
+    default:
+      assert (0);
+// done (switch) with FSM
+    }
+// done (while) there are inputs
+  }
+
+// consume all of the input items on all input streams
+// "ninput_items[]" doesn't seem to be reliable,
+// so compute this from the actual number of frames processed
+#if DO_PRINT_DEBUG_EXIT
+  std::cout << "Exiting FSM in state: " <<
+    (d_fsm == fsm_dec_init ? "init" :
+     (d_fsm == fsm_dec_doing_up ? "up" :
+      (d_fsm == fsm_dec_doing_middle ? "middle" :
+       (d_fsm == fsm_dec_doing_term ? "term" :
+       (d_fsm == fsm_dec_output ? "output" : "unknown"))))) << "\n" <<
+    "Consuming " << t_in_buf_ndx <<
+    " input items on each input stream (of " << t_ninput_items << ").\n";
+#endif
+  consume_each (t_in_buf_ndx);
+
+// make sure the number of output items makes sense
+// t_out_buf_ndx always points to the current index
+// t_out_bit_shift always points to the next bit position to be written
+  int t_leftover_bytes = t_out_buf_ndx % d_out_stream_el_size_bytes;
+  int t_leftover_bits = ((t_leftover_bytes * g_num_bits_per_byte) +
+                        t_out_bit_shift);
+  int t_noutput_items = noutput_items;
+#if DO_PRINT_DEBUG_EXIT
+  std::cout << "Final o_b[" << t_out_buf_ndx << "][" <<
+    t_out_bit_shift << "] of " << t_noutput_bytes <<
+    ", el_size = " << d_out_stream_el_size_bytes <<
+    ", lo_Bytes = " << t_leftover_bytes <<
+    ", t_lo_bits = " << t_leftover_bits << "\n" <<
+    "Desired # output items = " << noutput_items << "\n";
+#endif
+  if (t_leftover_bits != 0) {
+    // should never get here!
+#if 1
+    assert (0);
+#else
+    int t_ndx = t_out_buf_ndx - t_leftover_bytes;
+    size_t t_n_copy = t_leftover_bytes + ((t_out_bit_shift != 0) ? 1 : 0);
+    assert (t_n_copy <= d_out_stream_el_size_bytes);
+// copy the leftover into the save buffer
+    for (size_t n = 0; n < d_n_code_inputs; n++) {
+      bcopy (&(out_buf[n][t_ndx]), d_save_buffer[n], t_n_copy);
+    }
+    t_noutput_items = t_ndx / d_out_stream_el_size_bytes;
+    d_n_saved_bits = t_leftover_bits;
+#if DO_PRINT_DEBUG_EXIT
+    std::cout << "Copied " << t_n_copy << " Byte" <<
+      (t_n_copy != 1 ? "s" : "") << " from o_b[][" << t_ndx <<
+      "] into each save buffer.\n" <<
+      "Actual #output items = " << t_noutput_items <<
+      ", # saved bit(s) = " << d_n_saved_bits << "\n";
+#endif
+#endif
+  }
+
+#if DO_TIME_THOUGHPUT
+  u_long d_t = end_timer (&t_tp);
+
+  std::cout << "dec_blk_conv_soft_full: Completed " << t_ninput_items <<
+    " bits in " << d_t << " usec => " <<
+    1e6*(((double)(t_ninput_items))/((double) d_t)) <<
+    " b/s\n";
+#endif
+
+// returns number of items written to each output stream
+  return (t_noutput_items);
+}

Index: libecc/decoder_viterbi_block_full.h
===================================================================
RCS file: libecc/decoder_viterbi_block_full.h
diff -N libecc/decoder_viterbi_block_full.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libecc/decoder_viterbi_block_full.h 5 Jul 2006 17:49:58 -0000       1.1
@@ -0,0 +1,107 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef INCLUDED_DECODER_VITERBI_BLOCK_FULL_H
+#define INCLUDED_DECODER_VITERBI_BLOCK_FULL_H
+
+#include <decoder_viterbi.h>
+
+class decoder_viterbi_block_full : public gr_block
+{
+/*!
+ * \brief Decode the incoming streams using a Viterbi-style decoder
+ *
+ * input: encoded data as soft symbols, either as individual
+ *     streams or mux'ed into 1 stream.
+ *
+ * output: stream(s) of user-defined element size.
+ */
+
+public:
+  gr_decoder_viterbi_block_soft_full (int frame_size_bits,
+                                     int n_code_inputs,
+                                     int n_code_outputs,
+                                     std::vector<int> code_generator,
+                                     bool do_termination = true,
+                                     int start_memory_state = 0,
+                                     int end_memory_state = 0);
+
+  ~decoder_viterbi_block_soft_full ();
+
+  virtual void forecast (int noutput_items,
+                        gr_vector_int &ninput_items_required);
+
+  virtual int general_work (int noutput_items,
+                           gr_vector_int &ninput_items,
+                           gr_vector_const_void_star &input_items,
+                           gr_vector_void_star &output_items);
+
+  virtual int fixed_rate_noutput_to_ninput (int noutput_items);
+
+protected:
+
+/*
+ * state_get_from(v,i,k): use to retrieve a given bit-memory state,
+ *     from the inputs:
+ *
+ * int v: the value from which to retrieve the given state
+ * int i: for which input stream (0 to #I-1)
+ * int k: the number of memory slots per input (e.g. 1+D^2 -> 2)
+ */
+
+  inline memory_t state_get_from(v,i,k) {
+    return (((v)>>((i)*(k)))&((1<<(k))-1));};
+
+/*
+ * state_add_to(s,i,v,k): use to create a given bit-memory state,
+ *     from the inputs:
+ *
+ * int s: the state value to modify
+ * int i: for which input stream (0 to #I-1)
+ * int v: value to set the state to for this input
+ * int k: the number of memory slots per input (e.g. 1+D^2 -> 2)
+ */
+
+  inline void state_add_to(s,v,i,k) {(s)|=(((v)&((1<<(k))-1))<<((i)*(k)));};
+
+  void reset_metrics (u_char which);
+  void zero_metrics (u_char which);
+
+/*
+ * d_n_total_input_bits_per_stream: how many bits to store for each
+ *     state to determine the best decoder-output (encoder-input) bits 
+ */
+  size_t d_frame_size_bits;
+  size_t d_n_code_outputs, d_n_code_inputs, d_max_memory;
+  size_t d_time_count, d_n_total_input_bits_per_stream;
+  size_t d_n_saved_bits, d_n_saved_bits_start_ndx, d_n_traceback_els;
+  size_t d_n_states, d_n_input_combinations;
+  size_t d_states_ndx, d_up_term_ndx;
+  bool d_do_streaming, d_do_termination;
+  char **d_save_buffer;
+  state_t_ptr d_states[2];
+  fsm_dec_t d_fsm;
+  size_t* d_up_term_states_ndx[2];
+  traceback_t_hdl d_out_buf;
+};
+
+#endif /* INCLUDED_DECODER_VITERBI_BLOCK_FULL_H */

Index: libecc/decoder_viterbi_block_full_ic1.h
===================================================================
RCS file: libecc/decoder_viterbi_block_full_ic1.h
diff -N libecc/decoder_viterbi_block_full_ic1.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ libecc/decoder_viterbi_block_full_ic1.h     5 Jul 2006 17:49:58 -0000       
1.1
@@ -0,0 +1,58 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 Free Software Foundation, Inc.
+ * 
+ * This file is part of GNU Radio
+ * 
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef INCLUDED_DECODER_VITERBI_BLOCK_FULL_IC1_IC1_H
+#define INCLUDED_DECODER_VITERBI_BLOCK_FULL_IC1_IC1_H
+
+#include <decoder_viterbi_block_full.h>
+
+class decoder_viterbi_block_full_ic1_ic1 : public decoder_viterbi_block_full
+{
+public:
+/*!
+ * class decoder_viterbi_block_full_ic1_ic1 :
+ *     public decoder_viterbi_block_full
+ *
+ * Decode the incoming streams using a Viterbi-style decoder.
+ *
+ * output is "ic1": streams of char, one stream per output as defined
+ *     by the instantiated code, using only the right-most justified
+ *     bit as the single output bit per output item.
+ *
+ * The rest of the options are outlined in the inherited classes'
+ *     header files.
+ */
+
+  inline decoder_viterbi_block_full_ic1 (int sample_precision,
+                                        encoder* l_encoder)
+    : decoder_viterbi_base (int sample_precision,
+                           encoder* l_encoder) {};
+
+  virtual ~decoder_viterbi_block_full_ic1 () {};
+
+protected:
+  virtual void output_bit (char t_out_bit, char** out_buf,
+                          size_t t_output_stream);
+  virtual void increment_counters (bool while_decoding);
+};
+
+#endif /* INCLUDED_DECODER_VITERBI_BLOCK_FULL_IC1_IC1_H */

Index: gr_decoder_viterbi_block_soft_full.cc
===================================================================
RCS file: gr_decoder_viterbi_block_soft_full.cc
diff -N gr_decoder_viterbi_block_soft_full.cc
--- gr_decoder_viterbi_block_soft_full.cc       3 Jul 2006 02:12:53 -0000       
1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,1485 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006 Free Software Foundation, Inc.
- * 
- * This file is part of GNU Radio.
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- * 
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING.  If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gr_dec_blk_conv_soft_full.h>
-#include <gr_io_signature.h>
-#include <assert.h>
-#include <iostream>
-
-const int g_max_frame_size_bits = 10000000;
-const int g_max_num_streams = 10;
-const int g_num_bits_per_byte = 8;
-const int g_max_stream_el_size_bytes = 128;
-
-#define DO_TIME_THOUGHPUT 0
-#define DO_PRINT_DEBUG_INST 0
-#define DO_PRINT_DEBUG_INST_0 0
-#define DO_PRINT_DEBUG_INST_1 0
-#define DO_PRINT_DEBUG_INST_2 0
-#define DO_PRINT_DEBUG_FSM 0
-#define DO_PRINT_DEBUG_INIT 0
-#define DO_PRINT_DEBUG_UP 0
-#define DO_PRINT_DEBUG_UP_0 0
-#define DO_PRINT_DEBUG_UP_1 0
-#define DO_PRINT_DEBUG_MIDDLE 0
-#define DO_PRINT_DEBUG_MIDDLE_0 0
-#define DO_PRINT_DEBUG_MIDDLE_1 0
-#define DO_PRINT_DEBUG_TERM 0
-#define DO_PRINT_DEBUG_TERM_1 0
-#define DO_PRINT_DEBUG_OUTPUT 0
-#define DO_PRINT_DEBUG_OUTPUT_0 0
-#define DO_PRINT_DEBUG_EXIT 0
-#define DO_PRINT_DEBUG 0
-
-#if DO_TIME_THOUGHPUT
-#include <mld/mld_timer.h>
-#endif
-#if DO_PRINT_DEBUG
-#include <mld/n2bs.h>
-#endif
-
-gr_decoder_viterbi_block_soft_full_sptr
-gr_make_dec_blk_conv_soft_full
-(int frame_size_bits,
- int num_input_streams,
- int num_output_streams,
- std::vector<int> code_generator,
- bool do_termination)
-{
-  return gr_decoder_viterbi_block_soft_full_sptr
-    (new gr_decoder_viterbi_block_soft_full (frame_size_bits,
-                                            num_input_streams,
-                                            num_output_streams,
-                                            code_generator,
-                                            do_termination));
-}
-
-gr_decoder_viterbi_block_soft_full::gr_decoder_viterbi_block_soft_full
-(int frame_size_bits,
- int num_input_streams,
- int num_output_streams,
- std::vector<int> code_generator,
- bool do_termination)
-  : gr_block ("dec_blk_conv_soft_full",
-             gr_make_io_signature (0, 0, 0),
-             gr_make_io_signature (0, 0, 0))
-{
-// make sure the frame length makes sense, #1 - more later
-  if (frame_size_bits > g_max_frame_size_bits) {
-    std::cerr << "gr_decoder_viterbi_block_soft_full: " <<
-      "Requested frame length (" << frame_size_bits <<
-      " bits) must be at most " << g_max_frame_size_bits << " bits.\n";
-    assert (0);
-  }
-
-// check to make sure the number of input streams makes sense
-  if ((n_code_inputs <= 0) | (n_code_inputs > g_max_num_streams)) {
-    std::cerr << "gr_decoder_viterbi_block_soft_full: " <<
-      "Requested number of input streams (" <<
-      n_code_inputs << ") must be between 1 and " <<
-      g_max_num_streams << ".\n";
-    assert (0);
-  }
-
-// check to make sure the number of output streams makes sense
-  if ((n_code_outputs <= 0) | (n_code_outputs > g_max_num_streams)) {
-    std::cerr << "gr_decoder_viterbi_block_soft_full: " <<
-      "Requested number of output streams (" <<
-      n_code_outputs << ") must be between 1 and " <<
-      g_max_num_streams << ".\n";
-    assert (0);
-  }
-
-// make sure the code_generator is the correct length
-  if (code_generators.size () !=
-      ((size_t)(n_code_inputs * n_code_outputs))) {
-    std::cerr << "gr_decoder_viterbi_block_soft_full: " <<
-      "Number of code generator entries (" << code_generators.size () <<
-      ") is not equal to the product of the number of input and output" <<
-      " streams (" << (n_code_inputs * n_code_outputs) << ").\n";
-    assert (0);
-  }
-
-// create the class frame variables
-  d_frame_size_bits = frame_size_bits;
-  d_out_stream_el_size_bytes = out_stream_el_size_bytes;
-  d_n_code_inputs = n_code_inputs;
-  d_n_code_outputs = n_code_outputs;
-  d_do_streaming = (frame_size_bits == 0);
-  d_do_termination = (d_do_streaming == true) ? false : do_termination;
-  d_do_mux_inputs = do_mux_inputs;
-
-// allocate the vectors for doing the encoding.  use 32-bit int's
-// actual bits to represent memory and the code, as it makes the
-// operations quite simple the state vectors.
-// code generates are for each I/O combination
-
-  d_code_generators.resize (d_n_code_inputs * d_n_code_outputs, 0);
-
-// check the input code_generator for correctness & find the memory order
-// t_max_mem will be the mamimum number of memories used by the generator
-// t_code_ndx is a counter over all input code_generator elements
-  int t_max_mem = 0, t_code_ndx = d_code_generators.size() - 1;
-// loop over all input streams first, output streams second
-  for (int n = d_n_code_outputs - 1; n >= 0; n--) {
-    int t_all_inputs_zero = 0;
-    for (int m = d_n_code_inputs - 1; m >= 0; m--) {
-      int t_in_code = code_generators[t_code_ndx];
-      t_all_inputs_zero |= t_in_code;
-      int t_code_mem = 0;
-// find the memory requirement for this code generator
-      while (t_in_code != 0) {
-       t_in_code >>= 1;
-       t_code_mem++;
-      }
-      if (t_code_mem > t_max_mem)
-       t_max_mem = t_code_mem;
-// store in d_code_generators in output-first ordering
-      d_code_generators[(m*d_n_code_outputs) + n] =
-       code_generators[t_code_ndx--];
-    }
-    if (t_all_inputs_zero == 0) {
-      std::cerr << "gr_decoder_viterbi_block_soft_full: " <<
-       "At least 1 generator code for encode-output " << n+1 <<
-       " must be non-0.\n";
-      assert (0);
-    }
-  }
-
-// store the maximum memory order (e.g. "2" -> D^2)
-  d_max_memory = t_max_mem - 1;
-
-// make sure the frame length makes sense, #2
-  if (d_frame_size_bits < d_max_memory) {
-    std::cerr << "gr_decoder_viterbi_block_soft_full: " <<
-      "Requested frame length (" << d_frame_size_bits <<
-      " bit" << (d_frame_size_bits > 1 ? "s" : "") <<
-      ") must be at least 1 memory length (" << d_max_memory <<
-      " bit" << (d_max_memory > 1 ? "s" : "") <<
-      " for this code).\n";
-    assert (0);
-  }
-
-// NOTE: d_n_states is a 'u_long', and thus is quite limited in terms
-// of max memory and # of input streams to 2^32 states
-// This is OK, since that many states would be impossibly slow to decode!
-// might make this a "long long" (64 bits) in the future
-  d_n_states = 1 << (d_max_memory * d_n_code_inputs);
-  d_n_input_combinations = 1 << d_n_code_inputs;
-
-#if DO_PRINT_DEBUG_INST_0
-  std::cout << "Init:\n" <<
-    "d_frame_size_bits          = " << d_frame_size_bits << "\n" <<
-    "d_out_stream_el_size_bytes = " << d_out_stream_el_size_bytes << "\n" <<
-    "d_n_code_inputs            = " << d_n_code_inputs << "\n" <<
-    "d_n_code_outputs           = " << d_n_code_outputs << "\n" <<
-    "d_do_streaming             = " <<
-    ((d_do_streaming == true) ? "true" : "false") << "\n" <<
-    "d_do_termination           = " <<
-    ((d_do_termination == true) ? "true" : "false") << "\n" <<
-    "d_do_mux_inputs            = " <<
-    ((d_do_mux_inputs == true) ? "true" : "false") << "\n" <<
-    "d_max_memory               = " << d_max_memory << "\n" <<
-    "d_n_states                 = " << d_n_states << "\n" <<
-    "d_n_input_combinations     = " << d_n_input_combinations << "\n";
-#endif
-
-// leave the output multiple at 1 (element); will save any incomplete
-// output data (int's) in "d_save_buffer"; all input data will be consumed
-
-// create the correct input signature
-  int t_n_input_streams = ((d_do_mux_inputs == true) ?
-                          1 : n_code_outputs);
-
-  set_input_signature (gr_make_io_signature (t_n_input_streams,
-                                            t_n_input_streams,
-                                            sizeof (float)));
-// create the correct output signature
-  set_output_signature (gr_make_io_signature (n_code_inputs,
-                                             n_code_inputs,
-                                             d_out_stream_el_size_bytes));
-#if DO_PRINT_DEBUG_INST_0
-  std::cout <<
-    "input_signature            = [" << t_n_input_streams << ", " <<
-    t_n_input_streams << ", " << sizeof (float) << "]\n" <<
-    "output_signature           = [" << n_code_outputs << ", " <<
-    n_code_outputs << ", " << d_out_stream_el_size_bytes << "]\n";
-#endif
-
-// always start the fsm in the "init" state
-  d_fsm = fsm_dec_init;
-
-// create a vector of indexes to states when doing "up" or "termination";
-  d_up_term_states_ndx[0] = new size_t [d_n_states];
-  d_up_term_states_ndx[1] = new size_t [d_n_states];
-
-// create the traceback buffers
-// get the total number of out bits per stream
-  d_n_total_input_bits_per_stream = d_frame_size_bits;
-  if (d_do_termination == true)
-    d_n_total_input_bits_per_stream += d_max_memory;
-  d_n_traceback_els = d_n_total_input_bits_per_stream + 1;
-// create the output buffers:
-// this is a 2d matrix structure, where the first dimension
-// is the number of output bits; the second dimension is
-// the number of states.
-// When doing full frames (no tau), each bit-time's state's traceback
-// contains just the pointer to the previous bit-time's state's traceback
-// as well as the inputs for that connection.
-// No further work is required because each reverse-path is unique
-// once a given end-bit-time's state is determined to be "the one"
-  traceback_t_hdl t_out_buf =
-    d_out_buf = new traceback_t_ptr [d_n_traceback_els];
-  for (size_t n = d_n_traceback_els; n > 0; n--) {
-    (*t_out_buf++) = new traceback_t [d_n_states];
-  }
-
-  // create the save buffers
-  char** t_save_buffer = d_save_buffer = new char* [d_n_code_inputs];
-  size_t t_n_out_bytes = ((d_frame_size_bits / g_num_bits_per_byte) +
-                         ((d_frame_size_bits % g_num_bits_per_byte) ? 1 : 0));
-  for (size_t n = 0; n < d_n_code_inputs; n++) {
-    (*t_save_buffer++) = new char [t_n_out_bytes];
-  }
-
-// reset the number of saved bits
-  d_n_saved_bits_start_ndx = d_n_saved_bits = 0;
-
-// setup the internal structures for exiting and entering states
-
-#if DO_PRINT_DEBUG_INST_0
-  std::cout <<
-    "d_n_total in bits / stream = " << d_n_total_input_bits_per_stream << "\n" 
<<
-    "d_n_traceback_els          = " << d_n_traceback_els << "\n" <<
-    "t_n_out_bytes / stream     = " << t_n_out_bytes << "\n";
-#endif
-
-// Find the approximate output rate / input rate
-// each input item produces 1 bit of an output item w/o termination
-  double t_rel_rate = (double)(d_out_stream_el_size_bytes * 
g_num_bits_per_byte);
-  if (d_do_termination == true) {
-// include termination bits
-    t_rel_rate *= (((double) d_frame_size_bits) /
-                  ((double) d_n_total_input_bits_per_stream));
-  }
-// Set the approximate output rate / input rate
-  set_relative_rate (t_rel_rate);
-
-// 'new' everything first; no connections yet
-  state_t_ptr t_state = d_states[0] = new state_t [d_n_states];
-  for (size_t n = d_n_states; n > 0; n--, t_state++) {
-    connection_t_ptr t_connection = t_state->d_connections
-      = new connection_t [d_n_input_combinations];
-    for (size_t m = d_n_input_combinations; m > 0; m--, t_connection++) {
-      t_connection->d_output_bits = new float [d_n_code_outputs];
-    }
-  }
-
-// 'new' everything first; no connections yet
-  t_state = d_states[1] = new state_t [d_n_states];
-  for (size_t n = d_n_states; n > 0; n--, t_state++) {
-    connection_t_ptr t_connection = t_state->d_connections
-      = new connection_t [d_n_input_combinations];
-    for (size_t m = d_n_input_combinations; m > 0; m--, t_connection++) {
-      t_connection->d_output_bits = new float [d_n_code_outputs];
-    }
-  }
-
-// temporary memory and mask for output bit computations
-  size_t t_memory[d_n_code_inputs];
-  size_t t_memory_mask = ((2 << d_max_memory) - 1) ^ 1;
-
-#if DO_PRINT_DEBUG
-  size_t t_state_print_bits = (d_max_memory * d_n_code_inputs) + 1;
-  size_t t_mem_print_bits = d_max_memory + 2;
-
-  std::cout << "Setting States and Connections\n";
-#endif
-
-// loop over all possible memory states
-  state_t_ptr t_state0 = d_states[0];
-  state_t_ptr t_state1 = d_states[1];
-  for (size_t n = 0; n < d_n_states; n++, t_state0++, t_state1++) {
-#if DO_PRINT_DEBUG_INST_1
-    std::cout << "Starting state # " << n << " == " <<
-      n2bs (n, t_state_print_bits) << "\n";
-#endif
-// retrieve the memory values for this state
-// probably a faster way to do this, but since this is
-// executed only upon instantiation, whatever.
-    size_t* t_mem_ptr = t_memory;
-    for (size_t p = 0; p < d_n_code_inputs; p++) {
-      int t_mem = state_get_from (n, p, d_max_memory);
-#if DO_PRINT_DEBUG_INST_1
-      std::cout << "s_g_f (" <<
-       n2bs (n, t_state_print_bits) << ", " <<
-       p << ", " << d_max_memory << ") => t_m = " <<
-       n2bs (t_mem, t_mem_print_bits) << "\n";
-#endif
-// shift them by 1 (and mask) to make updating for all inputs simple
-      (*t_mem_ptr++) = t_mem << 1;
-#if DO_PRINT_DEBUG_INST_1
-      std::cout << "t_m_p[" << p << "] = " <<
-       n2bs (t_mem << 1, t_mem_print_bits) << " == (" <<
-       n2bs (t_mem, t_mem_print_bits) << " << 1)\n";
-#endif
-    }
-
-// loop over all possible input values, 1 bit per input stream
-    connection_t_ptr t_connection0 = t_state0->d_connections;
-    connection_t_ptr t_connection1 = t_state1->d_connections;
-    for (size_t q = 0; q < d_n_input_combinations;
-        q++, t_connection0++, t_connection1++) {
-#if DO_PRINT_DEBUG_INST_1
-      std::cout << "Starting inputs " << q << " == " <<
-       n2bs (q, d_n_code_inputs + 1) << "\n";
-#endif
-
-// update memory for this set of inputs
-      t_mem_ptr = t_memory;
-      size_t t_this_input = q;
-
-// loop over all code inputs, and update just the single input bit
-      for (size_t r = d_n_code_inputs; r > 0; r--) {
-       int t_mem = (*t_mem_ptr) & t_memory_mask;
-#if DO_PRINT_DEBUG_INST_1
-       std::cout << "t_m = " << n2bs (t_mem, t_mem_print_bits) <<
-         " == " << n2bs (*t_mem_ptr, t_mem_print_bits) <<
-         " & " << n2bs (t_memory_mask, t_mem_print_bits) << "\n";
-#endif
-       (*t_mem_ptr++) = t_mem | (t_this_input & 1);
-#if DO_PRINT_DEBUG_INST_1
-       std::cout << "t_m_p[" << (d_n_code_inputs - r) << "] = " <<
-         n2bs (t_mem | (t_this_input & 1), t_mem_print_bits) <<
-         " == t_m | " << (t_this_input & 1) << "\n";
-#endif
-       t_this_input >>= 1;
-      }
-
-// got the updated memory for this particular state & inputs
-// recreate the "to" state from the updated memory
-      t_mem_ptr = t_memory;
-      size_t t_out_state = 0;
-      for (size_t p = 0; p < d_n_code_inputs; p++) {
-#if DO_PRINT_DEBUG_INST_1
-       std::cout << "s_a_t (" <<
-         n2bs (t_out_state, t_state_print_bits) <<
-         ", " << n2bs (*t_mem_ptr, t_mem_print_bits) << ", " << p <<
-         ", " << d_max_memory << ") ==> t_o_s out = ";
-#endif
-       state_add_to (t_out_state, *t_mem_ptr++, p, d_max_memory);
-#if DO_PRINT_DEBUG_INST_1
-       std::cout << n2bs (t_out_state, t_state_print_bits) << "\n";
-#endif
-      }
-
-// get the "to" state pointers from d_states[0] to [1]
-      state_t_ptr t_to_state = &(d_states[1][t_out_state]);
-      t_connection0->d_to = t_to_state;
-      t_connection0->d_to_ndx = t_out_state;
-      float* t_output_bit0 = t_connection0->d_output_bits;
-
-// get the "to" state pointers from d_states[1] to [0]
-      t_to_state = &(d_states[0][t_out_state]);
-      t_connection1->d_to = t_to_state;
-      t_connection1->d_to_ndx = t_out_state;
-      float* t_output_bit1 = t_connection1->d_output_bits;
-
-// determine the ideal output values: loop over all outputs
-      size_t t_vec_ctr = 0;
-      for (size_t s = 0; s < d_n_code_outputs; s++) {
-
-// loop over all inputs, xor'ing the result each time
-       int t_out_result = 0;
-       t_mem_ptr = t_memory;
-       for (size_t t = 0; t < d_n_code_inputs; t++) {
-#if DO_PRINT_DEBUG_INST_1
-         std::cout << "b_i = " << n2bs (t_out_result, t_mem_print_bits) <<
-           ", st[" << t << "] = " << n2bs ((*t_mem_ptr), t_mem_print_bits) <<
-           ", cg[" << t_vec_ctr << "] = " <<
-           n2bs (d_code_generators[t_vec_ctr], t_mem_print_bits) <<
-           ", st[] & cg[] = " << n2bs ((*t_mem_ptr) &
-                                       d_code_generators[t_vec_ctr],
-                                       t_mem_print_bits);
-#endif
-         t_out_result ^= ((*t_mem_ptr++) &
-                          d_code_generators[t_vec_ctr++]);
-#if DO_PRINT_DEBUG_INST_1
-         std::cout << ", b_o = " <<
-           n2bs (t_out_result, t_mem_print_bits) << '\n';
-#endif
-       }
-#if DO_PRINT_DEBUG_INST_1
-       std::cout << "b_r = " << n2bs (t_out_result, t_mem_print_bits);
-#endif
-// sum the number of set bits, mod 2, for the output bit
-       size_t t_out_bit = t_out_result & 1;
-       for (size_t v = d_max_memory; v > 0; v--) {
-         t_out_result >>= 1;
-         t_out_bit ^= (t_out_result & 1);
-       }
-
-// store the result for this particular output stream,
-// converting the bit 1 -> +1.0, and 0 -> -1.0
-        float t_out_value = (float)(((int)(t_out_bit << 1)) - 1);
-       *t_output_bit0++ = t_out_value;
-       *t_output_bit1++ = t_out_value;
-#if DO_PRINT_DEBUG_INST_1
-       std::cout << ", o_v = " << t_out_value << "\n";
-#endif
-
-// finished (for) all output values
-      }
-// finished (for) over all possible input values
-    }
-// finished (for) over all possible states
-  }
-
-// so now d_states is/are completely populated!
-// These make for simple access to looping over all possible inputs or
-// outputs for a given state to determine what the path with the best
-// metric is.
-
-#if DO_PRINT_DEBUG_INST_2
-// loop over all possible memory states
-  std::cout << "State Tables\n";
-  t_state0 = d_states[0];
-  t_state1 = d_states[1];
-  for (size_t n = 0; n < d_n_states; n++, t_state0++, t_state1++) {
-    std::cout << "d_s[0][" << n << "] = " << t_state0 << "\n";
-// loop over all possible input values, 1 bit per input stream
-    connection_t_ptr t_connection0 = t_state0->d_connections;
-    for (size_t q = 0; q < d_n_input_combinations; q++, t_connection0++) {
-      std::cout << "s0[" << n2bs (n, t_state_print_bits) << "][" <<
-       n2bs (q, d_n_code_inputs+1) << "] = " << t_connection0 <<
-       " -> s1[" << n2bs (t_connection0->d_to_ndx, t_state_print_bits) <<
-       "] = " << t_connection0->d_to << "\n";
-    }
-    std::cout << "d_s[1][" << n << "] = " << t_state1 << "\n";
-    connection_t_ptr t_connection1 = t_state1->d_connections;
-    for (size_t q = 0; q < d_n_input_combinations; q++, t_connection1++) {
-      std::cout << "s1[" << n2bs (n, t_state_print_bits) << "][" <<
-       n2bs (q, d_n_code_inputs+1) << "] = " << t_connection1 <<
-       " -> s0[" << n2bs (t_connection1->d_to_ndx, t_state_print_bits) <<
-       "] = " << t_connection1->d_to << "\n";
-    }
-  }
-
-  traceback_t_hdl t_out_bufs = d_out_buf;
-  for (size_t n = 0; n < d_n_traceback_els; n++, *t_out_bufs++) {
-    traceback_t_ptr t_out_buf = *t_out_bufs;
-    for (size_t m = 0; m < d_n_states; m++, t_out_buf++) {
-      std::cout << "tb[" << n << "] = " << t_out_bufs <<
-       ", &tb[" << n << "][" << m << "] = " << (&d_out_buf[n][m]) <<
-       ", tb[" << n << "," << m << "] = " << t_out_buf << "\n";
-    }
-  }
-
-  std::cout << "Done with instantiation.\n";
-#endif
-}
-
-gr_decoder_viterbi_block_soft_full::~gr_decoder_viterbi_block_soft_full
-()
-{
-// reverse over from allocation
-
-  delete [] d_up_term_states_ndx[0];
-  delete [] d_up_term_states_ndx[1];
-
-// delete the state's structures
-  state_t_ptr t_state = d_states[0];
-  for (size_t n = d_n_states; n > 0; n--, t_state++) {
-    connection_t_ptr t_connection = t_state->d_connections;
-    for (size_t m = d_n_input_combinations; m > 0; m--, t_connection++) {
-      delete [] t_connection->d_output_bits;
-    }
-    delete [] t_state->d_connections;
-  }
-  delete [] d_states[0];
-
-  t_state = d_states[1];
-  for (size_t n = d_n_states; n > 0; n--, t_state++) {
-    connection_t_ptr t_connection = t_state->d_connections;
-    for (size_t m = d_n_input_combinations; m > 0; m--, t_connection++) {
-      delete [] t_connection->d_output_bits;
-    }
-    delete [] t_state->d_connections;
-  }
-  delete [] d_states[1];
-
-// delete the save buffer
-  char** t_save_buffer = d_save_buffer;
-  for (size_t n = 0; n < d_n_code_inputs; n++) {
-    delete [] (*t_save_buffer++);
-  }
-  delete [] d_save_buffer;
-
-// delete the output buffer
-  traceback_t_hdl t_out_buf = d_out_buf;
-  for (size_t n = d_n_traceback_els; n > 0; n--) {
-    delete [] (*t_out_buf++);
-  }
-  delete [] d_out_buf;
-}
-
-void gr_decoder_viterbi_block_soft_full::reset_metrics (u_char which)
-{
-  state_t_ptr t_state = d_states[which&1];
-  for (size_t n = d_n_states; n > 0; n--, t_state++) {
-    t_state->d_max_metric = -1e10;
-#if 0
-// probably don't need to do these, try removing them later
-    t_state->d_max_state_ndx = 0;
-    t_state->d_max_input = -1;
-#endif
-  }
-}
-
-void gr_decoder_viterbi_block_soft_full::zero_metrics (u_char which)
-{
-  state_t_ptr t_state = d_states[which&1];
-  for (size_t n = d_n_states; n > 0; n--, t_state++) {
-    t_state->d_max_metric = 0;
-#if 0
-// probably don't need to do these, try removing them later
-    t_state->d_max_state_ndx = -1;
-    t_state->d_max_input = -1;
-#endif
-  }
-}
-
-void gr_decoder_viterbi_block_soft_full::forecast
-(int noutput_items,
- gr_vector_int &ninput_items_required)
-{
-  int ninput_items = fixed_rate_noutput_to_ninput (noutput_items);
-
-  int ninputs = ninput_items_required.size();
-  for (int n = 0; n < ninputs; n++)
-    ninput_items_required[n] = ninput_items;
-}
-
-/*
- * Compute the number of input items (soft symbols [floats]) needed to produce
- * 'noutput' items (elements).  For convolutional decoders, there is 1
- * bit output per bit input per stream, with the addition of a some
- * bits for trellis termination if selected.  Without termination,
- * there is exactly 1:1 input to output (1 symbol in to 1 bit out),
- * no matter the encoding type.
- *
- * if (not terminating), then get the number of output bytes.
- *
- * otherwise, find the number of frames (not necessarily and integer),
- * and then compute the number of input bits (including termination)
- * required to produce those frames.  Subtract the number of bits
- * leftover from the previous computation, then find the number of input
- * elements (soft symbols), ceil'd to make sure there are enough.
- *
- * finally, if the input streams are mux'ed, then multiply by the
- * number of inputs.
- */
-
-int
-gr_decoder_viterbi_block_soft_full::fixed_rate_noutput_to_ninput
-(int noutput_items)
-{
-  int t_ninput_items = 0;
-  int t_noutput_bits = (noutput_items * d_out_stream_el_size_bytes *
-                        g_num_bits_per_byte) - d_n_saved_bits;
-// if there are enough saved bits, just use those, no inputs required
-  if (t_noutput_bits <= 0)
-    return (t_ninput_items);
-
-// remove any bits already in the decoding trellis
-  if (d_time_count != 0) {
-    int t_time_bits = ((d_time_count > d_frame_size_bits) ? 0 :
-                      d_frame_size_bits - d_time_count);
-    t_noutput_bits -= t_time_bits;
-    t_ninput_items += t_time_bits;
-  }
-// if completing this trellis doesn't create enough outputs ...
-  if (t_noutput_bits > 0) {
-
-// there is a 1:1 ratio between input symbols and output bits (per
-// stream), except for termination bits which are already taken into
-// account in the total # of input bits per stream class variable;
-// need to round the # output bits to the
-
-// find the number of frames, ceil'd to the next higher integer
-    int t_nframes = (int) ceilf (((float) t_noutput_bits) /
-                                ((float) d_frame_size_bits));
-// find the number of required input bits
-    t_ninput_items += t_nframes * d_n_total_input_bits_per_stream;
-  }
-
-// if doing mux'ing, there are more elements in the single input
-  if (d_do_mux_inputs == true) {
-    t_ninput_items *= d_n_code_outputs;
-  }
-  return (t_ninput_items);
-}
-
-int
-gr_decoder_viterbi_block_soft_full::general_work
-(int noutput_items,
- gr_vector_int &ninput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
-{
-#if DO_TIME_THOUGHPUT
-  struct timeval t_tp;
-  start_timer (&t_tp);
-#endif
-#if DO_PRINT_DEBUG
-  size_t t_state_print_bits = (d_max_memory * d_n_code_inputs) + 1;
-  size_t t_mem_print_bits = d_max_memory + 2;
-#endif
-// setup variables for quicker access
-  const float **in_buf = (const float **) &input_items[0];
-  char **out_buf = (char **) &output_items[0];
-  int t_in_buf_ndx = 0, t_out_buf_ndx = 0;
-  int t_out_bit_shift = 0;
-  int t_ninput_items = fixed_rate_noutput_to_ninput (noutput_items);
-  int t_noutput_bytes = noutput_items * d_out_stream_el_size_bytes;
-
-#if DO_PRINT_DEBUG_INST
-  std::cout << "# output items = " << noutput_items << " (" <<
-    t_noutput_bytes << " Bytes, " << (t_noutput_bytes * g_num_bits_per_byte) <<
-    " bits), # input items = " << t_ninput_items << " Symbols\n";
-  for (size_t n = 0; n < ninput_items.size(); n++) {
-    std::cout << "# input items [" << n << "] = " << ninput_items[n] << "\n";
-  }
-#endif
-
-// put any leftover bits into the output
-  if (d_n_saved_bits != 0) {
-// copy the leftover from the save buffer
-// check to make sure it will all fit
-    size_t t_noutput_bits = t_noutput_bytes * g_num_bits_per_byte;
-    size_t t_n_copy;
-    if (t_noutput_bits < d_n_saved_bits) {
-// asking for fewer bits than available; set to copy
-// just what's being asked for
-      t_n_copy = t_noutput_bytes;
-    } else {
-// asking for at least as many bits as available; set to copy all
-      t_out_buf_ndx = d_n_saved_bits / g_num_bits_per_byte;
-      t_out_bit_shift = d_n_saved_bits % g_num_bits_per_byte;
-      t_n_copy = t_out_buf_ndx + (t_out_bit_shift != 0 ? 1 : 0);
-    }
-// do the copy for all output streams (code inputs)
-// copy starting at save buffer index "start"
-    for (size_t n = 0; n < d_n_code_inputs; n++)
-      bcopy (&(d_save_buffer[n][d_n_saved_bits_start_ndx]),
-            out_buf[n], t_n_copy);
-#if DO_PRINT_DEBUG_INST
-    std::cout << "Copied " << t_n_copy << " Byte" <<
-      (t_n_copy != 1 ? "s" : "") << ": s_b[][" <<
-      d_n_saved_bits_start_ndx << "] => o_b[][0]\n" <<
-      "# saved bits = " << d_n_saved_bits <<
-      ", o_b_ndx = " << t_out_buf_ndx <<
-      ", bit shift = " << t_out_bit_shift << "\n";
-#endif
-//  update the number of saved bits and start
-    if (t_noutput_bits < d_n_saved_bits) {
-// asking for fewer bit than available: update
-// the number of saved bits and their starting index
-      d_n_saved_bits_start_ndx += t_noutput_bytes;
-      d_n_saved_bits -= (t_noutput_bytes * g_num_bits_per_byte);
-#if DO_PRINT_DEBUG_INST
-      std::cout << "Updated # saved bits = " << d_n_saved_bits <<
-       ", index = " << d_n_saved_bits_start_ndx << "\n";
-#endif
-// nothing to consume; return the desired number of output items
-      return (noutput_items);
-    } else {
-      d_n_saved_bits_start_ndx = d_n_saved_bits = 0;
-    }
-  }
-#if DO_PRINT_DEBUG_INST
-  std::cout << "Starting FSM in state: " <<
-    (d_fsm == fsm_dec_init ? "init" :
-     (d_fsm == fsm_dec_doing_up ? "up" :
-      (d_fsm == fsm_dec_doing_middle ? "middle" :
-       (d_fsm == fsm_dec_doing_term ? "term" :
-       (d_fsm == fsm_dec_output ? "output" : "unknown"))))) << "\n";
-#endif
-
-// while there are input items to create
-  while (t_out_buf_ndx < t_noutput_bytes) {
-#if DO_PRINT_DEBUG_FMS
-    std::cout << "Starting 'while': processing " << t_in_buf_ndx << " of " <<
-      t_ninput_items << " items.\nJumping to state '" <<
-      (d_fsm == fsm_dec_init ? "init" :
-       (d_fsm == fsm_dec_doing_up ? "up" :
-       (d_fsm == fsm_dec_doing_middle ? "middle" :
-        (d_fsm == fsm_dec_doing_term ? "term" :
-         (d_fsm == fsm_dec_output ? "output" : "unknown"))))) << "'\n";
-#endif
-// jump to the correct state in the fsm
-    switch (d_fsm) {
-    case fsm_dec_doing_up:
-#if DO_PRINT_DEBUG_FSM
-      std::cout << "Starting fsm_dec_doing_up\n";
-#endif
-// set the number of up_down indices
-      size_t t_n_up_down_ndx = 1 << (d_n_code_inputs *
-                                    d_time_count);
-// stay in this state until the correct number of input symbols are
-// reached; exit also if we run out of input symbols to process
-      while ((d_time_count < d_max_memory) &
-            (t_in_buf_ndx < t_ninput_items)) {
-#if DO_PRINT_DEBUG_UP_0
-       std::cout << "Doing 'while' loop:\n" <<
-         "t_n_up_down_ndx    = " << t_n_up_down_ndx << "\n" <<
-         "d_time_count       = " << d_time_count << "\n" <<
-         "d_max_memory       = " << d_max_memory << "\n" <<
-         "t_in_buf_ndx       = " << t_in_buf_ndx << "\n" <<
-         "t_ninput_items     = " << t_ninput_items << "\n";
-#endif
-// use the "from" states, loop over all inputs and compute the metric for
-// each & store it in the "to" state at the end of the connection.
-// no need to compare metrics yet, since none join into any given state
-
-#if 0
-// reset the "to" state's metrics
-// probably don't need to do this; try removing later
-        reset_metrics (d_states_ndx ^ 1);
-#if DO_PRINT_DEBUG_UP
-       std::cout << "Reset Metrics\n";
-#endif
-#endif
-
-// reset the state's index for each set of new inputs
-       size_t* t_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx];
-       size_t* t_next_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx ^ 1];
-// loop over all current stored "up" states
-       for (size_t n = 0; n < t_n_up_down_ndx; n++) {
-         size_t t_state_ndx = *t_state_ndx_ptr++;
-// get a pointer to this state's structure
-         state_t_ptr t_state = &(d_states[d_states_ndx][t_state_ndx]);
-// get the connections for all inputs
-         connection_t_ptr t_connection = t_state->d_connections;
-#if DO_PRINT_DEBUG_UP_0
-         std::cout << "Looping over all 'up' states:\n" <<
-           "n                  = " << n << "\n" <<
-           "t_n_up_down_ndx    = " << t_n_up_down_ndx << "\n" <<
-           "d_states_ndx       = " << d_states_ndx << "\n" <<
-           "t_state_ndx        = " << t_state_ndx << "\n" <<
-           "d_n_input_combs    = " << d_n_input_combinations << "\n" <<
-           "t_state            = " << t_state << "\n" <<
-           "t_connection       = " << t_connection << "\n";
-#endif
-// loop over all possible input values, 1 bit per input stream
-         for (size_t q = 0; q < d_n_input_combinations; q++, t_connection++) {
-// find the "to" state for this connection
-           state_t_ptr t_to_state = t_connection->d_to;
-// get the output bits for this connection
-           float* t_output_bit = t_connection->d_output_bits;
-// start with this state's metric
-           float t_metric = t_state->d_max_metric;
-#if DO_PRINT_DEBUG_UP_0
-           std::cout <<
-             "to state index     = " << t_connection->d_to_ndx << "\n" <<
-             "current metric     = " << t_metric << "\n";
-#endif
-           if (d_do_mux_inputs == true) {
-// if using mux'ed input streams, handle differently
-              const float* t_in_buf = &(in_buf[0][t_in_buf_ndx]);
-// loop over all encoder-output values
-             for (size_t r = d_n_code_outputs; r > 0; r--) {
-#if DO_PRINT_DEBUG_UP
-               std::cout << "in_sym = " << *t_in_buf << ", code_out_bit = " <<
-                 *t_output_bit << " ==> metric -> ";
-#endif
-               t_metric += ((*t_in_buf++) * (*t_output_bit++));
-#if DO_PRINT_DEBUG_UP
-               std::cout << t_metric << "\n";
-#endif
-             }
-           } else {
-// loop over all encoder-output values
-             for (size_t r = 0; r < d_n_code_outputs; r++) {
-#if DO_PRINT_DEBUG_UP
-               std::cout << "in_sym = " << in_buf[r][t_in_buf_ndx] <<
-                 ", code_out_bit = " << *t_output_bit << " ==> metric -> ";
-#endif
-               t_metric += (in_buf[r][t_in_buf_ndx] * (*t_output_bit++));
-#if DO_PRINT_DEBUG_UP
-               std::cout << t_metric << "\n";
-#endif
-             }
-           }
-// get the "to" state index
-           size_t t_to_ndx = t_connection->d_to_ndx;
-// store the metric in the "to" state; should not have been used before
-           t_to_state->d_max_metric = t_metric;
-// add the "to" state index to the "up" state list
-           *t_next_state_ndx_ptr++ = t_to_ndx;
-// update the traceback structure, depending on which variety it is
-// doing full trellis before decoding; use d_out_buf
-// simple: get the current state & output state
-           traceback_t_ptr t_out_buf = &(d_out_buf[d_time_count]
-                                         [t_state_ndx]);
-           traceback_t_ptr t_next_out_buf = &(d_out_buf[d_time_count+1]
-                                              [t_to_ndx]);
-#if DO_PRINT_DEBUG_UP_1
-           std::cout << "d_o_b[" << d_time_count+1 << "] => d_o_b prev\n" <<
-             "ndx[" << n << "] == " << t_state_ndx <<
-             ", s[" << n2bs(t_state_ndx,t_state_print_bits) <<
-             "]: max_ndx = " <<
-             n2bs(t_state->d_max_state_ndx,t_state_print_bits) <<
-             ", input = " << n2bs(q, d_n_code_inputs+1) <<
-             ": " << t_next_out_buf << " => " << t_out_buf << "\n";
-#endif
-// and connect output to the current, set inputs on output
-           t_next_out_buf->d_prev = t_out_buf;
-           t_next_out_buf->d_inputs = q;
-// finished (for) this input value
-         }
-// finished (for) this "up_term" state
-       }
-// increment the in_buf index, depending on mux'ing or not
-       t_in_buf_ndx += (d_do_mux_inputs == false) ? 1 : d_n_code_outputs;
-// increment the time counter
-        d_time_count++;
-// update the number of "up_term" states
-        d_up_term_ndx ^= 1;
-// increase the number of using states
-        t_n_up_down_ndx <<= d_n_code_inputs;
-// change which d_states' index to use as starting
-        d_states_ndx ^= 1;
-// finished (while) staying in this fsm state or not
-      }
-// if reached the end of doing the "up" part of the trellis,
-// switch states into the middle
-      if (d_time_count == d_max_memory) {
-#if DO_PRINT_DEBUG_FSM
-       std::cout << "Setting FSM to fsm_dec_doing_middle\n";
-#endif
-        d_fsm = fsm_dec_doing_middle;
-      }
-#if DO_PRINT_DEBUG_FSM
-      std::cout << "Exited fsm_dec_doing_up\n";
-#endif
-      break;
-    case (fsm_dec_doing_middle):
-#if DO_PRINT_DEBUG_FSM
-      std::cout << "Entered fsm_dec_doing_middle\n";
-#endif
-// stay in this state until the correct number of input symbols is
-// reached (if doing block coding), or until there are no more input
-// symbols to parse
-      while (((d_frame_size_bits != 0) &
-             (d_time_count < d_frame_size_bits) &
-             (t_in_buf_ndx < t_ninput_items)) |
-            ((d_frame_size_bits == 0) &
-             (t_in_buf_ndx < t_ninput_items))) {
-// use all states, loop over all inputs, compute the metric for
-// each; compare the current metric with all previous stored metric in the
-// endpoint of the connection to find the highest one.
-
-// reset the "to" state's metrics
-        reset_metrics (d_states_ndx ^ 1);
-// get the state's index for each set of new inputs
-       state_t_ptr t_state = d_states[d_states_ndx];
-#if DO_PRINT_DEBUG_MIDDLE
-       std::cout << "Time Count " << (d_time_count+1) << " of " <<
-         d_frame_size_bits << "\n" <<
-         "d_states_ndx = " << d_states_ndx << "\n";;
-#endif
-// loop over all current states
-       for (size_t n = 0; n < d_n_states; n++, t_state++) {
-// loop over all possible input values, 1 bit per input stream
-         connection_t_ptr t_connection = t_state->d_connections;
-#if DO_PRINT_DEBUG_MIDDLE_0
-         std::cout << "Looping over all 'middle' states: " <<
-           n << " of " << d_n_states << "\n";
-#endif
-         for (size_t q = 0; q < d_n_input_combinations; q++, t_connection++) {
-#if DO_PRINT_DEBUG_MIDDLE_0
-           std::cout << "Input = " << n2bs(q, d_n_code_inputs+1) << "\n";
-#endif
-// start with this state's metric
-           float t_metric = t_state->d_max_metric;
-// get the "to" state
-            state_t_ptr t_to_state = t_connection->d_to;
-// get that state's metric
-            float t_to_metric = t_to_state->d_max_metric;
-// see if the computation is even needed;
-// maximum change is d_n_code_outputs if all bits match exactly
-            if ((t_to_metric - t_metric) > ((float) 2*d_n_code_outputs)) {
-#if DO_PRINT_DEBUG_MIDDLE_0
-             std::cout << "!not computing metric!\n";
-#endif
-              continue;
-           }
-// metrics are close enough; do the computation and the compare
-// get the output bits for this connection
-           float* t_output_bit = t_connection->d_output_bits;
-           if (d_do_mux_inputs == true) {
-// if using mux'ed input streams, handle differently
-              const float* t_in_buf = &(in_buf[0][t_in_buf_ndx]);
-// loop over all encoder-output values
-             for (size_t r = d_n_code_outputs; r > 0; r--) {
-#if DO_PRINT_DEBUG_MIDDLE_0
-               std::cout << "in_sym = " << *t_in_buf << ", code_out_bit = " <<
-                 *t_output_bit << " ==> metric -> ";
-#endif
-               t_metric += ((*t_in_buf++) * (*t_output_bit++));
-#if DO_PRINT_DEBUG_MIDDLE_0
-               std::cout << t_metric << "\n";
-#endif
-             }
-           } else {
-// loop over all encoder-output values
-             for (size_t r = 0; r < d_n_code_outputs; r++) {
-#if DO_PRINT_DEBUG_MIDDLE_0
-               std::cout << "in_sym = " << in_buf[r][t_in_buf_ndx] <<
-                 ", code_out_bit = " << *t_output_bit << " ==> metric -> ";
-#endif
-               t_metric += (in_buf[r][t_in_buf_ndx] * (*t_output_bit++));
-#if DO_PRINT_DEBUG_MIDDLE_0
-               std::cout << t_metric << "\n";
-#endif
-             }
-           }
-// done with this input value; compare old and new metrics
-            if (t_metric > t_to_metric) {
-#if DO_PRINT_DEBUG_MIDDLE
-             std::cout << "New Metric to s[" <<
-               n2bs (t_connection->d_to_ndx,t_state_print_bits) << "]: ";
-             if (t_to_state->d_max_metric == -1e10) {
-               std::cout << "setting to ";
-             } else {
-               std::cout << "was s[" <<
-                 n2bs(t_to_state->d_max_state_ndx,t_state_print_bits) <<
-                 "]i[" << n2bs (t_to_state->d_max_input, d_n_code_inputs+1) <<
-                 "]@ " << t_to_state->d_max_metric << "  now ";
-             }
-             std::cout << "s[" << n2bs(n,t_state_print_bits) << "] i[" <<
-               n2bs (q, d_n_code_inputs+1) << "]@ " << t_metric << "\n";
-#endif
-// new metric is better; copy that info into the "to" state
-              t_to_state->d_max_metric = t_metric;
-              t_to_state->d_max_state_ndx = n;
-              t_to_state->d_max_input = q;
-            }
-// finished (for) this input value
-         }
-// finished (for) this state
-       }
-// done with all states and all inputs; now update the traceback structure
-// change which d_states' index to use as starting
-        d_states_ndx ^= 1;
-// get the state's index for the "to" set of new inputs to get the
-// "max" stuff from
-       t_state = d_states[d_states_ndx];
-// update the traceback structure
-// loop over all current states
-       traceback_t_ptr t_prev_out_bufs = d_out_buf[d_time_count];
-       traceback_t_ptr t_out_bufs = d_out_buf[d_time_count+1];
-#if DO_PRINT_DEBUG_MIDDLE_1
-       std::cout << "d_o_b[" << d_time_count+1 << "] => d_o_b prev\n";
-#endif
-       for (size_t n = d_n_states; n > 0; n--, t_state++) {
-// simple: get the current state & output state
-// and connect output to the current, set inputs on output
-         traceback_t_ptr t_out_buf = t_out_bufs++;
-         traceback_t_ptr t_prev_out_buf =
-           &(t_prev_out_bufs[t_state->d_max_state_ndx]);
-#if DO_PRINT_DEBUG_MIDDLE_1
-         std::cout << "s[" << n2bs(d_n_states-n,t_state_print_bits) <<
-           "]: max_ndx = " <<
-           n2bs(t_state->d_max_state_ndx,t_state_print_bits) <<
-           ", input = " << n2bs(t_state->d_max_input, d_n_code_inputs+1) <<
-           ": " << t_out_buf << " => " << t_prev_out_buf << "\n";
-#endif
-         t_out_buf->d_prev = t_prev_out_buf;
-         t_out_buf->d_inputs = t_state->d_max_input;
-// finished doing this state
-       }
-// increment the in_buf index, depending on mux'ing or not
-       t_in_buf_ndx += (d_do_mux_inputs == false) ? 1 : d_n_code_outputs;
-// increment the time counter
-        d_time_count++;
-// finished (while) staying in this fsm state or not
-      }
-      if ((d_frame_size_bits != 0) &
-          (d_time_count == d_frame_size_bits)) {
-#if DO_PRINT_DEBUG_FSM
-       std::cout << "Setting FSM to fsm_dec_doing_term\n";
-#endif
-        d_fsm = fsm_dec_doing_term;
-      }
-      break;
-#if DO_PRINT_DEBUG_FSM
-      std::cout << "Exited fsm_dec_doing_middle\n";
-#endif
-    case (fsm_dec_doing_term):
-#if DO_PRINT_DEBUG_FSM
-      std::cout << "Entered fsm_dec_doing_term\n";
-#endif
-// set the "next" up_down index to the end of their states
-      size_t t_time_count = d_max_memory - (d_time_count - d_frame_size_bits);
-      t_n_up_down_ndx = 1 << (d_n_code_inputs * t_time_count);
-// stay in this state until the correct number of input symbols are
-// reached; exit also if we run out of input symbols to process
-      while ((t_time_count > 0) &
-            (t_in_buf_ndx < t_ninput_items)) {
-#if DO_PRINT_DEBUG_TERM
-       std::cout << "Doing time " << (d_max_memory - t_time_count + 1) <<
-         " of " << d_max_memory << "; starting buf[" << t_in_buf_ndx <<
-         "] of [" << t_ninput_items << "]\n";
-#endif
-// use the "to" states,
-// FIXME: loop over just the "0" inputs
-// and compute the metric for
-// each, compare & store it in the "to" state at the end of the connection.
-
-// reset the "to" state's metrics
-        reset_metrics (d_states_ndx ^ 1);
-// reset the state's index for each set of new inputs
-       size_t* t_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx];
-       size_t* t_next_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx ^ 1];
-// loop over all current stored "term" state indeces
-       for (size_t n = 0; n < t_n_up_down_ndx; n++) {
-         size_t t_state_ndx = *t_state_ndx_ptr++;
-         state_t_ptr t_state = &(d_states[d_states_ndx][t_state_ndx]);
-// loop over just the all 0 input value (d_connections[0])
-         connection_t_ptr t_connection = t_state->d_connections;
-// get the "to" state
-          state_t_ptr t_to_state = t_connection->d_to;
-// start with this state's metric
-          float t_metric = t_state->d_max_metric;
-// get that state's metric
-          float t_to_metric = t_to_state->d_max_metric;
-#if DO_PRINT_DEBUG_TERM
-         std::cout << "Term state " << (n+1) << " of " << t_n_up_down_ndx <<
-           "; using d_s[" << d_states_ndx << "][" <<
-           n2bs(t_state_ndx,t_state_print_bits) << "]\n";
-#endif
-// see if the computation is even needed;
-// maximum change is d_n_code_outputs if all bits match exactly
-          if ((t_to_metric - t_metric) > ((float) 2*d_n_code_outputs)) {
-#if DO_PRINT_DEBUG_TERM
-           std::cout << "!not computing metric!\n";
-#endif
-           continue;
-         }
-// metrics are close enough; do the computation and the compare
-// get the output bits for this connection
-          float* t_output_bit = t_connection->d_output_bits;
-         if (d_do_mux_inputs == true) {
-// if using mux'ed input streams, handle differently
-            const float* t_in_buf = &(in_buf[0][t_in_buf_ndx]);
-// loop over all encoder-output values
-           for (size_t r = d_n_code_outputs; r > 0; r--) {
-             t_metric += ((*t_in_buf++) * (*t_output_bit++));
-           }
-         } else {
-// loop over all encoder-output values
-           for (size_t r = 0; r < d_n_code_outputs; r++) {
-              t_metric += (in_buf[r][t_in_buf_ndx] * (*t_output_bit++));
-           }
-         }
-// done with this input value; compare old and new metrics
-// see if it's the best metric
-          if (t_metric > t_to_metric) {
-#if DO_PRINT_DEBUG_TERM
-           std::cout << "New Metric to s[" <<
-             n2bs (t_connection->d_to_ndx,t_state_print_bits) << "]: ";
-           if (t_to_state->d_max_metric == -1e10) {
-             std::cout << "setting to ";
-           } else {
-             std::cout << "was s[" <<
-               n2bs(t_to_state->d_max_state_ndx,t_state_print_bits) <<
-               "]i[" << n2bs (t_to_state->d_max_input, d_n_code_inputs+1) <<
-               "]@ " << t_to_state->d_max_metric << "  now ";
-           }
-           std::cout << "s[" << n2bs(t_state_ndx,t_state_print_bits) <<
-             "] i[" << n2bs (0, d_n_code_inputs+1) << "]@ " << t_metric << 
"\n";
-#endif
-            t_to_state->d_max_metric = t_metric;
-            t_to_state->d_max_state_ndx = t_state_ndx;
-            t_to_state->d_max_input = 0;
-         }
-// add the "to" state's index to the "next" set of state's indices list
-          *t_next_state_ndx_ptr++ = t_connection->d_to_ndx;
-// finished (for) this state
-       }
-// done with all states and all inputs; now update the traceback structure
-// change which d_states' index to use as starting
-        d_states_ndx ^= 1;
-// update the number of "up_term" states
-        d_up_term_ndx ^= 1;
-// reduce the number of using states
-        t_n_up_down_ndx >>= d_n_code_inputs;
-// reset the state's index for each set of new inputs
-       t_state_ndx_ptr = d_up_term_states_ndx[d_up_term_ndx];
-// update the traceback structure
-// loop over all current states
-       traceback_t_ptr t_prev_out_bufs = d_out_buf[d_time_count];
-       traceback_t_ptr t_out_bufs = d_out_buf[d_time_count+1];
-#if DO_PRINT_DEBUG_TERM_1
-       std::cout << "d_o_b[" << d_time_count+1 << "] => d_o_b prev\n";
-#endif
-// loop over all current stored "term" state indices
-       for (size_t n = 0; n < t_n_up_down_ndx; n++) {
-// get the start index and then pointer to each of the "to" states,
-// which hold the newest "max" stuff
-         size_t t_state_ndx = *t_state_ndx_ptr++;
-         state_t_ptr t_state = &(d_states[d_states_ndx][t_state_ndx]);
-// simple: get the current state & output state
-// and connect output to the current, set inputs on output
-         traceback_t_ptr t_out_buf = &(t_out_bufs[t_state_ndx]);
-         traceback_t_ptr t_prev_out_buf =
-           &(t_prev_out_bufs[t_state->d_max_state_ndx]);
-#if DO_PRINT_DEBUG_TERM_1
-         std::cout << "ndx[" << n << "] == " << t_state_ndx <<
-           ", s[" << n2bs(t_state_ndx,t_state_print_bits) <<
-           "]: max_ndx = " <<
-           n2bs(t_state->d_max_state_ndx,t_state_print_bits) <<
-           ", input = " << n2bs(t_state->d_max_input, d_n_code_inputs+1) <<
-           ": " << t_out_buf << " => " << t_prev_out_buf << "\n";
-#endif
-         t_out_buf->d_prev = t_prev_out_buf;
-         t_out_buf->d_inputs = t_state->d_max_input;
-// finished (for) this state
-       }
-// increment the in_buf index, depending on mux'ing or not
-       t_in_buf_ndx += (d_do_mux_inputs == false) ? 1 : d_n_code_outputs;
-// increment the time counters
-        t_time_count--;
-        d_time_count++;
-// finished (while) staying in this fsm state or not
-      }
-      if (t_time_count == 0) {
-// finished this trellis, now move as much of the decoded input to the
-// output buffer as possible
-#if DO_PRINT_DEBUG_FSM
-       std::cout << "Setting FSM to fsm_dec_output\n";
-#endif
-       d_fsm = fsm_dec_output;
-      }
-#if DO_PRINT_DEBUG_FSM
-      std::cout << "Exited fsm_dec_doing_term\n";
-#endif
-      break;
-    case (fsm_dec_output):
-#if DO_PRINT_DEBUG_FSM
-      std::cout << "Entered fsm_dec_output.\n";
-#endif
-// this is done in reverse bit order (last time to first time)
-// using the traceback structure in d_out_buf, starting with
-// the maximum valued one in the last time slot, then using
-// the traceback's "d_prev" link to trace the trellis back
-
-// see where the output data will terminate
-      int t_next_out_buf_ndx = (t_out_buf_ndx +
-                               (d_frame_size_bits / g_num_bits_per_byte));
-      int t_next_out_bit_shift = (t_out_bit_shift +
-                                 (d_frame_size_bits % g_num_bits_per_byte));
-      if (t_next_out_bit_shift >= g_num_bits_per_byte) {
-       t_next_out_bit_shift -= g_num_bits_per_byte;
-       t_next_out_buf_ndx++;
-      }
-#if DO_PRINT_DEBUG_OUTPUT
-      std::cout << "First bit in at out[][" << t_out_buf_ndx << "].[" <<
-       t_out_bit_shift << "] -> " << d_frame_size_bits << " bits == " <<
-       (d_frame_size_bits / g_num_bits_per_byte) << " Byte" <<
-       ((d_frame_size_bits / g_num_bits_per_byte) != 1 ? "s" : "") <<
-       " + " << (d_frame_size_bits % g_num_bits_per_byte) << " bit" <<
-       ((d_frame_size_bits % g_num_bits_per_byte) != 1 ? "s" : "") <<
-       "\nNext set of bits start at out[][" << t_next_out_buf_ndx <<
-       "].[" << t_next_out_bit_shift << "]\n";
-#endif
-// find the starting traceback structure
-      traceback_t_ptr t_out_buf;
-      if (d_do_termination == true) {
-// FIXME: assume termination state == 0
-#if DO_PRINT_DEBUG_OUTPUT_0
-       std::cout << "Using termination; going through trellis for " <<
-         d_max_memory << " bit" <<
-         ((d_max_memory != 1) ? "s" : "") << "\n";
-#endif
-       t_out_buf = &(d_out_buf[d_time_count][0]);
-#if DO_PRINT_DEBUG_OUTPUT_0
-       std::cout << "Starting traceback ptr " << t_out_buf << "\n";
-#endif
-// skip over the termination bits
-       for (size_t n = d_max_memory; n > 0; n--) {
-         t_out_buf = t_out_buf->d_prev;
-#if DO_PRINT_DEBUG_OUTPUT_0
-         std::cout << "Next traceback ptr " << t_out_buf << "\n";
-#endif
-       }
-      } else {
-// no termination but doing block coding;
-// FIXME: use the state with the bext metric
-// get the state's index for each set of new inputs
-       state_t_ptr t_state = d_states[d_states_ndx];
-       float t_max_metric = t_state->d_max_metric;
-       size_t t_max_state_ndx = 0;
-       t_state++;
-// loop over all current states
-       for (size_t n = 1; n < d_n_states; n++, t_state++) {
-// start with this state's metric
-         float t_metric = t_state->d_max_metric;
-// compare with current max
-         if (t_metric > t_max_metric) {
-           t_max_metric = t_metric;
-           t_max_state_ndx = n;
-         }
-       }
-// get the correct out_buf reference to start with
-       t_out_buf = &(d_out_buf[d_time_count][t_max_state_ndx]);
-      }
-#if DO_PRINT_DEBUG_OUTPUT
-      std::cout << "Found starting traceback ptr " << t_out_buf <<
-       "; getting all " << d_frame_size_bits << " bits per stream.\n";
-#endif
-// now we've got the starting traceback structure address;
-// check to make sure there is enough space in each output buffer
-      size_t t_frame_bit_ndx = d_frame_size_bits;
-      if ((t_next_out_buf_ndx > t_noutput_bytes) |
-         ((t_next_out_buf_ndx == t_noutput_bytes) &
-          (t_next_out_bit_shift != 0))) {
-// not enough space for all output bits;
-// find the number of extra bits to save
-       size_t t_save_buf_ndx = t_next_out_buf_ndx - t_noutput_bytes;
-       size_t t_n_extra_bits = ((t_save_buf_ndx * g_num_bits_per_byte) +
-                                t_next_out_bit_shift);
-// set the number of saved bits
-       d_n_saved_bits = t_n_extra_bits;
-// remove the extra bits from the number to copy to the output buffer
-       t_frame_bit_ndx -= t_n_extra_bits;
-// find the actual output buf index, once we get there
-       t_next_out_buf_ndx -= t_save_buf_ndx;
-#if DO_PRINT_DEBUG_OUTPUT
-       std::cout << "Not enough output buffer space:\n" <<
-         "len (o_b) = " << t_noutput_bytes << " ==> " <<
-         t_n_extra_bits << " extra bit" <<
-         (t_n_extra_bits != 1 ? "s" : "") << " == " <<
-         t_save_buf_ndx << " Byte" <<
-         (t_save_buf_ndx != 1 ? "s" : "") << ", " <<
-         t_next_out_bit_shift << " bit" <<
-         (t_next_out_bit_shift != 1 ? "s" : "") << "\n";
-#endif
-// zero each output buffers' bytes
-       size_t t_n_zero = t_save_buf_ndx + (t_next_out_bit_shift ? 1 : 0);
-#if DO_PRINT_DEBUG_OUTPUT
-       size_t t_n_out_bytes = ((d_frame_size_bits / g_num_bits_per_byte) +
-                               ((d_frame_size_bits % g_num_bits_per_byte) ? 1 
: 0));
-       std::cout << "Zeroing save buffer from for " << t_n_zero <<
-         " Byte" << (t_n_zero != 1 ? "s" : "") << " (of " <<
-         d_frame_size_bits << " bit" <<
-         (d_frame_size_bits != 1 ? "s" : "") << " == " << t_n_out_bytes <<
-         " Byte" << (t_n_out_bytes != 1 ? "s" : "") << ")\n";
-#endif
-       for (size_t m = 0; m < d_n_code_inputs; m++)
-         bzero (d_save_buffer[m], t_n_zero);
-// loop over all extra bits
-       for (size_t n = t_n_extra_bits; n > 0; n--) {
-// first decrement the output bit & byte as necessary
-         if (--t_next_out_bit_shift < 0) {
-           t_next_out_bit_shift += g_num_bits_per_byte;
-           t_save_buf_ndx--;
-         }
-// get the encoder inputs to output
-         size_t t_inputs = t_out_buf->d_inputs;
-// loop over all code inputs (decoder-outputs), 1 bit per stream
-         for (size_t m = 0; m < d_n_code_inputs; m++) {
-           d_save_buffer[m][t_save_buf_ndx] |=
-             ((t_inputs & 1) << t_next_out_bit_shift);
-           t_inputs >>= 1;
-         }
-         t_out_buf = t_out_buf->d_prev;
-#if DO_PRINT_DEBUG_OUTPUT_0
-         std::cout << "Next traceback ptr " << t_out_buf << "\n";
-#endif
-       }
-// at exit, "t_out_buf_ndx" should be == t_noutput_bytes, and
-// "t_out_bit_shift" should be 0; check these!
-#if DO_PRINT_DEBUG_OUTPUT
-       std::cout << "n_o_b_ndx (" << t_next_out_buf_ndx << ") ?=? " <<
-         "#o_B (" << t_noutput_bytes << ") & t_o_b_sh (" <<
-         t_next_out_bit_shift << ") ?=? 0\n";
-       assert (t_next_out_buf_ndx == t_noutput_bytes);
-       assert (t_next_out_bit_shift == 0);
-#endif
-      }
-// set the correct output buffer index and bit shift
-      t_out_bit_shift = t_next_out_bit_shift;
-      t_out_buf_ndx = t_next_out_buf_ndx;
-// copy any remaining bits looping backwards in bit-time
-// through the traceback trellis
-      for (size_t n = t_frame_bit_ndx; n > 0; n--) {
-// first decrement the output bit & byte as necessary
-       if (--t_out_bit_shift < 0) {
-         t_out_bit_shift += g_num_bits_per_byte;
-         t_out_buf_ndx--;
-       }
-// get the encoder inputs to output
-       size_t t_inputs = t_out_buf->d_inputs;
-// loop over all code inputs (decoder-outputs), 1 bit per stream
-       for (size_t m = 0; m < d_n_code_inputs; m++) {
-         out_buf[m][t_out_buf_ndx] |= ((t_inputs & 1) << t_out_bit_shift);
-         t_inputs >>= 1;
-       }
-       t_out_buf = t_out_buf->d_prev;
-#if DO_PRINT_DEBUG_OUTPUT_0
-       std::cout << "Next traceback ptr " << t_out_buf << "\n";
-#endif
-      }
-// set the next output byte and bit-shift
-      t_out_bit_shift = t_next_out_bit_shift;
-      t_out_buf_ndx = t_next_out_buf_ndx;
-#if DO_PRINT_DEBUG_FSM
-      std::cout << "Set FSM to fsm_dec_init\n";
-#endif
-      d_fsm = fsm_dec_init;
-#if DO_PRINT_DEBUG_FSM
-      std::cout << "Exited fsm_dec_output\n";
-#endif
-      break;
-    case (fsm_dec_init):
-#if DO_PRINT_DEBUG_FSM
-      std::cout << "Entered fsm_dec_init\n";
-#endif
-// this is called immediately (first input bit upon startup),
-// or after termination of a trellis.
-
-// reset states to the 0'th one
-      d_up_term_ndx = d_states_ndx = 0;
-// zero the metrics for those states
-      zero_metrics (0);
-#if 0
-// might not need to do this; check and see after it works
-// reset up_term states and number so that there is 1 item, the "0" state.
-      bzero (d_up_term_states_ndx[0], sizeof (size_t) * d_n_states);
-      bzero (d_up_term_states_ndx[1], sizeof (size_t) * d_n_states);
-#else
-      d_up_term_states_ndx[0][0] = 0;
-#endif
-// reset time count back to the start
-      d_time_count = 0;
-#if 0
-// reset the traceback structures
-// might not need to do this; check and see after it works
-      traceback_t_hdl t_out_bufs = d_out_buf;
-      for (size_t n = d_n_traceback_els; n > 0; n--) {
-       traceback_t_ptr t_out_buf = (*t_out_bufs++);
-       for (size_t m = d_n_states; m > 0; m--, t_out_buf++) {
-         t_out_buf->d_prev = NULL;
-         t_out_buf->d_inputs = -1;
-       }
-      }
-#endif
-// set the fsm to "doing up"
-#if DO_PRINT_DEBUG_FSM
-      std::cout << "Set FSM to fsm_dec_doing_up\n";
-#endif
-      d_fsm = fsm_dec_doing_up;
-#if DO_PRINT_DEBUG_FSM
-      std::cout << "Exited fsm_dec_init\n";
-#endif
-      break;
-// should never get here!
-    default:
-      assert (0);
-// done (switch) with FSM
-    }
-// done (while) there are inputs
-  }
-
-// consume all of the input items on all input streams
-// "ninput_items[]" doesn't seem to be reliable,
-// so compute this from the actual number of frames processed
-#if DO_PRINT_DEBUG_EXIT
-  std::cout << "Exiting FSM in state: " <<
-    (d_fsm == fsm_dec_init ? "init" :
-     (d_fsm == fsm_dec_doing_up ? "up" :
-      (d_fsm == fsm_dec_doing_middle ? "middle" :
-       (d_fsm == fsm_dec_doing_term ? "term" :
-       (d_fsm == fsm_dec_output ? "output" : "unknown"))))) << "\n" <<
-    "Consuming " << t_in_buf_ndx <<
-    " input items on each input stream (of " << t_ninput_items << ").\n";
-#endif
-  consume_each (t_in_buf_ndx);
-
-// make sure the number of output items makes sense
-// t_out_buf_ndx always points to the current index
-// t_out_bit_shift always points to the next bit position to be written
-  int t_leftover_bytes = t_out_buf_ndx % d_out_stream_el_size_bytes;
-  int t_leftover_bits = ((t_leftover_bytes * g_num_bits_per_byte) +
-                        t_out_bit_shift);
-  int t_noutput_items = noutput_items;
-#if DO_PRINT_DEBUG_EXIT
-  std::cout << "Final o_b[" << t_out_buf_ndx << "][" <<
-    t_out_bit_shift << "] of " << t_noutput_bytes <<
-    ", el_size = " << d_out_stream_el_size_bytes <<
-    ", lo_Bytes = " << t_leftover_bytes <<
-    ", t_lo_bits = " << t_leftover_bits << "\n" <<
-    "Desired # output items = " << noutput_items << "\n";
-#endif
-  if (t_leftover_bits != 0) {
-    // should never get here!
-#if 1
-    assert (0);
-#else
-    int t_ndx = t_out_buf_ndx - t_leftover_bytes;
-    size_t t_n_copy = t_leftover_bytes + ((t_out_bit_shift != 0) ? 1 : 0);
-    assert (t_n_copy <= d_out_stream_el_size_bytes);
-// copy the leftover into the save buffer
-    for (size_t n = 0; n < d_n_code_inputs; n++) {
-      bcopy (&(out_buf[n][t_ndx]), d_save_buffer[n], t_n_copy);
-    }
-    t_noutput_items = t_ndx / d_out_stream_el_size_bytes;
-    d_n_saved_bits = t_leftover_bits;
-#if DO_PRINT_DEBUG_EXIT
-    std::cout << "Copied " << t_n_copy << " Byte" <<
-      (t_n_copy != 1 ? "s" : "") << " from o_b[][" << t_ndx <<
-      "] into each save buffer.\n" <<
-      "Actual #output items = " << t_noutput_items <<
-      ", # saved bit(s) = " << d_n_saved_bits << "\n";
-#endif
-#endif
-  }
-
-#if DO_TIME_THOUGHPUT
-  u_long d_t = end_timer (&t_tp);
-
-  std::cout << "dec_blk_conv_soft_full: Completed " << t_ninput_items <<
-    " bits in " << d_t << " usec => " <<
-    1e6*(((double)(t_ninput_items))/((double) d_t)) <<
-    " b/s\n";
-#endif
-
-// returns number of items written to each output stream
-  return (t_noutput_items);
-}

Index: gr_decoder_viterbi_block_soft_full.h
===================================================================
RCS file: gr_decoder_viterbi_block_soft_full.h
diff -N gr_decoder_viterbi_block_soft_full.h
--- gr_decoder_viterbi_block_soft_full.h        3 Jul 2006 02:12:53 -0000       
1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,238 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006 Free Software Foundation, Inc.
- * 
- * This file is part of GNU Radio.
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- * 
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING.  If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef INCLUDED_GR_DECODER_VITERBI_BLOCK_SOFT_FULL_H
-#define INCLUDED_GR_DECODER_VITERBI_BLOCK_SOFT_FULL_H
-
-#include <gr_block.h>
-#include <vector>
-#include <sys/types.h>
-
-struct state_t;
-
-/*
- * connection_t: describes an output connection from the current
- *     time-bit memory state to the next time-bit memory state
- *
- * d_to: state pointer to which this connection going
- *
- * d_to_ndx: index of the "to" state
- *
- * d_output_bits: what are the output bits, coverted into
- *     1->+1.0, 0->-1.0, for this connection
- */
-
-typedef struct connection_t {
-  struct state_t *d_to;
-  int d_to_ndx;
-  float* d_output_bits;
-} connection_t, *connection_t_ptr;
-
-/*
- * state_t: describes a given memory state
- *
- * d_connections:  a pointer to an array of these structures
- *     will be used to describes a given time-bit's memory state;
- *     an entry will be referenced via "state_add_to", to find the
- *     connections to the next time-bit memory states.  There is
- *     one entry per each input bit combination -> 2^#I connections in all.
- *     e.g. [0] means the all 0 input;
- *     [1] means that input #1 was 1 while all the others were 0;
- *     [2] means that input #2 was 1, while all the others were 0;
- *     [3] means that inputs #1 and #2 were 1, while the others were 0.
- *
- * d_max_metric: the maximum metric thus far for this state
- *
- * d_max_state: the state from which the maximum metric was attained
- *
- * d_max_input: the input bits from which the maximum metric was attained
- */
-
-typedef struct state_t {
-  connection_t_ptr d_connections;
-  float d_max_metric;
-  int d_max_state_ndx;
-  int d_max_input;
-} state_t, *state_t_ptr;
-
-/*
- * state_get_from(v,i,k): use to retrieve a given bit-memory state,
- *     from the inputs:
- *
- * int v: the value from which to retrieve the given state
- * int i: for which input stream (0 to #I-1)
- * int k: the number of memory slots per input (e.g. 1+D^2 -> 2)
- */
-
-#define state_get_from(v,i,k) (((v)>>((i)*(k)))&((1<<(k))-1))
-
-/*
- * state_add_to(s,i,v,k): use to create a given bit-memory state,
- *     from the inputs:
- *
- * int s: the state value to modify
- * int i: for which input stream (0 to #I-1)
- * int v: value to set the state to for this input
- * int k: the number of memory slots per input (e.g. 1+D^2 -> 2)
- */
-
-#define state_add_to(s,v,i,k) (s)|=(((v)&((1<<(k))-1))<<((i)*(k)))
-
-/*
- * fsm_dec_t: finite state machine for the decoder
- *
- * fsm_dec_init: initialize for a new frame / block; this is already
- *     done at instantiation, so do it only at the end of a block.
- *
- * fsm_dec_doing_up: starting the trellis; done for all types
- *
- * fsm_dec_doing_middle: full trellis; done for all types
- *
- * fsm_dec_doing_term: termination trellis, if requested
- *
- * fsm_dec_doing_output: output all bits
- */
-
-typedef enum {
-  fsm_dec_init, fsm_dec_doing_up, fsm_dec_doing_middle,
-  fsm_dec_doing_term, fsm_dec_output
-} fsm_dec_t;
-
-/*
- * traceback_t: used to store all encode-input bits for
- *     all possible paths, when computing all trellis bits before
- *     determining the ML decode-output sequence.
- *
- * d_prev: the connection to the previous bit's traceback structure
- *
- * d_inputs: the inputs (one per bit) for this connection
- */
-
-typedef struct traceback_t {
-  struct traceback_t *d_prev;
-  int d_inputs;
-} traceback_t, *traceback_t_ptr, **traceback_t_hdl;
-
-// GR stuff
-
-class gr_decoder_viterbi_block_soft_full;
-typedef boost::shared_ptr<gr_decoder_viterbi_block_soft_full>
-gr_decoder_viterbi_block_soft_full_sptr;
-
-gr_decoder_viterbi_block_soft_full_sptr gr_make_dec_blk_conv_soft_full
-(int frame_size_bits,
- int num_input_streams,
- int num_output_streams,
- std::vector<int> code_generator,
- bool do_termination);
-
-/*!
- * \brief Decode the incoming streams using a Viterbi-style decoder
- *
- * input: encoded data as soft symbols, either as individual
- *     streams or mux'ed into 1 stream.
- *
- * output: stream(s) of user-defined element size.
- */
-
-class gr_decoder_viterbi_block_soft_full : public gr_block
-{
-  friend gr_decoder_viterbi_block_soft_full_sptr
-  gr_make_dec_blk_conv_soft_full (int frame_size_bits,
-                                 int num_input_streams,
-                                 int num_output_streams,
-                                 std::vector<int> code_generator,
-                                 bool do_termination);
-/*
- * frame_size_bits: if == 0, then do streaming decoding (infinite
- *     trellis); otherwise this is the block size to decode before
- *     terminating the trellis.
- *
- * code_generator: vector of integers (32 bit) representing the code
- *     to be implemented in octal form.  E.g. "04" in binary is "100",
- *     which would be "D^2" for code generation.  "06" == 110b == "D^2 + D"
- *  ==> The vector is listed in order for each input stream, so if there
- *     are 2 input streams (I1, I2) [specified in "n_code_inputs"]
- *     and 2 output streams (O1, O2) [specified in "n_code_outputs"],
- *     then the vector would be the code generator for:
- *       [I1->O1, I1->O2, I2->O1, I2->O2]
- *     with each element being the octal representation of the code.
- *
- * do_termination is valid only if frame_size_bits != 0, and defines
- *     whether or not to to trellis termination.
- *
- * do_mux_input: is true, then the one input stream will be
- *     interpreted as the multiplexing all of the input bits.  For
- *     example for a 3 input decoder, the input stream would be
- *     [I1[k], I2[k], I3[k], I1[k+1], I2[k+1], ...], where "k" is the
- *     input sample time, and "I1" through "I3" are the 3 input
- *     streams.
- *
- * n_code_inputs: the number of decoder-input (encoder-output)
- *     streams, no matter if separate or mux'ed
- *
- * n_code_outputs: the number of decoder-output (encoder-input) streams
- */
-
-  gr_decoder_viterbi_block_soft_full (int frame_size_bits,
-                                     int num_input_streams,
-                                     int num_output_streams,
-                                     std::vector<int> code_generator,
-                                     bool do_termination);
-
-public:
-  ~gr_decoder_viterbi_block_soft_full ();
-
-  virtual void forecast (int noutput_items,
-                        gr_vector_int &ninput_items_required);
-
-  virtual int general_work (int noutput_items,
-                           gr_vector_int &ninput_items,
-                           gr_vector_const_void_star &input_items,
-                           gr_vector_void_star &output_items);
-
-  virtual int fixed_rate_noutput_to_ninput (int noutput_items);
-
-private:
-  void reset_metrics (u_char which);
-  void zero_metrics (u_char which);
-
-/*
- * d_n_total_input_bits_per_stream: how many bits to store for each
- *     state to determine the best decoder-output (encoder-input) bits 
- */
-  size_t d_frame_size_bits;
-  size_t d_n_code_outputs, d_n_code_inputs, d_max_memory;
-  size_t d_time_count, d_n_total_input_bits_per_stream;
-  size_t d_n_saved_bits, d_n_saved_bits_start_ndx, d_n_traceback_els;
-  size_t d_n_states, d_n_input_combinations;
-  size_t d_states_ndx, d_up_term_ndx;
-  bool d_do_streaming, d_do_termination, d_do_mux_inputs;
-  char **d_save_buffer;
-  std::vector<int> d_code_generators;
-  state_t_ptr d_states[2];
-  fsm_dec_t d_fsm;
-  size_t* d_up_term_states_ndx[2];
-  traceback_t_hdl d_out_buf;
-};
-
-#endif /* INCLUDED_GR_DECODER_VITERBI_BLOCK_SOFT_FULL_H */

Index: gr_decoder_viterbi_block_soft_full.i
===================================================================
RCS file: gr_decoder_viterbi_block_soft_full.i
diff -N gr_decoder_viterbi_block_soft_full.i
--- gr_decoder_viterbi_block_soft_full.i        3 Jul 2006 02:12:53 -0000       
1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,39 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006 Free Software Foundation, Inc.
- * 
- * This file is part of GNU Radio
- * 
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- * 
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING.  If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-GR_SWIG_BLOCK_MAGIC(gr,dec_blk_conv_soft_full);
-
-gr_decoder_viterbi_block_soft_full_sptr
-gr_make_decoder_viterbi_block_soft_full (int frame_size_bits,
-                                        int num_input_streams,
-                                        int num_output_streams,
-                                        std::vector<int> code_generator,
-                                        bool do_termination);
-
-class gr_decoder_viterbi_block_soft_full : public gr_block
-{
-  gr_decoder_viterbi_block_soft_full (int frame_size_bits,
-                                     int num_input_streams,
-                                     int num_output_streams,
-                                     std::vector<int> code_generator,
-                                     bool do_termination);
-};

Index: libecc/decoder_viterbi_base.h
===================================================================
RCS file: libecc/decoder_viterbi_base.h
diff -N libecc/decoder_viterbi_base.h
--- libecc/decoder_viterbi_base.h       4 Jul 2006 20:57:32 -0000       1.2
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,139 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006 Free Software Foundation, Inc.
- * 
- * This file is part of GNU Radio
- * 
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- * 
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING.  If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef INCLUDED_DECODER_VITERBI_H
-#define INCLUDED_DECODER_VITERBI_H
-
-#include <vector>
-#include "decoder.h"
-
-/*!
- * \brief Decode the incoming metrics streams using the Viterbi algorithm.
- *
- * input: streams of metrics, 
- *
- * output: streams of char, one stream per output as defined by the
- *     instantiated code, using only the right-most justified bit as
- *     the single output bit per output item.
- */
-
-class decoder_viterbi : public decoder
-{
-public:
-/*
- * frame_size_bits: if == 0, then do streaming encoding ("infinite"
- *     trellis); otherwise this is the frame size in bits to decode
- *     before terminating the trellis.  This value -does not- include
- *     any termination bits.
- *
- * n_code_inputs:
- * n_code_outputs:
- * code_generator: vector of integers (32 bit) representing the code
- *     to be implemented in octal form.  E.g. "04" in binary is "100",
- *     which would be "D^2" for code generation.  "06" == 110b == "D^2 + D"
- *  ==> The vector is listed in order for each input stream, so if there
- *     are 2 input streams (I1, I2) [specified in "n_code_inputs"]
- *     and 2 output streams (O1, O2) [specified in "n_code_outputs"],
- *     then the vector would be the code generator for:
- *       [I1->O1, I1->O2, I2->O1, I2->O2]
- *     with each element being the octal representation of the code.
- *
- * do_termination: valid only if frame_size_bits != 0, and defines
- *     whether or not to use trellis termination.  Default is to use
- *     termination when doing block coding.
- *
- * start_memory_state: when starting a new block, the starting memory
- *     state to begin encoding; there will be a helper function to
- *     assist in creating this value for a given set of inputs;
- *     default is the "all zero" state.
- * 
- * end_memory_state: when terminating a block, the ending memory
- *     state to stop encoding; there will be a helper function to
- *     assist in creating this value for a given set of inputs;
- *     default is the "all zero" state.
- */
-
-  decoder_viterbi (int frame_size_bits,
-                  int n_code_inputs,
-                  int n_code_outputs,
-                  std::vector<int> &code_generators,
-                  int start_memory_state = 0,
-                  int end_memory_state = 0,
-                  bool do_termination = true,
-                  bool use_muxed_inputs = false,
-                  bool do_muxed_outputs = false,
-                  bool use_packed_input = false,
-                  bool do_packed_outputs = false);
-
-  virtual ~decoder_viterbi () {};
-
-  virtual size_t compute_n_input_bits (size_t n_output_bits);
-  virtual size_t compute_n_output_bits (size_t n_input_bits);
-  virtual size_t decode (const char** in_buf,
-                        char** out_buf,
-                        size_t n_bits_to_output);
-  virtual size_t decode (const char** in_buf,
-                        size_t n_bits_to_input,
-                        char** out_buf);
-
-private:
-/*
- * fsm_dec_viterbi_t: finite state machine for the convolutional decoder;
- *     output happens all the time, so that's built-in to each state.
- *
- * fsm_dec_viterbi_init: initialize for a new frame / block; this is already
- *     done at instantiation, so do it only at the end of a block.
- *
- * fsm_dec_viterbi_doing_up: encoding at the start of a block
- *
- * fsm_dec_viterbi_doing_middle: doing encoding inside the trellis
- *
- * fsm_dec_viterbi_doing_term: termination trellis, if requested
- */
-
-  enum fsm_dec_viterbi_t {
-    fsm_dec_viterbi_init, fsm_dec_viterbi_doing_up,
-    fsm_dec_viterbi_doing_middle, fsm_dec_viterbi_doing_term
-  };
-
-  virtual void decode_private (const char** in_buf, char** out_buf);
-  virtual void decode_loop (const char** in_buf, char** out_buf,
-                           size_t* which_counter, size_t how_many);
-  virtual char get_new_input_bit (const char** in_buf, size_t code_input_n);
-  virtual char get_new_input_bit__up (const char** in_buf,
-                                     size_t code_input_n);
-  virtual char get_new_input_bit__middle (const char** in_buf,
-                                         size_t code_input_n);
-  virtual char get_new_input_bit__term (size_t code_input_n);
-  virtual void output_bit (char t_out_bit, char** out_buf,
-                          size_t t_output_stream);
-  virtual void increment_counters (bool while_encoding);
-
-  fsm_dec_viterbi_t d_fsm_state;
-  bool d_use_muxed_inputs, d_do_muxed_outputs;
-  bool d_use_packed_input, d_do_packed_outputs;
-  bool d_do_streaming, d_do_termination;
-  std::vector<memory_t> d_code_generators;
-  std::vector<memory_t> d_states, d_init_states, d_term_states;
-};
-
-#endif /* INCLUDED_DECODER_VITERBI_H */

Index: libecc/encoder_convolutional_base.cc
===================================================================
RCS file: libecc/encoder_convolutional_base.cc
diff -N libecc/encoder_convolutional_base.cc
--- libecc/encoder_convolutional_base.cc        4 Jul 2006 20:57:32 -0000       
1.2
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,730 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006 Free Software Foundation, Inc.
- * 
- * This file is part of GNU Radio
- * 
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- * 
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING.  If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <encoder_convolutional_base.h>
-#include <assert.h>
-#include <iostream>
-
-#define DO_TIME_THOUGHPUT 1
-#define DO_PRINT_DEBUG 1
-
-#if DO_TIME_THOUGHPUT
-#include <mld/mld_timer.h>
-#endif
-#if DO_PRINT_DEBUG
-#include <mld/n2bs.h>
-#endif
-
-static const int g_max_frame_size_bits = 10000000;
-static const int g_max_num_streams = 10;
-
-void encoder_convolutional_base::encoder_convolutional_base_init
-(int frame_size_bits,
- int n_code_inputs,
- int n_code_outputs,
- std::vector<int> &code_generators,
- bool do_termination,
- int start_memory_state,
- int end_memory_state)
-{
-  // do error checking on the input arguments
-
-  // make sure the frame length makes sense
-
-  if ((frame_size_bits < 0) | (frame_size_bits > g_max_frame_size_bits)) {
-    std::cerr << "encoder_convolutional_base: " <<
-      "Requested frame length (" << frame_size_bits <<
-      " bits) must be between 0 and " << g_max_frame_size_bits <<
-      " bits, with 0 being a streaming encoder.\n";
-    assert (0);
-  }
-
-  // check to make sure the number of input streams makes sense
-
-  if ((n_code_inputs <= 0) | (n_code_inputs > g_max_num_streams)) {
-    std::cerr << "encoder_convolutional_base: " <<
-      "Requested number of input streams (" <<
-      n_code_inputs << ") must be between 1 and " <<
-      g_max_num_streams << ".\n";
-    assert (0);
-  }
-
-  // check to make sure the number of output streams makes sense
-
-  if ((n_code_outputs <= 0) | (n_code_outputs > g_max_num_streams)) {
-    std::cerr << "encoder_convolutional_base: " <<
-      "Requested number of output streams (" <<
-      n_code_outputs << ") must be between 1 and " <<
-      g_max_num_streams << ".\n";
-    assert (0);
-  }
-
-  // make sure the code_generator is the correct length
-
-  if (code_generators.size () !=
-      ((size_t)(n_code_inputs * n_code_outputs))) {
-    std::cerr << "encoder_convolutional_base: " <<
-      "Number of code generator entries (" << code_generators.size () <<
-      ") is not equal to the product of the number of input and output" <<
-      " streams (" << (n_code_inputs * n_code_outputs) << ").\n";
-    assert (0);
-  }
-
-  // create the class frame variables
-
-  d_frame_size_bits = frame_size_bits;
-  d_n_code_inputs = n_code_inputs;
-  d_n_code_outputs = n_code_outputs;
-  d_do_streaming = (frame_size_bits == 0);
-  d_do_termination = (d_do_streaming == true) ? false : do_termination;
-
-  // allocate the vectors for doing the encoding.  use memory_t (an
-  // interger type, at least 32 bits) bits to represent memory and the
-  // code, as it makes the operations quite simple the state vectors.
-
-  // d_states is a "matrix" [#input by #outputs] containing pointers
-  // to memory_t's; this is done to make feedback function properly,
-  // and doesn't effect the computation time for feedforward.  The
-  // issue is that any code with the same feedback can use the same
-  // memory - thus reducing the actual number of memories required.
-  // These overlapping encoders will use the same actual memory, but
-  // given that there is no way to know a-priori where they are, use
-  // pointers over the full I/O matrix-space to make sure each I/O
-  // encoder uses the correct memory.
-  // reference the matrix using "maio(i,o)" ... see .h file.
-
-  d_states.assign (d_n_code_inputs * d_n_code_outputs, NULL);
-
-  // code generators (feedforward part) are [#inputs x #outputs],
-  // always - one for each I/O combination.
-  // reference the matrix using "maio(i,o)" ... see .h file
-
-  d_code_generators.assign (d_n_code_inputs * d_n_code_outputs, 0);
-
-  // for now, assign the feedback to the "1" for each code - meaning
-  // no feedback.  Set the variable for feedback to "false".
-  // reference the matrix using "maio(i,o)" ... see .h file
-
-  d_code_feedback.assign (d_n_code_inputs * d_n_code_outputs, 1);
-  d_do_feedback = false;
-
-  // check the input code_generator for correctness & find the memory order
-  // t_max_mem will be the mamimum number of memories used by the generator
-
-  size_t t_max_mem = 0;
-
-  // loop over all input streams first, output streams second
-
-  for (size_t n = 0; n < d_n_code_outputs; n++) {
-    memory_t t_all_inputs_zero = 0;
-    for (size_t m = 0; m < d_n_code_inputs; m++) {
-      size_t t_in_code = d_code_generators[maio(m,n)] =
-       code_generators[maio(m,n)];
-
-      // check that not all codes for this input are 0
-
-      t_all_inputs_zero |= t_in_code;
-
-      // find the memory requirement for this code generator
-
-      size_t t_code_mem = 0;
-      while (t_in_code != 0) {
-       t_in_code >>= 1;
-       t_code_mem++;
-      }
-      if (t_code_mem > t_max_mem)
-       t_max_mem = t_code_mem;
-    }
-
-    // check this input to make sure all encoders were not '0'
-
-    if (t_all_inputs_zero == 0) {
-      std::cerr << "encoder_convolutional_base: " <<
-       "At least 1 generator code for output " << n+1 <<
-       " must be non-0.\n";
-      assert (0);
-    }
-  }
-
-  // store the maximum memory order (e.g. "2" -> D^2)
-
-  d_max_memory = t_max_mem - 1;
-
-  // make sure the frame length makes sense, #2
-
-  if ((d_frame_size_bits != 0) & (d_frame_size_bits < d_max_memory)) {
-    std::cerr << "encoder_convolutional_base: " <<
-      "Requested frame length (" << d_frame_size_bits <<
-      " bit" << (d_frame_size_bits > 1 ? "s" : "") <<
-      ") must be at least 1 memory length (" << d_max_memory <<
-      " bit" << (d_max_memory > 1 ? "s" : "") <<
-      " for this code) when doing block coding.\n";
-    assert (0);
-  }
-
-  // create the memory mask for this code generator
-
-  d_max_mem_mask = (2 << d_max_memory) - 1;
-
-// FIXME:  STILL NEED TO parse START AND END MEMORY STATES;
-
-  // set the initial FSM state to 'init'
-
-  d_fsm_state = fsm_enc_conv_init;
-
-  if (DO_PRINT_DEBUG) {
-    std::cout << "Encoder:\n  Mask = " <<
-      n2bs (d_max_mem_mask, d_max_memory+2) <<
-      "\n  Max_Mem = " << d_max_memory << "\n.";
-  }
-
-  // by default no Feedback;
-  // setup for that from here down:
-  // 1 memory per input; same for init and term states;
-
-  d_n_memories = d_n_code_inputs;
-  d_memory.assign (d_n_code_inputs, 0);
-  d_init_states.assign (d_n_code_inputs, 0);
-  d_term_states.assign (d_n_code_inputs, 0);
-
-  // assign input numbers, one per memory
-
-  for (size_t n = 0; n < d_n_code_inputs; n++)
-    d_input_num[n] = n;
-
-  // assign d_states' pointers correctly
-  // loop over all I/O streams
-
-  for (size_t n = 0; n < d_n_code_outputs; n++)
-    for (size_t m = 0; m < d_n_code_inputs; m++)
-      d_states[maio(m,n)] = &(d_memory[m]);
-}
-
-encoder_convolutional_base::encoder_convolutional_base
-(int frame_size_bits,
- int n_code_inputs,
- int n_code_outputs,
- std::vector<int> &code_generators,
- std::vector<int> &code_feedback,
- bool do_termination,
- int start_memory_state,
- int end_memory_state)
-{
-  // call the general init routine, to parse inputs; deal with
-  // feedback after this parsing.
-
-  encoder_convolutional_base_init
-    (frame_size_bits,
-     n_code_inputs,
-     n_code_outputs,
-     code_generators,
-     do_termination,
-     start_memory_state,
-     end_memory_state);
-
-  // need to check the code_feedback to make sure it's valid; need to
-  // update the "d_max_memory" and comment back to the user if
-  // feedback is longer than feedforward.  Otherwise, everything else
-  // is done by the super-class.
-
-  d_do_feedback = true;
-
-  // resize the memory and states to the max size, worst case
-
-  d_memory.assign (d_n_code_inputs * d_n_code_outputs, 0);
-  d_init_states.assign (d_n_code_inputs * d_n_code_outputs, 0);
-  d_term_states.assign (d_n_code_inputs * d_n_code_outputs, 0);
-  d_code_feedback.assign (d_n_code_inputs * d_n_code_outputs, 0);
-  d_input_num.assign (d_n_code_inputs * d_n_code_outputs, 0);
-
-  // check the code_feedback for correctness & find the memory order
-  // t_max_mem will be the mamimum number of memories used by the
-  // feedback; code_feedback will be in "input" first order, which is
-  // what is required internally.
-
-  size_t t_max_mem = d_n_memories = 0;
-  memory_t t_all_inputs_one = 0;
-
-  for (size_t n = 0; n < d_n_code_outputs; n++) {
-    size_t t_n_unique_fb_prev_start = d_n_memories;
-
-    for (size_t m = 0; m < d_n_code_inputs; m++) {
-      size_t t_save_code = code_feedback[maio(m,n)];
-      size_t t_in_code = t_save_code;
-
-      // check to make sure (code & 1) == 1; can't do this type of
-      // convolutional encoder without it!
-
-      if ((t_in_code & 1) != 1) {
-       std::cerr << "encoder_convolutional_base: " <<
-         "All feedback codes must contain a '1' for the least "
-         "significant bit.\n";
-       assert (0);
-      }
-
-      // find if this feedback is unique for this input;
-
-      size_t l_n_unique_fb = t_n_unique_fb_prev_start;
-      while (l_n_unique_fb < d_n_memories) {
-       if (d_code_feedback[l_n_unique_fb] == t_save_code)
-         break;
-       l_n_unique_fb++;
-      }
-      if (l_n_unique_fb == d_n_memories) {
-
-       // this is a unique feedback;
-       // create new entries for it in d_code_feedback and d_input_num
-
-       d_code_feedback[l_n_unique_fb] = t_save_code;
-       d_input_num[l_n_unique_fb] = m;
-
-       // update the "or" of all unique memories
-
-       t_all_inputs_one |= t_save_code;
-
-       // find the memory requirement for this code feedback
-
-       size_t t_code_mem = 0;
-       t_in_code = t_save_code;
-       while (t_in_code != 0) {
-         t_in_code >>= 1;
-         t_code_mem++;
-       }
-       if (t_code_mem > t_max_mem)
-         t_max_mem = t_code_mem;
-
-       // increase the number of unique feedback codes
-
-       d_n_memories++;
-      }
-
-      // create the new entry in d_states
-
-      d_states[maio(m,n)] = &(d_memory[l_n_unique_fb]);
-    }
-  }
-
-  // check to see if all the feedback entries were "1", which implies
-  // no feedback; warn the user in that case.
-
-  if (t_all_inputs_one == 1) {
-    std::cout << "encoder_convolutional_base: Warning: " <<
-      "No feedback is required, use of the non-feedback constructor "
-      "will provide higher throughput.\n";
-  }
-
-  // check to see if the feedback's memory requirements are greater
-  // than the feedforward's; warn the user (not sure why, but it seems
-  // like a good idea).
-
-  if (--t_max_mem > d_max_memory) {
-    std::cout << "encoder_convolutional_base: Warning: " <<
-      "Feedback using more memory than feedforward.\n";
-    d_max_memory = t_max_mem;
-
-    // make sure the frame length makes sense, #2
-
-    if ((d_do_streaming == true) & (d_frame_size_bits < d_max_memory)) {
-      std::cerr << "encoder_convolutional_base: " <<
-       "Requested frame length (" << d_frame_size_bits <<
-       " bit" << (d_frame_size_bits > 1 ? "s" : "") <<
-       ") must be at least 1 memory length (" << d_max_memory <<
-       " bit" << (d_max_memory > 1 ? "s" : "") <<
-       " for this code) when doing block coding.\n";
-      assert (0);
-    }
-
-    // create the memory mask for this code generator
-
-    d_max_mem_mask = (2 << d_max_memory) - 1;
-  }
-}
-
-void
-encoder_convolutional_base::encode_private
-(const char** in_buf,
- char** out_buf)
-{
-#if DO_TIME_THOUGHPUT
-  struct timeval t_tp;
-  start_timer (&t_tp);
-#endif
-
-  // reset buffer indices
-
-  d_total_n_enc_bits = d_in_buf_ndx = d_out_buf_ndx =
-    d_in_bit_shift = d_out_bit_shift = 0;
-
-  if (DO_PRINT_DEBUG) {
-    std::cout << "Beginning this encode() call; starting parameters.\n";
-    std::cout << "d_n_input_bits_left = " << d_n_input_bits_left << '\n';
-    std::cout << "d_n_output_bits_left = " << d_n_output_bits_left << '\n';
-  }
-
-  // while there are inputs and outputs left to process ...
-
-  while ((d_n_input_bits_left != 0) & (d_n_output_bits_left != 0)) {
-
-    // jump to the correct state in the fsm
-
-    switch (d_fsm_state) {
-
-    case fsm_enc_conv_init:
-
-      // copy the init states to the current memory
-
-      d_memory = d_init_states;
-
-      // if not doing streaming, things to do; else nothing more do
-
-      if (d_do_streaming == false) {
-
-       // reset the number of encoded bits in this block (which is
-       // used to compare with the number of bits in the frame)
-
-       d_n_enc_bits = 0;
-      }
-
-      // move to the 'input' state
-
-      d_fsm_state = fsm_enc_conv_doing_input;
-      break;
-
-    case fsm_enc_conv_doing_input:
-
-      // working through the trellis section which requires input bits
-      // from external sources; loop up to the frame size (before
-      // termination bits, if any), counting down the number of
-      // available input bits.
-
-      encode_loop (in_buf, out_buf, &d_n_input_bits_left, d_frame_size_bits);
-
-      // finished this loop; check for jumping to the next state
-
-      if ((d_n_enc_bits == d_frame_size_bits) & (d_do_streaming == false)) {
-
-       // jump to another state, depending on termination requirement
-
-       if (d_do_termination == true) {
-         d_n_enc_bits = 0;
-         d_fsm_state = fsm_enc_conv_doing_term;
-       } else {
-         d_fsm_state = fsm_enc_conv_init;
-       }
-      }
-      break;
-
-    case fsm_enc_conv_doing_term:
-
-      // terminating the trellis, trying to get to a specific state;
-      // better get here only when do_termination is true, but check
-      // just in case; lop up to the max memory, counting down the
-      // number of output bits left
-
-      if (d_do_termination == false) {
-       encode_loop (in_buf, out_buf, &d_n_output_bits_left, d_max_memory);
-
-       // finished this loop; check for jumping to the next state
-
-       if (d_n_enc_bits == d_max_memory)
-         d_fsm_state = fsm_enc_conv_init;
-
-      } else {
-       // should never get here!
-       assert (0);
-      }
-      break;
-
-    default:
-      // better never get here!
-      assert (0);
-      break;
-
-      // done (switch) with FSM
-    }
-
-    // done (while) there are inputs and outputs
-  }
-
-  if (DO_PRINT_DEBUG) {
-    std::cout << "Done with this encode() call; ending parameters.\n"
-      "d_in_bit_shift = " << d_in_bit_shift << "\n"
-      "d_out_bit_shift = " << d_out_bit_shift << "\n"
-      "d_in_buf_ndx = " << d_in_buf_ndx << "\n"
-      "d_out_buf_ndx = " << d_out_buf_ndx << "\n"
-      "d_n_input_bits_left = " << d_n_input_bits_left << "\n"
-      "d_n_output_bits_left = " << d_n_output_bits_left << "\n"
-      "d_total_n_enc_bits = " << d_total_n_enc_bits << "\n";
-  }
-
-  if (DO_TIME_THOUGHPUT) {
-    // compute the throughput for this particular function call
-    u_long d_t = end_timer (&t_tp);
-    std::cout << "Completed " << d_total_n_enc_bits <<
-      " bits in " << d_t << " usec => " <<
-      1e6*(((double) d_total_n_enc_bits)/((double) d_t)) <<
-      " b/s\n";
-  }
-}
-
-void
-encoder_convolutional_base::encode_loop
-(const char** in_buf,
- char** out_buf,
- size_t* which_counter,
- size_t how_many)
-{
-  if (DO_PRINT_DEBUG) {
-    std::cout << "starting encode_loop.\n";
-  }
-  while (((*which_counter) > 0) & (d_n_enc_bits < how_many)) {
-    if (DO_PRINT_DEBUG) {
-      std::cout << "*w_c = " << (*which_counter) << ", "
-       "# enc_bits = " << d_n_enc_bits << " of " << how_many << ".\n"
-       "Getting new inputs.\n";
-    }
-
-    // get a new input bit per stream, and update the memory;
-    // loop over all inputs, push the current state bit into d_memory
-    // (which is pointed to by d_states, and thus both are updated).
-
-    for (size_t p = 0; p < d_n_memories; p++) {
-      if (DO_PRINT_DEBUG) {
-       std::cout << "mem_in[" << p << "] = " <<
-         n2bs (d_memory[p], d_max_memory+2) << "\n";
-      }
-
-      d_memory[p] |= get_next_bit (in_buf, d_input_num[p]);
-
-      if (DO_PRINT_DEBUG) {
-       std::cout << "mem_out[" << p << "] = " <<
-         n2bs (d_memory[p], d_max_memory+2) << "\n";
-      }
-    }
-
-    // now encode those inputs using the code generators,
-    // and output a single bit per output stream
-
-    // loop over all outputs
-
-    for (size_t q = 0; q < d_n_code_outputs; q++) {
-      memory_t t_out_result = 0;
-
-      // loop over all inputs, xor'ing the result each time
-
-      for (size_t p = 0; p < d_n_code_inputs; p++) {
-       memory_t t_c_g = d_code_generators[maio(p,q)];
-       memory_t t_mem = (*(d_states[maio(p,q)]));
-
-       if (DO_PRINT_DEBUG) {
-         std::cout << "b_i = " <<
-           n2bs (t_out_result, d_max_memory+2) <<
-           ", st[" << p << "," << q << "] = " <<
-           n2bs (t_mem, d_max_memory+2) <<
-           ", cg[" << p << "," << q << "] = " <<
-           n2bs (t_c_g, d_max_memory+2) <<
-           ", st[] & cg[] = " <<
-           n2bs (t_mem & t_c_g, d_max_memory+2);
-       }
-
-       t_out_result ^= (t_mem & t_c_g);
-
-       if (DO_PRINT_DEBUG) {
-         std::cout << ", b_o = " <<
-           n2bs (t_out_result, d_max_memory+2) << '\n';
-       }
-      }
-      if (DO_PRINT_DEBUG) {
-       std::cout << "b_r = " << n2bs (t_out_result, d_max_memory+2);
-      }
-
-      // sum the number of set bits, mod 2, for the output bit
-
-      char t_out_bit = sum_bits_mod2 (t_out_result, d_max_memory);
-
-      if (DO_PRINT_DEBUG) {
-       std::cout << "t_out_bit = mo2_sum (b_o) = " <<
-         n2bs (t_out_result, 2);
-      }
-
-      // output this particular bit on this output stream
-
-      output_bit (t_out_bit, out_buf, q);
-
-      // increment the input and output indices, if necessary, between
-      // output bits
-
-      increment_io_indices (true);
-    }
-
-    // do post-encoding memory mods (e.g. feedback); at a minimum:
-    // must shift memory to get ready for a new input bit, and mask
-    // off any extra bit from shifting (beyond a particular input's
-    // memory bits).
-
-    update_memory_post_encode ();
-
-    // increment the input and output counters, if necessary, between
-    // input bits
-
-    increment_io_indices (false);
-
-    // increment the number of encoded bits for the current block, and
-    // the total number of bits for this running of "encode()"
-
-    d_n_enc_bits++;
-    d_total_n_enc_bits++;
-
-    // decrement the number of input and output bits left
-
-    d_n_input_bits_left--;
-    d_n_output_bits_left--;
-  }
-
-  if (DO_PRINT_DEBUG) {
-    std::cout << "ending encode_loop.\n";
-  }
-}
-
-void
-encoder_convolutional_base::update_memory_post_encode
-()
-{
-  if (DO_PRINT_DEBUG) {
-    std::cout << "starting update_memory_post_encode.\n";
-  }
-
-  // update memory with any feedback, then shift up (left) by 1 bit
-  // and mask the memory state to be ready for the next input
-
-  // loop over all memories, shift the memory left (up) by 1 bit and
-  // mask off any high non-memory bit(s)
-
-  if (DO_PRINT_DEBUG) {
-    std::cout << "  doing memory shift and mask:\n";
-  }
-
-  for (size_t p = 0; p < d_n_memories; p++) {
-    if (DO_PRINT_DEBUG) {
-      std::cout << "    mem_in[" << p << "] = " <<
-       n2bs (d_memory[p], d_max_memory+2) << "\n";
-    }
-
-    d_memory[p] = (d_memory[p] << 1) & d_max_mem_mask;
-
-    if (DO_PRINT_DEBUG) {
-      std::cout << "    mem_out[" << p << "] = " <<
-       n2bs (d_memory[p], d_max_memory+2) << "\n";
-    }
-  }
-
-  if (d_do_feedback == true) {
-
-    if (DO_PRINT_DEBUG) {
-      std::cout << "  doing feedback:\n";
-    }
-
-    // loop over all unique memories, creating the feedback bit for each
-    // and placing those bits in the state's second bit location
-
-    for (size_t p = 0; p < d_n_memories; p++) {
-      if (DO_PRINT_DEBUG) {
-       std::cout << "    mem_in[" << p << "] = " <<
-         n2bs (d_memory[p], d_max_memory+2) << "\n";
-      }
-
-      // do feedback with current memory
-      // get the memory, and zero out the second bit
-
-      memory_t t_state = d_memory[p] & (d_max_mem_mask ^ 2);
-
-      if (DO_PRINT_DEBUG) {
-       std::cout << "    t_state = mem[] & (" << d_max_mem_mask <<
-         " xor 2) = " << n2bs (t_state, d_max_memory+2) << "\n";
-      }
-
-      // create the code feedback state
-
-      memory_t t_fb_state = t_state & (d_code_feedback[p]);
-
-      if (DO_PRINT_DEBUG) {
-       std::cout << "    t_fb_state = t_state & {fb[" << p << "] == " <<
-         d_code_feedback[p] << "} = " <<
-         n2bs (t_fb_state, d_max_memory+2) << "\n";
-      }
-
-      // mod2 sum the feedback state to get the feedback bit value
-
-      char t_fb_bit = sum_bits_mod2 (t_fb_state, d_max_memory);
-
-      if (DO_PRINT_DEBUG) {
-       std::cout << "    t_fb_bit = mod2_sum (t_fb_state) = " <<
-         n2bs (t_fb_bit, 2) << "\n";
-      }
-
-      // place the feedback bit into the second state bit
-
-      d_memory[p] = t_state | (t_fb_bit << 1);
-
-      if (DO_PRINT_DEBUG) {
-       std::cout << "    mem_out[" << p << "] = t_state | (fb_bit << 1) = " <<
-         n2bs (d_memory[p], d_max_memory+2) << "\n";
-      }
-    }
-  }
-
-  if (DO_PRINT_DEBUG) {
-    std::cout << "ending update_memory_post_encode.\n";
-  }
-}
-
-char
-encoder_convolutional_base::get_next_bit
-(const char** in_buf,
- size_t code_input_n)
-{
-  char ret_val = 0;
-  switch (d_fsm_state) {
-  case fsm_enc_conv_doing_input:
-    ret_val = get_next_bit__input (in_buf, code_input_n);
-    break;
-  case fsm_enc_conv_doing_term:
-    ret_val = get_next_bit__term (code_input_n);
-    break;
-  default:
-    assert (0);
-    break;
-  }
-  return (ret_val);
-}
-
-char
-encoder_convolutional_base::get_next_bit__term
-(size_t code_input_n)
-{
-  // FIXME: how to figure out which term bit to get?
-  return (d_term_states[code_input_n] & 1);
-}

Index: libecc/encoder_convolutional_base.h
===================================================================
RCS file: libecc/encoder_convolutional_base.h
diff -N libecc/encoder_convolutional_base.h
--- libecc/encoder_convolutional_base.h 4 Jul 2006 20:57:32 -0000       1.2
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,197 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006 Free Software Foundation, Inc.
- * 
- * This file is part of GNU Radio
- * 
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- * 
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING.  If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef INCLUDED_ENCODER_CONVOLUTIONAL_BASE_H
-#define INCLUDED_ENCODER_CONVOLUTIONAL_BASE_H
-
-#include <vector>
-#include "encoder.h"
-
-class encoder_convolutional_base : public encoder
-{
-public:
-/*!
- * Class encoder_convolutional_base is derived from the general
- *     encoder class.
- *
- * Encode the incoming streams using a convolutional encoder; This is
- *     a virtual base class which defines the basics of a
- *     convolutional encoder, but not how input and output bits are
- *     handled, nor feedback in the encoder.  These features are all
- *     defined by overriding methods appropriately.
- *
- * frame_size_bits: if == 0, then do streaming encoding ("infinite"
- *     trellis); otherwise this is the frame size in bits to encode
- *     before terminating the trellis.  This value -does not- include
- *     any termination bits.
- *
- * n_code_inputs:
- * n_code_outputs:
- * code_generator: vector of integers (32 bit) representing the code
- *     to be implemented.  E.g. "4" in binary is "100", which would be
- *     "D^2" for code generation.  "6" == 110b == "D^2 + D"
- *  ==> The vector is listed in order for each output stream, so if there
- *     are 2 input streams (I1, I2) [specified in "n_code_inputs"]
- *     and 2 output streams (O1, O2) [specified in "n_code_outputs"],
- *     then the vector would be the code generator for:
- *       [I1->O1, I2->O1, I1->O2, I2->O2]
- *     with each element being an integer representation of the code.
- *
- * do_termination: valid only if frame_size_bits != 0, and defines
- *     whether or not to use trellis termination.  Default is to use
- *     termination when doing block coding.
- *
- * start_memory_state: when starting a new block, the starting memory
- *     state to begin encoding; there will be a helper function to
- *     assist in creating this value for a given set of inputs;
- *     default is the "all zero" state.
- * 
- * end_memory_state: when terminating a block, the ending memory
- *     state to stop encoding; there will be a helper function to
- *     assist in creating this value for a given set of inputs;
- *     default is the "all zero" state.
- */
-
-  inline encoder_convolutional_base (int frame_size_bits,
-                                    int n_code_inputs,
-                                    int n_code_outputs,
-                                    std::vector<int> &code_generators,
-                                    bool do_termination = true,
-                                    int start_memory_state = 0,
-                                    int end_memory_state = 0)
-  {encoder_convolutional_base_init (frame_size_bits,
-                                   n_code_inputs,
-                                   n_code_outputs,
-                                   code_generators,
-                                   do_termination,
-                                   start_memory_state,
-                                   end_memory_state);};
-
-/*
- * Base encoder with feedback.
- *
- * code_feedback: vector of integers (32 bit) representing the code
- *     feedback to be implemented (same as for the
- *     code_generator).  For this feedback type, the LSB ("& 1") must
- *     be equal to 1 ... the represents the input bit for the given
- *     encoder, without which there would be no encoding!  Each
- *     successive higher-order bit represents the output of that
- *     delay block; for example "6" == 110b == "D^2 + D" means use
- *     the current input bit + the output of the second delay block.
- *     Listing order is the same as for the code_generator.
- */
-
-  encoder_convolutional_base (int frame_size_bits,
-                             int n_code_inputs,
-                             int n_code_outputs,
-                             std::vector<int> &code_generators,
-                             std::vector<int> &code_feedback,
-                             bool do_termination = true,
-                             int start_memory_state = 0,
-                             int end_memory_state = 0);
-
-  virtual ~encoder_convolutional_base () {};
-
-protected:
-/*
- * fsm_enc_conv_t: finite state machine for the convolutional encoder;
- *     output happens all the time, so that's built-in to each state.
- *
- * fsm_enc_conv_init: initialize for a new frame / block; this is already
- *     done at instantiation, so do it only at the end of a block.
- *
- * fsm_enc_conv_doing_input: doing encoding inside the trellis
- *
- * fsm_enc_conv_doing_term: termination trellis, if requested
- */
-
-  enum fsm_enc_conv_t {
-    fsm_enc_conv_init, fsm_enc_conv_doing_input, fsm_enc_conv_doing_term
-  };
-
-/*
- * maio(i,o): matrix access into a vector, knowing the # of code
- *     outputs (from inside the class). References into a vector with
- *     code inputs ordered by code output.
- *
- * 'i' is the first dimension - immediate memory order first - the code input
- * 'o' is the second dimension - slower memory order second - the code output
- *
- * returns ((o*n_code_outputs) + i)
- */
-
-  inline size_t maio(size_t i, size_t o) {return ((o*d_n_code_outputs) + i);};
-
-/*
- * maoi(i,o): matrix access into a vector, knowing the # of code
- *     inputs (from inside the class). References into a vector with
- *     code outputs ordered by code input.
- *
- * 'o' is the first dimension - immediate memory order first - the code output
- * 'i' is the second dimension - slower memory order second - the code input
- *
- * returns ((i*n_code_inputs) + o)
- */
-
-  inline size_t maoi(size_t i, size_t o) {return ((i*d_n_code_inputs) + o);};
-
-  // methods defined in this class
-
-  void encoder_convolutional_base_init (int frame_size_bits,
-                                       int n_code_inputs,
-                                       int n_code_outputs,
-                                       std::vector<int> &code_generators,
-                                       bool do_termination,
-                                       int start_memory_state,
-                                       int end_memory_state);
-  virtual void encode_private (const char** in_buf, char** out_buf);
-  virtual void encode_loop (const char** in_buf, char** out_buf,
-                           size_t* which_counter, size_t how_many);
-  virtual char get_next_bit (const char** in_buf, size_t code_input_n);
-  virtual char get_next_bit__term (size_t code_input_n);
-  virtual void update_memory_post_encode ();
-
-  // methods which are required by classes which inherit from this
-  // one; primarily just the parts which deal with getting input bits
-  // and writing output bits, changing the indices for those buffers.
-
-  virtual char get_next_bit__input (const char** in_buf,
-                                   size_t code_input_n) = 0;
-  virtual void increment_io_indices (bool while_encoding) = 0;
-
-  // variables
-
-  fsm_enc_conv_t d_fsm_state;
-  bool d_do_streaming, d_do_termination, d_do_feedback;
-  size_t d_n_memories;
-
-  // code generators and feedback are stored internally in "maXY(i,o)"
-  // order this allows for looping over all a single output and
-  // computing all input parts sequentially.
-
-  std::vector<memory_t> d_code_generators, d_code_feedback;
-  std::vector<memory_ptr_t> d_states;
-  std::vector<memory_t> d_memory, d_init_states, d_term_states;
-  std::vector<size_t> d_input_num;
-};
-
-#endif /* INCLUDED_ENCODER_CONVOLUTIONAL_BASE_H */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]