Line data Source code
1 : /*
2 : * libpoporon - encode.c
3 : *
4 : * This file is part of libpoporon.
5 : *
6 : * Author: Brian Armstrong (original, libcorrect)
7 : * SPDX-License-Identifier: BSD-3-Clause
8 : */
9 :
10 : #include "internal/common.h"
11 : #include "internal/ldpc.h"
12 : #include "internal/polynomial.h"
13 : #include "internal/rs.h"
14 :
15 : #if POPORON_USE_SIMD
16 : #include "internal/simd.h"
17 : #endif
18 :
19 7 : static bool rs_encode(poporon_t *pprn, uint8_t *data, size_t size, uint8_t *parity)
20 : {
21 7 : poporon_rs_t *rs = pprn->ctx.rs.rs;
22 : size_t pad_length;
23 : uint32_t i;
24 :
25 7 : if (size > (size_t)rs->message_length) {
26 0 : return false;
27 : }
28 :
29 7 : pad_length = (size_t)rs->message_length - size;
30 :
31 7 : pmemset(rs->encoded_polynomial.coeff, 0, (rs->encoded_polynomial.order + 1) * sizeof(uint16_t));
32 :
33 455 : for (i = 0; i < size; i++) {
34 448 : rs->encoded_polynomial.coeff[rs->encoded_polynomial.order - (i + pad_length)] = data[i] & rs->gf->field_size;
35 : }
36 :
37 7 : polynomial_mod(rs->gf, rs->encoded_polynomial, rs->generator, rs->encoded_remainder);
38 :
39 231 : for (i = 0; i < rs->num_roots; i++) {
40 224 : parity[i] = (uint8_t)rs->encoded_remainder.coeff[rs->num_roots - 1 - i];
41 : }
42 :
43 7 : return true;
44 : }
45 :
46 11 : static bool ldpc_encode(poporon_t *pprn, uint8_t *data, size_t size, uint8_t *parity)
47 : {
48 11 : poporon_ldpc_t *ldpc = pprn->ctx.ldpc.ldpc;
49 : uint8_t *outer_buf, *codeword, *interleaved, *encode_input;
50 : size_t i;
51 :
52 11 : if (size != ldpc->info_bytes) {
53 0 : return false;
54 : }
55 :
56 11 : if (ldpc->config.use_outer_interleave && ldpc->outer_interleaver.forward) {
57 7 : outer_buf = ldpc->temp_outer;
58 7 : if (!outer_buf) {
59 0 : return false;
60 : }
61 :
62 7 : pmemset(outer_buf, 0, ldpc->info_bytes);
63 :
64 775 : for (i = 0; i < ldpc->info_bytes; i++) {
65 768 : outer_buf[ldpc->outer_interleaver.forward[i]] = data[i];
66 : }
67 :
68 7 : pmemcpy(data, outer_buf, ldpc->info_bytes);
69 7 : encode_input = data;
70 : } else {
71 4 : encode_input = data;
72 : }
73 :
74 11 : if (!poporon_ldpc_encode(ldpc, encode_input, parity)) {
75 0 : return false;
76 : }
77 :
78 11 : if (ldpc->config.use_inner_interleave && ldpc->interleaver.forward) {
79 7 : codeword = ldpc->temp_codeword;
80 7 : pmemcpy(codeword, encode_input, ldpc->info_bytes);
81 7 : pmemcpy(codeword + ldpc->info_bytes, parity, ldpc->parity_bytes);
82 :
83 7 : interleaved = ldpc->temp_interleaved;
84 7 : if (!interleaved) {
85 0 : return false;
86 : }
87 :
88 7 : poporon_ldpc_interleave(ldpc, codeword, interleaved);
89 :
90 7 : pmemcpy(data, interleaved, ldpc->info_bytes);
91 7 : pmemcpy(parity, interleaved + ldpc->info_bytes, ldpc->parity_bytes);
92 : }
93 :
94 11 : return true;
95 : }
96 :
97 1 : static bool bch_encode(poporon_t *pprn, uint8_t *data, size_t size, uint8_t *parity)
98 : {
99 1 : poporon_bch_t *bch = pprn->ctx.bch.bch;
100 1 : uint32_t data_val = 0, codeword = 0, parity_val;
101 : uint16_t i, data_len, codeword_len, parity_bits, data_bytes, parity_bytes;
102 :
103 1 : data_len = poporon_bch_get_data_length(bch);
104 1 : codeword_len = poporon_bch_get_codeword_length(bch);
105 1 : parity_bits = codeword_len - data_len;
106 1 : data_bytes = (data_len + 7) / 8;
107 1 : parity_bytes = (parity_bits + 7) / 8;
108 :
109 1 : if (size < data_bytes) {
110 0 : return false;
111 : }
112 :
113 2 : for (i = 0; i < data_bytes && i < 4; i++) {
114 1 : data_val |= ((uint32_t)data[i]) << (8 * (data_bytes - 1 - i));
115 : }
116 :
117 1 : if (data_len < 32) {
118 1 : data_val &= ((uint32_t)1 << data_len) - 1;
119 : }
120 :
121 1 : if (!poporon_bch_encode(bch, data_val, &codeword)) {
122 0 : return false;
123 : }
124 :
125 1 : parity_val = codeword & (((uint32_t)1 << parity_bits) - 1);
126 1 : pmemset(parity, 0, parity_bytes);
127 3 : for (i = 0; i < parity_bytes && i < 4; i++) {
128 2 : parity[parity_bytes - 1 - i] = (uint8_t)(parity_val >> (8 * i));
129 : }
130 :
131 1 : return true;
132 : }
133 :
134 24 : extern bool poporon_encode(poporon_t *pprn, uint8_t *data, size_t size, uint8_t *parity)
135 : {
136 24 : if (!pprn || !data || !parity) {
137 5 : return false;
138 : }
139 :
140 19 : switch (pprn->fec_type) {
141 7 : case PPLN_FEC_RS:
142 7 : return rs_encode(pprn, data, size, parity);
143 11 : case PPLN_FEC_LDPC:
144 11 : return ldpc_encode(pprn, data, size, parity);
145 1 : case PPLN_FEC_BCH:
146 1 : return bch_encode(pprn, data, size, parity);
147 0 : default:
148 0 : return false;
149 : }
150 : }
|