/*============================= Include File ================================*/


#include <src/INFN/LU_SourceFileID_INFN.h>
#define __FILEID__ _GS_Gas_INFN__c
#include <src/INFN/PRH_ParamHandler_INFN.h>
#include <src/INFN/LU_LogUtility_INFN.h>
#include <src/INFN/PRH_ParamHandler_INFN_auto.h>
LU_DECL_MASK();
#include <src/INFN/CM_Common_INFN.h>
#include <src/INFN/GS_Gas_INFN.h>
#include <src/INFN/CH_CommandHandler_INFN.h>
#include <src/INFN/RM_RunManager_INFN.h>
#include <src/INFN/HB_HKBuffer_INFN.h>
#include <src/INFN/HK_Manager_INFN.h>
#include <src/INFN/KHB_Driver_INFN.h>
/*============================ External define ================================*/
// dont compile GAS
#ifdef GS_COMPILE
/*============================ Global define ================================*/

static BYTE GS_GasType;

// HOT , COLD

static GS_GasStruct GS_GasParam[2] = {{TM_VCB_STANDBY_ON,TM_GAS_HOT_OFF},{TM_VCB_STANDBY_ON,TM_GAS_COLD_OFF}};

static GS_LOOKUP_RAW_STRUCT GS_LookUp[GS_MAXMODE] = {};

// save the last operative command sent to Gas 
static GS_COMMAND GS_LastGasCommand;

// gas status mode 
static GS_MODE GS_Mode; 
static UINT16 GS_CCAGasMode;
static UINT32 GS_TaskSuspended;
static UINT32 GS_LocalCommandCounter;

PRH_EXTERN_VAR(GS_T0);
PRH_EXTERN_VAR(GS_T1);
PRH_EXTERN_VAR(GS_T2);
PRH_EXTERN_VAR(GS_TB);

status_code GS_Init() 
{
  GS_SetGasType(GS_HOT);
  GS_InitGasManager();
  //*(unsigned long long*)&GS_LastGasCommand = 0x000C07FF80000100LL;
  *(unsigned long long*)&GS_LastGasCommand = 0xFFFFFFFFFFFFFFFFLL;
  GS_Mode = GS_PARKING;
  GS_CCAGasMode = 0;
  GS_LocalCommandCounter = 0; 
 
  return CM_RC_SUCCESSFUL;
}

status_code GS_GasGetLookUp(GS_LOOKUP_RAW_STRUCT **raw)
{
  *raw = &GS_LookUp[GS_Mode];
  return CM_RC_SUCCESSFUL;
}

status_code GS_InitGasBoard() 
{
  status_code status;
  
  status = GS_COMOptNewT0(PRH_VAR_GS_T0);
  if (!status)
    {
      status = GS_COMOptNewT1(PRH_VAR_GS_T1);
      if (!status)
	{
	  status = GS_COMOptNewT2(PRH_VAR_GS_T2);
	  if (!status)
	    status = GS_COMOptNewB(PRH_VAR_GS_TB);
	}
    }
  return status;
}

int ConvertToSec(int label)
{
  int ret; 

  switch(label)
    {
    case GS_FRMIN15: ret = 15*60; break;
    case GS_FRMIN30: ret = 30*60; break;
    case GS_FRMIN60: ret = 60*60; break;
    case GS_FRMIN90: ret = 90*60; break;
    case GS_FRMIN120: ret = 120*60; break;
    case GS_FRSEC70:  ret = 70; break;
    case GS_FRSEC120: ret = 120; break;
    case GS_FRSEC180: ret = 180; break;
    case GS_FRSEC300: ret = 300; break;
    }

  return(ret);
}

status_code GS_FormatGasCommand(GS_COMMAND *command,UINT32 root,UINT32 flag_root,UINT32 flag_com,UINT32 error_state)
{
  command->root = root;
  command->flag_root = flag_root;
  command->flag_command = flag_com;
  command->error_state = error_state; 
  command->notused = 0;
  
  return CM_RC_SUCCESSFUL;
}

status_code GS_GasSendCommand(GS_COMMAND *combuf,GS_REPLY_STRUCT *reply)
{
  rtems_event_set evout;
  GS_REPLY_STRUCT outbuf;
  UINT32 last_com;
  status_code status;
  int i,recover;
  
  i = 0; recover = 0;
  
 RETRY:
  
  do 
    {
      status = HK_KHB_Cmd2FE(KHB_GAS_SYSTEM,GS_COMMAND_SIZE,GS_REPLY_SIZE,(UINT16*)combuf,(UINT16*)&outbuf,GS_BOARD_TIMEOUT);
            
      // in case of CM_RC_GS_BAD_COMMAND,CM_RC_GS_MISMATCH_COMMAND command is sent max 3 times
      
      if (!status)
	if (outbuf.valid == GS_GOOD_COMMAND)
	  {
	    if (reply != NULL)
	      *reply = outbuf;
	    
	    if ((combuf->root != GS_REQUEST) && (combuf->root != GS_ABORT))
	      {
		GS_LastGasCommand = *combuf;
		GS_LocalCommandCounter++;
	      }
	    
	    last_com = ((*(UINT32*)&GS_LastGasCommand) & 0x003FFFFF) >> 2;
	    
	    if ((last_com != 0xfffff) && (outbuf.command != last_com)) 
	      status =  CM_RC_GS_MISMATCH_COMMAND;                           /* executed command is not what is expected */                   
	    
	    if (outbuf.cont > GS_LocalCommandCounter) 
	      {
		// TDB 
		LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,(UINT16)outbuf.cont);
		LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,GS_LocalCommandCounter);
		GS_LocalCommandCounter = outbuf.cont;          /* temporaneo */
	      }
     	    
	    if (outbuf.err_fpga)                               /* err_fpga bit is set */
	      {
		// TDB
		LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
	      }
	  }
	else
	  status = CM_RC_GS_BAD_COMMAND;                 /* Bad command from Gas System FPGA */
      
      i++;
      
    } while ((i < 3) && status);
  
  if ((i == 3) && status)
    {
      i = 0;
      switch(recover)
	{
	case 0:
	  //status = HK_KHB_SoftReset(RST_GAS_SYSTEM);      /* first attempt : reset FE */
	  GS_LocalCommandCounter = 0;
	  break;
	case 1:
	  HK_KHB_HardReset();
	  //status = HK_KHB_SoftReset(RST_GAS_SYSTEM);      /* second attempt : reset Kayser and reset FE */
	  GS_LocalCommandCounter = 0;
	  break;
	case 2:
	  break;
	case 3:
	  break;
	}
      
      recover++; 
      LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
    }
  
  if (recover && (recover < 4) && !status)
    goto RETRY;
    
  LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
  
  return(status);
}

status_code GS_SetGasType(BYTE kind)
{
  GS_GasType = kind;
  return(CM_RC_SUCCESSFUL);
}

status_code GS_COMRequest(GS_REPLY_STRUCT *outbuf)
{
  GS_COMMAND combuf;
  status_code status;    
  
  GS_FormatGasCommand(&combuf,GS_REQUEST,GS_FRNULL,GS_FCNULL,GS_NO_ERR);
  status = GS_GasSendCommand(&combuf,outbuf);  

  LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
  
  return(status);
}

status_code GS_COMFillBuffer10cc(UINT32 sector)
{
  GS_COMMAND combuf;
  status_code status;

  GS_FormatGasCommand(&combuf,GS_FILL_BUFFER,GS_CC10,sector,GS_NO_ERR);
  status = GS_GasSendCommand(&combuf,NULL);
  LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);

  return(status);
}

status_code GS_COMFillBuffer10ccAllSector()
{
  GS_COMMAND combuf;
  status_code status;
  
  GS_FormatGasCommand(&combuf,GS_FILL_BUFFER,GS_CC10,GS_FCNULL,GS_NO_ERR);
  status = GS_GasSendCommand(&combuf,NULL);
  LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
  
  return(status);
}

status_code GS_COMFillBuffer125cc()
{
  GS_COMMAND combuf;
  status_code status;
  
  GS_FormatGasCommand(&combuf,GS_FILL_BUFFER,GS_CC125,GS_FCNULL,GS_NO_ERR);
  status = GS_GasSendCommand(&combuf,NULL);
  LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
  
  return(status);
}


status_code GS_COMEnAlarm(UINT32 mode)
{
  GS_COMMAND combuf;
  status_code status;
  
  GS_FormatGasCommand(&combuf,GS_EN_ALLARM,mode,GS_FCNULL,GS_NO_ERR);
  status = GS_GasSendCommand(&combuf,NULL);
  LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);

  return(status);
}

status_code GS_COMPurge(UINT32 flag_root,UINT32 flag_command,UINT32 kind)
{
  GS_COMMAND combuf;
  status_code status;
  
  if (kind == GS_OLD)
    GS_FormatGasCommand(&combuf,GS_PURGE,flag_root,flag_command,GS_NO_ERR);
  else
    GS_FormatGasCommand(&combuf,GS_PURGE_NEW,flag_root,flag_command,GS_NO_ERR);
  
  status = GS_GasSendCommand(&combuf,NULL);
  LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
  
  return(status);
}

status_code GS_COMOptPurge(UINT32 flag_root)
{
  GS_COMMAND combuf;
  status_code status;

  GS_FormatGasCommand(&combuf,GS_OPT_PURGE,flag_root,GS_FCNULL,GS_NO_ERR);
  status = GS_GasSendCommand(&combuf,NULL);
  LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);

  return(status);
}

status_code GS_COMAbort()
{
  GS_COMMAND combuf;
  status_code status;

  GS_FormatGasCommand(&combuf,GS_ABORT,GS_FRNULL,GS_FCNULL,GS_NO_ERR);
  status = GS_GasSendCommand(&combuf,NULL);
  LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
    
  return(status); 
}


status_code GS_COMMascValv(UINT32 valveno)
{
  GS_COMMAND combuf;
  status_code status;

  GS_FormatGasCommand(&combuf,GS_MASC_VALV,valveno,GS_FCNULL,GS_NO_ERR);
  status = GS_GasSendCommand(&combuf,NULL);
  LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
    
  return(status); 
}

status_code GS_COMMascSog(UINT32 thresoldno)
{
  GS_COMMAND combuf;
  status_code status;

  GS_FormatGasCommand(&combuf,GS_MASC_SOG,thresoldno,GS_FCNULL,GS_NO_ERR);
  status = GS_GasSendCommand(&combuf,NULL);
  LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
    
  return(status); 
}

status_code GS_COMOpen(UINT32 valves,UINT32 sector)
{
  GS_COMMAND combuf;
  status_code status;

  GS_FormatGasCommand(&combuf,GS_OPEN_VALV,valves,sector,GS_NO_ERR);
  status = GS_GasSendCommand(&combuf,NULL);
  LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
  
  return(status); 
}

status_code GS_COMClose(UINT32 valves,UINT32 sector)
{
  GS_COMMAND combuf;
  status_code status;

  GS_FormatGasCommand(&combuf,GS_CLOSE_VALV,valves,sector,GS_NO_ERR);
  status = GS_GasSendCommand(&combuf,NULL);
  LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
    
  return(status); 
}

status_code GS_COMOptNew(UINT32 command,UINT32 value)
{
  GS_COMMAND combuf;
  status_code status;

  GS_FormatGasCommand(&combuf,command,value,GS_FCNULL,GS_NO_ERR);
  status = GS_GasSendCommand(&combuf,NULL);
  LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
  
  return(status); 
}

status_code GS_COMOptNewT0(UINT32 value)
{
  status_code status;
  status = GS_COMOptNew(GS_OPTNEW_T0,value);
  return(status);  
}

