From 1b0b783a2f61c08e2fa247cd893a1cc344b682ea Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 16 Mar 2023 16:59:31 +0000 Subject: [PATCH] Pico Scroll: Add support for PicoGraphics. --- libraries/pico_scroll/pico_scroll.cmake | 2 +- libraries/pico_scroll/pico_scroll.cpp | 57 +++++++++++++++++++ libraries/pico_scroll/pico_scroll.hpp | 5 +- micropython/modules/pico_scroll/pico_scroll.c | 8 ++- .../modules/pico_scroll/pico_scroll.cpp | 25 +++++++- micropython/modules/pico_scroll/pico_scroll.h | 5 +- .../modules/picographics/picographics.c | 1 + .../modules/picographics/picographics.cpp | 10 +++- .../modules/picographics/picographics.h | 3 +- 9 files changed, 107 insertions(+), 9 deletions(-) diff --git a/libraries/pico_scroll/pico_scroll.cmake b/libraries/pico_scroll/pico_scroll.cmake index 3b42f97d..dbbfc94d 100644 --- a/libraries/pico_scroll/pico_scroll.cmake +++ b/libraries/pico_scroll/pico_scroll.cmake @@ -11,4 +11,4 @@ target_sources(pico_scroll INTERFACE target_include_directories(pico_scroll INTERFACE ${CMAKE_CURRENT_LIST_DIR}) # Pull in pico libraries that we need -target_link_libraries(pico_scroll INTERFACE pico_stdlib hardware_i2c) \ No newline at end of file +target_link_libraries(pico_scroll INTERFACE pico_stdlib pico_graphics hardware_i2c) \ No newline at end of file diff --git a/libraries/pico_scroll/pico_scroll.cpp b/libraries/pico_scroll/pico_scroll.cpp index 9522d4d5..1d3a99cb 100644 --- a/libraries/pico_scroll/pico_scroll.cpp +++ b/libraries/pico_scroll/pico_scroll.cpp @@ -171,4 +171,61 @@ namespace pimoroni { memcpy(&buffer[1], data, len); i2c_write_blocking(i2c0, DEFAULT_ADDRESS, buffer, len + 1, true); } + + void PicoScroll::update(PicoGraphics *graphics) { + if(graphics->pen_type == PicoGraphics::PEN_RGB888) { + uint32_t *p = (uint32_t *)graphics->frame_buffer; + + for(int y = 0; y < HEIGHT; y++) { + for(int x = 0; x < WIDTH; x++) { + uint32_t col = *p; + uint8_t r = (col & 0xff0000) >> 16; + uint8_t g = (col & 0x00ff00) >> 8; + uint8_t b = (col & 0x0000ff) >> 0; + p++; + + set_pixel(x, y, (r + g + b) / 3); + } + } + + update(); + } + else if(graphics->pen_type == PicoGraphics::PEN_RGB565) { + uint16_t *p = (uint16_t *)graphics->frame_buffer; + for(int y = 0; y < HEIGHT; y++) { + for(int x = 0; x < WIDTH; x++) { + uint16_t col = __builtin_bswap16(*p); + uint8_t r = (col & 0b1111100000000000) >> 8; + uint8_t g = (col & 0b0000011111100000) >> 3; + uint8_t b = (col & 0b0000000000011111) << 3; + p++; + + set_pixel(x, y, (r + g + b) / 3); + } + } + + update(); + } + else if(graphics->pen_type == PicoGraphics::PEN_P8 || graphics->pen_type == PicoGraphics::PEN_P4) { + int offset = 0; + graphics->frame_convert(PicoGraphics::PEN_RGB888, [this, offset](void *data, size_t length) mutable { + uint32_t *p = (uint32_t *)data; + for(auto i = 0u; i < length / 4; i++) { + int x = offset % WIDTH; + int y = offset / WIDTH; + + uint32_t col = *p; + uint8_t r = (col & 0xff0000) >> 16; + uint8_t g = (col & 0x00ff00) >> 8; + uint8_t b = (col & 0x0000ff) >> 0; + + set_pixel(x, y, (r + g + b) / 3); + offset++; + p++; + } + }); + + update(); + } + } } \ No newline at end of file diff --git a/libraries/pico_scroll/pico_scroll.hpp b/libraries/pico_scroll/pico_scroll.hpp index a7142fb2..dfa2c7b6 100644 --- a/libraries/pico_scroll/pico_scroll.hpp +++ b/libraries/pico_scroll/pico_scroll.hpp @@ -1,6 +1,8 @@ -#include #pragma once +#include +#include "pico_graphics.hpp" + namespace pimoroni { class PicoScroll { @@ -36,6 +38,7 @@ namespace pimoroni { void clear(); bool is_pressed(uint8_t button); + void update(PicoGraphics *graphics); private: void i2c_write(uint8_t reg, const char *data, uint8_t len); }; diff --git a/micropython/modules/pico_scroll/pico_scroll.c b/micropython/modules/pico_scroll/pico_scroll.c index eae44483..e18fa8eb 100644 --- a/micropython/modules/pico_scroll/pico_scroll.c +++ b/micropython/modules/pico_scroll/pico_scroll.c @@ -18,7 +18,7 @@ enum buttons STATIC MP_DEFINE_CONST_FUN_OBJ_1(picoscroll___del___obj, picoscroll___del__); STATIC MP_DEFINE_CONST_FUN_OBJ_1(picoscroll_get_width_obj, picoscroll_get_width); STATIC MP_DEFINE_CONST_FUN_OBJ_1(picoscroll_get_height_obj, picoscroll_get_height); -STATIC MP_DEFINE_CONST_FUN_OBJ_1(picoscroll_update_obj, picoscroll_update); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(picoscroll_show_obj, picoscroll_show); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picoscroll_set_pixel_obj, 4, 4, picoscroll_set_pixel); STATIC MP_DEFINE_CONST_FUN_OBJ_2(picoscroll_set_pixels_obj, picoscroll_set_pixels); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picoscroll_show_text_obj, 4, 4, picoscroll_show_text); @@ -26,13 +26,15 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picoscroll_scroll_text_obj, 4, 4, pic STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picoscroll_show_bitmap_1d_obj, 4, 4, picoscroll_show_bitmap_1d); STATIC MP_DEFINE_CONST_FUN_OBJ_1(picoscroll_clear_obj, picoscroll_clear); STATIC MP_DEFINE_CONST_FUN_OBJ_2(picoscroll_is_pressed_obj, picoscroll_is_pressed); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(picoscroll_update_obj, picoscroll_update); /* Class Methods */ STATIC const mp_rom_map_elem_t picoscroll_locals[] = { - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&picoscroll___del___obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&picoscroll___del___obj) }, + { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&picoscroll_update_obj) }, + { MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&picoscroll_show_obj) }, { MP_ROM_QSTR(MP_QSTR_get_width), MP_ROM_PTR(&picoscroll_get_width_obj) }, { MP_ROM_QSTR(MP_QSTR_get_height), MP_ROM_PTR(&picoscroll_get_height_obj) }, - { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&picoscroll_update_obj) }, { MP_ROM_QSTR(MP_QSTR_set_pixel), MP_ROM_PTR(&picoscroll_set_pixel_obj) }, { MP_ROM_QSTR(MP_QSTR_set_pixels), MP_ROM_PTR(&picoscroll_set_pixels_obj) }, { MP_ROM_QSTR(MP_QSTR_show_text), MP_ROM_PTR(&picoscroll_show_text_obj) }, diff --git a/micropython/modules/pico_scroll/pico_scroll.cpp b/micropython/modules/pico_scroll/pico_scroll.cpp index 7e4d2800..3effcd6f 100644 --- a/micropython/modules/pico_scroll/pico_scroll.cpp +++ b/micropython/modules/pico_scroll/pico_scroll.cpp @@ -15,6 +15,8 @@ PicoScroll *scroll = nullptr; extern "C" { #include "pico_scroll.h" +#include "micropython/modules/pimoroni_i2c/pimoroni_i2c.h" +#include "py/builtin.h" #define BUFFER_TOO_SMALL_MSG "bytearray too small: len(image) < width * height." #define INCORRECT_SIZE_MSG "Scroll height wrong: > 8 pixels." @@ -24,6 +26,17 @@ typedef struct _PicoScroll_obj_t { PicoScroll* scroll; } PicoScroll_obj_t; +// from picographics/picographics.cpp +// used to support accepting a PicoGraphics class +typedef struct _ModPicoGraphics_obj_t { + mp_obj_base_t base; + PicoGraphics *graphics; + DisplayDriver *display; + void *spritedata; + void *buffer; + _PimoroniI2C_obj_t *i2c; +} ModPicoGraphics_obj_t; + mp_obj_t picoscroll_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { _PicoScroll_obj_t *self = nullptr; @@ -52,7 +65,7 @@ mp_obj_t picoscroll_get_height(mp_obj_t self_in) { return mp_obj_new_int(PicoScroll::HEIGHT); } -mp_obj_t picoscroll_update(mp_obj_t self_in) { +mp_obj_t picoscroll_show(mp_obj_t self_in) { PicoScroll_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoScroll_obj_t); self->scroll->update(); return mp_const_none; @@ -207,4 +220,14 @@ mp_obj_t picoscroll_is_pressed(mp_obj_t self_in, mp_obj_t button_obj) { return buttonPressed ? mp_const_true : mp_const_false; } + +mp_obj_t picoscroll_update(mp_obj_t self_in, mp_obj_t graphics_in) { + PicoScroll_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoScroll_obj_t); + ModPicoGraphics_obj_t *picographics = MP_OBJ_TO_PTR2(graphics_in, ModPicoGraphics_obj_t); + + if(picographics->base.type == &ModPicoGraphics_type) { + self->scroll->update(picographics->graphics); + } + return mp_const_none; +} } diff --git a/micropython/modules/pico_scroll/pico_scroll.h b/micropython/modules/pico_scroll/pico_scroll.h index e841f0cd..f5c9ac9a 100644 --- a/micropython/modules/pico_scroll/pico_scroll.h +++ b/micropython/modules/pico_scroll/pico_scroll.h @@ -3,13 +3,14 @@ #include "py/objstr.h" extern const mp_obj_type_t PicoScroll_type; +extern const mp_obj_type_t ModPicoGraphics_type; // Declare the functions we'll make available in Python extern mp_obj_t picoscroll_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args); extern mp_obj_t picoscroll___del__(mp_obj_t self_in); extern mp_obj_t picoscroll_get_width(mp_obj_t self_in); extern mp_obj_t picoscroll_get_height(mp_obj_t self_in); -extern mp_obj_t picoscroll_update(mp_obj_t self_in); +extern mp_obj_t picoscroll_show(mp_obj_t self_in); extern mp_obj_t picoscroll_set_pixel(mp_uint_t n_args, const mp_obj_t *args); extern mp_obj_t picoscroll_set_pixels(mp_obj_t self_in, mp_obj_t image_obj); extern mp_obj_t picoscroll_show_text(mp_uint_t n_args, const mp_obj_t *args); @@ -17,3 +18,5 @@ extern mp_obj_t picoscroll_scroll_text(mp_uint_t n_args, const mp_obj_t *args); extern mp_obj_t picoscroll_show_bitmap_1d(mp_uint_t n_args, const mp_obj_t *args); extern mp_obj_t picoscroll_clear(mp_obj_t self_in); extern mp_obj_t picoscroll_is_pressed(mp_obj_t self_in, mp_obj_t button_obj); + +extern mp_obj_t picoscroll_update(mp_obj_t self_in, mp_obj_t graphics_in); \ No newline at end of file diff --git a/micropython/modules/picographics/picographics.c b/micropython/modules/picographics/picographics.c index 534c04b2..ed034dce 100644 --- a/micropython/modules/picographics/picographics.c +++ b/micropython/modules/picographics/picographics.c @@ -153,6 +153,7 @@ STATIC const mp_map_elem_t picographics_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_DISPLAY_INKY_FRAME_7), MP_ROM_INT(DISPLAY_INKY_FRAME_7) }, { MP_ROM_QSTR(MP_QSTR_DISPLAY_COSMIC_UNICORN), MP_ROM_INT(DISPLAY_COSMIC_UNICORN) }, { MP_ROM_QSTR(MP_QSTR_DISPLAY_UNICORN_PACK), MP_ROM_INT(DISPLAY_UNICORN_PACK) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_SCROLL_PACK), MP_ROM_INT(DISPLAY_SCROLL_PACK) }, { MP_ROM_QSTR(MP_QSTR_PEN_1BIT), MP_ROM_INT(PEN_1BIT) }, { MP_ROM_QSTR(MP_QSTR_PEN_P4), MP_ROM_INT(PEN_P4) }, diff --git a/micropython/modules/picographics/picographics.cpp b/micropython/modules/picographics/picographics.cpp index 24de1cad..989f1e32 100644 --- a/micropython/modules/picographics/picographics.cpp +++ b/micropython/modules/picographics/picographics.cpp @@ -217,6 +217,13 @@ bool get_display_settings(PicoGraphicsDisplay display, int &width, int &height, if(rotate == -1) rotate = (int)Rotation::ROTATE_0; if(pen_type == -1) pen_type = PEN_RGB888; break; + case DISPLAY_SCROLL_PACK: + width = 17; + height = 7; + bus_type = BUS_PIO; + if(rotate == -1) rotate = (int)Rotation::ROTATE_0; + if(pen_type == -1) pen_type = PEN_RGB888; + break; default: return false; } @@ -347,7 +354,8 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size || display == DISPLAY_INTERSTATE75_64X32 || display == DISPLAY_GALACTIC_UNICORN || display == DISPLAY_COSMIC_UNICORN - || display == DISPLAY_UNICORN_PACK) { + || display == DISPLAY_UNICORN_PACK + || display == DISPLAY_SCROLL_PACK) { // Create a dummy display driver self->display = m_new_class(DisplayDriver, width, height, (Rotation)rotate); diff --git a/micropython/modules/picographics/picographics.h b/micropython/modules/picographics/picographics.h index a0f3e78f..e5ea8cf3 100644 --- a/micropython/modules/picographics/picographics.h +++ b/micropython/modules/picographics/picographics.h @@ -26,7 +26,8 @@ enum PicoGraphicsDisplay { DISPLAY_INTERSTATE75_256X64, DISPLAY_INKY_FRAME_7, DISPLAY_COSMIC_UNICORN, - DISPLAY_UNICORN_PACK + DISPLAY_UNICORN_PACK, + DISPLAY_SCROLL_PACK }; enum PicoGraphicsPenType {