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__ = ("$Date: 2005/03/30 06:04:33 $").split(' ')[1] 00014 __version__ = "$Revision: 1.6 $" 00015 __release__ = "$Name: R04-12-00 $" 00016 __credits__ = "SLAC" 00017 00018 import LATTE.copyright_SLAC 00019 00020 import threading 00021 import sys 00022 00023 from LATTE.runcontrol.rcTransitions import rcTransitions 00024 from LATTE.runcontrol.ArgumentImpl import ArgumentImpl 00025 00026 from sihippo import * 00027 from time import sleep 00028 import logging as log 00029 00030 from support.SimpleGasuExample import * 00031 from support.MiniGLTExample import * 00032 00033 # This class puts up a GUI for inputting a value of some sort. It is used by 00034 # the userApplication example to get the number of self triggers to take. 00035 class userArgument(ArgumentImpl): 00036 "GUI for getting the user to input some sort of value." 00037 def __init__(self, parent = None, name = None, modal = 0, fl = 0): 00038 ArgumentImpl.__init__(self, parent, name, modal, fl) 00039 self.__value = 0 00040 self.setCaption("Hello world!") 00041 00042 def OKButtonClicked(self): 00043 self.__value = int(self.ArgumentList.text().latin1()) 00044 self.close() 00045 00046 def CancelButtonClicked(self): 00047 self.__value = None 00048 self.close() 00049 00050 def getValue(self, caption): 00051 self.setCaption(caption) 00052 self.show() 00053 self.exec_loop() 00054 return self.__value 00055 00056 class userArgText(object): 00057 "Text user interface for getting the user to input some sort of value" 00058 def __init__(self): 00059 pass 00060 00061 def getValue(self, caption): 00062 return int(raw_input("%s: " % (caption))) 00063 00064 00065 # Example application implementation. 00066 # Note that the name of the class must be userApplication. 00067 # Look at rcTransitions for names of other transition methods that can be used. 00068 class userApplication(rcTransitions): 00069 "Implmentation class for a user application" 00070 def __init__(self, gui, userId, debug): 00071 rcTransitions.__init__(self, gui, userId, debug) 00072 log.debug("userApplication.__init__()") 00073 self.__eventSem = threading.Semaphore(0) 00074 self.__cmdSynchSem = threading.Semaphore(0) 00075 00076 def getName(self): 00077 return __name__ 00078 00079 def setup(self): 00080 log.debug("userApplication.setup()") 00081 00082 if self.gui is None: 00083 self.__arg = userArgText() 00084 else: 00085 self.__arg = self.gui.createGUI(userArgument, self.gui, 'test1', 1) 00086 00087 self.gui.execGUImethod(self.__initHippo) 00088 00089 # Get a TEM instance 00090 if self.lat.TEMcnt() == 1: 00091 tem = self.lat.TEM[self.lat.TEM.keys()[0]] 00092 elif self.lat.TEMcnt() > 1: 00093 tem = self.lat.TEM.all() 00094 else: 00095 log.fatal("No TEM(s) found in the schema") 00096 return -1 00097 00098 tcc = tem.allTCC() 00099 00100 # 00101 # Configure GTRCs 00102 # 00103 00104 # our board is connected CC = 2, RC = 0 and CC = 3, RC = 0 00105 # reset GTRC # required before all triggers 00106 00107 trc = tcc.allTRC() 00108 00109 trc.CMD_RESET = 1 00110 00111 # number of GTFE to readout left 00112 nGTFEsLeft = 7 00113 nGTFEsRight = 0 00114 00115 # max hits per GTRC # 31 max 00116 maxHits = 31 00117 00118 enMask = 0x6 00119 00120 dLO = (enMask << 28) | ((nGTFEsRight << 7)& 0xF80) | (maxHits & 0x7F); 00121 log.debug("dLO= %d %s" % (dLO, hex(dLO))) 00122 00123 # cable controller 2, readout controller 0 00124 tcc = tem.downTCC(2) 00125 trc = tcc.downTRC(1) 00126 00127 trc.CSR = dLO 00128 00129 dLO = (enMask << 28) | ((nGTFEsLeft << 7)& 0xF80) | (maxHits & 0x7F); 00130 log.debug("dLO= %d %s" % (dLO, hex(dLO))) 00131 00132 # cable controller 3, readout controller 0 00133 tcc = tem.downTCC(3) 00134 trc = tcc.downTRC(1) 00135 00136 trc.CSR = dLO 00137 00138 # 00139 # Configure GTFEs 00140 # 00141 00142 tfe = trc.allTFE() 00143 tfe.TRIG_MASK = 0x0 00144 tfe.DATA_MASK = 0x0 00145 tfe.CALIB_MASK = 0x0 00146 #tfe.DAC = 0x00001902 00147 tfe.DAC = 0x00000000 00148 # configure front ends # all listen to left 00149 tfe.MODE = 0 00150 #tfe = trc.downTFE(0) 00151 00152 # configure default DACs for threshold and calibration 00153 # Calibration DAC Range and Resolution 00154 # Low Range (B6=0): DAC output voltage in mV = 1.57 + 1.53*DAC_Value 00155 # High Range (B6=1): DAC output voltage in mV = 15.0 + 14.6*DAC_Value 00156 # Discriminator Threshold DAC Range and Resolution 00157 # Low Range (B6=0): DAC output voltage in mV = 4.5 + 4.5*DAC_Value 00158 # High Range (B6=1): DAC output voltage in mV = 12.9 + 12.9*DAC_Value 00159 00160 00161 # calRng = 1 00162 # thrRng = 0 00163 # calDAC = 60 00164 # thrDAC = 10 00165 00166 #tfe.DAC = 0x00001952 # based on the above Rng and DAC values 00167 tfe.DAC = 0x00000000 00168 00169 # enable GTFE for data taking # all channels 00170 tfe.TRIG_MASK = 0xffffffffffffffff 00171 tfe.DATA_MASK = 0xffffffffffffffff 00172 00173 # Cal strobe channels 4 and 48 only 00174 tfe.CALIB_MASK = 0x0001000000000010 00175 00176 #~ #Mask of the following Registers 00177 #~ tfe = trc.downTFE(13) 00178 #~ tfe.DATA_MASK = 0x0L 00179 #~ tfe.CALIB_MASK = 0x0L 00180 #~ tfe.TRIG_MASK = 0x0L 00181 00182 #~ tfe = trc.downTFE(14) 00183 #~ tfe.DATA_MASK = 0x0L 00184 #~ tfe.CALIB_MASK = 0x0L 00185 #~ tfe.TRIG_MASK = 0x0L 00186 00187 #~ tfe = trc.downTFE(19) 00188 #~ #tfe.DATA_MASK = 0x0L 00189 #~ tfe.CALIB_MASK = 0x0L 00190 #~ tfe.TRIG_MASK = 0x0L 00191 00192 #~ tfe = trc.downTFE(20) 00193 #~ #tfe.DATA_MASK = 0x0L 00194 #~ tfe.CALIB_MASK = 0x0L 00195 #~ tfe.TRIG_MASK = 0x0L 00196 00197 # Two choices for the trigger, GEM and MiniGLT 00198 if self.lat.existsGEM(): 00199 self.trigger( SimpleGasuExample() ) 00200 else: 00201 self.trigger( MiniGLTExample() ) 00202 00203 # A state transition can be rejected by not returning None 00204 return None 00205 00206 def startRun(self): 00207 log.debug("userApplication.startRun()") 00208 00209 caption = "Enter number of triggers to take" 00210 if self.gui is None: 00211 cnt = self.__arg.getValue(caption) 00212 else: 00213 cnt = self.gui.execGUImethod(self.__arg.getValue, caption) 00214 00215 # The user pressed 'Cancel' 00216 if cnt is None: return -1 00217 self.__cnt = cnt 00218 self.gui.execGUImethod(self.__initPlots) 00219 00220 # Spawn a thread to synchronize commands with events 00221 self.__cmdSynchQuit = False 00222 00223 # A state transition can be rejected by not returning None 00224 return None 00225 00226 def stopRun(self): 00227 self.setCompletionStatus(self.COMPL_STATUS_PASSED) 00228 self.__cmdSynchQuit = True 00229 self.__eventSem.release() 00230 # The STOP_RUN transition can not be rejected 00231 00232 def resume(self): 00233 # Issue self trigger to make up for the one that was lost during PAUSE 00234 self.trigger().solicit() 00235 return None 00236 00237 def stop (self): 00238 return self.stopRun() 00239 00240 def teardown(self): 00241 log.debug("userApplication.teardown()") 00242 # Allow the C++ object to be deleted 00243 if self.gui is not None and self.__arg is not None: 00244 self.__arg.deleteLater() 00245 00246 def process(self, (status, buffer)): 00247 "Method called back for each data event taken" 00248 ###print "userApplication.process()" 00249 00250 evtCli = self.evtCli 00251 00252 if status != 0: 00253 if evtCli.isGGLTStatus(): 00254 log.error("GGLT_STATUS=%d %s" % (evtCli.getGGLTStatus(), evtCli.getGGLTStatusStr())) 00255 elif not evtCli.checkOnlineStatus(status, self.evtCli.PLAYBACK_ERROR): 00256 log.error("EVENT ERROR= 0x%x %s" % (status, evtCli.getOnlineStatusStr())) 00257 self.__eventSem.release() 00258 return 00259 try: 00260 # In the future this event may contain additional data 00261 if evtCli.isSweepEvent(): return 00262 except: 00263 # Event summary word inaccessible, handle the bad event here 00264 log.exception("") 00265 return 00266 00267 evtCli.evDumpTKR() 00268 for stripData in evtCli.evt.TKRstrips: 00269 self.__nt.addRow([stripData.strip.ui]) 00270 self.__nt2.addRow([evtCli.getEvtSize()]) 00271 00272 # Get next event triggered 00273 self.__eventSem.release() 00274 00275 def commandSynch(self): 00276 "Method called by the command synchronization task" 00277 import time 00278 trigger = self.trigger() 00279 eventSem = self.__eventSem 00280 # Drain the semaphore release count 00281 # Handles the case when the stop run release collided with a trigger release 00282 while eventSem.acquire(0): pass 00283 00284 t0 = time.time() 00285 00286 # Compensate for the extra CMD_SELF_TRIGGER below 00287 cnt = 1 00288 count = self.__cnt 00289 00290 # Wait for START_RUN to enable triggers 00291 trigger.waitForMaskEnable() 00292 00293 trigger.solicit() # Issue an internal trigger 00294 eventSem.acquire() # Wait for the event to be processed 00295 00296 t1 = trigger.getEnableTime() # get the last trigger enable time from GLT 00297 00298 while cnt < count and not self.__cmdSynchQuit: 00299 cnt += 1 00300 trigger.solicit() # Issue an internal trigger 00301 eventSem.acquire() # Wait for the event to be processed 00302 #trigger.disable() # Disable GLT triggers 00303 # Do stuff 00304 #trigger.enable() # Enable GLT triggers 00305 00306 t2 = trigger.getTimeStamp() # Get the last trigger timestamp 00307 # When we get here the triggers should still be enabled. 00308 # If the glt.MASK needs to be set through any other means 00309 # then it needs to be restored to its SETUP value here. 00310 00311 if t1 is None: 00312 t1 = t0 00313 if t2 is None: 00314 t2 = time.time() 00315 dT = t2 - t1 00316 if dT == 0.0: dT = 0.000001 00317 log.info("%s processed %d events in %.3f seconds = %.1f events/second" % \ 00318 (self.getName(), self.evtCnt, dT, self.evtCnt/dT)) 00319 00320 # Get out of waiting when in standalone mode 00321 self.sync() 00322 00323 # execute the GUI functions for stopRun, just in case 00324 if not self.__cmdSynchQuit and not self.isRunFromSuite(): 00325 if self.gui is not None: 00326 self.gui.doStop() 00327 00328 def wait(self): 00329 self.__cmdSynchSem.acquire() 00330 00331 def sync(self): 00332 if __name__ == "__main__": 00333 self.__cmdSynchSem.release() 00334 00335 00336 def __initHippo(self): 00337 label1 = ['Strip Hits'] 00338 label2 = ['Event Size'] 00339 ntc = NTupleController.instance() 00340 self.__nt = ntc.createNTuple(1) 00341 self.__nt2 = ntc.createNTuple ( label2 ) 00342 self.__nt.setTitle('Event Readout #1') 00343 self.__nt2.setTitle('Event Readout #2') 00344 self.__nt.setLabels(label1) 00345 # self.__nt2.setLabels(label2) 00346 self.__nt.reserve ( 512 ) 00347 self.__nt2.reserve ( 512 ) 00348 if __name__ == "__main__": 00349 ## app = HDApp() 00350 ## canvas = app.canvas() 00351 self.__canvas = CanvasWindow() 00352 self.__canvas.show() 00353 else: 00354 wc = WindowController.instance() 00355 self.__canvas = wc.currentCanvas() 00356 ## already done by main applicaton: canvas.show() 00357 ## ntuple_list = [0.0] 00358 ## self.__nt.addRow(ntuple_list) 00359 ## self.__nt2.addRow(ntuple_list) 00360 00361 ## see new way below 00362 ## hist = Display('Histogram',self.__nt,'Strip Hits') 00363 ## hist2 = Display('Histogram',self.__nt2,'Event 00364 00365 def __initPlots(self): 00366 label1 = ['Strip Hits'] 00367 label2 = ['Event Size'] 00368 self.__canvas.clear() 00369 self.__nt.clear() 00370 self.__nt2.clear() 00371 self.__nt.setIntervalCount ( 500 ) 00372 self.__nt2.setIntervalCount ( 100 ) 00373 dc = DisplayController.instance() 00374 self.__hist = dc.createDisplay ( 'Histogram', self.__nt, label1 ) 00375 self.__hist2 = dc.createDisplay ( 'Histogram', self.__nt2, label2 ) 00376 self.__canvas.addDisplay(self.__hist) 00377 self.__canvas.addDisplay(self.__hist2) 00378 self.__canvas.setIntervalEnabled ( 1 ) 00379 self.__canvas.show() 00380 00381 # Standalone mode: 00382 if __name__ == "__main__": 00383 from qt import * 00384 app = QApplication ( sys.argv ) 00385 ua = userApplication(None, 321, 0) 00386 ua.rcSetup('../repos/simpleTemSchema.xml') 00387 ua.rcStartRun() 00388 ua.wait() 00389 ua.rcStopRun() 00390 ua.rcTeardown() 00391 app.exec_loop() 00392 00393 # History: 00394 # $Log: hTestAppTkr.py,v $ 00395 # Revision 1.6 2005/03/30 06:04:33 stuvi 00396 # Removed configuration settings which should normally come from the schema. 00397 # 00398 # Revision 1.5 2005/03/24 03:37:09 stuvi 00399 # Removed TEM reset and other system register related accesses. 00400 # 00401 # Revision 1.4 2005/03/21 17:58:11 claus 00402 # Modified to use the first TEM found in the schema, if only one is there, or 00403 # broadcast to all TEMs if there are multiple. 00404 # 00405 # Revision 1.3 2004/10/22 20:32:48 stuvi 00406 # Fixed log.exception() 00407 # 00408 # Revision 1.2 2004/08/18 18:00:15 stuvi 00409 # Updated for LATTE 4. 00410 # All hippo functions go through the Qt GUI bridge now. 00411 # 00412 # Revision 1.1 2004/08/07 02:14:33 stuvi 00413 # no message 00414 # 00415 # Revision 1.16 2004/07/09 23:14:17 stuvi 00416 # Added "operatorobj" preference that contains the rcUser object and left the "operator" preference to contain the user name. 00417 # 00418 # Revision 1.15 2004/05/03 21:19:47 stuvi 00419 # Moved non-Runcontrol scripts to the support directory and modified imports accordingly. 00420 # 00421 # Revision 1.14 2004/04/17 02:22:17 stuvi 00422 # Various Hippo related fixes 00423 # Added teardown() to delete the C++ object for the userArgument 00424 # 00425 # Revision 1.13 2004/03/19 00:17:31 stuvi 00426 # The plots are now cleared every time the test is run. 00427 # 00428 # Revision 1.12 2004/03/10 22:24:50 panetta 00429 # Upgraded trigger interface. 00430 # Removed dependencies on self.glt. 00431 # 00432 # Revision 1.11 2004/02/24 02:13:34 stuvi 00433 # Changes for long transition support. 00434 # 00435 # Revision 1.10 2003/11/04 18:30:52 panetta 00436 # Changed the commandSynch logic so that the enableMask() call would not pose a threat to snapshot taking. 00437 # 00438 # Revision 1.9 2003/10/31 01:09:37 panetta 00439 # 1) Moved register writes from startRun to setup 00440 # 2) Added GLT enabling logic to __commandSynch 00441 # 3) Gave example of getting the start/stop time from the hardware/event stream 00442 # 00443 # Revision 1.8 2003/07/17 00:01:35 stuvi 00444 # no message 00445 # 00446 # Revision 1.7 2003/06/13 23:26:24 stuvi 00447 # Added TEM reset 00448 # 00449 # Revision 1.6 2003/04/09 00:45:15 stuvi 00450 # Commented out references to DATA_MASKS register which should not be touched during script execution. 00451 # 00452 # Revision 1.5 2003/04/01 21:04:59 stuvi 00453 # Fixed event count discrepancy when the run is stopped in the middle. 00454 # 00455 # Revision 1.4 2003/03/31 19:28:53 stuvi 00456 # Fixed name 00457 # 00458 # Revision 1.3 2003/03/26 21:59:36 stuvi 00459 # Fixed standalone mode 00460 # 00461 # Revision 1.2 2003/03/25 04:52:40 stuvi 00462 # Reduced event timeout value. 00463 # Changed to no diags. 00464 # Made sure the semaphores are drained 00465 # 00466 # Revision 1.1 2003/03/11 21:20:54 stuvi 00467 # Moved from RunControl directory 00468 # 00469 # Revision 1.12 2003/02/06 05:23:15 claus 00470 # Added resume; StopRun bug fix 00471 # 00472 # Revision 1.11 2003/02/06 01:31:23 stuvi 00473 # Added a delay in commandsnyc 00474 # 00475 # Revision 1.10 2003/01/15 16:47:56 stuvi 00476 # Delay the showing of canvas until the test app starts 00477 # 00478 # Revision 1.9 2003/01/12 19:45:41 pfkeb 00479 # Move interval counting to ntuple 00480 # 00481 # Revision 1.8 2003/01/08 00:22:21 pfkeb 00482 # New interface to NTupleController 00483 # 00484 # Revision 1.7 2003/01/06 23:57:21 claus 00485 # Merged Ric's changes with Paul's 00486 # 00487 # Revision 1.6 2003/01/05 00:18:50 pfkeb 00488 # Make use of new HippoDraw features 00489 # 00490 # Revision 1.5 2002/12/23 19:00:25 pfkeb 00491 # Add HippoDraw to RunControl 00492 # 00493 # Revision 1.4 2002/12/19 19:59:52 claus 00494 # Mods for Hippo 00495 # 00496 # Revision 1.3 2002/12/11 21:18:07 stuvi 00497 # Changed glt register assignments to bit field assignments 00498 # 00499 # Revision 1.2 2002/12/10 02:42:03 stuvi 00500 # Put the event size plotting outside the tracker strip look 00501 # 00502 # Revision 1.1 2002/12/10 00:59:16 stuvi 00503 # Runcontrol example that uses Hippo. Currently it doesn't work in GUI mode. 00504 # 00505 # Revision 1.4 2002/12/02 17:17:09 claus 00506 # Added provision to allow application to run stand-alone 00507 # 00508 # Revision 1.3 2002/11/28 02:02:04 claus 00509 # Shuffled constructor arguments 00510 # 00511 # Revision 1.2 2002/11/27 23:49:27 claus 00512 # Initialize semaphore with zero count 00513 # 00514 # Revision 1.1 2002/11/27 05:02:48 claus 00515 # Initial version of Run Control 00516 #