Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bongo cat #2

Merged
merged 8 commits into from
Sep 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions app/include/zmk/display/widgets/bongo_cat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2022 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/

#pragma once

#include <lvgl.h>
#include <kernel.h>

struct zmk_widget_bongo_cat {
sys_snode_t node;
lv_obj_t *obj;
bool is_right;
};

int zmk_widget_bongo_cat_init(struct zmk_widget_bongo_cat *widget, lv_obj_t *parent);
lv_obj_t *zmk_widget_bongo_cat_obj(struct zmk_widget_bongo_cat *widget);
9 changes: 9 additions & 0 deletions app/src/display/status_screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <zmk/display/widgets/battery_status.h>
#include <zmk/display/widgets/layer_status.h>
#include <zmk/display/widgets/wpm_status.h>
#include <zmk/display/widgets/bongo_cat.h>
#include <zmk/display/status_screen.h>

#include <logging/log.h>
Expand All @@ -34,6 +35,10 @@ static struct zmk_widget_layer_status layer_status_widget;
static struct zmk_widget_wpm_status wpm_status_widget;
#endif

#if IS_ENABLED(CONFIG_ZMK_WIDGET_BONGO_CAT)
static struct zmk_widget_bongo_cat bongo_cat_widget;
#endif

lv_obj_t *zmk_display_status_screen() {
lv_obj_t *screen;

Expand Down Expand Up @@ -70,6 +75,10 @@ lv_obj_t *zmk_display_status_screen() {
zmk_widget_wpm_status_init(&wpm_status_widget, screen);
lv_obj_align(zmk_widget_wpm_status_obj(&wpm_status_widget), NULL, LV_ALIGN_IN_BOTTOM_RIGHT, -12,
0);
#endif
#if IS_ENABLED(CONFIG_ZMK_WIDGET_BONGO_CAT)
zmk_widget_bongo_cat_init(&bongo_cat_widget, screen);
lv_obj_align(zmk_widget_bongo_cat_obj(&bongo_cat_widget), NULL, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
#endif
return screen;
}
2 changes: 2 additions & 0 deletions app/src/display/widgets/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ 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)
target_sources_ifdef(CONFIG_ZMK_WIDGET_BONGO_CAT app PRIVATE bongo_cat.c)
target_sources_ifdef(CONFIG_ZMK_WIDGET_BONGO_CAT app PRIVATE bongo_img.c)
6 changes: 6 additions & 0 deletions app/src/display/widgets/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,10 @@ config ZMK_WIDGET_WPM_STATUS
select LVGL_USE_LABEL
select ZMK_WPM

config ZMK_WIDGET_BONGO_CAT
bool "Widget for displaying bongo cat"
depends on !ZMK_SPLIT || ZMK_SPLIT_BLE_ROLE_CENTRAL
select LVGL_USE_LABEL
select LVGL_USE_IMG

endmenu
82 changes: 82 additions & 0 deletions app/src/display/widgets/bongo_cat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2022 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/

#include <logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);

#include <zmk/display.h>
#include <zmk/display/widgets/bongo_cat.h>
#include <zmk/event_manager.h>
#include <zmk/events/position_state_changed.h>

static sys_slist_t widgets = SYS_SLIST_STATIC_INIT(&widgets);

enum bongo_state {
bongo_state_none, /* no hands down */
bongo_state_left, /* left hand down */
bongo_state_right, /* right hand down */
} current_bongo_state;

LV_IMG_DECLARE(none);
LV_IMG_DECLARE(left);
LV_IMG_DECLARE(right);
LV_IMG_DECLARE(both);

const void *images[] = {
&none,
&left,
&right,
&both
};

int zmk_widget_bongo_cat_init(struct zmk_widget_bongo_cat *widget, lv_obj_t *parent) {
widget->obj = lv_img_create(parent, NULL);
lv_img_set_src(widget->obj, &none);
current_bongo_state = bongo_state_none;

sys_slist_append(&widgets, &widget->node);

return 0;
}

lv_obj_t *zmk_widget_bongo_cat_obj(struct zmk_widget_bongo_cat *widget) {
return widget->obj;
}

void set_bongo_state(struct zmk_widget_bongo_cat *widget, struct zmk_position_state_changed *ev) {
if (ev == NULL) {
return;
}

uint8_t tmp = bongo_state_left << widget->is_right;
if (ev->state) {
if (current_bongo_state & (bongo_state_left | bongo_state_right)) {
tmp = bongo_state_left | bongo_state_right;
}
} else {
if (current_bongo_state ^ (bongo_state_left | bongo_state_right)) {
tmp = bongo_state_none;
widget->is_right = !widget->is_right; /* switch hand when return to none state */
}
}

if (current_bongo_state == tmp) {
return;
}

current_bongo_state = tmp;
lv_img_set_src(widget->obj, images[current_bongo_state]);
}

int bongo_cat_listener(const zmk_event_t *eh) {
struct zmk_widget_bongo_cat *widget;
struct zmk_position_state_changed *ev = as_zmk_position_state_changed(eh);
SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_bongo_state(widget, ev); }
return ZMK_EV_EVENT_BUBBLE;
}

