13 #if !defined DEBUG && !defined __CC_ARM
25 template <
const uint8_t msg_length,
26 const uint8_t ecc_length>
31 const uint8_t enc_len = msg_length + ecc_length;
32 const uint8_t poly_len = ecc_length * 2;
33 uint8_t** memptr = &memory;
38 polynoms[0].Init(ID_MSG_IN, offset, enc_len, memptr);
41 polynoms[1].Init(ID_MSG_OUT, offset, enc_len, memptr);
44 for(uint8_t i = ID_GENERATOR; i < ID_MSG_E; i++) {
45 polynoms[i].Init(i, offset, poly_len, memptr);
49 polynoms[5].Init(ID_MSG_E, offset, enc_len, memptr);
52 for(uint8_t i = ID_TPOLY3; i < ID_ERR_EVAL+2; i++) {
53 polynoms[i].Init(i, offset, poly_len, memptr);
66 void EncodeBlock(
const void* src,
void* dst) {
67 assert(msg_length + ecc_length < 256);
70 static uint8_t generator_cache[ecc_length+1] = {0};
71 static bool generator_cached =
false;
74 uint8_t stack_memory[MSG_CNT * msg_length + POLY_CNT * ecc_length * 2];
75 this->memory = stack_memory;
77 const uint8_t* src_ptr = (
const uint8_t*) src;
78 uint8_t* dst_ptr = (uint8_t*) dst;
80 Poly *msg_in = &polynoms[ID_MSG_IN];
81 Poly *msg_out = &polynoms[ID_MSG_OUT];
82 Poly *gen = &polynoms[ID_GENERATOR];
89 if(generator_cached) {
90 gen->Set(generator_cache,
sizeof(generator_cache));
93 memcpy(generator_cache, gen->ptr(), gen->length);
94 generator_cached =
true;
98 msg_in->Set(src_ptr, msg_length);
99 msg_out->Set(src_ptr, msg_length);
100 msg_out->length = msg_in->length + ecc_length;
104 for(uint8_t i = 0; i < msg_length; i++){
105 coef = msg_out->at(i);
107 for(uint32_t j = 1; j < gen->length; j++){
108 msg_out->at(i+j) ^= gf::mul(gen->at(j), coef);
114 memcpy(dst_ptr, msg_out->ptr()+msg_length, ecc_length *
sizeof(uint8_t));
120 void Encode(
const void* src,
void* dst) {
121 uint8_t* dst_ptr = (uint8_t*) dst;
124 memcpy(dst_ptr, src, msg_length *
sizeof(uint8_t));
127 EncodeBlock(src, dst_ptr+msg_length);
137 int DecodeBlock(
const void* src,
const void* ecc,
void* dst, uint8_t* erase_pos = NULL,
size_t erase_count = 0) {
138 assert(msg_length + ecc_length < 256);
140 const uint8_t *src_ptr = (
const uint8_t*) src;
141 const uint8_t *ecc_ptr = (
const uint8_t*) ecc;
142 uint8_t *dst_ptr = (uint8_t*) dst;
144 const uint8_t src_len = msg_length + ecc_length;
145 const uint8_t dst_len = msg_length;
150 uint8_t stack_memory[MSG_CNT * msg_length + POLY_CNT * ecc_length * 2];
151 this->memory = stack_memory;
153 Poly *msg_in = &polynoms[ID_MSG_IN];
154 Poly *msg_out = &polynoms[ID_MSG_OUT];
155 Poly *epos = &polynoms[ID_ERASURES];
158 msg_in->Set(src_ptr, msg_length);
159 msg_in->Set(ecc_ptr, ecc_length, msg_length);
160 msg_out->Copy(msg_in);
163 if(erase_pos == NULL) {
166 epos->Set(erase_pos, erase_count);
167 for(uint8_t i = 0; i < epos->length; i++){
168 msg_in->at(epos->at(i)) = 0;
173 if(epos->length > ecc_length)
return 1;
175 Poly *synd = &polynoms[ID_SYNDROMES];
176 Poly *eloc = &polynoms[ID_ERRORS_LOC];
177 Poly *reloc = &polynoms[ID_TPOLY1];
178 Poly *err = &polynoms[ID_ERRORS];
179 Poly *forney = &polynoms[ID_FORNEY];
182 CalcSyndromes(msg_in);
185 bool has_errors =
false;
186 for(uint8_t i = 0; i < synd->length; i++) {
187 if(synd->at(i) != 0) {
194 if(!has_errors)
goto return_corrected_msg;
196 CalcForneySyndromes(synd, epos, src_len);
197 FindErrorLocator(forney, NULL, epos->length);
201 reloc->length = eloc->length;
202 for(int8_t i = eloc->length-1, j = 0; i >= 0; i--, j++){
203 reloc->at(j) = eloc->at(i);
207 ok = FindErrors(reloc, src_len);
211 if(err->length == 0)
return 1;
214 for(uint8_t i = 0; i < err->length; i++) {
215 epos->Append(err->at(i));
219 CorrectErrata(synd, epos, msg_in);
221 return_corrected_msg:
223 msg_out->length = dst_len;
224 memcpy(dst_ptr, msg_out->ptr(), msg_out->length *
sizeof(uint8_t));
234 int Decode(
const void* src,
void* dst, uint8_t* erase_pos = NULL,
size_t erase_count = 0) {
235 const uint8_t *src_ptr = (
const uint8_t*) src;
236 const uint8_t *ecc_ptr = src_ptr + msg_length;
238 return DecodeBlock(src, ecc_ptr, dst, erase_pos, erase_count);
272 Poly polynoms[MSG_CNT + POLY_CNT];
274 void GeneratorPoly() {
275 Poly *gen = polynoms + ID_GENERATOR;
279 Poly *mulp = polynoms + ID_TPOLY1;
280 Poly *temp = polynoms + ID_TPOLY2;
283 for(int8_t i = 0; i < ecc_length; i++){
285 mulp->at(1) = gf::pow(2, i);
287 gf::poly_mul(gen, mulp, temp);
293 void CalcSyndromes(
const Poly *msg) {
294 Poly *synd = &polynoms[ID_SYNDROMES];
295 synd->length = ecc_length+1;
297 for(uint8_t i = 1; i < ecc_length+1; i++){
298 synd->at(i) = gf::poly_eval(msg, gf::pow(2, i-1));
302 void FindErrataLocator(
const Poly *epos) {
303 Poly *errata_loc = &polynoms[ID_ERASURES_LOC];
304 Poly *mulp = &polynoms[ID_TPOLY1];
305 Poly *addp = &polynoms[ID_TPOLY2];
306 Poly *apol = &polynoms[ID_TPOLY3];
307 Poly *temp = &polynoms[ID_TPOLY4];
309 errata_loc->length = 1;
310 errata_loc->at(0) = 1;
315 for(uint8_t i = 0; i < epos->length; i++){
317 addp->at(0) = gf::pow(2, epos->at(i));
320 gf::poly_add(mulp, addp, apol);
321 gf::poly_mul(errata_loc, apol, temp);
323 errata_loc->Copy(temp);
327 void FindErrorEvaluator(
const Poly *synd,
const Poly *errata_loc,
Poly *dst, uint8_t ecclen) {
328 Poly *mulp = &polynoms[ID_TPOLY1];
329 gf::poly_mul(synd, errata_loc, mulp);
331 Poly *divisor = &polynoms[ID_TPOLY2];
332 divisor->length = ecclen+2;
337 gf::poly_div(mulp, divisor, dst);
340 void CorrectErrata(
const Poly *synd,
const Poly *err_pos,
const Poly *msg_in) {
341 Poly *c_pos = &polynoms[ID_COEF_POS];
342 Poly *corrected = &polynoms[ID_MSG_OUT];
343 c_pos->length = err_pos->length;
345 for(uint8_t i = 0; i < err_pos->length; i++)
346 c_pos->at(i) = msg_in->length - 1 - err_pos->at(i);
349 FindErrataLocator(c_pos);
350 Poly *errata_loc = &polynoms[ID_ERASURES_LOC];
353 Poly *rsynd = &polynoms[ID_TPOLY3];
354 rsynd->length = synd->length;
356 for(int8_t i = synd->length-1, j = 0; i >= 0; i--, j++) {
357 rsynd->at(j) = synd->at(i);
361 Poly *re_eval = &polynoms[ID_TPOLY4];
364 FindErrorEvaluator(rsynd, errata_loc, re_eval, errata_loc->length-1);
367 Poly *e_eval = &polynoms[ID_ERR_EVAL];
368 e_eval->length = re_eval->length;
369 for(int8_t i = re_eval->length-1, j = 0; i >= 0; i--, j++) {
370 e_eval->at(j) = re_eval->at(i);
373 Poly *X = &polynoms[ID_TPOLY1];
377 for(uint8_t i = 0; i < c_pos->length; i++){
378 l = 255 - c_pos->at(i);
379 X->Append(gf::pow(2, -l));
384 Poly *E = &polynoms[ID_MSG_E];
386 E->length = msg_in->length;
390 Poly *err_loc_prime_temp = &polynoms[ID_TPOLY2];
392 uint8_t err_loc_prime;
395 for(uint8_t i = 0; i < X->length; i++){
396 Xi_inv = gf::inverse(X->at(i));
398 err_loc_prime_temp->length = 0;
399 for(uint8_t j = 0; j < X->length; j++){
401 err_loc_prime_temp->Append(gf::sub(1, gf::mul(Xi_inv, X->at(j))));
406 for(uint8_t j = 0; j < err_loc_prime_temp->length; j++){
407 err_loc_prime = gf::mul(err_loc_prime, err_loc_prime_temp->at(j));
410 y = gf::poly_eval(re_eval, Xi_inv);
411 y = gf::mul(gf::pow(X->at(i), 1), y);
413 E->at(err_pos->at(i)) = gf::div(y, err_loc_prime);
416 gf::poly_add(msg_in, E, corrected);
419 bool FindErrorLocator(
const Poly *synd,
Poly *erase_loc = NULL,
size_t erase_count = 0) {
420 Poly *error_loc = &polynoms[ID_ERRORS_LOC];
421 Poly *err_loc = &polynoms[ID_TPOLY1];
422 Poly *old_loc = &polynoms[ID_TPOLY2];
423 Poly *temp = &polynoms[ID_TPOLY3];
424 Poly *temp2 = &polynoms[ID_TPOLY4];
426 if(erase_loc != NULL) {
427 err_loc->Copy(erase_loc);
428 old_loc->Copy(erase_loc);
436 uint8_t synd_shift = 0;
437 if(synd->length > ecc_length) {
438 synd_shift = synd->length - ecc_length;
445 for(uint8_t i = 0; i < ecc_length - erase_count; i++){
446 if(erase_loc != NULL)
447 K = erase_count + i + synd_shift;
452 for(uint8_t j = 1; j < err_loc->length; j++) {
453 index = err_loc->length - j - 1;
454 delta ^= gf::mul(err_loc->at(index), synd->at(K-j));
460 if(old_loc->length > err_loc->length) {
461 gf::poly_scale(old_loc, temp, delta);
462 gf::poly_scale(err_loc, old_loc, gf::inverse(delta));
465 gf::poly_scale(old_loc, temp, delta);
466 gf::poly_add(err_loc, temp, temp2);
467 err_loc->Copy(temp2);
472 while(err_loc->length && err_loc->at(shift) == 0) shift++;
474 uint32_t errs = err_loc->length - shift - 1;
475 if(((errs - erase_count) * 2 + erase_count) > ecc_length){
479 memcpy(error_loc->ptr(), err_loc->ptr() + shift, (err_loc->length - shift) *
sizeof(uint8_t));
480 error_loc->length = (err_loc->length - shift);
484 bool FindErrors(
const Poly *error_loc,
size_t msg_in_size) {
485 Poly *err = &polynoms[ID_ERRORS];
487 uint8_t errs = error_loc->length - 1;
490 for(uint8_t i = 0; i < msg_in_size; i++) {
491 if(gf::poly_eval(error_loc, gf::pow(2, i)) == 0) {
492 err->Append(msg_in_size - 1 - i);
499 if(err->length != errs)
505 void CalcForneySyndromes(
const Poly *synd,
const Poly *erasures_pos,
size_t msg_in_size) {
506 Poly *erase_pos_reversed = &polynoms[ID_TPOLY1];
507 Poly *forney_synd = &polynoms[ID_FORNEY];
508 erase_pos_reversed->length = 0;
510 for(uint8_t i = 0; i < erasures_pos->length; i++){
511 erase_pos_reversed->Append(msg_in_size - 1 - erasures_pos->at(i));
514 forney_synd->Reset();
515 forney_synd->Set(synd->ptr()+1, synd->length-1);
518 for(uint8_t i = 0; i < erasures_pos->length; i++) {
519 x = gf::pow(2, erase_pos_reversed->at(i));
520 for(int8_t j = 0; j < forney_synd->length - 1; j++){
521 forney_synd->at(j) = gf::mul(forney_synd->at(j), x) ^ forney_synd->at(j+1);
AudioTools internal: Reed-Solomon.
Definition: gf.hpp:19