From fe2693ee733f14a3b27c4e6e0c796e036e4aac07 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Wed, 26 Jan 2022 11:06:55 -0500 Subject: [PATCH] feat(behaviors): AdD `&sarcasm` BehAviOR. --- app/CMakeLists.txt | 1 + app/dts/behaviors.dtsi | 1 + app/dts/behaviors/sarcasm.dtsi | 18 +++ .../behaviors/zmk,behavior-sarcasm.yaml | 8 ++ app/src/behaviors/behavior_sarcasm.c | 136 ++++++++++++++++++ 5 files changed, 164 insertions(+) create mode 100644 app/dts/behaviors/sarcasm.dtsi create mode 100644 app/dts/bindings/behaviors/zmk,behavior-sarcasm.yaml create mode 100644 app/src/behaviors/behavior_sarcasm.c diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index af0b023c489..ae6d2a14582 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -57,6 +57,7 @@ if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL) target_sources(app PRIVATE src/combo.c) target_sources(app PRIVATE src/behaviors/behavior_tap_dance.c) target_sources(app PRIVATE src/behaviors/behavior_bottom.c) + target_sources(app PRIVATE src/behaviors/behavior_sarcasm.c) target_sources(app PRIVATE src/behavior_queue.c) target_sources(app PRIVATE src/conditional_layer.c) target_sources(app PRIVATE src/endpoints.c) diff --git a/app/dts/behaviors.dtsi b/app/dts/behaviors.dtsi index 386bc391231..b599338c456 100644 --- a/app/dts/behaviors.dtsi +++ b/app/dts/behaviors.dtsi @@ -20,3 +20,4 @@ #include #include #include +#include diff --git a/app/dts/behaviors/sarcasm.dtsi b/app/dts/behaviors/sarcasm.dtsi new file mode 100644 index 00000000000..dac9eb9e296 --- /dev/null +++ b/app/dts/behaviors/sarcasm.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2021 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include + +/ { + behaviors { + /omit-if-no-ref/ sarcasm: behavior_sarcasm { + compatible = "zmk,behavior-sarcasm"; + label = "SARCASM"; + #binding-cells = <0>; + }; + }; +}; + diff --git a/app/dts/bindings/behaviors/zmk,behavior-sarcasm.yaml b/app/dts/bindings/behaviors/zmk,behavior-sarcasm.yaml new file mode 100644 index 00000000000..de56014ce88 --- /dev/null +++ b/app/dts/bindings/behaviors/zmk,behavior-sarcasm.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2021 The ZMK Contributors +# SPDX-License-Identifier: MIT + +description: SaRcASm BeHaViOr + +compatible: "zmk,behavior-sarcasm" + +include: zero_param.yaml diff --git a/app/src/behaviors/behavior_sarcasm.c b/app/src/behaviors/behavior_sarcasm.c new file mode 100644 index 00000000000..582f9348a46 --- /dev/null +++ b/app/src/behaviors/behavior_sarcasm.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2021 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#define DT_DRV_COMPAT zmk_behavior_sarcasm + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) + +struct behavior_sarcasm_config { + uint8_t index; +}; + +struct behavior_sarcasm_data { + bool active; +}; + +static void activate_sarcasm(const struct device *dev) { + struct behavior_sarcasm_data *data = dev->data; + + data->active = true; +} + +static void deactivate_sarcasm(const struct device *dev) { + struct behavior_sarcasm_data *data = dev->data; + + data->active = false; +} + +static int on_sarcasm_binding_pressed(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + const struct device *dev = device_get_binding(binding->behavior_dev); + struct behavior_sarcasm_data *data = dev->data; + + if (data->active) { + deactivate_sarcasm(dev); + } else { + activate_sarcasm(dev); + } + + return ZMK_BEHAVIOR_OPAQUE; +} + +static int on_sarcasm_binding_released(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + return ZMK_BEHAVIOR_OPAQUE; +} + +static const struct behavior_driver_api behavior_sarcasm_driver_api = { + .binding_pressed = on_sarcasm_binding_pressed, + .binding_released = on_sarcasm_binding_released, +}; + +static int sarcasm_keycode_state_changed_listener(const zmk_event_t *eh); + +ZMK_LISTENER(behavior_sarcasm, sarcasm_keycode_state_changed_listener); +ZMK_SUBSCRIPTION(behavior_sarcasm, zmk_keycode_state_changed); + +static const struct device *devs[DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT)]; + +static bool sarcasm_is_alpha(uint8_t usage_id) { + return (usage_id >= HID_USAGE_KEY_KEYBOARD_A && usage_id <= HID_USAGE_KEY_KEYBOARD_Z); +} + +static void sarcasm_enhance_usage(const struct behavior_sarcasm_config *config, + struct zmk_keycode_state_changed *ev) { + if (ev->usage_page != HID_USAGE_KEY || !sarcasm_is_alpha(ev->keycode)) { + return; + } + + LOG_DBG("Enhancing usage 0x%02X with sarcasm", ev->keycode); + ev->implicit_modifiers |= MOD_LSFT; +} + +static int sarcasm_keycode_state_changed_listener(const zmk_event_t *eh) { + struct zmk_keycode_state_changed *ev = as_zmk_keycode_state_changed(eh); + if (ev == NULL || !ev->state) { + return ZMK_EV_EVENT_BUBBLE; + } + + for (int i = 0; i < DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT); i++) { + const struct device *dev = devs[i]; + if (dev == NULL) { + continue; + } + + struct behavior_sarcasm_data *data = dev->data; + if (!data->active) { + continue; + } + + const struct behavior_sarcasm_config *config = dev->config; + + if (zmk_hid_get_explicit_mods() == 0 && k_uptime_get() % 2 == 1) { + sarcasm_enhance_usage(config, ev); + } + } + + return ZMK_EV_EVENT_BUBBLE; +} + +static int behavior_sarcasm_init(const struct device *dev) { + const struct behavior_sarcasm_config *config = dev->config; + devs[config->index] = dev; + return 0; +} + +#define KP_INST(n) \ + static struct behavior_sarcasm_data behavior_sarcasm_data_##n = {.active = false}; \ + static struct behavior_sarcasm_config behavior_sarcasm_config_##n = { \ + .index = n, \ + }; \ + DEVICE_DT_INST_DEFINE(n, behavior_sarcasm_init, device_pm_control_nop, \ + &behavior_sarcasm_data_##n, &behavior_sarcasm_config_##n, APPLICATION, \ + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_sarcasm_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(KP_INST) + +#endif