Skip to content

Commit 8941a21

Browse files
laudominikfabiobaltieri
authored andcommitted
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 <[email protected]> Signed-off-by: Filip Kokosinski <[email protected]>
1 parent ac670c4 commit 8941a21

File tree

7 files changed

+224
-0
lines changed

7 files changed

+224
-0
lines changed

boards/native/native_sim/native_sim.dts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
zephyr,canbus = &can_loopback0;
2626
zephyr,code-partition = &slot0_partition;
2727
zephyr,bt-hci = &bt_hci_userchan;
28+
zephyr,touch = &input_sdl_touch;
2829
};
2930

3031
aliases {
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5+
project(touch)
6+
7+
target_sources(app PRIVATE src/main.c)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Copyright (c) 2024 Antmicro <www.antmicro.com>
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config SCREEN_WIDTH_TO_CROSS_DIM
5+
int "Screen width to cross horizontal/vertical dimension ratio"
6+
default 25
7+
8+
source "Kconfig.zephyr"
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
.. zephyr:code-sample:: draw_touch_events
2+
:name: Draw touch events
3+
:relevant-api: input_events display_interface
4+
5+
Visualize touch events on a display.
6+
7+
Overview
8+
********
9+
This sample will draw a small plus in the last touched coordinates, that way you can check
10+
if the touch screen works for a board, examine its parameters such as inverted/swapped axes.
11+
12+
Building and Running
13+
********************
14+
While this is a generic sample and it should work with any boards with both display controllers
15+
and touch controllers supported by Zephyr (provided the corresponding ``/chosen node`` properties
16+
are set i.e. ``zephyr,touch`` and ``zephyr,display``).
17+
Below is an example on how to build the sample for :ref:`stm32f746g_disco_board`:
18+
19+
.. zephyr-app-commands::
20+
:zephyr-app: samples/subsys/input/draw_touch_events
21+
:board: stm32f746g_disco
22+
:goals: build
23+
:compact:
24+
25+
For testing purposes without the need of any hardware, the :ref:`native_sim <native_sim>`
26+
board is also supported and can be built as follows:
27+
28+
.. zephyr-app-commands::
29+
:zephyr-app: samples/subsys/input/draw_touch_events
30+
:board: native_sim
31+
:goals: build
32+
:compact:
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
CONFIG_HEAP_MEM_POOL_SIZE=16384
2+
CONFIG_LOG=y
3+
CONFIG_INPUT=y
4+
CONFIG_DISPLAY=y
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
sample:
2+
description: Sample application for touch controllers
3+
name: touch_sample
4+
tests:
5+
sample.touch.native:
6+
build_only: true
7+
platform_allow: native_sim/native/64
8+
tags:
9+
- touch
10+
sample.touch.ft5336:
11+
platform_allow:
12+
- stm32f429i_disc1
13+
- stm32f746g_disco
14+
tags:
15+
- touch
16+
harness: none
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*
2+
* Copyright (c) 2024 Antmicro <www.antmicro.com>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/logging/log.h>
8+
#include <zephyr/kernel.h>
9+
#include <zephyr/device.h>
10+
#include <zephyr/input/input.h>
11+
#include <zephyr/drivers/display.h>
12+
13+
LOG_MODULE_REGISTER(sample, LOG_LEVEL_INF);
14+
15+
#if !DT_NODE_EXISTS(DT_CHOSEN(zephyr_touch))
16+
#error "Unsupported board: zephyr,touch is not assigned"
17+
#endif
18+
19+
#if !DT_NODE_EXISTS(DT_CHOSEN(zephyr_display))
20+
#error "Unsupported board: zephyr,display is not assigned"
21+
#endif
22+
23+
#define WIDTH (DT_PROP(DT_CHOSEN(zephyr_display), width))
24+
#define HEIGHT (DT_PROP(DT_CHOSEN(zephyr_display), height))
25+
#define CROSS_DIM (WIDTH / CONFIG_SCREEN_WIDTH_TO_CROSS_DIM)
26+
27+
#define PIXEL_FORMAT (DT_PROP_OR(DT_CHOSEN(zephyr_display), pixel_format, PIXEL_FORMAT_ARGB_8888))
28+
#define BPP ((DISPLAY_BITS_PER_PIXEL(PIXEL_FORMAT)) / 8)
29+
30+
#define BUFFER_SIZE (CROSS_DIM * CROSS_DIM * BPP)
31+
#define REFRESH_RATE 100
32+
33+
static const struct device *const display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display));
34+
static const struct device *const touch_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_touch));
35+
static struct display_buffer_descriptor buf_desc = {
36+
.buf_size = BUFFER_SIZE, .pitch = CROSS_DIM, .width = CROSS_DIM, .height = CROSS_DIM};
37+
38+
static uint8_t buffer_cross[BUFFER_SIZE];
39+
static const uint8_t buffer_cross_empty[BUFFER_SIZE];
40+
static struct k_sem sync;
41+
42+
static struct {
43+
size_t x;
44+
size_t y;
45+
bool pressed;
46+
} touch_point, touch_point_drawn;
47+
48+
static void touch_event_callback(struct input_event *evt, void *user_data)
49+
{
50+
if (evt->code == INPUT_ABS_X) {
51+
touch_point.x = evt->value;
52+
}
53+
if (evt->code == INPUT_ABS_Y) {
54+
touch_point.y = evt->value;
55+
}
56+
if (evt->code == INPUT_BTN_TOUCH) {
57+
touch_point.pressed = evt->value;
58+
}
59+
if (evt->sync) {
60+
k_sem_give(&sync);
61+
}
62+
}
63+
INPUT_CALLBACK_DEFINE(touch_dev, touch_event_callback, NULL);
64+
65+
static void clear_screen(void)
66+
{
67+
int x;
68+
int y;
69+
70+
for (x = 0; x < WIDTH; x += CROSS_DIM) {
71+
for (y = 0; y < HEIGHT; y += CROSS_DIM) {
72+
display_write(display_dev, x, y, &buf_desc, buffer_cross_empty);
73+
}
74+
}
75+
}
76+
77+
static void fill_cross_buffer(void)
78+
{
79+
int i;
80+
int x;
81+
int y;
82+
int index;
83+
84+
for (i = 0; i < BPP; i++) {
85+
for (x = 0; x < CROSS_DIM; x++) {
86+
index = BPP * (CROSS_DIM / 2 * CROSS_DIM + x);
87+
buffer_cross[index + i] = -1;
88+
}
89+
for (y = 0; y < CROSS_DIM; y++) {
90+
index = BPP * (y * CROSS_DIM + CROSS_DIM / 2);
91+
buffer_cross[index + i] = -1;
92+
}
93+
}
94+
}
95+
96+
static int get_draw_position(int value, int upper_bound)
97+
{
98+
if (value < CROSS_DIM / 2) {
99+
return 0;
100+
}
101+
102+
if (value + CROSS_DIM / 2 > upper_bound) {
103+
return upper_bound - CROSS_DIM;
104+
}
105+
106+
return value - CROSS_DIM / 2;
107+
}
108+
109+
int main(void)
110+
{
111+
112+
LOG_INF("Touch sample for touchscreen: %s, dc: %s", touch_dev->name, display_dev->name);
113+
114+
if (!device_is_ready(touch_dev)) {
115+
LOG_ERR("Device %s not found. Aborting sample.", touch_dev->name);
116+
return 0;
117+
}
118+
119+
if (!device_is_ready(display_dev)) {
120+
LOG_ERR("Device %s not found. Aborting sample.", display_dev->name);
121+
return 0;
122+
}
123+
124+
if (BPP == 0 || BPP > 4) {
125+
LOG_ERR("Unsupported BPP=%d", BPP);
126+
return 0;
127+
}
128+
fill_cross_buffer();
129+
display_blanking_off(display_dev);
130+
131+
clear_screen();
132+
touch_point_drawn.x = CROSS_DIM / 2;
133+
touch_point_drawn.y = CROSS_DIM / 2;
134+
touch_point.x = -1;
135+
touch_point.y = -1;
136+
137+
k_sem_init(&sync, 0, 1);
138+
139+
while (1) {
140+
k_msleep(REFRESH_RATE);
141+
k_sem_take(&sync, K_FOREVER);
142+
LOG_INF("TOUCH %s X, Y: (%d, %d)", touch_point.pressed ? "PRESS" : "RELEASE",
143+
touch_point.x, touch_point.y);
144+
145+
display_write(display_dev, get_draw_position(touch_point_drawn.x, WIDTH),
146+
get_draw_position(touch_point_drawn.y, HEIGHT), &buf_desc,
147+
buffer_cross_empty);
148+
149+
display_write(display_dev, get_draw_position(touch_point.x, WIDTH),
150+
get_draw_position(touch_point.y, HEIGHT), &buf_desc, buffer_cross);
151+
152+
touch_point_drawn.x = touch_point.x;
153+
touch_point_drawn.y = touch_point.y;
154+
}
155+
return 0;
156+
}

0 commit comments

Comments
 (0)