/****************************************************************************
 *  F i l e   D a t a                                                        
 *  $Id: S4_INFN.c,v 1.1.1.1 2006/04/25 09:00:20 kusanagi Exp $
 *  $Revision: 1.1.1.1 $
 *  $Date: 2006/04/25 09:00:20 $
 *  $RCSfile: S4_INFN.c,v $
 *                                                                           
 ****************************************************************************
 *  S W   D e v e l o p m e n t   E n v i r o n m e n t                      
 *                                                                           
 *  $Author: kusanagi $
 *               :                                                           
 ****************************************************************************
 *  U p d a t i n g                                                          

 *  $Log: S4_INFN.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.20  2005/03/06 14:54:46  sebastiani
 *  version running on 06 03 2005
 *
 *  Revision 1.19  2005/02/19 10:19:38  sebastiani
 *  ALM_S4_CALIB_00_HARD,ALM_S4_CALIB_00_SOFT,ALM_S4_128TRIGGER_0 added
 *
 *  Revision 1.18  2005/01/10 14:02:13  faber
 *  TRG,AC_1,AC_2,TOF Error Handler reviewed
 *
 *  Revision 1.17  2004/12/20 14:02:04  faber
 *  @LOG entry introduced in all ALM_WriteLog occurrences
 *
 *  Revision 1.16  2004/11/30 11:51:53  faber
 *  AC+AC2 software moved into AC_1 AC_2
 *  new calibration and initialization for AC
 *  first version,never run
 *
 *  Revision 1.15  2004/11/19 15:41:50  sebastiani
 *  *** empty log message ***
 *
 *  Revision 1.14  2004/11/19 15:14:52  sebastiani
 *  PRH_EXTERN_{VAR,ARR,TABLE} removed and put them on the autogenerated parameter heeader file
 *
 *  Revision 1.13  2004/10/05 13:32:41  sebastiani
 *  stupid bugfix
 *
 *  Revision 1.12  2004/10/04 13:59:05  alfarano
 *  fixed some return code in run manager
 *
 *  Revision 1.11  2004/10/04 13:42:48  sebastiani
 *  *** empty log message ***
 *
 *  Revision 1.10  2004/10/04 08:25:06  sebastiani
 *  *** empty log message ***
 *
 *  Revision 1.9  2004/10/01 13:59:45  sebastiani
 *  some bugfix in calib, but not tested
 *
 *  Revision 1.8  2004/10/01 11:13:21  sebastiani
 *  TIMEOUT S4 calib fix
 *
 *  Revision 1.7  2004/10/01 09:20:23  alfarano
 *  AC2 and little bug fix on S4 return code
 *
 *  Revision 1.6  2004/10/01 08:48:10  sebastiani
 *  TRD alarma renamed TRD_S4  - S4 Alarm renamed S4_POWER
 *  Callback function into DAQ_SendCmd2PIFWaitDAQReply_internal
 *
 *  Revision 1.5  2004/09/27 15:42:43  alfarano
 *  tracker sensor board functions
 *
 *  Revision 1.4  2004/09/22 15:54:54  alfarano
 *  S4 functions
 *
 *  Revision 1.3  2004/08/27 13:30:39  alfarano
 *  cvs header
 *
 *  Revision 1.1  2003/10/03 16:12:26  faber
 *  *** empty log message ***
 *
 *                                                                           
 *****************************************************************************/
/*============================= Include File ================================*/


#include <src/INFN/LU_SourceFileID_INFN.h>
#define __FILEID__ _S4_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/DAQ_IDAQ_INFN.h>
#include <src/INFN/CM_Common_INFN.h>
#include <src/INFN/S4_INFN.h>
#include <src/INFN/KHB_Driver_INFN.h>
#include <src/INFN/CH_CommandHandler_INFN.h>
#include <src/INFN/HB_HKBuffer_INFN.h>
#include <src/INFN/HK_Manager_INFN.h>
#include <src/INFN/ALM_Alarm_INFN.h>
#include <src/INFN/RM_RunManager_INFN.h>
#include <src/INFN/DAQ_IDAQ_INFN.h>

