From 8b9f7d7006a618e6c4633dac30171cc52b2d68e0 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 13 Mar 2025 10:40:31 -0500 Subject: [PATCH] Enable 3 & 5 temporal planes By doing a bit more math we can create a sensible schedule for these situations. A 6/3 schedule gives a very nice 150fps with temporal shimmer at 50Hz --- .../click.py | 4 +-- src/include/piomatter/matrixmap.h | 25 +++++++---------- src/protodemo.cpp | 28 +++++++++++++++---- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/src/adafruit_blinka_raspberry_pi5_piomatter/click.py b/src/adafruit_blinka_raspberry_pi5_piomatter/click.py index 9aef1cb..53482e5 100644 --- a/src/adafruit_blinka_raspberry_pi5_piomatter/click.py +++ b/src/adafruit_blinka_raspberry_pi5_piomatter/click.py @@ -27,8 +27,8 @@ class _PybindEnumChoice(click.Choice): return r def _validate_temporal_planes(ctx, param, value): - if value not in (0, 2, 4): - raise click.BadParameter("must be 0, 2, or 4") + if value not in (0, 1, 2, 3, 4, 5): + raise click.BadParameter("must be from 0 to 5 (0 and 1 both disable temporal planes)") return value def standard_options( diff --git a/src/include/piomatter/matrixmap.h b/src/include/piomatter/matrixmap.h index f721a88..acb3945 100644 --- a/src/include/piomatter/matrixmap.h +++ b/src/include/piomatter/matrixmap.h @@ -134,31 +134,26 @@ schedule_sequence make_temporal_dither_schedule(int n_planes, if (n_temporal_planes >= n_planes) { throw std::range_error("n_temporal_planes can't exceed n_planes"); } - if (n_temporal_planes != 2 && n_temporal_planes != 4) { - // the code can generate a schedule for 8 temporal planes, but it - // flickers intolerably - throw std::range_error("n_temporal_planes must be 0, 1, 2, or 4"); - } int n_real_planes = n_planes - n_temporal_planes; - schedule base_sched; - for (int j = 0; j < n_real_planes; j++) { - base_sched.emplace_back( - 9 - j, (1 << (n_temporal_planes + n_real_planes - j - 1)) / - n_temporal_planes); - } - schedule_sequence result; - auto add_sched = [&result, &base_sched](int plane, int count) { - auto sched = base_sched; + auto add_sched = [&result, n_real_planes, + n_temporal_planes](int i, int plane, int count) { + schedule sched; + for (int j = 0; j < n_real_planes; j++) { + int k = 1 << (n_temporal_planes + n_real_planes - j - 1); + printf("n_real_planes=%d n_temporal_planes=%d plane=%d k=%d\n", + n_real_planes, n_temporal_planes, j, k); + sched.emplace_back(9 - j, (k + i) / n_temporal_planes); + } sched.emplace_back(9 - plane, count); result.emplace_back(sched); }; for (int i = 0; i < n_temporal_planes; i++) { - add_sched(n_real_planes + i, 1 << (n_temporal_planes - i - 1)); + add_sched(i, n_real_planes + i, 1 << (n_temporal_planes - i - 1)); } #if 0 std::vector counts(10, 0); diff --git a/src/protodemo.cpp b/src/protodemo.cpp index b5899b3..6660bfd 100644 --- a/src/protodemo.cpp +++ b/src/protodemo.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "piomatter/piomatter.h" @@ -61,7 +62,7 @@ uint32_t pixels[height][width] = { #undef w #undef _ -#define rgb(r, g, b) ((r << 16) | (g << 8) | b) +#define rgb(r, g, b) (((r) << 16) | ((g) << 8) | (b)) uint32_t colorwheel(int i) { i = i & 0xff; @@ -102,28 +103,42 @@ static void print_dither_schedule(const piomatter::schedule_sequence &ss) { } printf("\n"); } + printf(" -> "); + std::map sums; + for (auto s : ss) { + for (auto i : s) { + sums[-i.shift] += i.active_time; + } + } + for (auto const &i : sums) { + printf("{%d %d} ", -i.first, i.second); + } printf("\n"); } static void test_simple_dither_schedule(int n_planes, int pixels_across) { auto ss = piomatter::make_simple_schedule(n_planes, pixels_across); print_dither_schedule(ss); + printf("\n"); } static void test_temporal_dither_schedule(int n_planes, int pixels_across, int n_temporal_frames) { auto ss = piomatter::make_temporal_dither_schedule(n_planes, pixels_across, n_temporal_frames); print_dither_schedule(ss); + printf("\n"); } int main(int argc, char **argv) { int n = argc > 1 ? atoi(argv[1]) : 0; - test_simple_dither_schedule(5, 1); - test_temporal_dither_schedule(5, 1, 0); - test_temporal_dither_schedule(5, 1, 2); - test_temporal_dither_schedule(5, 1, 4); + test_simple_dither_schedule(7, 1); + test_temporal_dither_schedule(7, 1, 2); + test_temporal_dither_schedule(7, 1, 3); + test_temporal_dither_schedule(7, 1, 4); + test_temporal_dither_schedule(7, 1, 5); + return 0; test_simple_dither_schedule(6, 1); test_temporal_dither_schedule(6, 1, 0); test_temporal_dither_schedule(6, 1, 2); @@ -131,6 +146,7 @@ int main(int argc, char **argv) { test_simple_dither_schedule(5, 16); test_temporal_dither_schedule(5, 16, 2); + test_temporal_dither_schedule(5, 16, 3); test_temporal_dither_schedule(5, 16, 4); test_simple_dither_schedule(5, 24); @@ -140,6 +156,8 @@ int main(int argc, char **argv) { test_simple_dither_schedule(10, 24); test_temporal_dither_schedule(10, 24, 8); + test_temporal_dither_schedule(5, 128, 3); + test_temporal_dither_schedule(5, 192, 3); test_temporal_dither_schedule(5, 128, 4); test_temporal_dither_schedule(5, 192, 4); return 0;