/* ---------------------------------------------------------------------
   (c) ED 2002
   Project      : Multiframe simulator
   Function     : MultiFrame Generator G.704 2048
   Module       : FMG
   File         : MFG.C
   Created      : 24-12-2002
   Modified     : 24-12-2002
   --------------------------------------------------------------------- */
#ifdef __cplusplus
#error This source file is not C++ but rather C. Please use a C-compiler
#endif

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

   0.0 24-12-2002 Creation

   La fonction mfg_get_it16() retourne une sequence de multitrame de
   signalisation selon G704 2048

   Celle-ci est programmable selon les criteres suivants:

   - Tout a 0
   - Tout a 1
   - Trame sans IADM
   - Trame avec IADM
   - Trame avec MVMT faux
   - Commande individuelle de chaque bit de signalisation

   --------------------------------------------------------------------- */

#include "ed/inc/bits.h"

#include "ed/inc/mfg.h"
#include "ed/inc/sys.h"

#include <stdlib.h>

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

#define bit_a bit3
#define bit_b bit2
#define bit_c bit1
#define bit_d bit0

/* constants =========================================================== */

enum
{
   /* abcd abcd */
   MFSW = 0x0B,                 /* 0000 1011 */
   IDLE = 0xDD,                 /* 1101 1101 */
   RMAI = bit2,                 /* 0000 XYXX : bit Y */
   end
};

/* types =============================================================== */
/* structures ========================================================== */
/* private data ======================================================== */
/* private functions =================================================== */
/* internal public data ================================================ */
/* internal public functions =========================================== */
/* entry points ======================================================== */

/* ---------------------------------------------------------------------
   mfg_init()
   ---------------------------------------------------------------------
   initialisation de l'objet MFG
   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
void mfg_init (mfg_s * const this, uint frame)
{
   this->frame = frame;
   this->rmai = RMAI;
   this->frc = 0;
   this->data = -1;
   this->mfsw = MFSW;

   {
      size_t i;
      for (i = 0; i < MFG_FRAME_NB; i++)
      {
         if (i == 0)
         {
            this->it16[i] = this->mfsw | this->rmai | MFSW;
         }
         else
         {
            this->it16[i] = IDLE;
         }
      }

      /* toutes les voies emettent a=1 b=1 c=0 d=1 */
      for (i = 0; i < NELEM (this->sig); i++)
      {
         this->sig[i] = 0x0D;   /* 1101 */
      }
   }
}

/* ---------------------------------------------------------------------
   mfg_zero()
   ---------------------------------------------------------------------
   Force l'emission 'tout a zero'
   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
void mfg_zero (mfg_s * const this, int const sts)
{
   this->frc = sts;
   this->data = 0x00;
}

/* ---------------------------------------------------------------------
   mfg_one()
   ---------------------------------------------------------------------
   Force l'emission 'tout a un'
   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
void mfg_one (mfg_s * const this, int const sts)
{
   this->frc = sts;
   this->data = 0xFF;
}

/* ---------------------------------------------------------------------
   mfg_rmai()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
void mfg_rmai (mfg_s * const this, int const sts)
{
   if (sts)
   {
      this->rmai = RMAI;
   }
   else
   {
      this->rmai = 0;
   }
   this->it16[0] = this->mfsw | this->rmai | MFSW;
}

/* ---------------------------------------------------------------------
   mfg_mfsw()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
void mfg_mfsw (mfg_s * const this, uchar const mfsw)
{
   this->mfsw = mfsw;
   this->it16[0] = this->mfsw | this->rmai | MFSW;
}

/* ---------------------------------------------------------------------
   mfg_sig()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
void mfg_sig (mfg_s * const this
              ,uint const voie
              ,mfg_bit_e const bit
              ,int const sts)
{
   if (this)
   {
      if (voie >= 1 && voie <= NELEM (this->sig))
      {
         size_t const ivoie = voie - 1;

         switch (bit)
         {

         case MFG_BIT_a:
            if (sts)
            {
               mSET (this->sig[ivoie], bit_a);
            }
            else
            {
               mCLR (this->sig[ivoie], bit_a);
            }
            break;

         case MFG_BIT_b:
            if (sts)
            {
               mSET (this->sig[ivoie], bit_b);
            }
            else
            {
               mCLR (this->sig[ivoie], bit_b);
            }
            break;

         case MFG_BIT_c:
            if (sts)
            {
               mSET (this->sig[ivoie], bit_c);
            }
            else
            {
               mCLR (this->sig[ivoie], bit_c);
            }
            break;

         case MFG_BIT_d:
            if (sts)
            {
               mSET (this->sig[ivoie], bit_d);
            }
            else
            {
               mCLR (this->sig[ivoie], bit_d);
            }
            break;
         default:
            ASSERT (0);
         }

         {
            uint upr = voie <= 15;
            uint trame = 1 + (ivoie % 15);

            if (upr)
            {
               mCLR (this->it16[trame], 0xF0);
               mSET (this->it16[trame], this->sig[ivoie] << 4);
            }
            else
            {
               mCLR (this->it16[trame], 0x0F);
               mSET (this->it16[trame], this->sig[ivoie]);
            }
         }
      }
   }
}

/* ---------------------------------------------------------------------
   mfg_get_it16()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
uchar mfg_get_it16 (mfg_s * const this)
{
   uchar data;

   if (this)
   {
      if (!this->frc)
      {
         /* Frame 0 to 15 */
         data = this->it16[this->frame];

         this->frame++;
         if (this->frame == MFG_FRAME_NB)
         {
            this->frame = 0;
         }
      }
      else
      {
         data = this->data;
      }
   }
   else
   {
      data = 0xFF;
   }
   return data;
}
