diff --git a/klippy/extras/display/display.py b/klippy/extras/display/display.py index 99d4d197..3ab2d7f2 100644 --- a/klippy/extras/display/display.py +++ b/klippy/extras/display/display.py @@ -6,7 +6,7 @@ # # This file may be distributed under the terms of the GNU GPLv3 license. import logging -import hd44780, st7920, uc1701, icons +import hd44780, st7920, uc1701 import menu LCD_chips = { @@ -30,7 +30,6 @@ class PrinterLCD: self.screen_update_timer = self.reactor.register_timer( self.screen_update_event) # Initialization - FAN1_GLYPH, FAN2_GLYPH, BED1_GLYPH, BED2_GLYPH = 0, 1, 2, 3 def printer_state(self, state): if state == 'ready': self.lcd_chip.init() @@ -48,34 +47,12 @@ class PrinterLCD: self.message = None self.gcode.register_command('M73', self.cmd_M73) self.gcode.register_command('M117', self.cmd_M117) - # Load glyphs - self.load_glyph(self.BED1_GLYPH, icons.bed_heat1_icon) - self.load_glyph(self.BED2_GLYPH, icons.bed_heat2_icon) - self.load_glyph(self.FAN1_GLYPH, icons.fan1_icon) - self.load_glyph(self.FAN2_GLYPH, icons.fan2_icon) # Start screen update timer self.reactor.update_timer(self.screen_update_timer, self.reactor.NOW) - # ST7920/UC1701 Glyphs - def load_glyph(self, glyph_id, data): - if self.lcd_type == 'uc1701': - self.lcd_chip.load_glyph(glyph_id, data) - elif self.lcd_type == 'st7920': - glyph = [0x00] * (len(data) * 2) - for i, bits in enumerate(data): - glyph[i*2] = (bits >> 8) & 0xff - glyph[i*2 + 1] = bits & 0xff - return self.lcd_chip.load_glyph(glyph_id, glyph) - def animate_glyphs(self, eventtime, x, y, glyph_id, do_animate): - frame = do_animate and int(eventtime) & 1 - if self.lcd_type == 'uc1701': - self.lcd_chip.write_glyph(x, y, glyph_id + frame) - elif self.lcd_type == 'st7920': - self.lcd_chip.write_text(x, y, (0, (glyph_id + frame)*2)) # Graphics drawing - def draw_icon(self, x, y, data): - for i, bits in enumerate(data): - self.lcd_chip.write_graphics( - x, y, i, [(bits >> 8) & 0xff, bits & 0xff]) + def animate_glyphs(self, eventtime, x, y, glyph_name, do_animate): + frame = do_animate and int(eventtime) & 1 + self.lcd_chip.write_glyph(x, y, glyph_name + str(frame + 1)) def draw_progress_bar(self, x, y, width, value): value = int(value * 100.) data = [0x00] * width @@ -165,27 +142,26 @@ class PrinterLCD: # Heaters if self.extruder0 is not None: info = self.extruder0.get_heater().get_status(eventtime) - self.draw_icon(0, 0, icons.nozzle_icon) + self.lcd_chip.write_glyph(0, 0, 'nozzle') self.draw_heater(2, 0, info) extruder_count = 1 if self.extruder1 is not None: info = self.extruder1.get_heater().get_status(eventtime) - self.draw_icon(0, 1, icons.nozzle_icon) + self.lcd_chip.write_glyph(0, 1, 'nozzle') self.draw_heater(2, 1, info) extruder_count = 2 if self.heater_bed is not None: info = self.heater_bed.get_status(eventtime) if info['target']: self.animate_glyphs(eventtime, 0, extruder_count, - self.BED1_GLYPH, True) + 'bed_heat', True) else: - self.draw_icon(0, extruder_count, icons.bed_icon) + self.lcd_chip.write_glyph(0, extruder_count, 'bed') self.draw_heater(2, extruder_count, info) # Fan speed if self.fan is not None: info = self.fan.get_status(eventtime) - self.animate_glyphs(eventtime, 10, 0, self.FAN1_GLYPH, - info['speed'] != 0.) + self.animate_glyphs(eventtime, 10, 0, 'fan', info['speed'] != 0.) self.draw_percent(12, 0, 4, info['speed'], '>') # SD card print progress progress = None @@ -210,7 +186,7 @@ class PrinterLCD: # G-Code speed factor gcode_info = self.gcode.get_status(eventtime) if extruder_count == 1: - self.draw_icon(10, 1, icons.feedrate_icon) + self.lcd_chip.write_glyph(10, 1, 'feedrate') self.draw_percent(12, 1, 4, gcode_info['speed_factor'], '>') # Printing time and status printing_time = toolhead_info['printing_time'] diff --git a/klippy/extras/display/icons.py b/klippy/extras/display/icons.py index 94701176..622c9cff 100644 --- a/klippy/extras/display/icons.py +++ b/klippy/extras/display/icons.py @@ -136,3 +136,10 @@ feedrate_icon = [ 0b0000000000000000, 0b0000000000000000 ] + +Icons16x16 = { + 'nozzle': nozzle_icon, + 'bed': bed_icon, 'bed_heat1': bed_heat1_icon, 'bed_heat2': bed_heat2_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 20787124..b8562322 100644 --- a/klippy/extras/display/st7920.py +++ b/klippy/extras/display/st7920.py @@ -4,6 +4,7 @@ # # This file may be distributed under the terms of the GNU GPLv3 license. import logging +import icons BACKGROUND_PRIORITY_CLOCK = 0x7fffffff00000000 @@ -37,6 +38,7 @@ class ST7920: for i in range(32)] self.framebuffers = ([self.text_framebuffer, self.glyph_framebuffer] + self.graphics_framebuffers) + self.cached_glyphs = {} def build_config(self): self.mcu.add_config_cmd( "config_st7920 oid=%u cs_pin=%s sclk_pin=%s sid_pin=%s" @@ -100,11 +102,18 @@ class ST7920: 0x0c] # Enable display and hide cursor self.send(cmds) self.flush() - def load_glyph(self, glyph_id, data): - if len(data) > 32: - data = data[:32] - pos = min(glyph_id * 32, 96) - self.glyph_framebuffer[0][pos:pos+len(data)] = data + # Setup animated glyphs + self.cache_glyph('fan1', 0) + self.cache_glyph('fan2', 1) + self.cache_glyph('bed_heat1', 2) + self.cache_glyph('bed_heat2', 3) + def cache_glyph(self, glyph_name, glyph_id): + icon = icons.Icons16x16[glyph_name] + for i, bits in enumerate(icon): + pos = glyph_id*32 + i*2 + data = [(bits >> 8) & 0xff, bits & 0xff] + self.glyph_framebuffer[0][pos:pos+len(data)] = data + self.cached_glyphs[glyph_name] = (0, glyph_id*2) def write_text(self, x, y, data): if x + len(data) > 16: data = data[:16 - min(x, 16)] @@ -118,6 +127,17 @@ class ST7920: gfx_fb -= 32 x += 16 self.graphics_framebuffers[gfx_fb][0][x:x+len(data)] = data + 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 + self.write_text(x, y, glyph_id) + return + icon = icons.Icons16x16.get(glyph_name) + if icon is not None: + # Draw icon in graphics mode + for i, bits in enumerate(icon): + self.write_graphics(x, y, i, [(bits >> 8) & 0xff, bits & 0xff]) def clear(self): self.text_framebuffer[0][:] = ' '*64 zeros = bytearray(32) diff --git a/klippy/extras/display/uc1701.py b/klippy/extras/display/uc1701.py index 32ba7ebf..5a2239eb 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 -from font8x14 import VGA_FONT as CHAR_SET +import icons, font8x14 BACKGROUND_PRIORITY_CLOCK = 0x7fffffff00000000 @@ -29,7 +29,6 @@ class UC1701: self.spi_oid = self.mcu.create_oid() self.a0_oid = self.mcu.create_oid() self.mcu.register_config_callback(self.build_config) - self.glyph_buffer = [] self.spi_xfer_cmd = self.set_pin_cmd = None self.vram = ([bytearray(128) for i in range(8)], [bytearray('~'*128) for i in range(8)]) @@ -114,24 +113,6 @@ class UC1701: page_byte = ~(0x01 << (pix_y % 8)) #set the correct pixel in the vram buffer to 0 self.vram[self.CURRENT_BUF][page_idx][pix_x] &= page_byte - def load_glyph(self, glyph_id, data): - if len(data) > 16: - data = data[:16] - self.glyph_buffer.append((glyph_id, data)) - self.glyph_buffer.sort(key=lambda x: x[0]) - def write_glyph(self, x, y, glyph_id): - pix_x = x*8 - pix_y = y*16 - data = self.glyph_buffer[glyph_id][1] - for bits in data: - if bits: - bit_x = pix_x - for i in range(15, -1, -1): - mask = 0x0001 << i - if bits & mask: - self.set_pixel(bit_x, pix_y) - bit_x += 1 - pix_y += 1 def write_text(self, x, y, data): if x + len(data) > 16: data = data[:16 - min(x, 16)] @@ -143,7 +124,7 @@ class UC1701: # Empty char pix_x += 8 continue - char = CHAR_SET[c_idx] + char = font8x14.VGA_FONT[c_idx] bit_y = pix_y for bits in char: if bits: @@ -166,6 +147,12 @@ class UC1701: if bits & mask: self.set_pixel(pix_x, pix_y) pix_x += 1 + def write_glyph(self, x, y, glyph_name): + icon = icons.Icons16x16.get(glyph_name) + if icon is not None: + # Draw icon in graphics mode + for i, bits in enumerate(icon): + self.write_graphics(x, y, i, [(bits >> 8) & 0xff, bits & 0xff]) def clear(self): zeros = bytearray(128) for page in self.vram[self.CURRENT_BUF]: