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):
while not exitFlag:
unpackedAdcData = self.unpackedDataQueue.get()
self.logger.debug("Read data from unpacked data queue = \n%s"%( ' , '.join([format(i,'08x') for i in unpackedAdcData ]) ))
unpackedData = self.unpackedDataQueue.get()
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 = unpackedAdcData.pop(0)
timeStamp = unpackedAdcData.pop(0)
[ eventNumber , timeStamp , AdcData ] = unpackedData
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
class MarocReadoutThread(threading.Thread):
"""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)
self.threadID = threadID
self.board = board
self.name = name
self.rawDataQueue = rawDataQueue
self.numTriggers = numTriggers
self.debugLevel = debugLevel
self.logger = logging.getLogger(__name__)
......@@ -30,18 +31,20 @@ class MarocReadoutThread(threading.Thread):
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" )
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.
marocData = MarocDAQ.MarocDAQ(board,debugLevel)
while not exitFlag:
# Read data from MAROC
......@@ -49,8 +52,18 @@ def readout_maroc(name, board , rawDataQueue , logger , debugLevel):
# fill the queue
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 ]) ))
rawDataQueue.put(event)
# 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 @@
from ROOT import TFile, TTree
from array import array
from time import sleep , time
from ROOT import gROOT
import logging
from marocLogging import marocLogging
from array import array
class MarocRecording(object):
def __init__(self, fileName="marocData.root" , debugLevel=logging.DEBUG ):
......@@ -24,31 +20,42 @@ class MarocRecording(object):
self.fileName = fileName
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"
self.rootTree = TTree( 'T', 'Maroc ADC Data' )
self.eventNumber = array( 'l' , [0] )
self.timeStamp = array( 'l' , [0] )
self.adcData = array( 's' , self.nADC*[0] )
self.rootTree.Branch( 'marocEventHeader' , self.adcStruct , "EventNumber/I:TimeStamp/I:ADCData[64]/s")
# create a branch for each piece of data
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 ):
def writeEvent( self, eventNumber, timeStamp , adcData ):
"""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.fileHandle.Write()
def closeFile( self ):
"""Flush data to file and close file"""
self.logger.info("Closing ROOT file %s"%(self.fileName))
self.fileHandle.Write()
self.fileHandle.Close()
......@@ -35,16 +35,21 @@ class MarocRecordingThread(threading.Thread):
while not exitFlag:
unpackedAdcData = self.unpackedDataQueue.get()
self.logger.debug("Read data from unpacked data queue = \n%s"%( ' , '.join([format(i,'08x') for i in unpackedAdcData ]) ))
unpackedData = self.unpackedDataQueue.get()
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)))
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.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
import Queue
import array
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"""
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)
self.threadID = threadID
self.name = name
self.rawDataQueue = rawDataQueue
self.unpackedDataQueue = unpackedDataQueue
self.recordingDataQueue = recordingDataQueue
self.histogramDataQueue = histogramDataQueue
self.debugLevel = debugLevel
self.logger = logging.getLogger(__name__)
......@@ -33,7 +36,7 @@ class MarocUnpackingThread(threading.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" )
......@@ -66,13 +69,19 @@ def greyIntToInt(greyInt):
normalBin = gray2bin(greyBin)
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:
adcData = rawDataQueue.get()
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
busWidth = 32
nADC = 64
......@@ -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)))
#assert adcDataSize == len(adcData)
unpackedData = [adcData[0],adcData[1]] # fill first and second words with trigger number and timestamp
unpackedAdcData = array.array('H')
eventNumber = adcData[0]
eventTimeStamp = adcData[1]
for adcNumber in range(0 , nADC) :
lowBit = adcNumber*nBits
lowWord = (adcDataSize-1) - (lowBit /busWidth) # rounds to integer
......@@ -97,9 +107,23 @@ def unpack_maroc_data(name, rawDataQueue , unpackedDataQueue , logger):
adcValueBin = greyIntToInt(adcValue)
unpackedData.append(adcValueBin)
unpackedAdcData.append(adcValueBin)
logger.debug("Unpacked data = \n%s"%( ' , '.join([format(i,'08x') for i in unpackedData ]) ))
unpackedDataQueue.put(unpackedData)
logger.debug("Event number, timestamp, Unpacked ADC data = %i %i \n%s"%( eventNumber, eventTimeStamp , ' , '.join([format(i,'08x') for i in unpackedAdcData ]) ))
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
from optparse import OptionParser
import csv
from marocLogging import marocLogging
import logging
import MarocReadoutThread
import MarocUnpackingThread
import MarocRecordingThread
import MarocHistogrammingThread
import MarocRunControlThread
import MarocConfiguration
from PyChipsUser import *
import Queue
logger = logging.getLogger(__name__)
marocLogging(logger,logging.DEBUG)
parser = OptionParser()
parser.add_option("-i", dest = 'ipAddress' , default="192.168.200.16")
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()
print "IP address = " + options.ipAddress
print "Board address table " + options.boardAddressTable
logger.info("IP address = %s"%( options.ipAddress))
logger.info("Board address table %s"%( options.boardAddressTable))
numTriggers = int(options.numTriggers)
logger.info("Event limit = %i "%( numTriggers))
bAddrTab = AddressTable(options.boardAddressTable)
board = ChipsBusUdp(bAddrTab,options.ipAddress,50001)
......@@ -37,16 +51,40 @@ firmwareID = board.read("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()
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()
unpackerThread.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