|
@@ -8652,7 +8652,68 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
8652
|
8652
|
mesh_line_to_destination(fr_mm_s, x_splits, y_splits);
|
8653
|
8653
|
}
|
8654
|
8654
|
|
8655
|
|
-#endif // MESH_BED_LEVELING
|
|
8655
|
+#elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
|
8656
|
+
|
|
8657
|
+ /**
|
|
8658
|
+ * Prepare a mesh-leveled linear move in a Cartesian setup,
|
|
8659
|
+ * splitting the move where it crosses mesh borders.
|
|
8660
|
+ */
|
|
8661
|
+ void bilinear_line_to_destination(float fr_mm_s, uint8_t x_splits = 0xff, uint8_t y_splits = 0xff) {
|
|
8662
|
+ int cx1 = RAW_CURRENT_POSITION(X_AXIS) / bilinear_grid_spacing[X_AXIS],
|
|
8663
|
+ cy1 = RAW_CURRENT_POSITION(Y_AXIS) / bilinear_grid_spacing[Y_AXIS],
|
|
8664
|
+ cx2 = RAW_X_POSITION(destination[X_AXIS]) / bilinear_grid_spacing[X_AXIS],
|
|
8665
|
+ cy2 = RAW_Y_POSITION(destination[Y_AXIS]) / bilinear_grid_spacing[Y_AXIS];
|
|
8666
|
+ NOMORE(cx1, ABL_GRID_POINTS_X - 2);
|
|
8667
|
+ NOMORE(cy1, ABL_GRID_POINTS_Y - 2);
|
|
8668
|
+ NOMORE(cx2, ABL_GRID_POINTS_X - 2);
|
|
8669
|
+ NOMORE(cy2, ABL_GRID_POINTS_Y - 2);
|
|
8670
|
+
|
|
8671
|
+ if (cx1 == cx2 && cy1 == cy2) {
|
|
8672
|
+ // Start and end on same mesh square
|
|
8673
|
+ line_to_destination(fr_mm_s);
|
|
8674
|
+ set_current_to_destination();
|
|
8675
|
+ return;
|
|
8676
|
+ }
|
|
8677
|
+
|
|
8678
|
+ #define LINE_SEGMENT_END(A) (current_position[A ##_AXIS] + (destination[A ##_AXIS] - current_position[A ##_AXIS]) * normalized_dist)
|
|
8679
|
+
|
|
8680
|
+ float normalized_dist, end[NUM_AXIS];
|
|
8681
|
+
|
|
8682
|
+ // Split at the left/front border of the right/top square
|
|
8683
|
+ int8_t gcx = max(cx1, cx2), gcy = max(cy1, cy2);
|
|
8684
|
+ if (cx2 != cx1 && TEST(x_splits, gcx)) {
|
|
8685
|
+ memcpy(end, destination, sizeof(end));
|
|
8686
|
+ destination[X_AXIS] = LOGICAL_X_POSITION(bilinear_start[X_AXIS] + bilinear_grid_spacing[X_AXIS] * gcx);
|
|
8687
|
+ normalized_dist = (destination[X_AXIS] - current_position[X_AXIS]) / (end[X_AXIS] - current_position[X_AXIS]);
|
|
8688
|
+ destination[Y_AXIS] = LINE_SEGMENT_END(Y);
|
|
8689
|
+ CBI(x_splits, gcx);
|
|
8690
|
+ }
|
|
8691
|
+ else if (cy2 != cy1 && TEST(y_splits, gcy)) {
|
|
8692
|
+ memcpy(end, destination, sizeof(end));
|
|
8693
|
+ destination[Y_AXIS] = LOGICAL_Y_POSITION(bilinear_start[Y_AXIS] + bilinear_grid_spacing[Y_AXIS] * gcy);
|
|
8694
|
+ normalized_dist = (destination[Y_AXIS] - current_position[Y_AXIS]) / (end[Y_AXIS] - current_position[Y_AXIS]);
|
|
8695
|
+ destination[X_AXIS] = LINE_SEGMENT_END(X);
|
|
8696
|
+ CBI(y_splits, gcy);
|
|
8697
|
+ }
|
|
8698
|
+ else {
|
|
8699
|
+ // Already split on a border
|
|
8700
|
+ line_to_destination(fr_mm_s);
|
|
8701
|
+ set_current_to_destination();
|
|
8702
|
+ return;
|
|
8703
|
+ }
|
|
8704
|
+
|
|
8705
|
+ destination[Z_AXIS] = LINE_SEGMENT_END(Z);
|
|
8706
|
+ destination[E_AXIS] = LINE_SEGMENT_END(E);
|
|
8707
|
+
|
|
8708
|
+ // Do the split and look for more borders
|
|
8709
|
+ bilinear_line_to_destination(fr_mm_s, x_splits, y_splits);
|
|
8710
|
+
|
|
8711
|
+ // Restore destination from stack
|
|
8712
|
+ memcpy(destination, end, sizeof(end));
|
|
8713
|
+ bilinear_line_to_destination(fr_mm_s, x_splits, y_splits);
|
|
8714
|
+ }
|
|
8715
|
+
|
|
8716
|
+#endif // AUTO_BED_LEVELING_BILINEAR
|
8656
|
8717
|
|
8657
|
8718
|
#if IS_KINEMATIC
|
8658
|
8719
|
|
|
@@ -8846,6 +8907,12 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) {
|
8846
|
8907
|
return false;
|
8847
|
8908
|
}
|
8848
|
8909
|
else
|
|
8910
|
+ #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
|
|
8911
|
+ if (planner.abl_enabled) {
|
|
8912
|
+ bilinear_line_to_destination(MMS_SCALED(feedrate_mm_s));
|
|
8913
|
+ return false;
|
|
8914
|
+ }
|
|
8915
|
+ else
|
8849
|
8916
|
#endif
|
8850
|
8917
|
line_to_destination(MMS_SCALED(feedrate_mm_s));
|
8851
|
8918
|
}
|