v.0.3.0 calculate char_width with shift operator

This commit is contained in:
tiijay
2025-10-23 14:31:09 +02:00
parent 2eea871408
commit a66b00989f
8 changed files with 377 additions and 182 deletions

View File

@@ -1,7 +1,7 @@
# Emoji symbols for LED matrix (16x16)
emoji_16x16 = {
# Basic Smileys
'😀': [
# === SMILEYS & EMOTIONS ===
'😀': [ # Grinning Face
0x07E0,
0x1FF8,
0x3FFC,
@@ -18,8 +18,8 @@ emoji_16x16 = {
0x1FF8,
0x07E0,
0x0000,
], # Grinning face (circle outline)
'😊': [
],
'😊': [ # Smiling Face with Smiling Eyes
0x07E0,
0x1FF8,
0x3FFC,
@@ -36,8 +36,8 @@ emoji_16x16 = {
0x3FFC,
0x1FF8,
0x07E0,
], # Smiling face
'😂': [
],
'😂': [ # Face with Tears of Joy
0x07E0,
0x1FF8,
0x3FFC,
@@ -54,8 +54,8 @@ emoji_16x16 = {
0x3FFC,
0x1FF8,
0x07E0,
], # Laughing with tears
'😍': [
],
'😍': [ # Smiling Face with Heart-Eyes
0x07E0,
0x1FF8,
0x3FFC,
@@ -72,8 +72,8 @@ emoji_16x16 = {
0x3FFC,
0x1FF8,
0x07E0,
], # Heart eyes
'😎': [
],
'😎': [ # Smiling Face with Sunglasses
0x07E0,
0x1FF8,
0x3FFC,
@@ -90,9 +90,45 @@ emoji_16x16 = {
0x3FFC,
0x1FF8,
0x07E0,
], # Cool sunglasses
# Hearts
'❤️': [
],
'😢': [ # Crying Face
0x07E0,
0x1FF8,
0x3FFC,
0x7FFE,
0x7C3E,
0xF81F,
0xF00F,
0xF3CF,
0xF3CF,
0xF00F,
0xF99F,
0x7C3E,
0x7FFE,
0x3FFC,
0x1FF8,
0x07E0,
],
'😠': [ # Angry Face
0x07E0,
0x1FF8,
0x3FFC,
0x7FFE,
0x7C3E,
0xF81F,
0xF3CF,
0xE667,
0xE667,
0xF3CF,
0xF81F,
0x7C3E,
0x7FFE,
0x3FFC,
0x1FF8,
0x07E0,
],
# === HEARTS ===
'❤️': [ # Red Heart
0x0000,
0x0000,
0x0C30,
@@ -109,9 +145,27 @@ emoji_16x16 = {
0x0F80,
0x0700,
0x0000,
], # Red heart
# Weather & Nature
'☀️': [
],
'💙': [ # Blue Heart
0x0000,
0x0000,
0x0C30,
0x1E78,
0x3FFC,
0x7FFE,
0x7FFE,
0xFFFE,
0xFFFC,
0x7FF8,
0x7FF0,
0x3FE0,
0x1FC0,
0x0F80,
0x0700,
0x0000,
],
# === WEATHER & NATURE ===
'☀️': [ # Sun
0x8001,
0x4002,
0x2004,
@@ -128,8 +182,8 @@ emoji_16x16 = {
0x2004,
0x4002,
0x8001,
], # Sun with detailed rays
'🌙': [
],
'🌙': [ # Crescent Moon
0x0000,
0x1F80,
0x3FC0,
@@ -146,8 +200,8 @@ emoji_16x16 = {
0xFC00,
0xF800,
0x0000,
], # Crescent moon
'': [
],
'': [ # Star
0x0180,
0x0180,
0x03C0,
@@ -164,9 +218,27 @@ emoji_16x16 = {
0x03C0,
0x0180,
0x0180,
], # Star
# Objects
'📱': [
],
'☁️': [ # Cloud
0x0000,
0x0000,
0x0F00,
0x1F80,
0x3FC0,
0x7FE0,
0x7FE0,
0xFFF0,
0xFFF0,
0xFFF0,
0x7FE0,
0x7FE0,
0x3FC0,
0x1F80,
0x0F00,
0x0000,
],
# === TECHNOLOGY ===
'📱': [ # Mobile Phone
0xFFFF,
0x8001,
0x8001,
@@ -183,8 +255,8 @@ emoji_16x16 = {
0x8001,
0x8001,
0xFFFF,
], # Smartphone
'💻': [
],
'💻': [ # Laptop
0x0000,
0x7FFE,
0x4002,
@@ -201,65 +273,8 @@ emoji_16x16 = {
0x3FFC,
0x1FF8,
0x0000,
], # Laptop
# Animals
'🐱': [
0x07E0,
0x1FF8,
0x3FFC,
0x7FFE,
0x7FFE,
0x6FF6,
0x6FF6,
0x6FF6,
0x6FF6,
0x6FF6,
0x7FFE,
0x7FFE,
0x3FFC,
0x1FF8,
0x07E0,
0x0000,
], # Cat face
'🐶': [
0x07E0,
0x1FF8,
0x3FFC,
0x7FFE,
0x7FFE,
0x6FF6,
0x6FF6,
0x6FF6,
0x6FF6,
0x6FF6,
0x7FFE,
0x7FFE,
0x3FFC,
0x1FF8,
0x07E0,
0x0000,
], # Dog face
# Food
'🍕': [
0x07E0,
0x1FF8,
0x3FFC,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x3FFC,
0x1FF8,
0x07E0,
0x0000,
], # Pizza
# Technology
'🔒': [
],
'🔒': [ # Lock
0x0FC0,
0x1FE0,
0x3FF0,
@@ -276,28 +291,82 @@ emoji_16x16 = {
0x3FF0,
0x3FF0,
0x3FF0,
], # Lock
# Vehicles
'🚗': [
],
'🔑': [ # Key
0x0000,
0x0000,
0x0FC0,
0x1FE0,
0x3FF0,
0x3FF0,
0x3FF0,
0x3FF0,
0x3FF0,
0x3FF0,
0x3FF0,
0x3FF0,
0x1FE0,
0x0FC0,
0x0F00,
0x1F80,
0x3FC0,
0x3FC0,
0x3FC0,
0x3FC0,
0x3FC0,
0x3FC0,
0x3FC0,
0x3FC0,
0x3FC0,
0x3FC0,
0x3FC0,
0x3FC0,
],
# === ANIMALS ===
'🐱': [ # Cat Face
0x07E0,
0x1FF8,
0x3FFC,
0x7FFE,
0x7FFE,
0x6FF6,
0x6FF6,
0x6FF6,
0x6FF6,
0x6FF6,
0x7FFE,
0x7FFE,
0x3FFC,
0x1FF8,
0x07E0,
0x0000,
],
'🐶': [ # Dog Face
0x07E0,
0x1FF8,
0x3FFC,
0x7FFE,
0x7FFE,
0x6FF6,
0x6FF6,
0x6FF6,
0x6FF6,
0x6FF6,
0x7FFE,
0x7FFE,
0x3FFC,
0x1FF8,
0x07E0,
0x0000,
],
'🐦': [ # Bird
0x0000,
0x0000,
], # Car
# Sports
'': [
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
],
# === FOOD ===
'🍕': [ # Pizza
0x07E0,
0x1FF8,
0x3FFC,
@@ -314,9 +383,101 @@ emoji_16x16 = {
0x1FF8,
0x07E0,
0x0000,
], # Soccer ball
# Holidays
'🎄': [
],
'🍎': [ # Red Apple
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
],
# === VEHICLES ===
'🚗': [ # Car
0x0000,
0x0000,
0x0FC0,
0x1FE0,
0x3FF0,
0x3FF0,
0x3FF0,
0x3FF0,
0x3FF0,
0x3FF0,
0x3FF0,
0x3FF0,
0x1FE0,
0x0FC0,
0x0000,
0x0000,
],
'✈️': [ # Airplane
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
0x0000,
],
# === SPORTS ===
'': [ # Soccer Ball
0x07E0,
0x1FF8,
0x3FFC,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x3FFC,
0x1FF8,
0x07E0,
0x0000,
],
'🏀': [ # Basketball
0x07E0,
0x1FF8,
0x3FFC,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x3FFC,
0x1FF8,
0x07E0,
0x0000,
],
# === HOLIDAYS ===
'🎄': [ # Christmas Tree
0x0180,
0x03C0,
0x03C0,
@@ -333,5 +494,23 @@ emoji_16x16 = {
0x03C0,
0x03C0,
0x03C0,
], # Christmas tree
],
'🎃': [ # Jack-O-Lantern
0x07E0,
0x1FF8,
0x3FFC,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x7FFE,
0x3FFC,
0x1FF8,
0x07E0,
0x0000,
],
}

View File

@@ -221,9 +221,9 @@ char_width = {
}
def get_char_width(char):
def get_char_width(char, default_witdth=5):
"""Get the display width of a character for proper spacing"""
return char_width.get(char, 5) # Default to 5 if character not found
return char_width.get(char, default_witdth) # Default to 5 if character not found
def get_text_width(text):

View File

@@ -6,6 +6,7 @@ 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},
@@ -34,3 +35,24 @@ def fonts_meta(font):
return fonts_meta_[16]
else:
return None
def char_width(char_matrix) -> int:
"""Berechnung der Bits für die Zeichenbreite
Args:
char_matrix (int): Zeichen als Array[int]
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
return cw

View File

@@ -1,6 +1,6 @@
from machine import Pin, RTC
from neopixel import NeoPixel
from .fonts.fonts_utils import fonts_meta
from .fonts.fonts_utils import fonts_meta, 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
@@ -124,18 +124,21 @@ class NeoPixel_64x64(NeoPixel):
color: RGB color tuple
"""
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)
[
# print(xpos, ypos)
self.set_pixel(xpos, ypos, GRAY)
for xpos in range(x, x + 8) # 8 because full with of character representation
for xpos in range(
x, x + char_width
) # 8 because full with of character representation
for ypos in range(y, y + self.font_height)
]
if letter in self.selected_font:
char_data = self.selected_font[letter]
char_width = get_char_width(letter)
for row in range(self.font_height):
row_data = char_data[row]

View File

@@ -7,9 +7,9 @@ def show_byte_matrix(char, matrix):
[print(f'{matrix_str[idx]} {number_to_bitarray_msb(byte)}') for idx, byte in enumerate(matrix)]
def number_to_bitarray_msb(number):
"""Convert 8-bit number to bit array (MSB first)"""
return [(number >> i) & 1 for i in range(7, -1, -1)]
def number_to_bitarray_msb(number, bits=8):
"""Convert 8/16-bit number to bit array (MSB first)"""
return [(number >> i) & 1 for i in range(bits - 1, -1, -1)]
def is_letter_assigned_right(char, letter) -> bool:

35
main.py
View File

@@ -17,28 +17,23 @@ display = NeoPixel_64x64()
def emoji_test():
display.clear()
# display.set_font(font_8x8)
# display.show_hello()
# display.rotate_text_left_continuous('FLOATING TEXT', 0, speed=8.0, duration=30)
display.set_font(font_16x16)
display.draw_text('ABCD', 1, 1, color=GOLD)
# try emoji
display.set_font(emoji_8x8)
display.draw_text('😀', 1, 20, color=GREEN)
display.draw_text('', 1, 29)
display.draw_text('', 1, 38)
display.draw_text('😎', 1, 47, color=RED)
display.draw_text('💙', 10, 47)
display.draw_text('💚', 19, 47)
display.draw_text('💛', 28, 47)
display.write_text('😀', 0, 0, color=GREEN)
display.write_text('😂', 0, 29)
# display.write_text('✅', 0, 38)
# display.write_text('😎', 0, 47, color=RED)
# display.write_text('💙', 10, 47)
# display.write_text('💚', 19, 47)
# display.write_text('💛', 28, 47)
char_row = '😀'
utils.is_letter_assigned_right(char_row, emoji_8x8[char_row])
# try emoji
# display.set_font(emoji_16x16)
# display.draw_text('😀', 10, 20, color=ORANGE)
display.write()
display.set_font(emoji_16x16)
display.write_text('🌙', 0, 10, color=ORANGE)
def weather_check(test_mode: bool = False):
@@ -58,7 +53,7 @@ def weather_check(test_mode: bool = False):
display.draw_text('weather data', 0, 16, color=RAINBOW[1])
display.write()
w_resp = wlan.actual_weather(test_mode=test_mode)
w_resp = wlan.actual_weather(lang='en', test_mode=test_mode)
display.clear()
@@ -106,10 +101,6 @@ def font_5x7_test() -> None:
def bit_arrays():
# def number_to_bitarray_msb(number):
# """Convert 8-bit number to bit array (MSB first)"""
# return [(number >> i) & 1 for i in range(7, -1, -1)]
# c = 'A'
# print(c)
# [print(utils.number_to_bitarray_msb(num)) for num in font_5x7[c]]

View File

@@ -6,50 +6,50 @@
"lat": 53.6667,
"lon": 10.2833,
"tz_id": "Europe/Berlin",
"localtime_epoch": 1760977041,
"localtime": "2025-10-20 18:17"
"localtime_epoch": 1761209139,
"localtime": "2025-10-23 10:45"
},
"current": {
"last_updated_epoch": 1760976900,
"last_updated": "2025-10-20 18:15",
"temp_c": 12.3,
"temp_f": 54.1,
"is_day": 0,
"last_updated_epoch": 1761209100,
"last_updated": "2025-10-23 10:45",
"temp_c": 12.4,
"temp_f": 54.3,
"is_day": 1,
"condition": {
"text": "leichter Regenfall",
"icon": "//cdn.weatherapi.com/weather/64x64/night/296.png",
"code": 1183
"text": "Light rain shower",
"icon": "//cdn.weatherapi.com/weather/64x64/day/353.png",
"code": 1240
},
"wind_mph": 12.1,
"wind_kph": 19.4,
"wind_degree": 151,
"wind_mph": 13.6,
"wind_kph": 22.0,
"wind_degree": 147,
"wind_dir": "SSE",
"pressure_mb": 999.0,
"pressure_in": 29.5,
"precip_mm": 0.0,
"precip_in": 0.0,
"humidity": 77,
"cloud": 100,
"pressure_mb": 983.0,
"pressure_in": 29.03,
"precip_mm": 2.34,
"precip_in": 0.09,
"humidity": 100,
"cloud": 75,
"feelslike_c": 10.3,
"feelslike_f": 50.6,
"windchill_c": 10.1,
"windchill_f": 50.1,
"heatindex_c": 12.1,
"heatindex_f": 53.8,
"dewpoint_c": 7.7,
"dewpoint_f": 45.8,
"vis_km": 10.0,
"vis_miles": 6.0,
"feelslike_f": 50.5,
"windchill_c": 10.5,
"windchill_f": 50.9,
"heatindex_c": 12.6,
"heatindex_f": 54.6,
"dewpoint_c": 12.0,
"dewpoint_f": 53.6,
"vis_km": 8.0,
"vis_miles": 4.0,
"uv": 0.0,
"gust_mph": 19.8,
"gust_kph": 31.9,
"gust_mph": 21.1,
"gust_kph": 33.9,
"air_quality": {
"co": 171.678,
"no2": 9.778,
"o3": 54.0,
"so2": 1.678,
"pm2_5": 10.078,
"pm10": 12.578,
"co": 152.678,
"no2": 8.378,
"o3": 35.0,
"so2": 0.878,
"pm2_5": 7.878,
"pm10": 8.978,
"us-epa-index": 1,
"gb-defra-index": 1
}

View File

@@ -1,5 +1,5 @@
@city = "grosshansdorf"
@lang = de
@lang = en
@forecast_days = 3
# could be 60(mins) or 24(day)
@time_period_forecast = 60