#include "hardware_led.hpp" #include HardwareLed::HardwareLed(uint8_t pin, uint8_t numPixels) : _strip(numPixels, pin, NEO_GRB + NEO_KHZ800), _isActive(false) {} void HardwareLed::begin() { _strip.begin(); _strip.show(); // Turn off } void HardwareLed::end() { _strip.clear(); _strip.show(); } void HardwareLed::update() { if (!_isActive) return; unsigned long now = millis(); if (_currentConfig.duration_ms > 0 && now - _startTime >= _currentConfig.duration_ms) { _isActive = false; _strip.clear(); _strip.show(); return; } switch (_currentConfig.which_animation_params) { case hardware_LedConfig_static_params_tag: applyStatic(_currentConfig.animation_params.static_params); break; case hardware_LedConfig_pulse_params_tag: applyPulse(_currentConfig.animation_params.pulse_params); break; case hardware_LedConfig_fade_params_tag: applyFade(_currentConfig.animation_params.fade_params); break; case hardware_LedConfig_flicker_params_tag: applyFlicker(_currentConfig.animation_params.flicker_params); break; default: break; } } void HardwareLed::set(const hardware_LedConfig& config) { _currentConfig = config; _startTime = millis(); _isActive = true; _pulseState = 0; _lastPulseTime = _startTime; _fadeIndex = 0; _lastFadeTime = _startTime; if (_currentConfig.which_animation_params == 5 && _currentConfig.animation_params.fade_params.colors_count > 0) { _fadeCurrentColor = _currentConfig.animation_params.fade_params.colors[0]; _fadeTargetColor = _currentConfig.animation_params.fade_params.colors[0]; _fadeProgress = 1.0f; _fadeStartTime = _startTime; } // Immediately apply initial state update(); } void HardwareLed::applyStatic(const hardware_StaticParams& params) { setColor(params.color, _currentConfig.brightness); } void HardwareLed::applyPulse(const hardware_PulseParams& params) { unsigned long now = millis(); float phase = fmod((now - _startTime) / (float)params.speed_ms, 1.0f); float brightnessFactor = 0.5f + 0.5f * sin(2 * PI * phase); uint8_t pulseBrightness = _currentConfig.brightness * brightnessFactor; setColor(params.color, pulseBrightness); } void HardwareLed::applyFade(const hardware_FadeParams& params) { if (params.colors_count == 0) return; unsigned long now = millis(); if (_fadeProgress >= 1.0f) { // Time to switch to next color _fadeIndex = (_fadeIndex + 1) % params.colors_count; _fadeCurrentColor = _fadeTargetColor; _fadeTargetColor = params.colors[_fadeIndex]; _fadeProgress = 0.0f; _fadeStartTime = now; } _fadeProgress = (now - _fadeStartTime) / (float)params.speed_ms; if (_fadeProgress > 1.0f) _fadeProgress = 1.0f; uint32_t interpolatedColor = lerpColor(_fadeCurrentColor, _fadeTargetColor, _fadeProgress); setColor(interpolatedColor, _currentConfig.brightness); } void HardwareLed::applyFlicker(const hardware_FlickerParams& params) { // Simple random flicker based on intensity uint8_t threshold = map(params.intensity, 0, 100, 0, 255); if (random(255) < threshold) { setColor(params.color, _currentConfig.brightness); } else { _strip.clear(); _strip.show(); } } void HardwareLed::setColor(uint32_t color, uint8_t brightness) { _strip.setBrightness(brightness); _strip.setPixelColor(0, color); _strip.show(); } uint32_t HardwareLed::lerpColor(uint32_t color1, uint32_t color2, float t) { 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; return (r << 16) | (g << 8) | b; }