Caen775Lib.c Code
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
- /
- include "vxWorks.h"
- include "stdio.h"
- include "string.h"
- include "logLib.h"
- include "taskLib.h"
- include "intLib.h"
- include "iv.h"
- include "semLib.h"
- include "vxLib.h"
/* Include TDC definitions */
- include "c775Lib.h"
/* Include DMA Library definintions */
- ifdef VXWORKSPPC
- include "universeDma.h"
- else
- include "mvme_dma.c"
- 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 */
- ifdef VXWORKS68K51
printf("c775Init: ERROR: 68K Based CPU cannot support A32 addressing (use A2
4)\n");
return(ERROR);
- 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 */
- ifdef VXWORKS68K51
lladdr = C775_68K_A24D32_OFFSET + (laddr&0x00ffffff);
- else
lladdr = laddr;
- 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); }
- 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);
- else
/* 68K Block 32 transfer from FIFO using VME2Chip */ retVal = mvme_dma((long)data, 1, (long)(c775pl[id]->data), 0, nwrds, 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 */
- ifdef VXWORKSPPC
if((intDisconnect((int)INUM_TO_IVEC(c775IntVec)) != 0)) { printf("c775IntConnect: ERROR disconnecting Interrupt\n"); return(ERROR); }
- 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
- /
- define C775_MAX_CHANNELS 32
- 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;
};
- define C775_BOARD_ID 0x00000307
/* Define Address offset for 68K based A24/D32 VME addressing */ /* default VMEChip2 programming only supports A24/D16 */
- define C775_68K_A24D32_OFFSET 0xe0000000
/* Define default interrupt vector/level */
- define C775_INT_VEC 0xaa
- define C775_VME_INT_LEVEL 4
- define C775_MIN_FSR 140 /* nsec (High resoulution) */
- define C775_MAX_FSR 1200 /* nsec (Low resoulution) */
- define C775_ROM_OFFSET 0x8026
/* Register Bits */
- define C775_VME_BUS_ERROR 0x8
- define C775_SOFT_RESET 0x80
- define C775_DATA_RESET 0x4
- define C775_BUFFER_EMPTY 0x2
- define C775_BUFFER_FULL 0x4
- define C775_DATA_READY 0x1
- define C775_BUSY 0x4
- define C775_MEM_TEST 0x1
- define C775_OFFLINE 0x2
- define C775_OVERFLOW_SUP 0x8
- define C775_UNDERFLOW_SUP 0x10
- define C775_INVALID_SUP 0x20
- define C775_TEST_MODE 0x40
- define C775_SLIDE_ENABLE 0x80
- define C775_COMMON_STOP 0x400
- define C775_AUTO_INCR 0x800
- define C775_INC_HEADER 0x1000
- define C775_SLIDE_SUB_ENABLE 0x2000
- define C775_INCR_ALL_TRIG 0x4000
- define C775_DATA 0x00000000
- define C775_HEADER_DATA 0x02000000
- define C775_TRAILER_DATA 0x04000000
- define C775_INVALID_DATA 0x06000000
/* Register Masks */
- define C775_BITSET1_MASK 0x0098
- define C775_INTLEVEL_MASK 0x0007
- define C775_INTVECTOR_MASK 0x00ff
- define C775_STATUS1_MASK 0x01ff
- define C775_CONTROL1_MASK 0x0034
- define C775_STATUS2_MASK 0x00f6
- define C775_BITSET2_MASK 0x7fff
- define C775_EVTRIGGER_MASK 0x001f
- define C775_FSR_MASK 0x00ff
- define C775_DATA_ID_MASK 0x07000000
- define C775_WORDCOUNT_MASK 0x00003f00
- define C775_CHANNEL_MASK 0x003f0000
- define C775_CRATE_MASK 0x00ff0000
- define C775_EVENTCOUNT_MASK 0x00ffffff
- define C775_GEO_ADDR_MASK 0xf8000000
- define C775_TDC_DATA_MASK 0x00000fff
/* Macros */
- define C775_EXEC_SOFT_RESET(id) {c775p[id]->bitSet1 = C775_SOFT_RESET; \
c775p[id]->bitClear1 = C775_SOFT_RESET;}
- define C775_EXEC_DATA_RESET(id) {c775p[id]->bitSet2 = C775_DATA_RESET; \
c775p[id]->bitClear2 = C775_DATA_RESET;}
- 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);}
- define C775_EXEC_SET_EVTREADCNT(id,val) { if(c775EvtReadCnt[id] < 0) \
c775EvtReadCnt[id] = val; \ else \ c775EvtReadCnt[id] = (c775EvtReadCnt[id]&0x7f000000) + val;
}
- define C775_EXEC_CLR_EVENT_COUNT(id) {c775p[id]->evCountReset = 1; c775EventCount[id] = 0;}
- define C775_EXEC_INCR_EVENT(id) {c775p[id]->incrEvent = 1; c775EvtReadCnt[id]++;}
- define C775_EXEC_INCR_WORD(id) {c775p[id]->incrOffset = 1;}
- 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);