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:
Marc Reilly 2019-07-15 18:41:09 +01:00 committed by Maureen Helm
commit 40a3e600a9
6 changed files with 287 additions and 0 deletions

View 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)

View 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/

View 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>;
};
};

View 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

View 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

View 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);
}
}