/************************************************/
/*                                              */
/* File        : calbhard.h                     */
/* Description : Calorimeter Boards             */
/*                    hardware base access      */
/*                                              */
/* Authors: G.Cabibbo, A.Passeri                 */
/*                                              */
/* Created      : 07.02.1997                    */
/* Last modified: 30.12.1997                    */
/*                                              */
/************************************************/

#ifndef CALBHARD_H
#define CALBHARD_H

#include <GeoVme.h>

/************************************************/
/*                                              */
/*   The result should be CALBH_ERROR_OK,       */
/*   else there have been an error              */
/*   (see CALBH_ERROR_.. constants)             */
/*   if not stated otherwise                    */
/*                                              */
/************************************************/

#define CALBH_ERROR_OK            0     /* MUST be 0 */
#define CALBH_ERROR_TEST          -1
#define CALBH_ERROR_UNKNOWN       -10
#define CALBH_ERROR_OUTRANGE      -9
#define CALBH_WARNING_ZSUP        -2


/********************************************************************/
/*                      Register offsets                            */
/*                DO NOT USE DIRECTLY IF NOT REALLY NECESSARY       */
/********************************************************************/

/* internal registers (16 bit)*/
#define CALBH_CREG_ofs	        0x3c         /*  R/W  */
#define CALBH_SREG_ofs          0x3e         /*   R   */
#define CALBH_RDTRG_ofs         0x4a         /*   R   */
#define CALBH_RESET_ofs         0x4c         /*   W   */
#define CALBH_CLRTRG_ofs        0x4e         /*   W   */
#define CALBH_SWTRG_ofs         0x50         /*   W   */


/* FIFO registers I/O  (32 bit)*/
#define CALBH_HFIFO_ofs   	0x40	
#define CALBH_DFIFO_ofs   	0x44	

/********************************************************************/
/*                          Page offsets                            */
/*                DO NOT USE DIRECTLY IF NOT REALLY NECESSARY       */
/********************************************************************/

#define CALBH_PAGE_LATCH_ofs	0x0000       /*   R   */
#define CALBH_PAGE_CSR_ofs	0x003c       /*   R   */
#define CALBH_PAGE_PED_A_ofs	0x4000       /*  R/W  */
#define CALBH_PAGE_PED_B_ofs	0x4040       /*  R/W  */
#define CALBH_PAGE_ZSUP1_A_ofs	0x8000       /*  R/W  */
#define CALBH_PAGE_ZSUP1_B_ofs	0xA000       /*  R/W  */
#define CALBH_PAGE_ZSUP2_A_ofs	0xC000       /*  R/W  */
#define CALBH_PAGE_ZSUP2_B_ofs	0xE000       /*  R/W  */

/*********************************************************************/
/*                          CALB hard id type                        */
/*********************************************************************/

typedef struct 
         {
	   int cid;                    /* VME channel id  */

           int chain;                  /* VIC chain       */
           int crate;                  /* position in the VIC chain */
           int slot;                   /* position in the crate */

	   unsigned int vme_addr;      /* VME address     */
	   unsigned int vme_am;        /* VME am          */
	   unsigned int offs;          /* CALB offs       */
	   void *map_ptr;              /* VME map pointer */

           int btype;                  /* board type: 1=ADC, 2=TDC */
           int sernum;                 /* serial number  */
	 } CALBH_id_base;

typedef CALBH_id_base *CALBH_id;

/*********************************************************************/
/*                          CALB info type                           */
/*********************************************************************/

typedef struct
{
  int btype;
  int sernum;
} CALBH_info;

/*********************************************************************/
/*                             readpage types                        */
/*********************************************************************/

typedef struct
         {
	   unsigned short creg;
	   unsigned short sreg; /*************warning************/
         } CALBH_CSR_regs;

/*********************************************************************/
/*                             array  types                          */
/*********************************************************************/

typedef unsigned int CALBH_CHANNELS[30]; 
typedef unsigned int CALBH_CHALF[15]; 

