Houston, we have a trunk.
[debian/gnuradio] / gr-error-correcting-codes / src / lib / libecc / encoder_convolutional_ic8_ic8.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_ic8_ic8.h>
28 #include <assert.h>
29 #include <iostream>
30
31 #define DO_TIME_THOUGHPUT 1
32 #define DO_PRINT_DEBUG 1
33
34 #if DO_TIME_THOUGHPUT
35 #include <mld/mld_timer.h>
36 #endif
37 #if DO_PRINT_DEBUG
38 #include <mld/n2bs.h>
39 #endif
40
41 // FIXME: when doing packed, should probably allow user to select how
42 // bits are selected, so-as to make sure it's always the same
43 // no matter the CPU endianness
44
45 // FIXME
46 size_t
47 encoder_convolutional_ic8_ic8::compute_n_output_bits
48 (size_t n_input_bits)
49 {
50   assert (0);
51   return (0);
52 }
53
54 /*
55  * Compute the number of input bits needed to produce
56  * 'n_output' bits.  For convolutional encoders, there is
57  * 1 bit output per bit input per stream, with the addition of a some
58  * bits for trellis termination if selected.  Thus the input:output
59  * bit ratio will be:
60  * 
61  * if (streaming | no termination), 1:1
62  *
63  * if (not streaming & termination), roughly 1:(1+X), where "X" is the
64  * total memory size of the code divided by the block length in bits.
65  * But this also depends on the state of the FSM ... how many bits are
66  * left before termination.
67  *
68  * The returned value will also depend on whether bits are packed, as
69  * well as whether streams are mux'ed together.
70  */
71
72 size_t
73 encoder_convolutional_ic8_ic8::compute_n_input_bits
74 (size_t n_output_bits)
75 {
76   size_t t_n_output_bits, t_n_input_bits;
77   t_n_output_bits = t_n_input_bits = n_output_bits;
78
79   if (d_do_termination == true) {
80
81     // not streaming, doing termination; find the number of bits
82     // currently available with no required inputs, if any
83
84     size_t n_extra = 0;
85     if (d_fsm_state == fsm_enc_conv_doing_term) {
86       n_extra = d_max_memory - d_n_enc_bits;
87     }
88
89     // check to see if this is enough; return 0 if it is.
90
91     if (n_extra >= t_n_output_bits)
92       return (0);
93
94     // remove those which require no input
95
96     t_n_output_bits -= n_extra;
97
98     // find the number of frames of data which could be processed
99
100     size_t t_n_output_bits_per_frame = d_frame_size_bits + d_max_memory;
101
102     // get the base number of input items required for the given
103     // number of frames to be generated
104
105     size_t t_n_frames = t_n_output_bits / t_n_output_bits_per_frame;
106     t_n_input_bits = t_n_frames * d_frame_size_bits;
107
108     // add to that the number of leftover inputs needed to generate
109     // the remainder of the outputs within the remaining frame, up to
110     // the given frame size (since anything beyond that within this
111     // frame requires no inputs)
112
113     size_t t_leftover_bits = t_n_output_bits % t_n_output_bits_per_frame;
114     t_n_input_bits += ((t_leftover_bits > d_frame_size_bits) ?
115                        d_frame_size_bits : t_leftover_bits);
116   }
117
118   return (t_n_input_bits);
119 }
120
121 void
122 encoder_convolutional_ic8_ic8::increment_io_indices
123 (bool while_encoding)
124 {
125   // increment the buffer index only for this version, only after
126   // encoding is done and all resulting outputs are stored on the
127   // output streams
128
129   if (while_encoding == false) {
130     d_out_buf_ndx++;
131     d_in_buf_ndx++;
132   }
133
134   // nothing to do while encoding, so no else
135
136 #if 0
137 // move counters to the next input bit, wrapping to the next input
138 // byte as necessary
139   if (++d_in_bit_shift % g_num_bits_per_byte == 0) {
140     d_in_bit_shift = 0;
141     d_in_buf_ndx++;
142   }
143 // move counters to the next output bit, wrapping to the next output
144 // byte as necessary
145     if (++d_out_bit_shift % g_num_bits_per_byte == 0) {
146       d_out_bit_shift = 0;
147       d_out_buf_ndx++;
148     }
149 #endif
150 }
151
152 void
153 encoder_convolutional_ic8_ic8::output_bit
154 (char t_out_bit,
155  char** out_buf,
156  size_t t_output_stream)
157 {
158   // store the result for this particular output stream
159   // one bit per output item for "ic8" type output
160
161   if (DO_PRINT_DEBUG) {
162     std::cout << ", O_i[" << t_output_stream <<
163       "][" << d_out_buf_ndx << "] = " <<
164       n2bs (out_buf[t_output_stream][d_out_buf_ndx], 2);
165   }
166
167   out_buf[t_output_stream][d_out_buf_ndx] = t_out_bit;
168
169   if (DO_PRINT_DEBUG) {
170     std::cout << ", b_out = " << t_out_bit <<
171       ", O_o[" << t_output_stream << "][" << d_out_buf_ndx << "][" <<
172       d_out_bit_shift << "] = " <<
173       n2bs (out_buf[t_output_stream][d_out_buf_ndx], 2) << '\n';
174   }
175
176 #if 0
177 #if DO_PRINT_DEBUG
178   std::cout << ", O_i[" << t_output_stream <<
179     "][" << d_out_buf_ndx << "] = " <<
180     n2bs (out_buf[t_output_stream][d_out_buf_ndx], g_num_bits_per_byte);
181 #endif
182
183 // packed bits in each output item
184   out_buf[t_output_stream][d_out_buf_ndx] |=
185     (t_out_bit << d_out_bit_shift);
186
187 #if DO_PRINT_DEBUG
188   std::cout << ", b_out = " << t_out_bit <<
189     ", O_o[" << t_output_stream << "][" << d_out_buf_ndx << "][" <<
190     d_out_bit_shift << "] = " <<
191     n2bs (out_buf[t_output_stream][d_out_buf_ndx], g_num_bits_per_byte) << '\n';
192 #endif
193 #endif
194 }
195
196 char
197 encoder_convolutional_ic8_ic8::get_next_bit__input
198 (const char** in_buf,
199  size_t code_input_n)
200 {
201   // get a bit from this particular input stream
202   // one bit per output item for "ic8" type input
203
204   if (DO_PRINT_DEBUG) {
205     std::cout << "I[" << p << "][" << d_in_buf_ndx << "] = ";
206     cout_binary (t_next_bit, g_num_bits_per_byte);
207     std::cout << ", st_i[" << p << "] = ";
208     cout_binary ((*t_states_ptr), d_max_memory+2);
209     std::cout << ", I[" << p << "][" << d_in_buf_ndx << "][" <<
210       d_in_bit_shift << "] = " << t_next_bit <<
211       ", st_o[" << p << "] = ";
212     cout_binary (t_state, d_max_memory+2);
213     std::cout << '\n';
214   }
215
216    return ((in_buf[code_input_n][d_in_buf_ndx] >> d_in_bit_shift) & 1);
217 }
218
219 char
220 encoder_convolutional_ic8_ic8::get_next_bit__term
221 (size_t code_input_n)
222 {
223   return ((d_term_states[code_input_n] >> d_in_bit_shift) & 1);
224 }