/****************************************************************************** * * tdc890.c - Driver library for readout of C.A.E.N. Model 890 TDC * using a VxWorks 5.2 or later based Single Board computer. * * Author: David Abbott * Jefferson Lab Data Acquisition Group * August 2002 * * Revision 1.0 - Initial Revision * - Supports up to 20 CAEN Model 890s in a Crate * - Programmed I/O reads * - Interrupts from a Single 890 * * adjusted for CLAS by Sergey Boyarinov - May 2003-present * */ #include #include #include #include #include #include #include #include #include "tdc890.h" /* for time profiling #include "coda.h" #include "uthbook.h" static UThisti histi[NHIST]; for time profiling */ /* Define external Functions */ IMPORT STATUS sysBusToLocalAdrs(int, char *, char **); IMPORT STATUS intDisconnect(int); IMPORT STATUS sysIntEnable(int); IMPORT STATUS sysIntDisable(int); /* Define global variables */ /* window parameters */ static int window_offset = -4000;; static int window_width = 4600; /* readout options */ static int a24_a32, sngl_blt_mblt, berr_fifo; /* variables filled by DmaStart and used by DmaDone */ static int ndata_save[21]; static int extra_save[21]; static int size_save[21]; /******************************************************************************* * * tdc890Init - Initialize tdc890 Library. * * * RETURNS: OK, or ERROR if the address is invalid or board is not present. */ STATUS tdc890Init(UINT32 addr, UINT32 addr_inc, int nadc, UINT16 crateID) { volatile TDC890 *tdc890; int ii, jj, res, rdata, errFlag = 0; int boardID = 0; /* Check if Board exists at that address */ tdc890 = (TDC890 *) addr; /*res = vxMemProbe((char *) tdc890,0,4,(char *)&rdata); if(res < 0) { printf("tdc890Init: ERROR: No addressable board at addr=0x%x\n", (UINT32) tdc890); errFlag = 1; } else*/ { /* Check if this is a Model V890 */ boardID = tdc890->firmwareRev; if((boardID != V890_BOARD_ID)&&(boardID != (V890_BOARD_ID+1))) { printf("WARN: Firmware does not match: 0x%08x (expected 0x%08x)\n", boardID,V890_BOARD_ID); /*return(ERROR);*/ } } printf("Initialized v890 TDC at address 0x%08x \n",(UINT32)tdc890); /* Disable/Clear all TDCs */ tdc890->moduleReset = 1; /* 'error' light here !!! */ tdc890->clear = 1; if(errFlag > 0) { printf("tdc890Init: ERROR: Unable to initialize v890 TDC Module\n"); return(ERROR); } else { return(OK); } } /******************************************************************************* * * tdc890Status - Gives Status info on specified TDC * * * RETURNS: None */ void tdc890Status(UINT32 addr, int reg, int sflag) { volatile TDC890 *tdc890 = (TDC890 *) addr; int lock; int drdy=0, afull=0, bfull=0; int berr=0, testmode=0; int trigMatch=0, headers=0, tdcerror[4]; UINT16 statReg, cntlReg, afullLevel, bltEvents; UINT16 iLvl, iVec, evStored; UINT16 evCount, res; /* read various registers */ lock = intLock(); statReg = (tdc890->status)&V890_STATUS_MASK; cntlReg = (tdc890->control)&V890_CONTROL_MASK; afullLevel = tdc890->almostFullLevel; bltEvents = (tdc890->bltEventNumber)&V890_BLTEVNUM_MASK; iLvl = (tdc890->intLevel)&V890_INTLEVEL_MASK; iVec = (tdc890->intVector)&V890_INTVECTOR_MASK; evCount = (tdc890->evCount)&V890_EVCOUNT_MASK; evStored = tdc890->evStored; intUnlock(lock); drdy = statReg&V890_STATUS_DATA_READY; afull = statReg&V890_STATUS_ALMOST_FULL; bfull = statReg&V890_STATUS_FULL; trigMatch = statReg&V890_STATUS_TRIG_MATCH; headers = statReg&V890_STATUS_HEADER_ENABLE; tdcerror[0] = (statReg&V890_STATUS_ERROR_0)>>6; tdcerror[1] = (statReg&V890_STATUS_ERROR_1)>>7; tdcerror[2] = (statReg&V890_STATUS_ERROR_2)>>8; tdcerror[3] = (statReg&V890_STATUS_ERROR_3)>>9; berr = cntlReg&V890_BUSERROR_ENABLE; testmode = cntlReg&V890_TESTMODE; /* print out status info */ printf("STATUS for v890 TDC at base address 0x%x\n",(UINT32)tdc890); printf("---------------------------------------------- \n"); if(iLvl>0) { printf(" Interrupts Enabled - Request level = %d words\n",afullLevel); printf(" VME Interrupt Level: %d Vector: 0x%x \n",iLvl,iVec); } else { printf(" Interrupts Disabled\n"); } printf("\n"); printf(" Data Status \n"); if(bfull) { printf(" Status = 0x%04x (Buffer Full)\n",statReg); } else if(afull) { printf(" Status = 0x%04x (Almost Full)\n",statReg); }else if(drdy) { printf(" Status = 0x%04x (Data Ready )\n",statReg); }else { printf(" Status = 0x%04x (No Data)\n",statReg); } printf(" Events Stored = %d\n",evStored); if(evCount == 0x00ffffff) printf(" Total Events = (No Events taken)\n"); else printf(" Total Events = %d\n",evCount); printf(" Almost Full = %d\n",afullLevel); printf("\n"); printf(" TDC Mode/Status \n"); tdc890GetEdgeResolution(addr,&res); printf(" Resolution : %d ps\n",res); if(testmode) printf(" Test Mode : On\n"); if(trigMatch) printf(" Trigger Matching: On\n"); else printf(" Trigger Matching: Off\n"); if(headers) printf(" TDC Headers/EOB : On\n"); else printf(" TDC Headers/EOB : Off\n"); if(berr) printf(" Bus Errors : On\n"); else printf(" Bus Errors : Off\n"); printf(" TDC Errors : 0:%d 1:%d 2:%d 3:%d\n", tdcerror[0],tdcerror[1],tdcerror[2],tdcerror[3]); printf("\n"); } /******************************************************************************* * * tdc890ReadMicro - Read Microcontroller Register * * returns OK or ERROR */ STATUS tdc890ReadMicro(UINT32 addr, UINT16 *data, int nwords) { volatile TDC890 *tdc890 = (TDC890 *) addr; int ii, jj, kk=0; UINT16 mstatus; retry: mstatus = (tdc890->microHandshake) & V890_MICRO_READOK; if(kk > 10) { printf("-> ReadMicro: mstatus=%d (0x%x)\n",mstatus,tdc890->microHandshake); } if(mstatus) { for(ii=0; iimicroHandshake) & V890_MICRO_READOK)) { jj++; if(jj>20) { logMsg("tdc890ReadMicro: ERROR1: Read Status not OK (read %d)\n", ii,0,0,0,0,0); return(ERROR); } } data[ii] = tdc890->microReg; } } else { kk++; if(kk>=20) { logMsg("tdc890ReadMicro: ERROR2: Read Status not OK\n",0,0,0,0,0,0); return(ERROR); } else { taskDelay(10); goto retry; } } if(kk > 10) printf("-> ReadMicro: kk=%d\n",kk); return(OK); } /* group read: read 'nwords' from 'nboards' boards into 'data' */ /* NOT FINISHED !!! */ STATUS tdc890ReadMicroGroup(int nboards, UINT32 *addr, UINT16 *data[21], int nwords) { volatile TDC890 *tdc890; int ii, jj, ll, kk; UINT16 *mstatus; for(ll=0; llmicroHandshake) & V890_MICRO_READOK; } for(ii=0; iimicroReg; } else { kk++; mstatus[ii] = 0; if(kk>=20) { logMsg("tdc890ReadMicroGroup: ERROR: Read Status not OK\n", 0,0,0,0,0,0); return(ERROR); } else { /* wait and repeat again */ taskDelay(10); mstatus[ii] = (tdc890->microHandshake) & V890_MICRO_READOK; goto retry; } } if(kk > 10) printf("-> ReadMicroGroup: ii=%d kk=%d\n",ii, kk); } } return(OK); } /******************************************************************************* * * tdc890WriteMicro - Write to Microcontroller Register * * returns OK or ERROR */ STATUS tdc890WriteMicro(UINT32 addr, UINT16 data) { volatile TDC890 *tdc890 = (TDC890 *) addr; int kk=0; volatile UINT16 mstatus; retry: mstatus = (tdc890->microHandshake) & V890_MICRO_WRITEOK; if(mstatus) { tdc890->microReg = data; } else { kk++; mstatus=0; if(kk>=20) { logMsg("tdc890WriteMicro: ERROR: Write Status not OK\n",0,0,0,0,0,0); return(ERROR); } else { taskDelay(10); goto retry; } } if(kk > 10) printf("-> WriteMicro: kk=%d\n",kk); return(OK); } /* group write: writes the same 'data' to 'nboards' boards */ /* NOT FINISHED !!! */ STATUS tdc890WriteMicroGroup(int nboards, UINT32 *addr, UINT16 data) { volatile TDC890 *tdc890; int ii, kk; volatile UINT16 *mstatus; for(ii=0; iimicroHandshake) & V890_MICRO_WRITEOK; } for(ii=0; iimicroReg = data; } else { kk++; mstatus[ii] = 0; if(kk>=20) { logMsg("tdc890WriteMicro: ERROR: Write Status not OK\n",0,0,0,0,0,0); return(ERROR); } else { /* wait and repeat again */ taskDelay(10); mstatus[ii] = (tdc890->microHandshake) & V890_MICRO_WRITEOK; goto retry; } } if(kk > 10) printf("-> WriteMicro: ii=%d kk=%d\n",ii, kk); } return(OK); } /******************************************************************************* * * tdc890PrintEvent - Print an event from TDC to standard out. * * * RETURNS: Number of Data words read from the TDC (including Header/Trailer). */ int tdc890PrintEvent(UINT32 addr, int pflag) { volatile TDC890 *tdc890 = (TDC890 *) addr; int ii, jj, nWords, evID, bunchID, evCount, headFlag, trigMatch; UINT32 gheader, gtrailer, theader, ttrailer, tmpData, dCnt; int tdcID, chanID, dataVal, tEdge; /* Check if there is a valid event */ if((tdc890->status)&V890_STATUS_DATA_READY) { dCnt = 0; headFlag = tdc890->status&V890_STATUS_HEADER_ENABLE; trigMatch = tdc890->status&V890_STATUS_TRIG_MATCH; if(trigMatch) { /* If trigger match mode then print individual event */ /* Read Global Header - Get event count */ gheader = tdc890->data[0]; if((gheader&V890_DATA_TYPE_MASK) != V890_GLOBAL_HEADER_DATA) { printf("tdc890PrintEvent: ERROR: Invalid Global Header Word 0x%08x\n", gheader); return(ERROR); } else { printf(" TDC DATA for Module at address 0x%08x\n",addr); evCount = (gheader&V890_GHEAD_EVCOUNT_MASK)>>5; dCnt++; printf(" Global Header: 0x%08x Event Count = %d \n",gheader,evCount); } /* Loop over four TDC chips and get data for each */ for(ii=0; ii<4; ii++) { /* Read TDC Header - Get event ID, Bunch ID */ theader = tdc890->data[0]; if((theader&V890_DATA_TYPE_MASK) != V890_TDC_HEADER_DATA) { printf("ERROR: Invalid TDC Header Word 0x%08x for TDC %d\n", theader,ii); return(ERROR); } else { evID = (theader&V890_TDCHEAD_EVID_MASK)>>12; bunchID = (theader&V890_TDCHEAD_BUNCHID_MASK); dCnt++; printf(" TDC %d Header: 0x%08x EventID = %d Bunch ID = %d ", ii,theader,evID,bunchID); } jj=0; tmpData = tdc890->data[0]; dCnt++; while((tmpData&V890_DATA_TYPE_MASK) != V890_TDC_EOB_DATA) { if((jj % 5) == 0) printf("\n "); printf(" 0x%08x",tmpData); jj++; tmpData = tdc890->data[jj]; } /* reached EOB for TDC */ printf("\n"); ttrailer = tmpData; if((ttrailer&V890_DATA_TYPE_MASK) != V890_TDC_EOB_DATA) { printf("ERROR: Invalid TDC EOB Word 0x%08x for TDC %d\n", ttrailer,ii); return(ERROR); } else { nWords = (ttrailer&V890_TDCEOB_WORDCOUNT_MASK); dCnt++; printf(" TDC %d EOB : 0x%08x Word Count = %d \n", ii,ttrailer,nWords); } } /* next data word should be Global EOB */ gtrailer = tdc890->data[dCnt]; if((gtrailer&V890_DATA_TYPE_MASK) != V890_GLOBAL_EOB_DATA) { printf("tdc890PrintEvent: ERROR: Invalid Global EOB Word 0x%08x\n", gtrailer); return(ERROR); } else { nWords = (gtrailer&V890_GEOB_WORDCOUNT_MASK)>>5; dCnt++; printf(" Global EOB : 0x%08x Total Word Count = %d \n", gtrailer,nWords); } } else /* Continuous Storage mode */ { tmpData = tdc890->data[dCnt]; printf(" TDC Continuous Storage DATA\n"); while((tmpData&V890_DATA_TYPE_MASK) != V890_FILLER_DATA) { tdcID = (tmpData&V890_TDC_MASK)>>24; chanID = (tmpData&V890_CHANNEL_MASK)>>19; tEdge = (tmpData&V890_EDGE_MASK)>>19; dataVal = (tmpData&V890_DATA_MASK); /* if((dCnt % 5) == 0) printf("\n "); printf(" 0x%08x",tmpData); */ printf(" %d %d %d %d\n",tdcID, chanID, tEdge, dataVal); dCnt++; tmpData = tdc890->data[dCnt]; } printf("\n"); } return(dCnt); } else { printf("tdc890PrintEvent: No data available for readout!\n"); return(0); } } /* ... */ int tdc890StatusFull(UINT32 addr) { volatile TDC890 *tdc890 = (TDC890 *) addr; int res; res = (tdc890->status) & V890_STATUS_FULL; return(res); } /****************************************************************************** * * tdc890Dready - data readyness * * * RETURNS: 0(No Data) or the number of events */ int tdc890Dready(UINT32 addr) { volatile TDC890 *tdc890 = (TDC890 *) addr; UINT16 i,stat=0, nevents; /* Check a few times in case the module is not ready right away */ for(i=0; i<10; i++){ stat = (tdc890->status) & V890_STATUS_DATA_READY; if(stat)break; } if(stat) { tdc890GetEventStored(addr, &nevents); return(nevents); } else { logMsg("tdc890Dready: board at 0x%08x is not ready\n",addr,2,3,4,5,6); return(0); } } int tdc890EventFifo(UINT32 addr, UINT32 flag) { volatile TDC890 *tdc890 = (TDC890 *) addr; printf("tdc890EventFifo befor: 0x%04x\n",tdc890->control); if(flag == 1) tdc890->control |= 0x100; else if(flag == 0) tdc890->control ^= 0x100; /* DOES IT WORK ? */ else printf("tdc890EventFifo: unknown flag=%d\n",flag); printf("tdc890EventFifo after: 0x%04x\n",tdc890->control); return(0); } int tdc890BusError(UINT32 addr, UINT32 flag) { volatile TDC890 *tdc890 = (TDC890 *) addr; printf("tdc890BusError befor: 0x%04x\n",tdc890->control); if(flag == 1) { printf("set BUSerror\n"); tdc890->control |= 0x1; } else if(flag == 0) { printf("reset BUSerror\n"); tdc890->control ^= 0x1; /* DOES NOT WORK !!! */ } else printf("tdc890BusError: unknown flag=%d\n",flag); printf("tdc890BusError after: 0x%04x\n",tdc890->control); return(0); } int tdc890Align64(UINT32 addr, UINT32 flag) { volatile TDC890 *tdc890 = (TDC890 *) addr; printf("tdc890Align64 befor: 0x%04x\n",tdc890->control); if(flag == 1) tdc890->control |= 0x10; else if(flag == 0) tdc890->control ^= 0x10; /* DOES IT WORK ? */ else printf("tdc890Align64: unknown flag=%d\n",flag); printf("tdc890Align64 after: 0x%04x\n",tdc890->control); return(0); } /****************************************************************************** * * tdc890ReadEventDma, * tdc890ReadEvent - reads data in trigger matching mode; before this call * user must make sure that trigger matching mode was set * and data is ready; data will be read out until Global * Trailer (Global EOB) is met * * * RETURNS: Number of Data words read from the TDC (including Header/Trailer). */ /* Dma functions prototypes (need header !) */ STATUS usrVme2MemDmaStart(UCHAR *localVmeAddr, UCHAR *localAddr, UINT32 nbytes); /* we'll DMA more words then actual event length, enforcing the same alignment for source and destination; mv5100 etc want it this way (see function usrVme2MemDmaStart() return(-2) (universe.c) )*/ /* Sergey: mv5100: if trying to DMA odd number of 32-bit words, last word usually lost; BUT: sometimes (on high rate 1-2kHz) it transfered !!! crap ... we'll check if number of words odd and add one extra ONLY if it's odd ! */ /* I've seen another interpretation: 'ndata' must be more then actual length to force 'VME bus error' return, otherwise next event read will return it instead of data ... need to understand it better what all this about ... */ int tdc890ReadEventDma(UINT32 addr, UINT32 *tdata) { volatile UINT32 *data = (UINT32 *) addr; volatile UINT32 *fifo = (UINT32 *) (addr+0x1038); UINT32 *output = tdata; int ndata, mdata, fifodata, res, extra; int i; /* TIMER_VAR; */ /* whole: 18usec */ /* part1: 1 usec */ if(berr_fifo == 0x01) { /* get event length in words */ fifodata = *fifo; ndata = fifodata&0xffff; /* logMsg("tdc890ReadEventDma: INFO: event fifo reports %d words\n", ndata,0,0,0,0,0); */ } else { ndata = V890_MAX_WORDS_PER_BOARD; mdata = 0; /* logMsg("tdc890ReadEventDma: INFO: trying to DMA %d words\n", ndata,0,0,0,0,0); */ } /* usrVmeDmaReset(); */ /* part2: 2 usec */ if(berr_fifo == 0x01) { if( (ndata%2) != 0 ) extra = 1; else extra = 0; /* logMsg("tdc890ReadDataDma: ndata=%d extra=%d\n",ndata,extra,3,4,5,6); */ res = usrVme2MemDmaStart( (UINT32 *)data, (UINT32 *)tdata, ((ndata+extra)<<2) ); } else { res = usrVme2MemDmaStart( (UINT32 *)data, (UINT32 *)tdata, (ndata<<2) ); } if(res < 0) { logMsg("tdc890ReadEventDma: ERROR: usrVme2MemDmaStart returned %d\n", res,0,0,0,0,0); return(0); } /*else { logMsg("tdc890ReadEventDma: usrVme2MemDmaStart returned %d\n", res,0,0,0,0,0); } */ /* { TIMER_NORMALIZE; TIMER_START; } */ /* part3: 14 usec */ if(berr_fifo == 0x01) { /* check if transfer is completed; returns zero or ERROR */ if((res = usrVme2MemDmaDone()) < 0) { logMsg("tdc890ReadEventDma: ERROR: usrVme2MemDmaDone returned = %d\n", res,2,3,4,5,6); return(0); } else { mdata = (ndata+extra) - (res>>2); /* logMsg("tdc890ReadEventDma: res=%d ndata=%d extra=%d -> mdata=%d\n", res,ndata,extra,mdata,5,6); */ if( (res>0) || ((mdata%2)!=0) ) { logMsg("WRONG alignment: res=%d (ndata=%d, extra=%d => was %d), mdata=%d\n", res,ndata,extra,((ndata+extra)<<2),mdata,6); } /* logMsg("tdc890ReadEventDma: INFO: usrVme2MemDmaDone returned = %d (%d)\n", res,mdata,3,4,5,6); */ } } else { /* check if transfer is completed; returns zero or ERROR */ if((res = usrVme2MemDmaDone()) < 0) { logMsg("tdc890ReadEventDma: ERROR: usrVme2MemDmaDone returned = %d\n", res,2,3,4,5,6); return(0); } else if(res == 0) { logMsg("tdc890ReadEventDma: ERROR: usrVme2MemDmaDone returned = %d\n", res,2,3,4,5,6); logMsg("tdc890ReadEventDma: ERROR: we are expecting VME BUS error !\n", res,2,3,4,5,6); return(0); } else { mdata = ndata - (res>>2); if(mdata>999) logMsg("tdc890ReadEventDma: INFO: usrVme2MemDmaDone returned = %d (%d)\n", res,mdata,3,4,5,6); } } /* { TIMER_STOP(100000,-1); } */ return(mdata); } /* start only */ int tdc890ReadEventDmaStart(int ib, UINT32 addr, UINT32 *tdata) { volatile UINT32 *data = (UINT32 *) addr; volatile UINT32 *fifo = (UINT32 *) (addr+0x1038); int mdata, fifodata, res; int i; if(berr_fifo == 0x01) { /* get event length in words */ fifodata = *fifo; ndata_save[ib] = fifodata&0xffff; /* logMsg("tdc890ReadEventDmaStart: INFO: event fifo reports %d words\n", ndata_save[ib],0,0,0,0,0); */ } else { ndata_save[ib] = V890_MAX_WORDS_PER_BOARD; mdata = 0; /* logMsg("tdc890ReadEventDmaStart: INFO: trying to DMA %d words\n", ndata_save[ib],0,0,0,0,0); */ } /*usrVmeDmaReset();*/ if(berr_fifo == 0x01) { if( (ndata_save[ib]%2) != 0 ) extra_save[ib] = 1; else extra_save[ib] = 0; /* logMsg("tdc890ReadEventDmaStart: ndata_save=%d extra_save=%d\n", ndata_save[ib],extra_save[ib],3,4,5,6); */ res = usrVme2MemDmaStart( (UINT32 *)data, (UINT32 *)tdata, ((ndata_save[ib]+extra_save[ib])<<2) ); } else { res = usrVme2MemDmaStart( (UINT32 *)data, (UINT32 *)tdata, (ndata_save[ib]<<2) ); } if(res < 0) { logMsg("tdc890ReadEventDmaStart: ERROR: usrVme2MemDmaStart returned %d\n", res,0,0,0,0,0); } /*else { logMsg("tdc890ReadEventDmaStart: usrVme2MemDmaStart returned %d\n", res,0,0,0,0,0); } */ return(res); } int tdc890ReadEventDmaDone(int ib) { int mdata, res; int i; if(berr_fifo == 0x01) { /* check if transfer is completed; returns zero or ERROR */ if((res = usrVme2MemDmaDone()) < 0) { logMsg("tdc890ReadEventDmaDone: ERROR: usrVme2MemDmaDone returned = %d\n", res,2,3,4,5,6); return(0); } else { mdata = (ndata_save[ib]+extra_save[ib]) - (res>>2); /* logMsg("tdc890ReadEventDmaDone: res=%d ndata_save=%d extra_save=%d -> mdata=%d\n", res,ndata_save[ib],extra_save[ib],mdata,5,6); */ if( (res>4) || ((mdata%2)!=0) ) { logMsg("WRONG alignment: res=%d (ndata_save=%d, extra_save=%d => was %d), mdata=%d\n", res,ndata_save[ib],extra_save[ib],((ndata_save[ib]+extra_save[ib])<<2),mdata,6); } /* logMsg("tdc890ReadDataDma: INFO: usrVme2MemDmaDone returned = %d (%d)\n", res,mdata,3,4,5,6); */ } } else { /* check if transfer is completed; returns zero or ERROR */ if((res = usrVme2MemDmaDone()) < 0) { logMsg("tdc890ReadEventDmaDone: ERROR: usrVme2MemDmaDone returned = %d\n", res,2,3,4,5,6); return(0); } else if(res == 0) { logMsg("tdc890ReadEventDmaDone: ERROR: usrVme2MemDmaDone returned = %d\n", res,2,3,4,5,6); logMsg("tdc890ReadDataDma: ERROR: we are expecting VME BUS error !\n", res,2,3,4,5,6); return(0); } else { mdata = ndata_save[ib] - (res>>2); if(mdata>999) logMsg("tdc890ReadEventDmaDone: INFO: usrVme2MemDmaDone returned = %d (%d)\n", res,mdata,3,4,5,6); } } return(mdata); } int tdc890ReadEvent(UINT32 addr, UINT32 *tdata) { volatile UINT32 *data = (UINT32 *) addr; volatile UINT32 *fifo = (UINT32 *) (addr+0x1038); UINT32 *output = tdata - 1; int fifodata, ndata; if(berr_fifo == 0x01) { /* get event length in words */ /* do not need it here but must read fifo as soon as it is enabled, otherwise 'full' condition will happen */ fifodata = *fifo; } do { *(++output) = *data; } while( ((*output)&V890_DATA_TYPE_MASK) != V890_GLOBAL_EOB_DATA ); return(((int)(output-tdata))+1); } /****************************************************************************** * * tdc890ReadData - available data into a buffer. * * * RETURNS: Number of Data words read from the TDC (including Header/Trailer). */ int tdc890ReadData(UINT32 addr, UINT32 *tdata, int maxWords) { volatile TDC890 *tdc890 = (TDC890 *) addr; int ii, jj, nWords, evID, bunchID, evCount, headFlag, trigMatch; UINT32 gheader, gtrailer, theader, ttrailer, tmpData, dCnt; if(maxWords==0) maxWords = 1024; /* Check if there is a valid event */ if((tdc890->status) & V890_STATUS_DATA_READY) { dCnt = 0; headFlag = tdc890->status & V890_STATUS_HEADER_ENABLE; trigMatch = tdc890->status & V890_STATUS_TRIG_MATCH; if(trigMatch) /* If trigger match mode then read individual event */ { /* Read Global Header - Get event count */ gheader = tdc890->data[0]; if((gheader & V890_DATA_TYPE_MASK) != V890_GLOBAL_HEADER_DATA) { printf("tdc890ReadData: ERROR: Invalid Global Header Word 0x%08x\n", gheader); return(ERROR); } else { tdata[dCnt] = gheader; evCount = (gheader & V890_GHEAD_EVCOUNT_MASK) >> 5; dCnt++; } /* Loop over four TDC chips and get data for each */ for(ii=0; ii<4; ii++) { /* Read TDC Header - Get event ID, Bunch ID */ theader = tdc890->data[0]; if((theader&V890_DATA_TYPE_MASK) != V890_TDC_HEADER_DATA) { printf("ERROR: Invalid TDC Header Word 0x%08x for TDC %d\n", theader,ii); return(ERROR); } else { tdata[dCnt] = theader; evID = (theader&V890_TDCHEAD_EVID_MASK)>>12; bunchID = (theader&V890_TDCHEAD_BUNCHID_MASK); dCnt++; } jj=0; tmpData = tdc890->data[0]; while((tmpData&V890_DATA_TYPE_MASK) != V890_TDC_EOB_DATA) { tdata[dCnt] = tmpData; jj++; dCnt++; tmpData = tdc890->data[jj]; } /* reached EOB for TDC */ ttrailer = tmpData; if((ttrailer&V890_DATA_TYPE_MASK) != V890_TDC_EOB_DATA) { printf("ERROR: Invalid TDC EOB Word 0x%08x for TDC %d\n", ttrailer,ii); return(ERROR); } else { tdata[dCnt] = ttrailer; nWords = (ttrailer&V890_TDCEOB_WORDCOUNT_MASK); dCnt++; } } /* next data word should be Global EOB */ gtrailer = tdc890->data[dCnt]; if((gtrailer&V890_DATA_TYPE_MASK) != V890_GLOBAL_EOB_DATA) { printf("tdc890ReadData: ERROR: Invalid Global EOB Word 0x%08x\n", gtrailer); return(ERROR); } else { tdata[dCnt] = gtrailer; nWords = (gtrailer&V890_GEOB_WORDCOUNT_MASK)>>5; dCnt++; } } else /* Continuous Storage mode */ { tmpData = tdc890->data[dCnt]; while(((tmpData&V890_DATA_TYPE_MASK) != V890_FILLER_DATA) && (dCntdata[dCnt]; } } return(dCnt); } else { printf("tdc890ReadData: No data available for readout!\n"); return(0); } } /*********** OPCODES **************/ /****************************/ /* ACQUISITION MODE OPCODES */ void tdc890SetTriggerMatchingMode(UINT32 addr) { tdc890WriteMicro(addr,0x0000); tdc890Clear(addr); return; } void tdc890SetContinuousStorageMode(UINT32 addr) { tdc890WriteMicro(addr,0x0100); tdc890Clear(addr); return; } void tdc890ReadAcquisitionMode(UINT32 addr, UINT16 *data) { UINT16 tdata; tdc890WriteMicro(addr,0x0200); tdc890ReadMicro(addr,&tdata,1); tdata &= 0x1; if(tdata==0) printf("Acquisition Mode: Continuous Storage\n"); else printf("Acquisition Mode: Trigger Matching\n"); return; } void tdc890SetKeepToken(UINT32 addr) { tdc890WriteMicro(addr,0x0300); return; } void tdc890ClearKeepToken(UINT32 addr) { tdc890WriteMicro(addr,0x0400); return; } void tdc890LoadDefaultConfiguration(UINT32 addr) { tdc890WriteMicro(addr,0x0500); return; } void tdc890SaveUserConfiguration(UINT32 addr) { tdc890WriteMicro(addr,0x0600); return; } void tdc890LoadUserConfiguration(UINT32 addr) { tdc890WriteMicro(addr,0x0700); return; } void tdc890SetAutoLoadUserConfiguration(UINT32 addr) { tdc890WriteMicro(addr,0x0800); return; } void tdc890SetAutoLoadDefaultConfiguration(UINT32 addr) { tdc890WriteMicro(addr,0x0900); return; } /************************/ /* TRIGGER MODE OPCODES */ /* set the width of the trigger window: 25ns < ww < 51175ns */ /* (25ns step) */ STATUS tdc890SetWindowWidth(UINT32 addr, UINT32 ww) { UINT16 tdata; tdc890WriteMicro(addr,0x1000); if(ww < 25) tdata = 1; else if(ww > 51175) tdata = 0x7FF; else tdata = ww/25; printf("Set Window Width to %d ns\n",tdata*25); tdc890WriteMicro(addr,tdata); return(OK); } /* set the offset of the trigger window with respect to the trigger itself: w0 > -800000ns (25ns step) */ STATUS tdc890SetWindowOffset(UINT32 addr, INT32 wo) { INT16 tdata; tdc890WriteMicro(addr,0x1100); if(wo < -800000) tdata = -32000; else tdata = wo/25; printf("Set Window Offset to %d ns\n",tdata*25); tdc890WriteMicro(addr,tdata); return(OK); } /* 0 < wm < 1250ns (25ns step) */ STATUS tdc890SetExtraSearchMargin(UINT32 addr, UINT32 wm) { UINT16 tdata; tdc890WriteMicro(addr,0x1200); if(wm < 0) tdata = 0; else if(wm > 1250) tdata = 50; else tdata = wm/25; printf("Set Extra Search Margin to %d ns\n",tdata*25); tdc890WriteMicro(addr,tdata); return(OK); } /* 0 < wr < ..ns (25ns step) */ STATUS tdc890SetRejectMargin(UINT32 addr, UINT32 wr) { UINT16 tdata; tdc890WriteMicro(addr,0x1300); if(wr < 0) tdata = 0; else if(wr > 1250) tdata = 50; else tdata = wr/25; printf("Set Reject Margin to %d ns\n",tdata*25); tdc890WriteMicro(addr,tdata); return(OK); } /* enable subtruction of trigger time */ STATUS tdc890EnableTriggerTimeSubtruction(UINT32 addr) { tdc890WriteMicro(addr,0x1400); return(OK); } /* disable subtruction of trigger time */ STATUS tdc890DisableTriggerTimeSubtruction(UINT32 addr) { tdc890WriteMicro(addr,0x1500); return(OK); } #define EIEIO __asm__ volatile ("eieio") #define SynC __asm__ volatile ("sync") /* Read back and print TDC Trigger Matching Configuration */ STATUS tdc890ReadTriggerConfiguration(UINT32 addr) { volatile TDC890 *tdc890 = (TDC890 *) addr; INT16 tmp[5] = {0,0,0,0,0}; EIEIO; SynC; tdc890WriteMicro(addr,0x1600); EIEIO; SynC; /*tdc890ReadMicro(addr,tmp,5);*/ tdc890ReadMicro(addr,&tmp[0],1); tdc890ReadMicro(addr,&tmp[1],1); tdc890ReadMicro(addr,&tmp[2],1); tdc890ReadMicro(addr,&tmp[3],1); tdc890ReadMicro(addr,&tmp[4],1); EIEIO; SynC; printf(" Window Width = %6d ns\n",tmp[0]*25); printf(" Window Offset = %6d ns\n",tmp[1]*25); printf(" Extra Seach Margin = %6d ns\n",tmp[2]*25); printf(" Reject Margin = %6d ns\n",tmp[3]*25); printf(" Trigger Time Subtruction = %6d\n",tmp[4]); return(OK); } /*****************************************/ /* EDGE DETECTION AND RESOLUTION OPCODES */ /* 0-pair, 1-trailing, 2-leading, 3-both leading and trailing */ STATUS tdc890SetEdgeDetectionConfig(UINT32 addr, UINT16 data) { UINT16 tdata; tdata = data & 0x3; printf("SetEdgeDetectionConfig: "); if(tdata==0x0) printf("set pair mode\n"); else if(tdata==0x1) printf("set trailing edge only\n"); else if(tdata==0x2) printf("set leading edge only\n"); else printf("set both leading and trailing edges\n"); tdc890WriteMicro(addr,0x2200); tdc890WriteMicro(addr,tdata); return(OK); } STATUS tdc890ReadEdgeDetectionConfig(UINT32 addr, UINT16 *data) { UINT16 tdata; tdc890WriteMicro(addr,0x2300); tdc890ReadMicro(addr,&tdata,1); *data = 0; tdata &= 0x3; printf("ReadEdgeDetectionConfig: tdata=%d (0x%x)\n",tdata,tdata); if(tdata==0) printf("ReadEdgeDetectionConfig: paired measurement\n"); else if(tdata==1) printf("ReadEdgeDetectionConfig: trailing edge\n"); else if(tdata==2) printf("ReadEdgeDetectionConfig: leading edge\n"); else if(tdata==3) printf("ReadEdgeDetectionConfig: both leading and trailing\n"); else { printf("ReadEdgeDetectionConfig: ERROR, tdata=%d (0x%x)\n",tdata,tdata); return(ERROR); } *data = tdata; return(OK); } /* set leading/trailing edge resolution: can be 100, 200 or 800 */ STATUS tdc890SetEdgeResolution(UINT32 addr, UINT16 data) { UINT16 tdata; if(data==800) tdata = 0; else if(data==200) tdata = 1; else if(data==100) tdata = 2; else { printf("ERROR: SetEdgeResolution: data=%d, must be 100, 200 or 800 ps\n",data); return(ERROR); } tdc890WriteMicro(addr,0x2400); tdc890WriteMicro(addr,tdata); printf("Set Edge Resolution to %d ps\n",data); return(OK); } /* get leading/trailing edge resolution */ STATUS tdc890GetEdgeResolution(UINT32 addr, UINT16 *data) { UINT16 tdata; tdc890WriteMicro(addr,0x2600); tdc890ReadMicro(addr,&tdata,1); tdata &= 0x3; if(tdata==0) *data = 800; else if(tdata==1) *data = 200; else if(tdata==2) *data = 100; else { printf("ERROR: GetEdgeResolution: tdata=%d (0x%x)\n",tdata,tdata); return(ERROR); } printf("Edge Resolution is %d ps\n",*data); return(OK); } /* set pair resolution: leading time resolution (data1): 100,200,400,800,1600,3120,6250,12500 ps width resolution (data2): 100,200,400,800,1600,3120,6250,12500, 25000,50000,100000,200000,400000,800000 ps */ STATUS tdc890SetPairResolution(UINT32 addr, UINT32 data1, UINT32 data2) { UINT16 tdata; if(data1==100) tdata = 0x0; else if(data1==200) tdata = 0x1; else if(data1==400) tdata = 0x2; else if(data1==800) tdata = 0x3; else if(data1==1600) tdata = 0x4; else if(data1==3120) tdata = 0x5; else if(data1==6250) tdata = 0x6; else if(data1==12500) tdata = 0x7; else { printf("ERROR: SetPairResolution: data1=%d, see source file\n",data1); return(ERROR); } if(data2==100) tdata += 0x0; else if(data2==200) tdata += 0x100; else if(data2==400) tdata += 0x200; else if(data2==800) tdata += 0x300; else if(data2==1600) tdata += 0x400; else if(data2==3200) tdata += 0x500; else if(data2==6250) tdata += 0x600; else if(data2==12500) tdata += 0x700; else if(data2==25000) tdata += 0x800; else if(data2==50000) tdata += 0x900; else if(data2==100000) tdata += 0xA00; else if(data2==200000) tdata += 0xB00; else if(data2==400000) tdata += 0xC00; else if(data2==800000) tdata += 0xD00; else { printf("ERROR: SetPairResolution: data2=%d, see source file\n",data2); return(ERROR); } tdc890WriteMicro(addr,0x2500); tdc890WriteMicro(addr,tdata); printf("Set Pair Resolution to %d(leading time), %d(width) ps\n",data1,data2); return(OK); } /* get pair resolution */ STATUS tdc890GetPairResolution(UINT32 addr, UINT32 *data1, UINT32 *data2) { UINT16 tdata, tdata1, tdata2; tdc890WriteMicro(addr,0x2600); tdc890ReadMicro(addr,&tdata,1); tdata1 = tdata & 0x7; if(tdata1 == 0x0) *data1 = 100; else if(tdata1 == 0x1) *data1 = 200; else if(tdata1 == 0x2) *data1 = 400; else if(tdata1 == 0x3) *data1 = 800; else if(tdata1 == 0x4) *data1 = 1600; else if(tdata1 == 0x5) *data1 = 3120; else if(tdata1 == 0x6) *data1 = 6250; else if(tdata1 == 0x7) *data1 = 12500; else { printf("ERROR: GetPairResolution: tdata1=%d\n",tdata1); return(ERROR); } tdata2 = tdata & 0xF00; if(tdata2 == 0x0) *data2 = 100; else if(tdata2 == 0x100) *data2 = 200; else if(tdata2 == 0x200) *data2 = 400; else if(tdata2 == 0x300) *data2 = 800; else if(tdata2 == 0x400) *data2 = 1600; else if(tdata2 == 0x500) *data2 = 3200; else if(tdata2 == 0x600) *data2 = 6250; else if(tdata2 == 0x700) *data2 = 12500; else if(tdata2 == 0x800) *data2 = 25000; else if(tdata2 == 0x900) *data2 = 50000; else if(tdata2 == 0xA00) *data2 = 100000; else if(tdata2 == 0xB00) *data2 = 200000; else if(tdata2 == 0xC00) *data2 = 400000; else if(tdata2 == 0xD00) *data2 = 800000; else { printf("ERROR: GetPairResolution: tdata2=%d\n",tdata2); return(ERROR); } printf("Pair Resolution is %d(leading time), %d(width) ps\n",*data1,*data2); return(OK); } /* set double hit resolution: can be 5, 10, 30 or 100 ns */ STATUS tdc890SetDoubleHitResolution(UINT32 addr, UINT16 data) { UINT16 tdata; if(data==5) tdata = 0; else if(data==10) tdata = 1; else if(data==30) tdata = 2; else if(data==100) tdata = 3; else { printf("ERROR: SetDoubleHitResolution: data=%d, must be 5, 10, 30 or 100 ns\n",data); return(ERROR); } tdc890WriteMicro(addr,0x2800); tdc890WriteMicro(addr,tdata); printf("Set Double Hit Resolution to %d ns\n",data); return(OK); } /* get double hit resolution */ STATUS tdc890GetDoubleHitResolution(UINT32 addr, UINT16 *data) { UINT16 tdata; tdc890WriteMicro(addr,0x2900); tdc890ReadMicro(addr,&tdata,1); tdata &= 0x3; if(tdata==0) *data = 5; else if(tdata==1) *data = 10; else if(tdata==2) *data = 30; else if(tdata==3) *data = 100; else { printf("ERROR: GetDoubleHitResolution: tdata=%d (0x%x)\n",tdata,tdata); return(ERROR); } printf("Double Hit Resolution is %d ns\n",*data); return(OK); } /***********************/ /* TDC READOUT OPCODES */ STATUS tdc890EnableTDCHeaderAndTrailer(UINT32 addr) { tdc890WriteMicro(addr,0x3000); return(OK); } STATUS tdc890DisableTDCHeaderAndTrailer(UINT32 addr) { tdc890WriteMicro(addr,0x3100); return(OK); } STATUS tdc890GetTDCHeaderAndTrailer(UINT32 addr, UINT16 *data) { UINT16 tdata; tdc890WriteMicro(addr,0x3200); tdc890ReadMicro(addr,&tdata,1); tdata &= 0x1; if(tdata==0) printf("GetTDCHeaderAndTrailer: TDC Header/Trailer disabled\n"); else if(tdata==1) printf("GetTDCHeaderAndTrailer: TDC Header/Trailer enabled\n"); else { printf("ERROR: GetTDCHeaderAndTrailer: tdata=%d (0x%x)\n",tdata,tdata); return(ERROR); } *data = tdata; return(OK); } STATUS tdc890SetMaxNumberOfHitsPerEvent(UINT32 addr, UINT32 nhits) { UINT16 tdata; tdc890WriteMicro(addr,0x3300); if(nhits==0) tdata = 0; else if(nhits==1) tdata = 1; else if(nhits==2) tdata = 2; else if(nhits==4) tdata = 3; else if(nhits==8) tdata = 4; else if(nhits==16) tdata = 5; else if(nhits==32) tdata = 6; else if(nhits==64) tdata = 7; else if(nhits==128) tdata = 8; else tdata = 9; if(tdata==9) printf("Set Unlimited Number Of Hits Per Event\n"); else printf("Set Maximum Number Of Hits Per Event to %d\n",nhits); tdc890WriteMicro(addr,tdata); return(OK); } STATUS tdc890GetMaxNumberOfHitsPerEvent(UINT32 addr, UINT16 *data) { UINT16 tdata; tdc890WriteMicro(addr,0x3400); tdc890ReadMicro(addr,&tdata,1); tdata &= 0xF; if(tdata==0) printf("GetMaxNumberOfHitsPerEvent: 0 hits\n"); else if(tdata==1) printf("GetMaxNumberOfHitsPerEvent: 1 hit\n"); else if(tdata==2) printf("GetMaxNumberOfHitsPerEvent: 2 hits\n"); else if(tdata==3) printf("GetMaxNumberOfHitsPerEvent: 4 hits\n"); else if(tdata==4) printf("GetMaxNumberOfHitsPerEvent: 8 hits\n"); else if(tdata==5) printf("GetMaxNumberOfHitsPerEvent: 16 hits\n"); else if(tdata==6) printf("GetMaxNumberOfHitsPerEvent: 32 hits\n"); else if(tdata==7) printf("GetMaxNumberOfHitsPerEvent: 64 hits\n"); else if(tdata==8) printf("GetMaxNumberOfHitsPerEvent: 128 hits\n"); else if(tdata==9) printf("GetMaxNumberOfHitsPerEvent: unlimited\n"); else { printf("ERROR: GetMaxNumberOfHitsPerEvent: tdata=%d (0x%x)\n",tdata,tdata); return(ERROR); } *data = tdata; return(OK); } STATUS tdc890EnableTDCErrorMark(UINT32 addr) { tdc890WriteMicro(addr,0x3500); return(OK); } STATUS tdc890DisableTDCErrorMark(UINT32 addr) { tdc890WriteMicro(addr,0x3600); return(OK); } STATUS tdc890EnableTDCErrorBypass(UINT32 addr) { tdc890WriteMicro(addr,0x3700); return(OK); } STATUS tdc890DisableTDCErrorBypass(UINT32 addr) { tdc890WriteMicro(addr,0x3800); return(OK); } STATUS tdc890SetTDCErrorType(UINT32 addr, UINT32 mask) { UINT16 tdata; tdata = mask & 0x7FF; tdc890WriteMicro(addr,0x3300); tdc890WriteMicro(addr,tdata); return(OK); } STATUS tdc890GetTDCErrorType(UINT32 addr, UINT16 *mask) { UINT16 tdata; tdc890WriteMicro(addr,0x3400); tdc890ReadMicro(addr,&tdata,1); tdata &= 0x7FF; if(tdata & 0x1) printf("GetTDCErrorType: Vernier error\n"); else if(tdata & 0x2) printf("GetTDCErrorType: Coarse error\n"); else if(tdata & 0x4) printf("GetTDCErrorType: Channel select error\n"); else if(tdata & 0x8) printf("GetTDCErrorType: L1 buffer parity error\n"); else if(tdata & 0x10) printf("GetTDCErrorType: Trigger fifo parity error\n"); else if(tdata & 0x20) printf("GetTDCErrorType: Trigger matching error\n"); else if(tdata & 0x40) printf("GetTDCErrorType: Readout fifo parity error\n"); else if(tdata & 0x80) printf("GetTDCErrorType: Readout state error\n"); else if(tdata & 0x100) printf("GetTDCErrorType: Set up parity error\n"); else if(tdata & 0x200) printf("GetTDCErrorType: Control parity error\n"); else if(tdata & 0x400) printf("GetTDCErrorType: Jtag instruction parity error\n"); *mask = tdata; return(OK); } /**************************/ /* CHANNEL ENABLE OPCODES */ STATUS tdc890EnableChannel(UINT32 addr, UINT16 channel) { int opcode = 0x4000 + (channel & 0x7F); tdc890WriteMicro(addr,opcode); return(OK); } STATUS tdc890DisableChannel(UINT32 addr, UINT16 channel) { int opcode = 0x4100 + (channel & 0x7F); tdc890WriteMicro(addr,opcode); return(OK); } STATUS tdc890EnableAllChannels(UINT32 addr) { tdc890WriteMicro(addr,0x4200); return(OK); } STATUS tdc890DisableAllChannels(UINT32 addr) { tdc890WriteMicro(addr,0x4300); return(OK); } STATUS tdc890EnableChannels(UINT32 addr, UINT16 channels[8]) { int i; tdc890WriteMicro(addr,0x4400); for(i=0; i<8; i++) tdc890WriteMicro(addr,channels[i]); return(OK); } STATUS tdc890GetChannels(UINT32 addr, UINT16 channels[8]) { int i; tdc890WriteMicro(addr,0x4500); tdc890ReadMicro(addr,channels,1); /* for(i=0; i<8; i++) tdc890ReadMicro(addr,&channels[i],1);*/ return(OK); } /********************/ /* ADVANCED OPCODES */ STATUS tdc890GetTDCError(UINT32 addr, UINT16 ntdc, UINT16 *error) { int opcode = 0x7400 + (ntdc & 0x3); unsigned short tmp; tdc890WriteMicro(addr,opcode); tdc890ReadMicro(addr,&tmp,1); *error = tmp & 0x7FF; return(OK); } STATUS tdc890GetTDCDLLLock(UINT32 addr, UINT16 ntdc, UINT16 *lock) { int opcode = 0x7500 + (ntdc & 0x3); unsigned short tmp; tdc890WriteMicro(addr,opcode); tdc890ReadMicro(addr,&tmp,1); *lock = tmp & 0x1; return(OK); } /****************************************************/ /************** MCST/CBLT functions *****************/ /* from config.h */ #define VME_A32_MSTR_BUS 0x08000000 /* ERRORRRRRRRRRRRRRRRRRRRRRRRRRRRR */ STATUS tdc890InitMCST(int nboards, UINT32 *addr, UINT32 *vmeaddress) { volatile TDC890 *tdc890; unsigned int offset, baseadrs; int ii; sysBusToLocalAdrs(0x09,VME_A32_MSTR_BUS,&offset); printf("A32 offset = 0x%08x\n",offset); printf("offset(0x09)=0x%08x\n",offset); baseadrs = (VME_A32_MSTR_BUS >> 24) & 0xFF; *vmeaddress = offset; printf("tdc base address = 0x%02x, global =0x%08x\n",baseadrs,*vmeaddress); printf("tdc890InitMCST: set base address 0x%02x for following boards:\n", (baseadrs & V890_MCSTBASEADDR_MASK)); for(ii=0; iimcstBaseAddr = (baseadrs & V890_MCSTBASEADDR_MASK); if(ii==0) { tdc890->mcstCtrl = 2; /* active first */ printf("tdc890InitMCST: first board at 0x%08x\n",addr[ii]); } else if(ii==(nboards-1)) { tdc890->mcstCtrl = 1; /* active last */ printf("tdc890InitMCST: last board at 0x%08x\n",addr[ii]); } else { tdc890->mcstCtrl = 3; /* active intermediate */ printf("tdc890InitMCST: middle board at 0x%08x\n",addr[ii]); } } return(OK); } UINT32 tdcbaseadr11, offset11; test33() { UINT32 tdcadr[4] = {0xfa210000,0xfa220000,0xfa230000,0xfa240000}; sysBusToLocalAdrs(0x39,0,&offset11); printf("offset(0x39)=0x%08x\n",offset11); sysBusToLocalAdrs(0x0A,VME_A32_MSTR_BUS,&offset11); printf("offset(0x0A)=0x%08x\n",offset11); sysBusToLocalAdrs(0x09,VME_A32_MSTR_BUS,&offset11); printf("offset(0x09)=0x%08x\n",offset11); tdcbaseadr11 = (/*VME_A32_MSTR_BUS*/offset11 >> 24) & 0xFF; printf("fbrol1: tdcbaseadr11 = 0x%02x\n",tdcbaseadr11); /*tdc890InitMCST(4,tdcadr,tdcbaseadr11);*/ tdc890InitMCST(1,tdcadr,tdcbaseadr11); } test44() { volatile TDC890 *tdc890 = (TDC890 *) offset11; printf("test44: offset11=0x%08x\n",offset11); tdc890->clear = 1; } test333() { UINT32 tdcadr[8] = {0xf0110000,0xf0120000,0xf0130000,0xf0140000, 0xf0150000,0xf0160000,0xf0170000,0xf0180000}; sysBusToLocalAdrs(0x39,0,&offset11); printf("offset(0x39)=0x%08x\n",offset11); sysBusToLocalAdrs(0x0A,VME_A32_MSTR_BUS,&offset11); printf("offset(0x0A)=0x%08x\n",offset11); sysBusToLocalAdrs(0x09,VME_A32_MSTR_BUS,&offset11); printf("offset(0x09)=0x%08x\n",offset11); tdcbaseadr11 = (VME_A32_MSTR_BUS/*offset11*/ >> 24) & 0xFF; printf("fbrol1: tdcbaseadr11 = 0x%02x\n",tdcbaseadr11); tdc890InitMCST(8,tdcadr,tdcbaseadr11); } test444() { volatile TDC890 *tdc890 = (TDC890 *) offset11; printf("test444: offset11=0x%08x\n",offset11); tdc890->clear = 1; } /****************************************************************************** * * tdc890Trig - Issue Software trigger to TDC * tdc890Enable - Bring TDC Online (Enable Gates) * tdc890Disable - Bring TDC Offline (Disable Gates) * tdc890Clear - Clear TDC * tdc890Reset - Clear/Reset TDC * * * RETURNS: None. */ void tdc890Trig(UINT32 addr) { volatile TDC890 *tdc890 = (TDC890 *) addr; tdc890->trigger = 1; return; } void tdc890Enable(UINT32 addr) { volatile TDC890 *tdc890 = (TDC890 *) addr; return; } void tdc890Disable(UINT32 addr) { volatile TDC890 *tdc890 = (TDC890 *) addr; return; } void tdc890Clear(UINT32 addr) { volatile TDC890 *tdc890 = (TDC890 *) addr; tdc890->clear = 1; return; } void tdc890Reset(UINT32 addr) { volatile TDC890 *tdc890 = (TDC890 *) addr; tdc890->moduleReset = 1; return; } void tdc890GetEventCounter(UINT32 addr, UINT32 *nevents) { volatile TDC890 *tdc890 = (TDC890 *) addr; *nevents = tdc890->evCount; return; } void tdc890GetEventStored(UINT32 addr, UINT16 *nevents) { volatile TDC890 *tdc890 = (TDC890 *) addr; *nevents = tdc890->evStored; return; } void tdc890SetAlmostFullLevel(UINT32 addr, UINT16 nwords) { volatile TDC890 *tdc890 = (TDC890 *) addr; tdc890->almostFullLevel = (nwords & 0x3FFF); return; } void tdc890GetAlmostFullLevel(UINT32 addr, UINT16 *nwords) { volatile TDC890 *tdc890 = (TDC890 *) addr; *nwords = tdc890->almostFullLevel; printf("Almost Full Level set to %d (0x%08x) words\n",*nwords,*nwords); return; } /*******************************************/ /*******************************************/ void tdc890Output(UINT32 addr, int delay) { if(delay<=0) delay=2; while(1) { tdc890PrintEvent(addr,0); taskDelay(60*delay); } return; } void tdc890TestMode(UINT32 addr, int off) { volatile TDC890 *tdc890 = (TDC890 *) addr; if(off) tdc890->control &= (~V890_TESTMODE&0xf); else tdc890->control |= V890_TESTMODE; return; } void tdc890Test(UINT32 addr, UINT16 tval) { volatile TDC890 *tdc890 = (TDC890 *) addr; UINT16 testMode=0; testMode = tdc890->control&V890_TESTMODE; if(testMode) { if(tval==0) tdc890->testReg = 0x11223344; else (UINT16 *)(tdc890->testReg) = tval; } else { printf("tdc890Test: ERROR: TestMode not enabled.\n"); } return; } void tdc890SetGeoAddress(UINT32 addr, UINT16 geoaddr) { volatile TDC890 *tdc890 = (TDC890 *) addr; tdc890->geoAddr = geoaddr & 0x1F; return; } void tdc890GetGeoAddress(UINT32 addr, UINT16 *geoaddr) { volatile TDC890 *tdc890 = (TDC890 *) addr; *geoaddr = tdc890->geoAddr & 0x1F; return; } void tdc890SetBLTEventNumber(UINT32 addr, UINT16 nevents) { volatile TDC890 *tdc890 = (TDC890 *) addr; tdc890->bltEventNumber = nevents & 0xFF; return; } void tdc890GetBLTEventNumber(UINT32 addr, UINT16 *nevents) { volatile TDC890 *tdc890 = (TDC890 *) addr; *nevents = tdc890->bltEventNumber; return; } /***********************/ /* INTERRUPT FUNCTIONS */ /***********************/ /* Define Interrupts variables */ BOOL v890IntRunning = FALSE; /* running flag */ int v890IntID = -1; /* id number of TDC generating interrupts */ LOCAL VOIDFUNCPTR v890IntRoutine = NULL; /* user interrupt service routine */ LOCAL int v890IntArg = 0; /* arg to user routine */ LOCAL int v890IntEvCount = 0; /* Number of Events to generate Interrupt */ LOCAL UINT32 v890IntLevel = V890_VME_INT_LEVEL; /* default VME interrupt level */ LOCAL UINT32 v890IntVec = V890_INT_VEC; /* default interrupt Vector */ int Nv890 = 0; volatile struct v890_struct *v890p[20]; int v890IntCount = 0; /* Count of interrupts from TDC */ /******************************************************************************* * * v890Int - default interrupt handler * * This rountine handles the v890 TDC interrupt. A user routine is * called, if one was connected by v890IntConnect(). * * RETURNS: N/A * */ LOCAL void v890Int (void) { UINT32 nevt=0; /* Disable interrupts */ sysIntDisable(v890IntLevel); v890IntCount++; if (v890IntRoutine != NULL) { /* call user routine */ (*v890IntRoutine) (v890IntArg); }else{ if((v890IntID<0) || (v890p[v890IntID] == NULL)) { logMsg("v890Int: ERROR : TDC id %d not initialized \n",v890IntID,0,0,0,0,0); return; } logMsg("v890Int: Processed %d events\n",nevt,0,0,0,0,0); } /* Enable interrupts */ sysIntEnable(v890IntLevel); } /******************************************************************************* * * v890IntConnect - connect a user routine to the v890 TDC interrupt * * This routine specifies the user interrupt routine to be called at each * interrupt. * * RETURNS: OK, or ERROR if Interrupts are enabled */ STATUS v890IntConnect (VOIDFUNCPTR routine, int arg, UINT16 level, UINT16 vector) { if(v890IntRunning) { printf("v890IntConnect: ERROR : Interrupts already Initialized for TDC id %d\n", v890IntID); return(ERROR); } v890IntRoutine = routine; v890IntArg = arg; /* Check for user defined VME interrupt level and vector */ if(level == 0) { v890IntLevel = V890_VME_INT_LEVEL; /* use default */ }else if (level > 7) { printf("v890IntConnect: ERROR: Invalid VME interrupt level (%d). Must be (1-7)\n",level); return(ERROR); } else { v890IntLevel = level; } if(vector == 0) { v890IntVec = V890_INT_VEC; /* use default */ }else if ((vector < 32)||(vector>255)) { printf("v890IntConnect: ERROR: Invalid interrupt vector (%d). Must be (32 0) { v890IntRunning = FALSE; }else{ /*boy semGive(v890Sem);*/ } return (OK); } /***************************/ /* CLAS-SPECIFIC FUNCTIONS */ /***************************/ /* CAEN v1190/v1290 TDCs base address and step */ /* first board has address TDCADR, second TDCADR+TDCSTEP etc */ /* NBOARDS - max # of boards */ #define TDCADR 0x210000 #define TDCSTEP 0x010000 #define NBOARDS 21 void tdc1190ScanCLAS(int *nboards, unsigned int *tdcadr) { volatile TDC890 *tdc890; int ii, res, rdata, errFlag = 0; int iboards, boardID = 0; unsigned int offset; sysBusToLocalAdrs(0x39,0,&offset); iboards = 0; for(ii=0; iifirmwareRev; if((boardID != V890_BOARD_ID)&&(boardID != (V890_BOARD_ID+1))) { printf("tdc1190ScanCLAS: Firmware does not match: 0x%08x (expected 0x%08x)\n", boardID,V890_BOARD_ID); *nboards = iboards; return(OK); } } iboards ++; tdcadr[ii] = (unsigned int *) tdc890; printf("tdc1190ScanCLAS: init v890 TDC number %d at address 0x%08x\n", iboards,tdcadr[ii]); } return(ERROR); } /* set global variables which will be used to program all boards in crate */ void tdc1190SetGlobalWindow(int width, int offset) { window_width = width; window_offset = offset; return; } void tdc1190InitCLAS(int options, int nboards, unsigned int *tdcadr, unsigned int *tdcbaseadr) { int ii, ifull; unsigned short value, value0, value1, array0[32], array1[32], data16; unsigned short dat16[21][10]; short tmp[5], tdata; unsigned int ww, wm, wr; int wo; printf("start v1190/v1290 initialization\n"); /* unpack options */ a24_a32 = (options>>16)&0xFF; sngl_blt_mblt = (options>>8)&0xFF; berr_fifo = (options)&0xFF; if(a24_a32==0x01) { printf(" A24 addressing mode (board-by-board readout)\n"); } else if(a24_a32==0x02) { printf(" A32 addressing mode (chained readout)\n"); } else { printf(" unknown addressing mode, use A24 addressing mode (board-by-board readout)\n"); a24_a32 = 0x01; } if(sngl_blt_mblt==0x01) { printf(" D32 single word readout\n"); } else if(sngl_blt_mblt==0x02) { printf(" D32 DMA (BLT) readout\n"); } else if(sngl_blt_mblt==0x03) { printf(" D64 DMA (MBLT) readout\n"); } else { printf(" unknown readout mode, use D32 single word readout\n"); sngl_blt_mblt = 0x01; } if(berr_fifo==0x00) { printf(" Nwords method: use VME BUS error\n"); } else if(berr_fifo==0x01) { printf(" Nwords method: use event fifo\n"); } else { printf(" unknown Nwords method, use VME BUS error\n"); berr_fifo = 0x00; } /* general initialization */ for(ii=0; ii 51175) value = 0x7FF; else value = ww/25; printf("Set Window Width to %d ns\n",value*25); tdc890WriteMicro(tdcadr[ii],value); } /* Set Trigger Window Offset (ns) */ wo = window_offset;; for(ii=0; ii 1250) value = 50; else value = wm/25; printf("Set Extra Search Margin to %d ns\n",value*25); tdc890WriteMicro(tdcadr[ii],value); } /* reject margin (before window) (ns) */ wr = 50; for(ii=0; ii 1250) value = 50; else value = wr/25; printf("Set Reject Margin to %d ns\n",value*25); tdc890WriteMicro(tdcadr[ii],value); } /* Enable subtraction of trigger time */ for(ii=0; iimcstCtrl = 0; - do it for every board ! */ *tdcbaseadr = 0; printf("Board-by-board readout: tdcbaseadr=0x%08x\n",*tdcbaseadr); } /*********************************************************/ /* VME controller DMA initialization (universe or tempe) */ usrVmeDmaInit(); /* usrVmeDmaConfig params: first: 0 - A16, 1 - A24, 2 - A32 second: 0 - D16 / SINGLE 1 - D32 / SINGLE 2 - D32 / BLOCK (BLT) <- use this for DMA ! 3 - D64 / BLOCK (MBLT) <- use this for DMA ! */ if(a24_a32==0x02) /* chained readout */ { usrVmeDmaConfig(2, sngl_blt_mblt); } else /* board-by-board readout */ { usrVmeDmaConfig(1, sngl_blt_mblt); } return; } /* generic readout for v1190/v1290 TDC boards */ /* time profiling data for 2 boards 550 bytes event size */ int tdc1190ReadEventCLAS(int nboards, UINT32 *tdcadr, INT32 *tdcbuf, INT32 *rlenbuf) { int jj, nev, itdcbuf; int nn[21]; unsigned short tdata; /* whole routine: 42 usec */ /* part1: 6 usec */ if(nboards==0) { logMsg("tdc1190ReadEventCLAS: ERROR: nboards=%d\n",nboards,2,3,4,5,6); } for(jj=0; jj 7) { logMsg("tdc1190ReadEventCLAS: ERROR: [%2d] nev=%d\n",jj,nev,3,4,5,6); } } /* part2: 36 usec */ /* readout */ itdcbuf = 0; for(jj=0; jj 7) { logMsg("tdc1190ReadEventStart: ERROR: [%2d] nev=%d\n",jj,nev,3,4,5,6); } } if(sngl_blt_mblt == 0x01) { logMsg("ERROR: DMA method must be used: sngl_blt_mblt=%d\n", sngl_blt_mblt,2,3,4,5,6); } else { /* readout */ itdcbuf = 0; for(jj=0; jj 0) { /* Trigger Supervisor has 6 event buffer, but we can get 7 if 'parallel' readout is in use */ if(nev > 7) { logMsg("[%2d] ERROR: nev=%d\n",jj,nev,3,4,5,6); } } else { logMsg("[%2d] next time ..\n",jj,2,3,4,5,6); } } /* should use following (?) rlenbuf[0] = tdc890ReadEventDma(tdcbaseadr, tdcbuf); */ ndata = V890_MAX_WORDS_PER_BOARD; mdata = 0; res = usrVme2MemDmaStart((UINT32 *)tdcbaseadr,(UINT32 *)tdcbuf,(ndata<<2)); if(res < 0) { logMsg("CLAStdc890ReadEventCBLT: ERROR: usrVme2MemDmaStart returned %d\n", res,0,0,0,0,0); return(0); } if((res = usrVme2MemDmaDone()) < 0) { logMsg("CLAStdc890ReadEventCBLT: ERROR: usrVme2MemDmaDone returned = %d\n", res,2,3,4,5,6); return(0); } else { mdata = ndata - (res>>2); } rlenbuf[0] = mdata; return(OK); } /* test !!!!!!!!!!!! */ STATUS CLAStdc890ReadEventCBLTStart(int nboards, UINT32 tdcbaseadr, UINT32 *tdcadr, INT32 *tdcbuf, INT32 *rlenbuf) { int rlen, jj, nev, res; int ndata; UINT32 mdata; if(nboards==0) { logMsg("CLAStdc890ReadEventCBLT: ERROR: nboards=%d\n",nboards,2,3,4,5,6); } /*****************************/ /* check if boards are ready */ for(jj=0; jj 0) { /* Trigger Supervisor has 6 event buffer, but we can get 7 if 'parallel' readout is in use */ if(nev > 7) { logMsg("[%2d] ERROR: nev=%d\n",jj,nev,3,4,5,6); } } else { logMsg("[%2d] next time ..\n",jj,2,3,4,5,6); } } ndata = V890_MAX_WORDS_PER_BOARD; mdata = 0; res = usrVme2MemDmaStart((UINT32 *)tdcbaseadr,(UINT32 *)tdcbuf,(ndata<<2)); if(res < 0) { logMsg("CLAStdc890ReadEventCBLT: ERROR: usrVme2MemDmaStart returned %d\n", res,0,0,0,0,0); return(0); } return(OK); } STATUS CLAStdc890ReadEventCBLTStop(INT32 *rlenbuf) { int res; int ndata; UINT32 mdata; if((res = usrVme2MemDmaDone()) < 0) { logMsg("CLAStdc890ReadEventCBLT: ERROR: usrVme2MemDmaDone returned = %d\n", res,2,3,4,5,6); return(0); } else { ndata = V890_MAX_WORDS_PER_BOARD; mdata = ndata - (res>>2); } rlenbuf[0] = mdata; return(OK); } /***********************/ /* SOME TEST FUNCTIONS */ /***********************/ STATUS tdc890Enable1(UINT32 addr) { printf("Enable ...\n"); tdc890WriteMicro(addr,0x2100); taskDelay(100); printf("... done.\n"); return(OK); } STATUS tdc890ReadMicro1(UINT32 addr, UINT16 *data, int nwords) { volatile TDC890 *tdc890 = (TDC890 *) addr; int ii, jj, kk=0; UINT16 mstatus; taskDelay(100); retry: taskDelay(100); mstatus = (tdc890->microHandshake) & V890_MICRO_READOK; printf("--> ReadMicro1: mstatus=%d (0x%x) data=0x%x\n", mstatus,tdc890->microHandshake,tdc890->microReg); if(mstatus) { for(ii=0; iimicroHandshake) & V890_MICRO_READOK)) { jj++; if(jj>1000000) { logMsg("ReadMicro1: ERROR1: Read Status not OK (read %d)\n", ii,0,0,0,0,0); return(ERROR); } } data[ii] = tdc890->microReg; } } else { kk++; if(kk>=1000000) { logMsg("ReadMicro1: ERROR2: Read Status not OK (%d, 0x%x)\n", mstatus,mstatus,3,4,5,6); return(ERROR); } else { goto retry; } } if(kk > 0) printf("kk1(read)=%d\n",kk); return(OK); } STATUS tdc890ReadEdge1(UINT32 addr, UINT16 *data) { UINT16 tdata; tdc890WriteMicro(addr,0x2300); tdc890ReadMicro1(addr,&tdata,1); *data = 0; tdata &= 0x3; printf("Edge: tdata=%d (0x%x)\n",tdata,tdata); if(tdata==0) printf("Edge: meaningless data\n"); else if(tdata==1) printf("Edge: trailing edge\n"); else if(tdata==2) printf("Edge: leading edge\n"); else if(tdata==3) printf(": paired measurement\n"); else { printf("Edge: ERROR, tdata=%d (0x%x)\n",tdata,tdata); return(ERROR); } *data = tdata; return(OK); } #define TDCADDRESS 0x210000 void tdc890_testopcode() { unsigned int tdcadr1; int status; unsigned short data16; unsigned int data321, data322; sysBusToLocalAdrs(0x39,TDCADDRESS,&tdcadr1); printf("tdcadr1=0x%08x\n",tdcadr1); /* Init */ tdc890Init(tdcadr1,0,1,0); tdc890Reset(tdcadr1); tdc890Clear(tdcadr1); printf("\n\n ..... edge test .............\n\n"); /* tdc890SetPairResolution(tdcadr1, 100, 400); tdc890GetPairResolution(tdcadr1, &data321, &data322); */ tdc890Enable1(tdcadr1); taskDelay(100); tdc890ReadEdge1(tdcadr1,&data16); taskDelay(100); return; /* Program TDC for trigger matching mode */ tdc890SetTriggerMatchingMode(tdcadr1); tdc890ReadAcquisitionMode(tdcadr1,&data16); /* Set Trigger Window Width (ns) */ tdc890SetWindowWidth(tdcadr1, 1000); /* Set Trigger Window Offset (ns) */ tdc890SetWindowOffset(tdcadr1, -1025); /* (ns) */ tdc890SetExtraSearchMargin(tdcadr1, 25); /* (ns) */ tdc890SetRejectMargin(tdcadr1, 50); /* Enable subtraction of trigger time */ tdc890EnableTriggerTimeSubtruction(tdcadr1); /* Enable leading edge */ tdc890SetEdgeDetectionConfig(tdcadr1, 2); /* get trigger configuration */ tdc890ReadTriggerConfiguration(tdcadr1); /* get edge detection configuration */ tdc890ReadEdgeDetectionConfig(tdcadr1,&data16); /* set dead time (double peak resolution) */ tdc890SetDoubleHitResolution(tdcadr1, 10); tdc890GetDoubleHitResolution(tdcadr1, &data16); } test2() { unsigned int tdcadr1; unsigned short data16; sysBusToLocalAdrs(0x39,TDCADDRESS,&tdcadr1); printf("tdcadr1=0x%08x\n",tdcadr1); tdc890ReadEdgeDetectionConfig(tdcadr1,&data16); } tdc890testopcodes() { unsigned short data16; unsigned int data32, data32_1, data32_2; unsigned int tdcadr1; sysBusToLocalAdrs(0x39,TDCADDRESS,&tdcadr1); printf("tdcadr1=0x%08x\n",tdcadr1); printf("start v890\n"); tdc890Init(tdcadr1,0,1,0); tdc890Clear(tdcadr1); tdc890Reset(tdcadr1); /* Program TDC for continuous storage mode */ tdc890SetContinuousStorageMode(tdcadr1); tdc890ReadAcquisitionMode(tdcadr1,&data16); /* Program TDC for trigger matching mode */ tdc890SetTriggerMatchingMode(tdcadr1); tdc890ReadAcquisitionMode(tdcadr1,&data16); /* Set Trigger Window Width (ns) (step 25ns) */ tdc890SetWindowWidth(tdcadr1, 1000); /* Set Trigger Window Offset (ns) (step 25ns) */ tdc890SetWindowOffset(tdcadr1, -900); /* (ns) (step 25ns) */ /*tdc890SetExtraSearchMargin(tdcadr1, 225);*/ /* (ns) (step 25ns) */ /*tdc890SetRejectMargin(tdcadr1, 125);*/ /* Enable subtraction of trigger time */ tdc890EnableTriggerTimeSubtruction(tdcadr1); /*tdc890DisableTriggerTimeSubtruction(tdcadr1);*/ /* get trigger configuration */ tdc890ReadTriggerConfiguration(tdcadr1); /* edge detection */ tdc890SetEdgeDetectionConfig(tdcadr1, 0); tdc890ReadEdgeDetectionConfig(tdcadr1,&data16); tdc890SetEdgeDetectionConfig(tdcadr1, 1); tdc890ReadEdgeDetectionConfig(tdcadr1,&data16); tdc890SetEdgeDetectionConfig(tdcadr1, 2); tdc890ReadEdgeDetectionConfig(tdcadr1,&data16); tdc890SetEdgeDetectionConfig(tdcadr1, 3); tdc890ReadEdgeDetectionConfig(tdcadr1,&data16); /* edge resolution */ tdc890SetEdgeResolution(tdcadr1, 800); tdc890GetEdgeResolution(tdcadr1, &data16); tdc890SetEdgeResolution(tdcadr1, 200); tdc890GetEdgeResolution(tdcadr1, &data16); tdc890SetEdgeResolution(tdcadr1, 100); tdc890GetEdgeResolution(tdcadr1, &data16); /* pair resolution */ tdc890SetPairResolution(tdcadr1, 200, 800); tdc890GetPairResolution(tdcadr1, &data32_1, &data32_2); /* double hit resolution */ tdc890SetDoubleHitResolution(tdcadr1, 100); tdc890GetDoubleHitResolution(tdcadr1, &data16); tdc890SetDoubleHitResolution(tdcadr1, 30); tdc890GetDoubleHitResolution(tdcadr1, &data16); tdc890SetDoubleHitResolution(tdcadr1, 10); tdc890GetDoubleHitResolution(tdcadr1, &data16); tdc890SetDoubleHitResolution(tdcadr1, 5); tdc890GetDoubleHitResolution(tdcadr1, &data16); printf("end v890\n"); }