From 9ba3a6cfabffb61300dd5ee998b4cf6cd79a0352 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Mon, 14 Jun 2021 15:26:58 +0100 Subject: [PATCH] 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. --- drivers/st7789/st7789.cpp | 25 +++- drivers/st7789/st7789.hpp | 4 +- examples/CMakeLists.txt | 1 + .../breakout_colourlcd320x240/CMakeLists.txt | 12 ++ examples/breakout_colourlcd320x240/demo.cpp | 112 ++++++++++++++++++ libraries/CMakeLists.txt | 1 + .../breakout_colourlcd320x240/CMakeLists.txt | 11 ++ .../breakout_colourlcd320x240.cmake | 14 +++ .../breakout_colourlcd320x240.cpp | 58 +++++++++ .../breakout_colourlcd320x240.hpp | 53 +++++++++ 10 files changed, 288 insertions(+), 3 deletions(-) create mode 100644 examples/breakout_colourlcd320x240/CMakeLists.txt create mode 100644 examples/breakout_colourlcd320x240/demo.cpp create mode 100644 libraries/breakout_colourlcd320x240/CMakeLists.txt create mode 100644 libraries/breakout_colourlcd320x240/breakout_colourlcd320x240.cmake create mode 100644 libraries/breakout_colourlcd320x240/breakout_colourlcd320x240.cpp create mode 100644 libraries/breakout_colourlcd320x240/breakout_colourlcd320x240.hpp diff --git a/drivers/st7789/st7789.cpp b/drivers/st7789/st7789.cpp index ff8946d4..7ba77607 100644 --- a/drivers/st7789/st7789.cpp +++ b/drivers/st7789/st7789.cpp @@ -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]); diff --git a/drivers/st7789/st7789.hpp b/drivers/st7789/st7789.hpp index 87b54421..a0f1f34e 100644 --- a/drivers/st7789/st7789.hpp +++ b/drivers/st7789/st7789.hpp @@ -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; diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index d514d21d..a834aad1 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -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) diff --git a/examples/breakout_colourlcd320x240/CMakeLists.txt b/examples/breakout_colourlcd320x240/CMakeLists.txt new file mode 100644 index 00000000..49a8df8c --- /dev/null +++ b/examples/breakout_colourlcd320x240/CMakeLists.txt @@ -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}) diff --git a/examples/breakout_colourlcd320x240/demo.cpp b/examples/breakout_colourlcd320x240/demo.cpp new file mode 100644 index 00000000..413321fb --- /dev/null +++ b/examples/breakout_colourlcd320x240/demo.cpp @@ -0,0 +1,112 @@ +#include +#include + +#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 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; +} diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index 0aec3bdf..9f1c2250 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -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) diff --git a/libraries/breakout_colourlcd320x240/CMakeLists.txt b/libraries/breakout_colourlcd320x240/CMakeLists.txt new file mode 100644 index 00000000..6ba464d6 --- /dev/null +++ b/libraries/breakout_colourlcd320x240/CMakeLists.txt @@ -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) \ No newline at end of file diff --git a/libraries/breakout_colourlcd320x240/breakout_colourlcd320x240.cmake b/libraries/breakout_colourlcd320x240/breakout_colourlcd320x240.cmake new file mode 100644 index 00000000..29c2de91 --- /dev/null +++ b/libraries/breakout_colourlcd320x240/breakout_colourlcd320x240.cmake @@ -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) diff --git a/libraries/breakout_colourlcd320x240/breakout_colourlcd320x240.cpp b/libraries/breakout_colourlcd320x240/breakout_colourlcd320x240.cpp new file mode 100644 index 00000000..862b2681 --- /dev/null +++ b/libraries/breakout_colourlcd320x240/breakout_colourlcd320x240.cpp @@ -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); + } + +} \ No newline at end of file diff --git a/libraries/breakout_colourlcd320x240/breakout_colourlcd320x240.hpp b/libraries/breakout_colourlcd320x240/breakout_colourlcd320x240.hpp new file mode 100644 index 00000000..17c92a64 --- /dev/null +++ b/libraries/breakout_colourlcd320x240/breakout_colourlcd320x240.hpp @@ -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); + }; + +}