#include "Arduino.h" #include #include #include #include "Platform.h" #include "Static.h" #include "Config.h" #include "LogService.h" #include #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::instance()->coordMap()); // FIXME: rewrite as static task /*FigmentFunc configDisplay([](Display* dpy) { uint8_t brightness = brighten8_video(beatsin8(60)); auto coords = Static::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()); if (Platform::bootopts.crashCount > 0) { Log.warning(u8"Previous crash detected!!!! We're on attempt %d", Platform::bootopts.crashCount); char lastTaskBuf[16]; strncpy(lastTaskBuf, MainLoop::lastTaskName(), sizeof(lastTaskBuf)); lastTaskBuf[15] = 0; Log.error(u8"Crash occurred in task %s", lastTaskBuf); } Log.trace("Startup reason: %d", Platform::bootopts.resetReason); Log.notice(u8"Setting timezone to +2 (CEST)"); Platform::setTimezone(+2); 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::instance()->overrideProfile("setup"); } // Render all layers to the displays Renderer* renderer = new Renderer({&dpy}, std::vector{Platform::beginFigments(), Platform::endFigments()}); std::vector defaultTasks{Platform::beginTasks(), Platform::endTasks()}; defaultTasks.push_back(renderer); runner = new MainLoop{std::vector{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(); }