#include <FastLED.h>

enum thePlanets {sun, mercury, venus, earth, mars, jupiter, saturn, uranus, neptune, pluto};

#define NUMPIX 1 + 6 + 16 + 36 + 46 + 56 + 66 + 76 + 86 // 415 ten pixel arrays
const int numOrbits = 10; // sun's orbit is rotational
int pixCount[numOrbits];

int orbit; // orbit counter
int step = 5, sunValue = 191;

int counter[numOrbits];
int startPosition[] = {1, 8, 10,  5,  2,   1,   4,   1,   3,   5}; // starting "clock" position  x/12
int orbitPixels[]   = {1, 6, 16, 26, 36,  46,  56,  66,  76,  86}; // pixels per ring
int orbitFirstPix[] = {0, 1,  7, 23, 49,  85, 131, 187, 253, 329};
int orbitLastPix[]  = {0, 6, 22, 48, 84, 130, 186, 252, 328, 414};

unsigned long timer[numOrbits], interval[] = {
  70.0, 40.0, 62.5, 38.4, 55.5,  260.8, 526.8, 1272.7, 2171.0, 2883.7
}; // millisecons per pixel for one Earth year in one second... see utilities.h

int planetColor[][3] = {
  {255, 255, 255}, // wht // sun
  {255,   0,   0}, // red // mercury
  {255, 127,   0}, // org // venus
  {  0, 127, 255}, // blu // earth
  {  0, 255, 255}, // cyn // mars
  {  0, 255,   0}, // grn // jupiter
  {255, 255,   0}, // yel // saturn
  {255,   0, 127}, // ros // uranus
  {255,   0, 255}, // mag // neptune
  {191, 191, 191}  // gry // pluto
};

#define DATAPIN    3
#define BUTTONPIN  2
#define MAXBRIGHT  255 // 415 pix * 3 LED/pix * 15 mA / LED = 18630mA (20A) at fullbright
CRGB led[NUMPIX]; // create the object

void setup() {
  FastLED.addLeds<WS2812B, DATAPIN, GRB>(led, NUMPIX);
  FastLED.setBrightness(MAXBRIGHT);
  FastLED.clear();
  FastLED.show();
  Serial.begin(115200);
  randomSeed(analogRead(A0));
  pinMode(LED_BUILTIN, OUTPUT);

  // relativeLocation(); while (1); // show planet location for 2024/08
  while (!digitalRead(BUTTONPIN)); // pause here, button-press to start
}

void loop() {
  relativeMotion();
}

void relativeMotion() {
  if (millis() - timer[orbit] >= interval[orbit]) { // check plante movement interval
    timer[orbit] = millis(); // reset orbit timer

    // sun LED = orbit 0
    if (sunValue >= 250 || sunValue < 127)
      step = -step;
    sunValue += step;
    led[0] = CRGB(255, sunValue, 0);

    // planets (not sun)
    pixCount[orbit]++; // move planet
    if (pixCount[orbit] > orbitPixels[orbit] - 1) // when past end of orbit...
      pixCount[orbit] = 0; // reset pixel counter to beginning
    led[pixCount[orbit] + orbitFirstPix[orbit]] = CRGB(planetColor[orbit][0], planetColor[orbit][1], planetColor[orbit][2]);
    if (pixCount[orbit] > 0) // after first LED...
      led[pixCount[orbit] - 1 + orbitFirstPix[orbit]] = CRGB(0, 0, 0); // ... clear previous LED
    if (pixCount[orbit] == 0) // when first LED...
      led[pixCount[orbit] + orbitLastPix[orbit]] = CRGB(0, 0, 0); // ... clear last LED
  }
  FastLED.show();
  if (orbit++ > 10) orbit = 1; // do not count sun (0)
}

//**********************************************************************
// Utility functions
//**********************************************************************

