aboutsummaryrefslogtreecommitdiffstats
path: root/klippy/extras/display/aip31068_spi.py
diff options
context:
space:
mode:
Diffstat (limited to 'klippy/extras/display/aip31068_spi.py')
-rw-r--r--klippy/extras/display/aip31068_spi.py151
1 files changed, 93 insertions, 58 deletions
diff --git a/klippy/extras/display/aip31068_spi.py b/klippy/extras/display/aip31068_spi.py
index 75f4978f..9bbbbdaa 100644
--- a/klippy/extras/display/aip31068_spi.py
+++ b/klippy/extras/display/aip31068_spi.py
@@ -16,10 +16,11 @@
from .. import bus
-LINE_LENGTH_DEFAULT=20
-LINE_LENGTH_OPTIONS={16:16, 20:20}
+LINE_LENGTH_DEFAULT = 20
+LINE_LENGTH_OPTIONS = {16: 16, 20: 20}
+
+TextGlyphs = {"right_arrow": b"\x7e"}
-TextGlyphs = { 'right_arrow': b'\x7e' }
# Each command is 9 bits long:
# 1 bit for RS (Register Select) - 0 for command, 1 for data
@@ -30,66 +31,79 @@ TextGlyphs = { 'right_arrow': b'\x7e' }
# or just by OR with enabled flags:
# cmd = CMND | flg_CMND.param1
class CMND:
- CLR = 1 # Clear display
- HOME = 2 # Return home
+ CLR = 1 # Clear display
+ HOME = 2 # Return home
ENTERY_MODE = 2**2 # Entry mode set
- DISPLAY = 2**3 # Display on/off control
- SHIFT = 2**4 # Cursor or display shift
- FUNCTION = 2**5 # Function set
- CGRAM = 2**6 # Character Generator RAM
- DDRAM = 2**7 # Display Data RAM
- WRITE_RAM = 2**8 # Write to RAM
+ DISPLAY = 2**3 # Display on/off control
+ SHIFT = 2**4 # Cursor or display shift
+ FUNCTION = 2**5 # Function set
+ CGRAM = 2**6 # Character Generator RAM
+ DDRAM = 2**7 # Display Data RAM
+ WRITE_RAM = 2**8 # Write to RAM
+
# Define flags for all commands:
class flg_ENTERY_MODE:
- INC = 2**1 # Increment
- SHIFT = 2**0 # Shift display
+ INC = 2**1 # Increment
+ SHIFT = 2**0 # Shift display
+
class flg_DISPLAY:
- ON = 2**2 # Display ON
- CURSOR = 2**1 # Cursor ON
- BLINK = 2**0 # Blink ON
+ ON = 2**2 # Display ON
+ CURSOR = 2**1 # Cursor ON
+ BLINK = 2**0 # Blink ON
+
class flg_SHIFT:
- WHOLE_DISPLAY = 2**3 # Shift whole display
- RIGHT = 2**2 # Shift right
+ WHOLE_DISPLAY = 2**3 # Shift whole display
+ RIGHT = 2**2 # Shift right
+
class flg_FUNCTION:
- TWO_LINES = 2**3 # 2-line display mode
- FIVE_BY_ELEVEN = 2**2 # 5x11 dot character font
+ TWO_LINES = 2**3 # 2-line display mode
+ FIVE_BY_ELEVEN = 2**2 # 5x11 dot character font
+
class flg_CGRAM:
- MASK = 0b00111111 # CGRAM address mask
+ MASK = 0b00111111 # CGRAM address mask
+
class flg_DDRAM:
- MASK = 0b01111111 # DDRAM address mask
+ MASK = 0b01111111 # DDRAM address mask
+
class flg_WRITE_RAM:
- MASK = 0b11111111 # Write RAM mask
+ MASK = 0b11111111 # Write RAM mask
-DISPLAY_INIT_CMNDS= [
+
+DISPLAY_INIT_CMNDS = [
# CMND.CLR - no need as framebuffer will rewrite all
- CMND.HOME, # move cursor to home (0x00)
- CMND.ENTERY_MODE | flg_ENTERY_MODE.INC, # increment cursor and no shift
- CMND.DISPLAY | flg_DISPLAY.ON, # keep cursor and blinking off
- CMND.SHIFT | flg_SHIFT.RIGHT, # shift right cursor only
- CMND.FUNCTION | flg_FUNCTION.TWO_LINES, # 2-line display mode, 5x8 dots
+ CMND.HOME, # move cursor to home (0x00)
+ CMND.ENTERY_MODE | flg_ENTERY_MODE.INC, # increment cursor and no shift
+ CMND.DISPLAY | flg_DISPLAY.ON, # keep cursor and blinking off
+ CMND.SHIFT | flg_SHIFT.RIGHT, # shift right cursor only
+ CMND.FUNCTION | flg_FUNCTION.TWO_LINES, # 2-line display mode, 5x8 dots
]
+
class aip31068_spi:
def __init__(self, config):
self.printer = config.get_printer()
# spi config
self.spi = bus.MCU_SPI_from_config(
- config, 0x00, pin_option="latch_pin") # (config, mode, cs_name)
+ config, 0x00, pin_option="latch_pin"
+ ) # (config, mode, cs_name)
self.mcu = self.spi.get_mcu()
self.icons = {}
- self.line_length = config.getchoice('line_length', LINE_LENGTH_OPTIONS,
- LINE_LENGTH_DEFAULT)
+ self.line_length = config.getchoice(
+ "line_length", LINE_LENGTH_OPTIONS, LINE_LENGTH_DEFAULT
+ )
# each controller's line is 2 lines on the display and hence twice
# line length
- self.text_framebuffers = [bytearray(b' '*2*self.line_length),
- bytearray(b' '*2*self.line_length)]
+ self.text_framebuffers = [
+ bytearray(b" " * 2 * self.line_length),
+ bytearray(b" " * 2 * self.line_length),
+ ]
self.glyph_framebuffer = bytearray(64)
# all_framebuffers - list of tuples per buffer type.
# Each tuple contains:
@@ -102,23 +116,33 @@ class aip31068_spi:
# (immutable tuple is allowed to store mutable bytearray)
self.all_framebuffers = [
# Text framebuffers
- (self.text_framebuffers[0], bytearray(b'~'*2*self.line_length),
- CMND.DDRAM | (flg_DDRAM.MASK & 0x00) ),
- (self.text_framebuffers[1], bytearray(b'~'*2*self.line_length),
- CMND.DDRAM | (flg_DDRAM.MASK & 0x40) ),
+ (
+ self.text_framebuffers[0],
+ bytearray(b"~" * 2 * self.line_length),
+ CMND.DDRAM | (flg_DDRAM.MASK & 0x00),
+ ),
+ (
+ self.text_framebuffers[1],
+ bytearray(b"~" * 2 * self.line_length),
+ CMND.DDRAM | (flg_DDRAM.MASK & 0x40),
+ ),
# Glyph framebuffer
- (self.glyph_framebuffer, bytearray(b'~'*64),
- CMND.CGRAM | (flg_CGRAM.MASK & 0x00) ) ]
+ (
+ self.glyph_framebuffer,
+ bytearray(b"~" * 64),
+ CMND.CGRAM | (flg_CGRAM.MASK & 0x00),
+ ),
+ ]
+
@staticmethod
- def encode(data, width = 9):
+ def encode(data, width=9):
encoded_bytes = []
accumulator = 0 # To accumulate bits
acc_bits = 0 # Count of bits in the accumulator
for num in data:
# check that num will fit in width bits
if num >= (1 << width):
- raise ValueError("Number {} does not fit in {} bits".
- format(num, width))
+ raise ValueError("Number {} does not fit in {} bits".format(num, width))
# Shift the current number into the accumulator from the right
accumulator = (accumulator << width) | num
acc_bits += width # Update the count of bits in the accumulator
@@ -135,6 +159,7 @@ class aip31068_spi:
last_byte = accumulator << (8 - acc_bits)
encoded_bytes.append(last_byte)
return encoded_bytes
+
def send(self, data, minclock=0):
# different commands have different processing time
# to avoid timing violation pad with some fast command, e.g. ENTRY_MODE
@@ -142,56 +167,63 @@ class aip31068_spi:
pad = CMND.ENTERY_MODE | flg_ENTERY_MODE.INC
for i in range(0, len(data), 8):
# Take a slice of 8 numbers
- group = data[i:i+8]
+ group = data[i : i + 8]
# Pad the group if it has fewer than 8 elements
if len(group) < 8:
group.extend([pad] * (8 - len(group)))
self.spi.spi_send(self.encode(group), minclock)
+
def flush(self):
# Find all differences in the framebuffers and send them to the chip
for new_data, old_data, fb_cmnd in self.all_framebuffers:
if new_data == old_data:
continue
# Find the position of all changed bytes in this framebuffer
- diffs = [[i, 1] for i, (n, o) in enumerate(zip(new_data, old_data))
- if n != o]
+ diffs = [
+ [i, 1] for i, (n, o) in enumerate(zip(new_data, old_data)) if n != o
+ ]
# Batch together changes that are close to each other
- for i in range(len(diffs)-2, -1, -1):
+ for i in range(len(diffs) - 2, -1, -1):
pos, count = diffs[i]
- nextpos, nextcount = diffs[i+1]
+ nextpos, nextcount = diffs[i + 1]
if pos + 4 >= nextpos and nextcount < 16:
diffs[i][1] = nextcount + (nextpos - pos)
- del diffs[i+1]
+ del diffs[i + 1]
# Transmit changes
for pos, count in diffs:
chip_pos = pos
self.send([fb_cmnd + chip_pos])
- self.send([CMND.WRITE_RAM | byte for byte in
- new_data[pos:pos+count]])
+ self.send(
+ [CMND.WRITE_RAM | byte for byte in new_data[pos : pos + count]]
+ )
old_data[:] = new_data
+
def init(self):
curtime = self.printer.get_reactor().monotonic()
print_time = self.mcu.estimated_print_time(curtime)
for i, cmds in enumerate(DISPLAY_INIT_CMNDS):
- minclock = self.mcu.print_time_to_clock(print_time + i * .100)
+ minclock = self.mcu.print_time_to_clock(print_time + i * 0.100)
self.send([cmds], minclock=minclock)
self.flush()
+
def write_text(self, x, y, data):
if x + len(data) > self.line_length:
- data = data[:self.line_length - min(x, self.line_length)]
+ data = data[: self.line_length - min(x, self.line_length)]
pos = x + ((y & 0x02) >> 1) * self.line_length
- 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):
for glyph_name, glyph_data in glyphs.items():
- data = glyph_data.get('icon5x8')
+ data = glyph_data.get("icon5x8")
if data is not None:
self.icons[glyph_name] = data
+
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, [slot])
- self.glyph_framebuffer[slot * 8:(slot + 1) * 8] = bits
+ self.glyph_framebuffer[slot * 8 : (slot + 1) * 8] = bits
return 1
char = TextGlyphs.get(glyph_name)
if char is not None:
@@ -199,11 +231,14 @@ class aip31068_spi:
self.write_text(x, y, char)
return 1
return 0
+
def write_graphics(self, x, y, data):
- pass # this display supports only hardcoded or 8 user defined glyphs
+ pass # this display supports only hardcoded or 8 user defined glyphs
+
def clear(self):
- spaces = b' ' * 2*self.line_length
+ spaces = b" " * 2 * self.line_length
self.text_framebuffers[0][:] = spaces
self.text_framebuffers[1][:] = spaces
+
def get_dimensions(self):
return (self.line_length, 4)