Merge pull request #9 from FoamyGuy/various_touchups
Some checks failed
Pip / build (ubuntu-24.04-arm, 3.11) (push) Has been cancelled
Pip / build (ubuntu-24.04-arm, 3.12) (push) Has been cancelled
Pip / build (ubuntu-24.04-arm, 3.13) (push) Has been cancelled
pre-commit / pre-commit (push) Has been cancelled
Wheels / Build SDist (push) Has been cancelled
Wheels / Wheels on ubuntu-24.04-arm (push) Has been cancelled
Wheels / Upload release (push) Has been cancelled
Some checks failed
Pip / build (ubuntu-24.04-arm, 3.11) (push) Has been cancelled
Pip / build (ubuntu-24.04-arm, 3.12) (push) Has been cancelled
Pip / build (ubuntu-24.04-arm, 3.13) (push) Has been cancelled
pre-commit / pre-commit (push) Has been cancelled
Wheels / Build SDist (push) Has been cancelled
Wheels / Wheels on ubuntu-24.04-arm (push) Has been cancelled
Wheels / Upload release (push) Has been cancelled
Various touchups
This commit is contained in:
commit
00101f6668
10 changed files with 299 additions and 10 deletions
|
|
@ -27,7 +27,7 @@ Installing from pip:
|
|||
System setup
|
||||
------------
|
||||
|
||||
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:
|
||||
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:
|
||||
|
||||
```
|
||||
SUBSYSTEM=="*-pio", GROUP="gpio", MODE="0660"
|
||||
|
|
|
|||
BIN
examples/LindenHill-webfont.ttf
Executable file
BIN
examples/LindenHill-webfont.ttf
Executable file
Binary file not shown.
3
examples/LindenHill-webfont.ttf.license
Normal file
3
examples/LindenHill-webfont.ttf.license
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# SPDX-FileCopyrightText: Copyright (c) 2010, Barry Schwartz <site-chieftain@crudfactory.com>, with Reserved Font Name OFL "Linden Hill"
|
||||
|
||||
# SPDX-License-Identifier: OFL-1.1-RFN
|
||||
|
|
@ -4,18 +4,57 @@ Mirror a scaled copy of the framebuffer to a 64x32 matrix
|
|||
|
||||
The upper left corner of the framebuffer is displayed until the user hits ctrl-c.
|
||||
|
||||
Control matrix size, and orientation with command line arguments.
|
||||
|
||||
python fbmirror_scaled.py [width] [height] [orientation]
|
||||
|
||||
width int: Total width of matrices in pixels. Default is 64.
|
||||
height int: Total height of matrices in pixels. Default is 32.
|
||||
orientation int: Orientation in degrees, must be 0, 90, 180, or 270.
|
||||
Default is 0 or Normal orientation.
|
||||
|
||||
The `/dev/fb0` special file will exist if a monitor is plugged in at boot time,
|
||||
or if `/boot/firmware/cmdline.txt` specifies a resolution such as
|
||||
`... video=HDMI-A-1:640x480M@60D`.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
import adafruit_raspberry_pi5_piomatter
|
||||
import numpy as np
|
||||
|
||||
width = 64
|
||||
height = 32
|
||||
|
||||
yoffset = 0
|
||||
xoffset = 0
|
||||
|
||||
|
||||
if len(sys.argv) >= 2:
|
||||
width = int(sys.argv[1])
|
||||
else:
|
||||
width = 64
|
||||
|
||||
if len(sys.argv) >= 3:
|
||||
height = int(sys.argv[2])
|
||||
else:
|
||||
height = 32
|
||||
|
||||
if len(sys.argv) >= 4:
|
||||
rotation = int(sys.argv[3])
|
||||
if rotation == 90:
|
||||
rotation = adafruit_raspberry_pi5_piomatter.Orientation.CW
|
||||
elif rotation == 180:
|
||||
rotation = adafruit_raspberry_pi5_piomatter.Orientation.R180
|
||||
elif rotation == 270:
|
||||
rotation = adafruit_raspberry_pi5_piomatter.Orientation.CCW
|
||||
elif rotation == 0:
|
||||
rotation = adafruit_raspberry_pi5_piomatter.Orientation.Normal
|
||||
else:
|
||||
raise ValueError("Invalid rotation. Must be 0, 90, 180, or 270.")
|
||||
else:
|
||||
rotation = adafruit_raspberry_pi5_piomatter.Orientation.Normal
|
||||
|
||||
with open("/sys/class/graphics/fb0/virtual_size") as f:
|
||||
screenx, screeny = [int(word) for word in f.read().split(",")]
|
||||
|
||||
|
|
@ -32,9 +71,8 @@ with open("/sys/class/graphics/fb0/stride") as f:
|
|||
|
||||
linux_framebuffer = np.memmap('/dev/fb0',mode='r', shape=(screeny, stride // bytes_per_pixel), dtype=dtype)
|
||||
|
||||
width = 64
|
||||
height = 32
|
||||
geometry = adafruit_raspberry_pi5_piomatter.Geometry(width=width, height=height, n_addr_lines=4, rotation=adafruit_raspberry_pi5_piomatter.Orientation.Normal)
|
||||
|
||||
geometry = adafruit_raspberry_pi5_piomatter.Geometry(width=width, height=height, n_addr_lines=4, rotation=rotation)
|
||||
matrix_framebuffer = np.zeros(shape=(geometry.height, geometry.width), dtype=dtype)
|
||||
matrix = adafruit_raspberry_pi5_piomatter.AdafruitMatrixBonnetRGB565(matrix_framebuffer, geometry)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,19 +1,59 @@
|
|||
#!/usr/bin/python3
|
||||
"""
|
||||
Mirror a scaled copy of the framebuffer to a 64x32 matrix
|
||||
Mirror a scaled copy of the framebuffer to 64x32 matrices,
|
||||
|
||||
The upper left corner of the framebuffer is displayed until the user hits ctrl-c.
|
||||
|
||||
Control scale, matrix size, and orientation with command line arguments.
|
||||
|
||||
python fbmirror_scaled.py [scale] [width] [height] [orientation]
|
||||
|
||||
scale int: How many times to scale down the display framebuffer. Default is 3.
|
||||
width int: Total width of matrices in pixels. Default is 64.
|
||||
height int: Total height of matrices in pixels. Default is 32.
|
||||
orientation int: Orientation in degrees, must be 0, 90, 180, or 270.
|
||||
Default is 0 or Normal orientation.
|
||||
|
||||
The `/dev/fb0` special file will exist if a monitor is plugged in at boot time,
|
||||
or if `/boot/firmware/cmdline.txt` specifies a resolution such as
|
||||
`... video=HDMI-A-1:640x480M@60D`.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
import adafruit_raspberry_pi5_piomatter
|
||||
import numpy as np
|
||||
import PIL.Image as Image
|
||||
|
||||
if len(sys.argv) >= 2:
|
||||
scale = int(sys.argv[1])
|
||||
else:
|
||||
scale = 3
|
||||
|
||||
if len(sys.argv) >= 3:
|
||||
width = int(sys.argv[2])
|
||||
else:
|
||||
width = 64
|
||||
|
||||
if len(sys.argv) >= 4:
|
||||
height = int(sys.argv[3])
|
||||
else:
|
||||
height = 32
|
||||
|
||||
if len(sys.argv) >= 5:
|
||||
rotation = int(sys.argv[4])
|
||||
if rotation == 90:
|
||||
rotation = adafruit_raspberry_pi5_piomatter.Orientation.CW
|
||||
elif rotation == 180:
|
||||
rotation = adafruit_raspberry_pi5_piomatter.Orientation.R180
|
||||
elif rotation == 270:
|
||||
rotation = adafruit_raspberry_pi5_piomatter.Orientation.CCW
|
||||
elif rotation == 0:
|
||||
rotation = adafruit_raspberry_pi5_piomatter.Orientation.Normal
|
||||
else:
|
||||
raise ValueError("Invalid rotation. Must be 0, 90, 180, or 270.")
|
||||
else:
|
||||
rotation = adafruit_raspberry_pi5_piomatter.Orientation.Normal
|
||||
|
||||
with open("/sys/class/graphics/fb0/virtual_size") as f:
|
||||
screenx, screeny = [int(word) for word in f.read().split(",")]
|
||||
|
||||
|
|
@ -32,11 +72,8 @@ linux_framebuffer = np.memmap('/dev/fb0',mode='r', shape=(screeny, stride // byt
|
|||
|
||||
xoffset = 0
|
||||
yoffset = 0
|
||||
width = 64
|
||||
height = 32
|
||||
scale = 3
|
||||
|
||||
geometry = adafruit_raspberry_pi5_piomatter.Geometry(width=width, height=height, n_addr_lines=4, rotation=adafruit_raspberry_pi5_piomatter.Orientation.Normal)
|
||||
geometry = adafruit_raspberry_pi5_piomatter.Geometry(width=width, height=height, n_addr_lines=4, rotation=rotation)
|
||||
matrix_framebuffer = np.zeros(shape=(geometry.height, geometry.width, 3), dtype=np.uint8)
|
||||
matrix = adafruit_raspberry_pi5_piomatter.AdafruitMatrixBonnetRGB888Packed(matrix_framebuffer, geometry)
|
||||
|
||||
|
|
|
|||
BIN
examples/nyan.gif
Normal file
BIN
examples/nyan.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
36
examples/play_gif.py
Normal file
36
examples/play_gif.py
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#!/usr/bin/python3
|
||||
"""
|
||||
Display an animated gif
|
||||
|
||||
Run like this:
|
||||
|
||||
$ python play_gif.py
|
||||
|
||||
The animated gif is played repeatedly until interrupted with ctrl-c.
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
import adafruit_raspberry_pi5_piomatter
|
||||
import numpy as np
|
||||
import PIL.Image as Image
|
||||
|
||||
width = 64
|
||||
height = 32
|
||||
|
||||
gif_file = "nyan.gif"
|
||||
|
||||
canvas = Image.new('RGB', (width, height), (0, 0, 0))
|
||||
geometry = adafruit_raspberry_pi5_piomatter.Geometry(width=width, height=height, n_addr_lines=4, rotation=adafruit_raspberry_pi5_piomatter.Orientation.Normal)
|
||||
framebuffer = np.asarray(canvas) + 0 # Make a mutable copy
|
||||
matrix = adafruit_raspberry_pi5_piomatter.AdafruitMatrixBonnetRGB888Packed(framebuffer, geometry)
|
||||
|
||||
with Image.open(gif_file) as img:
|
||||
print(f"frames: {img.n_frames}")
|
||||
while True:
|
||||
for i in range(img.n_frames):
|
||||
img.seek(i)
|
||||
canvas.paste(img, (0,0))
|
||||
framebuffer[:] = np.asarray(canvas)
|
||||
matrix.show()
|
||||
time.sleep(0.1)
|
||||
66
examples/quote_scroller.py
Normal file
66
examples/quote_scroller.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
#!/usr/bin/python3
|
||||
# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
Display quote from the Adafruit quotes API as text scrolling across the
|
||||
matrices.
|
||||
|
||||
Requires the requests library to be installed.
|
||||
|
||||
Run like this:
|
||||
|
||||
$ python quote_scroller.py
|
||||
|
||||
"""
|
||||
|
||||
import adafruit_raspberry_pi5_piomatter
|
||||
import numpy as np
|
||||
import requests
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
# 128px for 2x1 matrices. Change to 64 if you're using a single matrix.
|
||||
total_width = 128
|
||||
total_height = 32
|
||||
|
||||
bottom_half_shift_compensation = 1
|
||||
|
||||
font_color = (0, 128, 128)
|
||||
|
||||
# Load the font
|
||||
font = ImageFont.truetype("LindenHill-webfont.ttf", 26)
|
||||
|
||||
quote_resp = requests.get("https://www.adafruit.com/api/quotes.php").json()
|
||||
|
||||
text = f'{quote_resp[0]["text"]} - {quote_resp[0]["author"]}'
|
||||
#text = "Sometimes you just want to use hardcoded strings. - Unknown"
|
||||
|
||||
x, y, text_width, text_height = font.getbbox(text)
|
||||
|
||||
full_txt_img = Image.new("RGB", (int(text_width) + 6, int(text_height) + 6), (0, 0, 0))
|
||||
draw = ImageDraw.Draw(full_txt_img)
|
||||
draw.text((3, 3), text, font=font, fill=font_color)
|
||||
full_txt_img.save("quote.png")
|
||||
|
||||
single_frame_img = Image.new("RGB", (total_width, total_height), (0, 0, 0))
|
||||
|
||||
geometry = adafruit_raspberry_pi5_piomatter.Geometry(width=total_width, height=total_height, n_addr_lines=4, rotation=adafruit_raspberry_pi5_piomatter.Orientation.Normal)
|
||||
framebuffer = np.asarray(single_frame_img) + 0 # Make a mutable copy
|
||||
|
||||
matrix = adafruit_raspberry_pi5_piomatter.AdafruitMatrixBonnetRGB888Packed(framebuffer, geometry)
|
||||
|
||||
print("Ctrl-C to exit")
|
||||
while True:
|
||||
for x_pixel in range(-total_width-1,full_txt_img.width):
|
||||
if bottom_half_shift_compensation == 0:
|
||||
# full paste
|
||||
single_frame_img.paste(full_txt_img.crop((x_pixel, 0, x_pixel + total_width, total_height)), (0, 0))
|
||||
|
||||
else:
|
||||
# top half
|
||||
single_frame_img.paste(full_txt_img.crop((x_pixel, 0, x_pixel + total_width, total_height//2)), (0, 0))
|
||||
# bottom half shift compensation
|
||||
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))
|
||||
|
||||
framebuffer[:] = np.asarray(single_frame_img)
|
||||
matrix.show()
|
||||
102
examples/rainbow_spiral.py
Normal file
102
examples/rainbow_spiral.py
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
#!/usr/bin/python3
|
||||
# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
Display a simple test pattern of 3 shapes on a single 64x32 matrix panel.
|
||||
|
||||
Run like this:
|
||||
|
||||
$ python simpletest.py
|
||||
|
||||
"""
|
||||
import adafruit_raspberry_pi5_piomatter
|
||||
import numpy as np
|
||||
import rainbowio
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
width = 64
|
||||
height = 32
|
||||
pen_radius = 1
|
||||
|
||||
|
||||
canvas = Image.new('RGB', (width, height), (0, 0, 0))
|
||||
draw = ImageDraw.Draw(canvas)
|
||||
|
||||
geometry = adafruit_raspberry_pi5_piomatter.Geometry(width=width, height=height, n_addr_lines=4,
|
||||
rotation=adafruit_raspberry_pi5_piomatter.Orientation.Normal)
|
||||
framebuffer = np.asarray(canvas) + 0 # Make a mutable copy
|
||||
matrix = adafruit_raspberry_pi5_piomatter.AdafruitMatrixBonnetRGB888Packed(framebuffer, geometry)
|
||||
|
||||
color_index = 0
|
||||
|
||||
def update_matrix():
|
||||
framebuffer[:] = np.asarray(canvas)
|
||||
matrix.show()
|
||||
|
||||
def darken_color(hex_color, darkness_factor):
|
||||
# Convert hex color number to RGB
|
||||
r = (hex_color >> 16) & 0xFF
|
||||
g = (hex_color >> 8) & 0xFF
|
||||
b = hex_color & 0xFF
|
||||
|
||||
# Apply darkness factor
|
||||
r = int(r * (1 - darkness_factor))
|
||||
g = int(g * (1 - darkness_factor))
|
||||
b = int(b * (1 - darkness_factor))
|
||||
|
||||
# Ensure values are within the valid range
|
||||
r = max(0, min(255, r))
|
||||
g = max(0, min(255, g))
|
||||
b = max(0, min(255, b))
|
||||
|
||||
# Convert RGB back to hex number
|
||||
darkened_hex_color = (r << 16) + (g << 8) + b
|
||||
|
||||
return darkened_hex_color
|
||||
|
||||
step_count = 4
|
||||
darkness_factor = 0.5
|
||||
|
||||
clearing = False
|
||||
|
||||
try:
|
||||
# step_down_size = pen_radius * 2 + 2
|
||||
|
||||
while True:
|
||||
for step in range(step_count):
|
||||
step_down_size = step * (pen_radius* 2) + (2 * step)
|
||||
for x in range(pen_radius + step_down_size, width - pen_radius - step_down_size - 1):
|
||||
color_index = (color_index + 2) % 256
|
||||
color = darken_color(rainbowio.colorwheel(color_index), darkness_factor) if not clearing else 0x000000
|
||||
draw.circle((x, pen_radius + step_down_size), pen_radius, color)
|
||||
update_matrix()
|
||||
for y in range(pen_radius + step_down_size, height - pen_radius - step_down_size - 1):
|
||||
color_index = (color_index + 2) % 256
|
||||
color = darken_color(rainbowio.colorwheel(color_index), darkness_factor) if not clearing else 0x000000
|
||||
draw.circle((width - pen_radius - step_down_size -1, y), pen_radius, color)
|
||||
update_matrix()
|
||||
for x in range(width - pen_radius - step_down_size - 1, pen_radius + step_down_size, -1):
|
||||
color_index = (color_index + 2) % 256
|
||||
color = darken_color(rainbowio.colorwheel(color_index), darkness_factor) if not clearing else 0x000000
|
||||
draw.circle((x, height - pen_radius - step_down_size - 1), pen_radius, color)
|
||||
update_matrix()
|
||||
for y in range(height - pen_radius - step_down_size - 1, pen_radius + ((step+1) * (pen_radius* 2) + (2 * (step+1))) -1, -1):
|
||||
color_index = (color_index + 2) % 256
|
||||
color = darken_color(rainbowio.colorwheel(color_index), darkness_factor) if not clearing else 0x000000
|
||||
draw.circle((pen_radius + step_down_size, y), pen_radius, color)
|
||||
update_matrix()
|
||||
|
||||
if step != step_count-1:
|
||||
# connect to next iter
|
||||
for x in range(pen_radius + step_down_size, pen_radius + ((step+1) * (pen_radius* 2) + (2 * (step+1)))):
|
||||
color_index = (color_index + 2) % 256
|
||||
color = darken_color(rainbowio.colorwheel(color_index),
|
||||
darkness_factor) if not clearing else 0x000000
|
||||
draw.circle((x, pen_radius + ((step+1) * (pen_radius* 2) + (2 * (step+1)))), pen_radius, color)
|
||||
update_matrix()
|
||||
|
||||
clearing = not clearing
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("Exiting")
|
||||
7
requirements.txt
Normal file
7
requirements.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: Unlicense
|
||||
Adafruit-Blinka
|
||||
adafruit-circuitpython-pioasm
|
||||
numpy
|
||||
pillow
|
||||
Loading…
Reference in a new issue