-
-
Save anonymous/5128e70bc37dadba7d57267268ae5ede to your computer and use it in GitHub Desktop.
Stairlight
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <LiquidCrystal.h> | |
#include <IRremote.h> | |
#include <I2C.h> | |
#include <FAB_LED.h> | |
#include <avr/pgmspace.h> | |
#include <EEPROM.h> | |
#include <avr/wdt.h> //watchdog | |
#define RTC_ADDRESS 0x68 // I2C address of the RTC module | |
#define RTC_SECONDS 0x00 | |
#define RTC_MINS 0x01 | |
#define RTC_HOURS 0x02 | |
#define RTC_DAY 0x03 | |
#define RTC_DATE 0x04 | |
#define RTC_MONTH 0x05 | |
#define RTC_YEAR 0x06 | |
#define RTC_CONTROL 0x07 | |
#define numPixels 300 | |
#define maxWBrightness 100 //gamma off, white color | |
#define default_resolution 3 | |
#define anim_speed 20 //anim speed is the default offset at 60 fps | |
ws2812b<D, 7> ledstrip; | |
#define GREEN(x,i) x[i] | |
#define RED(x,i) x[i+1] | |
#define BLUE(x,i) x[i+2] | |
IRrecv irreceiver(10); | |
decode_results results; | |
LiquidCrystal lcd(13, 11, 5, 4, 12, 2); | |
byte upDownChar[8] = { | |
0b00100, | |
0b01110, | |
0b11011, | |
0b00000, | |
0b00000, | |
0b11011, | |
0b01110, | |
0b00100 | |
}; | |
byte leftChar[8] = { | |
0b00010, | |
0b00110, | |
0b01100, | |
0b11000, | |
0b11000, | |
0b01100, | |
0b00110, | |
0b00010 | |
}; | |
byte rightChar[8] = { | |
0b01000, | |
0b01100, | |
0b00110, | |
0b00011, | |
0b00011, | |
0b00110, | |
0b01100, | |
0b01000 | |
}; | |
byte upChar[8] = { | |
0b00100, | |
0b01110, | |
0b01110, | |
0b11011, | |
0b11011, | |
0b10001, | |
0b00000, | |
0b00000 | |
}; | |
byte downChar[8] = { | |
0b00000, | |
0b00000, | |
0b10001, | |
0b11011, | |
0b11011, | |
0b01110, | |
0b01110, | |
0b00100 | |
}; | |
extern const uint8_t gamma[], dim_curve[]; | |
unsigned long x = 0, frame; | |
int16_t fps = 0, cps = 0, L1max, L1min, L2max, L2min, L1switch, L1offset, L2switch, L2offset, hue; | |
int16_t report, position, kelvin, maxKelvin, minKelvin; | |
uint16_t menu, clockSeconds, slideshow, current_time, evening_time, morning_time; | |
byte light = 50, Bmax = 100, Bmin = 20, mode, repeat, lcd_brightness = 20, lcd_maxBrightness; | |
byte resolution = default_resolution, maxGBrightness; | |
byte colorSample[6] = {}, rtc[13] = {}, evening[4] = {}, morning[4] = {}; | |
int8_t timeout, default_timeout = 30; | |
boolean button, auto_light, auto_dim, standby_light, white, show, gamma_correction, flashing; | |
boolean lcd_update, lcd_light, trigger1, trigger2, PIR1, PIR2, RTC = true, inMenu = false, night_mode; | |
volatile bool second = false; | |
byte buffer1[numPixels * 3] = {}; | |
void rtcSignal() | |
{ | |
second = true; | |
} | |
void initRTC(bool power) | |
{ | |
byte temp = 255; | |
I2c.read(RTC_ADDRESS, RTC_SECONDS, 1); | |
if (power == true) temp = I2c.receive() & 0b01111111; //power on | |
else temp = I2c.receive() | 0b10000000; //power off | |
I2c.write(RTC_ADDRESS, RTC_SECONDS, temp); | |
I2c.read(RTC_ADDRESS, RTC_HOURS, 1); | |
temp = I2c.receive() & 0b00111111; | |
I2c.write(RTC_ADDRESS, RTC_HOURS, temp); //set 24 hour format | |
I2c.write(RTC_ADDRESS, RTC_CONTROL, 0b00010000); //1 hz interrupts | |
} | |
/*byte decToBcd(byte val) { | |
return ((val / 10 * 16) + (val % 10)); | |
}*/ | |
byte bcdToDec(byte val1, byte val2) { | |
val1 = val1 << 4 | val2; | |
return ((val1 / 16 * 10) + (val1 % 16)); | |
} | |
void setRTC() | |
{ | |
byte rawData[7] = {}; | |
for (byte i = 0, n = 0; i < 7; i++) { | |
if (i == 3) rawData[i++] = rtc[n++]; | |
else { | |
rawData[i] = rtc[n++] | (rtc[n++] << 4); | |
} | |
} | |
I2c.write(RTC_ADDRESS, RTC_SECONDS, rawData, 7); | |
} | |
void readRTC() | |
{ | |
byte rawData[7] = {}; | |
I2c.read(RTC_ADDRESS, RTC_SECONDS, 7, rawData); | |
for (byte i = 0, n = 0; i < 7; i++) { | |
if (i == 3) rtc[n++] = rawData[i++]; | |
else { | |
rtc[n++] = rawData[i] & 0b00001111; | |
rtc[n++] = rawData[i] >> 4; | |
} | |
} | |
} | |
void larsonScanner(unsigned long offset, uint16_t firstLed, uint16_t pixels, uint16_t resolution, byte r, byte g, byte b) { | |
byte temp; | |
offset /= 5; | |
pixels--; | |
if (offset > (pixels * 2)) offset %= (pixels * 2); | |
if (offset > pixels) offset = pixels * 2 - offset; | |
pixels++; | |
int T_high = offset + resolution, T_low = offset - resolution; | |
for (int i = firstLed, n; i < pixels; i++) { | |
n = i * 3; | |
if (i < T_low) temp = 0; | |
if (i > T_high) temp = 0; | |
if (i == T_low || i == T_high) temp = 65; | |
if (i == (T_low + 1) || i == (T_high - 1)) temp = 160; | |
if (i > (T_low + 1) && i < (T_high - 1)) temp = 255; | |
RED(buffer1, n) = r * temp / 255; | |
GREEN(buffer1, n) = g * temp / 255; | |
BLUE(buffer1, n) = b * temp / 255; | |
} | |
} | |
void lightWipe(boolean state, bool direction, int pos, byte r, byte g, byte b) { | |
byte temp; | |
if (state && direction) { | |
for (int i = 0, n; i < numPixels; i++) { | |
n = i * 3; | |
if (i < pos) temp = 255; | |
if (i == pos) temp = 223; | |
if (i == pos + 1) temp = 191; | |
if (i == pos + 2) temp = 159; | |
if (i == pos + 3) temp = 127; | |
if (i == pos + 4) temp = 95; | |
if (i == pos + 5) temp = 63; | |
if (i == pos + 6) temp = 31; | |
if (i > pos + 6) temp = 0; | |
RED(buffer1, n) = r * temp / 255; | |
GREEN(buffer1, n) = g * temp / 255; | |
BLUE(buffer1, n) = b * temp / 255; | |
} | |
} | |
if (!state && direction) { | |
for (int i = 0, n; i < numPixels; i++) { | |
n = i * 3; | |
if (i < pos) temp = 0; | |
if (i == pos) temp = 31; | |
if (i == pos + 1) temp = 63; | |
if (i == pos + 2) temp = 95; | |
if (i == pos + 3) temp = 127; | |
if (i == pos + 4) temp = 159; | |
if (i == pos + 5) temp = 191; | |
if (i == pos + 6) temp = 223; | |
if (i > pos + 6) temp = 255; | |
RED(buffer1, n) = r * temp / 255; | |
GREEN(buffer1, n) = g * temp / 255; | |
BLUE(buffer1, n) = b * temp / 255; | |
} | |
} | |
if (state && !direction) { | |
for (int i = numPixels - 1, n; i >= 0; i--) { | |
n = i * 3; | |
if (i < pos) temp = 0; | |
if (i == pos) temp = 31; | |
if (i == pos + 1) temp = 63; | |
if (i == pos + 2) temp = 95; | |
if (i == pos + 3) temp = 127; | |
if (i == pos + 4) temp = 159; | |
if (i == pos + 5) temp = 191; | |
if (i == pos + 6) temp = 223; | |
if (i > pos + 6) temp = 255; | |
RED(buffer1, n) = r * temp / 255; | |
GREEN(buffer1, n) = g * temp / 255; | |
BLUE(buffer1, n) = b * temp / 255; | |
} | |
} | |
if (!state && !direction) { | |
for (int i = numPixels - 1, n; i >= 0; i--) { | |
n = i * 3; | |
if (i < pos) temp = 255; | |
if (i == pos) temp = 223; | |
if (i == pos + 1) temp = 191; | |
if (i == pos + 2) temp = 159; | |
if (i == pos + 3) temp = 127; | |
if (i == pos + 4) temp = 95; | |
if (i == pos + 5) temp = 63; | |
if (i == pos + 6) temp = 31; | |
if (i > pos + 6) temp = 0; | |
RED(buffer1, n) = r * temp / 255; | |
GREEN(buffer1, n) = g * temp / 255; | |
BLUE(buffer1, n) = b * temp / 255; | |
} | |
} | |
} | |
void getRGB(int hue, int sat, int val) { | |
/* convert hue, saturation and brightness ( HSB/HSV ) to RGB | |
The dim_curve is used only on brightness/value and on saturation (inverted). | |
This looks the most natural. | |
*/ | |
val = pgm_read_byte(&dim_curve[val]); | |
if (! white) val *= 1.33; | |
if (gamma_correction) val = pgm_read_byte(&gamma[val]); | |
sat = 255 - pgm_read_byte(&dim_curve[255 - sat]); | |
int r; | |
int g; | |
int b; | |
int base; | |
if (sat == 0) { // Acromatic color (gray). Hue doesn't mind. | |
colorSample[0] = val; | |
colorSample[1] = val; | |
colorSample[2] = val; | |
} | |
else { | |
base = ((255 - sat) * val) >> 8; | |
switch (hue / 60) { | |
case 0: | |
r = val; | |
g = (((val - base) * hue) / 60) + base; | |
b = base; | |
break; | |
case 1: | |
r = (((val - base) * (60 - (hue % 60))) / 60) + base; | |
g = val; | |
b = base; | |
break; | |
case 2: | |
r = base; | |
g = val; | |
b = (((val - base) * (hue % 60)) / 60) + base; | |
break; | |
case 3: | |
r = base; | |
g = (((val - base) * (60 - (hue % 60))) / 60) + base; | |
b = val; | |
break; | |
case 4: | |
r = (((val - base) * (hue % 60)) / 60) + base; | |
g = base; | |
b = val; | |
break; | |
case 5: | |
r = val; | |
g = base; | |
b = (((val - base) * (60 - (hue % 60))) / 60) + base; | |
break; | |
} | |
RED(colorSample, 0) = r; | |
GREEN(colorSample, 0) = g; | |
BLUE(colorSample, 0) = b; | |
} | |
} | |
void lightAdjustment(byte light, bool gam) { | |
if (light != 255) { | |
if (gam) light = pgm_read_byte(&gamma[light]); | |
for (int i = 3; i < 6; i++) colorSample[i] = colorSample[i] * light / 255; | |
} | |
} | |
void getColorTemp(int colorTemp) { | |
/* Start with a temperature, in Kelvin, somewhere between 1000 and 40000. (Other values may work, | |
but I can't make any promises about the quality of the algorithm's estimates above 40000 K.) | |
Note also that the temperature and color variables need to be declared as floating-point. | |
colorTemp = desired temp / 100. | |
*/ | |
colorTemp /= 100; | |
if (colorTemp <= 66) RED(colorSample, 3) = 255; | |
else { | |
RED(colorSample, 3) = (float)329.698727446 * pow((colorTemp - 60), -0.1332047592); | |
RED(colorSample, 3) = constrain(RED(colorSample, 3), 0, 255); | |
} | |
if (colorTemp <= 66) GREEN(colorSample, 3) = (float)99.4708025861 * log(colorTemp) - 161.1195681661; | |
else GREEN(colorSample, 3) = (float)288.1221695283 * pow((colorTemp - 60), -0.0755148492); | |
GREEN(colorSample, 3) = constrain(GREEN(colorSample, 3), 0, 255); | |
if (colorTemp >= 66) BLUE(colorSample, 3) = 255; | |
else { | |
if (colorTemp <= 19) BLUE(colorSample, 3) = 0; | |
else BLUE(colorSample, 3) = (float)138.5177312231 * log(colorTemp - 10) - 305.0447927307; | |
BLUE(colorSample, 3) = constrain(BLUE(colorSample, 3), 0, 255); | |
} | |
} | |
void menuHandler(byte button) { | |
static byte temp; | |
if (inMenu) { | |
lcd_update = true; | |
switch (button) { | |
case 15: | |
switch (menu) { | |
case 51: | |
menu = 52; | |
break; | |
case 52: | |
L1switch = analogRead(A0); | |
break; | |
case 53: | |
menu = 54; | |
break; | |
case 54: | |
L2switch = analogRead(A1); | |
break; | |
case 56: | |
L1max = 0; | |
L1min = 1023; | |
L2max = 0; | |
L2min = 1023 ; | |
EEPROM.put(0, L1max); | |
EEPROM.put(2, L1min); | |
EEPROM.put(10, L2max); | |
EEPROM.put(12, L2min); | |
menu = 57; | |
break; | |
default: | |
goto select; | |
break; | |
} | |
break; | |
case 14: | |
if (menu >= 20 && menu < 30) menu = 11; | |
else if (menu < 20) { | |
menu = 1; | |
inMenu = false; | |
} | |
if (menu >= 40 && menu < 50) menu = 12; | |
if (menu == 60 || menu == 61) menu = 13; | |
if (menu >= 70 && menu < 80) menu = 14; | |
if (menu > 80 && menu <= 86) { | |
menu--; | |
break; | |
} | |
if (menu > 90 && menu <= 94) { | |
menu--; | |
break; | |
} | |
if (menu > 100 && menu <= 104) { | |
menu--; | |
break; | |
} | |
switch (menu) { | |
case 30: | |
menu = 20; | |
EEPROM.put(4, Bmax); | |
break; | |
case 31: | |
menu = 21; | |
EEPROM.put(5, Bmin); | |
break; | |
case 32: | |
menu = 22; | |
EEPROM.put(6, standby_light); | |
break; | |
case 33: | |
menu = 23; | |
EEPROM.put(7, default_timeout); | |
break; | |
case 34: | |
menu = 24; | |
EEPROM.put(8, white); | |
break; | |
case 35: | |
menu = 25; | |
EEPROM.put(9, gamma_correction); | |
break; | |
case 50: | |
EEPROM.put(33, auto_light); | |
menu = 40; | |
break; | |
case 51: | |
menu = 41; | |
break; | |
case 52: | |
menu = 41; | |
EEPROM.put(14, L1switch); | |
break; | |
case 53: | |
menu = 42; | |
break; | |
case 54: | |
menu = 42; | |
EEPROM.put(16, L2switch); | |
break; | |
case 55: | |
EEPROM.put(34, auto_dim); | |
menu = 43; | |
break; | |
case 56: | |
menu = 44; | |
break; | |
case 57: | |
menu = 44; | |
break; | |
case 64: | |
menu = 60; | |
EEPROM.put(18, lcd_light); | |
break; | |
case 63: | |
menu = 61; | |
EEPROM.put(19, lcd_maxBrightness); | |
break; | |
case 80: | |
setRTC(); | |
menu = 70; | |
break; | |
case 90: | |
EEPROM.put(20, evening); | |
menu = 71; | |
break; | |
case 100: | |
EEPROM.put(24, morning); | |
menu = 72; | |
break; | |
case 110: | |
EEPROM.put(28, night_mode); | |
menu = 26; | |
break; | |
case 111: | |
EEPROM.put(29, minKelvin); | |
menu = 27; | |
break; | |
case 112: | |
EEPROM.put(31, maxKelvin); | |
menu = 28; | |
break; | |
} | |
break; | |
case 16: | |
select: | |
if (menu >= 80 && menu < 86) menu++; | |
if (menu >= 90 && menu < 94) menu++; | |
if (menu >= 100 && menu < 104) menu++; | |
switch (menu) { | |
case 9: | |
menu = 10; | |
break; | |
case 10: | |
menu = 11; | |
break; | |
case 11: | |
menu = 20; | |
break; | |
case 12: | |
menu = 40; | |
break; | |
case 13: | |
menu = 60; | |
break; | |
case 14: | |
menu = 70; | |
break; | |
case 20: | |
menu = 30; | |
break; | |
case 21: | |
menu = 31; | |
break; | |
case 22: | |
menu = 32; | |
break; | |
case 23: | |
menu = 33; | |
break; | |
case 24: | |
menu = 34; | |
break; | |
case 25: | |
menu = 35; | |
break; | |
case 26: | |
menu = 110; | |
break; | |
case 27: | |
white = true; | |
menu = 111; | |
break; | |
case 28: | |
white = true; | |
menu = 112; | |
break; | |
case 40: | |
menu = 50; | |
break; | |
case 41: | |
menu = 51; | |
break; | |
case 42: | |
menu = 53; | |
break; | |
case 43: | |
menu = 55; | |
break; | |
case 44: | |
menu = 56; | |
break; | |
case 51: | |
menu = 52; | |
break; | |
case 53: | |
menu = 54; | |
break; | |
case 60: | |
menu = 64; | |
break; | |
case 61: | |
menu = 63; | |
break; | |
case 70: | |
menu = 80; | |
break; | |
case 71: | |
menu = 90; | |
break; | |
case 72: | |
menu = 100; | |
break; | |
} | |
break; | |
case 18: | |
if (menu > 10 && menu < 20) menu--; | |
if (menu >= 20 && menu <= 28) menu--; | |
if (menu >= 40 && menu <= 44) menu--; | |
if (menu == 33 && default_timeout < 120) default_timeout++; | |
if (menu == 52 && L1switch < L1max) L1switch++; | |
if (menu == 54 && L2switch < L2max) L2switch++; | |
if (menu == 60 || menu == 61) menu--; | |
if (menu == 63 && lcd_maxBrightness < 255) lcd_maxBrightness += 5; | |
if (menu >= 70 && menu <= 72) menu--; | |
if (menu == 111 && minKelvin < maxKelvin) { | |
minKelvin += 50; | |
kelvin = minKelvin; | |
} | |
if (menu == 112 && maxKelvin < 6500) { | |
maxKelvin += 50; | |
kelvin = maxKelvin; | |
} | |
switch (menu) { | |
case 10: | |
menu = 14; | |
break; | |
case 19: | |
menu = 28; | |
break; | |
case 39: | |
menu = 44; | |
break; | |
case 30: | |
light = ++Bmax; | |
if (! gamma_correction && Bmax > maxWBrightness) Bmax = maxWBrightness; | |
if (gamma_correction && Bmax > maxGBrightness) Bmax = maxGBrightness; | |
break; | |
case 31: | |
light = ++Bmin; | |
if (Bmin > Bmax) Bmin = Bmax; | |
break; | |
case 32: | |
standby_light = true; | |
break; | |
case 34: | |
white = true; | |
break; | |
case 35: | |
if (! gamma_correction) { | |
temp = Bmax; | |
while (pgm_read_byte(&gamma[temp]) <= Bmax) { | |
temp++; | |
} | |
Bmax = temp; | |
temp = Bmin; | |
while (pgm_read_byte(&gamma[temp]) <= Bmin) { | |
temp++; | |
} | |
Bmin = temp; | |
temp = light; | |
while (pgm_read_byte(&gamma[temp]) <= light) { | |
temp++; | |
} | |
light = temp; | |
} | |
gamma_correction = true; | |
break; | |
case 50: | |
auto_light = true; | |
break; | |
case 55: | |
auto_dim = true; | |
break; | |
case 59: | |
menu = 61; | |
break; | |
case 64: | |
lcd_light = true; | |
break; | |
case 69: | |
menu = 72; | |
break; | |
case 81: | |
if (rtc[5] < 2) rtc[5]++; | |
if (rtc[5] == 2 && rtc[4] > 3) rtc[4] = 3; | |
break; | |
case 82: | |
if (rtc[4] < 9) rtc[4]++; | |
if (rtc[5] == 2 && rtc[4] > 3) rtc[4] = 3; | |
break; | |
case 83: | |
if (rtc[3] < 5) rtc[3]++; | |
break; | |
case 84: | |
if (rtc[2] < 9) rtc[2]++; | |
break; | |
case 85: | |
if (rtc[1] < 5) rtc[1]++; | |
break; | |
case 86: | |
if (rtc[0] > 9) rtc[0]++; | |
break; | |
case 91: | |
if (evening[3] < 2) evening[3]++; | |
if (evening[3] == 2 && evening[2] > 3) evening[2] = 3; | |
break; | |
case 92: | |
if (evening[2] < 9) evening[2]++; | |
if (evening[3] == 2 && evening[2] > 3) evening[2] = 3; | |
break; | |
case 93: | |
if (evening[1] < 5) evening[1]++; | |
break; | |
case 94: | |
if (evening[0] < 9) evening[0]++; | |
break; | |
case 101: | |
if (morning[3] < 2) morning[3]++; | |
if (morning[3] == 2 && morning[2] > 3) morning[2] = 3; | |
break; | |
case 102: | |
if (morning[2] < 9) morning[2]++; | |
if (morning[3] == 2 && morning[2] > 3) morning[2] = 3; | |
break; | |
case 103: | |
if (morning[1] < 5) morning[1]++; | |
break; | |
case 104: | |
if (morning[0] < 9) morning[0]++; | |
break; | |
case 110: | |
night_mode = true; | |
break; | |
} | |
break; | |
case 12: | |
if (menu < 15) menu++; | |
if (menu >= 20 && menu <= 28) menu++; | |
if (menu >= 40 && menu <= 44) menu++; | |
if (menu == 30 && Bmax > Bmin) light = --Bmax; | |
if (menu == 33 && default_timeout > 10) default_timeout--; | |
if (menu == 52 && L1switch > L1min) L1switch--; | |
if (menu == 54 && L2switch > L2min) L2switch--; | |
if (menu == 60 || menu == 61) menu++; | |
if (menu == 63 && lcd_maxBrightness > 20) lcd_maxBrightness -= 5; | |
if (menu >= 70 && menu <= 72) menu++; | |
if (menu == 111 && minKelvin > 2000) { | |
minKelvin -= 50; | |
kelvin = minKelvin; | |
} | |
if (menu == 112 && maxKelvin > minKelvin) { | |
maxKelvin -= 50; | |
kelvin = maxKelvin; | |
} | |
switch (menu) { | |
case 15: | |
menu = 11; | |
break; | |
case 29: | |
menu = 20; | |
break; | |
case 45: | |
menu = 40; | |
break; | |
case 31: | |
light = --Bmin; | |
if (! gamma_correction && Bmin < 5) Bmin = 5; | |
if (gamma_correction && Bmin < 63) Bmin = 63; | |
break; | |
case 32: | |
standby_light = false; | |
break; | |
case 34: | |
white = false; | |
break; | |
case 35: | |
if (gamma_correction) { | |
Bmax = min(pgm_read_byte(&gamma[Bmax]), maxWBrightness); | |
Bmin = max(pgm_read_byte(&gamma[Bmin]), 5); | |
light = pgm_read_byte(&gamma[light]); | |
} | |
gamma_correction = false; | |
break; | |
case 50: | |
auto_light = false; | |
break; | |
case 55: | |
auto_dim = false; | |
break; | |
case 62: | |
menu = 60; | |
break; | |
case 64: | |
lcd_light = false; | |
break; | |
case 73: | |
menu = 70; | |
break; | |
case 81: | |
if (rtc[5] > 0) rtc[5]--; | |
break; | |
case 82: | |
if (rtc[4] > 0) rtc[4]--; | |
break; | |
case 83: | |
if (rtc[3] > 0) rtc[3]--; | |
break; | |
case 84: | |
if (rtc[2] > 0) rtc[2]--; | |
break; | |
case 85: | |
if (rtc[1] > 0) rtc[1]--; | |
break; | |
case 86: | |
if (rtc[0] > 0) rtc[0]--; | |
break; | |
case 91: | |
if (evening[3] > 0) evening[3]--; | |
break; | |
case 92: | |
if (evening[2] > 0) evening[2]--; | |
break; | |
case 93: | |
if (evening[1] > 0) evening[1]--; | |
break; | |
case 94: | |
if (evening[0] > 0) evening[0]--; | |
break; | |
case 101: | |
if (morning[3] > 0) morning[3]--; | |
break; | |
case 102: | |
if (morning[2] > 0) morning[2]--; | |
break; | |
case 103: | |
if (morning[1] > 0) morning[1]--; | |
break; | |
case 104: | |
if (morning[0] > 0) morning[0]--; | |
break; | |
case 110: | |
night_mode = false; | |
break; | |
} | |
break; | |
} | |
} | |
} | |
void byte2() { | |
lcd.setCursor(0, 1); | |
lcd.write(byte(2)); | |
lcd.setCursor(2, 1); | |
} | |
void byte4() { | |
lcd.setCursor(0, 1); | |
lcd.write(byte(4)); | |
lcd.setCursor(3, 1); | |
} | |
void print_night() { | |
lcd.print(F(" starts")); | |
lcd.setCursor(0, 1); | |
lcd.print(F("at: ")); | |
lcd.write(byte(0)); | |
lcd.write(byte(1)); | |
lcd.setCursor(7, 1); | |
} | |
void print_LED() { | |
lcd.print(F("LED")); | |
} | |
void lcd_menu(uint16_t page) { | |
byte temp; | |
if (page <= 80 || page == 90 || page == 100 || page >= 110) { | |
lcd.clear(); | |
lcd.setCursor(0, 0); | |
} | |
if (page > 0 && page <= 3) { | |
if (mode == 0) lcd.print(F("Standby...")); | |
else if (mode == 255) { | |
lcd.print(light); | |
lcd.setCursor(11, 0); | |
if (white) lcd.print(kelvin); | |
else lcd.print(hue); | |
} | |
else lcd.print(F("Active...")); | |
lcd.setCursor(0, 1); | |
} | |
if (page > 10 && page < 30) goto byte3; | |
if (page == 60 || page == 61) goto byte3; | |
if (page >= 70 && page <= 72) goto byte3; | |
if (page >= 40 && page < 50) { | |
byte3: | |
lcd.write(byte(3)); | |
lcd.setCursor(3, 0); | |
} | |
switch (page) { | |
case 0: //welcome | |
lcd.print(F("Stairlights v1.0")); | |
lcd.setCursor(0, 1); | |
lcd.print(F("by Istvan Kocsis")); | |
break; | |
case 1: | |
lcd.print(F("Press OK to menu")); | |
break; | |
case 2: | |
lcd.print(F("Press any to set")); | |
break; | |
case 3: | |
goto print_fps; | |
break; | |
case 4: | |
readRTC(); | |
lcd.print(F("Time:")); | |
lcd.setCursor(8, 0); | |
lcd.print(rtc[5]); | |
lcd.print(rtc[4]); | |
lcd.print(F(":")); | |
lcd.print(rtc[3]); | |
lcd.print(rtc[2]); | |
lcd.print(F(":")); | |
lcd.print(rtc[1]); | |
lcd.print(rtc[0]); | |
lcd.setCursor(0, 1); | |
print_fps: | |
lcd.print(F("FPS:")); | |
if (fps > 9) lcd.setCursor(5, 1); | |
else lcd.setCursor(6, 1); | |
lcd.print(fps); | |
lcd.setCursor(8, 1); | |
lcd.print(F("CPS:")); | |
lcd.print(cps); | |
break; | |
case 9: //inMenu | |
lcd.write(byte(2)); | |
lcd.setCursor(2, 0); | |
lcd.print(F("to scroll")); | |
lcd.setCursor(0, 1); | |
lcd.write(byte(0)); | |
lcd.print(F(" to go back")); | |
break; | |
case 10: //inMenu | |
lcd.write(byte(1)); | |
lcd.setCursor(2, 0); | |
lcd.print(F("or OK")); | |
lcd.setCursor(0, 1); | |
lcd.print(F("to select")); | |
break; | |
case 11: //LED settings | |
print_LED(); | |
goto case14; | |
break; | |
case 12: //Sensor settings | |
lcd.setCursor(2, 0); | |
lcd.print(F("Ambient light")); | |
lcd.setCursor(0, 1); | |
lcd.write(byte(4)); | |
lcd.print(F("sensor settings")); | |
break; | |
case 13: //LCD settings | |
lcd.print(F("Display")); | |
goto case14; | |
break; | |
case 14: //time settings | |
lcd.print(F("Date/Time")); | |
case14: | |
byte4(); | |
lcd.print(F("settings")); | |
break; | |
case 20: //LED submenu | |
print_LED(); | |
lcd.print(F(" max")); | |
goto case21; | |
break; | |
case 21: //LED submenu | |
print_LED(); | |
lcd.print(F(" min")); | |
case21: | |
byte4(); | |
lcd.print(F("brightness")); | |
break; | |
case 22: //LED submenu | |
print_LED(); | |
lcd.print(F(" standby")); | |
byte4(); | |
lcd.print(F("running light")); | |
break; | |
case 23: //LED submenu | |
print_LED(); | |
byte4(); | |
lcd.print(F("timeout")); | |
break; | |
case 24: //LED submenu | |
print_LED(); | |
lcd.print(F(" color")); | |
byte4(); | |
lcd.print(F("set")); | |
break; | |
case 25: //LED gamma | |
print_LED(); | |
lcd.print(F(" gamma")); | |
byte4(); | |
lcd.print(F("correction")); | |
break; | |
case 26: //LED night mode filter | |
goto case27; | |
break; | |
case 27: //LED night mode temp | |
case27: | |
lcd.print(F("Night mode")); | |
byte4(); | |
if (page == 27) goto case28; | |
else lcd.print(F("blue filter")); | |
break; | |
case 28: //LED day mode temp | |
lcd.print(F("Day mode")); | |
byte4(); | |
case28: | |
lcd.print(F("temperature")); | |
break; | |
case 30: //LED max brightness | |
lcd.print(F("Max brightness:")); | |
byte2(); | |
lcd.print(Bmax); | |
break; | |
case 31: //LED min brightness | |
lcd.print(F("Min brightness:")); | |
byte2(); | |
lcd.print(Bmin); | |
break; | |
case 32: //LED standby | |
lcd.print(F("Standby light:")); | |
byte2(); | |
if (standby_light) lcd.print(F("ON")); | |
else lcd.print(F("OFF")); | |
break; | |
case 33: //LED timeout | |
lcd.print(F("LED timeout:")); | |
byte2(); | |
lcd.print(default_timeout); | |
lcd.print(F(" sec")); | |
break; | |
case 34: //LED color | |
lcd.print(F("Default mode:")); | |
byte2(); | |
if (white) lcd.print(F("White")); | |
else lcd.print(F("Color")); | |
break; | |
case 35: //LED gamma | |
lcd.print(F("Correction:")); | |
byte2(); | |
if (gamma_correction) lcd.print(F("ON")); | |
else lcd.print(F("OFF")); | |
break; | |
case 40: //Sensor auto light | |
lcd.print(F("Ambient light")); | |
byte4(); | |
lcd.print(F("activating")); | |
break; | |
case 41: //Sensor adjust | |
lcd.print(F("Primary")); | |
goto case42; | |
break; | |
case 42: //Sensor adjust | |
lcd.setCursor(1, 0); | |
lcd.print(F("Secondary")); | |
case42: | |
lcd.print(F(" light")); | |
byte4(); | |
lcd.print(F("sensor")); | |
break; | |
case 43: | |
lcd.print(F("Auto dimming")); | |
byte4(); | |
lcd.print(F("in the dark")); | |
break; | |
case 44: //Sensor calibration | |
lcd.print(F("Light sensor")); | |
byte4(); | |
lcd.print(F("recalibration")); | |
break; | |
case 50: | |
lcd.print(F("Only in dark?")); | |
lcd.setCursor(0, 1); | |
lcd.write(byte(2)); | |
lcd.setCursor(2, 1); | |
if (auto_light) lcd.print(F("Auto ON")); | |
else lcd.print(F("Always ACTIVE")); | |
break; | |
case 51: | |
goto case53; | |
break; | |
case 52: | |
temp = map(L1switch, L1min, L1max, 0, 100); | |
lcd.print(F("Sensitivity:")); | |
lcd.setCursor(0, 1); | |
lcd.write(byte(2)); | |
if (L1switch > 999) lcd.setCursor(1, 1); | |
else if (L1switch > 99) lcd.setCursor(2, 1); | |
else if (L1switch > 9) lcd.setCursor(3, 1); | |
else lcd.setCursor(4, 1); | |
lcd.print(L1switch); | |
if (temp < 10 ) lcd.setCursor(7, 1); | |
else lcd.setCursor(6, 1); | |
lcd.print(temp); | |
lcd.print(F("% of max")); | |
break; | |
case 53: | |
case53: | |
lcd.print(F("OK: read sensor")); | |
lcd.setCursor(0, 1); | |
lcd.write(byte(2)); | |
lcd.setCursor(1, 1); | |
lcd.print(F(": to adjust")); | |
break; | |
case 54: | |
temp = map(L2switch, L2min, L2max, 0, 100); | |
lcd.print(F("Sensitivity:")); | |
lcd.setCursor(0, 1); | |
lcd.write(byte(2)); | |
if (L2switch > 999) lcd.setCursor(1, 1); | |
else if (L1switch > 99) lcd.setCursor(2, 1); | |
else if (L2switch > 9) lcd.setCursor(3, 1); | |
else lcd.setCursor(4, 1); | |
lcd.print(L2switch); | |
if (temp < 10 ) lcd.setCursor(7, 1); | |
else lcd.setCursor(6, 1); | |
lcd.print(temp); | |
lcd.print(F("% of max")); | |
break; | |
case 55: | |
lcd.write(byte(2)); | |
lcd.setCursor(2, 0); | |
lcd.print(F("Auto dimming")); | |
lcd.setCursor(0, 1); | |
if (auto_dim) lcd.print(F("ON: dim in dark")); | |
else lcd.print(F("OFF: full power")); | |
break; | |
case 56: | |
lcd.print(F("OK to reset")); | |
lcd.setCursor(0, 1); | |
lcd.print(F("stored values?")); | |
break; | |
case 57: | |
lcd.print(F("Calibration data")); | |
lcd.setCursor(0, 1); | |
lcd.print(F("cleared!")); | |
break; | |
case 60: | |
lcd.print(F("LCD backlight")); | |
byte4(); | |
lcd.print(F("mode")); | |
break; | |
case 61: | |
lcd.print(F("LCD")); | |
byte4(); | |
lcd.print(F("brightness")); | |
break; | |
case 63: | |
lcd.print(F("Brightness:")); | |
byte2(); | |
lcd.print(lcd_maxBrightness); | |
break; | |
case 64: | |
lcd.write(byte(2)); | |
lcd.setCursor(2, 0); | |
lcd.print(F("Auto dimming")); | |
lcd.setCursor(2, 1); | |
if (lcd_light) lcd.print(F("Always ON")); | |
else lcd.print(F("Auto OFF")); | |
break; | |
case 70: | |
lcd.print(F("Set time")); | |
lcd.setCursor(0, 1); | |
lcd.write(byte(4));; | |
break; | |
case 71: | |
lcd.print(F("Set start of")); | |
goto case72; | |
break; | |
case 72: | |
lcd.print(F("Set end of")); | |
case72: | |
byte4(); | |
lcd.print(F("night mode")); | |
break; | |
case 80: | |
lcd.print(F("Time:")); | |
lcd.setCursor(8, 0); | |
lcd.print(rtc[5]); | |
lcd.print(rtc[4]); | |
lcd.print(F(":")); | |
lcd.print(rtc[3]); | |
lcd.print(rtc[2]); | |
lcd.print(F(":")); | |
lcd.print(rtc[1]); | |
lcd.print(rtc[0]); | |
lcd.setCursor(0, 1); | |
lcd.write(byte(0)); | |
lcd.write(byte(1)); | |
break; | |
case 81: | |
lcd.setCursor(8, 0); | |
if (!flashing) lcd.print(F("_")); | |
else lcd.print(rtc[5]); | |
lcd.print(rtc[4]); | |
break; | |
case 82: | |
lcd.setCursor(8, 0); | |
lcd.print(rtc[5]); | |
if (!flashing) lcd.print(F("_")); | |
else lcd.print(rtc[4]); | |
lcd.print(F(":")); | |
lcd.print(rtc[3]); | |
break; | |
case 83: | |
lcd.setCursor(9, 0); | |
lcd.print(rtc[4]); | |
lcd.print(F(":")); | |
if (!flashing) lcd.print(F("_")); | |
else lcd.print(rtc[3]); | |
lcd.print(rtc[2]); | |
break; | |
case 84: | |
lcd.setCursor(11, 0); | |
lcd.print(rtc[3]); | |
if (!flashing) lcd.print(F("_")); | |
else lcd.print(rtc[2]); | |
lcd.print(F(":")); | |
lcd.print(rtc[1]); | |
break; | |
case 85: | |
lcd.setCursor(12, 0); | |
lcd.print(rtc[2]); | |
lcd.print(F(":")); | |
if (!flashing) lcd.print(F("_")); | |
else lcd.print(rtc[1]); | |
lcd.print(rtc[0]); | |
break; | |
case 86: | |
lcd.setCursor(14, 0); | |
lcd.print(rtc[1]); | |
if (!flashing) lcd.print(F("_")); | |
else lcd.print(rtc[0]); | |
break; | |
case 90: | |
lcd.print(F("Evening")); | |
print_night(); | |
lcd.print(evening[3]); | |
lcd.print(evening[2]); | |
lcd.print(F(":")); | |
lcd.print(evening[1]); | |
lcd.print(evening[0]); | |
break; | |
case 91: | |
lcd.setCursor(7, 1); | |
if (!flashing) lcd.print(F("_")); | |
else lcd.print(evening[3]); | |
lcd.print(evening[2]); | |
break; | |
case 92: | |
lcd.setCursor(7, 1); | |
lcd.print(evening[3]); | |
if (!flashing) lcd.print(F("_")); | |
else lcd.print(evening[2]); | |
lcd.print(F(":")); | |
lcd.print(evening[1]); | |
break; | |
case 93: | |
lcd.setCursor(8, 1); | |
lcd.print(evening[2]); | |
lcd.print(F(":")); | |
if (!flashing) lcd.print(F("_")); | |
else lcd.print(evening[1]); | |
lcd.print(evening[0]); | |
break; | |
case 94: | |
lcd.setCursor(10, 1); | |
lcd.print(evening[1]); | |
if (!flashing) lcd.print(F("_")); | |
else lcd.print(evening[0]); | |
break; | |
case 100: | |
lcd.print(F("Morning")); | |
print_night(); | |
lcd.print(morning[3]); | |
lcd.print(morning[2]); | |
lcd.print(F(":")); | |
lcd.print(morning[1]); | |
lcd.print(morning[0]); | |
break; | |
case 101: | |
lcd.setCursor(7, 1); | |
if (!flashing) lcd.print(F("_")); | |
else lcd.print(morning[3]); | |
lcd.print(morning[2]); | |
break; | |
case 102: | |
lcd.setCursor(7, 1); | |
lcd.print(morning[3]); | |
if (!flashing) lcd.print(F("_")); | |
else lcd.print(morning[2]); | |
lcd.print(F(":")); | |
lcd.print(morning[1]); | |
break; | |
case 103: | |
lcd.setCursor(8, 1); | |
lcd.print(morning[2]); | |
lcd.print(F(":")); | |
if (!flashing) lcd.print(F("_")); | |
else lcd.print(morning[1]); | |
lcd.print(morning[0]); | |
break; | |
case 104: | |
lcd.setCursor(10, 1); | |
lcd.print(morning[1]); | |
if (!flashing) lcd.print(F("_")); | |
else lcd.print(morning[0]); | |
break; | |
case 110: //LED temperature | |
lcd.print(F("Filter light")); | |
byte2(); | |
if (night_mode) lcd.print(F("ON")); | |
else lcd.print(F("OFF")); | |
break; | |
case 111: | |
goto case112; | |
break; | |
case 112: | |
case112: | |
lcd.print(F("Temperature:")); | |
byte2(); | |
if (page == 112) lcd.print(maxKelvin); | |
else lcd.print(minKelvin); //case 111 | |
lcd.print(F(" Kelvin")); | |
break; | |
} | |
} | |
ISR(WDT_vect, ISR_NAKED) | |
{ | |
register uint8_t *upStack; | |
upStack = (uint8_t *)SP + 1; | |
report = (*upStack << 8) | *(++upStack); | |
eeprom_write_word((uint16_t *)500, report); | |
} | |
void setup() { | |
//watchdog config | |
byte resetflag = MCUSR; // save flags for debug | |
MCUSR = 0; // reset various flags | |
WDTCSR |= 0b00011000; // see docs, set WDCE, WDE | |
WDTCSR = 0b01101001; // set WDIE, WDE, and appropriate delay | |
wdt_reset(); | |
//LCD | |
lcd.createChar(0, leftChar); | |
lcd.createChar(1, rightChar); | |
lcd.createChar(2, upDownChar); | |
lcd.createChar(3, upChar); | |
lcd.createChar(4, downChar); | |
pinMode(6, OUTPUT); | |
analogWrite(6, lcd_brightness); | |
lcd.begin(16, 2); | |
lcd_menu(0); | |
//IR receiver | |
irreceiver.enableIRIn(); // Start the receiver | |
//pinMode(8, INPUT); | |
pinMode(13, OUTPUT); | |
if (resetflag & 0b00001000) digitalWrite(13, HIGH); | |
else digitalWrite(13, LOW); | |
ledstrip.clear(1000); | |
Serial.begin(9600); | |
I2c.begin(); | |
I2c.setSpeed(true); | |
I2c.pullup(true); | |
I2c.timeOut(1000); | |
//I2C RTC | |
pinMode(3, INPUT_PULLUP); | |
attachInterrupt(digitalPinToInterrupt(3), rtcSignal, FALLING); | |
initRTC(true); | |
float temp1 = analogRead(A7) / 204.6; //map to 0..5V | |
Serial.print(F("Battery: ")); | |
Serial.print(temp1); | |
Serial.println(F("V")); | |
readRTC(); | |
//watchdog report | |
EEPROM.get(500, report); | |
Serial.print(F("Froze at: 0x")); | |
Serial.println(report * 2, HEX); | |
if (resetflag != 0) Serial.print(F("Reset: ")); | |
switch (resetflag) { | |
case 1: | |
Serial.println(F("Power-on")); | |
break; | |
case 2: | |
Serial.println(F("External")); | |
break; | |
case 4: | |
Serial.println(F("Brown-out")); | |
break; | |
case 8: | |
Serial.println(F("Watchdog")); | |
break; | |
} | |
//calculate maxGBrightness | |
maxGBrightness = maxWBrightness; | |
while (pgm_read_byte(&gamma[maxGBrightness]) <= maxWBrightness) { | |
maxGBrightness++; | |
} | |
//Stored sensor calibration data | |
EEPROM.get(0, L1max); | |
EEPROM.get(2, L1min); | |
EEPROM.get(10, L2max); | |
EEPROM.get(12, L2min); | |
Serial.print(F("Sensor data: ")); | |
Serial.print(L1max); | |
Serial.print(F(", ")); | |
Serial.println(L1min); | |
Serial.print(L2max); | |
Serial.print(F(", ")); | |
Serial.println(L2min); | |
//load data from eeprom | |
EEPROM.get(4, Bmax); | |
EEPROM.get(5, Bmin); | |
EEPROM.get(6, standby_light); | |
EEPROM.get(7, default_timeout); | |
EEPROM.get(8, white); | |
EEPROM.get(9, gamma_correction); | |
EEPROM.get(14, L1switch); | |
EEPROM.get(16, L2switch); | |
EEPROM.get(18, lcd_light); | |
EEPROM.get(19, lcd_maxBrightness); | |
EEPROM.get(20, evening); | |
EEPROM.get(24, morning); | |
EEPROM.get(28, night_mode); | |
EEPROM.get(29, minKelvin); | |
EEPROM.get(31, maxKelvin); | |
EEPROM.get(33, auto_light); | |
EEPROM.get(34, auto_dim); | |
} | |
void loop() { | |
wdt_reset(); //reset wathdog timer | |
frame = micros(); | |
//PIR trigger | |
if (digitalRead(8) == HIGH && !PIR1) { | |
PIR1 = true; | |
trigger1 = true; | |
//Serial.println("PIR 1"); | |
} | |
else if (digitalRead(8) == LOW) PIR1 = false; | |
if (digitalRead(9) == HIGH && !PIR2) { | |
PIR2 = true; | |
trigger2 = true; | |
//Serial.println("PIR 2"); | |
} | |
else if (digitalRead(9) == LOW) PIR2 = false; | |
//Infra remote | |
if (irreceiver.decode(&results)) { | |
//Serial.println(results.value, HEX); | |
irreceiver.resume(); | |
switch (results.value) { | |
case 0xFDA857: //OK | |
//Serial.println(F("OK")); | |
mode = 255; | |
repeat = 0; | |
if (! inMenu) { | |
inMenu = true; | |
menu = 9; | |
} | |
else menuHandler(15); | |
break; | |
case 0xFD8877: //UP | |
//Serial.println(F("Up")); | |
mode = 255; | |
repeat = 8; | |
show = true; | |
timeout = default_timeout; | |
goto up; | |
break; | |
case 0xFD9867: //DOWN | |
//Serial.println(F("Down")); | |
mode = 255; | |
repeat = 2; | |
show = true; | |
timeout = default_timeout; | |
goto down; | |
break; | |
case 0xFD28D7: //Left | |
//Serial.println(F("Left")); | |
mode = 255; | |
if (! inMenu) repeat = 4; | |
else repeat = 0; | |
show = true; | |
timeout = default_timeout; | |
goto left; | |
break; | |
case 0xFD6897: //Right | |
//Serial.println(F("Right")); | |
mode = 255; | |
if (! inMenu) repeat = 6; | |
else repeat = 0; | |
show = true; | |
timeout = default_timeout; | |
goto right; | |
break; | |
/*case 0xFD30CF: //Star | |
Serial.println(F("Star")); | |
RTC = !RTC; | |
initRTC(RTC); | |
repeat = 0; | |
timeout = default_timeout; | |
menuHandler(17); | |
break;*/ | |
case 0xFD708F: //Cross | |
//Serial.println(F("Cross")); | |
white = !white; | |
mode = 255; | |
repeat = 0; | |
show = true; | |
timeout = default_timeout; | |
menuHandler(19); | |
break; | |
/*case 0xFD00FF: // 1 | |
Serial.println(F("1")); | |
repeat = 0; | |
menuHandler(1); | |
break; | |
case 0xFD807F: // 2 | |
Serial.println(F("2")); | |
repeat = 0; | |
menuHandler(2); | |
break; | |
case 0xFD40BF: // 3 | |
Serial.println(F("3")); | |
repeat = 0; | |
menuHandler(3); | |
break; | |
case 0xFD20DF: // 4 | |
Serial.println(F("4")); | |
repeat = 0; | |
menuHandler(4); | |
break; | |
case 0xFDA05F: // 5 | |
Serial.println(F("5")); | |
repeat = 0; | |
menuHandler(5); | |
break; | |
case 0xFD609F: // 6 | |
Serial.println(F("6")); | |
repeat = 0; | |
menuHandler(6); | |
break; | |
case 0xFD10EF: // 7 | |
Serial.println(F("7")); | |
repeat = 0; | |
menuHandler(7); | |
break; | |
case 0xFD906F: // 8 | |
Serial.println(F("8")); | |
repeat = 0; | |
menuHandler(8); | |
break; | |
case 0xFD50AF: // 9 | |
Serial.println(F("9")); | |
repeat = 0; | |
menuHandler(9); | |
break; | |
case 0xFDB04F: // 0 | |
Serial.println(F("0")); | |
repeat = 0; | |
menuHandler(10); | |
break;*/ | |
default: | |
mode = 255; | |
show = true; | |
timeout = default_timeout; | |
break; | |
} | |
if (results.value == 0xFFFFFFFF) { | |
switch (repeat) { | |
case 8: //Up | |
up: | |
if (! inMenu) { | |
lcd_update = true; | |
if (light < Bmax) light += 5; | |
else light = Bmax; | |
//Serial.println(light); | |
} | |
else menuHandler(18); | |
break; | |
case 2: //Down | |
down: | |
if (! inMenu) { | |
if (light > Bmin) light -= 5; | |
else light = Bmin; | |
lcd_update = true; | |
//Serial.println(light); | |
} | |
else menuHandler(12); | |
break; | |
case 4: //Left | |
left: | |
if (! inMenu) { | |
lcd_update = true; | |
if (white) { | |
if (kelvin > 2000) kelvin -= 50; | |
else kelvin = 2000; | |
//Serial.println(kelvin); | |
} | |
else { | |
if (hue >= 2) hue -= 2; | |
else hue = 359; | |
//Serial.println(hue); | |
} | |
} | |
else menuHandler(14); | |
break; | |
case 6: //Right | |
right: | |
if (! inMenu) { | |
lcd_update = true; | |
if (white) { | |
if (kelvin < 6500) kelvin += 50; | |
else kelvin = 6500; | |
//Serial.println(kelvin); | |
} | |
else { | |
if (hue <= 357) hue += 2; | |
else hue = 0; | |
//Serial.println(hue); | |
} | |
} | |
else menuHandler(16); | |
break; | |
} | |
} | |
} | |
//light sensor | |
if (analogRead(A0) > L1max) { | |
L1max = analogRead(A0); | |
EEPROM.put(0, L1max); | |
} | |
if (analogRead(A0) < L1min) { | |
L1min = analogRead(A0); | |
EEPROM.put(2, L1min); | |
} | |
if (analogRead(A1) > L2max) { | |
L2max = analogRead(A1); | |
EEPROM.put(10, L2max); | |
} | |
if (analogRead(A1) < L2min) { | |
L2min = analogRead(A1); | |
EEPROM.put(12, L2min); | |
} | |
if (mode == 0) { | |
int temp1, temp2; | |
temp1 = analogRead(A0); | |
temp2 = analogRead(A1); | |
static int hys1 = temp1, hys2 = temp2; | |
if (temp1 > hys1 + 5 || temp1 < hys1 - 5) hys1 = temp1; | |
if (temp2 > hys2 + 5 || temp2 < hys2 - 5) hys2 = temp2; | |
if (auto_light) { | |
if (hys1 <= L1switch || hys2 <= L2switch) { | |
if (auto_dim) goto dimming; | |
else light = Bmax; | |
} | |
else light = 0; | |
} | |
else if (auto_dim) { | |
dimming: | |
light = min(max(map(hys1, L1min, L1switch, Bmin, Bmax), map(hys2, L2min, L2switch, Bmin, Bmax)), Bmax); | |
} | |
else light = Bmax; | |
} | |
//event manager | |
if (trigger1 && mode == 0) { | |
mode = 1; | |
timeout = default_timeout; | |
position = -6; | |
trigger1 = false; | |
} | |
if (trigger2 && mode == 1) { | |
mode = 12; | |
position = -6; | |
trigger2 = false; | |
} | |
if (trigger2 && mode == 0) { | |
mode = 2; | |
timeout = default_timeout; | |
position = numPixels; | |
trigger2 = false; | |
} | |
if (trigger1 && mode == 2) { | |
mode = 21; | |
position = numPixels; | |
trigger1 = false; | |
} | |
if (timeout < 1 && mode == 1) { | |
mode = 21; | |
position = numPixels; | |
} | |
if (timeout < 1 && mode == 2) { | |
mode = 12; | |
position = -6; | |
} | |
if (timeout < 1 && mode == 255) { | |
mode = 12; | |
position = -6; | |
} | |
switch (mode) { | |
case 0: //standby | |
if (standby_light) { | |
if (white) { | |
getColorTemp(kelvin); | |
lightAdjustment(min(3, light), false); | |
larsonScanner(x, 0, numPixels, resolution, RED(colorSample, 3), GREEN(colorSample, 3), BLUE(colorSample, 3)); | |
} | |
else { | |
getRGB(hue, 255, min(3, light)); | |
larsonScanner(x, 0, numPixels, resolution, RED(colorSample, 0), GREEN(colorSample, 0), BLUE(colorSample, 0)); | |
} | |
show = true; | |
} | |
break; | |
case 1: | |
if (white) { | |
getColorTemp(kelvin); | |
lightAdjustment(light, gamma_correction); | |
lightWipe(true, true, position, RED(colorSample, 3), GREEN(colorSample, 3), BLUE(colorSample, 3)); | |
} | |
else { | |
getRGB(hue, 255, light); | |
lightWipe(true, true, position, RED(colorSample, 0), GREEN(colorSample, 0), BLUE(colorSample, 0)); | |
} | |
if (position < numPixels) { | |
position += 4; | |
show = true; | |
} | |
break; | |
case 12: | |
if (white) { | |
getColorTemp(kelvin); | |
lightAdjustment(light, gamma_correction); | |
lightWipe(false, true, position, RED(colorSample, 3), GREEN(colorSample, 3), BLUE(colorSample, 3)); | |
} | |
else { | |
getRGB(hue, 255, light); | |
lightWipe(false, true, position, RED(colorSample, 0), GREEN(colorSample, 0), BLUE(colorSample, 0)); | |
} | |
if (position < numPixels) { | |
position += 2; | |
show = true; | |
} | |
else mode = 0; | |
break; | |
case 2: | |
if (white) { | |
getColorTemp(kelvin); | |
lightAdjustment(light, gamma_correction); | |
lightWipe(true, false, position, RED(colorSample, 3), GREEN(colorSample, 3), BLUE(colorSample, 3)); | |
} | |
else { | |
getRGB(hue, 255, light); | |
lightWipe(true, false, position, RED(colorSample, 0), GREEN(colorSample, 0), BLUE(colorSample, 0)); | |
} | |
if (position > -6) { | |
position -= 4; | |
show = true; | |
} | |
break; | |
case 21: | |
if (white) { | |
getColorTemp(kelvin); | |
lightAdjustment(light, gamma_correction); | |
lightWipe(false, false, position, RED(colorSample, 3), GREEN(colorSample, 3), BLUE(colorSample, 3)); | |
} | |
else { | |
getRGB(hue, 255, light); | |
lightWipe(false, false, position, RED(colorSample, 0), GREEN(colorSample, 0), BLUE(colorSample, 0)); | |
} | |
if (position > -6) { | |
position -= 2; | |
show = true; | |
} | |
else mode = 0; | |
break; | |
case 255: | |
if (white) { | |
getColorTemp(kelvin); | |
lightAdjustment(light, gamma_correction); | |
lightWipe(true, true, numPixels, RED(colorSample, 3), GREEN(colorSample, 3), BLUE(colorSample, 3)); | |
} | |
else { | |
getRGB(hue, 255, light); | |
lightWipe(true, true, numPixels, RED(colorSample, 0), GREEN(colorSample, 0), BLUE(colorSample, 0)); | |
} | |
break; | |
} | |
//LED update | |
if (show) { | |
ledstrip.sendPixels(numPixels, buffer1); | |
show = false; | |
fps++; | |
} | |
//LCD | |
if (lcd_update || second) { | |
if (! inMenu && (clockSeconds > slideshow + 5)) { | |
menu++; | |
if (menu > 4) menu = 1; | |
slideshow = clockSeconds; | |
} | |
if (inMenu && timeout == 0) { | |
menu = 1; | |
inMenu = false; | |
//Serial.print("Shit"); | |
} | |
lcd_menu(menu); | |
lcd_update = false; | |
} | |
if (mode == 0 && lcd_brightness > 0 && !lcd_light) analogWrite(6, --lcd_brightness); | |
if (mode == 255) { | |
if (lcd_brightness < lcd_maxBrightness) analogWrite(6, ++lcd_brightness); | |
else if (lcd_brightness != lcd_maxBrightness) analogWrite(6, --lcd_brightness); | |
} | |
frame = (micros() - frame); | |
x += round(anim_speed * float(60.0 / (1000000 / frame))); //60 fps = 100% speed | |
cps++; | |
if (second) { | |
flashing = !flashing; | |
clockSeconds++; | |
if (timeout > 0 ) timeout--; | |
//Time manager | |
if (night_mode && !inMenu) { | |
current_time = bcdToDec(rtc[5], rtc[4]) * 60 + bcdToDec(rtc[3], rtc[2]); | |
evening_time = bcdToDec(evening[3], evening[2]) * 60 + bcdToDec(evening[1], evening[0]); | |
morning_time = bcdToDec(morning[3], morning[2]) * 60 + bcdToDec(morning[1], morning[0]); | |
if (current_time >= evening_time) { | |
if (current_time - evening_time <= 30) { | |
byte temp = current_time - evening_time; | |
kelvin = map(temp, 0, 30, maxKelvin, minKelvin); | |
//Serial.println("1"); | |
} | |
else { | |
kelvin = minKelvin; | |
//Serial.println("2"); | |
} | |
} | |
else if (current_time <= morning_time) { | |
if (morning_time - current_time <= 30) { | |
byte temp = morning_time - current_time; | |
kelvin = map(temp, 0, 30, maxKelvin, minKelvin); | |
//Serial.println("3"); | |
} | |
else { | |
kelvin = minKelvin; | |
//Serial.println("4"); | |
} | |
} | |
else { | |
kelvin = maxKelvin; | |
//Serial.println("5"); | |
} | |
} | |
fps = 0; | |
cps = 0; | |
second = false; | |
} | |
} | |
const byte PROGMEM dim_curve[] = { | |
0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, | |
3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, | |
4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, | |
6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, | |
8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, | |
11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, | |
15, 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, | |
20, 20, 21, 21, 22, 22, 22, 23, 23, 24, 24, 25, 25, 25, 26, 26, | |
27, 27, 28, 28, 29, 29, 30, 30, 31, 32, 32, 33, 33, 34, 35, 35, | |
36, 36, 37, 38, 38, 39, 40, 40, 41, 42, 43, 43, 44, 45, 46, 47, | |
48, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, | |
63, 64, 65, 66, 68, 69, 70, 71, 73, 74, 75, 76, 78, 79, 81, 82, | |
83, 85, 86, 88, 90, 91, 93, 94, 96, 98, 99, 101, 103, 105, 107, 109, | |
110, 112, 114, 116, 118, 121, 123, 125, 127, 129, 132, 134, 136, 139, 141, 144, | |
146, 149, 151, 154, 157, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 190, | |
193, 196, 200, 203, 207, 211, 214, 218, 222, 226, 230, 234, 238, 242, 248, 255, | |
}; | |
const uint8_t PROGMEM gamma[] = { | |
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, | |
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, | |
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, | |
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, | |
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25, | |
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, | |
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, | |
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, | |
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89, | |
90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 109, 110, 112, 114, | |
115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133, 135, 137, 138, 140, 142, | |
144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 167, 169, 171, 173, 175, | |
177, 180, 182, 184, 186, 189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213, | |
215, 218, 220, 223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252, 255 | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment