summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--gnuradio-core/ChangeLog6
-rw-r--r--gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.cc.t12
-rw-r--r--gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.cc.t12
-rw-r--r--gr-error-correcting-codes/Makefile.am1
-rw-r--r--gr-error-correcting-codes/src/lib/Makefile.am36
-rw-r--r--gr-error-correcting-codes/src/lib/ecc.i16
-rw-r--r--gr-error-correcting-codes/src/lib/ecc_metrics_decode_viterbi_full_block.cc (renamed from gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.cc)103
-rw-r--r--gr-error-correcting-codes/src/lib/ecc_metrics_decode_viterbi_full_block.h (renamed from gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.h)62
-rw-r--r--gr-error-correcting-codes/src/lib/ecc_metrics_decode_viterbi_full_block.i (renamed from gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.i)22
-rw-r--r--gr-error-correcting-codes/src/lib/ecc_streams_encode_convolutional.cc (renamed from gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.cc)98
-rw-r--r--gr-error-correcting-codes/src/lib/ecc_streams_encode_convolutional.h (renamed from gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.h)45
-rw-r--r--gr-error-correcting-codes/src/lib/ecc_streams_encode_convolutional.i (renamed from gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.i)20
-rw-r--r--gr-error-correcting-codes/src/lib/ecc_streams_encode_turbo.cc (renamed from gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.cc)104
-rw-r--r--gr-error-correcting-codes/src/lib/ecc_streams_encode_turbo.h (renamed from gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.h)39
-rw-r--r--gr-error-correcting-codes/src/lib/ecc_streams_encode_turbo.i (renamed from gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.i)16
-rw-r--r--gr-error-correcting-codes/src/lib/ecc_syms_to_metrics.cc (renamed from gr-error-correcting-codes/src/lib/gr_syms_to_metrics.cc)107
-rw-r--r--gr-error-correcting-codes/src/lib/ecc_syms_to_metrics.h (renamed from gr-error-correcting-codes/src/lib/gr_syms_to_metrics.h)41
-rw-r--r--gr-error-correcting-codes/src/lib/ecc_syms_to_metrics.i (renamed from gr-error-correcting-codes/src/lib/gr_syms_to_metrics.i)18
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/Makefile.am14
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/code_convolutional_trellis.cc78
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/code_convolutional_trellis.h25
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/code_io.cc33
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/code_io.h556
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/code_metrics.cc588
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/code_metrics.h213
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/decoder.cc161
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/decoder.h70
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.cc383
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.h74
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.cc17
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.h9
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block_i1_ic1.cc162
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block_i1_ic1.h66
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/encoder.cc137
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/encoder.h60
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.cc155
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.h67
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.cc188
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.h91
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic8_ic8.cc224
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic8_ic8.h96
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/encoder_turbo.cc73
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/encoder_turbo.h52
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/mld/Makefile.am2
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/mld/n2bs.cc72
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/mld/n2bs.h31
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/tests/Makefile.am3
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/tests/qa_encoder_convolutional_ic1_ic1.cc84
-rw-r--r--gr-error-correcting-codes/src/lib/libecc/tests/qa_encoder_convolutional_ic1_ic1.h4
-rw-r--r--gr-error-correcting-codes/src/python/Makefile.am2
51 files changed, 2328 insertions, 2222 deletions
diff --git a/configure.ac b/configure.ac
index a9190a11d..9486bf510 100644
--- a/configure.ac
+++ b/configure.ac
@@ -155,7 +155,7 @@ GR_AUDIO_OSX dnl ***NOT TESTED***
GR_AUDIO_WINDOWS dnl ***NOT TESTED***
GR_ATSC
GR_COMEDI
-#GR_ERROR_CORRECTING_CODES dnl Disabled until compile error fixed from CVS
+GR_ERROR_CORRECTING_CODES
GR_GSM_FR_VOCODER
GR_RADAR
GR_RADIO_ASTRONOMY
diff --git a/gnuradio-core/ChangeLog b/gnuradio-core/ChangeLog
index 776ab8ca9..7ad6afb24 100644
--- a/gnuradio-core/ChangeLog
+++ b/gnuradio-core/ChangeLog
@@ -1,3 +1,9 @@
+2006-08-01 Achilleas Anastasopoulos <anastas@umich.edu>
+
+ * src/lib/general/gr_packed_to_unpacked_XX.cc.t,
+ src/lib/general/gr_unpacked_to_packed_XX.cc.t: fixed bug in
+ multiple stream support.
+
2006-07-06 Tom Rondeau <trondeau@vt.edu>
* src/python/gnuradio/blksimpl/gmsk2.py:
diff --git a/gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.cc.t b/gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.cc.t
index f585c4a6a..3d66c6896 100644
--- a/gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.cc.t
+++ b/gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.cc.t
@@ -87,12 +87,15 @@ int
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
+ unsigned int index_tmp;
+
assert (input_items.size() == output_items.size());
int nstreams = input_items.size();
for (int m=0; m < nstreams; m++){
const @I_TYPE@ *in = (@I_TYPE@ *) input_items[m];
@O_TYPE@ *out = (@O_TYPE@ *) output_items[m];
+ index_tmp = d_index;
// per stream processing
@@ -102,8 +105,8 @@ int
for (int i = 0; i < noutput_items; i++){
//printf("here msb %d\n",i);
@O_TYPE@ x = 0;
- for(unsigned int j=0; j<d_bits_per_chunk; j++, d_index++)
- x = (x<<1) | get_bit_be(in, d_index);
+ for(unsigned int j=0; j<d_bits_per_chunk; j++, index_tmp++)
+ x = (x<<1) | get_bit_be(in, index_tmp);
out[i] = x;
}
break;
@@ -112,8 +115,8 @@ int
for (int i = 0; i < noutput_items; i++){
//printf("here lsb %d\n",i);
@O_TYPE@ x = 0;
- for(unsigned int j=0; j<d_bits_per_chunk; j++, d_index++)
- x = (x<<1) | get_bit_le(in, d_index);
+ for(unsigned int j=0; j<d_bits_per_chunk; j++, index_tmp++)
+ x = (x<<1) | get_bit_le(in, index_tmp);
out[i] = x;
}
break;
@@ -126,6 +129,7 @@ int
assert(ninput_items[m] >= (int) ((d_index+(BITS_PER_TYPE-1))>>LOG2_L_TYPE));
}
+ d_index = index_tmp;
consume_each (d_index >> LOG2_L_TYPE);
d_index = d_index & (BITS_PER_TYPE-1);
//printf("got to end\n");
diff --git a/gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.cc.t b/gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.cc.t
index 7d5d72e65..fcb5d0637 100644
--- a/gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.cc.t
+++ b/gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.cc.t
@@ -78,12 +78,15 @@ int
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
+ unsigned int index_tmp;
+
assert (input_items.size() == output_items.size());
int nstreams = input_items.size();
for (int m=0; m< nstreams; m++) {
const @I_TYPE@ *in = (@I_TYPE@ *) input_items[m];
@O_TYPE@ *out = (@O_TYPE@ *) output_items[m];
+ index_tmp=d_index;
// per stream processing
@@ -95,8 +98,8 @@ int
for(int i=0;i<noutput_items;i++) {
@O_TYPE@ tmp=0;
for(unsigned int j=0; j<BITS_PER_TYPE; j++) {
- tmp = (tmp<<1) | get_bit_be1(in,d_index,d_bits_per_chunk);
- d_index++;
+ tmp = (tmp<<1) | get_bit_be1(in,index_tmp,d_bits_per_chunk);
+ index_tmp++;
}
out[i] = tmp;
}
@@ -106,8 +109,8 @@ int
for(int i=0;i<noutput_items;i++) {
unsigned long tmp=0;
for(unsigned int j=0; j<BITS_PER_TYPE; j++) {
- tmp = (tmp>>1)| (get_bit_be1(in,d_index,d_bits_per_chunk)<<(BITS_PER_TYPE-1));
- d_index++;
+ tmp = (tmp>>1)| (get_bit_be1(in,index_tmp,d_bits_per_chunk)<<(BITS_PER_TYPE-1));
+ index_tmp++;
}
out[i] = tmp;
}
@@ -118,6 +121,7 @@ int
}
}
+ d_index = index_tmp;
consume_each ((int)(d_index/d_bits_per_chunk));
d_index = d_index%d_bits_per_chunk;
diff --git a/gr-error-correcting-codes/Makefile.am b/gr-error-correcting-codes/Makefile.am
index 67a9e921d..704c43275 100644
--- a/gr-error-correcting-codes/Makefile.am
+++ b/gr-error-correcting-codes/Makefile.am
@@ -22,6 +22,5 @@
include $(top_srcdir)/Makefile.common
SUBDIRS = src
-DIST_SUBDIRS = src
MOSTLYCLEANFILES = *~
diff --git a/gr-error-correcting-codes/src/lib/Makefile.am b/gr-error-correcting-codes/src/lib/Makefile.am
index 3168a58f4..602c560a0 100644
--- a/gr-error-correcting-codes/src/lib/Makefile.am
+++ b/gr-error-correcting-codes/src/lib/Makefile.am
@@ -23,8 +23,6 @@ include $(top_srcdir)/Makefile.common
SUBDIRS = libecc
-LIBS += $(GNURADIO_CORE_LIBS)
-
# Install this stuff so that it ends up as the gnuradio.und module
# This usually ends up at:
# ${prefix}/lib/python${python_version}/site-packages/gnuradio
@@ -32,10 +30,9 @@ LIBS += $(GNURADIO_CORE_LIBS)
ourpythondir = $(grpythondir)
ourlibdir = $(grpythondir)
-INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) $(GNURADIO_INCLUDES)
+INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS)
-SWIGCPPPYTHONARGS = -fvirtual -python -modern $(PYTHON_CPPFLAGS) \
- $(GNURADIO_INCLUDES)
+SWIGCPPPYTHONARGS = -fvirtual -python -modern $(PYTHON_CPPFLAGS) $(STD_DEFINES_AND_INCLUDES)
ALL_IFILES = \
$(LOCAL_IFILES) \
@@ -45,10 +42,10 @@ NON_LOCAL_IFILES = \
$(top_srcdir)/gnuradio-core/src/lib/swig/gnuradio.i
LOCAL_IFILES = \
- gr_syms_to_metrics.i \
- gr_metrics_decode_viterbi_full_block.i \
- gr_streams_encode_convolutional.i \
- gr_streams_encode_turbo.i \
+ ecc_syms_to_metrics.i \
+ ecc_metrics_decode_viterbi_full_block.i \
+ ecc_streams_encode_convolutional.i \
+ ecc_streams_encode_turbo.i \
ecc.i
# These files are built by SWIG. The first is the C++ glue.
@@ -60,18 +57,18 @@ BUILT_SOURCES = \
ecc.py
# This gets ecc.py installed in the right place
-ourpython_PYTHON = \
- __init__.py \
+ourpython_PYTHON = \
+ __init__.py \
ecc.py
ourlib_LTLIBRARIES = _ecc.la
# These are the source files that go into the shared library
_ecc_la_SOURCES = \
- gr_syms_to_metrics.cc \
- gr_metrics_decode_viterbi_full_block.cc \
- gr_streams_encode_convolutional.cc \
- gr_streams_encode_turbo.cc \
+ ecc_syms_to_metrics.cc \
+ ecc_metrics_decode_viterbi_full_block.cc \
+ ecc_streams_encode_convolutional.cc \
+ ecc_streams_encode_turbo.cc \
ecc.cc
# magic flags
@@ -81,14 +78,15 @@ _ecc_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version
_ecc_la_LIBADD = \
libecc/libecc.la \
$(PYTHON_LDFLAGS) \
+ $(GNURADIO_CORE_LIBS) \
-lstdc++
# These headers get installed in ${prefix}/include/gnuradio
grinclude_HEADERS = \
- gr_syms_to_metrics.h \
- gr_metrics_decode_viterbi_full_block.h \
- gr_streams_encode_convolutional.h \
- gr_streams_encode_turbo.h
+ ecc_syms_to_metrics.h \
+ ecc_metrics_decode_viterbi_full_block.h \
+ ecc_streams_encode_convolutional.h \
+ ecc_streams_encode_turbo.h
# These swig headers get installed in ${prefix}/include/gnuradio/swig
swiginclude_HEADERS = $(LOCAL_IFILES)
diff --git a/gr-error-correcting-codes/src/lib/ecc.i b/gr-error-correcting-codes/src/lib/ecc.i
index 32ea9d2b2..3c6ea1e85 100644
--- a/gr-error-correcting-codes/src/lib/ecc.i
+++ b/gr-error-correcting-codes/src/lib/ecc.i
@@ -27,15 +27,15 @@
%{
#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix
-#include <gr_streams_encode_convolutional.h>
-#include <gr_streams_encode_turbo.h>
-#include <gr_metrics_decode_viterbi_full_block.h>
-#include <gr_syms_to_metrics.h>
+#include <ecc_streams_encode_convolutional.h>
+#include <ecc_streams_encode_turbo.h>
+#include <ecc_metrics_decode_viterbi_full_block.h>
+#include <ecc_syms_to_metrics.h>
#include <stdexcept>
%}
-%include "gr_streams_encode_convolutional.i"
-%include "gr_streams_encode_turbo.i"
-%include "gr_metrics_decode_viterbi_full_block.i"
-%include "gr_syms_to_metrics.i"
+%include "ecc_streams_encode_convolutional.i"
+%include "ecc_streams_encode_turbo.i"
+%include "ecc_metrics_decode_viterbi_full_block.i"
+%include "ecc_syms_to_metrics.i"
diff --git a/gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.cc b/gr-error-correcting-codes/src/lib/ecc_metrics_decode_viterbi_full_block.cc
index 94a7fe44a..dfb00932a 100644
--- a/gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.cc
+++ b/gr-error-correcting-codes/src/lib/ecc_metrics_decode_viterbi_full_block.cc
@@ -24,13 +24,13 @@
#include "config.h"
#endif
-#include <gr_metrics_decode_viterbi_full_block.h>
+#include <ecc_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
+ecc_metrics_decode_viterbi_full_block_sptr
+ecc_make_metrics_decode_viterbi_full_block
(int sample_precision,
int frame_size_bits,
int n_code_inputs,
@@ -40,8 +40,8 @@ gr_make_metrics_decode_viterbi_full_block
int start_memory_state,
int end_memory_state)
{
- return gr_metrics_decode_viterbi_full_block_sptr
- (new gr_metrics_decode_viterbi_full_block
+ return ecc_metrics_decode_viterbi_full_block_sptr
+ (new ecc_metrics_decode_viterbi_full_block
(sample_precision,
frame_size_bits,
n_code_inputs,
@@ -52,8 +52,8 @@ gr_make_metrics_decode_viterbi_full_block
end_memory_state));
}
-gr_metrics_decode_viterbi_full_block_feedback_sptr
-gr_make_metrics_decode_viterbi_full_block_feedback
+ecc_metrics_decode_viterbi_full_block_feedback_sptr
+ecc_make_metrics_decode_viterbi_full_block_feedback
(int sample_precision,
int frame_size_bits,
int n_code_inputs,
@@ -64,8 +64,8 @@ gr_make_metrics_decode_viterbi_full_block_feedback
int start_memory_state,
int end_memory_state)
{
- return gr_metrics_decode_viterbi_full_block_feedback_sptr
- (new gr_metrics_decode_viterbi_full_block
+ return ecc_metrics_decode_viterbi_full_block_feedback_sptr
+ (new ecc_metrics_decode_viterbi_full_block
(sample_precision,
frame_size_bits,
n_code_inputs,
@@ -77,7 +77,7 @@ gr_make_metrics_decode_viterbi_full_block_feedback
end_memory_state));
}
-gr_metrics_decode_viterbi_full_block::gr_metrics_decode_viterbi_full_block
+ecc_metrics_decode_viterbi_full_block::ecc_metrics_decode_viterbi_full_block
(int sample_precision,
int frame_size_bits,
int n_code_inputs,
@@ -90,18 +90,18 @@ gr_metrics_decode_viterbi_full_block::gr_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);
+ d_encoder = new encoder_convolutional (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
+ecc_metrics_decode_viterbi_full_block::ecc_metrics_decode_viterbi_full_block
(int sample_precision,
int frame_size_bits,
int n_code_inputs,
@@ -115,42 +115,50 @@ gr_metrics_decode_viterbi_full_block::gr_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,
- code_feedback,
- do_termination,
- start_memory_state,
- end_memory_state);
+ d_encoder = new encoder_convolutional (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
+ecc_metrics_decode_viterbi_full_block::~ecc_metrics_decode_viterbi_full_block
()
{
delete d_decoder;
+ d_decoder = 0;
delete d_encoder;
+ d_encoder = 0;
+ delete d_in_buf;
+ d_in_buf = 0;
+ delete d_out_buf;
+ d_out_buf = 0;
}
void
-gr_metrics_decode_viterbi_full_block::setup_io_signatures
+ecc_metrics_decode_viterbi_full_block::setup_io_signatures
(int sample_precision,
int n_code_inputs,
int n_code_outputs)
{
- // create the decoder using:
+ // create the decoder
//
- // the "i1" input model: individual input streams; two per metric
- // type (0-bit, 1-bit), single metric per input item (char, short, long)
+ // the input model: individual input streams; two per metric type
+ // (0-bit, 1-bit), single metric per input item (float, char, short,
+ // long)
//
- // the "ic1" output model:
+ // the "ic1l" 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);
+ d_decoder = new decoder_viterbi_full_block (sample_precision,
+ d_encoder);
+ d_out_buf = new code_output_ic1l (n_code_inputs);
// error checking is done in the encoder and decoder classes
// so just use the parameters as given; will be correct!
@@ -171,15 +179,19 @@ gr_metrics_decode_viterbi_full_block::setup_io_signatures
if (sample_precision == 0) {
// float
l_input_item_size_bytes = sizeof (float);
+ d_in_buf = new code_input_if (n_code_outputs);
} else if (sample_precision <= 8) {
// use char
l_input_item_size_bytes = sizeof (char);
+ d_in_buf = new code_input_ic (n_code_outputs);
} else if (sample_precision <= 16) {
// use short
l_input_item_size_bytes = sizeof (short);
+ d_in_buf = new code_input_is (n_code_outputs);
} else {
// use long
l_input_item_size_bytes = sizeof (long);
+ d_in_buf = new code_input_il (n_code_outputs);
}
set_input_signature (gr_make_io_signature (2*d_n_code_outputs,
@@ -187,36 +199,41 @@ gr_metrics_decode_viterbi_full_block::setup_io_signatures
l_input_item_size_bytes));
}
-void gr_metrics_decode_viterbi_full_block::forecast
+void ecc_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);
+ int ninput_items = d_decoder->compute_n_input_items (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
+ecc_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.
+ // 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_input_items = d_decoder->compute_n_input_items (noutput_items);
+#if 1
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));
+#endif
+
+ // setup the i/o buffers
+
+ d_in_buf->set_buffer ((void**)(&input_items[0]), t_n_input_items);
+ d_out_buf->set_buffer ((void**)(&output_items[0]), 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);
+ t_n_input_items = d_decoder->decode (d_in_buf, d_out_buf,
+ (size_t) noutput_items);
// consume the number of used input items on all input streams
diff --git a/gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.h b/gr-error-correcting-codes/src/lib/ecc_metrics_decode_viterbi_full_block.h
index 57ca1bab1..9f37f0525 100644
--- a/gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.h
+++ b/gr-error-correcting-codes/src/lib/ecc_metrics_decode_viterbi_full_block.h
@@ -20,21 +20,21 @@
* Boston, MA 02111-1307, USA.
*/
-#ifndef INCLUDED_GR_METRICS_DECODE_VITERBI_FULL_BLOCK_H
-#define INCLUDED_GR_METRICS_DECODE_VITERBI_FULL_BLOCK_H
+#ifndef INCLUDED_ECC_METRICS_DECODE_VITERBI_FULL_BLOCK_H
+#define INCLUDED_ECC_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>
+#include <libecc/decoder_viterbi_full_block.h>
+#include <libecc/encoder_convolutional.h>
-class gr_metrics_decode_viterbi_full_block;
+class ecc_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;
+typedef boost::shared_ptr<ecc_metrics_decode_viterbi_full_block>
+ecc_metrics_decode_viterbi_full_block_sptr,
+ecc_metrics_decode_viterbi_full_block_feedback_sptr;
-gr_metrics_decode_viterbi_full_block_sptr
-gr_make_metrics_decode_viterbi_full_block
+ecc_metrics_decode_viterbi_full_block_sptr
+ecc_make_metrics_decode_viterbi_full_block
(int frame_size_bits,
int n_code_inputs,
int n_code_outputs,
@@ -43,8 +43,8 @@ gr_make_metrics_decode_viterbi_full_block
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
+ecc_metrics_decode_viterbi_full_block_feedback_sptr
+ecc_make_metrics_decode_viterbi_full_block_feedback
(int frame_size_bits,
int n_code_inputs,
int n_code_outputs,
@@ -63,10 +63,11 @@ gr_make_metrics_decode_viterbi_full_block_feedback
* output: stream(s) of char, single bit stored in the LSB.
*/
-class gr_metrics_decode_viterbi_full_block : public gr_block
+class ecc_metrics_decode_viterbi_full_block : public gr_block
{
- friend gr_metrics_decode_viterbi_full_block_sptr
- gr_make_metrics_decode_viterbi_full_block
+protected:
+ friend ecc_metrics_decode_viterbi_full_block_sptr
+ ecc_make_metrics_decode_viterbi_full_block
(int sample_precision,
int frame_size_bits,
int n_code_inputs,
@@ -76,8 +77,8 @@ class gr_metrics_decode_viterbi_full_block : public gr_block
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
+ friend ecc_metrics_decode_viterbi_full_block_feedback_sptr
+ ecc_make_metrics_decode_viterbi_full_block_feedback
(int sample_precision,
int frame_size_bits,
int n_code_inputs,
@@ -118,7 +119,7 @@ class gr_metrics_decode_viterbi_full_block : public gr_block
* n_code_outputs: the number of decoder-output (encoder-input) streams
*/
- gr_metrics_decode_viterbi_full_block
+ ecc_metrics_decode_viterbi_full_block
(int sample_precision,
int frame_size_bits,
int n_code_inputs,
@@ -128,7 +129,7 @@ class gr_metrics_decode_viterbi_full_block : public gr_block
int start_memory_state,
int end_memory_state);
- gr_metrics_decode_viterbi_full_block
+ ecc_metrics_decode_viterbi_full_block
(int sample_precision,
int frame_size_bits,
int n_code_inputs,
@@ -139,8 +140,18 @@ class gr_metrics_decode_viterbi_full_block : public gr_block
int start_memory_state,
int end_memory_state);
+ 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* d_decoder;
+ encoder_convolutional* d_encoder;
+ code_input_ptr d_in_buf;
+ code_output_ptr d_out_buf;
+
public:
- ~gr_metrics_decode_viterbi_full_block ();
+ ~ecc_metrics_decode_viterbi_full_block ();
virtual void forecast (int noutput_items,
gr_vector_int &ninput_items_required);
@@ -149,15 +160,6 @@ public:
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 */
+#endif /* INCLUDED_ECC_METRICS_DECODE_VITERBI_FULL_BLOCK_H */
diff --git a/gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.i b/gr-error-correcting-codes/src/lib/ecc_metrics_decode_viterbi_full_block.i
index a7cd1ba25..85f6b6db3 100644
--- a/gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.i
+++ b/gr-error-correcting-codes/src/lib/ecc_metrics_decode_viterbi_full_block.i
@@ -20,17 +20,17 @@
* Boston, MA 02111-1307, USA.
*/
-GR_SWIG_BLOCK_MAGIC(gr,metrics_decode_viterbi_full_block);
+GR_SWIG_BLOCK_MAGIC(ecc,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;
+typedef boost::shared_ptr<ecc_metrics_decode_viterbi_full_block>
+ecc_metrics_decode_viterbi_full_block_feedback_sptr;
-LOCAL_GR_SWIG_BLOCK_MAGIC(gr,metrics_decode_viterbi_full_block_feedback);
+LOCAL_GR_SWIG_BLOCK_MAGIC(ecc,metrics_decode_viterbi_full_block_feedback);
-gr_metrics_decode_viterbi_full_block_sptr
-gr_make_metrics_decode_viterbi_full_block
+ecc_metrics_decode_viterbi_full_block_sptr
+ecc_make_metrics_decode_viterbi_full_block
(int sample_precision,
int frame_size_bits,
int n_code_inputs,
@@ -40,8 +40,8 @@ gr_make_metrics_decode_viterbi_full_block
int start_memory_state,
int end_memory_state);
-gr_metrics_decode_viterbi_full_block_feedback_sptr
-gr_make_metrics_decode_viterbi_full_block_feedback
+ecc_metrics_decode_viterbi_full_block_feedback_sptr
+ecc_make_metrics_decode_viterbi_full_block_feedback
(int sample_precision,
int frame_size_bits,
int n_code_inputs,
@@ -52,9 +52,9 @@ gr_make_metrics_decode_viterbi_full_block_feedback
int start_memory_state,
int end_memory_state);
-class gr_metrics_decode_viterbi_full_block : public gr_block
+class ecc_metrics_decode_viterbi_full_block : public gr_block
{
- gr_metrics_decode_viterbi_full_block
+ ecc_metrics_decode_viterbi_full_block
(int sample_precision,
int frame_size_bits,
int n_code_inputs,
@@ -64,7 +64,7 @@ class gr_metrics_decode_viterbi_full_block : public gr_block
int start_memory_state,
int end_memory_state);
- gr_metrics_decode_viterbi_full_block
+ ecc_metrics_decode_viterbi_full_block
(int sample_precision,
int frame_size_bits,
int n_code_inputs,
diff --git a/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.cc b/gr-error-correcting-codes/src/lib/ecc_streams_encode_convolutional.cc
index 98e292651..a0ffd1ab1 100644
--- a/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.cc
+++ b/gr-error-correcting-codes/src/lib/ecc_streams_encode_convolutional.cc
@@ -24,13 +24,13 @@
#include "config.h"
#endif
-#include <gr_streams_encode_convolutional.h>
+#include <ecc_streams_encode_convolutional.h>
#include <gr_io_signature.h>
#include <assert.h>
#include <iostream>
-gr_streams_encode_convolutional_sptr
-gr_make_streams_encode_convolutional
+ecc_streams_encode_convolutional_sptr
+ecc_make_streams_encode_convolutional
(int frame_size_bits,
int n_code_inputs,
int n_code_outputs,
@@ -39,8 +39,8 @@ gr_make_streams_encode_convolutional
int start_memory_state,
int end_memory_state)
{
- return gr_streams_encode_convolutional_sptr
- (new gr_streams_encode_convolutional (frame_size_bits,
+ return ecc_streams_encode_convolutional_sptr
+ (new ecc_streams_encode_convolutional (frame_size_bits,
n_code_inputs,
n_code_outputs,
code_generator,
@@ -49,8 +49,8 @@ gr_make_streams_encode_convolutional
end_memory_state));
}
-gr_streams_encode_convolutional_sptr
-gr_make_streams_encode_convolutional_feedback
+ecc_streams_encode_convolutional_sptr
+ecc_make_streams_encode_convolutional_feedback
(int frame_size_bits,
int n_code_inputs,
int n_code_outputs,
@@ -60,8 +60,8 @@ gr_make_streams_encode_convolutional_feedback
int start_memory_state,
int end_memory_state)
{
- return gr_streams_encode_convolutional_sptr
- (new gr_streams_encode_convolutional (frame_size_bits,
+ return ecc_streams_encode_convolutional_sptr
+ (new ecc_streams_encode_convolutional (frame_size_bits,
n_code_inputs,
n_code_outputs,
code_generator,
@@ -71,7 +71,7 @@ gr_make_streams_encode_convolutional_feedback
end_memory_state));
}
-gr_streams_encode_convolutional::gr_streams_encode_convolutional
+ecc_streams_encode_convolutional::ecc_streams_encode_convolutional
(int frame_size_bits,
int n_code_inputs,
int n_code_outputs,
@@ -86,18 +86,18 @@ gr_streams_encode_convolutional::gr_streams_encode_convolutional
// 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,
- do_termination,
- start_memory_state,
- end_memory_state);
+ d_encoder = new encoder_convolutional (frame_size_bits,
+ n_code_inputs,
+ n_code_outputs,
+ code_generators,
+ do_termination,
+ start_memory_state,
+ end_memory_state);
setup_io_signatures (n_code_inputs, n_code_outputs);
}
-gr_streams_encode_convolutional::gr_streams_encode_convolutional
+ecc_streams_encode_convolutional::ecc_streams_encode_convolutional
(int frame_size_bits,
int n_code_inputs,
int n_code_outputs,
@@ -113,50 +113,47 @@ gr_streams_encode_convolutional::gr_streams_encode_convolutional
// 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);
+ d_encoder = new encoder_convolutional (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
+ecc_streams_encode_convolutional::setup_io_signatures
(int n_code_inputs,
int n_code_outputs)
{
- fprintf (stderr, "gr_s_e_c: d_encoder == %X\n", (unsigned int)d_encoder);
-
// create the correct input signature; 1 bit per input char
+ d_in_buf = new code_input_ic1l (n_code_inputs);
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
+ d_out_buf = new code_output_ic1l (n_code_outputs);
set_output_signature (gr_make_io_signature (n_code_outputs,
n_code_outputs,
sizeof (char)));
-
- // no need to set the output multiple (to 1 item), since 1 is the
- // default, and the encoder class handles the rest internally
-
- // no need to set the relative rate (# out / # in) because for each
- // input bit per input stream there is 1 output bit per output
- // stream ... with a little added for termination, but ignore those.
}
-gr_streams_encode_convolutional::~gr_streams_encode_convolutional
+ecc_streams_encode_convolutional::~ecc_streams_encode_convolutional
()
{
delete d_encoder;
d_encoder = 0;
+ delete d_in_buf;
+ d_in_buf = 0;
+ delete d_out_buf;
+ d_out_buf = 0;
}
/*
@@ -164,48 +161,39 @@ gr_streams_encode_convolutional::~gr_streams_encode_convolutional
* bits. Handled internally by the encoder.
*/
-void gr_streams_encode_convolutional::forecast
+void ecc_streams_encode_convolutional::forecast
(int noutput_items,
gr_vector_int &ninput_items_required)
{
- fprintf (stderr, "gr_s_e_c::forecast: #out = %d\n",
- noutput_items);
-
int ninput_items = d_encoder->compute_n_input_bits (noutput_items);
-
- fprintf (stderr, "s_e_c::forecast: #out = %d, #in = %d\n",
- noutput_items, ninput_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_convolutional::general_work
+ecc_streams_encode_convolutional::general_work
(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
- fprintf (stderr, "gr_s_e_c::general_work: Starting #out = %d\n",
- noutput_items);
-
- // FIXME: compute the actual number of output items (1 bit char's) created.
+ // 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);
-
-#if 0
+#if 1
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));
#endif
+ // setup the i/o buffers
+
+ d_in_buf->set_buffer ((void**)(&input_items[0]), t_n_input_items);
+ d_out_buf->set_buffer ((void**)(&output_items[0]), 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]),
+ t_n_input_items = d_encoder->encode (d_in_buf, d_out_buf,
(size_t) noutput_items);
assert (0);
diff --git a/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.h b/gr-error-correcting-codes/src/lib/ecc_streams_encode_convolutional.h
index 66e910916..19f7ea8c1 100644
--- a/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.h
+++ b/gr-error-correcting-codes/src/lib/ecc_streams_encode_convolutional.h
@@ -20,11 +20,11 @@
* Boston, MA 02111-1307, USA.
*/
-#ifndef INCLUDED_GR_STREAMS_ENCODE_CONVOLUTIONAL_H
-#define INCLUDED_GR_STREAMS_ENCODE_CONVOLUTIONAL_H
+#ifndef INCLUDED_ECC_STREAMS_ENCODE_CONVOLUTIONAL_H
+#define INCLUDED_ECC_STREAMS_ENCODE_CONVOLUTIONAL_H
#include <gr_block.h>
-#include <libecc/encoder_convolutional_ic1_ic1.h>
+#include <libecc/encoder_convolutional.h>
/*!
* \brief Encode the incoming streams using a convolutional encoder
@@ -69,12 +69,12 @@
* default is the "all zero" state.
*/
-class gr_streams_encode_convolutional;
-typedef boost::shared_ptr<gr_streams_encode_convolutional>
- gr_streams_encode_convolutional_sptr;
+class ecc_streams_encode_convolutional;
+typedef boost::shared_ptr<ecc_streams_encode_convolutional>
+ ecc_streams_encode_convolutional_sptr;
-gr_streams_encode_convolutional_sptr
-gr_make_streams_encode_convolutional
+ecc_streams_encode_convolutional_sptr
+ecc_make_streams_encode_convolutional
(int frame_size_bits,
int n_code_inputs,
int n_code_outputs,
@@ -83,8 +83,8 @@ gr_make_streams_encode_convolutional
int start_memory_state = 0,
int end_memory_state = 0);
-gr_streams_encode_convolutional_sptr
-gr_make_streams_encode_convolutional_feedback
+ecc_streams_encode_convolutional_sptr
+ecc_make_streams_encode_convolutional_feedback
(int frame_size_bits,
int n_code_inputs,
int n_code_outputs,
@@ -94,10 +94,11 @@ gr_make_streams_encode_convolutional_feedback
int start_memory_state = 0,
int end_memory_state = 0);
-class gr_streams_encode_convolutional : public gr_block
+class ecc_streams_encode_convolutional : public gr_block
{
- friend gr_streams_encode_convolutional_sptr
- gr_make_streams_encode_convolutional
+protected:
+ friend ecc_streams_encode_convolutional_sptr
+ ecc_make_streams_encode_convolutional
(int frame_size_bits,
int n_code_inputs,
int n_code_outputs,
@@ -106,8 +107,8 @@ class gr_streams_encode_convolutional : public gr_block
int start_memory_state,
int end_memory_state);
- friend gr_streams_encode_convolutional_sptr
- gr_make_streams_encode_convolutional_feedback
+ friend ecc_streams_encode_convolutional_sptr
+ ecc_make_streams_encode_convolutional_feedback
(int frame_size_bits,
int n_code_inputs,
int n_code_outputs,
@@ -117,7 +118,7 @@ class gr_streams_encode_convolutional : public gr_block
int start_memory_state,
int end_memory_state);
- gr_streams_encode_convolutional (int frame_size_bits,
+ ecc_streams_encode_convolutional (int frame_size_bits,
int n_code_inputs,
int n_code_outputs,
const std::vector<int> &code_generator,
@@ -125,7 +126,7 @@ class gr_streams_encode_convolutional : public gr_block
int start_memory_state,
int end_memory_state);
- gr_streams_encode_convolutional (int frame_size_bits,
+ ecc_streams_encode_convolutional (int frame_size_bits,
int n_code_inputs,
int n_code_outputs,
const std::vector<int> &code_generator,
@@ -136,12 +137,14 @@ class gr_streams_encode_convolutional : public gr_block
void setup_io_signatures (int n_code_inputs, int n_code_outputs);
- encoder_convolutional_ic1_ic1* d_encoder;
+ encoder_convolutional* d_encoder;
+ code_input_ptr d_in_buf;
+ code_output_ptr d_out_buf;
public:
- ~gr_streams_encode_convolutional ();
+ ~ecc_streams_encode_convolutional ();
- inline encoder_convolutional_ic1_ic1* encoder () {return (d_encoder);};
+ inline encoder_convolutional* encoder () {return (d_encoder);};
virtual void forecast (int noutput_items,
gr_vector_int &ninput_items_required);
@@ -152,4 +155,4 @@ public:
gr_vector_void_star &output_items);
};
-#endif /* INCLUDED_GR_STREAMS_ENCODE_CONVOLUTIONAL_H */
+#endif /* INCLUDED_ECC_STREAMS_ENCODE_CONVOLUTIONAL_H */
diff --git a/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.i b/gr-error-correcting-codes/src/lib/ecc_streams_encode_convolutional.i
index 63d60c6de..7563a95db 100644
--- a/gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.i
+++ b/gr-error-correcting-codes/src/lib/ecc_streams_encode_convolutional.i
@@ -20,20 +20,20 @@
* Boston, MA 02111-1307, USA.
*/
-GR_SWIG_BLOCK_MAGIC(gr,streams_encode_convolutional);
+GR_SWIG_BLOCK_MAGIC(ecc,streams_encode_convolutional);
// Rename second constructor
-%rename(streams_encode_convolutional_feedback) gr_make_streams_encode_convolutional_feedback;
+%rename(streams_encode_convolutional_feedback) ecc_make_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>;
+ %template(x_vector_ecc_streams_encode_convolutional_sptr) vector<ecc_streams_encode_convolutional_sptr>;
};
-gr_streams_encode_convolutional_sptr
-gr_make_streams_encode_convolutional
+ecc_streams_encode_convolutional_sptr
+ecc_make_streams_encode_convolutional
(int block_size_bits,
int n_code_inputs,
int n_code_outputs,
@@ -42,8 +42,8 @@ gr_make_streams_encode_convolutional
int start_memory_state = 0,
int end_memory_state = 0);
-gr_streams_encode_convolutional_sptr
-gr_make_streams_encode_convolutional_feedback
+ecc_streams_encode_convolutional_sptr
+ecc_make_streams_encode_convolutional_feedback
(int block_size_bits,
int n_code_inputs,
int n_code_outputs,
@@ -53,10 +53,10 @@ gr_make_streams_encode_convolutional_feedback
int start_memory_state = 0,
int end_memory_state = 0);
-class gr_streams_encode_convolutional : public gr_block
+class ecc_streams_encode_convolutional : public gr_block
{
private:
- gr_streams_encode_convolutional
+ ecc_streams_encode_convolutional
(int block_size_bits,
int n_code_inputs,
int n_code_outputs,
@@ -65,7 +65,7 @@ private:
int start_memory_state,
int end_memory_state);
- gr_streams_encode_convolutional
+ ecc_streams_encode_convolutional
(int block_size_bits,
int n_code_inputs,
int n_code_outputs,
diff --git a/gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.cc b/gr-error-correcting-codes/src/lib/ecc_streams_encode_turbo.cc
index 9d7f72fe6..0c4cfd1a4 100644
--- a/gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.cc
+++ b/gr-error-correcting-codes/src/lib/ecc_streams_encode_turbo.cc
@@ -24,44 +24,42 @@
#include "config.h"
#endif
-#include <gr_streams_encode_turbo.h>
+#include <ecc_streams_encode_turbo.h>
#include <gr_io_signature.h>
#include <assert.h>
#include <iostream>
-gr_streams_encode_turbo_sptr
-gr_make_streams_encode_turbo
+ecc_streams_encode_turbo_sptr
+ecc_make_streams_encode_turbo
(int n_code_inputs,
int n_code_outputs,
- const std::vector<gr_streams_encode_convolutional_sptr> &encoders,
+ const std::vector<ecc_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));
+ return ecc_streams_encode_turbo_sptr
+ (new ecc_streams_encode_turbo (n_code_inputs,
+ n_code_outputs,
+ encoders,
+ interleavers));
}
-gr_streams_encode_turbo::gr_streams_encode_turbo
+ecc_streams_encode_turbo::ecc_streams_encode_turbo
(int n_code_inputs,
int n_code_outputs,
- const std::vector<gr_streams_encode_convolutional_sptr> &encoders,
+ const std::vector<ecc_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.
+ // error checking is done by the encoder class itself; just pass
+ // items on here. But ... check out individual encoders, to make
+ // sure the total I/O matches those specified by the user.
d_n_encoders = encoders.size ();
if (d_n_encoders < 2) {
- std::cerr << "gr_streams_encode_turbo: Error: "
+ std::cerr << "ecc_streams_encode_turbo: Error: "
"too few (" << d_n_encoders << ") encoders specified; a Turbo "
"code requires at least 2 constituent encoders.\n";
assert (0);
@@ -72,7 +70,7 @@ gr_streams_encode_turbo::gr_streams_encode_turbo
// matter to the encoder (but it might to the decoder; remains to be
// seen).
- encoder_convolutional_ic1_ic1* t_ec = encoders[0]->encoder ();
+ encoder_convolutional* 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;
@@ -89,15 +87,15 @@ gr_streams_encode_turbo::gr_streams_encode_turbo
}
if (t_diff_block_size == true) {
- std::cout << "gr_streams_encode_turbo: Warning: "
+ std::cout << "ecc_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: "
+ std::cout << "ecc_streams_encode_turbo: Warning: "
"Some constituent encoders are differently terminationed.\n";
}
- std::cout << "gr_streams_encode_turbo: setup:\n"
+ std::cout << "ecc_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"
@@ -118,57 +116,41 @@ gr_streams_encode_turbo::gr_streams_encode_turbo
#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);
+ d_encoder = new encoder_turbo (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
+ d_in_buf = new code_input_ic1l (n_code_inputs);
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
+ d_out_buf = new code_output_ic1l (n_code_outputs);
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
+ecc_streams_encode_turbo::~ecc_streams_encode_turbo
()
{
- if (d_encoder)
- delete d_encoder;
+ delete d_encoder;
+ d_encoder = 0;
+ delete d_in_buf;
+ d_in_buf = 0;
+ delete d_out_buf;
+ d_out_buf = 0;
}
-/*
- * 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
+void ecc_streams_encode_turbo::forecast
(int noutput_items,
gr_vector_int &ninput_items_required)
{
@@ -179,26 +161,32 @@ void gr_streams_encode_turbo::forecast
}
int
-gr_streams_encode_turbo::general_work
+ecc_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.
+ // 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);
+#if 1
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));
+#endif
+ // setup the i/o buffers
+
+ d_in_buf->set_buffer ((void**)(&input_items[0]), t_n_input_items);
+ d_out_buf->set_buffer ((void**)(&output_items[0]), 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]),
+ t_n_input_items = d_encoder->encode (d_in_buf, d_out_buf,
(size_t) noutput_items);
+ assert (0);
+
// consume the number of used input items on all input streams
consume_each (t_n_input_items);
diff --git a/gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.h b/gr-error-correcting-codes/src/lib/ecc_streams_encode_turbo.h
index 942772489..16f4427c5 100644
--- a/gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.h
+++ b/gr-error-correcting-codes/src/lib/ecc_streams_encode_turbo.h
@@ -20,11 +20,11 @@
* Boston, MA 02111-1307, USA.
*/
-#ifndef INCLUDED_GR_STREAMS_ENCODE_TURBO_H
-#define INCLUDED_GR_STREAMS_ENCODE_TURBO_H
+#ifndef INCLUDED_ECC_STREAMS_ENCODE_TURBO_H
+#define INCLUDED_ECC_STREAMS_ENCODE_TURBO_H
#include <gr_block.h>
-#include <gr_streams_encode_convolutional.h>
+#include <ecc_streams_encode_convolutional.h>
#if 0
#include <libecc/encoder_turbo_ic1_ic1.h>
@@ -56,41 +56,44 @@
* interleaver.
*/
-class gr_streams_encode_turbo;
+class ecc_streams_encode_turbo;
-typedef boost::shared_ptr<gr_streams_encode_turbo>
-gr_streams_encode_turbo_sptr;
+typedef boost::shared_ptr<ecc_streams_encode_turbo>
+ecc_streams_encode_turbo_sptr;
-gr_streams_encode_turbo_sptr
-gr_make_streams_encode_turbo
+ecc_streams_encode_turbo_sptr
+ecc_make_streams_encode_turbo
(int n_code_inputs,
int n_code_outputs,
- const std::vector<gr_streams_encode_convolutional_sptr> &encoders,
+ const std::vector<ecc_streams_encode_convolutional_sptr> &encoders,
const std::vector<size_t> &interleavers);
-class gr_streams_encode_turbo : public gr_block
+class ecc_streams_encode_turbo : public gr_block
{
- friend gr_streams_encode_turbo_sptr
- gr_make_streams_encode_turbo
+protected:
+ friend ecc_streams_encode_turbo_sptr
+ ecc_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<ecc_streams_encode_convolutional_sptr> &d_encoders,
const std::vector<size_t> &d_interleavers);
- gr_streams_encode_turbo
+ ecc_streams_encode_turbo
(int n_code_inputs,
int n_code_outputs,
- const std::vector<gr_streams_encode_convolutional_sptr> &d_encoders,
+ const std::vector<ecc_streams_encode_convolutional_sptr> &d_encoders,
const std::vector<size_t> &d_interleavers);
- std::vector<gr_streams_encode_turbo_sptr> d_encoders;
+ std::vector<ecc_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;
+ code_input_ptr d_in_buf;
+ code_output_ptr d_out_buf;
public:
- ~gr_streams_encode_turbo ();
+ ~ecc_streams_encode_turbo ();
virtual void forecast (int noutput_items,
gr_vector_int &ninput_items_required);
@@ -101,4 +104,4 @@ public:
gr_vector_void_star &output_items);
};
-#endif /* INCLUDED_GR_STREAMS_ENCODE_TURBO_H */
+#endif /* INCLUDED_ECC_STREAMS_ENCODE_TURBO_H */
diff --git a/gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.i b/gr-error-correcting-codes/src/lib/ecc_streams_encode_turbo.i
index 59ca5c51e..e453cdab9 100644
--- a/gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.i
+++ b/gr-error-correcting-codes/src/lib/ecc_streams_encode_turbo.i
@@ -20,22 +20,22 @@
* Boston, MA 02111-1307, USA.
*/
-GR_SWIG_BLOCK_MAGIC(gr,streams_encode_turbo);
+GR_SWIG_BLOCK_MAGIC(ecc,streams_encode_turbo);
-#include <gr_streams_encode_convolutional.h>
+#include <ecc_streams_encode_convolutional.h>
-gr_streams_encode_turbo_sptr
-gr_make_streams_encode_turbo
+ecc_streams_encode_turbo_sptr
+ecc_make_streams_encode_turbo
(int n_code_inputs,
int n_code_outputs,
- const std::vector<gr_streams_encode_convolutional_sptr> &encoders,
+ const std::vector<ecc_streams_encode_convolutional_sptr> &encoders,
const std::vector<size_t> &interleavers);
-class gr_streams_encode_turbo : public gr_block
+class ecc_streams_encode_turbo : public gr_block
{
- gr_streams_encode_turbo
+ ecc_streams_encode_turbo
(int frame_size_bits,
int n_code_inputs,
- const std::vector<gr_streams_encode_convolutional_sptr> &encoders,
+ const std::vector<ecc_streams_encode_convolutional_sptr> &encoders,
const std::vector<size_t> &interleavers);
};
diff --git a/gr-error-correcting-codes/src/lib/gr_syms_to_metrics.cc b/gr-error-correcting-codes/src/lib/ecc_syms_to_metrics.cc
index 7a1230960..c60eec8a7 100644
--- a/gr-error-correcting-codes/src/lib/gr_syms_to_metrics.cc
+++ b/gr-error-correcting-codes/src/lib/ecc_syms_to_metrics.cc
@@ -24,25 +24,25 @@
#include "config.h"
#endif
-#include <gr_syms_to_metrics.h>
+#include <ecc_syms_to_metrics.h>
#include <gr_io_signature.h>
#include <assert.h>
-gr_syms_to_metrics_sptr
-gr_make_syms_to_metrics (gr_feval_ff* pdf_fcn_0_bit,
- gr_feval_ff* pdf_fcn_1_bit,
- int n_samples,
- float min_sample,
- float max_sample,
- int sample_precision)
+ecc_syms_to_metrics_sptr
+ecc_make_syms_to_metrics (gr_feval_ff* pdf_fcn_0_bit,
+ gr_feval_ff* pdf_fcn_1_bit,
+ int n_samples,
+ float min_sample,
+ float max_sample,
+ int sample_precision)
{
- return gr_syms_to_metrics_sptr
- (new gr_syms_to_metrics (pdf_fcn_0_bit,
- pdf_fcn_1_bit,
- n_samples,
- min_sample,
- max_sample,
- sample_precision));
+ return ecc_syms_to_metrics_sptr
+ (new ecc_syms_to_metrics (pdf_fcn_0_bit,
+ pdf_fcn_1_bit,
+ n_samples,
+ min_sample,
+ max_sample,
+ sample_precision));
}
/*
@@ -63,7 +63,7 @@ static float pdf_fcn_1 (float x)
return (l_pdf_fcn_1_bit->eval (x));
}
-gr_syms_to_metrics::gr_syms_to_metrics
+ecc_syms_to_metrics::ecc_syms_to_metrics
(gr_feval_ff* pdf_fcn_0_bit,
gr_feval_ff* pdf_fcn_1_bit,
int n_samples,
@@ -74,62 +74,45 @@ gr_syms_to_metrics::gr_syms_to_metrics
gr_make_io_signature (1, -1, sizeof (float)),
gr_make_io_signature (0, 0, 0))
{
- if ((sample_precision < 0) | (sample_precision > 32)) {
- fprintf (stderr, "gr_syms_to_metrics: sample_precision must be "
- " between 0 and 32.\n");
- assert (0);
- }
+ // setup the dummy functions to do the conversion from the
+ // python-provided feval classes to that which is needed by the
+ // libecc's code_metrics classes.
l_pdf_fcn_0_bit = pdf_fcn_0_bit;
l_pdf_fcn_1_bit = pdf_fcn_1_bit;
- if (sample_precision == 0) {
- // float
- d_out_item_size_bytes = sizeof (float);
- d_code_metrics = new code_metric_ff (&pdf_fcn_0,
- &pdf_fcn_1,
- n_samples,
- min_sample,
- max_sample);
- } else if (sample_precision <= 8) {
- // use char
- d_out_item_size_bytes = sizeof (char);
- d_code_metrics = new code_metric_fb (&pdf_fcn_0,
- &pdf_fcn_1,
- n_samples,
- min_sample,
- max_sample,
- sample_precision);
- } else if (sample_precision <= 16) {
- // use short
- d_out_item_size_bytes = sizeof (short);
- d_code_metrics = new code_metric_fs (&pdf_fcn_0,
- &pdf_fcn_1,
- n_samples,
- min_sample,
- max_sample,
- sample_precision);
- } else {
- // use long
- d_out_item_size_bytes = sizeof (long);
- d_code_metrics = new code_metric_fl (&pdf_fcn_0,
- &pdf_fcn_1,
- n_samples,
- min_sample,
- max_sample,
- sample_precision);
- }
+ // use the static "create" member function to create the actual
+ // code_metrics to use.
+
+ d_code_metrics_table = libecc_code_metrics_create_table<float>
+ (&pdf_fcn_0,
+ &pdf_fcn_1,
+ n_samples,
+ min_sample,
+ max_sample,
+ sample_precision);
+
+ // get the output item size in bytes from the new code_metrics.
+
+ d_out_item_size_bytes = d_code_metrics_table->out_item_size_bytes ();
+
+ // set the output signature to match that which the code_metrics
+ // will generate.
set_output_signature (gr_make_io_signature (1, -1, d_out_item_size_bytes));
}
-bool gr_syms_to_metrics::check_topology (int ninputs, int noutputs)
+bool ecc_syms_to_metrics::check_topology (int ninputs, int noutputs)
{
+ // there are 2 output streams per input stream; the first is ~to
+ // log(p(0|x)) = log-probability of a 0-bit given the input symbol
+ // 'x'; the second is ~to log(p(1|x)).
+
return ((noutputs == (2*ninputs)) ? true : false);
}
void
-gr_syms_to_metrics::forecast
+ecc_syms_to_metrics::forecast
(int noutput_items,
gr_vector_int &ninput_items_required)
{
@@ -140,7 +123,7 @@ gr_syms_to_metrics::forecast
}
int
-gr_syms_to_metrics::general_work
+ecc_syms_to_metrics::general_work
(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
@@ -153,8 +136,8 @@ gr_syms_to_metrics::general_work
void* t_out_buf_0_bit = (void*)(&(output_items[2*n]));
void* t_out_buf_1_bit = (void*)(&(output_items[(2*n)+1]));
- d_code_metrics->convert (l_n_output_items, t_in_buf,
- t_out_buf_0_bit, t_out_buf_1_bit);
+ d_code_metrics_table->convert (l_n_output_items, t_in_buf,
+ t_out_buf_0_bit, t_out_buf_1_bit);
}
// consume the number of used input items on all input streams
diff --git a/gr-error-correcting-codes/src/lib/gr_syms_to_metrics.h b/gr-error-correcting-codes/src/lib/ecc_syms_to_metrics.h
index d084fde81..0f4577ad7 100644
--- a/gr-error-correcting-codes/src/lib/gr_syms_to_metrics.h
+++ b/gr-error-correcting-codes/src/lib/ecc_syms_to_metrics.h
@@ -28,10 +28,10 @@
#include <vector>
#include <libecc/code_metrics.h>
-class gr_syms_to_metrics;
-typedef boost::shared_ptr<gr_syms_to_metrics> gr_syms_to_metrics_sptr;
+class ecc_syms_to_metrics;
+typedef boost::shared_ptr<ecc_syms_to_metrics> ecc_syms_to_metrics_sptr;
-gr_syms_to_metrics_sptr gr_make_syms_to_metrics
+ecc_syms_to_metrics_sptr ecc_make_syms_to_metrics
(gr_feval_ff* pdf_fcn_0_bit,
gr_feval_ff* pdf_fcn_1_bit,
int n_samples,
@@ -49,18 +49,19 @@ gr_syms_to_metrics_sptr gr_make_syms_to_metrics
* input: stream(s) of float; output: stream(s) of metrics
*/
-class gr_syms_to_metrics : public gr_block
+class ecc_syms_to_metrics : public gr_block
{
- friend gr_syms_to_metrics_sptr
- gr_make_syms_to_metrics (gr_feval_ff* pdf_fcn_0_bit,
- gr_feval_ff* pdf_fcn_1_bit,
- int n_samples,
- float min_sample,
- float max_sample,
- int sample_precision);
+protected:
+ friend ecc_syms_to_metrics_sptr
+ ecc_make_syms_to_metrics (gr_feval_ff* pdf_fcn_0_bit,
+ gr_feval_ff* pdf_fcn_1_bit,
+ int n_samples,
+ float min_sample,
+ float max_sample,
+ int sample_precision);
/*
- * gr_syms_to_metrics: Convert the input soft (float) symbols into
+ * ecc_syms_to_metrics: Convert the input soft (float) symbols into
* log-probabilities (metrics) for use in the convolutional
* decoder. Samples the provided PDF function in 'n_samples'
* places from 'min_sample' to 'max_sample', takes the log of that
@@ -97,17 +98,19 @@ class gr_syms_to_metrics : public gr_block
*
*/
- gr_syms_to_metrics (gr_feval_ff* pdf_fcn_0_bit,
- gr_feval_ff* pdf_fcn_1_bit,
- int n_samples,
- float min_sample,
- float max_sample,
- int sample_precision);
+ ecc_syms_to_metrics (gr_feval_ff* pdf_fcn_0_bit,
+ gr_feval_ff* pdf_fcn_1_bit,
+ int n_samples,
+ float min_sample,
+ float max_sample,
+ int sample_precision);
size_t d_out_item_size_bytes;
- code_metrics* d_code_metrics;
+ code_metrics_table<float>* d_code_metrics_table;
public:
+ ~ecc_syms_to_metrics() {delete d_code_metrics_table;};
+
bool check_topology (int ninputs, int noutputs);
void forecast (int noutput_items, gr_vector_int &ninput_items_required);
diff --git a/gr-error-correcting-codes/src/lib/gr_syms_to_metrics.i b/gr-error-correcting-codes/src/lib/ecc_syms_to_metrics.i
index 6a76a7140..a51a15b9b 100644
--- a/gr-error-correcting-codes/src/lib/gr_syms_to_metrics.i
+++ b/gr-error-correcting-codes/src/lib/ecc_syms_to_metrics.i
@@ -20,9 +20,9 @@
* Boston, MA 02111-1307, USA.
*/
-GR_SWIG_BLOCK_MAGIC(gr,syms_to_metrics);
+GR_SWIG_BLOCK_MAGIC(ecc,syms_to_metrics);
-gr_syms_to_metrics_sptr gr_make_syms_to_metrics
+ecc_syms_to_metrics_sptr ecc_make_syms_to_metrics
(gr_feval_ff* pdf_fcn_0_bit,
gr_feval_ff* pdf_fcn_1_bit,
int n_samples,
@@ -30,12 +30,12 @@ gr_syms_to_metrics_sptr gr_make_syms_to_metrics
float max_sample,
int sample_precision);
-class gr_syms_to_metrics : public gr_block
+class ecc_syms_to_metrics : public gr_block
{
- gr_syms_to_metrics (gr_feval_ff* pdf_fcn_0_bit,
- gr_feval_ff* pdf_fcn_1_bit,
- int n_samples,
- float min_sample,
- float max_sample,
- int sample_precision);
+ ecc_syms_to_metrics (gr_feval_ff* pdf_fcn_0_bit,
+ gr_feval_ff* pdf_fcn_1_bit,
+ int n_samples,
+ float min_sample,
+ float max_sample,
+ int sample_precision);
};
diff --git a/gr-error-correcting-codes/src/lib/libecc/Makefile.am b/gr-error-correcting-codes/src/lib/libecc/Makefile.am
index e2fa9eca5..95e760253 100644
--- a/gr-error-correcting-codes/src/lib/libecc/Makefile.am
+++ b/gr-error-correcting-codes/src/lib/libecc/Makefile.am
@@ -23,31 +23,27 @@ include $(top_srcdir)/Makefile.common
SUBDIRS = mld . tests
-INCLUDES = $(STD_DEFINES_AND_INCLUDES) -I..
+INCLUDES = $(STD_DEFINES_AND_INCLUDES) -I$(top_srcdir)/gr-error-correcting-codes/src/lib
noinst_LTLIBRARIES = libecc.la
libecc_la_SOURCES = \
code_convolutional_trellis.cc \
- code_metrics.cc \
+ code_metrics.cc code_io.cc \
encoder.cc \
encoder_convolutional.cc \
- encoder_convolutional_ic1_ic1.cc \
encoder_turbo.cc \
decoder.cc \
decoder_viterbi.cc \
- decoder_viterbi_full_block.cc \
- decoder_viterbi_full_block_i1_ic1.cc
+ decoder_viterbi_full_block.cc
noinst_HEADERS = \
- code_types.h code_metrics.h \
+ code_types.h code_metrics.h code_io.h \
code_convolutional_trellis.h \
encoder.h encoder_turbo.h \
encoder_convolutional.h \
- encoder_convolutional_ic1_ic1.h \
decoder.h decoder_viterbi.h \
- decoder_viterbi_full_block.h \
- decoder_viterbi_full_block_i1_ic1.h
+ decoder_viterbi_full_block.h
# link the library against the c++ standard library
libecc_la_LIBADD = \
diff --git a/gr-error-correcting-codes/src/lib/libecc/code_convolutional_trellis.cc b/gr-error-correcting-codes/src/lib/libecc/code_convolutional_trellis.cc
index 72b8adbf7..c04fafaec 100644
--- a/gr-error-correcting-codes/src/lib/libecc/code_convolutional_trellis.cc
+++ b/gr-error-correcting-codes/src/lib/libecc/code_convolutional_trellis.cc
@@ -29,8 +29,8 @@
#include <iostream>
#define DO_TIME_THOUGHPUT 0
-#define DO_PRINT_DEBUG 1
-#define DO_PRINT_DEBUG_ENCODE 1
+#define DO_PRINT_DEBUG 0
+#define DO_PRINT_DEBUG_ENCODE 0
#include <mld/mld_timer.h>
#include <mld/n2bs.h>
@@ -285,7 +285,8 @@ code_convolutional_trellis::code_convolutional_trellis_init
// store the parameters for SOAI
- std::vector<size_t> t_fb_generators_soai, t_n_delays_soai, t_io_num_soai;
+ std::vector<memory_t> t_fb_generators_soai;
+ std::vector<size_t> 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;
@@ -554,23 +555,21 @@ code_convolutional_trellis::create_trellis
for (size_t m = 0; m < d_n_states; m++) {
d_trellis[m].resize (d_n_input_combinations);
- for (size_t n = 0; n < d_n_input_combinations; n++) {
- connection_t_ptr t_connection = &(d_trellis[m][n]);
- t_connection->d_output_bits.resize (d_n_code_outputs);
- }
}
// fill in the trellis
- for (size_t m = 0; m < d_n_states; m++) {
- for (size_t n = 0; n < d_n_input_combinations; n++) {
+ for (memory_t m = 0; m < d_n_states; m++) {
+ for (memory_t n = 0; n < d_n_input_combinations; n++) {
connection_t_ptr t_connection = &(d_trellis[m][n]);
encode_single (m, n, t_connection->d_to_state,
t_connection->d_output_bits);
if (DO_PRINT_DEBUG_ENCODE) {
std::cout << "set d_t[" << n2bs(m,d_total_n_delays) << "][" <<
n2bs(n,d_n_code_inputs) << "] : to_st = " <<
- n2bs(t_connection->d_to_state,d_total_n_delays) << "\n";
+ n2bs(t_connection->d_to_state,d_total_n_delays) <<
+ ", o_b = " << n2bs(t_connection->d_output_bits,d_n_code_outputs) <<
+ "\n";
}
}
}
@@ -642,11 +641,33 @@ code_convolutional_trellis::mux_inputs
}
void
+code_convolutional_trellis::demux_outputs
+(memory_t outputs,
+ std::vector<char>& out_vec)
+{
+ for (size_t m = 0; m < d_n_code_outputs; m++, outputs >>= 1) {
+ out_vec[m] = (char)(outputs & 1);
+ }
+}
+
+memory_t
+code_convolutional_trellis::mux_outputs
+(const std::vector<char>& out_vec)
+{
+ size_t bit_shift = 0;
+ memory_t outputs = 0;
+ for (size_t m = 0; m < out_vec.size(); m++, bit_shift++) {
+ outputs |= (((memory_t)(out_vec[m]&1)) << bit_shift);
+ }
+ return (outputs);
+}
+
+void
code_convolutional_trellis::encode_single
(memory_t in_state,
- size_t inputs,
+ memory_t inputs,
memory_t& out_state,
- std::vector<char>& out_bits)
+ memory_t& out_bits)
{
// set input parameters
@@ -672,42 +693,45 @@ code_convolutional_trellis::encode_single
// retrieve the output parameters
out_state = mux_state (d_memory);
- out_bits = d_current_outputs;
+ out_bits = mux_outputs (d_current_outputs);
}
void
code_convolutional_trellis::encode_lookup
(memory_t& state,
const std::vector<char>& inputs,
- std::vector<char>& out_bits)
+ memory_t& out_bits)
{
- if (DO_PRINT_DEBUG_ENCODE) {
- std::cout << "using d_t[" << state << "][" << mux_inputs(inputs) <<
- "] = ";
- std::cout.flush ();
- }
-
connection_t_ptr t_connection = &(d_trellis[state][mux_inputs(inputs)]);
-
- if (DO_PRINT_DEBUG_ENCODE) {
- std::cout << t_connection << ": to_state = "
- << t_connection->d_to_state << "\n";
- }
-
state = t_connection->d_to_state;
out_bits = t_connection->d_output_bits;
}
void
+code_convolutional_trellis::encode_lookup
+(memory_t& state,
+ const std::vector<char>& inputs,
+ std::vector<char>& out_bits)
+{
+ connection_t_ptr t_connection = &(d_trellis[state][mux_inputs(inputs)]);
+ state = t_connection->d_to_state;
+ demux_outputs (t_connection->d_output_bits, out_bits);
+}
+
+void
code_convolutional_trellis::get_termination_inputs
(memory_t term_start_state,
size_t bit_num,
std::vector<char>& inputs)
{
- inputs.resize (d_n_code_inputs);
+#if 1
+ // for now, just assign all 0's
+ inputs.assign (d_n_code_inputs, 0);
+#else
for (size_t m = 0; m < d_n_code_inputs; m++) {
inputs[m] = ((d_term_inputs[term_start_state][m]) >> bit_num) & 1;
}
+#endif
}
void
diff --git a/gr-error-correcting-codes/src/lib/libecc/code_convolutional_trellis.h b/gr-error-correcting-codes/src/lib/libecc/code_convolutional_trellis.h
index 205ccc03d..3aee1a0a6 100644
--- a/gr-error-correcting-codes/src/lib/libecc/code_convolutional_trellis.h
+++ b/gr-error-correcting-codes/src/lib/libecc/code_convolutional_trellis.h
@@ -32,12 +32,12 @@
*
* d_to_state: memory configuration of the "to" state
*
- * d_output_bits: the output bits for this connection
+ * d_output_bits: the output bits for this connection, mux'ed
*/
typedef struct connection_t {
memory_t d_to_state;
- std::vector<char> d_output_bits;
+ memory_t d_output_bits;
} connection_t, *connection_t_ptr;
/*
@@ -152,9 +152,11 @@ public:
/* 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);};
+ inline const size_t block_size_bits () {return (d_block_size_bits);};
+ inline const size_t n_code_inputs () {return (d_n_code_inputs);};
+ inline const size_t n_code_outputs () {return (d_n_code_outputs);};
+ inline const size_t n_states () {return (d_n_states);};
+ inline const size_t n_input_combinations () {return (d_n_input_combinations);};
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);};
@@ -165,14 +167,25 @@ public:
size_t bit_num,
std::vector<char>& inputs);
+ // encode_lookup: given the starting state and inputs, return the
+ // resulting state and output bits. Two versions: the first is
+ // better for decoding, while the second is better for encoding.
+
+ void encode_lookup (memory_t& state,
+ const std::vector<char>& inputs,
+ memory_t& out_bits);
void encode_lookup (memory_t& state,
const std::vector<char>& inputs,
std::vector<char>& out_bits);
+ // methods for setting and retrieving the state, inputs, and outputs.
+
void demux_state (memory_t in_state, std::vector<memory_t>& memories);
memory_t mux_state (const std::vector<memory_t>& memories);
void demux_inputs (memory_t inputs, std::vector<char>& in_vec);
memory_t mux_inputs (const std::vector<char>& in_vec);
+ void demux_outputs (memory_t outputs, std::vector<char>& out_vec);
+ memory_t mux_outputs (const std::vector<char>& out_vec);
protected:
#if 0
@@ -267,7 +280,7 @@ protected:
void encode_single (memory_t in_state,
memory_t inputs,
memory_t& out_state,
- std::vector<char>& out_bits);
+ memory_t& out_bits);
virtual void encode_single_soai ();
virtual void encode_single_siao ();
virtual void encode_single_soai_fb ();
diff --git a/gr-error-correcting-codes/src/lib/libecc/code_io.cc b/gr-error-correcting-codes/src/lib/libecc/code_io.cc
new file mode 100644
index 000000000..e25309069
--- /dev/null
+++ b/gr-error-correcting-codes/src/lib/libecc/code_io.cc
@@ -0,0 +1,33 @@
+/* -*- 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 <code_io.h>
+
+#define DO_PRINT_DEBUG 0
+
+static const int g_num_bits_per_byte = 8;
+
+// nothing yet ... it's all in the header file for now.
diff --git a/gr-error-correcting-codes/src/lib/libecc/code_io.h b/gr-error-correcting-codes/src/lib/libecc/code_io.h
new file mode 100644
index 000000000..1147db51f
--- /dev/null
+++ b/gr-error-correcting-codes/src/lib/libecc/code_io.h
@@ -0,0 +1,556 @@
+/* -*- 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_CODE_IO_H
+#define INCLUDED_CODE_IO_H
+
+#include "code_types.h"
+#include <vector>
+#include <assert.h>
+#include <iostream>
+
+/*
+ * code_io provides classes which do the input and output for these
+ * codes. One can add another class with its specific needs primarily
+ * by changing the way that the provided data is manipulated to read
+ * or write data items.
+ */
+
+/*
+ * combined io classes
+ */
+
+class code_io
+{
+public:
+ inline code_io (size_t n_streams) {
+ if (n_streams < 1) {
+ std::cerr << "code_io::code_io: Error:" <<
+ "Provided # of streams (" << n_streams <<
+ ") must be at least 1.\n";
+ assert (0);
+ }
+ d_n_streams = n_streams;
+ d_buf_ptrs.resize (d_n_streams);
+ };
+
+ virtual ~code_io () {};
+
+ inline void set_buffer (void** buffer, size_t n_items) {
+ if (buffer == 0) {
+ std::cerr << "code_io::set_buffer: Error:" <<
+ "Provided buffer is NULL.\n";
+ assert (0);
+ }
+ if (n_items == 0) {
+ std::cerr << "code_io::set_buffer: Warning:" <<
+ "Provided # of items is 0!\n";
+ }
+ d_buf = buffer;
+ d_n_items = d_n_items_left = n_items;
+ for (size_t m = 0; m < d_n_streams; m++) {
+ d_buf_ptrs[m] = d_buf[m];
+ }
+ };
+
+ inline void set_buffer (std::vector<void*>* buffer, size_t n_items) {
+ set_buffer (&((*buffer)[0]), n_items);};
+
+ inline void set_buffer (std::vector<void*>& buffer, size_t n_items) {
+ set_buffer (&(buffer[0]), n_items);};
+
+ inline virtual void increment_indices () {
+ if (d_n_items_left == 0) {
+ std::cerr << "code_io::increment_indices: Warning: "
+ "No items left!\n";
+ } else
+ d_n_items_left--;
+ };
+
+ // methods for getting info on class internals
+
+ const size_t& n_items_left () {return (d_n_items_left);};
+ const size_t n_items_used () {return (d_n_items - d_n_items_left);};
+ const size_t n_streams () {return (d_n_streams);};
+
+protected:
+ void** d_buf;
+ std::vector<void*> d_buf_ptrs;
+ size_t d_n_streams, d_n_items, d_n_items_left;
+};
+
+/*
+ * input classes
+ */
+
+class code_input : public code_io
+{
+public:
+ inline code_input (size_t n_streams) : code_io (n_streams) {};
+ virtual ~code_input () {};
+ virtual void read_item (void* item, size_t stream_n) = 0;
+ virtual void read_items (void* items) = 0;
+ inline virtual void increment_indices () {code_io::increment_indices ();};
+};
+
+typedef code_input* code_input_ptr;
+
+class code_input_id : public code_input
+{
+private:
+ typedef double input_t;
+
+public:
+/*!
+ * class code_input_id : public code_input
+ *
+ * "id":
+ * 'i': one stream per code input as defined by the instantiated
+ * code ("individual", not mux'ed);
+ * 'f': streams of double;
+ */
+ inline code_input_id (size_t n_streams) : code_input (n_streams) {};
+ virtual ~code_input_id () {};
+
+ inline virtual void read_item (void* item, size_t stream_n) {
+ /* no error checking for better speed! */
+ input_t* t_item = (input_t*) item;
+ (*t_item) = (*((input_t*)(d_buf_ptrs[stream_n])));
+ };
+ inline virtual void read_items (void* items) {
+ /* no error checking for better speed! */
+ input_t* t_items = (input_t*) items;
+ for (size_t m = 0; m < d_n_streams; m++) {
+ t_items[m] = (*((input_t*)(d_buf_ptrs[m])));
+ }
+ };
+ inline virtual void increment_indices () {
+ code_input::increment_indices ();
+ for (size_t m = 0; m < d_n_streams; m++) {
+ input_t* t_buf = (input_t*) d_buf_ptrs[m];
+ d_buf_ptrs[m] = (void*)(++t_buf);
+ }
+ };
+};
+
+class code_input_if : public code_input
+{
+private:
+ typedef float input_t;
+
+public:
+/*!
+ * class code_input_if : public code_input
+ *
+ * "if":
+ * 'i': one stream per code input as defined by the instantiated
+ * code ("individual", not mux'ed);
+ * 'f': streams of float;
+ */
+ inline code_input_if (size_t n_streams) : code_input (n_streams) {};
+ virtual ~code_input_if () {};
+
+ inline virtual void read_item (void* item, size_t stream_n) {
+ /* no error checking for better speed! */
+ input_t* t_item = (input_t*) item;
+ (*t_item) = (*((input_t*)(d_buf_ptrs[stream_n])));
+ };
+ inline virtual void read_items (void* items) {
+ /* no error checking for better speed! */
+ input_t* t_items = (input_t*) items;
+ for (size_t m = 0; m < d_n_streams; m++) {
+ t_items[m] = (*((input_t*)(d_buf_ptrs[m])));
+ }
+ };
+ inline virtual void increment_indices () {
+ code_input::increment_indices ();
+ for (size_t m = 0; m < d_n_streams; m++) {
+ input_t* t_buf = (input_t*) d_buf_ptrs[m];
+ d_buf_ptrs[m] = (void*)(++t_buf);
+ }
+ };
+};
+
+class code_input_ic : public code_input
+{
+private:
+ typedef char input_t;
+
+public:
+/*!
+ * class code_input_is : public code_input
+ *
+ * "ic":
+ * 'i': one stream per code input as defined by the instantiated
+ * code ("individual", not mux'ed);
+ * 'c': streams of char;
+ */
+ inline code_input_ic (size_t n_streams) : code_input (n_streams) {};
+ virtual ~code_input_ic () {};
+
+ inline virtual void read_item (void* item, size_t stream_n) {
+ /* no error checking for better speed! */
+ input_t* t_item = (input_t*) item;
+ (*t_item) = (*((input_t*)(d_buf_ptrs[stream_n])));
+ };
+ inline virtual void read_items (void* items) {
+ /* no error checking for better speed! */
+ input_t* t_items = (input_t*) items;
+ for (size_t m = 0; m < d_n_streams; m++) {
+ t_items[m] = (*((input_t*)(d_buf_ptrs[m])));
+ }
+ };
+ inline virtual void increment_indices () {
+ code_input::increment_indices ();
+ for (size_t m = 0; m < d_n_streams; m++) {
+ input_t* t_buf = (input_t*) d_buf_ptrs[m];
+ d_buf_ptrs[m] = (void*)(++t_buf);
+ }
+ };
+};
+
+class code_input_is : public code_input
+{
+private:
+ typedef short input_t;
+
+public:
+/*!
+ * class code_input_is : public code_input
+ *
+ * "is":
+ * 'i': one stream per code input as defined by the instantiated
+ * code ("individual", not mux'ed);
+ * 's': streams of short;
+ */
+ inline code_input_is (size_t n_streams) : code_input (n_streams) {};
+ virtual ~code_input_is () {};
+
+ inline virtual void read_item (void* item, size_t stream_n) {
+ /* no error checking for better speed! */
+ input_t* t_item = (input_t*) item;
+ (*t_item) = (*((input_t*)(d_buf_ptrs[stream_n])));
+ };
+ inline virtual void read_items (void* items) {
+ /* no error checking for better speed! */
+ input_t* t_items = (input_t*) items;
+ for (size_t m = 0; m < d_n_streams; m++) {
+ t_items[m] = (*((input_t*)(d_buf_ptrs[m])));
+ }
+ };
+ inline virtual void increment_indices () {
+ code_input::increment_indices ();
+ for (size_t m = 0; m < d_n_streams; m++) {
+ input_t* t_buf = (input_t*) d_buf_ptrs[m];
+ d_buf_ptrs[m] = (void*)(++t_buf);
+ }
+ };
+};
+
+class code_input_il : public code_input
+{
+private:
+ typedef long input_t;
+
+public:
+/*!
+ * class code_input_il : public code_input
+ *
+ * "il":
+ * 'i': one stream per code input as defined by the instantiated
+ * code ("individual", not mux'ed);
+ * 'l': streams of long;
+ */
+ inline code_input_il (size_t n_streams) : code_input (n_streams) {};
+ virtual ~code_input_il () {};
+
+ inline virtual void read_item (void* item, size_t stream_n) {
+ /* no error checking for better speed! */
+ input_t* t_item = (input_t*) item;
+ (*t_item) = (*((input_t*)(d_buf_ptrs[stream_n])));
+ };
+ inline virtual void read_items (void* items) {
+ /* no error checking for better speed! */
+ input_t* t_items = (input_t*) items;
+ for (size_t m = 0; m < d_n_streams; m++) {
+ t_items[m] = (*((input_t*)(d_buf_ptrs[m])));
+ }
+ };
+ inline virtual void increment_indices () {
+ code_input::increment_indices ();
+ for (size_t m = 0; m < d_n_streams; m++) {
+ input_t* t_buf = (input_t*) d_buf_ptrs[m];
+ d_buf_ptrs[m] = (void*)(++t_buf);
+ }
+ };
+};
+
+class code_input_ill : public code_input
+{
+private:
+ typedef long long input_t;
+
+public:
+/*!
+ * class code_input_ill : public code_input
+ *
+ * "ill":
+ * 'i': one stream per code input as defined by the instantiated
+ * code ("individual", not mux'ed);
+ * 'll': streams of long long;
+ */
+ inline code_input_ill (size_t n_streams) : code_input (n_streams) {};
+ virtual ~code_input_ill () {};
+
+ inline virtual void read_item (void* item, size_t stream_n) {
+ /* no error checking for better speed! */
+ input_t* t_item = (input_t*) item;
+ (*t_item) = (*((input_t*)(d_buf_ptrs[stream_n])));
+ };
+ inline virtual void read_items (void* items) {
+ /* no error checking for better speed! */
+ input_t* t_items = (input_t*) items;
+ for (size_t m = 0; m < d_n_streams; m++) {
+ t_items[m] = (*((input_t*)(d_buf_ptrs[m])));
+ }
+ };
+ inline virtual void increment_indices () {
+ code_input::increment_indices ();
+ for (size_t m = 0; m < d_n_streams; m++) {
+ input_t* t_buf = (input_t*) d_buf_ptrs[m];
+ d_buf_ptrs[m] = (void*)(++t_buf);
+ }
+ };
+};
+
+class code_input_ic1 : public code_input
+{
+public:
+/*!
+ * class code_input_ic1 : public code_input
+ *
+ * "ic":
+ * 'i': one stream per code input as defined by the instantiated
+ * code ("individual", not mux'ed);
+ * 'c': streams of char;
+ * '1': single bit per char;
+ * --> which bit to choose left to an inheriting class
+ */
+
+ inline code_input_ic1 (size_t n_streams) : code_input (n_streams) {};
+ virtual ~code_input_ic1 () {};
+
+ inline virtual void read_item (void* item, size_t stream_n) {
+ /* no error checking for better speed! */
+ char* t_item = (char*) item;
+ (*t_item) = (*((char*)(d_buf_ptrs[stream_n]))) & d_which_bit;
+ };
+ inline virtual void read_items (void* items) {
+ /* no error checking for better speed! */
+ char* t_items = (char*) items;
+ for (size_t m = 0; m < d_n_streams; m++) {
+ t_items[m] = (*((char*)(d_buf_ptrs[m]))) & d_which_bit;
+ }
+ };
+ inline virtual void increment_indices () {
+ code_input::increment_indices ();
+ for (size_t m = 0; m < d_n_streams; m++) {
+ char* t_buf = (char*) d_buf_ptrs[m];
+ d_buf_ptrs[m] = (void*)(++t_buf);
+ }
+ };
+
+protected:
+ char d_which_bit;
+};
+
+class code_input_ic1l : public code_input_ic1
+{
+public:
+/*!
+ * class code_input_ic1l : public code_input_ic1
+ *
+ * "ic1l":
+ * 'i': one stream per code input as defined by the instantiated
+ * code ("individual", not mux'ed);
+ * 'c': streams of char;
+ * '1': single bit per char;
+ * 'l': using only the LSB of the char.
+ */
+
+ inline code_input_ic1l (size_t n_streams) :
+ code_input_ic1 (n_streams) {d_which_bit = 1;};
+ virtual ~code_input_ic1l () {};
+};
+
+class code_input_ic1h : public code_input_ic1
+{
+public:
+/*!
+ * class code_input_ic1h : public code_input_ic1
+ *
+ * "ic1h":
+ * 'i': one stream per code input as defined by the instantiated
+ * code ("individual", not mux'ed);
+ * 'c': streams of char;
+ * '1': single bit per char;
+ * 'h': using only the MSB of the char.
+ */
+
+ inline code_input_ic1h (size_t n_streams)
+ : code_input_ic1 (n_streams) {d_which_bit = 128;};
+ virtual ~code_input_ic1h () {};
+};
+
+class code_input_ic8l : public code_input_ic1l
+{
+protected:
+ size_t d_bit_shift;
+ const static size_t g_num_bits_per_byte = 8;
+
+public:
+/*!
+ * class code_input_ic8l : public code_input_ic1l
+ *
+ * "ic8l":
+ * 'i': one stream per code input as defined by the instantiated
+ * code ("individual", not mux'ed);
+ * 'c': streams of char;
+ * '8': using all 8 bits per char;
+ * 'l': starting with the LSB and working up
+ */
+
+ inline code_input_ic8l (size_t n_streams) :
+ code_input_ic1l (n_streams) {d_bit_shift = 0;};
+
+ virtual ~code_input_ic8l () {};
+
+ inline virtual void increment_indices () {
+ code_input::increment_indices ();
+ if (++d_bit_shift % g_num_bits_per_byte == 0) {
+ d_bit_shift = 0;
+ for (size_t m = 0; m < d_n_streams; m++) {
+ char* t_buf = (char*) d_buf_ptrs[m];
+ d_buf_ptrs[m] = (void*)(++t_buf);
+ }
+ } else {
+ for (size_t m = 0; m < d_n_streams; m++) {
+ char* t_buf = (char*) d_buf_ptrs[m];
+ (*t_buf) >>= 1;
+ }
+ }
+ };
+};
+
+class code_input_ic8h : public code_input_ic1h
+{
+protected:
+ size_t d_bit_shift;
+ const static size_t g_num_bits_per_byte = 8;
+
+public:
+/*!
+ * class code_input_ic8h : public code_input_ic1h
+ *
+ * "ic8h":
+ * 'i': one stream per code input as defined by the instantiated
+ * code ("individual", not mux'ed);
+ * 'c': streams of char;
+ * '8': using all 8 bits per char;
+ * 'h': starting with the MSB and working down
+ */
+
+ inline code_input_ic8h (size_t n_streams) :
+ code_input_ic1h (n_streams) {d_bit_shift = 0;};
+
+ virtual ~code_input_ic8h () {};
+
+ inline virtual void increment_indices () {
+ code_input::increment_indices ();
+ if (++d_bit_shift % g_num_bits_per_byte == 0) {
+ d_bit_shift = 0;
+ for (size_t m = 0; m < d_n_streams; m++) {
+ char* t_buf = (char*) d_buf_ptrs[m];
+ d_buf_ptrs[m] = (void*)(++t_buf);
+ }
+ } else {
+ for (size_t m = 0; m < d_n_streams; m++) {
+ char* t_buf = (char*) d_buf_ptrs[m];
+ (*t_buf) <<= 1;
+ }
+ }
+ };
+};
+
+/*
+ * output classes
+ */
+
+class code_output : public code_io
+{
+public:
+ code_output (size_t n_streams) : code_io (n_streams) {};
+ virtual ~code_output () {};
+ virtual void write_item (const void* item, size_t stream_n) = 0;
+ virtual void write_items (const void* items) = 0;
+ virtual inline void increment_indices () {code_io::increment_indices ();};
+};
+
+typedef code_output* code_output_ptr;
+
+class code_output_ic1l : public code_output
+{
+public:
+/*!
+ * class code_output_ic1l : public code_output
+ *
+ * 'i': one stream per code input as defined by the instantiated
+ * code ("individual", not mux'ed);
+ * 'c': streams of char;
+ * '1': single bit per char;
+ * 'l': using only the right-most justified (LSB).
+ */
+
+ inline code_output_ic1l (size_t n_streams) : code_output (n_streams) {};
+ virtual ~code_output_ic1l () {};
+
+ inline virtual void write_item (const void* item, size_t stream_n) {
+ /* no error checking for better speed! */
+ const char* t_item = (char*) item;
+ (*((char*)(d_buf_ptrs[stream_n]))) = (*t_item) & 1;
+ };
+ inline virtual void write_items (const void* items) {
+ /* no error checking for better speed! */
+ const char* t_items = (char*) items;
+ for (size_t m = 0; m < d_n_streams; m++)
+ (*((char*)(d_buf_ptrs[m]))) = (t_items[m]) & 1;
+ };
+ inline virtual void increment_indices () {
+ code_output::increment_indices ();
+ for (size_t m = 0; m < d_n_streams; m++) {
+ char* t_buf = (char*) d_buf_ptrs[m];
+ d_buf_ptrs[m] = (void*)(++t_buf);
+ }
+ };
+};
+
+#endif /* INCLUDED_CODE_IO_H */
diff --git a/gr-error-correcting-codes/src/lib/libecc/code_metrics.cc b/gr-error-correcting-codes/src/lib/libecc/code_metrics.cc
index 392450863..c1278498d 100644
--- a/gr-error-correcting-codes/src/lib/libecc/code_metrics.cc
+++ b/gr-error-correcting-codes/src/lib/libecc/code_metrics.cc
@@ -29,274 +29,261 @@
#include <math.h>
#include <assert.h>
-code_metric_ff::code_metric_ff
-(pdf_fcn_t pdf_fcn_0_bit,
- pdf_fcn_t pdf_fcn_1_bit,
+template<typename pdf_fcn_io_t>
+code_metrics_table<pdf_fcn_io_t>*
+libecc_code_metrics_create_table
+(pdf_fcn_io_t (*pdf_fcn_0_bit) (pdf_fcn_io_t),
+ pdf_fcn_io_t (*pdf_fcn_1_bit) (pdf_fcn_io_t),
size_t n_samples,
pdf_fcn_io_t min_sample,
- pdf_fcn_io_t max_sample)
+ pdf_fcn_io_t max_sample,
+ int sample_precision)
{
- if (n_samples < 2) {
- fprintf (stderr, "code_metric_f32:: n_samples "
- "must be at least 2.\n");
+ if (! pdf_fcn_0_bit) {
+ std::cerr << "libecc_code_metrics_create_table: Error: "
+ "pdf_fcn_0_bit must be a non-null pointer to function.\n";
assert (0);
}
- if (min_sample >= max_sample) {
- fprintf (stderr, "code_metric_f32:: min_sample must be "
- "less than max_sample.\n");
+ if (! pdf_fcn_1_bit) {
+ std::cerr << "libecc_code_metrics_create_table: Error: "
+ "pdf_fcn_0_bit must be a non-null pointer to function.\n";
assert (0);
}
- if (! pdf_fcn_0_bit) {
- fprintf (stderr, "code_metric_f32:: pdf_fcn_0_bit must be "
- "a non-null pointer to function.\n");
+ if (n_samples < 2) {
+ std::cerr << "libecc_code_metrics_create_table: Error: "
+ "n_samples must be at least 2.\n";
assert (0);
}
- if (! pdf_fcn_1_bit) {
- fprintf (stderr, "code_metric_f32:: pdf_fcn_0_bit must be "
- "a non-null pointer to function.\n");
+ if (min_sample >= max_sample) {
+ std::cerr << "libecc_code_metrics_create_table: Error: "
+ "min_sample must be less than max_sample.\n";
assert (0);
}
-
- d_n_samples = n_samples;
- d_max_sample = max_sample;
- d_min_sample = min_sample;
- d_delta = (max_sample - min_sample) / (n_samples - 1);
- d_pdf_fcn_0_bit = pdf_fcn_0_bit;
- d_pdf_fcn_1_bit = pdf_fcn_1_bit;
- d_metric_table_0_bit.assign (n_samples, 0);
- d_metric_table_1_bit.assign (n_samples, 0);
-
- pdf_fcn_io_t l_val = min_sample;
- for (size_t m = 0; m < n_samples; m++) {
- d_metric_table_0_bit[m] = logf ((*pdf_fcn_0_bit)(l_val));
- d_metric_table_1_bit[m] = logf ((*pdf_fcn_1_bit)(l_val));
- l_val += d_delta;
+ if ((sample_precision < 0) | (sample_precision > 32)) {
+ std::cerr << "libecc_code_metrics_create_table: Error: "
+ "sample_precision must be between 0 and 32.\n";
+ assert (0);
}
-}
-void code_metric_ff::lookup
-(pdf_fcn_io_t sym,
- void* bit_0,
- void* bit_1)
-{
- metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
- metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
-
- if (sym <= d_min_sample) {
- *l_bit_0 = d_metric_table_0_bit[0];
- *l_bit_1 = d_metric_table_1_bit[0];
- return;
- }
- if (sym >= d_max_sample) {
- *l_bit_0 = d_metric_table_0_bit.back ();
- *l_bit_1 = d_metric_table_1_bit.back ();
- return;
+ code_metrics_table<pdf_fcn_io_t>* t_code_metrics_table;
+
+ if (sample_precision == 0) {
+ // float
+ t_code_metrics_table = new code_metrics_table_work
+ <pdf_fcn_io_t, float>(pdf_fcn_0_bit,
+ pdf_fcn_1_bit,
+ n_samples,
+ min_sample,
+ max_sample);
+ } else if (sample_precision <= 8) {
+ // use char
+ t_code_metrics_table = new code_metrics_table_work
+ <pdf_fcn_io_t, unsigned char>(pdf_fcn_0_bit,
+ pdf_fcn_1_bit,
+ n_samples,
+ min_sample,
+ max_sample,
+ sample_precision);
+ } else if (sample_precision <= 16) {
+ // use short
+ t_code_metrics_table = new code_metrics_table_work
+ <pdf_fcn_io_t, unsigned short>(pdf_fcn_0_bit,
+ pdf_fcn_1_bit,
+ n_samples,
+ min_sample,
+ max_sample,
+ sample_precision);
+ } else {
+ // use long
+ t_code_metrics_table = new code_metrics_table_work
+ <pdf_fcn_io_t, unsigned long>(pdf_fcn_0_bit,
+ pdf_fcn_1_bit,
+ n_samples,
+ min_sample,
+ max_sample,
+ sample_precision);
}
- size_t l_ndx = (size_t) roundf ((sym - d_min_sample) / d_delta);
- *l_bit_0 = d_metric_table_0_bit[l_ndx];
- *l_bit_1 = d_metric_table_1_bit[l_ndx];
-}
-
-void code_metric_ff::convert
-(size_t n_syms,
- pdf_fcn_io_t* sym,
- void* bit_0,
- void* bit_1)
-{
- metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
- metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
-
- for (size_t m = n_syms; m > 0; m--)
- lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++);
+ return (t_code_metrics_table);
}
-code_metric_fl::code_metric_fl
+template<typename pdf_fcn_io_t>
+code_metrics_table<pdf_fcn_io_t>::code_metrics_table
(pdf_fcn_t pdf_fcn_0_bit,
pdf_fcn_t pdf_fcn_1_bit,
size_t n_samples,
pdf_fcn_io_t min_sample,
- pdf_fcn_io_t max_sample,
- int sample_precision)
+ pdf_fcn_io_t max_sample)
{
- if (n_samples < 2) {
- fprintf (stderr, "code_metric_fl:: n_samples "
- "must be at least 2.\n");
- assert (0);
- }
- if (min_sample >= max_sample) {
- fprintf (stderr, "code_metric_fl:: min_sample must be "
- "less than max_sample.\n");
- assert (0);
- }
- if (! pdf_fcn_0_bit) {
- fprintf (stderr, "code_metric_fl:: pdf_fcn_0_bit must be "
- "a non-null pointer to function.\n");
- assert (0);
- }
- if (! pdf_fcn_1_bit) {
- fprintf (stderr, "code_metric_fl:: pdf_fcn_0_bit must be "
- "a non-null pointer to function.\n");
- assert (0);
- }
- if (sample_precision < 16 || sample_precision > 32) {
- fprintf (stderr, "code_metric_fl:: sample_precision must be "
- "between 16 and 32 for this class.\n");
- assert (0);
- }
+ // internally, all samples are taken as pdf_fcn_io_t initially, and
+ // only converted to other values by their specific constructors.
- d_sample_precision = sample_precision;
d_n_samples = n_samples;
d_max_sample = max_sample;
d_min_sample = min_sample;
- d_delta = (max_sample - min_sample) / (n_samples - 1);
+ d_delta = (max_sample - min_sample) / ((pdf_fcn_io_t) n_samples);
d_pdf_fcn_0_bit = pdf_fcn_0_bit;
d_pdf_fcn_1_bit = pdf_fcn_1_bit;
- d_metric_table_0_bit.assign (n_samples, 0);
- d_metric_table_1_bit.assign (n_samples, 0);
-
- // get the scale factor for converting from float to sample_precision
- // maps:
- // logf (pdf_fcn_0_bit->eval (d_min_sample)) -> l_min_map
- // logf (pdf_fcn_0_bit->eval (d_max_sample)) -> l_max_map
-
- metric_t l_min_map = - (1 << (sample_precision - 1));
- pdf_fcn_io_t l_min_log_val_0 = logf ((*pdf_fcn_0_bit)(d_min_sample));
- pdf_fcn_io_t l_max_log_val_0 = logf ((*pdf_fcn_0_bit)(d_max_sample));
- pdf_fcn_io_t l_slope_0 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) /
- (l_max_log_val_0 - l_min_log_val_0));
- pdf_fcn_io_t l_min_log_val_1 = logf ((*pdf_fcn_1_bit)(d_min_sample));
- pdf_fcn_io_t l_max_log_val_1 = logf ((*pdf_fcn_1_bit)(d_max_sample));
- pdf_fcn_io_t l_slope_1 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) /
- (l_max_log_val_1 - l_min_log_val_1));
+ // use a sub-sample by 100 to better determine the actual "bin"
+ // probability values for each actual sample. Each "bin" is 100
+ // delta's less than the min_sample up to the min_sample+delta; then
+ // each delta; then from the max_sample-delta to 100 delta's more
+ // than the max sample. Once normalized, these give a reasonable
+ // interpretation of the PDF function.
+
+ pdf_fcn_io_t d_sub_delta = d_delta / ((pdf_fcn_io_t) 100);
+ pdf_fcn_io_t d_sub_min_sample = d_min_sample - ((pdf_fcn_io_t) 100)*d_delta;
+ pdf_fcn_io_t d_sup_max_sample = d_max_sample + ((pdf_fcn_io_t) 100)*d_delta;
+
+ d_pdf_fcn_0_samples.assign (d_n_samples, 0);
+ d_pdf_fcn_1_samples.assign (d_n_samples, 0);
+
+ pdf_fcn_io_t t_val, t_sum_0, t_sum_1, t_max_0, t_max_1, t_min_0, t_min_1;
+ t_sum_0 = t_sum_1 = t_max_0 = t_max_1 = t_min_0 = t_min_1 = 0;
+ size_t m = 0;
+ t_val = d_sub_min_sample;
+ for (; m < (d_n_samples - 1); m++) {
+ pdf_fcn_io_t t_sample_0 = 1;
+ pdf_fcn_io_t t_sample_1 = 1;
+ for (; t_val < (d_min_sample+d_delta); t_val += d_sub_delta) {
+ t_sample_0 += ((*d_pdf_fcn_0_bit)(t_val));
+ t_sample_1 += ((*d_pdf_fcn_1_bit)(t_val));
+ }
+ d_pdf_fcn_0_samples[m] = t_sample_0;
+ d_pdf_fcn_0_samples[m] = t_sample_1;
+ t_sum_0 += t_sample_0;
+ t_sum_1 += t_sample_1;
+ if (m == 0) {
+ t_max_0 = t_min_0 = t_sample_0;
+ t_max_1 = t_min_1 = t_sample_1;
+ } else {
+ if (t_max_0 < t_sample_0)
+ t_max_0 = t_sample_0;
+ else if (t_min_0 > t_sample_0)
+ t_min_0 = t_sample_0;
+ if (t_max_1 < t_sample_1)
+ t_max_1 = t_sample_1;
+ else if (t_min_1 > t_sample_1)
+ t_min_1 = t_sample_1;
+ }
+ }
- pdf_fcn_io_t l_val = d_min_sample;
- for (size_t m = 0; m < d_n_samples; m++) {
- d_metric_table_0_bit[m] =
- (metric_t) roundf (((pdf_fcn_io_t) l_min_map) +
- (l_slope_0 * (logf ((*pdf_fcn_0_bit)(l_val)) -
- l_min_log_val_0)));
- d_metric_table_1_bit[m] =
- (metric_t) roundf (((pdf_fcn_io_t) l_min_map) +
- (l_slope_1 * (logf ((*pdf_fcn_1_bit)(l_val)) -
- l_min_log_val_1)));
- l_val += d_delta;
+ pdf_fcn_io_t t_sample_0 = 1;
+ pdf_fcn_io_t t_sample_1 = 1;
+ for (; t_val < d_sup_max_sample; t_val += d_sub_delta) {
+ t_sample_0 += ((*d_pdf_fcn_0_bit)(t_val));
+ t_sample_1 += ((*d_pdf_fcn_1_bit)(t_val));
}
-}
+ d_pdf_fcn_0_samples[m] = t_sample_0;
+ d_pdf_fcn_0_samples[m] = t_sample_1;
+ t_sum_0 += t_sample_0;
+ t_sum_1 += t_sample_1;
+ if (t_max_0 < t_sample_0)
+ t_max_0 = t_sample_0;
+ else if (t_min_0 > t_sample_0)
+ t_min_0 = t_sample_0;
+ if (t_max_1 < t_sample_1)
+ t_max_1 = t_sample_1;
+ else if (t_min_1 > t_sample_1)
+ t_min_1 = t_sample_1;
+
+ // normalize to the sum, so that these are "real" probabilities.
+
+ for (m = 0; m < d_n_samples; m++) {
+ d_pdf_fcn_0_samples[m] /= t_sum_0;
+ d_pdf_fcn_1_samples[m] /= t_sum_1;
+ }
+ t_max_0 /= t_sum_0;
+ t_min_0 /= t_sum_0;
+ t_max_1 /= t_sum_1;
+ t_min_1 /= t_sum_1;
-void code_metric_fl::lookup
-(pdf_fcn_io_t sym,
- void* bit_0,
- void* bit_1)
-{
- metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
- metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
+ // take the logf so that metrics can add
- if (sym <= d_min_sample) {
- *l_bit_0 = d_metric_table_0_bit[0];
- *l_bit_1 = d_metric_table_1_bit[0];
- return;
+ for (m = 0; m < d_n_samples; m++) {
+ d_pdf_fcn_0_samples[m] = logf (d_pdf_fcn_0_samples[m]);
+ d_pdf_fcn_1_samples[m] = logf (d_pdf_fcn_1_samples[m]);
}
- if (sym >= d_max_sample) {
- *l_bit_0 = d_metric_table_0_bit.back ();
- *l_bit_1 = d_metric_table_1_bit.back ();
- return;
+ t_max_0 = logf (t_max_0);
+ t_min_0 = logf (t_min_0);
+ t_max_1 = logf (t_max_1);
+ t_min_1 = logf (t_min_1);
+
+ // higher (less negative) log-probabilities mean more likely; lower
+ // (more negative) mean less likely. Want metrics which are 0 when
+ // most likely and more positive when less likely. So subtract the
+ // max, then negate and normalize to the min (new max) so that the
+ // max value is 1 and the min value is 0.
+
+ for (m = 0; m < d_n_samples; m++) {
+ d_pdf_fcn_0_samples[m] = ((d_pdf_fcn_0_samples[m] - t_max_0) /
+ (t_min_0 - t_max_0));
+ d_pdf_fcn_1_samples[m] = ((d_pdf_fcn_1_samples[m] - t_max_1) /
+ (t_min_1 - t_max_1));
}
- size_t l_ndx = (size_t) roundf ((sym - d_min_sample) / d_delta);
- *l_bit_0 = d_metric_table_0_bit[l_ndx];
- *l_bit_1 = d_metric_table_1_bit[l_ndx];
-}
+ // correct the delta to the lookup computations
-void code_metric_fl::convert
-(size_t n_syms,
- pdf_fcn_io_t* sym,
- void* bit_0,
- void* bit_1)
-{
- metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
- metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
-
- for (size_t m = n_syms; m > 0; m--)
- lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++);
+ d_delta = (max_sample - min_sample) / ((pdf_fcn_io_t)(n_samples-1));
}
-code_metric_fs::code_metric_fs
+template<typename pdf_fcn_io_t, typename metric_t>
+code_metrics_table_work<pdf_fcn_io_t,metric_t>::code_metrics_table_work
(pdf_fcn_t pdf_fcn_0_bit,
pdf_fcn_t pdf_fcn_1_bit,
size_t n_samples,
pdf_fcn_io_t min_sample,
pdf_fcn_io_t max_sample,
int sample_precision)
+ : code_metrics_table<pdf_fcn_io_t>
+ (pdf_fcn_0_bit,
+ pdf_fcn_1_bit,
+ n_samples,
+ min_sample,
+ max_sample)
{
- if (n_samples < 2) {
- fprintf (stderr, "code_metric_fs:: n_samples "
- "must be at least 2.\n");
- assert (0);
- }
- if (min_sample >= max_sample) {
- fprintf (stderr, "code_metric_fs:: min_sample must be "
- "less than max_sample.\n");
- assert (0);
- }
- if (! pdf_fcn_0_bit) {
- fprintf (stderr, "code_metric_fs:: pdf_fcn_0_bit must be "
- "a non-null pointer to function.\n");
- assert (0);
- }
- if (! pdf_fcn_1_bit) {
- fprintf (stderr, "code_metric_fs:: pdf_fcn_0_bit must be "
- "a non-null pointer to function.\n");
- assert (0);
- }
- if (sample_precision < 9 || sample_precision > 16) {
- fprintf (stderr, "code_metric_fs:: sample_precision must be "
- "between 9 and 16 for this class.\n");
- assert (0);
- }
+ code_metrics_table<pdf_fcn_io_t>::d_out_item_size_bytes = sizeof (metric_t);
+ code_metrics_table<pdf_fcn_io_t>::d_sample_precision = sample_precision;
+
+ // get the scale factor for converting from float to
+ // sample_precision maps: 0 -> 0, 1 -> (2^sample_precision)-1 for
+ // integers; there is no need for a mapping for float types, since
+ // those are already in [0,1].
+
+ pdf_fcn_io_t t_mult = ((sample_precision == 0) ? 1 :
+ ((pdf_fcn_io_t)((2^sample_precision)-1)));
+
+ // convert the 0 bit metrics from float to integer
- d_sample_precision = sample_precision;
- d_n_samples = n_samples;
- d_max_sample = max_sample;
- d_min_sample = min_sample;
- d_delta = (max_sample - min_sample) / (n_samples - 1);
- d_pdf_fcn_0_bit = pdf_fcn_0_bit;
- d_pdf_fcn_1_bit = pdf_fcn_1_bit;
d_metric_table_0_bit.assign (n_samples, 0);
- d_metric_table_1_bit.assign (n_samples, 0);
+ for (size_t m = 0; m < n_samples; m++) {
+ d_metric_table_0_bit[m] =
+ (metric_t)((code_metrics_table<pdf_fcn_io_t>::d_pdf_fcn_0_samples[m]) *
+ t_mult);
+ }
- // get the scale factor for converting from float to sample_precision
- // maps:
- // logf (pdf_fcn_0_bit->eval (d_min_sample)) -> l_min_map
- // logf (pdf_fcn_0_bit->eval (d_max_sample)) -> l_max_map
+ // clear the old float sample vectors to free memory
- metric_t l_min_map = - (1 << (sample_precision - 1));
+ code_metrics_table<pdf_fcn_io_t>::d_pdf_fcn_0_samples.resize (0);
- pdf_fcn_io_t l_min_log_val_0 = logf ((*pdf_fcn_0_bit)(d_min_sample));
- pdf_fcn_io_t l_max_log_val_0 = logf ((*pdf_fcn_0_bit)(d_max_sample));
- pdf_fcn_io_t l_slope_0 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) /
- (l_max_log_val_0 - l_min_log_val_0));
- pdf_fcn_io_t l_min_log_val_1 = logf ((*pdf_fcn_1_bit)(d_min_sample));
- pdf_fcn_io_t l_max_log_val_1 = logf ((*pdf_fcn_1_bit)(d_max_sample));
- pdf_fcn_io_t l_slope_1 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) /
- (l_max_log_val_1 - l_min_log_val_1));
+ // convert the 1 bit metrics from float to integer
- pdf_fcn_io_t l_val = d_min_sample;
- for (size_t m = 0; m < d_n_samples; m++) {
- d_metric_table_0_bit[m] =
- (metric_t) roundf (((pdf_fcn_io_t) l_min_map) +
- (l_slope_0 * (logf ((*pdf_fcn_0_bit)(l_val)) -
- l_min_log_val_0)));
+ d_metric_table_1_bit.assign (n_samples, 0);
+ for (size_t m = 0; m < n_samples; m++) {
d_metric_table_1_bit[m] =
- (metric_t) roundf (((pdf_fcn_io_t) l_min_map) +
- (l_slope_1 * (logf ((*pdf_fcn_1_bit)(l_val)) -
- l_min_log_val_1)));
- l_val += d_delta;
+ (metric_t)((code_metrics_table<pdf_fcn_io_t>::d_pdf_fcn_1_samples[m]) *
+ t_mult);
}
+
+ // clear the old float sample vectors to free memory
+
+ code_metrics_table<pdf_fcn_io_t>::d_pdf_fcn_1_samples.resize (0);
}
-void code_metric_fs::lookup
+template<typename pdf_fcn_io_t, typename metric_t>
+void
+code_metrics_table_work<pdf_fcn_io_t,metric_t>::lookup
(pdf_fcn_io_t sym,
void* bit_0,
void* bit_1)
@@ -304,23 +291,27 @@ void code_metric_fs::lookup
metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
- if (sym <= d_min_sample) {
+ if (sym <= code_metrics_table<pdf_fcn_io_t>::d_min_sample) {
*l_bit_0 = d_metric_table_0_bit[0];
*l_bit_1 = d_metric_table_1_bit[0];
return;
}
- if (sym >= d_max_sample) {
+ if (sym >= code_metrics_table<pdf_fcn_io_t>::d_max_sample) {
*l_bit_0 = d_metric_table_0_bit.back ();
*l_bit_1 = d_metric_table_1_bit.back ();
return;
}
- size_t l_ndx = (size_t) roundf ((sym - d_min_sample) / d_delta);
+ size_t l_ndx = (size_t) round
+ ((double)((sym - code_metrics_table<pdf_fcn_io_t>::d_min_sample) /
+ code_metrics_table<pdf_fcn_io_t>::d_delta));
*l_bit_0 = d_metric_table_0_bit[l_ndx];
*l_bit_1 = d_metric_table_1_bit[l_ndx];
}
-void code_metric_fs::convert
+template<typename pdf_fcn_io_t, typename metric_t>
+void
+code_metrics_table_work<pdf_fcn_io_t,metric_t>::convert
(size_t n_syms,
pdf_fcn_io_t* sym,
void* bit_0,
@@ -333,113 +324,88 @@ void code_metric_fs::convert
lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++);
}
-code_metric_fb::code_metric_fb
-(pdf_fcn_t pdf_fcn_0_bit,
- pdf_fcn_t pdf_fcn_1_bit,
- size_t n_samples,
- pdf_fcn_io_t min_sample,
- pdf_fcn_io_t max_sample,
- int sample_precision)
-{
- if (n_samples < 2) {
- fprintf (stderr, "code_metric_fb:: n_samples "
- "must be at least 2.\n");
- assert (0);
- }
- if (min_sample >= max_sample) {
- fprintf (stderr, "code_metric_fb:: min_sample must be "
- "less than max_sample.\n");
- assert (0);
- }
- if (! pdf_fcn_0_bit) {
- fprintf (stderr, "code_metric_fb:: pdf_fcn_0_bit must be "
- "a non-null pointer to function.\n");
- assert (0);
- }
- if (! pdf_fcn_1_bit) {
- fprintf (stderr, "code_metric_fb:: pdf_fcn_0_bit must be "
- "a non-null pointer to function.\n");
- assert (0);
- }
- if (sample_precision < 1 || sample_precision > 8) {
- fprintf (stderr, "code_metric_fb:: sample_precision must be "
- "between 1 and 8 for this class.\n");
- assert (0);
- }
+#if 0
+ // for compute_all_outputs
- d_sample_precision = sample_precision;
- d_n_samples = n_samples;
- d_max_sample = max_sample;
- d_min_sample = min_sample;
- d_delta = (max_sample - min_sample) / (n_samples - 1);
- d_pdf_fcn_0_bit = pdf_fcn_0_bit;
- d_pdf_fcn_1_bit = pdf_fcn_1_bit;
- d_metric_table_0_bit.assign (n_samples, 0);
- d_metric_table_1_bit.assign (n_samples, 0);
+ d_n_code_outputs = n_code_outputs;
- // get the scale factor for converting from float to sample_precision
- // maps:
- // logf (pdf_fcn_0_bit->eval (d_min_sample)) -> l_min_map
- // logf (pdf_fcn_0_bit->eval (d_max_sample)) -> l_max_map
+ in_l[0].resize (d_n_code_outputs);
+ in_l[1].resize (d_n_code_outputs);
+ in_f[0].resize (d_n_code_outputs);
+ in_f[1].resize (d_n_code_outputs);
- metric_t l_min_map = - (1 << (sample_precision - 1));
- pdf_fcn_io_t l_min_log_val_0 = logf ((*pdf_fcn_0_bit)(d_min_sample));
- pdf_fcn_io_t l_max_log_val_0 = logf ((*pdf_fcn_0_bit)(d_max_sample));
- pdf_fcn_io_t l_slope_0 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) /
- (l_max_log_val_0 - l_min_log_val_0));
- pdf_fcn_io_t l_min_log_val_1 = logf ((*pdf_fcn_1_bit)(d_min_sample));
- pdf_fcn_io_t l_max_log_val_1 = logf ((*pdf_fcn_1_bit)(d_max_sample));
- pdf_fcn_io_t l_slope_1 = (powf (2.0, (pdf_fcn_io_t)(d_sample_precision)) /
- (l_max_log_val_1 - l_min_log_val_1));
- pdf_fcn_io_t l_val = d_min_sample;
- for (size_t m = 0; m < d_n_samples; m++) {
- d_metric_table_0_bit[m] =
- (metric_t) roundf (((pdf_fcn_io_t) l_min_map) +
- (l_slope_0 * (logf ((*pdf_fcn_0_bit)(l_val)) -
- l_min_log_val_0)));
- d_metric_table_1_bit[m] =
- (metric_t) roundf (((pdf_fcn_io_t) l_min_map) +
- (l_slope_1 * (logf ((*pdf_fcn_1_bit)(l_val)) -
- l_min_log_val_1)));
- l_val += d_delta;
+ if (n_code_outputs == 0) {
+ std::cerr << "code_metrics::create: Error: # of code outputs "
+ "must be positive.\n";
+ assert (0);
}
-}
-void code_metric_fb::lookup
-(pdf_fcn_io_t sym,
- void* bit_0,
- void* bit_1)
-{
- metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
- metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
- if (sym <= d_min_sample) {
- *l_bit_0 = d_metric_table_0_bit[0];
- *l_bit_1 = d_metric_table_1_bit[0];
- return;
- }
- if (sym >= d_max_sample) {
- *l_bit_0 = d_metric_table_0_bit.back ();
- *l_bit_1 = d_metric_table_1_bit.back ();
- return;
+template<typename pdf_fcn_io_t>
+void
+code_metrics<pdf_fcn_io_t>::compute_all_outputs
+(pdf_fcn_io_t* syms,
+ std::vector<unsigned long>& out)
+{
+ // use the first 'n_code_output' symbols, convert them into metrics,
+ // then compute all possible (summation) combinations of them and
+ // return those in the provided vector.
+
+ convert (d_n_code_outputs, syms,
+ (void*)(&(in_l[0][0])), (void*)(&in_l[1][0]));
+
+ // assign the starting minimum metric to 0. This is safe because
+ // metrics are always non-negative.
+
+ unsigned long min_metric = 0;
+ for (size_t m = 0; m < (((size_t)2) << d_n_code_outputs); m++) {
+ size_t t_out_ndx = m;
+ unsigned long t_metric = 0;
+ for (size_t n = 0; n < d_n_code_outputs; n++, t_out_ndx >>= 1)
+ t_metric += in_l[t_out_ndx&1][n];
+ if (t_metric < min_metric)
+ min_metric = t_metric;
+ out[m] = t_metric;
}
- size_t l_ndx = (size_t) roundf ((sym - d_min_sample) / d_delta);
- *l_bit_0 = d_metric_table_0_bit[l_ndx];
- *l_bit_1 = d_metric_table_1_bit[l_ndx];
+ // normalize so that the minimum metric equals 0
+
+ for (size_t m = 0; m < d_n_code_outputs; m++)
+ out[m] -= min_metric;
}
-void code_metric_fb::convert
-(size_t n_syms,
- pdf_fcn_io_t* sym,
- void* bit_0,
- void* bit_1)
+template<typename pdf_fcn_io_t>
+void
+code_metrics<pdf_fcn_io_t>::compute_all_outputs
+(pdf_fcn_io_t* syms,
+ std::vector<float>& out)
{
- metric_ptr_t l_bit_0 = (metric_ptr_t) bit_0;
- metric_ptr_t l_bit_1 = (metric_ptr_t) bit_1;
+ // use the first 'n_code_output' symbols, convert them into metrics,
+ // then compute all possible (summation) combinations of them and
+ // return those in the provided vector.
+
+ convert (d_n_code_outputs, syms,
+ (void*)(&(in_f[0][0])), (void*)(&in_f[1][0]));
+
+ // assign the starting minimum metric to 0. This is safe because
+ // metrics are always non-negative.
+
+ float min_metric = 0;
+ for (size_t m = 0; m < (((size_t)2) << d_n_code_outputs); m++) {
+ size_t t_out_ndx = m;
+ float t_metric = 0;
+ for (size_t n = 0; n < d_n_code_outputs; n++, t_out_ndx >>= 1)
+ t_metric += in_f[t_out_ndx&1][n];
+ if (t_metric < min_metric)
+ min_metric = t_metric;
+ out[m] = t_metric;
+ }
- for (size_t m = n_syms; m > 0; m--)
- lookup (*sym++, (void*) l_bit_0++, (void*) l_bit_1++);
+ // normalize so that the minimum metric equals 0
+
+ for (size_t m = 0; m < d_n_code_outputs; m++)
+ out[m] -= min_metric;
}
+#endif
diff --git a/gr-error-correcting-codes/src/lib/libecc/code_metrics.h b/gr-error-correcting-codes/src/lib/libecc/code_metrics.h
index 9530dd640..050c08192 100644
--- a/gr-error-correcting-codes/src/lib/libecc/code_metrics.h
+++ b/gr-error-correcting-codes/src/lib/libecc/code_metrics.h
@@ -20,136 +20,153 @@
* Boston, MA 02111-1307, USA.
*/
-#ifndef INCLUDED_CODE_METRIC_H
-#define INCLUDED_CODE_METRIC_H
+#ifndef INCLUDED_CODE_METRICS_H
+#define INCLUDED_CODE_METRICS_H
-#include <sys/types.h>
+#include "code_types.h"
#include <vector>
-class code_metrics
+template<typename pdf_fcn_io_t>
+class code_metrics_table;
+
+template<typename pdf_fcn_io_t>
+code_metrics_table<pdf_fcn_io_t>*
+libecc_code_metrics_create_table
+(pdf_fcn_io_t (*pdf_fcn_0_bit) (pdf_fcn_io_t),
+ pdf_fcn_io_t (*pdf_fcn_1_bit) (pdf_fcn_io_t),
+ size_t n_samples,
+ pdf_fcn_io_t min_sample,
+ pdf_fcn_io_t max_sample,
+ int sample_precision = 0);
+
+#if 0
+template<typename pdf_fcn_io_t>
+class code_metrics_decoder;
+
+template<typename pdf_fcn_io_t>
+libecc_code_metrics_create_decoder
+(code_convolutional_trellis* trellis,
+ code_metrics_table<pdf_fcn_io_t>* table = 0,
+ int sample_precision = 0);
+#endif
+
+template<typename pdf_fcn_io_t>
+class code_metrics_table
{
+/*
+ * class code_metrics_table: metrics table for convolutional codes.
+ * Pre-compute a lookup table upon instantiation, which makes for
+ * quick conversion from soft-float symbol value ('sym') to metric
+ * value. The symbol value probability is defined by the arguments
+ * 'pdf_fcn_0_bit' and 'pdf_fcn_1_bit' for p(0|sym) and p(1|sym)
+ * respectively. Internally, the PDF's are sampled and normalized to
+ * always have a minimum value of 0. For float-precision, the maximum
+ * value is 1.0, while for integer M-bits the maximum value is
+ * (2^M)-1. Smaller metric values indicate that the received symbols
+ * are closer to the given output bits; larger values indicate greater
+ * differences. The only constraint on the PDF functions are that
+ * they are piecewise continuous; otherwise, they don't even have to
+ * be a true PDF in terms of the integral from -inf to +inf being
+ * equal to 1 due to the normalization.
+ *
+ * Storage type for the tables is determined by the "sample_precision"
+ * argument. When the precision equals 0, 32-bit float storage is
+ * used; otherwise, the next largest standard integer type is used
+ * unsigned (char for 1 to 8 bits, short for 9 to 16 bits, and long
+ * for 17 to 32 bits). For the purposes of coding gain, any
+ * sample_precision larger than about 9 will have minimal added
+ * benefit under most conditions where communications are possible.
+ * Trellis computations are performed in either 32-bit float (for
+ * float storage) or 32-bit unsigned long (for all integer storage).
+ *
+ * The number of samples to store is determined by the "n_samples"
+ * argument, which must be at least 2 but is otherwise not limited
+ * except by the memory of the host computer.
+ *
+ * Samples of the PDF functions are taken from "min_sample" to
+ * "max_sample", which represent the floor and ceiling on input symbol
+ * values below and above which symbol values are truncated.
+ * Internally, a sub-n_samples value is determined and used to "sum"
+ * the PDF functions to divide the probabilities into "bins".
+ */
+
public:
- typedef float pdf_fcn_io_t;
+ typedef pdf_fcn_io_t (*pdf_fcn_t) (pdf_fcn_io_t);
- code_metrics () {};
- virtual ~code_metrics () {};
+ virtual ~code_metrics_table () {};
-// lookup() returns either a float, or a sign-extended
-// 'sample_precision'-bit integer value.
+ // lookup() returns either a float, or a sign-extended
+ // 'sample_precision'-bit integer value.
virtual void lookup (pdf_fcn_io_t sym,
void* bit_0,
void* bit_1) = 0;
+ // convert does a lookup on 'n_syms' input symbols
+
virtual void convert (size_t n_syms,
pdf_fcn_io_t* syms,
void* bit_0,
void* bit_1) = 0;
-};
-class code_metric_ff : public code_metrics
-{
- typedef pdf_fcn_io_t (*pdf_fcn_t) (pdf_fcn_io_t);
- typedef float metric_t, *metric_ptr_t;
+ inline const unsigned char out_item_size_bytes ()
+ {return(d_out_item_size_bytes);};
-private:
+protected:
+ code_metrics_table (pdf_fcn_t pdf_fcn_0_bit,
+ pdf_fcn_t pdf_fcn_1_bit,
+ size_t n_samples,
+ pdf_fcn_io_t min_sample,
+ pdf_fcn_io_t max_sample);
+
+ unsigned char d_out_item_size_bytes, d_sample_precision;
size_t d_n_samples;
pdf_fcn_io_t d_max_sample, d_min_sample, d_delta;
pdf_fcn_t d_pdf_fcn_0_bit, d_pdf_fcn_1_bit;
- std::vector<metric_t> d_metric_table_0_bit;
- std::vector<metric_t> d_metric_table_1_bit;
-
-public:
- code_metric_ff (pdf_fcn_t pdf_fcn_0_bit,
- pdf_fcn_t pdf_fcn_1_bit,
- size_t n_samples,
- pdf_fcn_io_t min_sample,
- pdf_fcn_io_t max_sample);
- ~code_metric_ff () {};
-
- void lookup (pdf_fcn_io_t sym, void* bit_0, void* bit_1);
- void convert (size_t n_syms, pdf_fcn_io_t* sym, void* bit_0, void* bit_1);
+ std::vector<pdf_fcn_io_t> d_pdf_fcn_0_samples, d_pdf_fcn_1_samples;
};
-class code_metric_fl : public code_metrics
+template<typename pdf_fcn_io_t, typename metric_t>
+class code_metrics_table_work : public code_metrics_table<pdf_fcn_io_t>
{
- typedef float pdf_fcn_io_t;
- typedef pdf_fcn_io_t (*pdf_fcn_t) (pdf_fcn_io_t);
- typedef long metric_t, *metric_ptr_t;
-
-private:
- char d_sample_precision;
- size_t d_n_samples, d_sample_mask;
- pdf_fcn_io_t d_max_sample, d_min_sample, d_delta;
- pdf_fcn_t d_pdf_fcn_0_bit, d_pdf_fcn_1_bit;
- std::vector<metric_t> d_metric_table_0_bit;
- std::vector<metric_t> d_metric_table_1_bit;
-
public:
- code_metric_fl (pdf_fcn_t pdf_fcn_0_bit,
- pdf_fcn_t pdf_fcn_1_bit,
- size_t n_samples,
- pdf_fcn_io_t min_sample,
- pdf_fcn_io_t max_sample,
- int sample_precision = 32);
- ~code_metric_fl () {};
-
- void lookup (pdf_fcn_io_t sym, void* bit_0, void* bit_1);
- void convert (size_t n_syms, pdf_fcn_io_t* sym, void* bit_0, void* bit_1);
-};
-
-class code_metric_fs : public code_metrics
-{
- typedef float pdf_fcn_io_t;
+ typedef metric_t *metric_ptr_t;
typedef pdf_fcn_io_t (*pdf_fcn_t) (pdf_fcn_io_t);
- typedef short metric_t, *metric_ptr_t;
-private:
- char d_sample_precision;
- size_t d_n_samples, d_sample_mask;
- pdf_fcn_io_t d_max_sample, d_min_sample, d_delta;
- pdf_fcn_t d_pdf_fcn_0_bit, d_pdf_fcn_1_bit;
- std::vector<metric_t> d_metric_table_0_bit;
- std::vector<metric_t> d_metric_table_1_bit;
-
-public:
- code_metric_fs (pdf_fcn_t pdf_fcn_0_bit,
- pdf_fcn_t pdf_fcn_1_bit,
- size_t n_samples,
- pdf_fcn_io_t min_sample,
- pdf_fcn_io_t max_sample,
- int sample_precision = 16);
- ~code_metric_fs () {};
+ ~code_metrics_table_work () {};
void lookup (pdf_fcn_io_t sym, void* bit_0, void* bit_1);
void convert (size_t n_syms, pdf_fcn_io_t* sym, void* bit_0, void* bit_1);
-};
-class code_metric_fb : public code_metrics
-{
- typedef float pdf_fcn_io_t;
- typedef pdf_fcn_io_t (*pdf_fcn_t) (pdf_fcn_io_t);
- typedef char metric_t, *metric_ptr_t;
+protected:
+ code_metrics_table_work (pdf_fcn_t pdf_fcn_0_bit,
+ pdf_fcn_t pdf_fcn_1_bit,
+ size_t n_samples,
+ pdf_fcn_io_t min_sample,
+ pdf_fcn_io_t max_sample,
+ int sample_precision = 0);
+
+ friend code_metrics_table<pdf_fcn_io_t>*
+ libecc_code_metrics_create_table<pdf_fcn_io_t>
+ (pdf_fcn_io_t (*pdf_fcn_0_bit) (pdf_fcn_io_t),
+ pdf_fcn_io_t (*pdf_fcn_1_bit) (pdf_fcn_io_t),
+ size_t n_samples,
+ pdf_fcn_io_t min_sample,
+ pdf_fcn_io_t max_sample,
+ int sample_precision);
+
+ std::vector<metric_t> d_metric_table_0_bit, d_metric_table_1_bit;
+};
-private:
- char d_sample_precision;
- size_t d_n_samples, d_sample_mask;
- pdf_fcn_io_t d_max_sample, d_min_sample, d_delta;
- pdf_fcn_t d_pdf_fcn_0_bit, d_pdf_fcn_1_bit;
- std::vector<metric_t> d_metric_table_0_bit;
- std::vector<metric_t> d_metric_table_1_bit;
+#if 0
+ // compute all output-bit combinations of the incoming symbols' metrics
-public:
- code_metric_fb (pdf_fcn_t pdf_fcn_0_bit,
- pdf_fcn_t pdf_fcn_1_bit,
- size_t n_samples,
- pdf_fcn_io_t min_sample,
- pdf_fcn_io_t max_sample,
- int sample_precision = 8);
- ~code_metric_fb () {};
+ void compute_all_outputs (pdf_fcn_io_t* syms, std::vector<unsigned long>& out);
+ void compute_all_outputs (pdf_fcn_io_t* syms, std::vector<float>& out);
- void lookup (pdf_fcn_io_t sym, void* bit_0, void* bit_1);
- void convert (size_t n_syms, pdf_fcn_io_t* sym, void* bit_0, void* bit_1);
-};
+ size_t d_n_code_outputs;
+ std::vector<unsigned long> in_l[2];
+ std::vector<float> in_f[2];
+#endif
-#endif /* INCLUDED_CODE_METRIC_H */
+#endif /* INCLUDED_CODE_METRICS_H */
diff --git a/gr-error-correcting-codes/src/lib/libecc/decoder.cc b/gr-error-correcting-codes/src/lib/libecc/decoder.cc
index 0b77f779e..256880e13 100644
--- a/gr-error-correcting-codes/src/lib/libecc/decoder.cc
+++ b/gr-error-correcting-codes/src/lib/libecc/decoder.cc
@@ -25,93 +25,180 @@
#endif
#include <decoder.h>
-#include <assert.h>
#include <iostream>
-#define DO_PRINT_DEBUG 1
-
-#if DO_PRINT_DEBUG
-#include <mld/n2bs.h>
-#endif
+#define DO_PRINT_DEBUG 0
/*
* 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!
+ * number of input items and output bits; no error checking is done!
*
- * n_bits_to_output: the number of bits per output stream to output.
+ * n_bits_to_output: the number of bits per output stream to decode.
*
- * returns the actual number of metrics used per input stream.
+ * returns the actual number of items used per input stream.
*/
size_t
decoder::decode
-(const char** in_buf,
- char** out_buf,
+(const code_input_ptr in_buf,
+ code_output_ptr out_buf,
size_t n_bits_to_output)
{
+ if (in_buf == 0) {
+ std::cerr << "decoder::decode: Error: input buffer is NULL.\n";
+ assert (0);
+ }
+ if (out_buf == 0) {
+ std::cerr << "decoder::decode: Error: output buffer is NULL.\n";
+ assert (0);
+ }
+ if (n_bits_to_output == 0) {
+ std::cerr << "decoder::decode: Warning: no output bits requested.\n";
+ return (0);
+ }
+
// 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;
+ d_in_buf = in_buf;
+ d_out_buf = out_buf;
+
+ // check that there are enough output buffer items
+
+ if (d_out_buf->n_items_left() < n_bits_to_output) {
+ std::cerr << "encoder::encode: Warning: output buffer size (" <<
+ d_out_buf->n_items_left() << "is less than the desired number "
+ "of output items (" << n_bits_to_output <<
+ ") ... using lower number.\n";
+ n_bits_to_output = d_out_buf->n_items_left();
+ }
+
+ // check that there are enough input buffer items
+
+ size_t n_items_to_input = compute_n_input_items (n_bits_to_output);
+
+ if (d_in_buf->n_items_left() < n_items_to_input) {
+ std::cerr << "encoder::encode: Warning: input buffer size (" <<
+ d_in_buf->n_items_left() << "is less than the computed number "
+ "of required input items (" << n_items_to_input <<
+ ") ... using lower number.\n";
+ n_items_to_input = d_in_buf->n_items_left();
+ n_bits_to_output = compute_n_output_bits (n_items_to_input);
+ }
+
+ if (DO_PRINT_DEBUG) {
+ std::cout <<
+ "# output bits = " << n_bits_to_output << "\n"
+ "# input items = " << n_items_to_input << "\n";
+ }
// call the private decode function
- decode_private (in_buf, out_buf);
+ decode_private ();
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';
+ std::cout <<
+ "# input items used = " << d_in_buf->n_items_used() << "\n"
+ "# output bits used = " << d_out_buf->n_items_used() << "\n";
}
- // return the actual number of input metrics used
+ size_t n_items_used = d_in_buf->n_items_used ();
+
+ // clear these buffers, just in case
+
+ d_in_buf = 0;
+ d_out_buf = 0;
- return (saved_n_input_metrics - d_n_input_metrics_left);
+ // return the actual number of input bits used
+
+ return (n_items_used);
}
/*
* decode a certain number of input metrics
*
* 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!
+ * number of input items and output bits; no error checking is done!
*
- * n_metrics_to_input: the number of metrics per input stream to decode
+ * n_items_to_input: the number of items per input stream to decode
*
* returns the actual number of bits written per output stream
*/
size_t
decoder::decode
-(const char** in_buf,
- size_t n_metrics_to_input,
- char** out_buf)
+(const code_input_ptr in_buf,
+ size_t n_items_to_input,
+ code_output_ptr out_buf)
{
+ if (in_buf == 0) {
+ std::cerr << "encoder::encode: Error: input buffer is NULL.\n";
+ assert (0);
+ }
+ if (out_buf == 0) {
+ std::cerr << "encoder::encode: Error: output buffer is NULL.\n";
+ assert (0);
+ }
+ if (n_items_to_input == 0) {
+ std::cerr << "encoder::encode: Warning: no input items requested.\n";
+ return (0);
+ }
+
// 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_metrics_to_input);
- d_n_input_metrics_left = n_metrics_to_input;
+ d_in_buf = in_buf;
+ d_out_buf = out_buf;
+
+ // check that there are enough input buffer items
+
+ if (d_in_buf->n_items_left() < n_items_to_input) {
+ std::cerr << "encoder::encode: Warning: input buffer size (" <<
+ d_in_buf->n_items_left() << "is less than the desired number "
+ "of input items (" << n_items_to_input <<
+ ") ... using lower number.\n";
+ n_items_to_input = d_in_buf->n_items_left();
+ }
+
+ // check that there are enough output buffer items
+
+ size_t n_bits_to_output = compute_n_output_bits (n_items_to_input);
+
+ if (d_out_buf->n_items_left() < n_bits_to_output) {
+ std::cerr << "encoder::encode: Warning: output buffer size (" <<
+ d_out_buf->n_items_left() << "is less than the computed number "
+ "of required output items (" << n_bits_to_output <<
+ ") ... using lower number.\n";
+ n_bits_to_output = d_out_buf->n_items_left();
+ n_items_to_input = compute_n_input_items (n_bits_to_output);
+ }
+
+ if (DO_PRINT_DEBUG) {
+ std::cout <<
+ "# output bits = " << n_bits_to_output << "\n"
+ "# input items = " << n_items_to_input << "\n";
+ }
// call the private decode function
- decode_private (in_buf, out_buf);
+ decode_private ();
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';
+ std::cout <<
+ "# input items used = " << d_in_buf->n_items_used() << "\n"
+ "# output bits used = " << d_out_buf->n_items_used() << "\n";
}
+ size_t n_items_used = d_out_buf->n_items_used();
+
+ // clear these buffers, just in case
+
+ d_in_buf = 0;
+ d_out_buf = 0;
+
// return the actual number of output bits written
- return (saved_n_output_bits - d_n_output_bits_left);
+ return (n_items_used);
}
diff --git a/gr-error-correcting-codes/src/lib/libecc/decoder.h b/gr-error-correcting-codes/src/lib/libecc/decoder.h
index 76a24b20a..860800110 100644
--- a/gr-error-correcting-codes/src/lib/libecc/decoder.h
+++ b/gr-error-correcting-codes/src/lib/libecc/decoder.h
@@ -23,37 +23,69 @@
#ifndef INCLUDED_DECODER_H
#define INCLUDED_DECODER_H
-#include "code_types.h"
-
-// the 'decoder' class is a virtual class upon which all decoder types
-// can be built.
+#include "code_io.h"
class decoder
{
+ /*
+ * class decoder
+ * A virtual class upon which all decoder types can be built.
+ * This class provides the basic methods and variables
+ * generic for all decoders.
+ */
public:
decoder () {};
virtual ~decoder () {};
- 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,
+ /*
+ * compute_n_...: to be defined by inheriting classes, in order to
+ * allow for user-functions to figure out how many inputs are
+ * required to generate a given number of outputs, and vice versa.
+ * Can't define them without knowing the decoder type.
+ *
+ * Compute the number of input items (metrics, floats, whatevers)
+ * needed to produce 'n_output' bits, and the number of output bits
+ * which will be produced by 'n_input' items ... for a single stream
+ * only.
+ */
+
+ virtual size_t compute_n_input_items (size_t n_output_bits) = 0;
+ virtual size_t compute_n_output_bits (size_t n_input_items) = 0;
+
+ /*
+ * decode: given the input and output buffers, either decode up to
+ * the number of output bits or decode the number of input items
+ * ... if the buffers support either decoding amounts.
+ */
+
+ virtual size_t decode (const code_input_ptr in_buf,
+ code_output_ptr out_buf,
size_t n_bits_to_output);
- virtual size_t decode (const char** in_buf,
- size_t n_metrics_to_input,
- char** out_buf);
+ virtual size_t decode (const code_input_ptr in_buf,
+ size_t n_items_to_input,
+ code_output_ptr out_buf);
+
+/* for remote access to internal info */
+
+ inline const size_t block_size_bits () {return (d_block_size_bits);};
+ inline const size_t n_code_inputs () {return (d_n_code_inputs);};
+ inline const size_t n_code_outputs () {return (d_n_code_outputs);};
+ inline const size_t total_n_dec_bits () {return (d_total_n_dec_bits);};
protected:
- virtual void decode_private (const char** in_buf, char** out_buf) = 0;
- virtual char get_next_input (const char** in_buf, size_t code_input_n) = 0;
- virtual void output_bit (char t_out_bit, char** out_buf,
- size_t t_output_stream) = 0;
+ /*
+ * decode_private: decode 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 decode_private () = 0;
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;
+ size_t d_total_n_dec_bits;
+ code_input_ptr d_in_buf;
+ code_output_ptr d_out_buf;
};
#endif /* INCLUDED_DECODER_H */
diff --git a/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.cc b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.cc
index bce2cacb2..7e50d8936 100644
--- a/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.cc
+++ b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.cc
@@ -52,55 +52,45 @@ const int g_num_bits_per_byte = 8;
#define DO_PRINT_DEBUG_EXIT 0
#define DO_PRINT_DEBUG 0
-#if DO_TIME_THOUGHPUT
#include <mld/mld_timer.h>
-#endif
-#if DO_PRINT_DEBUG
#include <mld/n2bs.h>
-#endif
decoder_viterbi::decoder_viterbi
(int sample_precision,
- encoder_convolutional* l_encoder)
+ const encoder_convolutional* l_encoder)
{
- // make sure the sample precitions makes sense
+ // make sure that the encoder is "valid"
- if ((sample_precision < 0) | (sample_precision > 32)) {
- std::cerr << "decoder_viterbi: "
- "Requested sample_precision (" << sample_precision <<
- "must be between 0 and 32.\n";
+ if (! l_encoder) {
+ std::cerr << "decoder_viterbi: Error: Encoder is NULL.\n";
assert (0);
}
- // make sure that the encoder is "valid"
+ // make the metrics converter
- if (! l_encoder) {
- std::cerr << "decoder_viterbi: Error: Encoder is a NULL pointer.\n";
+ // d_code_metrics = new code_metrics (
+
+ if ((sample_precision < 0) | (sample_precision > 32)) {
+ std::cerr << "decoder_viterbi: "
+ "Requested sample_precision (" << sample_precision <<
+ ") must be between 0 and 32.\n";
assert (0);
}
- // keep around a pointer to the encoder
+ // get the trellis
- d_encoder = l_encoder;
+ d_encoder = (encoder_convolutional*) l_encoder;
+ d_trellis = (code_convolutional_trellis*) d_encoder->trellis ();
// fill the class variables
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
-
- // 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
-
- d_n_states = 1 << d_total_memory;
- d_n_input_combinations = 1 << d_n_code_inputs;
+ d_total_n_delays = d_encoder->total_n_delays ();
+ d_n_states = d_trellis->n_states ();
+ d_n_input_combinations = d_trellis->n_input_combinations ();
// really nothing else to do here, since this class doesn't "know"
// how to process streaming versus block decoding, or partial
@@ -112,11 +102,9 @@ decoder_viterbi::decoder_viterbi
"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_total_memory = " << d_total_memory << "\n" <<
+ "d_total_n_delays = " << d_total_n_delays << "\n" <<
"d_n_states = " << d_n_states << "\n" <<
"d_n_input_combinations = " << d_n_input_combinations << "\n";
}
@@ -134,17 +122,14 @@ decoder_viterbi::decoder_viterbi
d_n_total_inputs_per_stream = d_block_size_bits;
if (d_do_termination == true)
- d_n_total_inputs_per_stream += d_max_memory;
-
-
-
+ d_n_total_inputs_per_stream += d_total_n_delays;
}
decoder_viterbi::~decoder_viterbi
()
{
// reverse over from allocation
-
+#if 0
delete [] d_up_term_states_ndx[0];
delete [] d_up_term_states_ndx[1];
@@ -177,6 +162,7 @@ decoder_viterbi::~decoder_viterbi
delete [] (*t_save_buffer++);
}
delete [] d_save_buffer;
+#endif
}
void
@@ -209,20 +195,9 @@ decoder_viterbi::zero_metrics
}
}
-//FIXME
-
-char
-decoder_viterbi::get_next_input
-(const char** in_buf,
-size_t code_input_n)
-{
- return (0);
-}
-
void
decoder_viterbi::decode_private
-(const char** in_buf,
- char** out_buf)
+()
{
#if 0
@@ -231,8 +206,8 @@ decoder_viterbi::decode_private
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;
+ size_t t_state_print_bits = d_total_n_delays;
+ size_t t_mem_print_bits = d_total_n_delays;
#endif
// setup variables for quicker access
const char **in_buf = (const char **) &input_items[0];
@@ -319,148 +294,8 @@ decoder_viterbi::decode_private
// jump to the correct state in the fsm
switch (d_fsm_state) {
case fsm_dec_viterbi_doing_up:
-#if DO_PRINT_DEBUG_FSM
- 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 *
- 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_viterbi_doing_middle\n";
-#endif
- d_fsm_state = fsm_dec_viterbi_doing_middle;
- }
-#if DO_PRINT_DEBUG_FSM
- std::cout << "Exited fsm_dec_viterbi_doing_up\n";
+ encode_loop_up ();
#endif
break;
case (fsm_dec_viterbi_doing_middle):
@@ -486,7 +321,7 @@ decoder_viterbi::decode_private
#if DO_PRINT_DEBUG_MIDDLE
std::cout << "Time Count " << (d_time_count+1) << " of " <<
d_block_size_bits << "\n" <<
- "d_states_ndx = " << d_states_ndx << "\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++) {
@@ -621,15 +456,15 @@ decoder_viterbi::decode_private
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_block_size_bits);
+ size_t t_time_count = d_total_n_delays - (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
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 <<
+ std::cout << "Doing time " << (d_total_n_delays - t_time_count + 1) <<
+ " of " << d_total_n_delays << "; starting buf[" << t_in_buf_ndx <<
"] of [" << t_ninput_items << "]\n";
#endif
// use the "to" states,
@@ -800,15 +635,15 @@ decoder_viterbi::decode_private
// 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";
+ d_total_n_delays << " bit" <<
+ ((d_total_n_delays != 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--) {
+ for (size_t n = d_total_n_delays; 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";
@@ -1058,3 +893,157 @@ decoder_viterbi::decode_private
" b/s\n";
#endif
}
+
+#if 0
+
+void
+decoder_viterbi::encode_loop_up ()
+{
+#if DO_PRINT_DEBUG_FSM
+ 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 *
+ 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_total_n_delays) &
+ (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_total_n_delays = " << d_total_n_delays << "\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_total_n_delays) {
+#if DO_PRINT_DEBUG_FSM
+ std::cout << "Setting FSM to fsm_dec_viterbi_doing_middle\n";
+#endif
+ d_fsm_state = fsm_dec_viterbi_doing_middle;
+ }
+#if DO_PRINT_DEBUG_FSM
+ std::cout << "Exited fsm_dec_viterbi_doing_up\n";
+#endif
+}
+#endif
diff --git a/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.h b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.h
index 66a6ba405..e97f5cd10 100644
--- a/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.h
+++ b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.h
@@ -48,31 +48,11 @@ public:
*/
decoder_viterbi (int sample_precision,
- encoder_convolutional* l_encoder);
+ const encoder_convolutional* l_encoder);
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
*
@@ -94,7 +74,7 @@ protected:
*/
typedef struct state_t {
- connection_t_ptr d_connections;
+ struct state_t* d_connections;
float d_max_metric;
int d_max_state_ndx;
int d_max_input;
@@ -149,20 +129,21 @@ protected:
fsm_dec_viterbi_doing_middle, fsm_dec_viterbi_doing_term
};
- 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);
+ virtual void decode_private ();
#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__up (const char** in_buf,
- size_t code_input_n) = 0;
- virtual char get_next_input__middle (const char** in_buf,
- size_t code_input_n) = 0;
- virtual char get_next_input__term (size_t code_input_n) = 0;
+ virtual void decode_loop (size_t* which_counter, size_t how_many);
#endif
- virtual void increment_input_indices (bool while_decoding) = 0;
- virtual void increment_output_indices (bool while_decoding) = 0;
+ virtual void get_next_inputs () {
+ d_in_buf->read_items ((void*)(&(d_current_inputs[0])));
+ d_in_buf->increment_indices ();
+ };
+ virtual void write_output_bits () {
+ d_out_buf->write_items ((void*)(&(d_current_outputs[0])));
+ d_out_buf->increment_indices ();
+ };
+
+ void encode_loop_up ();
+
virtual void update_traceback__up (size_t from_state_ndx,
size_t to_state_ndx,
size_t l_input) = 0;
@@ -173,17 +154,32 @@ protected:
void zero_metrics (u_char which);
encoder_convolutional* d_encoder;
+ code_convolutional_trellis* d_trellis;
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_n_states, d_n_input_combinations, d_total_n_delays;
size_t d_states_ndx, d_up_term_ndx;
- bool d_do_streaming, d_do_termination;
- std::vector<memory_t> d_init_states, d_term_states;
- char **d_save_buffer;
+ bool d_do_termination;
+#if 1
state_t_ptr d_states[2];
size_t* d_up_term_states_ndx[2];
+ char **d_save_buffer;
+#else
+ std::vector<state_t> d_states[2];
+ std::vector<size_t> d_up_term_states_ndx[2];
+ std::vector<char **> d_save_buffer; ???
+#endif
+
+ // "inputs" are the current input symbols as soft-floats, to be
+ // converted to metrics internally
+
+ std::vector<float> d_current_inputs;
+
+ // "outputs" are the current output bits, in the LSB (&1) of each "char"
+
+ std::vector<char> d_current_outputs;
};
#endif /* INCLUDED_DECODER_VITERBI_H */
diff --git a/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.cc b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.cc
index 308d2775b..e604e4477 100644
--- a/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.cc
+++ b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.cc
@@ -127,6 +127,20 @@ decoder_viterbi_full_block::~decoder_viterbi_full_block
delete [] d_out_buf;
}
+size_t
+decoder_viterbi_full_block::compute_n_input_items
+(size_t n_output_bits)
+{
+ return (0);
+}
+
+size_t
+decoder_viterbi_full_block::compute_n_output_bits
+(size_t n_input_items)
+{
+ return (0);
+}
+
void
decoder_viterbi_full_block::update_traceback__up
(size_t from_state_ndx,
@@ -272,8 +286,7 @@ decoder_viterbi_full_block::update_traceback__term
void
decoder_viterbi_full_block::decode_private
-(const char** in_buf,
- char** out_buf)
+()
{
#if 0
diff --git a/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.h b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.h
index 531b7a6c6..832b656cc 100644
--- a/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.h
+++ b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.h
@@ -29,8 +29,8 @@ 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
+ * doing full trellis block decoding before putting out any
+ * decoded bits.
*
* input: streams of metrics, two per code output: one for the 0-bit
* metrics and the other for the 1-bit metric.
@@ -44,8 +44,11 @@ public:
virtual ~decoder_viterbi_full_block ();
+ virtual size_t compute_n_input_items (size_t n_output_bits);
+ virtual size_t compute_n_output_bits (size_t n_input_items);
+
protected:
- virtual void decode_private (const char** in_buf, char** out_buf);
+ virtual void decode_private ();
virtual void update_traceback__up (size_t from_state_ndx,
size_t to_state_ndx,
size_t l_input);
diff --git a/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block_i1_ic1.cc b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block_i1_ic1.cc
deleted file mode 100644
index b0fc4f364..000000000
--- a/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block_i1_ic1.cc
+++ /dev/null
@@ -1,162 +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 "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!";
-}
diff --git a/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block_i1_ic1.h b/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block_i1_ic1.h
deleted file mode 100644
index a7afeb396..000000000
--- a/gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block_i1_ic1.h
+++ /dev/null
@@ -1,66 +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_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 */
diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder.cc b/gr-error-correcting-codes/src/lib/libecc/encoder.cc
index 5bc97e7fc..967000fd0 100644
--- a/gr-error-correcting-codes/src/lib/libecc/encoder.cc
+++ b/gr-error-correcting-codes/src/lib/libecc/encoder.cc
@@ -42,43 +42,78 @@
size_t
encoder::encode
-(const char** in_buf,
- char** out_buf,
+(const code_input_ptr in_buf,
+ code_output_ptr out_buf,
size_t n_bits_to_output)
{
- if (DO_PRINT_DEBUG) {
- std::cout << "encode{out}(): Starting:";
+ if (in_buf == 0) {
+ std::cerr << "encoder::encode: Error: input buffer is NULL.\n";
+ assert (0);
+ }
+ if (out_buf == 0) {
+ std::cerr << "encoder::encode: Error: output buffer is NULL.\n";
+ assert (0);
+ }
+ if (n_bits_to_output == 0) {
+ std::cerr << "encoder::encode: Warning: no output bits requested.\n";
+ return (0);
}
// 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;
+ d_in_buf = in_buf;
+ d_out_buf = out_buf;
+
+ // check that there are enough output buffer items
+
+ if (d_out_buf->n_items_left() < n_bits_to_output) {
+ std::cerr << "encoder::encode: Warning: output buffer size (" <<
+ d_out_buf->n_items_left() << "is less than the desired number "
+ "of output items (" << n_bits_to_output <<
+ ") ... using lower number.\n";
+ n_bits_to_output = d_out_buf->n_items_left();
+ }
+
+ // check that there are enough input buffer items
+
+ size_t n_bits_to_input = compute_n_input_bits (n_bits_to_output);
+
+ if (d_in_buf->n_items_left() < n_bits_to_input) {
+ std::cerr << "encoder::encode: Warning: input buffer size (" <<
+ d_in_buf->n_items_left() << "is less than the computed number "
+ "of required input items (" << n_bits_to_input <<
+ ") ... using lower number.\n";
+ n_bits_to_input = d_in_buf->n_items_left();
+ n_bits_to_output = compute_n_output_bits (n_bits_to_input);
+ }
if (DO_PRINT_DEBUG) {
std::cout <<
- "# output bits provided = " << d_n_output_bits_left << "\n"
- "# input bits computed = " << d_n_input_bits_left << "\n";
+ "# output bits = " << n_bits_to_output << "\n"
+ "# input bits = " << n_bits_to_input << "\n";
}
// call the private encode function
- encode_private (in_buf, out_buf);
+ encode_private ();
if (DO_PRINT_DEBUG) {
std::cout <<
- "n_input_bits_used = " <<
- (saved_n_input_bits - d_n_input_bits_left) << "\n"
- "n_output_bits_used = " <<
- (n_bits_to_output - d_n_output_bits_left) << '\n';
+ "# input bits used = " << d_in_buf->n_items_used() << "\n"
+ "# output bits used = " << d_out_buf->n_items_used() << "\n";
}
+ size_t n_items_used = d_in_buf->n_items_used ();
+
+ // clear these buffers, just in case
+
+ d_in_buf = 0;
+ d_out_buf = 0;
+
// return the actual number of input bits used
- return (saved_n_input_bits - d_n_input_bits_left);
+ return (n_items_used);
}
/*
@@ -94,30 +129,76 @@ encoder::encode
size_t
encoder::encode
-(const char** in_buf,
+(const code_input_ptr in_buf,
size_t n_bits_to_input,
- char** out_buf)
+ code_output_ptr out_buf)
{
+ if (in_buf == 0) {
+ std::cerr << "encoder::encode: Error: input buffer is NULL.\n";
+ assert (0);
+ }
+ if (out_buf == 0) {
+ std::cerr << "encoder::encode: Error: output buffer is NULL.\n";
+ assert (0);
+ }
+ if (n_bits_to_input == 0) {
+ std::cerr << "encoder::encode: Warning: no input bits requested.\n";
+ return (0);
+ }
+
// 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;
+ d_in_buf = in_buf;
+ d_out_buf = out_buf;
+
+ // check that there are enough input buffer items
+
+ if (d_in_buf->n_items_left() < n_bits_to_input) {
+ std::cerr << "encoder::encode: Warning: input buffer size (" <<
+ d_in_buf->n_items_left() << "is less than the desired number "
+ "of input items (" << n_bits_to_input <<
+ ") ... using lower number.\n";
+ n_bits_to_input = d_in_buf->n_items_left();
+ }
+
+ // check that there are enough output buffer items
+
+ size_t n_bits_to_output = compute_n_output_bits (n_bits_to_input);
+
+ if (d_out_buf->n_items_left() < n_bits_to_output) {
+ std::cerr << "encoder::encode: Warning: output buffer size (" <<
+ d_out_buf->n_items_left() << "is less than the computed number "
+ "of required output items (" << n_bits_to_output <<
+ ") ... using lower number.\n";
+ n_bits_to_output = d_out_buf->n_items_left();
+ n_bits_to_input = compute_n_input_bits (n_bits_to_output);
+ }
+
+ if (DO_PRINT_DEBUG) {
+ std::cout <<
+ "# output bits = " << n_bits_to_output << "\n"
+ "# input bits = " << n_bits_to_input << "\n";
+ }
// call the private encode function
- encode_private (in_buf, out_buf);
+ encode_private ();
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';
+ std::cout <<
+ "# input bits used = " << d_in_buf->n_items_used() << "\n"
+ "# output bits used = " << d_out_buf->n_items_used() << "\n";
}
+ size_t n_items_used = d_out_buf->n_items_used();
+
+ // clear these buffers, just in case
+
+ d_in_buf = 0;
+ d_out_buf = 0;
+
// return the actual number of output bits written
- return (saved_n_output_bits - d_n_output_bits_left);
+ return (n_items_used);
}
diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder.h b/gr-error-correcting-codes/src/lib/libecc/encoder.h
index 2c3dde13a..96ff9f411 100644
--- a/gr-error-correcting-codes/src/lib/libecc/encoder.h
+++ b/gr-error-correcting-codes/src/lib/libecc/encoder.h
@@ -23,50 +23,68 @@
#ifndef INCLUDED_ENCODER_H
#define INCLUDED_ENCODER_H
-#include "code_types.h"
-
-// the 'encoder' class is a virtual class upon which all encoder types
-// can be built.
+#include "code_io.h"
class encoder
{
+ /*
+ * class encoder
+ * A virtual class upon which all encoder types can be built.
+ * This class provides the basic methods and variables
+ * generic for all encoders.
+ */
public:
encoder () {};
virtual ~encoder () {};
+ /*
+ * compute_n_...: to be defined by inheriting classes, in order to
+ * allow for user-functions to figure out how many inputs are
+ * required to generate a given number of outputs, and vice versa.
+ * Can't define them without knowing the encoder type.
+ *
+ * Compute the number of input bits needed to produce 'n_output' bits,
+ * and the number of output bits which will be produced by 'n_input'
+ * bits ... for a single stream only.
+ */
+
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 encode (const char** in_buf,
- char** out_buf,
+
+ /*
+ * encode: given the input and output buffers, either encode up to
+ * the number of output bits or encode the number of input bits
+ * ... if the buffers support either encoding amounts.
+ */
+
+ virtual size_t encode (const code_input_ptr in_buf,
+ code_output_ptr out_buf,
size_t n_bits_to_output);
- virtual size_t encode (const char** in_buf,
+ virtual size_t encode (const code_input_ptr in_buf,
size_t n_bits_to_input,
- char** out_buf);
+ code_output_ptr out_buf);
/* 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);};
+ inline const size_t block_size_bits () {return (d_block_size_bits);};
+ inline const size_t n_code_inputs () {return (d_n_code_inputs);};
+ inline const size_t n_code_outputs () {return (d_n_code_outputs);};
+ inline const size_t total_n_enc_bits () {return (d_total_n_enc_bits);};
protected:
- /* encode_private: encode the given in_buf and write the output bits
+ /*
+ * 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;
-
- /* inheriting methods need to figure out what makes the most sense
- * for them in terms of getting new inputs and writing outputs.
- */
+ virtual void encode_private () = 0;
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;
+ size_t d_total_n_enc_bits;
+ code_input_ptr d_in_buf;
+ code_output_ptr d_out_buf;
};
#endif /* INCLUDED_ENCODER_H */
diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.cc b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.cc
index b7bd87de0..a4634503b 100644
--- a/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.cc
+++ b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.cc
@@ -29,16 +29,12 @@
#include <iostream>
#define DO_TIME_THOUGHPUT 0
-#define DO_PRINT_DEBUG 1
#include <mld/mld_timer.h>
-#include <mld/n2bs.h>
+//#include <mld/n2bs.h>
-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
+void
+encoder_convolutional::encoder_convolutional_init
(int block_size_bits,
int n_code_inputs,
int n_code_outputs,
@@ -97,14 +93,16 @@ void encoder_convolutional::encoder_convolutional_init
d_init_state = start_memory_state;
+ // reset the inputs and outputs, both to get the correct size() and
+ // for the sake of zeroing them out.
+
d_current_inputs.assign (d_n_code_inputs, 0);
d_current_outputs.assign (d_n_code_outputs, 0);
}
void
encoder_convolutional::encode_private
-(const char** in_buf,
- char** out_buf)
+()
{
struct timeval t_tp;
if (DO_TIME_THOUGHPUT) {
@@ -113,18 +111,12 @@ encoder_convolutional::encode_private
// reset buffer indices
- d_total_n_enc_bits = d_in_buf_ndx = d_out_buf_ndx =
- d_in_bit_shift = d_out_bit_shift = 0;
-
- if (DO_PRINT_DEBUG) {
- std::cout << "Beginning this encode() call; starting parameters.\n";
- std::cout << "d_n_input_bits_left = " << d_n_input_bits_left << '\n';
- std::cout << "d_n_output_bits_left = " << d_n_output_bits_left << '\n';
- }
+ d_total_n_enc_bits = 0;
// while there are inputs and outputs left to process ...
- while ((d_n_input_bits_left != 0) & (d_n_output_bits_left != 0)) {
+ while ((d_in_buf->n_items_left() != 0) &
+ (d_out_buf->n_items_left() != 0)) {
// jump to the correct state in the fsm
@@ -158,7 +150,7 @@ encoder_convolutional::encode_private
// termination bits, if any), counting down the number of
// available input bits.
- encode_loop (in_buf, out_buf, &d_n_input_bits_left, d_block_size_bits);
+ encode_loop (d_in_buf->n_items_left(), d_block_size_bits);
// finished this loop; check for jumping to the next state
@@ -183,7 +175,12 @@ encoder_convolutional::encode_private
// number of output bits left
if (d_do_termination == true) {
- encode_loop (in_buf, out_buf, &d_n_output_bits_left, d_total_n_delays);
+ if (d_n_enc_bits == 0) {
+ // first time through this; save the starting termination state
+ d_term_state = d_memory;
+ }
+
+ encode_loop (d_out_buf->n_items_left(), d_total_n_delays);
// finished this loop; check for jumping to the next state
@@ -207,17 +204,6 @@ encoder_convolutional::encode_private
// done (while) there are inputs and outputs
}
- if (DO_PRINT_DEBUG) {
- std::cout << "Done with this encode() call; ending parameters.\n"
- "d_in_bit_shift = " << d_in_bit_shift << "\n"
- "d_out_bit_shift = " << d_out_bit_shift << "\n"
- "d_in_buf_ndx = " << d_in_buf_ndx << "\n"
- "d_out_buf_ndx = " << d_out_buf_ndx << "\n"
- "d_n_input_bits_left = " << d_n_input_bits_left << "\n"
- "d_n_output_bits_left = " << d_n_output_bits_left << "\n"
- "d_total_n_enc_bits = " << d_total_n_enc_bits << "\n";
- }
-
if (DO_TIME_THOUGHPUT) {
// compute the throughput for this particular function call
u_long d_t = end_timer (&t_tp);
@@ -230,28 +216,17 @@ encoder_convolutional::encode_private
void
encoder_convolutional::encode_loop
-(const char** in_buf,
- char** out_buf,
- size_t* which_counter,
+(const size_t& which_counter,
size_t how_many)
{
// generic encode_loop
- if (DO_PRINT_DEBUG) {
- std::cout << "Starting encode_loop.\n";
- }
-
- while (((*which_counter) > 0) & (d_n_enc_bits < how_many)) {
- if (DO_PRINT_DEBUG) {
- std::cout << "*w_c = " << (*which_counter) << ", "
- "# enc_bits = " << d_n_enc_bits << " of " << how_many << ".\n"
- "Getting new inputs.\n";
- }
+ while ((which_counter > 0) & (d_n_enc_bits < how_many)) {
// get the next set of input bits from all streams;
// written into d_current_inputs
- get_next_inputs (in_buf);
+ get_next_inputs ();
// use the trellis to do the encoding;
// updates the input memory to the new memory state for the given input
@@ -261,7 +236,7 @@ encoder_convolutional::encode_loop
// write the bits in d_current_outputs into the output buffer
- write_output_bits (out_buf);
+ write_output_bits ();
// increment the number of encoded bits for the current block, and
// the total number of bits for this running of "encode()"
@@ -269,22 +244,88 @@ encoder_convolutional::encode_loop
d_n_enc_bits++;
d_total_n_enc_bits++;
}
+}
+
+size_t
+encoder_convolutional::compute_n_output_bits
+(size_t n_input_bits)
+{
+ size_t t_n_output_bits, t_n_input_bits;
+ t_n_output_bits = t_n_input_bits = n_input_bits;
+
+ if (d_do_termination == true) {
+
+ // not streaming, doing termination; find the number of bits
+ // currently available with no required inputs, if any
+
+ size_t n_extra = 0;
+ if (d_fsm_state == fsm_enc_conv_doing_term) {
+ n_extra = d_total_n_delays - d_n_enc_bits;
+ }
+
+ t_n_output_bits += n_extra;
- if (DO_PRINT_DEBUG) {
- std::cout << "ending encode_loop.\n";
+ // find the number of blocks using just input bits,
+ // as well as the number of leftover bits
+
+ size_t t_n_blocks = t_n_input_bits / d_block_size_bits;
+ size_t t_leftover_bits = t_n_input_bits % d_block_size_bits;
+
+ // add the number of bits*blocks to the number of output bits, as
+ // well as the number of leftover bits which are not a whole block
+
+ t_n_output_bits += (t_n_blocks * (d_block_size_bits + d_total_n_delays));
+ t_n_output_bits += t_leftover_bits;
}
+
+ return (t_n_output_bits);
}
-void
-encoder_convolutional::get_next_inputs__term
-()
+size_t
+encoder_convolutional::compute_n_input_bits
+(size_t n_output_bits)
{
- // FIXME: how to figure out which term bit to get?
- // loop to set each entry of "d_current_inputs"
+ size_t t_n_output_bits, t_n_input_bits;
+ t_n_output_bits = t_n_input_bits = n_output_bits;
- // need to do feedback separately, since it involves determining the
- // FB bit value & using that as the input value to cancel it out
+ if (d_do_termination == true) {
- d_current_inputs.assign (d_n_code_inputs, 0);
- // return (d_term_states[code_input_n] & 1);
+ // not streaming, doing termination; find the number of bits
+ // currently available with no required inputs, if any
+
+ size_t n_extra = 0;
+ if (d_fsm_state == fsm_enc_conv_doing_term) {
+ n_extra = d_total_n_delays - d_n_enc_bits;
+ }
+
+ // check to see if this is enough; return 0 if it is.
+
+ if (n_extra >= t_n_output_bits)
+ return (0);
+
+ // remove those which require no input
+
+ t_n_output_bits -= n_extra;
+
+ // find the number of blocks of data which could be processed
+
+ size_t t_n_output_bits_per_block = d_block_size_bits + d_total_n_delays;
+
+ // get the base number of input items required for the given
+ // number of blocks to be generated
+
+ 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 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);
}
diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.h b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.h
index 4a0d479ac..11c8b4e69 100644
--- a/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.h
+++ b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.h
@@ -126,12 +126,37 @@ public:
virtual ~encoder_convolutional () {delete d_trellis;};
+/*
+ * Compute the number of input bits needed to produce 'n_output' bits,
+ * and the number of output bits which will be produced by 'n_input'
+ * bits ... for a single stream only.
+ *
+ * For convolutional 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 exactly;
+ *
+ * if (not streaming & termination), depends on the state of the FSM,
+ * and needs to include the number of termination bits (the total # of
+ * delays); ratio is roughly (1:(1+X)), where "X" is the number of
+ * termination bits divided by the (unterminated) block length in bits.
+ *
+ * It's up to the caller to change 'bits' to 'items' ... to know if
+ * bits are packed (see e.g. code_io "ic8l") or not ("ic1l"), or all
+ * streams are mux'ed together into one stream.
+*/
+
+ virtual size_t compute_n_input_bits (size_t n_output_bits);
+ virtual size_t compute_n_output_bits (size_t n_input_bits);
+
/* for remote access to internal info */
inline const bool do_termination () {return (d_do_termination);};
inline const bool do_feedback () {return (d_trellis->do_feedback());};
inline const bool do_streaming () {return (d_do_streaming);};
inline const size_t total_n_delays () {return (d_total_n_delays);};
+ inline const code_convolutional_trellis* trellis() {return (d_trellis);};
protected:
/*
@@ -161,15 +186,13 @@ protected:
int start_memory_state,
int end_memory_state);
- virtual void encode_private (const char** in_buf, char** out_buf);
+ virtual void encode_private ();
+ virtual void encode_loop (const size_t& which_counter, size_t how_many);
- virtual void encode_loop (const char** in_buf, char** out_buf,
- size_t* which_counter, size_t how_many);
-
- inline void get_next_inputs (const char** in_buf) {
+ inline void get_next_inputs () {
switch (d_fsm_state) {
case fsm_enc_conv_doing_input:
- get_next_inputs__input (in_buf);
+ get_next_inputs__input ();
break;
case fsm_enc_conv_doing_term:
get_next_inputs__term ();
@@ -180,7 +203,21 @@ protected:
}
};
- virtual void get_next_inputs__term ();
+ inline virtual void get_next_inputs__input () {
+ d_in_buf->read_items ((void*)(&(d_current_inputs[0])));
+ d_in_buf->increment_indices ();
+ };
+
+ inline virtual void get_next_inputs__term () {
+ d_trellis->get_termination_inputs (d_term_state,
+ d_n_enc_bits,
+ d_current_inputs);
+ };
+
+ inline virtual void write_output_bits () {
+ d_out_buf->write_items ((const void*)(&(d_current_outputs[0])));
+ d_out_buf->increment_indices ();
+ };
void get_memory_requirements (size_t m,
size_t n,
@@ -188,13 +225,6 @@ protected:
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 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;
@@ -203,7 +233,7 @@ protected:
// "total_n_delays" is the total # of delays, needed to determine the
// # of states in the decoder
- size_t d_total_n_delays;
+ size_t d_total_n_delays, d_n_enc_bits;
// the current state of the encoder (all delays / memories)
@@ -225,6 +255,13 @@ protected:
// interpreted w/r.t. the actual trellis;
memory_t d_init_state;
+
+ // "term_state" is the ending state before termination, used by the
+ // trellis to determine the correct input-bit sequences needed to
+ // properly terminate the trellis to the desired end-state;
+ // used only if doing termination.
+
+ memory_t d_term_state;
};
#endif /* INCLUDED_ENCODER_CONVOLUTIONAL_H */
diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.cc b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.cc
deleted file mode 100644
index aa83c0762..000000000
--- a/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.cc
+++ /dev/null
@@ -1,188 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <encoder_convolutional_ic1_ic1.h>
-#include <assert.h>
-#include <iostream>
-#include <mld/n2bs.h>
-
-#define DO_PRINT_DEBUG 0
-
-static const int g_num_bits_per_byte = 8;
-
-// FIXME
-size_t
-encoder_convolutional_ic1_ic1::compute_n_output_bits
-(size_t n_input_bits)
-{
- assert (0);
- return (0);
-}
-
-/*
- * Compute the number of input bits needed to produce
- * 'n_output' bits. For convolutional 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.
- *
- * The returned value will also depend on whether bits are packed, as
- * well as whether streams are mux'ed together.
- */
-
-size_t
-encoder_convolutional_ic1_ic1::compute_n_input_bits
-(size_t n_output_bits)
-{
- size_t t_n_output_bits, t_n_input_bits;
- t_n_output_bits = t_n_input_bits = n_output_bits;
-
- if (d_do_termination == true) {
-
- // not streaming, doing termination; find the number of bits
- // currently available with no required inputs, if any
-
- size_t n_extra = 0;
- if (d_fsm_state == fsm_enc_conv_doing_term) {
- n_extra = d_total_n_delays - d_n_enc_bits;
- }
-
- // check to see if this is enough; return 0 if it is.
-
- if (n_extra >= t_n_output_bits)
- return (0);
-
- // remove those which require no input
-
- t_n_output_bits -= n_extra;
-
- // find the number of blocks of data which could be processed
-
- size_t t_n_output_bits_per_block = d_block_size_bits + d_total_n_delays;
-
- // get the base number of input items required for the given
- // number of blocks to be generated
-
- 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 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);
-}
-
-void
-encoder_convolutional_ic1_ic1::write_output_bits
-(char** out_buf)
-{
- // write all the outputs bits in d_current_outputs LSB (&1) to the
- // given output buffer.
-
- // 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[" << 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], 1) << ", ";
- }
-
- out_buf[n][d_out_buf_ndx] = d_current_outputs[n];
-
- if (DO_PRINT_DEBUG) {
- std::cout << "O_o[][] = " <<
- 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++;
-}
-
-void
-encoder_convolutional_ic1_ic1::get_next_inputs__input
-(const char** in_buf)
-{
- // 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[" << m << "][" << d_in_buf_ndx << "] = " <<
- n2bs (d_current_inputs[m], 1) << "\n";
- }
- }
-
- // decrement the number of bits left on all streams
-
- if (DO_PRINT_DEBUG) {
- std::cout << "# in bits left: " << d_n_input_bits_left <<
- " -> " << (d_n_input_bits_left-1) << "\n";
- }
-
- d_n_input_bits_left--;
-
- // increment the input index (not the bit shift index) for the next
- // read
-
- if (DO_PRINT_DEBUG) {
- std::cout << "# in buf ndx: " << d_in_buf_ndx <<
- " -> " << (d_in_buf_ndx+1) << "\n";
- }
-
- d_in_buf_ndx++;
-}
diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.h b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.h
deleted file mode 100644
index a742b097a..000000000
--- a/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef INCLUDED_ENCODER_CONVOLUTIONAL_IC1_IC1_H
-#define INCLUDED_ENCODER_CONVOLUTIONAL_IC1_IC1_H
-
-#include "encoder_convolutional.h"
-
-class encoder_convolutional_ic1_ic1 : public encoder_convolutional
-{
-public:
-/*!
- * class encoder_convolutional_ic1_ic1 : public encoder_convolutional
- *
- * Encode the incoming streams using a convolutional encoder,
- * "feedforward" or feedback. Optional termination, data
- * streaming, and starting and ending memory states.
- *
- * input is "ic1": 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 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.
- */
-
- encoder_convolutional_ic1_ic1
- (int frame_size_bits,
- int n_code_inputs,
- int n_code_outputs,
- const std::vector<int> &code_generators,
- bool do_termination = true,
- int start_memory_state = 0,
- int end_memory_state = 0)
- : encoder_convolutional (frame_size_bits,
- n_code_inputs,
- n_code_outputs,
- code_generators,
- do_termination,
- start_memory_state,
- end_memory_state) {};
-
- encoder_convolutional_ic1_ic1
- (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 = true,
- int start_memory_state = 0,
- int end_memory_state = 0)
- : encoder_convolutional (frame_size_bits,
- n_code_inputs,
- n_code_outputs,
- code_generators,
- code_feedback,
- do_termination,
- start_memory_state,
- end_memory_state) {};
-
- virtual ~encoder_convolutional_ic1_ic1 () {};
-
- virtual size_t compute_n_input_bits (size_t n_output_bits);
- virtual size_t compute_n_output_bits (size_t n_input_bits);
-
-protected:
- 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 */
diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic8_ic8.cc b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic8_ic8.cc
deleted file mode 100644
index 5d2a4bbbd..000000000
--- a/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic8_ic8.cc
+++ /dev/null
@@ -1,224 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <encoder_convolutional_ic8_ic8.h>
-#include <assert.h>
-#include <iostream>
-
-#define DO_TIME_THOUGHPUT 1
-#define DO_PRINT_DEBUG 1
-
-#if DO_TIME_THOUGHPUT
-#include <mld/mld_timer.h>
-#endif
-#if DO_PRINT_DEBUG
-#include <mld/n2bs.h>
-#endif
-
-// FIXME: when doing packed, should probably allow user to select how
-// bits are selected, so-as to make sure it's always the same
-// no matter the CPU endianness
-
-// FIXME
-size_t
-encoder_convolutional_ic8_ic8::compute_n_output_bits
-(size_t n_input_bits)
-{
- assert (0);
- return (0);
-}
-
-/*
- * Compute the number of input bits needed to produce
- * 'n_output' bits. For convolutional 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.
- *
- * The returned value will also depend on whether bits are packed, as
- * well as whether streams are mux'ed together.
- */
-
-size_t
-encoder_convolutional_ic8_ic8::compute_n_input_bits
-(size_t n_output_bits)
-{
- size_t t_n_output_bits, t_n_input_bits;
- t_n_output_bits = t_n_input_bits = n_output_bits;
-
- if (d_do_termination == true) {
-
- // not streaming, doing termination; find the number of bits
- // currently available with no required inputs, if any
-
- size_t n_extra = 0;
- if (d_fsm_state == fsm_enc_conv_doing_term) {
- n_extra = d_max_memory - d_n_enc_bits;
- }
-
- // check to see if this is enough; return 0 if it is.
-
- if (n_extra >= t_n_output_bits)
- return (0);
-
- // remove those which require no input
-
- t_n_output_bits -= n_extra;
-
- // find the number of frames of data which could be processed
-
- size_t t_n_output_bits_per_frame = d_frame_size_bits + d_max_memory;
-
- // get the base number of input items required for the given
- // number of frames 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;
-
- // 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);
- }
-
- return (t_n_input_bits);
-}
-
-void
-encoder_convolutional_ic8_ic8::increment_io_indices
-(bool while_encoding)
-{
- // increment the buffer index only for this version, only after
- // encoding is done and all resulting outputs are stored on the
- // output streams
-
- if (while_encoding == false) {
- d_out_buf_ndx++;
- d_in_buf_ndx++;
- }
-
- // nothing to do while encoding, so no else
-
-#if 0
-// move counters to the next input bit, wrapping to the next input
-// byte as necessary
- if (++d_in_bit_shift % g_num_bits_per_byte == 0) {
- d_in_bit_shift = 0;
- d_in_buf_ndx++;
- }
-// move counters to the next output bit, wrapping to the next output
-// byte as necessary
- if (++d_out_bit_shift % g_num_bits_per_byte == 0) {
- d_out_bit_shift = 0;
- d_out_buf_ndx++;
- }
-#endif
-}
-
-void
-encoder_convolutional_ic8_ic8::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 "ic8" type output
-
- if (DO_PRINT_DEBUG) {
- std::cout << ", O_i[" << t_output_stream <<
- "][" << d_out_buf_ndx << "] = " <<
- n2bs (out_buf[t_output_stream][d_out_buf_ndx], 2);
- }
-
- out_buf[t_output_stream][d_out_buf_ndx] = t_out_bit;
-
- if (DO_PRINT_DEBUG) {
- std::cout << ", b_out = " << t_out_bit <<
- ", O_o[" << t_output_stream << "][" << d_out_buf_ndx << "][" <<
- d_out_bit_shift << "] = " <<
- n2bs (out_buf[t_output_stream][d_out_buf_ndx], 2) << '\n';
- }
-
-#if 0
-#if DO_PRINT_DEBUG
- std::cout << ", O_i[" << t_output_stream <<
- "][" << d_out_buf_ndx << "] = " <<
- n2bs (out_buf[t_output_stream][d_out_buf_ndx], g_num_bits_per_byte);
-#endif
-
-// packed bits in each output item
- out_buf[t_output_stream][d_out_buf_ndx] |=
- (t_out_bit << d_out_bit_shift);
-
-#if DO_PRINT_DEBUG
- std::cout << ", b_out = " << t_out_bit <<
- ", O_o[" << t_output_stream << "][" << d_out_buf_ndx << "][" <<
- d_out_bit_shift << "] = " <<
- n2bs (out_buf[t_output_stream][d_out_buf_ndx], g_num_bits_per_byte) << '\n';
-#endif
-#endif
-}
-
-char
-encoder_convolutional_ic8_ic8::get_next_bit__input
-(const char** in_buf,
- size_t code_input_n)
-{
- // get a bit from this particular input stream
- // one bit per output item for "ic8" type input
-
- if (DO_PRINT_DEBUG) {
- std::cout << "I[" << p << "][" << d_in_buf_ndx << "] = ";
- cout_binary (t_next_bit, g_num_bits_per_byte);
- std::cout << ", st_i[" << p << "] = ";
- cout_binary ((*t_states_ptr), d_max_memory+2);
- std::cout << ", I[" << p << "][" << d_in_buf_ndx << "][" <<
- d_in_bit_shift << "] = " << t_next_bit <<
- ", st_o[" << p << "] = ";
- cout_binary (t_state, d_max_memory+2);
- std::cout << '\n';
- }
-
- return ((in_buf[code_input_n][d_in_buf_ndx] >> d_in_bit_shift) & 1);
-}
-
-char
-encoder_convolutional_ic8_ic8::get_next_bit__term
-(size_t code_input_n)
-{
- return ((d_term_states[code_input_n] >> d_in_bit_shift) & 1);
-}
diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic8_ic8.h b/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic8_ic8.h
deleted file mode 100644
index dad39400c..000000000
--- a/gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic8_ic8.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef INCLUDED_ENCODER_CONVOLUTIONAL_IC8_IC8_H
-#define INCLUDED_ENCODER_CONVOLUTIONAL_IC8_IC8_H
-
-#include "encoder_convolutional.h"
-
-/*!
- * class encoder_convolutional_ic8_ic8 : public encoder_convolutional
- *
- * Encode the incoming streams using a convolutional encoder,
- * "feedforward" or feedback. Optional termination, data
- * streaming, and starting and ending memory states.
- *
- * input is "ic8": streams of char, one stream per input as defined by the
- * instantiated code, using all 8 bits in the char.
- *
- * FIXME: need to have inputs for MSB or LSB first input and output.
- *
- * output is "ic8": streams of char, one stream per output as defined by the
- * instantiated code, using all 8 bits in the char.
- */
-
-class encoder_convolutional_ic8_ic8 : public encoder_convolutional
-{
-public:
- encoder_convolutional_ic8_ic8
- (int frame_size_bits,
- int n_code_inputs,
- int n_code_outputs,
- const std::vector<int> &code_generators,
- bool do_termination = true,
- int start_memory_state = 0,
- int end_memory_state = 0)
- : encoder_convolutional (frame_size_bits,
- n_code_inputs,
- n_code_outputs,
- code_generators,
- do_termination,
- start_memory_state,
- end_memory_state) {};
-
- encoder_convolutional_ic8_ic8
- (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 = true,
- int start_memory_state = 0,
- int end_memory_state = 0)
- : encoder_convolutional (frame_size_bits,
- n_code_inputs,
- n_code_outputs,
- code_generators,
- code_feedback,
- do_termination,
- start_memory_state,
- end_memory_state) {};
-
- virtual ~encoder_convolutional_ic8_ic8 () {};
-
- virtual size_t compute_n_input_bits (size_t n_output_bits);
- 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 char get_next_bit__term (size_t code_input_n);
- virtual void output_bit (char t_out_bit, char** out_buf,
- size_t t_output_stream);
- virtual void increment_io_indices (bool while_encoding);
- virtual void update_memory_post_encode ();
-};
-
-#endif /* INCLUDED_ENCODER_CONVOLUTIONAL_IC8_IC8_H */
diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder_turbo.cc b/gr-error-correcting-codes/src/lib/libecc/encoder_turbo.cc
index 3f528cb91..fc14ac51d 100644
--- a/gr-error-correcting-codes/src/lib/libecc/encoder_turbo.cc
+++ b/gr-error-correcting-codes/src/lib/libecc/encoder_turbo.cc
@@ -1,52 +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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#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)
+ const std::vector<encoder_convolutional*>& encoders,
+ const std::vector<interleaver_t>& interleavers)
{
- // need error checking on inputs
+ // need error checking on inputs, not yet.
+#if 0
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)
-{
+#endif
}
diff --git a/gr-error-correcting-codes/src/lib/libecc/encoder_turbo.h b/gr-error-correcting-codes/src/lib/libecc/encoder_turbo.h
index 8c295f1e5..982ce7951 100644
--- a/gr-error-correcting-codes/src/lib/libecc/encoder_turbo.h
+++ b/gr-error-correcting-codes/src/lib/libecc/encoder_turbo.h
@@ -24,7 +24,8 @@
#define INCLUDED_ENCODER_TURBO_H
#include "encoder_convolutional.h"
-#include <vector>
+
+typedef std::vector<size_t> interleaver_t;
class encoder_turbo : public encoder
{
@@ -53,18 +54,19 @@ public:
encoder_turbo
(int n_code_inputs,
int n_code_outputs,
- const std::vector<encoder_convolutional*> &encoders,
- const std::vector<size_t> &interleavers);
+ const std::vector<encoder_convolutional*>& encoders,
+ const std::vector<interleaver_t>& interleavers);
virtual ~encoder_turbo () {};
/* for remote access to internal info */
- inline bool do_termination () {return (d_do_termination);};
+ inline const 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);
+ // dummy functions for now
+ virtual size_t compute_n_input_bits (size_t n_output_bits){return(0);};
+ virtual size_t compute_n_output_bits (size_t n_input_bits){return(0);};
#endif
protected:
@@ -84,44 +86,15 @@ protected:
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);
+ virtual void encode_private () {};
+
#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 void encode_private () = 0;
+ virtual void encode_loop (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;
@@ -131,7 +104,6 @@ protected:
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
diff --git a/gr-error-correcting-codes/src/lib/libecc/mld/Makefile.am b/gr-error-correcting-codes/src/lib/libecc/mld/Makefile.am
index b5accd5af..1b816aafd 100644
--- a/gr-error-correcting-codes/src/lib/libecc/mld/Makefile.am
+++ b/gr-error-correcting-codes/src/lib/libecc/mld/Makefile.am
@@ -21,7 +21,7 @@
include $(top_srcdir)/Makefile.common
-INCLUDES = $(STD_DEFINES_AND_INCLUDES) -I.. -I../..
+INCLUDES = $(STD_DEFINES_AND_INCLUDES)
noinst_LTLIBRARIES = libmld.la
diff --git a/gr-error-correcting-codes/src/lib/libecc/mld/n2bs.cc b/gr-error-correcting-codes/src/lib/libecc/mld/n2bs.cc
index 909aa0867..99e95a5d2 100644
--- a/gr-error-correcting-codes/src/lib/libecc/mld/n2bs.cc
+++ b/gr-error-correcting-codes/src/lib/libecc/mld/n2bs.cc
@@ -2,10 +2,8 @@
/*
* Copyright 2006 Free Software Foundation, Inc.
*
- * This file is part of GNU Radio.
+ * This file is part of GNU Radio
*
- * Primary Author: Michael Dickens, NCIP Lab, University of Notre Dame
- *
* 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)
@@ -24,13 +22,12 @@
#include <n2bs.h>
#include <iostream>
+#include "../code_types.h"
const int g_num_bits_per_byte = 8;
-std::string n2bs (long long number, size_t digits)
+std::string DoIt (int64_t number, size_t digits)
{
- if (digits > (sizeof (long long) * g_num_bits_per_byte))
- digits = sizeof (long long);
std::string retVal (digits, '0');
if (number != 0)
for (int n = --digits; n >= 0; n--) {
@@ -41,29 +38,66 @@ std::string n2bs (long long number, size_t digits)
}
return (retVal);
}
-std::string n2bs (char number, size_t digits)
+
+std::string n2bs (int64_t number, size_t digits)
+{
+ if (digits > (sizeof (int64_t) * g_num_bits_per_byte))
+ digits = sizeof (int64_t);
+ return DoIt (number, digits);
+}
+std::string n2bs (int8_t number, size_t digits)
{
- if (digits > (sizeof (char) * g_num_bits_per_byte))
- digits = sizeof (char);
- return n2bs ((long long) number, digits);
+ if (digits > (sizeof (int8_t) * g_num_bits_per_byte))
+ digits = sizeof (int8_t);
+ return DoIt ((int64_t) number, digits);
}
-std::string n2bs (int number, size_t digits)
+std::string n2bs (int16_t number, size_t digits)
{
- if (digits > (sizeof (int) * g_num_bits_per_byte))
- digits = sizeof (int);
- return n2bs ((long long) number, digits);
+ if (digits > (sizeof (int16_t) * g_num_bits_per_byte))
+ digits = sizeof (int16_t);
+ return DoIt ((int64_t) number, digits);
+}
+std::string n2bs (int32_t number, size_t digits)
+{
+ if (digits > (sizeof (int32_t) * g_num_bits_per_byte))
+ digits = sizeof (int32_t);
+ return DoIt ((int64_t) number, digits);
}
std::string n2bs (long number, size_t digits)
{
if (digits > (sizeof (long) * g_num_bits_per_byte))
digits = sizeof (long);
- return n2bs ((long long) number, digits);
+ return DoIt ((int64_t) number, digits);
+}
+std::string n2bs (u_int8_t number, size_t digits)
+{
+ if (digits > (sizeof (u_int8_t) * g_num_bits_per_byte))
+ digits = sizeof (u_int8_t);
+ return DoIt ((int64_t) number, digits);
+}
+std::string n2bs (u_int16_t number, size_t digits)
+{
+ if (digits > (sizeof (u_int16_t) * g_num_bits_per_byte))
+ digits = sizeof (u_int16_t);
+ return DoIt ((int64_t) number, digits);
+}
+std::string n2bs (u_int32_t number, size_t digits)
+{
+ if (digits > (sizeof (u_int32_t) * g_num_bits_per_byte))
+ digits = sizeof (u_int32_t);
+ return DoIt ((int64_t) number, digits);
+}
+std::string n2bs (unsigned long number, size_t digits)
+{
+ if (digits > (sizeof (unsigned long) * g_num_bits_per_byte))
+ digits = sizeof (unsigned long);
+ return DoIt ((int64_t) number, digits);
}
-std::string n2bs (size_t number, size_t digits)
+std::string n2bs (u_int64_t number, size_t digits)
{
- if (digits > (sizeof (size_t) * g_num_bits_per_byte))
- digits = sizeof (size_t);
- return n2bs ((long long) number, digits);
+ if (digits > (sizeof (u_int64_t) * g_num_bits_per_byte))
+ digits = sizeof (u_int64_t);
+ return DoIt ((int64_t) number, digits);
}
void cout_binary (int number, int digits)
diff --git a/gr-error-correcting-codes/src/lib/libecc/mld/n2bs.h b/gr-error-correcting-codes/src/lib/libecc/mld/n2bs.h
index a663dce8a..16ef4d758 100644
--- a/gr-error-correcting-codes/src/lib/libecc/mld/n2bs.h
+++ b/gr-error-correcting-codes/src/lib/libecc/mld/n2bs.h
@@ -2,10 +2,8 @@
/*
* Copyright 2006 Free Software Foundation, Inc.
*
- * This file is part of GNU Radio.
+ * This file is part of GNU Radio
*
- * Primary Author: Michael Dickens, NCIP Lab, University of Notre Dame
- *
* 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)
@@ -22,11 +20,26 @@
* Boston, MA 02111-1307, USA.
*/
+#ifndef INCLUDED_N2BS_H
+#define INCLUDED_N2BS_H
+
#include <string>
-extern std::string n2bs (char number, size_t digits);
-extern std::string n2bs (int number, size_t digits);
-extern std::string n2bs (long number, size_t digits);
-extern std::string n2bs (size_t number, size_t digits);
-extern std::string n2bs (long long number, size_t digits);
-extern void cout_binary (int number, int digits);
+std::string n2bs (int8_t number, size_t digits);
+std::string n2bs (int16_t number, size_t digits);
+std::string n2bs (int32_t number, size_t digits);
+#if 1
+std::string n2bs (long number, size_t digits);
+#endif
+std::string n2bs (int64_t number, size_t digits);
+std::string n2bs (u_int8_t number, size_t digits);
+std::string n2bs (u_int16_t number, size_t digits);
+std::string n2bs (u_int32_t number, size_t digits);
+#if 1
+std::string n2bs (unsigned long number, size_t digits);
+#endif
+std::string n2bs (u_int64_t number, size_t digits);
+
+void cout_binary (int number, int digits);
+
+#endif /* INCLUDED_N2BS_H */
diff --git a/gr-error-correcting-codes/src/lib/libecc/tests/Makefile.am b/gr-error-correcting-codes/src/lib/libecc/tests/Makefile.am
index 79850ba74..2be5a8c2b 100644
--- a/gr-error-correcting-codes/src/lib/libecc/tests/Makefile.am
+++ b/gr-error-correcting-codes/src/lib/libecc/tests/Makefile.am
@@ -21,7 +21,8 @@
include $(top_srcdir)/Makefile.common
-INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) -I..
+INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) \
+ -I$(top_srcdir)/gr-error-correcting-codes/src/lib/libecc
noinst_LTLIBRARIES = libecc-qa.la
diff --git a/gr-error-correcting-codes/src/lib/libecc/tests/qa_encoder_convolutional_ic1_ic1.cc b/gr-error-correcting-codes/src/lib/libecc/tests/qa_encoder_convolutional_ic1_ic1.cc
index 6ea72b6f8..7e9e1c37c 100644
--- a/gr-error-correcting-codes/src/lib/libecc/tests/qa_encoder_convolutional_ic1_ic1.cc
+++ b/gr-error-correcting-codes/src/lib/libecc/tests/qa_encoder_convolutional_ic1_ic1.cc
@@ -20,7 +20,7 @@
* Boston, MA 02111-1307, USA.
*/
-#include "encoder_convolutional_ic1_ic1.h"
+#include "encoder_convolutional.h"
#include <qa_encoder_convolutional_ic1_ic1.h>
#include <cppunit/TestAssert.h>
#include <string.h>
@@ -28,11 +28,12 @@
#include <iomanip>
#include <stdio.h>
-
void
qa_encoder_convolutional_ic1_ic1::do_encoder_check
-(const char** c_in,
+(int test_n,
+ const char** c_in,
const char** c_res,
+ int n_input_items,
int n_output_items,
int block_size_bits,
int n_code_inputs,
@@ -45,7 +46,7 @@ qa_encoder_convolutional_ic1_ic1::do_encoder_check
for (int m = 0; m < n_code_inputs * n_code_outputs; m++)
t_code_generators[m] = code_generators[m];
- encoder_convolutional_ic1_ic1* t_encoder;
+ encoder_convolutional* t_encoder;
if (code_feedback) {
std::vector<int> t_code_feedback;
@@ -53,33 +54,48 @@ qa_encoder_convolutional_ic1_ic1::do_encoder_check
for (int m = 0; m < n_code_inputs * n_code_outputs; m++)
t_code_feedback[m] = code_feedback[m];
- t_encoder = new encoder_convolutional_ic1_ic1
+ t_encoder = new encoder_convolutional
(block_size_bits,
n_code_inputs,
n_code_outputs,
t_code_generators,
t_code_feedback);
} else {
- t_encoder = new encoder_convolutional_ic1_ic1
+ t_encoder = new encoder_convolutional
(block_size_bits,
n_code_inputs,
n_code_outputs,
t_code_generators);
}
+ code_input_ic1l* t_c_in = new code_input_ic1l (n_code_inputs);
+ t_c_in->set_buffer ((void**) c_in, n_input_items);
+
char** t_out = new char*[n_code_outputs];
for (int m = 0; m < n_code_outputs; m++) {
t_out[m] = new char[n_output_items];
}
- t_encoder->encode (c_in, (char**) t_out, n_output_items);
+ code_output_ic1l* t_c_out = new code_output_ic1l (n_code_outputs);
+ t_c_out->set_buffer ((void**) t_out, n_output_items);
+
+ t_encoder->encode (t_c_in, t_c_out, n_output_items);
for (int m = 0; m < n_code_outputs; m++) {
for (int n = 0; n < n_output_items; n++) {
+ if (c_res[m][n] != t_out[m][n]) {
+ std::cout << "Test " << test_n << ": Item [" << m <<
+ "][" << n << "] not equal: des = " << (int)(c_res[m][n]) <<
+ ", act = " << (int)(t_out[m][n]) << "\n";
+ }
CPPUNIT_ASSERT_EQUAL (c_res[m][n], t_out[m][n]);
}
}
+ delete t_c_out;
+ t_c_out = 0;
+ delete t_c_in;
+ t_c_in = 0;
delete t_encoder;
t_encoder = 0;
@@ -122,9 +138,10 @@ void
qa_encoder_convolutional_ic1_ic1::t0
()
{
- do_encoder_check ((const char**) t0_in, (const char**) t0_res,
- t0_n_output_items, 100, t0_n_code_inputs,
- t0_n_code_outputs, (const int*) t0_code_generator);
+ do_encoder_check (0, (const char**) t0_in, (const char**) t0_res,
+ t0_n_input_items, t0_n_output_items, 100,
+ t0_n_code_inputs, t0_n_code_outputs,
+ (const int*) t0_code_generator);
}
// TEST 1
@@ -158,9 +175,10 @@ void
qa_encoder_convolutional_ic1_ic1::t1
()
{
- do_encoder_check ((const char**) t1_in, (const char**) t1_res,
- t1_n_output_items, 100, t1_n_code_inputs,
- t1_n_code_outputs, (const int*) t1_code_generator);
+ do_encoder_check (1, (const char**) t1_in, (const char**) t1_res,
+ t1_n_input_items, t1_n_output_items, 100,
+ t1_n_code_inputs, t1_n_code_outputs,
+ (const int*) t1_code_generator);
}
// TEST 2
@@ -195,9 +213,10 @@ void
qa_encoder_convolutional_ic1_ic1::t2
()
{
- do_encoder_check ((const char**) t2_in, (const char**) t2_res,
- t2_n_output_items, 100, t2_n_code_inputs,
- t2_n_code_outputs, (const int*) t2_code_generator,
+ do_encoder_check (2, (const char**) t2_in, (const char**) t2_res,
+ t2_n_input_items, t2_n_output_items, 100,
+ t2_n_code_inputs, t2_n_code_outputs,
+ (const int*) t2_code_generator,
(const int*) t2_code_feedback);
}
@@ -233,9 +252,10 @@ void
qa_encoder_convolutional_ic1_ic1::t3
()
{
- do_encoder_check ((const char**) t3_in, (const char**) t3_res,
- t3_n_output_items, 100, t3_n_code_inputs,
- t3_n_code_outputs, (const int*) t3_code_generator,
+ do_encoder_check (3, (const char**) t3_in, (const char**) t3_res,
+ t3_n_input_items, t3_n_output_items, 100,
+ t3_n_code_inputs, t3_n_code_outputs,
+ (const int*) t3_code_generator,
(const int*) t3_code_feedback);
}
@@ -271,9 +291,10 @@ void
qa_encoder_convolutional_ic1_ic1::t4
()
{
- do_encoder_check ((const char**) t4_in, (const char**) t4_res,
- t4_n_output_items, 100, t4_n_code_inputs,
- t4_n_code_outputs, (const int*) t4_code_generator,
+ do_encoder_check (4, (const char**) t4_in, (const char**) t4_res,
+ t4_n_input_items, t4_n_output_items, 100,
+ t4_n_code_inputs, t4_n_code_outputs,
+ (const int*) t4_code_generator,
(const int*) t4_code_feedback);
}
@@ -310,9 +331,10 @@ qa_encoder_convolutional_ic1_ic1::t5
()
{
#if 0
- do_encoder_check ((const char**) t5_in, (const char**) t5_res,
- t5_n_output_items, 100, t5_n_code_inputs,
- t5_n_code_outputs, (const int*) t5_code_generator);
+ do_encoder_check (5, (const char**) t5_in, (const char**) t5_res,
+ t5_n_input_items, t5_n_output_items, 100,
+ t5_n_code_inputs, t5_n_code_outputs,
+ (const int*) t5_code_generator);
#endif
}
@@ -346,8 +368,8 @@ void
qa_encoder_convolutional_ic1_ic1::t6
()
{
- do_encoder_check ((const char**) t6_in, (const char**) t6_res,
- t6_n_output_items, 5, t6_n_code_inputs,
+ do_encoder_check (6, (const char**) t6_in, (const char**) t6_res,
+ t6_n_input_items, t6_n_output_items, 5, t6_n_code_inputs,
t6_n_code_outputs, (const int*) t6_code_generator);
}
@@ -383,8 +405,8 @@ qa_encoder_convolutional_ic1_ic1::t7
()
{
#if 0
- do_encoder_check ((const char**) t7_in, (const char**) t7_res,
- t7_n_output_items, 5, t7_n_code_inputs,
+ do_encoder_check (7, (const char**) t7_in, (const char**) t7_res,
+ t7_n_input_items, t7_n_output_items, 5, t7_n_code_inputs,
t7_n_code_outputs, (const int*) t7_code_generator,
(const int*) t7_code_feedback);
#endif
@@ -422,8 +444,8 @@ qa_encoder_convolutional_ic1_ic1::t8
()
{
#if 0
- do_encoder_check ((const char**) t8_in, (const char**) t8_res,
- t8_n_output_items, 5, t8_n_code_inputs,
+ do_encoder_check (8, (const char**) t8_in, (const char**) t8_res,
+ t8_n_input_items, t8_n_output_items, 5, t8_n_code_inputs,
t8_n_code_outputs, (const int*) t8_code_generator,
(const int*) t8_code_feedback);
#endif
diff --git a/gr-error-correcting-codes/src/lib/libecc/tests/qa_encoder_convolutional_ic1_ic1.h b/gr-error-correcting-codes/src/lib/libecc/tests/qa_encoder_convolutional_ic1_ic1.h
index 4449e9eb8..64ab3ab5f 100644
--- a/gr-error-correcting-codes/src/lib/libecc/tests/qa_encoder_convolutional_ic1_ic1.h
+++ b/gr-error-correcting-codes/src/lib/libecc/tests/qa_encoder_convolutional_ic1_ic1.h
@@ -42,8 +42,10 @@ class qa_encoder_convolutional_ic1_ic1 : public CppUnit::TestCase {
CPPUNIT_TEST_SUITE_END ();
private:
- void do_encoder_check (const char** c_t1_in,
+ void do_encoder_check (int test_n,
+ const char** c_t1_in,
const char** c_t1_res,
+ int n_input_items,
int n_output_items,
int block_size_bits,
int n_code_inputs,
diff --git a/gr-error-correcting-codes/src/python/Makefile.am b/gr-error-correcting-codes/src/python/Makefile.am
index 7c387f92d..fdbb2800c 100644
--- a/gr-error-correcting-codes/src/python/Makefile.am
+++ b/gr-error-correcting-codes/src/python/Makefile.am
@@ -23,7 +23,7 @@ include $(top_srcdir)/Makefile.common
EXTRA_DIST = run_tests.in
-TESTS = run_tests
+#TESTS = run_tests
noinst_PYTHON = qa_test_coding_1.py qa_test_coding_2.py