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:
parent
6252387f00
commit
7e3f9ebf3f
|
@ -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
|
||||
|
|
7
samples/drivers/display/CMakeLists.txt
Normal file
7
samples/drivers/display/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(display)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
47
samples/drivers/display/README.rst
Normal file
47
samples/drivers/display/README.rst
Normal 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`
|
34
samples/drivers/display/dts_fixup.h
Normal file
34
samples/drivers/display/dts_fixup.h
Normal 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
|
||||
|
3
samples/drivers/display/prj.conf
Normal file
3
samples/drivers/display/prj.conf
Normal file
|
@ -0,0 +1,3 @@
|
|||
CONFIG_HEAP_MEM_POOL_SIZE=16384
|
||||
CONFIG_LOG=y
|
||||
CONFIG_DISPLAY=y
|
41
samples/drivers/display/sample.yaml
Normal file
41
samples/drivers/display/sample.yaml
Normal 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
|
285
samples/drivers/display/src/main.c
Normal file
285
samples/drivers/display/src/main.c
Normal 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);
|
||||
}
|
Loading…
Reference in a new issue