From c20625278d331ce5c0a819639b14b6831699758e Mon Sep 17 00:00:00 2001 From: tiijay Date: Wed, 19 Nov 2025 16:45:37 +0000 Subject: [PATCH] v.0.9.0 DigitalClock: optimzed update the display --- app/utils/digital_clock.py | 46 ++++++++++-- app/utils/font_utils.py | 140 ++++++++++++++++++++++--------------- main.py | 3 +- 3 files changed, 123 insertions(+), 66 deletions(-) diff --git a/app/utils/digital_clock.py b/app/utils/digital_clock.py index 62575a6..674089e 100644 --- a/app/utils/digital_clock.py +++ b/app/utils/digital_clock.py @@ -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 diff --git a/app/utils/font_utils.py b/app/utils/font_utils.py index c528772..5a188a8 100644 --- a/app/utils/font_utils.py +++ b/app/utils/font_utils.py @@ -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 diff --git a/main.py b/main.py index 4144d08..678f082 100644 --- a/main.py +++ b/main.py @@ -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)