samples: display: add a simple sample for st7789v display
This adds a basic app which puts some rectangles on the display It's hard to write an equivalent README to the rest of the sample documentation, as the LCD I have uses a custom board thrown together for testing. (ie other LCDs have publicly available modules) Signed-off-by: Marc Reilly <marc@cpdesign.com.au>
This commit is contained in:
parent
b0203ac95b
commit
40a3e600a9
6 changed files with 287 additions and 0 deletions
7
samples/display/st7789v/CMakeLists.txt
Normal file
7
samples/display/st7789v/CMakeLists.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.13.1)
|
||||
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
|
||||
project(st7789v)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
60
samples/display/st7789v/README.rst
Normal file
60
samples/display/st7789v/README.rst
Normal file
|
@ -0,0 +1,60 @@
|
|||
.. _st7789v-sample:
|
||||
|
||||
ST7789V Display driver
|
||||
######################
|
||||
|
||||
Overview
|
||||
********
|
||||
This sample will draw some basic rectangles onto the display.
|
||||
The rectangle colors and positions are chosen so that you can check the
|
||||
orientation of the LCD and correct RGB bit order. The rectangles are drawn
|
||||
in clockwise order, from top left corner: Red, Green, Blue, grey. The shade of
|
||||
grey changes from black through to white. (if the grey looks too green or red
|
||||
at any point then the LCD may be endian swapped).
|
||||
|
||||
Note: The display driver rotates the display so that the 'natural' LCD
|
||||
orientation is effectively 270 degrees clockwise of the default display
|
||||
controller orientation.
|
||||
|
||||
Building and Running
|
||||
********************
|
||||
The sample has a board overlay for a nrf52832 based board with the following
|
||||
pin assignments:
|
||||
|
||||
+-------------+-------------+
|
||||
| | nRF52832 | | LCD module|
|
||||
| | Pin | | signal |
|
||||
+=============+=============+
|
||||
| P0.03 | SPI_SCK |
|
||||
+-------------+-------------+
|
||||
| P0.05 | SPI_MOSI |
|
||||
+-------------+-------------+
|
||||
| P0.26 | SPI_MISO |
|
||||
+-------------+-------------+
|
||||
| P0.27 | CS |
|
||||
+-------------+-------------+
|
||||
| P0.25 | DATA/CMD |
|
||||
+-------------+-------------+
|
||||
| P0.02 | RESET |
|
||||
+-------------+-------------+
|
||||
|
||||
You might need to alter these according to your specific board/LCD configuration.
|
||||
|
||||
For :ref:`nrf52_pca10040`, build this sample application with the following commands:
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/display/st7789v
|
||||
:board: nrf52_pca10040
|
||||
:goals: build
|
||||
:compact:
|
||||
|
||||
See :ref:`nrf52_pca10040` on how to flash the build.
|
||||
|
||||
|
||||
References
|
||||
**********
|
||||
|
||||
- `ST7789V datasheet`_
|
||||
|
||||
.. _Manufacturer site: https://www.sitronix.com.tw/en/product/Driver/mobile_display.html
|
||||
.. _ST7789V datasheet: https://www.crystalfontz.com/controllers/Sitronix/ST7789V/
|
25
samples/display/st7789v/nrf52_pca10040.overlay
Normal file
25
samples/display/st7789v/nrf52_pca10040.overlay
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Creative Product Design
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
&spi0 {
|
||||
status = "okay";
|
||||
sck-pin = <3>;
|
||||
mosi-pin = <5>;
|
||||
miso-pin = <26>;
|
||||
cs-gpios = <&gpio0 27 0>;
|
||||
|
||||
st7789v@0 {
|
||||
compatible = "sitronix,st7789v";
|
||||
label = "DISPLAY";
|
||||
spi-max-frequency = <20000000>;
|
||||
reg = <0>;
|
||||
cmd-data-gpios = <&gpio0 25 0>;
|
||||
reset-gpios = <&gpio0 2 0>;
|
||||
width = <320>;
|
||||
height = <170>;
|
||||
y-offset = <35>;
|
||||
};
|
||||
};
|
15
samples/display/st7789v/prj.conf
Normal file
15
samples/display/st7789v/prj.conf
Normal file
|
@ -0,0 +1,15 @@
|
|||
CONFIG_PRINTK=y
|
||||
|
||||
CONFIG_HEAP_MEM_POOL_SIZE=16384
|
||||
|
||||
CONFIG_GPIO=y
|
||||
CONFIG_SPI=y
|
||||
|
||||
CONFIG_DISPLAY=y
|
||||
CONFIG_ST7789V=y
|
||||
CONFIG_ST7789V_LCD_TL019FQV01=y
|
||||
CONFIG_ST7789V_RGB565=y
|
||||
|
||||
CONFIG_DISPLAY_LOG_LEVEL_DBG=y
|
||||
|
||||
CONFIG_LOG=y
|
8
samples/display/st7789v/sample.yaml
Normal file
8
samples/display/st7789v/sample.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
sample:
|
||||
description: Sample application for ST7789V display
|
||||
name: st7789v_sample
|
||||
tests:
|
||||
sample.display.st7789v:
|
||||
build_only: true
|
||||
platform_whitelist: nrf52_pca10040
|
||||
tags: display
|
172
samples/display/st7789v/src/main.c
Normal file
172
samples/display/st7789v/src/main.c
Normal file
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Marc Reilly
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(app, LOG_LEVEL_INF);
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <device.h>
|
||||
#include <display.h>
|
||||
|
||||
static void backlight_init(void)
|
||||
{
|
||||
/* If you have a backlight, set it up and turn it on here */
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
LOG_INF("ST7789V display sample");
|
||||
struct device *display_dev;
|
||||
|
||||
struct display_capabilities capabilities;
|
||||
struct display_buffer_descriptor buf_desc;
|
||||
|
||||
backlight_init();
|
||||
|
||||
#ifdef CONFIG_ST7789V_RGB565
|
||||
const size_t rgb_size = 2;
|
||||
#else
|
||||
const size_t rgb_size = 3;
|
||||
#endif
|
||||
|
||||
display_dev = device_get_binding(DT_INST_0_SITRONIX_ST7789V_LABEL);
|
||||
|
||||
if (display_dev == NULL) {
|
||||
LOG_ERR("Device not found. Aborting test.");
|
||||
return;
|
||||
}
|
||||
|
||||
display_get_capabilities(display_dev, &capabilities);
|
||||
|
||||
/* size of the rectangle */
|
||||
const size_t w = 40;
|
||||
const size_t h = 20;
|
||||
const size_t buf_size = rgb_size * w * h;
|
||||
|
||||
/* points are clockwise, from top left */
|
||||
size_t x0, y0, x1, y1, x2, y2, x3, y3;
|
||||
|
||||
/* top left */
|
||||
x0 = 0;
|
||||
y0 = 0;
|
||||
/* top right */
|
||||
x1 = capabilities.x_resolution - w;
|
||||
y1 = 0;
|
||||
/* bottom right */
|
||||
x2 = capabilities.x_resolution - w;
|
||||
y2 = capabilities.y_resolution - h;
|
||||
/* bottom left */
|
||||
x3 = 0;
|
||||
y3 = capabilities.y_resolution - h;
|
||||
|
||||
/* Allocate rectangular buffer for corner data */
|
||||
u8_t *buf = k_malloc(buf_size);
|
||||
|
||||
if (buf == NULL) {
|
||||
LOG_ERR("Could not allocate memory. Aborting test.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Clear frame buffer before enabling LCD, reuse corner buffer
|
||||
*/
|
||||
int h_step;
|
||||
(void)memset(buf, 0, buf_size);
|
||||
h_step = (w * h) / capabilities.x_resolution;
|
||||
|
||||
buf_desc.buf_size = buf_size;
|
||||
buf_desc.pitch = capabilities.x_resolution;
|
||||
buf_desc.width = capabilities.x_resolution;
|
||||
buf_desc.height = h_step;
|
||||
|
||||
for (int idx = 0; idx < capabilities.y_resolution; idx += h_step) {
|
||||
display_write(display_dev, 0, idx, &buf_desc, buf);
|
||||
}
|
||||
|
||||
display_blanking_off(display_dev);
|
||||
|
||||
buf_desc.pitch = w;
|
||||
buf_desc.width = w;
|
||||
buf_desc.height = h;
|
||||
|
||||
int grey_count = 0;
|
||||
size_t cnt = 0;
|
||||
|
||||
while (1) {
|
||||
/* Update the color of the rectangle buffer and write the buffer
|
||||
* to one of the corners
|
||||
*/
|
||||
#ifdef CONFIG_ST7789V_RGB565
|
||||
int color = cnt % 4;
|
||||
/* RGB565 format */
|
||||
u16_t color_r;
|
||||
u16_t color_g;
|
||||
u16_t color_b;
|
||||
u16_t color_rgb;
|
||||
|
||||
color_r = (color == 0) ? 0xF800U : 0U;
|
||||
color_g = (color == 1) ? 0x07E0U : 0U;
|
||||
color_b = (color == 2) ? 0x001FU : 0U;
|
||||
color_rgb = color_r + color_g + color_b;
|
||||
if (color == 3) {
|
||||
u16_t t = grey_count & 0x1f;
|
||||
/* shift the green an extra bit, it has 6 bits */
|
||||
color_rgb = t << 11 | t << (5+1) | t;
|
||||
grey_count++;
|
||||
}
|
||||
|
||||
for (size_t idx = 0; idx < buf_size; idx += rgb_size) {
|
||||
*(buf + idx + 0) = (color_rgb >> 8) & 0xFFU;
|
||||
*(buf + idx + 1) = (color_rgb >> 0) & 0xFFU;
|
||||
}
|
||||
#else
|
||||
u32_t color_rgb;
|
||||
u32_t c = grey_count & 0xff;
|
||||
|
||||
switch (cnt % 4) {
|
||||
case 0:
|
||||
color_rgb = 0x00FF0000u;
|
||||
break;
|
||||
case 1:
|
||||
color_rgb = 0x0000FF00u;
|
||||
break;
|
||||
case 2:
|
||||
color_rgb = 0x000000FFu;
|
||||
break;
|
||||
case 3:
|
||||
color_rgb = c << 16 | c << 8 | c;
|
||||
grey_count++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* RGB888 format */
|
||||
for (size_t idx = color; idx < buf_size; idx += rgb_size) {
|
||||
*(buf + idx + 0) = color_rgb >> 16;
|
||||
*(buf + idx + 1) = color_rgb >> 8;
|
||||
*(buf + idx + 2) = color_rgb >> 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (cnt % 4) {
|
||||
case 0:
|
||||
/* top left, red */
|
||||
display_write(display_dev, x0, y0, &buf_desc, buf);
|
||||
break;
|
||||
case 1:
|
||||
/* top right, green */
|
||||
display_write(display_dev, x1, y1, &buf_desc, buf);
|
||||
break;
|
||||
case 2:
|
||||
/* bottom right, blue */
|
||||
display_write(display_dev, x2, y2, &buf_desc, buf);
|
||||
break;
|
||||
case 3:
|
||||
/* bottom left, alternating grey */
|
||||
display_write(display_dev, x3, y3, &buf_desc, buf);
|
||||
break;
|
||||
}
|
||||
++cnt;
|
||||
k_sleep(100);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue