Compare commits

...

7 commits

Author SHA1 Message Date
Stephan I. Böttcher
90d5d885a3 Merge branch 'master' of forge.bexus.org:Stephan/irena-arm 2024-12-11 13:52:16 +01:00
ava
1d9caa689c dorn.py: add config parameter n_channels and adjust every usage of old default value
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9174 bc5caf13-1734-44f8-af43-603852e9ee25
2024-12-11 12:49:51 +00:00
ava
2eaf8f41eb narena.py: import functions from dorn.py; added AHEPAM_CONFIG.update
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9173 bc5caf13-1734-44f8-af43-603852e9ee25
2024-12-11 12:35:51 +00:00
stephan
fcfd6f72ab nmdbstream: send bytes
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9172 bc5caf13-1734-44f8-af43-603852e9ee25
2024-12-11 07:27:52 +00:00
ava
d02f716316 narena.py: functions are now stored in dorn.py and imported from there
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9171 bc5caf13-1734-44f8-af43-603852e9ee25
2024-12-09 16:08:59 +00:00
ava
354c2c5171 dorn.py: delete arena and oszilloskop
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9170 bc5caf13-1734-44f8-af43-603852e9ee25
2024-12-04 16:01:33 +00:00
stephan
93e582cbe5 narena: start adaption to nmahepam
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9169 bc5caf13-1734-44f8-af43-603852e9ee25
2024-12-04 15:24:23 +00:00
3 changed files with 458 additions and 394 deletions

452
dorn.py Executable file
View 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
View file

@ -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")

View file

@ -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: