/*-----------------------------------------------------------------------------------------
 *  This software is in the public domain, furnished "as is", without technical
 *  support, and with no warranty, express or implied, as to its usefulness for
 *  any purpose.
 *
 *  LED.ino
 *
 * Functions to set RGB-LED. LED is used to show the differnt states of the
 * DualDriveMixer with a colorscheme. If a wateralarm is enabled the RGB-LED
 * will blink white and colorscheme in 1 second intervals.
 * supported States:
 * 0 = Failsafe (Red)
 * 1 = ManuelMode driving (Blue)
 * 2 = ManuelMode standstill (Blue-Blinking)
 * 3 = MixedMod driving (Green)
 * 4 = MixedMod standstill (Green-Blinking)
 * 5 = ModeChangeTrigger (Yellow)
 * 6 = LED off
 *
 *
 *  Author: Volker Frauenstein
 *  Date: 13/01/2021 Version: 2.2 LED blinking functionality added
 *
 *  Date: 08/01/2021 Version: 2.1 RGB_LED function for wateralert added
 *  Date: 05/01/2021 Version: 2.0 definitions adapted for ESP32 migration w
 *                                ithout WS2811 interface du to interupt conficts
 *  Date: 30/12/2020 Version: 1.0 implementation of WS2811 RGB-LED control
 */

// initialize the digital pins as output for RGB-LED
const uint8_t LEDpinR = 12;          // definition of output pin red (resistor >= 68Ohm is needed with ESP32)
const uint8_t LEDpinG = 14;          // definition of output pin green
const uint8_t LEDpinB = 27;          // definition of output pin blue

// generig definitions
static unsigned long blinkTimer = 0; // timer for blink interval
const uint16_t blinkmilles = 750;    // binkinterval in ms
bool sblink = true;                  // indicator if state blinking is aktiv
bool alert = false;                  // indicator for wateralarm aktiv
int oldstate = 0;                    // old LED state for blinking
//#define DEBUG_LED 1
//#define DEBUG_BLINK 1

void setup_LEDstate() {              // set up function to enable RGB-LED
  pinMode(LEDpinR, OUTPUT);
  pinMode(LEDpinG, OUTPUT);
  pinMode(LEDpinB, OUTPUT);
  show_black();                      // switch RGB-LED off for startup
}

void Blinkstate(int state) {         // function to switch blinking state

  if (state == oldstate) {           // no state change no blink reset
      if (millis() - blinkTimer > blinkmilles) {
        blinkTimer = millis();       // time over, reset timer
        sblink = !sblink;            // set semaphore to other state for LED
        #ifdef DEBUG_BLINK
         Serial.print(" Blink reset,");
        #endif
      }
    }
  else {                             // new LED state,
        blinkTimer = millis();       // set timer and
        oldstate = state;            // set new state
        sblink = true;               // set semaphore for LED state
        #ifdef DEBUG_BLINK
          Serial.print(" Blink start,");
        #endif
      }
}

void AlarmLED(bool alarm) {          // function to trigger alarmblinking

  if (!alert){
    if (alarm) {                     // alarm is new triggered
      blinkTimer = millis();         // set timer
      alert = alarm;                 // set LED alert state
      show_white();                  // white for alarm state
    }                                // no alarm, no else
  }
  else {                             // alarm was running
    if (!alarm) {
      alert = alarm;                 // reset LED alert state
      show_black();                  // white for alarm state
    }                                // alarm is still running, no else
  }
}

void set_LEDstate(int state) {       // function to set or change color of RGB LED

   Blinkstate(state);                // check for blinking condition

   if (state == 0) {                 // failsafe state
    if (alert && !sblink) {
      show_white();                  // blink white for alarm state
    }
    else show_red();                 // red for Failsafe state
   }
   if (state == 1) {                 // manual mode driving state
    if (alert && !sblink) {
      show_white();                  // blink white for alarm state
    }
    else show_blue();                // blue for manual mode
   }
   if (state == 2) {                 // manual mode standstill state
    if (alert && !sblink) {
      show_white();                  // blink white for alarm state
    }
    else if (!sblink) {
      show_black();                  // LED off for blue blinking
    }
    else show_blue();                // blue for manual mode
   }
   if (state == 3) {                 // mixed mode driving state
        if (alert && !sblink) {
      show_white();                  // blink white for alarm state
    }
    else show_green();               // green for MixedMode
   }
   if (state == 4) {                 // mixed mode standstill state
    if (alert && !sblink) {
      show_white();                  // blink white for alarm state
    }
    else if (!sblink) {
      show_black();                  // LED off for green blinking
    }
    else show_green();               // green for MixedMode
   }
   if (state == 5) {
        if (alert && !sblink) {
      show_white();                  // blink white for alarm state
    }
    else show_yellow();              // yellow for ChangeMode triggerd
   }
   if (state > 6) {
    show_black();                    // LED off
   }
   #ifdef DEBUG_LED
       Serial.print("  LED_State : ");Serial.print(state);
       Serial.print(", sblink : ");Serial.print(sblink);
       Serial.print(", alert : ");Serial.println(alert);
   #endif
}                                    // function set_LEDstate closed

// function to switch LED colors on
void show_red() {
   digitalWrite(LEDpinR, LOW);
   digitalWrite(LEDpinG, HIGH);
   digitalWrite(LEDpinB, HIGH);
}

void show_green() {
   digitalWrite(LEDpinR, HIGH);
   digitalWrite(LEDpinG, LOW);
   digitalWrite(LEDpinB, HIGH);
}

void show_blue() {
   digitalWrite(LEDpinR, HIGH);
   digitalWrite(LEDpinG, HIGH);
   digitalWrite(LEDpinB, LOW);
}

void show_yellow() {
   digitalWrite(LEDpinR, LOW);
   digitalWrite(LEDpinG, LOW);
   digitalWrite(LEDpinB, HIGH);
}

void show_turquoise() {
   digitalWrite(LEDpinR, HIGH);
   digitalWrite(LEDpinG, LOW);
   digitalWrite(LEDpinB, LOW);
}

void show_violet() {
   digitalWrite(LEDpinR, LOW);
   digitalWrite(LEDpinG, HIGH);
   digitalWrite(LEDpinB, LOW);
}

void show_black() {
   digitalWrite(LEDpinR, HIGH);
   digitalWrite(LEDpinG, HIGH);
   digitalWrite(LEDpinB, HIGH);
}

void show_white() {
   digitalWrite(LEDpinR, LOW);
   digitalWrite(LEDpinG, LOW);
   digitalWrite(LEDpinB, LOW);
}