Encapsulate common display code in a singleton (#12395)

* Encapsulate common LCD code in a singleton
* Depend more UBL code on UBL_DEVEL_DEBUGGING
  - Since most users don't need the debugging on at all times, this helps reduce the default build size for UBL by over 2K, a little closer to fitting on 128K boards.
This commit is contained in:
Scott Lahteine
2018-11-11 12:16:24 -06:00
committed by GitHub
parent 9da6809ac3
commit a0c795b097
65 changed files with 1881 additions and 1997 deletions

View File

@ -39,70 +39,6 @@
// macro name. The mapping is independent of whether the button is directly connected or
// via a shift/i2c register.
#if HAS_LCD_MENU
extern volatile uint8_t buttons;
//
// Setup other button mappings of each panel
//
#if ENABLED(LCD_I2C_VIKI)
#define B_I2C_BTN_OFFSET 3 // (the first three bit positions reserved for EN_A, EN_B, EN_C)
// button and encoder bit positions within 'buttons'
#define B_LE (BUTTON_LEFT << B_I2C_BTN_OFFSET) // The remaining normalized buttons are all read via I2C
#define B_UP (BUTTON_UP << B_I2C_BTN_OFFSET)
#define B_MI (BUTTON_SELECT << B_I2C_BTN_OFFSET)
#define B_DW (BUTTON_DOWN << B_I2C_BTN_OFFSET)
#define B_RI (BUTTON_RIGHT << B_I2C_BTN_OFFSET)
#undef LCD_CLICKED
#if BUTTON_EXISTS(ENC)
// the pause/stop/restart button is connected to BTN_ENC when used
#define B_ST (EN_C) // Map the pause/stop/resume button into its normalized functional name
#define LCD_CLICKED() (buttons & (B_MI|B_RI|B_ST)) // pause/stop button also acts as click until we implement proper pause/stop.
#else
#define LCD_CLICKED() (buttons & (B_MI|B_RI))
#endif
// I2C buttons take too long to read inside an interrupt context and so we read them during lcd_update
#define LCD_HAS_SLOW_BUTTONS
#elif ENABLED(LCD_I2C_PANELOLU2)
#if !BUTTON_EXISTS(ENC) // Use I2C if not directly connected to a pin
#define B_I2C_BTN_OFFSET 3 // (the first three bit positions reserved for EN_A, EN_B, EN_C)
#define B_MI (PANELOLU2_ENCODER_C << B_I2C_BTN_OFFSET) // requires LiquidTWI2 library v1.2.3 or later
#undef LCD_CLICKED
#define LCD_CLICKED() (buttons & B_MI)
// I2C buttons take too long to read inside an interrupt context and so we read them during lcd_update
#define LCD_HAS_SLOW_BUTTONS
#endif
#elif DISABLED(NEWPANEL) // old style ULTIPANEL
// Shift register bits correspond to buttons:
#define BL_LE 7 // Left
#define BL_UP 6 // Up
#define BL_MI 5 // Middle
#define BL_DW 4 // Down
#define BL_RI 3 // Right
#define BL_ST 2 // Red Button
#define B_LE (_BV(BL_LE))
#define B_UP (_BV(BL_UP))
#define B_MI (_BV(BL_MI))
#define B_DW (_BV(BL_DW))
#define B_RI (_BV(BL_RI))
#define B_ST (_BV(BL_ST))
#define LCD_CLICKED() (buttons & (B_MI|B_ST))
#endif
#endif // HAS_LCD_MENU
////////////////////////////////////
// Create LCD class instance and chipset-specific information
#if ENABLED(LCD_I2C_TYPE_PCF8575)
@ -122,7 +58,7 @@
#define LCD_CLASS LiquidCrystal_I2C
#elif ENABLED(LCD_I2C_TYPE_MCP23017)
// For the LED indicators (which may be mapped to different events in lcd_implementation_update_indicators())
// For the LED indicators (which may be mapped to different events in update_indicators())
#define LCD_HAS_STATUS_INDICATORS
#define LED_A 0x04 //100
#define LED_B 0x02 //010

View File

@ -86,10 +86,6 @@
#endif
#if ENABLED(LCD_HAS_STATUS_INDICATORS)
static void lcd_implementation_update_indicators();
#endif
static void createChar_P(const char c, const byte * const ptr) {
byte temp[8];
for (uint8_t i = 0; i < 8; i++)
@ -101,7 +97,7 @@ static void createChar_P(const char c, const byte * const ptr) {
#define LCD_STR_PROGRESS "\x03\x04\x05"
#endif
void lcd_set_custom_characters(
void MarlinUI::set_custom_characters(
#if ENABLED(LCD_PROGRESS_BAR) || ENABLED(SHOW_BOOTSCREEN)
const HD44780CharSet screen_charset/*=CHARSET_INFO*/
#endif
@ -319,7 +315,7 @@ void lcd_set_custom_characters(
}
void lcd_implementation_init() {
void MarlinUI::init_lcd() {
#if ENABLED(LCD_I2C_TYPE_PCF8575)
lcd.begin(LCD_WIDTH, LCD_HEIGHT);
@ -331,7 +327,7 @@ void lcd_implementation_init() {
#elif ENABLED(LCD_I2C_TYPE_MCP23017)
lcd.setMCPType(LTI_TYPE_MCP23017);
lcd.begin(LCD_WIDTH, LCD_HEIGHT);
lcd_implementation_update_indicators();
update_indicators();
#elif ENABLED(LCD_I2C_TYPE_MCP23008)
lcd.setMCPType(LTI_TYPE_MCP23008);
@ -345,12 +341,12 @@ void lcd_implementation_init() {
lcd.begin(LCD_WIDTH, LCD_HEIGHT);
#endif
LCD_SET_CHARSET(currentScreen == lcd_status_screen ? CHARSET_INFO : CHARSET_MENU);
LCD_SET_CHARSET(on_status_screen() ? CHARSET_INFO : CHARSET_MENU);
lcd.clear();
}
void lcd_implementation_clear() { lcd.clear(); }
void MarlinUI::clear_lcd() { lcd.clear(); }
#if ENABLED(SHOW_BOOTSCREEN)
@ -408,7 +404,7 @@ void lcd_implementation_clear() { lcd.clear(); }
lcd_moveto(indent, 2); lcd_put_wchar('\x02'); lcd_put_u8str_P(PSTR( "------" )); lcd_put_wchar('\x03');
}
void lcd_bootscreen() {
void MarlinUI::show_bootscreen() {
LCD_SET_CHARSET(CHARSET_BOOT);
lcd.clear();
@ -454,6 +450,9 @@ void lcd_implementation_clear() { lcd.clear(); }
CENTER_OR_SCROLL(STRING_SPLASH_LINE1, _SPLASH_WAIT_1);
#ifdef STRING_SPLASH_LINE2
CENTER_OR_SCROLL(STRING_SPLASH_LINE2, 1500);
#ifdef STRING_SPLASH_LINE3
CENTER_OR_SCROLL(STRING_SPLASH_LINE3, 1500);
#endif
#endif
}
#elif defined(STRING_SPLASH_LINE2)
@ -484,9 +483,9 @@ void lcd_implementation_clear() { lcd.clear(); }
#endif // SHOW_BOOTSCREEN
void lcd_kill_screen() {
void MarlinUI::draw_kill_screen() {
lcd_moveto(0, 0);
lcd_put_u8str(lcd_status_message);
lcd_put_u8str(status_message);
#if LCD_HEIGHT < 4
lcd_moveto(0, 2);
#else
@ -572,13 +571,7 @@ FORCE_INLINE void _draw_bed_status(const bool blink) {
#if HAS_PRINT_PROGRESS
FORCE_INLINE void _draw_print_progress() {
const uint8_t percent = (
#if ENABLED(SDSUPPORT)
IS_SD_PRINTING() ? card.percentDone() : 0
#else
progress_bar_percent
#endif
);
const uint8_t progress = ui.get_progress();
lcd_put_u8str_P(PSTR(
#if ENABLED(SDSUPPORT)
"SD"
@ -586,8 +579,8 @@ FORCE_INLINE void _draw_bed_status(const bool blink) {
"P:"
#endif
));
if (percent)
lcd_put_u8str(itostr3(percent));
if (progress)
lcd_put_u8str(itostr3(progress));
else
lcd_put_u8str_P(PSTR("---"));
lcd_put_wchar('%');
@ -616,7 +609,7 @@ FORCE_INLINE void _draw_bed_status(const bool blink) {
#endif // LCD_PROGRESS_BAR
FORCE_INLINE void _draw_status_message(const bool blink) {
void MarlinUI::draw_status_message(const bool blink) {
lcd_moveto(0, LCD_HEIGHT - 1);
@ -624,17 +617,15 @@ FORCE_INLINE void _draw_status_message(const bool blink) {
// Draw the progress bar if the message has shown long enough
// or if there is no message set.
#if DISABLED(LCD_SET_PROGRESS_MANUALLY)
const uint8_t progress_bar_percent = card.percentDone();
#endif
if (progress_bar_percent > 2 && (ELAPSED(millis(), progress_bar_ms + PROGRESS_BAR_MSG_TIME) || !lcd_status_message[0]))
return lcd_draw_progress_bar(progress_bar_percent);
if (ELAPSED(millis(), progress_bar_ms + PROGRESS_BAR_MSG_TIME) || !has_status()) {
const uint8_t progress = get_progress();
if (progress > 2) return lcd_draw_progress_bar(progress);
}
#elif ENABLED(FILAMENT_LCD_DISPLAY) && ENABLED(SDSUPPORT)
// Show Filament Diameter and Volumetric Multiplier %
// After allowing lcd_status_message to show for 5 seconds
if (ELAPSED(millis(), previous_lcd_status_ms + 5000UL)) {
// Alternate Status message and Filament display
if (ELAPSED(millis(), next_filament_display)) {
lcd_put_u8str_P(PSTR("Dia "));
lcd_put_u8str(ftostr12ns(filament_width_meas));
lcd_put_u8str_P(PSTR(" V"));
@ -654,13 +645,13 @@ FORCE_INLINE void _draw_status_message(const bool blink) {
static bool last_blink = false;
// Get the UTF8 character count of the string
uint8_t slen = utf8_strlen(lcd_status_message);
uint8_t slen = utf8_strlen(status_message);
// If the string fits into the LCD, just print it and do not scroll it
if (slen <= LCD_WIDTH) {
// The string isn't scrolling and may not fill the screen
lcd_put_u8str(lcd_status_message);
lcd_put_u8str(status_message);
// Fill the rest with spaces
while (slen < LCD_WIDTH) {
@ -672,7 +663,7 @@ FORCE_INLINE void _draw_status_message(const bool blink) {
// String is larger than the available space in screen.
// Get a pointer to the next valid UTF8 character
const char *stat = lcd_status_message + status_scroll_offset;
const char *stat = status_message + status_scroll_offset;
// Get the string remaining length
const uint8_t rlen = utf8_strlen(stat);
@ -692,7 +683,7 @@ FORCE_INLINE void _draw_status_message(const bool blink) {
if (--chars) { // Draw a second dot if there's space
lcd_put_wchar('.');
if (--chars)
lcd_put_u8str_max(lcd_status_message, chars); // Print a second copy of the message
lcd_put_u8str_max(status_message, chars); // Print a second copy of the message
}
}
if (last_blink != blink) {
@ -701,7 +692,7 @@ FORCE_INLINE void _draw_status_message(const bool blink) {
// Adjust by complete UTF8 characters
if (status_scroll_offset < slen) {
status_scroll_offset++;
while (!START_OF_UTF8_CHAR(lcd_status_message[status_scroll_offset]))
while (!START_OF_UTF8_CHAR(status_message[status_scroll_offset]))
status_scroll_offset++;
}
else
@ -712,10 +703,10 @@ FORCE_INLINE void _draw_status_message(const bool blink) {
UNUSED(blink);
// Get the UTF8 character count of the string
uint8_t slen = utf8_strlen(lcd_status_message);
uint8_t slen = utf8_strlen(status_message);
// Just print the string to the LCD
lcd_put_u8str_max(lcd_status_message, LCD_WIDTH);
lcd_put_u8str_max(status_message, LCD_WIDTH);
// Fill the rest with spaces if there are missing spaces
while (slen < LCD_WIDTH) {
@ -725,35 +716,47 @@ FORCE_INLINE void _draw_status_message(const bool blink) {
#endif
}
#if LCD_INFO_SCREEN_STYLE == 0
/**
* LCD_INFO_SCREEN_STYLE 0 : Classic Status Screen
*
* 16x2 |000/000 B000/000|
* |0123456789012345|
*
* 16x4 |000/000 B000/000|
* |SD---% Z 000.00|
* |F---% T--:--|
* |0123456789012345|
*
* 20x2 |T000/000° B000/000° |
* |01234567890123456789|
*
* 20x4 |T000/000° B000/000° |
* |X 000 Y 000 Z000.000|
* |F---% SD---% T--:--|
* |01234567890123456789|
*
* LCD_INFO_SCREEN_STYLE 1 : Prusa-style Status Screen
*
* |T000/000° Z 000.00 |
* |B000/000° F---% |
* |SD---% T--:-- |
* |01234567890123456789|
*
* |T000/000° Z 000.00 |
* |T000/000° F---% |
* |B000/000° SD---% |
* |01234567890123456789|
*/
/**
* LCD_INFO_SCREEN_STYLE 0 : Classic Status Screen
*
* 16x2 |000/000 B000/000|
* |0123456789012345|
*
* 16x4 |000/000 B000/000|
* |SD---% Z 000.00|
* |F---% T--:--|
* |0123456789012345|
*
* 20x2 |T000/000° B000/000° |
* |01234567890123456789|
*
* 20x4 |T000/000° B000/000° |
* |X 000 Y 000 Z000.000|
* |F---% SD---% T--:--|
* |01234567890123456789|
*/
void MarlinUI::draw_status_screen() {
void lcd_impl_status_screen_0() {
const bool blink = lcd_blink();
const bool blink = get_blink();
lcd_moveto(0, 0);
#if LCD_INFO_SCREEN_STYLE == 0
// ========== Line 1 ==========
lcd_moveto(0, 0);
#if LCD_WIDTH < 20
//
@ -885,39 +888,13 @@ FORCE_INLINE void _draw_status_message(const bool blink) {
#endif // LCD_HEIGHT > 3
// ========= Last Line ========
//
// Status Message (which may be a Progress Bar or Filament display)
//
_draw_status_message(blink);
}
#elif LCD_INFO_SCREEN_STYLE == 1
/**
* LCD_INFO_SCREEN_STYLE 1 : Prusa-style Status Screen
*
* |T000/000° Z 000.00 |
* |B000/000° F---% |
* |SD---% T--:-- |
* |01234567890123456789|
*
* |T000/000° Z 000.00 |
* |T000/000° F---% |
* |B000/000° SD---% |
* |01234567890123456789|
*/
void lcd_impl_status_screen_1() {
const bool blink = lcd_blink();
#elif LCD_INFO_SCREEN_STYLE == 1
// ========== Line 1 ==========
//
// Hotend 0 Temperature
//
lcd_moveto(0, 0);
_draw_heater_status(0, LCD_STR_THERMOMETER[0], blink);
//
@ -977,30 +954,30 @@ FORCE_INLINE void _draw_status_message(const bool blink) {
lcd_put_u8str(buffer);
#endif
// ========== Line 4 ==========
#endif // LCD_INFO_SCREEN_STYLE 1
//
// Status Message (which may be a Progress Bar or Filament display)
//
_draw_status_message(blink);
}
// ========= Last Line ========
#endif
//
// Status Message (which may be a Progress Bar or Filament display)
//
draw_status_message(blink);
}
#if HAS_LCD_MENU
#if ENABLED(ADVANCED_PAUSE_FEATURE)
void lcd_implementation_hotend_status(const uint8_t row, const uint8_t extruder) {
void MarlinUI::draw_hotend_status(const uint8_t row, const uint8_t extruder) {
if (row < LCD_HEIGHT) {
lcd_moveto(LCD_WIDTH - 9, row);
_draw_heater_status(extruder, LCD_STR_THERMOMETER[0], lcd_blink());
_draw_heater_status(extruder, LCD_STR_THERMOMETER[0], ui.get_blink());
}
}
#endif // ADVANCED_PAUSE_FEATURE
void lcd_implementation_drawmenu_static(const uint8_t row, PGM_P pstr, const bool center/*=true*/, const bool invert/*=false*/, const char *valstr/*=NULL*/) {
void draw_menu_item_static(const uint8_t row, PGM_P pstr, const bool center/*=true*/, const bool invert/*=false*/, const char *valstr/*=NULL*/) {
UNUSED(invert);
int8_t n = LCD_WIDTH;
lcd_moveto(0, row);
@ -1013,35 +990,35 @@ FORCE_INLINE void _draw_status_message(const bool blink) {
for (; n > 0; --n) lcd_put_wchar(' ');
}
void lcd_implementation_drawmenu_generic(const bool sel, const uint8_t row, PGM_P pstr, const char pre_char, const char post_char) {
void draw_menu_item_generic(const bool isSelected, const uint8_t row, PGM_P pstr, const char pre_char, const char post_char) {
uint8_t n = LCD_WIDTH - 2;
lcd_moveto(0, row);
lcd_put_wchar(sel ? pre_char : ' ');
lcd_put_wchar(isSelected ? pre_char : ' ');
n -= lcd_put_u8str_max_P(pstr, n);
while (n--) lcd_put_wchar(' ');
lcd_put_wchar(post_char);
}
void lcd_implementation_drawmenu_setting_edit_generic(const bool sel, const uint8_t row, PGM_P pstr, const char pre_char, const char* const data) {
void draw_menu_item_setting_edit_generic(const bool isSelected, const uint8_t row, PGM_P pstr, const char pre_char, const char* const data) {
uint8_t n = LCD_WIDTH - 2 - utf8_strlen(data);
lcd_moveto(0, row);
lcd_put_wchar(sel ? pre_char : ' ');
lcd_put_wchar(isSelected ? pre_char : ' ');
n -= lcd_put_u8str_max_P(pstr, n);
lcd_put_wchar(':');
while (n--) lcd_put_wchar(' ');
lcd_put_u8str(data);
}
void lcd_implementation_drawmenu_setting_edit_generic_P(const bool sel, const uint8_t row, PGM_P pstr, const char pre_char, const char* const data) {
void draw_menu_item_setting_edit_generic_P(const bool isSelected, const uint8_t row, PGM_P pstr, const char pre_char, const char* const data) {
uint8_t n = LCD_WIDTH - 2 - utf8_strlen_P(data);
lcd_moveto(0, row);
lcd_put_wchar(sel ? pre_char : ' ');
lcd_put_wchar(isSelected ? pre_char : ' ');
n -= lcd_put_u8str_max_P(pstr, n);
lcd_put_wchar(':');
while (n--) lcd_put_wchar(' ');
lcd_put_u8str_P(data);
}
void lcd_implementation_drawedit(PGM_P pstr, const char* const value/*=NULL*/) {
void draw_edit_screen(PGM_P const pstr, const char* const value/*=NULL*/) {
lcd_moveto(1, 1);
lcd_put_u8str_P(pstr);
if (value != NULL) {
@ -1056,27 +1033,29 @@ FORCE_INLINE void _draw_status_message(const bool blink) {
#if ENABLED(SDSUPPORT)
static void lcd_implementation_drawmenu_sd(const bool sel, const uint8_t row, PGM_P const pstr, CardReader &theCard, const uint8_t concat, const char post_char) {
void draw_sd_menu_item(const bool isSelected, const uint8_t row, PGM_P const pstr, CardReader &theCard, const bool isDir) {
const char post_char = isDir ? LCD_STR_FOLDER[0] : ' ',
sel_char = isSelected ? '>' : ' ';
UNUSED(pstr);
lcd_moveto(0, row);
lcd_put_wchar(sel ? '>' : ' ');
lcd_put_wchar(sel_char);
uint8_t n = LCD_WIDTH - concat;
uint8_t n = LCD_WIDTH - 2;
const char *outstr = theCard.longest_filename();
if (theCard.longFilename[0]) {
#if ENABLED(SCROLL_LONG_FILENAMES)
static uint8_t filename_scroll_hash;
if (sel) {
if (isSelected) {
uint8_t name_hash = row;
for (uint8_t l = FILENAME_LENGTH; l--;)
name_hash = ((name_hash << 1) | (name_hash >> 7)) ^ theCard.filename[l]; // rotate, xor
if (filename_scroll_hash != name_hash) { // If the hash changed...
filename_scroll_hash = name_hash; // Save the new hash
filename_scroll_max = MAX(0, utf8_strlen(theCard.longFilename) - n); // Update the scroll limit
filename_scroll_pos = 0; // Reset scroll to the start
lcd_status_update_delay = 8; // Don't scroll right away
ui.filename_scroll_max = MAX(0, utf8_strlen(theCard.longFilename) - n); // Update the scroll limit
ui.filename_scroll_pos = 0; // Reset scroll to the start
ui.lcd_status_update_delay = 8; // Don't scroll right away
}
outstr += filename_scroll_pos;
outstr += ui.filename_scroll_pos;
}
#else
theCard.longFilename[n] = '\0'; // cutoff at screen edge
@ -1084,45 +1063,18 @@ FORCE_INLINE void _draw_status_message(const bool blink) {
}
lcd_moveto(0, row);
lcd_put_wchar(sel ? '>' : ' ');
lcd_put_wchar(sel_char);
n -= lcd_put_u8str_max(outstr, n);
while (n) { --n; lcd_put_wchar(' '); }
for (; n; --n) lcd_put_wchar(' ');
lcd_put_wchar(post_char);
}
void lcd_implementation_drawmenu_sdfile(const bool sel, const uint8_t row, PGM_P pstr, CardReader &theCard) {
lcd_implementation_drawmenu_sd(sel, row, pstr, theCard, 2, ' ');
}
void lcd_implementation_drawmenu_sddirectory(const bool sel, const uint8_t row, PGM_P pstr, CardReader &theCard) {
lcd_implementation_drawmenu_sd(sel, row, pstr, theCard, 2, LCD_STR_FOLDER[0]);
}
#endif // SDSUPPORT
#if ENABLED(LCD_HAS_SLOW_BUTTONS)
extern millis_t next_button_update_ms;
static uint8_t lcd_implementation_read_slow_buttons() {
#if ENABLED(LCD_I2C_TYPE_MCP23017)
// Reading these buttons this is likely to be too slow to call inside interrupt context
// so they are called during normal lcd_update
uint8_t slow_bits = lcd.readButtons() << B_I2C_BTN_OFFSET;
#if ENABLED(LCD_I2C_VIKI)
if ((slow_bits & (B_MI | B_RI)) && PENDING(millis(), next_button_update_ms)) // LCD clicked
slow_bits &= ~(B_MI | B_RI); // Disable LCD clicked buttons if screen is updated
#endif // LCD_I2C_VIKI
return slow_bits;
#endif // LCD_I2C_TYPE_MCP23017
}
#endif // LCD_HAS_SLOW_BUTTONS
#if ENABLED(LCD_HAS_STATUS_INDICATORS)
static void lcd_implementation_update_indicators() {
static void MarlinUI::update_indicators() {
// Set the LEDS - referred to as backlights by the LiquidTWI2 library
static uint8_t ledsprev = 0;
uint8_t leds = 0;
@ -1242,7 +1194,7 @@ FORCE_INLINE void _draw_status_message(const bool blink) {
lcd_put_wchar(c);
}
void lcd_implementation_ubl_plot(const uint8_t x, const uint8_t inverted_y) {
void MarlinUI::ubl_plot(const uint8_t x, const uint8_t inverted_y) {
#if LCD_WIDTH >= 20
#define _LCD_W_POS 12
@ -1292,7 +1244,7 @@ FORCE_INLINE void _draw_status_message(const bool blink) {
lower_right.column = 0;
lower_right.row = 0;
lcd_implementation_clear();
clear_lcd();
x_map_pixels = (HD44780_CHAR_WIDTH) * (MESH_MAP_COLS) - 2; // Minus 2 because we are drawing a box around the map
y_map_pixels = (HD44780_CHAR_HEIGHT) * (MESH_MAP_ROWS) - 2;

View File

@ -135,35 +135,29 @@ FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const
}
}
FORCE_INLINE void lcd_implementation_status_message(const bool blink) {
void MarlinUI::draw_status_message(const bool blink) {
// Get the UTF8 character count of the string
uint8_t slen = utf8_strlen(status_message);
#if ENABLED(STATUS_MESSAGE_SCROLLING)
static bool last_blink = false;
// Get the UTF8 character count of the string
uint8_t slen = utf8_strlen(lcd_status_message);
// If the string fits into the LCD, just print it and do not scroll it
if (slen <= LCD_WIDTH) {
// The string isn't scrolling and may not fill the screen
lcd_put_u8str(lcd_status_message);
// Fill the rest with spaces
while (slen < LCD_WIDTH) {
lcd_put_wchar(' ');
++slen;
}
// The string fits within the line. Print with no scrolling
lcd_put_u8str(status_message);
for (; slen < LCD_WIDTH; ++slen) lcd_put_wchar(' ');
}
else {
// String is larger than the available space in screen.
// String is longer than the available space
// Get a pointer to the next valid UTF8 character
const char *stat = lcd_status_message + status_scroll_offset;
const char *stat = status_message + status_scroll_offset;
// Get the string remaining length
const uint8_t rlen = utf8_strlen(stat);
// If we have enough characters to display
if (rlen >= LCD_WIDTH) {
// The remaining string fills the screen - Print it
lcd_put_u8str_max(stat, LCD_PIXEL_WIDTH);
@ -178,7 +172,7 @@ FORCE_INLINE void lcd_implementation_status_message(const bool blink) {
lcd_put_wchar('.');
if (--chars) {
// Print a second copy of the message
lcd_put_u8str_max(lcd_status_message, LCD_PIXEL_WIDTH - ((rlen+2) * MENU_FONT_WIDTH));
lcd_put_u8str_max(status_message, LCD_PIXEL_WIDTH - (rlen + 2) * (MENU_FONT_WIDTH));
}
}
}
@ -188,36 +182,33 @@ FORCE_INLINE void lcd_implementation_status_message(const bool blink) {
// Adjust by complete UTF8 characters
if (status_scroll_offset < slen) {
status_scroll_offset++;
while (!START_OF_UTF8_CHAR(lcd_status_message[status_scroll_offset]))
while (!START_OF_UTF8_CHAR(status_message[status_scroll_offset]))
status_scroll_offset++;
}
else
status_scroll_offset = 0;
}
}
#else
#else // !STATUS_MESSAGE_SCROLLING
UNUSED(blink);
// Get the UTF8 character count of the string
uint8_t slen = utf8_strlen(lcd_status_message);
// Just print the string to the LCD
lcd_put_u8str_max(lcd_status_message, LCD_PIXEL_WIDTH);
lcd_put_u8str_max(status_message, LCD_PIXEL_WIDTH);
// Fill the rest with spaces if there are missing spaces
while (slen < LCD_WIDTH) {
lcd_put_wchar(' ');
++slen;
}
#endif
// Fill the rest with spaces
for (; slen < LCD_WIDTH; ++slen) lcd_put_wchar(' ');
#endif // !STATUS_MESSAGE_SCROLLING
}
void lcd_impl_status_screen_0() {
void MarlinUI::draw_status_screen() {
const bool blink = lcd_blink();
const bool blink = get_blink();
// Status Menu Font
lcd_setFont(FONT_STATUSMENU);
set_font(FONT_STATUSMENU);
//
// Fan Animation
@ -318,11 +309,9 @@ void lcd_impl_status_screen_0() {
PROGRESS_BAR_WIDTH, 4
);
#if DISABLED(LCD_SET_PROGRESS_MANUALLY)
const uint8_t progress_bar_percent = card.percentDone();
#endif
const uint8_t progress = get_progress();
if (progress_bar_percent > 1) {
if (progress > 1) {
//
// Progress bar solid part
@ -331,7 +320,7 @@ void lcd_impl_status_screen_0() {
if (PAGE_CONTAINS(50, 51)) // 50-51 (or just 50)
u8g.drawBox(
PROGRESS_BAR_X + 1, 50,
(uint16_t)((PROGRESS_BAR_WIDTH - 2) * progress_bar_percent * 0.01), 2
(uint16_t)((PROGRESS_BAR_WIDTH - 2) * progress * 0.01), 2
);
//
@ -342,7 +331,7 @@ void lcd_impl_status_screen_0() {
if (PAGE_CONTAINS(41, 48)) {
// Percent complete
lcd_moveto(55, 48);
lcd_put_u8str(itostr3(progress_bar_percent));
lcd_put_u8str(itostr3(progress));
lcd_put_wchar('%');
}
#endif
@ -449,11 +438,11 @@ void lcd_impl_status_screen_0() {
#define EXTRAS_BASELINE 50
if (PAGE_CONTAINS(EXTRAS_BASELINE - (INFO_FONT_HEIGHT - 1), EXTRAS_BASELINE)) {
lcd_setFont(FONT_MENU);
set_font(FONT_MENU);
lcd_moveto(3, EXTRAS_BASELINE);
lcd_put_wchar(LCD_STR_FEEDRATE[0]);
lcd_setFont(FONT_STATUSMENU);
set_font(FONT_STATUSMENU);
lcd_moveto(12, EXTRAS_BASELINE);
lcd_put_u8str(itostr3(feedrate_percentage));
lcd_put_wchar('%');
@ -467,7 +456,7 @@ void lcd_impl_status_screen_0() {
lcd_moveto(102, EXTRAS_BASELINE);
lcd_put_u8str(mstring);
lcd_put_wchar('%');
lcd_setFont(FONT_MENU);
set_font(FONT_MENU);
lcd_moveto(47, EXTRAS_BASELINE);
lcd_put_wchar(LCD_STR_FILAM_DIA[0]); // lcd_put_u8str_P(PSTR(LCD_STR_FILAM_DIA));
lcd_moveto(93, EXTRAS_BASELINE);
@ -485,9 +474,9 @@ void lcd_impl_status_screen_0() {
lcd_moveto(0, STATUS_BASELINE);
#if ENABLED(FILAMENT_LCD_DISPLAY) && ENABLED(SDSUPPORT)
if (PENDING(millis(), previous_lcd_status_ms + 5000UL)) { //Display both Status message line and Filament display on the last line
lcd_implementation_status_message(blink);
}
// Alternate Status message and Filament display
if (PENDING(millis(), next_filament_display))
draw_status_message(blink);
else {
lcd_put_u8str_P(PSTR(LCD_STR_FILAM_DIA));
lcd_put_wchar(':');
@ -498,7 +487,7 @@ void lcd_impl_status_screen_0() {
lcd_put_wchar('%');
}
#else
lcd_implementation_status_message(blink);
draw_status_message(blink);
#endif
}
}

View File

@ -230,12 +230,8 @@ void ST7920_Lite_Status_Screen::load_cgram_icon(const uint16_t addr, const void
*/
void ST7920_Lite_Status_Screen::draw_gdram_icon(uint8_t x, uint8_t y, const void *data) {
const uint16_t *p_word = (const uint16_t *)data;
if (y > 2) { // Handle display folding
y -= 2;
x += 8;
}
--x;
--y;
// Handle display folding
if (y > 1) y -= 2, x += 8;
for (int i = 0; i < 16; i++) {
set_gdram_address(x, i + y * 16);
begin_data();
@ -398,24 +394,20 @@ const uint16_t feedrate_icon[] PROGMEM = {
/************************** MAIN SCREEN *************************************/
// The ST7920 does not have a degree character, but we
// can fake it by writing it to GDRAM.
// This function takes as an argument character positions
// i.e x is [1-16], while the y position is [1-4]
void ST7920_Lite_Status_Screen::draw_degree_symbol(uint8_t x, uint8_t y, bool draw) {
/**
* The ST7920 has no degree character, so draw it to GDRAM.
* This function takes character position xy
* i.e., x is [0-15], while the y position is [0-3]
*/
void ST7920_Lite_Status_Screen::draw_degree_symbol(uint8_t x, uint8_t y, const bool draw) {
const uint8_t *p_bytes = degree_symbol;
if (y > 2) {
// Handle display folding
y -= 2;
x += 16;
}
x -= 1;
y -= 1;
// Handle display folding
if (y > 1) y -= 2, x += 16;
const bool oddChar = x & 1;
const uint8_t x_word = x >> 1;
const uint8_t y_top = degree_symbol_y_top;
const uint8_t y_bot = y_top + sizeof(degree_symbol)/sizeof(degree_symbol[0]);
for(uint8_t i = y_top; i < y_bot; i++) {
const uint8_t x_word = x >> 1,
y_top = degree_symbol_y_top,
y_bot = y_top + sizeof(degree_symbol)/sizeof(degree_symbol[0]);
for (uint8_t i = y_top; i < y_bot; i++) {
uint8_t byte = pgm_read_byte(p_bytes++);
set_gdram_address(x_word, i + y * 16);
begin_data();
@ -438,14 +430,14 @@ void ST7920_Lite_Status_Screen::draw_static_elements() {
load_cgram_icon(CGRAM_ICON_4_ADDR, fan2_icon);
// Draw the static icons in GDRAM
draw_gdram_icon(1, 1, nozzle_icon);
draw_gdram_icon(0, 0, nozzle_icon);
#if HOTENDS > 1
draw_gdram_icon(1,2,nozzle_icon);
draw_gdram_icon(1,3,bed_icon);
draw_gdram_icon(0, 1, nozzle_icon);
draw_gdram_icon(0, 2, bed_icon);
#else
draw_gdram_icon(1,2,bed_icon);
draw_gdram_icon(0, 1, bed_icon);
#endif
draw_gdram_icon(6,2,feedrate_icon);
draw_gdram_icon(5, 1, feedrate_icon);
// Draw the initial fan icon
draw_fan_icon(false);
@ -462,15 +454,15 @@ void ST7920_Lite_Status_Screen::draw_static_elements() {
void ST7920_Lite_Status_Screen::draw_progress_bar(const uint8_t value) {
#if HOTENDS == 1
// If we have only one extruder, draw a long progress bar on the third line
const uint8_t top = 1, // Top in pixels
bottom = 13, // Bottom in pixels
left = 12, // Left edge, in 16-bit words
width = 4; // Width of progress bar, in 16-bit words
constexpr uint8_t top = 1, // Top in pixels
bottom = 13, // Bottom in pixels
left = 12, // Left edge, in 16-bit words
width = 4; // Width of progress bar, in 16-bit words
#else
const uint8_t top = 16 + 1,
bottom = 16 + 13,
left = 5,
width = 3;
constexpr uint8_t top = 16 + 1,
bottom = 16 + 13,
left = 5,
width = 3;
#endif
const uint8_t char_pcnt = 100 / width; // How many percent does each 16-bit word represent?
@ -557,10 +549,10 @@ static struct {
void ST7920_Lite_Status_Screen::draw_temps(uint8_t line, const int16_t temp, const int16_t target, bool showTarget, bool targetStateChange) {
switch (line) {
case 1: set_ddram_address(DDRAM_LINE_1 + 1); break;
case 2: set_ddram_address(DDRAM_LINE_2 + 1); break;
case 0: set_ddram_address(DDRAM_LINE_1 + 1); break;
case 1: set_ddram_address(DDRAM_LINE_2 + 1); break;
case 2: set_ddram_address(DDRAM_LINE_3 + 1); break;
case 3: set_ddram_address(DDRAM_LINE_3 + 1); break;
case 4: set_ddram_address(DDRAM_LINE_3 + 1); break;
}
begin_data();
write_number(temp);
@ -572,27 +564,27 @@ void ST7920_Lite_Status_Screen::draw_temps(uint8_t line, const int16_t temp, con
if (targetStateChange) {
if (!showTarget) write_str(F(" "));
draw_degree_symbol(6, line, !showTarget);
draw_degree_symbol(10, line, showTarget);
draw_degree_symbol(5, line, !showTarget);
draw_degree_symbol(9, line, showTarget);
}
}
void ST7920_Lite_Status_Screen::draw_extruder_1_temp(const int16_t temp, const int16_t target, bool forceUpdate) {
const bool show_target = target && FAR(temp, target);
draw_temps(1, temp, target, show_target, display_state.E1_show_target != show_target || forceUpdate);
draw_temps(0, temp, target, show_target, display_state.E1_show_target != show_target || forceUpdate);
display_state.E1_show_target = show_target;
}
void ST7920_Lite_Status_Screen::draw_extruder_2_temp(const int16_t temp, const int16_t target, bool forceUpdate) {
const bool show_target = target && FAR(temp, target);
draw_temps(2, temp, target, show_target, display_state.E2_show_target != show_target || forceUpdate);
draw_temps(1, temp, target, show_target, display_state.E2_show_target != show_target || forceUpdate);
display_state.E2_show_target = show_target;
}
#if HAS_HEATED_BED
void ST7920_Lite_Status_Screen::draw_bed_temp(const int16_t temp, const int16_t target, bool forceUpdate) {
const bool show_target = target && FAR(temp, target);
draw_temps(2
draw_temps(1
#if HOTENDS > 1
+ 1
#endif
@ -632,44 +624,38 @@ void ST7920_Lite_Status_Screen::draw_feedrate_percentage(const uint16_t percenta
#endif
}
void ST7920_Lite_Status_Screen::draw_status_message(const char *str) {
void ST7920_Lite_Status_Screen::draw_status_message() {
const char *str = ui.status_message;
set_ddram_address(DDRAM_LINE_4);
begin_data();
const uint8_t lcd_len = 16;
#if ENABLED(STATUS_MESSAGE_SCROLLING)
uint8_t slen = utf8_strlen(str);
// If the string fits into the LCD, just print it and do not scroll it
if (slen <= lcd_len) {
// The string isn't scrolling and may not fill the screen
if (slen <= LCD_WIDTH) {
// String fits the LCD, so just print it
write_str(str);
// Fill the rest with spaces
while (slen < lcd_len) {
write_byte(' ');
++slen;
}
for (; slen < LCD_WIDTH; ++slen) write_byte(' ');
}
else {
// String is larger than the available space in screen.
// Get a pointer to the next valid UTF8 character
const char *stat = str + status_scroll_offset;
const char *stat = str + ui.status_scroll_offset;
// Get the string remaining length
const uint8_t rlen = utf8_strlen(stat);
// If we have enough characters to display
if (rlen >= lcd_len) {
if (rlen >= LCD_WIDTH) {
// The remaining string fills the screen - Print it
write_str(stat, lcd_len);
write_str(stat, LCD_WIDTH);
}
else {
// The remaining string does not completely fill the screen
write_str(stat); // The string leaves space
uint8_t chars = lcd_len - rlen; // Amount of space left in characters
uint8_t chars = LCD_WIDTH - rlen; // Amount of space left in characters
write_byte('.'); // Always at 1+ spaces left, draw a dot
if (--chars) { // Draw a second dot if there's space
@ -680,26 +666,21 @@ void ST7920_Lite_Status_Screen::draw_status_message(const char *str) {
}
// Adjust by complete UTF8 characters
if (status_scroll_offset < slen) {
status_scroll_offset++;
while (!START_OF_UTF8_CHAR(str[status_scroll_offset]))
status_scroll_offset++;
if (ui.status_scroll_offset < slen) {
ui.status_scroll_offset++;
while (!START_OF_UTF8_CHAR(str[ui.status_scroll_offset]))
ui.status_scroll_offset++;
}
else
status_scroll_offset = 0;
ui.status_scroll_offset = 0;
}
#else
// Get the UTF8 character count of the string
uint8_t slen = utf8_strlen(str);
write_str(str, LCD_WIDTH);
for (; slen < LCD_WIDTH; ++slen) write_byte(' ');
// Just print the string to the LCD
write_str(str, lcd_len);
// Fill the rest with spaces if there are missing spaces
while (slen < lcd_len) {
write_byte(' ');
++slen;
}
#endif
}
@ -709,7 +690,7 @@ void ST7920_Lite_Status_Screen::draw_position(const float x, const float y, cons
begin_data();
// If position is unknown, flash the labels.
const unsigned char alt_label = position_known ? 0 : (lcd_blink() ? ' ' : 0);
const unsigned char alt_label = position_known ? 0 : (ui.get_blink() ? ' ' : 0);
dtostrf(x, -4, 0, str);
write_byte(alt_label ? alt_label : 'X');
@ -728,7 +709,7 @@ bool ST7920_Lite_Status_Screen::indicators_changed() {
// We only add the target temperatures to the checksum
// because the actual temps fluctuate so by updating
// them only during blinks we gain a bit of stability.
const bool blink = lcd_blink();
const bool blink = ui.get_blink();
const uint16_t feedrate_perc = feedrate_percentage;
const uint8_t fs = (((uint16_t)fan_speed[0] + 1) * 100) / 256;
const int16_t extruder_1_target = thermalManager.degTargetHotend(0);
@ -754,7 +735,7 @@ bool ST7920_Lite_Status_Screen::indicators_changed() {
void ST7920_Lite_Status_Screen::update_indicators(const bool forceUpdate) {
if (forceUpdate || indicators_changed()) {
const bool blink = lcd_blink();
const bool blink = ui.get_blink();
const duration_t elapsed = print_job_timer.duration();
const uint16_t feedrate_perc = feedrate_percentage;
const uint8_t fs = (((uint16_t)fan_speed[0] + 1) * 100) / 256;
@ -783,41 +764,32 @@ void ST7920_Lite_Status_Screen::update_indicators(const bool forceUpdate) {
// Update the fan and bed animations
if (fs) draw_fan_icon(blink);
#if HAS_HEATED_BED
if (bed_target > 0)
draw_heat_icon(blink, true);
else
draw_heat_icon(false, false);
draw_heat_icon(bed_target > 0 && blink, bed_target > 0);
#endif
}
}
bool ST7920_Lite_Status_Screen::position_changed() {
const float x_pos = current_position[X_AXIS],
y_pos = current_position[Y_AXIS],
z_pos = current_position[Z_AXIS];
const float x_pos = current_position[X_AXIS], y_pos = current_position[Y_AXIS], z_pos = current_position[Z_AXIS];
const uint8_t checksum = uint8_t(x_pos) ^ uint8_t(y_pos) ^ uint8_t(z_pos);
static uint8_t last_checksum = 0;
if (last_checksum == checksum) return false;
last_checksum = checksum;
return true;
static uint8_t last_checksum = 0, changed = last_checksum != checksum;
if (changed) last_checksum = checksum;
return changed;
}
bool ST7920_Lite_Status_Screen::status_changed() {
uint8_t checksum = 0;
for (const char *p = lcd_status_message; *p; p++) checksum ^= *p;
static uint8_t last_checksum = 0;
if (last_checksum == checksum) return false;
last_checksum = checksum;
return true;
for (const char *p = ui.status_message; *p; p++) checksum ^= *p;
static uint8_t last_checksum = 0, changed = last_checksum != checksum;
if (changed) last_checksum = checksum;
return changed;
}
bool ST7920_Lite_Status_Screen::blink_changed() {
static uint8_t last_blink = 0;
const bool blink = lcd_blink();
if (last_blink == blink) return false;
last_blink = blink;
return true;
const bool blink = ui.get_blink(), changed = last_blink != blink;
if (changed) last_blink = blink;
return changed;
}
#ifndef STATUS_EXPIRE_SECONDS
@ -831,60 +803,56 @@ void ST7920_Lite_Status_Screen::update_status_or_position(bool forceUpdate) {
#endif
/**
* There is only enough room in the display for either the
* status message or the position, not both, so we choose
* one or another. Whenever the status message changes,
* we show it for a number of consecutive seconds, but
* then go back to showing the position as soon as the
* head moves, i.e:
* There's only enough room for either the status message or the position,
* so draw one or the other. When the status message changes, show it for
* a few seconds, then return to the position display once the head moves.
*
* countdown > 1 -- Show status
* countdown = 1 -- Show status, until movement
* countdown = 0 -- Show position
* countdown > 1 -- Show status
* countdown = 1 -- Show status, until movement
* countdown = 0 -- Show position
*
* If STATUS_EXPIRE_SECONDS is zero, the position display
* will be disabled and only the status will be shown.
* If STATUS_EXPIRE_SECONDS is zero, only the status is shown.
*/
if (forceUpdate || status_changed()) {
#if ENABLED(STATUS_MESSAGE_SCROLLING)
status_scroll_offset = 0;
ui.status_scroll_offset = 0;
#endif
#if STATUS_EXPIRE_SECONDS
countdown = lcd_status_message[0] ? STATUS_EXPIRE_SECONDS : 0;
countdown = ui.status_message[0] ? STATUS_EXPIRE_SECONDS : 0;
#endif
draw_status_message(lcd_status_message);
draw_status_message();
blink_changed(); // Clear changed flag
}
#if !STATUS_EXPIRE_SECONDS
#if ENABLED(STATUS_MESSAGE_SCROLLING)
else
draw_status_message(lcd_status_message);
draw_status_message();
#endif
#else
else if (countdown > 1 && blink_changed()) {
countdown--;
#if ENABLED(STATUS_MESSAGE_SCROLLING)
draw_status_message(lcd_status_message);
#endif
}
else if (countdown > 0 && blink_changed()) {
if (position_changed()) {
else if (blink_changed()) {
if (countdown > 1) {
countdown--;
forceUpdate = true;
#if ENABLED(STATUS_MESSAGE_SCROLLING)
draw_status_message();
#endif
}
else if (countdown > 0) {
if (position_changed()) {
countdown--;
forceUpdate = true;
}
#if ENABLED(STATUS_MESSAGE_SCROLLING)
draw_status_message();
#endif
}
#if ENABLED(STATUS_MESSAGE_SCROLLING)
draw_status_message(lcd_status_message);
#endif
}
if (countdown == 0 && (forceUpdate || position_changed() ||
#if DISABLED(DISABLE_REDUCED_ACCURACY_WARNING)
blink_changed()
#endif
)) {
draw_position(
current_position[X_AXIS],
current_position[Y_AXIS],
current_position[Z_AXIS],
draw_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS],
#if ENABLED(DISABLE_REDUCED_ACCURACY_WARNING)
true
#else
@ -898,24 +866,16 @@ void ST7920_Lite_Status_Screen::update_status_or_position(bool forceUpdate) {
void ST7920_Lite_Status_Screen::update_progress(const bool forceUpdate) {
#if ENABLED(LCD_SET_PROGRESS_MANUALLY) || ENABLED(SDSUPPORT)
#if DISABLED(LCD_SET_PROGRESS_MANUALLY)
uint8_t progress_bar_percent = 0;
#endif
#if ENABLED(SDSUPPORT)
// Progress bar % comes from SD when actively printing
if (IS_SD_PRINTING()) progress_bar_percent = card.percentDone();
#endif
// Since the progress bar involves writing
// quite a few bytes to GDRAM, only do this
// when an update is actually necessary.
static uint8_t last_progress = 0;
if (!forceUpdate && last_progress == progress_bar_percent) return;
last_progress = progress_bar_percent;
draw_progress_bar(progress_bar_percent);
const uint8_t progress = ui.get_progress();
if (forceUpdate || last_progress != progress) {
last_progress = progress;
draw_progress_bar(progress);
}
#else
@ -966,7 +926,7 @@ void ST7920_Lite_Status_Screen::clear_text_buffer() {
ncs();
}
void lcd_impl_status_screen_0() {
void MarlinUI::draw_status_screen() {
ST7920_Lite_Status_Screen::update(false);
}

View File

@ -74,7 +74,7 @@ class ST7920_Lite_Status_Screen {
static uint8_t string_checksum(const char *str);
protected:
static void draw_degree_symbol(uint8_t x, uint8_t y, bool draw);
static void draw_degree_symbol(uint8_t x, uint8_t y, const bool draw);
static void draw_static_elements();
static void draw_progress_bar(const uint8_t value);
static void draw_fan_icon(const bool whichIcon);
@ -86,7 +86,7 @@ class ST7920_Lite_Status_Screen {
static void draw_fan_speed(const uint8_t value);
static void draw_print_time(const duration_t &elapsed);
static void draw_feedrate_percentage(const uint16_t percentage);
static void draw_status_message(const char *str);
static void draw_status_message();
static void draw_position(const float x, const float y, const float z, bool position_known = true);
static bool indicators_changed();

View File

@ -75,16 +75,16 @@ U8GLIB *pu8g = &u8g;
#if HAS_LCD_CONTRAST
int16_t lcd_contrast; // Initialized by settings.load()
int16_t MarlinUI::contrast; // Initialized by settings.load()
void set_lcd_contrast(const int16_t value) {
lcd_contrast = constrain(value, LCD_CONTRAST_MIN, LCD_CONTRAST_MAX);
u8g.setContrast(lcd_contrast);
void MarlinUI::set_contrast(const int16_t value) {
contrast = constrain(value, LCD_CONTRAST_MIN, LCD_CONTRAST_MAX);
u8g.setContrast(contrast);
}
#endif
void lcd_setFont(const MarlinFont font_nr) {
void MarlinUI::set_font(const MarlinFont font_nr) {
static char currentfont = 0;
if (font_nr != currentfont) {
switch ((currentfont = font_nr)) {
@ -141,7 +141,7 @@ void lcd_setFont(const MarlinFont font_nr) {
#endif // SHOW_CUSTOM_BOOTSCREEN
void lcd_bootscreen() {
void MarlinUI::show_bootscreen() {
#if ENABLED(SHOW_CUSTOM_BOOTSCREEN)
lcd_custom_bootscreen();
#endif
@ -160,7 +160,7 @@ void lcd_setFont(const MarlinFont font_nr) {
u8g.firstPage();
do {
u8g.drawBitmapP(offx, offy, (START_BMPWIDTH + 7) / 8, START_BMPHEIGHT, start_bmp);
lcd_setFont(FONT_MENU);
ui.set_font(FONT_MENU);
#ifndef STRING_SPLASH_LINE2
const uint8_t txt1X = width - (sizeof(STRING_SPLASH_LINE1) - 1) * (MENU_FONT_WIDTH);
u8g.drawStr(txt1X, (height + MENU_FONT_HEIGHT) / 2, STRING_SPLASH_LINE1);
@ -181,7 +181,7 @@ void lcd_setFont(const MarlinFont font_nr) {
#endif
// Initialize or re-initialize the LCD
void lcd_implementation_init() {
void MarlinUI::init_lcd() {
#if PIN_EXISTS(LCD_BACKLIGHT) // Enable LCD backlight
OUT_WRITE(LCD_BACKLIGHT_PIN, HIGH);
@ -206,7 +206,7 @@ void lcd_implementation_init() {
#endif
#if HAS_LCD_CONTRAST
set_lcd_contrast(lcd_contrast);
refresh_contrast();
#endif
#if ENABLED(LCD_SCREEN_ROT_90)
@ -221,16 +221,16 @@ void lcd_implementation_init() {
}
// The kill screen is displayed for unrecoverable conditions
void lcd_kill_screen() {
void MarlinUI::draw_kill_screen() {
#if ENABLED(LIGHTWEIGHT_UI)
ST7920_Lite_Status_Screen::clear_text_buffer();
#endif
const uint8_t h4 = u8g.getHeight() / 4;
u8g.firstPage();
do {
lcd_setFont(FONT_MENU);
set_font(FONT_MENU);
lcd_moveto(0, h4 * 1);
lcd_put_u8str(lcd_status_message);
lcd_put_u8str(status_message);
lcd_moveto(0, h4 * 2);
lcd_put_u8str_P(PSTR(MSG_HALTED));
lcd_moveto(0, h4 * 3);
@ -238,7 +238,7 @@ void lcd_kill_screen() {
} while (u8g.nextPage());
}
void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
#if HAS_LCD_MENU
@ -246,7 +246,7 @@ void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
#if ENABLED(ADVANCED_PAUSE_FEATURE)
void lcd_implementation_hotend_status(const uint8_t row, const uint8_t extruder) {
void MarlinUI::draw_hotend_status(const uint8_t row, const uint8_t extruder) {
row_y1 = row * (MENU_FONT_HEIGHT) + 1;
row_y2 = row_y1 + MENU_FONT_HEIGHT - 1;
@ -259,7 +259,7 @@ void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
lcd_put_u8str(itostr3(thermalManager.degHotend(extruder)));
lcd_put_wchar('/');
if (lcd_blink() || !thermalManager.is_heater_idle(extruder))
if (get_blink() || !thermalManager.is_heater_idle(extruder))
lcd_put_u8str(itostr3(thermalManager.degTargetHotend(extruder)));
}
@ -295,7 +295,7 @@ void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
}
// Draw a static line of text in the same idiom as a menu item
void lcd_implementation_drawmenu_static(const uint8_t row, PGM_P pstr, const bool center/*=true*/, const bool invert/*=false*/, const char* valstr/*=NULL*/) {
void draw_menu_item_static(const uint8_t row, PGM_P pstr, const bool center/*=true*/, const bool invert/*=false*/, const char* valstr/*=NULL*/) {
if (mark_as_selected(row, invert)) {
@ -315,7 +315,7 @@ void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
}
// Draw a generic menu item
void lcd_implementation_drawmenu_generic(const bool isSelected, const uint8_t row, PGM_P pstr, const char pre_char, const char post_char) {
void draw_menu_item_generic(const bool isSelected, const uint8_t row, PGM_P const pstr, const char pre_char, const char post_char) {
UNUSED(pre_char);
if (mark_as_selected(row, isSelected)) {
@ -330,7 +330,7 @@ void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
}
// Draw a menu item with an editable value
void _drawmenu_setting_edit_generic(const bool isSelected, const uint8_t row, PGM_P pstr, const char* const data, const bool pgm) {
void _drawmenu_setting_edit_generic(const bool isSelected, const uint8_t row, PGM_P const pstr, const char* const data, const bool pgm) {
if (mark_as_selected(row, isSelected)) {
const uint8_t vallen = (pgm ? utf8_strlen_P(data) : utf8_strlen((char*)data));
uint8_t n = LCD_WIDTH - 2 - vallen;
@ -343,7 +343,7 @@ void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
}
}
void lcd_implementation_drawedit(PGM_P const pstr, const char* const value/*=NULL*/) {
void draw_edit_screen(PGM_P const pstr, const char* const value/*=NULL*/) {
const uint8_t labellen = utf8_strlen_P(pstr), vallen = utf8_strlen(value);
bool extra_row = labellen > LCD_WIDTH - 2 - vallen;
@ -356,12 +356,12 @@ void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
if (labellen + vallen + 1 > lcd_edit_width) extra_row = true;
lcd_chr_fit = lcd_edit_width + 1;
one_chr_width = EDIT_FONT_WIDTH;
lcd_setFont(FONT_EDIT);
ui.set_font(FONT_EDIT);
}
else {
lcd_chr_fit = LCD_WIDTH;
one_chr_width = MENU_FONT_WIDTH;
lcd_setFont(FONT_MENU);
ui.set_font(FONT_MENU);
}
#else
constexpr uint8_t lcd_chr_fit = LCD_WIDTH,
@ -397,7 +397,7 @@ void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
#if ENABLED(SDSUPPORT)
void _drawmenu_sd(const bool isSelected, const uint8_t row, PGM_P const pstr, CardReader &theCard, const bool isDir) {
void draw_sd_menu_item(const bool isSelected, const uint8_t row, PGM_P const pstr, CardReader &theCard, const bool isDir) {
UNUSED(pstr);
mark_as_selected(row, isSelected);
@ -415,11 +415,11 @@ void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
name_hash = ((name_hash << 1) | (name_hash >> 7)) ^ theCard.filename[l]; // rotate, xor
if (filename_scroll_hash != name_hash) { // If the hash changed...
filename_scroll_hash = name_hash; // Save the new hash
filename_scroll_max = MAX(0, utf8_strlen(theCard.longFilename) - maxlen); // Update the scroll limit
filename_scroll_pos = 0; // Reset scroll to the start
lcd_status_update_delay = 8; // Don't scroll right away
ui.filename_scroll_max = MAX(0, utf8_strlen(theCard.longFilename) - maxlen); // Update the scroll limit
ui.filename_scroll_pos = 0; // Reset scroll to the start
ui.lcd_status_update_delay = 8; // Don't scroll right away
}
outstr += filename_scroll_pos;
outstr += ui.filename_scroll_pos;
}
#else
theCard.longFilename[maxlen] = '\0'; // cutoff at screen edge
@ -428,8 +428,7 @@ void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
if (isDir) lcd_put_wchar(LCD_STR_FOLDER[0]);
int n;
n = lcd_put_u8str_max(outstr, maxlen * (MENU_FONT_WIDTH));
uint8_t n = lcd_put_u8str_max(outstr, maxlen * (MENU_FONT_WIDTH));
n = maxlen * (MENU_FONT_WIDTH) - n;
while (n - MENU_FONT_WIDTH > 0) { n -= lcd_put_wchar(' '); }
}
@ -446,7 +445,7 @@ void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
#define MAP_MAX_PIXELS_X 53
#define MAP_MAX_PIXELS_Y 49
void lcd_implementation_ubl_plot(const uint8_t x_plot, const uint8_t y_plot) {
void MarlinUI::ubl_plot(const uint8_t x_plot, const uint8_t y_plot) {
// Scale the box pixels appropriately
uint8_t 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),

View File

@ -681,14 +681,14 @@ namespace UI {
// At the moment, we piggy-back off the ultralcd calls, but this could be cleaned up in the future
void lcd_init() {
void MarlinUI::init() {
#if ENABLED(SDSUPPORT) && PIN_EXISTS(SD_DETECT)
SET_INPUT_PULLUP(SD_DETECT_PIN);
#endif
UI::onStartup();
}
void lcd_update() {
void MarlinUI::update() {
#if ENABLED(SDSUPPORT)
static bool last_sd_status;
const bool sd_status = IS_SD_INSERTED();
@ -712,15 +712,15 @@ void lcd_update() {
UI::onIdle();
}
bool lcd_hasstatus() { return true; }
bool lcd_detected() { return true; }
void lcd_reset_alert_level() { }
void lcd_refresh() { }
void lcd_setstatus(const char * const message, const bool persist /* = false */) { UI::onStatusChanged(message); }
void lcd_setstatusPGM(const char * const message, int8_t level /* = 0 */) { UI::onStatusChanged((progmem_str)message); }
void lcd_setalertstatusPGM(const char * const message) { lcd_setstatusPGM(message, 0); }
bool MarlinUI::hasstatus() { return true; }
bool MarlinUI::detected() { return true; }
void MarlinUI::reset_alert_level() { }
void MarlinUI::refresh() { }
void MarlinUI::setstatus(const char * const message, const bool persist /* = false */) { UI::onStatusChanged(message); }
void MarlinUI::setstatusPGM(const char * const message, int8_t level /* = 0 */) { UI::onStatusChanged((progmem_str)message); }
void MarlinUI::setalertstatusPGM(const char * const message) { setstatusPGM(message, 0); }
void lcd_reset_status() {
void MarlinUI::reset_status() {
static const char paused[] PROGMEM = MSG_PRINT_PAUSED;
static const char printing[] PROGMEM = MSG_PRINTING;
static const char welcome[] PROGMEM = WELCOME_MSG;
@ -729,17 +729,17 @@ void lcd_reset_status() {
msg = paused;
#if ENABLED(SDSUPPORT)
else if (IS_SD_PRINTING())
return lcd_setstatus(card.longest_filename(), true);
return setstatus(card.longest_filename(), true);
#endif
else if (print_job_timer.isRunning())
msg = printing;
else
msg = welcome;
lcd_setstatusPGM(msg, -1);
setstatusPGM(msg, -1);
}
void lcd_status_printf_P(const uint8_t level, const char * const fmt, ...) {
void MarlinUI::status_printf_P(const uint8_t level, const char * const fmt, ...) {
char buff[64];
va_list args;
va_start(args, fmt);
@ -749,7 +749,7 @@ void lcd_status_printf_P(const uint8_t level, const char * const fmt, ...) {
UI::onStatusChanged(buff);
}
void kill_screen(PGM_P msg) {
void MarlinUI::kill_screen(PGM_P const msg) {
if (!flags.printer_killed) {
flags.printer_killed = true;
UI::onPrinterKilled(msg);

View File

@ -204,7 +204,7 @@
#define MSG_INFO_PROTOCOL _UxGT("Protocolo")
#define MSG_CASE_LIGHT _UxGT("Luz cabina")
#if LCD_WIDTH > 19
#if LCD_WIDTH >= 20
#define MSG_INFO_PRINT_COUNT _UxGT("Conteo de impresión")
#define MSG_INFO_COMPLETED_PRINTS _UxGT("Completadas")
#define MSG_INFO_PRINT_TIME _UxGT("Tiempo total de imp.")

View File

@ -324,7 +324,7 @@
#define MSG_CASE_LIGHT _UxGT("外壳灯") // "Case light"
#define MSG_CASE_LIGHT_BRIGHTNESS _UxGT("灯亮度") // "Light BRIGHTNESS"
#if LCD_WIDTH > 19
#if LCD_WIDTH >= 20
#define MSG_INFO_PRINT_COUNT _UxGT("打印计数") //"Print Count"
#define MSG_INFO_COMPLETED_PRINTS _UxGT("完成了") //"Completed"
#define MSG_INFO_PRINT_TIME _UxGT("总打印时间") //"Total print time"

View File

@ -324,7 +324,7 @@
#define MSG_CASE_LIGHT _UxGT("外殼燈") // "Case light"
#define MSG_CASE_LIGHT_BRIGHTNESS _UxGT("燈亮度") // "Light BRIGHTNESS"
#if LCD_WIDTH > 19
#if LCD_WIDTH >= 20
#define MSG_INFO_PRINT_COUNT _UxGT("列印計數") //"Print Count"
#define MSG_INFO_COMPLETED_PRINTS _UxGT("已完成") //"Completed"
#define MSG_INFO_PRINT_TIME _UxGT("總列印時間") //"Total print time"

View File

@ -417,7 +417,7 @@ void update_usb_status(const bool forceUpdate) {
* The optimize attribute fixes a register Compile
* error for amtel.
*/
void lcd_update() {
void MarlinUI::update() {
static char inbound_buffer[MAX_CURLY_COMMAND];
// First report USB status.
@ -461,7 +461,7 @@ void lcd_update() {
* it and translate into gcode, which then gets injected into
* the command queue where possible.
*/
void lcd_init() {
void MarlinUI::init() {
inbound_count = 0;
LCD_SERIAL.begin(500000);
@ -479,7 +479,7 @@ void lcd_init() {
/**
* Set an alert.
*/
void lcd_setalertstatusPGM(PGM_P message) {
void MarlinUI::setalertstatusPGM(PGM_P message) {
char message_buffer[MAX_CURLY_COMMAND];
sprintf_P(message_buffer, PSTR("{E:%s}"), message);
write_to_lcd(message_buffer);

View File

@ -30,6 +30,7 @@
#include "../../module/motion.h"
#include "../../gcode/queue.h"
#include "../../sd/cardreader.h"
#include "../../libs/buzzer.h"
#if ENABLED(EEPROM_SETTINGS)
#include "../../module/configuration_store.h"
@ -61,10 +62,6 @@ menuPosition screen_history[6];
uint8_t screen_history_depth = 0;
bool screen_changed;
#if LCD_TIMEOUT_TO_STATUS
bool defer_return_to_status;
#endif
// Value Editing
PGM_P editLabel;
void *editValue;
@ -79,9 +76,9 @@ bool no_reentry = false;
//////// Menu Navigation & History /////////
////////////////////////////////////////////
void lcd_return_to_status() { lcd_goto_screen(lcd_status_screen); }
void MarlinUI::return_to_status() { goto_screen(status_screen); }
void lcd_save_previous_screen() {
void MarlinUI::save_previous_screen() {
if (screen_history_depth < COUNT(screen_history)) {
screen_history[screen_history_depth].menu_function = currentScreen;
screen_history[screen_history_depth].encoder_position = encoderPosition;
@ -89,25 +86,18 @@ void lcd_save_previous_screen() {
}
}
void lcd_goto_previous_menu() {
void MarlinUI::goto_previous_screen() {
if (screen_history_depth > 0) {
--screen_history_depth;
lcd_goto_screen(
goto_screen(
screen_history[screen_history_depth].menu_function,
screen_history[screen_history_depth].encoder_position
);
}
else
lcd_return_to_status();
return_to_status();
}
#if LCD_TIMEOUT_TO_STATUS
void lcd_goto_previous_menu_no_defer() {
set_defer_return_to_status(false);
lcd_goto_previous_menu();
}
#endif
////////////////////////////////////////////
/////////// Common Menu Actions ////////////
////////////////////////////////////////////
@ -142,34 +132,33 @@ void menu_item_gcode::action(PGM_P pgcode) { enqueue_and_echo_commands_P(pgcode)
* ...which calls:
* menu_item_int3::action_setting_edit(PSTR(MSG_SPEED), &feedrate_percentage, 10, 999)
*/
void menu_item_invariants::edit(strfunc_t strfunc, loadfunc_t loadfunc) {
ENCODER_DIRECTION_NORMAL();
if ((int32_t)encoderPosition < 0) encoderPosition = 0;
if ((int32_t)encoderPosition > maxEditValue) encoderPosition = maxEditValue;
if (lcdDrawUpdate)
lcd_implementation_drawedit(editLabel, strfunc(encoderPosition + minEditValue));
if (lcd_clicked || (liveEdit && lcdDrawUpdate)) {
if (editValue != NULL) loadfunc(editValue, encoderPosition + minEditValue);
if (callbackFunc && (liveEdit || lcd_clicked)) (*callbackFunc)();
if (lcd_clicked) lcd_goto_previous_menu();
lcd_clicked = false;
void MenuItemBase::edit(strfunc_t strfunc, loadfunc_t loadfunc) {
ui.encoder_direction_normal();
if ((int32_t)ui.encoderPosition < 0) ui.encoderPosition = 0;
if ((int32_t)ui.encoderPosition > maxEditValue) ui.encoderPosition = maxEditValue;
if (ui.should_draw())
draw_edit_screen(editLabel, strfunc(ui.encoderPosition + minEditValue));
if (ui.lcd_clicked || (liveEdit && ui.should_draw())) {
if (editValue != NULL) loadfunc(editValue, ui.encoderPosition + minEditValue);
if (callbackFunc && (liveEdit || ui.lcd_clicked)) (*callbackFunc)();
if (ui.use_click()) ui.goto_previous_screen();
}
}
void menu_item_invariants::init(PGM_P const el, void * const ev, const int32_t minv, const int32_t maxv, const uint32_t ep, const screenFunc_t cs, const screenFunc_t cb, const bool le) {
lcd_save_previous_screen();
lcd_refresh();
void MenuItemBase::init(PGM_P const el, void * const ev, const int32_t minv, const int32_t maxv, const uint32_t ep, const screenFunc_t cs, const screenFunc_t cb, const bool le) {
ui.save_previous_screen();
ui.refresh();
editLabel = el;
editValue = ev;
minEditValue = minv;
maxEditValue = maxv;
encoderPosition = ep;
currentScreen = cs;
ui.encoderPosition = ep;
ui.currentScreen = cs;
callbackFunc = cb;
liveEdit = le;
}
#define DEFINE_MENU_EDIT_ITEM(NAME) template class menu_item_template<NAME ## _item_info>;
#define DEFINE_MENU_EDIT_ITEM(NAME) template class TMenuItem<NAME ## _item_info>;
DEFINE_MENU_EDIT_ITEM(int3);
DEFINE_MENU_EDIT_ITEM(int4);
@ -184,7 +173,7 @@ DEFINE_MENU_EDIT_ITEM(float62);
DEFINE_MENU_EDIT_ITEM(long5);
void menu_item_bool::action_setting_edit(PGM_P pstr, bool *ptr, screenFunc_t callback) {
UNUSED(pstr); *ptr ^= true; lcd_refresh();
UNUSED(pstr); *ptr ^= true; ui.refresh();
if (callback) (*callback)();
}
@ -202,7 +191,7 @@ bool printer_busy() { return planner.movesplanned() || IS_SD_PRINTING(); }
/**
* General function to go directly to a screen
*/
void lcd_goto_screen(screenFunc_t screen, const uint32_t encoder/*=0*/) {
void MarlinUI::goto_screen(screenFunc_t screen, const uint32_t encoder/*=0*/) {
if (currentScreen != screen) {
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
@ -215,10 +204,10 @@ void lcd_goto_screen(screenFunc_t screen, const uint32_t encoder/*=0*/) {
// Going to menu_main from status screen? Remember first click time.
// Going back to status screen within a very short time? Go to Z babystepping.
if (screen == menu_main) {
if (currentScreen == lcd_status_screen)
if (on_status_screen())
doubleclick_expire_ms = millis() + DOUBLECLICK_MAX_INTERVAL;
}
else if (screen == lcd_status_screen && currentScreen == menu_main && PENDING(millis(), doubleclick_expire_ms)) {
else if (screen == status_screen && currentScreen == menu_main && PENDING(millis(), doubleclick_expire_ms)) {
if (printer_busy()) {
screen =
#if ENABLED(BABYSTEP_ZPROBE_OFFSET)
@ -239,25 +228,25 @@ void lcd_goto_screen(screenFunc_t screen, const uint32_t encoder/*=0*/) {
currentScreen = screen;
encoderPosition = encoder;
if (screen == lcd_status_screen) {
set_defer_return_to_status(false);
if (screen == status_screen) {
ui.defer_status_screen(false);
#if ENABLED(AUTO_BED_LEVELING_UBL)
ubl.lcd_map_control = false;
#endif
screen_history_depth = 0;
}
lcd_implementation_clear();
clear_lcd();
// Re-initialize custom characters that may be re-used
#if HAS_CHARACTER_LCD
#if ENABLED(AUTO_BED_LEVELING_UBL)
if (!ubl.lcd_map_control)
#endif
LCD_SET_CHARSET(screen == lcd_status_screen ? CHARSET_INFO : CHARSET_MENU);
LCD_SET_CHARSET(screen == status_screen ? CHARSET_INFO : CHARSET_MENU);
#endif
lcdDrawUpdate = LCDVIEW_CALL_REDRAW_NEXT;
refresh(LCDVIEW_CALL_REDRAW_NEXT);
screen_changed = true;
#if HAS_GRAPHICAL_LCD
drawing_screen = false;
@ -276,24 +265,24 @@ void lcd_goto_screen(screenFunc_t screen, const uint32_t encoder/*=0*/) {
//
static PGM_P sync_message;
void _lcd_synchronize() {
if (lcdDrawUpdate) lcd_implementation_drawmenu_static(LCD_HEIGHT >= 4 ? 1 : 0, sync_message);
void MarlinUI::_synchronize() {
if (should_draw()) draw_menu_item_static(LCD_HEIGHT >= 4 ? 1 : 0, sync_message);
if (no_reentry) return;
// Make this the current handler till all moves are done
no_reentry = true;
const screenFunc_t old_screen = currentScreen;
lcd_goto_screen(_lcd_synchronize);
goto_screen(_synchronize);
planner.synchronize(); // idle() is called until moves complete
no_reentry = false;
lcd_goto_screen(old_screen);
goto_screen(old_screen);
}
// Display the synchronize screen with a custom message
// ** This blocks the command queue! **
void lcd_synchronize(PGM_P const msg/*=NULL*/) {
void MarlinUI::synchronize(PGM_P const msg/*=NULL*/) {
static const char moving[] PROGMEM = MSG_MOVING;
sync_message = msg ? msg : moving;
_lcd_synchronize();
_synchronize();
}
/**
@ -308,16 +297,16 @@ void lcd_synchronize(PGM_P const msg/*=NULL*/) {
*/
int8_t encoderLine, screen_items;
void scroll_screen(const uint8_t limit, const bool is_menu) {
ENCODER_DIRECTION_MENUS();
ui.encoder_direction_menus();
ENCODER_RATE_MULTIPLY(false);
if (encoderPosition > 0x8000) encoderPosition = 0;
if (first_page) {
encoderLine = encoderPosition / (ENCODER_STEPS_PER_MENU_ITEM);
if (ui.encoderPosition > 0x8000) ui.encoderPosition = 0;
if (ui.first_page) {
encoderLine = ui.encoderPosition / (ENCODER_STEPS_PER_MENU_ITEM);
screen_changed = false;
}
if (screen_items > 0 && encoderLine >= screen_items - limit) {
encoderLine = MAX(0, screen_items - limit);
encoderPosition = encoderLine * (ENCODER_STEPS_PER_MENU_ITEM);
ui.encoderPosition = encoderLine * (ENCODER_STEPS_PER_MENU_ITEM);
}
if (is_menu) {
NOMORE(encoderTopLine, encoderLine);
@ -328,12 +317,12 @@ void scroll_screen(const uint8_t limit, const bool is_menu) {
encoderTopLine = encoderLine;
}
void lcd_completion_feedback(const bool good/*=true*/) {
void MarlinUI::completion_feedback(const bool good/*=true*/) {
if (good) {
lcd_buzz(100, 659);
lcd_buzz(100, 698);
BUZZ(100, 659);
BUZZ(100, 698);
}
else lcd_buzz(20, 440);
else BUZZ(20, 440);
}
#if HAS_LINE_TO_Z
@ -348,17 +337,17 @@ void lcd_completion_feedback(const bool good/*=true*/) {
#if ENABLED(BABYSTEP_ZPROBE_OFFSET)
void lcd_babystep_zoffset() {
if (use_click()) { return lcd_goto_previous_menu_no_defer(); }
set_defer_return_to_status(true);
if (ui.use_click()) return ui.goto_previous_screen_no_defer();
ui.defer_status_screen(true);
#if ENABLED(BABYSTEP_HOTEND_Z_OFFSET)
const bool do_probe = (active_extruder == 0);
#else
constexpr bool do_probe = true;
#endif
ENCODER_DIRECTION_NORMAL();
if (encoderPosition) {
const int16_t babystep_increment = (int32_t)encoderPosition * (BABYSTEP_MULTIPLICATOR);
encoderPosition = 0;
ui.encoder_direction_normal();
if (ui.encoderPosition) {
const int16_t babystep_increment = (int32_t)ui.encoderPosition * (BABYSTEP_MULTIPLICATOR);
ui.encoderPosition = 0;
const float diff = planner.steps_to_mm[Z_AXIS] * babystep_increment,
new_probe_offset = zprobe_zoffset + diff,
@ -378,16 +367,16 @@ void lcd_completion_feedback(const bool good/*=true*/) {
else hotend_offset[Z_AXIS][active_extruder] = new_offs;
#endif
lcdDrawUpdate = LCDVIEW_CALL_REDRAW_NEXT;
ui.refresh(LCDVIEW_CALL_REDRAW_NEXT);
}
}
if (lcdDrawUpdate) {
if (ui.should_draw()) {
#if ENABLED(BABYSTEP_HOTEND_Z_OFFSET)
if (!do_probe)
lcd_implementation_drawedit(PSTR(MSG_IDEX_Z_OFFSET), ftostr43sign(hotend_offset[Z_AXIS][active_extruder]));
draw_edit_screen(PSTR(MSG_IDEX_Z_OFFSET), ftostr43sign(hotend_offset[Z_AXIS][active_extruder]));
else
#endif
lcd_implementation_drawedit(PSTR(MSG_ZPROBE_ZOFFSET), ftostr43sign(zprobe_zoffset));
draw_edit_screen(PSTR(MSG_ZPROBE_ZOFFSET), ftostr43sign(zprobe_zoffset));
#if ENABLED(BABYSTEP_ZPROBE_GFX_OVERLAY)
if (do_probe) _lcd_zoffset_overlay_gfx(zprobe_zoffset);
@ -447,14 +436,14 @@ void watch_temp_callback_bed() {
#endif
#if ENABLED(EEPROM_SETTINGS)
void lcd_store_settings() { lcd_completion_feedback(settings.save()); }
void lcd_load_settings() { lcd_completion_feedback(settings.load()); }
void lcd_store_settings() { ui.completion_feedback(settings.save()); }
void lcd_load_settings() { ui.completion_feedback(settings.load()); }
#endif
void _lcd_draw_homing() {
constexpr uint8_t line = (LCD_HEIGHT - 1) / 2;
if (lcdDrawUpdate) lcd_implementation_drawmenu_static(line, PSTR(MSG_LEVEL_BED_HOMING));
lcdDrawUpdate = LCDVIEW_CALL_NO_REDRAW;
if (ui.should_draw()) draw_menu_item_static(line, PSTR(MSG_LEVEL_BED_HOMING));
ui.refresh(LCDVIEW_CALL_NO_REDRAW);
}
#if ENABLED(LCD_BED_LEVELING) || (HAS_LEVELING && DISABLED(SLIM_LCD_MENUS))

View File

@ -31,14 +31,6 @@ constexpr int16_t heater_maxtemp[HOTENDS] = ARRAY_BY_HOTENDS(HEATER_0_MAXTEMP, H
void scroll_screen(const uint8_t limit, const bool is_menu);
bool printer_busy();
void lcd_completion_feedback(const bool good=true);
void lcd_save_previous_screen();
void lcd_goto_previous_menu();
#if LCD_TIMEOUT_TO_STATUS
void lcd_goto_previous_menu_no_defer();
#else
#define lcd_goto_previous_menu_no_defer() lcd_goto_previous_menu()
#endif
////////////////////////////////////////////
////////// Menu Item Numeric Types /////////
@ -67,60 +59,46 @@ DECLARE_MENU_EDIT_TYPE(uint32_t, long5, ftostr5rj, 0.01f);
///////// Menu Item Draw Functions /////////
////////////////////////////////////////////
void draw_menu_item_generic(const bool isSelected, const uint8_t row, PGM_P const pstr, const char pre_char, const char post_char);
void draw_menu_item_static(const uint8_t row, PGM_P const pstr, const bool center=true, const bool invert=false, const char *valstr=NULL);
void draw_edit_screen(PGM_P const pstr, const char* const value=NULL);
#if ENABLED(SDSUPPORT)
class CardReader;
#endif
void lcd_implementation_drawmenu_generic(const bool isSelected, const uint8_t row, const char* pstr, const char pre_char, const char post_char);
void lcd_implementation_drawmenu_static(const uint8_t row, const char* pstr, const bool center=true, const bool invert=false, const char *valstr=NULL);
void lcd_implementation_drawedit(const char* const pstr, const char* const value=NULL);
#if ENABLED(ADVANCED_PAUSE_FEATURE)
void lcd_implementation_hotend_status(const uint8_t row, const uint8_t extruder);
void draw_sd_menu_item(const bool isSelected, const uint8_t row, PGM_P const pstr, CardReader &theCard, const bool isDir);
inline void draw_menu_item_sdfile(const bool sel, const uint8_t row, PGM_P const pstr, CardReader &theCard) { draw_sd_menu_item(sel, row, pstr, theCard, false); }
inline void draw_menu_item_sdfolder(const bool sel, const uint8_t row, PGM_P const pstr, CardReader &theCard) { draw_sd_menu_item(sel, row, pstr, theCard, true); }
#endif
#if HAS_GRAPHICAL_LCD
void _drawmenu_setting_edit_generic(const bool isSelected, const uint8_t row, const char* pstr, const char* const data, const bool pgm);
#define lcd_implementation_drawmenu_back(sel, row, pstr) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
#define lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, data) _drawmenu_setting_edit_generic(sel, row, pstr, data, false)
#define lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, data) _drawmenu_setting_edit_generic(sel, row, pstr, data, true)
#define DRAWMENU_SETTING_EDIT_GENERIC(SRC) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, SRC)
#define DRAW_BOOL_SETTING(sel, row, pstr, data) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
#if ENABLED(SDSUPPORT)
void _drawmenu_sd(const bool isSelected, const uint8_t row, PGM_P const pstr, CardReader &theCard, const bool isDir);
#define lcd_implementation_drawmenu_sdfile(sel, row, pstr, theCard) _drawmenu_sd(sel, row, pstr, theCard, false)
#define lcd_implementation_drawmenu_sddirectory(sel, row, pstr, theCard) _drawmenu_sd(sel, row, pstr, theCard, true)
#endif
#define draw_menu_item_back(sel, row, pstr) draw_menu_item_generic(sel, row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
#define draw_menu_item_setting_edit_generic(sel, row, pstr, data) _drawmenu_setting_edit_generic(sel, row, pstr, data, false)
#define draw_menu_item_setting_edit_generic_P(sel, row, pstr, data) _drawmenu_setting_edit_generic(sel, row, pstr, data, true)
#define DRAWMENU_SETTING_EDIT_GENERIC(SRC) draw_menu_item_setting_edit_generic(sel, row, pstr, SRC)
#define DRAW_BOOL_SETTING(sel, row, pstr, data) draw_menu_item_setting_edit_generic_P(sel, row, pstr, (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
#if ENABLED(BABYSTEP_ZPROBE_GFX_OVERLAY) || ENABLED(MESH_EDIT_GFX_OVERLAY)
void _lcd_zoffset_overlay_gfx(const float zvalue);
#endif
#else
#define lcd_implementation_drawmenu_back(sel, row, pstr) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_UPLEVEL_CHAR, LCD_UPLEVEL_CHAR)
void lcd_implementation_drawmenu_setting_edit_generic(const bool sel, const uint8_t row, const char* pstr, const char pre_char, const char* const data);
void lcd_implementation_drawmenu_setting_edit_generic_P(const bool sel, const uint8_t row, const char* pstr, const char pre_char, const char* const data);
#define DRAWMENU_SETTING_EDIT_GENERIC(SRC) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', SRC)
#define DRAW_BOOL_SETTING(sel, row, pstr, data) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
#if ENABLED(SDSUPPORT)
void lcd_implementation_drawmenu_sdfile(const bool sel, const uint8_t row, PGM_P pstr, CardReader &theCard);
void lcd_implementation_drawmenu_sddirectory(const bool sel, const uint8_t row, PGM_P pstr, CardReader &theCard);
#endif
#endif
#define lcd_implementation_drawmenu_submenu(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', LCD_STR_ARROW_RIGHT[0])
#define lcd_implementation_drawmenu_gcode(sel, row, pstr, gcode) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', ' ')
#define lcd_implementation_drawmenu_function(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', ' ')
#if ENABLED(AUTO_BED_LEVELING_UBL)
void lcd_implementation_ubl_plot(const uint8_t x, const uint8_t inverted_y);
#define draw_menu_item_back(sel, row, pstr) draw_menu_item_generic(sel, row, pstr, LCD_UPLEVEL_CHAR, LCD_UPLEVEL_CHAR)
void draw_menu_item_setting_edit_generic(const bool sel, const uint8_t row, const char* pstr, const char pre_char, const char* const data);
void draw_menu_item_setting_edit_generic_P(const bool sel, const uint8_t row, const char* pstr, const char pre_char, const char* const data);
#define DRAWMENU_SETTING_EDIT_GENERIC(SRC) draw_menu_item_setting_edit_generic(sel, row, pstr, '>', SRC)
#define DRAW_BOOL_SETTING(sel, row, pstr, data) draw_menu_item_setting_edit_generic_P(sel, row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
#endif
#define draw_menu_item_submenu(sel, row, pstr, data) draw_menu_item_generic(sel, row, pstr, '>', LCD_STR_ARROW_RIGHT[0])
#define draw_menu_item_gcode(sel, row, pstr, gcode) draw_menu_item_generic(sel, row, pstr, '>', ' ')
#define draw_menu_item_function(sel, row, pstr, data) draw_menu_item_generic(sel, row, pstr, '>', ' ')
////////////////////////////////////////////
/////// Edit Setting Draw Functions ////////
////////////////////////////////////////////
#define _DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(TYPE, NAME, STRFUNC) \
FORCE_INLINE void lcd_implementation_drawmenu_setting_edit_ ## NAME (const bool sel, const uint8_t row, PGM_P pstr, PGM_P pstr2, TYPE * const data, ...) { \
FORCE_INLINE void draw_menu_item_setting_edit_ ## NAME (const bool sel, const uint8_t row, PGM_P const pstr, PGM_P const pstr2, TYPE * const data, ...) { \
UNUSED(pstr2); \
DRAWMENU_SETTING_EDIT_GENERIC(STRFUNC(*(data))); \
} \
FORCE_INLINE void lcd_implementation_drawmenu_setting_edit_accessor_ ## NAME (const bool sel, const uint8_t row, PGM_P pstr, PGM_P pstr2, TYPE (*pget)(), void (*pset)(TYPE), ...) { \
FORCE_INLINE void draw_menu_item_setting_edit_accessor_ ## NAME (const bool sel, const uint8_t row, PGM_P const pstr, PGM_P const pstr2, TYPE (*pget)(), void (*pset)(TYPE), ...) { \
UNUSED(pstr2); UNUSED(pset); \
DRAWMENU_SETTING_EDIT_GENERIC(STRFUNC(pget())); \
} \
@ -139,8 +117,8 @@ DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float52sign);
DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float62);
DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(long5);
#define lcd_implementation_drawmenu_setting_edit_bool(sel, row, pstr, pstr2, data, ...) DRAW_BOOL_SETTING(sel, row, pstr, data)
#define lcd_implementation_drawmenu_setting_edit_accessor_bool(sel, row, pstr, pstr2, pget, pset) DRAW_BOOL_SETTING(sel, row, pstr, data)
#define draw_menu_item_setting_edit_bool(sel, row, pstr, pstr2, data, ...) DRAW_BOOL_SETTING(sel, row, pstr, data)
#define draw_menu_item_setting_edit_accessor_bool(sel, row, pstr, pstr2, pget, pset) DRAW_BOOL_SETTING(sel, row, pstr, data)
////////////////////////////////////////////
/////////////// Menu Actions ///////////////
@ -148,12 +126,12 @@ DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(long5);
class menu_item_back {
public:
static inline void action() { lcd_goto_previous_menu(); }
static inline void action() { ui.goto_previous_screen(); }
};
class menu_item_submenu {
public:
static inline void action(const screenFunc_t func) { lcd_save_previous_screen(); lcd_goto_screen(func); }
static inline void action(const screenFunc_t func) { ui.save_previous_screen(); ui.goto_screen(func); }
};
class menu_item_gcode {
@ -170,7 +148,7 @@ class menu_item_function {
/////////// Menu Editing Actions ///////////
////////////////////////////////////////////
class menu_item_invariants {
class MenuItemBase {
protected:
typedef char* (*strfunc_t)(const int32_t);
typedef void (*loadfunc_t)(void *, const int32_t);
@ -179,7 +157,7 @@ class menu_item_invariants {
};
template<typename NAME>
class menu_item_template : menu_item_invariants {
class TMenuItem : MenuItemBase {
private:
typedef typename NAME::type_t type_t;
inline static float unscale(const float value) {return value * (1.0f / NAME::scale);}
@ -191,10 +169,10 @@ class menu_item_template : menu_item_invariants {
const int32_t minv = scale(minValue);
init(pstr, ptr, minv, int32_t(scale(maxValue)) - minv, int32_t(scale(*ptr)) - minv, edit, callback, live);
}
static void edit() {menu_item_invariants::edit(to_string, load);}
static void edit() { MenuItemBase::edit(to_string, load); }
};
#define DECLARE_MENU_EDIT_ITEM(NAME) typedef menu_item_template<NAME ## _item_info> menu_item_ ## NAME;
#define DECLARE_MENU_EDIT_ITEM(NAME) typedef TMenuItem<NAME ## _item_info> menu_item_ ## NAME;
DECLARE_MENU_EDIT_ITEM(int3);
DECLARE_MENU_EDIT_ITEM(int4);
@ -210,7 +188,7 @@ DECLARE_MENU_EDIT_ITEM(long5);
class menu_item_bool {
public:
static void action_setting_edit(PGM_P pstr, bool* ptr, const screenFunc_t callbackFunc=NULL);
static void action_setting_edit(PGM_P const pstr, bool* ptr, const screenFunc_t callbackFunc=NULL);
};
////////////////////////////////////////////
@ -256,69 +234,47 @@ class menu_item_bool {
screen_items = _thisItemNr; \
UNUSED(_skipStatic)
/**
* REVERSE_MENU_DIRECTION
*
* To reverse the menu direction we need a general way to reverse
* the direction of the encoder everywhere. So encoderDirection is
* added to allow the encoder to go the other way.
*
* This behavior is limited to scrolling Menus and SD card listings,
* and is disabled in other contexts.
*/
#if ENABLED(REVERSE_MENU_DIRECTION)
extern int8_t encoderDirection;
#define ENCODER_DIRECTION_NORMAL() (encoderDirection = 1)
#define ENCODER_DIRECTION_MENUS() (encoderDirection = -1)
#else
#define ENCODER_DIRECTION_NORMAL() NOOP
#define ENCODER_DIRECTION_MENUS() NOOP
#endif
#if ENABLED(ENCODER_RATE_MULTIPLIER)
extern millis_t lastEncoderMovementMillis;
extern bool encoderRateMultiplierEnabled;
#define ENCODER_RATE_MULTIPLY(F) (encoderRateMultiplierEnabled = F)
#define _MENU_ITEM_MULTIPLIER_CHECK(USE_MULTIPLIER) if (USE_MULTIPLIER) { encoderRateMultiplierEnabled = true; lastEncoderMovementMillis = 0; }
#define ENCODER_RATE_MULTIPLY(F) (ui.encoderRateMultiplierEnabled = F)
#define _MENU_ITEM_MULTIPLIER_CHECK(USE_MULTIPLIER) do{ if (USE_MULTIPLIER) ui.enable_encoder_multiplier(true); }while(0)
//#define ENCODER_RATE_MULTIPLIER_DEBUG // If defined, output the encoder steps per second value
#else // !ENCODER_RATE_MULTIPLIER
#else
#define ENCODER_RATE_MULTIPLY(F) NOOP
#define _MENU_ITEM_MULTIPLIER_CHECK(USE_MULTIPLIER)
#endif // !ENCODER_RATE_MULTIPLIER
#endif
/**
* MENU_ITEM generates draw & handler code for a menu item, potentially calling:
*
* lcd_implementation_drawmenu_<type>[_variant](sel, row, label, arg3...)
* draw_menu_item_<type>[_variant](sel, row, label, arg3...)
* menu_item_<type>::action[_variant](arg3...)
*
* Examples:
* MENU_ITEM(back, MSG_WATCH, 0 [dummy parameter] )
* or
* MENU_BACK(MSG_WATCH)
* lcd_implementation_drawmenu_back(sel, row, PSTR(MSG_WATCH))
* draw_menu_item_back(sel, row, PSTR(MSG_WATCH))
* menu_item_back::action()
*
* MENU_ITEM(function, MSG_PAUSE_PRINT, lcd_sdcard_pause)
* lcd_implementation_drawmenu_function(sel, row, PSTR(MSG_PAUSE_PRINT), lcd_sdcard_pause)
* draw_menu_item_function(sel, row, PSTR(MSG_PAUSE_PRINT), lcd_sdcard_pause)
* menu_item_function::action(lcd_sdcard_pause)
*
* MENU_ITEM_EDIT(int3, MSG_SPEED, &feedrate_percentage, 10, 999)
* lcd_implementation_drawmenu_setting_edit_int3(sel, row, PSTR(MSG_SPEED), PSTR(MSG_SPEED), &feedrate_percentage, 10, 999)
* draw_menu_item_setting_edit_int3(sel, row, PSTR(MSG_SPEED), PSTR(MSG_SPEED), &feedrate_percentage, 10, 999)
* menu_item_int3::action_setting_edit(PSTR(MSG_SPEED), &feedrate_percentage, 10, 999)
*
*/
#define _MENU_ITEM_VARIANT_P(TYPE, VARIANT, USE_MULTIPLIER, PLABEL, ...) do { \
_skipStatic = false; \
if (_menuLineNr == _thisItemNr) { \
if (encoderLine == _thisItemNr && lcd_clicked) { \
lcd_clicked = false; \
if (encoderLine == _thisItemNr && ui.use_click()) { \
_MENU_ITEM_MULTIPLIER_CHECK(USE_MULTIPLIER); \
menu_item_ ## TYPE ::action ## VARIANT(__VA_ARGS__); \
if (screen_changed) return; \
} \
if (lcdDrawUpdate) \
lcd_implementation_drawmenu ## VARIANT ## _ ## TYPE(encoderLine == _thisItemNr, _lcdLineNr, PLABEL, ## __VA_ARGS__); \
if (ui.should_draw()) \
draw_menu_item ## VARIANT ## _ ## TYPE(encoderLine == _thisItemNr, _lcdLineNr, PLABEL, ## __VA_ARGS__); \
} \
++_thisItemNr; \
}while(0)
@ -328,17 +284,17 @@ class menu_item_bool {
#define STATIC_ITEM_P(PLABEL, ...) do{ \
if (_menuLineNr == _thisItemNr) { \
if (_skipStatic && encoderLine <= _thisItemNr) { \
encoderPosition += ENCODER_STEPS_PER_MENU_ITEM; \
ui.encoderPosition += ENCODER_STEPS_PER_MENU_ITEM; \
++encoderLine; \
} \
if (lcdDrawUpdate) \
lcd_implementation_drawmenu_static(_lcdLineNr, PLABEL, ## __VA_ARGS__); \
if (ui.should_draw()) \
draw_menu_item_static(_lcdLineNr, PLABEL, ## __VA_ARGS__); \
} \
++_thisItemNr; \
} while(0)
#define MENU_ITEM_ADDON_START(X) \
if (lcdDrawUpdate && _menuLineNr == _thisItemNr - 1) { \
if (ui.should_draw() && _menuLineNr == _thisItemNr - 1) { \
SETCURSOR(X, _lcdLineNr)
#define MENU_ITEM_ADDON_END() } (0)
@ -347,12 +303,12 @@ class menu_item_bool {
#define MENU_BACK(LABEL) MENU_ITEM(back, LABEL)
#define MENU_ITEM_DUMMY() do { _thisItemNr++; }while(0)
#define MENU_ITEM_P(TYPE, PLABEL, ...) _MENU_ITEM_VARIANT_P(TYPE, , 0, PLABEL, ## __VA_ARGS__)
#define MENU_ITEM(TYPE, LABEL, ...) _MENU_ITEM_VARIANT_P(TYPE, , 0, PSTR(LABEL), ## __VA_ARGS__)
#define MENU_ITEM_EDIT(TYPE, LABEL, ...) _MENU_ITEM_VARIANT_P(TYPE, _setting_edit, 0, PSTR(LABEL), PSTR(LABEL), ## __VA_ARGS__)
#define MENU_ITEM_EDIT_CALLBACK(TYPE, LABEL, ...) _MENU_ITEM_VARIANT_P(TYPE, _setting_edit, 0, PSTR(LABEL), PSTR(LABEL), ## __VA_ARGS__)
#define MENU_MULTIPLIER_ITEM_EDIT(TYPE, LABEL, ...) _MENU_ITEM_VARIANT_P(TYPE, _setting_edit, 1, PSTR(LABEL), PSTR(LABEL), ## __VA_ARGS__)
#define MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(TYPE, LABEL, ...) _MENU_ITEM_VARIANT_P(TYPE, _setting_edit, 1, PSTR(LABEL), PSTR(LABEL), ## __VA_ARGS__)
#define MENU_ITEM_P(TYPE, PLABEL, ...) _MENU_ITEM_VARIANT_P(TYPE, , false, PLABEL, ## __VA_ARGS__)
#define MENU_ITEM(TYPE, LABEL, ...) _MENU_ITEM_VARIANT_P(TYPE, , false, PSTR(LABEL), ## __VA_ARGS__)
#define MENU_ITEM_EDIT(TYPE, LABEL, ...) _MENU_ITEM_VARIANT_P(TYPE, _setting_edit, false, PSTR(LABEL), PSTR(LABEL), ## __VA_ARGS__)
#define MENU_ITEM_EDIT_CALLBACK(TYPE, LABEL, ...) _MENU_ITEM_VARIANT_P(TYPE, _setting_edit, false, PSTR(LABEL), PSTR(LABEL), ## __VA_ARGS__)
#define MENU_MULTIPLIER_ITEM_EDIT(TYPE, LABEL, ...) _MENU_ITEM_VARIANT_P(TYPE, _setting_edit, true, PSTR(LABEL), PSTR(LABEL), ## __VA_ARGS__)
#define MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(TYPE, LABEL, ...) _MENU_ITEM_VARIANT_P(TYPE, _setting_edit, true, PSTR(LABEL), PSTR(LABEL), ## __VA_ARGS__)
////////////////////////////////////////////
/////////////// Menu Screens ///////////////
@ -379,7 +335,6 @@ void menu_move();
////////////////////////////////////////////
void lcd_move_z();
void lcd_synchronize(PGM_P const msg=NULL);
void _lcd_draw_homing();
void watch_temp_callback_E0();
@ -426,3 +381,7 @@ void watch_temp_callback_bed();
void lcd_store_settings();
void lcd_load_settings();
#endif
#if ENABLED(POWER_LOSS_RECOVERY)
void menu_job_recovery();
#endif

View File

@ -52,7 +52,7 @@
//
void _lcd_set_home_offsets() {
enqueue_and_echo_commands_P(PSTR("M428"));
lcd_return_to_status();
ui.return_to_status();
}
#endif
@ -65,9 +65,9 @@
//
static void _lcd_toggle_sd_update() {
const bool new_state = !settings.sd_update_status();
lcd_completion_feedback(settings.set_sd_update_status(new_state));
lcd_return_to_status();
if (new_state) LCD_MESSAGEPGM(MSG_RESET_PRINTER); else lcd_reset_status();
ui.completion_feedback(settings.set_sd_update_status(new_state));
ui.return_to_status();
if (new_state) LCD_MESSAGEPGM(MSG_RESET_PRINTER); else ui.reset_status();
}
#endif
@ -539,8 +539,8 @@ void menu_advanced_temperature() {
#include "../../module/configuration_store.h"
static void lcd_init_eeprom() {
lcd_completion_feedback(settings.init_eeprom());
lcd_goto_previous_menu();
ui.completion_feedback(settings.init_eeprom());
ui.goto_previous_screen();
}
static void lcd_init_eeprom_confirm() {

View File

@ -77,7 +77,7 @@ void menu_level_bed_corners() {
MSG_NEXT_CORNER
#endif
, _lcd_goto_next_corner);
MENU_ITEM(function, MSG_BACK, lcd_goto_previous_menu_no_defer);
MENU_ITEM(function, MSG_BACK, ui.goto_previous_screen_no_defer);
END_MENU();
}
@ -85,18 +85,18 @@ void _lcd_level_bed_corners_homing() {
_lcd_draw_homing();
if (all_axes_homed()) {
bed_corner = 0;
lcd_goto_screen(menu_level_bed_corners);
ui.goto_screen(menu_level_bed_corners);
_lcd_goto_next_corner();
}
}
void _lcd_level_bed_corners() {
set_defer_return_to_status(true);
ui.defer_status_screen(true);
if (!all_axes_known()) {
set_all_unhomed();
enqueue_and_echo_commands_P(PSTR("G28"));
}
lcd_goto_screen(_lcd_level_bed_corners_homing);
ui.goto_screen(_lcd_level_bed_corners_homing);
}
#endif // HAS_LCD_MENU && LEVEL_BED_CORNERS

View File

@ -26,7 +26,7 @@
#include "../../inc/MarlinConfigPre.h"
#if HAS_LCD_MENU && ENABLED(LCD_BED_LEVELING)
#if ENABLED(LCD_BED_LEVELING)
#include "menu.h"
#include "../../module/planner.h"
@ -56,7 +56,7 @@
#endif
);
bool lcd_wait_for_move;
bool MarlinUI::wait_for_bl_move; // = false
//
// Bed leveling is done. Wait for G29 to complete.
@ -70,17 +70,17 @@
// ** This blocks the command queue! **
//
void _lcd_level_bed_done() {
if (!lcd_wait_for_move) {
if (!ui.wait_for_bl_move) {
#if MANUAL_PROBE_HEIGHT > 0 && DISABLED(MESH_BED_LEVELING)
// Display "Done" screen and wait for moves to complete
line_to_z(MANUAL_PROBE_HEIGHT);
lcd_synchronize(PSTR(MSG_LEVEL_BED_DONE));
ui.synchronize(PSTR(MSG_LEVEL_BED_DONE));
#endif
lcd_goto_previous_menu_no_defer();
lcd_completion_feedback();
ui.goto_previous_screen_no_defer();
ui.completion_feedback();
}
if (lcdDrawUpdate) lcd_implementation_drawmenu_static(LCD_HEIGHT >= 4 ? 1 : 0, PSTR(MSG_LEVEL_BED_DONE));
lcdDrawUpdate = LCDVIEW_CALL_REDRAW_NEXT;
if (ui.should_draw()) draw_menu_item_static(LCD_HEIGHT >= 4 ? 1 : 0, PSTR(MSG_LEVEL_BED_DONE));
ui.refresh(LCDVIEW_CALL_REDRAW_NEXT);
}
void _lcd_level_goto_next_point();
@ -89,9 +89,9 @@
// Step 7: Get the Z coordinate, click goes to the next point or exits
//
void _lcd_level_bed_get_z() {
ENCODER_DIRECTION_NORMAL();
ui.encoder_direction_normal();
if (use_click()) {
if (ui.use_click()) {
//
// Save the current Z position and move
@ -102,8 +102,8 @@
//
// The last G29 records the point and enables bed leveling
//
lcd_wait_for_move = true;
lcd_goto_screen(_lcd_level_bed_done);
ui.wait_for_bl_move = true;
ui.goto_screen(_lcd_level_bed_done);
#if ENABLED(MESH_BED_LEVELING)
enqueue_and_echo_commands_P(PSTR("G29 S2"));
#elif ENABLED(PROBE_MANUALLY)
@ -119,19 +119,19 @@
//
// Encoder knob or keypad buttons adjust the Z position
//
if (encoderPosition) {
const float z = current_position[Z_AXIS] + float((int32_t)encoderPosition) * (MESH_EDIT_Z_STEP);
if (ui.encoderPosition) {
const float z = current_position[Z_AXIS] + float((int32_t)ui.encoderPosition) * (MESH_EDIT_Z_STEP);
line_to_z(constrain(z, -(LCD_PROBE_Z_RANGE) * 0.5f, (LCD_PROBE_Z_RANGE) * 0.5f));
lcdDrawUpdate = LCDVIEW_CALL_REDRAW_NEXT;
encoderPosition = 0;
ui.refresh(LCDVIEW_CALL_REDRAW_NEXT);
ui.encoderPosition = 0;
}
//
// Draw on first display, then only on Z change
//
if (lcdDrawUpdate) {
if (ui.should_draw()) {
const float v = current_position[Z_AXIS];
lcd_implementation_drawedit(PSTR(MSG_MOVE_Z), ftostr43sign(v + (v < 0 ? -0.0001f : 0.0001f), '+'));
draw_edit_screen(PSTR(MSG_MOVE_Z), ftostr43sign(v + (v < 0 ? -0.0001f : 0.0001f), '+'));
}
}
@ -139,23 +139,23 @@
// Step 6: Display "Next point: 1 / 9" while waiting for move to finish
//
void _lcd_level_bed_moving() {
if (lcdDrawUpdate) {
if (ui.should_draw()) {
char msg[10];
sprintf_P(msg, PSTR("%i / %u"), (int)(manual_probe_index + 1), total_probe_points);
lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_NEXT_POINT), msg);
draw_edit_screen(PSTR(MSG_LEVEL_BED_NEXT_POINT), msg);
}
lcdDrawUpdate = LCDVIEW_CALL_NO_REDRAW;
if (!lcd_wait_for_move) lcd_goto_screen(_lcd_level_bed_get_z);
ui.refresh(LCDVIEW_CALL_NO_REDRAW);
if (!ui.wait_for_bl_move) ui.goto_screen(_lcd_level_bed_get_z);
}
//
// Step 5: Initiate a move to the next point
//
void _lcd_level_goto_next_point() {
lcd_goto_screen(_lcd_level_bed_moving);
ui.goto_screen(_lcd_level_bed_moving);
// G29 Records Z, moves, and signals when it pauses
lcd_wait_for_move = true;
ui.wait_for_bl_move = true;
#if ENABLED(MESH_BED_LEVELING)
enqueue_and_echo_commands_P(manual_probe_index ? PSTR("G29 S2") : PSTR("G29 S1"));
#elif ENABLED(PROBE_MANUALLY)
@ -168,8 +168,8 @@
// Move to the first probe position
//
void _lcd_level_bed_homing_done() {
if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_WAITING));
if (use_click()) {
if (ui.should_draw()) draw_edit_screen(PSTR(MSG_LEVEL_BED_WAITING));
if (ui.use_click()) {
manual_probe_index = 0;
_lcd_level_goto_next_point();
}
@ -180,7 +180,7 @@
//
void _lcd_level_bed_homing() {
_lcd_draw_homing();
if (all_axes_homed()) lcd_goto_screen(_lcd_level_bed_homing_done);
if (all_axes_homed()) ui.goto_screen(_lcd_level_bed_homing_done);
}
#if ENABLED(PROBE_MANUALLY)
@ -191,9 +191,9 @@
// Step 2: Continue Bed Leveling...
//
void _lcd_level_bed_continue() {
set_defer_return_to_status(true);
ui.defer_status_screen(true);
set_all_unhomed();
lcd_goto_screen(_lcd_level_bed_homing);
ui.goto_screen(_lcd_level_bed_homing);
enqueue_and_echo_commands_P(PSTR("G28"));
}
@ -292,4 +292,4 @@ void menu_bed_leveling() {
END_MENU();
}
#endif // HAS_LCD_MENU && LCD_BED_LEVELING
#endif // LCD_BED_LEVELING

View File

@ -41,35 +41,31 @@
void menu_advanced_settings();
void menu_delta_calibrate();
#if HAS_LCD_CONTRAST
void lcd_callback_set_contrast() { set_lcd_contrast(lcd_contrast); }
#endif
static void lcd_factory_settings() {
settings.reset();
lcd_completion_feedback();
ui.completion_feedback();
}
#if ENABLED(LCD_PROGRESS_BAR_TEST)
static void progress_bar_test() {
static int8_t bar_percent = 0;
if (use_click()) {
lcd_goto_previous_menu();
if (ui.use_click()) {
ui.goto_previous_screen();
LCD_SET_CHARSET(CHARSET_MENU);
return;
}
bar_percent += (int8_t)encoderPosition;
bar_percent += (int8_t)ui.encoderPosition;
bar_percent = constrain(bar_percent, 0, 100);
encoderPosition = 0;
lcd_implementation_drawmenu_static(0, PSTR(MSG_PROGRESS_BAR_TEST), true, true);
ui.encoderPosition = 0;
draw_menu_item_static(0, PSTR(MSG_PROGRESS_BAR_TEST), true, true);
lcd_moveto((LCD_WIDTH) / 2 - 2, LCD_HEIGHT - 2);
lcd_put_u8str(int(bar_percent)); lcd_put_wchar('%');
lcd_moveto(0, LCD_HEIGHT - 1); lcd_draw_progress_bar(bar_percent);
}
void _progress_bar_test() {
lcd_goto_screen(progress_bar_test);
ui.goto_screen(progress_bar_test);
LCD_SET_CHARSET(CHARSET_INFO);
}
@ -271,12 +267,12 @@ static void lcd_factory_settings() {
#endif
START_MENU();
MENU_BACK(MSG_CONFIGURATION);
MENU_ITEM_EDIT(int8, MSG_FAN_SPEED, &lcd_preheat_fan_speed[material], 0, 255);
MENU_ITEM_EDIT(int8, MSG_FAN_SPEED, &ui.preheat_fan_speed[material], 0, 255);
#if HAS_TEMP_HOTEND
MENU_ITEM_EDIT(int3, MSG_NOZZLE, &lcd_preheat_hotend_temp[material], MINTEMP_ALL, MAXTEMP_ALL - 15);
MENU_ITEM_EDIT(int3, MSG_NOZZLE, &ui.preheat_hotend_temp[material], MINTEMP_ALL, MAXTEMP_ALL - 15);
#endif
#if HAS_HEATED_BED
MENU_ITEM_EDIT(int3, MSG_BED, &lcd_preheat_bed_temp[material], BED_MINTEMP, BED_MAXTEMP - 15);
MENU_ITEM_EDIT(int3, MSG_BED, &ui.preheat_bed_temp[material], BED_MINTEMP, BED_MAXTEMP - 15);
#endif
#if ENABLED(EEPROM_SETTINGS)
MENU_ITEM(function, MSG_STORE_EEPROM, lcd_store_settings);
@ -338,7 +334,7 @@ void menu_configuration() {
#endif
#if HAS_LCD_CONTRAST
MENU_ITEM_EDIT_CALLBACK(int3, MSG_CONTRAST, &lcd_contrast, LCD_CONTRAST_MIN, LCD_CONTRAST_MAX, lcd_callback_set_contrast, true);
MENU_ITEM_EDIT_CALLBACK(int3, MSG_CONTRAST, &ui.contrast, LCD_CONTRAST_MIN, LCD_CONTRAST_MAX, ui.refresh_contrast, true);
#endif
#if ENABLED(FWRETRACT)
MENU_ITEM(submenu, MSG_RETRACT, menu_config_retract);

View File

@ -40,10 +40,10 @@
void _lcd_user_gcode(PGM_P const cmd) {
enqueue_and_echo_commands_P(cmd);
#if ENABLED(USER_SCRIPT_AUDIBLE_FEEDBACK)
lcd_completion_feedback();
ui.completion_feedback();
#endif
#if ENABLED(USER_SCRIPT_RETURN)
lcd_return_to_status();
ui.return_to_status();
#endif
}

View File

@ -38,9 +38,9 @@
void _man_probe_pt(const float &rx, const float &ry) {
do_blocking_move_to(rx, ry, Z_CLEARANCE_BETWEEN_PROBES);
lcd_synchronize();
ui.synchronize();
move_menu_scale = MAX(PROBE_MANUALLY_STEP, MIN_STEPS_PER_SEGMENT / float(DEFAULT_XYZ_STEPS_PER_UNIT));
lcd_goto_screen(lcd_move_z);
ui.goto_screen(lcd_move_z);
}
#if ENABLED(DELTA_AUTO_CALIBRATION)
@ -50,11 +50,11 @@ void _man_probe_pt(const float &rx, const float &ry) {
float lcd_probe_pt(const float &rx, const float &ry) {
_man_probe_pt(rx, ry);
KEEPALIVE_STATE(PAUSED_FOR_USER);
set_defer_return_to_status(true);
ui.defer_status_screen(true);
wait_for_user = true;
while (wait_for_user) idle();
KEEPALIVE_STATE(IN_HANDLER);
lcd_goto_previous_menu_no_defer();
ui.goto_previous_screen_no_defer();
return current_position[Z_AXIS];
}
@ -66,12 +66,12 @@ void _man_probe_pt(const float &rx, const float &ry) {
void _lcd_calibrate_homing() {
_lcd_draw_homing();
if (all_axes_homed()) lcd_goto_previous_menu();
if (all_axes_homed()) ui.goto_previous_screen();
}
void _lcd_delta_calibrate_home() {
enqueue_and_echo_commands_P(PSTR("G28"));
lcd_goto_screen(_lcd_calibrate_homing);
ui.goto_screen(_lcd_calibrate_homing);
}
void _goto_tower_x() { _man_probe_pt(cos(RADIANS(210)) * delta_calibration_radius, sin(RADIANS(210)) * delta_calibration_radius); }

View File

@ -323,15 +323,15 @@ static PGM_P advanced_pause_header() {
// Portions from STATIC_ITEM...
#define HOTEND_STATUS_ITEM() do { \
if (_menuLineNr == _thisItemNr) { \
if (lcdDrawUpdate) { \
lcd_implementation_drawmenu_static(_lcdLineNr, PSTR(MSG_FILAMENT_CHANGE_NOZZLE), false, true); \
lcd_implementation_hotend_status(_lcdLineNr, hotend_status_extruder); \
if (ui.should_draw()) { \
draw_menu_item_static(_lcdLineNr, PSTR(MSG_FILAMENT_CHANGE_NOZZLE), false, true); \
ui.draw_hotend_status(_lcdLineNr, hotend_status_extruder); \
} \
if (_skipStatic && encoderLine <= _thisItemNr) { \
encoderPosition += ENCODER_STEPS_PER_MENU_ITEM; \
ui.encoderPosition += ENCODER_STEPS_PER_MENU_ITEM; \
++encoderLine; \
} \
lcdDrawUpdate = LCDVIEW_CALL_REDRAW_NEXT; \
ui.refresh(LCDVIEW_CALL_REDRAW_NEXT); \
} \
++_thisItemNr; \
}while(0)
@ -507,11 +507,11 @@ void lcd_advanced_pause_show_message(
hotend_status_extruder = extruder;
const screenFunc_t next_screen = ap_message_screen(message);
if (next_screen) {
set_defer_return_to_status(true);
lcd_goto_screen(next_screen);
ui.defer_status_screen(true);
ui.goto_screen(next_screen);
}
else
lcd_return_to_status();
ui.return_to_status();
}
#endif // HAS_LCD_MENU && ADVANCED_PAUSE_FEATURE

View File

@ -47,7 +47,7 @@
// About Printer > Printer Stats
//
void menu_info_stats() {
if (use_click()) { return lcd_goto_previous_menu(); }
if (ui.use_click()) return ui.goto_previous_screen();
char buffer[21];
printStatistics stats = print_job_timer.getStats();
@ -80,7 +80,7 @@
// About Printer > Thermistors
//
void menu_info_thermistors() {
if (use_click()) { return lcd_goto_previous_menu(); }
if (ui.use_click()) return ui.goto_previous_screen();
START_SCREEN();
#define THERMISTOR_ID TEMP_SENSOR_0
#include "../thermistornames.h"
@ -139,7 +139,7 @@ void menu_info_thermistors() {
// About Printer > Board Info
//
void menu_info_board() {
if (use_click()) { return lcd_goto_previous_menu(); }
if (ui.use_click()) return ui.goto_previous_screen();
START_SCREEN();
STATIC_ITEM(BOARD_NAME, true, true); // MyPrinterController
STATIC_ITEM(MSG_INFO_BAUDRATE ": " STRINGIFY(BAUDRATE), true); // Baud: 250000
@ -158,7 +158,7 @@ void menu_info_board() {
// About Printer > Printer Info
//
void menu_info_printer() {
if (use_click()) { return lcd_goto_previous_menu(); }
if (ui.use_click()) return ui.goto_previous_screen();
START_SCREEN();
STATIC_ITEM(MSG_MARLIN, true, true); // Marlin
STATIC_ITEM(SHORT_BUILD_VERSION, true); // x.x.x-Branch

View File

@ -37,7 +37,7 @@ static void lcd_power_loss_recovery_resume() {
char cmd[20];
// Return to status now
lcd_return_to_status();
ui.return_to_status();
// Turn leveling off and home
enqueue_and_echo_commands_P(PSTR("M420 S0\nG28 R0"
@ -91,11 +91,11 @@ static void lcd_power_loss_recovery_resume() {
static void lcd_power_loss_recovery_cancel() {
card.removeJobRecoveryFile();
card.autostart_index = 0;
lcd_return_to_status();
ui.return_to_status();
}
void menu_job_recovery() {
set_defer_return_to_status(true);
ui.defer_status_screen(true);
START_MENU();
STATIC_ITEM(MSG_POWER_LOSS_RECOVERY);
MENU_ITEM(function, MSG_RESUME_PRINT, lcd_power_loss_recovery_resume);

View File

@ -43,7 +43,7 @@
#if ENABLED(PARK_HEAD_ON_PAUSE)
enqueue_and_echo_commands_P(PSTR("M125"));
#endif
lcd_reset_status();
ui.reset_status();
}
void lcd_sdcard_resume() {
@ -53,14 +53,14 @@
card.startFileprint();
print_job_timer.start();
#endif
lcd_reset_status();
ui.reset_status();
}
void lcd_sdcard_stop() {
wait_for_heatup = wait_for_user = false;
card.abort_sd_printing = true;
lcd_setstatusPGM(PSTR(MSG_PRINT_ABORTED), -1);
lcd_return_to_status();
ui.setstatusPGM(PSTR(MSG_PRINT_ABORTED), -1);
ui.return_to_status();
}
#if ENABLED(MENU_ADDAUTOSTART)

View File

@ -46,9 +46,6 @@
extern millis_t manual_move_start_time;
extern int8_t manual_move_axis;
#if ENABLED(DUAL_X_CARRIAGE) || E_MANUAL > 1
extern int8_t manual_move_e_index;
#endif
#if ENABLED(MANUAL_E_MOVES_RELATIVE)
float manual_move_e_origin = 0;
#endif
@ -57,18 +54,15 @@ extern int8_t manual_move_axis;
#endif
//
// Tell lcd_update() to start a move to current_position" after a short delay.
// Tell ui.update() to start a move to current_position" after a short delay.
//
inline void manual_move_to_current(AxisEnum axis
#if E_MANUAL > 1
, const int8_t eindex=-1
#endif
) {
#if ENABLED(DUAL_X_CARRIAGE) || E_MANUAL > 1
#if E_MANUAL > 1
if (axis == E_AXIS)
#endif
manual_move_e_index = eindex >= 0 ? eindex : active_extruder;
#if E_MANUAL > 1
if (axis == E_AXIS) ui.manual_move_e_index = eindex >= 0 ? eindex : active_extruder;
#endif
manual_move_start_time = millis() + (move_menu_scale < 0.99f ? 0UL : 250UL); // delay for bigger moves
manual_move_axis = (int8_t)axis;
@ -79,9 +73,9 @@ inline void manual_move_to_current(AxisEnum axis
//
static void _lcd_move_xyz(PGM_P name, AxisEnum axis) {
if (use_click()) { return lcd_goto_previous_menu_no_defer(); }
ENCODER_DIRECTION_NORMAL();
if (encoderPosition && !processing_manual_move) {
if (ui.use_click()) return ui.goto_previous_screen_no_defer();
ui.encoder_direction_normal();
if (ui.encoderPosition && !ui.processing_manual_move) {
// Start with no limits to movement
float min = current_position[axis] - 1000,
@ -127,32 +121,32 @@ static void _lcd_move_xyz(PGM_P name, AxisEnum axis) {
#endif
// Get the new position
const float diff = float((int32_t)encoderPosition) * move_menu_scale;
const float diff = float((int32_t)ui.encoderPosition) * move_menu_scale;
#if IS_KINEMATIC
manual_move_offset += diff;
if ((int32_t)encoderPosition < 0)
if ((int32_t)ui.encoderPosition < 0)
NOLESS(manual_move_offset, min - current_position[axis]);
else
NOMORE(manual_move_offset, max - current_position[axis]);
#else
current_position[axis] += diff;
if ((int32_t)encoderPosition < 0)
if ((int32_t)ui.encoderPosition < 0)
NOLESS(current_position[axis], min);
else
NOMORE(current_position[axis], max);
#endif
manual_move_to_current(axis);
lcdDrawUpdate = LCDVIEW_REDRAW_NOW;
ui.refresh(LCDVIEW_REDRAW_NOW);
}
encoderPosition = 0;
if (lcdDrawUpdate) {
const float pos = NATIVE_TO_LOGICAL(processing_manual_move ? destination[axis] : current_position[axis]
ui.encoderPosition = 0;
if (ui.should_draw()) {
const float pos = NATIVE_TO_LOGICAL(ui.processing_manual_move ? destination[axis] : current_position[axis]
#if IS_KINEMATIC
+ manual_move_offset
#endif
, axis);
lcd_implementation_drawedit(name, move_menu_scale >= 0.1f ? ftostr41sign(pos) : ftostr43sign(pos));
draw_edit_screen(name, move_menu_scale >= 0.1f ? ftostr41sign(pos) : ftostr43sign(pos));
}
}
void lcd_move_x() { _lcd_move_xyz(PSTR(MSG_MOVE_X), X_AXIS); }
@ -163,11 +157,11 @@ static void _lcd_move_e(
const int8_t eindex=-1
#endif
) {
if (use_click()) { return lcd_goto_previous_menu_no_defer(); }
ENCODER_DIRECTION_NORMAL();
if (encoderPosition) {
if (!processing_manual_move) {
const float diff = float((int32_t)encoderPosition) * move_menu_scale;
if (ui.use_click()) return ui.goto_previous_screen_no_defer();
ui.encoder_direction_normal();
if (ui.encoderPosition) {
if (!ui.processing_manual_move) {
const float diff = float((int32_t)ui.encoderPosition) * move_menu_scale;
#if IS_KINEMATIC
manual_move_offset += diff;
#else
@ -178,11 +172,11 @@ static void _lcd_move_e(
, eindex
#endif
);
lcdDrawUpdate = LCDVIEW_REDRAW_NOW;
ui.refresh(LCDVIEW_REDRAW_NOW);
}
encoderPosition = 0;
ui.encoderPosition = 0;
}
if (lcdDrawUpdate) {
if (ui.should_draw()) {
PGM_P pos_label;
#if E_MANUAL == 1
pos_label = PSTR(MSG_MOVE_E);
@ -205,7 +199,7 @@ static void _lcd_move_e(
}
#endif // E_MANUAL > 1
lcd_implementation_drawedit(pos_label, ftostr41sign(current_position[E_AXIS]
draw_edit_screen(pos_label, ftostr41sign(current_position[E_AXIS]
#if IS_KINEMATIC
+ manual_move_offset
#endif
@ -241,9 +235,9 @@ inline void lcd_move_e() { _lcd_move_e(); }
screenFunc_t _manual_move_func_ptr;
void _goto_manual_move(const float scale) {
set_defer_return_to_status(true);
ui.defer_status_screen(true);
move_menu_scale = scale;
lcd_goto_screen(_manual_move_func_ptr);
ui.goto_screen(_manual_move_func_ptr);
}
void menu_move_10mm() { _goto_manual_move(10); }
void menu_move_1mm() { _goto_manual_move( 1); }
@ -305,7 +299,7 @@ void lcd_move_get_e_amount() { _menu_move_distance(E_AXIS, lcd_move_e, -1); }
#if ENABLED(DELTA)
void lcd_lower_z_to_clip_height() {
line_to_z(delta_clip_start_height);
lcd_synchronize();
ui.synchronize();
}
#endif

View File

@ -39,35 +39,36 @@
#endif
void lcd_sd_updir() {
encoderPosition = card.updir() ? ENCODER_STEPS_PER_MENU_ITEM : 0;
ui.encoderPosition = card.updir() ? ENCODER_STEPS_PER_MENU_ITEM : 0;
encoderTopLine = 0;
screen_changed = true;
lcd_refresh();
ui.refresh();
}
#if ENABLED(SD_REPRINT_LAST_SELECTED_FILE)
uint32_t last_sdfile_encoderPosition = 0xFFFF;
void lcd_reselect_last_file() {
void MarlinUI::reselect_last_file() {
if (last_sdfile_encoderPosition == 0xFFFF) return;
#if HAS_GRAPHICAL_LCD
// Some of this is a hack to force the screen update to work.
// TODO: Fix the real issue that causes this!
lcdDrawUpdate = LCDVIEW_CALL_REDRAW_NEXT;
lcd_synchronize();
safe_delay(50);
lcd_synchronize();
lcdDrawUpdate = LCDVIEW_CALL_REDRAW_NEXT;
drawing_screen = screen_changed = true;
#endif
//#if HAS_GRAPHICAL_LCD
// // This is a hack to force a screen update.
// ui.refresh(LCDVIEW_CALL_REDRAW_NEXT);
// ui.synchronize();
// safe_delay(50);
// ui.synchronize();
// ui.refresh(LCDVIEW_CALL_REDRAW_NEXT);
// ui.drawing_screen = screen_changed = true;
//#endif
lcd_goto_screen(menu_sdcard, last_sdfile_encoderPosition);
set_defer_return_to_status(true);
goto_screen(menu_sdcard, last_sdfile_encoderPosition);
last_sdfile_encoderPosition = 0xFFFF;
#if HAS_GRAPHICAL_LCD
lcd_update();
#endif
defer_status_screen(true);
//#if HAS_GRAPHICAL_LCD
// update();
//#endif
}
#endif
@ -75,30 +76,30 @@ class menu_item_sdfile {
public:
static void action(CardReader &theCard) {
#if ENABLED(SD_REPRINT_LAST_SELECTED_FILE)
last_sdfile_encoderPosition = encoderPosition; // Save which file was selected for later use
last_sdfile_encoderPosition = ui.encoderPosition; // Save which file was selected for later use
#endif
card.openAndPrintFile(theCard.filename);
lcd_return_to_status();
lcd_reset_status();
ui.return_to_status();
ui.reset_status();
}
};
class menu_item_sddirectory {
class menu_item_sdfolder {
public:
static void action(CardReader &theCard) {
card.chdir(theCard.filename);
encoderTopLine = 0;
encoderPosition = 2 * ENCODER_STEPS_PER_MENU_ITEM;
ui.encoderPosition = 2 * ENCODER_STEPS_PER_MENU_ITEM;
screen_changed = true;
#if HAS_GRAPHICAL_LCD
drawing_screen = false;
ui.drawing_screen = false;
#endif
lcd_refresh();
ui.refresh();
}
};
void menu_sdcard() {
ENCODER_DIRECTION_MENUS();
ui.encoder_direction_menus();
const uint16_t fileCnt = card.get_num_Files();
@ -125,7 +126,7 @@ void menu_sdcard() {
card.getfilename_sorted(nr);
if (card.filenameIsDir)
MENU_ITEM(sddirectory, MSG_CARD_MENU, card);
MENU_ITEM(sdfolder, MSG_CARD_MENU, card);
else
MENU_ITEM(sdfile, MSG_CARD_MENU, card);
}

View File

@ -36,8 +36,8 @@
#endif
// Initialized by settings.load()
int16_t lcd_preheat_hotend_temp[2], lcd_preheat_bed_temp[2];
uint8_t lcd_preheat_fan_speed[2];
int16_t MarlinUI::preheat_hotend_temp[2], MarlinUI::preheat_bed_temp[2];
uint8_t MarlinUI::preheat_fan_speed[2];
//
// "Temperature" submenu items
@ -59,44 +59,44 @@ void _lcd_preheat(const int16_t endnum, const int16_t temph, const int16_t tempb
#else
UNUSED(fan);
#endif
lcd_return_to_status();
ui.return_to_status();
}
#if HOTENDS > 1
void lcd_preheat_m1_e1_only() { _lcd_preheat(1, lcd_preheat_hotend_temp[0], -1, lcd_preheat_fan_speed[0]); }
void lcd_preheat_m2_e1_only() { _lcd_preheat(1, lcd_preheat_hotend_temp[1], -1, lcd_preheat_fan_speed[1]); }
void lcd_preheat_m1_e1_only() { _lcd_preheat(1, ui.preheat_hotend_temp[0], -1, ui.preheat_fan_speed[0]); }
void lcd_preheat_m2_e1_only() { _lcd_preheat(1, ui.preheat_hotend_temp[1], -1, ui.preheat_fan_speed[1]); }
#if HAS_HEATED_BED
void lcd_preheat_m1_e1() { _lcd_preheat(1, lcd_preheat_hotend_temp[0], lcd_preheat_bed_temp[0], lcd_preheat_fan_speed[0]); }
void lcd_preheat_m2_e1() { _lcd_preheat(1, lcd_preheat_hotend_temp[1], lcd_preheat_bed_temp[1], lcd_preheat_fan_speed[1]); }
void lcd_preheat_m1_e1() { _lcd_preheat(1, ui.preheat_hotend_temp[0], ui.preheat_bed_temp[0], ui.preheat_fan_speed[0]); }
void lcd_preheat_m2_e1() { _lcd_preheat(1, ui.preheat_hotend_temp[1], ui.preheat_bed_temp[1], ui.preheat_fan_speed[1]); }
#endif
#if HOTENDS > 2
void lcd_preheat_m1_e2_only() { _lcd_preheat(2, lcd_preheat_hotend_temp[0], -1, lcd_preheat_fan_speed[0]); }
void lcd_preheat_m2_e2_only() { _lcd_preheat(2, lcd_preheat_hotend_temp[1], -1, lcd_preheat_fan_speed[1]); }
void lcd_preheat_m1_e2_only() { _lcd_preheat(2, ui.preheat_hotend_temp[0], -1, ui.preheat_fan_speed[0]); }
void lcd_preheat_m2_e2_only() { _lcd_preheat(2, ui.preheat_hotend_temp[1], -1, ui.preheat_fan_speed[1]); }
#if HAS_HEATED_BED
void lcd_preheat_m1_e2() { _lcd_preheat(2, lcd_preheat_hotend_temp[0], lcd_preheat_bed_temp[0], lcd_preheat_fan_speed[0]); }
void lcd_preheat_m2_e2() { _lcd_preheat(2, lcd_preheat_hotend_temp[1], lcd_preheat_bed_temp[1], lcd_preheat_fan_speed[1]); }
void lcd_preheat_m1_e2() { _lcd_preheat(2, ui.preheat_hotend_temp[0], ui.preheat_bed_temp[0], ui.preheat_fan_speed[0]); }
void lcd_preheat_m2_e2() { _lcd_preheat(2, ui.preheat_hotend_temp[1], ui.preheat_bed_temp[1], ui.preheat_fan_speed[1]); }
#endif
#if HOTENDS > 3
void lcd_preheat_m1_e3_only() { _lcd_preheat(3, lcd_preheat_hotend_temp[0], -1, lcd_preheat_fan_speed[0]); }
void lcd_preheat_m2_e3_only() { _lcd_preheat(3, lcd_preheat_hotend_temp[1], -1, lcd_preheat_fan_speed[1]); }
void lcd_preheat_m1_e3_only() { _lcd_preheat(3, ui.preheat_hotend_temp[0], -1, ui.preheat_fan_speed[0]); }
void lcd_preheat_m2_e3_only() { _lcd_preheat(3, ui.preheat_hotend_temp[1], -1, ui.preheat_fan_speed[1]); }
#if HAS_HEATED_BED
void lcd_preheat_m1_e3() { _lcd_preheat(3, lcd_preheat_hotend_temp[0], lcd_preheat_bed_temp[0], lcd_preheat_fan_speed[0]); }
void lcd_preheat_m2_e3() { _lcd_preheat(3, lcd_preheat_hotend_temp[1], lcd_preheat_bed_temp[1], lcd_preheat_fan_speed[1]); }
void lcd_preheat_m1_e3() { _lcd_preheat(3, ui.preheat_hotend_temp[0], ui.preheat_bed_temp[0], ui.preheat_fan_speed[0]); }
void lcd_preheat_m2_e3() { _lcd_preheat(3, ui.preheat_hotend_temp[1], ui.preheat_bed_temp[1], ui.preheat_fan_speed[1]); }
#endif
#if HOTENDS > 4
void lcd_preheat_m1_e4_only() { _lcd_preheat(4, lcd_preheat_hotend_temp[0], -1, lcd_preheat_fan_speed[0]); }
void lcd_preheat_m2_e4_only() { _lcd_preheat(4, lcd_preheat_hotend_temp[1], -1, lcd_preheat_fan_speed[1]); }
void lcd_preheat_m1_e4_only() { _lcd_preheat(4, ui.preheat_hotend_temp[0], -1, ui.preheat_fan_speed[0]); }
void lcd_preheat_m2_e4_only() { _lcd_preheat(4, ui.preheat_hotend_temp[1], -1, ui.preheat_fan_speed[1]); }
#if HAS_HEATED_BED
void lcd_preheat_m1_e4() { _lcd_preheat(4, lcd_preheat_hotend_temp[0], lcd_preheat_bed_temp[0], lcd_preheat_fan_speed[0]); }
void lcd_preheat_m2_e4() { _lcd_preheat(4, lcd_preheat_hotend_temp[1], lcd_preheat_bed_temp[1], lcd_preheat_fan_speed[1]); }
void lcd_preheat_m1_e4() { _lcd_preheat(4, ui.preheat_hotend_temp[0], ui.preheat_bed_temp[0], ui.preheat_fan_speed[0]); }
void lcd_preheat_m2_e4() { _lcd_preheat(4, ui.preheat_hotend_temp[1], ui.preheat_bed_temp[1], ui.preheat_fan_speed[1]); }
#endif
#if HOTENDS > 5
void lcd_preheat_m1_e5_only() { _lcd_preheat(5, lcd_preheat_hotend_temp[0], -1, lcd_preheat_fan_speed[0]); }
void lcd_preheat_m2_e5_only() { _lcd_preheat(5, lcd_preheat_hotend_temp[1], -1, lcd_preheat_fan_speed[1]); }
void lcd_preheat_m1_e5_only() { _lcd_preheat(5, ui.preheat_hotend_temp[0], -1, ui.preheat_fan_speed[0]); }
void lcd_preheat_m2_e5_only() { _lcd_preheat(5, ui.preheat_hotend_temp[1], -1, ui.preheat_fan_speed[1]); }
#if HAS_HEATED_BED
void lcd_preheat_m1_e5() { _lcd_preheat(5, lcd_preheat_hotend_temp[0], lcd_preheat_bed_temp[0], lcd_preheat_fan_speed[0]); }
void lcd_preheat_m2_e5() { _lcd_preheat(5, lcd_preheat_hotend_temp[1], lcd_preheat_bed_temp[1], lcd_preheat_fan_speed[1]); }
void lcd_preheat_m1_e5() { _lcd_preheat(5, ui.preheat_hotend_temp[0], ui.preheat_bed_temp[0], ui.preheat_fan_speed[0]); }
void lcd_preheat_m2_e5() { _lcd_preheat(5, ui.preheat_hotend_temp[1], ui.preheat_bed_temp[1], ui.preheat_fan_speed[1]); }
#endif
#endif // HOTENDS > 5
#endif // HOTENDS > 4
@ -113,15 +113,15 @@ void _lcd_preheat(const int16_t endnum, const int16_t temph, const int16_t tempb
void lcd_preheat_m1_all() {
#if HOTENDS > 1
thermalManager.setTargetHotend(lcd_preheat_hotend_temp[0], 1);
thermalManager.setTargetHotend(ui.preheat_hotend_temp[0], 1);
#if HOTENDS > 2
thermalManager.setTargetHotend(lcd_preheat_hotend_temp[0], 2);
thermalManager.setTargetHotend(ui.preheat_hotend_temp[0], 2);
#if HOTENDS > 3
thermalManager.setTargetHotend(lcd_preheat_hotend_temp[0], 3);
thermalManager.setTargetHotend(ui.preheat_hotend_temp[0], 3);
#if HOTENDS > 4
thermalManager.setTargetHotend(lcd_preheat_hotend_temp[0], 4);
thermalManager.setTargetHotend(ui.preheat_hotend_temp[0], 4);
#if HOTENDS > 5
thermalManager.setTargetHotend(lcd_preheat_hotend_temp[0], 5);
thermalManager.setTargetHotend(ui.preheat_hotend_temp[0], 5);
#endif // HOTENDS > 5
#endif // HOTENDS > 4
#endif // HOTENDS > 3
@ -136,15 +136,15 @@ void _lcd_preheat(const int16_t endnum, const int16_t temph, const int16_t tempb
void lcd_preheat_m2_all() {
#if HOTENDS > 1
thermalManager.setTargetHotend(lcd_preheat_hotend_temp[1], 1);
thermalManager.setTargetHotend(ui.preheat_hotend_temp[1], 1);
#if HOTENDS > 2
thermalManager.setTargetHotend(lcd_preheat_hotend_temp[1], 2);
thermalManager.setTargetHotend(ui.preheat_hotend_temp[1], 2);
#if HOTENDS > 3
thermalManager.setTargetHotend(lcd_preheat_hotend_temp[1], 3);
thermalManager.setTargetHotend(ui.preheat_hotend_temp[1], 3);
#if HOTENDS > 4
thermalManager.setTargetHotend(lcd_preheat_hotend_temp[1], 4);
thermalManager.setTargetHotend(ui.preheat_hotend_temp[1], 4);
#if HOTENDS > 5
thermalManager.setTargetHotend(lcd_preheat_hotend_temp[1], 5);
thermalManager.setTargetHotend(ui.preheat_hotend_temp[1], 5);
#endif // HOTENDS > 5
#endif // HOTENDS > 4
#endif // HOTENDS > 3
@ -161,14 +161,14 @@ void _lcd_preheat(const int16_t endnum, const int16_t temph, const int16_t tempb
#if HAS_TEMP_HOTEND || HAS_HEATED_BED
void lcd_preheat_m1_e0_only() { _lcd_preheat(0, lcd_preheat_hotend_temp[0], -1, lcd_preheat_fan_speed[0]); }
void lcd_preheat_m2_e0_only() { _lcd_preheat(0, lcd_preheat_hotend_temp[1], -1, lcd_preheat_fan_speed[1]); }
void lcd_preheat_m1_e0_only() { _lcd_preheat(0, ui.preheat_hotend_temp[0], -1, ui.preheat_fan_speed[0]); }
void lcd_preheat_m2_e0_only() { _lcd_preheat(0, ui.preheat_hotend_temp[1], -1, ui.preheat_fan_speed[1]); }
#if HAS_HEATED_BED
void lcd_preheat_m1_e0() { _lcd_preheat(0, lcd_preheat_hotend_temp[0], lcd_preheat_bed_temp[0], lcd_preheat_fan_speed[0]); }
void lcd_preheat_m2_e0() { _lcd_preheat(0, lcd_preheat_hotend_temp[1], lcd_preheat_bed_temp[1], lcd_preheat_fan_speed[1]); }
void lcd_preheat_m1_bedonly() { _lcd_preheat(0, 0, lcd_preheat_bed_temp[0], lcd_preheat_fan_speed[0]); }
void lcd_preheat_m2_bedonly() { _lcd_preheat(0, 0, lcd_preheat_bed_temp[1], lcd_preheat_fan_speed[1]); }
void lcd_preheat_m1_e0() { _lcd_preheat(0, ui.preheat_hotend_temp[0], ui.preheat_bed_temp[0], ui.preheat_fan_speed[0]); }
void lcd_preheat_m2_e0() { _lcd_preheat(0, ui.preheat_hotend_temp[1], ui.preheat_bed_temp[1], ui.preheat_fan_speed[1]); }
void lcd_preheat_m1_bedonly() { _lcd_preheat(0, 0, ui.preheat_bed_temp[0], ui.preheat_fan_speed[0]); }
void lcd_preheat_m2_bedonly() { _lcd_preheat(0, 0, ui.preheat_bed_temp[1], ui.preheat_fan_speed[1]); }
#endif
void menu_preheat_m1() {
@ -294,7 +294,7 @@ void _lcd_preheat(const int16_t endnum, const int16_t temph, const int16_t tempb
void lcd_cooldown() {
zero_fan_speeds();
thermalManager.disable_all_heaters();
lcd_return_to_status();
ui.return_to_status();
}
#endif // HAS_TEMP_HOTEND || HAS_HEATED_BED

View File

@ -62,29 +62,29 @@ void _lcd_refresh_e_factor_0() { planner.refresh_e_factor(0); }
long babysteps_done = 0;
void _lcd_babystep(const AxisEnum axis, PGM_P msg) {
if (use_click()) { return lcd_goto_previous_menu_no_defer(); }
ENCODER_DIRECTION_NORMAL();
if (encoderPosition) {
const int16_t babystep_increment = (int32_t)encoderPosition * (BABYSTEP_MULTIPLICATOR);
encoderPosition = 0;
lcdDrawUpdate = LCDVIEW_REDRAW_NOW;
if (ui.use_click()) return ui.goto_previous_screen_no_defer();
ui.encoder_direction_normal();
if (ui.encoderPosition) {
const int16_t babystep_increment = (int32_t)ui.encoderPosition * (BABYSTEP_MULTIPLICATOR);
ui.encoderPosition = 0;
ui.refresh(LCDVIEW_REDRAW_NOW);
thermalManager.babystep_axis(axis, babystep_increment);
babysteps_done += babystep_increment;
}
if (lcdDrawUpdate)
lcd_implementation_drawedit(msg, ftostr43sign(planner.steps_to_mm[axis] * babysteps_done));
if (ui.should_draw())
draw_edit_screen(msg, ftostr43sign(planner.steps_to_mm[axis] * babysteps_done));
}
#if ENABLED(BABYSTEP_XY)
void _lcd_babystep_x() { _lcd_babystep(X_AXIS, PSTR(MSG_BABYSTEP_X)); }
void _lcd_babystep_y() { _lcd_babystep(Y_AXIS, PSTR(MSG_BABYSTEP_Y)); }
void lcd_babystep_x() { lcd_goto_screen(_lcd_babystep_x); babysteps_done = 0; set_defer_return_to_status(true); }
void lcd_babystep_y() { lcd_goto_screen(_lcd_babystep_y); babysteps_done = 0; set_defer_return_to_status(true); }
void lcd_babystep_x() { ui.goto_screen(_lcd_babystep_x); babysteps_done = 0; ui.defer_status_screen(true); }
void lcd_babystep_y() { ui.goto_screen(_lcd_babystep_y); babysteps_done = 0; ui.defer_status_screen(true); }
#endif
#if DISABLED(BABYSTEP_ZPROBE_OFFSET)
void _lcd_babystep_z() { _lcd_babystep(Z_AXIS, PSTR(MSG_BABYSTEP_Z)); }
void lcd_babystep_z() { lcd_goto_screen(_lcd_babystep_z); babysteps_done = 0; set_defer_return_to_status(true); }
void lcd_babystep_z() { ui.goto_screen(_lcd_babystep_z); babysteps_done = 0; ui.defer_status_screen(true); }
#endif
#endif // BABYSTEPPING

View File

@ -51,22 +51,22 @@ float mesh_edit_value, mesh_edit_accumulator; // We round mesh_edit_value to 2.5
static int16_t ubl_encoderPosition = 0;
static void _lcd_mesh_fine_tune(PGM_P msg) {
set_defer_return_to_status(true);
ui.defer_status_screen(true);
if (ubl.encoder_diff) {
ubl_encoderPosition = (ubl.encoder_diff > 0) ? 1 : -1;
ubl.encoder_diff = 0;
mesh_edit_accumulator += float(ubl_encoderPosition) * 0.005f * 0.5f;
mesh_edit_value = mesh_edit_accumulator;
encoderPosition = 0;
lcdDrawUpdate = LCDVIEW_CALL_REDRAW_NEXT;
ui.encoderPosition = 0;
ui.refresh(LCDVIEW_CALL_REDRAW_NEXT);
const int32_t rounded = (int32_t)(mesh_edit_value * 1000);
mesh_edit_value = float(rounded - (rounded % 5L)) / 1000;
}
if (lcdDrawUpdate) {
lcd_implementation_drawedit(msg, ftostr43sign(mesh_edit_value));
if (ui.should_draw()) {
draw_edit_screen(msg, ftostr43sign(mesh_edit_value));
#if ENABLED(MESH_EDIT_GFX_OVERLAY)
_lcd_zoffset_overlay_gfx(mesh_edit_value);
#endif
@ -74,19 +74,19 @@ static void _lcd_mesh_fine_tune(PGM_P msg) {
}
void _lcd_mesh_edit_NOP() {
set_defer_return_to_status(true);
ui.defer_status_screen(true);
}
float lcd_mesh_edit() {
lcd_goto_screen(_lcd_mesh_edit_NOP);
lcdDrawUpdate = LCDVIEW_CALL_REDRAW_NEXT;
ui.goto_screen(_lcd_mesh_edit_NOP);
ui.refresh(LCDVIEW_CALL_REDRAW_NEXT);
_lcd_mesh_fine_tune(PSTR("Mesh Editor"));
return mesh_edit_value;
}
void lcd_mesh_edit_setup(const float &initial) {
mesh_edit_value = mesh_edit_accumulator = initial;
lcd_goto_screen(_lcd_mesh_edit_NOP);
ui.goto_screen(_lcd_mesh_edit_NOP);
}
void _lcd_z_offset_edit() {
@ -94,13 +94,13 @@ void _lcd_z_offset_edit() {
}
float lcd_z_offset_edit() {
lcd_goto_screen(_lcd_z_offset_edit);
ui.goto_screen(_lcd_z_offset_edit);
return mesh_edit_value;
}
void lcd_z_offset_edit_setup(const float &initial) {
mesh_edit_value = mesh_edit_accumulator = initial;
lcd_goto_screen(_lcd_z_offset_edit);
ui.goto_screen(_lcd_z_offset_edit);
}
/**
@ -160,7 +160,7 @@ void _menu_ubl_height_adjust() {
START_MENU();
MENU_BACK(MSG_EDIT_MESH);
MENU_ITEM_EDIT_CALLBACK(int3, MSG_UBL_MESH_HEIGHT_AMOUNT, &ubl_height_amount, -9, 9, _lcd_ubl_adjust_height_cmd);
MENU_ITEM(function, MSG_WATCH, lcd_return_to_status);
MENU_ITEM(function, MSG_WATCH, ui.return_to_status);
END_MENU();
}
@ -179,7 +179,7 @@ void _lcd_ubl_edit_mesh() {
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, _menu_ubl_height_adjust);
MENU_ITEM(function, MSG_WATCH, lcd_return_to_status);
MENU_ITEM(function, MSG_WATCH, ui.return_to_status);
END_MENU();
}
@ -220,7 +220,7 @@ void _lcd_ubl_validate_mesh() {
MENU_ITEM(gcode, MSG_UBL_VALIDATE_MESH_M2, PSTR("G28\nG26 C B0 H" STRINGIFY(PREHEAT_2_TEMP_HOTEND) " P"));
#endif
MENU_ITEM(function, MSG_UBL_VALIDATE_CUSTOM_MESH, _lcd_ubl_validate_custom_mesh);
MENU_ITEM(function, MSG_WATCH, lcd_return_to_status);
MENU_ITEM(function, MSG_WATCH, ui.return_to_status);
END_MENU();
}
@ -261,7 +261,7 @@ void _lcd_ubl_mesh_leveling() {
MENU_BACK(MSG_UBL_TOOLS);
MENU_ITEM(gcode, MSG_UBL_3POINT_MESH_LEVELING, PSTR("G29 J0"));
MENU_ITEM(submenu, MSG_UBL_GRID_MESH_LEVELING, _lcd_ubl_grid_level);
MENU_ITEM(function, MSG_WATCH, lcd_return_to_status);
MENU_ITEM(function, MSG_WATCH, ui.return_to_status);
END_MENU();
}
@ -290,7 +290,7 @@ void _menu_ubl_fillin() {
MENU_ITEM_EDIT_CALLBACK(int3, MSG_UBL_FILLIN_AMOUNT, &ubl_fillin_amount, 0, 9, _lcd_ubl_fillin_amount_cmd);
MENU_ITEM(gcode, MSG_UBL_SMART_FILLIN, PSTR("G29 P3 T0"));
MENU_ITEM(gcode, MSG_UBL_MANUAL_FILLIN, PSTR("G29 P2 B T0"));
MENU_ITEM(function, MSG_WATCH, lcd_return_to_status);
MENU_ITEM(function, MSG_WATCH, ui.return_to_status);
END_MENU();
}
@ -353,7 +353,7 @@ void _lcd_ubl_build_mesh() {
MENU_ITEM(gcode, MSG_UBL_CONTINUE_MESH, PSTR("G29 P1 C"));
MENU_ITEM(function, MSG_UBL_INVALIDATE_ALL, _lcd_ubl_invalidate);
MENU_ITEM(gcode, MSG_UBL_INVALIDATE_CLOSEST, PSTR("G29 I"));
MENU_ITEM(function, MSG_WATCH, lcd_return_to_status);
MENU_ITEM(function, MSG_WATCH, ui.return_to_status);
END_MENU();
}
@ -408,11 +408,11 @@ void _lcd_ubl_storage_mesh() {
void _lcd_ubl_output_map_lcd();
void _lcd_ubl_map_homing() {
set_defer_return_to_status(true);
ui.defer_status_screen(true);
_lcd_draw_homing();
if (all_axes_homed()) {
ubl.lcd_map_control = true; // Return to the map screen
lcd_goto_screen(_lcd_ubl_output_map_lcd);
ui.goto_screen(_lcd_ubl_output_map_lcd);
}
}
@ -444,10 +444,10 @@ void sync_plan_position();
void _lcd_do_nothing() {}
void _lcd_hard_stop() {
const screenFunc_t old_screen = currentScreen;
currentScreen = _lcd_do_nothing;
const screenFunc_t old_screen = ui.currentScreen;
ui.currentScreen = _lcd_do_nothing;
planner.quick_stop();
currentScreen = old_screen;
ui.currentScreen = old_screen;
set_current_from_steppers_for_axis(ALL_AXES);
sync_plan_position();
}
@ -455,15 +455,15 @@ void _lcd_hard_stop() {
void _lcd_ubl_output_map_lcd() {
static int16_t step_scaler = 0;
if (use_click()) return _lcd_ubl_map_lcd_edit_cmd();
ENCODER_DIRECTION_NORMAL();
if (ui.use_click()) return _lcd_ubl_map_lcd_edit_cmd();
ui.encoder_direction_normal();
if (encoderPosition) {
step_scaler += (int32_t)encoderPosition;
if (ui.encoderPosition) {
step_scaler += (int32_t)ui.encoderPosition;
x_plot += step_scaler / (ENCODER_STEPS_PER_MENU_ITEM);
if (ABS(step_scaler) >= ENCODER_STEPS_PER_MENU_ITEM) step_scaler = 0;
encoderPosition = 0;
lcdDrawUpdate = LCDVIEW_REDRAW_NOW;
ui.encoderPosition = 0;
ui.refresh(LCDVIEW_REDRAW_NOW);
}
// Encoder to the right (++)
@ -487,8 +487,8 @@ void _lcd_ubl_output_map_lcd() {
n_edit_pts = yc ? (xc ? 9 : 6) : (xc ? 6 : 4); // Corners
#endif
if (lcdDrawUpdate) {
lcd_implementation_ubl_plot(x_plot, y_plot);
if (ui.should_draw()) {
ui.ubl_plot(x_plot, y_plot);
if (planner.movesplanned()) // If the nozzle is already moving, cancel the move.
_lcd_hard_stop();
@ -505,7 +505,7 @@ void _lcd_ubl_output_map_lcd_cmd() {
set_all_unhomed();
enqueue_and_echo_commands_P(PSTR("G28"));
}
lcd_goto_screen(_lcd_ubl_map_homing);
ui.goto_screen(_lcd_ubl_map_homing);
}
/**

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,21 @@
#include "../inc/MarlinConfig.h"
#if HAS_SPI_LCD
#include "../Marlin.h"
#if ENABLED(ADVANCED_PAUSE_FEATURE)
#include "../feature/pause.h"
#include "../module/motion.h" // for active_extruder
#endif
#endif
#if HAS_BUZZER
#include "../libs/buzzer.h"
#endif
#if HAS_GRAPHICAL_LCD
#ifndef LCD_PIXEL_WIDTH
@ -171,13 +186,11 @@
#define INFO_FONT_DESCENT 2
#define INFO_FONT_HEIGHT (INFO_FONT_ASCENT + INFO_FONT_DESCENT)
// Font IDs
enum MarlinFont : uint8_t {
FONT_STATUSMENU = 1,
FONT_EDIT,
FONT_MENU
};
void lcd_setFont(const MarlinFont font_nr);
#if ENABLED(LIGHTWEIGHT_UI)
void lcd_in_status(const bool inStatus);
@ -185,46 +198,10 @@
#endif // HAS_GRAPHICAL_LCD
#if HAS_SPI_LCD || ENABLED(MALYAN_LCD) || ENABLED(EXTENSIBLE_UI)
void lcd_init();
bool lcd_detected();
void lcd_update();
void lcd_setalertstatusPGM(PGM_P message);
void kill_screen(PGM_P lcd_msg);
#else
inline void lcd_init() {}
inline bool lcd_detected() { return true; }
inline void lcd_update() {}
inline void lcd_setalertstatusPGM(PGM_P message) { UNUSED(message); }
#endif
#define HAS_ENCODER_ACTION (HAS_LCD_MENU || ENABLED(ULTIPANEL_FEEDMULTIPLY))
#if HAS_ENCODER_ACTION
extern uint32_t encoderPosition;
#endif
#if HAS_SPI_LCD
#include "../Marlin.h"
#if ENABLED(ADVANCED_PAUSE_FEATURE)
#include "../feature/pause.h"
#include "../module/motion.h" // for active_extruder
#endif
void lcd_status_screen();
void lcd_return_to_status();
bool lcd_hasstatus();
void lcd_setstatus(const char* message, const bool persist=false);
void lcd_setstatusPGM(PGM_P message, const int8_t level=0);
void lcd_setalertstatusPGM(PGM_P message);
void lcd_reset_alert_level();
void lcd_reset_status();
void lcd_status_printf_P(const uint8_t level, PGM_P const fmt, ...);
void lcd_kill_screen();
void kill_screen(PGM_P lcd_msg);
enum LCDViewAction : uint8_t {
LCDVIEW_NONE,
LCDVIEW_REDRAW_NOW,
@ -233,37 +210,10 @@
LCDVIEW_CALL_NO_REDRAW
};
extern LCDViewAction lcdDrawUpdate;
inline void lcd_refresh() { lcdDrawUpdate = LCDVIEW_CLEAR_CALL_REDRAW; }
#if HAS_BUZZER
void lcd_buzz(const long duration, const uint16_t freq);
#else
inline void lcd_buzz(const long duration, const uint16_t freq) { UNUSED(duration); UNUSED(freq); }
#endif
void lcd_quick_feedback(const bool clear_buttons=true); // Audible feedback for a button click - could also be visual
#if ENABLED(LCD_PROGRESS_BAR)
extern millis_t progress_bar_ms; // Start time for the current progress bar cycle
#if PROGRESS_MSG_EXPIRE > 0
void dontExpireStatus();
#endif
#endif
#if ENABLED(LCD_SET_PROGRESS_MANUALLY)
extern uint8_t progress_bar_percent;
#endif
#if ENABLED(ADC_KEYPAD)
uint8_t get_ADC_keyValue();
#endif
#if HAS_LCD_CONTRAST
extern int16_t lcd_contrast;
void set_lcd_contrast(const int16_t value);
#endif
#if HAS_GRAPHICAL_LCD
#define SETCURSOR(col, row) lcd_moveto(col * (MENU_FONT_WIDTH), (row + 1) * (MENU_FONT_HEIGHT))
#define SETCURSOR_RJ(len, row) lcd_moveto(LCD_PIXEL_WIDTH - len * (MENU_FONT_WIDTH), (row + 1) * (MENU_FONT_HEIGHT))
@ -272,10 +222,6 @@
#define SETCURSOR_RJ(len, row) lcd_moveto(LCD_WIDTH - len, row)
#endif
#if ENABLED(SHOW_BOOTSCREEN)
void lcd_bootscreen();
#endif
#define LCD_UPDATE_INTERVAL 100
#define BUTTON_EXISTS(BN) (defined(BTN_## BN) && BTN_## BN >= 0)
#define BUTTON_PRESSED(BN) !READ(BTN_## BN)
@ -284,41 +230,10 @@
typedef void (*screenFunc_t)();
typedef void (*menuAction_t)();
extern screenFunc_t currentScreen;
void lcd_goto_screen(const screenFunc_t screen, const uint32_t encoder=0);
extern bool lcd_clicked;
#if LCD_TIMEOUT_TO_STATUS
extern bool defer_return_to_status;
inline void set_defer_return_to_status(const bool defer) { defer_return_to_status = defer; }
#else
constexpr bool defer_return_to_status = false;
#define set_defer_return_to_status(D) NOOP
#endif
extern int16_t lcd_preheat_hotend_temp[2], lcd_preheat_bed_temp[2];
extern uint8_t lcd_preheat_fan_speed[2];
#if ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(G26_MESH_VALIDATION)
extern bool lcd_external_control;
#else
constexpr bool lcd_external_control = false;
#endif
#if ENABLED(LCD_BED_LEVELING)
extern bool lcd_wait_for_move;
#else
constexpr bool lcd_wait_for_move = false;
#endif
// Manual Movement
constexpr float manual_feedrate_mm_m[XYZE] = MANUAL_FEEDRATE;
extern float move_menu_scale;
#if IS_KINEMATIC
extern bool processing_manual_move;
#else
constexpr bool processing_manual_move = false;
#endif
#if ENABLED(ADVANCED_PAUSE_FEATURE)
void lcd_advanced_pause_show_message(const AdvancedPauseMessage message,
@ -326,65 +241,15 @@
const uint8_t extruder=active_extruder);
#endif
#if ENABLED(G26_MESH_VALIDATION)
void lcd_chirp();
#endif
#if ENABLED(AUTO_BED_LEVELING_UBL)
void lcd_mesh_edit_setup(const float &initial);
float lcd_mesh_edit();
#endif
#if ENABLED(SCROLL_LONG_FILENAMES)
extern uint8_t filename_scroll_pos, filename_scroll_max;
#endif
#endif // HAS_LCD_MENU
#if ENABLED(FILAMENT_LCD_DISPLAY) && ENABLED(SDSUPPORT)
extern millis_t previous_lcd_status_ms;
#endif
#if ENABLED(STATUS_MESSAGE_SCROLLING)
extern uint8_t status_scroll_offset;
#endif
bool lcd_blink();
bool use_click();
#if ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(G26_MESH_VALIDATION)
bool is_lcd_clicked();
void wait_for_release();
#endif
#elif ENABLED(EXTENSIBLE_UI)
// These functions are defined elsewhere
void lcd_setstatus(const char* const message, const bool persist=false);
void lcd_setstatusPGM(const char* const message, const int8_t level=0);
void lcd_status_printf_P(const uint8_t level, const char * const fmt, ...);
void lcd_reset_status();
void lcd_refresh();
void lcd_reset_alert_level();
bool lcd_hasstatus();
#else // MALYAN_LCD or no LCD
constexpr bool lcd_wait_for_move = false;
inline void lcd_refresh() {}
inline bool lcd_hasstatus() { return false; }
inline void lcd_setstatus(const char* const message, const bool persist=false) { UNUSED(message); UNUSED(persist); }
inline void lcd_setstatusPGM(PGM_P const message, const int8_t level=0) { UNUSED(message); UNUSED(level); }
inline void lcd_status_printf_P(const uint8_t level, PGM_P const fmt, ...) { UNUSED(level); UNUSED(fmt); }
inline void lcd_reset_alert_level() {}
inline void lcd_reset_status() {}
#endif
#define HAS_DIGITAL_ENCODER (HAS_SPI_LCD && ENABLED(NEWPANEL))
#if HAS_DIGITAL_ENCODER
// Wheel spin pins where BA is 00, 10, 11, 01 (1 bit always changes)
@ -402,103 +267,400 @@
#if BUTTON_EXISTS(BACK)
#define BLEN_D 3
#define EN_D _BV(BLEN_D)
#define LCD_BACK_CLICKED (buttons & EN_D)
#define LCD_BACK_CLICKED() (buttons & EN_D)
#endif
#endif // HAS_DIGITAL_ENCODER
#if ENABLED(REPRAPWORLD_KEYPAD)
#define REPRAPWORLD_BTN_OFFSET 0 // Bit offset into buttons for shift register values
#if HAS_LCD_MENU
#define BLEN_REPRAPWORLD_KEYPAD_F3 0
#define BLEN_REPRAPWORLD_KEYPAD_F2 1
#define BLEN_REPRAPWORLD_KEYPAD_F1 2
#define BLEN_REPRAPWORLD_KEYPAD_DOWN 3
#define BLEN_REPRAPWORLD_KEYPAD_RIGHT 4
#define BLEN_REPRAPWORLD_KEYPAD_MIDDLE 5
#define BLEN_REPRAPWORLD_KEYPAD_UP 6
#define BLEN_REPRAPWORLD_KEYPAD_LEFT 7
extern volatile uint8_t buttons; // The last-checked buttons in a bit array.
void lcd_buttons_update();
#define EN_REPRAPWORLD_KEYPAD_F1 (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_F1))
#define EN_REPRAPWORLD_KEYPAD_F2 (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_F2))
#define EN_REPRAPWORLD_KEYPAD_F3 (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_F3))
#define EN_REPRAPWORLD_KEYPAD_DOWN (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_DOWN))
#define EN_REPRAPWORLD_KEYPAD_RIGHT (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_RIGHT))
#define EN_REPRAPWORLD_KEYPAD_MIDDLE (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_MIDDLE))
#define EN_REPRAPWORLD_KEYPAD_UP (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_UP))
#define EN_REPRAPWORLD_KEYPAD_LEFT (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_LEFT))
#define RRK(B) (buttons_reprapworld_keypad & (B))
#ifdef EN_C
#define BUTTON_CLICK() ((buttons & EN_C) || RRK(EN_REPRAPWORLD_KEYPAD_MIDDLE))
#else
#define BUTTON_CLICK() RRK(EN_REPRAPWORLD_KEYPAD_MIDDLE)
#endif
#elif ENABLED(LCD_I2C_VIKI)
#define B_I2C_BTN_OFFSET 3 // (the first three bit positions reserved for EN_A, EN_B, EN_C)
// button and encoder bit positions within 'buttons'
#define B_LE (BUTTON_LEFT << B_I2C_BTN_OFFSET) // The remaining normalized buttons are all read via I2C
#define B_UP (BUTTON_UP << B_I2C_BTN_OFFSET)
#define B_MI (BUTTON_SELECT << B_I2C_BTN_OFFSET)
#define B_DW (BUTTON_DOWN << B_I2C_BTN_OFFSET)
#define B_RI (BUTTON_RIGHT << B_I2C_BTN_OFFSET)
#if BUTTON_EXISTS(ENC) // The pause/stop/restart button is connected to BTN_ENC when used
#define B_ST (EN_C) // Map the pause/stop/resume button into its normalized functional name
#define BUTTON_CLICK() (buttons & (B_MI|B_RI|B_ST)) // Pause/stop also acts as click until a proper pause/stop is implemented.
#else
#define BUTTON_CLICK() (buttons & (B_MI|B_RI))
#endif
// I2C buttons take too long to read inside an interrupt context and so we read them during lcd_update
#define LCD_HAS_SLOW_BUTTONS
#elif ENABLED(LCD_I2C_PANELOLU2)
#if !BUTTON_EXISTS(ENC) // Use I2C if not directly connected to a pin
#define B_I2C_BTN_OFFSET 3 // (the first three bit positions reserved for EN_A, EN_B, EN_C)
#define B_MI (PANELOLU2_ENCODER_C << B_I2C_BTN_OFFSET) // requires LiquidTWI2 library v1.2.3 or later
#define BUTTON_CLICK() (buttons & B_MI)
// I2C buttons take too long to read inside an interrupt context and so we read them during lcd_update
#define LCD_HAS_SLOW_BUTTONS
#endif
#endif
#else
inline void lcd_buttons_update() {}
// Shift register bits correspond to buttons:
#define BL_LE 7 // Left
#define BL_UP 6 // Up
#define BL_MI 5 // Middle
#define BL_DW 4 // Down
#define BL_RI 3 // Right
#define BL_ST 2 // Red Button
#define B_LE (_BV(BL_LE))
#define B_UP (_BV(BL_UP))
#define B_MI (_BV(BL_MI))
#define B_DW (_BV(BL_DW))
#define B_RI (_BV(BL_RI))
#define B_ST (_BV(BL_ST))
#define BUTTON_CLICK() (buttons & (B_MI|B_ST))
#endif
#if ENABLED(LCD_HAS_SLOW_BUTTONS)
extern volatile uint8_t slow_buttons;
#endif
#if ENABLED(REPRAPWORLD_KEYPAD)
#define REPRAPWORLD_BTN_OFFSET 0 // Bit offset into buttons for shift register values
#define BLEN_REPRAPWORLD_KEYPAD_F3 0
#define BLEN_REPRAPWORLD_KEYPAD_F2 1
#define BLEN_REPRAPWORLD_KEYPAD_F1 2
#define BLEN_REPRAPWORLD_KEYPAD_DOWN 3
#define BLEN_REPRAPWORLD_KEYPAD_RIGHT 4
#define BLEN_REPRAPWORLD_KEYPAD_MIDDLE 5
#define BLEN_REPRAPWORLD_KEYPAD_UP 6
#define BLEN_REPRAPWORLD_KEYPAD_LEFT 7
#define EN_REPRAPWORLD_KEYPAD_F1 (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_F1))
#define EN_REPRAPWORLD_KEYPAD_F2 (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_F2))
#define EN_REPRAPWORLD_KEYPAD_F3 (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_F3))
#define EN_REPRAPWORLD_KEYPAD_DOWN (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_DOWN))
#define EN_REPRAPWORLD_KEYPAD_RIGHT (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_RIGHT))
#define EN_REPRAPWORLD_KEYPAD_MIDDLE (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_MIDDLE))
#define EN_REPRAPWORLD_KEYPAD_UP (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_UP))
#define EN_REPRAPWORLD_KEYPAD_LEFT (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_LEFT))
#define RRK(B) (buttons_reprapworld_keypad & (B))
#ifndef BUTTON_CLICK
#ifdef EN_C
#define LCD_CLICKED() ((buttons & EN_C) || RRK(EN_REPRAPWORLD_KEYPAD_MIDDLE))
#define BUTTON_CLICK() (buttons & EN_C)
#else
#define LCD_CLICKED() RRK(EN_REPRAPWORLD_KEYPAD_MIDDLE)
#endif
#endif // REPRAPWORLD_KEYPAD
#ifndef LCD_CLICKED
#ifdef EN_C
#define LCD_CLICKED() (buttons & EN_C)
#else
#define LCD_CLICKED() false
#define BUTTON_CLICK() false
#endif
#endif
extern uint8_t lcd_status_update_delay;
extern char lcd_status_message[];
#define LCD_MESSAGEPGM(x) ui.setstatusPGM(PSTR(x))
#define LCD_ALERTMESSAGEPGM(x) ui.setalertstatusPGM(PSTR(x))
#define LCD_MESSAGEPGM(x) lcd_setstatusPGM(PSTR(x))
#define LCD_ALERTMESSAGEPGM(x) lcd_setalertstatusPGM(PSTR(x))
////////////////////////////////////////////
//////////// MarlinUI Singleton ////////////
////////////////////////////////////////////
// For i2c define BUZZ to use lcd_buzz
#if ENABLED(LCD_USE_I2C_BUZZER)
#define BUZZ(d,f) lcd_buzz(d, f)
#endif
class MarlinUI {
public:
#if ENABLED(SD_REPRINT_LAST_SELECTED_FILE)
void lcd_reselect_last_file();
#endif
#if HAS_GRAPHICAL_LCD
extern bool drawing_screen, first_page;
#elif HAS_SPI_LCD
constexpr bool first_page = true;
#endif
// LCD implementations
void lcd_implementation_clear();
void lcd_implementation_init();
#if HAS_CHARACTER_LCD
enum HD44780CharSet : uint8_t { CHARSET_MENU, CHARSET_INFO, CHARSET_BOOT };
void lcd_set_custom_characters(
#if ENABLED(LCD_PROGRESS_BAR) || ENABLED(SHOW_BOOTSCREEN)
const HD44780CharSet screen_charset=CHARSET_INFO
MarlinUI() {
#if HAS_LCD_MENU
currentScreen = status_screen;
#endif
);
#if ENABLED(LCD_PROGRESS_BAR)
#define LCD_SET_CHARSET(C) lcd_set_custom_characters(C)
#else
#define LCD_SET_CHARSET(C) lcd_set_custom_characters()
}
static inline void buzz(const long duration, const uint16_t freq) {
#if ENABLED(LCD_USE_I2C_BUZZER)
lcd.buzz(duration, freq);
#elif PIN_EXISTS(BEEPER)
buzzer.tone(duration, freq);
#else
UNUSED(duration); UNUSED(freq);
#endif
}
// LCD implementations
static void clear_lcd();
static void init_lcd();
#if HAS_SPI_LCD || ENABLED(MALYAN_LCD) || ENABLED(EXTENSIBLE_UI)
static void init();
static void update();
static bool detected();
static void setalertstatusPGM(PGM_P message);
#else // NO LCD
static inline void init() {}
static inline void update() {}
static constexpr bool detected() { return true; }
static inline void setalertstatusPGM(PGM_P message) { UNUSED(message); }
#endif
#endif
#if HAS_SPI_LCD || ENABLED(EXTENSIBLE_UI)
#if HAS_SPI_LCD
static LCDViewAction lcdDrawUpdate;
static inline bool should_draw() { return bool(lcdDrawUpdate); }
static inline void refresh(const LCDViewAction type) { lcdDrawUpdate = type; }
static inline void refresh() { refresh(LCDVIEW_CLEAR_CALL_REDRAW); }
#if ENABLED(SHOW_BOOTSCREEN)
static void show_bootscreen();
#endif
#if HAS_GRAPHICAL_LCD
static bool drawing_screen, first_page;
static void set_font(const MarlinFont font_nr);
#else
static constexpr bool drawing_screen = false, first_page = true;
enum HD44780CharSet : uint8_t { CHARSET_MENU, CHARSET_INFO, CHARSET_BOOT };
static void set_custom_characters(
#if ENABLED(LCD_PROGRESS_BAR) || ENABLED(SHOW_BOOTSCREEN)
const HD44780CharSet screen_charset=CHARSET_INFO
#endif
);
#if ENABLED(LCD_PROGRESS_BAR)
static millis_t progress_bar_ms; // Start time for the current progress bar cycle
#if PROGRESS_MSG_EXPIRE > 0
static millis_t MarlinUI::expire_status_ms; // = 0
static inline void reset_progress_bar_timeout() { expire_status_ms = 0; }
#endif
#define LCD_SET_CHARSET(C) set_custom_characters(C)
#else
#define LCD_SET_CHARSET(C) set_custom_characters()
#endif
#endif
// Status message
static char status_message[];
#if ENABLED(STATUS_MESSAGE_SCROLLING)
static uint8_t status_scroll_offset;
#endif
static uint8_t lcd_status_update_delay;
static uint8_t status_message_level; // Higher levels block lower levels
static inline void reset_alert_level() { status_message_level = 0; }
#if HAS_PRINT_PROGRESS
#if ENABLED(LCD_SET_PROGRESS_MANUALLY)
static uint8_t progress_bar_percent;
static void set_progress(const uint8_t progress) { progress_bar_percent = MIN(progress, 100); }
#endif
static uint8_t get_progress();
#else
static constexpr uint8_t get_progress() { return 0; }
#endif
#if HAS_LCD_CONTRAST
static int16_t contrast;
static void set_contrast(const int16_t value);
static inline void refresh_contrast() { set_contrast(contrast); }
#endif
#if ENABLED(FILAMENT_LCD_DISPLAY) && ENABLED(SDSUPPORT)
static millis_t next_filament_display;
#endif
static void quick_feedback(const bool clear_buttons=true);
static void completion_feedback(const bool good=true);
#if DISABLED(LIGHTWEIGHT_UI)
static void draw_status_message(const bool blink);
#endif
#if ENABLED(ADVANCED_PAUSE_FEATURE)
static void draw_hotend_status(const uint8_t row, const uint8_t extruder);
#endif
static void status_screen();
#else
static void refresh();
static void reset_alert_level();
#endif
static bool get_blink();
static void kill_screen(PGM_P const lcd_msg);
static void draw_kill_screen();
static bool hasstatus();
static void setstatus(const char* const message, const bool persist=false);
static void setstatusPGM(PGM_P const message, const int8_t level=0);
static void status_printf_P(const uint8_t level, PGM_P const fmt, ...);
static void reset_status();
#else // MALYAN_LCD or NO LCD
static inline void refresh() {}
static constexpr bool hasstatus() { return false; }
static inline void setstatus(const char* const message, const bool persist=false) { UNUSED(message); UNUSED(persist); }
static inline void setstatusPGM(PGM_P const message, const int8_t level=0) { UNUSED(message); UNUSED(level); }
static inline void status_printf_P(const uint8_t level, PGM_P const fmt, ...) { UNUSED(level); UNUSED(fmt); }
static inline void reset_status() {}
static inline void reset_alert_level() {}
#endif
#if HAS_LCD_MENU
#if ENABLED(ENCODER_RATE_MULTIPLIER)
static bool encoderRateMultiplierEnabled;
static millis_t lastEncoderMovementMillis;
static void enable_encoder_multiplier(const bool onoff);
#endif
#if ENABLED(SCROLL_LONG_FILENAMES)
static uint8_t filename_scroll_pos, filename_scroll_max;
#endif
#if IS_KINEMATIC
static bool processing_manual_move;
#else
static constexpr bool processing_manual_move = false;
#endif
#if E_MANUAL > 1
static int8_t manual_move_e_index;
#else
static constexpr int8_t manual_move_e_index = 0;
#endif
static int16_t preheat_hotend_temp[2], preheat_bed_temp[2];
static uint8_t preheat_fan_speed[2];
static void manage_manual_move();
static bool lcd_clicked;
static bool use_click();
static void synchronize(PGM_P const msg=NULL);
static screenFunc_t currentScreen;
static void goto_screen(const screenFunc_t screen, const uint32_t encoder=0);
static void save_previous_screen();
static void goto_previous_screen();
static void return_to_status();
static inline bool on_status_screen() { return currentScreen == status_screen; }
static inline void run_current_screen() { (*currentScreen)(); }
static inline void defer_status_screen(const bool defer) {
#if LCD_TIMEOUT_TO_STATUS
defer_return_to_status = defer;
#else
UNUSED(defer);
#endif
}
static inline void goto_previous_screen_no_defer() {
defer_status_screen(false);
goto_previous_screen();
}
#if ENABLED(SD_REPRINT_LAST_SELECTED_FILE)
static void reselect_last_file();
#endif
#if ENABLED(G26_MESH_VALIDATION)
static inline void chirp() { buzz(LCD_FEEDBACK_FREQUENCY_DURATION_MS, LCD_FEEDBACK_FREQUENCY_HZ); }
#endif
#if ENABLED(AUTO_BED_LEVELING_UBL)
static void ubl_plot(const uint8_t x, const uint8_t inverted_y);
#endif
#elif HAS_SPI_LCD
static constexpr bool lcd_clicked = false;
static constexpr bool on_status_screen() { return true; }
static inline void run_current_screen() { status_screen(); }
#endif
#if ENABLED(LCD_BED_LEVELING) && (ENABLED(PROBE_MANUALLY) || ENABLED(MESH_BED_LEVELING))
static bool wait_for_bl_move;
#else
static constexpr bool wait_for_bl_move = false;
#endif
#if HAS_LCD_MENU && (ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(G26_MESH_VALIDATION))
static bool external_control;
FORCE_INLINE static void capture() { external_control = true; }
FORCE_INLINE static void release() { external_control = false; }
#else
static constexpr bool external_control = false;
#endif
#if HAS_ENCODER_ACTION
static volatile uint8_t buttons;
#if ENABLED(LCD_HAS_SLOW_BUTTONS)
static volatile uint8_t slow_buttons;
static uint8_t read_slow_buttons();
#endif
static void update_buttons();
static inline bool button_pressed() { return BUTTON_CLICK(); }
#if ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(G26_MESH_VALIDATION)
static void wait_for_release();
#endif
static uint32_t encoderPosition;
#if ENABLED(REVERSE_ENCODER_DIRECTION)
#define ENCODERBASE -1
#else
#define ENCODERBASE +1
#endif
#if ENABLED(REVERSE_MENU_DIRECTION)
static int8_t encoderDirection;
static inline void encoder_direction_normal() { encoderDirection = +(ENCODERBASE); }
static inline void encoder_direction_menus() { encoderDirection = -(ENCODERBASE); }
#else
static constexpr int8_t encoderDirection = ENCODERBASE;
static inline void encoder_direction_normal() { }
static inline void encoder_direction_menus() { }
#endif
#else
static inline void update_buttons() { }
#endif
private:
static void _synchronize();
#if HAS_SPI_LCD
#if HAS_LCD_MENU
#if LCD_TIMEOUT_TO_STATUS
static bool defer_return_to_status;
#else
static constexpr bool defer_return_to_status = false;
#endif
#endif
static void draw_status_screen();
static void finishstatus(const bool persist);
#endif
};
extern MarlinUI ui;