Compare commits
2 commits
36c011d26e
...
6269048394
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6269048394 | ||
|
|
934fecf35b |
2 changed files with 175 additions and 0 deletions
Binary file not shown.
175
leia_stepper.py
Normal file
175
leia_stepper.py
Normal file
|
|
@ -0,0 +1,175 @@
|
||||||
|
|
||||||
|
import sys, armlib, struct, math, time
|
||||||
|
|
||||||
|
class leia_stepper:
|
||||||
|
|
||||||
|
class Stepper_Error(armlib.irena_ifc.IrenaError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __init__(self, ifc):
|
||||||
|
if ifc:
|
||||||
|
self._connect(ifc)
|
||||||
|
|
||||||
|
def _connect(self, ifc):
|
||||||
|
self.ifc = ifc
|
||||||
|
self.ifc.cmd("spi/reset/ssel/rate 30")
|
||||||
|
|
||||||
|
def _export(self, scope=None, prefix="stepper_"):
|
||||||
|
"""usage: ..._export(globals())
|
||||||
|
return a dict with all mames in self that
|
||||||
|
do not begin with an '_'
|
||||||
|
and are not all uppercase.
|
||||||
|
The scope is updated with the dict.
|
||||||
|
"""
|
||||||
|
r = {
|
||||||
|
prefix+k: getattr(self, k)
|
||||||
|
for k in dir(self)
|
||||||
|
if k.upper() != k and k[0] != "_"
|
||||||
|
}
|
||||||
|
if scope:
|
||||||
|
scope.update(r)
|
||||||
|
return r
|
||||||
|
|
||||||
|
_verbose = 2
|
||||||
|
|
||||||
|
cmd_pref = "spi/step"
|
||||||
|
|
||||||
|
def cmd(self, cmd, arg=0, argh=None, Error=False, retry=False, eth_retry=False):
|
||||||
|
c = ord(cmd[0])
|
||||||
|
arg2 = 0
|
||||||
|
if len(cmd)>1:
|
||||||
|
cc = f"{self.cmd_pref} {cmd!r} 0x{arg:x}"
|
||||||
|
else:
|
||||||
|
if isinstance(arg, str):
|
||||||
|
arg = arg.encode()
|
||||||
|
if isinstance(arg, bytes):
|
||||||
|
arg = arg[0]
|
||||||
|
if len(arg) > 1:
|
||||||
|
arg2 = arg[1]
|
||||||
|
if argh is not None:
|
||||||
|
arg2 = argh
|
||||||
|
if arg & 0xff00:
|
||||||
|
cc = f"{self.cmd_pref} {cmd!r} 0x{arg:x}"
|
||||||
|
else:
|
||||||
|
cc = f"{self.cmd_pref} {cmd!r} 0x{arg:x} 0x{arg2:x}"
|
||||||
|
while True:
|
||||||
|
r = self.ifc.cmd(cc, timeout=1000)
|
||||||
|
if r is None and eth_retry:
|
||||||
|
continue
|
||||||
|
if self._verbose >= 2:
|
||||||
|
print(cc, r, file=sys.stderr)
|
||||||
|
if self.ifc.cmdn(r) != 280:
|
||||||
|
if retry and self.ifc.cmdn(r) == 780 and r.split()[-1] == "130":
|
||||||
|
continue
|
||||||
|
raise self.Stepper_Error(r)
|
||||||
|
rr = r.split()
|
||||||
|
r1 = int(rr[2],0)
|
||||||
|
r = int(rr[3],0)
|
||||||
|
if retry and r1==0x45 and (r==0x5945 or r==0x5745):
|
||||||
|
# "EEY" interruped action by SPI
|
||||||
|
# "EEW" watchdog int during command Rx
|
||||||
|
continue
|
||||||
|
if r1 != c:
|
||||||
|
if Error:
|
||||||
|
r |= r1<<16
|
||||||
|
else:
|
||||||
|
raise self.Stepper_Error(f"{chr(r1)} {rr[3]}")
|
||||||
|
break
|
||||||
|
return r
|
||||||
|
|
||||||
|
def id(self):
|
||||||
|
n = self.hvc('V', 0xff) >> 8
|
||||||
|
return "".join([chr(self.hvc('V', i) & 0xff) for i in range(n)])
|
||||||
|
|
||||||
|
CONFN = [
|
||||||
|
"magic",
|
||||||
|
"version",
|
||||||
|
"flags",
|
||||||
|
"period",
|
||||||
|
"slen",
|
||||||
|
"lmask",
|
||||||
|
"lval",
|
||||||
|
"step",
|
||||||
|
"enable",
|
||||||
|
"reset",
|
||||||
|
"dir",
|
||||||
|
"n_steps",
|
||||||
|
"dac",
|
||||||
|
"dac_ramp",
|
||||||
|
"dac_step",
|
||||||
|
"adc_idx",
|
||||||
|
"adc_incr",
|
||||||
|
"adc_period",
|
||||||
|
"pad1", "pad23", "pad45", "pad67",
|
||||||
|
"adc00", "adc01", "adc02", "adc03",
|
||||||
|
"adc04", "adc05", "adc06", "adc07",
|
||||||
|
"adc08", "adc09", "adc10", "adc11",
|
||||||
|
"adc12", "adc13", "adc14", "adc15",
|
||||||
|
]
|
||||||
|
CONFV = (1,)
|
||||||
|
CONFF = "<HBBHH6B4H4B3H16B"
|
||||||
|
CONFS = 48
|
||||||
|
CONFM = b'\x1a\x1e'
|
||||||
|
|
||||||
|
def confdict(self, b):
|
||||||
|
b = struct.unpack(self.CONFF, b)
|
||||||
|
b = {k:v for k,v in zip(self.CONFN, b)}
|
||||||
|
return b
|
||||||
|
|
||||||
|
def confbytes(self, b, a=0):
|
||||||
|
"from str, dict, list, or bytes: make conf bytes"
|
||||||
|
if isinstance(b, str):
|
||||||
|
b = self.readhex(b, a, unpack=True)
|
||||||
|
if isinstance(b, dict):
|
||||||
|
b = [b[k] for k in self.CONFN]
|
||||||
|
if isinstance(b, list):
|
||||||
|
b = struct.pack(self.CONFF, *b)
|
||||||
|
return b
|
||||||
|
|
||||||
|
def read_conf(self, unpack=True):
|
||||||
|
b = []
|
||||||
|
while True:
|
||||||
|
r = self.cmd('x', len(b), Error=True)
|
||||||
|
if r & 0xff0000:
|
||||||
|
break
|
||||||
|
b.append(r & 0xff)
|
||||||
|
time.sleep(0.005)
|
||||||
|
b = bytes(b)
|
||||||
|
if unpack and b[:2]==self.CONFM and b[2] in self.CONFV:
|
||||||
|
return self.confdict(b)
|
||||||
|
return b
|
||||||
|
|
||||||
|
def readhex(self, fn, a=0, unpack=False):
|
||||||
|
import intelhex
|
||||||
|
b = bytes(intelhex.IntelHex(fn).tobinarray())[4*a:]
|
||||||
|
if not unpack:
|
||||||
|
return b
|
||||||
|
return self.confdict(b[:self.CONFS])
|
||||||
|
|
||||||
|
def verify_conf(self, b, a=0):
|
||||||
|
f = self.confbytes(b, a)
|
||||||
|
c = self.read_conf(unpack=False)
|
||||||
|
return [(4*a+i, b, f[i]) for i, b in enumerate(c) if b != f[i]]
|
||||||
|
|
||||||
|
def write_conf(self, b, a=0):
|
||||||
|
b = self.confbytes(b,a)
|
||||||
|
n = 0
|
||||||
|
for i, bb in enumerate(b):
|
||||||
|
self.cmd('X', i, bb)
|
||||||
|
n = i+1
|
||||||
|
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):
|
||||||
|
if dac is None:
|
||||||
|
dac = int(volt/3.3*0x10000)
|
||||||
|
if dac < 0 or dac >= 0x10000:
|
||||||
|
raise ValueError(f"DAC voltage out of range {volt}, {dac}")
|
||||||
|
old = self.cmd('D', dac)
|
||||||
|
if self._verbose >= 2:
|
||||||
|
print(f"DAC set to 0x{dac:04x}, old value: 0x{old:04x}",
|
||||||
|
file=sys.stderr)
|
||||||
|
self._dacvalue = dac
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue