/* ---------------------------------------------------------------------
   (c) ED 2001
   Project      : CLIB
   Function     : Pseudo Random Generator (1 tap, 32 bit max)
   Module       : PRG
   File         : PRG.C
   Created      : 05-09-2001
   Modified     : 05-09-2001
   --------------------------------------------------------------------- */

/* ---------------------------------------------------------------------
   Log

   0.0 - 05-09-2001 Created
   1.0 - 05-09-2001 Working version

   --------------------------------------------------------------------- */
#ifdef __cplusplus
#error This source file is not C++ but rather C. Please use a C-compiler
#endif

#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "ed/inc/prg.h"
#include "ed/inc/bits.h"
#include "ed/inc/sys.h"

/* macros ============================================================== */

#define MODULE "PRG"
#define VER "1.0"
#define ID "PRG Module \"C\" (c) ED 2001"

/* constants =========================================================== */
/* types =============================================================== */
/* structures ========================================================== */
/* private data ======================================================== */
/* private functions =================================================== */
/* entry points ======================================================== */

/* ---------------------------------------------------------------------
   PRG_sver()
   ---------------------------------------------------------------------
   Returns the "Version" string
   ---------------------------------------------------------------------
   E :
   S : ASCIIZ string pointer
   --------------------------------------------------------------------- */
char const *PRG_sver (void)
{
   return VER;
}

/* ---------------------------------------------------------------------
   PRG_sid()
   ---------------------------------------------------------------------
   Returns the "Identification" string
   ---------------------------------------------------------------------
   E :
   S : ASCIIZ string pointer
   --------------------------------------------------------------------- */
char const *PRG_sid (void)
{
   return ID;
}

/* ---------------------------------------------------------------------
   PRG_init()
   ---------------------------------------------------------------------
   Creates and initializes the C-object
   ---------------------------------------------------------------------
   E : tap
   E : end
   S : Context
   --------------------------------------------------------------------- */
int PRG_init (sPRG * pPrg, int tap, int end)
{
   int ret;

   if (pPrg != NULL)
   {
      /* All to typed 0 */
      CLR (pPrg, sPRG);

      /* creation code ... */
      pPrg->reg = 1;
      pPrg->tap = tap;
      pPrg->end = end;
      ret = 0;
   }
   else
   {
      ret = 1;
   }
   return ret;
}

/* ---------------------------------------------------------------------
   PRG_end()
   ---------------------------------------------------------------------
   Suppresses the C-object
   ---------------------------------------------------------------------
   E : Context
   S :
   --------------------------------------------------------------------- */
void PRG_end (sPRG * const pPrg)
{
   if (pPrg != NULL)
   {
   }
}

/* ---------------------------------------------------------------------
 * PRG_get()
 * ---------------------------------------------------------------------
 *
 *           D0   D1   D2   ..   ..   ..   ..
 *           --   --   --   --   --   --   --
 *       +->|-1|-|-2|-|-3|-|..|+|..|-|..|-|..|-+
 *       |   --   --   --   -- | --   --   --  |
 *       |                    tap             end
 *       |             ---     |               |
 *       |    ---     |   |<---+               |
 *       |   |   |<---|XOR|                    |
 * out <-+---|XOR|    |   |<-------------------+
 *           |   |<-+  ---
 *            ---   |
 *                 cde
 *                  |
 *                 ---
 *                |0/1|
 *                 ---
 *
 * ---------------------------------------------------------------------
 * E : context
 * E : command
 * S : 0/1
 *     -1 = err
 * ---------------------------------------------------------------------
 */
int PRG_get (sPRG * const pPrg, int cde)
{
   int out = -1;

   if (pPrg != NULL)
   {
      {
         /* get the bits */
         uint btap = !!(pPrg->reg & BIT (pPrg->tap - 1));
         uint bend = !!(pPrg->reg & BIT (pPrg->end - 1));

         /* XOR them with the command */
         out = btap ^ bend ^ (cde & 1);
      }

      /* rotation */
      pPrg->reg <<= 1;
      pPrg->reg |= out;
   }

   if (pPrg->nerr)
   {
      pPrg->nerr--;

      switch (pPrg->ferr)
      {
      case 0:
         out = 0;
         break;

      case 1:
         out = 1;
         break;

      case 2:                  /* XOR */
         out ^= 1;
         break;

      }

   }

   return out;
}

/* ---------------------------------------------------------------------
   PRG_err()
   ---------------------------------------------------------------------
   n consecutive bits in error
   ---------------------------------------------------------------------
   E : Context
   E : Value or the errored bit : 0 1 2(XOR)
   E : Number of bits in error : 0-INT_MAX
   S :
   --------------------------------------------------------------------- */
void PRG_err (sPRG * const pPrg, int ferr, int nerr)
{
   pPrg->nerr = nerr;
   pPrg->ferr = ferr;
}

/* public data ========================================================= */

/* File generated by 'NEW.EXE' Ver 1.30 (c) ED 1998-2001 */
