diff --git a/app/boards/shields/nice_view/README.md b/app/boards/shields/nice_view/README.md index 00abfbfab..0d0c04db0 100644 --- a/app/boards/shields/nice_view/README.md +++ b/app/boards/shields/nice_view/README.md @@ -4,9 +4,21 @@ The nice!view is a low-power, high refresh rate display meant to replace I2C OLE This shield requires that an `&nice_view_spi` labeled SPI bus is provided with _at least_ MOSI, SCK, and CS pins defined. +## Custom widget + +The nice!view shield includes a custom vertical widget. + +Profile indicators show the status of the first five BLE profiles using numbers from 1 to 5. +The number corresponding to the currently selected profile is drawn in a filled disk +and the circle outline around each profile number correspond to the following states: + +- solid outline: connected +- dashed outline: not connected +- no outline: not bound + ## Disable custom widget -The nice!view shield includes a custom vertical widget. To use the built-in ZMK one, add the following item to your `.conf` file: +To use the built-in ZMK widget instead of the custom nice!view one, add the following item to your `.conf` file: ``` CONFIG_ZMK_DISPLAY_STATUS_SCREEN_BUILT_IN=y diff --git a/app/boards/shields/nice_view/widgets/status.c b/app/boards/shields/nice_view/widgets/status.c index 5cbbd91cd..9769f4d7b 100644 --- a/app/boards/shields/nice_view/widgets/status.c +++ b/app/boards/shields/nice_view/widgets/status.c @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 The ZMK Contributors + * Copyright (c) 2025 The ZMK Contributors * SPDX-License-Identifier: MIT * */ @@ -33,6 +33,8 @@ struct output_status_state { int active_profile_index; bool active_profile_connected; bool active_profile_bonded; + bool profiles_connected[NICEVIEW_PROFILE_COUNT]; + bool profiles_bonded[NICEVIEW_PROFILE_COUNT]; }; struct layer_status_state { @@ -142,15 +144,24 @@ static void draw_middle(lv_obj_t *widget, lv_color_t cbuf[], const struct status lv_canvas_draw_rect(canvas, 0, 0, CANVAS_SIZE, CANVAS_SIZE, &rect_black_dsc); // Draw circles - int circle_offsets[5][2] = { + int circle_offsets[NICEVIEW_PROFILE_COUNT][2] = { {13, 13}, {55, 13}, {34, 34}, {13, 55}, {55, 55}, }; - for (int i = 0; i < 5; i++) { + for (int i = 0; i < NICEVIEW_PROFILE_COUNT; i++) { bool selected = i == state->active_profile_index; - lv_canvas_draw_arc(canvas, circle_offsets[i][0], circle_offsets[i][1], 13, 0, 360, - &arc_dsc); + if (state->profiles_connected[i]) { + lv_canvas_draw_arc(canvas, circle_offsets[i][0], circle_offsets[i][1], 13, 0, 360, + &arc_dsc); + } else if (state->profiles_bonded[i]) { + const int segments = 8; + const int gap = 20; + for (int j = 0; j < segments; ++j) + lv_canvas_draw_arc(canvas, circle_offsets[i][0], circle_offsets[i][1], 13, + 360. / segments * j + gap / 2.0, + 360. / segments * (j + 1) - gap / 2.0, &arc_dsc); + } if (selected) { lv_canvas_draw_arc(canvas, circle_offsets[i][0], circle_offsets[i][1], 9, 0, 359, @@ -234,6 +245,10 @@ static void set_output_status(struct zmk_widget_status *widget, widget->state.active_profile_index = state->active_profile_index; widget->state.active_profile_connected = state->active_profile_connected; widget->state.active_profile_bonded = state->active_profile_bonded; + for (int i = 0; i < NICEVIEW_PROFILE_COUNT; ++i) { + widget->state.profiles_connected[i] = state->profiles_connected[i]; + widget->state.profiles_bonded[i] = state->profiles_bonded[i]; + } draw_top(widget->obj, widget->cbuf, &widget->state); draw_middle(widget->obj, widget->cbuf2, &widget->state); @@ -245,12 +260,17 @@ static void output_status_update_cb(struct output_status_state state) { } static struct output_status_state output_status_get_state(const zmk_event_t *_eh) { - return (struct output_status_state){ + struct output_status_state state = { .selected_endpoint = zmk_endpoints_selected(), .active_profile_index = zmk_ble_active_profile_index(), .active_profile_connected = zmk_ble_active_profile_is_connected(), .active_profile_bonded = !zmk_ble_active_profile_is_open(), }; + for (int i = 0; i < MIN(NICEVIEW_PROFILE_COUNT, ZMK_BLE_PROFILE_COUNT); ++i) { + state.profiles_connected[i] = zmk_ble_profile_is_connected(i); + state.profiles_bonded[i] = !zmk_ble_profile_is_open(i); + } + return state; } ZMK_DISPLAY_WIDGET_LISTENER(widget_output_status, struct output_status_state, diff --git a/app/boards/shields/nice_view/widgets/util.h b/app/boards/shields/nice_view/widgets/util.h index fbcb616fa..686e5af27 100644 --- a/app/boards/shields/nice_view/widgets/util.h +++ b/app/boards/shields/nice_view/widgets/util.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2023 The ZMK Contributors + * Copyright (c) 2025 The ZMK Contributors * SPDX-License-Identifier: MIT * */ @@ -8,6 +8,8 @@ #include #include +#define NICEVIEW_PROFILE_COUNT 5 + #define CANVAS_SIZE 68 #define LVGL_BACKGROUND \ @@ -23,6 +25,8 @@ struct status_state { int active_profile_index; bool active_profile_connected; bool active_profile_bonded; + bool profiles_connected[NICEVIEW_PROFILE_COUNT]; + bool profiles_bonded[NICEVIEW_PROFILE_COUNT]; uint8_t layer_index; const char *layer_label; uint8_t wpm[10];