1
0
mirror of https://github.com/MarlinFirmware/Marlin.git synced 2024-11-23 12:04:19 +00:00

📺 Assorted small FTDI Eve Touch UI fixes (#22273)

This commit is contained in:
Marcio T 2021-07-06 19:32:08 -06:00 committed by Scott Lahteine
parent 091bdb79e6
commit 1bb61f27e9
19 changed files with 396 additions and 61 deletions

View File

@ -32,9 +32,7 @@
class MediaFileReader {
private:
#if ENABLED(SDSUPPORT)
DiskIODriver_SPI_SD card;
SdVolume volume;
SdFile root, file;
SdFile root, file;
#endif
public:

View File

@ -118,7 +118,6 @@ enum {
#include "../generic/files_screen.h"
#include "../generic/move_axis_screen.h"
#include "../generic/flow_percent_screen.h"
#include "../generic/tune_menu.h"
#if HAS_JUNCTION_DEVIATION
#include "../generic/junction_deviation_screen.h"
#else

View File

@ -294,4 +294,14 @@ void StatusScreen::onIdle() {
}
}
void StatusScreen::onMediaInserted() {
if (AT_SCREEN(StatusScreen))
setStatusMessage(GET_TEXT_F(MSG_MEDIA_INSERTED));
}
void StatusScreen::onMediaRemoved() {
if (AT_SCREEN(StatusScreen) || ExtUI::isPrintingFromMedia())
setStatusMessage(GET_TEXT_F(MSG_MEDIA_REMOVED));
}
#endif // COCOA_STATUS_SCREEN

View File

@ -52,4 +52,6 @@ class StatusScreen : public BaseScreen, public CachedScreen<STATUS_SCREEN_CACHE>
static bool onTouchHeld(uint8_t tag);
static bool onTouchEnd(uint8_t tag);
static void onIdle();
static void onMediaInserted();
static void onMediaRemoved();
};

View File

@ -239,9 +239,11 @@ class DeduplicatedPolyReader : public POLY_READER {
*/
template<class POLY_READER=DeduplicatedPolyReader<TransformedPolyReader>>
class GenericPolyUI {
private:
protected:
CommandProcessor &cmd;
draw_mode_t mode;
private:
// Attributes used to paint buttons
uint32_t btn_fill_color = 0x000000;
@ -250,8 +252,6 @@ class GenericPolyUI {
uint32_t btn_stroke_color = 0x000000;
uint8_t btn_stroke_width = 28;
draw_mode_t mode;
public:
enum ButtonStyle : uint8_t {
FILL = 1,

View File

@ -0,0 +1,47 @@
#!/usr/bin/python
# Written By Marcio Teixeira 2021 - SynDaver Labs, Inc.
#
# 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.
#
# To view a copy of the GNU General Public License, go to the following
# location: <https://www.gnu.org/licenses/>.
from __future__ import print_function
import argparse
import textwrap
import os
import zlib
def deflate(data):
return zlib.compress(data)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Converts a file into a packed C array for use as data')
parser.add_argument("input")
parser.add_argument("-d", "--deflate", action="store_true", help="Packs the data using the deflate algorithm")
args = parser.parse_args()
varname = os.path.splitext(os.path.basename(args.input))[0];
with open(args.input, "rb") as in_file:
data = in_file.read()
if args.deflate:
data = deflate(data)
data = bytearray(data)
data = list(map(lambda a: "0x" + format(a, '02x'), data))
nElements = len(data)
data = ', '.join(data)
data = textwrap.fill(data, 75, initial_indent = ' ', subsequent_indent = ' ')
print("const unsigned char " + varname + "[" + format(nElements) + "] PROGMEM = {")
print(data)
print("};")

View File

@ -0,0 +1,108 @@
#!/usr/bin/python
# Written By Marcio Teixeira 2019 - Aleph Objects, Inc.
#
# 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.
#
# To view a copy of the GNU General Public License, go to the following
# location: <https://www.gnu.org/licenses/>.
from __future__ import print_function
from PIL import Image
import argparse
import textwrap
def pack_rle(data):
"""Use run-length encoding to pack the bytes"""
rle = []
value = data[0]
count = 0
for i in data:
if i != value or count == 255:
rle.append(count)
rle.append(value)
value = i
count = 1
else:
count += 1
rle.append(count)
rle.append(value)
return rle
class WriteSource:
def __init__(self, lines_in_blocks):
self.blocks = []
self.values = []
self.block_size = lines_in_blocks
self.rows = 0
def add_pixel(self, value):
self.values.append(value)
def convert_to_4bpp(self, data, chunk_size = 0):
# Invert the image
data = list(map(lambda i: 255 - i, data))
# Quanitize 8-bit values into 4-bits
data = list(map(lambda i: i >> 4, data))
# Make sure there is an even number of elements
if (len(data) & 1) == 1:
data.append(0)
# Combine each two adjacent values into one
i = iter(data)
data = list(map(lambda a, b: a << 4 | b, i ,i))
# Pack the data
data = pack_rle(data)
# Convert values into hex strings
return list(map(lambda a: "0x" + format(a, '02x'), data))
def end_row(self, y):
# Pad each row into even number of values
if len(self.values) & 1:
self.values.append(0)
self.rows += 1
if self.block_size and (self.rows % self.block_size) == 0:
self.blocks.append(self.values)
self.values = []
def write(self):
if len(self.values):
self.blocks.append(self.values)
block_strs = [];
for b in self.blocks:
data = self.convert_to_4bpp(b)
data = ', '.join(data)
data = textwrap.fill(data, 75, initial_indent = ' ', subsequent_indent = ' ')
block_strs.append(data)
print("const unsigned char font[] PROGMEM = {")
for i, b in enumerate(block_strs):
if i:
print(',')
print('\n /* {} */'.format(i))
print(b, end='')
print("\n};")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Converts a grayscale bitmap into a 16-level RLE packed C array for use as font data')
parser.add_argument("input")
parser.add_argument('--char_height', help='Adds a separator every so many lines', type=int)
args = parser.parse_args()
writer = WriteSource(args.char_height)
img = Image.open(args.input).convert('L')
for y in range(img.height):
for x in range(img.width):
writer.add_pixel(img.getpixel((x,y)))
writer.end_row(y)
writer.write()

View File

@ -0,0 +1,113 @@
#!/usr/bin/python
# Written By Marcio Teixeira 2021 - SynDaver Labs, Inc.
#
# 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.
#
# To view a copy of the GNU General Public License, go to the following
# location: <https://www.gnu.org/licenses/>.
from __future__ import print_function
from PIL import Image
import argparse
import textwrap
import os
import sys
import zlib
class WriteSource:
def __init__(self, mode):
self.values = []
self.mode = mode
self.offset = 8
self.byte = 0
def finish_byte(self):
if self.offset != 8:
self.values.append(self.byte)
self.offset = 8
self.byte = 0
def add_bits_to_byte(self, value, size = 1):
self.offset -= size
self.byte = self.byte | value << self.offset
if self.offset == 0:
self.finish_byte()
def append_rgb565(self, color):
value = ((color[0] & 0xF8) << 8) + ((color[1] & 0xFC) << 3) + ((color[2] & 0xF8) >> 3)
self.values.append((value & 0x00FF) >> 0);
self.values.append((value & 0xFF00) >> 8);
def append_rgb332(self, color):
value = (color[0] & 0xE0) + ((color[1] & 0xE0) >> 3) + ((color[2] & 0xC0) >> 6)
self.values.append(value);
def append_grayscale(self, color, bits):
luminance = int(0.2126 * color[0] + 0.7152 * color[1] + 0.0722 * color[2])
self.add_bits_to_byte(luminance >> (8 - bits), bits)
def deflate(self, data):
return zlib.compress(data)
def add_pixel(self, color):
if self.mode == "l1":
self.append_grayscale(color, 1)
elif self.mode == "l2":
self.append_grayscale(color, 2)
elif self.mode == "l4":
self.append_grayscale(color, 4)
elif self.mode == "l8":
self.append_grayscale(color, 8)
elif self.mode == "rgb565":
self.append_rgb565(color)
elif self.mode == "rgb332":
self.append_rgb332(color)
def end_row(self, y):
if self.mode in ["l1", "l2", "l3"]:
self.finish_byte()
def write(self, varname, deflate):
print("Length of uncompressed data: ", len(self.values), file=sys.stderr)
data = bytes(bytearray(self.values))
if deflate:
data = self.deflate(data)
print("Length of data after compression: ", len(data), file=sys.stderr)
data = bytearray(data)
data = list(map(lambda a: "0x" + format(a, '02x'), data))
nElements = len(data)
data = ', '.join(data)
data = textwrap.fill(data, 75, initial_indent = ' ', subsequent_indent = ' ')
print("const unsigned char " + varname + "[" + format(nElements) + "] PROGMEM = {")
print(data)
print("};")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Converts a bitmap into a C array')
parser.add_argument("input")
parser.add_argument("-d", "--deflate", action="store_true", help="Packs the data using the deflate algorithm")
parser.add_argument("-m", "--mode", default="l1", help="Mode, can be l1, l2, l4, l8, rgb332 or rgb565")
args = parser.parse_args()
varname = os.path.splitext(os.path.basename(args.input))[0];
writer = WriteSource(args.mode)
img = Image.open(args.input)
print("Image height: ", img.height, file=sys.stderr)
print("Image width: ", img.width, file=sys.stderr)
for y in range(img.height):
for x in range(img.width):
writer.add_pixel(img.getpixel((x,y)))
writer.end_row(y)
writer.write(varname, args.deflate)

View File

@ -190,17 +190,11 @@ bool BedMeshEditScreen::onTouchEnd(uint8_t tag) {
}
void BedMeshEditScreen::show() {
// On entry, home if needed and save current mesh
if (!ExtUI::isMachineHomed()) {
SpinnerDialogBox::enqueueAndWait_P(F("G28\nG29 S1"));
// After the spinner, go to this screen.
current_screen.forget();
PUSH_SCREEN(BedMeshEditScreen);
}
else {
injectCommands_P(PSTR("G29 S1"));
GOTO_SCREEN(BedMeshEditScreen);
}
// On entry, always home (to account for possible Z offset changes) and save current mesh
SpinnerDialogBox::enqueueAndWait_P(F("G28\nG29 S1"));
// After the spinner, go to this screen.
current_screen.forget();
PUSH_SCREEN(BedMeshEditScreen);
}
#endif // FTDI_BED_MESH_EDIT_SCREEN

View File

@ -132,7 +132,6 @@ void BedMeshViewScreen::onMeshUpdate(const int8_t x, const int8_t y, const ExtUI
mydata.count = GRID_MAX_POINTS;
break;
case ExtUI::G26_START:
GOTO_SCREEN(BedMeshViewScreen);
mydata.message = nullptr;
mydata.count = 0;
break;
@ -161,7 +160,7 @@ void BedMeshViewScreen::doProbe() {
void BedMeshViewScreen::doMeshValidation() {
mydata.count = 0;
GOTO_SCREEN(StatusScreen);
injectCommands_P(PSTR("M75\nG28 O\nM117 Heating...\nG26 R X0 Y0\nG27\nM77"));
injectCommands_P(PSTR("G28\nM117 Heating...\nG26 R X0 Y0\nG27"));
}
void BedMeshViewScreen::show() {

View File

@ -83,8 +83,10 @@ void BootScreen::onIdle() {
if (UIData::animations_enabled()) {
// If there is a startup video in the flash SPI, play
// that, otherwise show a static splash screen.
if (!MediaPlayerScreen::playBootMedia())
showSplashScreen();
#ifdef FTDI_MEDIA_PLAYER_SCREEN
if (!MediaPlayerScreen::playBootMedia())
#endif
showSplashScreen();
}
#endif

View File

@ -35,12 +35,15 @@ void ConfirmUserRequestAlertBox::onRedraw(draw_mode_t mode) {
bool ConfirmUserRequestAlertBox::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1:
if (ExtUI::isPrintingPaused()) {
// The TuneMenu will call ExtUI::setUserConfirmed()
GOTO_SCREEN(TuneMenu);
current_screen.forget();
}
else {
#ifdef FTDI_TUNE_MENU
if (ExtUI::isPrintingPaused()) {
// The TuneMenu will call ExtUI::setUserConfirmed()
GOTO_SCREEN(TuneMenu);
current_screen.forget();
}
else
#endif
{
ExtUI::setUserConfirmed();
GOTO_PREVIOUS();
}

View File

@ -83,6 +83,7 @@ void LevelingMenu::onRedraw(draw_mode_t what) {
.font(font_medium).colors(normal_btn)
.enabled(EITHER(Z_STEPPER_AUTO_ALIGN,MECHANICAL_GANTRY_CALIBRATION))
.tag(2).button(LEVEL_AXIS_POS, GET_TEXT_F(MSG_LEVEL_X_AXIS))
.enabled(ENABLED(HAS_BED_PROBE))
.tag(3).button(PROBE_BED_POS, GET_TEXT_F(MSG_PROBE_BED))
.enabled(ENABLED(HAS_MESH))
.tag(4).button(SHOW_MESH_POS, GET_TEXT_F(MSG_SHOW_MESH))
@ -101,30 +102,32 @@ void LevelingMenu::onRedraw(draw_mode_t what) {
bool LevelingMenu::onTouchEnd(uint8_t tag) {
switch (tag) {
case 1: GOTO_PREVIOUS(); break;
case 1: GOTO_PREVIOUS(); break;
#if EITHER(Z_STEPPER_AUTO_ALIGN,MECHANICAL_GANTRY_CALIBRATION)
case 2: SpinnerDialogBox::enqueueAndWait_P(F("G34")); break;
case 2: SpinnerDialogBox::enqueueAndWait_P(F("G34")); break;
#endif
case 3:
#ifndef BED_LEVELING_COMMANDS
#define BED_LEVELING_COMMANDS "G29"
#if ENABLED(HAS_BED_PROBE)
case 3:
#ifndef BED_LEVELING_COMMANDS
#define BED_LEVELING_COMMANDS "G29"
#endif
#if ENABLED(AUTO_BED_LEVELING_UBL)
BedMeshViewScreen::doProbe();
#else
SpinnerDialogBox::enqueueAndWait_P(F(BED_LEVELING_COMMANDS));
#endif
break;
#endif
#if ENABLED(AUTO_BED_LEVELING_UBL)
BedMeshViewScreen::doProbe();
#else
SpinnerDialogBox::enqueueAndWait_P(F(BED_LEVELING_COMMANDS));
#endif
break;
#if ENABLED(AUTO_BED_LEVELING_UBL)
case 4: BedMeshViewScreen::show(); break;
case 5: BedMeshEditScreen::show(); break;
case 4: BedMeshViewScreen::show(); break;
case 5: BedMeshEditScreen::show(); break;
#endif
#if ENABLED(G26_MESH_VALIDATION)
case 6: BedMeshViewScreen::doMeshValidation(); break;
case 6: BedMeshViewScreen::doMeshValidation(); break;
#endif
#if ENABLED(BLTOUCH)
case 7: injectCommands_P(PSTR("M280 P0 S60")); break;
case 8: SpinnerDialogBox::enqueueAndWait_P(F("M280 P0 S90\nG4 P100\nM280 P0 S120")); break;
case 7: injectCommands_P(PSTR("M280 P0 S60")); break;
case 8: SpinnerDialogBox::enqueueAndWait_P(F("M280 P0 S90\nG4 P100\nM280 P0 S120")); break;
#endif
default: return false;
}

View File

@ -77,8 +77,11 @@ void TuneMenu::onRedraw(draw_mode_t what) {
.tag(3).button(FIL_CHANGE_POS, GET_TEXT_F(MSG_FILAMENTCHANGE))
.enabled(EITHER(LIN_ADVANCE, FILAMENT_RUNOUT_SENSOR))
.tag(9).button(FILAMENT_POS, GET_TEXT_F(MSG_FILAMENT))
.enabled(BOTH(HAS_LEVELING, HAS_BED_PROBE) || ENABLED(BABYSTEPPING))
.tag(4).button(NUDGE_NOZ_POS, GET_TEXT_F(TERN(BABYSTEPPING, MSG_NUDGE_NOZZLE, MSG_ZPROBE_ZOFFSET)))
#if ENABLED(BABYSTEPPING) && HAS_MULTI_HOTEND
.tag(4).button(NUDGE_NOZ_POS, GET_TEXT_F(MSG_NUDGE_NOZZLE))
#elif BOTH(HAS_LEVELING, HAS_BED_PROBE)
.tag(4).button(NUDGE_NOZ_POS, GET_TEXT_F(MSG_ZPROBE_ZOFFSET))
#endif
.tag(5).button(SPEED_POS, GET_TEXT_F(MSG_PRINT_SPEED))
.enabled(sdOrHostPrinting)
.tag(sdOrHostPaused ? 7 : 6)
@ -99,11 +102,11 @@ bool TuneMenu::onTouchEnd(uint8_t tag) {
using namespace Theme;
using namespace ExtUI;
switch (tag) {
case 1: GOTO_PREVIOUS(); break;
case 1: SaveSettingsDialogBox::promptToSaveSettings(); break;
case 2: GOTO_SCREEN(TemperatureScreen); break;
case 3: GOTO_SCREEN(ChangeFilamentScreen); break;
case 4:
#if ENABLED(BABYSTEPPING)
#if ENABLED(BABYSTEPPING) && HAS_MULTI_HOTEND
GOTO_SCREEN(NudgeNozzleScreen);
#elif BOTH(HAS_LEVELING, HAS_BED_PROBE)
GOTO_SCREEN(ZOffsetScreen);

View File

@ -53,7 +53,7 @@ void ZOffsetScreen::onRedraw(draw_mode_t what) {
w.heading( GET_TEXT_F(MSG_ZPROBE_ZOFFSET));
w.color(z_axis).adjuster(4, GET_TEXT_F(MSG_ZPROBE_ZOFFSET), getZOffset_mm());
w.increments();
w.button(2, GET_TEXT_F(MSG_PROBE_WIZARD), !isPrinting());
w.button(2, GET_TEXT_F(MSG_PROBE_WIZARD), !isPrinting() && !wizardRunning());
}
void ZOffsetScreen::move(float mm, int16_t steps) {

View File

@ -130,7 +130,7 @@ namespace Language_en {
PROGMEM Language_Str MSG_EEPROM_RESTORED = u8"Settings restored from backup";
PROGMEM Language_Str MSG_EEPROM_RESET = u8"Settings restored to default";
PROGMEM Language_Str MSG_EEPROM_SAVED = u8"Settings saved!";
PROGMEM Language_Str MSG_EEPROM_SAVE_PROMPT = u8"Do you wish to save these settings for next power-on?";
PROGMEM Language_Str MSG_EEPROM_SAVE_PROMPT = u8"Settings applied. Save these settings for next power-on?";
PROGMEM Language_Str MSG_EEPROM_RESET_WARNING = u8"Are you sure? Customizations will be lost.";
PROGMEM Language_Str MSG_PASSCODE_REJECTED = u8"Wrong passcode!";
@ -146,7 +146,7 @@ namespace Language_en {
PROGMEM Language_Str MSG_AXIS_LEVELING = u8"Axis Leveling";
PROGMEM Language_Str MSG_PROBE_BED = u8"Probe Mesh";
PROGMEM Language_Str MSG_SHOW_MESH = u8"View Mesh";
PROGMEM Language_Str MSG_PRINT_TEST = u8"Print Test";
PROGMEM Language_Str MSG_PRINT_TEST = u8"Print Test (PLA)";
PROGMEM Language_Str MSG_MOVE_Z_TO_TOP = u8"Raise Z to Top";
#if ENABLED(TOUCH_UI_LULZBOT_BIO)

View File

@ -40,7 +40,7 @@ extern tiny_timer_t refresh_timer;
#if ENABLED(TOUCH_UI_LULZBOT_BIO)
#include "bioprinter/screens.h"
#elif ENABLED(TOUCH_UI_COCOA_PRESS)
#include "cocoapress/screens.h"
#include "cocoa_press/screens.h"
#elif ENABLED(TOUCH_UI_SYNDAVER_LEVEL)
#include "syndaver_level/screens.h"
#else

View File

@ -36,7 +36,7 @@ namespace Theme {
.height = 23,
};
constexpr PROGMEM unsigned char Extruder_Icon[] = {
constexpr PROGMEM unsigned char Extruder_Icon[69] = {
0x3F, 0xFF, 0xFC,
0x7F, 0xFF, 0xFE,
0xC0, 0x00, 0x03,
@ -68,12 +68,12 @@ namespace Theme {
.filter = BILINEAR,
.wrapx = BORDER,
.wrapy = BORDER,
.RAMG_offset = 8100,
.RAMG_offset = 8069,
.width = 32,
.height = 23,
};
constexpr PROGMEM unsigned char Bed_Heat_Icon[] = {
constexpr PROGMEM unsigned char Bed_Heat_Icon[92] = {
0x01, 0x81, 0x81, 0x80,
0x01, 0x81, 0x81, 0x80,
0x00, 0xC0, 0xC0, 0xC0,
@ -105,12 +105,12 @@ namespace Theme {
.filter = BILINEAR,
.wrapx = BORDER,
.wrapy = BORDER,
.RAMG_offset = 8300,
.RAMG_offset = 8161,
.width = 32,
.height = 32,
};
constexpr PROGMEM unsigned char Fan_Icon[] = {
constexpr PROGMEM unsigned char Fan_Icon[128] = {
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0xF8, 0x00, 0x00, 0x1F,
@ -151,12 +151,12 @@ namespace Theme {
.filter = BILINEAR,
.wrapx = BORDER,
.wrapy = BORDER,
.RAMG_offset = 9000,
.RAMG_offset = 8289,
.width = 50,
.height = 20,
};
constexpr PROGMEM unsigned char TD_Icon[] = {
constexpr PROGMEM unsigned char TD_Icon[140] = {
0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, // Thumb Drive Widget
0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x80,
@ -179,5 +179,55 @@ namespace Theme {
0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFC, 0x00
};
constexpr PROGMEM uint32_t UTF8_FONT_OFFSET = 10000;
constexpr PROGMEM bitmap_info_t File_Icon_Info = {
.format = L1,
.linestride = 4,
.filter = BILINEAR,
.wrapx = BORDER,
.wrapy = BORDER,
.RAMG_offset = 8429,
.width = 25,
.height = 32,
};
const unsigned char File_Icon[128] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00,
0x40, 0x02, 0x80, 0x00, 0x40, 0x02, 0x40, 0x00, 0x40, 0x02, 0x20, 0x00,
0x40, 0x02, 0x10, 0x00, 0x40, 0x02, 0x08, 0x00, 0x40, 0x02, 0x04, 0x00,
0x40, 0x02, 0x02, 0x00, 0x40, 0x03, 0xFF, 0x00, 0x40, 0x00, 0x01, 0x00,
0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00,
0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00,
0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00,
0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00,
0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00,
0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00,
0x7F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00
};
constexpr PROGMEM bitmap_info_t Clock_Icon_Info = {
.format = L1,
.linestride = 4,
.filter = BILINEAR,
.wrapx = BORDER,
.wrapy = BORDER,
.RAMG_offset = 8557,
.width = 32,
.height = 32,
};
const unsigned char Clock_Icon[128] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x7E, 0x7E, 0x00,
0x00, 0xE0, 0x07, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x07, 0x01, 0x00, 0xE0,
0x0C, 0x01, 0x80, 0x70, 0x0C, 0x01, 0x80, 0x30, 0x18, 0x01, 0x80, 0x18,
0x30, 0x01, 0x80, 0x08, 0x30, 0x01, 0x80, 0x0C, 0x20, 0x01, 0x80, 0x0C,
0x60, 0x01, 0x80, 0x04, 0x60, 0x01, 0x80, 0x06, 0x60, 0x01, 0x80, 0x06,
0x60, 0x01, 0xFF, 0x06, 0x60, 0x01, 0xFF, 0x06, 0x60, 0x00, 0x00, 0x06,
0x60, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x0C,
0x30, 0x00, 0x00, 0x0C, 0x30, 0x00, 0x00, 0x08, 0x18, 0x00, 0x00, 0x18,
0x0C, 0x00, 0x00, 0x30, 0x0E, 0x00, 0x00, 0x70, 0x07, 0x00, 0x00, 0xE0,
0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x7F, 0xFE, 0x00,
0x00, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00
};
constexpr PROGMEM uint32_t UTF8_FONT_OFFSET = 10000;
}; // namespace Theme

View File

@ -190,7 +190,11 @@ namespace ExtUI {
void setHostResponse(const uint8_t);
#endif
inline void simulateUserClick() { ui.lcd_clicked = true; }
inline void simulateUserClick() {
#if EITHER(HAS_LCD_MENU, EXTENSIBLE_UI)
ui.lcd_clicked = true;
#endif
}
#if ENABLED(PRINTCOUNTER)
char* getFailedPrints_str(char buffer[21]);