/*
  Start after red select-button is pressed, then display a counter that counts up until 20 and then finishes.
  While running, it also checks the buttons pressed.
  So it executes 3 tasks in parallel:
  - blinking text
  - counter counting & display it
  - check buttons

  https://home.et.utwente.nl/slootenvanf/2020/06/08/countdown-timers-tasks-in-parallel/

  Author: F. van Slooten
*/
#include <U8g2lib.h>
#include <Bounce2.h>

byte button_pins[] = {4, 5, 6}; // button pins; 4/5 up/down, 6 = set/select

#define NUMBUTTONS sizeof(button_pins)

Bounce * buttons = new Bounce[NUMBUTTONS];

U8X8_SSD1306_128X64_NONAME_HW_I2C display(U8X8_PIN_NONE);

int count = 0; // start value of the counter (in seconds)

unsigned long previousMillis = 0, previousMillis2 = 0; // will store last time timer was updated

const unsigned long interval = 1000; // 1 second interval for countdown

char buf[10]; // text buffer; to be able to use draw2x2String to show the value

bool blink = true;

void setup() {
  Serial.begin(9600);

  // Make input & enable pull-up resistors on switch pins
  for (int i = 0; i < NUMBUTTONS; i++) {
    buttons[i].attach( button_pins[i] , INPUT_PULLUP  );       //setup the bounce instance for the current button
    buttons[i].interval(25);              // interval in ms
  }
  
  // initialize display
  display.begin();
  display.setPowerSave(0);
  display.setFont(u8x8_font_pxplusibmcgathin_f);

  // wait until button pressed to proceed:
  // (this while statement halts the program, until the button is pressed)
  while(digitalRead(button_pins[NUMBUTTONS-1])==HIGH) ; // note the empty statement: ';' does nothing, thus waits for first button to be pressed (becomes LOW)
  delay(1000); // wait 1 sec before starting
  display.drawString(0, 7, "running");
  Serial.println("Countdown running");
}

void loop() {
  unsigned long currentMillis = millis();

  // task 1: blink time on display every 300ms when setting it:
  if (currentMillis - previousMillis2 > 300 && count<20) { // 300ms passed? and running counter?
    previousMillis2 = currentMillis; // save the last time
    blink = !blink;
    if (blink) display.drawString(0, 7, "running");
    else display.clearLine(7);
  }

  // task 2: update countdown timer every second
  if (currentMillis - previousMillis > interval) { // interval passed?
    previousMillis = currentMillis; // save the last time
    if (count==20) {
      display.drawString(0, 7, "counter finished");
    }
    else if (count<20) {
      count++;
      sprintf(buf, "%02d", count);
      display.draw2x2String(2, 3, buf);
    }
  }

  // task 3: check for pressed buttons
  for (int i = 0; i < NUMBUTTONS; i++) {
    // Update the Bounce instance :
    buttons[i].update();
    if ( buttons[i].fell() ) { // a button was pressed
        sprintf(buf, "button %d press", i);
        display.drawString(0,0,buf);
        if ((i==2 && count==20)||(i==0 && count>20)) { // if button 2 was pressed and counter was finised, or device is off and first button pressed
          count=0; // restart counter/turn on device
        }
        else if (i==0 && count<=20) { // if first button was pressed turn off
          count=100; // set counter to high value (out of range)
          display.clear();
        }
    } // end if (button pressed)
  } // end for
}
$abcdeabcde151015202530354045505560fghijfghij