diff --git a/Core/Src/main.c b/Core/Src/main.c index ebc1c12..c984f02 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -101,13 +101,19 @@ void handle_menu(void *argument); /* USER CODE BEGIN 0 */ int run_snake = 0; int run_menu = 1; -int redraw_menu_pending; + #define RX_BUFFER_SIZE 1 #define LINE_BUFFER_SIZE 128 uint8_t rx_buffer[RX_BUFFER_SIZE]; char line_buffer[LINE_BUFFER_SIZE]; uint16_t line_pos = 0; + +//menu +int redraw_menu_pending; +#define GRID_X 2 +#define GRID_Y 3 +uint8_t menu_status[GRID_X][GRID_Y] = { 0 }; void process_line(const char *line) { if (strncmp(line, "ABS:", 4) == 0) { char axis[32]; @@ -128,18 +134,25 @@ void process_line(const char *line) { int state; if (sscanf(line, "KEY:%31[^:]:%d:", key, &state) == 2) { // Handle button press/release - char dir; - dir = key[0]; - osStatus_t status = osMessageQueuePut(pressesHandle, &dir, 0, 0); - if (status != osOK) { - // Optional: Handle error + + //we only care about presses + if (state) { + char dir; + dir = key[0]; + osStatus_t status = osMessageQueuePut(pressesHandle, &dir, 0, + 0); + + if (status != osOK) { + // Optional: Handle error + } } - if (key[0] == 'B' && state == 1) {// B goes to the menu + + if (key[0] == 'B' && state == 1) { // B goes to the menu run_snake = 0; run_menu = 1; - redraw_menu_pending=1; + redraw_menu_pending = 1; } - if (key[0] == 'Y' && state == 1) {// Y reboot + if (key[0] == 'Y' && state == 1) { // Y reboot } } @@ -736,8 +749,6 @@ void snakegame(void *argument) { * @param argument: Not used * @retval None */ -#define GRID_X 2 -#define GRID_Y 3 #define CELL_WIDTH 120 // Adjust as needed for your screen #define CELL_HEIGHT 40 @@ -747,6 +758,8 @@ void snakegame(void *argument) { #define COLOR_TEXT BLACK #define COLOR_BG WHITE #define COLOR_SELECTED GREEN +#define COLOR_ACTIVATED RED +#define COLOR_ACTIVATED_AND_SELECTED MAGENTA int sel_x; int sel_y; @@ -755,6 +768,7 @@ int sel_y; // Customize grid labels as needed const char *grid_labels[GRID_X][GRID_Y] = { { "Snake", "Options", "About" }, { "Highscore", "Credits", "Exit" } }; + void redraw_menu() { //only done onece saves resources // Redraw grid if (osMutexAcquire(displayHandle, osWaitForever) == osOK) { @@ -765,8 +779,25 @@ void redraw_menu() { //only done onece saves resources for (int j = 0; j < GRID_Y; j++) { uint16_t x = START_X + i * CELL_WIDTH; uint16_t y = START_Y + j * CELL_HEIGHT; - uint16_t bg = - (i == sel_x && j == sel_y) ? COLOR_SELECTED : COLOR_BG; + + uint16_t bg; + if (menu_status[i][j]) { + + if (i == sel_x && j == sel_y) { + bg = COLOR_ACTIVATED_AND_SELECTED; + } else { + bg = COLOR_ACTIVATED; + } + + } else { + if (i == sel_x && j == sel_y) { + bg = COLOR_SELECTED; + } else { + bg = COLOR_BG; + } + + } + if (osMutexAcquire(displayHandle, osWaitForever) == osOK) { ILI9341_DrawText(grid_labels[i][j], FONT2, x, y, COLOR_TEXT, bg); @@ -798,12 +829,20 @@ void handle_menu(void *argument) { run_snake = 1; run_menu = 0; } + menu_status[sel_x][sel_y] = !menu_status[sel_x][sel_y]; } if (dir == 'U' || dir == 'D' || dir == 'L' || dir == 'R') { - ILI9341_DrawText(grid_labels[sel_x][sel_y], FONT2, - START_X + sel_x * CELL_WIDTH, - START_Y + sel_y * CELL_HEIGHT, COLOR_TEXT, - COLOR_BG); + if (menu_status[sel_x][sel_y]) { + ILI9341_DrawText(grid_labels[sel_x][sel_y], FONT2, + START_X + sel_x * CELL_WIDTH, + START_Y + sel_y * CELL_HEIGHT, COLOR_TEXT, + COLOR_ACTIVATED); + } else { + ILI9341_DrawText(grid_labels[sel_x][sel_y], FONT2, + START_X + sel_x * CELL_WIDTH, + START_Y + sel_y * CELL_HEIGHT, COLOR_TEXT, + COLOR_BG); + } } if (dir == 'U' && sel_y > 0) sel_y--; @@ -814,10 +853,17 @@ void handle_menu(void *argument) { else if (dir == 'R' && sel_x < GRID_X - 1) sel_x++; } - ILI9341_DrawText(grid_labels[sel_x][sel_y], FONT2, - START_X + sel_x * CELL_WIDTH, START_Y + sel_y * CELL_HEIGHT, - COLOR_TEXT, - COLOR_SELECTED); + if (menu_status[sel_x][sel_y]) { + ILI9341_DrawText(grid_labels[sel_x][sel_y], FONT2, + START_X + sel_x * CELL_WIDTH, START_Y + sel_y * CELL_HEIGHT, + COLOR_TEXT, + COLOR_ACTIVATED_AND_SELECTED); + } else { + ILI9341_DrawText(grid_labels[sel_x][sel_y], FONT2, + START_X + sel_x * CELL_WIDTH, START_Y + sel_y * CELL_HEIGHT, + COLOR_TEXT, + COLOR_SELECTED); + } if (redraw_menu_pending) { redraw_menu(); redraw_menu_pending = 0; diff --git a/Core/Src/script.py b/Core/Src/script.py new file mode 100644 index 0000000..e3d0391 --- /dev/null +++ b/Core/Src/script.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +import evdev +from evdev import InputDevice, categorize, ecodes +import glob +import serial +import time +# Controller +#device_candidates = glob.glob('/dev/input/by-id/usb-8BitDo*-event*') +device_candidates = glob.glob('/dev/input/by-id/usb-8Bit*') +if not device_candidates: + print("Error: No matching 8BitDo input device found.") + sys.exit(1) + +device_path = device_candidates[0] +#device_path = '/dev/input/by-id/usb-8BitDo_8BitDo_Ultimate_Controller_6fdf5bd817e4-event-joystick' #or just put it in + +# UART +serial_port = '/dev/ttyUSB0' +baudrate = 115200 + + +device = InputDevice(device_path) +print(f"Listening on {device.name} ({device_path})") + +ser = serial.Serial(serial_port, baudrate, timeout=1) +print(f"UART opened on {serial_port} at {baudrate} bps") + +# diganostic time stamps +def timestamp_ms(): + return int(time.time() * 1000) + +import select + +button_map = { + 'BTN_SOUTH': 'B', + 'BTN_EAST': 'A', + 'BTN_NORTH': 'Y', + 'BTN_WEST': 'X', +} +try: + while True: + r, w, x = select.select([device.fd], [], [], 0.005) # timeout = 10ms + if device.fd in r: + for event in device.read(): + ts = timestamp_ms() + if event.type == ecodes.EV_KEY: + key_event = categorize(event) + k = key_event.keycode + if isinstance(k, tuple): + name = next((button_map[x] for x in k if x in button_map), str(k)) + else: + name = button_map.get(k, k) + + msg = f"KEY:{name}:{key_event.keystate}\n" + ser.write(msg.encode('utf-8')) + print(f"[{ts}] Sent: {msg.strip()}") + + elif event.type == ecodes.EV_ABS: + axis = ecodes.ABS.get(event.code, f"ABS_{event.code}") + val = event.value + if axis == 'ABS_HAT0Y' or axis == 'ABS_HAT0X': + if axis == 'ABS_HAT0Y': + if val == -1: + ser.write(b"KEY:U:1\r\n") + print(f"[{ts}] Sent: KEY:U:1:") + elif val == 1: + ser.write(b"KEY:D:1\r\n") + print(f"[{ts}] Sent: KEY:D:1:") + elif val == 0: + #ser.write(b"KEY:U:0\r\nKEY:D:0\r\n") + print(f"[{ts}] Sent: KEY:U:0\n[{ts}] Sent: KEY:D:0") + elif axis == 'ABS_HAT0X': + if val == -1: + ser.write(b"KEY:L:1\r\n") + print(f"[{ts}] Sent: KEY:L:1:") + elif val == 1: + ser.write(b"KEY:R:1\r\n") + print(f"[{ts}] Sent: KEY:R:1:") + elif val == 0: + #ser.write(b"KEY:L:0\r\nKEY:R:0\r\n") + print(f"[{ts}] Sent: KEY:L:0\n[{ts}] Sent: KEY:R:0") + else: + msg = f"ABS:{axis}:{event.value}:\r\n" + ser.write(msg.encode('utf-8')) + print(f"[{ts}] Sent: {msg.strip()}") + +except KeyboardInterrupt: + print("\nExiting...") + +finally: + ser.close() + print("UART closed.")