/*----------------------------------------------------------------------------*/ /** * @mainpage *
 *  Copyright (c) 2012        Southeastern Universities Research Association, *
 *                            Thomas Jefferson National Accelerator Facility  *
 *                                                                            *
 *    This software was developed under a United States Government license    *
 *    described in the NOTICE file included as part of this distribution.     *
 *                                                                            *
 *    Authors: Bryan Moffit                                                   *
 *             moffit@jlab.org                   Jefferson Lab, MS-12B3       *
 *             Phone: (757) 269-5660             12000 Jefferson Ave.         *
 *             Fax:   (757) 269-5800             Newport News, VA 23606       *
 *                                                                            *
 *----------------------------------------------------------------------------*
 *
 * Description:
 *     Primitive trigger control for VME CPUs using the TJNAF Trigger
 *     Supervisor (TI) card
 *
 * 
*----------------------------------------------------------------------------*/ #define _GNU_SOURCE #define DEVEL #include #ifdef VXWORKS #include #include #include #include #include #include #include #include #include "vxCompat.h" #include "../jvme/jvme.h" #else #include #include #include "jvme.h" #endif #include #include #include "tiLib.h" /* Mutex to guard TI read/writes */ pthread_mutex_t tiMutex = PTHREAD_MUTEX_INITIALIZER; #define TILOCK if(pthread_mutex_lock(&tiMutex)<0) perror("pthread_mutex_lock"); #define TIUNLOCK if(pthread_mutex_unlock(&tiMutex)<0) perror("pthread_mutex_unlock"); /* Global Variables */ volatile struct TI_A24RegStruct *TIp=NULL; /* pointer to TI memory map */ volatile unsigned int *TIpd=NULL; /* pointer to TI data FIFO */ unsigned long tiA24Offset=0; /* Difference in CPU A24 Base and VME A24 Base */ unsigned int tiA32Base =0x08000000; /* Minimum VME A32 Address for use by TI */ unsigned long tiA32Offset=0; /* Difference in CPU A32 Base and VME A32 Base */ int tiMaster=1; /* Whether or not this TI is the Master */ int tiCrateID=0x59; /* Crate ID */ int tiBlockLevel=0; /* Current Block level for TI */ int tiNextBlockLevel=0; /* Next Block level for TI */ unsigned int tiIntCount = 0; unsigned int tiAckCount = 0; unsigned int tiDaqCount = 0; /* Block count from previous update (in daqStatus) */ unsigned int tiReadoutMode = 0; unsigned int tiTriggerSource = 0; /* Set with tiSetTriggerSource(...) */ unsigned int tiSlaveMask = 0; /* TI Slaves (mask) to be used with TI Master */ int tiDoAck = 0; int tiNeedAck = 0; static BOOL tiIntRunning = FALSE; /* running flag */ static VOIDFUNCPTR tiIntRoutine = NULL; /* user intererrupt service routine */ static int tiIntArg = 0; /* arg to user routine */ static unsigned int tiIntLevel = TI_INT_LEVEL; /* VME Interrupt level */ static unsigned int tiIntVec = TI_INT_VEC; /* default interrupt vector */ static VOIDFUNCPTR tiAckRoutine = NULL; /* user trigger acknowledge routine */ static int tiAckArg = 0; /* arg to user trigger ack routine */ static int tiReadoutEnabled = 1; /* Readout enabled, by default */ int tiFiberLatencyOffset = 0xbf; /* Default offset for fiber latency */ static int tiFiberLatencyMeasurement = 0; /* Measured fiber latency */ static int sasha_syncDelay_write = 0; /* Check FiberOptical Delay register */ static int tiVersion = 0x0; /* Firmware version */ static int tiSyncEventFlag = 0; /* Sync Event/Block Flag */ static int tiSyncEventReceived = 0; /* Indicates reception of sync event */ static int tiNReadoutEvents = 0; /* Number of events to readout from crate modules */ static int tiDoSyncResetRequest =0; /* Option to request a sync reset during readout ack */ static int tiSlotNumber=0; /* Slot number in which the TI resides */ static int tiSwapTriggerBlock=0; /* Decision on whether or not to swap the trigger block endianness */ static int tiBusError=0; /* Bus Error block termination */ static int tiSlaveFiberIn=1; /* Which Fiber port to use when in Slave mode */ static int tiNoVXS=0; /* 1 if not in VXS crate */ static int tiSyncResetType=TI_SYNCCOMMAND_SYNCRESET_4US; /* Set default SyncReset Type to Fixed 4 us */ static unsigned int tiTrigPatternData[16]= /* Default Trigger Table to be loaded */ { /* TS#1,2,3,4,5,6 generates Trigger1 (physics trigger), No Trigger2 (playback trigger), No SyncEvent; */ 0x43424100, 0x47464544, 0x4b4a4948, 0x4f4e4d4c, 0x53525150, 0x57565554, 0x5b5a5958, 0x5f5e5d5c, 0x63626160, 0x67666564, 0x6b6a6968, 0x6f6e6d6c, 0x73727170, 0x77767574, 0x7b7a7978, 0x7f7e7d7c, }; /* Interrupt/Polling routine prototypes (static) */ static void tiInt(void); #ifndef VXWORKS static void tiPoll(void); static void tiStartPollingThread(void); /* polling thread pthread and pthread_attr */ pthread_attr_t tipollthread_attr; pthread_t tipollthread; #endif #ifdef VXWORKS extern int sysBusToLocalAdrs(int, char *, char **); extern int intDisconnect(int); extern int sysIntEnable(int); IMPORT STATUS sysIntDisable(int); IMPORT STATUS sysVmeDmaDone(int, int); IMPORT STATUS sysVmeDmaSend(UINT32, UINT32, int, BOOL); #endif static void FiberMeas(); /* VXS Payload Port to VME Slot map */ #define MAX_VME_SLOTS 21 /* This is either 20 or 21 */ unsigned short PayloadPort[MAX_VME_SLOTS+1] = { 0, /* Filler for mythical VME slot 0 */ #if MAX_VME_SLOTS == 21 0, /* VME Controller */ #endif 17, 15, 13, 11, 9, 7, 5, 3, 1, 0, /* Switch Slot A - SD */ 0, /* Switch Slot B - CTP/GTP */ 2, 4, 6, 8, 10, 12, 14, 16, 18 /* VME Slot Furthest to the Right - TI */ }; /** * @defgroup PreInit Pre-Initialization * @defgroup SlavePreInit Slave Pre-Initialization * @ingroup PreInit * @defgroup Config Initialization/Configuration * @defgroup MasterConfig Master Configuration * @ingroup Config * @defgroup SlaveConfig Slave Configuration * @ingroup Config * @defgroup Status Status * @defgroup MasterStatus Master Status * @ingroup Status * @defgroup Readout Data Readout * @defgroup MasterReadout Master Data Readout * @ingroup Readout * @defgroup IntPoll Interrupt/Polling * @defgroup Deprec Deprecated - To be removed */ /** * @ingroup PreInit * @brief Set the Fiber Latency Offset to be used during initialization * * @param flo fiber latency offset * * @return OK if successful, otherwise ERROR */ int tiSetFiberLatencyOffset_preInit(int flo) { if((flo<0) || (flo>0x1ff)) { printf("%s: ERROR: Invalid Fiber Latency Offset (%d)\n", __FUNCTION__,flo); return ERROR; } tiFiberLatencyOffset = flo; return OK; } /** * @ingroup PreInit * @brief Set the CrateID to be used during initialization * * @param cid Crate ID * * @return OK if successful, otherwise ERROR */ int tiSetCrateID_preInit(int cid) { if((cid<0) || (cid>0xff)) { printf("%s: ERROR: Invalid Crate ID (%d)\n", __FUNCTION__,cid); return ERROR; } tiCrateID = cid; return OK; } /** * @ingroup SlavePreInit * * @brief Set the Fiber In port to be used during initialization of TI Slave * * @param port Fiber In Port * * @return OK if successful, otherwise ERROR */ int tiSetFiberIn_preInit(int port) { if((port!=1) || (port!=5)) { printf("%s: ERROR: Invalid Slave Fiber In Port (%d)\n", __FUNCTION__,port); return ERROR; } tiSlaveFiberIn=port; return OK; } /** * @ingroup Config * @brief Initialize the TIp register space into local memory, * and setup registers given user input * * * @param tAddr Address or Slot Number * - A24 VME Address of the TI (0x000016 - 0xffffff) * - Slot number of TI (1 - 21) * * @param mode Readout/Triggering Mode * - 0 External Trigger - Interrupt Mode * - 1 TI/TImaster Trigger - Interrupt Mode * - 2 External Trigger - Polling Mode * - 3 TI/TImaster Trigger - Polling Mode * * @param iFlag Initialization bit mask * - 0 Do not initialize the board, just setup the pointers to the registers * - 1 Use Slave Fiber 5, instead of 1 * - 2 Ignore firmware check * * @return OK if successful, otherwise ERROR. * */ int tiInit(unsigned int tAddr, unsigned int mode, int iFlag) { unsigned long laddr; unsigned int rval, boardID, prodID, i2cread=0; unsigned int firmwareInfo; int stat; int noBoardInit=0, noFirmwareCheck=0; int fail_fiber_meas = 0; /* Check VME address */ if(tAddr<0 || tAddr>0xffffff) { printf("%s: ERROR: Invalid VME Address (%d)\n",__FUNCTION__, tAddr); } if(tAddr==0) { printf("%s: Scanning for TI...\n",__FUNCTION__); tAddr=tiFind(); if(tAddr==0) { printf("%s: ERROR: Unable to find TI\n",__FUNCTION__); return ERROR; } } if(tAddr<22) { /* User enter slot number, shift it to VME A24 address */ printf("%s: Initializing using slot number %d (VME address 0x%x)\n", __FUNCTION__, tAddr, tAddr<<19); tAddr = tAddr<<19; } if(iFlag&TI_INIT_NO_INIT) { noBoardInit = 1; } if(iFlag&TI_INIT_SLAVE_FIBER_5) { tiSlaveFiberIn=5; } if(iFlag&TI_INIT_SKIP_FIRMWARE_CHECK) { noFirmwareCheck=1; } #ifdef VXWORKS stat = sysBusToLocalAdrs(0x39,(char *)tAddr,(char **)&laddr); if (stat != 0) { printf("%s: ERROR: Error in sysBusToLocalAdrs res=%d \n",__FUNCTION__,stat); return ERROR; } else { printf("TI address = 0x%x\n",laddr); } #else stat = vmeBusToLocalAdrs(0x39,(char *)(unsigned long)tAddr,(char **)&laddr); if (stat != 0) { printf("%s: ERROR: Error in vmeBusToLocalAdrs res=%d \n",__FUNCTION__,stat); return ERROR; } else { if(!noBoardInit) printf("TI VME (Local) address = 0x%.8x (0x%.8lx)\n",tAddr,laddr); } #endif tiA24Offset = laddr-tAddr; /* Set Up pointer */ TIp = (struct TI_A24RegStruct *)laddr; /* Check if TI board is readable */ #ifdef VXWORKS stat = vxMemProbe((char *)(&TIp->boardID),0,4,(char *)&rval); #else stat = vmeMemProbe((char *)(&TIp->boardID),4,(char *)&rval); #endif if (stat != 0) { printf("%s: ERROR: TI card not addressable\n",__FUNCTION__); TIp=NULL; return(-1); } else { /* Check that it is a TI */ if(((rval&TI_BOARDID_TYPE_MASK)>>16) != TI_BOARDID_TYPE_TI) { printf("%s: ERROR: Invalid Board ID: 0x%x (rval = 0x%08x)\n", __FUNCTION__, (rval&TI_BOARDID_TYPE_MASK)>>16,rval); TIp=NULL; return(ERROR); } /* Check if this is board has a valid slot number */ boardID = (rval&TI_BOARDID_GEOADR_MASK)>>8; if((boardID <= 0)||(boardID >21)) { printf("%s: ERROR: Board Slot ID is not in range: %d\n", __FUNCTION__,boardID); TIp=NULL; return(ERROR); } tiSlotNumber = boardID; /* Get the "production" type bits. 2=modTI, 1=production, 0=prototype */ prodID = (rval&TI_BOARDID_PROD_MASK)>>16; /* Determine whether or not we'll need to swap the trigger block endianess */ if( ((TIp->boardID & TI_BOARDID_TYPE_MASK)>>16) != TI_BOARDID_TYPE_TI) tiSwapTriggerBlock=1; else tiSwapTriggerBlock=0; } /* Check to see if we're in a VXS Crate */ if((boardID==20) || (boardID==21)) { /* It's possible... now check for valid i2c to SWB (SD) */ i2cread = vmeRead32(&TIp->SWB[(0x3C7C/4)]) & 0xFFFF; /* Device 1, Address 0x1F */ if((i2cread!=0) && (i2cread!=0xffff)) { /* Valid response */ vmeSetMaximumVMESlots(boardID); tiNoVXS=0; } else { tiNoVXS=1; } } if(!noBoardInit) { if(tiMaster==0) /* Reload only on the TI Slaves */ { tiReload(); taskDelay(60); } tiDisableTriggerSource(0); tiDisableVXSSignals(); } /* Get the Firmware Information and print out some details */ firmwareInfo = tiGetFirmwareVersion(); if(firmwareInfo>0) { int supportedVersion = TI_SUPPORTED_FIRMWARE; int supportedType = TI_SUPPORTED_TYPE; int tiFirmwareType = (firmwareInfo & TI_FIRMWARE_TYPE_MASK)>>12; tiVersion = firmwareInfo&0xFFF; printf(" ID: 0x%x \tFirmware (type - revision): 0x%X - 0x%03X\n", (firmwareInfo&TI_FIRMWARE_ID_MASK)>>16, tiFirmwareType, tiVersion); if(tiFirmwareType != supportedType) { if(noFirmwareCheck) { printf("%s: WARN: Firmware type (%d) not supported by this driver.\n Supported type = %d (IGNORED)\n", __FUNCTION__,tiFirmwareType,supportedType); } else { printf("%s: ERROR: Firmware Type (%d) not supported by this driver.\n Supported type = %d\n", __FUNCTION__,tiFirmwareType,supportedType); TIp=NULL; return ERROR; } } if(tiVersion < supportedVersion) { if(noFirmwareCheck) { printf("%s: WARN: Firmware version (0x%x) not supported by this driver.\n Supported version = 0x%x (IGNORED)\n", __FUNCTION__,tiVersion,supportedVersion); } else { printf("%s: ERROR: Firmware version (0x%x) not supported by this driver.\n Supported version = 0x%x\n", __FUNCTION__,tiVersion,supportedVersion); TIp=NULL; return ERROR; } } } else { printf("%s: ERROR: Invalid firmware 0x%08x\n", __FUNCTION__,firmwareInfo); return ERROR; } /* Check if we should exit here, or initialize some board defaults */ if(noBoardInit) { return OK; } /* Set some defaults, dependent on Master/Slave status */ tiReadoutMode = mode; switch(mode) { case TI_READOUT_EXT_INT: case TI_READOUT_EXT_POLL: printf("... Configure as TI Master...\n"); /* Master (Supervisor) Configuration: takes in external triggers */ tiMaster = 1; /* Clear the Slave Mask */ tiSlaveMask = 0; /* BUSY from Loopback and Switch Slot B */ if(tiNoVXS==1) tiSetBusySource(TI_BUSY_LOOPBACK,1); else tiSetBusySource(TI_BUSY_LOOPBACK | TI_BUSY_SWB,1); /* Onboard Clock Source */ tiSetClockSource(TI_CLOCK_INTERNAL); /* Loopback Sync Source */ tiSetSyncSource(TI_SYNC_LOOPBACK); break; case TI_READOUT_TS_INT: case TI_READOUT_TS_POLL: printf("... Configure as TI Slave...\n"); /* Slave Configuration: takes in triggers from the Master (supervisor) */ tiMaster = 0; /* BUSY from Switch Slot B */ if(tiNoVXS==1) tiSetBusySource(0,1); else tiSetBusySource(TI_BUSY_SWB,1); if(tiSlaveFiberIn==1) { /* Enable HFBR#1 */ tiEnableFiber(1); /* HFBR#1 Clock Source */ tiSetClockSource(1); /* HFBR#1 Sync Source */ tiSetSyncSource(TI_SYNC_HFBR1); /* HFBR#1 Trigger Source */ tiSetTriggerSource(TI_TRIGGER_HFBR1); } else if(tiSlaveFiberIn==5) { /* Enable HFBR#5 */ tiEnableFiber(5); /* HFBR#5 Clock Source */ tiSetClockSource(5); /* HFBR#5 Sync Source */ tiSetSyncSource(TI_SYNC_HFBR5); /* HFBR#5 Trigger Source */ tiSetTriggerSource(TI_TRIGGER_HFBR5); } break; default: printf("%s: ERROR: Invalid TI Mode %d\n", __FUNCTION__,mode); return ERROR; } tiReadoutMode = mode; /* Setup some Other Library Defaults */ if(tiMaster!=1) { // int ii = 0; // for(ii = 0; ii < 500; ii++){ FiberMeas(); // printf("MEASURE FIBER LENGTH %d %d\n",ii, tiGetFiberLatencyMeasurement() ); // if( tiGetFiberLatencyMeasurement() < 10) fail_fiber_meas++; // } vmeWrite32(&TIp->syncWidth, 0x24); // TI IODELAY reset vmeWrite32(&TIp->reset,TI_RESET_IODELAY); taskDelay(1); // TI Sync auto alignment if(tiSlaveFiberIn==1) vmeWrite32(&TIp->reset,TI_RESET_AUTOALIGN_HFBR1_SYNC); else vmeWrite32(&TIp->reset,TI_RESET_AUTOALIGN_HFBR5_SYNC); taskDelay(1); // TI auto fiber delay measurement vmeWrite32(&TIp->reset,TI_RESET_MEASURE_LATENCY); taskDelay(1); // TI auto alignement fiber delay vmeWrite32(&TIp->reset,TI_RESET_FIBER_AUTO_ALIGN); taskDelay(1); } else { // TI IODELAY reset vmeWrite32(&TIp->reset,TI_RESET_IODELAY); taskDelay(1); // TI Sync auto alignment vmeWrite32(&TIp->reset,TI_RESET_AUTOALIGN_HFBR1_SYNC); taskDelay(1); // Perform a trigger link reset tiTrigLinkReset(); taskDelay(1); } /* Reset I2C engine */ vmeWrite32(&TIp->reset,TI_RESET_I2C); /* Setup a default Sync Delay and Pulse width */ if(tiMaster==1) tiSetSyncDelayWidth(0x54, 0x2f, 0); /* Set default sync delay (fiber compensation) */ if(tiMaster==1) vmeWrite32(&TIp->fiberSyncDelay, (tiFiberLatencyOffset<<16)&TI_FIBERSYNCDELAY_LOOPBACK_SYNCDELAY_MASK); /* Set Default Block Level to 1, and default crateID */ if(tiMaster==1) tiSetBlockLevel(1); tiSetCrateID(tiCrateID); /* Set Event format for CODA 3.0 */ tiSetEventFormat(3); /* Set Default Trig1 and Trig2 delay=16ns (0+1)*16ns, width=64ns (15+1)*4ns */ tiSetTriggerPulse(1,0,15,0); tiSetTriggerPulse(2,0,15,0); /* Set the default prescale factor to 0 for rate/(0+1) */ tiSetPrescale(0); /* Setup A32 data buffer with library default */ tiSetAdr32(tiA32Base); /* Enable Bus Errors to complete Block transfers */ tiEnableBusError(); /* MGT reset */ if(tiMaster==1) { tiResetMGT(); } /* Set this to 1 (ROC Lock mode), by default. */ tiSetBlockBufferLevel(1); /* Disable all TS Inputs */ tiDisableTSInput(TI_TSINPUT_ALL); return fail_fiber_meas; // return OK; } /** * @ingroup Config * @brief Find the TI within the prescribed "GEO Slot to A24 VME Address" * range from slot 3 to 21. * * @return A24 VME address if found. Otherwise, 0 */ unsigned int tiFind() { int islot, stat, tiFound=0; unsigned int tAddr, rval; unsigned long laddr; for(islot = 0; islot<20; islot++) { /* Form VME base address from slot number Start from slot 21 and 20, then go from 2 to 19 */ switch(islot) { case 0: tAddr = (21<<19); break; case 1: tAddr = (20<<19); break; default: tAddr = (islot<<19); } #ifdef VXWORKS stat = sysBusToLocalAdrs(0x39,(char *)tAddr,(char **)&laddr); #else stat = vmeBusToLocalAdrs(0x39,(char *)(unsigned long)tAddr,(char **)&laddr); #endif if(stat != 0) continue; /* Check if this address is readable */ #ifdef VXWORKS stat = vxMemProbe((char *)(laddr),0,4,(char *)&rval); #else stat = vmeMemProbe((char *)(laddr),4,(char *)&rval); #endif if (stat != 0) { continue; } else { /* Check that it is a TI */ if(((rval&TI_BOARDID_TYPE_MASK)>>16) != TI_BOARDID_TYPE_TI) { continue; } else { printf("%s: Found TI at 0x%08x\n",__FUNCTION__,tAddr); tiFound=1; break; } } } if(tiFound) return tAddr; else return 0; } int tiCheckAddresses() { unsigned long offset=0, expected=0, base=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } printf("%s:\n\t ---------- Checking TI address space ---------- \n",__FUNCTION__); base = (unsigned long) &TIp->boardID; offset = ((unsigned long) &TIp->trigsrc) - base; expected = 0x20; if(offset != expected) printf("%s: ERROR TIp->triggerSource not at offset = 0x%lx (@ 0x%lx)\n", __FUNCTION__,expected,offset); offset = ((unsigned long) &TIp->syncWidth) - base; expected = 0x80; if(offset != expected) printf("%s: ERROR TIp->syncWidth not at offset = 0x%lx (@ 0x%lx)\n", __FUNCTION__,expected,offset); offset = ((unsigned long) &TIp->adr24) - base; expected = 0xD0; if(offset != expected) printf("%s: ERROR TIp->adr24 not at offset = 0x%lx (@ 0x%lx)\n", __FUNCTION__,expected,offset); offset = ((unsigned long) &TIp->reset) - base; expected = 0x100; if(offset != expected) printf("%s: ERROR TIp->reset not at offset = 0x%lx (@ 0x%lx)\n", __FUNCTION__,expected,offset); offset = ((unsigned long) &TIp->SWB_status) - base; expected = 0x2000; if(offset != expected) printf("%s: ERROR TIp->SWB_status not at offset = 0x%lx (@ 0x%lx)\n", __FUNCTION__,expected,offset); offset = ((unsigned long) &TIp->SWA_status) - base; expected = 0x2800; if(offset != expected) printf("%s: ERROR TIp->SWA_status not at offset = 0x%lx (@ 0x%lx)\n", __FUNCTION__,expected,offset); offset = ((unsigned long) &TIp->JTAGPROMBase[0]) - base; expected = 0x10000; if(offset != expected) printf("%s: ERROR TIp->JTAGPROMBase[0] not at offset = 0x%lx (@ 0x%lx)\n", __FUNCTION__,expected,offset); offset = ((unsigned long) &TIp->JTAGFPGABase[0]) - base; expected = 0x20000; if(offset != expected) printf("%s: ERROR TIp->JTAGFPGABase[0] not at offset = 0x%lx (@ 0x%lx)\n", __FUNCTION__,expected,offset); offset = ((unsigned long) &TIp->SWA) - base; expected = 0x30000; if(offset != expected) printf("%s: ERROR TIp->SWA not at offset = 0x%lx (@ 0x%lx)\n", __FUNCTION__,expected,offset); offset = ((unsigned long) &TIp->SWB) - base; expected = 0x40000; if(offset != expected) printf("%s: ERROR TIp->SWB not at offset = 0x%lx (@ 0x%lx)\n", __FUNCTION__,expected,offset); return OK; } /** * @ingroup Status * @brief Print some status information of the TI to standard out * * @param pflag if pflag>0, print out raw registers * */ void tiStatus(int pflag) { struct TI_A24RegStruct ro; int iinp, iblock, ifiber; unsigned int blockStatus[5], nblocksReady, nblocksNeedAck; unsigned int fibermask; unsigned long TIBase; unsigned long long int l1a_count=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return; } /* latch live and busytime scalers */ tiLatchTimers(); l1a_count = tiGetEventCounter(); tiGetCurrentBlockLevel(); TILOCK; ro.boardID = vmeRead32(&TIp->boardID); ro.fiber = vmeRead32(&TIp->fiber); ro.intsetup = vmeRead32(&TIp->intsetup); ro.trigDelay = vmeRead32(&TIp->trigDelay); ro.adr32 = vmeRead32(&TIp->adr32); ro.blocklevel = vmeRead32(&TIp->blocklevel); ro.vmeControl = vmeRead32(&TIp->vmeControl); ro.trigsrc = vmeRead32(&TIp->trigsrc); ro.sync = vmeRead32(&TIp->sync); ro.busy = vmeRead32(&TIp->busy); ro.clock = vmeRead32(&TIp->clock); ro.trig1Prescale = vmeRead32(&TIp->trig1Prescale); ro.blockBuffer = vmeRead32(&TIp->blockBuffer); ro.tsInput = vmeRead32(&TIp->tsInput); ro.output = vmeRead32(&TIp->output); ro.blocklimit = vmeRead32(&TIp->blocklimit); ro.fiberSyncDelay = vmeRead32(&TIp->fiberSyncDelay); ro.GTPStatusA = vmeRead32(&TIp->GTPStatusA); ro.GTPStatusB = vmeRead32(&TIp->GTPStatusB); /* Latch scalers first */ vmeWrite32(&TIp->reset,TI_RESET_SCALERS_LATCH); ro.livetime = vmeRead32(&TIp->livetime); ro.busytime = vmeRead32(&TIp->busytime); ro.inputCounter = vmeRead32(&TIp->inputCounter); for(iblock=0;iblock<4;iblock++) blockStatus[iblock] = vmeRead32(&TIp->blockStatus[iblock]); blockStatus[4] = vmeRead32(&TIp->adr24); ro.nblocks = vmeRead32(&TIp->nblocks); ro.GTPtriggerBufferLength = vmeRead32(&TIp->GTPtriggerBufferLength); ro.rocEnable = vmeRead32(&TIp->rocEnable); TIUNLOCK; TIBase = (unsigned long)TIp; printf("\n"); #ifdef VXWORKS printf("STATUS for TI at base address 0x%08x \n", (unsigned int) TIp); #else printf("STATUS for TI at VME (Local) base address 0x%08lx (0x%lx) \n", (unsigned long) TIp - tiA24Offset, (unsigned long) TIp); #endif printf("--------------------------------------------------------------------------------\n"); printf(" A32 Data buffer "); if((ro.vmeControl&TI_VMECONTROL_A32) == TI_VMECONTROL_A32) { printf("ENABLED at "); #ifdef VXWORKS printf("base address 0x%08x\n", (unsigned long)TIpd); #else printf("VME (Local) base address 0x%08lx (0x%lx)\n", (unsigned long)TIpd - tiA32Offset, (unsigned long)TIpd); #endif } else printf("DISABLED\n"); if(tiMaster) printf(" Configured as a TI Master\n"); else printf(" Configured as a TI Slave\n"); printf(" Readout Count: %d\n",tiIntCount); printf(" Ack Count: %d\n",tiAckCount); printf(" L1A Count: %llu\n",l1a_count); printf(" Block Limit: %d %s\n",ro.blocklimit, (ro.blockBuffer & TI_BLOCKBUFFER_BUSY_ON_BLOCKLIMIT)?"* Finished *":"- In Progress -"); printf(" Block Count: %d\n",ro.nblocks & TI_NBLOCKS_COUNT_MASK); if(pflag>0) { printf(" Registers (offset):\n"); printf(" boardID (0x%04lx) = 0x%08x\t", (unsigned long)&TIp->boardID - TIBase, ro.boardID); printf(" fiber (0x%04lx) = 0x%08x\n", (unsigned long)(&TIp->fiber) - TIBase, ro.fiber); printf(" intsetup (0x%04lx) = 0x%08x\t", (unsigned long)(&TIp->intsetup) - TIBase, ro.intsetup); printf(" trigDelay (0x%04lx) = 0x%08x\n", (unsigned long)(&TIp->trigDelay) - TIBase, ro.trigDelay); printf(" adr32 (0x%04lx) = 0x%08x\t", (unsigned long)(&TIp->adr32) - TIBase, ro.adr32); printf(" blocklevel (0x%04lx) = 0x%08x\n", (unsigned long)(&TIp->blocklevel) - TIBase, ro.blocklevel); printf(" vmeControl (0x%04lx) = 0x%08x\n", (unsigned long)(&TIp->vmeControl) - TIBase, ro.vmeControl); printf(" trigger (0x%04lx) = 0x%08x\t", (unsigned long)(&TIp->trigsrc) - TIBase, ro.trigsrc); printf(" sync (0x%04lx) = 0x%08x\n", (unsigned long)(&TIp->sync) - TIBase, ro.sync); printf(" busy (0x%04lx) = 0x%08x\t", (unsigned long)(&TIp->busy) - TIBase, ro.busy); printf(" clock (0x%04lx) = 0x%08x\n", (unsigned long)(&TIp->clock) - TIBase, ro.clock); printf(" blockBuffer (0x%04lx) = 0x%08x\t", (unsigned long)(&TIp->blockBuffer) - TIBase, ro.blockBuffer); printf(" output (0x%04lx) = 0x%08x\n", (unsigned long)(&TIp->output) - TIBase, ro.output); printf(" fiberSyncDelay (0x%04lx) = 0x%08x\n", (unsigned long)(&TIp->fiberSyncDelay) - TIBase, ro.fiberSyncDelay); printf(" GTPStatusA (0x%04lx) = 0x%08x\t", (unsigned long)(&TIp->GTPStatusA) - TIBase, ro.GTPStatusA); printf(" GTPStatusB (0x%04lx) = 0x%08x\n", (unsigned long)(&TIp->GTPStatusB) - TIBase, ro.GTPStatusB); printf(" livetime (0x%04lx) = 0x%08x\t", (unsigned long)(&TIp->livetime) - TIBase, ro.livetime); printf(" busytime (0x%04lx) = 0x%08x\n", (unsigned long)(&TIp->busytime) - TIBase, ro.busytime); printf(" GTPTrgBufLen (0x%04lx) = 0x%08x\t", (unsigned long)(&TIp->GTPtriggerBufferLength) - TIBase, ro.GTPtriggerBufferLength); } printf("\n"); if((!tiMaster) && (tiBlockLevel==0)) { printf(" Block Level not yet received\n"); } else { printf(" Block Level = %d ", tiBlockLevel); if(tiBlockLevel != tiNextBlockLevel) printf("(To be set = %d)\n", tiNextBlockLevel); else printf("\n"); } fibermask = ro.fiber; if(tiMaster) { if(fibermask) { printf(" HFBR enabled (0x%x)= \n",fibermask&0xf); for(ifiber=0; ifiber<8; ifiber++) { if( fibermask & (1<>8, (ro.intsetup&TI_INTSETUP_VECTOR_MASK)); if(ro.vmeControl&TI_VMECONTROL_BERR) printf(" Bus Errors Enabled\n"); else printf(" Bus Errors Disabled\n"); printf(" Blocks ready for readout: %d\n",(ro.blockBuffer&TI_BLOCKBUFFER_BLOCKS_READY_MASK)>>8); if(tiMaster) { printf(" Slave Block Status: %s\n", (ro.busy&TI_BUSY_MONITOR_TRIG_LOST)?"** Waiting for Trigger Ack **":""); /* TI slave block status */ fibermask = tiSlaveMask; for(ifiber=0; ifiber<8; ifiber++) { if( fibermask & (1<>8; } else { nblocksReady = (blockStatus[(ifiber-1)/2] & TI_BLOCKSTATUS_NBLOCKS_READY1)>>16; nblocksNeedAck = (blockStatus[(ifiber-1)/2] & TI_BLOCKSTATUS_NBLOCKS_NEEDACK1)>>24; } printf(" Fiber %d : Blocks ready / need acknowledge: %d / %d\n", ifiber+1,nblocksReady, nblocksNeedAck); } } /* TI master block status */ nblocksReady = (blockStatus[4] & TI_BLOCKSTATUS_NBLOCKS_READY1)>>16; nblocksNeedAck = (blockStatus[4] & TI_BLOCKSTATUS_NBLOCKS_NEEDACK1)>>24; printf(" Loopback : Blocks ready / need acknowledge: %d / %d\n", nblocksReady, nblocksNeedAck); } printf(" Input counter %d\n",ro.inputCounter); printf("--------------------------------------------------------------------------------\n"); printf("\n\n"); } /** * @ingroup SlaveConfig * @brief This routine provides the ability to switch the port that the TI Slave * receives its Clock, SyncReset, and Trigger. * If the TI has already been configured to use this port, nothing is done. * * @param port * - 1 - Port 1 * - 5 - Port 5 * * @return OK if successful, ERROR otherwise * */ int tiSetSlavePort(int port) { if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(tiMaster) { printf("%s: ERROR: TI is not the TI Slave.\n",__FUNCTION__); return ERROR; } if((port!=1) && (port!=5)) { printf("%s: ERROR: Invalid port specified (%d). Must be 1 or 5 for TI Slave.\n", __FUNCTION__,port); return ERROR; } if(port==tiSlaveFiberIn) { printf("%s: INFO: TI Slave already configured to use port %d.\n", __FUNCTION__,port); return OK; } TILOCK; tiSlaveFiberIn=port; TIUNLOCK; if(tiSlaveFiberIn==1) { /* Enable HFBR#1 */ tiEnableFiber(1); /* HFBR#1 Clock Source */ tiSetClockSource(1); /* HFBR#1 Sync Source */ tiSetSyncSource(TI_SYNC_HFBR1); /* HFBR#1 Trigger Source */ tiSetTriggerSource(TI_TRIGGER_HFBR1); } else if(tiSlaveFiberIn==5) { /* Enable HFBR#5 */ tiEnableFiber(5); /* HFBR#5 Clock Source */ tiSetClockSource(5); /* HFBR#5 Sync Source */ tiSetSyncSource(TI_SYNC_HFBR5); /* HFBR#5 Trigger Source */ tiSetTriggerSource(TI_TRIGGER_HFBR5); } taskDelay(2); /* Measure and apply fiber compensation */ FiberMeas(); /* TI IODELAY reset */ TILOCK; vmeWrite32(&TIp->reset,TI_RESET_IODELAY); taskDelay(1); /* TI Sync auto alignment */ if(tiSlaveFiberIn==1) vmeWrite32(&TIp->reset,TI_RESET_AUTOALIGN_HFBR1_SYNC); else vmeWrite32(&TIp->reset,TI_RESET_AUTOALIGN_HFBR5_SYNC); taskDelay(1); /* TI auto fiber delay measurement */ vmeWrite32(&TIp->reset,TI_RESET_MEASURE_LATENCY); taskDelay(1); /* TI auto alignement fiber delay */ vmeWrite32(&TIp->reset,TI_RESET_FIBER_AUTO_ALIGN); taskDelay(1); TIUNLOCK; printf("%s: INFO: TI Slave configured to use port %d.\n", __FUNCTION__,port); return OK; } /** * @ingroup Status * @brief Returns the port of which the TI Slave has been configured (or will be) * * @return * - 1 - Port 1 * - 5 - Port 5 * */ int tiGetSlavePort() { return tiSlaveFiberIn; } /** * @ingroup Status * @brief Print a summary of all fiber port connections to potential TI Slaves * * @param pflag * - 0 - Default output * - 1 - Print Raw Registers * */ void tiSlaveStatus(int pflag) { int iport=0, ibs=0, ifiber=0; unsigned int TIBase; unsigned int hfbr_tiID[8] = {1,2,3,4,5,6,7}; unsigned int master_tiID; unsigned int blockStatus[5]; unsigned int fiber=0, busy=0, trigsrc=0; int nblocksReady=0, nblocksNeedAck=0, slaveCount=0; int blocklevel=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return; } TILOCK; for(iport=0; iport<8; iport++) { hfbr_tiID[iport] = vmeRead32(&TIp->hfbr_tiID[iport]); } master_tiID = vmeRead32(&TIp->master_tiID); fiber = vmeRead32(&TIp->fiber); busy = vmeRead32(&TIp->busy); trigsrc = vmeRead32(&TIp->trigsrc); for(ibs=0; ibs<4; ibs++) { blockStatus[ibs] = vmeRead32(&TIp->blockStatus[ibs]); } blockStatus[4] = vmeRead32(&TIp->adr24); blocklevel = (vmeRead32(&TIp->blocklevel) & TI_BLOCKLEVEL_CURRENT_MASK)>>16; TIUNLOCK; TIBase = (unsigned long)TIp; if(pflag>0) { printf(" Registers (offset):\n"); printf(" TIBase (0x%08x)\n",(unsigned int)(TIBase-tiA24Offset)); printf(" busy (0x%04lx) = 0x%08x\t", (unsigned long)(&TIp->busy) - TIBase, busy); printf(" fiber (0x%04lx) = 0x%08x\n", (unsigned long)(&TIp->fiber) - TIBase, fiber); printf(" hfbr_tiID[0] (0x%04lx) = 0x%08x\t", (unsigned long)(&TIp->hfbr_tiID[0]) - TIBase, hfbr_tiID[0]); printf(" hfbr_tiID[1] (0x%04lx) = 0x%08x\n", (unsigned long)(&TIp->hfbr_tiID[1]) - TIBase, hfbr_tiID[1]); printf(" hfbr_tiID[2] (0x%04lx) = 0x%08x\t", (unsigned long)(&TIp->hfbr_tiID[2]) - TIBase, hfbr_tiID[2]); printf(" hfbr_tiID[3] (0x%04lx) = 0x%08x\n", (unsigned long)(&TIp->hfbr_tiID[3]) - TIBase, hfbr_tiID[3]); printf(" hfbr_tiID[4] (0x%04lx) = 0x%08x\t", (unsigned long)(&TIp->hfbr_tiID[4]) - TIBase, hfbr_tiID[4]); printf(" hfbr_tiID[5] (0x%04lx) = 0x%08x\n", (unsigned long)(&TIp->hfbr_tiID[5]) - TIBase, hfbr_tiID[5]); printf(" hfbr_tiID[6] (0x%04lx) = 0x%08x\t", (unsigned long)(&TIp->hfbr_tiID[6]) - TIBase, hfbr_tiID[6]); printf(" hfbr_tiID[7] (0x%04lx) = 0x%08x\n", (unsigned long)(&TIp->hfbr_tiID[7]) - TIBase, hfbr_tiID[7]); printf(" master_tiID (0x%04lx) = 0x%08x\t", (unsigned long)(&TIp->master_tiID) - TIBase, master_tiID); printf("\n"); } printf("TI-Master Port STATUS Summary\n"); printf(" Block Status\n"); printf("Port ROCID Connected TrigSrcEn Busy Status Ready / NeedAck Blocklevel\n"); printf("--------------------------------------------------------------------------------\n"); /* Master first */ /* Slot and Port number */ printf("L "); /* Port Name */ printf("%5d ", (master_tiID&TI_ID_CRATEID_MASK)>>8); /* Connection Status */ printf("%s %s ", "YES", (trigsrc & TI_TRIGSRC_LOOPBACK)?"ENABLED ":"DISABLED"); /* Busy Status */ printf("%s ", (busy & TI_BUSY_MONITOR_LOOPBACK)?"BUSY":" "); /* Block Status */ nblocksReady = (blockStatus[4] & TI_BLOCKSTATUS_NBLOCKS_READY1)>>16; nblocksNeedAck = (blockStatus[4] & TI_BLOCKSTATUS_NBLOCKS_NEEDACK1)>>24; printf(" %3d / %3d",nblocksReady, nblocksNeedAck); printf(" %3d",blocklevel); printf("\n"); /* Slaves last */ for(iport=1; iport<9; iport++) { /* Only continue of this port has been configured as a slave */ if((tiSlaveMask & (1<<(iport-1)))==0) continue; /* Slot and Port number */ printf("%d ", iport); /* Port Name */ printf("%5d ", (hfbr_tiID[iport-1]&TI_ID_CRATEID_MASK)>>8); /* Connection Status */ printf("%s %s ", (fiber & TI_FIBER_CONNECTED_TI(iport))?"YES":"NO ", (fiber & TI_FIBER_TRIGSRC_ENABLED_TI(iport))?"ENABLED ":"DISABLED"); /* Busy Status */ printf("%s ", (busy & TI_BUSY_MONITOR_FIBER_BUSY(iport))?"BUSY":" "); /* Block Status */ ifiber=iport-1; if( (ifiber % 2) == 0) { nblocksReady = blockStatus[ifiber/2] & TI_BLOCKSTATUS_NBLOCKS_READY0; nblocksNeedAck = (blockStatus[ifiber/2] & TI_BLOCKSTATUS_NBLOCKS_NEEDACK0)>>8; } else { nblocksReady = (blockStatus[(ifiber-1)/2] & TI_BLOCKSTATUS_NBLOCKS_READY1)>>16; nblocksNeedAck = (blockStatus[(ifiber-1)/2] & TI_BLOCKSTATUS_NBLOCKS_NEEDACK1)>>24; } printf(" %3d / %3d",nblocksReady, nblocksNeedAck); printf(" %3d",(hfbr_tiID[iport-1]&TI_ID_BLOCKLEVEL_MASK)>>16); printf("\n"); slaveCount++; } printf("\n"); printf("Total Slaves Added = %d\n",slaveCount); } /** * @ingroup Status * @brief Get the Firmware Version * * @return Firmware Version if successful, ERROR otherwise * */ int tiGetFirmwareVersion() { unsigned int rval=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; /* reset the VME_to_JTAG engine logic */ vmeWrite32(&TIp->reset,TI_RESET_JTAG); /* Reset FPGA JTAG to "reset_idle" state */ vmeWrite32(&TIp->JTAGFPGABase[(0x003C)>>2],0); /* enable the user_code readback */ vmeWrite32(&TIp->JTAGFPGABase[(0x092C)>>2],0x3c8); /* shift in 32-bit to FPGA JTAG */ vmeWrite32(&TIp->JTAGFPGABase[(0x1F1C)>>2],0); /* Readback the firmware version */ rval = vmeRead32(&TIp->JTAGFPGABase[(0x1F1C)>>2]); TIUNLOCK; return rval; } /** * @ingroup Config * @brief Reload the firmware on the FPGA * * @return OK if successful, ERROR otherwise * */ int tiReload() { if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; vmeWrite32(&TIp->reset,TI_RESET_JTAG); vmeWrite32(&TIp->JTAGPROMBase[(0x3c)>>2],0); vmeWrite32(&TIp->JTAGPROMBase[(0xf2c)>>2],0xEE); TIUNLOCK; printf ("%s: \n FPGA Re-Load ! \n",__FUNCTION__); return OK; } /** * @ingroup Status * @brief Get the Module Serial Number * * @param rSN Pointer to string to pass Serial Number * * @return SerialNumber if successful, ERROR otherwise * */ unsigned int tiGetSerialNumber(char **rSN) { unsigned int rval=0; char retSN[10]; memset(retSN,0,sizeof(retSN)); if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; vmeWrite32(&TIp->reset,TI_RESET_JTAG); /* reset */ vmeWrite32(&TIp->JTAGPROMBase[(0x3c)>>2],0); /* Reset_idle */ vmeWrite32(&TIp->JTAGPROMBase[(0xf2c)>>2],0xFD); /* load the UserCode Enable */ vmeWrite32(&TIp->JTAGPROMBase[(0x1f1c)>>2],0); /* shift in 32-bit of data */ rval = vmeRead32(&TIp->JTAGPROMBase[(0x1f1c)>>2]); TIUNLOCK; if(rSN!=NULL) { sprintf(retSN,"TI-%d",rval&0x7ff); strcpy((char *)rSN,retSN); } printf("%s: TI Serial Number is %s (0x%08x)\n", __FUNCTION__,retSN,rval); return rval; } /** * @ingroup MasterConfig * @brief Resync the 250 MHz Clock * * @return OK if successful, ERROR otherwise * */ int tiClockResync() { if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; vmeWrite32(&TIp->syncCommand,TI_SYNCCOMMAND_AD9510_RESYNC); TIUNLOCK; printf ("%s: \n\t AD9510 ReSync ! \n",__FUNCTION__); return OK; } /** * @ingroup Config * @brief Perform a soft reset of the TI * * @return OK if successful, ERROR otherwise * */ int tiReset() { if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; vmeWrite32(&TIp->reset,TI_RESET_SOFT); TIUNLOCK; return OK; } /** * @ingroup Config * @brief Set the crate ID * * @return OK if successful, ERROR otherwise * */ int tiSetCrateID(unsigned int crateID) { if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(crateID>0xff) { printf("%s: ERROR: Invalid crate id (0x%x)\n",__FUNCTION__,crateID); return ERROR; } TILOCK; vmeWrite32(&TIp->boardID, (vmeRead32(&TIp->boardID) & ~TI_BOARDID_CRATEID_MASK) | crateID); tiCrateID = crateID; TIUNLOCK; return OK; } /** * @ingroup Status * @brief Get the crate ID of the selected port * * @param port * - 0 - Self * - 1-8 - Fiber port 1-8 (If Master) * * @return port Crate ID if successful, ERROR otherwise * */ int tiGetCrateID(int port) { int rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if((port<0) || (port>8)) { printf("%s: ERROR: Invalid port (%d)\n", __FUNCTION__,port); } TILOCK; if(port==0) { rval = (vmeRead32(&TIp->master_tiID) & TI_ID_CRATEID_MASK)>>8; } else { rval = (vmeRead32(&TIp->hfbr_tiID[port-1]) & TI_ID_CRATEID_MASK)>>8; } TIUNLOCK; return rval; } /** * @ingroup Status * @brief Get the trigger sources enabled bits of the selected port * * @param port * - 0 - Self * - 1-8 - Fiber port 1-8 (If Master) * * @return bitmask of rigger sources enabled if successful, otherwise ERROR * bitmask * - 0 - P0 * - 1 - Fiber 1 * - 2 - Loopback * - 3 - TRG (FP) * - 4 - VME * - 5 - TS Inputs (FP) * - 6 - TS (rev 2) * - 7 - Internal Pulser * */ int tiGetPortTrigSrcEnabled(int port) { int rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if((port<0) || (port>8)) { printf("%s: ERROR: Invalid port (%d)\n", __FUNCTION__,port); } TILOCK; if(port==0) { rval = (vmeRead32(&TIp->master_tiID) & TI_ID_TRIGSRC_ENABLE_MASK); } else { rval = (vmeRead32(&TIp->hfbr_tiID[port-1]) & TI_ID_TRIGSRC_ENABLE_MASK); } TIUNLOCK; return rval; } /** * @ingroup Status * @brief Get the blocklevel of the TI-Slave on the selected port * @param port * - 1-8 - Fiber port 1-8 * * @return port blocklevel if successful, ERROR otherwise * */ int tiGetSlaveBlocklevel(int port) { int rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if((port<1) || (port>8)) { printf("%s: ERROR: Invalid port (%d)\n", __FUNCTION__,port); } TILOCK; rval = (vmeRead32(&TIp->hfbr_tiID[port-1]) & TI_ID_BLOCKLEVEL_MASK)>>16; TIUNLOCK; return rval; } /** * @ingroup MasterConfig * @brief Set the number of events per block * @param blockLevel Number of events per block * @return OK if successful, ERROR otherwise * */ int tiSetBlockLevel(int blockLevel) { return tiBroadcastNextBlockLevel(blockLevel); } /** * @ingroup MasterConfig * @brief Broadcast the next block level (to be changed at the end of * the next sync event, or during a call to tiSyncReset(1). * * @see tiSyncReset(1) * @param blockLevel block level to broadcats * * @return OK if successful, ERROR otherwise * */ int tiBroadcastNextBlockLevel(int blockLevel) { unsigned int trigger=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if( (blockLevel>TI_BLOCKLEVEL_MASK) || (blockLevel==0) ) { printf("%s: ERROR: Invalid Block Level (%d)\n",__FUNCTION__,blockLevel); return ERROR; } if(!tiMaster) { printf("%s: ERROR: TI is not the TI Master.\n",__FUNCTION__); return ERROR; } TILOCK; trigger = vmeRead32(&TIp->trigsrc); if(!(trigger & TI_TRIGSRC_VME)) /* Turn on the VME trigger, if not enabled */ vmeWrite32(&TIp->trigsrc, TI_TRIGSRC_VME | trigger); vmeWrite32(&TIp->triggerCommand, TI_TRIGGERCOMMAND_SET_BLOCKLEVEL | blockLevel); if(!(trigger & TI_TRIGSRC_VME)) /* Turn off the VME trigger, if it was initially disabled */ vmeWrite32(&TIp->trigsrc, trigger); TIUNLOCK; tiGetNextBlockLevel(); return OK; } /** * @ingroup Status * @brief Get the block level that will be updated on the end of the block readout. * * @return Next Block Level if successful, ERROR otherwise * */ int tiGetNextBlockLevel() { unsigned int reg_bl=0; int bl=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; reg_bl = vmeRead32(&TIp->blocklevel); bl = (reg_bl & TI_BLOCKLEVEL_RECEIVED_MASK)>>24; tiNextBlockLevel = bl; tiBlockLevel = (reg_bl & TI_BLOCKLEVEL_CURRENT_MASK)>>16; TIUNLOCK; return bl; } /** * @ingroup Status * @brief Get the current block level * * @return Next Block Level if successful, ERROR otherwise * */ int tiGetCurrentBlockLevel() { unsigned int reg_bl=0; int bl=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; reg_bl = vmeRead32(&TIp->blocklevel); bl = (reg_bl & TI_BLOCKLEVEL_CURRENT_MASK)>>16; tiBlockLevel = bl; tiNextBlockLevel = (reg_bl & TI_BLOCKLEVEL_RECEIVED_MASK)>>24; TIUNLOCK; /* Change Bus Error block termination, based on blocklevel */ if(tiBlockLevel>2) { tiEnableBusError(); } else { tiDisableBusError(); } return bl; } /** * @ingroup Config * @brief Set TS to instantly change blocklevel when broadcast is received. * * @param enable Option to enable or disable this feature * - 0: Disable * !0: Enable * * @return OK if successful, ERROR otherwise * */ int tiSetInstantBlockLevelChange(int enable) { if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; if(enable) vmeWrite32(&TIp->vmeControl, vmeRead32(&TIp->vmeControl) | TI_VMECONTROL_BLOCKLEVEL_UPDATE); else vmeWrite32(&TIp->vmeControl, vmeRead32(&TIp->vmeControl) & ~TI_VMECONTROL_BLOCKLEVEL_UPDATE); TIUNLOCK; return OK; } /** * @ingroup Status * @brief Get Status of instant blocklevel change when broadcast is received. * * @return 1 if enabled, 0 if disabled , ERROR otherwise * */ int tiGetInstantBlockLevelChange() { int rval=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; rval = (vmeRead32(&TIp->vmeControl) & TI_VMECONTROL_BLOCKLEVEL_UPDATE)>>21; TIUNLOCK; return rval; } /** * @ingroup Config * @brief Set the trigger source * This routine will set a library variable to be set in the TI registers * at a call to tiIntEnable. * * @param trig - integer indicating the trigger source * - 0: P0 * - 1: HFBR#1 * - 2: Front Panel (TRG) * - 3: Front Panel TS Inputs * - 4: TS (rev2) * - 5: Random * - 6-9: TS Partition 1-4 * - 10: HFBR#5 * - 11: Pulser Trig 2 then Trig1 after specified delay * * @return OK if successful, ERROR otherwise * */ int tiSetTriggerSource(int trig) { unsigned int trigenable=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if( (trig>10) || (trig<0) ) { printf("%s: ERROR: Invalid Trigger Source (%d). Must be between 0 and 10.\n", __FUNCTION__,trig); return ERROR; } if(!tiMaster) { /* Setup for TI Slave */ trigenable = TI_TRIGSRC_VME; if((trig>=6) && (trig<=9)) /* TS partition specified */ { if(tiSlaveFiberIn!=1) { printf("%s: WARN: Partition triggers NOT USED on Fiber Port 5.\n", __FUNCTION__); trigenable |= TI_TRIGSRC_HFBR5; } trigenable |= TI_TRIGSRC_HFBR1; switch(trig) { case TI_TRIGGER_PART_1: trigenable |= TI_TRIGSRC_PART_1; break; case TI_TRIGGER_PART_2: trigenable |= TI_TRIGSRC_PART_2; break; case TI_TRIGGER_PART_3: trigenable |= TI_TRIGSRC_PART_3; break; case TI_TRIGGER_PART_4: trigenable |= TI_TRIGSRC_PART_4; break; } } else { if(tiSlaveFiberIn==1) { trigenable |= TI_TRIGSRC_HFBR1; } else if(tiSlaveFiberIn==5) { trigenable |= TI_TRIGSRC_HFBR5; } if( (trig != TI_TRIGGER_HFBR1) || (trig != TI_TRIGGER_HFBR5) ) { printf("%s: WARN: Only valid trigger source for TI Slave is HFBR%d (trig = %d)", __FUNCTION__, tiSlaveFiberIn, (tiSlaveFiberIn==1)?TI_TRIGGER_HFBR1:TI_TRIGGER_HFBR5); printf(" Ignoring specified trig (%d)\n",trig); } } } else { /* Setup for TI Master */ /* Set VME and Loopback by default */ trigenable = TI_TRIGSRC_VME; trigenable |= TI_TRIGSRC_LOOPBACK; switch(trig) { case TI_TRIGGER_P0: trigenable |= TI_TRIGSRC_P0; break; case TI_TRIGGER_HFBR1: trigenable |= TI_TRIGSRC_HFBR1; break; case TI_TRIGGER_HFBR5: trigenable |= TI_TRIGSRC_HFBR5; break; case TI_TRIGGER_FPTRG: trigenable |= TI_TRIGSRC_FPTRG; break; case TI_TRIGGER_TSINPUTS: trigenable |= TI_TRIGSRC_TSINPUTS; break; case TI_TRIGGER_TSREV2: trigenable |= TI_TRIGSRC_TSREV2; break; case TI_TRIGGER_PULSER: trigenable |= TI_TRIGSRC_PULSER; break; case TI_TRIGGER_TRIG21: trigenable |= TI_TRIGSRC_PULSER; trigenable |= TI_TRIGSRC_TRIG21; break; default: printf("%s: ERROR: Invalid Trigger Source (%d) for TI Master\n", __FUNCTION__,trig); return ERROR; } } tiTriggerSource = trigenable; printf("%s: INFO: tiTriggerSource = 0x%x\n",__FUNCTION__,tiTriggerSource); return OK; } /** * @ingroup Config * @brief Set trigger sources with specified trigmask * This routine is for special use when tiSetTriggerSource(...) does * not set all of the trigger sources that is required by the user. * * @param trigmask bits: * - 0: P0 * - 1: HFBR #1 * - 2: TI Master Loopback * - 3: Front Panel (TRG) Input * - 4: VME Trigger * - 5: Front Panel TS Inputs * - 6: TS (rev 2) Input * - 7: Random Trigger * - 8: FP/Ext/GTP * - 9: P2 Busy * - 10: HFBR #5 * - 11: Pulser Trig2 with delayed Trig1 (only compatible with 2 and 7) * * @return OK if successful, ERROR otherwise * */ int tiSetTriggerSourceMask(int trigmask) { if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } /* Check input mask */ if(trigmask>TI_TRIGSRC_SOURCEMASK) { printf("%s: ERROR: Invalid trigger source mask (0x%x).\n", __FUNCTION__,trigmask); return ERROR; } tiTriggerSource = trigmask; return OK; } /** * @ingroup Config * @brief Enable trigger sources * Enable trigger sources set by * tiSetTriggerSource(...) or * tiSetTriggerSourceMask(...) * @sa tiSetTriggerSource * @sa tiSetTriggerSourceMask * * @return OK if successful, ERROR otherwise * */ int tiEnableTriggerSource() { if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(tiTriggerSource==0) { printf("%s: WARN: No Trigger Sources Enabled\n",__FUNCTION__); } TILOCK; vmeWrite32(&TIp->trigsrc, tiTriggerSource); TIUNLOCK; return OK; } /** * @ingroup Config * @brief Disable trigger sources * * @param fflag * - 0: Disable Triggers * - >0: Disable Triggers and generate enough triggers to fill the current block * * @return OK if successful, ERROR otherwise * */ int tiDisableTriggerSource(int fflag) { int regset=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; if(tiMaster) regset = TI_TRIGSRC_LOOPBACK; vmeWrite32(&TIp->trigsrc,regset); TIUNLOCK; if(fflag && tiMaster) { tiFillToEndBlock(); } return OK; } /** * @ingroup Config * @brief Set the Sync source mask * * @param sync - MASK indicating the sync source * bit: description * - 0: P0 * - 1: HFBR1 * - 2: HFBR5 * - 3: FP * - 4: LOOPBACK * * @return OK if successful, ERROR otherwise * */ int tiSetSyncSource(unsigned int sync) { if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(sync>TI_SYNC_SOURCEMASK) { printf("%s: ERROR: Invalid Sync Source Mask (%d).\n", __FUNCTION__,sync); return ERROR; } TILOCK; vmeWrite32(&TIp->reset, TI_RESET_AUTOALIGN_HFBR1_SYNC | TI_RESET_AUTOALIGN_HFBR5_SYNC); taskDelay(2); vmeWrite32(&TIp->sync,sync); TIUNLOCK; return OK; } /** * @ingroup Config * @brief Set the event format * * @param format - integer number indicating the event format * - 0: 32 bit event number only * - 1: 32 bit event number + 32 bit timestamp * - 2: 32 bit event number + higher 16 bits of timestamp + higher 16 bits of eventnumber * - 3: 32 bit event number + 32 bit timestamp * + higher 16 bits of timestamp + higher 16 bits of eventnumber * * @return OK if successful, ERROR otherwise * */ int tiSetEventFormat(int format) { unsigned int formatset=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if( (format>3) || (format<0) ) { printf("%s: ERROR: Invalid Event Format (%d). Must be between 0 and 3.\n", __FUNCTION__,format); return ERROR; } TILOCK; formatset = vmeRead32(&TIp->dataFormat) & ~(TI_DATAFORMAT_TIMING_WORD | TI_DATAFORMAT_HIGHERBITS_WORD); switch(format) { case 0: break; case 1: formatset |= TI_DATAFORMAT_TIMING_WORD; break; case 2: formatset |= TI_DATAFORMAT_HIGHERBITS_WORD; break; case 3: formatset |= (TI_DATAFORMAT_TIMING_WORD | TI_DATAFORMAT_HIGHERBITS_WORD); break; } vmeWrite32(&TIp->dataFormat,formatset); TIUNLOCK; return OK; } /** * @ingroup Config * @brief Set whether or not the latched pattern of FP Inputs in block readout * * @param enable * - 0: Disable * - >0: Enable * * @return OK if successful, otherwise ERROR * */ int tiSetFPInputReadout(int enable) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; if(enable) vmeWrite32(&TIp->dataFormat, vmeRead32(&TIp->dataFormat) | TI_DATAFORMAT_FPINPUT_READOUT); else vmeWrite32(&TIp->dataFormat, vmeRead32(&TIp->dataFormat) & ~TI_DATAFORMAT_FPINPUT_READOUT); TIUNLOCK; return OK; } /** * @ingroup MasterConfig * @brief Set and enable the "software" trigger * * @param trigger trigger type 1 or 2 (playback trigger) * @param nevents integer number of events to trigger * @param period_inc period multiplier, depends on range (0-0x7FFF) * @param range * - 0: small period range (min: 120ns, increments of 120ns) * - 1: large period range (min: 120ns, increments of 245.7us) * * @return OK if successful, ERROR otherwise * */ int tiSoftTrig(int trigger, unsigned int nevents, unsigned int period_inc, int range) { unsigned int periodMax=(TI_FIXEDPULSER1_PERIOD_MASK>>16); unsigned int reg=0; int time=0; if(TIp==NULL) { logMsg("\ntiSoftTrig: ERROR: TI not initialized\n",1,2,3,4,5,6); return ERROR; } if(trigger!=1 && trigger!=2) { logMsg("\ntiSoftTrig: ERROR: Invalid trigger type %d\n",trigger,2,3,4,5,6); return ERROR; } if(nevents>TI_FIXEDPULSER1_NTRIGGERS_MASK) { logMsg("\ntiSoftTrig: ERROR: nevents (%d) must be less than %d\n",nevents, TI_FIXEDPULSER1_NTRIGGERS_MASK,3,4,5,6); return ERROR; } if(period_inc>periodMax) { logMsg("\ntiSoftTrig: ERROR: period_inc (%d) must be less than %d ns\n", period_inc,periodMax,3,4,5,6); return ERROR; } if( (range!=0) && (range!=1) ) { logMsg("\ntiSoftTrig: ERROR: range must be 0 or 1\n", periodMax,2,3,4,5,6); return ERROR; } if(range==0) time = 120+120*period_inc; if(range==1) time = 120+120*period_inc*2048; /* logMsg("\ntiSoftTrig: INFO: Setting software trigger for %d nevents with period of %d\n", */ /* nevents,time,3,4,5,6); */ reg = (range<<31)| (period_inc<<16) | (nevents); TILOCK; if(trigger==1) { vmeWrite32(&TIp->fixedPulser1, reg); } else if(trigger==2) { vmeWrite32(&TIp->fixedPulser2, reg); } TIUNLOCK; return OK; } /** * @ingroup MasterConfig * @brief Set the parameters of the random internal trigger * * @param trigger - Trigger Selection * - 1: trig1 * - 2: trig2 * @param setting - frequency prescale from 500MHz * * @sa tiDisableRandomTrigger * @return OK if successful, ERROR otherwise. * */ int tiSetRandomTrigger(int trigger, int setting) { double rate; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(trigger!=1 && trigger!=2) { logMsg("\ntiSetRandomTrigger: ERROR: Invalid trigger type %d\n",trigger,2,3,4,5,6); return ERROR; } if(setting>TI_RANDOMPULSER_TRIG1_RATE_MASK) { printf("%s: ERROR: setting (0x%x) must be less than 0x%x\n", __FUNCTION__,setting,TI_RANDOMPULSER_TRIG1_RATE_MASK); return ERROR; } if(setting>0) rate = ((double)500000) / ((double) (2<<(setting-1))); else rate = ((double)500000); printf("%s: Enabling random trigger (trig%d) at rate (kHz) = %.2f\n", __FUNCTION__,trigger,rate); TILOCK; if(trigger==1) vmeWrite32(&TIp->randomPulser, setting | (setting<<4) | TI_RANDOMPULSER_TRIG1_ENABLE); else if (trigger==2) vmeWrite32(&TIp->randomPulser, (setting | (setting<<4))<<8 | TI_RANDOMPULSER_TRIG2_ENABLE ); TIUNLOCK; return OK; } /** * @ingroup MasterConfig * @brief Disable random trigger generation * @sa tiSetRandomTrigger * @return OK if successful, ERROR otherwise. */ int tiDisableRandomTrigger() { if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; vmeWrite32(&TIp->randomPulser,0); TIUNLOCK; return OK; } /** * @ingroup Readout * @brief Read a block of events from the TI * * @param data - local memory address to place data * @param nwrds - Max number of words to transfer * @param rflag - Readout Flag * - 0 - programmed I/O from the specified board * - 1 - DMA transfer using Universe/Tempe DMA Engine * (DMA VME transfer Mode must be setup prior) * * @return Number of words transferred to data if successful, ERROR otherwise * */ int tiReadBlock(volatile unsigned int *data, int nwrds, int rflag) { int ii, dummy=0; int dCnt, retVal, xferCount; volatile unsigned int *laddr; unsigned int vmeAdr, val; if(TIp==NULL) { logMsg("\ntiReadBlock: ERROR: TI not initialized\n",1,2,3,4,5,6); return ERROR; } if(TIpd==NULL) { logMsg("\ntiReadBlock: ERROR: TI A32 not initialized\n",1,2,3,4,5,6); return ERROR; } if(data==NULL) { logMsg("\ntiReadBlock: ERROR: Invalid Destination address\n",0,0,0,0,0,0); return(ERROR); } TILOCK; if(rflag >= 1) { /* Block transfer */ if(tiBusError==0) { logMsg("tiReadBlock: WARN: Bus Error Block Termination was disabled. Re-enabling\n", 1,2,3,4,5,6); TIUNLOCK; tiEnableBusError(); TILOCK; } /* Assume that the DMA programming is already setup. Don't Bother checking if there is valid data - that should be done prior to calling the read routine */ /* Check for 8 byte boundary for address - insert dummy word (Slot 0 FADC Dummy DATA)*/ if((unsigned long) (data)&0x7) { #ifdef VXWORKS *data = (TI_DATA_TYPE_DEFINE_MASK) | (TI_FILLER_WORD_TYPE) | (tiSlotNumber<<22); #else *data = LSWAP((TI_DATA_TYPE_DEFINE_MASK) | (TI_FILLER_WORD_TYPE) | (tiSlotNumber<<22)); #endif dummy = 1; laddr = (data + 1); } else { dummy = 0; laddr = data; } vmeAdr = (unsigned long)TIpd - tiA32Offset; #ifdef VXWORKS retVal = sysVmeDmaSend((UINT32)laddr, vmeAdr, (nwrds<<2), 0); #else retVal = vmeDmaSend((unsigned long)laddr, vmeAdr, (nwrds<<2)); #endif if(retVal != 0) { logMsg("\ntiReadBlock: ERROR in DMA transfer Initialization 0x%x\n",retVal,0,0,0,0,0); TIUNLOCK; return(retVal); } /* Wait until Done or Error */ #ifdef VXWORKS retVal = sysVmeDmaDone(10000,1); #else retVal = vmeDmaDone(); #endif if(retVal > 0) { #ifdef VXWORKS xferCount = (nwrds - (retVal>>2) + dummy); /* Number of longwords transfered */ #else xferCount = ((retVal>>2) + dummy); /* Number of longwords transfered */ #endif TIUNLOCK; return(xferCount); } else if (retVal == 0) { #ifdef VXWORKS logMsg("\ntiReadBlock: WARN: DMA transfer terminated by word count 0x%x\n", nwrds,0,0,0,0,0); #else logMsg("\ntiReadBlock: WARN: DMA transfer returned zero word count 0x%x\n", nwrds,0,0,0,0,0,0); #endif TIUNLOCK; return(nwrds); } else { /* Error in DMA */ #ifdef VXWORKS logMsg("\ntiReadBlock: ERROR: sysVmeDmaDone returned an Error\n", 0,0,0,0,0,0); #else logMsg("\ntiReadBlock: ERROR: vmeDmaDone returned an Error\n", 0,0,0,0,0,0); #endif TIUNLOCK; return(retVal>>2); } } else { /* Programmed IO */ if(tiBusError==1) { logMsg("tiReadBlock: WARN: Bus Error Block Termination was enabled. Disabling\n", 1,2,3,4,5,6); TIUNLOCK; tiDisableBusError(); TILOCK; } dCnt = 0; ii=0; while(ii2) { /* Use DMA */ rflag = 1; } else { /* Use programmed I/O (Single cycle reads) */ rflag = 0; } /* Obtain the trigger bank by just making a call the tiReadBlock */ rval = tiReadBlock(data, nwrds, rflag); if(rval < 0) { /* Error occurred */ logMsg("tiReadTriggerBlock: ERROR: tiReadBlock returned ERROR\n", 1,2,3,4,5,6); return ERROR; } else if (rval == 0) { /* No data returned */ logMsg("tiReadTriggerBlock: WARN: No data available\n", 1,2,3,4,5,6); return 0; } /* Work down to find index of block header */ while(iword=0) { word = data[iword]; #ifndef VXWORKS word = LSWAP(word); #endif if(word & TI_DATA_TYPE_DEFINE_MASK) { if(((word & TI_WORD_TYPE_MASK)) == TI_BLOCK_TRAILER_WORD_TYPE) { #ifdef CDEBUG printf("%s: block trailer? 0x%08x\n", __FUNCTION__,word); #endif iblktrl = iword; break; } } iword--; } /* Check if the index is valid */ if(iblktrl == -1) { logMsg("tiReadTriggerBlock: ERROR: Failed to find TI Block Trailer\n", 1,2,3,4,5,6); return ERROR; } /* Get the block trailer, and check the number of words contained in it */ word = data[iblktrl]; #ifndef VXWORKS word = LSWAP(word); #endif if((iblktrl - iblkhead + 1) != (word & 0x3fffff)) { logMsg("tiReadTriggerBlock: Number of words inconsistent (index count = %d, block trailer count = %d\n", (iblktrl - iblkhead + 1), word & 0x3fffff,3,4,5,6); return ERROR; } /* Modify the total words returned */ rval = iblktrl - iblkhead; /* Write in the Trigger Bank Length */ #ifdef VXWORKS data[iblkhead] = rval-1; #else data[iblkhead] = LSWAP(rval-1); #endif if(tiSwapTriggerBlock==1) { for(iword=iblkhead; iword>16 != 0xFF10) || ((data[iword] & 0x0000FF00)>>8 != 0x20) ) { rval = ERROR; printf("%4d: %08X - **** INVALID TRIGGER BANK HEADER ****\n", iword, data[iword]); iword++; while(iwordblen) { rval = ERROR; printf("----: **** ERROR: Data continues past Trigger Bank Length (%d) ****\n",blen); } printf("%4d: %08X - **** REST OF DATA ****\n", iword, data[iword]); iword++; } } else { if(iword>blen) { rval = ERROR; printf("----: **** ERROR: Data continues past Trigger Bank Length (%d) ****\n",blen); } blevel = data[iword] & 0xFF; printf("%4d: %08X - TRIGGER BANK HEADER - type = %d blocklevel = %d\n", iword, data[iword], (data[iword] & 0x000F0000)>>16, blevel); iword++; for(iev=0; ievblen) { rval = ERROR; printf("----: **** ERROR: Data continues past Trigger Bank Length (%d) ****\n",blen); } if((data[iword] & 0x00FF0000)>>16!=0x01) { rval = ERROR; printf("%4d: %08x - **** INVALID EVENT HEADER ****\n", iword, data[iword]); iword++; while(iwordblen) { rval = ERROR; printf("----: **** ERROR: Data continues past Trigger Bank Length (%d) ****\n",blen); } evlen = data[iword] & 0x0000FFFF; printf("%4d: %08x - EVENT HEADER - trigtype = %d len = %d\n", iword, data[iword], (data[iword] & 0xFF000000)>>24, evlen); iword++; if(iword>blen) { rval = ERROR; printf("----: **** ERROR: Data continues past Trigger Bank Length (%d) ****\n",blen); } printf("%4d: %08x - EVENT NUMBER - evnum = %d\n", iword, data[iword], data[iword]); iword++; for(ievword=1; ievwordblen) { rval = ERROR; printf("----: **** ERROR: Data continues past Trigger Bank Length (%d) ****\n",blen); } printf("%4d: %08X - EVENT DATA\n", iword, data[iword]); iword++; } } } } printf("--------------------------------------------------------------------------------\n"); return rval; } /** * @ingroup Config * @brief Enable Fiber transceiver * * Note: All Fiber are enabled by default * (no harm, except for 1-2W power usage) * * @sa tiDisableFiber * @param fiber: integer indicative of the transceiver to enable * * * @return OK if successful, ERROR otherwise. * */ int tiEnableFiber(unsigned int fiber) { unsigned int sval; unsigned int fiberbit; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if((fiber<1) | (fiber>8)) { printf("%s: ERROR: Invalid value for fiber (%d)\n", __FUNCTION__,fiber); return ERROR; } fiberbit = (1<<(fiber-1)); TILOCK; sval = vmeRead32(&TIp->fiber); vmeWrite32(&TIp->fiber, sval | fiberbit ); TIUNLOCK; return OK; } /** * @ingroup Config * @brief Disnable Fiber transceiver * * @sa tiEnableFiber * * @param fiber: integer indicative of the transceiver to disable * * * @return OK if successful, ERROR otherwise. * */ int tiDisableFiber(unsigned int fiber) { unsigned int rval; unsigned int fiberbit; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if((fiber<1) | (fiber>8)) { printf("%s: ERROR: Invalid value for fiber (%d)\n", __FUNCTION__,fiber); return ERROR; } fiberbit = (1<<(fiber-1)); TILOCK; rval = vmeRead32(&TIp->fiber); vmeWrite32(&TIp->fiber, rval & ~fiberbit ); TIUNLOCK; return rval; } /** * @ingroup Config * @brief Set the busy source with a given sourcemask sourcemask bits: * * @param sourcemask * - 0: SWA * - 1: SWB * - 2: P2 * - 3: FP-FTDC * - 4: FP-FADC * - 5: FP * - 6: Unused * - 7: Loopack * - 8-15: Fiber 1-8 * * @param rFlag - decision to reset the global source flags * - 0: Keep prior busy source settings and set new "sourcemask" * - 1: Reset, using only that specified with "sourcemask" * @return OK if successful, ERROR otherwise. */ int tiSetBusySource(unsigned int sourcemask, int rFlag) { unsigned int busybits=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(sourcemask>TI_BUSY_SOURCEMASK) { printf("%s: ERROR: Invalid value for sourcemask (0x%x)\n", __FUNCTION__, sourcemask); return ERROR; } TILOCK; if(rFlag) { /* Read in the previous value , resetting previous BUSYs*/ busybits = vmeRead32(&TIp->busy) & ~(TI_BUSY_SOURCEMASK); } else { /* Read in the previous value , keeping previous BUSYs*/ busybits = vmeRead32(&TIp->busy); } busybits |= sourcemask; vmeWrite32(&TIp->busy, busybits); TIUNLOCK; return OK; } /** * @ingroup MasterConfig * @brief Set the the trigger lock mode. * * @param enable Enable flag * 0: Disable * !0: Enable * * @return OK if successful, ERROR otherwise. */ int tiSetTriggerLock(int enable) { if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(!tiMaster) { printf("%s: ERROR: TI is not the TI Master.\n",__FUNCTION__); return ERROR; } TILOCK; if(enable) vmeWrite32(&TIp->busy, vmeRead32(&TIp->busy) | TI_BUSY_TRIGGER_LOCK); else vmeWrite32(&TIp->busy, vmeRead32(&TIp->busy) & ~TI_BUSY_TRIGGER_LOCK); TIUNLOCK; return OK; } /** * @ingroup MasterStatus * @brief Get the current setting of the trigger lock mode. * * @return 1 if enabled, 0 if disabled, ERROR otherwise. */ int tiGetTriggerLock() { int rval=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(!tiMaster) { printf("%s: ERROR: TI is not the TI Master.\n",__FUNCTION__); return ERROR; } TILOCK; rval = (vmeRead32(&TIp->busy) & TI_BUSY_TRIGGER_LOCK)>>6; TIUNLOCK; return rval; } /** * @ingroup Config * @brief Enable Bus Errors to terminate Block Reads * @sa tiDisableBusError * @return OK if successful, otherwise ERROR */ void tiEnableBusError() { if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return; } TILOCK; vmeWrite32(&TIp->vmeControl, vmeRead32(&TIp->vmeControl) | (TI_VMECONTROL_BERR) ); tiBusError=1; TIUNLOCK; } /** * @ingroup Config * @brief Disable Bus Errors to terminate Block Reads * @sa tiEnableBusError * @return OK if successful, otherwise ERROR */ void tiDisableBusError() { if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return; } TILOCK; vmeWrite32(&TIp->vmeControl, vmeRead32(&TIp->vmeControl) & ~(TI_VMECONTROL_BERR) ); tiBusError=0; TIUNLOCK; } /** * @ingroup Deprec * @brief Routine to return the VME slot, provided the VXS payload port * @param payloadport Payload port * @return Vme Slot */ int tiPayloadPort2VMESlot(int payloadport) { int rval=0; int islot; if(payloadport<1 || payloadport>18) { printf("%s: ERROR: Invalid payloadport %d\n", __FUNCTION__,payloadport); return ERROR; } for(islot=1;islotMAX_VME_SLOTS) { printf("%s: ERROR: Invalid VME slot %d\n", __FUNCTION__,vmeslot); return ERROR; } rval = (int)PayloadPort[vmeslot]; if(rval==0) { printf("%s: ERROR: Unable to find Payload Port from VME Slot %d\n", __FUNCTION__,vmeslot); rval=ERROR; } return rval; } /** * @ingroup Deprec * @brief Routine to return the VXS Payload Port Mask, provided the VME Slot Mask * @param vmemask Vme Slot Mask * @param Payload port mask */ unsigned int tiVMESlotMask2PayloadPortMask(unsigned int vmemask) { int islot=0; unsigned int ppmask=0; for(islot=0; islot<22; islot++) { if(vmemask & (1<0xffff) { printf("%s: ERROR: Invalid prescale (%d). Must be between 0 and 65535.", __FUNCTION__,prescale); return ERROR; } TILOCK; vmeWrite32(&TIp->trig1Prescale, prescale); TIUNLOCK; return OK; } /** * @ingroup Status * @brief Get the current prescale factor * @return Current prescale factor, otherwise ERROR. */ int tiGetPrescale() { int rval; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; rval = vmeRead32(&TIp->trig1Prescale); TIUNLOCK; return rval; } /** * @ingroup MasterConfig * @brief Set the prescale factor for the selected input * * @param input Selected trigger input (1-6) * @param prescale Factor for prescale. * Max {prescale} available is 65535 * * @return OK if successful, otherwise ERROR. */ int tiSetInputPrescale(int input, int prescale) { unsigned int oldval=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if((prescale<0) || (prescale>0xf)) { printf("%s: ERROR: Invalid prescale (%d). Must be between 0 and 15.", __FUNCTION__,prescale); return ERROR; } if((input<1) || (input>6)) { { printf("%s: ERROR: Invalid input (%d).", __FUNCTION__,input); return ERROR; } } TILOCK; oldval = vmeRead32(&TIp->inputPrescale) & ~(TI_INPUTPRESCALE_FP_MASK(input)); vmeWrite32(&TIp->inputPrescale, oldval | (prescale<<(4*(input-1) )) ); TIUNLOCK; return OK; } /** * @ingroup Status * @brief Get the current prescale factor for the selected input * @param input Selected trigger input (1-6) * @return Current prescale factor, otherwise ERROR. */ int tiGetInputPrescale(int input) { int rval; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; rval = vmeRead32(&TIp->inputPrescale) & TI_INPUTPRESCALE_FP_MASK(input); rval = rval>>(4*(input-1)); TIUNLOCK; return rval; } /** * @ingroup Config * @brief Set the characteristics of a specified trigger * * @param trigger * - 1: set for trigger 1 * - 2: set for trigger 2 (playback trigger) * @param delay delay in units of delay_step * @param width pulse width in units of 4ns * @param delay_step step size of the delay * - 0: 16ns * !0: 64ns (with an offset of ~4.1 us) * * @return OK if successful, otherwise ERROR */ int tiSetTriggerPulse(int trigger, int delay, int width, int delay_step) { unsigned int rval=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(trigger<1 || trigger>2) { printf("%s: ERROR: Invalid trigger (%d). Must be 1 or 2.\n", __FUNCTION__,trigger); return ERROR; } if(delay<0 || delay>0x7F) { printf("%s: ERROR: Invalid delay (%d). Must be less than %d\n", __FUNCTION__,delay,TI_TRIGDELAY_TRIG1_DELAY_MASK); return ERROR; } if(width<0 || width>TI_TRIGDELAY_TRIG1_WIDTH_MASK) { printf("%s: ERROR: Invalid width (%d). Must be less than %d\n", __FUNCTION__,width,TI_TRIGDELAY_TRIG1_WIDTH_MASK); } TILOCK; if(trigger==1) { rval = vmeRead32(&TIp->trigDelay) & ~(TI_TRIGDELAY_TRIG1_DELAY_MASK | TI_TRIGDELAY_TRIG1_WIDTH_MASK) ; rval |= ( (delay) | (width<<8) ); if(delay_step) rval |= TI_TRIGDELAY_TRIG1_64NS_STEP; vmeWrite32(&TIp->trigDelay, rval); } if(trigger==2) { rval = vmeRead32(&TIp->trigDelay) & ~(TI_TRIGDELAY_TRIG2_DELAY_MASK | TI_TRIGDELAY_TRIG2_WIDTH_MASK) ; rval |= ( (delay<<16) | (width<<24) ); if(delay_step) rval |= TI_TRIGDELAY_TRIG2_64NS_STEP; vmeWrite32(&TIp->trigDelay, rval); } TIUNLOCK; return OK; } /** * @ingroup Config * @brief Set the width of the prompt trigger from OT#2 * * @param width Output width will be set to (width + 2) * 4ns * * This routine is only functional for Firmware type=2 (modTI) * * @return OK if successful, otherwise ERROR */ int tiSetPromptTriggerWidth(int width) { if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if((width<0) || (width>TI_PROMPT_TRIG_WIDTH_MASK)) { printf("%s: ERROR: Invalid prompt trigger width (%d)\n", __FUNCTION__,width); return ERROR; } TILOCK; vmeWrite32(&TIp->eventNumber_hi, width); TIUNLOCK; return OK; } /** * @ingroup Status * @brief Get the width of the prompt trigger from OT#2 * * This routine is only functional for Firmware type=2 (modTI) * * @return Output width set to (return value + 2) * 4ns, if successful. Otherwise ERROR */ int tiGetPromptTriggerWidth() { unsigned int rval=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; rval = vmeRead32(&TIp->eventNumber_hi) & TI_PROMPT_TRIG_WIDTH_MASK; TIUNLOCK; return OK; } /** * @ingroup Config * @brief Set the delay time and width of the Sync signal * * @param delay the delay (latency) set in units of 4ns. * @param width the width set in units of 4ns. * @param twidth if this is non-zero, set width in units of 32ns. * */ void tiSetSyncDelayWidth(unsigned int delay, unsigned int width, int widthstep) { int twidth=0, tdelay=0; if(TIp == NULL) { printf("%s: ERROR: TS not initialized\n",__FUNCTION__); return; } if(delay>TI_SYNCDELAY_MASK) { printf("%s: ERROR: Invalid delay (%d)\n",__FUNCTION__,delay); return; } if(width>TI_SYNCWIDTH_MASK) { printf("%s: WARN: Invalid width (%d).\n",__FUNCTION__,width); return; } if(widthstep) width |= TI_SYNCWIDTH_LONGWIDTH_ENABLE; tdelay = delay*4; if(widthstep) twidth = (width&TI_SYNCWIDTH_MASK)*32; else twidth = width*4; printf("%s: Setting Sync delay = %d (ns) width = %d (ns)\n", __FUNCTION__,tdelay,twidth); TILOCK; vmeWrite32(&TIp->syncDelay,delay); vmeWrite32(&TIp->syncWidth,width); TIUNLOCK; } /** * @ingroup MasterConfig * @brief Reset the trigger link. */ void tiTrigLinkReset() { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return; } TILOCK; vmeWrite32(&TIp->syncCommand,TI_SYNCCOMMAND_TRIGGERLINK_DISABLE); taskDelay(1); vmeWrite32(&TIp->syncCommand,TI_SYNCCOMMAND_TRIGGERLINK_DISABLE); taskDelay(1); vmeWrite32(&TIp->syncCommand,TI_SYNCCOMMAND_TRIGGERLINK_ENABLE); taskDelay(1); TIUNLOCK; printf ("%s: Trigger Data Link was reset.\n",__FUNCTION__); } /** * @ingroup MasterConfig * @brief Set type of SyncReset to send to TI Slaves * * @param type Sync Reset Type * - 0: User programmed width in each TI * - !0: Fixed 4 microsecond width in each TI * * @return OK if successful, otherwise ERROR */ int tiSetSyncResetType(int type) { if(type) tiSyncResetType=TI_SYNCCOMMAND_SYNCRESET_4US; else tiSyncResetType=TI_SYNCCOMMAND_SYNCRESET; return OK; } /** * @ingroup MasterConfig * @brief Generate a Sync Reset signal. This signal is sent to the loopback and * all configured TI Slaves. * * @param blflag Option to change block level, after SyncReset issued * - 0: Do not change block level * - >0: Broadcast block level to all connected slaves (including self) * BlockLevel broadcasted will be set to library value * (Set with tiSetBlockLevel) * */ void tiSyncReset(int blflag) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return; } TILOCK; vmeWrite32(&TIp->syncCommand,tiSyncResetType); taskDelay(1); vmeWrite32(&TIp->syncCommand,TI_SYNCCOMMAND_RESET_EVNUM); taskDelay(1); TIUNLOCK; if(blflag) /* Set the block level from "Next" to Current */ { printf("%s: INFO: Setting Block Level to %d\n", __FUNCTION__,tiNextBlockLevel); tiBroadcastNextBlockLevel(tiNextBlockLevel); } } /** * @ingroup MasterConfig * @brief Generate a Sync Reset Resync signal. This signal is sent to the loopback and * all configured TI Slaves. This type of Sync Reset will NOT reset * event numbers * */ void tiSyncResetResync() { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return; } TILOCK; vmeWrite32(&TIp->syncCommand,tiSyncResetType); TIUNLOCK; } /** * @ingroup MasterConfig * @brief Generate a Clock Reset signal. This signal is sent to the loopback and * all configured TI Slaves. * */ void tiClockReset() { unsigned int old_syncsrc=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return; } if(tiMaster!=1) { printf("%s: ERROR: TI is not the Master. No Clock Reset.\n", __FUNCTION__); return; } TILOCK; /* Send a clock reset */ vmeWrite32(&TIp->syncCommand,TI_SYNCCOMMAND_CLK250_RESYNC); taskDelay(2); /* Store the old sync source */ old_syncsrc = vmeRead32(&TIp->sync) & TI_SYNC_SOURCEMASK; /* Disable sync source */ vmeWrite32(&TIp->sync, 0); taskDelay(2); /* Send another clock reset */ vmeWrite32(&TIp->syncCommand,TI_SYNCCOMMAND_CLK250_RESYNC); taskDelay(2); /* Re-enable the sync source */ vmeWrite32(&TIp->sync, old_syncsrc); TIUNLOCK; } /** * @ingroup Config * @brief Routine to set the A32 Base * * @return OK if successful, otherwise ERROR */ int tiSetAdr32(unsigned int a32base) { unsigned long laddr=0; int res=0,a32Enabled=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(a32base<0x00800000) { printf("%s: ERROR: a32base out of range (0x%08x)\n", __FUNCTION__,a32base); return ERROR; } TILOCK; vmeWrite32(&TIp->adr32, (a32base & TI_ADR32_BASE_MASK) ); vmeWrite32(&TIp->vmeControl, vmeRead32(&TIp->vmeControl) | TI_VMECONTROL_A32); a32Enabled = vmeRead32(&TIp->vmeControl)&(TI_VMECONTROL_A32); if(!a32Enabled) { printf("%s: ERROR: Failed to enable A32 Address\n",__FUNCTION__); TIUNLOCK; return ERROR; } #ifdef VXWORKS res = sysBusToLocalAdrs(0x09,(char *)a32base,(char **)&laddr); if (res != 0) { printf("%s: ERROR in sysBusToLocalAdrs(0x09,0x%x,&laddr) \n", __FUNCTION__,a32base); TIUNLOCK; return(ERROR); } #else res = vmeBusToLocalAdrs(0x09,(char *)(unsigned long)a32base,(char **)&laddr); if (res != 0) { printf("%s: ERROR in vmeBusToLocalAdrs(0x09,0x%x,&laddr) \n", __FUNCTION__,a32base); TIUNLOCK; return(ERROR); } #endif tiA32Base = a32base; tiA32Offset = laddr - tiA32Base; TIpd = (unsigned int *)(laddr); /* Set a pointer to the FIFO */ TIUNLOCK; printf("%s: A32 Base address set to 0x%08x\n", __FUNCTION__,tiA32Base); return OK; } /** * @ingroup Config * @brief Disable A32 * * @return OK if successful, otherwise ERROR */ int tiDisableA32() { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; vmeWrite32(&TIp->adr32,0x0); vmeWrite32(&TIp->vmeControl, vmeRead32(&TIp->vmeControl) & ~TI_VMECONTROL_A32); TIUNLOCK; return OK; } /** * @ingroup Config * @brief Reset the L1A counter, as incremented by the TI. * * @return OK if successful, otherwise ERROR */ int tiResetEventCounter() { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; vmeWrite32(&TIp->reset, TI_RESET_SCALERS_RESET); TIUNLOCK; return OK; } /** * @ingroup Status * @brief Returns the event counter (48 bit) * * @return Number of accepted events if successful, otherwise ERROR */ unsigned long long int tiGetEventCounter() { unsigned long long int rval=0; unsigned int lo=0, hi=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; lo = vmeRead32(&TIp->eventNumber_lo); hi = (vmeRead32(&TIp->eventNumber_hi) & TI_EVENTNUMBER_HI_MASK)>>16; rval = lo | ((unsigned long long)hi<<32); TIUNLOCK; return rval; } /** * @ingroup MasterConfig * @brief Set the block number at which triggers will be disabled automatically * * @return OK if successful, otherwise ERROR */ int tiSetBlockLimit(unsigned int limit) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; vmeWrite32(&TIp->blocklimit,limit); TIUNLOCK; return OK; } /** * @ingroup Status * @brief Returns the value that is currently programmed as the block limit * * @return Current Block Limit if successful, otherwise ERROR */ unsigned int tiGetBlockLimit() { unsigned int rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; rval = vmeRead32(&TIp->blocklimit); TIUNLOCK; return rval; } /** * @ingroup Status * @brief Get the current status of the block limit * * @return 1 if block limit has been reached, 0 if not, otherwise ERROR; * */ int tiGetBlockLimitStatus() { unsigned int reg=0, rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; reg = vmeRead32(&TIp->blockBuffer) & TI_BLOCKBUFFER_BUSY_ON_BLOCKLIMIT; if(reg) rval = 1; else rval = 0; TIUNLOCK; return rval; } /** * @ingroup Readout * @brief Returns the number of Blocks available for readout * * @return Number of blocks available for readout if successful, otherwise ERROR * */ unsigned int tiBReady() { unsigned int blockBuffer=0, readyInt=0, rval=0; if(TIp == NULL) { logMsg("tiBReady: ERROR: TI not initialized\n",1,2,3,4,5,6); return 0; } TILOCK; blockBuffer = vmeRead32(&TIp->blockBuffer); rval = (blockBuffer&TI_BLOCKBUFFER_BLOCKS_READY_MASK)>>8; readyInt = (blockBuffer&TI_BLOCKBUFFER_BREADY_INT_MASK)>>24; tiSyncEventReceived = (blockBuffer&TI_BLOCKBUFFER_SYNCEVENT)>>31; tiNReadoutEvents = (blockBuffer&TI_BLOCKBUFFER_RO_NEVENTS_MASK)>>24; if( (readyInt==1) && (tiSyncEventReceived) ) tiSyncEventFlag = 1; else tiSyncEventFlag = 0; TIUNLOCK; return rval; } /** * @ingroup Readout * @brief Return the value of the Synchronization flag, obtained from tiBReady. * i.e. Return the value of the SyncFlag for the current readout block. * * @sa tiBReady * @return * - 1: if current readout block contains a Sync Event. * - 0: Otherwise * */ int tiGetSyncEventFlag() { int rval=0; TILOCK; rval = tiSyncEventFlag; TIUNLOCK; return rval; } /** * @ingroup Readout * @brief Return the value of whether or not the sync event has been received * * @return * - 1: if sync event received * - 0: Otherwise * */ int tiGetSyncEventReceived() { int rval=0; TILOCK; rval = tiSyncEventReceived; TIUNLOCK; return rval; } /** * @ingroup Readout * @brief Return the value of the number of readout events accepted * * @return Number of readout events accepted */ int tiGetReadoutEvents() { int rval=0; TILOCK; rval = tiNReadoutEvents; TIUNLOCK; return rval; } /** * @ingroup Config * @brief Enable trigger and sync signals sent through the VXS * to the Signal Distribution (SD) module. * * This may be required to eliminate the possibility of accidental * signals being sent during Clock Synchronization or Trigger * Enable/Disabling by the TI Master or TS. * * @sa tiDisableVXSSignals * @return OK if successful, otherwise ERROR * */ int tiEnableVXSSignals() { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; vmeWrite32(&TIp->fiber, (vmeRead32(&TIp->fiber) & 0xFF) | TI_FIBER_ENABLE_P0); TIUNLOCK; return OK; } /** * @ingroup Config * @brief Disable trigger and sync signals sent through the VXS * to the Signal Distribution (SD) module. * * This may be required to eliminate the possibility of accidental * signals being sent during Clock Synchronization or Trigger * Enable/Disabling by the TI Master or TS. * * @sa tiEnableVXSSignals * @return OK if successful, otherwise ERROR * */ int tiDisableVXSSignals() { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; vmeWrite32(&TIp->fiber, (vmeRead32(&TIp->fiber) & 0xFF) & ~TI_FIBER_ENABLE_P0); TIUNLOCK; return OK; } /** * @ingroup MasterConfig * @brief Set the block buffer level for the number of blocks in the system * that need to be read out. * * If this buffer level is full, the TI will go BUSY. * The BUSY is released as soon as the number of buffers in the system * drops below this level. * * @param level * - 0: No Buffer Limit - Pipeline mode * - 1: One Block Limit - "ROC LOCK" mode * - 2-65535: "Buffered" mode. * * @return OK if successful, otherwise ERROR * */ int tiSetBlockBufferLevel(unsigned int level) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(level>TI_BLOCKBUFFER_BUFFERLEVEL_MASK) { printf("%s: ERROR: Invalid value for level (%d)\n", __FUNCTION__,level); return ERROR; } TILOCK; vmeWrite32(&TIp->blockBuffer, level); TIUNLOCK; return OK; } /** * @ingroup MasterConfig * @brief Enable/Disable trigger inputs labelled TS#1-6 on the Front Panel * * These inputs MUST be disabled if not connected. * * @param inpMask * - 0: TS#1 * - 1: TS#2 * - 2: TS#3 * - 3: TS#4 * - 4: TS#5 * - 5: TS#6 * * @return OK if successful, otherwise ERROR */ int tiEnableTSInput(unsigned int inpMask) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(inpMask>0x3f) { printf("%s: ERROR: Invalid inpMask (0x%x)\n",__FUNCTION__,inpMask); return ERROR; } TILOCK; vmeWrite32(&TIp->tsInput, inpMask); TIUNLOCK; return OK; } /** * @ingroup MasterConfig * @brief Disable trigger inputs labelled TS#1-6 on the Front Panel * * These inputs MUST be disabled if not connected. * * @param inpMask * - 0: TS#1 * - 1: TS#2 * - 2: TS#3 * - 3: TS#4 * - 4: TS#5 * - 5: TS#6 * * @return OK if successful, otherwise ERROR */ int tiDisableTSInput(unsigned int inpMask) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(inpMask>0x3f) { printf("%s: ERROR: Invalid inpMask (0x%x)\n",__FUNCTION__,inpMask); return ERROR; } TILOCK; vmeWrite32(&TIp->tsInput, vmeRead32(&TIp->tsInput) & ~inpMask); TIUNLOCK; return OK; } /** * @ingroup Config * @brief Set (or unset) high level for the output ports on the front panel * labelled as O#1-4 * * @param set1 O#1 * @param set2 O#2 * @param set3 O#3 * @param set4 O#4 * * @return OK if successful, otherwise ERROR */ int tiSetOutputPort(unsigned int set1, unsigned int set2, unsigned int set3, unsigned int set4) { unsigned int bits=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(set1) bits |= (1<<0); if(set2) bits |= (1<<1); if(set3) bits |= (1<<2); if(set4) bits |= (1<<3); TILOCK; vmeWrite32(&TIp->output, bits); TIUNLOCK; return OK; } /** * @ingroup Config * @brief Set the clock to the specified source. * * @param source * - 0: Onboard clock * - 1: External clock (HFBR1 input) * - 5: External clock (HFBR5 input) * * @return OK if successful, otherwise ERROR */ int tiSetClockSource(unsigned int source) { int rval=OK; unsigned int clkset=0; unsigned int clkread=0; char sClock[20] = ""; int iwait = 0, reg = 0, Locked = 0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } switch(source) { case 0: /* ONBOARD */ clkset = TI_CLOCK_INTERNAL; sprintf(sClock,"ONBOARD (%d)",source); break; case 1: /* EXTERNAL (HFBR1) */ clkset = TI_CLOCK_HFBR1; sprintf(sClock,"EXTERNAL-HFBR1 (%d)",source); break; case 5: /* EXTERNAL (HFBR5) */ clkset = TI_CLOCK_HFBR5; sprintf(sClock,"EXTERNAL-HFBR5 (%d)",source); break; default: printf("%s: ERROR: Invalid Clock Souce (%d)\n",__FUNCTION__,source); return ERROR; } printf("%s: Setting clock source to %s\n",__FUNCTION__,sClock); TILOCK; vmeWrite32(&TIp->clock, clkset); /* Reset DCM (Digital Clock Manager) - 250/200MHz */ vmeWrite32(&TIp->reset,TI_RESET_CLK250); taskDelay(1); /* Reset DCM (Digital Clock Manager) - 125MHz */ vmeWrite32(&TIp->reset,TI_RESET_CLK125); taskDelay(10); /* Wait for FPGA Ready / Clock DCM locked */ while(iwait < 100) { reg = vmeRead32(&TIp->GTPtriggerBufferLength); Locked = (reg >> 29) & 0x7; if(Locked == 0x7){ printf("tiLib: THE CLOCK IS LOCKED %d 0x%X \n",iwait,reg); break; } taskDelay(50); iwait ++; } if(Locked < 0x7) { printf("%s: ERROR: FPGA is not yet ready.\n", __func__); printf(" CLK250 DCM: %s\n", (Locked & (1 << 0)) ? "Locked" : "*** Not Locked ***"); printf(" CLK125 DCM: %s\n", (Locked & (1 << 1)) ? "Locked" : "*** Not Locked ***"); printf(" VMECLK DCM: %s\n", (Locked & (1 << 2)) ? "Locked" : "*** Not Locked ***"); rval = ERROR; } if(source==1) /* Turn on running mode for External Clock verification */ { vmeWrite32(&TIp->runningMode,TI_RUNNINGMODE_ENABLE); taskDelay(1); clkread = vmeRead32(&TIp->clock) & TI_CLOCK_MASK; if(clkread != clkset) { printf("%s: ERROR Setting Clock Source (clkset = 0x%x, clkread = 0x%x)\n", __FUNCTION__,clkset, clkread); rval = ERROR; } vmeWrite32(&TIp->runningMode,TI_RUNNINGMODE_DISABLE); } TIUNLOCK; return rval; } /** * @ingroup Status * @brief Get the current clock source * @return Current Clock Source */ int tiGetClockSource() { int rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; rval = vmeRead32(&TIp->clock) & 0x3; TIUNLOCK; return rval; } /** * @ingroup Config * @brief Set the fiber delay required to align the sync and triggers for all crates. * @return Current fiber delay setting */ int tiSetFiberDelay(unsigned int delay, unsigned int offset) { unsigned int fiberLatency = 0, syncDelay = 0, syncDelay_write = 0, syncDelay_read = 0; int delta = -10; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return; } fiberLatency=0; TILOCK; if(delay>offset) { printf("%s: WARN: delay (%d) greater than offset (%d). Setting difference to zero\n", __FUNCTION__,delay,offset); syncDelay = 0; } else { syncDelay = (offset-(delay)); } // syncDelay_write = (syncDelay&0xff<<8) | (syncDelay&0xff<<16) | (syncDelay&0xff<<24); /* set the sync delay according to the fiber latency */ syncDelay_write = (syncDelay & 0xff)<<8 | (syncDelay & 0xff)<<16 | (syncDelay & 0xff)<<24; /* set the sync delay according to the fiber latency */ vmeWrite32(&TIp->fiberSyncDelay,syncDelay_write); taskDelay(2); // Read registers and compare syncDelay_read = vmeRead32(&TIp->fiberSyncDelay); delta = (syncDelay_write & 0xFF00FF00) - (syncDelay_read & 0xFF00FF00); sasha_syncDelay_write = syncDelay_write; #ifdef STOPTHIS if(tiMaster != 1) /* Slave only */ { taskDelay(10); vmeWrite32(&TIp->reset,0x4000); /* reset the IODELAY */ taskDelay(10); vmeWrite32(&TIp->reset,0x800); /* auto adjust the sync phase for HFBR#1 */ taskDelay(10); printf(" /n -------------- STOPHITS IS SET ----------------------------- /n"); } #endif TIUNLOCK; printf("%s: Test Wrote 0x%X to fiberSyncDelay %d %d %d \n",__FUNCTION__, syncDelay_write, offset, delay, syncDelay); return delta; } /** * @ingroup MasterConfig * @brief Add and configurate a TI Slave for the TI Master. * * This routine should be used by the TI Master to configure * HFBR porti and BUSY sources. * * @param fiber The fiber port of the TI Master that is connected to the slave * * @sa tiAddSlaveMask * * @return OK if successful, otherwise ERROR */ int tiAddSlave(unsigned int fiber) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(!tiMaster) { printf("%s: ERROR: TI is not the TI Master.\n",__FUNCTION__); return ERROR; } if((fiber<1) || (fiber>8) ) { printf("%s: ERROR: Invalid value for fiber (%d)\n", __FUNCTION__,fiber); return ERROR; } /* Add this slave to the global slave mask */ tiSlaveMask |= (1<<(fiber-1)); /* Add this fiber as a busy source (use first fiber macro as the base) */ if(tiSetBusySource(TI_BUSY_HFBR1<<(fiber-1),0)!=OK) return ERROR; /* Enable the fiber */ if(tiEnableFiber(fiber)!=OK) return ERROR; return OK; } /** * @ingroup MasterConfig * @brief Add and configure TI Slaves by using a mask for the TI-Master. * * This routine should be used by the TI-Master to configure * HFBR ports and BUSY sources. * * @param fibermask The fiber port mask of the TI-Master that is connected to * the slaves * * @sa tiAddSlave */ int tiAddSlaveMask(unsigned int fibermask) { int ibit=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if((fibermask==0) || (fibermask>0x100)) { printf("%s: ERROR: Invalid value for fibermask (0x%x)\n", __FUNCTION__,fibermask); return ERROR; } if(fibermask & (1<<0)) { printf("%s: WARN: Unused bit 0 in fibermask (0x%x)\n", __FUNCTION__,fibermask); } for(ibit=0; ibit<8; ibit++) { if(fibermask & (1< * rule * timestep 1 2 3 4 * -------- ------ ------- ------- -------- * 0 16ns 16ns 32ns 64ns * 1 480ns 960ns 1920ns 3840ns * 2 15360ns 30720ns 61440ns 122880ns * * * @return OK if successful, otherwise ERROR. * */ int tiSetTriggerHoldoff(int rule, unsigned int value, int timestep) { unsigned int wval=0, rval=0; unsigned int maxvalue=0x3f; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if( (rule<1) || (rule>5) ) { printf("%s: ERROR: Invalid value for rule (%d). Must be 1-4\n", __FUNCTION__,rule); return ERROR; } if(value>maxvalue) { printf("%s: ERROR: Invalid value (%d). Must be less than %d.\n", __FUNCTION__,value,maxvalue); return ERROR; } if(timestep) value |= (1<<7); /* Read the previous values */ TILOCK; rval = vmeRead32(&TIp->triggerRule); switch(rule) { case 1: wval = value | (rval & ~TI_TRIGGERRULE_RULE1_MASK); break; case 2: wval = (value<<8) | (rval & ~TI_TRIGGERRULE_RULE2_MASK); break; case 3: wval = (value<<16) | (rval & ~TI_TRIGGERRULE_RULE3_MASK); break; case 4: wval = (value<<24) | (rval & ~TI_TRIGGERRULE_RULE4_MASK); break; } vmeWrite32(&TIp->triggerRule,wval); if(timestep==2) vmeWrite32(&TIp->vmeControl, vmeRead32(&TIp->vmeControl) | TI_VMECONTROL_SLOWER_TRIGGER_RULES); else vmeWrite32(&TIp->vmeControl, vmeRead32(&TIp->vmeControl) & ~TI_VMECONTROL_SLOWER_TRIGGER_RULES); TIUNLOCK; return OK; } /** * @ingroup Status * @brief Get the value for a specified trigger rule. * * @param rule the number of triggers within some time period.. * e.g. rule=1: No more than ONE trigger within the * specified time period * * @return If successful, returns the value (in steps of 16ns) * for the specified rule. ERROR, otherwise. * */ int tiGetTriggerHoldoff(int rule) { unsigned int rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(rule<1 || rule>5) { printf("%s: ERROR: Invalid value for rule (%d). Must be 1-4.\n", __FUNCTION__,rule); return ERROR; } TILOCK; rval = vmeRead32(&TIp->triggerRule); TIUNLOCK; switch(rule) { case 1: rval = (rval & TI_TRIGGERRULE_RULE1_MASK); break; case 2: rval = (rval & TI_TRIGGERRULE_RULE2_MASK)>>8; break; case 3: rval = (rval & TI_TRIGGERRULE_RULE3_MASK)>>16; break; case 4: rval = (rval & TI_TRIGGERRULE_RULE4_MASK)>>24; break; } return rval; } /** * @ingroup MasterConfig * @brief Set the value for the minimum time of specified trigger rule. * * @param rule the number of triggers within some time period.. * e.g. rule=1: No more than ONE trigger within the * specified time period * * @param value the specified time period (in steps of timestep) *
 *       	 	      rule
 *    		         2      3      4
 *    		       ----- ------ ------
 *    		        16ns  480ns  480ns 
 *
* * @return OK if successful, otherwise ERROR. * */ int tiSetTriggerHoldoffMin(int rule, unsigned int value) { unsigned int mask=0, enable=0, shift=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(rule<2 || rule>5) { printf("%s: ERROR: Invalid rule (%d). Must be 2-4.\n", __FUNCTION__,rule); return ERROR; } if(value > 0x7f) { printf("%s: ERROR: Invalid value (%d). Must be less than %d.\n", __FUNCTION__,value,0x7f); return ERROR; } switch(rule) { case 2: mask = ~(TI_TRIGGERRULEMIN_MIN2_MASK | TI_TRIGGERRULEMIN_MIN2_EN); enable = TI_TRIGGERRULEMIN_MIN2_EN; shift = 8; break; case 3: mask = ~(TI_TRIGGERRULEMIN_MIN3_MASK | TI_TRIGGERRULEMIN_MIN3_EN); enable = TI_TRIGGERRULEMIN_MIN3_EN; shift = 16; break; case 4: mask = ~(TI_TRIGGERRULEMIN_MIN4_MASK | TI_TRIGGERRULEMIN_MIN4_EN); enable = TI_TRIGGERRULEMIN_MIN4_EN; shift = 24; break; } TILOCK; vmeWrite32(&TIp->triggerRuleMin, (vmeRead32(&TIp->triggerRuleMin) & mask) | enable | (value << shift) ); TIUNLOCK; return OK; } /** * @ingroup Status * @brief Get the value for a specified trigger rule minimum busy. * * @param rule the number of triggers within some time period.. * e.g. rule=1: No more than ONE trigger within the * specified time period * * @param pflag if not 0, print the setting to standard out. * * @return If successful, returns the value * (in steps of 16ns for rule 2, 480ns otherwise) * for the specified rule. ERROR, otherwise. * */ int tiGetTriggerHoldoffMin(int rule, int pflag) { int rval=0; unsigned int mask=0, enable=0, shift=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(rule<2 || rule>5) { printf("%s: ERROR: Invalid rule (%d). Must be 2-4.\n", __FUNCTION__,rule); return ERROR; } switch(rule) { case 2: mask = TI_TRIGGERRULEMIN_MIN2_MASK; enable = TI_TRIGGERRULEMIN_MIN2_EN; shift = 8; break; case 3: mask = TI_TRIGGERRULEMIN_MIN3_MASK; enable = TI_TRIGGERRULEMIN_MIN3_EN; shift = 16; break; case 4: mask = TI_TRIGGERRULEMIN_MIN4_MASK; enable = TI_TRIGGERRULEMIN_MIN4_EN; shift = 24; break; } TILOCK; rval = (vmeRead32(&TIp->triggerRuleMin) & mask)>>shift; TIUNLOCK; if(pflag) { printf("%s: Trigger rule %d minimum busy = %d - %s\n", __FUNCTION__,rule, rval & 0x7f, (rval & (1<<7))?"ENABLED":"DISABLED"); } return rval & ~(1<<8); } /** * @ingroup Config * @brief Disable the necessity to readout the TI for every block. * * For instances when the TI data is not required for analysis * When a block is "ready", a call to tiResetBlockReadout must be made. * * @sa tiEnableDataReadout tiResetBlockReadout * @return OK if successful, otherwise ERROR */ int tiDisableDataReadout() { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } tiReadoutEnabled = 0; TILOCK; vmeWrite32(&TIp->vmeControl, vmeRead32(&TIp->vmeControl) | TI_VMECONTROL_BUFFER_DISABLE); TIUNLOCK; printf("%s: Readout disabled.\n",__FUNCTION__); return OK; } /** * @ingroup Config * @brief Enable readout the TI for every block. * * @sa tiDisableDataReadout * @return OK if successful, otherwise ERROR */ int tiEnableDataReadout() { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } tiReadoutEnabled = 1; TILOCK; vmeWrite32(&TIp->vmeControl, vmeRead32(&TIp->vmeControl) & ~TI_VMECONTROL_BUFFER_DISABLE); TIUNLOCK; printf("%s: Readout enabled.\n",__FUNCTION__); return OK; } /** * @ingroup Readout * @brief Decrement the hardware counter for blocks available, effectively * simulating a readout from the data fifo. * * @sa tiDisableDataReadout */ void tiResetBlockReadout() { if(TIp == NULL) { logMsg("tiResetBlockReadout: ERROR: TI not initialized\n",1,2,3,4,5,6); return; } TILOCK; vmeWrite32(&TIp->reset,TI_RESET_BLOCK_READOUT); TIUNLOCK; } /** * @ingroup MasterConfig * @brief Configure trigger table to be loaded with a user provided array. * * @param itable Input Table (Array of 16 4byte words) * * @return OK if successful, otherwise ERROR */ int tiTriggerTableConfig(unsigned int *itable) { int ielement=0; if(itable==NULL) { printf("%s: ERROR: Invalid input table address\n", __FUNCTION__); return ERROR; } for(ielement=0; ielement<16; ielement++) tiTrigPatternData[ielement] = itable[ielement]; return OK; } /** * @ingroup MasterConfig * @brief Get the current trigger table stored in local memory (not necessarily on TI). * * @param otable Output Table (Array of 16 4byte words, user must allocate memory) * * @return OK if successful, otherwise ERROR */ int tiGetTriggerTable(unsigned int *otable) { int ielement=0; if(otable==NULL) { printf("%s: ERROR: Invalid output table address\n", __FUNCTION__); return ERROR; } for(ielement=0; ielement<16; ielement++) otable[ielement] = tiTrigPatternData[ielement]; return OK; } /** * @ingroup MasterConfig * @brief Configure trigger tabled to be loaded with a predefined * trigger table (mapping TS inputs to trigger types). * * @param mode * - 0: * - TS#1,2,3,4,5 generates Trigger1 (physics trigger), * - TS#6 generates Trigger2 (playback trigger), * - No SyncEvent; * - 1: * - TS#1,2,3 generates Trigger1 (physics trigger), * - TS#4,5,6 generates Trigger2 (playback trigger). * - If both Trigger1 and Trigger2, they are SyncEvent; * - 2: * - TS#1,2,3,4,5 generates Trigger1 (physics trigger), * - TS#6 generates Trigger2 (playback trigger), * - If both Trigger1 and Trigger2, generates SyncEvent; * - 3: * - TS#1,2,3,4,5,6 generates Trigger1 (physics trigger), * - No Trigger2 (playback trigger), * - No SyncEvent; * * @return OK if successful, otherwise ERROR */ int tiTriggerTablePredefinedConfig(int mode) { int ielement=0; unsigned int trigPattern[4][16] = { { /* mode 0: TS#1,2,3,4,5 generates Trigger1 (physics trigger), TS#6 generates Trigger2 (playback trigger), No SyncEvent; */ 0x43424100, 0x47464544, 0x4b4a4948, 0x4f4e4d4c, 0x53525150, 0x57565554, 0x5b5a5958, 0x5f5e5d5c, 0x636261a0, 0x67666564, 0x6b6a6968, 0x6f6e6d6c, 0x73727170, 0x77767574, 0x7b7a7978, 0x7f7e7d7c, }, { /* mode 1: TS#1,2,3 generates Trigger1 (physics trigger), TS#4,5,6 generates Trigger2 (playback trigger). If both Trigger1 and Trigger2, they are SyncEvent; */ 0x43424100, 0x47464544, 0xcbcac988, 0xcfcecdcc, 0xd3d2d190, 0xd7d6d5d4, 0xdbdad998, 0xdfdedddc, 0xe3e2e1a0, 0xe7e6e5e4, 0xebeae9a8, 0xefeeedec, 0xf3f2f1b0, 0xf7f6f5f4, 0xfbfaf9b8, 0xfffefdfc, }, { /* mode 2: TS#1,2,3,4,5 generates Trigger1 (physics trigger), TS#6 generates Trigger2 (playback trigger), If both Trigger1 and Trigger2, generates SyncEvent; */ 0x43424100, 0x47464544, 0x4b4a4948, 0x4f4e4d4c, 0x53525150, 0x57565554, 0x5b5a5958, 0x5f5e5d5c, 0xe3e2e1a0, 0xe7e6e5e4, 0xebeae9e8, 0xefeeedec, 0xf3f2f1f0, 0xf7f6f5f4, 0xfbfaf9f8, 0xfffefdfc }, { /* mode 3: TS#1,2,3,4,5,6 generates Trigger1 (physics trigger), No Trigger2 (playback trigger), No SyncEvent; */ 0x43424100, 0x47464544, 0x4b4a4948, 0x4f4e4d4c, 0x53525150, 0x57565554, 0x5b5a5958, 0x5f5e5d5c, 0x63626160, 0x67666564, 0x6b6a6968, 0x6f6e6d6c, 0x73727170, 0x77767574, 0x7b7a7978, 0x7f7e7d7c, } }; if(mode>3) { printf("%s: WARN: Invalid mode %d. Using Trigger Table mode = 0\n", __FUNCTION__,mode); mode=0; } /* Copy predefined choice into static array to be loaded */ for(ielement=0; ielement<16; ielement++) { tiTrigPatternData[ielement] = trigPattern[mode][ielement]; } return OK; } /** * @ingroup MasterConfig * @brief Define a specific trigger pattern as a hardware trigger (trig1/trig2/syncevent) * and Event Type * * @param trigMask Trigger Pattern (must be less than 0x3F) * - TS inputs defining the pattern. Starting bit: TS#1 = bit0 * @param hwTrig Hardware trigger type (must be less than 3) * 0: no trigger * 1: Trig1 (event trigger) * 2: Trig2 (playback trigger) * 3: SyncEvent * @param evType Event Type (must be less than 255) * * @return OK if successful, otherwise ERROR */ int tiDefineEventType(int trigMask, int hwTrig, int evType) { int element=0, byte=0; int data=0; unsigned int old_pattern=0; if(trigMask>0x3f) { printf("%s: ERROR: Invalid trigMask (0x%x)\n", __FUNCTION__, trigMask); return ERROR; } if(hwTrig>3) { printf("%s: ERROR: Invalid hwTrig (%d)\n", __FUNCTION__, hwTrig); return ERROR; } if(evType>0x3F) { printf("%s: ERROR: Invalid evType (%d)\n", __FUNCTION__, evType); return ERROR; } element = trigMask/4; byte = trigMask%4; data = (hwTrig<<6) | evType; old_pattern = (tiTrigPatternData[element] & ~(0xFF<<(byte*8))); tiTrigPatternData[element] = old_pattern | (data<<(byte*8)); return OK; } /** * @ingroup MasterConfig * @brief Define the event type for the TI Master's fixed and random internal trigger. * * @param fixed_type Fixed Pulser Event Type * @param random_type Pseudo Random Pulser Event Type * * @return OK if successful, otherwise ERROR */ int tiDefinePulserEventType(int fixed_type, int random_type) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if((fixed_type<0)||(fixed_type>0xFF)) { printf("%s: ERROR: Invalid fixed_type (0x%x)\n",__FUNCTION__,fixed_type); return ERROR; } if((random_type<0)||(random_type>0xFF)) { printf("%s: ERROR: Invalid random_type (0x%x)\n",__FUNCTION__,random_type); return ERROR; } TILOCK; vmeWrite32(&TIp->pulserEvType, (fixed_type)<<16 | (random_type)<<24); TIUNLOCK; return OK; } /** * @ingroup MasterConfig * @brief Load a predefined trigger table (mapping TS inputs to trigger types). * * @param mode * - 0: * - TS#1,2,3,4,5 generates Trigger1 (physics trigger), * - TS#6 generates Trigger2 (playback trigger), * - No SyncEvent; * - 1: * - TS#1,2,3 generates Trigger1 (physics trigger), * - TS#4,5,6 generates Trigger2 (playback trigger). * - If both Trigger1 and Trigger2, they are SyncEvent; * - 2: * - TS#1,2,3,4,5 generates Trigger1 (physics trigger), * - TS#6 generates Trigger2 (playback trigger), * - If both Trigger1 and Trigger2, generates SyncEvent; * - 3: * - TS#1,2,3,4,5,6 generates Trigger1 (physics trigger), * - No Trigger2 (playback trigger), * - No SyncEvent; * - 4: * User configured table @sa tiDefineEventType, tiTriggerTablePredefinedConfig * * @return OK if successful, otherwise ERROR */ int tiLoadTriggerTable(int mode) { int ipat; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(mode>4) { printf("%s: WARN: Invalid mode %d. Using Trigger Table mode = 0\n", __FUNCTION__,mode); mode=0; } if(mode!=4) tiTriggerTablePredefinedConfig(mode); TILOCK; for(ipat=0; ipat<16; ipat++) vmeWrite32(&TIp->trigTable[ipat], tiTrigPatternData[ipat]); TIUNLOCK; return OK; } /** * @ingroup MasterStatus * @brief Print trigger table to standard out. * * @param showbits Show trigger bit pattern, instead of hex * */ void tiPrintTriggerTable(int showbits) { int ielement, ibyte; int hwTrig=0, evType=0; for(ielement = 0; ielement<16; ielement++) { if(showbits) { printf("--TS INPUT-\n"); printf("1 2 3 4 5 6 HW evType\n"); } else { printf("TS Pattern HW evType\n"); } for(ibyte=0; ibyte<4; ibyte++) { hwTrig = ((tiTrigPatternData[ielement]>>(ibyte*8)) & 0xC0)>>6; evType = (tiTrigPatternData[ielement]>>(ibyte*8)) & 0x3F; if(showbits) { printf("%d %d %d %d %d %d %d %2d\n", ((ielement*4+ibyte) & (1<<0))?1:0, ((ielement*4+ibyte) & (1<<1))?1:0, ((ielement*4+ibyte) & (1<<2))?1:0, ((ielement*4+ibyte) & (1<<3))?1:0, ((ielement*4+ibyte) & (1<<4))?1:0, ((ielement*4+ibyte) & (1<<5))?1:0, hwTrig, evType); } else { printf(" 0x%02x %d %2d\n", ielement*4+ibyte,hwTrig, evType); } } printf("\n"); } } /** * @ingroup MasterConfig * @brief Set the window of the input trigger coincidence window * @param window_width Width of the input coincidence window (units of 4ns) * @return OK if successful, otherwise ERROR */ int tiSetTriggerWindow(int window_width) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if((window_width<1) || (window_width>TI_TRIGGERWINDOW_COINC_MASK)) { printf("%s: ERROR: Invalid Trigger Coincidence Window (%d)\n", __FUNCTION__,window_width); return ERROR; } TILOCK; vmeWrite32(&TIp->triggerWindow, (vmeRead32(&TIp->triggerWindow) & ~TI_TRIGGERWINDOW_COINC_MASK) | window_width); TIUNLOCK; return OK; } /** * @ingroup MasterStatus * @brief Get the window of the input trigger coincidence window * @return Width of the input coincidence window (units of 4ns), otherwise ERROR */ int tiGetTriggerWindow() { int rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; rval = vmeRead32(&TIp->triggerWindow) & TI_TRIGGERWINDOW_COINC_MASK; TIUNLOCK; return rval; } /** * @ingroup MasterConfig * @brief Set the width of the input trigger inhibit window * @param window_width Width of the input inhibit window (units of 4ns) * @return OK if successful, otherwise ERROR */ int tiSetTriggerInhibitWindow(int window_width) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if((window_width<1) || (window_width>(TI_TRIGGERWINDOW_INHIBIT_MASK>>8))) { printf("%s: ERROR: Invalid Trigger Inhibit Window (%d)\n", __FUNCTION__,window_width); return ERROR; } TILOCK; vmeWrite32(&TIp->triggerWindow, (vmeRead32(&TIp->triggerWindow) & ~TI_TRIGGERWINDOW_INHIBIT_MASK) | (window_width<<8)); TIUNLOCK; return OK; } /** * @ingroup MasterStatus * @brief Get the width of the input trigger inhibit window * @return Width of the input inhibit window (units of 4ns), otherwise ERROR */ int tiGetTriggerInhibitWindow() { int rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; rval = (vmeRead32(&TIp->triggerWindow) & TI_TRIGGERWINDOW_INHIBIT_MASK)>>8; TIUNLOCK; return rval; } /** * @ingroup MasterConfig * @brief Set the delay of Trig1 relative to Trig2 when trigger source is 11. * * @param delay Trig1 delay after Trig2 * - Latency in steps of 4 nanoseconds with an offset of ~2.6 microseconds * * @return OK if successful, otherwise ERROR */ int tiSetTrig21Delay(int delay) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(delay>0x1FF) { printf("%s: ERROR: Invalid delay (%d)\n", __FUNCTION__,delay); return ERROR; } TILOCK; vmeWrite32(&TIp->triggerWindow, (vmeRead32(&TIp->triggerWindow) & ~TI_TRIGGERWINDOW_TRIG21_MASK) | (delay<<16)); TIUNLOCK; return OK; } /** * @ingroup MasterStatus * @brief Get the delay of Trig1 relative to Trig2 when trigger source is 11. * * @return Latency in steps of 4 nanoseconds with an offset of ~2.6 microseconds, otherwise ERROR */ int tiGetTrig21Delay() { int rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; rval = (vmeRead32(&TIp->triggerWindow) & TI_TRIGGERWINDOW_TRIG21_MASK)>>16; TIUNLOCK; return rval; } /** * @ingroup MasterConfig * @brief Set the trigger latch pattern readout in the data stream to include * the Level of the input trigger OR the transition to Hi. * * @param enable * 1 to enable * <1 to disable * * @return OK if successful, otherwise ERROR */ int tiSetTriggerLatchOnLevel(int enable) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(enable < 1) enable = 0; TILOCK; vmeWrite32(&TIp->triggerWindow, (vmeRead32(&TIp->triggerWindow) & ~TI_TRIGGERWINDOW_LEVEL_LATCH) | (enable<<31)); TIUNLOCK; return OK; } /** * @ingroup MasterStatus * @brief Get the trigger latch pattern readout in the data stream to include * the Level of the input trigger OR the transition to Hi. * * @return 1 if enabled, 0 if disabled, otherwise ERROR */ int tiGetTriggerLatchOnLevel() { int rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; rval = (vmeRead32(&TIp->triggerWindow) & TI_TRIGGERWINDOW_LEVEL_LATCH)>>31; TIUNLOCK; return rval; } /** * @ingroup MasterConfig * @brief Latch the Busy and Live Timers. * * This routine should be called prior to a call to tiGetLiveTime and tiGetBusyTime * * @sa tiGetLiveTime * @sa tiGetBusyTime * * @return OK if successful, otherwise ERROR */ int tiLatchTimers() { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; vmeWrite32(&TIp->reset, TI_RESET_SCALERS_LATCH); TIUNLOCK; return OK; } /** * @ingroup Status * @brief Return the current "live" time of the module * * @returns The current live time in units of 7.68 us * */ unsigned int tiGetLiveTime() { unsigned int rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; rval = vmeRead32(&TIp->livetime); TIUNLOCK; return rval; } /** * @ingroup Status * @brief Return the current "busy" time of the module * * @returns The current live time in units of 7.68 us * */ unsigned int tiGetBusyTime() { unsigned int rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; rval = vmeRead32(&TIp->busytime); TIUNLOCK; return rval; } /** * @ingroup Status * @brief Calculate the live time (percentage) from the live and busy time scalers * * @param sflag if > 0, then returns the integrated live time * * @return live time as a 3 digit integer % (e.g. 987 = 98.7%) * */ int tiLive(int sflag) { int rval=0; float fval=0; unsigned int newBusy=0, newLive=0, newTotal=0; unsigned int live=0, total=0; static unsigned int oldLive=0, oldTotal=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; vmeWrite32(&TIp->reset,TI_RESET_SCALERS_LATCH); newLive = vmeRead32(&TIp->livetime); newBusy = vmeRead32(&TIp->busytime); newTotal = newLive+newBusy; if((sflag==0) && (oldTotal0) fval = 1000*(((float) live)/((float) total)); rval = (int) fval; TIUNLOCK; return rval; } /** * @ingroup Status * @brief Get the current counter for the specified TS Input * * @param input * - 1-6 : TS Input (1-6) * @param latch: * - 0: Do not latch before readout * - 1: Latch before readout * - 2: Latch and reset before readout * * * @return Specified counter value * */ unsigned int tiGetTSscaler(int input, int latch) { unsigned int rval=0; if(TIp == NULL) { logMsg("tiGetTSscaler: ERROR: TI not initialized\n",1,2,3,4,5,6); return ERROR; } if((input<1)||(input>6)) { logMsg("tiGetTSscaler: ERROR: Invalid input (%d).\n", input,2,3,4,5,6); return ERROR; } if((latch<0) || (latch>2)) { logMsg("tiGetTSscaler: ERROR: Invalid latch (%d).\n", latch,2,3,4,5,6); return ERROR; } TILOCK; switch(latch) { case 1: vmeWrite32(&TIp->reset,TI_RESET_SCALERS_LATCH); break; case 2: vmeWrite32(&TIp->reset,TI_RESET_SCALERS_LATCH | TI_RESET_SCALERS_RESET); break; } rval = vmeRead32(&TIp->ts_scaler[input-1]); TIUNLOCK; return rval; } /** * @ingroup Status * @brief Show block Status of specified fiber * @param fiber Fiber port to show * @param pflag Whether or not to print to standard out * @return 0 */ unsigned int tiBlockStatus(int fiber, int pflag) { unsigned int rval=0; char name[50]; unsigned int nblocksReady, nblocksNeedAck; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(fiber>8) { printf("%s: ERROR: Invalid value (%d) for fiber\n",__FUNCTION__,fiber); return ERROR; } switch(fiber) { case 0: rval = (vmeRead32(&TIp->adr24) & 0xFFFF0000)>>16; break; case 1: case 3: case 5: case 7: rval = (vmeRead32(&TIp->blockStatus[(fiber-1)/2]) & 0xFFFF); break; case 2: case 4: case 6: case 8: rval = ( vmeRead32(&TIp->blockStatus[(fiber/2)-1]) & 0xFFFF0000 )>>16; break; } if(pflag) { nblocksReady = rval & TI_BLOCKSTATUS_NBLOCKS_READY0; nblocksNeedAck = (rval & TI_BLOCKSTATUS_NBLOCKS_NEEDACK0)>>8; if(fiber==0) sprintf(name,"Loopback"); else sprintf(name,"Fiber %d",fiber); printf("%s: %s : Blocks ready / need acknowledge: %d / %d\n", __FUNCTION__, name, nblocksReady, nblocksNeedAck); } return rval; } static void FiberMeas() { int clksrc=0; unsigned int defaultDelay=0x1f1f1f00, fiberLatency=0, syncDelay=0, syncDelay_write=0; clksrc = tiGetClockSource(); /* Check to be sure the TI has external HFBR1/5 clock enabled */ if((clksrc != TI_CLOCK_HFBR1) && (clksrc != TI_CLOCK_HFBR5)) { printf("%s: ERROR: Unable to measure fiber latency without HFBR1/5 as Clock Source\n", __FUNCTION__); printf("\t Using default Fiber Sync Delay = %d (0x%x)", defaultDelay, defaultDelay); TILOCK; vmeWrite32(&TIp->fiberSyncDelay,defaultDelay); TIUNLOCK; return; } TILOCK; vmeWrite32(&TIp->reset,TI_RESET_IODELAY); // reset the IODELAY taskDelay(20); vmeWrite32(&TIp->reset,TI_RESET_FIBER_AUTO_ALIGN); // auto adjust the return signal phase taskDelay(20); vmeWrite32(&TIp->reset,TI_RESET_MEASURE_LATENCY); // measure the fiber latency taskDelay(2); // Alex // taskDelay(1); // vmeWrite32(&TIp->reset,TI_RESET_MEASURE_LATENCY); // measure the fiber latency // taskDelay(1); // Alex // taskDelay(4); // if(tiSlaveFiberIn==1) // fiberLatency = vmeRead32(&TIp->fiberLatencyMeasurement); //fiber 1 latency measurement result // else // fiberLatency = vmeRead32(&TIp->fiberAlignment); //fiber 5 latency measurement result // printf("tiSlaveFiberIn = %d \n", tiSlaveFiberIn); // printf("Software offset = 0x%08x (%d)\n",tiFiberLatencyOffset, tiFiberLatencyOffset); // printf("Fiber Latency is 0x%08x\n",fiberLatency); // printf(" Latency data = 0x%08x (%d ns)\n",(fiberLatency>>23), (fiberLatency>>23) * 4); if(tiSlaveFiberIn==1) vmeWrite32(&TIp->reset,TI_RESET_AUTOALIGN_HFBR1_SYNC); // auto adjust the sync phase for HFBR#1 else vmeWrite32(&TIp->reset,TI_RESET_AUTOALIGN_HFBR5_SYNC); // auto adjust the sync phase for HFBR#5 taskDelay(2); if(tiSlaveFiberIn==1) fiberLatency = vmeRead32(&TIp->fiberLatencyMeasurement); //fiber 1 latency measurement result else fiberLatency = vmeRead32(&TIp->fiberAlignment); //fiber 5 latency measurement result printf("tiSlaveFiberIn = %d \n", tiSlaveFiberIn); printf("Software offset = 0x%08x (%d)\n",tiFiberLatencyOffset, tiFiberLatencyOffset); printf("Fiber Latency is 0x%08x\n",fiberLatency); printf(" Latency data = 0x%08x (%d ns)\n",(fiberLatency>>23), (fiberLatency>>23) * 4); tiFiberLatencyMeasurement = ((fiberLatency & TI_FIBERLATENCYMEASUREMENT_DATA_MASK)>>23)>>1; syncDelay = (tiFiberLatencyOffset-(((fiberLatency>>23)&0x1ff)>>1)); syncDelay_write = (syncDelay&0xFF)<<8 | (syncDelay&0xFF)<<16 | (syncDelay&0xFF)<<24; taskDelay(1); vmeWrite32(&TIp->fiberSyncDelay,syncDelay_write); taskDelay(1); syncDelay = vmeRead32(&TIp->fiberSyncDelay); TIUNLOCK; sasha_syncDelay_write = syncDelay_write; printf (" \n The fiber latency of 0xA0 is: 0x%08x\n", fiberLatency); printf (" \n The sync latency of 0x50 is: 0x%08x\n",syncDelay); } /** * @ingroup Status * @brief Return measured fiber length * @return Value of measured fiber length */ int tiGetFiberLatencyMeasurement() { return tiFiberLatencyMeasurement; } /** * @ingroup MasterConfig * @brief Enable/Disable operation of User SyncReset * @sa tiUserSyncReset * @param enable * - >0: Enable * - 0: Disable * * @return OK if successful, otherwise ERROR */ int tiSetUserSyncResetReceive(int enable) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; if(enable) vmeWrite32(&TIp->sync, (vmeRead32(&TIp->sync) & TI_SYNC_SOURCEMASK) | TI_SYNC_USER_SYNCRESET_ENABLED); else vmeWrite32(&TIp->sync, (vmeRead32(&TIp->sync) & TI_SYNC_SOURCEMASK) & ~TI_SYNC_USER_SYNCRESET_ENABLED); TIUNLOCK; return OK; } /** * @ingroup Status * @brief Return last SyncCommand received * @param * - >0: print to standard out * @return Last SyncCommand received */ int tiGetLastSyncCodes(int pflag) { int rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; if(tiMaster) rval = ((vmeRead32(&TIp->sync) & TI_SYNC_LOOPBACK_CODE_MASK)>>16) & 0xF; else rval = ((vmeRead32(&TIp->sync) & TI_SYNC_HFBR1_CODE_MASK)>>8) & 0xF; TIUNLOCK; if(pflag) { printf(" Last Sync Code received: 0x%x\n",rval); } return rval; } /** * @ingroup Status * @brief Get the status of the SyncCommand History Buffer * * @param pflag * - >0: Print to standard out * * @return * - 0: Empty * - 1: Half Full * - 2: Full */ int tiGetSyncHistoryBufferStatus(int pflag) { int hist_status=0, rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; hist_status = vmeRead32(&TIp->sync) & (TI_SYNC_HISTORY_FIFO_MASK); TIUNLOCK; switch(hist_status) { case TI_SYNC_HISTORY_FIFO_EMPTY: rval=0; if(pflag) printf("%s: Sync history buffer EMPTY\n",__FUNCTION__); break; case TI_SYNC_HISTORY_FIFO_HALF_FULL: rval=1; if(pflag) printf("%s: Sync history buffer HALF FULL\n",__FUNCTION__); break; case TI_SYNC_HISTORY_FIFO_FULL: default: rval=2; if(pflag) printf("%s: Sync history buffer FULL\n",__FUNCTION__); break; } return rval; } /** * @ingroup Config * @brief Reset the SyncCommand history buffer */ void tiResetSyncHistory() { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return; } TILOCK; vmeWrite32(&TIp->reset, TI_RESET_SYNC_HISTORY); TIUNLOCK; } /** * @ingroup Config * @brief Control level of the SyncReset signal * @sa tiSetUserSyncResetReceive * @param enable * - >0: High * - 0: Low * @param pflag * - >0: Print status to standard out * - 0: Supress status message */ void tiUserSyncReset(int enable, int pflag) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return; } TILOCK; if(enable) vmeWrite32(&TIp->syncCommand,TI_SYNCCOMMAND_SYNCRESET_HIGH); else vmeWrite32(&TIp->syncCommand,TI_SYNCCOMMAND_SYNCRESET_LOW); taskDelay(2); TIUNLOCK; if(pflag) { printf("%s: User Sync Reset ",__FUNCTION__); if(enable) printf("HIGH\n"); else printf("LOW\n"); } } /** * @ingroup Status * @brief Print to standard out the history buffer of Sync Commands received. */ void tiPrintSyncHistory() { unsigned int syncHistory=0; int count=0, code=1, valid=0, timestamp=0, overflow=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return; } while(code!=0) { TILOCK; syncHistory = vmeRead32(&TIp->syncHistory); TIUNLOCK; printf(" TimeStamp: Code (valid)\n"); if(tiMaster) { code = (syncHistory & TI_SYNCHISTORY_LOOPBACK_CODE_MASK)>>10; valid = (syncHistory & TI_SYNCHISTORY_LOOPBACK_CODE_VALID)>>14; } else { code = syncHistory & TI_SYNCHISTORY_HFBR1_CODE_MASK; valid = (syncHistory & TI_SYNCHISTORY_HFBR1_CODE_VALID)>>4; } overflow = (syncHistory & TI_SYNCHISTORY_TIMESTAMP_OVERFLOW)>>15; timestamp = (syncHistory & TI_SYNCHISTORY_TIMESTAMP_MASK)>>16; /* if(valid) */ { printf("%4d: 0x%08x %d %5d : 0x%x (%d)\n", count, syncHistory, overflow, timestamp, code, valid); } count++; if(count>1024) { printf("%s: More than expected in the Sync History Buffer... exitting\n", __FUNCTION__); break; } } } /** * @ingroup MasterConfig * @brief Set the value of the syncronization event interval * * * @param blk_interval * Sync Event will occur in the last event of the set blk_interval (number of blocks) * * @return OK if successful, otherwise ERROR */ int tiSetSyncEventInterval(int blk_interval) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(!tiMaster) { printf("%s: ERROR: TI is not the TI Master.\n",__FUNCTION__); return ERROR; } if(blk_interval>TI_SYNCEVENTCTRL_NBLOCKS_MASK) { printf("%s: WARN: Value for blk_interval (%d) too large. Setting to %d\n", __FUNCTION__,blk_interval,TI_SYNCEVENTCTRL_NBLOCKS_MASK); blk_interval = TI_SYNCEVENTCTRL_NBLOCKS_MASK; } TILOCK; vmeWrite32(&TIp->syncEventCtrl, blk_interval); TIUNLOCK; return OK; } /** * @ingroup MasterStatus * @brief Get the SyncEvent Block interval * @return Block interval of the SyncEvent */ int tiGetSyncEventInterval() { int rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(!tiMaster) { printf("%s: ERROR: TI is not the TI Master.\n",__FUNCTION__); return ERROR; } TILOCK; rval = vmeRead32(&TIp->syncEventCtrl) & TI_SYNCEVENTCTRL_NBLOCKS_MASK; TIUNLOCK; return rval; } /** * @ingroup MasterReadout * @brief Force a sync event (type = 0). * @return OK if successful, otherwise ERROR */ int tiForceSyncEvent() { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(!tiMaster) { printf("%s: ERROR: TI is not the TI Master.\n",__FUNCTION__); return ERROR; } TILOCK; vmeWrite32(&TIp->reset, TI_RESET_FORCE_SYNCEVENT); TIUNLOCK; return OK; } /** * @ingroup Readout * @brief Sync Reset Request is sent to TI-Master or TS. * * This option is available for multicrate systems when the * synchronization is suspect. It should be exercised only during * "sync events" where the requested sync reset will immediately * follow all ROCs concluding their readout. * * @return OK if successful, otherwise ERROR */ int tiSyncResetRequest() { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; tiDoSyncResetRequest=1; TIUNLOCK; return OK; } /** * @ingroup MasterReadout * @brief Determine if a TI has requested a Sync Reset * * @return 1 if requested received, 0 if not, otherwise ERROR */ int tiGetSyncResetRequest() { int request=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(!tiMaster) { printf("%s: ERROR: TI is not the TI Master.\n",__FUNCTION__); return ERROR; } TILOCK; request = (vmeRead32(&TIp->blockBuffer) & TI_BLOCKBUFFER_SYNCRESET_REQUESTED)>>30; TIUNLOCK; return request; } /** * @ingroup MasterConfig * @brief Configure which ports (and self) to enable response of a SyncReset request. * @param portMask Mask of ports to enable (port 1 = bit 0) * @param self 1 to enable self, 0 to disable * * @return OK if successful, otherwise ERROR */ int tiEnableSyncResetRequest(unsigned int portMask, int self) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(!tiMaster) { printf("%s: ERROR: TI is not the TI Master.\n",__FUNCTION__); return ERROR; } if(portMask > 0xFF) { printf("%s: ERROR: Invalid portMask (0x%x)\n", __FUNCTION__, portMask); return ERROR; } /* Mask sure self is binary */ if(self) self = 1; else self = 0; TILOCK; vmeWrite32(&TIp->rocEnable, (vmeRead32(&TIp->rocEnable) & TI_ROCENABLE_MASK) | (portMask << 11) | (self << 10) ); TIUNLOCK; return OK; } /** * @ingroup MasterStatus * @brief Status of SyncReset Request received bits. * @param pflag Print to standard out if not 0 * @return Port mask of SyncReset Request received (port 1 = bit 0, TI-Master = bit 8), otherwise ERROR; */ int tiSyncResetRequestStatus(int pflag) { int self = 0, rval = 0, ibit = 0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(!tiMaster) { printf("%s: ERROR: TI is not the TI Master.\n",__FUNCTION__); return ERROR; } TILOCK; rval = (int)(vmeRead32(&TIp->rocEnable) & TI_ROCENABLE_SYNCRESET_REQUEST_MONITOR_MASK); TIUNLOCK; /* Reorganize the bits */ if(rval) { self = (rval & 0x1); rval = rval >> 1; rval = rval | (self<<8); } if(pflag) { if(rval) { printf(" ***** SyncReset Requested from "); for(ibit = 0; ibit < 8; ibit++) { printf("%d ", ibit + 1); } if(rval & (1 << 8)) { printf("SELF "); } printf("*****\n"); } else { printf(" No SyncReset Requested\n"); } } return rval; } /** * @ingroup MasterConfig * @brief Reset the registers that record the triggers enabled status of TI Slaves. * */ void tiTriggerReadyReset() { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return; } if(!tiMaster) { printf("%s: ERROR: TI is not the TI Master.\n",__FUNCTION__); return; } TILOCK; vmeWrite32(&TIp->syncCommand,TI_SYNCCOMMAND_TRIGGER_READY_RESET); TIUNLOCK; } /** * @ingroup MasterReadout * @brief Generate non-physics triggers until the current block is filled. * This feature is useful for "end of run" situations. * * @return OK if successful, otherwise ERROR */ int tiFillToEndBlock() { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(!tiMaster) { printf("%s: ERROR: TI is not the TI Master.\n",__FUNCTION__); return ERROR; } TILOCK; vmeWrite32(&TIp->reset, TI_RESET_FILL_TO_END_BLOCK); TIUNLOCK; return OK; } /** * @ingroup MasterConfig * @brief Reset the MGT * @return OK if successful, otherwise ERROR */ int tiResetMGT() { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(!tiMaster) { printf("%s: ERROR: TI is not the TI Master.\n",__FUNCTION__); return ERROR; } TILOCK; vmeWrite32(&TIp->reset, TI_RESET_MGT); TIUNLOCK; taskDelay(1); return OK; } /** * @ingroup Config * @brief Set the input delay for the specified front panel TSinput (1-6) * @param chan Front Panel TSInput Channel (1-6) * @param delay Delay in units of 4ns (0=8ns) * @return OK if successful, otherwise ERROR */ int tiSetTSInputDelay(int chan, int delay) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if((chan<1) || (chan>6)) { printf("%s: ERROR: Invalid chan (%d)\n",__FUNCTION__, chan); return ERROR; } if((delay<0) || (delay>0x1ff)) { printf("%s: ERROR: Invalid delay (%d)\n",__FUNCTION__, delay); return ERROR; } TILOCK; chan--; vmeWrite32(&TIp->fpDelay[chan%3], (vmeRead32(&TIp->fpDelay[chan%3]) & ~TI_FPDELAY_MASK(chan)) | delay<<(10*(chan%3))); TIUNLOCK; return OK; } /** * @ingroup Status * @brief Get the input delay for the specified front panel TSinput (1-6) * @param chan Front Panel TSInput Channel (1-6) * @return Channel delay (units of 4ns) if successful, otherwise ERROR */ int tiGetTSInputDelay(int chan) { int rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if((chan<1) || (chan>6)) { printf("%s: ERROR: Invalid chan (%d)\n",__FUNCTION__, chan); return ERROR; } TILOCK; chan--; rval = (vmeRead32(&TIp->fpDelay[chan%3]) & TI_FPDELAY_MASK(chan))>>(10*(chan%3)); TIUNLOCK; return rval; } /** * @ingroup Status * @brief Print Front Panel TSinput Delays to Standard Out * @return OK if successful, otherwise ERROR */ int tiPrintTSInputDelay() { unsigned int reg[11]; int ireg=0, ichan=0, delay=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; for(ireg=0; ireg<11; ireg++) reg[ireg] = vmeRead32(&TIp->fpDelay[ireg]); TIUNLOCK; printf("%s: Front panel delays:", __FUNCTION__); for(ichan=0;ichan<5;ichan++) { delay = reg[ichan%3] & TI_FPDELAY_MASK(ichan)>>(10*(ichan%3)); if((ichan%4)==0) { printf("\n"); } printf("Chan %2d: %5d ",ichan+1,delay); } printf("\n"); return OK; } /** * @ingroup Status * @brief Return value of buffer length from GTP * @return value of buffer length from GTP */ unsigned int tiGetGTPBufferLength(int pflag) { unsigned int rval=0; TILOCK; rval = vmeRead32(&TIp->GTPtriggerBufferLength); TIUNLOCK; if(pflag) printf("%s: 0x%08x\n",__FUNCTION__,rval); return rval; } /** * @ingroup MasterStatus * @brief Returns the mask of fiber channels that report a "connected" * status from a TI. * * @return Fiber Connected Mask */ int tiGetConnectedFiberMask() { int rval=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(!tiMaster) { printf("%s: ERROR: TI is not the TI Master.\n",__FUNCTION__); return ERROR; } TILOCK; rval = (vmeRead32(&TIp->fiber) & TI_FIBER_CONNECTED_MASK)>>16; TIUNLOCK; return rval; } /** * @ingroup MasterStatus * @brief Returns the mask of fiber channels that report a "connected" * status from a TI has it's trigger source enabled. * * @return Trigger Source Enabled Mask */ int tiGetTrigSrcEnabledFiberMask() { int rval=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(!tiMaster) { printf("%s: ERROR: TI is not the TI Master.\n",__FUNCTION__); return ERROR; } TILOCK; rval = (vmeRead32(&TIp->fiber) & TI_FIBER_TRIGSRC_ENABLED_MASK)>>24; TIUNLOCK; return rval; } /** * @ingroup Status * @brief Return the value from the SWa fast link register * @param reg Register to request * @return Value at specified register */ unsigned int tiGetSWAStatus(int reg) { unsigned int rval=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(reg>=128) { printf("%s: ERROR: SWA reg (0x%x) out of range.\n", __FUNCTION__,reg); return ERROR; } TILOCK; rval = vmeRead32(&TIp->SWA_status[reg]); TIUNLOCK; return rval; } /** * @ingroup Status * @brief Return the value from the SWB fast link register * @param reg Register to request * @return Value at specified register */ unsigned int tiGetSWBStatus(int reg) { unsigned int rval=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(reg>=128) { printf("%s: ERROR: SWB reg (0x%x) out of range.\n", __FUNCTION__,reg); return ERROR; } TILOCK; rval = vmeRead32(&TIp->SWB_status[reg]); TIUNLOCK; return rval; } /** * @ingroup Status * @brief Return geographic address as provided from a VME-64X crate. * @return Geographic Address if successful, otherwise ERROR. 0 would indicate that the TI is not in a VME-64X crate. */ int tiGetGeoAddress() { int rval=0; if(TIp==NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; rval = (vmeRead32(&TIp->adr24) & TI_ADR24_GEOADDR_MASK)>>10; TIUNLOCK; return rval; } /************************************************************* Library Interrupt/Polling routines *************************************************************/ /******************************************************************************* * * tiInt * - Default interrupt handler * Handles the TI interrupt. Calls a user defined routine, * if it was connected with tiIntConnect() * */ static void tiInt(void) { tiIntCount++; INTLOCK; if (tiIntRoutine != NULL) /* call user routine */ (*tiIntRoutine) (tiIntArg); /* Acknowledge trigger */ if(tiDoAck==1) { tiIntAck(); } INTUNLOCK; } /******************************************************************************* * * tiPoll * - Default Polling Server Thread * Handles the polling of latched triggers. Calls a user * defined routine if was connected with tiIntConnect. * */ #ifndef VXWORKS static void tiPoll(void) { int tidata; int policy=0; struct sched_param sp; /* #define DO_CPUAFFINITY */ #ifdef DO_CPUAFFINITY int j; cpu_set_t testCPU; if (pthread_getaffinity_np(pthread_self(), sizeof(testCPU), &testCPU) <0) { perror("pthread_getaffinity_np"); } printf("tiPoll: CPUset = "); for (j = 0; j < CPU_SETSIZE; j++) if (CPU_ISSET(j, &testCPU)) printf(" %d", j); printf("\n"); CPU_ZERO(&testCPU); CPU_SET(7,&testCPU); if (pthread_setaffinity_np(pthread_self(),sizeof(testCPU), &testCPU) <0) { perror("pthread_setaffinity_np"); } if (pthread_getaffinity_np(pthread_self(), sizeof(testCPU), &testCPU) <0) { perror("pthread_getaffinity_np"); } printf("tiPoll: CPUset = "); for (j = 0; j < CPU_SETSIZE; j++) if (CPU_ISSET(j, &testCPU)) printf(" %d", j); printf("\n"); #endif /* Set scheduler and priority for this thread */ policy=SCHED_FIFO; sp.sched_priority=40; printf("%s: Entering polling loop...\n",__FUNCTION__); pthread_setschedparam(pthread_self(),policy,&sp); pthread_getschedparam(pthread_self(),&policy,&sp); printf ("%s: INFO: Running at %s/%d\n",__FUNCTION__, (policy == SCHED_FIFO ? "FIFO" : (policy == SCHED_RR ? "RR" : (policy == SCHED_OTHER ? "OTHER" : "unknown"))), sp.sched_priority); prctl(PR_SET_NAME,"tiPoll"); while(1) { pthread_testcancel(); /* If still need Ack, don't test the Trigger Status */ if(tiNeedAck>0) { continue; } tidata = 0; tidata = tiBReady(); if(tidata == ERROR) { printf("%s: ERROR: tiIntPoll returned ERROR.\n",__FUNCTION__); break; } if(tidata && tiIntRunning) { INTLOCK; tiDaqCount = tidata; tiIntCount++; if (tiIntRoutine != NULL) /* call user routine */ (*tiIntRoutine) (tiIntArg); /* Write to TI to Acknowledge Interrupt */ if(tiDoAck==1) { tiIntAck(); } INTUNLOCK; } } printf("%s: Read ERROR: Exiting Thread\n",__FUNCTION__); pthread_exit(0); } #endif /******************************************************************************* * * tiStartPollingThread * - Routine that launches tiPoll in its own thread * */ #ifndef VXWORKS static void tiStartPollingThread(void) { int pti_status; pti_status = pthread_create(&tipollthread, NULL, (void*(*)(void *)) tiPoll, (void *)NULL); if(pti_status!=0) { printf("%s: ERROR: TI Polling Thread could not be started.\n", __FUNCTION__); printf("\t pthread_create returned: %d\n",pti_status); } } #endif /** * @ingroup IntPoll * @brief Connect a user routine to the TI Interrupt or * latched trigger, if polling. * * @param vector VME Interrupt Vector * @param routine Routine to call if block is available * @param arg argument to pass to routine * * @return OK if successful, otherwise ERROR */ int tiIntConnect(unsigned int vector, VOIDFUNCPTR routine, unsigned int arg) { #ifndef VXWORKS int status; #endif if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return(ERROR); } #ifdef VXWORKS /* Disconnect any current interrupts */ if((intDisconnect(tiIntVec) !=0)) printf("%s: Error disconnecting Interrupt\n",__FUNCTION__); #endif tiIntCount = 0; tiAckCount = 0; tiDoAck = 1; /* Set Vector and Level */ if((vector < 0xFF)&&(vector > 0x40)) { tiIntVec = vector; } else { tiIntVec = TI_INT_VEC; } TILOCK; vmeWrite32(&TIp->intsetup, (tiIntLevel<<8) | tiIntVec ); TIUNLOCK; switch (tiReadoutMode) { case TI_READOUT_TS_POLL: case TI_READOUT_EXT_POLL: break; case TI_READOUT_TS_INT: case TI_READOUT_EXT_INT: #ifdef VXWORKS intConnect(INUM_TO_IVEC(tiIntVec),tiInt,arg); #else status = vmeIntConnect (tiIntVec, tiIntLevel, tiInt,arg); if (status != OK) { printf("%s: vmeIntConnect failed with status = 0x%08x\n", __FUNCTION__,status); return(ERROR); } #endif break; default: printf("%s: ERROR: TI Mode not defined (%d)\n", __FUNCTION__,tiReadoutMode); return ERROR; } printf("%s: INFO: Interrupt Vector = 0x%x Level = %d\n", __FUNCTION__,tiIntVec,tiIntLevel); if(routine) { tiIntRoutine = routine; tiIntArg = arg; } else { tiIntRoutine = NULL; tiIntArg = 0; } return(OK); } /** * @ingroup IntPoll * @brief Disable interrupts or kill the polling service thread * * * @return OK if successful, otherwise ERROR */ int tiIntDisconnect() { #ifndef VXWORKS int status; void *res; #endif if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(tiIntRunning) { logMsg("tiIntDisconnect: ERROR: TI is Enabled - Call tiIntDisable() first\n", 1,2,3,4,5,6); return ERROR; } INTLOCK; switch (tiReadoutMode) { case TI_READOUT_TS_INT: case TI_READOUT_EXT_INT: #ifdef VXWORKS /* Disconnect any current interrupts */ sysIntDisable(tiIntLevel); if((intDisconnect(tiIntVec) !=0)) printf("%s: Error disconnecting Interrupt\n",__FUNCTION__); #else status = vmeIntDisconnect(tiIntLevel); if (status != OK) { printf("vmeIntDisconnect failed\n"); } #endif break; case TI_READOUT_TS_POLL: case TI_READOUT_EXT_POLL: #ifndef VXWORKS if(tipollthread) { if(pthread_cancel(tipollthread)<0) perror("pthread_cancel"); if(pthread_join(tipollthread,&res)<0) perror("pthread_join"); if (res == PTHREAD_CANCELED) printf("%s: Polling thread canceled\n",__FUNCTION__); else printf("%s: ERROR: Polling thread NOT canceled\n",__FUNCTION__); } #endif break; default: break; } INTUNLOCK; printf("%s: Disconnected\n",__FUNCTION__); return OK; } /** * @ingroup IntPoll * @brief Connect a user routine to be executed instead of the default * TI interrupt/trigger latching acknowledge prescription * * @param routine Routine to call * @param arg argument to pass to routine * @return OK if successful, otherwise ERROR */ int tiAckConnect(VOIDFUNCPTR routine, unsigned int arg) { if(routine) { tiAckRoutine = routine; tiAckArg = arg; } else { printf("%s: WARN: routine undefined.\n",__FUNCTION__); tiAckRoutine = NULL; tiAckArg = 0; return ERROR; } return OK; } /** * @ingroup IntPoll * @brief Acknowledge an interrupt or latched trigger. This "should" effectively * release the "Busy" state of the TI. * * Execute a user defined routine, if it is defined. Otherwise, use * a default prescription. */ void tiIntAck() { int resetbits=0; if(TIp == NULL) { logMsg("tiIntAck: ERROR: TI not initialized\n",0,0,0,0,0,0); return; } if (tiAckRoutine != NULL) { /* Execute user defined Acknowlege, if it was defined */ TILOCK; (*tiAckRoutine) (tiAckArg); TIUNLOCK; } else { TILOCK; tiDoAck = 1; tiAckCount++; resetbits = TI_RESET_BUSYACK; if(!tiReadoutEnabled) { /* Readout Acknowledge and decrease the number of available blocks by 1 */ resetbits |= TI_RESET_BLOCK_READOUT; } if(tiDoSyncResetRequest) { resetbits |= TI_RESET_SYNCRESET_REQUEST; tiDoSyncResetRequest=0; } vmeWrite32(&TIp->reset, resetbits); tiNReadoutEvents = 0; TIUNLOCK; } } /** * @ingroup IntPoll * @brief Enable interrupts or latching triggers (depending on set TI mode) * * @param iflag if = 1, trigger counter will be reset * * @return OK if successful, otherwise ERROR */ int tiIntEnable(int iflag) { #ifdef VXWORKS int lock_key=0; #endif if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return(-1); } TILOCK; if(iflag == 1) { tiIntCount = 0; tiAckCount = 0; } tiIntRunning = 1; tiDoAck = 1; tiNeedAck = 0; switch (tiReadoutMode) { case TI_READOUT_TS_POLL: case TI_READOUT_EXT_POLL: #ifndef VXWORKS tiStartPollingThread(); #endif break; case TI_READOUT_TS_INT: case TI_READOUT_EXT_INT: #ifdef VXWORKS lock_key = intLock(); sysIntEnable(tiIntLevel); #endif printf("%s: ******* ENABLE INTERRUPTS *******\n",__FUNCTION__); vmeWrite32(&TIp->intsetup, vmeRead32(&TIp->intsetup) | TI_INTSETUP_ENABLE ); break; default: tiIntRunning = 0; #ifdef VXWORKS if(lock_key) intUnlock(lock_key); #endif printf("%s: ERROR: TI Readout Mode not defined %d\n", __FUNCTION__,tiReadoutMode); TIUNLOCK; return(ERROR); } vmeWrite32(&TIp->runningMode,0x71); TIUNLOCK; /* Locks performed in tiEnableTriggerSource() */ taskDelay(30); tiEnableTriggerSource(); #ifdef VXWORKS if(lock_key) intUnlock(lock_key); #endif return(OK); } /** * @ingroup IntPoll * @brief Disable interrupts or latching triggers * */ void tiIntDisable() { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return; } tiDisableTriggerSource(1); TILOCK; vmeWrite32(&TIp->intsetup, vmeRead32(&TIp->intsetup) & ~(TI_INTSETUP_ENABLE)); vmeWrite32(&TIp->runningMode,0x0); tiIntRunning = 0; TIUNLOCK; } /** * @ingroup Status * @brief Return current readout count */ unsigned int tiGetIntCount() { unsigned int rval=0; TILOCK; rval = tiIntCount; TIUNLOCK; return(rval); } /** * @ingroup Status * @brief Return current acknowledge count */ unsigned int tiGetAckCount() { unsigned int rval=0; TILOCK; rval = tiAckCount; TIUNLOCK; return(rval); } /** * @ingroup Status * @brief Return status of Busy from SWB * @param pflag * - >0: Print to standard out * @return * - 1: Busy * - 0: Not Busy * - -1: Error */ int tiGetSWBBusy(int pflag) { unsigned int rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; rval = vmeRead32(&TIp->busy) & (TI_BUSY_SWB<<16); TIUNLOCK; if(pflag) { printf("%s: SWB %s\n", __FUNCTION__, (rval)?"BUSY":"NOT BUSY"); } return rval; } /** * @ingroup Status * @brief Return BUSY counter for specified Busy Source * @param busysrc * - 0: SWA * - 1: SWB * - 2: P2 * - 3: FP-FTDC * - 4: FP-FADC * - 5: FP * - 6: Unused * - 7: Loopack * - 8-15: Fiber 1-8 * @return * - Busy counter for specified busy source */ unsigned int tiGetBusyCounter(int busysrc) { unsigned int rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; if(busysrc<7) rval = vmeRead32(&TIp->busy_scaler1[busysrc]); else rval = vmeRead32(&TIp->busy_scaler2[busysrc-7]); TIUNLOCK; return rval; } /** * @ingroup Status * @brief Print the BUSY counters for all busy sources * @return * - OK if successful, otherwise ERROR; */ int tiPrintBusyCounters() { unsigned int counter[16]; const char *scounter[16] = { "SWA ", "SWB ", "P2 ", "FP-FTDC", "FP-FADC", "FP ", "Unused ", "Loopack", "Fiber 1", "Fiber 2", "Fiber 3", "Fiber 4", "Fiber 5", "Fiber 6", "Fiber 7", "Fiber 8" }; int icnt=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; for(icnt=0; icnt<16; icnt++) { if(icnt<7) counter[icnt] = vmeRead32(&TIp->busy_scaler1[icnt]); else counter[icnt] = vmeRead32(&TIp->busy_scaler2[icnt-7]); } TIUNLOCK; printf("\n\n"); printf(" Busy Counters \n"); printf("--------------------------------------------------------------------------------\n"); for(icnt=0; icnt<16; icnt++) { printf("%s 0x%08x (%10d)\n", scounter[icnt], counter[icnt], counter[icnt]); } printf("--------------------------------------------------------------------------------\n"); printf("\n\n"); return OK; } /** * @ingroup Config * @brief Turn on Token out test mode * @sa tiSetTokenOutTest * @return OK if successful, otherwise ERROR */ int tiSetTokenTestMode(int mode) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; if(mode) vmeWrite32(&TIp->vmeControl, vmeRead32(&TIp->vmeControl) | (TI_VMECONTROL_TOKEN_TESTMODE)); else vmeWrite32(&TIp->vmeControl, vmeRead32(&TIp->vmeControl) & ~(TI_VMECONTROL_TOKEN_TESTMODE)); TIUNLOCK; return OK; } /** * @ingroup Config * @brief Set the level of the token out signal * @param level * - >0: High * - 0: Low * @sa tiSetTokenTestMode * @return OK if successful, otherwise ERROR */ int tiSetTokenOutTest(int level) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; if(level) vmeWrite32(&TIp->vmeControl, vmeRead32(&TIp->vmeControl) | (TI_VMECONTROL_TOKENOUT_HI)); else vmeWrite32(&TIp->vmeControl, vmeRead32(&TIp->vmeControl) & ~(TI_VMECONTROL_TOKENOUT_HI)); printf("%s: vmeControl = 0x%08x\n",__FUNCTION__,vmeRead32(&TIp->vmeControl)); TIUNLOCK; return OK; } /* Module TI Routines */ int tiRocEnable(int roc) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if((roc<1) || (roc>8)) { printf("%s: ERROR: Invalid roc (%d)\n", __FUNCTION__,roc); return ERROR; } TILOCK; vmeWrite32(&TIp->rocEnable, (vmeRead32(&TIp->rocEnable) & TI_ROCENABLE_MASK) | TI_ROCENABLE_ROC(roc-1)); TIUNLOCK; return OK; } int tiRocEnableMask(int rocmask) { if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } if(rocmask>TI_ROCENABLE_MASK) { printf("%s: ERROR: Invalid rocmask (0x%x)\n", __FUNCTION__,rocmask); return ERROR; } TILOCK; vmeWrite32(&TIp->rocEnable, rocmask); TIUNLOCK; return OK; } int tiGetRocEnableMask() { int rval=0; if(TIp == NULL) { printf("%s: ERROR: TI not initialized\n",__FUNCTION__); return ERROR; } TILOCK; rval = vmeRead32(&TIp->rocEnable) & TI_ROCENABLE_MASK; TIUNLOCK; return rval; } /* Functions for testing */ int tiCheckFiberSyncDelay(){ unsigned int syncDelay = 0; int delta = -10; TILOCK; syncDelay = vmeRead32(&TIp->fiberSyncDelay); TIUNLOCK; delta = (syncDelay & 0xFF00FF00) - (sasha_syncDelay_write & 0xFF00FF00); printf("%s: TI fiberSyncDelay register. Write = 0x%X, Read = 0x%X, Delta = 0x%X \n", __FUNCTION__, sasha_syncDelay_write, syncDelay, delta); return delta; }