ZMK_LISTENER(widget_bongo_cat, bongo_cat_listener)
ZMK_SUBSCRIPTION(widget_bongo_cat, zmk_position_state_changed);
222 changes: 222 additions & 0 deletions app/src/display/widgets/bongo_img.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
/*
* Copyright (c) 2022 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/

/*
* This is a pixel redraw of the redraw of the original Bongo Cat
* https://twitter.com/strayrogue/status/992994454058381312
* The redraw is distributed under CC BY-SA 4.0
* https://commons.wikimedia.org/wiki/File:Bongo_Cat_Redraw.png
*/

#include <lvgl.h>

#ifndef LV_ATTRIBUTE_MEM_ALIGN
#define LV_ATTRIBUTE_MEM_ALIGN
#endif

#ifndef LV_ATTRIBUTE_IMG_NONE
#define LV_ATTRIBUTE_IMG_NONE
#endif

const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_NONE uint8_t none_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/

0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x80, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x00, 0x70, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x00, 0x0e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x60, 0x00, 0x01, 0xc0, 0x00, 0x00,
0x00, 0x38, 0x80, 0x00, 0x00, 0x30, 0x30, 0x00,
0x00, 0x45, 0x00, 0x00, 0x00, 0x0c, 0xc8, 0x00,
0x00, 0x82, 0x00, 0x00, 0x00, 0x03, 0x08, 0x00,
0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
0x00, 0x80, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00,
0x00, 0x80, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00,
0xf0, 0x80, 0x00, 0x48, 0x00, 0x00, 0x10, 0x00,
0x0f, 0x80, 0x00, 0x31, 0x00, 0x70, 0x10, 0x00,
0x00, 0xf0, 0x00, 0x06, 0x30, 0x88, 0x20, 0x00,
0x00, 0x0f, 0x00, 0x00, 0x31, 0x04, 0x20, 0x00,
0x00, 0x00, 0xf0, 0x00, 0x01, 0x04, 0x20, 0x00,
0x00, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x0f, 0x01, 0x00, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

const lv_img_dsc_t none = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 60,
.header.h = 31,
.data_size = 256,
.data = none_map,
};

#ifndef LV_ATTRIBUTE_IMG_LEFT
#define LV_ATTRIBUTE_IMG_LEFT
#endif

const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_LEFT uint8_t left_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/

0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x80, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x00, 0x70, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x00, 0x0e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x60, 0x00, 0x01, 0xc0, 0x00, 0x00,
0x00, 0x38, 0x80, 0x00, 0x00, 0x30, 0x30, 0x00,
0x00, 0x45, 0x00, 0x00, 0x00, 0x0c, 0xc8, 0x00,
0x00, 0x82, 0x00, 0x00, 0x00, 0x03, 0x08, 0x00,
0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
0x00, 0x80, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00,
0x00, 0x80, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00,
0xf0, 0x80, 0x00, 0x48, 0x00, 0x00, 0x10, 0x00,
0x0f, 0x80, 0x00, 0x31, 0x00, 0x00, 0x10, 0x00,
0x00, 0xf0, 0x00, 0x06, 0x30, 0x00, 0x20, 0x00,
0x00, 0x0f, 0x00, 0x00, 0x30, 0x00, 0x20, 0x00,
0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x20, 0x00,
0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0xf0, 0x02, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x0f, 0x04, 0x00, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x40, 0x0f, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x40, 0x30, 0xf4, 0x00,
0x00, 0x00, 0x00, 0x00, 0x40, 0xc0, 0x0f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
};

const lv_img_dsc_t left = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 60,
.header.h = 31,
.data_size = 256,
.data = left_map,
};

#ifndef LV_ATTRIBUTE_IMG_RIGHT
#define LV_ATTRIBUTE_IMG_RIGHT
#endif

const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_RIGHT uint8_t right_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/

0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x80, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x00, 0x70, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x00, 0x0e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x60, 0x00, 0x01, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x80, 0x00, 0x00, 0x30, 0x30, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0xc8, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x08, 0x00,
0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
0x00, 0x10, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00,
0x00, 0x20, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00,
0xf0, 0x40, 0x00, 0x48, 0x00, 0x00, 0x10, 0x00,
0x0f, 0x40, 0x00, 0x31, 0x00, 0x70, 0x10, 0x00,
0x00, 0x80, 0x20, 0x06, 0x30, 0x88, 0x20, 0x00,
0x00, 0x80, 0x40, 0x00, 0x31, 0x04, 0x20, 0x00,
0x01, 0x00, 0xf0, 0x00, 0x01, 0x04, 0x20, 0x00,
0x01, 0x01, 0x0f, 0x00, 0x01, 0x00, 0x10, 0x00,
0x01, 0x02, 0x00, 0xf0, 0x01, 0x00, 0x10, 0x00,
0x00, 0x8c, 0x00, 0x0f, 0x01, 0x00, 0x08, 0x00,
0x00, 0x70, 0x00, 0x00, 0xf1, 0x00, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

const lv_img_dsc_t right = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 60,
.header.h = 31,
.data_size = 256,
.data = right_map,
};

#ifndef LV_ATTRIBUTE_IMG_BOTH
#define LV_ATTRIBUTE_IMG_BOTH
#endif

const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_BOTH uint8_t both_map[] = {
0xff, 0xff, 0xff, 0xff, /*Color of index 0*/
0x00, 0x00, 0x00, 0xff, /*Color of index 1*/

0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x80, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x00, 0x70, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x00, 0x0e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x60, 0x00, 0x01, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x80, 0x00, 0x00, 0x30, 0x30, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0xc8, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x08, 0x00,
0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
0x00, 0x10, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00,
0x00, 0x20, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00,
0xf0, 0x40, 0x00, 0x48, 0x00, 0x00, 0x10, 0x00,
0x0f, 0x40, 0x00, 0x31, 0x00, 0x00, 0x10, 0x00,
0x00, 0x80, 0x20, 0x06, 0x30, 0x00, 0x20, 0x00,
0x00, 0x80, 0x40, 0x00, 0x30, 0x00, 0x20, 0x00,
0x01, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x20, 0x00,
0x01, 0x01, 0x0f, 0x00, 0x00, 0x00, 0x10, 0x00,
0x01, 0x02, 0x00, 0xf0, 0x02, 0x00, 0x10, 0x00,
0x00, 0x8c, 0x00, 0x0f, 0x04, 0x00, 0x08, 0x00,
0x00, 0x70, 0x00, 0x00, 0xf8, 0x00, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x40, 0x0f, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x40, 0x30, 0xf4, 0x00,
0x00, 0x00, 0x00, 0x00, 0x40, 0xc0, 0x0f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
};

const lv_img_dsc_t both = {
.header.cf = LV_IMG_CF_INDEXED_1BIT,
.header.always_zero = 0,
.header.reserved = 0,
.header.w = 60,
.header.h = 31,
.data_size = 256,
.data = both_map,
};
1 change: 1 addition & 0 deletions app/src/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ enum zmk_usb_conn_state zmk_usb_get_conn_state() {
switch (usb_status) {
case USB_DC_SUSPEND:
case USB_DC_CONFIGURED:
case USB_DC_RESUME:
return ZMK_USB_CONN_HID;

case USB_DC_DISCONNECTED:
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/behaviors/hold-tap.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ We call this the 'hold-preferred' flavor of hold-taps. While this flavor may wor

- The 'hold-preferred' flavor triggers the hold behavior when the `tapping-term-ms` has expired or another key is pressed.
- The 'balanced' flavor will trigger the hold behavior when the `tapping-term-ms` has expired or another key is pressed and released.
- The 'tap-preferred' flavor triggers the hold behavior when the `tapping-term-ms` has expired. It triggers the tap behavior when another key is pressed.
- The 'tap-preferred' flavor triggers the hold behavior when the `tapping-term-ms` has expired. Pressing another key within `tapping-term-ms` does not affect the decision.
- The 'tap-unless-interrupted' flavor triggers a hold behavior only when another key is pressed before `tapping-term-ms` has expired. It triggers the tap behavior in all other situations.

When the hold-tap key is released and the hold behavior has not been triggered, the tap behavior will trigger.
Expand Down