From caa9a4bc4643fe511f48b732686ce099161f9aa5 Mon Sep 17 00:00:00 2001 From: Andy Shinn Date: Tue, 10 Feb 2026 22:04:56 -0600 Subject: [PATCH] move statusLED to its own class and allow using for repeater --- examples/companion_radio/ui-new/UITask.cpp | 36 ++++----------- examples/companion_radio/ui-new/UITask.h | 16 +++---- examples/companion_radio/ui-orig/UITask.cpp | 45 +++++------------- examples/companion_radio/ui-orig/UITask.h | 13 +++++- examples/simple_repeater/main.cpp | 12 +++++ src/helpers/StatusLED.h | 51 +++++++++++++++++++++ 6 files changed, 101 insertions(+), 72 deletions(-) create mode 100644 src/helpers/StatusLED.h diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index ae2d93753..c65156fd4 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -11,12 +11,6 @@ #endif #define BOOT_SCREEN_MILLIS 3000 // 3 seconds -#ifdef PIN_STATUS_LED -#define LED_ON_MILLIS 20 -#define LED_ON_MSG_MILLIS 200 -#define LED_CYCLE_MILLIS 4000 -#endif - #define LONG_PRESS_MILLIS 1200 #ifndef UI_RECENT_LIST_SIZE @@ -577,6 +571,10 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no vibration.begin(); #endif +#ifdef PIN_STATUS_LED + status_led.begin(); +#endif + ui_started_at = millis(); _alert_expiry = 0; @@ -645,27 +643,6 @@ void UITask::newMsg(uint8_t path_len, const char* from_name, const char* text, i } } -void UITask::userLedHandler() { -#ifdef PIN_STATUS_LED - int cur_time = millis(); - if (cur_time > next_led_change) { - if (led_state == 0) { - led_state = 1; - if (_msgcount > 0) { - last_led_increment = LED_ON_MSG_MILLIS; - } else { - last_led_increment = LED_ON_MILLIS; - } - next_led_change = cur_time + last_led_increment; - } else { - led_state = 0; - next_led_change = cur_time + LED_CYCLE_MILLIS - last_led_increment; - } - digitalWrite(PIN_STATUS_LED, led_state == LED_STATE_ON); - } -#endif -} - void UITask::setCurrScreen(UIScreen* c) { curr = c; _next_refresh = 100; @@ -776,7 +753,10 @@ void UITask::loop() { _next_refresh = 100; // trigger refresh } - userLedHandler(); +#ifdef PIN_STATUS_LED + status_led.setAlert(_msgcount > 0); + status_led.loop(); +#endif #ifdef PIN_BUZZER if (buzzer.isPlaying()) buzzer.loop(); diff --git a/examples/companion_radio/ui-new/UITask.h b/examples/companion_radio/ui-new/UITask.h index 02c3cafbd..f6fa30647 100644 --- a/examples/companion_radio/ui-new/UITask.h +++ b/examples/companion_radio/ui-new/UITask.h @@ -8,8 +8,8 @@ #include #include -#ifndef LED_STATE_ON - #define LED_STATE_ON 1 +#ifdef PIN_STATUS_LED + #include #endif #ifdef PIN_BUZZER @@ -39,9 +39,7 @@ class UITask : public AbstractUITask { unsigned long ui_started_at, next_batt_chck; int next_backlight_btn_check = 0; #ifdef PIN_STATUS_LED - int led_state = 0; - int next_led_change = 0; - int last_led_increment = 0; + StatusLED status_led; #endif #ifdef PIN_USER_BTN_ANA @@ -53,8 +51,6 @@ class UITask : public AbstractUITask { UIScreen* msg_preview; UIScreen* curr; - void userLedHandler(); - // Button action handlers char checkDisplayOn(char c); char handleLongPress(char c); @@ -65,7 +61,11 @@ class UITask : public AbstractUITask { public: - UITask(mesh::MainBoard* board, BaseSerialInterface* serial) : AbstractUITask(board, serial), _display(NULL), _sensors(NULL) { + UITask(mesh::MainBoard* board, BaseSerialInterface* serial) : AbstractUITask(board, serial), _display(NULL), _sensors(NULL) +#ifdef PIN_STATUS_LED + , status_led(PIN_STATUS_LED) +#endif + { next_batt_chck = _next_refresh = 0; ui_started_at = 0; curr = NULL; diff --git a/examples/companion_radio/ui-orig/UITask.cpp b/examples/companion_radio/ui-orig/UITask.cpp index 3ad36fb00..83886b2ef 100644 --- a/examples/companion_radio/ui-orig/UITask.cpp +++ b/examples/companion_radio/ui-orig/UITask.cpp @@ -6,12 +6,6 @@ #define AUTO_OFF_MILLIS 15000 // 15 seconds #define BOOT_SCREEN_MILLIS 3000 // 3 seconds -#ifdef PIN_STATUS_LED -#define LED_ON_MILLIS 20 -#define LED_ON_MSG_MILLIS 200 -#define LED_CYCLE_MILLIS 4000 -#endif - #ifndef USER_BTN_PRESSED #define USER_BTN_PRESSED LOW #endif @@ -59,6 +53,10 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no buzzer.quiet(_node_prefs->buzzer_quiet); #endif +#ifdef PIN_STATUS_LED + status_led.begin(); +#endif + // Initialize digital button if available #ifdef PIN_USER_BTN _userButton = new Button(PIN_USER_BTN, USER_BTN_PRESSED); @@ -260,33 +258,8 @@ void UITask::renderCurrScreen() { _need_refresh = false; } -void UITask::userLedHandler() { -#ifdef PIN_STATUS_LED - static int state = 0; - static int next_change = 0; - static int last_increment = 0; - - int cur_time = millis(); - if (cur_time > next_change) { - if (state == 0) { - state = 1; - if (_msgcount > 0) { - last_increment = LED_ON_MSG_MILLIS; - } else { - last_increment = LED_ON_MILLIS; - } - next_change = cur_time + last_increment; - } else { - state = 0; - next_change = cur_time + LED_CYCLE_MILLIS - last_increment; - } - digitalWrite(PIN_STATUS_LED, state == LED_STATE_ON); - } -#endif -} - -/* - hardware-agnostic pre-shutdown activity should be done here +/* + hardware-agnostic pre-shutdown activity should be done here */ void UITask::shutdown(bool restart){ @@ -322,7 +295,11 @@ void UITask::loop() { _userButtonAnalog->update(); } #endif - userLedHandler(); + +#ifdef PIN_STATUS_LED + status_led.setAlert(_msgcount > 0); + status_led.loop(); +#endif #ifdef PIN_BUZZER if (buzzer.isPlaying()) buzzer.loop(); diff --git a/examples/companion_radio/ui-orig/UITask.h b/examples/companion_radio/ui-orig/UITask.h index 60cd0d042..b45d870b2 100644 --- a/examples/companion_radio/ui-orig/UITask.h +++ b/examples/companion_radio/ui-orig/UITask.h @@ -8,6 +8,9 @@ #ifdef PIN_BUZZER #include #endif +#ifdef PIN_STATUS_LED + #include +#endif #include "../AbstractUITask.h" #include "../NodePrefs.h" @@ -30,6 +33,9 @@ class UITask : public AbstractUITask { bool _need_refresh = true; bool _displayWasOn = false; // Track display state before button press unsigned long ui_started_at; +#ifdef PIN_STATUS_LED + StatusLED status_led; +#endif // Button handlers #ifdef PIN_USER_BTN @@ -40,7 +46,6 @@ class UITask : public AbstractUITask { #endif void renderCurrScreen(); - void userLedHandler(); void renderBatteryIndicator(uint16_t batteryMilliVolts); // Button action handlers @@ -54,7 +59,11 @@ class UITask : public AbstractUITask { public: - UITask(mesh::MainBoard* board, BaseSerialInterface* serial) : AbstractUITask(board, serial), _display(NULL), _sensors(NULL) { + UITask(mesh::MainBoard* board, BaseSerialInterface* serial) : AbstractUITask(board, serial), _display(NULL), _sensors(NULL) +#ifdef PIN_STATUS_LED + , status_led(PIN_STATUS_LED) +#endif + { _next_refresh = 0; ui_started_at = 0; } diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index d226d1fa7..3c767d20a 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -3,6 +3,11 @@ #include "MyMesh.h" +#ifdef PIN_STATUS_LED + #include + static StatusLED status_led(PIN_STATUS_LED); +#endif + #ifdef DISPLAY_CLASS #include "UITask.h" static UITask ui_task(display); @@ -35,6 +40,10 @@ void setup() { delay(5000); #endif +#ifdef PIN_STATUS_LED + status_led.begin(); +#endif + // For power saving lastActive = millis(); // mark last active time since boot @@ -133,6 +142,9 @@ void loop() { ui_task.loop(); #endif rtc_clock.tick(); +#ifdef PIN_STATUS_LED + status_led.loop(); +#endif if (the_mesh.getNodePrefs()->powersaving_enabled && !the_mesh.hasPendingWork()) { #if defined(NRF52_PLATFORM) diff --git a/src/helpers/StatusLED.h b/src/helpers/StatusLED.h new file mode 100644 index 000000000..be940a457 --- /dev/null +++ b/src/helpers/StatusLED.h @@ -0,0 +1,51 @@ +#pragma once + +#include + +#ifndef LED_ON_MILLIS + #define LED_ON_MILLIS 20 +#endif +#ifndef LED_ON_MSG_MILLIS + #define LED_ON_MSG_MILLIS 200 +#endif +#ifndef LED_CYCLE_MILLIS + #define LED_CYCLE_MILLIS 4000 +#endif +#ifndef LED_STATE_ON + #define LED_STATE_ON 1 +#endif + +class StatusLED { + uint8_t _pin; + uint8_t _active; + unsigned long _next_change = 0; + unsigned long _last_on_duration = 0; + uint8_t _state = 0; + bool _alert = false; + +public: + StatusLED(uint8_t pin, uint8_t active = LED_STATE_ON) : _pin(pin), _active(active) { } + + void begin() { + pinMode(_pin, OUTPUT); + digitalWrite(_pin, _active ? LOW : HIGH); // Start with LED off + } + + void setAlert(bool alert) { _alert = alert; } + bool isAlert() const { return _alert; } + + void loop() { + unsigned long now = millis(); + if (now > _next_change) { + if (_state == 0) { + _state = 1; + _last_on_duration = _alert ? LED_ON_MSG_MILLIS : LED_ON_MILLIS; + _next_change = now + _last_on_duration; + } else { + _state = 0; + _next_change = now + LED_CYCLE_MILLIS - _last_on_duration; + } + digitalWrite(_pin, (_state == _active) ? HIGH : LOW); + } + } +};