2019-05-10 05:17:29 +00:00
|
|
|
#pragma once
|
2021-03-29 08:10:55 +00:00
|
|
|
#include <Arduino.h>
|
2019-05-10 05:17:29 +00:00
|
|
|
#include <functional>
|
2021-03-29 08:10:55 +00:00
|
|
|
#include <ArduinoLog.h>
|
2019-05-10 05:17:29 +00:00
|
|
|
|
2023-02-19 17:40:37 +00:00
|
|
|
#define F_LIKELY(x) __builtin_expect(!!(x), true)
|
|
|
|
#define F_UNLIKELY(x) __builtin_expect(!!(x), false)
|
|
|
|
|
2019-05-10 05:17:29 +00:00
|
|
|
class Display;
|
|
|
|
class InputEvent;
|
|
|
|
class InputSource;
|
|
|
|
|
2023-03-03 18:43:51 +00:00
|
|
|
/**
|
|
|
|
* A generic interface for anything that can be executed and respond to events.
|
|
|
|
*/
|
2021-03-28 01:19:55 +00:00
|
|
|
struct Loopable {
|
2023-03-03 18:43:51 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Called by the MainLoop to process events
|
|
|
|
*/
|
2019-05-10 05:17:29 +00:00
|
|
|
virtual void handleEvent(const InputEvent& event) {}
|
2023-03-03 18:43:51 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Called on every MainLoop tick
|
|
|
|
*/
|
2019-05-10 05:17:29 +00:00
|
|
|
virtual void loop() = 0;
|
2021-03-28 01:19:55 +00:00
|
|
|
};
|
|
|
|
|
2023-03-03 18:43:51 +00:00
|
|
|
/**
|
|
|
|
* A Loopable that can be named and may be started or stopped in a MainLoop.
|
|
|
|
*/
|
2021-03-28 01:19:55 +00:00
|
|
|
struct Task : public virtual Loopable {
|
2023-03-03 18:43:51 +00:00
|
|
|
/**
|
|
|
|
* Implement in a subclass to run when the task is started
|
|
|
|
* The default implementation does nothing.
|
|
|
|
*/
|
2019-05-10 05:17:29 +00:00
|
|
|
virtual void onStart() {};
|
2023-03-03 18:43:51 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Implement in a subclass to run when the task is stopped.
|
|
|
|
* The default implementation does nothing.
|
|
|
|
*/
|
2019-05-10 05:17:29 +00:00
|
|
|
virtual void onStop() {};
|
|
|
|
|
|
|
|
enum State {
|
|
|
|
Running,
|
|
|
|
Stopped,
|
|
|
|
};
|
|
|
|
|
|
|
|
Task() {}
|
2023-02-18 15:33:09 +00:00
|
|
|
explicit Task(const char* name) : name(name) {}
|
2019-05-10 05:17:29 +00:00
|
|
|
|
2023-03-03 18:43:51 +00:00
|
|
|
/**
|
|
|
|
* Starts the task and makes it schedulable
|
|
|
|
*/
|
2021-03-29 08:10:55 +00:00
|
|
|
void start() { state = Running; onStart(); }
|
2023-03-03 18:43:51 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Stops the task and makes it unschedulable
|
|
|
|
*/
|
2021-03-29 08:10:55 +00:00
|
|
|
void stop() { onStop(); state = Stopped; }
|
2023-03-03 18:43:51 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A hacky way to determine if a task is a Figment subclass or not, without
|
|
|
|
* having to resort to RTTI
|
|
|
|
*/
|
2021-03-28 01:19:55 +00:00
|
|
|
virtual bool isFigment() const { return false; }
|
2019-05-10 05:17:29 +00:00
|
|
|
|
2022-06-11 09:02:27 +00:00
|
|
|
const char* name = "";
|
2023-02-18 15:33:09 +00:00
|
|
|
State state = Stopped;
|
2019-05-10 05:17:29 +00:00
|
|
|
};
|
|
|
|
|
2023-03-03 18:43:51 +00:00
|
|
|
/**
|
|
|
|
* Functional lambda interface for creating Tasks
|
|
|
|
*/
|
2021-04-10 18:10:25 +00:00
|
|
|
struct TaskFunc: public Task {
|
|
|
|
TaskFunc(std::function<void()> func) : Task("lambda"), func(func) {}
|
|
|
|
void loop() override {func();}
|
|
|
|
std::function<void()> func;
|
|
|
|
};
|
|
|
|
|
2023-03-03 18:43:51 +00:00
|
|
|
/**
|
|
|
|
* A Task with a graphical output
|
|
|
|
*/
|
2019-05-10 05:17:29 +00:00
|
|
|
struct Figment: public Task {
|
|
|
|
Figment() : Task() {}
|
2022-06-11 09:02:27 +00:00
|
|
|
explicit Figment(const char* name) : Task(name) {}
|
2023-03-03 18:43:51 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Called when the Figment should render its output to a display
|
|
|
|
*/
|
2019-05-10 05:17:29 +00:00
|
|
|
virtual void render(Display* dpy) const = 0;
|
2021-03-28 01:19:55 +00:00
|
|
|
bool isFigment() const override { return true; }
|
2019-05-10 05:17:29 +00:00
|
|
|
};
|
|
|
|
|
2023-03-03 18:43:51 +00:00
|
|
|
/**
|
|
|
|
* Functional lambda interface for creating Figments
|
|
|
|
*/
|
2019-05-10 05:17:29 +00:00
|
|
|
struct FigmentFunc: public Figment {
|
|
|
|
FigmentFunc(std::function<void(Display*)> func) : Figment("lambda"), func(func) {}
|
|
|
|
void loop() override {}
|
|
|
|
void render(Display* dpy) const override {
|
|
|
|
func(dpy);
|
|
|
|
}
|
|
|
|
std::function<void(Display*)> func;
|
|
|
|
};
|