#!/usr/bin/env python3 # Simple GPIO control for AmebaPro3 boot/reset via ASCII commands over CDC-ACM. import argparse import time import serial from serial import SerialException from serial.tools import list_ports def boot_seq(port: str, baud: int): with serial.Serial(port=port, baudrate=baud, timeout=0.2) as ser: ser.write(b"BOOT 1\n") ser.flush() time.sleep(0.05) ser.write(b"RESET 0\n") ser.flush() time.sleep(0.02) ser.write(b"BOOT 0\n") ser.write(b"RESET 0\n") # keep reset asserted; caller can release later ser.flush() def reset_seq(port: str, baud: int): with serial.Serial(port=port, baudrate=baud, timeout=0.2) as ser: ser.write(b"BOOT 0\n") ser.write(b"RESET 1\n") ser.flush() time.sleep(0.05) ser.write(b"RESET 0\n") ser.flush() time.sleep(0.02) ser.write(b"RESET 1\n") ser.flush() def main(): p = argparse.ArgumentParser(description="Send BOOT/RESET GPIO commands to AmebaPro3 over CDC-ACM") p.add_argument('-p', '--port', required=True, help='Serial device, e.g., /dev/ttyACM0') p.add_argument('-B', '--baudrate', type=int, default=115200, help='Baudrate (only for opening port)') p.add_argument('--boot-seq', action='store_true', help='Drive boot entry sequence via BOOT/RESET commands') p.add_argument('--reset-seq', action='store_true', help='Drive reset sequence via BOOT/RESET commands') p.add_argument('--boot', choices=['0', '1'], help='Assert/deassert BOOT line (0=deassert,1=assert)') p.add_argument('--reset', choices=['0', '1'], help='Assert/deassert RESET line (0=deassert,1=assert)') p.add_argument('--list', action='store_true', help='List available serial ports and exit') args = p.parse_args() if args.list: for port in list_ports.comports(): print(f"{port.device}: {port.description}") return if args.boot_seq: try: boot_seq(args.port, args.baudrate) except SerialException as e: p.error(f"Open {args.port} failed: {e}. Is another program using the port?") return if args.reset_seq: try: reset_seq(args.port, args.baudrate) except SerialException as e: p.error(f"Open {args.port} failed: {e}. Is another program using the port?") return if args.boot is not None or args.reset is not None: try: with serial.Serial(port=args.port, baudrate=args.baudrate, timeout=0.2, rtscts=False, dsrdtr=False) as ser: if args.boot is not None: ser.write(f"BOOT {args.boot}\n".encode()) if args.reset is not None: ser.write(f"RESET {args.reset}\n".encode()) ser.flush() except SerialException as e: p.error(f"Open {args.port} failed: {e}. Is another program using the port?") return p.error("No action specified (use --boot-seq, --reset-seq, or --boot/--reset)") if __name__ == '__main__': main()