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__ = "Example CAL test application that tests rule alarms, use with simpleAlarmSchema.xml" 00012 __author__ = "S. Tuvi <stuvi@SLAC.Stanford.edu> SLAC - GLAST LAT I&T/Online" 00013 __date__ = ("$Date: 2005/03/21 17:58:12 $").split(' ')[1] 00014 __version__ = "$Revision: 1.4 $" 00015 __release__ = "$Name: R04-12-00 $" 00016 __credits__ = "SLAC" 00017 00018 import LATTE.copyright_SLAC 00019 00020 import threading 00021 import logging as log 00022 from LATTE.runcontrol.rcTransitions import rcTransitions 00023 from LATTE.runcontrol.ArgumentImpl import ArgumentImpl 00024 #from rcHouseKeeping import rcHouseKeeping 00025 import time 00026 00027 from support.SimpleGasuExample import * 00028 from support.MiniGLTExample import * 00029 00030 # This class puts up a GUI for inputting a value of some sort. It is used by 00031 # the userApplication example to get the number of self triggers to take. 00032 class userArgument(ArgumentImpl): 00033 "GUI for getting the user to input some sort of value." 00034 def __init__(self, parent = None, name = None, modal = 0, fl = 0): 00035 ArgumentImpl.__init__(self, parent, name, modal, fl) 00036 self.__value = 0 00037 self.setCaption("Hello world!") 00038 00039 def OKButtonClicked(self): 00040 self.__value = int(self.ArgumentList.text().latin1()) 00041 self.close() 00042 00043 def CancelButtonClicked(self): 00044 self.__value = None 00045 self.close() 00046 00047 def getValue(self, caption): 00048 self.setCaption(caption) 00049 self.show() 00050 self.exec_loop() 00051 return self.__value 00052 00053 class userArgText(object): 00054 "Text user interface for getting the user to input some sort of value" 00055 def __init__(self): 00056 pass 00057 00058 def getValue(self, caption): 00059 return int(raw_input("%s: " % (caption))) 00060 00061 00062 # Example application implementation. 00063 # Note that the name of the class must be userApplication. 00064 # Look at rcTransitions for names of other transition methods that can be used. 00065 class userApplication(rcTransitions): 00066 "Implmentation class for a user application" 00067 def __init__(self, rc, userId, debug): 00068 rcTransitions.__init__(self, rc, userId, debug) 00069 log.debug("userApplication.__init__()") 00070 self.__eventSem = threading.Semaphore(0) 00071 self.__cmdSynchSem = threading.Semaphore(0) 00072 00073 def getName(self): 00074 return __name__ 00075 00076 def setup(self): 00077 log.debug("userApplication.setup()") 00078 00079 if self.rc is None: 00080 self.__arg = userArgText() 00081 else: 00082 self.__arg = self.rc.createGUI(userArgument, self.rc, 'test1', 1) 00083 00084 # Get a TEM instance 00085 if self.lat.TEMcnt() == 1: 00086 tem = self.lat.TEM[self.lat.TEM.keys()[0]] 00087 elif self.lat.TEMcnt() > 1: 00088 tem = self.lat.TEM.all() 00089 else: 00090 log.fatal("No TEM(s) found in the schema") 00091 return -1 00092 00093 tic = tem.TIC 00094 00095 # Retrieve the global rule list for this schema 00096 rules = self.lat.getRules() 00097 00098 # Access any of the rule objects and call clearAllActions() to clear actions. 00099 rules.values()[0].clearAllActions() 00100 # For the adc_tem_digital_3_3v register, associate the voltageMonitor rule's 00101 # yellowAction with the yellowAlarm1 method. 00102 rules['voltageMonitor'].registerAction('yellowAction', self.yellowAlarm1, 00103 sender=tic.regs['adc_tem_digital_3_3v']) 00104 # For all other registers using the voltageMonitor rule, associate this rule's 00105 # yellowAction with the yellowAlarm2 method. 00106 rules['tempMonitor'].registerAction('yellowAction', self.yellowAlarm2) 00107 # For all registers using the voltageMonitor rule, associate this rule's 00108 # redAction with the redAlarm method. 00109 rules['voltageMonitor'].registerAction('redAction', self.redAlarm) 00110 # The application can unregister any of the actions that it previously 00111 # registered using the following method call. 00112 #rules['voltageMonitor'].unregisterAction('redAction', self.redAlarm) 00113 00114 00115 00116 # reset the TEM since we are going to modify DATA_MASKS 00117 tem.CMD_RESET = 1 00118 00119 # clear TEM stats reg 00120 tem.COMMAND_RESPONSE = 0 00121 00122 # clear TEM status reg 00123 tem.STATUS = 0 00124 00125 # enable CAL, disable TKR, no diag # 0x10FF for diag 00126 tem.DATA_MASKS = 0x00FF 00127 00128 # TEM config reg # set TEM timeout 00129 tem.CONFIGURATION = 0 00130 00131 #status = gTEMread( __GT, temId, TEM_REG_CONFIGURATION, &payload); 00132 #printf("tem config reg = 0x%08x\n", payload); 00133 00134 # enable output in our GCCCs 00135 # broadcast load of GCCC_REG_CONFIGURATION 00136 00137 bcast_ccc = tem.allCCC() 00138 bcast_ccc.CONFIGURATION = 0x80000000L 00139 00140 # disable all GCRCs in all GCCCs via broadcast # GCCC_REG_LAYER_MASK_0, GCCC_REG_LAYER_MASK_1 00141 bcast_ccc.LAYER_MASK_0 = 0xFFFFFFFFL 00142 bcast_ccc.LAYER_MASK_1 = 0xFFFFFFFFL 00143 ccc0 = tem.downCCC(0) # O$GCCC_00 00144 ccc0.LAYER_MASK_0 = 0xFFFF0000L 00145 ccc0.LAYER_MASK_1 = 0xFFFF000FL 00146 ccc2 = tem.downCCC(2) # O$GCCC_02 00147 ccc2.LAYER_MASK_0 = 0xFFFF0000L 00148 ccc2.LAYER_MASK_1 = 0xFFFF0000L 00149 00150 # config GCFE for calibration -- range 0 first 00151 bcast_cfe = tem.allCCC().allCRC().allCFE() 00152 bcast_cfe.CONFIG_0 = 0x00 00153 bcast_cfe.CONFIG_1 = 0x36 00154 bcast_cfe.FLE_DAC = 0x55 00155 bcast_cfe.FHE_DAC = 0x55 00156 bcast_cfe.LOG_ACPT = 0x10 00157 bcast_cfe.RNG_ULD_DAC = 0x7F 00158 bcast_cfe.REF_DAC = 0x7f 00159 00160 # config GCRC for calibration 00161 bcast_crc = tem.allCCC().allCRC() 00162 bcast_crc.DELAY_1 = 0xFF 00163 bcast_crc.DELAY_2 = 0xFF 00164 bcast_crc.DELAY_3 = 0xFF 00165 bcast_crc.DAC = 0x42FE 00166 bcast_crc.DAC = 0x42FE 00167 00168 # large timeouts for all GCCCs 00169 # broadcast load of GCCC_REG_EVENT_TIMEOUTS 00170 bcast_ccc.EVENT_TIMEOUTS = 0x0 00171 #status = gGCCCread( __GT, temId, 1, GCCC_REG_EVENT_TIMEOUTS, &payload); 00172 #printf("gccc register event timeouts = 0x%08x\n", payload); 00173 00174 # Register environment variables for housekeeping 00175 #hsk = self.getHSK() 00176 #regs = [tem.regs['data_masks'], ccc2.regs['layer_mask_1']] 00177 #hsk.addEnvRegs(regs) 00178 #hsk.setUpdateInterval(1) 00179 00180 # Two choices for the trigger, GEM and MiniGLT 00181 if self.lat.existsGEM(): 00182 self.trigger( SimpleGasuExample() ) 00183 else: 00184 self.trigger( MiniGLTExample() ) 00185 00186 # A state transition can be rejected by not returning None 00187 return None 00188 00189 def startRun(self): 00190 log.debug("userApplication.startRun()") 00191 00192 caption = "Enter number of triggers to take" 00193 if self.rc is None: 00194 cnt = self.__arg.getValue(caption) 00195 else: 00196 cnt = self.rc.execGUImethod(self.__arg.getValue, caption) 00197 00198 # The user pressed 'Cancel' 00199 if cnt is None: return -1 00200 self.__cnt = cnt 00201 00202 # Spawn a thread to synchronize commands with events 00203 self.__cmdSynchQuit = False 00204 00205 # A state transition can be rejected by not returning None 00206 return None 00207 00208 def stopRun(self): 00209 log.debug("userApplication.stopRun()") 00210 00211 self.setCompletionStatus(self.COMPL_STATUS_PASSED) 00212 self.__cmdSynchQuit = True 00213 self.__eventSem.release() 00214 00215 # The STOP_RUN transition can not be rejected 00216 00217 def resume(self): 00218 log.debug("userApplication.resume()") 00219 00220 # Issue self trigger to make up for the one that was lost during PAUSE 00221 self.trigger().solicit() 00222 00223 return None 00224 00225 def stop(self): 00226 log.debug("userApplication.stop()") 00227 return self.stopRun() 00228 00229 def process(self, (status, buffer)): 00230 "Method called back for each data event taken" 00231 #log.debug("userApplication.process()") 00232 00233 evtCli = self.evtCli 00234 00235 if status != 0: 00236 if evtCli.isGGLTStatus(): 00237 log.error("GGLT_STATUS=%d %s" % (evtCli.getGGLTStatus(), evtCli.getGGLTStatusStr())) 00238 elif not evtCli.checkOnlineStatus(status, self.evtCli.PLAYBACK_ERROR): 00239 log.error("EVENT ERROR= 0x%x %s" % (status, evtCli.getOnlineStatusStr())) 00240 self.__eventSem.release() 00241 return 00242 try: 00243 # In the future this event may contain additional data 00244 if evtCli.isSweepEvent(): return 00245 except: 00246 # Event summary word inaccessible, handle the bad event here 00247 import gutil 00248 gutil.logException() 00249 return 00250 00251 #evtCli.evDumpCAL_LogAccepts(); 00252 ###print "" 00253 #evtCli.evDumpCAL_Logs(); 00254 #~ #print "" 00255 #~ #evtCli.evDumpTKR() 00256 ###evtCli.evDumpTEM_Error() 00257 ###evtCli.evDumpDiagnostic() 00258 ###for acc in evtCli.evt.CAL_LogAccepts: 00259 ### print "CAL Log Accept: 0x%08x" % acc.ui 00260 00261 ###for data in evtCli.evt.CAL_LogData: 00262 ### print "CAL Log Data: 0x%08x" % data.ui 00263 #~ sum = evtCli.evt.summary 00264 ###evtCli.evDumpSummary() 00265 00266 # Get next event triggered 00267 self.__eventSem.release() 00268 00269 00270 #def __commandSynch(self, count): 00271 def commandSynch(self): 00272 "Method called by the command synchronization task" 00273 import time 00274 trigger = self.trigger() 00275 eventSem = self.__eventSem 00276 00277 # Drain the semaphore release count 00278 # Handles the case when the stop run release collided with a trigger release 00279 while eventSem.acquire(0): pass 00280 00281 t0 = time.time() 00282 00283 # Compensate for the extra CMD_SELF_TRIGGER below 00284 cnt = 1 00285 count = self.__cnt 00286 00287 # Wait for START_RUN to enable triggers 00288 trigger.waitForMaskEnable() 00289 00290 trigger.solicit() # Issue an internal trigger 00291 eventSem.acquire() # Wait for the event to be processed 00292 00293 t1 = trigger.getEnableTime() # get the last trigger enable time from GLT 00294 00295 while cnt < count and not self.__cmdSynchQuit: 00296 cnt += 1 00297 trigger.solicit() # Issue an internal trigger 00298 time.sleep(.0001) 00299 eventSem.acquire() # Wait for the event to be processed 00300 #trigger.disable() # Disable triggers 00301 # Do stuff 00302 #trigger.enable() # Enable triggers 00303 00304 t2 = trigger.getTimeStamp() # Get the last trigger timestamp 00305 00306 if t1 is None: 00307 t1 = t0 00308 if t2 is None: 00309 t2 = time.time() 00310 dT = t2 - t1 00311 if dT == 0.0: dT = 0.000001 00312 log.info("%s processed %d events in %.3f seconds = %.1f events/second" % \ 00313 (self.getName(), self.evtCnt, dT, self.evtCnt/dT)) 00314 00315 # Get out of waiting when in suite or standalone mode 00316 self.sync() 00317 00318 # execute the GUI functions for stopRun, just in case 00319 if not self.__cmdSynchQuit and not self.isRunFromSuite(): 00320 if self.rc is not None: 00321 self.rc.doStop() 00322 00323 def wait(self): 00324 self.__cmdSynchSem.acquire() 00325 00326 def sync(self): 00327 if __name__ == "__main__" or self.isRunFromSuite(): 00328 self.__cmdSynchSem.release() 00329 00330 def yellowAlarm1(self, value, signal, sender, sendNode): 00331 print "Yellow Alarm #1!", value, signal, "from", sender.getName() 00332 00333 def yellowAlarm2(self, value, signal, sender, sendNode): 00334 print sender 00335 print sender.getName() 00336 print sendNode 00337 print "Yellow Alarm #2!", value, signal, "from", sender.getName() 00338 00339 def redAlarm(self, value, signal, sender): 00340 print "Red Alarm!", value, signal, "from", sender.getName() 00341 00342 00343 # Standalone mode: 00344 if __name__ == "__main__": 00345 import os 00346 log.basicConfig() 00347 log.getLogger("").setLevel(log.DEBUG) 00348 ua = userApplication(None, 321, 0) 00349 ua.rcSetup(os.path.join(os.environ['ONLINE_ROOT'], 'repos/simpleTemSchema.xml')) 00350 ua.rcStartRun() 00351 ua.wait() 00352 ua.rcStopRun() 00353 ua.rcTeardown()