From 46b12b80bb8b7be01b67af5818ab6b7bbebd23a1 Mon Sep 17 00:00:00 2001 From: Dominik Lau Date: Wed, 7 Aug 2024 12:08:51 +0200 Subject: [PATCH] samples: drivers: added a simple touch controller sample The sample is supposed to help examine the issues with touchscreen. It draws a plus in last touched position. Signed-off-by: Dominik Lau Signed-off-by: Filip Kokosinski --- samples/drivers/touch/CMakeLists.txt | 7 + samples/drivers/touch/README.rst | 32 ++++ .../touch/boards/native_posix_64.overlay | 6 + .../touch/boards/stm32f429i_disc1.overlay | 5 + .../touch/boards/stm32f746g_disco.overlay | 5 + samples/drivers/touch/prj.conf | 4 + samples/drivers/touch/sample.yaml | 15 ++ samples/drivers/touch/src/main.c | 142 ++++++++++++++++++ 8 files changed, 216 insertions(+) create mode 100644 samples/drivers/touch/CMakeLists.txt create mode 100644 samples/drivers/touch/README.rst create mode 100644 samples/drivers/touch/boards/native_posix_64.overlay create mode 100644 samples/drivers/touch/boards/stm32f429i_disc1.overlay create mode 100644 samples/drivers/touch/boards/stm32f746g_disco.overlay create mode 100644 samples/drivers/touch/prj.conf create mode 100644 samples/drivers/touch/sample.yaml create mode 100644 samples/drivers/touch/src/main.c diff --git a/samples/drivers/touch/CMakeLists.txt b/samples/drivers/touch/CMakeLists.txt new file mode 100644 index 000000000000000..e3531c4a6129f55 --- /dev/null +++ b/samples/drivers/touch/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(touch) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/drivers/touch/README.rst b/samples/drivers/touch/README.rst new file mode 100644 index 000000000000000..242f00c96f40b73 --- /dev/null +++ b/samples/drivers/touch/README.rst @@ -0,0 +1,32 @@ +.. zephyr:code-sample:: touch + :name: touchs + :relevant-api: io_interfaces + + Basic touchscreen sample. + +Overview +******** +This sample will draw a small plus in the last touched coordinates, that way you can check +if the touch screen works for a board, examine its parameters such as inverted/swapped axes. + +Building and Running +******************** +While this is a generic sample and it should work with any boards with both display controllers +and touch controllers supported by Zephyr (provided the corresponding /chosen node properties +are set i.e. `zephyr,touch` and `zephyr,display`). +Below is an example on how to build the sample for :ref:`stm327f746g_disco`; + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/touch + :board: stm32f746g_disco + :goals: build + :compact: + +For testing purpose without the need of any hardware, the :ref:`native_sim ` +board is also supported and can be built as follows; + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/touch + :board: native_sim + :goals: build + :compact: diff --git a/samples/drivers/touch/boards/native_posix_64.overlay b/samples/drivers/touch/boards/native_posix_64.overlay new file mode 100644 index 000000000000000..dd2d8cf0bfd2f9b --- /dev/null +++ b/samples/drivers/touch/boards/native_posix_64.overlay @@ -0,0 +1,6 @@ +/ { + chosen { + zephyr,display = &sdl_dc; + zephyr,touch = &input_sdl_touch; + }; +}; diff --git a/samples/drivers/touch/boards/stm32f429i_disc1.overlay b/samples/drivers/touch/boards/stm32f429i_disc1.overlay new file mode 100644 index 000000000000000..493650e7a98d998 --- /dev/null +++ b/samples/drivers/touch/boards/stm32f429i_disc1.overlay @@ -0,0 +1,5 @@ +/ { + chosen { + zephyr,touch = &stmpe811; + }; +}; diff --git a/samples/drivers/touch/boards/stm32f746g_disco.overlay b/samples/drivers/touch/boards/stm32f746g_disco.overlay new file mode 100644 index 000000000000000..afc84b6bf7165ad --- /dev/null +++ b/samples/drivers/touch/boards/stm32f746g_disco.overlay @@ -0,0 +1,5 @@ +/ { + chosen { + zephyr,touch = &ft5336; + }; +}; diff --git a/samples/drivers/touch/prj.conf b/samples/drivers/touch/prj.conf new file mode 100644 index 000000000000000..7e808b98aead3f3 --- /dev/null +++ b/samples/drivers/touch/prj.conf @@ -0,0 +1,4 @@ +CONFIG_HEAP_MEM_POOL_SIZE=16384 +CONFIG_LOG=y +CONFIG_INPUT=y +CONFIG_DISPLAY=y diff --git a/samples/drivers/touch/sample.yaml b/samples/drivers/touch/sample.yaml new file mode 100644 index 000000000000000..4ee057ae00876d9 --- /dev/null +++ b/samples/drivers/touch/sample.yaml @@ -0,0 +1,15 @@ +sample: + description: Sample application for touch controllers + name: touch_sample +tests: + sample.touch.native: + platform_allow: native_posix/native/64 + tags: + - touch + sample.touch.ft5336: + platform_allow: + - stm32f429i_disc1 + - stm32f746g_disco + tags: + - touch + harness: none diff --git a/samples/drivers/touch/src/main.c b/samples/drivers/touch/src/main.c new file mode 100644 index 000000000000000..606e054b0fc6f9a --- /dev/null +++ b/samples/drivers/touch/src/main.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2024 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_REGISTER(sample, LOG_LEVEL_INF); + +#include +#include +#include +#include + +#define CROSS_WIDTH 20 +#define CROSS_HEIGHT 20 +#define BUFFER_SIZE ((CROSS_WIDTH) * (CROSS_HEIGHT) * 4) +#define REFRESH_RATE 100 + +#ifndef DT_CHOSEN_zephyr_touch +#error "Unsupported board: zephyr,touch is not assigned" +#endif + +#ifndef DT_CHOSEN_zephyr_display +#error "Unsupported board: zephyr,display is not assigned" +#endif + +static const struct device *const display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display)); +static const struct device *const touch_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_touch)); +static struct display_capabilities capabilities; +static struct display_buffer_descriptor buf_desc = {.buf_size = BUFFER_SIZE, + .pitch = CROSS_WIDTH, + .width = CROSS_WIDTH, + .height = CROSS_HEIGHT}; + +static uint8_t buffer_cross[BUFFER_SIZE] = {0}; +static const uint8_t buffer_cross_empty[BUFFER_SIZE] = {0}; +static struct k_sem sync_x, sync_y; + +static struct { + size_t x; + size_t y; +} touch_point, touch_point_drawn; + +static void touch_event_callback(struct input_event *evt, void *user_data) +{ + if (evt->code == INPUT_ABS_X) { + touch_point.x = evt->value; + k_sem_give(&sync_x); + } + if (evt->code == INPUT_ABS_Y) { + touch_point.y = evt->value; + k_sem_give(&sync_y); + } +} + +static void clear_screen(void) +{ + int x; + int y; + + for (x = 0; x < capabilities.x_resolution; x += CROSS_WIDTH) { + for (y = 0; y < capabilities.y_resolution; y += CROSS_HEIGHT) { + display_write(display_dev, x, y, &buf_desc, buffer_cross_empty); + } + } +} + +static void fill_cross_buffer(int bpp) +{ + int i; + int x; + int y; + int index; + + for (i = 0; i < bpp; i++) { + for (x = 0; x < CROSS_WIDTH; x++) { + index = bpp * (CROSS_HEIGHT / 2 * CROSS_WIDTH + x); + buffer_cross[index + i] = -1; + } + for (y = 0; y < CROSS_HEIGHT; y++) { + index = bpp * (y * CROSS_WIDTH + CROSS_WIDTH / 2); + buffer_cross[index + i] = -1; + } + } +} + +int main(void) +{ + size_t tick_count; + size_t bpp; + + LOG_INF("Touch sample for touchscreen: %s, dc: %s", touch_dev->name, display_dev->name); + + if (!device_is_ready(touch_dev)) { + LOG_ERR("Device %s not found. Aborting sample.", display_dev->name); + return 1; + } + + if (!device_is_ready(display_dev)) { + LOG_ERR("Device %s not found. Aborting sample.", display_dev->name); + return 1; + } + + display_get_capabilities(display_dev, &capabilities); + bpp = DISPLAY_BITS_PER_PIXEL(capabilities.current_pixel_format) / 8u; + + if (bpp == 0 || bpp > 4) { + LOG_ERR("Unsupported BPP=%d", bpp); + return 1; + } + fill_cross_buffer(bpp); + display_blanking_off(display_dev); + + clear_screen(); + tick_count = 0; + touch_point_drawn.x = CROSS_WIDTH / 2; + touch_point_drawn.y = CROSS_HEIGHT / 2; + touch_point.x = -1; + touch_point.y = -1; + + k_sem_init(&sync_x, 0, 1); + k_sem_init(&sync_y, 0, 1); + INPUT_CALLBACK_DEFINE(NULL, touch_event_callback, NULL); + + while (1) { + k_msleep(REFRESH_RATE); + k_sem_take(&sync_x, K_FOREVER); + k_sem_take(&sync_y, K_FOREVER); + LOG_INF("TOUCH X, Y: (%d, %d)", touch_point.x, touch_point.y); + + display_write(display_dev, touch_point_drawn.x - CROSS_WIDTH / 2, + touch_point_drawn.y - CROSS_HEIGHT / 2, &buf_desc, + buffer_cross_empty); + display_write(display_dev, touch_point.x - CROSS_WIDTH / 2, + touch_point.y - CROSS_HEIGHT / 2, &buf_desc, buffer_cross); + + touch_point_drawn.x = touch_point.x; + touch_point_drawn.y = touch_point.y; + } + return 0; +}