/* Reed-Solomon encoder
 * Copyright 2003, Phil Karn, KA9Q
 * May be used under the terms of the GNU Lesser General Public License (LGPL)
 *
 * Slightly modified by Jason Milldrum NT7S, 2015 to fit into the Arduino framework
 *
 * The guts of the Reed-Solomon encoder, meant to be #included
 * into a function body with the following typedefs, macros and variables supplied
 * according to the code parameters:

 * data_t - a typedef for the data symbol
 * data_t data[] - array of NN-NROOTS-PAD and type data_t to be encoded
 * data_t parity[] - an array of NROOTS and type data_t to be written with parity symbols
 * NROOTS - the number of roots in the RS code generator polynomial,
 *          which is the same as the number of parity symbols in a block.
            Integer variable or literal.
 *
 * NN - the total number of symbols in a RS block. Integer variable or literal.
 * PAD - the number of pad symbols in a block. Integer variable or literal.
 * ALPHA_TO - The address of an array of NN elements to convert Galois field
 *            elements in index (log) form to polynomial form. Read only.
 * INDEX_OF - The address of an array of NN elements to convert Galois field
 *            elements in polynomial form to index (log) form. Read only.
 * MODNN - a function to reduce its argument modulo NN. May be inline or a macro.
 * GENPOLY - an array of NROOTS+1 elements containing the generator polynomial in index form

 * The memset() and memmove() functions are used. The appropriate header
 * file declaring these functions (usually <string.h>) must be included by the calling
 * program.
 */

#include <string.h>
#include <jtencode.h>
#include "int.h"
#include "rs_common.h"

void encode_rs_int(void *p, data_t *data, data_t *parity)
{
  struct rs *rs = (struct rs *)p;

  #undef A_0
  #define A_0 (NN) /* Special reserved value encoding zero in index form */

  {
    int i, j;
    data_t feedback;

    memset(parity,0,NROOTS*sizeof(data_t));

    for(i=0;i<NN-NROOTS-PAD;i++){
      feedback = INDEX_OF[data[i] ^ parity[0]];
      if(feedback != A_0){      /* feedback term is non-zero */
  #ifdef UNNORMALIZED
        /* This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
         * always be for the polynomials constructed by init_rs()
         */
        feedback = MODNN(NN - GENPOLY[NROOTS] + feedback);
  #endif
        for(j=1;j<NROOTS;j++)
  	parity[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS-j])];
      }
      /* Shift */
      memmove(&parity[0],&parity[1],sizeof(data_t)*(NROOTS-1));
      if(feedback != A_0)
        parity[NROOTS-1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])];
      else
        parity[NROOTS-1] = 0;
    }
  }
}
