enum t_ledState : byte {LED_OFF, LED_ON};
const byte ledCount = 50;
t_ledState ledState[ledCount];
const unsigned long tickPeriod = 100; // ms
unsigned long lastTick = 0;
byte tickCount = 0;
const byte buttonPin = 2;
enum : byte {WAITING, PRESSED, RELEASED, FINISHED} state;
void display() {
for (auto & s : ledState) Serial.write(s == LED_ON ? '*' : '.');
Serial.println();
}
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
Serial.begin(115200); Serial.println();
Serial.println("fire at will!");
}
void loop() {
unsigned long now = millis();
switch (state) {
case WAITING:
if (digitalRead(buttonPin) == LOW) {
delay(15); // poor's man anti-bounce
for (auto & s : ledState) s = LED_OFF;
ledState[0] = LED_ON;
lastTick = now;
tickCount = 0;
state = PRESSED;
Serial.println("starting");
for (auto & s : ledState) Serial.write('-');
Serial.println();
}
break;
case PRESSED:
if (digitalRead(buttonPin) == HIGH) {
delay(15); // poor's man anti-bounce
state = RELEASED;
} else tickCount = 0;
[[gnu::fallthrough]];
case RELEASED:
if (now - lastTick >= tickPeriod) {
if (tickCount++ <= ledCount) {
display();
for (byte i = ledCount - 1; i > 0; --i) ledState[i] = ledState[i - 1];
ledState[0] = (state == PRESSED) ? LED_ON : LED_OFF;
lastTick = now;
} else {
Serial.println("--- done ---\n");
state = FINISHED;
}
}
break;
case FINISHED:
if (digitalRead(buttonPin) == HIGH) {
delay(15); // poor's man anti-bounce
state = WAITING;
Serial.println("fire at will again!");
break;
}
}
}