Commit 311a7be8 authored by David Cussans's avatar David Cussans

Adding more Python readout scripts.

takeMarocData - multi-threaded top level script to take data.

MarocReadoutThread , MarocHistogrammingThread , MarocRecordingThread - classes that inherit from Threading class



git-svn-id: https://svn2.phy.bris.ac.uk/svn/uob-hep-pc049a/trunk@36 e1591323-3689-4d5a-aa31-d1a7cbdc5706
parent 227bbaa4
##########################################################
# I2cBusProperties - simple encapsulation of all items
# required to control an I2C bus.
#
# Carl Jeske, July 2010
# Refactored by Robert Frazier, May 2011
##########################################################
class I2cBusProperties(object):
"""Encapsulates details of an I2C bus master in the form of a host device, a clock prescale value, and seven I2C master registers
Provide the ChipsBus instance to the device hosting your I2C core, a 16-bit clock prescaling
value for the Serial Clock Line (see I2C core docs for details), and the names of the seven
registers that define/control the bus (assuming these names are not the defaults specified
in the constructor below). The seven registers consist of the two clock pre-scaling
registers (PRElo, PREhi), and five bus master registers (CONTROL, TRANSMIT, RECEIVE,
COMMAND and STATUS).
Usage: You'll need to create an instance of this class to give to a concrete I2C bus instance, such
as OpenCoresI2cBus. This I2cBusProperties class is simply a container to hold the properties
that define the bus; a class such as OpenCoresI2cBus will make use of these properties.
Access the items stored by this class via these (deliberately compact) variable names:
chipsBus -- the ChipsBus device hosting the I2C core
preHiVal -- the top byte of the clock prescale value
preLoVal -- the bottom byte of the clock prescale value
preHiReg -- the register the top byte of the clk prescale value (preHiVal) gets written to
preLoReg -- the register the bottom byte of the clk prescale value (preLoVal) gets written to
ctrlReg -- the I2C Control register
txReg -- the I2C Transmit register
rxReg -- the I2C Receive register
cmdReg -- the I2C Command register
statusReg -- the I2C Status register
Compatibility Notes: The seven register names are the registers typically required to operate an
OpenCores or similar I2C Master (Lattice Semiconductor's I2C bus master works
the same way as the OpenCores one). This software is not compatible with your
I2C bus master if it doesn't use this register interface.
"""
def __init__(self,
chipsBusDevice,
clkPrescaleU16,
clkPrescaleLoByteReg = "i2c_pre_lo",
clkPrescaleHiByteReg = "i2c_pre_hi",
controlReg = "i2c_ctrl",
transmitReg = "i2c_tx",
receiveReg = "i2c_rx",
commandReg = "i2c_cmd",
statusReg = "i2c_status"):
"""Provide a host ChipsBus device that is controlling the I2C bus, and the names of five I2C control registers.
chipsBusDevice: Provide a ChipsBus instance to the device where the I2C bus is being
controlled. The address table for this device must contain the five registers
that control the bus, as declared next...
clkPrescaleU16: A 16-bit value used to prescale the Serial Clock Line based on the host
master-clock. This value gets split into two 8-bit values and ultimately will
get written to the two I2C clock-prescale registers as declared below. See
the OpenCores or Lattice Semiconductor I2C documentation for more details.
clkPrescaleLoByteReg: The register where the lower byte of the clock prescale value is set. The default
name for this register is "i2c_pre_lo".
clkPrescaleHiByteReg: The register where the higher byte of the clock prescale value is set. The default
name for this register is "i2c_pre_hi"
controlReg: The CONTROL register, used for enabling/disabling the I2C core, etc. This register is
usually read and write accessible. The default name for this register is "i2c_ctrl".
transmitReg: The TRANSMIT register, used for holding the data to be transmitted via I2C, etc. This
typically shares the same address as the RECEIVE register, but has write-only access. The default
name for this register is "i2c_tx".
receiveReg: The RECEIVE register - allows access to the byte received over the I2C bus. This
typically shares the same address as the TRANSMIT register, but has read-only access. The
default name for this register is "i2c_rx".
commandReg: The COMMAND register - stores the command for the next I2C operation. This typically
shares the same address as the STATUS register, but has write-only access. The default name for
this register is "i2c_cmd".
statusReg: The STATUS register - allows monitoring of the I2C operations. This typically shares
the same address as the COMMAND register, but has read-only access. The default name for this
register is "i2c_status".
"""
object.__init__(self)
self.chipsBus = chipsBusDevice
self.preHiVal = ((clkPrescaleU16 & 0xff00) >> 8)
self.preLoVal = (clkPrescaleU16 & 0xff)
# Check to see all the registers are in the address table
registers = [clkPrescaleLoByteReg, clkPrescaleHiByteReg, controlReg, transmitReg, receiveReg, commandReg, statusReg]
for reg in registers:
if not self.chipsBus.addrTable.checkItem(reg):
raise ChipsException("I2cBusProperties error: register '" + reg + "' is not present in the address table of the device hosting the I2C bus master!")
# Check that the registers we'll need to write to are indeed writable
writableRegisters = [clkPrescaleLoByteReg, clkPrescaleHiByteReg, controlReg, transmitReg, commandReg]
for wReg in writableRegisters:
if not self.chipsBus.addrTable.getItem(wReg).getWriteFlag():
raise ChipsException("I2cBusProperties error: register '" + wReg + "' does not have the necessary write permission!")
# Check that the registers we'll need to read from are indeed readable
readableRegisters = [clkPrescaleLoByteReg, clkPrescaleHiByteReg, controlReg, receiveReg, statusReg]
for rReg in readableRegisters:
if not self.chipsBus.addrTable.getItem(rReg).getReadFlag():
raise ChipsException("I2cBusProperties error: register '" + rReg + "' does not have the necessary read permission!")
# Store the various register name strings
self.preHiReg = clkPrescaleHiByteReg
self.preLoReg = clkPrescaleLoByteReg
self.ctrlReg = controlReg
self.txReg = transmitReg
self.rxReg = receiveReg
self.cmdReg = commandReg
self.statusReg = statusReg
#
# Python class to perform basic DAQ operations on MAROC readout board.
#
# needs python 2.6
import logging
from marocLogging import marocLogging
numMaroc = 1
class MarocDAQ(object):
def __init__(self,board,debugLevel):
"""Class to interface to MAROC-3 via IPBus"""
self.board = board # pointer to PyChips object
self.timeStampEventSize = 12
self.timeStampBufferSize = 512
self.adcEventSize = 26 # size of each event
self.adcBufferSize = 4096 # size of rolling buffer. Be careful - buffer size changes with firmware version.....
self.numMaroc = 1
self.timeStampReadPointer = 0
self.adcReadPointer = self.numMaroc*[0]
self.timeStampWritePointer = 0
self.adcWritePointer = self.numMaroc*[0]
self.logger = logging.getLogger(__name__)
marocLogging(self.logger,debugLevel)
def readORCounters(self):
"""Reads the number of pulses on OR1 , OR2 lines"""
trigOR1_counters = self.board.blockRead("trigOR1_0_Counter",5)
trigOR2_counters = self.board.blockRead("trigOR2_0_Counter",5)
return [ trigOR1_counters , trigOR2_counters ]
# --------------------------------------------------------------------------------------------------------------
def readTimeStampData(self):
"""Reads the whole timestamp buffer, takes the portion after the read pointer and spits it into events.
It can cope with wrap-round of circular buffer. Returns an array of 32-bit integers"""
eventData = []
# get current write pointer
self.timeStampWritePointer = self.board.read("trigDPRWritePointer")
# read out whole buffer
timeStampData = self.board.blockRead("trigTimestampBuffer",
self.timeStampBufferSize )
self.logger.debug( "Timestamp Data = \n%s"%( ' , '.join([format(i,'08x') for i in timeStampData ]) ))
timeStampEventNumber = timeStampData[ self.timeStampReadPointer ]
self.logger.debug("Event number from timestamp data = %i " %(timeStampEventNumber) )
self.logger.debug("Timestamp read , write pointers = %i , %i " %(self.timeStampReadPointer , self.timeStampWritePointer) )
if (self.timeStampWritePointer >= self.timeStampReadPointer ):
self.logger.debug("No pointer wrap round")
else:
# First cope with data from readpointer up to end of buffer
self.logger.debug("Pointer has wrapped round")
while ( (self.timeStampReadPointer+self.timeStampEventSize)<self.timeStampBufferSize):
boardData = timeStampData[ self.timeStampReadPointer:(self.timeStampReadPointer+self.timeStampEventSize)]
self.timeStampReadPointer += self.timeStampEventSize
self.logger.debug("self.timeStampReadPointer = %i " %( self.timeStampReadPointer) )
#print boardData
eventData.append(boardData)
# glue together the data that wraps round end of buffer
boardData = timeStampData[ self.timeStampReadPointer: ]
wordsRead = self.timeStampBufferSize - self.timeStampReadPointer
self.logger.debug("read pointer just before gluing %i" %( self.timeStampReadPointer))
self.logger.debug( "words read at top of buffer = %s" %( wordsRead))
self.timeStampReadPointer = self.timeStampEventSize - wordsRead
self.logger.debug( "read pointer set to %i " %( self.timeStampReadPointer))
boardData = boardData + timeStampData[0:self.timeStampReadPointer]
self.logger.debug( "glued event data = %s"%( " ,".join([format(i,'08x') for i in boardData ]) ))
eventData.append(boardData)
# Now pack the non wrap-round data into an event structure.
while ( (self.timeStampReadPointer+self.timeStampEventSize)<=self.timeStampWritePointer):
boardData = timeStampData[ self.timeStampReadPointer:(self.timeStampReadPointer+self.timeStampEventSize)]
self.timeStampReadPointer = self.timeStampReadPointer + self.timeStampEventSize
self.logger.debug( "readPointer = %i " %( self.timeStampReadPointer))
#print boardData
eventData.append(boardData)
return eventData
# --------------------------------------------------------------------------------------------------------------
def readADCData(self):
"""Reads the whole ADC buffer for a MAROC, takes the portion after the read pointer and spits it into events.
It can cope with wrap-round of circular buffer. Returns an array of arrays of 32-bit integers"""
marocNumber = 0
eventData = []
writePointerName= 'adc'+format(marocNumber,'1d')+'WritePointer'
dataName= 'adc'+format(marocNumber,'1d')+'Data'
self.logger.info("Reading ADC data read , write pointers = %i , %i " %(self.adcReadPointer[marocNumber] , self.adcWritePointer[marocNumber]) )
# get current write pointer
self.adcWritePointer[marocNumber] = self.board.read(writePointerName)
# read out whole buffer
adcData = self.board.blockRead(dataName,self.adcBufferSize )
self.logger.debug( "Adc Data = \n%s"%( ' , '.join([format(i,'08x') for i in adcData ]) ))
adcEventNumber = adcData[ self.adcReadPointer[marocNumber] ]
self.logger.debug("Event number from adc data = %i " %(adcEventNumber) )
if (self.adcWritePointer[marocNumber] >= self.adcReadPointer[marocNumber] ):
self.logger.debug("No pointer wrap round")
else:
# First cope with data from readpointer up to end of buffer
self.logger.debug("Pointer has wrapped round")
while ( (self.adcReadPointer[marocNumber]+self.adcEventSize)<self.adcBufferSize):
boardData = adcData[ self.adcReadPointer[marocNumber]:(self.adcReadPointer[marocNumber]+self.adcEventSize)]
self.adcReadPointer[marocNumber] += self.adcEventSize
self.logger.debug("self.adcReadPointer[marocNumber] = %i " %( self.adcReadPointer[marocNumber]) )
#print boardData
eventData.append(boardData)
# glue together the data that wraps round end of buffer
boardData = adcData[ self.adcReadPointer[marocNumber]: ]
wordsRead = self.adcBufferSize - self.adcReadPointer[marocNumber]
self.logger.debug("read pointer just before gluing %i" %( self.adcReadPointer[marocNumber]))
self.logger.debug( "words read at top of buffer = %s" %( wordsRead))
self.adcReadPointer[marocNumber] = self.adcEventSize - wordsRead
self.logger.debug( "read pointer set to %i " %( self.adcReadPointer[marocNumber]))
boardData = boardData + adcData[0:self.adcReadPointer[marocNumber]]
self.logger.debug( "glued event data = %s"%( " ,".join([format(i,'08x') for i in boardData ]) ))
eventData.append(boardData)
# Now pack the non wrap-round data into an event structure.
while ( (self.adcReadPointer[marocNumber]+self.adcEventSize)<=self.adcWritePointer[marocNumber]):
boardData = adcData[ self.adcReadPointer[marocNumber]:(self.adcReadPointer[marocNumber]+self.adcEventSize)]
self.adcReadPointer[marocNumber] = self.adcReadPointer[marocNumber] + self.adcEventSize
self.logger.debug( "readPointer = %i " %( self.adcReadPointer[marocNumber]))
#print boardData
eventData.append(boardData)
return eventData
def decodeADCData(self,adcEventData):
"""Takes data from a single ADC, unpacks it into 12-bit words, performs Gray coding and returns an array of 64-ADC values.
*** NB. This doesn't seem to work correctly at the moment ****"""
def grayToBinary(num):
for shift in [1,2,4,8,16]: # assume 32-bit numbers
num ^= num >> shift
return num
def reverseBits(x,width):
return int(bin(x)[2:].zfill(width)[::-1], 2)
adcValues = []
nBits=12
busWidth = 32
nADC = 64
assert len(adcEventData) == 26
adcEventNumber=adcEventData[0]
adcTimeStamp=adcEventData[1]
adcData = adcEventData[2:] # strip off event number and timestamp
for adcNumber in range(0 , nADC) :
lowBit = adcNumber*nBits
lowWord = lowBit /busWidth
lowBitPos = lowBit % busWidth
if adcNumber > (nADC-3):
longWord = adcData[lowWord]
else:
longWord = adcData[lowWord] + (adcData[lowWord+1] << busWidth)
adcValue = 0x0FFF & (longWord >> lowBitPos)
adcValues.append(grayToBinary(adcValue))
print "nADC, lowBit , lowWord , lowBitPos , hex(longWord) , hex(adcValue), hex(grey) , hex(reverse-gray)" , adcNumber , lowBit , lowWord , lowBitPos , format(longWord,'016x') , format(adcValue,'03x') , format(grayToBinary(adcValue),'03x'), format(grayToBinary(reverseBits(adcValue,12)),'03x')
return adcValues
#
# 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 MarocHistograms
from marocLogging import marocLogging
class MarocHistogrammingThread(threading.Thread):
"""Class with functions that can read unpacked MAROC3 ADC data histogramme the results. Inherits from threading class, so has a 'start' method"""
def __init__(self, threadID, name , unpackedDataQueue , debugLevel=logging.DEBUG ):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.unpackedDataQueue = unpackedDataQueue
self.debugLevel = debugLevel
self.histogramObject = MarocHistograms.MarocHistograms(debugLevel=debugLevel)
self.logger = logging.getLogger(__name__)
def run(self):
exitFlag = 0
marocLogging(self.logger,self.debugLevel)
self.logger.info( "Starting thread" )
self.histogramObject.createHistograms()
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 ]) ))
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.histogramObject.fillHistograms(eventNumber,timeStamp,unpackedAdcData)
print "Exiting " + self.name
#
# Python class to book histograms for MAROC data.
#
from ROOT import TCanvas, TF1 , TH1F , gRandom , gBenchmark
from time import sleep , time
from math import sqrt
import logging
from marocLogging import marocLogging
class MarocHistograms(object):
def __init__(self,nBits=12, nPlots=64, nPlotsPerCanvas=4 , histoColour = 42 , histoUpdateInterval = 2.0 , debugLevel=logging.DEBUG ):
"""Class to book ROOT Histograms to store MAROC data"""
self.nBits=nBits
self.nPlots=nPlots
self.nPlotsPerCanvas = nPlotsPerCanvas
self.debugLevel = debugLevel
self.histoColour = histoColour
self.canvases = []
self.histograms = []
self.canvasNames = []
self.canvasTitles = []
self.canvasList = []
self.histosLastUpdated = time()
self.histoUpdateInterval = histoUpdateInterval
self.logger = logging.getLogger(__name__)
marocLogging(self.logger,debugLevel)
def createHistograms(self): #canvases , histograms , nBits , nPlots , nPlotsPerCanvas , debugLevel):
"""Creates a set of ROOT histograms on several different canvasses. Number of canvasses, number of bins etc. taken from arguments"""
assert(self.nPlots%self.nPlotsPerCanvas == 0),"Number of plots per canvas must be a factor of number-of-plots"
nCanvas = self.nPlots/self.nPlotsPerCanvas
nPlotsPerDirection = int(sqrt(self.nPlotsPerCanvas))
nBins = 2**self.nBits
self.canvasNames = [ "c%s"%canvas for canvas in range(nCanvas) ]
self.canvasTitles = [ "ADC Value for Channels %s - %s"%(canvas*self.nPlotsPerCanvas , (canvas+1)*self.nPlotsPerCanvas -1) for canvas in range(nCanvas) ]
print self.canvasNames
print self.canvasTitles
self.canvasList = [ TCanvas(self.canvasNames[chan],self.canvasTitles[chan],600,400) for chan in range(nCanvas) ]
self.histograms = []
# sorry, this next bit isn't very Pythonesque
for canvasIndex in range(nCanvas):
canvas = self.canvasList[canvasIndex]
canvas.cd(0) # change to current canvas
canvas.Divide(nPlotsPerDirection,nPlotsPerDirection)
for plotIndex in range(self.nPlotsPerCanvas):
plot = canvasIndex*self.nPlotsPerCanvas + plotIndex # look the other way please....
print canvasIndex , plotIndex , plot
canvas.cd(plotIndex+1) # Change current pad. (plotIndex counts from 0. Root expects count from 1 (0 is the parent))
canvas.SetGrid()
histo = TH1F("chan%s"%plot,"ADC Counts for channel %s"%plot,nBins,-0.5,nBins-0.5)
histo.SetFillColor(self.histoColour)
histo.Draw("elp")
canvas.Update()
self.histograms.append( histo )
def fillHistograms( self, eventNumber, timeStamp , ADCData ):
assert(len(ADCData) == self.nPlots) , "Number of elements in ADCData array must match number of ADCs in MAROC ..."
self.logger.debug("Histogramming data = \n%s"%( ' , '.join([format(i,'08x') for i in ADCData ]) ))
for ADCIndex in range(0,len(ADCData)):
self.histograms[ADCIndex].Fill(ADCData[ADCIndex])
#
# Python class to read data from MAROC board
#
import logging
from PyChipsUser import *
import threading
import time
import Queue
import MarocDAQ
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 ):
threading.Thread.__init__(self)
self.threadID = threadID
self.board = board
self.name = name
self.rawDataQueue = rawDataQueue
self.debugLevel = debugLevel
self.logger = logging.getLogger(__name__)
def run(self):
marocLogging(self.logger,self.debugLevel)
self.logger.info( "Starting thread" )
readout_maroc(self.name, self.board , self.rawDataQueue , self.logger , self.debugLevel)
self.logger.info( "Exiting thread" )
exitFlag = 0
def readout_maroc(name, board , rawDataQueue , logger , debugLevel):
# Create pointer to MAROC board and set up structures.
marocData = MarocDAQ.MarocDAQ(board,debugLevel)
while not exitFlag:
# Read data from MAROC
events = marocData.readADCData()
# fill the queue
for event in events:
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.
#
# Python class to book histograms for MAROC data.
#
from ROOT import TFile, TTree
from array import array
from time import sleep , time
import logging
from marocLogging import marocLogging
from array import array
class MarocRecording(object):
def __init__(self, fileName="marocData.root" , debugLevel=logging.DEBUG ):
"""Class to save MAROC data in ROOT TTree"""
self.logger = logging.getLogger(__name__)
marocLogging(self.logger,debugLevel)
self.logger.info("Opening ROOT file %s"%(fileName))
self.fileName = fileName
self.fileHandle = TFile( fileName, 'RECREATE' )
# 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] )
# 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 ):
"""Write an event to ROOT file"""
self.eventNumber = eventNumber
self.timeStamp = timeStamp
self.adcData = ADCData
self.rootTree.Fill()
self.fileHandle.Write()
def closeFile( self ):
self.logger.info("Closing ROOT file %s"%(self.fileName))
self.fileHandle.Close()
# 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:
unpackedAdcData = self.unpackedDataQueue.get()
self.logger.debug("Read data from unpacked data queue = \n%s"%( ' , '.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)
print "Exiting " + self.name
......@@ -7,163 +7,180 @@ import ConfigParser
import logging
from itertools import imap
class MarocSC(object):
"""Sets up an array of 32-bit words that can be written to MAROC-3 serial slow control register via a block write to IPBus-based firmware."""
def __init__(self,debugLevel=logging.DEBUG):
# Data structure to store the name of each MAROC flag (as the key) and the [bit-location , default]
# Data structure to store the name of each MAROC flag (as the key) and the [bit-location , default, description, comment]
# e.g. "swb_buf_1p":[183 ,1] means that flag swb_buf_1p is at position 183 and is should be set to 1 by default
self.flagLocation = {
"ON/OFF_otabg":[0 ,1, "power pulsing bit for bandgap","not active on MAROC3 test board because power pulsing pin is connected to vdd"] ,
"ON/OFF_dac":[1 ,1, "power pulsing bit for all DACs","not active on MAROC3 test board because power pulsing pin is connected to vdd"] ,
"small_dac":[2 ,0, "to decrease the slope of DAC0 -> better accuracy","small dac OFF: threshold VTH0 min= and max= / small dac ON: threshold VTH0 min= and max="] ,
"enb_outADC":[23 ,0, "wilkinson ADC parameter: enable data output","In order use the wilkinson ADC this bit should be OFF"] ,
"inv_startCmptGray":[24 ,0, "wilkinson ADC parameter: the start compteur polarity switching","In order to use the wilkinson ADC should be OFF"] ,
"ramp_8bit":[25 ,0, "wilkinson ADC parameter: ramp slope change to have quickly conversion on 8 bits","Set ON for 8-bit Wilkinson conversion"] ,
"ramp_10bit":[26 ,0, "wilkinson ADC parameter: ramp slope change to have quickly conversion on 10 bits","Set ON for 10-bit Wilkinson conversion"] ,
"cmd_CK_mux":[155 ,0, "Should be OFF" , ""] ,
"d1_d2":[156 ,1,"trigger output choice","d1_d2='0' -> trigger from FSB1 and DAC0 ; d1_d2='1' -> trigger from FSB2 and DAC1"] ,
"inv_discriADC":[157 ,0,"Invert ADC discriminator output","Should be OFF"] ,
"polar_discri":[158, 0 ,"polarity of trigger output" , "polar_discri='0' ->High polarity ; polar_discri='1' -> Low polarity"],
"Enb_tristate":[159 ,1,"enable all trigger outputs","Should be ON to see trigger outputs"] ,
"valid_dc_fsb2":[160 ,0,"enable FSB2 DC measurements",""] ,
"sw_fsb2_50f":[161 ,1,"Feedback capacitor for FSB2" ,"better if ON"] ,
"sw_fsb2_100f":[162 ,0,"Feedback capacitor for FSB2" ,""] ,
"sw_fsb2_100k":[163 ,1,"Feedback resistor for FSB2" ,""] ,
"sw_fsb2_50k":[164 ,0,"Feedback resistor for FSB2" ,""] ,
"valid_dc_fs":[165 ,0,"enable FSB and FSU DC measurements",""] ,
"cmd_fsb_fsu":[166 ,1,"Choice between FSB1 or FSU for the first discri input (with DAC0)","cmd_fsb_fsu='1'-> FSU ; cmd_fsb_fsu='0'-> FSB"] ,
"sw_fsb1_50f":[167 ,1,"Feedback capacitor for FSB1" ,"better if ON"] ,
"sw_fsb1_100f":[168 ,1,"Feedback capacitor for FSB1" ,"better if ON"] ,
"sw_fsb1_100k":[169 ,1,"Feedback resistor for FSB1" ,""] ,
"sw_fsb1_50k":[170 ,0,"Feedback resistor for FSB1" ,""] ,
"sw_fsu_100k":[171 ,1, "Feedback resistor for FSU" , ""] ,
"sw_fsu_50k":[172 ,1, "Feedback resistor for FSU" , ""] ,
"sw_fsu_25k":[173 ,1, "Feedback resistor for FSU" , ""] ,
"sw_fsu_40f":[174 ,1, "Feedback capacitor for FSU" , "better if ON"] ,
"sw_fsu_20f":[175 ,1, "Feedback capacitor for FSU" , "better if ON"] ,
"H1H2_choice":[176 ,1,"ADC wilkinson: choice between the first or the second track and hold for the input of the ADC",""] ,
"EN_ADC":[177 ,1,"ADC wilkinson: enable ADC conversion inside the asic ","Should be ON to enable ADC"] ,
"sw_ss_1200f":[178 ,1,"Feedback capacitor for Slow Shaper",""] ,
"sw_ss_600f":[179 ,1,"Feedback capacitor for Slow Shaper",""] ,
"sw_ss_300f":[180 ,1,"Feedback capacitor for Slow Shaper",""] ,
"ON/OFF_ss":[181 ,1,"Power supply of Slow Shaper",""] ,
"swb_buf_2p":[182 ,1,"capacitor for the buffer before the slow shaper",""] ,
"swb_buf_1p":[183 ,1,"capacitor for the buffer before the slow shaper",""] ,
"swb_buf_500f":[184 ,1,"capacitor for the buffer before the slow shaper",""] ,
"swb_buf_250f":[185 ,1,"capacitor for the buffer before the slow shaper",""] ,
"cmd_fsb":[186 ,1,"enable signal at the FSB inputs","Should be ON if we want to use FSB1 or FSB2"] ,
"cmd_ss":[187 ,1,"enable signal at the SS inputs","Should be ON if we want to do charge measurement"] ,
"cmd_fsu":[188 ,1,"enable signal at the FSU inputs","Should be ON if we want to use FSU"]
'ON/OFF_otabg':[0 ,1, 'power pulsing bit for bandgap','not active on MAROC3 test board because power pulsing pin is connected to vdd'] ,
'ON/OFF_dac':[1 ,1, 'power pulsing bit for all DACs','not active on MAROC3 test board because power pulsing pin is connected to vdd'] ,
'small_dac':[2 ,0, 'to decrease the slope of DAC0 -> better accuracy','small dac OFF: threshold VTH0 min= and max= / small dac ON: threshold VTH0 min= and max='] ,
'enb_outADC':[23 ,0, 'wilkinson ADC parameter: enable data output','In order use the wilkinson ADC this bit should be OFF'] ,
'inv_startCmptGray':[24 ,0, 'wilkinson ADC parameter: the start compteur polarity switching','In order to use the wilkinson ADC should be OFF'] ,
'ramp_8bit':[25 ,0, 'wilkinson ADC parameter: ramp slope change to have quickly conversion on 8 bits','Set ON for 8-bit Wilkinson conversion'] ,
'ramp_10bit':[26 ,0, 'wilkinson ADC parameter: ramp slope change to have quickly conversion on 10 bits','Set ON for 10-bit Wilkinson conversion'] ,
'cmd_CK_mux':[155 ,0, 'Should be OFF' , ''] ,
'd1_d2':[156 ,1,'trigger output choice','d1_d2=0 -> trigger from FSB1 and DAC0 ; d1_d2=1 -> trigger from FSB2 and DAC1'] ,
'inv_discriADC':[157 ,0,'Invert ADC discriminator output','Should be OFF'] ,
'polar_discri':[158, 0 ,'polarity of trigger output' , 'polar_discri=0 ->High polarity ; polar_discri=1 -> Low polarity'],
'Enb_tristate':[159 ,1,'enable all trigger outputs','Should be ON to see trigger outputs'] ,
'valid_dc_fsb2':[160 ,0,'enable FSB2 DC measurements',''] ,
'sw_fsb2_50f':[161 ,1,'Feedback capacitor for FSB2' ,'better if ON'] ,
'sw_fsb2_100f':[162 ,0,'Feedback capacitor for FSB2' ,''] ,
'sw_fsb2_100k':[163 ,1,'Feedback resistor for FSB2' ,''] ,
'sw_fsb2_50k':[164 ,0,'Feedback resistor for FSB2' ,''] ,
'valid_dc_fs':[165 ,0,'enable FSB and FSU DC measurements',''] ,
'cmd_fsb_fsu':[166 ,1,'Choice between FSB1 or FSU for the first discri input (with DAC0)','cmd_fsb_fsu=1-> FSU ; cmd_fsb_fsu=0-> FSB'] ,
'sw_fsb1_50f':[167 ,1,'Feedback capacitor for FSB1' ,'better if ON'] ,
'sw_fsb1_100f':[168 ,1,'Feedback capacitor for FSB1' ,'better if ON'] ,
'sw_fsb1_100k':[169 ,1,'Feedback resistor for FSB1' ,''] ,
'sw_fsb1_50k':[170 ,0,'Feedback resistor for FSB1' ,''] ,
'sw_fsu_100k':[171 ,1, 'Feedback resistor for FSU' , ''] ,
'sw_fsu_50k':[172 ,1, 'Feedback resistor for FSU' , ''] ,
'sw_fsu_25k':[173 ,1, 'Feedback resistor for FSU' , ''] ,
'sw_fsu_40f':[174 ,1, 'Feedback capacitor for FSU' , 'better if ON'] ,
'sw_fsu_20f':[175 ,1, 'Feedback capacitor for FSU' , 'better if ON'] ,
'H1H2_choice':[176 ,1,'ADC wilkinson: choice between the first or the second track and hold for the input of the ADC',''] ,
'EN_ADC':[177 ,1,'ADC wilkinson: enable ADC conversion inside the asic ','Should be ON to enable ADC'] ,
'sw_ss_1200f':[178 ,1,'Feedback capacitor for Slow Shaper',''] ,
'sw_ss_600f':[179 ,1,'Feedback capacitor for Slow Shaper',''] ,
'sw_ss_300f':[180 ,1,'Feedback capacitor for Slow Shaper',''] ,
'ON/OFF_ss':[181 ,1,'Power supply of Slow Shaper',''] ,
'swb_buf_2p':[182 ,1,'capacitor for the buffer before the slow shaper',''] ,
'swb_buf_1p':[183 ,1,'capacitor for the buffer before the slow shaper',''] ,
'swb_buf_500f':[184 ,1,'capacitor for the buffer before the slow shaper',''] ,
'swb_buf_250f':[185 ,1,'capacitor for the buffer before the slow shaper',''] ,
'cmd_fsb':[186 ,1,'enable signal at the FSB inputs','Should be ON if we want to use FSB1 or FSB2'] ,
'cmd_fsu':[188 ,1,'enable signal at the FSU inputs','Should be ON if we want to use FSU'] ,
'cmd_ss':[187 ,1,'enable signal at the SS inputs','Should be ON if we want to do charge measurement']
}
# Data structure to store the name of each MAROC parameter (as the key) and the [parameter-location , parameter-width , default ]
# Copy default flags onto the end of each flag
# structure = [bit-location , default, description, comment, currentValue]
for flagName in self.flagLocation.keys():
self.flagLocation[flagName].append(self.flagLocation[flagName][1])
# Data structure to store the name of each MAROC parameter (as the key) and the [parameter-location , parameter-width , default , description , comment ]
# parameter-location is the bit-location of the lowest SC bit ( most significant bit of highest indexed parameter )
# size of parameter array is deduced from array of default values
self.parameterLocation = {
"DAC":[ 3 , 10 , 2*[0x000,0x150], "DAC values for the discriminators. DAC[1]= second discriminator (with the fast shaper FSB2). DAC[0]=first discriminator (with the fast shaper FSB1 or FSU)","" ] , # The most significant bit of DAC2,
"mask_OR":[ 27 , 0 , 64*[0x0] ,"mask the discriminator outputs.","MSB of mask_OR[N] = OR2 = mask for second disriminator output ( FSB2) of channel N. LSB of mask_OR[N] = OR1 = mask for first discriminator output ( FSB1 / FSU ). Set bit ON to generate a trigger" ] ,
"GAIN":[ 189 , 9 , 64*[0x40] ,"Preamplifier gain (8-bits) and sum-enable for channels","Set sum-enable high for channel to contribute to analogue sum"],
"Ctest_ch":[765 , 1 , 64*[0x1] ,"Enable signal in Ctest input" ,"" ]
'DAC':[ 3 , 10 , [0x000,0x000], 'DAC values for the discriminators. DAC[1]= second discriminator (with the fast shaper FSB2). DAC[0]=first discriminator (with the fast shaper FSB1 or FSU)','' ] , # The most significant bit of DAC2,
'mask_OR':[ 27 , 2 , 64*[0x0] ,'mask the discriminator outputs.','MSB of mask_OR[N] = OR2 = mask for second disriminator output ( FSB2) of channel N. LSB of mask_OR[N] = OR1 = mask for first discriminator output ( FSB1 / FSU ). Set bit OFF to generate a trigger (ON to mask trigger)' ] ,
'GAIN':[ 189 , 9 , 64*[0x40] ,'Preamplifier gain (8-bits) and sum-enable for channels','Set sum-enable high for channel to contribute to analogue sum'],
'Ctest_ch':[765 , 1 , 64*[0x1] ,'Enable signal in Ctest input' ,'' ]
}
# Copy default parameters into dictionary
# parameterLocation = [parameter-location , parameter-width , default , description , comment , currentValue(s) ]
for paramName in self.parameterLocation.keys():
self.parameterLocation[paramName].append(self.parameterLocation[paramName][2])
self.numSCbits = 829 # number of bits in slow control register
self.numWords = 26
self.busWidth = 32
self.bitArray=self.numSCbits*[0]
self.SCData = self.numWords*[0x00000000]
self.debugLevel = debugLevel
logging.basicConfig(level=debugLevel)
# Call method to set up defaults...
self.setDefaults()
logging.basicConfig(format='%(levelname)s:MarocSC:%(message)s',level=debugLevel)
#print "flags = " , self.flagLocation
#print "parameters = " , self.parameterLocation
def getLocalBitArray(self):
def getBitArray(self):
"""Returns list of bits representing data to write to SC register.
( N.B. This is the contents of the local data structure that will be transmitted to the MAROC, *NOT* what is in the MAROC)"""
return self.bitArray
def printLocalBitArray(self):
bitArray = (self.numSCbits)*[0]
for flagName in self.flagLocation.keys(): # Loop through the flags
[ bitPosition , default , description , comment , bitValue ] = self.flagLocation[flagName]
logging.debug("Copying flag to bit-array. Flag name = %s , flag location = %i , default = %i , value = %i , description = %s , comment = %s" % ( flagName , bitPosition , default , bitValue , description , comment))
bitArray[bitPosition] = bitValue
for paramName in self.parameterLocation.keys(): # Loop through the parameters
[ paramLocation , paramWidth , paramDefault , description , comment , paramValue ] = self.parameterLocation[paramName]
for index in range(0, len(paramDefault)): # Loop over the array values for each parameter
arraySize = len(paramDefault)
assert index < arraySize
logging.debug("setting parameter = %s , base location = %i , index = %i . Value(s) = %i . Number of values = %i" %( paramName , paramLocation, index , int(paramValue[index]) , arraySize) )
for paramBitPos in range(0,paramWidth): # Loop over the bits in the parameter.
bitValue = (int(paramValue[index]) >> paramBitPos) & 0x00000001
bitLocation = paramLocation+ (paramWidth*( (arraySize-1) -index)) + ( (paramWidth - 1) - paramBitPos)
# print "value of bit %i is %i , writen to position %i" %( paramBitPos , bitValue , bitLocation)
logging.debug("value of bit %i is %i , writen to position %i" %( paramBitPos , bitValue , bitLocation))
bitArray[bitLocation] = bitValue
# self.setParameter(paramName , index , default[index])
return bitArray
def printBitArray(self):
""" Prints out the value of each bit in the list"""
for bitNumber in range(0 , len(self.bitArray) ):
print "bit %i = %i" %( bitNumber , self.bitArray[bitNumber] )
bitArray = self.getBitArray()
for bitNumber in range(0 , len(bitArray) ):
print "bit %i = %i" %( bitNumber , bitArray[bitNumber] )
def getLocalWordArray(self):
def getWordArray(self):
"""Return an array of 32-bit numbers to write to SC register.
( N.B. This is the contents of the local data structure that will be transmitted to the MAROC, *NOT* what is in the MAROC)"""
self.SCData = self.numWords*[0x00000000] # clear contents of array
for bitNumber in range(0 , len(self.bitArray) ):
SCData = self.numWords*[0x00000000] # clear contents of array
bitArray = self.getBitArray()
for bitNumber in range(0 , len(bitArray) ):
bitNum = self.numSCbits - bitNumber -1
wordBitPos = bitNum % self.busWidth
wordNum = bitNum / self.busWidth
logging.debug("setting bit number = %i (reversed = %i ) => bit %i of word %i to %i" %( bitNumber , bitNum , wordBitPos , wordNum, self.bitArray[bitNumber]))
self.SCData[wordNum] += self.bitArray[bitNumber] << wordBitPos
return self.SCData
logging.debug("setting bit number = %i (reversed = %i ) => bit %i of word %i to %i" %( bitNumber , bitNum , wordBitPos , wordNum, bitArray[bitNumber]))
SCData[wordNum] += bitArray[bitNumber] << wordBitPos
return SCData
def setFlagValue(self,flagName,bitValue):
"""Write to the flag with name flagName.
( Inside the code, the location of flag in the serial data stream is given by the hash flagLocation)"""
[bitPosition , default , description, comment] = self.flagLocation[flagName]
logging.debug("Setting flag %s , bit location %i to %i " %( flagName , bitPosition , int(bitValue) ) )
self.bitArray[bitPosition] = bitValue
[bitPosition , default , description, comment , currentValue] = self.flagLocation[flagName]
logging.debug("Setting flag %s , bit location %i to %i . Previous value = %i" %( flagName , bitPosition , int(bitValue) , int(currentValue) ) )
self.flagLocation[flagName][4] = bitValue
def getFlagValue(self,flagName):
"""Read from internal data-structure the contents of flagName."""
[bitLocation , default, description, comment ] = self.flagLocation[flagName]
return self.bitArray[bitLocation]
return self.flagLocation[flagName][4]
def getFlagLocations(self):
"""Return the list of flags, positions and defaults"""
return self.flagLocation
def setParameter(self,paramName,index,paramValue):
def setParameterValue(self,paramName,newParamValue,index=-1):
"""Writes to the parameter array with name paramName at index the value n"""
[ paramLocation , paramWidth , paramDefault, description, comment ] = self.parameterLocation[paramName]
[ paramLocation , paramWidth , paramDefault, description, comment ,oldParamValue] = self.parameterLocation[paramName]
arraySize = len(paramDefault)
assert index < arraySize
logging.debug("setting parameter = %s , base location = %i , index = %i . Value(s) = %i . Number of values = %i" %( paramName , paramLocation, index , int(paramValue) , arraySize) )
#print "setting parameter = %s , index = %i to %i . Number of values = %i" %( paramName , index , int(paramValue) , arraySize)
logging.debug("setting parameter = %s , index = %i to %i . Number of values = %i" %( paramName , index , int(paramValue) , arraySize))
for paramBitPos in range(0,paramWidth): # Loop over the bits in the parameter.
bitValue = (int(paramValue) >> paramBitPos) & 0x00000001
bitLocation = paramLocation+ (paramWidth*( (arraySize-1) -index)) + ( (paramWidth - 1) - paramBitPos)
# print "value of bit %i is %i , writen to position %i" %( paramBitPos , bitValue , bitLocation)
logging.debug("value of bit %i is %i , writen to position %i" %( paramBitPos , bitValue , bitLocation))
self.bitArray[bitLocation] = bitValue
def getParameter(self,paramName,index):
"""Gets parameter(index)"""
[ paramLocation , paramWidth , default, description, comment ] = self.parameterLocation[paramName]
if index<0: # if index not set ( or set to <0 ) then write all parameters at once.
paramString = ",".join(imap(str, newParamValue))
logging.debug("setting parameter array = %s , base location = %i , Values = %s . Number of values = %i" %( paramName , paramLocation, paramString , arraySize) )
assert len(paramDefault) == len(newParamValue) # Make sure array has the correct number of entries
self.parameterLocation[paramName][5] = newParamValue
else:
logging.debug("setting parameter = %s , base location = %i , index = %i . Value(s) = %i . Number of values = %i" %( paramName , paramLocation, index , int(newParamValue) , arraySize) )
self.parameterLocation[paramName][5][index] = newParamValue
def getParameterValue(self,paramName):
"""Gets parameter"""
[ paramLocation , paramWidth , default, description, comment , paramValue] = self.parameterLocation[paramName]
arraySize = len(default)
assert index < arraySize
logging.debug("reading parameter = %s , index = %i . Number of values = %i" %( paramName , index , arraySize) )
paramValue = 0
for paramBitPos in range(0,paramWidth): # Loop over the bits in the parameter.
bitLocation = paramLocation+ (paramWidth*(arraySize-index)) + (paramWidth - paramBitPos)
bitValue = self.bitArray[bitLocation]
paramValue = paramValue + (bitValue << paramBitPos)
logging.debug("value of bit %i is %i , writen to position %i" %( paramBitPos , bitValue , bitLocation))
paramString = ",".join(imap(str, paramValue))
logging.debug("reading parameter = %s , Number of values = %i , values = %s " %( paramName , arraySize , paramString) )
return paramValue
def getParameterLocations(self):
"""Returns the list of parameters , positions, array sizes and defaults"""
return self.parameterLocation
def setDefaults(self):
"""Loop through defaults and write to data structure"""
# First loop through the flags -
for flagName in self.flagLocation.keys():
[ bit , default , description , comment ] = self.flagLocation[flagName]
logging.debug("Setting defaults. Flag name = %s , flag location = %i , default = %i , description = %s , comment = %s" % ( flagName , bit , default , description , comment))
self.setFlagValue(flagName,default)
# now loop through the parameters
# (could be done in either order ... )
for parameterName in self.parameterLocation.keys():
[ bit , width , default , description , comment ] = self.parameterLocation[parameterName]
for index in range(0, len(default)):
self.setParameter(parameterName , index , default[index])
def readConfigFile(self,fName):
"""Reads a configuration file with 'windows-INI' like syntax.
Expects two sections -
......@@ -183,8 +200,7 @@ class MarocSC(object):
# read the parameters
for ( parameter , valueList ) in parameters:
values = valueList.split(",")
for index in range (0, len(values)):
self.setParameter( parameter , index , values[index] )
self.setParameter( parameter , values )
def writeConfigFile(self,fName):
"""Writes a configuration file with window-INI like syntax. Warning - will overwrite existing files"""
......@@ -200,9 +216,12 @@ class MarocSC(object):
logging.debug("Setting Flag name %s in config file to %i " %(flagName,bitValue))
config.set('flags',flagName,str(bitValue))
#for paramName in self.paramLocation.keys():
# paramValues = self.getParameters
for paramName in self.parameterLocation.keys():
paramValues = self.getParameterValue(paramName)
paramString = ",".join(imap(str, paramValues))
logging.debug("Setting Parameter name %s in config file to %s " %(paramName,paramString))
config.set('parameters',paramName,paramString)
# Write out configuration
config.write(cfgFile)
cfgFile.close()
......@@ -211,7 +230,7 @@ class MarocSC(object):
# """Writes contents of local data-structure to MAROC slow control.
# board - a PyChips object pointing to correct MAROC board"""
#
# SCData = self.getLocalWordArray()
# SCData = self.getWordArray()
# # write data into buffer
# board.blockWrite("scSrDataOut",SCData)
# # trigger writing of buffer to slow control shift register
......
#
#
# Python class to set up MAROC-3 serial control register.
#
#
import ConfigParser
import logging
class MarocSC_old(object):
"""Sets up an array of 32-bit words that can be written to MAROC-3 serial slow control register via a block write to IPBus-based firmware."""
def __init__(self,debugLevel=logging.DEBUG):
# Data structure to store the name of each MAROC flag (as the key) and the [bit-location , default]
# e.g. "swb_buf_1p":[183 ,1] means that flag swb_buf_1p is at position 183 and is should be set to 1 by default
self.flagLocation = {
"ON/OFF_otabg":[0 ,1, "power pulsing bit for bandgap","not active on MAROC3 test board because power pulsing pin is connected to vdd"] ,
"ON/OFF_dac":[1 ,1, "power pulsing bit for all DACs","not active on MAROC3 test board because power pulsing pin is connected to vdd"] ,
"small_dac":[2 ,0, "to decrease the slope of DAC0 -> better accuracy","small dac OFF: threshold VTH0 min= and max= / small dac ON: threshold VTH0 min= and max="] ,
"enb_outADC":[23 ,0, "wilkinson ADC parameter: enable data output","In order use the wilkinson ADC this bit should be OFF"] ,
"inv_startCmptGray":[24 ,0, "wilkinson ADC parameter: the start compteur polarity switching","In order to use the wilkinson ADC should be OFF"] ,
"ramp_8bit":[25 ,0, "wilkinson ADC parameter: ramp slope change to have quickly conversion on 8 bits","Set ON for 8-bit Wilkinson conversion"] ,
"ramp_10bit":[26 ,0, "wilkinson ADC parameter: ramp slope change to have quickly conversion on 10 bits","Set ON for 10-bit Wilkinson conversion"] ,
"cmd_CK_mux":[155 ,0, "Should be OFF" , ""] ,
"d1_d2":[156 ,1,"trigger output choice","d1_d2='0' -> trigger from FSB1 and DAC0 ; d1_d2='1' -> trigger from FSB2 and DAC1"] ,
"inv_discriADC":[157 ,0,"Invert ADC discriminator output","Should be OFF"] ,
"polar_discri":[158, 0 ,"polarity of trigger output" , "polar_discri='0' ->High polarity ; polar_discri='1' -> Low polarity"],
"Enb_tristate":[159 ,1,"enable all trigger outputs","Should be ON to see trigger outputs"] ,
"valid_dc_fsb2":[160 ,0,"enable FSB2 DC measurements",""] ,
"sw_fsb2_50f":[161 ,1,"Feedback capacitor for FSB2" ,"better if ON"] ,
"sw_fsb2_100f":[162 ,0,"Feedback capacitor for FSB2" ,""] ,
"sw_fsb2_100k":[163 ,1,"Feedback resistor for FSB2" ,""] ,
"sw_fsb2_50k":[164 ,0,"Feedback resistor for FSB2" ,""] ,
"valid_dc_fs":[165 ,0,"enable FSB and FSU DC measurements",""] ,
"cmd_fsb_fsu":[166 ,1,"Choice between FSB1 or FSU for the first discri input (with DAC0)","cmd_fsb_fsu='1'-> FSU ; cmd_fsb_fsu='0'-> FSB"] ,
"sw_fsb1_50f":[167 ,1,"Feedback capacitor for FSB1" ,"better if ON"] ,
"sw_fsb1_100f":[168 ,1,"Feedback capacitor for FSB1" ,"better if ON"] ,
"sw_fsb1_100k":[169 ,1,"Feedback resistor for FSB1" ,""] ,
"sw_fsb1_50k":[170 ,0,"Feedback resistor for FSB1" ,""] ,
"sw_fsu_100k":[171 ,1, "Feedback resistor for FSU" , ""] ,
"sw_fsu_50k":[172 ,1, "Feedback resistor for FSU" , ""] ,
"sw_fsu_25k":[173 ,1, "Feedback resistor for FSU" , ""] ,
"sw_fsu_40f":[174 ,1, "Feedback capacitor for FSU" , "better if ON"] ,
"sw_fsu_20f":[175 ,1, "Feedback capacitor for FSU" , "better if ON"] ,
"H1H2_choice":[176 ,1,"ADC wilkinson: choice between the first or the second track and hold for the input of the ADC",""] ,
"EN_ADC":[177 ,1,"ADC wilkinson: enable ADC conversion inside the asic ","Should be ON to enable ADC"] ,
"sw_ss_1200f":[178 ,1,"Feedback capacitor for Slow Shaper",""] ,
"sw_ss_600f":[179 ,1,"Feedback capacitor for Slow Shaper",""] ,
"sw_ss_300f":[180 ,1,"Feedback capacitor for Slow Shaper",""] ,
"ON/OFF_ss":[181 ,1,"Power supply of Slow Shaper",""] ,
"swb_buf_2p":[182 ,1,"capacitor for the buffer before the slow shaper",""] ,
"swb_buf_1p":[183 ,1,"capacitor for the buffer before the slow shaper",""] ,
"swb_buf_500f":[184 ,1,"capacitor for the buffer before the slow shaper",""] ,
"swb_buf_250f":[185 ,1,"capacitor for the buffer before the slow shaper",""] ,
"cmd_fsb":[186 ,1,"enable signal at the FSB inputs","Should be ON if we want to use FSB1 or FSB2"] ,
"cmd_ss":[187 ,1,"enable signal at the SS inputs","Should be ON if we want to do charge measurement"] ,
"cmd_fsu":[188 ,1,"enable signal at the FSU inputs","Should be ON if we want to use FSU"]
}
# Data structure to store the name of each MAROC parameter (as the key) and the [parameter-location , parameter-width , default ]
# parameter-location is the bit-location of the lowest SC bit ( most significant bit of highest indexed parameter )
# size of parameter array is deduced from array of default values
self.parameterLocation = {
"DAC":[ 3 , 10 , 2*[0x000,0x150], "DAC values for the discriminators. DAC[1]= second discriminator (with the fast shaper FSB2). DAC[0]=first discriminator (with the fast shaper FSB1 or FSU)","" ] , # The most significant bit of DAC2,
"mask_OR":[ 27 , 0 , 64*[0x0] ,"mask the discriminator outputs.","MSB of mask_OR[N] = OR2 = mask for second disriminator output ( FSB2) of channel N. LSB of mask_OR[N] = OR1 = mask for first discriminator output ( FSB1 / FSU ). Set bit ON to generate a trigger" ] ,
"GAIN":[ 189 , 9 , 64*[0x40] ,"Preamplifier gain (8-bits) and sum-enable for channels","Set sum-enable high for channel to contribute to analogue sum"],
"Ctest_ch":[765 , 1 , 64*[0x1] ,"Enable signal in Ctest input" ,"" ]
}
self.numSCbits = 829 # number of bits in slow control register
self.numWords = 26
self.busWidth = 32
self.bitArray=self.numSCbits*[0]
self.SCData = self.numWords*[0x00000000]
self.debugLevel = debugLevel
logging.basicConfig(level=debugLevel)
# Call method to set up defaults...
self.setDefaults()
def getLocalBitArray(self):
"""Returns list of bits representing data to write to SC register.
( N.B. This is the contents of the local data structure that will be transmitted to the MAROC, *NOT* what is in the MAROC)"""
return self.bitArray
def printLocalBitArray(self):
""" Prints out the value of each bit in the list"""
for bitNumber in range(0 , len(self.bitArray) ):
print "bit %i = %i" %( bitNumber , self.bitArray[bitNumber] )
def getLocalWordArray(self):
"""Return an array of 32-bit numbers to write to SC register.
( N.B. This is the contents of the local data structure that will be transmitted to the MAROC, *NOT* what is in the MAROC)"""
self.SCData = self.numWords*[0x00000000] # clear contents of array
for bitNumber in range(0 , len(self.bitArray) ):
bitNum = self.numSCbits - bitNumber -1
wordBitPos = bitNum % self.busWidth
wordNum = bitNum / self.busWidth
logging.debug("setting bit number = %i (reversed = %i ) => bit %i of word %i to %i" %( bitNumber , bitNum , wordBitPos , wordNum, self.bitArray[bitNumber]))
self.SCData[wordNum] += self.bitArray[bitNumber] << wordBitPos
return self.SCData
def setFlagValue(self,flagName,bitValue):
"""Write to the flag with name flagName.
( Inside the code, the location of flag in the serial data stream is given by the hash flagLocation)"""
[bitPosition , default , description, comment] = self.flagLocation[flagName]
logging.debug("Setting flag %s , bit location %i to %i " %( flagName , bitPosition , int(bitValue) ) )
self.bitArray[bitPosition] = bitValue
def getFlagValue(self,flagName):
"""Read from internal data-structure the contents of flagName."""
[bitLocation , default, description, comment ] = self.flagLocation[flagName]
return self.bitArray[bitLocation]
def getFlagLocations(self):
"""Return the list of flags, positions and defaults"""
return self.flagLocation
def setParameter(self,paramName,index,paramValue):
"""Writes to the parameter array with name paramName at index the value n"""
[ paramLocation , paramWidth , paramDefault, description, comment ] = self.parameterLocation[paramName]
arraySize = len(paramDefault)
assert index < arraySize
logging.debug("setting parameter = %s , base location = %i , index = %i . Value(s) = %i . Number of values = %i" %( paramName , paramLocation, index , int(paramValue) , arraySize) )
#print "setting parameter = %s , index = %i to %i . Number of values = %i" %( paramName , index , int(paramValue) , arraySize)
logging.debug("setting parameter = %s , index = %i to %i . Number of values = %i" %( paramName , index , int(paramValue) , arraySize))
for paramBitPos in range(0,paramWidth): # Loop over the bits in the parameter.
bitValue = (int(paramValue) >> paramBitPos) & 0x00000001
bitLocation = paramLocation+ (paramWidth*( (arraySize-1) -index)) + ( (paramWidth - 1) - paramBitPos)
# print "value of bit %i is %i , writen to position %i" %( paramBitPos , bitValue , bitLocation)
logging.debug("value of bit %i is %i , writen to position %i" %( paramBitPos , bitValue , bitLocation))
self.bitArray[bitLocation] = bitValue
def getParameter(self,paramName,index):
"""Gets parameter(index)"""
[ paramLocation , paramWidth , default, description, comment ] = self.parameterLocation[paramName]
arraySize = len(default)
assert index < arraySize
logging.debug("reading parameter = %s , index = %i . Number of values = %i" %( paramName , index , arraySize) )
paramValue = 0
for paramBitPos in range(0,paramWidth): # Loop over the bits in the parameter.
bitLocation = paramLocation+ (paramWidth*(arraySize-index)) + (paramWidth - paramBitPos)
bitValue = self.bitArray[bitLocation]
paramValue = paramValue + (bitValue << paramBitPos)
logging.debug("value of bit %i is %i , writen to position %i" %( paramBitPos , bitValue , bitLocation))
return paramValue
def getParameterLocations(self):
"""Returns the list of parameters , positions, array sizes and defaults"""
return self.parameterLocation
def setDefaults(self):
"""Loop through defaults and write to data structure"""
# First loop through the flags -
for flagName in self.flagLocation.keys():
[ bit , default , description , comment ] = self.flagLocation[flagName]
logging.debug("Setting defaults. Flag name = %s , flag location = %i , default = %i , description = %s , comment = %s" % ( flagName , bit , default , description , comment))
self.setFlagValue(flagName,default)
# now loop through the parameters
# (could be done in either order ... )
for parameterName in self.parameterLocation.keys():
[ bit , width , default , description , comment ] = self.parameterLocation[parameterName]
for index in range(0, len(default)):
self.setParameter(parameterName , index , default[index])
def readConfigFile(self,fName):
"""Reads a configuration file with 'windows-INI' like syntax.
Expects two sections -
flags , where the flag entries are ( fName: fVal ) are
parameters , where the parameter entries are ( pName: p(1),p(2),....,p(N) . N.B. no bounds checking is done on the parameter indices, so don't add too many to the list
"""
config = ConfigParser.SafeConfigParser()
config.optionxform = str # stop parser from changing to lower case.
config.read(fName)
flags = config.items("flags")
parameters = config.items("parameters")
logging.debug(flags)
logging.debug(parameters)
# read the flags...
for ( flag , value ) in flags:
self.setFlagValue( flag , int(value) )
# read the parameters
for ( parameter , valueList ) in parameters:
values = valueList.split(",")
for index in range (0, len(values)):
self.setParameter( parameter , index , values[index] )
def writeConfigFile(self,fName):
"""Writes a configuration file with window-INI like syntax. Warning - will overwrite existing files"""
cfgFile = open(fName,'w')
config = ConfigParser.SafeConfigParser()
config.optionxform = str # stop parser from changing to lower case
config.add_section('flags')
config.add_section('parameters')
# Set flag values
for flagName in self.flagLocation.keys():
bitValue = self.getFlagValue(flagName)
logging.debug("Setting Flag name %s in config file to %i " %(flagName,bitValue))
config.set('flags',flagName,str(bitValue))
#for paramName in self.paramLocation.keys():
# paramValues = self.getParameters
# Write out configuration
config.write(cfgFile)
cfgFile.close()
# def configure(self,board):
# """Writes contents of local data-structure to MAROC slow control.
# board - a PyChips object pointing to correct MAROC board"""
#
# SCData = self.getLocalWordArray()
# # write data into buffer
# board.blockWrite("scSrDataOut",SCData)
# # trigger writing of buffer to slow control shift register
# board.write("scSrCtrl" , 0x00000001)
#
# Python class to read ADC data from readout thread and unpack into ADC values.
#
import logging
from marocLogging import marocLogging
# NB. binstr isn't a standard Python library. Install from
# https://pypi.python.org/pypi/binstr/1.3
import binstr
from PyChipsUser import *
import threading
import time
import Queue
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 ):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.rawDataQueue = rawDataQueue
self.unpackedDataQueue = unpackedDataQueue
self.debugLevel = debugLevel
self.logger = logging.getLogger(__name__)
def run(self):
marocLogging(self.logger,self.debugLevel)
self.logger.info( "Starting thread" )
unpack_maroc_data(self.name, self.rawDataQueue , self.unpackedDataQueue , self.logger)
self.logger.info( "Ending thread" )
def int2bin(n):
'From positive integer to list of binary bits, msb at index 0'
if n:
bits = []
while n:
n,remainder = divmod(n, 2)
bits.insert(0, remainder)
return bits
else: return [0]
def bin2int(bits):
'From binary bits, msb at index 0 to integer'
i = 0
for bit in bits:
i = i * 2 + bit
return i
def gray2bin(bits):
b = [bits[0]]
for nextb in bits[1:]: b.append(b[-1] ^ nextb)
return b
def greyIntToInt(greyInt):
greyBin = int2bin(greyInt)
normalBin = gray2bin(greyBin)
return bin2int(normalBin)
exitFlag = 0
def unpack_maroc_data(name, rawDataQueue , unpackedDataQueue , logger):
while not exitFlag:
adcData = rawDataQueue.get()
logger.debug("Read data from raw data queue = \n%s"%( ' , '.join([format(i,'08x') for i in adcData ]) ))
nBits = 12
busWidth = 32
nADC = 64
adcDataSize = 26
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
for adcNumber in range(0 , nADC) :
lowBit = adcNumber*nBits
lowWord = (adcDataSize-1) - (lowBit /busWidth) # rounds to integer
lowBitPos = lowBit % busWidth
if adcNumber > (nADC-3): # for adc's 62,63
longWord = adcData[lowWord]
else:
longWord = adcData[lowWord] + (adcData[lowWord-1] << busWidth)
adcValue = 0x0FFF & (longWord >> lowBitPos)
adcValueBin = greyIntToInt(adcValue)
unpackedData.append(adcValueBin)
logger.debug("Unpacked data = \n%s"%( ' , '.join([format(i,'08x') for i in unpackedData ]) ))
unpackedDataQueue.put(unpackedData)
# Created on Sep 10, 2012
# @author: Kristian Harder, based on code by Carl Jeske
from I2cBusProperties import I2cBusProperties
from ChipsBus import ChipsBus
from ChipsLog import chipsLog
from ChipsException import ChipsException
class RawI2cAccess:
def __init__(self, i2cBusProps, slaveAddr):
# For performing read/writes over an OpenCores-compatible I2C bus master
#
# An instance of this class is required to communicate with each
# I2C slave on the I2C bus.
#
# i2cBusProps: an instance of the class I2cBusProperties that contains
# the relevant ChipsBus host and the I2C bus-master registers (if
# they differ from the defaults specified by the I2cBusProperties
# class).
#
#slaveAddr: The address of the I2C slave you wish to communicate with.
#
self._i2cProps = i2cBusProps # The I2C Bus Properties
self._slaveAddr = 0x7f & slaveAddr # 7-bit slave address
def resetI2cBus(self):
# Resets the I2C bus
#
# This function does the following:
# 1) Disables the I2C core
# 2) Sets the clock prescale registers
# 3) Enables the I2C core
# 4) Sets all writable bus-master registers to default values
try:
self._chipsBus().queueWrite(self._i2cProps.ctrlReg, 0x00)
self._chipsBus().queueWrite(self._i2cProps.preHiReg,
self._i2cProps.preHiVal)
self._chipsBus().queueWrite(self._i2cProps.preLoReg,
self._i2cProps.preLoVal)
self._chipsBus().queueWrite(self._i2cProps.ctrlReg, 0x80)
self._chipsBus().queueWrite(self._i2cProps.txReg, 0x00)
self._chipsBus().queueWrite(self._i2cProps.cmdReg, 0x00)
self._chipsBus().queueRun()
except ChipsException, err:
raise ChipsException("I2C reset error:\n\t" + str(err))
def read(self, numBytes):
# Performs an I2C read. Returns the 8-bit read result(s).
#
# numBytes: number of bytes expected as response
#
try:
result = self._privateRead(numBytes)
except ChipsException, err:
raise ChipsException("I2C read error:\n\t" + str(err))
return result
def write(self, listDataU8):
# Performs an 8-bit I2C write.
#
# listDataU8: The 8-bit data values to be written.
#
try:
self._privateWrite(listDataU8)
except ChipsException, err:
raise ChipsException("I2C write error:\n\t" + str(err))
return
def _chipsBus(self):
# Returns the instance of the ChipsBus device that's hosting
# the I2C bus master
return self._i2cProps.chipsBus
def _privateRead(self, numBytes):
# I2C read implementation.
#
# Fast I2C read implementation,
# i.e. done with the fewest packets possible.
# transmit reg definitions
# bits 7-1: 7-bit slave address during address transfer
# or first 7 bits of byte during data transfer
# bit 0: RW flag during address transfer or LSB during data transfer.
# '1' = reading from slave
# '0' = writing to slave
# command reg definitions
# bit 7: Generate start condition
# bit 6: Generate stop condition
# bit 5: Read from slave
# bit 4: Write to slave
# bit 3: 0 when acknowledgement is received
# bit 2:1: Reserved
# bit 0: Interrupt acknowledge. When set, clears a pending interrupt
# Reset bus before beginning
self.resetI2cBus()
# Set slave address in bits 7:1, and set bit 0 to zero
# (i.e. we're writing an address to the bus)
self._chipsBus().queueWrite(self._i2cProps.txReg,
(self._slaveAddr << 1) | 0x01)
# Set start and write bit in command reg
self._chipsBus().queueWrite(self._i2cProps.cmdReg, 0x90)
# Run the queue
self._chipsBus().queueRun()
# Wait for transaction to finish.
self._i2cWaitUntilFinished()
result=[]
for ibyte in range(numBytes):
if ibyte==numBytes-1:
stop_bit=0x40
ack_bit=0x08
else:
stop_bit=0
ack_bit=0
pass
# Set read bit, acknowledge and stop bit in command reg
self._chipsBus().write(self._i2cProps.cmdReg, 0x20+ack_bit+stop_bit)
# Wait for transaction to finish.
# Don't expect an ACK, do expect bus free at finish.
if stop_bit:
self._i2cWaitUntilFinished(requireAcknowledgement = False,
requireBusIdleAtEnd = True)
else:
self._i2cWaitUntilFinished(requireAcknowledgement = False,
requireBusIdleAtEnd = False)
pass
result.append(self._chipsBus().read(self._i2cProps.rxReg))
return result
def _privateWrite(self, listDataU8):
# I2C write implementation.
#
# Fast I2C write implementation,
# i.e. done with the fewest packets possible.
# transmit reg definitions
# bits 7-1: 7-bit slave address during address transfer
# or first 7 bits of byte during data transfer
# bit 0: RW flag during address transfer or LSB during data transfer.
# '1' = reading from slave
# '0' = writing to slave
# command reg definitions
# bit 7: Generate start condition
# bit 6: Generate stop condition
# bit 5: Read from slave
# bit 4: Write to slave
# bit 3: 0 when acknowledgement is received
# bit 2:1: Reserved
# bit 0: Interrupt acknowledge. When set, clears a pending interrupt
# Reset bus before beginning
self.resetI2cBus()
# Set slave address in bits 7:1, and set bit 0 to zero (i.e. "write mode")
self._chipsBus().queueWrite(self._i2cProps.txReg,
(self._slaveAddr << 1) & 0xfe)
# Set start and write bit in command reg
self._chipsBus().queueWrite(self._i2cProps.cmdReg, 0x90)
# Run the queue
self._chipsBus().queueRun()
# Wait for transaction to finish.
self._i2cWaitUntilFinished()
for ibyte in range(len(listDataU8)):
dataU8 = listDataU8[ibyte]
if ibyte==len(listDataU8)-1:
stop_bit=0x40
else:
stop_bit=0x00
pass
# Set data to be written in transmit reg
self._chipsBus().queueWrite(self._i2cProps.txReg, (dataU8 & 0xff))
# Set write and stop bit in command reg
self._chipsBus().queueWrite(self._i2cProps.cmdReg, 0x10+stop_bit)
# Run the queue
self._chipsBus().queueRun()
# Wait for transaction to finish.
# Do expect an ACK and do expect bus to be free at finish
if stop_bit:
self._i2cWaitUntilFinished(requireAcknowledgement = True,
requireBusIdleAtEnd = True)
else:
self._i2cWaitUntilFinished(requireAcknowledgement = True,
requireBusIdleAtEnd = False)
pass
pass
return
def _i2cWaitUntilFinished(self, requireAcknowledgement = True,
requireBusIdleAtEnd = False):
# Ensures the current bus transaction has finished successfully
# before allowing further I2C bus transactions
# This method monitors the status register
# and will not allow execution to continue until the
# I2C bus has completed properly. It will throw an exception
# if it picks up bus problems or a bus timeout occurs.
maxRetry = 20
attempt = 1
while attempt <= maxRetry:
# Get the status
i2c_status = self._chipsBus().read(self._i2cProps.statusReg)
receivedAcknowledge = not bool(i2c_status & 0x80)
busy = bool(i2c_status & 0x40)
arbitrationLost = bool(i2c_status & 0x20)
transferInProgress = bool(i2c_status & 0x02)
interruptFlag = bool(i2c_status & 0x01)
if arbitrationLost: # This is an instant error at any time
raise ChipsException("I2C error: Arbitration lost!")
if not transferInProgress:
break # The transfer looks to have completed successfully, pending further checks
attempt += 1
# At this point, we've either had too many retries, or the
# Transfer in Progress (TIP) bit went low. If the TIP bit
# did go low, then we do a couple of other checks to see if
# the bus operated as expected:
if attempt > maxRetry:
raise ChipsException("I2C error: Transaction timeout - the 'Transfer in Progress' bit remained high for too long!")
if requireAcknowledgement and not receivedAcknowledge:
raise ChipsException("I2C error: No acknowledge received!")
if requireBusIdleAtEnd and busy:
raise ChipsException("I2C error: Transfer finished but bus still busy!")
#!/usr/bin/python
import MarocSC
marocSC = MarocSC.MarocSC()
marocSC.getBitArray()
marocWordArray = marocSC.getWordArray()
print marocWordArray
marocSC.writeConfigFile("tmp.cfg")
#!/usr/bin/python
import MarocSC_old
marocSC = MarocSC_old.MarocSC_old()
marocSC.getLocalBitArray()
marocWordArray = marocSC.getLocalWordArray()
print marocWordArray
marocSC.writeConfigFile("tmp.cfg")
# Test of ROOT updating histograms.
# hsum1.C ( using Root interpreter ) takes 7.1 seconds for 100,000 fills and 200 updates (using gBenchmark).
# hsum.py takes 4.9s (using time).
from ROOT import TCanvas, TF1 , TH1F , gRandom , gBenchmark
from time import sleep
from math import sqrt
def hsum():
nPlots=64
nPlotsPerCanvas = 4
assert(nPlots%nPlotsPerCanvas == 0),"Number of plots per canvas must be a factor of number-of-plots"
nCanvas = nPlots/nPlotsPerCanvas
nPlotsPerDirection = int(sqrt(nPlotsPerCanvas))
nBits = 12 # number of bits in MAROC ADC
nBins = 2**nBits
histoColour = 42
canvasNames = [ "c%s"%canvas for canvas in range(nCanvas) ]
canvasTitles = [ "ADC Value for Channels %s - %s"%(canvas*nPlotsPerCanvas , (canvas+1)*nPlotsPerCanvas -1) for canvas in range(nCanvas) ]
print canvasNames
print canvasTitles
canvasList = [ TCanvas(canvasNames[chan],canvasTitles[chan],200,10,600,400) for chan in range(nCanvas) ]
histograms = []
# sorry, this next bit isn't very Pythonesque
for canvasIndex in range(nCanvas):
canvas = canvasList[canvasIndex]
canvas.cd(0) # change to current canvas
canvas.Divide(nPlotsPerDirection,nPlotsPerDirection)
for plotIndex in range(nPlotsPerCanvas):
plot = canvasIndex*nPlotsPerCanvas + plotIndex # look the other way please....
print canvasIndex , plotIndex , plot
canvas.cd(plotIndex+1) # Change current pad. (plotIndex counts from 0. Root expects count from 1 (0 is the parent))
canvas.SetGrid()
histo = TH1F("chan%s"%plot,"ADC Counts for channel %s"%plot,nBins,-0.5,nBins-0.5)
histo.SetFillColor(histoColour)
histo.Draw("same")
canvas.Update()
histograms.append( histo )
s1 = histograms[0]
c1 = canvasList[0]
c1.cd(1)
gRandom.SetSeed()
kUPDATE = 500
for i in range (0,100000):
xs1 = gRandom.Gaus(nBins/2,nBins/10)
s1.Fill(xs1,0.3)
if (i and ((i%kUPDATE) == 0) ):
# if (i == kUPDATE):
# s1.Draw("same")
# c1.Update()
c1.Modified()
c1.Update()
c1.Modified()
gBenchmark.Show("hsum")
sleep(100)
hsum()
# Test of ROOT updating histograms.
# hsum1.C ( using Root interpreter ) takes 7.1 seconds for 100,000 fills and 200 updates (using gBenchmark).
# hsum.py takes 4.9s (using time).
from ROOT import TCanvas, TF1 , TH1F , gRandom , gBenchmark
def hsum():
c1 = TCanvas("c1","The HSUM example",200,10,600,400)
c1.SetGrid()
s1 = TH1F("s1","This is the first signal",100,-4,4)
s1.SetFillColor(42)
gRandom.SetSeed()
kUPDATE = 500
for i in range (0,100000):
xs1 = gRandom.Gaus(-0.5,0.5)
s1.Fill(xs1,0.3)
if (i and ((i%kUPDATE) == 0) ):
if (i == kUPDATE):
s1.Draw("same")
c1.Update()
c1.Modified()
c1.Update()
c1.Modified()
gBenchmark.Show("hsum")
hsum()
import logging
def marocLogging(logger,debugLevel=logging.DEBUG):
logger.setLevel(debugLevel)
ch = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)
import time
from PyChipsUser import *
from I2cBusProperties import *
from RawI2cAccess import *
class pc049a_i2c:
############################
### configure i2c connection
############################
def __init__(self,board):
self.board = board
i2cClockPrescale = 0x30
self.i2cBusProps = I2cBusProperties(self.board, i2cClockPrescale)
return
##########################
### scan all i2c addresses
##########################
def i2c_scan(self):
list=[]
for islave in range(128):
i2cscan = RawI2cAccess(self.i2cBusProps, islave)
try:
i2cscan.write([0x00])
device="slave address "+hex(islave)+" "
if islave==0x1f:
device+="(DAC)"
elif islave==0x50:
device+="(serial number PROM)"
elif islave>=0x54 and islave<=0x57:
device+="(sp601 onboard EEPROM)"
else:
device+="(???)"
pass
list.append(device)
pass
except:
pass
pass
return list
###################
### write to EEPROM
###################
def eeprom_write(self,address,value):
if address<0 or address>127:
print "eeprom_write ERROR: address",address,"not in range 0-127"
return
if value<0 or value>255:
print "eeprom_write ERROR: value",value,"not in range 0-255"
return
i2cSlaveAddr = 0x50 # seven bit address, binary 1010000
prom = RawI2cAccess(self.i2cBusProps, i2cSlaveAddr)
prom.write([address,value])
time.sleep(0.01) # write cycle time is 5ms. let's wait 10 to make sure.
return
####################
### read from EEPROM
####################
def eeprom_read(self,address):
if address<0 or address>255:
print "eeprom_write ERROR: address",address,"not in range 0-127"
return
i2cSlaveAddr = 0x50 # seven bit address, binary 1010000
prom = RawI2cAccess(self.i2cBusProps, i2cSlaveAddr)
prom.write([address])
return prom.read(1)[0]
######################
### read serial number
######################
def get_serial_number(self):
result=""
for iaddr in [0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff]:
result+="%02x "%(self.eeprom_read(iaddr))
pass
return result
#################
### set DAC value
#################
def set_dac(self,channel,value , vrefOn = 0 , i2cSlaveAddrDac = 0x1F):
if channel<0 or channel>7:
print "set_dac ERROR: channel",channel,"not in range 0-7 (bit mask)"
return -1
if value<0 or value>0xFFFF:
print "set_dac ERROR: value",value,"not in range 0-0xFFFF"
return -1
# AD5665R chip with A0,A1 tied to ground
#i2cSlaveAddrDac = 0x1F # seven bit address, binary 00011111
print "I2C address of DAC = " , hex(i2cSlaveAddrDac)
dac = RawI2cAccess(self.i2cBusProps, i2cSlaveAddrDac)
# if we want to enable internal voltage reference:
if vrefOn:
# enter vref-on mode:
print "Turning internal reference ON"
dac.write([0x38,0x00,0x01])
else:
print "Turning internal reference OFF"
dac.write([0x38,0x00,0x00])
# now set the actual value
sequence=[( 0x18 + ( channel &0x7 ) ) , (value/256)&0xff , value&0xff]
print sequence
dac.write(sequence)
##################################################
### convert required threshold voltage to DAC code
##################################################
def convert_voltage_to_dac(self,desiredVoltage, Vref=1.300):
Vdaq = ( desiredVoltage + Vref ) / 2
dacCode = 0xFFFF * Vdaq / Vref
return int(dacCode)
##################################################
### calculate the DAC code required and set DAC
##################################################
def set_threshold_voltage(self, channel , voltage ):
dacCode = self.convert_voltage_to_dac(voltage)
print " requested voltage, calculated DAC code = " , voltage , dacCode
self.set_dac(channel , dacCode)
......@@ -5,7 +5,7 @@
from PyChipsUser import *
import sys
import sys , time
from optparse import OptionParser
......@@ -27,14 +27,18 @@ print "Firmware = " , hex(firmwareID)
nChan = 64
oldTriggerCounterVals = nChan*[0]
#trigCounters = board.blockRead("trigCounterBase", nChan )
for chan in range(0 , nChan) :
trigCounterVal = board.read("trigCounterBase", nChan )
print "chan, count = " , chan , trigCounterVal
looping = True
tSleep = 1.0
while looping:
trigCounterVals = board.blockRead("trigCounterBase", nChan )
for chan in range(0 , nChan) :
delta = trigCounterVals[chan] - oldTriggerCounterVals[chan]
print "chan, count , delta = " , chan , trigCounterVals[chan] , delta
oldTriggerCounterVals = trigCounterVals
time.sleep(tSleep)
#board.blockWrite("trigCounterBase", nChan*[0] )
#trigCounters = board.blockRead("trigCounterBase", nChan )
#for chan in range(0 , nChan) :
# print "chan, count = " , chan , trigCounters[chan]
#
# Script setup MAROC and take data.
#
import sys
import time
from optparse import OptionParser
import csv
import MarocReadoutThread
import MarocUnpackingThread
import MarocHistogrammingThread
from PyChipsUser import *
import Queue
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("-n" , dest = 'numTriggers' , default = 600 )
(options, args) = parser.parse_args()
print "IP address = " + options.ipAddress
print "Board address table " + options.boardAddressTable
bAddrTab = AddressTable(options.boardAddressTable)
board = ChipsBusUdp(bAddrTab,options.ipAddress,50001)
firmwareID = board.read("FirmwareId")
print "Firmware ID = " , hex(firmwareID)
rawDataQueue = Queue.Queue()
unpackedDataQueue = Queue.Queue()
readoutThread = MarocReadoutThread.MarocReadoutThread(1,"readoutThread",board,rawDataQueue,debugLevel=logging.INFO)
unpackerThread = MarocUnpackingThread.MarocUnpackingThread(2,"unpackingThread",rawDataQueue,unpackedDataQueue,debugLevel=logging.INFO)
histogramThread = MarocHistogrammingThread.MarocHistogrammingThread(3,"histogrammingThread",unpackedDataQueue,debugLevel=logging.INFO)
readoutThread.start()
unpackerThread.start()
histogramThread.start()
#
# Script to exercise MAROC ADC test firmware
#
from PyChipsUser import *
bAddrTab = AddressTable("./pc049aAddrTable_marocdemo.txt")
board = ChipsBusUdp(bAddrTab,"192.168.200.16",50001)
firmwareID=board.read("FirmwareId")
print "Firmware = " , hex(firmwareID)
adcSpecial = board.read("adcTestLocation")
print "ADC special value = " , hex(adcSpecial)
adcStatus = board.read("adcCtrl")
print "ADC Status before reset = " , hex(adcStatus)
# Should reset ADC
resetADC=0
if (resetADC):
print "Resetting ADC"
board.write("adcCtrl",0x00000002)
adcStatus = board.read("adcCtrl")
print "ADC Status before conversion = " , hex(adcStatus)
# Should trigger an ADC conversion
board.write("adcCtrl",0x00000001)
adcStatus = board.read("adcCtrl")
print "ADC Status after conversion = " , hex(adcStatus)
#adcDataSize = 1024
adcDataSize = 26
adcData = board.blockRead("adcData", adcDataSize)
print "ADC data = "
print adcData
bitCount = board.read("adcBitCount")
print "ADC bit count = " , bitCount
adcWritePointer = board.read("adcWritePointer")
print "ADC write pointer = ", hex(adcWritePointer)
#print "ADC data referenced to write pointer"
#adcData = board.blockRead("adcData", adcDataSize , adcWritePointer - adcDataSize )
#print adcData
print "Trigger Number = " , adcData[0]
print "Timestamp = " , adcData[1]
#
# Script to exercise MAROC ADC test firmware
#
# subprocess for quick hack...
from subprocess import call
# NB. binstr isn't a standard Python library. Install from
# https://pypi.python.org/pypi/binstr/1.3
import binstr
from PyChipsUser import *
import sys
from optparse import OptionParser
import MarocSC
import time
def int2bin(n):
'From positive integer to list of binary bits, msb at index 0'
if n:
bits = []
while n:
n,remainder = divmod(n, 2)
bits.insert(0, remainder)
return bits
else: return [0]
def bin2int(bits):
'From binary bits, msb at index 0 to integer'
i = 0
for bit in bits:
i = i * 2 + bit
return i
def gray2bin(bits):
b = [bits[0]]
for nextb in bits[1:]: b.append(b[-1] ^ nextb)
return b
def greyIntToInt(greyInt):
greyBin = int2bin(greyInt)
normalBin = gray2bin(greyBin)
return bin2int(normalBin)
####################################################################################################
parser = OptionParser()
parser.add_option("-i", dest = 'ipAddress' , default="192.168.200.16")
parser.add_option("-a", dest = 'boardAddressTable' , default="./pc049aAddrTable_marocdemo.txt")
(options, args) = parser.parse_args()
print "IP address = " + options.ipAddress
print "Board address table " + options.boardAddressTable
bAddrTab = AddressTable(options.boardAddressTable)
board = ChipsBusUdp(bAddrTab,options.ipAddress,50001)
firmwareID=board.read("FirmwareId")
print "Firmware = " , hex(firmwareID)
# Set up slow control
marocSC = MarocSC.MarocSC()
marocSC.setParameterValue("DAC",[650,450])
marocSC.setFlagValue("d1_d2",0)
marocSC.setFlagValue("cmd_fsb_fsu",1) # Select FSU
marocSC.setParameterValue("mask_OR",0x3,54) # Mask hot channel
SCData = marocSC.getWordArray()
print SCData
marocSC.writeConfigFile("testADC_marocSC.csv")
# Should write to output data buffer
board.blockWrite("scSrDataOut",SCData)
board.write("scSrCtrl" , 0x00000000)
# Set up which triggers are active.
#board.write("trigSourceSelect",0x00000001) # Just set internal triggers active
board.write("trigSourceSelect",0x0000000D) # Set OR1,OR2 and internal triggers active
trigSource = board.read("trigSourceSelect")
print "Trigger source select register = " , hex(trigSource)
print "Resetting timestamp and trigger counters"
board.write("trigStatus",0x00000001)
useSoftwareTrigger = False
conversionOnly = False
resetWritePointer = True
sleepBeforeReadout = True
if resetWritePointer:
# Should trigger an ADC conversion
print "Resetting write pointer"
board.write("adcCtrl",0x00000002)
if useSoftwareTrigger:
print "Firing manual trigger (should also trigger ADC conversion)"
board.write("trigManualTrigger",0x00000001)
if conversionOnly:
# Should trigger an ADC conversion
print "Starting ADC conversion"
board.write("adcCtrl",0x00000001)
adcStatus = board.read("adcCtrl")
print "ADC Status before conversion = " , hex(adcStatus)
if sleepBeforeReadout:
sleepTime = 5
print "Sleeping for ",sleepTime, " seconds. Press manual trigger"
time.sleep(sleepTime)
# Set usePing=1 if running with simulated hardware. Set to zero if running with real hardware.
usePing = 0
if usePing:
# use for Modelsim with DMN fake hardware to allow sim to run....
call(["ping", "-c" , "26" , "192.168.200.16"])
adcStatus = board.read("adcCtrl")
print "ADC Status after conversion = " , hex(adcStatus)
bitCount = board.read("adcBitCount")
print "ADC bit count = " , bitCount , "(should be 64*12 = 768 bits)"
adcWritePointer = board.read("adcWritePointer")
print "ADC write pointer = ", hex(adcWritePointer)
#adcDataSize = 1024
print "Reading ADC data referenced to write pointer"
adcDataSize = 26
adcData = board.blockRead("adcData", adcDataSize ,
(adcWritePointer - adcDataSize))
print "Trigger Number = " , hex(adcData[0])
print "Timestamp = " , hex(adcData[1])
hexAdcData = [ hex(x) for x in adcData]
#print adcData
print hexAdcData
nBits = 12
busWidth = 32
nADC = 64
for adcNumber in range(0 , nADC) :
lowBit = adcNumber*nBits
lowWord = (adcDataSize-1) - (lowBit /busWidth) # rounds to integer
lowBitPos = lowBit % busWidth
if adcNumber > (nADC-3): # for adc's 62,63
longWord = adcData[lowWord]
else:
longWord = adcData[lowWord] + (adcData[lowWord-1] << busWidth)
adcValue = 0x0FFF & (longWord >> lowBitPos)
adcValueBin = greyIntToInt(adcValue)
print "nADC, lowBit , lowWord , lowBitPos , hex(longWord) , hex(adcValue)" , adcNumber , lowBit , lowWord , lowBitPos , hex(longWord) , hex(adcValue), hex( adcValueBin )
#
# Script to exercise MAROC ADC test firmware
#
# subprocess for quick hack...
from subprocess import call
# NB. binstr isn't a standard Python library. Install from
# https://pypi.python.org/pypi/binstr/1.3
import binstr
from PyChipsUser import *
import sys
from optparse import OptionParser
def int2bin(n):
'From positive integer to list of binary bits, msb at index 0'
if n:
bits = []
while n:
n,remainder = divmod(n, 2)
bits.insert(0, remainder)
return bits
else: return [0]
def bin2int(bits):
'From binary bits, msb at index 0 to integer'
i = 0
for bit in bits:
i = i * 2 + bit
return i
def gray2bin(bits):
b = [bits[0]]
for nextb in bits[1:]: b.append(b[-1] ^ nextb)
return b
def greyIntToInt(greyInt):
greyBin = int2bin(greyInt)
normalBin = gray2bin(greyBin)
return bin2int(normalBin)
####################################################################################################
parser = OptionParser()
parser.add_option("-i", dest = 'ipAddress' , default="192.168.200.16")
parser.add_option("-a", dest = 'boardAddressTable' , default="./pc049aAddrTable_marocdemo.txt")
(options, args) = parser.parse_args()
print "IP address = " + options.ipAddress
print "Board address table " + options.boardAddressTable
bAddrTab = AddressTable(options.boardAddressTable)
board = ChipsBusUdp(bAddrTab,options.ipAddress,50001)
firmwareID=board.read("FirmwareId")
print "Firmware = " , hex(firmwareID)
# Set up which triggers are active. Set just internal trigger active
board.write("trigSourceSelect",0x00000001)
trigSource = board.read("trigSourceSelect")
print "Trigger source select register = " , hex(trigSource)
adcStatus = board.read("adcCtrl")
print "ADC Status before conversion = " , hex(adcStatus)
useTrigger = 1
if useTrigger:
print "Firing manual trigger (should also trigger ADC conversion)"
board.write("trigManualTrigger",0x00000001)
else:
# Should trigger an ADC conversion
print "Starting ADC conversion"
board.write("adcCtrl",0x00000001)
# Set usePing=1 if running with simulated hardware. Set to zero if running with real hardware.
usePing = 0
if usePing:
# use for Modelsim with DMN fake hardware to allow sim to run....
call(["ping", "-c" , "26" , "192.168.200.16"])
adcStatus = board.read("adcCtrl")
print "ADC Status after conversion = " , hex(adcStatus)
bitCount = board.read("adcBitCount")
print "ADC bit count = " , bitCount
adcWritePointer = board.read("adcWritePointer")
print "ADC write pointer = ", hex(adcWritePointer)
#adcDataSize = 1024
print "Reading ADC data referenced to write pointer"
adcDataSize = 26
adcData = board.blockRead("adcData", adcDataSize ,
(adcWritePointer - adcDataSize))
print "Trigger Number = " , hex(adcData[0])
print "Timestamp = " , hex(adcData[1])
hexAdcData = [ hex(x) for x in adcData]
#print adcData
print hexAdcData
nBits = 12
busWidth = 32
nADC = 64
for adcNumber in range(0 , nADC) :
lowBit = adcNumber*nBits
lowWord = (adcDataSize-1) - (lowBit /busWidth) # rounds to integer
lowBitPos = lowBit % busWidth
if adcNumber > (nADC-3):
longWord = adcData[lowWord]
else:
longWord = adcData[lowWord] + (adcData[lowWord-1] << busWidth)
adcValue = 0x0FFF & (longWord >> lowBitPos)
adcValueBin = greyIntToInt(adcValue)
# print "nADC, lowBit , lowWord , lowBitPos , hex(longWord) , hex(adcValue)" , adcNumber , lowBit , lowWord , lowBitPos , hex(longWord) , hex(adcValue), hex( adcValueBin )
print "nADC , hex(adcValueBin)" , adcNumber, hex( adcValueBin )
#
# Script to exercise AIDA mini-TLU
#
# David Cussans, December 2012
#
# Modified by Alvaro Dosil, January 2013
from PyChipsUser import *
from pc049a_i2c.py import *
from ROOT import *
import sys
import time
def mean(TS):
val=0
for i in range(1,len(TS)):
val+=TS[i]-TS[i-1]
return val/(len(TS)-1)
bAddrTab = AddressTable("./aida_mini_tlu_addr_map.txt")
# Assume DIP-switch controlled address. Switches at 1
board = ChipsBusUdp(bAddrTab,"192.168.200.16",50001)
firmwareID=board.read("FirmwareId")
print "Firmware = " , hex(firmwareID)
# Check the bus for I2C devices
boardi2c = FmcTluI2c(board)
print "Scanning I2C bus:"
scanResults = boardi2c.i2c_scan()
print scanResults
boardId = boardi2c.get_serial_number()
print "serial number = " , boardId
#
# Script to exercise MAROC Timestamp
#
import sys
import time
from optparse import OptionParser
import csv
from PyChipsUser import *
parser = OptionParser()
parser.add_option("-f", dest = 'ipAddress1' , default="192.168.200.208")
parser.add_option("-s", dest = 'ipAddress2' , default="192.168.200.224")
#parser.add_option("-f", dest = 'ipAddress1' , default="192.168.200.16")
#parser.add_option("-s", dest = 'ipAddress2' , default="192.168.200.32")
parser.add_option("-a", dest = 'boardAddressTable' , default="./fiveMarocAddrTable.txt")
parser.add_option("-o", dest = 'outputFile' , default = 'marocTimeStamps.dat' )
parser.add_option("-n" , dest = 'numTriggers' , default = 600 )
(options, args) = parser.parse_args()
csvfile = open( options.outputFile , 'w' )
print "IP addresses = " + options.ipAddress1 , " , " , options.ipAddress2
print "Board address table " + options.boardAddressTable
bAddrTab = AddressTable(options.boardAddressTable)
boards = [ ChipsBusUdp(bAddrTab,options.ipAddress1,50001) , ChipsBusUdp(bAddrTab,options.ipAddress2,50001) ]
firmwareIDs=[boards[0].read("FirmwareId") , boards[1].read("FirmwareId") ]
print "Firmware IDs = " , hex(firmwareIDs[0]) , hex(firmwareIDs[1])
# reset pointers etc.
print "Resetting pointers"
boards[0].write("controlReg",0xFFFF)
boards[1].write("controlReg",0xFFFF)
#sleepVal = 0.05
#print "Sleeping for " , sleepVal , " seconds"
#time.sleep(sleepVal)
SOFTWARE=0x01
HDMI= 0x02
OR1= 0x04
OR2= 0x08
OR1N= 0x10
OR2N= 0x20
GPIO= 0x40
#triggerSourceMask = ( SOFTWARE | OR1 | OR2 ) # software and or1, or2 triggers active
triggerSourceMask = ( GPIO ) # software and or1, or2 triggers active
boards[0].write("trigSourceSelect",triggerSourceMask) # select trigger source()s
boards[1].write("trigSourceSelect",triggerSourceMask) # select trigger source(s)
trigSource = [ boards[0].read("trigSourceSelect") , boards[0].read("trigSourceSelect") ]
print "Trigger source select register = " , hex(trigSource[0]) , hex(trigSource[1])
# write to mask register
maskval = [ boards[0].read("mask") , boards[1].read("mask") ]
print "MAROC Mask = ", hex(maskval[0]) ,hex(maskval[1])
internalTriggers = 0
readPointers = [0,0]
eventNumbers = [0,0]
eventData = [ [] , []]
timeStampEventSize = 12
timeStampBufferSize = 512
for iTrig in range(0, int(options.numTriggers) ):
if internalTriggers:
print "Firing manual trigger"
boards[0].write("trigManualTrigger",0x00000001)
boards[1].write("trigManualTrigger",0x00000001)
for iBoard in range(len(boards)):
print "Reading data for trigger , board = " , iTrig , iBoard
trigConversionCount = boards[iBoard].read("trigConversionCount")
trigDPRWritePointer = boards[iBoard].read("trigDPRWritePointer")
timeStampData = boards[iBoard].blockRead("trigTimestampBuffer", timeStampBufferSize )
#print "Timestamp data (entire buffer)= " , timeStampData
print " Loop number = " , iTrig
print "Trigger Number (from trigConversionCount) = " , trigConversionCount
print "DPR write pointer ( trigDPRWritePointer ) = " , trigDPRWritePointer
trigOR1_0_Counter = boards[iBoard].read("trigOR1_0_Counter")
print "trigOR1_0_Counter = " , trigOR1_0_Counter
trigOR1_1_Counter = boards[iBoard].read("trigOR1_1_Counter")
print "trigOR1_1_Counter = " , trigOR1_1_Counter
trigOR1_2_Counter = boards[iBoard].read("trigOR1_2_Counter")
print "trigOR1_2_Counter = " , trigOR1_2_Counter
trigOR1_3_Counter = boards[iBoard].read("trigOR1_3_Counter")
print "trigOR1_3_Counter = " , trigOR1_3_Counter
trigOR1_4_Counter = boards[iBoard].read("trigOR1_4_Counter")
print "trigOR1_4_Counter = " , trigOR1_4_Counter
trigOR2_0_Counter = boards[iBoard].read("trigOR2_0_Counter")
print "trigOR2_0_Counter = " , trigOR2_0_Counter
trigOR2_1_Counter = boards[iBoard].read("trigOR2_1_Counter")
print "trigOR2_1_Counter = " , trigOR2_1_Counter
trigOR2_2_Counter = boards[iBoard].read("trigOR2_2_Counter")
print "trigOR2_2_Counter = " , trigOR2_2_Counter
trigOR2_3_Counter = boards[iBoard].read("trigOR2_3_Counter")
print "trigOR2_3_Counter = " , trigOR2_3_Counter
trigOR2_4_Counter = boards[iBoard].read("trigOR2_4_Counter")
print "trigOR2_4_Counter = " , trigOR2_4_Counter
eventNumbers[iBoard] = timeStampData[ readPointers[iBoard] ]
print "Event number from board , iBoard = " , eventNumbers[iBoard]
if (trigDPRWritePointer >= readPointers[iBoard]):
print "No pointer wrap round"
else:
print "Pointer has wrapped round"
while ( (readPointers[iBoard]+timeStampEventSize)<timeStampBufferSize):
boardData = timeStampData[ readPointers[iBoard]:(readPointers[iBoard]+timeStampEventSize)]
readPointers[iBoard] = readPointers[iBoard] + timeStampEventSize
print "timeStampEventSize = " , timeStampEventSize
#print boardData
eventData[iBoard].append(boardData)
# glue together the data that wraps round end of buffer
boardData = timeStampData[ readPointers[iBoard]: ]
wordsRead = timeStampBufferSize - readPointers[iBoard]
print "read pointer just before gluing " , readPointers[iBoard]
print "words read at top of buffer = " , wordsRead
readPointers[iBoard] = timeStampEventSize - wordsRead
print "read pointer set to " , readPointers[iBoard]
boardData = boardData + timeStampData[0:readPointers[iBoard]]
print "glued event data = ",boardData
eventData[iBoard].append(boardData)
while ( (readPointers[iBoard]+timeStampEventSize)<=trigDPRWritePointer):
boardData = timeStampData[ readPointers[iBoard]:(readPointers[iBoard]+timeStampEventSize)]
readPointers[iBoard] = readPointers[iBoard] + timeStampEventSize
print "readPointer = " , readPointers[iBoard]
#print boardData
eventData[iBoard].append(boardData)
# Loop through and print out a CSV file.
csvwriter = csv.writer(csvfile,delimiter=',')
numEvents = len(eventData[0])
print " Number of Events recorded = " , numEvents
for iEvent in range(numEvents):
dataWords = []
for iBoard in range (len(boards)):
for dataWord in eventData[iBoard][iEvent]:
dataWords.append(dataWord)
#print dataWord , ", ",
print dataWords
print
csvwriter.writerow(dataWords)
#
# Script to read out Trigger counters looping over DAC values
#
from PyChipsUser import *
import sys , time
from optparse import OptionParser
import logging
import MarocSC
import matplotlib.pyplot as plt
###################################################################
# Define function to set DAC value
def setDAC ( marocSC , DACVal ):
marocSC.setParameterValue("DAC",[DACVal,DACVal])
SCData = marocSC.getWordArray()
board.blockWrite("scSrDataOut",SCData)
board.write("scSrCtrl" , 0x00000000)
board.write("scSrCtrl" , 0x00000001)
####################################################################################################
parser = OptionParser()
parser.add_option("-i", dest = 'ipAddress' , default="192.168.200.16")
parser.add_option("-a", dest = 'boardAddressTable' , default="./pc049aAddrTable_marocdemo.txt")
(options, args) = parser.parse_args()
print "IP address = " + options.ipAddress
print "Board address table " + options.boardAddressTable
bAddrTab = AddressTable(options.boardAddressTable)
board = ChipsBusUdp(bAddrTab,options.ipAddress,50001)
firmwareID=board.read("FirmwareId")
print "Firmware = " , hex(firmwareID)
marocSC = MarocSC.MarocSC(debugLevel=logging.INFO)
marocSC.setFlagValue("d1_d2",0) # Select FSU / FSB1 for trigger
marocSC.setFlagValue("cmd_fsb_fsu",1) # Select FSU
marocSC.setParameterValue("mask_OR",0x3,54) # Mask hot channel
nChan = 64
oldTriggerCounterVals = nChan*[0]
triggerSCurveValues = [ [] for _ in range(nChan)] # stores an array of arrays. Each element is an S-Curve. Initialize to a list of empty lists.
print triggerSCurveValues
looping = True
tSleep = 1.0
DACVals = range(0,1024,20)
for DACVal in DACVals:
print "Setting DACVal = " , DACVal
setDAC ( marocSC , DACVal )
oldTrigCounterVals = board.blockRead("trigCounterBase", nChan )
time.sleep(tSleep)
trigCounterVals = board.blockRead("trigCounterBase", nChan )
# print delta
for idx in range(len(trigCounterVals)):
delta = trigCounterVals[idx] - oldTrigCounterVals[idx]
# print "DACVal , idx, delta" , DACVal, idx,delta
triggerSCurveValues[idx].append(delta)
# After loop we have an array of values with each element being a separate DAC value.
# Reshape to have an array with 64 entries with each entry being an array of counts for a given DAC value.
print triggerSCurveValues
plt.plot(DACVals,triggerSCurveValues[27])
plt.ylabel("Trigger Counts (OR1/FSU)")
plt.xlabel("DAC0 value")
plt.show()
......@@ -26,9 +26,13 @@ print "Firmware = " , hex(firmwareID)
marocSC = MarocSC.MarocSC()
marocSC.setFlagValue("ON/OFF_dac",1)
#marocSC.setFlagValue("ON/OFF_dac",1)
marocSC.setParameterValue("DAC",[650,450])
marocSC.setFlagValue("d1_d2",0)
marocSC.setFlagValue("cmd_fsb_fsu",1) # Select FSU
marocSC.setParameterValue("mask_OR",0x3,54) # Mask hot channel
SCData = marocSC.getLocalWordArray()
SCData = marocSC.getWordArray()
print SCData
......@@ -38,7 +42,7 @@ board.blockWrite("scSrDataOut",SCData)
scdata0 = board.blockRead("scSrDataOut",len(SCData))
print "SC SR words to write = " , scdata0
writeWithReset = 0
writeWithReset = 1
writeNoReset = 1
if writeWithReset:
......
#
# Script to write to MAROC configuration ( slow control ) shift register
# Specify a set of bits to write high..
#
import sys
from optparse import OptionParser
from PyChipsUser import *
parser = OptionParser()
parser.add_option("-i", dest = 'ipAddress' , default="192.168.200.16")
parser.add_option("-a", dest = 'boardAddressTable' , default="./pc049aAddrTable_marocdemo.txt")
(options, args) = parser.parse_args()
print "IP address = " + options.ipAddress
print "Board address table " + options.boardAddressTable
bAddrTab = AddressTable(options.boardAddressTable)
board = ChipsBusUdp(bAddrTab,options.ipAddress,50001)
firmwareID=board.read("FirmwareId")
print "Firmware = " , hex(firmwareID)
numSCbits = 829
numWords = 26
busWidth = 32
bits = [ 0, 1, 15, 16, 17, 18, 19, 21, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 187, 188, 191, 200, 209, 218, 227, 236, 245, 254, 263, 272, 281, 290, 299, 308, 317, 326, 335, 344, 353, 362, 371, 380, 389, 398, 407, 416, 425, 434, 443, 452, 461, 470, 479, 488, 497, 506, 515, 524, 533, 542, 551, 560, 569, 578, 587, 596, 605, 614, 623, 632, 641, 650, 659, 668, 677, 686, 695, 704, 713, 722, 737, 740, 749, 758 ]
#bits = [ 0 ]
SCData = numWords*[0x00000000]
for bitNumber in bits:
bitNum = numSCbits - bitNumber -1
wordBitPos = bitNum % busWidth
wordNum = bitNum / busWidth
print "setting bit number (reversed) " , bitNumber , bitNum , " => bit " , wordBitPos , " of word " , wordNum
SCData[wordNum] += 0x00000001 << wordBitPos
print SCData
# Should write to output data buffer
board.blockWrite("scSrDataOut",SCData)
scdata0 = board.blockRead("scSrDataOut",numWords)
print "SC SR words = " , scdata0
# Trigger writing of control register
board.write("scSrCtrl" , 0x00000000)
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