Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | Related Pages

AcdHWMultiplexer.py

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 data export routines"
00012 __author__   = "J. Panetta <panetta@slac.stanford.edu> SLAC - GLAST LAT I&T/Online"
00013 __date__     = ("$Date: 2004/11/08 21:03:12 $").split(' ')[1]
00014 __version__  = "$Revision: 2.2 $"
00015 __release__  = "$Name: R04-12-00 $"
00016 __credits__  = "SLAC"
00017 
00018 import LATTE.copyright_SLAC
00019 
00020 import                           time
00021 from Numeric                     import array, zeros
00022 
00023 from LATTE.tools.taskEngine      import TaskEngine
00024 from LATTE.database.gLAT         import *
00025 from LATTE.trigger.TrgObject     import TrgObject
00026 from thread                      import allocate_lock
00027 
00028 class AcdHWMultiplexer(object):
00029   """\brief AcdHWMultiplexer class
00030 
00031   A class to multiplex the two ACD hardware scalers defined in
00032   section 2.6.2 of the GEM document, LAT-TD-01545 into up to 108
00033   separate counters.
00034 
00035   """
00036   __DEFAULT_DWELL_TIME             = 1    # Default to 1 second
00037 
00038   def __init__(self, GEM):
00039     """\brief AcdHWMultiplexer constructor
00040 
00041     \param GEM  a GEM object
00042     """
00043     self.__gemst = GEM.downGEMST()
00044     self.__gemie = GEM.downGEMIE()
00045 
00046     self.__dwell = None
00047     self.__tList = None
00048     self.__stats = None
00049 
00050     self.__accumEngine = TaskEngine("AcdHWMultiplexer")
00051     self.__accumEngine.start()
00052 
00053     self.__statsLock  = allocate_lock()
00054 
00055     self.__setupDone  = False
00056     self.__stopAccum  = False
00057     self.__abortAccum = False
00058 
00059     self.__sortIEregs()
00060 
00061   def start(self):
00062     """\brief Method for starting the accumulation of ACD hardware scalers
00063 
00064     Start the integration of the hardware counters.
00065     At the start of integration, the counters are all reset to zero (0).
00066     """
00067     # invalidate setup to reset stats, etc.
00068     self.__setupDone = False
00069     # spawn the accumulate engine
00070     self.__accumEngine.spawn(self.__accumulate)
00071 
00072   def stop(self):
00073     """\brief Method for stopping the accumulation of ACD hardware scalers
00074 
00075     Stop the integration of the hardware counters.
00076     The stop occurs at the end of the current cycle, and
00077     the counts from the current cycle are integrated into the count
00078     statistics
00079     """
00080     self.__stopAccum = True
00081 
00082   def resume(self):
00083     """\brief Method for resuming the accumulation of ACD hardware scalers after a stop
00084 
00085     Resume the integration of the hardware counters after a stop()
00086     call.  At resume of integration, the internal counters are not reset, but
00087     continue from their previous values.
00088     """
00089     # spawn the accumulate engine
00090     self.__stopAccum = False
00091     self.__accumEngine.spawn(self.__accumulate)
00092 
00093   def abort(self):
00094     """\brief Method for aborting the accumulation of ACD hardware scalers
00095 
00096     Abort the integration of the hardware counters.  The cycle
00097     stops immediately, and the set of counts from the current cycle
00098     is discarded.
00099     """
00100     self.__abortAccum = True
00101 
00102   def shutdown(self):
00103     """\brief Method for shutting down the Multiplexer.
00104 
00105     Shut down the thread the multiplexer is running in.  Should be
00106     called during endRun.
00107     """
00108     self.__accumEngine.shutdown()
00109 
00110   def dwell(self, d=None):
00111     """\brief Method to set the dwell time for scaler integration
00112 
00113     Set the dwell time (in seconds) for integration.
00114     Total time in a cycle through the scalers will be dwell * nTiles.
00115     Minimum dwell time is 0.1 seconds.  Default is 1 second.
00116     \param   dwell  Dwell time in seconds, default = 1 second
00117     """
00118     if d is not None:
00119       if d < 0.1:
00120         d = 0.1
00121       self.__dwell = d
00122       self.__setupDone = False      # invalidate setup, need to recompute stuff
00123     return self.__dwell
00124 
00125   def tileList(self, tList=None):
00126     """\brief Method to set which tiles are integrated
00127 
00128     Defines the list of tiles which are being integrated.
00129     Ex: range(108); [0,2,4,6]
00130 
00131     \param   tList  The list of tiles to be integrated.
00132     \return  The list of tiles that are being integrated
00133     """
00134     if tList is not None:
00135       self.__tList = tList
00136       self.__setupDone = False      # invalidate setup, need to recompute stuff
00137     return self.__tList
00138 
00139   def stats(self):
00140     """\brief Method to access the counter statistics
00141 
00142     Provides the user with the a list containing the counter statistics.
00143     This list corresponds to the tiles in tileList.
00144 
00145     \return The list of the tile statistics.
00146     """
00147     # Prevent multithread access to self.__stats with a lock
00148     self.__statsLock.acquire()
00149     s = self.__stats.tolist()
00150     self.__statsLock.release()
00151     return s
00152 
00153 
00154 # private:
00155   def __setup(self):
00156     """Set up the system
00157     """
00158     # Make sure we're able to run.
00159     self.__stopAccum  = False
00160     self.__abortAccum = False
00161     self.__setupDone  = True
00162 
00163     # error checking
00164     if self.__tList is None:
00165       msg = "No list of tiles defined for the multiplexer."
00166       raise Exception, msg
00167 
00168     # No dwell time specified?
00169     if self.__dwell is None:
00170       self.__dwell = AcdHWMultiplexer.__DEFAULT_DWELL_TIME
00171 
00172     # Check integrity of tile list
00173     for tile in self.__tList:
00174       if tile < TrgObject.TILE_NUMBER_MIN or \
00175          tile > TrgObject.TILE_NUMBER_MAX:
00176         msg = "Tile number %d is out of range [%d, %d]" % \
00177         ( tile, TrgObject.TILE_NUMBER_MIN, TrgObject.TILE_NUMBER_MAX )
00178         raise IndexError, msg
00179 
00180     # set up internal array structure
00181     self.__tListInt = array( self.__tList )
00182 
00183     # create our internal and external stats arrays
00184     self.__statsInt = zeros( self.__tListInt.shape )
00185     self.__stats    = zeros( self.__tListInt.shape )
00186 
00187   def __accumulate(self):
00188     """ This is where the work is really done.
00189     """
00190     if not self.__setupDone:
00191       self.__setup()
00192 
00193     sweepSize = len(self.__tListInt)
00194 
00195     while ( not self.__stopAccum ):
00196       for tileSet in range(0,sweepSize,2):
00197         # Check for abort here
00198         if self.__abortAccum:
00199           print "abort"
00200           return
00201 
00202         tile_0 = self.__tListInt[tileSet]
00203         if tileSet+1 < sweepSize:
00204           tile_1 = self.__tListInt[tileSet+1]
00205         else:
00206           tile_1 = None
00207 
00208         # cache input enables
00209         regList  = self.__gemie.regs.values()
00210         self.__regCache = zeros( (len(regList)) )
00211         for reg in regList:
00212           if reg.size() > 0:
00213             self.__regCache[reg.id()] = reg.get()
00214 
00215         # set up counters
00216         self.__gemst.TILE_0 = tile_0
00217         if tile_1 is not None:
00218           self.__gemst.TILE_1 = tile_1
00219 
00220         # enable the proper tiles
00221         self.__setIE(tile_0)
00222         if tile_1 is not None:
00223           self.__setIE(tile_1)
00224 
00225         self.__gemst.TILE_COUNTERS = 0
00226         # Accumulate
00227         time.sleep(self.__dwell)
00228         count = self.__gemst.TILE_COUNTERS
00229 
00230         # reset the input enables
00231         self.__resetIE(tile_0)
00232         if tile_1 is not None:
00233           self.__resetIE(tile_1)
00234 
00235         # pull counters
00236         self.__statsInt[tileSet] = ( count >>  0 ) & 0xffff
00237         if tile_1 is not None:
00238           self.__statsInt[tileSet+1] = ( count >> 16 ) & 0xffff
00239 
00240       # Send internal stats into external stats
00241       # Prevent multithread access to self.__stats with a lock
00242       self.__statsLock.acquire()
00243       self.__stats += self.__statsInt
00244       self.__statsLock.release()
00245     print "stopped"
00246 
00247   def __setIE(self,tile):
00248     # set the corresponding bits in the IE on for a tile
00249 
00250     reg,bit = divmod(tile,9)
00251     value   = ( 1 << bit ) + ( 1 << bit+9 )  # two nine bit fields
00252     self.__gemieDict[reg+5].set( self.__gemieDict[reg+5].get() | value )         # tile enables start at 5
00253 
00254   def __resetIE(self,tile):
00255     # reset the changed input enables to their cached values
00256     reg,bit = divmod(tile,9)
00257     self.__gemieDict[reg+5].set( self.__regCache[reg+5] )
00258 
00259   def __sortIEregs(self):
00260     # create a lookup table based on register number
00261     regList  = self.__gemie.regs.values()
00262     self.__gemieDict = {}
00263     for reg in regList:
00264       if reg.size() > 0:
00265         self.__gemieDict[reg.id()] = reg
00266 

Generated on Fri Jul 21 13:26:26 2006 for LATTE R04-12-00 by doxygen 1.4.3