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/libecc/encode...


From: Michael Dickens
Subject: [Commit-gnuradio] gr-error-correcting-codes/src lib/libecc/encode...
Date: Wed, 12 Jul 2006 23:43:38 +0000

CVSROOT:        /sources/gnuradio
Module name:    gr-error-correcting-codes
Changes by:     Michael Dickens <michaelld>     06/07/12 23:43:38

Modified files:
        src/lib/libecc : encoder.h encoder_convolutional.cc 
                         encoder_convolutional.h 
                         encoder_convolutional_ic1_ic1.cc 
                         encoder_convolutional_ic1_ic1.h 
        src/python     : qa_test_encoder_convolutional_1.py 

Log message:
        Still a work in progress; likely won't function properly as a block,
        but at least instantiates correctly and can provide debugging
        comments to check for correctness.
        
        Initial changes to allow for correct # delays required;
        added checking of the 2 primary realizations, and selecting
        the better of the 2.  Revised the encoding programming to
        make use of the selected realization, as well as if doing
        feedback or not (thus, 4 possible encoders).

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder.h?cvsroot=gnuradio&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.cc?cvsroot=gnuradio&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.h?cvsroot=gnuradio&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.cc?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.h?cvsroot=gnuradio&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gr-error-correcting-codes/src/python/qa_test_encoder_convolutional_1.py?cvsroot=gnuradio&r1=1.1&r2=1.2

Patches:
Index: lib/libecc/encoder.h
===================================================================
RCS file: /sources/gnuradio/gr-error-correcting-codes/src/lib/libecc/encoder.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- lib/libecc/encoder.h        9 Jul 2006 16:15:17 -0000       1.4
+++ lib/libecc/encoder.h        12 Jul 2006 23:43:38 -0000      1.5
@@ -55,10 +55,17 @@
   inline size_t n_code_outputs () {return (d_n_code_outputs);};
 
 protected:
+  /* encode_private: encode the given in_buf and write the output bits
+   * to the out_buf, using internal class variables.  This function is
+   * called from the publically available "encode()" methods, which
+   * first set the internal class variables before executing.
+   */
+
   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;
+
+  /* inheriting methods need to figure out what makes the most sense
+   * for them in terms of getting new inputs and writing outputs.
+   */
 
   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;

Index: lib/libecc/encoder_convolutional.cc
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.cc,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- lib/libecc/encoder_convolutional.cc 9 Jul 2006 18:40:42 -0000       1.5
+++ lib/libecc/encoder_convolutional.cc 12 Jul 2006 23:43:38 -0000      1.6
@@ -40,6 +40,7 @@
 
 static const int g_max_block_size_bits = 10000000;
 static const int g_max_num_streams = 10;
+static const int g_num_bits_per_byte = 8;
 
 void encoder_convolutional::encoder_convolutional_init
 (int block_size_bits,
@@ -98,6 +99,10 @@
 
   d_do_feedback = (code_feedback != NULL);
 
+  // set the initial FSM state to 'init'
+
+  d_fsm_state = fsm_enc_conv_init;
+
   // create the class block variables
 
   d_block_size_bits = block_size_bits;
@@ -123,7 +128,7 @@
   // interger type, at least 32 bits) bits to represent memory and the
   // code, as it makes the operations quite simple the state vectors.
 
-  // d_states is a "matrix" [#input by #outputs] containing pointers
+  // d_states is a "matrix" [#input by #outputs] containing indices
   // to memory_t's; this is done to make feedback function properly,
   // and doesn't effect the computation time for feedforward.  The
   // issue is that any code with the same feedback can use the same
@@ -134,7 +139,7 @@
   // encoder uses the correct memory.
   // reference the matrix using "maoi(i,o)" ... see .h file.
 
-  d_states.assign (d_n_code_inputs * d_n_code_outputs, NULL);
+  d_states_ndx.assign (d_n_code_inputs * d_n_code_outputs, 0);
 
   // code generators (feedforward part) are [#inputs x #outputs],
   // always - one for each I/O combination.
@@ -171,48 +176,13 @@
     }
   }
 
-  if (d_do_feedback == true) {
-    // resize the memory and states to the max size, worst case;
-
-    // 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]);
-  }
 
   // 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)];
+      d_code_generators[maio(m,n)] = code_generators[maio(m,n)];
 
   // check the input FF (and FB) code generators for correctness, and
   // find the minimum memory configuration: combining via a single
@@ -236,7 +206,7 @@
   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)];
+      t_all_inputs_zero |= d_code_generators[maio(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
@@ -253,7 +223,7 @@
   for (size_t m = 0; m < d_n_code_inputs; m++) {
     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)];
+      t_all_outputs_zero |= d_code_generators[maio(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
@@ -265,193 +235,117 @@
     }
   }
 
-#if 0
-I GOT TO HERE!
-
-  // 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
-
-      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;
-      // 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;
-
-
-
-       // 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
+  // create the inputs and outputs buffers
 
-         d_code_feedback[l_n_unique_fb] = t_save_code;
-         d_input_num[l_n_unique_fb] = m;
+  d_current_inputs.assign (d_n_code_inputs, 0);
+  d_current_outputs.assign (d_n_code_outputs, 0);
 
-         // update the "or" of all unique memories
 
-         t_all_inputs_one |= t_save_code;
 
-         // find the memory requirement for this code feedback
+  // still need to fill in:
+  //  d_max_delay, d_n_memories, d_total_n_delays,
+  //  d_code_feedback (if FB), d_io_num, d_max_mem_masks (if SIAO),
+  //  d_states_ndx, d_do_encode_soai
 
-         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;
+  // check and compute memory requirements in order to determine which
+  // realization uses the least memory; create and save findings to
+  // not have to re-do these computations later.
 
-         // increase the number of unique feedback codes
-
-         d_n_memories++;
-       }
-
-
-
-      }
+  // single output, all inputs (SOAI) realization:
+  // reset the global parameters
 
+  d_code_feedback.assign (d_n_code_inputs * d_n_code_outputs, 0);
+  d_n_delays.assign (d_n_code_inputs * d_n_code_outputs, 0);
+  d_io_num.assign (d_n_code_inputs * d_n_code_outputs, 0);
+  d_states_ndx.assign (d_n_code_inputs * d_n_code_outputs, 0);
+  d_max_delay = d_total_n_delays = d_n_memories = 0;
+  d_do_encode_soai = true;
 
+  for (size_t n = 0; n < d_n_code_outputs; n++) {
+    size_t t_max_mem = 0;
+    size_t t_n_unique_fb_prev_start = d_n_memories;
 
+    for (size_t m = 0; m < d_n_code_inputs; m++)
+      get_memory_requirements (m, n, t_max_mem,
+                              t_n_unique_fb_prev_start, code_feedback);
 
+    if (d_do_feedback == false) {
+      // not feedback; just store memory requirements for this output
+      d_total_n_delays += t_max_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_soai = t_memories;
-  size_t t_max_mem_soai = oa_max_mem;
-  size_t t_total_mem_soai = t_total_mem;
+  std::vector<size_t> t_fb_generators_soai, t_n_delays_soai, t_io_num_soai;
+  std::vector<size_t> t_states_ndx_soai;
+  size_t t_max_delay_soai, t_total_n_delays_soai, t_n_memories_soai;
+
+  t_fb_generators_soai = d_code_feedback;
+  t_n_delays_soai = d_n_delays;
+  t_io_num_soai = d_io_num;
+  t_states_ndx_soai = d_states_ndx;
+  t_n_memories_soai = d_n_memories;
+  t_total_n_delays_soai = d_total_n_delays;
+  t_max_delay_soai = d_max_delay;
 
-  // single input, all outputs (siao)
+  // single input, all outputs (SIAO) realization
+  // reset the global parameters
+
+  d_code_feedback.assign (d_n_code_inputs * d_n_code_outputs, 0);
+  d_n_delays.assign (d_n_code_inputs * d_n_code_outputs, 0);
+  d_io_num.assign (d_n_code_inputs * d_n_code_outputs, 0);
+  d_states_ndx.assign (d_n_code_inputs * d_n_code_outputs, 0);
+  d_max_delay = d_total_n_delays = d_n_memories = 0;
+  d_do_encode_soai = false;
 
-  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)];
+    size_t t_n_unique_fb_prev_start = d_n_memories;
 
-       // find the memory requirement for this code generator
+    for (size_t n = 0; n < d_n_code_outputs; n++)
+      get_memory_requirements (m, n, t_max_mem,
+                              t_n_unique_fb_prev_start, code_feedback);
 
-       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;
+    if (d_do_feedback == false) {
+      // not feedback; just store memory requirements for this output
+      d_total_n_delays += t_max_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 << "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";
+    std::cout <<
+      "  t_total_n_delays_siao  = " << d_total_n_delays << "\n"
+      "  t_total_n_delays_soai  = " << t_total_n_delays_soai << "\n";
   }
 
   // pick which realization to use; soai is preferred since it's faster
   // ... but unfortunately it's also less likely
 
-  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;
+  if (d_total_n_delays < t_total_n_delays_soai) {
+    // use siao
+    d_do_encode_soai = false;
+    // nothing else to do yet, since the global variables already hold
+    // the correct values.
   } 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;
 
+    d_code_feedback = t_fb_generators_soai;
+    d_n_delays = t_n_delays_soai;
+    d_io_num = t_io_num_soai;
+    d_states_ndx = t_states_ndx_soai;
+    d_n_memories = t_n_memories_soai;
+    d_total_n_delays = t_total_n_delays_soai;
+    d_max_delay = t_max_delay_soai;
   }
 
-  // store this maximum memory order (e.g. "2" -> D^2)
-
-  d_max_delay = t_max_mem - 1;
-
   if (DO_PRINT_DEBUG) {
     std::cout <<
-      "d_max_delay      = " << d_max_delay << "\n";
+      "  d_total_n_delays  = " << d_total_n_delays << "\n"
+      "  d_max_delay       = " << d_max_delay << "\n"
+      "  d_do_encode_soai  = " << 
+      ((d_do_encode_soai == true) ? "true" : "false") << "\n";
   }
 
   // make sure the block length makes sense, #2
@@ -466,130 +360,126 @@
     assert (0);
   }
 
+  if (d_do_encode_soai == false) {
+    // create the max_mem_mask to be used in encoding
 
+    d_max_mem_masks.assign (d_n_memories, 0);
 
+    for (size_t m = 0; m < d_n_memories; m++) {
+      if (d_n_delays[m] == sizeof (memory_t) * g_num_bits_per_byte)
+       d_max_mem_masks[m] = -1;
+      else
+       d_max_mem_masks[m] = (2 << d_n_delays[m]) - 1;
+    }
+  }
 
