kopia lustrzana https://github.com/pimoroni/pimoroni-pico
Hub75: Performance improvements and stacked mode.
Inline and simplify the pixel flip for a 13.2ms -> 3.8ms speedup at 128x128 on RP2350 stock. Drop RGB565 mode. Add the ability to stack some panels, eg: 2x128x64 in a 128x127 configuration.patch-img-open_file
rodzic
515521c16c
commit
44ffeeed3f
|
@ -37,10 +37,48 @@ Hub75::Hub75(uint width, uint height, Pixel *buffer, PanelType panel_type, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
if (brightness == 0) {
|
if (brightness == 0) {
|
||||||
|
#if PICO_RP2350
|
||||||
|
brightness = 6;
|
||||||
|
#else
|
||||||
if (width >= 64) brightness = 6;
|
if (width >= 64) brightness = 6;
|
||||||
if (width >= 96) brightness = 3;
|
if (width >= 96) brightness = 3;
|
||||||
if (width >= 128) brightness = 2;
|
if (width >= 128) brightness = 2;
|
||||||
if (width >= 160) brightness = 1;
|
if (width >= 160) brightness = 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (color_order) {
|
||||||
|
case COLOR_ORDER::RGB:
|
||||||
|
r_shift = 0;
|
||||||
|
g_shift = 10;
|
||||||
|
b_shift = 20;
|
||||||
|
break;
|
||||||
|
case COLOR_ORDER::RBG:
|
||||||
|
r_shift = 0;
|
||||||
|
g_shift = 20;
|
||||||
|
b_shift = 10;
|
||||||
|
break;
|
||||||
|
case COLOR_ORDER::GRB:
|
||||||
|
r_shift = 20;
|
||||||
|
g_shift = 0;
|
||||||
|
b_shift = 10;
|
||||||
|
break;
|
||||||
|
case COLOR_ORDER::GBR:
|
||||||
|
r_shift = 10;
|
||||||
|
g_shift = 20;
|
||||||
|
b_shift = 0;
|
||||||
|
break;
|
||||||
|
case COLOR_ORDER::BRG:
|
||||||
|
r_shift = 10;
|
||||||
|
g_shift = 00;
|
||||||
|
b_shift = 20;
|
||||||
|
break;
|
||||||
|
case COLOR_ORDER::BGR:
|
||||||
|
r_shift = 20;
|
||||||
|
g_shift = 10;
|
||||||
|
b_shift = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,26 +96,16 @@ void Hub75::set_color(uint x, uint y, Pixel c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hub75::set_pixel(uint x, uint y, uint8_t r, uint8_t g, uint8_t b) {
|
void Hub75::set_pixel(uint x, uint y, uint8_t r, uint8_t g, uint8_t b) {
|
||||||
switch(color_order) {
|
int offset = 0;
|
||||||
case COLOR_ORDER::RGB:
|
if(x >= width || y >= height) return;
|
||||||
set_color(x, y, Pixel(r, g, b));
|
if(y >= height / 2) {
|
||||||
break;
|
y -= height / 2;
|
||||||
case COLOR_ORDER::RBG:
|
offset = (y * width + x) * 2;
|
||||||
set_color(x, y, Pixel(r, b, g));
|
offset += 1;
|
||||||
break;
|
} else {
|
||||||
case COLOR_ORDER::GRB:
|
offset = (y * width + x) * 2;
|
||||||
set_color(x, y, Pixel(g, r, b));
|
|
||||||
break;
|
|
||||||
case COLOR_ORDER::GBR:
|
|
||||||
set_color(x, y, Pixel(g, b, r));
|
|
||||||
break;
|
|
||||||
case COLOR_ORDER::BRG:
|
|
||||||
set_color(x, y, Pixel(b, r, g));
|
|
||||||
break;
|
|
||||||
case COLOR_ORDER::BGR:
|
|
||||||
set_color(x, y, Pixel(b, g, r));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
back_buffer[offset] = (GAMMA_10BIT[b] << b_shift) | (GAMMA_10BIT[g] << g_shift) | (GAMMA_10BIT[r] << r_shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hub75::FM6126A_write_register(uint16_t value, uint8_t position) {
|
void Hub75::FM6126A_write_register(uint16_t value, uint8_t position) {
|
||||||
|
@ -247,28 +275,79 @@ void Hub75::dma_complete() {
|
||||||
|
|
||||||
void Hub75::update(PicoGraphics *graphics) {
|
void Hub75::update(PicoGraphics *graphics) {
|
||||||
if(graphics->pen_type == PicoGraphics::PEN_RGB888) {
|
if(graphics->pen_type == PicoGraphics::PEN_RGB888) {
|
||||||
uint32_t *p = (uint32_t *)graphics->frame_buffer;
|
uint8_t *p = (uint8_t *)graphics->frame_buffer;
|
||||||
for(uint y = 0; y < height; y++) {
|
if(graphics->bounds.w == int32_t(width / 2) && graphics->bounds.h == int32_t(height * 2)) {
|
||||||
for(uint x = 0; x < width; x++) {
|
for(int y = 0; y < graphics->bounds.h; y++) {
|
||||||
uint32_t col = *p;
|
for(int x = 0; x < graphics->bounds.w; x++) {
|
||||||
uint8_t r = (col & 0xff0000) >> 16;
|
int offset = 0;
|
||||||
uint8_t g = (col & 0x00ff00) >> 8;
|
int sy = y;
|
||||||
uint8_t b = (col & 0x0000ff) >> 0;
|
int sx = x;
|
||||||
set_pixel(x, y, r, g, b);
|
uint8_t b = *p++;
|
||||||
p++;
|
uint8_t g = *p++;
|
||||||
|
uint8_t r = *p++;
|
||||||
|
|
||||||
|
// Assuming our canvas is 128x128 and our display is 256x64,
|
||||||
|
// consisting of 2x128x64 panels, remap the bottom half
|
||||||
|
// of the canvas to the right-half of the display,
|
||||||
|
// This gives us an optional square arrangement.
|
||||||
|
if (sy >= int(height)) {
|
||||||
|
sy -= height;
|
||||||
|
sx += width / 2;
|
||||||
|
} else {
|
||||||
|
// Awkward hack to *TEMPORARILY* rotate the top panel
|
||||||
|
sy = height - 1 - sy;
|
||||||
|
sx = (width / 2) - 1 - sx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interlace the top and bottom halves of the panel.
|
||||||
|
// Since these are scanned out simultaneously to two chains
|
||||||
|
// of shift registers we need each pair of rows
|
||||||
|
// (N and N + height / 2) to be adjacent in the buffer.
|
||||||
|
offset = width * 2;
|
||||||
|
if(sy >= int(height / 2)) {
|
||||||
|
sy -= height / 2;
|
||||||
|
offset *= sy;
|
||||||
|
offset += 1;
|
||||||
|
} else {
|
||||||
|
offset *= sy;
|
||||||
|
}
|
||||||
|
offset += sx * 2;
|
||||||
|
|
||||||
|
back_buffer[offset] = (GAMMA_10BIT[b] << b_shift) | (GAMMA_10BIT[g] << g_shift) | (GAMMA_10BIT[r] << r_shift);
|
||||||
|
|
||||||
|
// Skip the empty byte in out 32-bit aligned 24-bit colour.
|
||||||
|
p++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
}
|
for(uint y = 0; y < height; y++) {
|
||||||
else if(graphics->pen_type == PicoGraphics::PEN_RGB565) {
|
for(uint x = 0; x < width; x++) {
|
||||||
uint16_t *p = (uint16_t *)graphics->frame_buffer;
|
int offset = 0;
|
||||||
for(uint y = 0; y < height; y++) {
|
int sy = y;
|
||||||
for(uint x = 0; x < width; x++) {
|
int sx = x;
|
||||||
uint16_t col = __builtin_bswap16(*p);
|
uint8_t b = *p++;
|
||||||
uint8_t r = (col & 0b1111100000000000) >> 8;
|
uint8_t g = *p++;
|
||||||
uint8_t g = (col & 0b0000011111100000) >> 3;
|
uint8_t r = *p++;
|
||||||
uint8_t b = (col & 0b0000000000011111) << 3;
|
|
||||||
set_pixel(x, y, r, g, b);
|
// Interlace the top and bottom halves of the panel.
|
||||||
p++;
|
// Since these are scanned out simultaneously to two chains
|
||||||
|
// of shift registers we need each pair of rows
|
||||||
|
// (N and N + height / 2) to be adjacent in the buffer.
|
||||||
|
offset = width * 2;
|
||||||
|
if(sy >= int(height / 2)) {
|
||||||
|
sy -= height / 2;
|
||||||
|
offset *= sy;
|
||||||
|
offset += 1;
|
||||||
|
} else {
|
||||||
|
offset *= sy;
|
||||||
|
}
|
||||||
|
offset += sx * 2;
|
||||||
|
|
||||||
|
back_buffer[offset] = (GAMMA_10BIT[b] << b_shift) | (GAMMA_10BIT[g] << g_shift) | (GAMMA_10BIT[r] << r_shift);
|
||||||
|
|
||||||
|
// Skip the empty byte in out 32-bit aligned 24-bit colour.
|
||||||
|
p++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,9 @@ class Hub75 {
|
||||||
};
|
};
|
||||||
uint width;
|
uint width;
|
||||||
uint height;
|
uint height;
|
||||||
|
uint r_shift = 0;
|
||||||
|
uint g_shift = 10;
|
||||||
|
uint b_shift = 20;
|
||||||
Pixel *back_buffer;
|
Pixel *back_buffer;
|
||||||
bool managed_buffer = false;
|
bool managed_buffer = false;
|
||||||
PanelType panel_type;
|
PanelType panel_type;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from pimoroni import RGBLED, Button
|
from pimoroni import RGBLED, Button
|
||||||
from picographics import PicoGraphics, DISPLAY_INTERSTATE75_32X32, DISPLAY_INTERSTATE75_64X32, DISPLAY_INTERSTATE75_96X32, DISPLAY_INTERSTATE75_96X48, DISPLAY_INTERSTATE75_128X32, DISPLAY_INTERSTATE75_64X64, DISPLAY_INTERSTATE75_128X64, DISPLAY_INTERSTATE75_192X64, DISPLAY_INTERSTATE75_256X64
|
from picographics import PicoGraphics, DISPLAY_INTERSTATE75_32X32, DISPLAY_INTERSTATE75_64X32, DISPLAY_INTERSTATE75_96X32, DISPLAY_INTERSTATE75_96X48, DISPLAY_INTERSTATE75_128X32, DISPLAY_INTERSTATE75_64X64, DISPLAY_INTERSTATE75_128X64, DISPLAY_INTERSTATE75_192X64, DISPLAY_INTERSTATE75_256X64, DISPLAY_INTERSTATE75_128X128
|
||||||
from pimoroni_i2c import PimoroniI2C
|
from pimoroni_i2c import PimoroniI2C
|
||||||
import hub75
|
import hub75
|
||||||
import sys
|
import sys
|
||||||
|
@ -29,6 +29,7 @@ class Interstate75:
|
||||||
DISPLAY_INTERSTATE75_128X64 = DISPLAY_INTERSTATE75_128X64
|
DISPLAY_INTERSTATE75_128X64 = DISPLAY_INTERSTATE75_128X64
|
||||||
DISPLAY_INTERSTATE75_192X64 = DISPLAY_INTERSTATE75_192X64
|
DISPLAY_INTERSTATE75_192X64 = DISPLAY_INTERSTATE75_192X64
|
||||||
DISPLAY_INTERSTATE75_256X64 = DISPLAY_INTERSTATE75_256X64
|
DISPLAY_INTERSTATE75_256X64 = DISPLAY_INTERSTATE75_256X64
|
||||||
|
DISPLAY_INTERSTATE75_128X128 = DISPLAY_INTERSTATE75_128X128
|
||||||
|
|
||||||
PANEL_GENERIC = hub75.PANEL_GENERIC
|
PANEL_GENERIC = hub75.PANEL_GENERIC
|
||||||
PANEL_FM6126A = hub75.PANEL_FM6126A
|
PANEL_FM6126A = hub75.PANEL_FM6126A
|
||||||
|
@ -46,7 +47,15 @@ class Interstate75:
|
||||||
self.interstate75w = "Pico W" in sys.implementation._machine
|
self.interstate75w = "Pico W" in sys.implementation._machine
|
||||||
self.display = PicoGraphics(display=display)
|
self.display = PicoGraphics(display=display)
|
||||||
self.width, self.height = self.display.get_bounds()
|
self.width, self.height = self.display.get_bounds()
|
||||||
self.hub75 = hub75.Hub75(self.width, self.height, panel_type=panel_type, stb_invert=stb_invert, color_order=color_order)
|
|
||||||
|
out_width = self.width
|
||||||
|
out_height = self.height
|
||||||
|
|
||||||
|
if display == DISPLAY_INTERSTATE75_128X128:
|
||||||
|
out_width = 256
|
||||||
|
out_height = 64
|
||||||
|
|
||||||
|
self.hub75 = hub75.Hub75(out_width, out_height, panel_type=panel_type, stb_invert=stb_invert, color_order=color_order)
|
||||||
self.hub75.start()
|
self.hub75.start()
|
||||||
if self.interstate75w:
|
if self.interstate75w:
|
||||||
self._switch_pins = self.SWITCH_PINS_W
|
self._switch_pins = self.SWITCH_PINS_W
|
||||||
|
|
Ładowanie…
Reference in New Issue