/*********************************************************************/
/*                             pedestal struct type                  */
/*********************************************************************/

typedef struct
        {
           CALBH_CHANNELS ped_a; 
           CALBH_CHANNELS ped_b; 
        } CALBH_PEDS_val;

/*********************************************************************/
/*                          zero suppression struct type             */
/*********************************************************************/

#define  CALBH_ZSUP_MAXWIND  16
typedef struct
        {
           CALBH_CHANNELS nwind_a; 
           CALBH_CHANNELS nwind_b; 
        } CALBH_ZSUP_nwind;

typedef struct
        {
           CALBH_CHANNELS zlow_a; 
           CALBH_CHANNELS zlow_b; 
           CALBH_CHANNELS zhig_a; 
           CALBH_CHANNELS zhig_b; 
        } CALBH_ZSUP_val[CALBH_ZSUP_MAXWIND];

typedef struct
        {
           CALBH_CHALF zlow; 
           CALBH_CHALF zhig; 
        } CALBH_ZSUP_val_elem[CALBH_ZSUP_MAXWIND];


/*********************************************************************/
/*                Load info: definitions and routines                */
/*********************************************************************/

CALBH_info *calb_info[GEOVME_DIM_CHAINS][GEOVME_DIM_CRATES][GEOVME_DIM_SLOTS];

int calbh_loadinfo(char* calb_mapname);     /* IN */
int calbh_unloadinfo(void);
int calbh_sernum(int chain,int crate,int slot);
int calbh_btype(int chain,int crate,int slot);

/*********************************************************************/
/*                          Query routines                           */
/*********************************************************************/

/* returns 0 if a CALB board is not present, 1 else */
int calbh_ispresent(int chain,                   /* IN, VIC chain */
		    int crate,                   /* IN, position in the VIC chain  */
                    int slot);                   /* IN, position in the crate */

/*********************************************************************/
/*                       Initialization routines                     */
/*********************************************************************/

int calbh_open(int chain,                   /* IN  */
	       int crate,                   /* IN  */
	       int slot,                    /* IN  */
	       CALBH_id *calb_id);           /* OUT */

  /* For test purpose only */
int calbh_open_raw(unsigned int vme_addr,       /* IN  */
		   int vme_size,                /* IN  */
		   int vme_am,                  /* IN  */
		   int offs,                    /* IN  */
		   CALBH_id *calb_id);          /* OUT */

int calbh_close(CALBH_id calb_id);          /* IN  */

/*********************************************************************/
/*                       read routines                               */
/*                       return the read value                       */
/*********************************************************************/

/***********************/
/*        generic      */
/* Do not use directly */
/***********************/


unsigned short calbh_read_reg16(CALBH_id calb_id,     /* IN  */
				unsigned int offset); /* IN  */

unsigned int   calbh_read_reg32(CALBH_id calb_id,     /* IN  */
				unsigned int offset); /* IN  */

/***********************/
/*      Use this       */
/***********************/

/*  internal registers */

#define calbh_read_creg(/*CALBH_id*/ calb_id)  /* IN  */ \
	calbh_read_reg16(calb_id,CALBH_CREG_ofs)

#define calbh_read_sreg(/*CALBH_id*/ calb_id)  /* IN  */ \
	calbh_read_reg16(calb_id,CALBH_SREG_ofs)

#define calbh_read_rdtrg(/*CALBH_id*/ calb_id)  /* IN  */ \
	calbh_read_reg16(calb_id,CALBH_RDTRG_ofs)

/*  FIFO  */

#define calbh_read_hfifo(/*CALBH_id*/ calb_id)  /* IN  */ \
	calbh_read_reg32(calb_id,CALBH_HFIFO_ofs)

#define calbh_read_dfifo(/*CALBH_id*/ calb_id)  /* IN  */ \
	calbh_read_reg32(calb_id,CALBH_DFIFO_ofs)

/* Pedestal  */

