/****************************************************************************
 *  F i l e   D a t a                                                        
 *  $Id: AC_Anticoincidence_INFN.c,v 1.25 2005/02/22 18:09:25 sebastiani Exp $
 *  $Revision: 1.25 $
 *  $Date: 2005/02/22 18:09:25 $
 *  $RCSfile: AC_Anticoincidence_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: sebastiani $
 *               :                                                           
 ****************************************************************************
 *  U p d a t i n g                                                          

 *  $Log: AC_Anticoincidence_INFN.c,v $
 *  Revision 1.25  2005/02/22 18:09:25  sebastiani
 *  various bugfixes
 *
 *  Revision 1.24  2005/02/19 10:19:00  sebastiani
 *  bugfix: HB_PKTTYPE_CALIB1_AC_1,HB_PKTTYPE_CALIB2_AC_2 error setting; optimization: LU_EXIT_IFERROR/RM_EXIT_IFERROR for space reducing
 *
 *  Revision 1.23  2005/01/26 18:46:48  sebastiani
 *  new bug fixes for WS
 *
 *  Revision 1.22  2005/01/10 14:02:12  faber
 *  TRG,AC_1,AC_2,TOF Error Handler reviewed
 *
 *  Revision 1.21  2004/12/02 10:43:38  sebastiani
 *  fix AC
 *  fix CAL
 *  fix HK BUFTYPE
 *
 *  Revision 1.20  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.19  2004/11/19 15:14:52  sebastiani
 *  PRH_EXTERN_{VAR,ARR,TABLE} removed and put them on the autogenerated parameter heeader file
 *
 *  Revision 1.18  2004/10/01 09:20:23  alfarano
 *  AC2 and little bug fix on S4 return code
 *
 *  Revision 1.17  2004/09/28 15:10:51  alfarano
 *  little bug
 *
 *  Revision 1.16  2004/09/17 15:52:00  faber
 *  fix command queue Cmd2Fe/Fe2Daq right invocation for Test funcion inf TOF and TRG
 *
 *  Revision 1.15  2004/09/17 15:01:00  faber
 *  LU_INFN_LOG flags fixing
 *
 *  Revision 1.14  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__ _AC_Anticoincidence_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/AC_Anticoincidence_INFN.h>
#include <src/INFN/KHB_Driver_INFN.h>
#include <src/INFN/HK_Manager_INFN.h>
#include <src/INFN/HB_HKBuffer_INFN.h>
#include <src/INFN/PM_PamManager_INFN.h>
#include <src/INFN/CH_CommandHandler_INFN.h>
#include <src/INFN/ALM_Alarm_INFN.h>
#include <src/INFN/RM_RunManager_INFN.h>
/*============================ Global define ================================*/


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

#define AC_SKIP_HEADER SM_PKTHEADER_LEN

DAQ_DECLBUF(daq_reply,128*1024);

#define AC_1 0
#define AC_2 1

static DAQ_CMD_BUF AC_SEND_DSP_PROG1;
static DAQ_CMD_BUF AC_1_SEND_DSP_PROG2,AC_2_SEND_DSP_PROG2;
static DAQ_CMD_BUF AC_1_SET_DAQ,AC_2_SET_DAQ;

static DAQ_CMD_BUF AC_1_WRITE_REG,AC_2_WRITE_REG;

static DAQ_CMD_BUF AC_READ_DSP_MEM;

DAQ_DECLBUF(AC_TempPif0,AC_MAXTEMPBUFFER);

