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 <gr_streams_encode_turbo.h>
28 #include <gr_io_signature.h>
32 gr_streams_encode_turbo_sptr
33 gr_make_streams_encode_turbo
36 const std::vector<gr_streams_encode_convolutional_sptr> &encoders,
37 const std::vector<size_t> &interleavers)
39 return gr_streams_encode_turbo_sptr
40 (new gr_streams_encode_turbo (n_code_inputs,
46 gr_streams_encode_turbo::gr_streams_encode_turbo
49 const std::vector<gr_streams_encode_convolutional_sptr> &encoders,
50 const std::vector<size_t> &interleavers)
51 : gr_block ("streams_encode_turbo",
52 gr_make_io_signature (0, 0, 0),
53 gr_make_io_signature (0, 0, 0))
55 // error checking is done by the encoder class itself;
56 // just pass items on here.
58 // check out individual encoders, to make sure the total input /
59 // output matches those specified by the user.
61 d_n_encoders = encoders.size ();
63 if (d_n_encoders < 2) {
64 std::cerr << "gr_streams_encode_turbo: Error: "
65 "too few (" << d_n_encoders << ") encoders specified; a Turbo "
66 "code requires at least 2 constituent encoders.\n";
70 // make sure that the block size and termination are consistent for
71 // all encoders; warn the user if not, since it doesn't really
72 // matter to the encoder (but it might to the decoder; remains to be
75 encoder_convolutional_ic1_ic1* t_ec = encoders[0]->encoder ();
76 d_block_size_bits = t_ec->block_size_bits ();
77 d_do_termination = t_ec->do_termination ();
78 bool t_diff_block_size, t_diff_termination;
79 t_diff_block_size = t_diff_termination = false;
81 for (size_t m = 1; m < d_n_encoders; m++) {
82 t_ec = encoders[0]->encoder ();
83 size_t t_block_size_bits = t_ec->block_size_bits ();
84 if (t_block_size_bits != d_block_size_bits)
85 t_diff_block_size = true;
86 bool t_do_termination = t_ec->do_termination ();
87 if (t_do_termination != d_do_termination)
88 t_do_termination = true;
91 if (t_diff_block_size == true) {
92 std::cout << "gr_streams_encode_turbo: Warning: "
93 "Some constituent encoders have different block size (bits).\n";
95 if (t_diff_termination == true) {
96 std::cout << "gr_streams_encode_turbo: Warning: "
97 "Some constituent encoders are differently terminationed.\n";
100 std::cout << "gr_streams_encode_turbo: setup:\n"
101 "d_n_encoders = " << d_n_encoders << "\n"
102 "n_code_inputs = " << n_code_inputs << "\n"
103 "n_code_outputs = " << n_code_outputs << "\n\n"
104 "Individual Encoders:\n";
106 for (size_t m = 0; m < d_n_encoders; m++) {
107 t_ec = encoders[m]->encoder ();
108 std::cout << " [" << (m+1) << "]:\n"
109 "n_code_inputs = " << (t_ec->n_code_inputs()) << "\n"
110 "n_code_outputs = " << (t_ec->n_code_outputs()) << "\n"
111 "block_size_bits = " << (t_ec->block_size_bits()) << "\n"
112 "do_termination = " <<
113 ((t_ec->do_termination()==true)?"true":"false") << "\n";
119 if (d_n_encoders != (interleavers.size())) {}
121 d_encoder = new encoder_turbo_ic1_ic1 (n_code_inputs,
129 // create the correct input signature; 1 bit per input char
131 set_input_signature (gr_make_io_signature (n_code_inputs,
135 // create the correct output signature; 1 bit per output char
137 set_output_signature (gr_make_io_signature (n_code_outputs,
141 // set the output multiple to 1 item, then let the encoder class
142 // handle the rest internally
144 set_output_multiple (1);
147 gr_streams_encode_turbo::~gr_streams_encode_turbo
155 * Compute the number of input bits (items in this case, since each
156 * item has 1 bit in it) needed to produce 'n_output' bits (items in
157 * this case, since each item has 1 bit in it).
159 * For turbo encoders, there is 1 bit output per bit input per
160 * stream, with the addition of a some bits for trellis termination if
161 * selected. Thus the input:output bit ratio will be:
163 * if (streaming | no termination), 1:1
165 * if (not streaming & termination), roughly 1:(1+X), where "X" is the
166 * total memory size of the code divided by the block length in bits.
167 * But this also depends on the state of the FSM ... how many bits are
168 * left before termination.
171 void gr_streams_encode_turbo::forecast
173 gr_vector_int &ninput_items_required)
175 int ninput_items = d_encoder->compute_n_input_bits (noutput_items);
176 size_t ninputs = ninput_items_required.size();
177 for (size_t n = 0; n < ninputs; n++)
178 ninput_items_required[n] = ninput_items;
182 gr_streams_encode_turbo::general_work
184 gr_vector_int &ninput_items,
185 gr_vector_const_void_star &input_items,
186 gr_vector_void_star &output_items)
188 // FIXME: compute the actual number of output items (1 bit char's) created.
190 size_t t_n_input_items = d_encoder->compute_n_input_bits (noutput_items);
191 size_t t_n_output_items = d_encoder->compute_n_output_bits (t_n_input_items);
193 assert (t_n_output_items == ((size_t)noutput_items));
195 // "work" is handled by the encoder; which returns the actual number
196 // of input items (1-bit char's) used.
198 t_n_input_items = d_encoder->encode ((const char **)(&input_items[0]),
199 (char **)(&output_items[0]),
200 (size_t) noutput_items);
202 // consume the number of used input items on all input streams
204 consume_each (t_n_input_items);
206 // returns number of items written to each output stream
208 return (noutput_items);