diff --git a/timeturner.py b/timeturner.py new file mode 100644 index 0000000..574f425 --- /dev/null +++ b/timeturner.py @@ -0,0 +1,75 @@ +import curses +import serial +import re +from datetime import datetime +import time + +# Configurable parameters +SERIAL_PORT = "/dev/ttyACM0" +BAUD_RATE = 115200 +REFRESH_INTERVAL = 0.5 # seconds + +# Regex to match LTC lines +ltc_pattern = re.compile( + r"\[(LOCK|FREE)\]\s+(\d{2}:\d{2}:\d{2}[:;]\d{2})\s+\|\s+([\d.]+fps)", re.IGNORECASE +) + +def read_ltc(ser): + """Reads and parses one line of LTC from the serial interface""" + try: + line = ser.readline().decode(errors='ignore').strip() + match = ltc_pattern.match(line) + if match: + status, timecode, framerate = match.groups() + return f"{status} {timecode} ({framerate.upper()})" + return None + except: + return None + +def draw_ui(stdscr): + curses.curs_set(0) # Hide cursor + stdscr.nodelay(True) + stdscr.timeout(int(REFRESH_INTERVAL * 1000)) + + # Open serial connection + try: + ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1) + except serial.SerialException as e: + stdscr.addstr(0, 0, f"[ERROR] Failed to open serial: {e}") + stdscr.getch() + return + + ltc_string = "Waiting for LTC…" + + while True: + try: + stdscr.clear() + + # Read LTC if available + new_ltc = read_ltc(ser) + if new_ltc: + ltc_string = new_ltc + + # Get system time + now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + + # Draw UI + stdscr.addstr(0, 0, "🕰️ NTP Timeturner v0.1") + stdscr.addstr(2, 0, f"LTC Timecode: {ltc_string}") + stdscr.addstr(3, 0, f"System Clock: {now}") + stdscr.addstr(5, 0, "Press Ctrl+C to quit.") + + stdscr.refresh() + time.sleep(REFRESH_INTERVAL) + + except KeyboardInterrupt: + break + except Exception as e: + stdscr.addstr(7, 0, f"[EXCEPTION] {e}") + stdscr.refresh() + time.sleep(1) + + ser.close() + +if __name__ == "__main__": + curses.wrapper(draw_ui)