Compare commits

...

6 commits

Author SHA1 Message Date
Stephan I. Böttcher
31e5155586 dorn hk(): config for SETH
HK() learns about SETH inputs.
hk() moves to `dorn.py`.
`dorn.CONFIG` learns about hk() channel calibration and formats.
`--seth` comandline option, CONFIG.seth() to select SETH configuration.
2025-06-02 20:58:45 +02:00
Stephan I. Böttcher
8b4b125637 .gitignore ahepam/seth/ 2025-06-02 20:57:14 +02:00
Stephan I. Böttcher
2eb78585ab SETH CRONFLY: var W for eth cmd timeout 2025-06-02 20:53:34 +02:00
Stephan I. Böttcher
fdf7110741 NMAHEPAM INIT: sleep to wait for USB 2025-06-02 20:52:30 +02:00
Stephan I. Böttcher
ca5a803293 armlib: .hk2degC(), NTC() 2025-06-02 20:51:20 +02:00
Stephan I. Böttcher
756e1c9fbd nmahepam_channels: SETH HK[7] 2025-06-02 20:50:22 +02:00
8 changed files with 248 additions and 108 deletions

1
.gitignore vendored
View file

@ -18,3 +18,4 @@ ahepamfile
nm64file nm64file
mustang_scripts mustang_scripts
nm64/nm64 nm64/nm64
ahepam/seth

View file

@ -8,8 +8,8 @@
4 SETH | monitor | Bias2 | Bias1 | VBias | NTC,E | NTC | NTC,R | Vss | Vcc | 4 SETH | monitor | Bias2 | Bias1 | VBias | NTC,E | NTC | NTC,R | Vss | Vcc |
5 | VrefL | VrefL | VrefL | VrefL | VrefL | VrefL | VrefL | VrefL | VrefL | 5 | VrefL | VrefL | VrefL | VrefL | VrefL | VrefL | VrefL | VrefL | VrefL |
6 | Vref | Vref | Vref | Vref | Vref | Vref | Vref | Vref | Vref | 6 | Vref | Vref | Vref | Vref | Vref | Vref | Vref | Vref | Vref |
7 SETH #1 | mon[A-H] | - | - | - | - | | | NTC | Ibias+| 7 SETH #1 | mon[A-H] | - | - | - | - | Iprim | Vprim | NTC,p | Ibias+|
7 SETH #2 | mon[A-H] | - | - | - | - | | | NTC | Ibias+| 7 SETH #2 | mon[A-H] | - | - | - | - | Ibias-| Vbias+| NTC,i | Ibias+|
connector | channel (PIN) | shaper | CONN1 | ADC | data | dorn connector | channel (PIN) | shaper | CONN1 | ADC | data | dorn
----------------------------------------------------------------- -----------------------------------------------------------------
@ -40,23 +40,22 @@ connector | channel (PIN) | shaper | CONN1 | ADC | data | dorn
CONN12 | 7 (7) | 22 | 46 | H2 | [0][7] | 7 CONN12 | 7 (7) | 22 | 46 | H2 | [0][7] | 7
CONN12 | 8 (6) | 23 | 6 | H1 | [1][7] | 15 CONN12 | 8 (6) | 23 | 6 | H1 | [1][7] | 15
SETH slice | HK | connector | SETH |
----------------------------------
slice | HK | connector | 0 | A7 | CONN2.14 | - |
--------------------------------- 0 | B7 | CONN2.15 | - |
0 | A7 | CONN2.14 | - 0 | C7 | CONN2.16 | - |
0 | B7 | CONN2.15 | - 0 | D7 | CONN2.17 | - |
0 | C7 | CONN2.16 | - 0 | E7 | CONN3.2 | Iprim |
0 | D7 | CONN2.17 | - 0 | F7 | CONN3.1 | Vprim |
0 | E7 | CONN3.2 | 0 | G7 | CONN3.14 | NTC Pwr |
0 | F7 | CONN3.1 | 0 | H7 | CONN3.15 | IBias+ |
0 | G7 | CONN3.14 | NTC ----------------------------------
0 | H7 | CONN3.15 | IBias+ 1 | A7 | CONN2.14 | - |
1 | A7 | CONN2.14 | - 1 | B7 | CONN2.15 | - |
1 | B7 | CONN2.15 | - 1 | C7 | CONN2.16 | - |
1 | C7 | CONN2.16 | - 1 | D7 | CONN2.17 | - |
1 | D7 | CONN2.17 | - 1 | E7 | CONN3.2 | Ibias- |
1 | E7 | CONN3.2 | 1 | F7 | CONN3.1 | Vbias+ |
1 | F7 | CONN3.1 | 1 | G7 | CONN3.14 | NTC ext |
1 | G7 | CONN3.14 | NTC 1 | H7 | CONN3.15 | IBias+ |
1 | H7 | CONN3.15 | IBias+

