#!/usr/bin/env python3
"""
Nexys A7 FPGA UART Communication Script

This script sends 4 bytes over a USB-UART serial interface to the Nexys A7 board
and reads 8 bytes back from the board.

FPGA Board Pin Mapping Context (grounded in Nexys A7 Master XDC & UART Verilog module):
  - Received bytes on FPGA: Updates LED[15:8] (Pins V11..V16)
  - 4-Byte Hex Value display on FPGA: Shown on 7-Segment display DISP2 (AN[7:4]: Pins U13, K2, T14, P14)
  - Transmitted bytes from FPGA: Updates LED[7:0] (Pins U16..H17)
  - UART RX/TX Pins: UART_TXD_IN (C4), UART_RXD_OUT (D4)
"""

import serial
import time
import sys
import argparse

def main():
    parser = argparse.ArgumentParser(description="Nexys A7 FPGA UART Communication")
    parser.add_argument("--port", type=str, default="/dev/ttyUSB1", help="Serial port (e.g., /dev/ttyUSB1 or COM3)")
    parser.add_argument("--baud", type=int, default=115200, help="Baud rate (default: 115200)")
    parser.add_argument("--data", type=str, default="12345678", help="4 bytes in hex format (8 hex digits, e.g., '12345678' or 'DEADBEEF')")
    
    args = parser.parse_args()

    # Parse 4-byte payload from hex input
    try:
        tx_bytes = bytes.fromhex(args.data)
        if len(tx_bytes) != 4:
            raise ValueError("Input hex data must be exactly 4 bytes (8 hex characters).")
    except ValueError as e:
        print(f"Error parsing hex data: {e}")
        sys.exit(1)

    print(f"--- Nexys A7 FPGA UART Interface ---")
    print(f"Serial Port: {args.port}")
    print(f"Baud Rate:   {args.baud}")
    print(f"Sending 4 Bytes:   0x{tx_bytes.hex().upper()} {[f'0x{b:02X}' for b in tx_bytes]}")

    try:
        # Open serial port with timeout
        with serial.Serial(args.port, args.baud, timeout=2.0) as ser:
            ser.reset_input_buffer()
            ser.reset_output_buffer()
            time.sleep(0.1) # Brief stabilization delay

            # Step 1: Send 4 bytes to FPGA
            print("\n[1/2] Sending 4 bytes to FPGA...")
            #ser.write([3,2,3,4,4,5,6,7,4,5,6,7,8,9,3,4])
            print(tx_bytes)
            for i, byte in enumerate(tx_bytes, start=1):
                ser.write(bytes([byte]))
                ser.flush()
                print(f"  -> Byte {i}/4 sent: 0x{byte:02X} (FPGA updates LED[15:8])")
                time.sleep(0.05) # Small inter-byte delay for FPGA RX processing

            print("  -> All 4 bytes sent! (FPGA displays 32-bit hex value on 7-segment array DISP2 / AN[7:4])")

            # Step 2: Read 8 bytes from FPGA
            print("\n[2/2] Reading 8 bytes from FPGA...")
            rx_bytes = ser.read(8)

            if len(rx_bytes) == 8:
                print(f"  <- Received 8 Bytes: 0x{rx_bytes.hex().upper()} {[f'0x{b:02X}' for b in rx_bytes]}")
                print("  -> Each byte sent by FPGA updates LED[7:0].")
            else:
                print(f"  <- Timeout/Partial Read: Received {len(rx_bytes)}/8 bytes: 0x{rx_bytes.hex().upper()}")

    except serial.SerialException as e:
        print(f"\nSerial Communication Error: {e}")
        print("Tip: Check board connection and serial port permissions (e.g., sudo usermod -a -G dialout $USER).")
        sys.exit(1)

if __name__ == "__main__":
    main()
