Commit 3cdb7af8 authored by Jan Pospisil's avatar Jan Pospisil

added reset of MC100EP140 bad state; better configuration; better debugging;…

added reset of MC100EP140 bad state; better configuration; better debugging; comments; attempt for better trigger latency calibration (not working yet)
Signed-off-by: 's avatarMichael Betz <Michael.Betz@cern.ch>
parent f036c33f
......@@ -35,6 +35,10 @@
## 2016-09-01 1.1 Jan Pospisil added version numbers (major.minor.rev)
## added clock_stable status bit
## added option for negative pulses
## 2016-09-02 1.2 Michael Betz added reset of MC100EP140 bad state;
## better configuration; better debugging;
## comments; attempt for better trigger
## latency calibration (not working yet)
##-----------------------------------------------------------------------------
# TODO: proper BUSY bits checking
......@@ -109,7 +113,8 @@ def WbSetBits(register, mask, bits = -1):
def WbReadMulti(register, start = 0, to = -1):
result = m.read(register, start=start, to=to)
if WB_DEBUG:
print(ConColors.MAGENTA+'WB_READ_MULTI:'+ConColors.NONE+' ['+register+']('+str(start)+':'+str(to)+') = ' + ', '.join([hex(x) for x in result]))
print(ConColors.MAGENTA+'WB_READ_MULTI:'+ConColors.NONE+' ['+register+']('+str(start)+':'+str(to)+') = ')
hexDump( result )
if WB_DEBUG_2_SV:
address = int(m[register]['offset'], 16)
if to == -1:
......@@ -124,7 +129,8 @@ def WbReadMulti(register, start = 0, to = -1):
def WbWriteMulti(register, data, start = 0, to = -1):
if WB_DEBUG:
print(ConColors.CYAN+'WB_WRITE_MULTI:'+ConColors.NONE+' ['+register+']('+str(start)+':'+str(to)+') <- ' + ', '.join([hex(x) for x in data]))
print(ConColors.CYAN+'WB_WRITE_MULTI:'+ConColors.NONE+' ['+register+']('+str(start)+':'+str(to)+') <- ')
hexDump( data )
if WB_DEBUG_2_SV:
address = int(m[register]['offset'], 16)
if to == -1:
......@@ -238,11 +244,62 @@ def ClearMemory(channel, memory, memoryPart = -1):
to = memoryPart
WbWriteMulti(address, (0,)*partToClear, to = to)
# channel: 1, 2, 0 (for both)
# pulse: 0 - delete, 1 - create
# which: 0 - both, 1 - set, 2 - reset
# polarity: 0 - negative pulse, 1 - positive pulse
def getRegname( channel, targ ):
""" channel: 1, 2 targ: "SET", "RESET" """
regName = {"SET":"ch%1d_set_mem", "RESET":"ch%1d_res_mem"}[targ]%channel
return regName
def putBit( channel, ind, val, targ="SET" ):
"""
channel: 1, 2, 0 (for both)
enable (val=1) or disable (val=0)
a bit in the "SET" or "RESET" array at index `ind`.
"""
regName = getRegname( channel, targ )
# The pulse generator arrays is made up of 32 bit words
# Here we split the array index into a memory address and a bit-index [0 - 31]
val = val & 0x01
position = ind/32
shift = ind%32
WbSetBitsMulti( regName, ((1<<shift),), ((val<<shift),), start=position, to=position+1)
def tobin(x, count=8):
""" Integer to binary. Count is number of padding bits """
return "".join(map(lambda y:str((x>>y)&1), range(count-1, -1, -1)))
def tohex(x, count=8):
""" Integer to hex. Count is number of padding digits """
return "".join(map(lambda y:str((x>>y)&1), range(count-1, -1, -1)))
def hexDump( dataArray ):
""" the ultimate hexdump function """
i = 0
for word in dataArray:
if i%8 == 0:
if i != 0:
sys.stdout.write("\n")
sys.stdout.write( "%4x: "%(i*4) )
#sys.stdout.write( tobin(word,32) + " " ) #binary format
sys.stdout.write( "%08x "%word ) #hex format
i += 1
sys.stdout.write("\n")
def ConfigurePulse(channel, start, stop, pulse, which = 0, polarity = 1):
"""
Manipulate the SET and RESET pulse generator arrays:
channel: 1, 2, 0 (for both)
pulse: 0 - delete, 1 - create
which: 0 - both, 1 - set, 2 - reset
polarity: 0 - negative pulse, 1 - positive pulse
| which: 0 |
| which: 1 | which: 2 |
pulse: 0 | SET[start] = 0 | RESET[stop] = 0 |
pulse: 1 | SET[start] = 1 | RESET[stop] = 1 |
"""
if channel == 1:
address = 'ch1_'
elif channel == 2:
......@@ -261,13 +318,15 @@ def ConfigurePulse(channel, start, stop, pulse, which = 0, polarity = 1):
if (stop < start):
raise Exception("Bad order!")
pulse &= 1
pulse &= 1 # Force all bits to zero except the first one
if polarity == 0:
if polarity == 0: # Swap `start` and `stop` for inverted mode
tmp = start
start = stop
stop = tmp
# The pulse generator arrays is made up of 32 bit words
# Here we split the array index into a memory address and a bit-index [0 - 31]
if which < 2:
position = start/32
shift = start%32
......@@ -358,6 +417,20 @@ def Stop(channel):
channel *= 2
WbSetBits('control', 0x30<<channel, 0) # set mode STOP
def ResetBadState(channel):
""" robust reset function to get out of the bad `state 1` """
Disable( channel ) #Outputs Hi-Z
Stop( channel ) #Stop clock
ClearMemory( channel, '*' ) #Clear the pulse generator arrays
# Define a single SET pulse per cycle,
# after two cycles, the MC100EP140 should be in the good
# state number 3 (output high)
ConfigurePulse(channel, 10, 50, 1, 1, 1)
Start( channel ) #Enable clock
time.sleep( 1e-3 )
Stop( channel )
ClearMemory( channel, '*' )
def Debug():
print('Debug:')
debug = WbRead('debug')
......@@ -456,45 +529,63 @@ def Init(memoryPart = -1):
SetTriggerThreshold(0.5)
SetVcxoFrequency(-0.2105) # 125.0000 MHz
ClearMemory(0, '*', memoryPart)
xx = 56.28 # problem mazbe in CalculateParams
print(xx)
Calibrate(xx) # 63.531 in [ns], depends on setup, cable length...
# how much is RF clock faster than bunch clock
RF_2_BUNCH_RATIO = 5
globalFineOffset = 0
# time 't' is in [ns] - same as other times
# output: (bit, delay)
# bit - position of the bit to set
# delay - delay parameter to be set
def CalculateParams(t):
rfPeriod = 4.99
delayOffset = 3.714
delayScale = 1.0362
def CalculateParams(t, intraBunchCheck = 0):
global globalFineOffset
rfPeriod = 4.99 # 1/Clk_rf
delayOffset = globalFineOffset #3.714 # fine compensation of trigger delay
delayScale = 1.0362 # non-linearity of delay IC
if (t < 0) or (t > RF_2_BUNCH_RATIO * rfPeriod):
if (intraBunchCheck) and ((t < 0) or (t > RF_2_BUNCH_RATIO * rfPeriod)):
raise Exception("Parameter t can be just in one bunch clock period!")
bit = int(t/rfPeriod) # bit position
rest = t - bit * rfPeriod # in ns
rest += delayOffset
delay = int(round(delayScale * rest * 100)) # delay IC value
value = int(round(delayScale * rest * 100))
value += delayOffset
delay = value # delay IC value (10 ps step)
return (bit, delay)
# delay and width (both in [ns]) of thi pulse within one bunch clock
# output: (setBit, resBit) - bit offset within one bunch clock
def SetPulseShape(channel, delay, width):
def SetPulseShape(channel, delay, width, intraBunchCheck = 0):
# calculate bitt shifts and delays
(setBit, setDelay) = CalculateParams(delay)
(resBit, resDelay) = CalculateParams(delay + width)
(setBit, setDelay) = CalculateParams(delay, intraBunchCheck)
(resBit, resDelay) = CalculateParams(delay + width, intraBunchCheck)
# set delays
WbWrite('ch'+str(channel)+'_delay_set', setDelay)
WbWrite('ch'+str(channel)+'_delay_res', resDelay+18)
WbWrite('ch'+str(channel)+'_delay_res', resDelay+18) # 18 is compensating difference between set and res relay IC
# return bit shifts
return (setBit, resBit)
# pulseDelay and pulseWidth in ns
def SetPulse(channel, pulseDelay, pulseWidth, polarity = 1):
ResetBadState(channel)
(setBit, resBit) = SetPulseShape(channel, pulseDelay, pulseWidth)
CreatePulse(channel, setBit, resBit, polarity = polarity)
def TestPulse(channel = 1, overflow = 17820, polarity = 1):
def SetPulsesInBunches(channel, listOfBunches, pulseDelay, pulseWidth, polarity = 1):
ResetBadState(channel)
(setBit, resBit) = SetPulseShape(channel, pulseDelay, pulseWidth, intraBunchCheck = 1)
for bunch in listOfBunches:
CreatePulse(channel, (bunch * RF_2_BUNCH_RATIO)+setBit, (bunch * RF_2_BUNCH_RATIO)+resBit, polarity = polarity)
def TestPulseInBunches(channel = 1, overflow = 17820, polarity = 1):
# configure channel
WbWrite('overflow', overflow)
WbWrite('trig_latency', 12)
pulseDelay = 10 # inter-bunch pulse delay in [ns]
pulseWidth = 10 # inter-bunch pulse width in [ns]
......@@ -502,18 +593,36 @@ def TestPulse(channel = 1, overflow = 17820, polarity = 1):
# bunches = range(overflow / RF_2_BUNCH_RATIO)
# bunches = (0,)
(setBit, resBit) = SetPulseShape(channel, pulseDelay, pulseWidth)
for bunch in bunches:
CreatePulse(channel, (bunch * RF_2_BUNCH_RATIO)+setBit, (bunch * RF_2_BUNCH_RATIO)+resBit, polarity = polarity)
SetPulsesInBunches(channel, bunches, pulseDelay, pulseWidth)
Enable(channel)
Start(channel)
def TestPulse(channel = 1, overflow = 17820, polarity = 1):
# configure channel
WbWrite('overflow', overflow)
SetPulse(channel, pulseDelay = 0, pulseWidth = 100, polarity=polarity)
Enable(channel)
Start(channel)
# phaseOffset in [ns] - real offset to the real beam
def Calibrate(phaseOffset):
global globalFineOffset
globalFineOffset = 0
(bitOffset, fineOffset) = CalculateParams(phaseOffset)
print('bitOffset = '+str(bitOffset)+', fineOffset = '+str(fineOffset))
WbWrite('trig_latency', bitOffset)
globalFineOffset = fineOffset
Init()
Control()
Status()
TestPulse(1, polarity = 0)
# TestPulse(2)
#TestPulseInBunches(1, polarity = 0)
TestPulse(1, polarity = 1)
Control()
Status()
Version()
......@@ -530,4 +639,4 @@ if WB_DEBUG_2_SV:
WB_DEBUG_2_SV_FP.write('\n')
WB_DEBUG_2_SV_FP.write('$display("Error count: %0d\\n", errors);\n')
WB_DEBUG_2_SV_FP.close()
WB_DEBUG_2_SV = False
\ No newline at end of file
WB_DEBUG_2_SV = False
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