diff --git a/examples-api-use/README.md b/examples-api-use/README.md index c337e3158..32162d2cc 100644 --- a/examples-api-use/README.md +++ b/examples-api-use/README.md @@ -291,16 +291,18 @@ two chains with 8 panels each (`--led-chain=8 --led-parallel=2 --led-pixel-mapper="U-mapper"`). -#### V-mapper (Vertical arrangement) +#### V-mapper and Vmapper:Z (Vertical arrangement) By default, when you add panels on a chain, they are added horizontally. -If you have 2 panels of 64x32, you get 128x32. If you wanted 64x64, you can -use a U-mapper, but it would require that some panels are 'upside down', which -might not be desirable. -The V-mapper allows the stacking to be vertical and not horizontal. +If you have 2 panels of 64x32, you get 128x32. +The V-mapper allows the stacking to be vertical and not horizontal and +get the 64x64 you might want. -Unlike the U mapper, all the panels are correct side up, and you need -more cable length as you need to cross back to the start of the next panel. +By default, all the panels are correct side up, and you need more cable length +as you need to cross back to the start of the next panel. +If you wish to use shorter cables, you can add use Vmapper:Z which will give +you serpentine cabling and every other panel will be upside down (see below +for an example). It is compatible with parallel chains, so you can have multiple stacks of panels all building a coherent overall display. @@ -315,23 +317,31 @@ Here an example with 3 chains of 4 panels (128x64) for a total of about Viewed looking the LED-side of the panels: ``` - [O < I] [O < I] [O < I] - ,---^ ,---^ ,---^ - [O < I] [O < I] [O < I] - ,---^ ,---^ ,---^ - [O < I] [O < I] [O < I] - ,---^ ,---^ ,---^ - [O < I] [O < I] [O < I] - ^ ^ ^ - #1 #2 #3 Pi connector (three parallel chains of len 4) + Vmapper Vmapper:Z + + [O < I] [O < I] [O < I] [I > O] [I > O] [I > O] + ,---^ ,---^ ,---^ ^ ^ ^ + [O < I] [O < I] [O < I] [O < I] [O < I] [O < I] + ,---^ ,---^ ,---^ ^ ^ ^ + [O < I] [O < I] [O < I] [I > O] [I > O] [I > O] + ,---^ ,---^ ,---^ ^ ^ ^ + [O < I] [O < I] [O < I] [O < I] [O < I] [O < I] + ^ ^ ^ ^ ^ ^ + #1 #2 #3 #1 #2 #3 + Pi connector (three parallel chains of len 4) ``` - (This is also a good time to notice that such large arrangement is probably an + (This is also a good time to notice that 384x256 with 12 128x64 panels, is probably an upper limit of what you can reasonably output without having an unusable fresh rate (Try these options to help: --led-pwm-bits=7 --led-pwm-dither-bits=1 and get about 100Hz)). -This can also be used to improve the refresh rate of a long display even -if it is only one panel high (e.g. for a text running output) by +This shows the wiring of a 3x5 Vmapper:Z array built by Marc MERLIN, using 15x 64x32 panels: +![Vmapper_Z_192x160_3x5.jpg](../img/Vmapper_Z_192x160_3x5.jpg) +With --led-pwm-bits=7 --led-pwm-dither-bits=1, it gets a better 300Hz refresh +but only offers around 31K pixels instead of 98K pixels in the previous example. + +Please note that Vmapper can also be used to improve the refresh rate of a long +display even if it is only one panel high (e.g. for a text running output) by splitting the load into multiple parallel chains. ``` diff --git a/img/Vmapper_Z_192x160_3x5.jpg b/img/Vmapper_Z_192x160_3x5.jpg new file mode 100644 index 000000000..0dc52aa2c Binary files /dev/null and b/img/Vmapper_Z_192x160_3x5.jpg differ diff --git a/lib/pixel-mapper.cc b/lib/pixel-mapper.cc index 4c65d9b04..e5161f247 100644 --- a/lib/pixel-mapper.cc +++ b/lib/pixel-mapper.cc @@ -228,6 +228,14 @@ class VerticalMapper : public PixelMapper { virtual bool SetParameters(int chain, int parallel, const char *param) { chain_ = chain; parallel_ = parallel; + // optional argument :Z allow for every other panel to be flipped + // upside down so that cabling can be shorter: + // [ O < I ] without Z [ O < I ] + // ,---^ <---- ^ + // [ O < I ] [ I > O ] + // ,---^ with Z ^ + // [ O < I ] ---> [ O < I ] + z_ = (param && strcmp(param, "Z") == 0) ? 1 : 0; return true; } @@ -237,10 +245,10 @@ class VerticalMapper : public PixelMapper { *visible_width = matrix_width * parallel_ / chain_; *visible_height = matrix_height * chain_ / parallel_; #if 0 - fprintf(stderr, "%s: C:%d P:%d. Turning W:%d H:%d Physical " - "into W:%d H:%d Virtual\n", - GetName(), chain_, parallel_, - *visible_width, *visible_height, matrix_width, matrix_height); + fprintf(stderr, "%s: C:%d P:%d. Turning W:%d H:%d Physical " + "into W:%d H:%d Virtual\n", + GetName(), chain_, parallel_, + *visible_width, *visible_height, matrix_width, matrix_height); #endif return true; } @@ -248,13 +256,26 @@ class VerticalMapper : public PixelMapper { virtual void MapVisibleToMatrix(int matrix_width, int matrix_height, int x, int y, int *matrix_x, int *matrix_y) const { - int panel_width = matrix_width / chain_; - int panel_height = matrix_height / parallel_; + const int panel_width = matrix_width / chain_; + const int panel_height = matrix_height / parallel_; + *matrix_x = (x % panel_width) + int(y/panel_height)* panel_width; *matrix_y = (y % panel_height) + int(x/panel_width) * panel_height; + + const int x_panel_offset_cnt = *matrix_x / panel_width; + + if (z_ && x_panel_offset_cnt % 2) { + const int x_panel_offset = x_panel_offset_cnt * panel_width; + const int y_panel_offset_cnt = *matrix_y / panel_height; + const int y_panel_offset = y_panel_offset_cnt * panel_height; + + *matrix_x = panel_width - (*matrix_x - x_panel_offset) - 1 + x_panel_offset; + *matrix_y = panel_height - (*matrix_y - y_panel_offset) - 1 + y_panel_offset; + } } private: + bool z_; int chain_; int parallel_; };