diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp index f6ff6eb75..0e54aeb2d 100755 --- a/Marlin/ultralcd.cpp +++ b/Marlin/ultralcd.cpp @@ -28,6 +28,7 @@ #include "temperature.h" #include "stepper.h" #include "configuration_store.h" +#include "utility.h" #if ENABLED(PRINTCOUNTER) #include "printcounter.h" @@ -1878,6 +1879,7 @@ void kill_screen(const char* lcd_msg) { * */ #if ENABLED(FWRETRACT) + static void lcd_control_retract_menu() { START_MENU(); MENU_ITEM(back, MSG_CONTROL); @@ -1895,6 +1897,7 @@ void kill_screen(const char* lcd_msg) { MENU_ITEM_EDIT(float3, MSG_CONTROL_RETRACT_RECOVERF, &retract_recover_feedrate_mm_s, 1, 999); END_MENU(); } + #endif // FWRETRACT #if ENABLED(SDSUPPORT) @@ -2582,12 +2585,12 @@ void lcd_update() { lcd_implementation_update_indicators(); #endif - #if ENABLED(LCD_HAS_SLOW_BUTTONS) - slow_buttons = lcd_implementation_read_slow_buttons(); // buttons which take too long to read in interrupt context - #endif - #if ENABLED(ULTIPANEL) + #if ENABLED(LCD_HAS_SLOW_BUTTONS) + slow_buttons = lcd_implementation_read_slow_buttons(); // buttons which take too long to read in interrupt context + #endif + #if ENABLED(REPRAPWORLD_KEYPAD) static uint8_t keypad_debounce = 0; @@ -2936,252 +2939,4 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; } #endif // ULTIPANEL -/*********************************/ -/** Number to string conversion **/ -/*********************************/ - -#define DIGIT(n) ('0' + (n)) -#define DIGIMOD(n) DIGIT((n) % 10) - -char conv[8]; - -// Convert float to rj string with 123 or -12 format -char *ftostr3(const float& x) { return itostr3((int)x); } - -// Convert float to rj string with _123, -123, _-12, or __-1 format -char *ftostr4sign(const float& x) { return itostr4sign((int)x); } - -// Convert unsigned int to string with 12 format -char* itostr2(const uint8_t& x) { - int xx = x; - conv[0] = DIGIMOD(xx / 10); - conv[1] = DIGIMOD(xx); - conv[2] = '\0'; - return conv; -} - -// Convert float to string with +123.4 / -123.4 format -char* ftostr41sign(const float& x) { - int xx = int(abs(x * 10)) % 10000; - conv[0] = x >= 0 ? '+' : '-'; - conv[1] = DIGIMOD(xx / 1000); - conv[2] = DIGIMOD(xx / 100); - conv[3] = DIGIMOD(xx / 10); - conv[4] = '.'; - conv[5] = DIGIMOD(xx); - conv[6] = '\0'; - return conv; -} - -// Convert signed float to string with 023.45 / -23.45 format -char *ftostr32(const float& x) { - long xx = abs(x * 100); - conv[0] = x >= 0 ? DIGIMOD(xx / 10000) : '-'; - conv[1] = DIGIMOD(xx / 1000); - conv[2] = DIGIMOD(xx / 100); - conv[3] = '.'; - conv[4] = DIGIMOD(xx / 10); - conv[5] = DIGIMOD(xx); - conv[6] = '\0'; - return conv; -} - -// Convert signed float to string (6 digit) with -1.234 / _0.000 / +1.234 format -char* ftostr43sign(const float& x, char plus/*=' '*/) { - long xx = x * 1000; - if (xx == 0) - conv[0] = ' '; - else if (xx > 0) - conv[0] = plus; - else { - xx = -xx; - conv[0] = '-'; - } - conv[1] = DIGIMOD(xx / 1000); - conv[2] = '.'; - conv[3] = DIGIMOD(xx / 100); - conv[4] = DIGIMOD(xx / 10); - conv[5] = DIGIMOD(xx); - conv[6] = '\0'; - return conv; -} - -// Convert unsigned float to string with 1.23 format -char* ftostr12ns(const float& x) { - long xx = x * 100; - xx = abs(xx); - conv[0] = DIGIMOD(xx / 100); - conv[1] = '.'; - conv[2] = DIGIMOD(xx / 10); - conv[3] = DIGIMOD(xx); - conv[4] = '\0'; - return conv; -} - -// Convert signed int to lj string with +012 / -012 format -char* itostr3sign(const int& x) { - int xx; - if (x >= 0) { - conv[0] = '+'; - xx = x; - } - else { - conv[0] = '-'; - xx = -x; - } - conv[1] = DIGIMOD(xx / 100); - conv[2] = DIGIMOD(xx / 10); - conv[3] = DIGIMOD(xx); - conv[4] = '.'; - conv[5] = '0'; - conv[6] = '\0'; - return conv; -} - -// Convert signed int to rj string with 123 or -12 format -char* itostr3(const int& x) { - int xx = x; - if (xx < 0) { - conv[0] = '-'; - xx = -xx; - } - else - conv[0] = xx >= 100 ? DIGIMOD(xx / 100) : ' '; - - conv[1] = xx >= 10 ? DIGIMOD(xx / 10) : ' '; - conv[2] = DIGIMOD(xx); - conv[3] = '\0'; - return conv; -} - -// Convert unsigned int to lj string with 123 format -char* itostr3left(const int& xx) { - if (xx >= 100) { - conv[0] = DIGIMOD(xx / 100); - conv[1] = DIGIMOD(xx / 10); - conv[2] = DIGIMOD(xx); - conv[3] = '\0'; - } - else if (xx >= 10) { - conv[0] = DIGIMOD(xx / 10); - conv[1] = DIGIMOD(xx); - conv[2] = '\0'; - } - else { - conv[0] = DIGIMOD(xx); - conv[1] = '\0'; - } - return conv; -} - -// Convert signed int to rj string with _123, -123, _-12, or __-1 format -char *itostr4sign(const int& x) { - int xx = abs(x); - int sign = 0; - if (xx >= 100) { - conv[1] = DIGIMOD(xx / 100); - conv[2] = DIGIMOD(xx / 10); - } - else if (xx >= 10) { - conv[0] = ' '; - sign = 1; - conv[2] = DIGIMOD(xx / 10); - } - else { - conv[0] = ' '; - conv[1] = ' '; - sign = 2; - } - conv[sign] = x < 0 ? '-' : ' '; - conv[3] = DIGIMOD(xx); - conv[4] = '\0'; - return conv; -} - -// Convert unsigned float to rj string with 12345 format -char* ftostr5rj(const float& x) { - long xx = abs(x); - conv[0] = xx >= 10000 ? DIGIMOD(xx / 10000) : ' '; - conv[1] = xx >= 1000 ? DIGIMOD(xx / 1000) : ' '; - conv[2] = xx >= 100 ? DIGIMOD(xx / 100) : ' '; - conv[3] = xx >= 10 ? DIGIMOD(xx / 10) : ' '; - conv[4] = DIGIMOD(xx); - conv[5] = '\0'; - return conv; -} - -// Convert signed float to string with +1234.5 format -char* ftostr51sign(const float& x) { - long xx = abs(x * 10); - conv[0] = (x >= 0) ? '+' : '-'; - conv[1] = DIGIMOD(xx / 10000); - conv[2] = DIGIMOD(xx / 1000); - conv[3] = DIGIMOD(xx / 100); - conv[4] = DIGIMOD(xx / 10); - conv[5] = '.'; - conv[6] = DIGIMOD(xx); - conv[7] = '\0'; - return conv; -} - -// Convert signed float to string with +123.45 format -char* ftostr52sign(const float& x) { - long xx = abs(x * 100); - conv[0] = (x >= 0) ? '+' : '-'; - conv[1] = DIGIMOD(xx / 10000); - conv[2] = DIGIMOD(xx / 1000); - conv[3] = DIGIMOD(xx / 100); - conv[4] = '.'; - conv[5] = DIGIMOD(xx / 10); - conv[6] = DIGIMOD(xx); - conv[7] = '\0'; - return conv; -} - -// Convert signed float to space-padded string with -_23.4_ format -char* ftostr52sp(const float& x) { - long xx = x * 100; - uint8_t dig; - if (xx < 0) { // negative val = -_0 - xx = -xx; - conv[0] = '-'; - dig = (xx / 1000) % 10; - conv[1] = dig ? DIGIT(dig) : ' '; - } - else { // positive val = __0 - dig = (xx / 10000) % 10; - if (dig) { - conv[0] = DIGIT(dig); - conv[1] = DIGIMOD(xx / 1000); - } - else { - conv[0] = ' '; - dig = (xx / 1000) % 10; - conv[1] = dig ? DIGIT(dig) : ' '; - } - } - - conv[2] = DIGIMOD(xx / 100); // lsd always - - dig = xx % 10; - if (dig) { // 2 decimal places - conv[5] = DIGIT(dig); - conv[4] = DIGIMOD(xx / 10); - conv[3] = '.'; - } - else { // 1 or 0 decimal place - dig = (xx / 10) % 10; - if (dig) { - conv[4] = DIGIT(dig); - conv[3] = '.'; - } - else { - conv[3] = conv[4] = ' '; - } - conv[5] = ' '; - } - conv[6] = '\0'; - return conv; -} - #endif // ULTRA_LCD diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index 4cc8334ec..3652da005 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -167,21 +167,4 @@ #endif //ULTRA_LCD -char* itostr2(const uint8_t& x); -char* itostr3sign(const int& x); -char* itostr3(const int& x); -char* itostr3left(const int& x); -char* itostr4sign(const int& x); - -char* ftostr3(const float& x); -char* ftostr4sign(const float& x); -char* ftostr41sign(const float& x); -char* ftostr32(const float& x); -char* ftostr43sign(const float& x, char plus=' '); -char* ftostr12ns(const float& x); -char* ftostr5rj(const float& x); -char* ftostr51sign(const float& x); -char* ftostr52sign(const float& x); -char* ftostr52sp(const float& x); // remove zero-padding from ftostr32 - #endif //ULTRALCD_H diff --git a/Marlin/ultralcd_impl_DOGM.h b/Marlin/ultralcd_impl_DOGM.h index c5353a605..8defa9480 100644 --- a/Marlin/ultralcd_impl_DOGM.h +++ b/Marlin/ultralcd_impl_DOGM.h @@ -45,6 +45,7 @@ #include "ultralcd.h" #include "ultralcd_st7920_u8glib_rrd.h" #include "dogm_bitmaps.h" +#include "utility.h" #include "duration_t.h" #include @@ -200,26 +201,20 @@ char lcd_print(char c) { } char lcd_print(const char* str) { - char c; int i = 0; - char n = 0; - while ((c = str[i++])) { - n += lcd_print(c); - } + char c, n = 0; + while ((c = str[i++])) n += lcd_print(c); return n; } -/* Arduino < 1.0.0 is missing a function to print PROGMEM strings, so we need to implement our own */ +// Needed for Arduino < 1.0.0 char lcd_printPGM(const char* str) { - char c; - char n = 0; - while ((c = pgm_read_byte(str++))) { - n += lcd_print(c); - } + char c, n = 0; + while ((c = pgm_read_byte(str++))) n += lcd_print(c); return n; } -/* Warning: This function is called from interrupt context */ +// Initialize or re-initializw the LCD static void lcd_implementation_init() { #if defined(LCD_PIN_BL) && LCD_PIN_BL > -1 // Enable LCD backlight @@ -290,6 +285,7 @@ static void lcd_implementation_init() { #endif // SHOW_BOOTSCREEN } +// The kill screen is displayed for unrecoverable conditions void lcd_kill_screen() { lcd_setFont(FONT_MENU); u8g.setPrintPos(0, u8g.getHeight()/4*1); @@ -302,6 +298,10 @@ void lcd_kill_screen() { static void lcd_implementation_clear() { } // Automatically cleared by Picture Loop +// +// Status Screen +// + FORCE_INLINE void _draw_centered_temp(int temp, int x, int y) { int degsize = 6 * (temp >= 100 ? 3 : temp >= 10 ? 2 : 1); // number's pixel width u8g.setPrintPos(x - (18 - degsize) / 2, y); // move left if shorter @@ -472,164 +472,173 @@ static void lcd_implementation_status_screen() { #endif } -static void lcd_implementation_mark_as_selected(uint8_t row, bool isSelected) { - if (isSelected) { - u8g.setColorIndex(1); // black on white - u8g.drawBox(0, row * (DOG_CHAR_HEIGHT) + 3 - (TALL_FONT_CORRECTION), LCD_PIXEL_WIDTH, DOG_CHAR_HEIGHT); - u8g.setColorIndex(0); // following text must be white on black - } - else { - u8g.setColorIndex(1); // unmarked text is black on white - } - u8g.setPrintPos((START_COL) * (DOG_CHAR_WIDTH), (row + 1) * (DOG_CHAR_HEIGHT)); -} +#if ENABLED(ULTIPANEL) -#if ENABLED(LCD_INFO_MENU) || ENABLED(FILAMENT_CHANGE_FEATURE) - - static void lcd_implementation_drawmenu_static(uint8_t row, const char* pstr, bool center=true, bool invert=false, const char* valstr=NULL) { - - lcd_implementation_mark_as_selected(row, invert); - - char c; - int8_t n = LCD_WIDTH - (START_COL); - - if (center && !valstr) { - int8_t pad = (LCD_WIDTH - lcd_strlen_P(pstr)) / 2; - while (--pad >= 0) { lcd_print(' '); n--; } - } - while (n > 0 && (c = pgm_read_byte(pstr))) { - n -= lcd_print(c); - pstr++; - } - if (valstr) while (n > 0 && (c = *valstr)) { - n -= lcd_print(c); - valstr++; - } - while (n-- > 0) lcd_print(' '); - } - -#endif // LCD_INFO_MENU || FILAMENT_CHANGE_FEATURE - -static void lcd_implementation_drawmenu_generic(bool isSelected, uint8_t row, const char* pstr, char pre_char, char post_char) { - UNUSED(pre_char); - - char c; - uint8_t n = LCD_WIDTH - (START_COL) - 2; - - lcd_implementation_mark_as_selected(row, isSelected); - - while (c = pgm_read_byte(pstr)) { - n -= lcd_print(c); - pstr++; - } - while (n--) lcd_print(' '); - u8g.setPrintPos(LCD_PIXEL_WIDTH - (DOG_CHAR_WIDTH), (row + 1) * (DOG_CHAR_HEIGHT)); - lcd_print(post_char); - lcd_print(' '); -} - -static void _drawmenu_setting_edit_generic(bool isSelected, uint8_t row, const char* pstr, const char* data, bool pgm) { - char c; - uint8_t vallen = (pgm ? lcd_strlen_P(data) : (lcd_strlen((char*)data))); - uint8_t n = LCD_WIDTH - (START_COL) - 2 - vallen; - - lcd_implementation_mark_as_selected(row, isSelected); - - while (c = pgm_read_byte(pstr)) { - n -= lcd_print(c); - pstr++; - } - lcd_print(':'); - while (n--) lcd_print(' '); - u8g.setPrintPos(LCD_PIXEL_WIDTH - (DOG_CHAR_WIDTH) * vallen, (row + 1) * (DOG_CHAR_HEIGHT)); - if (pgm) lcd_printPGM(data); else lcd_print((char*)data); -} - -#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 lcd_implementation_drawmenu_setting_edit_int3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, itostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float32(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr32(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float43(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr43sign(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5rj(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float52(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr52sign(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float51(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr51sign(*(data))) -#define lcd_implementation_drawmenu_setting_edit_long5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5rj(*(data))) -#define lcd_implementation_drawmenu_setting_edit_bool(sel, row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) - -//Add version for callback functions -#define lcd_implementation_drawmenu_setting_edit_callback_int3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, itostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float32(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr32(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float43(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr43sign(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5rj(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float52(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr52sign(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float51(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr51sign(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_long5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5rj(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_bool(sel, row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) - -void lcd_implementation_drawedit(const char* pstr, const char* value=NULL) { - uint8_t rows = 1; - uint8_t lcd_width = LCD_WIDTH - (START_COL), char_width = DOG_CHAR_WIDTH; - uint8_t vallen = lcd_strlen(value); - - #if ENABLED(USE_BIG_EDIT_FONT) - if (lcd_strlen_P(pstr) <= LCD_WIDTH_EDIT - 1) { - lcd_setFont(FONT_MENU_EDIT); - lcd_width = LCD_WIDTH_EDIT + 1; - char_width = DOG_CHAR_WIDTH_EDIT; - if (lcd_strlen_P(pstr) >= LCD_WIDTH_EDIT - vallen) rows = 2; + // Set the colors for a menu item based on whether it is selected + static void lcd_implementation_mark_as_selected(uint8_t row, bool isSelected) { + if (isSelected) { + u8g.setColorIndex(1); // black on white + u8g.drawBox(0, row * (DOG_CHAR_HEIGHT) + 3 - (TALL_FONT_CORRECTION), LCD_PIXEL_WIDTH, DOG_CHAR_HEIGHT); + u8g.setColorIndex(0); // following text must be white on black } else { - lcd_setFont(FONT_MENU); + u8g.setColorIndex(1); // unmarked text is black on white } - #endif - - if (lcd_strlen_P(pstr) > LCD_WIDTH - 2 - vallen) rows = 2; - - const float kHalfChar = (DOG_CHAR_HEIGHT_EDIT) / 2; - float rowHeight = u8g.getHeight() / (rows + 1); // 1/(rows+1) = 1/2 or 1/3 - - u8g.setPrintPos(0, rowHeight + kHalfChar); - lcd_printPGM(pstr); - if (value != NULL) { - lcd_print(':'); - u8g.setPrintPos((lcd_width - 1 - vallen) * char_width, rows * rowHeight + kHalfChar); - lcd_print(value); + u8g.setPrintPos((START_COL) * (DOG_CHAR_WIDTH), (row + 1) * (DOG_CHAR_HEIGHT)); } -} -#if ENABLED(SDSUPPORT) + #if ENABLED(LCD_INFO_MENU) || ENABLED(FILAMENT_CHANGE_FEATURE) - static void _drawmenu_sd(bool isSelected, uint8_t row, const char* pstr, const char* filename, char* const longFilename, bool isDir) { - UNUSED(pstr); - char c; - uint8_t n = LCD_WIDTH - (START_COL) - 1; + // Draw a static line of text in the same idiom as a menu item + static void lcd_implementation_drawmenu_static(uint8_t row, const char* pstr, bool center=true, bool invert=false, const char* valstr=NULL) { - if (longFilename[0]) { - filename = longFilename; - longFilename[n] = '\0'; + lcd_implementation_mark_as_selected(row, invert); + + char c; + int8_t n = LCD_WIDTH - (START_COL); + + if (center && !valstr) { + int8_t pad = (LCD_WIDTH - lcd_strlen_P(pstr)) / 2; + while (--pad >= 0) { lcd_print(' '); n--; } + } + while (n > 0 && (c = pgm_read_byte(pstr))) { + n -= lcd_print(c); + pstr++; + } + if (valstr) while (n > 0 && (c = *valstr)) { + n -= lcd_print(c); + valstr++; + } + while (n-- > 0) lcd_print(' '); } + #endif // LCD_INFO_MENU || FILAMENT_CHANGE_FEATURE + + // Draw a generic menu item + static void lcd_implementation_drawmenu_generic(bool isSelected, uint8_t row, const char* pstr, char pre_char, char post_char) { + UNUSED(pre_char); + + char c; + uint8_t n = LCD_WIDTH - (START_COL) - 2; + lcd_implementation_mark_as_selected(row, isSelected); - if (isDir) lcd_print(LCD_STR_FOLDER[0]); - while ((c = *filename)) { + while (c = pgm_read_byte(pstr)) { n -= lcd_print(c); - filename++; + pstr++; } while (n--) lcd_print(' '); + u8g.setPrintPos(LCD_PIXEL_WIDTH - (DOG_CHAR_WIDTH), (row + 1) * (DOG_CHAR_HEIGHT)); + lcd_print(post_char); + lcd_print(' '); } - #define lcd_implementation_drawmenu_sdfile(sel, row, pstr, filename, longFilename) _drawmenu_sd(sel, row, pstr, filename, longFilename, false) - #define lcd_implementation_drawmenu_sddirectory(sel, row, pstr, filename, longFilename) _drawmenu_sd(sel, row, pstr, filename, longFilename, true) + // Macros for specific types of menu items + #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_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, '>', ' ') -#endif //SDSUPPORT + // Draw a menu item with an editable value + static void _drawmenu_setting_edit_generic(bool isSelected, uint8_t row, const char* pstr, const char* data, bool pgm) { + char c; + uint8_t vallen = (pgm ? lcd_strlen_P(data) : (lcd_strlen((char*)data))); + uint8_t n = LCD_WIDTH - (START_COL) - 2 - vallen; -#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_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, '>', ' ') + lcd_implementation_mark_as_selected(row, isSelected); + + while (c = pgm_read_byte(pstr)) { + n -= lcd_print(c); + pstr++; + } + lcd_print(':'); + while (n--) lcd_print(' '); + u8g.setPrintPos(LCD_PIXEL_WIDTH - (DOG_CHAR_WIDTH) * vallen, (row + 1) * (DOG_CHAR_HEIGHT)); + if (pgm) lcd_printPGM(data); else lcd_print((char*)data); + } + + // Macros for edit items + #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 lcd_implementation_drawmenu_setting_edit_int3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, itostr3(*(data))) + #define lcd_implementation_drawmenu_setting_edit_float3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr3(*(data))) + #define lcd_implementation_drawmenu_setting_edit_float32(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr32(*(data))) + #define lcd_implementation_drawmenu_setting_edit_float43(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr43sign(*(data))) + #define lcd_implementation_drawmenu_setting_edit_float5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5rj(*(data))) + #define lcd_implementation_drawmenu_setting_edit_float52(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr52sign(*(data))) + #define lcd_implementation_drawmenu_setting_edit_float51(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr51sign(*(data))) + #define lcd_implementation_drawmenu_setting_edit_long5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5rj(*(data))) + #define lcd_implementation_drawmenu_setting_edit_bool(sel, row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) + + #define lcd_implementation_drawmenu_setting_edit_callback_int3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, itostr3(*(data))) + #define lcd_implementation_drawmenu_setting_edit_callback_float3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr3(*(data))) + #define lcd_implementation_drawmenu_setting_edit_callback_float32(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr32(*(data))) + #define lcd_implementation_drawmenu_setting_edit_callback_float43(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr43sign(*(data))) + #define lcd_implementation_drawmenu_setting_edit_callback_float5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5rj(*(data))) + #define lcd_implementation_drawmenu_setting_edit_callback_float52(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr52sign(*(data))) + #define lcd_implementation_drawmenu_setting_edit_callback_float51(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr51sign(*(data))) + #define lcd_implementation_drawmenu_setting_edit_callback_long5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5rj(*(data))) + #define lcd_implementation_drawmenu_setting_edit_callback_bool(sel, row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) + + void lcd_implementation_drawedit(const char* pstr, const char* value=NULL) { + uint8_t rows = 1; + uint8_t lcd_width = LCD_WIDTH - (START_COL), char_width = DOG_CHAR_WIDTH; + uint8_t vallen = lcd_strlen(value); + + #if ENABLED(USE_BIG_EDIT_FONT) + if (lcd_strlen_P(pstr) <= LCD_WIDTH_EDIT - 1) { + lcd_setFont(FONT_MENU_EDIT); + lcd_width = LCD_WIDTH_EDIT + 1; + char_width = DOG_CHAR_WIDTH_EDIT; + if (lcd_strlen_P(pstr) >= LCD_WIDTH_EDIT - vallen) rows = 2; + } + else { + lcd_setFont(FONT_MENU); + } + #endif + + if (lcd_strlen_P(pstr) > LCD_WIDTH - 2 - vallen) rows = 2; + + const float kHalfChar = (DOG_CHAR_HEIGHT_EDIT) / 2; + float rowHeight = u8g.getHeight() / (rows + 1); // 1/(rows+1) = 1/2 or 1/3 + + u8g.setPrintPos(0, rowHeight + kHalfChar); + lcd_printPGM(pstr); + if (value != NULL) { + lcd_print(':'); + u8g.setPrintPos((lcd_width - 1 - vallen) * char_width, rows * rowHeight + kHalfChar); + lcd_print(value); + } + } + + #if ENABLED(SDSUPPORT) + + static void _drawmenu_sd(bool isSelected, uint8_t row, const char* pstr, const char* filename, char* const longFilename, bool isDir) { + UNUSED(pstr); + char c; + uint8_t n = LCD_WIDTH - (START_COL) - 1; + + if (longFilename[0]) { + filename = longFilename; + longFilename[n] = '\0'; + } + + lcd_implementation_mark_as_selected(row, isSelected); + + if (isDir) lcd_print(LCD_STR_FOLDER[0]); + while ((c = *filename)) { + n -= lcd_print(c); + filename++; + } + while (n--) lcd_print(' '); + } + + #define lcd_implementation_drawmenu_sdfile(sel, row, pstr, filename, longFilename) _drawmenu_sd(sel, row, pstr, filename, longFilename, false) + #define lcd_implementation_drawmenu_sddirectory(sel, row, pstr, filename, longFilename) _drawmenu_sd(sel, row, pstr, filename, longFilename, true) + + #endif // SDSUPPORT + +#endif // ULTIPANEL #endif //__ULTRALCD_IMPL_DOGM_H diff --git a/Marlin/ultralcd_impl_HD44780.h b/Marlin/ultralcd_impl_HD44780.h index 05a892be7..44d0bb977 100644 --- a/Marlin/ultralcd_impl_HD44780.h +++ b/Marlin/ultralcd_impl_HD44780.h @@ -24,9 +24,11 @@ #define ULTRALCD_IMPL_HD44780_H /** -* Implementation of the LCD display routines for a Hitachi HD44780 display. These are common LCD character displays. -**/ + * Implementation of the LCD display routines for a Hitachi HD44780 display. + * These are the most common LCD character displays. + */ +#include "utility.h" #include "duration_t.h" extern volatile uint8_t buttons; //an extended version of the last checked buttons in a bit array. @@ -787,135 +789,158 @@ static void lcd_implementation_status_screen() { lcd_print(lcd_status_message); } -#if ENABLED(LCD_INFO_MENU) || ENABLED(FILAMENT_CHANGE_FEATURE) +#if ENABLED(ULTIPANEL) - static void lcd_implementation_drawmenu_static(uint8_t row, const char* pstr, bool center=true, bool invert=false, const char *valstr=NULL) { - UNUSED(invert); - char c; - int8_t n = LCD_WIDTH; - lcd.setCursor(0, row); - if (center && !valstr) { - int8_t pad = (LCD_WIDTH - lcd_strlen_P(pstr)) / 2; - while (--pad >= 0) { lcd.print(' '); n--; } + #if ENABLED(LCD_INFO_MENU) || ENABLED(FILAMENT_CHANGE_FEATURE) + + static void lcd_implementation_drawmenu_static(uint8_t row, const char* pstr, bool center=true, bool invert=false, const char *valstr=NULL) { + UNUSED(invert); + char c; + int8_t n = LCD_WIDTH; + lcd.setCursor(0, row); + if (center && !valstr) { + int8_t pad = (LCD_WIDTH - lcd_strlen_P(pstr)) / 2; + while (--pad >= 0) { lcd.print(' '); n--; } + } + while (n > 0 && (c = pgm_read_byte(pstr))) { + n -= lcd_print(c); + pstr++; + } + if (valstr) while (n > 0 && (c = *valstr)) { + n -= lcd_print(c); + valstr++; + } + while (n-- > 0) lcd.print(' '); } - while (n > 0 && (c = pgm_read_byte(pstr))) { + + #endif // LCD_INFO_MENU || FILAMENT_CHANGE_FEATURE + + static void lcd_implementation_drawmenu_generic(bool sel, uint8_t row, const char* pstr, char pre_char, char post_char) { + char c; + uint8_t n = LCD_WIDTH - 2; + lcd.setCursor(0, row); + lcd.print(sel ? pre_char : ' '); + while ((c = pgm_read_byte(pstr)) && n > 0) { n -= lcd_print(c); pstr++; } - if (valstr) while (n > 0 && (c = *valstr)) { - n -= lcd_print(c); - valstr++; - } - while (n-- > 0) lcd.print(' '); - } - -#endif // LCD_INFO_MENU || FILAMENT_CHANGE_FEATURE - -static void lcd_implementation_drawmenu_generic(bool sel, uint8_t row, const char* pstr, char pre_char, char post_char) { - char c; - uint8_t n = LCD_WIDTH - 2; - lcd.setCursor(0, row); - lcd.print(sel ? pre_char : ' '); - while ((c = pgm_read_byte(pstr)) && n > 0) { - n -= lcd_print(c); - pstr++; - } - while (n--) lcd.print(' '); - lcd.print(post_char); -} - -static void lcd_implementation_drawmenu_setting_edit_generic(bool sel, uint8_t row, const char* pstr, char pre_char, char* data) { - char c; - uint8_t n = LCD_WIDTH - 2 - lcd_strlen(data); - lcd.setCursor(0, row); - lcd.print(sel ? pre_char : ' '); - while ((c = pgm_read_byte(pstr)) && n > 0) { - n -= lcd_print(c); - pstr++; - } - lcd.print(':'); - while (n--) lcd.print(' '); - lcd_print(data); -} -static void lcd_implementation_drawmenu_setting_edit_generic_P(bool sel, uint8_t row, const char* pstr, char pre_char, const char* data) { - char c; - uint8_t n = LCD_WIDTH - 2 - lcd_strlen_P(data); - lcd.setCursor(0, row); - lcd.print(sel ? pre_char : ' '); - while ((c = pgm_read_byte(pstr)) && n > 0) { - n -= lcd_print(c); - pstr++; - } - lcd.print(':'); - while (n--) lcd.print(' '); - lcd_printPGM(data); -} - -#define lcd_implementation_drawmenu_setting_edit_int3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', itostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float32(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr32(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float43(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr43sign(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5rj(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float52(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr52sign(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float51(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr51sign(*(data))) -#define lcd_implementation_drawmenu_setting_edit_long5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5rj(*(data))) -#define lcd_implementation_drawmenu_setting_edit_bool(sel, row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) - -//Add version for callback functions -#define lcd_implementation_drawmenu_setting_edit_callback_int3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', itostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float32(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr32(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float43(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr43sign(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5rj(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float52(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr52sign(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float51(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr51sign(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_long5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5rj(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_bool(sel, row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) - -void lcd_implementation_drawedit(const char* pstr, const char* value=NULL) { - lcd.setCursor(1, 1); - lcd_printPGM(pstr); - if (value != NULL) { - lcd.print(':'); - lcd.setCursor(LCD_WIDTH - lcd_strlen(value), 1); - lcd_print(value); - } -} - -#if ENABLED(SDSUPPORT) - - static void lcd_implementation_drawmenu_sd(bool sel, uint8_t row, const char* pstr, const char* filename, char* longFilename, uint8_t concat, char post_char) { - UNUSED(pstr); - char c; - uint8_t n = LCD_WIDTH - concat; - lcd.setCursor(0, row); - lcd.print(sel ? '>' : ' '); - if (longFilename[0]) { - filename = longFilename; - longFilename[n] = '\0'; - } - while ((c = *filename) && n > 0) { - n -= lcd_print(c); - filename++; - } while (n--) lcd.print(' '); lcd.print(post_char); } - static void lcd_implementation_drawmenu_sdfile(bool sel, uint8_t row, const char* pstr, const char* filename, char* longFilename) { - lcd_implementation_drawmenu_sd(sel, row, pstr, filename, longFilename, 2, ' '); + static void lcd_implementation_drawmenu_setting_edit_generic(bool sel, uint8_t row, const char* pstr, char pre_char, char* data) { + char c; + uint8_t n = LCD_WIDTH - 2 - lcd_strlen(data); + lcd.setCursor(0, row); + lcd.print(sel ? pre_char : ' '); + while ((c = pgm_read_byte(pstr)) && n > 0) { + n -= lcd_print(c); + pstr++; + } + lcd.print(':'); + while (n--) lcd.print(' '); + lcd_print(data); + } + static void lcd_implementation_drawmenu_setting_edit_generic_P(bool sel, uint8_t row, const char* pstr, char pre_char, const char* data) { + char c; + uint8_t n = LCD_WIDTH - 2 - lcd_strlen_P(data); + lcd.setCursor(0, row); + lcd.print(sel ? pre_char : ' '); + while ((c = pgm_read_byte(pstr)) && n > 0) { + n -= lcd_print(c); + pstr++; + } + lcd.print(':'); + while (n--) lcd.print(' '); + lcd_printPGM(data); } - static void lcd_implementation_drawmenu_sddirectory(bool sel, uint8_t row, const char* pstr, const char* filename, char* longFilename) { - lcd_implementation_drawmenu_sd(sel, row, pstr, filename, longFilename, 2, LCD_STR_FOLDER[0]); + #define lcd_implementation_drawmenu_setting_edit_int3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', itostr3(*(data))) + #define lcd_implementation_drawmenu_setting_edit_float3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr3(*(data))) + #define lcd_implementation_drawmenu_setting_edit_float32(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr32(*(data))) + #define lcd_implementation_drawmenu_setting_edit_float43(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr43sign(*(data))) + #define lcd_implementation_drawmenu_setting_edit_float5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5rj(*(data))) + #define lcd_implementation_drawmenu_setting_edit_float52(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr52sign(*(data))) + #define lcd_implementation_drawmenu_setting_edit_float51(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr51sign(*(data))) + #define lcd_implementation_drawmenu_setting_edit_long5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5rj(*(data))) + #define lcd_implementation_drawmenu_setting_edit_bool(sel, row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) + + //Add version for callback functions + #define lcd_implementation_drawmenu_setting_edit_callback_int3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', itostr3(*(data))) + #define lcd_implementation_drawmenu_setting_edit_callback_float3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr3(*(data))) + #define lcd_implementation_drawmenu_setting_edit_callback_float32(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr32(*(data))) + #define lcd_implementation_drawmenu_setting_edit_callback_float43(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr43sign(*(data))) + #define lcd_implementation_drawmenu_setting_edit_callback_float5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5rj(*(data))) + #define lcd_implementation_drawmenu_setting_edit_callback_float52(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr52sign(*(data))) + #define lcd_implementation_drawmenu_setting_edit_callback_float51(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr51sign(*(data))) + #define lcd_implementation_drawmenu_setting_edit_callback_long5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5rj(*(data))) + #define lcd_implementation_drawmenu_setting_edit_callback_bool(sel, row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) + + void lcd_implementation_drawedit(const char* pstr, const char* value=NULL) { + lcd.setCursor(1, 1); + lcd_printPGM(pstr); + if (value != NULL) { + lcd.print(':'); + lcd.setCursor(LCD_WIDTH - lcd_strlen(value), 1); + lcd_print(value); + } } -#endif //SDSUPPORT + #if ENABLED(SDSUPPORT) -#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_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, '>', ' ') + static void lcd_implementation_drawmenu_sd(bool sel, uint8_t row, const char* pstr, const char* filename, char* longFilename, uint8_t concat, char post_char) { + UNUSED(pstr); + char c; + uint8_t n = LCD_WIDTH - concat; + lcd.setCursor(0, row); + lcd.print(sel ? '>' : ' '); + if (longFilename[0]) { + filename = longFilename; + longFilename[n] = '\0'; + } + while ((c = *filename) && n > 0) { + n -= lcd_print(c); + filename++; + } + while (n--) lcd.print(' '); + lcd.print(post_char); + } + + static void lcd_implementation_drawmenu_sdfile(bool sel, uint8_t row, const char* pstr, const char* filename, char* longFilename) { + lcd_implementation_drawmenu_sd(sel, row, pstr, filename, longFilename, 2, ' '); + } + + static void lcd_implementation_drawmenu_sddirectory(bool sel, uint8_t row, const char* pstr, const char* filename, char* longFilename) { + lcd_implementation_drawmenu_sd(sel, row, pstr, filename, longFilename, 2, LCD_STR_FOLDER[0]); + } + + #endif // SDSUPPORT + + #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_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(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 + +#endif // ULTIPANEL #if ENABLED(LCD_HAS_STATUS_INDICATORS) @@ -955,23 +980,4 @@ void lcd_implementation_drawedit(const char* pstr, const char* value=NULL) { #endif // LCD_HAS_STATUS_INDICATORS -#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 - #endif // ULTRALCD_IMPL_HD44780_H diff --git a/Marlin/utility.cpp b/Marlin/utility.cpp index 0285219c4..b2d09004c 100644 --- a/Marlin/utility.cpp +++ b/Marlin/utility.cpp @@ -32,3 +32,186 @@ void safe_delay(millis_t ms) { } delay(ms); } + +#if ENABLED(ULTRA_LCD) + + char conv[8]; + + #define DIGIT(n) ('0' + (n)) + #define DIGIMOD(n, f) DIGIT((n)/(f) % 10) + #define RJDIGIT(n, f) ((n) >= (f) ? DIGIMOD(n, f) : ' ') + #define MINUSOR(n, alt) (n >= 0 ? (alt) : (n = -n, '-')) + + // Convert unsigned int to string with 12 format + char* itostr2(const uint8_t& x) { + int xx = x; + conv[0] = DIGIMOD(xx, 10); + conv[1] = DIGIMOD(xx, 1); + conv[2] = '\0'; + return conv; + } + + // Convert signed int to rj string with 123 or -12 format + char* itostr3(const int& x) { + int xx = x; + conv[0] = MINUSOR(xx, RJDIGIT(xx, 100)); + conv[1] = RJDIGIT(xx, 10); + conv[2] = DIGIMOD(xx, 1); + conv[3] = '\0'; + return conv; + } + + // Convert unsigned int to lj string with 123 format + char* itostr3left(const int& xx) { + char *str = &conv[3]; + *str = '\0'; + *(--str) = DIGIMOD(xx, 1); + if (xx >= 10) { + *(--str) = DIGIMOD(xx, 10); + if (xx >= 100) + *(--str) = DIGIMOD(xx, 100); + } + return str; + } + + // Convert signed int to rj string with _123, -123, _-12, or __-1 format + char *itostr4sign(const int& x) { + int xx = abs(x), sign = 0; + if (xx >= 100) { + conv[1] = DIGIMOD(xx, 100); + conv[2] = DIGIMOD(xx, 10); + } + else { + conv[0] = ' '; + if (xx >= 10) { + sign = 1; + conv[2] = DIGIMOD(xx, 10); + } + else { + conv[1] = ' '; + sign = 2; + } + } + conv[sign] = x < 0 ? '-' : ' '; + conv[3] = DIGIMOD(xx, 1); + conv[4] = '\0'; + return conv; + } + + // Convert unsigned float to string with 1.23 format + char* ftostr12ns(const float& x) { + long xx = abs(x * 100); + conv[0] = DIGIMOD(xx, 100); + conv[1] = '.'; + conv[2] = DIGIMOD(xx, 10); + conv[3] = DIGIMOD(xx, 1); + conv[4] = '\0'; + return conv; + } + + // Convert signed float to fixed-length string with 023.45 / -23.45 format + char *ftostr32(const float& x) { + long xx = x * 100; + conv[0] = MINUSOR(xx, DIGIMOD(xx, 10000)); + conv[1] = DIGIMOD(xx, 1000); + conv[2] = DIGIMOD(xx, 100); + conv[3] = '.'; + conv[4] = DIGIMOD(xx, 10); + conv[5] = DIGIMOD(xx, 1); + conv[6] = '\0'; + return conv; + } + + // Convert float to fixed-length string with +123.4 / -123.4 format + char* ftostr41sign(const float& x) { + int xx = x * 10; + conv[0] = MINUSOR(xx, '+'); + conv[1] = DIGIMOD(xx, 1000); + conv[2] = DIGIMOD(xx, 100); + conv[3] = DIGIMOD(xx, 10); + conv[4] = '.'; + conv[5] = DIGIMOD(xx, 1); + conv[6] = '\0'; + return conv; + } + + // Convert signed float to string (6 digit) with -1.234 / _0.000 / +1.234 format + char* ftostr43sign(const float& x, char plus/*=' '*/) { + long xx = x * 1000; + conv[0] = xx ? MINUSOR(xx, plus) : ' '; + conv[1] = DIGIMOD(xx, 1000); + conv[2] = '.'; + conv[3] = DIGIMOD(xx, 100); + conv[4] = DIGIMOD(xx, 10); + conv[5] = DIGIMOD(xx, 1); + conv[6] = '\0'; + return conv; + } + + // Convert unsigned float to rj string with 12345 format + char* ftostr5rj(const float& x) { + long xx = abs(x); + conv[0] = RJDIGIT(xx, 10000); + conv[1] = RJDIGIT(xx, 1000); + conv[2] = RJDIGIT(xx, 100); + conv[3] = RJDIGIT(xx, 10); + conv[4] = DIGIMOD(xx, 1); + conv[5] = '\0'; + return conv; + } + + // Convert signed float to string with +1234.5 format + char* ftostr51sign(const float& x) { + long xx = x * 10; + conv[0] = MINUSOR(xx, '+'); + conv[1] = DIGIMOD(xx, 10000); + conv[2] = DIGIMOD(xx, 1000); + conv[3] = DIGIMOD(xx, 100); + conv[4] = DIGIMOD(xx, 10); + conv[5] = '.'; + conv[6] = DIGIMOD(xx, 1); + conv[7] = '\0'; + return conv; + } + + // Convert signed float to string with +123.45 format + char* ftostr52sign(const float& x) { + long xx = x * 100; + conv[0] = MINUSOR(xx, '+'); + conv[1] = DIGIMOD(xx, 10000); + conv[2] = DIGIMOD(xx, 1000); + conv[3] = DIGIMOD(xx, 100); + conv[4] = '.'; + conv[5] = DIGIMOD(xx, 10); + conv[6] = DIGIMOD(xx, 1); + conv[7] = '\0'; + return conv; + } + + // Convert signed float to space-padded string with -_23.4_ format + char* ftostr52sp(const float& x) { + long xx = x * 100; + uint8_t dig; + conv[0] = MINUSOR(xx, RJDIGIT(xx, 10000)); + conv[1] = RJDIGIT(xx, 1000); + conv[2] = DIGIMOD(xx, 100); + + if ((dig = xx % 10)) { // second digit after decimal point? + conv[3] = '.'; + conv[4] = DIGIMOD(xx, 10); + conv[5] = DIGIT(dig); + } + else { + if ((dig = (xx / 10) % 10)) { // first digit after decimal point? + conv[3] = '.'; + conv[4] = DIGIT(dig); + } + else // nothing after decimal point + conv[3] = conv[4] = ' '; + conv[5] = ' '; + } + conv[6] = '\0'; + return conv; + } + +#endif // ULTRA_LCD diff --git a/Marlin/utility.h b/Marlin/utility.h index 8ca70dbf8..8b107e7fd 100644 --- a/Marlin/utility.h +++ b/Marlin/utility.h @@ -25,4 +25,50 @@ void safe_delay(millis_t ms); -#endif +#if ENABLED(ULTRA_LCD) + + // Convert unsigned int to string with 12 format + char* itostr2(const uint8_t& x); + + // Convert signed int to rj string with 123 or -12 format + char* itostr3(const int& x); + + // Convert unsigned int to lj string with 123 format + char* itostr3left(const int& xx); + + // Convert signed int to rj string with _123, -123, _-12, or __-1 format + char *itostr4sign(const int& x); + + // Convert unsigned float to string with 1.23 format + char* ftostr12ns(const float& x); + + // Convert signed float to fixed-length string with 023.45 / -23.45 format + char *ftostr32(const float& x); + + // Convert float to fixed-length string with +123.4 / -123.4 format + char* ftostr41sign(const float& x); + + // Convert signed float to string (6 digit) with -1.234 / _0.000 / +1.234 format + char* ftostr43sign(const float& x, char plus=' '); + + // Convert unsigned float to rj string with 12345 format + char* ftostr5rj(const float& x); + + // Convert signed float to string with +1234.5 format + char* ftostr51sign(const float& x); + + // Convert signed float to space-padded string with -_23.4_ format + char* ftostr52sp(const float& x); + + // Convert signed float to string with +123.45 format + char* ftostr52sign(const float& x); + + // Convert float to rj string with 123 or -12 format + FORCE_INLINE char *ftostr3(const float& x) { return itostr3((int)x); } + + // Convert float to rj string with _123, -123, _-12, or __-1 format + FORCE_INLINE char *ftostr4sign(const float& x) { return itostr4sign((int)x); } + +#endif // ULTRA_LCD + +#endif // __UTILITY_H__