From d9527ea3c5ab6f1e0776b86ecc43459eb1a706b2 Mon Sep 17 00:00:00 2001 From: David Phillips Date: Sat, 13 Mar 2021 20:03:55 +1300 Subject: First cut of UI state machine This patch adds a first skeleton/draft of the UI state machine, with the altimeter setting logic implemented at a basic level. It also adds a Python script which uses GDB/MI to simulate/inject UI events on a GDB remote (i.e. qemu-avr running the sim copy of the firmware). --- ui_remote.py | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100755 ui_remote.py (limited to 'ui_remote.py') diff --git a/ui_remote.py b/ui_remote.py new file mode 100755 index 0000000..e2cb584 --- /dev/null +++ b/ui_remote.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +# ui_remote.py - naive script to poke and prod the altimeter firmware over +# GDB/MI. Useful for rapid UI development/testing, all while probably not being +# strictly threadsafe. We're not triggering an ISR on the remote, so PC could +# already be in the middle of an ISR when we fire a UI event, which should +# never be allowed to happen in normal use. +# Useful nonetheless. +# +# FIXME allow smarter queueing of UI events in this script so they can be +# batched into the same (slow) interrupt-and-continue window. +# + +import atexit +import curses +import pygdbmi.gdbcontroller +import sys + + +def interrupt_run_continue(mi, command): + mi.write('interrupt') + mi.write(command) + mi.write('continue &') + + +def main(): + def curses_init(): + stdscr = curses.initscr() + curses.cbreak() + curses.noecho() + return stdscr + + def curses_end(): + curses.nocbreak() + stdscr.keypad(False) + curses.echo() + curses.endwin() + + # Give pygdbmi hardcoded GDB, ELF paths, remote. Good enough for now + mi = pygdbmi.gdbcontroller.GdbController( + command=["/usr/bin/avr-gdb", '--interpreter=mi3']) + mi.write('file build/altimeter_sim.elf', timeout_sec=5) + mi.write('target remote :1234') + mi.write('continue &') + + # atexit covers crash cases which is nice + atexit.register(curses_end) + stdscr = curses_init() + + stdscr.addstr(0, 0, "UI remote control via GDB. Press q to quit") + stdscr.addstr(1, 0, "w: up s: down a: hold d: short press") + running = True + while running: + stdscr.addstr(2, 0, "ready") + stdscr.clrtoeol() + key = stdscr.getch() + stdscr.addstr(2, 0, "busy") + stdscr.clrtoeol() + stdscr.refresh() + if key == ord('q'): + running = False + elif key == ord('w'): + interrupt_run_continue(mi, 'call up()') + pass + elif key == ord('s'): + interrupt_run_continue(mi, 'call down()') + pass + elif key == ord('a'): + interrupt_run_continue(mi, 'call hold()') + pass + elif key == ord('d'): + interrupt_run_continue(mi, 'call press()') + pass + else: + stdscr.addstr(1, 0, str(key)) + + +if __name__ == "__main__": + sys.exit(main()) -- cgit v1.1