display: Make hd44780 glyphs configurable
Allow the 20x4 hd44780 screen glyphs to be customizable from the config file. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
1a7e4e51b3
commit
7713986ae1
|
@ -1913,7 +1913,15 @@
|
||||||
# pixel) where '.' is a blank pixel and '*' is an on pixel (e.g.,
|
# pixel) where '.' is a blank pixel and '*' is an on pixel (e.g.,
|
||||||
# "****************" to display a solid horizontal line). Put each
|
# "****************" to display a solid horizontal line). Put each
|
||||||
# display line into a separate config line. The glyph must consist
|
# display line into a separate config line. The glyph must consist
|
||||||
# of exactly 16 lines with 16 bits each.
|
# of exactly 16 lines with 16 bits each. This parameter is optional.
|
||||||
|
#hd44780_data:
|
||||||
|
# Glyph to use on 20x4 hd44780 displays. The glyph must consist of
|
||||||
|
# exactly 8 lines with 5 bits each. This parameter is optional.
|
||||||
|
#hd44780_slot:
|
||||||
|
# The hd44780 hardware index (0..7) to store the glyph at. If
|
||||||
|
# multiple distinct images use the same slot then make sure to only
|
||||||
|
# use one of those images in any given screen. This parameter is
|
||||||
|
# required if hd44780_data is specified.
|
||||||
|
|
||||||
# If a primary [display] section has been defined in printer.cfg as shown
|
# If a primary [display] section has been defined in printer.cfg as shown
|
||||||
# above it is possible to define multiple auxilary displays. Note that
|
# above it is possible to define multiple auxilary displays. Note that
|
||||||
|
|
|
@ -188,7 +188,7 @@ text: { render("_print_status") }
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Default display glyphs
|
# Default 16x4 glyphs
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
[display_glyph extruder]
|
[display_glyph extruder]
|
||||||
|
@ -327,8 +327,130 @@ data:
|
||||||
# In addition to the above glyphs, 16x4 displays also have the
|
# In addition to the above glyphs, 16x4 displays also have the
|
||||||
# following hard-coded single character glyphs: right_arrow, degrees.
|
# following hard-coded single character glyphs: right_arrow, degrees.
|
||||||
|
|
||||||
# The 20x4 displays do not have configurable glyphs. They do have
|
|
||||||
# hard-coded support for the following single character glyphs:
|
######################################################################
|
||||||
# right_arrow, degrees, extruder, bed, bed_heat1 (same as bed),
|
# Default 20x4 glyphs
|
||||||
# bed_heat2 (same as bed), feedrate, clock, usb, sd, fan1, fan2 (same
|
######################################################################
|
||||||
# as fan1).
|
|
||||||
|
[display_glyph extruder]
|
||||||
|
hd44780_slot: 0
|
||||||
|
hd44780_data:
|
||||||
|
..*..
|
||||||
|
.*.*.
|
||||||
|
.*.*.
|
||||||
|
.*.*.
|
||||||
|
.*.*.
|
||||||
|
*...*
|
||||||
|
*...*
|
||||||
|
.***.
|
||||||
|
|
||||||
|
[display_glyph bed]
|
||||||
|
hd44780_slot: 1
|
||||||
|
hd44780_data:
|
||||||
|
.....
|
||||||
|
*****
|
||||||
|
*.*.*
|
||||||
|
*...*
|
||||||
|
*.*.*
|
||||||
|
*****
|
||||||
|
.....
|
||||||
|
.....
|
||||||
|
|
||||||
|
[display_glyph bed_heat1]
|
||||||
|
hd44780_slot: 1
|
||||||
|
hd44780_data:
|
||||||
|
.....
|
||||||
|
*****
|
||||||
|
*.*.*
|
||||||
|
*...*
|
||||||
|
*.*.*
|
||||||
|
*****
|
||||||
|
.....
|
||||||
|
.....
|
||||||
|
|
||||||
|
[display_glyph bed_heat2]
|
||||||
|
hd44780_slot: 1
|
||||||
|
hd44780_data:
|
||||||
|
.....
|
||||||
|
*****
|
||||||
|
*.*.*
|
||||||
|
*...*
|
||||||
|
*.*.*
|
||||||
|
*****
|
||||||
|
.....
|
||||||
|
.....
|
||||||
|
|
||||||
|
[display_glyph fan]
|
||||||
|
hd44780_slot: 2
|
||||||
|
hd44780_data:
|
||||||
|
.....
|
||||||
|
*..**
|
||||||
|
**.*.
|
||||||
|
..*..
|
||||||
|
.*.**
|
||||||
|
**..*
|
||||||
|
.....
|
||||||
|
.....
|
||||||
|
|
||||||
|
[display_glyph feedrate]
|
||||||
|
hd44780_slot: 3
|
||||||
|
hd44780_data:
|
||||||
|
***..
|
||||||
|
*....
|
||||||
|
**...
|
||||||
|
*.***
|
||||||
|
..*.*
|
||||||
|
..**.
|
||||||
|
..*.*
|
||||||
|
.....
|
||||||
|
|
||||||
|
[display_glyph clock]
|
||||||
|
hd44780_slot: 4
|
||||||
|
hd44780_data:
|
||||||
|
.....
|
||||||
|
.***.
|
||||||
|
*..**
|
||||||
|
*.*.*
|
||||||
|
*...*
|
||||||
|
.***.
|
||||||
|
.....
|
||||||
|
.....
|
||||||
|
|
||||||
|
[display_glyph degrees]
|
||||||
|
hd44780_slot: 5
|
||||||
|
hd44780_data:
|
||||||
|
.**..
|
||||||
|
*..*.
|
||||||
|
*..*.
|
||||||
|
.**..
|
||||||
|
.....
|
||||||
|
.....
|
||||||
|
.....
|
||||||
|
.....
|
||||||
|
|
||||||
|
[display_glyph usb]
|
||||||
|
hd44780_slot: 6
|
||||||
|
hd44780_data:
|
||||||
|
.***.
|
||||||
|
.***.
|
||||||
|
.***.
|
||||||
|
*****
|
||||||
|
*****
|
||||||
|
*****
|
||||||
|
..*..
|
||||||
|
..*..
|
||||||
|
|
||||||
|
[display_glyph sd]
|
||||||
|
hd44780_slot: 6
|
||||||
|
hd44780_data:
|
||||||
|
.....
|
||||||
|
..***
|
||||||
|
.****
|
||||||
|
*****
|
||||||
|
*****
|
||||||
|
*****
|
||||||
|
*****
|
||||||
|
.....
|
||||||
|
|
||||||
|
# In addition to the above glyphs, 20x4 displays also have the
|
||||||
|
# following hard-coded glyphs: right_arrow.
|
||||||
|
|
|
@ -104,6 +104,18 @@ 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)
|
||||||
# Configurable display
|
# Configurable display
|
||||||
|
def _parse_glyph(self, config, glyph_name, data, width, height):
|
||||||
|
glyph_data = []
|
||||||
|
for line in data.split('\n'):
|
||||||
|
line = line.strip().replace('.', '0').replace('*', '1')
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
if len(line) != width or line.replace('0', '').replace('1', ''):
|
||||||
|
raise config.error("Invalid glyph line in %s" % (glyph_name,))
|
||||||
|
glyph_data.append(int(line, 2))
|
||||||
|
if len(glyph_data) != height:
|
||||||
|
raise config.error("Glyph %s incorrect lines" % (glyph_name,))
|
||||||
|
return glyph_data
|
||||||
def load_config(self, config):
|
def load_config(self, config):
|
||||||
# Load default display config file
|
# Load default display config file
|
||||||
pconfig = self.printer.lookup_object('configfile')
|
pconfig = self.printer.lookup_object('configfile')
|
||||||
|
@ -145,18 +157,15 @@ class PrinterLCD:
|
||||||
if c.get_name() not in dg_main_names]
|
if c.get_name() not in dg_main_names]
|
||||||
for dg in dg_main + dg_def:
|
for dg in dg_main + dg_def:
|
||||||
glyph_name = dg.get_name()[len(dg_prefix):]
|
glyph_name = dg.get_name()[len(dg_prefix):]
|
||||||
glyph_data = []
|
data = dg.get('data', None)
|
||||||
for line in dg.get('data').split('\n'):
|
if data is not None:
|
||||||
line = line.strip().replace('.', '0').replace('*', '1')
|
idata = self._parse_glyph(config, glyph_name, data, 16, 16)
|
||||||
if not line:
|
icons.setdefault(glyph_name, {})['icon16x16'] = idata
|
||||||
continue
|
data = dg.get('hd44780_data', None)
|
||||||
if len(line) != 16 or line.replace('0', '').replace('1', ''):
|
if data is not None:
|
||||||
raise config.error("Invalid glyph line in %s"
|
slot = dg.getint('hd44780_slot', minval=0, maxval=7)
|
||||||
% (glyph_name,))
|
idata = self._parse_glyph(config, glyph_name, data, 5, 8)
|
||||||
glyph_data.append(int(line, 2))
|
icons.setdefault(glyph_name, {})['icon5x8'] = (slot, idata)
|
||||||
if len(glyph_data) != 16:
|
|
||||||
raise config.error("Glyph %s must be 16 lines" % (glyph_name,))
|
|
||||||
icons[glyph_name] = glyph_data
|
|
||||||
self.lcd_chip.set_glyphs(icons)
|
self.lcd_chip.set_glyphs(icons)
|
||||||
# Initialization
|
# Initialization
|
||||||
def handle_ready(self):
|
def handle_ready(self):
|
||||||
|
|
|
@ -8,6 +8,8 @@ import logging
|
||||||
|
|
||||||
BACKGROUND_PRIORITY_CLOCK = 0x7fffffff00000000
|
BACKGROUND_PRIORITY_CLOCK = 0x7fffffff00000000
|
||||||
|
|
||||||
|
TextGlyphs = { 'right_arrow': '\x7e' }
|
||||||
|
|
||||||
HD44780_DELAY = .000040
|
HD44780_DELAY = .000040
|
||||||
|
|
||||||
class HD44780:
|
class HD44780:
|
||||||
|
@ -27,6 +29,7 @@ class HD44780:
|
||||||
self.oid = self.mcu.create_oid()
|
self.oid = self.mcu.create_oid()
|
||||||
self.mcu.register_config_callback(self.build_config)
|
self.mcu.register_config_callback(self.build_config)
|
||||||
self.send_data_cmd = self.send_cmds_cmd = None
|
self.send_data_cmd = self.send_cmds_cmd = None
|
||||||
|
self.icons = {}
|
||||||
# framebuffers
|
# framebuffers
|
||||||
self.text_framebuffers = [bytearray(' '*40), bytearray(' '*40)]
|
self.text_framebuffers = [bytearray(' '*40), bytearray(' '*40)]
|
||||||
self.glyph_framebuffer = bytearray(64)
|
self.glyph_framebuffer = bytearray(64)
|
||||||
|
@ -85,10 +88,6 @@ class HD44780:
|
||||||
for i, cmds in enumerate(init):
|
for i, cmds in enumerate(init):
|
||||||
minclock = self.mcu.print_time_to_clock(print_time + i * .100)
|
minclock = self.mcu.print_time_to_clock(print_time + i * .100)
|
||||||
self.send_cmds_cmd.send([self.oid, cmds], minclock=minclock)
|
self.send_cmds_cmd.send([self.oid, cmds], minclock=minclock)
|
||||||
# Add custom fonts
|
|
||||||
self.glyph_framebuffer[:len(HD44780_chars)] = HD44780_chars
|
|
||||||
for i in range(len(self.glyph_framebuffer)):
|
|
||||||
self.all_framebuffers[2][1][i] = self.glyph_framebuffer[i] ^ 1
|
|
||||||
self.flush()
|
self.flush()
|
||||||
def write_text(self, x, y, data):
|
def write_text(self, x, y, data):
|
||||||
if x + len(data) > 20:
|
if x + len(data) > 20:
|
||||||
|
@ -96,8 +95,17 @@ class HD44780:
|
||||||
pos = x + ((y & 0x02) >> 1) * 20
|
pos = x + ((y & 0x02) >> 1) * 20
|
||||||
self.text_framebuffers[y & 1][pos:pos+len(data)] = data
|
self.text_framebuffers[y & 1][pos:pos+len(data)] = data
|
||||||
def set_glyphs(self, glyphs):
|
def set_glyphs(self, glyphs):
|
||||||
pass
|
for glyph_name, glyph_data in glyphs.items():
|
||||||
|
data = glyph_data.get('icon5x8')
|
||||||
|
if data is not None:
|
||||||
|
self.icons[glyph_name] = data
|
||||||
def write_glyph(self, x, y, glyph_name):
|
def write_glyph(self, x, y, glyph_name):
|
||||||
|
data = self.icons.get(glyph_name)
|
||||||
|
if data is not None:
|
||||||
|
slot, bits = data
|
||||||
|
self.write_text(x, y, chr(slot))
|
||||||
|
self.glyph_framebuffer[slot * 8:(slot + 1) * 8] = bits
|
||||||
|
return 1
|
||||||
char = TextGlyphs.get(glyph_name)
|
char = TextGlyphs.get(glyph_name)
|
||||||
if char is not None:
|
if char is not None:
|
||||||
# Draw character
|
# Draw character
|
||||||
|
@ -112,90 +120,3 @@ class HD44780:
|
||||||
self.text_framebuffers[1][:] = spaces
|
self.text_framebuffers[1][:] = spaces
|
||||||
def get_dimensions(self):
|
def get_dimensions(self):
|
||||||
return (20, 4)
|
return (20, 4)
|
||||||
|
|
||||||
HD44780_chars = [
|
|
||||||
# Extruder (a thermometer)
|
|
||||||
0b00100,
|
|
||||||
0b01010,
|
|
||||||
0b01010,
|
|
||||||
0b01010,
|
|
||||||
0b01010,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b01110,
|
|
||||||
# Heated bed
|
|
||||||
0b00000,
|
|
||||||
0b11111,
|
|
||||||
0b10101,
|
|
||||||
0b10001,
|
|
||||||
0b10101,
|
|
||||||
0b11111,
|
|
||||||
0b00000,
|
|
||||||
0b00000,
|
|
||||||
# Feed rate
|
|
||||||
0b11100,
|
|
||||||
0b10000,
|
|
||||||
0b11000,
|
|
||||||
0b10111,
|
|
||||||
0b00101,
|
|
||||||
0b00110,
|
|
||||||
0b00101,
|
|
||||||
0b00000,
|
|
||||||
# Clock
|
|
||||||
0b00000,
|
|
||||||
0b01110,
|
|
||||||
0b10011,
|
|
||||||
0b10101,
|
|
||||||
0b10001,
|
|
||||||
0b01110,
|
|
||||||
0b00000,
|
|
||||||
0b00000,
|
|
||||||
# Degrees
|
|
||||||
0b01100,
|
|
||||||
0b10010,
|
|
||||||
0b10010,
|
|
||||||
0b01100,
|
|
||||||
0b00000,
|
|
||||||
0b00000,
|
|
||||||
0b00000,
|
|
||||||
0b00000,
|
|
||||||
# USB
|
|
||||||
0b01110,
|
|
||||||
0b01110,
|
|
||||||
0b01110,
|
|
||||||
0b11111,
|
|
||||||
0b11111,
|
|
||||||
0b11111,
|
|
||||||
0b00100,
|
|
||||||
0b00100,
|
|
||||||
# SD
|
|
||||||
0b00000,
|
|
||||||
0b00111,
|
|
||||||
0b01111,
|
|
||||||
0b11111,
|
|
||||||
0b11111,
|
|
||||||
0b11111,
|
|
||||||
0b11111,
|
|
||||||
0b00000,
|
|
||||||
# Fan
|
|
||||||
0b00000,
|
|
||||||
0b10011,
|
|
||||||
0b11010,
|
|
||||||
0b00100,
|
|
||||||
0b01011,
|
|
||||||
0b11001,
|
|
||||||
0b00000,
|
|
||||||
0b00000,
|
|
||||||
]
|
|
||||||
|
|
||||||
TextGlyphs = {
|
|
||||||
'right_arrow': '\x7e',
|
|
||||||
'extruder': '\x00',
|
|
||||||
'bed': '\x01', 'bed_heat1': '\x01', 'bed_heat2': '\x01',
|
|
||||||
'feedrate': '\x02',
|
|
||||||
'clock': '\x03',
|
|
||||||
'degrees': '\x04',
|
|
||||||
'usb': '\x05',
|
|
||||||
'sd': '\x06',
|
|
||||||
'fan1': '\x07', 'fan2': '\x07',
|
|
||||||
}
|
|
||||||
|
|
|
@ -137,7 +137,9 @@ class ST7920:
|
||||||
self.graphics_framebuffers[gfx_fb][x:x+len(data)] = data
|
self.graphics_framebuffers[gfx_fb][x:x+len(data)] = data
|
||||||
def set_glyphs(self, glyphs):
|
def set_glyphs(self, glyphs):
|
||||||
for glyph_name, glyph_data in glyphs.items():
|
for glyph_name, glyph_data in glyphs.items():
|
||||||
self.icons[glyph_name] = glyph_data
|
data = glyph_data.get('icon16x16')
|
||||||
|
if data is not None:
|
||||||
|
self.icons[glyph_name] = data
|
||||||
# Setup animated glyphs
|
# Setup animated glyphs
|
||||||
self.cache_glyph('fan2', 'fan1', 0)
|
self.cache_glyph('fan2', 'fan1', 0)
|
||||||
self.cache_glyph('bed_heat2', 'bed_heat1', 1)
|
self.cache_glyph('bed_heat2', 'bed_heat1', 1)
|
||||||
|
|
|
@ -81,9 +81,11 @@ class DisplayBase:
|
||||||
pix_x += 1
|
pix_x += 1
|
||||||
def set_glyphs(self, glyphs):
|
def set_glyphs(self, glyphs):
|
||||||
for glyph_name, glyph_data in glyphs.items():
|
for glyph_name, glyph_data in glyphs.items():
|
||||||
top1, bot1 = self._swizzle_bits([d >> 8 for d in glyph_data])
|
data = glyph_data.get('icon16x16')
|
||||||
top2, bot2 = self._swizzle_bits(glyph_data)
|
if data is not None:
|
||||||
self.icons[glyph_name] = (top1 + top2, bot1 + bot2)
|
top1, bot1 = self._swizzle_bits([d >> 8 for d in data])
|
||||||
|
top2, bot2 = self._swizzle_bits(data)
|
||||||
|
self.icons[glyph_name] = (top1 + top2, bot1 + bot2)
|
||||||
def write_glyph(self, x, y, glyph_name):
|
def write_glyph(self, x, y, glyph_name):
|
||||||
icon = self.icons.get(glyph_name)
|
icon = self.icons.get(glyph_name)
|
||||||
if icon is not None and x < 15:
|
if icon is not None and x < 15:
|
||||||
|
|
Loading…
Reference in New Issue