From 31fe15bb73fb174f87893cac64a7d4ce1ff2d85d Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Wed, 11 Feb 2026 12:02:22 -0600 Subject: [PATCH] =?UTF-8?q?ExternalNotification=20and=20StatusLED=20now=20?= =?UTF-8?q?call=20AmbientLighting=20to=20update=E2=80=A6=20(#9554)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ExternalNotification and StatusLED now call AmbientLighting to update RGB LEDs. Add optional heartbeat * Don't overwrite RGB state if heartbeat is disabled. * Use the right define * Remove another .h and make rgb static * move rgb objects into AmbientLighting class * Straighten out AmbientLighting Thread object * Use %f for floats --- src/AmbientLightingThread.h | 125 +++++++++++---------- src/graphics/NeoPixel.h | 4 - src/graphics/RAKled.h | 5 - src/main.cpp | 3 +- src/modules/ExternalNotificationModule.cpp | 98 +--------------- src/modules/ExternalNotificationModule.h | 5 + src/modules/StatusLEDModule.cpp | 10 ++ src/modules/StatusLEDModule.h | 4 + 8 files changed, 88 insertions(+), 166 deletions(-) delete mode 100644 src/graphics/NeoPixel.h delete mode 100644 src/graphics/RAKled.h diff --git a/src/AmbientLightingThread.h b/src/AmbientLightingThread.h index 947b1e054..bd9557c21 100644 --- a/src/AmbientLightingThread.h +++ b/src/AmbientLightingThread.h @@ -1,19 +1,21 @@ +#ifndef AMBIENTLIGHTINGTHREAD_H +#define AMBIENTLIGHTINGTHREAD_H + #include "Observer.h" #include "configuration.h" +#include "detect/ScanI2C.h" +#include "sleep.h" #ifdef HAS_NCP5623 -#include -NCP5623 rgb; +#include #endif #ifdef HAS_LP5562 #include -LP5562 rgbw; #endif #ifdef HAS_NEOPIXEL -#include -Adafruit_NeoPixel pixels(NEOPIXEL_COUNT, NEOPIXEL_DATA, NEOPIXEL_TYPE); +#include #endif #ifdef UNPHONE @@ -21,10 +23,24 @@ Adafruit_NeoPixel pixels(NEOPIXEL_COUNT, NEOPIXEL_DATA, NEOPIXEL_TYPE); extern unPhone unphone; #endif -namespace concurrency -{ class AmbientLightingThread : public concurrency::OSThread { + friend class StatusLEDModule; // Let the LEDStatusModule trigger the ambient lighting for notifications and battery status. + friend class ExternalNotificationModule; // Let the ExternalNotificationModule trigger the ambient lighting for notifications. + + private: +#ifdef HAS_NCP5623 + NCP5623 rgb; +#endif + +#ifdef HAS_LP5562 + LP5562 rgbw; +#endif + +#ifdef HAS_NEOPIXEL + Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NEOPIXEL_COUNT, NEOPIXEL_DATA, NEOPIXEL_TYPE); +#endif + public: explicit AmbientLightingThread(ScanI2C::DeviceType type) : OSThread("AmbientLighting") { @@ -36,14 +52,15 @@ class AmbientLightingThread : public concurrency::OSThread moduleConfig.ambient_lighting.led_state = true; #endif #endif - // Uncomment to test module - // moduleConfig.ambient_lighting.led_state = true; - // moduleConfig.ambient_lighting.current = 10; +#if AMBIENT_LIGHTING_TEST + // define to enable test + moduleConfig.ambient_lighting.led_state = true; + moduleConfig.ambient_lighting.current = 10; // Default to a color based on our node number - // moduleConfig.ambient_lighting.red = (myNodeInfo.my_node_num & 0xFF0000) >> 16; - // moduleConfig.ambient_lighting.green = (myNodeInfo.my_node_num & 0x00FF00) >> 8; - // moduleConfig.ambient_lighting.blue = myNodeInfo.my_node_num & 0x0000FF; - + moduleConfig.ambient_lighting.red = (myNodeInfo.my_node_num & 0xFF0000) >> 16; + moduleConfig.ambient_lighting.green = (myNodeInfo.my_node_num & 0x00FF00) >> 8; + moduleConfig.ambient_lighting.blue = myNodeInfo.my_node_num & 0x0000FF; +#endif #if defined(HAS_NCP5623) || defined(HAS_LP5562) _type = type; if (_type == ScanI2C::DeviceType::NONE) { @@ -53,11 +70,6 @@ class AmbientLightingThread : public concurrency::OSThread } #endif #ifdef HAS_RGB_LED - if (!moduleConfig.ambient_lighting.led_state) { - LOG_DEBUG("AmbientLighting Disable due to moduleConfig.ambient_lighting.led_state OFF"); - disable(); - return; - } LOG_DEBUG("AmbientLighting init"); #ifdef HAS_NCP5623 if (_type == ScanI2C::NCP5623) { @@ -77,7 +89,13 @@ class AmbientLightingThread : public concurrency::OSThread pixels.clear(); // Set all pixel colors to 'off' pixels.setBrightness(moduleConfig.ambient_lighting.current); #endif - setLighting(); + if (!moduleConfig.ambient_lighting.led_state) { + LOG_DEBUG("AmbientLighting Disable due to moduleConfig.ambient_lighting.led_state OFF"); + disable(); + return; + } + setLighting(moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red, + moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue); #endif #if defined(HAS_NCP5623) || defined(HAS_LP5562) } @@ -91,7 +109,8 @@ class AmbientLightingThread : public concurrency::OSThread #if defined(HAS_NCP5623) || defined(HAS_LP5562) if ((_type == ScanI2C::NCP5623 || _type == ScanI2C::LP5562) && moduleConfig.ambient_lighting.led_state) { #endif - setLighting(); + setLighting(moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red, + moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue); return 30000; // 30 seconds to reset from any animations that may have been running from Ext. Notification #if defined(HAS_NCP5623) || defined(HAS_LP5562) } @@ -148,65 +167,53 @@ class AmbientLightingThread : public concurrency::OSThread return 0; } - void setLighting() + protected: + void setLighting(float current, uint8_t red, uint8_t green, uint8_t blue) { #ifdef HAS_NCP5623 - rgb.setCurrent(moduleConfig.ambient_lighting.current); - rgb.setRed(moduleConfig.ambient_lighting.red); - rgb.setGreen(moduleConfig.ambient_lighting.green); - rgb.setBlue(moduleConfig.ambient_lighting.blue); - LOG_DEBUG("Init NCP5623 Ambient light w/ current=%d, red=%d, green=%d, blue=%d", - moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red, - moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue); + rgb.setCurrent(current); + rgb.setRed(red); + rgb.setGreen(green); + rgb.setBlue(blue); + LOG_DEBUG("Init NCP5623 Ambient light w/ current=%f, red=%d, green=%d, blue=%d", current, red, green, blue); #endif #ifdef HAS_LP5562 - rgbw.setCurrent(moduleConfig.ambient_lighting.current); - rgbw.setRed(moduleConfig.ambient_lighting.red); - rgbw.setGreen(moduleConfig.ambient_lighting.green); - rgbw.setBlue(moduleConfig.ambient_lighting.blue); - LOG_DEBUG("Init LP5562 Ambient light w/ current=%d, red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.current, - moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue); + rgbw.setCurrent(current); + rgbw.setRed(red); + rgbw.setGreen(green); + rgbw.setBlue(blue); + LOG_DEBUG("Init LP5562 Ambient light w/ current=%f, red=%d, green=%d, blue=%d", current, red, green, blue); #endif #ifdef HAS_NEOPIXEL - pixels.fill(pixels.Color(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, - moduleConfig.ambient_lighting.blue), - 0, NEOPIXEL_COUNT); + pixels.fill(pixels.Color(red, green, blue), 0, NEOPIXEL_COUNT); // RadioMaster Bandit has addressable LED at the two buttons // this allow us to set different lighting for them in variant.h file. -#ifdef RADIOMASTER_900_BANDIT #if defined(BUTTON1_COLOR) && defined(BUTTON1_COLOR_INDEX) pixels.fill(BUTTON1_COLOR, BUTTON1_COLOR_INDEX, 1); #endif #if defined(BUTTON2_COLOR) && defined(BUTTON2_COLOR_INDEX) pixels.fill(BUTTON2_COLOR, BUTTON2_COLOR_INDEX, 1); -#endif #endif pixels.show(); - // LOG_DEBUG("Init NeoPixel Ambient light w/ brightness(current)=%d, red=%d, green=%d, blue=%d", - // moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red, - // moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue); + // LOG_DEBUG("Init NeoPixel Ambient light w/ brightness(current)=%f, red=%d, green=%d, blue=%d", + // current, red, green, blue); #endif #ifdef RGBLED_CA - analogWrite(RGBLED_RED, 255 - moduleConfig.ambient_lighting.red); - analogWrite(RGBLED_GREEN, 255 - moduleConfig.ambient_lighting.green); - analogWrite(RGBLED_BLUE, 255 - moduleConfig.ambient_lighting.blue); - LOG_DEBUG("Init Ambient light RGB Common Anode w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red, - moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue); + analogWrite(RGBLED_RED, 255 - red); + analogWrite(RGBLED_GREEN, 255 - green); + analogWrite(RGBLED_BLUE, 255 - blue); + LOG_DEBUG("Init Ambient light RGB Common Anode w/ red=%d, green=%d, blue=%d", red, green, blue); #elif defined(RGBLED_RED) - analogWrite(RGBLED_RED, moduleConfig.ambient_lighting.red); - analogWrite(RGBLED_GREEN, moduleConfig.ambient_lighting.green); - analogWrite(RGBLED_BLUE, moduleConfig.ambient_lighting.blue); - LOG_DEBUG("Init Ambient light RGB Common Cathode w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red, - moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue); + analogWrite(RGBLED_RED, red); + analogWrite(RGBLED_GREEN, green); + analogWrite(RGBLED_BLUE, blue); + LOG_DEBUG("Init Ambient light RGB Common Cathode w/ red=%d, green=%d, blue=%d", red, green, blue); #endif #ifdef UNPHONE - unphone.rgb(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, - moduleConfig.ambient_lighting.blue); - LOG_DEBUG("Init unPhone Ambient light w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red, - moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue); + unphone.rgb(red, green, blue); + LOG_DEBUG("Init unPhone Ambient light w/ red=%d, green=%d, blue=%d", red, green, blue); #endif } }; - -} // namespace concurrency +#endif // AMBIENTLIGHTINGTHREAD_H \ No newline at end of file diff --git a/src/graphics/NeoPixel.h b/src/graphics/NeoPixel.h deleted file mode 100644 index dde74366e..000000000 --- a/src/graphics/NeoPixel.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifdef HAS_NEOPIXEL -#include -extern Adafruit_NeoPixel pixels; -#endif \ No newline at end of file diff --git a/src/graphics/RAKled.h b/src/graphics/RAKled.h deleted file mode 100644 index 659ea9b72..000000000 --- a/src/graphics/RAKled.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifdef HAS_NCP5623 -#include -extern NCP5623 rgb; - -#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 54b0bc3e6..153b9847e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,7 +29,6 @@ #include #endif #include "detect/einkScan.h" -#include "graphics/RAKled.h" #include "graphics/Screen.h" #include "main.h" #include "mesh/generated/meshtastic/config.pb.h" @@ -247,7 +246,7 @@ const char *getDeviceName() uint32_t timeLastPowered = 0; static OSThread *powerFSMthread; -static OSThread *ambientLightingThread; +OSThread *ambientLightingThread; RadioInterface *rIf = NULL; #ifdef ARCH_PORTDUINO diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp index 5e6985bdf..0301b2ac3 100644 --- a/src/modules/ExternalNotificationModule.cpp +++ b/src/modules/ExternalNotificationModule.cpp @@ -24,24 +24,8 @@ #include "mesh/generated/meshtastic/rtttl.pb.h" #include -#ifdef HAS_NCP5623 -#include -#endif - -#ifdef HAS_LP5562 -#include -#endif - -#ifdef HAS_NEOPIXEL -#include -#endif - -#ifdef UNPHONE -#include "unPhone.h" -extern unPhone unphone; -#endif - #if defined(HAS_RGB_LED) +#include "AmbientLightingThread.h" uint8_t red = 0; uint8_t green = 0; uint8_t blue = 0; @@ -123,32 +107,6 @@ int32_t ExternalNotificationModule::runOnce() green = (colorState & 2) ? brightnessValues[brightnessIndex] : 0; // Green enabled on colorState = 2,3,6,7 blue = (colorState & 1) ? (brightnessValues[brightnessIndex] * 1.5) : 0; // Blue enabled on colorState = 1,3,5,7 white = (colorState & 12) ? brightnessValues[brightnessIndex] : 0; -#ifdef HAS_NCP5623 - if (rgb_found.type == ScanI2C::NCP5623) { - rgb.setColor(red, green, blue); - } -#endif -#ifdef HAS_LP5562 - if (rgb_found.type == ScanI2C::LP5562) { - rgbw.setColor(red, green, blue, white); - } -#endif -#ifdef RGBLED_CA - analogWrite(RGBLED_RED, 255 - red); // CA type needs reverse logic - analogWrite(RGBLED_GREEN, 255 - green); - analogWrite(RGBLED_BLUE, 255 - blue); -#elif defined(RGBLED_RED) - analogWrite(RGBLED_RED, red); - analogWrite(RGBLED_GREEN, green); - analogWrite(RGBLED_BLUE, blue); -#endif -#ifdef HAS_NEOPIXEL - pixels.fill(pixels.Color(red, green, blue), 0, NEOPIXEL_COUNT); - pixels.show(); -#endif -#ifdef UNPHONE - unphone.rgb(red, green, blue); -#endif if (ascending) { // fade in brightnessIndex++; if (brightnessIndex == (sizeof(brightnessValues) - 1)) { @@ -255,34 +213,9 @@ void ExternalNotificationModule::setExternalState(uint8_t index, bool on) blue = 0; white = 0; } + ambientLightingThread->setLighting(moduleConfig.ambient_lighting.current, red, green, blue); #endif -#ifdef HAS_NCP5623 - if (rgb_found.type == ScanI2C::NCP5623) { - rgb.setColor(red, green, blue); - } -#endif -#ifdef HAS_LP5562 - if (rgb_found.type == ScanI2C::LP5562) { - rgbw.setColor(red, green, blue, white); - } -#endif -#ifdef RGBLED_CA - analogWrite(RGBLED_RED, 255 - red); // CA type needs reverse logic - analogWrite(RGBLED_GREEN, 255 - green); - analogWrite(RGBLED_BLUE, 255 - blue); -#elif defined(RGBLED_RED) - analogWrite(RGBLED_RED, red); - analogWrite(RGBLED_GREEN, green); - analogWrite(RGBLED_BLUE, blue); -#endif -#ifdef HAS_NEOPIXEL - pixels.fill(pixels.Color(red, green, blue), 0, NEOPIXEL_COUNT); - pixels.show(); -#endif -#ifdef UNPHONE - unphone.rgb(red, green, blue); -#endif #ifdef HAS_DRV2605 if (on) { drv.go(); @@ -407,33 +340,6 @@ ExternalNotificationModule::ExternalNotificationModule() LOG_INFO("Use Pin %i in PWM mode", config.device.buzzer_gpio); } } -#ifdef HAS_NCP5623 - if (rgb_found.type == ScanI2C::NCP5623) { - rgb.begin(); - rgb.setCurrent(10); - } -#endif -#ifdef HAS_LP5562 - if (rgb_found.type == ScanI2C::LP5562) { - rgbw.begin(); - rgbw.setCurrent(20); - } -#endif -#ifdef RGBLED_RED - pinMode(RGBLED_RED, OUTPUT); // set up the RGB led pins - pinMode(RGBLED_GREEN, OUTPUT); - pinMode(RGBLED_BLUE, OUTPUT); -#endif -#ifdef RGBLED_CA - analogWrite(RGBLED_RED, 255); // with a common anode type, logic is reversed - analogWrite(RGBLED_GREEN, 255); // so we want to initialise with lights off - analogWrite(RGBLED_BLUE, 255); -#endif -#ifdef HAS_NEOPIXEL - pixels.begin(); // Initialise the pixel(s) - pixels.clear(); // Set all pixel colors to 'off' - pixels.setBrightness(moduleConfig.ambient_lighting.current); -#endif } else { LOG_INFO("External Notification Module Disabled"); disable(); diff --git a/src/modules/ExternalNotificationModule.h b/src/modules/ExternalNotificationModule.h index f667f7be9..94b021360 100644 --- a/src/modules/ExternalNotificationModule.h +++ b/src/modules/ExternalNotificationModule.h @@ -5,6 +5,11 @@ #include "configuration.h" #include "input/InputBroker.h" +#ifdef HAS_RGB_LED +#include "AmbientLightingThread.h" +extern AmbientLightingThread *ambientLightingThread; +#endif + #if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !defined(CONFIG_IDF_TARGET_ESP32C6) #include #else diff --git a/src/modules/StatusLEDModule.cpp b/src/modules/StatusLEDModule.cpp index 7acf750c2..457935688 100644 --- a/src/modules/StatusLEDModule.cpp +++ b/src/modules/StatusLEDModule.cpp @@ -164,6 +164,16 @@ int32_t StatusLEDModule::runOnce() digitalWrite(LED_PAIRING, PAIRING_LED_state); #endif +#ifdef RGB_LED_POWER + if (!config.device.led_heartbeat_disabled) { + if (CHARGE_LED_state == LED_STATE_ON) { + ambientLightingThread->setLighting(10, 255, 0, 0); + } else { + ambientLightingThread->setLighting(0, 0, 0, 0); + } + } +#endif + #ifdef Battery_LED_1 digitalWrite(Battery_LED_1, chargeIndicatorLED1); #endif diff --git a/src/modules/StatusLEDModule.h b/src/modules/StatusLEDModule.h index c35f29019..972e26737 100644 --- a/src/modules/StatusLEDModule.h +++ b/src/modules/StatusLEDModule.h @@ -59,3 +59,7 @@ class StatusLEDModule : private concurrency::OSThread }; extern StatusLEDModule *statusLEDModule; +#ifdef RGB_LED_POWER +#include "AmbientLightingThread.h" +extern AmbientLightingThread *ambientLightingThread; +#endif