4LineDisplay enhancements.

Boot loop (preset apply) fix.
This commit is contained in:
Blaz Kristan 2021-04-11 16:47:53 +02:00
parent a6feb77e52
commit 735205492e
2 changed files with 172 additions and 107 deletions

View File

@ -24,7 +24,10 @@
#endif
class UsermodTemperature : public Usermod {
private:
bool initDone = false;
OneWire *oneWire;
DallasTemperature *sensor;
// The device's unique 64-bit serial code stored in on-board ROM.
@ -75,9 +78,7 @@ class UsermodTemperature : public Usermod {
public:
void setup() {
// pin retrieved from cfg.json (readFromConfig()) prior to running setup()
if (!pinManager.allocatePin(temperaturePin,false)) {
temperaturePin = -1; // allocation failed
@ -103,6 +104,7 @@ class UsermodTemperature : public Usermod {
} else {
DEBUG_PRINTLN(F("Dallas Temperature not found"));
}
initDone = true;
}
void loop() {
@ -123,7 +125,7 @@ class UsermodTemperature : public Usermod {
}
// we were waiting for a conversion to complete, have we waited log enough?
if (now - lastTemperaturesRequest >= 94 /* 93.75ms per the datasheet */) {
if (now - lastTemperaturesRequest >= 95 /* 93.75ms per the datasheet */) {
getTemperature();
if (WLED_MQTT_CONNECTED) {
@ -187,6 +189,7 @@ class UsermodTemperature : public Usermod {
* Read "<usermodname>_<usermodparam>" from json state and and change settings (i.e. GPIO pin) used.
*/
void readFromJsonState(JsonObject &root) {
if (!initDone) return; // prevent crash on boot applyPreset()
if (root[F("Temperature_pin")] != nullptr) {
int8_t pin = (int)root[F("Temperature_pin")];
if (pin != temperaturePin) {

View File

@ -57,8 +57,8 @@ typedef enum {
FLD_LINE_3_BRIGHTNESS = 0,
FLD_LINE_3_EFFECT_SPEED,
FLD_LINE_3_EFFECT_INTENSITY,
FLD_LINE_3_PALETTE,
FLD_LINE_3_TIME
FLD_LINE_3_MODE,
FLD_LINE_3_PALETTE
} Line3Type;
typedef enum {
@ -68,20 +68,23 @@ typedef enum {
} DisplayType;
class FourLineDisplayUsermod : public Usermod {
private:
bool initDone = false;
unsigned long lastTime = 0;
// HW interface & configuration
void *u8x8; // pointer to U8X8 display object
int8_t sclPin, sdaPin; // I2C pins for interfacing, get initialised in readFromConfig()
DisplayType type = NONE; // display type
bool flip; // flip display 180°
uint8_t contrast;
uint8_t lineHeight; // 1 row or 2 rows
uint32_t refreshRate; // in ms
uint32_t screenTimeout; // in ms
bool sleepMode; // allow screen sleep?
bool clockMode; // display clock instead of info?
void *u8x8 = nullptr; // pointer to U8X8 display object
int8_t sclPin=FLD_PIN_SCL, sdaPin=FLD_PIN_SDA; // I2C pins for interfacing, get initialised in readFromConfig()
DisplayType type = SSD1306; // display type
bool flip = false; // flip display 180°
uint8_t contrast = 10; // screen contrast
uint8_t lineHeight = 1; // 1 row or 2 rows
uint32_t refreshRate = USER_LOOP_REFRESH_RATE_MS; // in ms
uint32_t screenTimeout = SCREEN_TIMEOUT_MS; // in ms
bool sleepMode = true; // allow screen sleep?
bool clockMode = false; // display clock
// needRedraw marks if redraw is required to prevent often redrawing.
bool needRedraw = true;
@ -99,21 +102,19 @@ class FourLineDisplayUsermod : public Usermod {
uint8_t knownHour = 99;
bool displayTurnedOff = false;
long lastUpdate = 0;
long lastRedraw = 0;
long overlayUntil = 0;
unsigned long lastUpdate = 0;
unsigned long lastRedraw = 0;
unsigned long overlayUntil = 0;
Line3Type lineThreeType = FLD_LINE_3_BRIGHTNESS;
// Set to 2 or 3 to mark lines 2 or 3. Other values ignored.
byte markLineNum = 0;
char **modes_qstrings = nullptr;
char **palettes_qstrings = nullptr;
// If display does not work or looks corrupted check the
// constructor reference:
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
// or check the gallery:
// https://github.com/olikraus/u8g2/wiki/gallery
public:
// gets called once at boot. Do all initialization that doesn't depend on
@ -126,27 +127,22 @@ class FourLineDisplayUsermod : public Usermod {
case SSD1306:
u8x8 = (void *) new U8X8_SSD1306_128X32_UNIVISION_HW_I2C(U8X8_PIN_NONE, sclPin, sdaPin); // Pins are Reset, SCL, SDA
(static_cast<U8X8_SSD1306_128X32_UNIVISION_HW_I2C*>(u8x8))->begin();
(static_cast<U8X8_SSD1306_128X32_UNIVISION_HW_I2C*>(u8x8))->setFlipMode(flip);
(static_cast<U8X8_SSD1306_128X32_UNIVISION_HW_I2C*>(u8x8))->setContrast(contrast); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
break;
case SH1106:
u8x8 = (void *) new U8X8_SH1106_128X64_WINSTAR_HW_I2C(U8X8_PIN_NONE, sclPin, sdaPin); // Pins are Reset, SCL, SDA
(static_cast<U8X8_SH1106_128X64_WINSTAR_HW_I2C*>(u8x8))->begin();
(static_cast<U8X8_SH1106_128X64_WINSTAR_HW_I2C*>(u8x8))->setFlipMode(flip);
(static_cast<U8X8_SH1106_128X64_WINSTAR_HW_I2C*>(u8x8))->setContrast(contrast); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
break;
default:
u8x8 = nullptr;
type = NONE;
return;
}
setFlipMode(flip);
setContrast(contrast); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
setPowerSave(0);
String loading = String(F("Loading..."));
drawString(0, 0, loading.c_str());
ModeSortUsermod *modeSortUsermod = (ModeSortUsermod*) usermods.lookup(USERMOD_ID_MODE_SORT);
modes_qstrings = modeSortUsermod->getModesQStrings();
palettes_qstrings = modeSortUsermod->getPalettesQStrings();
initDone = true;
}
// gets called every time WiFi is (re-)connected. Initialize own network
@ -168,8 +164,31 @@ class FourLineDisplayUsermod : public Usermod {
/**
* Wrappers for screen drawing
*/
void setFlipMode(uint8_t mode) {
switch (type) {
case SSD1306:
(static_cast<U8X8_SSD1306_128X32_UNIVISION_HW_I2C*>(u8x8))->setFlipMode(mode);
break;
case SH1106:
(static_cast<U8X8_SH1106_128X64_WINSTAR_HW_I2C*>(u8x8))->setFlipMode(mode);
break;
default:
return;
}
}
void setContrast(uint8_t contrast) {
switch (type) {
case SSD1306:
(static_cast<U8X8_SSD1306_128X32_UNIVISION_HW_I2C*>(u8x8))->setContrast(contrast);
break;
case SH1106:
(static_cast<U8X8_SH1106_128X64_WINSTAR_HW_I2C*>(u8x8))->setContrast(contrast);
break;
default:
return;
}
}
void drawString(uint8_t col, uint8_t row, const char *string) {
if (type==NONE) return;
switch (type) {
case SSD1306:
(static_cast<U8X8_SSD1306_128X32_UNIVISION_HW_I2C*>(u8x8))->setFont(u8x8_font_chroma48medium8_r);
@ -181,10 +200,11 @@ class FourLineDisplayUsermod : public Usermod {
if (lineHeight==2) (static_cast<U8X8_SH1106_128X64_WINSTAR_HW_I2C*>(u8x8))->draw1x2String(col, row, string);
else (static_cast<U8X8_SH1106_128X64_WINSTAR_HW_I2C*>(u8x8))->drawString(col, row, string);
break;
default:
return;
}
}
void draw2x2String(uint8_t col, uint8_t row, const char *string) {
if (type==NONE) return;
switch (type) {
case SSD1306:
(static_cast<U8X8_SSD1306_128X32_UNIVISION_HW_I2C*>(u8x8))->setFont(u8x8_font_chroma48medium8_r);
@ -194,10 +214,11 @@ class FourLineDisplayUsermod : public Usermod {
(static_cast<U8X8_SH1106_128X64_WINSTAR_HW_I2C*>(u8x8))->setFont(u8x8_font_chroma48medium8_r);
(static_cast<U8X8_SH1106_128X64_WINSTAR_HW_I2C*>(u8x8))->draw2x2String(col, row, string);
break;
default:
return;
}
}
void drawGlyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font) {
if (type==NONE) return;
switch (type) {
case SSD1306:
(static_cast<U8X8_SSD1306_128X32_UNIVISION_HW_I2C*>(u8x8))->setFont(font);
@ -209,19 +230,21 @@ class FourLineDisplayUsermod : public Usermod {
if (lineHeight==2) (static_cast<U8X8_SH1106_128X64_WINSTAR_HW_I2C*>(u8x8))->draw1x2Glyph(col, row, glyph);
else (static_cast<U8X8_SH1106_128X64_WINSTAR_HW_I2C*>(u8x8))->drawGlyph(col, row, glyph);
break;
default:
return;
}
}
uint8_t getCols() {
if (type==NONE) return 255;
switch (type) {
case SSD1306:
return (static_cast<U8X8_SSD1306_128X32_UNIVISION_HW_I2C*>(u8x8))->getCols();
case SH1106:
return (static_cast<U8X8_SH1106_128X64_WINSTAR_HW_I2C*>(u8x8))->getCols();
default:
return 0;
}
}
void clear() {
if (type==NONE) return;
switch (type) {
case SSD1306:
(static_cast<U8X8_SSD1306_128X32_UNIVISION_HW_I2C*>(u8x8))->clear();
@ -229,10 +252,11 @@ class FourLineDisplayUsermod : public Usermod {
case SH1106:
(static_cast<U8X8_SH1106_128X64_WINSTAR_HW_I2C*>(u8x8))->clear();
break;
default:
return;
}
}
void setPowerSave(uint8_t save) {
if (type==NONE) return;
switch (type) {
case SSD1306:
(static_cast<U8X8_SSD1306_128X32_UNIVISION_HW_I2C*>(u8x8))->setPowerSave(save);
@ -240,6 +264,8 @@ class FourLineDisplayUsermod : public Usermod {
case SH1106:
(static_cast<U8X8_SH1106_128X64_WINSTAR_HW_I2C*>(u8x8))->setPowerSave(save);
break;
default:
return;
}
}
@ -287,6 +313,7 @@ class FourLineDisplayUsermod : public Usermod {
if(sleepMode && !displayTurnedOff && (millis() - lastRedraw > screenTimeout)) {
// We will still check if there is a change in redraw()
// and turn it back on if it changed.
knownHour = 99; // force screen clear
sleepOrClock(true);
} else if (displayTurnedOff && clockMode) {
showTime();
@ -294,26 +321,30 @@ class FourLineDisplayUsermod : public Usermod {
// change 4th line every 3s
switch (lineThreeType) {
case FLD_LINE_3_BRIGHTNESS:
setLineThreeType(FLD_LINE_3_PALETTE);
setLineThreeType(FLD_LINE_3_EFFECT_SPEED);
break;
case FLD_LINE_3_MODE:
setLineThreeType(FLD_LINE_3_BRIGHTNESS);
break;
case FLD_LINE_3_PALETTE:
setLineThreeType(FLD_LINE_3_EFFECT_SPEED);
setLineThreeType(clockMode ? FLD_LINE_3_MODE : FLD_LINE_3_BRIGHTNESS);
break;
case FLD_LINE_3_EFFECT_SPEED:
setLineThreeType(FLD_LINE_3_EFFECT_INTENSITY);
break;
case FLD_LINE_3_EFFECT_INTENSITY:
setLineThreeType(FLD_LINE_3_BRIGHTNESS);
setLineThreeType(FLD_LINE_3_PALETTE);
break;
default:
setLineThreeType(FLD_LINE_3_BRIGHTNESS);
break;
}
drawLineThree();
drawLineFour();
}
return;
} else
} else {
knownHour = 99; // force time display
clear();
}
needRedraw = false;
lastRedraw = millis();
@ -354,11 +385,12 @@ class FourLineDisplayUsermod : public Usermod {
drawString(1, lineHeight, (knownIp.toString()).c_str());
}
// Third row with mode name
showCurrentEffectOrPalette(modes_qstrings[knownMode], 2);
// Third row with mode name or current time
if (clockMode) showTime(false);
else showCurrentEffectOrPalette(knownMode, JSON_mode_names, 2);
// Fourth row
drawLineThree();
drawLineFour();
drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0), u8x8_font_open_iconic_weather_2x2); // sun/moon icon
drawGlyph(0, 0, 80, u8x8_font_open_iconic_embedded_1x1); // wifi icon
@ -366,7 +398,7 @@ class FourLineDisplayUsermod : public Usermod {
//if (markLineNum>1) drawGlyph(2, markLineNum*lineHeight, 66, u8x8_font_open_iconic_arrow_1x1); // arrow icon
}
void drawLineThree() {
void drawLineFour() {
char lineBuffer[LINE_BUFFER_SIZE];
switch(lineThreeType) {
case FLD_LINE_3_BRIGHTNESS:
@ -381,9 +413,12 @@ class FourLineDisplayUsermod : public Usermod {
sprintf_P(lineBuffer, PSTR("FX Intens. %3d"), effectIntensity);
drawString(2, 3*lineHeight, lineBuffer);
break;
case FLD_LINE_3_MODE:
showCurrentEffectOrPalette(knownMode, JSON_mode_names, 3);
break;
case FLD_LINE_3_PALETTE:
default:
showCurrentEffectOrPalette(palettes_qstrings[knownPalette], 3);
showCurrentEffectOrPalette(knownPalette, JSON_palette_names, 3);
break;
}
}
@ -391,23 +426,34 @@ class FourLineDisplayUsermod : public Usermod {
/**
* Display the current effect or palette (desiredEntry)
* on the appropriate line (row).
*
* TODO: Should we cache the current effect and
* TODO: palette name? This seems expensive.
*/
void showCurrentEffectOrPalette(char *qstring, uint8_t row) {
void showCurrentEffectOrPalette(int knownMode, const char *qstring, uint8_t row) {
char lineBuffer[LINE_BUFFER_SIZE];
uint8_t qComma = 0;
bool insideQuotes = false;
uint8_t printedChars = 0;
char singleJsonSymbol;
while (printedChars < getCols() - 2) {
singleJsonSymbol = pgm_read_byte_near(qstring + printedChars);
if (singleJsonSymbol == '"' || singleJsonSymbol == '\0' ) {
break;
// Find the mode name in JSON
for (size_t i = 0; i < strlen_P(qstring); i++) {
singleJsonSymbol = pgm_read_byte_near(qstring + i);
if (singleJsonSymbol == '\0') break;
switch (singleJsonSymbol) {
case '"':
insideQuotes = !insideQuotes;
break;
case '[':
case ']':
break;
case ',':
qComma++;
default:
if (!insideQuotes || (qComma != knownMode)) break;
lineBuffer[printedChars++] = singleJsonSymbol;
}
lineBuffer[printedChars++] = singleJsonSymbol;
if ((qComma > knownMode) || (printedChars > getCols()-2) || printedChars > sizeof(lineBuffer)-2) break;
}
for (;printedChars<getCols()-2; printedChars++) lineBuffer[printedChars]=' ';
for (;printedChars < getCols()-2 || printedChars > sizeof(lineBuffer)-2; printedChars++) lineBuffer[printedChars]=' ';
lineBuffer[printedChars] = 0;
drawString(2, row*lineHeight, lineBuffer);
}
@ -419,6 +465,7 @@ class FourLineDisplayUsermod : public Usermod {
* to wake up the screen.
*/
bool wakeDisplay() {
knownHour = 99;
if (displayTurnedOff) {
// Turn the display back on
sleepOrClock(false);
@ -454,8 +501,8 @@ class FourLineDisplayUsermod : public Usermod {
if (newLineThreeType == FLD_LINE_3_BRIGHTNESS ||
newLineThreeType == FLD_LINE_3_EFFECT_SPEED ||
newLineThreeType == FLD_LINE_3_EFFECT_INTENSITY ||
newLineThreeType == FLD_LINE_3_PALETTE ||
newLineThreeType == FLD_LINE_3_TIME) {
newLineThreeType == FLD_LINE_3_MODE ||
newLineThreeType == FLD_LINE_3_PALETTE) {
lineThreeType = newLineThreeType;
} else {
// Unknown value
@ -483,18 +530,12 @@ class FourLineDisplayUsermod : public Usermod {
*/
void sleepOrClock(bool enabled) {
if (enabled) {
if (clockMode) {
showTime();
}
else {
setPowerSave(1);
}
if (clockMode) showTime();
else setPowerSave(1);
displayTurnedOff = true;
}
else {
if (!clockMode) {
setPowerSave(0);
}
setPowerSave(0);
displayTurnedOff = false;
}
}
@ -510,21 +551,22 @@ class FourLineDisplayUsermod : public Usermod {
updateLocalTime();
byte minuteCurrent = minute(localTime);
byte hourCurrent = hour(localTime);
byte secondCurrent = second(localTime);
if (knownMinute == minuteCurrent && knownHour == hourCurrent) {
// Time hasn't changed.
return;
if (!fullScreen) return;
} else {
if (fullScreen) clear();
}
knownMinute = minuteCurrent;
knownHour = hourCurrent;
if (fullScreen) clear();
int currentMonth = month(localTime);
sprintf_P(lineBuffer, PSTR("%s %2d "), monthShortStr(currentMonth), day(localTime));
if (fullScreen)
draw2x2String(DATE_INDENT, lineHeight==1 ? 0 : lineHeight, lineBuffer);
else
drawString(0, lineHeight, lineBuffer);
drawString(2, lineHeight*2, lineBuffer);
byte showHour = hourCurrent;
boolean isAM = false;
@ -542,13 +584,17 @@ class FourLineDisplayUsermod : public Usermod {
}
}
sprintf_P(lineBuffer, PSTR("%02d:%02d %s"), showHour, minuteCurrent, useAMPM ? (isAM ? "AM" : "PM") : "");
sprintf_P(lineBuffer, PSTR("%2d:%02d"), (useAMPM && fullScreen ? showHour : hourCurrent), minuteCurrent);
// For time, we always use LINE_HEIGHT of 2 since
// we are printing it big.
if (fullScreen)
draw2x2String(TIME_INDENT + (useAMPM ? 0 : 2), lineHeight*2, lineBuffer);
else
drawString(8, lineHeight, lineBuffer);
if (fullScreen) {
draw2x2String(TIME_INDENT+2, lineHeight*2, lineBuffer);
if (useAMPM) drawString(12, lineHeight*2, (isAM ? "AM" : "PM"));
sprintf_P(lineBuffer, PSTR("%02d"), secondCurrent);
drawString(12, lineHeight*2+1, lineBuffer);
} else {
drawString(9, lineHeight*2, lineBuffer);
}
}
/*
@ -575,34 +621,48 @@ class FourLineDisplayUsermod : public Usermod {
* Values in the state object may be modified by connected clients
*/
void readFromJsonState(JsonObject& root) {
if (!initDone) return; // prevent crash on boot applyPreset()
DisplayType newType = type;
uint8_t newScl = sclPin;
uint8_t newSda = sdaPin;
uint8_t newContrast = contrast;
bool newFlip = flip;
if (root[F("4LineDisplay_type")] != nullptr) newType = (DisplayType)root[F("4LineDisplay_type")];
if (root[F("4LineDisplay_pin")] != nullptr) {
newScl = (int)root[F("4LineDisplay_pin")][0];
newSda = (int)root[F("4LineDisplay_pin")][1];
// just to reduce memory
String str4LineDisplay_type = String(F("4LineDisplay_type"));
String str4LineDisplay_pin = String(F("4LineDisplay_pin"));
String str4LineDisplay_contrast = String(F("4LineDisplay_contrast"));
String str4LineDisplay_refreshRate = String(F("4LineDisplay_refreshRate"));
String str4LineDisplay_screenTimeOut = String(F("4LineDisplay_screenTimeOut"));
String str4LineDisplay_flip = String(F("4LineDisplay_flip"));
String str4LineDisplay_sleepMode = String(F("4LineDisplay_sleepMode"));
String str4LineDisplay_clockMode = String(F("4LineDisplay_clockMode"));
if (root[str4LineDisplay_type] != nullptr) newType = (DisplayType)root[str4LineDisplay_type];
if (root[str4LineDisplay_pin] != nullptr) {
newScl = (int)root[str4LineDisplay_pin][0];
newSda = (int)root[str4LineDisplay_pin][1];
}
if (root[F("4LineDisplay_contrast")] != nullptr) newContrast = (int)root[F("4LineDisplay_contrast")];
if (root[F("4LineDisplay_refreshRate")] != nullptr) refreshRate = (int)root[F("4LineDisplay_refreshRate")]*1000;
if (root[F("4LineDisplay_screenTimeOut")] != nullptr) screenTimeout = (int)root[F("4LineDisplay_screenTimeOut")]*1000;
if (root[F("4LineDisplay_flip")] != nullptr) {
String str = root[F("4LineDisplay_flip")]; // checkbox -> off or on
newFlip = (bool)(str!="off"); // off is guaranteed to be present
if (root[str4LineDisplay_contrast] != nullptr) {
contrast = (int)root[str4LineDisplay_contrast];
setContrast(contrast);
}
if (root[F("4LineDisplay_sleepMode")] != nullptr) {
String str = root[F("4LineDisplay_sleepMode")]; // checkbox -> off or on
if (root[str4LineDisplay_refreshRate] != nullptr) refreshRate = (int)root[str4LineDisplay_refreshRate]*1000;
if (root[str4LineDisplay_screenTimeOut] != nullptr) screenTimeout = (int)root[str4LineDisplay_screenTimeOut]*1000;
if (root[str4LineDisplay_flip] != nullptr) {
String str = root[str4LineDisplay_flip]; // checkbox -> off or on
flip = (bool)(str!="off"); // off is guaranteed to be present
setFlipMode(flip);
}
if (root[str4LineDisplay_sleepMode] != nullptr) {
String str = root[str4LineDisplay_sleepMode]; // checkbox -> off or on
sleepMode = (bool)(str!="off"); // off is guaranteed to be present
}
if (root[F("4LineDisplay_clockMode")] != nullptr) {
String str = root[F("4LineDisplay_clockMode")]; // checkbox -> off or on
if (root[str4LineDisplay_clockMode] != nullptr) {
String str = root[str4LineDisplay_clockMode]; // checkbox -> off or on
clockMode = (bool)(str!="off"); // off is guaranteed to be present
setLineThreeType(clockMode ? FLD_LINE_3_MODE : FLD_LINE_3_BRIGHTNESS);
}
if (flip!=newFlip || contrast!=newContrast || sclPin!=newScl || sdaPin!=newSda || type!=newType) {
if (sclPin!=newScl || sdaPin!=newSda || type!=newType) {
if (type==SSD1306) delete (static_cast<U8X8_SSD1306_128X32_UNIVISION_HW_I2C*>(u8x8));
if (type==SH1106) delete (static_cast<U8X8_SH1106_128X64_WINSTAR_HW_I2C*>(u8x8));
pinManager.deallocatePin(sclPin);
@ -610,11 +670,10 @@ class FourLineDisplayUsermod : public Usermod {
sclPin = newScl;
sdaPin = newSda;
type = newType;
contrast = newContrast;
flip = newFlip;
lineHeight = type==SH1106 ? 2 : 1;
setup();
}
if (!wakeDisplay()) redraw(true);
}
/*
@ -655,16 +714,20 @@ class FourLineDisplayUsermod : public Usermod {
*/
void readFromConfig(JsonObject& root) {
JsonObject top = root[F("4LineDisplay")];
sclPin = top["pin"][0] | FLD_PIN_SCL;
sdaPin = top["pin"][1] | FLD_PIN_SDA;
type = top["type"] | SSD1306;
lineHeight = type==SH1106 ? 2 : 1;
flip = top[F("flip")] | false ;
contrast = top[F("contrast")] | 10;
refreshRate = int(top[F("refreshRate")])*1000 | USER_LOOP_REFRESH_RATE_MS;
screenTimeout = int(top[F("screenTimeOut")])*1000 | SCREEN_TIMEOUT_MS;
sleepMode = top[F("sleepMode")] | true;
clockMode = top[F("clockMode")] | false;
if (!top.isNull() && top["pin"] != nullptr) {
sclPin = top["pin"][0] | FLD_PIN_SCL;
sdaPin = top["pin"][1] | FLD_PIN_SDA;
type = top["type"] | SSD1306;
lineHeight = type==SH1106 ? 2 : 1;
flip = top[F("flip")] | false ;
contrast = top[F("contrast")] | 10;
refreshRate = int(top[F("refreshRate")])*1000 | USER_LOOP_REFRESH_RATE_MS;
screenTimeout = int(top[F("screenTimeOut")])*1000 | SCREEN_TIMEOUT_MS;
sleepMode = top[F("sleepMode")] | true;
clockMode = top[F("clockMode")] | false;
} else {
DEBUG_PRINTLN(F("No config found. (Using defaults.)"));
}
}
/*
@ -674,5 +737,4 @@ class FourLineDisplayUsermod : public Usermod {
uint16_t getId() {
return USERMOD_ID_FOUR_LINE_DISP;
}
};