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 l...


From: Michael Dickens
Subject: [Commit-gnuradio] gr-error-correcting-codes/src lib/Makefile.am l...
Date: Sun, 09 Jul 2006 16:15:18 +0000

CVSROOT:        /sources/gnuradio
Module name:    gr-error-correcting-codes
Changes by:     Michael Dickens <michaelld>     06/07/09 16:15:17

Modified files:
        src/lib        : Makefile.am ecc.i 
                         gr_streams_encode_convolutional.cc 
                         gr_streams_encode_convolutional.h 
                         gr_streams_encode_convolutional.i qa_ecc.py 
        src/lib/libecc : Makefile.am decoder.cc decoder.h 
                         decoder_viterbi.cc decoder_viterbi.h encoder.cc 
                         encoder.h encoder_convolutional.cc 
                         encoder_convolutional.h 
                         encoder_convolutional_ic1_ic1.cc 
                         encoder_convolutional_ic1_ic1.h 
                         encoder_convolutional_ic8_ic8.h 
Added files:
        src/lib        : gr_metrics_decode_viterbi_full_block.cc 
                         gr_metrics_decode_viterbi_full_block.h 
                         gr_metrics_decode_viterbi_full_block.i 
                         gr_streams_encode_turbo.cc 
                         gr_streams_encode_turbo.h 
                         gr_streams_encode_turbo.i 
        src/lib/libecc : decoder_viterbi_full_block.cc 
                         decoder_viterbi_full_block.h 
                         decoder_viterbi_full_block_i1_ic1.cc 
                         decoder_viterbi_full_block_i1_ic1.h 
                         encoder_turbo.cc encoder_turbo.h 
        src/python     : qa_test_encoder_convolutional_1.py 
Removed 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_viterbi_block_full.cc 
                         decoder_viterbi_block_full.h 
                         decoder_viterbi_block_full_ic1.h 

Log message:
        Renamed viterbi decoder to better represent distinguishing qualities
        ... "full" (will be versus "partial"; "block" is redundant, but work
        well since the second part of "partial" will be "block" or "stream").
        Corrected .i and .am files accordingly.
        
        Added starting codes for turbo encoder, primarily to test out passing
        std::vector<gr_block_sptr> from Python into C++.
        
        Messed with libecc files to get (most of) it to compile.  Still some
        work there, but making progress.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/Makefile.am?cvsroot=gnuradio&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/ecc.i?cvsroot=gnuradio&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.cc?cvsroot=gnuradio&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.h?cvsroot=gnuradio&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.i?cvsroot=gnuradio&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/qa_ecc.py?cvsroot=gnuradio&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.cc?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.h?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.i?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.cc?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.h?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.i?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/gr_decoder_viterbi_block_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_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_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.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/decoder.cc?cvsroot=gnuradio&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/decoder.h?cvsroot=gnuradio&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.cc?cvsroot=gnuradio&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.h?cvsroot=gnuradio&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder.cc?cvsroot=gnuradio&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder.h?cvsroot=gnuradio&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.cc?cvsroot=gnuradio&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.h?cvsroot=gnuradio&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.cc?cvsroot=gnuradio&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.h?cvsroot=gnuradio&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic8_ic8.h?cvsroot=gnuradio&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.cc?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.h?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block_i1_ic1.cc?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block_i1_ic1.h?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder_turbo.cc?cvsroot=gnuradio&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder_turbo.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&r1=1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_block_full.h?cvsroot=gnuradio&r1=1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_block_full_ic1.h?cvsroot=gnuradio&r1=1.1&r2=0
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/python/qa_test_encoder_convolutional_1.py?cvsroot=gnuradio&rev=1.1

Patches:
Index: lib/Makefile.am
===================================================================
RCS file: /sources/gnuradio/gr-error-correcting-codes/src/lib/Makefile.am,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- lib/Makefile.am     5 Jul 2006 17:49:58 -0000       1.2
+++ lib/Makefile.am     9 Jul 2006 16:15:17 -0000       1.3
@@ -44,8 +44,9 @@
 
 LOCAL_IFILES =                                         \
        gr_syms_to_metrics.i                    \
-       gr_decoder_viterbi_block_full.i         \
+       gr_metrics_decode_viterbi_full_block.i          \
        gr_streams_encode_convolutional.i       \
+       gr_streams_encode_turbo.i                       \
        ecc.i
 
 # These files are built by SWIG.  The first is the C++ glue.
@@ -66,8 +67,9 @@
 # These are the source files that go into the shared library
 _ecc_la_SOURCES =              \
        gr_syms_to_metrics.cc                   \
-       gr_decoder_viterbi_block_full.cc        \
+       gr_metrics_decode_viterbi_full_block.cc         \
        gr_streams_encode_convolutional.cc      \
+       gr_streams_encode_turbo.cc                      \
        ecc.cc
 
 # magic flags
@@ -85,8 +87,9 @@
 # These headers get installed in ${prefix}/include/gnuradio
 grinclude_HEADERS =                            \
        gr_syms_to_metrics.h                    \
-       gr_decoder_viterbi_block_full.h         \
-       gr_streams_encode_convolutional.h
+       gr_metrics_decode_viterbi_full_block.h          \
+       gr_streams_encode_convolutional.h               \
+       gr_streams_encode_turbo.h
 
 # These swig headers get installed in ${prefix}/include/gnuradio/swig
 swiginclude_HEADERS = $(LOCAL_IFILES)

Index: lib/ecc.i
===================================================================
RCS file: /sources/gnuradio/gr-error-correcting-codes/src/lib/ecc.i,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- lib/ecc.i   5 Jul 2006 17:49:58 -0000       1.2
+++ lib/ecc.i   9 Jul 2006 16:15:17 -0000       1.3
@@ -28,12 +28,35 @@
 
 #include "gnuradio_swig_bug_workaround.h"      // mandatory bug fix
 #include <gr_streams_encode_convolutional.h>
-#include <gr_decoder_viterbi_block_full.h>
+#include <gr_streams_encode_turbo.h>
+#include <gr_metrics_decode_viterbi_full_block.h>
 #include <gr_syms_to_metrics.h>
 #include <stdexcept>
 
 %}
 
+// same as "GR_SWIG_BLOCK_MAGIC_HELPER" except w/o the
+// "class NAME" & "typedef" statements.
+
+%define LOCAL_GR_SWIG_BLOCK_MAGIC_HELPER(PKG, NAME, BASE_NAME)
+%template(NAME ## _sptr) boost::shared_ptr<NAME>;
+%rename(BASE_NAME) PKG ## _make_ ## BASE_NAME;
+%inline {
+  gr_block_sptr NAME ## _block (NAME ## _sptr r)
+  {
+    return gr_block_sptr (r);
+  }
+}
+
+%pythoncode %{
+NAME ## _sptr.block = lambda self: NAME ## _block (self)
+NAME ## _sptr.__repr__ = lambda self: "<gr_block %s (%d)>" % (self.name(), 
self.unique_id ())
+%}
+
+%ignore NAME;
+%enddef
+
 %include "gr_streams_encode_convolutional.i"
-%include "gr_decoder_viterbi_block_full.i"
+%include "gr_streams_encode_turbo.i"
+%include "gr_metrics_decode_viterbi_full_block.i"
 %include "gr_syms_to_metrics.i"

Index: lib/gr_streams_encode_convolutional.cc
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.cc,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- lib/gr_streams_encode_convolutional.cc      3 Jul 2006 02:12:53 -0000       
1.1
+++ lib/gr_streams_encode_convolutional.cc      9 Jul 2006 16:15:17 -0000       
1.2
@@ -2,7 +2,7 @@
 /*
  * Copyright 2006 Free Software Foundation, Inc.
  * 
- * This file is part of GNU Radio.
+ * 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
@@ -30,10 +30,11 @@
 #include <iostream>
 
 gr_streams_encode_convolutional_sptr 
-gr_make_streams_encode_convolutional (int frame_size_bits,
+gr_make_streams_encode_convolutional
+(int frame_size_bits,
                                      int n_code_inputs,
                                      int n_code_outputs,
-                                     std::vector<int> &code_generator,
+ const std::vector<int> &code_generator,
                                      bool do_termination,
                                      int start_memory_state,
                                      int end_memory_state)
@@ -48,11 +49,33 @@
                                          end_memory_state));
 }
 
+gr_streams_encode_convolutional_feedback_sptr 
+gr_make_streams_encode_convolutional_feedback
+(int frame_size_bits,
+ int n_code_inputs,
+ int n_code_outputs,
+ const std::vector<int> &code_generator,
+ const std::vector<int> &code_feedback,
+ bool do_termination,
+ int start_memory_state,
+ int end_memory_state)
+{
+  return gr_streams_encode_convolutional_feedback_sptr
+    (new gr_streams_encode_convolutional (frame_size_bits,
+                                         n_code_inputs,
+                                         n_code_outputs,
+                                         code_generator,
+                                         code_feedback,
+                                         do_termination,
+                                         start_memory_state,
+                                         end_memory_state));
+}
+
 gr_streams_encode_convolutional::gr_streams_encode_convolutional
 (int frame_size_bits,
  int n_code_inputs,
  int n_code_outputs,
- std::vector<int> &code_generators,
+ const std::vector<int> &code_generators,
  bool do_termination,
  int start_memory_state,
  int end_memory_state)
@@ -60,10 +83,10 @@
              gr_make_io_signature (0, 0, 0),
              gr_make_io_signature (0, 0, 0))
 {
-// error checking is done by the encoder class itself;
-// just pass items on here.
+  // error checking is done by the encoder class itself;
+  // just pass items on here.
 
-  d_encoder = new encoder_convolutional (frame_size_bits,
+  d_encoder = new encoder_convolutional_ic1_ic1 (frame_size_bits,
                                         n_code_inputs,
                                         n_code_outputs,
                                         code_generators,
@@ -71,24 +94,63 @@
                                         start_memory_state,
                                         end_memory_state);
 
-// create the correct input signature; 1 bit per input char
+  setup_io_signatures (n_code_inputs, n_code_outputs);
+}
+
+gr_streams_encode_convolutional::gr_streams_encode_convolutional
+(int frame_size_bits,
+ int n_code_inputs,
+ int n_code_outputs,
+ const std::vector<int> &code_generators,
+ const std::vector<int> &code_feedback,
+ bool do_termination,
+ int start_memory_state,
+ int end_memory_state)
+  : gr_block ("streams_encode_convolutional_feedback",
+             gr_make_io_signature (0, 0, 0),
+             gr_make_io_signature (0, 0, 0))
+{
+  // error checking is done by the encoder class itself;
+  // just pass items on here.
+
+  d_encoder = new encoder_convolutional_ic1_ic1 (frame_size_bits,
+                                                n_code_inputs,
+                                                n_code_outputs,
+                                                code_generators,
+                                                code_feedback,
+                                                do_termination,
+                                                start_memory_state,
+                                                end_memory_state);
+
+  setup_io_signatures (n_code_inputs, n_code_outputs);
+}
+
+void
+gr_streams_encode_convolutional::setup_io_signatures
+(int n_code_inputs,
+ int n_code_outputs)
+{
+  // create the correct input signature; 1 bit per input char
+
   set_input_signature (gr_make_io_signature (n_code_inputs,
                                             n_code_inputs,
                                             sizeof (char)));
 
-// create the correct output signature; 1 bit per output char
+  // create the correct output signature; 1 bit per output char
+
   set_output_signature (gr_make_io_signature (n_code_outputs,
                                              n_code_outputs,
                                              sizeof (char)));
 
-// set the output multiple to 1 item, handle the rest internally
+// set the output multiple to 1 item, then let the encoder class
+// handle the rest internally
+
   set_output_multiple (1);
 }
 
 gr_streams_encode_convolutional::~gr_streams_encode_convolutional
 ()
 {
-  if (d_encoder)
     delete d_encoder;
 }
 
@@ -114,7 +176,8 @@
  gr_vector_int &ninput_items_required)
 {
   int ninput_items = d_encoder->compute_n_input_bits (noutput_items);
-  for (int n = ninput_items_required.size() - 1; n >= 0; n--)
+  size_t ninputs = ninput_items_required.size();
+  for (size_t n = 0; n < ninputs; n++)
     ninput_items_required[n] = ninput_items;
 }
 
@@ -125,13 +188,25 @@
  gr_vector_const_void_star &input_items,
  gr_vector_void_star &output_items)
 {
-  size_t t_n_input_items = d_encoder->encode ((const char 
**)(&input_items[0]), 
+  // FIXME: compute the actual number of output items (1 bit char's) created.
+
+  size_t t_n_input_items = d_encoder->compute_n_input_bits (noutput_items);
+  size_t t_n_output_items = d_encoder->compute_n_output_bits (t_n_input_items);
+
+  assert (t_n_output_items == ((size_t)noutput_items));
+
+  // "work" is handled by the encoder; which returns the actual number
+  // of input items (1-bit char's) used.
+
+  t_n_input_items = d_encoder->encode ((const char **)(&input_items[0]), 
                                             (char **)(&output_items[0]),
                                             (size_t) noutput_items);
 
-// consume the number of used input items on all input streams
+  // consume the number of used input items on all input streams
+
   consume_each (t_n_input_items);
 
-// returns number of items written to each output stream
+  // returns number of items written to each output stream
+
   return (noutput_items);
 }

Index: lib/gr_streams_encode_convolutional.h
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- lib/gr_streams_encode_convolutional.h       3 Jul 2006 02:12:53 -0000       
1.1
+++ lib/gr_streams_encode_convolutional.h       9 Jul 2006 16:15:17 -0000       
1.2
@@ -2,7 +2,7 @@
 /*
  * Copyright 2006 Free Software Foundation, Inc.
  * 
- * This file is part of GNU Radio.
+ * 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
@@ -24,21 +24,7 @@
 #define INCLUDED_GR_STREAMS_ENCODE_CONVOLUTIONAL_H
 
 #include <gr_block.h>
-#include <vector>
-#include <libecc/encoder_convolutional.h>
-#include <sys/types.h>
-
-class gr_streams_encode_convolutional;
-typedef boost::shared_ptr<gr_streams_encode_convolutional> 
gr_streams_encode_convolutional_sptr;
-
-gr_streams_encode_convolutional_sptr gr_make_streams_encode_convolutional
-(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);
+#include <libecc/encoder_convolutional_ic1_ic1.h>
 
 /*!
  * \brief Encode the incoming streams using a convolutional encoder
@@ -50,19 +36,7 @@
  * 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 gr_streams_encode_convolutional : public gr_block
-{
-  friend gr_streams_encode_convolutional_sptr
-  gr_make_streams_encode_convolutional (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);
-/*
+ *
  * 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
@@ -71,14 +45,14 @@
  * 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
+ *     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, I1->O2, I2->O1, I2->O2]
- *     with each element being the octal representation of the code.
+ *       [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
@@ -95,19 +69,82 @@
  *     default is the "all zero" state.
  */
 
-  gr_streams_encode_convolutional (int frame_size_bits,
+class gr_streams_encode_convolutional;
+
+typedef boost::shared_ptr<gr_streams_encode_convolutional>
+gr_streams_encode_convolutional_sptr,
+  gr_streams_encode_convolutional_feedback_sptr;
+
+gr_streams_encode_convolutional_sptr
+gr_make_streams_encode_convolutional
+(int frame_size_bits,
                                   int n_code_inputs,
                                   int n_code_outputs,
-                                  std::vector<int> &code_generator,
+ const std::vector<int> &code_generator,
                                   bool do_termination = true,
                                   int start_memory_state = 0,
                                   int end_memory_state = 0);
 
-  encoder_convolutional* d_encoder;
+gr_streams_encode_convolutional_feedback_sptr
+gr_make_streams_encode_convolutional_feedback
+(int frame_size_bits,
+ int n_code_inputs,
+ int n_code_outputs,
+ const std::vector<int> &code_generator,
+ const std::vector<int> &code_feedback,
+ bool do_termination = true,
+ int start_memory_state = 0,
+ int end_memory_state = 0);
+
+class gr_streams_encode_convolutional : public gr_block
+{
+  friend gr_streams_encode_convolutional_sptr
+  gr_make_streams_encode_convolutional
+  (int frame_size_bits,
+   int n_code_inputs,
+   int n_code_outputs,
+   const std::vector<int> &code_generator,
+   bool do_termination,
+   int start_memory_state,
+   int end_memory_state);
+
+  friend gr_streams_encode_convolutional_feedback_sptr
+  gr_make_streams_encode_convolutional_feedback
+  (int frame_size_bits,
+   int n_code_inputs,
+   int n_code_outputs,
+   const std::vector<int> &code_generator,
+   const std::vector<int> &code_feedback,
+   bool do_termination,
+   int start_memory_state,
+   int end_memory_state);
+
+  gr_streams_encode_convolutional (int frame_size_bits,
+                                  int n_code_inputs,
+                                  int n_code_outputs,
+                                  const std::vector<int> &code_generator,
+                                  bool do_termination,
+                                  int start_memory_state,
+                                  int end_memory_state);
+
+  gr_streams_encode_convolutional (int frame_size_bits,
+                                  int n_code_inputs,
+                                  int n_code_outputs,
+                                  const std::vector<int> &code_generator,
+                                  const std::vector<int> &code_feedback,
+                                  bool do_termination,
+                                  int start_memory_state,
+                                  int end_memory_state);
+
+  void setup_io_signatures (int n_code_inputs, int n_code_outputs);
+
+  encoder_convolutional_ic1_ic1* d_encoder;
 
 public:
   ~gr_streams_encode_convolutional ();
 
+  inline encoder_convolutional_ic1_ic1* encoder () {return (d_encoder);};
+
   virtual void forecast (int noutput_items,
                         gr_vector_int &ninput_items_required);
 

Index: lib/gr_streams_encode_convolutional.i
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.i,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- lib/gr_streams_encode_convolutional.i       3 Jul 2006 02:12:53 -0000       
1.1
+++ lib/gr_streams_encode_convolutional.i       9 Jul 2006 16:15:17 -0000       
1.2
@@ -22,21 +22,59 @@
 
 GR_SWIG_BLOCK_MAGIC(gr,streams_encode_convolutional);
 
+// corrected "class NAME" statement, which uses slightly different NAMEs
+
+typedef boost::shared_ptr<gr_streams_encode_convolutional>
+gr_streams_encode_convolutional_feedback_sptr;
+
+LOCAL_GR_SWIG_BLOCK_MAGIC(gr,streams_encode_convolutional_feedback);
+
+// support vectors of these ... for use in the convolutional decoder
+// as well as Turbo Codes (both encoder and decoder).
+
+namespace std {
+  %template(x_vector_gr_streams_encode_convolutional_sptr) 
vector<gr_streams_encode_convolutional_sptr>;
+};
+
 gr_streams_encode_convolutional_sptr
-gr_make_streams_encode_convolutional (int frame_size_bits,
+gr_make_streams_encode_convolutional
+(int block_size_bits,
+ int n_code_inputs,
+ int n_code_outputs,
+ const std::vector<int> &code_generator,
+ bool do_termination = true,
+ int start_memory_state = 0,
+ int end_memory_state = 0);
+
+gr_streams_encode_convolutional_feedback_sptr
+gr_make_streams_encode_convolutional_feedback
+(int block_size_bits,
+ int n_code_inputs,
+ int n_code_outputs,
+ const std::vector<int> &code_generator,
+ const std::vector<int> &code_feedback,
+ bool do_termination = true,
+ int start_memory_state = 0,
+ int end_memory_state = 0);
+
+class gr_streams_encode_convolutional : public gr_block
+{
+private:
+  gr_streams_encode_convolutional
+  (int block_size_bits,
                                      int n_code_inputs,
                                      int n_code_outputs,
-                                     std::vector<int> &code_generator,
+   const std::vector<int> &code_generator,
                                      bool do_termination,
                                      int start_memory_state,
                                      int end_memory_state);
 
-class gr_streams_encode_convolutional : public gr_block
-{
-  gr_streams_encode_convolutional (int frame_size_bits,
+  gr_streams_encode_convolutional
+  (int block_size_bits,
                                   int n_code_inputs,
                                   int n_code_outputs,
-                                  std::vector<int> &code_generator,
+   const std::vector<int> &code_generator,
+   const std::vector<int> &code_feedback,
                                   bool do_termination,
                                   int start_memory_state,
                                   int end_memory_state);

Index: lib/qa_ecc.py
===================================================================
RCS file: /sources/gnuradio/gr-error-correcting-codes/src/lib/qa_ecc.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- lib/qa_ecc.py       3 Jul 2006 02:12:53 -0000       1.1
+++ lib/qa_ecc.py       9 Jul 2006 16:15:17 -0000       1.2
@@ -22,7 +22,7 @@
 
 from gnuradio import gr, gr_unittest, ecc
 
-class qa_error-correcting-codes (gr_unittest.TestCase):
+class qa_ecc (gr_unittest.TestCase):
 
     def setUp (self):
         self.fg = gr.flow_graph ()

Index: lib/libecc/Makefile.am
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/lib/libecc/Makefile.am,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- lib/libecc/Makefile.am      5 Jul 2006 17:49:58 -0000       1.4
+++ lib/libecc/Makefile.am      9 Jul 2006 16:15:17 -0000       1.5
@@ -31,16 +31,19 @@
        encoder.cc code_metrics.cc              \
        encoder_convolutional.cc                \
        encoder_convolutional_ic1_ic1.cc        \
+       encoder_turbo.cc                        \
        decoder.cc decoder_viterbi.cc           \
-       decoder_viterbi_block_full.cc
+       decoder_viterbi_block_full.cc           \
+       decoder_viterbi_block_full_i1_ic1.cc
 
 noinst_HEADERS =                               \
        encoder.h code_metrics.h                \
        encoder_convolutional.h                 \
        encoder_convolutional_ic1_ic1.h         \
+       encoder_turbo.h                         \
        decoder.h decoder_viterbi.h             \
        decoder_viterbi_block_full.h            \
-       decoder_viterbi_block_full_ic1.h
+       decoder_viterbi_block_full_i1_ic1.h
 
 # link the library against the c++ standard library
 libecc_la_LIBADD =             \

Index: lib/libecc/decoder.cc
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/lib/libecc/decoder.cc,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- lib/libecc/decoder.cc       5 Jul 2006 17:49:58 -0000       1.1
+++ lib/libecc/decoder.cc       9 Jul 2006 16:15:17 -0000       1.2
@@ -34,71 +34,84 @@
 #include <mld/n2bs.h>
 #endif
 
+/*
+ * decode a certain number of output bits
+ *
+ * the 'in_buf' and 'out_buf' must have enough memory to handle the
+ *     number of input metrics and output bits; no error checking is done!
+ *
+ * n_bits_to_output: the number of bits per output stream to output.
+ *
+ * returns the actual number of metrics used per input stream.
+ */
+
 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);
+  // set the class-internal number of input metrics
+  // and output bits left to decode
+
+  size_t saved_n_input_metrics;
+  saved_n_input_metrics = d_n_input_metrics_left =
+    compute_n_input_metrics (n_bits_to_output);
   d_n_output_bits_left = n_bits_to_output;
 
-// call the private decode function
+  // 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 = " <<
+  if (DO_PRINT_DEBUG) {
+    std::cout << "n_input_metrics_used = " <<
+      (saved_n_input_metrics - d_n_input_metrics_left) << "\n"
+      "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 metrics used
 
-// return the actual number of input bits used
-  return (saved_n_input_bits - d_n_input_bits_left);
+  return (saved_n_input_metrics - d_n_input_metrics_left);
 }
 
 /*
- * decode a certain number of input bits
+ * decode a certain number of input metrics
  *
  * the 'in_buf' and 'out_buf' must have enough memory to handle the
- * number of input and output bits; no error checking is done!
+ *     number of input metrics and output bits; no error checking is done!
  *
- * n_bits_to_input: is the number of input bits per input stream to decode
+ * n_metrics_to_input: the number of metrics per input stream to decode
  *
- * returns the number of actual bits written to the output stream(s)
+ * returns the actual number of bits written per output stream
  */
 
 size_t
 decoder::decode
 (const char** in_buf,  
- size_t n_bits_to_input,
+ size_t n_metrics_to_input,
  char** out_buf)
 {
-// set the class-internal number of input and
-// output bits left to decode
+  // set the class-internal number of input metrics 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;
+    compute_n_output_bits (n_metrics_to_input);
+  d_n_input_metrics_left = n_metrics_to_input;
+
+  // call the private decode function
 
-// 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';
+  if (DO_PRINT_DEBUG) {
+    std::cout << "n_input_metrics_used = " <<
+      (n_metrics_to_input - d_n_input_metrics_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 output bits written
 
-// return the actual number of input bits used
   return (saved_n_output_bits - d_n_output_bits_left);
 }

Index: lib/libecc/decoder.h
===================================================================
RCS file: /sources/gnuradio/gr-error-correcting-codes/src/lib/libecc/decoder.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- lib/libecc/decoder.h        5 Jul 2006 17:49:58 -0000       1.3
+++ lib/libecc/decoder.h        9 Jul 2006 16:15:17 -0000       1.4
@@ -38,14 +38,14 @@
   decoder () {};
   virtual ~decoder () {};
 
-  virtual size_t compute_n_input_bits (size_t n_output_bits) = 0;
-  virtual size_t compute_n_output_bits (size_t n_input_bits) = 0;
+  virtual size_t compute_n_input_metrics (size_t n_output_bits) = 0;
+  virtual size_t compute_n_output_bits (size_t n_input_metrics) = 0;
   virtual size_t decode (const char** in_buf,
                         char** out_buf,
-                        size_t n_bits_to_output) = 0;
+                        size_t n_bits_to_output);
   virtual size_t decode (const char** in_buf,
-                        size_t n_bits_to_input,
-                        char** out_buf) = 0;
+                        size_t n_metrics_to_input,
+                        char** out_buf);
 
 protected:
   virtual void decode_private (const char** in_buf, char** out_buf) = 0;
@@ -53,12 +53,11 @@
   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, d_sample_precision;
-  memory_t d_max_mem_mask;
-  memory_t d_in_buf_ndx, d_out_buf_ndx;
-  memory_t d_out_bit_shift;
-  size_t d_n_input_bits_left, d_n_output_bits_left;
+  size_t d_block_size_bits, d_n_code_inputs, d_n_code_outputs;
+  size_t d_n_dec_bits;
+  size_t d_in_buf_ndx, d_out_buf_ndx;
+  size_t d_in_bit_shift, d_out_bit_shift;
+  size_t d_n_input_metrics_left, d_n_output_bits_left;
 };
 
 #endif /* INCLUDED_DECODER_H */

Index: lib/libecc/decoder_viterbi.cc
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.cc,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- lib/libecc/decoder_viterbi.cc       5 Jul 2006 17:49:58 -0000       1.1
+++ lib/libecc/decoder_viterbi.cc       9 Jul 2006 16:15:17 -0000       1.2
@@ -28,7 +28,7 @@
 #include <assert.h>
 #include <iostream>
 
-const int g_max_frame_size_bits = 10000000;
+const int g_max_block_size_bits = 10000000;
 const int g_max_num_streams = 10;
 const int g_num_bits_per_byte = 8;
 
@@ -61,13 +61,7 @@
 
 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)
+ encoder_convolutional* l_encoder)
 {
   // make sure the sample precitions makes sense
 
@@ -78,435 +72,84 @@
     assert (0);
   }
 
-  // the rest is handled by the encoder, but which encoder to use?
+  // make sure that the encoder is "valid"
 
-
-
-  // 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";
+  if (! l_encoder) {
+    std::cerr << "decoder_viterbi: Error: Encoder is a NULL pointer.\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);
-  }
+  // keep around a pointer to the encoder
 
-// 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);
-  }
+  d_encoder = l_encoder;
 
-// 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);
-  }
+  // fill the class variables
 
-// 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;
+  d_block_size_bits = d_encoder->block_size_bits ();
+  d_do_streaming = (d_block_size_bits == 0);
+  d_n_code_inputs = d_encoder->n_code_inputs ();
+  d_n_code_outputs = d_encoder->n_code_outputs ();
+  d_do_termination = d_encoder->do_termination ();
+#if 0
+  d_total_memory = d_encoder->total_memory ();
+#endif
 
-// 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 '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
 
-// 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_states = 1 << d_total_memory;
   d_n_input_combinations = 1 << d_n_code_inputs;
 
-#if DO_PRINT_DEBUG_INST_0
+  // really nothing else to do here, since this class doesn't "know"
+  // how to process streaming versus block decoding, or partial
+  // trellis versus full-trellis.  Those will be handled by
+  // sub-classes which inherit from this one.
+
+  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_block_size_bits          = " << d_block_size_bits << "\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_total_memory             = " << d_total_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
+  // always start the fsm in the "init" state
 
-// 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
+  d_fsm_state = fsm_dec_viterbi_init;
 
-// 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";
 
-// 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;
+  // get the total number of out bits per stream
 
-  std::cout << "Setting States and Connections\n";
-#endif
+  d_n_total_inputs_per_stream = d_block_size_bits;
+  if (d_do_termination == true)
+    d_n_total_inputs_per_stream += d_max_memory;
 
-// 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
+decoder_viterbi::~decoder_viterbi
 ()
 {
-// reverse over from allocation
+  // reverse over from allocation
 
   delete [] d_up_term_states_ndx[0];
   delete [] d_up_term_states_ndx[1];
 
-// delete the state's structures
+  // 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;
@@ -527,22 +170,18 @@
   }
   delete [] d_states[1];
 
-// delete the save buffer
+  // 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)
+void
+decoder_viterbi::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++) {
@@ -555,7 +194,9 @@
   }
 }
 
-void gr_decoder_viterbi_block_soft_full::zero_metrics (u_char which)
+void
+decoder_viterbi::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++) {
@@ -568,99 +209,38 @@
   }
 }
 
-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;
-}
+//FIXME 
 
-/*
- * 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)
+char
+decoder_viterbi::get_next_input
+(const char** in_buf,
+size_t code_input_n)
 {
-  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);
+  return (0);
 }
 
-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)
+void
+decoder_viterbi::decode_private
+(const char** in_buf,
+ char** out_buf)
 {
+#if 0
+
 #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_state_print_bits = d_total_memory + 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];
+  const char **in_buf = (const char **) &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;
+  int t_ninput_items = compute_n_input_metrics (noutput_items);
+  int t_noutput_bits = noutput_items;
 
 #if DO_PRINT_DEBUG_INST
   std::cout << "# output items = " << noutput_items << " (" <<
@@ -718,11 +298,11 @@
   }
 #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";
+    (d_fsm_state == fsm_dec_viterbi_init ? "init" :
+     (d_fsm_state == fsm_dec_viterbi_doing_up ? "up" :
+      (d_fsm_state == fsm_dec_viterbi_doing_middle ? "middle" :
+       (d_fsm_state == fsm_dec_viterbi_doing_term ? "term" :
+       (d_fsm_state == fsm_dec_viterbi_output ? "output" : "unknown"))))) << 
"\n";
 #endif
 
 // while there are input items to create
@@ -730,17 +310,17 @@
 #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";
+      (d_fsm_state == fsm_dec_viterbi_init ? "init" :
+       (d_fsm_state == fsm_dec_viterbi_doing_up ? "up" :
+       (d_fsm_state == fsm_dec_viterbi_doing_middle ? "middle" :
+        (d_fsm_state == fsm_dec_viterbi_doing_term ? "term" :
+         (d_fsm_state == fsm_dec_viterbi_output ? "output" : "unknown"))))) << 
"'\n";
 #endif
 // jump to the correct state in the fsm
-    switch (d_fsm) {
-    case fsm_dec_doing_up:
+    switch (d_fsm_state) {
+    case fsm_dec_viterbi_doing_up:
 #if DO_PRINT_DEBUG_FSM
-      std::cout << "Starting fsm_dec_doing_up\n";
+      std::cout << "Starting fsm_dec_viterbi_doing_up\n";
 #endif
 // set the number of up_down indices
       size_t t_n_up_down_ndx = 1 << (d_n_code_inputs *
@@ -875,25 +455,25 @@
 // 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";
+       std::cout << "Setting FSM to fsm_dec_viterbi_doing_middle\n";
 #endif
-        d_fsm = fsm_dec_doing_middle;
+        d_fsm_state = fsm_dec_viterbi_doing_middle;
       }
 #if DO_PRINT_DEBUG_FSM
-      std::cout << "Exited fsm_dec_doing_up\n";
+      std::cout << "Exited fsm_dec_viterbi_doing_up\n";
 #endif
       break;
-    case (fsm_dec_doing_middle):
+    case (fsm_dec_viterbi_doing_middle):
 #if DO_PRINT_DEBUG_FSM
-      std::cout << "Entered fsm_dec_doing_middle\n";
+      std::cout << "Entered fsm_dec_viterbi_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) &
+      while (((d_block_size_bits != 0) &
+             (d_time_count < d_block_size_bits) &
              (t_in_buf_ndx < t_ninput_items)) |
-            ((d_frame_size_bits == 0) &
+            ((d_block_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
@@ -905,7 +485,7 @@
        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_block_size_bits << "\n" <<
          "d_states_ndx = " << d_states_ndx << "\n";;
 #endif
 // loop over all current states
@@ -1025,23 +605,23 @@
         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 ((d_block_size_bits != 0) &
+          (d_time_count == d_block_size_bits)) {
 #if DO_PRINT_DEBUG_FSM
-       std::cout << "Setting FSM to fsm_dec_doing_term\n";
+       std::cout << "Setting FSM to fsm_dec_viterbi_doing_term\n";
 #endif
-        d_fsm = fsm_dec_doing_term;
+        d_fsm_state = fsm_dec_viterbi_doing_term;
       }
       break;
 #if DO_PRINT_DEBUG_FSM
-      std::cout << "Exited fsm_dec_doing_middle\n";
+      std::cout << "Exited fsm_dec_viterbi_doing_middle\n";
 #endif
-    case (fsm_dec_doing_term):
+    case (fsm_dec_viterbi_doing_term):
 #if DO_PRINT_DEBUG_FSM
-      std::cout << "Entered fsm_dec_doing_term\n";
+      std::cout << "Entered fsm_dec_viterbi_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);
+      size_t t_time_count = d_max_memory - (d_time_count - d_block_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
@@ -1178,17 +758,17 @@
 // 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";
+       std::cout << "Setting FSM to fsm_dec_viterbi_output\n";
 #endif
-       d_fsm = fsm_dec_output;
+       d_fsm_state = fsm_dec_viterbi_output;
       }
 #if DO_PRINT_DEBUG_FSM
-      std::cout << "Exited fsm_dec_doing_term\n";
+      std::cout << "Exited fsm_dec_viterbi_doing_term\n";
 #endif
       break;
-    case (fsm_dec_output):
+    case (fsm_dec_viterbi_output):
 #if DO_PRINT_DEBUG_FSM
-      std::cout << "Entered fsm_dec_output.\n";
+      std::cout << "Entered fsm_dec_viterbi_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
@@ -1197,20 +777,20 @@
 
 // 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));
+                               (d_block_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));
+                                 (d_block_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" : "") <<
+       t_out_bit_shift << "] -> " << d_block_size_bits << " bits == " <<
+       (d_block_size_bits / g_num_bits_per_byte) << " Byte" <<
+       ((d_block_size_bits / g_num_bits_per_byte) != 1 ? "s" : "") <<
+       " + " << (d_block_size_bits % g_num_bits_per_byte) << " bit" <<
+       ((d_block_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
@@ -1257,11 +837,11 @@
       }
 #if DO_PRINT_DEBUG_OUTPUT
       std::cout << "Found starting traceback ptr " << t_out_buf <<
-       "; getting all " << d_frame_size_bits << " bits per stream.\n";
+       "; getting all " << d_block_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;
+      size_t t_block_bit_ndx = d_block_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))) {
@@ -1273,7 +853,7 @@
 // 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;
+       t_block_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
@@ -1289,12 +869,12 @@
 // 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));
+       size_t t_n_out_bytes = ((d_block_size_bits / g_num_bits_per_byte) +
+                               ((d_block_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 <<
+         d_block_size_bits << " bit" <<
+         (d_block_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++)
@@ -1334,7 +914,7 @@
       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--) {
+      for (size_t n = t_block_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;
@@ -1356,16 +936,16 @@
       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";
+      std::cout << "Set FSM to fsm_dec_viterbi_init\n";
 #endif
-      d_fsm = fsm_dec_init;
+      d_fsm_state = fsm_dec_viterbi_init;
 #if DO_PRINT_DEBUG_FSM
-      std::cout << "Exited fsm_dec_output\n";
+      std::cout << "Exited fsm_dec_viterbi_output\n";
 #endif
       break;
-    case (fsm_dec_init):
+    case (fsm_dec_viterbi_init):
 #if DO_PRINT_DEBUG_FSM
-      std::cout << "Entered fsm_dec_init\n";
+      std::cout << "Entered fsm_dec_viterbi_init\n";
 #endif
 // this is called immediately (first input bit upon startup),
 // or after termination of a trellis.
@@ -1398,11 +978,11 @@
 #endif
 // set the fsm to "doing up"
 #if DO_PRINT_DEBUG_FSM
-      std::cout << "Set FSM to fsm_dec_doing_up\n";
+      std::cout << "Set FSM to fsm_dec_viterbi_doing_up\n";
 #endif
-      d_fsm = fsm_dec_doing_up;
+      d_fsm_state = fsm_dec_viterbi_doing_up;
 #if DO_PRINT_DEBUG_FSM
-      std::cout << "Exited fsm_dec_init\n";
+      std::cout << "Exited fsm_dec_viterbi_init\n";
 #endif
       break;
 // should never get here!
@@ -1415,14 +995,14 @@
 
 // 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
+// so compute this from the actual number of blocks 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" <<
+    (d_fsm_state == fsm_dec_viterbi_init ? "init" :
+     (d_fsm_state == fsm_dec_viterbi_doing_up ? "up" :
+      (d_fsm_state == fsm_dec_viterbi_doing_middle ? "middle" :
+       (d_fsm_state == fsm_dec_viterbi_doing_term ? "term" :
+       (d_fsm_state == fsm_dec_viterbi_output ? "output" : "unknown"))))) << 
"\n" <<
     "Consuming " << t_in_buf_ndx <<
     " input items on each input stream (of " << t_ninput_items << ").\n";
 #endif
@@ -1467,6 +1047,8 @@
 #endif
   }
 
+#endif
+
 #if DO_TIME_THOUGHPUT
   u_long d_t = end_timer (&t_tp);
 
@@ -1475,7 +1057,4 @@
     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: lib/libecc/decoder_viterbi.h
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- lib/libecc/decoder_viterbi.h        5 Jul 2006 17:49:58 -0000       1.1
+++ lib/libecc/decoder_viterbi.h        9 Jul 2006 16:15:17 -0000       1.2
@@ -23,9 +23,8 @@
 #ifndef INCLUDED_DECODER_VITERBI_H
 #define INCLUDED_DECODER_VITERBI_H
 
-#include <vector>
 #include "decoder.h"
-#include "encoder.h"
+#include "encoder_convolutional.h"
 
 class decoder_viterbi : public decoder
 {
@@ -49,17 +48,94 @@
  */
 
   decoder_viterbi (int sample_precision,
-                  encoder* l_encoder);
+                  encoder_convolutional* l_encoder);
 
-  virtual ~decoder_viterbi () {};
+  virtual ~decoder_viterbi ();
 
 protected:
+  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:
+ *
+ * memory_t v: the value from which to retrieve the given state
+ * size_t i: for which input stream (0 to #I-1)
+ * size_t k: the number of memory slots per input (e.g. 1+D^2 -> 2)
+ */
+
+  inline memory_t state_get_from (memory_t v,
+                                 size_t i,
+                                 size_t k)
+  {return (((v)>>((i)*(k)))&((1<<(k))-1));};
+
 /*
- * fsm_dec_viterbi_t: finite state machine for the convolutional decoder;
- *     output happens all the time, so that's built-in to each state.
+ * state_add_to(s,v,i,k): use to create a given bit-memory state,
+ *     from the inputs:
  *
- * 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.
+ * memory_t s: the state value to modify
+ * memory_t v: value to set the state to for this input
+ * size_t i: for which input stream (0 to #I-1)
+ * size_t k: the number of memory slots per input (e.g. 1+D^2 -> 2)
+ */
+
+  inline void state_add_to (memory_t s,
+                           memory_t v,
+                           size_t i,
+                           size_t k)
+  {(s)|=(((v)&((1<<(k))-1))<<((i)*(k)));};
+
+/*
+ * fsm_dec_viterbi_t: finite state machine for the Viterbi decoder
+ *
+ * fsm_dec_viterbi_init: initialize for a new block / 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
  *
@@ -74,39 +150,40 @@
   };
 
   virtual void decode_private (const char** in_buf, char** out_buf);
+  virtual char get_next_input (const char** in_buf, size_t code_input_n);
+#if 0
   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);
+                                     size_t code_input_n) = 0;
   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;
+                                         size_t code_input_n) = 0;
+  virtual char get_next_input__term (size_t code_input_n) = 0;
+#endif
+  virtual void increment_input_indices (bool while_decoding) = 0;
+  virtual void increment_output_indices (bool while_decoding) = 0;
+  virtual void update_traceback__up (size_t from_state_ndx,
+                                    size_t to_state_ndx,
+                                    size_t l_input) = 0;
+  virtual void update_traceback__middle () = 0;
+  virtual void update_traceback__term () = 0;
 
   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;
+  encoder_convolutional* d_encoder;
+  fsm_dec_viterbi_t d_fsm_state;
+  size_t d_max_memory, d_total_memory;
+  size_t d_time_count, d_n_total_inputs_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;
+  bool d_do_streaming, d_do_termination;
+  std::vector<memory_t> d_init_states, d_term_states;
   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: lib/libecc/encoder.cc
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/lib/libecc/encoder.cc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- lib/libecc/encoder.cc       4 Jul 2006 20:57:32 -0000       1.2
+++ lib/libecc/encoder.cc       9 Jul 2006 16:15:17 -0000       1.3
@@ -38,17 +38,17 @@
 #include <mld/n2bs.h>
 #endif
 
-// sum the number of set bits, mod 2, for the output bit
 char
 encoder::sum_bits_mod2
 (memory_t in_mem,
  size_t max_memory)
 {
-// there are faster ways to do this, but this works for now; could
-// certainly do a single inline asm, which most processors provide to
-// deal with summing the bits in an integer
+  // sum the number of set bits, mod 2, for the output bit
 
-// this routine can be overridden by another method if desired.
+  // there are faster ways to do this, but this works for now; could
+  // certainly do a single inline asm, which most processors provide
+  // to deal with summing the bits in an integer.
+  // this routine can be overridden by another method if desired.
 
   char t_out_bit = (char)(in_mem & 1);
   for (size_t r = max_memory; r > 0; r--) {
@@ -58,32 +58,44 @@
   return (t_out_bit);
 }
 
+/*
+ * encode a certain number of output 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_output: the number of bits per output stream to encode
+ *
+ * returns the actual number of bits used per input stream
+ */
+
 size_t
 encoder::encode
 (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 encode
+  // set the class-internal number of input bits and
+  // output bits left to encode
+
   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 encode function
+  // call the private encode function
+
   encode_private (in_buf, out_buf);
 
-#ifdef DO_PRINT_DEBUG
+  if (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 the actual number of input bits used
   return (saved_n_input_bits - d_n_input_bits_left);
 }
 
@@ -93,9 +105,9 @@
  * 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 encode
+ * n_bits_to_input: the number of bits per input stream to encode
  *
- * returns the number of actual bits written to the output stream(s)
+ * returns the actual number of bits written per output stream
  */
 
 size_t
@@ -104,25 +116,26 @@
  size_t n_bits_to_input,
  char** out_buf)
 {
-// set the class-internal number of input and
-// output bits left to encode
+  // set the class-internal number of input and
+  // output bits left to encode
+
   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 encode function
+  // call the private encode function
+
   encode_private (in_buf, out_buf);
 
-#ifdef DO_PRINT_DEBUG
+  if (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 output bits written
 
-// return the actual number of input bits used
   return (saved_n_output_bits - d_n_output_bits_left);
 }

Index: lib/libecc/encoder.h
===================================================================
RCS file: /sources/gnuradio/gr-error-correcting-codes/src/lib/libecc/encoder.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- lib/libecc/encoder.h        4 Jul 2006 20:57:32 -0000       1.3
+++ lib/libecc/encoder.h        9 Jul 2006 16:15:17 -0000       1.4
@@ -48,17 +48,22 @@
                         char** out_buf);
   virtual char sum_bits_mod2 (memory_t in_mem, size_t max_memory);
 
+/* for remote access to internal info */
+
+  inline size_t block_size_bits () {return (d_block_size_bits);};
+  inline size_t n_code_inputs () {return (d_n_code_inputs);};
+  inline size_t n_code_outputs () {return (d_n_code_outputs);};
+
 protected:
   virtual void encode_private (const char** in_buf, char** out_buf) = 0;
   virtual char get_next_bit (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, d_total_n_enc_bits;
-  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;
+  size_t d_block_size_bits, d_n_code_inputs, d_n_code_outputs;
+  size_t d_n_enc_bits, d_total_n_enc_bits;
+  size_t d_in_buf_ndx, d_out_buf_ndx;
+  size_t d_in_bit_shift, d_out_bit_shift;
   size_t d_n_input_bits_left, d_n_output_bits_left;
 };
 

Index: lib/libecc/encoder_convolutional.cc
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.cc,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- lib/libecc/encoder_convolutional.cc 5 Jul 2006 20:57:44 -0000       1.3
+++ lib/libecc/encoder_convolutional.cc 9 Jul 2006 16:15:17 -0000       1.4
@@ -24,7 +24,7 @@
 #include "config.h"
 #endif
 
-#include <encoder_convolutional.h>
+#include "encoder_convolutional.h"
 #include <assert.h>
 #include <iostream>
 
@@ -38,26 +38,27 @@
 #include <mld/n2bs.h>
 #endif
 
-static const int g_max_frame_size_bits = 10000000;
+static const int g_max_block_size_bits = 10000000;
 static const int g_max_num_streams = 10;
 
 void encoder_convolutional::encoder_convolutional_init
-(int frame_size_bits,
+(int block_size_bits,
  int n_code_inputs,
  int n_code_outputs,
- std::vector<int> &code_generators,
+ const std::vector<int> &code_generators,
+ const std::vector<int>* code_feedback,
  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
+  // make sure the block length makes sense
 
-  if ((frame_size_bits < 0) | (frame_size_bits > g_max_frame_size_bits)) {
+  if ((block_size_bits < 0) | (block_size_bits > g_max_block_size_bits)) {
     std::cerr << "encoder_convolutional: " <<
-      "Requested frame length (" << frame_size_bits <<
-      " bits) must be between 0 and " << g_max_frame_size_bits <<
+      "Requested block length (" << block_size_bits <<
+      " bits) must be between 0 and " << g_max_block_size_bits <<
       " bits, with 0 being a streaming encoder.\n";
     assert (0);
   }
@@ -93,14 +94,31 @@
     assert (0);
   }
 
-  // create the class frame variables
+  // check for feedback (== NULL or not)
 
-  d_frame_size_bits = frame_size_bits;
+  d_do_feedback = (code_feedback != NULL);
+
+  // create the class block variables
+
+  d_block_size_bits = block_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_streaming = (block_size_bits == 0);
   d_do_termination = (d_do_streaming == true) ? false : do_termination;
 
+  if (DO_PRINT_DEBUG) {
+    std::cout <<
+      "d_block_size_bits = " << d_block_size_bits << "\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_feedback     = " <<
+      ((d_do_feedback == true) ? "true" : "false") << "\n";
+  }
+
   // 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.
@@ -114,39 +132,152 @@
   // 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.
+  // reference the matrix using "maoi(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
+  // reference the matrix using "maoi(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
+  // check the feedback for correctness, before anything else, since
+  // any feedback impacts the total # of delays in the encoder:
+  // without feedback, this is the sum of the individual delays max'ed
+  // over each input (if siao) or output (if soai).
 
-  d_code_feedback.assign (d_n_code_inputs * d_n_code_outputs, 1);
+  if (d_do_feedback == true) {
+    memory_t t_OR_all_feedback = 0;
+    for (size_t n = 0; n < d_n_code_outputs; n++) {
+      for (size_t m = 0; m < d_n_code_inputs; m++) {
+       memory_t t_in_code = (*d_code_feedback)[maoi(m,n)];
+
+       // OR this feedback with the overall,
+       // to check for any delays used at all
+
+       t_OR_all_feedback |= t_in_code;
+      }
+    }
+
+    // check to see if all the feedback entries were either "0" or "1",
+    // which implies no feedback; warn the user in that case and reset
+    // the do_feedback parameter to false.
+
+    if ((t_OR_all_feedback | 1) == 1) {
+      std::cout << "encoder_convolutional: Warning: " <<
+       "No feedback is required, ignoring feedback.\n";
   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
+  if (d_do_feedback == true) {
+    // resize the memory and states to the max size, worst case;
 
-  size_t t_max_mem = 0;
+    // d_n_memories will define how many of these are actually used;
+
+    // d_input_num and d_states will be set separately depending on
+    // the actual feedback parameters.
+
+    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);
+  } else {
+    // Setup for No Feedback;
+    // 1 memory per input; same for init and term states;
+
+    d_n_memories = d_n_code_inputs;
+    d_memory.assign (d_n_memories, 0);
+    d_init_states.assign (d_n_memories, 0);
+    d_term_states.assign (d_n_memories, 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);
+
+    // 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[maoi(m,n)] = &(d_memory[m]);
+  }
 
-  // loop over all input streams first, output streams second
+  // copy over the FF code generators
+
+  for (size_t n = 0; n < d_n_code_outputs; n++)
+    for (size_t m = 0; m < d_n_code_inputs; m++)
+      d_code_generators[maoi(m,n)] = code_generators[maoi(m,n)];
+
+  // check the input FF (and FB) code generators for correctness, and
+  // find the minimum memory configuration: combining via a single
+  // input / all outputs (SIAO), or a single output / all inputs (SOAI).
+  //
+  // for FF only, look over both the SOAI and SIAO realizations to
+  // find the minimum total # of delays, and use that realization
+  // (SOAI is preferred if total # of delays is equal, since it's much
+  // simpler to implement).
+  //
+  // for FB:
+  //   for SIAO, check each input row (all outputs for a given input)
+  //     for unique feedback; duplicate feedback entries can be
+  //     combined into a single computation to reduce total # of delays.
+  //   for SOAI: check each output column (all inputs for a given
+  //     output) for unique feedback; duplicate feedback entries can
+  //     be combined into a simgle computation (ditto).
+
+  // check for SOAI all '0' output
 
   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++)
+      t_all_inputs_zero |= d_code_generators[maoi(m,n)];
+
+    // check this input to see if all encoders were '0'; this might be
+    // OK for some codes, but warn the user just in case
+
+    if (t_all_inputs_zero == 0) {
+      std::cout << "encoder_convolutional: Warning:"
+       "Output " << n+1 << " (of " << d_n_code_outputs <<
+       ") will always be 0.\n";
+    }
+  }
+
+  // check for SIAO all '0' input
+
     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)];
+    memory_t t_all_outputs_zero = 0;
+    for (size_t n = 0; n < d_n_code_outputs; n++)
+      t_all_outputs_zero |= d_code_generators[maoi(m,n)];
+
+    // check this input to see if all encoders were '0'; this might be
+    // OK for some codes, but warn the user just in case
+
+    if (t_all_outputs_zero == 0) {
+      std::cout << "encoder_convolutional: Warning:"
+       "Input " << m+1 << " (of " << d_n_code_inputs <<
+       ") will not be used; all encoders are '0'.\n";
+    }
+  }
 
-      // check that not all codes for this input are 0
+I GOT TO HERE!
 
-      t_all_inputs_zero |= t_in_code;
+  // single output, all inputs (SOAI) realization check
+
+  std::vector<size_t> t_memories;
+  size_t oa_max_mem, t_total_mem;
+
+  t_memories.assign (d_n_code_outputs, 0);
+  oa_max_mem = t_total_mem = 0;
+  for (size_t n = 0; n < d_n_code_outputs; n++) {
+    size_t t_max_mem = 0;
+    for (size_t m = 0; m < d_n_code_inputs; m++) {
+      size_t t_in_code = d_code_generators[maoi(m,n)];
 
       // find the memory requirement for this code generator
 
@@ -157,108 +288,195 @@
       }
       if (t_code_mem > t_max_mem)
        t_max_mem = t_code_mem;
+
+      // check the feedback portion, if it exists;
+      // for soai, check all the inputs which generate this output for
+      // uniqueness; duplicate entries can be combined to reduce total
+      // # of memories as well as required computations.
+
+      if (d_do_feedback == true) {
+       size_t t_save_code = t_in_code = (*d_code_feedback)[maoi(m,n)];;
+
+       // find the memory requirement for this code generator
+
+       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: " <<
-       "At least 1 generator code for output " << n+1 <<
-       " must be non-0.\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;
 
-  // store the maximum memory order (e.g. "2" -> D^2)
+         // increase the number of unique feedback codes
+
+         d_n_memories++;
+       }
 
-  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: " <<
-      "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;
+    // store memory requirements for this output
+
+    t_total_mem += t_max_mem;
+    t_memories[n] = t_max_mem;
+    if (oa_max_mem < t_max_mem)
+      oa_max_mem = t_max_mem;
+  }
+
+  // store the parameters for SOAI
+
+  std::vector<size_t> t_memories_soai = t_memories;
+  size_t t_max_mem_soai = oa_max_mem;
+  size_t t_total_mem_soai = t_total_mem;
+
+  // single input, all outputs (siao)
+
+  t_memories.assign (d_n_code_inputs, 0);
+  oa_max_mem = t_total_mem = 0;
+  for (size_t m = 0; m < d_n_code_inputs; m++) {
+    size_t t_max_mem = 0;
+    for (size_t n = 0; n < d_n_code_outputs; n++) {
+      size_t t_in_code = d_code_generators[maoi(m,n)];
+
+      // 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 the feedback portion, if it exists
+
+      if (d_do_feedback == true) {
+       t_in_code = (*d_code_feedback)[maoi(m,n)];
+
+       // find the memory requirement for this code generator
+
+       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;
+      }
+     }
+
+    // store memory requirements for this output
+
+    t_total_mem += t_max_mem;
+    t_memories[n] = t_max_mem;
+    if (oa_max_mem < t_max_mem)
+      oa_max_mem = t_max_mem;
+  }
+
+  // store the parameters for SOAI
+
+  std::vector<size_t> t_memories_siao = t_memories;
+  size_t t_max_mem_siao = oa_max_mem;
+  size_t t_total_mem_siao = t_total_mem;
 
   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.";
+    std::cout << "Parameters:\n"
+      "  max_mem_siao    = " << t_max_mem_siao << "\n"
+      "  total_mem_siao  = " << t_total_mem_siao << "\n"
+      "  max_mem_soai    = " << t_max_mem_soai << "\n"
+      "  total_mem_soai  = " << t_total_mem_soai << "\n";
   }
 
-  // by default no Feedback;
-  // setup for that from here down:
-  // 1 memory per input; same for init and term states;
+  // pick which realization to use; soai is preferred since it's faster
+  // ... but unfortunately it's also less likely
 
-  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);
+  if (t_max_mem_soai <= t_max_mem_soai) {
+    // use soai
+    d_do_encode_soai = true;
+    d_memories_siao = t_memories;
+    size_t t_max_mem_siao = t_max_mem;
+    size_t t_total_mem_siao = t_total_mem;
+  } else {
+    // use soai
+    d_do_encode_soai = true;
+    d_memories_siao = t_memories;
+    size_t t_max_mem_siao = t_max_mem;
+    size_t t_total_mem_siao = t_total_mem;
 
-  // assign input numbers, one per memory
+  }
 
-  for (size_t n = 0; n < d_n_code_inputs; n++)
-    d_input_num[n] = n;
+  // store this maximum memory order (e.g. "2" -> D^2)
 
-  // assign d_states' pointers correctly
-  // loop over all I/O streams
+  d_max_delay = t_max_mem - 1;
 
-  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]);
-}
+  if (DO_PRINT_DEBUG) {
+    std::cout <<
+      "d_max_delay      = " << d_max_delay << "\n";
+  }
 
-encoder_convolutional::encoder_convolutional
-(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.
+  // make sure the block length makes sense, #2
 
-  encoder_convolutional_init
-    (frame_size_bits,
-     n_code_inputs,
-     n_code_outputs,
-     code_generators,
-     do_termination,
-     start_memory_state,
-     end_memory_state);
+  if ((d_do_streaming == false) & (d_block_size_bits < d_max_delay)) {
+    std::cerr << "encoder_convolutional: " <<
+      "Requested block length (" << d_block_size_bits <<
+      " bit" << (d_block_size_bits > 1 ? "s" : "") <<
+      ") must be at least 1 memory length (" << d_max_delay <<
+      " bit" << (d_max_delay > 1 ? "s" : "") <<
+      " for this code) when doing block coding.\n";
+    assert (0);
+  }
 
-  // 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 feedback portion, if it exists,
+  // for correctness & # of memories
+
+  if (d_do_feedback == true) {
+    // need to check the code_feedback to make sure it's valid; need to
+    // update the "d_max_delay" and comment back to the user if
+    // feedback is longer than feedforward.
+
+    if (d_do_feedback == true) {
 
   // check the code_feedback for correctness & find the memory order
   // t_max_mem will be the mamimum number of memories used by the
@@ -327,40 +545,50 @@
     }
   }
 
-  // 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: 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).
+      // 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) {
+      if (--t_max_mem > d_max_delay) {
     std::cout << "encoder_convolutional: Warning: " <<
       "Feedback using more memory than feedforward.\n";
-    d_max_memory = t_max_mem;
+       d_max_delay = t_max_mem;
 
-    // make sure the frame length makes sense, #2
+       // make sure the block length makes sense, #2
 
-    if ((d_do_streaming == true) & (d_frame_size_bits < d_max_memory)) {
+       if ((d_do_streaming == false) & (d_block_size_bits < d_max_delay)) {
       std::cerr << "encoder_convolutional: " <<
-       "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" : "") <<
+           "Requested block length (" << d_block_size_bits <<
+           " bit" << (d_block_size_bits > 1 ? "s" : "") <<
+           ") must be at least 1 memory length (" << d_max_delay <<
+           " bit" << (d_max_delay > 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;
+       d_max_mem_mask = (2 << d_max_delay) - 1;
+      }
+    }
   }
+
+  // create the memory mask for this code generator
+
+  d_max_mem_mask = (2 << d_max_delay) - 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_delay+2) <<
+      "\n  Max_Mem = " << d_max_delay << "\n.";
+  }
+
 }
 
 void
@@ -403,7 +631,7 @@
       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)
+       // used to compare with the number of bits in the block)
 
        d_n_enc_bits = 0;
       }
@@ -416,15 +644,15 @@
     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
+      // from external sources; loop up to the block 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);
+      encode_loop (in_buf, out_buf, &d_n_input_bits_left, d_block_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)) {
+      if ((d_n_enc_bits == d_block_size_bits) & (d_do_streaming == false)) {
 
        // jump to another state, depending on termination requirement
 
@@ -445,11 +673,11 @@
       // number of output bits left
 
       if (d_do_termination == false) {
-       encode_loop (in_buf, out_buf, &d_n_output_bits_left, d_max_memory);
+       encode_loop (in_buf, out_buf, &d_n_output_bits_left, d_max_delay);
 
        // finished this loop; check for jumping to the next state
 
-       if (d_n_enc_bits == d_max_memory)
+       if (d_n_enc_bits == d_max_delay)
          d_fsm_state = fsm_enc_conv_init;
 
       } else {
@@ -497,8 +725,94 @@
  size_t* which_counter,
  size_t how_many)
 {
+  if (d_do_encode_soai == true)
+    encode_loop_soai (in_buf, out_buf, which_counter, how_many);
+  else
+    encode_loop_siao (in_buf, out_buf, which_counter, how_many);
+}
+
+void
+encoder_convolutional::encode_loop_soai
+(const char** in_buf,
+ char** out_buf,
+ size_t* which_counter,
+ size_t how_many)
+{
+  // single-output, all inputs
+
+  if (DO_PRINT_DEBUG) {
+    std::cout << "starting encode_loop_soai.\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).
+
+
+#if 0
+    for (m = 0; m < d_n_code_outputs; m++) {
+      memory_t t_mem = ??? >> 1;
+      for (n = 0; n < d_n_code_inputs; n++) {
+       if (get_next_bit (in_buf, d_input_num[???]))
+         t_mem ^= d_code_generator[maoi(n,m)];
+      }
+      char t_out_bit = t_mem & 1;
+
+      if ((d_do_feedback == true) & t_out_bit)
+       t_mem ^= (d_code_feedback (??[m]) & (d_mem_mask - 1));
+
+      ??? = t_mem;
+
+      // output this particular bit on this output stream
+
+      output_bit (t_out_bit, out_buf, m);
+
+      // increment the input and output indices, if necessary, between
+      // output bits
+
+      increment_io_indices (true);
+    }
+#endif
+    // 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_soai.\n";
+  }
+}
+
+void
+encoder_convolutional::encode_loop_siao
+(const char** in_buf,
+ char** out_buf,
+ size_t* which_counter,
+ size_t how_many)
+{
+  // single input, all outputs
+
   if (DO_PRINT_DEBUG) {
-    std::cout << "starting encode_loop.\n";
+    std::cout << "starting encode_loop_siao.\n";
   }
   while (((*which_counter) > 0) & (d_n_enc_bits < how_many)) {
     if (DO_PRINT_DEBUG) {
@@ -514,14 +828,14 @@
     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";
+         n2bs (d_memory[p], d_max_delay+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";
+         n2bs (d_memory[p], d_max_delay+2) << "\n";
       }
     }
 
@@ -536,34 +850,34 @@
       // 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)]));
+       memory_t t_c_g = d_code_generators[maoi(p,q)];
+       memory_t t_mem = (*(d_states[maoi(p,q)]));
 
        if (DO_PRINT_DEBUG) {
          std::cout << "b_i = " <<
-           n2bs (t_out_result, d_max_memory+2) <<
+           n2bs (t_out_result, d_max_delay+2) <<
            ", st[" << p << "," << q << "] = " <<
-           n2bs (t_mem, d_max_memory+2) <<
+           n2bs (t_mem, d_max_delay+2) <<
            ", cg[" << p << "," << q << "] = " <<
-           n2bs (t_c_g, d_max_memory+2) <<
+           n2bs (t_c_g, d_max_delay+2) <<
            ", st[] & cg[] = " <<
-           n2bs (t_mem & t_c_g, d_max_memory+2);
+           n2bs (t_mem & t_c_g, d_max_delay+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';
+           n2bs (t_out_result, d_max_delay+2) << '\n';
        }
       }
       if (DO_PRINT_DEBUG) {
-       std::cout << "b_r = " << n2bs (t_out_result, d_max_memory+2);
+       std::cout << "b_r = " << n2bs (t_out_result, d_max_delay+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);
+      char t_out_bit = sum_bits_mod2 (t_out_result, d_max_delay);
 
       if (DO_PRINT_DEBUG) {
        std::cout << "t_out_bit = mo2_sum (b_o) = " <<
@@ -585,38 +899,6 @@
     // 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::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
 
@@ -630,14 +912,14 @@
   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";
+         n2bs (d_memory[p], d_max_delay+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";
+         n2bs (d_memory[p], d_max_delay+2) << "\n";
     }
   }
 
@@ -653,7 +935,7 @@
     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";
+           n2bs (d_memory[p], d_max_delay+2) << "\n";
       }
 
       // do feedback with current memory
@@ -663,7 +945,7 @@
 
       if (DO_PRINT_DEBUG) {
        std::cout << "    t_state = mem[] & (" << d_max_mem_mask <<
-         " xor 2) = " << n2bs (t_state, d_max_memory+2) << "\n";
+           " xor 2) = " << n2bs (t_state, d_max_delay+2) << "\n";
       }
 
       // create the code feedback state
@@ -673,12 +955,12 @@
       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";
+           n2bs (t_fb_state, d_max_delay+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);
+       char t_fb_bit = sum_bits_mod2 (t_fb_state, d_max_delay);
 
       if (DO_PRINT_DEBUG) {
        std::cout << "    t_fb_bit = mod2_sum (t_fb_state) = " <<
@@ -691,13 +973,30 @@
 
       if (DO_PRINT_DEBUG) {
        std::cout << "    mem_out[" << p << "] = t_state | (fb_bit << 1) = " <<
-         n2bs (d_memory[p], d_max_memory+2) << "\n";
+           n2bs (d_memory[p], d_max_delay+2) << "\n";
       }
     }
   }
 
+    // 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 update_memory_post_encode.\n";
+    std::cout << "ending encode_loop_siao.\n";
   }
 }
 

Index: lib/libecc/encoder_convolutional.h
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- lib/libecc/encoder_convolutional.h  5 Jul 2006 20:57:44 -0000       1.3
+++ lib/libecc/encoder_convolutional.h  9 Jul 2006 16:15:17 -0000       1.4
@@ -23,12 +23,11 @@
 #ifndef INCLUDED_ENCODER_CONVOLUTIONAL_H
 #define INCLUDED_ENCODER_CONVOLUTIONAL_H
 
-#include <vector>
 #include "encoder.h"
+#include <vector>
 
 class encoder_convolutional : public encoder
 {
-public:
 /*!
  * class encoder_convolutional : public encoder
  *
@@ -38,8 +37,8 @@
  *     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
+ * block_size_bits: if == 0, then do streaming encoding ("infinite"
+ *     trellis); otherwise this is the block size in bits to encode
  *     before terminating the trellis.  This value -does not- include
  *     any termination bits.
  *
@@ -54,8 +53,12 @@
  *     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.
+ *     The "octal" representation is used frequently in the literature
+ *     (e.g. [015, 06] == [1101, 0110] in binary) due to its close
+ *     relationship with binary (each number is 3 binary digits)
+ *     ... but any integer representation will suffice.
  *
- * do_termination: valid only if frame_size_bits != 0, and defines
+ * do_termination: valid only if block_size_bits != 0, and defines
  *     whether or not to use trellis termination.  Default is to use
  *     termination when doing block coding.
  *
@@ -70,17 +73,20 @@
  *     default is the "all zero" state.
  */
 
-  inline encoder_convolutional (int frame_size_bits,
+public:
+  inline encoder_convolutional
+  (int block_size_bits,
                                     int n_code_inputs,
                                     int n_code_outputs,
-                                    std::vector<int> &code_generators,
+   const std::vector<int> &code_generators,
                                     bool do_termination = true,
                                     int start_memory_state = 0,
                                     int end_memory_state = 0)
-  {encoder_convolutional_init (frame_size_bits,
+  {encoder_convolutional_init (block_size_bits,
                               n_code_inputs,
                               n_code_outputs,
                               code_generators,
+                              NULL,
                               do_termination,
                               start_memory_state,
                               end_memory_state);};
@@ -89,33 +95,50 @@
  * 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.
+ *     feedback to be implemented (same as for the code_generator).
+ *     For this feedback type, the LSB ("& 1") is ignored (set to "1"
+ *     internally, since it's always 1) ... this (effectively)
+ *     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 (int frame_size_bits,
+  inline encoder_convolutional
+  (int block_size_bits,
                         int n_code_inputs,
                         int n_code_outputs,
-                        std::vector<int> &code_generators,
-                        std::vector<int> &code_feedback,
+   const std::vector<int> &code_generators,
+   const std::vector<int> &code_feedback,
                         bool do_termination = true,
                         int start_memory_state = 0,
-                        int end_memory_state = 0);
+   int end_memory_state = 0)
+  {encoder_convolutional_init (block_size_bits,
+                              n_code_inputs,
+                              n_code_outputs,
+                              code_generators,
+                              &code_feedback,
+                              do_termination,
+                              start_memory_state,
+                              end_memory_state);};
 
   virtual ~encoder_convolutional () {};
 
+/* for remote access to internal info */
+
+  inline const bool do_termination () {return (d_do_termination);};
+  inline const bool do_feedback () {return (d_do_feedback);};
+  inline const bool do_streaming () {return (d_do_streaming);};
+  inline const size_t total_n_delays () {return (d_total_n_delays);};
+
 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
+ * fsm_enc_conv_init: initialize for a new block / 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
@@ -132,42 +155,47 @@
  *     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
+ * 'i' is the 1st dimension - faster memory - the code input
+ * 'o' is the 2nd dimension - slower memory - the code output
  *
- * returns ((o*n_code_outputs) + i)
+ * returns ((o*n_code_inputs) + i)
  */
 
-  inline size_t maio(size_t i, size_t o) {return ((o*d_n_code_outputs) + i);};
+  inline size_t maio(size_t i, size_t o) {return ((o*d_n_code_inputs) + 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
+ * 'o' is the 1st dimension - faster memory - the code output
+ * 'i' is the 2nd dimension - slower memory - the code input
  *
- * returns ((i*n_code_inputs) + o)
+ * returns ((i*n_code_outputs) + o)
  */
 
-  inline size_t maoi(size_t i, size_t o) {return ((i*d_n_code_inputs) + o);};
+  inline size_t maoi(size_t i, size_t o) {return ((i*d_n_code_outputs) + o);};
 
   // methods defined in this class
 
-  void encoder_convolutional_init (int frame_size_bits,
+  void encoder_convolutional_init (int block_size_bits,
                                   int n_code_inputs,
                                   int n_code_outputs,
-                                  std::vector<int> &code_generators,
+                                  const std::vector<int>& code_generators,
+                                  const 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 void encode_loop_soai (const char** in_buf, char** out_buf,
+                                size_t* which_counter, size_t how_many);
+  virtual void encode_loop_siao (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
@@ -180,9 +208,24 @@
   // variables
 
   fsm_enc_conv_t d_fsm_state;
-  bool d_do_streaming, d_do_termination, d_do_feedback;
+  bool d_do_streaming, d_do_termination, d_do_feedback, d_do_encode_soai;
+  memory_t d_max_mem_mask;
+
+  // max_delay is the max # of delays for all unique generators (ff and fb), 
+  // needed to determine (e.g.) termination
+
+  size_t d_max_delay;
+
+  // n_memories is the number of unique memories as determined by
+  // either the feedforward or feedback generators (not both).
+
   size_t d_n_memories;
 
+  // total_n_delays is the total # of delays, needed to determine the
+  // # of states in the decoder
+
+  size_t d_total_n_delays;
+
   // 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.

Index: lib/libecc/encoder_convolutional_ic1_ic1.cc
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.cc,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- lib/libecc/encoder_convolutional_ic1_ic1.cc 4 Jul 2006 20:57:32 -0000       
1.1
+++ lib/libecc/encoder_convolutional_ic1_ic1.cc 9 Jul 2006 16:15:17 -0000       
1.2
@@ -89,24 +89,24 @@
 
     t_n_output_bits -= n_extra;
 
-    // find the number of frames of data which could be processed
+    // find the number of blocks of data which could be processed
 
-    size_t t_n_output_bits_per_frame = d_frame_size_bits + d_max_memory;
+    size_t t_n_output_bits_per_block = d_block_size_bits + d_max_memory;
 
     // get the base number of input items required for the given
-    // number of frames to be generated
+    // number of blocks to be generated
 
-    size_t t_n_frames = t_n_output_bits / t_n_output_bits_per_frame;
-    t_n_input_bits = t_n_frames * d_frame_size_bits;
+    size_t t_n_blocks = t_n_output_bits / t_n_output_bits_per_block;
+    t_n_input_bits = t_n_blocks * d_block_size_bits;
 
     // add to that the number of leftover inputs needed to generate
-    // the remainder of the outputs within the remaining frame, up to
-    // the given frame size (since anything beyond that within this
-    // frame requires no inputs)
-
-    size_t t_leftover_bits = t_n_output_bits % t_n_output_bits_per_frame;
-    t_n_input_bits += ((t_leftover_bits > d_frame_size_bits) ?
-                      d_frame_size_bits : t_leftover_bits);
+    // the remainder of the outputs within the remaining block, up to
+    // the given block size (since anything beyond that within this
+    // block requires no inputs)
+
+    size_t t_leftover_bits = t_n_output_bits % t_n_output_bits_per_block;
+    t_n_input_bits += ((t_leftover_bits > d_block_size_bits) ?
+                      d_block_size_bits : t_leftover_bits);
   }
 
   return (t_n_input_bits);

Index: lib/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.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- lib/libecc/encoder_convolutional_ic1_ic1.h  5 Jul 2006 17:49:58 -0000       
1.2
+++ lib/libecc/encoder_convolutional_ic1_ic1.h  9 Jul 2006 16:15:17 -0000       
1.3
@@ -44,10 +44,11 @@
  *     the single output bit per output item.
  */
 
-  inline encoder_convolutional_ic1_ic1 (int frame_size_bits,
+  inline encoder_convolutional_ic1_ic1
+  (int frame_size_bits,
                                        int n_code_inputs,
                                        int n_code_outputs,
-                                       std::vector<int> &code_generators,
+   const std::vector<int> &code_generators,
                                        bool do_termination = true,
                                        int start_memory_state = 0,
                                        int end_memory_state = 0)
@@ -59,11 +60,12 @@
                             start_memory_state,
                             end_memory_state) {};
 
-  inline encoder_convolutional_ic1_ic1 (int frame_size_bits,
+  inline encoder_convolutional_ic1_ic1
+  (int frame_size_bits,
                                        int n_code_inputs,
                                        int n_code_outputs,
-                                       std::vector<int> &code_generators,
-                                       std::vector<int> &code_feedback,
+   const std::vector<int> &code_generators,
+   const std::vector<int> &code_feedback,
                                        bool do_termination = true,
                                        int start_memory_state = 0,
                                        int end_memory_state = 0)

Index: lib/libecc/encoder_convolutional_ic8_ic8.h
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic8_ic8.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- lib/libecc/encoder_convolutional_ic8_ic8.h  5 Jul 2006 20:57:44 -0000       
1.1
+++ lib/libecc/encoder_convolutional_ic8_ic8.h  9 Jul 2006 16:15:17 -0000       
1.2
@@ -44,10 +44,11 @@
 class encoder_convolutional_ic8_ic8 : public encoder_convolutional
 {
 public:
-  inline encoder_convolutional_ic8_ic8 (int frame_size_bits,
+  inline encoder_convolutional_ic8_ic8
+  (int frame_size_bits,
                                        int n_code_inputs,
                                        int n_code_outputs,
-                                       std::vector<int> &code_generators,
+   const std::vector<int> &code_generators,
                                        bool do_termination = true,
                                        int start_memory_state = 0,
                                        int end_memory_state = 0)
@@ -59,11 +60,12 @@
                             start_memory_state,
                             end_memory_state) {};
 
-  inline encoder_convolutional_ic8_ic8 (int frame_size_bits,
+  inline encoder_convolutional_ic8_ic8
+  (int frame_size_bits,
                                        int n_code_inputs,
                                        int n_code_outputs,
-                                       std::vector<int> &code_generators,
-                                       std::vector<int> &code_feedback,
+   const std::vector<int> &code_generators,
+   const std::vector<int> &code_feedback,
                                        bool do_termination = true,
                                        int start_memory_state = 0,
                                        int end_memory_state = 0)
@@ -71,7 +73,7 @@
                             n_code_inputs,
                             n_code_outputs,
                             code_generators,
-                            code_feedback
+                            code_feedback,
                             do_termination,
                             start_memory_state,
                             end_memory_state) {};

Index: lib/gr_metrics_decode_viterbi_full_block.cc
===================================================================
RCS file: lib/gr_metrics_decode_viterbi_full_block.cc
diff -N lib/gr_metrics_decode_viterbi_full_block.cc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/gr_metrics_decode_viterbi_full_block.cc 9 Jul 2006 16:15:17 -0000       
1.1
@@ -0,0 +1,228 @@
+/* -*- 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_metrics_decode_viterbi_full_block.h>
+#include <gr_io_signature.h>
+#include <assert.h>
+#include <iostream>
+
+gr_metrics_decode_viterbi_full_block_sptr
+gr_make_metrics_decode_viterbi_full_block
+(int sample_precision,
+ int frame_size_bits,
+ int n_code_inputs,
+ int n_code_outputs,
+ const std::vector<int> &code_generator,
+ bool do_termination,
+ int start_memory_state,
+ int end_memory_state)
+{
+  return gr_metrics_decode_viterbi_full_block_sptr
+    (new gr_metrics_decode_viterbi_full_block
+     (sample_precision,
+      frame_size_bits,
+      n_code_inputs,
+      n_code_outputs,
+      code_generator,
+      do_termination,
+      start_memory_state,
+      end_memory_state));
+}
+
+gr_metrics_decode_viterbi_full_block_feedback_sptr
+gr_make_metrics_decode_viterbi_full_block_feedback
+(int sample_precision,
+ int frame_size_bits,
+ int n_code_inputs,
+ int n_code_outputs,
+ const std::vector<int> &code_generator,
+ const std::vector<int> &code_feedback,
+ bool do_termination,
+ int start_memory_state,
+ int end_memory_state)
+{
+  return gr_metrics_decode_viterbi_full_block_feedback_sptr
+    (new gr_metrics_decode_viterbi_full_block
+     (sample_precision,
+      frame_size_bits,
+      n_code_inputs,
+      n_code_outputs,
+      code_generator,
+      code_feedback,
+      do_termination,
+      start_memory_state,
+      end_memory_state));
+}
+
+gr_metrics_decode_viterbi_full_block::gr_metrics_decode_viterbi_full_block
+(int sample_precision,
+ int frame_size_bits,
+ int n_code_inputs,
+ int n_code_outputs,
+ const std::vector<int> &code_generator,
+ bool do_termination,
+ int start_memory_state,
+ int end_memory_state)
+  : gr_block ("metrics_decode_viterbi_full_block",
+             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);
+
+  setup_io_signatures (sample_precision, n_code_inputs, n_code_outputs);
+}
+
+gr_metrics_decode_viterbi_full_block::gr_metrics_decode_viterbi_full_block
+(int sample_precision,
+ int frame_size_bits,
+ int n_code_inputs,
+ int n_code_outputs,
+ const std::vector<int> &code_generator,
+ const std::vector<int> &code_feedback,
+ bool do_termination,
+ int start_memory_state,
+ int end_memory_state)
+  : gr_block ("metrics_decode_viterbi_full_block_feedback",
+             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);
+
+  setup_io_signatures (sample_precision, n_code_inputs, n_code_outputs);
+}
+
+gr_metrics_decode_viterbi_full_block::~gr_metrics_decode_viterbi_full_block
+()
+{
+  delete d_decoder;
+  delete d_encoder;
+}
+
+void
+gr_metrics_decode_viterbi_full_block::setup_io_signatures
+(int sample_precision,
+ int n_code_inputs,
+ int n_code_outputs)
+{
+  // create the decoder using:
+  //
+  // the "i1" input model: individual input streams; two per metric
+  // type (0-bit, 1-bit), single metric per input item (char, short, long)
+  //
+  // the "ic1" output model:
+  // individual output streams per decoded code input stream;
+  // each item is a 'char' type with 1 bit aligned on the LSB.
+
+  d_decoder = new decoder_viterbi_full_block_i1_ic1 (sample_precision,
+                                                    d_encoder);
+
+  // error checking is done in the encoder and decoder classes
+  // so just use the parameters as given; will be correct!
+
+  d_n_code_inputs = n_code_inputs;
+  d_n_code_outputs = n_code_outputs;
+
+  // 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_metrics_decode_viterbi_full_block::forecast
+(int noutput_items,
+ gr_vector_int &ninput_items_required)
+{
+  int ninput_items = d_decoder->compute_n_input_metrics (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_metrics_decode_viterbi_full_block::general_work
+(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+  // FIXME: compute the actual number of output items (1 bit char's) created.
+
+  size_t t_n_input_items = d_decoder->compute_n_input_metrics (noutput_items);
+  size_t t_n_output_items = d_decoder->compute_n_output_bits (t_n_input_items);
+
+  assert (t_n_output_items == ((size_t)noutput_items));
+
+  // "work" is handled by the decoder; which returns the actual number
+  // of input items (metrics) used.
+
+  t_n_input_items = d_decoder->decode ((const char**)(&input_items[0]),
+                                      (char**)(&output_items[0]),
+                                      noutput_items);
+
+  // consume the number of used input items on all input streams
+
+  consume_each (t_n_input_items);
+
+  // returns number of items written to each output stream
+
+  return (noutput_items);
+}

Index: lib/gr_metrics_decode_viterbi_full_block.h
===================================================================
RCS file: lib/gr_metrics_decode_viterbi_full_block.h
diff -N lib/gr_metrics_decode_viterbi_full_block.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/gr_metrics_decode_viterbi_full_block.h  9 Jul 2006 16:15:17 -0000       
1.1
@@ -0,0 +1,163 @@
+/* -*- 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_METRICS_DECODE_VITERBI_FULL_BLOCK_H
+#define INCLUDED_GR_METRICS_DECODE_VITERBI_FULL_BLOCK_H
+
+#include <gr_block.h>
+#include <libecc/decoder_viterbi_full_block_i1_ic1.h>
+#include <libecc/encoder_convolutional_ic1_ic1.h>
+
+class gr_metrics_decode_viterbi_full_block;
+
+typedef boost::shared_ptr<gr_metrics_decode_viterbi_full_block>
+gr_metrics_decode_viterbi_full_block_sptr,
+gr_metrics_decode_viterbi_full_block_feedback_sptr;
+
+gr_metrics_decode_viterbi_full_block_sptr
+gr_make_metrics_decode_viterbi_full_block
+(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);
+
+gr_metrics_decode_viterbi_full_block_feedback_sptr
+gr_make_metrics_decode_viterbi_full_block_feedback
+(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 = true,
+ int start_memory_state = 0,
+ int end_memory_state = 0);
+
+/*!
+ * \brief Decode the incoming streams using a Viterbi-style decoder,
+ *     full trellis block decoding.
+ *
+ * input: symbol metrics data.
+ *
+ * output: stream(s) of char, single bit stored in the LSB.
+ */
+
+class gr_metrics_decode_viterbi_full_block : public gr_block
+{
+  friend gr_metrics_decode_viterbi_full_block_sptr
+  gr_make_metrics_decode_viterbi_full_block
+  (int sample_precision,
+   int frame_size_bits,
+   int n_code_inputs,
+   int n_code_outputs,
+   const std::vector<int> &code_generator,
+   bool do_termination,
+   int start_memory_state,
+   int end_memory_state);
+
+  friend gr_metrics_decode_viterbi_full_block_feedback_sptr
+  gr_make_metrics_decode_viterbi_full_block_feedback
+  (int sample_precision,
+   int frame_size_bits,
+   int n_code_inputs,
+   int n_code_outputs,
+   const std::vector<int> &code_generator,
+   const std::vector<int> &code_feedback,
+   bool do_termination,
+   int start_memory_state,
+   int end_memory_state);
+/*
+ * 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_metrics_decode_viterbi_full_block
+  (int sample_precision,
+   int frame_size_bits,
+   int n_code_inputs,
+   int n_code_outputs,
+   const std::vector<int> &code_generator,
+   bool do_termination,
+   int start_memory_state,
+   int end_memory_state);
+
+  gr_metrics_decode_viterbi_full_block
+  (int sample_precision,
+   int frame_size_bits,
+   int n_code_inputs,
+   int n_code_outputs,
+   const std::vector<int> &code_generator,
+   const std::vector<int> &code_feedback,
+   bool do_termination,
+   int start_memory_state,
+   int end_memory_state);
+
+public:
+  ~gr_metrics_decode_viterbi_full_block ();
+
+  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:
+  void setup_io_signatures (int sample_precision,
+                           int n_code_inputs,
+                           int n_code_outputs);
+
+  int d_n_code_inputs, d_n_code_outputs;
+  decoder_viterbi_full_block_i1_ic1* d_decoder;
+  encoder_convolutional_ic1_ic1* d_encoder;
+};
+
+#endif /* INCLUDED_GR_METRICS_DECODE_VITERBI_FULL_BLOCK_H */

Index: lib/gr_metrics_decode_viterbi_full_block.i
===================================================================
RCS file: lib/gr_metrics_decode_viterbi_full_block.i
diff -N lib/gr_metrics_decode_viterbi_full_block.i
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/gr_metrics_decode_viterbi_full_block.i  9 Jul 2006 16:15:17 -0000       
1.1
@@ -0,0 +1,77 @@
+/* -*- 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,metrics_decode_viterbi_full_block);
+
+// corrected "class NAME" statement, which uses slightly different NAMEs
+
+typedef boost::shared_ptr<gr_metrics_decode_viterbi_full_block>
+gr_metrics_decode_viterbi_full_block_feedback_sptr;
+
+LOCAL_GR_SWIG_BLOCK_MAGIC(gr,metrics_decode_viterbi_full_block_feedback);
+
+gr_metrics_decode_viterbi_full_block_sptr
+gr_make_metrics_decode_viterbi_full_block
+(int sample_precision,
+ int frame_size_bits,
+ int n_code_inputs,
+ int n_code_outputs,
+ const std::vector<int> &code_generator,
+ bool do_termination,
+ int start_memory_state,
+ int end_memory_state);
+
+gr_metrics_decode_viterbi_full_block_feedback_sptr
+gr_make_metrics_decode_viterbi_full_block_feedback
+(int sample_precision,
+ int frame_size_bits,
+ int n_code_inputs,
+ int n_code_outputs,
+ const std::vector<int> &code_generator,
+ const std::vector<int> &code_feedback,
+ bool do_termination,
+ int start_memory_state,
+ int end_memory_state);
+
+class gr_metrics_decode_viterbi_full_block : public gr_block
+{
+  gr_metrics_decode_viterbi_full_block
+  (int sample_precision,
+   int frame_size_bits,
+   int n_code_inputs,
+   int n_code_outputs,
+   const std::vector<int> &code_generator,
+   bool do_termination,
+   int start_memory_state,
+   int end_memory_state);
+
+  gr_metrics_decode_viterbi_full_block
+  (int sample_precision,
+   int frame_size_bits,
+   int n_code_inputs,
+   int n_code_outputs,
+   const std::vector<int> &code_generator,
+   const std::vector<int> &code_feedback,
+   bool do_termination,
+   int start_memory_state,
+   int end_memory_state);
+};

Index: lib/gr_streams_encode_turbo.cc
===================================================================
RCS file: lib/gr_streams_encode_turbo.cc
diff -N lib/gr_streams_encode_turbo.cc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/gr_streams_encode_turbo.cc      9 Jul 2006 16:15:17 -0000       1.1
@@ -0,0 +1,209 @@
+/* -*- 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_streams_encode_turbo.h>
+#include <gr_io_signature.h>
+#include <assert.h>
+#include <iostream>
+
+gr_streams_encode_turbo_sptr 
+gr_make_streams_encode_turbo
+(int n_code_inputs,
+ int n_code_outputs,
+ const std::vector<gr_streams_encode_convolutional_sptr> &encoders,
+ const std::vector<size_t> &interleavers)
+{
+  return gr_streams_encode_turbo_sptr
+    (new gr_streams_encode_turbo (n_code_inputs,
+                                 n_code_outputs,
+                                 encoders,
+                                 interleavers));
+}
+
+gr_streams_encode_turbo::gr_streams_encode_turbo
+(int n_code_inputs,
+ int n_code_outputs,
+ const std::vector<gr_streams_encode_convolutional_sptr> &encoders,
+ const std::vector<size_t> &interleavers)
+  : gr_block ("streams_encode_turbo",
+             gr_make_io_signature (0, 0, 0),
+             gr_make_io_signature (0, 0, 0))
+{
+  // error checking is done by the encoder class itself;
+  // just pass items on here.
+
+  // check out individual encoders, to make sure the total input /
+  // output matches those specified by the user.
+
+  d_n_encoders = encoders.size ();
+
+  if (d_n_encoders < 2) {
+    std::cerr << "gr_streams_encode_turbo: Error: "
+      "too few (" << d_n_encoders << ") encoders specified; a Turbo "
+      "code requires at least 2 constituent encoders.\n";
+    assert (0);
+  }
+
+  // make sure that the block size and termination are consistent for
+  // all encoders; warn the user if not, since it doesn't really
+  // matter to the encoder (but it might to the decoder; remains to be
+  // seen).
+
+  encoder_convolutional_ic1_ic1* t_ec = encoders[0]->encoder ();
+  d_block_size_bits = t_ec->block_size_bits ();
+  d_do_termination = t_ec->do_termination ();
+  bool t_diff_block_size, t_diff_termination;
+  t_diff_block_size = t_diff_termination = false;
+
+  for (size_t m = 1; m < d_n_encoders; m++) {
+    t_ec = encoders[0]->encoder ();
+    size_t t_block_size_bits = t_ec->block_size_bits ();
+    if (t_block_size_bits != d_block_size_bits)
+      t_diff_block_size = true;
+    bool t_do_termination = t_ec->do_termination ();
+    if (t_do_termination != d_do_termination)
+      t_do_termination = true;
+  }
+
+  if (t_diff_block_size == true) {
+    std::cout << "gr_streams_encode_turbo: Warning: "
+      "Some constituent encoders have different block size (bits).\n";
+  }
+  if (t_diff_termination == true) {
+    std::cout << "gr_streams_encode_turbo: Warning: "
+      "Some constituent encoders are differently terminationed.\n";
+  }
+
+  std::cout << "gr_streams_encode_turbo: setup:\n"
+    "d_n_encoders = " << d_n_encoders << "\n"
+    "n_code_inputs = " << n_code_inputs << "\n"
+    "n_code_outputs = " << n_code_outputs << "\n\n"
+    "Individual Encoders:\n";
+
+  for (size_t m = 0; m < d_n_encoders; m++) {
+    t_ec = encoders[m]->encoder ();
+    std::cout << "  [" << (m+1) << "]:\n"
+      "n_code_inputs = " << (t_ec->n_code_inputs()) << "\n"
+      "n_code_outputs = " << (t_ec->n_code_outputs()) << "\n"
+      "block_size_bits = " << (t_ec->block_size_bits()) << "\n"
+      "do_termination = " <<
+      ((t_ec->do_termination()==true)?"true":"false") << "\n";
+  }
+
+#if 1
+  assert (0);
+#else
+  if (d_n_encoders != (interleavers.size())) {}
+
+  d_encoder = new encoder_turbo_ic1_ic1 (n_code_inputs,
+                                        n_code_outputs,
+                                        code_generators,
+                                        do_termination,
+                                        start_memory_state,
+                                        end_memory_state);
+#endif
+
+  // create the correct input signature; 1 bit per input char
+
+  set_input_signature (gr_make_io_signature (n_code_inputs,
+                                            n_code_inputs,
+                                            sizeof (char)));
+
+  // create the correct output signature; 1 bit per output char
+
+  set_output_signature (gr_make_io_signature (n_code_outputs,
+                                             n_code_outputs,
+                                             sizeof (char)));
+
+// set the output multiple to 1 item, then let the encoder class
+// handle the rest internally
+
+  set_output_multiple (1);
+}
+
+gr_streams_encode_turbo::~gr_streams_encode_turbo
+()
+{
+  if (d_encoder)
+    delete d_encoder;
+}
+
+/*
+ * Compute the number of input bits (items in this case, since each
+ * item has 1 bit in it) needed to produce 'n_output' bits (items in
+ * this case, since each item has 1 bit in it).
+ *
+ * For turbo encoders, there is 1 bit output per bit input per
+ * stream, with the addition of a some bits for trellis termination if
+ * selected.  Thus the input:output bit ratio will be:
+ * 
+ * if (streaming | no termination), 1:1
+ *
+ * if (not streaming & termination), roughly 1:(1+X), where "X" is the
+ * total memory size of the code divided by the block length in bits.
+ * But this also depends on the state of the FSM ... how many bits are
+ * left before termination.
+ */
+
+void gr_streams_encode_turbo::forecast
+(int noutput_items,
+ gr_vector_int &ninput_items_required)
+{
+  int ninput_items = d_encoder->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_streams_encode_turbo::general_work
+(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+  // FIXME: compute the actual number of output items (1 bit char's) created.
+
+  size_t t_n_input_items = d_encoder->compute_n_input_bits (noutput_items);
+  size_t t_n_output_items = d_encoder->compute_n_output_bits (t_n_input_items);
+
+  assert (t_n_output_items == ((size_t)noutput_items));
+
+  // "work" is handled by the encoder; which returns the actual number
+  // of input items (1-bit char's) used.
+
+  t_n_input_items = d_encoder->encode ((const char **)(&input_items[0]), 
+                                      (char **)(&output_items[0]),
+                                      (size_t) noutput_items);
+
+  // consume the number of used input items on all input streams
+
+  consume_each (t_n_input_items);
+
+  // returns number of items written to each output stream
+
+  return (noutput_items);
+}

Index: lib/gr_streams_encode_turbo.h
===================================================================
RCS file: lib/gr_streams_encode_turbo.h
diff -N lib/gr_streams_encode_turbo.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/gr_streams_encode_turbo.h       9 Jul 2006 16:15:17 -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.
+ */
+
+#ifndef INCLUDED_GR_STREAMS_ENCODE_TURBO_H
+#define INCLUDED_GR_STREAMS_ENCODE_TURBO_H
+
+#include <gr_block.h>
+#include <gr_streams_encode_convolutional.h>
+
+#if 0
+#include <libecc/encoder_turbo_ic1_ic1.h>
+#else
+#include <libecc/encoder_turbo.h>
+#endif
+
+/*!
+ * \brief Encode the incoming stream(s) using a turbo encoder
+ *
+ * input: streams of char, one stream per input as defined by the
+ *     instantiated code, using only the right-most justified bit as
+ *     the single input bit per input item.
+ *
+ * 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.
+ *
+ * n_code_inputs:
+ * n_code_outputs: the total number of code inputs and outputs for the
+ *     overall turbo encoder (not just the constituent codes).
+ *
+ * encoders: the constituent encoders to be used; all -should- be
+ *     configured with the same "block_size" and "termination", though
+ *     from this encoder's perspective it doesn't really matter.
+ *
+ * interleavers: the interleavers to use before each encoder,
+ *     respectively, except the first encoder which will not use an
+ *     interleaver.
+ */
+
+class gr_streams_encode_turbo;
+
+typedef boost::shared_ptr<gr_streams_encode_turbo>
+gr_streams_encode_turbo_sptr;
+
+gr_streams_encode_turbo_sptr
+gr_make_streams_encode_turbo
+(int n_code_inputs,
+ int n_code_outputs,
+ const std::vector<gr_streams_encode_convolutional_sptr> &encoders,
+ const std::vector<size_t> &interleavers);
+
+class gr_streams_encode_turbo : public gr_block
+{
+  friend gr_streams_encode_turbo_sptr
+  gr_make_streams_encode_turbo
+    (int n_code_inputs,
+     int n_code_outputs,
+     const std::vector<gr_streams_encode_convolutional_sptr> &d_encoders,
+     const std::vector<size_t> &d_interleavers);
+
+  gr_streams_encode_turbo
+    (int n_code_inputs,
+     int n_code_outputs,
+     const std::vector<gr_streams_encode_convolutional_sptr> &d_encoders,
+     const std::vector<size_t> &d_interleavers);
+
+  std::vector<gr_streams_encode_turbo_sptr> d_encoders;
+  std::vector<size_t> d_interleavers;
+  size_t d_n_encoders, d_block_size_bits;
+  bool d_do_termination;
+  encoder_turbo* d_encoder;
+
+public:
+  ~gr_streams_encode_turbo ();
+
+  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);
+};
+
+#endif /* INCLUDED_GR_STREAMS_ENCODE_TURBO_H */

Index: lib/gr_streams_encode_turbo.i
===================================================================
RCS file: lib/gr_streams_encode_turbo.i
diff -N lib/gr_streams_encode_turbo.i
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/gr_streams_encode_turbo.i       9 Jul 2006 16:15:17 -0000       1.1
@@ -0,0 +1,41 @@
+/* -*- 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,streams_encode_turbo);
+
+#include <gr_streams_encode_convolutional.h>
+
+gr_streams_encode_turbo_sptr
+gr_make_streams_encode_turbo
+(int n_code_inputs,
+ int n_code_outputs,
+ const std::vector<gr_streams_encode_convolutional_sptr> &encoders,
+ const std::vector<size_t> &interleavers);
+
+class gr_streams_encode_turbo : public gr_block
+{
+  gr_streams_encode_turbo
+  (int frame_size_bits,
+   int n_code_inputs,
+   const std::vector<gr_streams_encode_convolutional_sptr> &encoders,
+   const std::vector<size_t> &interleavers);
+};

Index: lib/libecc/decoder_viterbi_full_block.cc
===================================================================
RCS file: lib/libecc/decoder_viterbi_full_block.cc
diff -N lib/libecc/decoder_viterbi_full_block.cc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libecc/decoder_viterbi_full_block.cc    9 Jul 2006 16:15:17 -0000       
1.1
@@ -0,0 +1,1120 @@
+/* -*- 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_full_block.h"
+#include <assert.h>
+#include <iostream>
+#include <math.h>
+
+const int g_max_block_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_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 1
+
+#if DO_TIME_THOUGHPUT
+#include <mld/mld_timer.h>
+#endif
+#if DO_PRINT_DEBUG
+#include <mld/n2bs.h>
+#endif
+
+decoder_viterbi_full_block::decoder_viterbi_full_block
+(int sample_precision,
+ encoder_convolutional* l_encoder)
+  : decoder_viterbi (sample_precision, l_encoder)
+{
+  // verify that the block size is non-zero
+
+  if (d_block_size_bits == 0) {
+    std::cerr << "decoder_viterbi_full_block: Error: "
+      "Block size is 0, and must be positive for block decoding.\n";
+    assert (0);
+  }
+
+  // the traceback buffers are specific to the type of decoding
+  // (full/block, partial/block, partial/stream)
+
+  // create the traceback buffers; for full/block, use the total # of
+  // bits to decode + 1: each bit is represented by a transition
+  // between traceback elements.
+
+  d_n_traceback_els = d_n_total_inputs_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 blocks, 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];
+  }
+
+  if (DO_PRINT_DEBUG_INST) {
+    std::cout <<
+      "total # in bits / stream = " << d_n_total_inputs_per_stream << "\n" <<
+      "d_n_traceback_els        = " << d_n_traceback_els << "\n";
+  }
+
+  if (DO_PRINT_DEBUG_INST) {
+    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";
+      }
+    }
+  }
+}
+
+decoder_viterbi_full_block::~decoder_viterbi_full_block
+()
+{
+  // delete the traceback buffers
+
+  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
+decoder_viterbi_full_block::update_traceback__up
+(size_t from_state_ndx,
+ size_t to_state_ndx,
+ size_t l_input)
+{
+#if 0
+#if DO_PRINT_DEBUG
+  size_t t_state_print_bits = d_total_memory + 1;
+  size_t t_mem_print_bits = d_max_memory + 2;
+#endif
+  // update the traceback structure, depending on which variety it is
+  // doing full trellis before decoding; use d_out_buf
+
+  // get the current state & output state
+
+  traceback_t_ptr t_out_buf = &(d_out_buf[d_time_count]
+                               [from_state_ndx]);
+  traceback_t_ptr t_next_out_buf = &(d_out_buf[d_time_count+1]
+                                    [to_state_ndx]);
+  if (DO_PRINT_DEBUG_UP_1) {
+    std::cout << "d_o_b[" << d_time_count+1 << "] => d_o_b prev\n" <<
+      "ndx[" << n << "] == " << from_state_ndx <<
+      ", s[" << n2bs(from_state_ndx,t_state_print_bits) <<
+      "]: max_ndx = " <<
+      n2bs(t_state->d_max_state_ndx,t_state_print_bits) <<
+      ", input = " << n2bs(l_input, d_n_code_inputs+1) <<
+      ": " << t_next_out_buf << " => " << t_out_buf << "\n";
+  }
+
+  // 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 = l_input;
+#endif
+}
+
+void
+decoder_viterbi_full_block::update_traceback__middle
+()
+{
+#if 0
+
+#if DO_PRINT_DEBUG
+  size_t t_state_print_bits = d_total_memory + 1;
+  size_t t_mem_print_bits = d_max_memory + 2;
+#endif
+  // 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
+
+  state_t_ptr 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";
+  }
+
+  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";
+    }
+
+    t_out_buf->d_prev = t_prev_out_buf;
+    t_out_buf->d_inputs = t_state->d_max_input;
+  }
+
+#endif
+}
+
+void
+decoder_viterbi_full_block::update_traceback__term
+()
+{
+#if 0
+
+#if DO_PRINT_DEBUG
+  size_t t_state_print_bits = d_total_memory + 1;
+  size_t t_mem_print_bits = d_max_memory + 2;
+#endif
+// 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
+       }
+
+#endif
+}
+
+void
+decoder_viterbi_full_block::decode_private
+(const char** in_buf,
+ char** out_buf)
+{
+#if 0
+
+#if DO_TIME_THOUGHPUT
+  struct timeval t_tp;
+  start_timer (&t_tp);
+#endif
+#if DO_PRINT_DEBUG
+  size_t t_state_print_bits = d_total_memory + 1;
+  size_t t_mem_print_bits = d_max_memory + 2;
+#endif
+// setup variables for quicker access
+  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
+
+           update_traceback__up (t_state, t_to_state, q);
+
+           // next (for) input value
+         }
+
+         // next (for) "up_term" state
+       }
+
+       // increment the input buffer indices
+
+       increment_input_indices (false);
+
+       // increment the time counter
+
+        d_time_count++;
+
+       // change which up-term index to use
+
+        d_up_term_ndx ^= 1;
+
+       // increase the number of states to be used
+
+        t_n_up_down_ndx <<= d_n_code_inputs;
+
+       // change which d_states' index to use as starting
+
+        d_states_ndx ^= 1;
+
+       // next (while) input
+      }
+
+      // 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";
+       }
+        d_fsm = fsm_dec_doing_middle;
+      }
+      if (DO_PRINT_DEBUG_FSM) {
+       std::cout << "Exited fsm_dec_doing_up\n";
+      }
+      break;
+
+    case (fsm_dec_doing_middle):
+      if (DO_PRINT_DEBUG_FSM) {
+       std::cout << "Entered fsm_dec_doing_middle\n";
+      }
+
+      // stay in this state until a full block (+ optional
+      // termination) of input metrics is reached, or until there are
+      // no more input metrics to parse
+
+      while ((d_time_count < d_block_size_bits) &
+            (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_block_size_bits << "\nd_states_ndx = " << d_states_ndx << "\n";
+       }
+
+       // 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";
+         }
+
+         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";
+           }
+
+           // 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";
+             }
+              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;
+            }
+           // next (for) input value
+         }
+         // next (for) state
+       }
+
+       // done with all states and all inputs;
+       // update the traceback buffers
+
+       update_traceback__middle ();
+
+       // increment the input buffer indices
+
+       increment_input_indices ();
+
+       // increment the time counter
+
+        d_time_count++;
+
+       // check (while) staying in this fsm state or not
+      }
+
+      if ((d_block_size_bits != 0) &
+          (d_time_count == d_block_size_bits)) {
+       if (DO_PRINT_DEBUG_FSM) {
+         std::cout << "Setting FSM to fsm_dec_doing_term\n";
+       }
+        d_fsm = fsm_dec_doing_term;
+      }
+      if (DO_PRINT_DEBUG_FSM) {
+       std::cout << "Exited fsm_dec_doing_middle\n";
+      }
+      break;
+
+    case (fsm_dec_doing_term):
+      if (DO_PRINT_DEBUG_FSM) {
+       std::cout << "Entered fsm_dec_doing_term\n";
+      }
+
+      // set the "next" up_down index to the end of their states
+
+      size_t t_time_count = d_max_memory - (d_time_count - d_block_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 metrics
+      // are reached; exit if we run out of input metrics 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";
+       }
+
+       // FIXME: loop over just the "0" inputs
+
+       // use the "to" states, 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";
+         }
+
+         // 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";
+           }
+           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
+       }
+
+       // update the traceback buffers
+
+       update_traceback__term ();
+       increment_input_indices (false);
+
+       // 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";
+       }
+       d_fsm = fsm_dec_output;
+      }
+      if (DO_PRINT_DEBUG_FSM) {
+       std::cout << "Exited fsm_dec_doing_term\n";
+      }
+      break;
+
+    case (fsm_dec_output):
+      if (DO_PRINT_DEBUG_FSM) {
+       std::cout << "Entered fsm_dec_output.\n";
+      }
+
+      // 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_block_size_bits / g_num_bits_per_byte));
+      int t_next_out_bit_shift = (t_out_bit_shift +
+                                 (d_block_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_block_size_bits << " bits == " <<
+       (d_block_size_bits / g_num_bits_per_byte) << " Byte" <<
+       ((d_block_size_bits / g_num_bits_per_byte) != 1 ? "s" : "") <<
+       " + " << (d_block_size_bits % g_num_bits_per_byte) << " bit" <<
+       ((d_block_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_block_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_block_bit_ndx = d_block_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_block_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_block_size_bits / g_num_bits_per_byte) +
+                               ((d_block_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_block_size_bits << " bit" <<
+         (d_block_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_block_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 blocks 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
+  }
+
+#endif
+
+#if DO_TIME_THOUGHPUT
+  u_long d_t = end_timer (&t_tp);
+
+  std::cout << "decoder_viterbi_full_block: Completed " << t_ninput_items <<
+    " bits in " << d_t << " usec => " <<
+    1e6*(((double)(t_ninput_items))/((double) d_t)) <<
+    " b/s\n";
+#endif
+}

Index: lib/libecc/decoder_viterbi_full_block.h
===================================================================
RCS file: lib/libecc/decoder_viterbi_full_block.h
diff -N lib/libecc/decoder_viterbi_full_block.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libecc/decoder_viterbi_full_block.h     9 Jul 2006 16:15:17 -0000       
1.1
@@ -0,0 +1,78 @@
+/* -*- 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_FULL_BLOCK_H
+#define INCLUDED_DECODER_VITERBI_FULL_BLOCK_H
+
+#include "decoder_viterbi.h"
+
+class decoder_viterbi_full_block : public decoder_viterbi
+{
+/*!
+ * \brief Decode the incoming streams using a Viterbi-style decoder,
+ *     doing full trellis block decoding before putting out
+ *     any bits
+ *
+ * input: streams of metrics, two per code output: one for the 0-bit
+ *     metrics and the other for the 1-bit metric.
+ *
+ * output: stream(s) of output bits
+ */
+
+public:
+  decoder_viterbi_full_block (int sample_precision,
+                             encoder_convolutional* l_encoder);
+
+  virtual ~decoder_viterbi_full_block ();
+
+protected:
+  virtual void decode_private (const char** in_buf, char** out_buf);
+  virtual void update_traceback__up (size_t from_state_ndx,
+                                    size_t to_state_ndx,
+                                    size_t l_input);
+  virtual void update_traceback__middle ();
+  virtual void update_traceback__term ();
+
+/*
+ * 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;
+
+/*
+ * d_n_total_inputs_per_stream: how many bits to store for each
+ *     state to determine the best decoder-output (encoder-input) bits 
+ */
+  size_t d_n_inputs_per_stream;
+  traceback_t_hdl d_out_buf;
+};
+
+#endif /* INCLUDED_DECODER_VITERBI_FULL_BLOCK_H */

Index: lib/libecc/decoder_viterbi_full_block_i1_ic1.cc
===================================================================
RCS file: lib/libecc/decoder_viterbi_full_block_i1_ic1.cc
diff -N lib/libecc/decoder_viterbi_full_block_i1_ic1.cc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libecc/decoder_viterbi_full_block_i1_ic1.cc     9 Jul 2006 16:15:17 
-0000       1.1
@@ -0,0 +1,162 @@
+/* -*- 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_full_block_i1_ic1.h"
+#include <assert.h>
+#include <iostream>
+#include <math.h>
+
+const int g_max_block_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_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 1
+
+#if DO_TIME_THOUGHPUT
+#include <mld/mld_timer.h>
+#endif
+#if DO_PRINT_DEBUG
+#include <mld/n2bs.h>
+#endif
+
+// FIXME
+
+size_t
+decoder_viterbi_full_block_i1_ic1::compute_n_output_bits
+(size_t n_input_items)
+{
+  assert (0);
+  return (0);
+}
+
+/*
+ * Compute the number of input items (metrics) needed to produce
+ * 'noutput' bits.  For convolutional decoders, there is 1
+ * bit output per metric input per stream, with the addition of a some
+ * metrics for trellis termination if selected.  Without termination,
+ * there is exactly 1:1 input to output (1 metric in to 1 bit out),
+ * no matter the encoding type.
+ *
+ * if (not terminating), then get the number of output bits.
+ *
+ * otherwise, find the number of blocks (not necessarily an integer),
+ * and then compute the number of input metrics (including termination)
+ * required to produce those blocks.  Subtract the number of bits
+ * leftover from the previous computation, then find the number of input
+ * metrics, ceil'd to make sure there are enough.
+ */
+
+size_t
+decoder_viterbi_full_block_i1_ic1::compute_n_input_metrics
+(size_t n_output_bits)
+{
+  int t_ninput_items = 0;
+  int t_noutput_bits = ((int) n_output_bits) - ((int) d_n_saved_bits);
+
+  // if there are enough saved bits, just use those, no inputs required
+
+  if (t_noutput_bits <= 0)
+    return (0);
+
+  // remove any bits already in the decoding trellis
+
+  if (d_time_count != 0) {
+    int t_time_bits = ((d_time_count > d_block_size_bits) ? 0 :
+                      d_block_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 blocks, ceil'd to the next higher integer
+
+    int t_nblocks = (int) ceilf (((float) t_noutput_bits) /
+                                ((float) d_block_size_bits));
+
+    // find the number of required input bits
+
+    t_ninput_items += t_nblocks * d_n_total_inputs_per_stream;
+  }
+
+  return (t_ninput_items);
+}
+
+// FIXME, from here down dummies to get correct compiling; for testing
+// purposes only.
+
+void
+decoder_viterbi_full_block_i1_ic1::increment_input_indices
+(bool while_decoding)
+{
+  if (while_decoding)
+    std::cout << "foo!";
+
+#if 0
+// 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;
+#endif
+}
+
+void
+decoder_viterbi_full_block_i1_ic1::increment_output_indices
+(bool while_decoding)
+{
+  if (while_decoding)
+    std::cout << "bar!";
+}
+
+void
+decoder_viterbi_full_block_i1_ic1::output_bit
+(char t_out_bit,
+ char** out_buf,
+ size_t t_output_stream)
+{
+  if (t_out_bit)
+    std::cout << "mop!";
+}

Index: lib/libecc/decoder_viterbi_full_block_i1_ic1.h
===================================================================
RCS file: lib/libecc/decoder_viterbi_full_block_i1_ic1.h
diff -N lib/libecc/decoder_viterbi_full_block_i1_ic1.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libecc/decoder_viterbi_full_block_i1_ic1.h      9 Jul 2006 16:15:17 
-0000       1.1
@@ -0,0 +1,66 @@
+/* -*- 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_FULL_BLOCK_IC1_H
+#define INCLUDED_DECODER_VITERBI_FULL_BLOCK_IC1_H
+
+#include "decoder_viterbi_full_block.h"
+
+class decoder_viterbi_full_block_i1_ic1 : public decoder_viterbi_full_block
+{
+/*!
+ * class decoder_viterbi_full_block_i1_ic1 :
+ *     public decoder_viterbi_full_block
+ *
+ * Decode the incoming metrics using a Viterbi-style decoder, doing
+ *     full trellis block decoding before putting out any bits
+ *
+ * input is "i1": one stream per input (as defined by the
+ *     code-output), with one metric per input item.
+ *
+ * output is "ic1": streams of char, one stream per output (as defined
+ *     by the code-input), using only the right-most justified (LSB?)
+ *     bit as the single output bit per output item.
+ *
+ * The rest of the options are outlined in the inherited classes'
+ *     header files.
+ */
+
+public:
+  inline decoder_viterbi_full_block_i1_ic1
+  (int sample_precision,
+   encoder_convolutional* l_encoder)
+    : decoder_viterbi_full_block (sample_precision, l_encoder) {};
+
+  virtual ~decoder_viterbi_full_block_i1_ic1 () {};
+
+  virtual size_t compute_n_input_metrics (size_t n_output_bits);
+  virtual size_t compute_n_output_bits (size_t n_input_metrics);
+
+protected:
+  virtual void increment_input_indices (bool while_decoding);
+  virtual void output_bit (char t_out_bit, char** out_buf,
+                          size_t t_output_stream);
+  virtual void increment_output_indices (bool while_decoding);
+};
+
+#endif /* INCLUDED_DECODER_VITERBI_FULL_BLOCK_I1_IC1_H */

Index: lib/libecc/encoder_turbo.cc
===================================================================
RCS file: lib/libecc/encoder_turbo.cc
diff -N lib/libecc/encoder_turbo.cc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libecc/encoder_turbo.cc 9 Jul 2006 16:15:17 -0000       1.1
@@ -0,0 +1,52 @@
+#include "encoder_turbo.h"
+
+encoder_turbo::encoder_turbo
+(int n_code_inputs,
+ int n_code_outputs,
+ const std::vector<encoder_convolutional*> &encoders,
+ const std::vector<size_t> &interleavers)
+{
+  // need error checking on inputs
+
+  d_encoders = encoders;
+  d_interleavers = interleavers;
+}
+
+// dummy stuff for now to test std::vector<gr_streams_convolutional...> stuff
+
+size_t
+encoder_turbo::compute_n_input_bits
+(size_t n_output_bits)
+{
+  return (0);
+}
+
+size_t
+encoder_turbo::compute_n_output_bits
+(size_t n_input_bits)
+{
+  return (0);
+}
+
+void
+encoder_turbo::encode_private
+(const char** in_buf,
+ char** out_buf)
+{
+}
+
+char
+encoder_turbo::get_next_bit
+(const char** in_buf,
+ size_t code_input_n)
+{
+  return (0);
+}
+
+void
+encoder_turbo::output_bit
+(char t_out_bit,
+ char** out_buf,
+ size_t t_output_stream)
+{
+}

Index: lib/libecc/encoder_turbo.h
===================================================================
RCS file: lib/libecc/encoder_turbo.h
diff -N lib/libecc/encoder_turbo.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libecc/encoder_turbo.h  9 Jul 2006 16:15:17 -0000       1.1
@@ -0,0 +1,147 @@
+/* -*- 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_TURBO_H
+#define INCLUDED_ENCODER_TURBO_H
+
+#include "encoder_convolutional.h"
+#include <vector>
+
+class encoder_turbo : public encoder
+{
+public:
+/*!
+ * class encoder_turbo : public encoder
+ *
+ * Encode the incoming streams using a turbo encoder; This is a
+ *     virtual class which defines the basics of a turbo encoder, but
+ *     not how input and output bits are handled.  These features are
+ *     all defined by overriding methods appropriately.
+ *
+ * n_code_inputs:
+ * n_code_outputs: the total number of code inputs and outputs for the
+ *     overall turbo encoder (not just the constituent codes).
+ *
+ * encoders: the constituent encoders to be used; all -should- be
+ *     configured with the same "block_size" and "termination", though
+ *     from this encoder's perspective it doesn't really matter.
+ *
+ * interleavers: the interleavers to use before each encoder,
+ *     respectively, except the first encoder which will not use an
+ *     interleaver.
+ */
+
+  encoder_turbo
+  (int n_code_inputs,
+   int n_code_outputs,
+   const std::vector<encoder_convolutional*> &encoders,
+   const std::vector<size_t> &interleavers);
+
+  virtual ~encoder_turbo () {};
+
+/* for remote access to internal info */
+
+  inline bool do_termination () {return (d_do_termination);};
+
+#if 1
+  virtual size_t compute_n_input_bits (size_t n_output_bits);
+  virtual size_t compute_n_output_bits (size_t n_input_bits);
+#endif
+
+protected:
+/*
+ * fsm_enc_turbo_t: finite state machine for the turbo encoder;
+ *     output happens all the time, so that's built-in to each state.
+ *
+ * fsm_enc_turbo_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_turbo_doing_input: doing encoding inside the trellis
+ *
+ * fsm_enc_turbo_doing_term: termination trellis, if requested
+ */
+
+  enum fsm_enc_turbo_t {
+    fsm_enc_turbo_init, fsm_enc_turbo_doing_input, fsm_enc_turbo_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
+#if 1
+  // temporary just to get full compilation
+
+  virtual void encode_private (const char** in_buf, char** out_buf);
+  virtual char get_next_bit (const char** in_buf, size_t code_input_n);
+  virtual void output_bit (char t_out_bit, char** out_buf,
+                          size_t t_output_stream);
+#else
+  virtual void encode_private (const char** in_buf, char** out_buf) = 0;
+  virtual void encode_loop (const char** in_buf, char** out_buf,
+                           size_t* which_counter, size_t how_many) = 0;
+  virtual char get_next_bit (const char** in_buf, size_t code_input_n) = 0;
+  virtual char get_next_bit__term (size_t code_input_n) = 0;
+
+  // 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;
+#endif
+
+  // variables
+
+  fsm_enc_turbo_t d_fsm_state;
+  bool d_do_termination;
+  size_t d_max_memory, d_n_memories;
+
+  std::vector<encoder_convolutional*> d_encoders;
+  std::vector<size_t> d_interleavers;
+};
+
+#endif /* INCLUDED_ENCODER_TURBO_H */

Index: python/qa_test_encoder_convolutional_1.py
===================================================================
RCS file: python/qa_test_encoder_convolutional_1.py
diff -N python/qa_test_encoder_convolutional_1.py
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ python/qa_test_encoder_convolutional_1.py   9 Jul 2006 16:15:17 -0000       
1.1
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+#
+# 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.
+# 
+
+from gnuradio import ecc, gr
+from gnuradio.eng_option import eng_option
+
+def main ():
+       frame_size = 10
+       enc_code_in_chan = 2
+       code_generators = [05, 04] #, 03, 04] # , 0, 07]
+       enc_code_out_chan = len (code_generators) / enc_code_in_chan
+
+       ss_enc = ecc.streams_encode_convolutional (frame_size,
+                                                  enc_code_in_chan,
+                                                  enc_code_out_chan,
+                                                  code_generators)
+
+if __name__ == '__main__':
+    main ()

Index: lib/gr_decoder_viterbi_block_full.cc
===================================================================
RCS file: lib/gr_decoder_viterbi_block_full.cc
diff -N lib/gr_decoder_viterbi_block_full.cc
--- lib/gr_decoder_viterbi_block_full.cc        5 Jul 2006 17:49:58 -0000       
1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,208 +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_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: lib/gr_decoder_viterbi_block_full.h
===================================================================
RCS file: lib/gr_decoder_viterbi_block_full.h
diff -N lib/gr_decoder_viterbi_block_full.h
--- lib/gr_decoder_viterbi_block_full.h 5 Jul 2006 17:49:58 -0000       1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,120 +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_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: lib/gr_decoder_viterbi_block_full.i
===================================================================
RCS file: lib/gr_decoder_viterbi_block_full.i
diff -N lib/gr_decoder_viterbi_block_full.i
--- lib/gr_decoder_viterbi_block_full.i 5 Jul 2006 17:49:58 -0000       1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,43 +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,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: lib/libecc/decoder_viterbi_block_full.cc
===================================================================
RCS file: lib/libecc/decoder_viterbi_block_full.cc
diff -N lib/libecc/decoder_viterbi_block_full.cc
--- lib/libecc/decoder_viterbi_block_full.cc    5 Jul 2006 17:49:58 -0000       
1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,1484 +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;
-
-#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: lib/libecc/decoder_viterbi_block_full.h
===================================================================
RCS file: lib/libecc/decoder_viterbi_block_full.h
diff -N lib/libecc/decoder_viterbi_block_full.h
--- lib/libecc/decoder_viterbi_block_full.h     5 Jul 2006 17:49:58 -0000       
1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,107 +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_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: lib/libecc/decoder_viterbi_block_full_ic1.h
===================================================================
RCS file: lib/libecc/decoder_viterbi_block_full_ic1.h
diff -N lib/libecc/decoder_viterbi_block_full_ic1.h
--- lib/libecc/decoder_viterbi_block_full_ic1.h 5 Jul 2006 17:49:58 -0000       
1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,58 +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_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 */




reply via email to

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