status_code AC_Init_ParamBuffers()
{
  DAQ_INIT_BUF_FROM_PARAMBUF(AC_1_SET_DAQ);
  DAQ_INIT_BUF_FROM_PARAMBUF(AC_2_SET_DAQ);

  DAQ_INIT_BUF_FROM_PARAMBUF(AC_SEND_DSP_PROG1);

  DAQ_INIT_BUF_FROM_PARAMBUF(AC_1_SEND_DSP_PROG2);
  DAQ_INIT_BUF_FROM_PARAMBUF(AC_2_SEND_DSP_PROG2);

  DAQ_INIT_BUF_FROM_PARAMBUF(AC_1_SET_DAQ);
  DAQ_INIT_BUF_FROM_PARAMBUF(AC_2_SET_DAQ);

  //DAQ_INIT_BUF_FROM_PARAMBUF(AC_1_CALIB1);
  //DAQ_INIT_BUF_FROM_PARAMBUF(AC_2_CALIB1);

  //DAQ_INIT_BUF_FROM_PARAMBUF(AC_1_CALIB2);
  //DAQ_INIT_BUF_FROM_PARAMBUF(AC_2_CALIB2);

  DAQ_INIT_BUF_FROM_PARAMBUF(AC_READ_DSP_MEM);
  DAQ_INIT_BUF_FROM_PARAMBUF(AC_1_WRITE_REG);
  DAQ_INIT_BUF_FROM_PARAMBUF(AC_2_WRITE_REG);

  return CM_RC_SUCCESSFUL;
}

status_code AC_Init_ATOETO()
{
  int i;
  CH_PARAMBUF_SET_ATO_ETO(AC_1_SET_DAQ,0x1,0x4);
  CH_PARAMBUF_SET_ATO_ETO(AC_2_SET_DAQ,0x1,0x4);

  // CH_PARAMBUF_SET_ATO_ETO(AC_SEND_DSP_PROG2,0x1,0x9);
  CH_PARAMBUF_SET_ATO_ETO(AC_READ_DSP_MEM,0x1,0x9);

  CH_PARAMBUF_SET_ATO_ETO(AC_1_WRITE_REG,0x1,0x2);
  CH_PARAMBUF_SET_ATO_ETO(AC_2_WRITE_REG,0x1,0x2);

  CH_SetAtoEto(CH_AC_STATUS_RESET,1,2);
  CH_SetAtoEto(CH_AC_RESET_DSP,1,2);
  CH_SetAtoEto(CH_AC_CHANGE_MODE_CALIB,1,2);
  CH_SetAtoEto(CH_AC_CHANGE_MODE_PHYS,1,2);  
  CH_SetAtoEto(CH_AC_READ_EVENT,1,3);  
  CH_SetAtoEto(CH_AC_COUNTER_RESET,1,2);
  CH_SetAtoEto(CH_AC_READ_STATUS,1,2);  

  CH_PARAMBUF_SET_ATO_ETO(AC_SEND_DSP_PROG1,0x1,0x9);
  CH_PARAMBUF_SET_ATO_ETO(AC_1_SEND_DSP_PROG2,0x1,0x9);
  CH_PARAMBUF_SET_ATO_ETO(AC_2_SEND_DSP_PROG2,0x1,0x9);

}

status_code AC_Init() 
{
  DAQ_BUFFER_INIT(AC_TempPif0);
  DAQ_BUFFER_INIT(daq_reply);

  AC_Init_ParamBuffers();
  AC_Init_ATOETO();
  
  return CM_RC_SUCCESSFUL;
}




