/****************************************************************************
/*  F i l e   D a t a                                                        
/*                                                                           
/*  Module       : BasicSW                                                   
/*  C.I. No.     :                                                           
/*  $Revision: 1.26 $
/*  $Date: 2005/02/21 08:58:28 $
/*  Belonging to :                                                           
/*               :                                                           
/*  $RCSfile: TI_TimingInfo_op.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: sebastiani $
/*               :                                                           
/****************************************************************************
/*  U p d a t i n g                                                          
/*                                                                           
/*  $Log: TI_TimingInfo_op.c,v $
/*  Revision 1.26  2005/02/21 08:58:28  sebastiani
/*  all log comments completed
/*
/*  Revision 1.25  2005/02/19 10:16:47  sebastiani
/*  disable GPT
/*
/*  Revision 1.24  2005/01/26 18:46:26  sebastiani
/*  *** empty log message ***
/*
/*  Revision 1.23  2004/09/17 15:01:00  faber
/*  LU_INFN_LOG flags fixing
/*
/*  Revision 1.22  2004/09/08 10:39:12  faber
/*  *** empty log message ***
/*
/*  Revision 1.21  2004/08/26 16:54:01  sebastiani
/*  fix some bug
/*
/*  Revision 1.20  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.19  2004/07/08 16:23:35  sebastiani
/*  *** empty log message ***
/*
/*  Revision 1.18  2004/05/27 17:50:38  sebastiani
/*  *** empty log message ***
/*
/*  Revision 1.17  2004/05/07 08:01:05  faber
/*  *** empty log message ***
/*
/*  Revision 1.16  2004/05/06 15:50:57  faber
/*  GetTimeSyncInfo introduced
/*
/*  Revision 1.15  2004/04/29 07:11:43  faber
/*  pached GetOrbitOffset
/*
/*  Revision 1.14  2003/12/04 17:16:08  sebastiani
/*  GS debug/tests, and other
/*
/*  Revision 1.13  2003/12/01 09:27:16  sebastiani
/*  CCA info for Gas Module and first implementation of IPM infos.
/*
/*  Revision 1.12  2003/11/18 17:13:15  sebastiani
/*  GPT enabled to print a "\n" every 60s directly on UART, only to check if the CPU is
/*  alive
/*
/*  Revision 1.11  2003/11/04 11:36:35  alfarano
/*  deleted task in TM_TMTC manager and added to HK_Manager, added KHB buffer read task
/*
/*  Revision 1.10  2003/10/30 16:10:48  faber
/*  GPT disabled. the callback function is a null function
/*
/*  Revision 1.9  2003/10/21 16:09:12  alfarano
/*  LU_LOG_INFN replacement for all remaining original log functions
/*
/*  Revision 1.8  2003/09/15 09:20:23  faber
/*  GTP function modification for simulator mode (TimedFunction)
/*
/*  Revision 1.7  2003/09/12 10:52:56  faber
/*  introduced PTH_VAR_TC_CYC_RATE
/*
/*  Revision 1.6  2003/09/10 16:15:51  faber
/*  PRH_EXTERN_VAR(XX_LOGMASK) removed (not needed any more)
/*
/*  Revision 1.5  2003/09/10 11:55:07  faber
/*  LU_MASK introduced. Log mask for module is now an unique array (PRH_ARR_LOG_MASK) indexed by __FILEID__
/*
/*  Revision 1.4  2003/08/29 11:13:30  faber
/*  TI_StartTimerMoscowTime  introduced
/*
/*  Revision 1.3  2003/08/28 10:11:44  faber
/*  New timer management. GPT is now possible to be disabled. (DisableGPT,EnableGPT)
/*  GetTimeInfo now use the RTEMS clock instead reading the TI_SystemTime.
/*  GetTimeInfo now returns seconds, instead of milliseconds.
/*
/*  Revision 1.2  2003/08/22 07:47:35  sebastiani
/*  Timer behavior change: TYME_SYNC / OBT_ORBIT / OBT introduced.
/*  TymeSync MCMD now doesn't affect OBT (TI_SystemTime) any more
/*
/*  Revision 1.1.1.1  2003/08/04 09:40:21  sebastiani
/*  Imported sources laben rel. 19.06.2003 integrated with pam2
/*
/*  Revision 1.2  2003/06/18 16:53:19  sebastiani
/*  Pam/Run Manager development update. ExpSeq sequence is receiven from the RunManager (simulator mode)
/*
/*  Revision 1.1.1.1  2003/05/27 08:13:24  wizard
/*  Import of the Official Laben CD Release Software as the  pamela-EM_delivery_20030521_1454.tar.bz2
/*
/*  Revision 1.9  2003/01/30 09:43:49  aurora
/*  introduced ifdef for EM and FM
/*
/*  Revision 1.8  2002/11/14 09:46:42  zulia
/*  removed unsed status variable
/*
/*  Revision 1.7  2002/09/11 15:34:17  zulia
/*  comment
/*
/*  Revision 1.6  2002/05/09 08:16:34  zulia
/*  *  acceptance release
/*
/*                                                                           
/*****************************************************************************/


