/*
  State change detection (edge detection)
  (with debouncing, LED toggling, and active-LOW input using INPUT_PULLUP)
  https://wokwi.com/projects/391482018625678337
  modified from https://wokwi.com/projects/391475222059330561

  Often, you don't need to know the state of a digital input all the time, but
  you just need to know when the input changes from one state to another.
  For example, you want to know when a button goes from OFF to ON. This is called
  state change detection, or edge detection.

  This example shows how to:
  1) detect when a button or button changes from off to on and on to off.
  2) debounce an input with millis()
  3) toggle a LED based on its state

  The circuit:
  - pushbutton attached to pin 2 and GND
  - LED attached from pin 13 to ground through 220 ohm resistor (or use the
    built-in LED on most Arduino boards)

  created  27 Sep 2005
  modified 30 Aug 2011
  by Tom Igoe
  modified 04 Mar 2024 by DaveX for https://forum.arduino.cc/t/state-change-detection-edge-detection-for-pushbuttons/1231632/10
  This example code is in the public domain.
  
  Based on:
  https://docs.arduino.cc/built-in-examples/digital/StateChangeDetection/
*/

// this constant won't change:
const int buttonPin = 2;  // the pin that the pushbutton is attached to
const int ledPin = 13;    // the pin that the LED is attached to

// Variables will change:
int buttonState = 0;        // current state of the button
int lastButtonState = 0;    // previous state of the button
uint32_t lastChangeMillis = 0; // previous time of change for debouncing
uint32_t debounceInterval = 50;

void setup() {
  // initialize the button pin as a input with an internal pullup resistor:
  pinMode(buttonPin, INPUT_PULLUP);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(115200);
}

void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);
  uint32_t currentMillis = millis(); // save the current time

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState ) { // the state has changed
    if (currentMillis - lastChangeMillis >= debounceInterval) { // limit rate using time stamps
      lastChangeMillis = currentMillis; // record this change
      // Check for rising or falling edge
      if (buttonState == LOW) {
        // if the current state is LOW then the input is FALLING edge
        Serial.print("LOW ");
        toggleLed(ledPin); 
      } else {
        // if the current state is HIGH then the input is RISING edge
        Serial.print("HIGH ");
      }
      // save the current state as the last state, for next time through the loop
      lastButtonState = buttonState;
    }
  }
}

void toggleLed(byte pin){
  if (digitalRead(pin) == LOW) { // toggle the LED as needed
    digitalWrite(pin, HIGH);
    Serial.print("on ");
  } else {
    digitalWrite(pin, LOW);
    Serial.print("off ");
  }
}