Compare commits
7 commits
7826cce063
...
90d5d885a3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90d5d885a3 | ||
|
|
1d9caa689c | ||
|
|
2eaf8f41eb | ||
|
|
fcfd6f72ab | ||
|
|
d02f716316 | ||
|
|
354c2c5171 | ||
|
|
93e582cbe5 |
3 changed files with 458 additions and 394 deletions
452
dorn.py
Executable file
452
dorn.py
Executable file
|
|
@ -0,0 +1,452 @@
|
|||
import math
|
||||
|
||||
AHEPAM_CONFIG = {
|
||||
dorn_addr: 0x2000,
|
||||
verbose: True,
|
||||
slices: (0,1),
|
||||
n_channels: 24
|
||||
}
|
||||
|
||||
def dorn_config(a, v=None, m=None, slice=0):
|
||||
verb = AHEPAM_CONFIG.verbose
|
||||
a |= AHEPAM_CONFIG.dorn_addr | (slice<<11)
|
||||
a &= 0xfff
|
||||
if v is None:
|
||||
if not m:
|
||||
m = f"dorn[0x{a:03x}]"
|
||||
return int(ecmd(f"alt/cmd/del[10] 0x{a:03x}", task=m, verb=verb).split()[-1], 0)
|
||||
if not m:
|
||||
m = f"dorn[0x{a:03x}] = 0x{v:04x}"
|
||||
if v is False:
|
||||
ecmd(f"alt/cmd/inj/del[1] 0x{a:03x}", task=m, verb=verb)
|
||||
else:
|
||||
ecmd(f"alt/cmd/inj/del[1] 0x{a:03x} 0x{v:04x}", task=m, verb=verb)
|
||||
|
||||
def thres(sl, ch, v):
|
||||
dorn_config(0x040 | ch, v, slice=sl)
|
||||
|
||||
def write_l2(sl, ch, i, a, b):
|
||||
dorn_config(0x400 | (ch<<3) | (i<<1) | 0, a & 0xffff, slice=sl)
|
||||
dorn_config(0x400 | (ch<<3) | (i<<1) | 1, b & 0xffff, slice=sl)
|
||||
|
||||
l2_set6 = (
|
||||
(0, -1203, 0),
|
||||
(1, -1203, 0),
|
||||
(2, -1203, 0),
|
||||
(3, -1186, 0),
|
||||
(4, -39, 2000),
|
||||
(5, 1709, 970),
|
||||
(6, 2000, -1082),
|
||||
(7, 1125, -1888),
|
||||
)
|
||||
|
||||
l2cal = [
|
||||
[
|
||||
0.99964,
|
||||
None,
|
||||
0.99117,
|
||||
None,
|
||||
None, None, None, None,
|
||||
1.00178,
|
||||
None, None, None,
|
||||
None, None, None, None,
|
||||
],
|
||||
[], [], [],
|
||||
]
|
||||
|
||||
|
||||
def calib_l2(cal, l2_set6):
|
||||
if cal is None:
|
||||
return coeff
|
||||
from numpy import array, floor, add, any
|
||||
c = array(coeff)[:,1:] * cal
|
||||
i = floor(c+0.5)
|
||||
e = add.reduce(i)
|
||||
v = e>0
|
||||
w = e<0
|
||||
while any(v) or any(w):
|
||||
d = i - c
|
||||
vv = d.argmax(axis=0)
|
||||
ww = d.argmin(axis=0)
|
||||
for x,f in enumerate(v):
|
||||
if f:
|
||||
i[vv[x],x] -= 1
|
||||
for x,f in enumerate(w):
|
||||
if f:
|
||||
i[ww[x],x] += 1
|
||||
e = add.reduce(i)
|
||||
v = e>0
|
||||
w = e<0
|
||||
return [(x, int(ii[0]), int(ii[1])) for x, ii in enumerate(i)]
|
||||
|
||||
def l2filter(coeff=l2_set6, cal=None):
|
||||
for sl in AHEPAM_CONFIG.slices:
|
||||
for ch in range(AHEPAM_CONFIG.n_channels):
|
||||
c = coeff
|
||||
if cal and cal[sl] and cal[sl][ch]:
|
||||
c = calib_l2(cal[sl][ch])
|
||||
for cc in c:
|
||||
write_l2(sl, ch, *cc)
|
||||
|
||||
def write_l3(sl, ch, *p):
|
||||
scales = (14, 16, 14, 15)
|
||||
for i,pp in enumerate(p):
|
||||
if isinstance(pp, float):
|
||||
pp = int(pp * 2**scales[i])
|
||||
dorn_config(0x100 | (ch<<2) | i, pp & 0xffff, slice=sl)
|
||||
|
||||
def l3banana(
|
||||
# iterated F-banana 2022-03-13-aha-bi207-18,
|
||||
p0 = -4007,
|
||||
p1 = 0,
|
||||
p2 = 12737,
|
||||
p3 = -3698 ):
|
||||
for sl in AHEPAM_CONFIG.slices:
|
||||
for ch in range(12):
|
||||
write_l3(sl, ch, p0, p1, p2, p3)
|
||||
|
||||
def c16log2(A):
|
||||
return int(math.ceil(16*math.log(1024*A)/math.log(2)))
|
||||
|
||||
def enable_trigger(sl, triggers, det=False, sa=False):
|
||||
i = 2 if sa else 0 if det else 1
|
||||
dorn_config(0x008 | i | sl<<4, triggers, slice=sl)
|
||||
|
||||
def nsamples(sl, n=None, m=None, **slice):
|
||||
if n is None:
|
||||
return dorn_config(0x00b | sl<<4, slice=sl)
|
||||
if m is None:
|
||||
m = 0xfff if n else 0
|
||||
enable_trigger(sl, m, sa=True)
|
||||
dorn_config(0x00b | sl<<4, n, slice=sl)
|
||||
|
||||
def triggers(sl, atrig=0x3ff, dtrig=0, sam=0, nsa=32):
|
||||
enable_trigger(sl, dtrig, det=True)
|
||||
enable_trigger(sl, atrig)
|
||||
nsamples(sl, nsa, sam)
|
||||
|
||||
def hist_bins(sl, bin0=4.0, res=1, cwin=6, xtalk=6):
|
||||
"""configure dorn_l4 histogramming
|
||||
bin0: float: A-value of bin 0, int: 16LOG2(A)
|
||||
res: bin = 16×log₂(A) >> res
|
||||
cwin: anti-coincidence window [µs]
|
||||
xtalk: x-talk ratio cut: reject if S > (S>>xtalk)
|
||||
"""
|
||||
if isinstance(bin0, float):
|
||||
bin0=c16log2(bin0)
|
||||
dorn_config(0x00c | sl<<4, (xtalk<<8) | cwin)
|
||||
dorn_config(0x00d | sl<<4, (res<<9) | bin0)
|
||||
|
||||
def base_address(hists=None, counters=None, hmask=None, cmask=None):
|
||||
if hists is not None:
|
||||
if counters is None:
|
||||
counters = hists
|
||||
r = dorn_config(0x088, (counters<<3) | hists)
|
||||
else:
|
||||
if hmask is not None:
|
||||
r = dorn_config(0x088, 0x4000 | hmask)
|
||||
if cmask is not None:
|
||||
r = dorn_config(0x088, 0x8000 | cmask)
|
||||
if cmask is None and hmask is None:
|
||||
r = dorn_config(0x088, 0x8000)
|
||||
return r & 7, r >> 3
|
||||
|
||||
def fifo_status(i=None):
|
||||
e = dorn_config(0x084)
|
||||
p = dorn_config(0x085)
|
||||
f = dorn_config(0x086)
|
||||
if i is None:
|
||||
return e,p,f
|
||||
return (e>>i)&1, (p>>i)&1, (f>>i)&1
|
||||
|
||||
def fifo_select(hi=False, sl=None, hk=False, ev=False, sa=False, i=None):
|
||||
if i is not None:
|
||||
f = 1<<i
|
||||
else:
|
||||
f = (sa<<2) | (ev<<1) | hk
|
||||
if sl is not None:
|
||||
f <<= 3*sl+1
|
||||
else:
|
||||
f *= 18
|
||||
f |= hi
|
||||
return f
|
||||
|
||||
def fifo_enable(en=False, rfifo=False, sl=None, **aa):
|
||||
f = fifo_select(sl=sl, **aa)
|
||||
if sl is None and en:
|
||||
en = 3
|
||||
elif sl is not None:
|
||||
en <<= sl
|
||||
dorn_config(0x087, (f<<6) | (rfifo<<5) | en)
|
||||
|
||||
STROBES = {
|
||||
"read_fifos": 0,
|
||||
"incr": 1,
|
||||
"resync": 2,
|
||||
"clock_reset": 3,
|
||||
"hk": 4,
|
||||
"dorn_reset": 8,
|
||||
"mem_reset": 12,
|
||||
"rb_reset": 13,
|
||||
"fifo_reset": 14,
|
||||
}
|
||||
|
||||
def strobe(sl=None, **aa):
|
||||
s = 0
|
||||
for k in aa:
|
||||
if not k in STROBES:
|
||||
raise KeyError(f"No STROBE: {k}")
|
||||
if aa[k]:
|
||||
b = 1
|
||||
if k=="hk":
|
||||
if sl is None:
|
||||
b = 15;
|
||||
else:
|
||||
b <<= sl
|
||||
s |= b << STROBES[k]
|
||||
dorn_config(0x08b, s)
|
||||
|
||||
def fifo_reset(**aa):
|
||||
f = fifo_select(**aa)
|
||||
if not f:
|
||||
strobe(fifo_reset=True)
|
||||
else:
|
||||
dorn_config(0x084, f)
|
||||
|
||||
def fifo_read(**aa):
|
||||
f = fifo_select(**aa)
|
||||
if not f:
|
||||
ecmd("alt/cmd/inj 0x8800", verb=_verbose)
|
||||
else:
|
||||
dorn_config(0x085, f)
|
||||
|
||||
def degC(a, R1=10e3, R25=10e3, B25=3750, res=0x1000):
|
||||
R=R1*a/(res-(a&(res-1)))
|
||||
return B25/(math.log(R/R25)+B25/298) - 273
|
||||
|
||||
#TO DO: Adjust
|
||||
def nmahepam_hk(sl, what="data", data=none, ND=8, NV=8, Vref=3.3):
|
||||
if not data:
|
||||
ecmd("alt/stream/off")
|
||||
fifo_enable(en=True, sl=sl, hk=True)
|
||||
fifo_reset(sl=sl, hk=True)
|
||||
strobe(sl=sl, hk=True)
|
||||
sleep(0.001)
|
||||
fifo_read(sl=sl, hk=True)
|
||||
data=read_fifo()
|
||||
if (data[0] & 0xfffc) != 0x5710:
|
||||
raise ValueError("Read HK packet error", data)
|
||||
if what=="data":
|
||||
return data
|
||||
data = [d & 0xfff for d in data]
|
||||
data = [data[ND*i+1:ND*i+1+NV] for i in range(8)]
|
||||
if what=="raw":
|
||||
return data
|
||||
#NMAHEPAM:data[7][0] *= 2*Vref/4096 # Vcore
|
||||
data[7][1] = degC(data[7][1]) # Tana
|
||||
data[7][2] *= 2*Vref/4096 # V+6
|
||||
data[7][3] *= 2.5*Vref/4096 # V-6
|
||||
data[7][3] -= 1.5*data[7][2]
|
||||
data[6][0] *= Vref/4096/0.0206 # Vbias
|
||||
data[6][1] = degC(data[6][1]) # Tpa
|
||||
data[6][3] *= 2*Vref/4096 # Vcc
|
||||
data[6][2] *= 2.5*Vref/4096 # Vss
|
||||
data[6][2] -= 1.5*data[6][3]
|
||||
if what=="cooked":
|
||||
return data
|
||||
sys.stderr.write("""nmahepam HK:
|
||||
Vcore = %6.3f V
|
||||
Tana = %6.2f °C
|
||||
V+6 = %6.3f V
|
||||
V-6 = %6.3f V
|
||||
Vbias = %6.2f V
|
||||
Tpa = %6.2f °C
|
||||
Vss = %6.3f V
|
||||
Vcc = %6.3f V
|
||||
""" % tuple(data[7]+data[6]))
|
||||
|
||||
def default_config(thr=0x7ff):
|
||||
for sl in range(AHEPAM_CONFIG.slices):
|
||||
for ch in range(AHEPAM_CONFIG.n_channels):
|
||||
thres(sl, ch, thr)
|
||||
l2filter()
|
||||
l3banana()
|
||||
for sl in range(AHEPAM_CONFIG.slices):
|
||||
hist_bins(sl)
|
||||
triggers(sl, 0)
|
||||
|
||||
def print_trigger_config():
|
||||
tri = [[dorn_config(0x008 + i + (sl<<4)) for i in range(4)] for sl in range(2)]
|
||||
ff = [dorn_config(0x084+i) for i in range(4)]
|
||||
tri.append(ff)
|
||||
e = ff[3]
|
||||
df = [Areg(0x11+i) for i in range(3)]
|
||||
df.append(Areg(5))
|
||||
tri.append(df)
|
||||
print(f"""narena trigger config:
|
||||
trigger detector masks:
|
||||
det triggers: 0x{tri[0][0]:x} 0x{tri[1][0]:x}
|
||||
channel triggers: 0x{tri[0][1]:03x} 0x{tri[1][1]:03x}
|
||||
sample readout triggers: 0x{tri[0][2]:03x} 0x{tri[1][2]:03x}
|
||||
number of sample records: {tri[0][3]:-5d} {tri[1][3]:-5d}
|
||||
enable: {e&1} {(e>>1)&1}
|
||||
fifos enable SA/EV/HK HI {(e>>7)&7:03b} {(e>>10)&7:03b} {(e>>6)&1}
|
||||
empty {(ff[0]>>1)&7:03b} {(ff[0]>>4)&7:03b} {ff[0]&1} {(df[3]>>9)&7:03b}
|
||||
packet {(ff[1]>>1)&7:03b} {(ff[1]>>4)&7:03b} {ff[1]&1} {(df[3]>>13)&7:03b}
|
||||
full {(ff[2]>>1)&7:03b} {(ff[2]>>4)&7:03b} {ff[2]&1} {(df[3]>>5)&7:03b}
|
||||
dig fifo status {df[2]&0x3ff} {df[1]&0x3ff} {df[0]&0x3ff}
|
||||
""", file=sys.stderr)
|
||||
return tri
|
||||
|
||||
def read_event(sl=None, ev=None):
|
||||
if ev is None:
|
||||
fifo_read(sl=sl, ev=True)
|
||||
ev = read_fifo(2)
|
||||
if (ev[0] & 0xfffc) != 0x5718:
|
||||
raise ValueError(f"EV packet magic mismatch {ev[0]:04x}")
|
||||
Ba = ev[5]
|
||||
Ph = ev[6]
|
||||
A = ev[7]<<8 | ev[9]>>8
|
||||
B = ev[8]<<8 | ev[9]&0xff
|
||||
E = ev[10] | ev[11]<<16
|
||||
if Ba & 0x8000:
|
||||
Ba -= 0x10000
|
||||
if Ph & 0x8000:
|
||||
Ph -= 0x10000
|
||||
if A & 0x800000:
|
||||
A -= 0x1000000
|
||||
if B & 0x800000:
|
||||
B -= 0x1000000
|
||||
if E & 0x80000000:
|
||||
E -= 0x100000000
|
||||
print(f"""PHA Event slice {ev[0]&3} ch {ev[4]&15}
|
||||
time: {ev[1] | ev[2]<<16}
|
||||
Δtime: {ev[3]}
|
||||
lost: {ev[4]>>4}
|
||||
A: {A/1024:.2f}
|
||||
B: {B/1024:.2f}
|
||||
banana: {Ba/0x4000:.4f}
|
||||
φ: {Ph/0x4000:.4f}
|
||||
E: {E/0x20000:.2f}
|
||||
""", file=sys.stderr)
|
||||
return ev
|
||||
|
||||
def read_samples(sl=0, n=None, sa=None):
|
||||
if not sa:
|
||||
if not n:
|
||||
n = nsamples(sl)
|
||||
sa = []
|
||||
while n:
|
||||
ff = dorn_config(0x085)
|
||||
if not (ff & (8 << (3*sl))):
|
||||
break;
|
||||
fifo_read(sl=sl, sa=True)
|
||||
sa.append(read_fifo(3))
|
||||
n -= 1
|
||||
for s in sa:
|
||||
if (s[0] & 0xfffc) != 0x5714:
|
||||
raise ValueError(f"SA magic mismatch {s[0]:04x}")
|
||||
t = s[1] | s[2]<<16
|
||||
print(f"{t} ", " ".join([f"{ss&0xfff:5d}" for ss in s[3:]]), file=sys.stderr)
|
||||
return sa
|
||||
|
||||
def make_pulser():
|
||||
global pu
|
||||
try:
|
||||
pu.ID
|
||||
except:
|
||||
import agilent3322A
|
||||
pu = agilent3322A.pulser()
|
||||
return pu
|
||||
|
||||
from usbterm import DataJob
|
||||
|
||||
class pulser_test(DataJob):
|
||||
|
||||
cadence = 600
|
||||
coffset = None
|
||||
nsamples = 16
|
||||
thres = 16
|
||||
|
||||
def __init__(self,
|
||||
amplitudes=(0.25, 0.5, 1., 2., 4., 5.),
|
||||
fn = None):
|
||||
self.filename = fn
|
||||
self.pu = make_pulser()
|
||||
super().__init__(amplitudes)
|
||||
self.connect(ifc)
|
||||
|
||||
def iniz(self):
|
||||
disable()
|
||||
self.pu.cmd("OUTPUT ON")
|
||||
self.info("agilent pulser on")
|
||||
self.next_time(10)
|
||||
if self.filename:
|
||||
ifc._data.Open()
|
||||
enable()
|
||||
|
||||
def fini(self):
|
||||
self.pu.cmd("OUTPUT OFF")
|
||||
self.info("agilent pulser off")
|
||||
if self.filename:
|
||||
ifc._data.Open()
|
||||
disable()
|
||||
|
||||
def Start(self, fn=None):
|
||||
if fn is not None:
|
||||
self.filename = fn
|
||||
self.start()
|
||||
|
||||
def func(self, a):
|
||||
if self.filename:
|
||||
ifc._data.Open()
|
||||
disable()
|
||||
pu.set_highlevel(a)
|
||||
self.info("agilent pa %.3f" % a)
|
||||
if self.filename:
|
||||
ifc._data.Open(self.filename % a)
|
||||
enable()
|
||||
Status()
|
||||
|
||||
def mem_op(addr=None, hist=None, bank=None, data=None, read=None, clear=None, base=0x88c, WH=7):
|
||||
|
||||
a = 0
|
||||
if read:
|
||||
a |= 0x8000
|
||||
if clear:
|
||||
a |= 0x4000
|
||||
|
||||
if hist is True and addr is None:
|
||||
dorn_config(base+2, False, "mem addr next histogram")
|
||||
hist = None
|
||||
|
||||
if hist is not None:
|
||||
a |= 0x2000
|
||||
if addr is not None:
|
||||
a |= addr >> WH
|
||||
else:
|
||||
a |= hist
|
||||
elif bank is not None:
|
||||
a |= 0x1000
|
||||
if addr is not None:
|
||||
a |= addr >> (WH+6)
|
||||
else:
|
||||
a |= bank
|
||||
|
||||
if a:
|
||||
dorn_config(base+3, a, "mem address and command")
|
||||
|
||||
if data is None:
|
||||
return
|
||||
|
||||
try:
|
||||
dd = data.__iter__()
|
||||
except:
|
||||
dd = (data,)
|
||||
dh = 0x10000
|
||||
for d in dd:
|
||||
h = d >> 16
|
||||
if h != dh:
|
||||
dorn_config(base+1, h, "mem data high")
|
||||
dh = h
|
||||
dorn_config(base, d & 0xffff, "mem data write")
|
||||
398
narena.py
398
narena.py
|
|
@ -5,6 +5,7 @@ from arena import *
|
|||
import math
|
||||
from time import sleep
|
||||
import arena, scangen
|
||||
from dorn import *
|
||||
|
||||
ifc,_oo = armlib.init_irena(scope = globals(), name = "NARENA", prod = 0xee02)
|
||||
arena._connect(ifc)
|
||||
|
|
@ -24,29 +25,10 @@ from lasc import SCstart, SCread
|
|||
def SCplot(sc, CDIV=6, **kk):
|
||||
osc.LASCplot(None, sc, CDIV=CDIV, **kk)
|
||||
|
||||
_verbose = True
|
||||
def dorn_config(a, v=None, m=None):
|
||||
a |= 0x800
|
||||
a &= 0xfff
|
||||
if v is None:
|
||||
if not m:
|
||||
m = f"dorn[0x{a:03x}]"
|
||||
return int(ecmd(f"alt/cmd/del[10] 0x{a:03x}", task=m, verb=_verbose).split()[-1], 0)
|
||||
if not m:
|
||||
m = f"dorn[0x{a:03x}] = 0x{v:04x}"
|
||||
if v is False:
|
||||
ecmd(f"alt/cmd/inj/del[1] 0x{a:03x}", task=m, verb=_verbose)
|
||||
else:
|
||||
ecmd(f"alt/cmd/inj/del[1] 0x{a:03x} 0x{v:04x}", task=m, verb=_verbose)
|
||||
|
||||
def thres(sl, ch, v, verb=True):
|
||||
ch |= sl<<4
|
||||
dorn_config(0x040 | ch, v)
|
||||
|
||||
def write_l2(sl, ch, i, a, b, verb=True):
|
||||
ch |= sl<<4
|
||||
dorn_config(0x400 | (ch<<3) | (i<<1) | 0, a & 0xffff)
|
||||
dorn_config(0x400 | (ch<<3) | (i<<1) | 1, b & 0xffff)
|
||||
AHEPAM_CONFIG.update({
|
||||
"dorn_addr": 0x800,
|
||||
"n_channels": 12
|
||||
})
|
||||
|
||||
l2_set6 = (
|
||||
(0, -1203, 0),
|
||||
|
|
@ -59,190 +41,6 @@ l2_set6 = (
|
|||
(7, 1125, -1888),
|
||||
)
|
||||
|
||||
l2cal = [
|
||||
[
|
||||
0.99964,
|
||||
None,
|
||||
0.99117,
|
||||
None,
|
||||
None, None, None, None,
|
||||
1.00178,
|
||||
None, None, None,
|
||||
None, None, None, None,
|
||||
],
|
||||
[], [], [],
|
||||
]
|
||||
|
||||
def calib_l2(cal, coeff=l2_set6):
|
||||
if cal is None:
|
||||
return coeff
|
||||
from numpy import array, floor, add, any
|
||||
c = array(coeff)[:,1:] * cal
|
||||
i = floor(c+0.5)
|
||||
e = add.reduce(i)
|
||||
v = e>0
|
||||
w = e<0
|
||||
while any(v) or any(w):
|
||||
d = i - c
|
||||
vv = d.argmax(axis=0)
|
||||
ww = d.argmin(axis=0)
|
||||
for x,f in enumerate(v):
|
||||
if f:
|
||||
i[vv[x],x] -= 1
|
||||
for x,f in enumerate(w):
|
||||
if f:
|
||||
i[ww[x],x] += 1
|
||||
e = add.reduce(i)
|
||||
v = e>0
|
||||
w = e<0
|
||||
return [(x, int(ii[0]), int(ii[1])) for x, ii in enumerate(i)]
|
||||
|
||||
def l2filter(coeff=l2_set6, cal=None):
|
||||
for sl in range(2):
|
||||
for ch in range(12):
|
||||
c = coeff
|
||||
if cal and cal[sl] and cal[sl][ch]:
|
||||
c = calib_l2(cal[sl][ch])
|
||||
for cc in c:
|
||||
write_l2(sl, ch, *cc)
|
||||
|
||||
def write_l3(sl, ch, *p):
|
||||
ch |= sl<<4
|
||||
scales = (14, 16, 14, 15)
|
||||
for i,pp in enumerate(p):
|
||||
if isinstance(pp, float):
|
||||
pp = int(pp * 2**scales[i])
|
||||
dorn_config(0x100 | (ch<<2) | i, pp & 0xffff)
|
||||
|
||||
def l3banana(
|
||||
# iterated F-banana 2022-03-13-aha-bi207-18,
|
||||
p0 = -4007,
|
||||
p1 = 0,
|
||||
p2 = 12737,
|
||||
p3 = -3698 ):
|
||||
for sl in range(2):
|
||||
for ch in range(12):
|
||||
write_l3(sl, ch, p0, p1, p2, p3)
|
||||
|
||||
def c16log2(A):
|
||||
return int(math.ceil(16*math.log(1024*A)/math.log(2)))
|
||||
|
||||
def enable_trigger(sl, triggers, det=False, sa=False):
|
||||
i = 2 if sa else 0 if det else 1
|
||||
dorn_config(0x008 | i | sl<<4, triggers)
|
||||
|
||||
def nsamples(sl, n=None, m=None):
|
||||
if n is None:
|
||||
return dorn_config(0x00b | sl<<4)
|
||||
if m is None:
|
||||
m = 0xfff if n else 0
|
||||
enable_trigger(sl, m, sa=True)
|
||||
dorn_config(0x00b | sl<<4, n)
|
||||
|
||||
def triggers(sl, atrig=0x3ff, dtrig=0, sam=0, nsa=32):
|
||||
enable_trigger(sl, dtrig, det=True)
|
||||
enable_trigger(sl, atrig)
|
||||
nsamples(sl, nsa, sam)
|
||||
|
||||
def hist_bins(sl, bin0=4.0, res=1, cwin=6, xtalk=6):
|
||||
"""configure dorn_l4 histogramming
|
||||
bin0: float: A-value of bin 0, int: 16LOG2(A)
|
||||
res: bin = 16×log₂(A) >> res
|
||||
cwin: anti-coincidence window [µs]
|
||||
xtalk: x-talk ratio cut: reject if S > (S>>xtalk)
|
||||
"""
|
||||
if isinstance(bin0, float):
|
||||
bin0=c16log2(bin0)
|
||||
dorn_config(0x00c | sl<<4, (xtalk<<8) | cwin)
|
||||
dorn_config(0x00d | sl<<4, (res<<9) | bin0)
|
||||
|
||||
def base_address(hists=None, counters=None, hmask=None, cmask=None):
|
||||
if hists is not None:
|
||||
if counters is None:
|
||||
counters = hists
|
||||
r = dorn_config(0x088, (counters<<3) | hists)
|
||||
else:
|
||||
if hmask is not None:
|
||||
r = dorn_config(0x088, 0x4000 | hmask)
|
||||
if cmask is not None:
|
||||
r = dorn_config(0x088, 0x8000 | cmask)
|
||||
if cmask is None and hmask is None:
|
||||
r = dorn_config(0x088, 0x8000)
|
||||
return r & 7, r >> 3
|
||||
|
||||
def fifo_status(i=None):
|
||||
e = dorn_config(0x084)
|
||||
p = dorn_config(0x085)
|
||||
f = dorn_config(0x086)
|
||||
if i is None:
|
||||
return e,p,f
|
||||
return (e>>i)&1, (p>>i)&1, (f>>i)&1
|
||||
|
||||
def fifo_select(hi=False, sl=None, hk=False, ev=False, sa=False, i=None):
|
||||
if i is not None:
|
||||
f = 1<<i
|
||||
else:
|
||||
f = (sa<<2) | (ev<<1) | hk
|
||||
if sl is not None:
|
||||
f <<= 3*sl+1
|
||||
else:
|
||||
f *= 18
|
||||
f |= hi
|
||||
return f
|
||||
|
||||
def fifo_enable(en=False, rfifo=False, sl=None, **aa):
|
||||
f = fifo_select(sl=sl, **aa)
|
||||
if sl is None and en:
|
||||
en = 3
|
||||
elif sl is not None:
|
||||
en <<= sl
|
||||
dorn_config(0x087, (f<<6) | (rfifo<<5) | en)
|
||||
|
||||
STROBES = {
|
||||
"read_fifos": 0,
|
||||
"incr": 1,
|
||||
"resync": 2,
|
||||
"clock_reset": 3,
|
||||
"hk": 4,
|
||||
"dorn_reset": 8,
|
||||
"mem_reset": 12,
|
||||
"rb_reset": 13,
|
||||
"fifo_reset": 14,
|
||||
}
|
||||
|
||||
def strobe(sl=None, **aa):
|
||||
s = 0
|
||||
for k in aa:
|
||||
if not k in STROBES:
|
||||
raise KeyError(f"No STROBE: {k}")
|
||||
if aa[k]:
|
||||
b = 1
|
||||
if k=="hk":
|
||||
if sl is None:
|
||||
b = 15;
|
||||
else:
|
||||
b <<= sl
|
||||
s |= b << STROBES[k]
|
||||
dorn_config(0x08b, s)
|
||||
|
||||
def fifo_reset(**aa):
|
||||
f = fifo_select(**aa)
|
||||
if not f:
|
||||
strobe(fifo_reset=True)
|
||||
else:
|
||||
dorn_config(0x084, f)
|
||||
|
||||
def fifo_read(**aa):
|
||||
f = fifo_select(**aa)
|
||||
if not f:
|
||||
ecmd("alt/cmd/inj 0x8800", verb=_verbose)
|
||||
else:
|
||||
dorn_config(0x085, f)
|
||||
|
||||
def degC(a, R1=10e3, R25=10e3, B25=3750, res=0x1000):
|
||||
R=R1*a/(res-(a&(res-1)))
|
||||
return B25/(math.log(R/R25)+B25/298) - 273
|
||||
|
||||
def narena_hk(sl, what="data", data=None, ND=4, NV=8, Vref=3.3):
|
||||
"""what="data", "raw", "cooked", "print" (default)"""
|
||||
if not data:
|
||||
|
|
@ -284,189 +82,3 @@ Tpa = %6.2f °C
|
|||
Vss = %6.3f V
|
||||
Vcc = %6.3f V
|
||||
""" % tuple(data[7]+data[6]))
|
||||
|
||||
def default_config(thr=0x7ff):
|
||||
for sl in range(2):
|
||||
for ch in range(12):
|
||||
thres(sl, ch, thr)
|
||||
l2filter()
|
||||
l3banana()
|
||||
for sl in range(2):
|
||||
hist_bins(sl)
|
||||
triggers(sl, 0)
|
||||
|
||||
def print_trigger_config():
|
||||
tri = [[dorn_config(0x008 + i + (sl<<4)) for i in range(4)] for sl in range(2)]
|
||||
ff = [dorn_config(0x084+i) for i in range(4)]
|
||||
tri.append(ff)
|
||||
e = ff[3]
|
||||
df = [Areg(0x11+i) for i in range(3)]
|
||||
df.append(Areg(5))
|
||||
tri.append(df)
|
||||
print(f"""narena trigger config:
|
||||
trigger detector masks:
|
||||
det triggers: 0x{tri[0][0]:x} 0x{tri[1][0]:x}
|
||||
channel triggers: 0x{tri[0][1]:03x} 0x{tri[1][1]:03x}
|
||||
sample readout triggers: 0x{tri[0][2]:03x} 0x{tri[1][2]:03x}
|
||||
number of sample records: {tri[0][3]:-5d} {tri[1][3]:-5d}
|
||||
enable: {e&1} {(e>>1)&1}
|
||||
fifos enable SA/EV/HK HI {(e>>7)&7:03b} {(e>>10)&7:03b} {(e>>6)&1}
|
||||
empty {(ff[0]>>1)&7:03b} {(ff[0]>>4)&7:03b} {ff[0]&1} {(df[3]>>9)&7:03b}
|
||||
packet {(ff[1]>>1)&7:03b} {(ff[1]>>4)&7:03b} {ff[1]&1} {(df[3]>>13)&7:03b}
|
||||
full {(ff[2]>>1)&7:03b} {(ff[2]>>4)&7:03b} {ff[2]&1} {(df[3]>>5)&7:03b}
|
||||
dig fifo status {df[2]&0x3ff} {df[1]&0x3ff} {df[0]&0x3ff}
|
||||
""", file=sys.stderr)
|
||||
return tri
|
||||
|
||||
def read_event(sl=None, ev=None):
|
||||
if ev is None:
|
||||
fifo_read(sl=sl, ev=True)
|
||||
ev = read_fifo(2)
|
||||
if (ev[0] & 0xfffc) != 0x5718:
|
||||
raise ValueError(f"EV packet magic mismatch {ev[0]:04x}")
|
||||
Ba = ev[5]
|
||||
Ph = ev[6]
|
||||
A = ev[7]<<8 | ev[9]>>8
|
||||
B = ev[8]<<8 | ev[9]&0xff
|
||||
E = ev[10] | ev[11]<<16
|
||||
if Ba & 0x8000:
|
||||
Ba -= 0x10000
|
||||
if Ph & 0x8000:
|
||||
Ph -= 0x10000
|
||||
if A & 0x800000:
|
||||
A -= 0x1000000
|
||||
if B & 0x800000:
|
||||
B -= 0x1000000
|
||||
if E & 0x80000000:
|
||||
E -= 0x100000000
|
||||
print(f"""PHA Event slice {ev[0]&3} ch {ev[4]&15}
|
||||
time: {ev[1] | ev[2]<<16}
|
||||
Δtime: {ev[3]}
|
||||
lost: {ev[4]>>4}
|
||||
A: {A/1024:.2f}
|
||||
B: {B/1024:.2f}
|
||||
banana: {Ba/0x4000:.4f}
|
||||
φ: {Ph/0x4000:.4f}
|
||||
E: {E/0x20000:.2f}
|
||||
""", file=sys.stderr)
|
||||
return ev
|
||||
|
||||
def read_samples(sl=0, n=None, sa=None):
|
||||
if not sa:
|
||||
if not n:
|
||||
n = nsamples(sl)
|
||||
sa = []
|
||||
while n:
|
||||
ff = dorn_config(0x085)
|
||||
if not (ff & (8 << (3*sl))):
|
||||
break;
|
||||
fifo_read(sl=sl, sa=True)
|
||||
sa.append(read_fifo(3))
|
||||
n -= 1
|
||||
for s in sa:
|
||||
if (s[0] & 0xfffc) != 0x5714:
|
||||
raise ValueError(f"SA magic mismatch {s[0]:04x}")
|
||||
t = s[1] | s[2]<<16
|
||||
print(f"{t} ", " ".join([f"{ss&0xfff:5d}" for ss in s[3:]]), file=sys.stderr)
|
||||
return sa
|
||||
|
||||
def make_pulser():
|
||||
global pu
|
||||
try:
|
||||
pu.ID
|
||||
except:
|
||||
import agilent3322A
|
||||
pu = agilent3322A.pulser()
|
||||
return pu
|
||||
|
||||
from usbterm import DataJob
|
||||
|
||||
class pulser_test(DataJob):
|
||||
|
||||
cadence = 600
|
||||
coffset = None
|
||||
nsamples = 16
|
||||
thres = 16
|
||||
|
||||
def __init__(self,
|
||||
amplitudes=(0.25, 0.5, 1., 2., 4., 5.),
|
||||
fn = None):
|
||||
self.filename = fn
|
||||
self.pu = make_pulser()
|
||||
super().__init__(amplitudes)
|
||||
self.connect(ifc)
|
||||
|
||||
def iniz(self):
|
||||
disable()
|
||||
self.pu.cmd("OUTPUT ON")
|
||||
self.info("agilent pulser on")
|
||||
self.next_time(10)
|
||||
if self.filename:
|
||||
ifc._data.Open()
|
||||
enable()
|
||||
|
||||
def fini(self):
|
||||
self.pu.cmd("OUTPUT OFF")
|
||||
self.info("agilent pulser off")
|
||||
if self.filename:
|
||||
ifc._data.Open()
|
||||
disable()
|
||||
|
||||
def Start(self, fn=None):
|
||||
if fn is not None:
|
||||
self.filename = fn
|
||||
self.start()
|
||||
|
||||
def func(self, a):
|
||||
if self.filename:
|
||||
ifc._data.Open()
|
||||
disable()
|
||||
pu.set_highlevel(a)
|
||||
self.info("agilent pa %.3f" % a)
|
||||
if self.filename:
|
||||
ifc._data.Open(self.filename % a)
|
||||
enable()
|
||||
Status()
|
||||
|
||||
def mem_op(addr=None, hist=None, bank=None, data=None, read=None, clear=None, base=0x88c, WH=7):
|
||||
|
||||
a = 0
|
||||
if read:
|
||||
a |= 0x8000
|
||||
if clear:
|
||||
a |= 0x4000
|
||||
|
||||
if hist is True and addr is None:
|
||||
dorn_config(base+2, False, "mem addr next histogram")
|
||||
hist = None
|
||||
|
||||
if hist is not None:
|
||||
a |= 0x2000
|
||||
if addr is not None:
|
||||
a |= addr >> WH
|
||||
else:
|
||||
a |= hist
|
||||
elif bank is not None:
|
||||
a |= 0x1000
|
||||
if addr is not None:
|
||||
a |= addr >> (WH+6)
|
||||
else:
|
||||
a |= bank
|
||||
|
||||
if a:
|
||||
dorn_config(base+3, a, "mem address and command")
|
||||
|
||||
if data is None:
|
||||
return
|
||||
|
||||
try:
|
||||
dd = data.__iter__()
|
||||
except:
|
||||
dd = (data,)
|
||||
dh = 0x10000
|
||||
for d in dd:
|
||||
h = d >> 16
|
||||
if h != dh:
|
||||
dorn_config(base+1, h, "mem data high")
|
||||
dh = h
|
||||
dorn_config(base, d & 0xffff, "mem data write")
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ while True:
|
|||
logger("connection from %s\n" % repr(s[1]))
|
||||
if len(sockets)>=10:
|
||||
logger("too many connections %s\n" % repr(sockets))
|
||||
s[0].send("too many connections, good bye\n")
|
||||
s[0].send(b"too many connections, good bye\n")
|
||||
s[0].close()
|
||||
else:
|
||||
try:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue