Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow defining geometries (including more than 2 color lanes) via Python code #27

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/*.pio.h
protodemo
/build
*.egg-info
5 changes: 3 additions & 2 deletions examples/fbmirror.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@
"""


import adafruit_blinka_raspberry_pi5_piomatter as piomatter
import click
import numpy as np
import piomatter_click

import adafruit_blinka_raspberry_pi5_piomatter as piomatter
import adafruit_blinka_raspberry_pi5_piomatter.click as piomatter_click

with open("/sys/class/graphics/fb0/virtual_size") as f:
screenx, screeny = [int(word) for word in f.read().split(",")]
Expand Down
5 changes: 3 additions & 2 deletions examples/fbmirror_scaled.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,12 @@
`... video=HDMI-A-1:640x480M@60D`.
"""

import adafruit_blinka_raspberry_pi5_piomatter as piomatter
import click
import numpy as np
import PIL.Image as Image
import piomatter_click

import adafruit_blinka_raspberry_pi5_piomatter as piomatter
import adafruit_blinka_raspberry_pi5_piomatter.click as piomatter_click

with open("/sys/class/graphics/fb0/virtual_size") as f:
screenx, screeny = [int(word) for word in f.read().split(",")]
Expand Down
3 changes: 2 additions & 1 deletion examples/play_gif.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@

import time

import adafruit_blinka_raspberry_pi5_piomatter as piomatter
import numpy as np
import PIL.Image as Image

import adafruit_blinka_raspberry_pi5_piomatter as piomatter

width = 64
height = 32

Expand Down
3 changes: 2 additions & 1 deletion examples/playframes.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@
import sys
import time

import adafruit_blinka_raspberry_pi5_piomatter as piomatter
import numpy as np
import PIL.Image as Image

import adafruit_blinka_raspberry_pi5_piomatter as piomatter

images = sorted(glob.glob(sys.argv[1]))

geometry = piomatter.Geometry(width=64, height=32, n_addr_lines=4, rotation=piomatter.Orientation.Normal)
Expand Down
3 changes: 2 additions & 1 deletion examples/quote_scroller.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@

"""

import adafruit_blinka_raspberry_pi5_piomatter as piomatter
import numpy as np
import requests
from PIL import Image, ImageDraw, ImageFont

import adafruit_blinka_raspberry_pi5_piomatter as piomatter

# 128px for 2x1 matrices. Change to 64 if you're using a single matrix.
total_width = 128
total_height = 32
Expand Down
3 changes: 2 additions & 1 deletion examples/rainbow_spiral.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@
$ python rainbow_spiral.py

"""
import adafruit_blinka_raspberry_pi5_piomatter as piomatter
import numpy as np
import rainbowio
from PIL import Image, ImageDraw

import adafruit_blinka_raspberry_pi5_piomatter as piomatter

width = 64
height = 32
pen_radius = 1
Expand Down
128 changes: 128 additions & 0 deletions examples/rainbow_spiral_active3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#!/usr/bin/python3
# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
Display a spiral around the display drawn with a rainbow color.

Run like this:

$ python rainbow_spiral.py

"""
import numpy as np
import rainbowio
from PIL import Image, ImageDraw

import adafruit_blinka_raspberry_pi5_piomatter as piomatter

width = 64
n_lanes = 6
n_addr_lines = 5
height = n_lanes << n_addr_lines
pen_radius = 1

def make_pixelmap_multilane(width, height, n_addr_lines, n_lanes):
calc_height = n_lanes << n_addr_lines
if height != calc_height:
raise RuntimeError(f"Calculated height {calc_height} does not match requested height {height}")
n_addr = 1 << n_addr_lines

m = []
for addr in range(n_addr):
for x in range(width):
for lane in range(n_lanes):
y = addr + lane * n_addr
m.append(x + width * y)
print(m)
return m


canvas = Image.new('RGB', (width, height), (0, 0, 0))
draw = ImageDraw.Draw(canvas)

pixelmap = make_pixelmap_multilane(width, height, n_addr_lines, n_lanes)
geometry = piomatter.Geometry(width=width, height=height, n_addr_lines=n_addr_lines, n_planes=8, map=pixelmap, n_lanes=n_lanes)
framebuffer = np.asarray(canvas) + 0 # Make a mutable copy
matrix = piomatter.PioMatter(colorspace=piomatter.Colorspace.RGB888Packed,
pinout=piomatter.Pinout.Active3,
framebuffer=framebuffer,
geometry=geometry)

color_index = 0

update_interval = 3
update_counter = 0
def update_matrix():
global update_counter
if (update_counter := update_counter + 1) >= update_interval:
framebuffer[:] = np.asarray(canvas)
matrix.show()
update_counter = 0

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")
3 changes: 2 additions & 1 deletion examples/simpletest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@

import pathlib

import adafruit_blinka_raspberry_pi5_piomatter as piomatter
import numpy as np
import PIL.Image as Image

import adafruit_blinka_raspberry_pi5_piomatter as piomatter

geometry = piomatter.Geometry(width=64, height=64, n_addr_lines=4, rotation=piomatter.Orientation.Normal)
framebuffer = np.asarray(Image.open(pathlib.Path(__file__).parent / "blinka64x64.png"))
matrix = piomatter.PioMatter(colorspace=piomatter.Colorspace.RGB888Packed,
Expand Down
3 changes: 2 additions & 1 deletion examples/simpletest_addre_bgr.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@

import pathlib

import adafruit_blinka_raspberry_pi5_piomatter as piomatter
import numpy as np
import PIL.Image as Image

import adafruit_blinka_raspberry_pi5_piomatter as piomatter

geometry = piomatter.Geometry(width=64, height=64, n_addr_lines=5, rotation=piomatter.Orientation.Normal, n_planes=8)
framebuffer = np.asarray(Image.open(pathlib.Path(__file__).parent / "blinka64x64.png"))
matrix = piomatter.PioMatter(colorspace=piomatter.Colorspace.RGB888Packed, pinout=piomatter.Pinout.AdafruitMatrixBonnetBGR, framebuffer=framebuffer, geometry=geometry)
Expand Down
3 changes: 2 additions & 1 deletion examples/single_panel_simpletest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@

"""

import adafruit_blinka_raspberry_pi5_piomatter as piomatter
import numpy as np
from PIL import Image, ImageDraw

import adafruit_blinka_raspberry_pi5_piomatter as piomatter

width = 64
height = 32

Expand Down
5 changes: 3 additions & 2 deletions examples/virtualdisplay.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@
import shlex
from subprocess import Popen

import adafruit_blinka_raspberry_pi5_piomatter as piomatter
import click
import numpy as np
import piomatter_click
from pyvirtualdisplay.smartdisplay import SmartDisplay

import adafruit_blinka_raspberry_pi5_piomatter as piomatter
import adafruit_blinka_raspberry_pi5_piomatter.click as piomatter_click


@click.command
@click.option("--scale", type=float, help="The scale factor, larger numbers mean more virtual pixels", default=1)
Expand Down
3 changes: 2 additions & 1 deletion examples/virtualdisplay_keyboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,13 @@
import tty
from subprocess import Popen, run

import adafruit_blinka_raspberry_pi5_piomatter as piomatter
import click
import numpy as np
import piomatter_click
from pyvirtualdisplay.smartdisplay import SmartDisplay

import adafruit_blinka_raspberry_pi5_piomatter as piomatter

keyboard_debug = False
keys_down = set()
basic_characters = string.ascii_letters + string.digits
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ build-backend = "setuptools.build_meta"
[tool.setuptools_scm]

[tool.ruff]
extend-select = [
lint.extend-select = [
"B", # flake8-bugbear
"I", # isort
"PGH", # pygrep-hooks
"RUF", # Ruff-specific
"UP", # pyupgrade
]
extend-ignore = [
lint.extend-ignore = [
"E501", # Line too long
]
target-version = "py311"
4 changes: 3 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# say from a submodule.

ext_modules = [
Pybind11Extension("adafruit_blinka_raspberry_pi5_piomatter",
Pybind11Extension("adafruit_blinka_raspberry_pi5_piomatter._piomatter",
["src/pymain.cpp", "src/piolib/piolib.c", "src/piolib/pio_rp1.c"],
define_macros = [('VERSION_INFO', __version__)],
include_dirs = ['./src/include', './src/piolib/include'],
Expand All @@ -33,6 +33,8 @@
cmdclass={"build_ext": build_ext},
zip_safe=False,
python_requires=">=3.11",
packages=['adafruit_blinka_raspberry_pi5_piomatter'],
package_dir={'adafruit_blinka_raspberry_pi5_piomatter': 'src/adafruit_blinka_raspberry_pi5_piomatter'},
extras_require={
'docs': ["sphinx", "sphinx-rtd-theme", "sphinxcontrib-jquery"],
},
Expand Down
21 changes: 21 additions & 0 deletions src/adafruit_blinka_raspberry_pi5_piomatter/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from ._piomatter import (
AdafruitMatrixBonnetRGB565,
AdafruitMatrixBonnetRGB888,
AdafruitMatrixBonnetRGB888Packed,
Colorspace,
Geometry,
Orientation,
Pinout,
PioMatter,
)

__all__ = [
'AdafruitMatrixBonnetRGB565',
'AdafruitMatrixBonnetRGB888',
'AdafruitMatrixBonnetRGB888Packed',
'Colorspace',
'Geometry',
'Orientation',
'Pinout',
'PioMatter',
]
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
from collections.abc import Callable
from typing import Any

import adafruit_blinka_raspberry_pi5_piomatter as piomatter
import click

import adafruit_blinka_raspberry_pi5_piomatter as piomatter


class PybindEnumChoice(click.Choice):
def __init__(self, enum, case_sensitive=False):
Expand Down Expand Up @@ -35,6 +36,7 @@ def standard_options(
pinout=piomatter.Pinout.AdafruitMatrixBonnet,
n_planes=10,
n_addr_lines=4,
n_lanes=None,
) -> Callable[[], None]:
"""Add standard commandline flags, with the defaults given

Expand Down Expand Up @@ -76,6 +78,8 @@ def wrapper(f: click.decorators.FC):
f = click.option("--num-planes", "n_planes", default=n_planes, help="The number of bit planes (color depth. Lower values can improve refresh rate in frames per second")(f)
if n_addr_lines is not None:
f = click.option("--num-address-lines", "n_addr_lines", default=n_addr_lines, help="The number of address lines used by the panels")(f)
if n_lanes is not None:
f = click.option("--num-lanes", "n_lanes", default=n_lanes, help="The number of lanes used by the panels. One 16-pin connector has two lanes (6 RGB pins)")(f)
return f
if f is None:
return wrapper
Expand Down
Loading