status_code AC_Initialization(DAQ_FE fe,
			      BYTE pkt_type,
			      DAQ_CMD_BUF *ac_set_daq,
			      DAQ_CMD_BUF *ac_write_reg,
			      PRH_VAR_TYPE *ac_on) 
{

  UINT16 loop=0;
  DAQ_CMD_BUF* auto_buf;
  int i;
  BOOL check_ok;
  status_code status;

  *ac_on = 0;

  RM_Set_AcqExitIfError_FILEID(__FILEID__);

  DAQ_ResetPIF(DAQ_DEFAULT_ETO_TICS,DAQ_MAX_DTO_TICS,SM_DAQSETUP,pkt_type);

  DAQ_Format_CMD_Empty(&AC_TempPif0);
  
  DAQ_Format_Fe2Daq(&AC_TempPif0,ac_set_daq,fe);
  DAQ_Format_Fe2Daq(&AC_TempPif0,ac_write_reg,fe);
  CH_GetBuf(CH_AC_COUNTER_RESET,&auto_buf);
  DAQ_Format_Fe2Daq(&AC_TempPif0,auto_buf,fe);
  CH_GetBuf(CH_AC_STATUS_RESET,&auto_buf);
  DAQ_Format_Fe2Daq(&AC_TempPif0,auto_buf,fe);

  status = DAQ_StoreCmdQueue2PIF(SM_CALEXP0,&AC_TempPif0);
  RM_EXIT_IFERROR(status);
  
  do
    {
      status = DAQ_SendCmd2PIFWaitDAQReply(SM_CALEXP0,DAQ_STORE_MM,&daq_reply,DAQ_STORE_RAM);

      if (daq_reply.len < AC_SKIP_HEADER + 4*2)
	status = CM_RC_RUNTIMEOUT;
      
      RM_EXIT_IFERROR(status);

      check_ok = 
	(*(UINT16*)(&daq_reply.buf[AC_SKIP_HEADER +0]) == 0xFFFF) &&
	(*(UINT16*)(&daq_reply.buf[AC_SKIP_HEADER +2]) == 0xFFFF) &&
	(*(UINT16*)(&daq_reply.buf[AC_SKIP_HEADER +4]) == 0xFFFF) &&
	(*(UINT16*)(&daq_reply.buf[AC_SKIP_HEADER +6]) == 0xFFFF);
      
      loop++;
    }
  while ((loop < PRH_VAR_AC_LOOP) && !check_ok);

  if (check_ok)
    *ac_on = 1;
  else
    *ac_on = 0;

  return status;
}


status_code AC_1_Initialization() {
  return AC_Initialization(DAQ_FE_AC_1,
		    HB_PKTTYPE_AC_1_INIT,
		    &AC_1_SET_DAQ,
		    &AC_1_WRITE_REG,
		    &PRH_VAR_AC_1_ON);
}
status_code AC_2_Initialization() {
  return AC_Initialization(DAQ_FE_AC_2,
		    HB_PKTTYPE_AC_2_INIT,
		    &AC_2_SET_DAQ,
		    &AC_2_WRITE_REG,
		    &PRH_VAR_AC_2_ON);
}

