# define NLEDS	3

int ledArray[NLEDS] {3, 5, 6};
int buttonPin = 2;

unsigned char ledMachine(unsigned char);

void setup() {
  pinMode(ledArray[0], OUTPUT);
  pinMode(ledArray[1], OUTPUT);
  pinMode(ledArray[2], OUTPUT);
  pinMode (buttonPin, INPUT);
  pinMode (LED_BUILTIN, OUTPUT); // To see if off delay works. Onboard led

  Serial.begin (115200); Serial.println("LED FADE FSM\n");

  ledMachine(1);    // reset
}

unsigned char cycles = 5;

void loop() {
  unsigned char busy;

	digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
	
	busy = ledMachine(0);

	if (!busy && !--cycles) {
		Serial.println("That's All Folks!\n");
		while (1);		// hang it up here...
	}

}

enum {FADINGUP, TURNTOFF, TIMEOFF};

unsigned char ledMachine(unsigned char reset)
{	
	static unsigned char lmState = FADINGUP;		// what we doing?
	static unsigned char currentLED = 0;
	static unsigned int ledIntensity = 0;
	static unsigned long lastTime = 0;
	static unsigned char offTimer;

	if (reset) {
		// initialise or reset all machine variables
		currentLED = 0;
		ledIntensity = 0;
		lmState = FADINGUP;
		lastTime = 0;		// right away!

		return 1;				// finished, IDLE or reset, yes.
	}

	unsigned char returnCode = 1;		// not done, keep calling		

	unsigned long now = millis();
	if (now - lastTime < 20)   			// frame time? 50 fps here
    return;

	lastTime = now;
	
	switch (lmState) {
	case FADINGUP :						// make the LED a bit bright, switch to the next LED until all
		ledIntensity += 5;
		ledIntensity &= 0xff;		// constrain to 0..255

		analogWrite(ledArray[currentLED], ledIntensity);
	
		if (ledIntensity == 255)  { // we finished a fade up of an LED
			ledIntensity = 0;
			currentLED++;
			if (currentLED >= NLEDS) {
// we finished all fades up
				currentLED = 0;
				lmState = TURNTOFF;
			}
		}
		break;

	case TURNTOFF :
	    for (int i = 0; i <= NLEDS; i++)
	      analogWrite(ledArray[i], 0);
	      
	    lmState = TIMEOFF;
	    offTimer = 100;
    break;

	case TIMEOFF :
		if (offTimer && !--offTimer) {
			lmState = FADINGUP;
			returnCode = 1;		// yes finished
		}
		break;
	}
	
	return returnCode;
}