-  // check feedback portion, if it exists,
-  // for correctness & # of memories
+// FIXME:  STILL NEED TO parse START AND END MEMORY STATES;
+}
 
-  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.
+void
+encoder_convolutional::get_memory_requirements
+(size_t m,   // input number
+ size_t n,   // output number
+ size_t& t_max_mem,
+ size_t& t_n_unique_fb_prev_start,
+ const std::vector<int>* code_feedback)
+{
+  size_t t_in_code = d_code_generators[maio(m,n)];
 
-    if (d_do_feedback == true) {
+  // find the memory requirement for this code generator
 
-    // check the code_feedback for correctness & find the memory order
-    // t_max_mem will be the mamimum number of memories used by the
-    // feedback; code_feedback will be in "input" first order, which is
-    // what is required internally.
+  size_t t_code_mem_ff = max_bit_position (t_in_code);
 
-    size_t t_max_mem = d_n_memories = 0;
-    memory_t t_all_inputs_one = 0;
+  // check to see if this is bigger than any others in this row/column
 
-    for (size_t n = 0; n < d_n_code_outputs; n++) {
-      size_t t_n_unique_fb_prev_start = d_n_memories;
+  if (t_code_mem_ff > t_max_mem)
+    t_max_mem = t_code_mem_ff;
 
-      for (size_t m = 0; m < d_n_code_inputs; m++) {
-       size_t t_save_code = code_feedback[maio(m,n)];
-       size_t t_in_code = t_save_code;
+  if (DO_PRINT_DEBUG) {
+    std::cout << "c_g[" << m << "][" << n << "]{" <<
+      maio(m,n) << "} = " << n2bs(t_in_code, 8) <<
+      ", code_mem = " << t_code_mem_ff;
+  }
 
-       // check to make sure (code & 1) == 1; can't do this type of
-       // convolutional encoder without it!
+  // 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 ((t_in_code & 1) != 1) {
-         std::cerr << "encoder_convolutional: " <<
-           "All feedback codes must contain a '1' for the least "
-           "significant bit.\n";
-         assert (0);
+  if (d_do_feedback == true) {
+    if (DO_PRINT_DEBUG) {
+      std::cout << "\n";
        }
 
-       // find if this feedback is unique for this input;
+    // get the FB code, and OR with 1 to make sure it's valid
+
+    t_in_code = ((*code_feedback)[maio(m,n)]) | 1;
+
+    // find the memory requirement
+
+    size_t t_code_mem_fb = max_bit_position (t_in_code);
+
+    if (DO_PRINT_DEBUG) {
+      std::cout << "c_f[" << m << "][" << n << "]{" <<
+       maio(m,n) << "} = " << n2bs(t_in_code, 8) <<
+       ", code_mem = " << t_code_mem_fb;
+    }
+
+    // check to see if this feedback is unique
 
        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)
+      if (d_code_feedback[l_n_unique_fb] == t_in_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;
+      d_code_feedback[l_n_unique_fb] = t_in_code;
+      d_n_delays[l_n_unique_fb] = t_code_mem_fb;
 
          // increase the number of unique feedback codes
 
          d_n_memories++;
-       }
-
-       // create the new entry in d_states
 
-       d_states[maio(m,n)] = &(d_memory[l_n_unique_fb]);
-      }
-    }
-
-      // check to see if the feedback's memory requirements are
-      // greater than the feedforward's; warn the user (not sure why,
-      // but it seems like a good idea).
+      // store memory requirements for this output
 
-      if (--t_max_mem > d_max_delay) {
-       std::cout << "encoder_convolutional: Warning: " <<
-         "Feedback using more memory than feedforward.\n";
-       d_max_delay = t_max_mem;
+      if (t_max_mem < t_code_mem_fb)
+       t_max_mem = t_code_mem_fb;
+      d_total_n_delays += t_max_mem;
 
-       // make sure the block length makes sense, #2
+      if (DO_PRINT_DEBUG) {
+       std::cout << ",  uq # " << l_n_unique_fb <<
+         ", tot_mem = " << d_total_n_delays;
+      }
+    } else {
+      // not a unique feedback, but the FF might require more memory
 
-       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);
+      if (DO_PRINT_DEBUG) {
+       std::cout << ", !uq # " << l_n_unique_fb <<
+         " = " << d_n_delays[l_n_unique_fb];
        }
 
-       // create the memory mask for this code generator
+      if (d_n_delays[l_n_unique_fb] < t_code_mem_ff) {
+       d_total_n_delays += (t_code_mem_ff - d_n_delays[l_n_unique_fb]);
+       d_n_delays[l_n_unique_fb] = t_code_mem_ff;
 
-       d_max_mem_mask = (2 << d_max_delay) - 1;
+       if (DO_PRINT_DEBUG) {
+         std::cout << " => " << d_n_delays[l_n_unique_fb] <<
+           ", tot_mem = " << d_total_n_delays;
       }
     }
   }
-
-  // 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;
-
+    d_io_num[l_n_unique_fb] = ((d_do_encode_soai == true) ? n : m);
+    d_states_ndx[maio(m,n)] = l_n_unique_fb;
+  }
   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.";
