From 16ab6df18df89da9641378a150617c52a1d60c88 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Tue, 26 Apr 2022 05:00:46 +0000 Subject: [PATCH] feat(display): Add new peripheral status/display * Add new API/status to track state of the peripheral connection to the central. * Add new peripheral status widget for displaying the current status of the connection to the central. --- app/CMakeLists.txt | 35 ++++++----- .../zmk/display/widgets/peripheral_status.h | 19 ++++++ .../events/split_peripheral_status_changed.h | 16 +++++ app/include/zmk/split/bluetooth/peripheral.h | 9 +++ app/src/display/status_screen.c | 11 ++++ app/src/display/widgets/CMakeLists.txt | 1 + app/src/display/widgets/Kconfig | 10 +++- app/src/display/widgets/peripheral_status.c | 60 +++++++++++++++++++ .../events/split_peripheral_status_changed.c | 10 ++++ app/src/split/bluetooth/peripheral.c | 19 ++++++ 10 files changed, 172 insertions(+), 18 deletions(-) create mode 100644 app/include/zmk/display/widgets/peripheral_status.h create mode 100644 app/include/zmk/events/split_peripheral_status_changed.h create mode 100644 app/include/zmk/split/bluetooth/peripheral.h create mode 100644 app/src/display/widgets/peripheral_status.c create mode 100644 app/src/events/split_peripheral_status_changed.c diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index ee6d8759..734a1e59 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -26,25 +26,19 @@ target_sources(app PRIVATE src/stdlib.c) target_sources(app PRIVATE src/activity.c) target_sources(app PRIVATE src/kscan.c) target_sources(app PRIVATE src/matrix_transform.c) -target_sources(app PRIVATE src/hid.c) target_sources(app PRIVATE src/sensors.c) target_sources_ifdef(CONFIG_ZMK_WPM app PRIVATE src/wpm.c) target_sources(app PRIVATE src/event_manager.c) target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/ext_power_generic.c) target_sources(app PRIVATE src/events/activity_state_changed.c) target_sources(app PRIVATE src/events/position_state_changed.c) -target_sources(app PRIVATE src/events/layer_state_changed.c) -target_sources(app PRIVATE src/events/keycode_state_changed.c) -target_sources(app PRIVATE src/events/modifiers_state_changed.c) -target_sources(app PRIVATE src/events/endpoint_selection_changed.c) target_sources(app PRIVATE src/events/sensor_event.c) target_sources_ifdef(CONFIG_ZMK_WPM app PRIVATE src/events/wpm_state_changed.c) -target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/ble_active_profile_changed.c) -target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/battery_state_changed.c) target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/events/usb_conn_state_changed.c) target_sources(app PRIVATE src/behaviors/behavior_reset.c) target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/behaviors/behavior_ext_power.c) if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) + target_sources(app PRIVATE src/hid.c) target_sources(app PRIVATE src/behaviors/behavior_key_press.c) target_sources(app PRIVATE src/behaviors/behavior_hold_tap.c) target_sources(app PRIVATE src/behaviors/behavior_sticky_key.c) @@ -64,12 +58,16 @@ if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) target_sources(app PRIVATE src/behavior_queue.c) target_sources(app PRIVATE src/conditional_layer.c) target_sources(app PRIVATE src/endpoints.c) + target_sources(app PRIVATE src/events/endpoint_selection_changed.c) target_sources(app PRIVATE src/hid_listener.c) target_sources(app PRIVATE src/keymap.c) - - target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/behaviors/behavior_bt.c) + target_sources(app PRIVATE src/events/layer_state_changed.c) + target_sources(app PRIVATE src/events/modifiers_state_changed.c) + target_sources(app PRIVATE src/events/keycode_state_changed.c) if (CONFIG_ZMK_BLE) + target_sources(app PRIVATE src/events/ble_active_profile_changed.c) + target_sources(app PRIVATE src/behaviors/behavior_bt.c) target_sources(app PRIVATE src/ble.c) target_sources(app PRIVATE src/hog.c) endif() @@ -77,15 +75,20 @@ endif() target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/behaviors/behavior_rgb_underglow.c) target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/behaviors/behavior_backlight.c) + +target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/battery_state_changed.c) target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/battery.c) -if (CONFIG_ZMK_SPLIT_BLE AND (NOT CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)) - target_sources(app PRIVATE src/split_listener.c) - target_sources(app PRIVATE src/split/bluetooth/service.c) - target_sources(app PRIVATE src/split/bluetooth/peripheral.c) -endif() -if (CONFIG_ZMK_SPLIT_BLE AND CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) - target_sources(app PRIVATE src/split/bluetooth/central.c) +if (CONFIG_ZMK_SPLIT_BLE) + if (NOT CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) + target_sources(app PRIVATE src/split_listener.c) + target_sources(app PRIVATE src/split/bluetooth/service.c) + target_sources(app PRIVATE src/split/bluetooth/peripheral.c) + target_sources(app PRIVATE src/events/split_peripheral_status_changed.c) + endif() + if (CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) + target_sources(app PRIVATE src/split/bluetooth/central.c) + endif() endif() target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/usb.c) target_sources_ifdef(CONFIG_ZMK_USB app PRIVATE src/usb_hid.c) diff --git a/app/include/zmk/display/widgets/peripheral_status.h b/app/include/zmk/display/widgets/peripheral_status.h new file mode 100644 index 00000000..e3b41355 --- /dev/null +++ b/app/include/zmk/display/widgets/peripheral_status.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2022 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#pragma once + +#include +#include + +struct zmk_widget_peripheral_status { + sys_snode_t node; + lv_obj_t *obj; +}; + +int zmk_widget_peripheral_status_init(struct zmk_widget_peripheral_status *widget, + lv_obj_t *parent); +lv_obj_t *zmk_widget_peripheral_status_obj(struct zmk_widget_peripheral_status *widget); \ No newline at end of file diff --git a/app/include/zmk/events/split_peripheral_status_changed.h b/app/include/zmk/events/split_peripheral_status_changed.h new file mode 100644 index 00000000..c75a879f --- /dev/null +++ b/app/include/zmk/events/split_peripheral_status_changed.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2022 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#pragma once + +#include +#include + +struct zmk_split_peripheral_status_changed { + bool connected; +}; + +ZMK_EVENT_DECLARE(zmk_split_peripheral_status_changed); diff --git a/app/include/zmk/split/bluetooth/peripheral.h b/app/include/zmk/split/bluetooth/peripheral.h new file mode 100644 index 00000000..a650508a --- /dev/null +++ b/app/include/zmk/split/bluetooth/peripheral.h @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2022 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#pragma once + +bool zmk_split_bt_peripheral_is_connected(void); \ No newline at end of file diff --git a/app/src/display/status_screen.c b/app/src/display/status_screen.c index ff678afa..6ace1925 100644 --- a/app/src/display/status_screen.c +++ b/app/src/display/status_screen.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -21,6 +22,10 @@ static struct zmk_widget_battery_status battery_status_widget; static struct zmk_widget_output_status output_status_widget; #endif +#if IS_ENABLED(CONFIG_ZMK_WIDGET_PERIPHERAL_STATUS) +static struct zmk_widget_peripheral_status peripheral_status_widget; +#endif + #if IS_ENABLED(CONFIG_ZMK_WIDGET_LAYER_STATUS) static struct zmk_widget_layer_status layer_status_widget; #endif @@ -46,6 +51,12 @@ lv_obj_t *zmk_display_status_screen() { 0); #endif +#if IS_ENABLED(CONFIG_ZMK_WIDGET_PERIPHERAL_STATUS) + zmk_widget_peripheral_status_init(&peripheral_status_widget, screen); + lv_obj_align(zmk_widget_peripheral_status_obj(&peripheral_status_widget), NULL, + LV_ALIGN_IN_TOP_LEFT, 0, 0); +#endif + #if IS_ENABLED(CONFIG_ZMK_WIDGET_LAYER_STATUS) zmk_widget_layer_status_init(&layer_status_widget, screen); lv_obj_set_style_local_text_font(zmk_widget_layer_status_obj(&layer_status_widget), diff --git a/app/src/display/widgets/CMakeLists.txt b/app/src/display/widgets/CMakeLists.txt index 1d115dcc..fbf07072 100644 --- a/app/src/display/widgets/CMakeLists.txt +++ b/app/src/display/widgets/CMakeLists.txt @@ -3,5 +3,6 @@ target_sources_ifdef(CONFIG_ZMK_WIDGET_BATTERY_STATUS app PRIVATE battery_status.c) target_sources_ifdef(CONFIG_ZMK_WIDGET_OUTPUT_STATUS app PRIVATE output_status.c) +target_sources_ifdef(CONFIG_ZMK_WIDGET_PERIPHERAL_STATUS app PRIVATE peripheral_status.c) target_sources_ifdef(CONFIG_ZMK_WIDGET_LAYER_STATUS app PRIVATE layer_status.c) target_sources_ifdef(CONFIG_ZMK_WIDGET_WPM_STATUS app PRIVATE wpm_status.c) diff --git a/app/src/display/widgets/Kconfig b/app/src/display/widgets/Kconfig index 0a6bf5c4..7357663f 100644 --- a/app/src/display/widgets/Kconfig +++ b/app/src/display/widgets/Kconfig @@ -17,8 +17,14 @@ config ZMK_WIDGET_BATTERY_STATUS config ZMK_WIDGET_OUTPUT_STATUS bool "Widget for keyboard output status icons" - depends on BT - default y if BT + depends on BT && (!ZMK_SPLIT_BLE || ZMK_SPLIT_BLE_ROLE_CENTRAL) + default y if BT && (!ZMK_SPLIT_BLE || ZMK_SPLIT_BLE_ROLE_CENTRAL) + select LVGL_USE_LABEL + +config ZMK_WIDGET_PERIPHERAL_STATUS + bool "Widget for split peripheral status icons" + depends on BT && ZMK_SPLIT_BLE && !ZMK_SPLIT_BLE_ROLE_CENTRAL + default y if BT && ZMK_SPLIT_BLE && !ZMK_SPLIT_BLE_ROLE_CENTRAL select LVGL_USE_LABEL config ZMK_WIDGET_WPM_STATUS diff --git a/app/src/display/widgets/peripheral_status.c b/app/src/display/widgets/peripheral_status.c new file mode 100644 index 00000000..baf48f58 --- /dev/null +++ b/app/src/display/widgets/peripheral_status.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include + +#include +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#include +#include +#include +#include +#include + +static sys_slist_t widgets = SYS_SLIST_STATIC_INIT(&widgets); + +struct peripheral_status_state { + bool connected; +}; + +static struct peripheral_status_state get_state(const zmk_event_t *_eh) { + return (struct peripheral_status_state){.connected = zmk_split_bt_peripheral_is_connected()}; +} + +static void set_status_symbol(lv_obj_t *label, struct peripheral_status_state state) { + const char *text = + state.connected ? (LV_SYMBOL_WIFI " " LV_SYMBOL_OK) : (LV_SYMBOL_WIFI " " LV_SYMBOL_CLOSE); + + LOG_DBG("connected? %s", state.connected ? "true" : "false"); + lv_label_set_text(label, text); +} + +static void output_status_update_cb(struct peripheral_status_state state) { + struct zmk_widget_peripheral_status *widget; + SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_status_symbol(widget->obj, state); } +} + +ZMK_DISPLAY_WIDGET_LISTENER(widget_peripheral_status, struct peripheral_status_state, + output_status_update_cb, get_state) +ZMK_SUBSCRIPTION(widget_peripheral_status, zmk_split_peripheral_status_changed); + +int zmk_widget_peripheral_status_init(struct zmk_widget_peripheral_status *widget, + lv_obj_t *parent) { + widget->obj = lv_label_create(parent, NULL); + + lv_obj_set_size(widget->obj, 40, 15); + + sys_slist_append(&widgets, &widget->node); + + widget_peripheral_status_init(); + return 0; +} + +lv_obj_t *zmk_widget_peripheral_status_obj(struct zmk_widget_peripheral_status *widget) { + return widget->obj; +} diff --git a/app/src/events/split_peripheral_status_changed.c b/app/src/events/split_peripheral_status_changed.c new file mode 100644 index 00000000..1d70b2ff --- /dev/null +++ b/app/src/events/split_peripheral_status_changed.c @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2022 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include + +ZMK_EVENT_IMPL(zmk_split_peripheral_status_changed); \ No newline at end of file diff --git a/app/src/split/bluetooth/peripheral.c b/app/src/split/bluetooth/peripheral.c index 13b75ba7..aa690ab2 100644 --- a/app/src/split/bluetooth/peripheral.c +++ b/app/src/split/bluetooth/peripheral.c @@ -30,6 +30,8 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); +#include +#include #include #include @@ -39,16 +41,30 @@ static const struct bt_data zmk_ble_ad[] = { ), BT_DATA_BYTES(BT_DATA_UUID128_ALL, ZMK_SPLIT_BT_SERVICE_UUID)}; +static bool is_connected = false; + static int start_advertising() { return bt_le_adv_start(BT_LE_ADV_CONN, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0); }; +static void connected(struct bt_conn *conn, uint8_t err) { + is_connected = (err == 0); + + ZMK_EVENT_RAISE(new_zmk_split_peripheral_status_changed( + (struct zmk_split_peripheral_status_changed){.connected = is_connected})); +} + static void disconnected(struct bt_conn *conn, uint8_t reason) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); LOG_DBG("Disconnected from %s (reason 0x%02x)", log_strdup(addr), reason); + + is_connected = false; + + ZMK_EVENT_RAISE(new_zmk_split_peripheral_status_changed( + (struct zmk_split_peripheral_status_changed){.connected = is_connected})); } static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) { @@ -73,11 +89,14 @@ static void le_param_updated(struct bt_conn *conn, uint16_t interval, uint16_t l } static struct bt_conn_cb conn_callbacks = { + .connected = connected, .disconnected = disconnected, .security_changed = security_changed, .le_param_updated = le_param_updated, }; +bool zmk_split_bt_peripheral_is_connected() { return is_connected; } + static int zmk_peripheral_ble_init(const struct device *_arg) { int err = bt_enable(NULL);