// https://forum.arduino.cc/t/new-version-of-an-old-neopixel-sketch-not-working-for-me/1301943/

#include <Adafruit_NeoPixel.h>

#define PIN3 3 // Neopixel pin
#define PIN5 5 // Neopixel pin
#define PIX 1 // Number of Neopixels

Adafruit_NeoPixel pixel3 = Adafruit_NeoPixel(PIX, PIN3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixel5 = Adafruit_NeoPixel(PIX, PIN5, NEO_GRB + NEO_KHZ800);

int step = 0, stage = 0, stages = 6; // steps per color, stage of color
int minimum = 0, maximum = 255, increas, decreas;; // counters

unsigned long fadeTimer, fadeTimeout = 3900; // microseconds

/*
  Pulse transition states
  1    2          3    4                       1 <- STATE changes
  |----|          |----|                       |
  | 50 |   200    | 50 |          750          | total 1050ms per "pulse"
  |     ----------      -----------------------
    ON     OFF      ON            OFF
*/

byte pulseState = 0;  // current state indicator
bool stateVisit[] = {0, 0, 0, 0, 0}; // state visit flags

unsigned long pulseTimer = 0; // base timer
unsigned long pulseTimeout[] = {0, // end of state 0
                                0 + 50, // end of state 1
                                0 + 50 + 200, // end of state 2
                                0 + 50 + 200 + 50, // end of state 3
                                0 + 50 + 200 + 50 + 750 // end of state 4
                               };

void setup() {
  Serial.begin(115200);
  pixel3.begin(); // initialize a Neopixel object/instance on pin 3
  pixel3.clear(); // clear any set pixels in the buffer
  pixel3.show(); // display the pixel buffer

  pixel5.begin(); // second object for pin 5
  pixel5.clear();
  pixel5.show();
}

void loop() {
  // fade timing
  if (micros() - fadeTimer > fadeTimeout) { // if "start" to "now" is greater than "interval"...
    fadeTimer = micros(); // ... start a new "start time" and...
    fade(); // perform the function
  }

  // pulse timing
  switch (pulseState) {
    case 0: // this case/state is visited one time only
      setPulseColor(maximum); // set pulse to maximum
      pulseState = 1; // update state level
      // stateVisit[0] = 1; // not needed, never will return, always comment-out
      break;

    case 1: // state 1
      if ((millis() - pulseTimer > pulseTimeout[1]) && !stateVisit[1]) { // check "now" time with interval
        setPulseColor(minimum); // set pulse to (this)
        pulseState = 2;
        stateVisit[1] = 1; // do not return to this state until clear
      }
      break;

    case 2: // state 2
      if ((millis() - pulseTimer > pulseTimeout[2]) && !stateVisit[2]) {
        setPulseColor(maximum);
        pulseState = 3;
        stateVisit[2] = 1;
      }
      break;

    case 3: // state 3
      if ((millis() - pulseTimer > pulseTimeout[3]) && !stateVisit[3]) {
        setPulseColor(minimum);
        pulseState = 4;
        stateVisit[3] = 1;
      }
      break;

    case 4: // state 4
      if ((millis() - pulseTimer > pulseTimeout[4])  && !stateVisit[4]) {
        setPulseColor(maximum);
        pulseState = 1; // next pulseState
        pulseTimer = millis(); // new start-of-pulse time in Case1/State1

        for (int i = 0; i < 4; i++)
          stateVisit[i] = 0; // clear state visit flags
      }
      break;
  }
}

void fade() {
  if (increas++ == maximum) { // increment step until counter is max
    increas = minimum; // reset step counter
    if (stage++ == stages) // increment stage until stage is max
      stage = 1; // reset stage
  }

  decreas = maximum - increas; // invert the up-counter into a down-counter

  switch (stage) { // color transitions
    case 0: setFadeColor(increas, minimum, minimum); break; // blk to red - one time only
    case 1: setFadeColor(maximum, increas, minimum); break; // red to yel
    case 2: setFadeColor(decreas, maximum, minimum); break; // yel to grn
    case 3: setFadeColor(minimum, maximum, increas); break; // grn to cyn
    case 4: setFadeColor(minimum, decreas, maximum); break; // cyn to blu
    case 5: setFadeColor(increas, minimum, maximum); break; // blu to mag
    case 6: setFadeColor(maximum, minimum, decreas); break; // mag to red
    default: break;
  }
}

void setFadeColor(int red, int grn, int blu) { // color arguments will be max, min or changing
  pixel3.setPixelColor(0, pixel3.Color(red, blu, grn));
  pixel3.show();
}

void setPulseColor(int red) { // "red" will be 0 or 255 (OFF or ON)
  pixel5.setPixelColor(0, pixel5.Color(red, minimum, minimum));
  pixel5.show();
}
1000uF capacitor