renderbug-cpp/src/main.cpp
2023-12-20 09:28:53 +01:00

139 lines
4.0 KiB
C++

#include "Arduino.h"
#include <FastLED.h>
#include <Figments.h>
#include <ArduinoLog.h>
#include "Platform.h"
#include "Static.h"
#include "Config.h"
#include "LogService.h"
#include <time.h>
#include "inputs/ColorCycle.h"
#include "inputs/Buttons.h"
#include "SafeMode.h"
// Setup FastLED and the display
CRGB leds[HardwareConfig::MAX_LED_NUM];
Display dpy(leds, HardwareConfig::MAX_LED_NUM, Static<ConfigService>::instance()->coordMap());
// FIXME: rewrite as static task
/*FigmentFunc configDisplay([](Display* dpy) {
uint8_t brightness = brighten8_video(beatsin8(60));
auto coords = Static<ConfigService>::instance()->coordMap();
for(int i = 0; i < HardwareConfig::MAX_LED_NUM; i++) {
if (i < coords->startPixel || i > coords->startPixel + coords->pixelCount) {
dpy->pixelAt(i) += CRGB(brightness, 0, 0);
} else {
dpy->pixelAt(i) += CRGB(255 - brightness, 255 - brightness, 255 - brightness);
}
}
});*/
InputMapper keyMap([](const InputEvent& evt) {
if (evt.intent == InputEvent::UserInput) {
Buttons::Chord chord = (Buttons::Chord)evt.asInt();
switch(chord) {
case Buttons::Circle:
return InputEvent::PowerToggle;
break;
case Buttons::Triangle:
return InputEvent::NextPattern;
break;
case Buttons::Cross:
return InputEvent::UserInput;
break;
default:
break;
}
}
return InputEvent::None;
}, "Keymap");
REGISTER_TASK(keyMap);
// Cycle some random colors
ColorSequenceInput<9> idleCycle{{
CRGB(0, 123, 167), // Cerulean
CRGB(80, 200, 120), // Emerald
CRGB(207, 113, 175), // Sky Magenta
CRGB(128, 0, 128), // Purple
CRGB(255, 255, 255), // White
CRGB(0, 255, 255), // Cyan
}, "IdleColors"};
REGISTER_TASK(idleCycle);
ColorSequenceInput<7> rainbowCycle{{
CRGB(255, 0, 0), // Red
CRGB(255, 127, 0), // Yellow
CRGB(0, 255, 0), // Green
CRGB(0, 0, 255), // Blue
CRGB(128, 0, 128), // Purple
}, "Rainbow"};
REGISTER_TASK(rainbowCycle);
MainLoop* runner = &SafeMode::safeModeApp;
void setup() {
// Turn on,
Platform::preSetup();
Log.notice(u8"🐛 Booting Renderbug!");
Log.notice(u8"🐞 I am built for %d LEDs on pin %d", HardwareConfig::MAX_LED_NUM, RENDERBUG_LED_PIN);
Log.notice(u8"📡 Platform %s version %s", Platform::name(), Platform::version());
Log.notice(u8"Setting timezone to +2 (CEST)");
Platform::setTimezone(+1);
Log.trace(u8"Setting up platform...");
Platform::setup();
Platform::bootSplash();
Log.notice(u8"💡 Starting FastLED on %d LEDs...", HardwareConfig::MAX_LED_NUM);
Platform::addLEDs(leds, HardwareConfig::MAX_LED_NUM);
// Tune in,
if (Platform::bootopts.isSafeMode) {
Log.warning(u8"⚠️ Starting Figment in safe mode!!!");
runner = &SafeMode::safeModeApp;
for(auto task : runner->scheduler.tasks) {
task->state = Task::Running;
}
FastLED.showColor(CRGB(255, 0, 0));
FastLED.show();
} else {
Log.notice(u8"🌌 Starting Figment...");
if (Platform::bootopts.isSetup) {
Log.warning(u8"🔧 Booting up into setup profile!!!");
Static<ConfigService>::instance()->overrideProfile("setup");
}
// Render all layers to the displays
Renderer* renderer = new Renderer({&dpy}, std::vector<Figment*>{Platform::beginFigments(), Platform::endFigments()});
std::vector<Task*> defaultTasks{Platform::beginTasks(), Platform::endTasks()};
defaultTasks.push_back(renderer);
runner = new MainLoop{std::vector<Task*>{defaultTasks.begin(), defaultTasks.end()}};
}
Serial.flush();
runner->start();
Log.notice(u8"💽 %l bytes of free RAM", Platform::freeRam());
Log.notice(u8"🚀 Setup complete! Ready to rock and roll.");
Serial.flush();
}
// Drop out.
void loop() {
EVERY_N_SECONDS(5) {
Log.notice("FPS: %d\tRAM: %d", FastLED.getFPS(), Platform::freeRam());
}
runner->loop();
}