From 9fcc7712e67c670205fcb8ea947b0cc8b6a59060 Mon Sep 17 00:00:00 2001 From: tiijay Date: Thu, 23 Oct 2025 19:06:30 +0200 Subject: [PATCH] v.0.3.1 font 3x5 pretty --- app/display/fonts/font_3x5.py | 184 ++++++++++++----------- app/display/fonts/font_5x7.py | 215 ++++++++++++++------------- app/display/fonts/font_5x7_opt.py | 237 ------------------------------ app/display/fonts/fonts_utils.py | 101 ++++++++----- app/display/neopixel_64x64.py | 74 +++------- app/utils/utils.py | 46 ------ main.py | 69 +++++---- 7 files changed, 334 insertions(+), 592 deletions(-) delete mode 100644 app/display/fonts/font_5x7_opt.py diff --git a/app/display/fonts/font_3x5.py b/app/display/fonts/font_3x5.py index cb929f1..9876afc 100644 --- a/app/display/fonts/font_3x5.py +++ b/app/display/fonts/font_3x5.py @@ -1,90 +1,98 @@ font_3x5 = { - # Uppercase Letters - 'A': [0x07, 0x05, 0x07], - 'B': [0x07, 0x07, 0x07], - 'C': [0x07, 0x01, 0x07], - 'D': [0x06, 0x05, 0x06], - 'E': [0x07, 0x03, 0x07], - 'F': [0x07, 0x03, 0x01], - 'G': [0x07, 0x05, 0x07], - 'H': [0x05, 0x07, 0x05], - 'I': [0x07, 0x02, 0x07], - 'J': [0x04, 0x05, 0x07], - 'K': [0x05, 0x03, 0x05], - 'L': [0x01, 0x01, 0x07], - 'M': [0x07, 0x07, 0x05], - 'N': [0x07, 0x05, 0x05], - 'O': [0x07, 0x05, 0x07], - 'P': [0x07, 0x07, 0x01], - 'Q': [0x07, 0x05, 0x07], - 'R': [0x07, 0x07, 0x05], - 'S': [0x07, 0x07, 0x07], - 'T': [0x07, 0x02, 0x02], - 'U': [0x05, 0x05, 0x07], - 'V': [0x05, 0x05, 0x02], - 'W': [0x05, 0x07, 0x07], - 'X': [0x05, 0x02, 0x05], - 'Y': [0x05, 0x07, 0x02], - 'Z': [0x07, 0x02, 0x07], - # Numbers - '0': [0x07, 0x05, 0x07], - '1': [0x02, 0x02, 0x02], - '2': [0x07, 0x07, 0x07], - '3': [0x07, 0x07, 0x07], - '4': [0x05, 0x07, 0x04], - '5': [0x07, 0x07, 0x07], - '6': [0x07, 0x07, 0x07], - '7': [0x07, 0x04, 0x04], - '8': [0x07, 0x07, 0x07], - '9': [0x07, 0x07, 0x07], - # Lowercase (limited) - 'a': [0x06, 0x07, 0x07], - 'b': [0x01, 0x07, 0x07], - 'c': [0x07, 0x01, 0x07], - 'd': [0x04, 0x07, 0x07], - 'e': [0x07, 0x07, 0x03], - 'f': [0x06, 0x07, 0x02], - 'g': [0x07, 0x07, 0x06], - 'h': [0x01, 0x07, 0x05], - 'i': [0x02, 0x00, 0x02], - 'j': [0x04, 0x00, 0x06], - 'k': [0x01, 0x06, 0x05], - 'l': [0x02, 0x02, 0x02], - 'm': [0x07, 0x07, 0x05], - 'n': [0x07, 0x05, 0x05], - 'o': [0x07, 0x05, 0x07], - 'p': [0x07, 0x07, 0x01], - 'q': [0x07, 0x07, 0x04], - 'r': [0x07, 0x01, 0x01], - 's': [0x07, 0x07, 0x07], - 't': [0x02, 0x07, 0x02], - 'u': [0x05, 0x05, 0x07], - 'v': [0x05, 0x05, 0x02], - 'w': [0x05, 0x07, 0x07], - 'x': [0x05, 0x02, 0x05], - 'y': [0x05, 0x07, 0x02], - 'z': [0x07, 0x02, 0x07], - # Punctuation - ' ': [0x00, 0x00, 0x00], - '.': [0x00, 0x00, 0x02], - ',': [0x00, 0x00, 0x02], - '!': [0x02, 0x02, 0x00], - '?': [0x07, 0x06, 0x02], - ':': [0x00, 0x02, 0x00], - ';': [0x00, 0x02, 0x02], - '-': [0x00, 0x07, 0x00], - '_': [0x00, 0x00, 0x07], - '+': [0x02, 0x07, 0x02], - '=': [0x07, 0x00, 0x07], - '(': [0x02, 0x01, 0x02], - ')': [0x02, 0x04, 0x02], - '[': [0x03, 0x01, 0x03], - ']': [0x06, 0x04, 0x06], - '/': [0x04, 0x02, 0x01], - '\\': [0x01, 0x02, 0x04], - '*': [0x05, 0x02, 0x05], - '"': [0x05, 0x00, 0x00], - "'": [0x02, 0x00, 0x00], - '°': [0x02, 0x05, 0x02], # Degree symbol - '|': [0x02, 0x02, 0x02], # Vertical bar + ' ': [0x00, 0x00, 0x00, 0x00, 0x00], + '!': [0x01, 0x01, 0x01, 0x00, 0x01], + '"': [0x05, 0x05, 0x00, 0x00, 0x00], + '#': [0x05, 0x07, 0x05, 0x07, 0x05], + '$': [0x07, 0x06, 0x07, 0x03, 0x07], + '%': [0x05, 0x01, 0x02, 0x04, 0x05], + '&': [0x02, 0x05, 0x02, 0x05, 0x03], + "'": [0x01, 0x01, 0x00, 0x00, 0x00], + '(': [0x01, 0x02, 0x02, 0x02, 0x01], + ')': [0x02, 0x01, 0x01, 0x01, 0x02], + '*': [0x00, 0x05, 0x02, 0x05, 0x00], + '+': [0x00, 0x02, 0x07, 0x02, 0x00], + ',': [0x00, 0x00, 0x00, 0x01, 0x02], + '-': [0x00, 0x00, 0x07, 0x00, 0x00], + '.': [0x00, 0x00, 0x00, 0x00, 0x01], + '/': [0x01, 0x01, 0x02, 0x04, 0x04], + '0': [0x07, 0x05, 0x05, 0x05, 0x07], + '1': [0x02, 0x06, 0x02, 0x02, 0x07], + '2': [0x07, 0x01, 0x07, 0x04, 0x07], + '3': [0x07, 0x01, 0x07, 0x01, 0x07], + '4': [0x05, 0x05, 0x07, 0x01, 0x01], + '5': [0x07, 0x04, 0x07, 0x01, 0x07], + '6': [0x07, 0x04, 0x07, 0x05, 0x07], + '7': [0x07, 0x01, 0x01, 0x01, 0x01], + '8': [0x07, 0x05, 0x07, 0x05, 0x07], + '9': [0x07, 0x05, 0x07, 0x01, 0x07], + ':': [0x00, 0x01, 0x00, 0x01, 0x00], + ';': [0x00, 0x01, 0x00, 0x01, 0x02], + '<': [0x01, 0x02, 0x04, 0x02, 0x01], + '=': [0x00, 0x07, 0x00, 0x07, 0x00], + '>': [0x04, 0x02, 0x01, 0x02, 0x04], + '?': [0x07, 0x01, 0x02, 0x00, 0x02], + '@': [0x07, 0x05, 0x07, 0x04, 0x07], + 'A': [0x02, 0x05, 0x07, 0x05, 0x05], + 'B': [0x06, 0x05, 0x06, 0x05, 0x06], + 'C': [0x07, 0x04, 0x04, 0x04, 0x07], + 'D': [0x06, 0x05, 0x05, 0x05, 0x06], + 'E': [0x07, 0x04, 0x06, 0x04, 0x07], + 'F': [0x07, 0x04, 0x06, 0x04, 0x04], + 'G': [0x07, 0x04, 0x05, 0x05, 0x07], + 'H': [0x05, 0x05, 0x07, 0x05, 0x05], + 'I': [0x07, 0x02, 0x02, 0x02, 0x07], + 'J': [0x01, 0x01, 0x01, 0x05, 0x02], + 'K': [0x05, 0x05, 0x06, 0x05, 0x05], + 'L': [0x04, 0x04, 0x04, 0x04, 0x07], + 'M': [0x05, 0x07, 0x07, 0x05, 0x05], + 'N': [0x05, 0x07, 0x07, 0x07, 0x05], + 'O': [0x02, 0x05, 0x05, 0x05, 0x02], + 'P': [0x06, 0x05, 0x06, 0x04, 0x04], + 'Q': [0x02, 0x05, 0x05, 0x06, 0x03], + 'R': [0x06, 0x05, 0x06, 0x05, 0x05], + 'S': [0x07, 0x04, 0x02, 0x01, 0x07], + 'T': [0x07, 0x02, 0x02, 0x02, 0x02], + 'U': [0x05, 0x05, 0x05, 0x05, 0x07], + 'V': [0x05, 0x05, 0x05, 0x05, 0x02], + 'W': [0x05, 0x05, 0x07, 0x07, 0x05], + 'X': [0x05, 0x05, 0x02, 0x05, 0x05], + 'Y': [0x05, 0x05, 0x02, 0x02, 0x02], + 'Z': [0x07, 0x01, 0x02, 0x04, 0x07], + '[': [0x03, 0x02, 0x02, 0x02, 0x03], + '\\': [0x04, 0x04, 0x02, 0x01, 0x01], + ']': [0x03, 0x01, 0x01, 0x01, 0x03], + '^': [0x02, 0x05, 0x00, 0x00, 0x00], + '_': [0x00, 0x00, 0x00, 0x00, 0x07], + '`': [0x02, 0x01, 0x00, 0x00, 0x00], + 'a': [0x00, 0x07, 0x05, 0x05, 0x03], + 'b': [0x04, 0x04, 0x06, 0x05, 0x06], + 'c': [0x00, 0x07, 0x04, 0x04, 0x07], + 'd': [0x01, 0x01, 0x07, 0x05, 0x07], + 'e': [0x00, 0x07, 0x07, 0x04, 0x07], + 'f': [0x03, 0x04, 0x06, 0x04, 0x04], + 'g': [0x00, 0x07, 0x05, 0x07, 0x01], + 'h': [0x04, 0x04, 0x06, 0x05, 0x05], + 'i': [0x01, 0x00, 0x01, 0x01, 0x01], + 'j': [0x01, 0x00, 0x01, 0x01, 0x06], + 'k': [0x04, 0x05, 0x06, 0x05, 0x05], + 'l': [0x06, 0x02, 0x02, 0x02, 0x07], + 'm': [0x00, 0x05, 0x07, 0x05, 0x05], + 'n': [0x00, 0x06, 0x05, 0x05, 0x05], + 'o': [0x00, 0x02, 0x05, 0x05, 0x02], + 'p': [0x00, 0x06, 0x05, 0x06, 0x04], + 'q': [0x00, 0x07, 0x05, 0x07, 0x01], + 'r': [0x00, 0x03, 0x04, 0x04, 0x04], + 's': [0x00, 0x07, 0x06, 0x03, 0x07], + 't': [0x04, 0x07, 0x04, 0x04, 0x03], + 'u': [0x00, 0x05, 0x05, 0x05, 0x07], + 'v': [0x00, 0x05, 0x05, 0x05, 0x02], + 'w': [0x00, 0x05, 0x05, 0x07, 0x05], + 'x': [0x00, 0x05, 0x02, 0x02, 0x05], + 'y': [0x00, 0x05, 0x05, 0x07, 0x01], + 'z': [0x00, 0x07, 0x02, 0x04, 0x07], + '|': [0x01, 0x01, 0x01, 0x01, 0x01], + '~': [0x00, 0x03, 0x06, 0x00, 0x00], + '°': [0x02, 0x05, 0x02, 0x00, 0x00], + '¶': [0x07, 0x05, 0x05, 0x05, 0x05], + '•': [0x00, 0x00, 0x01, 0x00, 0x00], } diff --git a/app/display/fonts/font_5x7.py b/app/display/fonts/font_5x7.py index 747aea6..41d00ef 100644 --- a/app/display/fonts/font_5x7.py +++ b/app/display/fonts/font_5x7.py @@ -1,109 +1,114 @@ -# fonts.py - Ready-to-use fonts for LED matrix +# fonts.py - Optimized fonts for LED matrix with character width adjustment - -# 5x7 Font (Medium) +# 5x7 Font (Optimized Width) font_5x7 = { - # Uppercase letters (A-Z) - 'A': [0x0E, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11], - 'B': [0x1E, 0x11, 0x11, 0x1E, 0x11, 0x11, 0x1E], - 'C': [0x0E, 0x11, 0x10, 0x10, 0x10, 0x11, 0x0E], - 'D': [0x1E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1E], - 'E': [0x1F, 0x10, 0x10, 0x1E, 0x10, 0x10, 0x1F], - 'F': [0x1F, 0x10, 0x10, 0x1E, 0x10, 0x10, 0x10], - 'G': [0x0E, 0x11, 0x10, 0x13, 0x11, 0x11, 0x0F], - 'H': [0x11, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11], - 'I': [0x0E, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E], - 'J': [0x07, 0x02, 0x02, 0x02, 0x02, 0x12, 0x0C], - 'K': [0x11, 0x12, 0x14, 0x18, 0x14, 0x12, 0x11], - 'L': [0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1F], - 'M': [0x11, 0x1B, 0x15, 0x15, 0x11, 0x11, 0x11], - 'N': [0x11, 0x19, 0x19, 0x15, 0x13, 0x13, 0x11], - 'O': [0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E], - 'P': [0x1E, 0x11, 0x11, 0x1E, 0x10, 0x10, 0x10], - 'Q': [0x0E, 0x11, 0x11, 0x11, 0x15, 0x12, 0x0D], - 'R': [0x1E, 0x11, 0x11, 0x1E, 0x14, 0x12, 0x11], - 'S': [0x0F, 0x10, 0x10, 0x0E, 0x01, 0x01, 0x1E], - 'T': [0x1F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04], - 'U': [0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E], - 'V': [0x11, 0x11, 0x11, 0x11, 0x11, 0x0A, 0x04], - 'W': [0x11, 0x11, 0x11, 0x15, 0x15, 0x15, 0x0A], - 'X': [0x11, 0x11, 0x0A, 0x04, 0x0A, 0x11, 0x11], - 'Y': [0x11, 0x11, 0x0A, 0x04, 0x04, 0x04, 0x04], - 'Z': [0x1F, 0x01, 0x02, 0x04, 0x08, 0x10, 0x1F], - # Lowercase letters (a-z) - 'a': [0x00, 0x00, 0x0E, 0x01, 0x0F, 0x11, 0x0F], - 'b': [0x10, 0x10, 0x16, 0x19, 0x11, 0x11, 0x1E], - 'c': [0x00, 0x00, 0x0E, 0x11, 0x10, 0x11, 0x0E], - 'd': [0x01, 0x01, 0x0D, 0x13, 0x11, 0x11, 0x0F], - 'e': [0x00, 0x00, 0x0E, 0x11, 0x1F, 0x10, 0x0E], - 'f': [0x06, 0x09, 0x08, 0x1C, 0x08, 0x08, 0x08], - 'g': [0x00, 0x0F, 0x11, 0x11, 0x0F, 0x01, 0x0E], - 'h': [0x10, 0x10, 0x16, 0x19, 0x11, 0x11, 0x11], - 'i': [0x04, 0x00, 0x0C, 0x04, 0x04, 0x04, 0x0E], - 'j': [0x02, 0x00, 0x06, 0x02, 0x02, 0x12, 0x0C], - 'k': [0x10, 0x10, 0x12, 0x14, 0x18, 0x14, 0x12], - 'l': [0x0C, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E], - 'm': [0x00, 0x00, 0x1A, 0x15, 0x15, 0x15, 0x15], - 'n': [0x00, 0x00, 0x16, 0x19, 0x11, 0x11, 0x11], - 'o': [0x00, 0x00, 0x0E, 0x11, 0x11, 0x11, 0x0E], - 'p': [0x00, 0x00, 0x1E, 0x11, 0x1E, 0x10, 0x10], - 'q': [0x00, 0x00, 0x0D, 0x13, 0x0F, 0x01, 0x01], - 'r': [0x00, 0x00, 0x16, 0x19, 0x10, 0x10, 0x10], - 's': [0x00, 0x00, 0x0E, 0x10, 0x0E, 0x01, 0x1E], - 't': [0x08, 0x08, 0x1C, 0x08, 0x08, 0x09, 0x06], - 'u': [0x00, 0x00, 0x11, 0x11, 0x11, 0x13, 0x0D], - 'v': [0x00, 0x00, 0x11, 0x11, 0x11, 0x0A, 0x04], - 'w': [0x00, 0x00, 0x11, 0x11, 0x15, 0x15, 0x0A], - 'x': [0x00, 0x00, 0x11, 0x0A, 0x04, 0x0A, 0x11], - 'y': [0x00, 0x00, 0x11, 0x11, 0x0F, 0x01, 0x0E], - 'z': [0x00, 0x00, 0x1F, 0x02, 0x04, 0x08, 0x1F], - # Numbers (0-9) - '0': [0x0E, 0x11, 0x13, 0x15, 0x19, 0x11, 0x0E], - '1': [0x04, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x0E], - '2': [0x0E, 0x11, 0x01, 0x02, 0x04, 0x08, 0x1F], - '3': [0x1F, 0x02, 0x04, 0x02, 0x01, 0x11, 0x0E], - '4': [0x02, 0x06, 0x0A, 0x12, 0x1F, 0x02, 0x02], - '5': [0x1F, 0x10, 0x1E, 0x01, 0x01, 0x11, 0x0E], - '6': [0x06, 0x08, 0x10, 0x1E, 0x11, 0x11, 0x0E], - '7': [0x1F, 0x01, 0x02, 0x04, 0x08, 0x08, 0x08], - '8': [0x0E, 0x11, 0x11, 0x0E, 0x11, 0x11, 0x0E], - '9': [0x0E, 0x11, 0x11, 0x0F, 0x01, 0x02, 0x0C], - # Punctuation and symbols - ' ': [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], - '!': [0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x04], - '?': [0x0E, 0x11, 0x02, 0x04, 0x04, 0x00, 0x04], - '.': [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04], - ',': [0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08], - ':': [0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00], - ';': [0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x08], - "'": [0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00], - '"': [0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00], - '-': [0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00], - '_': [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F], - '+': [0x00, 0x04, 0x04, 0x1F, 0x04, 0x04, 0x00], - '=': [0x00, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x00], - '*': [0x00, 0x0A, 0x04, 0x1F, 0x04, 0x0A, 0x00], - '/': [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x00], - '\\': [0x00, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00], - '(': [0x02, 0x04, 0x08, 0x08, 0x08, 0x04, 0x02], - ')': [0x08, 0x04, 0x02, 0x02, 0x02, 0x04, 0x08], - '[': [0x0E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0E], - ']': [0x0E, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0E], - '{': [0x06, 0x04, 0x04, 0x08, 0x04, 0x04, 0x06], - '}': [0x0C, 0x04, 0x04, 0x02, 0x04, 0x04, 0x0C], - '<': [0x00, 0x01, 0x02, 0x04, 0x02, 0x01, 0x00], - '>': [0x00, 0x08, 0x04, 0x02, 0x04, 0x08, 0x00], - '@': [0x0E, 0x11, 0x17, 0x15, 0x17, 0x10, 0x0E], - '#': [0x0A, 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x0A], - '$': [0x04, 0x0F, 0x14, 0x0E, 0x05, 0x1E, 0x04], - '%': [0x18, 0x19, 0x02, 0x04, 0x08, 0x13, 0x03], - '&': [0x0C, 0x12, 0x14, 0x08, 0x15, 0x12, 0x0D], - '^': [0x04, 0x0A, 0x11, 0x00, 0x00, 0x00, 0x00], - '~': [0x00, 0x00, 0x00, 0x0D, 0x12, 0x00, 0x00], + # Uppercase letters (A-Z) - Optimized for better spacing + 'A': [0x0E, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11], # Width: 5 + 'B': [0x1E, 0x11, 0x11, 0x1E, 0x11, 0x11, 0x1E], # Width: 5 + 'C': [0x0E, 0x11, 0x10, 0x10, 0x10, 0x11, 0x0E], # Width: 5 + 'D': [0x1E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1E], # Width: 5 + 'E': [0x1F, 0x10, 0x10, 0x1E, 0x10, 0x10, 0x1F], # Width: 5 + 'F': [0x1F, 0x10, 0x10, 0x1E, 0x10, 0x10, 0x10], # Width: 5 + 'G': [0x0E, 0x11, 0x10, 0x13, 0x11, 0x11, 0x0F], # Width: 5 + 'H': [0x11, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11], # Width: 5 + # 'I': [0x0E, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E], # Width: 3 + 'I': [0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07], # Width: 3 + 'J': [0x07, 0x02, 0x02, 0x02, 0x02, 0x12, 0x0C], # Width: 4 + 'K': [0x11, 0x12, 0x14, 0x18, 0x14, 0x12, 0x11], # Width: 5 + 'L': [0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1F], # Width: 5 + 'M': [0x11, 0x1B, 0x15, 0x15, 0x11, 0x11, 0x11], # Width: 5 + 'N': [0x11, 0x19, 0x19, 0x15, 0x13, 0x13, 0x11], # Width: 5 + 'O': [0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E], # Width: 5 + 'P': [0x1E, 0x11, 0x11, 0x1E, 0x10, 0x10, 0x10], # Width: 5 + 'Q': [0x0E, 0x11, 0x11, 0x11, 0x15, 0x12, 0x0D], # Width: 5 + 'R': [0x1E, 0x11, 0x11, 0x1E, 0x14, 0x12, 0x11], # Width: 5 + 'S': [0x0F, 0x10, 0x10, 0x0E, 0x01, 0x01, 0x1E], # Width: 5 + 'T': [0x1F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04], # Width: 5 + 'U': [0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E], # Width: 5 + 'V': [0x11, 0x11, 0x11, 0x11, 0x11, 0x0A, 0x04], # Width: 5 + 'W': [0x11, 0x11, 0x11, 0x15, 0x15, 0x15, 0x0A], # Width: 5 + 'X': [0x11, 0x11, 0x0A, 0x04, 0x0A, 0x11, 0x11], # Width: 5 + 'Y': [0x11, 0x11, 0x0A, 0x04, 0x04, 0x04, 0x04], # Width: 5 + 'Z': [0x1F, 0x01, 0x02, 0x04, 0x08, 0x10, 0x1F], # Width: 5 + # Lowercase letters (a-z) - Optimized for compact display + 'a': [0x00, 0x00, 0x0E, 0x01, 0x0F, 0x11, 0x0F], # Width: 4 + 'b': [0x10, 0x10, 0x16, 0x19, 0x11, 0x11, 0x1E], # Width: 5 + 'c': [0x00, 0x00, 0x0E, 0x11, 0x10, 0x11, 0x0E], # Width: 4 + 'd': [0x01, 0x01, 0x0D, 0x13, 0x11, 0x11, 0x0F], # Width: 5 + 'e': [0x00, 0x00, 0x0E, 0x11, 0x1F, 0x10, 0x0E], # Width: 4 + 'f': [0x06, 0x09, 0x08, 0x1C, 0x08, 0x08, 0x08], # Width: 4 + 'g': [0x00, 0x0F, 0x11, 0x11, 0x0F, 0x01, 0x0E], # Width: 5 + 'h': [0x10, 0x10, 0x16, 0x19, 0x11, 0x11, 0x11], # Width: 5 + # 'i': [0x00, 0x04, 0x00, 0x0C, 0x04, 0x04, 0x0E], # Width: 2 + 'i': [0x00, 0x02, 0x00, 0x06, 0x02, 0x02, 0x07], # Width: 2 + 'j': [0x00, 0x02, 0x00, 0x06, 0x02, 0x12, 0x0C], # Width: 3 + 'k': [0x10, 0x10, 0x12, 0x14, 0x18, 0x14, 0x12], # Width: 4 + # 'l': [0x0C, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E], # Width: 3 + 'l': [0x06, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07], # Width: 3 + 'm': [0x00, 0x00, 0x1A, 0x15, 0x15, 0x15, 0x15], # Width: 5 + 'n': [0x00, 0x00, 0x16, 0x19, 0x11, 0x11, 0x11], # Width: 5 + 'o': [0x00, 0x00, 0x0E, 0x11, 0x11, 0x11, 0x0E], # Width: 4 + 'p': [0x00, 0x00, 0x1E, 0x11, 0x1E, 0x10, 0x10], # Width: 5 + 'q': [0x00, 0x00, 0x0D, 0x13, 0x0F, 0x01, 0x01], # Width: 5 + 'r': [0x00, 0x00, 0x16, 0x19, 0x10, 0x10, 0x10], # Width: 5 + 's': [0x00, 0x00, 0x0E, 0x10, 0x0E, 0x01, 0x1E], # Width: 4 + 't': [0x08, 0x08, 0x1C, 0x08, 0x08, 0x09, 0x06], # Width: 4 + 'u': [0x00, 0x00, 0x11, 0x11, 0x11, 0x13, 0x0D], # Width: 5 + 'v': [0x00, 0x00, 0x11, 0x11, 0x11, 0x0A, 0x04], # Width: 5 + 'w': [0x00, 0x00, 0x11, 0x11, 0x15, 0x15, 0x0A], # Width: 5 + 'x': [0x00, 0x00, 0x11, 0x0A, 0x04, 0x0A, 0x11], # Width: 5 + 'y': [0x00, 0x00, 0x11, 0x11, 0x0F, 0x01, 0x0E], # Width: 5 + 'z': [0x00, 0x00, 0x1F, 0x02, 0x04, 0x08, 0x1F], # Width: 5 + # Numbers (0-9) - Optimized for consistent width + '0': [0x0E, 0x11, 0x13, 0x15, 0x19, 0x11, 0x0E], # Width: 5 + '1': [0x02, 0x06, 0x02, 0x02, 0x02, 0x02, 0x07], # Width: 3 + # '1': [0x04, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x0E], # Width: 3 + # '1': [0x08, 0x18, 0x08, 0x08, 0x08, 0x08, 0x1C], # Width: 3 + '2': [0x0E, 0x11, 0x01, 0x02, 0x04, 0x08, 0x1F], # Width: 5 + '3': [0x1F, 0x02, 0x04, 0x02, 0x01, 0x11, 0x0E], # Width: 5 + '4': [0x02, 0x06, 0x0A, 0x12, 0x1F, 0x02, 0x02], # Width: 5 + '5': [0x1F, 0x10, 0x1E, 0x01, 0x01, 0x11, 0x0E], # Width: 5 + '6': [0x06, 0x08, 0x10, 0x1E, 0x11, 0x11, 0x0E], # Width: 5 + '7': [0x1F, 0x01, 0x02, 0x04, 0x08, 0x08, 0x08], # Width: 5 + '8': [0x0E, 0x11, 0x11, 0x0E, 0x11, 0x11, 0x0E], # Width: 5 + '9': [0x0E, 0x11, 0x11, 0x0F, 0x01, 0x02, 0x0C], # Width: 5 + # Punctuation and symbols - Optimized widths + ' ': [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], # Width: 2 + # '!': [0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x04], # Width: 1 + '!': [0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01], # Width: 1 + '?': [0x0E, 0x11, 0x02, 0x04, 0x04, 0x00, 0x04], # Width: 5 + '.': [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01], # Width: 1 + ',': [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02], # Width: 1 + ':': [0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00], # Width: 1 + ';': [0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x02], # Width: 1 + "'": [0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00], # Width: 1 + '"': [0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00], # Width: 3 + '-': [0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00], # Width: 5 + '_': [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F], # Width: 5 + '+': [0x00, 0x04, 0x04, 0x1F, 0x04, 0x04, 0x00], # Width: 5 + '=': [0x00, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x00], # Width: 5 + '*': [0x00, 0x0A, 0x04, 0x1F, 0x04, 0x0A, 0x00], # Width: 5 + '/': [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x00], # Width: 5 + '\\': [0x00, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00], # Width: 5 + '(': [0x01, 0x02, 0x04, 0x04, 0x04, 0x02, 0x01], # Width: 3 + ')': [0x04, 0x02, 0x01, 0x01, 0x01, 0x02, 0x04], # Width: 3 + '[': [0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07], # Width: 3 + ']': [0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07], # Width: 3 + '{': [0x03, 0x02, 0x02, 0x04, 0x02, 0x02, 0x03], # Width: 3 + '}': [0x06, 0x02, 0x02, 0x01, 0x02, 0x02, 0x06], # Width: 3 + '<': [0x00, 0x01, 0x02, 0x04, 0x02, 0x01, 0x00], # Width: 4 + '>': [0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x00], # Width: 4 + '@': [0x0E, 0x11, 0x17, 0x15, 0x17, 0x10, 0x0E], # Width: 5 + '#': [0x0A, 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x0A], # Width: 5 + '$': [0x04, 0x0F, 0x14, 0x0E, 0x05, 0x1E, 0x04], # Width: 5 + '%': [0x18, 0x19, 0x02, 0x04, 0x08, 0x13, 0x03], # Width: 5 + '&': [0x0C, 0x12, 0x14, 0x08, 0x15, 0x12, 0x0D], # Width: 5 + '^': [0x04, 0x0A, 0x11, 0x00, 0x00, 0x00, 0x00], # Width: 5 + '~': [0x00, 0x00, 0x00, 0x0D, 0x12, 0x00, 0x00], # Width: 5 # Special characters - '°': [0x0E, 0x0A, 0x0E, 0x00, 0x00, 0x00, 0x00], # Degree symbol - '|': [0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04], # Vertical bar - '`': [0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00], # Backtick - '¶': [0x1E, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A], # Paragraph symbol - '•': [0x00, 0x00, 0x04, 0x0E, 0x04, 0x00, 0x00], # Bullet point + '°': [0x07, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00], # Width: 3 (Degree symbol) + '|': [0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01], # Width: 1 (Vertical bar) + '`': [0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00], # Width: 2 (Backtick) + '¶': [0x0F, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D], # Width: 5 (Paragraph symbol) + '•': [0x00, 0x00, 0x02, 0x07, 0x02, 0x00, 0x00], # Width: 3 (Bullet point) } diff --git a/app/display/fonts/font_5x7_opt.py b/app/display/fonts/font_5x7_opt.py deleted file mode 100644 index 268abaa..0000000 --- a/app/display/fonts/font_5x7_opt.py +++ /dev/null @@ -1,237 +0,0 @@ -# fonts.py - Optimized fonts for LED matrix with character width adjustment - -# 5x7 Font (Optimized Width) -font_5x7 = { - # Uppercase letters (A-Z) - Optimized for better spacing - 'A': [0x0E, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11], # Width: 5 - 'B': [0x1E, 0x11, 0x11, 0x1E, 0x11, 0x11, 0x1E], # Width: 5 - 'C': [0x0E, 0x11, 0x10, 0x10, 0x10, 0x11, 0x0E], # Width: 5 - 'D': [0x1E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1E], # Width: 5 - 'E': [0x1F, 0x10, 0x10, 0x1E, 0x10, 0x10, 0x1F], # Width: 5 - 'F': [0x1F, 0x10, 0x10, 0x1E, 0x10, 0x10, 0x10], # Width: 5 - 'G': [0x0E, 0x11, 0x10, 0x13, 0x11, 0x11, 0x0F], # Width: 5 - 'H': [0x11, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11], # Width: 5 - # 'I': [0x0E, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E], # Width: 3 - 'I': [0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07], # Width: 3 - 'J': [0x07, 0x02, 0x02, 0x02, 0x02, 0x12, 0x0C], # Width: 4 - 'K': [0x11, 0x12, 0x14, 0x18, 0x14, 0x12, 0x11], # Width: 5 - 'L': [0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1F], # Width: 5 - 'M': [0x11, 0x1B, 0x15, 0x15, 0x11, 0x11, 0x11], # Width: 5 - 'N': [0x11, 0x19, 0x19, 0x15, 0x13, 0x13, 0x11], # Width: 5 - 'O': [0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E], # Width: 5 - 'P': [0x1E, 0x11, 0x11, 0x1E, 0x10, 0x10, 0x10], # Width: 5 - 'Q': [0x0E, 0x11, 0x11, 0x11, 0x15, 0x12, 0x0D], # Width: 5 - 'R': [0x1E, 0x11, 0x11, 0x1E, 0x14, 0x12, 0x11], # Width: 5 - 'S': [0x0F, 0x10, 0x10, 0x0E, 0x01, 0x01, 0x1E], # Width: 5 - 'T': [0x1F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04], # Width: 5 - 'U': [0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E], # Width: 5 - 'V': [0x11, 0x11, 0x11, 0x11, 0x11, 0x0A, 0x04], # Width: 5 - 'W': [0x11, 0x11, 0x11, 0x15, 0x15, 0x15, 0x0A], # Width: 5 - 'X': [0x11, 0x11, 0x0A, 0x04, 0x0A, 0x11, 0x11], # Width: 5 - 'Y': [0x11, 0x11, 0x0A, 0x04, 0x04, 0x04, 0x04], # Width: 5 - 'Z': [0x1F, 0x01, 0x02, 0x04, 0x08, 0x10, 0x1F], # Width: 5 - # Lowercase letters (a-z) - Optimized for compact display - 'a': [0x00, 0x00, 0x0E, 0x01, 0x0F, 0x11, 0x0F], # Width: 4 - 'b': [0x10, 0x10, 0x16, 0x19, 0x11, 0x11, 0x1E], # Width: 5 - 'c': [0x00, 0x00, 0x0E, 0x11, 0x10, 0x11, 0x0E], # Width: 4 - 'd': [0x01, 0x01, 0x0D, 0x13, 0x11, 0x11, 0x0F], # Width: 5 - 'e': [0x00, 0x00, 0x0E, 0x11, 0x1F, 0x10, 0x0E], # Width: 4 - 'f': [0x06, 0x09, 0x08, 0x1C, 0x08, 0x08, 0x08], # Width: 4 - 'g': [0x00, 0x0F, 0x11, 0x11, 0x0F, 0x01, 0x0E], # Width: 5 - 'h': [0x10, 0x10, 0x16, 0x19, 0x11, 0x11, 0x11], # Width: 5 - # 'i': [0x00, 0x04, 0x00, 0x0C, 0x04, 0x04, 0x0E], # Width: 2 - 'i': [0x00, 0x02, 0x00, 0x06, 0x02, 0x02, 0x07], # Width: 2 - 'j': [0x00, 0x02, 0x00, 0x06, 0x02, 0x12, 0x0C], # Width: 3 - 'k': [0x10, 0x10, 0x12, 0x14, 0x18, 0x14, 0x12], # Width: 4 - # 'l': [0x0C, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E], # Width: 3 - 'l': [0x06, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07], # Width: 3 - 'm': [0x00, 0x00, 0x1A, 0x15, 0x15, 0x15, 0x15], # Width: 5 - 'n': [0x00, 0x00, 0x16, 0x19, 0x11, 0x11, 0x11], # Width: 5 - 'o': [0x00, 0x00, 0x0E, 0x11, 0x11, 0x11, 0x0E], # Width: 4 - 'p': [0x00, 0x00, 0x1E, 0x11, 0x1E, 0x10, 0x10], # Width: 5 - 'q': [0x00, 0x00, 0x0D, 0x13, 0x0F, 0x01, 0x01], # Width: 5 - 'r': [0x00, 0x00, 0x16, 0x19, 0x10, 0x10, 0x10], # Width: 5 - 's': [0x00, 0x00, 0x0E, 0x10, 0x0E, 0x01, 0x1E], # Width: 4 - 't': [0x08, 0x08, 0x1C, 0x08, 0x08, 0x09, 0x06], # Width: 4 - 'u': [0x00, 0x00, 0x11, 0x11, 0x11, 0x13, 0x0D], # Width: 5 - 'v': [0x00, 0x00, 0x11, 0x11, 0x11, 0x0A, 0x04], # Width: 5 - 'w': [0x00, 0x00, 0x11, 0x11, 0x15, 0x15, 0x0A], # Width: 5 - 'x': [0x00, 0x00, 0x11, 0x0A, 0x04, 0x0A, 0x11], # Width: 5 - 'y': [0x00, 0x00, 0x11, 0x11, 0x0F, 0x01, 0x0E], # Width: 5 - 'z': [0x00, 0x00, 0x1F, 0x02, 0x04, 0x08, 0x1F], # Width: 5 - # Numbers (0-9) - Optimized for consistent width - '0': [0x0E, 0x11, 0x13, 0x15, 0x19, 0x11, 0x0E], # Width: 5 - '1': [0x02, 0x06, 0x02, 0x02, 0x02, 0x02, 0x07], # Width: 3 - # '1': [0x04, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x0E], # Width: 3 - # '1': [0x08, 0x18, 0x08, 0x08, 0x08, 0x08, 0x1C], # Width: 3 - '2': [0x0E, 0x11, 0x01, 0x02, 0x04, 0x08, 0x1F], # Width: 5 - '3': [0x1F, 0x02, 0x04, 0x02, 0x01, 0x11, 0x0E], # Width: 5 - '4': [0x02, 0x06, 0x0A, 0x12, 0x1F, 0x02, 0x02], # Width: 5 - '5': [0x1F, 0x10, 0x1E, 0x01, 0x01, 0x11, 0x0E], # Width: 5 - '6': [0x06, 0x08, 0x10, 0x1E, 0x11, 0x11, 0x0E], # Width: 5 - '7': [0x1F, 0x01, 0x02, 0x04, 0x08, 0x08, 0x08], # Width: 5 - '8': [0x0E, 0x11, 0x11, 0x0E, 0x11, 0x11, 0x0E], # Width: 5 - '9': [0x0E, 0x11, 0x11, 0x0F, 0x01, 0x02, 0x0C], # Width: 5 - # Punctuation and symbols - Optimized widths - ' ': [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], # Width: 2 - # '!': [0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x04], # Width: 1 - '!': [0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01], # Width: 1 - '?': [0x0E, 0x11, 0x02, 0x04, 0x04, 0x00, 0x04], # Width: 5 - '.': [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01], # Width: 1 - ',': [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02], # Width: 1 - ':': [0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00], # Width: 1 - ';': [0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x02], # Width: 1 - "'": [0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00], # Width: 1 - '"': [0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00], # Width: 3 - '-': [0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00], # Width: 5 - '_': [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F], # Width: 5 - '+': [0x00, 0x04, 0x04, 0x1F, 0x04, 0x04, 0x00], # Width: 5 - '=': [0x00, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x00], # Width: 5 - '*': [0x00, 0x0A, 0x04, 0x1F, 0x04, 0x0A, 0x00], # Width: 5 - '/': [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x00], # Width: 5 - '\\': [0x00, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00], # Width: 5 - '(': [0x01, 0x02, 0x04, 0x04, 0x04, 0x02, 0x01], # Width: 3 - ')': [0x04, 0x02, 0x01, 0x01, 0x01, 0x02, 0x04], # Width: 3 - '[': [0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07], # Width: 3 - ']': [0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07], # Width: 3 - '{': [0x03, 0x02, 0x02, 0x04, 0x02, 0x02, 0x03], # Width: 3 - '}': [0x06, 0x02, 0x02, 0x01, 0x02, 0x02, 0x06], # Width: 3 - '<': [0x00, 0x01, 0x02, 0x04, 0x02, 0x01, 0x00], # Width: 4 - '>': [0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x00], # Width: 4 - '@': [0x0E, 0x11, 0x17, 0x15, 0x17, 0x10, 0x0E], # Width: 5 - '#': [0x0A, 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x0A], # Width: 5 - '$': [0x04, 0x0F, 0x14, 0x0E, 0x05, 0x1E, 0x04], # Width: 5 - '%': [0x18, 0x19, 0x02, 0x04, 0x08, 0x13, 0x03], # Width: 5 - '&': [0x0C, 0x12, 0x14, 0x08, 0x15, 0x12, 0x0D], # Width: 5 - '^': [0x04, 0x0A, 0x11, 0x00, 0x00, 0x00, 0x00], # Width: 5 - '~': [0x00, 0x00, 0x00, 0x0D, 0x12, 0x00, 0x00], # Width: 5 - # Special characters - '°': [0x07, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00], # Width: 3 (Degree symbol) - '|': [0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01], # Width: 1 (Vertical bar) - '`': [0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00], # Width: 2 (Backtick) - '¶': [0x0F, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D], # Width: 5 (Paragraph symbol) - '•': [0x00, 0x00, 0x02, 0x07, 0x02, 0x00, 0x00], # Width: 3 (Bullet point) -} - -# Character width mapping for optimized spacing -char_width = { - # Wide characters (5 pixels) - 'A': 5, - 'B': 5, - 'C': 5, - 'D': 5, - 'E': 5, - 'F': 5, - 'G': 5, - 'H': 5, - 'K': 5, - 'L': 5, - 'M': 5, - 'N': 5, - 'O': 5, - 'P': 5, - 'Q': 5, - 'R': 5, - 'S': 5, - 'T': 5, - 'U': 5, - 'V': 5, - 'W': 5, - 'X': 5, - 'Y': 5, - 'Z': 5, - 'b': 5, - 'd': 5, - 'g': 5, - 'h': 5, - 'm': 5, - 'n': 5, - 'p': 5, - 'q': 5, - 'u': 5, - 'v': 5, - 'w': 5, - 'x': 5, - 'y': 5, - 'z': 5, - '0': 5, - '2': 5, - '3': 5, - '4': 5, - '5': 5, - '6': 5, - '7': 5, - '8': 5, - '9': 5, - '?': 5, - '-': 5, - '_': 5, - '+': 5, - '=': 5, - '*': 5, - '/': 5, - '\\': 5, - '@': 5, - '#': 5, - '$': 5, - '%': 5, - '&': 5, - '^': 5, - '~': 5, - '¶': 4, - # Medium characters (4 pixels) - 'J': 5, - 'a': 5, - 'c': 5, - 'e': 5, - 'f': 5, - 'k': 5, - 'o': 5, - 's': 5, - 't': 5, - '<': 4, - '>': 4, - # Narrow characters (3 pixels) - 'I': 3, - '1': 3, - 'l': 3, - 'j': 4, - '(': 3, - ')': 3, - '[': 3, - ']': 3, - '{': 3, - '}': 3, - '°': 3, - '•': 3, - # Very narrow characters (2 pixels) - 'i': 3, - ' ': 1, - '`': 2, - # Single pixel characters - '!': 1, - '.': 1, - ',': 2, - ':': 1, - ';': 2, - "'": 1, - '|': 1, - # Special cases - '"': 3, -} - - -def get_char_width(char, default_witdth=5): - """Get the display width of a character for proper spacing""" - return char_width.get(char, default_witdth) # Default to 5 if character not found - - -def get_text_width(text): - """Calculate total width of text including character spacing""" - width = 0 - for char in text: - if char in char_width: - width += char_width[char] + 1 # +1 for spacing between characters - else: - width += 6 # Default width + spacing - return max(0, width - 1) # Remove last spacing diff --git a/app/display/fonts/fonts_utils.py b/app/display/fonts/fonts_utils.py index 338f342..d8a8879 100644 --- a/app/display/fonts/fonts_utils.py +++ b/app/display/fonts/fonts_utils.py @@ -1,40 +1,4 @@ -from .font_3x5 import font_3x5 -from .font_5x7 import font_5x7 -from .font_5x7_opt import font_5x7 as font_5x7_opt -from .font_8x8 import font_8x8 -from .font_16x16 import font_16x16 -from ..emoji.emoji_5x7 import emoji_5x7 -from ..emoji.emoji_8x8 import emoji_8x8 -from ..emoji.emoji_16x16 import emoji_16x16 -from ...utils.utils import number_to_bitarray_msb - -fonts_meta_ = { - 3: {'w': 3, 'h': 5}, - 5: {'w': 5, 'h': 7}, - 8: {'w': 8, 'h': 8}, - 16: {'w': 16, 'h': 16}, -} - - -def fonts_meta(font): - if font == font_3x5: - return fonts_meta_[3] - elif font == font_5x7: - return fonts_meta_[5] - elif font == font_5x7_opt: - return fonts_meta_[5] - elif font == font_8x8: - return fonts_meta_[8] - elif font == font_16x16: - return fonts_meta_[16] - elif font == emoji_5x7: - return fonts_meta_[5] - elif font == emoji_8x8: - return fonts_meta_[8] - elif font == emoji_16x16: - return fonts_meta_[16] - else: - return None +import app.utils.utils as utils def char_width(char_matrix) -> int: @@ -56,3 +20,66 @@ def char_width(char_matrix) -> int: cw += 1 return cw + + +def shift_letter_right(char, letter, debug=False) -> bool: + """Prüfe ob das Zeichen auch komplett nach rechts gezogen ist + + Args: + letter (_type_): Array[0..nBytes] + + Returns: + bool: _description_ + """ + + def isLetterRight(letter): + def isByteRight(byte): + return True if 1 & byte == 1 else False + + for byte in letter: + if isByteRight(byte): + return True + + return False + + 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 + + return shifted + + if isLetterRight(letter): + return letter + + # letter is not right shifted + shifted = shiftLetterRight(letter) + + if debug: + print('origin:') + utils.show_byte_matrix(char, letter) + print('shifted') + utils.show_byte_matrix(char, shifted) + + return shifted + + +def align_font(font): + 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]) + 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)}' diff --git a/app/display/neopixel_64x64.py b/app/display/neopixel_64x64.py index 0742201..d71661d 100644 --- a/app/display/neopixel_64x64.py +++ b/app/display/neopixel_64x64.py @@ -1,9 +1,8 @@ from machine import Pin, RTC from neopixel import NeoPixel -from .fonts.fonts_utils import fonts_meta, char_width as charwidth +from .fonts.fonts_utils import char_width as charwidth from .fonts.font_5x7 import font_5x7 -from .fonts.font_5x7_opt import font_5x7 as font_5x7_opt, get_char_width from ..utils.colors import GRAY, RAINBOW, BLACK, WHITE, LIME from ..utils.utils import ( get_german_timestamp_short, @@ -32,7 +31,7 @@ class NeoPixel_64x64(NeoPixel): super().__init__(Pin(pin), self.MATRIX_WIDTH * self.MATRIX_HEIGHT) # Font configuration - self.set_font(font_5x7_opt) + self.set_font(font_5x7) def set_font(self, font): """ @@ -43,10 +42,10 @@ class NeoPixel_64x64(NeoPixel): """ self.selected_font = font - self.selected_font_meta = fonts_meta(font) - self.font_width = self.selected_font_meta['w'] - self.font_height = self.selected_font_meta['h'] - print(f'Font set: width: {self.font_width}; height: {self.font_height}') + # Höhe des Fonts, Anzahl der Zeilen für jedes Zeichen + # wir holen den Wert aus "A" + self.font_height = len(self.selected_font['A']) + print(f'Font set: width: per char; height: {self.font_height}') def set_pixel(self, x, y, color): """ @@ -92,27 +91,6 @@ class NeoPixel_64x64(NeoPixel): self.write() - def draw_letter___obsolet(self, letter, x, y, color): - """ - Draw a single letter using current font - - Args: - letter: Character to draw - x: X position - y: Y position - color: RGB color tuple - """ - if letter in self.selected_font: - char_data = self.selected_font[letter] - for row in range(self.font_height): - row_data = char_data[row] - for col in range(self.font_width): - # Check if pixel should be lit (MSB first) - if row_data & (1 << ((self.font_width - 1) - col)): - self.set_pixel(x + col, y + row, color) - else: - print(f'oops, letter does not exist in the font -> {letter}') - def draw_letter(self, letter, x, y, color): """ Draw a single letter using current font with optimized width @@ -126,7 +104,6 @@ class NeoPixel_64x64(NeoPixel): if letter in self.selected_font: char_data = self.selected_font[letter] - # char_width = get_char_width(letter, default_witdth=16) char_width = charwidth(char_data) # background for the letter (full font size) @@ -150,21 +127,6 @@ class NeoPixel_64x64(NeoPixel): else: print(f'oops, letter does not exist in the font -> {letter}') - def draw_text___obsolete(self, text, x, y, color=RAINBOW[2], spacing=1): - """ - Draw text string at specified position - - Args: - text: String to display - x: Starting X position - y: Starting Y position - color: RGB color tuple - spacing: Pixels between characters - """ - for idx, char in enumerate(text): - char_x = x + (idx * (self.font_width + spacing)) - self.draw_letter(char, char_x, y, color) - def draw_text(self, text, x, y, color): """ Draw text with optimized character spacing @@ -179,7 +141,7 @@ class NeoPixel_64x64(NeoPixel): for char in text: self.draw_letter(char, current_x, y, color) # Move cursor by character width + 1 pixel spacing - char_width = get_char_width(char) + char_width = charwidth(self.selected_font[char]) current_x += char_width + 1 def show_hello(self): @@ -243,7 +205,6 @@ class NeoPixel_64x64(NeoPixel): duration: How long to run animation in seconds """ start_time = time.time() - text_width = len(text) * (self.font_width + 1) counter = 0 while time.time() - start_time < duration: @@ -255,9 +216,10 @@ class NeoPixel_64x64(NeoPixel): # Draw text at floating position for i, char in enumerate(text): - char_x = current_x + (i * (self.font_width + 1)) + char_width = charwidth(self.selected_font[char]) + char_x = current_x + (i * (char_width + 1)) # Keep text within matrix bounds - if 0 <= char_x < self.MATRIX_WIDTH - self.font_width: + if 0 <= char_x < self.MATRIX_WIDTH - char_width: self.draw_letter(char, char_x, y, color) self.write() @@ -276,7 +238,12 @@ class NeoPixel_64x64(NeoPixel): duration: How long to run animation in seconds """ start_time = time.time() - text_width = len(text) * (self.font_width + 1) + # hier müssen wir die Länge/Breite in Pixel des gesamten Textes berechnen + # text_width_overall = len(text) * (self.font_width + 1) + ### TODO: ACHTUNG: noch zu testen !!! + # Breite jedes Zeichens + text_width_overall = sum([charwidth(self.selected_font[char]) for char in text]) + position = 0 while time.time() - start_time < duration: @@ -284,10 +251,11 @@ class NeoPixel_64x64(NeoPixel): # Draw text at current position for i, char in enumerate(text): - char_x = int(position + (i * (self.font_width + 1))) + char_width = charwidth(self.selected_font[char]) + char_x = int(position + (i * (char_width + 1))) # Handle wrapping - if char_x < -self.font_width: - char_x += self.MATRIX_WIDTH + text_width + if char_x < -char_width: + char_x += self.MATRIX_WIDTH + text_width_overall if 0 <= char_x < self.MATRIX_WIDTH: self.draw_letter(char, char_x, y, color) @@ -295,7 +263,7 @@ class NeoPixel_64x64(NeoPixel): # Move left and wrap around position -= speed - if position < -text_width: + if position < -text_width_overall: position = self.MATRIX_WIDTH time.sleep(0.05) diff --git a/app/utils/utils.py b/app/utils/utils.py index 24738b9..05f7da4 100644 --- a/app/utils/utils.py +++ b/app/utils/utils.py @@ -12,52 +12,6 @@ def number_to_bitarray_msb(number, bits=8): return [(number >> i) & 1 for i in range(bits - 1, -1, -1)] -def is_letter_assigned_right(char, letter) -> bool: - """Prüfe ob das Zeichen auch komplett nach rechts gezogen ist - - Args: - letter (_type_): Array[0..nBytes] - - Returns: - bool: _description_ - """ - - def isLetterRight(letter): - def isByteRight(byte): - return True if 1 & byte == 1 else False - - for byte in letter: - if isByteRight(byte): - return True - - return False - - 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 - - return shifted - - if isLetterRight(letter): - return True - - # letter is not right shifted - shifted = shiftLetterRight(letter) - - print('origin:') - show_byte_matrix(char, letter) - print('shifted') - show_byte_matrix(char, shifted) - - return False - - def get_datetime_string(format='full'): """ Return date/time as string with different formats diff --git a/main.py b/main.py index 56f8068..b233444 100644 --- a/main.py +++ b/main.py @@ -1,9 +1,12 @@ # from machine import Pin, ADC # type: ignore -from app.display.fonts.font_5x7_opt import font_5x7 +from app.display.fonts.font_3x5 import font_3x5 +from app.display.fonts.font_5x7 import font_5x7 +from app.display.fonts.fonts_utils import align_font from app.display.neopixel_64x64 import NeoPixel_64x64 from app.utils.colors import BLUE, GREEN, ORANGE, RAINBOW, RED, WHITE, YELLOW, GOLD from app.utils.system_load import show_system_load import app.utils.utils as utils +import app.display.fonts.fonts_utils as fonts_utils from app.web.wlan import Wlan @@ -29,7 +32,7 @@ def emoji_test(): # display.write_text('💛', 28, 47) char_row = '😀' - utils.is_letter_assigned_right(char_row, emoji_8x8[char_row]) + fonts_utils.shift_letter_right(char_row, emoji_8x8[char_row]) # try emoji display.set_font(emoji_16x16) @@ -40,32 +43,25 @@ def weather_check(test_mode: bool = False): wlan = Wlan('WOKWI-Guest', '12345678') try: - display = NeoPixel_64x64() display.clear() - display.draw_text('search wlan', 0, 0, color=YELLOW) - display.write() + display.write_text('search wlan', 0, 0, color=YELLOW) display.clear_row(0, effect=False) - # display.clear() - display.draw_text('wlan connected', 0, 0, color=RAINBOW[1]) - display.draw_text('querying', 0, 8, color=RAINBOW[1]) - display.draw_text('weather data', 0, 16, color=RAINBOW[1]) - display.write() + display.clear() + display.set_font(font_3x5) + display.write_text('wlan connected', 0, 0, color=RAINBOW[1]) + display.write_text('querying', 0, 8, color=RAINBOW[1]) + display.write_text('weather data', 0, 16, color=RAINBOW[1]) w_resp = wlan.actual_weather(lang='en', test_mode=test_mode) display.clear() - # display.draw_text(f'{str(w_resp.location.name)}', 0, 0, color=RAINBOW[0]) - # display.draw_text(f'{str(w_resp.current.temp_c)}°C', 0, 8, color=RAINBOW[1]) - # display.draw_text(f'upd: {str(w_resp.current.last_updated)[-5:]}', 0, 16, color=RAINBOW[2]) - # display.draw_text(f'cur: {str(w_resp.location.localtime)[-5:]}', 0, 24, color=RAINBOW[3]) - # display.write() - delta = 8 ypos = 0 - display.write_text(f'{str(w_resp.location.name)}', 0, ypos, color=RAINBOW[0]) + display.write_text(f'{str(w_resp.location.name).upper()}', 0, ypos, color=RAINBOW[0]) + display.set_font(font_5x7) ypos += delta display.write_text(f'{str(w_resp.current.temp_c)}°C', 0, ypos, color=RAINBOW[1]) ypos += delta @@ -86,28 +82,48 @@ def weather_check(test_mode: bool = False): print('finally done.') -def font_5x7_test() -> None: +def font_test(font) -> None: + display.set_font(font) + alphabet: str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' char_line_1 = alphabet[:11] char_line_2 = alphabet[11:22] char_line_3 = alphabet[21:] num_line = '0123456789' - display.write_text(num_line, 0, 0) - display.write_text(char_line_1.lower(), 0, 1, YELLOW) - display.write_text(char_line_2.lower(), 0, 2, YELLOW) - display.write_text(char_line_3.lower(), 0, 3, YELLOW) - display.write_text(' !?.,:;\'"-_+=*/\\()', 0, 4, ORANGE) + row = 0 + incr = 6 + display.write_text(num_line, 0, row) + row += incr + display.write_text(char_line_1.upper(), 0, row, YELLOW) + row += incr + display.write_text(char_line_2.upper(), 0, row, YELLOW) + row += incr + display.write_text(char_line_3.upper(), 0, row, YELLOW) + row += incr + display.write_text(char_line_1.lower(), 0, row, YELLOW) + row += incr + display.write_text(char_line_2.lower(), 0, row, YELLOW) + row += incr + display.write_text(char_line_3.lower(), 0, row, YELLOW) + row += incr * 2 + display.write_text('!.,:;\'"-_+=*/\\()~°•', 0, row, ORANGE) + + +def font_pretty(font): + pretty_font = align_font(font) + print(pretty_font) def bit_arrays(): + display.set_font(font_3x5) # c = 'A' # print(c) # [print(utils.number_to_bitarray_msb(num)) for num in font_5x7[c]] char_row = '1' [display.write_text(c, 0, idx, YELLOW) for idx, c in enumerate(char_row)] - utils.is_letter_assigned_right(char_row, font_5x7[char_row]) + fonts_utils.shift_letter_right(char_row, font_5x7[char_row]) # display.write_text(char_row, 0, len(char_row), ORANGE) # display.write_text('Kiel', 0, 7, BLUE) @@ -123,7 +139,8 @@ def bit_arrays(): if __name__ == '__main__': # emoji_test() - weather_check(test_mode=False) - # font_5x7_test() + # font_test(font_3x5) # bit_arrays() # show_system_load() + # font_pretty(font_3x5) + weather_check(test_mode=True)