Browse Source

Clean up LCD Manual Move / UBL Mesh Edit (#18373)

Scott Lahteine 3 years ago
parent
commit
f6a2b64091
No account linked to committer's email address

+ 1
- 6
Marlin/src/MarlinCore.cpp View File

@@ -498,12 +498,7 @@ inline void manage_inactivity(const bool ignore_stepper_queue=false) {
498 498
         if (ENABLED(DISABLE_INACTIVE_Z)) DISABLE_AXIS_Z();
499 499
         if (ENABLED(DISABLE_INACTIVE_E)) disable_e_steppers();
500 500
 
501
-        #if BOTH(HAS_LCD_MENU, AUTO_BED_LEVELING_UBL)
502
-          if (ubl.lcd_map_control) {
503
-            ubl.lcd_map_control = false;
504
-            ui.defer_status_screen(false);
505
-          }
506
-        #endif
501
+        TERN_(AUTO_BED_LEVELING_UBL, ubl.steppers_were_disabled());
507 502
       }
508 503
     }
509 504
     else

+ 1
- 5
Marlin/src/feature/bedlevel/ubl/ubl.cpp View File

@@ -84,11 +84,7 @@
84 84
     _GRIDPOS(Y, 12), _GRIDPOS(Y, 13), _GRIDPOS(Y, 14), _GRIDPOS(Y, 15)
85 85
   );
86 86
 
87
-  #if HAS_LCD_MENU
88
-    bool unified_bed_leveling::lcd_map_control = false;
89
-  #endif
90
-
91
-  volatile int unified_bed_leveling::encoder_diff;
87
+  volatile int16_t unified_bed_leveling::encoder_diff;
92 88
 
93 89
   unified_bed_leveling::unified_bed_leveling() {
94 90
     reset();

+ 4
- 1
Marlin/src/feature/bedlevel/ubl/ubl.h View File

@@ -111,9 +111,12 @@ class unified_bed_leveling {
111 111
 
112 112
     #if HAS_LCD_MENU
113 113
       static bool lcd_map_control;
114
+      static void steppers_were_disabled();
115
+    #else
116
+      static inline void steppers_were_disabled() {}
114 117
     #endif
115 118
 
116
-    static volatile int encoder_diff; // Volatile because it's changed at interrupt time.
119
+    static volatile int16_t encoder_diff; // Volatile because buttons may changed it at interrupt time
117 120
 
118 121
     unified_bed_leveling();
119 122
 

+ 18
- 7
Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp View File

@@ -54,7 +54,18 @@
54 54
   #define UBL_G29_P31
55 55
 
56 56
   #if HAS_LCD_MENU
57
-    void _lcd_ubl_output_map_lcd();
57
+
58
+    bool unified_bed_leveling::lcd_map_control = false;
59
+
60
+    void unified_bed_leveling::steppers_were_disabled() {
61
+      if (lcd_map_control) {
62
+        lcd_map_control = false;
63
+        ui.defer_status_screen(false);
64
+      }
65
+    }
66
+
67
+    void ubl_map_screen();
68
+
58 69
   #endif
59 70
 
60 71
   #define SIZE_OF_LITTLE_RAISE 1
@@ -789,11 +800,11 @@
789 800
 
790 801
     bool click_and_hold(const clickFunc_t func=nullptr) {
791 802
       if (ui.button_pressed()) {
792
-        ui.quick_feedback(false);                // Preserve button state for click-and-hold
803
+        ui.quick_feedback(false);         // Preserve button state for click-and-hold
793 804
         const millis_t nxt = millis() + 1500UL;
794
-        while (ui.button_pressed()) {                // Loop while the encoder is pressed. Uses hardware flag!
795
-          idle();                                 // idle, of course
796
-          if (ELAPSED(millis(), nxt)) {           // After 1.5 seconds
805
+        while (ui.button_pressed()) {     // Loop while the encoder is pressed. Uses hardware flag!
806
+          idle();                         // idle, of course
807
+          if (ELAPSED(millis(), nxt)) {   // After 1.5 seconds
797 808
             ui.quick_feedback();
798 809
             if (func) (*func)();
799 810
             ui.wait_for_release();
@@ -995,9 +1006,9 @@
995 1006
         lcd_mesh_edit_setup(new_z);
996 1007
 
997 1008
         do {
1009
+          idle();
998 1010
           new_z = lcd_mesh_edit();
999 1011
           TERN_(UBL_MESH_EDIT_MOVES_Z, do_blocking_move_to_z(h_offset + new_z)); // Move the nozzle as the point is edited
1000
-          idle();
1001 1012
           SERIAL_FLUSH();                                   // Prevent host M105 buffer overrun.
1002 1013
         } while (!ui.button_pressed());
1003 1014
 
@@ -1022,7 +1033,7 @@
1022 1033
       SERIAL_ECHOLNPGM("Done Editing Mesh");
1023 1034
 
1024 1035
       if (lcd_map_control)
1025
-        ui.goto_screen(_lcd_ubl_output_map_lcd);
1036
+        ui.goto_screen(ubl_map_screen);
1026 1037
       else
1027 1038
         ui.return_to_status();
1028 1039
     }

+ 0
- 1
Marlin/src/feature/touch/xpt2046.cpp View File

@@ -81,7 +81,6 @@
81 81
 #endif
82 82
 
83 83
 XPT2046 touch;
84
-extern int8_t encoderDiff;
85 84
 
86 85
 void XPT2046::init() {
87 86
   SET_INPUT(TOUCH_MISO_PIN);

+ 1
- 6
Marlin/src/gcode/control/M17_M18_M84.cpp View File

@@ -64,11 +64,6 @@ void GcodeSuite::M18_M84() {
64 64
     else
65 65
       planner.finish_and_disable();
66 66
 
67
-    #if BOTH(HAS_LCD_MENU, AUTO_BED_LEVELING_UBL)
68
-      if (ubl.lcd_map_control) {
69
-        ubl.lcd_map_control = false;
70
-        ui.defer_status_screen(false);
71
-      }
72
-    #endif
67
+    TERN_(AUTO_BED_LEVELING_UBL, ubl.steppers_were_disabled());
73 68
   }
74 69
 }

+ 1
- 1
Marlin/src/lcd/menu/menu.cpp View File

@@ -230,7 +230,7 @@ void MarlinUI::goto_screen(screenFunc_t screen, const uint16_t encoder/*=0*/, co
230 230
           screen = TERN(BABYSTEP_ZPROBE_OFFSET, lcd_babystep_zoffset, lcd_babystep_z);
231 231
         else {
232 232
           #if ENABLED(MOVE_Z_WHEN_IDLE)
233
-            move_menu_scale = MOVE_Z_IDLE_MULTIPLICATOR;
233
+            ui.manual_move.menu_scale = MOVE_Z_IDLE_MULTIPLICATOR;
234 234
             screen = lcd_move_z;
235 235
           #endif
236 236
         }

+ 1
- 1
Marlin/src/lcd/menu/menu_delta_calibrate.cpp View File

@@ -46,7 +46,7 @@ void _man_probe_pt(const xy_pos_t &xy) {
46 46
     do_blocking_move_to_xy_z(xy, Z_CLEARANCE_BETWEEN_PROBES);
47 47
     ui.wait_for_move = false;
48 48
     ui.synchronize();
49
-    move_menu_scale = _MAX(PROBE_MANUALLY_STEP, MIN_STEPS_PER_SEGMENT / float(DEFAULT_XYZ_STEPS_PER_UNIT));
49
+    ui.manual_move.menu_scale = _MAX(PROBE_MANUALLY_STEP, MIN_STEPS_PER_SEGMENT / float(DEFAULT_XYZ_STEPS_PER_UNIT));
50 50
     ui.goto_screen(lcd_move_z);
51 51
   }
52 52
 }

+ 14
- 29
Marlin/src/lcd/menu/menu_motion.cpp View File

@@ -51,27 +51,12 @@
51 51
 #endif
52 52
 
53 53
 //
54
-// Tell ui.update() to start a move to current_position" after a short delay.
55
-//
56
-inline void manual_move_to_current(AxisEnum axis
57
-  #if MULTI_MANUAL
58
-    , const int8_t eindex=-1
59
-  #endif
60
-) {
61
-  #if MULTI_MANUAL
62
-    if (axis == E_AXIS) ui.manual_move_e_index = eindex >= 0 ? eindex : active_extruder;
63
-  #endif
64
-  ui.manual_move_start_time = millis() + (move_menu_scale < 0.99f ? 0UL : 250UL); // delay for bigger moves
65
-  ui.manual_move_axis = (int8_t)axis;
66
-}
67
-
68
-//
69 54
 // "Motion" > "Move Axis" submenu
70 55
 //
71 56
 
72 57
 static void _lcd_move_xyz(PGM_P const name, const AxisEnum axis) {
73 58
   if (ui.use_click()) return ui.goto_previous_screen_no_defer();
74
-  if (ui.encoderPosition && !ui.processing_manual_move) {
59
+  if (ui.encoderPosition && !ui.manual_move.processing) {
75 60
 
76 61
     // Start with no limits to movement
77 62
     float min = current_position[axis] - 1000,
@@ -105,13 +90,13 @@ static void _lcd_move_xyz(PGM_P const name, const AxisEnum axis) {
105 90
     #endif
106 91
 
107 92
     // Get the new position
108
-    const float diff = float(int32_t(ui.encoderPosition)) * move_menu_scale;
93
+    const float diff = float(int32_t(ui.encoderPosition)) * ui.manual_move.menu_scale;
109 94
     #if IS_KINEMATIC
110
-      ui.manual_move_offset += diff;
95
+      ui.manual_move.offset += diff;
111 96
       if (int32_t(ui.encoderPosition) < 0)
112
-        NOLESS(ui.manual_move_offset, min - current_position[axis]);
97
+        NOLESS(ui.manual_move.offset, min - current_position[axis]);
113 98
       else
114
-        NOMORE(ui.manual_move_offset, max - current_position[axis]);
99
+        NOMORE(ui.manual_move.offset, max - current_position[axis]);
115 100
     #else
116 101
       current_position[axis] += diff;
117 102
       if (int32_t(ui.encoderPosition) < 0)
@@ -120,16 +105,16 @@ static void _lcd_move_xyz(PGM_P const name, const AxisEnum axis) {
120 105
         NOMORE(current_position[axis], max);
121 106
     #endif
122 107
 
123
-    manual_move_to_current(axis);
108
+    ui.manual_move.soon(axis);
124 109
     ui.refresh(LCDVIEW_REDRAW_NOW);
125 110
   }
126 111
   ui.encoderPosition = 0;
127 112
   if (ui.should_draw()) {
128 113
     const float pos = NATIVE_TO_LOGICAL(
129
-      ui.processing_manual_move ? destination[axis] : current_position[axis] + TERN0(IS_KINEMATIC, ui.manual_move_offset),
114
+      ui.manual_move.processing ? destination[axis] : current_position[axis] + TERN0(IS_KINEMATIC, ui.manual_move.offset),
130 115
       axis
131 116
     );
132
-    MenuEditItemBase::draw_edit_screen(name, move_menu_scale >= 0.1f ? ftostr41sign(pos) : ftostr43sign(pos));
117
+    MenuEditItemBase::draw_edit_screen(name, ui.manual_move.menu_scale >= 0.1f ? ftostr41sign(pos) : ftostr43sign(pos));
133 118
   }
134 119
 }
135 120
 void lcd_move_x() { _lcd_move_xyz(GET_TEXT(MSG_MOVE_X), X_AXIS); }
@@ -141,10 +126,10 @@ void lcd_move_z() { _lcd_move_xyz(GET_TEXT(MSG_MOVE_Z), Z_AXIS); }
141 126
   static void lcd_move_e(TERN_(MULTI_MANUAL, const int8_t eindex=-1)) {
142 127
     if (ui.use_click()) return ui.goto_previous_screen_no_defer();
143 128
     if (ui.encoderPosition) {
144
-      if (!ui.processing_manual_move) {
145
-        const float diff = float(int32_t(ui.encoderPosition)) * move_menu_scale;
146
-        TERN(IS_KINEMATIC, ui.manual_move_offset, current_position.e) += diff;
147
-        manual_move_to_current(E_AXIS
129
+      if (!ui.manual_move.processing) {
130
+        const float diff = float(int32_t(ui.encoderPosition)) * ui.manual_move.menu_scale;
131
+        TERN(IS_KINEMATIC, ui.manual_move.offset, current_position.e) += diff;
132
+        ui.manual_move.soon(E_AXIS
148 133
           #if MULTI_MANUAL
149 134
             , eindex
150 135
           #endif
@@ -160,7 +145,7 @@ void lcd_move_z() { _lcd_move_xyz(GET_TEXT(MSG_MOVE_Z), Z_AXIS); }
160 145
       MenuEditItemBase::draw_edit_screen(
161 146
         GET_TEXT(TERN(MULTI_MANUAL, MSG_MOVE_EN, MSG_MOVE_E)),
162 147
         ftostr41sign(current_position.e
163
-          + TERN0(IS_KINEMATIC, ui.manual_move_offset)
148
+          + TERN0(IS_KINEMATIC, ui.manual_move.offset)
164 149
           - TERN0(MANUAL_E_MOVES_RELATIVE, manual_move_e_origin)
165 150
         )
166 151
       );
@@ -181,7 +166,7 @@ screenFunc_t _manual_move_func_ptr;
181 166
 
182 167
 void _goto_manual_move(const float scale) {
183 168
   ui.defer_status_screen();
184
-  move_menu_scale = scale;
169
+  ui.manual_move.menu_scale = scale;
185 170
   ui.goto_screen(_manual_move_func_ptr);
186 171
 }
187 172
 

+ 102
- 89
Marlin/src/lcd/menu/menu_ubl.cpp View File

@@ -49,46 +49,36 @@ static int8_t x_plot = 0, y_plot = 0; // May be negative during move
49 49
   static int16_t custom_bed_temp = 50;
50 50
 #endif
51 51
 
52
-float mesh_edit_value, mesh_edit_accumulator; // We round mesh_edit_value to 2.5 decimal places. So we keep a
53
-                                              // separate value that doesn't lose precision.
54
-static int16_t ubl_encoderPosition = 0;
52
+float mesh_edit_accumulator;  // Rounded to 2.5 decimal places on use
53
+
54
+inline float rounded_mesh_value() {
55
+  const int32_t rounded = int32_t(mesh_edit_accumulator * 1000);
56
+  return float(rounded - (rounded % 5L)) / 1000;
57
+}
55 58
 
56 59
 static void _lcd_mesh_fine_tune(PGM_P const msg) {
57 60
   ui.defer_status_screen();
58 61
   if (ubl.encoder_diff) {
59
-    ubl_encoderPosition = (ubl.encoder_diff > 0) ? 1 : -1;
62
+    mesh_edit_accumulator += ubl.encoder_diff > 0 ? 0.005f : -0.005f;
60 63
     ubl.encoder_diff = 0;
61
-
62
-    mesh_edit_accumulator += float(ubl_encoderPosition) * 0.005f * 0.5f;
63
-    mesh_edit_value = mesh_edit_accumulator;
64
-    ui.encoderPosition = 0;
65 64
     ui.refresh(LCDVIEW_CALL_REDRAW_NEXT);
66
-
67
-    const int32_t rounded = (int32_t)(mesh_edit_value * 1000);
68
-    mesh_edit_value = float(rounded - (rounded % 5L)) / 1000;
69 65
   }
70 66
 
71 67
   if (ui.should_draw()) {
72
-    MenuEditItemBase::draw_edit_screen(msg, ftostr43sign(mesh_edit_value));
73
-    TERN_(MESH_EDIT_GFX_OVERLAY, _lcd_zoffset_overlay_gfx(mesh_edit_value));
68
+    const float rounded_f = rounded_mesh_value();
69
+    MenuEditItemBase::draw_edit_screen(msg, ftostr43sign(rounded_f));
70
+    TERN_(MESH_EDIT_GFX_OVERLAY, _lcd_zoffset_overlay_gfx(rounded_f));
74 71
   }
75 72
 }
76 73
 
77
-void lcd_limbo() {
78
-  ui.currentScreen = []{};
79
-  ui.defer_status_screen();
80
-}
81
-
82
-float lcd_mesh_edit() {
83
-  lcd_limbo();
84
-  ui.refresh(LCDVIEW_CALL_REDRAW_NEXT);
85
-  _lcd_mesh_fine_tune(GET_TEXT(MSG_MESH_EDITOR));
86
-  return mesh_edit_value;
87
-}
74
+//
75
+// Called external to the menu system to acquire the result of an edit.
76
+//
77
+float lcd_mesh_edit() { return rounded_mesh_value(); }
88 78
 
89 79
 void lcd_mesh_edit_setup(const float &initial) {
90
-  mesh_edit_value = mesh_edit_accumulator = initial;
91
-  lcd_limbo();
80
+  mesh_edit_accumulator = initial;
81
+  ui.goto_screen([]{ _lcd_mesh_fine_tune(GET_TEXT(MSG_MESH_EDIT_Z)); });
92 82
 }
93 83
 
94 84
 void _lcd_z_offset_edit() {
@@ -97,11 +87,11 @@ void _lcd_z_offset_edit() {
97 87
 
98 88
 float lcd_z_offset_edit() {
99 89
   ui.goto_screen(_lcd_z_offset_edit);
100
-  return mesh_edit_value;
90
+  return rounded_mesh_value();
101 91
 }
102 92
 
103 93
 void lcd_z_offset_edit_setup(const float &initial) {
104
-  mesh_edit_value = mesh_edit_accumulator = initial;
94
+  mesh_edit_accumulator = initial;
105 95
   ui.goto_screen(_lcd_z_offset_edit);
106 96
 }
107 97
 
@@ -391,23 +381,9 @@ void _lcd_ubl_storage_mesh() {
391 381
 }
392 382
 
393 383
 /**
394
- * UBL LCD "radar" map homing
395
- */
396
-void _lcd_ubl_output_map_lcd();
397
-
398
-void _lcd_ubl_map_homing() {
399
-  ui.defer_status_screen();
400
-  _lcd_draw_homing();
401
-  if (all_axes_homed()) {
402
-    ubl.lcd_map_control = true; // Return to the map screen
403
-    ui.goto_screen(_lcd_ubl_output_map_lcd);
404
-  }
405
-}
406
-
407
-/**
408 384
  * UBL LCD "radar" map point editing
409 385
  */
410
-void _lcd_ubl_map_lcd_edit_cmd() {
386
+void _lcd_ubl_map_edit_cmd() {
411 387
   char ubl_lcd_gcode[50], str[10], str2[10];
412 388
   dtostrf(ubl.mesh_index_to_xpos(x_plot), 0, 2, str);
413 389
   dtostrf(ubl.mesh_index_to_ypos(y_plot), 0, 2, str2);
@@ -419,85 +395,122 @@ void _lcd_ubl_map_lcd_edit_cmd() {
419 395
  * UBL LCD Map Movement
420 396
  */
421 397
 void ubl_map_move_to_xy() {
422
-  const feedRate_t fr_mm_s = MMM_TO_MMS(XY_PROBE_SPEED);
423
-
424
-  destination = current_position;          // sync destination at the start
425 398
 
426 399
   #if ENABLED(DELTA)
427
-    if (current_position.z > delta_clip_start_height) {
400
+    if (current_position.z > delta_clip_start_height) { // Make sure the delta has fully free motion
401
+      destination = current_position;
428 402
       destination.z = delta_clip_start_height;
429
-      prepare_internal_move_to_destination(fr_mm_s);
403
+      prepare_internal_fast_move_to_destination(homing_feedrate(Z_AXIS)); // Set current_position from destination
430 404
     }
431 405
   #endif
432 406
 
433
-  destination.set(ubl.mesh_index_to_xpos(x_plot), ubl.mesh_index_to_ypos(y_plot));
434
-  prepare_internal_move_to_destination(fr_mm_s);
407
+  // Set the nozzle position to the mesh point
408
+  current_position.set(ubl.mesh_index_to_xpos(x_plot), ubl.mesh_index_to_ypos(y_plot));
409
+
410
+  // Use the built-in manual move handler
411
+  ui.manual_move.soon(ALL_AXES);
412
+}
413
+
414
+inline int32_t grid_index(const uint8_t x, const uint8_t y) {
415
+  return (GRID_MAX_POINTS_X) * y + x;
435 416
 }
436 417
 
437 418
 /**
438 419
  * UBL LCD "radar" map
439 420
  */
440
-void _lcd_ubl_output_map_lcd() {
421
+void ubl_map_screen() {
422
+  // static millis_t next_move = 0;
423
+  // const millis_t ms = millis();
441 424
 
442
-  static int16_t step_scaler = 0;
425
+  uint8_t x, y;
443 426
 
444
-  if (ui.use_click()) return _lcd_ubl_map_lcd_edit_cmd();
427
+  if (ui.first_page) {
445 428
 
446
-  if (ui.encoderPosition) {
447
-    step_scaler += int32_t(ui.encoderPosition);
448
-    x_plot += step_scaler / (ENCODER_STEPS_PER_MENU_ITEM);
449
-    ui.encoderPosition = 0;
450
-    ui.refresh(LCDVIEW_REDRAW_NOW);
451
-  }
429
+    // On click send "G29 P4 ..." to edit the Z value
430
+    if (ui.use_click()) {
431
+      _lcd_ubl_map_edit_cmd();
432
+      return;
433
+    }
452 434
 
453
-  #define KEEP_LOOPING ENABLED(IS_KINEMATIC) // Loop until a valid point is found
435
+    ui.defer_status_screen();
436
+
437
+    #if IS_KINEMATIC
438
+      // Index of the mesh point upon entry
439
+      const uint32_t old_pos_index = grid_index(x_plot, y_plot);
440
+      // Direction from new (unconstrained) encoder value
441
+      const int8_t step_dir = int32_t(ui.encoderPosition) < old_pos_index ? -1 : 1;
442
+    #endif
454 443
 
455
-  do {
456
-    // Encoder to the right (++)
457
-    if (x_plot >= GRID_MAX_POINTS_X) { x_plot = 0; y_plot++; }
458
-    if (y_plot >= GRID_MAX_POINTS_Y) y_plot = 0;
444
+    do {
445
+      // Now, keep the encoder position within range
446
+      if (int32_t(ui.encoderPosition) < 0) ui.encoderPosition = GRID_MAX_POINTS - 1;
447
+      if (int32_t(ui.encoderPosition) > GRID_MAX_POINTS - 1) ui.encoderPosition = 0;
459 448
 
460
-    // Encoder to the left (--)
461
-    if (x_plot < 0) { x_plot = GRID_MAX_POINTS_X - 1; y_plot--; }
462
-    if (y_plot < 0) y_plot = GRID_MAX_POINTS_Y - 1;
449
+      // Draw the grid point based on the encoder
450
+      x = ui.encoderPosition % (GRID_MAX_POINTS_X);
451
+      y = ui.encoderPosition / (GRID_MAX_POINTS_X);
463 452
 
453
+      // Validate if needed
454
+      #if IS_KINEMATIC
455
+        const xy_pos_t xy = { ubl.mesh_index_to_xpos(x), ubl.mesh_index_to_ypos(y) };
456
+        if (position_is_reachable(xy)) break; // Found a valid point
457
+        ui.encoderPosition += step_dir;       // Test the next point
458
+      #endif
459
+    } while(ENABLED(IS_KINEMATIC));
460
+
461
+    // Determine number of points to edit
464 462
     #if IS_KINEMATIC
465
-      const xy_pos_t xy = { ubl.mesh_index_to_xpos(x_plot), ubl.mesh_index_to_ypos(y_plot) };
466
-      if (position_is_reachable(xy)) break; // Found a valid point
467
-      x_plot += (step_scaler < 0) ? -1 : 1;
463
+      n_edit_pts = 9; // TODO: Delta accessible edit points
464
+    #else
465
+      const bool xc = WITHIN(x, 1, GRID_MAX_POINTS_X - 2),
466
+                 yc = WITHIN(y, 1, GRID_MAX_POINTS_Y - 2);
467
+      n_edit_pts = yc ? (xc ? 9 : 6) : (xc ? 6 : 4); // Corners
468 468
     #endif
469 469
 
470
-  } while(KEEP_LOOPING);
470
+    // Refresh is also set by encoder movement
471
+    //if (int32_t(ui.encoderPosition) != grid_index(x, y))
472
+    //  ui.refresh(LCDVIEW_CALL_REDRAW_NEXT);
473
+  }
471 474
 
472
-  // Determine number of points to edit
473
-  #if IS_KINEMATIC
474
-    n_edit_pts = 9; //TODO: Delta accessible edit points
475
-  #else
476
-    const bool xc = WITHIN(x_plot, 1, GRID_MAX_POINTS_X - 2),
477
-               yc = WITHIN(y_plot, 1, GRID_MAX_POINTS_Y - 2);
478
-    n_edit_pts = yc ? (xc ? 9 : 6) : (xc ? 6 : 4); // Corners
479
-  #endif
475
+  // Draw the grid point based on the encoder
476
+  x = ui.encoderPosition % (GRID_MAX_POINTS_X);
477
+  y = ui.encoderPosition / (GRID_MAX_POINTS_X);
480 478
 
481
-  // Cleanup
482
-  if (ABS(step_scaler) >= ENCODER_STEPS_PER_MENU_ITEM) step_scaler = 0;
479
+  if (ui.should_draw()) ui.ubl_plot(x, y);
483 480
 
484
-  if (ui.should_draw()) {
485
-    ui.ubl_plot(x_plot, y_plot);
486
-    if (!planner.movesplanned())
487
-      ubl_map_move_to_xy();       // Move to new location
481
+  // Add a move if needed to match the grid point
482
+  if (x != x_plot || y != y_plot) {
483
+    x_plot = x; y_plot = y;   // The move is always posted, so update the grid point now
484
+    ubl_map_move_to_xy();     // Sets up a "manual move"
485
+    ui.refresh(LCDVIEW_CALL_REDRAW_NEXT); // Clean up a half drawn box
486
+  }
487
+}
488
+
489
+/**
490
+ * UBL LCD "radar" map homing
491
+ */
492
+void _ubl_map_screen_homing() {
493
+  ui.defer_status_screen();
494
+  _lcd_draw_homing();
495
+  if (all_axes_homed()) {
496
+    ubl.lcd_map_control = true;     // Return to the map screen after editing Z
497
+    ui.goto_screen(ubl_map_screen, grid_index(x_plot, y_plot)); // Pre-set the encoder value
498
+    ui.manual_move.menu_scale = 0;  // Immediate move
499
+    ubl_map_move_to_xy();           // Move to current mesh point
500
+    ui.manual_move.menu_scale = 1;  // Delayed moves
488 501
   }
489 502
 }
490 503
 
491 504
 /**
492 505
  * UBL Homing before LCD map
493 506
  */
494
-void _lcd_ubl_output_map_lcd_cmd() {
507
+void _ubl_goto_map_screen() {
508
+  if (planner.movesplanned()) return;     // The ACTION_ITEM will do nothing
495 509
   if (!all_axes_known()) {
496 510
     set_all_unhomed();
497 511
     queue.inject_P(G28_STR);
498 512
   }
499
-  if (planner.movesplanned()) return;
500
-  ui.goto_screen(_lcd_ubl_map_homing);
513
+  ui.goto_screen(_ubl_map_screen_homing); // Go to the "Homing" screen
501 514
 }
502 515
 
503 516
 /**
@@ -591,7 +604,7 @@ void _lcd_ubl_level_bed() {
591 604
   #if ENABLED(G26_MESH_VALIDATION)
592 605
     SUBMENU(MSG_UBL_STEP_BY_STEP_MENU, _lcd_ubl_step_by_step);
593 606
   #endif
594
-  ACTION_ITEM(MSG_UBL_MESH_EDIT, _lcd_ubl_output_map_lcd_cmd);
607
+  ACTION_ITEM(MSG_UBL_MESH_EDIT, _ubl_goto_map_screen);
595 608
   SUBMENU(MSG_UBL_STORAGE_MESH_MENU, _lcd_ubl_storage_mesh);
596 609
   SUBMENU(MSG_UBL_OUTPUT_MAP, _lcd_ubl_output_map);
597 610
   SUBMENU(MSG_UBL_TOOLS, _menu_ubl_tools);

+ 77
- 35
Marlin/src/lcd/ultralcd.cpp View File

@@ -211,7 +211,6 @@ millis_t MarlinUI::next_button_update_ms; // = 0
211 211
   #endif
212 212
 
213 213
   bool MarlinUI::lcd_clicked;
214
-  float move_menu_scale;
215 214
 
216 215
   bool MarlinUI::use_click() {
217 216
     const bool click = lcd_clicked;
@@ -388,7 +387,7 @@ bool MarlinUI::get_blink() {
388 387
     void lcd_move_z();
389 388
 
390 389
     void _reprapworld_keypad_move(const AxisEnum axis, const int16_t dir) {
391
-      move_menu_scale = REPRAPWORLD_KEYPAD_MOVE_STEP;
390
+      ui.manual_move.menu_scale = REPRAPWORLD_KEYPAD_MOVE_STEP;
392 391
       ui.encoderPosition = dir;
393 392
       switch (axis) {
394 393
         case X_AXIS: lcd_move_x(); break;
@@ -637,51 +636,65 @@ void MarlinUI::quick_feedback(const bool clear_buttons/*=true*/) {
637 636
 
638 637
 #if HAS_LCD_MENU
639 638
 
640
-  int8_t MarlinUI::manual_move_axis = (int8_t)NO_AXIS;
641
-  millis_t MarlinUI::manual_move_start_time = 0;
639
+  ManualMove MarlinUI::manual_move{};
642 640
 
643
-  #if IS_KINEMATIC
644
-    bool MarlinUI::processing_manual_move = false;
645
-    float MarlinUI::manual_move_offset = 0;
646
-  #endif
647
-
648
-  #if MULTI_MANUAL
649
-    int8_t MarlinUI::manual_move_e_index = 0;
650
-  #endif
641
+  millis_t ManualMove::start_time = 0;
642
+  float ManualMove::menu_scale = 1;
643
+  TERN_(IS_KINEMATIC, float ManualMove::offset = 0);
644
+  TERN_(IS_KINEMATIC, bool ManualMove::processing = false);
645
+  TERN_(MULTI_MANUAL, int8_t ManualMove::e_index = 0);
646
+  uint8_t ManualMove::axis = (uint8_t)NO_AXIS;
651 647
 
652 648
   /**
653
-   * If the most recent manual move hasn't been fed to the planner yet,
654
-   * and the planner can accept one, send a move immediately.
649
+   * If a manual move has been posted and its time has arrived, and if the planner
650
+   * has a space for it, then add a linear move to current_position the planner.
651
+   *
652
+   * If any manual move needs to be interrupted, make sure to force a manual move
653
+   * by setting manual_move.start_time to millis() after updating current_position.
654
+   *
655
+   * To post a manual move:
656
+   *   - Update current_position to the new place you want to go.
657
+   *   - Set manual_move.axis to an axis like X_AXIS. Use ALL_AXES for diagonal moves.
658
+   *   - Set manual_move.start_time to a point in the future (in ms) when the move should be done.
659
+   *
660
+   * For kinematic machines:
661
+   *   - Set manual_move.offset to modify one axis and post the move.
662
+   *     This is used to achieve more rapid stepping on kinematic machines.
663
+   *
664
+   * Currently used by the _lcd_move_xyz function in menu_motion.cpp
665
+   * and the ubl_map_move_to_xy funtion in menu_ubl.cpp.
655 666
    */
656
-  void MarlinUI::manage_manual_move() {
667
+  void ManualMove::task() {
657 668
 
658
-    if (processing_manual_move) return;
669
+    if (processing) return;   // Prevent re-entry from idle() calls
659 670
 
660
-    if (manual_move_axis != (int8_t)NO_AXIS && ELAPSED(millis(), manual_move_start_time) && !planner.is_full()) {
671
+    // Add a manual move to the queue?
672
+    if (axis != (uint8_t)NO_AXIS && ELAPSED(millis(), start_time) && !planner.is_full()) {
673
+
674
+      const feedRate_t fr_mm_s = (uint8_t(axis) <= E_AXIS) ? manual_feedrate_mm_s[axis] : XY_PROBE_FEEDRATE_MM_S;
661 675
 
662
-      const feedRate_t fr_mm_s = manual_feedrate_mm_s[manual_move_axis];
663 676
       #if IS_KINEMATIC
664 677
 
665 678
         #if EXTRUDERS > 1
666 679
           const int8_t old_extruder = active_extruder;
667
-          if (manual_move_axis == E_AXIS) active_extruder = manual_move_e_index;
680
+          if (axis == E_AXIS) active_extruder = e_index;
668 681
         #endif
669 682
 
670
-        // Set movement on a single axis
683
+        // Apply a linear offset to a single axis
671 684
         destination = current_position;
672
-        destination[manual_move_axis] += manual_move_offset;
685
+        if (axis <= XYZE) destination[axis] += offset;
673 686
 
674 687
         // Reset for the next move
675
-        manual_move_offset = 0;
676
-        manual_move_axis = (int8_t)NO_AXIS;
688
+        offset = 0;
689
+        axis = (uint8_t)NO_AXIS;
677 690
 
678 691
         // DELTA and SCARA machines use segmented moves, which could fill the planner during the call to
679 692
         // move_to_destination. This will cause idle() to be called, which can then call this function while the
680
-        // previous invocation is being blocked. Modifications to manual_move_offset shouldn't be made while
681
-        // processing_manual_move is true or the planner will get out of sync.
682
-        processing_manual_move = true;
693
+        // previous invocation is being blocked. Modifications to offset shouldn't be made while
694
+        // processing is true or the planner will get out of sync.
695
+        processing = true;
683 696
         prepare_internal_move_to_destination(fr_mm_s);  // will set current_position from destination
684
-        processing_manual_move = false;
697
+        processing = false;
685 698
 
686 699
         #if EXTRUDERS > 1
687 700
           active_extruder = old_extruder;
@@ -689,15 +702,47 @@ void MarlinUI::quick_feedback(const bool clear_buttons/*=true*/) {
689 702
 
690 703
       #else
691 704
 
692
-        planner.buffer_line(current_position, fr_mm_s, manual_move_axis == E_AXIS ? manual_move_e_index : active_extruder);
693
-        manual_move_axis = (int8_t)NO_AXIS;
705
+        // For Cartesian / Core motion simply move to the current_position
706
+        planner.buffer_line(current_position, fr_mm_s, axis == E_AXIS ? e_index : active_extruder);
707
+
708
+        //SERIAL_ECHOLNPAIR("Add planner.move with Axis ", int(axis), " at FR ", fr_mm_s);
709
+
710
+        axis = (uint8_t)NO_AXIS;
694 711
 
695 712
       #endif
696 713
     }
697 714
   }
698 715
 
716
+  //
717
+  // Tell ui.update() to start a move to current_position after a short delay.
718
+  //
719
+  void ManualMove::soon(AxisEnum move_axis
720
+    #if MULTI_MANUAL
721
+      , const int8_t eindex/*=-1*/
722
+    #endif
723
+  ) {
724
+    #if MULTI_MANUAL
725
+      if (move_axis == E_AXIS) e_index = eindex >= 0 ? eindex : active_extruder;
726
+    #endif
727
+    start_time = millis() + (menu_scale < 0.99f ? 0UL : 250UL); // delay for bigger moves
728
+    axis = (uint8_t)move_axis;
729
+    //SERIAL_ECHOLNPAIR("Post Move with Axis ", int(axis), " soon.");
730
+  }
731
+
699 732
 #endif // HAS_LCD_MENU
700 733
 
734
+#if ENABLED(AUTO_BED_LEVELING_UBL)
735
+
736
+  void MarlinUI::external_encoder() {
737
+    if (external_control && encoderDiff) {
738
+      ubl.encoder_diff += encoderDiff;  // Encoder for UBL G29 mesh editing
739
+      encoderDiff = 0;                  // Hide encoder events from the screen handler
740
+      refresh(LCDVIEW_REDRAW_NOW);      // ...but keep the refresh.
741
+    }
742
+  }
743
+
744
+#endif
745
+
701 746
 /**
702 747
  * Update the LCD, read encoder buttons, etc.
703 748
  *   - Read button states
@@ -753,7 +798,7 @@ void MarlinUI::update() {
753 798
   #if HAS_LCD_MENU
754 799
 
755 800
     // Handle any queued Move Axis motion
756
-    manage_manual_move();
801
+    manual_move.task();
757 802
 
758 803
     // Update button states for button_pressed(), etc.
759 804
     // If the state changes the next update may be delayed 300-500ms.
@@ -776,7 +821,7 @@ void MarlinUI::update() {
776 821
           if (ELAPSED(ms, next_button_update_ms)) {
777 822
             encoderDiff = (ENCODER_STEPS_PER_MENU_ITEM) * (ENCODER_PULSES_PER_STEP) * encoderDirection;
778 823
             if (touch_buttons & EN_A) encoderDiff *= -1;
779
-            TERN_(AUTO_BED_LEVELING_UBL, if (external_control) ubl.encoder_diff = encoderDiff);
824
+            TERN_(AUTO_BED_LEVELING_UBL, external_encoder());
780 825
             next_button_update_ms = ms + repeat_delay;    // Assume the repeat delay
781 826
             if (!wait_for_unclick) {
782 827
               next_button_update_ms += 250;               // Longer delay on first press
@@ -1196,10 +1241,7 @@ void MarlinUI::update() {
1196 1241
           case encrot2: ENCODER_SPIN(encrot1, encrot3); break;
1197 1242
           case encrot3: ENCODER_SPIN(encrot2, encrot0); break;
1198 1243
         }
1199
-        if (external_control) {
1200
-          TERN_(AUTO_BED_LEVELING_UBL, ubl.encoder_diff = encoderDiff); // Make encoder rotation available to UBL G29 mesh editing.
1201
-          encoderDiff = 0;                    // Hide the encoder event from the current screen handler.
1202
-        }
1244
+        TERN_(AUTO_BED_LEVELING_UBL, external_encoder());
1203 1245
         lastEncoderBits = enc;
1204 1246
       }
1205 1247
 

+ 34
- 20
Marlin/src/lcd/ultralcd.h View File

@@ -99,9 +99,6 @@
99 99
     typedef void (*screenFunc_t)();
100 100
     typedef void (*menuAction_t)();
101 101
 
102
-    // Manual Movement
103
-    extern float move_menu_scale;
104
-
105 102
     #if ENABLED(ADVANCED_PAUSE_FEATURE)
106 103
       void lcd_pause_show_message(const PauseMessage message,
107 104
                                   const PauseMode mode=PAUSE_MODE_SAME,
@@ -264,6 +261,35 @@
264 261
   } preheat_t;
265 262
 #endif
266 263
 
264
+#if HAS_LCD_MENU
265
+
266
+  // Manual Movement class
267
+  class ManualMove {
268
+  public:
269
+    static millis_t start_time;
270
+    static float menu_scale;
271
+    TERN_(IS_KINEMATIC, static float offset);
272
+    #if IS_KINEMATIC
273
+      static bool processing;
274
+    #else
275
+      static bool constexpr processing = false;
276
+    #endif
277
+    #if MULTI_MANUAL
278
+      static int8_t e_index;
279
+    #else
280
+      static int8_t constexpr e_index = 0;
281
+    #endif
282
+    static uint8_t axis;
283
+    static void task();
284
+    static void soon(AxisEnum axis
285
+      #if MULTI_MANUAL
286
+        , const int8_t eindex=-1
287
+      #endif
288
+    );
289
+  };
290
+
291
+#endif
292
+
267 293
 ////////////////////////////////////////////
268 294
 //////////// MarlinUI Singleton ////////////
269 295
 ////////////////////////////////////////////
@@ -494,29 +520,14 @@ public:
494 520
       static void enable_encoder_multiplier(const bool onoff);
495 521
     #endif
496 522
 
497
-    static int8_t manual_move_axis;
498
-    static millis_t manual_move_start_time;
499
-
500
-    #if IS_KINEMATIC
501
-      static float manual_move_offset;
502
-      static bool processing_manual_move;
503
-    #else
504
-      static constexpr bool processing_manual_move = false;
505
-    #endif
506
-
507
-    #if E_MANUAL > 1
508
-      static int8_t manual_move_e_index;
509
-    #else
510
-      static constexpr int8_t manual_move_e_index = 0;
511
-    #endif
523
+    // Manual Movement
524
+    static ManualMove manual_move;
512 525
 
513 526
     // Select Screen (modal NO/YES style dialog)
514 527
     static bool selection;
515 528
     static void set_selection(const bool sel) { selection = sel; }
516 529
     static bool update_selection();
517 530
 
518
-    static void manage_manual_move();
519
-
520 531
     static bool lcd_clicked;
521 532
     static bool use_click();
522 533
 
@@ -609,6 +620,9 @@ public:
609 620
     static bool external_control;
610 621
     FORCE_INLINE static void capture() { external_control = true; }
611 622
     FORCE_INLINE static void release() { external_control = false; }
623
+    #if ENABLED(AUTO_BED_LEVELING_UBL)
624
+      static void external_encoder();
625
+    #endif
612 626
   #else
613 627
     static constexpr bool external_control = false;
614 628
   #endif

+ 5
- 3
Marlin/src/module/motion.cpp View File

@@ -1316,16 +1316,18 @@ void do_homing_move(const AxisEnum axis, const float distance, const feedRate_t
1316 1316
     current_position[axis] = distance;
1317 1317
     line_to_current_position(real_fr_mm_s);
1318 1318
   #else
1319
+    // Get the ABC or XYZ positions in mm
1319 1320
     abce_pos_t target = planner.get_axis_positions_mm();
1320
-    target[axis] = 0;
1321
-    planner.set_machine_position_mm(target);
1322
-    target[axis] = distance;
1321
+
1322
+    target[axis] = 0;                         // Set the single homing axis to 0
1323
+    planner.set_machine_position_mm(target);  // Update the machine position
1323 1324
 
1324 1325
     #if HAS_DIST_MM_ARG
1325 1326
       const xyze_float_t cart_dist_mm{0};
1326 1327
     #endif
1327 1328
 
1328 1329
     // Set delta/cartesian axes directly
1330
+    target[axis] = distance;                  // The move will be towards the endstop
1329 1331
     planner.buffer_segment(target
1330 1332
       #if HAS_DIST_MM_ARG
1331 1333
         , cart_dist_mm

+ 4
- 2
Marlin/src/module/planner.cpp View File

@@ -1654,7 +1654,7 @@ void Planner::synchronize() {
1654 1654
  *  extruder      - target extruder
1655 1655
  *  millimeters   - the length of the movement, if known
1656 1656
  *
1657
- * Returns true if movement was properly queued, false otherwise
1657
+ * Returns true if movement was properly queued, false otherwise (if cleaning)
1658 1658
  */
1659 1659
 bool Planner::_buffer_steps(const xyze_long_t &target
1660 1660
   #if HAS_POSITION_FLOAT
@@ -2637,6 +2637,8 @@ void Planner::buffer_sync_block() {
2637 2637
  *  fr_mm_s     - (target) speed of the move
2638 2638
  *  extruder    - target extruder
2639 2639
  *  millimeters - the length of the movement, if known
2640
+ *
2641
+ * Return 'false' if no segment was queued due to cleaning, cold extrusion, full queue, etc.
2640 2642
  */
2641 2643
 bool Planner::buffer_segment(const float &a, const float &b, const float &c, const float &e
2642 2644
   #if HAS_DIST_MM_ARG
@@ -2706,7 +2708,7 @@ bool Planner::buffer_segment(const float &a, const float &b, const float &c, con
2706 2708
     SERIAL_ECHOLNPGM(")");
2707 2709
   //*/
2708 2710
 
2709
-  // Queue the movement
2711
+  // Queue the movement. Return 'false' if the move was not queued.
2710 2712
   if (!_buffer_steps(target
2711 2713
       #if HAS_POSITION_FLOAT
2712 2714
         , target_float

Loading…
Cancel
Save