Merge pull request #103 from pimoroni/Pinkyatacme-disp_enhance
ST7789 refactor + round LCD support
This commit is contained in:
commit
1fb7dcd358
|
@ -1,4 +1 @@
|
|||
add_library(st7789 st7789.cpp)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(st7789 pico_stdlib hardware_spi hardware_pwm hardware_dma)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/st7789.cmake)
|
|
@ -1,5 +1,7 @@
|
|||
add_library(st7789
|
||||
${CMAKE_CURRENT_LIST_DIR}/st7789.cpp)
|
||||
|
||||
target_include_directories(st7789 INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(st7789 pico_stdlib hardware_spi hardware_pwm hardware_dma)
|
||||
|
|
|
@ -1,150 +1,174 @@
|
|||
#include "st7789.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <math.h>
|
||||
|
||||
#include "hardware/dma.h"
|
||||
#include "hardware/pwm.h"
|
||||
|
||||
namespace pimoroni {
|
||||
|
||||
void ST7789::init(bool auto_init_sequence) {
|
||||
// configure spi interface and pins
|
||||
spi_init(spi, spi_baud);
|
||||
|
||||
gpio_set_function(dc, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(dc, GPIO_OUT);
|
||||
|
||||
gpio_set_function(cs, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(cs, GPIO_OUT);
|
||||
|
||||
gpio_set_function(sck, GPIO_FUNC_SPI);
|
||||
gpio_set_function(mosi, GPIO_FUNC_SPI);
|
||||
|
||||
if(miso != -1) {
|
||||
gpio_set_function(miso, GPIO_FUNC_SPI);
|
||||
}
|
||||
|
||||
// if supported by the display then the vsync pin is
|
||||
// toggled high during vertical blanking period
|
||||
if(vsync != -1) {
|
||||
gpio_set_function(vsync, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(vsync, GPIO_IN);
|
||||
gpio_set_pulls(vsync, false, true);
|
||||
}
|
||||
|
||||
// if a backlight pin is provided then set it up for
|
||||
// pwm control
|
||||
if(bl != -1) {
|
||||
pwm_config cfg = pwm_get_default_config();
|
||||
pwm_set_wrap(pwm_gpio_to_slice_num(bl), 65535);
|
||||
pwm_init(pwm_gpio_to_slice_num(bl), &cfg, true);
|
||||
gpio_set_function(bl, GPIO_FUNC_PWM);
|
||||
}
|
||||
|
||||
// if auto_init_sequence then send initialisation sequence
|
||||
// for our standard displays based on the width and height
|
||||
if(auto_init_sequence) {
|
||||
command(reg::SWRESET);
|
||||
|
||||
sleep_ms(150);
|
||||
|
||||
if(width == 240 && height == 240) {
|
||||
command(reg::MADCTL, 1, "\x04"); // row/column addressing order - rgb pixel order
|
||||
command(reg::TEON, 1, "\x00"); // enable frame sync signal if used
|
||||
command(reg::COLMOD, 1, "\x05"); // 16 bits per pixel
|
||||
}
|
||||
|
||||
if(width == 240 && height == 135) {
|
||||
command(reg::MADCTL, 1, "\x70");
|
||||
command(reg::COLMOD, 1, "\x05");
|
||||
}
|
||||
|
||||
command(reg::INVON); // set inversion mode
|
||||
command(reg::SLPOUT); // leave sleep mode
|
||||
command(reg::DISPON); // turn display on
|
||||
|
||||
sleep_ms(100);
|
||||
|
||||
// setup correct addressing window
|
||||
if(width == 240 && height == 240) {
|
||||
command(reg::CASET, 4, "\x00\x00\x00\xef"); // 0 .. 239 columns
|
||||
command(reg::RASET, 4, "\x00\x00\x00\xef"); // 0 .. 239 rows
|
||||
}
|
||||
|
||||
if(width == 240 && height == 135) {
|
||||
command(reg::RASET, 4, "\x00\x35\x00\xbb"); // 53 .. 187 (135 rows)
|
||||
command(reg::CASET, 4, "\x00\x28\x01\x17"); // 40 .. 279 (240 columns)
|
||||
}
|
||||
}
|
||||
|
||||
// the dma transfer works but without vsync it's not that useful as you could
|
||||
// be updating the framebuffer during transfer...
|
||||
//
|
||||
// this could be avoided by creating another buffer to draw into and flip
|
||||
// buffers (but costs another ~100kb of ram)
|
||||
//
|
||||
// it's probably not worth it for this particular usecase but will consider it
|
||||
// some more...
|
||||
|
||||
// setup spi for 16-bit transfers
|
||||
// spi_set_format(spi, 16, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
|
||||
|
||||
// initialise dma channel for transmitting pixel data to screen
|
||||
// dma_channel = dma_claim_unused_channel(true);
|
||||
// dma_channel_config config = dma_channel_get_default_config(dma_channel);
|
||||
// channel_config_set_transfer_data_size(&config, DMA_SIZE_16);
|
||||
// channel_config_set_dreq(&config, spi_get_index(spi) ? DREQ_SPI1_TX : DREQ_SPI0_TX);
|
||||
// dma_channel_configure(
|
||||
// dma_channel, &config, &spi_get_hw(spi)->dr, frame_buffer, width * height, false);
|
||||
}
|
||||
|
||||
void ST7789::command(uint8_t command, size_t len, const char *data) {
|
||||
//dma_channel_wait_for_finish_blocking(dma_channel);
|
||||
|
||||
gpio_put(cs, 0);
|
||||
|
||||
gpio_put(dc, 0); // command mode
|
||||
spi_write_blocking(spi, &command, 1);
|
||||
|
||||
if(data) {
|
||||
gpio_put(dc, 1); // data mode
|
||||
spi_write_blocking(spi, (const uint8_t*)data, len);
|
||||
}
|
||||
|
||||
gpio_put(cs, 1);
|
||||
}
|
||||
|
||||
void ST7789::update(bool dont_block) {
|
||||
ST7789::command(reg::RAMWR, width * height * sizeof(uint16_t), (const char*)frame_buffer);
|
||||
|
||||
/*if(dma_channel_is_busy(dma_channel) && dont_block) {
|
||||
return;
|
||||
}
|
||||
|
||||
dma_channel_wait_for_finish_blocking(dma_channel);
|
||||
|
||||
uint8_t r = reg::RAMWR;
|
||||
|
||||
gpio_put(cs, 0);
|
||||
|
||||
gpio_put(dc, 0); // command mode
|
||||
spi_write_blocking(spi, &r, 1);
|
||||
|
||||
gpio_put(dc, 1); // data mode
|
||||
|
||||
dma_channel_set_read_addr(dma_channel, frame_buffer, true);*/
|
||||
}
|
||||
|
||||
void ST7789::set_backlight(uint8_t brightness) {
|
||||
// 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) * 65535.0f + 0.5f);
|
||||
pwm_set_gpio_level(bl, value);
|
||||
}
|
||||
|
||||
void ST7789::vsync_callback(gpio_irq_callback_t callback) {
|
||||
gpio_set_irq_enabled_with_callback(vsync, GPIO_IRQ_EDGE_RISE, true, callback);
|
||||
}
|
||||
}
|
||||
#include "st7789.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <math.h>
|
||||
|
||||
#include "hardware/dma.h"
|
||||
#include "hardware/pwm.h"
|
||||
|
||||
namespace pimoroni {
|
||||
uint8_t madctl;
|
||||
uint16_t caset[2] = {0, 0};
|
||||
uint16_t raset[2] = {0, 0};
|
||||
|
||||
void ST7789::init(bool auto_init_sequence, bool round) {
|
||||
// configure spi interface and pins
|
||||
spi_init(spi, spi_baud);
|
||||
|
||||
gpio_set_function(dc, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(dc, GPIO_OUT);
|
||||
|
||||
gpio_set_function(cs, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(cs, GPIO_OUT);
|
||||
|
||||
gpio_set_function(sck, GPIO_FUNC_SPI);
|
||||
gpio_set_function(mosi, GPIO_FUNC_SPI);
|
||||
|
||||
if(miso != -1) {
|
||||
gpio_set_function(miso, GPIO_FUNC_SPI);
|
||||
}
|
||||
|
||||
// if supported by the display then the vsync pin is
|
||||
// toggled high during vertical blanking period
|
||||
if(vsync != -1) {
|
||||
gpio_set_function(vsync, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(vsync, GPIO_IN);
|
||||
gpio_set_pulls(vsync, false, true);
|
||||
}
|
||||
|
||||
// if a backlight pin is provided then set it up for
|
||||
// pwm control
|
||||
if(bl != -1) {
|
||||
pwm_config cfg = pwm_get_default_config();
|
||||
pwm_set_wrap(pwm_gpio_to_slice_num(bl), 65535);
|
||||
pwm_init(pwm_gpio_to_slice_num(bl), &cfg, true);
|
||||
gpio_set_function(bl, GPIO_FUNC_PWM);
|
||||
}
|
||||
|
||||
// if auto_init_sequence then send initialisation sequence
|
||||
// for our standard displays based on the width and height
|
||||
if(auto_init_sequence) {
|
||||
command(reg::SWRESET);
|
||||
|
||||
sleep_ms(150);
|
||||
|
||||
command(reg::TEON, 1, "\x00"); // enable frame sync signal if used
|
||||
command(reg::COLMOD, 1, "\x05"); // 16 bits per pixel
|
||||
|
||||
command(reg::INVON); // set inversion mode
|
||||
command(reg::SLPOUT); // leave sleep mode
|
||||
command(reg::DISPON); // turn display on
|
||||
|
||||
sleep_ms(100);
|
||||
|
||||
// setup correct addressing window
|
||||
if(width == 240 && height == 240) {
|
||||
caset[0] = 0;
|
||||
caset[1] = 239;
|
||||
raset[0] = round ? 40 : 0;
|
||||
raset[1] = round ? 279 : 239;
|
||||
madctl = MADCTL::HORIZ_ORDER;
|
||||
}
|
||||
|
||||
if(width == 240 && height == 135) {
|
||||
caset[0] = 40; // 240 cols
|
||||
caset[1] = 279;
|
||||
raset[0] = 53; // 135 rows
|
||||
raset[1] = 187;
|
||||
madctl = MADCTL::COL_ORDER | MADCTL::SWAP_XY | MADCTL::SCAN_ORDER;
|
||||
}
|
||||
|
||||
if(width == 135 && height == 240) {
|
||||
caset[0] = 52; // 135 cols
|
||||
caset[1] = 186;
|
||||
raset[0] = 40; // 240 rows
|
||||
raset[1] = 279;
|
||||
madctl = 0;
|
||||
}
|
||||
|
||||
// Byte swap the 16bit rows/cols values
|
||||
caset[0] = __builtin_bswap16(caset[0]);
|
||||
caset[1] = __builtin_bswap16(caset[1]);
|
||||
raset[0] = __builtin_bswap16(raset[0]);
|
||||
raset[1] = __builtin_bswap16(raset[1]);
|
||||
|
||||
command(reg::CASET, 4, (char *)caset);
|
||||
command(reg::RASET, 4, (char *)raset);
|
||||
command(reg::MADCTL, 1, (char *)&madctl);
|
||||
}
|
||||
|
||||
// the dma transfer works but without vsync it's not that useful as you could
|
||||
// be updating the framebuffer during transfer...
|
||||
//
|
||||
// this could be avoided by creating another buffer to draw into and flip
|
||||
// buffers (but costs another ~100kb of ram)
|
||||
//
|
||||
// it's probably not worth it for this particular usecase but will consider it
|
||||
// some more...
|
||||
|
||||
// setup spi for 16-bit transfers
|
||||
// spi_set_format(spi, 16, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
|
||||
|
||||
// initialise dma channel for transmitting pixel data to screen
|
||||
// dma_channel = dma_claim_unused_channel(true);
|
||||
// dma_channel_config config = dma_channel_get_default_config(dma_channel);
|
||||
// channel_config_set_transfer_data_size(&config, DMA_SIZE_16);
|
||||
// channel_config_set_dreq(&config, spi_get_index(spi) ? DREQ_SPI1_TX : DREQ_SPI0_TX);
|
||||
// dma_channel_configure(
|
||||
// dma_channel, &config, &spi_get_hw(spi)->dr, frame_buffer, width * height, false);
|
||||
}
|
||||
|
||||
void ST7789::command(uint8_t command, size_t len, const char *data) {
|
||||
//dma_channel_wait_for_finish_blocking(dma_channel);
|
||||
|
||||
gpio_put(cs, 0);
|
||||
|
||||
gpio_put(dc, 0); // command mode
|
||||
spi_write_blocking(spi, &command, 1);
|
||||
|
||||
if(data) {
|
||||
gpio_put(dc, 1); // data mode
|
||||
spi_write_blocking(spi, (const uint8_t*)data, len);
|
||||
}
|
||||
|
||||
gpio_put(cs, 1);
|
||||
}
|
||||
|
||||
void ST7789::update(bool dont_block) {
|
||||
ST7789::command(reg::RAMWR, width * height * sizeof(uint16_t), (const char*)frame_buffer);
|
||||
|
||||
/*if(dma_channel_is_busy(dma_channel) && dont_block) {
|
||||
return;
|
||||
}
|
||||
|
||||
dma_channel_wait_for_finish_blocking(dma_channel);
|
||||
|
||||
uint8_t r = reg::RAMWR;
|
||||
|
||||
gpio_put(cs, 0);
|
||||
|
||||
gpio_put(dc, 0); // command mode
|
||||
spi_write_blocking(spi, &r, 1);
|
||||
|
||||
gpio_put(dc, 1); // data mode
|
||||
|
||||
dma_channel_set_read_addr(dma_channel, frame_buffer, true);*/
|
||||
}
|
||||
|
||||
void ST7789::set_backlight(uint8_t brightness) {
|
||||
// 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) * 65535.0f + 0.5f);
|
||||
pwm_set_gpio_level(bl, value);
|
||||
}
|
||||
|
||||
void ST7789::vsync_callback(gpio_irq_callback_t callback) {
|
||||
gpio_set_irq_enabled_with_callback(vsync, GPIO_IRQ_EDGE_RISE, true, callback);
|
||||
}
|
||||
|
||||
void ST7789::flip(){
|
||||
madctl ^= MADCTL::ROW_ORDER | MADCTL::COL_ORDER;
|
||||
command(reg::MADCTL, 1, (char *)&madctl);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,80 +1,95 @@
|
|||
#pragma once
|
||||
|
||||
#include "hardware/spi.h"
|
||||
#include "hardware/gpio.h"
|
||||
|
||||
namespace pimoroni {
|
||||
|
||||
class ST7789 {
|
||||
spi_inst_t *spi = spi0;
|
||||
|
||||
uint32_t dma_channel;
|
||||
|
||||
// screen properties
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
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 bl = 20;
|
||||
int8_t vsync = -1; // only available on some products
|
||||
|
||||
uint32_t spi_baud = 64 * 1024 * 1024;
|
||||
|
||||
public:
|
||||
// frame buffer where pixel data is stored
|
||||
uint16_t *frame_buffer;
|
||||
|
||||
public:
|
||||
ST7789(uint16_t width, uint16_t height, uint16_t *frame_buffer) :
|
||||
width(width), height(height), frame_buffer(frame_buffer) {}
|
||||
|
||||
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) :
|
||||
spi(spi),
|
||||
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);
|
||||
|
||||
void command(uint8_t command, size_t len = 0, const char *data = NULL);
|
||||
void vsync_callback(gpio_irq_callback_t callback);
|
||||
void update(bool dont_block = false);
|
||||
void set_backlight(uint8_t brightness);
|
||||
|
||||
enum reg {
|
||||
SWRESET = 0x01,
|
||||
TEON = 0x35,
|
||||
MADCTL = 0x36,
|
||||
COLMOD = 0x3A,
|
||||
GCTRL = 0xB7,
|
||||
VCOMS = 0xBB,
|
||||
LCMCTRL = 0xC0,
|
||||
VDVVRHEN = 0xC2,
|
||||
VRHS = 0xC3,
|
||||
VDVS = 0xC4,
|
||||
FRCTRL2 = 0xC6,
|
||||
PWRCTRL1 = 0xD0,
|
||||
FRMCTR1 = 0xB1,
|
||||
FRMCTR2 = 0xB2,
|
||||
GMCTRP1 = 0xE0,
|
||||
GMCTRN1 = 0xE1,
|
||||
INVOFF = 0x20,
|
||||
SLPOUT = 0x11,
|
||||
DISPON = 0x29,
|
||||
GAMSET = 0x26,
|
||||
DISPOFF = 0x28,
|
||||
RAMWR = 0x2C,
|
||||
INVON = 0x21,
|
||||
CASET = 0x2A,
|
||||
RASET = 0x2B
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
#pragma once
|
||||
|
||||
#include "hardware/spi.h"
|
||||
#include "hardware/gpio.h"
|
||||
|
||||
namespace pimoroni {
|
||||
|
||||
class ST7789 {
|
||||
spi_inst_t *spi = spi0;
|
||||
|
||||
uint32_t dma_channel;
|
||||
|
||||
// screen properties
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
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 bl = 21;
|
||||
int8_t vsync = -1; // only available on some products
|
||||
|
||||
uint32_t spi_baud = 64 * 1024 * 1024;
|
||||
|
||||
public:
|
||||
// frame buffer where pixel data is stored
|
||||
uint16_t *frame_buffer;
|
||||
|
||||
public:
|
||||
ST7789(uint16_t width, uint16_t height, uint16_t *frame_buffer) :
|
||||
width(width), height(height), frame_buffer(frame_buffer) {}
|
||||
|
||||
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) :
|
||||
spi(spi),
|
||||
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, bool round = false);
|
||||
|
||||
void command(uint8_t command, size_t len = 0, const char *data = NULL);
|
||||
void vsync_callback(gpio_irq_callback_t callback);
|
||||
void update(bool dont_block = false);
|
||||
void set_backlight(uint8_t brightness);
|
||||
void flip();
|
||||
|
||||
enum MADCTL : uint8_t {
|
||||
ROW_ORDER = 0b10000000,
|
||||
COL_ORDER = 0b01000000,
|
||||
SWAP_XY = 0b00100000, // AKA "MV"
|
||||
SCAN_ORDER = 0b00010000,
|
||||
RGB = 0b00001000,
|
||||
HORIZ_ORDER = 0b00000100
|
||||
};
|
||||
|
||||
#define ROT_240_240_0 0
|
||||
#define ROT_240_240_90 MADCTL::SWAP_XY | MADCTL::HORIZ_ORDER | MADCTL::COL_ORDER
|
||||
#define ROT_240_240_180 MADCTL::SCAN_ORDER | MADCTL::HORIZ_ORDER | MADCTL::COL_ORDER | MADCTL::ROW_ORDER
|
||||
#define ROT_240_240_270 MADCTL::SWAP_XY | MADCTL::HORIZ_ORDER | MADCTL::ROW_ORDER
|
||||
|
||||
enum reg {
|
||||
SWRESET = 0x01,
|
||||
TEON = 0x35,
|
||||
MADCTL = 0x36,
|
||||
COLMOD = 0x3A,
|
||||
GCTRL = 0xB7,
|
||||
VCOMS = 0xBB,
|
||||
LCMCTRL = 0xC0,
|
||||
VDVVRHEN = 0xC2,
|
||||
VRHS = 0xC3,
|
||||
VDVS = 0xC4,
|
||||
FRCTRL2 = 0xC6,
|
||||
PWRCTRL1 = 0xD0,
|
||||
FRMCTR1 = 0xB1,
|
||||
FRMCTR2 = 0xB2,
|
||||
GMCTRP1 = 0xE0,
|
||||
GMCTRN1 = 0xE1,
|
||||
INVOFF = 0x20,
|
||||
SLPOUT = 0x11,
|
||||
DISPON = 0x29,
|
||||
GAMSET = 0x26,
|
||||
DISPOFF = 0x28,
|
||||
RAMWR = 0x2C,
|
||||
INVON = 0x21,
|
||||
CASET = 0x2A,
|
||||
RASET = 0x2B
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -6,3 +6,4 @@ add_subdirectory(pico_explorer)
|
|||
add_subdirectory(pico_rgb_keypad)
|
||||
add_subdirectory(pico_rtc_display)
|
||||
add_subdirectory(pico_tof_display)
|
||||
add_subdirectory(st7789)
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
add_executable(
|
||||
st7789_demo
|
||||
demo.cpp
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(st7789_demo pico_stdlib hardware_spi st7789 pico_graphics)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(st7789_demo)
|
|
@ -0,0 +1,59 @@
|
|||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "st7789.hpp"
|
||||
#include "pico_graphics.hpp"
|
||||
|
||||
#define CS 17
|
||||
#define DC 16
|
||||
#define SCK 18
|
||||
#define MOSI 19
|
||||
#define MISO -1
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
class PicoDisplay : public PicoGraphics {
|
||||
public:
|
||||
static const int WIDTH = 240;
|
||||
static const int HEIGHT = 240;
|
||||
|
||||
uint16_t *__fb;
|
||||
private:
|
||||
ST7789 screen;
|
||||
|
||||
public:
|
||||
PicoDisplay(uint16_t *buf) : PicoGraphics(WIDTH, HEIGHT, buf),
|
||||
screen(WIDTH, HEIGHT, buf,
|
||||
spi0,
|
||||
CS, DC, SCK, MOSI, MISO) {
|
||||
__fb = buf;
|
||||
}
|
||||
|
||||
void init() {
|
||||
screen.init(true, true);
|
||||
//screen.flip();
|
||||
};
|
||||
void update() {
|
||||
screen.update();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
uint16_t buffer[PicoDisplay::WIDTH * PicoDisplay::HEIGHT];
|
||||
PicoDisplay display(buffer);
|
||||
|
||||
int main() {
|
||||
display.init();
|
||||
|
||||
while(1) {
|
||||
display.set_pen(0, 0, 0);
|
||||
display.clear();
|
||||
display.set_pen(255, 0, 0);
|
||||
display.circle(Point(60, 120), 60);
|
||||
display.set_pen(255, 255, 255);
|
||||
display.text("Hello", Point(10, 10), 220, 4);
|
||||
display.update();
|
||||
}
|
||||
}
|
|
@ -17,6 +17,11 @@ namespace pimoroni {
|
|||
__fb = buf;
|
||||
}
|
||||
|
||||
PicoDisplay::PicoDisplay(uint16_t *buf, int width, int height)
|
||||
: PicoGraphics(width, height, buf), screen(width, height, buf) {
|
||||
__fb = buf;
|
||||
}
|
||||
|
||||
void PicoDisplay::init() {
|
||||
// setup the rgb led for pwm control
|
||||
pwm_config cfg = pwm_get_default_config();
|
||||
|
@ -79,4 +84,7 @@ namespace pimoroni {
|
|||
return !gpio_get(button);
|
||||
}
|
||||
|
||||
}
|
||||
void PicoDisplay::flip() {
|
||||
screen.flip();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,9 @@ namespace pimoroni {
|
|||
public:
|
||||
static const int WIDTH = 240;
|
||||
static const int HEIGHT = 135;
|
||||
static const uint8_t A = 12;
|
||||
static const int PORTRAIT_WIDTH = 135;
|
||||
static const int PORTRAIT_HEIGHT = 240;
|
||||
static const uint8_t A = 12;
|
||||
static const uint8_t B = 13;
|
||||
static const uint8_t X = 14;
|
||||
static const uint8_t Y = 15;
|
||||
|
@ -20,12 +22,14 @@ namespace pimoroni {
|
|||
|
||||
public:
|
||||
PicoDisplay(uint16_t *buf);
|
||||
PicoDisplay(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 +1 @@
|
|||
add_library(pico_graphics types.cpp font_data.cpp pico_graphics.cpp)
|
||||
include(pico_graphics.cmake)
|
|
@ -1,4 +1,6 @@
|
|||
add_library(pico_graphics
|
||||
${CMAKE_CURRENT_LIST_DIR}/types.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/font_data.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/pico_graphics.cpp)
|
||||
${CMAKE_CURRENT_LIST_DIR}/pico_graphics.cpp)
|
||||
|
||||
target_include_directories(pico_graphics INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
|
@ -22,6 +22,7 @@ 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);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picodisplay_flip_obj, picodisplay_flip);
|
||||
|
||||
//From PicoGraphics parent class
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picodisplay_set_pen_obj, 1, 3, picodisplay_set_pen);
|
||||
|
@ -47,6 +48,7 @@ STATIC const mp_map_elem_t picodisplay_globals_table[] = {
|
|||
{ 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_flip), MP_ROM_PTR(&picodisplay_flip_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) },
|
||||
|
@ -75,4 +77,4 @@ const mp_obj_module_t picodisplay_user_cmodule = {
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
MP_REGISTER_MODULE(MP_QSTR_picodisplay, picodisplay_user_cmodule, MODULE_PICODISPLAY_ENABLED);
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -43,6 +43,15 @@ mp_obj_t picodisplay_update() {
|
|||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picodisplay_flip() {
|
||||
if(display != nullptr)
|
||||
display->flip();
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picodisplay_set_backlight(mp_obj_t brightness_obj) {
|
||||
if(display != nullptr) {
|
||||
float brightness = mp_obj_get_float(brightness_obj);
|
||||
|
|
|
@ -10,6 +10,7 @@ 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);
|
||||
extern mp_obj_t picodisplay_flip();
|
||||
|
||||
// From PicoGraphics parent class
|
||||
extern mp_obj_t picodisplay_set_pen(mp_uint_t n_args, const mp_obj_t *args);
|
||||
|
@ -22,4 +23,4 @@ extern mp_obj_t picodisplay_pixel_span(mp_obj_t x_obj, mp_obj_t y_obj, mp_obj_t
|
|||
extern mp_obj_t picodisplay_rectangle(mp_uint_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t picodisplay_circle(mp_obj_t x_obj, mp_obj_t y_obj, mp_obj_t r_obj);
|
||||
extern mp_obj_t picodisplay_character(mp_uint_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t picodisplay_text(mp_uint_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t picodisplay_text(mp_uint_t n_args, const mp_obj_t *args);
|
||||
|
|
Loading…
Reference in New Issue