#include #include "codecAO40.h" /* ---------------------- */ /* AO40 Encoder - Decoder */ /* ---------------------- */ /* Scramble and RS encode 256 byte blocks of data into 5200 bits * or Descramble and RS decode 5200 bits into the 256 bytes of data * * -------------------------------------------------------------------------- * This decoder has evolved extensively through the work of Phil Karn. It draws * on his own ideas and optimisations, and on the work of others. The lineage * is as below, and parts of the authors' notices are included here. (JRM) * AO40 encoder / decoder * Copyright 2002 Phil Karn, KA9Q * May be used under the terms of the GNU General Public License (GPL) * * Reed-Solomon coding and decoding * Phil Karn (karn@ka9q.ampr.org) September 1996 * * This file is derived from the program "new_rs_erasures.c" by Robert * Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari Thirumoorthy * (harit@spectra.eng.hawaii.edu), Aug 1995 * -------------------------------------------------------------------------- * * From the RM-Z & HT program: * The encoding and decoding methods are based on the * book "Error Control Coding: Fundamentals and Applications", * by Lin and Costello, Prentice Hall, 1983, ISBN 0-13-283796-X * Portions of this program are from a Reed-Solomon encoder/decoder * in C, written by Simon Rockliff (simon@augean.ua.oz.au) on 21/9/89. * -------------------------------------------------------------------------- * * From the 1989/1991 SR program (also based on Lin and Costello): * This program may be freely modified and/or given to whoever wants it. * A condition of such distribution is that the author's contribution be * acknowledged by his name being left in the comments heading the program, * Simon Rockliff, 26th June 1991 * */ /* Defines for RS Decoder(s) */ #ifndef min #define min(a,b) ((a) < (b) ? (a) : (b)) #endif /* CCodecAO40::CCodecAO40(void) { } CCodecAO40::~CCodecAO40(void) { } */ //int CCodecAO40::mod255(int x) { int mod255(int x) { while (x >= 255) { x -= 255; x = (x >> 8) + (x & 255); } return x; } //int CCodecAO40::decode_rs_8(char *data, int *eras_pos, int no_eras){ int decode_rs_8(char *data, int *eras_pos, int no_eras){ int deg_lambda, el, deg_omega; int i, j, r,k; unsigned char u,q,tmp,num1,num2,den,discr_r; unsigned char lambda[NROOTS+1], s[NROOTS]; /* Err+Eras Locator poly and syndrome poly */ unsigned char b[NROOTS+1], t[NROOTS+1], omega[NROOTS+1]; unsigned char root[NROOTS], reg[NROOTS+1], loc[NROOTS]; int syn_error, count; /* form the syndromes; i.e., evaluate data(x) at roots of g(x) */ for(i=0;i 0) { /* Init lambda to be the erasure locator polynomial */ lambda[1] = ALPHA_TO[mod255(PRIM*(NN-1-eras_pos[0]))]; for (i = 1; i < no_eras; i++) { u = mod255(PRIM*(NN-1-eras_pos[i])); for (j = i+1; j > 0; j--) { tmp = INDEX_OF[lambda[j - 1]]; if(tmp != A0) lambda[j] ^= ALPHA_TO[mod255(u + tmp)]; } } } for(i=0;i 0; j--){ if (reg[j] != A0) { reg[j] = mod255(reg[j] + j); q ^= ALPHA_TO[reg[j]]; } } if (q != 0) continue; /* Not a root */ /* store root (index-form) and error location number */ root[count] = i; loc[count] = k; /* If we've already found max possible roots, * abort the search to save time */ if(++count == deg_lambda) break; } if (deg_lambda != count) { /* * deg(lambda) unequal to number of roots => uncorrectable * error detected */ count = -1; goto finish; } /* * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo * x**NROOTS). in index form. Also find deg(omega). */ deg_omega = 0; for (i = 0; i < NROOTS;i++){ tmp = 0; j = (deg_lambda < i) ? deg_lambda : i; for(;j >= 0; j--){ if ((s[i - j] != A0) && (lambda[j] != A0)) tmp ^= ALPHA_TO[mod255(s[i - j] + lambda[j])]; } if(tmp != 0) deg_omega = i; omega[i] = INDEX_OF[tmp]; } omega[NROOTS] = A0; /* * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = * inv(X(l))**(FCR-1) and den = lambda_pr(inv(X(l))) all in poly-form */ for (j = count-1; j >=0; j--) { num1 = 0; for (i = deg_omega; i >= 0; i--) { if (omega[i] != A0) num1 ^= ALPHA_TO[mod255(omega[i] + i * root[j])]; } num2 = ALPHA_TO[mod255(root[j] * (FCR - 1) + NN)]; den = 0; /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ for (i = min(deg_lambda,NROOTS-1) & ~1; i >= 0; i -=2) { if(lambda[i+1] != A0) den ^= ALPHA_TO[mod255(lambda[i+1] + i * root[j])]; } if (den == 0) { count = -1; goto finish; } /* Apply error to data */ if (num1 != 0) { data[loc[j]] ^= ALPHA_TO[mod255(INDEX_OF[num1] + INDEX_OF[num2] + NN - INDEX_OF[den])]; } } finish: if(eras_pos != NULL){ for(i=0;i> 7); c <<= 1; interleave_symbol( Partab[m_conv_sr & CPOLYA]); interleave_symbol(!Partab[m_conv_sr & CPOLYB]); /* Second encoder symbol is inverted */ } } /* Scramble a byte, convolutionally encode and interleave into frame */ //void CCodecAO40::scramble_and_encode(unsigned char c){ void scramble_and_encode(unsigned char c){ c ^= Scrambler[m_encoded_bytes]; /* Scramble byte */ encode_and_interleave(c,8); /* RS encode and place into reencode buffer */ } /* Encodes the 256 byte source block RSdecdata[] into 5200 byte block of symbols * results stored in m_encoded. * On success encoded buffer is returned, an zeroed buffer on failure */ //const unsigned char *CCodecAO40::encode(unsigned char *source_bytes, int byte_count) const unsigned char *encode(unsigned char *source_bytes, int byte_count) { if(BLOCKSIZE != byte_count || NULL == source_bytes ) { memset(m_encoded, 0, BLOCKSIZE); return m_encoded; } init_encoder(); for(int i=0;i>1]; scramble_and_encode(c); if(++m_encoded_bytes == 320){ /* Tail off the convolutional encoder (flush) */ encode_and_interleave(0,6); } } //void CCodecAO40::descramble_to_rsblocks(unsigned char viterbi_decoded[NBITS_OUT], char rsblocks[RSBLOCKS][NN]) void descramble_to_rsblocks(unsigned char viterbi_decoded[NBITS_OUT], char rsblocks[RSBLOCKS][NN]) { /* interleave into Reed Solomon codeblocks */ memset(rsblocks,0,RSBLOCKS*NN); /* Zero rsblocks array */ int di = 0; int si = 0; for(int col=RSPAD;col>7) ) { error_count++ ; } } return error_count; }