1
0
mirror of https://github.com/MarlinFirmware/Marlin.git synced 2024-12-14 06:21:44 +00:00
MarlinFirmware/Marlin/src/lcd/ultralcd_impl_DOGM.h

1080 lines
36 KiB
C
Raw Normal View History

/**
2016-03-24 18:01:20 +00:00
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* ultralcd_impl_DOGM.h
*
* Graphics LCD implementation for 128x64 pixel LCDs by STB for ErikZalm/Marlin
* Demonstrator: http://www.reprap.org/wiki/STB_Electronics
* License: http://opensource.org/licenses/BSD-3-Clause
*
* With the use of:
* u8glib by Oliver Kraus
2016-03-30 05:26:28 +00:00
* https://github.com/olikraus/U8glib_Arduino
* License: http://opensource.org/licenses/BSD-3-Clause
*/
#ifndef ULTRALCD_IMPL_DOGM_H
#define ULTRALCD_IMPL_DOGM_H
2017-09-06 11:28:32 +00:00
#include "../inc/MarlinConfig.h"
/**
* Implementation of the LCD display routines for a DOGM128 graphic display.
* These are common LCD 128x64 pixel graphic displays.
*/
#include "ultralcd.h"
2017-09-06 11:28:32 +00:00
/*
2017-09-06 11:28:32 +00:00
#if ENABLED(U8GLIB_ST7565_64128N)
#include "dogm/ultralcd_st7565_u8glib_VIKI.h"
#elif ENABLED(U8GLIB_ST7920)
#include "dogm/ultralcd_st7920_u8glib_rrd.h"
#endif
*/
2017-09-06 11:28:32 +00:00
#include "dogm/dogm_bitmaps.h"
2017-09-09 05:18:43 +00:00
#if ENABLED(SDSUPPORT)
#include "../libs/duration_t.h"
#endif
#include <U8glib.h>
#include "dogm/HAL_LCD_class_defines.h"
#if ENABLED(AUTO_BED_LEVELING_UBL)
2017-09-08 20:35:25 +00:00
#include "../feature/bedlevel/ubl/ubl.h"
#endif
#if ENABLED(SHOW_BOOTSCREEN) && ENABLED(SHOW_CUSTOM_BOOTSCREEN)
2017-09-06 11:28:32 +00:00
#include "../config/_Bootscreen.h"
#endif
// Only Western languages support big / small fonts
2016-11-26 12:50:25 +00:00
#if DISABLED(DISPLAY_CHARSET_ISO10646_1)
#undef USE_BIG_EDIT_FONT
2016-11-26 12:50:25 +00:00
#undef USE_SMALL_INFOFONT
#endif
#if ENABLED(USE_SMALL_INFOFONT)
2017-09-06 11:28:32 +00:00
#include "dogm/dogm_font_data_6x9_marlin.h"
#define FONT_STATUSMENU_NAME u8g_font_6x9
#else
#define FONT_STATUSMENU_NAME FONT_MENU_NAME
#endif
2017-09-06 11:28:32 +00:00
#include "dogm/dogm_font_data_Marlin_symbols.h" // The Marlin special symbols
#define FONT_SPECIAL_NAME Marlin_symbols
#if DISABLED(SIMULATE_ROMFONT)
#if ENABLED(DISPLAY_CHARSET_ISO10646_1)
2017-09-06 11:28:32 +00:00
#include "dogm/dogm_font_data_ISO10646_1.h"
#define FONT_MENU_NAME ISO10646_1_5x7
#elif ENABLED(DISPLAY_CHARSET_ISO10646_PL)
2017-09-06 11:28:32 +00:00
#include "dogm/dogm_font_data_ISO10646_1_PL.h"
#define FONT_MENU_NAME ISO10646_1_PL_5x7
#elif ENABLED(DISPLAY_CHARSET_ISO10646_5)
2017-09-06 11:28:32 +00:00
#include "dogm/dogm_font_data_ISO10646_5_Cyrillic.h"
#define FONT_MENU_NAME ISO10646_5_Cyrillic_5x7
#elif ENABLED(DISPLAY_CHARSET_ISO10646_KANA)
2017-09-06 11:28:32 +00:00
#include "dogm/dogm_font_data_ISO10646_Kana.h"
#define FONT_MENU_NAME ISO10646_Kana_5x7
2016-07-11 01:59:04 +00:00
#elif ENABLED(DISPLAY_CHARSET_ISO10646_GREEK)
2017-09-06 11:28:32 +00:00
#include "dogm/dogm_font_data_ISO10646_Greek.h"
2016-07-11 01:59:04 +00:00
#define FONT_MENU_NAME ISO10646_Greek_5x7
#elif ENABLED(DISPLAY_CHARSET_ISO10646_CN)
2017-09-06 11:28:32 +00:00
#include "dogm/dogm_font_data_ISO10646_CN.h"
#define FONT_MENU_NAME ISO10646_CN
#define TALL_FONT_CORRECTION 1
2016-11-04 07:33:11 +00:00
#elif ENABLED(DISPLAY_CHARSET_ISO10646_TR)
2017-09-06 11:28:32 +00:00
#include "dogm/dogm_font_data_ISO10646_1_tr.h"
2016-11-04 07:33:11 +00:00
#define FONT_MENU_NAME ISO10646_TR
2017-07-01 12:50:26 +00:00
#elif ENABLED(DISPLAY_CHARSET_ISO10646_CZ)
2017-09-06 11:28:32 +00:00
#include "dogm/dogm_font_data_ISO10646_CZ.h"
2017-07-01 12:50:26 +00:00
#define FONT_MENU_NAME ISO10646_CZ
#elif ENABLED(DISPLAY_CHARSET_ISO10646_SK)
#include "dogm/dogm_font_data_ISO10646_SK.h"
#define FONT_MENU_NAME ISO10646_SK
#else // fall-back
2017-09-06 11:28:32 +00:00
#include "dogm/dogm_font_data_ISO10646_1.h"
#define FONT_MENU_NAME ISO10646_1_5x7
#endif
#else // SIMULATE_ROMFONT
#if DISPLAY_CHARSET_HD44780 == JAPANESE
2017-09-06 11:28:32 +00:00
#include "dogm/dogm_font_data_HD44780_J.h"
#define FONT_MENU_NAME HD44780_J_5x7
#elif DISPLAY_CHARSET_HD44780 == WESTERN
2017-09-06 11:28:32 +00:00
#include "dogm/dogm_font_data_HD44780_W.h"
#define FONT_MENU_NAME HD44780_W_5x7
#elif DISPLAY_CHARSET_HD44780 == CYRILLIC
2017-09-06 11:28:32 +00:00
#include "dogm/dogm_font_data_HD44780_C.h"
#define FONT_MENU_NAME HD44780_C_5x7
#else // fall-back
2017-09-06 11:28:32 +00:00
#include "dogm/dogm_font_data_ISO10646_1.h"
#define FONT_MENU_NAME ISO10646_1_5x7
#endif
#endif // SIMULATE_ROMFONT
//#define FONT_STATUSMENU_NAME FONT_MENU_NAME
#define FONT_STATUSMENU 1
#define FONT_SPECIAL 2
#define FONT_MENU_EDIT 3
#define FONT_MENU 4
// DOGM parameters (size in pixels)
#define DOG_CHAR_WIDTH 6
#define DOG_CHAR_HEIGHT 12
#if ENABLED(USE_BIG_EDIT_FONT)
#define FONT_MENU_EDIT_NAME u8g_font_9x18
#define DOG_CHAR_WIDTH_EDIT 9
#define DOG_CHAR_HEIGHT_EDIT 13
#define LCD_WIDTH_EDIT 14
#else
#define FONT_MENU_EDIT_NAME FONT_MENU_NAME
#define DOG_CHAR_WIDTH_EDIT 6
#define DOG_CHAR_HEIGHT_EDIT 12
#define LCD_WIDTH_EDIT 22
#endif
2015-04-27 10:47:11 +00:00
#ifndef TALL_FONT_CORRECTION
#define TALL_FONT_CORRECTION 0
#endif
2016-07-09 19:06:47 +00:00
#define START_COL 0
// LCD selection
2016-06-21 12:39:10 +00:00
#if ENABLED(REPRAPWORLD_GRAPHICAL_LCD)
2017-11-27 02:18:52 +00:00
#ifdef CPU_32_BIT
U8GLIB_ST7920_128X64_4X u8g(LCD_PINS_D4, LCD_PINS_ENABLE, LCD_PINS_RS); // Original u8glib device. 2 stripes, SW SPI
#else
U8GLIB_ST7920_128X64_4X u8g(LCD_PINS_RS); // 2 stripes, HW SPI (shared with SD card)
#endif
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651) * Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port * Improving the Fast IO port access implementation on Arduino DUE * Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling) * Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it. * Fixing the case where the serial port selected is the USB device * Adding configuration for the Makerparts 3D printer (www.makerparts.net) * Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration * Fine tuned Maximum acceleration for MakerParts printer * Style cleanup * Style cleanup (2) * Style fixes (3) * Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port * Improving the Fast IO port access implementation on Arduino DUE * Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling) * Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it. * Fixing the case where the serial port selected is the USB device * Adding configuration for the Makerparts 3D printer (www.makerparts.net) * Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration * Fine tuned Maximum acceleration for MakerParts printer * Style cleanup * Style changes to u8g_dev_st7920_128_64_sw_spi.cpp * Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles * After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working * Moved comments out of macro, otherwise, token pasting does not properly work sometimes * Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency * Update u8g_dev_st7920_128_64_sw_spi.cpp * Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 23:51:36 +00:00
#elif ENABLED(U8GLIB_ST7920) && defined(__arm__)
// RepRap Discount Full Graphics Smart Controller on an ARM target
U8GLIB_ST7920_128X64_CUSTOM_SW_SPI u8g;
2017-11-10 08:28:53 +00:00
#elif ENABLED(U8GLIB_ST7920)
// RepRap Discount Full Graphics Smart Controller
//U8GLIB_ST7920_128X64_4X u8g(LCD_PINS_RS); // 2 stripes, HW SPI (shared with SD card, on AVR does not use standard LCD adapter)
2017-11-10 08:28:53 +00:00
//U8GLIB_ST7920_128X64_4X u8g(LCD_PINS_D4, LCD_PINS_ENABLE, LCD_PINS_RS); // Original u8glib device. 2 stripes, SW SPI
U8GLIB_ST7920_128X64_RRD u8g(LCD_PINS_D4, LCD_PINS_ENABLE, LCD_PINS_RS); // Number of stripes can be adjusted in ultralcd_st7920_u8glib_rrd.h with PAGE_HEIGHT
2017-11-10 08:28:53 +00:00
// AVR version ignores these pin settings
// HAL version uses these pin settings
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651) * Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port * Improving the Fast IO port access implementation on Arduino DUE * Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling) * Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it. * Fixing the case where the serial port selected is the USB device * Adding configuration for the Makerparts 3D printer (www.makerparts.net) * Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration * Fine tuned Maximum acceleration for MakerParts printer * Style cleanup * Style cleanup (2) * Style fixes (3) * Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port * Improving the Fast IO port access implementation on Arduino DUE * Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling) * Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it. * Fixing the case where the serial port selected is the USB device * Adding configuration for the Makerparts 3D printer (www.makerparts.net) * Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration * Fine tuned Maximum acceleration for MakerParts printer * Style cleanup * Style changes to u8g_dev_st7920_128_64_sw_spi.cpp * Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles * After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working * Moved comments out of macro, otherwise, token pasting does not properly work sometimes * Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency * Update u8g_dev_st7920_128_64_sw_spi.cpp * Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 23:51:36 +00:00
#elif ENABLED(CARTESIO_UI)
2016-07-04 15:32:52 +00:00
// The CartesioUI display
//U8GLIB_DOGM128_2X u8g(DOGLCD_SCK, DOGLCD_MOSI, DOGLCD_CS, DOGLCD_A0); // 4 stripes
U8GLIB_DOGM128_2X u8g(DOGLCD_CS, DOGLCD_A0); // 4 stripes
#elif ENABLED(U8GLIB_LM6059_AF)
// Based on the Adafruit ST7565 (http://www.adafruit.com/products/250)
//U8GLIB_LM6059 u8g(DOGLCD_CS, DOGLCD_A0); // 8 stripes
U8GLIB_LM6059_2X u8g(DOGLCD_CS, DOGLCD_A0); // 4 stripes
2017-08-15 00:34:31 +00:00
#elif ENABLED(U8GLIB_ST7565_64128N)
2017-09-27 09:57:14 +00:00
// The MaKrPanel, Mini Viki, and Viki 2.0, ST7565 controller
//U8GLIB_64128N_2X_HAL u8g(DOGLCD_CS, DOGLCD_A0); // using HW-SPI
U8GLIB_64128N_2X_HAL u8g(DOGLCD_SCK, DOGLCD_MOSI, DOGLCD_CS, DOGLCD_A0); // using SW-SPI
#elif ENABLED(U8GLIB_SSD1306)
// Generic support for SSD1306 OLED I2C LCDs
//U8GLIB_SSD1306_128X64_2X_I2C_2_WIRE u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_FAST); // 4 stripes
U8GLIB_SSD1306_128X64_2X u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_FAST); // 4 stripes
2017-10-09 20:58:02 +00:00
#elif ENABLED(MKS_12864OLED)
// MKS 128x64 (SH1106) OLED I2C LCD
U8GLIB_SH1106_128X64 u8g(DOGLCD_SCK, DOGLCD_MOSI, DOGLCD_CS, DOGLCD_A0); // 8 stripes
//U8GLIB_SH1106_128X64_2X u8g(DOGLCD_SCK, DOGLCD_MOSI, DOGLCD_CS, DOGLCD_A0); // 4 stripes
#elif ENABLED(U8GLIB_SH1106)
// Generic support for SH1106 OLED I2C LCDs
//U8GLIB_SH1106_128X64_2X_I2C_2_WIRE u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_FAST); // 4 stripes
U8GLIB_SH1106_128X64_2X u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_FAST); // 4 stripes
#elif ENABLED(MINIPANEL)
2015-07-23 08:12:19 +00:00
// The MINIPanel display
//U8GLIB_MINI12864 u8g(DOGLCD_CS, DOGLCD_A0); // 8 stripes
U8GLIB_MINI12864_2X u8g(DOGLCD_CS, DOGLCD_A0); // 4 stripes
#else
// for regular DOGM128 display with HW-SPI
//U8GLIB_DOGM128 u8g(DOGLCD_CS, DOGLCD_A0); // HW-SPI Com: CS, A0 // 8 stripes
U8GLIB_DOGM128_2X u8g(DOGLCD_CS, DOGLCD_A0); // HW-SPI Com: CS, A0 // 4 stripes
#endif
#ifndef LCD_PIXEL_WIDTH
#define LCD_PIXEL_WIDTH 128
#endif
#ifndef LCD_PIXEL_HEIGHT
#define LCD_PIXEL_HEIGHT 64
#endif
#include "utf_mapper.h"
uint16_t lcd_contrast; // Initialized by settings.load()
static char currentfont = 0;
// The current graphical page being rendered
u8g_page_t &page = ((u8g_pb_t *)((u8g.getU8g())->dev->dev_mem))->p;
// For selective rendering within a Y range
#define PAGE_UNDER(yb) (u8g.getU8g()->current_page.y0 <= (yb))
#define PAGE_CONTAINS(ya, yb) (PAGE_UNDER(yb) && u8g.getU8g()->current_page.y1 >= (ya))
static void lcd_setFont(const char font_nr) {
switch (font_nr) {
case FONT_STATUSMENU : {u8g.setFont(FONT_STATUSMENU_NAME); currentfont = FONT_STATUSMENU;}; break;
case FONT_MENU : {u8g.setFont(FONT_MENU_NAME); currentfont = FONT_MENU;}; break;
case FONT_SPECIAL : {u8g.setFont(FONT_SPECIAL_NAME); currentfont = FONT_SPECIAL;}; break;
case FONT_MENU_EDIT : {u8g.setFont(FONT_MENU_EDIT_NAME); currentfont = FONT_MENU_EDIT;}; break;
break;
}
}
void lcd_print(const char c) {
2017-03-31 14:00:49 +00:00
if (WITHIN(c, 1, LCD_STR_SPECIAL_MAX)) {
2016-09-02 09:09:34 +00:00
u8g.setFont(FONT_SPECIAL_NAME);
u8g.print(c);
lcd_setFont(currentfont);
}
else charset_mapper(c);
}
char lcd_print_and_count(const char c) {
2017-03-31 14:00:49 +00:00
if (WITHIN(c, 1, LCD_STR_SPECIAL_MAX)) {
u8g.setFont(FONT_SPECIAL_NAME);
u8g.print(c);
lcd_setFont(currentfont);
return 1;
}
2016-09-02 09:09:34 +00:00
else return charset_mapper(c);
}
2017-05-28 16:12:12 +00:00
/**
* Core LCD printing functions
* On DOGM all strings go through a filter for utf
* But only use lcd_print_utf and lcd_printPGM_utf for translated text
*/
2017-06-01 03:08:13 +00:00
void lcd_print(const char *str) { while (*str) lcd_print(*str++); }
void lcd_printPGM(const char *str) { while (const char c = pgm_read_byte(str)) lcd_print(c), ++str; }
2017-05-28 16:12:12 +00:00
2017-06-01 03:08:13 +00:00
void lcd_print_utf(const char *str, uint8_t n=LCD_WIDTH) {
2017-05-28 16:12:12 +00:00
char c;
2017-06-01 03:08:13 +00:00
while (n && (c = *str)) n -= charset_mapper(c), ++str;
}
2017-06-01 03:08:13 +00:00
void lcd_printPGM_utf(const char *str, uint8_t n=LCD_WIDTH) {
2017-05-28 16:12:12 +00:00
char c;
2017-06-01 03:08:13 +00:00
while (n && (c = pgm_read_byte(str))) n -= charset_mapper(c), ++str;
}
2017-07-02 05:35:41 +00:00
#if ENABLED(SHOW_BOOTSCREEN)
#if ENABLED(SHOW_CUSTOM_BOOTSCREEN)
#ifndef CUSTOM_BOOTSCREEN_TIMEOUT
#define CUSTOM_BOOTSCREEN_TIMEOUT 2500
#endif
2017-07-02 05:35:41 +00:00
void lcd_custom_bootscreen() {
u8g.firstPage();
do {
u8g.drawBitmapP(
(128 - (CUSTOM_BOOTSCREEN_BMPWIDTH)) /2,
( 64 - (CUSTOM_BOOTSCREEN_BMPHEIGHT)) /2,
CEILING(CUSTOM_BOOTSCREEN_BMPWIDTH, 8), CUSTOM_BOOTSCREEN_BMPHEIGHT, custom_start_bmp);
} while (u8g.nextPage());
safe_delay(CUSTOM_BOOTSCREEN_TIMEOUT);
2017-07-02 05:35:41 +00:00
}
#endif // SHOW_CUSTOM_BOOTSCREEN
void lcd_bootscreen() {
#if ENABLED(SHOW_CUSTOM_BOOTSCREEN)
lcd_custom_bootscreen();
#endif
#if ENABLED(START_BMPHIGH)
constexpr uint8_t offy = 0;
#else
constexpr uint8_t offy = DOG_CHAR_HEIGHT;
#endif
2017-07-02 05:35:41 +00:00
const uint8_t offx = (u8g.getWidth() - (START_BMPWIDTH)) / 2,
txt1X = (u8g.getWidth() - (sizeof(STRING_SPLASH_LINE1) - 1) * (DOG_CHAR_WIDTH)) / 2;
2017-07-02 05:35:41 +00:00
u8g.firstPage();
do {
u8g.drawBitmapP(offx, offy, START_BMPBYTEWIDTH, START_BMPHEIGHT, start_bmp);
lcd_setFont(FONT_MENU);
#ifndef STRING_SPLASH_LINE2
u8g.drawStr(txt1X, u8g.getHeight() - (DOG_CHAR_HEIGHT), STRING_SPLASH_LINE1);
2017-07-02 05:35:41 +00:00
#else
const uint8_t txt2X = (u8g.getWidth() - (sizeof(STRING_SPLASH_LINE2) - 1) * (DOG_CHAR_WIDTH)) / 2;
u8g.drawStr(txt1X, u8g.getHeight() - (DOG_CHAR_HEIGHT) * 3 / 2, STRING_SPLASH_LINE1);
u8g.drawStr(txt2X, u8g.getHeight() - (DOG_CHAR_HEIGHT) * 1 / 2, STRING_SPLASH_LINE2);
2017-07-02 05:35:41 +00:00
#endif
} while (u8g.nextPage());
safe_delay(BOOTSCREEN_TIMEOUT);
2017-07-02 05:35:41 +00:00
}
#endif // SHOW_BOOTSCREEN
// Initialize or re-initialize the LCD
static void lcd_implementation_init() {
2016-09-24 21:36:12 +00:00
#if PIN_EXISTS(LCD_BACKLIGHT) // Enable LCD backlight
2016-09-25 10:52:10 +00:00
OUT_WRITE(LCD_BACKLIGHT_PIN, HIGH);
#endif
2016-09-24 21:36:12 +00:00
#if PIN_EXISTS(LCD_RESET)
OUT_WRITE(LCD_RESET_PIN, LOW); // perform a clean hardware reset
_delay_ms(5);
2016-09-25 10:52:10 +00:00
OUT_WRITE(LCD_RESET_PIN, HIGH);
_delay_ms(5); // delay to allow the display to initalize
u8g.begin(); // re-initialize the display
#endif
2015-10-13 10:51:34 +00:00
#if DISABLED(MINIPANEL) // setContrast not working for Mini Panel
u8g.setContrast(lcd_contrast);
2015-07-23 08:12:19 +00:00
#endif
2015-10-13 10:51:34 +00:00
#if ENABLED(LCD_SCREEN_ROT_90)
2015-04-08 04:11:03 +00:00
u8g.setRot90(); // Rotate screen by 90°
#elif ENABLED(LCD_SCREEN_ROT_180)
u8g.setRot180(); // Rotate screen by 180°
#elif ENABLED(LCD_SCREEN_ROT_270)
u8g.setRot270(); // Rotate screen by 270°
#endif
}
2016-08-20 23:13:24 +00:00
// The kill screen is displayed for unrecoverable conditions
2016-07-10 02:50:45 +00:00
void lcd_kill_screen() {
u8g.firstPage();
do {
lcd_setFont(FONT_MENU);
u8g.setPrintPos(0, u8g.getHeight()/4*1);
lcd_print_utf(lcd_status_message);
u8g.setPrintPos(0, u8g.getHeight()/4*2);
lcd_printPGM(PSTR(MSG_HALTED));
u8g.setPrintPos(0, u8g.getHeight()/4*3);
lcd_printPGM(PSTR(MSG_PLEASE_RESET));
} while (u8g.nextPage());
2016-07-10 02:50:45 +00:00
}
2017-03-18 15:15:54 +00:00
void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
2016-08-20 23:12:57 +00:00
//
// Status Screen
//
FORCE_INLINE void _draw_centered_temp(const int16_t temp, const uint8_t x, const uint8_t y) {
const uint8_t degsize = 6 * (temp >= 100 ? 3 : temp >= 10 ? 2 : 1); // number's pixel width
u8g.setPrintPos(x - (18 - degsize) / 2, y); // move left if shorter
lcd_print(itostr3(temp));
lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
}
FORCE_INLINE void _draw_heater_status(const uint8_t x, const int8_t heater, const bool blink) {
#if !HEATER_IDLE_HANDLER
UNUSED(blink);
#endif
2016-04-19 02:34:59 +00:00
#if HAS_TEMP_BED
const bool isBed = heater < 0;
2016-04-19 02:34:59 +00:00
#else
constexpr bool isBed = false;
2016-04-19 02:34:59 +00:00
#endif
if (PAGE_UNDER(7)) {
#if HEATER_IDLE_HANDLER
const bool is_idle = (!isBed ? thermalManager.is_heater_idle(heater) :
#if HAS_TEMP_BED
thermalManager.is_bed_idle()
#else
false
#endif
);
if (blink || !is_idle)
#endif
_draw_centered_temp((isBed ? thermalManager.degTargetBed() : thermalManager.degTargetHotend(heater)) + 0.5, x, 7); }
if (PAGE_CONTAINS(21, 28))
_draw_centered_temp((isBed ? thermalManager.degBed() : thermalManager.degHotend(heater)) + 0.5, x, 28);
if (PAGE_CONTAINS(17, 20)) {
const uint8_t h = isBed ? 7 : 8,
y = isBed ? 18 : 17;
if (isBed ? thermalManager.isHeatingBed() : thermalManager.isHeatingHotend(heater)) {
u8g.setColorIndex(0); // white on black
u8g.drawBox(x + h, y, 2, 2);
u8g.setColorIndex(1); // black on white
}
else {
u8g.drawBox(x + h, y, 2, 2);
}
}
2014-12-18 15:03:40 +00:00
}
FORCE_INLINE void _draw_axis_label(const AxisEnum axis, const char* const pstr, const bool blink) {
if (blink)
lcd_printPGM(pstr);
else {
if (!axis_homed[axis])
2016-09-02 09:09:34 +00:00
u8g.print('?');
else {
#if DISABLED(HOME_AFTER_DEACTIVATE) && DISABLED(DISABLE_REDUCED_ACCURACY_WARNING)
if (!axis_known_position[axis])
2016-09-02 09:09:34 +00:00
u8g.print(' ');
else
#endif
lcd_printPGM(pstr);
}
}
}
2017-06-16 19:10:31 +00:00
inline void lcd_implementation_status_message(const bool blink) {
2017-05-28 16:12:12 +00:00
#if ENABLED(STATUS_MESSAGE_SCROLLING)
2017-06-04 22:00:11 +00:00
static bool last_blink = false;
2017-05-28 16:12:12 +00:00
const uint8_t slen = lcd_strlen(lcd_status_message);
const char *stat = lcd_status_message + status_scroll_pos;
if (slen <= LCD_WIDTH)
lcd_print_utf(stat); // The string isn't scrolling
else {
if (status_scroll_pos <= slen - LCD_WIDTH)
lcd_print_utf(stat); // The string fills the screen
else {
uint8_t chars = LCD_WIDTH;
if (status_scroll_pos < slen) { // First string still visible
lcd_print_utf(stat); // The string leaves space
chars -= slen - status_scroll_pos; // Amount of space left
}
2017-06-15 20:07:39 +00:00
u8g.print('.'); // Always at 1+ spaces left, draw a dot
if (--chars) {
if (status_scroll_pos < slen + 1) // Draw a second dot if there's space
2017-06-15 20:07:39 +00:00
--chars, u8g.print('.');
if (chars) lcd_print_utf(lcd_status_message, chars); // Print a second copy of the message
}
}
if (last_blink != blink) {
last_blink = blink;
2017-06-04 22:00:11 +00:00
// Skip any non-printing bytes
if (status_scroll_pos < slen) while (!PRINTABLE(lcd_status_message[status_scroll_pos])) status_scroll_pos++;
if (++status_scroll_pos >= slen + 2) status_scroll_pos = 0;
2017-06-04 22:00:11 +00:00
}
2017-05-28 16:12:12 +00:00
}
#else
UNUSED(blink);
2017-05-28 16:12:12 +00:00
lcd_print_utf(lcd_status_message);
#endif
}
//#define DOGM_SD_PERCENT
static void lcd_implementation_status_screen() {
2017-06-04 22:00:11 +00:00
const bool blink = lcd_blink();
// Status Menu Font
2016-04-19 02:46:12 +00:00
lcd_setFont(FONT_STATUSMENU);
//
// Fan Animation
//
if (PAGE_UNDER(STATUS_SCREENHEIGHT + 1)) {
u8g.drawBitmapP(9, 1, STATUS_SCREENBYTEWIDTH, STATUS_SCREENHEIGHT,
#if HAS_FAN0
blink && fanSpeeds[0] ? status_screen0_bmp : status_screen1_bmp
#else
status_screen0_bmp
#endif
);
}
//
// Temperature Graphics and Info
//
if (PAGE_UNDER(28)) {
// Extruders
HOTEND_LOOP() _draw_heater_status(5 + e * 25, e, blink);
// Heated bed
#if HOTENDS < 4 && HAS_TEMP_BED
_draw_heater_status(81, -1, blink);
#endif
#if HAS_FAN0
if (PAGE_CONTAINS(20, 27)) {
// Fan
const int16_t per = ((fanSpeeds[0] + 1) * 100) / 256;
if (per) {
u8g.setPrintPos(104, 27);
lcd_print(itostr3(per));
u8g.print('%');
}
}
#endif
}
#if ENABLED(SDSUPPORT)
//
// SD Card Symbol
//
2017-10-15 07:15:19 +00:00
if (card.isFileOpen() && PAGE_CONTAINS(42 - (TALL_FONT_CORRECTION), 51 - (TALL_FONT_CORRECTION))) {
// Upper box
u8g.drawBox(42, 42 - (TALL_FONT_CORRECTION), 8, 7); // 42-48 (or 41-47)
// Right edge
u8g.drawBox(50, 44 - (TALL_FONT_CORRECTION), 2, 5); // 44-48 (or 43-47)
// Bottom hollow box
u8g.drawFrame(42, 49 - (TALL_FONT_CORRECTION), 10, 4); // 49-52 (or 48-51)
// Corner pixel
u8g.drawPixel(50, 43 - (TALL_FONT_CORRECTION)); // 43 (or 42)
}
//
// Progress bar frame
//
2016-12-05 03:09:12 +00:00
#define PROGRESS_BAR_X 54
#define PROGRESS_BAR_WIDTH (LCD_PIXEL_WIDTH - PROGRESS_BAR_X)
if (PAGE_CONTAINS(49, 52 - (TALL_FONT_CORRECTION))) // 49-52 (or 49-51)
u8g.drawFrame(
PROGRESS_BAR_X, 49,
PROGRESS_BAR_WIDTH, 4 - (TALL_FONT_CORRECTION)
);
2017-10-15 07:15:19 +00:00
#if DISABLED(LCD_SET_PROGRESS_MANUALLY)
const uint8_t progress_bar_percent = card.percentDone();
#endif
if (progress_bar_percent > 1) {
//
// Progress bar solid part
//
2016-12-05 03:09:12 +00:00
if (PAGE_CONTAINS(50, 51 - (TALL_FONT_CORRECTION))) // 50-51 (or just 50)
u8g.drawBox(
PROGRESS_BAR_X + 1, 50,
2017-10-15 07:15:19 +00:00
(uint16_t)((PROGRESS_BAR_WIDTH - 2) * progress_bar_percent * 0.01), 2 - (TALL_FONT_CORRECTION)
2016-12-05 03:09:12 +00:00
);
//
// SD Percent Complete
//
#if ENABLED(DOGM_SD_PERCENT)
if (PAGE_CONTAINS(41, 48)) {
// Percent complete
u8g.setPrintPos(55, 48);
2017-10-15 07:15:19 +00:00
u8g.print(itostr3(progress_bar_percent));
u8g.print('%');
}
#endif
}
//
// Elapsed Time
//
#if DISABLED(DOGM_SD_PERCENT)
2016-12-05 03:09:12 +00:00
#define SD_DURATION_X (PROGRESS_BAR_X + (PROGRESS_BAR_WIDTH / 2) - len * (DOG_CHAR_WIDTH / 2))
#else
2016-12-05 03:09:12 +00:00
#define SD_DURATION_X (LCD_PIXEL_WIDTH - len * DOG_CHAR_WIDTH)
#endif
if (PAGE_CONTAINS(41, 48)) {
char buffer[10];
duration_t elapsed = print_job_timer.duration();
bool has_days = (elapsed.value > 60*60*24L);
2016-12-05 03:09:12 +00:00
uint8_t len = elapsed.toDigital(buffer, has_days);
u8g.setPrintPos(SD_DURATION_X, 48);
lcd_print(buffer);
}
2016-07-24 02:13:35 +00:00
#endif
2015-04-08 04:11:03 +00:00
//
// XYZ Coordinates
//
2014-12-18 15:03:40 +00:00
#if ENABLED(USE_SMALL_INFOFONT)
#define INFO_FONT_HEIGHT 7
#else
#define INFO_FONT_HEIGHT 8
2016-04-19 02:34:59 +00:00
#endif
2015-04-08 04:11:03 +00:00
#define XYZ_BASELINE (30 + INFO_FONT_HEIGHT)
#define X_LABEL_POS 3
#define X_VALUE_POS 11
#define XYZ_SPACING 40
#if ENABLED(XYZ_HOLLOW_FRAME)
#define XYZ_FRAME_TOP 29
#define XYZ_FRAME_HEIGHT INFO_FONT_HEIGHT + 3
#else
#define XYZ_FRAME_TOP 30
#define XYZ_FRAME_HEIGHT INFO_FONT_HEIGHT + 1
#endif
// Before homing the axis letters are blinking 'X' <-> '?'.
// When axis is homed but axis_known_position is false the axis letters are blinking 'X' <-> ' '.
// When everything is ok you see a constant 'X'.
static char xstring[5], ystring[5], zstring[7];
#if ENABLED(FILAMENT_LCD_DISPLAY) && DISABLED(SDSUPPORT)
static char wstring[5], mstring[4];
#endif
// At the first page, regenerate the XYZ strings
if (page.page == 0) {
2017-11-03 04:59:42 +00:00
strcpy(xstring, ftostr4sign(LOGICAL_X_POSITION(current_position[X_AXIS])));
strcpy(ystring, ftostr4sign(LOGICAL_Y_POSITION(current_position[Y_AXIS])));
strcpy(zstring, ftostr52sp(FIXFLOAT(LOGICAL_Z_POSITION(current_position[Z_AXIS]))));
#if ENABLED(FILAMENT_LCD_DISPLAY)
strcpy(wstring, ftostr12ns(filament_width_meas));
2017-12-13 08:32:34 +00:00
strcpy(mstring, itostr3(100.0 * (
parser.volumetric_enabled
? planner.volumetric_area_nominal / planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM]
: planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM]
)
));
#endif
}
if (PAGE_CONTAINS(XYZ_FRAME_TOP, XYZ_FRAME_TOP + XYZ_FRAME_HEIGHT - 1)) {
#if ENABLED(XYZ_HOLLOW_FRAME)
u8g.drawFrame(0, XYZ_FRAME_TOP, LCD_PIXEL_WIDTH, XYZ_FRAME_HEIGHT); // 8: 29-40 7: 29-39
#else
u8g.drawBox(0, XYZ_FRAME_TOP, LCD_PIXEL_WIDTH, XYZ_FRAME_HEIGHT); // 8: 30-39 7: 30-37
#endif
if (PAGE_CONTAINS(XYZ_BASELINE - (INFO_FONT_HEIGHT - 1), XYZ_BASELINE)) {
#if DISABLED(XYZ_HOLLOW_FRAME)
u8g.setColorIndex(0); // white on black
#endif
u8g.setPrintPos(0 * XYZ_SPACING + X_LABEL_POS, XYZ_BASELINE);
_draw_axis_label(X_AXIS, PSTR(MSG_X), blink);
u8g.setPrintPos(0 * XYZ_SPACING + X_VALUE_POS, XYZ_BASELINE);
lcd_print(xstring);
u8g.setPrintPos(1 * XYZ_SPACING + X_LABEL_POS, XYZ_BASELINE);
_draw_axis_label(Y_AXIS, PSTR(MSG_Y), blink);
u8g.setPrintPos(1 * XYZ_SPACING + X_VALUE_POS, XYZ_BASELINE);
lcd_print(ystring);
u8g.setPrintPos(2 * XYZ_SPACING + X_LABEL_POS, XYZ_BASELINE);
_draw_axis_label(Z_AXIS, PSTR(MSG_Z), blink);
u8g.setPrintPos(2 * XYZ_SPACING + X_VALUE_POS, XYZ_BASELINE);
lcd_print(zstring);
#if DISABLED(XYZ_HOLLOW_FRAME)
u8g.setColorIndex(1); // black on white
#endif
}
}
//
// Feedrate
//
if (PAGE_CONTAINS(51 - INFO_FONT_HEIGHT, 49)) {
lcd_setFont(FONT_MENU);
u8g.setPrintPos(3, 50);
lcd_print(LCD_STR_FEEDRATE[0]);
lcd_setFont(FONT_STATUSMENU);
u8g.setPrintPos(12, 50);
lcd_print(itostr3(feedrate_percentage));
u8g.print('%');
//
// Filament sensor display if SD is disabled
//
#if ENABLED(FILAMENT_LCD_DISPLAY) && DISABLED(SDSUPPORT)
u8g.setPrintPos(56, 50);
lcd_print(wstring);
u8g.setPrintPos(102, 50);
lcd_print(mstring);
u8g.print('%');
lcd_setFont(FONT_MENU);
u8g.setPrintPos(47, 50);
lcd_print(LCD_STR_FILAM_DIA);
u8g.setPrintPos(93, 50);
lcd_print(LCD_STR_FILAM_MUL);
#endif
}
//
// Status line
//
#define STATUS_BASELINE (55 + INFO_FONT_HEIGHT)
2017-06-28 03:19:32 +00:00
if (PAGE_CONTAINS(STATUS_BASELINE - (INFO_FONT_HEIGHT - 1), STATUS_BASELINE)) {
u8g.setPrintPos(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
2017-06-16 19:10:31 +00:00
lcd_implementation_status_message(blink);
}
else {
lcd_printPGM(PSTR(LCD_STR_FILAM_DIA));
u8g.print(':');
lcd_print(wstring);
lcd_printPGM(PSTR(" " LCD_STR_FILAM_MUL));
u8g.print(':');
lcd_print(mstring);
u8g.print('%');
}
#else
2017-06-16 19:10:31 +00:00
lcd_implementation_status_message(blink);
#endif
}
}
2016-08-20 23:12:57 +00:00
#if ENABLED(ULTIPANEL)
uint8_t row_y1, row_y2;
2017-02-18 05:57:13 +00:00
uint8_t constexpr row_height = DOG_CHAR_HEIGHT + 2 * (TALL_FONT_CORRECTION);
#if ENABLED(ADVANCED_PAUSE_FEATURE)
2017-02-18 05:57:13 +00:00
static void lcd_implementation_hotend_status(const uint8_t row) {
row_y1 = row * row_height + 1;
row_y2 = row_y1 + row_height - 1;
if (!PAGE_CONTAINS(row_y1 + 1, row_y2 + 2)) return;
u8g.setPrintPos(LCD_PIXEL_WIDTH - 11 * (DOG_CHAR_WIDTH), row_y2);
lcd_print('E');
2017-03-04 04:12:22 +00:00
lcd_print((char)('1' + active_extruder));
2017-02-18 05:57:13 +00:00
lcd_print(' ');
lcd_print(itostr3(thermalManager.degHotend(active_extruder)));
lcd_print('/');
if (lcd_blink() || !thermalManager.is_heater_idle(active_extruder))
lcd_print(itostr3(thermalManager.degTargetHotend(active_extruder)));
2017-02-18 05:57:13 +00:00
}
#endif // ADVANCED_PAUSE_FEATURE
2016-08-20 23:12:57 +00:00
// Set the colors for a menu item based on whether it is selected
static void lcd_implementation_mark_as_selected(const uint8_t row, const bool isSelected) {
2017-02-18 05:57:13 +00:00
row_y1 = row * row_height + 1;
row_y2 = row_y1 + row_height - 1;
2017-02-18 05:57:13 +00:00
if (!PAGE_CONTAINS(row_y1 + 1, row_y2 + 2)) return;
2016-08-20 23:12:57 +00:00
if (isSelected) {
#if ENABLED(MENU_HOLLOW_FRAME)
u8g.drawHLine(0, row_y1 + 1, LCD_PIXEL_WIDTH);
2017-02-18 05:57:13 +00:00
u8g.drawHLine(0, row_y2 + 2, LCD_PIXEL_WIDTH);
#else
u8g.setColorIndex(1); // black on white
2017-02-18 05:57:13 +00:00
u8g.drawBox(0, row_y1 + 2, LCD_PIXEL_WIDTH, row_height - 1);
u8g.setColorIndex(0); // white on black
#endif
2016-08-20 23:12:57 +00:00
}
#if DISABLED(MENU_HOLLOW_FRAME)
else {
u8g.setColorIndex(1); // unmarked text is black on white
}
#endif
u8g.setPrintPos((START_COL) * (DOG_CHAR_WIDTH), row_y2);
}
// Draw a static line of text in the same idiom as a menu item
static void lcd_implementation_drawmenu_static(const uint8_t row, const char* pstr, const bool center=true, const bool invert=false, const char* valstr=NULL) {
lcd_implementation_mark_as_selected(row, invert);
2016-07-09 01:18:40 +00:00
if (!PAGE_CONTAINS(row_y1, row_y2)) return;
char c;
int8_t n = LCD_WIDTH - (START_COL);
2016-07-09 01:18:40 +00:00
if (center && !valstr) {
int8_t pad = (LCD_WIDTH - lcd_strlen_P(pstr)) / 2;
while (--pad >= 0) { u8g.print(' '); n--; }
}
while (n > 0 && (c = pgm_read_byte(pstr))) {
n -= lcd_print_and_count(c);
pstr++;
}
if (valstr) while (n > 0 && (c = *valstr)) {
n -= lcd_print_and_count(c);
valstr++;
}
while (n-- > 0) u8g.print(' ');
}
2016-08-20 23:12:57 +00:00
// Draw a generic menu item
static void lcd_implementation_drawmenu_generic(const bool isSelected, const uint8_t row, const char* pstr, const char pre_char, const char post_char) {
2016-08-20 23:12:57 +00:00
UNUSED(pre_char);
2016-06-23 01:22:17 +00:00
2016-08-20 23:12:57 +00:00
lcd_implementation_mark_as_selected(row, isSelected);
if (!PAGE_CONTAINS(row_y1, row_y2)) return;
uint8_t n = LCD_WIDTH - (START_COL) - 2;
while (char c = pgm_read_byte(pstr)) {
2016-09-02 09:09:34 +00:00
n -= lcd_print_and_count(c);
2016-08-20 23:12:57 +00:00
pstr++;
}
2016-09-02 09:09:34 +00:00
while (n--) u8g.print(' ');
u8g.setPrintPos(LCD_PIXEL_WIDTH - (DOG_CHAR_WIDTH), row_y2);
2016-08-20 23:12:57 +00:00
lcd_print(post_char);
2016-09-02 09:09:34 +00:00
u8g.print(' ');
}
2016-08-20 23:12:57 +00:00
// Macros for specific types of menu items
#define lcd_implementation_drawmenu_back(sel, row, pstr, dummy) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
2016-08-20 23:12:57 +00:00
#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, '>', ' ')
2016-08-20 23:12:57 +00:00
// Draw a menu item with an editable value
static void _drawmenu_setting_edit_generic(const bool isSelected, const uint8_t row, const char* pstr, const char* const data, const bool pgm) {
2016-08-20 23:12:57 +00:00
lcd_implementation_mark_as_selected(row, isSelected);
if (!PAGE_CONTAINS(row_y1, row_y2)) return;
const uint8_t vallen = (pgm ? lcd_strlen_P(data) : (lcd_strlen((char*)data)));
uint8_t n = LCD_WIDTH - (START_COL) - 2 - vallen;
while (char c = pgm_read_byte(pstr)) {
2016-09-02 09:09:34 +00:00
n -= lcd_print_and_count(c);
2016-08-20 23:12:57 +00:00
pstr++;
}
2016-09-02 09:09:34 +00:00
u8g.print(':');
while (n--) u8g.print(' ');
u8g.setPrintPos(LCD_PIXEL_WIDTH - (DOG_CHAR_WIDTH) * vallen, row_y2);
2016-08-20 23:12:57 +00:00
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 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))
2016-08-20 23:12:57 +00:00
void lcd_implementation_drawedit(const char* const pstr, const char* const value=NULL) {
2016-12-05 03:09:12 +00:00
const uint8_t labellen = lcd_strlen_P(pstr),
2016-12-05 13:14:11 +00:00
vallen = lcd_strlen(value);
uint8_t rows = (labellen > LCD_WIDTH - 2 - vallen) ? 2 : 1;
2016-08-20 23:12:57 +00:00
#if ENABLED(USE_BIG_EDIT_FONT)
2016-12-05 03:09:12 +00:00
uint8_t lcd_width, char_width;
if (labellen <= LCD_WIDTH_EDIT - 1) {
if (labellen + vallen + 2 >= LCD_WIDTH_EDIT) rows = 2;
2016-08-20 23:12:57 +00:00
lcd_width = LCD_WIDTH_EDIT + 1;
char_width = DOG_CHAR_WIDTH_EDIT;
lcd_setFont(FONT_MENU_EDIT);
2016-08-20 23:12:57 +00:00
}
else {
lcd_width = LCD_WIDTH - (START_COL);
char_width = DOG_CHAR_WIDTH;
2016-08-20 23:12:57 +00:00
lcd_setFont(FONT_MENU);
}
#else
2016-12-05 03:09:12 +00:00
constexpr uint8_t lcd_width = LCD_WIDTH - (START_COL),
char_width = DOG_CHAR_WIDTH;
2016-08-20 23:12:57 +00:00
#endif
// Center either one or two rows
const uint8_t segmentHeight = u8g.getHeight() / (rows + 1); // 1 / (rows+1) = 1/2 or 1/3
uint8_t baseline = segmentHeight + (DOG_CHAR_HEIGHT_EDIT + 1) / 2;
bool onpage = PAGE_CONTAINS(baseline + 1 - (DOG_CHAR_HEIGHT_EDIT), baseline);
if (onpage) {
u8g.setPrintPos(0, baseline);
lcd_printPGM(pstr);
}
2016-08-20 23:12:57 +00:00
if (value != NULL) {
u8g.print(':');
if (rows == 2) {
baseline += segmentHeight;
onpage = PAGE_CONTAINS(baseline + 1 - (DOG_CHAR_HEIGHT_EDIT), baseline);
}
if (onpage) {
u8g.setPrintPos(((lcd_width - 1) - (vallen + 1)) * char_width, baseline); // Right-justified, leaving padded by spaces
u8g.print(' '); // overwrite char if value gets shorter
lcd_print(value);
}
2016-08-20 23:12:57 +00:00
}
}
2016-08-20 23:12:57 +00:00
#if ENABLED(SDSUPPORT)
static void _drawmenu_sd(const bool isSelected, const uint8_t row, const char* const pstr, const char* filename, char* const longFilename, const bool isDir) {
2016-08-20 23:12:57 +00:00
UNUSED(pstr);
lcd_implementation_mark_as_selected(row, isSelected);
if (!PAGE_CONTAINS(row_y1, row_y2)) return;
2017-10-19 03:15:33 +00:00
constexpr uint8_t maxlen = LCD_WIDTH - (START_COL) - 1;
const char *outstr = longFilename[0] ? longFilename : filename;
2016-08-20 23:12:57 +00:00
if (longFilename[0]) {
2017-10-19 03:15:33 +00:00
#if ENABLED(SCROLL_LONG_FILENAMES)
if (isSelected) {
uint8_t name_hash = row;
for (uint8_t l = FILENAME_LENGTH; l--;)
name_hash = ((name_hash << 1) | (name_hash >> 7)) ^ 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, lcd_strlen(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
}
outstr += filename_scroll_pos;
}
#else
longFilename[maxlen] = '\0'; // cutoff at screen edge
#endif
2016-08-20 23:12:57 +00:00
}
2016-08-20 23:12:57 +00:00
if (isDir) lcd_print(LCD_STR_FOLDER[0]);
2017-10-19 03:15:33 +00:00
char c;
uint8_t n = maxlen;
while (n && (c = *outstr)) {
2016-09-02 09:09:34 +00:00
n -= lcd_print_and_count(c);
2017-10-19 03:15:33 +00:00
++outstr;
2016-08-20 23:12:57 +00:00
}
2017-10-19 03:15:33 +00:00
while (n) { --n; u8g.print(' '); }
}
2016-08-20 23:12:57 +00:00
#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)
2016-08-20 23:12:57 +00:00
#endif // SDSUPPORT
2017-06-21 20:26:59 +00:00
#if ENABLED(AUTO_BED_LEVELING_UBL)
/**
* UBL LCD "radar" map data
*/
2017-06-28 03:19:32 +00:00
#define MAP_UPPER_LEFT_CORNER_X 35 // These probably should be moved to the .h file But for now,
#define MAP_UPPER_LEFT_CORNER_Y 8 // it is easier to play with things having them here
#define MAP_MAX_PIXELS_X 53
#define MAP_MAX_PIXELS_Y 49
void lcd_implementation_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),
pixels_per_x_mesh_pnt = x_map_pixels / (GRID_MAX_POINTS_X),
pixels_per_y_mesh_pnt = y_map_pixels / (GRID_MAX_POINTS_Y),
2017-06-28 03:19:32 +00:00
x_offset = MAP_UPPER_LEFT_CORNER_X + 1 + (MAP_MAX_PIXELS_X - x_map_pixels - 2) / 2,
y_offset = MAP_UPPER_LEFT_CORNER_Y + 1 + (MAP_MAX_PIXELS_Y - y_map_pixels - 2) / 2;
// Clear the Mesh Map
if (PAGE_CONTAINS(y_offset - 2, y_offset + y_map_pixels + 4)) {
u8g.setColorIndex(1); // First draw the bigger box in White so we have a border around the mesh map box
u8g.drawBox(x_offset - 2, y_offset - 2, x_map_pixels + 4, y_map_pixels + 4);
if (PAGE_CONTAINS(y_offset, y_offset + y_map_pixels)) {
u8g.setColorIndex(0); // Now actually clear the mesh map box
u8g.drawBox(x_offset, y_offset, x_map_pixels, y_map_pixels);
}
}
2017-06-21 20:26:59 +00:00
2017-06-28 03:19:32 +00:00
// Display Mesh Point Locations
2017-06-21 20:26:59 +00:00
u8g.setColorIndex(1);
const uint8_t sx = x_offset + pixels_per_x_mesh_pnt / 2;
uint8_t y = y_offset + pixels_per_y_mesh_pnt / 2;
for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++, y += pixels_per_y_mesh_pnt)
2017-06-28 03:19:32 +00:00
if (PAGE_CONTAINS(y, y))
for (uint8_t i = 0, x = sx; i < GRID_MAX_POINTS_X; i++, x += pixels_per_x_mesh_pnt)
2017-07-19 03:55:14 +00:00
u8g.drawBox(x, y, 1, 1);
2017-06-21 20:26:59 +00:00
2017-06-28 03:19:32 +00:00
// Fill in the Specified Mesh Point
2017-06-21 20:26:59 +00:00
2017-06-28 03:19:32 +00:00
uint8_t inverted_y = GRID_MAX_POINTS_Y - y_plot - 1; // The origin is typically in the lower right corner. We need to
// invert the Y to get it to plot in the right location.
2017-06-21 20:26:59 +00:00
const uint8_t by = y_offset + inverted_y * pixels_per_y_mesh_pnt;
if (PAGE_CONTAINS(by, by + pixels_per_y_mesh_pnt))
2017-06-28 03:19:32 +00:00
u8g.drawBox(
x_offset + x_plot * pixels_per_x_mesh_pnt, by,
pixels_per_x_mesh_pnt, pixels_per_y_mesh_pnt
2017-06-28 03:19:32 +00:00
);
// Put Relevant Text on Display
2017-06-21 20:26:59 +00:00
// Show X and Y positions at top of screen
u8g.setColorIndex(1);
2017-06-28 03:19:32 +00:00
if (PAGE_UNDER(7)) {
u8g.setPrintPos(5, 7);
lcd_print("X:");
lcd_print(ftostr32(LOGICAL_X_POSITION(pgm_read_float(&ubl._mesh_index_to_xpos[x_plot]))));
u8g.setPrintPos(74, 7);
lcd_print("Y:");
lcd_print(ftostr32(LOGICAL_Y_POSITION(pgm_read_float(&ubl._mesh_index_to_ypos[y_plot]))));
}
2017-06-21 20:26:59 +00:00
// Print plot position
2017-06-28 03:19:32 +00:00
if (PAGE_CONTAINS(64 - (INFO_FONT_HEIGHT - 1), 64)) {
u8g.setPrintPos(5, 64);
lcd_print('(');
u8g.print(x_plot);
lcd_print(',');
u8g.print(y_plot);
lcd_print(')');
// Show the location value
u8g.setPrintPos(74, 64);
lcd_print("Z:");
if (!isnan(ubl.z_values[x_plot][y_plot]))
lcd_print(ftostr43sign(ubl.z_values[x_plot][y_plot]));
else
lcd_printPGM(PSTR(" -----"));
2017-06-21 20:26:59 +00:00
}
2017-06-28 03:19:32 +00:00
2017-06-21 20:26:59 +00:00
}
2017-06-28 03:19:32 +00:00
2017-06-21 20:26:59 +00:00
#endif // AUTO_BED_LEVELING_UBL
2016-08-20 23:12:57 +00:00
#endif // ULTIPANEL
2017-05-09 17:35:43 +00:00
#endif // __ULTRALCD_IMPL_DOGM_H