#define calbh_read_ped_a(/*CALBH_id       */ calb_id,    /* IN  */  \
			 /*unsigned int   */ chan)     /* IN  */    \
        (unsigned int) (calbh_read_reg16(calb_id,CALBH_PAGE_PED_A_ofs+(chan*2))&0xfff)

#define calbh_read_ped_b(/*CALBH_id       */ calb_id,    /* IN  */  \
			 /*unsigned int   */ chan)     /* IN  */    \
        (unsigned int) (calbh_read_reg16(calb_id,CALBH_PAGE_PED_B_ofs+(chan*2))&0xfff)

/* Zero Suppression */

#define calbh_read_zsup_a(/*CALBH_id       */ calb_id,    /* IN  */  \
			  /*unsigned short */ bit_nr)     /* IN  */  \
        ((unsigned int) (calbh_read_reg16(calb_id,CALBH_PAGE_ZSUP1_A_ofs+((bit_nr)*2)) & 0x7fff) | \
	 (((unsigned int) (calbh_read_reg16(calb_id,CALBH_PAGE_ZSUP2_A_ofs+((bit_nr)*2))) & 0x7fff)<<15))

#define calbh_read_zsup_b(/*CALBH_id       */ calb_id,    /* IN  */  \
			  /*unsigned short */ bit_nr)     /* IN  */  \
        ((unsigned int) (calbh_read_reg16(calb_id,CALBH_PAGE_ZSUP1_B_ofs+((bit_nr)*2)) & 0x7fff) | \
	 (((unsigned int) (calbh_read_reg16(calb_id,CALBH_PAGE_ZSUP2_B_ofs+((bit_nr)*2)) & 0x7fff))<<15))


/*********************************************************************/
/*                       write routines                              */
/*********************************************************************/

/***********************/
/*        generic      */
/* Do not use directly */
/***********************/

int calbh_write_reg16(CALBH_id calb_id,         /* IN */
		      unsigned int offset,      /* IN */
		      unsigned short reg,       /* IN */
		      unsigned short testmask); /* IN, test if >0 */

/***********************/
/*      Use this       */
/***********************/

/* internal regs */

#define calbh_write_creg(/*CALBH_id      */ calb_id,  /* IN  */        \
			  /*unsigned char */ creg,    /* IN  */        \
			  /*char          */ test)     /* IN, bool  */  \
	calbh_write_reg16(calb_id,CALBH_CREG_ofs,creg,test*0xff)
        /*  only 8 significant bits in CREG  */

#define calbh_write_reset(/*CALBH_id      */ calb_id)  /* IN  */        \
	calbh_write_reg16(calb_id,CALBH_RESET_ofs,0,0)

#define calbh_write_clrtrg(/*CALBH_id      */ calb_id)  /* IN  */        \
	calbh_write_reg16(calb_id,CALBH_CLRTRG_ofs,0,0)

#define calbh_write_swtrg(/*CALBH_id      */ calb_id)  /* IN  */        \
	calbh_write_reg16(calb_id,CALBH_SWTRG_ofs,0,0)


/* Pedestal  */

#define calbh_write_ped_a(/*CALBH_id       */ calb_id,    /* IN  */  \
			 /*unsigned int     */ chan,     /* IN  */    \
			 /*unsigned short   */ value)     /* IN  */    \
        calbh_write_reg16(calb_id,CALBH_PAGE_PED_A_ofs+(chan*2),value,0xfff)

#define calbh_write_ped_b(/*CALBH_id       */ calb_id,    /* IN  */  \
			 /*unsigned int   */ chan,     /* IN  */    \
			 /*unsigned short   */ value)     /* IN  */    \
        calbh_write_reg16(calb_id,CALBH_PAGE_PED_B_ofs+(chan*2),value,0xfff)


/* zero suppression */
/* does not return a valid error value */

#define calbh_write_zsup_a(/*CALBH_id       */ calb_id,    /* IN  */  	\
			   /*unsigned short */ bit_nr,     /* IN  */  	\
			   /*unsigned int   */ data)       /* IN  */  	\
        {								\
	  calbh_write_reg16(calb_id,CALBH_PAGE_ZSUP1_A_ofs+((bit_nr)*2),data & 0x7fff,0);	\
	  calbh_write_reg16(calb_id,CALBH_PAGE_ZSUP2_A_ofs+((bit_nr)*2),data>>15,0);	\
        }

#define calbh_write_zsup_b(/*CALBH_id       */ calb_id,    /* IN  */  	\
			   /*unsigned short */ bit_nr,     /* IN  */  	\
			   /*unsigned int   */ data)       /* IN  */  	\
        {								\
	  calbh_write_reg16(calb_id,CALBH_PAGE_ZSUP1_B_ofs+((bit_nr)*2),data & 0x7fff,0);	\
	  calbh_write_reg16(calb_id,CALBH_PAGE_ZSUP2_B_ofs+((bit_nr)*2),data>>15,0);	\
        }


/*********************************************************************/
/*                     readLATCH routines                             */
/*********************************************************************/

/***********************/
/*       internal      */
/* Do not use directly */
/***********************/

int calbh_readlatch_i_chan (CALBH_id calb_id,                /* IN  */
			      unsigned int  chan);  /* IN */

int calbh_readlatch_i_all (CALBH_id calb_id,                /* IN  */
			      CALBH_CHANNELS   latch);  /* OUT */

/***********************/
/*      Use this       */
/***********************/

#define calbh_readlatch_chan(/*CALBH_id          */ calb_id,    /* IN  */  \
	               	/* unsigned int */ chan)   /* IN  */  \
	calbh_readlatch_i_chan(calb_id,chan)

#define calbh_readlatch_all(/*CALBH_id          */ calb_id,    /* IN  */  \
	               	/* CALBH_CHANNELS */ latch)   /* OUT */  \
	calbh_readlatch_i_all(calb_id,latch)


/*********************************************************************/
/*                     readpage routines                             */
/*********************************************************************/

/***********************/
/*       internal      */
/* Do not use directly */
/***********************/

int calbh_readpage_i_csr (CALBH_id calb_id,                /* IN  */
			      CALBH_CSR_regs *csr);  /* OUT */

int calbh_readpage_i_ped (CALBH_id calb_id,                /* IN  */
			      CALBH_PEDS_val *peds);  /* OUT */

int calbh_readpage_i_zsup (CALBH_id calb_id,                /* IN  */
                              CALBH_ZSUP_nwind  *zwind,  /* OUT */
			      CALBH_ZSUP_val zsup);  /* OUT */

int calbh_readpage_i_zsup_elem(CALBH_id calb_id /* IN  */,/* IN */ int zofs,
           /* OUT */ CALBH_CHALF z_nwind, /* OUT */ CALBH_ZSUP_val_elem zelem);

/***********************/
/*      Use this       */
/***********************/

#define calbh_readpage_csr(/*CALBH_id            */ calb_id,    /* IN  */  \
	               	/*CALBH_CSR_regs */ csr)   /* OUT */  \
	calbh_readpage_i_csr(calb_id,&(csr))

#define calbh_readpage_ped(/*CALBH_id            */ calb_id,    /* IN  */  \
	               	/* CALBH_PEDS_val  */ peds)   /* OUT */  \
	calbh_readpage_i_ped(calb_id,&(peds))

#define calbh_readpage_zsup(/*CALBH_id            */ calb_id,    /* IN  */  \
                        /* CALBH_ZSUP_nwind  */  zwind,   /* OUT */  \
	               	/* CALBH_ZSUP_val  */ zsup)   /* OUT */  \
	calbh_readpage_i_zsup(calb_id,&(zwind),zsup)

#define calbh_readpage_zsup_elem(/* CALBH_id */ calb_id /* IN  */,    \
                       /* IN */  zofs, /* OUT */  z_nwind, /* OUT */ zelem)  \
        calbh_readpage_i_zsup_elem(calb_id,zofs,z_nwind,zelem)

