/* * Copyright (C) 2015 Craig Shelley (craig@microtron.org.uk) * Copyright (C) 2016 Furrtek * * BCH Encoder/Decoder - Adapted from GNURadio * * This file is part of PortaPack. * * 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, 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; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ #include #include #include #include "bch_code.hpp" void BCHCode::generate_gf() { /* * generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m] * lookup tables: index->polynomial form alpha_to[] contains j=alpha**i; * polynomial form -> index form index_of[j=alpha**i] = i alpha=2 is the * primitive element of GF(2**m) */ int i, mask; mask = 1; alpha_to[m] = 0; for (i = 0; i < m; i++) { alpha_to[i] = mask; index_of[alpha_to[i]] = i; if (p[i] != 0) alpha_to[m] ^= mask; mask <<= 1; } index_of[alpha_to[m]] = m; mask >>= 1; for (i = m + 1; i < n; i++) { if (alpha_to[i - 1] >= mask) alpha_to[i] = alpha_to[m] ^ ((alpha_to[i - 1] ^ mask) << 1); else alpha_to[i] = alpha_to[i - 1] << 1; index_of[alpha_to[i]] = i; } index_of[0] = -1; } void BCHCode::gen_poly() { /* * Compute generator polynomial of BCH code of length = 31, redundancy = 10 * (OK, this is not very efficient, but we only do it once, right? :) */ int ii, jj, ll, kaux; int test, aux, nocycles, root, noterms, rdncy; int cycle[15][6], size[15], min[11], zeros[11]; // Generate cycle sets modulo 31 cycle[0][0] = 0; size[0] = 1; cycle[1][0] = 1; size[1] = 1; jj = 1; // cycle set index do { // Generate the jj-th cycle set ii = 0; do { ii++; cycle[jj][ii] = (cycle[jj][ii - 1] * 2) % n; size[jj]++; aux = (cycle[jj][ii] * 2) % n; } while (aux != cycle[jj][0]); // Next cycle set representative ll = 0; do { ll++; test = 0; for (ii = 1; ((ii <= jj) && (!test)); ii++) // Examine previous cycle sets for (kaux = 0; ((kaux < size[ii]) && (!test)); kaux++) if (ll == cycle[ii][kaux]) test = 1; } while ((test) && (ll < (n - 1))); if (!(test)) { jj++; // next cycle set index cycle[jj][0] = ll; size[jj] = 1; } } while (ll < (n - 1)); nocycles = jj; // number of cycle sets modulo n // Search for roots 1, 2, ..., d-1 in cycle sets kaux = 0; rdncy = 0; for (ii = 1; ii <= nocycles; ii++) { min[kaux] = 0; for (jj = 0; jj < size[ii]; jj++) for (root = 1; root < d; root++) if (root == cycle[ii][jj]) min[kaux] = ii; if (min[kaux]) { rdncy += size[min[kaux]]; kaux++; } } noterms = kaux; kaux = 1; for (ii = 0; ii < noterms; ii++) for (jj = 0; jj < size[min[ii]]; jj++) { zeros[kaux] = cycle[min[ii]][jj]; kaux++; } // Compute generator polynomial g[0] = alpha_to[zeros[1]]; g[1] = 1; // g(x) = (X + zeros[1]) initially for (ii = 2; ii <= rdncy; ii++) { g[ii] = 1; for (jj = ii - 1; jj > 0; jj--) if (g[jj] != 0) g[jj] = g[jj - 1] ^ alpha_to[(index_of[g[jj]] + zeros[ii]) % n]; else g[jj] = g[jj - 1]; g[0] = alpha_to[(index_of[g[0]] + zeros[ii]) % n]; } } int * BCHCode::encode(int data[]) { // Calculate redundant bits bb[] int h, i, j=0, start=0, end=(n-k); // 10 int Mr[31]; if (!valid) return nullptr; for (i = 0; i < n; i++) { Mr[i] = 0; } for (h = 0; h < k; ++h) Mr[h] = data[h]; while (end < n) { for (i=end; i>start-2; --i) { if (Mr[start] != 0) { Mr[i]^=g[j]; ++j; } else { ++start; j = 0; end = start+(n-k); break; } } } j = 0; for (i = start; i p_init, int m, int n, int k, int t ) : m { m }, n { n }, k { k }, t { t } { size_t i; d = 5; alpha_to = (int *)chHeapAlloc(NULL, sizeof(int) * (n + 1)); index_of = (int *)chHeapAlloc(0, sizeof(int) * (n + 1)); p = (int *)chHeapAlloc(0, sizeof(int) * (m + 1)); g = (int *)chHeapAlloc(0, sizeof(int) * (n - k + 1)); bb = (int *)chHeapAlloc(0, sizeof(int) * (n - k + 1)); if (alpha_to == NULL || index_of == NULL || p == NULL || g == NULL || bb == NULL) valid = false; else valid = true; if (valid) { for (i = 0; i < (size_t)(m + 1); i++) { p[i] = p_init[i]; } generate_gf(); /* generate the Galois Field GF(2**m) */ gen_poly(); /* Compute the generator polynomial of BCH code */ } } BCHCode::~BCHCode() { if (alpha_to != NULL) chHeapFree(alpha_to); if (index_of != NULL) chHeapFree(index_of); if (p != NULL) chHeapFree(p); if (g != NULL) chHeapFree(g); if (bb != NULL) chHeapFree(bb); }