320x240 LCD library + tweaks to ST7789 driver

Add the init required for the 320x240 2.0" LCD.

Add an option to set baudrate, 320x240 needs 74MHz for 60FPS

Add library and example for 320x240 2.0 LCD.
pull/170/head
Phil Howard 2021-06-14 15:26:58 +01:00
rodzic 3c3b29cfc0
commit 9ba3a6cfab
10 zmienionych plików z 288 dodań i 3 usunięć

Wyświetl plik

@ -53,7 +53,7 @@ namespace pimoroni {
RASET = 0x2B
};
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 +112,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, "\x74");
command(reg::VCOMS, 1, "\x2f");
command(reg::LCMCTRL, 1, "\2c");
command(reg::VDVVRHEN, 1, "\x01");
command(reg::VRHS, 1, "\x19");
command(reg::VDVS, 1, "\x20");
command(reg::FRCTRL2, 1, "\x0f");
command(reg::PWCTRL1, 2, "\xa4\xa1");
command(0xd6, 1, "\xa1"); // ???
command(reg::GMCTRP1, 14, "\xF0\x08\x0F\x0B\x0B\x07\x34\x43\x4B\x38\x14\x13\x2C\x31");
command(reg::GMCTRN1, 14, "\xF0\x0C\x11\x09\x08\x24\x34\x33\x4A\x3A\x16\x16\x2E\x32");
}
command(reg::INVON); // set inversion mode
command(reg::SLPOUT); // leave sleep mode
command(reg::DISPON); // turn display on
@ -143,6 +158,14 @@ namespace pimoroni {
madctl = 0;
}
if(width == 320 && height == 240) {
caset[0] = 0;
caset[1] = 319;
raset[0] = 0;
raset[1] = 239;
madctl = 0;
}
// Byte swap the 16bit rows/cols values
caset[0] = __builtin_bswap16(caset[0]);
caset[1] = __builtin_bswap16(caset[1]);

Wyświetl plik

@ -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;

Wyświetl plik

@ -12,6 +12,7 @@ add_subdirectory(breakout_rtc)
add_subdirectory(breakout_trackball)
add_subdirectory(breakout_sgp30)
add_subdirectory(breakout_colourlcd240x240)
add_subdirectory(breakout_colourlcd320x240)
add_subdirectory(breakout_msa301)
add_subdirectory(breakout_bme688)
add_subdirectory(breakout_bmp280)

Wyświetl plik

@ -0,0 +1,12 @@
set(OUTPUT_NAME colourlcd320x240_demo)
add_executable(
${OUTPUT_NAME}
demo.cpp
)
# Pull in pico libraries that we need
target_link_libraries(${OUTPUT_NAME} pico_stdlib breakout_colourlcd320x240 button rgbled)
# create map/bin/hex file etc.
pico_add_extra_outputs(${OUTPUT_NAME})

Wyświetl plik

@ -0,0 +1,112 @@
#include <math.h>
#include <vector>
#include "common/pimoroni_common.hpp"
#include "button.hpp"
#include "rgbled.hpp"
#include "breakout_colourlcd320x240.hpp"
using namespace pimoroni;
static const uint A = 12;
static const uint B = 13;
static const uint X = 14;
static const uint Y = 15;
static const uint LED_R = 6;
static const uint LED_G = 7;
static const uint LED_B = 8;
Button buttonA(A, ACTIVE_LOW);
Button buttonB(B, ACTIVE_LOW);
Button buttonX(X, ACTIVE_LOW);
Button buttonY(Y, ACTIVE_LOW);
RGBLED rgbled(LED_R, LED_G, LED_B, ACTIVE_LOW);
uint16_t buffer[BreakoutColourLCD320x240::WIDTH * BreakoutColourLCD320x240::HEIGHT];
BreakoutColourLCD320x240 lcd(buffer);
void setup_buttons() {
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);
}
int main() {
lcd.init();
lcd.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() % lcd.bounds.w;
shape.y = rand() % lcd.bounds.h;
shape.r = (rand() % 10) + 3;
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);
shapes.push_back(shape);
}
Point text_location(0, 0);
while(true) {
if(buttonA.read()) text_location.x -= 1;
if(buttonB.read()) text_location.x += 1;
if(buttonX.read()) text_location.y -= 1;
if(buttonY.read()) text_location.y += 1;
lcd.set_pen(120, 40, 60);
lcd.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) >= lcd.bounds.w) {
shape.dx *= -1;
shape.x = lcd.bounds.w - shape.r;
}
if((shape.y - shape.r) < 0) {
shape.dy *= -1;
shape.y = shape.r;
}
if((shape.y + shape.r) >= lcd.bounds.h) {
shape.dy *= -1;
shape.y = lcd.bounds.h - shape.r;
}
lcd.set_pen(shape.pen);
lcd.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.
rgbled.set_hsv(float(millis()) / 5000.0f, 1.0f, 1.0f);
rgbled.set_brightness(127 + sinf(millis() / 100.0f / 3.14159f) * 127);
lcd.set_pen(255, 255, 255);
lcd.text("Hello World", text_location, 320);
// update screen
lcd.update();
}
return 0;
}

