summaryrefslogtreecommitdiffstats
path: root/include/osmocom/core/conv.h
blob: e7f6bd6ac5a210f90c9c52ab3efeea2de2f1c1cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
 * conv.h
 *
 * Copyright (C) 2011  Sylvain Munaut <tnt@246tNt.com>
 *
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

/*! \defgroup conv Convolutional encoding and decoding routines
 *  @{
 */

/*! \file conv.h
 * Osmocom convolutional encoder and decoder
 */

#pragma once

#include <stdint.h>

#include <osmocom/core/bits.h>

/*! \brief possibe termination types
 *
 *  The termination type will determine which state the encoder/decoder
 *  can start/end with. This is mostly taken care of in the high level API
 *  call. So if you use the low level API, you must take care of making the
 *  proper calls yourself.
 */
enum osmo_conv_term {
	CONV_TERM_FLUSH = 0,	/*!< \brief Flush encoder state */
	CONV_TERM_TRUNCATION,	/*!< \brief Direct truncation */
	CONV_TERM_TAIL_BITING,	/*!< \brief Tail biting */
};

/*! \brief structure describing a given convolutional code
 *
 *  The only required fields are N,K and the next_output/next_state arrays. The
 *  other can be left to default value of zero depending on what the code does.
 *  If 'len' is left at 0 then only the low level API can be used.
 */
struct osmo_conv_code {
	int N;				/*!< \brief Inverse of code rate */
	int K;				/*!< \brief Constraint length */
	int len;			/*!< \brief # of data bits */

	enum osmo_conv_term term;	/*!< \brief Termination type */

	const uint8_t (*next_output)[2];/*!< \brief Next output array */
	const uint8_t (*next_state)[2];	/*!< \brief Next state array  */

	const uint8_t *next_term_output;/*!< \brief Flush termination output */
	const uint8_t *next_term_state;	/*!< \brief Flush termination state  */

	const int *puncture;		/*!< \brief Punctured bits indexes */
};


/* Common */

int osmo_conv_get_input_length(const struct osmo_conv_code *code, int len);
int osmo_conv_get_output_length(const struct osmo_conv_code *code, int len);


/* Encoding */

	/* Low level API */

/*! \brief convolutional encoder state */
struct osmo_conv_encoder {
	const struct osmo_conv_code *code; /*!< \brief for which code? */
	int i_idx;	/*!< \brief Next input bit index */
	int p_idx;	/*!< \brief Current puncture index */
	uint8_t state;	/*!< \brief Current state */
};

void osmo_conv_encode_init(struct osmo_conv_encoder *encoder,
                           const struct osmo_conv_code *code);
void osmo_conv_encode_load_state(struct osmo_conv_encoder *encoder,
                                 const ubit_t *input);
int  osmo_conv_encode_raw(struct osmo_conv_encoder *encoder,
                          const ubit_t *input, ubit_t *output, int n);
int  osmo_conv_encode_flush(struct osmo_conv_encoder *encoder, ubit_t *output);

	/* All-in-one */
int  osmo_conv_encode(const struct osmo_conv_code *code,
                      const ubit_t *input, ubit_t *output);


/* Decoding */

	/* Low level API */

/*! \brief convolutional decoder state */
struct osmo_conv_decoder {
	const struct osmo_conv_code *code; /*!< \brief for which code? */

	int n_states;		/*!< \brief number of states */

	int len;		/*!< \brief Max o_idx (excl. termination) */

	int o_idx;		/*!< \brief output index */
	int p_idx;		/*!< \brief puncture index */

	unsigned int *ae;	/*!< \brief accumulated error */
	unsigned int *ae_next;	/*!< \brief next accumulated error (tmp in scan) */
	uint8_t *state_history;	/*!< \brief state history [len][n_states] */
};

void osmo_conv_decode_init(struct osmo_conv_decoder *decoder,
                           const struct osmo_conv_code *code,
                           int len, int start_state);
void osmo_conv_decode_reset(struct osmo_conv_decoder *decoder, int start_state);
void osmo_conv_decode_rewind(struct osmo_conv_decoder *decoder);
void osmo_conv_decode_deinit(struct osmo_conv_decoder *decoder);

int osmo_conv_decode_scan(struct osmo_conv_decoder *decoder,
                          const sbit_t *input, int n);
int osmo_conv_decode_flush(struct osmo_conv_decoder *decoder,
                           const sbit_t *input);
int osmo_conv_decode_get_output(struct osmo_conv_decoder *decoder,
                                ubit_t *output, int has_flush, int end_state);

	/* All-in-one */
int osmo_conv_decode(const struct osmo_conv_code *code,
                     const sbit_t *input, ubit_t *output);


/*! @} */