#include <FastLED.h>
#define N 30
#define DATA_PIN A3
#define SET_PIN 2
#define SETTINGS_PIN 3
#define ON_PIN 4
CRGB leds[N];
int br = 255, brc = 10, brt = 10;
bool on = false;
int mode = 0, mode_count = 3;
// settings display
int right_set, left_set;
long int right_set_time, left_set_time;
bool display_left, display_right;
// rgb
int len = 30, del = 1000 / 30;
double curs = 0, sp = (double)len / 3.0 * (double)del / 1000.0;
// hue and temp
int chue = 0, chuec = 18;
int ctemp = 0, ctempc = 16, ctempdif = 10;
bool cupd = false;
void setup() {
pinMode(ON_PIN, INPUT_PULLUP);
pinMode(SET_PIN, INPUT_PULLUP);
pinMode(SETTINGS_PIN, INPUT_PULLUP);
FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, N);
for (int i = 0; i < N; i++)
leds[i] = CRGB(0, 0, 0);
FastLED.show();
}
int lerpf0(int b, double x)
{
if (x <= 0)
return 0;
if (x >= 1)
return b;
return (int)(b * x);
}
void display_settings()
{
if (display_left)
{
for (int i = 0; i < left_set; i++)
leds[i] = CRGB(0, br, lerpf0(br, 0.33));
leds[left_set] = CRGB(br, 0, 0);
leds[left_set + 1] = CRGB(0, 0, 0);
}
if (display_right)
{
for (int i = N - 1; i >= N - right_set; i--)
leds[i] = CRGB(0, br, lerpf0(br, 0.33));
leds[N - right_set - 1] = CRGB(br, 0, 0);
leds[N - right_set - 2] = CRGB(0, 0, 0);
}
}
double rgb(double i, int n, int c)
{
double shift = (double)(n * c) / 3;
double f = 3 * (i - shift) / n;
if (f < 0)
f += 3;
if (f < 1)
return f;
else if (f > 2)
return 0;
else
return 2 - f;
}
int rgbInt(double i, int n, int c)
{
return lerpf0(br, rgb(i, n, c));
}
void rgb_init()
{
curs = 0;
}
void rgb()
{
double s = curs;
for (int i = 0; i < N; i++)
{
s += 1;
if (s >= len)
s -= len;
leds[i] = CRGB(rgbInt(s, len, 0), rgbInt(s, len, 1), rgbInt(s, len, 2));
}
curs += sp;
if (curs >= len)
curs -= len;
display_settings();
FastLED.show();
delay(del);
}
void color_hue()
{
if (cupd)
{
for (int i = 0; i < N; i++)
leds[i] = CRGB(rgbInt(chue, chuec, 0), rgbInt(chue, chuec, 1), rgbInt(chue, chuec, 2));
display_settings();
FastLED.show();
cupd = false;
}
}
void color_temp()
{
if (cupd)
{
int r, g, b, a = ctemp - ctempc/2;
if (a <= 0)
{
r = br;
g = lerpf0(br, (255.0 + 1 * a * ctempdif) / 255.0);
b = lerpf0(br, (255.0 + 2.5 * a * ctempdif) / 255.0);
}
else
{
r = lerpf0(br, (255.0 - a * ctempdif) / 255.0);
g = r;
b = br;
}
for (int i = 0; i < N; i++)
leds[i] = CRGB(r, g, b);
display_settings();
FastLED.show();
cupd = false;
}
}
int brightness()
{
brt--;
if (brt < 0)
brt += brc;
br = (int)((brt + 1) * 255.0 / (brc + 1));
if (mode == 1 || mode == 2)
cupd = true;
return brt;
}
int hue()
{
chue = (chue + 1) % chuec;
if (mode != 1)
mode = 1;
cupd = true;
return -1;
}
int temp()
{
ctemp = (ctemp + 1) % ctempc;
if (mode != 2)
mode = 2;
cupd = true;
return ctemp;
}
void (*modes[])() = { rgb, color_hue, color_temp };
void (*modes_init[])() = { rgb_init, [](){ cupd = true; }, [](){ cupd = true; } };
int switch_mode()
{
mode = (mode + 1) % mode_count;
(*modes_init[mode])();
return -1;
}
int settings_mode = 0, settings_mode_count = 4;
int (*settings_modes[])() = { switch_mode, brightness, hue, temp };
long int on_time, set_time, settings_time;
void loop() {
// updating on button
if (millis() - on_time > 1000)
if (digitalRead(ON_PIN) == LOW)
{
on_time = millis();
on = !on;
if (on == false)
{
for (int i = 0; i < N; i++)
leds[i] = CRGB(0, 0, 0);
FastLED.show();
}
else
cupd = true;
}
if (!on)
return;
// updating other two buttons
if (millis() - set_time > 250)
if (digitalRead(SET_PIN) == LOW)
{
set_time = millis();
left_set_time = millis();
display_left = false;
// may actually fail at runtime
left_set = (*settings_modes[settings_mode])(); // sets cupd=true inside functions
display_left = left_set != -1;
}
if (millis() - settings_time > 500)
if (digitalRead(SETTINGS_PIN) == LOW)
{
settings_mode = (settings_mode + 1) % settings_mode_count;
right_set = settings_mode;
settings_time = millis();
right_set_time = millis();
display_right = true;
cupd = true; // to update settigs display in static modes
}
// checking if settings display time is out
if (millis() - left_set_time > 2000 && display_left)
{
display_left = false;
cupd = true;
}
if (millis() - right_set_time > 2000 && display_right)
{
display_right = false;
cupd = true;
}
(*modes[mode])();
}