/*
  Solution For:
  Topics:   1 InputCondition 1 led fade
  Category: Project Guidance
  Link:     https://forum.arduino.cc/t/1-button-1-led-fade/1113139/26

  Sketch:   AuCP_FadeInOut.ino
  Created:  10-Apr-23
  MicroBeaut (μB)
*/

#include "Debounce.h"

#define pbPin 5  // Pin connected to the pushbutton
#define ledPin 3 // Pin connected to the LED

#define millisec(t) (t * 1000UL) // Macro to convert seconds to milliseconds

bool input;         // Current input state
bool prevInput;     // Previous input state
bool fade;          // Flag for fading status
uint8_t brightness; // Current LED brightness level

Debounce inputDebounce; // Debounce object for input

unsigned long startTime;    // Start time for tracking intervals
unsigned long repeatRate;   // Button press repeat rate
unsigned long debounceTime; // Time for input debouncing

void InputCondition();      // Function for handling input conditions
void Fade();                // Function for controlling LED fading
void PrintBrightness(uint8_t brightness); // Function to print the current brightness level

void setup() {
  Serial.begin(115200); // Initialize serial communication
  pinMode(pbPin, INPUT_PULLUP);     // Set pushbutton pin mode
  pinMode(LED_BUILTIN, OUTPUT);     // Set LED pin mode

  repeatRate = millisec(10);          // Set button repeat rate to 10 milliseconds
  inputDebounce.setDebounceTime(20);  // Set debounce time to 20 milliseconds

  brightness = 0;                   // Set initial brightness
  fade = false;                     // Set initial fade (TRUE = Fade-In, FALSE = Fade-Out)
  digitalWrite(LED_BUILTIN, !fade); // Set next fade status (ON = Fade-In, OFF = Fade-Out)
  PrintBrightness(brightness);      // Print initial brightness
}


void loop() {
  InputCondition(); // Check button input condition
  Fade();           // Perform LED fade-in/fade-out
}

void InputCondition() {
  bool pbValue = !digitalRead(pbPin);       // Read input from pushbutton
  input = inputDebounce.debounce(pbValue);  // Debounce input

  if (input & !prevInput) {                 // Rising edge detector for button press
    startTime = micros();                   // Reload start time for time tracking
    fade = !fade;                           // Toggle fade (TRUE = Fade-In, FALSE = Fade-Out)
  }

  if (!input & prevInput) {                 // Falling edge detector for button release
    digitalWrite(LED_BUILTIN, !fade);       // Set next fade status (ON = Fade-In, OFF = Fade-Out)
  }

  prevInput = input; // Update previous input state
}

void Fade() {
  if (!input) return;               // Exit if no input
  if (micros() - startTime < repeatRate) return;  // Check for button press repeat rate
  startTime = micros();             // Reload start time for time tracking
  if (fade) {                       // Fade-In
    if (brightness > 254) return;   // Check if brightness equals 255, then exit
    brightness++;                   // Increase brightness for fade-in
    PrintBrightness(brightness);    // Print current brightness
  } else {                          // Fade-Out
    if (brightness < 1) return;     // Check if brightness equals 0, then exit
    brightness--;                   // Decrease brightness for fade-out
    PrintBrightness(brightness);    // Print current brightness
  }
  analogWrite(ledPin, brightness); // Update LED brightness
}

void PrintBrightness(uint8_t brightness) {
  Serial.print("Brightness:= ");  // Print label for brightness
  Serial.println(brightness);     // Print the current brightness value
}