WIP move matrix creation into click
This commit is contained in:
parent
0225964f24
commit
182529a41b
9 changed files with 55 additions and 30 deletions
2
.github/workflows/pre-commit.yml
vendored
2
.github/workflows/pre-commit.yml
vendored
|
|
@ -19,7 +19,7 @@ jobs:
|
||||||
- name: Set up repository
|
- name: Set up repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: false
|
submodules: true
|
||||||
show-progress: false
|
show-progress: false
|
||||||
fetch-depth: 1
|
fetch-depth: 1
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,3 +1,5 @@
|
||||||
/*.pio.h
|
/*.pio.h
|
||||||
/build
|
/build
|
||||||
|
/dist
|
||||||
|
/docs/api
|
||||||
*.egg-info
|
*.egg-info
|
||||||
|
|
|
||||||
1
examples/adafruit_blinka_raspberry_pi5_piomatter
Symbolic link
1
examples/adafruit_blinka_raspberry_pi5_piomatter
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../build/lib.linux-x86_64-cpython-311/adafruit_blinka_raspberry_pi5_piomatter/
|
||||||
|
|
@ -17,7 +17,6 @@ import numpy as np
|
||||||
|
|
||||||
import adafruit_blinka_raspberry_pi5_piomatter as piomatter
|
import adafruit_blinka_raspberry_pi5_piomatter as piomatter
|
||||||
import adafruit_blinka_raspberry_pi5_piomatter.click as piomatter_click
|
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:
|
with open("/sys/class/graphics/fb0/virtual_size") as f:
|
||||||
screenx, screeny = [int(word) for word in f.read().split(",")]
|
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("--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)
|
@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
|
@piomatter_click.standard_options
|
||||||
def main(xoffset, yoffset, width, height, serpentine, rotation, pinout, n_planes, n_temporal_planes, n_addr_lines, n_lanes):
|
@piomatter_click.make_matrix(colorspace=piomatter.Colorspace.RGB565)
|
||||||
if n_lanes != 2:
|
def main(xoffset, yoffset, matrix, framebuffer):
|
||||||
pixelmap = simple_multilane_mapper(width, height, n_addr_lines, n_lanes)
|
width = matrix.width
|
||||||
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)
|
height = matrix.height
|
||||||
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)
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
framebuffer[:,:] = linux_framebuffer[yoffset:yoffset+height, xoffset:xoffset+width]
|
framebuffer[:,:] = linux_framebuffer[yoffset:yoffset+height, xoffset:xoffset+width]
|
||||||
matrix.show()
|
matrix.show()
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ from pyvirtualdisplay.smartdisplay import SmartDisplay
|
||||||
|
|
||||||
import adafruit_blinka_raspberry_pi5_piomatter as piomatter
|
import adafruit_blinka_raspberry_pi5_piomatter as piomatter
|
||||||
import adafruit_blinka_raspberry_pi5_piomatter.click as piomatter_click
|
import adafruit_blinka_raspberry_pi5_piomatter.click as piomatter_click
|
||||||
from adafruit_blinka_raspberry_pi5_piomatter.pixelmappers import simple_multilane_mapper
|
|
||||||
|
|
||||||
|
|
||||||
@click.command
|
@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))
|
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)
|
@click.option("--use-xauth/--no-use-xauth", help="If a Xauthority file should be created", default=False)
|
||||||
@piomatter_click.standard_options
|
@piomatter_click.standard_options
|
||||||
|
@piomatter_click.make_matrix(colorspace=piomatter.Colorspace.RGB888Packed)
|
||||||
@click.argument("command", nargs=-1)
|
@click.argument("command", nargs=-1)
|
||||||
def main(scale, backend, use_xauth, extra_args, rfbport, brightness, width, height, serpentine, rotation, pinout,
|
def main(matrix, framebuffer, scale, backend, use_xauth, extra_args, rfbport, brightness, command):
|
||||||
n_planes, n_temporal_planes, n_addr_lines, n_lanes, command):
|
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
if backend == "xvnc":
|
if backend == "xvnc":
|
||||||
kwargs['rfbport'] = rfbport
|
kwargs['rfbport'] = rfbport
|
||||||
if extra_args:
|
if extra_args:
|
||||||
kwargs['extra_args'] = shlex.split(extra_args)
|
kwargs['extra_args'] = shlex.split(extra_args)
|
||||||
print("xauth", use_xauth)
|
print("xauth", use_xauth)
|
||||||
if n_lanes != 2:
|
|
||||||
pixelmap = simple_multilane_mapper(width, height, n_addr_lines, n_lanes)
|
width = matrix.width
|
||||||
geometry = piomatter.Geometry(width=width, height=height, n_planes=n_planes, n_addr_lines=n_addr_lines,
|
height = matrix.height
|
||||||
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)
|
|
||||||
|
|
||||||
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:
|
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:
|
while proc.poll() is None:
|
||||||
|
|
|
||||||
3
setup.py
3
setup.py
|
|
@ -1,8 +1,9 @@
|
||||||
# Available at setup time due to pyproject.toml
|
# Available at setup time due to pyproject.toml
|
||||||
from pybind11.setup_helpers import Pybind11Extension, build_ext
|
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
from setuptools_scm import get_version
|
from setuptools_scm import get_version
|
||||||
|
|
||||||
|
from pybind11.setup_helpers import Pybind11Extension, build_ext
|
||||||
|
|
||||||
__version__ = get_version()
|
__version__ = get_version()
|
||||||
|
|
||||||
# The main interface is through Pybind11Extension.
|
# The main interface is through Pybind11Extension.
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,39 @@ from collections.abc import Callable
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import click
|
import click
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
import adafruit_blinka_raspberry_pi5_piomatter as piomatter
|
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):
|
class _PybindEnumChoice(click.Choice):
|
||||||
def __init__(self, enum, case_sensitive=False):
|
def __init__(self, enum, case_sensitive=False):
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ static uint64_t monotonicns64() {
|
||||||
constexpr size_t MAX_XFER = 65532;
|
constexpr size_t MAX_XFER = 65532;
|
||||||
|
|
||||||
struct piomatter_base {
|
struct piomatter_base {
|
||||||
piomatter_base() {}
|
piomatter_base(const matrix_geometry &geometry) : geometry{geometry} {}
|
||||||
piomatter_base(const piomatter_base &) = delete;
|
piomatter_base(const piomatter_base &) = delete;
|
||||||
piomatter_base &operator=(const piomatter_base &) = delete;
|
piomatter_base &operator=(const piomatter_base &) = delete;
|
||||||
|
|
||||||
|
|
@ -65,17 +65,18 @@ struct piomatter_base {
|
||||||
virtual int show() = 0;
|
virtual int show() = 0;
|
||||||
|
|
||||||
double fps;
|
double fps;
|
||||||
|
matrix_geometry geometry;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class pinout = adafruit_matrix_bonnet_pinout,
|
template <class pinout = adafruit_matrix_bonnet_pinout,
|
||||||
class colorspace = colorspace_rgb888>
|
class colorspace = colorspace_rgb888>
|
||||||
struct piomatter : piomatter_base {
|
struct piomatter : public piomatter_base {
|
||||||
using buffer_type = std::vector<uint32_t>;
|
using buffer_type = std::vector<uint32_t>;
|
||||||
using bufseq_type = std::vector<buffer_type>;
|
using bufseq_type = std::vector<buffer_type>;
|
||||||
piomatter(std::span<typename colorspace::data_type const> framebuffer,
|
piomatter(std::span<typename colorspace::data_type const> framebuffer,
|
||||||
const matrix_geometry &geometry)
|
const matrix_geometry &geometry)
|
||||||
: framebuffer(framebuffer), geometry{geometry}, converter{},
|
: piomatter_base{geometry},
|
||||||
blitter_thread{} {
|
framebuffer(framebuffer), converter{}, blitter_thread{} {
|
||||||
if (geometry.n_addr_lines > std::size(pinout::PIN_ADDR)) {
|
if (geometry.n_addr_lines > std::size(pinout::PIN_ADDR)) {
|
||||||
throw std::runtime_error("too many address lines requested");
|
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;
|
std::span<typename colorspace::data_type const> framebuffer;
|
||||||
bufseq_type buffers[3];
|
bufseq_type buffers[3];
|
||||||
buffer_manager manager{};
|
buffer_manager manager{};
|
||||||
matrix_geometry geometry;
|
|
||||||
colorspace converter;
|
colorspace converter;
|
||||||
std::thread blitter_thread;
|
std::thread blitter_thread;
|
||||||
std::atomic<int> pending_error_errno;
|
std::atomic<int> pending_error_errno;
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ struct PyPiomatter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
double fps() const { return matter->fps; }
|
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>
|
template <typename pinout, typename colorspace>
|
||||||
|
|
@ -288,5 +290,7 @@ data is triple-buffered to prevent tearing.
|
||||||
)pbdoc")
|
)pbdoc")
|
||||||
.def_property_readonly("fps", &PyPiomatter::fps, R"pbdoc(
|
.def_property_readonly("fps", &PyPiomatter::fps, R"pbdoc(
|
||||||
The approximate number of matrix refreshes per second.
|
The approximate number of matrix refreshes per second.
|
||||||
)pbdoc");
|
)pbdoc")
|
||||||
|
.def_property_readonly("width", &PyPiomatter::width)
|
||||||
|
.def_property_readonly("height", &PyPiomatter::height);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue