/****************************************************************************
/*  F i l e   D a t a                                                        
/*                                                                           
/*  Module       : BasicSW                                                   
/*  C.I. No.     :                                                           
/*  $Revision: 1.1.1.1 $
/*  $Date: 2006/04/25 09:00:20 $
/*  Belonging to :                                                           
/*               :                                                           
/*  $RCSfile: BI_Bus1553B_int.c,v $
/*  Program Type :                                                           
/*  Sub-modules  :                                                           
/*                                                                           
/****************************************************************************
/*  S W   D e v e l o p m e n t   E n v i r o n m e n t                      
/*                                                                           
/*  Host system  :                                                           
/*  SW Compiler  :                                                           
/*  $Author: kusanagi $
/*               :                                                           
/****************************************************************************
/*  U p d a t i n g                                                          
/*                                                                           
/*  $Log: BI_Bus1553B_int.c,v $
/*  Revision 1.1.1.1  2006/04/25 09:00:20  kusanagi
/*  These program extract in an XML format the info contained into the ROOT files generated by YODA from the PAMELA data. To visualize the XML files in a more human readable format a collection of XSL files are given in the Data subfolder.
/*
/*  Revision 1.12  2005/03/06 14:51:24  sebastiani
/*  *** empty log message ***
/*
/*  Revision 1.11  2004/12/03 10:05:54  faber
/*  GAS SYSTEM: this must be zero as agreed in document protocol PAM. R1d1-346bis-04 (russian)
/*
/*  Revision 1.10  2004/12/02 09:53:58  faber
/*  GAS System Bit in CCA zeroed as agreed in russian document PAM. R1d1-346bis-04
/*
/*  Revision 1.9  2004/11/10 16:59:55  sebastiani
/*  - GS_COMPILE directive introduced and be undef by default
/*  - automatic flush mechanism by run manager mailbox timeout
/*
/*  Revision 1.8  2004/07/27 17:30:17  faber
/*  OBT can be now in second or milliseconds, depending of the situazion.
/*  OBT_s is used for FM compatibility, OBT_ms basically for MM infos
/*
/*  Revision 1.7  2004/02/05 11:16:07  sebastiani
/*  file size in CCA is now in MByte
/*
/*  Revision 1.6  2003/12/11 11:35:47  sebastiani
/*  IPM error bit managerment
/*
/*  Revision 1.5  2003/12/11 10:53:36  alfarano
/*  update
/*
/*  Revision 1.4  2003/12/01 09:27:16  sebastiani
/*  CCA info for Gas Module and first implementation of IPM infos.
/*
/*  Revision 1.3  2003/11/18 09:01:14  alfarano
/*  laben patch fixes some problems
/*
/*  Revision 1.2  2003/09/10 13:47:47  laben
/*  delete reference to file2
/*  need to fix the format CCA.
/*
/*  Revision 1.1.1.1  2003/08/04 09:40:21  sebastiani
/*  Imported sources laben rel. 19.06.2003 integrated with pam2
/*
/*  Revision 1.12  2003/02/26 17:21:33  aurora
/*  fixed remap descriptor block for mode codes (brd)
/*
/*  Revision 1.11  2003/02/26 16:23:42  zulia
/*  fixed remap descriptor block for mode codes
/*
/*  Revision 1.10  2002/11/06 15:48:00  zulia
/*  Correct 1553 ack bug
/*
/*  Revision 1.9  2002/08/01 08:12:12  aurora
/*  Check on TT MAX length added
/*
/*  Revision 1.8  2002/05/15 13:55:53  zulia
/*  Modified to return MCMD ID and
/*  Source Sequence Counter in case of MCMD validation error
/*
/*  Revision 1.7  2002/05/15 13:13:09  aurora
/*  Modified to return MCMD ID and
/*  Source Sequence Counter in case of MCMD validation error
/*
/*  Revision 1.6  2002/05/09 08:16:33  zulia
/*  *  acceptance release
/*
/*                                                                           
/*****************************************************************************/

