3 * Copyright 2006 Free Software Foundation, Inc.
5 * This file is part of GNU Radio
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)
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.
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.
27 #include "encoder_convolutional.h"
31 #define DO_TIME_THOUGHPUT 0
32 #define DO_PRINT_DEBUG 1
34 #include <mld/mld_timer.h>
37 static const int g_max_block_size_bits = 10000000;
38 static const int g_max_num_streams = 10;
39 static const int g_num_bits_per_byte = 8;
41 void encoder_convolutional::encoder_convolutional_init
45 const std::vector<int>& code_generators,
46 const std::vector<int>* code_feedback,
48 int start_memory_state,
51 // error checking on the input arguments is done by the trellis class
54 d_trellis = new code_convolutional_trellis
63 d_trellis = new code_convolutional_trellis
71 // set the initial FSM state to 'init'
73 d_fsm_state = fsm_enc_conv_init;
75 // create the class block variables
77 d_block_size_bits = block_size_bits;
78 d_n_code_inputs = n_code_inputs;
79 d_n_code_outputs = n_code_outputs;
80 d_do_streaming = d_trellis->do_streaming ();
81 d_do_termination = d_trellis->do_termination ();
82 d_total_n_delays = d_trellis->total_n_delays ();
84 // parse the init state
86 memory_t t_mask = (memory_t)((2 << d_total_n_delays) - 1);
87 size_t t_n_states = (1 << d_total_n_delays);
89 if (start_memory_state & t_mask) {
90 std::cout << "encoder_convolutional: Warning: " <<
91 "provided end memory state out (" << end_memory_state <<
92 ") is out of the state range [0, " <<
93 (t_n_states-1) << "]; masking off the unused bits.\n";
95 start_memory_state &= t_mask;
98 d_init_state = start_memory_state;
100 d_current_inputs.assign (d_n_code_inputs, 0);
101 d_current_outputs.assign (d_n_code_outputs, 0);
105 encoder_convolutional::encode_private
106 (const char** in_buf,
110 if (DO_TIME_THOUGHPUT) {
114 // reset buffer indices
116 d_total_n_enc_bits = d_in_buf_ndx = d_out_buf_ndx =
117 d_in_bit_shift = d_out_bit_shift = 0;
119 if (DO_PRINT_DEBUG) {
120 std::cout << "Beginning this encode() call; starting parameters.\n";
121 std::cout << "d_n_input_bits_left = " << d_n_input_bits_left << '\n';
122 std::cout << "d_n_output_bits_left = " << d_n_output_bits_left << '\n';
125 // while there are inputs and outputs left to process ...
127 while ((d_n_input_bits_left != 0) & (d_n_output_bits_left != 0)) {
129 // jump to the correct state in the fsm
131 switch (d_fsm_state) {
133 case fsm_enc_conv_init:
135 // copy the init states to the current memory
137 d_memory = d_init_state;
139 // if not doing streaming, things to do; else nothing more do
141 if (d_do_streaming == false) {
143 // reset the number of encoded bits in this block (which is
144 // used to compare with the number of bits in the block)
149 // move to the 'input' state
151 d_fsm_state = fsm_enc_conv_doing_input;
154 case fsm_enc_conv_doing_input:
156 // working through the trellis section which requires input bits
157 // from external sources; loop up to the block size (before
158 // termination bits, if any), counting down the number of
159 // available input bits.
161 encode_loop (in_buf, out_buf, &d_n_input_bits_left, d_block_size_bits);
163 // finished this loop; check for jumping to the next state
165 if ((d_n_enc_bits == d_block_size_bits) & (d_do_streaming == false)) {
167 // jump to another state, depending on termination requirement
169 if (d_do_termination == true) {
171 d_fsm_state = fsm_enc_conv_doing_term;
173 d_fsm_state = fsm_enc_conv_init;
178 case fsm_enc_conv_doing_term:
180 // terminating the trellis, trying to get to a specific state;
181 // better get here only when do_termination is true, but check
182 // just in case; lop up to the max memory, counting down the
183 // number of output bits left
185 if (d_do_termination == true) {
186 encode_loop (in_buf, out_buf, &d_n_output_bits_left, d_total_n_delays);
188 // finished this loop; check for jumping to the next state
190 if (d_n_enc_bits == d_total_n_delays)
191 d_fsm_state = fsm_enc_conv_init;
194 // should never get here!
200 // better never get here!
204 // done (switch) with FSM
207 // done (while) there are inputs and outputs
210 if (DO_PRINT_DEBUG) {
211 std::cout << "Done with this encode() call; ending parameters.\n"
212 "d_in_bit_shift = " << d_in_bit_shift << "\n"
213 "d_out_bit_shift = " << d_out_bit_shift << "\n"
214 "d_in_buf_ndx = " << d_in_buf_ndx << "\n"
215 "d_out_buf_ndx = " << d_out_buf_ndx << "\n"
216 "d_n_input_bits_left = " << d_n_input_bits_left << "\n"
217 "d_n_output_bits_left = " << d_n_output_bits_left << "\n"
218 "d_total_n_enc_bits = " << d_total_n_enc_bits << "\n";
221 if (DO_TIME_THOUGHPUT) {
222 // compute the throughput for this particular function call
223 u_long d_t = end_timer (&t_tp);
224 std::cout << "Completed " << d_total_n_enc_bits <<
225 " bits in " << d_t << " usec => " <<
226 1e6*(((double) d_total_n_enc_bits)/((double) d_t)) <<
232 encoder_convolutional::encode_loop
233 (const char** in_buf,
235 size_t* which_counter,
238 // generic encode_loop
240 if (DO_PRINT_DEBUG) {
241 std::cout << "Starting encode_loop.\n";
244 while (((*which_counter) > 0) & (d_n_enc_bits < how_many)) {
245 if (DO_PRINT_DEBUG) {
246 std::cout << "*w_c = " << (*which_counter) << ", "
247 "# enc_bits = " << d_n_enc_bits << " of " << how_many << ".\n"
248 "Getting new inputs.\n";
251 // get the next set of input bits from all streams;
252 // written into d_current_inputs
254 get_next_inputs (in_buf);
256 // use the trellis to do the encoding;
257 // updates the input memory to the new memory state for the given input
258 // and writes the output bits to the current_outputs
260 d_trellis->encode_lookup (d_memory, d_current_inputs, d_current_outputs);
262 // write the bits in d_current_outputs into the output buffer
264 write_output_bits (out_buf);
266 // increment the number of encoded bits for the current block, and
267 // the total number of bits for this running of "encode()"
270 d_total_n_enc_bits++;
273 if (DO_PRINT_DEBUG) {
274 std::cout << "ending encode_loop.\n";
279 encoder_convolutional::get_next_inputs__term
282 // FIXME: how to figure out which term bit to get?
283 // loop to set each entry of "d_current_inputs"
285 // need to do feedback separately, since it involves determining the
286 // FB bit value & using that as the input value to cancel it out
288 d_current_inputs.assign (d_n_code_inputs, 0);
289 // return (d_term_states[code_input_n] & 1);