2019-05-10 05:17:29 +00:00
|
|
|
#include "./Renderer.h"
|
|
|
|
#include "./Display.h"
|
2023-12-23 10:06:50 +00:00
|
|
|
#include "./MainLoop.h"
|
2019-05-10 05:17:29 +00:00
|
|
|
|
2021-03-29 08:10:55 +00:00
|
|
|
#include <ArduinoLog.h>
|
|
|
|
|
2023-12-11 06:50:28 +00:00
|
|
|
#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;
|
|
|
|
}
|
|
|
|
|
2019-05-10 05:17:29 +00:00
|
|
|
void
|
|
|
|
Renderer::loop()
|
|
|
|
{
|
2023-12-20 08:17:10 +00:00
|
|
|
uint16_t totalPower = 0;
|
2019-05-10 05:17:29 +00:00
|
|
|
for(Display* dpy : m_displays) {
|
2023-12-20 08:17:10 +00:00
|
|
|
totalPower += calculate_unscaled_power_mW(dpy->pixelBacking(), dpy->pixelCount());
|
2019-05-10 05:17:29 +00:00
|
|
|
for(Figment* figment : m_figments) {
|
|
|
|
if (figment->state == Task::Running) {
|
2022-06-11 09:02:27 +00:00
|
|
|
#if defined(BOARD_ESP32) or defined(BOARD_ESP8266)
|
2021-04-10 18:10:25 +00:00
|
|
|
unsigned int frameStart = ESP.getCycleCount();
|
2022-06-11 09:02:27 +00:00
|
|
|
#endif
|
|
|
|
Log.verbose("Render %s", figment->name);
|
2023-12-11 06:50:28 +00:00
|
|
|
s_lastFigmentName = figment->name;
|
2019-05-10 05:17:29 +00:00
|
|
|
figment->render(dpy);
|
2022-06-11 09:02:27 +00:00
|
|
|
#if defined(BOARD_ESP32) or defined(BOARD_ESP8266)
|
2021-04-10 18:10:25 +00:00
|
|
|
unsigned int runtime = (ESP.getCycleCount() - frameStart) / 160000;
|
2022-06-11 09:02:27 +00:00
|
|
|
#else
|
|
|
|
unsigned int runtime = 0;
|
|
|
|
#endif
|
2021-04-10 18:10:25 +00:00
|
|
|
if (runtime >= 8) {
|
2022-06-11 09:02:27 +00:00
|
|
|
Log.warning("SLOW RENDER: %s took %dms!", figment->name, runtime);
|
2021-04-10 18:10:25 +00:00
|
|
|
}
|
2019-05-10 05:17:29 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2023-12-23 10:06:50 +00:00
|
|
|
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);
|
2021-03-29 08:10:55 +00:00
|
|
|
FastLED.countFPS();
|
2019-05-10 05:17:29 +00:00
|
|
|
}
|
|
|
|
|
2023-12-20 08:17:10 +00:00
|
|
|
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();
|
2023-12-23 10:06:50 +00:00
|
|
|
Log.notice("Brightness is now %d (%d requested)", (uint8_t)m_brightness, evt.asInt());
|
2023-12-20 08:17:10 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t
|
|
|
|
Renderer::powerScale(uint8_t target, uint32_t totalPower) const
|
|
|
|
{
|
|
|
|
if (m_powerManaged) {
|
2023-12-23 10:06:50 +00:00
|
|
|
const uint32_t maxPower = m_voltage * m_milliamps;
|
2023-12-20 08:17:10 +00:00
|
|
|
uint32_t requested = ((uint32_t)totalPower * target) / 256;
|
2023-12-23 10:06:50 +00:00
|
|
|
if (requested > maxPower) {
|
|
|
|
return (uint32_t)((uint8_t)(target) * (uint32_t)(maxPower)) / ((uint32_t)(requested));
|
2023-12-20 08:17:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return target;
|
|
|
|
}
|
|
|
|
|
2019-05-10 05:17:29 +00:00
|
|
|
void
|
|
|
|
Renderer::onStart()
|
|
|
|
{
|
|
|
|
for(Display* dpy : m_displays) {
|
|
|
|
dpy->clear();
|
|
|
|
}
|
2021-03-29 08:10:55 +00:00
|
|
|
FastLED.show();
|
2019-05-10 05:17:29 +00:00
|
|
|
}
|
2023-12-20 08:17:10 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
Renderer::doOn(Args& args, Print& print)
|
2023-12-20 08:29:10 +00:00
|
|
|
{
|
2023-12-23 10:06:50 +00:00
|
|
|
MainLoop::instance()->dispatch(InputEvent{InputEvent::SetPower, 255});
|
2023-12-20 08:29:10 +00:00
|
|
|
}
|
2023-12-20 08:17:10 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
Renderer::doOff(Args& args, Print& print)
|
2023-12-20 08:29:10 +00:00
|
|
|
{
|
2023-12-23 10:06:50 +00:00
|
|
|
MainLoop::instance()->dispatch(InputEvent{InputEvent::SetPower, 0});
|
2023-12-20 08:29:10 +00:00
|
|
|
}
|
2023-12-20 08:17:10 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
Renderer::doBrightness(Args& args, Print& print)
|
2023-12-20 08:29:10 +00:00
|
|
|
{
|
2023-12-23 10:06:50 +00:00
|
|
|
MainLoop::instance()->dispatch(InputEvent{InputEvent::SetBrightness, atoi(args[1].c_str())});
|
2023-12-20 08:29:10 +00:00
|
|
|
}
|
2023-12-20 08:17:10 +00:00
|
|
|
|
|
|
|
const std::vector<Command>&
|
|
|
|
Renderer::commands() const
|
|
|
|
{
|
|
|
|
static const std::vector<Command> _commands = {
|
|
|
|
Command{"brightness", &Renderer::doBrightness},
|
|
|
|
Command{"on", &Renderer::doOn},
|
|
|
|
Command{"off", &Renderer::doOff}
|
|
|
|
};
|
|
|
|
|
|
|
|
return _commands;
|
|
|
|
}
|