Difference between revisions of "CAEN V792 ADC"

From New IAC Wiki
Jump to navigation Jump to search
 
(4 intermediate revisions by one other user not shown)
Line 1: Line 1:
 +
=Property=
 +
Sensitivity: 100 fC/channel
 +
 +
= Manual=
 +
 +
[[Media:CAEN_V792_Manual.pdf]]
 +
 
=Module address=
 
=Module address=
  
Line 113: Line 120:
  
 
[[caen775Lib.c_Code]]
 
[[caen775Lib.c_Code]]
/******************************************************************************
 
*
 
*  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;
 
}
 
  
  
Line 1,222: Line 132:
 
==Control lines==
 
==Control lines==
 
[[Image:ECL-QDC_FSTCLR.jpg | 400 px]]
 
[[Image:ECL-QDC_FSTCLR.jpg | 400 px]]
 +
 +
[http://wiki.iac.isu.edu/index.php/VME_modules Go back]
 +
[[VME_modules]] Go back

Latest revision as of 00:03, 27 April 2011

Property

Sensitivity: 100 fC/channel

Manual

Media:CAEN_V792_Manual.pdf

Module address

CAEN V792 QDC Address.jpg

Rotary dials

The rotary dials for the address were set by the factory to be 32 bit addressing with "e" and "e" on the last dials.

We would like to use 24 bit addressing so lets set the first two dials to "ee". The last two dials should also be set to something non-zero in order to permit 32 bit addressing. The MVME-6100 board only has a small amount of 32 bit VME addressing space mapped to the MVME's address space.

               VME                             CPU
    A24   0x000000-0xffffff           0x90000000-0x90ffffff
    A32   0x08000000-0x11ffffff       0x80000000-0x89ffffff


If you set the last two dials to 0 8 then the addressing will look like

    c792Init 0xee0000     (for A24 addressing)

or

    c792Init 0x08ee0000   (for A32 addressing)

Data banks

The ADC module library will send the entire block over unless you set the ADC for specification.

Below is shown the data structure for Multi-Event Buffer. The data is organized in events[1]. The header, which contains the crate number and the number of converted channels(the second row in the table), the data words - the number of the channel, the Under-Threshold (UN) bit, the Overflow (OV) bit and the 12-bit converted value(ADC COUNTS) and event counter is in The End of Block.

The Header

The bits[26..24] - shows the word type(010 - header);
The bits[23..16] - the crate number;
The bits[13...8] - the memorized channel number.

The data words

The bits[26..24] - the type of word (000 - datum);
The bits[21..16] - the data output channel number;
The bit[13] - the underthreshold;
The bit[12] - the overflow;
The bits[11...0] - the 12 bit converted data.

The End of Block(EOB)

The bits[26..24] - identification of the word type(100 - EOB);
The bits[23..0] - the event counter value.


26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0 1 0 CRATE NUMBER 0 0 MEM. CHANNELS(2)
0 0 0 CHANNEL(2) UN OV ADC COUNTS
0 0 0 CHANNEL(5) UN OV ADC COUNTS
1 0 0 EVENT COUNTER(m)
0 1 0 CRATE NUMBER 0 0 MEM. CHANNELS(3)
0 0 0 CHANNEL(0) UN OV ADC COUNTS
0 0 0 CHANNEL(17) UN OV ADC COUNTS
0 0 0 CHANNEL(3) UN OV ADC COUNTS
1 0 0 EVENT COUNTER(m+3)

Assuming we read all 32 channels then the data block will look like

ADC1:
Crate #=0
Ch       data    Hex
0       3896    f8005f38
16      3896    f8105f38
1       3896    f8015f38
17      3896    f8115f38
2       3896    f8025f38
18      3896    f8125f38
3       3896    f8035f38
19      3896    f8135f38
4       3896    f8045f38
20      3896    f8145f38
5       3896    f8055f38
21      3896    f8155f38
6       3896    f8065f38
22      3896    f8165f38
7       3896    f8075f38
23      3896    f8175f38
8       3896    f8085f38
24      3896    f8185f38
9       3896    f8095f38
25      3896    f8195f38
10      3896    f80a5f38
26      3896    f81a5f38
11      3896    f80b5f38
27      3896    f81b5f38
12      3896    f80c5f38
28      3896    f81c5f38
13      3896    f80d5f38
29      3896    f81d5f38
14      3896    f80e5f38
30      3896    f81e5f38
15      3896    f80f5f38
31      3896    f81f5f38
Event Counter=46=0xfc00002e


ROC library

caen775Lib.c_Code


The command below will compile the above library.


v792 >ccppc -fno-builtin -fno-for-scope -fstrength-reduce -mlongcall -mcpu=604 -DCPU=PPC604 -DVXWORKS -D_GNU_TOOL 
-DVXWORKSPPC  -I/usr/local/coda/2.5/common/include -I../h   -c -o v792Lib.o caen792Lib.c

ECL input polarity

Control lines

ECL-QDC FSTCLR.jpg

Go back VME_modules Go back