Merge pull request #6738 from thinkyhead/bf_config_crc_rebase
Implement CRC16, develop mesh allocation table
This commit is contained in:
		| @@ -3943,7 +3943,7 @@ void home_all_axes() { gcode_G28(true); } | ||||
| #if ENABLED(MESH_BED_LEVELING) | ||||
|  | ||||
|   // Save 130 bytes with non-duplication of PSTR | ||||
|   void say_not_entered() { SERIAL_PROTOCOLLNPGM(" not entered."); } | ||||
|   void echo_not_entered() { SERIAL_PROTOCOLLNPGM(" not entered."); } | ||||
|  | ||||
|   void mbl_mesh_report() { | ||||
|     SERIAL_PROTOCOLLNPGM("Num X,Y: " STRINGIFY(GRID_MAX_POINTS_X) "," STRINGIFY(GRID_MAX_POINTS_Y)); | ||||
| @@ -4074,7 +4074,7 @@ void home_all_axes() { gcode_G28(true); } | ||||
|           } | ||||
|         } | ||||
|         else { | ||||
|           SERIAL_CHAR('X'); say_not_entered(); | ||||
|           SERIAL_CHAR('X'); echo_not_entered(); | ||||
|           return; | ||||
|         } | ||||
|  | ||||
| @@ -4086,7 +4086,7 @@ void home_all_axes() { gcode_G28(true); } | ||||
|           } | ||||
|         } | ||||
|         else { | ||||
|           SERIAL_CHAR('Y'); say_not_entered(); | ||||
|           SERIAL_CHAR('Y'); echo_not_entered(); | ||||
|           return; | ||||
|         } | ||||
|  | ||||
| @@ -4094,7 +4094,7 @@ void home_all_axes() { gcode_G28(true); } | ||||
|           mbl.z_values[px][py] = code_value_linear_units(); | ||||
|         } | ||||
|         else { | ||||
|           SERIAL_CHAR('Z'); say_not_entered(); | ||||
|           SERIAL_CHAR('Z'); echo_not_entered(); | ||||
|           return; | ||||
|         } | ||||
|         break; | ||||
| @@ -4104,7 +4104,7 @@ void home_all_axes() { gcode_G28(true); } | ||||
|           mbl.z_offset = code_value_linear_units(); | ||||
|         } | ||||
|         else { | ||||
|           SERIAL_CHAR('Z'); say_not_entered(); | ||||
|           SERIAL_CHAR('Z'); echo_not_entered(); | ||||
|           return; | ||||
|         } | ||||
|         break; | ||||
| @@ -5123,7 +5123,7 @@ void home_all_axes() { gcode_G28(true); } | ||||
|       SERIAL_PROTOCOLPGM("Checking... AC"); | ||||
|       if (verbose_level == 0) SERIAL_PROTOCOLPGM(" (DRY-RUN)"); | ||||
|       SERIAL_EOL; | ||||
|       LCD_MESSAGEPGM("Checking... AC"); | ||||
|       LCD_MESSAGEPGM("Checking... AC"); // TODO: Make translatable string | ||||
|  | ||||
|       SERIAL_PROTOCOLPAIR(".Height:", DELTA_HEIGHT + home_offset[Z_AXIS]); | ||||
|       if (!do_height_only) { | ||||
| @@ -5343,7 +5343,7 @@ void home_all_axes() { gcode_G28(true); } | ||||
|             SERIAL_PROTOCOL_SP(36); | ||||
|             SERIAL_PROTOCOLPGM("rolling back."); | ||||
|             SERIAL_EOL; | ||||
|             LCD_MESSAGEPGM("Calibration OK"); | ||||
|             LCD_MESSAGEPGM("Calibration OK"); // TODO: Make translatable string | ||||
|           } | ||||
|           else {                                                     // !end iterations | ||||
|             char mess[15] = "No convergence"; | ||||
| @@ -5394,7 +5394,7 @@ void home_all_axes() { gcode_G28(true); } | ||||
|           } | ||||
|           else { | ||||
|             SERIAL_PROTOCOLLNPGM("Calibration OK"); | ||||
|             LCD_MESSAGEPGM("Calibration OK"); | ||||
|             LCD_MESSAGEPGM("Calibration OK"); // TODO: Make translatable string | ||||
|             SERIAL_PROTOCOLPAIR(".Height:", DELTA_HEIGHT + home_offset[Z_AXIS]); | ||||
|             SERIAL_EOL; | ||||
|             serialprintPGM(save_message); | ||||
| @@ -8460,15 +8460,22 @@ void quickstop_stepper() { | ||||
|     #if ENABLED(AUTO_BED_LEVELING_UBL) | ||||
|       // L to load a mesh from the EEPROM | ||||
|       if (code_seen('L')) { | ||||
|         const int8_t storage_slot = code_has_value() ? code_value_int() : ubl.state.eeprom_storage_slot; | ||||
|         const int16_t j = (UBL_LAST_EEPROM_INDEX - ubl.eeprom_start) / sizeof(ubl.z_values); | ||||
|         if (!WITHIN(storage_slot, 0, j - 1) || ubl.eeprom_start <= 0) { | ||||
|           SERIAL_PROTOCOLLNPGM("?EEPROM storage not available for use.\n"); | ||||
|         const int8_t storage_slot = code_has_value() ? code_value_int() : ubl.state.storage_slot; | ||||
|         const int16_t a = settings.calc_num_meshes(); | ||||
|  | ||||
|         if (!a) { | ||||
|           SERIAL_PROTOCOLLNPGM("?EEPROM storage not available."); | ||||
|           return; | ||||
|         } | ||||
|  | ||||
|         ubl.load_mesh(storage_slot); | ||||
|         ubl.state.eeprom_storage_slot = storage_slot; | ||||
|         if (!WITHIN(storage_slot, 0, a - 1)) { | ||||
|           SERIAL_PROTOCOLLNPGM("?Invalid storage slot."); | ||||
|           SERIAL_PROTOCOLLNPAIR("?Use 0 to ", a - 1); | ||||
|           return; | ||||
|         } | ||||
|  | ||||
|         settings.load_mesh(storage_slot); | ||||
|         ubl.state.storage_slot = storage_slot; | ||||
|       } | ||||
|     #endif // AUTO_BED_LEVELING_UBL | ||||
|  | ||||
| @@ -8496,7 +8503,7 @@ void quickstop_stepper() { | ||||
|       if (code_seen('L') || code_seen('V')) { | ||||
|         ubl.display_map(0);  // Currently only supports one map type | ||||
|         SERIAL_ECHOLNPAIR("UBL_MESH_VALID = ", UBL_MESH_VALID); | ||||
|         SERIAL_ECHOLNPAIR("eeprom_storage_slot = ", ubl.state.eeprom_storage_slot); | ||||
|         SERIAL_ECHOLNPAIR("ubl.state.storage_slot = ", ubl.state.storage_slot); | ||||
|       } | ||||
|     #endif | ||||
|  | ||||
|   | ||||
| @@ -36,16 +36,16 @@ | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #define EEPROM_VERSION "V37" | ||||
| #define EEPROM_VERSION "V38" | ||||
|  | ||||
| // Change EEPROM version if these are changed: | ||||
| #define EEPROM_OFFSET 100 | ||||
|  | ||||
| /** | ||||
|  * V37 EEPROM Layout: | ||||
|  * V38 EEPROM Layout: | ||||
|  * | ||||
|  *  100  Version                                    (char x4) | ||||
|  *  104  EEPROM Checksum                            (uint16_t) | ||||
|  *  104  EEPROM CRC16                               (uint16_t) | ||||
|  * | ||||
|  *  106            E_STEPPERS                       (uint8_t) | ||||
|  *  107  M92 XYZE  planner.axis_steps_per_mm        (float x4 ... x8) | ||||
| @@ -90,7 +90,7 @@ | ||||
|  * AUTO_BED_LEVELING_UBL:                           6 bytes | ||||
|  *  324  G29 A     ubl.state.active                 (bool) | ||||
|  *  325  G29 Z     ubl.state.z_offset               (float) | ||||
|  *  329  G29 S     ubl.state.eeprom_storage_slot    (int8_t) | ||||
|  *  329  G29 S     ubl.state.storage_slot           (int8_t) | ||||
|  * | ||||
|  * DELTA:                                           48 bytes | ||||
|  *  348  M666 XYZ  endstop_adj                      (float x3) | ||||
| @@ -158,6 +158,14 @@ | ||||
|  * | ||||
|  *  588                                Minimum end-point | ||||
|  * 1909 (588 + 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) | ||||
|  * | ||||
|  */ | ||||
| #include "configuration_store.h" | ||||
|  | ||||
| @@ -230,18 +238,26 @@ void MarlinSettings::postprocess() { | ||||
|  | ||||
| #if ENABLED(EEPROM_SETTINGS) | ||||
|  | ||||
|   #define DUMMY_PID_VALUE 3000.0f | ||||
|   #define EEPROM_START() int eeprom_index = EEPROM_OFFSET | ||||
|   #define EEPROM_SKIP(VAR) eeprom_index += sizeof(VAR) | ||||
|   #define EEPROM_WRITE(VAR) write_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR), &working_crc) | ||||
|   #define EEPROM_READ(VAR) 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) | ||||
|  | ||||
|   const char version[4] = EEPROM_VERSION; | ||||
|  | ||||
|   uint16_t MarlinSettings::eeprom_checksum; | ||||
|   bool MarlinSettings::eeprom_error; | ||||
|  | ||||
|   bool MarlinSettings::eeprom_write_error, | ||||
|        MarlinSettings::eeprom_read_error; | ||||
|   #if ENABLED(AUTO_BED_LEVELING_UBL) | ||||
|     int MarlinSettings::meshes_begin; | ||||
|   #endif | ||||
|  | ||||
|   void MarlinSettings::write_data(int &pos, const uint8_t* value, uint16_t size) { | ||||
|     if (eeprom_write_error) return; | ||||
|   void MarlinSettings::write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc) { | ||||
|     if (eeprom_error) return; | ||||
|     while (size--) { | ||||
|       uint8_t * const p = (uint8_t * const)pos; | ||||
|       const uint8_t v = *value; | ||||
|       uint8_t v = *value; | ||||
|       // EEPROM has only ~100,000 write cycles, | ||||
|       // so only write bytes that have changed! | ||||
|       if (v != eeprom_read_byte(p)) { | ||||
| @@ -249,32 +265,27 @@ void MarlinSettings::postprocess() { | ||||
|         if (eeprom_read_byte(p) != v) { | ||||
|           SERIAL_ECHO_START; | ||||
|           SERIAL_ECHOLNPGM(MSG_ERR_EEPROM_WRITE); | ||||
|           eeprom_write_error = true; | ||||
|           eeprom_error = true; | ||||
|           return; | ||||
|         } | ||||
|       } | ||||
|       eeprom_checksum += v; | ||||
|       crc16(crc, &v, 1); | ||||
|       pos++; | ||||
|       value++; | ||||
|     }; | ||||
|   } | ||||
|   void MarlinSettings::read_data(int &pos, uint8_t* value, uint16_t size) { | ||||
|  | ||||
|   void MarlinSettings::read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc) { | ||||
|     if (eeprom_error) return; | ||||
|     do { | ||||
|       uint8_t c = eeprom_read_byte((unsigned char*)pos); | ||||
|       if (!eeprom_read_error) *value = c; | ||||
|       eeprom_checksum += c; | ||||
|       *value = c; | ||||
|       crc16(crc, &c, 1); | ||||
|       pos++; | ||||
|       value++; | ||||
|     } while (--size); | ||||
|   } | ||||
|  | ||||
|   #define DUMMY_PID_VALUE 3000.0f | ||||
|   #define EEPROM_START() int eeprom_index = EEPROM_OFFSET | ||||
|   #define EEPROM_SKIP(VAR) eeprom_index += sizeof(VAR) | ||||
|   #define EEPROM_WRITE(VAR) write_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR)) | ||||
|   #define EEPROM_READ(VAR) read_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR)) | ||||
|   #define EEPROM_ASSERT(TST,ERR) if (!(TST)) do{ SERIAL_ERROR_START; SERIAL_ERRORLNPGM(ERR); eeprom_read_error = true; }while(0) | ||||
|  | ||||
|   /** | ||||
|    * M500 - Store Configuration | ||||
|    */ | ||||
| @@ -282,14 +293,16 @@ void MarlinSettings::postprocess() { | ||||
|     float dummy = 0.0f; | ||||
|     char ver[4] = "000"; | ||||
|  | ||||
|     uint16_t working_crc = 0; | ||||
|  | ||||
|     EEPROM_START(); | ||||
|  | ||||
|     eeprom_write_error = false; | ||||
|     eeprom_error = false; | ||||
|  | ||||
|     EEPROM_WRITE(ver);     // invalidate data first | ||||
|     EEPROM_SKIP(eeprom_checksum); // Skip the checksum slot | ||||
|     EEPROM_SKIP(working_crc); // Skip the checksum slot | ||||
|  | ||||
|     eeprom_checksum = 0; // clear before first "real data" | ||||
|     working_crc = 0; // clear before first "real data" | ||||
|  | ||||
|     const uint8_t esteppers = COUNT(planner.axis_steps_per_mm) - XYZ; | ||||
|     EEPROM_WRITE(esteppers); | ||||
| @@ -410,14 +423,14 @@ void MarlinSettings::postprocess() { | ||||
|     #if ENABLED(AUTO_BED_LEVELING_UBL) | ||||
|       EEPROM_WRITE(ubl.state.active); | ||||
|       EEPROM_WRITE(ubl.state.z_offset); | ||||
|       EEPROM_WRITE(ubl.state.eeprom_storage_slot); | ||||
|       EEPROM_WRITE(ubl.state.storage_slot); | ||||
|     #else | ||||
|       const bool ubl_active = 0; | ||||
|       const bool ubl_active = false; | ||||
|       dummy = 0.0f; | ||||
|       const int8_t eeprom_slot = -1; | ||||
|       const int8_t storage_slot = -1; | ||||
|       EEPROM_WRITE(ubl_active); | ||||
|       EEPROM_WRITE(dummy); | ||||
|       EEPROM_WRITE(eeprom_slot); | ||||
|       EEPROM_WRITE(storage_slot); | ||||
|     #endif // AUTO_BED_LEVELING_UBL | ||||
|  | ||||
|     // 9 floats for DELTA / Z_DUAL_ENDSTOPS | ||||
| @@ -609,43 +622,42 @@ void MarlinSettings::postprocess() { | ||||
|       EEPROM_WRITE(dummy); | ||||
|     #endif | ||||
|  | ||||
|     if (!eeprom_write_error) { | ||||
|  | ||||
|       const uint16_t final_checksum = eeprom_checksum, | ||||
|                      eeprom_size = eeprom_index; | ||||
|     if (!eeprom_error) { | ||||
|       const int eeprom_size = eeprom_index; | ||||
|  | ||||
|       // Write the EEPROM header | ||||
|       eeprom_index = EEPROM_OFFSET; | ||||
|       EEPROM_WRITE(version); | ||||
|       EEPROM_WRITE(final_checksum); | ||||
|       EEPROM_WRITE(working_crc); | ||||
|  | ||||
|       // Report storage size | ||||
|       SERIAL_ECHO_START; | ||||
|       SERIAL_ECHOPAIR("Settings Stored (", eeprom_size - (EEPROM_OFFSET)); | ||||
|       SERIAL_ECHOLNPGM(" bytes)"); | ||||
|       SERIAL_ECHOPAIR(" bytes; crc ", working_crc); | ||||
|       SERIAL_ECHOLNPGM(")"); | ||||
|     } | ||||
|  | ||||
|     #if ENABLED(UBL_SAVE_ACTIVE_ON_M500) | ||||
|       if (ubl.state.eeprom_storage_slot >= 0) | ||||
|         ubl.store_mesh(ubl.state.eeprom_storage_slot); | ||||
|       if (ubl.state.storage_slot >= 0) | ||||
|         store_mesh(ubl.state.storage_slot); | ||||
|     #endif | ||||
|  | ||||
|     return !eeprom_write_error; | ||||
|     return !eeprom_error; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * M501 - Retrieve Configuration | ||||
|    */ | ||||
|   bool MarlinSettings::load() { | ||||
|     uint16_t working_crc = 0; | ||||
|  | ||||
|     EEPROM_START(); | ||||
|     eeprom_read_error = false; // If set EEPROM_READ won't write into RAM | ||||
|  | ||||
|     char stored_ver[4]; | ||||
|     EEPROM_READ(stored_ver); | ||||
|  | ||||
|     uint16_t stored_checksum; | ||||
|     EEPROM_READ(stored_checksum); | ||||
|     uint16_t stored_crc; | ||||
|     EEPROM_READ(stored_crc); | ||||
|  | ||||
|     // Version has to match or defaults are used | ||||
|     if (strncmp(version, stored_ver, 3) != 0) { | ||||
| @@ -662,7 +674,7 @@ void MarlinSettings::postprocess() { | ||||
|     else { | ||||
|       float dummy = 0; | ||||
|  | ||||
|       eeprom_checksum = 0; // clear before reading first "real data" | ||||
|       working_crc = 0; //clear before reading first "real data" | ||||
|  | ||||
|       // Number of esteppers may change | ||||
|       uint8_t esteppers; | ||||
| @@ -788,7 +800,7 @@ void MarlinSettings::postprocess() { | ||||
|       #if ENABLED(AUTO_BED_LEVELING_UBL) | ||||
|         EEPROM_READ(ubl.state.active); | ||||
|         EEPROM_READ(ubl.state.z_offset); | ||||
|         EEPROM_READ(ubl.state.eeprom_storage_slot); | ||||
|         EEPROM_READ(ubl.state.storage_slot); | ||||
|       #else | ||||
|         bool dummyb; | ||||
|         uint8_t dummyui8; | ||||
| @@ -960,42 +972,45 @@ void MarlinSettings::postprocess() { | ||||
|         EEPROM_READ(dummy); | ||||
|       #endif | ||||
|  | ||||
|       if (eeprom_checksum == stored_checksum) { | ||||
|         if (eeprom_read_error) | ||||
|           reset(); | ||||
|         else { | ||||
|       if (working_crc == stored_crc) { | ||||
|           postprocess(); | ||||
|           SERIAL_ECHO_START; | ||||
|           SERIAL_ECHO(version); | ||||
|           SERIAL_ECHOPAIR(" stored settings retrieved (", eeprom_index - (EEPROM_OFFSET)); | ||||
|           SERIAL_ECHOLNPGM(" bytes)"); | ||||
|         } | ||||
|           SERIAL_ECHOPAIR(" bytes; crc ", working_crc); | ||||
|           SERIAL_ECHOLNPGM(")"); | ||||
|       } | ||||
|       else { | ||||
|         SERIAL_ERROR_START; | ||||
|         SERIAL_ERRORLNPGM("EEPROM checksum mismatch"); | ||||
|         SERIAL_ERRORPGM("EEPROM checksum mismatch - (stored CRC)"); | ||||
|         SERIAL_ERROR(stored_crc); | ||||
|         SERIAL_ERRORPGM(" != "); | ||||
|         SERIAL_ERROR(working_crc); | ||||
|         SERIAL_ERRORLNPGM(" (calculated CRC)!"); | ||||
|         reset(); | ||||
|       } | ||||
|  | ||||
|       #if ENABLED(AUTO_BED_LEVELING_UBL) | ||||
|         ubl.eeprom_start = (eeprom_index + 32) & 0xFFF8; // Pad the end of configuration data so it | ||||
|                                                          // can float up or down a little bit without | ||||
|                                                          // disrupting the Unified Bed Leveling data | ||||
|         SERIAL_ECHOPGM(" UBL "); | ||||
|         if (!ubl.state.active) SERIAL_ECHO("not "); | ||||
|         SERIAL_ECHOLNPGM("active!"); | ||||
|         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_ECHOLNPGM("\nUnified Bed Leveling system initialized.\n"); | ||||
|           SERIAL_EOL; | ||||
|           ubl.echo_name(); | ||||
|           SERIAL_ECHOLNPGM(" initialized.\n"); | ||||
|         } | ||||
|         else { | ||||
|           SERIAL_PROTOCOLPGM("?Unable to enable Unified Bed Leveling system.\n"); | ||||
|           SERIAL_PROTOCOLPGM("?Can't enable "); | ||||
|           ubl.echo_name(); | ||||
|           SERIAL_PROTOCOLLNPGM("."); | ||||
|           ubl.reset(); | ||||
|         } | ||||
|  | ||||
|         if (ubl.state.eeprom_storage_slot >= 0) { | ||||
|           ubl.load_mesh(ubl.state.eeprom_storage_slot); | ||||
|           SERIAL_ECHOPAIR("Mesh ", ubl.state.eeprom_storage_slot); | ||||
|         if (ubl.state.storage_slot >= 0) { | ||||
|           load_mesh(ubl.state.storage_slot); | ||||
|           SERIAL_ECHOPAIR("Mesh ", ubl.state.storage_slot); | ||||
|           SERIAL_ECHOLNPGM(" loaded from storage."); | ||||
|         } | ||||
|         else { | ||||
| @@ -1009,9 +1024,87 @@ void MarlinSettings::postprocess() { | ||||
|       report(); | ||||
|     #endif | ||||
|  | ||||
|     return !eeprom_read_error; | ||||
|     return !eeprom_error; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   #if ENABLED(AUTO_BED_LEVELING_UBL) | ||||
|  | ||||
|     void ubl_invalid_slot(const int s) { | ||||
|       SERIAL_PROTOCOLLNPGM("?Invalid slot."); | ||||
|       SERIAL_PROTOCOL(s); | ||||
|       SERIAL_PROTOCOLLNPGM(" mesh slots available."); | ||||
|     } | ||||
|  | ||||
|     int 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); | ||||
|     } | ||||
|  | ||||
|     void MarlinSettings::store_mesh(int8_t slot) { | ||||
|  | ||||
|       #if ENABLED(AUTO_BED_LEVELING_UBL) | ||||
|         const int a = calc_num_meshes(); | ||||
|         if (!WITHIN(slot, 0, a - 1)) { | ||||
|           ubl_invalid_slot(a); | ||||
|           SERIAL_PROTOCOLPAIR("E2END=", E2END); | ||||
|           SERIAL_PROTOCOLPAIR(" meshes_end=", (int)meshes_end); | ||||
|           SERIAL_PROTOCOLLNPAIR(" slot=", slot); | ||||
|           SERIAL_EOL; | ||||
|           return; | ||||
|         } | ||||
|  | ||||
|         uint16_t crc = 0; | ||||
|         int pos = meshes_end - (slot + 1) * sizeof(ubl.z_values); | ||||
|  | ||||
|         write_data(pos, (uint8_t *)&ubl.z_values, sizeof(ubl.z_values), &crc); | ||||
|  | ||||
|         // Write crc to MAT along with other data, or just tack on to the beginning or end | ||||
|  | ||||
|         SERIAL_PROTOCOLPAIR("Mesh saved in slot ", slot); | ||||
|  | ||||
|       #else | ||||
|  | ||||
|         // Other mesh types | ||||
|  | ||||
|       #endif | ||||
|     } | ||||
|  | ||||
|     void MarlinSettings::load_mesh(int8_t slot, void *into /* = 0 */) { | ||||
|  | ||||
|       #if ENABLED(AUTO_BED_LEVELING_UBL) | ||||
|  | ||||
|         const int16_t a = settings.calc_num_meshes(); | ||||
|  | ||||
|         if (!WITHIN(slot, 0, a - 1)) { | ||||
|           ubl_invalid_slot(a); | ||||
|           return; | ||||
|         } | ||||
|  | ||||
|         uint16_t crc = 0; | ||||
|         int pos = meshes_end - (slot + 1) * sizeof(ubl.z_values); | ||||
|         uint8_t * const dest = into ? (uint8_t*)into : (uint8_t*)&ubl.z_values; | ||||
|         read_data(pos, dest, sizeof(ubl.z_values), &crc); | ||||
|  | ||||
|         // Compare crc with crc from MAT, or read from end | ||||
|  | ||||
|         SERIAL_PROTOCOLPAIR("Mesh loaded from slot ", slot); | ||||
|  | ||||
|       #else | ||||
|  | ||||
|         // Other mesh types | ||||
|  | ||||
|       #endif | ||||
|     } | ||||
|  | ||||
|     //void MarlinSettings::delete_mesh() { return; } | ||||
|     //void MarlinSettings::defrag_meshes() { return; } | ||||
|  | ||||
|   #endif // AUTO_BED_LEVELING_UBL | ||||
|  | ||||
| #else // !EEPROM_SETTINGS | ||||
|  | ||||
|   bool MarlinSettings::save() { | ||||
| @@ -1449,7 +1542,8 @@ void MarlinSettings::reset() { | ||||
|  | ||||
|       if (!forReplay) { | ||||
|         CONFIG_ECHO_START; | ||||
|         SERIAL_ECHOLNPGM("Unified Bed Leveling:"); | ||||
|         ubl.echo_name(); | ||||
|         SERIAL_ECHOLNPGM(":"); | ||||
|       } | ||||
|       CONFIG_ECHO_START; | ||||
|       SERIAL_ECHOPAIR("  M420 S", ubl.state.active ? 1 : 0); | ||||
| @@ -1458,7 +1552,19 @@ void MarlinSettings::reset() { | ||||
|       #endif | ||||
|       SERIAL_EOL; | ||||
|  | ||||
|       if (!forReplay) ubl.g29_what_command(); | ||||
|       if (!forReplay) { | ||||
|         SERIAL_EOL; | ||||
|         ubl.report_state(); | ||||
|  | ||||
|         SERIAL_ECHOLNPAIR("\nActive Mesh Slot: ", ubl.state.storage_slot); | ||||
|  | ||||
|         SERIAL_ECHOPGM("z_offset: "); | ||||
|         SERIAL_ECHO_F(ubl.state.z_offset, 6); | ||||
|         SERIAL_EOL; | ||||
|  | ||||
|         SERIAL_ECHOPAIR("EEPROM can hold ", calc_num_meshes()); | ||||
|         SERIAL_ECHOLNPGM(" meshes.\n"); | ||||
|       } | ||||
|  | ||||
|     #elif HAS_ABL | ||||
|  | ||||
|   | ||||
| @@ -34,6 +34,18 @@ class MarlinSettings { | ||||
|  | ||||
|     #if ENABLED(EEPROM_SETTINGS) | ||||
|       static bool load(); | ||||
|  | ||||
|       #if ENABLED(AUTO_BED_LEVELING_UBL) // Eventually make these available if any leveling system | ||||
|                                          // That can store is enabled | ||||
|         FORCE_INLINE static int get_start_of_meshes() { return meshes_begin; } | ||||
|         FORCE_INLINE static int get_end_of_meshes() { return meshes_end; } | ||||
|         static int calc_num_meshes(); | ||||
|         static void store_mesh(int8_t slot); | ||||
|         static void load_mesh(int8_t slot, void *into = 0); | ||||
|  | ||||
|         //static void delete_mesh();    // necessary if we have a MAT | ||||
|         //static void defrag_meshes();  // " | ||||
|       #endif | ||||
|     #else | ||||
|       FORCE_INLINE | ||||
|       static bool load() { reset(); report(); return true; } | ||||
| @@ -50,10 +62,18 @@ class MarlinSettings { | ||||
|     static void postprocess(); | ||||
|  | ||||
|     #if ENABLED(EEPROM_SETTINGS) | ||||
|       static uint16_t eeprom_checksum; | ||||
|       static bool eeprom_read_error, eeprom_write_error; | ||||
|       static void write_data(int &pos, const uint8_t* value, uint16_t size); | ||||
|       static void read_data(int &pos, uint8_t* value, uint16_t size); | ||||
|       static bool eeprom_error; | ||||
|  | ||||
|       #if ENABLED(AUTO_BED_LEVELING_UBL) // Eventually make these available if any leveling system | ||||
|                                          // That can store is enabled | ||||
|         static int meshes_begin; | ||||
|         const static int mat_end = E2END;            // Mesh allocation table; this may not end up being necessary | ||||
|         const static int meshes_end = mat_end - 128; // 128 is a placeholder for the size of the MAT | ||||
|  | ||||
|       #endif | ||||
|  | ||||
|       static void write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc); | ||||
|       static void read_data(int &pos, uint8_t *value, uint16_t size, uint16_t *crc); | ||||
|     #endif | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -41,6 +41,16 @@ | ||||
|  | ||||
|   uint8_t ubl_cnt = 0; | ||||
|  | ||||
|   void unified_bed_leveling::echo_name() { SERIAL_PROTOCOLPGM("Unified Bed Leveling"); } | ||||
|  | ||||
|   void unified_bed_leveling::report_state() { | ||||
|     echo_name(); | ||||
|     SERIAL_PROTOCOLPGM(" System v" UBL_VERSION " "); | ||||
|     if (!state.active) SERIAL_PROTOCOLPGM("in"); | ||||
|     SERIAL_PROTOCOLLNPGM("active."); | ||||
|     safe_delay(50); | ||||
|   } | ||||
|  | ||||
|   static void serial_echo_xy(const int16_t x, const int16_t y) { | ||||
|     SERIAL_CHAR('('); | ||||
|     SERIAL_ECHO(x); | ||||
| @@ -63,9 +73,6 @@ | ||||
|   bool unified_bed_leveling::g26_debug_flag = false, | ||||
|        unified_bed_leveling::has_control_of_lcd_panel = false; | ||||
|  | ||||
|   int16_t unified_bed_leveling::eeprom_start = -1;  // Please stop changing this to 8 bits in size | ||||
|                                                     // It needs to hold values bigger than this. | ||||
|  | ||||
|   volatile int unified_bed_leveling::encoder_diff; | ||||
|  | ||||
|   unified_bed_leveling::unified_bed_leveling() { | ||||
| @@ -73,53 +80,10 @@ | ||||
|     reset(); | ||||
|   } | ||||
|  | ||||
|   void unified_bed_leveling::load_mesh(const int16_t slot) { | ||||
|     int16_t j = (UBL_LAST_EEPROM_INDEX - eeprom_start) / sizeof(z_values); | ||||
|  | ||||
|     if (slot == -1) { | ||||
|       SERIAL_PROTOCOLLNPGM("?No mesh saved in EEPROM. Zeroing mesh in memory.\n"); | ||||
|       reset(); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     if (!WITHIN(slot, 0, j - 1) || eeprom_start <= 0) { | ||||
|       SERIAL_PROTOCOLLNPGM("?EEPROM storage not available to load mesh.\n"); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     j = UBL_LAST_EEPROM_INDEX - (slot + 1) * sizeof(z_values); | ||||
|     eeprom_read_block((void *)&z_values, (void *)j, sizeof(z_values)); | ||||
|  | ||||
|     SERIAL_PROTOCOLPAIR("Mesh loaded from slot ", slot); | ||||
|     SERIAL_PROTOCOLLNPAIR(" at offset ", hex_address((void*)j)); | ||||
|   } | ||||
|  | ||||
|   void unified_bed_leveling::store_mesh(const int16_t slot) { | ||||
|     int16_t j = (UBL_LAST_EEPROM_INDEX - eeprom_start) / sizeof(z_values); | ||||
|  | ||||
|     if (!WITHIN(slot, 0, j - 1) || eeprom_start <= 0) { | ||||
|       SERIAL_PROTOCOLLNPGM("?EEPROM storage not available to load mesh.\n"); | ||||
|       SERIAL_PROTOCOL(slot); | ||||
|       SERIAL_PROTOCOLLNPGM(" mesh slots available.\n"); | ||||
|       SERIAL_PROTOCOLLNPAIR("E2END     : ", E2END); | ||||
|       SERIAL_PROTOCOLLNPAIR("k         : ", (int)UBL_LAST_EEPROM_INDEX); | ||||
|       SERIAL_PROTOCOLLNPAIR("j         : ", j); | ||||
|       SERIAL_PROTOCOLLNPAIR("m         : ", slot); | ||||
|       SERIAL_EOL; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     j = UBL_LAST_EEPROM_INDEX - (slot + 1) * sizeof(z_values); | ||||
|     eeprom_write_block((const void *)&z_values, (void *)j, sizeof(z_values)); | ||||
|  | ||||
|     SERIAL_PROTOCOLPAIR("Mesh saved in slot ", slot); | ||||
|     SERIAL_PROTOCOLLNPAIR(" at offset ", hex_address((void*)j)); | ||||
|   } | ||||
|  | ||||
|   void unified_bed_leveling::reset() { | ||||
|     state.active = false; | ||||
|     state.z_offset = 0; | ||||
|     state.eeprom_storage_slot = -1; | ||||
|     state.storage_slot = -1; | ||||
|  | ||||
|     ZERO(z_values); | ||||
|  | ||||
| @@ -203,9 +167,9 @@ | ||||
|   bool unified_bed_leveling::sanity_check() { | ||||
|     uint8_t error_flag = 0; | ||||
|  | ||||
|     const int j = (UBL_LAST_EEPROM_INDEX - eeprom_start) / sizeof(z_values); | ||||
|     if (j < 1) { | ||||
|       SERIAL_PROTOCOLLNPGM("?No EEPROM storage available for a mesh of this size.\n"); | ||||
|     const int a = settings.calc_num_meshes(); | ||||
|     if (a < 1) { | ||||
|       SERIAL_PROTOCOLLNPGM("?Insufficient EEPROM storage for a mesh of this size."); | ||||
|       error_flag++; | ||||
|     } | ||||
|  | ||||
|   | ||||
							
								
								
									
										16
									
								
								Marlin/ubl.h
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								Marlin/ubl.h
									
									
									
									
									
								
							| @@ -30,8 +30,9 @@ | ||||
|   #include "planner.h" | ||||
|   #include "math.h" | ||||
|   #include "vector_3.h" | ||||
|   #include "configuration_store.h" | ||||
|  | ||||
|   #define UBL_VERSION "1.00" | ||||
|   #define UBL_VERSION "1.01" | ||||
|   #define UBL_OK false | ||||
|   #define UBL_ERR true | ||||
|  | ||||
| @@ -92,7 +93,7 @@ | ||||
|   typedef struct { | ||||
|     bool active = false; | ||||
|     float z_offset = 0.0; | ||||
|     int8_t eeprom_storage_slot = -1; | ||||
|     int8_t storage_slot = -1; | ||||
|   } ubl_state; | ||||
|  | ||||
|   class unified_bed_leveling { | ||||
| @@ -102,6 +103,8 @@ | ||||
|  | ||||
|     public: | ||||
|  | ||||
|       void echo_name(); | ||||
|       void report_state(); | ||||
|       void find_mean_mesh_height(); | ||||
|       void shift_mesh_height(); | ||||
|       void probe_entire_mesh(const float &lx, const float &ly, const bool do_ubl_mesh_map, const bool stow_probe, bool do_furthest); | ||||
| @@ -117,10 +120,6 @@ | ||||
|       void display_map(const int); | ||||
|       void reset(); | ||||
|       void invalidate(); | ||||
|       void store_state(); | ||||
|       void load_state(); | ||||
|       void store_mesh(const int16_t); | ||||
|       void load_mesh(const int16_t); | ||||
|       bool sanity_check(); | ||||
|  | ||||
|       static ubl_state state; | ||||
| @@ -153,9 +152,6 @@ | ||||
|  | ||||
|       static bool g26_debug_flag, has_control_of_lcd_panel; | ||||
|  | ||||
|       static int16_t eeprom_start;    // Please do no change this to 8 bits in size | ||||
|                                       // It needs to hold values bigger than this. | ||||
|  | ||||
|       static volatile int encoder_diff; // Volatile because it's changed at interrupt time. | ||||
|  | ||||
|       unified_bed_leveling(); | ||||
| @@ -351,7 +347,5 @@ | ||||
|  | ||||
|   extern unified_bed_leveling ubl; | ||||
|  | ||||
|   #define UBL_LAST_EEPROM_INDEX E2END | ||||
|  | ||||
| #endif // AUTO_BED_LEVELING_UBL | ||||
| #endif // UNIFIED_BED_LEVELING_H | ||||
|   | ||||
| @@ -314,7 +314,7 @@ | ||||
|  | ||||
|   void __attribute__((optimize("O0"))) gcode_G29() { | ||||
|  | ||||
|     if (ubl.eeprom_start < 0) { | ||||
|     if (!settings.calc_num_meshes()) { | ||||
|       SERIAL_PROTOCOLLNPGM("?You need to enable your EEPROM and initialize it"); | ||||
|       SERIAL_PROTOCOLLNPGM("with M502, M500, M501 in that order.\n"); | ||||
|       return; | ||||
| @@ -419,9 +419,9 @@ | ||||
|     } | ||||
|  | ||||
|     if (code_seen('P')) { | ||||
|       if (WITHIN(phase_value, 0, 1) && ubl.state.eeprom_storage_slot == -1) { | ||||
|         ubl.state.eeprom_storage_slot = 0; | ||||
|         SERIAL_PROTOCOLLNPGM("Default storage slot 0 selected.\n"); | ||||
|       if (WITHIN(phase_value, 0, 1) && ubl.state.storage_slot == -1) { | ||||
|         ubl.state.storage_slot = 0; | ||||
|         SERIAL_PROTOCOLLNPGM("Default storage slot 0 selected."); | ||||
|       } | ||||
|  | ||||
|       switch (phase_value) { | ||||
| @@ -430,7 +430,7 @@ | ||||
|           // Zero Mesh Data | ||||
|           // | ||||
|           ubl.reset(); | ||||
|           SERIAL_PROTOCOLLNPGM("Mesh zeroed.\n"); | ||||
|           SERIAL_PROTOCOLLNPGM("Mesh zeroed."); | ||||
|           break; | ||||
|  | ||||
|         case 1: | ||||
| @@ -439,7 +439,7 @@ | ||||
|           // | ||||
|           if (!code_seen('C')) { | ||||
|             ubl.invalidate(); | ||||
|             SERIAL_PROTOCOLLNPGM("Mesh invalidated. Probing mesh.\n"); | ||||
|             SERIAL_PROTOCOLLNPGM("Mesh invalidated. Probing mesh."); | ||||
|           } | ||||
|           if (g29_verbose_level > 1) { | ||||
|             SERIAL_PROTOCOLPAIR("Probing Mesh Points Closest to (", x_pos); | ||||
| @@ -455,7 +455,7 @@ | ||||
|           // | ||||
|           // Manually Probe Mesh in areas that can't be reached by the probe | ||||
|           // | ||||
|           SERIAL_PROTOCOLLNPGM("Manually probing unreachable mesh locations.\n"); | ||||
|           SERIAL_PROTOCOLLNPGM("Manually probing unreachable mesh locations."); | ||||
|           do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES); | ||||
|           if (!x_flag && !y_flag) { | ||||
|             /** | ||||
| @@ -485,7 +485,7 @@ | ||||
|             card_thickness = code_has_value() ? code_value_float() : measure_business_card_thickness(height); | ||||
|  | ||||
|             if (fabs(card_thickness) > 1.5) { | ||||
|               SERIAL_PROTOCOLLNPGM("?Error in Business Card measurement.\n"); | ||||
|               SERIAL_PROTOCOLLNPGM("?Error in Business Card measurement."); | ||||
|               return; | ||||
|             } | ||||
|           } | ||||
| @@ -561,17 +561,25 @@ | ||||
|     // | ||||
|  | ||||
|     if (code_seen('L')) {     // Load Current Mesh Data | ||||
|       storage_slot = code_has_value() ? code_value_int() : ubl.state.eeprom_storage_slot; | ||||
|       storage_slot = code_has_value() ? code_value_int() : ubl.state.storage_slot; | ||||
|  | ||||
|       const int16_t j = (UBL_LAST_EEPROM_INDEX - ubl.eeprom_start) / sizeof(ubl.z_values); | ||||
|       int16_t a = settings.calc_num_meshes(); | ||||
|  | ||||
|       if (!WITHIN(storage_slot, 0, j - 1) || ubl.eeprom_start <= 0) { | ||||
|         SERIAL_PROTOCOLLNPGM("?EEPROM storage not available for use.\n"); | ||||
|       if (!a) { | ||||
|         SERIAL_PROTOCOLLNPGM("?EEPROM storage not available."); | ||||
|         return; | ||||
|       } | ||||
|       ubl.load_mesh(storage_slot); | ||||
|       ubl.state.eeprom_storage_slot = storage_slot; | ||||
|       SERIAL_PROTOCOLLNPGM("Done.\n"); | ||||
|  | ||||
|       if (!WITHIN(storage_slot, 0, a - 1)) { | ||||
|         SERIAL_PROTOCOLLNPGM("?Invalid storage slot."); | ||||
|         SERIAL_PROTOCOLLNPAIR("?Use 0 to ", a - 1); | ||||
|         return; | ||||
|       } | ||||
|  | ||||
|       settings.load_mesh(storage_slot); | ||||
|       ubl.state.storage_slot = storage_slot; | ||||
|  | ||||
|       SERIAL_PROTOCOLLNPGM("Done."); | ||||
|     } | ||||
|  | ||||
|     // | ||||
| @@ -579,7 +587,7 @@ | ||||
|     // | ||||
|  | ||||
|     if (code_seen('S')) {     // Store (or Save) Current Mesh Data | ||||
|       storage_slot = code_has_value() ? code_value_int() : ubl.state.eeprom_storage_slot; | ||||
|       storage_slot = code_has_value() ? code_value_int() : ubl.state.storage_slot; | ||||
|  | ||||
|       if (storage_slot == -1) {                     // Special case, we are going to 'Export' the mesh to the | ||||
|         SERIAL_ECHOLNPGM("G29 I 999");              // host in a form it can be reconstructed on a different machine | ||||
| @@ -597,17 +605,23 @@ | ||||
|         return; | ||||
|       } | ||||
|  | ||||
|       const int16_t j = (UBL_LAST_EEPROM_INDEX - ubl.eeprom_start) / sizeof(ubl.z_values); | ||||
|       int16_t a = settings.calc_num_meshes(); | ||||
|  | ||||
|       if (!WITHIN(storage_slot, 0, j - 1) || ubl.eeprom_start <= 0) { | ||||
|         SERIAL_PROTOCOLLNPGM("?EEPROM storage not available for use.\n"); | ||||
|         SERIAL_PROTOCOLLNPAIR("?Use 0 to ", j - 1); | ||||
|       if (!a) { | ||||
|         SERIAL_PROTOCOLLNPGM("?EEPROM storage not available."); | ||||
|         goto LEAVE; | ||||
|       } | ||||
|       ubl.store_mesh(storage_slot); | ||||
|       ubl.state.eeprom_storage_slot = storage_slot; | ||||
|  | ||||
|       SERIAL_PROTOCOLLNPGM("Done.\n"); | ||||
|       if (!WITHIN(storage_slot, 0, a - 1)) { | ||||
|         SERIAL_PROTOCOLLNPGM("?Invalid storage slot."); | ||||
|         SERIAL_PROTOCOLLNPAIR("?Use 0 to ", a - 1); | ||||
|         goto LEAVE; | ||||
|       } | ||||
|  | ||||
|       settings.store_mesh(storage_slot); | ||||
|       ubl.state.storage_slot = storage_slot; | ||||
|  | ||||
|       SERIAL_PROTOCOLLNPGM("Done."); | ||||
|     } | ||||
|  | ||||
|     if (code_seen('T')) | ||||
| @@ -654,7 +668,7 @@ | ||||
|           if (ELAPSED(millis(), nxt)) { | ||||
|             SERIAL_PROTOCOLLNPGM("\nZ-Offset Adjustment Stopped."); | ||||
|             do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE); | ||||
|             LCD_MESSAGEPGM("Z-Offset Stopped"); | ||||
|             LCD_MESSAGEPGM("Z-Offset Stopped"); // TODO: Make translatable string | ||||
|             ubl.restore_ubl_active_state_and_leave(); | ||||
|             goto LEAVE; | ||||
|           } | ||||
| @@ -892,7 +906,7 @@ | ||||
|     return current_position[Z_AXIS]; | ||||
|   } | ||||
|  | ||||
|   static void say_and_take_a_measurement() { | ||||
|   static void echo_and_take_a_measurement() { | ||||
|     SERIAL_PROTOCOLLNPGM(" and take a measurement."); | ||||
|   } | ||||
|  | ||||
| @@ -906,17 +920,17 @@ | ||||
|     stepper.synchronize(); | ||||
|  | ||||
|     SERIAL_PROTOCOLPGM("Place shim under nozzle"); | ||||
|     LCD_MESSAGEPGM("Place shim & measure"); | ||||
|     LCD_MESSAGEPGM("Place shim & measure"); // TODO: Make translatable string | ||||
|     lcd_goto_screen(lcd_status_screen); | ||||
|     say_and_take_a_measurement(); | ||||
|     echo_and_take_a_measurement(); | ||||
|  | ||||
|     const float z1 = use_encoder_wheel_to_measure_point(); | ||||
|     do_blocking_move_to_z(current_position[Z_AXIS] + SIZE_OF_LITTLE_RAISE); | ||||
|     stepper.synchronize(); | ||||
|  | ||||
|     SERIAL_PROTOCOLPGM("Remove shim"); | ||||
|     LCD_MESSAGEPGM("Remove & measure bed"); | ||||
|     say_and_take_a_measurement(); | ||||
|     LCD_MESSAGEPGM("Remove & measure bed"); // TODO: Make translatable string | ||||
|     echo_and_take_a_measurement(); | ||||
|  | ||||
|     const float z2 = use_encoder_wheel_to_measure_point(); | ||||
|  | ||||
| @@ -962,7 +976,7 @@ | ||||
|  | ||||
|       do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES); | ||||
|  | ||||
|       LCD_MESSAGEPGM("Moving to next"); | ||||
|       LCD_MESSAGEPGM("Moving to next"); // TODO: Make translatable string | ||||
|  | ||||
|       do_blocking_move_to_xy(xProbe, yProbe); | ||||
|       do_blocking_move_to_z(z_clearance); | ||||
| @@ -972,8 +986,10 @@ | ||||
|  | ||||
|       if (do_ubl_mesh_map) ubl.display_map(map_type);  // show user where we're probing | ||||
|  | ||||
|       if (code_seen('B')) {LCD_MESSAGEPGM("Place shim & measure");} | ||||
|       else {LCD_MESSAGEPGM("Measure");} | ||||
|       if (code_seen('B')) | ||||
|         LCD_MESSAGEPGM("Place shim & measure"); // TODO: Make translatable string | ||||
|       else | ||||
|         LCD_MESSAGEPGM("Measure"); // TODO: Make translatable string | ||||
|  | ||||
|       while (ubl_lcd_clicked()) delay(50);             // wait for user to release encoder wheel | ||||
|       delay(50);                                       // debounce | ||||
| @@ -1017,21 +1033,10 @@ | ||||
|     do_blocking_move_to_xy(lx, ly); | ||||
|   } | ||||
|  | ||||
|   static void say_ubl_name() { | ||||
|     SERIAL_PROTOCOLPGM("Unified Bed Leveling "); | ||||
|   } | ||||
|  | ||||
|   static void report_ubl_state() { | ||||
|     say_ubl_name(); | ||||
|     SERIAL_PROTOCOLPGM("System "); | ||||
|     if (!ubl.state.active) SERIAL_PROTOCOLPGM("de"); | ||||
|     SERIAL_PROTOCOLLNPGM("activated.\n"); | ||||
|   } | ||||
|  | ||||
|   bool g29_parameter_parsing() { | ||||
|     bool err_flag = false; | ||||
|  | ||||
|     LCD_MESSAGEPGM("Doing G29 UBL!"); | ||||
|     LCD_MESSAGEPGM("Doing G29 UBL!"); // TODO: Make translatable string | ||||
|     lcd_quick_feedback(); | ||||
|  | ||||
|     ubl_constant = 0.0; | ||||
| @@ -1096,12 +1101,12 @@ | ||||
|         SERIAL_PROTOCOLLNPGM("?Can't activate and deactivate at the same time.\n"); | ||||
|         return UBL_ERR; | ||||
|       } | ||||
|       ubl.state.active = 1; | ||||
|       report_ubl_state(); | ||||
|       ubl.state.active = true; | ||||
|       ubl.report_state(); | ||||
|     } | ||||
|     else if (code_seen('D')) { | ||||
|       ubl.state.active = 0; | ||||
|       report_ubl_state(); | ||||
|       ubl.state.active = false; | ||||
|       ubl.report_state(); | ||||
|     } | ||||
|  | ||||
|     // Set global 'C' flag and its value | ||||
| @@ -1134,7 +1139,7 @@ | ||||
|     ubl_state_recursion_chk++; | ||||
|     if (ubl_state_recursion_chk != 1) { | ||||
|       SERIAL_ECHOLNPGM("save_ubl_active_state_and_disabled() called multiple times in a row."); | ||||
|       LCD_MESSAGEPGM("save_UBL_active() error"); | ||||
|       LCD_MESSAGEPGM("save_UBL_active() error"); // TODO: Make translatable string | ||||
|       lcd_quick_feedback(); | ||||
|       return; | ||||
|     } | ||||
| @@ -1145,7 +1150,7 @@ | ||||
|   void unified_bed_leveling::restore_ubl_active_state_and_leave() { | ||||
|     if (--ubl_state_recursion_chk) { | ||||
|       SERIAL_ECHOLNPGM("restore_ubl_active_state_and_leave() called too many times."); | ||||
|       LCD_MESSAGEPGM("restore_UBL_active() error"); | ||||
|       LCD_MESSAGEPGM("restore_UBL_active() error"); // TODO: Make translatable string | ||||
|       lcd_quick_feedback(); | ||||
|       return; | ||||
|     } | ||||
| @@ -1157,21 +1162,12 @@ | ||||
|    * good to have the extra information. Soon... we prune this to just a few items | ||||
|    */ | ||||
|   void unified_bed_leveling::g29_what_command() { | ||||
|     const uint16_t k = E2END - ubl.eeprom_start; | ||||
|     report_state(); | ||||
|  | ||||
|     say_ubl_name(); | ||||
|     SERIAL_PROTOCOLPGM("System Version " UBL_VERSION " "); | ||||
|     if (state.active) | ||||
|       SERIAL_PROTOCOLCHAR('A'); | ||||
|     else | ||||
|       SERIAL_PROTOCOLPGM("Ina"); | ||||
|     SERIAL_PROTOCOLLNPGM("ctive.\n"); | ||||
|     safe_delay(50); | ||||
|  | ||||
|     if (state.eeprom_storage_slot == -1) | ||||
|     if (state.storage_slot == -1) | ||||
|       SERIAL_PROTOCOLPGM("No Mesh Loaded."); | ||||
|     else { | ||||
|       SERIAL_PROTOCOLPAIR("Mesh ", state.eeprom_storage_slot); | ||||
|       SERIAL_PROTOCOLPAIR("Mesh ", state.storage_slot); | ||||
|       SERIAL_PROTOCOLPGM(" Loaded."); | ||||
|     } | ||||
|     SERIAL_EOL; | ||||
| @@ -1188,12 +1184,15 @@ | ||||
|     SERIAL_PROTOCOL_F(zprobe_zoffset, 7); | ||||
|     SERIAL_EOL; | ||||
|  | ||||
|     SERIAL_PROTOCOLLNPAIR("ubl.eeprom_start=", hex_address((void*)eeprom_start)); | ||||
|  | ||||
|     SERIAL_ECHOLNPAIR("UBL_MESH_MIN_X  " STRINGIFY(UBL_MESH_MIN_X) "=", UBL_MESH_MIN_X); | ||||
|     SERIAL_ECHOLNPAIR("UBL_MESH_MIN_Y  " STRINGIFY(UBL_MESH_MIN_Y) "=", UBL_MESH_MIN_Y); | ||||
|     safe_delay(25); | ||||
|     SERIAL_ECHOLNPAIR("UBL_MESH_MAX_X  " STRINGIFY(UBL_MESH_MAX_X) "=", UBL_MESH_MAX_X); | ||||
|     SERIAL_ECHOLNPAIR("UBL_MESH_MAX_Y  " STRINGIFY(UBL_MESH_MAX_Y) "=", UBL_MESH_MAX_Y); | ||||
|     safe_delay(25); | ||||
|     SERIAL_ECHOLNPAIR("GRID_MAX_POINTS_X  ", GRID_MAX_POINTS_X); | ||||
|     SERIAL_ECHOLNPAIR("GRID_MAX_POINTS_Y  ", GRID_MAX_POINTS_Y); | ||||
|     safe_delay(25); | ||||
|  | ||||
|     SERIAL_ECHOLNPAIR("MESH_X_DIST  ", MESH_X_DIST); | ||||
|     SERIAL_ECHOLNPAIR("MESH_Y_DIST  ", MESH_Y_DIST); | ||||
|     safe_delay(25); | ||||
| @@ -1214,43 +1213,39 @@ | ||||
|     } | ||||
|     SERIAL_EOL; | ||||
|  | ||||
|     SERIAL_PROTOCOLLNPAIR("Free EEPROM space starts at: ", hex_address((void*)eeprom_start)); | ||||
|     SERIAL_PROTOCOLLNPAIR("end of EEPROM: ", hex_address((void*)E2END)); | ||||
|     safe_delay(25); | ||||
|     #if HAS_KILL | ||||
|       SERIAL_PROTOCOLPAIR("Kill pin on :", KILL_PIN); | ||||
|       SERIAL_PROTOCOLLNPAIR("  state:", READ(KILL_PIN)); | ||||
|     #endif | ||||
|     SERIAL_EOL; | ||||
|     safe_delay(50); | ||||
|  | ||||
|     SERIAL_PROTOCOLPAIR("sizeof(ubl.state) : ", (int)sizeof(state)); | ||||
|     SERIAL_PROTOCOLLNPAIR("ubl_state_at_invocation :", ubl_state_at_invocation); | ||||
|     SERIAL_EOL; | ||||
|     SERIAL_PROTOCOLLNPAIR("ubl_state_recursion_chk :", ubl_state_recursion_chk); | ||||
|     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())); | ||||
|     safe_delay(50); | ||||
|  | ||||
|     SERIAL_PROTOCOLLNPAIR("sizeof(ubl) :  ", (int)sizeof(ubl)); | ||||
|     SERIAL_EOL; | ||||
|     SERIAL_PROTOCOLLNPAIR("z_value[][] size: ", (int)sizeof(z_values)); | ||||
|     SERIAL_EOL; | ||||
|     safe_delay(25); | ||||
|  | ||||
|     SERIAL_PROTOCOLLNPAIR("EEPROM free for UBL: ", hex_address((void*)k)); | ||||
|     safe_delay(25); | ||||
|     SERIAL_PROTOCOLLNPAIR("EEPROM free for UBL: ", hex_address((void*)(settings.get_end_of_meshes() - settings.get_start_of_meshes()))); | ||||
|     safe_delay(50); | ||||
|  | ||||
|     SERIAL_PROTOCOLPAIR("EEPROM can hold ", k / sizeof(z_values)); | ||||
|     SERIAL_PROTOCOLPAIR("EEPROM can hold ", settings.calc_num_meshes()); | ||||
|     SERIAL_PROTOCOLLNPGM(" meshes.\n"); | ||||
|     safe_delay(25); | ||||
|  | ||||
|     SERIAL_PROTOCOLPAIR("\nGRID_MAX_POINTS_X  ", GRID_MAX_POINTS_X); | ||||
|     SERIAL_PROTOCOLPAIR("\nGRID_MAX_POINTS_Y  ", GRID_MAX_POINTS_Y); | ||||
|     safe_delay(25); | ||||
|     SERIAL_EOL; | ||||
|  | ||||
|     SERIAL_ECHOPGM("UBL_MESH_MIN_X  " STRINGIFY(UBL_MESH_MIN_X)); | ||||
|     SERIAL_ECHOLNPAIR("=", UBL_MESH_MIN_X ); | ||||
|     SERIAL_ECHOPGM("UBL_MESH_MIN_Y  " STRINGIFY(UBL_MESH_MIN_Y)); | ||||
|     SERIAL_ECHOLNPAIR("=", UBL_MESH_MIN_Y ); | ||||
|     safe_delay(25); | ||||
|  | ||||
|     SERIAL_ECHOPGM("UBL_MESH_MAX_X  " STRINGIFY(UBL_MESH_MAX_X)); | ||||
|     SERIAL_ECHOLNPAIR("=", UBL_MESH_MAX_X); | ||||
|     SERIAL_ECHOPGM("UBL_MESH_MAX_Y  " STRINGIFY(UBL_MESH_MAX_Y)); | ||||
|     SERIAL_ECHOLNPAIR("=", UBL_MESH_MAX_Y); | ||||
|     safe_delay(25); | ||||
|  | ||||
|     if (!sanity_check()) { | ||||
|       say_ubl_name(); | ||||
|       SERIAL_PROTOCOLLNPGM("sanity checks passed."); | ||||
|       echo_name(); | ||||
|       SERIAL_PROTOCOLLNPGM(" sanity checks passed."); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -1284,27 +1279,32 @@ | ||||
|    * use cases for the users. So we can wait and see what to do with it. | ||||
|    */ | ||||
|   void g29_compare_current_mesh_to_stored_mesh() { | ||||
|     float tmp_z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; | ||||
|     int16_t a = settings.calc_num_meshes(); | ||||
|  | ||||
|     if (!a) { | ||||
|       SERIAL_PROTOCOLLNPGM("?EEPROM storage not available."); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     if (!code_has_value()) { | ||||
|       SERIAL_PROTOCOLLNPGM("?Mesh # required.\n"); | ||||
|       SERIAL_PROTOCOLLNPGM("?Storage slot # required."); | ||||
|       SERIAL_PROTOCOLLNPAIR("?Use 0 to ", a - 1); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     storage_slot = code_value_int(); | ||||
|  | ||||
|     int16_t j = (UBL_LAST_EEPROM_INDEX - ubl.eeprom_start) / sizeof(tmp_z_values); | ||||
|  | ||||
|     if (!WITHIN(storage_slot, 0, j - 1) || ubl.eeprom_start <= 0) { | ||||
|       SERIAL_PROTOCOLLNPGM("?EEPROM storage not available for use.\n"); | ||||
|     if (!WITHIN(storage_slot, 0, a - 1)) { | ||||
|       SERIAL_PROTOCOLLNPGM("?Invalid storage slot."); | ||||
|       SERIAL_PROTOCOLLNPAIR("?Use 0 to ", a - 1); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     j = UBL_LAST_EEPROM_INDEX - (storage_slot + 1) * sizeof(tmp_z_values); | ||||
|     eeprom_read_block((void *)&tmp_z_values, (void *)j, sizeof(tmp_z_values)); | ||||
|     float tmp_z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; | ||||
|     settings.load_mesh(storage_slot, &tmp_z_values); | ||||
|  | ||||
|     SERIAL_ECHOPAIR("Subtracting Mesh ", storage_slot); | ||||
|     SERIAL_PROTOCOLLNPAIR(" loaded from EEPROM address ", hex_address((void*)j)); // Soon, we can remove the extra clutter of printing | ||||
|                                                                         // the address in the EEPROM where the Mesh is stored. | ||||
|     SERIAL_PROTOCOLPAIR("Subtracting mesh in slot ", storage_slot); | ||||
|     SERIAL_PROTOCOLLNPGM(" from current mesh."); | ||||
|  | ||||
|     for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++) | ||||
|       for (uint8_t y = 0; y < GRID_MAX_POINTS_Y; y++) | ||||
| @@ -1396,7 +1396,7 @@ | ||||
|  | ||||
|     memset(not_done, 0xFF, sizeof(not_done)); | ||||
|  | ||||
|     LCD_MESSAGEPGM("Fine Tuning Mesh"); | ||||
|     LCD_MESSAGEPGM("Fine Tuning Mesh"); // TODO: Make translatable string | ||||
|  | ||||
|     do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE); | ||||
|     do_blocking_move_to_xy(lx, ly); | ||||
| @@ -1454,7 +1454,7 @@ | ||||
|           lcd_return_to_status(); | ||||
|           //SERIAL_PROTOCOLLNPGM("\nFine Tuning of Mesh Stopped."); | ||||
|           do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE); | ||||
|           LCD_MESSAGEPGM("Mesh Editing Stopped"); | ||||
|           LCD_MESSAGEPGM("Mesh Editing Stopped"); // TODO: Make translatable string | ||||
|  | ||||
|           while (ubl_lcd_clicked()) idle(); | ||||
|  | ||||
| @@ -1481,7 +1481,7 @@ | ||||
|  | ||||
|     do_blocking_move_to_xy(lx, ly); | ||||
|  | ||||
|     LCD_MESSAGEPGM("Done Editing Mesh"); | ||||
|     LCD_MESSAGEPGM("Done Editing Mesh"); // TODO: Make translatable string | ||||
|     SERIAL_ECHOLNPGM("Done Editing Mesh"); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -1425,10 +1425,6 @@ void kill_screen(const char* lcd_msg) { | ||||
|  | ||||
|     static uint8_t manual_probe_index; | ||||
|  | ||||
|     #if ENABLED(PROBE_MANUALLY) | ||||
|       extern bool g29_in_progress; | ||||
|     #endif | ||||
|  | ||||
|     // LCD probed points are from defaults | ||||
|     constexpr uint8_t total_probe_points = ( | ||||
|       #if ENABLED(AUTO_BED_LEVELING_3POINT) | ||||
| @@ -1645,6 +1641,10 @@ void kill_screen(const char* lcd_msg) { | ||||
|  | ||||
|   #if ENABLED(LCD_BED_LEVELING) || HAS_ABL | ||||
|  | ||||
|     #if ENABLED(PROBE_MANUALLY) | ||||
|       extern bool g29_in_progress; | ||||
|     #endif | ||||
|  | ||||
|     /** | ||||
|      * Step 2: Continue Bed Leveling... | ||||
|      */ | ||||
|   | ||||
| @@ -34,6 +34,19 @@ void safe_delay(millis_t ms) { | ||||
|   thermalManager.manage_heater(); // This keeps us safe if too many small safe_delay() calls are made | ||||
| } | ||||
|  | ||||
| #if ENABLED(EEPROM_SETTINGS) | ||||
|  | ||||
|   void crc16(uint16_t *crc, const void * const data, uint16_t cnt) { | ||||
|     uint8_t *ptr = (uint8_t*)data; | ||||
|     while (cnt-- > 0) { | ||||
|       *crc = (uint16_t)(*crc ^ (uint16_t)(((uint16_t)*ptr++) << 8)); | ||||
|       for (uint8_t x = 0; x < 8; x++) | ||||
|         *crc = (uint16_t)((*crc & 0x8000) ? ((uint16_t)(*crc << 1) ^ 0x1021) : (*crc << 1)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| #endif // EEPROM_SETTINGS | ||||
|  | ||||
| #if ENABLED(ULTRA_LCD) | ||||
|  | ||||
|   char conv[8] = { 0 }; | ||||
|   | ||||
| @@ -25,6 +25,10 @@ | ||||
|  | ||||
| void safe_delay(millis_t ms); | ||||
|  | ||||
| #if ENABLED(EEPROM_SETTINGS) | ||||
|   void crc16(uint16_t *crc, const void * const data, uint16_t cnt); | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(ULTRA_LCD) | ||||
|  | ||||
|   // Convert unsigned int to string with 12 format | ||||
|   | ||||
		Reference in New Issue
	
	Block a user