Commit 716ff8db authored by David Cussans's avatar David Cussans

MarocConfiguration - class that writes to registers in FPGA , including register…

MarocConfiguration - class that writes to registers in FPGA , including register that controls interface to MAROC slow control. Reads data to write to slow control from CSV file.

takeMarocData.py - passes number of events to readout thread. Passes file name to recording thread. Waits for threads to finish before exiting

MarocRecording.py - eventually sorted out how to record to a ROOT file. Inefficient at the moment. 

MarocSC.py - started to add ability to store register values in CSV file as well as contents of MAROC SC registers.

MarocHistogrammingThread.py,MarocReadoutThread.py,MarocRecordingThread.py,MarocUnpackingThread.py - when readout thread reaches event limit it passes a "special" event along processing pipeline that causes threads to exit.

MarocRunControlThread.py - beginnings of a run-control thread. Not used at the moment.



git-svn-id: https://svn2.phy.bris.ac.uk/svn/uob-hep-pc049a/trunk@37 e1591323-3689-4d5a-aa31-d1a7cbdc5706
parent 311a7be8
#
# Python class to configure single Maroc board pc049a
#
import logging
from marocLogging import marocLogging
import MarocSC
class MarocConfiguration(object):
def __init__(self,board,configurationFile = "marocConfig.csv" , debugLevel = logging.DEBUG):
"""Class to configure MAROC and FPGA registers for pc049a"""
self.board = board # pointer to PyChips object
self.logger = logging.getLogger(__name__)
marocLogging(self.logger,debugLevel)
self.slowControlObject = MarocSC.MarocSC()
def configure(self):
self.logger.info("Configuring board")
self.slowControlObject.setParameterValue("DAC",[650,450])
self.slowControlObject.setFlagValue("d1_d2",0)
self.slowControlObject.setFlagValue("cmd_fsb_fsu",1) # Select FSU
self.slowControlObject.setParameterValue("mask_OR",0x3,54) # Mask hot channel
SCData = self.slowControlObject.getWordArray() # Get data to write
self.logger.debug("Slow control data = %s"%( ' , '.join([format(i,'08x') for i in SCData ]) ))
# write to slow control output data buffer
self.board.blockWrite("scSrDataOut",SCData)
self.board.write("scSrCtrl" , 0x00000000)
# set up triggers
#triggerSource = 0x0000000D
triggerSource = 0x00000008
self.board.write("trigSourceSelect",triggerSource) # Set OR1,OR2 and internal triggers active
trigSourceReadback = self.board.read("trigSourceSelect")
self.logger.debug( "Trigger source select register = %s" % (hex(trigSourceReadback)))
self.logger.debug( "Resetting timestamp and trigger counters")
self.board.write("trigStatus",0x00000001)
# Reset ADC buffer write buffer
self.board.write("adc0Ctrl",0x00000002)
...@@ -36,19 +36,26 @@ class MarocHistogrammingThread(threading.Thread): ...@@ -36,19 +36,26 @@ class MarocHistogrammingThread(threading.Thread):
while not exitFlag: while not exitFlag:
unpackedAdcData = self.unpackedDataQueue.get() unpackedData = self.unpackedDataQueue.get()
self.logger.debug("Read data from unpacked data queue = \n%s"%( ' , '.join([format(i,'08x') for i in unpackedAdcData ]) )) if len(unpackedData) == 1:
self.logger.info("Swallowed poison pill from readout thread.")
exitFlag = True
continue
self.logger.debug("event size = %i"%( len(unpackedAdcData)))
[ eventNumber , timeStamp , AdcData ] = unpackedData
eventNumber = unpackedAdcData.pop(0)
timeStamp = unpackedAdcData.pop(0)
self.logger.info("Event number , timestamp = %i %i "%(eventNumber, timeStamp)) self.logger.info("Event number , timestamp = %i %i "%(eventNumber, timeStamp))
self.logger.debug("Read ADC data from unpacked data queue = \n%s"%( ' , '.join([format(i,'08x') for i in AdcData ]) ))
self.logger.debug("event size = %i"%( len(AdcData)))
#eventNumber = unpackedAdcData.pop(0)
#timeStamp = unpackedAdcData.pop(0)
self.histogramObject.fillHistograms(eventNumber,timeStamp,unpackedAdcData) self.histogramObject.fillHistograms(eventNumber,timeStamp,AdcData)
print "Exiting " + self.name self.logger.info( "Ending thread" )
......
...@@ -17,12 +17,13 @@ from marocLogging import marocLogging ...@@ -17,12 +17,13 @@ from marocLogging import marocLogging
class MarocReadoutThread(threading.Thread): class MarocReadoutThread(threading.Thread):
"""Class with functions that can read out MAROC3 using IPBus. Inherits from threading class, so has a 'start' method""" """Class with functions that can read out MAROC3 using IPBus. Inherits from threading class, so has a 'start' method"""
def __init__(self, threadID, name, board , rawDataQueue , debugLevel=logging.DEBUG ): def __init__(self, threadID, name, board , rawDataQueue , numTriggers, debugLevel=logging.DEBUG ):
threading.Thread.__init__(self) threading.Thread.__init__(self)
self.threadID = threadID self.threadID = threadID
self.board = board self.board = board
self.name = name self.name = name
self.rawDataQueue = rawDataQueue self.rawDataQueue = rawDataQueue
self.numTriggers = numTriggers
self.debugLevel = debugLevel self.debugLevel = debugLevel
self.logger = logging.getLogger(__name__) self.logger = logging.getLogger(__name__)
...@@ -30,18 +31,20 @@ class MarocReadoutThread(threading.Thread): ...@@ -30,18 +31,20 @@ class MarocReadoutThread(threading.Thread):
marocLogging(self.logger,self.debugLevel) marocLogging(self.logger,self.debugLevel)
self.logger.info( "Starting thread" ) self.logger.info( "Starting thread. Event limit = %i" %(self.numTriggers) )
readout_maroc(self.name, self.board , self.rawDataQueue , self.logger , self.debugLevel) readout_maroc(self.name, self.board , self.rawDataQueue , self.numTriggers , self.logger , self.debugLevel)
self.logger.info( "Exiting thread" ) self.logger.info( "Exiting thread" )
exitFlag = 0
def readout_maroc(name, board , rawDataQueue , logger , debugLevel):
def readout_maroc(name, board , rawDataQueue , numTriggers , logger , debugLevel):
exitFlag = False
# Create pointer to MAROC board and set up structures. # Create pointer to MAROC board and set up structures.
marocData = MarocDAQ.MarocDAQ(board,debugLevel) marocData = MarocDAQ.MarocDAQ(board,debugLevel)
while not exitFlag: while not exitFlag:
# Read data from MAROC # Read data from MAROC
...@@ -49,8 +52,18 @@ def readout_maroc(name, board , rawDataQueue , logger , debugLevel): ...@@ -49,8 +52,18 @@ def readout_maroc(name, board , rawDataQueue , logger , debugLevel):
# fill the queue # fill the queue
for event in events: for event in events:
eventNumber = event[0]
logger.info("Read event %i",eventNumber)
if ( eventNumber > numTriggers):
exitFlag = True
logger.info("Setting exitFlag = True")
logger.debug("Pushing data into raw data queue = \n%s"%( ' , '.join([format(i,'08x') for i in event ]) )) logger.debug("Pushing data into raw data queue = \n%s"%( ' , '.join([format(i,'08x') for i in event ]) ))
rawDataQueue.put(event) rawDataQueue.put(event)
# TODO - set exit flag when told to by run control. Start and stop run when told to by run control. # TODO - set exit flag when told to by run control. Start and stop run when told to by run control.
poisonPill = [-1]
rawDataQueue.put(poisonPill)
logger.info("Fed poison pill to unpacker")
...@@ -4,15 +4,11 @@ ...@@ -4,15 +4,11 @@
from ROOT import TFile, TTree from ROOT import TFile, TTree
from array import array from ROOT import gROOT
from time import sleep , time
import logging import logging
from marocLogging import marocLogging from marocLogging import marocLogging
from array import array
class MarocRecording(object): class MarocRecording(object):
def __init__(self, fileName="marocData.root" , debugLevel=logging.DEBUG ): def __init__(self, fileName="marocData.root" , debugLevel=logging.DEBUG ):
...@@ -24,31 +20,42 @@ class MarocRecording(object): ...@@ -24,31 +20,42 @@ class MarocRecording(object):
self.fileName = fileName self.fileName = fileName
self.fileHandle = TFile( fileName, 'RECREATE' ) self.fileHandle = TFile( fileName, 'RECREATE' )
gROOT.ProcessLine(
"struct ADCStruct {\
UInt_t fMarocEventNumber;\
UInt_t fMarocTimeStamp;\
UShort_t fMarocAdcData[64];\
};" );
from ROOT import ADCStruct
self.adcStruct = ADCStruct()
# Create a root "tree" # Create a root "tree"
self.rootTree = TTree( 'T', 'Maroc ADC Data' ) self.rootTree = TTree( 'T', 'Maroc ADC Data' )
self.eventNumber = array( 'l' , [0] ) self.rootTree.Branch( 'marocEventHeader' , self.adcStruct , "EventNumber/I:TimeStamp/I:ADCData[64]/s")
self.timeStamp = array( 'l' , [0] )
self.adcData = array( 's' , self.nADC*[0] )
# create a branch for each piece of data def writeEvent( self, eventNumber, timeStamp , adcData ):
tree.Branch( 'marocEventNumber' , self.eventNumber , "EventNumber/l")
tree.Branch( 'marocTimeStamp' , self.timeStamp , "TimeStamp/l")
tree.Branch( 'marcoADCData' , self.adcData , "ADCData[64]/s")
def writeEvent( self, eventNumber, timeStamp , ADCData ):
"""Write an event to ROOT file""" """Write an event to ROOT file"""
self.eventNumber = eventNumber
self.timeStamp = timeStamp
self.adcData = ADCData
# copy data into ROOT data-structure
# This is a Nasty, Nasty hack. Improve when possible. This is just copying data.....
self.adcStruct.fMarocEventNumber = eventNumber
self.adcStruct.fMarocTimeStamp = timeStamp
for idx in range(64):
self.adcStruct.fMarocAdcData[idx] = adcData[idx]
self.logger.debug("event number, timestamp = %i %i "%(self.adcStruct.fMarocEventNumber , self.adcStruct.fMarocTimeStamp))
self.rootTree.Fill() self.rootTree.Fill()
self.fileHandle.Write()
def closeFile( self ): def closeFile( self ):
"""Flush data to file and close file"""
self.logger.info("Closing ROOT file %s"%(self.fileName)) self.logger.info("Closing ROOT file %s"%(self.fileName))
self.fileHandle.Write()
self.fileHandle.Close() self.fileHandle.Close()
...@@ -35,16 +35,21 @@ class MarocRecordingThread(threading.Thread): ...@@ -35,16 +35,21 @@ class MarocRecordingThread(threading.Thread):
while not exitFlag: while not exitFlag:
unpackedAdcData = self.unpackedDataQueue.get() unpackedData = self.unpackedDataQueue.get()
self.logger.debug("Read data from unpacked data queue = \n%s"%( ' , '.join([format(i,'08x') for i in unpackedAdcData ]) ))
if len(unpackedData) == 1:
self.logger.info("Swallowed poison pill from unpacking thread.")
exitFlag = True
continue
[ eventNumber , timeStamp , unpackedAdcData ] = unpackedData
self.logger.debug("Read ADC data from unpacked data queue event number , timestamp, ADC-data = %i %i \n%s"%( (eventNumber, timeStamp , ' , '.join([format(i,'08x') for i in unpackedAdcData ]) )))
self.logger.debug("event size = %i"%( len(unpackedAdcData))) self.logger.debug("event size = %i"%( len(unpackedAdcData)))
eventNumber = unpackedAdcData.pop(0)
timeStamp = unpackedAdcData.pop(0)
self.logger.info("Event number , timestamp = %i %i "%(eventNumber, timeStamp))
self.fileObject.writeEvent(eventNumber,timeStamp,unpackedAdcData) self.fileObject.writeEvent(eventNumber,timeStamp,unpackedAdcData)
self.fileObject.closeFile()
print "Exiting " + self.name self.logger.info( "Ending thread" )
# Python class to read ADC data from readout thread and unpack into ADC values.
#
import logging
from PyChipsUser import *
import threading
import time
import Queue
import MarocRecording
from marocLogging import marocLogging
class MarocRecordingThread(threading.Thread):
"""Class with functions that can store data from MAROC3 into a ROOT file as a TTree. Inherits from threading class, so has a 'start' method"""
def __init__(self, threadID, name , unpackedDataQueue , fileName="marocData.root" , debugLevel=logging.DEBUG ):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.unpackedDataQueue = unpackedDataQueue
self.debugLevel = debugLevel
self.fileName = fileName
self.fileObject = MarocRecording.MarocRecording(fileName=fileName,debugLevel=debugLevel)
self.logger = logging.getLogger(__name__)
def run(self):
exitFlag = 0
marocLogging(self.logger,self.debugLevel)
self.logger.info( "Starting thread" )
while not exitFlag:
unpackedData = self.unpackedDataQueue.get()
[ eventNumber , timeStamp , unpackedAdcData ] = unpackedData
self.logger.debug("Read ADC data from unpacked data queue event number , timestamp, ADC-data = %i %i \n%s"%( (eventNumber, timeStamp , ' , '.join([format(i,'08x') for i in AdcData ]) )))
#self.logger.debug("Read unpacked data from unpacked data queue = \n%s"%( ' , '.join([format(i,'08x') for i in unpackedAdcData ]) ))
self.logger.debug("event size = %i"%( len(unpackedAdcData)))
self.fileObject.writeEvent(eventNumber,timeStamp,unpackedAdcData)
self.logger.info( "Ending thread" )
This diff is collapsed.
...@@ -16,14 +16,17 @@ import time ...@@ -16,14 +16,17 @@ import time
import Queue import Queue
import array
class MarocUnpackingThread(threading.Thread): class MarocUnpackingThread(threading.Thread):
"""Class with functions that can read unpack raw MAROC3 ADC data and pack into an array of integers. Inherits from threading class, so has a 'start' method""" """Class with functions that can read unpack raw MAROC3 ADC data and pack into an array of integers. Inherits from threading class, so has a 'start' method"""
def __init__(self, threadID, name , rawDataQueue , unpackedDataQueue , debugLevel=logging.DEBUG ): def __init__(self, threadID, name , rawDataQueue , recordingDataQueue, histogramDataQueue , debugLevel=logging.DEBUG ):
threading.Thread.__init__(self) threading.Thread.__init__(self)
self.threadID = threadID self.threadID = threadID
self.name = name self.name = name
self.rawDataQueue = rawDataQueue self.rawDataQueue = rawDataQueue
self.unpackedDataQueue = unpackedDataQueue self.recordingDataQueue = recordingDataQueue
self.histogramDataQueue = histogramDataQueue
self.debugLevel = debugLevel self.debugLevel = debugLevel
self.logger = logging.getLogger(__name__) self.logger = logging.getLogger(__name__)
...@@ -33,7 +36,7 @@ class MarocUnpackingThread(threading.Thread): ...@@ -33,7 +36,7 @@ class MarocUnpackingThread(threading.Thread):
self.logger.info( "Starting thread" ) self.logger.info( "Starting thread" )
unpack_maroc_data(self.name, self.rawDataQueue , self.unpackedDataQueue , self.logger) unpack_maroc_data(self.name, self.rawDataQueue , self.recordingDataQueue , self.histogramDataQueue , self.logger)
self.logger.info( "Ending thread" ) self.logger.info( "Ending thread" )
...@@ -66,13 +69,19 @@ def greyIntToInt(greyInt): ...@@ -66,13 +69,19 @@ def greyIntToInt(greyInt):
normalBin = gray2bin(greyBin) normalBin = gray2bin(greyBin)
return bin2int(normalBin) return bin2int(normalBin)
exitFlag = 0
def unpack_maroc_data(name, rawDataQueue , unpackedDataQueue , logger): def unpack_maroc_data(name, rawDataQueue , recordingDataQueue, histogramDataQueue , logger):
exitFlag = False
while not exitFlag: while not exitFlag:
adcData = rawDataQueue.get() adcData = rawDataQueue.get()
logger.debug("Read data from raw data queue = \n%s"%( ' , '.join([format(i,'08x') for i in adcData ]) )) logger.debug("Read data from raw data queue = \n%s"%( ' , '.join([format(i,'08x') for i in adcData ]) ))
if len(adcData) == 1:
logger.info("Swallowed poison pill from readout thread.")
exitFlag = True
continue
nBits = 12 nBits = 12
busWidth = 32 busWidth = 32
nADC = 64 nADC = 64
...@@ -80,9 +89,10 @@ def unpack_maroc_data(name, rawDataQueue , unpackedDataQueue , logger): ...@@ -80,9 +89,10 @@ def unpack_maroc_data(name, rawDataQueue , unpackedDataQueue , logger):
logger.info("event number , time-stamp , event size = %i %i %i"%( adcData[0],adcData[1],len(adcData))) logger.info("event number , time-stamp , event size = %i %i %i"%( adcData[0],adcData[1],len(adcData)))
#assert adcDataSize == len(adcData) #assert adcDataSize == len(adcData)
unpackedAdcData = array.array('H')
unpackedData = [adcData[0],adcData[1]] # fill first and second words with trigger number and timestamp eventNumber = adcData[0]
eventTimeStamp = adcData[1]
for adcNumber in range(0 , nADC) : for adcNumber in range(0 , nADC) :
lowBit = adcNumber*nBits lowBit = adcNumber*nBits
lowWord = (adcDataSize-1) - (lowBit /busWidth) # rounds to integer lowWord = (adcDataSize-1) - (lowBit /busWidth) # rounds to integer
...@@ -97,9 +107,23 @@ def unpack_maroc_data(name, rawDataQueue , unpackedDataQueue , logger): ...@@ -97,9 +107,23 @@ def unpack_maroc_data(name, rawDataQueue , unpackedDataQueue , logger):
adcValueBin = greyIntToInt(adcValue) adcValueBin = greyIntToInt(adcValue)
unpackedData.append(adcValueBin) unpackedAdcData.append(adcValueBin)
logger.debug("Unpacked data = \n%s"%( ' , '.join([format(i,'08x') for i in unpackedData ]) )) logger.debug("Event number, timestamp, Unpacked ADC data = %i %i \n%s"%( eventNumber, eventTimeStamp , ' , '.join([format(i,'08x') for i in unpackedAdcData ]) ))
unpackedDataQueue.put(unpackedData) unpackedData = [eventNumber, eventTimeStamp, unpackedAdcData]
# Push the data to histogramming
# only push data if the queue has space in it
if not histogramDataQueue.full():
histogramDataQueue.put(unpackedData)
# Push data to recording.
recordingDataQueue.put(unpackedData)
poisonPill = [-1]
histogramDataQueue.put(poisonPill)
logger.info("Fed poison pill to histogrammer")
recordingDataQueue.put(poisonPill)
logger.info("Fed poison pill to data recorder")
...@@ -7,28 +7,42 @@ import time ...@@ -7,28 +7,42 @@ import time
from optparse import OptionParser from optparse import OptionParser
import csv import csv
from marocLogging import marocLogging
import logging
import MarocReadoutThread import MarocReadoutThread
import MarocUnpackingThread import MarocUnpackingThread
import MarocRecordingThread
import MarocHistogrammingThread import MarocHistogrammingThread
import MarocRunControlThread
import MarocConfiguration
from PyChipsUser import * from PyChipsUser import *
import Queue import Queue
logger = logging.getLogger(__name__)
marocLogging(logger,logging.DEBUG)
parser = OptionParser() parser = OptionParser()
parser.add_option("-i", dest = 'ipAddress' , default="192.168.200.16") parser.add_option("-i", dest = 'ipAddress' , default="192.168.200.16")
parser.add_option("-a", dest = 'boardAddressTable' , default="./pc049aAddrTable.txt") parser.add_option("-a", dest = 'boardAddressTable' , default="./pc049aAddrTable.txt")
parser.add_option("-o", dest = 'outputFile' , default = 'marocTimeStamps.dat' ) parser.add_option("-o", dest = 'outputFile' , default = 'marocTimeStamps.root' )
parser.add_option("-n" , dest = 'numTriggers' , default = 600 ) parser.add_option("-n" , dest = 'numTriggers' , default = 1000 )
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
print "IP address = " + options.ipAddress logger.info("IP address = %s"%( options.ipAddress))
print "Board address table " + options.boardAddressTable logger.info("Board address table %s"%( options.boardAddressTable))
numTriggers = int(options.numTriggers)
logger.info("Event limit = %i "%( numTriggers))
bAddrTab = AddressTable(options.boardAddressTable) bAddrTab = AddressTable(options.boardAddressTable)
board = ChipsBusUdp(bAddrTab,options.ipAddress,50001) board = ChipsBusUdp(bAddrTab,options.ipAddress,50001)
...@@ -37,16 +51,40 @@ firmwareID = board.read("FirmwareId") ...@@ -37,16 +51,40 @@ firmwareID = board.read("FirmwareId")
print "Firmware ID = " , hex(firmwareID) print "Firmware ID = " , hex(firmwareID)
# Create object with configuration information - in the long run this should be done in a separate thread with a GUI
marocConfiguration = MarocConfiguration.MarocConfiguration(board,debugLevel=logging.DEBUG)
rawDataQueue = Queue.Queue() rawDataQueue = Queue.Queue()
unpackedDataQueue = Queue.Queue() recordingDataQueue = Queue.Queue()
histogramQueueSize = 100
histogramDataQueue = Queue.Queue(histogramQueueSize)
# Create a readout thread. Pass down an event limit. When the event limit is reached the readout thread will pass a message along chain and threads will terminate.
readoutThread = MarocReadoutThread.MarocReadoutThread(1,"readoutThread",board,rawDataQueue,numTriggers,debugLevel=logging.INFO)
readoutThread = MarocReadoutThread.MarocReadoutThread(1,"readoutThread",board,rawDataQueue,debugLevel=logging.INFO) unpackerThread = MarocUnpackingThread.MarocUnpackingThread(2,"unpackingThread",rawDataQueue,recordingDataQueue,histogramDataQueue,debugLevel=logging.INFO)
unpackerThread = MarocUnpackingThread.MarocUnpackingThread(2,"unpackingThread",rawDataQueue,unpackedDataQueue,debugLevel=logging.INFO) histogramThread = MarocHistogrammingThread.MarocHistogrammingThread(3,"histogrammingThread",histogramDataQueue,debugLevel=logging.INFO)
histogramThread = MarocHistogrammingThread.MarocHistogrammingThread(3,"histogrammingThread",unpackedDataQueue,debugLevel=logging.INFO) recordingThread = MarocRecordingThread.MarocRecordingThread(3,"recordingThread",recordingDataQueue,fileName=options.outputFile, debugLevel=logging.DEBUG)
# Send configuration to board.
marocConfiguration.configure()
# Having created the threads, now start them running
readoutThread.start() readoutThread.start()
unpackerThread.start() unpackerThread.start()
histogramThread.start() histogramThread.start()
recordingThread.start()
# Wait for threads to exit
readoutThread.join()
unpackerThread.join()
histogramThread.join()
recordingThread.join()
logger.info("All threads terminated. Exiting main programme")
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment