|
|
@ -111,9 +111,6 @@ static void lcd_status_screen(); |
|
|
|
|
|
|
|
#if ENABLED(MANUAL_BED_LEVELING) |
|
|
|
#include "mesh_bed_leveling.h" |
|
|
|
static void _lcd_level_bed(); |
|
|
|
static void _lcd_level_bed_homing(); |
|
|
|
static void lcd_level_bed(); |
|
|
|
#endif |
|
|
|
|
|
|
|
/* Different types of actions that can be used in menu items. */ |
|
|
@ -464,6 +461,15 @@ static void lcd_status_screen() { |
|
|
|
|
|
|
|
#if ENABLED(ULTIPANEL) |
|
|
|
|
|
|
|
inline void line_to_current(AxisEnum axis) { |
|
|
|
#if ENABLED(DELTA) |
|
|
|
calculate_delta(current_position); |
|
|
|
plan_buffer_line(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], current_position[E_AXIS], manual_feedrate[axis]/60, active_extruder); |
|
|
|
#else |
|
|
|
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[axis]/60, active_extruder); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
#if ENABLED(SDSUPPORT) |
|
|
|
|
|
|
|
static void lcd_sdcard_pause() { card.pauseSDPrint(); } |
|
|
@ -852,6 +858,147 @@ void lcd_cooldown() { |
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
#if ENABLED(MANUAL_BED_LEVELING) |
|
|
|
|
|
|
|
/**
|
|
|
|
* |
|
|
|
* "Prepare" > "Bed Leveling" handlers |
|
|
|
* |
|
|
|
*/ |
|
|
|
|
|
|
|
static int _lcd_level_bed_position; |
|
|
|
|
|
|
|
/**
|
|
|
|
* MBL Wait for controller movement and clicks: |
|
|
|
* - Movement adjusts the Z axis |
|
|
|
* - Click saves the Z and goes to the next mesh point |
|
|
|
*/ |
|
|
|
static void _lcd_level_bed_procedure() { |
|
|
|
static bool mbl_wait_for_move = false; |
|
|
|
// Menu handlers may be called in a re-entrant fashion
|
|
|
|
// if they call st_synchronize or plan_buffer_line. So
|
|
|
|
// while waiting for a move we just ignore new input.
|
|
|
|
if (mbl_wait_for_move) { |
|
|
|
lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
ENCODER_DIRECTION_NORMAL(); |
|
|
|
|
|
|
|
// Encoder wheel adjusts the Z position
|
|
|
|
if (encoderPosition != 0 && movesplanned() <= 3) { |
|
|
|
refresh_cmd_timeout(); |
|
|
|
current_position[Z_AXIS] += float((int)encoderPosition) * (MBL_Z_STEP); |
|
|
|
if (min_software_endstops) NOLESS(current_position[Z_AXIS], Z_MIN_POS); |
|
|
|
if (max_software_endstops) NOMORE(current_position[Z_AXIS], Z_MAX_POS); |
|
|
|
encoderPosition = 0; |
|
|
|
line_to_current(Z_AXIS); |
|
|
|
lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW; |
|
|
|
} |
|
|
|
|
|
|
|
// Update on first display, then only on updates to Z position
|
|
|
|
if (lcdDrawUpdate) { |
|
|
|
float v = current_position[Z_AXIS] - MESH_HOME_SEARCH_Z; |
|
|
|
lcd_implementation_drawedit(PSTR(MSG_MOVE_Z), ftostr43(v + (v < 0 ? -0.0001 : 0.0001), '+')); |
|
|
|
} |
|
|
|
|
|
|
|
// We want subsequent calls, but don't force redraw
|
|
|
|
// Set here so it can be overridden by lcd_return_to_status below
|
|
|
|
lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW; |
|
|
|
|
|
|
|
// Click sets the current Z and moves to the next position
|
|
|
|
static bool debounce_click = false; |
|
|
|
if (LCD_CLICKED) { |
|
|
|
if (!debounce_click) { |
|
|
|
debounce_click = true; // ignore multiple "clicks" in a row
|
|
|
|
int ix = _lcd_level_bed_position % (MESH_NUM_X_POINTS), |
|
|
|
iy = _lcd_level_bed_position / (MESH_NUM_X_POINTS); |
|
|
|
if (iy & 1) ix = (MESH_NUM_X_POINTS - 1) - ix; // Zig zag
|
|
|
|
mbl.set_z(ix, iy, current_position[Z_AXIS]); |
|
|
|
_lcd_level_bed_position++; |
|
|
|
if (_lcd_level_bed_position == (MESH_NUM_X_POINTS) * (MESH_NUM_Y_POINTS)) { |
|
|
|
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z; |
|
|
|
mbl_wait_for_move = true; |
|
|
|
line_to_current(Z_AXIS); |
|
|
|
st_synchronize(); |
|
|
|
mbl.active = 1; |
|
|
|
enqueue_and_echo_commands_P(PSTR("G28")); |
|
|
|
mbl_wait_for_move = false; |
|
|
|
lcd_return_to_status(); |
|
|
|
#if ENABLED(NEWPANEL) |
|
|
|
lcd_quick_feedback(); |
|
|
|
#endif |
|
|
|
LCD_ALERTMESSAGEPGM(MSG_LEVEL_BED_DONE); |
|
|
|
#if HAS_BUZZER |
|
|
|
buzz(200, 659); |
|
|
|
buzz(200, 698); |
|
|
|
#endif |
|
|
|
} |
|
|
|
else { |
|
|
|
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z; |
|
|
|
line_to_current(Z_AXIS); |
|
|
|
ix = _lcd_level_bed_position % (MESH_NUM_X_POINTS); |
|
|
|
iy = _lcd_level_bed_position / (MESH_NUM_X_POINTS); |
|
|
|
if (iy & 1) ix = (MESH_NUM_X_POINTS - 1) - ix; // Zig zag
|
|
|
|
current_position[X_AXIS] = mbl.get_x(ix); |
|
|
|
current_position[Y_AXIS] = mbl.get_y(iy); |
|
|
|
line_to_current(manual_feedrate[X_AXIS] <= manual_feedrate[Y_AXIS] ? X_AXIS : Y_AXIS); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
debounce_click = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static void _lcd_level_bed_homing_done() { |
|
|
|
if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_WAITING), NULL); |
|
|
|
lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW; |
|
|
|
if (LCD_CLICKED) { |
|
|
|
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z; |
|
|
|
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); |
|
|
|
current_position[X_AXIS] = MESH_MIN_X; |
|
|
|
current_position[Y_AXIS] = MESH_MIN_Y; |
|
|
|
line_to_current(manual_feedrate[X_AXIS] <= manual_feedrate[Y_AXIS] ? X_AXIS : Y_AXIS); |
|
|
|
_lcd_level_bed_position = 0; |
|
|
|
lcd_goto_menu(_lcd_level_bed_procedure, true); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* MBL Move to mesh starting point |
|
|
|
*/ |
|
|
|
static void _lcd_level_bed_homing() { |
|
|
|
if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_HOMING), NULL); |
|
|
|
lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW; |
|
|
|
if (axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS]) |
|
|
|
lcd_goto_menu(_lcd_level_bed_homing_done); |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* MBL Continue Bed Leveling... |
|
|
|
*/ |
|
|
|
static void _lcd_level_bed_continue() { |
|
|
|
defer_return_to_status = true; |
|
|
|
axis_known_position[X_AXIS] = axis_known_position[Y_AXIS] = axis_known_position[Z_AXIS] = false; |
|
|
|
mbl.reset(); |
|
|
|
enqueue_and_echo_commands_P(PSTR("G28")); |
|
|
|
lcd_goto_menu(_lcd_level_bed_homing, true); |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* MBL entry-point |
|
|
|
*/ |
|
|
|
static void lcd_level_bed() { |
|
|
|
START_MENU(); |
|
|
|
MENU_ITEM(back, MSG_LEVEL_BED_CANCEL); |
|
|
|
MENU_ITEM(submenu, MSG_LEVEL_BED, _lcd_level_bed_continue); |
|
|
|
END_MENU(); |
|
|
|
} |
|
|
|
|
|
|
|
#endif // MANUAL_BED_LEVELING
|
|
|
|
|
|
|
|
/**
|
|
|
|
* |
|
|
|
* "Prepare" submenu |
|
|
@ -951,15 +1098,6 @@ static void lcd_prepare_menu() { |
|
|
|
|
|
|
|
#endif // DELTA_CALIBRATION_MENU
|
|
|
|
|
|
|
|
inline void line_to_current(AxisEnum axis) { |
|
|
|
#if ENABLED(DELTA) |
|
|
|
calculate_delta(current_position); |
|
|
|
plan_buffer_line(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], current_position[E_AXIS], manual_feedrate[axis]/60, active_extruder); |
|
|
|
#else |
|
|
|
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[axis]/60, active_extruder); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* |
|
|
|
* "Prepare" > "Move Axis" submenu |
|
|
@ -2495,138 +2633,4 @@ char* ftostr52(const float& x) { |
|
|
|
return conv; |
|
|
|
} |
|
|
|
|
|
|
|
#if ENABLED(MANUAL_BED_LEVELING) |
|
|
|
|
|
|
|
static int _lcd_level_bed_position; |
|
|
|
|
|
|
|
/**
|
|
|
|
* MBL Wait for controller movement and clicks: |
|
|
|
* - Movement adjusts the Z axis |
|
|
|
* - Click saves the Z and goes to the next mesh point |
|
|
|
*/ |
|
|
|
static void _lcd_level_bed_procedure() { |
|
|
|
static bool mbl_wait_for_move = false; |
|
|
|
// Menu handlers may be called in a re-entrant fashion
|
|
|
|
// if they call st_synchronize or plan_buffer_line. So
|
|
|
|
// while waiting for a move we just ignore new input.
|
|
|
|
if (mbl_wait_for_move) { |
|
|
|
lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
ENCODER_DIRECTION_NORMAL(); |
|
|
|
|
|
|
|
// Encoder wheel adjusts the Z position
|
|
|
|
if (encoderPosition != 0 && movesplanned() <= 3) { |
|
|
|
refresh_cmd_timeout(); |
|
|
|
current_position[Z_AXIS] += float((int)encoderPosition) * (MBL_Z_STEP); |
|
|
|
if (min_software_endstops) NOLESS(current_position[Z_AXIS], Z_MIN_POS); |
|
|
|
if (max_software_endstops) NOMORE(current_position[Z_AXIS], Z_MAX_POS); |
|
|
|
encoderPosition = 0; |
|
|
|
line_to_current(Z_AXIS); |
|
|
|
lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW; |
|
|
|
} |
|
|
|
|
|
|
|
// Update on first display, then only on updates to Z position
|
|
|
|
if (lcdDrawUpdate) { |
|
|
|
float v = current_position[Z_AXIS] - MESH_HOME_SEARCH_Z; |
|
|
|
lcd_implementation_drawedit(PSTR(MSG_MOVE_Z), ftostr43(v + (v < 0 ? -0.0001 : 0.0001), '+')); |
|
|
|
} |
|
|
|
|
|
|
|
// We want subsequent calls, but don't force redraw
|
|
|
|
// Set here so it can be overridden by lcd_return_to_status below
|
|
|
|
lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW; |
|
|
|
|
|
|
|
// Click sets the current Z and moves to the next position
|
|
|
|
static bool debounce_click = false; |
|
|
|
if (LCD_CLICKED) { |
|
|
|
if (!debounce_click) { |
|
|
|
debounce_click = true; // ignore multiple "clicks" in a row
|
|
|
|
int ix = _lcd_level_bed_position % (MESH_NUM_X_POINTS), |
|
|
|
iy = _lcd_level_bed_position / (MESH_NUM_X_POINTS); |
|
|
|
if (iy & 1) ix = (MESH_NUM_X_POINTS - 1) - ix; // Zig zag
|
|
|
|
mbl.set_z(ix, iy, current_position[Z_AXIS]); |
|
|
|
_lcd_level_bed_position++; |
|
|
|
if (_lcd_level_bed_position == (MESH_NUM_X_POINTS) * (MESH_NUM_Y_POINTS)) { |
|
|
|
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z; |
|
|
|
mbl_wait_for_move = true; |
|
|
|
line_to_current(Z_AXIS); |
|
|
|
st_synchronize(); |
|
|
|
mbl.active = 1; |
|
|
|
enqueue_and_echo_commands_P(PSTR("G28")); |
|
|
|
mbl_wait_for_move = false; |
|
|
|
lcd_return_to_status(); |
|
|
|
#if ENABLED(NEWPANEL) |
|
|
|
lcd_quick_feedback(); |
|
|
|
#endif |
|
|
|
LCD_ALERTMESSAGEPGM(MSG_LEVEL_BED_DONE); |
|
|
|
#if HAS_BUZZER |
|
|
|
buzz(200, 659); |
|
|
|
buzz(200, 698); |
|
|
|
#endif |
|
|
|
} |
|
|
|
else { |
|
|
|
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z; |
|
|
|
line_to_current(Z_AXIS); |
|
|
|
ix = _lcd_level_bed_position % (MESH_NUM_X_POINTS); |
|
|
|
iy = _lcd_level_bed_position / (MESH_NUM_X_POINTS); |
|
|
|
if (iy & 1) ix = (MESH_NUM_X_POINTS - 1) - ix; // Zig zag
|
|
|
|
current_position[X_AXIS] = mbl.get_x(ix); |
|
|
|
current_position[Y_AXIS] = mbl.get_y(iy); |
|
|
|
line_to_current(manual_feedrate[X_AXIS] <= manual_feedrate[Y_AXIS] ? X_AXIS : Y_AXIS); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
debounce_click = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static void _lcd_level_bed_homing_done() { |
|
|
|
if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_WAITING), NULL); |
|
|
|
lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW; |
|
|
|
if (LCD_CLICKED) { |
|
|
|
current_position[Z_AXIS] = MESH_HOME_SEARCH_Z; |
|
|
|
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); |
|
|
|
current_position[X_AXIS] = MESH_MIN_X; |
|
|
|
current_position[Y_AXIS] = MESH_MIN_Y; |
|
|
|
line_to_current(manual_feedrate[X_AXIS] <= manual_feedrate[Y_AXIS] ? X_AXIS : Y_AXIS); |
|
|
|
_lcd_level_bed_position = 0; |
|
|
|
lcd_goto_menu(_lcd_level_bed_procedure, true); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* MBL Move to mesh starting point |
|
|
|
*/ |
|
|
|
static void _lcd_level_bed_homing() { |
|
|
|
if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_HOMING), NULL); |
|
|
|
lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW; |
|
|
|
if (axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS]) |
|
|
|
lcd_goto_menu(_lcd_level_bed_homing_done); |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* MBL Continue Bed Leveling... |
|
|
|
*/ |
|
|
|
static void _lcd_level_bed_continue() { |
|
|
|
defer_return_to_status = true; |
|
|
|
axis_known_position[X_AXIS] = axis_known_position[Y_AXIS] = axis_known_position[Z_AXIS] = false; |
|
|
|
mbl.reset(); |
|
|
|
enqueue_and_echo_commands_P(PSTR("G28")); |
|
|
|
lcd_goto_menu(_lcd_level_bed_homing, true); |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* MBL entry-point |
|
|
|
*/ |
|
|
|
static void lcd_level_bed() { |
|
|
|
START_MENU(); |
|
|
|
MENU_ITEM(back, MSG_LEVEL_BED_CANCEL); |
|
|
|
MENU_ITEM(submenu, MSG_LEVEL_BED, _lcd_level_bed_continue); |
|
|
|
END_MENU(); |
|
|
|
} |
|
|
|
|
|
|
|
#endif // MANUAL_BED_LEVELING
|
|
|
|
|
|
|
|
#endif // ULTRA_LCD
|
|
|
|