#pragma once #include #include "../Config.h" class Power: public Figment, ConfigTaskMixin { public: Power() : Figment("Power") {state = Task::Running;} void handleEvent(const InputEvent& evt) override { switch (evt.intent) { case InputEvent::PowerToggle: m_powerState = m_powerState.value() <= 128 ? 255 : 0; m_forced = false; Log.notice("Power toggled to %t", m_powerState); break; case InputEvent::SetPower: m_powerState = evt.asInt() == 0 ? 0 : 255; m_forced = false; Log.notice("Power state is now %t", m_powerState); break; case InputEvent::SetBrightness: m_brightness = evt.asInt(); m_forced = false; break; case InputEvent::Beat: m_beatDecay.set(0, 255); break; default: ConfigTaskMixin::handleEvent(evt); } } void handleConfigChange(const Configuration& config) override; void loop() override { ConfigTaskMixin::loop(); m_powerState.update(); m_brightness.update(); EVERY_N_MILLISECONDS(20) { m_beatDecay.update(13); } } void render(Display* dpy) const override { if (F_LIKELY(m_valid && !m_forced)) { const uint8_t decayedBrightness = scale8((uint8_t)m_brightness, m_useBPM ? ease8InOutCubic((uint8_t)m_beatDecay) : 255); const uint8_t clippedBrightness = std::min(decayedBrightness, (uint8_t)255); const uint8_t scaledBrightness = scale8(m_powerState, clippedBrightness); const uint8_t videoBrightness = brighten8_video(scaledBrightness); const uint8_t powerBrightness = calculate_max_brightness_for_power_mW(videoBrightness, m_voltage * m_milliamps); FastLED.setBrightness(powerBrightness); } } void forceBrightness(uint8_t v); const std::vector& commands() const override; private: AnimatedNumber m_powerState = 255; AnimatedNumber m_brightness = 255; AnimatedNumber m_beatDecay = 255; uint8_t m_voltage = 5; uint16_t m_milliamps = 500; bool m_valid = true; bool m_useBPM = false; bool m_forced = false; };