#include <Button_SL.hpp> // Description: https://github.com/DoImant/Button_SL
using namespace Btn;
//
// Global constants
//
constexpr uint8_t LEDGRP_PINS[] {2, 3, 4, 5};
constexpr uint8_t LEDGRP_NUM {sizeof(LEDGRP_PINS) / sizeof(LEDGRP_PINS[0])};
constexpr uint8_t LEDEXTRA_PIN {11};
constexpr uint32_t DELAY_MS {1000};
//////////////////////////////////////////////////////////////////////////////
/// Helperclass for timer operations
///
//////////////////////////////////////////////////////////////////////////////
class Timer {
public:
void start() { timeStamp = millis(); }
bool operator()(const uint32_t duration) const { return (millis() - timeStamp >= duration) ? true : false; }
private:
uint32_t timeStamp {0};
};
///
/// Global variables / objects
///
enum class State : uint8_t { idle, sequence, waitForReset };
ButtonSL startBtn {8};
ButtonSL resetBtn {9};
ButtonSL extraBtn {10};
Timer wait;
///
/// Function(s)
///
void fsm() {
static State state {State::idle};
static uint8_t ledIdx {0};
switch (state) {
case State::idle:
if (startBtn.tick() != ButtonState::notPressed) { state = State::sequence; }
break;
case State::sequence:
if (extraBtn.tick() == ButtonState::shortPressed && !digitalRead(LEDEXTRA_PIN)) {
digitalWrite(LEDEXTRA_PIN, HIGH);
}
if (wait(DELAY_MS)) {
digitalWrite(LEDGRP_PINS[ledIdx], HIGH);
if (++ledIdx < LEDGRP_NUM) {
wait.start();
} else {
state = State::waitForReset;
}
}
break;
case State::waitForReset:
if (resetBtn.tick() != ButtonState::notPressed) {
for (const auto &pin : LEDGRP_PINS) { digitalWrite(pin, LOW); }
digitalWrite(LEDEXTRA_PIN, LOW);
ledIdx = 0;
state = State::idle;
}
break;
default: break;
}
}
///
/// Main
///
void setup() {
// Init Buttons
startBtn.begin();
resetBtn.begin();
extraBtn.begin();
startBtn.setDebounceTime_ms(40);
resetBtn.setDebounceTime_ms(40);
extraBtn.setDebounceTime_ms(40);
for (const auto &pin : LEDGRP_PINS) { pinMode(pin, OUTPUT); }
pinMode(LEDEXTRA_PIN, OUTPUT);
}
void loop() { fsm(); }
start
reset
extra