+    std::cout << "\n";
   }
-#endif
+  if (d_max_delay < t_max_mem)
+    d_max_delay = t_max_mem;
 }
 
 void
@@ -720,29 +610,16 @@
 }
 
 void
-encoder_convolutional::encode_loop
-(const char** in_buf,
- char** out_buf,
- 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
+  // single-output, all inputs; no feedback
 
   if (DO_PRINT_DEBUG) {
-    std::cout << "starting encode_loop_soai.\n";
+    std::cout << "Starting encode_loop_soai.\n";
   }
 
   while (((*which_counter) > 0) & (d_n_enc_bits < how_many)) {
@@ -752,50 +629,45 @@
        "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).
+    // get the next set of input bits from all streams;
+    // written into d_current_inputs
 
+    get_next_inputs (in_buf);
 
-#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));
+    // shift memories down by 1 bit to make room for feedback; no
+    // masking required.
 
-      ??? = t_mem;
+    for (size_t p = 0; p < d_n_memories; p++) {
+      d_memory[p] >>= 1;
+    }
 
-      // output this particular bit on this output stream
+    // for each input bit, if that bit's a '1', then XOR the code
+    // generators into the correct state's memory.
 
-      output_bit (t_out_bit, out_buf, m);
+    for (size_t m = 0; m < d_n_code_inputs; m++) {
+      if (d_current_inputs[m] == 1) {
+       for (size_t n = 0; n < d_n_code_outputs; n++) {
+         d_memory[d_states_ndx[maio(m,n)]] ^= d_code_generators[maio(m,n)];
+       }
+      }
+    }
 
-      // increment the input and output indices, if necessary, between
-      // output bits
+    // create the output bits, by XOR'ing the individual unique
+    // memory(ies) into the correct output bit
 
-      increment_io_indices (true);
+    for (size_t p = 0; p < d_n_memories; p++) {
+      d_current_outputs[d_io_num[p]] ^= ((char)(d_memory[p] & 1));
     }
-#endif
-    // increment the input and output counters, if necessary, between
-    // input bits
 
-    increment_io_indices (false);
+    // write the bits in d_current_outputs into the output buffer
+
+    write_output_bits (out_buf);
 
     // 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) {
@@ -804,17 +676,18 @@
 }
 
 void
-encoder_convolutional::encode_loop_siao
+encoder_convolutional::encode_loop_soai_fb
 (const char** in_buf,
  char** out_buf,
  size_t* which_counter,
  size_t how_many)
 {
-  // single input, all outputs
+  // single-output, all inputs; with feedback
 
   if (DO_PRINT_DEBUG) {
-    std::cout << "starting encode_loop_siao.\n";
+    std::cout << "Starting encode_loop_soai_fb.\n";
   }
+
   while (((*which_counter) > 0) & (d_n_enc_bits < how_many)) {
     if (DO_PRINT_DEBUG) {
       std::cout << "*w_c = " << (*which_counter) << ", "
@@ -822,209 +695,219 @@
        "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).
+    // get the next set of input bits from all streams;
+    // written into d_current_inputs
+
+    get_next_inputs (in_buf);
+
+    // shift memories down by 1 bit to make room for feedback; no
+    // masking required.
 
     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_delay+2) << "\n";
+      d_memory[p] >>= 1;
       }
 
-      d_memory[p] |= get_next_bit (in_buf, d_input_num[p]);
+    // for each input bit, if that bit's a '1', then XOR the code
+    // generators into the correct state's memory.
 
-      if (DO_PRINT_DEBUG) {
-       std::cout << "mem_out[" << p << "] = " <<
-         n2bs (d_memory[p], d_max_delay+2) << "\n";
+    for (size_t m = 0; m < d_n_code_inputs; m++) {
+      if (d_current_inputs[m] == 1) {
+       for (size_t n = 0; n < d_n_code_outputs; n++) {
+         d_memory[d_states_ndx[maio(m,n)]] ^= d_code_generators[maio(m,n)];
+       }
       }
     }
 
-    // now encode those inputs using the code generators,
-    // and output a single bit per output stream
+    // create the output bits, by XOR'ing the individual unique
+    // memory(ies) into the correct output bit
 
-    // loop over all outputs
+    for (size_t p = 0; p < d_n_memories; p++) {
+      d_current_outputs[d_io_num[p]] ^= ((char)(d_memory[p] & 1));
+    }
 
-    for (size_t q = 0; q < d_n_code_outputs; q++) {
-      memory_t t_out_result = 0;
+    // now that the output bits are fully created, XOR the FB back
+    // into the memories; the feedback bits have the LSB (&1) masked
+    // off already so that it doesn't contribute.
 
-      // loop over all inputs, xor'ing the result each time
+    for (size_t p = 0; p < d_n_memories; p++) {
+      if (d_current_outputs[d_io_num[p]] == 1) {
+       d_memory[p] ^= d_code_feedback[p];
+      }
+    }
 
-      for (size_t p = 0; p < d_n_code_inputs; p++) {
-       memory_t t_c_g = d_code_generators[maoi(p,q)];
-       memory_t t_mem = (*(d_states[maoi(p,q)]));
+    // write the bits in d_current_outputs into the output buffer
 
-       if (DO_PRINT_DEBUG) {
-         std::cout << "b_i = " <<
-           n2bs (t_out_result, d_max_delay+2) <<
-           ", st[" << p << "," << q << "] = " <<
-           n2bs (t_mem, d_max_delay+2) <<
-           ", cg[" << p << "," << q << "] = " <<
-           n2bs (t_c_g, d_max_delay+2) <<
-           ", st[] & cg[] = " <<
-           n2bs (t_mem & t_c_g, d_max_delay+2);
-       }
+    write_output_bits (out_buf);
 
-       t_out_result ^= (t_mem & t_c_g);
+    // increment the number of encoded bits for the current block, and
+    // the total number of bits for this running of "encode()"
 
-       if (DO_PRINT_DEBUG) {
-         std::cout << ", b_o = " <<
-           n2bs (t_out_result, d_max_delay+2) << '\n';
-       }
+    d_n_enc_bits++;
+    d_total_n_enc_bits++;
       }
+
       if (DO_PRINT_DEBUG) {
-       std::cout << "b_r = " << n2bs (t_out_result, d_max_delay+2);
+    std::cout << "ending encode_loop_soai.\n";
       }
+}
 
-      // sum the number of set bits, mod 2, for the output bit
-
-      char t_out_bit = sum_bits_mod2 (t_out_result, d_max_delay);
+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; no feedback
 
       if (DO_PRINT_DEBUG) {
-       std::cout << "t_out_bit = mo2_sum (b_o) = " <<
-         n2bs (t_out_result, 2);
+    std::cout << "starting encode_loop_siao.\n";
       }
 
-      // output this particular bit on this output stream
-
-      output_bit (t_out_bit, out_buf, q);
-
-      // increment the input and output indices, if necessary, between
-      // output bits
-
-      increment_io_indices (true);
+  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";
     }
 
-    // do post-encoding memory mods (e.g. feedback); at a minimum:
-    // must shift memory to get ready for a new input bit, and mask
-    // off any extra bit from shifting (beyond a particular input's
-    // memory bits).
+    // get the next set of input bits from all streams;
+    // written into d_current_inputs
 
-    // update memory with any feedback, then shift up (left) by 1 bit
-    // and mask the memory state to be ready for the next input
+    get_next_inputs (in_buf);
 
-    // loop over all memories, shift the memory left (up) by 1 bit and
-    // mask off any high non-memory bit(s)
+    // update the memories with the current input bits;
+    // pre-shift delays instead of post-shift to gather loops.
 
-    if (DO_PRINT_DEBUG) {
-      std::cout << "  doing memory shift and mask:\n";
-    }
+    // for each unique memory (1 per input), shift the delays and mask
+    // off the extra high bits; then XOR in the input bit.
 
     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_delay+2) << "\n";
+      memory_t t_mem = (d_memory[p] << 1) & d_max_mem_masks[p];
+      d_memory[p] = t_mem ^ ((memory_t)(d_current_inputs[d_io_num[p]]));
       }
 
-      d_memory[p] = (d_memory[p] << 1) & d_max_mem_mask;
+    // create the output bits: for each output, loop over all inputs,
+    // find the output bits for each encoder, and XOR each together
+    // then sum (would usually be sum then XOR, but they're mutable in
+    // base-2 and it's faster this way).
 
-      if (DO_PRINT_DEBUG) {
-       std::cout << "    mem_out[" << p << "] = " <<
-         n2bs (d_memory[p], d_max_delay+2) << "\n";
+    for (size_t n = 0; n < d_n_code_outputs; n++) {
+      memory_t t_mem = 0;
+      for (size_t m = 0; m < d_n_code_inputs; m++) {
+       t_mem ^= ((d_memory[d_states_ndx[maio(m,n)]]) &
+                 d_code_generators[maio(m,n)]);
       }
+      d_current_outputs[n] = sum_bits_mod2 (t_mem, d_max_delay);
     }
 
-    if (d_do_feedback == true) {
-
-      if (DO_PRINT_DEBUG) {
-       std::cout << "  doing feedback:\n";
+#if 0
+    for (size_t p = 0; p < d_n_memories; p++) {
+      memory_t t_mem = (d_memory[p] << 1);
+      d_memory[p] = (t_mem & d_max_mem_masks[p]);
       }
+#endif
 
-      // loop over all unique memories, creating the feedback bit for each
-      // and placing those bits in the state's second bit location
+    // write the bits in d_current_outputs into the output buffer
 
-      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_delay+2) << "\n";
-       }
+    write_output_bits (out_buf);
 
-       // do feedback with current memory
-       // get the memory, and zero out the second bit
+    // increment the number of encoded bits for the current block, and
+    // the total number of bits for this running of "encode()"
 
-       memory_t t_state = d_memory[p] & (d_max_mem_mask ^ 2);
+    d_n_enc_bits++;
+    d_total_n_enc_bits++;
+  }
 
        if (DO_PRINT_DEBUG) {
-         std::cout << "    t_state = mem[] & (" << d_max_mem_mask <<
-           " xor 2) = " << n2bs (t_state, d_max_delay+2) << "\n";
+    std::cout << "ending encode_loop_siao.\n";
        }
+}
 
-       // create the code feedback state
+void
+encoder_convolutional::encode_loop_siao_fb
+(const char** in_buf,
+ char** out_buf,
+ size_t* which_counter,
+ size_t how_many)
+{
+  // single input, all outputs; with feedback
 
-       memory_t t_fb_state = t_state & (d_code_feedback[p]);
+  if (DO_PRINT_DEBUG) {
+    std::cout << "starting encode_loop_siao_fb.\n";
+  }
 
+  while (((*which_counter) > 0) & (d_n_enc_bits < how_many)) {
        if (DO_PRINT_DEBUG) {
-         std::cout << "    t_fb_state = t_state & {fb[" << p << "] == " <<
-           d_code_feedback[p] << "} = " <<
-           n2bs (t_fb_state, d_max_delay+2) << "\n";
+      std::cout << "*w_c = " << (*which_counter) << ", "
+       "# enc_bits = " << d_n_enc_bits << " of " << how_many << ".\n"
+       "Getting new inputs.\n";
        }
 
-       // mod2 sum the feedback state to get the feedback bit value
+    // get the next set of input bits from all streams;
+    // written into d_current_inputs
 
-       char t_fb_bit = sum_bits_mod2 (t_fb_state, d_max_delay);
+    get_next_inputs (in_buf);
 
-       if (DO_PRINT_DEBUG) {
-         std::cout << "    t_fb_bit = mod2_sum (t_fb_state) = " <<
-           n2bs (t_fb_bit, 2) << "\n";
-       }
+    // update the memories with the current input bits;
+    // pre-shift delays instead of post-shift to gather loops.
 
-       // place the feedback bit into the second state bit
+    // for each unique memory (1 per input), shift the delays and mask
+    // off the extra high bits; then XOR in the input bit.
+    // with FB: find the feedback bit, and OR it into the input bit's slot;
 
-       d_memory[p] = t_state | (t_fb_bit << 1);
+    for (size_t p = 0; p < d_n_memories; p++) {
+      memory_t t_mem = (d_memory[p] << 1) & d_max_mem_masks[p];
+      memory_t t_fb = t_mem & d_code_feedback[p];
+      char t_fb_bit = sum_bits_mod2 (t_fb, d_max_delay);
+      t_mem |= ((memory_t) t_fb_bit);
+      d_memory[p] = t_mem ^ ((memory_t)(d_current_inputs[d_io_num[p]]));
+    }
 
-       if (DO_PRINT_DEBUG) {
-         std::cout << "    mem_out[" << p << "] = t_state | (fb_bit << 1) = " 
<<
-           n2bs (d_memory[p], d_max_delay+2) << "\n";
+    // create the output bits: for each output, loop over all inputs,
+    // find the output bits for each encoder, and XOR each together
+    // then sum (would usually be sum then XOR, but they're mutable in
+    // base-2 and it's faster this way).
+
+    for (size_t n = 0; n < d_n_code_outputs; n++) {
+      memory_t t_mem = 0;
+      for (size_t m = 0; m < d_n_code_inputs; m++) {
+       t_mem ^= ((d_memory[d_states_ndx[maio(m,n)]]) &
+                 d_code_generators[maio(m,n)]);
        }
+      d_current_outputs[n] = sum_bits_mod2 (t_mem, d_max_delay);
       }
+
+#if 0
+    for (size_t p = 0; p < d_n_memories; p++) {
+      memory_t t_mem = (d_memory[p] << 1);
+      d_memory[p] = (t_mem & d_max_mem_masks[p]);
     }
+#endif
 
-    // increment the input and output counters, if necessary, between
-    // input bits
+    // write the bits in d_current_outputs into the output buffer
 
-    increment_io_indices (false);
+    write_output_bits (out_buf);
 
     // 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_siao.\n";
-  }
-}
-
-char
-encoder_convolutional::get_next_bit
-(const char** in_buf,
- size_t code_input_n)
-{
-  char ret_val = 0;
-  switch (d_fsm_state) {
-  case fsm_enc_conv_doing_input:
-    ret_val = get_next_bit__input (in_buf, code_input_n);
-    break;
-  case fsm_enc_conv_doing_term:
-    ret_val = get_next_bit__term (code_input_n);
-    break;
-  default:
-    assert (0);
-    break;
+    std::cout << "ending encode_loop_siao_fb.\n";
   }
-  return (ret_val);
 }
 
-char
-encoder_convolutional::get_next_bit__term
-(size_t code_input_n)
+void
+encoder_convolutional::get_next_inputs__term
+()
 {
   // FIXME: how to figure out which term bit to get?
-  return (d_term_states[code_input_n] & 1);
+  // loop to set each entry of "d_current_inputs"
+
+  d_current_inputs.assign (d_n_code_inputs, 0);
+  //   return (d_term_states[code_input_n] & 1);
 }

Index: lib/libecc/encoder_convolutional.h
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- lib/libecc/encoder_convolutional.h  9 Jul 2006 16:15:17 -0000       1.4
+++ lib/libecc/encoder_convolutional.h  12 Jul 2006 23:43:38 -0000      1.5
@@ -176,6 +176,24 @@
 
   inline size_t maoi(size_t i, size_t o) {return ((i*d_n_code_outputs) + o);};
 
+/*
+ * max_bit_position (x): returns the bit-number of the highest "1" bit
+ * in the provided value, such that the LSB would return 0 and the MSB
+ * of a long would return 31.
+ */
+
+  inline size_t max_bit_position (memory_t x)
+  {
+    size_t t_code_mem = 0;
+    memory_t t_in_code = x >> 1;
+    while (t_in_code != 0) {
+      t_in_code >>= 1;
+      t_code_mem++;
+    }
+
+    return (t_code_mem);
+  }
+
   // methods defined in this class
 
   void encoder_convolutional_init (int block_size_bits,
@@ -188,52 +206,134 @@
                                   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);
+
+  inline void encode_loop (const char** in_buf, char** out_buf,
+                          size_t* which_counter, size_t how_many) {
+    if (d_do_encode_soai == true) {
+      if (d_do_feedback == true) {
+       encode_loop_soai_fb (in_buf, out_buf, which_counter, how_many);
+      } else {
+       encode_loop_soai (in_buf, out_buf, which_counter, how_many);
+      }
+    } else {
+      if (d_do_feedback == true) {
+       encode_loop_siao (in_buf, out_buf, which_counter, how_many);
+      } else {
+       encode_loop_siao (in_buf, out_buf, which_counter, 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 encode_loop_soai_fb (const char** in_buf, char** out_buf,
+                                   size_t* which_counter, size_t how_many);
+  virtual void encode_loop_siao_fb (const char** in_buf, char** out_buf,
+                                   size_t* which_counter, size_t how_many);
+
+  inline void get_next_inputs (const char** in_buf) {
+    switch (d_fsm_state) {
+    case fsm_enc_conv_doing_input:
+      get_next_inputs__input (in_buf);
+      break;
+    case fsm_enc_conv_doing_term:
+      get_next_inputs__term ();
+      break;
+    default:
+      assert (0);
+      break;
+    }
+  };
+
+  virtual void get_next_inputs__term ();
+
+  void get_memory_requirements (size_t m,
+                               size_t n,
+                               size_t& t_max_mem,
+                               size_t& t_n_unique_fb_prev_start,
+                               const std::vector<int>* code_feedback);
 
   // 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;
+  virtual void write_output_bits (char** out_buf) = 0;
+  virtual void get_next_inputs__input (const char** in_buf) = 0;
 
   // variables
 
   fsm_enc_conv_t d_fsm_state;
   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), 
+  // "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).
+  // "n_memories" is the number of unique memories as determined by
+  // either the feedforward or feedback generators (not both).  For
+  // FF, this number equals either the number of code inputs (for
+  // SIAO) or outputs (for SOAI).
 
   size_t d_n_memories;
 
-  // total_n_delays is the total # of delays, needed to determine the
+  // "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.
+  // "code generators" are stored internally in "maXY(i,o)" order this
+  // allows for looping over all a single output and computing all
+  // input parts sequentially.
+
+  std::vector<memory_t> d_code_generators;
+
+  // "feedback" are found as "d_n_memories" unique entries, and stored
+  // in at most 1 entry per I/O combination.  Listed in the same order
+  // as "d_io_num" entries show.
+
+  std::vector<memory_t> d_code_feedback;
+
+  // "n_delays" is a vector, the number of delays for the FB generator
+  // in the same [] location; also relates directly to the
+  // "max_mem_masks" in the same [] location.
+
+  std::vector<size_t> d_n_delays;
+
+  // "io_num" is a vector, mapping which FB in SIAO goes with which
+  // input, or which FB in SOAI goes with which output
+
+  std::vector<size_t> d_io_num;
+
+  // "max_mem_masks" are the memory masks, one per unique FB for SIAO;
+  // otherwise not used.
+
+  std::vector<memory_t> d_max_mem_masks;
+
+  // "states_ndx" is a "matrix" whose contents are the indices into
+  // the "io_num" vector, telling which input goes with which
+  // state; uses the same "maXY(i,o)" as the code generators.
+
+  std::vector<size_t> d_states_ndx;
+
+  // "memory" are the actual stored delay bits, one memory for each
+  // unique FF or FB code generator;
+  // "init_states" are the user-provided init states - and
+  // "term_states" are the user-provided termination states -
+  // interpreted w/r.t. the actual FF and FB code generators and SOAI
+  // / SIAO realization;
 
-  std::vector<memory_t> d_code_generators, d_code_feedback;
-  std::vector<memory_ptr_t> d_states;
   std::vector<memory_t> d_memory, d_init_states, d_term_states;
-  std::vector<size_t> d_input_num;
+
+  // "inputs" are the current input bits, in the LSB (&1) of each "char"
+
+  std::vector<char> d_current_inputs;
+
+  // "outputs" are the current output bits, in the LSB (&1) of each "char"
+
+  std::vector<char> d_current_outputs;
 };
 
 #endif /* INCLUDED_ENCODER_CONVOLUTIONAL_H */

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.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- lib/libecc/encoder_convolutional_ic1_ic1.cc 9 Jul 2006 18:40:42 -0000       
1.3
+++ lib/libecc/encoder_convolutional_ic1_ic1.cc 12 Jul 2006 23:43:38 -0000      
1.4
@@ -113,57 +113,69 @@
 }
 
 void
-encoder_convolutional_ic1_ic1::increment_io_indices
-(bool while_encoding)
+encoder_convolutional_ic1_ic1::write_output_bits
+(char** out_buf)
 {
-  // increment the buffer index only (not the internal bit shift
-  // indices) for "ic1" type, only after encoding is done and all
-  // resulting outputs are stored on the output streams; nothing to do
-  // while encoding
+  // write all the outputs bits in d_current_outputs LSB (&1) to the
+  // given output buffer.
 
-  if (while_encoding == false) {
-    d_out_buf_ndx++;
-    d_in_buf_ndx++;
-  }
-}
-
-void
-encoder_convolutional_ic1_ic1::output_bit
-(char t_out_bit,
- char** out_buf,
- size_t t_output_stream)
-{
-  // store the result for this particular output stream
-  // one bit per output item for "ic1" type output
+  // one bit per output 'char' for "ic1" type output
 
+  for (size_t n = 0; n < d_n_code_outputs; n++) {
   if (DO_PRINT_DEBUG) {
     std::cout << "Starting output_bit:\n"
-      "  O_i[" << t_output_stream << "][" << d_out_buf_ndx << "] = " <<
-      n2bs (out_buf[t_output_stream][d_out_buf_ndx], g_num_bits_per_byte) <<
-      ", b_out = " << n2bs (t_out_bit, 2) << ", ";
+       "  O_i[" << n << "][" << d_out_buf_ndx << "] = " <<
+       n2bs (out_buf[n][d_out_buf_ndx], g_num_bits_per_byte) <<
+       ", b_out = " << n2bs (d_current_outputs[n], 2) << ", ";
   }
 
-  out_buf[t_output_stream][d_out_buf_ndx] = t_out_bit;
+    out_buf[n][d_out_buf_ndx] = d_current_outputs[n];
 
   if (DO_PRINT_DEBUG) {
     std::cout << "O_o[][] = " <<
-      n2bs (out_buf[t_output_stream][d_out_buf_ndx], g_num_bits_per_byte) <<
-      "\nEnding output_bit.\n";
+       n2bs (out_buf[n][d_out_buf_ndx], g_num_bits_per_byte) <<
+       "\n";
+    }
+  }
+
+  if (DO_PRINT_DEBUG) {
+    std::cout << "Ending write_output_bits.\n";
   }
+
+  // decrement the number of output bits left on all streams
+
+  d_n_output_bits_left--;
+
+  // increment the output index (not the bit shift index) for the next
+  // write
+
+  d_out_buf_ndx++;
 }
 
-char
-encoder_convolutional_ic1_ic1::get_next_bit__input
-(const char** in_buf,
- size_t code_input_n)
+void
+encoder_convolutional_ic1_ic1::get_next_inputs__input
+(const char** in_buf)
 {
-  // get a bit from this particular input stream
-  // one bit per output item for "ic1" type input
+  // get the next set of input bits, moved into the LSB (&1) of
+  // d_current_inputs
+
+  // one bit per input 'char' for "ic1" type input
+
+  for (size_t m = 0; m < d_n_code_inputs; m++) {
+    d_current_inputs[m] = ((in_buf[m][d_in_buf_ndx]) & 1);
 
   if (DO_PRINT_DEBUG) {
-    std::cout << "I[" << code_input_n << "][" << d_in_buf_ndx << "] = " <<
-      n2bs (in_buf[code_input_n][d_in_buf_ndx], 2) << "\n";
+      std::cout << "I[" << m << "][" << d_in_buf_ndx << "] = " <<
+       n2bs (d_current_inputs[m], 2) << "\n";
+    }
   }
 
-  return (in_buf[code_input_n][d_in_buf_ndx] & 1);
+  // decrement the number of bits left on all streams
+
+  d_n_input_bits_left--;
+
+  // increment the input index (not the bit shift index) for the next
+  // read
+
+  d_in_buf_ndx++;
 }

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.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- lib/libecc/encoder_convolutional_ic1_ic1.h  9 Jul 2006 16:15:17 -0000       
1.3
+++ lib/libecc/encoder_convolutional_ic1_ic1.h  12 Jul 2006 23:43:38 -0000      
1.4
@@ -84,11 +84,8 @@
   virtual size_t compute_n_output_bits (size_t n_input_bits);
 
 protected:
-  virtual char get_next_bit__input (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);
-  virtual void increment_io_indices (bool while_encoding);
+  virtual void get_next_inputs__input (const char** in_buf);
+  virtual void write_output_bits (char** out_buf);
 };
 
 #endif /* INCLUDED_ENCODER_CONVOLUTIONAL_IC1_IC1_H */

Index: python/qa_test_encoder_convolutional_1.py
===================================================================
RCS file: 
/sources/gnuradio/gr-error-correcting-codes/src/python/qa_test_encoder_convolutional_1.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- python/qa_test_encoder_convolutional_1.py   9 Jul 2006 16:15:17 -0000       
1.1
+++ python/qa_test_encoder_convolutional_1.py   12 Jul 2006 23:43:38 -0000      
1.2
@@ -24,15 +24,11 @@
 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
+       e1 = ecc.streams_encode_convolutional (100, 3, 2, [1, 0, 5, 0, 1, 6])
 
-       ss_enc = ecc.streams_encode_convolutional (frame_size,
-                                                  enc_code_in_chan,
-                                                  enc_code_out_chan,
-                                                  code_generators)
+       e2 = ecc.streams_encode_convolutional (100, 2, 3, [1, 0, 0, 1, 5, 6])
+
+       e3 = ecc.streams_encode_convolutional_feedback (100, 2, 3, [1, 7, 0, 1, 
5, 6], [1, 1, 1, 1, 017, 017])
 
 if __name__ == '__main__':
     main ()




reply via email to

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