Caen775Lib.c Code

From New IAC Wiki
Jump to navigation Jump to search

caenLib.c

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

  • caen775Lib.c - Driver library for readout of C.A.E.N. Model 775 TDC
  • using a VxWorks 5.2 or later based Single Board computer.
  • Author: David Abbott
  • Jefferson Lab Data Acquisition Group
  • March 2002
  • Revision 1.0 - Initial Revision
  • - Supports up to 20 CAEN Model 775s in a Crate
  • - Programmed I/O reads
  • - Interrupts from a Single 775
  • /
  1. include "vxWorks.h"
  2. include "stdio.h"
  3. include "string.h"
  4. include "logLib.h"
  5. include "taskLib.h"
  6. include "intLib.h"
  7. include "iv.h"
  8. include "semLib.h"
  9. include "vxLib.h"

/* Include TDC definitions */

  1. include "c775Lib.h"

/* Include DMA Library definintions */

  1. ifdef VXWORKSPPC
  2. include "universeDma.h"
  3. else
  4. include "mvme_dma.c"
  5. endif

/* Define external Functions */ IMPORT STATUS sysBusToLocalAdrs(int, char *, char **); IMPORT STATUS intDisconnect(int); IMPORT STATUS sysIntEnable(int); IMPORT STATUS sysIntDisable(int);

/* Define Interrupts variables */ BOOL c775IntRunning = FALSE; /* running flag */ int c775IntID = -1; /* id number of TD C generating interrupts */ LOCAL VOIDFUNCPTR c775IntRoutine = NULL; /* user interrupt service routine */ LOCAL int c775IntArg = 0; /* arg to user rou tine */ LOCAL int c775IntEvCount = 0; /* Number of Event s to generate Interrupt */ LOCAL UINT32 c775IntLevel = C775_VME_INT_LEVEL; /* default VME int errupt level */ LOCAL UINT32 c775IntVec = C775_INT_VEC; /* default interru pt Vector */


/* Define global variables */ int Nc775 = 0; /* Number of TDCs in Crate */ volatile struct c775_struct *c775p[20]; /* pointers to TDC memory map */ volatile struct c775_struct *c775pl[20]; /* Support for 68K second memory m ap A24/D32 */ int c775IntCount = 0; /* Count of interrupts from TDC */ int c775EventCount[20]; /* Count of Events taken by TDC (E vent Count Register value) */ int c775EvtReadCnt[20]; /* Count of events read from speci fied TDC */ SEM_ID c775Sem; /* Semephore for Task syncronizati on */

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

  • c775Init - Initialize c775 Library.
  • RETURNS: OK, or ERROR if the address is invalid or board is not present.
  • /

