/*
 * Board:   Arduino Uno
 * Target:  PE Series on LED Effects
 * Author:  Clive "Max" Maxfield (max@clivemaxfield.com) 
 * License: The MIT License (See full license at the bottom of this file)
 *
 * Notes:   Using a standard 4--pin tricolor LED
 */


#define SWITCH_ON                      LOW
#define SWITCH_OFF                    HIGH

#define LED_ON                        HIGH
#define LED_OFF                        LOW

#define COLOR_WHITE              0xFFFFFFU
#define COLOR_BLACK              0x000000U
#define COLOR_RED                0xFF0000U
#define COLOR_GREEN              0x00FF00U
#define COLOR_BLUE               0x0000FFU
#define COLOR_YELLOW             0x7F7F00U
#define COLOR_CYAN               0x007F7FU
#define COLOR_HOT_PINK           0x7F007FU
#define COLOR_DARK_ORANGE        0xBD1F00U

#define NUM_CYCLES                       1
#define CYCLE_DELAY                   2000


enum SwitchStates {
    SWITCH_NC_ACTIVE,
    SWITCH_NO_ACTIVE,
    SWITCH_CENTER
};

enum SwitchStates NewSwitchState;
enum SwitchStates OldSwitchState;


int PinSwitchNc = 3;
int PinSwitchNo = 4;

int PinLedRed   =  9;
int PinLedGreen = 10;
int PinLedBlue  = 11;


void setup ()
{
//    Serial.begin (9600);

    int switchNc;
    int switchNo;
  
    pinMode(PinSwitchNc, INPUT);
    pinMode(PinSwitchNo, INPUT);

    pinMode(PinLedRed,   OUTPUT);
    pinMode(PinLedGreen, OUTPUT);
    pinMode(PinLedBlue,  OUTPUT);

    digitalWrite(PinLedRed,   LED_OFF);
    digitalWrite(PinLedGreen, LED_OFF);
    digitalWrite(PinLedBlue,  LED_OFF);

    for (int iCycle = 0; iCycle < NUM_CYCLES; iCycle++)
    {
        LightLed(COLOR_RED);      delay(CYCLE_DELAY);
        LightLed(COLOR_GREEN);    delay(CYCLE_DELAY);
        LightLed(COLOR_BLUE);     delay(CYCLE_DELAY);
        LightLed(COLOR_YELLOW);   delay(CYCLE_DELAY);
        LightLed(COLOR_CYAN);     delay(CYCLE_DELAY);
        LightLed(COLOR_HOT_PINK); delay(CYCLE_DELAY);
        LightLed(COLOR_WHITE);    delay(CYCLE_DELAY);
        LightLed(COLOR_BLACK);    delay(CYCLE_DELAY);
    }
  
    switchNc = digitalRead(PinSwitchNc);
    switchNo = digitalRead(PinSwitchNo);

    // The following is overkill on the conditions to make it clear what's going on
    if      ( (switchNc == SWITCH_ON)  && (switchNo == SWITCH_OFF) ) OldSwitchState = SWITCH_NC_ACTIVE;
    else if ( (switchNc == SWITCH_OFF) && (switchNo == SWITCH_ON)  ) OldSwitchState = SWITCH_NO_ACTIVE;
    else if ( (switchNc == SWITCH_OFF) && (switchNo == SWITCH_OFF) ) OldSwitchState = SWITCH_CENTER;

    // The following is overkill on the conditions to make it clear what's going on
    if (OldSwitchState == SWITCH_NC_ACTIVE)
    {
        LightLed(COLOR_GREEN);
    }
    else if (OldSwitchState == SWITCH_NO_ACTIVE)
    {
        LightLed(COLOR_RED);
    }
    else if (OldSwitchState == SWITCH_CENTER)
    {
        LightLed(COLOR_BLACK); // Should be yellow, but use black for the video
        // LightLed(COLOR_YELLOW); 
    }
}

void loop ()
{
    int switchNc;
    int switchNo;

    switchNc = digitalRead(PinSwitchNc);
    switchNo = digitalRead(PinSwitchNo);

    // The following is overkill on the conditions to make it clear what's going on
    if      ( (switchNc == SWITCH_ON)  && (switchNo == SWITCH_OFF) ) NewSwitchState = SWITCH_NC_ACTIVE;
    else if ( (switchNc == SWITCH_OFF) && (switchNo == SWITCH_ON)  ) NewSwitchState = SWITCH_NO_ACTIVE;
    else if ( (switchNc == SWITCH_OFF) && (switchNo == SWITCH_OFF) ) NewSwitchState = SWITCH_CENTER;

    if (NewSwitchState != OldSwitchState)
    {
        // The following is overkill on the conditions to make it clear what's going on
        if (NewSwitchState == SWITCH_NC_ACTIVE)
        {
            LightLed(COLOR_GREEN);
        }
        else if (NewSwitchState == SWITCH_NO_ACTIVE)
        {
            LightLed(COLOR_RED);
        }
        else if (NewSwitchState == SWITCH_CENTER)
        {
            if (OldSwitchState == SWITCH_NC_ACTIVE)
            {
                LightLed(COLOR_YELLOW);
            }
            else if (OldSwitchState == SWITCH_NO_ACTIVE)
            {
                LightLed(COLOR_DARK_ORANGE);
            }
        }
        
        OldSwitchState = NewSwitchState;
    }
}


void LightLed (unsigned long thisColor)
{
    int tmpRed;
    int tmpGreen;
    int tmpBlue;

    tmpRed   = (int) (thisColor >> 16) & 0xFF;
    tmpGreen = (int) (thisColor >>  8) & 0xFF;
    tmpBlue  = (int)  thisColor & 0xFF;

    analogWrite(PinLedRed,   tmpRed);
    analogWrite(PinLedGreen, tmpGreen);
    analogWrite(PinLedBlue,  tmpBlue);
}



/*
 * Copyright (c) 2020 Clive "Max" Maxfield
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and any associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */