// Giant_Button_Demo
// CLClab306 02/18/2023
/*
* Button Pin Connections:
* Button LED D-in                 -> Arduino Pin 7
* Button LED +5V                  -> Arduino +5V
* Button Switch Common & LED (-)  -> Arduino GND
* Button Switch Normally Open     -> Arduino Pin 2
*/

#include <TimerOne.h>
#include <Adafruit_NeoPixel.h>

#define NUM_LEDS 1
#define DATA_PIN 7              // Pin 7 = D-in for RGB LED
#define SWTCH_PIN 2             // Pin 2 = Giant Button microswitch (NO lug)

// Define the neopixel array
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_LEDS, DATA_PIN, NEO_GRB + NEO_KHZ800);

volatile int newSWTCH = 0;
volatile int duration = 0;
int SWTCH = 1;
int lastSWTCH = 1;
int timeCTR = 0;
int blinkInterval = 25;       // built-in LED blink delay (10-msec units)
int i = 0;
int pushCounter = 0;

void setup()
  {
    pinMode(SWTCH_PIN, INPUT_PULLUP);   // Common lug on switch connected to GND (Pin is HIGH when switch is open)
    pinMode(13, OUTPUT);                // UNO built-in LED
    pixels.setBrightness(255);
    pixels.begin();                     // This initializes the NeoPixel library.
    Timer1.initialize(10000);
    Timer1.attachInterrupt(button);     // button routine runs every 10 msec (100 Hz)
    Serial.begin(9600);
  }

void loop() 
  {
  if(newSWTCH)                                // check for new button input
      {
        pushCounter++;
        Serial.print("Switch Closed for: ");
        Serial.print(duration * 10);          // convert duration counts to msec
        Serial.print(" msec; Total Count = ");
        Serial.println(pushCounter);
        for(int x = 0; x < 5; x++)            // Blink RGB LED 5x for button input
          {
            pixels.setPixelColor(0, pixels.Color(255,255,255));    // Blinks White
            pixels.show();
            delay(250);
            pixels.setPixelColor(0, pixels.Color(0,0,0));
            pixels.show();
            delay(250);
          }
        duration = 0;
        newSWTCH = 0;       
        // new button presses won't be counted until after this point
        // Also, the rainbow sweep will start up again
      }
  }

void button()
  {
    // Timer interrupt routine--runs every 10 msec
    SWTCH = digitalRead(SWTCH_PIN);             // read current switch state
    if(lastSWTCH == 0 && SWTCH == 0)            // is switch still on from last check?
      {
        duration++;                             // Yes: increment duration counter (10 msec units)
      }
    if(lastSWTCH == 0 && lastSWTCH != SWTCH)    // did button go from On to Off?
      {
        newSWTCH = 1;                           // Yes: set newSWTCH flag
      }
    lastSWTCH = SWTCH;
    
    // Check timing for built-in LED blink interval
    timeCTR++;                                      // increment counter for blink timer
    if(timeCTR == blinkInterval)
      {
        digitalWrite(13, !digitalRead(13));     // toggle LED
        timeCTR = 0;                            // reset time counter
      }

    if(newSWTCH == 1) return;                   // rainbow sweep is paused when button push detected 

    // rainbow color sweep for RGB LED between button presses
    i++;
    if(i >= 255)
      {
        i = 0;
      }
    pixels.setPixelColor(0, Wheel(i));
    pixels.show();
  }

// Subroutine to get colors for rainbow sweep
uint32_t Wheel(byte WheelPos) 
  {
    WheelPos = 255 - WheelPos;
    if(WheelPos < 85) 
      {
        return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3,0);
      }
    if(WheelPos < 170) 
      {
        WheelPos -= 85;
        return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3,0);
      }
    WheelPos -= 170;
    return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0,0);
  }