Skip to content

Commit 00101f6

Browse files
authored
Merge pull request #9 from FoamyGuy/various_touchups
Various touchups
2 parents 1727669 + 5452337 commit 00101f6

10 files changed

+299
-10
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Installing from pip:
2727
System setup
2828
------------
2929

30-
If `ls -l /dev/pio0` reports that the file is not found, you may need to update your Pi 5 firmware to one with PIO support and make sure that you are running a suitably recent kernel. If `ls -l /dev/pio0` reports that the file is owned by root and group root, you should add the following to /etc/udev/rules/99-com.rules:
30+
If `ls -l /dev/pio0` reports that the file is not found, you may need to update your Pi 5 firmware to one with PIO support and make sure that you are running a suitably recent kernel. If `ls -l /dev/pio0` reports that the file is owned by root and group root, you should add the following to /etc/udev/rules.d/99-com.rules:
3131

3232
```
3333
SUBSYSTEM=="*-pio", GROUP="gpio", MODE="0660"

examples/LindenHill-webfont.ttf

36.6 KB
Binary file not shown.
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2010, Barry Schwartz <[email protected]>, with Reserved Font Name OFL "Linden Hill"
2+
3+
# SPDX-License-Identifier: OFL-1.1-RFN

examples/fbmirror.py

+41-3
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,57 @@
44
55
The upper left corner of the framebuffer is displayed until the user hits ctrl-c.
66
7+
Control matrix size, and orientation with command line arguments.
8+
9+
python fbmirror_scaled.py [width] [height] [orientation]
10+
11+
width int: Total width of matrices in pixels. Default is 64.
12+
height int: Total height of matrices in pixels. Default is 32.
13+
orientation int: Orientation in degrees, must be 0, 90, 180, or 270.
14+
Default is 0 or Normal orientation.
15+
716
The `/dev/fb0` special file will exist if a monitor is plugged in at boot time,
817
or if `/boot/firmware/cmdline.txt` specifies a resolution such as
918
`... video=HDMI-A-1:640x480M@60D`.
1019
"""
1120

21+
import sys
1222

1323
import adafruit_raspberry_pi5_piomatter
1424
import numpy as np
1525

26+
width = 64
27+
height = 32
28+
1629
yoffset = 0
1730
xoffset = 0
1831

32+
33+
if len(sys.argv) >= 2:
34+
width = int(sys.argv[1])
35+
else:
36+
width = 64
37+
38+
if len(sys.argv) >= 3:
39+
height = int(sys.argv[2])
40+
else:
41+
height = 32
42+
43+
if len(sys.argv) >= 4:
44+
rotation = int(sys.argv[3])
45+
if rotation == 90:
46+
rotation = adafruit_raspberry_pi5_piomatter.Orientation.CW
47+
elif rotation == 180:
48+
rotation = adafruit_raspberry_pi5_piomatter.Orientation.R180
49+
elif rotation == 270:
50+
rotation = adafruit_raspberry_pi5_piomatter.Orientation.CCW
51+
elif rotation == 0:
52+
rotation = adafruit_raspberry_pi5_piomatter.Orientation.Normal
53+
else:
54+
raise ValueError("Invalid rotation. Must be 0, 90, 180, or 270.")
55+
else:
56+
rotation = adafruit_raspberry_pi5_piomatter.Orientation.Normal
57+
1958
with open("/sys/class/graphics/fb0/virtual_size") as f:
2059
screenx, screeny = [int(word) for word in f.read().split(",")]
2160

@@ -32,9 +71,8 @@
3271

3372
linux_framebuffer = np.memmap('/dev/fb0',mode='r', shape=(screeny, stride // bytes_per_pixel), dtype=dtype)
3473

35-
width = 64
36-
height = 32
37-
geometry = adafruit_raspberry_pi5_piomatter.Geometry(width=width, height=height, n_addr_lines=4, rotation=adafruit_raspberry_pi5_piomatter.Orientation.Normal)
74+
75+
geometry = adafruit_raspberry_pi5_piomatter.Geometry(width=width, height=height, n_addr_lines=4, rotation=rotation)
3876
matrix_framebuffer = np.zeros(shape=(geometry.height, geometry.width), dtype=dtype)
3977
matrix = adafruit_raspberry_pi5_piomatter.AdafruitMatrixBonnetRGB565(matrix_framebuffer, geometry)
4078

examples/fbmirror_scaled.py

+43-6
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,59 @@
11
#!/usr/bin/python3
22
"""
3-
Mirror a scaled copy of the framebuffer to a 64x32 matrix
3+
Mirror a scaled copy of the framebuffer to 64x32 matrices,
44
55
The upper left corner of the framebuffer is displayed until the user hits ctrl-c.
66
7+
Control scale, matrix size, and orientation with command line arguments.
8+
9+
python fbmirror_scaled.py [scale] [width] [height] [orientation]
10+
11+
scale int: How many times to scale down the display framebuffer. Default is 3.
12+
width int: Total width of matrices in pixels. Default is 64.
13+
height int: Total height of matrices in pixels. Default is 32.
14+
orientation int: Orientation in degrees, must be 0, 90, 180, or 270.
15+
Default is 0 or Normal orientation.
16+
717
The `/dev/fb0` special file will exist if a monitor is plugged in at boot time,
818
or if `/boot/firmware/cmdline.txt` specifies a resolution such as
919
`... video=HDMI-A-1:640x480M@60D`.
1020
"""
11-
21+
import sys
1222

1323
import adafruit_raspberry_pi5_piomatter
1424
import numpy as np
1525
import PIL.Image as Image
1626

27+
if len(sys.argv) >= 2:
28+
scale = int(sys.argv[1])
29+
else:
30+
scale = 3
31+
32+
if len(sys.argv) >= 3:
33+
width = int(sys.argv[2])
34+
else:
35+
width = 64
36+
37+
if len(sys.argv) >= 4:
38+
height = int(sys.argv[3])
39+
else:
40+
height = 32
41+
42+
if len(sys.argv) >= 5:
43+
rotation = int(sys.argv[4])
44+
if rotation == 90:
45+
rotation = adafruit_raspberry_pi5_piomatter.Orientation.CW
46+
elif rotation == 180:
47+
rotation = adafruit_raspberry_pi5_piomatter.Orientation.R180
48+
elif rotation == 270:
49+
rotation = adafruit_raspberry_pi5_piomatter.Orientation.CCW
50+
elif rotation == 0:
51+
rotation = adafruit_raspberry_pi5_piomatter.Orientation.Normal
52+
else:
53+
raise ValueError("Invalid rotation. Must be 0, 90, 180, or 270.")
54+
else:
55+
rotation = adafruit_raspberry_pi5_piomatter.Orientation.Normal
56+
1757
with open("/sys/class/graphics/fb0/virtual_size") as f:
1858
screenx, screeny = [int(word) for word in f.read().split(",")]
1959

@@ -32,11 +72,8 @@
3272

3373
xoffset = 0
3474
yoffset = 0
35-
width = 64
36-
height = 32
37-
scale = 3
3875

39-
geometry = adafruit_raspberry_pi5_piomatter.Geometry(width=width, height=height, n_addr_lines=4, rotation=adafruit_raspberry_pi5_piomatter.Orientation.Normal)
76+
geometry = adafruit_raspberry_pi5_piomatter.Geometry(width=width, height=height, n_addr_lines=4, rotation=rotation)
4077
matrix_framebuffer = np.zeros(shape=(geometry.height, geometry.width, 3), dtype=np.uint8)
4178
matrix = adafruit_raspberry_pi5_piomatter.AdafruitMatrixBonnetRGB888Packed(matrix_framebuffer, geometry)
4279

examples/nyan.gif

4.28 KB
Loading

examples/play_gif.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/python3
2+
"""
3+
Display an animated gif
4+
5+
Run like this:
6+
7+
$ python play_gif.py
8+
9+
The animated gif is played repeatedly until interrupted with ctrl-c.
10+
"""
11+
12+
import time
13+
14+
import adafruit_raspberry_pi5_piomatter
15+
import numpy as np
16+
import PIL.Image as Image
17+
18+
width = 64
19+
height = 32
20+
21+
gif_file = "nyan.gif"
22+
23+
canvas = Image.new('RGB', (width, height), (0, 0, 0))
24+
geometry = adafruit_raspberry_pi5_piomatter.Geometry(width=width, height=height, n_addr_lines=4, rotation=adafruit_raspberry_pi5_piomatter.Orientation.Normal)
25+
framebuffer = np.asarray(canvas) + 0 # Make a mutable copy
26+
matrix = adafruit_raspberry_pi5_piomatter.AdafruitMatrixBonnetRGB888Packed(framebuffer, geometry)
27+
28+
with Image.open(gif_file) as img:
29+
print(f"frames: {img.n_frames}")
30+
while True:
31+
for i in range(img.n_frames):
32+
img.seek(i)
33+
canvas.paste(img, (0,0))
34+
framebuffer[:] = np.asarray(canvas)
35+
matrix.show()
36+
time.sleep(0.1)

examples/quote_scroller.py

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#!/usr/bin/python3
2+
# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
3+
#
4+
# SPDX-License-Identifier: MIT
5+
"""
6+
Display quote from the Adafruit quotes API as text scrolling across the
7+
matrices.
8+
9+
Requires the requests library to be installed.
10+
11+
Run like this:
12+
13+
$ python quote_scroller.py
14+
15+
"""
16+
17+
import adafruit_raspberry_pi5_piomatter
18+
import numpy as np
19+
import requests
20+
from PIL import Image, ImageDraw, ImageFont
21+
22+
# 128px for 2x1 matrices. Change to 64 if you're using a single matrix.
23+
total_width = 128
24+
total_height = 32
25+
26+
bottom_half_shift_compensation = 1
27+
28+
font_color = (0, 128, 128)
29+
30+
# Load the font
31+
font = ImageFont.truetype("LindenHill-webfont.ttf", 26)
32+
33+
quote_resp = requests.get("https://www.adafruit.com/api/quotes.php").json()
34+
35+
text = f'{quote_resp[0]["text"]} - {quote_resp[0]["author"]}'
36+
#text = "Sometimes you just want to use hardcoded strings. - Unknown"
37+
38+
x, y, text_width, text_height = font.getbbox(text)
39+
40+
full_txt_img = Image.new("RGB", (int(text_width) + 6, int(text_height) + 6), (0, 0, 0))
41+
draw = ImageDraw.Draw(full_txt_img)
42+
draw.text((3, 3), text, font=font, fill=font_color)
43+
full_txt_img.save("quote.png")
44+
45+
single_frame_img = Image.new("RGB", (total_width, total_height), (0, 0, 0))
46+
47+
geometry = adafruit_raspberry_pi5_piomatter.Geometry(width=total_width, height=total_height, n_addr_lines=4, rotation=adafruit_raspberry_pi5_piomatter.Orientation.Normal)
48+
framebuffer = np.asarray(single_frame_img) + 0 # Make a mutable copy
49+
50+
matrix = adafruit_raspberry_pi5_piomatter.AdafruitMatrixBonnetRGB888Packed(framebuffer, geometry)
51+
52+
print("Ctrl-C to exit")
53+
while True:
54+
for x_pixel in range(-total_width-1,full_txt_img.width):
55+
if bottom_half_shift_compensation == 0:
56+
# full paste
57+
single_frame_img.paste(full_txt_img.crop((x_pixel, 0, x_pixel + total_width, total_height)), (0, 0))
58+
59+
else:
60+
# top half
61+
single_frame_img.paste(full_txt_img.crop((x_pixel, 0, x_pixel + total_width, total_height//2)), (0, 0))
62+
# bottom half shift compensation
63+
single_frame_img.paste(full_txt_img.crop((x_pixel, total_height//2, x_pixel + total_width, total_height)), (bottom_half_shift_compensation, total_height//2))
64+
65+
framebuffer[:] = np.asarray(single_frame_img)
66+
matrix.show()

examples/rainbow_spiral.py

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/usr/bin/python3
2+
# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
3+
#
4+
# SPDX-License-Identifier: MIT
5+
"""
6+
Display a simple test pattern of 3 shapes on a single 64x32 matrix panel.
7+
8+
Run like this:
9+
10+
$ python simpletest.py
11+
12+
"""
13+
import adafruit_raspberry_pi5_piomatter
14+
import numpy as np
15+
import rainbowio
16+
from PIL import Image, ImageDraw
17+
18+
width = 64
19+
height = 32
20+
pen_radius = 1
21+
22+
23+
canvas = Image.new('RGB', (width, height), (0, 0, 0))
24+
draw = ImageDraw.Draw(canvas)
25+
26+
geometry = adafruit_raspberry_pi5_piomatter.Geometry(width=width, height=height, n_addr_lines=4,
27+
rotation=adafruit_raspberry_pi5_piomatter.Orientation.Normal)
28+
framebuffer = np.asarray(canvas) + 0 # Make a mutable copy
29+
matrix = adafruit_raspberry_pi5_piomatter.AdafruitMatrixBonnetRGB888Packed(framebuffer, geometry)
30+
31+
color_index = 0
32+
33+
def update_matrix():
34+
framebuffer[:] = np.asarray(canvas)
35+
matrix.show()
36+
37+
def darken_color(hex_color, darkness_factor):
38+
# Convert hex color number to RGB
39+
r = (hex_color >> 16) & 0xFF
40+
g = (hex_color >> 8) & 0xFF
41+
b = hex_color & 0xFF
42+
43+
# Apply darkness factor
44+
r = int(r * (1 - darkness_factor))
45+
g = int(g * (1 - darkness_factor))
46+
b = int(b * (1 - darkness_factor))
47+
48+
# Ensure values are within the valid range
49+
r = max(0, min(255, r))
50+
g = max(0, min(255, g))
51+
b = max(0, min(255, b))
52+
53+
# Convert RGB back to hex number
54+
darkened_hex_color = (r << 16) + (g << 8) + b
55+
56+
return darkened_hex_color
57+
58+
step_count = 4
59+
darkness_factor = 0.5
60+
61+
clearing = False
62+
63+
try:
64+
# step_down_size = pen_radius * 2 + 2
65+
66+
while True:
67+
for step in range(step_count):
68+
step_down_size = step * (pen_radius* 2) + (2 * step)
69+
for x in range(pen_radius + step_down_size, width - pen_radius - step_down_size - 1):
70+
color_index = (color_index + 2) % 256
71+
color = darken_color(rainbowio.colorwheel(color_index), darkness_factor) if not clearing else 0x000000
72+
draw.circle((x, pen_radius + step_down_size), pen_radius, color)
73+
update_matrix()
74+
for y in range(pen_radius + step_down_size, height - pen_radius - step_down_size - 1):
75+
color_index = (color_index + 2) % 256
76+
color = darken_color(rainbowio.colorwheel(color_index), darkness_factor) if not clearing else 0x000000
77+
draw.circle((width - pen_radius - step_down_size -1, y), pen_radius, color)
78+
update_matrix()
79+
for x in range(width - pen_radius - step_down_size - 1, pen_radius + step_down_size, -1):
80+
color_index = (color_index + 2) % 256
81+
color = darken_color(rainbowio.colorwheel(color_index), darkness_factor) if not clearing else 0x000000
82+
draw.circle((x, height - pen_radius - step_down_size - 1), pen_radius, color)
83+
update_matrix()
84+
for y in range(height - pen_radius - step_down_size - 1, pen_radius + ((step+1) * (pen_radius* 2) + (2 * (step+1))) -1, -1):
85+
color_index = (color_index + 2) % 256
86+
color = darken_color(rainbowio.colorwheel(color_index), darkness_factor) if not clearing else 0x000000
87+
draw.circle((pen_radius + step_down_size, y), pen_radius, color)
88+
update_matrix()
89+
90+
if step != step_count-1:
91+
# connect to next iter
92+
for x in range(pen_radius + step_down_size, pen_radius + ((step+1) * (pen_radius* 2) + (2 * (step+1)))):
93+
color_index = (color_index + 2) % 256
94+
color = darken_color(rainbowio.colorwheel(color_index),
95+
darkness_factor) if not clearing else 0x000000
96+
draw.circle((x, pen_radius + ((step+1) * (pen_radius* 2) + (2 * (step+1)))), pen_radius, color)
97+
update_matrix()
98+
99+
clearing = not clearing
100+
101+
except KeyboardInterrupt:
102+
print("Exiting")

requirements.txt

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: Unlicense
4+
Adafruit-Blinka
5+
adafruit-circuitpython-pioasm
6+
numpy
7+
pillow

0 commit comments

Comments
 (0)