Compare commits
No commits in common. "8179bdb629c8709c273a2660edb8e1770eb9cfac" and "c52d619bb74d1dfdbfee9b5bb7c7f5bcbc7a61a5" have entirely different histories.
8179bdb629
...
c52d619bb7
2 changed files with 6 additions and 643 deletions
611
src/dorn.py
611
src/dorn.py
|
|
@ -1,611 +0,0 @@
|
|||
import math, time, sys
|
||||
|
||||
def _connect(ifc):
|
||||
global _ifc, acmd, rfifo
|
||||
_ifc = ifc
|
||||
acmd = ifc.acmd
|
||||
rfifo = ifc.rfifo
|
||||
|
||||
def degCβ(a, R1=10e3, R25=10e3, B25=3940, res=0x1000):
|
||||
if not a:
|
||||
a = 1
|
||||
R = R1 * a / (res - (a & (res-1)))
|
||||
T = B25/(math.log(R/R25) + B25/298) - 273
|
||||
return T
|
||||
|
||||
def degC(a, idx=0):
|
||||
return degCβ(a, **CONFIG.NTC[idx])
|
||||
|
||||
def HK_fmt(s, i, n, d):
|
||||
return f"{i}. {n}: {repr(d)}\n"
|
||||
|
||||
def HK3_fmt(s, i, n, d):
|
||||
return f"""{i}. {n}
|
||||
T = {d[5]:6.2f} °C, GND = {d[0]:6.3f} V,
|
||||
Vff = {d[1]:6.3f} V, Vnn = {d[2]:6.3f} V, Vpp = {d[3]:6.3f} V, Vdig = {d[4]:6.3f} V,
|
||||
Vcc = {d[6]:6.3f} V, Vss = {d[7]:6.3f} V.
|
||||
"""
|
||||
def HK4_AHBGO_fmt(s, i, n, d):
|
||||
return f"""{i}. {n}
|
||||
Tbgo = {d[0]:6.2f} °C, {d[1]:6.2f} °C, {d[3]:6.2f} °C,
|
||||
Vbias = {d[2]:6.3f} V, Ibias = {d[4]:6.1f} nA, {d[5]:6.1f} nA,
|
||||
Vcc = {d[7]:6.3f} V, Vss = {d[6]:6.3f} V.
|
||||
"""
|
||||
def HK4_SETH_fmt(s, i, n, d):
|
||||
return f"""{i}. {n}
|
||||
Tpa = {d[4]:6.2f} °C, Tbgo = {d[3]:6.2f} °C, {d[5]:6.2f} °C,
|
||||
Vbias = {d[2]:6.3f} V, Ibias = {d[1]:6.1f} nA, {d[0]:6.1f} nA,
|
||||
Vcc = {d[7]:6.3f} V, Vss = {d[6]:6.3f} V.
|
||||
"""
|
||||
def HK7_SETH_fmt(s, i, n, d):
|
||||
if s==0:
|
||||
return f"""{i}. {n}
|
||||
na = {repr(d[:4])}
|
||||
Tpwr = {d[6]:.1f} °C,
|
||||
Vprim = {d[5]:.1f} V, Iprim = {d[4]:.1f} mA,
|
||||
Ibias⁺ = {d[7]:.1f} nA.
|
||||
"""
|
||||
return f"""{i}. {n}
|
||||
na = {repr(d[:4])}
|
||||
Text = {d[6]:.1f} °C,
|
||||
Ibias = {d[4]:.1f} nA,
|
||||
Ibias⁺ = {d[7]:.1f} nA, Vbias⁺ = {d[5]:.1f} V.
|
||||
"""
|
||||
def HK3_LEIA_fmt(s, i, n, d):
|
||||
return f"""{i}. {n}
|
||||
Tadc = {d[0]:6.2f} °C,
|
||||
Vadc = {d[1]:6.3f} V,
|
||||
VbiasD = {d[7]:6.2f} V,
|
||||
Vbias2 = {d[6]:6.1f} V,
|
||||
Vpp = {d[3]:6.3f} V, Vnn = {d[2]:6.3f} V,
|
||||
Vcc = {d[5]:6.3f} V, Vss = {d[4]:6.3f} V.
|
||||
"""
|
||||
def HK4_LEIA_fmt(s, i, n, d):
|
||||
return f"""{i}. {n}
|
||||
Ibias1 = {d[3]:.1f} nA, Ibias2 = {d[2]:.1f} nA, IbiasD = {d[0]:.1f} nA,
|
||||
VbiasG = {d[1]:.1f} V, Vbias1 = {d[4]:.1f} V,
|
||||
Tpa0 = {d[5]:6.2f} °C, Tpa1= {d[6]:6.2f} °C, Tpa2 = {d[7]:6.2f} °C.
|
||||
"""
|
||||
|
||||
class DORN_CONFIG:
|
||||
# stis_ana_core 2×24 ch
|
||||
dorn_addr = 0x2000
|
||||
verbose = True
|
||||
slices = (0,1)
|
||||
n_channels = 24
|
||||
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),
|
||||
)
|
||||
|
||||
HK3 = [[
|
||||
("GND",),
|
||||
("Vff", 2.0),
|
||||
("Vnn", 2.5, ("Vpp", -1.5)),
|
||||
("Vpp", 2.0),
|
||||
("Vdig", 2.0),
|
||||
("Tadc", (degC, {})),
|
||||
("Vcc", 2.0),
|
||||
("Vss", 2.5, ("Vcc", -1.5)),
|
||||
]]
|
||||
|
||||
HK = [
|
||||
("INP₀", None, HK_fmt),
|
||||
("INP₁", None, HK_fmt),
|
||||
("INP₂", None, HK_fmt),
|
||||
("HK ADC", HK3, HK3_fmt),
|
||||
("HK PA", None, HK_fmt),
|
||||
("VrefL", None, HK_fmt),
|
||||
("VrefH", None, HK_fmt),
|
||||
("HK_PWR", None, HK_fmt),
|
||||
]
|
||||
|
||||
def n_adc(self):
|
||||
return self.n_channels//3
|
||||
|
||||
def Vref(self, slice=None):
|
||||
try:
|
||||
return self.VREF[slice]
|
||||
except:
|
||||
pass
|
||||
return 3.3
|
||||
|
||||
def n_trigs(self):
|
||||
if self.n_channels > 16:
|
||||
return self.n_adc()
|
||||
return self.n_channels
|
||||
|
||||
def m_trigs(self):
|
||||
return (1 << self.n_trigs()) - 1
|
||||
|
||||
NTC = [dict(R1=10e3, R25=10e3, B25=3940, res=0x1000)]
|
||||
|
||||
HK4_SETH = [
|
||||
[
|
||||
("Ibias₂", 10470/470 * 51/1051 * 100, -97),
|
||||
("Ibias₁", 10470/470 * 51/1051 * 100, -135),
|
||||
("Vbias", -1/0.047),
|
||||
("Tbgo₁", (degC, {})),
|
||||
("Tpa", (degC, {})),
|
||||
("Tbgo₂", (degC, {})),
|
||||
("Vss", 2.5, ("Vcc", -1.5)),
|
||||
("Vcc", 2.0),
|
||||
],
|
||||
[
|
||||
("Ibias₂", 10470/470 * 51/1051 * 100, -98),
|
||||
("Ibias₁", 10470/470 * 51/1051 * 100, -112),
|
||||
("Vbias", -1/0.047, 2.0),
|
||||
("Tbgo₁", (degC, {})),
|
||||
("Tpa", (degC, {})),
|
||||
("Tbgo₂", (degC, {})),
|
||||
("Vss", 2.5, ("Vcc", -1.5)),
|
||||
("Vcc", 2.0),
|
||||
],
|
||||
]
|
||||
|
||||
HK7_SETH = [
|
||||
[
|
||||
("na₁",), ("na₂",), ("na₃",), ("na₄",),
|
||||
("Iprim", 2000.0),
|
||||
("Vprim", 16.3),
|
||||
("Tpwr", (degC, {})),
|
||||
("Ibias⁺", 100.0),
|
||||
],
|
||||
[
|
||||
("na₁",), ("na₂",), ("na₃",), ("na₄",),
|
||||
("Ibias", 100.0),
|
||||
("Vbias⁺", 100.0),
|
||||
("Text", (degC, {})),
|
||||
("Ibias⁺", 100.0),
|
||||
],
|
||||
]
|
||||
|
||||
def seth(self):
|
||||
# ! change the class attribute .HK
|
||||
self.HK[4] = ("HK PA", self.HK4_SETH, HK4_SETH_fmt)
|
||||
self.HK[7] = ("HK_PWR", self.HK7_SETH, HK7_SETH_fmt)
|
||||
self.BGO = [(0,3), (0,12), (0,20), (1,3), (1,12), (1,20)]
|
||||
|
||||
HK4_AHBGO = [[
|
||||
("Tbgo₁", (degC, {})),
|
||||
("Tbgo₂", (degC, {})),
|
||||
("Vbias1", -1/0.047),
|
||||
("Tbgo₃", (degC, {})),
|
||||
("Ibias₁", 10470/470 * 51/1051 * 100),
|
||||
("Ibias₂", 10470/470 * 51/1051 * 100),
|
||||
("Vss", 2.5, ("Vcc", -1.5)),
|
||||
("Vcc", 2.0),
|
||||
]]
|
||||
|
||||
def ahbgo(self):
|
||||
# ! change the class attribute .HK
|
||||
self.HK[4] = ("HK PA", self.HK4_AHBGO, HK4_AHBGO_fmt)
|
||||
|
||||
# calib 2025-11-25
|
||||
Fluke_cal = 1/0.862
|
||||
# SN2 dac, 14*HK3H, VbiasD
|
||||
VbiasD_SN2 = [
|
||||
[ 64, 0.51, 0.5 * Fluke_cal ],
|
||||
[ 960, 1.85, 1.6 * Fluke_cal ],
|
||||
[ 1984, 3.36, 2.9 * Fluke_cal ],
|
||||
[ 4992, 7.85, 6.7 * Fluke_cal ],
|
||||
[ 9984, 15.27, 13.1 * Fluke_cal ],
|
||||
[ 14976, 22.56, 19.3 * Fluke_cal ],
|
||||
[ 19968, 29.91, 25.6 * Fluke_cal ],
|
||||
[ 20992, 31.42, 26.9 * Fluke_cal ],
|
||||
[ 21440, 32.06, 27.5 * Fluke_cal ],
|
||||
[ 21952, 32.83, 28.0 * Fluke_cal ],
|
||||
[ 24960, 37.36, 28.6 * Fluke_cal ],
|
||||
]
|
||||
VbiasD_a = 0.033
|
||||
VbiasD_b = 0.9918
|
||||
|
||||
HK3_LEIA = [[
|
||||
("Tadc", (degC, {})),
|
||||
("Vadc", 2.0),
|
||||
("Vnn", 2.5, ("Vpp", -1.5)),
|
||||
("Vpp", 2.0),
|
||||
("Vss", 2.5, ("Vcc", -1.5)),
|
||||
("Vcc", 2.0),
|
||||
("Vbias2", -1/0.022 * 66.6/75.2),
|
||||
("VbiasD", -14 * VbiasD_b - VbiasD_a),
|
||||
]]
|
||||
|
||||
HK4_LEIA = [[
|
||||
("IbiasD", 100., -1.4),
|
||||
("VbiasG", 46.3, ("Vref", -45.3)),
|
||||
("Ibias2", 10470/470 * 51/1051 * 100, -71.0),
|
||||
("Ibias1", 10470/470 * 51/1051 * 100, -52.0),
|
||||
("Vbias1", -1/0.047 * 44.7/48.5),
|
||||
("Tpa0", (degC, {})),
|
||||
("Tpa1", (degC, {})),
|
||||
("Tpa2", (degC, {})),
|
||||
]]
|
||||
|
||||
def leia(self):
|
||||
self.VREF = (3.342,)
|
||||
self.slices=(0,)
|
||||
self.HK[3] = ("HK_AD", self.HK3_LEIA, HK3_LEIA_fmt)
|
||||
self.HK[4] = ("HK_PA", self.HK4_LEIA, HK4_LEIA_fmt)
|
||||
|
||||
def thhor(self):
|
||||
self.slices=(0,)
|
||||
self.n_channels = 12
|
||||
self.NTC = [dict(R1=22e3, R25=10e3, B25=3940, res=0x1000)]
|
||||
|
||||
CONFIG = DORN_CONFIG()
|
||||
|
||||
def hk(sl=0, what="print", data=None):
|
||||
if not data:
|
||||
_ifc.menable()
|
||||
fifo_enable(en=True, sl=sl, hk=True)
|
||||
fifo_reset(sl=sl, hk=True)
|
||||
strobe(sl=sl, hk=True)
|
||||
time.sleep(0.1)
|
||||
fifo_read(sl=sl, hk=True)
|
||||
data=rfifo()
|
||||
if data[0] != 0x5710 + sl:
|
||||
raise ValueError("Read HK packet error", data)
|
||||
if isinstance(data, str):
|
||||
# HDORN … data line
|
||||
if "x" in data:
|
||||
return sl, None
|
||||
data = data.split()
|
||||
if data[0] != "HDORN":
|
||||
return sl, None
|
||||
data = list(map(int, data[1:]))
|
||||
if sl is None:
|
||||
sl = data[0] & 3;
|
||||
if data[0] & 3 != sl:
|
||||
return sl, None
|
||||
if what=="data":
|
||||
return sl, data
|
||||
ND = CONFIG.n_adc()
|
||||
NV = ND
|
||||
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 sl, data
|
||||
Vref = CONFIG.Vref(sl)/4096
|
||||
ddata = []
|
||||
VV = {"Vref": CONFIG.Vref(sl)}
|
||||
for a in range(8):
|
||||
V = {}
|
||||
ddata.append(V)
|
||||
HK = CONFIG.HK[a][1]
|
||||
# cookbook:
|
||||
# None
|
||||
# (name, factor, offset)
|
||||
# (name, factor, (offset_name, factor))
|
||||
# (name, (func, {args}))
|
||||
if not HK:
|
||||
V.update({c:data[a][c] for c in range(8)})
|
||||
continue
|
||||
HK = HK[sl % len(HK)]
|
||||
for c in range(8):
|
||||
H = HK[c]
|
||||
if len(H) > 1:
|
||||
if isinstance(H[1], tuple):
|
||||
data[a][c] = H[1][0](data[a][c], **H[1][1])
|
||||
else:
|
||||
data[a][c] *= Vref*H[1]
|
||||
V[H[0]] = data[a][c]
|
||||
VV.update(V)
|
||||
for c in range(8):
|
||||
H = HK[c]
|
||||
if len(H) > 2:
|
||||
if isinstance(H[2], tuple):
|
||||
data[a][c] += VV[H[2][0]] * H[2][1]
|
||||
else:
|
||||
data[a][c] += H[2]
|
||||
V[H[0]] = data[a][c]
|
||||
|
||||
if what=="cooked":
|
||||
return sl, data
|
||||
if what=="dict":
|
||||
return sl, ddata
|
||||
|
||||
r = []
|
||||
for a in range(8):
|
||||
H=CONFIG.HK[a]
|
||||
# (name, [cookbooks], fmt_function)
|
||||
r.append(H[2](sl, a, H[0], data[a]))
|
||||
|
||||
if what=="print":
|
||||
sys.stderr.write("".join(r))
|
||||
return sl, r
|
||||
|
||||
def dorn_config(a, v=None, mes=None, slice=0):
|
||||
verb = CONFIG.verbose
|
||||
a |= CONFIG.dorn_addr | (slice<<11)
|
||||
if v is None:
|
||||
if not mes:
|
||||
mes = f"dorn[0x{a:03x}]"
|
||||
return acmd(a, task=mes, verb=verb)
|
||||
if not mes:
|
||||
mes = f"dorn[0x{a:03x}] = 0x{v:04x}"
|
||||
if v is False:
|
||||
acmd(a, task=mes, verb=verb)
|
||||
else:
|
||||
acmd(a, v, task=mes, 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<<4) | (i<<1) | 0, a & 0xffff, slice=sl)
|
||||
dorn_config(0x400 | (ch<<4) | (i<<1) | 1, b & 0xffff, slice=sl)
|
||||
|
||||
def calib_l2(cal, coeff):
|
||||
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=None, cal=None):
|
||||
if coeff==None:
|
||||
coeff = CONFIG.l2
|
||||
for sl in CONFIG.slices:
|
||||
for ch in range(CONFIG.n_channels):
|
||||
c = coeff
|
||||
if cal and cal[sl] and cal[sl][ch]:
|
||||
c = calib_l2(cal[sl][ch], c)
|
||||
for cc in c:
|
||||
write_l2(sl, ch, *cc)
|
||||
|
||||
def write_l3(sl, ch, *p):
|
||||
scales = (14, 14, 15, 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(
|
||||
# 2025-02-20-seth-pa1-4
|
||||
p0 = -3839,
|
||||
p2 = 13891,
|
||||
p3 = 3579,
|
||||
p4 = 22853 ):
|
||||
for sl in CONFIG.slices:
|
||||
for ch in range(CONFIG.n_channels):
|
||||
write_l3(sl, ch, p0, p2, p3, p4)
|
||||
|
||||
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, triggers, slice=sl)
|
||||
|
||||
def nsamples(sl, n=None, m=None):
|
||||
if n is None:
|
||||
return dorn_config(0x00b, slice=sl)
|
||||
if m is None:
|
||||
m = 0xffff if n else 0
|
||||
enable_trigger(sl, m, sa=True)
|
||||
dorn_config(0x00b, n, slice=sl)
|
||||
|
||||
def triggers(sl, atrig=0xffff, dtrig=0, sam=0, nsa=10):
|
||||
enable_trigger(sl, dtrig, det=True)
|
||||
enable_trigger(sl, atrig)
|
||||
nsamples(sl, nsa, sam)
|
||||
|
||||
def atriggers(sl, atrig=0, gtrig=0, csa=False, gsa=False, nsa=10):
|
||||
dorn_config(0x008, slice=sl, v=atrig & 0xffff, mes="atrig[15:0]")
|
||||
dorn_config(0x009, slice=sl, v=(atrig>>16)|((gtrig&0xff)<<8), mes="gtrig[7:0],atrig[23:8]")
|
||||
dorn_config(0x00a, slice=sl, v=gtrig>>8, mes="gtrig[23:8]")
|
||||
dorn_config(0x00b, slice=sl, v=(gsa<<9)|(csa<<8)|nsa, mes="nsamples")
|
||||
|
||||
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, (xtalk<<8) | cwin, slice=sl)
|
||||
dorn_config(0x00d, (res<<9) | bin0, slice=sl)
|
||||
|
||||
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 *= 0b0010010010010
|
||||
f |= hi
|
||||
return f
|
||||
|
||||
def fifo_enable(en=True, rfifo=True, men=True, sl=None, **aa):
|
||||
f = fifo_select(sl=sl, **aa)
|
||||
if sl is None and en is True:
|
||||
en = 0xf
|
||||
elif sl is not None:
|
||||
en <<= sl
|
||||
dorn_config(0x087, (f<<6) | (rfifo<<5) | (men<<4) | 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:
|
||||
acmd(0x8800, verb=_verbose)
|
||||
else:
|
||||
dorn_config(0x085, f)
|
||||
|
||||
def default_config(thr=0x7ff):
|
||||
for sl in CONFIG.slices:
|
||||
for ch in range(CONFIG.n_channels):
|
||||
thres(sl, ch, thr)
|
||||
l2filter()
|
||||
l3banana()
|
||||
for sl in CONFIG.slices:
|
||||
atriggers(sl)
|
||||
|
||||
def print_trigger_config():
|
||||
tri = [[dorn_config(0x008 + i, slice=sl)
|
||||
for i in range(4)]
|
||||
for sl in CONFIG.slices]
|
||||
ff = [dorn_config(0x084+i) for i in range(4)]
|
||||
tri.append(ff)
|
||||
e = ff[3]
|
||||
df = [_ifc.Areg(0x11+i) for i in range(3)]
|
||||
df.append(_ifc.Areg(5))
|
||||
tri.append(df)
|
||||
ct0 = tri[0][0] | (tri[0][1]<<16) & 0xff0000
|
||||
ct1 = tri[1][0] | (tri[1][1]<<16) & 0xff0000
|
||||
gt0 = (tri[0][2]<<8) | (tri[0][1]>>8)
|
||||
gt1 = (tri[1][2]<<8) | (tri[1][1]>>8)
|
||||
ns0 = tri[0][3] & 0xff
|
||||
ns1 = tri[1][3] & 0xff
|
||||
se0 = tri[0][3] >> 8
|
||||
se1 = tri[1][3] >> 8
|
||||
print(f"""narena trigger config:
|
||||
trigger detector masks:
|
||||
ctriggers: 0x{ct0:06x} 0x{ct1:06x}
|
||||
gtriggers: 0x{gt0:06x} 0x{gt1:06x}
|
||||
nsamples: {ns0:-6d} {ns1}
|
||||
samples enable: {se0:-6d} {se1}
|
||||
enable: {e&1:-6d} {(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 = _ifc._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(rfifo(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
|
||||
|
||||
38
src/dose.py
38
src/dose.py
|
|
@ -1,4 +1,4 @@
|
|||
#! /usr/bin/ipython3 --profile=thhor
|
||||
#! /usr/bin/ipython3 --profile=turbo_dose
|
||||
|
||||
import sys, time, getopt, fileinput, struct
|
||||
import uart
|
||||
|
|
@ -452,11 +452,9 @@ class dose_cmd(uart.uart):
|
|||
"HKSZ": 0x0018,
|
||||
"HKMA": 0x0019,
|
||||
"HKHV": 0x001a,
|
||||
|
||||
"BATE": 0x037f,
|
||||
}
|
||||
|
||||
def icmd(self, c, p=None, r=2, flgs=0, mes=None):
|
||||
def icmd(self, c, p=None, r=2, flgs=0):
|
||||
if c in self.AADDR:
|
||||
c = self.AADDR[c]+flgs
|
||||
w = [c | 0x8000]
|
||||
|
|
@ -467,23 +465,10 @@ class dose_cmd(uart.uart):
|
|||
w.extend([0x8001]*(r-1))
|
||||
w.append(0)
|
||||
d = struct.pack(f">{len(w)}H", *w)
|
||||
if self._verbose:
|
||||
if mes:
|
||||
mes = f"[{mes}]"
|
||||
else:
|
||||
mes = ""
|
||||
print(f"icmd{mes} → {[f"{ww:04x}" for ww in w]}")
|
||||
print(f"icmd → {[f"{ww:04x}" for ww in w]}")
|
||||
d = self.fpga_cmd(d)
|
||||
r = struct.unpack(f">{len(w)+1}H", d[:2*len(w)+2])
|
||||
if self._verbose:
|
||||
print(f" {mes} ← {[f"{rr:04x}" for rr in r]}", file=sys.stderr)
|
||||
return r
|
||||
|
||||
def acmd(self, c, v=None, task=None, verb=True):
|
||||
_v = self._verbose
|
||||
self._verbose = _v
|
||||
r = self.icmd(c, v, mes=task)[-1]
|
||||
self._verbose = _v
|
||||
print(f" ← {[f"{rr:04x}" for rr in r]}", file=sys.stderr)
|
||||
return r
|
||||
|
||||
def rfifo(self, fifo=1, n=None):
|
||||
|
|
@ -508,9 +493,9 @@ class dose_cmd(uart.uart):
|
|||
print(f"FIFO[{fifo}] ← {[f"{rr:04x}" for rr in r]}", file=sys.stderr)
|
||||
return r
|
||||
|
||||
def pressure(self, data=None, cmd="BATE", fifo=1):
|
||||
def pressure(self, data=None, cmd=0x037f, fifo=1):
|
||||
if data is None:
|
||||
self.icmd(cmd, mes="bate")
|
||||
self.icmd(cmd)
|
||||
time.sleep(0.2)
|
||||
data = self.rfifo(fifo)
|
||||
import pressure
|
||||
|
|
@ -520,13 +505,6 @@ class dose_cmd(uart.uart):
|
|||
print(f"bate reading {p=:.2f} mbar, {T=:.2f} °C", file=sys.stderr)
|
||||
return p, T, data
|
||||
|
||||
def menable(self, on=True, what=0x0001):
|
||||
if on:
|
||||
self.icmd("MCONF_SET", what)
|
||||
else:
|
||||
self.icmd("MCONF_CLR", what)
|
||||
|
||||
|
||||
def flags2int(FLAGS, flags):
|
||||
r = 0
|
||||
if isinstance(flags, int):
|
||||
|
|
@ -551,10 +529,6 @@ if tty:
|
|||
tty = dose_cmd(tty, baud)
|
||||
tty._export(globals())
|
||||
tty._verbose = False
|
||||
import dorn
|
||||
from dorn import *
|
||||
dorn._connect(tty)
|
||||
dorn.CONFIG.thhor()
|
||||
|
||||
uart.set_prompt("GRETEL")
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue