samples: display: Added generic display shield sample

Added a generic display shield sample.

Signed-off-by: Jan Van Winkel <jan.van_winkel@dxplore.eu>
This commit is contained in:
Jan Van Winkel 2019-11-11 14:58:18 +01:00 committed by Maureen Helm
parent 6252387f00
commit 7e3f9ebf3f
7 changed files with 418 additions and 0 deletions

View file

@ -313,6 +313,7 @@
/samples/boards/intel_s1000_crb/ @sathishkuttan @dcpleung @nashif
/samples/display/ @vanwinkeljan
/samples/drivers/CAN/ @alexanderwachter
/samples/drivers/display/ @vanwinkeljan
/samples/drivers/ht16k33/ @henrikbrixandersen
/samples/drivers/lora/ @Mani-Sadhasivam
/samples/gui/ @vanwinkeljan

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(display)
target_sources(app PRIVATE src/main.c)

View file

@ -0,0 +1,47 @@
.. _display-sample:
Display Sample
##############
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 or the order of the corners is not as described above then the LCD
may be endian swapped.
Building and Running
********************
As this is a generic sample it should work with any display supported by Zephyr.
Below is an example on how to build for a :ref:`nrf52840_pca10056` board with a
:ref:`adafruit_2_8_tft_touch_v2`.
.. zephyr-app-commands::
:zephyr-app: samples/drivers/display_shield
:board: nrf52840_pca10056
:goals: build
:shield: adafruit_2_8_tft_touch_v2
:compact:
For testing purpose without the need of any hardware, the :ref:`native_posix`
board is also supported and can be built as follows;
.. zephyr-app-commands::
:zephyr-app: samples/drivers/display_shield
:board: native_posix
:goals: build
:compact:
List of Arduino-based display shields
*************************************
- :ref:`adafruit_2_8_tft_touch_v2`
- :ref:`ssd1306_128_shield`
- :ref:`st7789v_generic`
- :ref:`waveshare_e_paper_raw_panel_shield`

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2019 Jan Van Winkel <jan.van_winkel@dxplore.eu>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifdef DT_INST_0_ILITEK_ILI9340_LABEL
#define DISPLAY_DEV_NAME DT_INST_0_ILITEK_ILI9340_LABEL
#endif
#ifdef DT_INST_0_SOLOMON_SSD1306FB_LABEL
#define DISPLAY_DEV_NAME DT_INST_0_SOLOMON_SSD1306FB_LABEL
#endif
#ifdef DT_INST_0_GOODDISPLAY_GDEH0213B1_LABEL
#define DISPLAY_DEV_NAME DT_INST_0_GOODDISPLAY_GDEH0213B1_LABEL
#endif
#ifdef DT_INST_0_SITRONIX_ST7789V_LABEL
#define DISPLAY_DEV_NAME DT_INST_0_SITRONIX_ST7789V_LABEL
#endif
#ifdef DT_INST_0_FSL_IMX6SX_LCDIF_LABEL
#define DISPLAY_DEV_NAME DT_INST_0_FSL_IMX6SX_LCDIF_LABEL
#endif
#ifdef CONFIG_SDL_DISPLAY_DEV_NAME
#define DISPLAY_DEV_NAME CONFIG_SDL_DISPLAY_DEV_NAME
#endif
#ifdef CONFIG_DUMMY_DISPLAY_DEV_NAME
#define DISPLAY_DEV_NAME CONFIG_DUMMY_DISPLAY_DEV_NAME
#endif

View file

@ -0,0 +1,3 @@
CONFIG_HEAP_MEM_POOL_SIZE=16384
CONFIG_LOG=y
CONFIG_DISPLAY=y

View file

@ -0,0 +1,41 @@
sample:
description: Sample application for displays
name: display_sample
tests:
sample.display.shield.adafruit_2_8_tft_touch_v2:
platform_whitelist: nrf52840_pca10056
extra_args: SHIELD=adafruit_2_8_tft_touch_v2
tags: display shield
sample.display.shield.ssd1306_128x32:
platform_whitelist: nrf52840_pca10056
extra_args: SHIELD=ssd1306_128x32
tags: display shield
sample.display.shield.ssd1306_128x64:
platform_whitelist: nrf52840_pca10056
extra_args: SHIELD=ssd1306_128x64
tags: display shield
sample.display.shield.waveshare_epaper_gdeh0213b1:
platform_whitelist: nrf52840_pca10056
extra_args: SHIELD=waveshare_epaper_gdeh0213b1
sample.display.st7789v_tl019fqv01:
platform_whitelist: nrf52_pca10040
extra_args: SHIELD=st7789v_tl019fqv01
tags: display shield
sample.display.st7789v_waveshare_240x240:
platform_whitelist: nrf52_pca10040
extra_args: SHIELD=st7789v_waveshare_240x240
tags: display shield
sample.display.mcux_elcdif:
platform_whitelist: mimxrt1050_evk
tags: display
sample.display.sdl:
build_only: true
platform_whitelist: native_posix_64
tags: display
sample.display.dummy:
platform_whitelist: native_posix
extra_configs:
- CONFIG_DUMMY_DISPLAY=y
- CONFIG_SDL_DISPLAY=n
- CONFIG_TEST=y
tags: display

View file

@ -0,0 +1,285 @@
/*
* Copyright (c) 2019 Jan Van Winkel <jan.van_winkel@dxplore.eu>
*
* Based on ST7789V sample:
* Copyright (c) 2019 Marc Reilly
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "display.h"
#include <logging/log.h>
LOG_MODULE_REGISTER(sample, LOG_LEVEL_INF);
#include <zephyr.h>
#include <device.h>
#include <drivers/display.h>
#ifdef CONFIG_ARCH_POSIX
#include "posix_board_if.h"
#endif
#ifdef CONFIG_ARCH_POSIX
#define RETURN_FROM_MAIN(exit_code) posix_exit_main(exit_code)
#else
#define RETURN_FROM_MAIN(exit_code) return
#endif
enum corner {
TOP_LEFT,
TOP_RIGHT,
BOTTOM_RIGHT,
BOTTOM_LEFT
};
typedef void (*fill_buffer)(enum corner corner, u8_t grey, u8_t *buf,
size_t buf_size);
#ifdef CONFIG_ARCH_POSIX
static void posix_exit_main(int exit_code)
{
#if CONFIG_TEST
if (exit_code == 0) {
LOG_INF("PROJECT EXECUTION SUCCESSFUL");
} else {
LOG_INF("PROJECT EXECUTION FAILED");
}
#endif
posix_exit(exit_code);
}
#endif
static void fill_buffer_argb8888(enum corner corner, u8_t grey, u8_t *buf,
size_t buf_size)
{
u32_t color = 0;
switch (corner) {
case TOP_LEFT:
color = 0x00FF0000u;
break;
case TOP_RIGHT:
color = 0x0000FF00u;
break;
case BOTTOM_RIGHT:
color = 0x000000FFu;
break;
case BOTTOM_LEFT:
color = grey << 16 | grey << 8 | grey;
break;
}
for (size_t idx = 0; idx < buf_size; idx += 4) {
*((u32_t *)(buf + idx)) = color;
}
}
static void fill_buffer_rgb888(enum corner corner, u8_t grey, u8_t *buf,
size_t buf_size)
{
u32_t color = 0;
switch (corner) {
case TOP_LEFT:
color = 0x00FF0000u;
break;
case TOP_RIGHT:
color = 0x0000FF00u;
break;
case BOTTOM_RIGHT:
color = 0x000000FFu;
break;
case BOTTOM_LEFT:
color = grey << 16 | grey << 8 | grey;
break;
}
for (size_t idx = 0; idx < buf_size; idx += 3) {
*(buf + idx + 0) = color >> 16;
*(buf + idx + 1) = color >> 8;
*(buf + idx + 2) = color >> 0;
}
}
static void fill_buffer_rgb565(enum corner corner, u8_t grey, u8_t *buf,
size_t buf_size)
{
u16_t color = 0;
u16_t grey_5bit;
switch (corner) {
case TOP_LEFT:
color = 0xF800u;
break;
case TOP_RIGHT:
color = 0x07E0u;
break;
case BOTTOM_RIGHT:
color = 0x001Fu;
break;
case BOTTOM_LEFT:
grey_5bit = grey & 0x1Fu;
/* shift the green an extra bit, it has 6 bits */
color = grey_5bit << 11 | grey_5bit << (5 + 1) | grey_5bit;
break;
}
for (size_t idx = 0; idx < buf_size; idx += 2) {
*(buf + idx + 0) = (color >> 8) & 0xFFu;
*(buf + idx + 1) = (color >> 0) & 0xFFu;
}
}
static void fill_buffer_mono(enum corner corner, u8_t grey, u8_t *buf,
size_t buf_size)
{
u16_t color;
switch (corner) {
case BOTTOM_LEFT:
color = (grey & 0x01u) ? 0xFFu : 0x00u;
break;
default:
color = 0;
break;
}
memset(buf, color, buf_size);
}
void main(void)
{
size_t x;
size_t y;
size_t rect_w;
size_t rect_h;
size_t h_step;
size_t scale;
size_t grey_count;
u8_t *buf;
s32_t grey_scale_sleep;
struct device *display_dev;
struct display_capabilities capabilities;
struct display_buffer_descriptor buf_desc;
size_t buf_size = 0;
fill_buffer fill_buffer_fnc = NULL;
LOG_INF("Display sample for %s", DISPLAY_DEV_NAME);
display_dev = device_get_binding(DISPLAY_DEV_NAME);
if (display_dev == NULL) {
LOG_ERR("Device %s not found. Aborting sample.",
DISPLAY_DEV_NAME);
RETURN_FROM_MAIN(1);
}
display_get_capabilities(display_dev, &capabilities);
if (capabilities.screen_info & SCREEN_INFO_MONO_VTILED) {
rect_w = 16;
rect_h = 8;
} else {
rect_w = 2;
rect_h = 1;
}
h_step = rect_h;
scale = (capabilities.x_resolution / 8) / rect_h;
rect_w *= scale;
rect_h *= scale;
if (capabilities.screen_info & SCREEN_INFO_EPD) {
grey_scale_sleep = K_MSEC(10000);
} else {
grey_scale_sleep = K_MSEC(100);
}
buf_size = rect_w * rect_h;
if (buf_size < (capabilities.x_resolution * h_step)) {
buf_size = capabilities.x_resolution * h_step;
}
switch (capabilities.current_pixel_format) {
case PIXEL_FORMAT_ARGB_8888:
fill_buffer_fnc = fill_buffer_argb8888;
buf_size *= 4;
break;
case PIXEL_FORMAT_RGB_888:
fill_buffer_fnc = fill_buffer_rgb888;
buf_size *= 3;
break;
case PIXEL_FORMAT_RGB_565:
fill_buffer_fnc = fill_buffer_rgb565;
buf_size *= 2;
break;
case PIXEL_FORMAT_MONO01:
case PIXEL_FORMAT_MONO10:
fill_buffer_fnc = fill_buffer_mono;
buf_size /= 8;
break;
default:
LOG_ERR("Unsupported pixel format. Aborting sample.");
RETURN_FROM_MAIN(1);
}
buf = k_malloc(buf_size);
if (buf == NULL) {
LOG_ERR("Could not allocate memory. Aborting sample.");
RETURN_FROM_MAIN(1);
}
(void)memset(buf, 0xFFu, buf_size);
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);
}
buf_desc.pitch = rect_w;
buf_desc.width = rect_w;
buf_desc.height = rect_h;
fill_buffer_fnc(TOP_LEFT, 0, buf, buf_size);
x = 0;
y = 0;
display_write(display_dev, x, y, &buf_desc, buf);
fill_buffer_fnc(TOP_RIGHT, 0, buf, buf_size);
x = capabilities.x_resolution - rect_w;
y = 0;
display_write(display_dev, x, y, &buf_desc, buf);
fill_buffer_fnc(BOTTOM_RIGHT, 0, buf, buf_size);
x = capabilities.x_resolution - rect_w;
y = capabilities.y_resolution - rect_h;
display_write(display_dev, x, y, &buf_desc, buf);
display_blanking_off(display_dev);
grey_count = 0;
x = 0;
y = capabilities.y_resolution - rect_h;
while (1) {
fill_buffer_fnc(BOTTOM_LEFT, grey_count, buf, buf_size);
display_write(display_dev, x, y, &buf_desc, buf);
++grey_count;
k_sleep(grey_scale_sleep);
#if CONFIG_TEST
if (grey_count >= 1024) {
break;
}
#endif
}
RETURN_FROM_MAIN(0);
}