View file

@ -377,6 +377,10 @@ class irena_ifc(object):
r = self.cmd("var/print "+ch).split()[1] r = self.cmd("var/print "+ch).split()[1]
return self.Vref*(int(r)&0xffff)/0x10000; return self.Vref*(int(r)&0xffff)/0x10000;
def hk2degC(self, ch, r=1.0, β=3940):
a = int(self.cmd("var/print "+ch).split()[1]) & 0xffff
return NTC(a, r=r, β=β)
def housekeeping(self): def housekeeping(self):
self._log("dac %6.1f mV\n" % self.hk2mvolt("dac")) self._log("dac %6.1f mV\n" % self.hk2mvolt("dac"))
self._log("Ibias %6.1f mV\n" % self.hk2mvolt("adc_Ibias")) self._log("Ibias %6.1f mV\n" % self.hk2mvolt("adc_Ibias"))
@ -691,6 +695,14 @@ def float2int(f, e=4, m=12, s=False):
mm = -mm mm = -mm
return mm return mm
def NTC(a, r=1, β=4000, b=0x10000):
"""Temp [°C] from ADC reading `a`
`b`: ADC range (max+1)
`r`: R₁/R₂₅
`β`: slope [K]
"""
from math import log
return β / (log(r*a/(b-a)) + β/298.0) - 273;
def irena_exit(status=0): def irena_exit(status=0):
try: try:

208
dorn.py
View file

