From 9906fdec38854516d3506bc87db7589a2025c81e Mon Sep 17 00:00:00 2001 From: ZodiusInfuser Date: Thu, 17 Jun 2021 15:33:05 +0100 Subject: [PATCH] C class and MP bindings for PicoDisplay2 --- examples/CMakeLists.txt | 1 + examples/pico_display_2/CMakeLists.txt | 12 + examples/pico_display_2/demo.cpp | 111 ++++++ libraries/CMakeLists.txt | 1 + libraries/pico_display_2/CMakeLists.txt | 11 + libraries/pico_display_2/README.md | 123 +++++++ libraries/pico_display_2/pico_display_2.cmake | 14 + libraries/pico_display_2/pico_display_2.cpp | 90 +++++ libraries/pico_display_2/pico_display_2.hpp | 35 ++ micropython/examples/pico_display/buttons.py | 3 +- micropython/examples/pico_display/demo.py | 3 +- micropython/examples/pico_display/rainbow.py | 3 +- .../examples/pico_display/thermometer.py | 4 +- micropython/modules/micropython.cmake | 1 + micropython/modules/pico_display_2/README.md | 206 +++++++++++ .../modules/pico_display_2/images/circle.png | Bin 0 -> 5200 bytes .../modules/pico_display_2/images/clip.png | Bin 0 -> 6696 bytes .../pico_display_2/images/rectangle.png | Bin 0 -> 4814 bytes .../pico_display_2/images/text_scale.png | Bin 0 -> 6698 bytes .../modules/pico_display_2/micropython.cmake | 28 ++ .../modules/pico_display_2/pico_display_2.c | 80 ++++ .../modules/pico_display_2/pico_display_2.cpp | 341 ++++++++++++++++++ .../modules/pico_display_2/pico_display_2.h | 26 ++ 23 files changed, 1089 insertions(+), 4 deletions(-) create mode 100644 examples/pico_display_2/CMakeLists.txt create mode 100644 examples/pico_display_2/demo.cpp create mode 100644 libraries/pico_display_2/CMakeLists.txt create mode 100644 libraries/pico_display_2/README.md create mode 100644 libraries/pico_display_2/pico_display_2.cmake create mode 100644 libraries/pico_display_2/pico_display_2.cpp create mode 100644 libraries/pico_display_2/pico_display_2.hpp create mode 100644 micropython/modules/pico_display_2/README.md create mode 100644 micropython/modules/pico_display_2/images/circle.png create mode 100644 micropython/modules/pico_display_2/images/clip.png create mode 100644 micropython/modules/pico_display_2/images/rectangle.png create mode 100644 micropython/modules/pico_display_2/images/text_scale.png create mode 100644 micropython/modules/pico_display_2/micropython.cmake create mode 100755 micropython/modules/pico_display_2/pico_display_2.c create mode 100644 micropython/modules/pico_display_2/pico_display_2.cpp create mode 100644 micropython/modules/pico_display_2/pico_display_2.h diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index a834aad1..ac939c96 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -21,6 +21,7 @@ add_subdirectory(breakout_as7262) add_subdirectory(breakout_bh1745) add_subdirectory(pico_display) +add_subdirectory(pico_display_2) add_subdirectory(pico_unicorn) add_subdirectory(pico_unicorn_plasma) add_subdirectory(pico_scroll) diff --git a/examples/pico_display_2/CMakeLists.txt b/examples/pico_display_2/CMakeLists.txt new file mode 100644 index 00000000..00228e0f --- /dev/null +++ b/examples/pico_display_2/CMakeLists.txt @@ -0,0 +1,12 @@ +set(OUTPUT_NAME display_2) + +add_executable( + ${OUTPUT_NAME} + demo.cpp +) + +# Pull in pico libraries that we need +target_link_libraries( ${OUTPUT_NAME} pico_stdlib hardware_spi hardware_pwm hardware_dma pico_display_2) + +# create map/bin/hex file etc. +pico_add_extra_outputs( ${OUTPUT_NAME}) \ No newline at end of file diff --git a/examples/pico_display_2/demo.cpp b/examples/pico_display_2/demo.cpp new file mode 100644 index 00000000..95f812bb --- /dev/null +++ b/examples/pico_display_2/demo.cpp @@ -0,0 +1,111 @@ +#include +#include +#include +#include + +#include "pico_display_2.hpp" + +using namespace pimoroni; + +uint16_t buffer[PicoDisplay2::WIDTH * PicoDisplay2::HEIGHT]; +PicoDisplay2 pico_display(buffer); + +// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel +// Outputs are rgb in the range 0-255 for each channel +void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) { + float i = floor(h * 6.0f); + float f = h * 6.0f - i; + v *= 255.0f; + uint8_t p = v * (1.0f - s); + uint8_t q = v * (1.0f - f * s); + uint8_t t = v * (1.0f - (1.0f - f) * s); + + switch (int(i) % 6) { + case 0: r = v; g = t; b = p; break; + case 1: r = q; g = v; b = p; break; + case 2: r = p; g = v; b = t; break; + case 3: r = p; g = q; b = v; break; + case 4: r = t; g = p; b = v; break; + case 5: r = v; g = p; b = q; break; + } +} + +int main() { + pico_display.init(); + pico_display.set_backlight(255); + + struct pt { + float x; + float y; + uint8_t r; + float dx; + float dy; + uint16_t pen; + }; + + std::vector shapes; + for(int i = 0; i < 100; i++) { + pt shape; + shape.x = rand() % pico_display.bounds.w; + shape.y = rand() % pico_display.bounds.h; + shape.r = (rand() % 10) + 3; + shape.dx = float(rand() % 255) / 64.0f; + shape.dy = float(rand() % 255) / 64.0f; + shape.pen = pico_display.create_pen(rand() % 255, rand() % 255, rand() % 255); + shapes.push_back(shape); + } + + Point text_location(0, 0); + + while(true) { + if(pico_display.is_pressed(pico_display.A)) text_location.x -= 1; + if(pico_display.is_pressed(pico_display.B)) text_location.x += 1; + + if(pico_display.is_pressed(pico_display.X)) text_location.y -= 1; + if(pico_display.is_pressed(pico_display.Y)) text_location.y += 1; + + pico_display.set_pen(120, 40, 60); + pico_display.clear(); + + for(auto &shape : shapes) { + shape.x += shape.dx; + shape.y += shape.dy; + if((shape.x - shape.r) < 0) { + shape.dx *= -1; + shape.x = shape.r; + } + if((shape.x + shape.r) >= pico_display.bounds.w) { + shape.dx *= -1; + shape.x = pico_display.bounds.w - shape.r; + } + if((shape.y - shape.r) < 0) { + shape.dy *= -1; + shape.y = shape.r; + } + if((shape.y + shape.r) >= pico_display.bounds.h) { + shape.dy *= -1; + shape.y = pico_display.bounds.h - shape.r; + } + + pico_display.set_pen(shape.pen); + pico_display.circle(Point(shape.x, shape.y), shape.r); + + } + + // Since HSV takes a float from 0.0 to 1.0 indicating hue, + // then we can divide millis by the number of milliseconds + // we want a full colour cycle to take. 5000 = 5 sec. + uint8_t r = 0, g = 0, b = 0; + from_hsv((float)millis() / 5000.0f, 1.0f, 0.5f + sinf(millis() / 100.0f / 3.14159f) * 0.5f, r, g, b); + pico_display.set_led(r, g, b); + + + pico_display.set_pen(255, 255, 255); + pico_display.text("Hello World", text_location, 320); + + // update screen + pico_display.update(); + } + + return 0; +} diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index 9f1c2250..cd30b160 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -18,6 +18,7 @@ add_subdirectory(breakout_msa301) add_subdirectory(breakout_bh1745) add_subdirectory(pico_graphics) add_subdirectory(pico_display) +add_subdirectory(pico_display_2) add_subdirectory(pico_unicorn) add_subdirectory(pico_scroll) add_subdirectory(pico_explorer) diff --git a/libraries/pico_display_2/CMakeLists.txt b/libraries/pico_display_2/CMakeLists.txt new file mode 100644 index 00000000..a9333008 --- /dev/null +++ b/libraries/pico_display_2/CMakeLists.txt @@ -0,0 +1,11 @@ +set(LIB_NAME pico_display_2) +add_library(${LIB_NAME} INTERFACE) + +target_sources(${LIB_NAME} INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/${LIB_NAME}.cpp +) + +target_include_directories(${LIB_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + +# Pull in pico libraries that we need +target_link_libraries(${LIB_NAME} INTERFACE pico_stdlib hardware_spi hardware_pwm hardware_dma st7789 pico_graphics) \ No newline at end of file diff --git a/libraries/pico_display_2/README.md b/libraries/pico_display_2/README.md new file mode 100644 index 00000000..ee454773 --- /dev/null +++ b/libraries/pico_display_2/README.md @@ -0,0 +1,123 @@ +# Pico Display 2.0" Pack + +Our Pico Display Pack offers a vibrant 1.14" (240x135) IPS LCD screen for your Raspberry Pi Pico it also includes four switches and and an RGB LED! + +We've included helper functions to handle every aspect of drawing to the screen and interfacing with the buttons and LED. See the [function reference](#function-reference) for details. + +- [Example Program](#example-program) +- [Function Reference](#function-reference) + - [PicoGraphics](#picographics) + - [init](#init) + - [set_backlight](#set_backlight) + - [set_led](#set_led) + - [is_pressed](#is_pressed) + - [update](#update) + +## Example Program + +The following example sets up Pico Display, displays some basic demo text and graphics and will illuminate the RGB LED green if the A button is pressed. + +```c++ +#include "pico_display_2.hpp" + +using namespace pimoroni; + +uint16_t buffer[PicoDisplay2::WIDTH * PicoDisplay2::HEIGHT]; +PicoDisplay2 pico_display(buffer); + +int main() { + pico_display.init(); + + // set the backlight to a value between 0 and 255 + // the backlight is driven via PWM and is gamma corrected by our + // library to give a gorgeous linear brightness range. + pico_display.set_backlight(100); + + while(true) { + // detect if the A button is pressed (could be A, B, X, or Y) + if(pico_display.is_pressed(pico_display.A)) { + // make the led glow green + // parameters are red, green, blue all between 0 and 255 + // these are also gamma corrected + pico_display.set_led(0, 255, 0); + } + + // set the colour of the pen + // parameters are red, green, blue all between 0 and 255 + pico_display.set_pen(30, 40, 50); + + // fill the screen with the current pen colour + pico_display.clear(); + + // draw a box to put some text in + pico_display.set_pen(10, 20, 30); + Rect text_rect(10, 10, 150, 150); + pico_display.rectangle(text_rect); + + // write some text inside the box with 10 pixels of margin + // automatically word wrapping + text_rect.deflate(10); + pico_display.set_pen(110, 120, 130); + pico_display.text("This is a message", Point(text_rect.x, text_rect.y), text_rect.w); + + // now we've done our drawing let's update the screen + pico_display.update(); + } +} +``` + +## Function Reference + +### PicoGraphics + +Pico Display uses our Pico Graphics library to draw graphics and text. For more information [read the Pico Graphics function reference.](../pico_graphics/README.md#function-reference). + +### init + +Sets up Pico Display. `init` must be called before any other functions since it configures the required PWM and GPIO: + +```c++ +pico_display.init(); +``` + +### set_backlight + +Set the display backlight from 0-255. + +```c++ +pico_display.set_backlight(brightness); +``` + +Uses hardware PWM to dim the display backlight, dimming values are gamma-corrected to provide smooth brightness transitions across the full range of intensity. This may result in some low values mapping as "off." + +### set_led + +Sets the RGB LED on Pico Display with an RGB triplet: + +```c++ +pico_display.set_led(r, g, b); +``` + +Uses hardware PWM to drive the LED. Values are automatically gamma-corrected to provide smooth brightness transitions and low values may map as "off." + +### is_pressed + +Reads the GPIO pin connected to one of Pico Display's buttons, returning a `bool` - `true` if it's pressed and `false` if it is released. + +```c++ +pico_display.is_pressed(button); +``` + +The button vaule should be a `uint8_t` denoting a pin, and constants `A`, `B`, `X` and `Y` are supplied to make it easier. e: + +```c++ +bool is_a_button_pressed = pico_display.is_pressed(PicoDisplay2::A) +``` + +### update + +To display your changes on Pico Display's screen you need to call `update`: + +```c++ +pico_display.update(); +``` diff --git a/libraries/pico_display_2/pico_display_2.cmake b/libraries/pico_display_2/pico_display_2.cmake new file mode 100644 index 00000000..1b75294d --- /dev/null +++ b/libraries/pico_display_2/pico_display_2.cmake @@ -0,0 +1,14 @@ +include(${CMAKE_CURRENT_LIST_DIR}/../../drivers/st7789/st7789.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/../pico_graphics/pico_graphics.cmake) + +set(LIB_NAME pico_display_2) +add_library(${LIB_NAME} INTERFACE) + +target_sources(${LIB_NAME} INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/${LIB_NAME}.cpp +) + +target_include_directories(${LIB_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}) + +# Pull in pico libraries that we need +target_link_libraries(${LIB_NAME} INTERFACE pico_stdlib hardware_spi hardware_pwm hardware_dma st7789 pico_graphics) \ No newline at end of file diff --git a/libraries/pico_display_2/pico_display_2.cpp b/libraries/pico_display_2/pico_display_2.cpp new file mode 100644 index 00000000..38227b33 --- /dev/null +++ b/libraries/pico_display_2/pico_display_2.cpp @@ -0,0 +1,90 @@ +#include +#include + +#include "hardware/gpio.h" // Workaround SDK bug - https://github.com/raspberrypi/pico-sdk/issues/3 +#include "hardware/pwm.h" + +#include "pico_display_2.hpp" + +const uint8_t LED_R = 6; +const uint8_t LED_G = 7; +const uint8_t LED_B = 8; + +namespace pimoroni { + + PicoDisplay2::PicoDisplay2(uint16_t *buf) + : PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, buf, BG_SPI_FRONT) { + __fb = buf; + } + + PicoDisplay2::PicoDisplay2(uint16_t *buf, int width, int height) + : PicoGraphics(width, height, buf), screen(width, height, buf, BG_SPI_FRONT) { + __fb = buf; + } + + void PicoDisplay2::init() { + // setup the rgb led for pwm control + pwm_config cfg = pwm_get_default_config(); + pwm_config_set_output_polarity(&cfg, true, true); + + // red + pwm_set_wrap(pwm_gpio_to_slice_num(LED_R), 65535); + pwm_init(pwm_gpio_to_slice_num(LED_R), &cfg, true); + gpio_set_function(LED_R, GPIO_FUNC_PWM); + + // green + pwm_set_wrap(pwm_gpio_to_slice_num(LED_G), 65535); + pwm_init(pwm_gpio_to_slice_num(LED_G), &cfg, true); + gpio_set_function(LED_G, GPIO_FUNC_PWM); + + // blue + pwm_set_wrap(pwm_gpio_to_slice_num(LED_B), 65535); + pwm_init(pwm_gpio_to_slice_num(LED_B), &cfg, true); + gpio_set_function(LED_B, GPIO_FUNC_PWM); + + // setup button inputs + gpio_set_function(A, GPIO_FUNC_SIO); gpio_set_dir(A, GPIO_IN); gpio_pull_up(A); + gpio_set_function(B, GPIO_FUNC_SIO); gpio_set_dir(B, GPIO_IN); gpio_pull_up(B); + gpio_set_function(X, GPIO_FUNC_SIO); gpio_set_dir(X, GPIO_IN); gpio_pull_up(X); + gpio_set_function(Y, GPIO_FUNC_SIO); gpio_set_dir(Y, GPIO_IN); gpio_pull_up(Y); + + // initialise the screen + screen.init(true, false, 74 * 1000 * 1000); + } + + void PicoDisplay2::update() { + screen.update(); + } + + void PicoDisplay2::set_backlight(uint8_t brightness) { + screen.set_backlight(brightness); + } + + void PicoDisplay2::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 + static const float gamma = 2.8; + + uint16_t value; + + // red + 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) * 65535.0f + 0.5f); + pwm_set_gpio_level(LED_G, value); + + // blue + value = (uint16_t)(pow((float)(b) / 255.0f, gamma) * 65535.0f + 0.5f); + pwm_set_gpio_level(LED_B, value); + } + + bool PicoDisplay2::is_pressed(uint8_t button) { + return !gpio_get(button); + } + + void PicoDisplay2::flip() { + screen.flip(); + } +} diff --git a/libraries/pico_display_2/pico_display_2.hpp b/libraries/pico_display_2/pico_display_2.hpp new file mode 100644 index 00000000..55c0afdf --- /dev/null +++ b/libraries/pico_display_2/pico_display_2.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include "drivers/st7789/st7789.hpp" +#include "libraries/pico_graphics/pico_graphics.hpp" + +namespace pimoroni { + + class PicoDisplay2 : public PicoGraphics { + public: + static const int WIDTH = 320; + static const int HEIGHT = 240; + static const int PORTRAIT_WIDTH = 240; + static const int PORTRAIT_HEIGHT = 320; + static const uint8_t A = 12; + static const uint8_t B = 13; + static const uint8_t X = 14; + static const uint8_t Y = 15; + + uint16_t *__fb; + private: + ST7789 screen; + + public: + PicoDisplay2(uint16_t *buf); + PicoDisplay2(uint16_t *buf, int width, int height); + + 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); + void flip(); + }; + +} diff --git a/micropython/examples/pico_display/buttons.py b/micropython/examples/pico_display/buttons.py index cec17963..c496bedf 100644 --- a/micropython/examples/pico_display/buttons.py +++ b/micropython/examples/pico_display/buttons.py @@ -1,6 +1,7 @@ # This example shows you a simple, non-interrupt way of reading Pico Display's buttons with a loop that checks to see if buttons are pressed. -import picodisplay as display +import picodisplay as display # Comment this line out to use PicoDisplay2 +# import picodisplay2 as display # Uncomment this line to use PicoDisplay2 import utime # Initialise display with a bytearray display buffer diff --git a/micropython/examples/pico_display/demo.py b/micropython/examples/pico_display/demo.py index 5132f556..ce383d70 100644 --- a/micropython/examples/pico_display/demo.py +++ b/micropython/examples/pico_display/demo.py @@ -1,6 +1,7 @@ import time import random -import picodisplay as display +import picodisplay as display # Comment this line out to use PicoDisplay2 +# import picodisplay2 as display # Uncomment this line to use PicoDisplay2 width = display.get_width() height = display.get_height() diff --git a/micropython/examples/pico_display/rainbow.py b/micropython/examples/pico_display/rainbow.py index 8fae5e2e..8ed33c3f 100644 --- a/micropython/examples/pico_display/rainbow.py +++ b/micropython/examples/pico_display/rainbow.py @@ -1,7 +1,8 @@ # This example borrows a CircuitPython hsv_to_rgb function to cycle through some rainbows on Pico Display's screen and RGB LED . If you're into rainbows, HSV (Hue, Saturation, Value) is very useful! import utime -import picodisplay as display +import picodisplay as display # Comment this line out to use PicoDisplay2 +# import picodisplay2 as display # Uncomment this line to use PicoDisplay2 # Set up and initialise Pico Display buf = bytearray(display.get_width() * display.get_height() * 2) diff --git a/micropython/examples/pico_display/thermometer.py b/micropython/examples/pico_display/thermometer.py index bceba3e8..f64a0930 100644 --- a/micropython/examples/pico_display/thermometer.py +++ b/micropython/examples/pico_display/thermometer.py @@ -6,7 +6,9 @@ import utime import gc # Pico Display boilerplate -import picodisplay as display +import picodisplay as display # Comment this line out to use PicoDisplay2 +# import picodisplay2 as display # Uncomment this line to use PicoDisplay2 + width = display.get_width() height = display.get_height() gc.collect() diff --git a/micropython/modules/micropython.cmake b/micropython/modules/micropython.cmake index 30044027..215b3def 100644 --- a/micropython/modules/micropython.cmake +++ b/micropython/modules/micropython.cmake @@ -30,6 +30,7 @@ include(pico_scroll/micropython) include(pico_rgb_keypad/micropython) include(pico_unicorn/micropython) include(pico_display/micropython) +include(pico_display_2/micropython) include(pico_explorer/micropython) include(pico_wireless/micropython) include(plasma/micropython) diff --git a/micropython/modules/pico_display_2/README.md b/micropython/modules/pico_display_2/README.md new file mode 100644 index 00000000..ccf580c4 --- /dev/null +++ b/micropython/modules/pico_display_2/README.md @@ -0,0 +1,206 @@ +# Pico Display Pack - MicroPython + +Pico Display 2.0" Pack is a vibrant 2.0", 320 x 240 pixel IPS LCD screen for your Raspberry Pi Pico, with four useful buttons and a RGB LED. [Click here](https://shop.pimoroni.com/products/pico-display-pack) to find out more! + +We've included helper functions to handle every aspect of drawing to the screen and interfacing with the buttons and LED. See the [function reference](#function-reference) for details. + +Check out [UnfinishedStuff's excellent Display Pack guide](https://github.com/UnfinishedStuff/Pimoroni_Pico_Display_Pack_documentation) for more detail on the functions and code examples, and [tonygo2's Display Pack Workout](https://www.instructables.com/Pimoroni-Pico-Display-Workout/) for a comprehensive demo! + +- [Example Program](#example-program) +- [Function Reference](#function-reference) + - [init](#init) + - [set_backlight](#set_backlight) + - [set_led](#set_led) + - [is_pressed](#is_pressed) + - [update](#update) + - [set_pen](#set_pen) + - [create_pen](#create_pen) + - [clear](#clear) + - [pixel](#pixel) + - [pixel_span](#pixel_span) + - [rectangle](#rectangle) + - [circle](#circle) + - [character](#character) + - [text](#text) + - [set_clip](#set_clip) + - [remove_clip](#remove_clip) + +## Example Program + +The following example sets up Pico Display, displays some basic demo text and illuminates the RGB LED green when the A button is pressed. + +```python +import utime +import picodisplay2 as picodisplay + +# Initialise Picodisplay with a bytearray display buffer +buf = bytearray(picodisplay.get_width() * picodisplay.get_height() * 2) +picodisplay.init(buf) +picodisplay.set_backlight(1.0) + +picodisplay.set_pen(255, 0, 0) # Set a red pen +picodisplay.clear() # Clear the display buffer +picodisplay.set_pen(255, 255, 255) # Set a white pen +picodisplay.text("pico display", 10, 10, 240, 6) # Add some text +picodisplay.update() # Update the display with our changes + +picodisplay.set_led(255, 0, 0) # Set the RGB LED to red +utime.sleep(1) # Wait for a second +picodisplay.set_led(0, 255, 0) # Set the RGB LED to green +utime.sleep(1) # Wait for a second +picodisplay.set_led(0, 0, 255) # Set the RGB LED to blue + +while picodisplay.is_pressed(picodisplay.BUTTON_A) == False: + pass + +picodisplay.set_led(0, 255, 0) # Set the RGB LED to green +``` + +## Function Reference + +### init + +Sets up Pico Display. `init` must be called before any other functions since it configures the required PWM and GPIO. `init()` needs a bytearray type display buffer that MicroPython's garbage collection isn't going to eat, make sure you create one and pass it in like so: + +```python +buf = bytearray(picodisplay.get_width() * picodisplay.get_height() * 2) +picodisplay.init(buf) +``` + +### set_backlight + +Sets the display backlight from 0.0 to 1.0. + +```python +picodisplay.set_backlight(brightness) +``` + +Uses hardware PWM to dim the display backlight, dimming values are gamma-corrected to provide smooth brightness transitions across the full range of intensity. This may result in some low values mapping as "off." + +### set_led + +Sets the RGB LED on Pico Display with an RGB triplet. + +```python +picodisplay.set_led(r, g, b) +``` + +Uses hardware PWM to drive the LED. Values are automatically gamma-corrected to provide smooth brightness transitions and low values may map as "off." + +### is_pressed + +Reads the GPIO pin connected to one of Pico Display's buttons, returning `True` if it's pressed and `False` if it is released. + +```python +picodisplay.is_pressed(button) +``` + +The button value should be a number denoting a pin, and constants `picodisplay.BUTTON_A`, `picodisplay.BUTTON_B`, `picodisplay.BUTTON_X` and `picodisplay.BUTTON_Y` are supplied to make it easier. e: + +```python +is_a_button_pressed = picodisplay.is_pressed(picodisplay.BUTTON_A) +``` + +### update + +To display your changes on Pico Display's screen you need to call `update`. + +```python +picodisplay.update() +``` + +### set_pen + +Sets the colour to be used by subsequent calls to drawing functions. The values for `r`, `g` and `b` should be from 0-255 inclusive. + +```python +picodisplay.set_pen(r, g, b) +``` + +### create_pen + +Creates a pen which can be stored as a variable for faster re-use of the same colour through calls to `set_pen`. The values for `r`, `g` and `b` should be from 0-255 inclusive. + +```python +pen_colour = picodisplay.create_pen(r, g, b) +picodisplay.set_pen(penColour) +``` + +### clear + +Fills the display buffer with the currently set pen colour. + +```python +picodisplay.clear() +``` + +### pixel + +Sets a single pixel in the display buffer to the current pen colour. The `x` and `y` parameters determine the X and Y coordinates of the drawn pixel in the buffer. + +```python +picodisplay.pixel(x, y) +``` + +### pixel_span + +Draws a horizontal line of pixels to the buffer. The `x` and `y` parameters specify the coordinates of the first pixel of the line. The `l` parameter describes the length of the line in pixels. This function will only extend the line towards the end of the screen, i.e. the `x` coordinate should specify the left hand extreme of the line. + +```python +picodisplay.pixel_span(x, y, l) +``` + +### rectangle + +Draws a rectangle filled with the current pen colour to the buffer. The `x` and `y` parameters specify the upper left corner of the rectangle, `w` specifies the width in pixels, and `h` the height. + +```python +picodisplay.rectangle(x, y, w, h) +``` + +![Rectangle function explanation image](/micropython/modules/pico_display/images/rectangle.png) + +### circle + +Draws a circle filled with the current pen colour to the buffer. The `x` and `y` parameters specify the centre of the circle, `r` specifies the radius in pixels. + +```python +picodisplay.circle(x, y, r) +``` + +![Circle function explanation image](/micropython/modules/pico_display/images/circle.png) + +### character + +Draws a single character to the display buffer in the current pen colour. The `c` parameter should be the ASCII numerical representation of the character to be printed, `x` and `y` describe the top-left corner of the character's drawing field. The `character` function can also be given an optional 4th parameter, `scale`, describing the scale of the character to be drawn. Default value is 2. + +```python +char_a = ord('a') +picodisplay.character(char_a, x, y) +picodisplay.character(char_a, x, y, scale) +``` + +### text + +Draws a string of text to the display buffer in the current pen colour. The `string` parameter is the string of text to be drawn, and `x` and `y` specify the upper left corner of the drawing field. The `wrap` parameter describes the width, in pixels, after which the next word in the string will be drawn on a new line underneath the current text. This will wrap the string over multiple lines if required. This function also has an optional parameter, `scale`, which describes the size of the characters to be drawn. The default `scale` is 2. + +```python +picodisplay.text(string, x, y, wrap) +picodisplay.text(string, x, y, wrap, scale) +``` + +![Text scale explanation image](/micropython/modules/pico_display/images/text_scale.png) + +### set_clip + +This function defines a rectangular area outside which no drawing actions will take effect. If a drawing action crosses the boundary of the clip then only the pixels inside the clip will be drawn. Note that `clip` does not remove pixels which have already been drawn, it only prevents new pixels being drawn outside the described area. A more visual description of the function of clips can be found below. Only one clip can be active at a time, and defining a new clip replaces any previous clips. The `x` and `y` parameters describe the upper-left corner of the clip area, `w` and `h` describe the width and height in pixels. + +```python +picodisplay.set_clip(x, y, w, h) +``` + +![Clip function explanation image](/micropython/modules/pico_display/images/clip.png) + +### remove_clip + +This function removes any currently implemented clip. diff --git a/micropython/modules/pico_display_2/images/circle.png b/micropython/modules/pico_display_2/images/circle.png new file mode 100644 index 0000000000000000000000000000000000000000..4efadd9cd87a6b82c01fdbc653e95e405bce6974 GIT binary patch literal 5200 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 literal 0 HcmV?d00001 diff --git a/micropython/modules/pico_display_2/images/rectangle.png b/micropython/modules/pico_display_2/images/rectangle.png new file mode 100644 index 0000000000000000000000000000000000000000..4e0c3467565964aa03a06bc76cc7eea23fa43ff5 GIT binary patch literal 4814 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 DFnxLN literal 0 HcmV?d00001 diff --git a/micropython/modules/pico_display_2/images/text_scale.png b/micropython/modules/pico_display_2/images/text_scale.png new file mode 100644 index 0000000000000000000000000000000000000000..1f029ed2c0258c7d36abc78a28b670ac92b2c4b6 GIT binary patch literal 6698 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 literal 0 HcmV?d00001 diff --git a/micropython/modules/pico_display_2/micropython.cmake b/micropython/modules/pico_display_2/micropython.cmake new file mode 100644 index 00000000..bb710909 --- /dev/null +++ b/micropython/modules/pico_display_2/micropython.cmake @@ -0,0 +1,28 @@ +set(MOD_NAME pico_display_2) +string(TOUPPER ${MOD_NAME} MOD_NAME_UPPER) +add_library(usermod_${MOD_NAME} INTERFACE) + +target_sources(usermod_${MOD_NAME} INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.c + ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/${MOD_NAME}/${MOD_NAME}.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/st7789/st7789.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/pico_graphics/pico_graphics.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../../libraries/pico_graphics/types.cpp +) + +target_include_directories(usermod_${MOD_NAME} INTERFACE + ${CMAKE_CURRENT_LIST_DIR} +) + +target_compile_definitions(usermod_${MOD_NAME} INTERFACE + MODULE_${MOD_NAME_UPPER}_ENABLED=1 +) + +target_link_libraries(usermod INTERFACE usermod_${MOD_NAME}) + +set_source_files_properties( + ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.c + PROPERTIES COMPILE_FLAGS + "-Wno-discarded-qualifiers -Wno-implicit-int" +) diff --git a/micropython/modules/pico_display_2/pico_display_2.c b/micropython/modules/pico_display_2/pico_display_2.c new file mode 100755 index 00000000..64fcfbcb --- /dev/null +++ b/micropython/modules/pico_display_2/pico_display_2.c @@ -0,0 +1,80 @@ +#include "pico_display_2.h" + +/***** Constants *****/ +enum buttons +{ + BUTTON_A = 0, + BUTTON_B, + BUTTON_X, + BUTTON_Y, +}; + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// picodisplay2 Module +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/***** Module Functions *****/ +STATIC MP_DEFINE_CONST_FUN_OBJ_1(picodisplay2_init_obj, picodisplay2_init); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(picodisplay2_get_width_obj, picodisplay2_get_width); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(picodisplay2_get_height_obj, picodisplay2_get_height); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(picodisplay2_update_obj, picodisplay2_update); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(picodisplay2_set_backlight_obj, picodisplay2_set_backlight); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(picodisplay2_set_led_obj, picodisplay2_set_led); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(picodisplay2_is_pressed_obj, picodisplay2_is_pressed); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(picodisplay2_flip_obj, picodisplay2_flip); + +//From PicoGraphics parent class +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picodisplay2_set_pen_obj, 1, 3, picodisplay2_set_pen); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(picodisplay2_create_pen_obj, picodisplay2_create_pen); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picodisplay2_set_clip_obj, 4, 4, picodisplay2_set_clip); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(picodisplay2_remove_clip_obj, picodisplay2_remove_clip); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(picodisplay2_clear_obj, picodisplay2_clear); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(picodisplay2_pixel_obj, picodisplay2_pixel); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(picodisplay2_pixel_span_obj, picodisplay2_pixel_span); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picodisplay2_rectangle_obj, 4, 4, picodisplay2_rectangle); +STATIC MP_DEFINE_CONST_FUN_OBJ_3(picodisplay2_circle_obj, picodisplay2_circle); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picodisplay2_character_obj, 3, 4, picodisplay2_character); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picodisplay2_text_obj, 4, 5, picodisplay2_text); + + +/***** Globals Table *****/ +STATIC const mp_map_elem_t picodisplay2_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_picodisplay2) }, + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&picodisplay2_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_width), MP_ROM_PTR(&picodisplay2_get_width_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_height), MP_ROM_PTR(&picodisplay2_get_height_obj) }, + { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&picodisplay2_update_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_backlight), MP_ROM_PTR(&picodisplay2_set_backlight_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_led), MP_ROM_PTR(&picodisplay2_set_led_obj) }, + { MP_ROM_QSTR(MP_QSTR_is_pressed), MP_ROM_PTR(&picodisplay2_is_pressed_obj) }, + { MP_ROM_QSTR(MP_QSTR_flip), MP_ROM_PTR(&picodisplay2_flip_obj) }, + + { MP_ROM_QSTR(MP_QSTR_set_pen), MP_ROM_PTR(&picodisplay2_set_pen_obj) }, + { MP_ROM_QSTR(MP_QSTR_create_pen), MP_ROM_PTR(&picodisplay2_create_pen_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_clip), MP_ROM_PTR(&picodisplay2_set_clip_obj) }, + { MP_ROM_QSTR(MP_QSTR_remove_clip), MP_ROM_PTR(&picodisplay2_remove_clip_obj) }, + { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&picodisplay2_clear_obj) }, + { MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&picodisplay2_pixel_obj) }, + { MP_ROM_QSTR(MP_QSTR_pixel_span), MP_ROM_PTR(&picodisplay2_pixel_span_obj) }, + { MP_ROM_QSTR(MP_QSTR_rectangle), MP_ROM_PTR(&picodisplay2_rectangle_obj) }, + { MP_ROM_QSTR(MP_QSTR_circle), MP_ROM_PTR(&picodisplay2_circle_obj) }, + { MP_ROM_QSTR(MP_QSTR_character), MP_ROM_PTR(&picodisplay2_character_obj) }, + { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&picodisplay2_text_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_picodisplay2_globals, picodisplay2_globals_table); + +/***** Module Definition *****/ +const mp_obj_module_t picodisplay2_user_cmodule = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_picodisplay2_globals, +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +MP_REGISTER_MODULE(MP_QSTR_picodisplay2, picodisplay2_user_cmodule, MODULE_PICO_DISPLAY_2_ENABLED); +//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/micropython/modules/pico_display_2/pico_display_2.cpp b/micropython/modules/pico_display_2/pico_display_2.cpp new file mode 100644 index 00000000..6268c8a4 --- /dev/null +++ b/micropython/modules/pico_display_2/pico_display_2.cpp @@ -0,0 +1,341 @@ +#include "hardware/spi.h" +#include "hardware/sync.h" +#include "pico/binary_info.h" + +#include "libraries/pico_display_2/pico_display_2.hpp" + +using namespace pimoroni; + +PicoDisplay2 *display2 = nullptr; + + +extern "C" { +#include "pico_display_2.h" + +#define NOT_INITIALISED_MSG "Cannot call this function, as picodisplay2 is not initialised. Call picodisplay2.init() first." + +mp_obj_t picodisplay2_buf_obj; + +mp_obj_t picodisplay2_init(mp_obj_t buf_obj) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_obj, &bufinfo, MP_BUFFER_RW); + picodisplay2_buf_obj = buf_obj; + if(display2 == nullptr) + display2 = new PicoDisplay2((uint16_t *)bufinfo.buf); + display2->init(); + return mp_const_none; +} + +mp_obj_t picodisplay2_get_width() { + return mp_obj_new_int(PicoDisplay2::WIDTH); +} + +mp_obj_t picodisplay2_get_height() { + return mp_obj_new_int(PicoDisplay2::HEIGHT); +} + +mp_obj_t picodisplay2_update() { + if(display2 != nullptr) + display2->update(); + else + mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG); + + return mp_const_none; +} + +mp_obj_t picodisplay2_flip() { + if(display2 != nullptr) + display2->flip(); + else + mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG); + + return mp_const_none; +} + +mp_obj_t picodisplay2_set_backlight(mp_obj_t brightness_obj) { + if(display2 != nullptr) { + 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 + display2->set_backlight((uint8_t)(brightness * 255.0f)); + } + else + mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG); + + return mp_const_none; +} + +mp_obj_t picodisplay2_set_led(mp_obj_t r_obj, mp_obj_t g_obj, mp_obj_t b_obj) { + if(display2 != nullptr) { + 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 + display2->set_led(r, g, b); + } + else + mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG); + + return mp_const_none; +} + +mp_obj_t picodisplay2_is_pressed(mp_obj_t button_obj) { + bool buttonPressed = false; + + if(display2 != nullptr) { + int buttonID = mp_obj_get_int(button_obj); + switch(buttonID) { + case 0: + buttonPressed = display2->is_pressed(PicoDisplay2::A); + break; + + case 1: + buttonPressed = display2->is_pressed(PicoDisplay2::B); + break; + + case 2: + buttonPressed = display2->is_pressed(PicoDisplay2::X); + break; + + case 3: + buttonPressed = display2->is_pressed(PicoDisplay2::Y); + break; + + default: + mp_raise_ValueError("button not valid. Expected 0 to 3"); + break; + } + } + else + mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG); + + return buttonPressed ? mp_const_true : mp_const_false; +} + +mp_obj_t picodisplay2_set_pen(mp_uint_t n_args, const mp_obj_t *args) { + if(display2 != nullptr) { + switch(n_args) { + case 1: { + int p = mp_obj_get_int(args[0]); + + if(p < 0 || p > 0xffff) + mp_raise_ValueError("p is not a valid pen."); + else + display2->set_pen(p); + } break; + + case 3: { + int r = mp_obj_get_int(args[0]); + int g = mp_obj_get_int(args[1]); + int b = mp_obj_get_int(args[2]); + + 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 + display2->set_pen(r, g, b); + } break; + + default: { + char *buffer; + buffer = (char*)malloc(100); + sprintf(buffer, "function takes 1 or 3 (r,g,b) positional arguments but %d were given", n_args); + mp_raise_TypeError(buffer); + } break; + } + } + else + mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG); + + return mp_const_none; +} + +mp_obj_t picodisplay2_create_pen(mp_obj_t r_obj, mp_obj_t g_obj, mp_obj_t b_obj) { + int pen = 0; + + if(display2 != nullptr) { + 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 + pen = display2->create_pen(r, g, b); + } + else + mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG); + + return mp_obj_new_int(pen); +} + +mp_obj_t picodisplay2_set_clip(mp_uint_t n_args, const mp_obj_t *args) { + (void)n_args; //Unused input parameter, we know it's 4 + + if(display2 != nullptr) { + int x = mp_obj_get_int(args[0]); + int y = mp_obj_get_int(args[1]); + int w = mp_obj_get_int(args[2]); + int h = mp_obj_get_int(args[3]); + + Rect r(x, y, w, h); + display2->set_clip(r); + } + else + mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG); + + return mp_const_none; +} + +mp_obj_t picodisplay2_remove_clip() { + if(display2 != nullptr) + display2->remove_clip(); + else + mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG); + + return mp_const_none; +} + +mp_obj_t picodisplay2_clear() { + if(display2 != nullptr) + display2->clear(); + else + mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG); + + return mp_const_none; +} + +mp_obj_t picodisplay2_pixel(mp_obj_t x_obj, mp_obj_t y_obj) { + if(display2 != nullptr) { + int x = mp_obj_get_int(x_obj); + int y = mp_obj_get_int(y_obj); + + Point p(x, y); + display2->pixel(p); + } + else + mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG); + + return mp_const_none; +} + +mp_obj_t picodisplay2_pixel_span(mp_obj_t x_obj, mp_obj_t y_obj, mp_obj_t l_obj) { + if(display2 != nullptr) { + int x = mp_obj_get_int(x_obj); + int y = mp_obj_get_int(y_obj); + int l = mp_obj_get_int(l_obj); + + Point p(x, y); + display2->pixel_span(p, l); + } + else + mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG); + + return mp_const_none; +} + +mp_obj_t picodisplay2_rectangle(mp_uint_t n_args, const mp_obj_t *args) { + (void)n_args; //Unused input parameter, we know it's 4 + + if(display2 != nullptr) { + int x = mp_obj_get_int(args[0]); + int y = mp_obj_get_int(args[1]); + int w = mp_obj_get_int(args[2]); + int h = mp_obj_get_int(args[3]); + + Rect r(x, y, w, h); + display2->rectangle(r); + } + else + mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG); + + return mp_const_none; +} + +mp_obj_t picodisplay2_circle(mp_obj_t x_obj, mp_obj_t y_obj, mp_obj_t r_obj) { + if(display2 != nullptr) { + int x = mp_obj_get_int(x_obj); + int y = mp_obj_get_int(y_obj); + int r = mp_obj_get_int(r_obj); + + Point p(x, y); + display2->circle(p, r); + } + else + mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG); + + return mp_const_none; +} + +mp_obj_t picodisplay2_character(mp_uint_t n_args, const mp_obj_t *args) { + if(display2 != nullptr) { + int c = mp_obj_get_int(args[0]); + int x = mp_obj_get_int(args[1]); + int y = mp_obj_get_int(args[2]); + + Point p(x, y); + if(n_args == 4) { + int scale = mp_obj_get_int(args[3]); + display2->character((char)c, p, scale); + } + else + display2->character((char)c, p); + } + + return mp_const_none; +} + +mp_obj_t picodisplay2_text(mp_uint_t n_args, const mp_obj_t *args) { + if(display2 != nullptr) { + if(mp_obj_is_str_or_bytes(args[0])) { + GET_STR_DATA_LEN(args[0], str, str_len); + + std::string t((const char*)str); + + int x = mp_obj_get_int(args[1]); + int y = mp_obj_get_int(args[2]); + int wrap = mp_obj_get_int(args[3]); + + Point p(x, y); + if(n_args == 5) { + int scale = mp_obj_get_int(args[4]); + display2->text(t, p, wrap, scale); + } + else + display2->text(t, p, wrap); + } + else if(mp_obj_is_float(args[0])) { + mp_raise_TypeError("can't convert 'float' object to str implicitly"); + } + else if(mp_obj_is_int(args[0])) { + mp_raise_TypeError("can't convert 'int' object to str implicitly"); + } + else if(mp_obj_is_bool(args[0])) { + mp_raise_TypeError("can't convert 'bool' object to str implicitly"); + } + else { + mp_raise_TypeError("can't convert object to str implicitly"); + } + } + else + mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG); + + return mp_const_none; +} +} diff --git a/micropython/modules/pico_display_2/pico_display_2.h b/micropython/modules/pico_display_2/pico_display_2.h new file mode 100644 index 00000000..bccd69dd --- /dev/null +++ b/micropython/modules/pico_display_2/pico_display_2.h @@ -0,0 +1,26 @@ +// Include MicroPython API. +#include "py/runtime.h" +#include "py/objstr.h" + +// Declare the functions we'll make available in Python +extern mp_obj_t picodisplay2_init(mp_obj_t buf_obj); +extern mp_obj_t picodisplay2_get_width(); +extern mp_obj_t picodisplay2_get_height(); +extern mp_obj_t picodisplay2_set_backlight(mp_obj_t brightness_obj); +extern mp_obj_t picodisplay2_update(); +extern mp_obj_t picodisplay2_set_led(mp_obj_t r_obj, mp_obj_t g_obj, mp_obj_t b_obj); +extern mp_obj_t picodisplay2_is_pressed(mp_obj_t button_obj); +extern mp_obj_t picodisplay2_flip(); + +// From PicoGraphics parent class +extern mp_obj_t picodisplay2_set_pen(mp_uint_t n_args, const mp_obj_t *args); +extern mp_obj_t picodisplay2_create_pen(mp_obj_t r_obj, mp_obj_t g_obj, mp_obj_t b_obj); +extern mp_obj_t picodisplay2_set_clip(mp_uint_t n_args, const mp_obj_t *args); +extern mp_obj_t picodisplay2_remove_clip(); +extern mp_obj_t picodisplay2_clear(); +extern mp_obj_t picodisplay2_pixel(mp_obj_t x_obj, mp_obj_t y_obj); +extern mp_obj_t picodisplay2_pixel_span(mp_obj_t x_obj, mp_obj_t y_obj, mp_obj_t l_obj); +extern mp_obj_t picodisplay2_rectangle(mp_uint_t n_args, const mp_obj_t *args); +extern mp_obj_t picodisplay2_circle(mp_obj_t x_obj, mp_obj_t y_obj, mp_obj_t r_obj); +extern mp_obj_t picodisplay2_character(mp_uint_t n_args, const mp_obj_t *args); +extern mp_obj_t picodisplay2_text(mp_uint_t n_args, const mp_obj_t *args);