builds, but broken with weird error

This commit is contained in:
Jeff Epler 2025-01-14 14:50:43 -06:00
parent ee8b718621
commit 895a5e5458
6 changed files with 113 additions and 52 deletions

BIN
examples/blinka64x64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

10
examples/simpletest.py Normal file
View file

@ -0,0 +1,10 @@
import adafruit_raspberry_pi5_piomatter
import numpy as np
import PIL.Image as Image
g = adafruit_raspberry_pi5_piomatter.Geometry(64, 64, 4, rotation=adafruit_raspberry_pi5_piomatter.Orientation.Normal)
arr = np.asarray(Image.open("blinka64x64.png"))
m = adafruit_raspberry_pi5_piomatter.AdafruitMatrixBonnetRGB888Packed(arr, g)
m.show()
input("Hit enter to exit")

View file

@ -11,13 +11,13 @@ __version__ = get_version()
# say from a submodule.
ext_modules = [
Pybind11Extension("adafruit_raspberry_pi5_neopixel_write",
Pybind11Extension("adafruit_raspberry_pi5_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'],
cxx_std=20,
# use this setting when debugging
#extra_compile_args = ["-g3", "-Og"],
extra_compile_args = ["-g3", "-Og"],
),
]
@ -25,7 +25,7 @@ setup(
name="Adafruit-Blinka-Raspberry-Pi5-Neopixel",
version=__version__,
url="https://github.com/adafruit/Adafruit_Blinka_Raspberry_Pi5_Neopixel",
description="Control NeoPixel & compatibles on a Pi 5",
description="HUB75 matrix driver for Raspberry Pi 5 using PIO",
long_description="A pio-based driver",
ext_modules=ext_modules,
# Currently, build_ext only provides an optional "highest supported C++

View file

@ -29,6 +29,10 @@ void pio_sm_xfer_data_large(PIO pio, int sm, int direction, size_t size,
}
struct piomatter_base {
piomatter_base() {}
piomatter_base(const piomatter_base &) = delete;
piomatter_base &operator=(const piomatter_base &) = delete;
virtual ~piomatter_base() {}
virtual void show() = 0;
};

View file

@ -73,6 +73,9 @@ struct gamma_lut {
struct colorspace_rgb565 {
using data_type = uint16_t;
static constexpr size_t data_size_in_bytes(size_t n_pixels) {
return sizeof(data_type) * n_pixels;
}
colorspace_rgb565(float gamma = 2.2) : lut{gamma} {}
gamma_lut lut;
@ -86,6 +89,9 @@ struct colorspace_rgb565 {
struct colorspace_rgb888 {
using data_type = uint32_t;
static constexpr size_t data_size_in_bytes(size_t n_pixels) {
return sizeof(data_type) * n_pixels;
}
colorspace_rgb888(float gamma = 2.2) : lut{gamma} {}
gamma_lut lut;
@ -99,6 +105,9 @@ struct colorspace_rgb888 {
struct colorspace_rgb888_packed {
using data_type = uint8_t;
static constexpr size_t data_size_in_bytes(size_t n_pixels) {
return sizeof(data_type) * n_pixels * 3;
}
colorspace_rgb888_packed(float gamma = 2.2) : lut{gamma} {}
gamma_lut lut;

View file

@ -1,5 +1,6 @@
#include <iostream>
#include <pybind11/pybind11.h>
#include <string>
#include "piomatter/piomatter.h"
@ -8,12 +9,47 @@
namespace py = pybind11;
namespace {}
namespace {
struct PyPiomatter {
PyPiomatter(py::buffer buffer,
std::unique_ptr<piomatter::piomatter_base> &&matter)
: buffer{buffer}, matter{std::move(matter)} {}
py::buffer buffer;
std::unique_ptr<piomatter::piomatter_base> matter;
void show() { matter->show(); }
};
template <typename pinout, typename colorspace>
std::unique_ptr<PyPiomatter>
make_piomatter(py::buffer buffer, const piomatter::matrix_geometry &geometry) {
using cls = piomatter::piomatter<pinout, colorspace>;
using data_type = colorspace::data_type;
const auto n_pixels = geometry.width * geometry.height;
const auto data_size_in_bytes = colorspace::data_size_in_bytes(n_pixels);
const py::buffer_info info = buffer.request();
const size_t buffer_size_in_bytes = info.size * info.itemsize;
if (buffer_size_in_bytes != data_size_in_bytes) {
throw std::runtime_error(
py::str(
"Framebuffer size must be {} bytes, got a buffer of {} bytes")
.attr("format")(data_size_in_bytes, buffer_size_in_bytes)
.template cast<std::string>());
}
std::span<data_type> framebuffer(reinterpret_cast<data_type *>(info.ptr),
data_size_in_bytes / sizeof(data_type));
return std::make_unique<PyPiomatter>(
buffer, std::move(std::make_unique<cls>(framebuffer, geometry)));
}
} // namespace
PYBIND11_MODULE(adafruit_raspberry_pi5_piomatter, m) {
m.doc() = R"pbdoc(
hub75 matrix driver for pi5 using pio
-------------------------------------
HUB75 matrix driver for Raspberry Pi 5 using PIO
------------------------------------------------
.. currentmodule:: adafruit_raspberry_pi5_piomatter
@ -23,77 +59,79 @@ PYBIND11_MODULE(adafruit_raspberry_pi5_piomatter, m) {
Piomatter
)pbdoc";
#if 0
py::enum_<piomatter::orientation>(m, "Orientation", py::doc("describes the orientation of a panel"))
py::enum_<piomatter::orientation>(m, "Orientation")
.value("Normal", piomatter::orientation::normal)
.value("R180", piomatter::orientation::r180)
.value("CCW", piomatter::orientation::ccw)
.value("CW", piomatter::orientation::cw)
//.doc() = "Describes the orientation of a panel"
;
#endif
py::class_<piomatter::matrix_geometry>(m, "Geometry"
#if 0
, py::doc("Describes the geometry of a panel")
#endif
)
.def(py::init([](size_t width, size_t height, size_t pixels_across,
size_t n_addr_lines, bool serpentine, int rotation,
py::class_<piomatter::matrix_geometry>(m, "Geometry")
.def(py::init([](size_t width, size_t height, size_t n_addr_lines,
bool serpentine, piomatter::orientation rotation,
size_t n_planes) {
size_t n_lines = 2 << n_addr_lines;
size_t pixels_across = width * height / n_lines;
size_t odd = (width * height) % n_lines;
if (odd) {
throw std::runtime_error(
py::str(
"Total pixel count {} must be a multiple of {}, "
"the number of distinct row addresses for {}")
.attr("format")(width * height, n_lines,
n_addr_lines)
.cast<std::string>());
}
switch (rotation) {
case 0:
case piomatter::orientation::normal:
return piomatter::matrix_geometry(
pixels_across, n_addr_lines, n_planes, width, height,
serpentine, piomatter::orientation_normal);
case 180:
case piomatter::orientation::r180:
return piomatter::matrix_geometry(
pixels_across, n_addr_lines, n_planes, width, height,
serpentine, piomatter::orientation_r180);
case 90:
case piomatter::orientation::ccw:
return piomatter::matrix_geometry(
pixels_across, n_addr_lines, n_planes, width, height,
serpentine, piomatter::orientation_ccw);
case 270:
case piomatter::orientation::cw:
return piomatter::matrix_geometry(
pixels_across, n_addr_lines, n_planes, width, height,
serpentine, piomatter::orientation_cw);
}
throw std::runtime_error("invalid orientation");
})
#if 1
,
py::arg("width"), py::arg("height"), py::arg("pixels_across"),
py::arg("n_addr_lines"), py::arg("serpentine") = false,
py::arg("orientation") = 0u, py::arg("n_planes") = 10u
#endif
)
throw std::runtime_error("invalid rotation");
}),
py::arg("width"), py::arg("height"), py::arg("n_addr_lines"),
py::arg("serpentine") = true,
py::arg("rotation") = piomatter::orientation::normal,
py::arg("n_planes") = 10u)
.def_readonly("width", &piomatter::matrix_geometry::width)
.def_readonly("hieght", &piomatter::matrix_geometry::height);
#if 0
py::class_<piomatter::piomatter_base>(m, "PiomatterBase", py::doc("Base class of all pinouts"))
.def("show", &piomatter_base::show)
.def_readonly("hieght", &piomatter::matrix_geometry::height)
//.doc() = "Describes the geometry of a panel"
;
#endif
using AdafruitMatrixBonnetRGB888 =
piomatter::piomatter<piomatter::adafruit_matrix_bonnet_pinout,
piomatter::colorspace_rgb888>;
py::class_<AdafruitMatrixBonnetRGB888>(
m, "AdafruitMatrixBonnetRGB888") // .def(py::init<py::buffer,
// matrix_geometry>())
.def("show", &AdafruitMatrixBonnetRGB888::show);
py::class_<PyPiomatter>(m, "PioMatter").def("show", &PyPiomatter::show)
//.doc() = "HUB75 matrix driver for Raspberry Pi 5 using PIO"
;
#if 0
#define pinout(pinoutname, colorspace, pyclassname) \
py::class_<piomatter<pinoutname, colorspace>, piomatter_base>(m, \
pyclassname) \
.def(py::init<matrix_geometry, py::buffer>())
m.def("AdafruitMatrixBonnetRGB888",
make_piomatter<piomatter::adafruit_matrix_bonnet_pinout,
piomatter::colorspace_rgb888>,
py::arg("buffer"), py::arg("geometry"))
//.doc() = "Drive panels connected to an Adafruit Matrix Bonnet using
// the RGB888 memory layout (4 bytes per pixel)"
;
pinout(adafruit_matrix_bonnet_pinout, colorspace_rgb888, "AdafruitMatrixBonnetRGB888");
//pinout(adafruit_matrix_bonnet_pinout, colorspace_rgb888_packed, "AdafruitMatrixBonnetRGB888Packed");
#endif
m.def("AdafruitMatrixBonnetRGB888Packed",
make_piomatter<piomatter::adafruit_matrix_bonnet_pinout,
piomatter::colorspace_rgb888_packed>,
py::arg("buffer"), py::arg("geometry"))
// .doc() = "Drive panels connected to an Adafruit Matrix Bonnet using
// the RGB888 packed memory layout (3 bytes per pixel)"
;
}