Compare commits
4 commits
c18624c745
...
d5e4d19165
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5e4d19165 | ||
|
|
26d700bbad | ||
|
|
4c6bb8cb79 | ||
|
|
85b210b9e8 |
8 changed files with 303 additions and 74 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "avr"]
|
||||||
|
path = avr
|
||||||
|
url = ../irena-avr.git
|
||||||
1
avr
Submodule
1
avr
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 50f46b8494bbba65ccbec124f4fd4d9c0c4b72a3
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
@pressure/inject
|
@clock/short
|
||||||
@s/if sd_status & 0xc00: sd/init
|
@s/if !(sec % M): nm/cou/clear/short
|
||||||
|
|
|
||||||
|
|
@ -21,25 +21,25 @@ irena/nsamples 0 0x3f
|
||||||
irena/adcmask 0x02664
|
irena/adcmask 0x02664
|
||||||
irena/windows 2 5 8
|
irena/windows 2 5 8
|
||||||
echo Thresholds 100*mV high gain
|
echo Thresholds 100*mV high gain
|
||||||
@var/set V=14000
|
@var/set mV=14000
|
||||||
@irena/l1t 0 1000*V 0x000
|
@irena/l1t 0 1000*mV 0x000
|
||||||
@irena/l1t 1 100*V 0x000
|
@irena/l1t 1 100*mV 0x000
|
||||||
@irena/l1t 2 100*V 0x001
|
@irena/l1t 2 100*mV 0x001
|
||||||
@irena/l1t 3 1000*V 0x000
|
@irena/l1t 3 1000*mV 0x000
|
||||||
@irena/l1t 4 1000*V 0x000
|
@irena/l1t 4 1000*mV 0x000
|
||||||
@irena/l1t 5 100*V 0x001
|
@irena/l1t 5 100*mV 0x001
|
||||||
@irena/l1t 6 100*V 0x001
|
@irena/l1t 6 100*mV 0x001
|
||||||
@irena/l1t 7 1000*V 0x000
|
@irena/l1t 7 1000*mV 0x000
|
||||||
@irena/l1t 8 1000*V 0x000
|
@irena/l1t 8 1000*mV 0x000
|
||||||
@irena/l1t 9 100*V 0x001
|
@irena/l1t 9 100*mV 0x001
|
||||||
@irena/l1t 10 100*V 0x001
|
@irena/l1t 10 100*mV 0x001
|
||||||
@irena/l1t 11 1000*V 0x000
|
@irena/l1t 11 1000*mV 0x000
|
||||||
@irena/l1t 12 1000*V 0x000
|
@irena/l1t 12 1000*mV 0x000
|
||||||
@irena/l1t 13 100*V 0x001
|
@irena/l1t 13 100*mV 0x001
|
||||||
@irena/l1t 14 100*V 0x000
|
@irena/l1t 14 100*mV 0x000
|
||||||
@irena/l1t 15 1000*V 0x000
|
@irena/l1t 15 1000*mV 0x000
|
||||||
@irena/l1t 16 1000*V 0x000
|
@irena/l1t 16 1000*mV 0x000
|
||||||
@irena/l1t 17 100*V 0x000
|
@irena/l1t 17 100*mV 0x000
|
||||||
@irena/l2t/ch=0/any=0x001/read=0x02664 All
|
@irena/l2t/ch=0/any=0x001/read=0x02664 All
|
||||||
@irena/l2t/ch=1/disable
|
@irena/l2t/ch=1/disable
|
||||||
@irena/l2t/ch=2/disable
|
@irena/l2t/ch=2/disable
|
||||||
|
|
|
||||||
BIN
flash_alke/IRENA2TH.RBF
Normal file
BIN
flash_alke/IRENA2TH.RBF
Normal file
Binary file not shown.
|
|
@ -1,9 +1,9 @@
|
||||||
|
|
||||||
|
|
||||||
HW = {
|
HW.update({
|
||||||
"NCH" : 18,
|
"NCH" : 18,
|
||||||
"NPEEK" : 18,
|
"NPEEK" : 18,
|
||||||
}
|
})
|
||||||
|
|
||||||
def defaults(nch=18, ntr=6):
|
def defaults(nch=18, ntr=6):
|
||||||
adcmask()
|
adcmask()
|
||||||
|
|
@ -58,8 +58,10 @@ pulse_desy = [
|
||||||
pulse_desy.reverse()
|
pulse_desy.reverse()
|
||||||
|
|
||||||
def shaper2u2(nch=18, ntr=6, **kk):
|
def shaper2u2(nch=18, ntr=6, **kk):
|
||||||
|
HW["NCH"] = nch
|
||||||
global mV
|
global mV
|
||||||
mV=14000
|
mV=14000
|
||||||
|
Var("mV", mV)
|
||||||
defaults(nch=nch, ntr=ntr)
|
defaults(nch=nch, ntr=ntr)
|
||||||
pulse(range(nch), pulse2u2, **kk)
|
pulse(range(nch), pulse2u2, **kk)
|
||||||
readconfig(nch=nch, ntr=ntr)
|
readconfig(nch=nch, ntr=ntr)
|
||||||
|
|
@ -277,12 +279,11 @@ def TANOS():
|
||||||
readconfig()
|
readconfig()
|
||||||
|
|
||||||
def Gd4():
|
def Gd4():
|
||||||
global mV
|
shaper2u2()
|
||||||
mV=14000
|
|
||||||
readmask=0x6666
|
readmask=0x6666
|
||||||
adcmask(readmask)
|
adcmask(readmask)
|
||||||
windows(2,3,4,5)
|
windows(2,3,4,5)
|
||||||
for c in (0,3,4,7,8,11,12,15,16):
|
for c in (0,3,4,7,8,11,12,15,16,17):
|
||||||
thres(c, 100*mV, mask=0)
|
thres(c, 100*mV, mask=0)
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
thres(4*i+1, 100*mV, mask=(1<<i)|(1<<(2*i+4)))
|
thres(4*i+1, 100*mV, mask=(1<<i)|(1<<(2*i+4)))
|
||||||
|
|
@ -292,6 +293,27 @@ def Gd4():
|
||||||
l2trig(5, all=2, read=0)
|
l2trig(5, all=2, read=0)
|
||||||
readconfig()
|
readconfig()
|
||||||
|
|
||||||
|
def Gd4_2thr():
|
||||||
|
cmd("alt/file 'IRENA2TH.RBF'")
|
||||||
|
Script("IRENA.RC")
|
||||||
|
shaper2u2(nch=9)
|
||||||
|
readmask=0x0ff
|
||||||
|
adcmask(readmask)
|
||||||
|
windows(2,3,4,5)
|
||||||
|
for c in (8,17):
|
||||||
|
thres(c, 1000*mV, mask=0)
|
||||||
|
for i in range(4):
|
||||||
|
thres(2*i+0, 100*mV, mask=(1<<i)|(1<<(2*i+4)))
|
||||||
|
thres(2*i+1, 100*mV, mask=(1<<i)|(1<<(2*i+5)))
|
||||||
|
thres(2*i+9, 100*mV, mask=0);
|
||||||
|
thres(2*i+10, 100*mV, mask=0);
|
||||||
|
l2trig(i, any=1<<i, read=readmask)
|
||||||
|
l2trig(4, all=1, read=0)
|
||||||
|
l2trig(5, all=2, read=0)
|
||||||
|
readconfig()
|
||||||
|
Var("M", 3)
|
||||||
|
cmd("s/cron 'CRON.RC'")
|
||||||
|
|
||||||
def TRES():
|
def TRES():
|
||||||
shaper2u2()
|
shaper2u2()
|
||||||
global mV, AH, BH, CH, AL, BL, CL
|
global mV, AH, BH, CH, AL, BL, CL
|
||||||
|
|
|
||||||
283
leia_stepper.py
283
leia_stepper.py
|
|
@ -13,10 +13,11 @@ class leia_stepper:
|
||||||
def _connect(self, ifc):
|
def _connect(self, ifc):
|
||||||
self.ifc = ifc
|
self.ifc = ifc
|
||||||
self.ifc.cmd("spi/reset/ssel/rate 30")
|
self.ifc.cmd("spi/reset/ssel/rate 30")
|
||||||
|
print("LEIA stepper: ", self.id(), file=sys.stderr)
|
||||||
|
|
||||||
def _export(self, scope=None, prefix="stepper_"):
|
def _export(self, scope=None, prefix="stepper_"):
|
||||||
"""usage: ..._export(globals())
|
"""usage: ..._export(globals())
|
||||||
return a dict with all mames in self that
|
return a dict with all names in self that
|
||||||
do not begin with an '_'
|
do not begin with an '_'
|
||||||
and are not all uppercase.
|
and are not all uppercase.
|
||||||
The scope is updated with the dict.
|
The scope is updated with the dict.
|
||||||
|
|
@ -31,14 +32,18 @@ class leia_stepper:
|
||||||
return r
|
return r
|
||||||
|
|
||||||
_verbose = 2
|
_verbose = 2
|
||||||
|
_cmd_prefix = "spi/step"
|
||||||
cmd_pref = "spi/step"
|
|
||||||
|
|
||||||
def cmd(self, cmd, arg=0, argh=None, Error=False, retry=False, eth_retry=False):
|
def cmd(self, cmd, arg=0, argh=None,
|
||||||
|
Error=False, retry=True,
|
||||||
|
eth_retry=False, sleep=False,
|
||||||
|
verbose=None):
|
||||||
|
if verbose is None:
|
||||||
|
verbose = self._verbose >= 2
|
||||||
c = ord(cmd[0])
|
c = ord(cmd[0])
|
||||||
arg2 = 0
|
arg2 = 0
|
||||||
if len(cmd)>1:
|
if len(cmd)>1:
|
||||||
cc = f"{self.cmd_pref} {cmd!r} 0x{arg:x}"
|
cc = f"{self._cmd_prefix} {cmd!r} 0x{arg:x}"
|
||||||
else:
|
else:
|
||||||
if isinstance(arg, str):
|
if isinstance(arg, str):
|
||||||
arg = arg.encode()
|
arg = arg.encode()
|
||||||
|
|
@ -49,14 +54,16 @@ class leia_stepper:
|
||||||
if argh is not None:
|
if argh is not None:
|
||||||
arg2 = argh
|
arg2 = argh
|
||||||
if arg & 0xff00:
|
if arg & 0xff00:
|
||||||
cc = f"{self.cmd_pref} {cmd!r} 0x{arg:x}"
|
cc = f"{self._cmd_prefix} {cmd!r} 0x{arg:x}"
|
||||||
else:
|
else:
|
||||||
cc = f"{self.cmd_pref} {cmd!r} 0x{arg:x} 0x{arg2:x}"
|
cc = f"{self._cmd_prefix} {cmd!r} 0x{arg:x} 0x{arg2:x}"
|
||||||
while True:
|
while True:
|
||||||
|
if sleep:
|
||||||
|
time.sleep(sleep)
|
||||||
r = self.ifc.cmd(cc, timeout=1000)
|
r = self.ifc.cmd(cc, timeout=1000)
|
||||||
if r is None and eth_retry:
|
if r is None and eth_retry:
|
||||||
continue
|
continue
|
||||||
if self._verbose >= 2:
|
if verbose:
|
||||||
print(cc, r, file=sys.stderr)
|
print(cc, r, file=sys.stderr)
|
||||||
if self.ifc.cmdn(r) != 280:
|
if self.ifc.cmdn(r) != 280:
|
||||||
if retry and self.ifc.cmdn(r) == 780 and r.split()[-1] == "130":
|
if retry and self.ifc.cmdn(r) == 780 and r.split()[-1] == "130":
|
||||||
|
|
@ -65,21 +72,29 @@ class leia_stepper:
|
||||||
rr = r.split()
|
rr = r.split()
|
||||||
r1 = int(rr[2],0)
|
r1 = int(rr[2],0)
|
||||||
r = int(rr[3],0)
|
r = int(rr[3],0)
|
||||||
if retry and r1==0x45 and (r==0x5945 or r==0x5745):
|
if retry and r1==0x45:
|
||||||
# "EEY" interruped action by SPI
|
r2 = r & 0xff
|
||||||
# "EEW" watchdog int during command Rx
|
if r2==0x53:
|
||||||
continue
|
# "ES" SPI too slow or early
|
||||||
|
continue
|
||||||
|
r3 = r >> 8
|
||||||
|
if r2==0x45 and r3 != c:
|
||||||
|
# "EE" unknown command
|
||||||
|
continue
|
||||||
if r1 != c:
|
if r1 != c:
|
||||||
if Error:
|
if Error:
|
||||||
r |= r1<<16
|
r |= r1<<16
|
||||||
else:
|
else:
|
||||||
raise self.Stepper_Error(f"{chr(r1)} {rr[3]}")
|
rc = chr(r1)
|
||||||
|
if rc.isprintable():
|
||||||
|
raise self.Stepper_Error(f"{rc} {rr[3]}")
|
||||||
|
raise self.Stepper_Error(f"{rr[2]} {rr[3]}")
|
||||||
break
|
break
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def id(self):
|
def id(self):
|
||||||
n = self.hvc('V', 0xff) >> 8
|
n = self.cmd('v', 0xff, verbose=False) >> 8
|
||||||
return "".join([chr(self.hvc('V', i) & 0xff) for i in range(n)])
|
return bytes(self.cmd('v', i, verbose=False) & 0xff for i in range(n)).decode()
|
||||||
|
|
||||||
CONFN = [
|
CONFN = [
|
||||||
"magic",
|
"magic",
|
||||||
|
|
@ -94,63 +109,130 @@ class leia_stepper:
|
||||||
"reset",
|
"reset",
|
||||||
"dir",
|
"dir",
|
||||||
"n_steps",
|
"n_steps",
|
||||||
"dac",
|
|
||||||
"dac_ramp",
|
"dac_ramp",
|
||||||
"dac_step",
|
"dac_step",
|
||||||
"adc_idx",
|
|
||||||
"adc_incr",
|
"adc_incr",
|
||||||
"adc_period",
|
"adc_period",
|
||||||
"pad1", "pad23", "pad45", "pad67",
|
"awake",
|
||||||
"adc00", "adc01", "adc02", "adc03",
|
"ledoff",
|
||||||
"adc04", "adc05", "adc06", "adc07",
|
"disable",
|
||||||
"adc08", "adc09", "adc10", "adc11",
|
"dac_ref",
|
||||||
"adc12", "adc13", "adc14", "adc15",
|
("padc", struct.Struct("<6B")),
|
||||||
|
("adc_ch", struct.Struct("<16B")),
|
||||||
|
("adc", struct.Struct("<16H")),
|
||||||
|
"dac",
|
||||||
|
"adc_idx",
|
||||||
|
"eewr_n",
|
||||||
|
"eewr_a",
|
||||||
|
("pads", struct.Struct("<42B"))
|
||||||
]
|
]
|
||||||
CONFV = (1,)
|
|
||||||
CONFF = "<HBBHH6B4H4B3H16B"
|
|
||||||
CONFS = 48
|
|
||||||
CONFM = b'\x1a\x1e'
|
CONFM = b'\x1a\x1e'
|
||||||
|
CONFV = (1,)
|
||||||
|
CONFF = struct.Struct("<HBBHH6B3H6B6s16s")
|
||||||
|
STATF = struct.Struct(CONFF.format + "32sHBBH42s")
|
||||||
|
|
||||||
def confdict(self, b):
|
def confdict(self, b):
|
||||||
b = struct.unpack(self.CONFF, b)
|
if len(b)==self.CONFF.size:
|
||||||
b = {k:v for k,v in zip(self.CONFN, b)}
|
b = self.CONFF.unpack(b)
|
||||||
return b
|
else:
|
||||||
|
b = self.STATF.unpack(b)
|
||||||
|
i = 0
|
||||||
|
bb = {}
|
||||||
|
for i, bbb in enumerate(b):
|
||||||
|
k = self.CONFN[i]
|
||||||
|
if isinstance(k, tuple):
|
||||||
|
bbb = list(k[1].unpack(bbb))
|
||||||
|
k = k[0]
|
||||||
|
bb[k] = bbb
|
||||||
|
return bb
|
||||||
|
|
||||||
|
def fromdict(self, b):
|
||||||
|
bb = []
|
||||||
|
for kk in self.CONFN:
|
||||||
|
k = kk
|
||||||
|
if isinstance(kk, tuple):
|
||||||
|
k = k[0]
|
||||||
|
if not k in b:
|
||||||
|
break
|
||||||
|
bbb = b[k]
|
||||||
|
if isinstance(kk, tuple):
|
||||||
|
bbb=kk[1].pack(*bbb)
|
||||||
|
bb.append(bbb)
|
||||||
|
try:
|
||||||
|
return self.CONFF.pack(*bb)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return self.STATF.pack(*bb)
|
||||||
|
|
||||||
def confbytes(self, b, a=0):
|
def confbytes(self, b, a=0):
|
||||||
"from str, dict, list, or bytes: make conf bytes"
|
"from str, dict, list, or bytes: make conf bytes"
|
||||||
if isinstance(b, str):
|
if isinstance(b, str):
|
||||||
b = self.readhex(b, a, unpack=True)
|
b = self.readhex(b, a, unpack=True)
|
||||||
if isinstance(b, dict):
|
if isinstance(b, dict):
|
||||||
b = [b[k] for k in self.CONFN]
|
b = self.fromdict(b)
|
||||||
if isinstance(b, list):
|
if isinstance(b, list):
|
||||||
b = struct.pack(self.CONFF, *b)
|
bb = []
|
||||||
|
for i, bbb in enumerate(b):
|
||||||
|
if isinstance(bbb, list):
|
||||||
|
bbb = self.CONFN[i][1].pack(bbb)
|
||||||
|
bb.extend(bbb)
|
||||||
|
else:
|
||||||
|
bb.append(bbb)
|
||||||
|
try:
|
||||||
|
b = struct.pack(self.CONFF, *bb)
|
||||||
|
except:
|
||||||
|
b = struct.pack(self.STATF, *bb)
|
||||||
return b
|
return b
|
||||||
|
|
||||||
def read_conf(self, unpack=True):
|
def read_conf(self, unpack=True):
|
||||||
b = []
|
b = []
|
||||||
while True:
|
while True:
|
||||||
r = self.cmd('x', len(b), Error=True)
|
r = self.cmd('x', len(b), Error=True, sleep=0.001)
|
||||||
if r & 0xff0000:
|
if r & 0xff0000:
|
||||||
break
|
break
|
||||||
b.append(r & 0xff)
|
b.append(r & 0xff)
|
||||||
time.sleep(0.005)
|
|
||||||
b = bytes(b)
|
b = bytes(b)
|
||||||
if unpack and b[:2]==self.CONFM and b[2] in self.CONFV:
|
if unpack and b[:2]==self.CONFM and b[2] in self.CONFV:
|
||||||
return self.confdict(b)
|
return self.confdict(b)
|
||||||
return b
|
return b
|
||||||
|
|
||||||
|
def read_eeprom(self, a=0, n=CONFF.size):
|
||||||
|
return bytes([self.cmd('x', aa | 0x800, sleep=0.001) & 0xff
|
||||||
|
for aa in range(a, a+n)])
|
||||||
|
|
||||||
|
def read_ram(self, a=0x100, n=0x800):
|
||||||
|
return bytes([self.cmd('y', aa, sleep=0.001) & 0xff
|
||||||
|
for aa in range(a, a+n)])
|
||||||
|
|
||||||
|
def read_rom(self, a=0, n=0x8000):
|
||||||
|
return bytes([self.cmd('y', aa|0x8000, sleep=0.001) & 0xff
|
||||||
|
for aa in range(a, a+n)])
|
||||||
|
|
||||||
def readhex(self, fn, a=0, unpack=False):
|
def readhex(self, fn, a=0, unpack=False):
|
||||||
import intelhex
|
import intelhex
|
||||||
b = bytes(intelhex.IntelHex(fn).tobinarray())[4*a:]
|
b = bytes(intelhex.IntelHex(fn).tobinarray())[4*a:]
|
||||||
if not unpack:
|
if not unpack:
|
||||||
return b
|
return b
|
||||||
return self.confdict(b[:self.CONFS])
|
return self.confdict(b)
|
||||||
|
|
||||||
def verify_conf(self, b, a=0):
|
def verify_conf(self, b, a=0):
|
||||||
f = self.confbytes(b, a)
|
f = self.confbytes(b, a)[:self.CONFF.size]
|
||||||
c = self.read_conf(unpack=False)
|
c = self.read_conf(unpack=False)[:self.CONFF.size]
|
||||||
return [(4*a+i, b, f[i]) for i, b in enumerate(c) if b != f[i]]
|
return [(4*a+i, b, f[i]) for i, b in enumerate(c) if b != f[i]]
|
||||||
|
|
||||||
|
def dictdiff(self, a, b):
|
||||||
|
return [(k, a[k], b[k]) for k in a if a[k] != b[k]]
|
||||||
|
|
||||||
|
def get_confs(self, ihex="avr/leia.eeprom", eaddr=0):
|
||||||
|
self.conf = self.read_conf(unpack=True)
|
||||||
|
if ihex:
|
||||||
|
self.ihex = self.readhex(ihex, unpack=True)
|
||||||
|
if eaddr is not None:
|
||||||
|
self.econf = self.confdict(self.read_eeprom(eaddr))
|
||||||
|
print("eeprom → conf: ", self.dictdiff(self.econf, self.conf), file=sys.stderr)
|
||||||
|
if ihex:
|
||||||
|
print("ihex → conf: ", self.dictdiff(self.ihex, self.conf), file=sys.stderr)
|
||||||
|
|
||||||
def write_conf(self, b, a=0):
|
def write_conf(self, b, a=0):
|
||||||
b = self.confbytes(b,a)
|
b = self.confbytes(b,a)
|
||||||
n = 0
|
n = 0
|
||||||
|
|
@ -158,18 +240,135 @@ class leia_stepper:
|
||||||
self.cmd('X', i, bb)
|
self.cmd('X', i, bb)
|
||||||
n = i+1
|
n = i+1
|
||||||
return b[:n]
|
return b[:n]
|
||||||
|
|
||||||
def adc(self, ch=0, what=0, val=0):
|
|
||||||
return self.cmd('a', val, what<<4 | ch & 0xf);
|
|
||||||
|
|
||||||
def dac(self, volt=0.0, dac=None, ramp=True):
|
ADC_V = {
|
||||||
|
"data": 0,
|
||||||
|
"mux": 1,
|
||||||
|
"idx": 2,
|
||||||
|
"incr": 3,
|
||||||
|
"period": 4,
|
||||||
|
"ADMUX": 5,
|
||||||
|
"ADCSRA": 6,
|
||||||
|
"ADCH": 7,
|
||||||
|
}
|
||||||
|
|
||||||
|
def adc(self, ch=0, what=None, val=None, enable=None, **aa):
|
||||||
|
"send one 'a' or 'A' command"
|
||||||
|
if what in self.ADC_V:
|
||||||
|
what = self.ADC_V[what]
|
||||||
|
for a in aa:
|
||||||
|
if what is not None or val is not None:
|
||||||
|
raise ValueError("multiple whatsits not supported")
|
||||||
|
what = self.ADC_V[a]
|
||||||
|
val = aa[a]
|
||||||
|
what = what or 0
|
||||||
|
if isinstance(val, float):
|
||||||
|
if what == self.ADC_V["period"]:
|
||||||
|
val = int(val/self.T0TICK + 0.5) # ms
|
||||||
|
else:
|
||||||
|
raise ValueError("fload not supported for this whatsit")
|
||||||
|
if enable is not None:
|
||||||
|
if what and enable and val is not None:
|
||||||
|
raise ValueError("cannot enable and read a whatsit")
|
||||||
|
what != 0x80
|
||||||
|
what = (what << 4) | ch;
|
||||||
|
c = 'A' if val is not None or enable else 'a'
|
||||||
|
val = val or 0
|
||||||
|
r = self.cmd(c, val, what);
|
||||||
|
if not what & 0x70:
|
||||||
|
return r
|
||||||
|
if (r>>8) != what:
|
||||||
|
raise self.Stepper_Error(f"{c}, {val}, {what} → {r}")
|
||||||
|
return r & 0xff
|
||||||
|
|
||||||
|
def dac(self, volt=0.0, dac=None, ramp=True, ms=None):
|
||||||
if dac is None:
|
if dac is None:
|
||||||
dac = int(volt/3.3*0x10000)
|
dac = int(volt/2.5*0x10000)
|
||||||
if dac < 0 or dac >= 0x10000:
|
if dac < 0 or dac >= 0x10000:
|
||||||
raise ValueError(f"DAC voltage out of range {volt}, {dac}")
|
raise ValueError(f"DAC voltage out of range {volt}, {dac}")
|
||||||
|
if not ramp:
|
||||||
|
self.cmd('P', 0)
|
||||||
|
if ms is not None:
|
||||||
|
t = self.adc(what="period")*self.T0TICK
|
||||||
|
p = int(t * 64/ ms + 0.5)
|
||||||
|
if p < 1:
|
||||||
|
p = 1
|
||||||
|
if p > 1024:
|
||||||
|
p = 1024
|
||||||
|
self.cmd('P', p)
|
||||||
|
if self._verbose >= 1:
|
||||||
|
print(f"DAC ramp speed {t*64/p:.1f} ms/step", file=sys.stderr)
|
||||||
old = self.cmd('D', dac)
|
old = self.cmd('D', dac)
|
||||||
if self._verbose >= 2:
|
if self._verbose >= 1:
|
||||||
print(f"DAC set to 0x{dac:04x}, old value: 0x{old:04x}",
|
print(f"DAC set to 0x{dac:04x}, old value: 0x{old:04x}",
|
||||||
file=sys.stderr)
|
file=sys.stderr)
|
||||||
self._dacvalue = dac
|
|
||||||
|
def Temp(self, a, Vref, **aa):
|
||||||
|
a *= self.Vcc/Vref
|
||||||
|
return armlib.NTC(a, β=3940)
|
||||||
|
|
||||||
|
def AVR_Temp(self, a, Vref, **aa):
|
||||||
|
return a/64 * 2.5/Vref - 273
|
||||||
|
|
||||||
|
ADC_MUX = {
|
||||||
|
3: ("Iprim", 1.0, "uncal"),
|
||||||
|
8: ("NTC1", Temp, "°C"),
|
||||||
|
9: ("NTC2", Temp, "°C"),
|
||||||
|
10: ("NTC3", Temp, "°C"),
|
||||||
|
11: ("Temp", AVR_Temp, "°C"),
|
||||||
|
12: ("Vcc", 4.0, "V"),
|
||||||
|
17: ("Bandgap", 1.0, "V"),
|
||||||
|
18: ("GND", 1.0, "V"),
|
||||||
|
}
|
||||||
|
|
||||||
|
Vcc = 3.3
|
||||||
|
T0TICK = 0.0925925925925926
|
||||||
|
|
||||||
|
def read_adcs(self, chs=tuple(range(16)), update_vcc=True):
|
||||||
|
r = []
|
||||||
|
for ch in chs:
|
||||||
|
mux = self.cmd('a', 0, 0x10+ch)
|
||||||
|
if not mux & 0x40: # REFS0
|
||||||
|
r.append((ch, mux))
|
||||||
|
continue
|
||||||
|
Vref = 2.5 if mux & 0x80 else self.Vcc; # REFS1
|
||||||
|
a = self.cmd('a', 0, ch)
|
||||||
|
if not mux & 0x1f in self.ADC_MUX:
|
||||||
|
r.append((ch, mux, a))
|
||||||
|
continue
|
||||||
|
avg = not mux & 0x20
|
||||||
|
n = self.ADC_MUX[mux & 0x1f]
|
||||||
|
v = a
|
||||||
|
if mux & 0x20:
|
||||||
|
# ADLAR, single conversion
|
||||||
|
# !ADLAR: exponential average, τ=64 conversions
|
||||||
|
v &= 0xffc0
|
||||||
|
if isinstance(n[1], float):
|
||||||
|
v *= Vref/0x10000 * n[1]
|
||||||
|
else:
|
||||||
|
v = n[1](self, v, mux=mux, Vref=Vref)
|
||||||
|
r.append((ch, mux, a, n[0], v, n[2], Vref))
|
||||||
|
if (mux & 0xff) == 0xcc:
|
||||||
|
self.Vcc = v
|
||||||
|
for rr in r:
|
||||||
|
try:
|
||||||
|
ch, mux, a, n, v, u, Vref = rr
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
print(f"{ch:2d} 0x{mux:04x} 0x{a:04x} {n:7s} {v:6.3f} {u:5s} {'single' if mux & 0x20 else 'avg '} ({Vref:.2f} V)")
|
||||||
|
return r
|
||||||
|
|
||||||
|
def avrdude(self):
|
||||||
|
print(self.ifc.cmd("v spi_ssel = 0"), file=sys.stderr)
|
||||||
|
print(self.ifc.cmd("spi/reset"), file=sys.stderr)
|
||||||
|
try:
|
||||||
|
print("SPI reset for programming the AVR", file=sys.stderr)
|
||||||
|
print("Press ^C when done …", end="", file=sys.stderr)
|
||||||
|
while True:
|
||||||
|
sys.stderr.flush()
|
||||||
|
time.sleep(60)
|
||||||
|
print(" …", end="", file=sys.stderr)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
pass
|
||||||
|
print(" done.\n", self.ifc.cmd("spi/reset/ssel"), file=sys.stderr)
|
||||||
|
print("commit: ", self.id(), file=sys.stderr)
|
||||||
|
|
|
||||||
14
nmahepam.py
14
nmahepam.py
|
|
@ -20,7 +20,7 @@ def HK():
|
||||||
return Vcc, Vss, Icc, Iss, Vprim, Vbias, Ibias, Ibiasp, Tntc7, Tntc8
|
return Vcc, Vss, Icc, Iss, Vprim, Vbias, Ibias, Ibiasp, Tntc7, Tntc8
|
||||||
|
|
||||||
def findnmahepam():
|
def findnmahepam():
|
||||||
findxrena(prod=(0xee0c,))
|
findxrena(prod=(0xee0c,0xee0a))
|
||||||
if connected_p():
|
if connected_p():
|
||||||
set_clock()
|
set_clock()
|
||||||
messages()
|
messages()
|
||||||
|
|
@ -75,8 +75,10 @@ Keep_alive = armlib.Keep_Alive_Schedule(
|
||||||
)
|
)
|
||||||
|
|
||||||
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,0xee0a),
|
||||||
long_options=["seth", "ahbgo"])
|
long_options=["seth", "ahbgo", "leia"])
|
||||||
|
if ifc.is_a("USB"):
|
||||||
|
findnmahepam()
|
||||||
for o,v in _oo[0]:
|
for o,v in _oo[0]:
|
||||||
if o=="--seth":
|
if o=="--seth":
|
||||||
dorn.CONFIG.seth()
|
dorn.CONFIG.seth()
|
||||||
|
|
@ -85,9 +87,11 @@ if __name__=="__main__":
|
||||||
if o=="--ahbgo":
|
if o=="--ahbgo":
|
||||||
dorn.CONFIG.ahbgo()
|
dorn.CONFIG.ahbgo()
|
||||||
armlib.set_prompt("AHBGO")
|
armlib.set_prompt("AHBGO")
|
||||||
|
if o=="--leia":
|
||||||
|
armlib.set_prompt("LEIA")
|
||||||
|
import leia_stepper
|
||||||
|
st = leia_stepper.leia_stepper(ifc)
|
||||||
ifc._stream_fifos = 'hk1/f1/f2/f3'
|
ifc._stream_fifos = 'hk1/f1/f2/f3'
|
||||||
if ifc.is_a("USB"):
|
|
||||||
findnmahepam()
|
|
||||||
from dorn import *
|
from dorn import *
|
||||||
dorn._connect(ifc)
|
dorn._connect(ifc)
|
||||||
ifc._stream_reset |= 0x000c
|
ifc._stream_reset |= 0x000c
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue