/*
  Interlocking Monoflop

  https://forum.arduino.cc/t/delay-turning-led-off-after-button-press/1105635/
  2023-03-23 by noiasca
  to be deleted: 2023-06

  Variant post #21: don't switch off the current pin in case of a long button press
*/

void release(uint8_t); // only a prototype - just the signature of a function implemented later in the code

// a class for one LED one button
class Monoflop {
    const uint8_t buttonPin;  // the input GPIO, active LOW
    const uint8_t relayPin;   // the output GPIO, active 
    uint32_t previousMillis = 0; // time management
    bool state = false;       // active or inactive
  public:
    Monoflop(uint8_t buttonPin, uint8_t relayPin) : buttonPin{buttonPin}, relayPin{relayPin}
    {}

    void begin() {                         // to be called in setup()
      pinMode(buttonPin, INPUT_PULLUP);
      pinMode(relayPin, OUTPUT);
    }

    uint8_t getRelayPin() {
      return relayPin;
    }

    void off() {                           // handles switching off 
      digitalWrite(relayPin, LOW);
      state = false;
    }

    void update(uint32_t currentMillis = millis()) {   // to be called in loop()
      uint8_t buttonState = digitalRead(buttonPin);
      if (buttonState == LOW) {
        release(relayPin);
        previousMillis = currentMillis;
        digitalWrite(relayPin, HIGH);
        state = true;
      }
      if (state && currentMillis-previousMillis > 1000) {
        off();
      }
    }
};

//create 3 instances (each with one button and one relay/LED)
Monoflop monoflop[] {
  {A0, 12},  // buttonPin, relayPin
  {A1, 11},
  {A2, 10},
};

void release(uint8_t currentPin){    // release all outputs
  for (auto &i : monoflop) if (i.getRelayPin() != currentPin) i.off();
}

void setup() {
  for (auto &i : monoflop) i.begin();
}

void loop() {
  for (auto &i : monoflop) i.update();
}