mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
84 lines
2.8 KiB
Python
Executable file
84 lines
2.8 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
import argparse
|
|
import os
|
|
import select
|
|
import sys
|
|
import termios
|
|
import time
|
|
import tty
|
|
|
|
BAUD_FLAGS = {
|
|
9600: termios.B9600,
|
|
19200: termios.B19200,
|
|
38400: termios.B38400,
|
|
57600: termios.B57600,
|
|
115200: termios.B115200,
|
|
}
|
|
|
|
|
|
def configure(fd: int, baud: int) -> list[int]:
|
|
old = termios.tcgetattr(fd)
|
|
tty.setraw(fd)
|
|
attrs = termios.tcgetattr(fd)
|
|
baud_flag = BAUD_FLAGS[baud]
|
|
attrs[4] = baud_flag
|
|
attrs[5] = baud_flag
|
|
attrs[2] |= termios.CLOCAL | termios.CREAD
|
|
attrs[2] &= ~termios.CSTOPB
|
|
attrs[2] &= ~termios.PARENB
|
|
attrs[2] &= ~termios.CSIZE
|
|
attrs[2] |= termios.CS8
|
|
attrs[6][termios.VMIN] = 0
|
|
attrs[6][termios.VTIME] = 0
|
|
termios.tcsetattr(fd, termios.TCSANOW, attrs)
|
|
return old
|
|
|
|
|
|
def decode(byte: int) -> str:
|
|
tag = byte >> 4
|
|
payload = byte & 0x0F
|
|
if tag == 0x5:
|
|
return f"0x{byte:02x} tag=state state={payload}"
|
|
if tag == 0x6:
|
|
audio_mode = (payload >> 3) & 1
|
|
emit = (payload >> 2) & 1
|
|
handle_k = payload & 0x03
|
|
return f"0x{byte:02x} tag=meta mode={'audio' if audio_mode else 'manual'} emit={bool(emit)} handleK={handle_k}"
|
|
return f"0x{byte:02x} tag=0x{tag:x} low=0x{payload:x}"
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description="Monitor Tang Nano 9K Sparkle Phi/S3C UART telemetry.")
|
|
parser.add_argument("port", nargs="?", default="/dev/ttyUSB1")
|
|
parser.add_argument("--baud", type=int, default=115200, choices=sorted(BAUD_FLAGS))
|
|
parser.add_argument("--seconds", type=float, default=0.0, help="Stop after N seconds; 0 means run forever.")
|
|
parser.add_argument("--expect-state-tag", action="store_true", help="Fail unless state-tagged 0x5N frames arrive.")
|
|
parser.add_argument("--min-frames", type=int, default=1, help="Minimum expected frames when checking telemetry.")
|
|
args = parser.parse_args()
|
|
|
|
fd = os.open(args.port, os.O_RDONLY | os.O_NOCTTY | os.O_NONBLOCK)
|
|
old_attrs = configure(fd, args.baud)
|
|
deadline = None if args.seconds <= 0 else time.monotonic() + args.seconds
|
|
matched = 0
|
|
print(f"listening on {args.port} at {args.baud} baud; press the FPGA user button")
|
|
try:
|
|
while deadline is None or time.monotonic() < deadline:
|
|
ready, _, _ = select.select([fd], [], [], 0.25)
|
|
if not ready:
|
|
continue
|
|
data = os.read(fd, 256)
|
|
for byte in data:
|
|
if byte >> 4 == 0x5:
|
|
matched += 1
|
|
print(decode(byte), flush=True)
|
|
finally:
|
|
termios.tcsetattr(fd, termios.TCSANOW, old_attrs)
|
|
os.close(fd)
|
|
if args.expect_state_tag and matched < args.min_frames:
|
|
print(f"expected at least {args.min_frames} state-tag frame(s), saw {matched}", file=sys.stderr)
|
|
return 1
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|