Skip to content

Commit 632b3f5

Browse files
authored
Create Display_LVGL_Font.py
1 parent e579992 commit 632b3f5

File tree

1 file changed

+160
-0
lines changed

1 file changed

+160
-0
lines changed
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# SPDX-FileCopyrightText: 2025 Anne Barela for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
#
5+
# Display an LVGL (.bin) font on a CircuitPython board and
6+
# 640x480 DVI display. Unknown characters will be "."
7+
#
8+
import displayio
9+
import supervisor
10+
from adafruit_bitmap_font import bitmap_font
11+
from adafruit_display_text import label
12+
import gc
13+
from adafruit_fruitjam.peripherals import request_display_config
14+
15+
# Use the easy library call to set the resolution
16+
request_display_config(640, 480)
17+
18+
# Initialize display
19+
display = supervisor.runtime.display
20+
main_group = displayio.Group()
21+
display.root_group = main_group
22+
23+
print(f"Initial memory: {gc.mem_free()}")
24+
25+
# Font loading with error handling and diagnostics
26+
font_file = "fonts/CP437_16h.bin"
27+
try:
28+
font = bitmap_font.load_font(font_file)
29+
print(f"Font loaded: {font_file}")
30+
print(f"Memory after font load: {gc.mem_free()}")
31+
32+
# Diagnostic: Check font properties
33+
try:
34+
bbox = font.get_bounding_box()
35+
print(f"Font bounding box: {bbox}")
36+
37+
# Test a few common characters
38+
test_chars = [32, 65, 97] # space, 'A', 'a'
39+
for char_code in test_chars:
40+
glyph = font.get_glyph(char_code)
41+
if glyph:
42+
print(f"Char {char_code} ('{chr(char_code)}'): OK")
43+
else:
44+
print(f"Char {char_code} ('{chr(char_code)}'): Missing")
45+
46+
except Exception as e:
47+
print(f"Error checking font properties: {e}")
48+
49+
except Exception as e:
50+
print(f"Error loading font {font_file}: {e}")
51+
# Fallback to terminalio font
52+
import terminalio
53+
font = terminalio.FONT
54+
print("Using fallback terminalio.FONT")
55+
56+
# Get actual font dimensions
57+
try:
58+
font_bbox = font.get_bounding_box()
59+
char_width = font_bbox[0]
60+
char_height = font_bbox[1]
61+
print(f"Actual font size: {char_width}x{char_height}")
62+
except:
63+
char_width = 9 # fallback
64+
char_height = 16 # fallback
65+
print(f"Using fallback font size: {char_width}x{char_height}")
66+
67+
chars_per_line = 32 # Fixed at 32 characters per line
68+
line_number_width = 5 * char_width # Space for "000: " (5 characters)
69+
70+
displayed_count = 0
71+
skipped_count = 0
72+
current_x = line_number_width # Start after line number space
73+
current_y = char_height
74+
current_line_start = 0
75+
76+
def create_char_label(font, char, x, y):
77+
"""Helper function to create character labels with error handling"""
78+
try:
79+
return label.Label(font, text=char, color=0xFFFFFF, x=x, y=y)
80+
except Exception as e:
81+
print(f"Error creating label for '{char}': {e}")
82+
return None
83+
84+
# Add first line number
85+
text = f"{current_line_start:03d}: "
86+
print(f"Creating line number: '{text}'")
87+
88+
for i, char in enumerate(text):
89+
char_label = create_char_label(font, char, i * char_width, current_y)
90+
if char_label:
91+
main_group.append(char_label)
92+
93+
print(f"Memory after first line number: {gc.mem_free()}")
94+
95+
# Try all characters from 0-255 and display ones that exist
96+
for char_code in range(256):
97+
try:
98+
# Check if we need to wrap to next line
99+
if (char_code > 0) and (char_code % chars_per_line == 0):
100+
current_x = line_number_width # Reset to after line number
101+
current_y += char_height + 4 # Add some line spacing
102+
current_line_start = char_code
103+
104+
# Stop if we run out of vertical space
105+
if current_y + char_height > display.height:
106+
print(f"Display full, stopped at character {char_code}")
107+
break
108+
109+
# Add line number for this new line
110+
text = f"{current_line_start:03d}: "
111+
for i, char in enumerate(text):
112+
char_label = create_char_label(font, char, i * char_width, current_y)
113+
if char_label:
114+
main_group.append(char_label)
115+
116+
# Check if glyph exists
117+
glyph = font.get_glyph(char_code)
118+
119+
if glyph is None:
120+
# No glyph available - display a period instead
121+
display_char = "."
122+
skipped_count += 1
123+
else:
124+
# Glyph exists - display the actual character
125+
display_char = chr(char_code)
126+
127+
# Create label for this character (or replacement)
128+
char_label = create_char_label(font, display_char, current_x, current_y)
129+
if char_label:
130+
main_group.append(char_label)
131+
132+
current_x += char_width
133+
displayed_count += 1
134+
135+
except (MemoryError, ValueError) as e:
136+
print(f"Memory/Value error at character {char_code}: {e}")
137+
break
138+
except Exception as e:
139+
print(f"Unexpected error at character {char_code}: {e}")
140+
# Continue with next character
141+
current_x += char_width
142+
displayed_count += 1
143+
144+
# More frequent garbage collection
145+
if char_code % 8 == 0:
146+
gc.collect()
147+
148+
# Progress indicator for debugging
149+
if char_code % 32 == 0:
150+
print(f"Processed up to character {char_code}, memory: {gc.mem_free()}")
151+
152+
print(f"\nCompleted character display:")
153+
print(f"Found {displayed_count - skipped_count} characters with glyphs")
154+
print(f"{skipped_count} missing characters displayed as periods")
155+
print(f"Total labels created: {len(main_group)}")
156+
print(f"Final free memory: {gc.mem_free()} bytes")
157+
158+
# Keep display active
159+
while True:
160+
pass

0 commit comments

Comments
 (0)