From 2bbd44a8b5f9c3e08e0672ff2c2a3904747c14a3 Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Sun, 19 Jan 2025 21:40:26 +0100 Subject: [PATCH] Unphone improvements (#172) - Debounce nav button presses: This fixes multiple triggers on a single press to navigate back. Otherwise, more than 1 app would often close at the same time. - Nav button respond to release instead of push down, because these buttons aren't super reliable in general. (I might change this in the future after more testing) - Move single buzz earlier in boot phase, so that we can detect silent boot loops. --- Boards/UnPhone/Source/PowerOn.cpp | 18 ++++---- Boards/UnPhone/Source/UnPhoneFeatures.cpp | 51 +++++++++++++++-------- Documentation/ideas.md | 1 + 3 files changed, 43 insertions(+), 27 deletions(-) diff --git a/Boards/UnPhone/Source/PowerOn.cpp b/Boards/UnPhone/Source/PowerOn.cpp index 963cd068..64663250 100644 --- a/Boards/UnPhone/Source/PowerOn.cpp +++ b/Boards/UnPhone/Source/PowerOn.cpp @@ -64,24 +64,22 @@ static bool unPhonePowerOn() { unPhoneFeatures.printInfo(); + // Vibrate once + // Note: Do this before power switching logic, to detect silent boot loops + unPhoneFeatures.setVibePower(true); + tt::kernel::delayMillis(150); + unPhoneFeatures.setVibePower(false); + + // Turn off the device if power switch is on off state, + // instead of waiting for the Thread to start and continue booting updatePowerSwitch(); startPowerSwitchThread(); unPhoneFeatures.setBacklightPower(false); - - // Init touch screen GPIOs (used for vibe motor) unPhoneFeatures.setVibePower(false); - unPhoneFeatures.setIrPower(false); - - // This will be default LOW implicitly, but this makes it explicit unPhoneFeatures.setExpanderPower(false); - // Vibrate once - unPhoneFeatures.setVibePower(true); - tt::kernel::delayMillis(150); - unPhoneFeatures.setVibePower(false); - return true; } diff --git a/Boards/UnPhone/Source/UnPhoneFeatures.cpp b/Boards/UnPhone/Source/UnPhoneFeatures.cpp index 1f0d884c..1c7b899f 100644 --- a/Boards/UnPhone/Source/UnPhoneFeatures.cpp +++ b/Boards/UnPhone/Source/UnPhoneFeatures.cpp @@ -1,6 +1,7 @@ #include "UnPhoneFeatures.h" #include "FreeRTOS-Kernel/include/FreeRTOS.h" #include "Log.h" +#include "kernel/Kernel.h" #include "service/loader/Loader.h" #include #include @@ -39,10 +40,18 @@ static int32_t buttonHandlingThreadMain(void* context) { int pinNumber; while (!*interrupted) { if (xQueueReceive(interruptQueue, &pinNumber, portMAX_DELAY)) { + // The buttons might generate more than 1 click because of how they are built TT_LOG_I(TAG, "Pressed button %d", pinNumber); if (pinNumber == pin::BUTTON1) { tt::service::loader::stopApp(); } + + // Debounce all events for a short period of time + // This is easier than keeping track when each button was last pressed + tt::kernel::delayMillis(50); + xQueueReset(interruptQueue); + tt::kernel::delayMillis(50); + xQueueReset(interruptQueue); } } return 0; @@ -56,17 +65,15 @@ UnPhoneFeatures::~UnPhoneFeatures() { } bool UnPhoneFeatures::initPowerSwitch() { - uint64_t power_pin_mask = BIT64(pin::POWER_SWITCH); - - gpio_config_t power_gpio_config = { - .pin_bit_mask = power_pin_mask, + gpio_config_t config = { + .pin_bit_mask = BIT64(pin::POWER_SWITCH), .mode = GPIO_MODE_INPUT, .pull_up_en = GPIO_PULLUP_DISABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE, .intr_type = GPIO_INTR_POSEDGE, }; - if (gpio_config(&power_gpio_config) != ESP_OK) { + if (gpio_config(&config) != ESP_OK) { TT_LOG_E(TAG, "Power pin init failed"); return false; } @@ -81,6 +88,11 @@ bool UnPhoneFeatures::initPowerSwitch() { } bool UnPhoneFeatures::initNavButtons() { + if (!initGpioExpander()) { + TT_LOG_E(TAG, "GPIO expander init failed"); + return false; + } + interruptQueue = xQueueCreate(4, sizeof(int)); buttonHandlingThread.setName("unphone_buttons"); @@ -89,20 +101,25 @@ bool UnPhoneFeatures::initNavButtons() { buttonHandlingThread.setCallback(buttonHandlingThreadMain, &buttonHandlingThreadInterruptRequest); buttonHandlingThread.start(); - uint64_t input_pin_mask = + uint64_t pin_mask = BIT64(pin::BUTTON1) | BIT64(pin::BUTTON2) | BIT64(pin::BUTTON3); - gpio_config_t input_gpio_config = { - .pin_bit_mask = input_pin_mask, + gpio_config_t config = { + .pin_bit_mask = pin_mask, .mode = GPIO_MODE_INPUT, .pull_up_en = GPIO_PULLUP_ENABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_NEGEDGE, + /** + * We have to listen to the button release (= positive signal). + * If we listen to button press, the buttons might create more than 1 signal + * when they are continuously pressed. + */ + .intr_type = GPIO_INTR_POSEDGE, }; - if (gpio_config(&input_gpio_config) != ESP_OK) { + if (gpio_config(&config) != ESP_OK) { TT_LOG_E(TAG, "Nav button pin init failed"); return false; } @@ -125,7 +142,7 @@ bool UnPhoneFeatures::initOutputPins() { BIT64(pin::IR_LEDS) | BIT64(pin::LED_RED); - gpio_config_t output_gpio_config = { + gpio_config_t config = { .pin_bit_mask = output_pin_mask, .mode = GPIO_MODE_OUTPUT, .pull_up_en = GPIO_PULLUP_DISABLE, @@ -133,7 +150,7 @@ bool UnPhoneFeatures::initOutputPins() { .intr_type = GPIO_INTR_DISABLE, }; - if (gpio_config(&output_gpio_config) != ESP_OK) { + if (gpio_config(&config) != ESP_OK) { TT_LOG_E(TAG, "Output pin init failed"); return false; } @@ -165,6 +182,11 @@ bool UnPhoneFeatures::initGpioExpander() { bool UnPhoneFeatures::init() { TT_LOG_I(TAG, "init"); + if (!initGpioExpander()) { + TT_LOG_E(TAG, "GPIO expander init failed"); + return false; + } + if (!initNavButtons()) { TT_LOG_E(TAG, "Input pin init failed"); return false; @@ -180,11 +202,6 @@ bool UnPhoneFeatures::init() { return false; } - if (!initGpioExpander()) { - TT_LOG_E(TAG, "GPIO expander init failed"); - return false; - } - return true; } diff --git a/Documentation/ideas.md b/Documentation/ideas.md index b32d9b93..51690fcc 100644 --- a/Documentation/ideas.md +++ b/Documentation/ideas.md @@ -16,6 +16,7 @@ - Fix bug in T-Deck/etc: esp_lvgl_port settings has a large stack size (~9kB) to fix an issue where the T-Deck would get a stackoverflow. This sometimes happens when WiFi is auto-enabled and you open the app while it is still connecting. - M5Stack Core only shows 4MB of SPIRAM in use - Try to improve Core2 and CoreS3 performance by setting swap_bytes of display driver to false (this is a software operation on the display buffer!) and use 24 bit colour mode if needed +- Files app: When SD card is not mounted, don't show it # TODOs - Boards' CMakeLists.txt manually declare each source folder. Update them all to do a recursive search of all folders.