Pico Unicorn: Add support for PicoGraphics.

pull/711/head
Phil Howard 2023-03-16 13:24:53 +00:00
rodzic 3eb42336e6
commit f2751ba6e9
12 zmienionych plików z 107 dodań i 12 usunięć

Wyświetl plik

@ -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)

Wyświetl plik

@ -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)

Wyświetl plik

@ -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)

Wyświetl plik

@ -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++;
}
});
}
}
}
}

Wyświetl plik

@ -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);

Wyświetl plik

@ -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

Wyświetl plik

@ -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) },

Wyświetl plik

@ -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;
}
}

Wyświetl plik

@ -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);
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);

Wyświetl plik

@ -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) },

Wyświetl plik

@ -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 {

Wyświetl plik

@ -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 {