diff --git a/Marlin/src/HAL/HAL_AVR/persistent_store_impl.cpp b/Marlin/src/HAL/HAL_AVR/persistent_store_impl.cpp index bee8caf833..9d5ddd1bd7 100644 --- a/Marlin/src/HAL/HAL_AVR/persistent_store_impl.cpp +++ b/Marlin/src/HAL/HAL_AVR/persistent_store_impl.cpp @@ -38,10 +38,10 @@ bool write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc) { return false; } -bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc) { +bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc, const bool writing/*=true*/) { do { uint8_t c = eeprom_read_byte((unsigned char*)pos); - *value = c; + if (writing) *value = c; crc16(crc, &c, 1); pos++; value++; diff --git a/Marlin/src/HAL/HAL_DUE/persistent_store_impl.cpp b/Marlin/src/HAL/HAL_DUE/persistent_store_impl.cpp index 0239a71638..f5276e045c 100644 --- a/Marlin/src/HAL/HAL_DUE/persistent_store_impl.cpp +++ b/Marlin/src/HAL/HAL_DUE/persistent_store_impl.cpp @@ -43,10 +43,10 @@ bool write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc) { return false; } -bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc) { +bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc, const bool writing/*=true*/) { do { uint8_t c = eeprom_read_byte((unsigned char*)pos); - *value = c; + if (writing) *value = c; crc16(crc, &c, 1); pos++; value++; diff --git a/Marlin/src/HAL/HAL_LPC1768/persistent_store_impl.cpp b/Marlin/src/HAL/HAL_LPC1768/persistent_store_impl.cpp index 82fd567ab9..f2f33ba9f1 100644 --- a/Marlin/src/HAL/HAL_LPC1768/persistent_store_impl.cpp +++ b/Marlin/src/HAL/HAL_LPC1768/persistent_store_impl.cpp @@ -128,7 +128,7 @@ bool write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc) { return (bytes_written != size); // return true for any error } -bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc) { +bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc, const bool writing/*=true*/) { UINT bytes_read = 0; FRESULT s; s = f_lseek(&eeprom_file, pos); @@ -140,7 +140,15 @@ bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc) { SERIAL_PROTOCOLLNPAIR(" f_lseek()=", (int)s); return true; } - s = f_read(&eeprom_file, (void *)value, size, &bytes_read); + if (writing) { + s = f_read(&eeprom_file, (void *)value, size, &bytes_read); + crc16(crc, value, size); + } + else { + uint8_t temp[size]; + s = f_read(&eeprom_file, (void *)temp, size, &bytes_read); + crc16(crc, temp, size); + } if (s) { SERIAL_PROTOCOLPAIR(" read_data(", pos); // This extra chit-chat goes away soon. But it is helpful SERIAL_PROTOCOLPAIR(",", (int)value); // right now to see errors that are happening in the @@ -151,7 +159,6 @@ bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc) { SERIAL_PROTOCOLLNPAIR("\n bytes_read=", bytes_read); return true; } - crc16(crc, value, size); pos = pos + size; return bytes_read != size; // return true for any error } diff --git a/Marlin/src/HAL/HAL_STM32F1/persistent_store_flash.cpp b/Marlin/src/HAL/HAL_STM32F1/persistent_store_flash.cpp index d8b013ae6c..dff5122964 100644 --- a/Marlin/src/HAL/HAL_STM32F1/persistent_store_flash.cpp +++ b/Marlin/src/HAL/HAL_STM32F1/persistent_store_flash.cpp @@ -93,13 +93,13 @@ bool write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc) { return true; } -void read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc) { +void read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc, const bool writing/*=true*/) { for (uint16_t i = 0; i < size; i++) { byte* accessPoint = (byte*)(pageBase + pos + i); - value[i] = *accessPoint; + uint8_t c = *accessPoint; + if (writing) value[i] = c; + crc16(crc, &c, 1); } - - crc16(crc, value, size); pos += ((size + 1) & ~1); } diff --git a/Marlin/src/HAL/HAL_STM32F1/persistent_store_impl.cpp b/Marlin/src/HAL/HAL_STM32F1/persistent_store_impl.cpp index b8d7df7e6e..f5c6ec58bd 100644 --- a/Marlin/src/HAL/HAL_STM32F1/persistent_store_impl.cpp +++ b/Marlin/src/HAL/HAL_STM32F1/persistent_store_impl.cpp @@ -62,7 +62,6 @@ bool access_start() { return true; } - bool access_finish(){ if (!card.cardOK) return false; int16_t bytes_written = 0; @@ -81,11 +80,12 @@ bool write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc) { return false; } -bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc) { +bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc, const bool writing/*=true*/) { for (int i = 0; i < size; i++) { - value[i] = HAL_STM32F1_eeprom_content [pos + i]; + uint8_t c = HAL_STM32F1_eeprom_content[pos + i]; + if (writing) value[i] = c`; + crc16(crc, &c, 1); } - crc16(crc, value, size); pos += size; return false; } diff --git a/Marlin/src/HAL/HAL_TEENSY35_36/persistent_store_impl.cpp b/Marlin/src/HAL/HAL_TEENSY35_36/persistent_store_impl.cpp index f78a8ec4cd..be0604dae2 100644 --- a/Marlin/src/HAL/HAL_TEENSY35_36/persistent_store_impl.cpp +++ b/Marlin/src/HAL/HAL_TEENSY35_36/persistent_store_impl.cpp @@ -38,10 +38,10 @@ bool write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc) { return false; } -bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc) { +bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc, const bool writing/*=true*/) { do { uint8_t c = eeprom_read_byte((unsigned char*)pos); - *value = c; + if (writing) *value = c; crc16(crc, &c, 1); pos++; value++; diff --git a/Marlin/src/HAL/persistent_store_api.h b/Marlin/src/HAL/persistent_store_api.h index ada9e0d88b..642e5712f3 100644 --- a/Marlin/src/HAL/persistent_store_api.h +++ b/Marlin/src/HAL/persistent_store_api.h @@ -10,7 +10,7 @@ namespace PersistentStore { bool access_start(); bool access_finish(); bool write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc); -bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc); +bool read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc, const bool writing=true); } // PersistentStore } // HAL diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp index 8d9a98025a..96a827fad2 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp @@ -309,12 +309,6 @@ void unified_bed_leveling::G29() { - if (!settings.calc_num_meshes()) { - SERIAL_PROTOCOLLNPGM("?Enable EEPROM and init with"); - SERIAL_PROTOCOLLNPGM("M502, M500, M501 in that order.\n"); - return; - } - if (g29_parameter_parsing()) return; // abort if parsing the simple parameters causes a problem, // Check for commands that require the printer to be homed @@ -1272,8 +1266,8 @@ SERIAL_EOL(); safe_delay(50); - SERIAL_PROTOCOLPAIR("Meshes go from ", hex_address((void*)settings.get_start_of_meshes())); - SERIAL_PROTOCOLLNPAIR(" to ", hex_address((void*)settings.get_end_of_meshes())); + SERIAL_PROTOCOLPAIR("Meshes go from ", hex_address((void*)settings.meshes_start_index())); + SERIAL_PROTOCOLLNPAIR(" to ", hex_address((void*)settings.meshes_end_index())); safe_delay(50); SERIAL_PROTOCOLLNPAIR("sizeof(ubl) : ", (int)sizeof(ubl)); @@ -1282,7 +1276,7 @@ SERIAL_EOL(); safe_delay(25); - SERIAL_PROTOCOLLNPAIR("EEPROM free for UBL: ", hex_address((void*)(settings.get_end_of_meshes() - settings.get_start_of_meshes()))); + SERIAL_PROTOCOLLNPAIR("EEPROM free for UBL: ", hex_address((void*)(settings.meshes_end_index() - settings.meshes_start_index()))); safe_delay(50); SERIAL_PROTOCOLPAIR("EEPROM can hold ", settings.calc_num_meshes()); diff --git a/Marlin/src/gcode/eeprom/M500-M503.cpp b/Marlin/src/gcode/eeprom/M500-M504.cpp similarity index 87% rename from Marlin/src/gcode/eeprom/M500-M503.cpp rename to Marlin/src/gcode/eeprom/M500-M504.cpp index 45faa10179..74140eee15 100644 --- a/Marlin/src/gcode/eeprom/M500-M503.cpp +++ b/Marlin/src/gcode/eeprom/M500-M504.cpp @@ -55,3 +55,15 @@ void GcodeSuite::M502() { } #endif // !DISABLE_M503 + +#if ENABLED(EEPROM_SETTINGS) + /** + * M504: Validate EEPROM Contents + */ + void GcodeSuite::M504() { + if (settings.validate()) { + SERIAL_ECHO_START(); + SERIAL_ECHOLNPGM("EEPROM OK"); + } + } +#endif diff --git a/Marlin/src/gcode/gcode.cpp b/Marlin/src/gcode/gcode.cpp index 31d628d859..70e396f4ab 100644 --- a/Marlin/src/gcode/gcode.cpp +++ b/Marlin/src/gcode/gcode.cpp @@ -610,6 +610,9 @@ void GcodeSuite::process_parsed_command() { #if DISABLED(DISABLE_M503) case 503: M503(); break; // M503: print settings currently in memory #endif + #if ENABLED(EEPROM_SETTINGS) + case 504: M504(); break; // M504: Validate EEPROM contents + #endif #if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED) case 540: M540(); break; // M540: Set abort on endstop hit for SD printing diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h index 377c948b68..47142cae9b 100644 --- a/Marlin/src/gcode/gcode.h +++ b/Marlin/src/gcode/gcode.h @@ -271,8 +271,8 @@ public: static WorkspacePlane workspace_plane; #endif + #define MAX_COORDINATE_SYSTEMS 9 #if ENABLED(CNC_COORDINATE_SYSTEMS) - #define MAX_COORDINATE_SYSTEMS 9 static int8_t active_coordinate_system; static float coordinate_system[MAX_COORDINATE_SYSTEMS][XYZ]; static bool select_coordinate_system(const int8_t _new); @@ -681,6 +681,9 @@ private: #if DISABLED(DISABLE_M503) static void M503(); #endif + #if ENABLED(EEPROM_SETTINGS) + static void M504(); + #endif #if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED) static void M540(); diff --git a/Marlin/src/lcd/ultralcd.cpp b/Marlin/src/lcd/ultralcd.cpp index 550c712630..553ecdf4d4 100644 --- a/Marlin/src/lcd/ultralcd.cpp +++ b/Marlin/src/lcd/ultralcd.cpp @@ -2309,7 +2309,6 @@ void kill_screen(const char* lcd_msg) { MENU_BACK(MSG_UBL_LEVEL_BED); if (!WITHIN(ubl_storage_slot, 0, a - 1)) { STATIC_ITEM(MSG_NO_STORAGE); - STATIC_ITEM(MSG_INIT_EEPROM); } else { MENU_ITEM_EDIT(int3, MSG_UBL_STORAGE_SLOT, &ubl_storage_slot, 0, a - 1); diff --git a/Marlin/src/module/configuration_store.cpp b/Marlin/src/module/configuration_store.cpp index f872dd2cb1..6c4d21f96c 100644 --- a/Marlin/src/module/configuration_store.cpp +++ b/Marlin/src/module/configuration_store.cpp @@ -36,174 +36,25 @@ * */ +// Change EEPROM version if the structure changes #define EEPROM_VERSION "V48" - -// Change EEPROM version if these are changed: #define EEPROM_OFFSET 100 -/** - * V48 EEPROM Layout: - * - * 100 Version (char x4) - * 104 EEPROM CRC16 (uint16_t) - * - * 106 E_STEPPERS (uint8_t) - * 107 M92 XYZE planner.axis_steps_per_mm (float x4 ... x8) + 64 - * 123 M203 XYZE planner.max_feedrate_mm_s (float x4 ... x8) + 64 - * 139 M201 XYZE planner.max_acceleration_mm_per_s2 (uint32_t x4 ... x8) + 64 - * 155 M204 P planner.acceleration (float) - * 159 M204 R planner.retract_acceleration (float) - * 163 M204 T planner.travel_acceleration (float) - * 167 M205 S planner.min_feedrate_mm_s (float) - * 171 M205 T planner.min_travel_feedrate_mm_s (float) - * 175 M205 B planner.min_segment_time_us (ulong) - * 179 M205 X planner.max_jerk[X_AXIS] (float) - * 183 M205 Y planner.max_jerk[Y_AXIS] (float) - * 187 M205 Z planner.max_jerk[Z_AXIS] (float) - * 191 M205 E planner.max_jerk[E_AXIS] (float) - * 195 M206 XYZ home_offset (float x3) - * 207 M218 XYZ hotend_offset (float x3 per additional hotend) +16 - * - * Global Leveling: 4 bytes - * 219 z_fade_height (float) - * - * MESH_BED_LEVELING: 43 bytes - * 223 M420 S planner.leveling_active (bool) - * 224 mbl.z_offset (float) - * 228 GRID_MAX_POINTS_X (uint8_t) - * 229 GRID_MAX_POINTS_Y (uint8_t) - * 230 G29 S3 XYZ z_values[][] (float x9, up to float x81) +288 - * - * HAS_BED_PROBE: 4 bytes - * 266 M851 zprobe_zoffset (float) - * - * ABL_PLANAR: 36 bytes - * 270 planner.bed_level_matrix (matrix_3x3 = float x9) - * - * AUTO_BED_LEVELING_BILINEAR: 46 bytes - * 306 GRID_MAX_POINTS_X (uint8_t) - * 307 GRID_MAX_POINTS_Y (uint8_t) - * 308 bilinear_grid_spacing (int x2) - * 312 G29 L F bilinear_start (int x2) - * 316 z_values[][] (float x9, up to float x256) +988 - * - * AUTO_BED_LEVELING_UBL: 2 bytes - * 352 G29 A planner.leveling_active (bool) - * 353 G29 S ubl.storage_slot (int8_t) - * - * DELTA: 44 bytes - * 354 M666 H delta_height (float) - * 358 M666 XYZ delta_endstop_adj (float x3) - * 370 M665 R delta_radius (float) - * 374 M665 L delta_diagonal_rod (float) - * 378 M665 S delta_segments_per_second (float) - * 382 M665 B delta_calibration_radius (float) - * 386 M665 X delta_tower_angle_trim[A] (float) - * 390 M665 Y delta_tower_angle_trim[B] (float) - * 394 M665 Z delta_tower_angle_trim[C] (float) - * - * [XYZ]_DUAL_ENDSTOPS: 12 bytes - * 354 M666 X x_endstop_adj (float) - * 358 M666 Y y_endstop_adj (float) - * 362 M666 Z z_endstop_adj (float) - * - * ULTIPANEL: 6 bytes - * 398 M145 S0 H lcd_preheat_hotend_temp (int x2) - * 402 M145 S0 B lcd_preheat_bed_temp (int x2) - * 406 M145 S0 F lcd_preheat_fan_speed (int x2) - * - * PIDTEMP: 82 bytes - * 410 M301 E0 PIDC Kp[0], Ki[0], Kd[0], Kc[0] (float x4) - * 426 M301 E1 PIDC Kp[1], Ki[1], Kd[1], Kc[1] (float x4) - * 442 M301 E2 PIDC Kp[2], Ki[2], Kd[2], Kc[2] (float x4) - * 458 M301 E3 PIDC Kp[3], Ki[3], Kd[3], Kc[3] (float x4) - * 474 M301 E4 PIDC Kp[3], Ki[3], Kd[3], Kc[3] (float x4) - * 490 M301 L lpq_len (int) - * - * PIDTEMPBED: 12 bytes - * 492 M304 PID bedKp, .bedKi, .bedKd (float x3) - * - * DOGLCD: 2 bytes - * 504 M250 C lcd_contrast (uint16_t) - * - * FWRETRACT: 33 bytes - * 506 M209 S autoretract_enabled (bool) - * 507 M207 S retract_length (float) - * 511 M207 F retract_feedrate_mm_s (float) - * 515 M207 Z retract_zlift (float) - * 519 M208 S retract_recover_length (float) - * 523 M208 F retract_recover_feedrate_mm_s (float) - * 527 M207 W swap_retract_length (float) - * 531 M208 W swap_retract_recover_length (float) - * 535 M208 R swap_retract_recover_feedrate_mm_s (float) - * - * Volumetric Extrusion: 21 bytes - * 539 M200 D parser.volumetric_enabled (bool) - * 540 M200 T D planner.filament_size (float x5) (T0..4) - * - * HAS_TRINAMIC: 22 bytes - * 560 M906 X Stepper X current (uint16_t) - * 562 M906 Y Stepper Y current (uint16_t) - * 564 M906 Z Stepper Z current (uint16_t) - * 566 M906 X2 Stepper X2 current (uint16_t) - * 568 M906 Y2 Stepper Y2 current (uint16_t) - * 570 M906 Z2 Stepper Z2 current (uint16_t) - * 572 M906 E0 Stepper E0 current (uint16_t) - * 574 M906 E1 Stepper E1 current (uint16_t) - * 576 M906 E2 Stepper E2 current (uint16_t) - * 578 M906 E3 Stepper E3 current (uint16_t) - * 580 M906 E4 Stepper E4 current (uint16_t) - * - * SENSORLESS_HOMING: 4 bytes - * 582 M914 X Stepper X and X2 threshold (int16_t) - * 584 M914 Y Stepper Y and Y2 threshold (int16_t) - * - * LIN_ADVANCE: 8 bytes - * 586 M900 K extruder_advance_k (float) - * 590 M900 WHD advance_ed_ratio (float) - * - * HAS_MOTOR_CURRENT_PWM: - * 594 M907 X Stepper XY current (uint32_t) - * 598 M907 Z Stepper Z current (uint32_t) - * 602 M907 E Stepper E current (uint32_t) - * - * CNC_COORDINATE_SYSTEMS: 108 bytes - * 606 G54-G59.3 coordinate_system (float x 27) - * - * SKEW_CORRECTION: 12 bytes - * 714 M852 I planner.xy_skew_factor (float) - * 718 M852 J planner.xz_skew_factor (float) - * 722 M852 K planner.yz_skew_factor (float) - * - * ADVANCED_PAUSE_FEATURE: 40 bytes - * 726 M603 T U filament_change_unload_length (float x 5) (T0..4) - * 746 M603 T L filament_change_load_length (float x 5) (T0..4) - * - * 766 Minimum end-point - * 2295 (766 + 208 + 36 + 9 + 288 + 988) Maximum end-point - * - * ======================================================================== - * meshes_begin (between max and min end-point, directly above) - * -- MESHES -- - * meshes_end - * -- MAT (Mesh Allocation Table) -- 128 bytes (placeholder size) - * mat_end = E2END (0xFFF) - * - */ +// Check the integrity of data offsets. +// Can be disabled for production build. +//#define DEBUG_EEPROM_READWRITE + #include "configuration_store.h" - -MarlinSettings settings; - #include "endstops.h" #include "planner.h" #include "stepper.h" #include "temperature.h" #include "../lcd/ultralcd.h" #include "../core/language.h" +#include "../libs/vector_3.h" +#include "../gcode/gcode.h" #include "../Marlin.h" -#include "../gcode/parser.h" - #if HAS_LEVELING #include "../feature/bedlevel/bedlevel.h" #endif @@ -220,13 +71,198 @@ MarlinSettings settings; #include "../feature/fwretract.h" #endif -#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT) - float new_z_fade_height; -#endif +typedef struct PID { float Kp, Ki, Kd; } PID; +typedef struct PIDC { float Kp, Ki, Kd, Kc; } PIDC; + +/** + * Current EEPROM Layout + * + * Keep this data structure up to date so + * EEPROM size is known at compile time! + */ +typedef struct SettingsDataStruct { + char version[4]; // Vnn\0 + uint16_t crc; // Data Checksum + + // + // DISTINCT_E_FACTORS + // + uint8_t esteppers; // XYZE_N - XYZ + + float planner_axis_steps_per_mm[XYZE_N], // M92 XYZE planner.axis_steps_per_mm[XYZE_N] + planner_max_feedrate_mm_s[XYZE_N]; // M203 XYZE planner.max_feedrate_mm_s[XYZE_N] + uint32_t planner_max_acceleration_mm_per_s2[XYZE_N]; // M201 XYZE planner.max_acceleration_mm_per_s2[XYZE_N] + float planner_acceleration, // M204 P planner.acceleration + planner_retract_acceleration, // M204 R planner.retract_acceleration + planner_travel_acceleration, // M204 T planner.travel_acceleration + planner_min_feedrate_mm_s, // M205 S planner.min_feedrate_mm_s + planner_min_travel_feedrate_mm_s; // M205 T planner.min_travel_feedrate_mm_s + uint32_t planner_min_segment_time_us; // M205 B planner.min_segment_time_us + float planner_max_jerk[XYZE]; // M205 XYZE planner.max_jerk[XYZE] + + float home_offset[XYZ]; // M206 XYZ + + #if HOTENDS > 1 + float hotend_offset[XYZ][HOTENDS - 1]; // M218 XYZ + #endif + + // + // ENABLE_LEVELING_FADE_HEIGHT + // + float planner_z_fade_height; // M420 Zn planner.z_fade_height + + // + // MESH_BED_LEVELING + // + bool mbl_has_mesh; // mbl.has_mesh + float mbl_z_offset; // mbl.z_offset + uint8_t mesh_num_x, mesh_num_y; // GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y + #if ENABLED(MESH_BED_LEVELING) + float mbl_z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; // mbl.z_values + #else + float mbl_z_values[3][3]; + #endif + + // + // HAS_BED_PROBE + // + float zprobe_zoffset; // M851 Z + + // + // ABL_PLANAR + // + matrix_3x3 planner_bed_level_matrix; // planner.bed_level_matrix + + // + // AUTO_BED_LEVELING_BILINEAR + // + uint8_t grid_max_x, grid_max_y; // GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y + int bilinear_grid_spacing[2], + bilinear_start[2]; // G29 L F + #if ENABLED(AUTO_BED_LEVELING_BILINEAR) + float z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; // G29 + #else + float z_values[3][3]; + #endif + + // + // AUTO_BED_LEVELING_UBL + // + bool planner_leveling_active; // M420 S planner.leveling_active + int8_t ubl_storage_slot; // ubl.storage_slot + + // + // DELTA / [XYZ]_DUAL_ENDSTOPS + // + #if ENABLED(DELTA) + float delta_height, // M666 H + delta_endstop_adj[ABC], // M666 XYZ + delta_radius, // M665 R + delta_diagonal_rod, // M665 L + delta_segments_per_second, // M665 S + delta_calibration_radius, // M665 B + delta_tower_angle_trim[ABC]; // M665 XYZ + #elif ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS) + float x_endstop_adj, // M666 X + y_endstop_adj, // M666 Y + z_endstop_adj; // M666 Z + float xyz_dual_reserved[8]; + #else + float xyz_dual_placeholder[11]; + #endif + + // + // ULTIPANEL + // + int lcd_preheat_hotend_temp[2], // M145 S0 H + lcd_preheat_bed_temp[2], // M145 S0 B + lcd_preheat_fan_speed[2]; // M145 S0 F + + // + // PIDTEMP + // + PIDC hotendPID[MAX_EXTRUDERS]; // M301 En PIDC / M303 En U + + int lpq_len; // M301 L + + // + // PIDTEMPBED + // + PID bedPID; // M304 PID / M303 E-1 U + + // + // HAS_LCD_CONTRAST + // + uint16_t lcd_contrast; // M250 C + + // + // FWRETRACT + // + bool autoretract_enabled; // M209 S + float retract_length, // M207 S + retract_feedrate_mm_s, // M207 F + retract_zlift, // M207 Z + retract_recover_length, // M208 S + retract_recover_feedrate_mm_s, // M208 F + swap_retract_length, // M207 W + swap_retract_recover_length, // M208 W + swap_retract_recover_feedrate_mm_s; // M208 R + + // + // !NO_VOLUMETRIC + // + bool parser_volumetric_enabled; // M200 D parser.volumetric_enabled + float planner_filament_size[MAX_EXTRUDERS]; // M200 T D planner.filament_size[] + + // + // HAS_TRINAMIC + // + uint16_t tmc_stepper_current[11]; // M906 X Y Z X2 Y2 Z2 E0 E1 E2 E3 E4 + int16_t tmc_sgt[2]; // M914 X Y + + // + // LIN_ADVANCE + // + float planner_extruder_advance_k, // M900 K planner.extruder_advance_k + planner_advance_ed_ratio; // M900 WHD planner.advance_ed_ratio + + // + // HAS_MOTOR_CURRENT_PWM + // + uint32_t motor_current_setting[XYZ]; // M907 X Z E + + // + // CNC_COORDINATE_SYSTEMS + // + float coordinate_system[MAX_COORDINATE_SYSTEMS][XYZ]; // G54-G59.3 + + // + // SKEW_CORRECTION + // + float planner_xy_skew_factor, // M852 I planner.xy_skew_factor + planner_xz_skew_factor, // M852 J planner.xz_skew_factor + planner_yz_skew_factor; // M852 K planner.yz_skew_factor + + // + // ADVANCED_PAUSE_FEATURE + // + float filament_change_unload_length[MAX_EXTRUDERS], // M603 T U + filament_change_load_length[MAX_EXTRUDERS]; // M603 T L + +} SettingsData; + +MarlinSettings settings; + +uint16_t MarlinSettings::datasize() { return sizeof(SettingsData); } /** * Post-process after Retrieve or Reset */ + +#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT) + float new_z_fade_height; +#endif + void MarlinSettings::postprocess() { const float oldpos[] = { current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] }; @@ -289,16 +325,32 @@ void MarlinSettings::postprocess() { #define EEPROM_FINISH() HAL::PersistentStore::access_finish() #define EEPROM_SKIP(VAR) eeprom_index += sizeof(VAR) #define EEPROM_WRITE(VAR) HAL::PersistentStore::write_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR), &working_crc) - #define EEPROM_READ(VAR) HAL::PersistentStore::read_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR), &working_crc) - #define EEPROM_ASSERT(TST,ERR) if (!(TST)) do{ SERIAL_ERROR_START(); SERIAL_ERRORLNPGM(ERR); eeprom_read_error = true; }while(0) + #define EEPROM_READ(VAR) HAL::PersistentStore::read_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR), &working_crc, !validating) + #define EEPROM_READ_ALWAYS(VAR) HAL::PersistentStore::read_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR), &working_crc) + #define EEPROM_ASSERT(TST,ERR) if (!(TST)) do{ SERIAL_ERROR_START(); SERIAL_ERRORLNPGM(ERR); eeprom_error = true; }while(0) + + #if ENABLED(DEBUG_EEPROM_READWRITE) + #define _FIELD_TEST(FIELD) \ + EEPROM_ASSERT( \ + eeprom_error || eeprom_index == offsetof(SettingsData, FIELD), \ + "Field " STRINGIFY(FIELD) " mismatch." \ + ) + #else + #define _FIELD_TEST(FIELD) NOOP + #endif const char version[4] = EEPROM_VERSION; - bool MarlinSettings::eeprom_error; + bool MarlinSettings::eeprom_error, MarlinSettings::validating; - #if ENABLED(AUTO_BED_LEVELING_UBL) - int16_t MarlinSettings::meshes_begin; - #endif + bool MarlinSettings::size_error(const uint16_t size) { + if (size != datasize()) { + SERIAL_ERROR_START(); + SERIAL_ERRORLNPGM("EEPROM datasize error."); + return true; + } + return false; + } /** * M500 - Store Configuration @@ -321,6 +373,8 @@ void MarlinSettings::postprocess() { working_crc = 0; // clear before first "real data" + _FIELD_TEST(esteppers); + const uint8_t esteppers = COUNT(planner.axis_steps_per_mm) - XYZ; EEPROM_WRITE(esteppers); @@ -335,6 +389,9 @@ void MarlinSettings::postprocess() { EEPROM_WRITE(planner.min_travel_feedrate_mm_s); EEPROM_WRITE(planner.min_segment_time_us); EEPROM_WRITE(planner.max_jerk); + + _FIELD_TEST(home_offset); + #if !HAS_HOME_OFFSET const float home_offset[XYZ] = { 0 }; #endif @@ -384,6 +441,8 @@ void MarlinSettings::postprocess() { for (uint8_t q = mesh_num_x * mesh_num_y; q--;) EEPROM_WRITE(dummy); #endif // MESH_BED_LEVELING + _FIELD_TEST(zprobe_zoffset); + #if !HAS_BED_PROBE const float zprobe_zoffset = 0; #endif @@ -428,6 +487,8 @@ void MarlinSettings::postprocess() { for (uint16_t q = grid_max_x * grid_max_y; q--;) EEPROM_WRITE(dummy); #endif // AUTO_BED_LEVELING_BILINEAR + _FIELD_TEST(planner_leveling_active); + #if ENABLED(AUTO_BED_LEVELING_UBL) EEPROM_WRITE(planner.leveling_active); EEPROM_WRITE(ubl.storage_slot); @@ -440,6 +501,7 @@ void MarlinSettings::postprocess() { // 11 floats for DELTA / [XYZ]_DUAL_ENDSTOPS #if ENABLED(DELTA) + _FIELD_TEST(delta_height); EEPROM_WRITE(delta_height); // 1 float EEPROM_WRITE(delta_endstop_adj); // 3 floats EEPROM_WRITE(delta_radius); // 1 float @@ -449,6 +511,7 @@ void MarlinSettings::postprocess() { EEPROM_WRITE(delta_tower_angle_trim); // 3 floats #elif ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS) + _FIELD_TEST(x_endstop_adj); // Write dual endstops in X, Y, Z order. Unused = 0.0 dummy = 0.0f; #if ENABLED(X_DUAL_ENDSTOPS) @@ -476,6 +539,8 @@ void MarlinSettings::postprocess() { for (uint8_t q = 11; q--;) EEPROM_WRITE(dummy); #endif + _FIELD_TEST(lcd_preheat_hotend_temp); + #if DISABLED(ULTIPANEL) constexpr int lcd_preheat_hotend_temp[2] = { PREHEAT_1_TEMP_HOTEND, PREHEAT_2_TEMP_HOTEND }, lcd_preheat_bed_temp[2] = { PREHEAT_1_TEMP_BED, PREHEAT_2_TEMP_BED }, @@ -525,6 +590,8 @@ void MarlinSettings::postprocess() { EEPROM_WRITE(thermalManager.bedKd); #endif + _FIELD_TEST(lcd_contrast); + #if !HAS_LCD_CONTRAST const uint16_t lcd_contrast = 32; #endif @@ -550,6 +617,7 @@ void MarlinSettings::postprocess() { // // Volumetric & Filament Size // + _FIELD_TEST(parser_volumetric_enabled); #if DISABLED(NO_VOLUMETRICS) EEPROM_WRITE(parser.volumetric_enabled); @@ -560,81 +628,81 @@ void MarlinSettings::postprocess() { EEPROM_WRITE(dummy); } + #else + + const bool volumetric_enabled = false; + dummy = DEFAULT_NOMINAL_FILAMENT_DIA; + EEPROM_WRITE(volumetric_enabled); + for (uint8_t q = MAX_EXTRUDERS; q--;) EEPROM_WRITE(dummy); + #endif + // // Save TMC2130 or TMC2208 Configuration, and placeholder values - uint16_t val; - #if HAS_TRINAMIC - #if X_IS_TRINAMIC - val = stepperX.getCurrent(); + // + _FIELD_TEST(tmc_stepper_current); + uint16_t currents[11] = { + #if HAS_TRINAMIC + #if X_IS_TRINAMIC + stepperX.getCurrent(), + #else + 0, + #endif + #if Y_IS_TRINAMIC + stepperY.getCurrent(), + #else + 0, + #endif + #if Z_IS_TRINAMIC + stepperZ.getCurrent(), + #else + 0, + #endif + #if X2_IS_TRINAMIC + stepperX2.getCurrent(), + #else + 0, + #endif + #if Y2_IS_TRINAMIC + stepperY2.getCurrent(), + #else + 0, + #endif + #if Z2_IS_TRINAMIC + stepperZ2.getCurrent(), + #else + 0, + #endif + #if E0_IS_TRINAMIC + stepperE0.getCurrent(), + #else + 0, + #endif + #if E1_IS_TRINAMIC + stepperE1.getCurrent(), + #else + 0, + #endif + #if E2_IS_TRINAMIC + stepperE2.getCurrent(), + #else + 0, + #endif + #if E3_IS_TRINAMIC + stepperE3.getCurrent(), + #else + 0, + #endif + #if E4_IS_TRINAMIC + stepperE4.getCurrent() + #else + 0 + #endif #else - val = 0; + 0 #endif - EEPROM_WRITE(val); - #if Y_IS_TRINAMIC - val = stepperY.getCurrent(); - #else - val = 0; - #endif - EEPROM_WRITE(val); - #if Z_IS_TRINAMIC - val = stepperZ.getCurrent(); - #else - val = 0; - #endif - EEPROM_WRITE(val); - #if X2_IS_TRINAMIC - val = stepperX2.getCurrent(); - #else - val = 0; - #endif - EEPROM_WRITE(val); - #if Y2_IS_TRINAMIC - val = stepperY2.getCurrent(); - #else - val = 0; - #endif - EEPROM_WRITE(val); - #if Z2_IS_TRINAMIC - val = stepperZ2.getCurrent(); - #else - val = 0; - #endif - EEPROM_WRITE(val); - #if E0_IS_TRINAMIC - val = stepperE0.getCurrent(); - #else - val = 0; - #endif - EEPROM_WRITE(val); - #if E1_IS_TRINAMIC - val = stepperE1.getCurrent(); - #else - val = 0; - #endif - EEPROM_WRITE(val); - #if E2_IS_TRINAMIC - val = stepperE2.getCurrent(); - #else - val = 0; - #endif - EEPROM_WRITE(val); - #if E3_IS_TRINAMIC - val = stepperE3.getCurrent(); - #else - val = 0; - #endif - EEPROM_WRITE(val); - #if E4_IS_TRINAMIC - val = stepperE4.getCurrent(); - #else - val = 0; - #endif - EEPROM_WRITE(val); - #else - val = 0; - for (uint8_t q = 11; q--;) EEPROM_WRITE(val); - #endif + }; + EEPROM_WRITE(currents); // // TMC2130 Sensorless homing threshold @@ -661,7 +729,7 @@ void MarlinSettings::postprocess() { // // Linear Advance // - + _FIELD_TEST(planner_extruder_advance_k); #if ENABLED(LIN_ADVANCE) EEPROM_WRITE(planner.extruder_advance_k); EEPROM_WRITE(planner.advance_ed_ratio); @@ -681,18 +749,18 @@ void MarlinSettings::postprocess() { // // CNC Coordinate Systems // - + _FIELD_TEST(coordinate_system); #if ENABLED(CNC_COORDINATE_SYSTEMS) EEPROM_WRITE(coordinate_system); // 27 floats #else dummy = 0.0f; - for (uint8_t q = 27; q--;) EEPROM_WRITE(dummy); + for (uint8_t q = MAX_COORDINATE_SYSTEMS * XYZ; q--;) EEPROM_WRITE(dummy); #endif // // Skew correction factors // - + _FIELD_TEST(planner_xy_skew_factor); #if ENABLED(SKEW_CORRECTION) EEPROM_WRITE(planner.xy_skew_factor); EEPROM_WRITE(planner.xz_skew_factor); @@ -705,6 +773,7 @@ void MarlinSettings::postprocess() { // // Advanced Pause filament load & unload lengths // + _FIELD_TEST(filament_change_unload_length); #if ENABLED(ADVANCED_PAUSE_FEATURE) for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) { if (q < COUNT(filament_change_unload_length)) dummy = filament_change_unload_length[q]; @@ -719,12 +788,12 @@ void MarlinSettings::postprocess() { for (uint8_t q = MAX_EXTRUDERS * 2; q--;) EEPROM_WRITE(dummy); #endif + // + // Validate CRC and Data Size + // if (!eeprom_error) { - #if ENABLED(EEPROM_CHITCHAT) - const int eeprom_size = eeprom_index; - #endif - - const uint16_t final_crc = working_crc; + const uint16_t eeprom_size = eeprom_index - (EEPROM_OFFSET), + final_crc = working_crc; // Write the EEPROM header eeprom_index = EEPROM_OFFSET; @@ -735,13 +804,18 @@ void MarlinSettings::postprocess() { // Report storage size #if ENABLED(EEPROM_CHITCHAT) SERIAL_ECHO_START(); - SERIAL_ECHOPAIR("Settings Stored (", eeprom_size - (EEPROM_OFFSET)); + SERIAL_ECHOPAIR("Settings Stored (", eeprom_size); SERIAL_ECHOPAIR(" bytes; crc ", (uint32_t)final_crc); SERIAL_ECHOLNPGM(")"); #endif + + eeprom_error |= size_error(eeprom_size); } EEPROM_FINISH(); + // + // UBL Mesh + // #if ENABLED(UBL_SAVE_ACTIVE_ON_M500) if (ubl.storage_slot >= 0) store_mesh(ubl.storage_slot); @@ -753,16 +827,16 @@ void MarlinSettings::postprocess() { /** * M501 - Retrieve Configuration */ - bool MarlinSettings::load() { + bool MarlinSettings::_load() { uint16_t working_crc = 0; EEPROM_START(); char stored_ver[4]; - EEPROM_READ(stored_ver); + EEPROM_READ_ALWAYS(stored_ver); uint16_t stored_crc; - EEPROM_READ(stored_crc); + EEPROM_READ_ALWAYS(stored_crc); // Version has to match or defaults are used if (strncmp(version, stored_ver, 3) != 0) { @@ -776,7 +850,8 @@ void MarlinSettings::postprocess() { SERIAL_ECHOPAIR("(EEPROM=", stored_ver); SERIAL_ECHOLNPGM(" Marlin=" EEPROM_VERSION ")"); #endif - reset(); + if (!validating) reset(); + eeprom_error = true; } else { float dummy = 0; @@ -788,7 +863,7 @@ void MarlinSettings::postprocess() { // Number of esteppers may change uint8_t esteppers; - EEPROM_READ(esteppers); + EEPROM_READ_ALWAYS(esteppers); // // Planner Motion @@ -803,7 +878,7 @@ void MarlinSettings::postprocess() { EEPROM_READ(tmp1); EEPROM_READ(tmp2); EEPROM_READ(tmp3); - LOOP_XYZE_N(i) { + if (!validating) LOOP_XYZE_N(i) { planner.axis_steps_per_mm[i] = i < XYZ + esteppers ? tmp1[i] : def1[i < COUNT(def1) ? i : COUNT(def1) - 1]; planner.max_feedrate_mm_s[i] = i < XYZ + esteppers ? tmp2[i] : def2[i < COUNT(def2) ? i : COUNT(def2) - 1]; planner.max_acceleration_mm_per_s2[i] = i < XYZ + esteppers ? tmp3[i] : def3[i < COUNT(def3) ? i : COUNT(def3) - 1]; @@ -852,21 +927,23 @@ void MarlinSettings::postprocess() { bool leveling_is_on; uint8_t mesh_num_x, mesh_num_y; - EEPROM_READ(leveling_is_on); + EEPROM_READ_ALWAYS(leveling_is_on); EEPROM_READ(dummy); - EEPROM_READ(mesh_num_x); - EEPROM_READ(mesh_num_y); + EEPROM_READ_ALWAYS(mesh_num_x); + EEPROM_READ_ALWAYS(mesh_num_y); #if ENABLED(MESH_BED_LEVELING) - mbl.has_mesh = leveling_is_on; - mbl.z_offset = dummy; + if (!validating) { + mbl.has_mesh = leveling_is_on; + mbl.z_offset = dummy; + } if (mesh_num_x == GRID_MAX_POINTS_X && mesh_num_y == GRID_MAX_POINTS_Y) { // EEPROM data fits the current mesh EEPROM_READ(mbl.z_values); } else { // EEPROM data is stale - mbl.reset(); + if (!validating) mbl.reset(); for (uint16_t q = mesh_num_x * mesh_num_y; q--;) EEPROM_READ(dummy); } #else @@ -894,11 +971,11 @@ void MarlinSettings::postprocess() { // uint8_t grid_max_x, grid_max_y; - EEPROM_READ(grid_max_x); // 1 byte - EEPROM_READ(grid_max_y); // 1 byte + EEPROM_READ_ALWAYS(grid_max_x); // 1 byte + EEPROM_READ_ALWAYS(grid_max_y); // 1 byte #if ENABLED(AUTO_BED_LEVELING_BILINEAR) if (grid_max_x == GRID_MAX_POINTS_X && grid_max_y == GRID_MAX_POINTS_Y) { - set_bed_leveling_enabled(false); + if (!validating) set_bed_leveling_enabled(false); EEPROM_READ(bilinear_grid_spacing); // 2 ints EEPROM_READ(bilinear_start); // 2 ints EEPROM_READ(z_values); // 9 to 256 floats @@ -990,7 +1067,7 @@ void MarlinSettings::postprocess() { EEPROM_READ(dummy); // Kp if (e < HOTENDS && dummy != DUMMY_PID_VALUE) { // do not need to scale PID values as the values in EEPROM are already scaled - PID_PARAM(Kp, e) = dummy; + if (!validating) PID_PARAM(Kp, e) = dummy; EEPROM_READ(PID_PARAM(Ki, e)); EEPROM_READ(PID_PARAM(Kd, e)); #if ENABLED(PID_EXTRUSION_SCALING) @@ -1024,7 +1101,7 @@ void MarlinSettings::postprocess() { #if ENABLED(PIDTEMPBED) EEPROM_READ(dummy); // bedKp if (dummy != DUMMY_PID_VALUE) { - thermalManager.bedKp = dummy; + if (!validating) thermalManager.bedKp = dummy; EEPROM_READ(thermalManager.bedKi); EEPROM_READ(thermalManager.bedKd); } @@ -1069,63 +1146,62 @@ void MarlinSettings::postprocess() { for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) { EEPROM_READ(dummy); - if (q < COUNT(planner.filament_size)) planner.filament_size[q] = dummy; + if (!validating && q < COUNT(planner.filament_size)) + planner.filament_size[q] = dummy; } + #else + + EEPROM_READ(dummyb); + for (uint8_t q=MAX_EXTRUDERS; q--;) EEPROM_READ(dummy); + #endif // // TMC2130 Stepper Current // - - uint16_t val; #if HAS_TRINAMIC + #define SET_CURR(N,Q) stepper##Q.setCurrent(val[N], R_SENSE, HOLD_MULTIPLIER) + uint16_t val[11]; EEPROM_READ(val); - #if X_IS_TRINAMIC - stepperX.setCurrent(val, R_SENSE, HOLD_MULTIPLIER); - #endif - EEPROM_READ(val); - #if Y_IS_TRINAMIC - stepperY.setCurrent(val, R_SENSE, HOLD_MULTIPLIER); - #endif - EEPROM_READ(val); - #if Z_IS_TRINAMIC - stepperZ.setCurrent(val, R_SENSE, HOLD_MULTIPLIER); - #endif - EEPROM_READ(val); - #if X2_IS_TRINAMIC - stepperX2.setCurrent(val, R_SENSE, HOLD_MULTIPLIER); - #endif - EEPROM_READ(val); - #if Y2_IS_TRINAMIC - stepperY2.setCurrent(val, R_SENSE, HOLD_MULTIPLIER); - #endif - EEPROM_READ(val); - #if Z2_IS_TRINAMIC - stepperZ2.setCurrent(val, R_SENSE, HOLD_MULTIPLIER); - #endif - EEPROM_READ(val); - #if E0_IS_TRINAMIC - stepperE0.setCurrent(val, R_SENSE, HOLD_MULTIPLIER); - #endif - EEPROM_READ(val); - #if E1_IS_TRINAMIC - stepperE1.setCurrent(val, R_SENSE, HOLD_MULTIPLIER); - #endif - EEPROM_READ(val); - #if E2_IS_TRINAMIC - stepperE2.setCurrent(val, R_SENSE, HOLD_MULTIPLIER); - #endif - EEPROM_READ(val); - #if E3_IS_TRINAMIC - stepperE3.setCurrent(val, R_SENSE, HOLD_MULTIPLIER); - #endif - EEPROM_READ(val); - #if E4_IS_TRINAMIC - stepperE4.setCurrent(val, R_SENSE, HOLD_MULTIPLIER); - #endif + if (!validating) { + #if X_IS_TRINAMIC + SET_CURR(0, X); + #endif + #if Y_IS_TRINAMIC + SET_CURR(1, Y); + #endif + #if Z_IS_TRINAMIC + SET_CURR(2, Z); + #endif + #if X2_IS_TRINAMIC + SET_CURR(3, X2); + #endif + #if Y2_IS_TRINAMIC + SET_CURR(4, Y2); + #endif + #if Z2_IS_TRINAMIC + SET_CURR(5, Z2); + #endif + #if E0_IS_TRINAMIC + SET_CURR(6, E0); + #endif + #if E1_IS_TRINAMIC + SET_CURR(7, E1); + #endif + #if E2_IS_TRINAMIC + SET_CURR(8, E2); + #endif + #if E3_IS_TRINAMIC + SET_CURR(9, E3); + #endif + #if E4_IS_TRINAMIC + SET_CURR(10, E4); + #endif + } #else - for (uint8_t q = 11; q--;) EEPROM_READ(val); + uint16_t val; + for (uint8_t q=11; q--;) EEPROM_READ(val); #endif /* @@ -1136,19 +1212,23 @@ void MarlinSettings::postprocess() { int16_t thrs; #if ENABLED(SENSORLESS_HOMING) EEPROM_READ(thrs); - #if ENABLED(X_IS_TMC2130) - stepperX.sgt(thrs); - #endif - #if ENABLED(X2_IS_TMC2130) - stepperX2.sgt(thrs); - #endif + if (!validating) { + #if ENABLED(X_IS_TMC2130) + stepperX.sgt(thrs); + #endif + #if ENABLED(X2_IS_TMC2130) + stepperX2.sgt(thrs); + #endif + } EEPROM_READ(thrs); - #if ENABLED(Y_IS_TMC2130) - stepperY.sgt(thrs); - #endif - #if ENABLED(Y2_IS_TMC2130) - stepperY2.sgt(thrs); - #endif + if (!validating) { + #if ENABLED(Y_IS_TMC2130) + stepperY.sgt(thrs); + #endif + #if ENABLED(Y2_IS_TMC2130) + stepperY2.sgt(thrs); + #endif + } #else for (uint8_t q = 0; q < 2; q++) EEPROM_READ(thrs); #endif @@ -1181,10 +1261,10 @@ void MarlinSettings::postprocess() { // #if ENABLED(CNC_COORDINATE_SYSTEMS) - (void)gcode.select_coordinate_system(-1); // Go back to machine space + if (!validating) (void)gcode.select_coordinate_system(-1); // Go back to machine space EEPROM_READ(gcode.coordinate_system); // 27 floats #else - for (uint8_t q = 27; q--;) EEPROM_READ(dummy); + for (uint8_t q = MAX_COORDINATE_SYSTEMS * XYZ; q--;) EEPROM_READ(dummy); #endif // @@ -1211,27 +1291,24 @@ void MarlinSettings::postprocess() { #if ENABLED(ADVANCED_PAUSE_FEATURE) for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) { EEPROM_READ(dummy); - if (q < COUNT(filament_change_unload_length)) filament_change_unload_length[q] = dummy; + if (!validating && q < COUNT(filament_change_unload_length)) filament_change_unload_length[q] = dummy; } for (uint8_t q = 0; q < MAX_EXTRUDERS; q++) { EEPROM_READ(dummy); - if (q < COUNT(filament_change_load_length)) filament_change_load_length[q] = dummy; + if (!validating && q < COUNT(filament_change_load_length)) filament_change_load_length[q] = dummy; } #else for (uint8_t q = MAX_EXTRUDERS * 2; q--;) EEPROM_READ(dummy); #endif - if (working_crc == stored_crc) { - postprocess(); - #if ENABLED(EEPROM_CHITCHAT) - SERIAL_ECHO_START(); - SERIAL_ECHO(version); - SERIAL_ECHOPAIR(" stored settings retrieved (", eeprom_index - (EEPROM_OFFSET)); - SERIAL_ECHOPAIR(" bytes; crc ", (uint32_t)working_crc); - SERIAL_ECHOLNPGM(")"); - #endif + eeprom_error = size_error(eeprom_index - (EEPROM_OFFSET)); + if (eeprom_error) { + SERIAL_ECHO_START(); + SERIAL_ECHOPAIR("Index: ", int(eeprom_index - (EEPROM_OFFSET))); + SERIAL_ECHOLNPAIR(" Size: ", datasize()); } - else { + else if (working_crc != stored_crc) { + eeprom_error = true; #if ENABLED(EEPROM_CHITCHAT) SERIAL_ERROR_START(); SERIAL_ERRORPGM("EEPROM CRC mismatch - (stored) "); @@ -1240,55 +1317,80 @@ void MarlinSettings::postprocess() { SERIAL_ERROR(working_crc); SERIAL_ERRORLNPGM(" (calculated)!"); #endif - reset(); + } + else if (!validating) { + #if ENABLED(EEPROM_CHITCHAT) + SERIAL_ECHO_START(); + SERIAL_ECHO(version); + SERIAL_ECHOPAIR(" stored settings retrieved (", eeprom_index - (EEPROM_OFFSET)); + SERIAL_ECHOPAIR(" bytes; crc ", (uint32_t)working_crc); + SERIAL_ECHOLNPGM(")"); + #endif + } + + if (!validating) { + if (eeprom_error) reset(); else postprocess(); } #if ENABLED(AUTO_BED_LEVELING_UBL) - meshes_begin = (eeprom_index + 32) & 0xFFF8; // Pad the end of configuration data so it - // can float up or down a little bit without - // disrupting the mesh data ubl.report_state(); - if (!ubl.sanity_check()) { - SERIAL_EOL(); - #if ENABLED(EEPROM_CHITCHAT) - ubl.echo_name(); - SERIAL_ECHOLNPGM(" initialized.\n"); - #endif - } - else { - #if ENABLED(EEPROM_CHITCHAT) - SERIAL_PROTOCOLPGM("?Can't enable "); - ubl.echo_name(); - SERIAL_PROTOCOLLNPGM("."); - #endif - ubl.reset(); - } + if (!validating) { + if (!ubl.sanity_check()) { + SERIAL_EOL(); + #if ENABLED(EEPROM_CHITCHAT) + ubl.echo_name(); + SERIAL_ECHOLNPGM(" initialized.\n"); + #endif + } + else { + eeprom_error = true; + #if ENABLED(EEPROM_CHITCHAT) + SERIAL_PROTOCOLPGM("?Can't enable "); + ubl.echo_name(); + SERIAL_PROTOCOLLNPGM("."); + #endif + ubl.reset(); + } - if (ubl.storage_slot >= 0) { - load_mesh(ubl.storage_slot); - #if ENABLED(EEPROM_CHITCHAT) - SERIAL_ECHOPAIR("Mesh ", ubl.storage_slot); - SERIAL_ECHOLNPGM(" loaded from storage."); - #endif - } - else { - ubl.reset(); - #if ENABLED(EEPROM_CHITCHAT) - SERIAL_ECHOLNPGM("UBL System reset()"); - #endif + if (ubl.storage_slot >= 0) { + load_mesh(ubl.storage_slot); + #if ENABLED(EEPROM_CHITCHAT) + SERIAL_ECHOPAIR("Mesh ", ubl.storage_slot); + SERIAL_ECHOLNPGM(" loaded from storage."); + #endif + } + else { + ubl.reset(); + #if ENABLED(EEPROM_CHITCHAT) + SERIAL_ECHOLNPGM("UBL System reset()"); + #endif + } } #endif } #if ENABLED(EEPROM_CHITCHAT) && DISABLED(DISABLE_M503) - report(); + if (!validating) report(); #endif EEPROM_FINISH(); return !eeprom_error; } + bool MarlinSettings::validate() { + validating = true; + const bool success = _load(); + validating = false; + return success; + } + + bool MarlinSettings::load() { + if (validate()) return _load(); + reset(); + return true; + } + #if ENABLED(AUTO_BED_LEVELING_UBL) #if ENABLED(EEPROM_CHITCHAT) @@ -1299,12 +1401,13 @@ void MarlinSettings::postprocess() { } #endif + int16_t MarlinSettings::meshes_start_index() { + return (datasize() + EEPROM_OFFSET + 32) & 0xFFF8; // Pad the end of configuration data so it can float up + // or down a little bit without disrupting the mesh data + } + uint16_t MarlinSettings::calc_num_meshes() { - //obviously this will get more sophisticated once we've added an actual MAT - - if (meshes_begin <= 0) return 0; - - return (meshes_end - meshes_begin) / sizeof(ubl.z_values); + return (meshes_end - meshes_start_index()) / sizeof(ubl.z_values); } void MarlinSettings::store_mesh(const int8_t slot) { diff --git a/Marlin/src/module/configuration_store.h b/Marlin/src/module/configuration_store.h index d27f374f93..361a51e94a 100644 --- a/Marlin/src/module/configuration_store.h +++ b/Marlin/src/module/configuration_store.h @@ -29,31 +29,31 @@ class MarlinSettings { public: MarlinSettings() { } + static uint16_t datasize(); + static void reset(); - static bool save(); + static bool save(); // Return 'true' if data was saved FORCE_INLINE static bool init_eeprom() { bool success = true; reset(); #if ENABLED(EEPROM_SETTINGS) - if ((success = save())) { - #if ENABLED(AUTO_BED_LEVELING_UBL) - success = load(); // UBL uses load() to know the end of EEPROM - #elif ENABLED(EEPROM_CHITCHAT) - report(); - #endif - } + success = save(); + #if ENABLED(EEPROM_CHITCHAT) + if (success) report(); + #endif #endif return success; } #if ENABLED(EEPROM_SETTINGS) - static bool load(); + static bool load(); // Return 'true' if data was loaded ok + static bool validate(); // Return 'true' if EEPROM data is ok #if ENABLED(AUTO_BED_LEVELING_UBL) // Eventually make these available if any leveling system // That can store is enabled - FORCE_INLINE static int16_t get_start_of_meshes() { return meshes_begin; } - FORCE_INLINE static int16_t get_end_of_meshes() { return meshes_end; } + static int16_t meshes_start_index(); + FORCE_INLINE static int16_t meshes_end_index() { return meshes_end; } static uint16_t calc_num_meshes(); static void store_mesh(const int8_t slot); static void load_mesh(const int8_t slot, void * const into=NULL); @@ -77,16 +77,18 @@ class MarlinSettings { static void postprocess(); #if ENABLED(EEPROM_SETTINGS) - static bool eeprom_error; + + static bool eeprom_error, validating; #if ENABLED(AUTO_BED_LEVELING_UBL) // Eventually make these available if any leveling system // That can store is enabled - static int16_t meshes_begin; const static int16_t meshes_end = E2END - 128; // 128 is a placeholder for the size of the MAT; the MAT will always // live at the very end of the eeprom #endif + static bool _load(); + static bool size_error(const uint16_t size); #endif };