#include "./Renderer.h" #include "./Display.h" #include "./MainLoop.h" #include #ifndef __NOINIT_ATTR // Pre-defined on esp32 #define __NOINIT_ATTR __attribute__ ((section (".noinit"))) #endif __NOINIT_ATTR const char* s_lastFigmentName; const char* Renderer::lastFigmentName() { return s_lastFigmentName; } void Renderer::loop() { uint16_t totalPower = 0; for(Display* dpy : m_displays) { dpy->clear(); totalPower += calculate_unscaled_power_mW(dpy->pixelBacking(), dpy->pixelCount()); for(Figment* figment : m_figments) { if (figment->state == Task::Running) { #if defined(BOARD_ESP32) or defined(BOARD_ESP8266) unsigned int frameStart = ESP.getCycleCount(); #endif Log.verbose("Render %s", figment->name); s_lastFigmentName = figment->name; figment->render(dpy); #if defined(BOARD_ESP32) or defined(BOARD_ESP8266) unsigned int runtime = (ESP.getCycleCount() - frameStart) / 160000; #else unsigned int runtime = 0; #endif if (runtime >= 8) { Log.warning("SLOW RENDER: %s took %dms!", figment->name, runtime); } } }; } static uint8_t videoBrightness = 255; static uint8_t scaledBrightness = powerScale(videoBrightness, totalPower); EVERY_N_MILLISECONDS(30) { m_powerState.update(); m_brightness.update(); videoBrightness = brighten8_video(min((uint8_t)m_brightness, (uint8_t)m_powerState)); scaledBrightness = powerScale(videoBrightness, totalPower); } FastLED.show(scaledBrightness); FastLED.countFPS(); } void Renderer::handleEvent(const InputEvent& evt) { switch (evt.intent) { case InputEvent::PowerToggle: m_powerState = m_powerState.value() <= 128 ? 255 : 0; Log.notice("Power toggled to %t", m_powerState); break; case InputEvent::SetPower: m_powerState = evt.asInt() == 0 ? 0 : 255; Log.notice("Power state is now %t", m_powerState); break; case InputEvent::SetBrightness: m_brightness = evt.asInt(); Log.notice("Brightness is now %d (%d requested)", (uint8_t)m_brightness, evt.asInt()); break; } } uint8_t Renderer::powerScale(uint8_t target, uint32_t totalPower) const { if (m_powerManaged) { const uint32_t maxPower = m_voltage * m_milliamps; uint32_t requested = ((uint32_t)totalPower * target) / 256; if (requested > maxPower) { return (uint32_t)((uint8_t)(target) * (uint32_t)(maxPower)) / ((uint32_t)(requested)); } } return target; } void Renderer::onStart() { for(Display* dpy : m_displays) { dpy->clear(); } FastLED.show(); } void Renderer::doOn(Args& args, Print& print) { MainLoop::instance()->dispatch(InputEvent{InputEvent::SetPower, 255}); } void Renderer::doOff(Args& args, Print& print) { MainLoop::instance()->dispatch(InputEvent{InputEvent::SetPower, 0}); } void Renderer::doBrightness(Args& args, Print& print) { MainLoop::instance()->dispatch(InputEvent{InputEvent::SetBrightness, atoi(args[1].c_str())}); } const std::vector& Renderer::commands() const { static const std::vector _commands = { Command{"brightness", &Renderer::doBrightness}, Command{"on", &Renderer::doOn}, Command{"off", &Renderer::doOff} }; return _commands; }