diff --git a/config/example-extras.cfg b/config/example-extras.cfg index ca36c969b..59c2c82ae 100644 --- a/config/example-extras.cfg +++ b/config/example-extras.cfg @@ -1903,6 +1903,17 @@ # template. This field is evaluated using command templates (see # docs/Command_Templates.md). This parameter must be provided. +# Display a custom glyph on displays that support it. The given name +# will be assigned the given display data which can then be referenced +# in the display templates by their name surrounded by two "tilde" symbols +# i.e. ~my_display_glyph~ +#[display_glyph my_display_glyph] +#data: +# The display data, stored as 16 lines consisting of 16 bits (1 per pixel) +# e.g. 1111111111111111 to display a solid horizontal line. Put each display +# line into a separate config line. The glyph must consist of exactly 16 +# lines with 16 bits each. + # If a primary [display] section has been defined in printer.cfg as shown # above it is possible to define multiple auxilary displays. Note that # auxilary displays do not currently support menu functionality, thus they diff --git a/klippy/extras/display/display.cfg b/klippy/extras/display/display.cfg index e6b46c8c9..bb395cc4c 100644 --- a/klippy/extras/display/display.cfg +++ b/klippy/extras/display/display.cfg @@ -13,7 +13,8 @@ text: # Show glyph {% if param_heater_name == "heater_bed" %} {% if heater.target %} - ~animated_bed~ + {% set frame = (printer.toolhead.estimated_print_time|int % 2) + 1 %} + ~bed_heat{frame}~ {% else %} ~bed~ {% endif %} @@ -35,9 +36,10 @@ text: {% if 'fan' in printer %} {% set speed = printer.fan.speed %} {% if speed %} - ~animated_fan~ + {% set frame = (printer.toolhead.estimated_print_time|int % 2) + 1 %} + ~fan{frame}~ {% else %} - ~fan~ + ~fan1~ {% endif %} { "{:>4.0%}".format(speed) } {% endif %} @@ -183,3 +185,140 @@ text: [display_data _default_20x4 print_status] position: 3, 0 text: { render("_print_status") } + +###################################################################### +# Default display glyphs +###################################################################### + +[display_glyph extruder] +data: + 0000000000000000 + 0000000000000000 + 0011111111111100 + 0000011111100000 + 0011111111111100 + 0000011111100000 + 0011111111111100 + 0000000000000000 + 0000111111110000 + 0000111111010000 + 0000111111110000 + 0000000000000000 + 0000001111000000 + 0000000110000000 + 0000000000000000 + 0000000000000000 + +[display_glyph bed] +data: + 0000000000000000 + 0000000000000000 + 0000000000000000 + 0000000000000000 + 0000000000000000 + 0000000000000000 + 0000000000000000 + 0000000000000000 + 0000000000000000 + 0000000000000000 + 0000000000000000 + 0001111111110000 + 0010000000001000 + 0111111111111100 + 0000000000000000 + 0000000000000000 + +[display_glyph bed_heat1] +data: + 0000000000000000 + 0000000000000000 + 0010000100001000 + 0100001000010000 + 0010000100001000 + 0001000010000100 + 0010000100001000 + 0100001000010000 + 0010000100001000 + 0000000000000000 + 0000000000000000 + 0001111111110000 + 0010000000001000 + 0111111111111100 + 0000000000000000 + 0000000000000000 + +[display_glyph bed_heat2] +data: + 0000000000000000 + 0000000000000000 + 0010000100001000 + 0001000010000100 + 0010000100001000 + 0100001000010000 + 0010000100001000 + 0001000010000100 + 0010000100001000 + 0000000000000000 + 0000000000000000 + 0001111111110000 + 0010000000001000 + 0111111111111100 + 0000000000000000 + 0000000000000000 + +[display_glyph fan1] +data: + 0000000000000000 + 0000000000000000 + 0000111000000000 + 0001111000011000 + 0001111000111100 + 0000111001111100 + 0000010000111100 + 0000000110000000 + 0000000110000000 + 0011110000100000 + 0011111001110000 + 0011110001111000 + 0001100001111000 + 0000000001110000 + 0000000000000000 + 0000000000000000 + +[display_glyph fan2] +data: + 0000000000000000 + 0000000000000000 + 0000000111100000 + 0000000111100000 + 0000000111000000 + 0011000110000000 + 0011100000000000 + 0011110110111100 + 0011110110111100 + 0000000000011100 + 0000000110001100 + 0000001110000000 + 0000011110000000 + 0000011110000000 + 0000000000000000 + 0000000000000000 + +[display_glyph feedrate] +data: + 0000000000000000 + 0000000000000000 + 1110111011101100 + 1000100010001010 + 1100110011001010 + 1000100010001010 + 1000111011101100 + 0000000000000000 + 1100010011101110 + 1010101001001000 + 1100111001001100 + 1010101001001000 + 1010101001001110 + 0000000000000000 + 0000000000000000 + 0000000000000000 diff --git a/klippy/extras/display/display.py b/klippy/extras/display/display.py index 0433c4328..880e0a327 100644 --- a/klippy/extras/display/display.py +++ b/klippy/extras/display/display.py @@ -100,9 +100,6 @@ class PrinterLCD: self.show_data_group = self.display_data_groups.get(dgroup) if self.show_data_group is None: raise config.error("Unknown display_data group '%s'" % (dgroup,)) - # Screen updating - self.glyph_helpers = { 'animated_bed': self.animate_bed, - 'animated_fan': self.animate_fan } self.printer.register_event_handler("klippy:ready", self.handle_ready) self.screen_update_timer = self.reactor.register_timer( self.screen_update_event) @@ -139,6 +136,28 @@ class PrinterLCD: for group_name, data_configs in groups.items(): dg = DisplayGroup(config, group_name, data_configs) self.display_data_groups[group_name] = dg + # Load display glyphs + dg_prefix = 'display_glyph ' + icons = {} + dg_main = config.get_prefix_sections(dg_prefix) + dg_main_names = {c.get_name(): 1 for c in dg_main} + dg_def = [c for c in dconfig.get_prefix_sections(dg_prefix) + if c.get_name() not in dg_main_names] + for dg in dg_main + dg_def: + glyph_name = dg.get_name()[len(dg_prefix):] + glyph_data = [] + for line in dg.get('data').split('\n'): + if line: + line_val = int(line, 2) + if line_val > 65535: + raise config.error("Glyph line out of range for " + \ + "glyph %s maximum is 65535" % (glyph_name,)) + glyph_data.append(line_val) + if len(glyph_data) < 16: + raise config.error("Not enough lines for" + \ + "glyph %s, 16 lines are needed" % (glyph_name,)) + icons[dg.get_name()[len(dg_prefix):]] = glyph_data + self.lcd_chip.set_glyphs(icons) # Initialization def handle_ready(self): self.lcd_chip.init() @@ -159,13 +178,6 @@ class PrinterLCD: logging.exception("Error during display screen update") self.lcd_chip.flush() return eventtime + .500 - # Rendering helpers - def animate_bed(self, row, col, eventtime): - frame = int(eventtime) & 1 - return self.lcd_chip.write_glyph(col, row, 'bed_heat%d' % (frame + 1,)) - def animate_fan(self, row, col, eventtime): - frame = int(eventtime) & 1 - return self.lcd_chip.write_glyph(col, row, 'fan%d' % (frame + 1,)) def draw_text(self, row, col, mixed_text, eventtime): pos = col for i, text in enumerate(mixed_text.split('~')): @@ -173,8 +185,6 @@ class PrinterLCD: # write text self.lcd_chip.write_text(pos, row, text) pos += len(text) - elif text in self.glyph_helpers: - pos += self.glyph_helpers[text](row, pos, eventtime) else: # write glyph pos += self.lcd_chip.write_glyph(pos, row, text) diff --git a/klippy/extras/display/hd44780.py b/klippy/extras/display/hd44780.py index 49cf0572a..b1faef45a 100644 --- a/klippy/extras/display/hd44780.py +++ b/klippy/extras/display/hd44780.py @@ -95,6 +95,8 @@ class HD44780: data = data[:20 - min(x, 20)] pos = x + ((y & 0x02) >> 1) * 20 self.text_framebuffers[y & 1][pos:pos+len(data)] = data + def set_glyphs(self, glyphs): + pass def write_glyph(self, x, y, glyph_name): char = TextGlyphs.get(glyph_name) if char is not None: diff --git a/klippy/extras/display/icons.py b/klippy/extras/display/icons.py deleted file mode 100644 index 8f91a2b15..000000000 --- a/klippy/extras/display/icons.py +++ /dev/null @@ -1,146 +0,0 @@ -# Common LCD icons -# -# Copyright (C) 2018 Aleph Objects, Inc -# Copyright (C) 2018 Alexander Fadeev -# -# This file may be distributed under the terms of the GNU GPLv3 license. - -extruder_icon = [ - 0b0000000000000000, - 0b0000000000000000, - 0b0011111111111100, - 0b0000011111100000, - 0b0011111111111100, - 0b0000011111100000, - 0b0011111111111100, - 0b0000000000000000, - 0b0000111111110000, - 0b0000111111010000, - 0b0000111111110000, - 0b0000000000000000, - 0b0000001111000000, - 0b0000000110000000, - 0b0000000000000000, - 0b0000000000000000 -] - -bed_icon = [ - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000, - 0b0001111111110000, - 0b0010000000001000, - 0b0111111111111100, - 0b0000000000000000, - 0b0000000000000000 -] - -bed_heat1_icon = [ - 0b0000000000000000, - 0b0000000000000000, - 0b0010000100001000, - 0b0100001000010000, - 0b0010000100001000, - 0b0001000010000100, - 0b0010000100001000, - 0b0100001000010000, - 0b0010000100001000, - 0b0000000000000000, - 0b0000000000000000, - 0b0001111111110000, - 0b0010000000001000, - 0b0111111111111100, - 0b0000000000000000, - 0b0000000000000000 -] - -bed_heat2_icon = [ - 0b0000000000000000, - 0b0000000000000000, - 0b0010000100001000, - 0b0001000010000100, - 0b0010000100001000, - 0b0100001000010000, - 0b0010000100001000, - 0b0001000010000100, - 0b0010000100001000, - 0b0000000000000000, - 0b0000000000000000, - 0b0001111111110000, - 0b0010000000001000, - 0b0111111111111100, - 0b0000000000000000, - 0b0000000000000000 -] - -fan1_icon = [ - 0b0000000000000000, - 0b0000000000000000, - 0b0000111000000000, - 0b0001111000011000, - 0b0001111000111100, - 0b0000111001111100, - 0b0000010000111100, - 0b0000000110000000, - 0b0000000110000000, - 0b0011110000100000, - 0b0011111001110000, - 0b0011110001111000, - 0b0001100001111000, - 0b0000000001110000, - 0b0000000000000000, - 0b0000000000000000 -] - -fan2_icon = [ - 0b0000000000000000, - 0b0000000000000000, - 0b0000000111100000, - 0b0000000111100000, - 0b0000000111000000, - 0b0011000110000000, - 0b0011100000000000, - 0b0011110110111100, - 0b0011110110111100, - 0b0000000000011100, - 0b0000000110001100, - 0b0000001110000000, - 0b0000011110000000, - 0b0000011110000000, - 0b0000000000000000, - 0b0000000000000000 -] - -feedrate_icon = [ - 0b0000000000000000, - 0b0000000000000000, - 0b1110111011101100, - 0b1000100010001010, - 0b1100110011001010, - 0b1000100010001010, - 0b1000111011101100, - 0b0000000000000000, - 0b1100010011101110, - 0b1010101001001000, - 0b1100111001001100, - 0b1010101001001000, - 0b1010101001001110, - 0b0000000000000000, - 0b0000000000000000, - 0b0000000000000000 -] - -Icons16x16 = { - 'extruder': extruder_icon, - 'bed': bed_icon, 'bed_heat1': bed_heat1_icon, 'bed_heat2': bed_heat2_icon, - 'fan': fan1_icon, 'fan1': fan1_icon, 'fan2': fan2_icon, - 'feedrate': feedrate_icon, -} diff --git a/klippy/extras/display/st7920.py b/klippy/extras/display/st7920.py index 9cfcdb16e..30c3dfb13 100644 --- a/klippy/extras/display/st7920.py +++ b/klippy/extras/display/st7920.py @@ -4,7 +4,7 @@ # # This file may be distributed under the terms of the GNU GPLv3 license. import logging -import icons, font8x14 +import font8x14 BACKGROUND_PRIORITY_CLOCK = 0x7fffffff00000000 @@ -46,6 +46,7 @@ class ST7920: ] + [(self.graphics_framebuffers[i], bytearray('~'*32), i) for i in range(32)] self.cached_glyphs = {} + self.icons = {} def build_config(self): self.mcu.add_config_cmd( "config_st7920 oid=%u cs_pin=%s sclk_pin=%s sid_pin=%s" @@ -108,13 +109,12 @@ class ST7920: 0x06, # Set positive update direction 0x0c] # Enable display and hide cursor self.send(cmds) - # Setup animated glyphs - self.cache_glyph('fan2', 'fan1', 0) - self.cache_glyph('bed_heat2', 'bed_heat1', 1) self.flush() def cache_glyph(self, glyph_name, base_glyph_name, glyph_id): - icon = icons.Icons16x16[glyph_name] - base_icon = icons.Icons16x16[base_glyph_name] + icon = self.icons.get(glyph_name) + base_icon = self.icons.get(base_glyph_name) + if icon is None or base_icon is None: + return for i, (bits, base_bits) in enumerate(zip(icon, base_icon)): pos = glyph_id*32 + i*2 b1, b2 = (bits >> 8) & 0xff, bits & 0xff @@ -135,13 +135,19 @@ class ST7920: gfx_fb -= 32 x += 16 self.graphics_framebuffers[gfx_fb][x:x+len(data)] = data + def set_glyphs(self, glyphs): + for glyph_name, glyph_data in glyphs.items(): + self.icons[glyph_name] = glyph_data + # Setup animated glyphs + self.cache_glyph('fan2', 'fan1', 0) + self.cache_glyph('bed_heat2', 'bed_heat1', 1) def write_glyph(self, x, y, glyph_name): glyph_id = self.cached_glyphs.get(glyph_name) if glyph_id is not None and x & 1 == 0: # Render cached icon using character generator glyph_name = glyph_id[0] self.write_text(x, y, glyph_id[1]) - icon = icons.Icons16x16.get(glyph_name) + icon = self.icons.get(glyph_name) if icon is not None: # Draw icon in graphics mode for i, bits in enumerate(icon): diff --git a/klippy/extras/display/uc1701.py b/klippy/extras/display/uc1701.py index f19d9f970..690ea0bc9 100644 --- a/klippy/extras/display/uc1701.py +++ b/klippy/extras/display/uc1701.py @@ -5,7 +5,7 @@ # # This file may be distributed under the terms of the GNU GPLv3 license. import logging -import icons, font8x14, extras.bus +import font8x14, extras.bus BACKGROUND_PRIORITY_CLOCK = 0x7fffffff00000000 @@ -23,10 +23,6 @@ class DisplayBase: self.font = [self._swizzle_bits(bytearray(c)) for c in font8x14.VGA_FONT] self.icons = {} - for name, icon in icons.Icons16x16.items(): - top1, bot1 = self._swizzle_bits([d >> 8 for d in icon]) - top2, bot2 = self._swizzle_bits(icon) - self.icons[name] = (top1 + top2, bot1 + bot2) def flush(self): # Find all differences in the framebuffers and send them to the chip for new_data, old_data, page in self.all_framebuffers: @@ -83,6 +79,11 @@ class DisplayBase: if (bits << col) & 0x80: page[pix_x] ^= bit pix_x += 1 + def set_glyphs(self, glyphs): + for glyph_name, glyph_data in glyphs.items(): + top1, bot1 = self._swizzle_bits([d >> 8 for d in glyph_data]) + top2, bot2 = self._swizzle_bits(glyph_data) + self.icons[glyph_name] = (top1 + top2, bot1 + bot2) def write_glyph(self, x, y, glyph_name): icon = self.icons.get(glyph_name) if icon is not None and x < 15: