/* **++ ** FACILITY: ** Distant data U slave processor user routine for DSSD at FMA w/ ROT TARG ** ** ABSTRACT: ** evtuser.c - This file is a skeleton which can be filled in ** to tailor the data acquisition slave for user ** experiments. The tailorable routines are: ** usrini - One time user initialization when system starts. ** usrbegin - User special begin run processing ** usrresume - User special resume run processing ** usrgetevt - Acquire a physics event. ** usrgetmax - Return the maximum number of words in an ** event (MUST be a correct upper bound). ** usrrdscl - Read scalers. ** userper1 - User special actions called at the frequency ** with which snapshot scalers are read out. ** userper2 - User special actions called at the frequency ** with which taped scalers are read. ** usrend - User special end run processing. ** usrpause - User special pause run handling. ** usrtrig1 - User trigger 1. ** usrtrig2 - Process user trigger 2. ** ** For many cases, the default processing performed by ** all but usrgetevt and usrgetmax is sufficient, nonetheless, ** some special experiments may have special requirements. ** See the comment headers of each routine for more details. ** ** It may be that the user will need to make use of some ** of the settable parameters (that's what there here for ** after all). These are accessable as the arrays: ** ** userints[0]..userints[NUMIPAR] - Integer parameters ** userflags[0]..userflags[NUMFPAR] - Boolean flag parameters ** userfloats[0]..userfloats[NUMRPAR]- Floating point params. ** AUTHORS: ** Ron Fox, and you ** ** CREATION DATE: 25-Aug-1988 ** MODIFIED: 27-Feb-1995 (DJB) **-- **/ /* ** INCLUDE FILES /kt/ do not modify this sequence of ifdefs and includes **/ #if CPU == MICROPROJECT #define VME16 0 #endif #include "types.h" #include "slvshared.h" #include "vme.h" /* Define VME access */ #include "psosdef.h" #include "evpool.h" #include "camac.h" #include "macros.h" #include "evtsevents.h" /* Event definitions. */ #include #ifdef VME16 #undef VME16 #endif #undef CAMBAS #if CPU == IRONICS #define CAMBAS 0xFA800000 #endif #if CPU == MICROPROJECT #define CAMBAS 0xFE800000 #endif /* The following macros trigger user events: */ extern union evtsevtflags actionflags; #define TRIGGER11 actionflags.flags.usertrig1 = 1 #define TRIGGER2 actionflags.flags.usertrig2 = 1 /* The following defines the interrupt vector and interrupt service rtn */ /* for the Camac BRANCH driver. */ #define CAMVEC 103 /* CAMAC vector. */ #define CAMIPL 2 /* CAMAC IPL. */ int camacisr(); /* CAMAC interrupt service rtn. */ int vmeon(); /* Enables acceptance of vme ints. */ /* ** ** The line below can be used as a simplified way to tailor ** usrgetmax. The actual maximum event length depends on the ** number of scalers as well as the sizes of various headers, ** and the maximum number of words in a physics data event. ** If you don't want to worry about all of this, and just let ** the default usrmaxevt return the maximum event size, then ** just alter the definition below to indicate the largest number ** of words that will be read out in physics data: ** */ #define STDEVTHEADER 4 /* Touch this and die. */ #define STDSCLHEADER 5 /* Touch this and die too. */ /* The typedef below defines a CAMAC register: */ typedef INT16 *CAMREG; /* Declare the cbdptr function: */ CAMREG cbdptr(); /* This defines a table of integer digits in ascii strings. */ char *digit[10] = {" 0 ", " 1 ", " 2 ", " 3 ", " 4 ", " 5 ", " 6 ", " 7 ", " 8 ", " 9 " }; #define SECOND 64 /* Number of ticks/second */ /* The definition below gives the number of branches to be initted. */ #define NUMBR 1 /* The initialized array below indicates the number of crates in each */ /* Branch. We assume the user has set the crate numbers so that each */ /* branch begins with crate 1 and there are no holes in the crate numbering */ /* scheme. */ static int syscrates[NUMBR] = { 2 }; /* /kt/ ** ** These definitions replace the standard MSU setup which includes a CAMAC ** gate generator at slot 21, a system NIM OUT at slot 20, and a CLEAR NIM ** OUT at slot 19. ** ** ** Instead, we use a Jorway 41 output register located in slot 22. The ** following macros compute the memory pointer for the different NAF ** functions -- selective set and clear, and strobe. See below for how ** to use... */ #define SYSOUTREG 16 #define SSET_SYSOUTREG CBDPTR(0,1,SYSOUTREG,0,20,CAM16) #define SCLR_SYSOUTREG CBDPTR(0,1,SYSOUTREG,0,22,CAM16) #define PULS_SYSOUTREG CBDPTR(0,1,SYSOUTREG,0,17,CAM16) /* ** The first eight outputs on the Jorway Model 41 output register are... ** The last four outputs are available for the user. Note there are 2 ** STOPPED_OUT outputs. */ #define CLRLATCH_OUT 1 #define STOPPED_OUT 6 #define EVTRD_OUT 8 #define SCLRD_OUT 16 #define NULLEVT_OUT 32 #define SYS_RESERVED1 64 #define SYS_RESERVED2 128 #define CLRDECBUSY_OUT 512 #define CLRADC_OUT 1024 /* /kt/ ** Instead of the standard MSU hardware setup, we use a Jorway 41 output ** and a gate-generator with a latch setting, hereafter called the busy-latch. ** The user provides the event trigger to both the CES VME-CAMAC interface ** and to the busy-latch to trigger event busy. The nim-out of the busy-latch ** should be or'ed with the stopped_out of the Jorway 41 to provide busy. ** The stopped_out is cleared when the system starts to acquire. The ** busy-latch is cleared after every event and when acquisition starts. */ /* This is a good place to define our user stuff: */ /*------------------------------------------------------------------------*/ /* slot assignments */ /*------------------------------------------------------------------------*/ #define SCL_SLOT 20 #define SCL_CRAT 1 #define EVTYPE 1 /* pattern register for event type (BiRa 2351) */ #define ADCPAT 1 /* which adc's fired (BiRa 2351 stuck in crate 2) */ #define PPACTDC 3 /* PPAC TDC */ #define LATCH48 17 /* Latching Scaler */ #define CAENADC 4 /* CAEN adc for monitor and PPAC */ #define ROTTAR 22 /* rotating target controller */ /* slot numbers for camac modules: recoil front 1,2,3 slot 6,7,9 in crate 1 recoil back 1,2,3 slot 10,12,13 in crate 1 decay front 1,2,3,4,5,6 slot 8,9,10,11,13,14 in crate 2 decay back 1,2,3,4,5,6 slot 15,16,18,19,20,21 in crate 2 */ static int radc[6] = {6,7,9,10,12,13}; static int dadc[12]= {8,9,10,11, 13,14,15,16, 18,19,20,21}; /*------------------------------------------------------------------------*/ /* adc channnels */ /*------------------------------------------------------------------------*/ #define DECH 4 /* ppac deltaE channel in CAEN ADC */ #define MONCH 0 /* monitor channel in CAEN ADC */ #define SILCH 5 /* silicon behind DSSD channel in CAEN ADC */ #define ELCH 6 /* LEPS energy channel in CAEN ADC */ #define TLCH 7 /* LEPS-DSSD TAC channel in CAEN ADC */ /*------------------------------------------------------------------------*/ /* bit masks */ /*------------------------------------------------------------------------*/ #define ZERO 0 /* null event */ #define DECAY 1 /* decay event */ #define IMPLANT 2 /* implant event */ #define MONITOR 4 /* monitor event */ #define SETUP 8 /* FMA setup event */ static int rec_adcpat[6] = {1,2,4,8,16,32}; /* recoils use bit 1-6 */ static int dec_adcpat[6] = {64,128,256,512,1024,2048}; /* decays use 7-12 */ /*------------------------------------------------------------------------*/ /* case definitions: where to branch for various comb. of evtype bits */ /*------------------------------------------------------------------------*/ static int branch[9] = {0,DECAY,IMPLANT,IMPLANT, MONITOR,MONITOR,MONITOR,MONITOR,SETUP}; /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** donothing - A local function with the purpose of inserting some ** time between CAMAC write/control pairs to work around ** an error in the CES board which causes that board to ** generate a bus error on the control part of that pair. **-- **/ static donothing() {} /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** usrlights - This function puts a spinning pattern of lights in the ** system crate dataway display register. The speed ** depends on what else is happening in the world. ** The pattern is governed by the ltsarray initialization ** and PATTSIZE constant. ** ** /kt/ we dont have a dataway display in slot 1, so... **-- **/ usrlights() {} /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** usrini - This function is called at power up initialization ** (When slave has just been loaded and started). It is ** called exactly once. The user should: ** ** 1. Initialize all CAMAC branch drivers. ** 2. If desired, C/Z all CAMAC crates. ** 3. Remove the inhibits from all CAMAC crates. ** 4. Program gate generator to latch mode. **-- **/ usrini() { int crate, branch; /* loop counters */ CAMREG reg; /* CAMAC pointer */ int panic(); /* 1. Initialize all CAMAC branch driver interfaces */ /* our standard initialization takes each branch */ /* driver, clears the IT interrupts, zeroes the branch */ /* and sets the interrupt masks to mask all interrupts */ for (branch = 0; branch < NUMBR; branch++) { reg = cbdptr(branch, 0, 29, 0, 0, CAM16); /* Branch CSR. */ CAMWR16(reg, (MNOX | MTO |MLAM | MIT2 | MIT4)); /* Mask interrupts */ reg = cbdptr(branch, 0, 29, 0, 4, CAM16); /* Interrupt flag reg */ CAMWR16(reg, 0); /* Clear interrupts */ reg = cbdptr(branch, 0, 29, 0, 9, CAM16); /* Branch zero reg */ CAMWR16(reg, 0); /* Zero branch */ pause_p(2); /* Wait for zero. */ } /* 2. C/Z the CAMAC crates we care to C/Z */ /* 3. Remove the inhibits from all CAMAC crates. */ /* We loop until missing or offline crates are made good */ for (branch = 0; branch < NUMBR ; branch ++) for (crate = 1; crate <= syscrates[branch]; crate++) { reg = cbdptr(branch, 0, 29, 0, 9, CAM16); /* Online mask */ while ( (CAMRD16(reg) & (1 << crate)) == 0) /* check online */ { dbgdisplay("Crate number: "); dbgdisplay(digit[crate]); dbgdisplay("is offline or missing"); dbgcrlf(); pause_p(SECOND*5); /* Try again in 5 sec */ } reg = cbdptr(branch, crate, 28, 9, 26, CAM16); CAMCTL(reg); /* C the crate. */ donothing(); reg = cbdptr(branch, crate, 28, 8, 26, CAM16); CAMCTL(reg); /* Z the crate. */ donothing(); reg = cbdptr(branch, crate, 30, 9, 24, CAM16); CAMCTL(reg); /* Remove inhibit. */ donothing(); } CAMWR16(SSET_SYSOUTREG, STOPPED_OUT); /* set stopped */ /* 5. Plug the interrupt vector for the CAMAC event trigger. */ *((INT32 *)(CAMVEC << 2)) = (INT32)camacisr; #if CPU == IRONICS /* IRONICS boards need to enable VME */ /* Interrupts on the CAMAC IPL. */ vmeon(CAMIPL); /* Enable VME interrupt reception. */ #endif /* /kt/ add whatever power-up initializations here */ } /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** usrbegin - This function is called at the beginning of each ** run. The begin run buffer is already on its way to ** the VAX. Users may inject other events into the ** event stream by calling allocevt(), filling in the event ** and doing a call to putevt(). They had damned well ** better know what they're doing if they choose to do ** this however... or they could easily crash the system. ** ** Typical tailoring that must be done at this time ** is whatever code is needed to enable the acquisition. ** This consists of the following: ** 1. Load thresholds etc. into programmable devices. ** 2. Clear devices. ** 3. Enable LAMS on devices. ** 4. Enable the event trigger interrupt. ** 5. Clear the dead time gate. ** ** This skeleton includes sample code to enable event ** trigger inputs using the Branch 1 branch driver INT2 ** input to indicate event startup. **-- **/ usrbegin() { int conreg,i,j,lt,ut,off,comthr,ped; int freq; CAMREG reg; usrini(); /* In case crates were off. */ /*-----------------------------------------------------------------------*/ /* 2. Clear all data acquisition devices and scalers. */ /*-----------------------------------------------------------------------*/ camctl(0,1,PPACTDC,3,11); /* ppac tdc */ camctl(0,1,CAENADC,0,9); /* CAEN adc */ for (i=0;i<6;i++) camctl(0,1,radc[i],3,11); /* phillips adc */ for (i=0;i<12;i++) camctl(0,2,dadc[i],0,9); /* silena adc */ CLRBIT(0,1,EVTYPE); /* clear input event reg */ CLRBIT(0,2,ADCPAT); /* clear input adcbit reg */ CLR2551(0,SCL_CRAT,SCL_SLOT); /* clear scaler */ /*-----------------------------------------------------------------------*/ /* 3. Program Modules */ /*-----------------------------------------------------------------------*/ lt=userints[4]; /* phillips */ ut=userints[5]; ped=userints[6]; /* PPAC TDC */ camwrite16(0,1,PPACTDC,0,19,7); /* write control reg */ camwrite16(0,1,PPACTDC,0,17,0); /* sel ped */ for (j=0;j<16;j++) camwrite16(0,1,PPACTDC,j,20,ped); /* write ped */ camwrite16(0,1,PPACTDC,1,17,0); /* sel lt */ for (j=0;j<16;j++) camwrite16(0,1,PPACTDC,j,20,lt); /* write lt */ camwrite16(0,1,PPACTDC,2,17,0); /* sel ut */ for (j=0;j<16;j++) camwrite16(0,1,PPACTDC,j,20,ut); /* write ut */ for (i=0;i<6;i++) /* RECOIL ADC's */ { camwrite16(0,1,radc[i],0,19,7); /* write control reg */ camwrite16(0,1,radc[i],0,17,0); /* sel ped */ for (j=0;j<16;j++) camwrite16(0,1,radc[i],j,20,ped); /* write ped */ camwrite16(0,1,radc[i],1,17,0); /* sel lt */ for (j=0;j<16;j++) camwrite16(0,1,radc[i],j,20,lt); /* write lt */ camwrite16(0,1,radc[i],2,17,0); /* sel ut */ for (j=0;j<16;j++) camwrite16(0,1,radc[i],j,20,ut); /* write ut */ } lt=userints[0]; /* silena adc */ ut=userints[1]; off=userints[2]; comthr=userints[3]; for (i=0;i<12;i++) { conreg = 0x3801 + i; /* stat reg */ camwrite16(0,2,dadc[i],14,20,conreg); camwrite16(0,2,dadc[i],9,20,comthr); /* common thresh */ for (j=0;j<8;j++) { camwrite16(0,2,dadc[i],j,17,ut); /* ut */ camwrite16(0,2,dadc[i],j+8,17,lt); /* lt */ camwrite16(0,2,dadc[i],j,20,off); /* offset */ } } lt=userints[7]; /* CAEN adc */ ut=userints[8]; conreg=userints[9]; camwrite16(0,1,CAENADC,0,17,conreg); /* reset caen contr reg */ camwrite16(0,1,CAENADC,4,17,conreg); /* since usrini is called */ camwrite16(0,1,CAENADC,6,17,conreg); /* above here and it Z's the */ camwrite16(0,1,CAENADC,7,17,conreg); /* crate which upset the CAEN */ camwrite16(0,1,CAENADC,0,20,lt); /* also do LT */ camwrite16(0,1,CAENADC,8,20,lt); camwrite16(0,1,CAENADC,12,20,lt); camwrite16(0,1,CAENADC,14,20,lt); camwrite16(0,1,CAENADC,1,20,ut); /* also do UT */ camwrite16(0,1,CAENADC,9,20,ut); camwrite16(0,1,CAENADC,13,20,ut); camwrite16(0,1,CAENADC,15,20,ut); lt=userints[10]; /* 48 bit scaler freq (0-7) */ camwrite16(0,1,LATCH48,0,17,lt); /* set freq */ /*-----------------------------------------------------------------------*/ /* 4. Enable the event trigger interrupt. */ /*-----------------------------------------------------------------------*/ reg = cbdptr(0, 0, 29, 0, 4, CAM16); /* Interrupt flag register. */ CAMWR16(reg, 0); /* Clear pending interrupts. */ reg = cbdptr(0, 0, 29, 0, 0, CAM16); /* Branch CSR. */ CAMWR16(reg, (MNOX | MTO |MLAM | MIT4)); /* Allow IT2 */ donothing(); actionflags.flags.takeevent = 0; /* Clear take event flag.... */ donothing(); CAMWR16(PULS_SYSOUTREG, CLRLATCH_OUT); /* clear Busy */ donothing(); CAMWR16(SCLR_SYSOUTREG, STOPPED_OUT); /* indicate acquiring */ } /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** usrresume - This function is called whenever a run is to be ** resumed after a pause. The routine is called after ** the resume buffer is already on it's way to the ** VAX. Users may inject other events into the event stream ** by calling allocevt(), filling in the event and doing a ** call to putevt(). They had damned well better know what ** they're doing if they do this... or they could easily ** crash the system. ** Typical actions on resums are identical to those ** done at usrbegin. The default action of this routine ** is therefore just to call usrbegin(). **-- **/ usrresume() { usrbegin(); } /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** usrgetevt - This routine is called when an event trigger is ** detected. The user is handed a pointer to a buffer ** which is gaurenteed to be large enough to hold the ** largest event that could be taken (assuming the ** user was honest in tailoring usrgetmax... if they're ** dishonest, then system crashes are almost certain). ** The following is typically done to read out an event: ** ** 1. Read a pattern register from CAMAC and put it in ** the buffer. ** 2. Based on the pattern register, compute the set ** of required LAMS, wait for them for some period ** of time in excess of the conversion time of the ** devices. If all LAMS are not in in time, then ** declare a LAM timeout. ** 3. Read out the event, and clear the digitizers. ** 4. Clear the computer busy signal and return the number ** of words read. ** Note that the user must return the number of words ** that were actually read out. This must be ** accurate. ** Note If zero or less is returned from this procedure, then ** no event is put in the buffer. This allows filtering ** of events to be done at this level. ** ** FORMAL PARAMETERS: ** ** buffer - Pointer to the event buffer. ** ** FUNCTION VALUE: ** ** words actually read from CAMAC. Include all words that were ** put in the buffer (bit registers lam masks the works. This word ** count will be prepended to the event as seen by the VAX so that ** the whole thing will look like this: ** ** +--------------------------------+ ** | word count returned from here | ** +--------------------------------+ ** | All the words you read | ** | into the buffer here. | ** + ... + **-- **/ /* --------------------------------------------------------------------------- Event program for new electronics for 48x48 DSSD --------------------------------------------------------------------------- electronics used: Phillips 7164 Peak ADC Recoils in DSSD Phillips 7166 TDC PPAC R,L,U,D and Si TOF Silena 4418/V Peak ADC Decays in DSSD CAEN Peak ADC Monitor and PPAC DE BiRa 2351 Input Register ---------------------- NOTE: BiRa input register requires the strobe to PRECEDE the signal. It is read using F(2).A(0). After first readout the data remains in the memory of BiRa module, but new readouts give Q=0 response (only the first F(2) read gives Q=1). This is utilised to check if there was a second strobe or not. ----------------------- Silicon detector (behind dssd) is read only when there is a decay event. ------------------------ PPAC dE and ppac-dssd time of flight are read also for decay events. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EVTYPE bit 1=1 decay (No PPAC) bit 2=1 recoil implantation bit 3=1 monitor event bit 4=1 FMA setup (read just FMA) event structure is: for implantation event: EVTYPE 48 BIT SCALER - low 16 bits - middle - high rotating target encoder Delta_E (read early to allow for fast decay) ADC HIT PATTERN (which ADC's to read out) RF1 pattern word and data for strip #'s 1-16 RF2 " 17-32 RF3 " 33-48 RB1 " 1 -16 RB2 " 17-32 RB3 " 33-48 Right Left Up Down TOF (ppac-dssd) TOF (ppac-rf) for decay event: EVTYPE (for fast decay event, this just a 1, not a real pattern) 48 BIT SCALER - low 16 bits - middle - high ADC HIT PATTERN (which ADC's to read out) DF1 HEADER WORD, PATTERN WORD, data for strips 1-8 DF2 9-16 DF3 17-24 DF4 25-32 DF5 33-40 DF6 41-48 DB1 HEADER WORD, PATTERN WORD, data for strips 1-8 DB2 9-16 DB3 17-24 DB4 25-32 DB5 33-40 DB6 41-48 PPAC DE xxx E Silicon behind DSSD xxx t Silicon behind DSSD LEPS Energy LEPS-DSSD TAC for FMA alone (i.e. setup): EVTYPE rotating target encoder Right Left Up Down TOF (PPAC-DSSD) PPAC DE TOF (PPAC-RF) for monitor event: EVTYPE 48 BIT SCALER - low 16 bits - middle - high Emon rotating target encoder */ /* redefine this to the largest possible event size in words */ #define EVENT_MAXWORDS 500 int usrgetevt(buffer) INT16 *buffer; /* Buffer pointer is treated as a word. */ { int evtsiz,i,j,k,type; int epat,adcpat; int mpat; INT16 *bufpt; /* moving pointer */ /*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/ bufpt = (INT16*) buffer; CAMWR16(SSET_SYSOUTREG,EVTRD_OUT); /* indicate reading */ evtsiz = 0; /* reset evtsiz */ /*------------------------------------------------------------------------*/ /* EVENT PATTERN REGISTER AND CLOCK */ /*------------------------------------------------------------------------*/ epat=camread16(0,1,EVTYPE,0,2); /* read event type */ if (epat > 0) /* check for any data */ { putbufw(epat); /* and put in buffer */ /*--------------------------------------------------------------------*/ /* DETERMINE EVENT TYPE AND READ OUT APPROPRIATE BLOCK */ /*--------------------------------------------------------------------*/ if (epat <= 8) type=branch[epat]; else type=0; switch(type) /* read only those modules */ { /*--------------------------------------------------------------------*/ /* FMA SETUP EVENT */ /*--------------------------------------------------------------------*/ case SETUP: rdtobuf16(0,1,ROTTAR,0,4); /* rot target position */ rdtobuf16(0,1,PPACTDC,1,0); /* right */ rdtobuf16(0,1,PPACTDC,3,0); /* left */ rdtobuf16(0,1,PPACTDC,5,0); /* up */ rdtobuf16(0,1,PPACTDC,7,0); /* down */ rdtobuf16(0,1,PPACTDC,9,0); /* si tof */ rdtobuf16(0,1,CAENADC,DECH,2); /* DE */ break; /*--------------------------------------------------------------------*/ /* MONITOR EVENT */ /*--------------------------------------------------------------------*/ case MONITOR: rdtobuf16(0,1,LATCH48,0,0); /* read time-lo 16 */ rdtobuf16(0,1,LATCH48,1,0); /* read time-mid 16*/ rdtobuf16(0,1,LATCH48,2,0); /* read time-hi 16*/ rdtobuf16(0,1,CAENADC,MONCH,2); /* read EMON */ rdtobuf16(0,1,ROTTAR,0,4); /* rot target position */ break; /*--------------------------------------------------------------------*/ /* RECOIL EVENT */ /*--------------------------------------------------------------------*/ case IMPLANT: rdtobuf16(0,1,LATCH48,0,0); /* read time-lo 16 */ rdtobuf16(0,1,LATCH48,1,0); /* read time-mid 16*/ rdtobuf16(0,1,LATCH48,2,0); /* read time-hi 16*/ rdtobuf16(0,1,ROTTAR,0,4); /* rot target position */ rdtobuf16(0,1,CAENADC,DECH,2); /* DE */ READBIT(0,2,ADCPAT,0,2,adcpat); /* read adc hit pattern */ /* free up decay busy, now that DE is read and cleared */ CAMWR16(PULS_SYSOUTREG, CLRDECBUSY_OUT); donothing(); for (i=0; i<6; i++) /* loop over 6 adc's*/ { if ((adcpat & rec_adcpat[i]) == rec_adcpat[i]) /* check bit */ { rdtobuf16(0,1,radc[i],1,6); /* pattern word for recoil adc */ qstoptobuf(0,1,radc[i],0,4); /* block read till no data */ } } rdtobuf16(0,1,PPACTDC,1,0); /* right */ rdtobuf16(0,1,PPACTDC,3,0); /* left */ rdtobuf16(0,1,PPACTDC,5,0); /* up */ rdtobuf16(0,1,PPACTDC,7,0); /* down */ rdtobuf16(0,1,PPACTDC,9,0); /* si tof */ rdtobuf16(0,1,PPACTDC,11,0); /* rf-ppac tof */ epat=camread16(0,1,EVTYPE,0,2); /* read evtype again */ if ( qtst(0) && ((epat & 1) == 1) ) /* did decay occur */ putbufw(1); else { putbufw(0); break; } /*--------------------------------------------------------------------*/ /* DECAY EVENT */ /*--------------------------------------------------------------------*/ case DECAY: rdtobuf16(0,1,LATCH48,0,0); /* read time-lo 16 */ rdtobuf16(0,1,LATCH48,1,0); /* read time-mid 16*/ rdtobuf16(0,1,LATCH48,2,0); /* read time-hi 16*/ READBIT(0,2,ADCPAT,0,2,adcpat); /* read adc hit pattern */ j=-2; for (i=0; i<6; i++) /* loop over 6 bits for 12 adc's*/ { j=j+2; k=j+1; if ((adcpat & dec_adcpat[i]) != 0 ) /* check bit */ { qstoptobuf(0,2,dadc[j],0,2);/* block read till no data */ qstoptobuf(0,2,dadc[k],0,2);/* block read till no data */ } } rdtobuf16(0,1,CAENADC,DECH,2); /* PPAC DE for veto purposes */ /* rdtobuf16(0,1,CAENADC,SILCH,2); */ /* Silicon behind DSSD */ /* rdtobuf16(0,1,CAENADC,TSICH,2); */ /* t Silicon behind DSSD */ rdtobuf16(0,1,CAENADC,ELCH,2); /* E LEPS behind DSSD */ rdtobuf16(0,1,CAENADC,TLCH,2); /* t LEPS behind DSSD */ break; /*--------------------------------------------------------------------*/ /* default case, none of the above */ /*--------------------------------------------------------------------*/ default: /* nothing happened */ break; } /* end of switch */ /*--------------------------------------------------------------------*/ /* end of readout */ /*--------------------------------------------------------------------*/ putbufw(0xDEAD); /*an end of event marker to make dumps readable */ } /* end of if block checking epat */ /*--------------------------------------------------------------------*/ /* compute evtsiz in words */ /*--------------------------------------------------------------------*/ evtsiz = bufpt - buffer; /*--------------------------------------------------------------------*/ /* clear modules */ /*--------------------------------------------------------------------*/ CAMWR16(PULS_SYSOUTREG,CLRADC_OUT); /* clear adc's */ donothing(); camctl(0,1,PPACTDC,3,11); /* Phillips tdc */ CLRBIT(0,1,EVTYPE); /* clear input event reg */ CLRBIT(0,2,ADCPAT); /* clear input adcbit reg */ /* Event rejection code goes here. Reject an event by setting */ /* evtsiz = 0 */ if (evtsiz == 0) { CAMWR16(PULS_SYSOUTREG, NULLEVT_OUT); /* indicate event rejected */ donothing(); } CAMWR16(PULS_SYSOUTREG, CLRLATCH_OUT); /* clear busy-latch */ donothing(); CAMWR16(SCLR_SYSOUTREG,EVTRD_OUT); /* indicate done */ donothing(); return evtsiz; } /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** usrgetmax - This function should return the maximum number ** of words which can be put into an event of any kind. ** By default, we compute this from what we know about ** physics event maximum sizes, the number of scalers read, ** and the sizes of the various fixed sized events. ** ** IMPLICIT INPUTS: ** ** MAXPHYSICS - Maximum size of physics data. ** STDEVTHEADER - Event pool header size. ** STDSCLHEADER - Event pool scaler event header. ** numscalers - Number of scalers being read out. ** **-- **/ int usrgetmax() { int nwds1, nwds2; if (EVENT_MAXWORDS < 0 ) die(); nwds1 = EVENT_MAXWORDS + STDEVTHEADER; /* Biggest physics event. */ nwds2 = STDSCLHEADER + STDEVTHEADER + (numscalers << 1); /* Biggest scaler evt. */ /* Return the largest of the two sizes. */ if (nwds1 > nwds2) return nwds1; else return nwds2; } /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** usrrdscl - This function reads out a scaler event. The layers of ** code above us take care of the summing and interval ** computations needed to deal with snapshot scalers and ** similar nonsense. The only thing we need to do is: ** ** 1. If desired, indicated scaler readout in progress. ** 2. Read and clear the scalers into the event. ** 3. If 1. done, then indicate scaler readout completed. ** 4. Return the number of scaler words actually read ** This return value indicates the actual number ** of words that will be considered part of the ** event. Normally, this is just 2 * num_scalers ** However, if the user wants to inject some other ** non summed, non scaler data into scaler buffers, ** making nwds larger makes this possible. Upper layers ** will ignore these words, but pass them on to the ** VAX. ** NOTE: Scalers are normally 32 bits long and therefore ** require 2 words per scaler. ** ** FORMAL PARAMETERS: ** ** buffer - Pointer to a buffer guarenteed to be large enough to hold your ** scalers, assuming usrgetmax was coded honestly. ** numscalers - Number of scalers to read out. ** ** ** FUNCTION VALUE: ** ** The number of WORDS actually use. Normally this is ** numscalers << 1 **-- **/ int usrrdscl(bufpt, numscalers) WORD *bufpt; int numscalers; { INT32 *_sbufpt; _sbufpt = (INT32*) bufpt; CAMWR16(SSET_SYSOUTREG, SCLRD_OUT); /* indicate scaler readout */ donothing(); /* read scalers, then clear it */ READALL2551(0,SCL_CRAT,SCL_SLOT); CLR2551(0,SCL_CRAT,SCL_SLOT); CAMWR16(SCLR_SYSOUTREG, SCLRD_OUT); /* indicate scaler readout end */ donothing(); /*-------------------------------END USER CODE ---------------------------*/ return (bufpt - (WORD *)_sbufpt); } /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** usrper1 - This function is called at the same frequency that ** snap shot scalers are called and is a mechanism for ** the user to take periodic arbitrary actions. ** The user can inject data into the event stream at this point ** by calling allocevt(), filling in the event, and calling ** putevt(), but if you do you had better know what you're ** doing or you can easily crash the system. ** Other things that could be done here would be to periodically ** refresh/monitor programmable devices or whatever else you feel ** like doing. ** NOTE: Unless the programmer explicitly inhibits event ** acquisition, the system is live at this point. **-- **/ usrper1() { } /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** usrper2 - This function is called at the same frequency that ** scalers are called and is a mechanism for ** the user to take periodic arbitrary actions. ** The user can inject data into the event stream at this point ** by calling allocevt(), filling in the event, and calling ** putevt(), but if you do you had better know what you're ** doing or you can easily crash the system. ** Other things that could be done here would be to periodically ** refresh/monitor programmable devices or whatever else you feel ** like doing. ** NOTE: Unless the programmer explicitly inhibits event ** acquisition, the system is live at this point. **-- **/ usrper2() { } /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** usrend - This function is called to allow user specific actions ** at the end of a run. The procedure is called before the ** end run scalers and end run buffer are constructed and ** sent to the vax. Thus it's possible to inject events ** into the event stream at this point and they'll wind ** up on the tape file corresponding to the run being ended. ** All caveats about knowing what you're doing apply here. ** Normally, you must: ** ** 1. Disable event trigger interrupts. ** 2. Turn off LAMs on acquisition devices. **-- **/ usrend() { CAMREG reg; /* indicate stopped; STOPPED_OUT is OR'ed with busy-latch to block front-end electronics. */ CAMWR16(SSET_SYSOUTREG, STOPPED_OUT); /* 2. Turn off event trigger interrupts. */ reg = cbdptr(0, 0, 29, 0, 0, CAM16); /* Branch CSR. */ CAMWR16(reg, (MNOX | MTO |MLAM | MIT2 | MIT4)); /* Mask interrupts */ } /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** usrpause - This function is called to allow users specific actions ** when runs pause. Like usrend, it's called before the ** pause scaler buffer and pause buffer are formatted ** and sent to the VAX. Therefore, any data added to ** the event stream at this point will appear on event ** tapes before the pause buffer. ** Normally, the actions performed here are the same ** as for end of runs, so the default action is to ** call usrend() **-- **/ usrpause() { usrend(); } /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** usrupdate - This function is called whenever the master ** issues an update request. The update request ** is intended to be used by systems which want to ** batch a bunch of parameter changes and then apply ** them all in a bunch. **-- **/ usrupdate() { } /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** usrnewint - Is called to indicate that a SET INTEGER command ** has been processed. ** ** FORMAL PARAMETERS: ** ** int intnum - Number of the parameter modified. ** int oldval - Old value of the parameter. **-- **/ usrnewint(intnum, oldval) int intnum; int oldval; { } /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** usrnewreal - This function is called when a SET REAL command has ** been processed. ** ** FORMAL PARAMETERS: ** ** int floatnum - The floating point parameter number that changed ** double oldfloat - The previous value of the floating point value. **-- **/ usrnewreal(floatnum, oldfloat) int floatnum; double oldfloat; { } /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** usrnewflag - This routine is called when a SET FLAG command is ** executed. ** ** FORMAL PARAMETERS: ** ** int flagnum - Number of flag parameter. ** int oldflag - Previous value of flag parameter. **-- **/ usrnewflag(flagnum, oldflag) int flagnum; int oldflag; { } /*------------------------------------------------------------------------*/ /* This section needs only to be filled if the user is implementing */ /* slave command processing. */ /* Below is the definition of a function to allow the slave command */ /* processor to pass a reply data block back to the master at the end */ /* of command processing. The size of this data is limited to 64bytes */ /* at present. However, there's nothing to stop a single master command */ /* to invoke more than one slave command should more data need to be passed */ /* the main point to keep in mind is that the command mailbox region is meant */ /* for low bandwidth communications. */ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** setreturn - This function sets data into the CMDDAT part of the ** register area. This function is used by command ** operations which return data to the master. ** ** FORMAL PARAMETERS: ** ** INT8 *data - Pointer to the data to send to master. ** int count - Number of bytes to move, at most 64. ** ** **-- **/ extern INT16 setreturn; /*** setreturn(data, count); ***/ /* Newer compilers don't like this declaration */ /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** slvusrcmd - This function processes user slave commands. ** ** FORMAL PARAMETERS: ** ** int code - The command code sent from the master. ** INT8 *data - Pointer to the command data. ** ** FUNCTION VALUE: ** ** 0 - If the command can be successfully handled else ** 1 - If the command cannot be handled. ** **-- **/ int slvusrcmd(code, data) int code; INT8 *data; { return 0; } /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** usrtrig1 - This processes user 1 triggers. **-- */ usrtrig1 () { } /*------------------------------------------------------------------------*/ /* **++ ** FUNCTIONAL DESCRIPTION: ** ** usrtrig2 - This processes user2 triggers. **-- */ usrtrig2 () { }