// 2021 by stevesigma
// Perform traffic light. TODO: make a pair.
// Changed to CRGB colors

#include <FastLED.h>

#define LED_PIN     13
#define NUM_LEDS    21
#define BRIGHTNESS  255
#define LED_TYPE    WS2812
#define COLOR_ORDER GRB

#define BLACK   CRGB(0x000000)
#define RED     CRGB::Red
#define ORANGE  CRGB::Yellow
#define GREEN   CRGB::Lime

#define GLOW_IN     true
#define FADE_OUT    false

// Imagine, every light is made of group of 7 pixels.
#define GROUP_SIZE  7
CRGB leds[NUM_LEDS];

void setup() {
    delay( 2000 ); // power-up safety delay

    FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
    FastLED.setBrightness(  BRIGHTNESS );

    for (int i=0;i<255;i++) {
        fill_solid(leds,NUM_LEDS,CHSV(i,255,255));
        FastLED.show();
        FastLED.delay(10);
    }

    fill_solid(leds,NUM_LEDS,CRGB::Black);    // Turn off
}


void loop() {
    uint8_t i;

    glowToColor(1,BLACK,RED);
    FastLED.delay(5000);

    glowToColor(2,BLACK,ORANGE);
    glowToColor(1,RED,BLACK);
    FastLED.delay(800);

    glowToColor(3,BLACK,GREEN);
    glowToColor(2,ORANGE,BLACK);
    FastLED.delay(5000);

    // flash
    for (i=0;i<5;i++) {
        glowToColor(3,BLACK,GREEN);
        FastLED.delay(100);
        glowToColor(3,GREEN,BLACK);
        FastLED.delay(50);
    }

    glowToColor(2,BLACK,ORANGE);
    FastLED.delay(800);
    glowToColor(2,ORANGE,BLACK);
}

// Perform gradient glow in or out of selected group
// 3 groups: 0,1,2,3 0=all groups
// Fade from black to selected color
void glowToColor(byte group, CRGB startColor, CRGB endColor) {
    uint8_t i;
    uint16_t v;
    uint8_t begin_pos;  // slice begin
    uint8_t end_pos;    // and end

    if ( group==0 ) {
        begin_pos = 0;
        end_pos = NUM_LEDS;
    } else {
        group = 4-group;    // 3->1, 2->2, 1->3

        begin_pos = GROUP_SIZE*(group-1);
        end_pos = GROUP_SIZE*group;
    }

    // FADE IN/OUT
    for ( v=5 ; v<255 ; v+=5 ) {
        for ( i=begin_pos ; i<end_pos ; i++) {
            // Mix up a new color, which is a blend of the start and end colors
            // Use the blend function to get the right mix for this particular pixel
            leds[i] = blend( startColor, endColor, v);
        }
        FastLED.show();
        FastLED.delay(4);
    }
    // fix twinkling leds
    if (endColor == BLACK) {
        for ( i=begin_pos ; i<end_pos ; i++) {
            leds[i] = BLACK;
        }
    }
    FastLED.show();

}