Wyświetl plik

@ -4,6 +4,7 @@ add_subdirectory(breakout_ioexpander)
add_subdirectory(breakout_ltr559)
add_subdirectory(breakout_colourlcd160x80)
add_subdirectory(breakout_colourlcd240x240)
add_subdirectory(breakout_colourlcd320x240)
add_subdirectory(breakout_roundlcd)
add_subdirectory(breakout_rgbmatrix5x5)
add_subdirectory(breakout_matrix11x7)

Wyświetl plik

@ -0,0 +1,11 @@
set(LIB_NAME breakout_colourlcd320x240)
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 st7789 pico_graphics)

Wyświetl plik

@ -0,0 +1,14 @@
include(drivers/st7789/st7789.cmake)
include(libraries/pico_graphics/pico_graphics.cmake)
set(LIB_NAME breakout_colourlcd320x240)
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 st7789 pico_graphics)

Wyświetl plik

@ -0,0 +1,58 @@
#include "breakout_colourlcd320x240.hpp"
namespace pimoroni {
BreakoutColourLCD320x240::BreakoutColourLCD320x240(uint16_t *buf)
: PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, buf) {
__fb = buf;
}
BreakoutColourLCD320x240::BreakoutColourLCD320x240(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) {
__fb = buf;
}
BreakoutColourLCD320x240::BreakoutColourLCD320x240(uint16_t *buf, BG_SPI_SLOT slot)
: PicoGraphics(WIDTH, HEIGHT, buf), screen(WIDTH, HEIGHT, buf, slot) {
__fb = buf;
}
void BreakoutColourLCD320x240::init() {
// initialise the screen
screen.init(true, false, 74 * 1000 * 1000);
}
spi_inst_t* BreakoutColourLCD320x240::get_spi() const {
return screen.get_spi();
}
int BreakoutColourLCD320x240::get_cs() const {
return screen.get_cs();
}
int BreakoutColourLCD320x240::get_dc() const {
return screen.get_dc();
}
int BreakoutColourLCD320x240::get_sck() const {
return screen.get_sck();
}
int BreakoutColourLCD320x240::get_mosi() const {
return screen.get_mosi();
}
int BreakoutColourLCD320x240::get_bl() const {
return screen.get_bl();
}
void BreakoutColourLCD320x240::update() {
screen.update();
}
void BreakoutColourLCD320x240::set_backlight(uint8_t brightness) {
screen.set_backlight(brightness);
}
}

Wyświetl plik

@ -0,0 +1,53 @@
#pragma once
#include "drivers/st7789/st7789.hpp"
#include "libraries/pico_graphics/pico_graphics.hpp"
#include "common/pimoroni_common.hpp"
namespace pimoroni {
class BreakoutColourLCD320x240 : public PicoGraphics {
//--------------------------------------------------
// Constants
//--------------------------------------------------
public:
static const int WIDTH = 320;
static const int HEIGHT = 240;
//--------------------------------------------------
// Variables
//--------------------------------------------------
public:
uint16_t *__fb;
private:
ST7789 screen;
//--------------------------------------------------
// Constructors/Destructor
//--------------------------------------------------
public:
BreakoutColourLCD320x240(uint16_t *buf);
BreakoutColourLCD320x240(uint16_t *buf, spi_inst_t *spi,
uint cs, uint dc, uint sck, uint mosi, uint miso = PIN_UNUSED, uint bl = PIN_UNUSED);
BreakoutColourLCD320x240(uint16_t *buf, BG_SPI_SLOT slot);
//--------------------------------------------------
// Methods
//--------------------------------------------------
public:
void init();
spi_inst_t* get_spi() const;
int get_cs() const;
int get_dc() const;
int get_sck() const;
int get_mosi() const;
int get_bl() const;
void update();
void set_backlight(uint8_t brightness);
};
}