#include <Arduino.h>
// Timing.cpp
/*
void setup() {
  DDRD |= (1 << DDD3) | (1 << DDD4) | (1 << DDD5);  // Set PD3, PD4, PD5 as outputs
}

void loop() {
  PORTD ^= (1 << PORTD3);  // Toggle PD3
  delay(250);  // 4 Hz
  PORTD ^= (1 << PORTD4);  // Toggle PD4
  delay(125);  // 8 Hz
  PORTD ^= (1 << PORTD5);  // Toggle PD5
  delay(62);  // 16 Hz
}
*/

/*

// SwitchToggle.cpp

#include <Arduino.h>

const int switchPin = A1;
const int ledPin = 6;

int switchState = HIGH;
int lastSwitchState = HIGH;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(switchPin, INPUT_PULLUP);
}

void loop() {
  int reading = digitalRead(switchPin);
  if (reading != lastSwitchState) {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != switchState) {
      switchState = reading;
      if (switchState == LOW) {
        digitalWrite(ledPin, !digitalRead(ledPin));
      }
    }
  }

  lastSwitchState = reading;
}
*/

/*
// NonBlockingDelay.cpp

#include <Arduino.h>

const int ledPin = 7;
const int switchPin = A2;

unsigned long previousMillis = 0;
int interval = 500;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(switchPin, INPUT_PULLUP);
}

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

  if (digitalRead(switchPin) == LOW) {
    interval = 2000;
  } else {
    interval = 500;
  }

  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    digitalWrite(ledPin, !digitalRead(ledPin));
  }
}
*/

// InterruptToggle.cpp
/*
#include <Arduino.h>

const int ledPin = 2;
const int switchPin = A0;

volatile bool toggleState = false;

void toggleInterrupt();  // Funktion vor ihrer Verwendung deklarieren

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(switchPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(switchPin), toggleInterrupt, FALLING);
}

void loop() {
  // Kein spezifischer Code im Loop, da der Interrupt das Umschalten übernimmt
}

void toggleInterrupt() {
  toggleState = !toggleState;
  digitalWrite(ledPin, toggleState);
}
*/
// CombinedProgram.cpp

#include <Arduino.h>

const int ledPinTiming1 = 3;
const int ledPinTiming2 = 4;
const int ledPinTiming3 = 5;

const int switchPinToggle = A1;
const int ledPinToggle = 6;

const int ledPinNonBlockingDelay = 7;
const int switchPinDelay = A2;

const int ledPinInterrupt = 2;
const int switchPinInterrupt = A0;

volatile bool toggleState = false;
unsigned long previousMillis = 0;
int interval = 500;

void toggleInterrupt();

void setup() {
  pinMode(ledPinTiming1, OUTPUT);
  pinMode(ledPinTiming2, OUTPUT);
  pinMode(ledPinTiming3, OUTPUT);

  pinMode(ledPinToggle, OUTPUT);
  pinMode(switchPinToggle, INPUT_PULLUP);

  pinMode(ledPinNonBlockingDelay, OUTPUT);
  pinMode(switchPinDelay, INPUT_PULLUP);

  pinMode(ledPinInterrupt, OUTPUT);
  pinMode(switchPinInterrupt, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(switchPinInterrupt), toggleInterrupt, FALLING);
}

void loop() {
  // Teilaufgabe 201 - Timing
  digitalWrite(ledPinTiming1, !digitalRead(ledPinTiming1));
  delay(250);
  digitalWrite(ledPinTiming2, !digitalRead(ledPinTiming2));
  delay(125);
  digitalWrite(ledPinTiming3, !digitalRead(ledPinTiming3));
  delay(62);

  // Teilaufgabe 202 - Flankenerkennung und Entprellen
  int switchStateToggle = digitalRead(switchPinToggle);
  static int lastSwitchStateToggle = HIGH;
  static unsigned long lastDebounceTimeToggle = 0;
  static unsigned long debounceDelayToggle = 50;

  if (switchStateToggle != lastSwitchStateToggle) {
    lastDebounceTimeToggle = millis();
  }

  if ((millis() - lastDebounceTimeToggle) > debounceDelayToggle) {
    if (switchStateToggle != digitalRead(ledPinToggle)) {
      digitalWrite(ledPinToggle, switchStateToggle == LOW);
    }
  }

  lastSwitchStateToggle = switchStateToggle;

  // Teilaufgabe 203 - Non-Blocking Delay
  unsigned long currentMillisDelay = millis();

  if (digitalRead(switchPinDelay) == LOW) {
    interval = 2000;
  } else {
    interval = 500;
  }

  if (currentMillisDelay - previousMillis >= interval) {
    previousMillis = currentMillisDelay;
    digitalWrite(ledPinNonBlockingDelay, !digitalRead(ledPinNonBlockingDelay));
  }
}

void toggleInterrupt() {
  toggleState = !toggleState;
  digitalWrite(ledPinInterrupt, toggleState);
}