WLED/wled00/wled01_eeprom.ino
cschwinne 70d0aae07c First commit of 0.8.0 dev cycle
Updated to newer WS2812FX version which supports segments (not supported in WLED yet)
Added new (FastLED) effects
Adjusted FX speed timings
Removed Sweep transition and Custom Chase (seldomly used - hinder development)
Removed solid overlay (no longer needed once segments are added)
Fixed Blynk effect set
2018-09-04 15:51:38 +02:00

607 lines
18 KiB
C++

/*
* Methods to handle saving and loading to non-volatile memory
* EEPROM Map: https://github.com/Aircoookie/WLED/wiki/EEPROM-Map
*/
#define EEPSIZE 3072
//eeprom Version code, enables default settings instead of 0 init on update
#define EEPVER 7
//0 -> old version, default
//1 -> 0.4p 1711272 and up
//2 -> 0.4p 1711302 and up
//3 -> 0.4 1712121 and up
//4 -> 0.5.0 and up
//5 -> 0.5.1 and up
//6 -> 0.6.0 and up
//7 -> 0.7.1 and up
//8 -> 0.8.0 and up
/*
* Erase all configuration data
*/
void clearEEPROM()
{
for (int i = 0; i < EEPSIZE; i++)
{
EEPROM.write(i, 0);
}
EEPROM.commit();
}
/*
* Write configuration to flash
*/
void saveSettingsToEEPROM()
{
if (EEPROM.read(233) != 233) //set no first boot flag
{
clearEEPROM();
EEPROM.write(233, 233);
}
for (int i = 0; i < 32; ++i)
{
EEPROM.write(i, clientSSID[i]);
}
for (int i = 32; i < 96; ++i)
{
EEPROM.write(i, clientPass[i-32]);
}
for (int i = 96; i < 128; ++i)
{
EEPROM.write(i, cmDNS[i-96]);
}
for (int i = 128; i < 160; ++i)
{
EEPROM.write(i, apSSID[i-128]);
}
for (int i = 160; i < 224; ++i)
{
EEPROM.write(i, apPass[i-160]);
}
EEPROM.write(224, nightlightDelayMins);
EEPROM.write(225, nightlightFade);
EEPROM.write(226, notifyDirectDefault);
EEPROM.write(227, apChannel);
EEPROM.write(228, apHide);
EEPROM.write(229, (ledCount >> 0) & 0xFF);
EEPROM.write(230, notifyButton);
EEPROM.write(231, notifyTwice);
EEPROM.write(232, buttonEnabled);
//233 reserved for first boot flag
for (int i = 0; i<4; i++) //ip addresses
{
EEPROM.write(234+i, staticIP[i]);
EEPROM.write(238+i, staticGateway[i]);
EEPROM.write(242+i, staticSubnet[i]);
}
EEPROM.write(246, colS[0]);
EEPROM.write(247, colS[1]);
EEPROM.write(248, colS[2]);
EEPROM.write(249, briS);
EEPROM.write(250, receiveNotificationBrightness);
EEPROM.write(251, fadeTransition);
EEPROM.write(252, reverseMode);
EEPROM.write(253, (transitionDelayDefault >> 0) & 0xFF);
EEPROM.write(254, (transitionDelayDefault >> 8) & 0xFF);
EEPROM.write(255, briMultiplier);
//255,250,231,230,226 notifier bytes
for (int i = 256; i < 288; ++i)
{
EEPROM.write(i, otaPass[i-256]);
}
EEPROM.write(288, nightlightTargetBri);
EEPROM.write(289, otaLock);
EEPROM.write(290, (udpPort >> 0) & 0xFF);
EEPROM.write(291, (udpPort >> 8) & 0xFF);
for (int i = 292; i < 324; ++i)
{
EEPROM.write(i, serverDescription[i-292]);
}
EEPROM.write(324, effectDefault);
EEPROM.write(325, effectSpeedDefault);
EEPROM.write(326, effectIntensityDefault);
EEPROM.write(327, ntpEnabled);
EEPROM.write(328, currentTimezone);
EEPROM.write(329, useAMPM);
EEPROM.write(330, useGammaCorrectionBri);
EEPROM.write(331, useGammaCorrectionRGB);
EEPROM.write(332, overlayDefault);
EEPROM.write(333, alexaEnabled);
for (int i = 334; i < 366; ++i)
{
EEPROM.write(i, alexaInvocationName[i-334]);
}
EEPROM.write(366, alexaNotify);
EEPROM.write(367, (arlsOffset>=0));
EEPROM.write(368, abs(arlsOffset));
EEPROM.write(369, turnOnAtBoot);
EEPROM.write(370, useHSBDefault);
EEPROM.write(371, whiteS);
EEPROM.write(372, useRGBW);
EEPROM.write(375, apWaitTimeSecs);
EEPROM.write(376, recoveryAPDisabled);
EEPROM.write(377, EEPVER); //eeprom was updated to latest
EEPROM.write(378, colSecS[0]);
EEPROM.write(379, colSecS[1]);
EEPROM.write(380, colSecS[2]);
EEPROM.write(381, whiteSecS);
EEPROM.write(389, bootPreset);
EEPROM.write(390, aOtaEnabled);
EEPROM.write(391, receiveNotificationColor);
EEPROM.write(392, receiveNotificationEffects);
EEPROM.write(393, wifiLock);
EEPROM.write(394, (abs(utcOffsetSecs) >> 0) & 0xFF);
EEPROM.write(395, (abs(utcOffsetSecs) >> 8) & 0xFF);
EEPROM.write(396, (utcOffsetSecs<0)); //is negative
EEPROM.write(397, initLedsLast);
EEPROM.write(398, (ledCount >> 8) & 0xFF);
EEPROM.write(399, disableSecTransition);
for (int k=0;k<6;k++){
int in = 900+k*8;
for (int i=in; i < in+8; ++i)
{
EEPROM.write(i, cssCol[i-in][k]);
}}
EEPROM.write(948,currentTheme);
for (int i = 950; i < 982; ++i)
{
EEPROM.write(i, cssFont[i-950]);
}
EEPROM.write(2048, huePollingEnabled);
//EEPROM.write(2049, hueUpdatingEnabled);
for (int i = 2050; i < 2054; ++i)
{
EEPROM.write(i, hueIP[i-2050]);
}
for (int i = 2054; i < 2100; ++i)
{
EEPROM.write(i, hueApiKey[i-2054]);
}
EEPROM.write(2100, (huePollIntervalMs >> 0) & 0xFF);
EEPROM.write(2101, (huePollIntervalMs >> 8) & 0xFF);
EEPROM.write(2102, notifyHue);
EEPROM.write(2103, hueApplyOnOff);
EEPROM.write(2104, hueApplyBri);
EEPROM.write(2105, hueApplyColor);
EEPROM.write(2106, huePollLightId);
EEPROM.write(2150, overlayMin);
EEPROM.write(2151, overlayMax);
EEPROM.write(2152, analogClock12pixel);
EEPROM.write(2153, analogClock5MinuteMarks);
EEPROM.write(2154, analogClockSecondsTrail);
EEPROM.write(2155, countdownMode);
EEPROM.write(2156, countdownYear);
EEPROM.write(2157, countdownMonth);
EEPROM.write(2158, countdownDay);
EEPROM.write(2159, countdownHour);
EEPROM.write(2160, countdownMin);
EEPROM.write(2161, countdownSec);
setCountdown();
for (int i = 2165; i < 2171; ++i)
{
EEPROM.write(i, cronixieDisplay[i-2165]);
}
EEPROM.write(2171, cronixieBacklight);
setCronixie();
EEPROM.write(2175, macroBoot);
EEPROM.write(2176, macroAlexaOn);
EEPROM.write(2177, macroAlexaOff);
EEPROM.write(2178, macroButton);
EEPROM.write(2179, macroLongPress);
EEPROM.write(2180, macroCountdown);
EEPROM.write(2181, macroNl);
EEPROM.write(2190, (e131Universe >> 0) & 0xFF);
EEPROM.write(2191, (e131Universe >> 8) & 0xFF);
EEPROM.write(2192, e131Multicast);
EEPROM.write(2193, (arlsTimeoutMillis >> 0) & 0xFF);
EEPROM.write(2194, (arlsTimeoutMillis >> 8) & 0xFF);
EEPROM.write(2195, arlsForceMaxBri);
EEPROM.write(2196, arlsDisableGammaCorrection);
EEPROM.write(2200,!receiveDirect);
EEPROM.write(2201,enableRealtimeUI);
EEPROM.write(2202,uiConfiguration);
EEPROM.write(2203,autoRGBtoRGBW);
EEPROM.write(2204,skipFirstLed);
if (saveCurrPresetCycConf)
{
EEPROM.write(2205,presetCyclingEnabled);
EEPROM.write(2206,(presetCycleTime >> 0) & 0xFF);
EEPROM.write(2207,(presetCycleTime >> 8) & 0xFF);
EEPROM.write(2208,presetCycleMin);
EEPROM.write(2209,presetCycleMax);
EEPROM.write(2210,presetApplyBri);
EEPROM.write(2211,presetApplyCol);
EEPROM.write(2212,presetApplyFx);
saveCurrPresetCycConf = false;
}
for (int i = 2220; i < 2255; ++i)
{
EEPROM.write(i, blynkApiKey[i-2220]);
}
EEPROM.commit();
}
/*
* Read all configuration from flash
*/
void loadSettingsFromEEPROM(bool first)
{
if (EEPROM.read(233) != 233) //first boot/reset to default
{
saveSettingsToEEPROM();
return;
}
int lastEEPROMversion = EEPROM.read(377); //last EEPROM version before update
for (int i = 0; i < 32; ++i)
{
clientSSID[i] = EEPROM.read(i);
if (clientSSID[i] == 0) break;
}
for (int i = 32; i < 96; ++i)
{
clientPass[i-32] = EEPROM.read(i);
if (clientPass[i-32] == 0) break;
}
for (int i = 96; i < 128; ++i)
{
cmDNS[i-96] = EEPROM.read(i);
if (cmDNS[i-96] == 0) break;
}
for (int i = 128; i < 160; ++i)
{
apSSID[i-128] = EEPROM.read(i);
if (apSSID[i-128] == 0) break;
}
for (int i = 160; i < 224; ++i)
{
apPass[i-160] = EEPROM.read(i);
if (apPass[i-160] == 0) break;
}
nightlightDelayMins = EEPROM.read(224);
nightlightFade = EEPROM.read(225);
notifyDirectDefault = EEPROM.read(226);
notifyDirect = notifyDirectDefault;
apChannel = EEPROM.read(227);
if (apChannel > 13 || apChannel < 1) apChannel = 1;
apHide = EEPROM.read(228);
if (apHide > 1) apHide = 1;
ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200 || ledCount == 0) ledCount = 10;
notifyButton = EEPROM.read(230);
notifyTwice = EEPROM.read(231);
buttonEnabled = EEPROM.read(232);
staticIP[0] = EEPROM.read(234);
staticIP[1] = EEPROM.read(235);
staticIP[2] = EEPROM.read(236);
staticIP[3] = EEPROM.read(237);
staticGateway[0] = EEPROM.read(238);
staticGateway[1] = EEPROM.read(239);
staticGateway[2] = EEPROM.read(240);
staticGateway[3] = EEPROM.read(241);
staticSubnet[0] = EEPROM.read(242);
staticSubnet[1] = EEPROM.read(243);
staticSubnet[2] = EEPROM.read(244);
staticSubnet[3] = EEPROM.read(245);
colS[0] = EEPROM.read(246); col[0] = colS[0];
colS[1] = EEPROM.read(247); col[1] = colS[1];
colS[2] = EEPROM.read(248); col[2] = colS[2];
briS = EEPROM.read(249); bri = briS;
if (!EEPROM.read(369) && first)
{
bri = 0; briLast = briS;
}
receiveNotificationBrightness = EEPROM.read(250);
fadeTransition = EEPROM.read(251);
reverseMode = EEPROM.read(252);
transitionDelayDefault = ((EEPROM.read(253) << 0) & 0xFF) + ((EEPROM.read(254) << 8) & 0xFF00);
transitionDelay = transitionDelayDefault;
briMultiplier = EEPROM.read(255);
for (int i = 256; i < 288; ++i)
{
otaPass[i-256] = EEPROM.read(i);
if (otaPass[i-256] == 0) break;
}
nightlightTargetBri = EEPROM.read(288);
otaLock = EEPROM.read(289);
udpPort = ((EEPROM.read(290) << 0) & 0xFF) + ((EEPROM.read(291) << 8) & 0xFF00);
for (int i = 292; i < 324; ++i)
{
serverDescription[i-292] = EEPROM.read(i);
if (serverDescription[i-292] == 0) break;
}
effectDefault = EEPROM.read(324); effectCurrent = effectDefault;
effectSpeedDefault = EEPROM.read(325); effectSpeed = effectSpeedDefault;
ntpEnabled = EEPROM.read(327);
currentTimezone = EEPROM.read(328);
useAMPM = EEPROM.read(329);
useGammaCorrectionBri = EEPROM.read(330);
useGammaCorrectionRGB = EEPROM.read(331);
overlayDefault = EEPROM.read(332);
if (lastEEPROMversion < 8 && overlayDefault > 0) overlayDefault--; //overlay mode 1 (solid) was removed
alexaEnabled = EEPROM.read(333);
for (int i = 334; i < 366; ++i)
{
alexaInvocationName[i-334] = EEPROM.read(i);
if (alexaInvocationName[i-334] == 0) break;
}
alexaNotify = EEPROM.read(366);
arlsOffset = EEPROM.read(368);
if (!EEPROM.read(367)) arlsOffset = -arlsOffset;
turnOnAtBoot = EEPROM.read(369);
useHSBDefault = EEPROM.read(370);
whiteS = EEPROM.read(371); white = whiteS;
useRGBW = EEPROM.read(372);
if (lastEEPROMversion > 0) {
apWaitTimeSecs = EEPROM.read(375);
recoveryAPDisabled = EEPROM.read(376);
}
//377 = lastEEPROMversion
if (lastEEPROMversion > 1) {
colSecS[0] = EEPROM.read(378); colSec[0] = colSecS[0];
colSecS[1] = EEPROM.read(379); colSec[1] = colSecS[1];
colSecS[2] = EEPROM.read(380); colSec[2] = colSecS[2];
whiteSecS = EEPROM.read(381); whiteSec = whiteSecS;
}
if (lastEEPROMversion > 3) {
effectIntensityDefault = EEPROM.read(326); effectIntensity = effectIntensityDefault;
aOtaEnabled = EEPROM.read(390);
receiveNotificationColor = EEPROM.read(391);
receiveNotificationEffects = EEPROM.read(392);
for (int i = 950; i < 982; ++i)
{
cssFont[i-950] = EEPROM.read(i);
if (cssFont[i-950] == 0) break;
}
} else //keep receiving notification behavior from pre0.5.0 after update
{
receiveNotificationColor = receiveNotificationBrightness;
receiveNotificationEffects = receiveNotificationBrightness;
}
receiveNotifications = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
if (lastEEPROMversion > 4) {
huePollingEnabled = EEPROM.read(2048);
//hueUpdatingEnabled = EEPROM.read(2049);
for (int i = 2050; i < 2054; ++i)
{
hueIP[i-2050] = EEPROM.read(i);
}
for (int i = 2054; i < 2100; ++i)
{
hueApiKey[i-2054] = EEPROM.read(i);
if (hueApiKey[i-2054] == 0) break;
}
huePollIntervalMs = ((EEPROM.read(2100) << 0) & 0xFF) + ((EEPROM.read(2101) << 8) & 0xFF00);
notifyHue = EEPROM.read(2102);
hueApplyOnOff = EEPROM.read(2103);
hueApplyBri = EEPROM.read(2104);
hueApplyColor = EEPROM.read(2105);
huePollLightId = EEPROM.read(2106);
}
if (lastEEPROMversion > 5) {
overlayMin = EEPROM.read(2150);
overlayMax = EEPROM.read(2151);
analogClock12pixel = EEPROM.read(2152);
analogClock5MinuteMarks = EEPROM.read(2153);
analogClockSecondsTrail = EEPROM.read(2154);
countdownMode = EEPROM.read(2155);
countdownYear = EEPROM.read(2156);
countdownMonth = EEPROM.read(2157);
countdownDay = EEPROM.read(2158);
countdownHour = EEPROM.read(2159);
countdownMin = EEPROM.read(2160);
countdownSec = EEPROM.read(2161);
setCountdown();
for (int i = 2165; i < 2171; ++i)
{
cronixieDisplay[i-2165] = EEPROM.read(i);
}
cronixieBacklight = EEPROM.read(2171);
macroBoot = EEPROM.read(2175);
macroAlexaOn = EEPROM.read(2176);
macroAlexaOff = EEPROM.read(2177);
macroButton = EEPROM.read(2178);
macroLongPress = EEPROM.read(2179);
macroCountdown = EEPROM.read(2180);
macroNl = EEPROM.read(2181);
}
if (lastEEPROMversion > 6)
{
e131Universe = ((EEPROM.read(2190) << 0) & 0xFF) + ((EEPROM.read(2191) << 8) & 0xFF00);
e131Multicast = EEPROM.read(2192);
arlsTimeoutMillis = ((EEPROM.read(2193) << 0) & 0xFF) + ((EEPROM.read(2194) << 8) & 0xFF00);
arlsForceMaxBri = EEPROM.read(2195);
arlsDisableGammaCorrection = EEPROM.read(2196);
}
receiveDirect = !EEPROM.read(2200);
enableRealtimeUI = EEPROM.read(2201);
uiConfiguration = EEPROM.read(2202);
#ifdef WLED_FLASH_512K_MODE
uiConfiguration = 1;
//force default UI since mobile is unavailable
#endif
autoRGBtoRGBW = EEPROM.read(2203);
skipFirstLed = EEPROM.read(2204);
if (EEPROM.read(2210) || EEPROM.read(2211) || EEPROM.read(2212))
{
presetCyclingEnabled = EEPROM.read(2205);
presetCycleTime = ((EEPROM.read(2206) << 0) & 0xFF) + ((EEPROM.read(2207) << 8) & 0xFF00);
presetCycleMin = EEPROM.read(2208);
presetCycleMax = EEPROM.read(2209);
presetApplyBri = EEPROM.read(2210);
presetApplyCol = EEPROM.read(2211);
presetApplyFx = EEPROM.read(2212);
}
for (int i = 2220; i < 2255; ++i)
{
blynkApiKey[i-2220] = EEPROM.read(i);
if (blynkApiKey[i-2220] == 0) break;
}
bootPreset = EEPROM.read(389);
wifiLock = EEPROM.read(393);
utcOffsetSecs = ((EEPROM.read(394) << 0) & 0xFF) + ((EEPROM.read(395) << 8) & 0xFF00);
if (EEPROM.read(396)) utcOffsetSecs = -utcOffsetSecs; //negative
initLedsLast = EEPROM.read(397);
disableSecTransition = EEPROM.read(399);
//favorite setting (preset) memory (25 slots/ each 20byte)
//400 - 899 reserved
currentTheme = EEPROM.read(948);
for (int k=0;k<6;k++){
int in=900+k*8;
for (int i=in; i < in+8; ++i)
{
if (EEPROM.read(i) == 0) break;
cssCol[i-in][k] =EEPROM.read(i);
}}
//custom macro memory (16 slots/ each 64byte)
//1024-2047 reserved
//user MOD memory
//2944 - 3071 reserved
useHSB = useHSBDefault;
strip.setMode(effectCurrent);
strip.setSpeed(effectSpeed);
strip.setIntensity(effectIntensity);
overlayCurrent = overlayDefault;
}
//PRESET PROTOCOL 20 bytes
//0: preset purpose byte 0:invalid 1:valid preset 1.0
//1:a 2:r 3:g 4:b 5:w 6:er 7:eg 8:eb 9:ew 10:fx 11:sx | custom chase 12:numP 13:numS 14:(0:fs 1:both 2:fe) 15:step 16:ix 17-19:Zeros
void applyPreset(byte index, bool loadBri, bool loadCol, bool loadFX)
{
if (index == 255 || index == 0) loadSettingsFromEEPROM(false);//load boot defaults
if (index > 25 || index < 1) return;
uint16_t i = 380 + index*20;
if (EEPROM.read(i) == 0) return;
if (loadBri) bri = EEPROM.read(i+1);
if (loadCol)
{
col[0] = EEPROM.read(i+2);
col[1] = EEPROM.read(i+3);
col[2] = EEPROM.read(i+4);
white = EEPROM.read(i+5);
colSec[0] = EEPROM.read(i+6);
colSec[1] = EEPROM.read(i+7);
colSec[2] = EEPROM.read(i+8);
whiteSec = EEPROM.read(i+9);
}
if (loadFX)
{
byte lastfx = effectCurrent;
effectCurrent = EEPROM.read(i+10);
effectSpeed = EEPROM.read(i+11);
effectIntensity = EEPROM.read(i+16);
if (lastfx != effectCurrent) strip.setMode(effectCurrent);
strip.setSpeed(effectSpeed);
strip.setIntensity(effectIntensity);
}
}
void savePreset(byte index)
{
if (index > 25) return;
if (index < 1) {saveSettingsToEEPROM();return;}
uint16_t i = 380 + index*20;//min400
EEPROM.write(i, 1);
EEPROM.write(i+1, bri);
EEPROM.write(i+2, col[0]);
EEPROM.write(i+3, col[1]);
EEPROM.write(i+4, col[2]);
EEPROM.write(i+5, white);
EEPROM.write(i+6, colSec[0]);
EEPROM.write(i+7, colSec[1]);
EEPROM.write(i+8, colSec[2]);
EEPROM.write(i+9, whiteSec);
EEPROM.write(i+10, effectCurrent);
EEPROM.write(i+11, effectSpeed);
EEPROM.write(i+16, effectIntensity);
EEPROM.commit();
}
String loadMacro(byte index)
{
index-=1;
String m="";
if (index > 15) return m;
for (int i = 1024+64*index; i < 1088+64*index; i++)
{
if (EEPROM.read(i) == 0) break;
m += char(EEPROM.read(i));
}
if (m.charAt(0) < 65 || m.charAt(0) > 90) return ""; //do simple check if macro is valid (capital first letter)
return m;
}
void applyMacro(byte index)
{
index-=1;
if (index > 15) return;
String mc="win&";
mc += loadMacro(index+1);
mc += "&IN"; //internal, no XML response
if (!macroNotify) mc += "&NN";
String forbidden = "&M="; //dont apply if called by the macro itself to prevent loop
/*
* NOTE: loop is still possible if you call a different macro from a macro, which then calls the first macro again.
* To prevent that, but also disable calling macros within macros, comment the next line out.
*/
forbidden = forbidden + index;
if (mc.indexOf(forbidden) >= 0) return;
handleSet(mc);
}
void saveMacro(byte index, String mc, bool sing=true) //only commit on single save, not in settings
{
index-=1;
if (index > 15) return;
int s = 1024+index*64;
for (int i = s; i < s+64; i++)
{
EEPROM.write(i, mc.charAt(i-s));
}
if (sing) EEPROM.commit();
}