WIP move matrix creation into click

This commit is contained in:
Jeff Epler 2025-03-18 11:23:26 -05:00
parent 0225964f24
commit 182529a41b
9 changed files with 55 additions and 30 deletions

View file

@ -19,7 +19,7 @@ jobs:
- name: Set up repository
uses: actions/checkout@v4
with:
submodules: false
submodules: true
show-progress: false
fetch-depth: 1
persist-credentials: false

2
.gitignore vendored
View file

@ -1,3 +1,5 @@
/*.pio.h
/build
/dist
/docs/api
*.egg-info

View file

@ -0,0 +1 @@
../build/lib.linux-x86_64-cpython-311/adafruit_blinka_raspberry_pi5_piomatter/

View file

@ -17,7 +17,6 @@ import numpy as np
import adafruit_blinka_raspberry_pi5_piomatter as piomatter
import adafruit_blinka_raspberry_pi5_piomatter.click as piomatter_click
from adafruit_blinka_raspberry_pi5_piomatter.pixelmappers import simple_multilane_mapper
with open("/sys/class/graphics/fb0/virtual_size") as f:
screenx, screeny = [int(word) for word in f.read().split(",")]
@ -39,15 +38,10 @@ linux_framebuffer = np.memmap('/dev/fb0',mode='r', shape=(screeny, stride // byt
@click.option("--x-offset", "xoffset", type=int, help="The x offset of top left corner of the region to mirror", default=0)
@click.option("--y-offset", "yoffset", type=int, help="The y offset of top left corner of the region to mirror", default=0)
@piomatter_click.standard_options
def main(xoffset, yoffset, width, height, serpentine, rotation, pinout, n_planes, n_temporal_planes, n_addr_lines, n_lanes):
if n_lanes != 2:
pixelmap = simple_multilane_mapper(width, height, n_addr_lines, n_lanes)
geometry = piomatter.Geometry(width=width, height=height, n_planes=n_planes, n_addr_lines=n_addr_lines, n_temporal_planes=n_temporal_planes, n_lanes=n_lanes, map=pixelmap)
else:
geometry = piomatter.Geometry(width=width, height=height, n_planes=n_planes, n_addr_lines=n_addr_lines, n_temporal_planes=n_temporal_planes, rotation=rotation)
framebuffer = np.zeros(shape=(geometry.height, geometry.width), dtype=dtype)
matrix = piomatter.PioMatter(colorspace=piomatter.Colorspace.RGB565, pinout=pinout, framebuffer=framebuffer, geometry=geometry)
@piomatter_click.make_matrix(colorspace=piomatter.Colorspace.RGB565)
def main(xoffset, yoffset, matrix, framebuffer):
width = matrix.width
height = matrix.height
while True:
framebuffer[:,:] = linux_framebuffer[yoffset:yoffset+height, xoffset:xoffset+width]
matrix.show()

View file

@ -30,7 +30,6 @@ from pyvirtualdisplay.smartdisplay import SmartDisplay
import adafruit_blinka_raspberry_pi5_piomatter as piomatter
import adafruit_blinka_raspberry_pi5_piomatter.click as piomatter_click
from adafruit_blinka_raspberry_pi5_piomatter.pixelmappers import simple_multilane_mapper
@click.command
@ -42,24 +41,18 @@ from adafruit_blinka_raspberry_pi5_piomatter.pixelmappers import simple_multilan
default=1.0, type=click.FloatRange(min=0.1, max=1.0))
@click.option("--use-xauth/--no-use-xauth", help="If a Xauthority file should be created", default=False)
@piomatter_click.standard_options
@piomatter_click.make_matrix(colorspace=piomatter.Colorspace.RGB888Packed)
@click.argument("command", nargs=-1)
def main(scale, backend, use_xauth, extra_args, rfbport, brightness, width, height, serpentine, rotation, pinout,
n_planes, n_temporal_planes, n_addr_lines, n_lanes, command):
def main(matrix, framebuffer, scale, backend, use_xauth, extra_args, rfbport, brightness, command):
kwargs = {}
if backend == "xvnc":
kwargs['rfbport'] = rfbport
if extra_args:
kwargs['extra_args'] = shlex.split(extra_args)
print("xauth", use_xauth)
if n_lanes != 2:
pixelmap = simple_multilane_mapper(width, height, n_addr_lines, n_lanes)
geometry = piomatter.Geometry(width=width, height=height, n_planes=n_planes, n_addr_lines=n_addr_lines,
n_temporal_planes=n_temporal_planes, n_lanes=n_lanes, map=pixelmap)
else:
geometry = piomatter.Geometry(width=width, height=height, n_planes=n_planes, n_addr_lines=n_addr_lines,
n_temporal_planes=n_temporal_planes, rotation=rotation)
framebuffer = np.zeros(shape=(geometry.height, geometry.width, 3), dtype=np.uint8)
matrix = piomatter.PioMatter(colorspace=piomatter.Colorspace.RGB888Packed, pinout=pinout, framebuffer=framebuffer, geometry=geometry)
width = matrix.width
height = matrix.height
with SmartDisplay(backend=backend, use_xauth=use_xauth, size=(round(width*scale),round(height*scale)), manage_global_env=False, **kwargs) as disp, Popen(command, env=disp.env()) as proc:
while proc.poll() is None:

View file

@ -1,8 +1,9 @@
# Available at setup time due to pyproject.toml
from pybind11.setup_helpers import Pybind11Extension, build_ext
from setuptools import setup
from setuptools_scm import get_version
from pybind11.setup_helpers import Pybind11Extension, build_ext
__version__ = get_version()
# The main interface is through Pybind11Extension.

View file

@ -6,9 +6,39 @@ from collections.abc import Callable
from typing import Any
import click
import numpy as np
import adafruit_blinka_raspberry_pi5_piomatter as piomatter
from .pixelmappers import simple_multilane_mapper
def make_matrix(*, colorspace):
print("make_matrix", colorspace)
def do_make_matrix(f):
print("do_make_matrix", f)
def wrapper(width, height, serpentine, rotation, pinout, n_planes, n_temporal_planes, n_addr_lines, n_lanes, **click_args):
if colorspace == piomatter.Colorspace.RGB565:
framebuffer = np.zeros((height, width), dtype=np.uint16)
elif colorspace == piomatter.Colorspace.RGB888:
framebuffer = np.zeros((height, width), dtype=np.uint32)
elif colorspace == piomatter.Colorspace.RGB888Packed:
framebuffer = np.zeros((height, width, 3), dtype=np.uint8)
else:
raise ValueError(f"Unsupported colorspace {colorspace!r}")
if n_lanes != 2:
if serpentine:
raise ValueError("Serpentine is only avaialble with 2 lanes")
pixelmap = simple_multilane_mapper(width, height, n_addr_lines, n_lanes)
geometry = piomatter.Geometry(width=width, height=height, n_planes=n_planes, n_addr_lines=n_addr_lines, n_temporal_planes=n_temporal_planes, n_lanes=n_lanes, map=pixelmap)
else:
geometry = piomatter.Geometry(width=width, height=height, n_planes=n_planes, n_addr_lines=n_addr_lines, n_temporal_planes=n_temporal_planes, rotation=rotation)
matrix = piomatter.PioMatter(colorspace=colorspace, pinout=pinout, framebuffer=framebuffer, geometry=geometry)
return f(matrix=matrix, framebuffer=framebuffer, **click_args)
return wrapper
return do_make_matrix
class _PybindEnumChoice(click.Choice):
def __init__(self, enum, case_sensitive=False):

View file

@ -57,7 +57,7 @@ static uint64_t monotonicns64() {
constexpr size_t MAX_XFER = 65532;
struct piomatter_base {
piomatter_base() {}
piomatter_base(const matrix_geometry &geometry) : geometry{geometry} {}
piomatter_base(const piomatter_base &) = delete;
piomatter_base &operator=(const piomatter_base &) = delete;
@ -65,17 +65,18 @@ struct piomatter_base {
virtual int show() = 0;
double fps;
matrix_geometry geometry;
};
template <class pinout = adafruit_matrix_bonnet_pinout,
class colorspace = colorspace_rgb888>
struct piomatter : piomatter_base {
struct piomatter : public piomatter_base {
using buffer_type = std::vector<uint32_t>;
using bufseq_type = std::vector<buffer_type>;
piomatter(std::span<typename colorspace::data_type const> framebuffer,
const matrix_geometry &geometry)
: framebuffer(framebuffer), geometry{geometry}, converter{},
blitter_thread{} {
: piomatter_base{geometry},
framebuffer(framebuffer), converter{}, blitter_thread{} {
if (geometry.n_addr_lines > std::size(pinout::PIN_ADDR)) {
throw std::runtime_error("too many address lines requested");
}
@ -240,7 +241,6 @@ struct piomatter : piomatter_base {
std::span<typename colorspace::data_type const> framebuffer;
bufseq_type buffers[3];
buffer_manager manager{};
matrix_geometry geometry;
colorspace converter;
std::thread blitter_thread;
std::atomic<int> pending_error_errno;

View file

@ -27,6 +27,8 @@ struct PyPiomatter {
}
}
double fps() const { return matter->fps; }
int width() const { return matter->geometry.width; }
int height() const { return matter->geometry.height; }
};
template <typename pinout, typename colorspace>
@ -288,5 +290,7 @@ data is triple-buffered to prevent tearing.
)pbdoc")
.def_property_readonly("fps", &PyPiomatter::fps, R"pbdoc(
The approximate number of matrix refreshes per second.
)pbdoc");
)pbdoc")
.def_property_readonly("width", &PyPiomatter::width)
.def_property_readonly("height", &PyPiomatter::height);
}