|
@@ -23,387 +23,375 @@
|
23
|
23
|
#ifndef UNIFIED_BED_LEVELING_H
|
24
|
24
|
#define UNIFIED_BED_LEVELING_H
|
25
|
25
|
|
26
|
|
-#include "MarlinConfig.h"
|
27
|
|
-
|
28
|
|
-#if ENABLED(AUTO_BED_LEVELING_UBL)
|
29
|
|
- #include "Marlin.h"
|
30
|
|
- #include "planner.h"
|
31
|
|
- #include "math.h"
|
32
|
|
- #include "vector_3.h"
|
33
|
|
- #include "configuration_store.h"
|
34
|
|
-
|
35
|
|
- #define UBL_VERSION "1.01"
|
36
|
|
- #define UBL_OK false
|
37
|
|
- #define UBL_ERR true
|
38
|
|
-
|
39
|
|
- #define USE_NOZZLE_AS_REFERENCE 0
|
40
|
|
- #define USE_PROBE_AS_REFERENCE 1
|
41
|
|
-
|
42
|
|
- typedef struct {
|
43
|
|
- int8_t x_index, y_index;
|
44
|
|
- float distance; // When populated, the distance from the search location
|
45
|
|
- } mesh_index_pair;
|
46
|
|
-
|
47
|
|
- // ubl.cpp
|
48
|
|
-
|
49
|
|
- void bit_clear(uint16_t bits[16], uint8_t x, uint8_t y);
|
50
|
|
- void bit_set(uint16_t bits[16], uint8_t x, uint8_t y);
|
51
|
|
- bool is_bit_set(uint16_t bits[16], uint8_t x, uint8_t y);
|
52
|
|
-
|
53
|
|
- // ubl_motion.cpp
|
54
|
|
-
|
55
|
|
- void debug_current_and_destination(const char * const title);
|
56
|
|
-
|
57
|
|
- // ubl_G29.cpp
|
58
|
|
-
|
59
|
|
- enum MeshPointType { INVALID, REAL, SET_IN_BITMAP };
|
60
|
|
-
|
61
|
|
- // External references
|
62
|
|
-
|
63
|
|
- char *ftostr43sign(const float&, char);
|
64
|
|
- bool ubl_lcd_clicked();
|
65
|
|
- void home_all_axes();
|
66
|
|
-
|
67
|
|
- extern uint8_t ubl_cnt;
|
68
|
|
-
|
69
|
|
- ///////////////////////////////////////////////////////////////////////////////////////////////////////
|
70
|
|
-
|
71
|
|
- #if ENABLED(ULTRA_LCD)
|
72
|
|
- extern char lcd_status_message[];
|
73
|
|
- void lcd_quick_feedback();
|
74
|
|
- #endif
|
75
|
|
-
|
76
|
|
- #define MESH_X_DIST (float(UBL_MESH_MAX_X - (UBL_MESH_MIN_X)) / float(GRID_MAX_POINTS_X - 1))
|
77
|
|
- #define MESH_Y_DIST (float(UBL_MESH_MAX_Y - (UBL_MESH_MIN_Y)) / float(GRID_MAX_POINTS_Y - 1))
|
78
|
|
-
|
79
|
|
- typedef struct {
|
80
|
|
- bool active = false;
|
81
|
|
- float z_offset = 0.0;
|
82
|
|
- int8_t storage_slot = -1;
|
83
|
|
- } ubl_state;
|
84
|
|
-
|
85
|
|
- class unified_bed_leveling {
|
86
|
|
- private:
|
87
|
|
-
|
88
|
|
- static float last_specified_z;
|
89
|
|
-
|
90
|
|
- static int g29_verbose_level,
|
91
|
|
- g29_phase_value,
|
92
|
|
- g29_repetition_cnt,
|
93
|
|
- g29_storage_slot,
|
94
|
|
- g29_map_type,
|
95
|
|
- g29_grid_size;
|
96
|
|
- static bool g29_c_flag, g29_x_flag, g29_y_flag;
|
97
|
|
- static float g29_x_pos, g29_y_pos,
|
98
|
|
- g29_card_thickness,
|
99
|
|
- g29_constant;
|
100
|
|
-
|
101
|
|
- #if ENABLED(UBL_G26_MESH_VALIDATION)
|
102
|
|
- static float g26_extrusion_multiplier,
|
103
|
|
- g26_retraction_multiplier,
|
104
|
|
- g26_nozzle,
|
105
|
|
- g26_filament_diameter,
|
106
|
|
- g26_prime_length,
|
107
|
|
- g26_x_pos, g26_y_pos,
|
108
|
|
- g26_ooze_amount,
|
109
|
|
- g26_layer_height;
|
110
|
|
- static int16_t g26_bed_temp,
|
111
|
|
- g26_hotend_temp,
|
112
|
|
- g26_repeats;
|
113
|
|
- static int8_t g26_prime_flag;
|
114
|
|
- static bool g26_continue_with_closest, g26_keep_heaters_on;
|
115
|
|
- #endif
|
116
|
|
-
|
117
|
|
- static float measure_point_with_encoder();
|
118
|
|
- static float measure_business_card_thickness(float);
|
119
|
|
- static bool g29_parameter_parsing();
|
120
|
|
- static void find_mean_mesh_height();
|
121
|
|
- static void shift_mesh_height();
|
122
|
|
- static void probe_entire_mesh(const float &lx, const float &ly, const bool do_ubl_mesh_map, const bool stow_probe, bool do_furthest);
|
123
|
|
- static void manually_probe_remaining_mesh(const float&, const float&, const float&, const float&, const bool);
|
124
|
|
- static void tilt_mesh_based_on_3pts(const float &z1, const float &z2, const float &z3);
|
125
|
|
- static void tilt_mesh_based_on_probed_grid(const bool do_ubl_mesh_map);
|
126
|
|
- static void g29_what_command();
|
127
|
|
- static void g29_eeprom_dump();
|
128
|
|
- static void g29_compare_current_mesh_to_stored_mesh();
|
129
|
|
- static void fine_tune_mesh(const float &lx, const float &ly, const bool do_ubl_mesh_map);
|
130
|
|
- static bool smart_fill_one(const uint8_t x, const uint8_t y, const int8_t xdir, const int8_t ydir);
|
131
|
|
- static void smart_fill_mesh();
|
132
|
|
-
|
133
|
|
- #if ENABLED(UBL_G26_MESH_VALIDATION)
|
134
|
|
- static bool exit_from_g26();
|
135
|
|
- static bool parse_G26_parameters();
|
136
|
|
- static void G26_line_to_destination(const float &feed_rate);
|
137
|
|
- static mesh_index_pair find_closest_circle_to_print(const float&, const float&);
|
138
|
|
- static bool look_for_lines_to_connect();
|
139
|
|
- static bool turn_on_heaters();
|
140
|
|
- static bool prime_nozzle();
|
141
|
|
- static void retract_filament(const float where[XYZE]);
|
142
|
|
- static void recover_filament(const float where[XYZE]);
|
143
|
|
- static void print_line_from_here_to_there(const float&, const float&, const float&, const float&, const float&, const float&);
|
144
|
|
- static void move_to(const float&, const float&, const float&, const float&);
|
145
|
|
- inline static void move_to(const float where[XYZE], const float &de) { move_to(where[X_AXIS], where[Y_AXIS], where[Z_AXIS], de); }
|
146
|
|
- #endif
|
147
|
|
-
|
148
|
|
- public:
|
149
|
|
-
|
150
|
|
- static void echo_name();
|
151
|
|
- static void report_state();
|
152
|
|
- static void save_ubl_active_state_and_disable();
|
153
|
|
- static void restore_ubl_active_state_and_leave();
|
154
|
|
- static void display_map(const int);
|
155
|
|
- static mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType, const float&, const float&, const bool, uint16_t[16], bool);
|
156
|
|
- static void reset();
|
157
|
|
- static void invalidate();
|
158
|
|
- static void set_all_mesh_points_to_value(float);
|
159
|
|
- static bool sanity_check();
|
160
|
|
-
|
161
|
|
- static void G29() _O0; // O0 for no optimization
|
162
|
|
- static void smart_fill_wlsf(const float &) _O2; // O2 gives smaller code than Os on A2560
|
163
|
|
-
|
164
|
|
- #if ENABLED(UBL_G26_MESH_VALIDATION)
|
165
|
|
- static void G26();
|
166
|
|
- #endif
|
167
|
|
-
|
168
|
|
- static ubl_state state;
|
169
|
|
-
|
170
|
|
- static float z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
|
171
|
|
-
|
172
|
|
- // 15 is the maximum nubmer of grid points supported + 1 safety margin for now,
|
173
|
|
- // until determinism prevails
|
174
|
|
- constexpr static float _mesh_index_to_xpos[16] PROGMEM = {
|
175
|
|
- UBL_MESH_MIN_X + 0 * (MESH_X_DIST), UBL_MESH_MIN_X + 1 * (MESH_X_DIST),
|
176
|
|
- UBL_MESH_MIN_X + 2 * (MESH_X_DIST), UBL_MESH_MIN_X + 3 * (MESH_X_DIST),
|
177
|
|
- UBL_MESH_MIN_X + 4 * (MESH_X_DIST), UBL_MESH_MIN_X + 5 * (MESH_X_DIST),
|
178
|
|
- UBL_MESH_MIN_X + 6 * (MESH_X_DIST), UBL_MESH_MIN_X + 7 * (MESH_X_DIST),
|
179
|
|
- UBL_MESH_MIN_X + 8 * (MESH_X_DIST), UBL_MESH_MIN_X + 9 * (MESH_X_DIST),
|
180
|
|
- UBL_MESH_MIN_X + 10 * (MESH_X_DIST), UBL_MESH_MIN_X + 11 * (MESH_X_DIST),
|
181
|
|
- UBL_MESH_MIN_X + 12 * (MESH_X_DIST), UBL_MESH_MIN_X + 13 * (MESH_X_DIST),
|
182
|
|
- UBL_MESH_MIN_X + 14 * (MESH_X_DIST), UBL_MESH_MIN_X + 15 * (MESH_X_DIST)
|
183
|
|
- };
|
184
|
|
-
|
185
|
|
- constexpr static float _mesh_index_to_ypos[16] PROGMEM = {
|
186
|
|
- UBL_MESH_MIN_Y + 0 * (MESH_Y_DIST), UBL_MESH_MIN_Y + 1 * (MESH_Y_DIST),
|
187
|
|
- UBL_MESH_MIN_Y + 2 * (MESH_Y_DIST), UBL_MESH_MIN_Y + 3 * (MESH_Y_DIST),
|
188
|
|
- UBL_MESH_MIN_Y + 4 * (MESH_Y_DIST), UBL_MESH_MIN_Y + 5 * (MESH_Y_DIST),
|
189
|
|
- UBL_MESH_MIN_Y + 6 * (MESH_Y_DIST), UBL_MESH_MIN_Y + 7 * (MESH_Y_DIST),
|
190
|
|
- UBL_MESH_MIN_Y + 8 * (MESH_Y_DIST), UBL_MESH_MIN_Y + 9 * (MESH_Y_DIST),
|
191
|
|
- UBL_MESH_MIN_Y + 10 * (MESH_Y_DIST), UBL_MESH_MIN_Y + 11 * (MESH_Y_DIST),
|
192
|
|
- UBL_MESH_MIN_Y + 12 * (MESH_Y_DIST), UBL_MESH_MIN_Y + 13 * (MESH_Y_DIST),
|
193
|
|
- UBL_MESH_MIN_Y + 14 * (MESH_Y_DIST), UBL_MESH_MIN_Y + 15 * (MESH_Y_DIST)
|
194
|
|
- };
|
195
|
|
-
|
196
|
|
- static bool g26_debug_flag, has_control_of_lcd_panel;
|
197
|
|
-
|
198
|
|
- static volatile int encoder_diff; // Volatile because it's changed at interrupt time.
|
199
|
|
-
|
200
|
|
- unified_bed_leveling();
|
201
|
|
-
|
202
|
|
- FORCE_INLINE static void set_z(const int8_t px, const int8_t py, const float &z) { z_values[px][py] = z; }
|
203
|
|
-
|
204
|
|
- static int8_t get_cell_index_x(const float &x) {
|
205
|
|
- const int8_t cx = (x - (UBL_MESH_MIN_X)) * (1.0 / (MESH_X_DIST));
|
206
|
|
- return constrain(cx, 0, (GRID_MAX_POINTS_X) - 1); // -1 is appropriate if we want all movement to the X_MAX
|
207
|
|
- } // position. But with this defined this way, it is possible
|
208
|
|
- // to extrapolate off of this point even further out. Probably
|
209
|
|
- // that is OK because something else should be keeping that from
|
210
|
|
- // happening and should not be worried about at this level.
|
211
|
|
- static int8_t get_cell_index_y(const float &y) {
|
212
|
|
- const int8_t cy = (y - (UBL_MESH_MIN_Y)) * (1.0 / (MESH_Y_DIST));
|
213
|
|
- return constrain(cy, 0, (GRID_MAX_POINTS_Y) - 1); // -1 is appropriate if we want all movement to the Y_MAX
|
214
|
|
- } // position. But with this defined this way, it is possible
|
215
|
|
- // to extrapolate off of this point even further out. Probably
|
216
|
|
- // that is OK because something else should be keeping that from
|
217
|
|
- // happening and should not be worried about at this level.
|
218
|
|
-
|
219
|
|
- static int8_t find_closest_x_index(const float &x) {
|
220
|
|
- const int8_t px = (x - (UBL_MESH_MIN_X) + (MESH_X_DIST) * 0.5) * (1.0 / (MESH_X_DIST));
|
221
|
|
- return WITHIN(px, 0, GRID_MAX_POINTS_X - 1) ? px : -1;
|
|
26
|
+#include "../../Marlin.h"
|
|
27
|
+#include "../../core/serial.h"
|
|
28
|
+#include "../../module/planner.h"
|
|
29
|
+
|
|
30
|
+#define UBL_VERSION "1.01"
|
|
31
|
+#define UBL_OK false
|
|
32
|
+#define UBL_ERR true
|
|
33
|
+
|
|
34
|
+#define USE_NOZZLE_AS_REFERENCE 0
|
|
35
|
+#define USE_PROBE_AS_REFERENCE 1
|
|
36
|
+
|
|
37
|
+typedef struct {
|
|
38
|
+ int8_t x_index, y_index;
|
|
39
|
+ float distance; // When populated, the distance from the search location
|
|
40
|
+} mesh_index_pair;
|
|
41
|
+
|
|
42
|
+// ubl.cpp
|
|
43
|
+
|
|
44
|
+void bit_clear(uint16_t bits[16], const uint8_t x, const uint8_t y);
|
|
45
|
+void bit_set(uint16_t bits[16], const uint8_t x, const uint8_t y);
|
|
46
|
+bool is_bit_set(uint16_t bits[16], const uint8_t x, const uint8_t y);
|
|
47
|
+
|
|
48
|
+// ubl_motion.cpp
|
|
49
|
+
|
|
50
|
+void debug_current_and_destination(const char * const title);
|
|
51
|
+
|
|
52
|
+// ubl_G29.cpp
|
|
53
|
+
|
|
54
|
+enum MeshPointType { INVALID, REAL, SET_IN_BITMAP };
|
|
55
|
+
|
|
56
|
+// External references
|
|
57
|
+
|
|
58
|
+char *ftostr43sign(const float&, char);
|
|
59
|
+bool ubl_lcd_clicked();
|
|
60
|
+void home_all_axes();
|
|
61
|
+
|
|
62
|
+extern uint8_t ubl_cnt;
|
|
63
|
+
|
|
64
|
+///////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
65
|
+
|
|
66
|
+#if ENABLED(ULTRA_LCD)
|
|
67
|
+ extern char lcd_status_message[];
|
|
68
|
+ void lcd_quick_feedback();
|
|
69
|
+#endif
|
|
70
|
+
|
|
71
|
+#define MESH_X_DIST (float(UBL_MESH_MAX_X - (UBL_MESH_MIN_X)) / float(GRID_MAX_POINTS_X - 1))
|
|
72
|
+#define MESH_Y_DIST (float(UBL_MESH_MAX_Y - (UBL_MESH_MIN_Y)) / float(GRID_MAX_POINTS_Y - 1))
|
|
73
|
+
|
|
74
|
+typedef struct {
|
|
75
|
+ bool active = false;
|
|
76
|
+ float z_offset = 0.0;
|
|
77
|
+ int8_t storage_slot = -1;
|
|
78
|
+} ubl_state;
|
|
79
|
+
|
|
80
|
+class unified_bed_leveling {
|
|
81
|
+ private:
|
|
82
|
+
|
|
83
|
+ static float last_specified_z;
|
|
84
|
+
|
|
85
|
+ static int g29_verbose_level,
|
|
86
|
+ g29_phase_value,
|
|
87
|
+ g29_repetition_cnt,
|
|
88
|
+ g29_storage_slot,
|
|
89
|
+ g29_map_type,
|
|
90
|
+ g29_grid_size;
|
|
91
|
+ static bool g29_c_flag, g29_x_flag, g29_y_flag;
|
|
92
|
+ static float g29_x_pos, g29_y_pos,
|
|
93
|
+ g29_card_thickness,
|
|
94
|
+ g29_constant;
|
|
95
|
+
|
|
96
|
+ #if ENABLED(UBL_G26_MESH_VALIDATION)
|
|
97
|
+ static float g26_extrusion_multiplier,
|
|
98
|
+ g26_retraction_multiplier,
|
|
99
|
+ g26_nozzle,
|
|
100
|
+ g26_filament_diameter,
|
|
101
|
+ g26_prime_length,
|
|
102
|
+ g26_x_pos, g26_y_pos,
|
|
103
|
+ g26_ooze_amount,
|
|
104
|
+ g26_layer_height;
|
|
105
|
+ static int16_t g26_bed_temp,
|
|
106
|
+ g26_hotend_temp,
|
|
107
|
+ g26_repeats;
|
|
108
|
+ static int8_t g26_prime_flag;
|
|
109
|
+ static bool g26_continue_with_closest, g26_keep_heaters_on;
|
|
110
|
+ #endif
|
|
111
|
+
|
|
112
|
+ static float measure_point_with_encoder();
|
|
113
|
+ static float measure_business_card_thickness(float);
|
|
114
|
+ static bool g29_parameter_parsing();
|
|
115
|
+ static void find_mean_mesh_height();
|
|
116
|
+ static void shift_mesh_height();
|
|
117
|
+ static void probe_entire_mesh(const float &lx, const float &ly, const bool do_ubl_mesh_map, const bool stow_probe, bool do_furthest);
|
|
118
|
+ static void manually_probe_remaining_mesh(const float&, const float&, const float&, const float&, const bool);
|
|
119
|
+ static void tilt_mesh_based_on_3pts(const float &z1, const float &z2, const float &z3);
|
|
120
|
+ static void tilt_mesh_based_on_probed_grid(const bool do_ubl_mesh_map);
|
|
121
|
+ static void g29_what_command();
|
|
122
|
+ static void g29_eeprom_dump();
|
|
123
|
+ static void g29_compare_current_mesh_to_stored_mesh();
|
|
124
|
+ static void fine_tune_mesh(const float &lx, const float &ly, const bool do_ubl_mesh_map);
|
|
125
|
+ static bool smart_fill_one(const uint8_t x, const uint8_t y, const int8_t xdir, const int8_t ydir);
|
|
126
|
+ static void smart_fill_mesh();
|
|
127
|
+
|
|
128
|
+ #if ENABLED(UBL_G26_MESH_VALIDATION)
|
|
129
|
+ static bool exit_from_g26();
|
|
130
|
+ static bool parse_G26_parameters();
|
|
131
|
+ static void G26_line_to_destination(const float &feed_rate);
|
|
132
|
+ static mesh_index_pair find_closest_circle_to_print(const float&, const float&);
|
|
133
|
+ static bool look_for_lines_to_connect();
|
|
134
|
+ static bool turn_on_heaters();
|
|
135
|
+ static bool prime_nozzle();
|
|
136
|
+ static void retract_filament(const float where[XYZE]);
|
|
137
|
+ static void recover_filament(const float where[XYZE]);
|
|
138
|
+ static void print_line_from_here_to_there(const float&, const float&, const float&, const float&, const float&, const float&);
|
|
139
|
+ static void move_to(const float&, const float&, const float&, const float&);
|
|
140
|
+ inline static void move_to(const float where[XYZE], const float &de) { move_to(where[X_AXIS], where[Y_AXIS], where[Z_AXIS], de); }
|
|
141
|
+ #endif
|
|
142
|
+
|
|
143
|
+ public:
|
|
144
|
+
|
|
145
|
+ static void echo_name();
|
|
146
|
+ static void report_state();
|
|
147
|
+ static void save_ubl_active_state_and_disable();
|
|
148
|
+ static void restore_ubl_active_state_and_leave();
|
|
149
|
+ static void display_map(const int);
|
|
150
|
+ static mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType, const float&, const float&, const bool, uint16_t[16], bool);
|
|
151
|
+ static void reset();
|
|
152
|
+ static void invalidate();
|
|
153
|
+ static void set_all_mesh_points_to_value(float);
|
|
154
|
+ static bool sanity_check();
|
|
155
|
+
|
|
156
|
+ static void G29() _O0; // O0 for no optimization
|
|
157
|
+ static void smart_fill_wlsf(const float &) _O2; // O2 gives smaller code than Os on A2560
|
|
158
|
+
|
|
159
|
+ #if ENABLED(UBL_G26_MESH_VALIDATION)
|
|
160
|
+ static void G26();
|
|
161
|
+ #endif
|
|
162
|
+
|
|
163
|
+ static ubl_state state;
|
|
164
|
+
|
|
165
|
+ static float z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
|
|
166
|
+
|
|
167
|
+ // 15 is the maximum nubmer of grid points supported + 1 safety margin for now,
|
|
168
|
+ // until determinism prevails
|
|
169
|
+ constexpr static float _mesh_index_to_xpos[16] PROGMEM = {
|
|
170
|
+ UBL_MESH_MIN_X + 0 * (MESH_X_DIST), UBL_MESH_MIN_X + 1 * (MESH_X_DIST),
|
|
171
|
+ UBL_MESH_MIN_X + 2 * (MESH_X_DIST), UBL_MESH_MIN_X + 3 * (MESH_X_DIST),
|
|
172
|
+ UBL_MESH_MIN_X + 4 * (MESH_X_DIST), UBL_MESH_MIN_X + 5 * (MESH_X_DIST),
|
|
173
|
+ UBL_MESH_MIN_X + 6 * (MESH_X_DIST), UBL_MESH_MIN_X + 7 * (MESH_X_DIST),
|
|
174
|
+ UBL_MESH_MIN_X + 8 * (MESH_X_DIST), UBL_MESH_MIN_X + 9 * (MESH_X_DIST),
|
|
175
|
+ UBL_MESH_MIN_X + 10 * (MESH_X_DIST), UBL_MESH_MIN_X + 11 * (MESH_X_DIST),
|
|
176
|
+ UBL_MESH_MIN_X + 12 * (MESH_X_DIST), UBL_MESH_MIN_X + 13 * (MESH_X_DIST),
|
|
177
|
+ UBL_MESH_MIN_X + 14 * (MESH_X_DIST), UBL_MESH_MIN_X + 15 * (MESH_X_DIST)
|
|
178
|
+ };
|
|
179
|
+
|
|
180
|
+ constexpr static float _mesh_index_to_ypos[16] PROGMEM = {
|
|
181
|
+ UBL_MESH_MIN_Y + 0 * (MESH_Y_DIST), UBL_MESH_MIN_Y + 1 * (MESH_Y_DIST),
|
|
182
|
+ UBL_MESH_MIN_Y + 2 * (MESH_Y_DIST), UBL_MESH_MIN_Y + 3 * (MESH_Y_DIST),
|
|
183
|
+ UBL_MESH_MIN_Y + 4 * (MESH_Y_DIST), UBL_MESH_MIN_Y + 5 * (MESH_Y_DIST),
|
|
184
|
+ UBL_MESH_MIN_Y + 6 * (MESH_Y_DIST), UBL_MESH_MIN_Y + 7 * (MESH_Y_DIST),
|
|
185
|
+ UBL_MESH_MIN_Y + 8 * (MESH_Y_DIST), UBL_MESH_MIN_Y + 9 * (MESH_Y_DIST),
|
|
186
|
+ UBL_MESH_MIN_Y + 10 * (MESH_Y_DIST), UBL_MESH_MIN_Y + 11 * (MESH_Y_DIST),
|
|
187
|
+ UBL_MESH_MIN_Y + 12 * (MESH_Y_DIST), UBL_MESH_MIN_Y + 13 * (MESH_Y_DIST),
|
|
188
|
+ UBL_MESH_MIN_Y + 14 * (MESH_Y_DIST), UBL_MESH_MIN_Y + 15 * (MESH_Y_DIST)
|
|
189
|
+ };
|
|
190
|
+
|
|
191
|
+ static bool g26_debug_flag, has_control_of_lcd_panel;
|
|
192
|
+
|
|
193
|
+ static volatile int encoder_diff; // Volatile because it's changed at interrupt time.
|
|
194
|
+
|
|
195
|
+ unified_bed_leveling();
|
|
196
|
+
|
|
197
|
+ FORCE_INLINE static void set_z(const int8_t px, const int8_t py, const float &z) { z_values[px][py] = z; }
|
|
198
|
+
|
|
199
|
+ static int8_t get_cell_index_x(const float &x) {
|
|
200
|
+ const int8_t cx = (x - (UBL_MESH_MIN_X)) * (1.0 / (MESH_X_DIST));
|
|
201
|
+ return constrain(cx, 0, (GRID_MAX_POINTS_X) - 1); // -1 is appropriate if we want all movement to the X_MAX
|
|
202
|
+ } // position. But with this defined this way, it is possible
|
|
203
|
+ // to extrapolate off of this point even further out. Probably
|
|
204
|
+ // that is OK because something else should be keeping that from
|
|
205
|
+ // happening and should not be worried about at this level.
|
|
206
|
+ static int8_t get_cell_index_y(const float &y) {
|
|
207
|
+ const int8_t cy = (y - (UBL_MESH_MIN_Y)) * (1.0 / (MESH_Y_DIST));
|
|
208
|
+ return constrain(cy, 0, (GRID_MAX_POINTS_Y) - 1); // -1 is appropriate if we want all movement to the Y_MAX
|
|
209
|
+ } // position. But with this defined this way, it is possible
|
|
210
|
+ // to extrapolate off of this point even further out. Probably
|
|
211
|
+ // that is OK because something else should be keeping that from
|
|
212
|
+ // happening and should not be worried about at this level.
|
|
213
|
+
|
|
214
|
+ static int8_t find_closest_x_index(const float &x) {
|
|
215
|
+ const int8_t px = (x - (UBL_MESH_MIN_X) + (MESH_X_DIST) * 0.5) * (1.0 / (MESH_X_DIST));
|
|
216
|
+ return WITHIN(px, 0, GRID_MAX_POINTS_X - 1) ? px : -1;
|
|
217
|
+ }
|
|
218
|
+
|
|
219
|
+ static int8_t find_closest_y_index(const float &y) {
|
|
220
|
+ const int8_t py = (y - (UBL_MESH_MIN_Y) + (MESH_Y_DIST) * 0.5) * (1.0 / (MESH_Y_DIST));
|
|
221
|
+ return WITHIN(py, 0, GRID_MAX_POINTS_Y - 1) ? py : -1;
|
|
222
|
+ }
|
|
223
|
+
|
|
224
|
+ /**
|
|
225
|
+ * z2 --|
|
|
226
|
+ * z0 | |
|
|
227
|
+ * | | + (z2-z1)
|
|
228
|
+ * z1 | | |
|
|
229
|
+ * ---+-------------+--------+-- --|
|
|
230
|
+ * a1 a0 a2
|
|
231
|
+ * |<---delta_a---------->|
|
|
232
|
+ *
|
|
233
|
+ * calc_z0 is the basis for all the Mesh Based correction. It is used to
|
|
234
|
+ * find the expected Z Height at a position between two known Z-Height locations.
|
|
235
|
+ *
|
|
236
|
+ * It is fairly expensive with its 4 floating point additions and 2 floating point
|
|
237
|
+ * multiplications.
|
|
238
|
+ */
|
|
239
|
+ FORCE_INLINE static float calc_z0(const float &a0, const float &a1, const float &z1, const float &a2, const float &z2) {
|
|
240
|
+ return z1 + (z2 - z1) * (a0 - a1) / (a2 - a1);
|
|
241
|
+ }
|
|
242
|
+
|
|
243
|
+ /**
|
|
244
|
+ * z_correction_for_x_on_horizontal_mesh_line is an optimization for
|
|
245
|
+ * the case where the printer is making a vertical line that only crosses horizontal mesh lines.
|
|
246
|
+ */
|
|
247
|
+ inline static float z_correction_for_x_on_horizontal_mesh_line(const float &lx0, const int x1_i, const int yi) {
|
|
248
|
+ if (!WITHIN(x1_i, 0, GRID_MAX_POINTS_X - 2) || !WITHIN(yi, 0, GRID_MAX_POINTS_Y - 1)) {
|
|
249
|
+ serialprintPGM( !WITHIN(x1_i, 0, GRID_MAX_POINTS_X - 1) ? PSTR("x1l_i") : PSTR("yi") );
|
|
250
|
+ SERIAL_ECHOPAIR(" out of bounds in z_correction_for_x_on_horizontal_mesh_line(lx0=", lx0);
|
|
251
|
+ SERIAL_ECHOPAIR(",x1_i=", x1_i);
|
|
252
|
+ SERIAL_ECHOPAIR(",yi=", yi);
|
|
253
|
+ SERIAL_CHAR(')');
|
|
254
|
+ SERIAL_EOL();
|
|
255
|
+ return NAN;
|
222
|
256
|
}
|
223
|
257
|
|
224
|
|
- static int8_t find_closest_y_index(const float &y) {
|
225
|
|
- const int8_t py = (y - (UBL_MESH_MIN_Y) + (MESH_Y_DIST) * 0.5) * (1.0 / (MESH_Y_DIST));
|
226
|
|
- return WITHIN(py, 0, GRID_MAX_POINTS_Y - 1) ? py : -1;
|
|
258
|
+ const float xratio = (RAW_X_POSITION(lx0) - mesh_index_to_xpos(x1_i)) * (1.0 / (MESH_X_DIST)),
|
|
259
|
+ z1 = z_values[x1_i][yi];
|
|
260
|
+
|
|
261
|
+ return z1 + xratio * (z_values[x1_i + 1][yi] - z1);
|
|
262
|
+ }
|
|
263
|
+
|
|
264
|
+ //
|
|
265
|
+ // See comments above for z_correction_for_x_on_horizontal_mesh_line
|
|
266
|
+ //
|
|
267
|
+ inline static float z_correction_for_y_on_vertical_mesh_line(const float &ly0, const int xi, const int y1_i) {
|
|
268
|
+ if (!WITHIN(xi, 0, GRID_MAX_POINTS_X - 1) || !WITHIN(y1_i, 0, GRID_MAX_POINTS_Y - 2)) {
|
|
269
|
+ serialprintPGM( !WITHIN(xi, 0, GRID_MAX_POINTS_X - 1) ? PSTR("xi") : PSTR("yl_i") );
|
|
270
|
+ SERIAL_ECHOPAIR(" out of bounds in z_correction_for_y_on_vertical_mesh_line(ly0=", ly0);
|
|
271
|
+ SERIAL_ECHOPAIR(", xi=", xi);
|
|
272
|
+ SERIAL_ECHOPAIR(", y1_i=", y1_i);
|
|
273
|
+ SERIAL_CHAR(')');
|
|
274
|
+ SERIAL_EOL();
|
|
275
|
+ return NAN;
|
227
|
276
|
}
|
228
|
277
|
|
229
|
|
- /**
|
230
|
|
- * z2 --|
|
231
|
|
- * z0 | |
|
232
|
|
- * | | + (z2-z1)
|
233
|
|
- * z1 | | |
|
234
|
|
- * ---+-------------+--------+-- --|
|
235
|
|
- * a1 a0 a2
|
236
|
|
- * |<---delta_a---------->|
|
237
|
|
- *
|
238
|
|
- * calc_z0 is the basis for all the Mesh Based correction. It is used to
|
239
|
|
- * find the expected Z Height at a position between two known Z-Height locations.
|
240
|
|
- *
|
241
|
|
- * It is fairly expensive with its 4 floating point additions and 2 floating point
|
242
|
|
- * multiplications.
|
243
|
|
- */
|
244
|
|
- FORCE_INLINE static float calc_z0(const float &a0, const float &a1, const float &z1, const float &a2, const float &z2) {
|
245
|
|
- return z1 + (z2 - z1) * (a0 - a1) / (a2 - a1);
|
246
|
|
- }
|
|
278
|
+ const float yratio = (RAW_Y_POSITION(ly0) - mesh_index_to_ypos(y1_i)) * (1.0 / (MESH_Y_DIST)),
|
|
279
|
+ z1 = z_values[xi][y1_i];
|
247
|
280
|
|
248
|
|
- /**
|
249
|
|
- * z_correction_for_x_on_horizontal_mesh_line is an optimization for
|
250
|
|
- * the case where the printer is making a vertical line that only crosses horizontal mesh lines.
|
251
|
|
- */
|
252
|
|
- inline static float z_correction_for_x_on_horizontal_mesh_line(const float &lx0, const int x1_i, const int yi) {
|
253
|
|
- if (!WITHIN(x1_i, 0, GRID_MAX_POINTS_X - 2) || !WITHIN(yi, 0, GRID_MAX_POINTS_Y - 1)) {
|
254
|
|
- serialprintPGM( !WITHIN(x1_i, 0, GRID_MAX_POINTS_X - 1) ? PSTR("x1l_i") : PSTR("yi") );
|
255
|
|
- SERIAL_ECHOPAIR(" out of bounds in z_correction_for_x_on_horizontal_mesh_line(lx0=", lx0);
|
256
|
|
- SERIAL_ECHOPAIR(",x1_i=", x1_i);
|
257
|
|
- SERIAL_ECHOPAIR(",yi=", yi);
|
258
|
|
- SERIAL_CHAR(')');
|
259
|
|
- SERIAL_EOL();
|
260
|
|
- return NAN;
|
261
|
|
- }
|
|
281
|
+ return z1 + yratio * (z_values[xi][y1_i + 1] - z1);
|
|
282
|
+ }
|
262
|
283
|
|
263
|
|
- const float xratio = (RAW_X_POSITION(lx0) - mesh_index_to_xpos(x1_i)) * (1.0 / (MESH_X_DIST)),
|
264
|
|
- z1 = z_values[x1_i][yi];
|
|
284
|
+ /**
|
|
285
|
+ * This is the generic Z-Correction. It works anywhere within a Mesh Cell. It first
|
|
286
|
+ * does a linear interpolation along both of the bounding X-Mesh-Lines to find the
|
|
287
|
+ * Z-Height at both ends. Then it does a linear interpolation of these heights based
|
|
288
|
+ * on the Y position within the cell.
|
|
289
|
+ */
|
|
290
|
+ static float get_z_correction(const float &lx0, const float &ly0) {
|
|
291
|
+ const int8_t cx = get_cell_index_x(RAW_X_POSITION(lx0)),
|
|
292
|
+ cy = get_cell_index_y(RAW_Y_POSITION(ly0));
|
265
|
293
|
|
266
|
|
- return z1 + xratio * (z_values[x1_i + 1][yi] - z1);
|
267
|
|
- }
|
|
294
|
+ if (!WITHIN(cx, 0, GRID_MAX_POINTS_X - 2) || !WITHIN(cy, 0, GRID_MAX_POINTS_Y - 2)) {
|
268
|
295
|
|
269
|
|
- //
|
270
|
|
- // See comments above for z_correction_for_x_on_horizontal_mesh_line
|
271
|
|
- //
|
272
|
|
- inline static float z_correction_for_y_on_vertical_mesh_line(const float &ly0, const int xi, const int y1_i) {
|
273
|
|
- if (!WITHIN(xi, 0, GRID_MAX_POINTS_X - 1) || !WITHIN(y1_i, 0, GRID_MAX_POINTS_Y - 2)) {
|
274
|
|
- serialprintPGM( !WITHIN(xi, 0, GRID_MAX_POINTS_X - 1) ? PSTR("xi") : PSTR("yl_i") );
|
275
|
|
- SERIAL_ECHOPAIR(" out of bounds in z_correction_for_y_on_vertical_mesh_line(ly0=", ly0);
|
276
|
|
- SERIAL_ECHOPAIR(", xi=", xi);
|
277
|
|
- SERIAL_ECHOPAIR(", y1_i=", y1_i);
|
278
|
|
- SERIAL_CHAR(')');
|
279
|
|
- SERIAL_EOL();
|
280
|
|
- return NAN;
|
281
|
|
- }
|
|
296
|
+ SERIAL_ECHOPAIR("? in get_z_correction(lx0=", lx0);
|
|
297
|
+ SERIAL_ECHOPAIR(", ly0=", ly0);
|
|
298
|
+ SERIAL_CHAR(')');
|
|
299
|
+ SERIAL_EOL();
|
282
|
300
|
|
283
|
|
- const float yratio = (RAW_Y_POSITION(ly0) - mesh_index_to_ypos(y1_i)) * (1.0 / (MESH_Y_DIST)),
|
284
|
|
- z1 = z_values[xi][y1_i];
|
285
|
|
-
|
286
|
|
- return z1 + yratio * (z_values[xi][y1_i + 1] - z1);
|
|
301
|
+ #if ENABLED(ULTRA_LCD)
|
|
302
|
+ strcpy(lcd_status_message, "get_z_correction() indexes out of range.");
|
|
303
|
+ lcd_quick_feedback();
|
|
304
|
+ #endif
|
|
305
|
+ return NAN; // this used to return state.z_offset
|
287
|
306
|
}
|
288
|
307
|
|
289
|
|
- /**
|
290
|
|
- * This is the generic Z-Correction. It works anywhere within a Mesh Cell. It first
|
291
|
|
- * does a linear interpolation along both of the bounding X-Mesh-Lines to find the
|
292
|
|
- * Z-Height at both ends. Then it does a linear interpolation of these heights based
|
293
|
|
- * on the Y position within the cell.
|
294
|
|
- */
|
295
|
|
- static float get_z_correction(const float &lx0, const float &ly0) {
|
296
|
|
- const int8_t cx = get_cell_index_x(RAW_X_POSITION(lx0)),
|
297
|
|
- cy = get_cell_index_y(RAW_Y_POSITION(ly0));
|
298
|
|
-
|
299
|
|
- if (!WITHIN(cx, 0, GRID_MAX_POINTS_X - 2) || !WITHIN(cy, 0, GRID_MAX_POINTS_Y - 2)) {
|
300
|
|
-
|
301
|
|
- SERIAL_ECHOPAIR("? in get_z_correction(lx0=", lx0);
|
302
|
|
- SERIAL_ECHOPAIR(", ly0=", ly0);
|
303
|
|
- SERIAL_CHAR(')');
|
304
|
|
- SERIAL_EOL();
|
305
|
|
-
|
306
|
|
- #if ENABLED(ULTRA_LCD)
|
307
|
|
- strcpy(lcd_status_message, "get_z_correction() indexes out of range.");
|
308
|
|
- lcd_quick_feedback();
|
309
|
|
- #endif
|
310
|
|
- return NAN; // this used to return state.z_offset
|
|
308
|
+ const float z1 = calc_z0(RAW_X_POSITION(lx0),
|
|
309
|
+ mesh_index_to_xpos(cx), z_values[cx][cy],
|
|
310
|
+ mesh_index_to_xpos(cx + 1), z_values[cx + 1][cy]);
|
|
311
|
+
|
|
312
|
+ const float z2 = calc_z0(RAW_X_POSITION(lx0),
|
|
313
|
+ mesh_index_to_xpos(cx), z_values[cx][cy + 1],
|
|
314
|
+ mesh_index_to_xpos(cx + 1), z_values[cx + 1][cy + 1]);
|
|
315
|
+
|
|
316
|
+ float z0 = calc_z0(RAW_Y_POSITION(ly0),
|
|
317
|
+ mesh_index_to_ypos(cy), z1,
|
|
318
|
+ mesh_index_to_ypos(cy + 1), z2);
|
|
319
|
+
|
|
320
|
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
321
|
+ if (DEBUGGING(MESH_ADJUST)) {
|
|
322
|
+ SERIAL_ECHOPAIR(" raw get_z_correction(", lx0);
|
|
323
|
+ SERIAL_CHAR(',');
|
|
324
|
+ SERIAL_ECHO(ly0);
|
|
325
|
+ SERIAL_ECHOPGM(") = ");
|
|
326
|
+ SERIAL_ECHO_F(z0, 6);
|
311
|
327
|
}
|
|
328
|
+ #endif
|
312
|
329
|
|
313
|
|
- const float z1 = calc_z0(RAW_X_POSITION(lx0),
|
314
|
|
- mesh_index_to_xpos(cx), z_values[cx][cy],
|
315
|
|
- mesh_index_to_xpos(cx + 1), z_values[cx + 1][cy]);
|
316
|
|
-
|
317
|
|
- const float z2 = calc_z0(RAW_X_POSITION(lx0),
|
318
|
|
- mesh_index_to_xpos(cx), z_values[cx][cy + 1],
|
319
|
|
- mesh_index_to_xpos(cx + 1), z_values[cx + 1][cy + 1]);
|
|
330
|
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
331
|
+ if (DEBUGGING(MESH_ADJUST)) {
|
|
332
|
+ SERIAL_ECHOPGM(" >>>---> ");
|
|
333
|
+ SERIAL_ECHO_F(z0, 6);
|
|
334
|
+ SERIAL_EOL();
|
|
335
|
+ }
|
|
336
|
+ #endif
|
320
|
337
|
|
321
|
|
- float z0 = calc_z0(RAW_Y_POSITION(ly0),
|
322
|
|
- mesh_index_to_ypos(cy), z1,
|
323
|
|
- mesh_index_to_ypos(cy + 1), z2);
|
|
338
|
+ if (isnan(z0)) { // if part of the Mesh is undefined, it will show up as NAN
|
|
339
|
+ z0 = 0.0; // in ubl.z_values[][] and propagate through the
|
|
340
|
+ // calculations. If our correction is NAN, we throw it out
|
|
341
|
+ // because part of the Mesh is undefined and we don't have the
|
|
342
|
+ // information we need to complete the height correction.
|
324
|
343
|
|
325
|
344
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
326
|
345
|
if (DEBUGGING(MESH_ADJUST)) {
|
327
|
|
- SERIAL_ECHOPAIR(" raw get_z_correction(", lx0);
|
|
346
|
+ SERIAL_ECHOPAIR("??? Yikes! NAN in get_z_correction(", lx0);
|
328
|
347
|
SERIAL_CHAR(',');
|
329
|
348
|
SERIAL_ECHO(ly0);
|
330
|
|
- SERIAL_ECHOPGM(") = ");
|
331
|
|
- SERIAL_ECHO_F(z0, 6);
|
332
|
|
- }
|
333
|
|
- #endif
|
334
|
|
-
|
335
|
|
- #if ENABLED(DEBUG_LEVELING_FEATURE)
|
336
|
|
- if (DEBUGGING(MESH_ADJUST)) {
|
337
|
|
- SERIAL_ECHOPGM(" >>>---> ");
|
338
|
|
- SERIAL_ECHO_F(z0, 6);
|
|
349
|
+ SERIAL_CHAR(')');
|
339
|
350
|
SERIAL_EOL();
|
340
|
351
|
}
|
341
|
352
|
#endif
|
342
|
|
-
|
343
|
|
- if (isnan(z0)) { // if part of the Mesh is undefined, it will show up as NAN
|
344
|
|
- z0 = 0.0; // in ubl.z_values[][] and propagate through the
|
345
|
|
- // calculations. If our correction is NAN, we throw it out
|
346
|
|
- // because part of the Mesh is undefined and we don't have the
|
347
|
|
- // information we need to complete the height correction.
|
348
|
|
-
|
349
|
|
- #if ENABLED(DEBUG_LEVELING_FEATURE)
|
350
|
|
- if (DEBUGGING(MESH_ADJUST)) {
|
351
|
|
- SERIAL_ECHOPAIR("??? Yikes! NAN in get_z_correction(", lx0);
|
352
|
|
- SERIAL_CHAR(',');
|
353
|
|
- SERIAL_ECHO(ly0);
|
354
|
|
- SERIAL_CHAR(')');
|
355
|
|
- SERIAL_EOL();
|
356
|
|
- }
|
357
|
|
- #endif
|
358
|
|
- }
|
359
|
|
- return z0; // there used to be a +state.z_offset on this line
|
360
|
353
|
}
|
361
|
|
-
|
362
|
|
- /**
|
363
|
|
- * This function sets the Z leveling fade factor based on the given Z height,
|
364
|
|
- * only re-calculating when necessary.
|
365
|
|
- *
|
366
|
|
- * Returns 1.0 if planner.z_fade_height is 0.0.
|
367
|
|
- * Returns 0.0 if Z is past the specified 'Fade Height'.
|
368
|
|
- */
|
369
|
|
- #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
370
|
|
- static inline float fade_scaling_factor_for_z(const float &lz) {
|
371
|
|
- if (planner.z_fade_height == 0.0) return 1.0;
|
372
|
|
- static float fade_scaling_factor = 1.0;
|
373
|
|
- const float rz = RAW_Z_POSITION(lz);
|
374
|
|
- if (last_specified_z != rz) {
|
375
|
|
- last_specified_z = rz;
|
376
|
|
- fade_scaling_factor =
|
377
|
|
- rz < planner.z_fade_height
|
378
|
|
- ? 1.0 - (rz * planner.inverse_z_fade_height)
|
379
|
|
- : 0.0;
|
380
|
|
- }
|
381
|
|
- return fade_scaling_factor;
|
|
354
|
+ return z0; // there used to be a +state.z_offset on this line
|
|
355
|
+ }
|
|
356
|
+
|
|
357
|
+ /**
|
|
358
|
+ * This function sets the Z leveling fade factor based on the given Z height,
|
|
359
|
+ * only re-calculating when necessary.
|
|
360
|
+ *
|
|
361
|
+ * Returns 1.0 if planner.z_fade_height is 0.0.
|
|
362
|
+ * Returns 0.0 if Z is past the specified 'Fade Height'.
|
|
363
|
+ */
|
|
364
|
+ #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
|
365
|
+ static inline float fade_scaling_factor_for_z(const float &lz) {
|
|
366
|
+ if (planner.z_fade_height == 0.0) return 1.0;
|
|
367
|
+ static float fade_scaling_factor = 1.0;
|
|
368
|
+ const float rz = RAW_Z_POSITION(lz);
|
|
369
|
+ if (last_specified_z != rz) {
|
|
370
|
+ last_specified_z = rz;
|
|
371
|
+ fade_scaling_factor =
|
|
372
|
+ rz < planner.z_fade_height
|
|
373
|
+ ? 1.0 - (rz * planner.inverse_z_fade_height)
|
|
374
|
+ : 0.0;
|
382
|
375
|
}
|
383
|
|
- #else
|
384
|
|
- FORCE_INLINE static float fade_scaling_factor_for_z(const float &lz) { return 1.0; }
|
385
|
|
- #endif
|
386
|
|
-
|
387
|
|
- FORCE_INLINE static float mesh_index_to_xpos(const uint8_t i) {
|
388
|
|
- return i < GRID_MAX_POINTS_X ? pgm_read_float(&_mesh_index_to_xpos[i]) : UBL_MESH_MIN_X + i * (MESH_X_DIST);
|
389
|
|
- }
|
390
|
|
-
|
391
|
|
- FORCE_INLINE static float mesh_index_to_ypos(const uint8_t i) {
|
392
|
|
- return i < GRID_MAX_POINTS_Y ? pgm_read_float(&_mesh_index_to_ypos[i]) : UBL_MESH_MIN_Y + i * (MESH_Y_DIST);
|
|
376
|
+ return fade_scaling_factor;
|
393
|
377
|
}
|
|
378
|
+ #else
|
|
379
|
+ FORCE_INLINE static float fade_scaling_factor_for_z(const float &lz) { return 1.0; }
|
|
380
|
+ #endif
|
394
|
381
|
|
395
|
|
- static bool prepare_segmented_line_to(const float ltarget[XYZE], const float &feedrate);
|
396
|
|
- static void line_to_destination_cartesian(const float &fr, uint8_t e);
|
|
382
|
+ FORCE_INLINE static float mesh_index_to_xpos(const uint8_t i) {
|
|
383
|
+ return i < GRID_MAX_POINTS_X ? pgm_read_float(&_mesh_index_to_xpos[i]) : UBL_MESH_MIN_X + i * (MESH_X_DIST);
|
|
384
|
+ }
|
397
|
385
|
|
398
|
|
- }; // class unified_bed_leveling
|
|
386
|
+ FORCE_INLINE static float mesh_index_to_ypos(const uint8_t i) {
|
|
387
|
+ return i < GRID_MAX_POINTS_Y ? pgm_read_float(&_mesh_index_to_ypos[i]) : UBL_MESH_MIN_Y + i * (MESH_Y_DIST);
|
|
388
|
+ }
|
399
|
389
|
|
400
|
|
- extern unified_bed_leveling ubl;
|
|
390
|
+ static bool prepare_segmented_line_to(const float ltarget[XYZE], const float &feedrate);
|
|
391
|
+ static void line_to_destination_cartesian(const float &fr, uint8_t e);
|
401
|
392
|
|
402
|
|
- #if ENABLED(UBL_G26_MESH_VALIDATION)
|
403
|
|
- FORCE_INLINE void gcode_G26() { ubl.G26(); }
|
404
|
|
- #endif
|
|
393
|
+}; // class unified_bed_leveling
|
405
|
394
|
|
406
|
|
- FORCE_INLINE void gcode_G29() { ubl.G29(); }
|
|
395
|
+extern unified_bed_leveling ubl;
|
407
|
396
|
|
408
|
|
-#endif // AUTO_BED_LEVELING_UBL
|
409
|
397
|
#endif // UNIFIED_BED_LEVELING_H
|