#include <src/BasicSW/Bus1553B/BI_Bus1553B_int.h>
#include <src/MCMDManager/MCMDArea/MA_MCMDArea_p.h>
#include <src/MCMDManager/TTManager/MT_TTManager_p.h>
#include <src/HKManager/HistoryArea/HA_HistoryArea_p.h>
#include <src/MCMDManager/MCMDDispatcher/MD_MCMDDispatcher_p.h>
#include <src/HKManager/ReportGenerator/RG_ReportGenerator_p.h>
#include <src/FileManager/FileSystem/FS_FileSystem_p.h>

#include <src/BasicSW/TimingInfo/TI_TimingInfo_p.h>

#include <src/INFN/GS_Gas_INFN.h>
#include <src/INFN/PWR_PowerHandler_INFN.h>


/*============================== Local Variables ============================*/
/*****************************************************************************/
/* @Variable: legalTable                                                     */
/* @Purpose :                                                                */
/*   LEGAL_DATA type                                                         */
/*   Array of structures to store informations for opened descriptors        */
/* @@                                                                        */
/*****************************************************************************/
LEGAL_DATA legalTable [NUM_OF_DESC_BLK_ID];

/*****************************************************************************/
/* @Variable: sumRtDescrPointerReg                                           */
/* @Purpose :                                                                */
/*   unsigned int* type                                                      */
/*   Pointer to the SuMMIT Descriptor Pointer Register                       */
/* @@                                                                        */
/*****************************************************************************/
static unsigned int* sumRtDescrPointerReg = (unsigned int*)SUM_RTDPR_ADRS;

/*****************************************************************************/
/* @Variable: sumIllegalizationReg                                           */
/* @Purpose :                                                                */
/*   unsigned int* type                                                      */
/*   Pointer to the SuMMIT Illegalization Register                           */
/* @@                                                                        */
/*****************************************************************************/
static unsigned int* sumIllegalizationReg = (unsigned int*)SUM_ILLGR_ADRS;

/*****************************************************************************/
/* @Variable: exgMemoryAreaAdrs                                              */
/* @Purpose :                                                                */
/*   unsigned int* type                                                      */
/*   Pointer to the SuMMIT Exchange Memory Area (Area 0)                     */
/* @@                                                                        */
/*****************************************************************************/
static unsigned int* exgMemoryAreaAdrs = (unsigned int*)EXG_MEM_ADRS_AREA0;

/*****************************************************************************/
/*=====      I N T E R N A L   F U N C T I O N S                        =====*/
/*****************************************************************************/

/*****************************************************************************/
/* @Function: BI_ifSuMMITRTDrv                                               */
/* @Purpose :                                                                */
/*  The function initialize SuMMIT as SRT device driver and sets             */
/*                                                                           */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/*  rtAdrs               IN      Value of the Remote Terminal Address        */
/*  status_1553          OUT     Return code                                 */
/* @@                                                                        */
/*****************************************************************************/

status_1553 BI_ifSuMMITRTDrv(unsigned int rtAdrs )
{
    int i, j;
    status_1553 ret_code = BI_OK;

    if (rtAdrs < NUM_OF_RT_ADRS)
    {
        /* Control Register */
        /* set enhanced mode number 1 */
        /* interrupt log list enable */
        /* channel A (bus A) and channel B (bus B) enable */
        /* transmit status word   */
        /* register value: 0x9993 */
        *(unsigned int*)SUM_CTRLR_ADRS = START_EXEC_BIT     |
                                         SRT_EN_MODE_2      |
                                         INT_LOG_LIST_ENABLE|
                                         CHAN_A_ENABLE      |
                                         CHAN_B_ENABLE      |
                                         BROADCAST_ENABLE   |
                                         TX_STATUS_WORD_ENABLE;

        /*Operational Status Register */
        /* set remote terminal mode of operation */
        /* set remote terminal address */
        /* remote terminal address parity bit enable */
        // no RT_PARITY_BIT_ENABLE;
        *(unsigned int*)SUM_OPSTR_ADRS = SRT_OP_MODE | (rtAdrs << 11);

        /* Interrupt Mask Register */
        *(unsigned int*)SUM_INTMR_ADRS = REG_IRQ_MASK_VALUE;

        /* Interrupt Log List Pointer Register */
        /* set location of the Interrupt Log List within */
        /* a 64k memory space */
        *(unsigned int*)SUM_ILLPR_ADRS = REG_IRQ_LOG_LIST_PTR_VALUE;

        /* RT Descriptor Pointer Register */
        /* set location to start the Descriptor Table within */
        /* a 64k memory space */
        /* Interrupt Log List resides in a 32-word ring buffer */
        *sumRtDescrPointerReg = NUM_OF_ILL_WORDS;//=32 subaddrs;

        /* Status Word Bits Register */
        /* immediate clear function enable */
        *(unsigned int*)SUM_STWBR_ADRS = IMCLRF_ENABLE;

        /* Illegalization Registers */
        /* illegalization of all subaddress/mode code */
        /* (logical 1 = illegal in illegalization registers) */
        for (i = 0; i < 16; i++)
        {
            *(sumIllegalizationReg + i) = 0xFFFF;
        }

        /* initialize legalization table to use in BI_ifSuMMITRTDbLegalize() */
        for (i = 0; i < NUM_OF_DESC_BLK_ID; i += 32)
        {
            for (j = 0; j < 32; j++)
            {
                legalTable[i+j].blkType = i/32;
                legalTable[i+j].subAdrs = j;
            }
        }
    }
    else
    {
        ret_code = BI_RT_ADRS_ERROR;
    }

    return ret_code;
}


/*****************************************************************************/
/* @Function: BI_ifSuMMITRTDbLegalize                                        */
/* @Purpose :                                                                */
/* This routine legalizes subaddress/mode code of a specified block          */
/*                                                                           */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/*  blkType              IN      Receive or Transmit type block              */
/*  subAdrs              IN      subaddress                                  */
/*  int                  OUT     Block descriptor index                      */
/* @@                                                                        */
/*****************************************************************************/

int BI_ifSuMMITRTDbLegalize(unsigned int blkType, unsigned int subAdrs)
{
  int i, block_idx = 0;

    /* Set the correct legalization bit for the specified subaddress */
    if ((subAdrs >= 0) && (subAdrs <= 15))
    {
        *(unsigned int *)((unsigned int)sumIllegalizationReg + blkType * BLK_SIZE) &=
        ~(1 << subAdrs);
    }
    else if ((subAdrs >= 16) && (subAdrs <= 31))
    {
        *(unsigned int *)((unsigned int)sumIllegalizationReg + blkType * BLK_SIZE +
                           BLK_SIZE / 2) &= ~(1 << (subAdrs - 16));
    }
    /* Evaluate the subuddress descriptor block index */
    for (i = 0; i < NUM_OF_DESC_BLK_ID; i++)
    {
        if ((legalTable[i].blkType == blkType) && (legalTable[i].subAdrs == subAdrs))
        {
            /* If a broadcast subaddress/modecode is specified, remap it to the */
            /* same non-broadcast desctiptor block index                        */
            if(i < BI_RXTX_END_BLOCK)
            {
                block_idx = i;
            }
            else if(i < BI_BDC_RXTX_END_BLOCK)
	    /* Subaddress is broadcast tx/rx                                  */
            {
                block_idx = i - BI_BDC_RXTX_OFS;
            }
            else if(i < BI_MC_TXRX_END_BLOCK)
	    /* Subaddress is Mode code tx/rx                                    */
            {
                block_idx = i;
            }
            else
            {
                block_idx = i - BI_BRMC_TXRX_OFS;
            }  
        }
    }

    return block_idx;
}


/*****************************************************************************/
/* @Function: BI_ifSuMMITRTDbGet                                             */
/* @Purpose :                                                                */
/* This routine retrieves the descriptor block related to the specified      */
/* subaddress identifier                                                     */
/*                                                                           */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/*  descblkId            IN      Identifier of the descriptor block (0..255) */
/*  db                   OUT     descriptor block structure                  */
/* @@                                                                        */
/*****************************************************************************/

