diff --git a/zephcore/helpers/ui-joystick/joystick_ui_task.cpp b/zephcore/helpers/ui-joystick/joystick_ui_task.cpp index 6a9ff1f..d7ba17e 100644 --- a/zephcore/helpers/ui-joystick/joystick_ui_task.cpp +++ b/zephcore/helpers/ui-joystick/joystick_ui_task.cpp @@ -951,6 +951,14 @@ void JoystickUITask::adjustScreenOff(int32_t delta_ms) mesh_save_screen_off_secs((uint16_t)(_screen_off_ms / 1000)); } +void JoystickUITask::cyclePathHashMode() +{ + if (!_prefs) return; + uint8_t next = (uint8_t)((_prefs->path_hash_mode + 1) % 3); /* 0→1→2→0 */ + _prefs->path_hash_mode = next; + mesh_save_path_hash_mode(next); +} + void JoystickUITask::toggleWakeOnMsg() { _wake_on_msg = !_wake_on_msg; diff --git a/zephcore/helpers/ui-joystick/joystick_ui_task.h b/zephcore/helpers/ui-joystick/joystick_ui_task.h index c19fd7e..ad29e91 100644 --- a/zephcore/helpers/ui-joystick/joystick_ui_task.h +++ b/zephcore/helpers/ui-joystick/joystick_ui_task.h @@ -95,6 +95,10 @@ public: void adjustBrightness(int delta); bool getWakeOnMsg() const { return _wake_on_msg; } void toggleWakeOnMsg(); + /* Path-hash-mode: 0/1/2 → 1/2/3 bytes per hop appended to outbound flood + * path. Cycles through the three valid settings; persists to prefs. */ + uint8_t getPathHashBytes() const { return _prefs ? (uint8_t)(_prefs->path_hash_mode + 1) : 1; } + void cyclePathHashMode(); bool isBuzzerQuiet() const; void toggleBuzzer(); bool isGPSAvailable() const; diff --git a/zephcore/helpers/ui-joystick/screens/system.cpp b/zephcore/helpers/ui-joystick/screens/system.cpp index e0d53eb..457b34b 100644 --- a/zephcore/helpers/ui-joystick/screens/system.cpp +++ b/zephcore/helpers/ui-joystick/screens/system.cpp @@ -21,7 +21,7 @@ static const char * const kSysCatLabels[] = { "Device", "Display", "Info", "Powe static const int kSysCatCount = 4; /* Device submenu items */ -enum SysDevItem { SYSDEV_BUZZER=0, SYSDEV_BLUETOOTH, SYSDEV_OFFGRID, SYSDEV_LEDS, SYSDEV_BLE_CODE, SYSDEV_DFU, SYSDEV_TELEMETRY, SYSDEV_RENAME, SYSDEV_COUNT }; +enum SysDevItem { SYSDEV_BUZZER=0, SYSDEV_BLUETOOTH, SYSDEV_OFFGRID, SYSDEV_LEDS, SYSDEV_BLE_CODE, SYSDEV_PATHHASH, SYSDEV_DFU, SYSDEV_TELEMETRY, SYSDEV_RENAME, SYSDEV_COUNT }; #define DFU_CONFIRM_WINDOW_MS 3000 /* Display submenu items */ @@ -56,11 +56,12 @@ int SystemScreen::render(JoystickDisplay &display) return 500; } if (_mode == SYSMODE_DEVICE) { - char bt_label[24], buz_label[24], og_label[24], led_label[24], dfu_label[24]; + char bt_label[24], buz_label[24], og_label[24], led_label[24], dfu_label[24], ph_label[24]; snprintf(buz_label, sizeof(buz_label), "Buzzer: %s", _task->isBuzzerQuiet() ? "OFF" : "ON"); snprintf(bt_label, sizeof(bt_label), "Bluetooth: %s", _task->isSerialEnabled() ? "ON" : "OFF"); snprintf(og_label, sizeof(og_label), "Offgrid: %s", _task->isOffgridEnabled() ? "ON" : "OFF"); snprintf(led_label, sizeof(led_label), "LEDs: %s", _task->isLedsDisabled() ? "OFF" : "ON"); + snprintf(ph_label, sizeof(ph_label), "Path hash: %db", (int)_task->getPathHashBytes()); uint32_t now = k_uptime_get_32(); bool dfu_pending = (_dfu_confirm_time != 0 && (now - _dfu_confirm_time) <= DFU_CONFIRM_WINDOW_MS); @@ -69,6 +70,7 @@ int SystemScreen::render(JoystickDisplay &display) items[SYSDEV_BUZZER] = buz_label; items[SYSDEV_BLUETOOTH] = bt_label; items[SYSDEV_BLE_CODE] = "BLE Code"; + items[SYSDEV_PATHHASH] = ph_label; items[SYSDEV_TELEMETRY] = "Telemetry"; items[SYSDEV_RENAME] = "Rename node"; items[SYSDEV_OFFGRID] = og_label; @@ -159,6 +161,13 @@ bool SystemScreen::handleInput(char c) _task->toggleLeds(); _task->showAlert(_task->isLedsDisabled() ? "LEDs: OFF" : "LEDs: ON", 1000); return true; + case SYSDEV_PATHHASH: { + _task->cyclePathHashMode(); + char alert[24]; + snprintf(alert, sizeof(alert), "Path hash: %db", (int)_task->getPathHashBytes()); + _task->showAlert(alert, 1000); + return true; + } case SYSDEV_DFU: { uint32_t now = k_uptime_get_32(); if (_dfu_confirm_time != 0 && diff --git a/zephcore/helpers/ui/ui_mesh_actions.cpp b/zephcore/helpers/ui/ui_mesh_actions.cpp index 098a986..0cde111 100644 --- a/zephcore/helpers/ui/ui_mesh_actions.cpp +++ b/zephcore/helpers/ui/ui_mesh_actions.cpp @@ -44,6 +44,7 @@ LOG_MODULE_REGISTER(zephcore_ui_actions, CONFIG_ZEPHCORE_UI_ACTIONS_LOG_LEVEL); #define UI_ACTION_SAVE_RESTART BIT(8) #define UI_ACTION_WAKE_ON_MSG_SAVE BIT(9) #define UI_ACTION_SCREEN_OFF_SAVE BIT(10) +#define UI_ACTION_PATH_HASH_MODE_SAVE BIT(11) /* Module-local pointers, set by init */ static CompanionMesh *s_mesh; @@ -68,6 +69,7 @@ static atomic_t pending_ble_disabled; static atomic_t pending_brightness; static atomic_t pending_wake_on_msg; static atomic_t pending_screen_off_secs; +static atomic_t pending_path_hash_mode; extern "C" void ui_mesh_actions_init(struct k_event *mesh_events, uint32_t mesh_event_ui_action, @@ -144,6 +146,13 @@ extern "C" void mesh_save_screen_off_secs(uint16_t secs) k_event_post(s_mesh_events, s_mesh_event_ui_action); } +extern "C" void mesh_save_path_hash_mode(uint8_t mode) +{ + atomic_set(&pending_path_hash_mode, (atomic_val_t)mode); + atomic_or(&pending_ui_actions, UI_ACTION_PATH_HASH_MODE_SAVE); + k_event_post(s_mesh_events, s_mesh_event_ui_action); +} + extern "C" void mesh_set_buzzer_quiet(bool quiet) { /* Defer the flash write (savePrefs) to mesh thread */ @@ -286,6 +295,14 @@ extern "C" void mesh_handle_ui_actions(void) need_save = true; } + if (actions & UI_ACTION_PATH_HASH_MODE_SAVE) { + uint8_t mode = (uint8_t)atomic_get(&pending_path_hash_mode); + if (mode > 2) mode = 2; /* clamp to valid range (0-2 → 1-3 bytes) */ + s_mesh->prefs.path_hash_mode = mode; + LOG_INF("path_hash_mode=%d (%d bytes per hop)", mode, mode + 1); + need_save = true; + } + if (need_save || (actions & UI_ACTION_SAVE_RESTART)) { s_data_store->savePrefs(s_mesh->prefs); LOG_INF("prefs saved (button action)"); diff --git a/zephcore/helpers/ui/ui_mesh_actions.h b/zephcore/helpers/ui/ui_mesh_actions.h index b3beff6..c8fb508 100644 --- a/zephcore/helpers/ui/ui_mesh_actions.h +++ b/zephcore/helpers/ui/ui_mesh_actions.h @@ -64,6 +64,8 @@ void mesh_save_brightness(uint8_t brightness); void mesh_save_and_restart(void); void mesh_set_wake_on_msg(bool enabled); void mesh_save_screen_off_secs(uint16_t secs); +/* path_hash_mode: 0/1/2 → 1/2/3 bytes per hop appended to outbound flood path */ +void mesh_save_path_hash_mode(uint8_t mode); #ifdef __cplusplus }