STATUS c775Init (UINT32 addr, UINT32 addr_inc, int nadc, UINT16 crateID) {

 int ii, res, rdata, errFlag = 0;
 int boardID = 0;
 unsigned long laddr, lladdr;
 volatile struct c775_ROM_struct *rp;


 /* Check for valid address */
 if(addr==0) {
   printf("c775Init: ERROR: Must specify a Bus (VME-based A32/A24) address for 

TDC 0\n");

   return(ERROR);
 }else if(addr < 0x00ffffff) { /* A24 Addressing */
   if((addr_inc==0)||(nadc==0))
     nadc = 1; /* assume only one TDC to initialize */
   /* get the TDCs address */
   res = sysBusToLocalAdrs(0x39,(char *)addr,(char **)&laddr);
   if (res != 0) {
     printf("c775Init: ERROR in sysBusToLocalAdrs(0x39,0x%x,&laddr) \n",addr);
     return(ERROR);
   }
 }else{ /* A32 Addressing */
  1. ifdef VXWORKS68K51
   printf("c775Init: ERROR: 68K Based CPU cannot support A32 addressing (use A2

4)\n");

   return(ERROR);
  1. endif
   if((addr_inc==0)||(nadc==0))
     nadc = 1; /* assume only one TDC to initialize */
   /* get the TDC address */
   res = sysBusToLocalAdrs(0x09,(char *)addr,(char **)&laddr);
   if (res != 0) {
     printf("c775Init: ERROR in sysBusToLocalAdrs(0x09,0x%x,&laddr) \n",addr);
     return(ERROR);
   }
 }
  /* Put in Hack for 68K seperate address spaces for A24/D16 and A24/D32 */
  /* for PowerPC they are one and the same */
  1. ifdef VXWORKS68K51
 lladdr = C775_68K_A24D32_OFFSET + (laddr&0x00ffffff);
  1. else
 lladdr = laddr;
  1. endif


 Nc775 = 0;
 for (ii=0;ii<nadc;ii++) {
   c775p[ii] = (struct c775_struct *)(laddr + ii*addr_inc);
   c775pl[ii] = (struct c775_struct *)(lladdr + ii*addr_inc);
   /* Check if Board exists at that address */
   res = vxMemProbe((char *) &(c775p[ii]->rev),0,2,(char *)&rdata);
   if(res < 0) {
     printf("c775Init: ERROR: No addressable board at addr=0x%x\n",(UINT32) c77

5p[ii]);

     c775p[ii] = NULL;
     errFlag = 1;
     break;
   } else {
     /* Check if this is a Model 775 */
     rp = (struct c775_ROM_struct *)((UINT32)c775p[ii] + C775_ROM_OFFSET);
     boardID = (((rp->ID_3)&(0xff))<<16) + (((rp->ID_2)&(0xff))<<8) + ((rp->ID_

1)&(0xff));

     if((boardID != C775_BOARD_ID)&&(boardID != C775_BOARD_ID)) {
       printf("c775Init: ERROR: Board ID does not match: %d \n",boardID);
       return(ERROR);
     }
   }
   Nc775++;
   printf("Initialized TDC ID %d at address 0x%08x \n",ii,(UINT32) c775p[ii]);
 }
 /* Initialize/Create Semephore */
 if(c775Sem != 0) {
   semFlush(c775Sem);
   semDelete(c775Sem);
 }
 c775Sem = semBCreate(SEM_Q_PRIORITY,SEM_EMPTY);
 if(c775Sem <= 0) {
   printf("c775Init: ERROR: Unable to create Binary Semephore\n");
   return(ERROR);
 }
 
 /* Disable/Clear all TDCs */
 for(ii=0;ii<Nc775;ii++) {
   C775_EXEC_SOFT_RESET(ii);
   C775_EXEC_DATA_RESET(ii);
   c775p[ii]->intLevel = 0;        /* Disable Interrupts */
   c775p[ii]->evTrigger = 0;       /* Zero interrupt trigger count */
   c775p[ii]->crateSelect = crateID;  /* Set Crate ID Register */
   c775p[ii]->bitClear2 = C775_INCR_ALL_TRIG; /* Increment event count only on
                                                accepted gates */
   c775EventCount[ii] =  0;          /* Initialize the Event Count */
   c775EvtReadCnt[ii] = -1;          /* Initialize the Read Count */
   c775SetFSR(ii,C775_MIN_FSR);  /* Set Full Scale Range for TDC */
  c775Sparse(ii,0,0);           /* Disable Overflow/Underflow suppression */
 }
 /* Initialize Interrupt variables */
 c775IntID = -1;
 c775IntRunning = FALSE;
 c775IntLevel = 0;
 c775IntVec = 0;
 c775IntRoutine = NULL;
 c775IntArg = 0;
 c775IntEvCount = 0;
   
 if(errFlag > 0) {
   printf("c775Init: ERROR: Unable to initialize all TDC Modules\n");
   if(Nc775 > 0)
     printf("c7752Init: %d TDC(s) successfully initialized\n",Nc775);
   return(ERROR);
 } else {
   return(OK);
 }

}

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

  • c775Status - Gives Status info on specified TDC
  • RETURNS: None
  • /

void c775Status( int id, int reg, int sflag) {

 int DRdy=0, BufFull=0;
 UINT16 stat1, stat2, bit1, bit2, cntl1;
 UINT16 iLvl, iVec, evTrig;
 UINT16 fsr;    
 if((id<0) || (c775p[id] == NULL)) {
   printf("c775Status: ERROR : TDC id %d not initialized \n",id);
   return;
 }


 /* read various registers */
 stat1 = (c775p[id]->status1)&C775_STATUS1_MASK;
 stat2 = (c775p[id]->status2)&C775_STATUS2_MASK;
 bit1 =  (c775p[id]->bitSet1)&C775_BITSET1_MASK;
 bit2 =  (c775p[id]->bitSet2)&C775_BITSET2_MASK;
 cntl1 = (c775p[id]->control1)&C775_CONTROL1_MASK;
 fsr =   4*(290 - ((c775p[id]->iped)&C775_FSR_MASK));
 C775_EXEC_READ_EVENT_COUNT(id);
 if(stat1&C775_DATA_READY) DRdy = 1;
 if(stat2&C775_BUFFER_FULL) BufFull = 1;
 
 iLvl = (c775p[id]->intLevel)&C775_INTLEVEL_MASK;
 iVec = (c775p[id]->intVector)&C775_INTVECTOR_MASK;
 evTrig = (c775p[id]->evTrigger)&C775_EVTRIGGER_MASK;
 /* print out status info */
 printf("STATUS for TDC id %d at base address 0x%x \n",id,(UINT32) c775p[id]);
 printf("---------------------------------------------- \n");
 if( (iLvl>0) && (evTrig>0)) {
   printf(" Interrupts Enabled - Every %d events\n",evTrig);
   printf(" VME Interrupt Level: %d   Vector: 0x%x \n",iLvl,iVec);
   printf(" Interrupt Count    : %d \n",c775IntCount);
 } else {
   printf(" Interrupts Disabled\n");
   printf(" Last Interrupt Count    : %d \n",c775IntCount);
 }
 printf("\n");
 printf("             --1--  --2--\n");
 if(BufFull && DRdy) {
   printf("  Status  = 0x%04x 0x%04x  (Buffer Full)\n",stat1,stat2);
 } else if(DRdy) {
   printf("  Status  = 0x%04x 0x%04x  (Data Ready)\n",stat1,stat2);
 }else{
   printf("  Status  = 0x%04x 0x%04x\n",stat1,stat2);
 }
 printf("  BitSet  = 0x%04x 0x%04x\n",bit1,bit2);
 printf("  Control = 0x%04x\n",cntl1);
 printf("  FSR     = %d nsec\n",fsr);
 if(c775EventCount[id] == 0xffffff) {
   printf("  Event Count     = (No Events Taken)\n");
   printf("  Last Event Read = (No Events Read)\n");
 }else{
   printf("  Event Count     = %d\n",c775EventCount[id]);
   if(c775EvtReadCnt[id] == -1)
     printf("  Last Event Read = (No Events Read)\n");
   else
     printf("  Last Event Read = %d\n",c775EvtReadCnt[id]);
 }

}

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

  • c775PrintEvent - Print event from TDC to standard out.
  • RETURNS: Number of Data words read from the TDC (including Header/Trailer).
  • /

int c775PrintEvent(int id, int pflag) {

 int ii, nWords, evID;
 UINT32 header, trailer, dCnt;
 if((id<0) || (c775p[id] == NULL)) {
   printf("c775ClearThresh: ERROR : TDC id %d not initialized \n",id);
   return(-1);
 }
 /* Check if there is a valid event */
 if((c775p[id]->status2)&C775_BUFFER_EMPTY) {
   printf("c775PrintEvent: Data Buffer is EMPTY!\n");
   return(0);
 }
 if((c775p[id]->status1)&C775_DATA_READY) {
   dCnt = 0;
   /* Read Header - Get Word count */
   header = c775pl[id]->data[0];
   if((header&C775_DATA_ID_MASK) != C775_HEADER_DATA) {
     printf("c775PrintEvent: ERROR: Invalid Header Word 0x%08x\n",header);
     return(-1);
   }else{
     printf("  TDC DATA for Module %d\n",id);
     nWords = (header&C775_WORDCOUNT_MASK)>>8;
     dCnt++;
     printf("  Header: 0x%08x   nWords = %d ",header,nWords);
  }
   for(ii=0;ii<nWords;ii++) {
     if ((ii % 5) == 0) printf("\n    ");
     printf("  0x%08x",(UINT32) c775pl[id]->data[ii+1]);
   }
   printf("\n");
   dCnt += ii;
   trailer = c775pl[id]->data[dCnt];
   if((trailer&C775_DATA_ID_MASK) != C775_TRAILER_DATA) {
     printf("c775PrintEvent: ERROR: Invalid Trailer Word 0x%08x\n",trailer);
     return(-1);
   }else{
     evID = trailer&C775_EVENTCOUNT_MASK;
     dCnt++;
     printf("  Trailer: 0x%08x   Event Count = %d \n",trailer,evID);
   }
   C775_EXEC_SET_EVTREADCNT(id,evID);
   return (dCnt);
 }else{
   printf("c775PrintEvent: Data Not ready for readout!\n");
   return(0);
 }

}


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

  • c775ReadEvent - Read event from TDC to specified address.
  • RETURNS: Number of Data words read from the TDC (including Header/Trailer).
  • /

int c775ReadEvent(int id, UINT32 *data) {

 int ii, nWords, evID;
 UINT32 header, trailer, dCnt;
 if((id<0) || (c775p[id] == NULL)) {
   logMsg("c775ReadEvent: ERROR : TDC id %d not initialized \n",id,0,0,0,0,0);
   return(-1);
 }
 /* Check if there is a valid event */
 if((c775p[id]->status2)&C775_BUFFER_EMPTY) {
   logMsg("c775ReadEvent: Data Buffer is EMPTY!\n",0,0,0,0,0,0);
   return(0);
 }
 if((c775p[id]->status1)&C775_DATA_READY) {
   dCnt = 0;
   /* Read Header - Get Word count */
   header = c775pl[id]->data[dCnt];
   if((header&C775_DATA_ID_MASK) != C775_HEADER_DATA) {
     logMsg("c775ReadEvent: ERROR: Invalid Header Word 0x%08x\n",header,0,0,0,0

,0);

     return(-1);
   }else{
     nWords = (header&C775_WORDCOUNT_MASK)>>8;
     data[dCnt] = header;
     dCnt++;
   }
   for(ii=0;ii<nWords;ii++) {
     data[ii+1] = c775pl[id]->data[ii+1];
  }
   dCnt += ii;
   trailer = c775pl[id]->data[dCnt];
   if((trailer&C775_DATA_ID_MASK) != C775_TRAILER_DATA) {
     logMsg("c775ReadEvent: ERROR: Invalid Trailer Word 0x%08x\n",trailer,0,0,0

,0,0);

     return(-1);
   }else{
     evID = trailer&C775_EVENTCOUNT_MASK;
     data[dCnt] = trailer;
     dCnt++;
   }
   C775_EXEC_SET_EVTREADCNT(id,evID);
   return (dCnt);
 }else{
   logMsg("c775ReadEvent: Data Not ready for readout!\n",0,0,0,0,0,0);
   return(0);
 }

}

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

  • c775FlushEvent - Flush event/data from TDC.
  • RETURNS: Number of Data words read from the TDC.
  • /

int c775FlushEvent(int id, int fflag) {

 int evID;
 int done = 0;
 UINT32 tmpData, dCnt;
 if((id<0) || (c775p[id] == NULL)) {
   logMsg("c775FlushEvent: ERROR : TDC id %d not initialized \n",id,0,0,0,0,0);
   return(-1);
 }
 /* Check if there is a valid event */
 if((c775p[id]->status2)&C775_BUFFER_EMPTY) {
   if(fflag > 0) logMsg("c775FlushEvent: Data Buffer is EMPTY!\n",0,0,0,0,0,0);
   return(0);
 }
 /* Check if Data Ready Flag is on */
 if((c775p[id]->status1)&C775_DATA_READY) {
   dCnt = 0;
   
   while (!done) {
     tmpData = c775pl[id]->data[dCnt];
     switch (tmpData&C775_DATA_ID_MASK) {
     case C775_HEADER_DATA:
       if(fflag > 0) logMsg("c775FlushEvent: Found Header 0x%08x\n",tmpData,0,0

,0,0,0);

       break;
     case C775_DATA:
       break;
     case C775_TRAILER_DATA:
       if(fflag > 0) logMsg(" c775FlushEvent: Found Trailer 0x%08x\n",tmpData,0

,0,0,0,0);

       evID = tmpData&C775_EVENTCOUNT_MASK;
       C775_EXEC_SET_EVTREADCNT(id,evID);
       done = 1;
       break;
     case C775_INVALID_DATA:
       if(fflag > 0) logMsg(" c775FlushEvent: Buffer Empty 0x%08x\n",tmpData,0,

0,0,0,0);

       done = 1;
       break;
     default:
       if(fflag > 0) logMsg(" c775FlushEvent: Invalid Data 0x%08x\n",tmpData,0,

0,0,0,0);

     }
     /* Print out Data */
     if(fflag > 1) {
       if ((dCnt % 5) == 0) printf("\n    ");
       printf("  0x%08x ",tmpData);
     }
     dCnt++;
   }
   if(fflag > 1) printf("\n");
   return (dCnt);
 }else{
   if(fflag > 0) logMsg("c775FlushEvent: Data Not ready for readout!\n",0,0,0,0

,0,0);

   return(0);
 }

}


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

  • c775ReadBlock - Read Block of events from TDC to specified address.
  • INPUTS: id - module id of TDC to access
  • data - address of data destination
  • nwrds - number of data words to transfer
  • RETURNS: OK or ERROR on success of transfer.
  • Note: User must call c775IncrEventBlk after a successful
  • call to c775ReadBlock to increment the number of events Read.
  • (e.g. c775IncrEventBlk(0,15);
  • /

int c775ReadBlock(int id, volatile UINT32 *data, int nwrds) {

 int retVal, xferCount;
 UINT32 evID;
 UINT16 stat = 0;
 if((id<0) || (c775p[id] == NULL)) {
   logMsg("c775ReadBlock: ERROR : TDC id %d not initialized \n",id,0,0,0,0,0);
   return(-1);
 }


  1. ifdef VXWORKSPPC
 /* Don't bother checking if there is a valid event. Just blast data out of the

    FIFO Valid or Invalid 
    Also assume that the Universe DMA programming is setup. */
 retVal = sysVmeDmaSend((UINT32)data, (UINT32)(c775pl[id]->data), (nwrds<<2), 0

);

 if(retVal < 0) {
   logMsg("c775ReadBlock: ERROR in DMA transfer Initialization 0x%x\n",retVal,0

,0,0,0,0);

   return(retVal);
 }
 /* Wait until Done or Error */
 retVal = sysVmeDmaDone(1000,1);
  1. else
 /* 68K Block 32 transfer from FIFO using VME2Chip */
 retVal = mvme_dma((long)data, 1, (long)(c775pl[id]->data), 0, nwrds, 1);
  1. endif
 if(retVal != 0) {
   /* Check to see if error was generated by TDC */
   stat = (c775p[id]->bitSet1)&C775_VME_BUS_ERROR;
   if((retVal>0) && (stat)) {
     c775p[id]->bitClear1 = C775_VME_BUS_ERROR;
     logMsg("c775ReadBlock: INFO: DMA terminated by TDC(BUS Error) - Transfer O

K\n",0,0,0,0,0,0);

     xferCount = (nwrds - (retVal>>2));  /* Number of Longwords transfered */
     if ((data[xferCount-1]&C775_DATA_ID_MASK) == C775_TRAILER_DATA) {
       evID = data[xferCount-1]&C775_EVENTCOUNT_MASK;
       C775_EXEC_SET_EVTREADCNT(id,evID);
       return(xferCount); /* Return number of data words transfered */
     } else {
       logMsg("c775ReadBlock: ERROR: Invalid Trailer data 0x%x\n",data[xferCoun

t-1],0,0,0,0,0);

       return(xferCount);
     }
   } else {
     logMsg("c775ReadBlock: ERROR in DMA transfer 0x%x\n",retVal,0,0,0,0,0);
     return(retVal);
   }
 }
 return(OK);

}


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

  • c775Int - default interrupt handler
  • This rountine handles the c775 TDC interrupt. A user routine is
  • called, if one was connected by c775IntConnect().
  • RETURNS: N/A
  • /

LOCAL void c775Int (void) {

 int ii=0;
 UINT32 nevt=0;
 
 /* Disable interrupts */
 sysIntDisable(c775IntLevel);
 c775IntCount++;

 if (c775IntRoutine != NULL)  {     /* call user routine */
   (*c775IntRoutine) (c775IntArg);
 }else{
   if((c775IntID<0) || (c775p[c775IntID] == NULL)) {
     logMsg("c775Int: ERROR : TDC id %d not initialized \n",c775IntID,0,0,0,0,0

);

     return;
   }
   /* Default action is to increment the Read pointer by
      the number of events in the Event Trigger register
      or until the Data buffer is empty. The later case would
      indicate a possible error. In either case the data is
      effectively thrown away */
   nevt = (c775p[c775IntID]->evTrigger)&C775_EVTRIGGER_MASK;
   while ( (ii<nevt) && (c775Dready(c775IntID) > 0) ) {
     C775_EXEC_INCR_EVENT(c775IntID);
     ii++;
   }
   if(ii<nevt)
     logMsg("c775Int: WARN : TDC %d - Events dumped (%d) != Events Triggered (%

d)\n",

            c775IntID,ii,nevt,0,0,0);
   logMsg("c775Int: Processed %d events\n",nevt,0,0,0,0,0);
 }
 /* Enable interrupts */
 sysIntEnable(c775IntLevel);

}


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

  • c775IntConnect - connect a user routine to the c775 TDC interrupt
  • This routine specifies the user interrupt routine to be called at each
  • interrupt.
  • RETURNS: OK, or ERROR if Interrupts are enabled
  • /

STATUS c775IntConnect (VOIDFUNCPTR routine, int arg, UINT16 level, UINT16 vector) {

 if(c775IntRunning) {
   printf("c775IntConnect: ERROR : Interrupts already Initialized for TDC id %d

\n",

          c775IntID);
   return(ERROR);
 }

 c775IntRoutine = routine;
 c775IntArg = arg;
 /* Check for user defined VME interrupt level and vector */
 if(level == 0) {
   c775IntLevel = C775_VME_INT_LEVEL; /* use default */
 }else if (level > 7) {
   printf("c775IntConnect: ERROR: Invalid VME interrupt level (%d). Must be (1-

7)\n",level);

   return(ERROR);
 } else {
   c775IntLevel = level;
 }
 if(vector == 0) {
   c775IntVec = C775_INT_VEC;  /* use default */
 }else if ((vector < 32)||(vector>255)) {
   printf("c775IntConnect: ERROR: Invalid interrupt vector (%d). Must be (32<ve

ctor<255)\n",vector);

   return(ERROR);
 }else{
   c775IntVec = vector;
 }
     
 /* Connect the ISR */
  1. ifdef VXWORKSPPC
 if((intDisconnect((int)INUM_TO_IVEC(c775IntVec)) != 0)) {
   printf("c775IntConnect: ERROR disconnecting Interrupt\n");
   return(ERROR);
 }
  1. endif
 if((intConnect(INUM_TO_IVEC(c775IntVec),c775Int,0)) != 0) {
   printf("c775IntConnect: ERROR in intConnect()\n");
   return(ERROR);
 }
 return (OK);

}


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

  • c775IntEnable - Enable interrupts from specified TDC
  • Enables interrupts for a specified TDC.
  • RETURNS OK or ERROR if TDC is not available or parameter is out of range
  • /

STATUS c775IntEnable (int id, UINT16 evCnt) {

 if(c775IntRunning) {
   printf("c775IntEnable: ERROR : Interrupts already initialized for TDC id %d\

n",

          c775IntID);
   return(ERROR);
 }
 if((id<0) || (c775p[id] == NULL)) {
   printf("c775IntEnable: ERROR : TDC id %d not initialized \n",id);
   return(ERROR);
 }else{
   c775IntID = id;
 }
 
 /* check for event count out of range */
 if((evCnt<=0) || (evCnt>31)) {
   printf("c775IntEnable: ERROR: Event count %d for Interrupt is out of range (

1-31)\n"

          ,evCnt);
   return(ERROR);
 }
 
 sysIntEnable(c775IntLevel);   /* Enable VME interrupts */
 
 /* Zero Counter and set Running Flag */
 c775IntEvCount = evCnt;
 c775IntCount = 0;
 c775IntRunning = TRUE;
 /* Enable interrupts on TDC */
 c775p[c775IntID]->intVector = c775IntVec;
 c775p[c775IntID]->intLevel = c775IntLevel;
 c775p[c775IntID]->evTrigger = c775IntEvCount;
 
 return(OK);

}


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

  • c775IntDisable - disable the TDC interrupts
  • RETURNS: OK, or ERROR if not initialized
  • /

STATUS c775IntDisable (int iflag) {

 if((c775IntID<0) || (c775p[c775IntID] == NULL)) {
   logMsg("c775IntDisable: ERROR : TDC id %d not initialized \n",c775IntID,0,0,

0,0,0);

   return(ERROR);
 }
 sysIntDisable(c775IntLevel);   /* Disable VME interrupts */
 c775p[c775IntID]->evTrigger = 0;
 /* Tell tasks that Interrupts have been disabled */
 if(iflag > 0) {
   c775IntRunning = FALSE;
   c775p[c775IntID]->intLevel = 0;
   c775p[c775IntID]->intVector = 0;
 }else{
   semGive(c775Sem);
 }
 
 return (OK);

}

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

  • c775IntResume - Re-enable interrupts from previously
  • intitialized TDC
  • RETURNS: OK, or ERROR if not initialized
  • /

STATUS c775IntResume (void) {

 UINT16 evTrig = 0;
 if((c775IntID<0) || (c775p[c775IntID] == NULL)) {
   logMsg("c775IntResume: ERROR : TDC id %d not initialized \n",c775IntID,0,0,0

,0,0);

   return(ERROR);
 }
 if ((c775IntRunning)) {
   evTrig = (c775p[c775IntID]->evTrigger)&C775_EVTRIGGER_MASK;
   if (evTrig == 0) {
     sysIntEnable(c775IntLevel);
     c775p[c775IntID]->evTrigger = c775IntEvCount;
   } else {
     logMsg("c775IntResume: WARNING : Interrupts already enabled \n",0,0,0,0,0,

0);

     return(ERROR);
   }
 } else {
     logMsg("c775IntResume: ERROR : Interrupts are not Enabled \n",0,0,0,0,0,0)
     return(ERROR);
 }
 
 return (OK);

}

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

  • c775Sparse - Enable/Disable Overflow and Under threshold sparsification
  • RETURNS: Bit Set 2 Register value.
  • /

UINT16 c775Sparse(int id, int over, int under) {

 if((id<0) || (c775p[id] == NULL)) {
   printf("c775Sparse: ERROR : TDC id %d not initialized \n",id);
   return(0xffff);
 }
 
 if(!over) {  /* Set Overflow suppression */
   c775p[id]->bitSet2 = C775_OVERFLOW_SUP;
 }else{
   c775p[id]->bitClear2 = C775_OVERFLOW_SUP;
 }
 if(!under) {  /* Set Underflow suppression */
   c775p[id]->bitSet2 = C775_UNDERFLOW_SUP;
 }else{
   c775p[id]->bitClear2 = C775_UNDERFLOW_SUP;
 }
 return((c775p[id]->bitSet2)&C775_BITSET2_MASK);

}


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

  • c775Dready - Return status of Data Ready bit in TDC
  • RETURNS: 0(No Data) or # of events in FIFO (1-32) or ERROR.
  • /

int c775Dready(int id) {

int nevts = 0;
 UINT16 stat=0;


 if((id<0) || (c775p[id] == NULL)) {
   logMsg("c775Dready: ERROR : TDC id %d not initialized \n",id,0,0,0,0,0);
   return (ERROR);
 }
 
 stat = (c775p[id]->status1)&C775_DATA_READY;
 if(stat) {
   C775_EXEC_READ_EVENT_COUNT(id);
   nevts = c775EventCount[id] - c775EvtReadCnt[id];
   if(nevts <= 0) {
     logMsg("c775Dready: ERROR : Bad Event Ready Count (nevts = %d)\n",
            nevts,0,0,0,0,0);
     return(ERROR);
   }
 }
 return(nevts);

}

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

  • c775SetFSR - Set and/or Return TDC full scale range programming
  • Register value: 0xff (255) -> 35 ps/count ( 140ns FSR )
  • range between: 0x1e ( 30) -> 300 ps/count ( 1200ns FSR )
  • FSR = 4*(290-reg)
  • reg = 290 - FSR/4
  • Note: Passing 0 for fsr will return the contents of the register
  • but not set it.
  • RETURNS: Full scale range of the TDC in nanoseconds or ERROR.
  • /

int c775SetFSR(int id, UINT16 fsr) {

 int rfsr=0;
 UINT16 reg;
 if((id<0) || (c775p[id] == NULL)) {
   logMsg("c775SetFSR: ERROR : TDC id %d not initialized \n",id,0,0,0,0,0);
   return (ERROR);
 }
 if(fsr==0) {
   reg = (c775p[id]->iped)&C775_FSR_MASK;
   rfsr = (int)(290 - reg)*4;
 }else if((fsr<C775_MIN_FSR)||(fsr>C775_MAX_FSR)) {
   logMsg("c775SetFSR: ERROR: FSR (%d ns) out of range (140<=FSR<=1200)\n",fsr,

0,0,0,0,0);

   return(ERROR);
 }else{
   reg = (UINT16)(290 - (fsr>>2));
   c775p[id]->iped = reg;
   reg = (c775p[id]->iped)&C775_FSR_MASK;
   rfsr = (int)(290 - reg)*4;
 }
 return(rfsr);

}

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

*
*
* c775BitSet2      - Program Bit Set 2 register
* c775BitClear2    - Program Bit clear 2 register
*
*/

INT16 c775BitSet2(int id, UINT16 val) {

 if((id<0) || (c775p[id] == NULL)) {
   logMsg("c775BitSet2: ERROR : TDC id %d not initialized \n",id,0,0,0,0,0);
   return (ERROR);
 }
 if(val)
   c775p[id]->bitSet2 = val;
 return((c775p[id]->bitSet2)&C775_BITSET2_MASK);

} INT16 c775BitClear2(int id, UINT16 val) {

 if((id<0) || (c775p[id] == NULL)) {
   logMsg("c775BitClear2: ERROR : TDC id %d not initialized \n",id,0,0,0,0,0);
   return (ERROR);
 }
 if(val)
   c775p[id]->bitClear2 = val;
 return((c775p[id]->bitSet2)&C775_BITSET2_MASK);

}


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

  • c775ClearThresh - Zero TDC thresholds for all channels
  • c775Gate - Issue Software Gate to TDC
  • c775IncrEventBlk - Increment Event counter for Block reads
  • c775IncrEvent - Increment Read pointer to next event in the Buffer
  • c775IncrWord - Increment Read pointer to next word in the event
  • c775Enable - Bring TDC Online (Enable Gates)
  • c775Disable - Bring TDC Offline (Disable Gates)
  • c775CommonStop - Program for Common Stop
  • c775CommonStart - Program for Common Start (Default)
  • c775Clear - Clear TDC
  • c775Reset - Clear/Reset TDC
  • RETURNS: None.
  • /

void c775ClearThresh(int id) {

 int ii;
 if((id<0) || (c775p[id] == NULL)) {
   logMsg("c775ClearThresh: ERROR : TDC id %d not initialized \n",id,0,0,0,0,0)
   return;
 }
 for (ii=0;ii< C775_MAX_CHANNELS; ii++) {
   c775p[id]->threshold[ii] = 0;
 }

}

void c775Gate(int id) {

 if((id<0) || (c775p[id] == NULL)) {
   logMsg("c775Gate: ERROR : TDC id %d not initialized \n",id,0,0,0,0,0);
   return;
 }
 C775_EXEC_GATE(id);

}

void c775IncrEventBlk(int id, int count) {

 if((id<0) || (c775p[id] == NULL)) {
   logMsg("c775IncrEventBlk: ERROR : TDC id %d not initialized \n",id,0,0,0,0,0

);

   return;
 }
 if((count > 0) && (count <=32))
   c775EvtReadCnt[id] += count;

}

void c775IncrEvent(int id) {

 if((id<0) || (c775p[id] == NULL)) {
   logMsg("c775IncrEvent: ERROR : TDC id %d not initialized \n",id,0,0,0,0,0);
   return;
 }
 C775_EXEC_INCR_EVENT(id);

}

void c775IncrWord(int id) {

 if((id<0) || (c775p[id] == NULL)) {
   logMsg("c775IncrWord: ERROR : TDC id %d not initialized \n",id,0,0,0,0,0);
   return;
 }
 C775_EXEC_INCR_WORD(id);

} void c775Enable(int id) {

 if((id<0) || (c775p[id] == NULL)) {
   logMsg("c775Enable: ERROR : TDC id %d not initialized \n",id,0,0,0,0,0);
   return;
 }
 c775p[id]->bitClear2 = C775_OFFLINE;

}

void c775Disable(int id) {

 if((id<0) || (c775p[id] == NULL)) {
   logMsg("c775Disable: ERROR : TDC id %d not initialized \n",id,0,0,0,0,0);
   return;
 }
 c775p[id]->bitSet2 = C775_OFFLINE;

}

void c775CommonStop(int id) {

 if((id<0) || (c775p[id] == NULL)) {
   logMsg("c775CommonStop: ERROR : TDC id %d not initialized \n",id,0,0,0,0,0);
   return;
 }
 c775p[id]->bitSet2 = C775_COMMON_STOP;

}

void c775CommonStart(int id) {

 if((id<0) || (c775p[id] == NULL)) {
   logMsg("c775CommonStart: ERROR : TDC id %d not initialized \n",id,0,0,0,0,0)
   return;
 }
 c775p[id]->bitClear2 = C775_COMMON_STOP;

}


void c775Clear(int id) {

 if((id<0) || (c775p[id] == NULL)) {
   logMsg("c775Clear: ERROR : TDC id %d not initialized \n",id,0,0,0,0,0);
   return;
 }
 C775_EXEC_DATA_RESET(id);
 c775EvtReadCnt[id] = -1;
 c775EventCount[id] =  0;

}

void c775Reset(int id) {

 if((id<0) || (c775p[id] == NULL)) {
   logMsg("c775Reset: ERROR : TDC id %d not initialized \n",id,0,0,0,0,0);
   return;
 }
 C775_EXEC_DATA_RESET(id);
 C775_EXEC_SOFT_RESET(id);
 c775EvtReadCnt[id] = -1;
 c775EventCount[id] =  0;

}

c775Lib.h

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

  • c775Lib.h - Driver library header file for readout of a C.A.E.N. multiple
  • Model 775 TDCs using a VxWorks 5.2 or later based single board
  • computer.
  • Author: David Abbott
  • Jefferson Lab Data Acquisition Group
  • March 2002
  • /


  1. define C775_MAX_CHANNELS 32
  2. define C775_MAX_WORDS_PER_EVENT 34

/* Define a Structure for access to TDC*/ struct c775_struct {

 volatile unsigned long  data[512];
 unsigned long blank1[512];
 volatile unsigned short rev;
 volatile unsigned short geoAddr;
 volatile unsigned short cbltAddr;
 volatile unsigned short bitSet1;
 volatile unsigned short bitClear1;
 volatile unsigned short intLevel;
 volatile unsigned short intVector;
 volatile unsigned short status1;
 volatile unsigned short control1;
 volatile unsigned short aderHigh;
 volatile unsigned short aderLow;
 volatile unsigned short ssReset;
 unsigned short blank2;
 volatile unsigned short cbltControl;
 unsigned short blank3[2];
 volatile unsigned short evTrigger;
 volatile unsigned short status2;
 volatile unsigned short evCountL;
 volatile unsigned short evCountH;
 volatile unsigned short incrEvent;
 volatile unsigned short incrOffset;
 volatile unsigned short loadTest;
 unsigned short blank4;
 volatile unsigned short fclrWindow;
 volatile unsigned short bitSet2;
 volatile unsigned short bitClear2;
 volatile unsigned short wMemTestAddr;
 volatile unsigned short memTestWordH;
 volatile unsigned short memTestWordL;
 volatile unsigned short crateSelect;
 volatile unsigned short testEvWrite;
 volatile unsigned short evCountReset;
 unsigned short blank5[15];
 volatile unsigned short iped;
unsigned short blank6;
 volatile unsigned short rTestAddr;
 unsigned short blank7;
 volatile unsigned short swComm;
 volatile unsigned short slideConst;
 unsigned short blank8[2];
 volatile unsigned short AAD;
 volatile unsigned short BAD;
 unsigned short blank9[6];
 volatile unsigned short threshold[C775_MAX_CHANNELS];

};

struct c775_ROM_struct {

 volatile unsigned short OUI_3;
 unsigned short blank1;
 volatile unsigned short OUI_2;
 unsigned short blank2;
 volatile unsigned short OUI_1;
 unsigned short blank3;
 volatile unsigned short version;
 unsigned short blank4;
 volatile unsigned short ID_3;
 unsigned short blank5;
 volatile unsigned short ID_2;
 unsigned short blank6;
 volatile unsigned short ID_1;
 unsigned short blank7[7];
 volatile unsigned short revision;

};


  1. define C775_BOARD_ID 0x00000307

/* Define Address offset for 68K based A24/D32 VME addressing */ /* default VMEChip2 programming only supports A24/D16 */

  1. define C775_68K_A24D32_OFFSET 0xe0000000

/* Define default interrupt vector/level */

  1. define C775_INT_VEC 0xaa
  2. define C775_VME_INT_LEVEL 4
  1. define C775_MIN_FSR 140 /* nsec (High resoulution) */
  2. define C775_MAX_FSR 1200 /* nsec (Low resoulution) */
  1. define C775_ROM_OFFSET 0x8026

/* Register Bits */

  1. define C775_VME_BUS_ERROR 0x8
  2. define C775_SOFT_RESET 0x80
  3. define C775_DATA_RESET 0x4
  1. define C775_BUFFER_EMPTY 0x2
  2. define C775_BUFFER_FULL 0x4
  1. define C775_DATA_READY 0x1
  2. define C775_BUSY 0x4
  1. define C775_MEM_TEST 0x1
  2. define C775_OFFLINE 0x2
  3. define C775_OVERFLOW_SUP 0x8
  4. define C775_UNDERFLOW_SUP 0x10
  5. define C775_INVALID_SUP 0x20
  6. define C775_TEST_MODE 0x40
  7. define C775_SLIDE_ENABLE 0x80
  8. define C775_COMMON_STOP 0x400
  9. define C775_AUTO_INCR 0x800
  10. define C775_INC_HEADER 0x1000
  11. define C775_SLIDE_SUB_ENABLE 0x2000
  12. define C775_INCR_ALL_TRIG 0x4000


  1. define C775_DATA 0x00000000
  2. define C775_HEADER_DATA 0x02000000
  3. define C775_TRAILER_DATA 0x04000000
  4. define C775_INVALID_DATA 0x06000000


/* Register Masks */

  1. define C775_BITSET1_MASK 0x0098
  2. define C775_INTLEVEL_MASK 0x0007
  3. define C775_INTVECTOR_MASK 0x00ff
  4. define C775_STATUS1_MASK 0x01ff
  5. define C775_CONTROL1_MASK 0x0034
  6. define C775_STATUS2_MASK 0x00f6
  7. define C775_BITSET2_MASK 0x7fff
  8. define C775_EVTRIGGER_MASK 0x001f
  9. define C775_FSR_MASK 0x00ff
  1. define C775_DATA_ID_MASK 0x07000000
  2. define C775_WORDCOUNT_MASK 0x00003f00
  3. define C775_CHANNEL_MASK 0x003f0000
  4. define C775_CRATE_MASK 0x00ff0000
  5. define C775_EVENTCOUNT_MASK 0x00ffffff
  6. define C775_GEO_ADDR_MASK 0xf8000000
  7. define C775_TDC_DATA_MASK 0x00000fff

/* Macros */

  1. define C775_EXEC_SOFT_RESET(id) {c775p[id]->bitSet1 = C775_SOFT_RESET; \
                                 c775p[id]->bitClear1 = C775_SOFT_RESET;}
  1. define C775_EXEC_DATA_RESET(id) {c775p[id]->bitSet2 = C775_DATA_RESET; \
                                 c775p[id]->bitClear2 = C775_DATA_RESET;}
  1. define C775_EXEC_READ_EVENT_COUNT(id) { volatile unsigned short s1, s2; \
                                        s1 = c775p[id]->evCountL; s2 = c775p[id]->evCountH;  \
                                        c775EventCount[id] = (c775EventCount[id]&0xff000000) + \
                                                             (s2<<16) + \
                                                             (s1);}
  1. define C775_EXEC_SET_EVTREADCNT(id,val) { if(c775EvtReadCnt[id] < 0) \
                                            c775EvtReadCnt[id] = val; \
                                          else \
                                            c775EvtReadCnt[id] = (c775EvtReadCnt[id]&0x7f000000) + val;

}

  1. define C775_EXEC_CLR_EVENT_COUNT(id) {c775p[id]->evCountReset = 1; c775EventCount[id] = 0;}
  2. define C775_EXEC_INCR_EVENT(id) {c775p[id]->incrEvent = 1; c775EvtReadCnt[id]++;}
  3. define C775_EXEC_INCR_WORD(id) {c775p[id]->incrOffset = 1;}
  4. define C775_EXEC_GATE(id) {c775p[id]->swComm = 1;}

/* Function Prototypes */ STATUS c775Init (UINT32 addr, UINT32 addr_inc, int nadc, UINT16 crateID); void c775Status( int id, int reg, int sflag); int c775PrintEvent(int id, int pflag); int c775ReadEvent(int id, UINT32 *data); int c775FlushEvent(int id, int fflag); int c775ReadBlock(int id, volatile UINT32 *data, int nwrds); STATUS c775IntConnect (VOIDFUNCPTR routine, int arg, UINT16 level, UINT16 vector); STATUS c775IntEnable (int id, UINT16 evCnt); STATUS c775IntDisable (int iflag); STATUS c775IntResume (void); UINT16 c775Sparse(int id, int over, int under); int c775Dready(int id); int c775SetFSR(int id, UINT16 fsr); INT16 c775BitSet2(int id, UINT16 val); INT16 c775BitClear2(int id, UINT16 val); void c775ClearThresh(int id); void c775Gate(int id); void c775IncrEventBlk(int id, int count); void c775IncrEvent(int id); void c775IncrWord(int id); void c775Enable(int id); void c775Disable(int id); void c775CommonStop(int id); void c775CommonStart(int id); void c775Clear(int id); void c775Reset(int id);


CAEN_V792_ADC