From 75560ea038746df91c6effeb38a9e85807e87a0a Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Wed, 20 Jan 2021 15:59:48 +0000 Subject: [PATCH] Added outline of an mpy wrapper for pico_display --- drivers/st7789/st7789.cpp | 2 +- drivers/st7789/st7789.hpp | 8 +- examples/pico_display/demo.cpp | 1 + libraries/pico_display/pico_display.cpp | 20 ++- libraries/pico_display/pico_display.hpp | 22 +-- libraries/pico_graphics/pico_graphics.hpp | 5 +- .../modules/pico_display/micropython.mk | 6 + .../modules/pico_display/pico_display.c | 84 ++++++++++ .../modules/pico_display/pico_display.cpp | 150 ++++++++++++++++++ .../modules/pico_display/pico_display.h | 31 ++++ 10 files changed, 309 insertions(+), 20 deletions(-) create mode 100755 micropython/modules/pico_display/micropython.mk create mode 100755 micropython/modules/pico_display/pico_display.c create mode 100644 micropython/modules/pico_display/pico_display.cpp create mode 100644 micropython/modules/pico_display/pico_display.h diff --git a/drivers/st7789/st7789.cpp b/drivers/st7789/st7789.cpp index bd412252..251e8e90 100644 --- a/drivers/st7789/st7789.cpp +++ b/drivers/st7789/st7789.cpp @@ -140,7 +140,7 @@ namespace pimoroni { // gamma correct the provided 0-255 brightness value onto a // 0-65535 range for the pwm counter float gamma = 2.8; - uint16_t value = (uint16_t)(pow((float)(brightness) / 255.0f, gamma) * 65536.0f + 0.5f); + uint16_t value = (uint16_t)(pow((float)(brightness) / 255.0f, gamma) * 65535.0f + 0.5f); pwm_set_gpio_level(bl, value); } diff --git a/drivers/st7789/st7789.hpp b/drivers/st7789/st7789.hpp index a2ee83ff..d4b62bff 100644 --- a/drivers/st7789/st7789.hpp +++ b/drivers/st7789/st7789.hpp @@ -16,11 +16,11 @@ namespace pimoroni { uint16_t row_stride; // interface pins with our standard defaults where appropriate + int8_t cs = 17; + int8_t dc = 16; int8_t sck = 18; int8_t mosi = 19; int8_t miso = -1; // we generally don't use this pin - int8_t cs = 17; - int8_t dc = 16; int8_t bl = 20; int8_t vsync = -1; // only available on some products @@ -37,9 +37,9 @@ namespace pimoroni { ST7789(uint16_t width, uint16_t height, uint16_t *frame_buffer, spi_inst_t *spi, uint8_t cs, uint8_t dc, uint8_t sck, uint8_t mosi, uint8_t miso = -1) : - width(width), height(height), frame_buffer(frame_buffer), spi(spi), - cs(cs), dc(dc), sck(sck), mosi(mosi), miso(miso) {} + width(width), height(height), + cs(cs), dc(dc), sck(sck), mosi(mosi), miso(miso), frame_buffer(frame_buffer) {} void init(bool auto_init_sequence = true); diff --git a/examples/pico_display/demo.cpp b/examples/pico_display/demo.cpp index 2a2659c8..92cc217b 100644 --- a/examples/pico_display/demo.cpp +++ b/examples/pico_display/demo.cpp @@ -70,6 +70,7 @@ void sprite(uint8_t *p, int x, int y, bool flip, uint16_t c) { }*/ int main() { + pico_display.init(); pico_display.set_backlight(100); // uint16_t white = pico_display.create_pen(255, 255, 255); diff --git a/libraries/pico_display/pico_display.cpp b/libraries/pico_display/pico_display.cpp index c8906c1d..fa9c94a0 100644 --- a/libraries/pico_display/pico_display.cpp +++ b/libraries/pico_display/pico_display.cpp @@ -1,4 +1,5 @@ #include +#include #include "hardware/pwm.h" @@ -11,8 +12,11 @@ const uint8_t LED_B = 8; namespace pimoroni { PicoDisplay::PicoDisplay() - : screen(240, 135, __fb), PicoGraphics(240, 135, __fb) { + : PicoGraphics(WIDTH, HEIGHT, __fb), screen(WIDTH, HEIGHT, __fb) { + memset(__fb, 0, sizeof(__fb)); + } + void PicoDisplay::init() { // setup the rgb led for pwm control pwm_config cfg = pwm_get_default_config(); pwm_config_set_output_polarity(&cfg, true, true); @@ -42,6 +46,14 @@ namespace pimoroni { screen.init(); } + void PicoDisplay::update() { + screen.update(); + } + + void PicoDisplay::set_backlight(uint8_t brightness) { + screen.set_backlight(brightness); + } + void PicoDisplay::set_led(uint8_t r, uint8_t g, uint8_t b) { // gamma correct the provided 0-255 brightness value onto a // 0-65535 range for the pwm counter @@ -50,15 +62,15 @@ namespace pimoroni { uint16_t value; // red - value = (uint16_t)(pow((float)(r) / 255.0f, gamma) * 65536.0f + 0.5f); + value = (uint16_t)(pow((float)(r) / 255.0f, gamma) * 65535.0f + 0.5f); pwm_set_gpio_level(LED_R, value); // green - value = (uint16_t)(pow((float)(g) / 255.0f, gamma) * 65536.0f + 0.5f); + value = (uint16_t)(pow((float)(g) / 255.0f, gamma) * 65535.0f + 0.5f); pwm_set_gpio_level(LED_G, value); // blue - value = (uint16_t)(pow((float)(b) / 255.0f, gamma) * 65536.0f + 0.5f); + value = (uint16_t)(pow((float)(b) / 255.0f, gamma) * 65535.0f + 0.5f); pwm_set_gpio_level(LED_B, value); } diff --git a/libraries/pico_display/pico_display.hpp b/libraries/pico_display/pico_display.hpp index b1c53d66..e9060b19 100644 --- a/libraries/pico_display/pico_display.hpp +++ b/libraries/pico_display/pico_display.hpp @@ -6,22 +6,26 @@ namespace pimoroni { class PicoDisplay : public PicoGraphics { - uint16_t __fb[240 * 135]; + public: + static const int WIDTH = 240; + static const int HEIGHT = 135; + static const uint8_t A = 12; + static const uint8_t B = 13; + static const uint8_t X = 14; + static const uint8_t Y = 15; + + private: + uint16_t __fb[WIDTH * HEIGHT]; ST7789 screen; public: PicoDisplay(); - void set_backlight(uint8_t brightness) {screen.set_backlight(brightness);} - void update() {screen.update();} - + void init(); + void update(); + void set_backlight(uint8_t brightness); void set_led(uint8_t r, uint8_t g, uint8_t b); bool is_pressed(uint8_t button); - - static const uint8_t A = 12; - static const uint8_t B = 13; - static const uint8_t X = 14; - static const uint8_t Y = 15; }; } \ No newline at end of file diff --git a/libraries/pico_graphics/pico_graphics.hpp b/libraries/pico_graphics/pico_graphics.hpp index 2aef657e..de3b133b 100644 --- a/libraries/pico_graphics/pico_graphics.hpp +++ b/libraries/pico_graphics/pico_graphics.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -39,11 +40,11 @@ namespace pimoroni { class PicoGraphics { public: + uint16_t *frame_buffer; + rect bounds; rect clip; - uint16_t *frame_buffer; - uint16_t pen; public: diff --git a/micropython/modules/pico_display/micropython.mk b/micropython/modules/pico_display/micropython.mk new file mode 100755 index 00000000..a6faed27 --- /dev/null +++ b/micropython/modules/pico_display/micropython.mk @@ -0,0 +1,6 @@ +DISPLAY_MOD_DIR := $(USERMOD_DIR) +# Add all C files to SRC_USERMOD. +SRC_USERMOD += $(DISPLAY_MOD_DIR)/pico_display.c +# # We can add our module folder to include paths if needed +# # This is not actually needed in this example. +CFLAGS_USERMOD += -I$(DISPLAY_MOD_DIR) diff --git a/micropython/modules/pico_display/pico_display.c b/micropython/modules/pico_display/pico_display.c new file mode 100755 index 00000000..13122696 --- /dev/null +++ b/micropython/modules/pico_display/pico_display.c @@ -0,0 +1,84 @@ +#include "pico_display.h" + +/***** Constants *****/ +enum buttons +{ + BUTTON_A = 0, + BUTTON_B, + BUTTON_X, + BUTTON_Y, +}; + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// picodisplay Module +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/***** Module Functions *****/ +STATIC MP_DEFINE_CONST_FUN_OBJ_0(picodisplay_init_obj, picodisplay_init); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(picodisplay_get_width_obj, picodisplay_get_width); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(picodisplay_get_height_obj, picodisplay_get_height); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(picodisplay_update_obj, picodisplay_update); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(picodisplay_set_backlight_obj, picodisplay_set_backlight); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(picodisplay_set_led_obj, picodisplay_set_led); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(picodisplay_is_pressed_obj, picodisplay_is_pressed); + +//From PicoGraphics parent class +STATIC MP_DEFINE_CONST_FUN_OBJ_3(picodisplay_set_pen_rgb_obj, picodisplay_set_pen_rgb); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(picodisplay_set_pen_obj, picodisplay_set_pen); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(picodisplay_create_pen_obj, picodisplay_create_pen); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(picodisplay_set_clip_obj, picodisplay_set_clip); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(picodisplay_remove_clip_obj, picodisplay_remove_clip); +//STATIC MP_DEFINE_CONST_FUN_OBJ_1(picodisplay_ptr_obj, picodisplay_ptr); +//STATIC MP_DEFINE_CONST_FUN_OBJ_1(picodisplay_ptr_obj, picodisplay_ptr); +//STATIC MP_DEFINE_CONST_FUN_OBJ_2(picodisplay_ptr_obj, picodisplay_ptr); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(picodisplay_clear_obj, picodisplay_clear); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(picodisplay_pixel_obj, picodisplay_pixel); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(picodisplay_pixel_span_obj, picodisplay_pixel_span); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(picodisplay_rectangle_obj, picodisplay_rectangle); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(picodisplay_circle_obj, picodisplay_circle); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(picodisplay_text_obj, picodisplay_text); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(picodisplay_character_obj, picodisplay_character); + + +/***** Globals Table *****/ +STATIC const mp_map_elem_t picodisplay_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_picodisplay) }, + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&picodisplay_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_width), MP_ROM_PTR(&picodisplay_get_width_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_height), MP_ROM_PTR(&picodisplay_get_height_obj) }, + { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&picodisplay_update_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_backlight), MP_ROM_PTR(&picodisplay_set_backlight_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_led), MP_ROM_PTR(&picodisplay_set_led_obj) }, + { MP_ROM_QSTR(MP_QSTR_is_pressed), MP_ROM_PTR(&picodisplay_is_pressed_obj) }, + + { MP_ROM_QSTR(MP_QSTR_set_pen_rgb), MP_ROM_PTR(&picodisplay_set_pen_rgb_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_pen), MP_ROM_PTR(&picodisplay_set_pen_obj) }, + { MP_ROM_QSTR(MP_QSTR_create_pen), MP_ROM_PTR(&picodisplay_create_pen_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_clip), MP_ROM_PTR(&picodisplay_set_clip_obj) }, + { MP_ROM_QSTR(MP_QSTR_remove_clip), MP_ROM_PTR(&picodisplay_remove_clip_obj) }, + // + { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&picodisplay_clear_obj) }, + { MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&picodisplay_pixel_obj) }, + { MP_ROM_QSTR(MP_QSTR_pixel_span), MP_ROM_PTR(&picodisplay_pixel_span_obj) }, + { MP_ROM_QSTR(MP_QSTR_rectangle), MP_ROM_PTR(&picodisplay_rectangle_obj) }, + { MP_ROM_QSTR(MP_QSTR_circle), MP_ROM_PTR(&picodisplay_circle_obj) }, + { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&picodisplay_text_obj) }, + { MP_ROM_QSTR(MP_QSTR_character), MP_ROM_PTR(&picodisplay_character_obj) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_A), MP_ROM_INT(BUTTON_A) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_B), MP_ROM_INT(BUTTON_B) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_X), MP_ROM_INT(BUTTON_X) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_Y), MP_ROM_INT(BUTTON_Y) }, +}; +STATIC MP_DEFINE_CONST_DICT(mp_module_picodisplay_globals, picodisplay_globals_table); + +/***** Module Definition *****/ +const mp_obj_module_t picodisplay_user_cmodule = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_picodisplay_globals, +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +MP_REGISTER_MODULE(MP_QSTR_picodisplay, picodisplay_user_cmodule, MODULE_PICODISPLAY_ENABLED); +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/micropython/modules/pico_display/pico_display.cpp b/micropython/modules/pico_display/pico_display.cpp new file mode 100644 index 00000000..c3e4f75d --- /dev/null +++ b/micropython/modules/pico_display/pico_display.cpp @@ -0,0 +1,150 @@ +#include "hardware/spi.h" +#include "hardware/sync.h" +#include "pico/binary_info.h" + +#include "../../../pimoroni-pico/libraries/pico_display/pico_display.hpp" + +using namespace pimoroni; + +PicoDisplay display; + + +extern "C" { +#include "pico_display.h" + +mp_obj_t picodisplay_init() { + display.init(); + return mp_const_none; +} + +mp_obj_t picodisplay_get_width() { + return mp_obj_new_int(PicoDisplay::WIDTH); +} + +mp_obj_t picodisplay_get_height() { + return mp_obj_new_int(PicoDisplay::HEIGHT); +} + +mp_obj_t picodisplay_update() { + display.update(); + return mp_const_none; +} + +mp_obj_t picodisplay_set_backlight(mp_obj_t brightness_obj) { + float brightness = mp_obj_get_float(brightness_obj); + + if(brightness < 0 || brightness > 1.0f) + mp_raise_ValueError("brightness out of range. Expected 0.0 to 1.0"); + else + display.set_backlight((uint8_t)(brightness * 255.0f)); + + return mp_const_none; +} + +mp_obj_t picodisplay_set_led(mp_obj_t r_obj, mp_obj_t g_obj, mp_obj_t b_obj) { + int r = mp_obj_get_int(r_obj); + int g = mp_obj_get_int(g_obj); + int b = mp_obj_get_int(b_obj); + + if(r < 0 || r > 255) + mp_raise_ValueError("r out of range. Expected 0 to 255"); + else if(g < 0 || g > 255) + mp_raise_ValueError("g out of range. Expected 0 to 255"); + else if(b < 0 || b > 255) + mp_raise_ValueError("b out of range. Expected 0 to 255"); + else + display.set_led(r, g, b); + + return mp_const_none; +} + +mp_obj_t picodisplay_is_pressed(mp_obj_t button_obj) { + int buttonID = mp_obj_get_int(button_obj); + + bool buttonPressed = false; + switch(buttonID) + { + case 0: + buttonPressed = display.is_pressed(PicoDisplay::A); + break; + + case 1: + buttonPressed = display.is_pressed(PicoDisplay::B); + break; + + case 2: + buttonPressed = display.is_pressed(PicoDisplay::X); + break; + + case 3: + buttonPressed = display.is_pressed(PicoDisplay::Y); + break; + + default: + mp_raise_ValueError("button not valid. Expected 0 to 3"); + break; + } + + return buttonPressed ? mp_const_true : mp_const_false; +} + +mp_obj_t picodisplay_set_pen_rgb(mp_obj_t r_obj, mp_obj_t g_obj, mp_obj_t b_obj) { + return mp_const_none; +} + +mp_obj_t picodisplay_set_pen(mp_obj_t p_obj) { + return mp_const_none; +} + +mp_obj_t picodisplay_create_pen(mp_obj_t r_obj, mp_obj_t g_obj, mp_obj_t b_obj) { + return mp_const_none; +} + +mp_obj_t picodisplay_set_clip(mp_obj_t r_obj) { + return mp_const_none; +} + +mp_obj_t picodisplay_remove_clip() { + return mp_const_none; +} + +// mp_obj_t picodisplay_ptr(mp_obj_t p_obj) { +// return mp_const_none; +// } + +// mp_obj_t picodisplay_ptr(mp_obj_t r_obj) { +// return mp_const_none; +// } + +// mp_obj_t picodisplay_ptr(mp_obj_t x_obj, mp_obj_t y_obj) { +// return mp_const_none; +// } + +mp_obj_t picodisplay_clear() { + return mp_const_none; +} + +mp_obj_t picodisplay_pixel(mp_obj_t p_obj) { + return mp_const_none; +} + +mp_obj_t picodisplay_pixel_span(mp_obj_t p_obj, mp_obj_t l_obj) { + return mp_const_none; +} + +mp_obj_t picodisplay_rectangle(mp_obj_t r_obj) { + return mp_const_none; +} + +mp_obj_t picodisplay_circle(mp_obj_t p_obj, mp_obj_t r_obj) { + return mp_const_none; +} + +mp_obj_t picodisplay_text(mp_obj_t t_obj, mp_obj_t p_obj, mp_obj_t wrap_obj) { + return mp_const_none; +} + +mp_obj_t picodisplay_character(mp_obj_t c_obj, mp_obj_t p_obj, mp_obj_t scale_obj) { + return mp_const_none; +} +} \ No newline at end of file diff --git a/micropython/modules/pico_display/pico_display.h b/micropython/modules/pico_display/pico_display.h new file mode 100644 index 00000000..5e60033b --- /dev/null +++ b/micropython/modules/pico_display/pico_display.h @@ -0,0 +1,31 @@ +// Include MicroPython API. +#include "py/runtime.h" + +// Declare the functions we'll make available in Python +extern mp_obj_t picodisplay_init(); +extern mp_obj_t picodisplay_get_width(); +extern mp_obj_t picodisplay_get_height(); +extern mp_obj_t picodisplay_set_backlight(mp_obj_t brightness_obj); +extern mp_obj_t picodisplay_update(); +extern mp_obj_t picodisplay_set_led(mp_obj_t r_obj, mp_obj_t g_obj, mp_obj_t b_obj); +extern mp_obj_t picodisplay_is_pressed(mp_obj_t button_obj); + +// From PicoGraphics parent class +extern mp_obj_t picodisplay_set_pen_rgb(mp_obj_t r_obj, mp_obj_t g_obj, mp_obj_t b_obj); +extern mp_obj_t picodisplay_set_pen(mp_obj_t p_obj); +extern mp_obj_t picodisplay_create_pen(mp_obj_t r_obj, mp_obj_t g_obj, mp_obj_t b_obj); + +extern mp_obj_t picodisplay_set_clip(mp_obj_t r_obj); +extern mp_obj_t picodisplay_remove_clip(); + +//extern mp_obj_t picodisplay_ptr(mp_obj_t p_obj); +//extern mp_obj_t picodisplay_ptr(mp_obj_t r_obj); +//extern mp_obj_t picodisplay_ptr(mp_obj_t x_obj, mp_obj_t y_obj); + +extern mp_obj_t picodisplay_clear(); +extern mp_obj_t picodisplay_pixel(mp_obj_t p_obj); +extern mp_obj_t picodisplay_pixel_span(mp_obj_t p_obj, mp_obj_t l_obj); +extern mp_obj_t picodisplay_rectangle(mp_obj_t r_obj); +extern mp_obj_t picodisplay_circle(mp_obj_t p_obj, mp_obj_t r_obj); +extern mp_obj_t picodisplay_text(mp_obj_t t_obj, mp_obj_t p_obj, mp_obj_t wrap_obj); +extern mp_obj_t picodisplay_character(mp_obj_t c_obj, mp_obj_t p_obj, mp_obj_t scale_obj); \ No newline at end of file