//Based around ESP32-S3 - NO PSRAM
//Program, circuit, and build by Travis Christensen of TC Technologies for Pat Cornelio
//Using FastLED for WS2812B by Daniel Garcia https://github.com/FastLED/FastLED
//Date: 2023-08-30
#define FASTLED_ALLOW_INTERRUPTS 0
#define FASTLED_INTERNAL // add this before including FastLED.h
#include <FastLED.h>
//////////////////////////////////////////////////////////////////////////////
// START PARAMETERS***********************************************************
//////////////////////////////////////////////////////////////////////////////
int debug = 1; //set to "1" to enable serial monitor, set to "0" to disable
#define NUM_STRIPS 8 //actual amount strips in use
#define VOLTS 5 //sets RGB operating voltage for MAX calculation
#define MAX_MA 10000 // defines max amperage of all RGB LEDS
//COLOUR SETTINGS
// For RGB colour codes go to https://steamtraininfo.com/led-lights__trashed/fast-led-color-names
// in reference to the colour list at http://fastled.io/docs/struct_c_r_g_b.html#aeb40a08b7cb90c1e21bd408261558b99abde6007b13c22c05d888db898ec814a7
#define frontMarkerColour (0xF8F8FF) //Ghost White (0xFF4500) //OrangeRed
#define rearMarkerColour (0x006400) //DarkGreen
#define brakesColour (0x800000) //Maroon
#define blackColour (0x000000) //Black
//BRIGHTNESS SETTINGS
#define BRIGHTNESS 255 //set initial default brightness to full
int brightMarkRun = 70; //0-255 RGB: brightness of the marker running lights
int brightMarkFlash = 255; //0-255 RGB: brightness of the marker flashes
int tailRunBrightness = 10; //0-255 LED: brightness of tail light running lights
int tailBrakeBrightness = 255; //0-255 LED: brightness of the tail light brakes
//TIMING SETTINGS
int anySigInputFreq = 1000; //(ms)how long to wait and hold the signals on between input pulses ms
int numBrakeFlash = 8; //how many times we flash the brakes when first applied
int brakeFlashSpeed = 100; //(ms) How fast the brake lights flash when first applied
//LINKED TIMING SETTINGS
//to sync the markers (markFillSpeed) and tail RGBs (tailFillSpeed)
//tailFillSpeed must be 50/23=2.1739 times faster than markFillSpeed
int markFillSpeed = 22; //(ms)RGB:how fast the marker lights are filled
int tailFillSpeed = 10; //(ms)RGB:how fast the tail lights are filled
//to sync tail LED with the above RGB speeds, sigFlashSpeed must be tailFillSpeed*50
int sigFlashSpeed = 500; //(ms)LED:Tail light led signal flash speed
//EFFECTS SETTINGS
int chanceOfRunGlitter = 100; //chance of glitter for running lights when called
int chanceOfShowGlitter = 100; //chance of glitter for show modes when called
//SHOW MODE 1 SETTINGS
int showModeOffTime = 3000; //hold the brake for this long to disengage show mode
int show1HaloSwell = 10; //(ms)time between next dim step of halo lights
int show1HaloStep = 5; //size of steps during dimming 0-255
int haloMin = 0; //min of 0-255 brightness for halos
int haloMax = 255; //max of 0-255 brightness for halos
int show1TailSwell = 10; //(ms)time between next dim step of tail lights
int show1TailStep = 5; //size of steps during dimming 0-255
int tailMin = 0; //min of 0-255 brightness for tails
int tailMax = 255; //max of 0-255 brightness for tails
//SHOW MODE 2 SETTINGS
//TwinkleFox see:https://gist.github.com/kriegsman/756ea6dcae8e30845b5a
#define TWINKLE_SPEED 6
#define TWINKLE_DENSITY 5
#define SECONDS_PER_PALETTE 30
CRGB gBackgroundColor = CRGB::Black;
#define AUTO_SELECT_BACKGROUND_COLOR 0
#define COOL_LIKE_INCANDESCENT 1
//LED stuff only
int show2Flash = 10; // Number of times to flash
int show2FlashFreq = 100; // Flash frequency in milliseconds
int show2FadeDuration = 1000; // Duration of fading in milliseconds
//ADC THRESHOLDS
const int onThreshold = 500; //ADC counts of input signal to register as ON
const int offThreshold = 500; //ADC counts of input signal to register as OFF
//////////////////////////////////////////////////////////////////////////////
// END PARAMETERS***********************************************************
//////////////////////////////////////////////////////////////////////////////
/********* RGB PIN REFERENCE ************************************************
STRIP_A = PORT 1 = PIN 13 = GRILL LIGHTS
STRIP_B = PORT 2 = PIN 12 = REAR LIGHTS
STRIP_C = PORT 3 = PIN 11 = LF MARKER LIGHT
STRIP_D = PORT 4 = PIN 10 = RF MARKER LIGHT
STRIP_E = PORT 5 = PIN 9 = LR MARKER LIGHT
STRIP_F = PORT 6 = PIN 6 = RR MARKER LIGHT
STRIP_G = PORT 7 = PIN 5 = SPARE 1
STRIP_H = PORT 8 = PIN 4 = SPARE 2
STRIP_I = PORT 9 = PIN 3 = SPARE 3
STRIP_J = PORT 10 = PIN 39 = SPARE 4
*/
//INPUT PINS DEFINITION*********************************************************
int leftSig = 34;
int rightSig = 15;
int brakeSig = 0;
int runSig = 4;
// int headSig = 14;
// int spareSig2 = 8;
// int spareSig3 = 36;
// int spareSig4 = 35;
//OUTPUT PINS DEFINITION********************************************************
//#define ONBOARD_LED PIN_NEOPIXEL
#define PIN_STRIP_A 13
#define PIN_STRIP_B 12
#define PIN_STRIP_C 25
#define PIN_STRIP_D 27
#define PIN_STRIP_E 26
#define PIN_STRIP_F 21
#define PIN_STRIP_G 5
#define PIN_STRIP_H 4
const int spare3Relay = 14; //not really a "relay" TIP120, 5A NPN transistor
const int spare4Relay = 4; //not really a "relay" TIP120, 5A NPN transistor
const int driveTailLed = 5;
const int passTailLed = 18;
//Set the number of LEDs for each strip******************************************
#define NUM_LEDS_PER_STRIP_A 10 //# OF LEDS NOT DEFINED
#define NUM_LEDS_PER_STRIP_B 100 //0-50 LEDs are the drivers tail light ring, 50-99 are the passenger tail light ring
#define NUM_LEDS_PER_STRIP_C 23
#define NUM_LEDS_PER_STRIP_D 23
#define NUM_LEDS_PER_STRIP_E 23
#define NUM_LEDS_PER_STRIP_F 23
#define NUM_LEDS_PER_STRIP_G 10 //# OF LEDS NOT DEFINED
#define NUM_LEDS_PER_STRIP_H 10 //# OF LEDS NOT DEFINED
//Set the number of LEDs for each port********************************************
CRGB port1[NUM_LEDS_PER_STRIP_A]; //Grille - not yet in use
CRGB port2[NUM_LEDS_PER_STRIP_B]; //Tail Lights
CRGB port3[NUM_LEDS_PER_STRIP_C]; //Left front marker
CRGB port4[NUM_LEDS_PER_STRIP_D]; //Right front marker
CRGB port5[NUM_LEDS_PER_STRIP_E]; //Left rear marker
CRGB port6[NUM_LEDS_PER_STRIP_F]; //Right rear marker
CRGB port7[NUM_LEDS_PER_STRIP_G]; //Interior Lights - not yet in use
CRGB port8[NUM_LEDS_PER_STRIP_H]; //Spare 1 - not yet in use
CRGB onBoard[1];
//General Variables****************************************************************
int leftSigToggle = 0;
int rightSigToggle = 0;
int leftSigOn = 0;
int rightSigOn = 0;
int goLeftSig = 0;
int goRightSig = 0;
static int prevGoLeftSig = 0;
static int prevGoRightSig = 0;
int leftSigTogPrevMillis = 0; //to store the last time we saw a left signal pulse
int rightSigTogPrevMillis = 0; //to store the last time we saw a right signal pulse
int leftSigPrevMillis = 0; //to store this time we saw a left signal pulse
int rightSigPrevMillis = 0; //to store this time we saw a right signal pulse
int runCount = 0;
int headCount = 0;
int brakeCount = 0;
int driveTailLedOutput = 0;
int passTailLedOutput = 0;
//variables to store last RGB led written - not in use
int port1Position = 0;
int port2Position = 0;
int port3Position = 0;
int port4Position = 0;
int port5Position = 0;
int port6Position = 0;
int port7Position = 0;
int port8Position = 0;
int port9Position = 0;
int port10Position = 0;
int runActive = 0;
int leftActive = 0;
int rightActive = 0;
int brakeActive = 0;
//showMode 1 & 2 variables
int showTarget = 0;
int show1Active = 0;
int show2Active = 0;
int show1CodeCounter = 0;
int show1Step = 0;
int show2Step = 0;
int haloVar = 0; //variable to hold value of output to halos
int haloToggle = 0; //state of last halo
int tailVar = 0; //variable to hold value of output to tails
int tailToggle = 0; //state of last tail
int tailRightRGBtoggle = 0;
int tailLeftRGBtoggle = 0;
//showMode2 variables
//TwinkleFox Defines see:https://gist.github.com/kriegsman/756ea6dcae8e30845b5a
// Example of dim incandescent fairy light background color
// CRGB gBackgroundColor = CRGB(CRGB::FairyLight).nscale8_video(16);
CRGBPalette16 gCurrentPalette;
CRGBPalette16 gTargetPalette;
unsigned long show2LastFlashTime = 0; // To keep track of the last flash time
unsigned long show2LastFadeTime = 0; // To keep track of the last fade time
int show2TailBrightness = 0; // To store the current tail brightness
int leftMarkVar = 0;
int rightMarkVar = 0;
int runMarkVar = 0;
int runMarkFillToggle = 0;
int leftMarkToggle = 0;
int rightMarkToggle = 0;
int leftTailVar = -1; //start of the driver tail light strip
int rightTailVar = 49; //start of the passenger tail light strip
int leftTailToggle = 0;
int rightTailToggle = 0;
void setup() {
if (debug == 1){
Serial.begin(9600);
}
FastLED.setMaxPowerInVoltsAndMilliamps( VOLTS, MAX_MA);
chooseNextColorPalette(gTargetPalette);
//delay(1000);
// tell FastLED there's "NUM_LEDS_PER_STRIP_A" NEOPIXEL leds on port1(pin 13), and so on...
// FastLED.addLeds<WS2812B, PIN_STRIP_A, GRB>(port1, NUM_LEDS_PER_STRIP_A).setCorrection( TypicalLEDStrip );
FastLED.addLeds<WS2812B, PIN_STRIP_B, GRB>(port2, NUM_LEDS_PER_STRIP_B).setCorrection( TypicalLEDStrip );
//FastLED.addLeds<WS2812B, PIN_STRIP_C, GRB>(port3, NUM_LEDS_PER_STRIP_C).setCorrection( TypicalLEDStrip );
// FastLED.addLeds<WS2812B, PIN_STRIP_D, GRB>(port4, NUM_LEDS_PER_STRIP_D).setCorrection( TypicalLEDStrip );
// FastLED.addLeds<WS2812B, PIN_STRIP_E, GRB>(port5, NUM_LEDS_PER_STRIP_E).setCorrection( TypicalLEDStrip );
//FastLED.addLeds<WS2812B, PIN_STRIP_F, GRB>(port6, NUM_LEDS_PER_STRIP_F).setCorrection( TypicalLEDStrip );
// FastLED.addLeds<WS2812B, PIN_STRIP_G, GRB>(port7, NUM_LEDS_PER_STRIP_G).setCorrection( TypicalLEDStrip );
// FastLED.addLeds<WS2812B, PIN_STRIP_H, GRB>(port8, NUM_LEDS_PER_STRIP_H).setCorrection( TypicalLEDStrip );
FastLED.addLeds<WS2812B, 33 ,GRB>(onBoard, 1);
FastLED.setBrightness(BRIGHTNESS);
//set pins as inputs and outputs
pinMode(leftSig, INPUT);
pinMode(rightSig, INPUT);
pinMode(brakeSig, INPUT);
pinMode(runSig, INPUT);
// pinMode(headSig, INPUT);
// pinMode(spareSig2, INPUT);
// pinMode(spareSig3, INPUT);
// pinMode(spareSig4, INPUT);
pinMode(spare3Relay, OUTPUT);
pinMode(spare4Relay, OUTPUT);
pinMode(driveTailLed, OUTPUT);
pinMode(passTailLed, OUTPUT);
//pinMode(7, OUTPUT);
//digitalWrite(7,LOW); //set GPIO7 Low to disable stemma QT
digitalWrite(driveTailLed,LOW);
digitalWrite(passTailLed,LOW);
}
void loop() {
delay(10); //helps simulation. comment this out for real life
FastLED.show();
//these two lines are just the onboard neopixel
static uint8_t starthue = 0;
fill_rainbow(onBoard,1,--starthue,20);
if (show1Active == 0 && show2Active == 0){
doTail();
doMarkers();
}
if (show1Active == 1){
doShow1();
}
if (show2Active == 1){
doShow2();
EVERY_N_SECONDS( SECONDS_PER_PALETTE ) {
chooseNextColorPalette( gTargetPalette );
}
EVERY_N_MILLISECONDS( 10 ) {
nblendPaletteTowardPalette( gCurrentPalette, gTargetPalette, 12);
}
drawTwinkles(port1, NUM_LEDS_PER_STRIP_A);
drawTwinkles(port2, NUM_LEDS_PER_STRIP_B);
drawTwinkles(port3, NUM_LEDS_PER_STRIP_C);
drawTwinkles(port4, NUM_LEDS_PER_STRIP_D);
drawTwinkles(port5, NUM_LEDS_PER_STRIP_E);
drawTwinkles(port6, NUM_LEDS_PER_STRIP_F);
drawTwinkles(port7, NUM_LEDS_PER_STRIP_G);
drawTwinkles(port8, NUM_LEDS_PER_STRIP_H);
}
//rear input pin states
leftSig = analogRead(34);
rightSig = analogRead(15);
brakeSig = analogRead(0);
runSig = analogRead(4);
// headSig = analogRead(14);
// spareSig2 = analogRead(8);
// spareSig3 = analogRead(36);
// spareSig4 = analogRead(35);
unsigned long leftSigCurrentMillis = millis();
unsigned long rightSigCurrentMillis = millis();
unsigned long leftSigTogCurrentMillis = millis();
unsigned long rightSigTogCurrentMillis = millis();
//CHECK IF THE INPUT PULSES FROM THE LEFT FLASHER RELAY IS HAPPENING
if (leftSig >= onThreshold) {
goLeftSig = 1;
leftSigTogPrevMillis = leftSigTogCurrentMillis; //SAVE THE LAST TIME WE RECEIVED AN INPUT
}
//CHECK IF THE INPUT PULSE HASN'T OCCURED FOR MORE THAN "anySigInputFreq", IF TRUE, STOP THE LEFT SIGNAL
if (leftSig <= offThreshold){
if (leftSigTogCurrentMillis - leftSigTogPrevMillis >= anySigInputFreq){
goLeftSig = 0;
}
}
//CHECK IF THE INPUT PULSES FROM THE RIGHT FLASHER RELAY IS HAPPENING
if (rightSig >= onThreshold) {
goRightSig = 1;
rightSigTogPrevMillis = rightSigTogCurrentMillis; //SAVE THE LAST TIME WE RECEIVED AN INPUT
}
//CHECK IF THE INPUT PULSE HASN'T OCCURED FOR MORE THAN "anySigInputFreq", IF TRUE, STOP THE RIGHT SIGNAL
if (rightSig <= offThreshold){
if (rightSigTogCurrentMillis - rightSigTogPrevMillis >= anySigInputFreq){
goRightSig = 0;
}
}
//are the running lights on?
if (runSig >= onThreshold){
runActive = 1;
// doRunLights();
}
else{
runActive = 0;
}
//are the brakes on?
if (brakeSig >= onThreshold){
brakeActive = 1;
// doBrakeLights();
}
else{
brakeActive = 0;
}
//Which show mode are we working toward entering the code on?
if (show1Step > show2Step){
showTarget = 1;
}
else{
showTarget = 2;
}
if (show1Step == show2Step){
showTarget = 0;
}
//SHOW MODE 1 CODE AND CONTROL///////////////////////////////////////
if (rightSig >= onThreshold){
if (show1Step == 0){
show1Step = 1;
}
if (show1Step == 2){
show1Step = 3;
}
}
else if (rightSig <= onThreshold && show1Step == 1){
if (leftSig >= onThreshold){
show1Step = 2;
}
}
else if (rightSig <= onThreshold && show1Step == 3){
if (leftSig >= onThreshold){
show1Step = 4;
}
}
else if (brakeSig >= onThreshold && show1Step == 4 && showTarget == 1){
show1Active = 1;
show1Step = 5;
clearAll();
}
if (show1Step != 0 && show1Step != 5){
//if we are in step 1 of the code, and the next input is wrong, reset show1Step
if (show1Step != 4 && brakeActive == 1 && show1Active == 0){
show1Step = 0;
}
}
if (show1Active == 1) {
EVERY_N_MILLISECONDS(showModeOffTime){
if (brakeSig >= onThreshold){ //Deactivate show1Mode and clear everything
show1Active = 0;
clearAll();
}
}
}
//END SHOW MODE 1 CODE AND CONTROL///////////////////////////////////////
//SHOW MODE 2 CODE AND CONTROL///////////////////////////////////////
if (leftSig >= onThreshold){
if (show2Step == 0){
show2Step = 1;
}
if (show2Step == 2){
show2Step = 3;
}
}
else if (leftSig <= onThreshold && show2Step == 1){
if (rightSig >= onThreshold){
show2Step = 2;
}
}
else if (leftSig <= onThreshold && show2Step == 3){
if (rightSig >= onThreshold){
show2Step = 4;
}
}
else if (brakeSig >= onThreshold && show2Step == 4 && showTarget == 2){
show2Active = 1;
show2Step = 5;
clearAll();
}
if (show2Step != 0 && show2Step != 5){
//if we are in step 1 of the code, and the next input is wrong, reset show2Step
if (show2Step != 4 && brakeActive == 1 && show2Active == 0){
show2Step = 0;
}
}
if (show2Active == 1) {
EVERY_N_MILLISECONDS(showModeOffTime){
if (brakeSig >= onThreshold){ //Deactivate show2Mode and clear everything
show2Active = 0;
clearAll();
}
}
}
//END SHOW MODE 2 CODE AND CONTROL///////////////////////////////////////
if (debug == 1){
EVERY_N_MILLISECONDS(250){
// Serial.print("leftSig Value: ");
// Serial.println(leftSig);
// Serial.print("rightSig Value: ");
// Serial.println(rightSig);
// Serial.print("BrakeSig Value: ");
// Serial.println(brakeSig);
// Serial.print("RunSig Value: ");
// Serial.println(runSig);
// Serial.print("leftSigOn: ");
// Serial.println(leftSigOn);
Serial.print("goLeftSig: ");
Serial.println(goLeftSig);
// Serial.print("rightSigOn: ");
// Serial.println(rightSigOn);
Serial.print("goRightSig: ");
Serial.println(goRightSig);
// // Serial.print("headSig: ");
// // Serial.println(headSig);
// Serial.print("spare3Output: ");
// Serial.println(spare3Relay);
Serial.print("brakeActive: ");
Serial.println(brakeActive);
// Serial.print("brakeCount: " );
// Serial.println(brakeCount);
Serial.print("runActive: ");
Serial.println(runActive);
// Serial.print("driveTailLED Output: ");
// Serial.println(driveTailLedOutput);
// Serial.print("passTailLED Output: ");
// Serial.println(passTailLedOutput);
// Serial.print("leftMarkToggle: ");
// Serial.println(leftMarkToggle);
// Serial.print("leftMarkVar: ");
// Serial.println(leftMarkVar);
// Serial.print("runMarkVar: ");
// Serial.println(runMarkVar);
// Serial.print("show1Step ");
// Serial.println(show1Step);
// Serial.print("show1Active ");
// Serial.println(show1Active);
// Serial.print("show2Step ");
// Serial.println(show2Step);
// Serial.print("show2Active ");
// Serial.println(show2Active);
Serial.println();
}
}
}
void doTail(){ //*****************DO ALL THE TAIL LIGHT THINGS*************************
if (brakeActive == 1){ //checks if JUST brake is on
//Do a flashing of the LED when the brakes are first applied
if (brakeCount <= numBrakeFlash){
//if we havent flashed more times than numBrakeFlash
EVERY_N_MILLISECONDS(brakeFlashSpeed){// LED:flash the brakes numBrakeFlash times
brakeCount++;
if (driveTailLedOutput == 0){
analogWrite(driveTailLed,tailBrakeBrightness);
driveTailLedOutput = tailBrakeBrightness;
analogWrite(passTailLed,tailBrakeBrightness);
passTailLedOutput = tailBrakeBrightness;
fill_solid(port2,100, brakesColour); //RGB:this copies the LED
}
else{
analogWrite(driveTailLed,0);
driveTailLedOutput = 0;
analogWrite(passTailLed,0);
passTailLedOutput = 0;
fill_solid(port2,100, blackColour); //RGB:this copies the LED
}
}
}
else if (goRightSig == 1 and goLeftSig == 1){ // RGB:if BRAKES are on & 4-WAYS, do RGB swipe both
EVERY_N_MILLISECONDS(tailFillSpeed){
if (rightTailVar < 100){
rightTailVar++;
port2[rightTailVar] = brakesColour;
}
else{
fill_solid(port2+50,50, blackColour);
rightTailVar = 49;
}
if (leftTailVar < 50){
leftTailVar++;
port2[leftTailVar] = brakesColour;
}
else{
fill_solid(port2,50, blackColour);
leftTailVar = -1;
}
}
EVERY_N_MILLISECONDS(sigFlashSpeed){ // LED:if BRAKES are on & 4-WAYS, make sure we are flashing both
if (passTailLedOutput != tailBrakeBrightness){
analogWrite(passTailLed,tailBrakeBrightness);
passTailLedOutput = tailBrakeBrightness;
//fill_solid(port2+50,50, brakesColour); //RGB:this copies the LED
}
else{
analogWrite(passTailLed,0);
passTailLedOutput = 0;
//fill_solid(port2+50,50, blackColour); //RGB:this copies the LED
}
if (driveTailLedOutput != tailBrakeBrightness){
analogWrite(driveTailLed,tailBrakeBrightness);
driveTailLedOutput = tailBrakeBrightness;
//fill_solid(port2,50, brakesColour); //RGB:this copies the LED
}
else{
analogWrite(driveTailLed,0);
driveTailLedOutput = 0;
//fill_solid(port2,50, blackColour); //RGB:this copies the LED
}
}
}
else if (goLeftSig == 1){ // RGB:if BRAKES are on & LEFT signal is on, do RGB swipe
analogWrite(passTailLed,tailBrakeBrightness);
passTailLedOutput = tailBrakeBrightness;
EVERY_N_MILLISECONDS(tailFillSpeed){
if (leftTailVar < 50){
leftTailVar++;
port2[leftTailVar] = brakesColour;
}
else{
fill_solid(port2,50, blackColour);
leftTailVar = -1;
}
}
EVERY_N_MILLISECONDS(sigFlashSpeed){ // LED:if BRAKES are on & LEFT signal is on, make sure we are flashing
if (driveTailLedOutput != tailBrakeBrightness){
analogWrite(driveTailLed,tailBrakeBrightness);
driveTailLedOutput = tailBrakeBrightness;
// fill_solid(port2,50, brakesColour); //RGB:this copies the LED
}
else{
analogWrite(driveTailLed,0);
driveTailLedOutput = 0;
// fill_solid(port2,50, blackColour); //RGB:this copies the LED
}
}
}
else if (goRightSig == 1){ // RGB:if BRAKES are on & RIGHT signal is on, do RGB swipe
analogWrite(driveTailLed,tailBrakeBrightness);
driveTailLedOutput = tailBrakeBrightness;
EVERY_N_MILLISECONDS(tailFillSpeed){
if (rightTailVar < 100){
rightTailVar++;
port2[rightTailVar] = brakesColour;
}
else{
fill_solid(port2+50,50, blackColour);
rightTailVar = 49;
}
}
EVERY_N_MILLISECONDS(sigFlashSpeed){ // LED:if BRAKES are on & RIGHT signal is on, make sure we are flashing
if (passTailLedOutput != tailBrakeBrightness){
analogWrite(passTailLed,tailBrakeBrightness);
passTailLedOutput = tailBrakeBrightness;
//fill_solid(port2+50,50, brakesColour); //RGB:this copies the LED
}
else{
analogWrite(passTailLed,0);
passTailLedOutput = 0;
//fill_solid(port2+50,50, blackColour); //RGB:this copies the LED
}
}
}
else{ //no signal is on, but the brakes are on solid after flashing
analogWrite(driveTailLed,tailBrakeBrightness); //LED
driveTailLedOutput = tailBrakeBrightness;
analogWrite(passTailLed,tailBrakeBrightness);
passTailLedOutput = tailBrakeBrightness;
fill_solid(port2,50, brakesColour); //RGB driver:this copies the LED
fill_solid(port2+50,50,brakesColour);//RGB pass:this copies the LED
}
}
//BRAKES ARE OFF NOW
//4-WAY FLASHERS WITH BRAKES OFF
else if (goRightSig == 1 and goLeftSig == 1){ // RGB:if BRAKES are off & 4-WAYS, do RGB swipe both
EVERY_N_MILLISECONDS(tailFillSpeed){
if (rightTailVar < 100){
rightTailVar++;
port2[rightTailVar] = brakesColour;
}
else{
fill_solid(port2+50,50, blackColour);
rightTailVar = 49;
}
if (leftTailVar < 50){
leftTailVar++;
port2[leftTailVar] = brakesColour;
}
else{
fill_solid(port2,50, blackColour);
leftTailVar = -1;
}
}
EVERY_N_MILLISECONDS(sigFlashSpeed){ // LED:if BRAKES are off & 4-WAYS, make sure we are flashing both
if (passTailLedOutput != tailBrakeBrightness){
analogWrite(passTailLed,tailBrakeBrightness);
passTailLedOutput = tailBrakeBrightness;
//fill_solid(port2+50,50, brakesColour); //RGB:this copies the LED
}
else{
analogWrite(passTailLed,0);
passTailLedOutput = 0;
//fill_solid(port2+50,50, blackColour); //RGB:this copies the LED
}
if (driveTailLedOutput != tailBrakeBrightness){
analogWrite(driveTailLed,tailBrakeBrightness);
driveTailLedOutput = tailBrakeBrightness;
//fill_solid(port2,50, brakesColour); //RGB:this copies the LED
}
else{
analogWrite(driveTailLed,0);
driveTailLedOutput = 0;
//fill_solid(port2,50, blackColour); //RGB:this copies the LED
}
}
}
//RUNNING LIGHTS FILL
else if (runActive == 1 && goLeftSig == 0 && goRightSig == 0){
analogWrite(driveTailLed,tailRunBrightness);
driveTailLedOutput = tailRunBrightness;
analogWrite(passTailLed,tailRunBrightness);
passTailLedOutput = tailRunBrightness;
brakeCount = 0;
EVERY_N_MILLISECONDS(tailFillSpeed){
if (leftTailVar < 50){
leftTailVar++;
port2[leftTailVar] = brakesColour;
FastLED.show();
//delay(10);//maybe needed for both lights to fill at once
}
else{
fill_solid(port2,50, brakesColour);//if the fill animation has completed, turn solid
}
if (rightTailVar < 100){
rightTailVar++;
port2[rightTailVar] = brakesColour;
FastLED.show();
}
else{
fill_solid(port2+50,50, brakesColour);
}
if (random8() < chanceOfRunGlitter){
port2[ random16(100) ] += CRGB::White;
}
}
}
//if the brakes and running lights are off, but the left signal is on
else if (runActive == 0 && goLeftSig == 1){
brakeCount = 0;
EVERY_N_MILLISECONDS(sigFlashSpeed){
if (driveTailLedOutput != tailBrakeBrightness){
analogWrite(driveTailLed,tailBrakeBrightness);
driveTailLedOutput = tailBrakeBrightness;
// fill_solid(port2,50, brakesColour); //RGB:this copies the LED
}
else{
analogWrite(driveTailLed,0);
driveTailLedOutput = 0;
// fill_solid(port2,50, blackColour); //RGB:this copies the LED
}
}
EVERY_N_MILLISECONDS(tailFillSpeed){
if (leftTailVar < 50){
leftTailVar++;
port2[leftTailVar] = brakesColour;
}
else{
fill_solid(port2,50, blackColour);
leftTailVar = -1;
}
}
}
//if the brakes are off, but the running lights and left signal are on
else if (runActive == 1 && goLeftSig == 1){
analogWrite(passTailLed,tailRunBrightness);
passTailLedOutput = tailRunBrightness;
fill_solid(port2+50,50, brakesColour);//RGB:make sure the passenger running light is on
brakeCount = 0;
EVERY_N_MILLISECONDS(sigFlashSpeed){
if (driveTailLedOutput != tailBrakeBrightness){
analogWrite(driveTailLed,tailBrakeBrightness);
driveTailLedOutput = tailBrakeBrightness;
// fill_solid(port2,50, brakesColour); //RGB:this copies the LED
}
else{ //turn the left off at the specified interval
analogWrite(driveTailLed,0);
driveTailLedOutput = 0;
// fill_solid(port2,50, blackColour); //RGB:this copies the LED
}
}
EVERY_N_MILLISECONDS(tailFillSpeed){
if (leftTailVar < 50){
leftTailVar++;
port2[leftTailVar] = brakesColour;
}
else{
fill_solid(port2,50, blackColour);
leftTailVar = -1;
}
}
}
//if the brakes and running lights are off, but the right signal is on
else if (runActive == 0 && goRightSig == 1 && brakeActive == 0){
brakeCount = 0;
EVERY_N_MILLISECONDS(sigFlashSpeed){
if (passTailLedOutput != tailBrakeBrightness){
analogWrite(passTailLed,tailBrakeBrightness);
passTailLedOutput = tailBrakeBrightness;
// fill_solid(port2+50,50,brakesColour); //RGB:this copies the LED
}
else{
analogWrite(passTailLed,0);
passTailLedOutput = 0;
// fill_solid(port2+50,50,blackColour); //RGB:this copies the LED
}
}
EVERY_N_MILLISECONDS(tailFillSpeed){
if (rightTailVar < 100){
rightTailVar++;
port2[rightTailVar] = brakesColour;
}
else{
fill_solid(port2+50,50, blackColour);
rightTailVar = 49;
}
}
}
//if the brakes are off, but the running lights and right signal are on
else if (runActive == 1 && goRightSig == 1 && brakeActive == 0){
analogWrite(driveTailLed,tailRunBrightness);
driveTailLedOutput = tailRunBrightness;
fill_solid(port2,50, brakesColour);//RGB:make sure the driver running light is on
brakeCount = 0;
EVERY_N_MILLISECONDS(sigFlashSpeed){
if (passTailLedOutput != tailBrakeBrightness){
analogWrite(passTailLed,tailBrakeBrightness);
passTailLedOutput = tailBrakeBrightness;
// fill_solid(port2+50,50,brakesColour); //RGB:this copies the LED
}
else{ //turn the right off at the specified interval
analogWrite(passTailLed,0);
passTailLedOutput = 0;
// fill_solid(port2+50,50,blackColour); //RGB:this copies the LED
}
}
EVERY_N_MILLISECONDS(tailFillSpeed){
if (rightTailVar < 100){
rightTailVar++;
port2[rightTailVar] = brakesColour;
}
else{
fill_solid(port2+50,50, blackColour);
rightTailVar = 49;
}
}
}
//if the brakes, running, and left signal is off
if (runActive == 0 && goLeftSig == 0 && brakeActive == 0){
brakeCount = 0;
analogWrite(driveTailLed,0);
driveTailLedOutput = 0;
fill_solid(port2,50, blackColour);
leftTailVar = -1;
}
//if the brakes, running, and right signal is off
if (runActive == 0 && goRightSig == 0 && brakeActive == 0){
brakeCount = 0;
analogWrite(passTailLed,0);
passTailLedOutput = 0;
fill_solid(port2+50,50,blackColour);
rightTailVar = 49;
}
//Everything is off
if (runActive == 0 && goRightSig == 0 && goLeftSig == 0 && brakeActive == 0){
brakeCount = 0;
analogWrite(passTailLed,0);
passTailLedOutput = 0;
// fill_solid(port2+50,50,blackColour);
fadeToBlackBy(port2+50,50,1);
rightTailVar = 49;
analogWrite(driveTailLed,0);
driveTailLedOutput = 0;
// fill_solid(port2,50, blackColour);
fadeToBlackBy(port2,50,1);
leftTailVar = -1;
}
//END TAIL LIGHTS///////////////////////////////////////////////
}
/********MARKERS************************************************/
void doMarkers(){
//RUNNING LIGHTS
if (prevGoLeftSig == 1 && goLeftSig == 0) {
runMarkVar = 0; // Set runMarkVar to 0 when goLeftSig turns from 1 to 0
prevGoLeftSig = 0;
}
if (prevGoRightSig == 1 && goRightSig == 0) {
runMarkVar = 0; // Set runMarkVar to 0 when goLeftSig turns from 1 to 0
prevGoRightSig = 0;
}
if (runActive == 1){ //are the running lights on?
if (runMarkVar <= 22){
EVERY_N_MILLISECONDS(markFillSpeed){
port3[runMarkVar] = frontMarkerColour;
port5[runMarkVar] = rearMarkerColour;
port4[runMarkVar] = frontMarkerColour;
port6[runMarkVar] = rearMarkerColour;
runMarkVar++;
runMarkFillToggle = 1;
leftMarkVar = runMarkVar;
rightMarkVar = runMarkVar;
}
}
else if (goLeftSig == 1){ //Running lights and left signal is on
prevGoLeftSig = 1;
if (leftMarkVar >= -1){
EVERY_N_MILLISECONDS(markFillSpeed){
port3[leftMarkVar] = blackColour;
port5[leftMarkVar] = blackColour;
leftMarkVar--;
}
}
else{
runMarkVar = 0;
leftMarkVar = 0;
}
}
//Running lights and right signal is on
else if (goRightSig == 1){ //Running lights and right signal is on
prevGoRightSig = 1;
if (rightMarkVar >= -1){
EVERY_N_MILLISECONDS(markFillSpeed){
port4[rightMarkVar] = blackColour;
port6[rightMarkVar] = blackColour;
rightMarkVar--;
}
}
else{
runMarkVar = 0;
rightMarkVar = 0;
}
}
}
//Running lights are off, but left signal is on
else if (runActive == 0 && goLeftSig == 1){
EVERY_N_MILLISECONDS(markFillSpeed){
if (leftMarkVar <= 22 && leftMarkToggle == 0){
leftMarkVar++;
port3[leftMarkVar] = frontMarkerColour;
port5[leftMarkVar] = rearMarkerColour;
}
else{
leftMarkToggle = 1;
leftMarkVar--;
port3[leftMarkVar] = blackColour;
port5[runMarkVar] = blackColour;
if (leftMarkVar == -1){
leftMarkToggle = 0;
}
}
}
}
//Running lights are off, but right signal is on
else if (runActive == 0 && goRightSig == 1){
EVERY_N_MILLISECONDS(markFillSpeed){
if (rightMarkVar <= 21 && rightMarkToggle == 0){
rightMarkVar++;
port4[rightMarkVar] = frontMarkerColour;
port6[rightMarkVar] = rearMarkerColour;
}
else{
rightMarkToggle = 1;
rightMarkVar--;
port4[rightMarkVar] = blackColour;
port6[rightMarkVar] = blackColour;
if (rightMarkVar == -1){
rightMarkToggle = 0;
}
}
}
}
else if (runActive == 0 && goLeftSig == 0 && goRightSig == 0){
fill_solid(port3,23, blackColour);
fill_solid(port5,23, blackColour);
fill_solid(port4,23, blackColour);
fill_solid(port6,23, blackColour);
runMarkVar = -1;
leftMarkVar = -1;
rightMarkVar = -1;
leftMarkToggle = 0;
leftMarkToggle = 0;
}
if (goLeftSig == 0){
leftMarkToggle = 0;
}
if (goRightSig == 0){
rightMarkToggle = 0;
}
}
//END MARKER LIGHTS///////////////////////////////////////////////
//START show1Mode/////////////////////////////////////////////////
void doShow1(){
//LED:Front Grill Halo Lights
EVERY_N_MILLISECONDS(show1HaloSwell){
if (haloVar < haloMax && haloToggle == 0){
haloVar = haloVar+show1HaloStep;
analogWrite(spare3Relay, haloVar);
}
else{
haloToggle = 1;
haloVar = haloVar-show1HaloStep;
analogWrite(spare3Relay, haloVar);
if (haloVar < haloMin){
haloToggle = 0;
}
}
}
//LED:do same behaviour to tail lights as grille halos
EVERY_N_MILLISECONDS(show1TailSwell){
if (tailVar < tailMax && tailToggle == 0){
tailVar = tailVar+show1TailStep;
analogWrite(driveTailLed, tailVar);
analogWrite(passTailLed, tailVar);
}
else{
tailToggle = 1;
tailVar = tailVar-show1TailStep;
analogWrite(driveTailLed, tailVar);
analogWrite(passTailLed, tailVar);
if (tailVar < tailMin){
tailToggle = 0;
}
}
}
//Tail Lights RGB: Go around and around
EVERY_N_MILLISECONDS(tailFillSpeed){
if (rightTailVar < 100 && tailRightRGBtoggle == 0){
rightTailVar++;
port2[rightTailVar] = brakesColour;
}
else{
if (tailRightRGBtoggle == 0){
tailRightRGBtoggle = 1;
rightTailVar = 49;
}
if (rightTailVar < 100){
rightTailVar++;
port2[rightTailVar] = blackColour;
}
else{
tailRightRGBtoggle = 0;
rightTailVar = 49;
}
}
if (leftTailVar < 50 && tailLeftRGBtoggle == 0){
leftTailVar++;
port2[leftTailVar] = brakesColour;
}
else{
if (tailLeftRGBtoggle == 0){
tailLeftRGBtoggle = 1;
leftTailVar = -1;
}
if (leftTailVar < 50){
leftTailVar++;
port2[leftTailVar] = blackColour;
}
else{
tailLeftRGBtoggle = 0;
leftTailVar = -1;
}
}
if (random8() < chanceOfShowGlitter){
port2[ random16(100) ] += CRGB::White;
}
}
//Marker Lights RGB: Go around and around
EVERY_N_MILLISECONDS(markFillSpeed){
if (runMarkVar < 23 && runMarkFillToggle == 0){
runMarkVar++;
port3[runMarkVar] = frontMarkerColour;
port4[runMarkVar] = frontMarkerColour;
port5[runMarkVar] = rearMarkerColour;
port6[runMarkVar] = rearMarkerColour;
}
else{
if (runMarkFillToggle == 0){
runMarkFillToggle = 1;
runMarkVar = -1;
}
if (runMarkVar < 23){
runMarkVar++;
port3[runMarkVar] = blackColour;
port4[runMarkVar] = blackColour;
port5[runMarkVar] = blackColour;
port6[runMarkVar] = blackColour;
}
else{
runMarkFillToggle = 0;
runMarkVar = -1;
}
}
if (random8() < chanceOfShowGlitter){
port3[ random16(23) ] += CRGB::White;
port4[ random16(23) ] += CRGB::White;
port5[ random16(23) ] += CRGB::White;
port6[ random16(23) ] += CRGB::White;
}
}
}
//START show mode 2
void doShow2(){
// //USE THIS FOR NO RANDOMNESS
// // Flash the brakes for the specified number of times
// if (millis() - show2LastFlashTime < show2Flash * show2FlashFreq) {
// // Flash the brakes
// EVERY_N_MILLISECONDS(show2FlashFreq) {
// analogWrite(driveTailLed, tailBrakeBrightness);
// analogWrite(passTailLed, tailBrakeBrightness);
// analogWrite(spare3Relay, tailBrakeBrightness); // Add this line
// }
// EVERY_N_MILLISECONDS(show2FlashFreq * 2) {
// analogWrite(driveTailLed, 0);
// analogWrite(passTailLed, 0);
// analogWrite(spare3Relay, 0); // Add this line
// }
// }
// else {
// // Fading up and down
// if (millis() - show2LastFadeTime < show2FadeDuration * 2) {
// show2TailBrightness = map(millis() - show2LastFadeTime, 0, show2FadeDuration, 0, tailBrakeBrightness);
// analogWrite(driveTailLed, show2TailBrightness);
// analogWrite(passTailLed, show2TailBrightness);
// analogWrite(spare3Relay, show2TailBrightness); // Add this line
// }
// else {
// show2LastFlashTime = millis();
// show2LastFadeTime = millis();
// }
// }
//USE THIS FOR SOME RANDOMNESS
// Flash the brakes for the specified number of times
if (millis() - show2LastFlashTime < show2Flash * show2FlashFreq) {
// Flash the brakes with randomness
EVERY_N_MILLISECONDS(show2FlashFreq + random(-100, 100)) {
analogWrite(driveTailLed, tailBrakeBrightness);
analogWrite(passTailLed, tailBrakeBrightness);
analogWrite(spare3Relay, tailBrakeBrightness); // Add this line
}
EVERY_N_MILLISECONDS((show2FlashFreq + random(-100, 100)) * 2) {
analogWrite(driveTailLed, 0);
analogWrite(passTailLed, 0);
analogWrite(spare3Relay, 0); // Add this line
}
}
else {
// Fading up and down with randomness
if (millis() - show2LastFadeTime < show2FadeDuration * 2) {
show2TailBrightness = map(millis() - show2LastFadeTime, 0, show2FadeDuration, 0, tailBrakeBrightness);
show2TailBrightness += random(-20, 20); // Add some randomness
show2TailBrightness = constrain(show2TailBrightness, 0, 255); // Constrain brightness to valid range
analogWrite(driveTailLed, show2TailBrightness);
analogWrite(passTailLed, show2TailBrightness);
analogWrite(spare3Relay, show2TailBrightness); // Add this line
}
else {
show2LastFlashTime = millis();
show2LastFadeTime = millis();
}
}
}
//this is called after show modes to clear everything back to startup conditions
void clearAll(){
show1Step = 0;
show2Step = 0;
showTarget = 0;
brakeCount = 0;
rightTailVar = 49;
leftTailVar = -1;
runMarkVar = 0;
leftMarkVar = 0;
rightMarkVar = 0;
runMarkFillToggle = 0;
leftMarkToggle = 0;
leftMarkToggle = 0;
analogWrite(spare3Relay, 0);
analogWrite(spare3Relay, 0);
analogWrite(driveTailLed, 0);
analogWrite(passTailLed,0);
fill_solid(port1,NUM_LEDS_PER_STRIP_A, blackColour);
fill_solid(port2,NUM_LEDS_PER_STRIP_B, blackColour);
fill_solid(port3,NUM_LEDS_PER_STRIP_C, blackColour);
fill_solid(port4,NUM_LEDS_PER_STRIP_D, blackColour);
fill_solid(port5,NUM_LEDS_PER_STRIP_E, blackColour);
fill_solid(port6,NUM_LEDS_PER_STRIP_F, blackColour);
fill_solid(port7,NUM_LEDS_PER_STRIP_G, blackColour);
fill_solid(port8,NUM_LEDS_PER_STRIP_H, blackColour);
}
void drawTwinkles(CRGB leds[], int numLeds)
{
uint16_t PRNG16 = 11337;
uint32_t clock32 = millis();
CRGB bg;
if ((AUTO_SELECT_BACKGROUND_COLOR == 1) &&
(gCurrentPalette[0] == gCurrentPalette[1]))
{
bg = gCurrentPalette[0];
uint8_t bglight = bg.getAverageLight();
if (bglight > 64)
{
bg.nscale8_video(16);
}
else if (bglight > 16)
{
bg.nscale8_video(64);
}
else
{
bg.nscale8_video(86);
}
}
else
{
bg = gBackgroundColor;
}
uint8_t backgroundBrightness = bg.getAverageLight();
for (int i = 0; i < numLeds; ++i)
{
PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384;
uint16_t myclockoffset16 = PRNG16;
PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384;
uint8_t myspeedmultiplierQ5_3 = ((((PRNG16 & 0xFF) >> 4) + (PRNG16 & 0x0F)) & 0x0F) + 0x08;
uint32_t myclock30 = (uint32_t)((clock32 * myspeedmultiplierQ5_3) >> 3) + myclockoffset16;
uint8_t myunique8 = PRNG16 >> 8;
CRGB c = computeOneTwinkle(myclock30, myunique8);
uint8_t cbright = c.getAverageLight();
int16_t deltabright = cbright - backgroundBrightness;
if (deltabright >= 32 || (!bg))
{
leds[i] = c;
}
else if (deltabright > 0)
{
leds[i] = blend(bg, c, deltabright * 8);
}
else
{
leds[i] = bg;
}
}
}
// This function takes a time in pseudo-milliseconds,
// figures out brightness = f( time ), and also hue = f( time )
// The 'low digits' of the millisecond time are used as
// input to the brightness wave function.
// The 'high digits' are used to select a color, so that the color
// does not change over the course of the fade-in, fade-out
// of one cycle of the brightness wave function.
// The 'high digits' are also used to determine whether this pixel
// should light at all during this cycle, based on the TWINKLE_DENSITY.
CRGB computeOneTwinkle( uint32_t ms, uint8_t salt)
{
uint16_t ticks = ms >> (8-TWINKLE_SPEED);
uint8_t fastcycle8 = ticks;
uint16_t slowcycle16 = (ticks >> 8) + salt;
slowcycle16 += sin8( slowcycle16);
slowcycle16 = (slowcycle16 * 2053) + 1384;
uint8_t slowcycle8 = (slowcycle16 & 0xFF) + (slowcycle16 >> 8);
uint8_t bright = 0;
if( ((slowcycle8 & 0x0E)/2) < TWINKLE_DENSITY) {
bright = attackDecayWave8( fastcycle8);
}
uint8_t hue = slowcycle8 - salt;
CRGB c;
if( bright > 0) {
c = ColorFromPalette( gCurrentPalette, hue, bright, NOBLEND);
if( COOL_LIKE_INCANDESCENT == 1 ) {
coolLikeIncandescent( c, fastcycle8);
}
} else {
c = CRGB::Black;
}
return c;
}
// This function is like 'triwave8', which produces a
// symmetrical up-and-down triangle sawtooth waveform, except that this
// function produces a triangle wave with a faster attack and a slower decay:
//
// / \
// / \
// / \
// / \
//
uint8_t attackDecayWave8( uint8_t i)
{
if( i < 86) {
return i * 3;
} else {
i -= 86;
return 255 - (i + (i/2));
}
}
// This function takes a pixel, and if its in the 'fading down'
// part of the cycle, it adjusts the color a little bit like the
// way that incandescent bulbs fade toward 'red' as they dim.
void coolLikeIncandescent( CRGB& c, uint8_t phase)
{
if( phase < 128) return;
uint8_t cooling = (phase - 128) >> 4;
c.g = qsub8( c.g, cooling);
c.b = qsub8( c.b, cooling * 2);
}
// A mostly red palette with green accents and white trim.
// "CRGB::Gray" is used as white to keep the brightness more uniform.
const TProgmemRGBPalette16 RedGreenWhite_p FL_PROGMEM =
{ CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red,
CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red,
CRGB::Red, CRGB::Red, CRGB::Gray, CRGB::Gray,
CRGB::Green, CRGB::Green, CRGB::Green, CRGB::Green };
// A mostly (dark) green palette with red berries.
#define Holly_Green 0x00580c
#define Holly_Red 0xB00402
const TProgmemRGBPalette16 Holly_p FL_PROGMEM =
{ Holly_Green, Holly_Green, Holly_Green, Holly_Green,
Holly_Green, Holly_Green, Holly_Green, Holly_Green,
Holly_Green, Holly_Green, Holly_Green, Holly_Green,
Holly_Green, Holly_Green, Holly_Green, Holly_Red
};
// A red and white striped palette
// "CRGB::Gray" is used as white to keep the brightness more uniform.
const TProgmemRGBPalette16 RedWhite_p FL_PROGMEM =
{ CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red,
CRGB::Gray, CRGB::Gray, CRGB::Gray, CRGB::Gray,
CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red,
CRGB::Gray, CRGB::Gray, CRGB::Gray, CRGB::Gray };
// A mostly blue palette with white accents.
// "CRGB::Gray" is used as white to keep the brightness more uniform.
const TProgmemRGBPalette16 BlueWhite_p FL_PROGMEM =
{ CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue,
CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue,
CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue,
CRGB::Blue, CRGB::Gray, CRGB::Gray, CRGB::Gray };
// A pure "fairy light" palette with some brightness variations
#define HALFFAIRY ((CRGB::FairyLight & 0xFEFEFE) / 2)
#define QUARTERFAIRY ((CRGB::FairyLight & 0xFCFCFC) / 4)
const TProgmemRGBPalette16 FairyLight_p FL_PROGMEM =
{ CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight,
HALFFAIRY, HALFFAIRY, CRGB::FairyLight, CRGB::FairyLight,
QUARTERFAIRY, QUARTERFAIRY, CRGB::FairyLight, CRGB::FairyLight,
CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight };
// A palette of soft snowflakes with the occasional bright one
const TProgmemRGBPalette16 Snow_p FL_PROGMEM =
{ 0x304048, 0x304048, 0x304048, 0x304048,
0x304048, 0x304048, 0x304048, 0x304048,
0x304048, 0x304048, 0x304048, 0x304048,
0x304048, 0x304048, 0x304048, 0xE0F0FF };
// A palette reminiscent of large 'old-school' C9-size tree lights
// in the five classic colors: red, orange, green, blue, and white.
#define C9_Red 0xB80400
#define C9_Orange 0x902C02
#define C9_Green 0x046002
#define C9_Blue 0x070758
#define C9_White 0x606820
const TProgmemRGBPalette16 RetroC9_p FL_PROGMEM =
{ C9_Red, C9_Orange, C9_Red, C9_Orange,
C9_Orange, C9_Red, C9_Orange, C9_Red,
C9_Green, C9_Green, C9_Green, C9_Green,
C9_Blue, C9_Blue, C9_Blue,
C9_White
};
// A cold, icy pale blue palette
#define Ice_Blue1 0x0C1040
#define Ice_Blue2 0x182080
#define Ice_Blue3 0x5080C0
const TProgmemRGBPalette16 Ice_p FL_PROGMEM =
{
Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1,
Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1,
Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1,
Ice_Blue2, Ice_Blue2, Ice_Blue2, Ice_Blue3
};
// Add or remove palette names from this list to control which color
// palettes are used, and in what order.
const TProgmemRGBPalette16* ActivePaletteList[] = {
&RetroC9_p,
&BlueWhite_p,
&RainbowColors_p,
&FairyLight_p,
&RedGreenWhite_p,
&PartyColors_p,
&RedWhite_p,
&Snow_p,
&Holly_p,
&Ice_p
};
// Advance to the next color palette in the list (above).
void chooseNextColorPalette( CRGBPalette16& pal)
{
const uint8_t numberOfPalettes = sizeof(ActivePaletteList) / sizeof(ActivePaletteList[0]);
static uint8_t whichPalette = -1;
whichPalette = addmod8( whichPalette, 1, numberOfPalettes);
pal = *(ActivePaletteList[whichPalette]);
}