main: move more tiny objects out of main.cpp
This commit is contained in:
parent
2848c8ad12
commit
1494dd6405
@ -80,7 +80,18 @@ ConfigService::onStart()
|
|||||||
if (strlen(m_config.data.loadedProfile) == 0) {
|
if (strlen(m_config.data.loadedProfile) == 0) {
|
||||||
strcpy(m_config.data.loadedProfile, "default");
|
strcpy(m_config.data.loadedProfile, "default");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_overrideProfile != nullptr) {
|
||||||
|
loadProfile(m_overrideProfile);
|
||||||
|
} else {
|
||||||
loadProfile(m_config.data.loadedProfile);
|
loadProfile(m_config.data.loadedProfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConfigService::overrideProfile(const char* profileName)
|
||||||
|
{
|
||||||
|
m_overrideProfile = profileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -36,10 +36,12 @@ struct ConfigService: public Task {
|
|||||||
void handleEvent(const InputEvent &evt) override;
|
void handleEvent(const InputEvent &evt) override;
|
||||||
const CoordinateMapping* coordMap() const { return &m_jsonMap; }
|
const CoordinateMapping* coordMap() const { return &m_jsonMap; }
|
||||||
const char* loadedProfile() const;
|
const char* loadedProfile() const;
|
||||||
|
void overrideProfile(const char* profileName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HardwareConfig m_config;
|
HardwareConfig m_config;
|
||||||
JsonCoordinateMapping m_jsonMap;
|
JsonCoordinateMapping m_jsonMap;
|
||||||
|
const char* m_overrideProfile = nullptr;
|
||||||
|
|
||||||
void loadProfile(const char* name);
|
void loadProfile(const char* name);
|
||||||
void loadMap(const String& mapName);
|
void loadMap(const String& mapName);
|
||||||
|
56
src/SafeMode.cpp
Normal file
56
src/SafeMode.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include "./SafeMode.h"
|
||||||
|
#include "./LogService.h"
|
||||||
|
#include "./Platform.h"
|
||||||
|
#include "./Static.h"
|
||||||
|
#include "./Config.h"
|
||||||
|
|
||||||
|
TaskFunc safeModeNag([]{
|
||||||
|
static uint8_t frame = 0;
|
||||||
|
static CRGB* leds = FastLED.leds();
|
||||||
|
EVERY_N_SECONDS(30) {
|
||||||
|
Log.fatal("I am running in safe mode!");
|
||||||
|
}
|
||||||
|
EVERY_N_MILLISECONDS(16) {
|
||||||
|
frame++;
|
||||||
|
for(int i = 0; i < HardwareConfig::MAX_LED_NUM; i++) {
|
||||||
|
leds[i] = CRGB(0, 0, 0);
|
||||||
|
}
|
||||||
|
for(int idx = 0; idx < 3; idx++) {
|
||||||
|
uint8_t length = beatsin8(5, 3, HardwareConfig::MAX_LED_NUM, 0, idx * 5);
|
||||||
|
for(int i = 0; i < length; i++) {
|
||||||
|
leds[i] += CRGB(scale8(5, beatsin8(5 + i * 7, 0, 255, 0, i*3)), 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FastLED.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
#ifdef CONFIG_WIFI
|
||||||
|
#include "platform/arduino/WiFiTask.h"
|
||||||
|
#endif // CONFIG_WIFI
|
||||||
|
#ifdef CONFIG_OTA
|
||||||
|
#include "platform/arduino/OTA.h"
|
||||||
|
#endif // CONFIG_OTA
|
||||||
|
#ifdef CONFIG_MQTT
|
||||||
|
#include "platform/arduino/MQTTTelemetry.h"
|
||||||
|
#endif // CONFIG_MQTT
|
||||||
|
|
||||||
|
MainLoop
|
||||||
|
SafeMode::safeModeApp{{
|
||||||
|
Static<Platform>::instance(),
|
||||||
|
// System logging
|
||||||
|
Static<LogService>::instance(),
|
||||||
|
&safeModeNag,
|
||||||
|
#ifdef CONFIG_WIFI
|
||||||
|
// ESP Wifi
|
||||||
|
Static<WiFiTask>::instance(),
|
||||||
|
#endif // CONFIG_WIFI
|
||||||
|
#ifdef CONFIG_MQTT
|
||||||
|
// MQTT
|
||||||
|
Static<MQTTTelemetry>::instance(),
|
||||||
|
#endif // CONFIG_MQTT
|
||||||
|
#ifdef CONFIG_OTA
|
||||||
|
// OTA Updates
|
||||||
|
Static<ArduinoOTAUpdater>::instance(),
|
||||||
|
#endif // CONFIG_OTA
|
||||||
|
}};
|
7
src/SafeMode.h
Normal file
7
src/SafeMode.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Figments.h>
|
||||||
|
|
||||||
|
class SafeMode {
|
||||||
|
public:
|
||||||
|
static MainLoop safeModeApp;
|
||||||
|
};
|
5
src/inputs/BPM.cpp
Normal file
5
src/inputs/BPM.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include "./BPM.h"
|
||||||
|
#include "../Static.h"
|
||||||
|
|
||||||
|
STATIC_ALLOC(BPM);
|
||||||
|
STATIC_TASK(BPM);
|
52
src/inputs/BPM.h
Normal file
52
src/inputs/BPM.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Figments.h>
|
||||||
|
|
||||||
|
class BPM : public InputSource {
|
||||||
|
public:
|
||||||
|
BPM() : InputSource("BPM") {}
|
||||||
|
void handleEvent(const InputEvent& evt) override {
|
||||||
|
if (evt.intent == InputEvent::BeatDetect) {
|
||||||
|
m_nextBpm = millis();
|
||||||
|
m_timings.insert(millis());
|
||||||
|
Log.notice("%d timings", m_timings.size());
|
||||||
|
if (m_timings.size() >= 5) {
|
||||||
|
updateBPM();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InputEvent read() override {
|
||||||
|
if (m_bpm > 0) {
|
||||||
|
uint16_t now = millis();
|
||||||
|
if (now >= m_nextBpm) {
|
||||||
|
m_nextBpm += m_bpm;
|
||||||
|
return InputEvent{InputEvent::Beat, m_bpm};
|
||||||
|
}
|
||||||
|
if (now >= m_nextLearn && m_nextLearn != 0) {
|
||||||
|
m_timings.clear();
|
||||||
|
m_nextLearn = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return InputEvent{};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint16_t m_bpm = 0;
|
||||||
|
uint16_t m_nextBpm = 0;
|
||||||
|
uint16_t m_nextLearn = 0;
|
||||||
|
Ringbuf<uint16_t, 7> m_timings;
|
||||||
|
|
||||||
|
void updateBPM() {
|
||||||
|
uint16_t avgDelta = 0;
|
||||||
|
for(uint8_t i = 0; i < m_timings.size() - 1; i++) {
|
||||||
|
uint16_t delta = m_timings.peek(i+1) - m_timings.peek(i);
|
||||||
|
Log.notice("Timing %d Delta %d", m_timings.peek(i), delta);
|
||||||
|
avgDelta += delta;
|
||||||
|
}
|
||||||
|
m_bpm = avgDelta / 4;
|
||||||
|
m_nextLearn = m_bpm * 5 + millis();
|
||||||
|
Log.notice("BPM is now %d", m_bpm);
|
||||||
|
uint16_t trash;
|
||||||
|
m_timings.take(trash);
|
||||||
|
}
|
||||||
|
};
|
5
src/inputs/CircadianRhythm.cpp
Normal file
5
src/inputs/CircadianRhythm.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include "./CircadianRhythm.h"
|
||||||
|
#include "../Static.h"
|
||||||
|
|
||||||
|
STATIC_ALLOC(CircadianRhythm);
|
||||||
|
STATIC_TASK(CircadianRhythm);
|
90
src/inputs/CircadianRhythm.h
Normal file
90
src/inputs/CircadianRhythm.h
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Figments.h>
|
||||||
|
|
||||||
|
struct ScheduleEntry {
|
||||||
|
uint8_t hour;
|
||||||
|
uint8_t brightness;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::array<ScheduleEntry, 10> schedule{{
|
||||||
|
{0, 0},
|
||||||
|
{5, 0},
|
||||||
|
{6, 0},
|
||||||
|
{7, 10},
|
||||||
|
{8, 80},
|
||||||
|
{11, 120},
|
||||||
|
{18, 200},
|
||||||
|
{19, 255},
|
||||||
|
{22, 120},
|
||||||
|
{23, 20}
|
||||||
|
}};
|
||||||
|
|
||||||
|
class CircadianRhythm : public InputSource {
|
||||||
|
private:
|
||||||
|
bool needsUpdate = true;
|
||||||
|
public:
|
||||||
|
CircadianRhythm() : InputSource("CircadianRhythm") {}
|
||||||
|
|
||||||
|
void onStart() {
|
||||||
|
needsUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t brightnessForTime(uint8_t hour, uint8_t minute) const {
|
||||||
|
ScheduleEntry start = schedule.back();
|
||||||
|
ScheduleEntry end = schedule.front();
|
||||||
|
for(ScheduleEntry cur : schedule) {
|
||||||
|
// Find the last hour that is prior to or equal to now
|
||||||
|
if (cur.hour <= hour) {
|
||||||
|
start = cur;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(ScheduleEntry cur : schedule) {
|
||||||
|
// Find the first hour that is after now
|
||||||
|
// If no such hour exists, we should automatically wrap back to hour 0
|
||||||
|
if (cur.hour > hour) {
|
||||||
|
end = cur;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start.hour > end.hour) {
|
||||||
|
end.hour += 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t startTime = start.hour * 60;
|
||||||
|
uint16_t endTime = end.hour * 60;
|
||||||
|
uint16_t nowTime = hour * 60 + minute;
|
||||||
|
|
||||||
|
uint16_t duration = endTime - startTime;
|
||||||
|
uint16_t curDuration = nowTime - startTime;
|
||||||
|
|
||||||
|
uint8_t frac = map8(curDuration, 0, duration);
|
||||||
|
|
||||||
|
return lerp8by8(start.brightness, end.brightness, frac);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
InputEvent read() {
|
||||||
|
EVERY_N_SECONDS(60) {
|
||||||
|
needsUpdate = true;
|
||||||
|
}
|
||||||
|
if (needsUpdate) {
|
||||||
|
uint8_t hour = 0;
|
||||||
|
uint8_t minute = 0;
|
||||||
|
needsUpdate = false;
|
||||||
|
struct tm timeinfo;
|
||||||
|
if (Platform::getLocalTime(&timeinfo)) {
|
||||||
|
hour = timeinfo.tm_hour;
|
||||||
|
minute = timeinfo.tm_min;
|
||||||
|
} else {
|
||||||
|
hour = 0;
|
||||||
|
minute = 0;
|
||||||
|
}
|
||||||
|
Log.notice("Current time: %d:%d", hour, minute);
|
||||||
|
return InputEvent{InputEvent::SetBrightness, brightnessForTime(hour, minute)};
|
||||||
|
}
|
||||||
|
return InputEvent{};
|
||||||
|
}
|
||||||
|
};
|
5
src/inputs/ConfigInput.cpp
Normal file
5
src/inputs/ConfigInput.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include "./ConfigInput.h"
|
||||||
|
#include "./Static.h"
|
||||||
|
|
||||||
|
STATIC_ALLOC(ConfigInput);
|
||||||
|
STATIC_TASK(ConfigInput);
|
77
src/inputs/ConfigInput.h
Normal file
77
src/inputs/ConfigInput.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Figments.h>
|
||||||
|
|
||||||
|
class ConfigInputTask : public BufferedInputSource {
|
||||||
|
public:
|
||||||
|
ConfigInputTask() : BufferedInputSource("ConfigInput") {}
|
||||||
|
|
||||||
|
void handleEvent(const InputEvent& evt) override {
|
||||||
|
if (evt.intent == InputEvent::UserInput) {
|
||||||
|
Buttons::Chord chord = (Buttons::Chord) evt.asInt();
|
||||||
|
switch (chord) {
|
||||||
|
case Buttons::Circle:
|
||||||
|
m_currentIntent = nextIntent();
|
||||||
|
//Log.info("Next setting... (%d)", m_currentIntent);
|
||||||
|
break;
|
||||||
|
case Buttons::CircleTriangle:
|
||||||
|
//Log.info("Increment...");
|
||||||
|
increment();
|
||||||
|
break;
|
||||||
|
case Buttons::CircleCross:
|
||||||
|
//Log.info("Decrement...");
|
||||||
|
decrement();
|
||||||
|
break;
|
||||||
|
case Buttons::Triangle:
|
||||||
|
//Log.info("Save...");
|
||||||
|
setEvent(InputEvent::SaveConfigurationRequest);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
InputEvent::Intent m_currentIntent = InputEvent::SetDisplayLength;
|
||||||
|
|
||||||
|
void decrement() {
|
||||||
|
int current = 0;
|
||||||
|
switch (m_currentIntent) {
|
||||||
|
case InputEvent::SetDisplayLength:
|
||||||
|
current = Static<ConfigService>::instance()->coordMap()->pixelCount;
|
||||||
|
break;
|
||||||
|
case InputEvent::SetDisplayOffset:
|
||||||
|
current = Static<ConfigService>::instance()->coordMap()->startPixel;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
setEvent(InputEvent{m_currentIntent, current - 1});
|
||||||
|
}
|
||||||
|
|
||||||
|
void increment() {
|
||||||
|
int current = 0;
|
||||||
|
switch (m_currentIntent) {
|
||||||
|
case InputEvent::SetDisplayLength:
|
||||||
|
current = Static<ConfigService>::instance()->coordMap()->pixelCount;
|
||||||
|
break;
|
||||||
|
case InputEvent::SetDisplayOffset:
|
||||||
|
current = Static<ConfigService>::instance()->coordMap()->startPixel;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
setEvent(InputEvent{m_currentIntent, current + 1});
|
||||||
|
}
|
||||||
|
|
||||||
|
InputEvent::Intent nextIntent() {
|
||||||
|
switch (m_currentIntent) {
|
||||||
|
case InputEvent::SetDisplayLength:
|
||||||
|
return InputEvent::SetDisplayOffset;
|
||||||
|
case InputEvent::SetDisplayOffset:
|
||||||
|
return InputEvent::SetDisplayLength;
|
||||||
|
default:
|
||||||
|
return InputEvent::None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
319
src/main.cpp
319
src/main.cpp
@ -14,11 +14,10 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "animations/Power.h"
|
#include "animations/Power.h"
|
||||||
#include "animations/Drain.h"
|
|
||||||
#include "animations/InputBlip.h"
|
|
||||||
|
|
||||||
#include "inputs/ColorCycle.h"
|
#include "inputs/ColorCycle.h"
|
||||||
#include "inputs/Buttons.h"
|
#include "inputs/Buttons.h"
|
||||||
|
#include "SafeMode.h"
|
||||||
|
|
||||||
#define MAX_BRIGHTNESS 255
|
#define MAX_BRIGHTNESS 255
|
||||||
//#define PSU_MILLIAMPS 4800
|
//#define PSU_MILLIAMPS 4800
|
||||||
@ -36,9 +35,9 @@ Display dpy(leds, HardwareConfig::MAX_LED_NUM, Static<ConfigService>::instance()
|
|||||||
|
|
||||||
// Setup power management
|
// Setup power management
|
||||||
Power<MAX_BRIGHTNESS, PSU_MILLIAMPS> power;
|
Power<MAX_BRIGHTNESS, PSU_MILLIAMPS> power;
|
||||||
|
|
||||||
REGISTER_TASK(power);
|
REGISTER_TASK(power);
|
||||||
|
|
||||||
|
// FIXME: rewrite as static task
|
||||||
/*FigmentFunc configDisplay([](Display* dpy) {
|
/*FigmentFunc configDisplay([](Display* dpy) {
|
||||||
uint8_t brightness = brighten8_video(beatsin8(60));
|
uint8_t brightness = brighten8_video(beatsin8(60));
|
||||||
auto coords = Static<ConfigService>::instance()->coordMap();
|
auto coords = Static<ConfigService>::instance()->coordMap();
|
||||||
@ -91,63 +90,6 @@ InputMapper keyMap([](const InputEvent& evt) {
|
|||||||
|
|
||||||
REGISTER_TASK(keyMap);
|
REGISTER_TASK(keyMap);
|
||||||
|
|
||||||
class BPM : public InputSource {
|
|
||||||
public:
|
|
||||||
BPM() : InputSource("BPM") {}
|
|
||||||
void handleEvent(const InputEvent& evt) override {
|
|
||||||
if (evt.intent == InputEvent::BeatDetect) {
|
|
||||||
m_nextBpm = millis();
|
|
||||||
m_timings.insert(millis());
|
|
||||||
Log.notice("%d timings", m_timings.size());
|
|
||||||
if (m_timings.size() >= 5) {
|
|
||||||
updateBPM();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InputEvent read() override {
|
|
||||||
if (m_bpm > 0) {
|
|
||||||
uint16_t now = millis();
|
|
||||||
if (now >= m_nextBpm) {
|
|
||||||
m_nextBpm += m_bpm;
|
|
||||||
return InputEvent{InputEvent::Beat, m_bpm};
|
|
||||||
}
|
|
||||||
if (now >= m_nextLearn && m_nextLearn != 0) {
|
|
||||||
m_timings.clear();
|
|
||||||
m_nextLearn = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return InputEvent{};
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint16_t m_bpm = 0;
|
|
||||||
uint16_t m_nextBpm = 0;
|
|
||||||
uint16_t m_nextLearn = 0;
|
|
||||||
Ringbuf<uint16_t, 7> m_timings;
|
|
||||||
|
|
||||||
void updateBPM() {
|
|
||||||
uint16_t avgDelta = 0;
|
|
||||||
for(uint8_t i = 0; i < m_timings.size() - 1; i++) {
|
|
||||||
uint16_t delta = m_timings.peek(i+1) - m_timings.peek(i);
|
|
||||||
Log.notice("Timing %d Delta %d", m_timings.peek(i), delta);
|
|
||||||
avgDelta += delta;
|
|
||||||
}
|
|
||||||
m_bpm = avgDelta / 4;
|
|
||||||
m_nextLearn = m_bpm * 5 + millis();
|
|
||||||
Log.notice("BPM is now %d", m_bpm);
|
|
||||||
uint16_t trash;
|
|
||||||
m_timings.take(trash);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
STATIC_ALLOC(BPM);
|
|
||||||
STATIC_TASK(BPM);
|
|
||||||
|
|
||||||
Renderer configRenderer{
|
|
||||||
{&dpy},
|
|
||||||
{Static<DrainAnimation>::instance(), /*&configDisplay,*/ Static<InputBlip>::instance(), &power}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Cycle some random colors
|
// Cycle some random colors
|
||||||
ColorSequenceInput<9> idleCycle{{
|
ColorSequenceInput<9> idleCycle{{
|
||||||
@ -171,249 +113,7 @@ ColorSequenceInput<7> rainbowCycle{{
|
|||||||
|
|
||||||
REGISTER_TASK(rainbowCycle);
|
REGISTER_TASK(rainbowCycle);
|
||||||
|
|
||||||
/*struct ConfigInputTask: public BufferedInputSource {
|
MainLoop* runner = &SafeMode::safeModeApp;
|
||||||
public:
|
|
||||||
ConfigInputTask() : BufferedInputSource("ConfigInput") {}
|
|
||||||
|
|
||||||
void handleEvent(const InputEvent& evt) override {
|
|
||||||
if (evt.intent == InputEvent::UserInput) {
|
|
||||||
Buttons::Chord chord = (Buttons::Chord) evt.asInt();
|
|
||||||
switch (chord) {
|
|
||||||
case Buttons::Circle:
|
|
||||||
m_currentIntent = nextIntent();
|
|
||||||
//Log.info("Next setting... (%d)", m_currentIntent);
|
|
||||||
break;
|
|
||||||
case Buttons::CircleTriangle:
|
|
||||||
//Log.info("Increment...");
|
|
||||||
increment();
|
|
||||||
break;
|
|
||||||
case Buttons::CircleCross:
|
|
||||||
//Log.info("Decrement...");
|
|
||||||
decrement();
|
|
||||||
break;
|
|
||||||
case Buttons::Triangle:
|
|
||||||
//Log.info("Save...");
|
|
||||||
setEvent(InputEvent::SaveConfigurationRequest);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
InputEvent::Intent m_currentIntent = InputEvent::SetDisplayLength;
|
|
||||||
|
|
||||||
void decrement() {
|
|
||||||
int current = 0;
|
|
||||||
switch (m_currentIntent) {
|
|
||||||
case InputEvent::SetDisplayLength:
|
|
||||||
current = Static<ConfigService>::instance()->coordMap()->pixelCount;
|
|
||||||
break;
|
|
||||||
case InputEvent::SetDisplayOffset:
|
|
||||||
current = Static<ConfigService>::instance()->coordMap()->startPixel;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
setEvent(InputEvent{m_currentIntent, current - 1});
|
|
||||||
}
|
|
||||||
|
|
||||||
void increment() {
|
|
||||||
int current = 0;
|
|
||||||
switch (m_currentIntent) {
|
|
||||||
case InputEvent::SetDisplayLength:
|
|
||||||
current = Static<ConfigService>::instance()->coordMap()->pixelCount;
|
|
||||||
break;
|
|
||||||
case InputEvent::SetDisplayOffset:
|
|
||||||
current = Static<ConfigService>::instance()->coordMap()->startPixel;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
setEvent(InputEvent{m_currentIntent, current + 1});
|
|
||||||
}
|
|
||||||
|
|
||||||
InputEvent::Intent nextIntent() {
|
|
||||||
switch (m_currentIntent) {
|
|
||||||
case InputEvent::SetDisplayLength:
|
|
||||||
return InputEvent::SetDisplayOffset;
|
|
||||||
case InputEvent::SetDisplayOffset:
|
|
||||||
return InputEvent::SetDisplayLength;
|
|
||||||
default:
|
|
||||||
return InputEvent::None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};*/
|
|
||||||
|
|
||||||
struct ScheduleEntry {
|
|
||||||
uint8_t hour;
|
|
||||||
uint8_t brightness;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::array<ScheduleEntry, 10> schedule{{
|
|
||||||
{0, 0},
|
|
||||||
{5, 0},
|
|
||||||
{6, 0},
|
|
||||||
{7, 10},
|
|
||||||
{8, 80},
|
|
||||||
{11, 120},
|
|
||||||
{18, 200},
|
|
||||||
{19, 255},
|
|
||||||
{22, 120},
|
|
||||||
{23, 20}
|
|
||||||
}};
|
|
||||||
|
|
||||||
class CircadianRhythm : public InputSource {
|
|
||||||
private:
|
|
||||||
bool needsUpdate = true;
|
|
||||||
public:
|
|
||||||
CircadianRhythm() : InputSource("CircadianRhythm") {}
|
|
||||||
|
|
||||||
void onStart() {
|
|
||||||
needsUpdate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t brightnessForTime(uint8_t hour, uint8_t minute) const {
|
|
||||||
ScheduleEntry start = schedule.back();
|
|
||||||
ScheduleEntry end = schedule.front();
|
|
||||||
for(ScheduleEntry cur : schedule) {
|
|
||||||
// Find the last hour that is prior to or equal to now
|
|
||||||
if (cur.hour <= hour) {
|
|
||||||
start = cur;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(ScheduleEntry cur : schedule) {
|
|
||||||
// Find the first hour that is after now
|
|
||||||
// If no such hour exists, we should automatically wrap back to hour 0
|
|
||||||
if (cur.hour > hour) {
|
|
||||||
end = cur;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (start.hour > end.hour) {
|
|
||||||
end.hour += 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t startTime = start.hour * 60;
|
|
||||||
uint16_t endTime = end.hour * 60;
|
|
||||||
uint16_t nowTime = hour * 60 + minute;
|
|
||||||
|
|
||||||
uint16_t duration = endTime - startTime;
|
|
||||||
uint16_t curDuration = nowTime - startTime;
|
|
||||||
|
|
||||||
uint8_t frac = map8(curDuration, 0, duration);
|
|
||||||
|
|
||||||
return lerp8by8(start.brightness, end.brightness, frac);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
InputEvent read() {
|
|
||||||
EVERY_N_SECONDS(60) {
|
|
||||||
needsUpdate = true;
|
|
||||||
}
|
|
||||||
if (needsUpdate) {
|
|
||||||
uint8_t hour = 0;
|
|
||||||
uint8_t minute = 0;
|
|
||||||
needsUpdate = false;
|
|
||||||
struct tm timeinfo;
|
|
||||||
if (Platform::getLocalTime(&timeinfo)) {
|
|
||||||
hour = timeinfo.tm_hour;
|
|
||||||
minute = timeinfo.tm_min;
|
|
||||||
} else {
|
|
||||||
hour = 0;
|
|
||||||
minute = 0;
|
|
||||||
}
|
|
||||||
Log.notice("Current time: %d:%d", hour, minute);
|
|
||||||
return InputEvent{InputEvent::SetBrightness, brightnessForTime(hour, minute)};
|
|
||||||
}
|
|
||||||
return InputEvent{};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
STATIC_ALLOC(CircadianRhythm);
|
|
||||||
STATIC_TASK(CircadianRhythm);
|
|
||||||
|
|
||||||
// A special mainloop app for configuring hardware settings that reboots the
|
|
||||||
// device when the user is finished.
|
|
||||||
/*MainLoop configApp{{
|
|
||||||
Static<Platform>::instance(),
|
|
||||||
|
|
||||||
// Manage read/write of configuration data
|
|
||||||
Static<ConfigService>::instance(),
|
|
||||||
|
|
||||||
// Read hardware inputs
|
|
||||||
Static<Buttons>::instance(),
|
|
||||||
|
|
||||||
// Map input buttons to configuration commands
|
|
||||||
new ConfigInputTask(),
|
|
||||||
|
|
||||||
// System logging
|
|
||||||
Static<LogService>::instance(),
|
|
||||||
|
|
||||||
// Fill the entire display with a color, to see size
|
|
||||||
&configDisplay,
|
|
||||||
// Render some basic input feedback
|
|
||||||
&inputBlip,
|
|
||||||
// Render it all
|
|
||||||
&configRenderer,
|
|
||||||
}};*/
|
|
||||||
|
|
||||||
MainLoop configApp{std::vector<Task*>()};
|
|
||||||
|
|
||||||
TaskFunc safeModeNag([]{
|
|
||||||
static uint8_t frame = 0;
|
|
||||||
EVERY_N_SECONDS(30) {
|
|
||||||
Log.fatal("I am running in safe mode!");
|
|
||||||
}
|
|
||||||
EVERY_N_MILLISECONDS(16) {
|
|
||||||
frame++;
|
|
||||||
for(int i = 0; i < HardwareConfig::MAX_LED_NUM; i++) {
|
|
||||||
leds[i] = CRGB(0, 0, 0);
|
|
||||||
}
|
|
||||||
for(int idx = 0; idx < 3; idx++) {
|
|
||||||
uint8_t length = beatsin8(5, 3, HardwareConfig::MAX_LED_NUM, 0, idx * 5);
|
|
||||||
for(int i = 0; i < length; i++) {
|
|
||||||
leds[i] += CRGB(scale8(5, beatsin8(5 + i * 7, 0, 255, 0, i*3)), 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FastLED.show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
#ifdef CONFIG_WIFI
|
|
||||||
#include "platform/arduino/WiFiTask.h"
|
|
||||||
#endif // CONFIG_WIFI
|
|
||||||
#ifdef CONFIG_OTA
|
|
||||||
#include "platform/arduino/OTA.h"
|
|
||||||
#endif // CONFIG_OTA
|
|
||||||
#ifdef CONFIG_MQTT
|
|
||||||
#include "platform/arduino/MQTTTelemetry.h"
|
|
||||||
#endif // CONFIG_MQTT
|
|
||||||
|
|
||||||
MainLoop safeModeApp{{
|
|
||||||
Static<Platform>::instance(),
|
|
||||||
// System logging
|
|
||||||
Static<LogService>::instance(),
|
|
||||||
&safeModeNag,
|
|
||||||
#ifdef CONFIG_WIFI
|
|
||||||
// ESP Wifi
|
|
||||||
Static<WiFiTask>::instance(),
|
|
||||||
#endif // CONFIG_WIFI
|
|
||||||
#ifdef CONFIG_MQTT
|
|
||||||
// MQTT
|
|
||||||
Static<MQTTTelemetry>::instance(),
|
|
||||||
#endif // CONFIG_MQTT
|
|
||||||
#ifdef CONFIG_OTA
|
|
||||||
// OTA Updates
|
|
||||||
Static<ArduinoOTAUpdater>::instance(),
|
|
||||||
#endif // CONFIG_OTA
|
|
||||||
}};
|
|
||||||
|
|
||||||
MainLoop* runner = &safeModeApp;
|
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
// Turn on,
|
// Turn on,
|
||||||
@ -436,18 +136,19 @@ void setup() {
|
|||||||
// Tune in,
|
// Tune in,
|
||||||
if (Platform::bootopts.isSafeMode) {
|
if (Platform::bootopts.isSafeMode) {
|
||||||
Log.notice(u8"⚠️ Starting Figment in safe mode!!!");
|
Log.notice(u8"⚠️ Starting Figment in safe mode!!!");
|
||||||
runner = &safeModeApp;
|
runner = &SafeMode::safeModeApp;
|
||||||
FastLED.showColor(CRGB(5, 0, 0));
|
FastLED.showColor(CRGB(5, 0, 0));
|
||||||
FastLED.show();
|
FastLED.show();
|
||||||
} else if (Platform::bootopts.isSetup) {
|
|
||||||
Log.notice(u8"🔧 Starting Figment in configuration mode...");
|
|
||||||
FastLED.showColor(CRGB(0, 5, 0));
|
|
||||||
//runner = &configApp;
|
|
||||||
} else {
|
} else {
|
||||||
Log.notice(u8"🌌 Starting Figment...");
|
Log.notice(u8"🌌 Starting Figment...");
|
||||||
|
|
||||||
|
if (Platform::bootopts.isSetup) {
|
||||||
|
Log.notice(u8"🔧 Booting up into setup profile!!!");
|
||||||
|
Static<ConfigService>::instance()->overrideProfile("setup");
|
||||||
|
}
|
||||||
|
|
||||||
// Render all layers to the displays
|
// Render all layers to the displays
|
||||||
Renderer* renderer = new Renderer({&dpy}, std::vector<Figment*>{Platform::beginFigments(), Platform::endFigments()});
|
Renderer* renderer = new Renderer({&dpy}, std::vector<Figment*>{Platform::beginFigments(), Platform::endFigments()});
|
||||||
|
|
||||||
std::vector<Task*> defaultTasks{Platform::beginTasks(), Platform::endTasks()};
|
std::vector<Task*> defaultTasks{Platform::beginTasks(), Platform::endTasks()};
|
||||||
defaultTasks.push_back(renderer);
|
defaultTasks.push_back(renderer);
|
||||||
runner = new MainLoop{std::vector<Task*>{defaultTasks.begin(), defaultTasks.end()}};
|
runner = new MainLoop{std::vector<Task*>{defaultTasks.begin(), defaultTasks.end()}};
|
||||||
|
Loading…
Reference in New Issue
Block a user