-
Notifications
You must be signed in to change notification settings - Fork 6.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
drivers: input: added input_tsc_keys
input_tsc_keys to detect key press releases using STM32 TSC Signed-off-by: Arif Balik <[email protected]>
- Loading branch information
Showing
7 changed files
with
303 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Copyright (c) 2024 Arif Balik <[email protected]> | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
config INPUT_TSC_KEYS | ||
bool "STM32 TSC touch library" | ||
default y | ||
depends on STM32_TSC | ||
select RING_BUFFER | ||
help | ||
Enable support for STM32 TSC touch library. | ||
|
||
config INPUT_TSC_KEYS_BUFFER_WORD_SIZE | ||
int "STM32 TSC touch buffer size in words" | ||
default 10 | ||
depends on INPUT_TSC_KEYS | ||
help | ||
Set the size of the buffer for the STM32 TSC touch library. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
/* | ||
* Copyright (c) 2024 Arif Balik <[email protected]> | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#define DT_DRV_COMPAT tsc_keys | ||
|
||
#include <autoconf.h> | ||
#include <stdbool.h> | ||
#include <stdlib.h> | ||
#include <zephyr/device.h> | ||
#include <zephyr/drivers/misc/stm32_tsc/stm32_tsc.h> | ||
#include <zephyr/input/input.h> | ||
#include <zephyr/kernel.h> | ||
#include <zephyr/logging/log.h> | ||
#include <zephyr/sys/spsc_lockfree.h> | ||
#include <zephyr/sys/spsc_pbuf.h> | ||
#include <zephyr/sys/util.h> | ||
#include <zephyr/sys/ring_buffer.h> | ||
|
||
LOG_MODULE_REGISTER(tsc_keys, CONFIG_INPUT_LOG_LEVEL); | ||
|
||
struct input_tsc_keys_child_data { | ||
uint32_t buffer[CONFIG_INPUT_TSC_KEYS_BUFFER_WORD_SIZE]; | ||
struct ring_buf rb; | ||
enum { | ||
INPUT_TSC_KEYS_EXPECT_DOWN, | ||
INPUT_TSC_KEYS_EXPECT_UP, | ||
} state; | ||
}; | ||
|
||
struct input_tsc_keys_child_config { | ||
char *label; | ||
uint8_t group_index; | ||
int32_t noise_threshold; | ||
int zephyr_code; | ||
struct input_tsc_keys_child_data *data; | ||
}; | ||
|
||
struct input_tsc_keys_data { | ||
struct k_timer sampling_timer; | ||
}; | ||
|
||
struct input_tsc_keys_config { | ||
const struct device *tsc_dev; | ||
stm32_tsc_callback_t tsc_callback; | ||
uint32_t sampling_interval_ms; | ||
struct input_tsc_keys_child_config *children; | ||
uint8_t child_num; | ||
}; | ||
|
||
static void input_tsc_sampling_timer_callback(struct k_timer *timer) | ||
{ | ||
const struct device *dev = k_timer_user_data_get(timer); | ||
|
||
stm32_tsc_start(dev); | ||
} | ||
|
||
static inline struct input_tsc_keys_child_config * | ||
input_tsc_child_config_get(const struct device *dev, uint8_t group) | ||
{ | ||
const struct input_tsc_keys_config *config = dev->config; | ||
|
||
for (int i = 0; i < config->child_num; i++) { | ||
const struct input_tsc_keys_child_config *child = &config->children[i]; | ||
|
||
if (child->group_index == group) { | ||
return (struct input_tsc_keys_child_config *)child; | ||
} | ||
} | ||
|
||
return NULL; | ||
} | ||
|
||
static void input_tsc_callback_handler(const struct device *dev, uint8_t group, uint32_t value) | ||
{ | ||
const struct input_tsc_keys_config *config = dev->config; | ||
|
||
const struct input_tsc_keys_child_config *child_config = | ||
input_tsc_child_config_get(dev, group); | ||
|
||
if (!child_config) { | ||
LOG_ERR("TSC@%p: No child config for group %d", config->tsc_dev, group); | ||
return; | ||
} | ||
|
||
struct input_tsc_keys_child_data *child_data = child_config->data; | ||
|
||
if (ring_buf_item_space_get(&child_data->rb) == 0) { | ||
uint32_t oldest_point; | ||
int32_t slope; | ||
|
||
(void)ring_buf_get(&child_data->rb, (uint8_t *)&oldest_point, sizeof(oldest_point)); | ||
|
||
slope = value - oldest_point; | ||
if (slope < -child_config->noise_threshold && | ||
child_data->state == INPUT_TSC_KEYS_EXPECT_DOWN) { | ||
/* this is a key press, now expect a release */ | ||
child_data->state = INPUT_TSC_KEYS_EXPECT_UP; | ||
input_report_key(dev, child_config->zephyr_code, 1, false, K_NO_WAIT); | ||
} else if (slope > child_config->noise_threshold && | ||
child_data->state == INPUT_TSC_KEYS_EXPECT_UP) { | ||
/* this is a key release, now expect a press */ | ||
child_data->state = INPUT_TSC_KEYS_EXPECT_DOWN; | ||
input_report_key(dev, child_config->zephyr_code, 0, false, K_NO_WAIT); | ||
} | ||
} | ||
|
||
(void)ring_buf_put(&child_data->rb, (uint8_t *)&value, sizeof(value)); | ||
} | ||
|
||
int input_tsc_keys_init(const struct device *dev) | ||
{ | ||
const struct input_tsc_keys_config *config = dev->config; | ||
struct input_tsc_keys_data *data = dev->data; | ||
|
||
if (!device_is_ready(config->tsc_dev)) { | ||
LOG_ERR("TSC@%p: TSC device not ready", config->tsc_dev); | ||
return -ENODEV; | ||
} | ||
|
||
for (uint8_t i = 0; i < config->child_num; i++) { | ||
const struct input_tsc_keys_child_config *child = &config->children[i]; | ||
struct input_tsc_keys_child_data *child_data = child->data; | ||
|
||
ring_buf_item_init(&child_data->rb, CONFIG_INPUT_TSC_KEYS_BUFFER_WORD_SIZE, | ||
child_data->buffer); | ||
} | ||
|
||
stm32_tsc_register_callback(config->tsc_dev, config->tsc_callback); | ||
|
||
k_timer_init(&data->sampling_timer, input_tsc_sampling_timer_callback, NULL); | ||
k_timer_user_data_set(&data->sampling_timer, (void *)config->tsc_dev); | ||
k_timer_start(&data->sampling_timer, K_NO_WAIT, K_MSEC(config->sampling_interval_ms)); | ||
|
||
return 0; | ||
} | ||
|
||
#define TSC_KEYS_CHILD(node_id) \ | ||
{ \ | ||
.label = DT_PROP(node_id, label), \ | ||
.group_index = DT_PROP(DT_PHANDLE(node_id, group), group), \ | ||
.zephyr_code = DT_PROP(node_id, zephyr_code), \ | ||
.noise_threshold = DT_PROP(node_id, noise_threshold), \ | ||
.data = &tsc_keys_child_data_##node_id, \ | ||
}, | ||
|
||
#define TSC_KEYS_CHILD_DATA(node_id) \ | ||
static struct input_tsc_keys_child_data tsc_keys_child_data_##node_id; | ||
|
||
#define TSC_KEYS_INIT(node_id) \ | ||
DT_INST_FOREACH_CHILD_STATUS_OKAY(node_id, TSC_KEYS_CHILD_DATA) \ | ||
static struct input_tsc_keys_child_config tsc_keys_children_##node_id[] = { \ | ||
DT_INST_FOREACH_CHILD_STATUS_OKAY(node_id, TSC_KEYS_CHILD)}; \ | ||
static void stm32_tsc_callback_##node_id(uint8_t group, uint32_t value) \ | ||
{ \ | ||
input_tsc_callback_handler(DEVICE_DT_INST_GET(node_id), group, value); \ | ||
} \ | ||
\ | ||
static struct input_tsc_keys_data tsc_keys_data_##node_id; \ | ||
\ | ||
static const struct input_tsc_keys_config tsc_keys_config_##node_id = { \ | ||
.tsc_dev = DEVICE_DT_GET(DT_INST_PHANDLE(node_id, tsc_controller)), \ | ||
.sampling_interval_ms = DT_INST_PROP(node_id, sampling_interval_ms), \ | ||
.child_num = DT_INST_CHILD_NUM_STATUS_OKAY(node_id), \ | ||
.children = tsc_keys_children_##node_id, \ | ||
.tsc_callback = stm32_tsc_callback_##node_id, \ | ||
}; \ | ||
\ | ||
DEVICE_DT_INST_DEFINE(node_id, input_tsc_keys_init, NULL, &tsc_keys_data_##node_id, \ | ||
&tsc_keys_config_##node_id, POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, \ | ||
NULL); | ||
|
||
DT_INST_FOREACH_STATUS_OKAY(TSC_KEYS_INIT); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# Copyright (c) 2024 Arif Balik <[email protected]> | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
description: | | ||
Input driver for STM32 Tocuh Sensing Controller (TSC). | ||
This node takes a st,stm32-tsc child node and applies | ||
filters and calculations to detect an input event | ||
Each of the `tsc-keys` child nodes represents a key | ||
in the context of the input subsystem, and a group in | ||
the context of the TSC controller, for more | ||
information see drivers/misc/st,stm32-tsc.yaml | ||
Example: | ||
#include <dt-bindings/input/input-event-codes.h> | ||
touch_buttons { | ||
compatible = "tsc-keys"; | ||
status = "okay"; | ||
tsc-controller = <&tsc>; | ||
sampling-interval-ms = <10>; | ||
demo_button { | ||
label = "Demo Button"; | ||
group = <&tsc_group0>; | ||
noise-threshold = <50>; | ||
zephyr,code = <INPUT_KEY_0>; | ||
}; | ||
}; | ||
compatible: "tsc-keys" | ||
|
||
include: | ||
- name: base.yaml | ||
property-allowlist: | ||
- compatible | ||
- zephyr,deferred-init | ||
- label | ||
- status | ||
|
||
properties: | ||
tsc-controller: | ||
type: phandle | ||
required: true | ||
description: Phandle to the TSC controller node. | ||
sampling-interval-ms: | ||
type: int | ||
default: 1 | ||
description: | | ||
Sampling interval in milliseconds. | ||
oversampling: | ||
type: int | ||
default: 10 | ||
description: | | ||
Over sampling factor. | ||
child-binding: | ||
include: | ||
- name: base.yaml | ||
property-allowlist: | ||
- label | ||
|
||
properties: | ||
group: | ||
type: phandle | ||
required: true | ||
description: Phandle to the TSC group node. | ||
noise-threshold: | ||
type: int | ||
required: true | ||
description: | | ||
This value will be used to reject the noise for both | ||
directions of the slope. | ||
sticky-key-timeout-ms: | ||
type: int | ||
default: 10000 | ||
description: | | ||
Time in milliseconds to wait before releasing a key. | ||
zephyr,code: | ||
type: int | ||
required: true | ||
description: Key code to emit. |
12 changes: 12 additions & 0 deletions
12
samples/subsys/input/input_dump/boards/stm32u083c_dk.overlay
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/* | ||
* Copyright (c) 2024 Arif Balik <[email protected]> | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
&tsc { | ||
status = "okay"; | ||
|
||
spread-spectrum; | ||
spread-spectrum-deviation = <100>; | ||
}; |