forked from kofal.net/zmk
refactor(display): Output/layer/battery thread safety.
* Submit widget updates to display queue. * Use mutex to control access to shared state for widgets.
This commit is contained in:
committed by
Pete Johanson
parent
063d98e3df
commit
2128b2b55f
@@ -4,8 +4,57 @@
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/** @file display.h
|
||||
* @brief Display functions and macros.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
struct k_work_q *zmk_display_work_q();
|
||||
|
||||
int zmk_display_init();
|
||||
bool zmk_display_is_initialized();
|
||||
int zmk_display_init();
|
||||
|
||||
/**
|
||||
* @brief Macro to define a ZMK event listener that handles the thread safety of fetching
|
||||
* the necessary state from the system work queue context, invoking a work callback
|
||||
* in the display queue context, and properly accessing that state safely when performing
|
||||
* display/LVGL updates.
|
||||
*
|
||||
* @param listener THe ZMK Event manager listener name.
|
||||
* @param state_type The struct/enum type used to store/transfer state.
|
||||
* @param cb The callback to invoke in the dispaly queue context to update the UI. Should be `void
|
||||
* func(state_type)` signature.
|
||||
* @param state_func The callback function to invoke to fetch the updated state from ZMK core.
|
||||
* Should be `state type func(const zmk_event_t *eh)` signature.
|
||||
* @retval listner##_init Generates a function `listener##_init` that should be called by the widget
|
||||
* once ready to be updated.
|
||||
**/
|
||||
#define ZMK_DISPLAY_WIDGET_LISTENER(listener, state_type, cb, state_func) \
|
||||
K_MUTEX_DEFINE(listener##_mutex); \
|
||||
static state_type __##listener##_state; \
|
||||
static state_type listener##_get_local_state() { \
|
||||
k_mutex_lock(&listener##_mutex, K_FOREVER); \
|
||||
state_type copy = __##listener##_state; \
|
||||
k_mutex_unlock(&listener##_mutex); \
|
||||
return copy; \
|
||||
}; \
|
||||
static void listener##_work_cb(struct k_work *work) { cb(listener##_get_local_state()); }; \
|
||||
K_WORK_DEFINE(listener##_work, listener##_work_cb); \
|
||||
static void listener##_refresh_state(const zmk_event_t *eh) { \
|
||||
k_mutex_lock(&listener##_mutex, K_FOREVER); \
|
||||
__##listener##_state = state_func(eh); \
|
||||
k_mutex_unlock(&listener##_mutex); \
|
||||
}; \
|
||||
static void listener##_init() { \
|
||||
listener##_refresh_state(NULL); \
|
||||
listener##_work_cb(NULL); \
|
||||
} \
|
||||
static int listener##_cb(const zmk_event_t *eh) { \
|
||||
if (zmk_display_is_initialized()) { \
|
||||
listener##_refresh_state(eh); \
|
||||
k_work_submit_to_queue(zmk_display_work_q(), &listener##_work); \
|
||||
} \
|
||||
return ZMK_EV_EVENT_BUBBLE; \
|
||||
} \
|
||||
ZMK_LISTENER(listener, listener##_cb);
|
||||
|
||||
Reference in New Issue
Block a user