From 824f71d50372616ca218bcb23e7fe797daa5f797 Mon Sep 17 00:00:00 2001 From: Roxy-3D Date: Mon, 12 Jun 2017 18:26:49 -0500 Subject: [PATCH] LCD Panel Interactive Mesh Editing (#7045) Original Mesh Bed Leveling replacement put at top of UBL Menu Options to help facilitate the removal of the Original Mesh Bed Leveling. Radar display (and control) of the UBL Interactive Mesh Editing. --- Marlin/Marlin_main.cpp | 14 +- Marlin/language_en.h | 3 + Marlin/ubl.cpp | 27 ++-- Marlin/ubl_G29.cpp | 17 ++- Marlin/ultralcd.cpp | 253 ++++++++++++++++++++++++++++++--- Marlin/ultralcd_impl_DOGM.h | 4 + Marlin/ultralcd_impl_HD44780.h | 8 ++ 7 files changed, 294 insertions(+), 32 deletions(-) diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 35a9f3e5d..33384530f 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -324,6 +324,8 @@ #if ENABLED(AUTO_BED_LEVELING_UBL) #include "ubl.h" + extern bool defer_return_to_status; + extern bool ubl_lcd_map_control; unified_bed_leveling ubl; #define UBL_MESH_VALID !( ( ubl.z_values[0][0] == ubl.z_values[0][1] && ubl.z_values[0][1] == ubl.z_values[0][2] \ && ubl.z_values[1][0] == ubl.z_values[1][1] && ubl.z_values[1][1] == ubl.z_values[1][2] \ @@ -755,7 +757,7 @@ void report_current_position_detail(); * Set the planner/stepper positions directly from current_position with * no kinematic translation. Used for homing axes and cartesian/core syncing. */ -inline void sync_plan_position() { +void sync_plan_position() { #if ENABLED(DEBUG_LEVELING_FEATURE) if (DEBUGGING(LEVELING)) DEBUG_POS("sync_plan_position", current_position); #endif @@ -7656,6 +7658,12 @@ inline void gcode_M18_M84() { if (parser.seen('E')) disable_e_steppers(); #endif } + + #if ENABLED(AUTO_BED_LEVELING_UBL) + ubl_lcd_map_control = false; + defer_return_to_status = false; + #endif + } } @@ -12429,6 +12437,10 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) { #if ENABLED(DISABLE_INACTIVE_E) disable_e_steppers(); #endif + #if ENABLED(AUTO_BED_LEVELING_UBL) + ubl_lcd_map_control = false; + defer_return_to_status = false; + #endif } #ifdef CHDK // Check if pin should be set to LOW after M240 set it to HIGH diff --git a/Marlin/language_en.h b/Marlin/language_en.h index 56a0e5642..dfad170a7 100644 --- a/Marlin/language_en.h +++ b/Marlin/language_en.h @@ -280,6 +280,9 @@ #ifndef MSG_UBL_OUTPUT_MAP_CSV #define MSG_UBL_OUTPUT_MAP_CSV _UxGT("Output for CSV") #endif + #ifndef MSG_UBL_OUTPUT_MAP_BACKUP + #define MSG_UBL_OUTPUT_MAP_BACKUP _UxGT("Off Printer Backup") + #endif #ifndef MSG_UBL_INFO_UBL #define MSG_UBL_INFO_UBL _UxGT("Output UBL Info") #endif diff --git a/Marlin/ubl.cpp b/Marlin/ubl.cpp index e11629659..14d411e5c 100644 --- a/Marlin/ubl.cpp +++ b/Marlin/ubl.cpp @@ -107,11 +107,15 @@ } } + // display_map() currently produces three different mesh map types + // 0 : suitable for PronterFace and Repetier's serial console + // 1 : .CSV file suitable for importation into various spread sheets + // 2 : disply of the map data on a RepRap Graphical LCD Panel + void unified_bed_leveling::display_map(const int map_type) { - const bool map0 = map_type == 0; constexpr uint8_t spaces = 8 * (GRID_MAX_POINTS_X - 2); - if (map0) { + if (map_type == 0) { SERIAL_PROTOCOLLNPGM("\nBed Topography Report:\n"); serial_echo_xy(0, GRID_MAX_POINTS_Y - 1); SERIAL_ECHO_SP(spaces + 3); @@ -123,6 +127,9 @@ SERIAL_EOL(); } + if (map_type == 1) { SERIAL_PROTOCOLLNPGM("\nBed Topography Report for CSV:"); SERIAL_EOL(); } + if (map_type == 2) { SERIAL_PROTOCOLLNPGM("\nBed Topography Report for LCD:"); SERIAL_EOL(); } + const float current_xi = get_cell_index_x(current_position[X_AXIS] + (MESH_X_DIST) / 2.0), current_yi = get_cell_index_y(current_position[Y_AXIS] + (MESH_Y_DIST) / 2.0); @@ -131,37 +138,37 @@ const bool is_current = i == current_xi && j == current_yi; // is the nozzle here? then mark the number - if (map0) SERIAL_CHAR(is_current ? '[' : ' '); + if (map_type == 0) SERIAL_CHAR(is_current ? '[' : ' '); const float f = z_values[i][j]; if (isnan(f)) { - serialprintPGM(map0 ? PSTR(" . ") : PSTR("NAN")); + serialprintPGM((map_type == 0) ? PSTR(" . ") : PSTR("NAN")); } else { // if we don't do this, the columns won't line up nicely - if (map0 && f >= 0.0) SERIAL_CHAR(' '); - SERIAL_PROTOCOL_F(f, 3); + if ((map_type == 0) && f >= 0.0) SERIAL_CHAR(' '); + if (map_type <= 1) SERIAL_PROTOCOL_F(f, 3); idle(); } - if (!map0 && i < GRID_MAX_POINTS_X - 1) SERIAL_CHAR(','); + if (map_type == 1 && i < GRID_MAX_POINTS_X - 1) SERIAL_CHAR(','); #if TX_BUFFER_SIZE > 0 MYSERIAL.flushTX(); #endif safe_delay(15); - if (map0) { + if (map_type == 0) { SERIAL_CHAR(is_current ? ']' : ' '); SERIAL_CHAR(' '); } } SERIAL_EOL(); - if (j && map0) { // we want the (0,0) up tight against the block of numbers + if (j && (map_type == 0)) { // we want the (0,0) up tight against the block of numbers SERIAL_CHAR(' '); SERIAL_EOL(); } } - if (map0) { + if (map_type == 0) { serial_echo_xy(UBL_MESH_MIN_X, UBL_MESH_MIN_Y); SERIAL_ECHO_SP(spaces + 4); serial_echo_xy(UBL_MESH_MAX_X, UBL_MESH_MIN_Y); diff --git a/Marlin/ubl_G29.cpp b/Marlin/ubl_G29.cpp index 64a3820f1..7ae5b3099 100644 --- a/Marlin/ubl_G29.cpp +++ b/Marlin/ubl_G29.cpp @@ -45,6 +45,9 @@ void lcd_mesh_edit_setup(float initial); float lcd_mesh_edit(); void lcd_z_offset_edit_setup(float); + #ifdef DOGLCD + extern void _lcd_ubl_output_map_lcd(); + #endif float lcd_z_offset_edit(); #endif @@ -53,6 +56,9 @@ extern float probe_pt(const float &x, const float &y, bool, int); extern bool set_probe_deployed(bool); extern void set_bed_leveling_enabled(bool); + extern bool ubl_lcd_map_control; + typedef void (*screenFunc_t)(); + extern void lcd_goto_screen(screenFunc_t screen, const uint32_t encoder = 0); #define SIZE_OF_LITTLE_RAISE 1 #define BIG_RAISE_NOT_NEEDED 0 @@ -1191,7 +1197,7 @@ #endif g29_map_type = parser.seen('T') && parser.has_value() ? parser.value_int() : 0; - if (!WITHIN(g29_map_type, 0, 1)) { + if (!WITHIN(g29_map_type, 0, 2)) { SERIAL_PROTOCOLLNPGM("Invalid map type.\n"); return UBL_ERR; } @@ -1535,8 +1541,8 @@ while (ubl_lcd_clicked()) { // debounce and watch for abort idle(); if (ELAPSED(millis(), nxt)) { + ubl_lcd_map_control = false; lcd_return_to_status(); - //SERIAL_PROTOCOLLNPGM("\nFine Tuning of Mesh Stopped."); do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES); LCD_MESSAGEPGM(MSG_EDITING_STOPPED); @@ -1567,6 +1573,13 @@ LCD_MESSAGEPGM(MSG_UBL_DONE_EDITING_MESH); SERIAL_ECHOLNPGM("Done Editing Mesh"); + + if (ubl_lcd_map_control) { + #ifdef DOGLCD + lcd_goto_screen(_lcd_ubl_output_map_lcd); + #endif + } + else lcd_return_to_status(); } #endif diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp index fa22df4ef..865a6e3db 100644 --- a/Marlin/ultralcd.cpp +++ b/Marlin/ultralcd.cpp @@ -26,6 +26,7 @@ #include "language.h" #include "cardreader.h" #include "temperature.h" +#include "planner.h" #include "stepper.h" #include "configuration_store.h" #include "utility.h" @@ -43,6 +44,11 @@ #include "endstops.h" #endif +#if ENABLED(AUTO_BED_LEVELING_UBL) + #include "ubl.h" + bool ubl_lcd_map_control = false; +#endif + int lcd_preheat_hotend_temp[2], lcd_preheat_bed_temp[2], lcd_preheat_fan_speed[2]; #if ENABLED(FILAMENT_LCD_DISPLAY) && ENABLED(SDSUPPORT) @@ -102,9 +108,6 @@ uint16_t max_display_update_time = 0; extern bool powersupply_on; #endif - #if ENABLED(AUTO_BED_LEVELING_UBL) - #include "ubl.h" - #endif //////////////////////////////////////////// ///////////////// Menu Tree //////////////// @@ -1044,6 +1047,7 @@ void kill_screen(const char* lcd_msg) { float lcd_mesh_edit() { lcd_goto_screen(_lcd_mesh_edit_NOP); + lcdDrawUpdate = LCDVIEW_CALL_REDRAW_NEXT; _lcd_mesh_fine_tune(PSTR("Mesh Editor")); return mesh_edit_value; } @@ -1795,8 +1799,10 @@ void kill_screen(const char* lcd_msg) { custom_hotend_temp = 190, side_points = 3, ubl_fillin_amount = 5, - ubl_height_amount, - map_type; + ubl_height_amount = 1, + n_edit_pts = 1, + x_plot = 0, + y_plot = 0; /** * UBL Build Custom Mesh Command @@ -1856,8 +1862,7 @@ void kill_screen(const char* lcd_msg) { void _lcd_ubl_edit_mesh() { START_MENU(); MENU_BACK(MSG_UBL_TOOLS); - MENU_BACK(MSG_UBL_LEVEL_BED); - MENU_ITEM(gcode, MSG_UBL_FINE_TUNE_ALL, PSTR("G29 P4 R T")); + MENU_ITEM(gcode, MSG_UBL_FINE_TUNE_ALL, PSTR("G29 P4 R999 T")); MENU_ITEM(gcode, MSG_UBL_FINE_TUNE_CLOSEST, PSTR("G29 P4 T")); MENU_ITEM(submenu, MSG_UBL_MESH_HEIGHT_ADJUST, _lcd_ubl_height_adjust_menu); MENU_ITEM(function, MSG_WATCH, lcd_return_to_status); @@ -1944,7 +1949,7 @@ void kill_screen(const char* lcd_msg) { */ void _lcd_ubl_smart_fillin_cmd() { char UBL_LCD_GCODE[12]; - sprintf_P(UBL_LCD_GCODE, PSTR("G29 P3 T%i"), map_type); + sprintf_P(UBL_LCD_GCODE, PSTR("G29 P3 T0")); enqueue_and_echo_command(UBL_LCD_GCODE); } @@ -2045,12 +2050,219 @@ void kill_screen(const char* lcd_msg) { } /** - * UBL Output map Command + * UBL LCD "radar" map homing */ - void _lcd_ubl_output_map_cmd() { - char UBL_LCD_GCODE[10]; - sprintf_P(UBL_LCD_GCODE, PSTR("G29 T%i"), map_type); - enqueue_and_echo_command(UBL_LCD_GCODE); + void _lcd_ubl_output_map_lcd(); + + void _lcd_ubl_map_homing() { + if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_HOMING), NULL); + lcdDrawUpdate = LCDVIEW_CALL_NO_REDRAW; + if (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS]) + lcd_goto_screen(_lcd_ubl_output_map_lcd); + } + + /** + * UBL LCD "radar" map point editing + */ + void _lcd_ubl_map_lcd_edit_cmd() { + char ubl_lcd_gcode [50], str[10], str2[10]; + + ubl_lcd_map_control = true; // Used for returning to the map screen + + dtostrf(pgm_read_float(&ubl._mesh_index_to_xpos[x_plot]), 0, 2, str); + dtostrf(pgm_read_float(&ubl._mesh_index_to_ypos[y_plot]), 0, 2, str2); + snprintf_P(ubl_lcd_gcode, sizeof(ubl_lcd_gcode), PSTR("G29 P4 X%s Y%s R%i"), str, str2, n_edit_pts); + enqueue_and_echo_command(ubl_lcd_gcode); + } + + #ifdef DOGLCD + + /** + * UBL LCD "radar" map data + */ + #define MAP_UPPER_LEFT_CORNER_X 35 // These probably should be moved to the .h file But for now, + #define MAP_UPPER_LEFT_CORNER_Y 8 // it is easier to play with things having them here + #define MAP_MAX_PIXELS_X 53 + #define MAP_MAX_PIXELS_Y 49 + + void _lcd_ubl_plot_drawing_prep() { + uint8_t i, j, x_offset, y_offset, x_map_pixels, y_map_pixels; + uint8_t pixels_per_X_mesh_pnt, pixels_per_Y_mesh_pnt, inverted_y; + + /*********************************************************/ + /************ Scale the box pixels appropriately *********/ + /*********************************************************/ + x_map_pixels = ((MAP_MAX_PIXELS_X - 4) / GRID_MAX_POINTS_X) * GRID_MAX_POINTS_X; + y_map_pixels = ((MAP_MAX_PIXELS_Y - 4) / GRID_MAX_POINTS_Y) * GRID_MAX_POINTS_Y; + + pixels_per_X_mesh_pnt = x_map_pixels / GRID_MAX_POINTS_X; + pixels_per_Y_mesh_pnt = y_map_pixels / GRID_MAX_POINTS_Y; + + x_offset = MAP_UPPER_LEFT_CORNER_X + 1 + (MAP_MAX_PIXELS_X-x_map_pixels-2)/2; + y_offset = MAP_UPPER_LEFT_CORNER_Y + 1 + (MAP_MAX_PIXELS_Y-y_map_pixels-2)/2; + + /*********************************************************/ + /************ Clear the Mesh Map Box**********************/ + /*********************************************************/ + + u8g.setColorIndex(1); // First draw the bigger box in White so we have a border around the mesh map box + u8g.drawBox(x_offset-2, y_offset-2, x_map_pixels+4, y_map_pixels+4); + + u8g.setColorIndex(0); // Now actually clear the mesh map box + u8g.drawBox(x_offset, y_offset, x_map_pixels, y_map_pixels); + + /*********************************************************/ + /************ Display Mesh Point Locations ***************/ + /*********************************************************/ + + u8g.setColorIndex(1); + for (i = 0; i < GRID_MAX_POINTS_X; i++) { + for (j = 0; j < GRID_MAX_POINTS_Y; j++) { + u8g.drawBox(x_offset+i*pixels_per_X_mesh_pnt+pixels_per_X_mesh_pnt/2, + y_offset+j*pixels_per_Y_mesh_pnt+pixels_per_Y_mesh_pnt/2, 1, 1); + } + } + + /*********************************************************/ + /************ Fill in the Specified Mesh Point ***********/ + /*********************************************************/ + + inverted_y = GRID_MAX_POINTS_Y - y_plot - 1; // The origin is typically in the lower right corner. We need to + // invert the Y to get it to plot in the right location. + u8g.drawBox(x_offset+x_plot*pixels_per_X_mesh_pnt, y_offset+inverted_y*pixels_per_Y_mesh_pnt, + pixels_per_X_mesh_pnt, pixels_per_Y_mesh_pnt); + + /*********************************************************/ + /************** Put Relevent Text on Display *************/ + /*********************************************************/ + + // Show X and Y positions at top of screen + u8g.setColorIndex(1); + u8g.setPrintPos(5, 7); + lcd_print("X:"); + lcd_print(ftostr32(LOGICAL_X_POSITION(pgm_read_float(&ubl._mesh_index_to_xpos[x_plot])))); + u8g.setPrintPos(74, 7); + lcd_print("Y:"); + lcd_print(ftostr32(LOGICAL_Y_POSITION(pgm_read_float(&ubl._mesh_index_to_ypos[y_plot])))); + + // Print plot position + u8g.setPrintPos(5, 64); + lcd_print("("); + u8g.print(x_plot); + lcd_print(","); + u8g.print(y_plot); + lcd_print(")"); + + // Show the location value + u8g.setPrintPos(74, 64); + lcd_print("Z:"); + if (!isnan(ubl.z_values[x_plot][y_plot])) { + lcd_print(ftostr43sign(ubl.z_values[x_plot][y_plot])); + } + else { + lcd_print(" -----"); + } + } + + #endif // DOGLCD + + /** + * UBL LCD Map Movement + */ + void ubl_map_move_to_xy() { + current_position[X_AXIS] = LOGICAL_X_POSITION(pgm_read_float(&ubl._mesh_index_to_xpos[x_plot])); + current_position[Y_AXIS] = LOGICAL_Y_POSITION(pgm_read_float(&ubl._mesh_index_to_ypos[y_plot])); + planner.buffer_line_kinematic(current_position, MMM_TO_MMS(XY_PROBE_SPEED), active_extruder); + } + + /** + * UBL LCD "radar" map + */ + void set_current_from_steppers_for_axis(const AxisEnum axis); + void sync_plan_position(); + + void _lcd_ubl_output_map_lcd() { + static int step_scaler=0; + int32_t signed_enc_pos; + + defer_return_to_status = true; + + if (axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS]) { + + if (lcd_clicked) { return _lcd_ubl_map_lcd_edit_cmd(); } + ENCODER_DIRECTION_NORMAL(); + + if (encoderPosition != 0) { + signed_enc_pos = (int32_t)encoderPosition; + step_scaler += signed_enc_pos; + x_plot = (x_plot + step_scaler / ENCODER_STEPS_PER_MENU_ITEM); + + if (abs(step_scaler) >= ENCODER_STEPS_PER_MENU_ITEM) + step_scaler = 0; + refresh_cmd_timeout(); + + lcdDrawUpdate = LCDVIEW_REDRAW_NOW; + } + + encoderPosition = 0; + + // Encoder to the right (++) + if (x_plot >= GRID_MAX_POINTS_X) { x_plot = 0; y_plot++; } + if (y_plot >= GRID_MAX_POINTS_Y) y_plot = 0; + + // Encoder to the left (--) + if (x_plot <= GRID_MAX_POINTS_X - (GRID_MAX_POINTS_X + 1)) { x_plot = GRID_MAX_POINTS_X - 1; y_plot--; } + if (y_plot <= GRID_MAX_POINTS_Y - (GRID_MAX_POINTS_Y + 1)) y_plot = GRID_MAX_POINTS_Y - 1; + + // Prevent underrun/overrun of plot numbers + x_plot = constrain(x_plot, GRID_MAX_POINTS_X - (GRID_MAX_POINTS_X + 1), GRID_MAX_POINTS_X + 1); + y_plot = constrain(y_plot, GRID_MAX_POINTS_Y - (GRID_MAX_POINTS_Y + 1), GRID_MAX_POINTS_Y + 1); + + // Determine number of points to edit + #if IS_KINEMATIC + n_edit_pts = 9; //TODO: Delta accessible edit points + #else + if (x_plot < 1 || x_plot >= GRID_MAX_POINTS_X - 1) + if (y_plot < 1 || y_plot >= GRID_MAX_POINTS_Y - 1) n_edit_pts = 4; // Corners + else n_edit_pts = 6; + else if (y_plot < 1 || y_plot >= GRID_MAX_POINTS_Y - 1) n_edit_pts = 6; // Edges + else n_edit_pts = 9; // Field + #endif + + if (lcdDrawUpdate) { + #if ENABLED(DOGLCD) + _lcd_ubl_plot_drawing_prep(); + #else + _lcd_ubl_output_char_lcd(); + #endif + + ubl_map_move_to_xy(); // Move to current location + + if (planner.movesplanned()>1) { // if the nozzle is moving, cancel the move. There is a new location + #define ENABLE_STEPPER_DRIVER_INTERRUPT() SBI(TIMSK1, OCIE1A) + #define DISABLE_STEPPER_DRIVER_INTERRUPT() CBI(TIMSK1, OCIE1A) + DISABLE_STEPPER_DRIVER_INTERRUPT(); + while (planner.blocks_queued()) planner.discard_current_block(); + stepper.current_block = NULL; + planner.clear_block_buffer_runtime(); + ENABLE_STEPPER_DRIVER_INTERRUPT(); + set_current_from_steppers_for_axis(ALL_AXES); + sync_plan_position(); + ubl_map_move_to_xy(); // Move to new location + } + } + safe_delay(10); + } + else lcd_goto_screen(_lcd_ubl_map_homing); + } + + /** + * UBL Homing before LCD map + */ + void _lcd_ubl_output_map_lcd_cmd() { + if (!(axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS])) + enqueue_and_echo_commands_P(PSTR("G28")); + lcd_goto_screen(_lcd_ubl_map_homing); } /** @@ -2059,9 +2271,10 @@ void kill_screen(const char* lcd_msg) { void _lcd_ubl_output_map() { START_MENU(); MENU_BACK(MSG_UBL_LEVEL_BED); - MENU_ITEM_EDIT(int3, MSG_UBL_MAP_TYPE, &map_type, 0, 1); - if (map_type == 0) MENU_ITEM(function, MSG_UBL_OUTPUT_MAP_HOST, _lcd_ubl_output_map_cmd); - if (map_type == 1) MENU_ITEM(function, MSG_UBL_OUTPUT_MAP_CSV, _lcd_ubl_output_map_cmd); + MENU_ITEM(gcode, MSG_UBL_OUTPUT_MAP_HOST, PSTR("G29 T0")); + MENU_ITEM(gcode, MSG_UBL_OUTPUT_MAP_CSV, PSTR("G29 T1")); + MENU_ITEM(gcode, MSG_UBL_OUTPUT_MAP_BACKUP, PSTR("G29 S-1")); + MENU_ITEM(function, MSG_UBL_OUTPUT_MAP, _lcd_ubl_output_map_lcd_cmd); END_MENU(); } @@ -2091,8 +2304,10 @@ void kill_screen(const char* lcd_msg) { * Load Bed Mesh * Save Bed Mesh * - Output Map - * Map Type: - * Output Bed Mesh Host / Output Bed Mesh CSV + * Topography to Host + * CSV for Spreadsheet + * Mesh Output Backup + * Output to LCD Grid * - UBL Tools * - Build Mesh * Build PLA Mesh @@ -4035,7 +4250,7 @@ void lcd_update() { int32_t encoderMovementSteps = abs(encoderDiff) / ENCODER_PULSES_PER_STEP; if (lastEncoderMovementMillis != 0) { - // Note that the rate is always calculated between to passes through the + // Note that the rate is always calculated between two passes through the // loop and that the abs of the encoderDiff value is tracked. float encoderStepRate = (float)(encoderMovementSteps) / ((float)(ms - lastEncoderMovementMillis)) * 1000.0; diff --git a/Marlin/ultralcd_impl_DOGM.h b/Marlin/ultralcd_impl_DOGM.h index 29445262c..676dfcacf 100644 --- a/Marlin/ultralcd_impl_DOGM.h +++ b/Marlin/ultralcd_impl_DOGM.h @@ -50,6 +50,10 @@ #include +#if ENABLED(AUTO_BED_LEVELING_UBL) + #include "ubl.h" +#endif + #if ENABLED(SHOW_BOOTSCREEN) && ENABLED(SHOW_CUSTOM_BOOTSCREEN) #include "_Bootscreen.h" #endif diff --git a/Marlin/ultralcd_impl_HD44780.h b/Marlin/ultralcd_impl_HD44780.h index 7bc901854..fe21c0ae8 100644 --- a/Marlin/ultralcd_impl_HD44780.h +++ b/Marlin/ultralcd_impl_HD44780.h @@ -1076,4 +1076,12 @@ static void lcd_implementation_status_screen() { #endif // LCD_HAS_STATUS_INDICATORS +#ifdef AUTO_BED_LEVELING_UBL + void lcd_return_to_status(); // These are just place holders for the 20x4 LCD work that + void _lcd_ubl_output_char_lcd() { // is coming up very soon. Soon this will morph into the + lcd_return_to_status(); // real code. + } + +#endif // AUTO_BED_LEVELING_UBL + #endif // ULTRALCD_IMPL_HD44780_H