display: Move icon drawing from display.py to lcd_chip code
Move the st7920 icon rendering optimizations from display.py to st7920.py. This simplifies the code for other displays. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
2857255ef1
commit
2a5778be3a
|
@ -6,7 +6,7 @@
|
||||||
#
|
#
|
||||||
# This file may be distributed under the terms of the GNU GPLv3 license.
|
# This file may be distributed under the terms of the GNU GPLv3 license.
|
||||||
import logging
|
import logging
|
||||||
import hd44780, st7920, uc1701, icons
|
import hd44780, st7920, uc1701
|
||||||
import menu
|
import menu
|
||||||
|
|
||||||
LCD_chips = {
|
LCD_chips = {
|
||||||
|
@ -30,7 +30,6 @@ class PrinterLCD:
|
||||||
self.screen_update_timer = self.reactor.register_timer(
|
self.screen_update_timer = self.reactor.register_timer(
|
||||||
self.screen_update_event)
|
self.screen_update_event)
|
||||||
# Initialization
|
# Initialization
|
||||||
FAN1_GLYPH, FAN2_GLYPH, BED1_GLYPH, BED2_GLYPH = 0, 1, 2, 3
|
|
||||||
def printer_state(self, state):
|
def printer_state(self, state):
|
||||||
if state == 'ready':
|
if state == 'ready':
|
||||||
self.lcd_chip.init()
|
self.lcd_chip.init()
|
||||||
|
@ -48,34 +47,12 @@ class PrinterLCD:
|
||||||
self.message = None
|
self.message = None
|
||||||
self.gcode.register_command('M73', self.cmd_M73)
|
self.gcode.register_command('M73', self.cmd_M73)
|
||||||
self.gcode.register_command('M117', self.cmd_M117)
|
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
|
# Start screen update timer
|
||||||
self.reactor.update_timer(self.screen_update_timer, self.reactor.NOW)
|
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
|
# Graphics drawing
|
||||||
def draw_icon(self, x, y, data):
|
def animate_glyphs(self, eventtime, x, y, glyph_name, do_animate):
|
||||||
for i, bits in enumerate(data):
|
frame = do_animate and int(eventtime) & 1
|
||||||
self.lcd_chip.write_graphics(
|
self.lcd_chip.write_glyph(x, y, glyph_name + str(frame + 1))
|
||||||
x, y, i, [(bits >> 8) & 0xff, bits & 0xff])
|
|
||||||
def draw_progress_bar(self, x, y, width, value):
|
def draw_progress_bar(self, x, y, width, value):
|
||||||
value = int(value * 100.)
|
value = int(value * 100.)
|
||||||
data = [0x00] * width
|
data = [0x00] * width
|
||||||
|
@ -165,27 +142,26 @@ class PrinterLCD:
|
||||||
# Heaters
|
# Heaters
|
||||||
if self.extruder0 is not None:
|
if self.extruder0 is not None:
|
||||||
info = self.extruder0.get_heater().get_status(eventtime)
|
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)
|
self.draw_heater(2, 0, info)
|
||||||
extruder_count = 1
|
extruder_count = 1
|
||||||
if self.extruder1 is not None:
|
if self.extruder1 is not None:
|
||||||
info = self.extruder1.get_heater().get_status(eventtime)
|
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)
|
self.draw_heater(2, 1, info)
|
||||||
extruder_count = 2
|
extruder_count = 2
|
||||||
if self.heater_bed is not None:
|
if self.heater_bed is not None:
|
||||||
info = self.heater_bed.get_status(eventtime)
|
info = self.heater_bed.get_status(eventtime)
|
||||||
if info['target']:
|
if info['target']:
|
||||||
self.animate_glyphs(eventtime, 0, extruder_count,
|
self.animate_glyphs(eventtime, 0, extruder_count,
|
||||||
self.BED1_GLYPH, True)
|
'bed_heat', True)
|
||||||
else:
|
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)
|
self.draw_heater(2, extruder_count, info)
|
||||||
# Fan speed
|
# Fan speed
|
||||||
if self.fan is not None:
|
if self.fan is not None:
|
||||||
info = self.fan.get_status(eventtime)
|
info = self.fan.get_status(eventtime)
|
||||||
self.animate_glyphs(eventtime, 10, 0, self.FAN1_GLYPH,
|
self.animate_glyphs(eventtime, 10, 0, 'fan', info['speed'] != 0.)
|
||||||
info['speed'] != 0.)
|
|
||||||
self.draw_percent(12, 0, 4, info['speed'], '>')
|
self.draw_percent(12, 0, 4, info['speed'], '>')
|
||||||
# SD card print progress
|
# SD card print progress
|
||||||
progress = None
|
progress = None
|
||||||
|
@ -210,7 +186,7 @@ class PrinterLCD:
|
||||||
# G-Code speed factor
|
# G-Code speed factor
|
||||||
gcode_info = self.gcode.get_status(eventtime)
|
gcode_info = self.gcode.get_status(eventtime)
|
||||||
if extruder_count == 1:
|
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'], '>')
|
self.draw_percent(12, 1, 4, gcode_info['speed_factor'], '>')
|
||||||
# Printing time and status
|
# Printing time and status
|
||||||
printing_time = toolhead_info['printing_time']
|
printing_time = toolhead_info['printing_time']
|
||||||
|
|
|
@ -136,3 +136,10 @@ feedrate_icon = [
|
||||||
0b0000000000000000,
|
0b0000000000000000,
|
||||||
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,
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#
|
#
|
||||||
# This file may be distributed under the terms of the GNU GPLv3 license.
|
# This file may be distributed under the terms of the GNU GPLv3 license.
|
||||||
import logging
|
import logging
|
||||||
|
import icons
|
||||||
|
|
||||||
BACKGROUND_PRIORITY_CLOCK = 0x7fffffff00000000
|
BACKGROUND_PRIORITY_CLOCK = 0x7fffffff00000000
|
||||||
|
|
||||||
|
@ -37,6 +38,7 @@ class ST7920:
|
||||||
for i in range(32)]
|
for i in range(32)]
|
||||||
self.framebuffers = ([self.text_framebuffer, self.glyph_framebuffer]
|
self.framebuffers = ([self.text_framebuffer, self.glyph_framebuffer]
|
||||||
+ self.graphics_framebuffers)
|
+ self.graphics_framebuffers)
|
||||||
|
self.cached_glyphs = {}
|
||||||
def build_config(self):
|
def build_config(self):
|
||||||
self.mcu.add_config_cmd(
|
self.mcu.add_config_cmd(
|
||||||
"config_st7920 oid=%u cs_pin=%s sclk_pin=%s sid_pin=%s"
|
"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
|
0x0c] # Enable display and hide cursor
|
||||||
self.send(cmds)
|
self.send(cmds)
|
||||||
self.flush()
|
self.flush()
|
||||||
def load_glyph(self, glyph_id, data):
|
# Setup animated glyphs
|
||||||
if len(data) > 32:
|
self.cache_glyph('fan1', 0)
|
||||||
data = data[:32]
|
self.cache_glyph('fan2', 1)
|
||||||
pos = min(glyph_id * 32, 96)
|
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.glyph_framebuffer[0][pos:pos+len(data)] = data
|
||||||
|
self.cached_glyphs[glyph_name] = (0, glyph_id*2)
|
||||||
def write_text(self, x, y, data):
|
def write_text(self, x, y, data):
|
||||||
if x + len(data) > 16:
|
if x + len(data) > 16:
|
||||||
data = data[:16 - min(x, 16)]
|
data = data[:16 - min(x, 16)]
|
||||||
|
@ -118,6 +127,17 @@ class ST7920:
|
||||||
gfx_fb -= 32
|
gfx_fb -= 32
|
||||||
x += 16
|
x += 16
|
||||||
self.graphics_framebuffers[gfx_fb][0][x:x+len(data)] = data
|
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):
|
def clear(self):
|
||||||
self.text_framebuffer[0][:] = ' '*64
|
self.text_framebuffer[0][:] = ' '*64
|
||||||
zeros = bytearray(32)
|
zeros = bytearray(32)
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#
|
#
|
||||||
# This file may be distributed under the terms of the GNU GPLv3 license.
|
# This file may be distributed under the terms of the GNU GPLv3 license.
|
||||||
import logging
|
import logging
|
||||||
from font8x14 import VGA_FONT as CHAR_SET
|
import icons, font8x14
|
||||||
|
|
||||||
BACKGROUND_PRIORITY_CLOCK = 0x7fffffff00000000
|
BACKGROUND_PRIORITY_CLOCK = 0x7fffffff00000000
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@ class UC1701:
|
||||||
self.spi_oid = self.mcu.create_oid()
|
self.spi_oid = self.mcu.create_oid()
|
||||||
self.a0_oid = self.mcu.create_oid()
|
self.a0_oid = self.mcu.create_oid()
|
||||||
self.mcu.register_config_callback(self.build_config)
|
self.mcu.register_config_callback(self.build_config)
|
||||||
self.glyph_buffer = []
|
|
||||||
self.spi_xfer_cmd = self.set_pin_cmd = None
|
self.spi_xfer_cmd = self.set_pin_cmd = None
|
||||||
self.vram = ([bytearray(128) for i in range(8)],
|
self.vram = ([bytearray(128) for i in range(8)],
|
||||||
[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))
|
page_byte = ~(0x01 << (pix_y % 8))
|
||||||
#set the correct pixel in the vram buffer to 0
|
#set the correct pixel in the vram buffer to 0
|
||||||
self.vram[self.CURRENT_BUF][page_idx][pix_x] &= page_byte
|
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):
|
def write_text(self, x, y, data):
|
||||||
if x + len(data) > 16:
|
if x + len(data) > 16:
|
||||||
data = data[:16 - min(x, 16)]
|
data = data[:16 - min(x, 16)]
|
||||||
|
@ -143,7 +124,7 @@ class UC1701:
|
||||||
# Empty char
|
# Empty char
|
||||||
pix_x += 8
|
pix_x += 8
|
||||||
continue
|
continue
|
||||||
char = CHAR_SET[c_idx]
|
char = font8x14.VGA_FONT[c_idx]
|
||||||
bit_y = pix_y
|
bit_y = pix_y
|
||||||
for bits in char:
|
for bits in char:
|
||||||
if bits:
|
if bits:
|
||||||
|
@ -166,6 +147,12 @@ class UC1701:
|
||||||
if bits & mask:
|
if bits & mask:
|
||||||
self.set_pixel(pix_x, pix_y)
|
self.set_pixel(pix_x, pix_y)
|
||||||
pix_x += 1
|
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):
|
def clear(self):
|
||||||
zeros = bytearray(128)
|
zeros = bytearray(128)
|
||||||
for page in self.vram[self.CURRENT_BUF]:
|
for page in self.vram[self.CURRENT_BUF]:
|
||||||
|
|
Loading…
Reference in New Issue