Last active
August 5, 2020 01:08
-
-
Save hare1039/2547f103d588c8aae1c08a42e87c5da4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <ArduinoSTL.h> | |
#include <vector> | |
#include <functional> | |
using arduino_time_t = unsigned long; | |
using function_ptr = void (*)(); | |
class dispatcher | |
{ | |
static inline arduino_time_t now() { return millis(); } | |
public: | |
struct animation | |
{ | |
arduino_time_t const duration; | |
function_ptr const callable; | |
arduino_time_t actual_time; | |
}; | |
private: | |
std::vector<animation> animations_; | |
arduino_time_t start_ {now()}; | |
public: | |
dispatcher(std::initializer_list<animation> animations): | |
animations_ {animations} | |
{ | |
restart(); | |
} | |
dispatcher& restart() | |
{ | |
start_ = now(); | |
arduino_time_t prev = 0; | |
for (animation& ani : animations_) | |
prev = ani.actual_time = prev + ani.duration; | |
return *this; | |
} | |
dispatcher& stop() | |
{ | |
std::vector<animation>().swap(animations_); | |
return *this; | |
} | |
dispatcher& skip() | |
{ | |
for (animation& ani : animations_) | |
{ | |
if (now() < (ani.actual_time + start_)) | |
{ | |
start_ -= (ani.actual_time + start_ - now()); | |
break; | |
} | |
} | |
return *this; | |
} | |
void operator() () { run(); } | |
void run () | |
{ | |
for (animation& ani : animations_) | |
{ | |
if (now() < (ani.actual_time + start_)) | |
{ | |
ani.callable(); | |
break; | |
} | |
} | |
} | |
}; | |
template<typename T> | |
class once | |
{ | |
T data_; | |
bool locked = false; | |
public: | |
once(T t): data_{t} {} | |
operator T* () | |
{ | |
if (locked) | |
return nullptr; | |
locked = true; | |
return &data_; | |
} | |
void unlock() { locked = false; } | |
}; | |
class led_controller | |
{ | |
int pin_ = 0; | |
dispatcher* control_ = nullptr; | |
public: | |
once<int> current_; | |
int amount = 1; | |
public: | |
led_controller(int pin, int start): pin_{pin}, current_{start} {} | |
void set(dispatcher * v) { control_ = v; control_->restart(); } | |
void run() { if (control_) { control_->run(); } } | |
void apply() | |
{ | |
current_.unlock(); | |
int* current = current_; | |
analogWrite(pin_, *current); | |
} | |
void off() | |
{ | |
digitalWrite(pin_, LOW); | |
} | |
}; | |
led_controller nine{9, 2}; | |
dispatcher nine_dispatcher | |
{ | |
dispatcher::animation{100, []() { nine.current_.unlock(); nine_dispatcher.skip(); }}, | |
dispatcher::animation{20, []() { | |
int * current = nine.current_; | |
if (current) | |
{ | |
if (*current >= 15 || *current <= 1) | |
nine.amount = -nine.amount; | |
(*current) += nine.amount; | |
} | |
}}, | |
dispatcher::animation{30, []() { nine.apply(); nine_dispatcher.restart(); }} | |
}; | |
dispatcher nine_fast_flash | |
{ | |
dispatcher::animation{100, []() { nine.apply(); }}, | |
dispatcher::animation{100, []() { nine.off(); }}, | |
dispatcher::animation{30, []() { nine_fast_flash.restart(); }} | |
}; | |
led_controller ten{10, 11}; | |
dispatcher ten_dispatcher | |
{ | |
dispatcher::animation{100, []() { ten.current_.unlock(); ten_dispatcher.skip(); }}, | |
dispatcher::animation{45, []() { | |
int * current = ten.current_; | |
if (current) | |
{ | |
if (*current >= 20 || *current <= 1) | |
ten.amount = -ten.amount; | |
(*current) += ten.amount; | |
} | |
}}, | |
dispatcher::animation{30, []() { ten.apply(); ten_dispatcher.restart(); }} | |
}; | |
dispatcher ten_fast_flash | |
{ | |
dispatcher::animation{30, []() { ten.apply(); }}, | |
dispatcher::animation{30, []() { ten.off(); }}, | |
dispatcher::animation{30, []() { ten_fast_flash.restart(); }} | |
}; | |
void setup() | |
{ | |
Serial.begin(9600); | |
pinMode(9, OUTPUT); | |
pinMode(10, OUTPUT); | |
delay(100); | |
nine.set(&nine_dispatcher); | |
ten.set(&ten_dispatcher); | |
} | |
bool have_lights = false; | |
void loop() | |
{ | |
int v = analogRead(A1); | |
bool new_status = v < 500; | |
if (have_lights != new_status) | |
{ | |
Serial.print (have_lights); | |
if (have_lights) | |
{ | |
nine.set(&nine_dispatcher); | |
ten.set(&ten_dispatcher); | |
} | |
else | |
{ | |
nine.set(&nine_fast_flash); | |
ten.set(&ten_fast_flash); | |
} | |
} | |
have_lights = new_status; | |
nine.run(); | |
ten.run(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment