samples: boards: renesas: Add sample for CTSU input driver
Add sample for CTSU input driver using QE config files on
RSK-RX130-512KB
Signed-off-by: Minh Tang <minh.tang.ue@bp.renesas.com>
diff --git a/samples/boards/renesas/ctsu_input/CMakeLists.txt b/samples/boards/renesas/ctsu_input/CMakeLists.txt
new file mode 100644
index 0000000..48994f4
--- /dev/null
+++ b/samples/boards/renesas/ctsu_input/CMakeLists.txt
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: Apache-2.0
+
+cmake_minimum_required(VERSION 3.20.0)
+find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
+
+project(renesas_ctsu)
+
+target_sources(app PRIVATE src/main.c)
+
+if(CONFIG_INPUT_RENESAS_RX_QE_TOUCH_CFG)
+ zephyr_include_directories(src/qe_generated_files)
+ zephyr_sources(src/qe_generated_files/qe_touch_config.c)
+endif()
diff --git a/samples/boards/renesas/ctsu_input/boards/rsk_rx130_512kb.overlay b/samples/boards/renesas/ctsu_input/boards/rsk_rx130_512kb.overlay
new file mode 100644
index 0000000..ee4811e
--- /dev/null
+++ b/samples/boards/renesas/ctsu_input/boards/rsk_rx130_512kb.overlay
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+&ctsu {
+ status = "okay";
+};
+
+&onboard_slider {
+ zephyr,code = <1>;
+};
+
+&onboard_button_1 {
+ zephyr,code = <10>;
+};
+
+&onboard_button_2 {
+ zephyr,code = <11>;
+};
+
+/ {
+ leds {
+ testled0: testled0 {
+ gpios = <&ioportd 3 GPIO_ACTIVE_LOW>;
+ label = "LED0";
+ };
+
+ testled1: testled1 {
+ gpios = <&ioportd 4 GPIO_ACTIVE_LOW>;
+ label = "LED1";
+ };
+
+ testled2: testled2 {
+ gpios = <&ioporte 6 GPIO_ACTIVE_LOW>;
+ label = "LED2";
+ };
+
+ testled3: testled3 {
+ gpios = <&ioporte 7 GPIO_ACTIVE_LOW>;
+ label = "LED3";
+ };
+ };
+};
diff --git a/samples/boards/renesas/ctsu_input/prj.conf b/samples/boards/renesas/ctsu_input/prj.conf
new file mode 100644
index 0000000..f691746
--- /dev/null
+++ b/samples/boards/renesas/ctsu_input/prj.conf
@@ -0,0 +1,4 @@
+CONFIG_GPIO=y
+CONFIG_INPUT=y
+CONFIG_INPUT_MODE_SYNCHRONOUS=y
+CONFIG_INPUT_RENESAS_RX_QE_TOUCH_CFG=y
diff --git a/samples/boards/renesas/ctsu_input/src/main.c b/samples/boards/renesas/ctsu_input/src/main.c
new file mode 100644
index 0000000..5912c5e
--- /dev/null
+++ b/samples/boards/renesas/ctsu_input/src/main.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <zephyr/sys/util.h>
+#include <zephyr/device.h>
+#include <zephyr/drivers/gpio/gpio_emul.h>
+#include <zephyr/kernel.h>
+#include <zephyr/input/input.h>
+#include <zephyr/input/input_renesas_rx_ctsu.h>
+
+#ifdef CONFIG_INPUT_RENESAS_RX_QE_TOUCH_CFG
+#include "qe_touch_config.h"
+#endif /* CONFIG_INPUT_RENESAS_RX_QE_TOUCH_CFG */
+
+static const struct device *const test_touch_dev = DEVICE_DT_GET(DT_NODELABEL(ctsu));
+#define BUTTON_1_IDX DT_NODE_CHILD_IDX(DT_NODELABEL(onboard_button_1))
+#define BUTTON_2_IDX DT_NODE_CHILD_IDX(DT_NODELABEL(onboard_button_2))
+#define SLIDER_IDX DT_NODE_CHILD_IDX(DT_NODELABEL(onboard_slider))
+
+#define STACKSIZE 1024
+#define PRIORITY 7
+#define LED0_NODE DT_NODELABEL(testled0)
+#define LED1_NODE DT_NODELABEL(testled1)
+#define LED2_NODE DT_NODELABEL(testled2)
+#define LED3_NODE DT_NODELABEL(testled3)
+#define NUM_TEST_LED 4
+
+#define LED_ON 1
+#define LED_OFF 0
+
+enum {
+ TOUCH_BUTTON_1 = 10,
+ TOUCH_BUTTON_2 = 11,
+ TOUCH_SLIDER = 1,
+};
+
+static const struct gpio_dt_spec led0 = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
+static const struct gpio_dt_spec led1 = GPIO_DT_SPEC_GET(LED1_NODE, gpios);
+static const struct gpio_dt_spec led2 = GPIO_DT_SPEC_GET(LED2_NODE, gpios);
+static const struct gpio_dt_spec led3 = GPIO_DT_SPEC_GET(LED3_NODE, gpios);
+static const struct gpio_dt_spec *leds[] = {&led0, &led1, &led2, &led3};
+static volatile int led_state;
+static volatile int leds_on_off[NUM_TEST_LED] = {0};
+static volatile int current_main_led;
+
+static volatile int event_count[DT_CHILD_NUM_STATUS_OKAY(DT_NODELABEL(ctsu))] = {0};
+static uint16_t last_code;
+static volatile int32_t last_val[DT_CHILD_NUM_STATUS_OKAY(DT_NODELABEL(ctsu))];
+static struct k_sem btn1_sem;
+static struct k_sem btn2_sem;
+static struct k_sem sldr_sem;
+static struct k_sem render_sem;
+
+static void sample_setup(void)
+{
+ gpio_pin_configure_dt(&led0, GPIO_OUTPUT_INACTIVE);
+ gpio_pin_configure_dt(&led1, GPIO_OUTPUT_INACTIVE);
+ gpio_pin_configure_dt(&led2, GPIO_OUTPUT_INACTIVE);
+ gpio_pin_configure_dt(&led3, GPIO_OUTPUT_INACTIVE);
+
+ k_sem_init(&btn1_sem, 0, 1);
+ k_sem_init(&btn2_sem, 0, 1);
+ k_sem_init(&sldr_sem, 0, 1);
+ k_sem_init(&render_sem, 0, 1);
+
+#ifdef CONFIG_INPUT_RENESAS_RX_QE_TOUCH_CFG
+ int ret = renesas_rx_ctsu_group_configure(
+ test_touch_dev, (struct renesas_rx_ctsu_touch_cfg *)&g_qe_touch_instance_config01);
+
+ if (ret < 0) {
+ printk("Failed to configure QE Touch: %d\n", ret);
+ return;
+ }
+#endif /* CONFIG_INPUT_RENESAS_RX_QE_TOUCH_CFG */
+}
+
+static void button1_task(void)
+{
+ while (1) {
+ k_sem_take(&btn1_sem, K_FOREVER);
+ if (led_state == 0) {
+ /** Current leds are OFF, do nothing */
+ } else {
+ if (led_state >= 15) {
+ led_state = 1;
+ } else {
+ led_state++;
+ }
+ }
+ k_sem_give(&render_sem);
+ }
+}
+
+static void button2_task(void)
+{
+ int prev_state = 0;
+
+ while (1) {
+ k_sem_take(&btn2_sem, K_FOREVER);
+ if (led_state == 0) {
+ /** Current led state is OFF */
+ if (prev_state == 0) {
+ /** First time power on */
+ led_state = 1;
+ } else {
+ /** Restore prev_state */
+ led_state = prev_state;
+ }
+ } else {
+ prev_state = led_state;
+ led_state = 0;
+ }
+ k_sem_give(&render_sem);
+ }
+}
+
+static void slider_task(void)
+{
+ while (1) {
+ k_sem_take(&sldr_sem, K_FOREVER);
+ if (led_state == 0) {
+ continue;
+ }
+ int curr_val = last_val[SLIDER_IDX];
+
+ if (curr_val != TOUCH_OFF_VALUE) {
+ if (curr_val == 100) {
+ curr_val = 99;
+ }
+ current_main_led = 3 - (curr_val / 25);
+ }
+ k_sem_give(&render_sem);
+ }
+}
+
+static void render_task(void)
+{
+ while (1) {
+ k_sem_take(&render_sem, K_FOREVER);
+ for (int i = 0; i < NUM_TEST_LED; i++) {
+ if (led_state & BIT(i)) {
+ gpio_pin_set_dt(leds[(current_main_led + i) % 4], LED_ON);
+ } else {
+ gpio_pin_set_dt(leds[(current_main_led + i) % 4], LED_OFF);
+ }
+ }
+ }
+}
+
+static void test_touch_keys_cb_handler(struct input_event *evt, void *user_data)
+{
+ switch (evt->code) {
+ case TOUCH_BUTTON_1:
+ if (evt->value == 0) {
+ printk("Button 1 released\n");
+ if (last_val[BUTTON_1_IDX] != 0) {
+ k_sem_give(&btn1_sem);
+ }
+ } else {
+ event_count[BUTTON_1_IDX]++;
+ printk("Button 1 pressed %d time(s)\n", event_count[BUTTON_1_IDX]);
+ }
+ last_val[BUTTON_1_IDX] = evt->value;
+ break;
+
+ case TOUCH_BUTTON_2:
+ if (evt->value == 0) {
+ printk("Button 2 released\n");
+ if (last_val[BUTTON_2_IDX] != 0) {
+ k_sem_give(&btn2_sem);
+ }
+ } else {
+ event_count[BUTTON_2_IDX]++;
+ printk("Button 2 pressed %d time(s)\n", event_count[BUTTON_2_IDX]);
+ }
+ last_val[BUTTON_2_IDX] = evt->value;
+ break;
+
+ case TOUCH_SLIDER:
+ if (evt->value == TOUCH_OFF_VALUE) {
+ printk("Slider released\n");
+ if (last_val[SLIDER_IDX] != TOUCH_OFF_VALUE) {
+ }
+ } else {
+ if (last_val[SLIDER_IDX] == TOUCH_OFF_VALUE) {
+ event_count[SLIDER_IDX]++;
+ printk("Slider pressed\n");
+ }
+ printk("Position: %d\n", evt->value);
+ }
+ k_sem_give(&sldr_sem);
+ last_val[SLIDER_IDX] = evt->value;
+ break;
+
+ default:
+ break;
+ }
+ last_code = evt->code;
+}
+INPUT_CALLBACK_DEFINE(test_touch_dev, test_touch_keys_cb_handler, NULL);
+
+K_THREAD_DEFINE(button1_id, STACKSIZE, button1_task, NULL, NULL, NULL, PRIORITY, 0, 0);
+K_THREAD_DEFINE(button2_id, STACKSIZE, button2_task, NULL, NULL, NULL, PRIORITY, 0, 0);
+K_THREAD_DEFINE(slider_id, STACKSIZE, slider_task, NULL, NULL, NULL, PRIORITY, 0, 0);
+K_THREAD_DEFINE(render_id, STACKSIZE, render_task, NULL, NULL, NULL, PRIORITY, 0, 0);
+
+int main(void)
+{
+ sample_setup();
+ printk("On board CTSU components sample started!\n");
+ printk("Press on touch nodes for sample\n");
+ return 0;
+}
diff --git a/samples/boards/renesas/ctsu_input/src/qe_generated_files/qe_touch_config.c b/samples/boards/renesas/ctsu_input/src/qe_generated_files/qe_touch_config.c
new file mode 100644
index 0000000..afd30b7
--- /dev/null
+++ b/samples/boards/renesas/ctsu_input/src/qe_generated_files/qe_touch_config.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "qe_touch_config.h"
+
+volatile uint8_t g_qe_touch_flag;
+volatile ctsu_event_t g_qe_ctsu_event;
+
+void qe_touch_callback(touch_callback_args_t *p_args)
+{
+ g_qe_touch_flag = 1;
+ g_qe_ctsu_event = p_args->event;
+}
+
+/* CTSU Related Information for [CONFIG01] configuration. */
+
+const ctsu_element_cfg_t g_qe_ctsu_element_cfg_config01[] = {
+ {.ssdiv = CTSU_SSDIV_2000, .so = 0x045, .snum = 0x03, .sdpa = 0x07},
+ {.ssdiv = CTSU_SSDIV_2000, .so = 0x055, .snum = 0x03, .sdpa = 0x07},
+ {.ssdiv = CTSU_SSDIV_2000, .so = 0x04D, .snum = 0x03, .sdpa = 0x07},
+ {.ssdiv = CTSU_SSDIV_2000, .so = 0x042, .snum = 0x03, .sdpa = 0x07},
+ {.ssdiv = CTSU_SSDIV_4000, .so = 0x0D0, .snum = 0x07, .sdpa = 0x03},
+ {.ssdiv = CTSU_SSDIV_4000, .so = 0x0C9, .snum = 0x07, .sdpa = 0x03},
+};
+
+const ctsu_cfg_t g_qe_ctsu_cfg_config01 = {
+ .cap = CTSU_CAP_SOFTWARE,
+
+ .txvsel = CTSU_TXVSEL_VCC,
+
+ .atune1 = CTSU_ATUNE1_NORMAL,
+
+ .md = CTSU_MODE_SELF_MULTI_SCAN,
+
+ .ctsuchac0 = 0x80, /* ch0-ch7 enable mask */
+ .ctsuchac1 = 0x1F, /* ch8-ch15 enable mask */
+ .ctsuchac2 = 0x00, /* ch16-ch23 enable mask */
+ .ctsuchac3 = 0x00, /* ch24-ch31 enable mask */
+ .ctsuchac4 = 0x00, /* ch32-ch39 enable mask */
+ .ctsuchtrc0 = 0x00, /* ch0-ch7 mutual tx mask */
+ .ctsuchtrc1 = 0x00, /* ch8-ch15 mutual tx mask */
+ .ctsuchtrc2 = 0x00, /* ch16-ch23 mutual tx mask */
+ .ctsuchtrc3 = 0x00, /* ch24-ch31 mutual tx mask */
+ .ctsuchtrc4 = 0x00, /* ch32-ch39 mutual tx mask */
+ .num_rx = 6,
+ .num_tx = 0,
+ .p_elements = g_qe_ctsu_element_cfg_config01,
+
+#if (CTSU_TARGET_VALUE_CONFIG_SUPPORT == 1)
+ .tuning_self_target_value = 15360,
+ .tuning_mutual_target_value = 10240,
+#endif
+
+ .num_moving_average = 4,
+ .tuning_enable = true,
+ .p_callback = &qe_touch_callback,
+
+};
+
+ctsu_instance_ctrl_t g_qe_ctsu_ctrl_config01;
+
+const ctsu_instance_t g_qe_ctsu_instance_config01 = {
+ .p_ctrl = &g_qe_ctsu_ctrl_config01,
+ .p_cfg = &g_qe_ctsu_cfg_config01,
+ .p_api = &g_ctsu_on_ctsu,
+};
+
+/* Touch Related Information for [CONFIG01] configuration. */
+
+#define QE_TOUCH_CONFIG01_NUM_BUTTONS (2)
+#define QE_TOUCH_CONFIG01_NUM_SLIDERS (1)
+#define QE_TOUCH_CONFIG01_NUM_WHEELS (0)
+
+/* Button configurations */
+#if (QE_TOUCH_CONFIG01_NUM_BUTTONS != 0)
+const touch_button_cfg_t g_qe_touch_button_cfg_config01[] = {
+
+ /* button1 */
+ {
+ .elem_index = 4,
+ .threshold = 2056,
+ .hysteresis = 102,
+ },
+ /* button02 */
+ {
+ .elem_index = 5,
+ .threshold = 2865,
+ .hysteresis = 143,
+ },
+};
+#endif
+
+/* Slider configurations */
+const uint8_t g_qe_touch_elem_slider_config01_slider01[] = {3, 2, 1, 0};
+
+#if (QE_TOUCH_CONFIG01_NUM_SLIDERS != 0)
+const touch_slider_cfg_t g_qe_touch_slider_cfg_config01[] = {
+ /* slider01 */
+ {
+ .p_elem_index = g_qe_touch_elem_slider_config01_slider01,
+ .num_elements = 4,
+ .threshold = 1157,
+ },
+};
+#endif
+
+/* Wheel configurations */
+#if (QE_TOUCH_CONFIG01_NUM_WHEELS != 0)
+const touch_wheel_cfg_t g_qe_touch_wheel_cfg_config01[] = {NULL};
+#endif
+
+/* Touch configurations */
+const touch_cfg_t g_qe_touch_cfg_config01 = {
+ .p_buttons = g_qe_touch_button_cfg_config01,
+ .p_sliders = g_qe_touch_slider_cfg_config01,
+ .p_wheels = NULL,
+ .num_buttons = QE_TOUCH_CONFIG01_NUM_BUTTONS,
+ .num_sliders = QE_TOUCH_CONFIG01_NUM_SLIDERS,
+ .num_wheels = QE_TOUCH_CONFIG01_NUM_WHEELS,
+
+ .number = 0,
+
+ .on_freq = 3,
+ .off_freq = 3,
+ .drift_freq = 255,
+ .cancel_freq = 0,
+
+ .p_ctsu_instance = &g_qe_ctsu_instance_config01,
+};
+
+touch_instance_ctrl_t g_qe_touch_ctrl_config01;
+
+const touch_instance_t g_qe_touch_instance_config01 = {
+ .p_ctrl = &g_qe_touch_ctrl_config01,
+ .p_cfg = &g_qe_touch_cfg_config01,
+ .p_api = &g_touch_on_ctsu,
+};
diff --git a/samples/boards/renesas/ctsu_input/src/qe_generated_files/qe_touch_config.h b/samples/boards/renesas/ctsu_input/src/qe_generated_files/qe_touch_config.h
new file mode 100644
index 0000000..fbf8f27
--- /dev/null
+++ b/samples/boards/renesas/ctsu_input/src/qe_generated_files/qe_touch_config.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef QE_TOUCH_CONFIG_H
+#define QE_TOUCH_CONFIG_H
+
+#include "r_ctsu_qe.h"
+#include "rm_touch_qe.h"
+#include "qe_touch_define.h"
+
+/* Exported global variables */
+extern const ctsu_instance_t g_qe_ctsu_instance_config01;
+extern const touch_instance_t g_qe_touch_instance_config01;
+
+extern volatile uint8_t g_qe_touch_flag;
+extern volatile ctsu_event_t g_qe_ctsu_event;
+
+/* Exported global functions (to be accessed by other files) */
+extern void qe_touch_callback(touch_callback_args_t *p_args);
+
+#endif /* QE_TOUCH_CONFIG_H */
diff --git a/samples/boards/renesas/ctsu_input/src/qe_generated_files/qe_touch_define.h b/samples/boards/renesas/ctsu_input/src/qe_generated_files/qe_touch_define.h
new file mode 100644
index 0000000..d57c453
--- /dev/null
+++ b/samples/boards/renesas/ctsu_input/src/qe_generated_files/qe_touch_define.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2025 Renesas Electronics Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef QE_TOUCH_DEFINE_H
+#define QE_TOUCH_DEFINE_H
+
+/* Macro definitions */
+#define QE_TOUCH_VERSION 0x0420
+
+#define CTSU_CFG_NUM_SELF_ELEMENTS 6
+
+#define CTSU_CFG_NUM_MUTUAL_ELEMENTS 0
+
+#define TOUCH_CFG_MONITOR_ENABLE 1
+#define TOUCH_CFG_NUM_BUTTONS 2
+#define TOUCH_CFG_NUM_SLIDERS 1
+#define TOUCH_CFG_NUM_WHEELS 0
+#define TOUCH_CFG_PAD_ENABLE 0
+
+#define QE_TOUCH_MACRO_CTSU_IP_KIND 1
+
+#define CTSU_CFG_VCC_MV 3300
+#define CTSU_CFG_LOW_VOLTAGE_MODE 0
+
+#define CTSU_CFG_PCLK_DIVISION 0
+
+#define CTSU_CFG_TSCAP_PORT 0x0C04
+
+#define CTSU_CFG_NUM_SUMULTI 1
+
+#define CTSU_CFG_TARGET_VALUE_QE_SUPPORT 1
+
+#define CTSU_CFG_NUM_AUTOJUDGE_SELF_ELEMENTS 0
+#define CTSU_CFG_NUM_AUTOJUDGE_MUTUAL_ELEMENTS 0
+
+/* Button State Mask for each configuration. */
+#define CONFIG01_INDEX_BUTTON1 0
+#define CONFIG01_MASK_BUTTON1 (1ULL << CONFIG01_INDEX_BUTTON1)
+#define CONFIG01_INDEX_BUTTON02 1
+#define CONFIG01_MASK_BUTTON02 (1ULL << CONFIG01_INDEX_BUTTON02)
+
+#endif /* QE_TOUCH_DEFINE_H */