Skip to content

Commit 6831fda

Browse files
[CXRD-17] Added User-Alerts subsystem
- added capability to send predefined patterns of signals to the user using output devices e.g. buzzer/leds Signed-off-by: Anuj Pathak <[email protected]>
1 parent a93c40a commit 6831fda

File tree

6 files changed

+157
-0
lines changed

6 files changed

+157
-0
lines changed

include/user_alerts/user_alerts.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#include <stdint.h>
2+
#include <stdbool.h>
3+
#include <zephyr/kernel.h>
4+
5+
struct alert_step {
6+
uint16_t ms;
7+
/* extends alert info here */
8+
};
9+
10+
struct buzzer_alert_step {
11+
uint16_t ms;
12+
uint16_t freq;
13+
};
14+
15+
struct mono_led_alert_step {
16+
uint16_t ms;
17+
uint8_t duty;
18+
};
19+
20+
struct bi_led_alert_step {
21+
uint16_t ms;
22+
uint8_t duty_1;
23+
uint8_t duty_2;
24+
};
25+
26+
struct rgb_led_alert_step {
27+
uint16_t ms;
28+
uint8_t r;
29+
uint8_t g;
30+
uint8_t b;
31+
uint8_t _rsv;
32+
};
33+
34+
struct user_alerts_pattern {
35+
const void *steps;
36+
uint16_t steps_count;
37+
uint16_t loop_count;
38+
};
39+
40+
struct user_alerts_channel;
41+
typedef int (*user_alerts_step_exec)(const struct user_alerts_channel *ch, const void *step);
42+
43+
struct user_alerts_channel {
44+
uint8_t step_size;
45+
const void *io;
46+
user_alerts_step_exec exec;
47+
uint16_t cur_step_idx;
48+
uint16_t cur_loop_idx;
49+
struct k_timer timer;
50+
const struct user_alerts_pattern *pattern;
51+
};
52+
53+
int user_alerts_channel_init_timer(struct user_alerts_channel *ch);
54+
55+
int user_alerts_channel_play(struct user_alerts_channel *ch, const struct user_alerts_pattern *pattern,
56+
bool force);
57+
58+
int user_alerts_channel_stop(struct user_alerts_channel *ch, bool force);

subsys/CMakeLists.txt

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

subsys/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rsource "user_alerts/Kconfig"

subsys/user_alerts/CMakeLists.txt

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_alerts.c
4+
)

subsys/user_alerts/Kconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
config USER_ALERTS
2+
bool "enable user alert subsystem"
3+
default y
4+
help
5+
this will enable capability to signal specific pattern on any output device
6+
such as buzzer, led etc to alter user
7+
8+
if USER_ALERTS
9+
10+
config USER_ALERTS_CHANNEL_QUEUE_SIZE
11+
int "define maximum number of pending commands"
12+
default 4
13+
14+
endif

subsys/user_alerts/user_alerts.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#include <zephyr/kernel.h>
2+
#include <user_alerts/user_alerts.h>
3+
4+
K_MSGQ_DEFINE(user_alerts_q, sizeof(const struct user_alerts_channel *), CONFIG_USER_ALERTS_CHANNEL_QUEUE_SIZE, 1);
5+
6+
void ch_timer_period_irq(struct k_timer *timer)
7+
{
8+
struct user_alerts_channel *ch = k_timer_user_data_get(timer);
9+
k_msgq_put(&user_alerts_q, &ch, K_NO_WAIT);
10+
}
11+
12+
int user_alerts_channel_init_timer(struct user_alerts_channel *ch)
13+
{
14+
if (!ch) {
15+
return -EINVAL;
16+
}
17+
if (k_timer_remaining_ticks(&ch->timer) > 0) {
18+
k_timer_stop(&ch->timer);
19+
}
20+
k_timer_init(&ch->timer, ch_timer_period_irq, NULL);
21+
k_timer_user_data_set(&ch->timer, ch);
22+
return 0;
23+
}
24+
25+
int user_alerts_channel_stop(struct user_alerts_channel *ch, bool force)
26+
{
27+
if (!ch) {
28+
return -EINVAL;
29+
}
30+
ch->pattern = NULL;
31+
return 0;
32+
}
33+
34+
int user_alerts_channel_play(struct user_alerts_channel *ch, const struct user_alerts_pattern *pattern,
35+
bool force)
36+
{
37+
if (!ch && !pattern && !ch->exec) {
38+
return -EINVAL;
39+
}
40+
if (ch->pattern && (force == false)) {
41+
return -EAGAIN;
42+
}
43+
ch->cur_step_idx = 0;
44+
ch->cur_loop_idx = 0;
45+
ch->pattern = pattern;
46+
return k_msgq_put(&user_alerts_q, &ch, K_MSEC(1));
47+
}
48+
49+
static void beeper_thread_loop(void)
50+
{
51+
struct user_alerts_channel *ch;
52+
while (true) {
53+
k_msgq_get(&user_alerts_q, &ch, K_FOREVER);
54+
if (ch->pattern) {
55+
if ((ch->pattern->loop_count == 0) ||
56+
(ch->cur_loop_idx < ch->pattern->loop_count)) {
57+
const void *step = ((uint8_t *)ch->pattern->steps) + (ch->step_size * ch->cur_step_idx);
58+
ch->exec(ch, step);
59+
k_timer_start(&ch->timer, K_MSEC(((struct alert_step *)step)->ms),
60+
K_NO_WAIT);
61+
ch->cur_step_idx++;
62+
if (ch->cur_step_idx >= ch->pattern->steps_count) {
63+
ch->cur_step_idx = 0;
64+
ch->cur_loop_idx++;
65+
}
66+
} else {
67+
ch->exec(ch, NULL);
68+
ch->pattern = NULL;
69+
k_timer_stop(&ch->timer);
70+
}
71+
} else {
72+
ch->exec(ch, NULL);
73+
k_timer_stop(&ch->timer);
74+
}
75+
}
76+
}
77+
78+
K_THREAD_DEFINE(beeper_thread_id, 1024, beeper_thread_loop, NULL, NULL, NULL, K_IDLE_PRIO + 1, 0,
79+
0);

0 commit comments

Comments
 (0)