Merge pull request #170 from pimoroni/driver/320x240lcd
320x240 LCD library + tweaks to ST7789 driver
This commit is contained in:
commit
2d465da3fa
|
@ -50,10 +50,11 @@ namespace pimoroni {
|
|||
RAMWR = 0x2C,
|
||||
INVON = 0x21,
|
||||
CASET = 0x2A,
|
||||
RASET = 0x2B
|
||||
RASET = 0x2B,
|
||||
PWMFRSEL = 0xCC
|
||||
};
|
||||
|
||||
void ST7789::init(bool auto_init_sequence, bool round) {
|
||||
void ST7789::init(bool auto_init_sequence, bool round, uint32_t spi_baud) {
|
||||
// configure spi interface and pins
|
||||
spi_init(spi, spi_baud);
|
||||
|
||||
|
@ -112,6 +113,21 @@ namespace pimoroni {
|
|||
command(reg::GMCTRN1, 14, "\xD0\x04\x0C\x11\x13\x2C\x3F\x44\x51\x2F\x1F\x1F\x20\x23");
|
||||
}
|
||||
|
||||
if(width == 320 && height == 240) {
|
||||
command(reg::PORCTRL, 5, "\x0c\x0c\x00\x33\x33");
|
||||
command(reg::GCTRL, 1, "\x35");
|
||||
command(reg::VCOMS, 1, "\x1f");
|
||||
command(reg::LCMCTRL, 1, "\x2c");
|
||||
command(reg::VDVVRHEN, 1, "\x01");
|
||||
command(reg::VRHS, 1, "\x12");
|
||||
command(reg::VDVS, 1, "\x20");
|
||||
command(reg::FRCTRL2, 1, "\x0f");
|
||||
command(reg::PWCTRL1, 2, "\xa4\xa1");
|
||||
command(0xd6, 1, "\xa1"); // ???
|
||||
command(reg::GMCTRP1, 14, "\xD0\x08\x11\x08\x0C\x15\x39\x33\x50\x36\x13\x14\x29\x2D");
|
||||
command(reg::GMCTRN1, 14, "\xD0\x08\x10\x08\x06\x06\x39\x44\x51\x0B\x16\x14\x2F\x31");
|
||||
}
|
||||
|
||||
command(reg::INVON); // set inversion mode
|
||||
command(reg::SLPOUT); // leave sleep mode
|
||||
command(reg::DISPON); // turn display on
|
||||
|
@ -143,6 +159,14 @@ namespace pimoroni {
|
|||
madctl = 0;
|
||||
}
|
||||
|
||||
if(width == 320 && height == 240) {
|
||||
caset[0] = 0;
|
||||
caset[1] = 319;
|
||||
raset[0] = 0;
|
||||
raset[1] = 239;
|
||||
madctl = 0x70;
|
||||
}
|
||||
|
||||
// Byte swap the 16bit rows/cols values
|
||||
caset[0] = __builtin_bswap16(caset[0]);
|
||||
caset[1] = __builtin_bswap16(caset[1]);
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace pimoroni {
|
|||
uint bl = SPI_BG_FRONT_PWM;
|
||||
uint vsync = PIN_UNUSED; // only available on some products
|
||||
|
||||
uint32_t spi_baud = 16 * 1000 * 1000;
|
||||
static const uint32_t SPI_BAUD = 16 * 1000 * 1000;
|
||||
|
||||
public:
|
||||
// frame buffer where pixel data is stored
|
||||
|
@ -68,7 +68,7 @@ namespace pimoroni {
|
|||
// Methods
|
||||
//--------------------------------------------------
|
||||
public:
|
||||
void init(bool auto_init_sequence = true, bool round = false);
|
||||
void init(bool auto_init_sequence = true, bool round = false, uint32_t spi_baud = SPI_BAUD);
|
||||
|
||||
spi_inst_t* get_spi() const;
|
||||
uint get_cs() const;
|
||||
|
|
|
@ -20,6 +20,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)
|
||||
|
|
|
@ -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})
|
|
@ -0,0 +1,111 @@
|
|||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
|
||||
#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<pt> 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;
|
||||
}
|
|
@ -17,6 +17,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)
|
||||
|
|
|
@ -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)
|
|
@ -0,0 +1,123 @@
|
|||
# Pico Display 2.0" Pack <!-- omit in toc -->
|
||||
|
||||
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();
|
||||
```
|
|
@ -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)
|
|
@ -0,0 +1,90 @@
|
|||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
};
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
# Pico Display Pack - MicroPython <!-- omit in toc -->
|
||||
|
||||
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.
|
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.5 KiB |
|
@ -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"
|
||||
)
|
|
@ -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);
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
@ -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(<bytearray>) 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;
|
||||
}
|
||||
}
|
|
@ -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);
|
Loading…
Reference in New Issue