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:
Kevin O'Connor 2018-09-20 11:58:43 -04:00 committed by KevinOConnor
parent 2857255ef1
commit 2a5778be3a
4 changed files with 50 additions and 60 deletions

View File

@ -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']

View File

@ -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,
}

View File

@ -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.glyph_framebuffer[0][pos:pos+len(data)] = data 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): 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)

View File

@ -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]: