Houston, we have a trunk.
[debian/gnuradio] / gr-error-correcting-codes / src / lib / libecc / encoder_convolutional_ic1_ic1.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2006 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <encoder_convolutional_ic1_ic1.h>
28 #include <assert.h>
29 #include <iostream>
30 #include <mld/n2bs.h>
31
32 #define DO_PRINT_DEBUG 0
33
34 static const int g_num_bits_per_byte = 8;
35
36 // FIXME
37 size_t
38 encoder_convolutional_ic1_ic1::compute_n_output_bits
39 (size_t n_input_bits)
40 {
41   assert (0);
42   return (0);
43 }
44
45 /*
46  * Compute the number of input bits needed to produce
47  * 'n_output' bits.  For convolutional encoders, there is
48  * 1 bit output per bit input per stream, with the addition of a some
49  * bits for trellis termination if selected.  Thus the input:output
50  * bit ratio will be:
51  * 
52  * if (streaming | no termination), 1:1
53  *
54  * if (not streaming & termination), roughly 1:(1+X), where "X" is the
55  * total memory size of the code divided by the block length in bits.
56  * But this also depends on the state of the FSM ... how many bits are
57  * left before termination.
58  *
59  * The returned value will also depend on whether bits are packed, as
60  * well as whether streams are mux'ed together.
61  */
62
63 size_t
64 encoder_convolutional_ic1_ic1::compute_n_input_bits
65 (size_t n_output_bits)
66 {
67   size_t t_n_output_bits, t_n_input_bits;
68   t_n_output_bits = t_n_input_bits = n_output_bits;
69
70   if (d_do_termination == true) {
71
72     // not streaming, doing termination; find the number of bits
73     // currently available with no required inputs, if any
74
75     size_t n_extra = 0;
76     if (d_fsm_state == fsm_enc_conv_doing_term) {
77       n_extra = d_total_n_delays - d_n_enc_bits;
78     }
79
80     // check to see if this is enough; return 0 if it is.
81
82     if (n_extra >= t_n_output_bits)
83       return (0);
84
85     // remove those which require no input
86
87     t_n_output_bits -= n_extra;
88
89     // find the number of blocks of data which could be processed
90
91     size_t t_n_output_bits_per_block = d_block_size_bits + d_total_n_delays;
92
93     // get the base number of input items required for the given
94     // number of blocks to be generated
95
96     size_t t_n_blocks = t_n_output_bits / t_n_output_bits_per_block;
97     t_n_input_bits = t_n_blocks * d_block_size_bits;
98
99     // add to that the number of leftover inputs needed to generate
100     // the remainder of the outputs within the remaining block, up to
101     // the given block size (since anything beyond that within this
102     // block requires no inputs)
103
104     size_t t_leftover_bits = t_n_output_bits % t_n_output_bits_per_block;
105     t_n_input_bits += ((t_leftover_bits > d_block_size_bits) ?
106                        d_block_size_bits : t_leftover_bits);
107   }
108
109   return (t_n_input_bits);
110 }
111
112 void
113 encoder_convolutional_ic1_ic1::write_output_bits
114 (char** out_buf)
115 {
116   // write all the outputs bits in d_current_outputs LSB (&1) to the
117   // given output buffer.
118
119   // one bit per output 'char' for "ic1" type output
120
121   for (size_t n = 0; n < d_n_code_outputs; n++) {
122     if (DO_PRINT_DEBUG) {
123       std::cout << "Starting output_bit:\n"
124         "  O_i[" << n << "][" << d_out_buf_ndx << "] = " <<
125         n2bs (out_buf[n][d_out_buf_ndx], g_num_bits_per_byte) <<
126         ", b_out = " << n2bs (d_current_outputs[n], 1) << ", ";
127     }
128
129     out_buf[n][d_out_buf_ndx] = d_current_outputs[n];
130
131     if (DO_PRINT_DEBUG) {
132       std::cout << "O_o[][] = " <<
133         n2bs (out_buf[n][d_out_buf_ndx], g_num_bits_per_byte) <<
134         "\n";
135     }
136   }
137
138   if (DO_PRINT_DEBUG) {
139     std::cout << "Ending write_output_bits.\n";
140   }
141
142   // decrement the number of output bits left on all streams
143
144   d_n_output_bits_left--;
145
146   // increment the output index (not the bit shift index) for the next
147   // write
148
149   d_out_buf_ndx++;
150 }
151
152 void
153 encoder_convolutional_ic1_ic1::get_next_inputs__input
154 (const char** in_buf)
155 {
156   // get the next set of input bits, moved into the LSB (&1) of
157   // d_current_inputs
158
159   // one bit per input 'char' for "ic1" type input
160
161   for (size_t m = 0; m < d_n_code_inputs; m++) {
162     d_current_inputs[m] = ((in_buf[m][d_in_buf_ndx]) & 1);
163
164     if (DO_PRINT_DEBUG) {
165       std::cout << "I[" << m << "][" << d_in_buf_ndx << "] = " <<
166         n2bs (d_current_inputs[m], 1) << "\n";
167     }
168   }
169
170   // decrement the number of bits left on all streams
171
172   if (DO_PRINT_DEBUG) {
173     std::cout << "# in bits left: " << d_n_input_bits_left <<
174       " -> " << (d_n_input_bits_left-1) << "\n";
175   }
176
177   d_n_input_bits_left--;
178
179   // increment the input index (not the bit shift index) for the next
180   // read
181
182   if (DO_PRINT_DEBUG) {
183     std::cout << "# in buf ndx: " << d_in_buf_ndx <<
184       " -> " << (d_in_buf_ndx+1) << "\n";
185   }
186
187   d_in_buf_ndx++;
188 }