#define UNUSED(arg) (void)arg
template<typename T, size_t CNT>
constexpr size_t COUNT_OF(T(&)[CNT]) { return CNT; }
/*
* Объект отвечающий за переключение действий.
* Переключение инициируется после истечении периода
*/
class sequencer {
public:
/* short typename */
typedef void(*func_t)(uint32_t mil, uint8_t period, uint8_t pin);
/* Описатель действия */
struct action_t {
uint8_t period;
func_t Action;
};
public:
void operator()(void) {
auto m = millis();
auto stampDelta = m - timeStamp;
actionList[iterator].Action(stampDelta, actionList[iterator].period, PIN);
if ((stampDelta) >= (actionList[iterator].period * 1000UL)) {
/* переключение на следующее действие */
iterator = (iterator + 1) % CNT_MAX;
timeStamp = m;
}
}
template<uint8_t MAX_CNT>
sequencer(const action_t (&actionList)[MAX_CNT], uint8_t pin)
: CNT_MAX(MAX_CNT), PIN(pin), actionList(actionList), iterator(0), timeStamp(0) {
pinMode(PIN, OUTPUT);
}
private:
const uint8_t CNT_MAX;
const uint8_t PIN;
const action_t* const actionList;
uint8_t iterator;
uint32_t timeStamp;
};
/*
* Функции определяющие поведение описываемых ниже действий
*/
void TurneOff (uint32_t mil, uint8_t period, uint8_t pin) { UNUSED(mil), UNUSED(period); digitalWrite(pin, LOW); }
void TurneOn (uint32_t mil, uint8_t period, uint8_t pin) { UNUSED(mil), UNUSED(period); digitalWrite(pin, HIGH); }
void SmoothRise (uint32_t mil, uint8_t period, uint8_t pin) { analogWrite(pin, map(mil, 0 , period * 1000, 0, 255)); }
void Fade (uint32_t mil, uint8_t period, uint8_t pin) { analogWrite(pin, map(mil, 0 , period * 1000, 255, 0)); }
/*
* Определение списков действий.
* Списки могут быть абсолютно разные, даже с разным количеством действий,
* но не менее 1-го
*/
const sequencer::action_t actionListA[] = {
/* period, Action fuction */
2, TurneOff,
4, SmoothRise,
1, TurneOn,
2, Fade
};
const sequencer::action_t actionListB[] = {
1, TurneOff,
1, SmoothRise,
1, TurneOn,
1, Fade
};
const sequencer::action_t actionListC[] = {
1, TurneOff,
1, TurneOn
};
/* Экземпляры мигалок, на базе секвенсора */
sequencer leds[] = {
sequencer(actionListA, 9),
sequencer(actionListB, 10),
sequencer(actionListC, 13),
};
void setup() { }
void loop() {
for (uint8_t i = 0; i < COUNT_OF(leds); ++i) {
leds[i]();
}
}