status_code AC_Calibration1() 
{
  status_code status = CM_RC_SUCCESSFUL;
  DAQ_CMD_BUF* auto_buf;
  UINT16 alarm_reg;
  int i;
  UINT16      ac_ok[2] = {PRH_VAR_AC_1_OK,PRH_VAR_AC_2_OK};
  UINT16      ac_on[2] = {PRH_VAR_AC_1_ON,PRH_VAR_AC_2_ON};
  DAQ_CMD_BUF *ac_send_dsp_prog2[2] = {&AC_1_SEND_DSP_PROG2,&AC_2_SEND_DSP_PROG2};
  DAQ_CMD_BUF *ac_set_daq[2]        = {&AC_1_SET_DAQ,&AC_2_SET_DAQ};
  DAQ_FE      ac_fe[2]             = {DAQ_FE_AC_1,DAQ_FE_AC_2};
  BYTE        ac_pkttype[2]        = {HB_PKTTYPE_CALIB1_AC_1,HB_PKTTYPE_CALIB1_AC_2};

  RM_Set_AcqExitIfError_FILEID(__FILEID__);

  DAQ_ResetPIF(DAQ_DEFAULT_ETO_TICS,DAQ_MAX_DTO_TICS,SM_DAQSETUP,HB_PKTTYPE_RSV_AC_CALIB1);

  for(i=0;i<2;i++) {
    if(ac_ok[i] && ac_on[i]) {
      PM_pi_SetPktType(ac_pkttype[i]);

      DAQ_Format_CMD_Empty(&AC_TempPif0);
      
      CH_GetBuf(CH_AC_RESET_DSP,&auto_buf);
      DAQ_Format_Fe2Daq(&AC_TempPif0,auto_buf,ac_fe[i]);
      
      status = DAQ_StoreCmdQueue2PIF(SM_CALEXP0,&AC_TempPif0);
      RM_EXIT_IFERROR(status);
      
      status = DAQ_SendCmd2PIFWaitDAQReply(SM_CALEXP0,DAQ_NO_STORE_MM,&daq_reply,DAQ_STORE_RAM);
      RM_EXIT_IFERROR(status);
      
      DAQ_Format_CMD_Empty(&AC_TempPif0);
      DAQ_Format_Fe2Daq(&AC_TempPif0,&AC_SEND_DSP_PROG1,ac_fe[i]);
      
      status = DAQ_StoreCmdQueue2PIF(SM_CALEXP0,&AC_TempPif0);
      RM_EXIT_IFERROR(status);
      
      status = DAQ_SendCmd2PIFWaitDAQReply(SM_CALEXP0,DAQ_NO_STORE_MM,&daq_reply,DAQ_STORE_RAM);
      RM_EXIT_IFERROR(status);
      
      DAQ_Format_CMD_Empty(&AC_TempPif0);
      
      DAQ_Format_Fe2Daq(&AC_TempPif0,ac_send_dsp_prog2[i],ac_fe[i]);
      CH_GetBuf(CH_AC_CHANGE_MODE_CALIB,&auto_buf);
      DAQ_Format_Fe2Daq(&AC_TempPif0,auto_buf,ac_fe[i]);
      
      status = DAQ_StoreCmdQueue2PIF(SM_CALEXP1,&AC_TempPif0);
      RM_EXIT_IFERROR(status);
      
      status = DAQ_SendCmd2PIFWaitDAQReply(SM_CALEXP1,DAQ_NO_STORE_MM,&daq_reply,DAQ_STORE_RAM);
      RM_EXIT_IFERROR(status);
    }
  }

  status = RM_TaskSuspendUnlessSINT(2500);
  RM_EXIT_IFERROR(status);

  for(i=0;i<2;i++) {
    if(ac_ok[i] && ac_on[i]) {
      PM_pi_SetPktType(ac_pkttype[i]);

      DAQ_Format_CMD_Empty(&AC_TempPif0);
      DAQ_Format_Fe2Daq(&AC_TempPif0,ac_set_daq[i],ac_fe[i]);
      CH_GetBuf(CH_AC_CHANGE_MODE_PHYS,&auto_buf);
      DAQ_Format_Fe2Daq(&AC_TempPif0,auto_buf,ac_fe[i]);
      status = DAQ_StoreCmdQueue2PIF(SM_CALEXP2,&AC_TempPif0);
      RM_EXIT_IFERROR(status);
      
      status = DAQ_SendCmd2PIFWaitDAQReply(SM_CALEXP2,DAQ_STORE_MM,&daq_reply,DAQ_NO_STORE_RAM);
      RM_EXIT_IFERROR(status);
    }
  }
  return status;
}