/*
  https://media.giphy.com/media/YqopropuC719C/giphy.gif
  https://theskylive.com/3dsolarsystem

  PLANETARY YEAR IN EARTH DAYS
  Sun:         25 days/ 0.07 years (for one Sol day)
  Mercury:     88 days/ 0.24 years at 47.87 km/s
  Venus:      225 days/ 0.61 years at 35.02 km/s
  Earth:      365 days/  1.0 year  at 29.78 km/s <-- 1 rev per year
  Mars:       687 days/  2.0 years at 24.08 km/s
  Jupiter:  4,333 days/ 12.0 years at 13.07 km/s
  Saturn:  10,759 days/ 29.5 years at  9.69 km/s
  Uranus:  30,687 days/ 84.0 years at  6.81 km/s
  Neptune: 60,190 days/165.0 years at  5.43 km/s
  Pluto:   90,520 days/248.0 years at  4.64 km/s

  PLANET INTERVALS PER PIXEL
  Sun        0.07 sec/rev /  1 pix/rev = 0.0700 sec/pix =   70.0ms
  Mercury    0.24 sec/rev /  6 pix/rev = 0.0400 sec/pix =   40.0ms
  Venus      0.61 sec/rev / 16 pix/rev = 0.0625 sec/pix =   62.5ms
  Earth      1.00 sec/rev / 26 pix/rev = 0.0384 sec/pix =   38.4ms
  Mars       2.00 sec/rev / 36 pix/rev = 0.0555 sec/pix =   55.5ms
  Jupiter   12.00 sec/rev / 46 pix/rev = 0.2608 sec/pix =  260.8ms
  Saturn    29.50 sec/rev / 56 pix/rev = 0.5268 sec/pix =  526.8ms
  Uranus    84.00 sec/rev / 66 pix/rev = 1.2727 sec/pix = 1272.7ms
  Neptune  165.00 sec/rev / 76 pix/rev = 2.1710 sec/pix = 2171.0ms
  Pluto    248.00 sec/rev / 86 pix/rev = 2.8837 sec/pix = 2883.7ms

  21 JULY 2024 Starting "clock" position
  https://www.theplanetstoday.com/
   8 // Mercury
  10 // Venus
   5 // Earth
   2 // Mars
   1 // Jupiter
   4 // Saturn
   1 // Uranus
   3 // Neptune
   5 // Pluto
*/

void relativeLocation() { // show relative position
  int totalPix;
  for (int orbit = 0; orbit < numOrbits; orbit++) { // skip sun
    int startPix = orbitPixels[orbit] * startPosition[orbit] / 12 + totalPix;
    led[startPix] = CRGB(planetColor[orbit][0], planetColor[orbit][1], planetColor[orbit][2]);
    Serial.print("orbit ");
    Serial.print(orbit);
    Serial.print(" at ");
    Serial.print(startPosition[orbit]);
    Serial.print(" o'clock pix ");
    Serial.println(startPix);
    FastLED.show();
    totalPix += orbitPixels[orbit];
  }
}

void planetNumbers() {
  Serial.println(sun);
  Serial.println(mercury);
  Serial.println(venus);
  Serial.println(earth);
  Serial.println(mars);
  Serial.println(jupiter);
  Serial.println(saturn);
  Serial.println(uranus);
  Serial.println(neptune);
  Serial.println(pluto);
}

void eachOrbit() {
  for (int orbit = 0; orbit < 10; orbit++) {
    for (int i = orbitFirstPix[orbit]; i < orbitFirstPix[orbit] + orbitPixels[orbit]; i++) {
      led[i] = CRGB(planetColor[orbit][0], planetColor[orbit][1], planetColor[orbit][2]);
      FastLED.show();
      led[i] = CRGB(0, 0, 0);
      delay(50);
    }
    delay(500);
  }
}

void oneOrbit() { // one orbit per orbit speed
  int planet = jupiter;
  for (int i = orbitFirstPix[planet]; i < orbitLastPix[planet]; i++) {
    led[i] = CRGB(planetColor[planet][0], planetColor[planet][1], planetColor[planet][2]);
    FastLED.show();
    led[i] = CRGB(  0,   0,   0);
    delay(interval[planet]);
  }
}

void fillOrbit(int orbit, int red, int grn, int blu) {
  for (int i = orbitFirstPix[orbit]; i < orbitFirstPix[orbit]  + orbitPixels[orbit]; i++) {
    led[i] = CRGB(red, grn, blu);
  }
  FastLED.show();
}

void propeller() {
  int steps = 16;
  for (int j = 0; j < steps; j++) {
    FastLED.clear();
    FastLED.show();
    for (int i = 0; i < 10; i++) {
      led[orbitFirstPix[i] + orbitPixels[i] * j / steps] = CRGB(planetColor[i][0], planetColor[i][1], planetColor[i][2]);
    }
    FastLED.show();
    delay(137);
  }
}

void firstPix() {
  Serial.print("First pixel: ");
  for (int i = 0; i < 10; i++) {
    Serial.print(orbitFirstPix[i]);
    if (i < 9) Serial.print(", ");
    led[orbitFirstPix[i]] = CRGB(planetColor[i][0], planetColor[i][1], planetColor[i][2]);
    FastLED.show();
  }
}

void rings() {
  int red, grn, blu;
  for (int i = 0; i < numOrbits; i++) {
    fillOrbit(i, planetColor[i][0], planetColor[i][1], planetColor[i][2]);
  }
  delay(250);
  FastLED.clear();
  FastLED.show();
}

void pixCheck() {
  for (int i = 0; i < NUMPIX; i++) {
    led[i] = CRGB(random(255), random(255), random(255));
  }
  FastLED.show();
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); // blink LED_BUILTIN
  delay(100);
  for (int i = 0; i < NUMPIX; i++) {
    led[i] = CRGB(255, 255, 255);
    FastLED.show();
    led[i] = CRGB(0, 0, 0);
  }
}
capacitor1000ufBreakout
PUSH