Updated FSF address in all files. Fixes ticket:51
[debian/gnuradio] / gr-error-correcting-codes / src / lib / libecc / encoder_convolutional.h
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., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #ifndef INCLUDED_ENCODER_CONVOLUTIONAL_H
24 #define INCLUDED_ENCODER_CONVOLUTIONAL_H
25
26 #include "encoder.h"
27 #include "code_convolutional_trellis.h"
28
29 class encoder_convolutional : public encoder
30 {
31 /*!
32  * class encoder_convolutional : public encoder
33  *
34  * Encode the incoming streams using a convolutional encoder; This is
35  *     a virtual class which defines the basics of a convolutional
36  *     encoder, but not how input and output bits are handled, nor
37  *     feedback in the encoder.  These features are all defined by
38  *     overriding methods appropriately.
39  *
40  * block_size_bits: if == 0, then do streaming encoding ("infinite"
41  *     trellis); otherwise this is the block size in bits to encode
42  *     before terminating the trellis.  This value -does not- include
43  *     any termination bits.
44  *
45  * n_code_inputs:
46  * n_code_outputs:
47  * code_generator: vector of integers (32 bit) representing the code
48  *     to be implemented.  E.g. "4" in binary is "100", which would be
49  *     "D^2" for code generation.  "6" == 110b == "D^2 + D"
50  *  ==> The vector is listed in order for each output stream, so if there
51  *     are 2 input streams (I1, I2) [specified in "n_code_inputs"]
52  *     and 2 output streams (O1, O2) [specified in "n_code_outputs"],
53  *     then the vector would be the code generator for:
54  *       [I1->O1, I2->O1, I1->O2, I2->O2]
55  *     with each element being an integer representation of the code.
56  *     The "octal" representation is used frequently in the literature
57  *     (e.g. [015, 06] == [1101, 0110] in binary) due to its close
58  *     relationship with binary (each number is 3 binary digits)
59  *     ... but any integer representation will suffice.
60  *
61  * do_termination: valid only if block_size_bits != 0, and defines
62  *     whether or not to use trellis termination.  Default is to use
63  *     termination when doing block coding.
64  *
65  * start_memory_state: when starting a new block, the starting memory
66  *     state to begin encoding; there will be a helper function to
67  *     assist in creating this value for a given set of inputs;
68  *     default is the "all zero" state.
69  * 
70  * end_memory_state: when terminating a block, the ending memory
71  *     state to stop encoding; there will be a helper function to
72  *     assist in creating this value for a given set of inputs;
73  *     default is the "all zero" state.
74  */
75
76 public:
77   inline encoder_convolutional
78   (int block_size_bits,
79    int n_code_inputs,
80    int n_code_outputs,
81    const std::vector<int> &code_generators,
82    bool do_termination = true,
83    int start_memory_state = 0,
84    int end_memory_state = 0)
85   {encoder_convolutional_init (block_size_bits,
86                                n_code_inputs,
87                                n_code_outputs,
88                                code_generators,
89                                0,
90                                do_termination,
91                                start_memory_state,
92                                end_memory_state);};
93
94 /*!
95  * Encoder with feedback.
96  *
97  * code_feedback: vector of integers (32 bit) representing the code
98  *     feedback to be implemented (same as for the code_generator).
99  *     For this feedback type, the LSB ("& 1") is ignored (set to "1"
100  *     internally, since it's always 1) ... this (effectively)
101  *     represents the input bit for the given encoder, without which
102  *     there would be no encoding!  Each successive higher-order bit
103  *     represents the output of that delay block; for example "6" ==
104  *     110b == "D^2 + D" means use the current input bit + the output
105  *     of the second delay block.  Listing order is the same as for
106  *     the code_generator.
107  */
108
109   inline encoder_convolutional
110   (int block_size_bits,
111    int n_code_inputs,
112    int n_code_outputs,
113    const std::vector<int>& code_generators,
114    const std::vector<int>& code_feedback,
115    bool do_termination = true,
116    int start_memory_state = 0,
117    int end_memory_state = 0)
118   {encoder_convolutional_init (block_size_bits,
119                                n_code_inputs,
120                                n_code_outputs,
121                                code_generators,
122                                &code_feedback,
123                                do_termination,
124                                start_memory_state,
125                                end_memory_state);};
126
127   virtual ~encoder_convolutional () {delete d_trellis;};
128
129 /*
130  * Compute the number of input bits needed to produce 'n_output' bits,
131  * and the number of output bits which will be produced by 'n_input'
132  * bits ... for a single stream only.
133  *
134  * For convolutional encoders, there is 1 bit output per bit input per
135  * stream, with the addition of a some bits for trellis termination if
136  * selected.  Thus the input:output bit ratio will be:
137  * 
138  * if (streaming | no termination), 1:1 exactly;
139  *
140  * if (not streaming & termination), depends on the state of the FSM,
141  * and needs to include the number of termination bits (the total # of
142  * delays); ratio is roughly (1:(1+X)), where "X" is the number of
143  * termination bits divided by the (unterminated) block length in bits.
144  *
145  * It's up to the caller to change 'bits' to 'items' ... to know if
146  * bits are packed (see e.g. code_io "ic8l") or not ("ic1l"), or all
147  * streams are mux'ed together into one stream.
148 */
149
150   virtual size_t compute_n_input_bits (size_t n_output_bits);
151   virtual size_t compute_n_output_bits (size_t n_input_bits);
152
153 /* for remote access to internal info */
154
155   inline const bool do_termination () {return (d_do_termination);};
156   inline const bool do_feedback () {return (d_trellis->do_feedback());};
157   inline const bool do_encode_soai () {return (d_trellis->do_encode_soai());};
158   inline const bool do_streaming () {return (d_do_streaming);};
159   inline const size_t total_n_delays () {return (d_total_n_delays);};
160   inline const size_t n_bits_to_term () {return (d_n_bits_to_term);};
161   inline const code_convolutional_trellis* trellis() {return (d_trellis);};
162
163 protected:
164 /*
165  * fsm_enc_conv_t: finite state machine for the convolutional encoder;
166  *     output happens all the time, so that's built-in to each state.
167  *
168  * fsm_enc_conv_init: initialize for a new block / block; this is already
169  *     done at instantiation, so do it only at the end of a block.
170  *
171  * fsm_enc_conv_doing_input: doing encoding inside the trellis
172  *
173  * fsm_enc_conv_doing_term: termination trellis, if requested
174  */
175
176   enum fsm_enc_conv_t {
177     fsm_enc_conv_init, fsm_enc_conv_doing_input, fsm_enc_conv_doing_term
178   };
179
180   // methods defined in this class
181
182   void encoder_convolutional_init (int block_size_bits,
183                                    int n_code_inputs,
184                                    int n_code_outputs,
185                                    const std::vector<int>& code_generators,
186                                    const std::vector<int>* code_generators,
187                                    bool do_termination,
188                                    int start_memory_state,
189                                    int end_memory_state);
190
191   virtual void encode_private ();
192   virtual void encode_loop (size_t& which_counter, size_t how_many);
193
194   inline void get_next_inputs () {
195     switch (d_fsm_state) {
196     case fsm_enc_conv_doing_input:
197       get_next_inputs__input ();
198       break;
199     case fsm_enc_conv_doing_term:
200       get_next_inputs__term ();
201       break;
202     default:
203       assert (0);
204       break;
205     }
206   };
207
208   inline virtual void get_next_inputs__input () {
209     d_in_buf->read_items ((void*)(&(d_current_inputs[0])));
210     d_in_buf->increment_indices ();
211     d_n_bits_to_input--;
212   };
213
214   inline virtual void get_next_inputs__term () {
215     d_trellis->get_termination_inputs (d_term_state,
216                                        d_n_enc_bits,
217                                        d_current_inputs);
218   };
219
220   inline virtual void write_output_bits () {
221     d_out_buf->write_items ((const void*)(&(d_current_outputs[0])));
222     d_out_buf->increment_indices ();
223     d_n_bits_to_output--;
224   };
225
226   void get_memory_requirements (size_t m,
227                                 size_t n,
228                                 size_t& t_max_mem,
229                                 size_t& t_n_unique_fb_prev_start,
230                                 const std::vector<int>* code_feedback);
231
232   // variables
233
234   fsm_enc_conv_t d_fsm_state;
235   bool d_do_streaming, d_do_termination;
236
237   // "total_n_delays" is the total # of delays, needed to determine the
238   // # of states in the decoder
239
240   size_t d_total_n_delays, d_n_enc_bits;
241
242   // the current state of the encoder (all delays / memories)
243
244   memory_t d_memory;
245
246   // "inputs" are the current input bits, in the LSB (&1) of each "char"
247
248   std::vector<char> d_current_inputs;
249
250   // "outputs" are the current output bits, in the LSB (&1) of each "char"
251
252   std::vector<char> d_current_outputs;
253
254   // "n_bits_to_term" is the number of bits to terminate the trellis
255   // to the desired state, as determined by the termination table.
256   //    d_max_delay <= d_n_bits_to_term <= d_total_n_delays
257   // These numbers will vary depending on the realization.
258
259   size_t d_n_bits_to_term;
260
261   // "trellis" is the code trellis for the given input parameters
262
263   code_convolutional_trellis* d_trellis;
264
265   // "init_states" are the user-provided init states,
266   // interpreted w/r.t. the actual trellis;
267
268   memory_t d_init_state;
269
270   // "term_state" is the ending state before termination, used by the
271   // trellis to determine the correct input-bit sequences needed to
272   // properly terminate the trellis to the desired end-state;
273   // used only if doing termination.
274
275   memory_t d_term_state;
276 };
277
278 #endif /* INCLUDED_ENCODER_CONVOLUTIONAL_H */