/*********************************************************************/
/*                     writepage routines                            */
/*********************************************************************/

/***********************/
/*       internal      */
/* Do not use directly */
/***********************/

int calbh_writepage_i_ped (CALBH_id calb_id,                /* IN  */
			      CALBH_PEDS_val *peds);  /* IN */

int calbh_writepage_i_zsup (CALBH_id calb_id,                /* IN  */
                              CALBH_ZSUP_nwind  *zwind,     /* IN */
			      CALBH_ZSUP_val zsup);  /* IN */

int calbh_writepage_i_zsup_elem(CALBH_id calb_id /* IN  */, /* IN */ int zofs,
    	     /* IN */ CALBH_CHALF z_nwind, /* IN */ CALBH_ZSUP_val_elem zelem);

/***********************/
/*      Use this       */
/***********************/

#define calbh_writepage_ped(/*CALBH_id            */ calb_id,    /* IN  */  \
	               	/* CALBH_PEDS_val  */ peds)   /* IN */  \
	calbh_writepage_i_ped(calb_id,&(peds))

#define calbh_writepage_zsup(/*CALBH_id            */ calb_id,    /* IN  */  \
                        /* CALBH_ZSUP_nwind */  zwind,  /* IN */  \
	               	/* CALBH_ZSUP_val  */ zsup)   /*IN  */  \
	calbh_writepage_i_zsup(calb_id,&(zwind),zsup)

#define calbh_writepage_zsup_elem( calb_id /* IN  */, /* IN */ zofs, \
                                       /* IN */ z_nwind, /* IN */ zelem) \
        calbh_writepage_i_zsup_elem(calb_id,zofs,z_nwind,zelem)

/*********************************************************************/
/*                     readfifo routines                             */
/*********************************************************************/

/***********************/
/*        generic      */
/* Do not use directly */
/***********************/

int calbh_read_pio_i_hfifo (CALBH_id calb_id,	/* IN  */
			unsigned int nels,	/* IN  */
			unsigned int *buffer,	/* OUT */
			unsigned int *count);	/* OUT, nr of els really read */

int calbh_read_pio_i_dfifo (CALBH_id calb_id,	/* IN  */
			unsigned int nels,	/* IN  */
			unsigned int *buffer,	/* OUT */
			unsigned int *count);	/* OUT, nr of els really read */

int calbh_read_blt_fifo (CALBH_id calb_id,	/* IN  */
			unsigned int offset,	/* IN  */
			unsigned int nrels,	/* IN  */
			unsigned int *buffer,	/* OUT */
			unsigned int *count);	/* OUT, nr of els really read */

/***********************/
/*      Use this       */
/***********************/

#define calbh_read_pio_hfifo(/*CALBH_id       */ calb_id,	/* IN  */    \
			     /*unsigned int   */ count,		/* IN nr els to read, OUT nr els really read */    \
			     /*unsigned int * */ buffer)	/* OUT */ \
	calbh_read_pio_i_hfifo(calb_id,count,buffer,&(count))

#define calbh_read_pio_dfifo(/*CALBH_id       */ calb_id,	/* IN  */    \
			     /*unsigned int   */ count,		/* IN nr els to read, OUT nr els really read */    \
			     /*unsigned int * */ buffer)	/* OUT */ \
	calbh_read_pio_i_dfifo(calb_id,count,buffer,&(count))

#define calbh_read_blt_dfifo(/*CALBH_id       */ calb_id,	/* IN  */    \
			     /*unsigned int   */ count,		/* IN nr els to read, OUT nr els really read */    \
			     /*unsigned int * */ buffer)	/* OUT */ \
	calbh_read_blt_fifo(calb_id,CALBH_DFIFO_ofs,count,buffer,&(count))


/**********
   parse utility
***********/
#define myparse(/* char * */ buff) \
   {   \
     while(buff[0]==' ') buff++; \
     while(buff[0]!=' ') buff++; \
     buff++;  \
   }

#endif /* CALBHARD_H */