diff --git a/drivers/st7735/st7735.cpp b/drivers/st7735/st7735.cpp index d2cabff7..1ae5728e 100644 --- a/drivers/st7735/st7735.cpp +++ b/drivers/st7735/st7735.cpp @@ -165,21 +165,17 @@ namespace pimoroni { // Native 16-bit framebuffer update void ST7735::update(PicoGraphics *graphics) { - if(graphics->pen_type == PicoGraphics::PEN_RGB565) { - 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); + 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) { diff --git a/drivers/st7789/st7789.cpp b/drivers/st7789/st7789.cpp index ed34447c..b76f9b07 100644 --- a/drivers/st7789/st7789.cpp +++ b/drivers/st7789/st7789.cpp @@ -282,30 +282,26 @@ namespace pimoroni { void ST7789::update(PicoGraphics *graphics) { uint8_t cmd = reg::RAMWR; - if(graphics->pen_type == PicoGraphics::PEN_RGB565) { // 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, 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); } void ST7789::set_backlight(uint8_t brightness) { diff --git a/libraries/pico_graphics/pico_graphics.cpp b/libraries/pico_graphics/pico_graphics.cpp index 4e32e4ec..58ae1ba7 100644 --- a/libraries/pico_graphics/pico_graphics.cpp +++ b/libraries/pico_graphics/pico_graphics.cpp @@ -19,6 +19,13 @@ namespace pimoroni { RGB* PicoGraphics::get_palette() {return nullptr;} bool PicoGraphics::supports_alpha_blend() {return false;} + void PicoGraphics::set_layer(uint l) { + this->layer = l; + }; + uint PicoGraphics::get_layer() { + return this->layer; + }; + void PicoGraphics::set_dimensions(int width, int height) { bounds = clip = {0, 0, width, height}; } diff --git a/libraries/pico_graphics/pico_graphics.hpp b/libraries/pico_graphics/pico_graphics.hpp index d6fadc08..66d74254 100644 --- a/libraries/pico_graphics/pico_graphics.hpp +++ b/libraries/pico_graphics/pico_graphics.hpp @@ -226,6 +226,9 @@ namespace pimoroni { Rect clip; uint thickness = 1; + uint layers = 1; + uint layer = 0; + typedef std::function conversion_callback_func; typedef std::function next_pixel_func; typedef std::function next_pixel_func_rgb888; @@ -270,6 +273,12 @@ namespace pimoroni { PicoGraphics(uint16_t width, uint16_t height, void *frame_buffer) : frame_buffer(frame_buffer), bounds(0, 0, width, height), clip(0, 0, width, height) { set_font(&font6); + layers = 1; + }; + + PicoGraphics(uint16_t width, uint16_t height, uint16_t layers, void *frame_buffer) + : frame_buffer(frame_buffer), bounds(0, 0, width, height), clip(0, 0, width, height), layers(layers) { + set_font(&font6); }; virtual void set_pen(uint c) = 0; @@ -278,6 +287,9 @@ namespace pimoroni { virtual void set_pixel_span(const Point &p, uint l) = 0; void set_thickness(uint t); + void set_layer(uint l); + uint get_layer(); + virtual int get_palette_size(); virtual RGB* get_palette(); virtual bool supports_alpha_blend(); @@ -330,7 +342,7 @@ namespace pimoroni { public: uint8_t color; - PicoGraphics_Pen1Bit(uint16_t width, uint16_t height, void *frame_buffer); + PicoGraphics_Pen1Bit(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers = 1); void set_pen(uint c) override; void set_pen(uint8_t r, uint8_t g, uint8_t b) override; @@ -346,7 +358,7 @@ namespace pimoroni { public: uint8_t color; - PicoGraphics_Pen1BitY(uint16_t width, uint16_t height, void *frame_buffer); + PicoGraphics_Pen1BitY(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers = 1); void set_pen(uint c) override; void set_pen(uint8_t r, uint8_t g, uint8_t b) override; @@ -387,7 +399,7 @@ namespace pimoroni { bool cache_built = false; std::array candidates; - PicoGraphics_Pen3Bit(uint16_t width, uint16_t height, void *frame_buffer); + PicoGraphics_Pen3Bit(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers = 1); void set_pen(uint c) override; void set_pen(uint8_t r, uint8_t g, uint8_t b) override; @@ -420,7 +432,7 @@ namespace pimoroni { bool cache_built = false; std::array candidates; - PicoGraphics_PenP4(uint16_t width, uint16_t height, void *frame_buffer); + PicoGraphics_PenP4(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers = 1); void set_pen(uint c) override; void set_pen(uint8_t r, uint8_t g, uint8_t b) override; int update_pen(uint8_t i, uint8_t r, uint8_t g, uint8_t b) override; @@ -453,7 +465,7 @@ namespace pimoroni { bool cache_built = false; std::array candidates; - PicoGraphics_PenP8(uint16_t width, uint16_t height, void *frame_buffer); + PicoGraphics_PenP8(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers = 1); void set_pen(uint c) override; void set_pen(uint8_t r, uint8_t g, uint8_t b) override; int update_pen(uint8_t i, uint8_t r, uint8_t g, uint8_t b) override; @@ -478,7 +490,7 @@ namespace pimoroni { class PicoGraphics_PenRGB332 : public PicoGraphics { public: RGB332 color; - PicoGraphics_PenRGB332(uint16_t width, uint16_t height, void *frame_buffer); + PicoGraphics_PenRGB332(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers = 1); void set_pen(uint c) override; void set_pen(uint8_t r, uint8_t g, uint8_t b) override; int create_pen(uint8_t r, uint8_t g, uint8_t b) override; @@ -503,7 +515,7 @@ namespace pimoroni { public: RGB src_color; RGB565 color; - PicoGraphics_PenRGB565(uint16_t width, uint16_t height, void *frame_buffer); + PicoGraphics_PenRGB565(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers = 1); void set_pen(uint c) override; void set_pen(uint8_t r, uint8_t g, uint8_t b) override; int create_pen(uint8_t r, uint8_t g, uint8_t b) override; @@ -516,13 +528,15 @@ namespace pimoroni { static size_t buffer_size(uint w, uint h) { return w * h * sizeof(RGB565); } + + void frame_convert(PenType type, conversion_callback_func callback) override; }; class PicoGraphics_PenRGB888 : public PicoGraphics { public: RGB src_color; RGB888 color; - PicoGraphics_PenRGB888(uint16_t width, uint16_t height, void *frame_buffer); + PicoGraphics_PenRGB888(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers = 1); void set_pen(uint c) override; void set_pen(uint8_t r, uint8_t g, uint8_t b) override; int create_pen(uint8_t r, uint8_t g, uint8_t b) override; @@ -600,7 +614,7 @@ namespace pimoroni { uint color; IDirectDisplayDriver &driver; - PicoGraphics_PenInky7(uint16_t width, uint16_t height, IDirectDisplayDriver &direct_display_driver); + PicoGraphics_PenInky7(uint16_t width, uint16_t height, IDirectDisplayDriver &direct_display_driver, uint16_t layers = 1); void set_pen(uint c) override; void set_pen(uint8_t r, uint8_t g, uint8_t b) override; int create_pen(uint8_t r, uint8_t g, uint8_t b) override; diff --git a/libraries/pico_graphics/pico_graphics_pen_1bit.cpp b/libraries/pico_graphics/pico_graphics_pen_1bit.cpp index 30fb1e53..e05b2a37 100644 --- a/libraries/pico_graphics/pico_graphics_pen_1bit.cpp +++ b/libraries/pico_graphics/pico_graphics_pen_1bit.cpp @@ -2,11 +2,11 @@ namespace pimoroni { - PicoGraphics_Pen1Bit::PicoGraphics_Pen1Bit(uint16_t width, uint16_t height, void *frame_buffer) - : PicoGraphics(width, height, frame_buffer) { + PicoGraphics_Pen1Bit::PicoGraphics_Pen1Bit(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers) + : PicoGraphics(width, height, layers, frame_buffer) { this->pen_type = PEN_1BIT; if(this->frame_buffer == nullptr) { - this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]); + this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height) * layers]); } } diff --git a/libraries/pico_graphics/pico_graphics_pen_1bitY.cpp b/libraries/pico_graphics/pico_graphics_pen_1bitY.cpp index 6fc2cb8c..6efdde92 100644 --- a/libraries/pico_graphics/pico_graphics_pen_1bitY.cpp +++ b/libraries/pico_graphics/pico_graphics_pen_1bitY.cpp @@ -2,8 +2,8 @@ namespace pimoroni { - PicoGraphics_Pen1BitY::PicoGraphics_Pen1BitY(uint16_t width, uint16_t height, void *frame_buffer) - : PicoGraphics(width, height, frame_buffer) { + PicoGraphics_Pen1BitY::PicoGraphics_Pen1BitY(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers) + : PicoGraphics(width, height, layers, frame_buffer) { this->pen_type = PEN_1BIT; if(this->frame_buffer == nullptr) { this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]); diff --git a/libraries/pico_graphics/pico_graphics_pen_3bit.cpp b/libraries/pico_graphics/pico_graphics_pen_3bit.cpp index 5faba1cd..dc67018b 100644 --- a/libraries/pico_graphics/pico_graphics_pen_3bit.cpp +++ b/libraries/pico_graphics/pico_graphics_pen_3bit.cpp @@ -2,8 +2,8 @@ namespace pimoroni { - PicoGraphics_Pen3Bit::PicoGraphics_Pen3Bit(uint16_t width, uint16_t height, void *frame_buffer) - : PicoGraphics(width, height, frame_buffer) { + PicoGraphics_Pen3Bit::PicoGraphics_Pen3Bit(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers) + : PicoGraphics(width, height, layers, frame_buffer) { this->pen_type = PEN_3BIT; if(this->frame_buffer == nullptr) { this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]); diff --git a/libraries/pico_graphics/pico_graphics_pen_inky7.cpp b/libraries/pico_graphics/pico_graphics_pen_inky7.cpp index 9a6ae5b0..e41de871 100644 --- a/libraries/pico_graphics/pico_graphics_pen_inky7.cpp +++ b/libraries/pico_graphics/pico_graphics_pen_inky7.cpp @@ -1,8 +1,8 @@ #include "pico_graphics.hpp" namespace pimoroni { - PicoGraphics_PenInky7::PicoGraphics_PenInky7(uint16_t width, uint16_t height, IDirectDisplayDriver &direct_display_driver) - : PicoGraphics(width, height, nullptr), + PicoGraphics_PenInky7::PicoGraphics_PenInky7(uint16_t width, uint16_t height, IDirectDisplayDriver &direct_display_driver, uint16_t layers) + : PicoGraphics(width, height, layers, nullptr), driver(direct_display_driver) { this->pen_type = PEN_INKY7; } diff --git a/libraries/pico_graphics/pico_graphics_pen_p4.cpp b/libraries/pico_graphics/pico_graphics_pen_p4.cpp index dfba55af..fbeafd40 100644 --- a/libraries/pico_graphics/pico_graphics_pen_p4.cpp +++ b/libraries/pico_graphics/pico_graphics_pen_p4.cpp @@ -2,8 +2,8 @@ namespace pimoroni { - PicoGraphics_PenP4::PicoGraphics_PenP4(uint16_t width, uint16_t height, void *frame_buffer) - : PicoGraphics(width, height, frame_buffer) { + PicoGraphics_PenP4::PicoGraphics_PenP4(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers) + : PicoGraphics(width, height, layers, frame_buffer) { this->pen_type = PEN_P4; if(this->frame_buffer == nullptr) { this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]); diff --git a/libraries/pico_graphics/pico_graphics_pen_p8.cpp b/libraries/pico_graphics/pico_graphics_pen_p8.cpp index f7d0be73..b93f835b 100644 --- a/libraries/pico_graphics/pico_graphics_pen_p8.cpp +++ b/libraries/pico_graphics/pico_graphics_pen_p8.cpp @@ -1,8 +1,8 @@ #include "pico_graphics.hpp" namespace pimoroni { - PicoGraphics_PenP8::PicoGraphics_PenP8(uint16_t width, uint16_t height, void *frame_buffer) - : PicoGraphics(width, height, frame_buffer) { + PicoGraphics_PenP8::PicoGraphics_PenP8(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers) + : PicoGraphics(width, height, layers, frame_buffer) { this->pen_type = PEN_P8; if(this->frame_buffer == nullptr) { this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]); diff --git a/libraries/pico_graphics/pico_graphics_pen_rgb332.cpp b/libraries/pico_graphics/pico_graphics_pen_rgb332.cpp index 1bce808f..58afcae8 100644 --- a/libraries/pico_graphics/pico_graphics_pen_rgb332.cpp +++ b/libraries/pico_graphics/pico_graphics_pen_rgb332.cpp @@ -2,11 +2,11 @@ #include namespace pimoroni { - PicoGraphics_PenRGB332::PicoGraphics_PenRGB332(uint16_t width, uint16_t height, void *frame_buffer) - : PicoGraphics(width, height, frame_buffer) { + PicoGraphics_PenRGB332::PicoGraphics_PenRGB332(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers) + : PicoGraphics(width, height, layers, frame_buffer) { this->pen_type = PEN_RGB332; if(this->frame_buffer == nullptr) { - this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]); + this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height) * layers]); } } void PicoGraphics_PenRGB332::set_pen(uint c) { @@ -23,12 +23,14 @@ 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[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 = &buf[p.y * bounds.w + p.x]; + buf += buffer_size(this->bounds.w, this->bounds.h) * layer; + buf += p.y * bounds.w + p.x; while(l--) { *buf++ = color; @@ -38,6 +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; RGB332 blended = RGB(buf[p.y * bounds.w + p.x]).blend(RGB(color), a).to_rgb332(); @@ -96,9 +99,20 @@ namespace pimoroni { // Treat our void* frame_buffer as uint8_t uint8_t *src = (uint8_t *)frame_buffer; - frame_convert_rgb565(callback, [&]() { - return rgb332_to_rgb565_lut[*src++]; - }); + if(this->layers > 1) { + // Assume only two layers for now + uint8_t *src_layer2 = src + buffer_size(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; + }); + } else { + frame_convert_rgb565(callback, [&]() { + return rgb332_to_rgb565_lut[*src++]; + }); + } } } void PicoGraphics_PenRGB332::sprite(void* data, const Point &sprite, const Point &dest, const int scale, const int transparent) { diff --git a/libraries/pico_graphics/pico_graphics_pen_rgb565.cpp b/libraries/pico_graphics/pico_graphics_pen_rgb565.cpp index 30ef5bed..fb7b37e3 100644 --- a/libraries/pico_graphics/pico_graphics_pen_rgb565.cpp +++ b/libraries/pico_graphics/pico_graphics_pen_rgb565.cpp @@ -1,8 +1,8 @@ #include "pico_graphics.hpp" namespace pimoroni { - PicoGraphics_PenRGB565::PicoGraphics_PenRGB565(uint16_t width, uint16_t height, void *frame_buffer) - : PicoGraphics(width, height, frame_buffer) { + PicoGraphics_PenRGB565::PicoGraphics_PenRGB565(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers) + : PicoGraphics(width, height, layers, frame_buffer) { this->pen_type = PEN_RGB565; if(this->frame_buffer == nullptr) { this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]); @@ -23,11 +23,15 @@ 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[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 = &buf[p.y * bounds.w + p.x]; while(l--) { @@ -35,26 +39,50 @@ namespace pimoroni { } } + void PicoGraphics_PenRGB565::frame_convert(PenType type, conversion_callback_func callback) { + if(type == PEN_RGB565) { + // Treat our void* frame_buffer as uint8_t + uint16_t *src = (uint16_t *)frame_buffer; - void PicoGraphics_PenRGB565::sprite(void* data, const Point &sprite, const Point &dest, const int scale, const int transparent) { - //int sprite_x = (sprite & 0x0f) << 3; - //int sprite_y = (sprite & 0xf0) >> 1; - Point s { - sprite.x << 3, - sprite.y << 3 - }; - RGB565 *ptr = (RGB565 *)data; - Point o = {0, 0}; - for(o.y = 0; o.y < 8 * scale; o.y++) { - Point so = { - 0, - o.y / scale - }; - for(o.x = 0; o.x < 8 * scale; o.x++) { - so.x = o.x / scale; - color = ptr[(s.y + so.y) * 128 + (s.x + so.x)]; - if(color != transparent) pixel(dest + o); - } - } - } + 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; + + frame_convert_rgb565(callback, [&]() { + RGB565 c1 = *src++; + RGB565 c2 = *src_layer2++; + return c2 ? c2 : c1; + }); + } else { + frame_convert_rgb565(callback, [&]() { + return *src++; + }); + } + } + } + + void PicoGraphics_PenRGB565::sprite(void* data, const Point &sprite, const Point &dest, const int scale, const int transparent) { + //int sprite_x = (sprite & 0x0f) << 3; + //int sprite_y = (sprite & 0xf0) >> 1; + Point s { + sprite.x << 3, + sprite.y << 3 + }; + RGB565 *ptr = (RGB565 *)data; + Point o = {0, 0}; + for(o.y = 0; o.y < 8 * scale; o.y++) { + Point so = { + 0, + o.y / scale + }; + for(o.x = 0; o.x < 8 * scale; o.x++) { + so.x = o.x / scale; + color = ptr[(s.y + so.y) * 128 + (s.x + so.x)]; + if(color != transparent) pixel(dest + o); + } + } + } } diff --git a/libraries/pico_graphics/pico_graphics_pen_rgb888.cpp b/libraries/pico_graphics/pico_graphics_pen_rgb888.cpp index 6cc9d2ad..6f536064 100644 --- a/libraries/pico_graphics/pico_graphics_pen_rgb888.cpp +++ b/libraries/pico_graphics/pico_graphics_pen_rgb888.cpp @@ -1,8 +1,8 @@ #include "pico_graphics.hpp" namespace pimoroni { - PicoGraphics_PenRGB888::PicoGraphics_PenRGB888(uint16_t width, uint16_t height, void *frame_buffer) - : PicoGraphics(width, height, frame_buffer) { + PicoGraphics_PenRGB888::PicoGraphics_PenRGB888(uint16_t width, uint16_t height, void *frame_buffer, uint16_t layers) + : PicoGraphics(width, height, layers, frame_buffer) { this->pen_type = PEN_RGB888; if(this->frame_buffer == nullptr) { this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]); diff --git a/micropython/modules/picographics/picographics.c b/micropython/modules/picographics/picographics.c index 0074b55f..ad6d0dc5 100644 --- a/micropython/modules/picographics/picographics.c +++ b/micropython/modules/picographics/picographics.c @@ -24,6 +24,9 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_create_pen_obj, 4, 4, ModPic MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_create_pen_hsv_obj, 4, 4, ModPicoGraphics_create_pen_hsv); MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_set_thickness_obj, ModPicoGraphics_set_thickness); +// Layers +MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_set_layer_obj, ModPicoGraphics_set_layer); + // Primitives MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_set_clip_obj, 5, 5, ModPicoGraphics_set_clip); MP_DEFINE_CONST_FUN_OBJ_1(ModPicoGraphics_remove_clip_obj, ModPicoGraphics_remove_clip); @@ -60,6 +63,8 @@ static const mp_rom_map_elem_t ModPicoGraphics_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_set_thickness), MP_ROM_PTR(&ModPicoGraphics_set_thickness_obj) }, { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&ModPicoGraphics_clear_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_layer), MP_ROM_PTR(&ModPicoGraphics_set_layer_obj) }, + { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&ModPicoGraphics_update_obj) }, { MP_ROM_QSTR(MP_QSTR_partial_update), MP_ROM_PTR(&ModPicoGraphics_partial_update_obj) }, { MP_ROM_QSTR(MP_QSTR_set_update_speed), MP_ROM_PTR(&ModPicoGraphics_set_update_speed_obj) }, diff --git a/micropython/modules/picographics/picographics.cpp b/micropython/modules/picographics/picographics.cpp index a55e8ad4..8ac300cf 100644 --- a/micropython/modules/picographics/picographics.cpp +++ b/micropython/modules/picographics/picographics.cpp @@ -254,24 +254,24 @@ bool get_display_settings(PicoGraphicsDisplay display, int &width, int &height, return true; } -size_t get_required_buffer_size(PicoGraphicsPenType pen_type, uint width, uint height) { +size_t get_required_buffer_size(PicoGraphicsPenType pen_type, uint width, uint height, uint layers) { switch(pen_type) { case PEN_1BIT: - return PicoGraphics_Pen1Bit::buffer_size(width, height); + return PicoGraphics_Pen1Bit::buffer_size(width, height) * layers; case PEN_3BIT: - return PicoGraphics_Pen3Bit::buffer_size(width, height); + return PicoGraphics_Pen3Bit::buffer_size(width, height) * layers; case PEN_P4: - return PicoGraphics_PenP4::buffer_size(width, height); + return PicoGraphics_PenP4::buffer_size(width, height) * layers; case PEN_P8: - return PicoGraphics_PenP8::buffer_size(width, height); + return PicoGraphics_PenP8::buffer_size(width, height) * layers; case PEN_RGB332: - return PicoGraphics_PenRGB332::buffer_size(width, height); + return PicoGraphics_PenRGB332::buffer_size(width, height) * layers; case PEN_RGB565: - return PicoGraphics_PenRGB565::buffer_size(width, height); + return PicoGraphics_PenRGB565::buffer_size(width, height) * layers; case PEN_RGB888: - return PicoGraphics_PenRGB888::buffer_size(width, height); + return PicoGraphics_PenRGB888::buffer_size(width, height) * layers; case PEN_INKY7: - return PicoGraphics_PenInky7::buffer_size(width, height); + return PicoGraphics_PenInky7::buffer_size(width, height) * layers; default: return 0; } @@ -280,7 +280,7 @@ size_t get_required_buffer_size(PicoGraphicsPenType pen_type, uint width, uint h mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { ModPicoGraphics_obj_t *self = nullptr; - enum { ARG_display, ARG_rotate, ARG_bus, ARG_buffer, ARG_pen_type, ARG_extra_pins, ARG_i2c_address }; + enum { ARG_display, ARG_rotate, ARG_bus, ARG_buffer, ARG_pen_type, ARG_extra_pins, ARG_i2c_address, ARG_layers }; static const mp_arg_t allowed_args[] = { { MP_QSTR_display, MP_ARG_INT | MP_ARG_REQUIRED }, { MP_QSTR_rotate, MP_ARG_INT, { .u_int = -1 } }, @@ -289,6 +289,7 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size { MP_QSTR_pen_type, MP_ARG_INT, { .u_int = -1 } }, { MP_QSTR_extra_pins, MP_ARG_OBJ, { .u_obj = mp_const_none } }, { MP_QSTR_i2c_address, MP_ARG_INT, { .u_int = -1 } }, + { MP_QSTR_layers, MP_ARG_INT, { .u_int = 1 } }, }; // Parse args. @@ -304,6 +305,7 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size int height = 0; int pen_type = args[ARG_pen_type].u_int; int rotate = args[ARG_rotate].u_int; + int layers = args[ARG_layers].u_int; PicoGraphicsBusType bus_type = BUS_SPI; if(!get_display_settings(display, width, height, rotate, pen_type, bus_type)) mp_raise_ValueError("Unsupported display!"); if(rotate == -1) rotate = (int)Rotation::ROTATE_0; @@ -395,7 +397,7 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size } // Create or fetch buffer - size_t required_size = get_required_buffer_size((PicoGraphicsPenType)pen_type, width, height); + size_t required_size = get_required_buffer_size((PicoGraphicsPenType)pen_type, width, height, layers); if(required_size == 0) mp_raise_ValueError("Unsupported pen type!"); if(pen_type == PEN_INKY7) { @@ -418,31 +420,31 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size switch((PicoGraphicsPenType)pen_type) { case PEN_1BIT: if (display == DISPLAY_INKY_PACK) { - self->graphics = m_new_class(PicoGraphics_Pen1BitY, self->display->width, self->display->height, self->buffer); + self->graphics = m_new_class(PicoGraphics_Pen1BitY, self->display->width, self->display->height, self->buffer, layers); } else { - self->graphics = m_new_class(PicoGraphics_Pen1Bit, self->display->width, self->display->height, self->buffer); + self->graphics = m_new_class(PicoGraphics_Pen1Bit, self->display->width, self->display->height, self->buffer, layers); } break; case PEN_3BIT: - self->graphics = m_new_class(PicoGraphics_Pen3Bit, self->display->width, self->display->height, self->buffer); + self->graphics = m_new_class(PicoGraphics_Pen3Bit, self->display->width, self->display->height, self->buffer, layers); break; case PEN_P4: - self->graphics = m_new_class(PicoGraphics_PenP4, self->display->width, self->display->height, self->buffer); + self->graphics = m_new_class(PicoGraphics_PenP4, self->display->width, self->display->height, self->buffer, layers); break; case PEN_P8: - self->graphics = m_new_class(PicoGraphics_PenP8, self->display->width, self->display->height, self->buffer); + self->graphics = m_new_class(PicoGraphics_PenP8, self->display->width, self->display->height, self->buffer, layers); break; case PEN_RGB332: - self->graphics = m_new_class(PicoGraphics_PenRGB332, self->display->width, self->display->height, self->buffer); + self->graphics = m_new_class(PicoGraphics_PenRGB332, self->display->width, self->display->height, self->buffer, layers); break; case PEN_RGB565: - self->graphics = m_new_class(PicoGraphics_PenRGB565, self->display->width, self->display->height, self->buffer); + self->graphics = m_new_class(PicoGraphics_PenRGB565, self->display->width, self->display->height, self->buffer, layers); break; case PEN_RGB888: - self->graphics = m_new_class(PicoGraphics_PenRGB888, self->display->width, self->display->height, self->buffer); + self->graphics = m_new_class(PicoGraphics_PenRGB888, self->display->width, self->display->height, self->buffer, layers); break; case PEN_INKY7: - self->graphics = m_new_class(PicoGraphics_PenInky7, self->display->width, self->display->height, *(IDirectDisplayDriver *)self->buffer); + self->graphics = m_new_class(PicoGraphics_PenInky7, self->display->width, self->display->height, *(IDirectDisplayDriver *)self->buffer, layers); break; default: break; @@ -453,8 +455,15 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size self->spritedata = nullptr; // Clear the buffer + self->graphics->set_layer(0); self->graphics->set_pen(0); self->graphics->clear(); + if(layers > 1) { + self->graphics->set_layer(1); + self->graphics->set_pen(0); + self->graphics->clear(); + self->graphics->set_layer(0); + } // Update the LCD from the graphics library if (display != DISPLAY_INKY_FRAME && display != DISPLAY_INKY_FRAME_4 && display != DISPLAY_INKY_PACK && display != DISPLAY_INKY_FRAME_7) { @@ -477,7 +486,7 @@ mp_obj_t ModPicoGraphics_set_spritesheet(mp_obj_t self_in, mp_obj_t spritedata) mp_buffer_info_t bufinfo; mp_get_buffer_raise(spritedata, &bufinfo, MP_BUFFER_RW); - int required_size = get_required_buffer_size((PicoGraphicsPenType)self->graphics->pen_type, 128, 128); + int required_size = get_required_buffer_size((PicoGraphicsPenType)self->graphics->pen_type, 128, 128, 1); if(bufinfo.len != (size_t)(required_size)) { mp_raise_ValueError("Spritesheet the wrong size!"); @@ -562,7 +571,7 @@ mp_int_t ModPicoGraphics_get_framebuffer(mp_obj_t self_in, mp_buffer_info_t *buf mp_raise_ValueError("No local framebuffer."); } bufinfo->buf = self->graphics->frame_buffer; - bufinfo->len = get_required_buffer_size((PicoGraphicsPenType)self->graphics->pen_type, self->graphics->bounds.w, self->graphics->bounds.h); + bufinfo->len = get_required_buffer_size((PicoGraphicsPenType)self->graphics->pen_type, self->graphics->bounds.w, self->graphics->bounds.h, 1); bufinfo->typecode = 'B'; return 0; } @@ -603,7 +612,7 @@ mp_obj_t ModPicoGraphics_get_required_buffer_size(mp_obj_t display_in, mp_obj_t int pen_type = mp_obj_get_int(pen_type_in); PicoGraphicsBusType bus_type = BUS_SPI; if(!get_display_settings(display, width, height, rotation, pen_type, bus_type)) mp_raise_ValueError("Unsupported display!"); - size_t required_size = get_required_buffer_size((PicoGraphicsPenType)pen_type, width, height); + size_t required_size = get_required_buffer_size((PicoGraphicsPenType)pen_type, width, height, 1); if(required_size == 0) mp_raise_ValueError("Unsupported pen type!"); return mp_obj_new_int(required_size); @@ -755,6 +764,14 @@ mp_obj_t ModPicoGraphics_set_pen(mp_obj_t self_in, mp_obj_t pen) { return mp_const_none; } +mp_obj_t ModPicoGraphics_set_layer(mp_obj_t self_in, mp_obj_t layer) { + ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t); + + self->graphics->set_layer(mp_obj_get_int(layer)); + + return mp_const_none; +} + mp_obj_t ModPicoGraphics_reset_pen(mp_obj_t self_in, mp_obj_t pen) { ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t); diff --git a/micropython/modules/picographics/picographics.h b/micropython/modules/picographics/picographics.h index 655d336b..1238354d 100644 --- a/micropython/modules/picographics/picographics.h +++ b/micropython/modules/picographics/picographics.h @@ -77,6 +77,9 @@ extern mp_obj_t ModPicoGraphics_reset_pen(mp_obj_t self_in, mp_obj_t pen); extern mp_obj_t ModPicoGraphics_set_palette(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); extern mp_obj_t ModPicoGraphics_hsv_to_rgb(size_t n_args, const mp_obj_t *args); +// Layers +extern mp_obj_t ModPicoGraphics_set_layer(mp_obj_t self_in, mp_obj_t layer); + // Pen extern mp_obj_t ModPicoGraphics_set_pen(mp_obj_t self_in, mp_obj_t pen); extern mp_obj_t ModPicoGraphics_create_pen(size_t n_args, const mp_obj_t *args);