Skip to content

Commit

Permalink
[CXRD-17] Added User-Alerts subsystem
Browse files Browse the repository at this point in the history
- 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]>
  • Loading branch information
cx-anuj-pathak committed Jul 29, 2024
1 parent a93c40a commit 6831fda
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 0 deletions.
58 changes: 58 additions & 0 deletions include/user_alerts/user_alerts.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include <stdint.h>
#include <stdbool.h>
#include <zephyr/kernel.h>

struct alert_step {
uint16_t ms;
/* extends alert info here */
};

struct buzzer_alert_step {
uint16_t ms;
uint16_t freq;
};

struct mono_led_alert_step {
uint16_t ms;
uint8_t duty;
};

struct bi_led_alert_step {
uint16_t ms;
uint8_t duty_1;
uint8_t duty_2;
};

struct rgb_led_alert_step {
uint16_t ms;
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t _rsv;
};

struct user_alerts_pattern {
const void *steps;
uint16_t steps_count;
uint16_t loop_count;
};

struct user_alerts_channel;
typedef int (*user_alerts_step_exec)(const struct user_alerts_channel *ch, const void *step);

struct user_alerts_channel {
uint8_t step_size;
const void *io;
user_alerts_step_exec exec;
uint16_t cur_step_idx;
uint16_t cur_loop_idx;
struct k_timer timer;
const struct user_alerts_pattern *pattern;
};

int user_alerts_channel_init_timer(struct user_alerts_channel *ch);

int user_alerts_channel_play(struct user_alerts_channel *ch, const struct user_alerts_pattern *pattern,
bool force);

int user_alerts_channel_stop(struct user_alerts_channel *ch, bool force);
1 change: 1 addition & 0 deletions subsys/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add_subdirectory_ifdef(CONFIG_USER_ALERTS user_alerts)
1 change: 1 addition & 0 deletions subsys/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rsource "user_alerts/Kconfig"
4 changes: 4 additions & 0 deletions subsys/user_alerts/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
zephyr_library()
zephyr_library_sources(
user_alerts.c
)
14 changes: 14 additions & 0 deletions subsys/user_alerts/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
config USER_ALERTS
bool "enable user alert subsystem"
default y
help
this will enable capability to signal specific pattern on any output device
such as buzzer, led etc to alter user

if USER_ALERTS

config USER_ALERTS_CHANNEL_QUEUE_SIZE
int "define maximum number of pending commands"
default 4

endif
79 changes: 79 additions & 0 deletions subsys/user_alerts/user_alerts.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include <zephyr/kernel.h>
#include <user_alerts/user_alerts.h>

K_MSGQ_DEFINE(user_alerts_q, sizeof(const struct user_alerts_channel *), CONFIG_USER_ALERTS_CHANNEL_QUEUE_SIZE, 1);

void ch_timer_period_irq(struct k_timer *timer)
{
struct user_alerts_channel *ch = k_timer_user_data_get(timer);
k_msgq_put(&user_alerts_q, &ch, K_NO_WAIT);
}

int user_alerts_channel_init_timer(struct user_alerts_channel *ch)
{
if (!ch) {
return -EINVAL;
}
if (k_timer_remaining_ticks(&ch->timer) > 0) {
k_timer_stop(&ch->timer);
}
k_timer_init(&ch->timer, ch_timer_period_irq, NULL);
k_timer_user_data_set(&ch->timer, ch);
return 0;
}

int user_alerts_channel_stop(struct user_alerts_channel *ch, bool force)
{
if (!ch) {
return -EINVAL;
}
ch->pattern = NULL;
return 0;
}

int user_alerts_channel_play(struct user_alerts_channel *ch, const struct user_alerts_pattern *pattern,
bool force)
{
if (!ch && !pattern && !ch->exec) {
return -EINVAL;
}
if (ch->pattern && (force == false)) {
return -EAGAIN;
}
ch->cur_step_idx = 0;
ch->cur_loop_idx = 0;
ch->pattern = pattern;
return k_msgq_put(&user_alerts_q, &ch, K_MSEC(1));
}

static void beeper_thread_loop(void)
{
struct user_alerts_channel *ch;
while (true) {
k_msgq_get(&user_alerts_q, &ch, K_FOREVER);
if (ch->pattern) {
if ((ch->pattern->loop_count == 0) ||
(ch->cur_loop_idx < ch->pattern->loop_count)) {
const void *step = ((uint8_t *)ch->pattern->steps) + (ch->step_size * ch->cur_step_idx);
ch->exec(ch, step);
k_timer_start(&ch->timer, K_MSEC(((struct alert_step *)step)->ms),
K_NO_WAIT);
ch->cur_step_idx++;
if (ch->cur_step_idx >= ch->pattern->steps_count) {
ch->cur_step_idx = 0;
ch->cur_loop_idx++;
}
} else {
ch->exec(ch, NULL);
ch->pattern = NULL;
k_timer_stop(&ch->timer);
}
} else {
ch->exec(ch, NULL);
k_timer_stop(&ch->timer);
}
}
}

K_THREAD_DEFINE(beeper_thread_id, 1024, beeper_thread_loop, NULL, NULL, NULL, K_IDLE_PRIO + 1, 0,
0);

0 comments on commit 6831fda

Please sign in to comment.