kopia lustrzana https://github.com/pimoroni/pimoroni-pico
PicoGraphics: Support multiple layers in more types.
rodzic
5e0682bc22
commit
be24eb5d4e
|
@ -165,17 +165,21 @@ namespace pimoroni {
|
|||
|
||||
// Native 16-bit framebuffer update
|
||||
void ST7735::update(PicoGraphics *graphics) {
|
||||
command(reg::RAMWR);
|
||||
gpio_put(dc, 1); // data mode
|
||||
gpio_put(cs, 0);
|
||||
if(graphics->pen_type == PicoGraphics::PEN_RGB565 && graphics->layers == 1) {
|
||||
command(reg::RAMWR, width * height * sizeof(uint16_t), (const char*)graphics->frame_buffer);
|
||||
} else {
|
||||
command(reg::RAMWR);
|
||||
gpio_put(dc, 1); // data mode
|
||||
gpio_put(cs, 0);
|
||||
|
||||
graphics->frame_convert(PicoGraphics::PEN_RGB565, [this](void *data, size_t length) {
|
||||
if (length > 0) {
|
||||
spi_write_blocking(spi, (const uint8_t*)data, length);
|
||||
}
|
||||
});
|
||||
graphics->frame_convert(PicoGraphics::PEN_RGB565, [this](void *data, size_t length) {
|
||||
if (length > 0) {
|
||||
spi_write_blocking(spi, (const uint8_t*)data, length);
|
||||
}
|
||||
});
|
||||
|
||||
gpio_put(cs, 1);
|
||||
gpio_put(cs, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ST7735::set_backlight(uint8_t brightness) {
|
||||
|
|
|
@ -282,26 +282,30 @@ namespace pimoroni {
|
|||
void ST7789::update(PicoGraphics *graphics) {
|
||||
uint8_t cmd = reg::RAMWR;
|
||||
|
||||
gpio_put(dc, 0); // command mode
|
||||
gpio_put(cs, 0);
|
||||
if(spi) { // SPI Bus
|
||||
spi_write_blocking(spi, &cmd, 1);
|
||||
} else { // Parallel Bus
|
||||
write_blocking_parallel(&cmd, 1);
|
||||
if(graphics->pen_type == PicoGraphics::PEN_RGB565 && graphics->layers == 1) { // Display buffer is screen native
|
||||
command(cmd, width * height * sizeof(uint16_t), (const char*)graphics->frame_buffer);
|
||||
} else {
|
||||
gpio_put(dc, 0); // command mode
|
||||
gpio_put(cs, 0);
|
||||
if(spi) { // SPI Bus
|
||||
spi_write_blocking(spi, &cmd, 1);
|
||||
} else { // Parallel Bus
|
||||
write_blocking_parallel(&cmd, 1);
|
||||
}
|
||||
|
||||
gpio_put(dc, 1); // data mode
|
||||
|
||||
graphics->frame_convert(PicoGraphics::PEN_RGB565, [this](void *data, size_t length) {
|
||||
if (length > 0) {
|
||||
write_blocking_dma((const uint8_t*)data, length);
|
||||
}
|
||||
else {
|
||||
dma_channel_wait_for_finish_blocking(st_dma);
|
||||
}
|
||||
});
|
||||
|
||||
gpio_put(cs, 1);
|
||||
}
|
||||
|
||||
gpio_put(dc, 1); // data mode
|
||||
|
||||
graphics->frame_convert(PicoGraphics::PEN_RGB565, [this](void *data, size_t length) {
|
||||
if (length > 0) {
|
||||
write_blocking_dma((const uint8_t*)data, length);
|
||||
}
|
||||
else {
|
||||
dma_channel_wait_for_finish_blocking(st_dma);
|
||||
}
|
||||
});
|
||||
|
||||
gpio_put(cs, 1);
|
||||
}
|
||||
|
||||
void ST7789::set_backlight(uint8_t brightness) {
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace pimoroni {
|
|||
|
||||
void PicoGraphics::set_layer(uint l) {
|
||||
this->layer = l;
|
||||
this->layer_offset = this->bounds.w * this->bounds.h * l;
|
||||
};
|
||||
uint PicoGraphics::get_layer() {
|
||||
return this->layer;
|
||||
|
|
|
@ -79,6 +79,7 @@ namespace pimoroni {
|
|||
}
|
||||
}
|
||||
|
||||
constexpr operator bool() {return r || g || b;};
|
||||
constexpr RGB operator+ (const RGB& c) const {return RGB(r + c.r, g + c.g, b + c.b);}
|
||||
constexpr RGB& operator+=(const RGB& c) {r += c.r; g += c.g; b += c.b; return *this;}
|
||||
constexpr RGB& operator-=(const RGB& c) {r -= c.r; g -= c.g; b -= c.b; return *this;}
|
||||
|
@ -228,6 +229,7 @@ namespace pimoroni {
|
|||
|
||||
uint layers = 1;
|
||||
uint layer = 0;
|
||||
uint layer_offset = 0;
|
||||
|
||||
typedef std::function<void(void *data, size_t length)> conversion_callback_func;
|
||||
typedef std::function<RGB565()> next_pixel_func;
|
||||
|
|
|
@ -59,6 +59,7 @@ namespace pimoroni {
|
|||
|
||||
// pointer to byte in framebuffer that contains this pixel
|
||||
uint8_t *buf = (uint8_t *)frame_buffer;
|
||||
buf += this->layer_offset / 2;
|
||||
uint8_t *f = &buf[i / 2];
|
||||
|
||||
uint8_t o = (~i & 0b1) * 4; // bit offset within byte
|
||||
|
@ -74,6 +75,7 @@ namespace pimoroni {
|
|||
|
||||
// pointer to byte in framebuffer that contains this pixel
|
||||
uint8_t *buf = (uint8_t *)frame_buffer;
|
||||
buf += this->layer_offset / 2;
|
||||
uint8_t *f = &buf[i / 2];
|
||||
|
||||
// doubled up color value, so the color is stored in both nibbles
|
||||
|
@ -144,16 +146,39 @@ namespace pimoroni {
|
|||
uint8_t *src = (uint8_t *)frame_buffer;
|
||||
uint8_t o = 4;
|
||||
|
||||
frame_convert_rgb565(callback, [&]() {
|
||||
uint8_t c = *src;
|
||||
uint8_t b = (c >> o) & 0xf; // bit value shifted to position
|
||||
|
||||
// Increment to next 4-bit entry
|
||||
o ^= 4;
|
||||
if (o != 0) ++src;
|
||||
if(this->layers > 1) {
|
||||
|
||||
return cache[b];
|
||||
});
|
||||
uint offset = this->bounds.w * this->bounds.h / 2;
|
||||
|
||||
frame_convert_rgb565(callback, [&]() {
|
||||
uint8_t b = 0;
|
||||
|
||||
// Iterate through layers in reverse order
|
||||
// Return the first nonzero (not transparent) pixel
|
||||
for(auto layer = this->layers; layer > 0; layer--) {
|
||||
uint8_t c = *(src + offset * (layer - 1));
|
||||
b = (c >> o) & 0xf; // bit value shifted to position
|
||||
if (b) break;
|
||||
}
|
||||
|
||||
// Increment to next 4-bit entry
|
||||
o ^= 4;
|
||||
if (o != 0) src++;
|
||||
|
||||
return cache[b];
|
||||
});
|
||||
} else {
|
||||
frame_convert_rgb565(callback, [&]() {
|
||||
uint8_t c = *src;
|
||||
uint8_t b = (c >> o) & 0xf; // bit value shifted to position
|
||||
|
||||
// Increment to next 4-bit entry
|
||||
o ^= 4;
|
||||
if (o != 0) ++src;
|
||||
|
||||
return cache[b];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,12 +51,14 @@ namespace pimoroni {
|
|||
}
|
||||
void PicoGraphics_PenP8::set_pixel(const Point &p) {
|
||||
uint8_t *buf = (uint8_t *)frame_buffer;
|
||||
buf += this->layer_offset;
|
||||
buf[p.y * bounds.w + p.x] = color;
|
||||
}
|
||||
|
||||
void PicoGraphics_PenP8::set_pixel_span(const Point &p, uint l) {
|
||||
// pointer to byte in framebuffer that contains this pixel
|
||||
uint8_t *buf = (uint8_t *)frame_buffer;
|
||||
buf += this->layer_offset;
|
||||
buf = &buf[p.y * bounds.w + p.x];
|
||||
|
||||
while(l--) {
|
||||
|
@ -103,26 +105,70 @@ namespace pimoroni {
|
|||
}
|
||||
|
||||
void PicoGraphics_PenP8::frame_convert(PenType type, conversion_callback_func callback) {
|
||||
if(type == PEN_RGB565) {
|
||||
// Cache the RGB888 palette as RGB565
|
||||
RGB565 cache[palette_size];
|
||||
for(auto i = 0u; i < palette_size; i++) {
|
||||
cache[i] = palette[i].to_rgb565();
|
||||
// Treat our void* frame_buffer as uint8_t
|
||||
uint8_t *src = (uint8_t *)frame_buffer;
|
||||
|
||||
if(layers > 1) {
|
||||
// The size of a single layer
|
||||
uint offset = this->bounds.w * this->bounds.h;
|
||||
|
||||
if(type == PEN_RGB565) {
|
||||
// Cache the RGB888 palette as RGB565
|
||||
RGB565 cache[palette_size];
|
||||
for(auto i = 0u; i < palette_size; i++) {
|
||||
cache[i] = palette[i].to_rgb565();
|
||||
}
|
||||
|
||||
frame_convert_rgb565(callback, [&]() {
|
||||
// Check the *palette* index, rather than the colour
|
||||
// Thus palette entry 0 is *always* transparent
|
||||
uint8_t c = 0;
|
||||
|
||||
// Iterate through layers in reverse order
|
||||
// Return the first nonzero (not transparent) pixel
|
||||
for(auto layer = this->layers; layer > 0; layer--) {
|
||||
c = *(src + offset * (layer - 1));
|
||||
if (c) break;
|
||||
}
|
||||
|
||||
src++;
|
||||
|
||||
return cache[c];
|
||||
});
|
||||
} else if (type == PEN_RGB888) {
|
||||
frame_convert_rgb888(callback, [&]() {
|
||||
// Check the *palette* index, rather than the colour
|
||||
// Thus palette entry 0 is *always* transparent
|
||||
uint8_t c = 0;
|
||||
|
||||
// Iterate through layers in reverse order
|
||||
// Return the first nonzero (not transparent) pixel
|
||||
for(auto layer = this->layers; layer > 0; layer--) {
|
||||
c = *(src + offset * (layer - 1));
|
||||
if (c) break;
|
||||
}
|
||||
|
||||
src++;
|
||||
|
||||
return palette[c].to_rgb888();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if(type == PEN_RGB565) {
|
||||
// Cache the RGB888 palette as RGB565
|
||||
RGB565 cache[palette_size];
|
||||
for(auto i = 0u; i < palette_size; i++) {
|
||||
cache[i] = palette[i].to_rgb565();
|
||||
}
|
||||
|
||||
// Treat our void* frame_buffer as uint8_t
|
||||
uint8_t *src = (uint8_t *)frame_buffer;
|
||||
|
||||
frame_convert_rgb565(callback, [&]() {
|
||||
return cache[*src++];
|
||||
});
|
||||
} else if (type == PEN_RGB888) {
|
||||
// Treat our void* frame_buffer as uint8_t
|
||||
uint8_t *src = (uint8_t *)frame_buffer;
|
||||
|
||||
frame_convert_rgb888(callback, [&]() {
|
||||
return palette[*src++].to_rgb888();
|
||||
});
|
||||
frame_convert_rgb565(callback, [&]() {
|
||||
return cache[*src++];
|
||||
});
|
||||
} else if (type == PEN_RGB888) {
|
||||
frame_convert_rgb888(callback, [&]() {
|
||||
return palette[*src++].to_rgb888();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,13 +23,13 @@ namespace pimoroni {
|
|||
}
|
||||
void PicoGraphics_PenRGB332::set_pixel(const Point &p) {
|
||||
uint8_t *buf = (uint8_t *)frame_buffer;
|
||||
buf += buffer_size(this->bounds.w, this->bounds.h) * layer;
|
||||
buf += this->layer_offset;
|
||||
buf[p.y * bounds.w + p.x] = color;
|
||||
}
|
||||
void PicoGraphics_PenRGB332::set_pixel_span(const Point &p, uint l) {
|
||||
// pointer to byte in framebuffer that contains this pixel
|
||||
uint8_t *buf = (uint8_t *)frame_buffer;
|
||||
buf += buffer_size(this->bounds.w, this->bounds.h) * layer;
|
||||
buf += this->layer_offset;
|
||||
buf += p.y * bounds.w + p.x;
|
||||
|
||||
while(l--) {
|
||||
|
@ -40,7 +40,7 @@ namespace pimoroni {
|
|||
if(!bounds.contains(p)) return;
|
||||
|
||||
uint8_t *buf = (uint8_t *)frame_buffer;
|
||||
buf += buffer_size(this->bounds.w, this->bounds.h) * layer;
|
||||
buf += this->layer_offset;
|
||||
|
||||
RGB332 blended = RGB(buf[p.y * bounds.w + p.x]).blend(RGB(color), a).to_rgb332();
|
||||
|
||||
|
@ -99,14 +99,23 @@ namespace pimoroni {
|
|||
// Treat our void* frame_buffer as uint8_t
|
||||
uint8_t *src = (uint8_t *)frame_buffer;
|
||||
|
||||
if(this->layers > 1) {
|
||||
// Assume only two layers for now
|
||||
uint8_t *src_layer2 = src + buffer_size(this->bounds.w, this->bounds.h);
|
||||
if(this->layers > 1) {
|
||||
// The size of a single layer
|
||||
uint offset = this->bounds.w * this->bounds.h;
|
||||
|
||||
frame_convert_rgb565(callback, [&]() {
|
||||
RGB565 c1 = rgb332_to_rgb565_lut[*src++];
|
||||
RGB565 c2 = rgb332_to_rgb565_lut[*src_layer2++];
|
||||
return c2 ? c2 : c1;
|
||||
uint8_t c = 0;
|
||||
|
||||
// Iterate through layers in reverse order
|
||||
// Return the first nonzero (not transparent) pixel
|
||||
for(auto layer = this->layers; layer > 0; layer--) {
|
||||
c = *(src + offset * (layer - 1));
|
||||
if (c) break;
|
||||
}
|
||||
|
||||
src++;
|
||||
|
||||
return rgb332_to_rgb565_lut[c];
|
||||
});
|
||||
} else {
|
||||
frame_convert_rgb565(callback, [&]() {
|
||||
|
|
|
@ -24,14 +24,14 @@ namespace pimoroni {
|
|||
void PicoGraphics_PenRGB565::set_pixel(const Point &p) {
|
||||
uint16_t *buf = (uint16_t *)frame_buffer;
|
||||
// We can't use buffer_size because our pointer is uint16_t
|
||||
buf += this->bounds.w * this->bounds.h * layer;
|
||||
buf += this->layer_offset;
|
||||
buf[p.y * bounds.w + p.x] = color;
|
||||
}
|
||||
void PicoGraphics_PenRGB565::set_pixel_span(const Point &p, uint l) {
|
||||
// pointer to byte in framebuffer that contains this pixel
|
||||
uint16_t *buf = (uint16_t *)frame_buffer;
|
||||
// We can't use buffer_size because our pointer is uint16_t
|
||||
buf += this->bounds.w * this->bounds.h * layer;
|
||||
buf += this->layer_offset;
|
||||
buf = &buf[p.y * bounds.w + p.x];
|
||||
|
||||
while(l--) {
|
||||
|
@ -45,10 +45,8 @@ namespace pimoroni {
|
|||
|
||||
if(layers > 1) {
|
||||
// Assume only two layers for now
|
||||
uint16_t *src_layer2 = src;
|
||||
|
||||
// We can't use buffer_size because our pointer is uint16_t
|
||||
src_layer2 += this->bounds.w * this->bounds.h * layer;
|
||||
uint16_t *src_layer2 = src + this->bounds.w * this->bounds.h;
|
||||
|
||||
frame_convert_rgb565(callback, [&]() {
|
||||
RGB565 c1 = *src++;
|
||||
|
|
|
@ -23,11 +23,13 @@ namespace pimoroni {
|
|||
}
|
||||
void PicoGraphics_PenRGB888::set_pixel(const Point &p) {
|
||||
uint32_t *buf = (uint32_t *)frame_buffer;
|
||||
buf += this->layer_offset;
|
||||
buf[p.y * bounds.w + p.x] = color;
|
||||
}
|
||||
void PicoGraphics_PenRGB888::set_pixel_span(const Point &p, uint l) {
|
||||
// pointer to byte in framebuffer that contains this pixel
|
||||
uint32_t *buf = (uint32_t *)frame_buffer;
|
||||
buf += this->layer_offset;
|
||||
buf = &buf[p.y * bounds.w + p.x];
|
||||
|
||||
while(l--) {
|
||||
|
|
Ładowanie…
Reference in New Issue