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., 51 Franklin Street,
20 * Boston, MA 02110-1301, USA.
23 #ifndef INCLUDED_CODE_CONVOLUTIONAL_TRELLIS_H
24 #define INCLUDED_CODE_CONVOLUTIONAL_TRELLIS_H
26 #include "code_types.h"
30 * connection_t: describes an output connection from the current
31 * time-bit memory state to the next time-bit memory state
33 * d_to_state: memory configuration of the "to" state
35 * d_output_bits: the output bits for this connection, mux'ed
38 typedef struct connection_t {
40 memory_t d_output_bits;
41 } connection_t, *connection_t_ptr;
44 * trellis_t: describes a single set of trellis connections, from a
45 * time-bit to the next, forward transitions only
47 * This is a 2d "matrix", where the first dimention is the starting
48 * memory state, and the second is the (combined) input as an
49 * integer: e.g. for a 2 input code, if I1 = 0 and I2 = 1, then
50 * the combined input is the "number" found by appending I2 and I1
51 * together, in this case 10b = 3.
53 * The trellis is used to lookup information: given a starting state
54 * and inputs, return the output bits and next state.
57 typedef std::vector<std::vector<connection_t> > trellis_t, *trellis_t_ptr;
59 class code_convolutional_trellis
62 * class code_convolutional_trellis
64 * Create a convolutional code trellis structure, but encoding,
65 * decoding, determining termination transitions, and anything else
66 * which might be useful.
68 * block_size_bits: if == 0, then do streaming encoding ("infinite"
69 * trellis); otherwise this is the block size in bits to encode
70 * before terminating the trellis. This value -does not- include
71 * any termination bits.
75 * code_generator: vector of integers (32 bit) representing the code
76 * to be implemented. E.g. "4" in binary is "100", which would be
77 * "D^2" for code generation. "6" == 110b == "D^2 + D"
78 * ==> The vector is listed in order for each output stream, so if there
79 * are 2 input streams (I1, I2) [specified in "n_code_inputs"]
80 * and 2 output streams (O1, O2) [specified in "n_code_outputs"],
81 * then the vector would be the code generator for:
82 * [I1->O1, I2->O1, I1->O2, I2->O2]
83 * with each element being an integer representation of the code.
84 * The "octal" representation is used frequently in the literature
85 * (e.g. [015, 06] == [1101, 0110] in binary) due to its close
86 * relationship with binary (each number is 3 binary digits)
87 * ... but any integer representation will suffice.
89 * do_termination: valid only if block_size_bits != 0, and defines
90 * whether or not to use trellis termination. Default is to use
91 * termination when doing block coding.
93 * start_memory_state: when starting a new block, the starting memory
94 * state to begin encoding; there will be a helper function to
95 * assist in creating this value for a given set of inputs;
96 * default is the "all zero" state.
98 * end_memory_state: when terminating a block, the ending memory
99 * state to stop encoding; there will be a helper function to
100 * assist in creating this value for a given set of inputs;
101 * default is the "all zero" state.
105 inline code_convolutional_trellis
106 (int block_size_bits,
109 const std::vector<int> &code_generators,
110 bool do_termination = true,
111 int end_memory_state = 0)
112 {code_convolutional_trellis_init (block_size_bits,
121 * Encoder with feedback.
123 * code_feedback: vector of integers (32 bit) representing the code
124 * feedback to be implemented (same as for the code_generator).
125 * For this feedback type, the LSB ("& 1") is ignored (set to "1"
126 * internally, since it's always 1) ... this (effectively)
127 * represents the input bit for the given encoder, without which
128 * there would be no encoding! Each successive higher-order bit
129 * represents the output of that delay block; for example "6" ==
130 * 110b == "D^2 + D" means use the current input bit + the output
131 * of the second delay block. Listing order is the same as for
132 * the code_generator.
135 inline code_convolutional_trellis
136 (int block_size_bits,
139 const std::vector<int> &code_generators,
140 const std::vector<int> &code_feedback,
141 bool do_termination = true,
142 int end_memory_state = 0)
143 {code_convolutional_trellis_init (block_size_bits,
151 virtual ~code_convolutional_trellis () {};
153 /* for remote access to internal info */
155 inline const size_t block_size_bits () {return (d_block_size_bits);};
156 inline const size_t n_code_inputs () {return (d_n_code_inputs);};
157 inline const size_t n_code_outputs () {return (d_n_code_outputs);};
158 inline const size_t n_states () {return (d_n_states);};
159 inline const size_t n_input_combinations ()
160 {return (d_n_input_combinations);};
161 inline const bool do_termination () {return (d_do_termination);};
162 inline const bool do_feedback () {return (d_do_feedback);};
163 inline const bool do_streaming () {return (d_do_streaming);};
164 inline const bool do_encode_soai () {return (d_do_encode_soai);};
165 inline const size_t total_n_delays () {return (d_total_n_delays);};
166 inline const size_t n_bits_to_term () {return (d_n_bits_to_term);};
168 virtual char sum_bits_mod2 (memory_t in_mem, size_t max_memory);
169 void get_termination_inputs (memory_t term_start_state,
171 std::vector<char>& inputs) {
172 // no error checking ... be careful!
173 for (size_t m = 0; m < d_n_code_inputs; m++) {
174 inputs[m] = ((d_term_inputs[term_start_state][m]) >> bit_num) & 1;
178 // encode_lookup: given the starting state and inputs, return the
179 // resulting state and output bits. Two versions: the first is
180 // better for decoding, while the second is better for encoding.
182 void encode_lookup (memory_t& state,
183 const std::vector<char>& inputs,
185 void encode_lookup (memory_t& state,
186 const std::vector<char>& inputs,
187 std::vector<char>& out_bits);
189 // methods for setting and retrieving the state, inputs, and outputs.
191 void demux_state (memory_t in_state, std::vector<memory_t>& memories);
192 memory_t mux_state (const std::vector<memory_t>& memories);
193 void demux_inputs (memory_t inputs, std::vector<char>& in_vec);
194 memory_t mux_inputs (const std::vector<char>& in_vec);
195 void demux_outputs (memory_t outputs, std::vector<char>& out_vec);
196 memory_t mux_outputs (const std::vector<char>& out_vec);
201 * state_get_from(v,i,k): use to retrieve a given bit-memory state,
204 * memory_t v: the value from which to retrieve the given state
205 * size_t i: for which input stream (0 to #I-1)
206 * size_t k: the number of memory slots per input (e.g. 1+D^2 -> 2)
209 inline memory_t state_get_from (memory_t v,
212 {return (((v)>>((i)*(k)))&((1<<(k))-1));};
215 * state_add_to(s,v,i,k): use to create a given bit-memory state,
218 * memory_t s: the state value to modify
219 * memory_t v: value to set the state to for this input
220 * size_t i: for which input stream (0 to #I-1)
221 * size_t k: the number of memory slots per input (e.g. 1+D^2 -> 2)
224 inline void state_add_to (memory_t s,
228 {(s)|=(((v)&((1<<(k))-1))<<((i)*(k)));};
232 * maio(i,o): matrix access into a vector, knowing the # of code
233 * outputs (from inside the class). References into a vector with
234 * code inputs ordered by code output.
236 * 'i' is the 1st dimension - faster memory - the code input
237 * 'o' is the 2nd dimension - slower memory - the code output
239 * returns ((o*n_code_inputs) + i)
242 inline size_t maio(size_t i, size_t o) {return ((o*d_n_code_inputs) + i);};
245 * maoi(i,o): matrix access into a vector, knowing the # of code
246 * inputs (from inside the class). References into a vector with
247 * code outputs ordered by code input.
249 * 'o' is the 1st dimension - faster memory - the code output
250 * 'i' is the 2nd dimension - slower memory - the code input
252 * returns ((i*n_code_outputs) + o)
255 inline size_t maoi(size_t i, size_t o) {return ((i*d_n_code_outputs) + o);};
258 * max_bit_position (x): returns the bit-number of the highest "1" bit
259 * in the provided value, such that the LSB would return 0 and the MSB
260 * of a long would return 31.
263 inline size_t max_bit_position (memory_t x)
265 size_t t_code_mem = 0;
266 memory_t t_in_code = x >> 1;
267 while (t_in_code != 0) {
275 // methods defined in this class
277 void code_convolutional_trellis_init
278 (int block_size_bits,
281 const std::vector<int>& code_generators,
282 const std::vector<int>* code_generators,
284 int end_memory_state);
286 void create_trellis ();
287 void create_termination_table (memory_t end_memory_state);
288 void encode_single (memory_t in_state,
292 virtual void encode_single_soai ();
293 virtual void encode_single_siao ();
294 virtual void encode_single_soai_fb ();
295 virtual void encode_single_siao_fb ();
297 void get_memory_requirements (size_t m,
300 size_t& t_n_unique_fb_prev_start,
301 const std::vector<int>* code_feedback);
305 size_t d_block_size_bits, d_n_code_outputs;
306 size_t d_n_code_inputs, d_n_input_combinations;
307 bool d_do_streaming, d_do_termination, d_do_feedback, d_do_encode_soai;
309 // "max_delay" is the max # of delays for all unique generators (ff and fb),
313 // "n_memories" is the number of unique memories as determined by
314 // either the feedforward or feedback generators (not both). For
315 // FF, this number equals either the number of code inputs (for
316 // SIAO) or outputs (for SOAI).
320 // "total_n_delays" is the total # of delays, needed to determine the
321 // # of states in the decoder
322 // "n_states" = (2^total_n_delays) - 1 .. the number of memory states
324 size_t d_total_n_delays, d_n_states;
326 // "code generators" are stored internally in "maXY(i,o)" order this
327 // allows for looping over all a single output and computing all
328 // input parts sequentially.
330 std::vector<memory_t> d_code_generators;
332 // "feedback" are found as "d_n_memories" unique entries, and stored
333 // in at most 1 entry per I/O combination. Listed in the same order
334 // as "d_io_num" entries show.
336 std::vector<memory_t> d_code_feedback;
338 // "n_delays" is a vector, the number of delays for the FB generator
339 // in the same [] location; also relates directly to the
340 // "max_mem_masks" in the same [] location.
342 std::vector<size_t> d_n_delays;
344 // "io_num" is a vector, mapping which FB in SIAO goes with which
345 // input, or which FB in SOAI goes with which output
347 std::vector<size_t> d_io_num;
349 // "max_mem_masks" are the memory masks, one per unique FB for SIAO;
350 // otherwise not used.
352 std::vector<size_t> d_states_ndx;
354 // "memory" are the actual stored delay bits, one memory for each
355 // unique FF or FB code generator;
356 // interpreted w/r.t. the actual FF and FB code generators and
357 // SOAI / SIAO realization;
359 std::vector<memory_t> d_max_mem_masks;
361 // "states_ndx" is a "matrix" whose contents are the indices into
362 // the "io_num" vector, telling which input goes with which
363 // state; uses the same "maXY(i,o)" as the code generators.
365 std::vector<memory_t> d_memory;
367 // "term_inputs" are the inputs required to terminate the trellis -
368 // interpreted w/r.t. the actual FF and FB code generators and
369 // SOAI / SIAO realization;
370 // first dimension is the memory state #;
371 // second dimension is the input stream #;
372 // bits are packed, with the first input being the LSB and the last
373 // input being farthest away from the LSB.
375 typedef std::vector<std::vector<memory_t> > term_input_t;
376 term_input_t d_term_inputs;
378 // "n_bits_to_term" is the number of bits to terminate the trellis
379 // to the desired state, as determined by the termination table.
380 // d_max_delay <= d_n_bits_to_term <= d_total_n_delays
381 // These numbers will vary depending on the realization.
383 size_t d_n_bits_to_term;
385 // "inputs" are the current input bits, in the LSB (&1) of each "char"
387 std::vector<char> d_current_inputs;
389 // "outputs" are the current output bits, in the LSB (&1) of each "char"
391 std::vector<char> d_current_outputs;
393 // "ind_outputs" are the current output bits, in the LSB (&1) of
394 // each "char", for each individual memory's computations; needed
395 // for soai-type feedback only
397 std::vector<char> d_ind_outputs;
399 // "trellis" is the single-stage memory state transition ("trellis")
400 // representation for this code; forward paths only
405 #endif /* INCLUDED_CODE_CONVOLUTIONAL_TRELLIS_H */