00001 #!/usr/local/bin/python 00002 # 00003 # Copyright 2002 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__ = "Example TKR test application" 00012 __author__ = "R. Claus <Claus@SLAC.Stanford.edu> SLAC - GLAST LAT I&T/Online" 00013 __date__ = "11/21/2002" 00014 __version__ = "$Revision: 1.8 $" 00015 __credits__ = "SLAC" 00016 00017 import LATTE.copyright_SLAC 00018 00019 import threading 00020 import logging as log 00021 00022 from LATTE.runcontrol.rcTransitions import rcTransitions 00023 from LATTE.runcontrol.ArgumentImpl import ArgumentImpl 00024 import time 00025 00026 from support.SimpleGasuExample import * 00027 from support.MiniGLTExample import * 00028 00029 TRUE = (0 < 1) 00030 FALSE = not TRUE 00031 00032 # This class puts up a GUI for inputting a value of some sort. It is used by 00033 # the userApplication example to get the number of self triggers to take. 00034 class userArgument(ArgumentImpl): 00035 "GUI for getting the user to input some sort of value." 00036 def __init__(self, parent = None, name = None, modal = 0, fl = 0): 00037 ArgumentImpl.__init__(self, parent, name, modal, fl) 00038 self.__value = 0 00039 self.setCaption("Hello world!") 00040 00041 def OKButtonClicked(self): 00042 self.__value = int(self.ArgumentList.text().latin1()) 00043 self.close() 00044 00045 def CancelButtonClicked(self): 00046 self.__value = None 00047 self.close() 00048 00049 def getValue(self, caption): 00050 self.setCaption(caption) 00051 self.show() 00052 self.exec_loop() 00053 return self.__value 00054 00055 class userArgText(object): 00056 "Text user interface for getting the user to input some sort of value" 00057 def __init__(self): 00058 pass 00059 00060 def getValue(self, caption): 00061 return int(raw_input("%s: " % (caption))) 00062 00063 00064 # Example application implementation. 00065 # Note that the name of the class must be userApplication. 00066 # Look at rcTransitions for names of other transition methods that can be used. 00067 class userApplication(rcTransitions): 00068 "Implmentation class for a user application" 00069 def __init__(self, rc, userId, debug): 00070 rcTransitions.__init__(self, rc, userId, debug) 00071 log.debug("userApplication.__init__()") 00072 self.__eventSem = threading.Semaphore(0) 00073 self.__cmdSynchSem = threading.Semaphore(0) 00074 00075 def getName(self): 00076 return __name__ 00077 00078 def setup(self): 00079 log.debug("userApplication.setup()") 00080 00081 if self.rc is None: 00082 self.__arg = userArgText() 00083 else: 00084 self.__arg = self.rc.createGUI(userArgument, self.rc, 'test1', 1) 00085 00086 # Get a TEM instance 00087 if self.lat.TEMcnt() == 1: 00088 tem = self.lat.TEM[self.lat.TEM.keys()[0]] 00089 elif self.lat.TEMcnt() > 1: 00090 tem = self.lat.TEM.all() 00091 else: 00092 log.fatal("No TEM(s) found in the schema") 00093 return -1 00094 00095 # Move to schema configuration 00096 # # reset the TEM since we are going to modify DATA_MASKS 00097 # tem.CMD_RESET = 1 00098 00099 # # 00100 # # Configure TEM 00101 00102 # # config TEM TKR calstrobe delay for ~ 5usec 00103 # tem.TKR_TRGSEQ = 0x3C 00104 00105 # # enable TKR, no diag # 0x1F00 for diag 00106 # # make sure we also enable CAL CC 1 since it is required for 00107 # # proper event data taking 00108 # # enable GTCC 2 and 3 00109 # tem.DATA_MASKS = 0x0DF3 00110 # tem.configuration = 0x00010000L # primary 00111 # #tem.CONFIGURATION = 0x03010000L # redundant 00112 00113 # ccc = tem.allCCC() 00114 # # enable output in our GCCCs 00115 # # broadcast load of GCCC_REG_CONFIGURATION 00116 # ccc.CONFIGURATION = 0x80000000L 00117 00118 # # disable all GCRCs in all GCCCs via broadcast 00119 # ccc.LAYER_MASK_0 = 0xFFFFFFFFL 00120 # ccc.LAYER_MASK_1 = 0xFFFFFFFFL 00121 00122 tcc = tem.allTCC() 00123 00124 # Move to schema configuration 00125 # broadcast load of GTCC_REG_CONFIGURATION 00126 # enable controller output and set cable length to 1 00127 # 0xC0000000 is for one layer 00128 # 0x80000000 is for two layers 00129 #tcc.CONFIGURATION = 0xC0000000L 00130 #x_tcc = tem.downTCC(0) 00131 # enable all masks 00132 00133 tcc.INPUT_MASK = 0x0 00134 00135 # set maximum event timeout 00136 tcc.EVENT_TIMEOUTS = 0x0 00137 00138 # 00139 # Configure GTRCs 00140 # 00141 00142 # our board is connected CC = 2, RC = 0 and CC = 3, RC = 0 00143 # reset GTRC # required before all triggers 00144 00145 trc = tcc.allTRC() 00146 00147 trc.CMD_RESET = 1 00148 00149 # number of GTFE to readout left 00150 nGTFEsLeft = 7 00151 nGTFEsRight = 0 00152 00153 # max hits per GTRC # 31 max 00154 maxHits = 31 00155 00156 enMask = 0x6 00157 00158 dLO = (enMask << 28) | ((nGTFEsRight << 7)& 0xF80) | (maxHits & 0x7F); 00159 print "dLO=", dLO, hex(dLO) 00160 00161 # cable controller 2, readout controller 0 00162 tcc = tem.downTCC(2) 00163 trc = tcc.downTRC(1) 00164 00165 trc.CSR = dLO 00166 00167 dLO = (enMask << 28) | ((nGTFEsLeft << 7)& 0xF80) | (maxHits & 0x7F); 00168 print "dLO=", dLO, hex(dLO) 00169 00170 # cable controller 3, readout controller 0 00171 tcc = tem.downTCC(3) 00172 trc = tcc.downTRC(1) 00173 00174 trc.CSR = dLO 00175 00176 # 00177 # Configure GTFEs 00178 # 00179 00180 tfe = trc.allTFE() 00181 tfe.TRIG_MASK = 0x0 00182 tfe.DATA_MASK = 0x0 00183 tfe.CALIB_MASK = 0x0 00184 tfe.DAC = 0x00001902 00185 # configure front ends # all listen to left 00186 tfe.MODE = 0 00187 #tfe = trc.downTFE(0) 00188 00189 # configure default DACs for threshold and calibration 00190 # Calibration DAC Range and Resolution 00191 # Low Range (B6=0): DAC output voltage in mV = 1.57 + 1.53*DAC_Value 00192 # High Range (B6=1): DAC output voltage in mV = 15.0 + 14.6*DAC_Value 00193 # Discriminator Threshold DAC Range and Resolution 00194 # Low Range (B6=0): DAC output voltage in mV = 4.5 + 4.5*DAC_Value 00195 # High Range (B6=1): DAC output voltage in mV = 12.9 + 12.9*DAC_Value 00196 00197 00198 # calRng = 1 00199 # thrRng = 0 00200 # calDAC = 60 00201 # thrDAC = 10 00202 00203 tfe.DAC = 0x00001952 # based on the above Rng and DAC values 00204 00205 # enable GTFE for data taking # all channels 00206 tfe.TRIG_MASK = 0xffffffffffffffff 00207 tfe.DATA_MASK = 0xffffffffffffffff 00208 00209 # Cal strobe channels 4 and 48 only 00210 tfe.CALIB_MASK = 0x0001000000000010 00211 00212 #~ #Mask of the following Registers 00213 #~ tfe = trc.downTFE(13) 00214 #~ tfe.DATA_MASK = 0x0L 00215 #~ tfe.CALIB_MASK = 0x0L 00216 #~ tfe.TRIG_MASK = 0x0L 00217 00218 #~ tfe = trc.downTFE(14) 00219 #~ tfe.DATA_MASK = 0x0L 00220 #~ tfe.CALIB_MASK = 0x0L 00221 #~ tfe.TRIG_MASK = 0x0L 00222 00223 #~ tfe = trc.downTFE(19) 00224 #~ #tfe.DATA_MASK = 0x0L 00225 #~ tfe.CALIB_MASK = 0x0L 00226 #~ tfe.TRIG_MASK = 0x0L 00227 00228 #~ tfe = trc.downTFE(20) 00229 #~ #tfe.DATA_MASK = 0x0L 00230 #~ tfe.CALIB_MASK = 0x0L 00231 #~ tfe.TRIG_MASK = 0x0L 00232 00233 00234 00235 # Two choices for the trigger, GEM and MiniGLT 00236 if self.lat.existsGEM(): 00237 self.trigger( SimpleGasuExample() ) 00238 else: 00239 self.trigger( MiniGLTExample() ) 00240 00241 00242 # A state transition can be rejected by not returning None 00243 return None 00244 00245 def startRun(self): 00246 log.debug("userApplication.startRun()") 00247 00248 caption = "Enter number of triggers to take" 00249 if self.rc is None: 00250 cnt = self.__arg.getValue(caption) 00251 else: 00252 cnt = self.rc.execGUImethod(self.__arg.getValue, caption) 00253 00254 # The user pressed 'Cancel' 00255 if cnt is None: return -1 00256 self.__cnt = cnt 00257 00258 if self.rc is not None: 00259 self.getParameterVerifier().add(caption, cnt) 00260 00261 # Spawn a thread to synchronize commands with events 00262 # This must happen after triggers are enabled 00263 self.__cmdSynchQuit = FALSE 00264 #cmdSynch = threading.Thread(None, self.__commandSynch, 'CmdSynch', (cnt,)) 00265 #self.__cmdSynch = cmdSynch 00266 #cmdSynch.start() 00267 # A state transition can be rejected by not returning None 00268 return None 00269 00270 def stopRun(self): 00271 log.debug("userApplication.stopRun()") 00272 self.setCompletionStatus(self.COMPL_STATUS_PASSED) 00273 self.__cmdSynchQuit = TRUE 00274 self.__eventSem.release() 00275 #self.__cmdSynch.join() 00276 00277 # The STOP_RUN transition can not be rejected 00278 00279 def resume(self): 00280 log.debug("userApplication.resume()") 00281 # Issue self trigger to make up for the one that was lost during PAUSE 00282 self.trigger().solicit() 00283 00284 return None 00285 00286 def stop(self): 00287 log.debug("userApplication.stop()") 00288 00289 return self.stopRun() 00290 00291 def teardown(self): 00292 log.debug("userApplication.teardown()") 00293 # Allow the C++ object to be deleted 00294 if self.rc is not None and self.__arg is not None: 00295 self.__arg.deleteLater() 00296 00297 def process(self, (status, buffer)): 00298 "Method called back for each data event taken" 00299 ###log.debug("userApplication.process()") 00300 00301 evtCli = self.evtCli 00302 00303 if status != 0: 00304 if evtCli.isGGLTStatus(): 00305 log.error("GGLT_STATUS=%d %s" % (evtCli.getGGLTStatus(), evtCli.getGGLTStatusStr())) 00306 elif not evtCli.checkOnlineStatus(status, self.evtCli.PLAYBACK_ERROR): 00307 log.error("EVENT ERROR= 0x%x %s" % (status, evtCli.getOnlineStatusStr())) 00308 self.__eventSem.release() 00309 return 00310 try: 00311 # In the future this event may contain additional data 00312 if evtCli.isSweepEvent(): return 00313 except: 00314 # Event summary word inaccessible, handle the bad event here 00315 log.exception("") 00316 return 00317 00318 if evtCli.setCurrentContribution(evtCli.TEM0) != -1: 00319 evtCli.evDumpSummary() 00320 evtCli.evDumpTKR() 00321 evtCli.evDumpTEM_Error() 00322 evtCli.evDumpDiagnostic() 00323 else: 00324 log.error("*******************************************") 00325 log.error("* NO TEM 0 CONTRIBUTION PRESENT *") 00326 log.error("*******************************************") 00327 00328 #print "TKRSTRIPS: ", len(evtCli.evt.TKRstrips) 00329 #for strip in evtCli.evt.TKRstrips: 00330 # print strip.ui 00331 00332 # Get next event triggered 00333 self.__eventSem.release() 00334 00335 #def __commandSynch(self, count): 00336 def commandSynch(self): 00337 "Method called by the command synchronization task" 00338 import time 00339 trigger = self.trigger() 00340 eventSem = self.__eventSem 00341 # Drain the semaphore release count 00342 # Handles the case when the stop run release collided with a trigger release 00343 while eventSem.acquire(0): pass 00344 00345 t0 = time.time() 00346 00347 # Compensate for the extra CMD_SELF_TRIGGER below 00348 cnt = 1 00349 count = self.__cnt 00350 00351 # Wait for START_RUN to enable triggers 00352 trigger.waitForMaskEnable() 00353 00354 trigger.solicit() # Issue an internal trigger 00355 eventSem.acquire() # Wait for the event to be processed 00356 00357 t1 = trigger.getEnableTime() # get the last trigger enable time from GLT 00358 00359 while cnt < count and not self.__cmdSynchQuit: 00360 cnt += 1 00361 trigger.solicit() # Issue an internal trigger 00362 time.sleep(.0001) 00363 eventSem.acquire() # Wait for the event to be processed 00364 #trigger.disable() # Disable triggers 00365 # Do stuff 00366 #trigger.enable() # Enable triggers 00367 00368 t2 = trigger.getTimeStamp() # Get the last trigger timestamp 00369 # When we get here the triggers should still be enabled. 00370 # If the glt.MASK needs to be set through any other means 00371 # then it needs to be restored to its SETUP value here. 00372 00373 if t1 is None: 00374 t1 = t0 00375 if t2 is None: 00376 t2 = time.time() 00377 dT = t2 - t1 00378 if dT == 0.0: dT = 0.000001 00379 log.info("%s processed %d events in %.3f seconds = %.1f events/second" % \ 00380 (self.getName(), self.evtCnt, dT, self.evtCnt/dT)) 00381 00382 # Get out of waiting when in suite or standalone mode 00383 self.sync() 00384 00385 # execute the GUI functions for stopRun, just in case 00386 if not self.__cmdSynchQuit and not self.isRunFromSuite(): 00387 if self.rc is not None: 00388 self.rc.doStop() 00389 00390 def wait(self): 00391 self.__cmdSynchSem.acquire() 00392 00393 def sync(self): 00394 if __name__ == "__main__" or self.isRunFromSuite(): 00395 self.__cmdSynchSem.release() 00396 00397 00398 00399 # Standalone mode: 00400 if __name__ == "__main__": 00401 from LATTE.runcontrol.RunControlCommon import RunControlCommon 00402 00403 rcCommon = RunControlCommon() 00404 rcCommon.initialize() 00405 rcCommon.setLoggingLevel("INFO") 00406 rcCommon.connect() 00407 ua = userApplication(None, 321, rcCommon) 00408 ua.rcSetup() 00409 ua.rcStartRun() 00410 ua.wait() 00411 ua.rcStopRun() 00412 ua.rcTeardown()