v.0.9.0 DigitalClock: optimzed update the display

This commit is contained in:
tiijay
2025-11-19 16:45:37 +00:00
parent f9e0e6b74b
commit c20625278d
3 changed files with 123 additions and 66 deletions

View File

@@ -1,26 +1,58 @@
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
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):
self.display = display
self.xpos = xpos
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):
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.ypos,
self.xpos,
clear_x_start_pos,
self.ypos + self.display.font_height,
self.xpos + self.CLOCK_WIDTH,
color=colors.MAGENTA,
clear_x_end_pos,
color=self.clear_color,
)
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

View File

@@ -1,82 +1,108 @@
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:
"""Berechnung der Bits für die Zeichenbreite
"""Berechnung der Bits für die Zeichenbreite
Args:
char_matrix (int): Zeichen als Array[int]
Args:
char_matrix (int): Zeichen als Array[int]
Returns:
int: Anzahl Bits für die Zeichenbreite
"""
max_val = max(char_matrix)
Returns:
int: Anzahl Bits für die Zeichenbreite
"""
max_val = max(char_matrix)
val = max_val
cw = 0
while 0xFFFFFFFF & val:
"""rechts shiften, bis alles Nullen da sind"""
val >>= 1
cw += 1
val = max_val
cw = 0
while 0xFFFFFFFF & val:
"""rechts shiften, bis alles Nullen da sind"""
val >>= 1
cw += 1
return cw
return cw
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:
letter (_type_): Array[0..nBytes]
Args:
letter (_type_): Array[0..nBytes]
Returns:
bool: _description_
"""
Returns:
bool: _description_
"""
def isLetterRight(letter):
def isByteRight(byte):
return True if 1 & byte == 1 else False
def isLetterRight(letter):
def isByteRight(byte):
return True if 1 & byte == 1 else False
for byte in letter:
if isByteRight(byte):
return True
for byte in letter:
if isByteRight(byte):
return True
return False
return False
def shiftLetterRight(letter):
def shift(letter):
return [byte >> 1 for byte in letter]
def shiftLetterRight(letter):
def shift(letter):
return [byte >> 1 for byte in letter]
shifted = letter
for i in range(8): # max 1 Bit's
shifted = shift(shifted)
if isLetterRight(shifted):
break
shifted = letter
for i in range(8): # max 1 Bit's
shifted = shift(shifted)
if isLetterRight(shifted):
break
return shifted
return shifted
if isLetterRight(letter):
return letter
if isLetterRight(letter):
return letter
# letter is not right shifted
shifted = shiftLetterRight(letter)
# letter is not right shifted
shifted = shiftLetterRight(letter)
if debug:
print('origin:')
show_byte_matrix(char, letter)
print('shifted')
show_byte_matrix(char, shifted)
if debug:
print("origin:")
show_byte_matrix(char, letter)
print("shifted")
show_byte_matrix(char, shifted)
return shifted
return shifted
def align_font(font, debug=False):
chars = [char for char in font]
print(chars)
chars = [char for char in font]
print(chars)
# Print the dictionary
print('font_pretty = {')
for char in sorted(font.keys()):
shifted = shift_letter_right(char=char, letter=font[char], debug=debug)
hex_values = [f'0x{val:02X}' for val in shifted]
print(f"\t'{char}': [{', '.join(hex_values)}],")
print('}')
# Print the dictionary
print("font_pretty = {")
for char in sorted(font.keys()):
shifted = shift_letter_right(char=char, letter=font[char], debug=debug)
hex_values = [f"0x{val:02X}" for val in shifted]
print(f"\t'{char}': [{', '.join(hex_values)}],")
print("}")
# return f'#keys: {len(list(font.keys()))}'
return f'#keys: {len(font)}'
# return f'#keys: {len(list(font.keys()))}'
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

View File

@@ -32,9 +32,8 @@ async def print_time_task() -> None:
digitalClock: DigitalClock = DigitalClock(display, 0, bottom_ypos)
while True:
dt1: str = get_datetime_string()
dt2: str = get_german_datetime()
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 asyncio.sleep(2)