diff --git a/examples/pico_unicorn/CMakeLists.txt b/examples/pico_unicorn/CMakeLists.txt index bdc84672..51120b99 100644 --- a/examples/pico_unicorn/CMakeLists.txt +++ b/examples/pico_unicorn/CMakeLists.txt @@ -4,7 +4,7 @@ add_executable( ) # Pull in pico libraries that we need -target_link_libraries(unicorn pico_stdlib hardware_pio hardware_dma pico_unicorn) +target_link_libraries(unicorn pico_stdlib hardware_pio hardware_dma pico_graphics pico_unicorn) # create map/bin/hex file etc. pico_add_extra_outputs(unicorn) diff --git a/examples/pico_unicorn_plasma/CMakeLists.txt b/examples/pico_unicorn_plasma/CMakeLists.txt index 9af28bee..44559f42 100644 --- a/examples/pico_unicorn_plasma/CMakeLists.txt +++ b/examples/pico_unicorn_plasma/CMakeLists.txt @@ -8,7 +8,7 @@ pico_enable_stdio_usb(unicornplasma 1) pico_enable_stdio_uart(unicornplasma 1) # Pull in pico libraries that we need -target_link_libraries(unicornplasma pico_stdlib hardware_pio hardware_dma pico_unicorn) +target_link_libraries(unicornplasma pico_stdlib hardware_pio hardware_dma pico_graphics pico_unicorn) # create map/bin/hex file etc. pico_add_extra_outputs(unicornplasma) diff --git a/libraries/pico_unicorn/pico_unicorn.cmake b/libraries/pico_unicorn/pico_unicorn.cmake index fd2a3c5c..ab622d8b 100644 --- a/libraries/pico_unicorn/pico_unicorn.cmake +++ b/libraries/pico_unicorn/pico_unicorn.cmake @@ -9,4 +9,4 @@ target_sources(pico_unicorn INTERFACE target_include_directories(pico_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR}) # Pull in pico libraries that we need -target_link_libraries(pico_unicorn INTERFACE pico_stdlib hardware_pio hardware_dma) +target_link_libraries(pico_unicorn INTERFACE pico_stdlib pico_graphics hardware_pio hardware_dma) diff --git a/libraries/pico_unicorn/pico_unicorn.cpp b/libraries/pico_unicorn/pico_unicorn.cpp index 39576a4d..294d546e 100644 --- a/libraries/pico_unicorn/pico_unicorn.cpp +++ b/libraries/pico_unicorn/pico_unicorn.cpp @@ -291,4 +291,57 @@ namespace pimoroni { hw_set_bits(&dma_hw->inte0, irq0_save); } + void PicoUnicorn::update(PicoGraphics *graphics) { + if(unicorn == this) { + 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); + } + } + } + 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); + } + } + } + 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); + offset++; + p++; + } + }); + } + } + } + } diff --git a/libraries/pico_unicorn/pico_unicorn.hpp b/libraries/pico_unicorn/pico_unicorn.hpp index a251ecd1..176a075a 100644 --- a/libraries/pico_unicorn/pico_unicorn.hpp +++ b/libraries/pico_unicorn/pico_unicorn.hpp @@ -1,6 +1,7 @@ #pragma once #include "hardware/pio.h" +#include "pico_graphics.hpp" namespace pimoroni { @@ -39,6 +40,8 @@ namespace pimoroni { void set_pixel(uint8_t x, uint8_t y, uint8_t v); bool is_pressed(uint8_t button); + + void update(PicoGraphics *graphics); private: void partial_teardown(); void dma_safe_abort(uint channel); diff --git a/micropython/modules/pico_unicorn/micropython.cmake b/micropython/modules/pico_unicorn/micropython.cmake index 261efebb..9190c767 100644 --- a/micropython/modules/pico_unicorn/micropython.cmake +++ b/micropython/modules/pico_unicorn/micropython.cmake @@ -10,6 +10,7 @@ pico_generate_pio_header(usermod_pico_unicorn ${CMAKE_CURRENT_LIST_DIR}/../../.. target_include_directories(usermod_pico_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR} + ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/pico_graphics/ ) target_compile_definitions(usermod_pico_unicorn INTERFACE diff --git a/micropython/modules/pico_unicorn/pico_unicorn.c b/micropython/modules/pico_unicorn/pico_unicorn.c index 37b80c29..b97767e9 100755 --- a/micropython/modules/pico_unicorn/pico_unicorn.c +++ b/micropython/modules/pico_unicorn/pico_unicorn.c @@ -23,9 +23,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(picounicorn_clear_obj, picounicorn_clear); STATIC MP_DEFINE_CONST_FUN_OBJ_2(picounicorn_is_pressed_obj, picounicorn_is_pressed); STATIC MP_DEFINE_CONST_FUN_OBJ_1(picounicorn_get_width_obj, picounicorn_get_width); STATIC MP_DEFINE_CONST_FUN_OBJ_1(picounicorn_get_height_obj, picounicorn_get_height); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(picounicorn_update_obj, picounicorn_update); STATIC const mp_rom_map_elem_t picounicorn_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&picounicorn__del__obj) }, + { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&picounicorn_update_obj) }, { MP_ROM_QSTR(MP_QSTR_set_pixel), MP_ROM_PTR(&picounicorn_set_pixel_obj) }, { MP_ROM_QSTR(MP_QSTR_set_pixel_value), MP_ROM_PTR(&picounicorn_set_pixel_value_obj) }, { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&picounicorn_clear_obj) }, diff --git a/micropython/modules/pico_unicorn/pico_unicorn.cpp b/micropython/modules/pico_unicorn/pico_unicorn.cpp index eab23eff..b5312344 100644 --- a/micropython/modules/pico_unicorn/pico_unicorn.cpp +++ b/micropython/modules/pico_unicorn/pico_unicorn.cpp @@ -4,18 +4,32 @@ #include "micropython/modules/util.hpp" #include "libraries/pico_unicorn/pico_unicorn.hpp" +#include "libraries/pico_graphics/pico_graphics.hpp" using namespace pimoroni; extern "C" { #include "pico_unicorn.h" +#include "micropython/modules/pimoroni_i2c/pimoroni_i2c.h" +#include "py/builtin.h" typedef struct _picounicorn_obj_t { mp_obj_base_t base; PicoUnicorn *unicorn; } picounicorn_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 picounicorn_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { picounicorn_obj_t *self = m_new_obj_with_finaliser(picounicorn_obj_t); self->base.type = &picounicorn_type; @@ -120,4 +134,14 @@ mp_obj_t picounicorn_is_pressed(mp_obj_t self_in, mp_obj_t button_obj) { return buttonPressed ? mp_const_true : mp_const_false; } + +mp_obj_t picounicorn_update(mp_obj_t self_in, mp_obj_t graphics_in) { + picounicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, picounicorn_obj_t); + ModPicoGraphics_obj_t *picographics = MP_OBJ_TO_PTR2(graphics_in, ModPicoGraphics_obj_t); + + if(picographics->base.type == &ModPicoGraphics_type) { + self->unicorn->update(picographics->graphics); + } + return mp_const_none; +} } \ No newline at end of file diff --git a/micropython/modules/pico_unicorn/pico_unicorn.h b/micropython/modules/pico_unicorn/pico_unicorn.h index 0ffa5f91..636e0f7d 100644 --- a/micropython/modules/pico_unicorn/pico_unicorn.h +++ b/micropython/modules/pico_unicorn/pico_unicorn.h @@ -1,6 +1,7 @@ #include "py/runtime.h" extern const mp_obj_type_t picounicorn_type; +extern const mp_obj_type_t ModPicoGraphics_type; extern mp_obj_t picounicorn_get_width(mp_obj_t self_in); extern mp_obj_t picounicorn_get_height(mp_obj_t self_in); @@ -10,4 +11,6 @@ extern mp_obj_t picounicorn_make_new(const mp_obj_type_t *type, size_t n_args, s extern mp_obj_t picounicorn_set_pixel(mp_uint_t n_args, const mp_obj_t *args); extern mp_obj_t picounicorn_set_pixel_value(mp_uint_t n_args, const mp_obj_t *args); extern mp_obj_t picounicorn_clear(mp_obj_t self_in); -extern mp_obj_t picounicorn_is_pressed(mp_obj_t self_in, mp_obj_t button_obj); \ No newline at end of file +extern mp_obj_t picounicorn_is_pressed(mp_obj_t self_in, mp_obj_t button_obj); + +extern mp_obj_t picounicorn_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 c11dda68..534c04b2 100644 --- a/micropython/modules/picographics/picographics.c +++ b/micropython/modules/picographics/picographics.c @@ -152,6 +152,7 @@ STATIC const mp_map_elem_t picographics_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_DISPLAY_INTERSTATE75_256X64), MP_ROM_INT(DISPLAY_INTERSTATE75_256X64) }, { 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_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 f49494b4..24de1cad 100644 --- a/micropython/modules/picographics/picographics.cpp +++ b/micropython/modules/picographics/picographics.cpp @@ -210,6 +210,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_UNICORN_PACK: + width = 16; + 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; } @@ -331,17 +338,17 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size } else if (display == DISPLAY_INKY_PACK) { self->display = m_new_class(UC8151, width, height, (Rotation)rotate, spi_bus); - - } else if (display == DISPLAY_GALACTIC_UNICORN) { - self->display = m_new_class(DisplayDriver, width, height, (Rotation)rotate); } else if (display == DISPLAY_GFX_PACK) { self->display = m_new_class(ST7567, width, height, spi_bus); - } else if (display == DISPLAY_INTERSTATE75_32X32 || display == DISPLAY_INTERSTATE75_64X64 || display == DISPLAY_INTERSTATE75_64X32) { - self->display = m_new_class(DisplayDriver, width, height, (Rotation)rotate); - - } else if (display == DISPLAY_COSMIC_UNICORN) { + } else if (display == DISPLAY_INTERSTATE75_32X32 + || display == DISPLAY_INTERSTATE75_64X64 + || display == DISPLAY_INTERSTATE75_64X32 + || display == DISPLAY_GALACTIC_UNICORN + || display == DISPLAY_COSMIC_UNICORN + || display == DISPLAY_UNICORN_PACK) { + // Create a dummy display driver self->display = m_new_class(DisplayDriver, width, height, (Rotation)rotate); } else { diff --git a/micropython/modules/picographics/picographics.h b/micropython/modules/picographics/picographics.h index 665c307a..a0f3e78f 100644 --- a/micropython/modules/picographics/picographics.h +++ b/micropython/modules/picographics/picographics.h @@ -25,7 +25,8 @@ enum PicoGraphicsDisplay { DISPLAY_INTERSTATE75_192X64, DISPLAY_INTERSTATE75_256X64, DISPLAY_INKY_FRAME_7, - DISPLAY_COSMIC_UNICORN + DISPLAY_COSMIC_UNICORN, + DISPLAY_UNICORN_PACK }; enum PicoGraphicsPenType {