Allow using fewer than all the lanes

It's always the lowest numbered lanes. So now you can at least run
the first lane of an Active3 with a standard matrix map
This commit is contained in:
Jeff Epler 2025-03-06 14:24:19 -06:00
parent 274adf1805
commit 296047a806
3 changed files with 27 additions and 15 deletions

View file

@ -48,7 +48,8 @@ matrix_map make_matrixmap(size_t width, size_t height, size_t n_addr_lines,
size_t panel_height = 2 << n_addr_lines;
if (height % panel_height != 0) {
throw std::range_error("Height does not evenly divide panel height");
throw std::range_error(
"Overall height does not evenly divide calculated panel height");
}
size_t half_panel_height = 1u << n_addr_lines;
@ -86,20 +87,21 @@ struct matrix_geometry {
size_t width, size_t height, bool serpentine, const Cb &cb)
: matrix_geometry(
pixels_across, n_addr_lines, n_planes, width, height,
make_matrixmap(width, height, n_addr_lines, serpentine, cb)) {}
make_matrixmap(width, height, n_addr_lines, serpentine, cb), 2) {}
matrix_geometry(size_t pixels_across, size_t n_addr_lines, int n_planes,
size_t width, size_t height, matrix_map map)
size_t width, size_t height, matrix_map map, size_t n_lanes)
: pixels_across(pixels_across), n_addr_lines(n_addr_lines),
n_planes(n_planes), width(width), height(height), map(map) {
size_t pixels_down = 2u << n_addr_lines;
n_lanes(n_lanes), n_planes(n_planes), width(width), height(height),
map(map) {
size_t pixels_down = n_lanes << n_addr_lines;
if (map.size() != pixels_down * pixels_across) {
throw std::range_error(
"map size does not match calculated pixel count");
}
}
size_t pixels_across, n_addr_lines;
size_t pixels_across, n_addr_lines, n_lanes;
int n_planes;
size_t width, height;
matrix_map map;

View file

@ -214,18 +214,18 @@ void protomatter_render_rgb10(std::vector<uint32_t> &result,
auto mapiter = matrixmap.map.begin() + 2 * addr * pixels_across;
for (size_t x = 0; x < pixels_across; x++) {
uint32_t data = addr_bits;
for(size_t px = 0; px < std::size(pinout::PIN_RGB) / 3; px++) {
for (size_t px = 0; px < matrixmap.n_lanes; px++) {
assert(mapiter != matrixmap.map.end());
auto pixel0 = pixels[*mapiter++];
auto r_bit = pixel0 & r_mask;
auto g_bit = pixel0 & g_mask;
auto b_bit = pixel0 & b_mask;
if(r_bit)
if (r_bit)
data |= (1 << pinout::PIN_RGB[px * 3 + 0]);
if(g_bit)
if (g_bit)
data |= (1 << pinout::PIN_RGB[px * 3 + 1]);
if(b_bit)
if (b_bit)
data |= (1 << pinout::PIN_RGB[px * 3 + 2]);
}

View file

@ -33,6 +33,14 @@ make_piomatter_pc(py::buffer buffer,
const py::buffer_info info = buffer.request();
const size_t buffer_size_in_bytes = info.size * info.itemsize;
if (geometry.n_lanes * 3 > std::size(pinout::PIN_RGB)) {
throw std::runtime_error(
py::str("Geometry lane count {} exceeds the pinout with {} rgb "
"pins ({} lanes)")
.attr("format")(geometry.n_lanes, std::size(pinout::PIN_RGB),
std::size(pinout::PIN_RGB) / 3)
.template cast<std::string>());
}
if (buffer_size_in_bytes != data_size_in_bytes) {
throw std::runtime_error(
py::str("Framebuffer size must be {} bytes ({} elements of {} "
@ -217,19 +225,21 @@ The default, 10, is the maximum value.
py::arg("rotation") = piomatter::orientation::normal,
py::arg("n_planes") = 10u)
.def(py::init([](size_t width, size_t height, size_t n_addr_lines,
piomatter::matrix_map map, size_t n_planes) {
size_t n_lines = 2 << n_addr_lines;
piomatter::matrix_map map, size_t n_planes,
size_t n_lanes) {
size_t n_lines = n_lanes << n_addr_lines;
size_t pixels_across = width * height / n_lines;
for (auto el : map) {
if ((size_t)el >= width * height) {
throw std::out_of_range("Map element out of range");
}
}
return piomatter::matrix_geometry(
pixels_across, n_addr_lines, n_planes, width, height, map);
return piomatter::matrix_geometry(pixels_across, n_addr_lines,
n_planes, width, height, map,
n_lanes);
}),
py::arg("width"), py::arg("height"), py::arg("n_addr_lines"),
py::arg("map"), py::arg("n_planes") = 10u)
py::arg("map"), py::arg("n_planes") = 10u, py::arg("n_lanes") = 2)
.def_readonly("width", &piomatter::matrix_geometry::width)
.def_readonly("height", &piomatter::matrix_geometry::height);