From dd9c75d4f468318b8eac673d24bcfdc82d02e9e1 Mon Sep 17 00:00:00 2001 From: Jakub <106778416+MarekZegare4@users.noreply.github.com> Date: Wed, 27 May 2026 17:33:41 +0200 Subject: [PATCH] fix(ui/input): first melody note duration; OLED joystick reset UITask: when a key is pressed while the buzzer is playing, defer the next screen refresh by 300 ms instead of triggering it immediately (via _next_refresh = 100). The blocking e-ink endFrame() was extending the first note by the full refresh duration (~150-200 ms). Subsequent notes were unaffected because _next_refresh was already future-dated after the first render. DataStore: for builds where JOYSTICK_ROTATION is not defined and FEAT_JOYSTICK_ROTATION_SETTING is 0 (OLED), always reset joystick_rotation to 0 on prefs load. Without this, stale e-ink prefs (which allow changing joystick rotation in Settings) could silently leave a non-zero value that reversed all joystick directions on OLED. Co-Authored-By: Claude Sonnet 4.6 --- examples/companion_radio/DataStore.cpp | 8 ++++++++ examples/companion_radio/ui-new/UITask.cpp | 11 +++++++++++ 2 files changed, 19 insertions(+) diff --git a/examples/companion_radio/DataStore.cpp b/examples/companion_radio/DataStore.cpp index ec4de9b1..7a252552 100644 --- a/examples/companion_radio/DataStore.cpp +++ b/examples/companion_radio/DataStore.cpp @@ -211,6 +211,10 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no #endif #ifdef JOYSTICK_ROTATION _prefs.joystick_rotation = JOYSTICK_ROTATION; +#elif !FEAT_JOYSTICK_ROTATION_SETTING + // OLED: no rotation setting in UI — always reset to 0 so stale e-ink prefs + // (which could have a non-zero value) don't silently reverse the joystick. + _prefs.joystick_rotation = 0; #endif File file = openRead(_fs, filename); @@ -312,6 +316,8 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no rd(&_prefs.trail_interval_idx, sizeof(_prefs.trail_interval_idx)); rd(&_prefs.trail_min_delta_idx, sizeof(_prefs.trail_min_delta_idx)); rd(&_prefs.trail_units_idx, sizeof(_prefs.trail_units_idx)); + rd(&_prefs.ch_fav_bitmask, sizeof(_prefs.ch_fav_bitmask)); + rd(&_prefs.ch_fav_only, sizeof(_prefs.ch_fav_only)); // Schema sentinel: bumped on layout changes. Mismatch means an older file // (or a different schema); rd() already zero-inits any fields not present, @@ -417,6 +423,8 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_ file.write((uint8_t *)&_prefs.trail_interval_idx, sizeof(_prefs.trail_interval_idx)); file.write((uint8_t *)&_prefs.trail_min_delta_idx, sizeof(_prefs.trail_min_delta_idx)); file.write((uint8_t *)&_prefs.trail_units_idx, sizeof(_prefs.trail_units_idx)); + file.write((uint8_t *)&_prefs.ch_fav_bitmask, sizeof(_prefs.ch_fav_bitmask)); + file.write((uint8_t *)&_prefs.ch_fav_only, sizeof(_prefs.ch_fav_only)); // Tail sentinel — must be last. See NodePrefs::SCHEMA_SENTINEL. uint32_t sentinel = NodePrefs::SCHEMA_SENTINEL; diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index 21bb1f0c..2b9f4c30 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -1590,7 +1590,18 @@ void UITask::loop() { if (!_locked && curr) { curr->handleInput(c); { uint32_t aoff = autoOffMillis(); if (aoff > 0) _auto_off = millis() + aoff; } // extend auto-off timer +#ifdef PIN_BUZZER + if (buzzer.isPlaying()) { + // Keep the next render at least 300 ms away so the blocking e-ink endFrame() + // doesn't extend the current note. 300 ms covers the slowest note at 120 BPM (1/4). + unsigned long deadline = millis() + 300; + if (_next_refresh < deadline) _next_refresh = deadline; + } else { + _next_refresh = 100; // trigger refresh immediately + } +#else _next_refresh = 100; // trigger refresh +#endif } else if (_locked) { // Locked: eat all keys — wake window is set only when display first turns on _next_refresh = 0;