 
 // Walk the stairs adding random effects.
 void walk() {
-  static uint8_t valTop = 200;
-  static int i = 0;
-  // Pick two colors from the palette. 
-  choosePalette();
-  CRGB c1 = gPalette[gLastPalette];
-  CRGB c2 = gPalette[gLastPalette+1];
-  // chance of a random palette
-  i = random8(1,255); i = random8(1,255); // bit of seeding
-  if ( random8( 5 ) == 3 ){
-    c1 = CRGB(random8(3,100),random8(3,100),random8(3,100));
-    c2 = CRGB(random8(3,100),random8(3,100),random8(3,100));
-  }
-  // fix random Black palette.
-  if ( (int(c1.r) + int(c1.g) + int(c1.b)) < 6 ){
-    c1 = gPalette[2];
-    c2 = gPalette[4];
-  }
-  CRGB trans = CRGB::Black;
-  CRGB trans2 = CRGB::Black;
-  //(r2-r1)/ticks * tick)
   
-  for(gStair=0; gStair < NUM_LEDS; gStair+=2) {
-    // Fade in step
-    for (gBright=0; gBright<255; gBright = qadd8(gBright,4)) {
-      // Fade in from off
-      trans = blend(CRGB::Black,c1,gBright);
-      leds[gUpDown[gStair]] = trans;
-      leds[gUpDown[gStair + 1]] = trans;
-      if (  gStair >= 2 ) { // shift last to stairs to the 2nd color.
+  if ( stage == stage_init ){
+    valTop = 200;
+    // Pick two colors from the palette. 
+    choosePalette();
+    c1 = gPalette[gLastPalette];
+    c2 = gPalette[gLastPalette+1];
+    // chance of a random palette
+    if ( random8( 5 ) == 3 ){
+      c1 = CRGB(random8(3,100),random8(3,100),random8(3,100));
+      c2 = CRGB(random8(3,100),random8(3,100),random8(3,100));
+    }
+    // fix random Black palette.
+    if ( (int(c1.r) + int(c1.g) + int(c1.b)) < 8 ){
+      c1 = gPalette[2];
+      c2 = gPalette[4];
+    }
+    trans = CRGB::Black;
+    trans2 = CRGB::Black;
+    z[0] = c2;
+    z[1] = c1;
+    z[2] = CRGB(random8(2,100),random8(2,100),random8(2,100));
+    z[3] = c1;
+    z[4] = c2;
+    //(r2-r1)/ticks * tick)
+    gStair=0;
+    gBright=0;
+    interval=5;
+    i = 0;
+    x = 0;
+    r = 0;
+    g = 0;
+    b = 0;
+    walk_effect = (WalkEffects)random8( 0, 4 );
+    stage = stage_grow;
+  } else if ( stage == stage_grow ) {
+    if (gBright < 255){
+      if ( gStair < NUM_LEDS ){
+        trans = blend(CRGB::Black,c1,gBright); // fade in next two
+        leds[gUpDown[gStair]] = trans;
+        leds[gUpDown[gStair + 1]] = trans;
+      }
+      if (  gStair >= 2 ) { // shift last two stairs to the 2nd color.
         trans2 = blend(c1,c2,gBright);
         leds[gUpDown[gStair - 1]] = trans2;
         leds[gUpDown[gStair - 2]] = trans2;
       }
+      gBright = qadd8(gBright, 4);
+    } else {
+      if ( gStair < NUM_LEDS - 2 ) {
+        gStair+=2;  //next stair.
+      } else {
+        stage = stage_init_run;
+        gStair = 0;
+      }
+      gBright = 0;
+    }
+  } else if ( stage == stage_init_run ) {
+    fill_solid(leds, NUM_LEDS, c2);
+    x = 0;
+    stage = stage_run;
+  } else if ( stage == stage_run ) {
+    trans2 = c2;
+    randomEffect();  // waits for timer to run out.
+  } else if ( stage == stage_init_dim ) {
+    interval = 3;
+    for(b=0; b<255; b++) {
+      trans = blend(trans2,c2,b);
+      fill_solid(leds, NUM_LEDS, trans);
       FastLED.show();
-      FastLED.delay(1); 
-    }
-  }
-  
-  // Hue shift the last two stairs
-  for (gBright=0; gBright<255; gBright = qadd8(gBright,2)) {
-    trans2 = blend(c1,c2,gBright);
-    leds[gUpDown[NUM_LEDS - 1]] = trans2;
-    leds[gUpDown[NUM_LEDS - 2]] = trans2;
-    FastLED.show();
-    FastLED.delay(1); 
-  }
-
-  // Delay + random effects
-  
-  randomEffect(c1, c2);
-  
-  // Turn off steps
-  
-  for(gStair=0; gStair < NUM_LEDS; gStair+=2) {
-    for (gBright=0; gBright<=valTop; gBright++) { 
-      leds[gUpDown[gStair]].fadeToBlackBy( valTop );
-      leds[gUpDown[gStair + 1]].fadeToBlackBy( valTop );
-      FastLED.show();
-    }
-    leds[gUpDown[gStair]] = CRGB( 0, 0, 0);
-    leds[gUpDown[gStair + 1]] = CRGB( 0, 0, 0);
-    FastLED.show();
-  }
-  gLightsOn = LOW;  
+      FastLED.delay(8);
+    }
+    interval = 8;
+    gBright = 0;
+    gStair = 0;
+    stage = stage_dim;
+  } else if ( stage == stage_dim ) {
+    if ( gBright <= valTop  ) {
+      if ( gStair < NUM_LEDS ){
+        leds[gUpDown[gStair]].fadeToBlackBy( 6 );
+        leds[gUpDown[gStair + 1]].fadeToBlackBy( 6 );
+        gBright+=4;
+      } else {
+        stage = off;
+      }
+    } else {
+      leds[gUpDown[gStair]] = CRGB( 0, 0, 0);
+      leds[gUpDown[gStair + 1]] = CRGB( 0, 0, 0);
+      gStair += 2; 
+      gBright = 0;
+    }
+  } else {
+    stage = off;
+  }  
 }
 
 // Random effects for the walk() stair function.
-void randomEffect(CRGB c1, CRGB c2){
-  int i = 0, x = 0;
-  i = random8(1,255); i = random8(1,255); // bit of seeding
-  uint8_t var = random8( 1, 5 );
-  CRGB trans2 = CRGB::Black;
-  FastLED.delay(500); // Wait for it...
-  switch (var) {
-    case 1:
-      //sparkle
-      {
-        for ( i=0; i<=500; i++){
-          fill_solid(leds, NUM_LEDS, c2);
-          addGlitter(80);
-          FastLED.show();
-          FastLED.delay(8.5);
-        }        
-        fill_solid(leds, NUM_LEDS, c2);
+void randomEffect(){
+  if ( walk_effect == sparkle ) { 
+    interval = 8;
+    fill_solid(leds, NUM_LEDS, c2);
+    addGlitter(80);
+  } else if ( walk_effect == pulsate1 ) {
+    interval = 10;
+    if ( b < 255 ){
+      if ( i < 4 ) {
+        trans2 = blend(z[i],z[i+1],b);
+        fill_solid(leds, NUM_LEDS, trans2);
+        b=qadd8(b,1);
+      } else {
+        i = 0;
+      }
+    } else {
+      i++;
+      b=0;
+    }
+  } else if ( walk_effect == pulsate2 ) {
+    interval = 5;
+    for(gStair=0; gStair < NUM_LEDS; gStair++) {
+      trans2 = blend(c1,c2,quadwave8(r+=( -20 * gupDownDir )));
+      leds[gStair] = trans2;
+    }
+    gStair = 0;
+    r = ++g;
+  } else if ( walk_effect == flash ) {
+    if ( x == 0 ) {
+      for(gStair=0; gStair < NUM_LEDS; gStair+=2) {
+        leds[gUpDown[gStair]] = CRGB( 100, 100, 100);
+        leds[gUpDown[gStair + 1]] = CRGB( 100, 100, 100);
         FastLED.show();
-      }
-      break;
-    case 2:
-      //pulsate entire strip between colors
-      {
-        CRGBPalette16 z;
-        z[0] = c2;
-        z[1] = c1;
-        z[2] = CRGB(random8(2,100),random8(2,100),random8(2,100));
-        z[3] = c1;
-        for (i=0; i<4; i++){
-          for (x = 0; x<255; x=qadd8(x,1)){
-            trans2 = blend(z[i],z[i+1],x);
-            fill_solid(leds, NUM_LEDS, trans2);
-            FastLED.show();
-            FastLED.delay(10);
-          }
-        }
-      }
-      break;
-    case 3:
-      //pulsate each stair strip between colors
-      {
-        CRGBPalette16 p;
-        for (i=0; i<16; i+=2){
-          p[i] = c1;
-          p[i+1] = c2;
-        }
-        // Set final color
-        p[8] = c1;
-        p[9] = c1;
-        for (i=0; i < 10; i++){
-          CRGB cur1 = leds[0];
-          CRGB cur2 = leds[2];
-          for (uint8_t fade=0; fade<255; fade = qadd8(fade,2)) {
-            for(gStair=0; gStair < NUM_LEDS; gStair+=4) {
-              leds[gUpDown[gStair]] = blend(cur1,p[i],fade);
-              if (gStair + 1 < NUM_LEDS){
-                leds[gUpDown[gStair + 1]] = blend(cur1,p[i],fade);  
-              }
-              if (gStair + 2 < NUM_LEDS){
-                leds[gUpDown[gStair + 2]] = blend(cur2,p[i+1],fade);  
-              }
-              if (gStair + 3 < NUM_LEDS){
-                leds[gUpDown[gStair + 3]] = blend(cur2,p[i+1],fade);  
-              } 
-            }  
-            FastLED.show();
-            FastLED.delay(10);
-          }
-        }
-      }
-      break;
-    default: 
-      //Flash then solid 
-      {
-        for(gStair=0; gStair < NUM_LEDS; gStair+=2) {
-          leds[gUpDown[gStair]] = CRGB( 100, 100, 100);
-          leds[gUpDown[gStair + 1]] = CRGB( 100, 100, 100);
-          FastLED.show();
-        }
-        for(gStair=0; gStair < NUM_LEDS; gStair+=2) {
-          leds[gUpDown[gStair]] = c2;
-          leds[gUpDown[gStair+1]] = c2;
-          FastLED.show();
-        }
+        FastLED.delay(1);
+      }
+      for(gStair=0; gStair < NUM_LEDS; gStair+=2) {
+        leds[gUpDown[gStair]] = c2;
+        leds[gUpDown[gStair+1]] = c2;
         FastLED.show();
-        FastLED.delay(7000);
-      }
-  } 
+        FastLED.delay(1);
+      }
+      x = 1;
+      gStair=0;
+    } 
+  }
 }
 
 // Sparkle rainbow welcome give delay to calibrate pir sensors.  This also indicates if program crashed.


// Candle flicker, blown out, + ember glow
void flicker(){
  static uint16_t i = 0;
  static uint8_t rnd = 0;
  uint8_t r = 0, g = 0, b = 0;
  int8_t stair = 0;
  gBright = 0;
  for(gStair=0; gStair < NUM_LEDS; gStair+=2) {
    for( i = 0; i <= 18; i++ ) {
      for (stair = 0; stair <= gStair; stair+=2) {
        rnd = random8(1, 4);
        if ( rnd == 2 ){
          gBright = random8(110,140);
          leds[gUpDown[stair]] = CHSV( 60, 200, gBright );
          leds[gUpDown[stair + 1]] = CHSV( 60, 200, gBright );
        }
        FastLED.show();
      }
    }
  }
  // Wait
  for ( i=0; i<=300; i++) {
    for( gStair = 0; gStair < NUM_LEDS; gStair+=2) {  
      rnd = random8(1, 4);
      if ( rnd == 2 ){

#define PIN_PIR_UP 7            // PIR Upstairs Pin
#define GO_UP -1                // Direction control - Arduino at top of stairs
#define GO_DOWN 1               // Direction control - Arduino at top of stairs
uint8_t gHue = 0;               // track color shifts.
int8_t  gStair = 0;             // track curent stair.
uint8_t gBright = 0;            // track brightness
uint8_t gUpDown[NUM_LEDS];      // directional array to walk/loop up or down stairs.
int8_t gupDownDir = 1;
CRGB    leds[NUM_LEDS];         // setup leds object to access the string
CRGBPalette16 gPalette;         // some favorite and random colors for display.
CRGBPalette16 fade6 =         (CRGB( BRIGHTNESS, 0, 0),      CRGB(BRIGHTNESS,BRIGHTNESS,0), CRGB(0,BRIGHTNESS,0),
                              CRGB(0,BRIGHTNESS,BRIGHTNESS), CRGB(0,0,BRIGHTNESS),         CRGB(BRIGHTNESS, 0, BRIGHTNESS),
                              CRGB( BRIGHTNESS, 0, 0));
CRGBPalette16 z;
int8_t  gLastPalette = 15;      // track last chosen palette.
uint8_t gLastWalk = 1;
unsigned long currentMillis = millis(); // define here so it does not redefine in the loop.
long    previousMillis = 0;
long    previousOffMillis = 0; // countdown power off timer
long    offInterval = 30000; // 1000mills * 30sec
//long offInterval = 7000;
long    interval = 40;
enum Effects { ewalk, eflicker, efade6 };
Effects effect = ewalk;
enum WalkEffects { sparkle, pulsate1, pulsate2, flash };
WalkEffects walk_effect = sparkle;
// Stages of the animation.  Allows for PIR sensor to re-activation the run stage of the animation.
enum Stage { off, stage_init, stage_grow, stage_init_run, stage_run, stage_init_dim, stage_dim };
Stage stage = off;
int i = 0;
int x = 0;
uint8_t var = 0;
uint8_t valTop = 200;
uint8_t rnd = 0;
uint8_t r = 0, g = 0, b = 0, h = 0, s = 0, v = 0;
int8_t stair = 0;
CRGB c1;
CRGB c2;
CRGB trans;
CRGB trans2;


void setup() {
  delay (3000); // Power Up 3 second safety delay.
  //Serial.begin(57600);
  randomSeed(millis());
  FastLED.addLeds<WS2812B, PIN_LED, GRB>(leds, NUM_LEDS);  // NOTE set LED string type here.
  pinMode(PIN_PIR_DOWN, INPUT);
  pinMode(PIN_PIR_UP, INPUT);
  pinMode(13, OUTPUT);
  digitalWrite(PIN_PIR_DOWN, LOW);
  digitalWrite(PIN_PIR_UP, LOW);
  welcomeRainbow();             // rainbow - give time for PIR sensors to colibrate.
  setUpDown(GO_DOWN);           // populate the array index used for stair direction.
  setPalette();                 // setup some favorite & random colors
  stage = off;
}

// Main Loop track PIR sensors.
void loop() {
  currentMillis = millis();
  readSensors();
  if(currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    update_effect(); 
    FastLED.show();
  }
  if((currentMillis - previousOffMillis > offInterval) && stage == stage_run){
    stage = stage_init_dim;
    i = 0; r = 0; g = 0; b = 0;
  }
}

void readSensors(){
  if ( digitalRead(PIN_PIR_UP) == HIGH ){  // Walk Down.
    previousOffMillis = currentMillis;
    if ( stage == off ){
      chooseEffects();
      stage = stage_init;
      setUpDown(GO_DOWN);
    } else if ( stage == stage_dim || stage == stage_init_dim ){
      stage = stage_init_run;
    }
  } else if ( digitalRead(PIN_PIR_DOWN) == HIGH  ){ // Walk Up.
    previousOffMillis = currentMillis;
    if ( stage == off ){
      chooseEffects();
      stage = stage_init;
      setUpDown(GO_UP);
    } else if ( stage == stage_dim || stage == stage_init_dim){
      stage = stage_init_run;
    }
  }
}
   
void chooseEffects(){
  randomSeed(millis());
  r = random8(1, 255);
  if ( r >= 0 && r <= 100 ){
    effect = ewalk;  // My favorite transition with random effect variations
  } else if ( r > 100 && r <= 175 ){
    effect = eflicker;  // Candle with embers.
  } else {
    effect = efade6;  // hueshift rainbow.
  } 
}

void update_effect(){
  if ( effect == ewalk ){
    walk();  
  } else if ( effect == eflicker ){
    flicker();
  } else if ( effect == efade6 ){
    fade();
  }
}

// setup walking gUpDown array in forward: 0,1,2,3... or reverse:  ...3,2,1,0
void setUpDown(int8_t upDownDir){
  gupDownDir = upDownDir;
  uint8_t gStairStart = 0;
  if (upDownDir == GO_UP){
    for ( gStair = NUM_LEDS -1; gStair >= 0; gStair-- ){
