Compare commits

...

4 commits

Author SHA1 Message Date
foamyguy
792955cf1a
Merge pull request #39 from FoamyGuy/cli_examples_serpentine_fix
add serpentine arg to CLI examples
2025-03-18 13:28:12 -05:00
foamyguy
b35b3d35bb add serpentine arg to CLI examples 2025-03-18 12:20:42 -05:00
foamyguy
0225964f24
Merge pull request #36 from adafruit/large-xfer-workaround
Restore large xfer workaround & actually report errors in pio_sm_xfer_data
2025-03-17 13:47:18 -05:00
89dd515ae5 restore large xfer workaround
sadly, it's not possible to gracefully switch from large to blocked
xfers, further xfer ioctls fail after the first large xfer fails.
2025-03-17 11:29:28 -05:00
5 changed files with 45 additions and 9 deletions

View file

@ -44,7 +44,7 @@ def main(xoffset, yoffset, width, height, serpentine, rotation, pinout, n_planes
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)
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, serpentine=serpentine)
framebuffer = np.zeros(shape=(geometry.height, geometry.width), dtype=dtype)
matrix = piomatter.PioMatter(colorspace=piomatter.Colorspace.RGB565, pinout=pinout, framebuffer=framebuffer, geometry=geometry)

View file

@ -72,7 +72,7 @@ def main(xoffset, yoffset, scale, width, height, serpentine, rotation, pinout, n
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_temporal_planes=n_temporal_planes, n_addr_lines=n_addr_lines, rotation=rotation)
geometry = piomatter.Geometry(width=width, height=height, n_planes=n_planes, n_temporal_planes=n_temporal_planes, n_addr_lines=n_addr_lines, rotation=rotation, serpentine=serpentine)
matrix_framebuffer = np.zeros(shape=(geometry.height, geometry.width, 3), dtype=np.uint8)
matrix = piomatter.PioMatter(colorspace=piomatter.Colorspace.RGB888Packed, pinout=pinout, framebuffer=matrix_framebuffer, geometry=geometry)

View file

@ -57,7 +57,7 @@ def main(scale, backend, use_xauth, extra_args, rfbport, brightness, width, heig
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)
n_temporal_planes=n_temporal_planes, rotation=rotation, serpentine=serpentine)
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)

View file

@ -52,7 +52,7 @@ def main(width, height, serpentine, rotation, pinout, n_planes,
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)
n_temporal_planes=n_temporal_planes, rotation=rotation, serpentine=serpentine)
framebuffer = np.zeros(shape=(geometry.height, geometry.width, 3), dtype=np.uint8)
matrix = piomatter.PioMatter(colorspace=piomatter.Colorspace.RGB888Packed, pinout=pinout, framebuffer=framebuffer,

View file

@ -12,6 +12,42 @@
namespace piomatter {
static int pio_sm_xfer_data_large(PIO pio, int sm, int direction, size_t size,
uint32_t *databuf) {
#if 0
// it would be NICE to gracefully fall back to blocked transfer, but sadly
// once the large xfer ioctl fails, future small xfers fail too.
static enum { UNKNOWN, OK, BAD } large_xfer_status = UNKNOWN;
printf("large_xfer_status=%d\n", large_xfer_status);
if (large_xfer_status != BAD) {
int r = pio_sm_xfer_data(pio, sm, direction, size, databuf);
if (large_xfer_status == UNKNOWN && r != 0) {
large_xfer_status = BAD;
fprintf(stderr,
"Transmission limit workaround engaged. May reduce quality of "
"output.\nSee https://github.com/raspberrypi/utils/issues/123 "
"for details.\n");
} else {
if (large_xfer_status == UNKNOWN && r == 0) {
large_xfer_status = OK;
}
return r;
}
}
#endif
constexpr size_t MAX_XFER = 65532;
while (size) {
size_t xfersize = std::min(size_t{MAX_XFER}, size);
int r = pio_sm_xfer_data(pio, sm, direction, xfersize, databuf);
if (r != 0) {
return r;
}
size -= xfersize;
databuf += xfersize / sizeof(*databuf);
}
return 0;
}
static uint64_t monotonicns64() {
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp);
@ -181,12 +217,12 @@ struct piomatter : piomatter_base {
auto dataptr = const_cast<uint32_t *>(&data[0]);
// returns err = rp1_ioctl.... which seems to be a negative
// errno value
int r =
pio_sm_xfer_data(pio, sm, PIO_DIR_TO_SM, datasize, dataptr);
int r = pio_sm_xfer_data_large(pio, sm, PIO_DIR_TO_SM, datasize,
dataptr);
if (r != 0) {
pending_error_errno.store(-r);
printf("xfer_data() returned error %d (%s)\n", r,
strerror(-r));
pending_error_errno.store(errno);
printf("xfer_data() returned error %d (errno=%s)\n", r,
strerror(errno));
}
t1 = monotonicns64();
if (t0 != t1) {