Houston, we have a trunk.
[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., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, 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 /* for remote access to internal info */
130
131   inline const bool do_termination () {return (d_do_termination);};
132   inline const bool do_feedback () {return (d_trellis->do_feedback());};
133   inline const bool do_streaming () {return (d_do_streaming);};
134   inline const size_t total_n_delays () {return (d_total_n_delays);};
135
136 protected:
137 /*
138  * fsm_enc_conv_t: finite state machine for the convolutional encoder;
139  *     output happens all the time, so that's built-in to each state.
140  *
141  * fsm_enc_conv_init: initialize for a new block / block; this is already
142  *     done at instantiation, so do it only at the end of a block.
143  *
144  * fsm_enc_conv_doing_input: doing encoding inside the trellis
145  *
146  * fsm_enc_conv_doing_term: termination trellis, if requested
147  */
148
149   enum fsm_enc_conv_t {
150     fsm_enc_conv_init, fsm_enc_conv_doing_input, fsm_enc_conv_doing_term
151   };
152
153   // methods defined in this class
154
155   void encoder_convolutional_init (int block_size_bits,
156                                    int n_code_inputs,
157                                    int n_code_outputs,
158                                    const std::vector<int>& code_generators,
159                                    const std::vector<int>* code_generators,
160                                    bool do_termination,
161                                    int start_memory_state,
162                                    int end_memory_state);
163
164   virtual void encode_private (const char** in_buf, char** out_buf);
165
166   virtual void encode_loop (const char** in_buf, char** out_buf,
167                             size_t* which_counter, size_t how_many);
168
169   inline void get_next_inputs (const char** in_buf) {
170     switch (d_fsm_state) {
171     case fsm_enc_conv_doing_input:
172       get_next_inputs__input (in_buf);
173       break;
174     case fsm_enc_conv_doing_term:
175       get_next_inputs__term ();
176       break;
177     default:
178       assert (0);
179       break;
180     }
181   };
182
183   virtual void get_next_inputs__term ();
184
185   void get_memory_requirements (size_t m,
186                                 size_t n,
187                                 size_t& t_max_mem,
188                                 size_t& t_n_unique_fb_prev_start,
189                                 const std::vector<int>* code_feedback);
190
191   // methods which are required by classes which inherit from this
192   // one; primarily just the parts which deal with getting input bits
193   // and writing output bits, changing the indices for those buffers.
194
195   virtual void write_output_bits (char** out_buf) = 0;
196   virtual void get_next_inputs__input (const char** in_buf) = 0;
197
198   // variables
199
200   fsm_enc_conv_t d_fsm_state;
201   bool d_do_streaming, d_do_termination;
202
203   // "total_n_delays" is the total # of delays, needed to determine the
204   // # of states in the decoder
205
206   size_t d_total_n_delays;
207
208   // the current state of the encoder (all delays / memories)
209
210   memory_t d_memory;
211
212   // "inputs" are the current input bits, in the LSB (&1) of each "char"
213
214   std::vector<char> d_current_inputs;
215
216   // "outputs" are the current output bits, in the LSB (&1) of each "char"
217
218   std::vector<char> d_current_outputs;
219
220   // "trellis" is the code trellis for the given input parameters
221
222   code_convolutional_trellis* d_trellis;
223
224   // "init_states" are the user-provided init states,
225   // interpreted w/r.t. the actual trellis;
226
227   memory_t d_init_state;
228 };
229
230 #endif /* INCLUDED_ENCODER_CONVOLUTIONAL_H */