Skip to content

Commit b8ddf29

Browse files
[CXRD-19] Added User button actions subsys
- added user action subsytem to monitor actions on button Signed-off-by: Anuj Pathak <[email protected]>
1 parent 3538165 commit b8ddf29

File tree

6 files changed

+158
-0
lines changed

6 files changed

+158
-0
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#pragma once
2+
3+
#include <stdint.h>
4+
#include <zephyr/kernel.h>
5+
#include <zephyr/drivers/gpio.h>
6+
#include <utils/sll_listeners.h>
7+
8+
enum user_button_actions {
9+
eUSER_BUTTON_PRESS = 0x01,
10+
eUSER_BUTTON_CLICK = 0x11,
11+
eUSER_BUTTON_CLICK_AND_HOLD = 0x12,
12+
eUSER_BUTTON_DOUBLE_CLICK = 0x22,
13+
eUSER_BUTTON_DOUBLE_CLICK_AND_HOLD = 0x23,
14+
eUSER_BUTTON_TRIPLE_CLICK = 0x33,
15+
eUSER_BUTTON_TRIPLE_CLICK_AND_HOLD = 0x34,
16+
};
17+
18+
union user_button_action_code {
19+
struct {
20+
uint8_t down_cnt : 4;
21+
uint8_t up_cnt : 4;
22+
};
23+
uint8_t code;
24+
};
25+
26+
struct user_button_actions_channel {
27+
uint8_t id;
28+
union user_button_action_code _rv;
29+
union user_button_action_code result;
30+
struct k_timer timer;
31+
struct k_work work;
32+
struct gpio_dt_spec btn;
33+
struct gpio_callback cb;
34+
};
35+
36+
typedef void (*user_button_actions_callback)(struct user_button_actions_channel *ch);
37+
38+
struct user_button_actions_listener {
39+
user_button_actions_callback handler;
40+
};
41+
42+
SLL_LISTENER_DECLARE(user_button_actions, struct user_button_actions_listener);
43+
44+
int user_button_actions_start_monitor(struct user_button_actions_channel *ch);

subsys/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
add_subdirectory_ifdef(CONFIG_USER_ALERTS user_alerts)
2+
add_subdirectory_ifdef(CONFIG_USER_BUTTON_ACTIONS user_button_actions)

subsys/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
rsource "user_alerts/Kconfig"
2+
rsource "user_button_actions/Kconfig"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
zephyr_library()
2+
zephyr_library_sources(
3+
user_button_actions.c
4+
)

subsys/user_button_actions/Kconfig

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
config USER_BUTTON_ACTIONS
2+
bool "Enable user buttin actions monitoring"
3+
select GPIO
4+
help
5+
enable button monitoring to help user signal
6+
multiple actions to the user
7+
8+
if USER_BUTTON_ACTIONS
9+
10+
config USER_BUTTON_ACTION_HOLD_TIMEOUT_MS
11+
int "timeout to detect button hold"
12+
default 1000
13+
14+
config USER_BUTTON_ACTION_RE_CLICK_TIMEOUT_MS
15+
int "timeout to detect button hold"
16+
default 250
17+
18+
endif
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#include <user_button_actions/user_button_actions.h>
2+
#include <zephyr/kernel.h>
3+
#include <zephyr/device.h>
4+
#include <zephyr/logging/log.h>
5+
#include <zephyr/drivers/gpio.h>
6+
7+
LOG_MODULE_REGISTER(user_button_actions);
8+
9+
#define CB_NULL_CHECK(cb) (((cb)->handler) != NULL)
10+
11+
SLL_LISTENER_DEFINE(user_button_actions, CB_NULL_CHECK);
12+
13+
void user_button_actions_fire_work(struct k_work *work)
14+
{
15+
struct user_button_actions_channel *ch = CONTAINER_OF(work,
16+
struct user_button_actions_channel,
17+
work);
18+
if ((ch->_rv.down_cnt - ch->_rv.up_cnt) <= 1) {
19+
LOG_INF("BTN Action %x", ch->result.code);
20+
SLL_LISTENER_FIRE_NODES(user_button_actions, handler, ch);
21+
}
22+
}
23+
24+
void user_button_actions_timeout(struct k_timer *timer)
25+
{
26+
struct user_button_actions_channel *ch = CONTAINER_OF(timer,
27+
struct user_button_actions_channel,
28+
timer);
29+
ch->result.code = ch->_rv.code;
30+
ch->_rv.code = 0;
31+
k_work_submit(&ch->work);
32+
}
33+
34+
static void user_button_actions_handler(const struct device *dev,
35+
struct gpio_callback *cb,
36+
uint32_t pins)
37+
{
38+
struct user_button_actions_channel *ch = CONTAINER_OF(cb,
39+
struct user_button_actions_channel,
40+
cb);
41+
if (gpio_pin_get_dt(&ch->btn)) {
42+
// pressed
43+
ch->_rv.down_cnt++;
44+
k_timer_start(&ch->timer,
45+
K_MSEC(CONFIG_USER_BUTTON_ACTION_HOLD_TIMEOUT_MS),
46+
K_NO_WAIT);
47+
} else {
48+
// releases
49+
ch->_rv.up_cnt++;
50+
k_timer_start(&ch->timer,
51+
K_MSEC(CONFIG_USER_BUTTON_ACTION_RE_CLICK_TIMEOUT_MS),
52+
K_NO_WAIT);
53+
}
54+
}
55+
56+
int user_button_actions_start_monitor(struct user_button_actions_channel *ch)
57+
{
58+
int err;
59+
60+
err = gpio_is_ready_dt(&ch->btn);
61+
if (!err) {
62+
LOG_ERR("BTN is not ready");
63+
return 0;
64+
}
65+
66+
err = gpio_pin_configure_dt(&ch->btn, GPIO_INPUT);
67+
if (err) {
68+
LOG_ERR("BTN is config err %d", err);
69+
return 0;
70+
}
71+
72+
gpio_init_callback(&ch->cb, user_button_actions_handler, BIT(ch->btn.pin));
73+
74+
err = gpio_add_callback(ch->btn.port, &ch->cb);
75+
if (err) {
76+
LOG_ERR("Callback config err %d", err);
77+
return 0;
78+
}
79+
80+
err = gpio_pin_interrupt_configure_dt(&ch->btn, GPIO_INT_EDGE_BOTH);
81+
if (err) {
82+
LOG_ERR("int config err %d", err);
83+
return 0;
84+
}
85+
86+
k_timer_init(&ch->timer, user_button_actions_timeout, NULL);
87+
k_work_init(&ch->work, user_button_actions_fire_work);
88+
89+
return 0;
90+
}

0 commit comments

Comments
 (0)