unsigned int* BI_ifSuMMITRTDbGet( unsigned int descblkId, DESC_BLK* db )
{
  unsigned int* pexg = (unsigned int*)0;

    if( descblkId < NUM_OF_DESC_BLK_ID )
    {
        // computes the address of the specified descriptor
        pexg = exgMemoryAreaAdrs + (*sumRtDescrPointerReg>>16) + descblkId*4;
        db->ctrlWord    = pexg[0] >> 16;
        db->topAdrs     = pexg[1] >> 16;
        db->currentAdrs = pexg[2] >> 16;
        db->mib         = pexg[3] >> 16;
    }

    return pexg;
}


/*****************************************************************************/
/* @Function: BI_ifSuMMITRTGetDataAddress                                    */
/* @Purpose :                                                                */
/* This routine retrieves the pointer of the descriptor block related to     */
/* the specified subaddress identifier                                       */
/*                                                                           */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/*  descblkId            IN      Identifier of the descriptor block (0..255) */
/* @@                                                                        */
/*****************************************************************************/
unsigned int* BI_ifSuMMITRTGetDataAddress(unsigned int descblkId)
{
  unsigned int* pexg = (unsigned int*)0;

    if( descblkId < NUM_OF_DESC_BLK_ID )
    {
        /* computes the address of the specified descriptor */
        pexg = exgMemoryAreaAdrs + (*sumRtDescrPointerReg>>16) + descblkId*4;
        pexg = exgMemoryAreaAdrs + (pexg[1] >> 16); 
    }

    return pexg;
}


/*****************************************************************************/
/* @Function: BI_ifSuMMITRTDbWrite                                           */
/* @Purpose :                                                                */
/* This routine writes a descriptor block related to the specified           */
/* subaddress identifier                                                     */
/*                                                                           */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/*  descblkId            IN      Identifier of the descriptor block (0..255) */
/*  db                   IN      descriptor block structure                  */
/*  DESC_BLK*            OUT     returns the descriptor block memory address */
/* @@                                                                        */
/*****************************************************************************/

DESC_BLK* BI_ifSuMMITRTDbWrite(unsigned int descblkId, DESC_BLK db)
{
    DESC_BLK* pdb = (DESC_BLK*)0;

    if( descblkId < NUM_OF_DESC_BLK_ID )
    {
        /* computes the address of the specified descriptor */
        pdb = (DESC_BLK*)(exgMemoryAreaAdrs + (*sumRtDescrPointerReg>>16) + descblkId*4);
        pdb->ctrlWord    = db.ctrlWord;
        pdb->topAdrs     = db.topAdrs;
        pdb->currentAdrs = db.currentAdrs;
        pdb->mib         = db.mib;
    }

    return pdb;
}


/*****************************************************************************/
/* @Function: BI_ifSuMMITRTPacketRead                                        */
/* @Purpose :                                                                */
/* This routine copies a number of 16 bit words from 1553 exchange memory    */
/* (at the address of the corrispondent descriptor block) to RAM memory.     */
/*                                                                           */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/*  descblkId            IN      Identifier of the descriptor block (0..255) */
/*  memRAM               IN      pointer to the RAM memory to be copied      */
/*  numWords16           IN      number of 16 bit words to be copied         */
/*  status_1553          OUT     return code                                 */
/* @@                                                                        */
/*****************************************************************************/
status_1553 BI_ifSuMMITRTPacketRead( unsigned int descblkId, unsigned short* memRAM, unsigned int numWords16 )
{
  status_1553   status = BI_OK;
  unsigned int* memExg;
  DESC_BLK      DescBlk;


    if ( descblkId >= NUM_OF_DESC_BLK_ID )
    {
        status = BI_DESC_BLK_ID_ERROR;
    }
    else
    {
        memExg = BI_ifSuMMITRTGetDataAddress(descblkId); // gets the address of data of the i-th descriptor
        
        if( memExg )
        {
            while( numWords16 ) // copies the data into RAM
            {
              *memRAM = (unsigned short int)(*memExg >> 16); // only 16MSB are significative
              memRAM++;
              memExg++;
              numWords16--;
            }
        }
        else
        {
            status = BI_DATA_BOUNDARY_ERROR;
        } 
    }

    return status;
}


