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 #include <zephyr/sys/util.h>
13
14 LOG_MODULE_REGISTER(sample, LOG_LEVEL_INF);
15
16 #if !DT_NODE_EXISTS(DT_CHOSEN(zephyr_touch))
17 #error "Unsupported board: zephyr,touch is not assigned"
18 #endif
19
20 #if !DT_NODE_EXISTS(DT_CHOSEN(zephyr_display))
21 #error "Unsupported board: zephyr,display is not assigned"
22 #endif
23
24 #define WIDTH (DT_PROP(DT_CHOSEN(zephyr_display), width))
25 #define HEIGHT (DT_PROP(DT_CHOSEN(zephyr_display), height))
26 #define CROSS_DIM (WIDTH / CONFIG_SCREEN_WIDTH_TO_CROSS_DIM)
27
28 #define PIXEL_FORMAT (DT_PROP_OR(DT_CHOSEN(zephyr_display), pixel_format, PIXEL_FORMAT_ARGB_8888))
29 #define BPP ((DISPLAY_BITS_PER_PIXEL(PIXEL_FORMAT)) / BITS_PER_BYTE)
30
31 #define BUFFER_SIZE (CROSS_DIM * CROSS_DIM * BPP)
32 #define REFRESH_RATE 100
33
34 static const struct device *const display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display));
35 static const struct device *const touch_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_touch));
36 static struct display_buffer_descriptor buf_desc = {
37 .buf_size = BUFFER_SIZE, .pitch = CROSS_DIM, .width = CROSS_DIM, .height = CROSS_DIM};
38
39 static uint8_t buffer_cross[BUFFER_SIZE];
40 static const uint8_t buffer_cross_empty[BUFFER_SIZE];
41 static struct k_sem sync;
42
43 static struct {
44 size_t x;
45 size_t y;
46 bool pressed;
47 } touch_point, touch_point_drawn;
48
touch_event_callback(struct input_event * evt,void * user_data)49 static void touch_event_callback(struct input_event *evt, void *user_data)
50 {
51 if (evt->code == INPUT_ABS_X) {
52 touch_point.x = evt->value;
53 }
54 if (evt->code == INPUT_ABS_Y) {
55 touch_point.y = evt->value;
56 }
57 if (evt->code == INPUT_BTN_TOUCH) {
58 touch_point.pressed = evt->value;
59 }
60 if (evt->sync) {
61 k_sem_give(&sync);
62 }
63 }
64 INPUT_CALLBACK_DEFINE(touch_dev, touch_event_callback, NULL);
65
clear_screen(void)66 static void clear_screen(void)
67 {
68 int x;
69 int y;
70
71 for (x = 0; x < WIDTH; x += CROSS_DIM) {
72 for (y = 0; y < HEIGHT; y += CROSS_DIM) {
73 display_write(display_dev, x, y, &buf_desc, buffer_cross_empty);
74 }
75 }
76 }
77
fill_cross_buffer(void)78 static void fill_cross_buffer(void)
79 {
80 int i;
81 int x;
82 int y;
83 int index;
84
85 for (i = 0; i < BPP; i++) {
86 for (x = 0; x < CROSS_DIM; x++) {
87 index = BPP * (CROSS_DIM / 2 * CROSS_DIM + x);
88 buffer_cross[index + i] = -1;
89 }
90 for (y = 0; y < CROSS_DIM; y++) {
91 index = BPP * (y * CROSS_DIM + CROSS_DIM / 2);
92 buffer_cross[index + i] = -1;
93 }
94 }
95 }
96
get_draw_position(int value,int upper_bound)97 static int get_draw_position(int value, int upper_bound)
98 {
99 if (value < CROSS_DIM / 2) {
100 return 0;
101 }
102
103 if (value + CROSS_DIM / 2 > upper_bound) {
104 return upper_bound - CROSS_DIM;
105 }
106
107 return value - CROSS_DIM / 2;
108 }
109
main(void)110 int main(void)
111 {
112
113 LOG_INF("Touch sample for touchscreen: %s, dc: %s", touch_dev->name, display_dev->name);
114
115 if (!device_is_ready(touch_dev)) {
116 LOG_ERR("Device %s not found. Aborting sample.", touch_dev->name);
117 return 0;
118 }
119
120 if (!device_is_ready(display_dev)) {
121 LOG_ERR("Device %s not found. Aborting sample.", display_dev->name);
122 return 0;
123 }
124
125 if (BPP == 0 || BPP > 4) {
126 LOG_ERR("Unsupported BPP=%d", BPP);
127 return 0;
128 }
129 fill_cross_buffer();
130 display_blanking_off(display_dev);
131
132 clear_screen();
133 touch_point_drawn.x = CROSS_DIM / 2;
134 touch_point_drawn.y = CROSS_DIM / 2;
135 touch_point.x = -1;
136 touch_point.y = -1;
137
138 k_sem_init(&sync, 0, 1);
139
140 while (1) {
141 k_msleep(REFRESH_RATE);
142 k_sem_take(&sync, K_FOREVER);
143 LOG_INF("TOUCH %s X, Y: (%d, %d)", touch_point.pressed ? "PRESS" : "RELEASE",
144 touch_point.x, touch_point.y);
145
146 display_write(display_dev, get_draw_position(touch_point_drawn.x, WIDTH),
147 get_draw_position(touch_point_drawn.y, HEIGHT), &buf_desc,
148 buffer_cross_empty);
149
150 display_write(display_dev, get_draw_position(touch_point.x, WIDTH),
151 get_draw_position(touch_point.y, HEIGHT), &buf_desc, buffer_cross);
152
153 touch_point_drawn.x = touch_point.x;
154 touch_point_drawn.y = touch_point.y;
155 }
156 return 0;
157 }
158