Line data Source code
1 : /*
2 : * libpoporon - poporon.c
3 : *
4 : * This file is part of libpoporon.
5 : *
6 : * SPDX-License-Identifier: BSD-3-Clause
7 : */
8 :
9 : #include <poporon.h>
10 :
11 : #include "internal/common.h"
12 : #include "internal/config.h"
13 : #include "internal/ldpc.h"
14 : #include "internal/rs.h"
15 :
16 10 : static inline poporon_t *poporon_create_rs_internal(const poporon_config_t *cfg)
17 : {
18 : poporon_t *pprn;
19 : poporon_rs_t *rs;
20 :
21 10 : if (cfg->params.rs.primitive_element == 0) {
22 0 : return NULL;
23 : }
24 :
25 10 : rs = poporon_rs_create(cfg->params.rs.symbol_size, cfg->params.rs.generator_polynomial,
26 10 : cfg->params.rs.first_consecutive_root, cfg->params.rs.primitive_element,
27 10 : cfg->params.rs.num_roots);
28 10 : if (!rs) {
29 0 : return NULL;
30 : }
31 :
32 10 : pprn = (poporon_t *)pcalloc(1, sizeof(poporon_t));
33 10 : if (!pprn) {
34 0 : poporon_rs_destroy(rs);
35 0 : return NULL;
36 : }
37 :
38 10 : pprn->fec_type = PPLN_FEC_RS;
39 10 : pprn->ctx.rs.rs = rs;
40 10 : pprn->ctx.rs.erasure = cfg->params.rs.erasure;
41 10 : pprn->ctx.rs.ext_syndrome = cfg->params.rs.syndrome;
42 10 : pprn->ctx.rs.last_corrected = 0;
43 :
44 10 : return pprn;
45 : }
46 :
47 12 : static inline poporon_t *poporon_create_ldpc_internal(const poporon_config_t *cfg)
48 : {
49 : poporon_t *pprn;
50 : poporon_ldpc_params_t ldpc_params;
51 : poporon_ldpc_t *ldpc;
52 :
53 12 : ldpc_params.matrix_type = cfg->params.ldpc.matrix_type;
54 12 : ldpc_params.column_weight = cfg->params.ldpc.column_weight;
55 12 : ldpc_params.use_inner_interleave = cfg->params.ldpc.use_inner_interleave;
56 12 : ldpc_params.use_outer_interleave = cfg->params.ldpc.use_outer_interleave;
57 12 : ldpc_params.interleave_depth = cfg->params.ldpc.interleave_depth;
58 12 : ldpc_params.lifting_factor = cfg->params.ldpc.lifting_factor;
59 12 : ldpc_params.seed = cfg->params.ldpc.seed;
60 :
61 12 : ldpc = poporon_ldpc_create(cfg->params.ldpc.block_size, cfg->params.ldpc.rate, &ldpc_params);
62 12 : if (!ldpc) {
63 0 : return NULL;
64 : }
65 :
66 12 : pprn = (poporon_t *)pcalloc(1, sizeof(poporon_t));
67 12 : if (!pprn) {
68 0 : poporon_ldpc_destroy(ldpc);
69 0 : return NULL;
70 : }
71 :
72 12 : pprn->fec_type = PPLN_FEC_LDPC;
73 12 : pprn->ctx.ldpc.ldpc = ldpc;
74 12 : pprn->ctx.ldpc.soft_llr = cfg->params.ldpc.soft_llr;
75 12 : pprn->ctx.ldpc.soft_llr_size = cfg->params.ldpc.soft_llr_size;
76 12 : pprn->ctx.ldpc.use_soft_decode = cfg->params.ldpc.use_soft_decode;
77 12 : pprn->ctx.ldpc.max_iterations = cfg->params.ldpc.max_iterations;
78 12 : pprn->ctx.ldpc.last_iterations = 0;
79 :
80 12 : return pprn;
81 : }
82 :
83 2 : static inline poporon_t *poporon_create_bch_internal(const poporon_config_t *cfg)
84 : {
85 : poporon_t *pprn;
86 : poporon_bch_t *bch;
87 :
88 2 : bch = poporon_bch_create(cfg->params.bch.symbol_size, cfg->params.bch.generator_polynomial,
89 2 : cfg->params.bch.correction_capability);
90 2 : if (!bch) {
91 0 : return NULL;
92 : }
93 :
94 2 : pprn = (poporon_t *)pcalloc(1, sizeof(poporon_t));
95 2 : if (!pprn) {
96 0 : poporon_bch_destroy(bch);
97 0 : return NULL;
98 : }
99 :
100 2 : pprn->fec_type = PPLN_FEC_BCH;
101 2 : pprn->ctx.bch.bch = bch;
102 2 : pprn->ctx.bch.last_num_errors = 0;
103 :
104 2 : return pprn;
105 : }
106 :
107 26 : extern poporon_t *poporon_create(const poporon_config_t *config)
108 : {
109 26 : if (!config) {
110 2 : return NULL;
111 : }
112 :
113 24 : switch (config->fec_type) {
114 10 : case PPLN_FEC_RS:
115 10 : return poporon_create_rs_internal(config);
116 12 : case PPLN_FEC_LDPC:
117 12 : return poporon_create_ldpc_internal(config);
118 2 : case PPLN_FEC_BCH:
119 2 : return poporon_create_bch_internal(config);
120 0 : default:
121 0 : return NULL;
122 : }
123 : }
124 :
125 25 : extern void poporon_destroy(poporon_t *pprn)
126 : {
127 25 : if (!pprn) {
128 1 : return;
129 : }
130 :
131 24 : switch (pprn->fec_type) {
132 10 : case PPLN_FEC_RS:
133 10 : poporon_rs_destroy(pprn->ctx.rs.rs);
134 10 : break;
135 12 : case PPLN_FEC_LDPC:
136 12 : poporon_ldpc_destroy(pprn->ctx.ldpc.ldpc);
137 12 : break;
138 2 : case PPLN_FEC_BCH:
139 2 : poporon_bch_destroy(pprn->ctx.bch.bch);
140 2 : break;
141 0 : case PPLN_FEC_UNKNOWN:
142 : default:
143 0 : break;
144 : }
145 :
146 24 : pfree(pprn);
147 :
148 24 : return;
149 : }
150 :
151 10 : extern poporon_config_t *poporon_rs_config_create(uint8_t symbol_size, uint16_t generator_polynomial,
152 : uint16_t first_consecutive_root, uint16_t primitive_element,
153 : uint8_t num_roots, poporon_erasure_t *erasure, uint16_t *syndrome)
154 : {
155 10 : poporon_config_t *config = (poporon_config_t *)pcalloc(1, sizeof(poporon_config_t));
156 10 : if (!config) {
157 0 : return NULL;
158 : }
159 :
160 10 : config->fec_type = PPLN_FEC_RS;
161 10 : config->params.rs.symbol_size = symbol_size;
162 10 : config->params.rs.generator_polynomial = generator_polynomial;
163 10 : config->params.rs.first_consecutive_root = first_consecutive_root;
164 10 : config->params.rs.primitive_element = primitive_element;
165 10 : config->params.rs.num_roots = num_roots;
166 10 : config->params.rs.erasure = erasure;
167 10 : config->params.rs.syndrome = syndrome;
168 :
169 10 : return config;
170 : }
171 :
172 12 : extern poporon_config_t *poporon_ldpc_config_create(size_t block_size, poporon_ldpc_rate_t rate,
173 : poporon_ldpc_matrix_type_t matrix_type, uint32_t column_weight,
174 : bool use_soft_decode, bool use_outer_interleave,
175 : bool use_inner_interleave, uint32_t interleave_depth,
176 : uint32_t lifting_factor, uint32_t max_iterations,
177 : const int8_t *soft_llr, size_t soft_llr_size, uint64_t seed)
178 : {
179 12 : poporon_config_t *config = (poporon_config_t *)pcalloc(1, sizeof(poporon_config_t));
180 12 : if (!config) {
181 0 : return NULL;
182 : }
183 :
184 12 : config->fec_type = PPLN_FEC_LDPC;
185 12 : config->params.ldpc.block_size = block_size;
186 12 : config->params.ldpc.rate = rate;
187 12 : config->params.ldpc.matrix_type = matrix_type;
188 12 : config->params.ldpc.column_weight = column_weight;
189 12 : config->params.ldpc.use_soft_decode = use_soft_decode;
190 12 : config->params.ldpc.use_outer_interleave = use_outer_interleave;
191 12 : config->params.ldpc.use_inner_interleave = use_inner_interleave;
192 12 : config->params.ldpc.interleave_depth = interleave_depth;
193 12 : config->params.ldpc.lifting_factor = lifting_factor;
194 12 : config->params.ldpc.max_iterations = max_iterations;
195 12 : config->params.ldpc.soft_llr = soft_llr;
196 12 : config->params.ldpc.soft_llr_size = soft_llr_size;
197 12 : config->params.ldpc.seed = seed;
198 :
199 12 : return config;
200 : }
201 :
202 2 : extern poporon_config_t *poporon_bch_config_create(uint8_t symbol_size, uint16_t generator_polynomial,
203 : uint8_t correction_capability)
204 : {
205 2 : poporon_config_t *config = (poporon_config_t *)pcalloc(1, sizeof(poporon_config_t));
206 2 : if (!config) {
207 0 : return NULL;
208 : }
209 :
210 2 : config->fec_type = PPLN_FEC_BCH;
211 2 : config->params.bch.symbol_size = symbol_size;
212 2 : config->params.bch.generator_polynomial = generator_polynomial;
213 2 : config->params.bch.correction_capability = correction_capability;
214 :
215 2 : return config;
216 : }
217 :
218 5 : extern poporon_config_t *poporon_config_rs_default(void)
219 : {
220 5 : return poporon_rs_config_create(8, 0x11D, 1, 1, 32, NULL, NULL);
221 : }
222 :
223 5 : extern poporon_config_t *poporon_config_ldpc_default(size_t block_size, poporon_ldpc_rate_t rate)
224 : {
225 5 : return poporon_ldpc_config_create(block_size, rate, PPRN_LDPC_RANDOM, 3, true, true, true, 0, 0, 0, NULL, 0, 0);
226 : }
227 :
228 1 : extern poporon_config_t *poporon_config_ldpc_burst_resistant(size_t block_size, poporon_ldpc_rate_t rate)
229 : {
230 1 : return poporon_ldpc_config_create(block_size, rate, PPRN_LDPC_RANDOM, 7, true, true, true, 0, 0, 0, NULL, 0, 0);
231 : }
232 :
233 2 : extern poporon_config_t *poporon_config_bch_default(void)
234 : {
235 2 : return poporon_bch_config_create(4, 0x13, 3);
236 : }
237 :
238 24 : extern void poporon_config_destroy(poporon_config_t *config)
239 : {
240 24 : pfree(config);
241 24 : }
242 :
243 5 : extern poporon_fec_type_t poporon_get_fec_type(const poporon_t *pprn)
244 : {
245 5 : if (!pprn) {
246 0 : return PPLN_FEC_UNKNOWN;
247 : }
248 :
249 5 : return pprn->fec_type;
250 : }
251 :
252 1 : extern uint32_t poporon_get_iterations_used(const poporon_t *pprn)
253 : {
254 1 : if (!pprn || pprn->fec_type != PPLN_FEC_LDPC) {
255 0 : return 0;
256 : }
257 :
258 1 : return pprn->ctx.ldpc.last_iterations;
259 : }
260 :
261 12 : extern size_t poporon_get_parity_size(const poporon_t *pprn)
262 : {
263 : uint16_t cw, data;
264 :
265 12 : if (!pprn) {
266 0 : return 0;
267 : }
268 :
269 12 : switch (pprn->fec_type) {
270 1 : case PPLN_FEC_RS:
271 1 : return pprn->ctx.rs.rs->num_roots;
272 11 : case PPLN_FEC_LDPC:
273 11 : return poporon_ldpc_parity_size(pprn->ctx.ldpc.ldpc);
274 0 : case PPLN_FEC_BCH:
275 0 : cw = poporon_bch_get_codeword_length(pprn->ctx.bch.bch);
276 0 : data = poporon_bch_get_data_length(pprn->ctx.bch.bch);
277 0 : return (size_t)(cw - data + 7) / 8;
278 0 : default:
279 0 : return 0;
280 : }
281 : }
282 :
283 7 : extern size_t poporon_get_info_size(const poporon_t *pprn)
284 : {
285 7 : if (!pprn) {
286 1 : return 0;
287 : }
288 :
289 6 : switch (pprn->fec_type) {
290 2 : case PPLN_FEC_RS:
291 2 : return (size_t)(pprn->ctx.rs.rs->gf->field_size - pprn->ctx.rs.rs->num_roots);
292 2 : case PPLN_FEC_LDPC:
293 2 : return poporon_ldpc_info_size(pprn->ctx.ldpc.ldpc);
294 2 : case PPLN_FEC_BCH:
295 2 : return (size_t)(poporon_bch_get_data_length(pprn->ctx.bch.bch) + 7) / 8;
296 0 : default:
297 0 : return 0;
298 : }
299 : }
300 :
301 1 : extern uint32_t poporon_version_id(void)
302 : {
303 1 : return (uint32_t)POPORON_VERSION_ID;
304 : }
305 :
306 1 : extern poporon_buildtime_t poporon_buildtime(void)
307 : {
308 1 : return (poporon_buildtime_t)POPORON_BUILDTIME;
309 : }
|