ST7789: Refactor and Bugfixes
* Make ST7789 accept only full config with SPI pins * Make Generic ST7789 wrapper library handle "slot" * Update Round LCD and 240x240 Square LCD * Remove Python Round LCD and 240x240 LCD modules (we need the space!) * Remove C++ Round LCD and 240x240 LCD libraries (they're a little redundant!) * Fix garbage collected framebuffer bug in Python ST7789 * Deprecate "flip" in favour of "configure_display" * Tidy up ST7789, remove dead/unused/commented code
This commit is contained in:
parent
65fb478b6e
commit
8e1e9df002
|
@ -3,9 +3,6 @@
|
|||
#include <cstdlib>
|
||||
#include <math.h>
|
||||
|
||||
#include "hardware/dma.h"
|
||||
#include "hardware/pwm.h"
|
||||
|
||||
namespace pimoroni {
|
||||
uint8_t madctl;
|
||||
uint16_t caset[2] = {0, 0};
|
||||
|
@ -20,11 +17,6 @@ namespace pimoroni {
|
|||
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,
|
||||
TEOFF = 0x34,
|
||||
|
@ -54,122 +46,69 @@ namespace pimoroni {
|
|||
PWMFRSEL = 0xCC
|
||||
};
|
||||
|
||||
void ST7789::init(bool auto_init_sequence, bool round, uint32_t spi_baud) {
|
||||
this->round = round;
|
||||
void ST7789::init() {
|
||||
command(reg::SWRESET);
|
||||
|
||||
// configure spi interface and pins
|
||||
spi_init(spi, spi_baud);
|
||||
sleep_ms(150);
|
||||
|
||||
gpio_set_function(dc, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(dc, GPIO_OUT);
|
||||
// Common init
|
||||
command(reg::TEON); // enable frame sync signal if used
|
||||
command(reg::COLMOD, 1, "\x05"); // 16 bits per pixel
|
||||
|
||||
gpio_set_function(cs, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(cs, GPIO_OUT);
|
||||
command(reg::PORCTRL, 5, "\x0c\x0c\x00\x33\x33");
|
||||
command(reg::LCMCTRL, 1, "\x2c");
|
||||
command(reg::VDVVRHEN, 1, "\x01");
|
||||
command(reg::VRHS, 1, "\x12");
|
||||
command(reg::VDVS, 1, "\x20");
|
||||
command(reg::PWCTRL1, 2, "\xa4\xa1");
|
||||
command(reg::FRCTRL2, 1, "\x0f");
|
||||
|
||||
gpio_set_function(sck, GPIO_FUNC_SPI);
|
||||
gpio_set_function(mosi, GPIO_FUNC_SPI);
|
||||
|
||||
if(miso != PIN_UNUSED) {
|
||||
gpio_set_function(miso, GPIO_FUNC_SPI);
|
||||
if(width == 240 && height == 240) {
|
||||
command(reg::GCTRL, 1, "\x14");
|
||||
command(reg::VCOMS, 1, "\x37");
|
||||
command(reg::GMCTRP1, 14, "\xD0\x04\x0D\x11\x13\x2B\x3F\x54\x4C\x18\x0D\x0B\x1F\x23");
|
||||
command(reg::GMCTRN1, 14, "\xD0\x04\x0C\x11\x13\x2C\x3F\x44\x51\x2F\x1F\x1F\x20\x23");
|
||||
}
|
||||
|
||||
// if supported by the display then the vsync pin is
|
||||
// toggled high during vertical blanking period
|
||||
if(vsync != PIN_UNUSED) {
|
||||
gpio_set_function(vsync, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(vsync, GPIO_IN);
|
||||
gpio_set_pulls(vsync, false, true);
|
||||
if((width == 320 && height == 240)
|
||||
|| (width == 240 && height == 320)) {
|
||||
command(reg::GCTRL, 1, "\x35");
|
||||
command(reg::VCOMS, 1, "\x1f");
|
||||
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");
|
||||
}
|
||||
|
||||
// if a backlight pin is provided then set it up for
|
||||
// pwm control
|
||||
command(reg::INVON); // set inversion mode
|
||||
command(reg::SLPOUT); // leave sleep mode
|
||||
command(reg::DISPON); // turn display on
|
||||
|
||||
sleep_ms(100);
|
||||
|
||||
configure_display(false);
|
||||
|
||||
if(bl != PIN_UNUSED) {
|
||||
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);
|
||||
set_backlight(0); // Turn backlight off initially to avoid nasty surprises
|
||||
update(); // Send the new buffer to the display to clear any previous content
|
||||
sleep_ms(50); // Wait for the update to apply
|
||||
set_backlight(255); // Turn backlight on now surprises have passed
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// Common init
|
||||
command(reg::TEON); // enable frame sync signal if used
|
||||
command(reg::COLMOD, 1, "\x05"); // 16 bits per pixel
|
||||
|
||||
command(reg::PORCTRL, 5, "\x0c\x0c\x00\x33\x33");
|
||||
command(reg::LCMCTRL, 1, "\x2c");
|
||||
command(reg::VDVVRHEN, 1, "\x01");
|
||||
command(reg::VRHS, 1, "\x12");
|
||||
command(reg::VDVS, 1, "\x20");
|
||||
command(reg::PWCTRL1, 2, "\xa4\xa1");
|
||||
command(reg::FRCTRL2, 1, "\x0f");
|
||||
|
||||
if(width == 240 && height == 240) {
|
||||
command(reg::GCTRL, 1, "\x14");
|
||||
command(reg::VCOMS, 1, "\x37");
|
||||
command(reg::GMCTRP1, 14, "\xD0\x04\x0D\x11\x13\x2B\x3F\x54\x4C\x18\x0D\x0B\x1F\x23");
|
||||
command(reg::GMCTRN1, 14, "\xD0\x04\x0C\x11\x13\x2C\x3F\x44\x51\x2F\x1F\x1F\x20\x23");
|
||||
}
|
||||
|
||||
if((width == 320 && height == 240)
|
||||
|| (width == 240 && height == 320)) {
|
||||
command(reg::GCTRL, 1, "\x35");
|
||||
command(reg::VCOMS, 1, "\x1f");
|
||||
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
|
||||
|
||||
sleep_ms(100);
|
||||
|
||||
configure_display(false);
|
||||
|
||||
if(bl != PIN_UNUSED) {
|
||||
update(); // Send the new buffer to the display to clear any previous content
|
||||
sleep_ms(50); // Wait for the update to apply
|
||||
set_backlight(255); // Turn backlight on now surprises have passed
|
||||
}
|
||||
}
|
||||
|
||||
// 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::configure_display(bool rotate180) {
|
||||
// setup correct addressing window
|
||||
// 240x240 Square and Round LCD Breakouts
|
||||
// TODO: How can we support 90 degree rotations here?
|
||||
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(round) {
|
||||
raset[0] = 40;
|
||||
raset[1] = 279;
|
||||
} else {
|
||||
raset[0] = rotate180 ? 80 : 0;
|
||||
raset[1] = rotate180 ? 329 : 239;
|
||||
}
|
||||
madctl = rotate180 ? (MADCTL::COL_ORDER | MADCTL::ROW_ORDER) : 0;
|
||||
madctl |= MADCTL::HORIZ_ORDER;
|
||||
}
|
||||
|
||||
// Pico Display
|
||||
|
@ -216,9 +155,9 @@ namespace pimoroni {
|
|||
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);
|
||||
command(reg::CASET, 4, (char *)caset);
|
||||
command(reg::RASET, 4, (char *)raset);
|
||||
command(reg::MADCTL, 1, (char *)&madctl);
|
||||
}
|
||||
|
||||
spi_inst_t* ST7789::get_spi() const {
|
||||
|
@ -246,8 +185,6 @@ namespace pimoroni {
|
|||
}
|
||||
|
||||
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
|
||||
|
@ -261,25 +198,8 @@ namespace pimoroni {
|
|||
gpio_put(cs, 1);
|
||||
}
|
||||
|
||||
void ST7789::update(bool dont_block) {
|
||||
void ST7789::update() {
|
||||
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) {
|
||||
|
@ -290,12 +210,7 @@ namespace pimoroni {
|
|||
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);
|
||||
configure_display(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,14 +2,15 @@
|
|||
|
||||
#include "hardware/spi.h"
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/pwm.h"
|
||||
#include "../../common/pimoroni_common.hpp"
|
||||
|
||||
|
||||
namespace pimoroni {
|
||||
|
||||
class ST7789 {
|
||||
spi_inst_t *spi = PIMORONI_SPI_DEFAULT_INSTANCE;
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// Variables
|
||||
//--------------------------------------------------
|
||||
|
@ -18,16 +19,13 @@ namespace pimoroni {
|
|||
uint16_t width;
|
||||
uint16_t height;
|
||||
bool round;
|
||||
uint16_t row_stride;
|
||||
uint32_t dma_channel;
|
||||
|
||||
// interface pins with our standard defaults where appropriate
|
||||
uint cs = SPI_BG_FRONT_CS;
|
||||
uint dc = SPI_DEFAULT_MISO;
|
||||
uint sck = SPI_DEFAULT_SCK;
|
||||
uint mosi = SPI_DEFAULT_MOSI;
|
||||
uint miso = PIN_UNUSED; // used as data/command
|
||||
uint bl = SPI_BG_FRONT_PWM;
|
||||
uint cs;
|
||||
uint dc;
|
||||
uint sck;
|
||||
uint mosi;
|
||||
uint bl;
|
||||
uint vsync = PIN_UNUSED; // only available on some products
|
||||
|
||||
// The ST7789 requires 16 ns between SPI rising edges.
|
||||
|
@ -39,43 +37,47 @@ namespace pimoroni {
|
|||
// frame buffer where pixel data is stored
|
||||
uint16_t *frame_buffer;
|
||||
|
||||
ST7789(uint16_t width, uint16_t height, uint16_t *frame_buffer, BG_SPI_SLOT slot) :
|
||||
width(width), height(height), frame_buffer(frame_buffer) {
|
||||
switch(slot) {
|
||||
case PICO_EXPLORER_ONBOARD:
|
||||
cs = SPI_BG_FRONT_CS;
|
||||
bl = PIN_UNUSED;
|
||||
break;
|
||||
case BG_SPI_FRONT:
|
||||
cs = SPI_BG_FRONT_CS;
|
||||
bl = SPI_BG_FRONT_PWM;
|
||||
break;
|
||||
case BG_SPI_BACK:
|
||||
cs = SPI_BG_BACK_CS;
|
||||
bl = SPI_BG_BACK_PWM;
|
||||
break;
|
||||
}
|
||||
if(!this->frame_buffer) {
|
||||
this->frame_buffer = new uint16_t(width * height);
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
ST7789(uint16_t width, uint16_t height, bool round, uint16_t *frame_buffer,
|
||||
spi_inst_t *spi,
|
||||
uint cs, uint dc, uint sck, uint mosi, uint miso = PIN_UNUSED, uint bl = PIN_UNUSED) :
|
||||
uint cs, uint dc, uint sck, uint mosi, uint bl = PIN_UNUSED) :
|
||||
spi(spi),
|
||||
width(width), height(height),
|
||||
cs(cs), dc(dc), sck(sck), mosi(mosi), miso(miso), bl(bl), frame_buffer(frame_buffer) {}
|
||||
width(width), height(height), round(round),
|
||||
cs(cs), dc(dc), sck(sck), mosi(mosi), bl(bl), frame_buffer(frame_buffer) {
|
||||
|
||||
if(!this->frame_buffer) {
|
||||
this->frame_buffer = new uint16_t[width * height];
|
||||
}
|
||||
|
||||
// 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 a backlight pin is provided then set it up for
|
||||
// pwm control
|
||||
if(bl != PIN_UNUSED) {
|
||||
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);
|
||||
set_backlight(0); // Turn backlight off initially to avoid nasty surprises
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// Methods
|
||||
//--------------------------------------------------
|
||||
public:
|
||||
void init(bool auto_init_sequence = true, bool round = false, uint32_t spi_baud = SPI_BAUD);
|
||||
void init();
|
||||
void configure_display(bool rotate180);
|
||||
|
||||
spi_inst_t* get_spi() const;
|
||||
|
@ -86,10 +88,33 @@ namespace pimoroni {
|
|||
uint get_bl() const;
|
||||
|
||||
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 update();
|
||||
void set_backlight(uint8_t brightness);
|
||||
void flip();
|
||||
|
||||
static uint get_slot_cs(BG_SPI_SLOT slot) {
|
||||
switch(slot) {
|
||||
case PICO_EXPLORER_ONBOARD:
|
||||
return SPI_BG_FRONT_CS;
|
||||
case BG_SPI_FRONT:
|
||||
return SPI_BG_FRONT_CS;
|
||||
case BG_SPI_BACK:
|
||||
return SPI_BG_BACK_CS;
|
||||
}
|
||||
return PIN_UNUSED;
|
||||
};
|
||||
|
||||
static uint get_slot_bl(BG_SPI_SLOT slot) {
|
||||
switch(slot) {
|
||||
case PICO_EXPLORER_ONBOARD:
|
||||
return PIN_UNUSED;
|
||||
case BG_SPI_FRONT:
|
||||
return SPI_BG_FRONT_PWM;
|
||||
case BG_SPI_BACK:
|
||||
return SPI_BG_BACK_PWM;
|
||||
}
|
||||
return PIN_UNUSED;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ add_executable(
|
|||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(${OUTPUT_NAME} pico_stdlib breakout_colourlcd240x240)
|
||||
target_link_libraries(${OUTPUT_NAME} pico_stdlib generic_st7789)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(${OUTPUT_NAME})
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
#include <math.h>
|
||||
#include <vector>
|
||||
|
||||
#include "breakout_colourlcd240x240.hpp"
|
||||
#include "generic_st7789.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
uint16_t buffer[BreakoutColourLCD240x240::WIDTH * BreakoutColourLCD240x240::HEIGHT];
|
||||
BreakoutColourLCD240x240 lcd(buffer);
|
||||
const int WIDTH = 240;
|
||||
const int HEIGHT = 240;
|
||||
|
||||
ST7789Generic lcd(WIDTH, HEIGHT, false, nullptr, BG_SPI_FRONT);
|
||||
|
||||
int main() {
|
||||
lcd.init();
|
||||
//lcd.configure_display(false);
|
||||
lcd.set_backlight(255);
|
||||
|
||||
struct pt {
|
||||
|
@ -24,9 +26,11 @@ int main() {
|
|||
std::vector<pt> shapes;
|
||||
for(int i = 0; i < 100; i++) {
|
||||
pt shape;
|
||||
shape.x = rand() % lcd.bounds.w;
|
||||
shape.y = rand() % lcd.bounds.h;
|
||||
shape.r = (rand() % 10) + 3;
|
||||
shape.x = rand() % (lcd.bounds.w - (shape.r * 2));
|
||||
shape.y = rand() % (lcd.bounds.h - (shape.r * 2));
|
||||
shape.x += shape.r;
|
||||
shape.y += shape.r;
|
||||
shape.dx = float(rand() % 255) / 64.0f;
|
||||
shape.dy = float(rand() % 255) / 64.0f;
|
||||
shape.pen = lcd.create_pen(rand() % 255, rand() % 255, rand() % 255);
|
||||
|
@ -40,15 +44,18 @@ int main() {
|
|||
for(auto &shape : shapes) {
|
||||
shape.x += shape.dx;
|
||||
shape.y += shape.dy;
|
||||
if(shape.x < 0) shape.dx *= -1;
|
||||
if(shape.x >= lcd.bounds.w) shape.dx *= -1;
|
||||
if(shape.y < 0) shape.dy *= -1;
|
||||
if(shape.y >= lcd.bounds.h) shape.dy *= -1;
|
||||
if(shape.x < shape.r) shape.dx *= -1;
|
||||
if(shape.x >= lcd.bounds.w - shape.r) shape.dx *= -1;
|
||||
if(shape.y < shape.r) shape.dy *= -1;
|
||||
if(shape.y >= lcd.bounds.h - shape.r) shape.dy *= -1;
|
||||
|
||||
lcd.set_pen(shape.pen);
|
||||
lcd.circle(Point(shape.x, shape.y), shape.r);
|
||||
}
|
||||
|
||||
lcd.set_pen(255, 255, 255);
|
||||
lcd.text("Hello World", Point(0, 0), 240);
|
||||
|
||||
// update screen
|
||||
lcd.update();
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ add_executable(
|
|||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(${OUTPUT_NAME} pico_stdlib breakout_roundlcd)
|
||||
target_link_libraries(${OUTPUT_NAME} pico_stdlib generic_st7789)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(${OUTPUT_NAME})
|
|
@ -3,7 +3,7 @@
|
|||
#include <vector>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "breakout_roundlcd.hpp"
|
||||
#include "generic_st7789.hpp"
|
||||
#include "time.h"
|
||||
|
||||
// Place a 1.3 Round SPI LCD in the *front* slot of breakout garden.
|
||||
|
@ -11,10 +11,12 @@
|
|||
using namespace pimoroni;
|
||||
|
||||
|
||||
uint16_t buffer[BreakoutRoundLCD::WIDTH * BreakoutRoundLCD::HEIGHT];
|
||||
BreakoutRoundLCD display(buffer, BG_SPI_FRONT);
|
||||
const int WIDTH = 240;
|
||||
const int HEIGHT = 240;
|
||||
|
||||
constexpr float RADIUS = BreakoutRoundLCD::WIDTH / 2;
|
||||
ST7789Generic display(WIDTH, HEIGHT, true, nullptr, BG_SPI_FRONT);
|
||||
|
||||
constexpr float RADIUS = WIDTH / 2;
|
||||
|
||||
Pen from_hsv(float h, float s, float v) {
|
||||
uint8_t r = 0, g = 0, b = 0;
|
||||
|
@ -39,7 +41,6 @@ Pen from_hsv(float h, float s, float v) {
|
|||
}
|
||||
|
||||
int main() {
|
||||
display.init();
|
||||
display.set_backlight(255);
|
||||
|
||||
uint32_t steps = 70;
|
||||
|
|
|
@ -3,8 +3,6 @@ add_subdirectory(breakout_encoder)
|
|||
add_subdirectory(breakout_ioexpander)
|
||||
add_subdirectory(breakout_ltr559)
|
||||
add_subdirectory(breakout_colourlcd160x80)
|
||||
add_subdirectory(breakout_colourlcd240x240)
|
||||
add_subdirectory(breakout_roundlcd)
|
||||
add_subdirectory(breakout_rgbmatrix5x5)
|
||||
add_subdirectory(breakout_matrix11x7)
|
||||
add_subdirectory(breakout_mics6814)
|
||||
|
|
|
@ -3,24 +3,24 @@
|
|||
namespace pimoroni {
|
||||
|
||||
BreakoutColourLCD240x240::BreakoutColourLCD240x240(uint16_t *buf)
|
||||
: PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, buf) {
|
||||
: PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, false, buf,
|
||||
PIMORONI_SPI_DEFAULT_INSTANCE, SPI_BG_FRONT_CS, SPI_DEFAULT_MISO, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, SPI_BG_FRONT_PWM) {
|
||||
__fb = buf;
|
||||
}
|
||||
|
||||
BreakoutColourLCD240x240::BreakoutColourLCD240x240(uint16_t *buf, spi_inst_t *spi,
|
||||
uint cs, uint dc, uint sck, uint mosi, uint miso, uint bl)
|
||||
: PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, buf, spi, cs, dc, sck, mosi, miso, bl) {
|
||||
uint cs, uint dc, uint sck, uint mosi, uint bl)
|
||||
: PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, false, buf, spi, cs, dc, sck, mosi, bl) {
|
||||
__fb = buf;
|
||||
}
|
||||
|
||||
BreakoutColourLCD240x240::BreakoutColourLCD240x240(uint16_t *buf, BG_SPI_SLOT slot)
|
||||
: PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, buf, slot) {
|
||||
: PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, false, buf,
|
||||
PIMORONI_SPI_DEFAULT_INSTANCE, screen.get_slot_cs(slot), SPI_DEFAULT_MISO, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, screen.get_slot_bl(slot)) {
|
||||
__fb = buf;
|
||||
}
|
||||
|
||||
void BreakoutColourLCD240x240::init() {
|
||||
// initialise the screen
|
||||
screen.init();
|
||||
}
|
||||
|
||||
spi_inst_t* BreakoutColourLCD240x240::get_spi() const {
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace pimoroni {
|
|||
public:
|
||||
BreakoutColourLCD240x240(uint16_t *buf);
|
||||
BreakoutColourLCD240x240(uint16_t *buf, spi_inst_t *spi,
|
||||
uint cs, uint dc, uint sck, uint mosi, uint miso = PIN_UNUSED, uint bl = PIN_UNUSED);
|
||||
uint cs, uint dc, uint sck, uint mosi, uint bl = PIN_UNUSED);
|
||||
BreakoutColourLCD240x240(uint16_t *buf, BG_SPI_SLOT slot);
|
||||
|
||||
|
||||
|
|
|
@ -3,23 +3,24 @@
|
|||
namespace pimoroni {
|
||||
|
||||
BreakoutRoundLCD::BreakoutRoundLCD(uint16_t *buf)
|
||||
: PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, buf) {
|
||||
: PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, true, buf,
|
||||
PIMORONI_SPI_DEFAULT_INSTANCE, SPI_BG_FRONT_CS, SPI_DEFAULT_MISO, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, SPI_BG_FRONT_PWM) {
|
||||
__fb = buf;
|
||||
}
|
||||
|
||||
BreakoutRoundLCD::BreakoutRoundLCD(uint16_t *buf, spi_inst_t *spi,
|
||||
uint cs, uint dc, uint sck, uint mosi, uint miso, uint bl)
|
||||
: PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, buf, spi, cs, dc, sck, mosi, miso, bl) {
|
||||
uint cs, uint dc, uint sck, uint mosi, uint bl)
|
||||
: PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, true, buf, spi, cs, dc, sck, mosi, bl) {
|
||||
__fb = buf;
|
||||
}
|
||||
|
||||
BreakoutRoundLCD::BreakoutRoundLCD(uint16_t *buf, BG_SPI_SLOT slot) : PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, buf, slot) {
|
||||
BreakoutRoundLCD::BreakoutRoundLCD(uint16_t *buf, BG_SPI_SLOT slot)
|
||||
: PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, true, buf,
|
||||
PIMORONI_SPI_DEFAULT_INSTANCE, screen.get_slot_cs(slot), SPI_DEFAULT_MISO, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, screen.get_slot_bl(slot)) {
|
||||
__fb = buf;
|
||||
}
|
||||
|
||||
void BreakoutRoundLCD::init() {
|
||||
// initialise the screen
|
||||
screen.init(true, true);
|
||||
}
|
||||
|
||||
spi_inst_t* BreakoutRoundLCD::get_spi() const {
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace pimoroni {
|
|||
public:
|
||||
BreakoutRoundLCD(uint16_t *buf);
|
||||
BreakoutRoundLCD(uint16_t *buf, spi_inst_t *spi,
|
||||
uint cs, uint dc, uint sck, uint mosi, uint miso = PIN_UNUSED, uint bl = PIN_UNUSED);
|
||||
uint cs, uint dc, uint sck, uint mosi, uint bl = PIN_UNUSED);
|
||||
BreakoutRoundLCD(uint16_t *buf, BG_SPI_SLOT slot);
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
# ST7789 - Pico Display Pack & Pico Display Pack 2.0" <!-- omit in toc -->
|
||||
|
||||
Our Pico Display Packs offers a vibrant 1.14" (240x135) or 2.0" (320x240) 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.hpp"
|
||||
#include "generic_st7789.hpp"
|
||||
#include "rgbled.hpp"
|
||||
#include "button.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
uint16_t buffer[PicoDisplay::WIDTH * PicoDisplay::HEIGHT];
|
||||
PicoDisplay 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(PicoDisplay::A)
|
||||
```
|
||||
|
||||
### update
|
||||
|
||||
To display your changes on Pico Display's screen you need to call `update`:
|
||||
|
||||
```c++
|
||||
pico_display.update();
|
||||
```
|
|
@ -5,28 +5,6 @@
|
|||
|
||||
|
||||
namespace pimoroni {
|
||||
|
||||
ST7789Generic::ST7789Generic(int width, int height, BG_SPI_SLOT slot, uint16_t *frame_buffer)
|
||||
: PicoGraphics(width, height, frame_buffer), st7789(width, height, frame_buffer, slot) {
|
||||
this->frame_buffer = st7789.frame_buffer;
|
||||
this->st7789.init(true, false);
|
||||
}
|
||||
|
||||
ST7789Generic::ST7789Generic(int width, int height, uint16_t *frame_buffer)
|
||||
: PicoGraphics(width, height, frame_buffer), st7789(width, height, frame_buffer, BG_SPI_FRONT) {
|
||||
this->frame_buffer = st7789.frame_buffer;
|
||||
this->st7789.init(true, false);
|
||||
}
|
||||
|
||||
ST7789Generic::ST7789Generic(uint16_t width, uint16_t height, spi_inst_t *spi,
|
||||
uint cs, uint dc, uint sck, uint mosi, uint miso, uint bl,
|
||||
uint16_t *frame_buffer) :
|
||||
PicoGraphics(width, height, frame_buffer),
|
||||
st7789(width, height, frame_buffer, spi, cs, dc, sck, mosi, miso, bl) {
|
||||
this->frame_buffer = st7789.frame_buffer;
|
||||
this->st7789.init(true, false);
|
||||
}
|
||||
|
||||
spi_inst_t* ST7789Generic::get_spi() const {
|
||||
return st7789.get_spi();
|
||||
}
|
||||
|
@ -56,7 +34,7 @@ namespace pimoroni {
|
|||
}
|
||||
|
||||
void ST7789Generic::flip() {
|
||||
st7789.flip();
|
||||
st7789.configure_display(true);
|
||||
}
|
||||
|
||||
void ST7789Generic::set_backlight(uint8_t brightness) {
|
||||
|
|
|
@ -10,11 +10,28 @@ namespace pimoroni {
|
|||
ST7789 st7789;
|
||||
|
||||
public:
|
||||
ST7789Generic(int width, int height, BG_SPI_SLOT slot, uint16_t *frame_buffer = nullptr);
|
||||
ST7789Generic(int width, int height, uint16_t *frame_buffer = nullptr);
|
||||
ST7789Generic(uint16_t width, uint16_t height, spi_inst_t *spi,
|
||||
uint cs, uint dc, uint sck, uint mosi, uint miso = PIN_UNUSED, uint bl = PIN_UNUSED,
|
||||
uint16_t *frame_buffer = nullptr);
|
||||
ST7789Generic(uint16_t width, uint16_t height, bool round=false, uint16_t *frame_buffer=nullptr) :
|
||||
PicoGraphics(width, height, frame_buffer),
|
||||
st7789(width, height, round, frame_buffer, PIMORONI_SPI_DEFAULT_INSTANCE, SPI_BG_FRONT_CS, SPI_DEFAULT_MISO, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, SPI_BG_FRONT_PWM) {
|
||||
this->frame_buffer = st7789.frame_buffer;
|
||||
this->st7789.init();
|
||||
};
|
||||
|
||||
ST7789Generic(uint16_t width, uint16_t height, bool round, uint16_t *frame_buffer, BG_SPI_SLOT slot) :
|
||||
PicoGraphics(width, height, frame_buffer),
|
||||
st7789(width, height, round, frame_buffer, PIMORONI_SPI_DEFAULT_INSTANCE, st7789.get_slot_cs(slot), SPI_DEFAULT_MISO, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, st7789.get_slot_bl(slot)) {
|
||||
this->frame_buffer = st7789.frame_buffer;
|
||||
this->st7789.init();
|
||||
};
|
||||
|
||||
ST7789Generic(uint16_t width, uint16_t height, bool round, uint16_t *frame_buffer,
|
||||
spi_inst_t *spi,
|
||||
uint cs, uint dc, uint sck, uint mosi, uint bl = PIN_UNUSED) :
|
||||
PicoGraphics(width, height, frame_buffer),
|
||||
st7789(width, height, round, frame_buffer, spi, cs, dc, sck, mosi, bl) {
|
||||
this->frame_buffer = st7789.frame_buffer;
|
||||
this->st7789.init();
|
||||
};
|
||||
|
||||
spi_inst_t* get_spi() const;
|
||||
int get_cs() const;
|
||||
|
@ -24,7 +41,7 @@ namespace pimoroni {
|
|||
int get_bl() const;
|
||||
|
||||
void update();
|
||||
void flip();
|
||||
[[deprecated("Use configure_display(true) instead.")]] void flip();
|
||||
void set_backlight(uint8_t brightness);
|
||||
void configure_display(bool rotate180);
|
||||
};
|
||||
|
|
|
@ -19,49 +19,60 @@ The following example sets up Pico Display, displays some basic demo text and gr
|
|||
|
||||
```c++
|
||||
#include "pico_display.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
#include "generic_st7789.hpp"
|
||||
#include "rgbled.hpp"
|
||||
#include "button.hpp"
|
||||
|
||||
uint16_t buffer[PicoDisplay::WIDTH * PicoDisplay::HEIGHT];
|
||||
PicoDisplay pico_display(buffer);
|
||||
|
||||
// Swap WIDTH and HEIGHT to rotate 90 degrees
|
||||
ST7789Generic display(PicoDisplay::WIDTH, PicoDisplay::HEIGHT, buffer);
|
||||
|
||||
// Create an RGB LED
|
||||
RGBLED led(PicoDisplay::LED_R, PicoDisplay::LED_G, PicoDisplay::LED_B);
|
||||
|
||||
// And each button
|
||||
Button button_a(PicoDisplay::A);
|
||||
Button button_b(PicoDisplay::B);
|
||||
Button button_x(PicoDisplay::X);
|
||||
Button button_y(PicoDisplay::Y);
|
||||
|
||||
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);
|
||||
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)) {
|
||||
if(button_a.raw(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);
|
||||
led.set_rgb(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);
|
||||
display.set_pen(30, 40, 50);
|
||||
|
||||
// fill the screen with the current pen colour
|
||||
pico_display.clear();
|
||||
display.clear();
|
||||
|
||||
// draw a box to put some text in
|
||||
pico_display.set_pen(10, 20, 30);
|
||||
display.set_pen(10, 20, 30);
|
||||
Rect text_rect(10, 10, 150, 150);
|
||||
pico_display.rectangle(text_rect);
|
||||
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);
|
||||
display.set_pen(110, 120, 130);
|
||||
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();
|
||||
display.update();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -72,52 +83,32 @@ int main() {
|
|||
|
||||
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
|
||||
### configure_display
|
||||
|
||||
Sets up Pico Display. `init` must be called before any other functions since it configures the required PWM and GPIO:
|
||||
Configures an ST7789 display. Done by default, but you can use this to set 180 degree rotation like so:
|
||||
|
||||
```c++
|
||||
pico_display.init();
|
||||
display.configure_display(true);
|
||||
```
|
||||
|
||||
### flip
|
||||
|
||||
Deprecated: calls `configure_display(true);`
|
||||
|
||||
### set_backlight
|
||||
|
||||
Set the display backlight from 0-255.
|
||||
|
||||
```c++
|
||||
pico_display.set_backlight(brightness);
|
||||
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(PicoDisplay::A)
|
||||
```
|
||||
|
||||
### update
|
||||
|
||||
To display your changes on Pico Display's screen you need to call `update`:
|
||||
|
||||
```c++
|
||||
pico_display.update();
|
||||
```
|
||||
display.update();
|
||||
```
|
||||
|
|
|
@ -9,12 +9,14 @@
|
|||
namespace pimoroni {
|
||||
|
||||
PicoDisplay::PicoDisplay(uint16_t *buf)
|
||||
: PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, buf, BG_SPI_FRONT) {
|
||||
: PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, false, buf,
|
||||
PIMORONI_SPI_DEFAULT_INSTANCE, SPI_BG_FRONT_CS, SPI_DEFAULT_MISO, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, SPI_BG_FRONT_PWM) {
|
||||
__fb = buf;
|
||||
}
|
||||
|
||||
PicoDisplay::PicoDisplay(uint16_t *buf, int width, int height)
|
||||
: PicoGraphics(width, height, buf), screen(width, height, buf, BG_SPI_FRONT) {
|
||||
: PicoGraphics(width, height, buf), screen(width, height, false, buf,
|
||||
PIMORONI_SPI_DEFAULT_INSTANCE, SPI_BG_FRONT_CS, SPI_DEFAULT_MISO, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, SPI_BG_FRONT_PWM) {
|
||||
__fb = buf;
|
||||
}
|
||||
|
||||
|
@ -43,9 +45,6 @@ namespace pimoroni {
|
|||
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();
|
||||
}
|
||||
|
||||
void PicoDisplay::update() {
|
||||
|
|
|
@ -9,12 +9,14 @@
|
|||
namespace pimoroni {
|
||||
|
||||
PicoDisplay2::PicoDisplay2(uint16_t *buf)
|
||||
: PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, buf, BG_SPI_FRONT) {
|
||||
: PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, false, buf,
|
||||
PIMORONI_SPI_DEFAULT_INSTANCE, SPI_BG_FRONT_CS, SPI_DEFAULT_MISO, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, SPI_BG_FRONT_PWM) {
|
||||
__fb = buf;
|
||||
}
|
||||
|
||||
PicoDisplay2::PicoDisplay2(uint16_t *buf, int width, int height)
|
||||
: PicoGraphics(width, height, buf), screen(width, height, buf, BG_SPI_FRONT) {
|
||||
: PicoGraphics(width, height, buf), screen(width, height, false, buf,
|
||||
PIMORONI_SPI_DEFAULT_INSTANCE, SPI_BG_FRONT_CS, SPI_DEFAULT_MISO, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, SPI_BG_FRONT_PWM) {
|
||||
__fb = buf;
|
||||
}
|
||||
|
||||
|
@ -43,9 +45,6 @@ namespace pimoroni {
|
|||
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);
|
||||
}
|
||||
|
||||
void PicoDisplay2::update() {
|
||||
|
|
|
@ -15,8 +15,9 @@ const uint8_t MOTOR2P = 11;
|
|||
namespace pimoroni {
|
||||
|
||||
PicoExplorer::PicoExplorer(uint16_t *buf)
|
||||
: PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, buf, PICO_EXPLORER_ONBOARD) {
|
||||
__fb = buf;
|
||||
: PicoGraphics(WIDTH, HEIGHT, buf),
|
||||
screen(WIDTH, HEIGHT, false, buf, PIMORONI_SPI_DEFAULT_INSTANCE, screen.get_slot_cs(PICO_EXPLORER_ONBOARD), SPI_DEFAULT_MISO, SPI_DEFAULT_SCK, SPI_DEFAULT_MOSI, screen.get_slot_bl(PICO_EXPLORER_ONBOARD)) {
|
||||
__fb = buf;
|
||||
}
|
||||
|
||||
void PicoExplorer::init() {
|
||||
|
@ -48,9 +49,6 @@ namespace pimoroni {
|
|||
|
||||
pwm_init(pwm_gpio_to_slice_num(MOTOR2P), &motor_pwm_cfg, true);
|
||||
gpio_set_function(MOTOR2P, GPIO_FUNC_PWM);
|
||||
|
||||
// initialise the screen
|
||||
screen.init();
|
||||
}
|
||||
|
||||
void PicoExplorer::update() {
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
import time
|
||||
import random
|
||||
from breakout_colourlcd240x240 import BreakoutColourLCD240x240
|
||||
from st7789 import ST7789
|
||||
|
||||
width = BreakoutColourLCD240x240.WIDTH
|
||||
height = BreakoutColourLCD240x240.HEIGHT
|
||||
WIDTH, HEIGHT = 240, 240
|
||||
|
||||
display_buffer = bytearray(width * height * 2) # 2-bytes per pixel (RGB565)
|
||||
display = BreakoutColourLCD240x240(display_buffer)
|
||||
display = ST7789(WIDTH, HEIGHT, round=False)
|
||||
|
||||
display.set_backlight(1.0)
|
||||
|
||||
|
@ -27,8 +25,8 @@ for i in range(0, 100):
|
|||
r = random.randint(0, 10) + 3
|
||||
balls.append(
|
||||
Ball(
|
||||
random.randint(r, r + (width - 2 * r)),
|
||||
random.randint(r, r + (height - 2 * r)),
|
||||
random.randint(r, r + (WIDTH - 2 * r)),
|
||||
random.randint(r, r + (HEIGHT - 2 * r)),
|
||||
r,
|
||||
(14 - r) / 2,
|
||||
(14 - r) / 2,
|
||||
|
@ -44,9 +42,9 @@ while True:
|
|||
ball.x += ball.dx
|
||||
ball.y += ball.dy
|
||||
|
||||
xmax = width - ball.r
|
||||
xmax = WIDTH - ball.r
|
||||
xmin = ball.r
|
||||
ymax = height - ball.r
|
||||
ymax = HEIGHT - ball.r
|
||||
ymin = ball.r
|
||||
|
||||
if ball.x < xmin or ball.x > xmax:
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
import time
|
||||
import math
|
||||
from breakout_roundlcd import BreakoutRoundLCD
|
||||
from st7789 import ST7789
|
||||
|
||||
width = BreakoutRoundLCD.WIDTH
|
||||
height = BreakoutRoundLCD.HEIGHT
|
||||
WIDTH, HEIGHT = 240, 240
|
||||
|
||||
display_buffer = bytearray(width * height * 2) # 2-bytes per pixel (RGB565)
|
||||
display = BreakoutRoundLCD(display_buffer)
|
||||
display = ST7789(WIDTH, HEIGHT, round=True)
|
||||
|
||||
display.set_backlight(1.0)
|
||||
|
||||
RADIUS = width // 2
|
||||
RADIUS = WIDTH // 2
|
||||
|
||||
|
||||
def hsv_to_rgb(h, s, v):
|
||||
|
|
|
@ -120,7 +120,7 @@ mp_obj_t BreakoutColourLCD240x240_make_new(const mp_obj_type_t *type, size_t n_a
|
|||
|
||||
spi_inst_t *spi = (spi_id == 0) ? spi0 : spi1;
|
||||
self->breakout = new BreakoutColourLCD240x240((uint16_t *)bufinfo.buf, spi,
|
||||
args[ARG_cs].u_int, args[ARG_dc].u_int, sck, mosi, PIN_UNUSED, args[ARG_bl].u_int);
|
||||
args[ARG_cs].u_int, args[ARG_dc].u_int, sck, mosi, args[ARG_bl].u_int);
|
||||
}
|
||||
|
||||
self->breakout->init();
|
||||
|
|
|
@ -120,7 +120,7 @@ mp_obj_t BreakoutRoundLCD_make_new(const mp_obj_type_t *type, size_t n_args, siz
|
|||
|
||||
spi_inst_t *spi = (spi_id == 0) ? spi0 : spi1;
|
||||
self->breakout = new BreakoutRoundLCD((uint16_t *)bufinfo.buf, spi,
|
||||
args[ARG_cs].u_int, args[ARG_dc].u_int, sck, mosi, PIN_UNUSED, args[ARG_bl].u_int);
|
||||
args[ARG_cs].u_int, args[ARG_dc].u_int, sck, mosi, args[ARG_bl].u_int);
|
||||
}
|
||||
|
||||
self->breakout->init();
|
||||
|
|
|
@ -12,7 +12,6 @@ include(breakout_ioexpander/micropython)
|
|||
include(breakout_ltr559/micropython)
|
||||
include(breakout_colourlcd160x80/micropython)
|
||||
include(breakout_as7262/micropython)
|
||||
include(breakout_roundlcd/micropython)
|
||||
include(breakout_rgbmatrix5x5/micropython)
|
||||
include(breakout_matrix11x7/micropython)
|
||||
include(breakout_msa301/micropython)
|
||||
|
@ -22,7 +21,6 @@ include(breakout_potentiometer/micropython)
|
|||
include(breakout_rtc/micropython)
|
||||
include(breakout_trackball/micropython)
|
||||
include(breakout_sgp30/micropython)
|
||||
include(breakout_colourlcd240x240/micropython)
|
||||
include(breakout_bh1745/micropython)
|
||||
include(breakout_bme68x/micropython)
|
||||
include(breakout_bme280/micropython)
|
||||
|
|
|
@ -17,6 +17,7 @@ extern "C" {
|
|||
typedef struct _GenericST7789_obj_t {
|
||||
mp_obj_base_t base;
|
||||
ST7789Generic *st7789;
|
||||
uint16_t *buffer;
|
||||
} GenericST7789_obj_t;
|
||||
|
||||
/***** Print *****/
|
||||
|
@ -51,10 +52,11 @@ void GenericST7789_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin
|
|||
mp_obj_t GenericST7789_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
GenericST7789_obj_t *self = nullptr;
|
||||
|
||||
enum { ARG_width, ARG_height, ARG_rotate180, ARG_slot, ARG_buffer, ARG_spi, ARG_cs, ARG_dc, ARG_sck, ARG_mosi, ARG_bl };
|
||||
enum { ARG_width, ARG_height, ARG_round, ARG_rotate180, ARG_slot, ARG_buffer, ARG_spi, ARG_cs, ARG_dc, ARG_sck, ARG_mosi, ARG_bl };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_round, MP_ARG_OBJ, {.u_obj = mp_const_false} },
|
||||
{ MP_QSTR_rotate180, MP_ARG_OBJ, {.u_obj = mp_const_false} },
|
||||
{ MP_QSTR_slot, MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_buffer, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
|
@ -74,24 +76,24 @@ mp_obj_t GenericST7789_make_new(const mp_obj_type_t *type, size_t n_args, size_t
|
|||
self->base.type = &GenericST7789_type;
|
||||
|
||||
bool rotate180 = args[ARG_rotate180].u_obj == mp_const_true;
|
||||
bool round = args[ARG_round].u_obj == mp_const_true;
|
||||
int width = args[ARG_width].u_int;
|
||||
int height = args[ARG_height].u_int;
|
||||
|
||||
uint16_t *buffer;
|
||||
if (args[ARG_buffer].u_obj != mp_const_none) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_RW);
|
||||
buffer = (uint16_t *)bufinfo.buf;
|
||||
self->buffer = (uint16_t *)bufinfo.buf;
|
||||
if(bufinfo.len < (size_t)(width * height * 2)) {
|
||||
mp_raise_ValueError("Supplied buffer is too small!");
|
||||
}
|
||||
} else {
|
||||
buffer = m_new(uint16_t, width * height);
|
||||
self->buffer = m_new(uint16_t, width * height);
|
||||
}
|
||||
|
||||
if(args[ARG_slot].u_int != -1) {
|
||||
BG_SPI_SLOT slot = (BG_SPI_SLOT)args[ARG_slot].u_int;
|
||||
self->st7789 = new ST7789Generic(width, height, slot, buffer);
|
||||
self->st7789 = new ST7789Generic(width, height, round, self->buffer, slot);
|
||||
if (rotate180) {
|
||||
self->st7789->configure_display(true);
|
||||
}
|
||||
|
@ -119,9 +121,8 @@ mp_obj_t GenericST7789_make_new(const mp_obj_type_t *type, size_t n_args, size_t
|
|||
mp_raise_ValueError(MP_ERROR_TEXT("bad MOSI pin"));
|
||||
}
|
||||
spi_inst_t *spi = (spi_id == 0) ? spi0 : spi1;
|
||||
self->st7789 = new ST7789Generic(width, height, spi,
|
||||
cs, dc, sck, mosi, PIN_UNUSED, bl,
|
||||
buffer);
|
||||
self->st7789 = new ST7789Generic(width, height, round, self->buffer,
|
||||
spi, cs, dc, sck, mosi, bl);
|
||||
if (rotate180) {
|
||||
self->st7789->configure_display(true);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue