mirror of
https://codeberg.org/SiB64/turbo_weather.git
synced 2026-06-30 08:19:50 +02:00
Compare commits
No commits in common. "6f80ed5d646b0c7b3362b5dc92a44947c3d01393" and "42fb68de4dadb99c9513ac361686d58f973d0d49" have entirely different histories.
6f80ed5d64
...
42fb68de4d
4 changed files with 12 additions and 482 deletions
|
|
@ -496,10 +496,9 @@ int main()
|
||||||
send_calib_adc(i);
|
send_calib_adc(i);
|
||||||
send_eol();
|
send_eol();
|
||||||
}
|
}
|
||||||
if (config.power & POWER_LINE) {
|
if (config.send & (SEND_ADC_VOLT|SEND_ADC_HEX))
|
||||||
send_cks();
|
if (config.power & POWER_LINE)
|
||||||
uart_cks = 0;
|
send_cks();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
command();
|
command();
|
||||||
|
|
@ -564,6 +563,8 @@ int main()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uart_cks = 0;
|
||||||
|
|
||||||
if (config.send & SEND_CONFIG && !config_clock--) {
|
if (config.send & SEND_CONFIG && !config_clock--) {
|
||||||
send_config = 1;
|
send_config = 1;
|
||||||
config_clock = config.confp;
|
config_clock = config.confp;
|
||||||
|
|
|
||||||
448
src/cmd.py
448
src/cmd.py
|
|
@ -1,448 +0,0 @@
|
||||||
#! /usr/bin/python3
|
|
||||||
|
|
||||||
import sys, time, struct
|
|
||||||
import cmdsocket
|
|
||||||
|
|
||||||
class turbocmd(cmdsocket.cmder):
|
|
||||||
|
|
||||||
pace_delay = 0.1
|
|
||||||
pace_next = 0
|
|
||||||
def pace(self):
|
|
||||||
t = time.time()
|
|
||||||
if t < self.pace_next:
|
|
||||||
time.sleep(self.pace_next - t)
|
|
||||||
self.pace_next = t+self.pace_delay
|
|
||||||
|
|
||||||
def set_pace(seld, d):
|
|
||||||
self.pace_delay = d
|
|
||||||
|
|
||||||
def clock(self, t=None):
|
|
||||||
if t is None:
|
|
||||||
t = time.time()
|
|
||||||
tt = struct.unpack("4B", struct.pack("<L", int(t)))
|
|
||||||
self.write(b"K"+b"".join([b"%02x" % ttt for ttt in tt]))
|
|
||||||
|
|
||||||
SEND = {
|
|
||||||
"CONFIG": 0x01,
|
|
||||||
"BATED": 0x02,
|
|
||||||
"BATEW": 0x04,
|
|
||||||
"CLOCK": 0x08,
|
|
||||||
"CALIB": 0x10,
|
|
||||||
"ADC_HEX": 0x20,
|
|
||||||
"ADC_VOLT": 0x40,
|
|
||||||
"ADC": 0x60,
|
|
||||||
"DEBUG": 0x80,
|
|
||||||
}
|
|
||||||
|
|
||||||
POWER = {
|
|
||||||
"DOWN": 0x01,
|
|
||||||
"DOWN_CLI": 0x02,
|
|
||||||
"STOP_MCLK": 0x04,
|
|
||||||
"LED": 0x08,
|
|
||||||
"STDBY": 0x10,
|
|
||||||
"RX": 0x20,
|
|
||||||
"RF": 0x40,
|
|
||||||
"LINE": 0x80,
|
|
||||||
}
|
|
||||||
|
|
||||||
TRIGGER = {
|
|
||||||
"ONCE": 0x01,
|
|
||||||
"CONT": 0x02,
|
|
||||||
"UART": 0x04,
|
|
||||||
"CLOCK": 0x08,
|
|
||||||
"BREAK": 0x10,
|
|
||||||
"IMMED": 0x20,
|
|
||||||
}
|
|
||||||
|
|
||||||
UART = {
|
|
||||||
"TX": 0x40,
|
|
||||||
"RX": 0x80,
|
|
||||||
"SFD": 0x10,
|
|
||||||
"ODME": 0x08,
|
|
||||||
"CLKX2": 0x02,
|
|
||||||
"GAUTO": 0x04,
|
|
||||||
"LAUTO": 0x06,
|
|
||||||
}
|
|
||||||
|
|
||||||
REGS = {
|
|
||||||
"magic": (0x00, 1,),
|
|
||||||
"version": (0x01, 1,),
|
|
||||||
"triggers": (0x02, 1, TRIGGER),
|
|
||||||
"send": (0x03, 1, SEND),
|
|
||||||
"power": (0x04, 1, POWER),
|
|
||||||
"calib_test": (0x05, 1,),
|
|
||||||
"spi_div": (0x06, 1,),
|
|
||||||
"mclk_delay": (0x07, 1,),
|
|
||||||
"period": (0x08, 1,),
|
|
||||||
"confp": (0x09, 1,),
|
|
||||||
"cpu_clk": (0x0a, 1,),
|
|
||||||
"mclk_period": (0x0b, 1,),
|
|
||||||
"baud_div": (0x0c, 2,),
|
|
||||||
"uart_mode": (0x0e, 1, UART),
|
|
||||||
"pit_period": (0x0f, 1,),
|
|
||||||
"immediate": (0x10, 1,),
|
|
||||||
"pad": (0x11, 7,),
|
|
||||||
"line_preable": (0x18, 7,),
|
|
||||||
"zero": (0x1f, 1,),
|
|
||||||
}
|
|
||||||
|
|
||||||
def fconf(self, idx):
|
|
||||||
for k in self.REGS:
|
|
||||||
if self.REGS[k][0] == idx:
|
|
||||||
return self.REGS[k]
|
|
||||||
|
|
||||||
num_base = 0
|
|
||||||
|
|
||||||
def number(self, a, idx=None, kw=True):
|
|
||||||
"""return an index, value or bit
|
|
||||||
None, idx a config index symbol
|
|
||||||
-1, val a number
|
|
||||||
0…, val a bit value symbol
|
|
||||||
|
|
||||||
bit values are searched for the provided index, or the next
|
|
||||||
if no index is provided, any bit value may be returned
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return (-1, int(a, self.num_base))
|
|
||||||
except ValueError:
|
|
||||||
if not kw:
|
|
||||||
raise
|
|
||||||
if a.lower() in self.REGS:
|
|
||||||
return (None, self.REGS[a.lower()][0])
|
|
||||||
a = a.upper()
|
|
||||||
try:
|
|
||||||
return (idx, self.fconf(idx)[2][a])
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if idx is not None:
|
|
||||||
idx += 1
|
|
||||||
return (idx, self.fconf(idx)[2][a])
|
|
||||||
for v in self.REGS.values():
|
|
||||||
try:
|
|
||||||
return (v[0], v[2][a])
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
# raise
|
|
||||||
return (None, self.REGS[a][0])
|
|
||||||
|
|
||||||
def config(self, cmd, magic, reg, *a):
|
|
||||||
keywords = cmd != b'E'
|
|
||||||
ii, idx = self.number(reg, kw=keywords)
|
|
||||||
b = [magic, idx]
|
|
||||||
partial = False
|
|
||||||
if ii is not None and ii >= 0:
|
|
||||||
b[1:1] = [ii]
|
|
||||||
partial = True
|
|
||||||
idx = ii
|
|
||||||
elif not a:
|
|
||||||
if cmd==b'C':
|
|
||||||
aa = self.find_symbol("config")
|
|
||||||
if cmd==b'U':
|
|
||||||
aa = self.find_symbol("USERROW")
|
|
||||||
if cmd==b'E':
|
|
||||||
aa = self.find_symbol("EEPROM")
|
|
||||||
self.write(b'M%04x' % (aa+idx))
|
|
||||||
return
|
|
||||||
for aa in a:
|
|
||||||
try:
|
|
||||||
ii, bb = self.number(aa, idx, kw=keywords)
|
|
||||||
except Exception as e:
|
|
||||||
raise ValueError(f"{aa}: invalid config item\n{e}")
|
|
||||||
if ii==idx:
|
|
||||||
# got a bit for this config byte
|
|
||||||
if not partial:
|
|
||||||
b.append(bb)
|
|
||||||
partial = True
|
|
||||||
else:
|
|
||||||
b[-1] |= bb
|
|
||||||
continue
|
|
||||||
if ii is None:
|
|
||||||
# got a config index
|
|
||||||
# those need to be consecutive
|
|
||||||
if bb == idx:
|
|
||||||
continue
|
|
||||||
if bb != idx+1:
|
|
||||||
raise IndexError(f"{aa} nonconsecutive configs")
|
|
||||||
if not partial:
|
|
||||||
b.append(0)
|
|
||||||
partial = False
|
|
||||||
idx = bb
|
|
||||||
continue
|
|
||||||
if ii == idx+1:
|
|
||||||
# got a bit for the next config byte
|
|
||||||
if not partial:
|
|
||||||
b.append(0)
|
|
||||||
b.append(bb)
|
|
||||||
partial = True
|
|
||||||
idx = ii
|
|
||||||
continue
|
|
||||||
if ii < 0:
|
|
||||||
# got a number. Either a byte or a word
|
|
||||||
b.append(bb & 0xff)
|
|
||||||
s = 1
|
|
||||||
if keywords:
|
|
||||||
try:
|
|
||||||
s = self.fconf(idx)[1]
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if s==2:
|
|
||||||
b.append(bb >> 8)
|
|
||||||
if s==4:
|
|
||||||
b.append((bb >> 8) & 0xff)
|
|
||||||
b.append((bb >> 16) & 0xff)
|
|
||||||
b.append((bb >> 24) & 0xff)
|
|
||||||
idx += s
|
|
||||||
partial = False
|
|
||||||
self.write(cmd + b"".join([b"%02x" % (bb&0xff) for bb in b]))
|
|
||||||
|
|
||||||
def mem(self, a, v=None):
|
|
||||||
aa = a.split("+", 1)
|
|
||||||
a = self.find_symbol(aa[0])
|
|
||||||
if len(aa)==2:
|
|
||||||
a += int(aa[1], self.num_base)
|
|
||||||
if v is None:
|
|
||||||
self.write(b'M%04x' % a)
|
|
||||||
return
|
|
||||||
v = int(v, self.num_base)
|
|
||||||
self.write(b'W%04x %02x' % (a & 0xffff, v & 0xff))
|
|
||||||
|
|
||||||
def value(self, cmd, v):
|
|
||||||
v = int(v, self.num_base)
|
|
||||||
self.write(cmd + b'%02x' % (v & 0xff))
|
|
||||||
|
|
||||||
# ATtiny424 IO
|
|
||||||
symbols = {
|
|
||||||
"VPORTA": 0x0000,
|
|
||||||
"VPORTB": 0x0004,
|
|
||||||
"VPORTC": 0x0008,
|
|
||||||
"RSTCTRL": 0x0040,
|
|
||||||
"SLPCTRL": 0x0050,
|
|
||||||
"CLKCTRL": 0x0060,
|
|
||||||
"BOD": 0x0080,
|
|
||||||
"VREF": 0x00A0,
|
|
||||||
"WDT": 0x0100,
|
|
||||||
"CPUINT": 0x0110,
|
|
||||||
"CRCSCAN": 0x0120,
|
|
||||||
"RTC": 0x0140,
|
|
||||||
"EVSYS": 0x0180,
|
|
||||||
"CCL": 0x01C0,
|
|
||||||
"PORTA": 0x0400,
|
|
||||||
"PORTB": 0x0420,
|
|
||||||
"PORTC": 0x0440,
|
|
||||||
"PORTMUX": 0x05E0,
|
|
||||||
"ADC0": 0x0600,
|
|
||||||
"AC0": 0x0680,
|
|
||||||
"USART0": 0x0800,
|
|
||||||
"USART1": 0x0820,
|
|
||||||
"TWI0": 0x08A0,
|
|
||||||
"SPI0": 0x08C0,
|
|
||||||
"TCA0": 0x0A00,
|
|
||||||
"TCB0": 0x0A80,
|
|
||||||
"TCB1": 0x0A90,
|
|
||||||
"SYSCFG": 0x0F00,
|
|
||||||
"NVMCTRL": 0x1000,
|
|
||||||
"SIGROW": 0x1100,
|
|
||||||
"FUSE": 0x1280,
|
|
||||||
"LOCK_BIT": 0x128A,
|
|
||||||
"USERROW": 0x1300,
|
|
||||||
"EEPROM": 0x1400,
|
|
||||||
}
|
|
||||||
|
|
||||||
def find_symbol(self, s):
|
|
||||||
try:
|
|
||||||
return int(s, self.num_base)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if s not in self.symbols:
|
|
||||||
if not self.elf_read:
|
|
||||||
self.read_elf()
|
|
||||||
return self.symbols[s]
|
|
||||||
|
|
||||||
elf = "bate.elf"
|
|
||||||
elf_read = False
|
|
||||||
|
|
||||||
def read_elf(self):
|
|
||||||
self.elf_read = True
|
|
||||||
import subprocess
|
|
||||||
r = subprocess.run(["/usr/bin/nm", self.elf], text=True, stdout=subprocess.PIPE)
|
|
||||||
for l in r.stdout.split("\n"):
|
|
||||||
ll = l.split()
|
|
||||||
if len(ll)==3 and ll[1] in "BD":
|
|
||||||
self.symbols[ll[2]] = int(ll[0], 16) & 0xffff
|
|
||||||
|
|
||||||
ADC_MODE = {"DIFF": 0x51, "NORM": 0xd1}
|
|
||||||
ADC_REF = {"VDD": 0x50, "1V": 0x54, "2V": 0x55, "2.5V": 0x56, "4V": 0x57}
|
|
||||||
ADC_INP = {"GND": 0x30, "VDD": 0x31, "TEMP": 0x32, "RFP": 4, "NTC": 6, "BAT": 7}
|
|
||||||
ADC_CONF = {
|
|
||||||
"mode": (0, 1, ADC_MODE),
|
|
||||||
"ref": (1, 1, ADC_REF),
|
|
||||||
"inp": (2, 1, ADC_INP),
|
|
||||||
"inn": (3, 1, ADC_INP),
|
|
||||||
"offset": (4, 1, {}),
|
|
||||||
"shifts": (5, 1, {}),
|
|
||||||
"calib": (6, 2, {}),
|
|
||||||
}
|
|
||||||
|
|
||||||
def adc_conf(self, reg, *a):
|
|
||||||
"1 [mode] NORM [ref] 1V [inp] NTC [inn] RFP"
|
|
||||||
n = int(reg, 0)
|
|
||||||
r = None
|
|
||||||
rr = self.ADC_CONF["mode"]
|
|
||||||
b = []
|
|
||||||
for aa in a:
|
|
||||||
print(aa,n,r,rr,b)
|
|
||||||
if aa in self.ADC_CONF:
|
|
||||||
r = self.ADC_CONF[aa]
|
|
||||||
if not b:
|
|
||||||
rr = r
|
|
||||||
elif r[0] != rr[0]+len(b):
|
|
||||||
raise ValueError(f"{aa} adc registers must be consecutive")
|
|
||||||
continue
|
|
||||||
if r is None:
|
|
||||||
for rrr in self.ADC_CONF.values():
|
|
||||||
if rrr[0] == rr[0]+len(b):
|
|
||||||
r = rrr
|
|
||||||
break
|
|
||||||
if r is None:
|
|
||||||
raise ValueError(f"{aa} adc register undefined")
|
|
||||||
try:
|
|
||||||
i = int(aa, self.num_base)
|
|
||||||
except:
|
|
||||||
i = r[2][aa]
|
|
||||||
b.append(i & 0xff)
|
|
||||||
if r[1] == 2:
|
|
||||||
b.append(i >> 8)
|
|
||||||
r = None
|
|
||||||
|
|
||||||
if not b:
|
|
||||||
a = self.symbols["EEPROM"] + 8*n + rr[0]
|
|
||||||
self.write(b'M%04x' % (a & 0xffff))
|
|
||||||
return
|
|
||||||
|
|
||||||
b[:0] = [0x9d, 8*n + rr[0]]
|
|
||||||
self.write(b'E' + b"".join([b"%02x" % (bb & 0xff) for bb in b]))
|
|
||||||
|
|
||||||
class ttycmd(turbocmd):
|
|
||||||
|
|
||||||
def open(self, path=None):
|
|
||||||
if path == '-':
|
|
||||||
path = None
|
|
||||||
self.path = path
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def write(self, m):
|
|
||||||
self.pace()
|
|
||||||
m = self.format(m)
|
|
||||||
if self.path:
|
|
||||||
with open(self.path, "wb") as f:
|
|
||||||
f.write(m)
|
|
||||||
else:
|
|
||||||
sys.stdout.write(m.decode())
|
|
||||||
|
|
||||||
def usage():
|
|
||||||
print(sys.argv[0], """{options} {args}
|
|
||||||
format and send commands to the turbo weather station
|
|
||||||
-h print this help
|
|
||||||
-q be quiet
|
|
||||||
-v be verbose, echo commands to stderr
|
|
||||||
-s «path» open tty or socket
|
|
||||||
-x args are hexadecimal
|
|
||||||
-b «base» args are in base «base»
|
|
||||||
-p prefix messages with newline
|
|
||||||
-d «delay» (float) seconds to wait between messages
|
|
||||||
-R reboot the µC
|
|
||||||
-K set clock
|
|
||||||
-M «addr» read a byte
|
|
||||||
-T «n» do «n» immediate triggers
|
|
||||||
-D «n» do «n» testdata triggers
|
|
||||||
-W «…» write a byte
|
|
||||||
-C «…» write config
|
|
||||||
-U «…» write userrow config
|
|
||||||
-E «…» write to EEPROM
|
|
||||||
-A «…» write/read ADC config in EEPROM
|
|
||||||
|
|
||||||
a single command option requiring args «…» must be last.
|
|
||||||
config write commands are limitted to eight bytes, including address and magic
|
|
||||||
|
|
||||||
-C «reg» [«value»|{«bits»}] …
|
|
||||||
-A «idx» «reg» «value» …
|
|
||||||
|
|
||||||
config registers may be numbers or symbols
|
|
||||||
config values may be symbolic «bits» or numbers
|
|
||||||
adc registers are lowercare symbols
|
|
||||||
adc values may be numbers or symbols
|
|
||||||
values must match the consecutive sequence of registers
|
|
||||||
redundant matching register names may be interleaved
|
|
||||||
a config bit symbol may refer to the following register
|
|
||||||
a config bit symbol may implicitly select the inital register
|
|
||||||
""", file=sys.stderr)
|
|
||||||
|
|
||||||
def main(argv):
|
|
||||||
|
|
||||||
import getopt
|
|
||||||
options, args = getopt.getopt(argv, "hxb:pvqs:d:RKC:U:E:M:W:T:D:A:")
|
|
||||||
path = None
|
|
||||||
for o,v in options:
|
|
||||||
if o=="-s":
|
|
||||||
path = v
|
|
||||||
if o=="-h":
|
|
||||||
usage()
|
|
||||||
return
|
|
||||||
if path == '-':
|
|
||||||
path = None
|
|
||||||
if path is None or path.startswith('/dev/tty'):
|
|
||||||
cmd = ttycmd(path)
|
|
||||||
else:
|
|
||||||
cmd = turbocmd(path)
|
|
||||||
last_cmd = None
|
|
||||||
last_args = []
|
|
||||||
for o,v in options:
|
|
||||||
if last_cmd:
|
|
||||||
raise ValueError(f"{o}: command option after long command")
|
|
||||||
if o=="-x":
|
|
||||||
cmd.num_base = 16
|
|
||||||
if o=="-b":
|
|
||||||
cmd.num_base = int(v)
|
|
||||||
if o=="-p":
|
|
||||||
cmd.bol = b'\n'
|
|
||||||
if o=="-q":
|
|
||||||
cmd.verbose = False
|
|
||||||
if o=="-v":
|
|
||||||
cmd.verbose = True
|
|
||||||
if o=="-d":
|
|
||||||
cmd.set_pace(float(v))
|
|
||||||
if o=="-K":
|
|
||||||
cmd.clock()
|
|
||||||
if o=="-C":
|
|
||||||
last_cmd = cmd.config
|
|
||||||
last_args = [b'C', 0xba]
|
|
||||||
if o=="-U":
|
|
||||||
last_cmd = cmd.config
|
|
||||||
last_args = [b'U', 0x9d]
|
|
||||||
if o=="-E":
|
|
||||||
last_cmd = cmd.config
|
|
||||||
last_args = [b'E', 0x9d]
|
|
||||||
if o=="-M":
|
|
||||||
cmd.mem(v, None)
|
|
||||||
if o=="-W":
|
|
||||||
last_cmd = cmd.mem
|
|
||||||
if o=="-R":
|
|
||||||
cmd.value(b'R', 0xd8)
|
|
||||||
if o=="-D":
|
|
||||||
cmd.value(b'D', v)
|
|
||||||
if o=="-T":
|
|
||||||
cmd.value(b'T', v)
|
|
||||||
if o=="-A":
|
|
||||||
last_cmd = cmd.adc_conf
|
|
||||||
|
|
||||||
if v and last_cmd:
|
|
||||||
last_args.append(v)
|
|
||||||
|
|
||||||
last_args.extend(args)
|
|
||||||
if last_cmd:
|
|
||||||
last_cmd(*last_args)
|
|
||||||
|
|
||||||
if __name__=="__main__":
|
|
||||||
main(sys.argv[1:])
|
|
||||||
|
|
@ -89,41 +89,22 @@ class cmder(cmd_socket):
|
||||||
raise ValueError("socket is not closed")
|
raise ValueError("socket is not closed")
|
||||||
self.s = socket.socket(socket.AF_UNIX)
|
self.s = socket.socket(socket.AF_UNIX)
|
||||||
self.s.connect(path)
|
self.s.connect(path)
|
||||||
self.path = path
|
|
||||||
|
|
||||||
eol = b'\n'
|
def write(self, m, eol=b'\n'):
|
||||||
bol = b''
|
|
||||||
verbose = True
|
|
||||||
|
|
||||||
def format(self, m):
|
|
||||||
if isinstance(m, str):
|
if isinstance(m, str):
|
||||||
m = m.encode()
|
m = m.encode()
|
||||||
if self.eol and m[-1:] != self.eol:
|
if eol and m[-1:] != eol:
|
||||||
m += self.eol
|
m += eol
|
||||||
if self.bol and m[:1] != self.bol:
|
self.s.send(m)
|
||||||
m = self.bol + m
|
|
||||||
if self.verbose:
|
|
||||||
print(f"{self.path}.send({m})", file=sys.stderr)
|
|
||||||
return m
|
|
||||||
|
|
||||||
def write(self, m):
|
|
||||||
self.pace()
|
|
||||||
m = self.format(m)
|
|
||||||
if self.s:
|
|
||||||
self.s.send(m)
|
|
||||||
|
|
||||||
def pace(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
import getopt, time
|
import getopt, time
|
||||||
options, messages = getopt.gnu_getopt(sys.argv[1:], "s:d:rfnN")
|
options, messages = getopt.gnu_getopt(sys.argv[1:], "s:d:rfn")
|
||||||
path = ()
|
path = ()
|
||||||
delay = 0.1
|
delay = 0.1
|
||||||
receiver = False
|
receiver = False
|
||||||
force = False
|
force = False
|
||||||
eol = b'\n'
|
eol = b'\n'
|
||||||
bol = None
|
|
||||||
for o,v in options:
|
for o,v in options:
|
||||||
if o=="-s":
|
if o=="-s":
|
||||||
path = (v,)
|
path = (v,)
|
||||||
|
|
@ -135,8 +116,6 @@ def main():
|
||||||
force = True
|
force = True
|
||||||
if o=="-n":
|
if o=="-n":
|
||||||
eol = None
|
eol = None
|
||||||
if o=="-N":
|
|
||||||
bol = b'\n'
|
|
||||||
|
|
||||||
if receiver:
|
if receiver:
|
||||||
s = cmd_receiver(*path, blocking=True, force=force)
|
s = cmd_receiver(*path, blocking=True, force=force)
|
||||||
|
|
@ -147,12 +126,10 @@ def main():
|
||||||
s.close()
|
s.close()
|
||||||
return
|
return
|
||||||
s = cmder(*path)
|
s = cmder(*path)
|
||||||
s.eol = eol
|
|
||||||
s.bol = bol
|
|
||||||
for m in messages:
|
for m in messages:
|
||||||
if delay:
|
if delay:
|
||||||
time.sleep(delay)
|
time.sleep(delay)
|
||||||
s.write(m)
|
s.write(m, eol)
|
||||||
|
|
||||||
if __name__=="__main__":
|
if __name__=="__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ command:
|
||||||
mov r18, r20
|
mov r18, r20
|
||||||
1:
|
1:
|
||||||
ld r22, X+
|
ld r22, X+
|
||||||
rcall send_char22
|
call send_char22
|
||||||
subi r18, 1
|
subi r18, 1
|
||||||
brne 1b
|
brne 1b
|
||||||
ldi r24, lo8(uart_rx)
|
ldi r24, lo8(uart_rx)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue