#include <FastLED.h>

#define LED_PIN 2
#define NUM_LEDS 64
#define FRAMES_PER_SECOND 120

CRGB leds[NUM_LEDS];


void setup() {
  Serial.begin(2000000);
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
}

void loop() {
  // juggle();
  juggle2();

  FastLED.show();
  FastLED.delay(1000.f / FRAMES_PER_SECOND - (NUM_LEDS * 0.03f + 0.59f));
}


void juggle() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 20);
  byte dothue = 0;
  for ( int i = 0; i < 8; i++) {
    leds[beatsin16(i + 7, 0, NUM_LEDS - 1)] |= CHSV(dothue, 200, 255);
    dothue += 32;
  }
}


void juggle2() {
  fadeToBlackBy(leds, NUM_LEDS, 20);
  byte dothue = 0;
  uint32_t const ms = millis();
  for (byte i = 0; i < 8; i++) {
    // at this moment in time, where along the cosine wave is this dot?
    uint16_t cospos = ms * (i + 7);
    // if it's in the 2nd half of the wave, skip back to the 1st half 
    if (cospos >= 32768)
      cospos -= 32768;
    // to reverse direction use this instead:
    // if (cospos < 32768)
      // cospos += 32768;
    // get the cosine and shift it to be always positive
    uint16_t cosine = cos16(cospos) + 32767;
    // scale down from 0-65535 to 0-(NUM_LEDS - 1)
    uint16_t ledpos = (uint32_t)cosine * NUM_LEDS / 65536;
    leds[ledpos] |= CHSV(dothue, 200, 255);
    dothue += 32;
  }
}