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()