#include <FastLED.h>
#include <avr/pgmspace.h>
// How many leds in your strip?
#define NUM_LEDS 30
// For led chips like WS2812, which have a data line, ground, and power, you just
// need to define DATA_PIN. For led chipsets that are SPI based (four wires - data, clock,
// ground, and power), like the LPD8806 define both DATA_PIN and CLOCK_PIN
// Clock pin only needed for SPI based chipsets when not using hardware SPI
#define DATA_PIN 6
// Define the array of leds
CRGB leds[NUM_LEDS];
#define BRIGHTNESS 255
// Define a new type so we can create an array of sequences, along with metadata we want to add
struct Sequence {
uint8_t* sequence;
uint8_t length;
};
// Define the sequences
const PROGMEM uint8_t sequence0[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
const PROGMEM uint8_t sequence1[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
const PROGMEM uint8_t sequence2[] = {20, 22, 24, 26, 28};
const PROGMEM uint8_t sequence3[] = {21, 23, 25, 27, 29};
const PROGMEM Sequence sequences[] = {
{sequence0, sizeof(sequence0)},
{sequence1, sizeof(sequence1)},
{sequence2, sizeof(sequence2)},
{sequence3, sizeof(sequence3)},
};
void setup() {
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS); // GRB ordering is assumed
}
// A forward declaration of a function we're going to use before it's defined.
// I don't know why. I'm copying the style of the original code. Arduino code shouldn't need this.
void moveSequence(uint8_t, uint8_t, Sequence*);
void loop() {
// swap direction each second
static uint8_t dir = 0;
EVERY_N_MILLIS(1000) {
dir ^= 1;
}
// The "global" base hue. It increases by 1 each frame.
static uint8_t gHue = 0;
gHue += 1;
// each Sequence's "local" hue is derived from the "global" hue for this frame
uint8_t lHue = gHue;
// for each Sequence in the sequences[] array
for (uint8_t seqcnt = 0; seqcnt < sizeof(sequences) / sizeof(sequences[0]); seqcnt++) {
// shift the LEDs in this Sequence one pixel up or down
CRGB* uncovered = moveSequence(dir, &sequences[seqcnt]);
// plot over the freshly uncovered pixel
*uncovered = CHSV(lHue + random8(20), 255, 255);
// change the "local" hue for the next sequence
lHue += 64;
}
// dither for 50ms: slows down the animation speed, and may increase apparent colour depth.
FastLED.delay(50);
}
// shift a Sequence by one pixel, and return a pointer to the freshly uncovered pixel
CRGB* moveSequence(uint8_t dir, Sequence* sequence) {
uint8_t src, dst, length = pgm_read_byte_near(&sequence->length);
uint8_t* seq = pgm_read_ptr_near(&sequence->sequence);
switch (dir) {
case 0:
src = pgm_read_byte_near(seq);
for (uint8_t i = 1; i < length; i++) {
dst = src;
src = pgm_read_byte_near(seq + i);
leds[dst] = leds[src];
}
return &leds[pgm_read_byte_near(seq + length - 1)];
break;
case 1:
src = pgm_read_byte_near(seq + length - 1);
for (uint8_t i = length - 1; i > 0; i--) {
dst = src;
src = pgm_read_byte_near(seq + i - 1);
leds[dst] = leds[src];
}
return &leds[pgm_read_byte_near(seq)];
break;
default:
return &leds[pgm_read_byte_near(seq)];
break;
}
}