|
| 1 | +/* |
| 2 | + * File: bch3.c |
| 3 | + * Title: Encoder/decoder for binary BCH codes in C (Version 3.1) |
| 4 | + * Author: Robert Morelos-Zaragoza |
| 5 | + * Date: August 1994 |
| 6 | + * Revised: June 13, 1997 |
| 7 | + * |
| 8 | + * =============== Encoder/Decoder for binary BCH codes in C ================= |
| 9 | + * |
| 10 | + * Version 1: Original program. The user provides the generator polynomial |
| 11 | + * of the code (cumbersome!). |
| 12 | + * Version 2: Computes the generator polynomial of the code. |
| 13 | + * Version 3: No need to input the coefficients of a primitive polynomial of |
| 14 | + * degree m, used to construct the Galois Field GF(2**m). The |
| 15 | + * program now works for any binary BCH code of length such that: |
| 16 | + * 2**(m-1) - 1 < length <= 2**m - 1 |
| 17 | + * |
| 18 | + * Note: You may have to change the size of the arrays to make it work. |
| 19 | + * |
| 20 | + * The encoding and decoding methods used in this program are based on the |
| 21 | + * book "Error Control Coding: Fundamentals and Applications", by Lin and |
| 22 | + * Costello, Prentice Hall, 1983. |
| 23 | + * |
| 24 | + * Thanks to Patrick Boyle (pboyle@era.com) for his observation that 'bch2.c' |
| 25 | + * did not work for lengths other than 2**m-1 which led to this new version. |
| 26 | + * Portions of this program are from 'rs.c', a Reed-Solomon encoder/decoder |
| 27 | + * in C, written by Simon Rockliff (simon@augean.ua.oz.au) on 21/9/89. The |
| 28 | + * previous version of the BCH encoder/decoder in C, 'bch2.c', was written by |
| 29 | + * Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) on 5/19/92. |
| 30 | + * |
| 31 | + * NOTE: |
| 32 | + * The author is not responsible for any malfunctioning of |
| 33 | + * this program, nor for any damage caused by it. Please include the |
| 34 | + * original program along with these comments in any redistribution. |
| 35 | + * |
| 36 | + * For more information, suggestions, or other ideas on implementing error |
| 37 | + * correcting codes, please contact me at: |
| 38 | + * |
| 39 | + * Robert Morelos-Zaragoza |
| 40 | + * 5120 Woodway, Suite 7036 |
| 41 | + * Houston, Texas 77056 |
| 42 | + * |
| 43 | + * email: r.morelos-zaragoza@ieee.org |
| 44 | + * |
| 45 | + * COPYRIGHT NOTICE: This computer program is free for non-commercial purposes. |
| 46 | + * You may implement this program for any non-commercial application. You may |
| 47 | + * also implement this program for commercial purposes, provided that you |
| 48 | + * obtain my written permission. Any modification of this program is covered |
| 49 | + * by this copyright. |
| 50 | + * |
| 51 | + * == Copyright (c) 1994-7, Robert Morelos-Zaragoza. All rights reserved. == |
| 52 | + * |
| 53 | + * m = order of the Galois field GF(2**m) |
| 54 | + * n = 2**m - 1 = size of the multiplicative group of GF(2**m) |
| 55 | + * length = length of the BCH code |
| 56 | + * t = error correcting capability (max. no. of errors the code corrects) |
| 57 | + * d = 2*t + 1 = designed min. distance = no. of consecutive roots of g(x) + 1 |
| 58 | + * k = n - deg(g(x)) = dimension (no. of information bits/codeword) of the code |
| 59 | + * p[] = coefficients of a primitive polynomial used to generate GF(2**m) |
| 60 | + * g[] = coefficients of the generator polynomial, g(x) |
| 61 | + * alpha_to [] = log table of GF(2**m) |
| 62 | + * index_of[] = antilog table of GF(2**m) |
| 63 | + * data[] = information bits = coefficients of data polynomial, i(x) |
| 64 | + * bb[] = coefficients of redundancy polynomial x^(length-k) i(x) modulo g(x) |
| 65 | + * numerr = number of errors |
| 66 | + * errpos[] = error positions |
| 67 | + * recd[] = coefficients of the received polynomial |
| 68 | + * decerror = number of decoding errors (in _message_ positions) |
| 69 | + * |
| 70 | + */ |
| 71 | + |
| 72 | +#include <math.h> |
| 73 | +#include <stdio.h> |
| 74 | +#include <stdlib.h> |
| 75 | +#include <string.h> |
| 76 | +#include "bch.h" |
| 77 | + |
| 78 | +int bch_init(bch_t *bch, int m, int length, int t) { |
| 79 | + |
| 80 | + int p[21], n; |
| 81 | + |
| 82 | + if (bch == NULL) { |
| 83 | + return -1; |
| 84 | + } |
| 85 | + |
| 86 | + if (m < 2 || m > 20) { |
| 87 | + return -2; |
| 88 | + } |
| 89 | + |
| 90 | + bch->m = m; |
| 91 | + bch->length = length; |
| 92 | + bch->t = t; |
| 93 | + |
| 94 | + for (int i=1; i<m; i++) { |
| 95 | + p[i] = 0; |
| 96 | + } |
| 97 | + |
| 98 | + p[0] = p[m] = 1; |
| 99 | + if (m == 2) p[1] = 1; |
| 100 | + else if (m == 3) p[1] = 1; |
| 101 | + else if (m == 4) p[1] = 1; |
| 102 | + else if (m == 5) p[2] = 1; |
| 103 | + else if (m == 6) p[1] = 1; |
| 104 | + else if (m == 7) p[1] = 1; |
| 105 | + else if (m == 8) p[4] = p[5] = p[6] = 1; |
| 106 | + else if (m == 9) p[4] = 1; |
| 107 | + else if (m == 10) p[3] = 1; |
| 108 | + else if (m == 11) p[2] = 1; |
| 109 | + else if (m == 12) p[3] = p[4] = p[7] = 1; |
| 110 | + else if (m == 13) p[1] = p[3] = p[4] = 1; |
| 111 | + else if (m == 14) p[1] = p[11] = p[12] = 1; |
| 112 | + else if (m == 15) p[1] = 1; |
| 113 | + else if (m == 16) p[2] = p[3] = p[5] = 1; |
| 114 | + else if (m == 17) p[3] = 1; |
| 115 | + else if (m == 18) p[7] = 1; |
| 116 | + else if (m == 19) p[1] = p[5] = p[6] = 1; |
| 117 | + else if (m == 20) p[3] = 1; |
| 118 | + printf("p(x) = "); |
| 119 | + |
| 120 | + n = 1; |
| 121 | + for (int i = 0; i <= m; i++) { |
| 122 | + n *= 2; |
| 123 | + printf("%1d", p[i]); |
| 124 | + } |
| 125 | + printf("\n"); |
| 126 | + n = n / 2 - 1; |
| 127 | + bch->n = n; |
| 128 | + int ninf = (n + 1) / 2 - 1; |
| 129 | + |
| 130 | + if (length < ninf || length > n) { |
| 131 | + return -3; |
| 132 | + } |
| 133 | + |
| 134 | +/* |
| 135 | + * Generate field GF(2**m) from the irreducible polynomial p(X) with |
| 136 | + * coefficients in p[0]..p[m]. |
| 137 | + * |
| 138 | + * Lookup tables: |
| 139 | + * index->polynomial form: alpha_to[] contains j=alpha^i; |
| 140 | + * polynomial form -> index form: index_of[j=alpha^i] = i |
| 141 | + * |
| 142 | + * alpha=2 is the primitive element of GF(2**m) |
| 143 | + */ |
| 144 | + register int i, mask; |
| 145 | + |
| 146 | + bch->alpha_to = malloc(n * sizeof(int)); |
| 147 | + bch->index_of = malloc(n * sizeof(int)); |
| 148 | + |
| 149 | + mask = 1; |
| 150 | + bch->alpha_to[m] = 0; |
| 151 | + for (int i = 0; i < m; i++) { |
| 152 | + bch->alpha_to[i] = mask; |
| 153 | + bch->index_of[bch->alpha_to[i]] = i; |
| 154 | + if (p[i] != 0) |
| 155 | + bch->alpha_to[m] ^= mask; |
| 156 | + mask <<= 1; |
| 157 | + } |
| 158 | + bch->index_of[bch->alpha_to[m]] = m; |
| 159 | + mask >>= 1; |
| 160 | + for (int i = m + 1; i < n; i++) { |
| 161 | + if (bch->alpha_to[i - 1] >= mask) |
| 162 | + bch->alpha_to[i] = bch->alpha_to[m] ^ ((bch->alpha_to[i - 1] ^ mask) << 1); |
| 163 | + else |
| 164 | + bch->alpha_to[i] = bch->alpha_to[i - 1] << 1; |
| 165 | + bch->index_of[bch->alpha_to[i]] = i; |
| 166 | + } |
| 167 | + bch->index_of[0] = -1; |
| 168 | + |
| 169 | +/* |
| 170 | + * Compute the generator polynomial of a binary BCH code. Fist generate the |
| 171 | + * cycle sets modulo 2**m - 1, cycle[][] = (i, 2*i, 4*i, ..., 2^l*i). Then |
| 172 | + * determine those cycle sets that contain integers in the set of (d-1) |
| 173 | + * consecutive integers {1..(d-1)}. The generator polynomial is calculated |
| 174 | + * as the product of linear factors of the form (x+alpha^i), for every i in |
| 175 | + * the above cycle sets. |
| 176 | + */ |
| 177 | + register int ii, jj, ll, kaux; |
| 178 | + register int test, aux, nocycles, root, noterms, rdncy; |
| 179 | + int cycle[1024][21], size[1024], min[1024], zeros[1024]; |
| 180 | + |
| 181 | + /* Generate cycle sets modulo n, n = 2**m - 1 */ |
| 182 | + cycle[0][0] = 0; |
| 183 | + size[0] = 1; |
| 184 | + cycle[1][0] = 1; |
| 185 | + size[1] = 1; |
| 186 | + jj = 1; /* cycle set index */ |
| 187 | + if (bch->m > 9) { |
| 188 | + printf("Computing cycle sets modulo %d\n", bch->n); |
| 189 | + printf("(This may take some time)...\n"); |
| 190 | + } |
| 191 | + do { |
| 192 | + /* Generate the jj-th cycle set */ |
| 193 | + ii = 0; |
| 194 | + do { |
| 195 | + ii++; |
| 196 | + cycle[jj][ii] = (cycle[jj][ii - 1] * 2) % bch->n; |
| 197 | + size[jj]++; |
| 198 | + aux = (cycle[jj][ii] * 2) % bch->n; |
| 199 | + } while (aux != cycle[jj][0]); |
| 200 | + /* Next cycle set representative */ |
| 201 | + ll = 0; |
| 202 | + do { |
| 203 | + ll++; |
| 204 | + test = 0; |
| 205 | + for (ii = 1; ((ii <= jj) && (!test)); ii++) |
| 206 | + /* Examine previous cycle sets */ |
| 207 | + for (kaux = 0; ((kaux < size[ii]) && (!test)); kaux++) |
| 208 | + if (ll == cycle[ii][kaux]) |
| 209 | + test = 1; |
| 210 | + } while ((test) && (ll < (bch->n - 1))); |
| 211 | + if (!(test)) { |
| 212 | + jj++; /* next cycle set index */ |
| 213 | + cycle[jj][0] = ll; |
| 214 | + size[jj] = 1; |
| 215 | + } |
| 216 | + } while (ll < (bch->n - 1)); |
| 217 | + nocycles = jj; /* number of cycle sets modulo n */ |
| 218 | + |
| 219 | + int d = 2 * t + 1; |
| 220 | + |
| 221 | + /* Search for roots 1, 2, ..., d-1 in cycle sets */ |
| 222 | + kaux = 0; |
| 223 | + rdncy = 0; |
| 224 | + for (ii = 1; ii <= nocycles; ii++) { |
| 225 | + min[kaux] = 0; |
| 226 | + test = 0; |
| 227 | + for (jj = 0; ((jj < size[ii]) && (!test)); jj++) |
| 228 | + for (root = 1; ((root < d) && (!test)); root++) |
| 229 | + if (root == cycle[ii][jj]) { |
| 230 | + test = 1; |
| 231 | + min[kaux] = ii; |
| 232 | + } |
| 233 | + if (min[kaux]) { |
| 234 | + rdncy += size[min[kaux]]; |
| 235 | + kaux++; |
| 236 | + } |
| 237 | + } |
| 238 | + noterms = kaux; |
| 239 | + kaux = 1; |
| 240 | + for (ii = 0; ii < noterms; ii++) |
| 241 | + for (jj = 0; jj < size[min[ii]]; jj++) { |
| 242 | + zeros[kaux] = cycle[min[ii]][jj]; |
| 243 | + kaux++; |
| 244 | + } |
| 245 | + |
| 246 | + bch-> k = length - rdncy; |
| 247 | + |
| 248 | + if (bch->k<0) |
| 249 | + { |
| 250 | + printf("Parameters invalid!\n"); |
| 251 | + return -4; |
| 252 | + } |
| 253 | + |
| 254 | + printf("This is a (%d, %d, %d) binary BCH code\n", bch->length, bch->k, d); |
| 255 | + |
| 256 | + /* Compute the generator polynomial */ |
| 257 | + bch->g = malloc(rdncy * sizeof(int)); |
| 258 | + bch->g[0] = bch->alpha_to[zeros[1]]; |
| 259 | + bch->g[1] = 1; /* g(x) = (X + zeros[1]) initially */ |
| 260 | + for (ii = 2; ii <= rdncy; ii++) { |
| 261 | + bch->g[ii] = 1; |
| 262 | + for (jj = ii - 1; jj > 0; jj--) |
| 263 | + if (bch->g[jj] != 0) |
| 264 | + bch->g[jj] = bch->g[jj - 1] ^ bch->alpha_to[(bch->index_of[bch->g[jj]] + zeros[ii]) % bch->n]; |
| 265 | + else |
| 266 | + bch->g[jj] = bch->g[jj - 1]; |
| 267 | + bch->g[0] = bch->alpha_to[(bch->index_of[bch->g[0]] + zeros[ii]) % bch->n]; |
| 268 | + } |
| 269 | + printf("Generator polynomial:\ng(x) = "); |
| 270 | + for (ii = 0; ii <= rdncy; ii++) { |
| 271 | + printf("%d", bch->g[ii]); |
| 272 | + } |
| 273 | + printf("\n"); |
| 274 | + |
| 275 | + return 0; |
| 276 | +} |
| 277 | + |
| 278 | +void generate_bch(bch_t *bch, int *data, int *bb) { |
| 279 | +/* |
| 280 | + * Compute redundacy bb[], the coefficients of b(x). The redundancy |
| 281 | + * polynomial b(x) is the remainder after dividing x^(length-k)*data(x) |
| 282 | + * by the generator polynomial g(x). |
| 283 | + */ |
| 284 | + register int feedback; |
| 285 | + |
| 286 | + for (int i = 0; i < bch->length - bch->k; i++) |
| 287 | + bb[i] = 0; |
| 288 | + for (int i = bch->k - 1; i >= 0; i--) { |
| 289 | + feedback = data[i] ^ bb[bch->length - bch->k - 1]; |
| 290 | + if (feedback != 0) { |
| 291 | + for (int j = bch->length - bch->k - 1; j > 0; j--) |
| 292 | + if (bch->g[j] != 0) |
| 293 | + bb[j] = bb[j - 1] ^ feedback; |
| 294 | + else |
| 295 | + bb[j] = bb[j - 1]; |
| 296 | + bb[0] = bch->g[0] && feedback; |
| 297 | + } else { |
| 298 | + for (int j = bch->length - bch->k - 1; j > 0; j--) |
| 299 | + bb[j] = bb[j - 1]; |
| 300 | + bb[0] = 0; |
| 301 | + } |
| 302 | + } |
| 303 | +} |
| 304 | + |
| 305 | + |
| 306 | +int |
| 307 | +apply_bch(bch_t *bch, int *recd) |
| 308 | +/* |
| 309 | + * Simon Rockliff's implementation of Berlekamp's algorithm. |
| 310 | + * |
| 311 | + * Assume we have received bits in recd[i], i=0..(n-1). |
| 312 | + * |
| 313 | + * Compute the 2*t syndromes by substituting alpha^i into rec(X) and |
| 314 | + * evaluating, storing the syndromes in s[i], i=1..2t (leave s[0] zero) . |
| 315 | + * Then we use the Berlekamp algorithm to find the error location polynomial |
| 316 | + * elp[i]. |
| 317 | + * |
| 318 | + * If the degree of the elp is >t, then we cannot correct all the errors, and |
| 319 | + * we have detected an uncorrectable error pattern. We output the information |
| 320 | + * bits uncorrected. |
| 321 | + * |
| 322 | + * If the degree of elp is <=t, we substitute alpha^i , i=1..n into the elp |
| 323 | + * to get the roots, hence the inverse roots, the error location numbers. |
| 324 | + * This step is usually called "Chien's search". |
| 325 | + * |
| 326 | + * If the number of errors located is not equal the degree of the elp, then |
| 327 | + * the decoder assumes that there are more than t errors and cannot correct |
| 328 | + * them, only detect them. We output the information bits uncorrected. |
| 329 | + */ |
| 330 | +{ |
| 331 | + register int i, j, u, q, t2, count = 0, syn_error = 0; |
| 332 | + int elp[1026][1024], d[1026], l[1026], u_lu[1026], s[1025]; |
| 333 | + int root[200], loc[200], err[1024], reg[201]; |
| 334 | + |
| 335 | + t2 = 2 * bch->t; |
| 336 | + |
| 337 | + /* first form the syndromes */ |
| 338 | + printf("S(x) = "); |
| 339 | + for (i = 1; i <= t2; i++) { |
| 340 | + s[i] = 0; |
| 341 | + for (j = 0; j < bch->length; j++) |
| 342 | + if (recd[j] != 0) |
| 343 | + s[i] ^= bch->alpha_to[(i * j) % bch->n]; |
| 344 | + if (s[i] != 0) |
| 345 | + syn_error = 1; /* set error flag if non-zero syndrome */ |
| 346 | +/* |
| 347 | + * Note: If the code is used only for ERROR DETECTION, then |
| 348 | + * exit program here indicating the presence of errors. |
| 349 | + */ |
| 350 | + /* convert syndrome from polynomial form to index form */ |
| 351 | + s[i] = bch->index_of[s[i]]; |
| 352 | + printf("%3d ", s[i]); |
| 353 | + } |
| 354 | + printf("\n"); |
| 355 | + |
| 356 | + if (syn_error) { /* if there are errors, try to correct them */ |
| 357 | + /* |
| 358 | + * Compute the error location polynomial via the Berlekamp |
| 359 | + * iterative algorithm. Following the terminology of Lin and |
| 360 | + * Costello's book : d[u] is the 'mu'th discrepancy, where |
| 361 | + * u='mu'+1 and 'mu' (the Greek letter!) is the step number |
| 362 | + * ranging from -1 to 2*t (see L&C), l[u] is the degree of |
| 363 | + * the elp at that step, and u_l[u] is the difference between |
| 364 | + * the step number and the degree of the elp. |
| 365 | + */ |
| 366 | + /* initialise table entries */ |
| 367 | + d[0] = 0; /* index form */ |
| 368 | + d[1] = s[1]; /* index form */ |
| 369 | + elp[0][0] = 0; /* index form */ |
| 370 | + elp[1][0] = 1; /* polynomial form */ |
| 371 | + for (i = 1; i < t2; i++) { |
| 372 | + elp[0][i] = -1; /* index form */ |
| 373 | + elp[1][i] = 0; /* polynomial form */ |
| 374 | + } |
| 375 | + l[0] = 0; |
| 376 | + l[1] = 0; |
| 377 | + u_lu[0] = -1; |
| 378 | + u_lu[1] = 0; |
| 379 | + u = 0; |
| 380 | + |
| 381 | + do { |
| 382 | + u++; |
| 383 | + if (d[u] == -1) { |
| 384 | + l[u + 1] = l[u]; |
| 385 | + for (i = 0; i <= l[u]; i++) { |
| 386 | + elp[u + 1][i] = elp[u][i]; |
| 387 | + elp[u][i] = bch->index_of[elp[u][i]]; |
| 388 | + } |
| 389 | + } else |
| 390 | + /* |
| 391 | + * search for words with greatest u_lu[q] for |
| 392 | + * which d[q]!=0 |
| 393 | + */ |
| 394 | + { |
| 395 | + q = u - 1; |
| 396 | + while ((d[q] == -1) && (q > 0)) |
| 397 | + q--; |
| 398 | + /* have found first non-zero d[q] */ |
| 399 | + if (q > 0) { |
| 400 | + j = q; |
| 401 | + do { |
| 402 | + j--; |
| 403 | + if ((d[j] != -1) && (u_lu[q] < u_lu[j])) |
| 404 | + q = j; |
| 405 | + } while (j > 0); |
| 406 | + } |
| 407 | + |
| 408 | + /* |
| 409 | + * have now found q such that d[u]!=0 and |
| 410 | + * u_lu[q] is maximum |
| 411 | + */ |
| 412 | + /* store degree of new elp polynomial */ |
| 413 | + if (l[u] > l[q] + u - q) |
| 414 | + l[u + 1] = l[u]; |
| 415 | + else |
| 416 | + l[u + 1] = l[q] + u - q; |
| 417 | + |
| 418 | + /* form new elp(x) */ |
| 419 | + for (i = 0; i < t2; i++) |
| 420 | + elp[u + 1][i] = 0; |
| 421 | + for (i = 0; i <= l[q]; i++) |
| 422 | + if (elp[q][i] != -1) |
| 423 | + elp[u + 1][i + u - q] = |
| 424 | + bch->alpha_to[(d[u] + bch->n - d[q] + elp[q][i]) % bch->n]; |
| 425 | + for (i = 0; i <= l[u]; i++) { |
| 426 | + elp[u + 1][i] ^= elp[u][i]; |
| 427 | + elp[u][i] = bch->index_of[elp[u][i]]; |
| 428 | + } |
| 429 | + } |
| 430 | + u_lu[u + 1] = u - l[u + 1]; |
| 431 | + |
| 432 | + /* form (u+1)th discrepancy */ |
| 433 | + if (u < t2) { |
| 434 | + /* no discrepancy computed on last iteration */ |
| 435 | + if (s[u + 1] != -1) |
| 436 | + d[u + 1] = bch->alpha_to[s[u + 1]]; |
| 437 | + else |
| 438 | + d[u + 1] = 0; |
| 439 | + for (i = 1; i <= l[u + 1]; i++) |
| 440 | + if ((s[u + 1 - i] != -1) && (elp[u + 1][i] != 0)) |
| 441 | + d[u + 1] ^= bch->alpha_to[(s[u + 1 - i] |
| 442 | + + bch->index_of[elp[u + 1][i]]) % bch->n]; |
| 443 | + /* put d[u+1] into index form */ |
| 444 | + d[u + 1] = bch->index_of[d[u + 1]]; |
| 445 | + } |
| 446 | + } while ((u < t2) && (l[u + 1] <= bch->t)); |
| 447 | + |
| 448 | + u++; |
| 449 | + if (l[u] <= bch->t) {/* Can correct errors */ |
| 450 | + /* put elp into index form */ |
| 451 | + for (i = 0; i <= l[u]; i++) |
| 452 | + elp[u][i] = bch->index_of[elp[u][i]]; |
| 453 | + |
| 454 | + printf("sigma(x) = "); |
| 455 | + for (i = 0; i <= l[u]; i++) |
| 456 | + printf("%3d ", elp[u][i]); |
| 457 | + printf("\n"); |
| 458 | + printf("Roots: "); |
| 459 | + |
| 460 | + /* Chien search: find roots of the error location polynomial */ |
| 461 | + for (i = 1; i <= l[u]; i++) |
| 462 | + reg[i] = elp[u][i]; |
| 463 | + count = 0; |
| 464 | + for (i = 1; i <= bch->n; i++) { |
| 465 | + q = 1; |
| 466 | + for (j = 1; j <= l[u]; j++) |
| 467 | + if (reg[j] != -1) { |
| 468 | + reg[j] = (reg[j] + j) % bch->n; |
| 469 | + q ^= bch->alpha_to[reg[j]]; |
| 470 | + } |
| 471 | + if (!q) { /* store root and error |
| 472 | + * location number indices */ |
| 473 | + root[count] = i; |
| 474 | + loc[count] = bch->n - i; |
| 475 | + count++; |
| 476 | + printf("%3d ", bch->n - i); |
| 477 | + } |
| 478 | + } |
| 479 | + printf("\n"); |
| 480 | + if (count == l[u]) { |
| 481 | + /* no. roots = degree of elp hence <= t errors */ |
| 482 | + for (i = 0; i < l[u]; i++) |
| 483 | + recd[loc[i]] ^= 1; |
| 484 | + return l[u]; |
| 485 | + } |
| 486 | + else { /* elp has degree >t hence cannot solve */ |
| 487 | + printf("Incomplete decoding: errors detected\n"); |
| 488 | + return -1; |
| 489 | + } |
| 490 | + } else { |
| 491 | + return -1; |
| 492 | + } |
| 493 | + } else { |
| 494 | + return 0; // No errors |
| 495 | + } |
| 496 | +} |
| 497 | + |
| 498 | +/* LEFT justified in hex */ |
| 499 | +void bytes_to_bits(int *bytes, int *bit_dest, int num_bits) { |
| 500 | + for (int i = 0; i < num_bits; i++) { |
| 501 | + int index = i / 8; |
| 502 | + int bit_pos = 7 - (i % 8); |
| 503 | + int bit_mask = 1 << bit_pos; |
| 504 | + bit_dest[i] = (bytes[index] & bit_mask) != 0; |
| 505 | + } |
| 506 | +} |
| 507 | + |
| 508 | +void dump_bch(bch_t *bch) { |
| 509 | + printf("m: %d length: %d t: %d n: %d k: %d\n", bch->m, bch->length, bch->t, bch->n, bch->k); |
| 510 | +} |
| 511 | + |
| 512 | +#define TEST_APPLY |
| 513 | + |
| 514 | +int main() |
| 515 | +{ |
| 516 | + int test[][8] = { |
| 517 | + { 0xb2, 0x17, 0xa2, 0xb9, 0x53, 0xdd, 0xc5, 0x52 }, /* perfect random test */ |
| 518 | + { 0xf0, 0x5a, 0x6a, 0x6a, 0x01, 0x63, 0x33, 0xd0 }, /* g001-cut-lenthened_457.938M.wav */ |
| 519 | + { 0xf0, 0x81, 0x52, 0x6b, 0x71, 0xa5, 0x63, 0x08 }, /* 1st in eotd_received_data */ |
| 520 | +/* 3 errors */ { 0xf0, 0x85, 0x50, 0x6a, 0x01, 0xe5, 0x6e, 0x84 }, /* 2nd in eotd_received_data */ |
| 521 | +/* fixed */ { 0xf0, 0x85, 0x50, 0x6a, 0x01, 0xe5, 0x06, 0x84 }, /* 2nd, but with the bits fixed */ |
| 522 | + { 0xf0, 0x85, 0x59, 0x5a, 0x01, 0xe5, 0x6e, 0x84 }, /* 3rd */ |
| 523 | + { 0xf1, 0x34, 0x50, 0x1a, 0x01, 0xe5, 0x66, 0xfe }, /* 4th */ |
| 524 | + { 0xf0, 0xeb, 0x10, 0xea, 0x01, 0x6e, 0x54, 0x1c }, /* 5th */ |
| 525 | + { 0xf0, 0xea, 0x5c, 0xea, 0x01, 0x6e, 0x55, 0x0e }, /* 6th */ |
| 526 | + { 0xe0, 0x21, 0x10, 0x1a, 0x01, 0x32, 0xbc, 0xe4 }, /* Sun Mar 20 05:41:00 2022 */ |
| 527 | + { 0xf0, 0x42, 0x50, 0x5b, 0xcf, 0xd5, 0x64, 0xe4 }, /* Sun Mar 20 12:58:43 2022 */ |
| 528 | + { 0xf0, 0x8c, 0x10, 0xaa, 0x01, 0x73, 0x7b, 0x1a }, /* Sun Mar 20 13:35:48 2022 */ |
| 529 | + { 0xf0, 0x8c, 0x10, 0xb1, 0xc0, 0xe0, 0x90, 0x64 }, /* Sun Mar 20 13:37:05 2022 */ |
| 530 | + { 0xf0, 0x8c, 0x10, 0x6a, 0x01, 0x64, 0x7a, 0xe8 }, /* Sun Mar 20 13:37:48 2022 */ |
| 531 | + { 0x50, 0x8c, 0x12, 0x6a, 0x01, 0x64, 0x7a, 0xe8 }, |
| 532 | + }; |
| 533 | + |
| 534 | + int bits[63]; |
| 535 | + bch_t bch; |
| 536 | + |
| 537 | + bch_init(&bch, 6, 63, 3); |
| 538 | + |
| 539 | + for (int count = 0; count < sizeof(test) / sizeof(*test); count++) { |
| 540 | + bytes_to_bits(test[count], bits, 63); |
| 541 | +#ifdef TEST_BYTES_TO_BITS |
| 542 | + printf("ORIG pkt [%d]\n", count); |
| 543 | + for (int i = 0; i < 8; i++) { |
| 544 | + printf("%02x ", test[count][i]); |
| 545 | + } |
| 546 | + printf("\n"); |
| 547 | + |
| 548 | + printf("ORIG pkt[%d] bits\n", count); |
| 549 | + for (int i = 0; i < 63; i++) { |
| 550 | + printf("%d ", bits[i]); |
| 551 | + } |
| 552 | + printf("\n"); |
| 553 | +#endif |
| 554 | +#ifdef TEST_GENERATE |
| 555 | + int bch_code[18]; |
| 556 | + generate_bch(&bch, bits, bch_code); |
| 557 | + printf("generated BCH\n"); |
| 558 | + for (int i = 0; i < 18; i++) { |
| 559 | + printf("%d ", bch_code[i]); |
| 560 | + } |
| 561 | + printf("\n"); |
| 562 | +#endif |
| 563 | +#ifdef TEST_APPLY |
| 564 | + int recv[63]; |
| 565 | + // backwards, for now |
| 566 | + for (int i = 0; i < 45; i++) { |
| 567 | + recv[i + 18] = bits[i]; |
| 568 | + } |
| 569 | + |
| 570 | + for (int i = 0; i < 18; i++) { |
| 571 | + recv[i] = bits[i + 45]; |
| 572 | + } |
| 573 | + |
| 574 | + printf("rearranged packet: "); |
| 575 | + for (int i = 0; i < 63; i++) { |
| 576 | + printf("%d ", recv[i]); |
| 577 | + } |
| 578 | + printf("\n"); |
| 579 | + |
| 580 | + int corrected = apply_bch(&bch, recv); |
| 581 | + |
| 582 | + printf("corrected [%d] packet: ", corrected); |
| 583 | + for (int i = 0; i < 63; i++) { |
| 584 | + printf("%d ", recv[i]); |
| 585 | + } |
| 586 | + printf("\n"); |
| 587 | +#endif |
| 588 | + } |
| 589 | +} |
0 commit comments