synth/mbv/prog.py
2025-06-25 08:39:33 -07:00

82 lines
1.8 KiB
Python

import argparse
import serial
import struct
import sys
import threading
import time
offset = 0x80000000
tty = "/dev/ttyUSB1"
baud = 115200
chunksize = 1024
def write(s, offset, dat):
for i in range(0, len(dat), chunksize):
chunk = dat[i : i + chunksize]
cmd = struct.pack("<cII", b"c", offset + i, len(chunk))
print(f"Sending {len(chunk)} bytes @0x{offset + i:04x}")
s.write(cmd)
s.write(chunk)
ack = s.read(2)
if len(ack) < 2:
raise RuntimeError(f"timeout waiting for full ack. got {ack}")
if ack[0] != b"a"[0]:
raise RuntimeError(f"expected ack, got this instead: {ack}")
print(f"Ack! len={ack[1]}")
def jump(s, offset):
cmd = struct.pack("<cI", b"j", offset)
print(f"Jumping to 0x{offset:04x}")
s.write(cmd)
def stream_logs(s):
while True:
dat = s.read()
if not dat:
continue
sys.stdout.buffer.write(dat.replace(b"\r", b""))
sys.stdout.buffer.flush()
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument("binary")
parser.add_argument(
"--monitor",
action="store_true",
help="wait for and display program serial output",
)
return parser.parse_args()
def main():
args = parse_args()
with open(args.binary, "rb") as f:
dat = f.read()
s = serial.Serial(tty, baud, timeout=1)
write(s, offset, dat)
jump(s, offset)
if args.monitor:
t = threading.Thread(target=lambda: stream_logs(s), daemon=True)
t.start()
try:
while True:
dat = input("") + "\r"
s.write(dat.encode())
except KeyboardInterrupt:
print("Bye.")
if __name__ == "__main__":
main()