renderbug/firmware/Figments/Input.h

154 lines
3.4 KiB
C
Raw Normal View History

2019-05-10 05:17:29 +00:00
#pragma once
#include "application.h"
#include "./Geometry.h"
#include "./Figment.h"
2021-03-28 21:50:31 +00:00
#include "./Ringbuf.h"
2019-05-10 05:17:29 +00:00
#include "FastLED/FastLED.h"
typedef Vector3d<int> MotionVec;
struct Variant {
enum Type {
Null,
Integer,
String,
Color,
};
Variant(int v)
: type(Integer), m_value{.asInt=v} {}
Variant(const char* v)
: type(String), m_value{.asString=v} {}
Variant(const NSFastLED::CRGB &v)
: type(Color), m_value{.asRGB={v.r, v.g, v.b}} {}
Variant()
: type(Null) {}
Type type;
const char* asString() const;
NSFastLED::CRGB asRGB() const;
int asInt() const;
private:
union {
int asInt;
const char* asString;
uint8_t asRGB[3];
} m_value;
};
struct InputEvent: public Variant {
enum Intent {
2021-03-28 01:19:55 +00:00
// An empty non-event
2019-05-10 05:17:29 +00:00
None,
2021-03-28 01:19:55 +00:00
// An input from the user, for other tasks to translate into canonical
// types. Makes for easy button re-mapping on the fly.
UserInput,
//
// The canonical types
//
// Hardware inputs
ButtonPress,
Acceleration,
NetworkStatus,
NetworkActivity,
// Power management
2019-05-10 05:17:29 +00:00
PowerToggle,
SetPower,
SetBrightness,
2021-03-28 01:19:55 +00:00
// Animation sequencing
2019-05-10 05:17:29 +00:00
PreviousPattern,
NextPattern,
SetPattern,
2021-03-28 01:19:55 +00:00
PreviousScene,
NextScene,
SetScene,
// Timekeeping
ScheduleChange,
// Task management
2019-05-10 05:17:29 +00:00
StartThing,
StopThing,
2021-03-28 01:19:55 +00:00
// Configuration
SetDisplayOffset,
SetDisplayLength,
SetColor,
SaveConfigurationRequest,
// Firmware events
FirmwareUpdate,
2019-05-10 05:17:29 +00:00
};
template<typename Value>
InputEvent(Intent s, Value v)
: Variant(v), intent(s) {}
InputEvent(Intent s)
: Variant(), intent(s) {}
InputEvent()
: Variant(), intent(None) {}
Intent intent;
};
class InputSource: public Task {
public:
InputSource() : Task() {}
InputSource(const char* name) : Task(name) {}
InputSource(Task::State initialState) : Task(initialState) {}
InputSource(const char* name, Task::State initialState) : Task(name, initialState) {}
void loop() override;
virtual InputEvent read() = 0;
};
class InputFunc : public InputSource {
public:
InputFunc(std::function<InputEvent(void)> f) : InputSource(), m_func(f) {}
InputFunc(std::function<InputEvent(void)> f, const char* name) : InputSource(name), m_func(f) {}
InputFunc(std::function<InputEvent(void)> f, const char* name, Task::State initialState) : InputSource(name, initialState), m_func(f) {}
InputEvent read() override {
return m_func();
}
private:
std::function<InputEvent(void)> m_func;
};
2019-05-10 05:17:29 +00:00
class BufferedInputSource: public InputSource {
public:
BufferedInputSource() : InputSource() {}
BufferedInputSource(const char* name) : InputSource(name) {}
InputEvent read() override;
protected:
void setEvent(InputEvent &&evt);
2021-03-28 01:19:55 +00:00
void setEvent(InputEvent::Intent intent, Variant &&v);
2019-05-10 05:17:29 +00:00
private:
2021-03-28 21:50:31 +00:00
Ringbuf<InputEvent, 5> m_eventQueue;
2019-05-10 05:17:29 +00:00
};
2021-03-28 01:19:55 +00:00
class InputMapper: public BufferedInputSource {
public:
InputMapper(std::function<InputEvent(const InputEvent)> f) : BufferedInputSource(), m_func(f) {}
void handleEvent(const InputEvent& evt) override {
setEvent(m_func(evt));
}
private:
std::function<InputEvent(const InputEvent)> m_func;
};