From a4b4362b1b1ebdebfabb12059d41d9d8133c0f5a Mon Sep 17 00:00:00 2001 From: Jakub <106778416+MarekZegare4@users.noreply.github.com> Date: Sun, 24 May 2026 22:26:56 +0200 Subject: [PATCH] refactor(prefs): centralise home-page bit numbering in NodePrefs::HomePageBit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pageBit/bitToPage in HomeScreen and homePageBitIndex in SettingsScreen each spelled out the bit assignment with magic numbers 0..10. Lift the numbering into a NodePrefs::HomePageBit enum (HPB_CLOCK … HPB_QUICK_MSG, HPB_COUNT) and route every reference through it: mapping functions, the HP_* bitmasks, the homePageLabel table sizing, loop bounds over page_order, the bounds check on page_order[0], the "always-visible" discriminator for SETTINGS/QUICK_MSG. Per-class enums (HomeScreen::HomePage, SettingsScreen::SettingItem) stay — they index different concerns (navigation page vs. settings row). The mapping functions still exist, but now reference a single source of truth for the bit values. Co-Authored-By: Claude Sonnet 4.6 --- examples/companion_radio/DataStore.cpp | 2 +- examples/companion_radio/NodePrefs.h | 52 ++++++++++++------ .../companion_radio/ui-new/SettingsScreen.h | 45 ++++++++-------- examples/companion_radio/ui-new/UITask.cpp | 54 +++++++++---------- 4 files changed, 86 insertions(+), 67 deletions(-) diff --git a/examples/companion_radio/DataStore.cpp b/examples/companion_radio/DataStore.cpp index a1a5d4ee..5e71af8d 100644 --- a/examples/companion_radio/DataStore.cpp +++ b/examples/companion_radio/DataStore.cpp @@ -300,7 +300,7 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no // Migration: pre-magic firmware wrote page_order without a flag. If we see a plausible // first entry from such a save, accept it once — savePrefs will then persist the magic. if (_prefs.page_order_set != NodePrefs::PAGE_ORDER_MAGIC - && _prefs.page_order[0] >= 1 && _prefs.page_order[0] <= 11) { + && _prefs.page_order[0] >= 1 && _prefs.page_order[0] <= NodePrefs::HPB_COUNT) { _prefs.page_order_set = NodePrefs::PAGE_ORDER_MAGIC; } diff --git a/examples/companion_radio/NodePrefs.h b/examples/companion_radio/NodePrefs.h index 88f0e2d1..6d17c2ed 100644 --- a/examples/companion_radio/NodePrefs.h +++ b/examples/companion_radio/NodePrefs.h @@ -81,9 +81,11 @@ struct NodePrefs { // persisted to file DmMelodyEntry dm_melody[DM_MELODY_TABLE_MAX]; uint8_t use_lemon_font; // 0=default Adafruit font, 1=Lemon font (Unicode, pixel-accurate wrap) uint8_t display_rotation; // 0-3; only used on e-ink displays - // Home screen page order: each byte = bit-index+1 (see HP_* bit positions + 9=Settings, 10=Messages). - // 0 = end of list. Validity gated by page_order_set magic (see below) — not by entry value range, - // so a junk byte in 1..11 cannot trigger custom-order mode. + // Home screen page order: each byte = HomePageBit + 1. 0 terminates the list. + // Validity gated by page_order_set magic (see below) — not by entry value range, + // so a junk byte in 1..HPB_COUNT cannot trigger custom-order mode. + // (Array length = HPB_COUNT, declared as literal so the field offset is stable + // across builds that add new HomePageBit entries.) uint8_t page_order[11]; uint8_t joystick_rotation; // 0-3 steps CW; independent of display_rotation uint8_t eink_full_refresh_every; // index into {0,5,10,20,30}: full refresh every N partials (0=off) @@ -96,25 +98,45 @@ struct NodePrefs { // persisted to file // High 24 bits identify the file format; low byte is the schema revision. static const uint32_t SCHEMA_SENTINEL = 0xC0DE0001; + // Bit-index for each home page. Used by page_order (entries store bit+1) and + // by home_pages_mask. Single source of truth — both HomeScreen::pageBit/bitToPage + // and SettingsScreen::homePageBitIndex route their per-enum lookups through these. + enum HomePageBit : uint8_t { + HPB_CLOCK = 0, + HPB_RECENT = 1, + HPB_RADIO = 2, + HPB_BLUETOOTH = 3, + HPB_ADVERT = 4, + HPB_GPS = 5, + HPB_SENSORS = 6, + HPB_TOOLS = 7, + HPB_SHUTDOWN = 8, + HPB_SETTINGS = 9, + HPB_QUICK_MSG = 10, + HPB_COUNT = 11, + }; + // Bitmasks for home_pages_mask (bit=1 → page visible; 0 field = all visible). - static const uint16_t HP_CLOCK = 1 << 0; - static const uint16_t HP_RECENT = 1 << 1; - static const uint16_t HP_RADIO = 1 << 2; - static const uint16_t HP_BLUETOOTH = 1 << 3; - static const uint16_t HP_ADVERT = 1 << 4; - static const uint16_t HP_GPS = 1 << 5; - static const uint16_t HP_SENSORS = 1 << 6; - static const uint16_t HP_TOOLS = 1 << 7; - static const uint16_t HP_SHUTDOWN = 1 << 8; + // SETTINGS and QUICK_MSG have no mask bit — they're always visible. + static const uint16_t HP_CLOCK = 1 << HPB_CLOCK; + static const uint16_t HP_RECENT = 1 << HPB_RECENT; + static const uint16_t HP_RADIO = 1 << HPB_RADIO; + static const uint16_t HP_BLUETOOTH = 1 << HPB_BLUETOOTH; + static const uint16_t HP_ADVERT = 1 << HPB_ADVERT; + static const uint16_t HP_GPS = 1 << HPB_GPS; + static const uint16_t HP_SENSORS = 1 << HPB_SENSORS; + static const uint16_t HP_TOOLS = 1 << HPB_TOOLS; + static const uint16_t HP_SHUTDOWN = 1 << HPB_SHUTDOWN; static const uint16_t HP_ALL = 0x01FF; - // Label for home page by bit-index (0–10); returns "" for out-of-range. + // Label for home page by bit-index; returns "" for out-of-range. + // Array indices match HomePageBit values. static const char* homePageLabel(uint8_t bit) { - static const char* labels[] = { + static const char* labels[HPB_COUNT] = { "Clock", "Recent", "Radio", "Bluetooth", "Advert", "GPS", "Sensors", "Tools", "Shutdown", "Settings", "Messages" }; - return (bit < 11) ? labels[bit] : ""; + return (bit < HPB_COUNT) ? labels[bit] : ""; } static void buildRTTTLString(const uint8_t* notes, uint8_t len, uint8_t bpm_idx, diff --git a/examples/companion_radio/ui-new/SettingsScreen.h b/examples/companion_radio/ui-new/SettingsScreen.h index 6705c77b..623dbd9b 100644 --- a/examples/companion_radio/ui-new/SettingsScreen.h +++ b/examples/companion_radio/ui-new/SettingsScreen.h @@ -178,12 +178,14 @@ class SettingsScreen : public UIScreen { uint16_t homePageBit(int item) const { int bit = homePageBitIndex(item); - return (bit >= 0 && bit < 9) ? (uint16_t)(1 << bit) : 0; + // Bits 0..HPB_SHUTDOWN have mask bits in home_pages_mask; SETTINGS and + // QUICK_MSG are always visible (no mask bit) and return 0. + return (bit >= 0 && bit < NodePrefs::HPB_SETTINGS) ? (uint16_t)(1 << bit) : 0; } const char* homePageLabel(int item) const { int bit = homePageBitIndex(item); - return NodePrefs::homePageLabel((uint8_t)(bit >= 0 ? bit : 11)); + return NodePrefs::homePageLabel((uint8_t)(bit >= 0 ? bit : NodePrefs::HPB_COUNT)); } bool homePageVisible(int item, const NodePrefs* p) const { @@ -198,23 +200,24 @@ class SettingsScreen : public UIScreen { return item != HOME_SETTINGS && item != HOME_QUICK_MSG; } - // Returns the bit-index (0-10) used in page_order for this SettingItem, or -1. + // Returns the bit-index used in page_order for this SettingItem, or -1. + // Bit-index values are defined once in NodePrefs::HomePageBit. int homePageBitIndex(int item) const { - if (item == HOME_CLOCK) return 0; - if (item == HOME_RECENT) return 1; - if (item == HOME_RADIO) return 2; - if (item == HOME_BT) return 3; - if (item == HOME_ADVERT) return 4; + if (item == HOME_CLOCK) return NodePrefs::HPB_CLOCK; + if (item == HOME_RECENT) return NodePrefs::HPB_RECENT; + if (item == HOME_RADIO) return NodePrefs::HPB_RADIO; + if (item == HOME_BT) return NodePrefs::HPB_BLUETOOTH; + if (item == HOME_ADVERT) return NodePrefs::HPB_ADVERT; #if ENV_INCLUDE_GPS == 1 - if (item == HOME_GPS) return 5; + if (item == HOME_GPS) return NodePrefs::HPB_GPS; #endif #if UI_SENSORS_PAGE == 1 - if (item == HOME_SENSORS) return 6; + if (item == HOME_SENSORS) return NodePrefs::HPB_SENSORS; #endif - if (item == HOME_TOOLS) return 7; - if (item == HOME_SHUTDOWN) return 8; - if (item == HOME_SETTINGS) return 9; - if (item == HOME_QUICK_MSG) return 10; + if (item == HOME_TOOLS) return NodePrefs::HPB_TOOLS; + if (item == HOME_SHUTDOWN) return NodePrefs::HPB_SHUTDOWN; + if (item == HOME_SETTINGS) return NodePrefs::HPB_SETTINGS; + if (item == HOME_QUICK_MSG) return NodePrefs::HPB_QUICK_MSG; return -1; } @@ -223,9 +226,9 @@ class SettingsScreen : public UIScreen { if (!p || p->page_order_set != NodePrefs::PAGE_ORDER_MAGIC) return 0; int bit = homePageBitIndex(item); if (bit < 0) return 0; - for (int i = 0; i < 11; i++) { + for (int i = 0; i < NodePrefs::HPB_COUNT; i++) { uint8_t v = p->page_order[i]; - if (v < 1 || v > 11) break; + if (v < 1 || v > NodePrefs::HPB_COUNT) break; if ((int)(v - 1) == bit) return i + 1; } return 0; @@ -237,9 +240,9 @@ class SettingsScreen : public UIScreen { if (!p) return; if (p->page_order_set == NodePrefs::PAGE_ORDER_MAGIC) { // Order was previously set — verify CLOCK is present to guard against partial/corrupted data. - for (int i = 0; i < 11; i++) { + for (int i = 0; i < NodePrefs::HPB_COUNT; i++) { uint8_t v = p->page_order[i]; - if (v < 1 || v > 11) break; + if (v < 1 || v > NodePrefs::HPB_COUNT) break; if (v == 0 + 1) return; // CLOCK found, order is intact } // CLOCK missing — reset and fall through to full re-init. @@ -262,7 +265,7 @@ class SettingsScreen : public UIScreen { p->page_order[j++] = 7 + 1; // TOOLS p->page_order[j++] = 10 + 1; // MESSAGES (QUICK_MSG) p->page_order[j++] = 8 + 1; // SHUTDOWN - while (j < 11) p->page_order[j++] = 0; + while (j < NodePrefs::HPB_COUNT) p->page_order[j++] = 0; p->page_order_set = NodePrefs::PAGE_ORDER_MAGIC; } @@ -272,9 +275,9 @@ class SettingsScreen : public UIScreen { int bit = homePageBitIndex(item); if (bit < 0) return; int cur = -1, total = 0; - for (int i = 0; i < 11; i++) { + for (int i = 0; i < NodePrefs::HPB_COUNT; i++) { uint8_t v = p->page_order[i]; - if (v < 1 || v > 11) break; + if (v < 1 || v > NodePrefs::HPB_COUNT) break; if ((int)(v - 1) == bit) cur = i; total++; } diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index dcbc4792..425d7bb1 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -148,47 +148,41 @@ class HomeScreen : public UIScreen { AdvertPath recent[UI_RECENT_LIST_SIZE]; int pageBit(int page) const { - if (page == CLOCK) return 0; - if (page == RECENT) return 1; - if (page == RADIO) return 2; - if (page == BLUETOOTH) return 3; - if (page == ADVERT) return 4; + if (page == CLOCK) return NodePrefs::HPB_CLOCK; + if (page == RECENT) return NodePrefs::HPB_RECENT; + if (page == RADIO) return NodePrefs::HPB_RADIO; + if (page == BLUETOOTH) return NodePrefs::HPB_BLUETOOTH; + if (page == ADVERT) return NodePrefs::HPB_ADVERT; #if ENV_INCLUDE_GPS == 1 - if (page == GPS) return 5; + if (page == GPS) return NodePrefs::HPB_GPS; #endif #if UI_SENSORS_PAGE == 1 - if (page == SENSORS) return 6; + if (page == SENSORS) return NodePrefs::HPB_SENSORS; #endif - if (page == TOOLS) return 7; - if (page == SHUTDOWN) return 8; - return -1; // SETTINGS, QUICK_MSG always visible + if (page == TOOLS) return NodePrefs::HPB_TOOLS; + if (page == SHUTDOWN) return NodePrefs::HPB_SHUTDOWN; + return -1; // SETTINGS, QUICK_MSG always visible (no mask bit) } - // Maps page_order bit-index (0-10) back to the HomePage enum value for this build. + // Maps page_order bit-index back to the HomePage enum value for this build. // Returns -1 if the page is not compiled in. int bitToPage(int bit) const { switch (bit) { - case 0: return CLOCK; - case 1: return RECENT; - case 2: return RADIO; - case 3: return BLUETOOTH; - case 4: return ADVERT; - case 5: + case NodePrefs::HPB_CLOCK: return CLOCK; + case NodePrefs::HPB_RECENT: return RECENT; + case NodePrefs::HPB_RADIO: return RADIO; + case NodePrefs::HPB_BLUETOOTH: return BLUETOOTH; + case NodePrefs::HPB_ADVERT: return ADVERT; #if ENV_INCLUDE_GPS == 1 - return GPS; -#else - return -1; + case NodePrefs::HPB_GPS: return GPS; #endif - case 6: #if UI_SENSORS_PAGE == 1 - return SENSORS; -#else - return -1; + case NodePrefs::HPB_SENSORS: return SENSORS; #endif - case 7: return TOOLS; - case 8: return SHUTDOWN; - case 9: return SETTINGS; - case 10: return QUICK_MSG; + case NodePrefs::HPB_TOOLS: return TOOLS; + case NodePrefs::HPB_SHUTDOWN: return SHUTDOWN; + case NodePrefs::HPB_SETTINGS: return SETTINGS; + case NodePrefs::HPB_QUICK_MSG: return QUICK_MSG; default: return -1; } } @@ -206,9 +200,9 @@ class HomeScreen : public UIScreen { int n = 0; bool custom = _node_prefs && _node_prefs->page_order_set == NodePrefs::PAGE_ORDER_MAGIC; if (custom) { - for (int i = 0; i < 11; i++) { + for (int i = 0; i < NodePrefs::HPB_COUNT; i++) { uint8_t v = _node_prefs->page_order[i]; - if (v < 1 || v > 11) break; + if (v < 1 || v > NodePrefs::HPB_COUNT) break; int pg = bitToPage(v - 1); if (pg >= 0 && pg < (int)Count && isPageVisible(pg)) out[n++] = pg; }