#!/usr/bin/env python3 """Interactive UART console to the re-bba-rb board (FT2232H channel B). The BBA default build runs an interactive shell on this port ("rebbarb> "): help list commands udp broadcast [msg] send a UDP broadcast on the test socket udp unicast [msg] send a UDP datagram to The bring-up diagnostics (w5100_selftest / w5100_udptest / w5100_regdump) just stream a status line on the same port, so this works for those too. Usage: sudo ./scripts/uart-console.py # /dev/ttyUSB1 @ 115200 sudo ./scripts/uart-console.py /dev/ttyUSB0 115200 ./scripts/uart-console.py --send "udp broadcast hi" # one-shot, no tty ./scripts/uart-console.py --read 5 # just dump 5s of output Channel A of the FT2232H is the MPSSE/iceprog port; the UART is channel B, which is normally the SECOND ttyUSB (…USB1). Needs read/write on the device node — run under sudo, or add yourself to the port's group. Quit the interactive console with Ctrl-] (or Ctrl-C). """ import sys, time, argparse try: import serial except ImportError: sys.exit("needs pyserial: pip install pyserial") def main(): ap = argparse.ArgumentParser(add_help=True) ap.add_argument("port", nargs="?", default="/dev/ttyUSB1") ap.add_argument("baud", nargs="?", type=int, default=115200) ap.add_argument("--send", metavar="CMD", help="send one command, print the reply, exit") ap.add_argument("--read", metavar="SECONDS", type=float, help="just read for N seconds and exit (no tty needed)") args = ap.parse_args() try: ser = serial.Serial(args.port, args.baud, timeout=0.1) except serial.SerialException as e: sys.exit(f"cannot open {args.port}: {e}\n(try: sudo {' '.join(sys.argv)})") # ── one-shot modes (safe in scripts / no controlling terminal) ─────────── if args.read is not None: end = time.time() + args.read while time.time() < end: data = ser.read(256) if data: sys.stdout.write(data.decode("ascii", "replace")) sys.stdout.flush() return if args.send is not None: time.sleep(0.2); ser.reset_input_buffer() ser.write(args.send.encode() + b"\r") end = time.time() + 2.0 buf = b"" while time.time() < end: buf += ser.read(256) sys.stdout.write(buf.decode("ascii", "replace")) return # ── interactive console ───────────────────────────────────────────────── import termios, tty, select print(f"[uart-console] {args.port} @ {args.baud} 8N1 — Ctrl-] to quit\r") fd = sys.stdin.fileno() try: old = termios.tcgetattr(fd) except termios.error: old = None try: if old is not None: tty.setraw(fd) while True: r, _, _ = select.select([sys.stdin, ser], [], [], 0.05) if ser in r: data = ser.read(4096) if data: sys.stdout.write(data.decode("ascii", "replace")) sys.stdout.flush() if sys.stdin in r: ch = sys.stdin.buffer.read(1) if not ch or ch == b"\x1d": # Ctrl-] break if ch == b"\n": # send CR, the shell wants it ch = b"\r" ser.write(ch) except KeyboardInterrupt: pass finally: if old is not None: termios.tcsetattr(fd, termios.TCSADRAIN, old) ser.close() print("\r\n[uart-console] closed") if __name__ == "__main__": main()