/*============================ Global define ================================*/


/*============================== global types  ==============================*/

DAQ_DECLBUF(S4_TempPif0,S4_MAXTEMPBUFFER);
DAQ_DECLBUF(daq_reply,S4_MAXTEMPBUFFER);
DAQ_DECLBUF(S4_Buffer,S4_MAXTEMPBUFFER);

#define S4_SKIP_HEADER SM_PKTHEADER_LEN

/*=========================== Structure define ==============================*/


/*============================ Enumerate define =============================*/


status_code S4_Init_ETOATO()
{
  CH_SetAtoEto(CH_S4_GEN_RESET,2,3);
  CH_SetAtoEto(CH_S4_READ_CR,2,3);
  CH_SetAtoEto(CH_S4_ACQUISITION,2,3);
}

status_code S4_Init() 
{
  DAQ_BUFFER_INIT(S4_TempPif0);
  DAQ_BUFFER_INIT(daq_reply);
  DAQ_BUFFER_INIT(S4_Buffer);

  S4_Init_ETOATO();
  
  return CM_RC_SUCCESSFUL;
}

status_code S4_Initialization()
{
  status_code status;
  DAQ_CMD_BUF* auto_buf;
  UINT16 status_reg;
  UINT16 combuf,outbuf;
  DAQ_FE s4_link = DAQ_FE_S4;
  
  DAQ_ResetPIF(DAQ_DEFAULT_ETO_TICS,DAQ_MAX_DTO_TICS,SM_DAQSETUP,HB_PKTTYPE_S4_INIT);
  PRH_VAR_S4_WORKING = 1;

  combuf = PRH_VAR_S4_TRH;
  status = HK_KHB_Cmd2FE(KHB_S4,1,0,&combuf,&outbuf,S4_BOARD_TIMEOUT);

  if (status == CM_RC_SUCCESSFUL)
    {
      status = HK_ReadKHBStatusRegister(&status_reg);
      
      if (status == CM_RC_SUCCESSFUL)
	{
	  if (status_reg & KHB_STS_ALARM_S4_FE)
	    {
	      /*@LOG S4 Initialization: S4 alarm on KHB status after S4_TRH setting */
	      ALM_WriteLog(ALM_TRACE_ID,ALM_S4_TRH_1_SOFT);
	      PRH_VAR_S4_WORKING = 0;
	    }
	  
	  DAQ_Format_CMD_Empty(&S4_TempPif0);
	  CH_GetBuf(CH_S4_GEN_RESET, &auto_buf);
	  DAQ_Format_Fe2Daq(&S4_TempPif0,auto_buf,s4_link);
	  
	  DAQ_StoreCmdQueue2PIF(SM_CALEXP0,&S4_TempPif0);	    
	  status = DAQ_SendCmd2PIFWaitDAQReply(SM_CALEXP0,DAQ_STORE_MM,NULL,DAQ_NO_STORE_RAM);
	}
      else
	{
	  /*@LOG S4 Initialization: KHB status register reading error after S4_TRH setting */
	  ALM_WriteLog(ALM_TRACE_ID,ALM_S4_TRH_1_HARD);
	  status = CM_RC_DO_POWER_OFF_ON;
	}
    }
  else
    {
      /*@LOG S4 Initialization: KHB status eror reading error after S4_TRH setting */
      ALM_WriteLog(ALM_TRACE_ID,ALM_S4_TRH_1_HARD);
      status = CM_RC_DO_POWER_OFF_ON;
    }   
  return status;
}