/*============================= Include File ================================*/
#include <src/INFN/LU_SourceFileID_INFN.h>
#define __FILEID__ _TI_TimingInfo_op__c
#include <src/INFN/PRH_ParamHandler_INFN_auto.h>
#include <src/INFN/PRH_ParamHandler_INFN.h>
#include <src/INFN/LU_LogUtility_INFN.h>

LU_DECL_MASK();


#include <src/INFN/OS_rtems_INFN_p.h>


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

//##FS 17.6.03
#ifdef SIMULATOR
#include <src/INFN/PM_PamManager_INFN.h>
#endif
//##FS END 17.6.03

/*****************************************************************************/
/*============================= Object variables ============================*/


/*****************************************************************************/
/* @Variable: TI_ObtTimeSync                                                 */
/* @Purpose :                                                                */
/*   TI_TIME type                                                            */
/*   is the OBT in the moment in which the Time Sync MCMD arrived.           */
/*   if zero, means not set.                                                 */
/*   in milliseconds                                                         */
/* @@                                                                        */
/*****************************************************************************/
static TI_TIME        TI_ObtTimeSync_s;
static TI_TIME        TI_ObtTimeSync_ms;

volatile static BOOL TimeSyncExtInt_enabled = FALSE;

/*****************************************************************************/
/* @Variable: TI_TimeSync                                                    */
/* @Purpose :                                                                */
/*   TI_TIME type                                                            */
/*   is the "Moscow Time" arrived by the MCMD                                */
/*   if zero, means not set.                                                 */
/*   in      seconds                                                         */
/* @@                                                                        */
/*****************************************************************************/
static TI_TIME        TI_TimeSync_s;



/*****************************************************************************/
/* @Variable: TI_ObtOrbit                                                    */
/* @Purpose :                                                                */
/*   TI_TIME type                                                            */
/*   is the OBT in the moment of the Ascending Node (CALIBRATE MCMD)         */
/*   To know the tim of the (last) ascending node, calculate:                */
/*   OBT - ObtOrbit                                                          */
/*   zero means not set.                                                     */
/*   in seconds                                                              */
/* @@                                                                        */
/*****************************************************************************/
static TI_TIME        TI_ObtOrbit_s;



/*****************************************************************************/
/* @Variable: TI_TimeSyncCounter                                             */
/* @Purpose :                                                                */
/*   unsigned int type                                                       */
/*   store the number times the TimeSync MCMD was received.                  */
/*   if zero means that the Time Sync                                        */
/*   MCMD has never arrived (in this case time-variables should be TI_UNSET).*/
/*   in seconds                                                              */
/* @@                                                                        */
/*****************************************************************************/
static unsigned int TI_TimeSyncCounter;

/*===========================================================================*/



/* External Parameters */

/*****************************************************************************/

/*===== T i m i n g I n f o   O P E R A T I O N A L   F U N C T I O N S =====*/

/*****************************************************************************/
/* @Function: TI_opInitTimingInfo                                            */
/* @Purpose :                                                                */
/*  The function performs the following initialization:                      */
/*  - Establishes an ISR for ERC 32 General Purpos Timer (GPT).              */
/*  - Initializes the GPT Scaler and Couter.                                 */
/*  - Initializes global object variables.                                   */
/*                                                                           */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/* @@                                                                        */
/*****************************************************************************/