/*****************************************************************************/
/* @Function: BI_ifSuMMITRTRegRead                                           */
/* @Purpose :                                                                */
/* This routine reads a SuMMIT register                                      */
/*                                                                           */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/*  regId                IN      offset of the register (0..31)              */
/*  reg                  OUT     register                                    */
/*  status_1553          OUT     return code                                 */
/* @@                                                                        */
/*****************************************************************************/

status_1553 BI_ifSuMMITRTRegRead(unsigned int regId, unsigned int *reg )
{
    status_1553 ret_code = BI_OK;

    /* check register offset */
    if (regId >= NUM_OF_SUMMIT_REG)
    {
        ret_code = BI_OFFSET_ERROR;
    }
    else
    {
        *reg = *((unsigned int*)SUM_REG_ADRS + regId) >> 16;
    }
    return ret_code;
}

/*****************************************************************************/
/* @Function: BI_if1553BLoadMCMD                                             */
/* @Purpose :                                                                */
/* This routine loads a Macrocommand performing the low level check of the   */
/* MCMD Identifier, MCMD length, MCMD checksum                               */
/*                                                                           */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/*  subaddId             IN      Identifier of the descriptor block (0..255) */
/*  BI_1553MCMDBuffer    OUT     Buffer of the MCMD                          */
/*  BI_1553MCMDACKWord   OUT     Buffer of the Acknowledge word              */
/*  status_1553          OUT     return code                                 */
/* @@                                                                        */
/*****************************************************************************/
status_code BI_if1553BLoadMCMD( unsigned int subaddId,
                                unsigned short int* BI_1553MCMDBuffer,
                                unsigned short int* BI_1553MCMDACKWord )
{
  status_code    status;
  unsigned int   nwords16, nwords16exg, ttFlag;
  DESC_BLK       db;
  unsigned int   checksum, i;
  unsigned int   mcmdType,
                 mcmdId;
  unsigned char* pbyte;
  MsgTsk         sndMsg;
  MA_HEADER_MCMD mcmdHeader;
  int            mcmdttag_direct;
  TI_TIME        obtime;
  unsigned int*  pexg;
  
  
    status = SUCCESSFUL;
    
    BI_ifSuMMITRTDbGet( subaddId, &db );
    
    pexg = BI_ifSuMMITRTGetDataAddress( subaddId ); /* pexg points to the data area of RSA20 */
    
    nwords16 = nwords16exg = 0;

    if( db.currentAdrs > db.topAdrs )
    {
        nwords16    = db.currentAdrs - db.topAdrs;
        nwords16exg =(pexg[2]>>16) & 0x0FFF;
	ttFlag      =(pexg[1]>>31);
        
        /* checks the Identifier RS2-040 */
        mcmdId = (pexg[1]>>16) & 0xFF;

        MA_piGetMCMDType(mcmdId, &mcmdType);

        /* Verify MCMD identifier         */
        if( mcmdType == NULL_MCMD )
        {
            status = UNSATISFIED;
            BI_1553MCMDACKWord[0] |= BI_MCMD_NOT_OK | BI_MCMD_WRONG_IDENTIFIER;
        }
	else
	{
            /* verifies the words loaded      */
            if ( nwords16 != nwords16exg         ||  
	         nwords16 >  BI_MAX_MCMD_LENGTH  ||
		(ttFlag && nwords16 >  BI_MAX_TT_MCMD_LENGTH) ||
	         MA_piGetMCMDLenght(mcmdType,nwords16) != SUCCESSFUL)
            {
                 status = UNSATISFIED;
                 BI_1553MCMDACKWord[0] |= BI_MCMD_NOT_OK | BI_MCMD_WRONG_WORD_NUMBER;
            }
            else
            {
                BI_ifSuMMITRTPacketRead(subaddId, BI_1553MCMDBuffer, nwords16);
                if( BI_1553MCMDBuffer[1] & BI_MCMD_TT_MASK )
                {
                   BI_1553MCMDACKWord[0] |= BI_MCMD_IS_TIMETAGGED;
                }
                mcmdHeader.Type = mcmdType;

                // verifies the checksum
                checksum = 0;
                for (i=0, pbyte = (unsigned char*)BI_1553MCMDBuffer; i<2*(nwords16-1); pbyte++, i++)
                {
                   checksum += *pbyte;
                }
            
                if( (checksum & 0xFF) != (BI_1553MCMDBuffer[nwords16-1] & 0xFF) )
                {
                    status = UNSATISFIED;
                    BI_1553MCMDACKWord[0] |= BI_MCMD_NOT_OK | BI_MCMD_CHECKSUM_ERROR;
                }
            }
        }

    }
    else
    {
        status = UNSATISFIED;
        BI_1553MCMDACKWord[0] |= BI_MCMD_NOT_OK | BI_MCMD_WRONG_WORD_NUMBER;         
    }
    
    if( !(BI_1553MCMDACKWord[0] & BI_MCMD_NOT_OK) )
    {
        if( BI_1553MCMDBuffer[1] & BI_MCMD_TT_MASK )
        {
            mcmdHeader.TimeTag = BI_1553MCMDBuffer[3]<<16 | BI_1553MCMDBuffer[4];
            mcmdttag_direct = TIMETAG_MCMD;
            sndMsg.Code = MT_STORE_TIMETAG_MCMD;
        }
        else
        {
            mcmdHeader.TimeTag = 0;
            mcmdttag_direct = IMMEDIATE_MCMD;
            sndMsg.Code = MD_MCMD_EXEC;
        }

        mcmdHeader.Length = BI_1553MCMDBuffer[2] & 0x0FFF;
        
        //INFN_PATCH if( MA_piGetBufferMCMD(&mcmdHeader.PtrMCMD, mcmdttag_direct, WAIT, NO_TIMEOUT)
	    if( MA_piGetBufferMCMD(&mcmdHeader.PtrMCMD, mcmdttag_direct)
                              != SUCCESSFUL )
        {
            /* internal error: reject the MCMD */
            status = UNSATISFIED;
        }
        else
        {
            memcpy((unsigned short int*)mcmdHeader.PtrMCMD, BI_1553MCMDBuffer, 2*mcmdHeader.Length);
            *(MA_HEADER_MCMD*)sndMsg.Info = mcmdHeader;
            sndMsg.LlInfo = sizeof(MA_HEADER_MCMD);
            if( mcmdttag_direct == TIMETAG_MCMD )
            {
                status = MT_piSndMsgTTManager(&sndMsg);
                
                if( status == HA_E1_TIMETAG_NOT_ALLOWED)
                {
                    BI_1553MCMDACKWord[0] |= BI_MCMD_NOT_OK | BI_MCMD_WRONG_TIMETAG;
                    *(unsigned short int*)&sndMsg.Info[6] = status;
                    /* Extract parameters and delete MCMD from partition  */
                    //INFN_PATCH MA_piDelBufferMCMD(mcmdHeader.PtrMCMD,TIMETAG_MCMD,WAIT,NO_TIMEOUT);
		    MA_piDelBufferMCMD(mcmdHeader.PtrMCMD,TIMETAG_MCMD);
                }
                else if(status == HA_E1_MCMD_QUEUE_FULL )
                {
                    BI_1553MCMDACKWord[0] |= BI_MCMD_NOT_OK | BI_MCMD_TTQUEUE_FULL;
                    *(unsigned short int*)&sndMsg.Info[6] = status;
                    /* Extract parameters and delete MCMD from partition  */
		    //INFN_PATCH MA_piDelBufferMCMD(mcmdHeader.PtrMCMD,TIMETAG_MCMD,WAIT,NO_TIMEOUT);
                    MA_piDelBufferMCMD(mcmdHeader.PtrMCMD,TIMETAG_MCMD);
                }
            }
            else
            {
                status = MD_piSndMsgMCMDDispatcher(&sndMsg);
            }
        }
    }
    
    if( BI_1553MCMDACKWord[0] & BI_MCMD_NOT_OK )
      {

#warning do we want OBT in s or in ms ? if ms, russian must be warned ? TM was in s
        TI_piGetTimeInfo_s(&obtime);
        *(unsigned short int*)&sndMsg.Info[0] = HA_HEADER_E1 | mcmdId;
        *(unsigned short int*)&sndMsg.Info[2] = obtime >> 16;
        *(unsigned short int*)&sndMsg.Info[4] = obtime;
        sndMsg.Code   = HA_TRACEVENT;
        sndMsg.LlInfo = HA_SIZEW_E1;
                        
        if( BI_1553MCMDACKWord[0] & BI_MCMD_WRONG_IDENTIFIER )
        {
           *(unsigned short int*)&sndMsg.Info[6] = HA_E1_MCMD_ID_NOT_ALLOWED;
        }
        else if( BI_1553MCMDACKWord[0] & BI_MCMD_WRONG_WORD_NUMBER )
        {
           *(unsigned short int*)&sndMsg.Info[6] = HA_E1_MCMD_LENGHT_ERROR;
        }
        else if( BI_1553MCMDACKWord[0] & BI_MCMD_CHECKSUM_ERROR )
        {
           *(unsigned short int*)&sndMsg.Info[6] = HA_E1_MCMD_CHECKSUM_ERROR;
        }
        else if( BI_1553MCMDACKWord[0] & BI_MCMD_TTQUEUE_FULL )
        {
           *(unsigned short int*)&sndMsg.Info[6] = HA_E1_MCMD_QUEUE_FULL;
        }
        else /* ( BI_1553MCMDACKWord[0] & BI_MCMD_WRONG_TIMETAG )  */
        {
           *(unsigned short int*)&sndMsg.Info[6] = HA_E1_TIMETAG_NOT_ALLOWED;
        }
        HA_piSndMsgHistoryArea(&sndMsg);
    }

    return status;
}


/*****************************************************************************/
/* @Function: BI_if1553BWriteAck                                             */
/* @Purpose :                                                                */
/* This routine writes the acknowledge word to perform the MCMD protocol     */
/*                                                                           */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/*  subaddId             IN      subaddress of the ACK word  (TSA01)         */
/*  BI_1553MCMDACKWord      OUT     Buffer of the Acknowledge word           */
/*  subaddIdMCMD         OUT     MCMD subaddress                             */
/*  status_1553          OUT     return code                                 */
/* @@                                                                        */
/*****************************************************************************/
status_code BI_if1553BWriteAck( unsigned int subaddId,unsigned int subaddIdMCMD,
                                unsigned short int* BI_1553MCMDACKWord)
{
  status_code   status;
  unsigned int* pexg;
  unsigned int* pexgMCMD;

    status   = SUCCESSFUL;
    pexg     = BI_ifSuMMITRTGetDataAddress(subaddId);
    pexgMCMD = BI_ifSuMMITRTGetDataAddress(subaddIdMCMD);
    
    if ( pexg == (unsigned int*)0 )
    {
        status = UNSATISFIED;
    }
    else
    {
        BI_1553MCMDACKWord[0] |= pexgMCMD[1] << 8;
        BI_1553MCMDACKWord[1]  = pexgMCMD[0];
        pexg[0] = BI_1553MCMDACKWord[0];
        pexg[1] = BI_1553MCMDACKWord[1];

    }

    return (status);
}


/*****************************************************************************/
/* @Function: BI_if1553BWriteCCA                                             */
/* @Purpose :                                                                */
/* This routine writes the communication control word                        */
/*                                                                           */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/*  subaddId             IN      subaddress of the CCA (TSA03)               */
/*  BI_1553CCABuffer     OUT     Buffer of the CCA structure                 */
/*  BI_1553MCMDACKWord   OUT     Buffer of the Acknowledge word              */
/*  status_1553          OUT     return code                                 */
/* @@                                                                        */
/*****************************************************************************/
status_code BI_if1553BWriteCCA( unsigned int subaddId,
                                unsigned short int* BI_1553CCABuffer,
                                unsigned short int* BI_1553MCMDACKWord )
{
status_code    status;
unsigned int   *pexg, i;
TI_TIME        obt;
unsigned int   ssw;
FS_FILE_DESCR  fileInfo;
unsigned short size;
UINT16         IPMStatus;

    status = SUCCESSFUL;
    pexg = BI_ifSuMMITRTGetDataAddress(subaddId);

    if ( pexg == (unsigned int*)0 )
    {
        status = UNSATISFIED;
    }
    else
    {
      /* Get OBT                               */
      
      // TI_piGetTimeInfo(&obt);      
      TI_piGetCurrentMoscowTime_s(&obt);
        
	/* Get Status Word                       */
        RG_piGetSubStatusWord(&ssw);

      /* Get IPM Status */
	PWR_GetIPMStatus(&IPMStatus);


        /* File size resolution is 1 bit 8Mb     */
        /* (FileInfo.Size is 1 bit 4 bytes)      */
	//        FS_piGetFileInfo(FS_FILE1,&fileInfo);
        // size =(unsigned short)(((fileInfo.Size>>21)<<8) & 0x0000FF00);
        // FS_piGetFileInfo(FS_FILE2,&fileInfo);
        // size |=(unsigned short)((fileInfo.Size>>21) & 0x000000FF);
	
        FS_piGetFileInfo(FS_FILE1,&fileInfo);
	
	// size =(unsigned short)(((fileInfo.Size>>21)) & 0x000000FF);       
	// size |= (unsigned short)(((fileInfo.Size>>21)<<8) & 0x0000FF00);
	// Size in Megabyte
	size =(unsigned short)(((fileInfo.Size>>18)) & 0x0000FFFF);       
        
        /* Get INFN information                  */
        /* Function TBD                          */
        
        BI_1553CCABuffer[0]  =(unsigned short)(obt >> 16);
        BI_1553CCABuffer[1]  =(unsigned short)(obt & 0xffff);
        BI_1553CCABuffer[2]  =(unsigned short)(ssw & 0xffff);
        BI_1553CCABuffer[3]  =BI_1553MCMDACKWord[0];
        BI_1553CCABuffer[4]  =BI_1553MCMDACKWord[1];
        BI_1553CCABuffer[5]  =size;
        
        BI_1553CCABuffer[6]  = IPMStatus; // IPM STATUS
        BI_1553CCABuffer[7]  = 0; // GSStatus; // GAS SYSTEM: this must be zero as agreed in document protocol PAM. R1d1-346bis-04 (russian)
        BI_1553CCABuffer[8]  = 0;
        BI_1553CCABuffer[9]  = 0;
        BI_1553CCABuffer[10] = 0;
        BI_1553CCABuffer[11] = 0;     
        
	  
        /* Copy CCA words into 1553B area        */
        for (i=0; i<BI_MAX_CCA_VORDS; i++)
        {
           *pexg++ = BI_1553CCABuffer[i];
        }
    }

    return status;
}



/*****************************************************************************/
/* @Function: BI_if1553BWriteSSW                                             */
/* @Purpose :                                                                */
/* This routine writes the status word                                       */
/*                                                                           */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/*  subaddId             IN      subaddress of the SSW (TSA02)               */
/*  status_1553          OUT     return code                                 */
/* @@                                                                        */
/*****************************************************************************/
status_code BI_if1553BWriteSSW( unsigned int subaddId )
{
  status_code     status = SUCCESSFUL;
  unsigned int*   pexg;
  unsigned int    ssw;

    pexg = BI_ifSuMMITRTGetDataAddress(subaddId);

    if ( pexg == (unsigned int*)0 )
    {
        status = UNSATISFIED;
    }
    else
    {
        RG_piGetSubStatusWord(&ssw);
        *pexg = ssw;
    }

    return status;
}