status_code AC_Calibration2() 
{


  status_code status = CM_RC_SUCCESSFUL;
  DAQ_CMD_BUF* auto_buf;
  UINT16 alarm_reg;
  int i;
  UINT16      ac_ok[2] = {PRH_VAR_AC_1_OK,PRH_VAR_AC_2_OK};
  UINT16      ac_on[2] = {PRH_VAR_AC_1_ON,PRH_VAR_AC_2_ON};
  DAQ_FE      ac_fe[2]             = {DAQ_FE_AC_1,DAQ_FE_AC_2};
  BYTE        ac_pkttype[2]        = {HB_PKTTYPE_CALIB2_AC_1,HB_PKTTYPE_CALIB2_AC_2};

  RM_Set_AcqExitIfError_FILEID(__FILEID__);

  DAQ_ResetPIF(DAQ_DEFAULT_ETO_TICS,DAQ_MAX_DTO_TICS,SM_DAQSETUP,HB_PKTTYPE_RSV_AC_CALIB2);

  for(i=0;i<2;i++) {
    if(ac_ok[i] && ac_on[i]) {
      
      PM_pi_SetPktType(ac_pkttype[i]);

      DAQ_Format_CMD_Empty(&AC_TempPif0);
      DAQ_Format_Fe2Daq(&AC_TempPif0,&AC_READ_DSP_MEM,ac_fe[i]);
      CH_GetBuf(CH_AC_RESET_DSP,&auto_buf);
      DAQ_Format_Fe2Daq(&AC_TempPif0,auto_buf,ac_fe[i]);

      status = DAQ_StoreCmdQueue2PIF(SM_CALEXP2,&AC_TempPif0);
      RM_EXIT_IFERROR(status);
      
      status = DAQ_SendCmd2PIFWaitDAQReply(SM_CALEXP2,DAQ_STORE_MM,&daq_reply,DAQ_NO_STORE_RAM);
      RM_EXIT_IFERROR(status);
      
      if(i == AC_1)
	status=AC_1_Initialization();
      else
	status=AC_2_Initialization();

      RM_EXIT_IFERROR(status);

    }
  }

  return status;
}

status_code AC_Error_Handler(DAQ_FE fe)
{
  UINT32 AC_Count2 = 0;
  DAQ_CMD_BUF *auto_buf;
  status_code status;
  BOOL do_power_off_on=FALSE;
  BOOL do_reset=FALSE;

  DAQ_Format_CMD_Empty(&AC_TempPif0);

  CH_GetBuf(CH_AC_READ_STATUS,&auto_buf);
  DAQ_Format_Fe2Daq(&AC_TempPif0,auto_buf,fe);


  status = DAQ_StoreCmdQueue2PIF(SM_CALEXP0,&AC_TempPif0);

  if(status == CM_RC_SUCCESSFUL) {
    do {
      AC_Count2++;

      status = DAQ_SendCmd2PIFWaitDAQReply(SM_CALEXP0,DAQ_STORE_MM,&daq_reply,DAQ_STORE_RAM);
      if(status != CM_RC_SUCCESSFUL)
	return CM_RC_DO_RESET_IF_ALM;

      do_reset = ((signed int)daq_reply.len) - AC_SKIP_HEADER < 4;
      
    } while( do_reset && (AC_Count2 <= PRH_VAR_AC_LOOP2));

    if(!do_reset)
      do_power_off_on=
	(  daq_reply.buf[AC_SKIP_HEADER+1]        != 0xFF) ||
	( (daq_reply.buf[AC_SKIP_HEADER  ] & 0x1) != 0x1)  ;


    DAQ_Format_CMD_Empty(&AC_TempPif0);

    CH_GetBuf(CH_AC_STATUS_RESET,&auto_buf);
    DAQ_Format_Fe2Daq(&AC_TempPif0,auto_buf,fe);

    status = DAQ_StoreCmdQueue2PIF(SM_CALEXP1,&AC_TempPif0);
    if(status != CM_RC_SUCCESSFUL)
      return do_power_off_on ? CM_RC_DO_POWER_OFF_ON : CM_RC_DO_RESET_IF_ALM;
    
    status = DAQ_SendCmd2PIFWaitDAQReply(SM_CALEXP1,DAQ_STORE_MM,&daq_reply,DAQ_NO_STORE_RAM);
    if(status != CM_RC_SUCCESSFUL)
      return do_power_off_on ? CM_RC_DO_POWER_OFF_ON : CM_RC_DO_RESET_IF_ALM;

    if(!do_power_off_on && !do_reset) 
      if(fe == DAQ_FE_AC_2)
	status = AC_2_Initialization();
      else
	status = AC_1_Initialization();
    
    if(status != CM_RC_SUCCESSFUL || do_reset || do_power_off_on )
      return do_power_off_on ? CM_RC_DO_POWER_OFF_ON : CM_RC_DO_RESET_IF_ALM;

  }else
    status = CM_RC_DO_RESET_IF_ALM;

  return status;
}