status_code TI_opInitTimingInfo (void)
{
  status_code status;
  void*       OldHandler;

  /* the rtems epoch is  01.01.1988 00:00 */
  static rtems_time_of_day epoch = {1988,1,1,0,0,0,0};

/*===========================================================================*/
    /*================ GENERAL PURPOSE TIMER (ERC32) ========================*/
    /*
    status =OS_piIsrCatch ( TI_opNull,
                            ERC32_INTERRUPT_GENERAL_PURPOSE_TIMER+0x10,
                            &OldHandler);
    */
#if TI_GPT_ENABLED
    status =OS_piIsrCatch ( TI_ihTimingInfo,
                            ERC32_INTERRUPT_GENERAL_PURPOSE_TIMER+0x10,
                            &OldHandler);
    
    if (status==SUCCESSFUL)
    {
        /*==== INIT OF THE GENERAL PURPOSE TIMER (ERC32) ====================*/
        ERC32_MEC.General_Purpose_Timer_Counter =TI_GPT_COUNTER_VALUE*1000*5;
        ERC32_MEC.General_Purpose_Timer_Scalar  =TI_GPT_SCALER_VALUE;
        ERC32_MEC_Set_General_Purpose_Timer_Control( 
                    ERC32_MEC_TIMER_COUNTER_RELOAD_AT_ZERO  |
                    ERC32_MEC_TIMER_COUNTER_LOAD_COUNTER    |
                    ERC32_MEC_TIMER_COUNTER_ENABLE_COUNTING |
                    ERC32_MEC_TIMER_COUNTER_LOAD_SCALER);
	TI_opEnableGPT();
    }
    else
    {
        /* ISR not successfully established  */
        // LOG_INFN HA_piLogHistoryEntry10(HA_E10_SW_TI,HA_E10_INT_CATCH_ERR,status);        
      /*@LOG Isr not successfully enstablisched - status */
	LU_INFN_LOG(LU_FATAL|LU_HA,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
    }
#else
    TI_opDisableGPT();
#endif
/*===========================================================================*/
    /*=================== SYSTEM TIME INITIALIZATION ========================*/


    TI_ObtTimeSync_s   =TI_UNSET; 
    TI_ObtTimeSync_ms  =TI_UNSET;
    TI_TimeSync_s      =TI_UNSET;
    TI_ObtOrbit_s      =TI_UNSET;
    TI_TimeSyncCounter = 0;
    
    /* init the RTEMS system clock to the RTEMS epoch: */
    status = rtems_clock_set(&epoch);
    if(status)
      /*@LOG invalid time of day - statys */
      LU_INFN_LOG(LU_FATAL|LU_HA,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
    return (status);
}



/*****************************************************************************/
/* @Function: TI_OBT                                                         */
/* @Purpose :                                                                */
/*  Get the OBT using the rtems clock. The function returns the number of    */
/*  seconds since bootstrap (pamela initialization)                          */
/*****************************************************************************/

static TI_TIME TI_OBT_s() {
  rtems_interval sse;
  rtems_clock_get(RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH,&sse);
  /* TI_TIME is unsigned long (uint32). rtems_interval is unsigned32 too. */
  return sse;
}

static TI_TIME TI_OBT_ms() {
  rtems_clock_time_value t;
  rtems_clock_get(RTEMS_CLOCK_GET_TIME_VALUE,&t);
  return (t.seconds*1000)+(t.microseconds/1000);
}

void TI_opDisableGPT() {
  ERC32_Mask_interrupt( ERC32_INTERRUPT_GENERAL_PURPOSE_TIMER );  
}


void TI_opEnableGPT() {
  ERC32_Unmask_interrupt( ERC32_INTERRUPT_GENERAL_PURPOSE_TIMER );  
}


/*****************************************************************************/
/* @Function: TI_opTimingOperation                                           */
/* @Purpose :                                                                */
/*  The function implements the OBT interrupt handler.  The interrupt rate   */
/*  is every 1 ms. The function provides for the following actions:          */
/*  - Increment the variable TI_SystemTime (OBT).                            */
/*  - Decrement the Monitoring counter, and whenever this counter goes to    */
/*    zero (every second) send a message to Monitoring to start parameters   */
/*    check.                                                                 */
/*  - Send message to TTMANAGER every 128 ms  for MCMD timetag.              */
/*    check.                                                                 */
/*                                                                           */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/* @@                                                                        */
/*****************************************************************************/

void TI_opNull(void) {
  return;
}

void TI_opTimingOperation (void)
{
  // MsgTsk      SndMsg;
  static unsigned int t=0;
  t++;
  console_outbyte_polled(0,'-'); 
  console_outbyte_polled(0,'0'+t%10);
  console_outbyte_polled(0,'\n'); 
  LU_UART_CR('-');
#ifdef SIMULATOR
  PM_SendTestCommand(105,0,0,0,0);
#endif
  /*
  if(TI_SystemTime == MAX_SYSTEM_TIME) {
    TI_SystemTimeRestart++;      
    TI_SystemTime=1;
    LU_INFN_LOG(LU_WARNING,LU_MASK(__FILEID__),__FILEID__,__LINE__,TI_SystemTimeRestart );
    }
  */
}


/*****************************************************************************/
/* @Function: TI_opGetTimeInfo                                               */
/* @Purpose :                                                                */
/*  The function returns the On Board Time (OBT) information.                */
/*                                                                           */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/*                      IN                                                   */
/* status_code          OUT     Return code                                  */
/* @@                                                                        */
/*****************************************************************************/


void TI_opGetTimeInfo_s (TI_TIME* Time)
{
  *Time = TI_OBT_s();
}

void TI_opGetTimeInfo_ms (TI_TIME* Time)
{
  *Time = TI_OBT_ms();
}


status_code TI_opResourceObtain() {
  status_code s;
  if(rtems_interrupt_is_in_progress())
    return TI_SUCCESSFUL; 
  s=OS_piResourceObtain(TI_RES,WAIT,NO_TIMEOUT);
  if(s != SUCCESSFUL) {
    /*@LOG TI_opResourceObtain(): error - status */
    LU_INFN_LOG(LU_CRITICAL|LU_HA,LU_MASK(__FILEID__),__FILEID__,__LINE__,s);
    s=TI_RESERROR;
  }else
    s=TI_SUCCESSFUL;
  return s;
}

status_code TI_opResourceRelease() {
  status_code  s;  
  if(rtems_interrupt_is_in_progress())
    return TI_SUCCESSFUL; 
  s=OS_piResourceRelease(TI_RES);
  if(s != SUCCESSFUL) {
    /*@LOG TI_opResourceRelease(): error - status */
    LU_INFN_LOG(LU_CRITICAL|LU_HA,LU_MASK(__FILEID__),__FILEID__,__LINE__,s);
    s=TI_RESERROR;
  }else
    s=TI_SUCCESSFUL;
  return s;
}



void TI_opSetObtTimeSync(TI_TIME ms,BOOL enable_next) {
  UINT32 intLevel;
  OS_PROTECTED_INT(intLevel,
		   do {
		     if(TimeSyncExtInt_enabled) {
		       TI_ObtTimeSync_ms = ms;
		       TI_ObtTimeSync_s = ms / 1000;
		       TimeSyncExtInt_enabled = enable_next;
		     }
		   } while(0)
		   );
}


void TI_opTimeSyncExtInterrupt() 
{
  volatile BOOL doit;
  UINT32 intLevel;
  OS_PROTECTED_INT(intLevel,doit = TimeSyncExtInt_enabled);
  if(doit) 
    TI_opSetObtTimeSync(TI_OBT_ms(),FALSE);
}

/*****************************************************************************/
/* @Function: TI_opUpdateTimeInfo                                            */
/* @Purpose :                                                                */
/*  The function updates the Time Information when a TimeSync MCMD arrive.   */
/*                                                                           */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/* Time                 IN      The "Moscow Time" in seconds                 */
/* @@                                                                        */
/*****************************************************************************/
void TI_opUpdateTimeInfo_s (TI_TIME  Time)
{
  UINT32 intLevel;
  OS_PROTECTED_INT(intLevel,TimeSyncExtInt_enabled = TRUE);

  if( (TI_opResourceObtain()) == SUCCESSFUL) {
    TI_TimeSyncCounter++;
    TI_TimeSync_s = Time;
    /* this is incorrect, but it will fix if the interrupt will not come: */
    TI_opSetObtTimeSync(TI_OBT_ms(),TRUE);
    OS_PROTECTED_INT(intLevel,TimeSyncExtInt_enabled = TRUE);
  }
  TI_opResourceRelease();
  

}



/*****************************************************************************/
/* @Function: TI_GetTimeSyncInfo                                             */
/* @Purpose :                                                                */
/*  The function return the time sync infos stored wten the time sync arrived*/
/*  if info is not available, put 0 into both output params and return error */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/* OBT                  OUT      OBT at the moment of the TSYNC              */ 
/* TimeSync             OUT      MoscowTime arrived                          */
/* @@                                                                        */
/*****************************************************************************/


status_code  TI_opGetTimeSyncInfo_s(TI_TIME *obt_ts,TI_TIME *ts) {
  status_code status;
  volatile TI_TIME TI_ObtTimeSync_s_local;
  UINT32 intLevel;
  if( (status=TI_opResourceObtain()) == SUCCESSFUL) {
    if(TI_TimeSyncCounter > 0) {
      OS_PROTECTED_INT(intLevel,TI_ObtTimeSync_s_local = TI_ObtTimeSync_s);
      *obt_ts = TI_ObtTimeSync_s_local;
      *ts  = TI_TimeSync_s;
      status=TI_SUCCESSFUL;
    } else {
      status=TI_NOTIMESYNC;
      *obt_ts = 0;
      *ts  = 0;
    }
  }
  if(TI_opResourceRelease() == TI_RESERROR)
    status = TI_RESERROR;
  return status;
}

/*****************************************************************************/
/* @Function: TI_GetTimeSyncOffset                                           */
/* @Purpose :                                                                */
/*  The function return the TIME_SYNC_OFFSET that is TI_OBT -         */
/*  TI_ObtTimeSync.                                                          */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/* Time                 IN      The "Moscow Time" in seconds                 */
/* @@                                                                        */
/*****************************************************************************/

status_code  TI_opGetTimeSyncOffset_s(TI_TIME *t) {
  status_code status;
  volatile TI_TIME TI_ObtTimeSync_s_local;
  UINT32 intLevel;
  if( (status=TI_opResourceObtain()) == SUCCESSFUL) {
    if(TI_TimeSyncCounter > 0) {
      OS_PROTECTED_INT(intLevel,TI_ObtTimeSync_s_local = TI_ObtTimeSync_s);
      *t = TI_OBT_s() - TI_ObtTimeSync_s_local;
      status=TI_SUCCESSFUL;
    } else 
      status=TI_NOTIMESYNC;
  }
  if(TI_opResourceRelease() == TI_RESERROR)
    status = TI_RESERROR;
  return status;
}


/*****************************************************************************/
/* @Function: TI_GetCurrentMoscowTime                                        */
/* @Purpose :                                                                */
/*  The current moscow time is the TimeSync plus the "time sync offset",     */
/*  that is TI_OBT - TI_ObtTimeSync                                          */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/* t                    OUT     The "Moscow Time" in seconds                 */
/* @@                                                                        */
/*****************************************************************************/

status_code TI_opGetCurrentMoscowTime_s(TI_TIME *t) {
  status_code status;
  volatile TI_TIME TI_ObtTimeSync_s_local;
  UINT32 intLevel;
  if( (status=TI_opResourceObtain()) == SUCCESSFUL) {
    if(TI_TimeSyncCounter != 0) {
      OS_PROTECTED_INT(intLevel,TI_ObtTimeSync_s_local = TI_ObtTimeSync_s);
      *t = TI_TimeSync_s + (TI_OBT_s() - TI_ObtTimeSync_s_local);
      status=TI_SUCCESSFUL;
    } else {
      *t = 0;
      status=TI_NOTIMESYNC;
    }
  }
  if(TI_opResourceRelease() == TI_RESERROR)
    status = TI_RESERROR;
  return status;
}


/*****************************************************************************/
/* @Function: TI_TimeSyncIsAvailable                                         */
/* @Purpose :                                                                */
/*  The information of the TimeSync is available if UpdateTimeInfo has called*/
/*  at least one time, that means a TimeSync MCMD was coming.                */
/*  if TI_TimeSyncCounter == 0, then the information is not available.       */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/* t                    OUT     The "Moscow Time" in seconds                 */
/* @@                                                                        */
/*****************************************************************************/

status_code TI_opTimeSyncIsAvailable(BOOL* avail) {
  status_code status;
  if( (status=TI_opResourceObtain()) == SUCCESSFUL) {
    *avail = (TI_TimeSyncCounter != 0);
  }
  if(TI_opResourceRelease() == TI_RESERROR)
    status = TI_RESERROR;
  return status;
}


/*****************************************************************************/
/* @Function: TI_SetObtOrbit                                                 */
/* @Purpose :                                                                */
/*  The TI_ObtOrbit is defined to be the OBT (TI_OBT) in the moment          */
/*  of the ascending node. This function sets the TI_ObtOrbit properly  and  */
/*  it sshould be called only when the                                       */
/*  ascending node MCMD (CALIBRATE) cames.                                   */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/* t                    OUT     The "Moscow Time" in seconds                 */
/* @@                                                                        */
/*****************************************************************************/

status_code TI_opSetObtOrbit_s() {
  status_code status;
  if( (status=TI_opResourceObtain()) == SUCCESSFUL) {
    TI_ObtOrbit_s = TI_OBT_s();
  }
  if(TI_opResourceRelease() == TI_RESERROR)
    status = TI_RESERROR;
  return status;
}

status_code TI_opGetObtOrbit_s(TI_TIME* t) {
  status_code status;
  if( (status=TI_opResourceObtain()) == SUCCESSFUL) {
    if(TI_ObtOrbit_s != TI_UNSET) {
      *t=TI_ObtOrbit_s;
      status=TI_SUCCESSFUL;
    }else
      status=TI_NOORBIT;
  }
  if(TI_opResourceRelease() == TI_RESERROR)
    status = TI_RESERROR;
  return status;
}

/*****************************************************************************/
/* @Function: TI_GetOrbitOffset                                              */
/* @Purpose :                                                                */
/*  The Orbit Offset is the time in seconds elapsed since the last ascendind */
/*  node (CALIBRATE) MCMD                                                    */
/*  that is TI_OBT-TI_ObtOrbit                                               */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/* @@                                                                        */
/*****************************************************************************/

status_code TI_opGetOrbitOffset_s(TI_TIME *t) {
  status_code status;
  if( (status=TI_opResourceObtain()) == SUCCESSFUL) {
    if(TI_ObtOrbit_s != TI_UNSET) {
      *t = TI_OBT_s() - TI_ObtOrbit_s;
      status=TI_SUCCESSFUL;
    }else
      status=TI_NOORBIT;
  }
  if(TI_opResourceRelease() == TI_RESERROR)
    status = TI_RESERROR;
  return status;
}


/*****************************************************************************/
/* @Function: TI_StartTimerMoscowTime                                        */
/* @Purpose :                                                                */
/*  This function is a wrapper of the OS_StartTimer_INFN function.           */
/*  but the time info is expressed in absolute MoscowTime.                   */
/*  the function computes the remaining time before the event,               */
/*  if the time is elapled (belong into the past, the function return        */
/*  TI_ELAPSED                                                               */
/*  if the OS_StartTimer returns an error, its logged and return             */
/*  TI_TIMERERROR                                                            */
/*  this function cannot be called into an ISR becasue the semaphore         */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/* t                    OUT     The "Moscow Time" in seconds                 */
/* @@                                                                        */
/*****************************************************************************/
status_code TI_opStartTimer_INFN_MoscowTime_s(unsigned int   Tim,TI_TIME   Time,void*     Routine,void*     UserData) {
  status_code status;
  TI_TIME now,after;
  status = TI_opGetCurrentMoscowTime_s(&now);
  if(status == TI_SUCCESSFUL) {
    if(now > Time) /* time is elapsed */
      status = TI_ELAPSED;
    else {
      after = Time - now;
      status = OS_piStartTimer_INFN (Tim,after,Routine,UserData);
      if (status != SUCCESSFUL) {
	/*@LOG StartTimer_INFN error - status */
	LU_INFN_LOG(LU_CRITICAL|LU_HA,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
	status=TI_TIMERERROR;
      }
    }
  }
  return status;
}
