From c8b7882c2daca97a7887431267356c06f2aeaf7b Mon Sep 17 00:00:00 2001 From: Jean Jacques Avril Date: Sat, 4 Oct 2025 12:03:59 +0200 Subject: [PATCH] Refactor HardwareLed class to use FastLED library and template for GPIO pin specification --- lib/hardware/hardware_led.cpp | 108 ++++++++++++++++++++++------------ lib/hardware/hardware_led.hpp | 24 +++++--- platformio.ini | 2 +- src/main.cpp | 2 +- 4 files changed, 89 insertions(+), 47 deletions(-) diff --git a/lib/hardware/hardware_led.cpp b/lib/hardware/hardware_led.cpp index a5a6335..c885ab3 100644 --- a/lib/hardware/hardware_led.cpp +++ b/lib/hardware/hardware_led.cpp @@ -1,5 +1,6 @@ #include "hardware_led.hpp" #include +#include #define DEBUG_LED #ifdef DEBUG_LED @@ -8,8 +9,10 @@ #define LOG(msg) #endif -HardwareLed::HardwareLed(uint8_t pin, uint8_t numPixels) - : m_strip(numPixels > 0 ? numPixels : 1, pin, NEO_GRB + NEO_KHZ800), +template +HardwareLed::HardwareLed(uint8_t numPixels) + : m_leds(new CRGB[numPixels > 0 ? numPixels : 1]), + m_numPixels(numPixels > 0 ? numPixels : 1), m_currentConfig(hardware_LedConfig_init_default), m_isActive(false), m_startTime(0), @@ -20,20 +23,31 @@ HardwareLed::HardwareLed(uint8_t pin, uint8_t numPixels) m_fadeCurrentColor(0), m_fadeTargetColor(0), m_fadeProgress(0.0f), - m_fadeStartTime(0) {} + m_fadeStartTime(0), + m_callback(nullptr) {} -void HardwareLed::begin() { - m_strip.begin(); - m_strip.show(); +template +HardwareLed::~HardwareLed() { + delete[] m_leds; +} + +template +void HardwareLed::begin() { + FastLED.addLeds(m_leds, m_numPixels).setCorrection(TypicalLEDStrip); + FastLED.setMaxPowerInVoltsAndMilliamps(5, m_numPixels * 60); // Limit power + FastLED.clear(); + FastLED.show(); randomSeed(analogRead(0)); } -void HardwareLed::end() { - m_strip.clear(); - m_strip.show(); +template +void HardwareLed::end() { + FastLED.clear(); + FastLED.show(); } -void HardwareLed::update() { +template +void HardwareLed::update() { static unsigned long lastUpdate = 0; unsigned long now = millis(); if (now - lastUpdate < 10) return; // Limit to ~100 FPS @@ -44,8 +58,8 @@ void HardwareLed::update() { // Safe against millis() overflow due to unsigned arithmetic if (m_currentConfig.duration_ms > 0 && (now - m_startTime) >= m_currentConfig.duration_ms) { m_isActive = false; - m_strip.clear(); - m_strip.show(); + FastLED.clear(); + FastLED.show(); if (m_callback) m_callback(); return; } @@ -69,7 +83,8 @@ void HardwareLed::update() { } } -void HardwareLed::set(const hardware_LedConfig& config) { +template +void HardwareLed::set(const hardware_LedConfig& config) { if (config.brightness > 255) { LOG("Error: Brightness exceeds 255"); return; @@ -79,8 +94,8 @@ void HardwareLed::set(const hardware_LedConfig& config) { config.animation_params.fade_params.colors_count > 5)) { LOG("Error: Invalid colors_count in FadeParams"); m_isActive = false; - m_strip.clear(); - m_strip.show(); + FastLED.clear(); + FastLED.show(); return; } if (config.which_animation_params == hardware_LedConfig_pulse_params_tag && @@ -105,20 +120,24 @@ void HardwareLed::set(const hardware_LedConfig& config) { update(); } -void HardwareLed::applyStatic(const hardware_StaticParams& params) { +template +void HardwareLed::applyStatic(const hardware_StaticParams& params) { setColor(params.color, m_currentConfig.brightness); } -void HardwareLed::applyPulse(const hardware_PulseParams& params) { +template +void HardwareLed::applyPulse(const hardware_PulseParams& params) { unsigned long now = millis(); float speed_ms = max(params.speed_ms, 1U); // Prevent division by zero float phase = fmod((now - m_startTime) / (float)speed_ms, 1.0f); float brightnessFactor = 0.5f + 0.5f * sin(2 * PI * phase); - uint8_t pulseBrightness = m_currentConfig.brightness * brightnessFactor; - setColor(params.color, pulseBrightness); + uint16_t pulseBrightness = roundf(m_currentConfig.brightness * brightnessFactor); + if (pulseBrightness > 255) pulseBrightness = 255; + setColor(params.color, (uint8_t)pulseBrightness); } -void HardwareLed::applyFade(const hardware_FadeParams& params) { +template +void HardwareLed::applyFade(const hardware_FadeParams& params) { if (params.colors_count == 0 || params.colors_count > 5) { LOG("Error: Invalid colors_count in FadeParams"); return; @@ -138,46 +157,59 @@ void HardwareLed::applyFade(const hardware_FadeParams& params) { setColor(interpolatedColor, m_currentConfig.brightness); } -void HardwareLed::applyFlicker(const hardware_FlickerParams& params) { +template +void HardwareLed::applyFlicker(const hardware_FlickerParams& params) { uint32_t intensity = min(params.intensity, 100U); // Clamp to 0-100 uint8_t threshold = map(intensity, 0, 100, 0, 255); bool showPixel = random(255) < threshold; - if (showPixel != (m_strip.getPixelColor(0) != 0)) { + if (showPixel != (m_leds[0] != CRGB(0, 0, 0))) { if (showPixel) { setColor(params.color, m_currentConfig.brightness); } else { - m_strip.clear(); - m_strip.show(); + FastLED.clear(); + FastLED.show(); } } } -void HardwareLed::setColor(uint32_t color, uint8_t brightness) { +template +void HardwareLed::setColor(uint32_t color, uint8_t brightness) { uint8_t r = (color >> 16) & 0xFF; uint8_t g = (color >> 8) & 0xFF; uint8_t b = color & 0xFF; - r = (r * brightness) / 255; - g = (g * brightness) / 255; - b = (b * brightness) / 255; - for (uint16_t i = 0; i < m_strip.numPixels(); i++) { - m_strip.setPixelColor(i, r, g, b); + uint16_t r_scaled = ((uint16_t)r * brightness) / 255; + uint16_t g_scaled = ((uint16_t)g * brightness) / 255; + uint16_t b_scaled = ((uint16_t)b * brightness) / 255; + r = (r_scaled > 255) ? 255 : (uint8_t)r_scaled; + g = (g_scaled > 255) ? 255 : (uint8_t)g_scaled; + b = (b_scaled > 255) ? 255 : (uint8_t)b_scaled; + for (uint16_t i = 0; i < m_numPixels; i++) { + m_leds[i] = CRGB(r, g, b); } - m_strip.show(); + FastLED.show(); } -uint32_t HardwareLed::lerpColor(uint32_t color1, uint32_t color2, float t) const { +template +uint32_t HardwareLed::lerpColor(uint32_t color1, uint32_t color2, float t) const { uint8_t r1 = (color1 >> 16) & 0xFF; uint8_t g1 = (color1 >> 8) & 0xFF; uint8_t b1 = color1 & 0xFF; uint8_t r2 = (color2 >> 16) & 0xFF; uint8_t g2 = (color2 >> 8) & 0xFF; uint8_t b2 = color2 & 0xFF; - uint8_t r = r1 + (r2 - r1) * t; - uint8_t g = g1 + (g2 - g1) * t; - uint8_t b = b1 + (b2 - b1) * t; + float r_f = r1 + (r2 - r1) * t; + float g_f = g1 + (g2 - g1) * t; + float b_f = b1 + (b2 - b1) * t; + uint8_t r = (uint8_t)roundf(r_f); + uint8_t g = (uint8_t)roundf(g_f); + uint8_t b = (uint8_t)roundf(b_f); return (r << 16) | (g << 8) | b; } -float HardwareLed::estimateCurrent_mA() const { - return m_strip.numPixels() * (m_currentConfig.brightness / 255.0f) * 60.0f; -} \ No newline at end of file +template +float HardwareLed::estimateCurrent_mA() const { + return m_numPixels * (m_currentConfig.brightness / 255.0f) * 60.0f; +} + +// Explicit instantiation for pin D2 (GPIO 2) +template class HardwareLed<2>; \ No newline at end of file diff --git a/lib/hardware/hardware_led.hpp b/lib/hardware/hardware_led.hpp index e055949..8453168 100644 --- a/lib/hardware/hardware_led.hpp +++ b/lib/hardware/hardware_led.hpp @@ -1,21 +1,30 @@ #pragma once #include "hardware.pb.h" -#include +#include /** * @class HardwareLed - * @brief Manages an LED strip on ESP8266 using Adafruit NeoPixel library. + * @brief Manages an LED strip on ESP8266 using FastLED library. * Supports animations defined by hardware_LedConfig (static, pulse, fade, flicker). + * Template parameter PIN specifies the GPIO pin at compile time. + * + * @tparam PIN The GPIO pin connected to the LED strip (e.g., 2 for D2 on ESP8266). */ +template class HardwareLed { public: using AnimationCallback = void (*)(); - HardwareLed(uint8_t pin, uint8_t numPixels = 1); + /** + * @brief Constructor for HardwareLed. + * @param numPixels Number of pixels in the strip (default: 1). + */ + HardwareLed(uint8_t numPixels = 1); + ~HardwareLed(); void begin(); void end(); - void update(); // Removed const + void update(); void set(const hardware_LedConfig& config); void setAnimationCallback(AnimationCallback cb) { m_callback = cb; } float estimateCurrent_mA() const; @@ -23,13 +32,15 @@ public: private: void applyStatic(const hardware_StaticParams& params); void applyPulse(const hardware_PulseParams& params); - void applyFade(const hardware_FadeParams& params); // Removed const + void applyFade(const hardware_FadeParams& params); void applyFlicker(const hardware_FlickerParams& params); void setColor(uint32_t color, uint8_t brightness = 255); uint32_t lerpColor(uint32_t color1, uint32_t color2, float t) const; - Adafruit_NeoPixel m_strip; + CRGB* m_leds; // Dynamic array for pixel data + uint8_t m_numPixels; hardware_LedConfig m_currentConfig = hardware_LedConfig_init_default; + bool m_isActive; unsigned long m_startTime; uint8_t m_pulseState; unsigned long m_lastPulseTime; @@ -39,6 +50,5 @@ private: uint32_t m_fadeTargetColor; float m_fadeProgress; unsigned long m_fadeStartTime; - bool m_isActive; AnimationCallback m_callback = nullptr; }; \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index caac4be..9c3ac30 100644 --- a/platformio.ini +++ b/platformio.ini @@ -17,7 +17,7 @@ monitor_speed = 9600 board_build.filesystem = littlefs lib_deps = miguelbalboa/MFRC522@^1.4.12 - adafruit/Adafruit NeoPixel@^1.15.1 + ;adafruit/Adafruit NeoPixel@^1.15.1 fastled/FastLED@^3.10.3 nanopb/Nanopb@^0.4.91 custom_nanopb_protos = diff --git a/src/main.cpp b/src/main.cpp index 37be572..a2c2d70 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,7 +4,7 @@ #include "hardware.pb.h" // Demo for HardwareLed -HardwareLed led(2); // Assuming NeoPixel on pin 4 (D2 on ESP8266) +HardwareLed<2> led; // Assuming NeoPixel on pin 2 (D2 on ESP8266) // Demo for HardwareRfid HardwareRfid rfid(4, 5); // SS=D2 (GPIO4), RST=D1 (GPIO5)