00001 #!/usr/local/bin/python 00002 # 00003 # Copyright 2004 00004 # by 00005 # The Board of Trustees of the 00006 # Leland Stanford Junior University. 00007 # All rights reserved. 00008 # 00009 00010 __facility__ = "Online" 00011 __abstract__ = "GLAST LAT Coincidence based Trigger System Interface classes" 00012 __author__ = "Jim Panetta <panetta@slac.stanford.edu> SLAC - GLAST I&T" 00013 __date__ = "2/14/04" 00014 __version__ = "$Revision: 2.9 $" 00015 __release__ = "$Name: R04-12-00 $" 00016 __credits__ = "SLAC" 00017 00018 import LATTE.copyright_SLAC 00019 00020 """TrgGem: This file implements the hardware register access to the GEM""" 00021 00022 from TrgGemRegisters import TrgGemRegisters 00023 from TrgGemCounters import * 00024 from LATTE.database.gGEM import GGEM 00025 00026 class TrgGem(TrgGemRegisters): 00027 """\brief Trigger Global Trigger Electronics Module Interface class definition 00028 This class implements the hardware register access to the GEM 00029 """ 00030 __SOLICIT_MASK = 0x40 00031 00032 def __init__(self): 00033 """\brief TrgGem constructor 00034 """ 00035 TrgGemRegisters.__init__(self) 00036 00037 self.__condValue = None 00038 self.__glt = None 00039 00040 def GEM(self, glt = None): 00041 """\brief GEM function 00042 \param glt: a GGEM object 00043 \return a GGEM object 00044 00045 This function sets and/or the GGEM hardware implementation used by 00046 TrgGem. 00047 """ 00048 if ( glt is not None ): 00049 if ( not isinstance(glt,GGEM) ): 00050 raise AssertionError, "the glt object passed is not a GGEM" 00051 self.__glt = glt 00052 self.__epuaddr = glt.getEPUaddr() 00053 return self.__glt 00054 00055 def __commit(self): 00056 """\brief Private commit function 00057 00058 This function commits the configuration defined by this 00059 TrgGem object to the hardware. It does *all* the registers. 00060 """ 00061 gem = self.GEM() 00062 00063 # set up the counter accesses and reset them 00064 self.__triggerCounters = TrgGemTriggerCounters(gem) 00065 self.__tileCounters = TrgGemTileCounters(gem) 00066 self.__cnoCounters = TrgGemCnoCounters(gem) 00067 self.__cmdCounters = TrgGemCmdCounters(gem) 00068 self.__eventCounter = TrgGemEventCounter(gem) 00069 self.__ppsTimer = TrgGemPPSTimer(gem) 00070 self.__triggerCounters.reset() 00071 self.__tileCounters.reset() 00072 self.__cnoCounters.reset() 00073 self.__cmdCounters.reset() 00074 self.__eventCounter.reset() 00075 00076 # Pass the GEM to TrgGemSequence and TrgGemPeriodicCondition objects 00077 self.sequence()._TrgGemSequence__setGEM(gem) 00078 self.periodicCondition()._TrgGemPeriodicCondition__setGEM(gem) 00079 00080 # set all engine destination addresses. 00081 # Because engines can't have a real HW dependence, this is done by cheating: 00082 # replace each instance of the TrgEngineRequest.destination function 00083 # with a local private function. 00084 for engineNo in range(TrgObject.ENGINE_NUMBER_MAX + 1): 00085 self.engines().engine(engineNo).request().destination = self.__getDestinationFromEPU 00086 00087 gemw = gem.downGEMW() 00088 gemw.WINDOW_OPEN_MASK = 0 # all disabled at startup by default 00089 00090 # print "setting command registers" 00091 # Command registers (GEMC) 00092 gemc = gem.downGEMC() 00093 gemc.CONFIGURATION = self.configurationRegister() 00094 # NEVER EVER touch the ADDRESS register. Ever. Really. 00095 gemc.PERIODIC_MODE = self.periodicModeRegister() 00096 gemc.PERIODIC_LIMITS = self.periodicLimitRegister() 00097 gemc.PERIODIC_RATE = self.periodicRateRegister() 00098 # gemc.SEQUENCE = self.sequenceRegister() # commented out to set sequence in rcStartRun 00099 gemc.CR_STATISTICS = 0 # Always reset statistics 00100 gemc.EVENT_STATISTICS = 0 # Always reset statistics 00101 00102 # print "setting TAM" 00103 # TAM generator (GEMMG) 00104 gemmg = gem.downGEMMG() 00105 if gemmg is None: 00106 raise RuntimeError, "GEM has no GEMMG" 00107 regList = gemmg.regs.values() # get the list of registers 00108 for reg in regList: 00109 if reg.size() > 0 and not reg.isDeprecated(): 00110 reg.set(self.templateRegister(reg.id())) 00111 00112 # print "setting statistics" 00113 # Statistics registers (GEMST) 00114 gemst = gem.downGEMST() 00115 if gemst is None: 00116 raise RuntimeError, "GEM has no GEMST" 00117 regList = gemst.regs.values() # get the list of registers 00118 for reg in regList: 00119 if reg.size() > 0 and not reg.isDeprecated(): 00120 reg.set(0) # Reset all to zero 00121 00122 # print "setting scheduler" 00123 # Scheduler Registers (GEMSC) 00124 gemsc = gem.downGEMSC() 00125 if gemsc is None: 00126 raise RuntimeError, "GEM has no GEMSC" 00127 regList = gemsc.regs.values() # get the list of registers 00128 for reg in regList: 00129 if reg.size() > 0 and not reg.isDeprecated(): 00130 reg.set(self.lookupTableRegister(reg.id())) 00131 00132 # print "setting roi" 00133 # ROI Registers (GEMVG) 00134 gemvg = gem.downGEMVG() 00135 if gemvg is None: 00136 raise RuntimeError, "GEM has no GEMVG" 00137 regList = gemvg.regs.values() # get the list of registers 00138 for reg in regList: 00139 if reg.size() > 0 and not reg.isDeprecated(): 00140 reg.set(self.roiRegister(reg.id())) 00141 00142 # print "setting input enables" 00143 # Input Enable Registers (GEMIE) 00144 gemie = gem.downGEMIE() 00145 if gemie is None: 00146 raise RuntimeError, "GEM has no GEMIE" 00147 #ST 6/14/05 00148 #regList = gemie.regs.values() # get the list of registers 00149 #for reg in regList: 00150 00151 # The above two lines have been replaced by the following line to support 00152 # the older GASUs. This is outlined in JIRA OACD-3 which dictates that to 00153 # avoid overwriting the TILES_000_013 register, the EXTERNAL register has to 00154 # be written first. In order for this to happen, a new method attrIter has 00155 # been added to the Gdb class which allows iterating the attributes in the 00156 # same order as they are declared in the node's __attrs member. The EXTERNAL 00157 # register has now been specified as the first register in this list so it 00158 # is guaranteed to be modified first. 00159 for reg in gemie.attrIter(): 00160 if reg.size() > 0 and not reg.isDeprecated(): 00161 setting = self.__ieRegister(reg.id()) # private function below 00162 if setting is not None: 00163 reg.set(setting) 00164 00165 # print "setting windowing" 00166 # Window Registers (GEMW) 00167 gemw = gem.downGEMW() 00168 if gemw is None: 00169 raise RuntimeError, "GEM has no GEMW" 00170 gemw.WINDOW_WIDTH = self.width() 00171 gemw.WINDOW_OPEN_MASK = 0 # all disabled at startup by default 00172 00173 def __getDestinationFromEPU(self): 00174 return self.__epuaddr 00175 00176 def __ieRegister(self, registerNumber): 00177 # routine that maps the input-enable registers to the register functions 00178 # 18 input enable registers. 00179 # 0-3 Tower Inputs 00180 # 4 acdCNO 00181 # 5-16 ACD veto enables 00182 # 17 Tower_busy enable 00183 if 0 <= registerNumber <= 3: 00184 return self.towerEnableRegister(registerNumber) 00185 if 4 == registerNumber: 00186 return self.cnoEnableRegister() 00187 if 5 <= registerNumber <= 16: 00188 return self.tileEnableRegister(registerNumber - 5) 00189 if 17 == registerNumber: 00190 try: # special try block to allow Run Control to override register 00191 return self.towerBusyEnableRegister() 00192 except NotImplementedError: 00193 return None 00194 if 18 == registerNumber: 00195 return self.externalEnableRegister() 00196 # shouldn't get here 00197 raise IndexError, "registerNumber out of range 0..18" 00198 00199 ############### Pure virtual function implementation 00200 def version(self): 00201 cfg = self.GEM().GEMC.CONFIGURATION 00202 return ( ( cfg >> 16 ) & 0xffff ) 00203 00204 def solicit(self): 00205 # transmit the GEM's TRIGGER dataless command 00206 self.GEM().downGEMC().CMD_TRIGGER = 1 00207 00208 def enable(self, mask=None): 00209 if mask is not None: 00210 outMask = mask 00211 elif self.conditions() is not None: 00212 outMask = self.conditions().value() 00213 else: 00214 raise AssertionError, "Attempting to enable a TrgConditionsValue of None" 00215 self.GEM().downGEMW().WINDOW_OPEN_MASK = outMask 00216 00217 def disable(self): 00218 self.GEM().downGEMW().WINDOW_OPEN_MASK = 0 00219 00220 def triggerCounters(self): 00221 return self.__triggerCounters 00222 00223 def tileCounters(self): 00224 return self.__tileCounters 00225 00226 def cnoCounters(self): 00227 return self.__cnoCounters 00228 00229 def cmdCounters(self): 00230 return self.__cmdCounters 00231 00232 def eventCounter(self): 00233 return self.__eventCounter 00234 00235 def ppsTimer(self): 00236 return self.__ppsTimer 00237 00238 def shut(self, marker): 00239 """Implementation of the shut function. 00240 """ 00241 gemw = self.GEM().GEMW 00242 gemmg = self.GEM().GEMMG 00243 gemsc = self.GEM().GEMSC 00244 00245 #0) disable triggers 00246 self.disable() 00247 00248 #1) Replace engine 0 with a marker engine 00249 from TrgEngine import TrgInjectMarker 00250 newEngine = TrgInjectMarker(marker) 00251 newTAM = self._TrgGemRegisters__parseEngine(newEngine) 00252 oldTAM = gemmg.ENGINE_0 00253 gemmg.ENGINE_0 = newTAM 00254 00255 #2) replace contents of all schedulers with solicited with (Engine) 0 00256 scheduler = ( 0x00000000L ) # Everything's 0! 00257 regList = gemsc.regs.values() 00258 oldSched = {} # dictionary keyed on register names 00259 for reg in regList: 00260 oldSched[reg.getName()] = reg.get() 00261 reg.set(scheduler) 00262 00263 #3) Change conditions to be solicit only, solicit a trigger and disable 00264 gemw.WINDOW_OPEN_MASK = TrgGem.__SOLICIT_MASK 00265 self.solicit() 00266 self.disable() 00267 00268 #4) Put the original contents of scheduler 0x40 back, and put the TAM back 00269 for reg in regList: 00270 reg.set(oldSched[reg.getName()]) 00271 00272 gemmg.ENGINE_0 = oldTAM 00273 00274 #5) Put the trigger conditions back 00275 self.enable() 00276