v.0.9.1 DigitalClock: optimzed update the display
This commit is contained in:
@@ -1,26 +1,58 @@
|
|||||||
from app.display.neopixel_64x64 import NeoPixel_64x64
|
from app.display.neopixel_64x64 import NeoPixel_64x64
|
||||||
from app.utils import get_datetime_string
|
from app.utils import get_datetime_string, text_width, find_first_mismatch
|
||||||
from app.utils import colors
|
from app.utils import colors
|
||||||
|
|
||||||
|
|
||||||
class DigitalClock:
|
class DigitalClock:
|
||||||
CLOCK_WIDTH = 38
|
stored_time_str: str = "99:99:99"
|
||||||
|
text_color: tuple[int[3]] = colors.NEON_YELLOW
|
||||||
|
clear_color: tuple[int[3]] = colors.BLACK
|
||||||
|
|
||||||
def __init__(self, display: NeoPixel_64x64, xpos: int, ypos: int):
|
def __init__(self, display: NeoPixel_64x64, xpos: int, ypos: int):
|
||||||
self.display = display
|
self.display = display
|
||||||
self.xpos = xpos
|
self.xpos = xpos
|
||||||
self.ypos = ypos
|
self.ypos = ypos
|
||||||
|
|
||||||
|
def _toggle_clear_color(self) -> tuple[int]:
|
||||||
|
self.clear_color = (
|
||||||
|
colors.BLACK if self.clear_color != colors.BLACK else colors.MAGENTA
|
||||||
|
)
|
||||||
|
return self.clear_color
|
||||||
|
|
||||||
|
def _text_width(self, text: str) -> int:
|
||||||
|
return text_width(text, self.display.selected_font)
|
||||||
|
|
||||||
async def tick(self):
|
async def tick(self):
|
||||||
time_str: str = get_datetime_string("time")
|
time_str: str = get_datetime_string("time")[:8]
|
||||||
|
|
||||||
|
# ab welcher Position malen wir den String neu
|
||||||
|
mismatch_pos: int = find_first_mismatch(self.stored_time_str, time_str)
|
||||||
|
|
||||||
|
untouched_part: str = time_str[:mismatch_pos]
|
||||||
|
fresh_part: str = time_str[mismatch_pos:]
|
||||||
|
part_to_clear: str = self.stored_time_str[mismatch_pos:]
|
||||||
|
|
||||||
|
print(f"untouched_part: {untouched_part}[{part_to_clear}-->{fresh_part}] ")
|
||||||
|
|
||||||
|
textwidth: int = self._text_width(self.stored_time_str)
|
||||||
|
print(f"{self.stored_time_str}: #{textwidth}")
|
||||||
|
|
||||||
|
textwidth_untouched_part: int = self._text_width(untouched_part)
|
||||||
|
clear_x_start_pos: int = self.xpos + textwidth_untouched_part + 1
|
||||||
|
|
||||||
|
textwidth_part_to_clear: int = self._text_width(part_to_clear)
|
||||||
|
clear_x_end_pos: int = clear_x_start_pos + textwidth_part_to_clear - 1
|
||||||
|
|
||||||
self.display.clear_box(
|
self.display.clear_box(
|
||||||
self.ypos,
|
self.ypos,
|
||||||
self.xpos,
|
clear_x_start_pos,
|
||||||
self.ypos + self.display.font_height,
|
self.ypos + self.display.font_height,
|
||||||
self.xpos + self.CLOCK_WIDTH,
|
clear_x_end_pos,
|
||||||
color=colors.MAGENTA,
|
color=self.clear_color,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.display.write_text(
|
self.display.write_text(
|
||||||
time_str[:8], self.xpos, self.ypos, color=colors.NEON_YELLOW
|
fresh_part, clear_x_start_pos, self.ypos, color=self.text_color
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.stored_time_str = time_str
|
||||||
|
|||||||
@@ -1,82 +1,108 @@
|
|||||||
from .math_utils import show_byte_matrix
|
from .math_utils import show_byte_matrix
|
||||||
|
|
||||||
|
|
||||||
|
def text_width(text: str, font: dict[str, list[int]]) -> int:
|
||||||
|
text_width_overall: int = sum([char_width(font[char]) for char in text])
|
||||||
|
|
||||||
|
return text_width_overall + len(text) - 1
|
||||||
|
|
||||||
|
|
||||||
def char_width(char_matrix) -> int:
|
def char_width(char_matrix) -> int:
|
||||||
"""Berechnung der Bits für die Zeichenbreite
|
"""Berechnung der Bits für die Zeichenbreite
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
char_matrix (int): Zeichen als Array[int]
|
char_matrix (int): Zeichen als Array[int]
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
int: Anzahl Bits für die Zeichenbreite
|
int: Anzahl Bits für die Zeichenbreite
|
||||||
"""
|
"""
|
||||||
max_val = max(char_matrix)
|
max_val = max(char_matrix)
|
||||||
|
|
||||||
val = max_val
|
val = max_val
|
||||||
cw = 0
|
cw = 0
|
||||||
while 0xFFFFFFFF & val:
|
while 0xFFFFFFFF & val:
|
||||||
"""rechts shiften, bis alles Nullen da sind"""
|
"""rechts shiften, bis alles Nullen da sind"""
|
||||||
val >>= 1
|
val >>= 1
|
||||||
cw += 1
|
cw += 1
|
||||||
|
|
||||||
|
return cw
|
||||||
|
|
||||||
return cw
|
|
||||||
|
|
||||||
def shift_letter_right(char, letter, debug=False) -> bool:
|
def shift_letter_right(char, letter, debug=False) -> bool:
|
||||||
"""Prüfe ob das Zeichen auch komplett nach rechts gezogen ist
|
"""Prüfe ob das Zeichen auch komplett nach rechts gezogen ist
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
letter (_type_): Array[0..nBytes]
|
letter (_type_): Array[0..nBytes]
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: _description_
|
bool: _description_
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def isLetterRight(letter):
|
def isLetterRight(letter):
|
||||||
def isByteRight(byte):
|
def isByteRight(byte):
|
||||||
return True if 1 & byte == 1 else False
|
return True if 1 & byte == 1 else False
|
||||||
|
|
||||||
for byte in letter:
|
for byte in letter:
|
||||||
if isByteRight(byte):
|
if isByteRight(byte):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def shiftLetterRight(letter):
|
def shiftLetterRight(letter):
|
||||||
def shift(letter):
|
def shift(letter):
|
||||||
return [byte >> 1 for byte in letter]
|
return [byte >> 1 for byte in letter]
|
||||||
|
|
||||||
shifted = letter
|
shifted = letter
|
||||||
for i in range(8): # max 1 Bit's
|
for i in range(8): # max 1 Bit's
|
||||||
shifted = shift(shifted)
|
shifted = shift(shifted)
|
||||||
if isLetterRight(shifted):
|
if isLetterRight(shifted):
|
||||||
break
|
break
|
||||||
|
|
||||||
return shifted
|
return shifted
|
||||||
|
|
||||||
if isLetterRight(letter):
|
if isLetterRight(letter):
|
||||||
return letter
|
return letter
|
||||||
|
|
||||||
# letter is not right shifted
|
# letter is not right shifted
|
||||||
shifted = shiftLetterRight(letter)
|
shifted = shiftLetterRight(letter)
|
||||||
|
|
||||||
if debug:
|
if debug:
|
||||||
print('origin:')
|
print("origin:")
|
||||||
show_byte_matrix(char, letter)
|
show_byte_matrix(char, letter)
|
||||||
print('shifted')
|
print("shifted")
|
||||||
show_byte_matrix(char, shifted)
|
show_byte_matrix(char, shifted)
|
||||||
|
|
||||||
|
return shifted
|
||||||
|
|
||||||
return shifted
|
|
||||||
|
|
||||||
def align_font(font, debug=False):
|
def align_font(font, debug=False):
|
||||||
chars = [char for char in font]
|
chars = [char for char in font]
|
||||||
print(chars)
|
print(chars)
|
||||||
|
|
||||||
# Print the dictionary
|
# Print the dictionary
|
||||||
print('font_pretty = {')
|
print("font_pretty = {")
|
||||||
for char in sorted(font.keys()):
|
for char in sorted(font.keys()):
|
||||||
shifted = shift_letter_right(char=char, letter=font[char], debug=debug)
|
shifted = shift_letter_right(char=char, letter=font[char], debug=debug)
|
||||||
hex_values = [f'0x{val:02X}' for val in shifted]
|
hex_values = [f"0x{val:02X}" for val in shifted]
|
||||||
print(f"\t'{char}': [{', '.join(hex_values)}],")
|
print(f"\t'{char}': [{', '.join(hex_values)}],")
|
||||||
print('}')
|
print("}")
|
||||||
|
|
||||||
# return f'#keys: {len(list(font.keys()))}'
|
# return f'#keys: {len(list(font.keys()))}'
|
||||||
return f'#keys: {len(font)}'
|
return f"#keys: {len(font)}"
|
||||||
|
|
||||||
|
|
||||||
|
def find_first_mismatch(str1: str, str2: str) -> int:
|
||||||
|
"""
|
||||||
|
Compare two strings of equal length and return the position of first mismatch.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
str1 (str): First string
|
||||||
|
str2 (str): Second string (same length as str1)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: Position of first mismatch, or -1 if strings are identical
|
||||||
|
"""
|
||||||
|
for i in range(len(str1)):
|
||||||
|
if str1[i] != str2[i]:
|
||||||
|
return i
|
||||||
|
return -1
|
||||||
|
|||||||
3
main.py
3
main.py
@@ -32,9 +32,8 @@ async def print_time_task() -> None:
|
|||||||
digitalClock: DigitalClock = DigitalClock(display, 0, bottom_ypos)
|
digitalClock: DigitalClock = DigitalClock(display, 0, bottom_ypos)
|
||||||
while True:
|
while True:
|
||||||
dt1: str = get_datetime_string()
|
dt1: str = get_datetime_string()
|
||||||
dt2: str = get_german_datetime()
|
|
||||||
simpleCnt += 1
|
simpleCnt += 1
|
||||||
print(f"print_time_task running... {simpleCnt.value % 16} {dt1} {dt2}")
|
print(f"print_time_task running... {simpleCnt.value % 16} {dt1}")
|
||||||
|
|
||||||
await digitalClock.tick()
|
await digitalClock.tick()
|
||||||
await asyncio.sleep(2)
|
await asyncio.sleep(2)
|
||||||
|
|||||||
Reference in New Issue
Block a user