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
This diff is collapsed.
This diff is collapsed.
#
# 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)))