status_code S4_Calibration() 
{
  status_code status;
  DAQ_CMD_BUF* auto_buf;
  UINT16 status_reg,i,combuf,outbuf;
  DAQ_FE s4_link,tb_link;

  s4_link = DAQ_FE_S4;
  tb_link = DAQ_SELECT_TRIG(PRH_VAR_TB_LINK);
  
  DAQ_ResetPIF(DAQ_ACQ_ETO_TICS,DAQ_MAX_DTO_TICS,SM_DAQSETUP,HB_PKTTYPE_CALIB_S4);
  DAQ_Format_CMD_Empty(&S4_TempPif0);
  DAQ_Format_CMD_Empty(&S4_Buffer);
  
  CH_GetBuf(CH_TB_OPEN_CALIB_GATE,&auto_buf);  
  DAQ_Format_Cmd2Fe(&S4_TempPif0,auto_buf,tb_link);
  DAQ_StoreCmdQueue2PIF(SM_CALEXP0,&S4_TempPif0);	
  status = DAQ_SendCmdQueue2CMDIF(SM_CALEXP0);
  
  if (status)
    return(status);
  

  combuf = S4_CALIB_00;
  status = HK_KHB_Cmd2FE(KHB_S4,1,0,&combuf,&outbuf,S4_BOARD_TIMEOUT);

  if(status == CM_RC_SUCCESSFUL) /* calib 00 */
    {

       status = HK_ReadKHBStatusRegister(&status_reg);

       if (status == CM_RC_SUCCESSFUL)  /* calib 00 stw */
	 {
	   if (status_reg & KHB_STS_ALARM_S4_FE) 
	     {
	       /*@LOG S4 Calibration: KHB alarm on status register after S4_CALIB_00 setting */
	       ALM_WriteLog(ALM_TRACE_ID,ALM_S4_CALIB_00_SOFT);
	       PRH_VAR_S4_WORKING = 0;
	       
	     }
	   DAQ_Format_CMD_Empty(&S4_TempPif0);
	   DAQ_Format_ReleaseBusy(&S4_TempPif0);
	   CH_GetBuf(CH_S4_ACQUISITION,&auto_buf);  
	   DAQ_Format_Fe2Daq(&S4_TempPif0,auto_buf,s4_link);
	   DAQ_StoreCmdQueue2PIF(SM_CALEXP0,&S4_TempPif0);	
	   status = DAQ_SendCmd2PIFWaitDAQReply_CallBack(SM_CALEXP0,
							 DAQ_NO_STORE_MM,
							 &daq_reply,
							 DAQ_STORE_RAM,
							 HK_KHBSend128Trigger);
	   LU_EXIT_IFERROR(status);
	   
	   DAQ_Format_AppendBuffer_offset(&S4_Buffer,&daq_reply,S4_SKIP_HEADER);
	   
	   if (status == CM_RC_SUCCESSFUL) /* 128_0 */
	     {
	       for(i=0; i < 127; i++)
		 {
		   status = DAQ_SendCmd2PIFWaitDAQReply(SM_CALEXP0,DAQ_NO_STORE_MM,&daq_reply,DAQ_STORE_RAM);
		   LU_EXIT_IFERROR(status);
		   DAQ_Format_AppendBuffer_offset(&S4_Buffer,&daq_reply,S4_SKIP_HEADER);
		 }
	       
	       combuf = S4_CALIB_01;
	       status = HK_KHB_Cmd2FE(KHB_S4,1,0,&combuf,&outbuf,S4_BOARD_TIMEOUT);
  
	       if (status == CM_RC_SUCCESSFUL)  /* calib 01 */
		 {
		   status = HK_ReadKHBStatusRegister(&status_reg);
      
		   if (status == CM_RC_SUCCESSFUL)  /* calib 01 stw */
		     { 
		       if (status_reg & KHB_STS_ALARM_S4_FE)
			 {
			   /*@LOG S4 Calibration: KHB alarm on status register after S4_CALIB_01 setting */
			   ALM_WriteLog(ALM_TRACE_ID,ALM_S4_CALIB_01_SOFT);
			   PRH_VAR_S4_WORKING = 0;
			 }
	  
		       DAQ_Format_CMD_Empty(&S4_TempPif0);
		       DAQ_Format_ReleaseBusy(&S4_TempPif0);
		       CH_GetBuf(CH_S4_ACQUISITION,&auto_buf);  
		       DAQ_Format_Fe2Daq(&S4_TempPif0,auto_buf,s4_link);
		       DAQ_StoreCmdQueue2PIF(SM_CALEXP0,&S4_TempPif0);	
		       status = DAQ_SendCmd2PIFWaitDAQReply_CallBack(SM_CALEXP0,
								     DAQ_NO_STORE_MM,
								     &daq_reply,
								     DAQ_STORE_RAM,
								     HK_KHBSend128Trigger);
		       LU_EXIT_IFERROR(status);
	  
		       DAQ_Format_AppendBuffer_offset(&S4_Buffer,&daq_reply,S4_SKIP_HEADER);
	  
		       if (status == CM_RC_SUCCESSFUL) /* 128_1 */
			 {
			   for(i=0; i < 127; i++)
			     {
			       status = DAQ_SendCmd2PIFWaitDAQReply(SM_CALEXP0,DAQ_NO_STORE_MM,&daq_reply,DAQ_STORE_RAM);
			       LU_EXIT_IFERROR(status);
			       DAQ_Format_AppendBuffer_offset(&S4_Buffer,&daq_reply,S4_SKIP_HEADER);
			     }
	      
			   combuf = S4_CALIB_10;
			   status = HK_KHB_Cmd2FE(KHB_S4,1,0,&combuf,&outbuf,S4_BOARD_TIMEOUT);
	      
			   if (status == CM_RC_SUCCESSFUL) /* calib 10 */
			     {
			       status = HK_ReadKHBStatusRegister(&status_reg);
		  
			       if (status == CM_RC_SUCCESSFUL) /* calib 10 stw */
				 {
				   if (status_reg & KHB_STS_ALARM_S4_FE)
				     {
				       /*@LOG S4 Calibration: S4 alarm on status register after S4_CALIB_02 setting */
				       ALM_WriteLog(ALM_TRACE_ID,ALM_S4_CALIB_10_SOFT);
				       PRH_VAR_S4_WORKING = 0;
				     }
		      
				   status = DAQ_SendCmd2PIFWaitDAQReply_CallBack(SM_CALEXP0,
										 DAQ_NO_STORE_MM,
										 &daq_reply,
										 DAQ_STORE_RAM,
										 HK_KHBSend128Trigger);
				   LU_EXIT_IFERROR(status);
				   DAQ_Format_AppendBuffer_offset(&S4_Buffer,&daq_reply,S4_SKIP_HEADER);

				   if (status == CM_RC_SUCCESSFUL) /* 128_2 */
				     {
				       for(i=0; i < 127; i++)
					 {
					   status = DAQ_SendCmd2PIFWaitDAQReply(SM_CALEXP0,DAQ_NO_STORE_MM,&daq_reply,DAQ_STORE_RAM);
					   LU_EXIT_IFERROR(status);
					   DAQ_Format_AppendBuffer_offset(&S4_Buffer,&daq_reply,S4_SKIP_HEADER);
					 }
			  
				       combuf = S4_CALIB_11;
				       status = HK_KHB_Cmd2FE(KHB_S4,1,0,&combuf,&outbuf,S4_BOARD_TIMEOUT);

				       if (status == CM_RC_SUCCESSFUL) /* calib 11 */
					 {
					   status = HK_ReadKHBStatusRegister(&status_reg);
			  
					   if (status == CM_RC_SUCCESSFUL) /* calib 11 stw */
					     {
					       if (status_reg & KHB_STS_ALARM_S4_FE)
						 {
						   /*@LOG S4 Calibration: S4 alarm on status register after S4_CALIB_11 setting */
						   ALM_WriteLog(ALM_TRACE_ID,ALM_S4_CALIB_11_SOFT);
						   PRH_VAR_S4_WORKING = 0;
						 }
				  
					       status = DAQ_SendCmd2PIFWaitDAQReply_CallBack(SM_CALEXP0,
											     DAQ_NO_STORE_MM,
											     &daq_reply,
											     DAQ_STORE_RAM,
											     HK_KHBSend128Trigger);

					       LU_EXIT_IFERROR(status);
					       DAQ_Format_AppendBuffer_offset(&S4_Buffer,&daq_reply,S4_SKIP_HEADER);
				  
					       if (status == CM_RC_SUCCESSFUL) /* 128_3 */
						 {
						   for(i=0; i < 127; i++)
						     {
						       status = DAQ_SendCmd2PIFWaitDAQReply(SM_CALEXP0,
											    DAQ_NO_STORE_MM,
											    &daq_reply,
											    DAQ_STORE_RAM);
						       LU_EXIT_IFERROR(status);
						       DAQ_Format_AppendBuffer_offset(&S4_Buffer,&daq_reply,S4_SKIP_HEADER);
						     }
				      
						   combuf = PRH_VAR_S4_TRH;
						   status = HK_KHB_Cmd2FE(KHB_S4,1,0,&combuf,&outbuf,S4_BOARD_TIMEOUT);
				      
						   if (status == CM_RC_SUCCESSFUL) /* S4_TRH_1 */
						     {
						       status = HK_ReadKHBStatusRegister(&status_reg);
					  
						       if (status == CM_RC_SUCCESSFUL) /* S4_TRH_1 stw */
							 {
							   if (status_reg & KHB_STS_ALARM_S4_FE)
							     {
							       /*@LOG S4 Calibration: S4 alarm on status register after S4_TRH setting */
							       ALM_WriteLog(ALM_TRACE_ID,ALM_S4_TRH_2_SOFT);
							       PRH_VAR_S4_WORKING = 0;
							     }
					      
							   DAQ_Format_CMD_Empty(&S4_TempPif0);
							   CH_GetBuf(CH_TB_CLOSE_CALIB_GATE,&auto_buf);  
							   DAQ_Format_Cmd2Fe(&S4_TempPif0,auto_buf,tb_link);
							   DAQ_StoreCmdQueue2PIF(SM_CALEXP0,&S4_TempPif0);	
							   status = DAQ_SendCmdQueue2CMDIF(SM_CALEXP0);
							   LU_EXIT_IFERROR(status);
							   HB_StoreMisc(HB_PKTTYPE_CALIB_S4,&S4_Buffer);
							   RM_WriteHBInfos(FALSE);
							 }
						       else /* S4_TRH_1 stw */
							 {
							   /*@LOG S4 Calibration: S4 KHB status register reading hard error after S4_TRH_1 */
							   ALM_WriteLog(ALM_TRACE_ID,ALM_S4_TRH_1_HARD);
							   status = CM_RC_DO_POWER_OFF_ON;
							 }
						     }
						   else /* S4_TRH_1 */
						     {
						       /*@LOG S4 Calibration: S4 KHB hard error after S4_TRH_1 */
						       ALM_WriteLog(ALM_TRACE_ID,ALM_S4_TRH_1_HARD);
						       status = CM_RC_DO_POWER_OFF_ON;
						     }
						 }
					       else /* 128_3 */
						 {
						   /*@LOG S4 Calibration: S4 KHB 128_3 failed */
						   ALM_WriteLog(ALM_TRACE_ID,ALM_S4_128TRIGGER_3);
						   status = CM_RC_DO_POWER_OFF_ON;
						 }
					     }
					   else  /* calib 11 stw */
					     {
					       /*@LOG S4 Calibration: S4 KHB status register reading hard error after S4_TRH_11 */
					       ALM_WriteLog(ALM_TRACE_ID,ALM_S4_CALIB_11_HARD);
					       status = CM_RC_DO_POWER_OFF_ON;
					     }
					 } 
				       else /* calib 11 */
					 {
					   /*@LOG S4 Calibration: S4 KHB hard error after S4_TRH_11 */
					   ALM_WriteLog(ALM_TRACE_ID,ALM_S4_CALIB_11_HARD);
					   status = CM_RC_DO_POWER_OFF_ON;
					 }
				     }
				   else /* 128_2 */
				     {
				       /*@LOG S4 Calibration: S4 KHB 128_2 failed */
				       ALM_WriteLog(ALM_TRACE_ID,ALM_S4_128TRIGGER_2);
				       status = CM_RC_DO_POWER_OFF_ON;
				     }
				 }
			       else  /* calib 10 stw */
				 {
				   /*@LOG S4 Calibration: S4 KHB status register reading hard error after S4_TRH_10 */
				   ALM_WriteLog(ALM_TRACE_ID,ALM_S4_CALIB_10_HARD);
				   status = CM_RC_DO_POWER_OFF_ON;
				 }
			     }
			   else /* calib 10 */
			     {
			       /*@LOG S4 Calibration: S4 KHB hard error after S4_TRH_10 */
			       ALM_WriteLog(ALM_TRACE_ID,ALM_S4_CALIB_10_HARD);
			       status = CM_RC_DO_POWER_OFF_ON;
			     }
			 }
		       else /* 128_1 */
			 {
			   /*@LOG S4 Calibration: S4 KHB 128_1 failed */
			   ALM_WriteLog(ALM_TRACE_ID,ALM_S4_128TRIGGER_1);
			   status = CM_RC_DO_POWER_OFF_ON;
			 }
		     }
		   else /*calib 01 stw */
		     {
		       /*@LOG S4 Calibration: S4 KHB status register reading hard error after S4_TRH_01 */
		       ALM_WriteLog(ALM_TRACE_ID,ALM_S4_CALIB_01_HARD);
		       status = CM_RC_DO_POWER_OFF_ON;
		     }
		 }
	       else /* calib 01 */
		 {
		   /*@LOG S4 Calibration: S4 KHB hard error after S4_TRH_01 */
		   ALM_WriteLog(ALM_TRACE_ID,ALM_S4_CALIB_01_HARD);
		   status = CM_RC_DO_POWER_OFF_ON;
		 }
	     }else /* 128_0 */
	       {
		 /*@LOG S4 Calibration: S4 KHB 128_1 failed */
		 ALM_WriteLog(ALM_TRACE_ID,ALM_S4_128TRIGGER_0);
		 status = CM_RC_DO_POWER_OFF_ON;
	       }
	 }else /*calib 01 stw */
	   {
	     /*@LOG S4 Calibration: S4 KHB status register reading hard error after S4_TRH_01 */
	     ALM_WriteLog(ALM_TRACE_ID,ALM_S4_CALIB_00_HARD);
	     status = CM_RC_DO_POWER_OFF_ON;
	   }
    }else /* calib 01 */
      {
	/*@LOG S4 Calibration: S4 KHB hard error after S4_TRH_00 */
	ALM_WriteLog(ALM_TRACE_ID,ALM_S4_CALIB_00_HARD);
	status = CM_RC_DO_POWER_OFF_ON;
      }

  return status;
}

status_code S4_Error_Handler()
{
  status_code status;
  DAQ_CMD_BUF* auto_buf;
  PRH_VAR_S4_WORKING = 0;
  
  DAQ_Format_CMD_Empty(&S4_TempPif0);
  
  CH_GetBuf(CH_S4_READ_CR,&auto_buf);
  DAQ_Format_Fe2Daq(&S4_TempPif0,auto_buf,DAQ_FE_S4);
  
  DAQ_StoreCmdQueue2PIF(SM_CALEXP0,&S4_TempPif0);	    
  status = DAQ_SendCmd2PIFWaitDAQReply(SM_CALEXP0,DAQ_STORE_MM,NULL,DAQ_NO_STORE_RAM);
  if(status != CM_RC_SUCCESSFUL)
    status=CM_RC_DO_RESET_IF_ALM;
  return status;
}
