// Schnupperlehre: 2024-02-14  
// HW: MCU (ESP32-C3-Super Mini), Rotary Encoder & 24-er LED-Ring
// Mit dem Rotary Encoder können verschiedene Anzeigemodi gewählt werden:
// - Drehbewegung neuer Modus wählen
// - Mit Button gewählter Modus anzeigen

// Bibliotheken einbinden
#include <Adafruit_NeoPixel.h>    // <x.h> in Standard-Bibliotheks-Verzeichnis
#include "color.h"                // "x.h" eine eigene Bibliotheks-Datei im gleichen Projekt-Verzeichnis

// Zeiten definieren => Wert * 10ms
#define TIME_INTERVAL_SLOW  100
#define TIME_INTERVAL_NORM  50 
#define TIME_INTERVAL_FAST  25 

// Rotary Encoder definieren
#define BUTTON              1     // Zeitdauer in ms

#define STATE_MAX           12    // Anzahl Anzeigeeffekte

// Variabeln deklarieren und initialisieren
// boolean (true or false), byte (0 ... 255), unsigned int (0 ... 65535)
boolean button_bup = false;
boolean first = true;
byte i;
byte mode = 0;
byte step = 0;
boolean direction = false;
unsigned int time_counter = 0;
unsigned int time_interval = 0;
boolean interval = false;


// ------------------------------------------------------------------------------------
// SETUP
// ------------------------------------------------------------------------------------
void setup() {
  led_ring.begin(); // LED-Ring inititalisieren
  Serial.begin(115200);
  Serial.println("---------------------------------------------------------");

  pinMode(BUTTON, INPUT_PULLUP);

  // Power-On-Test => für 2s leuchten alle LEDs weiss
  setAllLedsToColor(0xFF, 0xFF, 0xFF);
  delay(2000);
  led_ring.clear(); // Set all pixel colors to ’off’
}


// ------------------------------------------------------------------------------------
// LOOP
// ------------------------------------------------------------------------------------
void loop() {

  // Taster am Rotary Endoder prüfen ob er gedrückt wurde, wenn dann state 
  // eins im Kreis herum schieben.
  if ((digitalRead(BUTTON) == LOW) && (button_bup == false)) {
    button_bup = true;
    first = true;
    if (mode < (STATE_MAX - 1)) {
      mode++;
    } else {
      mode = 0;
    }
    Serial.print("State: "); Serial.println(mode);
  }
  if ((digitalRead(BUTTON) == HIGH) && (button_bup == true)) {
    button_bup = false;
  }

  // Den mit "mode" gewählten Anzeigemodus ausführen
  switch (mode) {

    // Modus "Alle LEDs rot"
    case 0:   if (first == true) {
                first = false;
                setAllLedsToColor(0xFF, 0x00, 0x00);
              }
              break;

    // Modus "Alle LEDs grün"
    case 1:   if (first == true) {
                first = false;
                setAllLedsToColor(0x00, 0xFF, 0x00);
              }
              break;

    // Modus "Alle LEDs blau"
    case 2:   if (first == true) {
                first = false;
                setAllLedsToColor(0x00, 0x00, 0xFF);
              }
              break;
    
    // Modus "Alle LEDs weiss"
    case 3:   if (first == true) {
                first = false;
                setAllLedsToColor(0xFF, 0xFF, 0xFF);
              }
              break;

    // Modus "Alle LEDs in 24 Stufen durch den Regenbogen"
    case 4:   if (first == true) {
                first = false;
                time_counter = 0;
                time_interval = TIME_INTERVAL_SLOW;
                interval = true;
                r = 240;
                g = 0;
                b = 0;
                step = 0;
              }
              
              if (interval == true) {
                setAllLedsToColor(r, g, b);
                Serial.print("Step: "); Serial.print(step); Serial.print(" R: "); Serial.print(r); Serial.print(", G: "); Serial.print(g); Serial.print(", B: "); Serial.println(b);
                interval = false;
                if (step < 8) {
                  r -= 30;
                  g += 30;
                } else if (step < 16 ) {
                  g -= 30;
                  b += 30;
                } else {
                  b -= 30;
                  r += 30;
                }

                if (step < 23) {
                  step++;
                } else {
                  step = 0;
                }                
              }              
              break;
        
    // Modus "Alle LEDs der Reihen nach im Uhrzeigersinn und den Farben entsprechend einschalten"
    case 5:   if (first == true) {
                first = false;
                time_counter = 0;
                time_interval = TIME_INTERVAL_NORM;
                interval = true;
                step = 0;
              }
              if (interval == true) {
                interval = false;
                setBarGraphOneColor(step, 255, 0, 255);

                if (step < 15) {
                  step++;
                } else {
                  step = 0;
                }
              }
              break;
        
    // Modus "Alle LEDs der Reihen nach im Gegen-Uhrzeigersinn und in den 2 Farben entsprechend einschalten"
    case 6:   if (first == true) {
                first = false;
                time_counter = 0;
                time_interval = TIME_INTERVAL_NORM;
                interval = true;
                step = 15;
              }
              if (interval == true) {
                interval = false;
                setBarGraphTwoColor(step, 0, 0, 255, 255, 255, 0);

                if (step > 0) {
                  step--;
                } else {
                  step = 15;
                }
              }
              break;

    // Modus "Alle LEDs der Reihen nach im Gegen-Uhrzeigersinn und in den 2 Farben entsprechend einschalten"
    case 7:   if (first == true) {
                first = false;
                time_counter = 0;
                time_interval = TIME_INTERVAL_NORM;
                interval = true;
                step = 15;
              }
              if (interval == true) {
                interval = false;
                setBarGraphMyColorArray(step);

                if (step > 0) {
                  step--;
                } else {
                  step = 15;
                }
              }
              break;

    // Modus "Einen Punkt im Uhrzeigersinn wandern lassen und dann im Gegen-Uhrzeigersinn zurück"
    case 8:   if (first == true) {
                first = false;
                time_counter = 0;
                time_interval = TIME_INTERVAL_FAST;
                interval = true;
                step = 0;
                direction = true;
              }
              if (interval == true) {
                interval = false;
                setDotOneColor(step, 0, 255, 255);

                if (direction == true) {
                  if (step < (NUM_PIXELS - 1)) {
                    step++;
                  } else {
                    direction = false;
                    step = NUM_PIXELS - 2;
                  }
                } else {
                  if (step > 0) {
                    step--;
                  } else {
                    direction = true;
                    step = 1;
                  }
                }
              }
              break;

    // Modus "Alle LEDs der Reihen nach im Uhrzeigersinn und den Farben im Array entsprechend einschalten"
    case 9:   if (first == true) {
                first = false;
                time_counter = 0;
                time_interval = TIME_INTERVAL_FAST;
                interval = true;
                step = 0;
              }
              if (interval == true) {
                interval = false;
                for(i = 0; i < NUM_PIXELS; i++) { 
                  if (i <= step) {
                    led_ring.setPixelColor(i, led_ring.Color(rgb_array[i][0], rgb_array[i][1], rgb_array[i][2]));
                  } else {
                    led_ring.setPixelColor(i, led_ring.Color(0x00, 0x00, 0x00));
                  }
                }
                led_ring.show();   
                if (step < 15) {
                  step++;
                } else {
                  step = 0;
                }
              }
              break;

    // Modus "Alle LEDs leuchten in den regenbogenfarben"
    case 10:  if (first == true) {
                first = false;
                setAllLedsToRainbow();
              }
              break;

    // Modus "Alle LEDs der Reihen nach im Uhrzeigersinn in den Regenbogen-Farben entsprechend einschalten"
    case 11:  if (first == true) {
                first = false;
                time_counter = 0;
                time_interval = TIME_INTERVAL_NORM;
                interval = true;
                step = 0;
              }
              if (interval == true) {
                interval = false;
                setDotRainbow(step);

                if (step < 15) {
                  step++;
                } else {
                  step = 0;
                }
              }
              break;


    case 23:   
    default:  break;
  }

  // Blinkzeit managen
  if (time_counter >= time_interval) {
    time_counter = 0;
    interval = true;
  } else {
    time_counter++;
  }
  delay(10); // Warte 10ms
}