Преглед на файлове

Implement CRC16, develop mesh allocation table

 - Add crc16 utility function
 - Implement CRC16 for config store, remove old checksum, increment layout version
 - Move UBL mesh store/load to MarlinSettings; increment UBL_VERSION
 - Begin to lay out MAT structure, prototype functions, etc.
 - Rename ubl.state.eeprom_storage_slot to .storage_slot
 - Misc. optimization
 - Cleanup/standardize/improve some messages

This is a work in progress!
Brian преди 7 години
родител
ревизия
7852369987
променени са 8 файла, в които са добавени 299 реда и са изтрити 194 реда
  1. 14
    7
      Marlin/Marlin_main.cpp
  2. 157
    57
      Marlin/configuration_store.cpp
  3. 24
    4
      Marlin/configuration_store.h
  4. 4
    50
      Marlin/ubl.cpp
  5. 3
    11
      Marlin/ubl.h
  6. 80
    65
      Marlin/ubl_G29.cpp
  7. 13
    0
      Marlin/utility.cpp
  8. 4
    0
      Marlin/utility.h

+ 14
- 7
Marlin/Marlin_main.cpp Целия файл

@@ -8341,15 +8341,22 @@ void quickstop_stepper() {
8341 8341
     #if ENABLED(AUTO_BED_LEVELING_UBL)
8342 8342
       // L to load a mesh from the EEPROM
8343 8343
       if (code_seen('L')) {
8344
-        const int8_t storage_slot = code_has_value() ? code_value_int() : ubl.state.eeprom_storage_slot;
8345
-        const int16_t j = (UBL_LAST_EEPROM_INDEX - ubl.eeprom_start) / sizeof(ubl.z_values);
8346
-        if (!WITHIN(storage_slot, 0, j - 1) || ubl.eeprom_start <= 0) {
8347
-          SERIAL_PROTOCOLLNPGM("?EEPROM storage not available for use.\n");
8344
+        const int8_t storage_slot = code_has_value() ? code_value_int() : ubl.state.storage_slot;
8345
+        const int16_t a = settings.calc_num_meshes();
8346
+
8347
+        if (!a) {
8348
+          SERIAL_PROTOCOLLNPGM("?EEPROM storage not available.");
8349
+          return;
8350
+        }
8351
+
8352
+        if (!WITHIN(storage_slot, 0, a - 1)) {
8353
+          SERIAL_PROTOCOLLNPGM("?Invalid storage slot.");
8354
+          SERIAL_PROTOCOLLNPAIR("?Use 0 to ", a - 1);
8348 8355
           return;
8349 8356
         }
8350 8357
 
8351
-        ubl.load_mesh(storage_slot);
8352
-        ubl.state.eeprom_storage_slot = storage_slot;
8358
+        settings.load_mesh(storage_slot);
8359
+        ubl.state.storage_slot = storage_slot;
8353 8360
       }
8354 8361
     #endif // AUTO_BED_LEVELING_UBL
8355 8362
 
@@ -8377,7 +8384,7 @@ void quickstop_stepper() {
8377 8384
       if (code_seen('L') || code_seen('V')) {
8378 8385
         ubl.display_map(0);  // Currently only supports one map type
8379 8386
         SERIAL_ECHOLNPAIR("UBL_MESH_VALID = ", UBL_MESH_VALID);
8380
-        SERIAL_ECHOLNPAIR("eeprom_storage_slot = ", ubl.state.eeprom_storage_slot);
8387
+        SERIAL_ECHOLNPAIR("ubl.state.storage_slot = ", ubl.state.storage_slot);
8381 8388
       }
8382 8389
     #endif
8383 8390
 

+ 157
- 57
Marlin/configuration_store.cpp Целия файл

@@ -36,16 +36,16 @@
36 36
  *
37 37
  */
38 38
 
39
-#define EEPROM_VERSION "V37"
39
+#define EEPROM_VERSION "V38"
40 40
 
41 41
 // Change EEPROM version if these are changed:
42 42
 #define EEPROM_OFFSET 100
43 43
 
44 44
 /**
45
- * V37 EEPROM Layout:
45
+ * V38 EEPROM Layout:
46 46
  *
47 47
  *  100  Version                                    (char x4)
48
- *  104  EEPROM Checksum                            (uint16_t)
48
+ *  104  EEPROM CRC16                               (uint16_t)
49 49
  *
50 50
  *  106            E_STEPPERS                       (uint8_t)
51 51
  *  107  M92 XYZE  planner.axis_steps_per_mm        (float x4 ... x8)
@@ -90,7 +90,7 @@
90 90
  * AUTO_BED_LEVELING_UBL:                           6 bytes
91 91
  *  324  G29 A     ubl.state.active                 (bool)
92 92
  *  325  G29 Z     ubl.state.z_offset               (float)
93
- *  329  G29 S     ubl.state.eeprom_storage_slot    (int8_t)
93
+ *  329  G29 S     ubl.state.storage_slot           (int8_t)
94 94
  *
95 95
  * DELTA:                                           48 bytes
96 96
  *  348  M666 XYZ  endstop_adj                      (float x3)
@@ -158,6 +158,14 @@
158 158
  *
159 159
  *  588                                Minimum end-point
160 160
  * 1909 (588 + 36 + 9 + 288 + 988)     Maximum end-point
161
+ *
162
+ * ========================================================================
163
+ * meshes_begin (between max and min end-point, directly above)
164
+ * -- MESHES --
165
+ * meshes_end
166
+ * -- MAT (Mesh Allocation Table) --                128 bytes (placeholder size)
167
+ * mat_end = E2END (0xFFF)
168
+ *
161 169
  */
162 170
 #include "configuration_store.h"
163 171
 
@@ -230,18 +238,26 @@ void MarlinSettings::postprocess() {
230 238
 
231 239
 #if ENABLED(EEPROM_SETTINGS)
232 240
 
241
+  #define DUMMY_PID_VALUE 3000.0f
242
+  #define EEPROM_START() int eeprom_index = EEPROM_OFFSET
243
+  #define EEPROM_SKIP(VAR) eeprom_index += sizeof(VAR)
244
+  #define EEPROM_WRITE(VAR) write_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR), &working_crc)
245
+  #define EEPROM_READ(VAR) read_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR), &working_crc)
246
+  #define EEPROM_ASSERT(TST,ERR) if (!(TST)) do{ SERIAL_ERROR_START; SERIAL_ERRORLNPGM(ERR); eeprom_read_error = true; }while(0)
247
+
233 248
   const char version[4] = EEPROM_VERSION;
234 249
 
235
-  uint16_t MarlinSettings::eeprom_checksum;
250
+  bool MarlinSettings::eeprom_error;
236 251
 
237
-  bool MarlinSettings::eeprom_write_error,
238
-       MarlinSettings::eeprom_read_error;
252
+  #if ENABLED(AUTO_BED_LEVELING_UBL)
253
+    int MarlinSettings::meshes_begin;
254
+  #endif
239 255
 
240
-  void MarlinSettings::write_data(int &pos, const uint8_t* value, uint16_t size) {
241
-    if (eeprom_write_error) return;
256
+  void MarlinSettings::write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc) {
257
+    if (eeprom_error) return;
242 258
     while (size--) {
243 259
       uint8_t * const p = (uint8_t * const)pos;
244
-      const uint8_t v = *value;
260
+      uint8_t v = *value;
245 261
       // EEPROM has only ~100,000 write cycles,
246 262
       // so only write bytes that have changed!
247 263
       if (v != eeprom_read_byte(p)) {
@@ -249,32 +265,27 @@ void MarlinSettings::postprocess() {
249 265
         if (eeprom_read_byte(p) != v) {
250 266
           SERIAL_ECHO_START;
251 267
           SERIAL_ECHOLNPGM(MSG_ERR_EEPROM_WRITE);
252
-          eeprom_write_error = true;
268
+          eeprom_error = true;
253 269
           return;
254 270
         }
255 271
       }
256
-      eeprom_checksum += v;
272
+      crc16(crc, &v, 1);
257 273
       pos++;
258 274
       value++;
259 275
     };
260 276
   }
261
-  void MarlinSettings::read_data(int &pos, uint8_t* value, uint16_t size) {
277
+
278
+  void MarlinSettings::read_data(int &pos, uint8_t* value, uint16_t size, uint16_t *crc) {
279
+    if (eeprom_error) return;
262 280
     do {
263 281
       uint8_t c = eeprom_read_byte((unsigned char*)pos);
264
-      if (!eeprom_read_error) *value = c;
265
-      eeprom_checksum += c;
282
+      *value = c;
283
+      crc16(crc, &c, 1);
266 284
       pos++;
267 285
       value++;
268 286
     } while (--size);
269 287
   }
270 288
 
271
-  #define DUMMY_PID_VALUE 3000.0f
272
-  #define EEPROM_START() int eeprom_index = EEPROM_OFFSET
273
-  #define EEPROM_SKIP(VAR) eeprom_index += sizeof(VAR)
274
-  #define EEPROM_WRITE(VAR) write_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR))
275
-  #define EEPROM_READ(VAR) read_data(eeprom_index, (uint8_t*)&VAR, sizeof(VAR))
276
-  #define EEPROM_ASSERT(TST,ERR) if (!(TST)) do{ SERIAL_ERROR_START; SERIAL_ERRORLNPGM(ERR); eeprom_read_error = true; }while(0)
277
-
278 289
   /**
279 290
    * M500 - Store Configuration
280 291
    */
@@ -282,14 +293,16 @@ void MarlinSettings::postprocess() {
282 293
     float dummy = 0.0f;
283 294
     char ver[4] = "000";
284 295
 
296
+    uint16_t working_crc = 0;
297
+
285 298
     EEPROM_START();
286 299
 
287
-    eeprom_write_error = false;
300
+    eeprom_error = false;
288 301
 
289 302
     EEPROM_WRITE(ver);     // invalidate data first
290
-    EEPROM_SKIP(eeprom_checksum); // Skip the checksum slot
303
+    EEPROM_SKIP(working_crc); // Skip the checksum slot
291 304
 
292
-    eeprom_checksum = 0; // clear before first "real data"
305
+    working_crc = 0; // clear before first "real data"
293 306
 
294 307
     const uint8_t esteppers = COUNT(planner.axis_steps_per_mm) - XYZ;
295 308
     EEPROM_WRITE(esteppers);
@@ -410,14 +423,14 @@ void MarlinSettings::postprocess() {
410 423
     #if ENABLED(AUTO_BED_LEVELING_UBL)
411 424
       EEPROM_WRITE(ubl.state.active);
412 425
       EEPROM_WRITE(ubl.state.z_offset);
413
-      EEPROM_WRITE(ubl.state.eeprom_storage_slot);
426
+      EEPROM_WRITE(ubl.state.storage_slot);
414 427
     #else
415 428
       const bool ubl_active = 0;
416 429
       dummy = 0.0f;
417
-      const int8_t eeprom_slot = -1;
430
+      const int8_t storage_slot = -1;
418 431
       EEPROM_WRITE(ubl_active);
419 432
       EEPROM_WRITE(dummy);
420
-      EEPROM_WRITE(eeprom_slot);
433
+      EEPROM_WRITE(storage_slot);
421 434
     #endif // AUTO_BED_LEVELING_UBL
422 435
 
423 436
     // 9 floats for DELTA / Z_DUAL_ENDSTOPS
@@ -609,43 +622,42 @@ void MarlinSettings::postprocess() {
609 622
       EEPROM_WRITE(dummy);
610 623
     #endif
611 624
 
612
-    if (!eeprom_write_error) {
613
-
614
-      const uint16_t final_checksum = eeprom_checksum,
615
-                     eeprom_size = eeprom_index;
625
+    if (!eeprom_error) {
626
+      const int eeprom_size = eeprom_index;
616 627
 
617 628
       // Write the EEPROM header
618 629
       eeprom_index = EEPROM_OFFSET;
619 630
       EEPROM_WRITE(version);
620
-      EEPROM_WRITE(final_checksum);
631
+      EEPROM_WRITE(working_crc);
621 632
 
622 633
       // Report storage size
623 634
       SERIAL_ECHO_START;
624 635
       SERIAL_ECHOPAIR("Settings Stored (", eeprom_size - (EEPROM_OFFSET));
625
-      SERIAL_ECHOLNPGM(" bytes)");
636
+      SERIAL_ECHOPAIR(" bytes; crc ", working_crc);
637
+      SERIAL_ECHOLNPGM(")");
626 638
     }
627 639
 
628 640
     #if ENABLED(UBL_SAVE_ACTIVE_ON_M500)
629
-      if (ubl.state.eeprom_storage_slot >= 0)
630
-        ubl.store_mesh(ubl.state.eeprom_storage_slot);
641
+      if (ubl.state.storage_slot >= 0)
642
+        store_mesh(ubl.state.storage_slot);
631 643
     #endif
632 644
 
633
-    return !eeprom_write_error;
645
+    return !eeprom_error;
634 646
   }
635 647
 
636 648
   /**
637 649
    * M501 - Retrieve Configuration
638 650
    */
639 651
   bool MarlinSettings::load() {
652
+    uint16_t working_crc = 0;
640 653
 
641 654
     EEPROM_START();
642
-    eeprom_read_error = false; // If set EEPROM_READ won't write into RAM
643 655
 
644 656
     char stored_ver[4];
645 657
     EEPROM_READ(stored_ver);
646 658
 
647
-    uint16_t stored_checksum;
648
-    EEPROM_READ(stored_checksum);
659
+    uint16_t stored_crc;
660
+    EEPROM_READ(stored_crc);
649 661
 
650 662
     // Version has to match or defaults are used
651 663
     if (strncmp(version, stored_ver, 3) != 0) {
@@ -662,7 +674,7 @@ void MarlinSettings::postprocess() {
662 674
     else {
663 675
       float dummy = 0;
664 676
 
665
-      eeprom_checksum = 0; // clear before reading first "real data"
677
+      working_crc = 0; //clear before reading first "real data"
666 678
 
667 679
       // Number of esteppers may change
668 680
       uint8_t esteppers;
@@ -788,7 +800,7 @@ void MarlinSettings::postprocess() {
788 800
       #if ENABLED(AUTO_BED_LEVELING_UBL)
789 801
         EEPROM_READ(ubl.state.active);
790 802
         EEPROM_READ(ubl.state.z_offset);
791
-        EEPROM_READ(ubl.state.eeprom_storage_slot);
803
+        EEPROM_READ(ubl.state.storage_slot);
792 804
       #else
793 805
         bool dummyb;
794 806
         uint8_t dummyui8;
@@ -960,27 +972,28 @@ void MarlinSettings::postprocess() {
960 972
         EEPROM_READ(dummy);
961 973
       #endif
962 974
 
963
-      if (eeprom_checksum == stored_checksum) {
964
-        if (eeprom_read_error)
965
-          reset();
966
-        else {
975
+      if (working_crc == stored_crc) {
967 976
           postprocess();
968 977
           SERIAL_ECHO_START;
969 978
           SERIAL_ECHO(version);
970 979
           SERIAL_ECHOPAIR(" stored settings retrieved (", eeprom_index - (EEPROM_OFFSET));
971
-          SERIAL_ECHOLNPGM(" bytes)");
972
-        }
980
+          SERIAL_ECHOPAIR(" bytes; crc ", working_crc);
981
+          SERIAL_ECHOLNPGM(")");
973 982
       }
974 983
       else {
975 984
         SERIAL_ERROR_START;
976
-        SERIAL_ERRORLNPGM("EEPROM checksum mismatch");
985
+        SERIAL_ERRORPGM("EEPROM checksum mismatch - (stored CRC)");
986
+        SERIAL_ERROR(stored_crc);
987
+        SERIAL_ERRORPGM(" != ");
988
+        SERIAL_ERROR(working_crc);
989
+        SERIAL_ERRORLNPGM(" (calculated CRC)!");
977 990
         reset();
978 991
       }
979 992
 
980 993
       #if ENABLED(AUTO_BED_LEVELING_UBL)
981
-        ubl.eeprom_start = (eeprom_index + 32) & 0xFFF8; // Pad the end of configuration data so it
982
-                                                         // can float up or down a little bit without
983
-                                                         // disrupting the Unified Bed Leveling data
994
+        meshes_begin = (eeprom_index + 32) & 0xFFF8;   // Pad the end of configuration data so it
995
+                                                          // can float up or down a little bit without
996
+                                                          // disrupting the mesh data
984 997
         SERIAL_ECHOPGM(" UBL ");
985 998
         if (!ubl.state.active) SERIAL_ECHO("not ");
986 999
         SERIAL_ECHOLNPGM("active!");
@@ -993,9 +1006,9 @@ void MarlinSettings::postprocess() {
993 1006
           ubl.reset();
994 1007
         }
995 1008
 
996
-        if (ubl.state.eeprom_storage_slot >= 0) {
997
-          ubl.load_mesh(ubl.state.eeprom_storage_slot);
998
-          SERIAL_ECHOPAIR("Mesh ", ubl.state.eeprom_storage_slot);
1009
+        if (ubl.state.storage_slot >= 0) {
1010
+          load_mesh(ubl.state.storage_slot);
1011
+          SERIAL_ECHOPAIR("Mesh ", ubl.state.storage_slot);
999 1012
           SERIAL_ECHOLNPGM(" loaded from storage.");
1000 1013
         }
1001 1014
         else {
@@ -1009,9 +1022,85 @@ void MarlinSettings::postprocess() {
1009 1022
       report();
1010 1023
     #endif
1011 1024
 
1012
-    return !eeprom_read_error;
1025
+    return !eeprom_error;
1013 1026
   }
1014 1027
 
1028
+
1029
+  #if ENABLED(AUTO_BED_LEVELING_UBL)
1030
+
1031
+    int MarlinSettings::calc_num_meshes() {
1032
+      //obviously this will get more sophisticated once we've added an actual MAT
1033
+
1034
+      if (meshes_begin <= 0) return 0;
1035
+
1036
+      return (meshes_end - meshes_begin) / sizeof(ubl.z_values);
1037
+    }
1038
+
1039
+    void MarlinSettings::store_mesh(int8_t slot) {
1040
+
1041
+      #if ENABLED(AUTO_BED_LEVELING_UBL)
1042
+        const int a = calc_num_meshes();
1043
+        if (!WITHIN(slot, 0, a - 1)) {
1044
+          SERIAL_PROTOCOLLNPGM("?Invalid slot.");
1045
+          SERIAL_PROTOCOL(a);
1046
+          SERIAL_PROTOCOLLNPGM(" mesh slots available.");
1047
+          SERIAL_PROTOCOLLNPAIR("E2END      : ", E2END);
1048
+          SERIAL_PROTOCOLLNPAIR("meshes_end : ", (int)meshes_end);
1049
+          SERIAL_PROTOCOLLNPAIR("slot       : ", slot);
1050
+          SERIAL_EOL;
1051
+          return;
1052
+        }
1053
+
1054
+        uint16_t crc = 0;
1055
+        int pos = meshes_end - (slot + 1) * sizeof(ubl.z_values);
1056
+
1057
+        write_data(pos, (uint8_t *)&ubl.z_values, sizeof(ubl.z_values), &crc);
1058
+
1059
+        // Write crc to MAT along with other data, or just tack on to the beginning or end
1060
+
1061
+        SERIAL_PROTOCOLPAIR("Mesh saved in slot ", slot);
1062
+
1063
+      #else
1064
+
1065
+        // Other mesh types
1066
+
1067
+      #endif
1068
+    }
1069
+
1070
+    void MarlinSettings::load_mesh(int8_t slot, void *into /* = 0 */) {
1071
+
1072
+      #if ENABLED(AUTO_BED_LEVELING_UBL)
1073
+
1074
+        const int16_t a = settings.calc_num_meshes();
1075
+
1076
+        if (!WITHIN(slot, 0, a - 1)) {
1077
+          SERIAL_PROTOCOLLNPGM("?Invalid Slot.");
1078
+          SERIAL_PROTOCOL(a);
1079
+          SERIAL_PROTOCOLLNPGM(" mesh slots available.");
1080
+          return;
1081
+        }
1082
+
1083
+        uint16_t crc = 0;
1084
+        int pos = meshes_end - (slot + 1) * sizeof(ubl.z_values);
1085
+        uint8_t * const dest = into ? (uint8_t*)into : (uint8_t*)&ubl.z_values;
1086
+        read_data(pos, dest, sizeof(ubl.z_values), &crc);
1087
+
1088
+        // Compare crc with crc from MAT, or read from end
1089
+
1090
+        SERIAL_PROTOCOLPAIR("Mesh loaded from slot ", slot);
1091
+
1092
+      #else
1093
+
1094
+        // Other mesh types
1095
+
1096
+      #endif
1097
+    }
1098
+
1099
+    //void MarlinSettings::delete_mesh() { return; }
1100
+    //void MarlinSettings::defrag_meshes() { return; }
1101
+
1102
+  #endif // AUTO_BED_LEVELING_UBL
1103
+
1015 1104
 #else // !EEPROM_SETTINGS
1016 1105
 
1017 1106
   bool MarlinSettings::save() {
@@ -1458,7 +1547,18 @@ void MarlinSettings::reset() {
1458 1547
       #endif
1459 1548
       SERIAL_EOL;
1460 1549
 
1461
-      if (!forReplay) ubl.g29_what_command();
1550
+      if (!forReplay) {
1551
+        SERIAL_ECHOPGM("\nUBL is ");
1552
+        ubl.state.active ? SERIAL_CHAR('A') : SERIAL_ECHOPGM("Ina");
1553
+        SERIAL_ECHOLNPAIR("ctive\n\nActive Mesh Slot: ", ubl.state.storage_slot);
1554
+
1555
+        SERIAL_ECHOPGM("z_offset: ");
1556
+        SERIAL_ECHO_F(ubl.state.z_offset, 6);
1557
+        SERIAL_EOL;
1558
+
1559
+        SERIAL_ECHOPAIR("EEPROM can hold ", calc_num_meshes());
1560
+        SERIAL_ECHOLNPGM(" meshes.\n");
1561
+      }
1462 1562
 
1463 1563
     #elif HAS_ABL
1464 1564
 

+ 24
- 4
Marlin/configuration_store.h Целия файл

@@ -34,6 +34,18 @@ class MarlinSettings {
34 34
 
35 35
     #if ENABLED(EEPROM_SETTINGS)
36 36
       static bool load();
37
+
38
+      #if ENABLED(AUTO_BED_LEVELING_UBL) // Eventually make these available if any leveling system
39
+                                         // That can store is enabled
40
+        FORCE_INLINE static int get_start_of_meshes() { return meshes_begin; }
41
+        FORCE_INLINE static int get_end_of_meshes() { return meshes_end; }
42
+        static int calc_num_meshes();
43
+        static void store_mesh(int8_t slot);
44
+        static void load_mesh(int8_t slot, void *into = 0);
45
+
46
+        //static void delete_mesh();    // necessary if we have a MAT
47
+        //static void defrag_meshes();  // "
48
+      #endif
37 49
     #else
38 50
       FORCE_INLINE
39 51
       static bool load() { reset(); report(); return true; }
@@ -50,10 +62,18 @@ class MarlinSettings {
50 62
     static void postprocess();
51 63
 
52 64
     #if ENABLED(EEPROM_SETTINGS)
53
-      static uint16_t eeprom_checksum;
54
-      static bool eeprom_read_error, eeprom_write_error;
55
-      static void write_data(int &pos, const uint8_t* value, uint16_t size);
56
-      static void read_data(int &pos, uint8_t* value, uint16_t size);
65
+      static bool eeprom_error;
66
+
67
+      #if ENABLED(AUTO_BED_LEVELING_UBL) // Eventually make these available if any leveling system
68
+                                         // That can store is enabled
69
+        static int meshes_begin;
70
+        const static int mat_end = E2END;            // Mesh allocation table; this may not end up being necessary
71
+        const static int meshes_end = mat_end - 128; // 128 is a placeholder for the size of the MAT
72
+
73
+      #endif
74
+
75
+      static void write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc);
76
+      static void read_data(int &pos, uint8_t *value, uint16_t size, uint16_t *crc);
57 77
     #endif
58 78
 };
59 79
 

+ 4
- 50
Marlin/ubl.cpp Целия файл

@@ -63,9 +63,6 @@
63 63
   bool unified_bed_leveling::g26_debug_flag = false,
64 64
        unified_bed_leveling::has_control_of_lcd_panel = false;
65 65
 
66
-  int16_t unified_bed_leveling::eeprom_start = -1;  // Please stop changing this to 8 bits in size
67
-                                                    // It needs to hold values bigger than this.
68
-
69 66
   volatile int unified_bed_leveling::encoder_diff;
70 67
 
71 68
   unified_bed_leveling::unified_bed_leveling() {
@@ -73,53 +70,10 @@
73 70
     reset();
74 71
   }
75 72
 
76
-  void unified_bed_leveling::load_mesh(const int16_t slot) {
77
-    int16_t j = (UBL_LAST_EEPROM_INDEX - eeprom_start) / sizeof(z_values);
78
-
79
-    if (slot == -1) {
80
-      SERIAL_PROTOCOLLNPGM("?No mesh saved in EEPROM. Zeroing mesh in memory.\n");
81
-      reset();
82
-      return;
83
-    }
84
-
85
-    if (!WITHIN(slot, 0, j - 1) || eeprom_start <= 0) {
86
-      SERIAL_PROTOCOLLNPGM("?EEPROM storage not available to load mesh.\n");
87
-      return;
88
-    }
89
-
90
-    j = UBL_LAST_EEPROM_INDEX - (slot + 1) * sizeof(z_values);
91
-    eeprom_read_block((void *)&z_values, (void *)j, sizeof(z_values));
92
-
93
-    SERIAL_PROTOCOLPAIR("Mesh loaded from slot ", slot);
94
-    SERIAL_PROTOCOLLNPAIR(" at offset ", hex_address((void*)j));
95
-  }
96
-
97
-  void unified_bed_leveling::store_mesh(const int16_t slot) {
98
-    int16_t j = (UBL_LAST_EEPROM_INDEX - eeprom_start) / sizeof(z_values);
99
-
100
-    if (!WITHIN(slot, 0, j - 1) || eeprom_start <= 0) {
101
-      SERIAL_PROTOCOLLNPGM("?EEPROM storage not available to load mesh.\n");
102
-      SERIAL_PROTOCOL(slot);
103
-      SERIAL_PROTOCOLLNPGM(" mesh slots available.\n");
104
-      SERIAL_PROTOCOLLNPAIR("E2END     : ", E2END);
105
-      SERIAL_PROTOCOLLNPAIR("k         : ", (int)UBL_LAST_EEPROM_INDEX);
106
-      SERIAL_PROTOCOLLNPAIR("j         : ", j);
107
-      SERIAL_PROTOCOLLNPAIR("m         : ", slot);
108
-      SERIAL_EOL;
109
-      return;
110
-    }
111
-
112
-    j = UBL_LAST_EEPROM_INDEX - (slot + 1) * sizeof(z_values);
113
-    eeprom_write_block((const void *)&z_values, (void *)j, sizeof(z_values));
114
-
115
-    SERIAL_PROTOCOLPAIR("Mesh saved in slot ", slot);
116
-    SERIAL_PROTOCOLLNPAIR(" at offset ", hex_address((void*)j));
117
-  }
118
-
119 73
   void unified_bed_leveling::reset() {
120 74
     state.active = false;
121 75
     state.z_offset = 0;
122
-    state.eeprom_storage_slot = -1;
76
+    state.storage_slot = -1;
123 77
 
124 78
     ZERO(z_values);
125 79
 
@@ -203,9 +157,9 @@
203 157
   bool unified_bed_leveling::sanity_check() {
204 158
     uint8_t error_flag = 0;
205 159
 
206
-    const int j = (UBL_LAST_EEPROM_INDEX - eeprom_start) / sizeof(z_values);
207
-    if (j < 1) {
208
-      SERIAL_PROTOCOLLNPGM("?No EEPROM storage available for a mesh of this size.\n");
160
+    const int a = settings.calc_num_meshes();
161
+    if (a < 1) {
162
+      SERIAL_PROTOCOLLNPGM("?Insufficient EEPROM storage for a mesh of this size.");
209 163
       error_flag++;
210 164
     }
211 165
 

+ 3
- 11
Marlin/ubl.h Целия файл

@@ -30,8 +30,9 @@
30 30
   #include "planner.h"
31 31
   #include "math.h"
32 32
   #include "vector_3.h"
33
+  #include "configuration_store.h"
33 34
 
34
-  #define UBL_VERSION "1.00"
35
+  #define UBL_VERSION "1.01"
35 36
   #define UBL_OK false
36 37
   #define UBL_ERR true
37 38
 
@@ -92,7 +93,7 @@
92 93
   typedef struct {
93 94
     bool active = false;
94 95
     float z_offset = 0.0;
95
-    int8_t eeprom_storage_slot = -1;
96
+    int8_t storage_slot = -1;
96 97
   } ubl_state;
97 98
 
98 99
   class unified_bed_leveling {
@@ -117,10 +118,6 @@
117 118
       void display_map(const int);
118 119
       void reset();
119 120
       void invalidate();
120
-      void store_state();
121
-      void load_state();
122
-      void store_mesh(const int16_t);
123
-      void load_mesh(const int16_t);
124 121
       bool sanity_check();
125 122
 
126 123
       static ubl_state state;
@@ -153,9 +150,6 @@
153 150
 
154 151
       static bool g26_debug_flag, has_control_of_lcd_panel;
155 152
 
156
-      static int16_t eeprom_start;    // Please do no change this to 8 bits in size
157
-                                      // It needs to hold values bigger than this.
158
-
159 153
       static volatile int encoder_diff; // Volatile because it's changed at interrupt time.
160 154
 
161 155
       unified_bed_leveling();
@@ -351,7 +345,5 @@
351 345
 
352 346
   extern unified_bed_leveling ubl;
353 347
 
354
-  #define UBL_LAST_EEPROM_INDEX E2END
355
-
356 348
 #endif // AUTO_BED_LEVELING_UBL
357 349
 #endif // UNIFIED_BED_LEVELING_H

+ 80
- 65
Marlin/ubl_G29.cpp Целия файл

@@ -314,7 +314,7 @@
314 314
 
315 315
   void __attribute__((optimize("O0"))) gcode_G29() {
316 316
 
317
-    if (ubl.eeprom_start < 0) {
317
+    if (!settings.calc_num_meshes()) {
318 318
       SERIAL_PROTOCOLLNPGM("?You need to enable your EEPROM and initialize it");
319 319
       SERIAL_PROTOCOLLNPGM("with M502, M500, M501 in that order.\n");
320 320
       return;
@@ -419,9 +419,9 @@
419 419
     }
420 420
 
421 421
     if (code_seen('P')) {
422
-      if (WITHIN(phase_value, 0, 1) && ubl.state.eeprom_storage_slot == -1) {
423
-        ubl.state.eeprom_storage_slot = 0;
424
-        SERIAL_PROTOCOLLNPGM("Default storage slot 0 selected.\n");
422
+      if (WITHIN(phase_value, 0, 1) && ubl.state.storage_slot == -1) {
423
+        ubl.state.storage_slot = 0;
424
+        SERIAL_PROTOCOLLNPGM("Default storage slot 0 selected.");
425 425
       }
426 426
 
427 427
       switch (phase_value) {
@@ -430,7 +430,7 @@
430 430
           // Zero Mesh Data
431 431
           //
432 432
           ubl.reset();
433
-          SERIAL_PROTOCOLLNPGM("Mesh zeroed.\n");
433
+          SERIAL_PROTOCOLLNPGM("Mesh zeroed.");
434 434
           break;
435 435
 
436 436
         case 1:
@@ -439,7 +439,7 @@
439 439
           //
440 440
           if (!code_seen('C')) {
441 441
             ubl.invalidate();
442
-            SERIAL_PROTOCOLLNPGM("Mesh invalidated. Probing mesh.\n");
442
+            SERIAL_PROTOCOLLNPGM("Mesh invalidated. Probing mesh.");
443 443
           }
444 444
           if (g29_verbose_level > 1) {
445 445
             SERIAL_PROTOCOLPAIR("Probing Mesh Points Closest to (", x_pos);
@@ -455,7 +455,7 @@
455 455
           //
456 456
           // Manually Probe Mesh in areas that can't be reached by the probe
457 457
           //
458
-          SERIAL_PROTOCOLLNPGM("Manually probing unreachable mesh locations.\n");
458
+          SERIAL_PROTOCOLLNPGM("Manually probing unreachable mesh locations.");
459 459
           do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES);
460 460
           if (!x_flag && !y_flag) {
461 461
             /**
@@ -485,7 +485,7 @@
485 485
             card_thickness = code_has_value() ? code_value_float() : measure_business_card_thickness(height);
486 486
 
487 487
             if (fabs(card_thickness) > 1.5) {
488
-              SERIAL_PROTOCOLLNPGM("?Error in Business Card measurement.\n");
488
+              SERIAL_PROTOCOLLNPGM("?Error in Business Card measurement.");
489 489
               return;
490 490
             }
491 491
           }
@@ -561,17 +561,25 @@
561 561
     //
562 562
 
563 563
     if (code_seen('L')) {     // Load Current Mesh Data
564
-      storage_slot = code_has_value() ? code_value_int() : ubl.state.eeprom_storage_slot;
564
+      storage_slot = code_has_value() ? code_value_int() : ubl.state.storage_slot;
565 565
 
566
-      const int16_t j = (UBL_LAST_EEPROM_INDEX - ubl.eeprom_start) / sizeof(ubl.z_values);
566
+      int16_t a = settings.calc_num_meshes();
567 567
 
568
-      if (!WITHIN(storage_slot, 0, j - 1) || ubl.eeprom_start <= 0) {
569
-        SERIAL_PROTOCOLLNPGM("?EEPROM storage not available for use.\n");
568
+      if (!a) {
569
+        SERIAL_PROTOCOLLNPGM("?EEPROM storage not available.");
570 570
         return;
571 571
       }
572
-      ubl.load_mesh(storage_slot);
573
-      ubl.state.eeprom_storage_slot = storage_slot;
574
-      SERIAL_PROTOCOLLNPGM("Done.\n");
572
+
573
+      if (!WITHIN(storage_slot, 0, a - 1)) {
574
+        SERIAL_PROTOCOLLNPGM("?Invalid storage slot.");
575
+        SERIAL_PROTOCOLLNPAIR("?Use 0 to ", a - 1);
576
+        return;
577
+      }
578
+
579
+      settings.load_mesh(storage_slot);
580
+      ubl.state.storage_slot = storage_slot;
581
+
582
+      SERIAL_PROTOCOLLNPGM("Done.");
575 583
     }
576 584
 
577 585
     //
@@ -579,7 +587,7 @@
579 587
     //
580 588
 
581 589
     if (code_seen('S')) {     // Store (or Save) Current Mesh Data
582
-      storage_slot = code_has_value() ? code_value_int() : ubl.state.eeprom_storage_slot;
590
+      storage_slot = code_has_value() ? code_value_int() : ubl.state.storage_slot;
583 591
 
584 592
       if (storage_slot == -1) {                     // Special case, we are going to 'Export' the mesh to the
585 593
         SERIAL_ECHOLNPGM("G29 I 999");              // host in a form it can be reconstructed on a different machine
@@ -597,17 +605,23 @@
597 605
         return;
598 606
       }
599 607
 
600
-      const int16_t j = (UBL_LAST_EEPROM_INDEX - ubl.eeprom_start) / sizeof(ubl.z_values);
608
+      int16_t a = settings.calc_num_meshes();
601 609
 
602
-      if (!WITHIN(storage_slot, 0, j - 1) || ubl.eeprom_start <= 0) {
603
-        SERIAL_PROTOCOLLNPGM("?EEPROM storage not available for use.\n");
604
-        SERIAL_PROTOCOLLNPAIR("?Use 0 to ", j - 1);
610
+      if (!a) {
611
+        SERIAL_PROTOCOLLNPGM("?EEPROM storage not available.");
605 612
         goto LEAVE;
606 613
       }
607
-      ubl.store_mesh(storage_slot);
608
-      ubl.state.eeprom_storage_slot = storage_slot;
609 614
 
610
-      SERIAL_PROTOCOLLNPGM("Done.\n");
615
+      if (!WITHIN(storage_slot, 0, a - 1)) {
616
+        SERIAL_PROTOCOLLNPGM("?Invalid storage slot.");
617
+        SERIAL_PROTOCOLLNPAIR("?Use 0 to ", a - 1);
618
+        goto LEAVE;
619
+      }
620
+
621
+      settings.store_mesh(storage_slot);
622
+      ubl.state.storage_slot = storage_slot;
623
+
624
+      SERIAL_PROTOCOLLNPGM("Done.");
611 625
     }
612 626
 
613 627
     if (code_seen('T'))
@@ -1157,8 +1171,6 @@
1157 1171
    * good to have the extra information. Soon... we prune this to just a few items
1158 1172
    */
1159 1173
   void unified_bed_leveling::g29_what_command() {
1160
-    const uint16_t k = E2END - ubl.eeprom_start;
1161
-
1162 1174
     say_ubl_name();
1163 1175
     SERIAL_PROTOCOLPGM("System Version " UBL_VERSION " ");
1164 1176
     if (state.active)
@@ -1168,10 +1180,10 @@
1168 1180
     SERIAL_PROTOCOLLNPGM("ctive.\n");
1169 1181
     safe_delay(50);
1170 1182
 
1171
-    if (state.eeprom_storage_slot == -1)
1183
+    if (state.storage_slot == -1)
1172 1184
       SERIAL_PROTOCOLPGM("No Mesh Loaded.");
1173 1185
     else {
1174
-      SERIAL_PROTOCOLPAIR("Mesh ", state.eeprom_storage_slot);
1186
+      SERIAL_PROTOCOLPAIR("Mesh ", state.storage_slot);
1175 1187
       SERIAL_PROTOCOLPGM(" Loaded.");
1176 1188
     }
1177 1189
     SERIAL_EOL;
@@ -1188,12 +1200,15 @@
1188 1200
     SERIAL_PROTOCOL_F(zprobe_zoffset, 7);
1189 1201
     SERIAL_EOL;
1190 1202
 
1191
-    SERIAL_PROTOCOLLNPAIR("ubl.eeprom_start=", hex_address((void*)eeprom_start));
1192
-
1203
+    SERIAL_ECHOLNPAIR("UBL_MESH_MIN_X  " STRINGIFY(UBL_MESH_MIN_X) "=", UBL_MESH_MIN_X);
1204
+    SERIAL_ECHOLNPAIR("UBL_MESH_MIN_Y  " STRINGIFY(UBL_MESH_MIN_Y) "=", UBL_MESH_MIN_Y);
1205
+    safe_delay(25);
1206
+    SERIAL_ECHOLNPAIR("UBL_MESH_MAX_X  " STRINGIFY(UBL_MESH_MAX_X) "=", UBL_MESH_MAX_X);
1207
+    SERIAL_ECHOLNPAIR("UBL_MESH_MAX_Y  " STRINGIFY(UBL_MESH_MAX_Y) "=", UBL_MESH_MAX_Y);
1208
+    safe_delay(25);
1193 1209
     SERIAL_ECHOLNPAIR("GRID_MAX_POINTS_X  ", GRID_MAX_POINTS_X);
1194 1210
     SERIAL_ECHOLNPAIR("GRID_MAX_POINTS_Y  ", GRID_MAX_POINTS_Y);
1195 1211
     safe_delay(25);
1196
-
1197 1212
     SERIAL_ECHOLNPAIR("MESH_X_DIST  ", MESH_X_DIST);
1198 1213
     SERIAL_ECHOLNPAIR("MESH_Y_DIST  ", MESH_Y_DIST);
1199 1214
     safe_delay(25);
@@ -1214,38 +1229,34 @@
1214 1229
     }
1215 1230
     SERIAL_EOL;
1216 1231
 
1217
-    SERIAL_PROTOCOLLNPAIR("Free EEPROM space starts at: ", hex_address((void*)eeprom_start));
1218
-    SERIAL_PROTOCOLLNPAIR("end of EEPROM: ", hex_address((void*)E2END));
1219
-    safe_delay(25);
1232
+    #if HAS_KILL
1233
+      SERIAL_PROTOCOLPAIR("Kill pin on :", KILL_PIN);
1234
+      SERIAL_PROTOCOLLNPAIR("  state:", READ(KILL_PIN));
1235
+    #endif
1236
+    SERIAL_EOL;
1237
+    safe_delay(50);
1220 1238
 
1221
-    SERIAL_PROTOCOLPAIR("sizeof(ubl.state) : ", (int)sizeof(state));
1239
+    SERIAL_PROTOCOLLNPAIR("ubl_state_at_invocation :", ubl_state_at_invocation);
1222 1240
     SERIAL_EOL;
1223
-    SERIAL_PROTOCOLLNPAIR("z_value[][] size: ", (int)sizeof(z_values));
1241
+    SERIAL_PROTOCOLLNPAIR("ubl_state_recursion_chk :", ubl_state_recursion_chk);
1224 1242
     SERIAL_EOL;
1225
-    safe_delay(25);
1226
-
1227
-    SERIAL_PROTOCOLLNPAIR("EEPROM free for UBL: ", hex_address((void*)k));
1228
-    safe_delay(25);
1243
+    safe_delay(50);
1229 1244
 
1230
-    SERIAL_PROTOCOLPAIR("EEPROM can hold ", k / sizeof(z_values));
1231
-    SERIAL_PROTOCOLLNPGM(" meshes.\n");
1232
-    safe_delay(25);
1245
+    SERIAL_PROTOCOLPAIR("Meshes go from ", hex_address((void*)settings.get_start_of_meshes()));
1246
+    SERIAL_PROTOCOLLNPAIR(" to ", hex_address((void*)settings.get_end_of_meshes()));
1247
+    safe_delay(50);
1233 1248
 
1234
-    SERIAL_PROTOCOLPAIR("\nGRID_MAX_POINTS_X  ", GRID_MAX_POINTS_X);
1235
-    SERIAL_PROTOCOLPAIR("\nGRID_MAX_POINTS_Y  ", GRID_MAX_POINTS_Y);
1236
-    safe_delay(25);
1249
+    SERIAL_PROTOCOLLNPAIR("sizeof(ubl) :  ", (int)sizeof(ubl));
1250
+    SERIAL_EOL;
1251
+    SERIAL_PROTOCOLLNPAIR("z_value[][] size: ", (int)sizeof(z_values));
1237 1252
     SERIAL_EOL;
1238
-
1239
-    SERIAL_ECHOPGM("UBL_MESH_MIN_X  " STRINGIFY(UBL_MESH_MIN_X));
1240
-    SERIAL_ECHOLNPAIR("=", UBL_MESH_MIN_X );
1241
-    SERIAL_ECHOPGM("UBL_MESH_MIN_Y  " STRINGIFY(UBL_MESH_MIN_Y));
1242
-    SERIAL_ECHOLNPAIR("=", UBL_MESH_MIN_Y );
1243 1253
     safe_delay(25);
1244 1254
 
1245
-    SERIAL_ECHOPGM("UBL_MESH_MAX_X  " STRINGIFY(UBL_MESH_MAX_X));
1246
-    SERIAL_ECHOLNPAIR("=", UBL_MESH_MAX_X);
1247
-    SERIAL_ECHOPGM("UBL_MESH_MAX_Y  " STRINGIFY(UBL_MESH_MAX_Y));
1248
-    SERIAL_ECHOLNPAIR("=", UBL_MESH_MAX_Y);
1255
+    SERIAL_PROTOCOLLNPAIR("EEPROM free for UBL: ", hex_address((void*)(settings.get_end_of_meshes() - settings.get_start_of_meshes())));
1256
+    safe_delay(50);
1257
+
1258
+    SERIAL_PROTOCOLPAIR("EEPROM can hold ", settings.calc_num_meshes());
1259
+    SERIAL_PROTOCOLLNPGM(" meshes.\n");
1249 1260
     safe_delay(25);
1250 1261
 
1251 1262
     if (!sanity_check()) {
@@ -1284,27 +1295,31 @@
1284 1295
    * use cases for the users. So we can wait and see what to do with it.
1285 1296
    */
1286 1297
   void g29_compare_current_mesh_to_stored_mesh() {
1287
-    float tmp_z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
1298
+    int16_t a = settings.calc_num_meshes();
1299
+
1300
+    if (!a) {
1301
+      SERIAL_PROTOCOLLNPGM("?EEPROM storage not available.");
1302
+      return;
1303
+    }
1288 1304
 
1289 1305
     if (!code_has_value()) {
1290
-      SERIAL_PROTOCOLLNPGM("?Mesh # required.\n");
1306
+      SERIAL_PROTOCOLLNPGM("?Storage slot # required.");
1307
+      SERIAL_PROTOCOLLNPAIR("?Use 0 to ", a - 1);
1291 1308
       return;
1292 1309
     }
1293
-    storage_slot = code_value_int();
1294 1310
 
1295
-    int16_t j = (UBL_LAST_EEPROM_INDEX - ubl.eeprom_start) / sizeof(tmp_z_values);
1311
+    storage_slot = code_value_int();
1296 1312
 
1297
-    if (!WITHIN(storage_slot, 0, j - 1) || ubl.eeprom_start <= 0) {
1298
-      SERIAL_PROTOCOLLNPGM("?EEPROM storage not available for use.\n");
1313
+    if (!WITHIN(storage_slot, 0, a - 1)) {
1314
+      SERIAL_PROTOCOLLNPGM("?Invalid storage slot.");
1315
+      SERIAL_PROTOCOLLNPAIR("?Use 0 to ", a - 1);
1299 1316
       return;
1300 1317
     }
1301 1318
 
1302
-    j = UBL_LAST_EEPROM_INDEX - (storage_slot + 1) * sizeof(tmp_z_values);
1303
-    eeprom_read_block((void *)&tmp_z_values, (void *)j, sizeof(tmp_z_values));
1319
+    float tmp_z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
1320
+    settings.load_mesh(storage_slot, &tmp_z_values);
1304 1321
 
1305
-    SERIAL_ECHOPAIR("Subtracting Mesh ", storage_slot);
1306
-    SERIAL_PROTOCOLLNPAIR(" loaded from EEPROM address ", hex_address((void*)j)); // Soon, we can remove the extra clutter of printing
1307
-                                                                        // the address in the EEPROM where the Mesh is stored.
1322
+    SERIAL_ECHOPAIR("Subtracting current mesh from mesh loaded from slot ", storage_slot);
1308 1323
 
1309 1324
     for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++)
1310 1325
       for (uint8_t y = 0; y < GRID_MAX_POINTS_Y; y++)

+ 13
- 0
Marlin/utility.cpp Целия файл

@@ -34,6 +34,19 @@ void safe_delay(millis_t ms) {
34 34
   thermalManager.manage_heater(); // This keeps us safe if too many small safe_delay() calls are made
35 35
 }
36 36
 
37
+#if ENABLED(EEPROM_SETTINGS)
38
+
39
+  void crc16(uint16_t *crc, const void * const data, uint16_t cnt) {
40
+    uint8_t *ptr = (uint8_t*)data;
41
+    while (cnt-- > 0) {
42
+      *crc = (uint16_t)(*crc ^ (uint16_t)(((uint16_t)*ptr++) << 8));
43
+      for (uint8_t x = 0; x < 8; x++)
44
+        *crc = (uint16_t)((*crc & 0x8000) ? ((uint16_t)(*crc << 1) ^ 0x1021) : (*crc << 1));
45
+    }
46
+  }
47
+
48
+#endif // EEPROM_SETTINGS
49
+
37 50
 #if ENABLED(ULTRA_LCD)
38 51
 
39 52
   char conv[8] = { 0 };

+ 4
- 0
Marlin/utility.h Целия файл

@@ -25,6 +25,10 @@
25 25
 
26 26
 void safe_delay(millis_t ms);
27 27
 
28
+#if ENABLED(EEPROM_SETTINGS)
29
+  void crc16(uint16_t *crc, const void * const data, uint16_t cnt);
30
+#endif
31
+
28 32
 #if ENABLED(ULTRA_LCD)
29 33
 
30 34
   // Convert unsigned int to string with 12 format

Loading…
Отказ
Запис