#include <neoPixel.h>
#include <mechButton.h>
#include <blinker.h>
#include <colorObj.h>



#define COUTDOWN_MS   5000.0
#define IDLE_COLOR    &black
#define START_COLOR   &green
#define MID_COLOR     &yellow
#define END_COLOR     &red
#define NUM_LEDS      21
#define STEP_TIME     COUTDOWN_MS/NUM_LEDS
#define PIXEL_PIN     6
#define RESET_PIN     2
#define START_PIN     3
#define START_LED_PIN 4
#define END_LED_PIN   5


enum states { done, resetting, ready, timing };

states          ourState;
neoPixel        ourPixels(NUM_LEDS,PIXEL_PIN);
timeObj         resetTimer(50);
int             resetIndex;
timeObj         countdownTimer(STEP_TIME);
int             countIndex;
mechButton      resetBtn(RESET_PIN);
mechButton      startBtn(START_PIN);
blinker         startLED(START_LED_PIN);
colorMultiMap   ourColorMap;

void setup() {
  
  ourPixels.begin();
  pinMode(END_LED_PIN,OUTPUT);
  resetBtn.setCallback(resetClk);
  startBtn.setCallback(startClk);
  ourColorMap.addColor(0,END_COLOR);
  ourColorMap.addColor(COUTDOWN_MS/2,MID_COLOR);
  ourColorMap.addColor(COUTDOWN_MS,START_COLOR);
  reset();
}


void reset(void) {

  digitalWrite(END_LED_PIN,LOW);
  resetIndex = 0;
  ourPixels.setAll(IDLE_COLOR);
  ourPixels.show();
  ourPixels.setPixelColor(resetIndex++,START_COLOR);
  resetTimer.start();
  ourPixels.show();
  ourState = resetting;
}


void resetClk(void) {

  if (!resetBtn.getState()) {
    reset();
  }
}


void startClk(void) {

  if (!startBtn.getState()) {
    countdownTimer.start();
    ourPixels.setAll(START_COLOR);
    ourPixels.show();
    startLED.setOnOff(false);
    countIndex = NUM_LEDS;
    ourState = timing;
  }
}


void loop() {
  
  colorObj  currentColor;

  idle();
  switch(ourState) {
    case done    : break;
    case resetting  :
      if (resetTimer.ding()) {
        if (resetIndex<NUM_LEDS) {
          ourPixels.setPixelColor(resetIndex++,START_COLOR);
          ourPixels.show();
          resetTimer.start();
        } else {
          resetTimer.reset();
          startLED.setOnOff(true);
          ourState = ready;
        }
      }
    break;
    case ready    : break;
    case timing   :
      if (countdownTimer.ding()) {
        countIndex--;
        currentColor = ourColorMap.map(countIndex*STEP_TIME);
        if (countIndex) {
          ourPixels.setAll(IDLE_COLOR);
          for (int i=0;i<countIndex;i++) {
            ourPixels.setPixelColor(i,&currentColor);
          }
          ourPixels.show();
          countdownTimer.stepTime();
        } else {
          digitalWrite(END_LED_PIN,HIGH);
          ourPixels.setPixelColor(0,IDLE_COLOR);
          ourPixels.show();
          countdownTimer.reset();
          ourState = done;
        }
      }
    break;
  }
}
Start
Reset