From ce5cb322bae46f6186634e34d091f08c15918f8a Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Mon, 2 Mar 2026 16:30:46 +0000 Subject: [PATCH 1/3] pico: rework input drivers to allow using multiple at once --- 32blit-pico/CMakeLists.txt | 11 +++++++++- 32blit-pico/board-config.cmake | 5 +---- 32blit-pico/input.cpp | 38 ++++++++++++++++++++++++++++++++++ 32blit-pico/input.hpp | 9 ++++++++ 32blit-pico/input/gpio.cpp | 12 +++++------ 32blit-pico/input/none.cpp | 7 ------- 32blit-pico/input/tca9555.cpp | 12 +++++------ 32blit-pico/input/usb_hid.cpp | 20 ++++++++---------- 8 files changed, 79 insertions(+), 35 deletions(-) create mode 100644 32blit-pico/input.cpp delete mode 100644 32blit-pico/input/none.cpp diff --git a/32blit-pico/CMakeLists.txt b/32blit-pico/CMakeLists.txt index eee1ed6c3..ddcc4abb1 100644 --- a/32blit-pico/CMakeLists.txt +++ b/32blit-pico/CMakeLists.txt @@ -14,6 +14,7 @@ target_sources(BlitHalPico INTERFACE ${CMAKE_CURRENT_LIST_DIR}/blit_launch.cpp ${CMAKE_CURRENT_LIST_DIR}/display.cpp ${CMAKE_CURRENT_LIST_DIR}/file.cpp + ${CMAKE_CURRENT_LIST_DIR}/input.cpp ${CMAKE_CURRENT_LIST_DIR}/main.cpp ${CMAKE_CURRENT_LIST_DIR}/multiplayer.cpp ${CMAKE_CURRENT_LIST_DIR}/overlay.cpp @@ -54,10 +55,13 @@ if(BLIT_DISPLAY_DRIVER STREQUAL "picovision") endif() # driver sources +list(TRANSFORM BLIT_INPUT_DRIVER PREPEND ${CMAKE_CURRENT_LIST_DIR}/input/ OUTPUT_VARIABLE INPUT_SOURCES) +list(TRANSFORM INPUT_SOURCES APPEND .cpp) + target_sources(BlitHalPico INTERFACE ${CMAKE_CURRENT_LIST_DIR}/audio/${BLIT_AUDIO_DRIVER}.cpp ${CMAKE_CURRENT_LIST_DIR}/display/${BLIT_DISPLAY_DRIVER}.cpp - ${CMAKE_CURRENT_LIST_DIR}/input/${BLIT_INPUT_DRIVER}.cpp + ${INPUT_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/led/${BLIT_LED_DRIVER}.cpp ${CMAKE_CURRENT_LIST_DIR}/storage/${BLIT_STORAGE_DRIVER}.cpp ${CMAKE_CURRENT_LIST_DIR}/usb/${BLIT_USB_DRIVER}.cpp @@ -69,6 +73,11 @@ if(PICO_BOARD STREQUAL "pimoroni_tufty2350") target_sources(BlitHalPico INTERFACE ${CMAKE_CURRENT_LIST_DIR}/board/pimoroni_tufty2350/powman.c) endif() +# BLIT_INPUT_XXX=1 defines +list(TRANSFORM BLIT_INPUT_DRIVER TOUPPER OUTPUT_VARIABLE INPUT_DEFINES) +list(TRANSFORM INPUT_DEFINES PREPEND BLIT_INPUT_) +target_compile_definitions(BlitHalPico INTERFACE ${INPUT_DEFINES}) + if(BLIT_ENABLE_CORE1) list(APPEND BLIT_BOARD_DEFINITIONS ENABLE_CORE1) endif() diff --git a/32blit-pico/board-config.cmake b/32blit-pico/board-config.cmake index 2709a9565..f5d7908e5 100644 --- a/32blit-pico/board-config.cmake +++ b/32blit-pico/board-config.cmake @@ -46,9 +46,6 @@ endif() if(NOT BLIT_DISPLAY_DRIVER) set(BLIT_DISPLAY_DRIVER "none") endif() -if(NOT BLIT_INPUT_DRIVER) - set(BLIT_INPUT_DRIVER "none") -endif() if(NOT BLIT_LED_DRIVER) set(BLIT_LED_DRIVER "none") endif() @@ -73,7 +70,7 @@ elseif(BLIT_DISPLAY_DRIVER STREQUAL "scanvideo") list(APPEND BLIT_BOARD_LIBRARIES pico_scanvideo_dpi) endif() -if(BLIT_INPUT_DRIVER STREQUAL "usb_hid") +if("usb_hid" IN_LIST BLIT_INPUT_DRIVER) list(APPEND BLIT_BOARD_DEFINITIONS INPUT_USB_HID) endif() diff --git a/32blit-pico/input.cpp b/32blit-pico/input.cpp new file mode 100644 index 000000000..5c2b172a6 --- /dev/null +++ b/32blit-pico/input.cpp @@ -0,0 +1,38 @@ +#include + +#include "input.hpp" + +#include "engine/api_private.hpp" + +extern const InputDriver gpio_input_driver; +extern const InputDriver tca9555_driver; +extern const InputDriver usb_hid_driver; + +static const InputDriver *input_drivers[] { +#ifdef BLIT_INPUT_GPIO + &gpio_input_driver, +#endif +#ifdef BLIT_INPUT_TCA9555 + &tca9555_driver, +#endif +#ifdef BLIT_INPUT_USB_HID + &usb_hid_driver, +#endif +}; +static constexpr unsigned num_input_drivers = sizeof(input_drivers) / sizeof(input_drivers[0]); + +void init_input() { + for(unsigned i = 0; i < num_input_drivers; i++) + input_drivers[i]->init(); +} + +void update_input() { + uint32_t new_buttons = 0; + blit::Vec2 new_joystick; + + for(unsigned i = 0; i < num_input_drivers; i++) + input_drivers[i]->update(new_buttons, new_joystick); + + blit::api_data.buttons = new_buttons; + blit::api_data.joystick = new_joystick; +} diff --git a/32blit-pico/input.hpp b/32blit-pico/input.hpp index 1970e367c..5afbad12a 100644 --- a/32blit-pico/input.hpp +++ b/32blit-pico/input.hpp @@ -1,4 +1,13 @@ #pragma once +#include + +#include "types/vec2.hpp" + +struct InputDriver { + void (*init)(); + void (*update)(uint32_t &, blit::Vec2 &); +}; + void init_input(); void update_input(); diff --git a/32blit-pico/input/gpio.cpp b/32blit-pico/input/gpio.cpp index 12ddd99ec..b56a7ef62 100644 --- a/32blit-pico/input/gpio.cpp +++ b/32blit-pico/input/gpio.cpp @@ -52,7 +52,7 @@ static void init_button(int pin, bool active_high) { gpio_pull_up(pin); } -void init_input() { +void init_gpio_input() { for(size_t i = 0; i < std::size(button_io); i++) init_button(button_io[i], button_active[i]); @@ -72,11 +72,9 @@ void init_input() { #undef BUTTON_BI_DECL } -void update_input() { +void update_gpio_input(uint32_t &new_buttons, blit::Vec2 &new_joystick) { auto io = gpio_get_all(); - uint32_t new_buttons = 0; - for(size_t i = 0; i < std::size(button_io); i++) { // pin not defined, skip if(button_io[i] == -1) @@ -87,6 +85,8 @@ void update_input() { if(pin_state == button_active[i]) new_buttons |= 1 << i; } - - blit::api_data.buttons = new_buttons; } + +extern const InputDriver gpio_input_driver { + init_gpio_input, update_gpio_input +}; diff --git a/32blit-pico/input/none.cpp b/32blit-pico/input/none.cpp deleted file mode 100644 index 98e405714..000000000 --- a/32blit-pico/input/none.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "input.hpp" - -void init_input() { -} - -void update_input() { -} diff --git a/32blit-pico/input/tca9555.cpp b/32blit-pico/input/tca9555.cpp index 43349ef0c..b3545d817 100644 --- a/32blit-pico/input/tca9555.cpp +++ b/32blit-pico/input/tca9555.cpp @@ -32,13 +32,13 @@ static bool tca9555_found = false; -void init_input() { +void init_tca9555() { // setup for reading uint8_t port = 0; tca9555_found = i2c_write_timeout_us(TCA9555_I2C, TCA9555_ADDR, &port, 1, false, 1000) == 1; } -void update_input() { +void update_tca9555(uint32_t &new_buttons, blit::Vec2 &new_joystick) { if(!tca9555_found) return; @@ -46,8 +46,6 @@ void update_input() { i2c_read_blocking(TCA9555_I2C, TCA9555_ADDR, (uint8_t *)&gpio, 2, false); - uint32_t new_buttons = 0; - if(!(gpio & (1 << TCA9555_LEFT_IO))) new_buttons |= blit::Button::DPAD_LEFT; @@ -77,6 +75,8 @@ void update_input() { if(!(gpio & (1 << TCA9555_SELECT_IO))) new_buttons |= blit::Button::MENU; - - blit::api_data.buttons = new_buttons; } + +extern const InputDriver tca9555_driver { + init_tca9555, update_tca9555 +}; diff --git a/32blit-pico/input/usb_hid.cpp b/32blit-pico/input/usb_hid.cpp index 0ebc2d7dd..956c30093 100644 --- a/32blit-pico/input/usb_hid.cpp +++ b/32blit-pico/input/usb_hid.cpp @@ -49,18 +49,14 @@ const uint32_t dpad_map[]{ 0 }; -void init_input() { +void init_usb_hid() { } -void update_input() { +void update_usb_hid(uint32_t &new_buttons, blit::Vec2 &new_joystick) { using namespace blit; - if(!hid_keyboard_detected && !hid_gamepad_id) { - blit::api_data.buttons = 0; + if(!hid_keyboard_detected && !hid_gamepad_id) return; - } - - uint32_t new_buttons = 0; // keyboard if(hid_keyboard_detected) { @@ -139,8 +135,10 @@ void update_input() { | (hid_buttons & (1 << mapping->home) ? uint32_t(Button::HOME) : 0) | (hid_buttons & (1 << mapping->joystick) ? uint32_t(Button::JOYSTICK) : 0); - api_data.buttons = new_buttons; - - api_data.joystick.x = (float(hid_joystick[0]) - 0x80) / 0x80; - api_data.joystick.y = (float(hid_joystick[1]) - 0x80) / 0x80; + new_joystick.x = (float(hid_joystick[0]) - 0x80) / 0x80; + new_joystick.y = (float(hid_joystick[1]) - 0x80) / 0x80; } + +extern const InputDriver usb_hid_driver { + init_usb_hid, update_usb_hid +}; From 3e76f03ed4aca043aa9d2fe4973226fd90a5b9a6 Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Sun, 8 Mar 2026 17:31:56 +0000 Subject: [PATCH 2/3] pico: reset tca9555 address if read fails This allows surviving a temporary disconnect --- 32blit-pico/input/tca9555.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/32blit-pico/input/tca9555.cpp b/32blit-pico/input/tca9555.cpp index b3545d817..da6eb28f3 100644 --- a/32blit-pico/input/tca9555.cpp +++ b/32blit-pico/input/tca9555.cpp @@ -44,7 +44,12 @@ void update_tca9555(uint32_t &new_buttons, blit::Vec2 &new_joystick) { uint16_t gpio = 0xFFFF; - i2c_read_blocking(TCA9555_I2C, TCA9555_ADDR, (uint8_t *)&gpio, 2, false); + if(i2c_read_blocking(TCA9555_I2C, TCA9555_ADDR, (uint8_t *)&gpio, 2, false) != 2) { + // attempt to reset the address if read fails + uint8_t port = 0; + i2c_write_timeout_us(TCA9555_I2C, TCA9555_ADDR, &port, 1, false, 1000); + return; // will try again next time + } if(!(gpio & (1 << TCA9555_LEFT_IO))) new_buttons |= blit::Button::DPAD_LEFT; From f6e96202eaad5c0f53c4814ba895bd36a1e312c7 Mon Sep 17 00:00:00 2001 From: Charlie Birks Date: Mon, 9 Mar 2026 12:35:41 +0000 Subject: [PATCH 3/3] pico: enable tca9555 driver for Tufty 2350 --- 32blit-pico/board/pimoroni_tufty2350/config.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/32blit-pico/board/pimoroni_tufty2350/config.cmake b/32blit-pico/board/pimoroni_tufty2350/config.cmake index 8f06250a4..31c642706 100644 --- a/32blit-pico/board/pimoroni_tufty2350/config.cmake +++ b/32blit-pico/board/pimoroni_tufty2350/config.cmake @@ -1,5 +1,5 @@ set(BLIT_BOARD_NAME "Tufty 2350") blit_driver(display dbi) -blit_driver(input gpio) +blit_driver(input "gpio;tca9555") blit_driver(led pwm_mono)