status_code GS_COMOptNewT1(UINT32 value)
{
  status_code status;
  status = GS_COMOptNew(GS_OPTNEW_T1,value);
  return(status);  
}

status_code GS_COMOptNewT2(UINT32 value)
{
  status_code status;
  status = GS_COMOptNew(GS_OPTNEW_T2,value);
  return(status);  
}

status_code GS_COMOptNewE(UINT32 value)
{
  status_code status;
  status = GS_COMOptNew(GS_OPTNEW_E,value);
  return(status);  
}

status_code GS_COMOptNewB(UINT32 value)
{
  status_code status;
  status = GS_COMOptNew(GS_OPTNEW_B,value);
  return(status);  
}

status_code GS_COMResetErrFPGA()
{
  GS_COMMAND combuf;
  status_code status;
  
  GS_FormatGasCommand(&combuf,GS_RESET_ERR_FPGA,GS_FRNULL,GS_FCNULL,GS_NO_ERR);
  status = GS_GasSendCommand(&combuf,NULL);
  LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
  
  return(status); 
}

status_code GS_COMResetErrPSCU()
{
  GS_COMMAND combuf;
  status_code status;
   
  GS_FormatGasCommand(&combuf,GS_RESET_ERR,GS_FRNULL,GS_FCNULL,GS_NO_ERR);
  status = GS_GasSendCommand(&combuf,NULL);
  LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
    
  return(status); 
}

status_code GS_COMEmptyBuffer(UINT32 valve)
{
  GS_COMMAND combuf;
  status_code status;

  GS_FormatGasCommand(&combuf,GS_EMPTY_BUFFER,valve,GS_FCNULL,GS_NO_ERR);
  status = GS_GasSendCommand(&combuf,NULL);
  LU_INFN_LOG(LU_DEBUG_TRACE,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
  
  return(status); 
}


/* High Level Command Function */

status_code GS_HLStandBy(BYTE mode)
{
  status_code status;
  UINT32 addr;
  int value = 1;

  if (mode == GS_STDBY_ON)
    addr = GS_GasParam[GS_GasType].VCB_on;
  else
 #warning "da ricontrollare"
    //addr = TM_VCB_STANDBY_OFF;

  status = HK_SendTC(addr,value); 
  
  return(status);
}

status_code GS_CheckPower(CM_ON_OFF *mode)
{
  UINT32 v;
  status_code s;

#warning "da ricontrollare"
  // s=HK_GetTMValue(TM_GAS_ENABLED,&v);

  if(s == CM_RC_SUCCESSFUL) 
    {
      if(v)
	*mode = CM_OFF;
      else
	*mode = CM_ON;
    }

  return s;
}


status_code GS_HLGasOff()
{
  status_code status;
  int value = 1;
  UINT32 addr;

  addr = GS_GasParam[GS_GasType].GasOff;
  status = HK_SendTC(addr,value); 
  
  return(status);
}


status_code GS_GasOn()
{
}


/* Gas System Procedure */


status_code GS_GasStartUp()
{
  GS_REPLY_STRUCT answ;
  status_code status;
  int check_interval = 60;
  int GS_STARTUP_SUSPEND = 3*ConvertToSec(PRH_VAR_GS_T2)+2 + 60;    // 60 for safe

  status = GS_COMRequest(&answ);

  if (!status)
    {

      
      status = GS_HLStandBy(GS_STDBY_OFF);
      
      if (!status)
	{
	  status = GS_COMFillBuffer10cc(GS_FCNULL);
	  
	  if (!status)
	    {
	      status = GS_GasSuspend(check_interval*1000,GS_STARTUP_SUSPEND*1000);
	      
	      switch(status)
		{
		case CM_RC_SUCCESSFUL:
		  {
		    status = 0;     // TBD  GS_COMEnAlarm(GS_FRON); temporaneamnte disabilitato per i test 
		    if (!status)
		      {
			status = GS_COMRequest(&answ);
		      }
		  }
		  break;
		case CM_RC_GS_INTERRUPTED:
		  status = GS_COMAbort();
		  break;
		case CM_RC_TIMEOUT:
		  break;
		case CM_RC_GS_BAD_COMMAND:
		case CM_RC_GS_MISMATCH_COMMAND:
		case CM_RC_GS_ERR_FPGA: 
		  break;
		}
	    }
	}
    }
  else
    {
      // turnoff , turnon forse high level 3.6V OFF da vedere
      status = GS_HLGasOff();
      OS_piTaskSuspend(500);                                        // mezzo secondo prima di riprovare PROVVISORIO
      GS_GasOn();
      GS_SendCodeGasManager(GS_START_UP,NULL);                      // contare 2 volte 
    }
  return(status);
}

status_code GS_GasPurgeSector(UINT32 sector)
{
  GS_REPLY_STRUCT answ;
  status_code status;
  int check_interval = 5*60;
  int GS_SUSPEND = ConvertToSec(PRH_VAR_GS_T0) + 10*(ConvertToSec(PRH_VAR_GS_T0)+ConvertToSec(PRH_VAR_GS_T1)+2)+
    ConvertToSec(PRH_VAR_GS_T0)+ConvertToSec(PRH_VAR_GS_T1)+2+ConvertToSec(PRH_VAR_GS_T2) + 200;  // 200 for safe
  
  status = GS_COMPurge(GS_N12,sector,GS_NEW);

  if (!status)
    {
      status = GS_GasSuspend(check_interval*1000,GS_SUSPEND*1000);  
      
      switch(status)
	{
	case CM_RC_SUCCESSFUL:
	  break;
	case CM_RC_GS_INTERRUPTED:
	  status = GS_COMAbort();
	  break;
	case CM_RC_GS_BAD_COMMAND:
	case CM_RC_GS_MISMATCH_COMMAND:
	case CM_RC_GS_ERR_FPGA: 
	  break;
	}
    }
  return(status);
}

status_code GS_TRDPurge()
{
  GS_REPLY_STRUCT answ;
  status_code status;
  UINT32 sector[3]={GS_FC1,GS_FC2,GS_FC3};
  UINT32 counter,value;

 #warning "da ricontrollare"  
  //  status = HK_GetTMValue(TM_GAS_TH,&value);
  
  if (status)
    return(status);

  //if (value > 0x532)                     // temp < 5°C 
  //  return(CM_RC_VALUE_UNDER_RANGE);     // TBD

  counter = 0;
  status = GS_COMRequest(&answ);

  if (!status)
    {
      GS_Mode = GS_TRD_PURGING;
      
      GS_SetCCAGasMode(GS_GAS_IN_TRD,GS_BITSET);
      
      while ((counter < 3) && (!status))
	{
	  status = GS_GasPurgeSector(sector[counter]);
	  counter++;
	}
      
      if (status)
	GS_SetCCAGasMode(GS_GAS_IN_TRD,GS_BITRESET);
    }

  return(status);
}  


status_code GS_TechnologicalPurge()
{
  status_code status=CM_RC_SUCCESSFUL;
  int i;

  i = 0;
  
  while ((i++ < 3) && (status == CM_RC_SUCCESSFUL))
    status = GS_TRDPurge();
  
  return(status);
}

status_code GS_GasFillInputBuffer()
{
  GS_REPLY_STRUCT answ;
  status_code status;
  int check_interval = 60;
  int GS_STARTUP_SUSPEND = 3*ConvertToSec(PRH_VAR_GS_T2)+2 + 60;    // 60 for safe
  
  status = GS_COMRequest(&answ);  

  if (!status)
    {
      status = GS_COMFillBuffer10cc(GS_FCNULL);
      if (!status)
	{
	  status = GS_GasSuspend(1000*check_interval,GS_STARTUP_SUSPEND*1000);  
      
	  switch(status)
	    {
	    case CM_RC_SUCCESSFUL:
	      break;
	    case CM_RC_GS_INTERRUPTED:
	      status = GS_COMAbort();
	      break;
	    case CM_RC_GS_BAD_COMMAND:
	    case CM_RC_GS_MISMATCH_COMMAND:
	    case CM_RC_GS_ERR_FPGA: 
	      break;
	    }
	}
    }
  
  return(status);
}
  

status_code GS_ContainerPurge()
{
  status_code status;
  int i,tmp,done;
  
  status = GS_COMPurge(GS_N12,GS_FCB,GS_NEW);
  
  if (!status)
    {
      GS_SetCCAGasMode(GS_GAS_CONTAINER_PURGE,GS_BITSET);  
      i = 0; done = 1;

      while ((i < 30) && done)
	{
	  status = HK_GetTMValue(TM_GAS_LPS5,&tmp);

	  if (!status)
	    {
	      if (tmp < 0x88)            // 800 mbar  3 Volt = 1500 mbar   
		{
		  status = GS_COMAbort();
		  done = 0;
		}
	    }
	  
	  status = GS_GasTaskSuspend(10*1000);

	  if (status != RTEMS_TIMEOUT)  
	    {
	      GS_SendCodeGasManager(GS_ABORT_OP,NULL); 
	      return(CM_RC_SUCCESSFUL);
	    }
	  i++;
	}
      
      if (done) 
	GS_SendCodeGasManager(GS_CONTAINER_PURGE,NULL); 
      else
	GS_SetCCAGasMode(GS_GAS_CONTAINER_PURGE,GS_BITRESET);  
    }
  return(status);
}

status_code GS_SwitchOff(UINT32 stdby)
{
  status_code status;

  status = GS_COMAbort();

  if (!status)
    {
      status = GS_COMEnAlarm(GS_FROFF);
      if (!status)
	{
	  if (stdby)
	    status = GS_HLStandBy(GS_STDBY_ON);                          // in case of alarm should no send STDBYON
	  if (!status)
	    status = GS_HLGasOff();
	}
    }
  return(status);
}

status_code GS_Alarm()
{
  status_code status;

  status = GS_SwitchOff(GS_FALSE);
  if (!status) 
    status = CM_RC_GS_ALARM;                       /* error in reply from Gas System */

  return(status);
}

/* GAS task handler */

status_code GS_InitGasManager (void)
  {
    status_code       status;
    void            * p;
    unsigned short  * pR;
    unsigned int      OldPriority;
    
    // Task initialization

    if ((status=OS_piTaskReady_INFN(GS_INFN_TASK,GS_tkGSManager)) != SUCCESSFUL)
      {
        // Task is not correctly started

	LU_INFN_LOG (LU_CRITICAL|LU_HA, LU_MASK(__FILEID__), __FILEID__, __LINE__, status);    
        
	status = UNSATISFIED;
      }

    if ( (status=OS_piTaskPriority_INFN(GS_INFN_TASK,GS_MANAGER_PRIORITY,&OldPriority)) != SUCCESSFUL)
      {
        // Task priority is not correctly updated

	LU_INFN_LOG (LU_CRITICAL|LU_HA, LU_MASK(__FILEID__), __FILEID__, __LINE__, status);    

        status = UNSATISFIED;
      }
    
    return (status);
  }

/*****************************************************************************/
/* @Function: GS_SndMsgGSManager                                             */
/* @Purpose :                                                                */
/*  The function  invokes the directive of the OS to send a message to the   */
/*  HKManager mailbox.                                                       */
/*                                                                           */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/*  SndMsg               IN      Message buffer that contains task operation */
/*  status_code          OUT     Return code                                 */
/* @@                                                                        */
/*****************************************************************************/

status_code GS_SndMsgGSManager (MsgTsk* SndMsg)
  {
    status_code   status;

    // Send message to GS_SndMsgHKManager task mailbox

    status = OS_piMsgQueueSend_INFN(GS_INFN_MAILBOX,  (void *) SndMsg,  sizeof(MsgTsk));
    if (status) 
      LU_INFN_LOG (LU_FATAL|LU_HA, LU_MASK(__FILEID__), __FILEID__, __LINE__, status);    
     
    return (status);
  }


/*****************************************************************************/
/* @Function: GS_tkHKManager                                                 */
/* @Purpose :                                                                */
/*  The function is the task handler of the GS_tkHKManager object.           */
/*  When a message is received into task mailbox it wakes up.                */
/*  The information contained in the message (MsgTsk structure) define       */
/*  parameters (Info field), and the operation type that the task performs   */
/*  (Code field).                                                            */
/*  The GS_tkHKManager task activity is to activate the cyclic telemetry     */
/*   acquisitin.                                                             */
/*                                                                           */
/* @@                                                                        */
/* @Parameter Name      @Mode   @Description                                 */
/* @@                                                                        */
/*****************************************************************************/

task GS_tkGSManager (task_argument unused)
{
  status_code       status;
  MsgTsk            RxMsg;
  unsigned int      MsgSize,value;
  CM_ON_OFF power;   

  while (FOREVER) 
    {
      RxMsg.Code = NULL_MSG_TM;
      
      // Wait for a message to become available
      
      if ((status = OS_piMsgQueueReceive_INFN(GS_INFN_MAILBOX,  (void *) &RxMsg,   &MsgSize,  WAIT,   NO_TIMEOUT)) == SUCCESSFUL)
	{
	  GS_CheckPower(&power);
	  power= CM_ON;   // TBD remove this 
	  
	  if (power == CM_ON)
	    switch (RxMsg.Code)
	      {
	      case GS_START_UP:
		GS_GasStartUp();
		break;
	      case GS_CONTAINER_PURGE:
		GS_ContainerPurge();
		break;
	      case GS_TRD_PURGE:
		GS_TRDPurge();
		break;
	      case GS_TECH_PURGE:
		GS_TechnologicalPurge();
		break;
	      case GS_FILLINPUT_BUFFER:
		GS_GasFillInputBuffer();
		break;
	      case GS_TEST:
		GS_Test();
		break;
	      case GS_ABORT_OP:
		GS_COMAbort();
		break;
	      }
	}
    }
}

status_code GS_SendCodeGasManager(GS_OPCODES code,UINT16 value) 
{
  MsgTsk SndMsg;
  SndMsg.Code = code;
  SndMsg.Info[0] = value >> 8;
  SndMsg.Info[1] = value & 0xff;
  return GS_SndMsgGSManager(&SndMsg);
}

status_code GS_GasTaskSuspend(UINT32 delay)
{
  UINT32 Level,unused;
  status_code e;

  OS_piEventReceive(OS_GS_RESUME,RTEMS_NO_WAIT,0,&unused);  

  OS_piInterDisable(&Level);
  GS_TaskSuspended = TRUE;
  OS_piInterEnable(Level);
  
  e=OS_piEventReceive(OS_GS_RESUME,RTEMS_WAIT,delay,&unused);  

  OS_piInterDisable(&Level);
  GS_TaskSuspended = FALSE;
  OS_piInterEnable(Level);

  return(e);
}

/* this function suspend the gas task 
   return

   CM_RC_GS_BAD_COMMAND in case of Bad command from Gas System FPGA
   CM_RC_SUCCESSFUL in case of previously scheduled operation has finished 
   CM_RC_GS_INTERRUPTED in case of operation interrupted by some external event 
   CM_RC_TIMEOUT reached timeout but operation not finished 
   CM_RC_GS_MISMATCH_COMMAND  if the executed command is not what is expected 
   CM_RC_GS_ERR_FPGA  if err_fpga error has occurred 
*/

status_code GS_GasSuspend(UINT32 check_interval,UINT32 timeout)
{
  UINT32 i,exit_loop;
  status_code status;
  GS_REPLY_STRUCT answ;
  
  i = 0; exit_loop = 0;
  do
    {
      status = GS_COMRequest(&answ);
      
      if (!status)
	{
	  if (answ.curr_state != GS_CSEND)
	    {
	      status = GS_GasTaskSuspend(check_interval);
	      
	      if (status != RTEMS_TIMEOUT)  
		{
		  status = CM_RC_GS_INTERRUPTED;
		  exit_loop = 1;
		}
	    }
	  else
	    return(CM_RC_SUCCESSFUL);                                // curr_state = GS_CSEND
	}
      else
	exit_loop = 1;
      
      i++;
      
    } while (((i*check_interval) < timeout) && !exit_loop);
  
  if (!exit_loop)
    status = CM_RC_TIMEOUT;
  
  return(status);
}
 
status_code GS_GasResume()
{
  UINT32 Level,unused;
  status_code e = CM_RC_SUCCESSFUL;
  
  OS_piInterDisable(&Level);

  if (GS_TaskSuspended)
    {
      e = OS_piEventSend(GS_INFN_TASK,OS_GS_RESUME);
      GS_TaskSuspended = FALSE;
    }

  OS_piInterEnable(Level);
  
  return(e);
}


status_code GS_GetGaSStatus(UINT16* GSStatus)
{
  /*
   TBD
  */
  *GSStatus = GS_CCAGasMode;
  return CM_RC_SUCCESSFUL;
}

status_code GS_SetCCAGasMode(UINT16 bit,UINT16 mode)
{
  if (mode == GS_BITSET)
    GS_CCAGasMode |= bit;
  else
    GS_CCAGasMode &= ~bit;
  
  return CM_RC_SUCCESSFUL;
}

status_code GS_CheckPurgeTemp()
{
  
}



status_code GS_Test()
{
  static int test = 1;
  
  status_code status;
  static UINT32 valid;
  static UINT32 command;
  static UINT32 valve_conf;
  static UINT32 curr_state;
  static UINT32 conf_soglie;
  static UINT32 err_fpga;
  static UINT32 err_pscu;
  static UINT32 cont;
  static UINT32 com;
  static GS_REPLY_STRUCT outbuf;
  static UINT32 sector;
  
  switch (test)
    {
    case 1: 
      {
	status = GS_COMRequest(&outbuf);
	
	valid = outbuf.valid;
	command = outbuf.command;
	valve_conf = outbuf.valve_conf;
	curr_state = outbuf.curr_state;
	conf_soglie = outbuf.conf_soglie;
	err_fpga = outbuf.err_fpga;
	err_pscu = outbuf.err_pscu;
	cont = outbuf.cont;
	com = outbuf.com;
	
	if (!status)
	  status = GS_HLStandBy(GS_STDBY_OFF);
	
	if (!status)
	  status = GS_COMMascValv(GS_FRALL);
	
	sector = GS_FCNULL;
	
	if (!status) 
	  status = GS_COMFillBuffer10cc(sector);
	
	if (!status) 
	  status = GS_COMRequest(&outbuf);
	
	valid = outbuf.valid;
	command = outbuf.command;
	valve_conf = outbuf.valve_conf;
	curr_state = outbuf.curr_state;
	conf_soglie = outbuf.conf_soglie;
	err_fpga = outbuf.err_fpga;
	err_pscu = outbuf.err_pscu;
	cont = outbuf.cont;
	com = outbuf.com;
      }
      break;
    case 2 :
      {
	static int i;
	
	for (i=0; i < 100; i++)
	  {
	    
	    status = GS_COMRequest(&outbuf);
	    
	    valid = outbuf.valid;
	    command = outbuf.command;
	    valve_conf = outbuf.valve_conf;
	    curr_state = outbuf.curr_state;
	    conf_soglie = outbuf.conf_soglie;
	    err_fpga = outbuf.err_fpga;
	    err_pscu = outbuf.err_pscu;
	    cont = outbuf.cont;
	    com = outbuf.com;
	  }
      }
      break;
    case 3:
      {
	
	status = GS_COMPurge(GS_N12,GS_FC1,GS_NEW);
	
      }
      break;
    }
}

#endif // GS_COMPILE