@ -5,6 +5,52 @@ def _connect(ifc):
_ifc = ifc _ifc = ifc
ecmd = ifc.ecmd ecmd = ifc.ecmd
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" Ibias = {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.
"""
class DORN_CONFIG: class DORN_CONFIG:
# stis_ana_core 2×24 ch # stis_ana_core 2×24 ch
dorn_addr = 0x2000 dorn_addr = 0x2000
@ -21,6 +67,86 @@ class DORN_CONFIG:
(6, 2000, -1082), (6, 2000, -1082),
(7, 1125, -1888), (7, 1125, -1888),
) )
HK3 = [[
("Ibias", 10470/470 * 51/1051 * 100),
("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)),
]]
HK4_AHBGO = [[
("Tbgo₁", (degC, {})),
("Tbgo₂", (degC, {})),
("Vbias", -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),
]]
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),
],
]
HK = [
("INP₀", None, HK_fmt),
("INP₁", None, HK_fmt),
("INP₂", None, HK_fmt),
("HK ADC", HK3, HK3_fmt),
("HK PA", HK4_AHBGO, HK4_AHBGO_fmt),
("VrefL", None, HK_fmt),
("VrefH", None, HK_fmt),
("HK_PWR", None, HK_fmt),
]
def n_adc(self): def n_adc(self):
return self.n_channels//3 return self.n_channels//3
@ -41,8 +167,80 @@ class DORN_CONFIG:
NTC = [dict(R1=10e3, R25=10e3, B25=3940, res=0x1000)] NTC = [dict(R1=10e3, R25=10e3, B25=3940, res=0x1000)]
def seth(self):
# ! change the class attribute
self.HK[4] = ("HK PA", self.HK4_SETH, HK4_SETH_fmt)
self.HK[7] = ("HK_PWR", self.HK7_SETH, HK7_SETH_fmt)
CONFIG = DORN_CONFIG() CONFIG = DORN_CONFIG()
def hk(sl, what="print", data=None):
if not data:
ecmd("alt/stream/off")
_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=_ifc.read_fifo()
if data[0] != 0x5710 + sl:
raise ValueError("Read HK packet error", data)
if what=="data":
return 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 data
Vref = CONFIG.Vref(sl)/4096
ddata = []
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]
for c in range(8):
H = HK[c]
if len(H) > 2:
if isinstance(H[2], tuple):
data[a][c] += V[H[2][0]] * H[2][1]
else:
data[a][c] += H[2]
V[H[0]] = data[a][c]
if what=="cooked":
return data
if what=="dict":
return 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 r
def dorn_config(a, v=None, mes=None, slice=0): def dorn_config(a, v=None, mes=None, slice=0):
verb = CONFIG.verbose verb = CONFIG.verbose
a |= CONFIG.dorn_addr | (slice<<11) a |= CONFIG.dorn_addr | (slice<<11)
@ -237,16 +435,6 @@ def fifo_read(**aa):
else: else:
dorn_config(0x085, f) dorn_config(0x085, f)
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 default_config(thr=0x7ff): def default_config(thr=0x7ff):
for sl in CONFIG.slices: for sl in CONFIG.slices:
for ch in range(CONFIG.n_channels): for ch in range(CONFIG.n_channels):

View file

@ -13,7 +13,7 @@ dorn/fifo/strobe/inj 0x30
@s/if ! udp_rx_cmd: var udp_size=0 @s/if ! udp_rx_cmd: var udp_size=0
@s/if udp_rx_cmd > U: var V=time @s/if udp_rx_cmd > U: var V=time
@var U=udp_rx_cmd @var U=udp_rx_cmd
@s/if V+600 < time: var udp_size=0 @s/if V+W < time: var udp_size=0
@s/if enc == 0xb: eth/rx/en @s/if enc == 0xb: eth/rx/en
@s/if enc != 0xf: var udp_size=0 @s/if enc != 0xf: var udp_size=0
@s/if udp_size: s/exit @s/if udp_size: s/exit

View file

@ -8,5 +8,6 @@ altera/file "NMAHEPAM.RBF"
@s/if errno>=500: s/exit @s/if errno>=500: s/exit
@e/eval "s/exe 'SN%d.RC'", serial @e/eval "s/exe 'SN%d.RC'", serial
@s/exe "DORN.RC" @s/exe "DORN.RC"
@sleep 10
@s/if usb: s/exit @s/if usb: s/exit
@s/if F>4: s/exe "MEASURE.RC" @s/if F>4: s/exe "MEASURE.RC"

View file

@ -9,6 +9,7 @@ var/set spi_min_qtime = 665
@v/set sd_write_count = 0 @v/set sd_write_count = 0
@v/set udp_count = 0 @v/set udp_count = 0
@v/set udp_size = 0 @v/set udp_size = 0
@V W=600
@v/set R=-1 @v/set R=-1
@script/cron/none @script/cron/none
@var/cache ssp_dma spy_return second time hk_count hk_mes @var/cache ssp_dma spy_return second time hk_count hk_mes

View file

@ -11,9 +11,13 @@ def HK():
Vprim = hk2mvolt("adc_Vprim")*(0.011) Vprim = hk2mvolt("adc_Vprim")*(0.011)
Vbias = hk2mvolt("adc_Vbias")*(-0.05) Vbias = hk2mvolt("adc_Vbias")*(-0.05)
Ibias = hk2mvolt("adc_Ibias")*0.0955 Ibias = hk2mvolt("adc_Ibias")*0.0955
r = (Vcc, Vss, Icc, Iss, Vprim, Vbias, Ibias) Ibiasp = hk2mvolt("adc_dac")*0.0955
print("Vcc:%4.2fV, Vss:%4.2fV, Icc:%6.1fmA, Iss:%6.1fmA, Vprim:%4.1fV, Vbias:%.1fV Ibias:%.1fnA" % r) Tntc7 = hk2degC("adc_Ifet", β=3940)
return r Tntc8 = hk2degC("adc_Vfet", β=3940)
print(f"Vcc:{Vcc:4.2f}V, Vss:{Vss:4.2f}V, Icc:{Icc:6.1f}mA, Iss:{Iss:6.1f}mA, Vprim:{Vprim:4.1f}V\n"
f"Vbias:{Vbias:.1f}V Ibias:{Ibias:.1f}nA Ibias₂:{Ibiasp:.1f}nA\n"
f"T₇:{Tntc7:.1f}°C T₈:{Tntc8:.1f}°C")
return Vcc, Vss, Icc, Iss, Vprim, Vbias, Ibias, Ibiasp, Tntc7, Tntc8
def findnmahepam(): def findnmahepam():
findxrena(prod=(0xee0c,)) findxrena(prod=(0xee0c,))
@ -22,77 +26,6 @@ def findnmahepam():
messages() messages()
HK() HK()
#TO DO: Adjust
def hk(sl, what="print", data=None):
if not data:
ecmd("alt/stream/off")
menable()
dorn.fifo_enable(en=True, sl=sl, hk=True)
dorn.fifo_reset(sl=sl, hk=True)
dorn.strobe(sl=sl, hk=True)
time.sleep(0.1)
dorn.fifo_read(sl=sl, hk=True)
data=read_fifo()
if data[0] != 0x5710 + sl:
raise ValueError("Read HK packet error", data)
if what=="data":
return data
ND = dorn.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 data
Vref = dorn.CONFIG.Vref(sl)/4096
#NMAHEPAM:data[7][0] *= 2*Vref/4096 # Vcore
data[4][0] = degC(data[4][0], 0) # T_BGO,EXT
data[4][1] = degC(data[4][1], 0) # T_BGO,NTC
data[4][2] *= -Vref/0.047 # V_bias
data[4][3] = degC(data[4][3], 0) # T_BGO,REF
data[4][4] *= Vref * 10470/470 * 51/1051 * 100 # Ibias
data[4][5] *= Vref * 10470/470 * 51/1051 * 100 # Ibias
data[4][7] *= Vref * 2 # VCC
data[4][6] *= Vref * 2.5 # VSS
data[4][6] -= 1.5*data[4][7] # VSS
data[3][0] *= Vref * 10470/470 * 51/1051 * 100 # Ibias
data[3][1] *= Vref * 2 # Vff
data[3][3] *= Vref * 2 # Vpp (V+6V)?
data[3][2] *= Vref * 2.5 # Vnn
data[3][2] -= 1.5*data[3][3] # Vnn
data[3][4] *= Vref * 2 # Vdig (Vadc)
data[3][5] = degC(data[3][5], 0) # NTC ?
data[3][6] *= Vref * 2 # VCC
data[3][7] *= Vref * 2.5 # VSS
data[3][7] -= 1.5*data[3][6] # VSS
if what=="cooked":
return data
r = f"""# nmahepam HK:
0. {data[0]}
1. {data[1]}
2. {data[2]}
3. ADC board
T = {data[3][5]:6.2f} °C
Ibias = {data[3][0]:6.3f} V
Vff = {data[3][1]:6.3f} V , Vnn = {data[3][2]:6.3f} V, Vpp = {data[3][3]:6.3f} V, Vdig = {data[3][4]:6.3f} V
Vcc = {data[3][6]:6.3f} V, Vss = {data[3][7]:6.3f} V
4. PA board
Tbgo = {data[4][0]:6.2f} °C, {data[4][1]:6.2f} °C, {data[4][3]:6.2f} °C
Vbias = {data[4][2]:6.3f} V, Ibias = {data[4][4]:6.1f} nA, {data[4][5]:6.1f} nA
Vcc = {data[4][7]:6.3f} V, Vss = {data[4][6]:6.3f} V
5. {data[5]}
6. {data[6]}
7. {data[7]}
"""
if what=="print":
sys.stderr.write(r)
return r
def TBITS(t): def TBITS(t):
return sum([1<<n for n in t]) return sum([1<<n for n in t])
@ -115,7 +48,12 @@ def aenable(sl=None, hk=True, ev=True, **aa):
enable() enable()
if __name__=="__main__": if __name__=="__main__":
ifc,_oo = armlib.init_irena(scope = globals(), name = "AHEPAM", prod = (0xee0c,)) ifc,_oo = armlib.init_irena(scope = globals(), name = "AHEPAM", prod = (0xee0c,),
long_options=["seth"])
for o,v in _oo[0]:
if o=="--seth":
dorn.CONFIG.seth()
armlib.set_prompt("SETH")
ifc._stream_fifos = 'hk1/f1/f2/f3' ifc._stream_fifos = 'hk1/f1/f2/f3'
if ifc.is_a("USB"): if ifc.is_a("USB"):
findnmahepam() findnmahepam()