✨ MarlinUI for Ender 3 v2 DWIN LCD (#22594)
Co-Authored-By: Taylor Talkington <taylor.talkington@gmail.com>
This commit is contained in:
		
				
					committed by
					
						
						Scott Lahteine
					
				
			
			
				
	
			
			
			
						parent
						
							d51e70083d
						
					
				
				
					commit
					73ef26a106
				
			
							
								
								
									
										470
									
								
								Marlin/src/lcd/e3v2/marlinui/dwin_lcd.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										470
									
								
								Marlin/src/lcd/e3v2/marlinui/dwin_lcd.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,470 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Marlin 3D Printer Firmware
 | 
			
		||||
 * Copyright (c) 2021 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 <https://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/********************************************************************************
 | 
			
		||||
 * @file     lcd/e3v2/marlinui/dwin_lcd.cpp
 | 
			
		||||
 * @brief    DWIN screen control functions
 | 
			
		||||
 ********************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "../../../inc/MarlinConfigPre.h"
 | 
			
		||||
 | 
			
		||||
#if IS_DWIN_MARLINUI
 | 
			
		||||
 | 
			
		||||
#include "../../../inc/MarlinConfig.h"
 | 
			
		||||
 | 
			
		||||
#include "dwin_lcd.h"
 | 
			
		||||
#include <string.h> // for memset
 | 
			
		||||
 | 
			
		||||
//#define DEBUG_OUT 1
 | 
			
		||||
#include "../../../core/debug_out.h"
 | 
			
		||||
 | 
			
		||||
// Make sure DWIN_SendBuf is large enough to hold the largest string plus draw command and tail.
 | 
			
		||||
// Assume the narrowest (6 pixel) font and 2-byte gb2312-encoded characters.
 | 
			
		||||
uint8_t DWIN_SendBuf[11 + DWIN_WIDTH / 6 * 2] = { 0xAA };
 | 
			
		||||
uint8_t DWIN_BufTail[4] = { 0xCC, 0x33, 0xC3, 0x3C };
 | 
			
		||||
uint8_t databuf[26] = { 0 };
 | 
			
		||||
uint8_t receivedType;
 | 
			
		||||
 | 
			
		||||
int recnum = 0;
 | 
			
		||||
 | 
			
		||||
inline void DWIN_Byte(size_t &i, const uint16_t bval) {
 | 
			
		||||
  DWIN_SendBuf[++i] = bval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void DWIN_Word(size_t &i, const uint16_t wval) {
 | 
			
		||||
  DWIN_SendBuf[++i] = wval >> 8;
 | 
			
		||||
  DWIN_SendBuf[++i] = wval & 0xFF;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void DWIN_Long(size_t &i, const uint32_t lval) {
 | 
			
		||||
  DWIN_SendBuf[++i] = (lval >> 24) & 0xFF;
 | 
			
		||||
  DWIN_SendBuf[++i] = (lval >> 16) & 0xFF;
 | 
			
		||||
  DWIN_SendBuf[++i] = (lval >>  8) & 0xFF;
 | 
			
		||||
  DWIN_SendBuf[++i] = lval & 0xFF;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void DWIN_String(size_t &i, char * const string) {
 | 
			
		||||
  const size_t len = _MIN(sizeof(DWIN_SendBuf) - i, strlen(string));
 | 
			
		||||
  memcpy(&DWIN_SendBuf[i+1], string, len);
 | 
			
		||||
  i += len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void DWIN_String(size_t &i, const __FlashStringHelper * string) {
 | 
			
		||||
  if (!string) return;
 | 
			
		||||
  const size_t len = strlen_P((PGM_P)string); // cast it to PGM_P, which is basically const char *, and measure it using the _P version of strlen.
 | 
			
		||||
  if (len == 0) return;
 | 
			
		||||
  memcpy(&DWIN_SendBuf[i+1], string, len);
 | 
			
		||||
  i += len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Send the data in the buffer and the packet end
 | 
			
		||||
inline void DWIN_Send(size_t &i) {
 | 
			
		||||
  ++i;
 | 
			
		||||
  LOOP_L_N(n, i) { LCD_SERIAL.write(DWIN_SendBuf[n]); delayMicroseconds(1); }
 | 
			
		||||
  LOOP_L_N(n, 4) { LCD_SERIAL.write(DWIN_BufTail[n]); delayMicroseconds(1); }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*-------------------------------------- System variable function --------------------------------------*/
 | 
			
		||||
 | 
			
		||||
// Handshake (1: Success, 0: Fail)
 | 
			
		||||
bool DWIN_Handshake(void) {
 | 
			
		||||
  #ifndef LCD_BAUDRATE
 | 
			
		||||
    #define LCD_BAUDRATE 115200
 | 
			
		||||
  #endif
 | 
			
		||||
  LCD_SERIAL.begin(LCD_BAUDRATE);
 | 
			
		||||
  const millis_t serial_connect_timeout = millis() + 1000UL;
 | 
			
		||||
  while (!LCD_SERIAL.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
 | 
			
		||||
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  DWIN_Byte(i, 0x00);
 | 
			
		||||
  DWIN_Send(i);
 | 
			
		||||
 | 
			
		||||
  while (LCD_SERIAL.available() > 0 && recnum < (signed)sizeof(databuf)) {
 | 
			
		||||
    databuf[recnum] = LCD_SERIAL.read();
 | 
			
		||||
    // ignore the invalid data
 | 
			
		||||
    if (databuf[0] != FHONE) { // prevent the program from running.
 | 
			
		||||
      if (recnum > 0) {
 | 
			
		||||
        recnum = 0;
 | 
			
		||||
        ZERO(databuf);
 | 
			
		||||
      }
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    delay(10);
 | 
			
		||||
    recnum++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return ( recnum >= 3
 | 
			
		||||
        && databuf[0] == FHONE
 | 
			
		||||
        && databuf[1] == '\0'
 | 
			
		||||
        && databuf[2] == 'O'
 | 
			
		||||
        && databuf[3] == 'K' );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DWIN_Startup(void) {
 | 
			
		||||
  DEBUG_ECHOPGM("\r\nDWIN handshake ");
 | 
			
		||||
  delay(750);   // Delay here or init later in the boot process
 | 
			
		||||
  const bool success = DWIN_Handshake();
 | 
			
		||||
  if (success) DEBUG_ECHOLNPGM("ok."); else DEBUG_ECHOLNPGM("error.");
 | 
			
		||||
  DWIN_Frame_SetDir(TERN(DWIN_MARLINUI_LANDSCAPE, 0, 1));
 | 
			
		||||
  DWIN_Frame_Clear(Color_Bg_Black); // MarlinUI handles the bootscreen so just clear here
 | 
			
		||||
  DWIN_UpdateLCD();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set the backlight luminance
 | 
			
		||||
//  luminance: (0x00-0xFF)
 | 
			
		||||
void DWIN_Backlight_SetLuminance(const uint8_t luminance) {
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  DWIN_Byte(i, 0x30);
 | 
			
		||||
  DWIN_Byte(i, _MAX(luminance, 0x1F));
 | 
			
		||||
  DWIN_Send(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set screen display direction
 | 
			
		||||
//  dir: 0=0°, 1=90°, 2=180°, 3=270°
 | 
			
		||||
void DWIN_Frame_SetDir(uint8_t dir) {
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  DWIN_Byte(i, 0x34);
 | 
			
		||||
  DWIN_Byte(i, 0x5A);
 | 
			
		||||
  DWIN_Byte(i, 0xA5);
 | 
			
		||||
  DWIN_Byte(i, dir);
 | 
			
		||||
  DWIN_Send(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update display
 | 
			
		||||
void DWIN_UpdateLCD(void) {
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  DWIN_Byte(i, 0x3D);
 | 
			
		||||
  DWIN_Send(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*---------------------------------------- Drawing functions ----------------------------------------*/
 | 
			
		||||
 | 
			
		||||
// Clear screen
 | 
			
		||||
//  color: Clear screen color
 | 
			
		||||
void DWIN_Frame_Clear(const uint16_t color) {
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  DWIN_Byte(i, 0x01);
 | 
			
		||||
  DWIN_Word(i, color);
 | 
			
		||||
  DWIN_Send(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Draw a point
 | 
			
		||||
//  width: point width   0x01-0x0F
 | 
			
		||||
//  height: point height 0x01-0x0F
 | 
			
		||||
//  x,y: upper left point
 | 
			
		||||
void DWIN_Draw_Point(uint16_t color, uint8_t width, uint8_t height, uint16_t x, uint16_t y) {
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  DWIN_Byte(i, 0x02);
 | 
			
		||||
  DWIN_Word(i, color);
 | 
			
		||||
  DWIN_Byte(i, width);
 | 
			
		||||
  DWIN_Byte(i, height);
 | 
			
		||||
  DWIN_Word(i, x);
 | 
			
		||||
  DWIN_Word(i, y);
 | 
			
		||||
  DWIN_Send(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Draw a line
 | 
			
		||||
//  color: Line segment color
 | 
			
		||||
//  xStart/yStart: Start point
 | 
			
		||||
//  xEnd/yEnd: End point
 | 
			
		||||
void DWIN_Draw_Line(uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd) {
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  DWIN_Byte(i, 0x03);
 | 
			
		||||
  DWIN_Word(i, color);
 | 
			
		||||
  DWIN_Word(i, xStart);
 | 
			
		||||
  DWIN_Word(i, yStart);
 | 
			
		||||
  DWIN_Word(i, xEnd);
 | 
			
		||||
  DWIN_Word(i, yEnd);
 | 
			
		||||
  DWIN_Send(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Draw a rectangle
 | 
			
		||||
//  mode: 0=frame, 1=fill, 2=XOR fill
 | 
			
		||||
//  color: Rectangle color
 | 
			
		||||
//  xStart/yStart: upper left point
 | 
			
		||||
//  xEnd/yEnd: lower right point
 | 
			
		||||
void DWIN_Draw_Rectangle(uint8_t mode, uint16_t color,
 | 
			
		||||
                         uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd) {
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  DWIN_Byte(i, 0x05);
 | 
			
		||||
  DWIN_Byte(i, mode);
 | 
			
		||||
  DWIN_Word(i, color);
 | 
			
		||||
  DWIN_Word(i, xStart);
 | 
			
		||||
  DWIN_Word(i, yStart);
 | 
			
		||||
  DWIN_Word(i, xEnd);
 | 
			
		||||
  DWIN_Word(i, yEnd);
 | 
			
		||||
  DWIN_Send(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Move a screen area
 | 
			
		||||
//  mode: 0, circle shift; 1, translation
 | 
			
		||||
//  dir: 0=left, 1=right, 2=up, 3=down
 | 
			
		||||
//  dis: Distance
 | 
			
		||||
//  color: Fill color
 | 
			
		||||
//  xStart/yStart: upper left point
 | 
			
		||||
//  xEnd/yEnd: bottom right point
 | 
			
		||||
void DWIN_Frame_AreaMove(uint8_t mode, uint8_t dir, uint16_t dis,
 | 
			
		||||
                         uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd) {
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  DWIN_Byte(i, 0x09);
 | 
			
		||||
  DWIN_Byte(i, (mode << 7) | dir);
 | 
			
		||||
  DWIN_Word(i, dis);
 | 
			
		||||
  DWIN_Word(i, color);
 | 
			
		||||
  DWIN_Word(i, xStart);
 | 
			
		||||
  DWIN_Word(i, yStart);
 | 
			
		||||
  DWIN_Word(i, xEnd);
 | 
			
		||||
  DWIN_Word(i, yEnd);
 | 
			
		||||
  DWIN_Send(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*---------------------------------------- Text related functions ----------------------------------------*/
 | 
			
		||||
 | 
			
		||||
// Draw a string
 | 
			
		||||
//  bShow: true=display background color; false=don't display background color
 | 
			
		||||
//  size: Font size
 | 
			
		||||
//  color: Character color
 | 
			
		||||
//  bColor: Background color
 | 
			
		||||
//  x/y: Upper-left coordinate of the string
 | 
			
		||||
//  *string: The string
 | 
			
		||||
void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t x, uint16_t y, char *string) {
 | 
			
		||||
  uint8_t widthAdjust = 0;
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  DWIN_Byte(i, 0x11);
 | 
			
		||||
  // Bit 7: widthAdjust
 | 
			
		||||
  // Bit 6: bShow
 | 
			
		||||
  // Bit 5-4: Unused (0)
 | 
			
		||||
  // Bit 3-0: size
 | 
			
		||||
  DWIN_Byte(i, (widthAdjust * 0x80) | (bShow * 0x40) | size);
 | 
			
		||||
  DWIN_Word(i, color);
 | 
			
		||||
  DWIN_Word(i, bColor);
 | 
			
		||||
  DWIN_Word(i, x);
 | 
			
		||||
  DWIN_Word(i, y);
 | 
			
		||||
  DWIN_String(i, string);
 | 
			
		||||
  DWIN_Send(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Draw a positive integer
 | 
			
		||||
//  bShow: true=display background color; false=don't display background color
 | 
			
		||||
//  zeroFill: true=zero fill; false=no zero fill
 | 
			
		||||
//  zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
 | 
			
		||||
//  size: Font size
 | 
			
		||||
//  color: Character color
 | 
			
		||||
//  bColor: Background color
 | 
			
		||||
//  iNum: Number of digits
 | 
			
		||||
//  x/y: Upper-left coordinate
 | 
			
		||||
//  value: Integer value
 | 
			
		||||
void DWIN_Draw_IntValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color,
 | 
			
		||||
                          uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, uint16_t value) {
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  DWIN_Byte(i, 0x14);
 | 
			
		||||
  // Bit 7: bshow
 | 
			
		||||
  // Bit 6: 1 = signed; 0 = unsigned number;
 | 
			
		||||
  // Bit 5: zeroFill
 | 
			
		||||
  // Bit 4: zeroMode
 | 
			
		||||
  // Bit 3-0: size
 | 
			
		||||
  DWIN_Byte(i, (bShow * 0x80) | (zeroFill * 0x20) | (zeroMode * 0x10) | size);
 | 
			
		||||
  DWIN_Word(i, color);
 | 
			
		||||
  DWIN_Word(i, bColor);
 | 
			
		||||
  DWIN_Byte(i, iNum);
 | 
			
		||||
  DWIN_Byte(i, 0); // fNum
 | 
			
		||||
  DWIN_Word(i, x);
 | 
			
		||||
  DWIN_Word(i, y);
 | 
			
		||||
  #if 0
 | 
			
		||||
    for (char count = 0; count < 8; count++) {
 | 
			
		||||
      DWIN_Byte(i, value);
 | 
			
		||||
      value >>= 8;
 | 
			
		||||
      if (!(value & 0xFF)) break;
 | 
			
		||||
    }
 | 
			
		||||
  #else
 | 
			
		||||
    // Write a big-endian 64 bit integer
 | 
			
		||||
    const size_t p = i + 1;
 | 
			
		||||
    for (char count = 8; count--;) { // 7..0
 | 
			
		||||
      ++i;
 | 
			
		||||
      DWIN_SendBuf[p + count] = value;
 | 
			
		||||
      value >>= 8;
 | 
			
		||||
    }
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  DWIN_Send(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Draw a floating point number
 | 
			
		||||
//  bShow: true=display background color; false=don't display background color
 | 
			
		||||
//  zeroFill: true=zero fill; false=no zero fill
 | 
			
		||||
//  zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
 | 
			
		||||
//  size: Font size
 | 
			
		||||
//  color: Character color
 | 
			
		||||
//  bColor: Background color
 | 
			
		||||
//  iNum: Number of whole digits
 | 
			
		||||
//  fNum: Number of decimal digits
 | 
			
		||||
//  x/y: Upper-left point
 | 
			
		||||
//  value: Float value
 | 
			
		||||
void DWIN_Draw_FloatValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color,
 | 
			
		||||
                            uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, long value) {
 | 
			
		||||
  //uint8_t *fvalue = (uint8_t*)&value;
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  DWIN_Byte(i, 0x14);
 | 
			
		||||
  DWIN_Byte(i, (bShow * 0x80) | (zeroFill * 0x20) | (zeroMode * 0x10) | size);
 | 
			
		||||
  DWIN_Word(i, color);
 | 
			
		||||
  DWIN_Word(i, bColor);
 | 
			
		||||
  DWIN_Byte(i, iNum);
 | 
			
		||||
  DWIN_Byte(i, fNum);
 | 
			
		||||
  DWIN_Word(i, x);
 | 
			
		||||
  DWIN_Word(i, y);
 | 
			
		||||
  DWIN_Long(i, value);
 | 
			
		||||
  /*
 | 
			
		||||
  DWIN_Byte(i, fvalue[3]);
 | 
			
		||||
  DWIN_Byte(i, fvalue[2]);
 | 
			
		||||
  DWIN_Byte(i, fvalue[1]);
 | 
			
		||||
  DWIN_Byte(i, fvalue[0]);
 | 
			
		||||
  */
 | 
			
		||||
  DWIN_Send(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*---------------------------------------- Picture related functions ----------------------------------------*/
 | 
			
		||||
 | 
			
		||||
// Draw JPG and cached in #0 virtual display area
 | 
			
		||||
// id: Picture ID
 | 
			
		||||
void DWIN_JPG_ShowAndCache(const uint8_t id) {
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  DWIN_Word(i, 0x2200);
 | 
			
		||||
  DWIN_Byte(i, id);
 | 
			
		||||
  DWIN_Send(i);     // AA 23 00 00 00 00 08 00 01 02 03 CC 33 C3 3C
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Draw an Icon
 | 
			
		||||
//  libID: Icon library ID
 | 
			
		||||
//  picID: Icon ID
 | 
			
		||||
//  x/y: Upper-left point
 | 
			
		||||
void DWIN_ICON_Show(uint8_t libID, uint8_t picID, uint16_t x, uint16_t y) {
 | 
			
		||||
  NOMORE(x, DWIN_WIDTH - 1);
 | 
			
		||||
  NOMORE(y, DWIN_HEIGHT - 1); // -- ozy -- srl
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  DWIN_Byte(i, 0x23);
 | 
			
		||||
  DWIN_Word(i, x);
 | 
			
		||||
  DWIN_Word(i, y);
 | 
			
		||||
  DWIN_Byte(i, 0x80 | libID);
 | 
			
		||||
  //DWIN_Byte(i, libID);
 | 
			
		||||
  DWIN_Byte(i, picID);
 | 
			
		||||
  DWIN_Send(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unzip the JPG picture to a virtual display area
 | 
			
		||||
//  n: Cache index
 | 
			
		||||
//  id: Picture ID
 | 
			
		||||
void DWIN_JPG_CacheToN(uint8_t n, uint8_t id) {
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  DWIN_Byte(i, 0x25);
 | 
			
		||||
  DWIN_Byte(i, n);
 | 
			
		||||
  DWIN_Byte(i, id);
 | 
			
		||||
  DWIN_Send(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Copy area from virtual display area to current screen
 | 
			
		||||
//  cacheID: virtual area number
 | 
			
		||||
//  xStart/yStart: Upper-left of virtual area
 | 
			
		||||
//  xEnd/yEnd: Lower-right of virtual area
 | 
			
		||||
//  x/y: Screen paste point
 | 
			
		||||
void DWIN_Frame_AreaCopy(uint8_t cacheID, uint16_t xStart, uint16_t yStart,
 | 
			
		||||
                         uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y) {
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  DWIN_Byte(i, 0x27);
 | 
			
		||||
  DWIN_Byte(i, 0x80 | cacheID);
 | 
			
		||||
  DWIN_Word(i, xStart);
 | 
			
		||||
  DWIN_Word(i, yStart);
 | 
			
		||||
  DWIN_Word(i, xEnd);
 | 
			
		||||
  DWIN_Word(i, yEnd);
 | 
			
		||||
  DWIN_Word(i, x);
 | 
			
		||||
  DWIN_Word(i, y);
 | 
			
		||||
  DWIN_Send(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Animate a series of icons
 | 
			
		||||
//  animID: Animation ID; 0x00-0x0F
 | 
			
		||||
//  animate: true on; false off;
 | 
			
		||||
//  libID: Icon library ID
 | 
			
		||||
//  picIDs: Icon starting ID
 | 
			
		||||
//  picIDe: Icon ending ID
 | 
			
		||||
//  x/y: Upper-left point
 | 
			
		||||
//  interval: Display time interval, unit 10mS
 | 
			
		||||
void DWIN_ICON_Animation(uint8_t animID, bool animate, uint8_t libID, uint8_t picIDs, uint8_t picIDe, uint16_t x, uint16_t y, uint16_t interval) {
 | 
			
		||||
  NOMORE(x, DWIN_WIDTH - 1);
 | 
			
		||||
  NOMORE(y, DWIN_HEIGHT - 1); // -- ozy -- srl
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  DWIN_Byte(i, 0x28);
 | 
			
		||||
  DWIN_Word(i, x);
 | 
			
		||||
  DWIN_Word(i, y);
 | 
			
		||||
  // Bit 7: animation on or off
 | 
			
		||||
  // Bit 6: start from begin or end
 | 
			
		||||
  // Bit 5-4: unused (0)
 | 
			
		||||
  // Bit 3-0: animID
 | 
			
		||||
  DWIN_Byte(i, (animate * 0x80) | 0x40 | animID);
 | 
			
		||||
  DWIN_Byte(i, libID);
 | 
			
		||||
  DWIN_Byte(i, picIDs);
 | 
			
		||||
  DWIN_Byte(i, picIDe);
 | 
			
		||||
  DWIN_Byte(i, interval);
 | 
			
		||||
  DWIN_Send(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Animation Control
 | 
			
		||||
//  state: 16 bits, each bit is the state of an animation id
 | 
			
		||||
void DWIN_ICON_AnimationControl(uint16_t state) {
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
  DWIN_Byte(i, 0x29);
 | 
			
		||||
  DWIN_Word(i, state);
 | 
			
		||||
  DWIN_Send(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*---------------------------------------- Memory functions ----------------------------------------*/
 | 
			
		||||
// The LCD has an additional 32KB SRAM and 16KB Flash
 | 
			
		||||
 | 
			
		||||
// Data can be written to the sram and save to one of the jpeg page files
 | 
			
		||||
 | 
			
		||||
// Write Data Memory
 | 
			
		||||
//  command 0x31
 | 
			
		||||
//  Type: Write memory selection; 0x5A=SRAM; 0xA5=Flash
 | 
			
		||||
//  Address: Write data memory address; 0x000-0x7FFF for SRAM; 0x000-0x3FFF for Flash
 | 
			
		||||
//  Data: data
 | 
			
		||||
//
 | 
			
		||||
//  Flash writing returns 0xA5 0x4F 0x4B
 | 
			
		||||
 | 
			
		||||
// Read Data Memory
 | 
			
		||||
//  command 0x32
 | 
			
		||||
//  Type: Read memory selection; 0x5A=SRAM; 0xA5=Flash
 | 
			
		||||
//  Address: Read data memory address; 0x000-0x7FFF for SRAM; 0x000-0x3FFF for Flash
 | 
			
		||||
//  Length: leangth of data to read; 0x01-0xF0
 | 
			
		||||
//
 | 
			
		||||
//  Response:
 | 
			
		||||
//    Type, Address, Length, Data
 | 
			
		||||
 | 
			
		||||
// Write Picture Memory
 | 
			
		||||
//  Write the contents of the 32KB SRAM data memory into the designated image memory space
 | 
			
		||||
//  Issued: 0x5A, 0xA5, PIC_ID
 | 
			
		||||
//  Response: 0xA5 0x4F 0x4B
 | 
			
		||||
//
 | 
			
		||||
//  command 0x33
 | 
			
		||||
//  0x5A, 0xA5
 | 
			
		||||
//  PicId: Picture Memory location, 0x00-0x0F
 | 
			
		||||
//
 | 
			
		||||
//  Flash writing returns 0xA5 0x4F 0x4B
 | 
			
		||||
 | 
			
		||||
#endif // IS_DWIN_MARLINUI
 | 
			
		||||
							
								
								
									
										302
									
								
								Marlin/src/lcd/e3v2/marlinui/dwin_lcd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										302
									
								
								Marlin/src/lcd/e3v2/marlinui/dwin_lcd.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,302 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Marlin 3D Printer Firmware
 | 
			
		||||
 * Copyright (c) 2021 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 <https://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
/********************************************************************************
 | 
			
		||||
 * @file     lcd/e3v2/marlinui/dwin_lcd.h
 | 
			
		||||
 * @brief    DWIN screen control functions
 | 
			
		||||
 ********************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#define RECEIVED_NO_DATA         0x00
 | 
			
		||||
#define RECEIVED_SHAKE_HAND_ACK  0x01
 | 
			
		||||
 | 
			
		||||
#define FHONE                    0xAA
 | 
			
		||||
 | 
			
		||||
#define DWIN_SCROLL_UP   2
 | 
			
		||||
#define DWIN_SCROLL_DOWN 3
 | 
			
		||||
 | 
			
		||||
#if DISABLED(DWIN_MARLINUI_LANDSCAPE)
 | 
			
		||||
  #define DWIN_WIDTH  272
 | 
			
		||||
  #define DWIN_HEIGHT 480
 | 
			
		||||
#else
 | 
			
		||||
  #define DWIN_WIDTH  480
 | 
			
		||||
  #define DWIN_HEIGHT 272
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Picture ID
 | 
			
		||||
#define DWIN_Boot_Horiz      0
 | 
			
		||||
#define DWIN_Boot_Vert       1
 | 
			
		||||
#define DWIN_MarlinUI_Assets 2
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 3-.0:The font size, 0x00-0x09, corresponds to the font size below:
 | 
			
		||||
 * 0x00=6*12   0x01=8*16   0x02=10*20  0x03=12*24  0x04=14*28
 | 
			
		||||
 * 0x05=16*32  0x06=20*40  0x07=24*48  0x08=28*56  0x09=32*64
 | 
			
		||||
 */
 | 
			
		||||
#define font6x12  0x00
 | 
			
		||||
#define font8x16  0x01
 | 
			
		||||
#define font10x20 0x02
 | 
			
		||||
#define font12x24 0x03
 | 
			
		||||
#define font14x28 0x04
 | 
			
		||||
#define font16x32 0x05
 | 
			
		||||
#define font20x40 0x06
 | 
			
		||||
#define font24x48 0x07
 | 
			
		||||
#define font28x56 0x08
 | 
			
		||||
#define font32x64 0x09
 | 
			
		||||
 | 
			
		||||
#define DWIN_FONT_MENU  font10x20
 | 
			
		||||
#define DWIN_FONT_STAT  font14x28
 | 
			
		||||
#define DWIN_FONT_HEAD  font10x20
 | 
			
		||||
#define DWIN_FONT_ALERT font14x28
 | 
			
		||||
 | 
			
		||||
// Color
 | 
			
		||||
#define Color_White       0xFFFF
 | 
			
		||||
#define Color_Yellow      0xFF0F
 | 
			
		||||
#define Color_Error_Red   0xB000  // Error!
 | 
			
		||||
#define Color_Bg_Red      0xF00F  // Red background color
 | 
			
		||||
#define Color_Bg_Window   0x31E8  // Popup background color
 | 
			
		||||
#define Color_Bg_Heading  0x3344  // Static Heading
 | 
			
		||||
#define Color_Bg_Blue     0x1125  // Dark blue background color
 | 
			
		||||
#define Color_Bg_Black    0x0841  // Black background color
 | 
			
		||||
#define Color_IconBlue    0x45FA  // Lighter blue that matches icons/accents
 | 
			
		||||
#define Popup_Text_Color  0xD6BA  // Popup font background color
 | 
			
		||||
#define Line_Color        0x3A6A  // Split line color
 | 
			
		||||
#define Rectangle_Color   0xEE2F  // Blue square cursor color
 | 
			
		||||
#define Percent_Color     0xFE29  // Percentage color
 | 
			
		||||
#define BarFill_Color     0x10E4  // Fill color of progress bar
 | 
			
		||||
#define Select_Color      0x33BB  // Selected color
 | 
			
		||||
 | 
			
		||||
// Character matrix width x height
 | 
			
		||||
//#define LCD_WIDTH ((DWIN_WIDTH) / 8)
 | 
			
		||||
//#define LCD_HEIGHT ((DWIN_HEIGHT) / 12)
 | 
			
		||||
 | 
			
		||||
// ICON ID
 | 
			
		||||
#define BOOT_ICON           3 // Icon set file 3.ICO
 | 
			
		||||
#define ICON                4 // Icon set file 4.ICO
 | 
			
		||||
 | 
			
		||||
// MarlinUI Boot Icons
 | 
			
		||||
#define ICON_MarlinBoot            0
 | 
			
		||||
#define ICON_OpenSource            1
 | 
			
		||||
#define ICON_GitHubURL             2
 | 
			
		||||
#define ICON_MarlinURL             3
 | 
			
		||||
#define ICON_Copyright             4
 | 
			
		||||
 | 
			
		||||
// MarlinUI Icons
 | 
			
		||||
#define ICON_LOGO_Marlin           0
 | 
			
		||||
#define ICON_HotendOff             1
 | 
			
		||||
#define ICON_HotendOn              2
 | 
			
		||||
#define ICON_BedOff                3
 | 
			
		||||
#define ICON_BedOn                 4
 | 
			
		||||
#define ICON_Fan0                  5
 | 
			
		||||
#define ICON_Fan1                  6
 | 
			
		||||
#define ICON_Fan2                  7
 | 
			
		||||
#define ICON_Fan3                  8
 | 
			
		||||
#define ICON_Halted                9
 | 
			
		||||
#define ICON_Question             10
 | 
			
		||||
#define ICON_Alert                11
 | 
			
		||||
#define ICON_RotateCW             12
 | 
			
		||||
#define ICON_RotateCCW            13
 | 
			
		||||
#define ICON_UpArrow              14
 | 
			
		||||
#define ICON_DownArrow            15
 | 
			
		||||
#define ICON_BedLine              16
 | 
			
		||||
 | 
			
		||||
#define ICON_AdvSet               ICON_Language
 | 
			
		||||
#define ICON_HomeOff              ICON_AdvSet
 | 
			
		||||
#define ICON_HomeOffX             ICON_StepX
 | 
			
		||||
#define ICON_HomeOffY             ICON_StepY
 | 
			
		||||
#define ICON_HomeOffZ             ICON_StepZ
 | 
			
		||||
#define ICON_ProbeOff             ICON_AdvSet
 | 
			
		||||
#define ICON_ProbeOffX            ICON_StepX
 | 
			
		||||
#define ICON_ProbeOffY            ICON_StepY
 | 
			
		||||
#define ICON_PIDNozzle            ICON_SetEndTemp
 | 
			
		||||
#define ICON_PIDbed               ICON_SetBedTemp
 | 
			
		||||
 | 
			
		||||
/*-------------------------------------- System variable function --------------------------------------*/
 | 
			
		||||
 | 
			
		||||
// Handshake (1: Success, 0: Fail)
 | 
			
		||||
bool DWIN_Handshake(void);
 | 
			
		||||
 | 
			
		||||
// Common DWIN startup
 | 
			
		||||
void DWIN_Startup(void);
 | 
			
		||||
 | 
			
		||||
// Set the backlight luminance
 | 
			
		||||
//  luminance: (0x00-0xFF)
 | 
			
		||||
void DWIN_Backlight_SetLuminance(const uint8_t luminance);
 | 
			
		||||
 | 
			
		||||
// Set screen display direction
 | 
			
		||||
//  dir: 0=0°, 1=90°, 2=180°, 3=270°
 | 
			
		||||
void DWIN_Frame_SetDir(uint8_t dir);
 | 
			
		||||
 | 
			
		||||
// Update display
 | 
			
		||||
void DWIN_UpdateLCD(void);
 | 
			
		||||
 | 
			
		||||
/*---------------------------------------- Drawing functions ----------------------------------------*/
 | 
			
		||||
 | 
			
		||||
// Clear screen
 | 
			
		||||
//  color: Clear screen color
 | 
			
		||||
void DWIN_Frame_Clear(const uint16_t color);
 | 
			
		||||
 | 
			
		||||
// Draw a point
 | 
			
		||||
//  color: point color
 | 
			
		||||
//  width: point width   0x01-0x0F
 | 
			
		||||
//  height: point height 0x01-0x0F
 | 
			
		||||
//  x,y: upper left point
 | 
			
		||||
void DWIN_Draw_Point(uint16_t color, uint8_t width, uint8_t height, uint16_t x, uint16_t y);
 | 
			
		||||
 | 
			
		||||
// Draw a line
 | 
			
		||||
//  color: Line segment color
 | 
			
		||||
//  xStart/yStart: Start point
 | 
			
		||||
//  xEnd/yEnd: End point
 | 
			
		||||
void DWIN_Draw_Line(uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd);
 | 
			
		||||
 | 
			
		||||
// Draw a Horizontal line
 | 
			
		||||
//  color: Line segment color
 | 
			
		||||
//  xStart/yStart: Start point
 | 
			
		||||
//  xLength: Line Length
 | 
			
		||||
inline void DWIN_Draw_HLine(uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xLength) {
 | 
			
		||||
  DWIN_Draw_Line(color, xStart, yStart, xStart + xLength - 1, yStart);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Draw a Vertical line
 | 
			
		||||
//  color: Line segment color
 | 
			
		||||
//  xStart/yStart: Start point
 | 
			
		||||
//  yLength: Line Length
 | 
			
		||||
inline void DWIN_Draw_VLine(uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t yLength) {
 | 
			
		||||
  DWIN_Draw_Line(color, xStart, yStart, xStart, yStart + yLength - 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Draw a rectangle
 | 
			
		||||
//  mode: 0=frame, 1=fill, 2=XOR fill
 | 
			
		||||
//  color: Rectangle color
 | 
			
		||||
//  xStart/yStart: upper left point
 | 
			
		||||
//  xEnd/yEnd: lower right point
 | 
			
		||||
void DWIN_Draw_Rectangle(uint8_t mode, uint16_t color,
 | 
			
		||||
                         uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd);
 | 
			
		||||
 | 
			
		||||
// Draw a box
 | 
			
		||||
//  mode: 0=frame, 1=fill, 2=XOR fill
 | 
			
		||||
//  color: Rectangle color
 | 
			
		||||
//  xStart/yStart: upper left point
 | 
			
		||||
//  xSize/ySize: box size
 | 
			
		||||
inline void DWIN_Draw_Box(uint8_t mode, uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xSize, uint16_t ySize) {
 | 
			
		||||
  DWIN_Draw_Rectangle(mode, color, xStart, yStart, xStart + xSize - 1, yStart + ySize - 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Move a screen area
 | 
			
		||||
//  mode: 0, circle shift; 1, translation
 | 
			
		||||
//  dir: 0=left, 1=right, 2=up, 3=down
 | 
			
		||||
//  dis: Distance
 | 
			
		||||
//  color: Fill color
 | 
			
		||||
//  xStart/yStart: upper left point
 | 
			
		||||
//  xEnd/yEnd: bottom right point
 | 
			
		||||
void DWIN_Frame_AreaMove(uint8_t mode, uint8_t dir, uint16_t dis,
 | 
			
		||||
                         uint16_t color, uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd);
 | 
			
		||||
 | 
			
		||||
/*---------------------------------------- Text related functions ----------------------------------------*/
 | 
			
		||||
 | 
			
		||||
// Draw a string
 | 
			
		||||
//  bShow: true=display background color; false=don't display background color
 | 
			
		||||
//  size: Font size
 | 
			
		||||
//  color: Character color
 | 
			
		||||
//  bColor: Background color
 | 
			
		||||
//  x/y: Upper-left coordinate of the string
 | 
			
		||||
//  *string: The string
 | 
			
		||||
void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t x, uint16_t y, char *string);
 | 
			
		||||
 | 
			
		||||
class __FlashStringHelper;
 | 
			
		||||
 | 
			
		||||
inline void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t x, uint16_t y, const __FlashStringHelper *title) {
 | 
			
		||||
  DWIN_Draw_String(bShow, size, color, bColor, x, y, (char *)title);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Draw a positive integer
 | 
			
		||||
//  bShow: true=display background color; false=don't display background color
 | 
			
		||||
//  zeroFill: true=zero fill; false=no zero fill
 | 
			
		||||
//  zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
 | 
			
		||||
//  size: Font size
 | 
			
		||||
//  color: Character color
 | 
			
		||||
//  bColor: Background color
 | 
			
		||||
//  iNum: Number of digits
 | 
			
		||||
//  x/y: Upper-left coordinate
 | 
			
		||||
//  value: Integer value
 | 
			
		||||
void DWIN_Draw_IntValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color,
 | 
			
		||||
                          uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, uint16_t value);
 | 
			
		||||
 | 
			
		||||
// Draw a floating point number
 | 
			
		||||
//  bShow: true=display background color; false=don't display background color
 | 
			
		||||
//  zeroFill: true=zero fill; false=no zero fill
 | 
			
		||||
//  zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
 | 
			
		||||
//  size: Font size
 | 
			
		||||
//  color: Character color
 | 
			
		||||
//  bColor: Background color
 | 
			
		||||
//  iNum: Number of whole digits
 | 
			
		||||
//  fNum: Number of decimal digits
 | 
			
		||||
//  x/y: Upper-left point
 | 
			
		||||
//  value: Float value
 | 
			
		||||
void DWIN_Draw_FloatValue(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color,
 | 
			
		||||
                            uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, long value);
 | 
			
		||||
 | 
			
		||||
/*---------------------------------------- Picture related functions ----------------------------------------*/
 | 
			
		||||
 | 
			
		||||
// Draw JPG and cached in #0 virtual display area
 | 
			
		||||
// id: Picture ID
 | 
			
		||||
void DWIN_JPG_ShowAndCache(const uint8_t id);
 | 
			
		||||
 | 
			
		||||
// Draw an Icon
 | 
			
		||||
//  libID: Icon library ID
 | 
			
		||||
//  picID: Icon ID
 | 
			
		||||
//  x/y: Upper-left point
 | 
			
		||||
void DWIN_ICON_Show(uint8_t libID, uint8_t picID, uint16_t x, uint16_t y);
 | 
			
		||||
 | 
			
		||||
// Unzip the JPG picture to a virtual display area
 | 
			
		||||
//  n: Cache index
 | 
			
		||||
//  id: Picture ID
 | 
			
		||||
void DWIN_JPG_CacheToN(uint8_t n, uint8_t id);
 | 
			
		||||
 | 
			
		||||
// Unzip the JPG picture to virtual display area #1
 | 
			
		||||
//  id: Picture ID
 | 
			
		||||
inline void DWIN_JPG_CacheTo1(uint8_t id) { DWIN_JPG_CacheToN(1, id); }
 | 
			
		||||
 | 
			
		||||
// Copy area from virtual display area to current screen
 | 
			
		||||
//  cacheID: virtual area number
 | 
			
		||||
//  xStart/yStart: Upper-left of virtual area
 | 
			
		||||
//  xEnd/yEnd: Lower-right of virtual area
 | 
			
		||||
//  x/y: Screen paste point
 | 
			
		||||
void DWIN_Frame_AreaCopy(uint8_t cacheID, uint16_t xStart, uint16_t yStart,
 | 
			
		||||
                         uint16_t xEnd, uint16_t yEnd, uint16_t x, uint16_t y);
 | 
			
		||||
 | 
			
		||||
// Animate a series of icons
 | 
			
		||||
//  animID: Animation ID  up to 16
 | 
			
		||||
//  animate: animation on or off
 | 
			
		||||
//  libID: Icon library ID
 | 
			
		||||
//  picIDs: Icon starting ID
 | 
			
		||||
//  picIDe: Icon ending ID
 | 
			
		||||
//  x/y: Upper-left point
 | 
			
		||||
//  interval: Display time interval, unit 10mS
 | 
			
		||||
void DWIN_ICON_Animation(uint8_t animID, bool animate, uint8_t libID, uint8_t picIDs,
 | 
			
		||||
                         uint8_t picIDe, uint16_t x, uint16_t y, uint16_t interval);
 | 
			
		||||
 | 
			
		||||
// Animation Control
 | 
			
		||||
//  state: 16 bits, each bit is the state of an animation id
 | 
			
		||||
void DWIN_ICON_AnimationControl(uint16_t state);
 | 
			
		||||
							
								
								
									
										180
									
								
								Marlin/src/lcd/e3v2/marlinui/dwin_string.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								Marlin/src/lcd/e3v2/marlinui/dwin_string.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,180 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Marlin 3D Printer Firmware
 | 
			
		||||
 * Copyright (c) 2021 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 <https://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "../../../inc/MarlinConfig.h"
 | 
			
		||||
 | 
			
		||||
#if IS_DWIN_MARLINUI
 | 
			
		||||
 | 
			
		||||
#include "dwin_string.h"
 | 
			
		||||
//#include "../../fontutils.h"
 | 
			
		||||
 | 
			
		||||
uint8_t DWIN_String::data[];
 | 
			
		||||
uint16_t DWIN_String::span;
 | 
			
		||||
uint8_t DWIN_String::len;
 | 
			
		||||
 | 
			
		||||
void DWIN_String::set() {
 | 
			
		||||
  //*data = 0x00;
 | 
			
		||||
  memset(data, 0x00, sizeof(data));
 | 
			
		||||
  span = 0;
 | 
			
		||||
  len = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t read_byte(uint8_t *byte) { return *byte; }
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Add a string, applying substitutions for the following characters:
 | 
			
		||||
 *
 | 
			
		||||
 *   = displays  '0'....'10' for indexes 0 - 10
 | 
			
		||||
 *   ~ displays  '1'....'11' for indexes 0 - 10
 | 
			
		||||
 *   * displays 'E1'...'E11' for indexes 0 - 10 (By default. Uses LCD_FIRST_TOOL)
 | 
			
		||||
 */
 | 
			
		||||
void DWIN_String::add(uint8_t *string, int8_t index, uint8_t *itemString) {
 | 
			
		||||
  wchar_t wchar;
 | 
			
		||||
 | 
			
		||||
  while (*string) {
 | 
			
		||||
    string = get_utf8_value_cb(string, read_byte, &wchar);
 | 
			
		||||
    if (wchar > 255) wchar |= 0x0080;
 | 
			
		||||
    uint8_t ch = uint8_t(wchar & 0x00FF);
 | 
			
		||||
 | 
			
		||||
    if (ch == '=' || ch == '~' || ch == '*') {
 | 
			
		||||
      if (index >= 0) {
 | 
			
		||||
        int8_t inum = index + ((ch == '=') ? 0 : LCD_FIRST_TOOL);
 | 
			
		||||
        if (ch == '*') add_character('E');
 | 
			
		||||
        if (inum >= 10) { add_character('0' + (inum / 10)); inum %= 10; }
 | 
			
		||||
        add_character('0' + inum);
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        add(index == -2 ? GET_TEXT(MSG_CHAMBER) : GET_TEXT(MSG_BED));
 | 
			
		||||
      }
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    else if (ch == '$' && itemString) {
 | 
			
		||||
      add(itemString);
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    add_character(ch);
 | 
			
		||||
  }
 | 
			
		||||
  eol();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DWIN_String::add(uint8_t *string, uint8_t max_len) {
 | 
			
		||||
  wchar_t wchar;
 | 
			
		||||
  while (*string && max_len) {
 | 
			
		||||
    string = get_utf8_value_cb(string, read_byte, &wchar);
 | 
			
		||||
    /*
 | 
			
		||||
    if (wchar > 255) wchar |= 0x0080;
 | 
			
		||||
    uint8_t ch = uint8_t(wchar & 0x00FF);
 | 
			
		||||
    add_character(ch);
 | 
			
		||||
    */
 | 
			
		||||
    add(wchar);
 | 
			
		||||
    max_len--;
 | 
			
		||||
  }
 | 
			
		||||
  eol();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DWIN_String::add(wchar_t character) {
 | 
			
		||||
  int ret;
 | 
			
		||||
  size_t idx = 0;
 | 
			
		||||
  dwin_charmap_t pinval;
 | 
			
		||||
  dwin_charmap_t *copy_address = nullptr;
 | 
			
		||||
  pinval.uchar = character;
 | 
			
		||||
  pinval.idx = -1;
 | 
			
		||||
 | 
			
		||||
  // For 8-bit ASCII just print the single character
 | 
			
		||||
  char str[] = { '?', 0 };
 | 
			
		||||
  if (character < 255) {
 | 
			
		||||
    str[0] = (char)character;
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    copy_address = nullptr;
 | 
			
		||||
    ret = pf_bsearch_r((void *)g_dwin_charmap_device, COUNT(g_dwin_charmap_device), pf_bsearch_cb_comp_dwinmap_pgm, (void *)&pinval, &idx);
 | 
			
		||||
    if (ret >= 0) {
 | 
			
		||||
      copy_address = (dwin_charmap_t*)(g_dwin_charmap_device + idx);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      ret = pf_bsearch_r((void *)g_dwin_charmap_common, COUNT(g_dwin_charmap_common), pf_bsearch_cb_comp_dwinmap_pgm, (void *)&pinval, &idx);
 | 
			
		||||
      if (ret >= 0)
 | 
			
		||||
        copy_address = (dwin_charmap_t*)(g_dwin_charmap_common + idx);
 | 
			
		||||
    }
 | 
			
		||||
    if (ret >= 0) {
 | 
			
		||||
      dwin_charmap_t localval;
 | 
			
		||||
      memcpy_P(&localval, copy_address, sizeof(localval));
 | 
			
		||||
      str[0] = localval.idx;
 | 
			
		||||
      str[1] = localval.idx2;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (str[0]) add_character(str[0]);
 | 
			
		||||
  if (str[1]) add_character(str[1]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DWIN_String::add_character(uint8_t character) {
 | 
			
		||||
  if (len < MAX_STRING_LENGTH) {
 | 
			
		||||
    data[len] = character;
 | 
			
		||||
    len++;
 | 
			
		||||
    //span += glyph(character)->DWidth;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DWIN_String::rtrim(uint8_t character) {
 | 
			
		||||
  while (len) {
 | 
			
		||||
    if (data[len - 1] == 0x20 || data[len - 1] == character) {
 | 
			
		||||
      len--;
 | 
			
		||||
      //span -= glyph(data[length])->DWidth;
 | 
			
		||||
      eol();
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DWIN_String::ltrim(uint8_t character) {
 | 
			
		||||
  uint16_t i, j;
 | 
			
		||||
  for (i = 0; (i < len) && (data[i] == 0x20 || data[i] == character); i++) {
 | 
			
		||||
    //span -= glyph(data[i])->DWidth;
 | 
			
		||||
  }
 | 
			
		||||
  if (i == 0) return;
 | 
			
		||||
  for (j = 0; i < len; data[j++] = data[i++]);
 | 
			
		||||
  len = j;
 | 
			
		||||
  eol();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DWIN_String::trim(uint8_t character) {
 | 
			
		||||
  rtrim(character);
 | 
			
		||||
  ltrim(character);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* return v1 - v2 */
 | 
			
		||||
int dwin_charmap_compare(dwin_charmap_t *v1, dwin_charmap_t *v2) {
 | 
			
		||||
  return (v1->uchar < v2->uchar) ? -1 : (v1->uchar > v2->uchar) ? 1 : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pf_bsearch_cb_comp_dwinmap_pgm(void *userdata, size_t idx, void * data_pin) {
 | 
			
		||||
  dwin_charmap_t localval;
 | 
			
		||||
  dwin_charmap_t *p_dwin_charmap = (dwin_charmap_t *)userdata;
 | 
			
		||||
  memcpy_P(&localval, p_dwin_charmap + idx, sizeof(localval));
 | 
			
		||||
  return dwin_charmap_compare(&localval, (dwin_charmap_t *)data_pin);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DWIN_String dwin_string;
 | 
			
		||||
 | 
			
		||||
#endif // IS_DWIN_MARLINUI
 | 
			
		||||
							
								
								
									
										1007
									
								
								Marlin/src/lcd/e3v2/marlinui/dwin_string.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1007
									
								
								Marlin/src/lcd/e3v2/marlinui/dwin_string.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										193
									
								
								Marlin/src/lcd/e3v2/marlinui/lcdprint_dwin.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								Marlin/src/lcd/e3v2/marlinui/lcdprint_dwin.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,193 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Marlin 3D Printer Firmware
 | 
			
		||||
 * Copyright (c) 2021 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/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * lcd/e3v2/marlinui/lcdprint_dwin.cpp
 | 
			
		||||
 *
 | 
			
		||||
 * Due to DWIN hardware limitations simplified characters are used
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "../../../inc/MarlinConfigPre.h"
 | 
			
		||||
 | 
			
		||||
#if IS_DWIN_MARLINUI
 | 
			
		||||
 | 
			
		||||
#include "lcdprint_dwin.h"
 | 
			
		||||
#include "dwin_lcd.h"
 | 
			
		||||
#include "dwin_string.h"
 | 
			
		||||
 | 
			
		||||
#include "../../marlinui.h"
 | 
			
		||||
#include "../../../MarlinCore.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
cursor_t cursor;
 | 
			
		||||
 | 
			
		||||
extern dwin_font_t dwin_font;
 | 
			
		||||
 | 
			
		||||
void lcd_moveto_xy(const lcd_uint_t x, const lcd_uint_t y) { cursor.x = x; cursor.y = y; }
 | 
			
		||||
 | 
			
		||||
void lcd_moveto(const lcd_uint_t col, const lcd_uint_t row) {
 | 
			
		||||
  cursor.x = col * dwin_font.width;
 | 
			
		||||
  cursor.y = (row * (dwin_font.height + EXTRA_ROW_HEIGHT)) + (EXTRA_ROW_HEIGHT / 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void lcd_advance_cursor() { cursor.x += dwin_font.width; }
 | 
			
		||||
 | 
			
		||||
void lcd_put_int(const int i) {
 | 
			
		||||
  // TODO: Draw an int at the cursor position, advance the cursor
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lcd_put_dwin_string() {
 | 
			
		||||
  DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, (char*)dwin_string.string());
 | 
			
		||||
  cursor.x += dwin_string.length() * dwin_font.width;
 | 
			
		||||
  return dwin_string.length();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// return < 0 on error
 | 
			
		||||
// return the advanced cols
 | 
			
		||||
int lcd_put_wchar_max(wchar_t c, pixel_len_t max_length) {
 | 
			
		||||
  dwin_string.set();
 | 
			
		||||
  dwin_string.add(c);
 | 
			
		||||
  dwin_string.truncate(max_length);
 | 
			
		||||
  // Draw the char(s) at the cursor and advance the cursor
 | 
			
		||||
  DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, (char*)dwin_string.string());
 | 
			
		||||
  cursor.x += dwin_string.length() * dwin_font.width;
 | 
			
		||||
  return dwin_string.length();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Draw a UTF-8 string
 | 
			
		||||
 *
 | 
			
		||||
 * @param utf8_str : the UTF-8 string
 | 
			
		||||
 * @param cb_read_byte : the callback function to read one byte from the utf8_str (from RAM or ROM)
 | 
			
		||||
 * @param max_length : the pixel length of the string allowed (or number of slots in HD44780)
 | 
			
		||||
 *
 | 
			
		||||
 * @return the number of pixels advanced
 | 
			
		||||
 *
 | 
			
		||||
 * Draw a UTF-8 string
 | 
			
		||||
 */
 | 
			
		||||
static int lcd_put_u8str_max_cb(const char * utf8_str, uint8_t (*cb_read_byte)(uint8_t * str), pixel_len_t max_length) {
 | 
			
		||||
  uint8_t *p = (uint8_t *)utf8_str;
 | 
			
		||||
  dwin_string.set();
 | 
			
		||||
  while (dwin_string.length() < max_length) {
 | 
			
		||||
    wchar_t ch = 0;
 | 
			
		||||
    p = get_utf8_value_cb(p, cb_read_byte, &ch);
 | 
			
		||||
    if (!ch) break;
 | 
			
		||||
    dwin_string.add(ch);
 | 
			
		||||
  }
 | 
			
		||||
  DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, (char*)dwin_string.string());
 | 
			
		||||
  cursor.x += dwin_string.length() * dwin_font.width;
 | 
			
		||||
  return dwin_string.length();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lcd_put_u8str_max(const char * utf8_str, pixel_len_t max_length) {
 | 
			
		||||
  return lcd_put_u8str_max_cb(utf8_str, read_byte_ram, max_length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int lcd_put_u8str_max_P(PGM_P utf8_str_P, pixel_len_t max_length) {
 | 
			
		||||
  return lcd_put_u8str_max_cb(utf8_str_P, read_byte_rom, max_length);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
lcd_uint_t lcd_put_u8str_ind_P(PGM_P const pstr, const int8_t ind, PGM_P const inStr/*=nullptr*/, const lcd_uint_t maxlen/*=LCD_WIDTH*/) {
 | 
			
		||||
  dwin_string.set();
 | 
			
		||||
  dwin_string.add((uint8_t*)pstr, ind, (uint8_t*)inStr);
 | 
			
		||||
  dwin_string.truncate(maxlen);
 | 
			
		||||
  DWIN_Draw_String(dwin_font.solid, dwin_font.index, dwin_font.fg, dwin_font.bg, cursor.x, cursor.y, (char*)dwin_string.string());
 | 
			
		||||
  cursor.x += dwin_string.length() * dwin_font.width;
 | 
			
		||||
  return dwin_string.length();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if ENABLED(DEBUG_LCDPRINT)
 | 
			
		||||
 | 
			
		||||
  int test_dwin_charmap(dwin_charmap_t *data, size_t size, char *name, char flg_show_contents) {
 | 
			
		||||
    int ret;
 | 
			
		||||
    size_t idx = 0;
 | 
			
		||||
    dwin_charmap_t preval = { 0, 0, 0 };
 | 
			
		||||
    dwin_charmap_t pinval = { 0, 0, 0 };
 | 
			
		||||
    char flg_error = 0;
 | 
			
		||||
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    TRACE("Test %s\n", name);
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < size; i ++) {
 | 
			
		||||
      memcpy_P(&pinval, &(data[i]), sizeof(pinval));
 | 
			
		||||
 | 
			
		||||
      if (flg_show_contents) {
 | 
			
		||||
        #if 1
 | 
			
		||||
          TRACE("[% 4d] % 6" PRIu32 "(0x%04" PRIX32 ") --> 0x%02X,0x%02X%s\n", i, pinval.uchar, pinval.uchar, (unsigned int)(pinval.idx), (unsigned int)(pinval.idx2), (preval.uchar < pinval.uchar?"":" <--- ERROR"));
 | 
			
		||||
        #else
 | 
			
		||||
          TRACE("[% 4d]", i);
 | 
			
		||||
          TRACE("% 6" PRIu32 "(0x%04" PRIX32 "),", pinval.uchar, pinval.uchar);
 | 
			
		||||
          TRACE("0x%02X,", (unsigned int)(pinval.idx));
 | 
			
		||||
          TRACE("0x%02X,", (unsigned int)(pinval.idx2));
 | 
			
		||||
          TRACE("%s", (preval.uchar < pinval.uchar?"":" <--- ERROR"));
 | 
			
		||||
        #endif
 | 
			
		||||
      }
 | 
			
		||||
      if (preval.uchar >= pinval.uchar) {
 | 
			
		||||
        flg_error = 1;
 | 
			
		||||
        //TRACE("Error: out of order in array %s: idx=%d, val=%d(0x%x)\n", name, i, pinval.uchar, pinval.uchar);
 | 
			
		||||
        //return -1;
 | 
			
		||||
      }
 | 
			
		||||
      memcpy(&preval, &pinval, sizeof(pinval));
 | 
			
		||||
 | 
			
		||||
      ret = pf_bsearch_r((void *)data, size, pf_bsearch_cb_comp_dwinmap_pgm, (void *)&pinval, &idx);
 | 
			
		||||
      if (ret < 0) {
 | 
			
		||||
        flg_error = 1;
 | 
			
		||||
        TRACE("Error: not found item in array %s: idx=%d, val=%d(0x%x)\n", name, i, pinval.uchar, pinval.uchar);
 | 
			
		||||
        //return -1;
 | 
			
		||||
      }
 | 
			
		||||
      if (idx != i) {
 | 
			
		||||
        flg_error = 1;
 | 
			
		||||
        TRACE("Error: wrong index found item in array %s: idx=%d, val=%d(0x%x)\n", name, i, pinval.uchar, pinval.uchar);
 | 
			
		||||
        //return -1;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (flg_error) {
 | 
			
		||||
      TRACE("\nError: in array %s\n\n", name);
 | 
			
		||||
      return -1;
 | 
			
		||||
    }
 | 
			
		||||
    TRACE("\nPASS array %s\n\n", name);
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int test_dwin_charmap_all() {
 | 
			
		||||
    int flg_error = 0;
 | 
			
		||||
    if (test_dwin_charmap(g_dwin_charmap_device, COUNT(g_dwin_charmap_device), "g_dwin_charmap_device", 0) < 0) {
 | 
			
		||||
      flg_error = 1;
 | 
			
		||||
      test_dwin_charmap(g_dwin_charmap_device, COUNT(g_dwin_charmap_device), "g_dwin_charmap_device", 1);
 | 
			
		||||
    }
 | 
			
		||||
    if (test_dwin_charmap(g_dwin_charmap_common, COUNT(g_dwin_charmap_common), "g_dwin_charmap_common", 0) < 0) {
 | 
			
		||||
      flg_error = 1;
 | 
			
		||||
      test_dwin_charmap(g_dwin_charmap_common, COUNT(g_dwin_charmap_common), "g_dwin_charmap_common", 1);
 | 
			
		||||
    }
 | 
			
		||||
    if (flg_error) {
 | 
			
		||||
      TRACE("\nFAILED in dwin tests!\n");
 | 
			
		||||
      return -1;
 | 
			
		||||
    }
 | 
			
		||||
    TRACE("\nPASS in dwin tests.\n");
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#endif // DEBUG_LCDPRINT
 | 
			
		||||
 | 
			
		||||
#endif // IS_DWIN_MARLINUI
 | 
			
		||||
							
								
								
									
										30
									
								
								Marlin/src/lcd/e3v2/marlinui/lcdprint_dwin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								Marlin/src/lcd/e3v2/marlinui/lcdprint_dwin.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Marlin 3D Printer Firmware
 | 
			
		||||
 * Copyright (c) 2021 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 <https://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "../../lcdprint.h"
 | 
			
		||||
 | 
			
		||||
typedef struct { int16_t x, y; } cursor_t;
 | 
			
		||||
extern cursor_t cursor;
 | 
			
		||||
 | 
			
		||||
int lcd_put_dwin_string();
 | 
			
		||||
void lcd_moveto_xy(const lcd_uint_t, const lcd_uint_t);
 | 
			
		||||
							
								
								
									
										146
									
								
								Marlin/src/lcd/e3v2/marlinui/marlinui_dwin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								Marlin/src/lcd/e3v2/marlinui/marlinui_dwin.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,146 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Marlin 3D Printer Firmware
 | 
			
		||||
 * Copyright (c) 2021 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/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * lcd/e3v2/marlinui/lcdprint_dwin.h
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "../../../inc/MarlinConfigPre.h"
 | 
			
		||||
#include "dwin_lcd.h"
 | 
			
		||||
 | 
			
		||||
typedef uint16_t dwin_coord_t;  // Screen can be pretty big
 | 
			
		||||
typedef uint16_t lcd_uint_t;
 | 
			
		||||
typedef int16_t lcd_int_t;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  uint8_t index, width, height;
 | 
			
		||||
  uint16_t fg, bg;
 | 
			
		||||
  bool solid;
 | 
			
		||||
} dwin_font_t;
 | 
			
		||||
 | 
			
		||||
extern dwin_font_t dwin_font;
 | 
			
		||||
 | 
			
		||||
// Only Western languages support big / small fonts
 | 
			
		||||
//#if DISABLED(DISPLAY_CHARSET_ISO10646_1)
 | 
			
		||||
//  #undef USE_BIG_EDIT_FONT
 | 
			
		||||
//  #undef USE_SMALL_INFOFONT
 | 
			
		||||
//#endif
 | 
			
		||||
 | 
			
		||||
#if ENABLED(USE_BIG_EDIT_FONT)
 | 
			
		||||
  #define DWIN_FONT_EDIT font10x20
 | 
			
		||||
#else
 | 
			
		||||
  #define DWIN_FONT_EDIT font8x16
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define DWIN_FONT_INFO font8x16
 | 
			
		||||
 | 
			
		||||
#if DWIN_FONT_MENU == font6x12
 | 
			
		||||
  #define MENU_FONT_WIDTH    6
 | 
			
		||||
  #define MENU_FONT_ASCENT  10
 | 
			
		||||
  #define MENU_FONT_DESCENT  2
 | 
			
		||||
#elif DWIN_FONT_MENU == font8x16
 | 
			
		||||
  #define MENU_FONT_WIDTH    8
 | 
			
		||||
  #define MENU_FONT_ASCENT  13
 | 
			
		||||
  #define MENU_FONT_DESCENT  3
 | 
			
		||||
#elif DWIN_FONT_MENU == font10x20
 | 
			
		||||
  #define MENU_FONT_WIDTH   10
 | 
			
		||||
  #define MENU_FONT_ASCENT  16
 | 
			
		||||
  #define MENU_FONT_DESCENT  4
 | 
			
		||||
#endif
 | 
			
		||||
#define MENU_FONT_HEIGHT (MENU_FONT_ASCENT + MENU_FONT_DESCENT)
 | 
			
		||||
 | 
			
		||||
#define EXTRA_ROW_HEIGHT 8
 | 
			
		||||
#define MENU_LINE_HEIGHT (MENU_FONT_HEIGHT + EXTRA_ROW_HEIGHT)
 | 
			
		||||
 | 
			
		||||
#if DWIN_FONT_EDIT == font6x12
 | 
			
		||||
  #define EDIT_FONT_WIDTH    6
 | 
			
		||||
  #define EDIT_FONT_ASCENT  10
 | 
			
		||||
  #define EDIT_FONT_DESCENT  2
 | 
			
		||||
#elif DWIN_FONT_EDIT == font8x16
 | 
			
		||||
  #define EDIT_FONT_WIDTH    8
 | 
			
		||||
  #define EDIT_FONT_ASCENT  13
 | 
			
		||||
  #define EDIT_FONT_DESCENT  3
 | 
			
		||||
#elif DWIN_FONT_EDIT == font10x20
 | 
			
		||||
  #define EDIT_FONT_WIDTH   10
 | 
			
		||||
  #define EDIT_FONT_ASCENT  16
 | 
			
		||||
  #define EDIT_FONT_DESCENT  4
 | 
			
		||||
#endif
 | 
			
		||||
#define EDIT_FONT_HEIGHT (EDIT_FONT_ASCENT + EDIT_FONT_DESCENT)
 | 
			
		||||
 | 
			
		||||
#if DWIN_FONT_INFO == font6x12
 | 
			
		||||
  #define INFO_FONT_WIDTH    6
 | 
			
		||||
  #define INFO_FONT_ASCENT  10
 | 
			
		||||
  #define INFO_FONT_DESCENT  2
 | 
			
		||||
#elif DWIN_FONT_INFO == font8x16
 | 
			
		||||
  #define INFO_FONT_WIDTH    8
 | 
			
		||||
  #define INFO_FONT_ASCENT  13
 | 
			
		||||
  #define INFO_FONT_DESCENT  3
 | 
			
		||||
#elif DWIN_FONT_INFO == font10x20
 | 
			
		||||
  #define INFO_FONT_WIDTH   10
 | 
			
		||||
  #define INFO_FONT_ASCENT  16
 | 
			
		||||
  #define INFO_FONT_DESCENT  4
 | 
			
		||||
#endif
 | 
			
		||||
#define INFO_FONT_HEIGHT (INFO_FONT_ASCENT + INFO_FONT_DESCENT)
 | 
			
		||||
 | 
			
		||||
#if DWIN_FONT_STAT == font6x12
 | 
			
		||||
  #define STAT_FONT_WIDTH    6
 | 
			
		||||
  #define STAT_FONT_ASCENT  10
 | 
			
		||||
  #define STAT_FONT_DESCENT  2
 | 
			
		||||
#elif DWIN_FONT_STAT == font8x16
 | 
			
		||||
  #define STAT_FONT_WIDTH    8
 | 
			
		||||
  #define STAT_FONT_ASCENT  13
 | 
			
		||||
  #define STAT_FONT_DESCENT  3
 | 
			
		||||
#elif DWIN_FONT_STAT == font10x20
 | 
			
		||||
  #define STAT_FONT_WIDTH   10
 | 
			
		||||
  #define STAT_FONT_ASCENT  16
 | 
			
		||||
  #define STAT_FONT_DESCENT  4
 | 
			
		||||
#elif DWIN_FONT_STAT == font12x24
 | 
			
		||||
  #define STAT_FONT_WIDTH   12
 | 
			
		||||
  #define STAT_FONT_ASCENT  19
 | 
			
		||||
  #define STAT_FONT_DESCENT  5
 | 
			
		||||
#elif DWIN_FONT_STAT == font14x28
 | 
			
		||||
  #define STAT_FONT_WIDTH   14
 | 
			
		||||
  #define STAT_FONT_ASCENT  22
 | 
			
		||||
  #define STAT_FONT_DESCENT  6
 | 
			
		||||
#elif DWIN_FONT_STAT == font16x32
 | 
			
		||||
  #define STAT_FONT_WIDTH   16
 | 
			
		||||
  #define STAT_FONT_ASCENT  26
 | 
			
		||||
  #define STAT_FONT_DESCENT  6
 | 
			
		||||
#elif DWIN_FONT_STAT == font20x40
 | 
			
		||||
  #define STAT_FONT_WIDTH   20
 | 
			
		||||
  #define STAT_FONT_ASCENT  32
 | 
			
		||||
  #define STAT_FONT_DESCENT  8
 | 
			
		||||
#elif DWIN_FONT_STAT == font24x48
 | 
			
		||||
  #define STAT_FONT_WIDTH   24
 | 
			
		||||
  #define STAT_FONT_ASCENT  38
 | 
			
		||||
  #define STAT_FONT_DESCENT 10
 | 
			
		||||
#elif DWIN_FONT_STAT == font28x56
 | 
			
		||||
  #define STAT_FONT_WIDTH   28
 | 
			
		||||
  #define STAT_FONT_ASCENT  44
 | 
			
		||||
  #define STAT_FONT_DESCENT 12
 | 
			
		||||
#elif DWIN_FONT_STAT == font32x64
 | 
			
		||||
  #define STAT_FONT_WIDTH   32
 | 
			
		||||
  #define STAT_FONT_ASCENT  50
 | 
			
		||||
  #define STAT_FONT_DESCENT 14
 | 
			
		||||
#endif
 | 
			
		||||
#define STAT_FONT_HEIGHT (STAT_FONT_ASCENT + STAT_FONT_DESCENT)
 | 
			
		||||
							
								
								
									
										595
									
								
								Marlin/src/lcd/e3v2/marlinui/ui_common.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										595
									
								
								Marlin/src/lcd/e3v2/marlinui/ui_common.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,595 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Marlin 3D Printer Firmware
 | 
			
		||||
 * Copyright (c) 2021 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/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "../../../inc/MarlinConfigPre.h"
 | 
			
		||||
 | 
			
		||||
#if IS_DWIN_MARLINUI
 | 
			
		||||
 | 
			
		||||
#include "marlinui_dwin.h"
 | 
			
		||||
#include "dwin_lcd.h"
 | 
			
		||||
#include "dwin_string.h"
 | 
			
		||||
 | 
			
		||||
//#include "../../lcdprint.h"
 | 
			
		||||
#include "lcdprint_dwin.h"
 | 
			
		||||
#include "../../fontutils.h"
 | 
			
		||||
#include "../../../libs/numtostr.h"
 | 
			
		||||
#include "../../marlinui.h"
 | 
			
		||||
 | 
			
		||||
#include "../../../sd/cardreader.h"
 | 
			
		||||
#include "../../../module/motion.h"
 | 
			
		||||
#include "../../../module/temperature.h"
 | 
			
		||||
#include "../../../module/printcounter.h"
 | 
			
		||||
 | 
			
		||||
#if ENABLED(SDSUPPORT)
 | 
			
		||||
  #include "../../../libs/duration_t.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if ENABLED(AUTO_BED_LEVELING_UBL)
 | 
			
		||||
  #include "../../../feature/bedlevel/bedlevel.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// DWIN printing specifies the font on each string operation
 | 
			
		||||
// but we'll make the font modal for Marlin
 | 
			
		||||
dwin_font_t dwin_font = { font8x16, 8, 16, Color_White, Color_Bg_Black, true };
 | 
			
		||||
void MarlinUI::set_font(const uint8_t font_nr) {
 | 
			
		||||
  if (font_nr != dwin_font.index) {
 | 
			
		||||
    dwin_font.index = font_nr;
 | 
			
		||||
    uint8_t w, h;
 | 
			
		||||
    switch (font_nr) {
 | 
			
		||||
      default:
 | 
			
		||||
      case font6x12:  w =  6; h = 12; break;
 | 
			
		||||
      case font8x16:  w =  8; h = 16; break;
 | 
			
		||||
      case font10x20: w = 10; h = 20; break;
 | 
			
		||||
      case font12x24: w = 12; h = 24; break;
 | 
			
		||||
      case font14x28: w = 14; h = 28; break;
 | 
			
		||||
      case font16x32: w = 16; h = 32; break;
 | 
			
		||||
      case font20x40: w = 20; h = 40; break;
 | 
			
		||||
      case font24x48: w = 24; h = 48; break;
 | 
			
		||||
      case font28x56: w = 28; h = 56; break;
 | 
			
		||||
      case font32x64: w = 32; h = 64; break;
 | 
			
		||||
    }
 | 
			
		||||
    dwin_font.width = w;
 | 
			
		||||
    dwin_font.height = h;
 | 
			
		||||
    // TODO: Array with dimensions, auto fit menu items,
 | 
			
		||||
    // update char width / height of the screen based on
 | 
			
		||||
    // new (fixed-width) font size.
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This display is always detected
 | 
			
		||||
bool MarlinUI::detected() { return true; }
 | 
			
		||||
 | 
			
		||||
// Initialize or re-initialize the LCD
 | 
			
		||||
void MarlinUI::init_lcd() {
 | 
			
		||||
  DWIN_Startup();
 | 
			
		||||
 | 
			
		||||
  // Load the assets JPG (currently just the status screen 'icon')
 | 
			
		||||
  DWIN_JPG_CacheToN(1, DWIN_MarlinUI_Assets);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This LCD should clear where it will draw anew
 | 
			
		||||
void MarlinUI::clear_lcd() {
 | 
			
		||||
  DWIN_ICON_AnimationControl(0x0000); // disable all icon animations
 | 
			
		||||
  DWIN_Frame_Clear(Color_Bg_Black);
 | 
			
		||||
  DWIN_UpdateLCD();
 | 
			
		||||
 | 
			
		||||
  did_first_redraw = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if ENABLED(SHOW_BOOTSCREEN)
 | 
			
		||||
 | 
			
		||||
  void MarlinUI::show_bootscreen() {
 | 
			
		||||
    clear_lcd();
 | 
			
		||||
    dwin_string.set(F(SHORT_BUILD_VERSION));
 | 
			
		||||
 | 
			
		||||
    #if ENABLED(DWIN_MARLINUI_PORTRAIT)
 | 
			
		||||
      #define LOGO_CENTER ((LCD_PIXEL_WIDTH) / 2)
 | 
			
		||||
      #define INFO_CENTER LOGO_CENTER
 | 
			
		||||
      #define VERSION_Y   330
 | 
			
		||||
      DWIN_ICON_Show(BOOT_ICON, ICON_MarlinBoot, LOGO_CENTER - 266 / 2,  15);
 | 
			
		||||
      DWIN_ICON_Show(BOOT_ICON, ICON_OpenSource, LOGO_CENTER - 174 / 2, 280);
 | 
			
		||||
      DWIN_ICON_Show(BOOT_ICON, ICON_GitHubURL,  LOGO_CENTER - 180 / 2, 420);
 | 
			
		||||
      DWIN_ICON_Show(BOOT_ICON, ICON_MarlinURL,  LOGO_CENTER - 100 / 2, 440);
 | 
			
		||||
      DWIN_ICON_Show(BOOT_ICON, ICON_Copyright,  LOGO_CENTER - 126 / 2, 460);
 | 
			
		||||
    #else
 | 
			
		||||
      #define LOGO_CENTER (280 / 2)
 | 
			
		||||
      #define INFO_CENTER ((LCD_PIXEL_WIDTH) - 200 / 2)
 | 
			
		||||
      #define VERSION_Y   84
 | 
			
		||||
      DWIN_ICON_Show(BOOT_ICON, ICON_MarlinBoot, LOGO_CENTER - 266 / 2,  15);
 | 
			
		||||
      DWIN_ICON_Show(BOOT_ICON, ICON_OpenSource, INFO_CENTER - 174 / 2,  60);
 | 
			
		||||
      DWIN_ICON_Show(BOOT_ICON, ICON_GitHubURL,  INFO_CENTER - 180 / 2, 130);
 | 
			
		||||
      DWIN_ICON_Show(BOOT_ICON, ICON_MarlinURL,  INFO_CENTER - 100 / 2, 152);
 | 
			
		||||
      DWIN_ICON_Show(BOOT_ICON, ICON_Copyright,  INFO_CENTER - 126 / 2, 200);
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    DWIN_Draw_String(false, font10x20, Color_Yellow, Color_Bg_Black, INFO_CENTER - (dwin_string.length() * 10) / 2, VERSION_Y, S(dwin_string.string()));
 | 
			
		||||
    DWIN_UpdateLCD();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void MarlinUI::bootscreen_completion(const millis_t sofar) {
 | 
			
		||||
    if ((BOOTSCREEN_TIMEOUT) > sofar) safe_delay((BOOTSCREEN_TIMEOUT) - sofar);
 | 
			
		||||
    clear_lcd();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// The kill screen is displayed for unrecoverable conditions
 | 
			
		||||
void MarlinUI::draw_kill_screen() {
 | 
			
		||||
  set_font(DWIN_FONT_ALERT);
 | 
			
		||||
  DWIN_Frame_Clear(Color_Bg_Black);
 | 
			
		||||
  dwin_font.fg = Color_Error_Red;
 | 
			
		||||
  dwin_font.solid = false;
 | 
			
		||||
  DWIN_Draw_Rectangle(1, Color_Bg_Window, 20, 20, LCD_PIXEL_WIDTH - 20, LCD_PIXEL_HEIGHT - 20);
 | 
			
		||||
  // make the frame a few pixels thick
 | 
			
		||||
  DWIN_Draw_Rectangle(0, Color_Yellow, 20, 20, LCD_PIXEL_WIDTH - 20, LCD_PIXEL_HEIGHT - 20);
 | 
			
		||||
  DWIN_Draw_Rectangle(0, Color_Yellow, 21, 21, LCD_PIXEL_WIDTH - 21, LCD_PIXEL_HEIGHT - 21);
 | 
			
		||||
  DWIN_Draw_Rectangle(0, Color_Yellow, 22, 22, LCD_PIXEL_WIDTH - 22, LCD_PIXEL_HEIGHT - 22);
 | 
			
		||||
 | 
			
		||||
  uint8_t cx = (LCD_PIXEL_WIDTH / dwin_font.width / 2),
 | 
			
		||||
          cy = (LCD_PIXEL_HEIGHT / dwin_font.height / 2);
 | 
			
		||||
 | 
			
		||||
  #if ENABLED(DWIN_MARLINUI_LANDSCAPE)
 | 
			
		||||
    cx += (96 / 2 / dwin_font.width);
 | 
			
		||||
    DWIN_ICON_Show(ICON, ICON_Halted, 40, (LCD_PIXEL_HEIGHT - 96) / 2);
 | 
			
		||||
  #else
 | 
			
		||||
    DWIN_ICON_Show(ICON, ICON_Halted, (LCD_PIXEL_WIDTH - 96) / 2, 40);
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  uint8_t slen = utf8_strlen(status_message);
 | 
			
		||||
  lcd_moveto(cx - (slen / 2), cy - 1);
 | 
			
		||||
  lcd_put_u8str(status_message);
 | 
			
		||||
 | 
			
		||||
  slen = utf8_strlen(S(GET_TEXT_F(MSG_HALTED)));
 | 
			
		||||
  lcd_moveto(cx - (slen / 2), cy);
 | 
			
		||||
  lcd_put_u8str_P((const char*)GET_TEXT_F(MSG_HALTED));
 | 
			
		||||
 | 
			
		||||
  slen = utf8_strlen(S(GET_TEXT_F(MSG_HALTED)));
 | 
			
		||||
  lcd_moveto(cx - (slen / 2), cy + 1);
 | 
			
		||||
  lcd_put_u8str_P((const char*)GET_TEXT_F(MSG_HALTED));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Status Message
 | 
			
		||||
//
 | 
			
		||||
void MarlinUI::draw_status_message(const bool blink) {
 | 
			
		||||
  set_font(DWIN_FONT_STAT);
 | 
			
		||||
  dwin_font.solid = true;
 | 
			
		||||
  dwin_font.fg = Color_White;
 | 
			
		||||
  dwin_font.bg = Color_Bg_Black;
 | 
			
		||||
  lcd_moveto_xy(0, LCD_PIXEL_HEIGHT - (STAT_FONT_HEIGHT) - 1);
 | 
			
		||||
 | 
			
		||||
  constexpr uint8_t max_status_chars = (LCD_PIXEL_WIDTH) / (STAT_FONT_WIDTH);
 | 
			
		||||
 | 
			
		||||
  auto status_changed = []{
 | 
			
		||||
    static uint16_t old_hash = 0x0000;
 | 
			
		||||
    uint16_t hash = 0x0000;
 | 
			
		||||
    for (uint8_t i = 0; i < MAX_MESSAGE_LENGTH; i++) {
 | 
			
		||||
      const char c = ui.status_message[i];
 | 
			
		||||
      if (!c) break;
 | 
			
		||||
      hash = ((hash << 1) | (hash >> 15)) ^ c;
 | 
			
		||||
    }
 | 
			
		||||
    const bool hash_changed = hash != old_hash;
 | 
			
		||||
    old_hash = hash;
 | 
			
		||||
    return hash_changed || !ui.did_first_redraw;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  #if ENABLED(STATUS_MESSAGE_SCROLLING)
 | 
			
		||||
    static bool last_blink = false;
 | 
			
		||||
 | 
			
		||||
    // Get the UTF8 character count of the string
 | 
			
		||||
    uint8_t slen = utf8_strlen(status_message);
 | 
			
		||||
 | 
			
		||||
    // If the string fits into the LCD, just print it and do not scroll it
 | 
			
		||||
    if (slen <= max_status_chars) {
 | 
			
		||||
 | 
			
		||||
      if (status_changed()) {
 | 
			
		||||
 | 
			
		||||
        // The string isn't scrolling and may not fill the screen
 | 
			
		||||
        lcd_put_u8str(status_message);
 | 
			
		||||
 | 
			
		||||
        // Fill the rest with spaces
 | 
			
		||||
        while (slen < max_status_chars) { lcd_put_wchar(' '); ++slen; }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      // String is larger than the available line space
 | 
			
		||||
 | 
			
		||||
      // Get a pointer to the next valid UTF8 character
 | 
			
		||||
      // and the string remaining length
 | 
			
		||||
      uint8_t rlen;
 | 
			
		||||
      const char *stat = status_and_len(rlen);
 | 
			
		||||
      lcd_put_u8str_max(stat, max_status_chars);
 | 
			
		||||
 | 
			
		||||
      // If the string doesn't completely fill the line...
 | 
			
		||||
      if (rlen < max_status_chars) {
 | 
			
		||||
        lcd_put_wchar('.');                   // Always at 1+ spaces left, draw a dot
 | 
			
		||||
        uint8_t chars = max_status_chars - rlen;  // Amount of space left in characters
 | 
			
		||||
        if (--chars) {                        // Draw a second dot if there's space
 | 
			
		||||
          lcd_put_wchar('.');
 | 
			
		||||
          if (--chars)
 | 
			
		||||
            lcd_put_u8str_max(status_message, chars); // Print a second copy of the message
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (last_blink != blink) {
 | 
			
		||||
        last_blink = blink;
 | 
			
		||||
        advance_status_scroll();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  #else
 | 
			
		||||
 | 
			
		||||
    UNUSED(blink);
 | 
			
		||||
 | 
			
		||||
    if (status_changed()) {
 | 
			
		||||
      // Get the UTF8 character count of the string
 | 
			
		||||
      uint8_t slen = utf8_strlen(status_message);
 | 
			
		||||
 | 
			
		||||
      // Just print the string to the LCD
 | 
			
		||||
      lcd_put_u8str_max(status_message, max_status_chars);
 | 
			
		||||
 | 
			
		||||
      // Fill the rest with spaces if there are missing spaces
 | 
			
		||||
      while (slen < max_status_chars) { lcd_put_wchar(' '); ++slen; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  #endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if HAS_LCD_MENU
 | 
			
		||||
 | 
			
		||||
  #include "../../menu/menu.h"
 | 
			
		||||
 | 
			
		||||
  #if ENABLED(ADVANCED_PAUSE_FEATURE)
 | 
			
		||||
 | 
			
		||||
    void MarlinUI::draw_hotend_status(const uint8_t row, const uint8_t extruder) {
 | 
			
		||||
 | 
			
		||||
      dwin_font.solid = false;
 | 
			
		||||
      dwin_font.fg = Color_White;
 | 
			
		||||
      dwin_string.set("E");
 | 
			
		||||
      dwin_string.add('1' + extruder);
 | 
			
		||||
      dwin_string.add(' ');
 | 
			
		||||
      dwin_string.add(i16tostr3rj(thermalManager.degHotend(extruder)));
 | 
			
		||||
      dwin_string.add('/');
 | 
			
		||||
      if (get_blink() || !thermalManager.heater_idle[thermalManager.idle_index_for_id(extruder)].timed_out)
 | 
			
		||||
        dwin_string.add(i16tostr3rj(thermalManager.degTargetHotend(extruder)));
 | 
			
		||||
      else
 | 
			
		||||
        dwin_string.add(PSTR("    "));
 | 
			
		||||
 | 
			
		||||
      lcd_moveto(LCD_WIDTH - dwin_string.length(), row);
 | 
			
		||||
      lcd_put_dwin_string();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  // Set the colors for a menu item based on whether it is selected
 | 
			
		||||
  static bool mark_as_selected(const uint8_t row, const bool sel, const bool is_static=false) {
 | 
			
		||||
    const dwin_coord_t y = row * (MENU_LINE_HEIGHT) + 1;
 | 
			
		||||
    if (y >= LCD_PIXEL_HEIGHT) return false;
 | 
			
		||||
 | 
			
		||||
    if (is_static && sel)
 | 
			
		||||
      DWIN_Draw_Box(1, Color_Bg_Heading, 0, y, LCD_PIXEL_WIDTH, MENU_LINE_HEIGHT - 1);
 | 
			
		||||
    else {
 | 
			
		||||
      #if ENABLED(MENU_HOLLOW_FRAME)
 | 
			
		||||
                 DWIN_Draw_Box(1, Color_Bg_Black, 0, y, LCD_PIXEL_WIDTH, MENU_LINE_HEIGHT - 1);
 | 
			
		||||
        if (sel) DWIN_Draw_Box(0, Select_Color,   0, y, LCD_PIXEL_WIDTH, MENU_LINE_HEIGHT - 1);
 | 
			
		||||
      #else
 | 
			
		||||
        DWIN_Draw_Box(1, sel ? Select_Color : Color_Bg_Black, 0, y, LCD_PIXEL_WIDTH, MENU_LINE_HEIGHT - 1);
 | 
			
		||||
      #endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Draw a static line of text in the same idiom as a menu item
 | 
			
		||||
 | 
			
		||||
  void MenuItem_static::draw(const uint8_t row, PGM_P const pstr, const uint8_t style/*=SS_DEFAULT*/, const char * const vstr/*=nullptr*/) {
 | 
			
		||||
    // Call mark_as_selected to draw a bigger selection box
 | 
			
		||||
    // and draw the text without a background
 | 
			
		||||
    if (mark_as_selected(row, (bool)(style & SS_INVERT), true)) {
 | 
			
		||||
      ui.set_font(DWIN_FONT_MENU);
 | 
			
		||||
      dwin_font.solid = false;
 | 
			
		||||
      dwin_font.fg = Color_White;
 | 
			
		||||
 | 
			
		||||
      dwin_string.set();
 | 
			
		||||
      const int8_t plen = pstr ? utf8_strlen_P(pstr) : 0,
 | 
			
		||||
                   vlen = vstr ? utf8_strlen(vstr) : 0;
 | 
			
		||||
      if (style & SS_CENTER) {
 | 
			
		||||
        int8_t pad = (LCD_WIDTH - 1 - plen - vlen) / 2;
 | 
			
		||||
        while (--pad) dwin_string.add(' ');
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (plen) dwin_string.add((uint8_t*)pstr, itemIndex, (uint8_t*)itemString);
 | 
			
		||||
      if (vlen) dwin_string.add((uint8_t*)vstr);
 | 
			
		||||
      if (style & SS_CENTER) {
 | 
			
		||||
        int8_t pad = (LCD_WIDTH - 1 - plen - vlen) / 2;
 | 
			
		||||
        while (--pad) dwin_string.add(' ');
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      lcd_moveto(1, row);
 | 
			
		||||
      lcd_put_dwin_string();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Draw a generic menu item
 | 
			
		||||
  void MenuItemBase::_draw(const bool sel, const uint8_t row, PGM_P const pstr, const char, const char post_char) {
 | 
			
		||||
    if (mark_as_selected(row, sel)) {
 | 
			
		||||
      ui.set_font(DWIN_FONT_MENU);
 | 
			
		||||
      dwin_font.solid = false;
 | 
			
		||||
      dwin_font.fg = Color_White;
 | 
			
		||||
 | 
			
		||||
      dwin_string.set(pstr, itemIndex, itemString);
 | 
			
		||||
 | 
			
		||||
      pixel_len_t n = LCD_WIDTH - 1 - dwin_string.length();
 | 
			
		||||
      while (--n > 1) dwin_string.add(' ');
 | 
			
		||||
 | 
			
		||||
      dwin_string.add(post_char);
 | 
			
		||||
 | 
			
		||||
      lcd_moveto(1, row);
 | 
			
		||||
      lcd_put_dwin_string();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Draw a menu item with an editable value
 | 
			
		||||
  //
 | 
			
		||||
  void MenuEditItemBase::draw(const bool sel, const uint8_t row, PGM_P const pstr, const char* const data, const bool pgm) {
 | 
			
		||||
    if (mark_as_selected(row, sel)) {
 | 
			
		||||
      ui.set_font(DWIN_FONT_MENU);
 | 
			
		||||
      dwin_font.solid = false;
 | 
			
		||||
      dwin_font.fg = Color_White;
 | 
			
		||||
 | 
			
		||||
      const uint8_t vallen = (pgm ? utf8_strlen_P(data) : utf8_strlen(S(data)));
 | 
			
		||||
 | 
			
		||||
      dwin_string.set(pstr, itemIndex, itemString);
 | 
			
		||||
      if (vallen) dwin_string.add(':');
 | 
			
		||||
 | 
			
		||||
      lcd_moveto(1, row);
 | 
			
		||||
      lcd_put_dwin_string();
 | 
			
		||||
 | 
			
		||||
      if (vallen) {
 | 
			
		||||
        dwin_font.fg = Color_Yellow;
 | 
			
		||||
        dwin_string.set(data);
 | 
			
		||||
        lcd_moveto(LCD_WIDTH - vallen - 1, row);
 | 
			
		||||
        lcd_put_dwin_string();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Draw an edit screen with label and current value
 | 
			
		||||
  //
 | 
			
		||||
  void MenuEditItemBase::draw_edit_screen(PGM_P const pstr, const char* const value/*=nullptr*/) {
 | 
			
		||||
    ui.encoder_direction_normal();
 | 
			
		||||
 | 
			
		||||
    const dwin_coord_t labellen = utf8_strlen_P(pstr), vallen = utf8_strlen(value);
 | 
			
		||||
 | 
			
		||||
    dwin_string.set();
 | 
			
		||||
    dwin_string.add((uint8_t*)pstr, itemIndex);
 | 
			
		||||
    if (vallen) dwin_string.add(':');  // If a value is included, add a colon
 | 
			
		||||
 | 
			
		||||
    // Assume the label is alpha-numeric (with a descender)
 | 
			
		||||
    const uint16_t row = (LCD_HEIGHT / 2) - 1;
 | 
			
		||||
 | 
			
		||||
    dwin_font.fg = Color_White;
 | 
			
		||||
    dwin_font.solid = true;
 | 
			
		||||
    lcd_moveto((LCD_WIDTH - labellen + !!vallen) / 2, row);
 | 
			
		||||
    lcd_put_dwin_string();
 | 
			
		||||
 | 
			
		||||
    // If a value is included, print the value in larger text below the label
 | 
			
		||||
    if (vallen) {
 | 
			
		||||
      dwin_string.set();
 | 
			
		||||
      dwin_string.add(value);
 | 
			
		||||
 | 
			
		||||
      const dwin_coord_t by = (row * MENU_LINE_HEIGHT) + MENU_FONT_HEIGHT + EXTRA_ROW_HEIGHT / 2;
 | 
			
		||||
      DWIN_Draw_String(true, font16x32, Color_Yellow, Color_Bg_Black, (LCD_PIXEL_WIDTH - vallen * 16) / 2, by, S(dwin_string.string()));
 | 
			
		||||
 | 
			
		||||
      extern screenFunc_t _manual_move_func_ptr;
 | 
			
		||||
      if (ui.currentScreen != _manual_move_func_ptr && !ui.external_control) {
 | 
			
		||||
 | 
			
		||||
        const dwin_coord_t slider_length = LCD_PIXEL_WIDTH - TERN(DWIN_MARLINUI_LANDSCAPE, 120, 20),
 | 
			
		||||
                           slider_height = 16,
 | 
			
		||||
                           slider_x = (LCD_PIXEL_WIDTH - slider_length) / 2,
 | 
			
		||||
                           slider_y = by + 32 + 4,
 | 
			
		||||
                           amount = ui.encoderPosition * slider_length / maxEditValue;
 | 
			
		||||
 | 
			
		||||
        DWIN_Draw_Rectangle(1, Color_Bg_Window, slider_x - 1, slider_y - 1, slider_x - 1 + slider_length + 2 - 1, slider_y - 1 + slider_height + 2 - 1);
 | 
			
		||||
        if (amount > 0)
 | 
			
		||||
          DWIN_Draw_Box(1, BarFill_Color, slider_x, slider_y, amount, slider_height);
 | 
			
		||||
        if (amount < slider_length)
 | 
			
		||||
          DWIN_Draw_Box(1, Color_Bg_Black, slider_x + amount, slider_y, slider_length - amount, slider_height);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  inline void draw_boxed_string(const bool yesopt, PGM_P const pstr, const bool inv) {
 | 
			
		||||
    const uint8_t len = utf8_strlen_P(pstr),
 | 
			
		||||
                  mar = TERN(DWIN_MARLINUI_PORTRAIT, 1, 4),
 | 
			
		||||
                  col = yesopt ? LCD_WIDTH - mar - len : mar,
 | 
			
		||||
                  row = (LCD_HEIGHT >= 8 ? LCD_HEIGHT / 2 + 3 : LCD_HEIGHT - 1);
 | 
			
		||||
    lcd_moveto(col, row);
 | 
			
		||||
    DWIN_Draw_Box(1, inv ? Select_Color : Color_Bg_Black, cursor.x - dwin_font.width, cursor.y + 1, dwin_font.width * (len + 2), dwin_font.height + 2);
 | 
			
		||||
    lcd_put_u8str_P(col, row, pstr);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void MenuItem_confirm::draw_select_screen(
 | 
			
		||||
    PGM_P const yes, PGM_P const no, const bool yesno,
 | 
			
		||||
    PGM_P const pref, const char * const string/*=nullptr*/, PGM_P const suff/*=nullptr*/
 | 
			
		||||
  ) {
 | 
			
		||||
    ui.set_font(DWIN_FONT_MENU);
 | 
			
		||||
    dwin_font.solid = false;
 | 
			
		||||
    dwin_font.fg = Color_White;
 | 
			
		||||
    ui.draw_select_screen_prompt(pref, string, suff);
 | 
			
		||||
    draw_boxed_string(false, no, !yesno);
 | 
			
		||||
    draw_boxed_string(true, yes,  yesno);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #if ENABLED(SDSUPPORT)
 | 
			
		||||
 | 
			
		||||
    void MenuItem_sdbase::draw(const bool sel, const uint8_t row, PGM_P const, CardReader &theCard, const bool isDir) {
 | 
			
		||||
      if (mark_as_selected(row, sel)) {
 | 
			
		||||
        dwin_string.set();
 | 
			
		||||
 | 
			
		||||
        uint8_t maxlen = LCD_WIDTH - 1;
 | 
			
		||||
        if (isDir) {
 | 
			
		||||
          dwin_string.add(LCD_STR_FOLDER " ");
 | 
			
		||||
          maxlen -= 2;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        dwin_string.add((uint8_t*)ui.scrolled_filename(theCard, maxlen, row, sel), maxlen);
 | 
			
		||||
        uint8_t n = maxlen - dwin_string.length();
 | 
			
		||||
        while (n > 0) { dwin_string.add(' '); --n; }
 | 
			
		||||
        lcd_moveto(1, row);
 | 
			
		||||
        lcd_put_dwin_string();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  #endif // SDSUPPORT
 | 
			
		||||
 | 
			
		||||
  #if ENABLED(AUTO_BED_LEVELING_UBL)
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * UBL LCD "radar" map data
 | 
			
		||||
     */
 | 
			
		||||
    #define MAP_UPPER_LEFT_CORNER_X   5  // These probably should be moved to the .h file  But for now,
 | 
			
		||||
    #define MAP_UPPER_LEFT_CORNER_Y   5  // it is easier to play with things having them here
 | 
			
		||||
    #define MAP_MAX_PIXELS_X        262  // 272 - 10
 | 
			
		||||
    #define MAP_MAX_PIXELS_Y        262
 | 
			
		||||
 | 
			
		||||
    void MarlinUI::ubl_plot(const uint8_t x_plot, const uint8_t y_plot) {
 | 
			
		||||
      // Scale the box pixels appropriately
 | 
			
		||||
      dwin_coord_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),
 | 
			
		||||
 | 
			
		||||
              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
 | 
			
		||||
 | 
			
		||||
      // First draw the bigger box in White so we have a border around the mesh map box
 | 
			
		||||
      DWIN_Draw_Rectangle(1, Color_White, x_offset - 2, y_offset - 2, x_offset + 2 + x_map_pixels, y_offset + 2 + y_map_pixels);
 | 
			
		||||
      // Now actually clear the mesh map box
 | 
			
		||||
      DWIN_Draw_Rectangle(1, Color_Bg_Black, x_offset, y_offset, x_offset + x_map_pixels, y_offset + y_map_pixels);
 | 
			
		||||
 | 
			
		||||
      // Fill in the Specified Mesh Point
 | 
			
		||||
 | 
			
		||||
      const uint8_t y_plot_inv = (GRID_MAX_POINTS_Y - 1) - y_plot;  // The origin is typically in the lower right corner.  We need to
 | 
			
		||||
                                                                    // invert the Y to get it to plot in the right location.
 | 
			
		||||
 | 
			
		||||
      const dwin_coord_t by = y_offset + y_plot_inv * pixels_per_y_mesh_pnt;
 | 
			
		||||
      DWIN_Draw_Rectangle(1, Select_Color,
 | 
			
		||||
        x_offset + (x_plot * pixels_per_x_mesh_pnt), by,
 | 
			
		||||
        x_offset + (x_plot * pixels_per_x_mesh_pnt) + pixels_per_x_mesh_pnt, by + pixels_per_y_mesh_pnt
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      // Display Mesh Point Locations
 | 
			
		||||
      const dwin_coord_t sx = x_offset + pixels_per_x_mesh_pnt / 2;
 | 
			
		||||
            dwin_coord_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)
 | 
			
		||||
        for (uint8_t i = 0, x = sx; i < GRID_MAX_POINTS_X; i++, x += pixels_per_x_mesh_pnt)
 | 
			
		||||
          DWIN_Draw_Point(Color_White, 1, 1, x, y);
 | 
			
		||||
 | 
			
		||||
      // Put Relevant Text on Display
 | 
			
		||||
 | 
			
		||||
      // Show X and Y positions at top of screen
 | 
			
		||||
      dwin_font.fg = Color_White;
 | 
			
		||||
      dwin_font.solid = true;
 | 
			
		||||
      const xy_pos_t pos = { ubl.mesh_index_to_xpos(x_plot), ubl.mesh_index_to_ypos(y_plot) },
 | 
			
		||||
                     lpos = pos.asLogical();
 | 
			
		||||
 | 
			
		||||
      lcd_moveto(
 | 
			
		||||
        TERN(DWIN_MARLINUI_LANDSCAPE, ((x_offset + x_map_pixels) / MENU_FONT_WIDTH) + 2, 1),
 | 
			
		||||
        TERN(DWIN_MARLINUI_LANDSCAPE, 1, ((y_offset + y_map_pixels) / MENU_LINE_HEIGHT) + 1)
 | 
			
		||||
      );
 | 
			
		||||
      lcd_put_u8str_P(X_LBL);
 | 
			
		||||
      lcd_put_u8str(ftostr52(lpos.x));
 | 
			
		||||
      lcd_moveto(
 | 
			
		||||
        TERN(DWIN_MARLINUI_LANDSCAPE, ((x_offset + x_map_pixels) / MENU_FONT_WIDTH) + 2, 1),
 | 
			
		||||
        TERN(DWIN_MARLINUI_LANDSCAPE, 3, ((y_offset + y_map_pixels) / MENU_LINE_HEIGHT) + 2)
 | 
			
		||||
      );
 | 
			
		||||
      lcd_put_u8str_P(Y_LBL);
 | 
			
		||||
      lcd_put_u8str(ftostr52(lpos.y));
 | 
			
		||||
 | 
			
		||||
      // Print plot position
 | 
			
		||||
      dwin_string.set("(");
 | 
			
		||||
      dwin_string.add(i8tostr3rj(x_plot));
 | 
			
		||||
      dwin_string.add(",");
 | 
			
		||||
      dwin_string.add(i8tostr3rj(y_plot));
 | 
			
		||||
      dwin_string.add(")");
 | 
			
		||||
      lcd_moveto(
 | 
			
		||||
        TERN(DWIN_MARLINUI_LANDSCAPE, ((x_offset + x_map_pixels) / MENU_FONT_WIDTH) + 2, LCD_WIDTH - dwin_string.length()),
 | 
			
		||||
        TERN(DWIN_MARLINUI_LANDSCAPE, LCD_HEIGHT - 2, ((y_offset + y_map_pixels) / MENU_LINE_HEIGHT) + 1)
 | 
			
		||||
      );
 | 
			
		||||
      lcd_put_dwin_string();
 | 
			
		||||
 | 
			
		||||
      // Show the location value
 | 
			
		||||
      dwin_string.set(Z_LBL);
 | 
			
		||||
      if (!isnan(ubl.z_values[x_plot][y_plot]))
 | 
			
		||||
        dwin_string.add(ftostr43sign(ubl.z_values[x_plot][y_plot]));
 | 
			
		||||
      else
 | 
			
		||||
        dwin_string.add(PSTR(" -----"));
 | 
			
		||||
      lcd_moveto(
 | 
			
		||||
        TERN(DWIN_MARLINUI_LANDSCAPE, ((x_offset + x_map_pixels) / MENU_FONT_WIDTH) + 2, LCD_WIDTH - dwin_string.length()),
 | 
			
		||||
        TERN(DWIN_MARLINUI_LANDSCAPE, LCD_HEIGHT - 1, ((y_offset + y_map_pixels) / MENU_LINE_HEIGHT) + 2)
 | 
			
		||||
      );
 | 
			
		||||
      lcd_put_dwin_string();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  #endif // AUTO_BED_LEVELING_UBL
 | 
			
		||||
 | 
			
		||||
  #if ANY(BABYSTEP_ZPROBE_GFX_OVERLAY, MESH_EDIT_GFX_OVERLAY, BABYSTEP_GFX_OVERLAY)
 | 
			
		||||
 | 
			
		||||
    void _lcd_zoffset_overlay_gfx(const float zvalue) {
 | 
			
		||||
      // Determine whether the user is raising or lowering the nozzle.
 | 
			
		||||
      static int8_t dir;
 | 
			
		||||
      static float old_zvalue;
 | 
			
		||||
      if (zvalue != old_zvalue) {
 | 
			
		||||
        dir = zvalue ? zvalue < old_zvalue ? -1 : 1 : 0;
 | 
			
		||||
        old_zvalue = zvalue;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const int rot_up = TERN(OVERLAY_GFX_REVERSE, ICON_RotateCCW, ICON_RotateCW),
 | 
			
		||||
                rot_down = TERN(OVERLAY_GFX_REVERSE, ICON_RotateCW, ICON_RotateCCW);
 | 
			
		||||
 | 
			
		||||
      const int nozzle = (LCD_PIXEL_WIDTH / 2) - 20;
 | 
			
		||||
 | 
			
		||||
      // Draw a representation of the nozzle
 | 
			
		||||
      DWIN_Draw_Box(1, Color_Bg_Black, nozzle + 3, 8, 48, 52); // 'clear' the area where the nozzle is drawn in case it was moved up/down
 | 
			
		||||
      DWIN_ICON_Show(ICON, ICON_HotendOff, nozzle + 3, 10 - dir);
 | 
			
		||||
      DWIN_ICON_Show(ICON, ICON_BedLine, nozzle, 10 + 36);
 | 
			
		||||
 | 
			
		||||
      // Draw cw/ccw indicator and up/down arrows
 | 
			
		||||
      const int arrow_y = LCD_PIXEL_HEIGHT / 2 - 24;
 | 
			
		||||
      DWIN_ICON_Show(ICON, ICON_DownArrow, 0, arrow_y - dir);
 | 
			
		||||
      DWIN_ICON_Show(ICON, rot_down, 48, arrow_y);
 | 
			
		||||
 | 
			
		||||
      DWIN_ICON_Show(ICON, ICON_UpArrow, LCD_PIXEL_WIDTH - 10 - (48*2), arrow_y - dir);
 | 
			
		||||
      DWIN_ICON_Show(ICON, rot_up, LCD_PIXEL_WIDTH - 10 - 48, arrow_y);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  #endif // BABYSTEP_ZPROBE_GFX_OVERLAY || MESH_EDIT_GFX_OVERLAY
 | 
			
		||||
 | 
			
		||||
#endif // HAS_LCD_MENU
 | 
			
		||||
 | 
			
		||||
#endif // IS_DWIN_MARLINUI
 | 
			
		||||
							
								
								
									
										391
									
								
								Marlin/src/lcd/e3v2/marlinui/ui_status_480x272.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										391
									
								
								Marlin/src/lcd/e3v2/marlinui/ui_status_480x272.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,391 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Marlin 3D Printer Firmware
 | 
			
		||||
 * Copyright (c) 2021 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/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "../../../inc/MarlinConfigPre.h"
 | 
			
		||||
 | 
			
		||||
#if IS_DWIN_MARLINUI
 | 
			
		||||
 | 
			
		||||
#include "marlinui_dwin.h"
 | 
			
		||||
#include "dwin_lcd.h"
 | 
			
		||||
#include "dwin_string.h"
 | 
			
		||||
#include "lcdprint_dwin.h"
 | 
			
		||||
 | 
			
		||||
#include "../../fontutils.h"
 | 
			
		||||
#include "../../../libs/numtostr.h"
 | 
			
		||||
#include "../../marlinui.h"
 | 
			
		||||
 | 
			
		||||
#include "../../../sd/cardreader.h"
 | 
			
		||||
#include "../../../module/motion.h"
 | 
			
		||||
#include "../../../module/temperature.h"
 | 
			
		||||
#include "../../../module/printcounter.h"
 | 
			
		||||
 | 
			
		||||
#if ENABLED(SDSUPPORT)
 | 
			
		||||
  #include "../../../libs/duration_t.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if ENABLED(LCD_SHOW_E_TOTAL)
 | 
			
		||||
  #include "../../../MarlinCore.h" // for printingIsActive
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define STATUS_HEATERS_X      15
 | 
			
		||||
#define STATUS_HEATERS_Y      56
 | 
			
		||||
#define STATUS_HEATERS_XSPACE 64
 | 
			
		||||
#define STATUS_FAN_WIDTH      48
 | 
			
		||||
#define STATUS_FAN_HEIGHT     48
 | 
			
		||||
#define STATUS_FAN_Y          STATUS_HEATERS_Y + 22
 | 
			
		||||
#define STATUS_CHR_WIDTH      14
 | 
			
		||||
#define STATUS_CHR_HEIGHT     28
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Before homing, blink '123' <-> '???'.
 | 
			
		||||
// Homed but unknown... '123' <-> '   '.
 | 
			
		||||
// Homed and known, display constantly.
 | 
			
		||||
//
 | 
			
		||||
FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const bool blink, const uint16_t x, const uint16_t y) {
 | 
			
		||||
  uint8_t vallen = utf8_strlen(value);
 | 
			
		||||
 | 
			
		||||
  if (!ui.did_first_redraw) {
 | 
			
		||||
    dwin_string.set();
 | 
			
		||||
    dwin_string.add('X' + axis);
 | 
			
		||||
    DWIN_Draw_String(true, font16x32, Color_IconBlue, Color_Bg_Black, x + (vallen * 14 - 14) / 2, y + 2, S(dwin_string.string()));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  dwin_string.set();
 | 
			
		||||
  if (blink)
 | 
			
		||||
    dwin_string.add(value);
 | 
			
		||||
  else {
 | 
			
		||||
    if (!TEST(axis_homed, axis))
 | 
			
		||||
      while (const char c = *value++) dwin_string.add(c <= '.' ? c : '?');
 | 
			
		||||
    else {
 | 
			
		||||
      #if NONE(HOME_AFTER_DEACTIVATE, DISABLE_REDUCED_ACCURACY_WARNING)
 | 
			
		||||
        if (!TEST(axis_trusted, axis))
 | 
			
		||||
          dwin_string.add(TERN1(DWIN_MARLINUI_PORTRAIT, axis == Z_AXIS) ? PSTR("       ") : PSTR("    "));
 | 
			
		||||
        else
 | 
			
		||||
      #endif
 | 
			
		||||
          dwin_string.add(value);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // For E_TOTAL there may be some characters to cover up
 | 
			
		||||
  if (BOTH(DWIN_MARLINUI_PORTRAIT, LCD_SHOW_E_TOTAL) && axis == X_AXIS)
 | 
			
		||||
    dwin_string.add("   ");
 | 
			
		||||
 | 
			
		||||
  DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + 32, S(dwin_string.string()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if ENABLED(LCD_SHOW_E_TOTAL)
 | 
			
		||||
 | 
			
		||||
  FORCE_INLINE void _draw_e_value(const_float_t value, const uint16_t x, const uint16_t y) {
 | 
			
		||||
    const uint8_t scale = value >= 100000.0f ? 10 : 1; // show cm after 99,999mm
 | 
			
		||||
 | 
			
		||||
    if (!ui.did_first_redraw) {
 | 
			
		||||
      // Extra spaces so we don't have to clear the 'Y' label separately
 | 
			
		||||
      dwin_string.set("E         ");
 | 
			
		||||
      DWIN_Draw_String(true, font16x32, Color_IconBlue, Color_Bg_Black, x + (4 * 14 / 2) - 7, y + 2, S(dwin_string.string()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dwin_string.set(ui16tostr5rj(value / scale));
 | 
			
		||||
    DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + 32, S(dwin_string.string()));
 | 
			
		||||
 | 
			
		||||
    // Extra spaces so we don't have to clear out the Y value separately
 | 
			
		||||
    DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, x + (5 * 14), y + 32, S(scale == 1 ? "mm      " : "cm      "));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Fan Icon and Percentage
 | 
			
		||||
//
 | 
			
		||||
FORCE_INLINE void _draw_fan_status(const uint16_t x, const uint16_t y) {
 | 
			
		||||
  const uint16_t fanx = (4 * STATUS_CHR_WIDTH - STATUS_FAN_WIDTH) / 2;
 | 
			
		||||
  const uint8_t fan_pct = thermalManager.scaledFanSpeedPercent(0);
 | 
			
		||||
  const bool fan_on = !!fan_pct;
 | 
			
		||||
  if (fan_on) {
 | 
			
		||||
    DWIN_ICON_Animation(0, fan_on, ICON, ICON_Fan0, ICON_Fan3, x + fanx, y, 25);
 | 
			
		||||
    dwin_string.set(i8tostr3rj(fan_pct));
 | 
			
		||||
    dwin_string.add('%');
 | 
			
		||||
    DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + STATUS_FAN_HEIGHT, S(dwin_string.string()));
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    DWIN_ICON_Show(ICON, ICON_Fan0, x + fanx, y);
 | 
			
		||||
    dwin_string.set(PSTR("    "));
 | 
			
		||||
    DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + STATUS_FAN_HEIGHT, S(dwin_string.string()));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if HOTENDS > 2
 | 
			
		||||
  #define HOTEND_STATS 3
 | 
			
		||||
#elif HOTENDS > 1
 | 
			
		||||
  #define HOTEND_STATS 2
 | 
			
		||||
#elif HAS_HOTEND
 | 
			
		||||
  #define HOTEND_STATS 1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Draw a single heater icon with current and target temperature, at the given XY
 | 
			
		||||
 */
 | 
			
		||||
FORCE_INLINE void _draw_heater_status(const heater_id_t heater, const uint16_t x, const uint16_t y) {
 | 
			
		||||
 | 
			
		||||
  #if HAS_HOTEND
 | 
			
		||||
    static celsius_t old_temp[HOTEND_STATS] = ARRAY_N_1(HOTEND_STATS, 500),
 | 
			
		||||
                     old_target[HOTEND_STATS] = ARRAY_N_1(HOTEND_STATS, 500);
 | 
			
		||||
    static bool old_on[HOTEND_STATS] = ARRAY_N_1(HOTEND_STATS, false);
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if HAS_HEATED_BED
 | 
			
		||||
    static celsius_t old_bed_temp = 500, old_bed_target = 500;
 | 
			
		||||
    static bool old_bed_on = false;
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if HAS_HOTEND && HAS_HEATED_BED
 | 
			
		||||
    const bool isBed = heater < 0;
 | 
			
		||||
    const float tc = (isBed ? thermalManager.degBed()       : thermalManager.degHotend(heater)),
 | 
			
		||||
                tt = (isBed ? thermalManager.degTargetBed() : thermalManager.degTargetHotend(heater));
 | 
			
		||||
    const uint8_t ta = isBed ? thermalManager.isHeatingBed() : thermalManager.isHeatingHotend(heater);
 | 
			
		||||
    const bool c_draw = tc != (isBed ? old_bed_temp : old_temp[heater]),
 | 
			
		||||
               t_draw = tt != (isBed ? old_bed_target : old_target[heater]),
 | 
			
		||||
               i_draw = ta != (isBed ? old_bed_on : old_on[heater]);
 | 
			
		||||
    if (isBed) { old_bed_temp = tc; old_bed_target = tt; old_bed_on = ta; }
 | 
			
		||||
    else { old_temp[heater] = tc; old_target[heater] = tt; old_on[heater] = ta; }
 | 
			
		||||
  #elif HAS_HOTEND
 | 
			
		||||
    constexpr bool isBed = false;
 | 
			
		||||
    const float tc = thermalManager.degHotend(heater), tt = thermalManager.degTargetHotend(heater);
 | 
			
		||||
    const uint8_t ta = thermalManager.isHeatingHotend(heater);
 | 
			
		||||
    const bool c_draw = tc != old_bed_temp, t_draw = tt != old_bed_target, i_draw = ta != old_bed_on;
 | 
			
		||||
    old_temp[heater] = tc; old_target[heater] = tt; old_on[heater] = ta;
 | 
			
		||||
  #elif HAS_HEATED_BED
 | 
			
		||||
    constexpr bool isBed = true;
 | 
			
		||||
    const float tc = thermalManager.degBed(), tt = thermalManager.degTargetBed();
 | 
			
		||||
    const uint8_t ta = thermalManager.isHeatingBed();
 | 
			
		||||
    const bool c_draw = tc != old_temp[heater], t_draw = tt != old_target[heater], i_draw = ta != old_on[heater];
 | 
			
		||||
    old_bed_temp = tc; old_bed_target = tt; old_bed_on = ta;
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  if (!ui.did_first_redraw || t_draw) {
 | 
			
		||||
    dwin_string.set(i16tostr3rj(tt + 0.5));
 | 
			
		||||
    dwin_string.add(LCD_STR_DEGREE);
 | 
			
		||||
    DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y, S(dwin_string.string()));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!ui.did_first_redraw || i_draw)
 | 
			
		||||
    DWIN_ICON_Show(ICON, (isBed ? ICON_BedOff : ICON_HotendOff) + ta, x, y + STATUS_CHR_HEIGHT + 2);
 | 
			
		||||
 | 
			
		||||
  if (!ui.did_first_redraw || c_draw) {
 | 
			
		||||
    dwin_string.set(i16tostr3rj(tc + 0.5));
 | 
			
		||||
    dwin_string.add(LCD_STR_DEGREE);
 | 
			
		||||
    DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x, y + 70, S(dwin_string.string()));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Draw the current "feed rate" percentage preceded by the >> character
 | 
			
		||||
 */
 | 
			
		||||
FORCE_INLINE void _draw_feedrate_status(const char *value, uint16_t x, uint16_t y) {
 | 
			
		||||
  if (!ui.did_first_redraw) {
 | 
			
		||||
    dwin_string.set(LCD_STR_FEEDRATE);
 | 
			
		||||
    DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, x, y, S(dwin_string.string()));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  dwin_string.set(value);
 | 
			
		||||
  dwin_string.add(PSTR("%"));
 | 
			
		||||
  DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, x + 14, y, S(dwin_string.string()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Draw the MarlinUI Status Screen for Ender 3 V2
 | 
			
		||||
 */
 | 
			
		||||
void MarlinUI::draw_status_screen() {
 | 
			
		||||
  const bool blink = get_blink();
 | 
			
		||||
 | 
			
		||||
  // Draw elements that never change
 | 
			
		||||
  if (!ui.did_first_redraw) {
 | 
			
		||||
    // Logo/Status Icon
 | 
			
		||||
    #define STATUS_LOGO_WIDTH  128
 | 
			
		||||
    #define STATUS_LOGO_HEIGHT  40
 | 
			
		||||
    DWIN_ICON_Show(ICON, ICON_LOGO_Marlin, (LCD_PIXEL_WIDTH - (STATUS_LOGO_WIDTH)) / 2, ((STATUS_HEATERS_Y - 4) - (STATUS_LOGO_HEIGHT)) / 2);
 | 
			
		||||
 | 
			
		||||
    // Draw a frame around the x/y/z values
 | 
			
		||||
    #if ENABLED(DWIN_MARLINUI_PORTRAIT)
 | 
			
		||||
      DWIN_Draw_Rectangle(0, Select_Color, 0, 193, LCD_PIXEL_WIDTH, 260);
 | 
			
		||||
    #else
 | 
			
		||||
      //DWIN_Draw_Rectangle(0, Select_Color, LCD_PIXEL_WIDTH - 106, 50, LCD_PIXEL_WIDTH - 1, 230);
 | 
			
		||||
    #endif
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  uint16_t hx = STATUS_HEATERS_X;
 | 
			
		||||
  #if HAS_HOTEND
 | 
			
		||||
    _draw_heater_status(H_E0, hx, STATUS_HEATERS_Y);
 | 
			
		||||
    hx += STATUS_HEATERS_XSPACE;
 | 
			
		||||
  #endif
 | 
			
		||||
  #if HAS_MULTI_HOTEND
 | 
			
		||||
    _draw_heater_status(H_E1, hx, STATUS_HEATERS_Y);
 | 
			
		||||
    hx += STATUS_HEATERS_XSPACE;
 | 
			
		||||
  #endif
 | 
			
		||||
  #if HAS_HEATED_BED
 | 
			
		||||
    _draw_heater_status(H_BED, hx, STATUS_HEATERS_Y);
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if HAS_FAN
 | 
			
		||||
    // Fan display, pinned to the right side
 | 
			
		||||
    #if ENABLED(DWIN_MARLINUI_PORTRAIT)
 | 
			
		||||
      _draw_fan_status(LCD_PIXEL_WIDTH - STATUS_CHR_WIDTH * 4, STATUS_FAN_Y);
 | 
			
		||||
    #else
 | 
			
		||||
      _draw_fan_status(212, STATUS_FAN_Y);
 | 
			
		||||
    #endif
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  // Axis values
 | 
			
		||||
  const xyz_pos_t lpos = current_position.asLogical();
 | 
			
		||||
  const bool show_e_total = TERN0(LCD_SHOW_E_TOTAL, printingIsActive()); UNUSED(show_e_total);
 | 
			
		||||
  #if ENABLED(DWIN_MARLINUI_PORTRAIT)
 | 
			
		||||
    constexpr int16_t cpy = 195;
 | 
			
		||||
    if (show_e_total) {
 | 
			
		||||
      TERN_(LCD_SHOW_E_TOTAL, _draw_e_value(e_move_accumulator, 6, cpy));
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
                        _draw_axis_value(X_AXIS, ftostr4sign(lpos.x), blink,  6, cpy);
 | 
			
		||||
      TERN_(HAS_Y_AXIS, _draw_axis_value(Y_AXIS, ftostr4sign(lpos.y), blink, 95, cpy));
 | 
			
		||||
    }
 | 
			
		||||
    TERN_(HAS_Z_AXIS, _draw_axis_value(Z_AXIS, ftostr52sp(lpos.z), blink, 165, cpy));
 | 
			
		||||
  #else
 | 
			
		||||
    constexpr int16_t cpx = LCD_PIXEL_WIDTH - 104;
 | 
			
		||||
                      _draw_axis_value(X_AXIS, ftostr52sp(lpos.x), blink, cpx, STATUS_HEATERS_Y);
 | 
			
		||||
    TERN_(HAS_Y_AXIS, _draw_axis_value(Y_AXIS, ftostr52sp(lpos.y), blink, cpx, STATUS_HEATERS_Y + 59));
 | 
			
		||||
    TERN_(HAS_Z_AXIS, _draw_axis_value(Z_AXIS, ftostr52sp(lpos.z), blink, cpx, STATUS_HEATERS_Y + 118));
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  // Feedrate
 | 
			
		||||
  static uint16_t old_fp = 0;
 | 
			
		||||
  if (!ui.did_first_redraw || old_fp != feedrate_percentage) {
 | 
			
		||||
    old_fp = feedrate_percentage;
 | 
			
		||||
    _draw_feedrate_status(i16tostr3rj(feedrate_percentage),
 | 
			
		||||
      #if ENABLED(DWIN_MARLINUI_PORTRAIT)
 | 
			
		||||
        5, 290
 | 
			
		||||
      #else
 | 
			
		||||
        294, STATUS_HEATERS_Y
 | 
			
		||||
      #endif
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Elapsed time
 | 
			
		||||
  //
 | 
			
		||||
  char buffer[14];
 | 
			
		||||
  duration_t time;
 | 
			
		||||
 | 
			
		||||
  #if ENABLED(DWIN_MARLINUI_PORTRAIT)
 | 
			
		||||
 | 
			
		||||
    // Portrait mode only shows one value at a time, and will rotate if ROTATE_PROGRESS_DISPLAY
 | 
			
		||||
    dwin_string.set();
 | 
			
		||||
    char prefix = ' ';
 | 
			
		||||
    #if ENABLED(SHOW_REMAINING_TIME)
 | 
			
		||||
      if (TERN1(ROTATE_PROGRESS_DISPLAY, blink) && print_job_timer.isRunning()) {
 | 
			
		||||
        time = get_remaining_time();
 | 
			
		||||
        prefix = 'R';
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
    #endif
 | 
			
		||||
        time = print_job_timer.duration();
 | 
			
		||||
 | 
			
		||||
    time.toDigital(buffer);
 | 
			
		||||
    dwin_string.add(prefix);
 | 
			
		||||
    dwin_string.add(buffer);
 | 
			
		||||
    DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, (LCD_PIXEL_WIDTH - ((dwin_string.length() + 1) * 14)), 290, S(dwin_string.string()));
 | 
			
		||||
 | 
			
		||||
  #else
 | 
			
		||||
 | 
			
		||||
    // landscape mode shows both elapsed and remaining (if SHOW_REMAINING_TIME)
 | 
			
		||||
    time = print_job_timer.duration();
 | 
			
		||||
    time.toDigital(buffer);
 | 
			
		||||
    dwin_string.set(" ");
 | 
			
		||||
    dwin_string.add(buffer);
 | 
			
		||||
    DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, 280, 100, S(dwin_string.string()));
 | 
			
		||||
 | 
			
		||||
    #if ENABLED(LCD_SHOW_E_TOTAL)
 | 
			
		||||
      if (show_e_total && TERN1(SHOW_REMAINING_TIME, !blink)) { // if SHOW_REMAINING_TIME is also
 | 
			
		||||
        const uint8_t escale = e_move_accumulator >= 100000.0f ? 10 : 1; // show cm after 99,000mm
 | 
			
		||||
 | 
			
		||||
        DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, 249, 135, S("E"));
 | 
			
		||||
        dwin_string.set(ui16tostr5rj(e_move_accumulator * escale));
 | 
			
		||||
        DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, 263, 135, S(dwin_string.string()));
 | 
			
		||||
        DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, 333, 135, S(escale==1 ? "mm" : "cm"));
 | 
			
		||||
      }
 | 
			
		||||
    #endif
 | 
			
		||||
    #if ENABLED(SHOW_REMAINING_TIME)
 | 
			
		||||
      if (!show_e_total || blink) {
 | 
			
		||||
        DWIN_Draw_String(true, font14x28, Color_IconBlue, Color_Bg_Black, 249, 135, S(" R "));
 | 
			
		||||
        time = get_remaining_time();
 | 
			
		||||
        time.toDigital(buffer);
 | 
			
		||||
        dwin_string.set(buffer);
 | 
			
		||||
        DWIN_Draw_String(true, font14x28, Color_White, Color_Bg_Black, 291, 135, S(dwin_string.string()));
 | 
			
		||||
      }
 | 
			
		||||
    #endif
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Progress Bar
 | 
			
		||||
  //
 | 
			
		||||
  constexpr int16_t pb_margin = 5, pb_left = pb_margin, pb_height = 60,
 | 
			
		||||
                    pb_right = LCD_PIXEL_WIDTH - TERN(DWIN_MARLINUI_PORTRAIT, 0, 107) - pb_margin,
 | 
			
		||||
                    pb_bottom = TERN(DWIN_MARLINUI_PORTRAIT, 410, 230),
 | 
			
		||||
                    pb_top = pb_bottom - pb_height,
 | 
			
		||||
                    pb_width = pb_right - pb_left;
 | 
			
		||||
 | 
			
		||||
  const progress_t progress = TERN(HAS_PRINT_PROGRESS_PERMYRIAD, get_progress_permyriad, get_progress_percent)();
 | 
			
		||||
 | 
			
		||||
  if (!ui.did_first_redraw)
 | 
			
		||||
    DWIN_Draw_Rectangle(0, Select_Color, pb_left, pb_top, pb_right, pb_bottom);   // Outline
 | 
			
		||||
 | 
			
		||||
  static uint16_t old_solid = 50;
 | 
			
		||||
  const uint16_t pb_solid = (pb_width - 2) * (progress / (PROGRESS_SCALE)) * 0.01f;
 | 
			
		||||
  const bool p_draw = !ui.did_first_redraw || old_solid != pb_solid;
 | 
			
		||||
 | 
			
		||||
  if (p_draw) {
 | 
			
		||||
    //if (pb_solid)
 | 
			
		||||
      DWIN_Draw_Rectangle(1, Select_Color, pb_left + 1, pb_top + 1, pb_left + pb_solid, pb_bottom - 1); // Fill the solid part
 | 
			
		||||
 | 
			
		||||
    //if (pb_solid < old_solid)
 | 
			
		||||
      DWIN_Draw_Rectangle(1, Color_Bg_Black, pb_left + 1 + pb_solid, pb_top + 1, pb_right - 1, pb_bottom - 1); // Erase the rest
 | 
			
		||||
 | 
			
		||||
    #if ENABLED(SHOW_SD_PERCENT)
 | 
			
		||||
      dwin_string.set(TERN(PRINT_PROGRESS_SHOW_DECIMALS, permyriadtostr4(progress), ui8tostr3rj(progress / (PROGRESS_SCALE))));
 | 
			
		||||
      dwin_string.add(PSTR("%"));
 | 
			
		||||
      DWIN_Draw_String(
 | 
			
		||||
        false, font16x32, Percent_Color, Color_Bg_Black,
 | 
			
		||||
        pb_left + (pb_width - dwin_string.length() * 16) / 2,
 | 
			
		||||
        pb_top + (pb_height - 32) / 2,
 | 
			
		||||
        S(dwin_string.string())
 | 
			
		||||
      );
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    old_solid = pb_solid;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Status Message
 | 
			
		||||
  //
 | 
			
		||||
  draw_status_message(blink);
 | 
			
		||||
 | 
			
		||||
  ui.did_first_redraw = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // IS_DWIN_MARLINUI
 | 
			
		||||
@@ -26,7 +26,7 @@
 | 
			
		||||
 | 
			
		||||
#include "../inc/MarlinConfigPre.h"
 | 
			
		||||
 | 
			
		||||
#if HAS_WIRED_LCD && !HAS_GRAPHICAL_TFT
 | 
			
		||||
#if HAS_WIRED_LCD && !HAS_GRAPHICAL_TFT && !IS_DWIN_MARLINUI
 | 
			
		||||
 | 
			
		||||
#include "marlinui.h"
 | 
			
		||||
#include "lcdprint.h"
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,21 @@
 | 
			
		||||
 | 
			
		||||
#include "../inc/MarlinConfig.h"
 | 
			
		||||
 | 
			
		||||
#if HAS_MARLINUI_U8GLIB
 | 
			
		||||
#if IS_DWIN_MARLINUI
 | 
			
		||||
 | 
			
		||||
  #include "e3v2/marlinui/marlinui_dwin.h"
 | 
			
		||||
 | 
			
		||||
  #define LCD_PIXEL_WIDTH     DWIN_WIDTH
 | 
			
		||||
  #define LCD_PIXEL_HEIGHT    DWIN_HEIGHT
 | 
			
		||||
  #define LCD_WIDTH           ((LCD_PIXEL_WIDTH)  / (MENU_FONT_WIDTH))
 | 
			
		||||
  #define LCD_HEIGHT          ((LCD_PIXEL_HEIGHT) / (MENU_LINE_HEIGHT))
 | 
			
		||||
 | 
			
		||||
  // The DWIN lcd_moveto function uses row / column, not pixels
 | 
			
		||||
  #define LCD_COL_X(col)    (col)
 | 
			
		||||
  #define LCD_ROW_Y(row)    (row)
 | 
			
		||||
  #define LCD_COL_X_RJ(len) (LCD_WIDTH - LCD_COL_X(len))
 | 
			
		||||
 | 
			
		||||
#elif HAS_MARLINUI_U8GLIB
 | 
			
		||||
 | 
			
		||||
  #include "dogm/u8g_fontutf8.h"
 | 
			
		||||
  typedef u8g_uint_t lcd_uint_t;
 | 
			
		||||
@@ -105,7 +119,10 @@
 | 
			
		||||
  #define MENU_LINE_HEIGHT MENU_FONT_HEIGHT
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define LCD_COL_X_RJ(len)      (LCD_PIXEL_WIDTH - LCD_COL_X(len))
 | 
			
		||||
#ifndef LCD_COL_X_RJ
 | 
			
		||||
  #define LCD_COL_X_RJ(len)    (LCD_PIXEL_WIDTH - LCD_COL_X(len))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define SETCURSOR(col, row)    lcd_moveto(LCD_COL_X(col), LCD_ROW_Y(row))
 | 
			
		||||
#define SETCURSOR_RJ(len, row) lcd_moveto(LCD_COL_X_RJ(len), LCD_ROW_Y(row))
 | 
			
		||||
#define SETCURSOR_X(col)       SETCURSOR(col, _lcdLineNr)
 | 
			
		||||
 
 | 
			
		||||
@@ -202,6 +202,10 @@ constexpr uint8_t epps = ENCODER_PULSES_PER_STEP;
 | 
			
		||||
    bool MarlinUI::drawing_screen, MarlinUI::first_page; // = false
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  #if IS_DWIN_MARLINUI
 | 
			
		||||
    bool MarlinUI::did_first_redraw;
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  // Encoder Handling
 | 
			
		||||
  #if HAS_ENCODER_ACTION
 | 
			
		||||
    uint32_t MarlinUI::encoderPosition;
 | 
			
		||||
@@ -335,6 +339,7 @@ constexpr uint8_t epps = ENCODER_PULSES_PER_STEP;
 | 
			
		||||
          col = (LCD_WIDTH - plen - slen) / 2;
 | 
			
		||||
          row = LCD_HEIGHT > 3 ? 1 : 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (LCD_HEIGHT >= 8) row = LCD_HEIGHT / 2 - 2;
 | 
			
		||||
        wrap_string_P(col, row, pref, true);
 | 
			
		||||
        if (string) {
 | 
			
		||||
          if (col) { col = 0; row++; } // Move to the start of the next line
 | 
			
		||||
@@ -1073,6 +1078,9 @@ constexpr uint8_t epps = ENCODER_PULSES_PER_STEP;
 | 
			
		||||
 | 
			
		||||
          run_current_screen();
 | 
			
		||||
 | 
			
		||||
          // Apply all DWIN drawing after processing
 | 
			
		||||
          TERN_(IS_DWIN_MARLINUI, DWIN_UpdateLCD());
 | 
			
		||||
 | 
			
		||||
        #endif
 | 
			
		||||
 | 
			
		||||
        TERN_(HAS_LCD_MENU, lcd_clicked = false);
 | 
			
		||||
 
 | 
			
		||||
@@ -387,22 +387,22 @@ public:
 | 
			
		||||
      #endif
 | 
			
		||||
 | 
			
		||||
      #if HAS_MARLINUI_U8GLIB
 | 
			
		||||
 | 
			
		||||
        static void set_font(const MarlinFont font_nr);
 | 
			
		||||
      #elif IS_DWIN_MARLINUI
 | 
			
		||||
        static void set_font(const uint8_t font_nr);
 | 
			
		||||
      #endif
 | 
			
		||||
 | 
			
		||||
      #else
 | 
			
		||||
 | 
			
		||||
      #if HAS_MARLINUI_HD44780
 | 
			
		||||
        static void set_custom_characters(const HD44780CharSet screen_charset=CHARSET_INFO);
 | 
			
		||||
      #endif
 | 
			
		||||
 | 
			
		||||
        #if ENABLED(LCD_PROGRESS_BAR)
 | 
			
		||||
          static millis_t progress_bar_ms;  // Start time for the current progress bar cycle
 | 
			
		||||
          static void draw_progress_bar(const uint8_t percent);
 | 
			
		||||
          #if PROGRESS_MSG_EXPIRE > 0
 | 
			
		||||
            static millis_t expire_status_ms; // = 0
 | 
			
		||||
            FORCE_INLINE static void reset_progress_bar_timeout() { expire_status_ms = 0; }
 | 
			
		||||
          #endif
 | 
			
		||||
      #if ENABLED(LCD_PROGRESS_BAR) && !HAS_MARLINUI_U8GLIB
 | 
			
		||||
        static millis_t progress_bar_ms;  // Start time for the current progress bar cycle
 | 
			
		||||
        static void draw_progress_bar(const uint8_t percent);
 | 
			
		||||
        #if PROGRESS_MSG_EXPIRE > 0
 | 
			
		||||
          static millis_t expire_status_ms; // = 0
 | 
			
		||||
          FORCE_INLINE static void reset_progress_bar_timeout() { expire_status_ms = 0; }
 | 
			
		||||
        #endif
 | 
			
		||||
 | 
			
		||||
      #endif
 | 
			
		||||
 | 
			
		||||
      static uint8_t lcd_status_update_delay;
 | 
			
		||||
@@ -447,6 +447,10 @@ public:
 | 
			
		||||
      static constexpr bool drawing_screen = false, first_page = true;
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    #if IS_DWIN_MARLINUI
 | 
			
		||||
      static bool did_first_redraw;
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
    static bool get_blink();
 | 
			
		||||
    static void kill_screen(PGM_P const lcd_error, PGM_P const lcd_component);
 | 
			
		||||
    static void draw_kill_screen();
 | 
			
		||||
 
 | 
			
		||||
@@ -179,6 +179,8 @@ bool printer_busy() {
 | 
			
		||||
void MarlinUI::goto_screen(screenFunc_t screen, const uint16_t encoder/*=0*/, const uint8_t top/*=0*/, const uint8_t items/*=0*/) {
 | 
			
		||||
  if (currentScreen != screen) {
 | 
			
		||||
 | 
			
		||||
    TERN_(IS_DWIN_MARLINUI, did_first_redraw = false);
 | 
			
		||||
 | 
			
		||||
    TERN_(HAS_TOUCH_BUTTONS, repeat_delay = BUTTON_DELAY_MENU);
 | 
			
		||||
 | 
			
		||||
    TERN_(LCD_SET_PROGRESS_MANUALLY, progress_reset());
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,7 @@ typedef void (*selectFunc_t)();
 | 
			
		||||
#define SS_INVERT  0x02
 | 
			
		||||
#define SS_DEFAULT SS_CENTER
 | 
			
		||||
 | 
			
		||||
#if HAS_MARLINUI_U8GLIB && EITHER(BABYSTEP_ZPROBE_GFX_OVERLAY, MESH_EDIT_GFX_OVERLAY)
 | 
			
		||||
#if EITHER(HAS_MARLINUI_U8GLIB, IS_DWIN_MARLINUI) && EITHER(BABYSTEP_ZPROBE_GFX_OVERLAY, MESH_EDIT_GFX_OVERLAY)
 | 
			
		||||
  void _lcd_zoffset_overlay_gfx(const_float_t zvalue);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user