diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index 63e20842bb6d..f297951d828a 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -1334,14 +1334,19 @@ void setup() { SETUP_RUN(card.mount()); // Mount media with settings before first_load #endif - SETUP_RUN(settings.first_load()); // Load data from EEPROM if available (or use defaults) - // This also updates variables in the planner, elsewhere + // Prepare some LCDs to display early + #if HAS_EARLY_LCD_SETTINGS + SETUP_RUN(settings.load_lcd_state()); + #endif #if ALL(HAS_WIRED_LCD, SHOW_BOOTSCREEN) SETUP_RUN(ui.show_bootscreen()); const millis_t bootscreen_ms = millis(); #endif + SETUP_RUN(settings.first_load()); // Load data from EEPROM if available (or use defaults) + // This also updates variables in the planner, elsewhere + #if ENABLED(PROBE_TARE) SETUP_RUN(probe.tare_init()); #endif diff --git a/Marlin/src/inc/Conditionals_post.h b/Marlin/src/inc/Conditionals_post.h index d43132e13c82..bdaba1570a68 100644 --- a/Marlin/src/inc/Conditionals_post.h +++ b/Marlin/src/inc/Conditionals_post.h @@ -3384,6 +3384,10 @@ #define LCD_HEIGHT TERN(IS_ULTIPANEL, 4, 2) #endif #endif + // Prepare the LCD to show the bootscreen early in setup + #if ENABLED(SHOW_BOOTSCREEN) && ANY(HAS_LCD_CONTRAST, HAS_LCD_BRIGHTNESS) + #define HAS_EARLY_LCD_SETTINGS 1 + #endif #endif #if BUTTONS_EXIST(EN1, EN2, ENC) diff --git a/Marlin/src/module/settings.cpp b/Marlin/src/module/settings.cpp index a9f2f888bff4..d4467b76877d 100644 --- a/Marlin/src/module/settings.cpp +++ b/Marlin/src/module/settings.cpp @@ -778,11 +778,13 @@ void MarlinSettings::postprocess() { #define TWO_BYTE_HASH(A,B) uint16_t((uint16_t(A ^ 0xC3) << 4) ^ (uint16_t(B ^ 0xC3) << 12)) + #define EEPROM_OFFSETOF(FIELD) (EEPROM_OFFSET + offsetof(SettingsData, FIELD)) + #if ENABLED(DEBUG_EEPROM_READWRITE) #define _FIELD_TEST(FIELD) \ SERIAL_ECHOLNPGM("Field: " STRINGIFY(FIELD)); \ EEPROM_ASSERT( \ - eeprom_error || eeprom_index == offsetof(SettingsData, FIELD) + EEPROM_OFFSET, \ + eeprom_error || eeprom_index == EEPROM_OFFSETOF(FIELD), \ "Field " STRINGIFY(FIELD) " mismatch." \ ) #else @@ -797,7 +799,7 @@ void MarlinSettings::postprocess() { #define EEPROM_READ_ALWAYS(V...) EEPROM_READ_ALWAYS_(V) #endif - const char version[4] = EEPROM_VERSION; + constexpr char version_str[4] = EEPROM_VERSION; #if ENABLED(EEPROM_INIT_NOW) constexpr uint32_t strhash32(const char *s, const uint32_t h=0) { @@ -827,14 +829,14 @@ void MarlinSettings::postprocess() { */ bool MarlinSettings::save() { float dummyf = 0; - MString<3> ver(F("ERR")); if (!EEPROM_START(EEPROM_OFFSET)) return false; EEPROM_Error eeprom_error = ERR_EEPROM_NOERR; // Write or Skip version. (Flash doesn't allow rewrite without erase.) - TERN(FLASH_EEPROM_EMULATION, EEPROM_SKIP, EEPROM_WRITE)(ver); + constexpr char dummy_version[] = "ERR"; + TERN(FLASH_EEPROM_EMULATION, EEPROM_SKIP, EEPROM_WRITE)(dummy_version); #if ENABLED(EEPROM_INIT_NOW) EEPROM_SKIP(build_hash); // Skip the hash slot which will be written later @@ -1765,7 +1767,7 @@ void MarlinSettings::postprocess() { // Write the EEPROM header eeprom_index = EEPROM_OFFSET; - EEPROM_WRITE(version); + EEPROM_WRITE(version_str); #if ENABLED(EEPROM_INIT_NOW) EEPROM_WRITE(build_hash); #endif @@ -1797,29 +1799,39 @@ void MarlinSettings::postprocess() { return success; } + EEPROM_Error MarlinSettings::check_version() { + if (!EEPROM_START(EEPROM_OFFSET)) return ERR_EEPROM_NOPROM; + char stored_ver[4]; + EEPROM_READ_ALWAYS(stored_ver); + + // Version has to match or defaults are used + if (strncmp(stored_ver, version_str, 3) != 0) { + if (stored_ver[3] != '\0') { + stored_ver[0] = '?'; + stored_ver[1] = '\0'; + } + DEBUG_ECHO_MSG("EEPROM version mismatch (EEPROM=", stored_ver, " Marlin=" EEPROM_VERSION ")"); + return ERR_EEPROM_VERSION; + } + return ERR_EEPROM_NOERR; + } + /** * M501 - Retrieve Configuration */ EEPROM_Error MarlinSettings::_load() { EEPROM_Error eeprom_error = ERR_EEPROM_NOERR; - if (!EEPROM_START(EEPROM_OFFSET)) return eeprom_error; - - char stored_ver[4]; - EEPROM_READ_ALWAYS(stored_ver); + const EEPROM_Error check = check_version(); + if (check == ERR_EEPROM_VERSION) return eeprom_error; uint16_t stored_crc; do { // A block to break out of on error // Version has to match or defaults are used - if (strncmp(version, stored_ver, 3) != 0) { - if (stored_ver[3] != '\0') { - stored_ver[0] = '?'; - stored_ver[1] = '\0'; - } - DEBUG_ECHO_MSG("EEPROM version mismatch (EEPROM=", stored_ver, " Marlin=" EEPROM_VERSION ")"); - eeprom_error = ERR_EEPROM_VERSION; + if (check == ERR_EEPROM_VERSION) { + eeprom_error = check; break; } @@ -2880,8 +2892,7 @@ void MarlinSettings::postprocess() { } else if (!validating) { DEBUG_ECHO_START(); - DEBUG_ECHO(version); - DEBUG_ECHOLNPGM(" stored settings retrieved (", eeprom_total, " bytes; crc ", working_crc, ")"); + DEBUG_ECHOLN(version_str, F(" stored settings retrieved ("), eeprom_total, F(" bytes; crc "), working_crc, ')'); TERN_(HOST_EEPROM_CHITCHAT, hostui.notify(F("Stored settings retrieved"))); } @@ -2967,6 +2978,26 @@ void MarlinSettings::postprocess() { return (err == ERR_EEPROM_NOERR); } + #if HAS_EARLY_LCD_SETTINGS + + #if HAS_LCD_CONTRAST + void MarlinSettings::load_contrast() { + uint8_t lcd_contrast; EEPROM_START(EEPROM_OFFSETOF(lcd_contrast)); EEPROM_READ(lcd_contrast); + DEBUG_ECHOLNPGM("LCD Contrast: ", lcd_contrast); + ui.contrast = lcd_contrast; + } + #endif + + #if HAS_LCD_BRIGHTNESS + void MarlinSettings::load_brightness() { + uint8_t lcd_brightness; EEPROM_START(EEPROM_OFFSETOF(lcd_brightness)); EEPROM_READ(lcd_brightness); + DEBUG_ECHOLNPGM("LCD Brightness: ", lcd_brightness); + ui.brightness = lcd_brightness; + } + #endif + + #endif // HAS_EARLY_LCD_SETTINGS + bool MarlinSettings::load() { if (validate()) { const EEPROM_Error err = _load(); @@ -3117,6 +3148,25 @@ void MarlinSettings::postprocess() { #endif // !EEPROM_SETTINGS +#if HAS_EARLY_LCD_SETTINGS + + void MarlinSettings::load_lcd_state() { + if (TERN0(EEPROM_SETTINGS, check_version() == ERR_EEPROM_NOERR)) { + #if ENABLED(EEPROM_SETTINGS) + TERN_(HAS_LCD_CONTRAST, load_contrast()); + TERN_(HAS_LCD_BRIGHTNESS, load_brightness()); + #endif + } + else { + TERN_(HAS_LCD_CONTRAST, ui.contrast = LCD_CONTRAST_DEFAULT); + TERN_(HAS_LCD_BRIGHTNESS, ui.brightness = LCD_BRIGHTNESS_DEFAULT); + } + TERN_(HAS_LCD_CONTRAST, ui.refresh_contrast()); + TERN_(HAS_LCD_BRIGHTNESS, ui.refresh_brightness()); + } + +#endif // HAS_EARLY_LCD_SETTINGS + /** * M502 - Reset Configuration */ diff --git a/Marlin/src/module/settings.h b/Marlin/src/module/settings.h index b7c5210db5b2..f181e4014dae 100644 --- a/Marlin/src/module/settings.h +++ b/Marlin/src/module/settings.h @@ -34,7 +34,8 @@ ERR_EEPROM_VERSION, ERR_EEPROM_SIZE, ERR_EEPROM_CRC, - ERR_EEPROM_CORRUPT + ERR_EEPROM_CORRUPT, + ERR_EEPROM_NOPROM }; #endif @@ -66,11 +67,24 @@ class MarlinSettings { static bool load(); // Return 'true' if data was loaded ok static bool validate(); // Return 'true' if EEPROM data is ok + static EEPROM_Error check_version(); + static void first_load() { static bool loaded = false; if (!loaded && load()) loaded = true; } + #if HAS_EARLY_LCD_SETTINGS + // Special cases for LCD contrast and brightness, so + // some LCDs can display bootscreens earlier in setup(). + #if HAS_LCD_CONTRAST + static void load_contrast(); + #endif + #if HAS_LCD_BRIGHTNESS + static void load_brightness(); + #endif + #endif + #if ENABLED(AUTO_BED_LEVELING_UBL) // Eventually make these available if any leveling system // That can store is enabled static uint16_t meshes_start_index(); @@ -93,6 +107,10 @@ class MarlinSettings { #endif // !EEPROM_SETTINGS + #if HAS_EARLY_LCD_SETTINGS + static void load_lcd_state(); + #endif + #if DISABLED(DISABLE_M503) static void report(const bool forReplay=false); #else