diff --git a/.github/workflows/clang-format-lint.yml b/.github/workflows/clang-format-lint.yml index 8bd42753..b6d515c1 100644 --- a/.github/workflows/clang-format-lint.yml +++ b/.github/workflows/clang-format-lint.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: DoozyX/clang-format-lint-action@v0.9 + - uses: DoozyX/clang-format-lint-action@v0.11 with: source: "./app" extensions: "h,c" diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index b217a1a1..e283487f 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -28,6 +28,7 @@ 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) @@ -36,6 +37,7 @@ 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/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 app PRIVATE src/events/usb_conn_state_changed.c) @@ -45,6 +47,7 @@ if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) target_sources(app PRIVATE src/behaviors/behavior_hold_tap.c) target_sources(app PRIVATE src/behaviors/behavior_sticky_key.c) target_sources(app PRIVATE src/behaviors/behavior_momentary_layer.c) + target_sources(app PRIVATE src/behaviors/behavior_mod_morph.c) target_sources(app PRIVATE src/behaviors/behavior_outputs.c) target_sources(app PRIVATE src/behaviors/behavior_toggle_layer.c) target_sources(app PRIVATE src/behaviors/behavior_to_layer.c) diff --git a/app/Kconfig b/app/Kconfig index 0aa291d6..aa6143ce 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -41,7 +41,7 @@ config USB_NUMOF_EP_WRITE_RETRIES #ZMK_USB endif -config ZMK_BLE +menuconfig ZMK_BLE bool "BLE (HID over GATT)" select BT select BT_SMP @@ -58,6 +58,22 @@ if ZMK_BLE config SYSTEM_WORKQUEUE_STACK_SIZE default 2048 +config ZMK_BLE_THREAD_STACK_SIZE + int "BLE notify thread stack size" + default 512 + +config ZMK_BLE_THREAD_PRIORITY + int "BLE notify thread priority" + default 5 + +config ZMK_BLE_KEYBOARD_REPORT_QUEUE_SIZE + int "Max number of keyboard HID reports to queue for sending over BLE" + default 20 + +config ZMK_BLE_CONSUMER_REPORT_QUEUE_SIZE + int "Max number of consumer HID reports to queue for sending over BLE" + default 5 + config ZMK_BLE_CLEAR_BONDS_ON_START bool "Configuration that clears all bond information from the keyboard on startup." default n @@ -86,7 +102,7 @@ config ZMK_SPLIT if ZMK_SPLIT -config ZMK_SPLIT_BLE +menuconfig ZMK_SPLIT_BLE bool "Split keyboard support via BLE transport" depends on ZMK_BLE default y @@ -94,13 +110,33 @@ config ZMK_SPLIT_BLE if ZMK_SPLIT_BLE -config ZMK_SPLIT_BLE_ROLE_CENTRAL +menuconfig ZMK_SPLIT_BLE_ROLE_CENTRAL bool "Central" select BT_CENTRAL select BT_GATT_CLIENT +if ZMK_SPLIT_BLE_ROLE_CENTRAL + +config ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE + int "Max number of key position state events to queue when received from peripherals" + default 5 + +endif + if !ZMK_SPLIT_BLE_ROLE_CENTRAL +config ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE + int "BLE split peripheral notify thread stack size" + default 512 + +config ZMK_SPLIT_BLE_PERIPHERAL_PRIORITY + int "BLE split peripheral notify thread priority" + default 5 + +config ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE + int "Max number of key position state events to queue to send to the central" + default 10 + config ZMK_USB default n @@ -301,11 +337,9 @@ config ZMK_KSCAN_EVENT_QUEUE_SIZE config ZMK_KSCAN_MOCK_DRIVER bool "Enable mock kscan driver to simulate key presses" - default n config ZMK_KSCAN_COMPOSITE_DRIVER bool "Enable composite kscan driver to combine kscan devices" - default n #KSCAN Settings endmenu @@ -381,6 +415,10 @@ config REBOOT config USB default y if HAS_HW_NRF_USBD +config ZMK_WPM + bool "Calculate WPM" + default n + module = ZMK module-str = zmk source "subsys/logging/Kconfig.template.log_config" diff --git a/app/boards/shields/microdox/microdox.dtsi b/app/boards/shields/microdox/microdox.dtsi index ee2114d7..a692ce4d 100644 --- a/app/boards/shields/microdox/microdox.dtsi +++ b/app/boards/shields/microdox/microdox.dtsi @@ -58,8 +58,6 @@ RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) page-offset = <0>; display-offset = <0>; multiplex-ratio = <31>; - segment-remap; - com-invdir; com-sequential; prechargep = <0x22>; }; diff --git a/app/boards/shields/microdox/microdox_right.overlay b/app/boards/shields/microdox/microdox_right.overlay index c5622b25..0801c7e1 100644 --- a/app/boards/shields/microdox/microdox_right.overlay +++ b/app/boards/shields/microdox/microdox_right.overlay @@ -10,6 +10,11 @@ col-offset = <5>; }; +&oled { + segment-remap; + com-invdir; +}; + &kscan0 { col-gpios = <&pro_micro_d 15 GPIO_ACTIVE_HIGH> diff --git a/app/boards/shields/nibble/nibble.keymap b/app/boards/shields/nibble/nibble.keymap index 0bb625ec..bc274cd8 100644 --- a/app/boards/shields/nibble/nibble.keymap +++ b/app/boards/shields/nibble/nibble.keymap @@ -20,7 +20,7 @@ &kp ESC &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS &kp EQUAL &kp BSPC &kp HOME &kp C_VOL_UP &kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp LBKT &kp RBKT &kp BSLH &kp DEL &kp C_VOL_DN &kp CLCK &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT &kp RET &kp PG_UP -&trans &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT &kp UP &kp PG_DN +&trans &kp LSHFT &trans &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RSHFT &kp UP &kp PG_DN &trans &kp LCTRL &kp LGUI &kp LALT &kp SPACE &mo FUNC &kp RALT &kp RCTRL &kp LEFT &kp DOWN &kp RIGHT >; }; @@ -29,7 +29,7 @@ &kp TILDE &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &trans &kp END &bt BT_CLR &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &bootloader &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans -&bt BT_PRV &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans +&bt BT_PRV &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &bt BT_NXT &trans &trans &trans &trans &trans &trans &trans &kp C_PREV &kp C_PP &kp C_NEXT >; }; diff --git a/app/boards/shields/nibble/nibble.overlay b/app/boards/shields/nibble/nibble.overlay index fd1b2f61..3b672752 100644 --- a/app/boards/shields/nibble/nibble.overlay +++ b/app/boards/shields/nibble/nibble.overlay @@ -21,7 +21,7 @@ , <&pro_micro_d 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> , <&pro_micro_d 16 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> , <&pro_micro_d 10 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> - , <&pro_micro_d 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&pro_micro_d 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> ; output-gpios = <&pro_micro_a 3 GPIO_ACTIVE_HIGH> @@ -39,11 +39,11 @@ //TODO: Add a keymap graphic here map = < - RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10) RC(0,11) RC(0,12) RC(0,13) RC(0,14) RC(0,15) -RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10) RC(1,11) RC(1,12) RC(1,13) RC(1,14) RC(1,15) -RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11) RC(2,12) RC(2,14) RC(2,15) -RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11) RC(3,12) RC(3,14) RC(3,15) -RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,6) RC(4,9) RC(4,10) RC(4,11) RC(4,12) RC(4,14) RC(4,15) + RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10) RC(0,11) RC(0,12) RC(0,13) RC(0,14) RC(0,15) +RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10) RC(1,11) RC(1,12) RC(1,13) RC(1,14) RC(1,15) +RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11) RC(2,12) RC(2,14) RC(2,15) +RC(3,0) RC(3,1) RC(0,0) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11) RC(3,12) RC(3,14) RC(3,15) +RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,6) RC(4,9) RC(4,10) RC(4,11) RC(4,12) RC(4,14) RC(4,15) >; }; }; diff --git a/app/boards/shields/splitreus62/Kconfig.defconfig b/app/boards/shields/splitreus62/Kconfig.defconfig index fdaa3779..41c1218a 100644 --- a/app/boards/shields/splitreus62/Kconfig.defconfig +++ b/app/boards/shields/splitreus62/Kconfig.defconfig @@ -16,7 +16,7 @@ endif if SHIELD_SPLITREUS62_RIGHT config ZMK_KEYBOARD_NAME - default "Splitreus62 Right" + default "Splitreus62 Rt" endif diff --git a/app/drivers/kscan/Kconfig b/app/drivers/kscan/Kconfig index 654e0ee4..dc3580d5 100644 --- a/app/drivers/kscan/Kconfig +++ b/app/drivers/kscan/Kconfig @@ -10,11 +10,9 @@ if ZMK_KSCAN_GPIO_DRIVER config ZMK_KSCAN_MATRIX_POLLING bool "Poll for key event triggers instead of using interrupts on matrix boards." - default n config ZMK_KSCAN_DIRECT_POLLING bool "Poll for key event triggers instead of using interrupts on direct wired boards." - default n endif diff --git a/app/drivers/kscan/kscan_gpio_matrix.c b/app/drivers/kscan/kscan_gpio_matrix.c index 6697cf69..9af3171a 100644 --- a/app/drivers/kscan/kscan_gpio_matrix.c +++ b/app/drivers/kscan/kscan_gpio_matrix.c @@ -51,6 +51,11 @@ static int kscan_gpio_config_interrupts(const struct device **devices, } #endif +#define COND_POLLING(code) COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (code), ()) +#define COND_INTERRUPTS(code) COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), (code)) +#define COND_POLL_OR_INTERRUPTS(pollcode, intcode) \ + COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, pollcode, intcode) + #define INST_MATRIX_ROWS(n) DT_INST_PROP_LEN(n, row_gpios) #define INST_MATRIX_COLS(n) DT_INST_PROP_LEN(n, col_gpios) #define INST_OUTPUT_LEN(n) \ @@ -61,19 +66,21 @@ static int kscan_gpio_config_interrupts(const struct device **devices, (INST_MATRIX_ROWS(n))) #define GPIO_INST_INIT(n) \ - struct kscan_gpio_irq_callback_##n { \ - struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) * work; \ - struct gpio_callback callback; \ - const struct device *dev; \ - }; \ - static struct kscan_gpio_irq_callback_##n irq_callbacks_##n[INST_INPUT_LEN(n)]; \ + COND_INTERRUPTS( \ + struct kscan_gpio_irq_callback_##n { \ + struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) * \ + work; \ + struct gpio_callback callback; \ + const struct device *dev; \ + }; \ + static struct kscan_gpio_irq_callback_##n irq_callbacks_##n[INST_INPUT_LEN(n)];) \ struct kscan_gpio_config_##n { \ struct kscan_gpio_item_config rows[INST_MATRIX_ROWS(n)]; \ struct kscan_gpio_item_config cols[INST_MATRIX_COLS(n)]; \ }; \ struct kscan_gpio_data_##n { \ kscan_callback_t callback; \ - COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (struct k_timer poll_timer;), ()) \ + COND_POLLING(struct k_timer poll_timer;) \ struct COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work), (k_delayed_work)) work; \ bool matrix_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \ const struct device *rows[INST_MATRIX_ROWS(n)]; \ @@ -102,17 +109,16 @@ static int kscan_gpio_config_interrupts(const struct device **devices, return ( \ COND_CODE_0(DT_ENUM_IDX(DT_DRV_INST(n), diode_direction), (cfg->rows), (cfg->cols))); \ } \ - COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \ - ( \ - static int kscan_gpio_enable_interrupts_##n(const struct device *dev) { \ - return kscan_gpio_config_interrupts( \ - kscan_gpio_input_devices_##n(dev), kscan_gpio_input_configs_##n(dev), \ - INST_INPUT_LEN(n), GPIO_INT_LEVEL_ACTIVE); \ - } static int kscan_gpio_disable_interrupts_##n(const struct device *dev) { \ - return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ - kscan_gpio_input_configs_##n(dev), \ - INST_INPUT_LEN(n), GPIO_INT_DISABLE); \ - })) \ + COND_INTERRUPTS( \ + static int kscan_gpio_enable_interrupts_##n(const struct device *dev) { \ + return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ + kscan_gpio_input_configs_##n(dev), \ + INST_INPUT_LEN(n), GPIO_INT_LEVEL_ACTIVE); \ + } static int kscan_gpio_disable_interrupts_##n(const struct device *dev) { \ + return kscan_gpio_config_interrupts(kscan_gpio_input_devices_##n(dev), \ + kscan_gpio_input_configs_##n(dev), \ + INST_INPUT_LEN(n), GPIO_INT_DISABLE); \ + }) \ static void kscan_gpio_set_output_state_##n(const struct device *dev, int value) { \ int err; \ for (int i = 0; i < INST_OUTPUT_LEN(n); i++) { \ @@ -132,17 +138,22 @@ static int kscan_gpio_config_interrupts(const struct device **devices, (output_index))] = value; \ } \ static int kscan_gpio_read_##n(const struct device *dev) { \ - bool submit_follow_up_read = false; \ + COND_INTERRUPTS(bool submit_follow_up_read = false;) \ struct kscan_gpio_data_##n *data = dev->data; \ static bool read_state[INST_MATRIX_ROWS(n)][INST_MATRIX_COLS(n)]; \ + int err; \ /* Disable our interrupts temporarily while we scan, to avoid */ \ /* re-entry while we iterate columns and set them active one by one */ \ /* to get pressed state for each matrix cell. */ \ - kscan_gpio_set_output_state_##n(dev, 0); \ + COND_INTERRUPTS(kscan_gpio_set_output_state_##n(dev, 0);) \ for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \ const struct device *out_dev = kscan_gpio_output_devices_##n(dev)[o]; \ const struct kscan_gpio_item_config *out_cfg = &kscan_gpio_output_configs_##n(dev)[o]; \ - gpio_pin_set(out_dev, out_cfg->pin, 1); \ + err = gpio_pin_set(out_dev, out_cfg->pin, 1); \ + if (err) { \ + LOG_ERR("Failed to set output active (err %d)", err); \ + return err; \ + } \ for (int i = 0; i < INST_INPUT_LEN(n); i++) { \ const struct device *in_dev = kscan_gpio_input_devices_##n(dev)[i]; \ const struct kscan_gpio_item_config *in_cfg = \ @@ -150,16 +161,20 @@ static int kscan_gpio_config_interrupts(const struct device **devices, kscan_gpio_set_matrix_state_##n(read_state, i, o, \ gpio_pin_get(in_dev, in_cfg->pin) > 0); \ } \ - gpio_pin_set(out_dev, out_cfg->pin, 0); \ + err = gpio_pin_set(out_dev, out_cfg->pin, 0); \ + if (err) { \ + LOG_ERR("Failed to set output inactive (err %d)", err); \ + return err; \ + } \ } \ /* Set all our outputs as active again. */ \ - kscan_gpio_set_output_state_##n(dev, 1); \ + COND_INTERRUPTS(kscan_gpio_set_output_state_##n(dev, 1);) \ for (int r = 0; r < INST_MATRIX_ROWS(n); r++) { \ for (int c = 0; c < INST_MATRIX_COLS(n); c++) { \ bool pressed = read_state[r][c]; \ /* Follow up reads needed because further interrupts won't fire on already tripped \ * input GPIO pins */ \ - submit_follow_up_read = (submit_follow_up_read || pressed); \ + COND_INTERRUPTS(submit_follow_up_read = (submit_follow_up_read || pressed);) \ if (pressed != data->matrix_state[r][c]) { \ LOG_DBG("Sending event at %d,%d state %s", r, c, (pressed ? "on" : "off")); \ data->matrix_state[r][c] = pressed; \ @@ -167,33 +182,31 @@ static int kscan_gpio_config_interrupts(const struct device **devices, } \ } \ } \ - if (submit_follow_up_read) { \ - COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(&data->work); }), ({ \ - k_delayed_work_cancel(&data->work); \ - k_delayed_work_submit(&data->work, K_MSEC(5)); \ - })) \ - } else { \ - COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \ - (kscan_gpio_enable_interrupts_##n(dev);)) \ - } \ + COND_INTERRUPTS( \ + if (submit_follow_up_read) { \ + COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(&data->work); }), \ + ({ \ + k_delayed_work_cancel(&data->work); \ + k_delayed_work_submit(&data->work, K_MSEC(5)); \ + })) \ + } else { kscan_gpio_enable_interrupts_##n(dev); }) \ return 0; \ } \ static void kscan_gpio_work_handler_##n(struct k_work *work) { \ struct kscan_gpio_data_##n *data = CONTAINER_OF(work, struct kscan_gpio_data_##n, work); \ kscan_gpio_read_##n(data->dev); \ } \ - static void kscan_gpio_irq_callback_handler_##n( \ + COND_INTERRUPTS(static void kscan_gpio_irq_callback_handler_##n( \ const struct device *dev, struct gpio_callback *cb, gpio_port_pins_t pin) { \ struct kscan_gpio_irq_callback_##n *data = \ CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback); \ - COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \ - (kscan_gpio_disable_interrupts_##n(data->dev);)) \ + kscan_gpio_disable_interrupts_##n(data->dev); \ COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(data->work); }), ({ \ k_delayed_work_cancel(data->work); \ k_delayed_work_submit(data->work, \ K_MSEC(DT_INST_PROP(n, debounce_period))); \ })) \ - } \ + }) \ \ static struct kscan_gpio_data_##n kscan_gpio_data_##n = { \ .rows = {[INST_MATRIX_ROWS(n) - 1] = NULL}, .cols = {[INST_MATRIX_COLS(n) - 1] = NULL}}; \ @@ -207,25 +220,22 @@ static int kscan_gpio_config_interrupts(const struct device **devices, return 0; \ }; \ static int kscan_gpio_enable_##n(const struct device *dev) { \ - COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ - (struct kscan_gpio_data_##n *data = dev->data; \ - k_timer_start(&data->poll_timer, K_MSEC(10), K_MSEC(10)); return 0;), \ - (int err = kscan_gpio_enable_interrupts_##n(dev); \ - if (err) { return err; } return kscan_gpio_read_##n(dev);)) \ + COND_POLL_OR_INTERRUPTS((struct kscan_gpio_data_##n *data = dev->data; \ + k_timer_start(&data->poll_timer, K_MSEC(10), K_MSEC(10)); \ + return 0;), \ + (int err = kscan_gpio_enable_interrupts_##n(dev); \ + if (err) { return err; } return kscan_gpio_read_##n(dev);)) \ }; \ static int kscan_gpio_disable_##n(const struct device *dev) { \ - COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ - (struct kscan_gpio_data_##n *data = dev->data; \ - k_timer_stop(&data->poll_timer); return 0;), \ - (return kscan_gpio_disable_interrupts_##n(dev);)) \ + COND_POLL_OR_INTERRUPTS((struct kscan_gpio_data_##n *data = dev->data; \ + k_timer_stop(&data->poll_timer); return 0;), \ + (return kscan_gpio_disable_interrupts_##n(dev);)) \ }; \ - COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ - (static void kscan_gpio_timer_handler(struct k_timer *timer) { \ - struct kscan_gpio_data_##n *data = \ - CONTAINER_OF(timer, struct kscan_gpio_data_##n, poll_timer); \ - k_work_submit(&data->work.work); \ - }), \ - ()) \ + COND_POLLING(static void kscan_gpio_timer_handler_##n(struct k_timer *timer) { \ + struct kscan_gpio_data_##n *data = \ + CONTAINER_OF(timer, struct kscan_gpio_data_##n, poll_timer); \ + k_work_submit(&data->work.work); \ + }) \ static int kscan_gpio_init_##n(const struct device *dev) { \ struct kscan_gpio_data_##n *data = dev->data; \ int err; \ @@ -244,15 +254,15 @@ static int kscan_gpio_config_interrupts(const struct device **devices, } else { \ LOG_DBG("Configured pin %d on %s for input", in_cfg->pin, in_cfg->label); \ } \ - irq_callbacks_##n[i].work = &data->work; \ - irq_callbacks_##n[i].dev = dev; \ - gpio_init_callback(&irq_callbacks_##n[i].callback, \ - kscan_gpio_irq_callback_handler_##n, BIT(in_cfg->pin)); \ - err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \ - if (err) { \ - LOG_ERR("Error adding the callback to the column device"); \ - return err; \ - } \ + COND_INTERRUPTS( \ + irq_callbacks_##n[i].work = &data->work; irq_callbacks_##n[i].dev = dev; \ + gpio_init_callback(&irq_callbacks_##n[i].callback, \ + kscan_gpio_irq_callback_handler_##n, BIT(in_cfg->pin)); \ + err = gpio_add_callback(input_devices[i], &irq_callbacks_##n[i].callback); \ + if (err) { \ + LOG_ERR("Error adding the callback to the input device"); \ + return err; \ + }) \ } \ const struct device **output_devices = kscan_gpio_output_devices_##n(dev); \ for (int o = 0; o < INST_OUTPUT_LEN(n); o++) { \ @@ -262,8 +272,8 @@ static int kscan_gpio_config_interrupts(const struct device **devices, LOG_ERR("Unable to find output GPIO device"); \ return -EINVAL; \ } \ - err = gpio_pin_configure(output_devices[o], out_cfg->pin, \ - GPIO_OUTPUT_ACTIVE | out_cfg->flags); \ + err = \ + gpio_pin_configure(output_devices[o], out_cfg->pin, GPIO_OUTPUT | out_cfg->flags); \ if (err) { \ LOG_ERR("Unable to configure pin %d on %s for output", out_cfg->pin, \ out_cfg->label); \ @@ -271,10 +281,12 @@ static int kscan_gpio_config_interrupts(const struct device **devices, } \ } \ data->dev = dev; \ - COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, \ - (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler, NULL);), ()) \ (COND_CODE_0(DT_INST_PROP(n, debounce_period), (k_work_init), (k_delayed_work_init)))( \ &data->work, kscan_gpio_work_handler_##n); \ + COND_POLL_OR_INTERRUPTS( \ + (k_timer_init(&data->poll_timer, kscan_gpio_timer_handler_##n, NULL); \ + kscan_gpio_set_output_state_##n(dev, 0);), \ + (kscan_gpio_set_output_state_##n(dev, 1);)) \ return 0; \ } \ static const struct kscan_driver_api gpio_driver_api_##n = { \ diff --git a/app/dts/behaviors.dtsi b/app/dts/behaviors.dtsi index daa073f1..4333ceea 100644 --- a/app/dts/behaviors.dtsi +++ b/app/dts/behaviors.dtsi @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include diff --git a/app/dts/behaviors/gresc.dtsi b/app/dts/behaviors/gresc.dtsi new file mode 100644 index 00000000..29593880 --- /dev/null +++ b/app/dts/behaviors/gresc.dtsi @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include + +/ { + behaviors { + /omit-if-no-ref/ gresc: grave_escape { + compatible = "zmk,behavior-mod-morph"; + label = "GRAVE_ESCAPE"; + #binding-cells = <0>; + bindings = <&kp ESC>, <&kp GRAVE>; + mods = <(MOD_LGUI|MOD_LSFT|MOD_RGUI|MOD_RSFT)>; + }; + }; +}; diff --git a/app/dts/behaviors/sticky_key.dtsi b/app/dts/behaviors/sticky_key.dtsi index 1e66a1ed..f1c1cdd5 100644 --- a/app/dts/behaviors/sticky_key.dtsi +++ b/app/dts/behaviors/sticky_key.dtsi @@ -19,6 +19,7 @@ #binding-cells = <1>; release-after-ms = <1000>; bindings = <&mo>; + quick-release; }; }; diff --git a/app/dts/bindings/behaviors/one_param.yaml b/app/dts/bindings/behaviors/one_param.yaml index 8eabba1b..faa01a0d 100644 --- a/app/dts/bindings/behaviors/one_param.yaml +++ b/app/dts/bindings/behaviors/one_param.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Pete Johanson +# Copyright (c) 2020 The ZMK Contributors # SPDX-License-Identifier: MIT properties: diff --git a/app/dts/bindings/behaviors/two_param.yaml b/app/dts/bindings/behaviors/two_param.yaml index c508c401..d4cdfaa0 100644 --- a/app/dts/bindings/behaviors/two_param.yaml +++ b/app/dts/bindings/behaviors/two_param.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Pete Johanson +# Copyright (c) 2020 The ZMK Contributors # SPDX-License-Identifier: MIT properties: diff --git a/app/dts/bindings/behaviors/zero_param.yaml b/app/dts/bindings/behaviors/zero_param.yaml index 6defbb20..075270d6 100644 --- a/app/dts/bindings/behaviors/zero_param.yaml +++ b/app/dts/bindings/behaviors/zero_param.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Pete Johanson +# Copyright (c) 2020 The ZMK Contributors # SPDX-License-Identifier: MIT properties: diff --git a/app/dts/bindings/behaviors/zmk,behavior-bluetooth.yaml b/app/dts/bindings/behaviors/zmk,behavior-bluetooth.yaml index 9ce56734..b357fbf6 100644 --- a/app/dts/bindings/behaviors/zmk,behavior-bluetooth.yaml +++ b/app/dts/bindings/behaviors/zmk,behavior-bluetooth.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Peter Johanson +# Copyright (c) 2020 The ZMK Contributors # SPDX-License-Identifier: MIT description: Bluetooth Behavior diff --git a/app/dts/bindings/behaviors/zmk,behavior-key-press.yaml b/app/dts/bindings/behaviors/zmk,behavior-key-press.yaml index 37f1886f..5a40a8db 100644 --- a/app/dts/bindings/behaviors/zmk,behavior-key-press.yaml +++ b/app/dts/bindings/behaviors/zmk,behavior-key-press.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Pete Johanson +# Copyright (c) 2020 The ZMK Contributors # SPDX-License-Identifier: MIT description: Key press/release behavior diff --git a/app/dts/bindings/behaviors/zmk,behavior-mod-morph.yaml b/app/dts/bindings/behaviors/zmk,behavior-mod-morph.yaml new file mode 100644 index 00000000..66b452a5 --- /dev/null +++ b/app/dts/bindings/behaviors/zmk,behavior-mod-morph.yaml @@ -0,0 +1,16 @@ +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT + +description: Keyboard Reset Behavior + +compatible: "zmk,behavior-mod-morph" + +include: zero_param.yaml + +properties: + bindings: + type: phandle-array + required: true + mods: + type: int + required: true diff --git a/app/dts/bindings/behaviors/zmk,behavior-momentary-layer.yaml b/app/dts/bindings/behaviors/zmk,behavior-momentary-layer.yaml index b8f26af6..5423e29c 100644 --- a/app/dts/bindings/behaviors/zmk,behavior-momentary-layer.yaml +++ b/app/dts/bindings/behaviors/zmk,behavior-momentary-layer.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Pete Johanson +# Copyright (c) 2020 The ZMK Contributors # SPDX-License-Identifier: MIT description: Momentary layer on press/release behavior diff --git a/app/dts/bindings/behaviors/zmk,behavior-none.yaml b/app/dts/bindings/behaviors/zmk,behavior-none.yaml index 4d1ad406..42d22587 100644 --- a/app/dts/bindings/behaviors/zmk,behavior-none.yaml +++ b/app/dts/bindings/behaviors/zmk,behavior-none.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Pete Johanson +# Copyright (c) 2020 The ZMK Contributors # SPDX-License-Identifier: MIT description: None Binding Behavior diff --git a/app/dts/bindings/behaviors/zmk,behavior-reset.yaml b/app/dts/bindings/behaviors/zmk,behavior-reset.yaml index 6133411e..9eb7aa6a 100644 --- a/app/dts/bindings/behaviors/zmk,behavior-reset.yaml +++ b/app/dts/bindings/behaviors/zmk,behavior-reset.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Pete Johanson +# Copyright (c) 2020 The ZMK Contributors # SPDX-License-Identifier: MIT description: Keyboard Reset Behavior diff --git a/app/dts/bindings/behaviors/zmk,behavior-sticky-key.yaml b/app/dts/bindings/behaviors/zmk,behavior-sticky-key.yaml index df9c423c..1c2ab7f3 100644 --- a/app/dts/bindings/behaviors/zmk,behavior-sticky-key.yaml +++ b/app/dts/bindings/behaviors/zmk,behavior-sticky-key.yaml @@ -13,3 +13,5 @@ properties: required: true release-after-ms: type: int + quick-release: + type: boolean diff --git a/app/dts/bindings/behaviors/zmk,behavior-transparent.yaml b/app/dts/bindings/behaviors/zmk,behavior-transparent.yaml index 19c25ffa..97295fcc 100644 --- a/app/dts/bindings/behaviors/zmk,behavior-transparent.yaml +++ b/app/dts/bindings/behaviors/zmk,behavior-transparent.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Pete Johanson +# Copyright (c) 2020 The ZMK Contributors # SPDX-License-Identifier: MIT description: Transparent Binding Behavior diff --git a/app/dts/common/arduino_uno_pro_micro_map.dtsi b/app/dts/common/arduino_uno_pro_micro_map.dtsi index fe59a866..3f3d64f0 100644 --- a/app/dts/common/arduino_uno_pro_micro_map.dtsi +++ b/app/dts/common/arduino_uno_pro_micro_map.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Pete Johanson + * Copyright (c) 2020 The ZMK Contributors * * SPDX-License-Identifier: MIT */ diff --git a/app/include/zmk/display/widgets/wpm_status.h b/app/include/zmk/display/widgets/wpm_status.h new file mode 100644 index 00000000..0592299e --- /dev/null +++ b/app/include/zmk/display/widgets/wpm_status.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#pragma once + +#include +#include + +struct zmk_widget_wpm_status { + sys_snode_t node; + lv_obj_t *obj; +}; + +int zmk_widget_wpm_status_init(struct zmk_widget_wpm_status *widget, lv_obj_t *parent); +lv_obj_t *zmk_widget_wpm_status_obj(struct zmk_widget_wpm_status *widget); \ No newline at end of file diff --git a/app/include/zmk/event_manager.h b/app/include/zmk/event_manager.h index e5b6ed53..5acb26eb 100644 --- a/app/include/zmk/event_manager.h +++ b/app/include/zmk/event_manager.h @@ -14,16 +14,16 @@ struct zmk_event_type { const char *name; }; -struct zmk_event_header { +typedef struct { const struct zmk_event_type *event; uint8_t last_listener_index; -}; +} zmk_event_t; #define ZMK_EV_EVENT_BUBBLE 0 #define ZMK_EV_EVENT_HANDLED 1 #define ZMK_EV_EVENT_CAPTURED 2 -typedef int (*zmk_listener_callback_t)(const struct zmk_event_header *eh); +typedef int (*zmk_listener_callback_t)(const zmk_event_t *eh); struct zmk_listener { zmk_listener_callback_t callback; }; @@ -34,25 +34,28 @@ struct zmk_event_subscription { }; #define ZMK_EVENT_DECLARE(event_type) \ - struct event_type *new_##event_type(); \ - bool is_##event_type(const struct zmk_event_header *eh); \ - struct event_type *cast_##event_type(const struct zmk_event_header *eh); \ + struct event_type##_event { \ + zmk_event_t header; \ + struct event_type data; \ + }; \ + struct event_type##_event *new_##event_type(struct event_type); \ + struct event_type *as_##event_type(const zmk_event_t *eh); \ extern const struct zmk_event_type zmk_event_##event_type; #define ZMK_EVENT_IMPL(event_type) \ const struct zmk_event_type zmk_event_##event_type = {.name = STRINGIFY(event_type)}; \ const struct zmk_event_type *zmk_event_ref_##event_type __used \ __attribute__((__section__(".event_type"))) = &zmk_event_##event_type; \ - struct event_type *new_##event_type() { \ - struct event_type *ev = (struct event_type *)k_malloc(sizeof(struct event_type)); \ + struct event_type##_event *new_##event_type(struct event_type data) { \ + struct event_type##_event *ev = \ + (struct event_type##_event *)k_malloc(sizeof(struct event_type##_event)); \ ev->header.event = &zmk_event_##event_type; \ + ev->data = data; \ return ev; \ }; \ - bool is_##event_type(const struct zmk_event_header *eh) { \ - return eh->event == &zmk_event_##event_type; \ - }; \ - struct event_type *cast_##event_type(const struct zmk_event_header *eh) { \ - return (struct event_type *)eh; \ + struct event_type *as_##event_type(const zmk_event_t *eh) { \ + return (eh->event == &zmk_event_##event_type) ? &((struct event_type##_event *)eh)->data \ + : NULL; \ }; #define ZMK_LISTENER(mod, cb) const struct zmk_listener zmk_listener_##mod = {.callback = cb}; @@ -65,18 +68,19 @@ struct zmk_event_subscription { .listener = &zmk_listener_##mod, \ }; -#define ZMK_EVENT_RAISE(ev) zmk_event_manager_raise((struct zmk_event_header *)ev); +#define ZMK_EVENT_RAISE(ev) zmk_event_manager_raise((zmk_event_t *)ev); #define ZMK_EVENT_RAISE_AFTER(ev, mod) \ - zmk_event_manager_raise_after((struct zmk_event_header *)ev, &zmk_listener_##mod); + zmk_event_manager_raise_after((zmk_event_t *)ev, &zmk_listener_##mod); #define ZMK_EVENT_RAISE_AT(ev, mod) \ - zmk_event_manager_raise_at((struct zmk_event_header *)ev, &zmk_listener_##mod); + zmk_event_manager_raise_at((zmk_event_t *)ev, &zmk_listener_##mod); -#define ZMK_EVENT_RELEASE(ev) zmk_event_manager_release((struct zmk_event_header *)ev); +#define ZMK_EVENT_RELEASE(ev) zmk_event_manager_release((zmk_event_t *)ev); -int zmk_event_manager_raise(struct zmk_event_header *event); -int zmk_event_manager_raise_after(struct zmk_event_header *event, - const struct zmk_listener *listener); -int zmk_event_manager_raise_at(struct zmk_event_header *event, const struct zmk_listener *listener); -int zmk_event_manager_release(struct zmk_event_header *event); +#define ZMK_EVENT_FREE(ev) k_free((void *)ev); + +int zmk_event_manager_raise(zmk_event_t *event); +int zmk_event_manager_raise_after(zmk_event_t *event, const struct zmk_listener *listener); +int zmk_event_manager_raise_at(zmk_event_t *event, const struct zmk_listener *listener); +int zmk_event_manager_release(zmk_event_t *event); \ No newline at end of file diff --git a/app/include/zmk/events/activity_state_changed.h b/app/include/zmk/events/activity_state_changed.h index 511fbad6..998fa2d4 100644 --- a/app/include/zmk/events/activity_state_changed.h +++ b/app/include/zmk/events/activity_state_changed.h @@ -10,17 +10,8 @@ #include #include -struct activity_state_changed { - struct zmk_event_header header; +struct zmk_activity_state_changed { enum zmk_activity_state state; }; -ZMK_EVENT_DECLARE(activity_state_changed); - -static inline struct activity_state_changed * -create_activity_state_changed(enum zmk_activity_state state) { - struct activity_state_changed *ev = new_activity_state_changed(); - ev->state = state; - - return ev; -} \ No newline at end of file +ZMK_EVENT_DECLARE(zmk_activity_state_changed); \ No newline at end of file diff --git a/app/include/zmk/events/battery_state_changed.h b/app/include/zmk/events/battery_state_changed.h index 47e44ba1..6a003d8d 100644 --- a/app/include/zmk/events/battery_state_changed.h +++ b/app/include/zmk/events/battery_state_changed.h @@ -9,10 +9,9 @@ #include #include -struct battery_state_changed { - struct zmk_event_header header; +struct zmk_battery_state_changed { // TODO: Other battery channels uint8_t state_of_charge; }; -ZMK_EVENT_DECLARE(battery_state_changed); \ No newline at end of file +ZMK_EVENT_DECLARE(zmk_battery_state_changed); \ No newline at end of file diff --git a/app/include/zmk/events/ble_active_profile_changed.h b/app/include/zmk/events/ble_active_profile_changed.h index fa161266..4d3bb7ae 100644 --- a/app/include/zmk/events/ble_active_profile_changed.h +++ b/app/include/zmk/events/ble_active_profile_changed.h @@ -12,10 +12,9 @@ #include -struct ble_active_profile_changed { - struct zmk_event_header header; +struct zmk_ble_active_profile_changed { uint8_t index; struct zmk_ble_profile *profile; }; -ZMK_EVENT_DECLARE(ble_active_profile_changed); +ZMK_EVENT_DECLARE(zmk_ble_active_profile_changed); diff --git a/app/include/zmk/events/keycode_state_changed.h b/app/include/zmk/events/keycode_state_changed.h index 85b792b7..466bbd76 100644 --- a/app/include/zmk/events/keycode_state_changed.h +++ b/app/include/zmk/events/keycode_state_changed.h @@ -7,37 +7,42 @@ #pragma once #include -#include -#include #include #include -struct keycode_state_changed { - struct zmk_event_header header; +struct zmk_keycode_state_changed { uint16_t usage_page; uint32_t keycode; uint8_t implicit_modifiers; + uint8_t explicit_modifiers; bool state; int64_t timestamp; }; -ZMK_EVENT_DECLARE(keycode_state_changed); +ZMK_EVENT_DECLARE(zmk_keycode_state_changed); -static inline struct keycode_state_changed * -keycode_state_changed_from_encoded(uint32_t encoded, bool pressed, int64_t timestamp) { +static inline struct zmk_keycode_state_changed_event * +zmk_keycode_state_changed_from_encoded(uint32_t encoded, bool pressed, int64_t timestamp) { uint16_t page = HID_USAGE_PAGE(encoded) & 0xFF; uint16_t id = HID_USAGE_ID(encoded); - zmk_mod_flags_t implicit_mods = SELECT_MODS(encoded); + uint8_t implicit_modifiers = 0x00; + uint8_t explicit_modifiers = 0x00; if (!page) { page = HID_USAGE_KEY; } - struct keycode_state_changed *ev = new_keycode_state_changed(); - ev->usage_page = page; - ev->keycode = id; - ev->implicit_modifiers = implicit_mods; - ev->state = pressed; - ev->timestamp = timestamp; - return ev; + if (is_mod(page, id)) { + explicit_modifiers = SELECT_MODS(encoded); + } else { + implicit_modifiers = SELECT_MODS(encoded); + } + + return new_zmk_keycode_state_changed( + (struct zmk_keycode_state_changed){.usage_page = page, + .keycode = id, + .implicit_modifiers = implicit_modifiers, + .explicit_modifiers = explicit_modifiers, + .state = pressed, + .timestamp = timestamp}); } diff --git a/app/include/zmk/events/layer_state_changed.h b/app/include/zmk/events/layer_state_changed.h index cf240025..33183546 100644 --- a/app/include/zmk/events/layer_state_changed.h +++ b/app/include/zmk/events/layer_state_changed.h @@ -9,20 +9,16 @@ #include #include -struct layer_state_changed { - struct zmk_event_header header; +struct zmk_layer_state_changed { uint8_t layer; bool state; int64_t timestamp; }; -ZMK_EVENT_DECLARE(layer_state_changed); +ZMK_EVENT_DECLARE(zmk_layer_state_changed); -static inline struct layer_state_changed *create_layer_state_changed(uint8_t layer, bool state) { - struct layer_state_changed *ev = new_layer_state_changed(); - ev->layer = layer; - ev->state = state; - ev->timestamp = k_uptime_get(); - - return ev; +static inline struct zmk_layer_state_changed_event *create_layer_state_changed(uint8_t layer, + bool state) { + return new_zmk_layer_state_changed((struct zmk_layer_state_changed){ + .layer = layer, .state = state, .timestamp = k_uptime_get()}); } diff --git a/app/include/zmk/events/modifiers_state_changed.h b/app/include/zmk/events/modifiers_state_changed.h index 4f40f4c9..504c2c9c 100644 --- a/app/include/zmk/events/modifiers_state_changed.h +++ b/app/include/zmk/events/modifiers_state_changed.h @@ -10,19 +10,9 @@ #include #include -struct modifiers_state_changed { - struct zmk_event_header header; +struct zmk_modifiers_state_changed { zmk_mod_flags_t modifiers; bool state; }; -ZMK_EVENT_DECLARE(modifiers_state_changed); - -inline struct modifiers_state_changed *create_modifiers_state_changed(zmk_mod_flags_t modifiers, - bool state) { - struct modifiers_state_changed *ev = new_modifiers_state_changed(); - ev->modifiers = modifiers; - ev->state = state; - - return ev; -} \ No newline at end of file +ZMK_EVENT_DECLARE(zmk_modifiers_state_changed); \ No newline at end of file diff --git a/app/include/zmk/events/position_state_changed.h b/app/include/zmk/events/position_state_changed.h index 0f1ac1b2..e2f68720 100644 --- a/app/include/zmk/events/position_state_changed.h +++ b/app/include/zmk/events/position_state_changed.h @@ -8,12 +8,10 @@ #include #include - -struct position_state_changed { - struct zmk_event_header header; +struct zmk_position_state_changed { uint32_t position; bool state; int64_t timestamp; }; -ZMK_EVENT_DECLARE(position_state_changed); \ No newline at end of file +ZMK_EVENT_DECLARE(zmk_position_state_changed); \ No newline at end of file diff --git a/app/include/zmk/events/sensor_event.h b/app/include/zmk/events/sensor_event.h index 14fb2d3d..f579bc39 100644 --- a/app/include/zmk/events/sensor_event.h +++ b/app/include/zmk/events/sensor_event.h @@ -9,12 +9,10 @@ #include #include #include - -struct sensor_event { - struct zmk_event_header header; +struct zmk_sensor_event { uint8_t sensor_number; const struct device *sensor; int64_t timestamp; }; -ZMK_EVENT_DECLARE(sensor_event); \ No newline at end of file +ZMK_EVENT_DECLARE(zmk_sensor_event); \ No newline at end of file diff --git a/app/include/zmk/events/usb_conn_state_changed.h b/app/include/zmk/events/usb_conn_state_changed.h index b38fb9fe..b40158c3 100644 --- a/app/include/zmk/events/usb_conn_state_changed.h +++ b/app/include/zmk/events/usb_conn_state_changed.h @@ -12,9 +12,8 @@ #include #include -struct usb_conn_state_changed { - struct zmk_event_header header; +struct zmk_usb_conn_state_changed { enum zmk_usb_conn_state conn_state; }; -ZMK_EVENT_DECLARE(usb_conn_state_changed); \ No newline at end of file +ZMK_EVENT_DECLARE(zmk_usb_conn_state_changed); \ No newline at end of file diff --git a/app/include/zmk/events/wpm_state_changed.h b/app/include/zmk/events/wpm_state_changed.h new file mode 100644 index 00000000..3d1a3695 --- /dev/null +++ b/app/include/zmk/events/wpm_state_changed.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#pragma once + +#include +#include +#include + +struct zmk_wpm_state_changed { + int state; +}; + +ZMK_EVENT_DECLARE(zmk_wpm_state_changed); diff --git a/app/include/zmk/hid.h b/app/include/zmk/hid.h index 1ec51262..5aa004c2 100644 --- a/app/include/zmk/hid.h +++ b/app/include/zmk/hid.h @@ -166,8 +166,11 @@ struct zmk_hid_consumer_report { struct zmk_hid_consumer_report_body body; } __packed; +zmk_mod_flags_t zmk_hid_get_explicit_mods(); int zmk_hid_register_mod(zmk_mod_t modifier); int zmk_hid_unregister_mod(zmk_mod_t modifier); +int zmk_hid_register_mods(zmk_mod_flags_t explicit_modifiers); +int zmk_hid_unregister_mods(zmk_mod_flags_t explicit_modifiers); int zmk_hid_implicit_modifiers_press(zmk_mod_flags_t implicit_modifiers); int zmk_hid_implicit_modifiers_release(); int zmk_hid_keyboard_press(zmk_key_t key); diff --git a/app/include/zmk/keymap.h b/app/include/zmk/keymap.h index 4bcdc2b4..7151930a 100644 --- a/app/include/zmk/keymap.h +++ b/app/include/zmk/keymap.h @@ -19,3 +19,12 @@ int zmk_keymap_layer_to(uint8_t layer); const char *zmk_keymap_layer_label(uint8_t layer); int zmk_keymap_position_state_changed(uint32_t position, bool pressed, int64_t timestamp); + +#define ZMK_KEYMAP_EXTRACT_BINDING(idx, drv_inst) \ + { \ + .behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(drv_inst, bindings, idx)), \ + .param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(drv_inst, bindings, idx, param1), (0), \ + (DT_PHA_BY_IDX(drv_inst, bindings, idx, param1))), \ + .param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(drv_inst, bindings, idx, param2), (0), \ + (DT_PHA_BY_IDX(drv_inst, bindings, idx, param2))), \ + } diff --git a/app/include/zmk/keys.h b/app/include/zmk/keys.h index 62e3cce8..38777ec8 100644 --- a/app/include/zmk/keys.h +++ b/app/include/zmk/keys.h @@ -18,4 +18,9 @@ struct zmk_key_event { uint32_t row; zmk_key_t key; bool pressed; -}; \ No newline at end of file +}; + +static inline bool is_mod(uint8_t usage_page, uint32_t keycode) { + return (keycode >= HID_USAGE_KEY_KEYBOARD_LEFTCONTROL && + keycode <= HID_USAGE_KEY_KEYBOARD_RIGHT_GUI && usage_page == HID_USAGE_KEY); +} \ No newline at end of file diff --git a/app/include/zmk/wpm.h b/app/include/zmk/wpm.h new file mode 100644 index 00000000..6db100a0 --- /dev/null +++ b/app/include/zmk/wpm.h @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#pragma once + +int zmk_wpm_get_state(); \ No newline at end of file diff --git a/app/run-test.sh b/app/run-test.sh index dd3c752b..47089323 100755 --- a/app/run-test.sh +++ b/app/run-test.sh @@ -17,7 +17,7 @@ testcases=$(find $path -name native_posix.keymap -exec dirname \{\} \;) num_cases=$(echo "$testcases" | wc -l) if [ $num_cases -gt 1 ]; then echo "" > ./build/tests/pass-fail.log - echo "$testcases" | xargs -l -P 4 ./run-test.sh + echo "$testcases" | xargs -L 1 -P 4 ./run-test.sh err=$? sort -k2 ./build/tests/pass-fail.log exit $err @@ -45,4 +45,4 @@ else echo "PASS: $testcase" >> ./build/tests/pass-fail.log exit 0 fi -fi \ No newline at end of file +fi diff --git a/app/src/activity.c b/app/src/activity.c index 8fe912a3..0661b270 100644 --- a/app/src/activity.c +++ b/app/src/activity.c @@ -29,7 +29,10 @@ static uint32_t activity_last_uptime; #define MAX_SLEEP_MS CONFIG_ZMK_IDLE_SLEEP_TIMEOUT #endif -int raise_event() { return ZMK_EVENT_RAISE(create_activity_state_changed(activity_state)); } +int raise_event() { + return ZMK_EVENT_RAISE(new_zmk_activity_state_changed( + (struct zmk_activity_state_changed){.state = activity_state})); +} int set_state(enum zmk_activity_state state) { if (activity_state == state) @@ -41,7 +44,7 @@ int set_state(enum zmk_activity_state state) { enum zmk_activity_state zmk_activity_get_state() { return activity_state; } -int activity_event_listener(const struct zmk_event_header *eh) { +int activity_event_listener(const zmk_event_t *eh) { activity_last_uptime = k_uptime_get(); return set_state(ZMK_ACTIVITY_ACTIVE); @@ -74,7 +77,7 @@ int activity_init() { } ZMK_LISTENER(activity, activity_event_listener); -ZMK_SUBSCRIPTION(activity, position_state_changed); -ZMK_SUBSCRIPTION(activity, sensor_event); +ZMK_SUBSCRIPTION(activity, zmk_position_state_changed); +ZMK_SUBSCRIPTION(activity, zmk_sensor_event); SYS_INIT(activity_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); diff --git a/app/src/battery.c b/app/src/battery.c index 917af9cf..5a7c57b0 100644 --- a/app/src/battery.c +++ b/app/src/battery.c @@ -45,9 +45,8 @@ static int zmk_battery_update(const struct device *battery) { return rc; } - struct battery_state_changed *ev = new_battery_state_changed(); - ev->state_of_charge = state_of_charge.val1; - return ZMK_EVENT_RAISE(ev); + return ZMK_EVENT_RAISE(new_zmk_battery_state_changed( + (struct zmk_battery_state_changed){.state_of_charge = state_of_charge.val1})); } static void zmk_battery_work(struct k_work *work) { diff --git a/app/src/behaviors/behavior_hold_tap.c b/app/src/behaviors/behavior_hold_tap.c index 9b62eb15..4e918466 100644 --- a/app/src/behaviors/behavior_hold_tap.c +++ b/app/src/behaviors/behavior_hold_tap.c @@ -8,8 +8,8 @@ #include #include +#include #include -#include #include #include #include @@ -17,8 +17,8 @@ #include #include #include -#include #include +#include LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); @@ -36,14 +36,10 @@ enum flavor { ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED = 2, }; -struct behavior_hold_tap_behaviors { - struct zmk_behavior_binding tap; - struct zmk_behavior_binding hold; -}; - struct behavior_hold_tap_config { int tapping_term_ms; - struct behavior_hold_tap_behaviors *behaviors; + char *hold_behavior_dev; + char *tap_behavior_dev; enum flavor flavor; }; @@ -69,9 +65,9 @@ struct active_hold_tap { struct active_hold_tap *undecided_hold_tap = NULL; struct active_hold_tap active_hold_taps[ZMK_BHV_HOLD_TAP_MAX_HELD] = {}; // We capture most position_state_changed events and some modifiers_state_changed events. -const struct zmk_event_header *captured_events[ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS] = {}; +const zmk_event_t *captured_events[ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS] = {}; -static int capture_event(const struct zmk_event_header *event) { +static int capture_event(const zmk_event_t *event) { for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) { if (captured_events[i] == NULL) { captured_events[i] = event; @@ -81,17 +77,18 @@ static int capture_event(const struct zmk_event_header *event) { return -ENOMEM; } -static struct position_state_changed *find_captured_keydown_event(uint32_t position) { - struct position_state_changed *last_match = NULL; +static struct zmk_position_state_changed *find_captured_keydown_event(uint32_t position) { + struct zmk_position_state_changed *last_match = NULL; for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) { - const struct zmk_event_header *eh = captured_events[i]; + const zmk_event_t *eh = captured_events[i]; if (eh == NULL) { return last_match; } - if (!is_position_state_changed(eh)) { + struct zmk_position_state_changed *position_event = as_zmk_position_state_changed(eh); + if (position_event == NULL) { continue; } - struct position_state_changed *position_event = cast_position_state_changed(eh); + if (position_event->position == position && position_event->state) { last_match = position_event; } @@ -132,7 +129,7 @@ static void release_captured_events() { // [k1_down, k1_up, null, null, null, ...] // now mt2 will start releasing it's own captured positions. for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) { - const struct zmk_event_header *captured_event = captured_events[i]; + const zmk_event_t *captured_event = captured_events[i]; if (captured_event == NULL) { return; } @@ -140,14 +137,13 @@ static void release_captured_events() { if (undecided_hold_tap != NULL) { k_msleep(10); } - if (is_position_state_changed(captured_event)) { - struct position_state_changed *position_event = - cast_position_state_changed(captured_event); + + struct zmk_position_state_changed *position_event; + struct zmk_keycode_state_changed *modifier_event; + if ((position_event = as_zmk_position_state_changed(captured_event)) != NULL) { LOG_DBG("Releasing key position event for position %d %s", position_event->position, (position_event->state ? "pressed" : "released")); - } else { - struct keycode_state_changed *modifier_event = - cast_keycode_state_changed(captured_event); + } else if ((modifier_event = as_zmk_keycode_state_changed(captured_event)) != NULL) { LOG_DBG("Releasing mods changed event 0x%02X %s", modifier_event->keycode, (modifier_event->state ? "pressed" : "released")); } @@ -290,11 +286,11 @@ static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_mome struct zmk_behavior_binding binding; if (hold_tap->is_hold) { - binding.behavior_dev = hold_tap->config->behaviors->hold.behavior_dev; + binding.behavior_dev = hold_tap->config->hold_behavior_dev; binding.param1 = hold_tap->param_hold; binding.param2 = 0; } else { - binding.behavior_dev = hold_tap->config->behaviors->tap.behavior_dev; + binding.behavior_dev = hold_tap->config->tap_behavior_dev; binding.param1 = hold_tap->param_tap; binding.param2 = 0; } @@ -351,7 +347,8 @@ static int on_hold_tap_binding_released(struct zmk_behavior_binding *binding, decide_hold_tap(hold_tap, HT_KEY_UP); - // todo: set up the binding and data items inside of the active_hold_tap struct + // todo: set up the binding and data items inside of the + // active_hhold_tap->config->behaviors->tap.behavior_dev;old_tap struct struct zmk_behavior_binding_event sub_behavior_data = { .position = hold_tap->position, .timestamp = hold_tap->timestamp, @@ -359,11 +356,11 @@ static int on_hold_tap_binding_released(struct zmk_behavior_binding *binding, struct zmk_behavior_binding sub_behavior_binding; if (hold_tap->is_hold) { - sub_behavior_binding.behavior_dev = hold_tap->config->behaviors->hold.behavior_dev; + sub_behavior_binding.behavior_dev = hold_tap->config->hold_behavior_dev; sub_behavior_binding.param1 = hold_tap->param_hold; sub_behavior_binding.param2 = 0; } else { - sub_behavior_binding.behavior_dev = hold_tap->config->behaviors->tap.behavior_dev; + sub_behavior_binding.behavior_dev = hold_tap->config->tap_behavior_dev; sub_behavior_binding.param1 = hold_tap->param_tap; sub_behavior_binding.param2 = 0; } @@ -387,8 +384,8 @@ static const struct behavior_driver_api behavior_hold_tap_driver_api = { .binding_released = on_hold_tap_binding_released, }; -static int position_state_changed_listener(const struct zmk_event_header *eh) { - struct position_state_changed *ev = cast_position_state_changed(eh); +static int position_state_changed_listener(const zmk_event_t *eh) { + struct zmk_position_state_changed *ev = as_zmk_position_state_changed(eh); if (undecided_hold_tap == NULL) { LOG_DBG("%d bubble (no undecided hold_tap active)", ev->position); @@ -428,21 +425,16 @@ static int position_state_changed_listener(const struct zmk_event_header *eh) { return ZMK_EV_EVENT_CAPTURED; } -static inline bool only_mods(struct keycode_state_changed *ev) { - return ev->usage_page == HID_USAGE_KEY && ev->keycode >= HID_USAGE_KEY_KEYBOARD_LEFTCONTROL && - ev->keycode <= HID_USAGE_KEY_KEYBOARD_RIGHT_GUI; -} - -static int keycode_state_changed_listener(const struct zmk_event_header *eh) { +static int keycode_state_changed_listener(const zmk_event_t *eh) { // we want to catch layer-up events too... how? - struct keycode_state_changed *ev = cast_keycode_state_changed(eh); + struct zmk_keycode_state_changed *ev = as_zmk_keycode_state_changed(eh); if (undecided_hold_tap == NULL) { // LOG_DBG("0x%02X bubble (no undecided hold_tap active)", ev->keycode); return ZMK_EV_EVENT_BUBBLE; } - if (!only_mods(ev)) { + if (!is_mod(ev->usage_page, ev->keycode)) { // LOG_DBG("0x%02X bubble (not a mod)", ev->keycode); return ZMK_EV_EVENT_BUBBLE; } @@ -455,19 +447,19 @@ static int keycode_state_changed_listener(const struct zmk_event_header *eh) { return ZMK_EV_EVENT_CAPTURED; } -int behavior_hold_tap_listener(const struct zmk_event_header *eh) { - if (is_position_state_changed(eh)) { +int behavior_hold_tap_listener(const zmk_event_t *eh) { + if (as_zmk_position_state_changed(eh) != NULL) { return position_state_changed_listener(eh); - } else if (is_keycode_state_changed(eh)) { + } else if (as_zmk_keycode_state_changed(eh) != NULL) { return keycode_state_changed_listener(eh); } return ZMK_EV_EVENT_BUBBLE; } ZMK_LISTENER(behavior_hold_tap, behavior_hold_tap_listener); -ZMK_SUBSCRIPTION(behavior_hold_tap, position_state_changed); +ZMK_SUBSCRIPTION(behavior_hold_tap, zmk_position_state_changed); // this should be modifiers_state_changed, but unfrotunately that's not implemented yet. -ZMK_SUBSCRIPTION(behavior_hold_tap, keycode_state_changed); +ZMK_SUBSCRIPTION(behavior_hold_tap, zmk_keycode_state_changed); void behavior_hold_tap_timer_work_handler(struct k_work *item) { struct active_hold_tap *hold_tap = CONTAINER_OF(item, struct active_hold_tap, work); @@ -495,22 +487,11 @@ static int behavior_hold_tap_init(const struct device *dev) { struct behavior_hold_tap_data {}; static struct behavior_hold_tap_data behavior_hold_tap_data; -/* todo: get rid of unused param1 and param2. */ -#define _TRANSFORM_ENTRY(idx, node) \ - { \ - .behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(node, bindings, idx)), \ - .param1 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param1), (0), \ - (DT_INST_PHA_BY_IDX(node, bindings, idx, param1))), \ - .param2 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param2), (0), \ - (DT_INST_PHA_BY_IDX(node, bindings, idx, param2))), \ - }, - #define KP_INST(n) \ - static struct behavior_hold_tap_behaviors behavior_hold_tap_behaviors_##n = { \ - .hold = _TRANSFORM_ENTRY(0, n).tap = _TRANSFORM_ENTRY(1, n)}; \ static struct behavior_hold_tap_config behavior_hold_tap_config_##n = { \ - .behaviors = &behavior_hold_tap_behaviors_##n, \ .tapping_term_ms = DT_INST_PROP(n, tapping_term_ms), \ + .hold_behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(n, bindings, 0)), \ + .tap_behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(n, bindings, 1)), \ .flavor = DT_ENUM_IDX(DT_DRV_INST(n), flavor), \ }; \ DEVICE_AND_API_INIT(behavior_hold_tap_##n, DT_INST_LABEL(n), behavior_hold_tap_init, \ diff --git a/app/src/behaviors/behavior_key_press.c b/app/src/behaviors/behavior_key_press.c index df0828ac..8282977e 100644 --- a/app/src/behaviors/behavior_key_press.c +++ b/app/src/behaviors/behavior_key_press.c @@ -22,14 +22,14 @@ static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event) { LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1); return ZMK_EVENT_RAISE( - keycode_state_changed_from_encoded(binding->param1, true, event.timestamp)); + zmk_keycode_state_changed_from_encoded(binding->param1, true, event.timestamp)); } static int on_keymap_binding_released(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event) { LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1); return ZMK_EVENT_RAISE( - keycode_state_changed_from_encoded(binding->param1, false, event.timestamp)); + zmk_keycode_state_changed_from_encoded(binding->param1, false, event.timestamp)); } static const struct behavior_driver_api behavior_key_press_driver_api = { diff --git a/app/src/behaviors/behavior_mod_morph.c b/app/src/behaviors/behavior_mod_morph.c new file mode 100644 index 00000000..36d109b8 --- /dev/null +++ b/app/src/behaviors/behavior_mod_morph.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#define DT_DRV_COMPAT zmk_behavior_mod_morph + +#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_mod_morph_config { + struct zmk_behavior_binding normal_binding; + struct zmk_behavior_binding morph_binding; + zmk_mod_flags_t mods; +}; + +struct behavior_mod_morph_data { + struct zmk_behavior_binding *pressed_binding; +}; + +static int on_mod_morph_binding_pressed(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + const struct device *dev = device_get_binding(binding->behavior_dev); + const struct behavior_mod_morph_config *cfg = dev->config; + struct behavior_mod_morph_data *data = dev->data; + + if (data->pressed_binding != NULL) { + LOG_ERR("Can't press the same mod-morph twice"); + return -ENOTSUP; + } + + if (zmk_hid_get_explicit_mods() & cfg->mods) { + data->pressed_binding = (struct zmk_behavior_binding *)&cfg->morph_binding; + } else { + data->pressed_binding = (struct zmk_behavior_binding *)&cfg->normal_binding; + } + return behavior_keymap_binding_pressed(data->pressed_binding, event); +} + +static int on_mod_morph_binding_released(struct zmk_behavior_binding *binding, + struct zmk_behavior_binding_event event) { + const struct device *dev = device_get_binding(binding->behavior_dev); + struct behavior_mod_morph_data *data = dev->data; + + if (data->pressed_binding == NULL) { + LOG_ERR("Mod-morph already released"); + return -ENOTSUP; + } + + struct zmk_behavior_binding *pressed_binding = data->pressed_binding; + data->pressed_binding = NULL; + return behavior_keymap_binding_released(pressed_binding, event); +} + +static const struct behavior_driver_api behavior_mod_morph_driver_api = { + .binding_pressed = on_mod_morph_binding_pressed, + .binding_released = on_mod_morph_binding_released, +}; + +static int behavior_mod_morph_init(const struct device *dev) { return 0; } + +#define _TRANSFORM_ENTRY(idx, node) \ + { \ + .behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(node, bindings, idx)), \ + .param1 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param1), (0), \ + (DT_INST_PHA_BY_IDX(node, bindings, idx, param1))), \ + .param2 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param2), (0), \ + (DT_INST_PHA_BY_IDX(node, bindings, idx, param2))), \ + } + +#define KP_INST(n) \ + static struct behavior_mod_morph_config behavior_mod_morph_config_##n = { \ + .normal_binding = _TRANSFORM_ENTRY(0, n), \ + .morph_binding = _TRANSFORM_ENTRY(1, n), \ + .mods = DT_INST_PROP(n, mods), \ + }; \ + static struct behavior_mod_morph_data behavior_mod_morph_data_##n = {}; \ + DEVICE_AND_API_INIT(behavior_mod_morph_##n, DT_INST_LABEL(n), behavior_mod_morph_init, \ + &behavior_mod_morph_data_##n, &behavior_mod_morph_config_##n, APPLICATION, \ + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_mod_morph_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(KP_INST) + +#endif \ No newline at end of file diff --git a/app/src/behaviors/behavior_sensor_rotate_key_press.c b/app/src/behaviors/behavior_sensor_rotate_key_press.c index 1e659a15..67a2e710 100644 --- a/app/src/behaviors/behavior_sensor_rotate_key_press.c +++ b/app/src/behaviors/behavior_sensor_rotate_key_press.c @@ -45,12 +45,12 @@ static int on_sensor_binding_triggered(struct zmk_behavior_binding *binding, LOG_DBG("SEND %d", keycode); - ZMK_EVENT_RAISE(keycode_state_changed_from_encoded(keycode, true, timestamp)); + ZMK_EVENT_RAISE(zmk_keycode_state_changed_from_encoded(keycode, true, timestamp)); // TODO: Better way to do this? k_msleep(5); - return ZMK_EVENT_RAISE(keycode_state_changed_from_encoded(keycode, false, timestamp)); + return ZMK_EVENT_RAISE(zmk_keycode_state_changed_from_encoded(keycode, false, timestamp)); } static const struct behavior_driver_api behavior_sensor_rotate_key_press_driver_api = { diff --git a/app/src/behaviors/behavior_sticky_key.c b/app/src/behaviors/behavior_sticky_key.c index 15c9e21c..20af93a8 100644 --- a/app/src/behaviors/behavior_sticky_key.c +++ b/app/src/behaviors/behavior_sticky_key.c @@ -18,6 +18,7 @@ #include #include #include +#include LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); @@ -29,6 +30,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); struct behavior_sticky_key_config { uint32_t release_after_ms; + bool quick_release; struct zmk_behavior_binding behavior; }; @@ -175,11 +177,11 @@ static const struct behavior_driver_api behavior_sticky_key_driver_api = { .binding_released = on_sticky_key_binding_released, }; -static int sticky_key_keycode_state_changed_listener(const struct zmk_event_header *eh) { - if (!is_keycode_state_changed(eh)) { +static int sticky_key_keycode_state_changed_listener(const zmk_event_t *eh) { + struct zmk_keycode_state_changed *ev = as_zmk_keycode_state_changed(eh); + if (ev == NULL) { return ZMK_EV_EVENT_BUBBLE; } - struct keycode_state_changed *ev = cast_keycode_state_changed(eh); for (int i = 0; i < ZMK_BHV_STICKY_KEY_MAX_HELD; i++) { struct active_sticky_key *sticky_key = &active_sticky_keys[i]; if (sticky_key->position == ZMK_BHV_STICKY_KEY_POSITION_FREE) { @@ -209,10 +211,12 @@ static int sticky_key_keycode_state_changed_listener(const struct zmk_event_head } if (sticky_key->timer_started) { stop_timer(sticky_key); + if (sticky_key->config->quick_release) { + release_sticky_key_behavior(sticky_key, ev->timestamp); + } } sticky_key->modified_key_usage_page = ev->usage_page; sticky_key->modified_key_keycode = ev->keycode; - } else { // key up if (sticky_key->timer_started && sticky_key->modified_key_usage_page == ev->usage_page && @@ -226,7 +230,7 @@ static int sticky_key_keycode_state_changed_listener(const struct zmk_event_head } ZMK_LISTENER(behavior_sticky_key, sticky_key_keycode_state_changed_listener); -ZMK_SUBSCRIPTION(behavior_sticky_key, keycode_state_changed); +ZMK_SUBSCRIPTION(behavior_sticky_key, zmk_keycode_state_changed); void behavior_sticky_key_timer_handler(struct k_work *item) { struct active_sticky_key *sticky_key = @@ -257,18 +261,11 @@ static int behavior_sticky_key_init(const struct device *dev) { struct behavior_sticky_key_data {}; static struct behavior_sticky_key_data behavior_sticky_key_data; -#define _TRANSFORM_ENTRY(idx, node) \ - { \ - .behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(node, bindings, idx)), \ - .param1 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param1), (0), \ - (DT_INST_PHA_BY_IDX(node, bindings, idx, param1))), \ - .param2 = COND_CODE_0(DT_INST_PHA_HAS_CELL_AT_IDX(node, bindings, idx, param2), (0), \ - (DT_INST_PHA_BY_IDX(node, bindings, idx, param2))), \ - }, - #define KP_INST(n) \ static struct behavior_sticky_key_config behavior_sticky_key_config_##n = { \ - .behavior = _TRANSFORM_ENTRY(0, n).release_after_ms = DT_INST_PROP(n, release_after_ms), \ + .behavior = ZMK_KEYMAP_EXTRACT_BINDING(0, DT_DRV_INST(n)), \ + .release_after_ms = DT_INST_PROP(n, release_after_ms), \ + .quick_release = DT_INST_PROP(n, quick_release), \ }; \ DEVICE_AND_API_INIT(behavior_sticky_key_##n, DT_INST_LABEL(n), behavior_sticky_key_init, \ &behavior_sticky_key_data, &behavior_sticky_key_config_##n, APPLICATION, \ @@ -276,4 +273,4 @@ static struct behavior_sticky_key_data behavior_sticky_key_data; DT_INST_FOREACH_STATUS_OKAY(KP_INST) -#endif \ No newline at end of file +#endif diff --git a/app/src/ble.c b/app/src/ble.c index b32696ff..b15a079e 100644 --- a/app/src/ble.c +++ b/app/src/ble.c @@ -63,6 +63,8 @@ static uint8_t active_profile; #define DEVICE_NAME CONFIG_BT_DEVICE_NAME #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1) +BUILD_ASSERT(DEVICE_NAME_LEN <= 16, "ERROR: BLE device name is too long. Max length: 16"); + #define IS_HOST_PERIPHERAL \ (!IS_ENABLED(CONFIG_ZMK_SPLIT) || IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)) #define IS_SPLIT_PERIPHERAL \ @@ -92,11 +94,8 @@ static bt_addr_le_t peripheral_addr; #endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */ static void raise_profile_changed_event() { - struct ble_active_profile_changed *ev = new_ble_active_profile_changed(); - ev->index = active_profile; - ev->profile = &profiles[active_profile]; - - ZMK_EVENT_RAISE(ev); + ZMK_EVENT_RAISE(new_zmk_ble_active_profile_changed((struct zmk_ble_active_profile_changed){ + .index = active_profile, .profile = &profiles[active_profile]})); } static void raise_profile_changed_event_callback(struct k_work *work) { @@ -376,7 +375,10 @@ static void connected(struct bt_conn *conn, uint8_t err) { LOG_DBG("Connected %s", log_strdup(addr)); - bt_conn_le_param_update(conn, BT_LE_CONN_PARAM(0x0006, 0x000c, 30, 400)); + err = bt_conn_le_param_update(conn, BT_LE_CONN_PARAM(0x0006, 0x000c, 30, 400)); + if (err) { + LOG_WRN("Failed to update LE parameters (err %d)", err); + } #if IS_SPLIT_PERIPHERAL bt_conn_le_phy_update(conn, BT_CONN_LE_PHY_PARAM_2M); @@ -423,10 +425,20 @@ static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_ } } +static void le_param_updated(struct bt_conn *conn, uint16_t interval, uint16_t latency, + uint16_t timeout) { + char addr[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + LOG_DBG("%s: interval %d latency %d timeout %d", log_strdup(addr), interval, latency, timeout); +} + static struct bt_conn_cb conn_callbacks = { .connected = connected, .disconnected = disconnected, .security_changed = security_changed, + .le_param_updated = le_param_updated, }; /* diff --git a/app/src/combo.c b/app/src/combo.c index 49638703..82f6538f 100644 --- a/app/src/combo.c +++ b/app/src/combo.c @@ -40,7 +40,7 @@ struct active_combo { // key_positions_pressed is filled with key_positions when the combo is pressed. // The keys are removed from this array when they are released. // Once this array is empty, the behavior is released. - struct position_state_changed *key_positions_pressed[CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO]; + const zmk_event_t *key_positions_pressed[CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO]; }; struct combo_candidate { @@ -52,7 +52,7 @@ struct combo_candidate { }; // set of keys pressed -struct position_state_changed *pressed_keys[CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO] = {NULL}; +const zmk_event_t *pressed_keys[CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO] = {NULL}; // the set of candidate combos based on the currently pressed_keys struct combo_candidate candidates[CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY]; // the last candidate that was completely pressed @@ -202,7 +202,7 @@ static int clear_candidates() { return CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY; } -static int capture_pressed_key(struct position_state_changed *ev) { +static int capture_pressed_key(const zmk_event_t *ev) { for (int i = 0; i < CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY; i++) { if (pressed_keys[i] != NULL) { continue; @@ -228,7 +228,7 @@ static void release_pressed_keys() { if (pressed_keys[i] == NULL) { return; } - struct position_state_changed *captured_event = pressed_keys[i]; + const zmk_event_t *captured_event = pressed_keys[i]; pressed_keys[i] = NULL; ZMK_EVENT_RAISE(captured_event); } @@ -290,7 +290,8 @@ static void activate_combo(struct combo_cfg *combo) { return; } move_pressed_keys_to_active_combo(active_combo); - press_combo_behavior(combo, active_combo->key_positions_pressed[0]->timestamp); + press_combo_behavior( + combo, as_zmk_position_state_changed(active_combo->key_positions_pressed[0])->timestamp); } static void deactivate_combo(int active_combo_index) { @@ -314,10 +315,11 @@ static bool release_combo_key(int32_t position, int64_t timestamp) { for (int i = 0; i < active_combo->combo->key_position_len; i++) { if (active_combo->key_positions_pressed[i] == NULL) { all_keys_pressed = false; - } else if (active_combo->key_positions_pressed[i]->position != position) { + } else if (as_zmk_position_state_changed(active_combo->key_positions_pressed[i]) + ->position != position) { all_keys_released = false; } else { // not null and position matches - k_free(active_combo->key_positions_pressed[i]); + ZMK_EVENT_FREE(active_combo->key_positions_pressed[i]); active_combo->key_positions_pressed[i] = NULL; key_released = true; } @@ -362,16 +364,16 @@ static void update_timeout_task() { } } -static int position_state_down(struct position_state_changed *ev) { +static int position_state_down(const zmk_event_t *ev, struct zmk_position_state_changed *data) { int num_candidates; if (candidates[0].combo == NULL) { - num_candidates = setup_candidates_for_first_keypress(ev->position, ev->timestamp); + num_candidates = setup_candidates_for_first_keypress(data->position, data->timestamp); if (num_candidates == 0) { return 0; } } else { - filter_timed_out_candidates(ev->timestamp); - num_candidates = filter_candidates(ev->position); + filter_timed_out_candidates(data->timestamp); + num_candidates = filter_candidates(data->position); } update_timeout_task(); @@ -395,7 +397,7 @@ static int position_state_down(struct position_state_changed *ev) { } } -static int position_state_up(struct position_state_changed *ev) { +static int position_state_up(struct zmk_position_state_changed *ev) { cleanup(); if (release_combo_key(ev->position, ev->timestamp)) { return ZMK_EV_EVENT_HANDLED; @@ -415,21 +417,21 @@ static void combo_timeout_handler(struct k_work *item) { update_timeout_task(); } -static int position_state_changed_listener(const struct zmk_event_header *eh) { - if (!is_position_state_changed(eh)) { +static int position_state_changed_listener(const zmk_event_t *ev) { + struct zmk_position_state_changed *data = as_zmk_position_state_changed(ev); + if (data == NULL) { return 0; } - struct position_state_changed *ev = cast_position_state_changed(eh); - if (ev->state) { // keydown - return position_state_down(ev); + if (data->state) { // keydown + return position_state_down(ev, data); } else { // keyup - return position_state_up(ev); + return position_state_up(data); } } ZMK_LISTENER(combo, position_state_changed_listener); -ZMK_SUBSCRIPTION(combo, position_state_changed); +ZMK_SUBSCRIPTION(combo, zmk_position_state_changed); // todo: remove this once #506 is merged and #include #define KEY_BINDING_TO_STRUCT(idx, drv_inst) \ diff --git a/app/src/display/main.c b/app/src/display/main.c index 0bef6567..55dd1ce2 100644 --- a/app/src/display/main.c +++ b/app/src/display/main.c @@ -75,8 +75,12 @@ int zmk_display_init() { return 0; } -int display_event_handler(const struct zmk_event_header *eh) { - struct activity_state_changed *ev = cast_activity_state_changed(eh); +int display_event_handler(const zmk_event_t *eh) { + struct zmk_activity_state_changed *ev = as_zmk_activity_state_changed(eh); + if (ev == NULL) { + return -ENOTSUP; + } + switch (ev->state) { case ZMK_ACTIVITY_ACTIVE: start_display_updates(); @@ -93,4 +97,4 @@ int display_event_handler(const struct zmk_event_header *eh) { } ZMK_LISTENER(display, display_event_handler); -ZMK_SUBSCRIPTION(display, activity_state_changed); \ No newline at end of file +ZMK_SUBSCRIPTION(display, zmk_activity_state_changed); \ No newline at end of file diff --git a/app/src/display/status_screen.c b/app/src/display/status_screen.c index 0c88717a..6f32b283 100644 --- a/app/src/display/status_screen.c +++ b/app/src/display/status_screen.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -24,6 +25,10 @@ static struct zmk_widget_output_status output_status_widget; static struct zmk_widget_layer_status layer_status_widget; #endif +#if IS_ENABLED(CONFIG_ZMK_WIDGET_WPM_STATUS) +static struct zmk_widget_wpm_status wpm_status_widget; +#endif + lv_obj_t *zmk_display_status_screen() { lv_obj_t *screen; @@ -47,5 +52,10 @@ lv_obj_t *zmk_display_status_screen() { 0, 0); #endif +#if IS_ENABLED(CONFIG_ZMK_WIDGET_WPM_STATUS) + 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 return screen; } diff --git a/app/src/display/widgets/CMakeLists.txt b/app/src/display/widgets/CMakeLists.txt index ad7e132a..1d115dcc 100644 --- a/app/src/display/widgets/CMakeLists.txt +++ b/app/src/display/widgets/CMakeLists.txt @@ -4,3 +4,4 @@ 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_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 bdb3024e..f12d99a3 100644 --- a/app/src/display/widgets/Kconfig +++ b/app/src/display/widgets/Kconfig @@ -22,5 +22,12 @@ config ZMK_WIDGET_OUTPUT_STATUS default y if BT select LVGL_USE_LABEL select LVGL_FONT_MONTSERRAT_16 + +config ZMK_WIDGET_WPM_STATUS + bool "Widget for displaying typed words per minute" + depends on !ZMK_SPLIT || ZMK_SPLIT_BLE_ROLE_CENTRAL + select LVGL_USE_LABEL + select LVGL_FONT_MONTSERRAT_16 + select ZMK_WPM endmenu diff --git a/app/src/display/widgets/battery_status.c b/app/src/display/widgets/battery_status.c index f1f1c9f1..309c3e9d 100644 --- a/app/src/display/widgets/battery_status.c +++ b/app/src/display/widgets/battery_status.c @@ -75,14 +75,14 @@ lv_obj_t *zmk_widget_battery_status_obj(struct zmk_widget_battery_status *widget return widget->obj; } -int battery_status_listener(const struct zmk_event_header *eh) { +int battery_status_listener(const zmk_event_t *eh) { struct zmk_widget_battery_status *widget; SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_battery_symbol(widget->obj); } return ZMK_EV_EVENT_BUBBLE; } ZMK_LISTENER(widget_battery_status, battery_status_listener) -ZMK_SUBSCRIPTION(widget_battery_status, battery_state_changed); +ZMK_SUBSCRIPTION(widget_battery_status, zmk_battery_state_changed); #if IS_ENABLED(CONFIG_USB) -ZMK_SUBSCRIPTION(widget_battery_status, usb_conn_state_changed); +ZMK_SUBSCRIPTION(widget_battery_status, zmk_usb_conn_state_changed); #endif /* IS_ENABLED(CONFIG_USB) */ diff --git a/app/src/display/widgets/layer_status.c b/app/src/display/widgets/layer_status.c index 6700bb30..9960f2a0 100644 --- a/app/src/display/widgets/layer_status.c +++ b/app/src/display/widgets/layer_status.c @@ -69,11 +69,11 @@ lv_obj_t *zmk_widget_layer_status_obj(struct zmk_widget_layer_status *widget) { return widget->obj; } -int layer_status_listener(const struct zmk_event_header *eh) { +int layer_status_listener(const zmk_event_t *eh) { struct zmk_widget_layer_status *widget; SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_layer_symbol(widget->obj); } return 0; } ZMK_LISTENER(widget_layer_status, layer_status_listener) -ZMK_SUBSCRIPTION(widget_layer_status, layer_state_changed); \ No newline at end of file +ZMK_SUBSCRIPTION(widget_layer_status, zmk_layer_state_changed); \ No newline at end of file diff --git a/app/src/display/widgets/output_status.c b/app/src/display/widgets/output_status.c index 716228b7..7e37f906 100644 --- a/app/src/display/widgets/output_status.c +++ b/app/src/display/widgets/output_status.c @@ -79,7 +79,7 @@ lv_obj_t *zmk_widget_output_status_obj(struct zmk_widget_output_status *widget) return widget->obj; } -int output_status_listener(const struct zmk_event_header *eh) { +int output_status_listener(const zmk_event_t *eh) { struct zmk_widget_output_status *widget; SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_status_symbol(widget->obj); } return ZMK_EV_EVENT_BUBBLE; @@ -87,8 +87,8 @@ int output_status_listener(const struct zmk_event_header *eh) { ZMK_LISTENER(widget_output_status, output_status_listener) #if defined(CONFIG_USB) -ZMK_SUBSCRIPTION(widget_output_status, usb_conn_state_changed); +ZMK_SUBSCRIPTION(widget_output_status, zmk_usb_conn_state_changed); #endif #if defined(CONFIG_ZMK_BLE) -ZMK_SUBSCRIPTION(widget_output_status, ble_active_profile_changed); +ZMK_SUBSCRIPTION(widget_output_status, zmk_ble_active_profile_changed); #endif diff --git a/app/src/display/widgets/wpm_status.c b/app/src/display/widgets/wpm_status.c new file mode 100644 index 00000000..41ee3685 --- /dev/null +++ b/app/src/display/widgets/wpm_status.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#include +#include +#include +#include +#include + +static sys_slist_t widgets = SYS_SLIST_STATIC_INIT(&widgets); +static lv_style_t label_style; + +static bool style_initialized = false; + +void wpm_status_init() { + if (style_initialized) { + return; + } + + style_initialized = true; + lv_style_init(&label_style); + lv_style_set_text_color(&label_style, LV_STATE_DEFAULT, LV_COLOR_BLACK); + lv_style_set_text_font(&label_style, LV_STATE_DEFAULT, &lv_font_montserrat_12); + lv_style_set_text_letter_space(&label_style, LV_STATE_DEFAULT, 1); + lv_style_set_text_line_space(&label_style, LV_STATE_DEFAULT, 1); +} + +void set_wpm_symbol(lv_obj_t *label, int wpm) { + char text[4] = {}; + + LOG_DBG("WPM changed to %i", wpm); + sprintf(text, "%i ", wpm); + + lv_label_set_text(label, text); +} + +int zmk_widget_wpm_status_init(struct zmk_widget_wpm_status *widget, lv_obj_t *parent) { + wpm_status_init(); + widget->obj = lv_label_create(parent, NULL); + lv_obj_add_style(widget->obj, LV_LABEL_PART_MAIN, &label_style); + lv_label_set_align(widget->obj, LV_LABEL_ALIGN_RIGHT); + + lv_obj_set_size(widget->obj, 40, 15); + set_wpm_symbol(widget->obj, 0); + + sys_slist_append(&widgets, &widget->node); + + return 0; +} + +lv_obj_t *zmk_widget_wpm_status_obj(struct zmk_widget_wpm_status *widget) { return widget->obj; } + +int wpm_status_listener(const zmk_event_t *eh) { + struct zmk_wpm_state_changed *ev = as_zmk_wpm_state_changed(eh); + struct zmk_widget_wpm_status *widget; + SYS_SLIST_FOR_EACH_CONTAINER(&widgets, widget, node) { set_wpm_symbol(widget->obj, ev->state); } + return 0; +} + +ZMK_LISTENER(widget_wpm_status, wpm_status_listener) +ZMK_SUBSCRIPTION(widget_wpm_status, zmk_wpm_state_changed); \ No newline at end of file diff --git a/app/src/endpoints.c b/app/src/endpoints.c index feff7996..93dfb817 100644 --- a/app/src/endpoints.c +++ b/app/src/endpoints.c @@ -245,17 +245,17 @@ static void update_current_endpoint() { } } -static int endpoint_listener(const struct zmk_event_header *eh) { +static int endpoint_listener(const zmk_event_t *eh) { update_current_endpoint(); return 0; } ZMK_LISTENER(endpoint_listener, endpoint_listener); #if IS_ENABLED(CONFIG_ZMK_USB) -ZMK_SUBSCRIPTION(endpoint_listener, usb_conn_state_changed); +ZMK_SUBSCRIPTION(endpoint_listener, zmk_usb_conn_state_changed); #endif #if IS_ENABLED(CONFIG_ZMK_BLE) -ZMK_SUBSCRIPTION(endpoint_listener, ble_active_profile_changed); +ZMK_SUBSCRIPTION(endpoint_listener, zmk_ble_active_profile_changed); #endif SYS_INIT(zmk_endpoints_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); diff --git a/app/src/event_manager.c b/app/src/event_manager.c index 872f5c86..0399ca80 100644 --- a/app/src/event_manager.c +++ b/app/src/event_manager.c @@ -17,7 +17,7 @@ extern struct zmk_event_type *__event_type_end[]; extern struct zmk_event_subscription __event_subscriptions_start[]; extern struct zmk_event_subscription __event_subscriptions_end[]; -int zmk_event_manager_handle_from(struct zmk_event_header *event, uint8_t start_index) { +int zmk_event_manager_handle_from(zmk_event_t *event, uint8_t start_index) { int ret = 0; uint8_t len = __event_subscriptions_end - __event_subscriptions_start; for (int i = start_index; i < len; i++) { @@ -48,12 +48,9 @@ release: return ret; } -int zmk_event_manager_raise(struct zmk_event_header *event) { - return zmk_event_manager_handle_from(event, 0); -} +int zmk_event_manager_raise(zmk_event_t *event) { return zmk_event_manager_handle_from(event, 0); } -int zmk_event_manager_raise_after(struct zmk_event_header *event, - const struct zmk_listener *listener) { +int zmk_event_manager_raise_after(zmk_event_t *event, const struct zmk_listener *listener) { uint8_t len = __event_subscriptions_end - __event_subscriptions_start; for (int i = 0; i < len; i++) { struct zmk_event_subscription *ev_sub = __event_subscriptions_start + i; @@ -68,8 +65,7 @@ int zmk_event_manager_raise_after(struct zmk_event_header *event, return -EINVAL; } -int zmk_event_manager_raise_at(struct zmk_event_header *event, - const struct zmk_listener *listener) { +int zmk_event_manager_raise_at(zmk_event_t *event, const struct zmk_listener *listener) { uint8_t len = __event_subscriptions_end - __event_subscriptions_start; for (int i = 0; i < len; i++) { struct zmk_event_subscription *ev_sub = __event_subscriptions_start + i; @@ -84,6 +80,6 @@ int zmk_event_manager_raise_at(struct zmk_event_header *event, return -EINVAL; } -int zmk_event_manager_release(struct zmk_event_header *event) { +int zmk_event_manager_release(zmk_event_t *event) { return zmk_event_manager_handle_from(event, event->last_listener_index + 1); } diff --git a/app/src/events/activity_state_changed.c b/app/src/events/activity_state_changed.c index 001e6a1a..2c27ce74 100644 --- a/app/src/events/activity_state_changed.c +++ b/app/src/events/activity_state_changed.c @@ -7,4 +7,4 @@ #include #include -ZMK_EVENT_IMPL(activity_state_changed); \ No newline at end of file +ZMK_EVENT_IMPL(zmk_activity_state_changed); \ No newline at end of file diff --git a/app/src/events/battery_state_changed.c b/app/src/events/battery_state_changed.c index ed6147a0..435fb24d 100644 --- a/app/src/events/battery_state_changed.c +++ b/app/src/events/battery_state_changed.c @@ -7,4 +7,4 @@ #include #include -ZMK_EVENT_IMPL(battery_state_changed); \ No newline at end of file +ZMK_EVENT_IMPL(zmk_battery_state_changed); \ No newline at end of file diff --git a/app/src/events/ble_active_profile_changed.c b/app/src/events/ble_active_profile_changed.c index e2d172fd..c4887f73 100644 --- a/app/src/events/ble_active_profile_changed.c +++ b/app/src/events/ble_active_profile_changed.c @@ -7,4 +7,4 @@ #include #include -ZMK_EVENT_IMPL(ble_active_profile_changed); \ No newline at end of file +ZMK_EVENT_IMPL(zmk_ble_active_profile_changed); \ No newline at end of file diff --git a/app/src/events/keycode_state_changed.c b/app/src/events/keycode_state_changed.c index d46126be..c9ef6aa7 100644 --- a/app/src/events/keycode_state_changed.c +++ b/app/src/events/keycode_state_changed.c @@ -7,4 +7,4 @@ #include #include -ZMK_EVENT_IMPL(keycode_state_changed); +ZMK_EVENT_IMPL(zmk_keycode_state_changed); diff --git a/app/src/events/layer_state_changed.c b/app/src/events/layer_state_changed.c index e7f8039c..bd6234c9 100644 --- a/app/src/events/layer_state_changed.c +++ b/app/src/events/layer_state_changed.c @@ -7,4 +7,4 @@ #include #include -ZMK_EVENT_IMPL(layer_state_changed); \ No newline at end of file +ZMK_EVENT_IMPL(zmk_layer_state_changed); \ No newline at end of file diff --git a/app/src/events/modifiers_state_changed.c b/app/src/events/modifiers_state_changed.c index 4143796e..3dfea25f 100644 --- a/app/src/events/modifiers_state_changed.c +++ b/app/src/events/modifiers_state_changed.c @@ -7,4 +7,4 @@ #include #include -ZMK_EVENT_IMPL(modifiers_state_changed); \ No newline at end of file +ZMK_EVENT_IMPL(zmk_modifiers_state_changed); \ No newline at end of file diff --git a/app/src/events/position_state_changed.c b/app/src/events/position_state_changed.c index b80314b9..bb40584e 100644 --- a/app/src/events/position_state_changed.c +++ b/app/src/events/position_state_changed.c @@ -7,4 +7,4 @@ #include #include -ZMK_EVENT_IMPL(position_state_changed); \ No newline at end of file +ZMK_EVENT_IMPL(zmk_position_state_changed); \ No newline at end of file diff --git a/app/src/events/sensor_event.c b/app/src/events/sensor_event.c index 6811e7dd..94ade947 100644 --- a/app/src/events/sensor_event.c +++ b/app/src/events/sensor_event.c @@ -7,4 +7,4 @@ #include #include -ZMK_EVENT_IMPL(sensor_event); \ No newline at end of file +ZMK_EVENT_IMPL(zmk_sensor_event); \ No newline at end of file diff --git a/app/src/events/usb_conn_state_changed.c b/app/src/events/usb_conn_state_changed.c index c299da7a..b3555569 100644 --- a/app/src/events/usb_conn_state_changed.c +++ b/app/src/events/usb_conn_state_changed.c @@ -7,4 +7,4 @@ #include #include -ZMK_EVENT_IMPL(usb_conn_state_changed); \ No newline at end of file +ZMK_EVENT_IMPL(zmk_usb_conn_state_changed); \ No newline at end of file diff --git a/app/src/events/wpm_state_changed.c b/app/src/events/wpm_state_changed.c new file mode 100644 index 00000000..3d9830bf --- /dev/null +++ b/app/src/events/wpm_state_changed.c @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include + +ZMK_EVENT_IMPL(zmk_wpm_state_changed); \ No newline at end of file diff --git a/app/src/hid.c b/app/src/hid.c index 37378b45..7ab080e5 100644 --- a/app/src/hid.c +++ b/app/src/hid.c @@ -26,6 +26,8 @@ static zmk_mod_flags_t explicit_modifiers = 0; LOG_DBG("Modifiers set to 0x%02X", keyboard_report.body.modifiers); \ } +zmk_mod_flags_t zmk_hid_get_explicit_mods() { return explicit_modifiers; } + int zmk_hid_register_mod(zmk_mod_t modifier) { explicit_modifier_counts[modifier]++; LOG_DBG("Modifier %d count %d", modifier, explicit_modifier_counts[modifier]); @@ -49,13 +51,33 @@ int zmk_hid_unregister_mod(zmk_mod_t modifier) { return 0; } +int zmk_hid_register_mods(zmk_mod_flags_t modifiers) { + for (zmk_mod_t i = 0; i < 8; i++) { + if (modifiers & (1 << i)) { + zmk_hid_register_mod(i); + } + } + return 0; +} + +int zmk_hid_unregister_mods(zmk_mod_flags_t modifiers) { + for (zmk_mod_t i = 0; i < 8; i++) { + if (modifiers & (1 << i)) { + zmk_hid_unregister_mod(i); + } + } + return 0; +} + #define TOGGLE_KEYBOARD(match, val) \ for (int idx = 0; idx < ZMK_HID_KEYBOARD_NKRO_SIZE; idx++) { \ if (keyboard_report.body.keys[idx] != match) { \ continue; \ } \ keyboard_report.body.keys[idx] = val; \ - break; \ + if (val) { \ + break; \ + } \ } #define TOGGLE_CONSUMER(match, val) \ @@ -64,7 +86,9 @@ int zmk_hid_unregister_mod(zmk_mod_t modifier) { continue; \ } \ consumer_report.body.keys[idx] = val; \ - break; \ + if (val) { \ + break; \ + } \ } int zmk_hid_implicit_modifiers_press(zmk_mod_flags_t implicit_modifiers) { diff --git a/app/src/hid_listener.c b/app/src/hid_listener.c index 6537ccab..d582c169 100644 --- a/app/src/hid_listener.c +++ b/app/src/hid_listener.c @@ -16,71 +16,71 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include -static int hid_listener_keycode_pressed(uint16_t usage_page, uint32_t keycode, - zmk_mod_flags_t implicit_modifiers) { +static int hid_listener_keycode_pressed(const struct zmk_keycode_state_changed *ev) { int err; - LOG_DBG("usage_page 0x%02X keycode 0x%02X mods 0x%02X", usage_page, keycode, - implicit_modifiers); - switch (usage_page) { + LOG_DBG("usage_page 0x%02X keycode 0x%02X implicit_mods 0x%02X explicit_mods 0x%02X", + ev->usage_page, ev->keycode, ev->implicit_modifiers, ev->explicit_modifiers); + switch (ev->usage_page) { case HID_USAGE_KEY: - err = zmk_hid_keyboard_press(keycode); + err = zmk_hid_keyboard_press(ev->keycode); if (err) { LOG_ERR("Unable to press keycode"); return err; } break; case HID_USAGE_CONSUMER: - err = zmk_hid_consumer_press(keycode); + err = zmk_hid_consumer_press(ev->keycode); if (err) { LOG_ERR("Unable to press keycode"); return err; } break; } - zmk_hid_implicit_modifiers_press(implicit_modifiers); - return zmk_endpoints_send_report(usage_page); + zmk_hid_register_mods(ev->explicit_modifiers); + zmk_hid_implicit_modifiers_press(ev->implicit_modifiers); + return zmk_endpoints_send_report(ev->usage_page); } -static int hid_listener_keycode_released(uint16_t usage_page, uint32_t keycode, - zmk_mod_flags_t implicit_modifiers) { +static int hid_listener_keycode_released(const struct zmk_keycode_state_changed *ev) { int err; - LOG_DBG("usage_page 0x%02X keycode 0x%02X mods 0x%02X", usage_page, keycode, - implicit_modifiers); - switch (usage_page) { + LOG_DBG("usage_page 0x%02X keycode 0x%02X implicit_mods 0x%02X explicit_mods 0x%02X", + ev->usage_page, ev->keycode, ev->implicit_modifiers, ev->explicit_modifiers); + switch (ev->usage_page) { case HID_USAGE_KEY: - err = zmk_hid_keyboard_release(keycode); + err = zmk_hid_keyboard_release(ev->keycode); if (err) { LOG_ERR("Unable to release keycode"); return err; } break; case HID_USAGE_CONSUMER: - err = zmk_hid_consumer_release(keycode); + err = zmk_hid_consumer_release(ev->keycode); if (err) { LOG_ERR("Unable to release keycode"); return err; } } + zmk_hid_unregister_mods(ev->explicit_modifiers); // There is a minor issue with this code. // If LC(A) is pressed, then LS(B), then LC(A) is released, the shift for B will be released // prematurely. This causes if LS(B) to repeat like Bbbbbbbb when pressed for a long time. // Solving this would require keeping track of which key's implicit modifiers are currently // active and only releasing modifiers at that time. zmk_hid_implicit_modifiers_release(); - return zmk_endpoints_send_report(usage_page); + return zmk_endpoints_send_report(ev->usage_page); } -int hid_listener(const struct zmk_event_header *eh) { - if (is_keycode_state_changed(eh)) { - const struct keycode_state_changed *ev = cast_keycode_state_changed(eh); +int hid_listener(const zmk_event_t *eh) { + const struct zmk_keycode_state_changed *ev = as_zmk_keycode_state_changed(eh); + if (ev) { if (ev->state) { - hid_listener_keycode_pressed(ev->usage_page, ev->keycode, ev->implicit_modifiers); + hid_listener_keycode_pressed(ev); } else { - hid_listener_keycode_released(ev->usage_page, ev->keycode, ev->implicit_modifiers); + hid_listener_keycode_released(ev); } } return 0; } ZMK_LISTENER(hid_listener, hid_listener); -ZMK_SUBSCRIPTION(hid_listener, keycode_state_changed); \ No newline at end of file +ZMK_SUBSCRIPTION(hid_listener, zmk_keycode_state_changed); \ No newline at end of file diff --git a/app/src/hog.c b/app/src/hog.c index 8d10b8f7..07343097 100644 --- a/app/src/hog.c +++ b/app/src/hog.c @@ -5,6 +5,7 @@ */ #include +#include #include @@ -156,28 +157,115 @@ struct bt_conn *destination_connection() { return conn; } +K_THREAD_STACK_DEFINE(hog_q_stack, CONFIG_ZMK_BLE_THREAD_STACK_SIZE); + +struct k_work_q hog_work_q; + +K_MSGQ_DEFINE(zmk_hog_keyboard_msgq, sizeof(struct zmk_hid_keyboard_report_body), + CONFIG_ZMK_BLE_KEYBOARD_REPORT_QUEUE_SIZE, 4); + +void send_keyboard_report_callback(struct k_work *work) { + struct zmk_hid_keyboard_report_body report; + + while (k_msgq_get(&zmk_hog_keyboard_msgq, &report, K_NO_WAIT) == 0) { + struct bt_conn *conn = destination_connection(); + if (conn == NULL) { + return; + } + + struct bt_gatt_notify_params notify_params = { + .attr = &hog_svc.attrs[5], + .data = &report, + .len = sizeof(report), + }; + + int err = bt_gatt_notify_cb(conn, ¬ify_params); + if (err) { + LOG_ERR("Error notifying %d", err); + } + + bt_conn_unref(conn); + } +} + +K_WORK_DEFINE(hog_keyboard_work, send_keyboard_report_callback); + int zmk_hog_send_keyboard_report(struct zmk_hid_keyboard_report_body *report) { - struct bt_conn *conn = destination_connection(); - if (conn == NULL) { - return -ENOTCONN; + int err = k_msgq_put(&zmk_hog_keyboard_msgq, report, K_MSEC(100)); + if (err) { + switch (err) { + case -EAGAIN: { + LOG_WRN("Keyboard message queue full, popping first message and queueing again"); + struct zmk_hid_keyboard_report_body discarded_report; + k_msgq_get(&zmk_hog_keyboard_msgq, &discarded_report, K_NO_WAIT); + return zmk_hog_send_keyboard_report(report); + } + default: + LOG_WRN("Failed to queue keyboard report to send (%d)", err); + return err; + } } - LOG_DBG("Sending to NULL? %s", conn == NULL ? "yes" : "no"); + k_work_submit_to_queue(&hog_work_q, &hog_keyboard_work); - int err = bt_gatt_notify(conn, &hog_svc.attrs[5], report, - sizeof(struct zmk_hid_keyboard_report_body)); - bt_conn_unref(conn); - return err; + return 0; }; +K_MSGQ_DEFINE(zmk_hog_consumer_msgq, sizeof(struct zmk_hid_consumer_report_body), + CONFIG_ZMK_BLE_CONSUMER_REPORT_QUEUE_SIZE, 4); + +void send_consumer_report_callback(struct k_work *work) { + struct zmk_hid_consumer_report_body report; + + while (k_msgq_get(&zmk_hog_consumer_msgq, &report, K_NO_WAIT) == 0) { + struct bt_conn *conn = destination_connection(); + if (conn == NULL) { + return; + } + + struct bt_gatt_notify_params notify_params = { + .attr = &hog_svc.attrs[10], + .data = &report, + .len = sizeof(report), + }; + + int err = bt_gatt_notify_cb(conn, ¬ify_params); + if (err) { + LOG_DBG("Error notifying %d", err); + } + + bt_conn_unref(conn); + } +}; + +K_WORK_DEFINE(hog_consumer_work, send_consumer_report_callback); + int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *report) { - struct bt_conn *conn = destination_connection(); - if (conn == NULL) { - return -ENOTCONN; + int err = k_msgq_put(&zmk_hog_consumer_msgq, report, K_MSEC(100)); + if (err) { + switch (err) { + case -EAGAIN: { + LOG_WRN("Consumer message queue full, popping first message and queueing again"); + struct zmk_hid_consumer_report_body discarded_report; + k_msgq_get(&zmk_hog_consumer_msgq, &discarded_report, K_NO_WAIT); + return zmk_hog_send_consumer_report(report); + } + default: + LOG_WRN("Failed to queue consumer report to send (%d)", err); + return err; + } } - int err = bt_gatt_notify(conn, &hog_svc.attrs[10], report, - sizeof(struct zmk_hid_consumer_report_body)); - bt_conn_unref(conn); - return err; + k_work_submit_to_queue(&hog_work_q, &hog_consumer_work); + + return 0; }; + +int zmk_hog_init(const struct device *_arg) { + k_work_q_start(&hog_work_q, hog_q_stack, K_THREAD_STACK_SIZEOF(hog_q_stack), + CONFIG_ZMK_BLE_THREAD_PRIORITY); + + return 0; +} + +SYS_INIT(zmk_hog_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY); diff --git a/app/src/keymap.c b/app/src/keymap.c index 322a9369..75ec6bf4 100644 --- a/app/src/keymap.c +++ b/app/src/keymap.c @@ -28,18 +28,10 @@ static uint8_t _zmk_keymap_layer_default = 0; #define ZMK_KEYMAP_NODE DT_DRV_INST(0) #define ZMK_KEYMAP_LAYERS_LEN (DT_INST_FOREACH_CHILD(0, LAYER_CHILD_LEN) 0) -#define LAYER_NODE(l) DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, l) +#define BINDING_WITH_COMMA(idx, drv_inst) ZMK_KEYMAP_EXTRACT_BINDING(idx, drv_inst), -#define _TRANSFORM_ENTRY(idx, layer) \ - { \ - .behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(layer, bindings, idx)), \ - .param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(layer, bindings, idx, param1), (0), \ - (DT_PHA_BY_IDX(layer, bindings, idx, param1))), \ - .param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(layer, bindings, idx, param2), (0), \ - (DT_PHA_BY_IDX(layer, bindings, idx, param2))), \ - }, - -#define TRANSFORMED_LAYER(node) {UTIL_LISTIFY(DT_PROP_LEN(node, bindings), _TRANSFORM_ENTRY, node)}, +#define TRANSFORMED_LAYER(node) \ + {UTIL_LISTIFY(DT_PROP_LEN(node, bindings), BINDING_WITH_COMMA, node)}, #if ZMK_KEYMAP_HAS_SENSORS #define _TRANSFORM_SENSOR_ENTRY(idx, layer) \ @@ -246,23 +238,27 @@ int zmk_keymap_sensor_triggered(uint8_t sensor_number, const struct device *sens #endif /* ZMK_KEYMAP_HAS_SENSORS */ -int keymap_listener(const struct zmk_event_header *eh) { - if (is_position_state_changed(eh)) { - const struct position_state_changed *ev = cast_position_state_changed(eh); - return zmk_keymap_position_state_changed(ev->position, ev->state, ev->timestamp); -#if ZMK_KEYMAP_HAS_SENSORS - } else if (is_sensor_event(eh)) { - const struct sensor_event *ev = cast_sensor_event(eh); - return zmk_keymap_sensor_triggered(ev->sensor_number, ev->sensor, ev->timestamp); -#endif /* ZMK_KEYMAP_HAS_SENSORS */ +int keymap_listener(const zmk_event_t *eh) { + const struct zmk_position_state_changed *pos_ev; + if ((pos_ev = as_zmk_position_state_changed(eh)) != NULL) { + return zmk_keymap_position_state_changed(pos_ev->position, pos_ev->state, + pos_ev->timestamp); } +#if ZMK_KEYMAP_HAS_SENSORS + const struct zmk_sensor_event *sensor_ev; + if ((sensor_ev = as_zmk_sensor_event(eh)) != NULL) { + return zmk_keymap_sensor_triggered(sensor_ev->sensor_number, sensor_ev->sensor, + sensor_ev->timestamp); + } +#endif /* ZMK_KEYMAP_HAS_SENSORS */ + return -ENOTSUP; } ZMK_LISTENER(keymap, keymap_listener); -ZMK_SUBSCRIPTION(keymap, position_state_changed); +ZMK_SUBSCRIPTION(keymap, zmk_position_state_changed); #if ZMK_KEYMAP_HAS_SENSORS -ZMK_SUBSCRIPTION(keymap, sensor_event); +ZMK_SUBSCRIPTION(keymap, zmk_sensor_event); #endif /* ZMK_KEYMAP_HAS_SENSORS */ diff --git a/app/src/kscan.c b/app/src/kscan.c index 6b84490a..0c128b2d 100644 --- a/app/src/kscan.c +++ b/app/src/kscan.c @@ -47,14 +47,10 @@ void zmk_kscan_process_msgq(struct k_work *item) { while (k_msgq_get(&zmk_kscan_msgq, &ev, K_NO_WAIT) == 0) { bool pressed = (ev.state == ZMK_KSCAN_EVENT_STATE_PRESSED); uint32_t position = zmk_matrix_transform_row_column_to_position(ev.row, ev.column); - struct position_state_changed *pos_ev; LOG_DBG("Row: %d, col: %d, position: %d, pressed: %s\n", ev.row, ev.column, position, (pressed ? "true" : "false")); - pos_ev = new_position_state_changed(); - pos_ev->state = pressed; - pos_ev->position = position; - pos_ev->timestamp = k_uptime_get(); - ZMK_EVENT_RAISE(pos_ev); + ZMK_EVENT_RAISE(new_zmk_position_state_changed((struct zmk_position_state_changed){ + .state = pressed, .position = position, .timestamp = k_uptime_get()})); } } diff --git a/app/src/sensors.c b/app/src/sensors.c index 5e9ef150..dd5f4267 100644 --- a/app/src/sensors.c +++ b/app/src/sensors.c @@ -35,7 +35,6 @@ static struct sensors_data_item sensors[] = {UTIL_LISTIFY(ZMK_KEYMAP_SENSORS_LEN static void zmk_sensors_trigger_handler(const struct device *dev, struct sensor_trigger *trigger) { int err; struct sensors_data_item *item = CONTAINER_OF(trigger, struct sensors_data_item, trigger); - struct sensor_event *event; LOG_DBG("sensor %d", item->sensor_number); @@ -45,12 +44,8 @@ static void zmk_sensors_trigger_handler(const struct device *dev, struct sensor_ return; } - event = new_sensor_event(); - event->sensor_number = item->sensor_number; - event->sensor = dev; - event->timestamp = k_uptime_get(); - - ZMK_EVENT_RAISE(event); + ZMK_EVENT_RAISE(new_zmk_sensor_event((struct zmk_sensor_event){ + .sensor_number = item->sensor_number, .sensor = dev, .timestamp = k_uptime_get()})); } static void zmk_sensors_init_item(const char *node, uint8_t i, uint8_t abs_i) { diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c index 5ad83ad2..a56b0b81 100644 --- a/app/src/split/bluetooth/central.c +++ b/app/src/split/bluetooth/central.c @@ -33,6 +33,19 @@ static struct bt_uuid_128 uuid = BT_UUID_INIT_128(ZMK_SPLIT_BT_SERVICE_UUID); static struct bt_gatt_discover_params discover_params; static struct bt_gatt_subscribe_params subscribe_params; +K_MSGQ_DEFINE(peripheral_event_msgq, sizeof(struct zmk_position_state_changed), + CONFIG_ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE, 4); + +void peripheral_event_work_callback(struct k_work *work) { + struct zmk_position_state_changed ev; + while (k_msgq_get(&peripheral_event_msgq, &ev, K_NO_WAIT) == 0) { + LOG_DBG("Trigger key position state change for %d", ev.position); + ZMK_EVENT_RAISE(new_zmk_position_state_changed(ev)); + } +} + +K_WORK_DEFINE(peripheral_event_work, peripheral_event_work_callback); + static uint8_t split_central_notify_func(struct bt_conn *conn, struct bt_gatt_subscribe_params *params, const void *data, uint16_t length) { @@ -58,13 +71,11 @@ static uint8_t split_central_notify_func(struct bt_conn *conn, if (changed_positions[i] & BIT(j)) { uint32_t position = (i * 8) + j; bool pressed = position_state[i] & BIT(j); - struct position_state_changed *pos_ev = new_position_state_changed(); - pos_ev->position = position; - pos_ev->state = pressed; - pos_ev->timestamp = k_uptime_get(); + struct zmk_position_state_changed ev = { + .position = position, .state = pressed, .timestamp = k_uptime_get()}; - LOG_DBG("Trigger key position state change for %d", position); - ZMK_EVENT_RAISE(pos_ev); + k_msgq_put(&peripheral_event_msgq, &ev, K_NO_WAIT); + k_work_submit(&peripheral_event_work); } } } @@ -321,4 +332,4 @@ int zmk_split_bt_central_init(const struct device *_arg) { return start_scan(); } -SYS_INIT(zmk_split_bt_central_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY); \ No newline at end of file +SYS_INIT(zmk_split_bt_central_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY); diff --git a/app/src/split/bluetooth/service.c b/app/src/split/bluetooth/service.c index 48390849..fbac6446 100644 --- a/app/src/split/bluetooth/service.c +++ b/app/src/split/bluetooth/service.c @@ -6,6 +6,7 @@ #include #include +#include #include @@ -18,8 +19,10 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include +#define POS_STATE_LEN 16 + static uint8_t num_of_positions = ZMK_KEYMAP_LEN; -static uint8_t position_state[16]; +static uint8_t position_state[POS_STATE_LEN]; static ssize_t split_svc_pos_state(struct bt_conn *conn, const struct bt_gatt_attr *attrs, void *buf, uint16_t len, uint16_t offset) { @@ -45,12 +48,62 @@ BT_GATT_SERVICE_DEFINE( BT_GATT_DESCRIPTOR(BT_UUID_NUM_OF_DIGITALS, BT_GATT_PERM_READ, split_svc_num_of_positions, NULL, &num_of_positions), ); +K_THREAD_STACK_DEFINE(service_q_stack, CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE); + +struct k_work_q service_work_q; + +K_MSGQ_DEFINE(position_state_msgq, sizeof(char[POS_STATE_LEN]), + CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE, 4); + +void send_position_state_callback(struct k_work *work) { + uint8_t state[POS_STATE_LEN]; + + while (k_msgq_get(&position_state_msgq, &state, K_NO_WAIT) == 0) { + int err = bt_gatt_notify(NULL, &split_svc.attrs[1], &state, sizeof(state)); + if (err) { + LOG_DBG("Error notifying %d", err); + } + } +}; + +K_WORK_DEFINE(service_position_notify_work, send_position_state_callback); + +int send_position_state() { + int err = k_msgq_put(&position_state_msgq, position_state, K_MSEC(100)); + if (err) { + switch (err) { + case -EAGAIN: { + LOG_WRN("Position state message queue full, popping first message and queueing again"); + uint8_t discarded_state[POS_STATE_LEN]; + k_msgq_get(&position_state_msgq, &discarded_state, K_NO_WAIT); + return send_position_state(); + } + default: + LOG_WRN("Failed to queue position state to send (%d)", err); + return err; + } + } + + k_work_submit_to_queue(&service_work_q, &service_position_notify_work); + + return 0; +} + int zmk_split_bt_position_pressed(uint8_t position) { WRITE_BIT(position_state[position / 8], position % 8, true); - return bt_gatt_notify(NULL, &split_svc.attrs[1], &position_state, sizeof(position_state)); + return send_position_state(); } int zmk_split_bt_position_released(uint8_t position) { WRITE_BIT(position_state[position / 8], position % 8, false); - return bt_gatt_notify(NULL, &split_svc.attrs[1], &position_state, sizeof(position_state)); -} \ No newline at end of file + return send_position_state(); +} + +int service_init(const struct device *_arg) { + k_work_q_start(&service_work_q, service_q_stack, K_THREAD_STACK_SIZEOF(service_q_stack), + CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_PRIORITY); + + return 0; +} + +SYS_INIT(service_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY); diff --git a/app/src/split_listener.c b/app/src/split_listener.c index f475002c..8ac56c9f 100644 --- a/app/src/split_listener.c +++ b/app/src/split_listener.c @@ -19,10 +19,10 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); #include #include -int split_listener(const struct zmk_event_header *eh) { +int split_listener(const zmk_event_t *eh) { LOG_DBG(""); - if (is_position_state_changed(eh)) { - const struct position_state_changed *ev = cast_position_state_changed(eh); + const struct zmk_position_state_changed *ev = as_zmk_position_state_changed(eh); + if (ev != NULL) { if (ev->state) { return zmk_split_bt_position_pressed(ev->position); } else { @@ -33,4 +33,4 @@ int split_listener(const struct zmk_event_header *eh) { } ZMK_LISTENER(split_listener, split_listener); -ZMK_SUBSCRIPTION(split_listener, position_state_changed); \ No newline at end of file +ZMK_SUBSCRIPTION(split_listener, zmk_position_state_changed); \ No newline at end of file diff --git a/app/src/usb.c b/app/src/usb.c index 7900acef..c2f61a5b 100644 --- a/app/src/usb.c +++ b/app/src/usb.c @@ -55,10 +55,8 @@ int zmk_usb_hid_send_report(const uint8_t *report, size_t len) { #endif /* CONFIG_ZMK_USB */ static void raise_usb_status_changed_event() { - struct usb_conn_state_changed *ev = new_usb_conn_state_changed(); - ev->conn_state = zmk_usb_get_conn_state(); - - ZMK_EVENT_RAISE(ev); + ZMK_EVENT_RAISE(new_zmk_usb_conn_state_changed( + (struct zmk_usb_conn_state_changed){.conn_state = zmk_usb_get_conn_state()})); } enum usb_dc_status_code zmk_usb_get_status() { return usb_status; } diff --git a/app/src/wpm.c b/app/src/wpm.c new file mode 100644 index 00000000..bcabf377 --- /dev/null +++ b/app/src/wpm.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include + +#include + +LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); + +#include +#include +#include + +#include + +#define WPM_UPDATE_INTERVAL_SECONDS 1 +#define WPM_RESET_INTERVAL_SECONDS 5 + +// See https://en.wikipedia.org/wiki/Words_per_minute +// "Since the length or duration of words is clearly variable, for the purpose of measurement of +// text entry, the definition of each "word" is often standardized to be five characters or +// keystrokes long in English" +#define CHARS_PER_WORD 5.0 + +static uint8_t wpm_state = -1; +static uint8_t last_wpm_state; +static uint8_t wpm_update_counter; +static uint32_t key_pressed_count; + +int zmk_wpm_get_state() { return wpm_state; } + +int wpm_event_listener(const zmk_event_t *eh) { + const struct zmk_keycode_state_changed *ev = as_zmk_keycode_state_changed(eh); + if (ev) { + // count only key up events + if (!ev->state) { + key_pressed_count++; + LOG_DBG("key_pressed_count %d keycode %d", key_pressed_count, ev->keycode); + } + } + return 0; +} + +void wpm_work_handler(struct k_work *work) { + wpm_update_counter++; + wpm_state = (key_pressed_count / CHARS_PER_WORD) / + (wpm_update_counter * WPM_UPDATE_INTERVAL_SECONDS / 60.0); + + if (last_wpm_state != wpm_state) { + LOG_DBG("Raised WPM state changed %d wpm_update_counter %d", wpm_state, wpm_update_counter); + + ZMK_EVENT_RAISE( + new_zmk_wpm_state_changed((struct zmk_wpm_state_changed){.state = wpm_state})); + + last_wpm_state = wpm_state; + } + + if (wpm_update_counter >= WPM_RESET_INTERVAL_SECONDS) { + wpm_update_counter = 0; + key_pressed_count = 0; + } +} + +K_WORK_DEFINE(wpm_work, wpm_work_handler); + +void wpm_expiry_function() { k_work_submit(&wpm_work); } + +K_TIMER_DEFINE(wpm_timer, wpm_expiry_function, NULL); + +int wpm_init() { + wpm_state = 0; + wpm_update_counter = 0; + k_timer_start(&wpm_timer, K_SECONDS(WPM_UPDATE_INTERVAL_SECONDS), + K_SECONDS(WPM_UPDATE_INTERVAL_SECONDS)); + return 0; +} + +ZMK_LISTENER(wpm, wpm_event_listener); +ZMK_SUBSCRIPTION(wpm, zmk_keycode_state_changed); + +SYS_INIT(wpm_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); diff --git a/app/tests/combo/combos-and-holdtaps-0/keycode_events.snapshot b/app/tests/combo/combos-and-holdtaps-0/keycode_events.snapshot index ad86b269..e1c02dae 100644 --- a/app/tests/combo/combos-and-holdtaps-0/keycode_events.snapshot +++ b/app/tests/combo/combos-and-holdtaps-0/keycode_events.snapshot @@ -1,4 +1,4 @@ -pressed: usage_page 0x07 keycode 0xe0 mods 0x00 -pressed: usage_page 0x07 keycode 0x1c mods 0x00 -released: usage_page 0x07 keycode 0xe0 mods 0x00 -released: usage_page 0x07 keycode 0x1c mods 0x00 +pressed: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/combo/combos-and-holdtaps-1/keycode_events.snapshot b/app/tests/combo/combos-and-holdtaps-1/keycode_events.snapshot index dc4dbb49..ff060370 100644 --- a/app/tests/combo/combos-and-holdtaps-1/keycode_events.snapshot +++ b/app/tests/combo/combos-and-holdtaps-1/keycode_events.snapshot @@ -1,4 +1,4 @@ -pressed: usage_page 0x07 keycode 0x1c mods 0x00 -pressed: usage_page 0x07 keycode 0x06 mods 0x00 -released: usage_page 0x07 keycode 0x1c mods 0x00 -released: usage_page 0x07 keycode 0x06 mods 0x00 +pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/combo/combos-and-holdtaps-2/keycode_events.snapshot b/app/tests/combo/combos-and-holdtaps-2/keycode_events.snapshot index a6508804..325549fb 100644 --- a/app/tests/combo/combos-and-holdtaps-2/keycode_events.snapshot +++ b/app/tests/combo/combos-and-holdtaps-2/keycode_events.snapshot @@ -1,2 +1,2 @@ -pressed: usage_page 0x07 keycode 0xe0 mods 0x00 -pressed: usage_page 0x07 keycode 0xe4 mods 0x00 +pressed: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/combo/multiple-timeouts/keycode_events.snapshot b/app/tests/combo/multiple-timeouts/keycode_events.snapshot index c5bdd6e0..bb47d852 100644 --- a/app/tests/combo/multiple-timeouts/keycode_events.snapshot +++ b/app/tests/combo/multiple-timeouts/keycode_events.snapshot @@ -1,4 +1,4 @@ -pressed: usage_page 0x07 keycode 0x04 mods 0x00 -pressed: usage_page 0x07 keycode 0x05 mods 0x00 -released: usage_page 0x07 keycode 0x04 mods 0x00 -released: usage_page 0x07 keycode 0x05 mods 0x00 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/combo/overlapping-combos-0/keycode_events.snapshot b/app/tests/combo/overlapping-combos-0/keycode_events.snapshot index ec63b77f..cc5b30f8 100644 --- a/app/tests/combo/overlapping-combos-0/keycode_events.snapshot +++ b/app/tests/combo/overlapping-combos-0/keycode_events.snapshot @@ -1,20 +1,20 @@ -pressed: usage_page 0x07 keycode 0x1b mods 0x00 -released: usage_page 0x07 keycode 0x1b mods 0x00 -pressed: usage_page 0x07 keycode 0x1b mods 0x00 -released: usage_page 0x07 keycode 0x1b mods 0x00 -pressed: usage_page 0x07 keycode 0x1b mods 0x00 -released: usage_page 0x07 keycode 0x1b mods 0x00 -pressed: usage_page 0x07 keycode 0x1b mods 0x00 -released: usage_page 0x07 keycode 0x1b mods 0x00 -pressed: usage_page 0x07 keycode 0x1b mods 0x00 -released: usage_page 0x07 keycode 0x1b mods 0x00 -pressed: usage_page 0x07 keycode 0x1b mods 0x00 -released: usage_page 0x07 keycode 0x1b mods 0x00 -pressed: usage_page 0x07 keycode 0x1c mods 0x00 -released: usage_page 0x07 keycode 0x1c mods 0x00 -pressed: usage_page 0x07 keycode 0x1c mods 0x00 -released: usage_page 0x07 keycode 0x1c mods 0x00 -pressed: usage_page 0x07 keycode 0x1c mods 0x00 -released: usage_page 0x07 keycode 0x1c mods 0x00 -pressed: usage_page 0x07 keycode 0x1c mods 0x00 -released: usage_page 0x07 keycode 0x1c mods 0x00 +pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/combo/overlapping-combos-1/keycode_events.snapshot b/app/tests/combo/overlapping-combos-1/keycode_events.snapshot index daf72478..a80db25c 100644 --- a/app/tests/combo/overlapping-combos-1/keycode_events.snapshot +++ b/app/tests/combo/overlapping-combos-1/keycode_events.snapshot @@ -1,8 +1,8 @@ -pressed: usage_page 0x07 keycode 0x1c mods 0x00 -released: usage_page 0x07 keycode 0x1c mods 0x00 -pressed: usage_page 0x07 keycode 0x1c mods 0x00 -released: usage_page 0x07 keycode 0x1c mods 0x00 -pressed: usage_page 0x07 keycode 0x1c mods 0x00 -released: usage_page 0x07 keycode 0x1c mods 0x00 -pressed: usage_page 0x07 keycode 0x1c mods 0x00 -released: usage_page 0x07 keycode 0x1c mods 0x00 +pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/combo/overlapping-combos-2/keycode_events.snapshot b/app/tests/combo/overlapping-combos-2/keycode_events.snapshot index dc4dbb49..ff060370 100644 --- a/app/tests/combo/overlapping-combos-2/keycode_events.snapshot +++ b/app/tests/combo/overlapping-combos-2/keycode_events.snapshot @@ -1,4 +1,4 @@ -pressed: usage_page 0x07 keycode 0x1c mods 0x00 -pressed: usage_page 0x07 keycode 0x06 mods 0x00 -released: usage_page 0x07 keycode 0x1c mods 0x00 -released: usage_page 0x07 keycode 0x06 mods 0x00 +pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/combo/overlapping-combos-3/keycode_events.snapshot b/app/tests/combo/overlapping-combos-3/keycode_events.snapshot index e0cb655e..3df81e52 100644 --- a/app/tests/combo/overlapping-combos-3/keycode_events.snapshot +++ b/app/tests/combo/overlapping-combos-3/keycode_events.snapshot @@ -1,4 +1,4 @@ -pressed: usage_page 0x07 keycode 0x04 mods 0x00 -pressed: usage_page 0x07 keycode 0x1c mods 0x00 -released: usage_page 0x07 keycode 0x04 mods 0x00 -released: usage_page 0x07 keycode 0x1c mods 0x00 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/combo/partially-overlapping-combos/keycode_events.snapshot b/app/tests/combo/partially-overlapping-combos/keycode_events.snapshot index adaa64bc..e6c88146 100644 --- a/app/tests/combo/partially-overlapping-combos/keycode_events.snapshot +++ b/app/tests/combo/partially-overlapping-combos/keycode_events.snapshot @@ -1,16 +1,16 @@ -pressed: usage_page 0x07 keycode 0x1b mods 0x00 -released: usage_page 0x07 keycode 0x1b mods 0x00 -pressed: usage_page 0x07 keycode 0x1b mods 0x00 -released: usage_page 0x07 keycode 0x1b mods 0x00 -pressed: usage_page 0x07 keycode 0x1b mods 0x00 -released: usage_page 0x07 keycode 0x1b mods 0x00 -pressed: usage_page 0x07 keycode 0x1b mods 0x00 -released: usage_page 0x07 keycode 0x1b mods 0x00 -pressed: usage_page 0x07 keycode 0x1c mods 0x00 -released: usage_page 0x07 keycode 0x1c mods 0x00 -pressed: usage_page 0x07 keycode 0x1c mods 0x00 -released: usage_page 0x07 keycode 0x1c mods 0x00 -pressed: usage_page 0x07 keycode 0x1c mods 0x00 -released: usage_page 0x07 keycode 0x1c mods 0x00 -pressed: usage_page 0x07 keycode 0x1c mods 0x00 -released: usage_page 0x07 keycode 0x1c mods 0x00 +pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1c implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/combo/press-release/keycode_events.snapshot b/app/tests/combo/press-release/keycode_events.snapshot index 01718e71..d0767ca4 100644 --- a/app/tests/combo/press-release/keycode_events.snapshot +++ b/app/tests/combo/press-release/keycode_events.snapshot @@ -1,8 +1,8 @@ -pressed: usage_page 0x07 keycode 0x06 mods 0x00 -released: usage_page 0x07 keycode 0x06 mods 0x00 -pressed: usage_page 0x07 keycode 0x06 mods 0x00 -released: usage_page 0x07 keycode 0x06 mods 0x00 -pressed: usage_page 0x07 keycode 0x06 mods 0x00 -released: usage_page 0x07 keycode 0x06 mods 0x00 -pressed: usage_page 0x07 keycode 0x06 mods 0x00 -released: usage_page 0x07 keycode 0x06 mods 0x00 +pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/combo/press-timeout/keycode_events.snapshot b/app/tests/combo/press-timeout/keycode_events.snapshot index c5bdd6e0..bb47d852 100644 --- a/app/tests/combo/press-timeout/keycode_events.snapshot +++ b/app/tests/combo/press-timeout/keycode_events.snapshot @@ -1,4 +1,4 @@ -pressed: usage_page 0x07 keycode 0x04 mods 0x00 -pressed: usage_page 0x07 keycode 0x05 mods 0x00 -released: usage_page 0x07 keycode 0x04 mods 0x00 -released: usage_page 0x07 keycode 0x05 mods 0x00 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/combo/press1-press2-release1-release2/keycode_events.snapshot b/app/tests/combo/press1-press2-release1-release2/keycode_events.snapshot index cfa02de2..0539a7ca 100644 --- a/app/tests/combo/press1-press2-release1-release2/keycode_events.snapshot +++ b/app/tests/combo/press1-press2-release1-release2/keycode_events.snapshot @@ -1,4 +1,4 @@ -pressed: usage_page 0x07 keycode 0x06 mods 0x00 -pressed: usage_page 0x07 keycode 0x07 mods 0x00 -released: usage_page 0x07 keycode 0x06 mods 0x00 -released: usage_page 0x07 keycode 0x07 mods 0x00 +pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/combo/press1-press2-release2-release1/keycode_events.snapshot b/app/tests/combo/press1-press2-release2-release1/keycode_events.snapshot index b55f09ba..c473ece0 100644 --- a/app/tests/combo/press1-press2-release2-release1/keycode_events.snapshot +++ b/app/tests/combo/press1-press2-release2-release1/keycode_events.snapshot @@ -1,4 +1,4 @@ -pressed: usage_page 0x07 keycode 0x06 mods 0x00 -pressed: usage_page 0x07 keycode 0x07 mods 0x00 -released: usage_page 0x07 keycode 0x07 mods 0x00 -released: usage_page 0x07 keycode 0x06 mods 0x00 +pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/combo/press1-release1-press2-release2/keycode_events.snapshot b/app/tests/combo/press1-release1-press2-release2/keycode_events.snapshot index c41dee8c..3c8dc138 100644 --- a/app/tests/combo/press1-release1-press2-release2/keycode_events.snapshot +++ b/app/tests/combo/press1-release1-press2-release2/keycode_events.snapshot @@ -1,4 +1,4 @@ -pressed: usage_page 0x07 keycode 0x06 mods 0x00 -released: usage_page 0x07 keycode 0x06 mods 0x00 -pressed: usage_page 0x07 keycode 0x07 mods 0x00 -released: usage_page 0x07 keycode 0x07 mods 0x00 +pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/combo/slowrelease-disabled/keycode_events.snapshot b/app/tests/combo/slowrelease-disabled/keycode_events.snapshot index c41dee8c..3c8dc138 100644 --- a/app/tests/combo/slowrelease-disabled/keycode_events.snapshot +++ b/app/tests/combo/slowrelease-disabled/keycode_events.snapshot @@ -1,4 +1,4 @@ -pressed: usage_page 0x07 keycode 0x06 mods 0x00 -released: usage_page 0x07 keycode 0x06 mods 0x00 -pressed: usage_page 0x07 keycode 0x07 mods 0x00 -released: usage_page 0x07 keycode 0x07 mods 0x00 +pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/combo/slowrelease-enabled/keycode_events.snapshot b/app/tests/combo/slowrelease-enabled/keycode_events.snapshot index cfa02de2..0539a7ca 100644 --- a/app/tests/combo/slowrelease-enabled/keycode_events.snapshot +++ b/app/tests/combo/slowrelease-enabled/keycode_events.snapshot @@ -1,4 +1,4 @@ -pressed: usage_page 0x07 keycode 0x06 mods 0x00 -pressed: usage_page 0x07 keycode 0x07 mods 0x00 -released: usage_page 0x07 keycode 0x06 mods 0x00 -released: usage_page 0x07 keycode 0x07 mods 0x00 +pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/gresc/gresc-press-release/events.patterns b/app/tests/gresc/gresc-press-release/events.patterns new file mode 100644 index 00000000..b1342af4 --- /dev/null +++ b/app/tests/gresc/gresc-press-release/events.patterns @@ -0,0 +1 @@ +s/.*hid_listener_keycode_//p diff --git a/app/tests/gresc/gresc-press-release/keycode_events.snapshot b/app/tests/gresc/gresc-press-release/keycode_events.snapshot new file mode 100644 index 00000000..7c4c32ca --- /dev/null +++ b/app/tests/gresc/gresc-press-release/keycode_events.snapshot @@ -0,0 +1,18 @@ +pressed: usage_page 0x07 keycode 0x29 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x29 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x35 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x35 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0xe3 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x35 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x35 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0xe3 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x35 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x35 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0xe3 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x35 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0xe3 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x35 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/gresc/gresc-press-release/native_posix.keymap b/app/tests/gresc/gresc-press-release/native_posix.keymap new file mode 100644 index 00000000..7ca3d77d --- /dev/null +++ b/app/tests/gresc/gresc-press-release/native_posix.keymap @@ -0,0 +1,49 @@ +#include +#include +#include + +/ { + keymap { + compatible = "zmk,keymap"; + label ="Default keymap"; + + default_layer { + bindings = < + &gresc &none + &kp LEFT_SHIFT &kp LEFT_GUI + >; + }; + }; +}; + +&kscan { + events = < + /* esc */ + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_RELEASE(0,0,10) + + /* ~ */ + ZMK_MOCK_PRESS(1,0,10) + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_RELEASE(0,0,10) + ZMK_MOCK_RELEASE(1,0,10) + + /* LGUI+` */ + ZMK_MOCK_PRESS(1,1,10) + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_RELEASE(0,0,10) + ZMK_MOCK_RELEASE(1,1,10) + + /* ~ */ + ZMK_MOCK_PRESS(1,0,10) + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_RELEASE(1,0,10) + ZMK_MOCK_RELEASE(0,0,10) + + /* LGUI+` */ + ZMK_MOCK_PRESS(1,1,10) + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_RELEASE(1,1,10) + ZMK_MOCK_RELEASE(0,0,10) + >; +}; \ No newline at end of file diff --git a/app/tests/gresc/gresc-two-instances/events.patterns b/app/tests/gresc/gresc-two-instances/events.patterns new file mode 100644 index 00000000..ef7b7955 --- /dev/null +++ b/app/tests/gresc/gresc-two-instances/events.patterns @@ -0,0 +1,2 @@ +s/.*hid_listener_keycode_//p +s/.*on_mod_morph_binding_/morph_binding_/p \ No newline at end of file diff --git a/app/tests/gresc/gresc-two-instances/keycode_events.snapshot b/app/tests/gresc/gresc-two-instances/keycode_events.snapshot new file mode 100644 index 00000000..4a640a45 --- /dev/null +++ b/app/tests/gresc/gresc-two-instances/keycode_events.snapshot @@ -0,0 +1,6 @@ +pressed: usage_page 0x07 keycode 0x29 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x29 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x35 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x35 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/gresc/gresc-two-instances/native_posix.keymap b/app/tests/gresc/gresc-two-instances/native_posix.keymap new file mode 100644 index 00000000..0c38721d --- /dev/null +++ b/app/tests/gresc/gresc-two-instances/native_posix.keymap @@ -0,0 +1,43 @@ +#include +#include +#include + +/* +This test checks nothing breaks if two grave-escapes are pressed at the same time. +If someone ever really needs two, they can make a second behavior definition. + +The second gresc that is pressed is ignored. +The first gresc that is released releases the key. +*/ + +/ { + keymap { + compatible = "zmk,keymap"; + label ="Default keymap"; + + default_layer { + bindings = < + &gresc &gresc + &kp LEFT_SHIFT &kp LEFT_GUI + >; + }; + }; +}; + +&kscan { + events = < + /* esc */ + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_PRESS(0,1,10) /* the second gresc is ignored */ + ZMK_MOCK_RELEASE(0,0,10) + ZMK_MOCK_RELEASE(0,1,10) /* the second gresc is ignored */ + + /* ~ */ + ZMK_MOCK_PRESS(1,0,10) + ZMK_MOCK_PRESS(0,1,10) + ZMK_MOCK_PRESS(0,0,10) /* the second gresc is ignored */ + ZMK_MOCK_RELEASE(1,0,10) + ZMK_MOCK_RELEASE(0,1,10) + ZMK_MOCK_RELEASE(0,0,10) /* the second gresc is ignored */ + >; +}; \ No newline at end of file diff --git a/app/tests/hold-tap/balanced/1-dn-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/1-dn-up/keycode_events.snapshot index c088e5e6..41344422 100644 --- a/app/tests/hold-tap/balanced/1-dn-up/keycode_events.snapshot +++ b/app/tests/hold-tap/balanced/1-dn-up/keycode_events.snapshot @@ -1,5 +1,5 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided tap (balanced event 0) -kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00 -kp_released: usage_page 0x07 keycode 0x09 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/balanced/2-dn-timer-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/2-dn-timer-up/keycode_events.snapshot index a8b5d1fe..f83b4086 100644 --- a/app/tests/hold-tap/balanced/2-dn-timer-up/keycode_events.snapshot +++ b/app/tests/hold-tap/balanced/2-dn-timer-up/keycode_events.snapshot @@ -1,5 +1,5 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (balanced event 3) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/keycode_events.snapshot index ca458c7b..ca744aac 100644 --- a/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/keycode_events.snapshot +++ b/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/keycode_events.snapshot @@ -1,7 +1,7 @@ -kp_pressed: usage_page 0x07 keycode 0xe4 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00 ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided tap (balanced event 0) -kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe4 mods 0x00 -kp_released: usage_page 0x07 keycode 0x09 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/keycode_events.snapshot index ef4dfa5f..c2bddc26 100644 --- a/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/keycode_events.snapshot +++ b/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/keycode_events.snapshot @@ -1,7 +1,7 @@ -kp_pressed: usage_page 0x07 keycode 0xe4 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00 ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (balanced event 3) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe4 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/keycode_events.snapshot index 70a3353d..6bef3460 100644 --- a/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/keycode_events.snapshot +++ b/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/keycode_events.snapshot @@ -1,7 +1,7 @@ -kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 ht_binding_pressed: 0 new undecided hold_tap -kp_released: usage_page 0x07 keycode 0x07 mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 ht_decide: 0 decided tap (balanced event 0) -kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00 -kp_released: usage_page 0x07 keycode 0x09 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot index 121f0071..5354ff74 100644 --- a/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot +++ b/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot @@ -1,7 +1,7 @@ -kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 ht_binding_pressed: 0 new undecided hold_tap -kp_released: usage_page 0x07 keycode 0x07 mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 ht_decide: 0 decided hold (balanced event 3) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/keycode_events.snapshot index ae9dcc96..10380651 100644 --- a/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/keycode_events.snapshot +++ b/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/keycode_events.snapshot @@ -1,10 +1,10 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (balanced event 3) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_pressed: 1 new undecided hold_tap ht_decide: 1 decided tap (balanced event 0) -kp_pressed: usage_page 0x07 keycode 0x0d mods 0x00 -kp_released: usage_page 0x07 keycode 0x0d mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x0d implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x0d implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 1 cleaning up hold-tap -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot index c1e03ad2..9d5a9e83 100644 --- a/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot +++ b/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot @@ -1,7 +1,7 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (balanced event 3) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot index 95330e69..190d95e0 100644 --- a/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot +++ b/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot @@ -1,7 +1,7 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (balanced event 2) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/keycode_events.snapshot b/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/keycode_events.snapshot index 95330e69..190d95e0 100644 --- a/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/keycode_events.snapshot +++ b/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/keycode_events.snapshot @@ -1,7 +1,7 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (balanced event 2) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot b/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot index 63219ee0..31089abf 100644 --- a/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot +++ b/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot @@ -1,7 +1,7 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided tap (balanced event 0) -kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00 -kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0x09 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap -kp_released: usage_page 0x07 keycode 0x07 mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/hold-tap/balanced/many-nested/keycode_events.snapshot b/app/tests/hold-tap/balanced/many-nested/keycode_events.snapshot index dda02ddf..4bd40a91 100644 --- a/app/tests/hold-tap/balanced/many-nested/keycode_events.snapshot +++ b/app/tests/hold-tap/balanced/many-nested/keycode_events.snapshot @@ -1,20 +1,20 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (balanced event 3) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_pressed: 1 new undecided hold_tap ht_decide: 1 decided hold (balanced event 3) -kp_pressed: usage_page 0x07 keycode 0xe0 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 ht_binding_pressed: 2 new undecided hold_tap ht_binding_released: 0 cleaning up hold-tap ht_decide: 2 decided hold (balanced event 3) -kp_pressed: usage_page 0x07 keycode 0xe3 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe3 implicit_mods 0x00 explicit_mods 0x00 ht_binding_pressed: 3 new undecided hold_tap ht_binding_released: 1 cleaning up hold-tap ht_decide: 3 decided hold (balanced event 3) -kp_pressed: usage_page 0x07 keycode 0xe2 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe0 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe3 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe2 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe3 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 2 cleaning up hold-tap -kp_released: usage_page 0x07 keycode 0xe2 mods 0x00 +kp_released: usage_page 0x07 keycode 0xe2 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 3 cleaning up hold-tap diff --git a/app/tests/hold-tap/hold-preferred/1-dn-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/1-dn-up/keycode_events.snapshot index 2eb64758..12c1a548 100644 --- a/app/tests/hold-tap/hold-preferred/1-dn-up/keycode_events.snapshot +++ b/app/tests/hold-tap/hold-preferred/1-dn-up/keycode_events.snapshot @@ -1,5 +1,5 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided tap (hold-preferred event 0) -kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00 -kp_released: usage_page 0x07 keycode 0x09 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/hold-preferred/2-dn-timer-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/2-dn-timer-up/keycode_events.snapshot index 86517aa3..291d17b1 100644 --- a/app/tests/hold-tap/hold-preferred/2-dn-timer-up/keycode_events.snapshot +++ b/app/tests/hold-tap/hold-preferred/2-dn-timer-up/keycode_events.snapshot @@ -1,5 +1,5 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (hold-preferred event 3) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot index b7434c65..2f8b72e7 100644 --- a/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot +++ b/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot @@ -1,7 +1,7 @@ -kp_pressed: usage_page 0x07 keycode 0xe4 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00 ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided tap (hold-preferred event 0) -kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe4 mods 0x00 -kp_released: usage_page 0x07 keycode 0x09 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot index ffb6aadd..73308626 100644 --- a/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot +++ b/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot @@ -1,7 +1,7 @@ -kp_pressed: usage_page 0x07 keycode 0xe4 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00 ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (hold-preferred event 3) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe4 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot index 1254fedd..45964250 100644 --- a/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot +++ b/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot @@ -1,7 +1,7 @@ -kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 ht_binding_pressed: 0 new undecided hold_tap -kp_released: usage_page 0x07 keycode 0x07 mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 ht_decide: 0 decided tap (hold-preferred event 0) -kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00 -kp_released: usage_page 0x07 keycode 0x09 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot index ba7b48b3..5d6d637e 100644 --- a/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot +++ b/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot @@ -1,7 +1,7 @@ -kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 ht_binding_pressed: 0 new undecided hold_tap -kp_released: usage_page 0x07 keycode 0x07 mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 ht_decide: 0 decided hold (hold-preferred event 3) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot index c8acfc17..92886a8c 100644 --- a/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot +++ b/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot @@ -1,10 +1,10 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (hold-preferred event 1) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_pressed: 1 new undecided hold_tap ht_decide: 1 decided tap (hold-preferred event 0) -kp_pressed: usage_page 0x07 keycode 0x0d mods 0x00 -kp_released: usage_page 0x07 keycode 0x0d mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x0d implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x0d implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 1 cleaning up hold-tap -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot index 97cd07bf..e2feeefc 100644 --- a/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot +++ b/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot @@ -1,7 +1,7 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (hold-preferred event 1) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot index 97cd07bf..e2feeefc 100644 --- a/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot +++ b/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot @@ -1,7 +1,7 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (hold-preferred event 1) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot index 97cd07bf..e2feeefc 100644 --- a/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot +++ b/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot @@ -1,7 +1,7 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (hold-preferred event 1) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot b/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot index 2a21d929..da5b8265 100644 --- a/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot +++ b/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot @@ -1,7 +1,7 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (hold-preferred event 1) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap -kp_released: usage_page 0x07 keycode 0x07 mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/hold-tap/tap-preferred/1-dn-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/1-dn-up/keycode_events.snapshot index 57e4fcd7..93b5ce29 100644 --- a/app/tests/hold-tap/tap-preferred/1-dn-up/keycode_events.snapshot +++ b/app/tests/hold-tap/tap-preferred/1-dn-up/keycode_events.snapshot @@ -1,5 +1,5 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided tap (tap-preferred event 0) -kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00 -kp_released: usage_page 0x07 keycode 0x09 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/tap-preferred/2-dn-timer-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/2-dn-timer-up/keycode_events.snapshot index 71ba8da4..3dccfd31 100644 --- a/app/tests/hold-tap/tap-preferred/2-dn-timer-up/keycode_events.snapshot +++ b/app/tests/hold-tap/tap-preferred/2-dn-timer-up/keycode_events.snapshot @@ -1,5 +1,5 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (tap-preferred event 3) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot index 0bc731f0..09d2f10e 100644 --- a/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot +++ b/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot @@ -1,7 +1,7 @@ -kp_pressed: usage_page 0x07 keycode 0xe4 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00 ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided tap (tap-preferred event 0) -kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe4 mods 0x00 -kp_released: usage_page 0x07 keycode 0x09 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot index 6a3398f4..c89aecfa 100644 --- a/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot +++ b/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot @@ -1,7 +1,7 @@ -kp_pressed: usage_page 0x07 keycode 0xe4 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00 ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (tap-preferred event 3) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe4 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot index e518582c..4211e851 100644 --- a/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot +++ b/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot @@ -1,7 +1,7 @@ -kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 ht_binding_pressed: 0 new undecided hold_tap -kp_released: usage_page 0x07 keycode 0x07 mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 ht_decide: 0 decided tap (tap-preferred event 0) -kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00 -kp_released: usage_page 0x07 keycode 0x09 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot index b3b06730..c149544a 100644 --- a/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot +++ b/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot @@ -1,7 +1,7 @@ -kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 ht_binding_pressed: 0 new undecided hold_tap -kp_released: usage_page 0x07 keycode 0x07 mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 ht_decide: 0 decided hold (tap-preferred event 3) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot index 7f454210..cf7db305 100644 --- a/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot +++ b/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot @@ -1,10 +1,10 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (tap-preferred event 3) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_pressed: 1 new undecided hold_tap ht_decide: 1 decided tap (tap-preferred event 0) -kp_pressed: usage_page 0x07 keycode 0x0d mods 0x00 -kp_released: usage_page 0x07 keycode 0x0d mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x0d implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x0d implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 1 cleaning up hold-tap -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot index ade0d3ea..95573b9b 100644 --- a/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot +++ b/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot @@ -1,7 +1,7 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (tap-preferred event 3) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot index ade0d3ea..95573b9b 100644 --- a/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot +++ b/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot @@ -1,7 +1,7 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided hold (tap-preferred event 3) -kp_pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0xe1 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot index 418312c3..38cce941 100644 --- a/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot +++ b/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot @@ -1,7 +1,7 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided tap (tap-preferred event 0) -kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00 -kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0x09 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap diff --git a/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot b/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot index c0b4c0b7..8749a46c 100644 --- a/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot +++ b/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot @@ -1,7 +1,7 @@ ht_binding_pressed: 0 new undecided hold_tap ht_decide: 0 decided tap (tap-preferred event 0) -kp_pressed: usage_page 0x07 keycode 0x09 mods 0x00 -kp_pressed: usage_page 0x07 keycode 0x07 mods 0x00 -kp_released: usage_page 0x07 keycode 0x09 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00 ht_binding_released: 0 cleaning up hold-tap -kp_released: usage_page 0x07 keycode 0x07 mods 0x00 +kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/keypress/kp-press-release/keycode_events.snapshot b/app/tests/keypress/kp-press-release/keycode_events.snapshot index 80cac202..259501ba 100644 --- a/app/tests/keypress/kp-press-release/keycode_events.snapshot +++ b/app/tests/keypress/kp-press-release/keycode_events.snapshot @@ -1,2 +1,2 @@ -pressed: usage_page 0x07 keycode 0x05 mods 0x00 -released: usage_page 0x07 keycode 0x05 mods 0x00 +pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/modifiers/explicit/kp-hyper-dn-a-dn-a-up-hyper-up/events.patterns b/app/tests/modifiers/explicit/kp-hyper-dn-a-dn-a-up-hyper-up/events.patterns new file mode 100644 index 00000000..cbf21aff --- /dev/null +++ b/app/tests/modifiers/explicit/kp-hyper-dn-a-dn-a-up-hyper-up/events.patterns @@ -0,0 +1,4 @@ +s/.*hid_listener_keycode_//p +s/.*hid_register_mod/reg/p +s/.*hid_unregister_mod/unreg/p +s/.*zmk_hid_.*Modifiers set to /mods: Modifiers set to /p \ No newline at end of file diff --git a/app/tests/modifiers/explicit/kp-hyper-dn-a-dn-a-up-hyper-up/keycode_events.snapshot b/app/tests/modifiers/explicit/kp-hyper-dn-a-dn-a-up-hyper-up/keycode_events.snapshot new file mode 100644 index 00000000..e146b9ca --- /dev/null +++ b/app/tests/modifiers/explicit/kp-hyper-dn-a-dn-a-up-hyper-up/keycode_events.snapshot @@ -0,0 +1,28 @@ +pressed: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x0e +reg: Modifier 0 count 1 +reg: Modifiers set to 0x01 +reg: Modifier 1 count 1 +reg: Modifiers set to 0x03 +reg: Modifier 2 count 1 +reg: Modifiers set to 0x07 +reg: Modifier 3 count 1 +reg: Modifiers set to 0x0f +mods: Modifiers set to 0x0f +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +mods: Modifiers set to 0x0f +released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +mods: Modifiers set to 0x0f +released: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x0e +unreg: Modifier 0 count: 0 +unreg: Modifier 0 released +unreg: Modifiers set to 0x0e +unreg: Modifier 1 count: 0 +unreg: Modifier 1 released +unreg: Modifiers set to 0x0c +unreg: Modifier 2 count: 0 +unreg: Modifier 2 released +unreg: Modifiers set to 0x08 +unreg: Modifier 3 count: 0 +unreg: Modifier 3 released +unreg: Modifiers set to 0x00 +mods: Modifiers set to 0x00 diff --git a/app/tests/modifiers/explicit/kp-hyper-dn-a-dn-a-up-hyper-up/native_posix.keymap b/app/tests/modifiers/explicit/kp-hyper-dn-a-dn-a-up-hyper-up/native_posix.keymap new file mode 100644 index 00000000..b8142425 --- /dev/null +++ b/app/tests/modifiers/explicit/kp-hyper-dn-a-dn-a-up-hyper-up/native_posix.keymap @@ -0,0 +1,28 @@ +#include +#include +#include + + +&kscan { + events = < + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_PRESS(1,0,10) + ZMK_MOCK_RELEASE(1,0,10) + ZMK_MOCK_RELEASE(0,0,10) + + >; +}; + +/ { + keymap { + compatible = "zmk,keymap"; + label ="Default keymap"; + + default_layer { + bindings = < + &kp LS(LA(LG(LEFT_CONTROL))) &kp LEFT_CONTROL + &kp A &none + >; + }; + }; +}; diff --git a/app/tests/modifiers/explicit/kp-lctl-dn-lctl-dn-lctl-up-lctl-up/keycode_events.snapshot b/app/tests/modifiers/explicit/kp-lctl-dn-lctl-dn-lctl-up-lctl-up/keycode_events.snapshot index 6218e650..25b79445 100644 --- a/app/tests/modifiers/explicit/kp-lctl-dn-lctl-dn-lctl-up-lctl-up/keycode_events.snapshot +++ b/app/tests/modifiers/explicit/kp-lctl-dn-lctl-dn-lctl-up-lctl-up/keycode_events.snapshot @@ -1,16 +1,16 @@ -pressed: usage_page 0x07 keycode 0xe0 mods 0x00 +pressed: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 reg: Modifier 0 count 1 reg: Modifiers set to 0x01 mods: Modifiers set to 0x01 -pressed: usage_page 0x07 keycode 0xe0 mods 0x00 +pressed: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 reg: Modifier 0 count 2 reg: Modifiers set to 0x01 mods: Modifiers set to 0x01 -released: usage_page 0x07 keycode 0xe0 mods 0x00 +released: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 unreg: Modifier 0 count: 1 unreg: Modifiers set to 0x01 mods: Modifiers set to 0x01 -released: usage_page 0x07 keycode 0xe0 mods 0x00 +released: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 unreg: Modifier 0 count: 0 unreg: Modifier 0 released unreg: Modifiers set to 0x00 diff --git a/app/tests/modifiers/explicit/kp-lctl-dn-lctl-up/keycode_events.snapshot b/app/tests/modifiers/explicit/kp-lctl-dn-lctl-up/keycode_events.snapshot index 42324284..545af6e7 100644 --- a/app/tests/modifiers/explicit/kp-lctl-dn-lctl-up/keycode_events.snapshot +++ b/app/tests/modifiers/explicit/kp-lctl-dn-lctl-up/keycode_events.snapshot @@ -1,8 +1,8 @@ -pressed: usage_page 0x07 keycode 0xe0 mods 0x00 +pressed: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 reg: Modifier 0 count 1 reg: Modifiers set to 0x01 mods: Modifiers set to 0x01 -released: usage_page 0x07 keycode 0xe0 mods 0x00 +released: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 unreg: Modifier 0 count: 0 unreg: Modifier 0 released unreg: Modifiers set to 0x00 diff --git a/app/tests/modifiers/explicit/kp-lctl-dn-lsft-dn-lctl-up-lsft-up/keycode_events.snapshot b/app/tests/modifiers/explicit/kp-lctl-dn-lsft-dn-lctl-up-lsft-up/keycode_events.snapshot index 60d829a6..b7445420 100644 --- a/app/tests/modifiers/explicit/kp-lctl-dn-lsft-dn-lctl-up-lsft-up/keycode_events.snapshot +++ b/app/tests/modifiers/explicit/kp-lctl-dn-lsft-dn-lctl-up-lsft-up/keycode_events.snapshot @@ -1,17 +1,17 @@ -pressed: usage_page 0x07 keycode 0xe0 mods 0x00 +pressed: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 reg: Modifier 0 count 1 reg: Modifiers set to 0x01 mods: Modifiers set to 0x01 -pressed: usage_page 0x07 keycode 0xe1 mods 0x00 +pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 reg: Modifier 1 count 1 reg: Modifiers set to 0x03 mods: Modifiers set to 0x03 -released: usage_page 0x07 keycode 0xe0 mods 0x00 +released: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 unreg: Modifier 0 count: 0 unreg: Modifier 0 released unreg: Modifiers set to 0x02 mods: Modifiers set to 0x02 -released: usage_page 0x07 keycode 0xe1 mods 0x00 +released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 unreg: Modifier 1 count: 0 unreg: Modifier 1 released unreg: Modifiers set to 0x00 diff --git a/app/tests/modifiers/explicit/kp-lctl-dn-lsft-dn-lsft-up-lctl-up/keycode_events.snapshot b/app/tests/modifiers/explicit/kp-lctl-dn-lsft-dn-lsft-up-lctl-up/keycode_events.snapshot index b4755e5b..74916a8c 100644 --- a/app/tests/modifiers/explicit/kp-lctl-dn-lsft-dn-lsft-up-lctl-up/keycode_events.snapshot +++ b/app/tests/modifiers/explicit/kp-lctl-dn-lsft-dn-lsft-up-lctl-up/keycode_events.snapshot @@ -1,17 +1,17 @@ -pressed: usage_page 0x07 keycode 0xe0 mods 0x00 +pressed: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 reg: Modifier 0 count 1 reg: Modifiers set to 0x01 mods: Modifiers set to 0x01 -pressed: usage_page 0x07 keycode 0xe1 mods 0x00 +pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 reg: Modifier 1 count 1 reg: Modifiers set to 0x03 mods: Modifiers set to 0x03 -released: usage_page 0x07 keycode 0xe1 mods 0x00 +released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 unreg: Modifier 1 count: 0 unreg: Modifier 1 released unreg: Modifiers set to 0x01 mods: Modifiers set to 0x01 -released: usage_page 0x07 keycode 0xe0 mods 0x00 +released: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 unreg: Modifier 0 count: 0 unreg: Modifier 0 released unreg: Modifiers set to 0x00 diff --git a/app/tests/modifiers/implicit/kp-mod1-dn-mod2-dn-mod1-up-mod2-up/keycode_events.snapshot b/app/tests/modifiers/implicit/kp-mod1-dn-mod2-dn-mod1-up-mod2-up/keycode_events.snapshot index 61dd271b..6dad3dea 100644 --- a/app/tests/modifiers/implicit/kp-mod1-dn-mod2-dn-mod1-up-mod2-up/keycode_events.snapshot +++ b/app/tests/modifiers/implicit/kp-mod1-dn-mod2-dn-mod1-up-mod2-up/keycode_events.snapshot @@ -1,8 +1,8 @@ -pressed: usage_page 0x07 keycode 0x05 mods 0x02 +pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x02 explicit_mods 0x00 mods: Modifiers set to 0x02 -pressed: usage_page 0x07 keycode 0x04 mods 0x01 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x01 explicit_mods 0x00 mods: Modifiers set to 0x01 -released: usage_page 0x07 keycode 0x05 mods 0x02 +released: usage_page 0x07 keycode 0x05 implicit_mods 0x02 explicit_mods 0x00 mods: Modifiers set to 0x01 -released: usage_page 0x07 keycode 0x04 mods 0x01 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x01 explicit_mods 0x00 mods: Modifiers set to 0x00 diff --git a/app/tests/modifiers/implicit/kp-mod1-dn-mod2-dn-mod2-up-mod1-up/keycode_events.snapshot b/app/tests/modifiers/implicit/kp-mod1-dn-mod2-dn-mod2-up-mod1-up/keycode_events.snapshot index e8a231fe..723b03e5 100644 --- a/app/tests/modifiers/implicit/kp-mod1-dn-mod2-dn-mod2-up-mod1-up/keycode_events.snapshot +++ b/app/tests/modifiers/implicit/kp-mod1-dn-mod2-dn-mod2-up-mod1-up/keycode_events.snapshot @@ -1,8 +1,8 @@ -pressed: usage_page 0x07 keycode 0x04 mods 0x01 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x01 explicit_mods 0x00 mods: Modifiers set to 0x01 -pressed: usage_page 0x07 keycode 0x05 mods 0x02 +pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x02 explicit_mods 0x00 mods: Modifiers set to 0x02 -released: usage_page 0x07 keycode 0x05 mods 0x02 +released: usage_page 0x07 keycode 0x05 implicit_mods 0x02 explicit_mods 0x00 mods: Modifiers set to 0x00 -released: usage_page 0x07 keycode 0x04 mods 0x01 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x01 explicit_mods 0x00 mods: Modifiers set to 0x00 diff --git a/app/tests/modifiers/mixed/kp-lctl-dn-mod-dn-lctl-up-mod-up/keycode_events.snapshot b/app/tests/modifiers/mixed/kp-lctl-dn-mod-dn-lctl-up-mod-up/keycode_events.snapshot index 40c5841e..aece8bed 100644 --- a/app/tests/modifiers/mixed/kp-lctl-dn-mod-dn-lctl-up-mod-up/keycode_events.snapshot +++ b/app/tests/modifiers/mixed/kp-lctl-dn-mod-dn-lctl-up-mod-up/keycode_events.snapshot @@ -1,13 +1,13 @@ -pressed: usage_page 0x07 keycode 0xe0 mods 0x00 +pressed: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 reg: Modifier 0 count 1 reg: Modifiers set to 0x01 mods: Modifiers set to 0x01 -pressed: usage_page 0x07 keycode 0x05 mods 0x02 +pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x02 explicit_mods 0x00 mods: Modifiers set to 0x03 -released: usage_page 0x07 keycode 0xe0 mods 0x00 +released: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 unreg: Modifier 0 count: 0 unreg: Modifier 0 released unreg: Modifiers set to 0x00 mods: Modifiers set to 0x00 -released: usage_page 0x07 keycode 0x05 mods 0x02 +released: usage_page 0x07 keycode 0x05 implicit_mods 0x02 explicit_mods 0x00 mods: Modifiers set to 0x00 diff --git a/app/tests/modifiers/mixed/kp-lctl-dn-mod-dn-mod-up-lctl-up/keycode_events.snapshot b/app/tests/modifiers/mixed/kp-lctl-dn-mod-dn-mod-up-lctl-up/keycode_events.snapshot index 5df571be..c24494fb 100644 --- a/app/tests/modifiers/mixed/kp-lctl-dn-mod-dn-mod-up-lctl-up/keycode_events.snapshot +++ b/app/tests/modifiers/mixed/kp-lctl-dn-mod-dn-mod-up-lctl-up/keycode_events.snapshot @@ -1,12 +1,12 @@ -pressed: usage_page 0x07 keycode 0xe0 mods 0x00 +pressed: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 reg: Modifier 0 count 1 reg: Modifiers set to 0x01 mods: Modifiers set to 0x01 -pressed: usage_page 0x07 keycode 0x05 mods 0x02 +pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x02 explicit_mods 0x00 mods: Modifiers set to 0x03 -released: usage_page 0x07 keycode 0x05 mods 0x02 +released: usage_page 0x07 keycode 0x05 implicit_mods 0x02 explicit_mods 0x00 mods: Modifiers set to 0x01 -released: usage_page 0x07 keycode 0xe0 mods 0x00 +released: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 unreg: Modifier 0 count: 0 unreg: Modifier 0 released unreg: Modifiers set to 0x00 diff --git a/app/tests/momentary-layer/1-normal/keycode_events.snapshot b/app/tests/momentary-layer/1-normal/keycode_events.snapshot index 608ce093..0a00aa27 100644 --- a/app/tests/momentary-layer/1-normal/keycode_events.snapshot +++ b/app/tests/momentary-layer/1-normal/keycode_events.snapshot @@ -1,4 +1,4 @@ mo_pressed: position 1 layer 1 -kp_pressed: usage_page 0x07 keycode 0x06 mods 0x00 -kp_released: usage_page 0x07 keycode 0x06 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00 mo_released: position 1 layer 1 diff --git a/app/tests/momentary-layer/2-early-key-release/keycode_events.snapshot b/app/tests/momentary-layer/2-early-key-release/keycode_events.snapshot index 82ebc67c..e24f11f9 100644 --- a/app/tests/momentary-layer/2-early-key-release/keycode_events.snapshot +++ b/app/tests/momentary-layer/2-early-key-release/keycode_events.snapshot @@ -1,4 +1,4 @@ -kp_pressed: usage_page 0x07 keycode 0x05 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 mo_pressed: position 1 layer 1 -kp_released: usage_page 0x07 keycode 0x05 mods 0x00 +kp_released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 mo_released: position 1 layer 1 diff --git a/app/tests/momentary-layer/4-nested/keycode_events.snapshot b/app/tests/momentary-layer/4-nested/keycode_events.snapshot index f03e4d5b..29b2e3fd 100644 --- a/app/tests/momentary-layer/4-nested/keycode_events.snapshot +++ b/app/tests/momentary-layer/4-nested/keycode_events.snapshot @@ -1,6 +1,6 @@ mo_pressed: position 1 layer 1 mo_pressed: position 0 layer 2 -kp_pressed: usage_page 0x07 keycode 0x05 mods 0x00 -kp_released: usage_page 0x07 keycode 0x05 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 mo_released: position 0 layer 2 mo_released: position 1 layer 1 diff --git a/app/tests/momentary-layer/5-nested-early-key-release/keycode_events.snapshot b/app/tests/momentary-layer/5-nested-early-key-release/keycode_events.snapshot index 15be601e..d14d7881 100644 --- a/app/tests/momentary-layer/5-nested-early-key-release/keycode_events.snapshot +++ b/app/tests/momentary-layer/5-nested-early-key-release/keycode_events.snapshot @@ -1,6 +1,6 @@ mo_pressed: position 1 layer 1 mo_pressed: position 0 layer 2 -kp_pressed: usage_page 0x07 keycode 0x05 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 mo_released: position 1 layer 1 mo_released: position 0 layer 2 -kp_released: usage_page 0x07 keycode 0x05 mods 0x00 +kp_released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/sticky-keys/1-os-dn-up/keycode_events.snapshot b/app/tests/sticky-keys/1-os-dn-up/keycode_events.snapshot index 5280f5c1..d2609894 100644 --- a/app/tests/sticky-keys/1-os-dn-up/keycode_events.snapshot +++ b/app/tests/sticky-keys/1-os-dn-up/keycode_events.snapshot @@ -1,4 +1,4 @@ -pressed: usage_page 0x07 keycode 0x08 mods 0x00 -released: usage_page 0x07 keycode 0x08 mods 0x00 -pressed: usage_page 0x07 keycode 0x04 mods 0x00 -released: usage_page 0x07 keycode 0x04 mods 0x00 +pressed: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/sticky-keys/2-os-dn-up-kcdn-kcup/keycode_events.snapshot b/app/tests/sticky-keys/2-os-dn-up-kcdn-kcup/keycode_events.snapshot index dba30cc2..addbca8c 100644 --- a/app/tests/sticky-keys/2-os-dn-up-kcdn-kcup/keycode_events.snapshot +++ b/app/tests/sticky-keys/2-os-dn-up-kcdn-kcup/keycode_events.snapshot @@ -1,8 +1,8 @@ -pressed: usage_page 0x07 keycode 0x08 mods 0x00 -pressed: usage_page 0x07 keycode 0x04 mods 0x00 -released: usage_page 0x07 keycode 0x08 mods 0x00 -released: usage_page 0x07 keycode 0x04 mods 0x00 -pressed: usage_page 0x07 keycode 0x08 mods 0x00 -pressed: usage_page 0x07 keycode 0x04 mods 0x00 -released: usage_page 0x07 keycode 0x08 mods 0x00 -released: usage_page 0x07 keycode 0x04 mods 0x00 +pressed: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/sticky-keys/2-sl-dn-up-kcdn-kcup/events.patterns b/app/tests/sticky-keys/2-sl-dn-up-kcdn-kcup/events.patterns new file mode 100644 index 00000000..833100f6 --- /dev/null +++ b/app/tests/sticky-keys/2-sl-dn-up-kcdn-kcup/events.patterns @@ -0,0 +1 @@ +s/.*hid_listener_keycode_//p \ No newline at end of file diff --git a/app/tests/sticky-keys/2-sl-dn-up-kcdn-kcup/keycode_events.snapshot b/app/tests/sticky-keys/2-sl-dn-up-kcdn-kcup/keycode_events.snapshot new file mode 100644 index 00000000..7e745b51 --- /dev/null +++ b/app/tests/sticky-keys/2-sl-dn-up-kcdn-kcup/keycode_events.snapshot @@ -0,0 +1,8 @@ +pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x1b implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/sticky-keys/2-sl-dn-up-kcdn-kcup/native_posix.keymap b/app/tests/sticky-keys/2-sl-dn-up-kcdn-kcup/native_posix.keymap new file mode 100644 index 00000000..4470fb21 --- /dev/null +++ b/app/tests/sticky-keys/2-sl-dn-up-kcdn-kcup/native_posix.keymap @@ -0,0 +1,52 @@ +#include +#include +#include + +/* + sticky layers should quick-release. + Thus, the second keypress should be on the default layer, not on the lower_layer. +*/ + +/ { + keymap { + compatible = "zmk,keymap"; + label ="Default keymap"; + + default_layer { + bindings = < + &sk E &sl 1 + &kp A &kp B>; + }; + + lower_layer { + bindings = < + &sk LEFT_CONTROL &kp X + &kp Y &kp Z>; + }; + }; +}; + +&kscan { + events = < + /* press sl 1 */ + ZMK_MOCK_PRESS(0,1,10) + ZMK_MOCK_RELEASE(0,1,10) + /* press X */ + ZMK_MOCK_PRESS(0,1,10) + /* press A */ + ZMK_MOCK_PRESS(1,0,10) + ZMK_MOCK_RELEASE(0,1,10) + ZMK_MOCK_RELEASE(1,0,10) + + /* repeat test to check if cleanup is done correctly */ + /* press sl 1 */ + ZMK_MOCK_PRESS(0,1,10) + ZMK_MOCK_RELEASE(0,1,10) + /* press X */ + ZMK_MOCK_PRESS(0,1,10) + /* press Y */ + ZMK_MOCK_PRESS(1,0,10) + ZMK_MOCK_RELEASE(0,1,10) + ZMK_MOCK_RELEASE(1,0,10) + >; +}; \ No newline at end of file diff --git a/app/tests/sticky-keys/3a-os-dn-kcdn-kcup-up/keycode_events.snapshot b/app/tests/sticky-keys/3a-os-dn-kcdn-kcup-up/keycode_events.snapshot index ee8aee01..1b091a6a 100644 --- a/app/tests/sticky-keys/3a-os-dn-kcdn-kcup-up/keycode_events.snapshot +++ b/app/tests/sticky-keys/3a-os-dn-kcdn-kcup-up/keycode_events.snapshot @@ -1,4 +1,4 @@ -pressed: usage_page 0x07 keycode 0x08 mods 0x00 -pressed: usage_page 0x07 keycode 0x04 mods 0x00 -released: usage_page 0x07 keycode 0x04 mods 0x00 -released: usage_page 0x07 keycode 0x08 mods 0x00 +pressed: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/sticky-keys/3b-os-dn-kcdn-up-kcup/keycode_events.snapshot b/app/tests/sticky-keys/3b-os-dn-kcdn-up-kcup/keycode_events.snapshot index 758ed616..6e004ec2 100644 --- a/app/tests/sticky-keys/3b-os-dn-kcdn-up-kcup/keycode_events.snapshot +++ b/app/tests/sticky-keys/3b-os-dn-kcdn-up-kcup/keycode_events.snapshot @@ -1,4 +1,4 @@ -pressed: usage_page 0x07 keycode 0x08 mods 0x00 -pressed: usage_page 0x07 keycode 0x04 mods 0x00 -released: usage_page 0x07 keycode 0x08 mods 0x00 -released: usage_page 0x07 keycode 0x04 mods 0x00 +pressed: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/sticky-keys/4-os-dn-up-kcdn-timer-kcup/keycode_events.snapshot b/app/tests/sticky-keys/4-os-dn-up-kcdn-timer-kcup/keycode_events.snapshot index 758ed616..6e004ec2 100644 --- a/app/tests/sticky-keys/4-os-dn-up-kcdn-timer-kcup/keycode_events.snapshot +++ b/app/tests/sticky-keys/4-os-dn-up-kcdn-timer-kcup/keycode_events.snapshot @@ -1,4 +1,4 @@ -pressed: usage_page 0x07 keycode 0x08 mods 0x00 -pressed: usage_page 0x07 keycode 0x04 mods 0x00 -released: usage_page 0x07 keycode 0x08 mods 0x00 -released: usage_page 0x07 keycode 0x04 mods 0x00 +pressed: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/sticky-keys/5-os-kcdn-dn-kcup-up/keycode_events.snapshot b/app/tests/sticky-keys/5-os-kcdn-dn-kcup-up/keycode_events.snapshot index 99bac8de..03495b46 100644 --- a/app/tests/sticky-keys/5-os-kcdn-dn-kcup-up/keycode_events.snapshot +++ b/app/tests/sticky-keys/5-os-kcdn-dn-kcup-up/keycode_events.snapshot @@ -1,4 +1,4 @@ -pressed: usage_page 0x07 keycode 0x04 mods 0x00 -pressed: usage_page 0x07 keycode 0x08 mods 0x00 -released: usage_page 0x07 keycode 0x04 mods 0x00 -released: usage_page 0x07 keycode 0x08 mods 0x00 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/sticky-keys/7-os-dn-up-kc1dn-kc2dn-kc1up-kc2up/keycode_events.snapshot b/app/tests/sticky-keys/7-os-dn-up-kc1dn-kc2dn-kc1up-kc2up/keycode_events.snapshot index a9de7e1b..3c757bbb 100644 --- a/app/tests/sticky-keys/7-os-dn-up-kc1dn-kc2dn-kc1up-kc2up/keycode_events.snapshot +++ b/app/tests/sticky-keys/7-os-dn-up-kc1dn-kc2dn-kc1up-kc2up/keycode_events.snapshot @@ -1,6 +1,6 @@ -pressed: usage_page 0x07 keycode 0x08 mods 0x00 -pressed: usage_page 0x07 keycode 0x04 mods 0x00 -pressed: usage_page 0x07 keycode 0x05 mods 0x00 -released: usage_page 0x07 keycode 0x08 mods 0x00 -released: usage_page 0x07 keycode 0x04 mods 0x00 -released: usage_page 0x07 keycode 0x05 mods 0x00 +pressed: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/sticky-keys/8-lsk-osk-combination/events.patterns b/app/tests/sticky-keys/8-lsk-osk-combination/events.patterns index 833100f6..b1342af4 100644 --- a/app/tests/sticky-keys/8-lsk-osk-combination/events.patterns +++ b/app/tests/sticky-keys/8-lsk-osk-combination/events.patterns @@ -1 +1 @@ -s/.*hid_listener_keycode_//p \ No newline at end of file +s/.*hid_listener_keycode_//p diff --git a/app/tests/sticky-keys/8-lsk-osk-combination/keycode_events.snapshot b/app/tests/sticky-keys/8-lsk-osk-combination/keycode_events.snapshot index 51660c34..374035fc 100644 --- a/app/tests/sticky-keys/8-lsk-osk-combination/keycode_events.snapshot +++ b/app/tests/sticky-keys/8-lsk-osk-combination/keycode_events.snapshot @@ -1,8 +1,8 @@ -pressed: usage_page 0x07 keycode 0xe0 mods 0x00 -pressed: usage_page 0x07 keycode 0x1c mods 0x00 -released: usage_page 0x07 keycode 0xe0 mods 0x00 -released: usage_page 0x07 keycode 0x1c mods 0x00 -pressed: usage_page 0x07 keycode 0xe0 mods 0x00 -pressed: usage_page 0x07 keycode 0x1c mods 0x00 -released: usage_page 0x07 keycode 0xe0 mods 0x00 -released: usage_page 0x07 keycode 0x1c mods 0x00 +pressed: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0xe0 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/sticky-keys/8-lsk-osk-combination/native_posix.keymap b/app/tests/sticky-keys/8-lsk-osk-combination/native_posix.keymap index beedd44e..bdcccf33 100644 --- a/app/tests/sticky-keys/8-lsk-osk-combination/native_posix.keymap +++ b/app/tests/sticky-keys/8-lsk-osk-combination/native_posix.keymap @@ -29,7 +29,7 @@ /* tap sk LEFT_CONTROL */ ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_RELEASE(0,0,10) - /* tap Y */ + /* tap A */ ZMK_MOCK_PRESS(1,0,10) ZMK_MOCK_RELEASE(1,0,10) @@ -40,7 +40,7 @@ /* tap sk */ ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_RELEASE(0,0,10) - /* tap Y */ + /* tap A */ ZMK_MOCK_PRESS(1,0,10) ZMK_MOCK_RELEASE(1,0,10) >; diff --git a/app/tests/sticky-keys/9-sk-dn-up-dn-up/keycode_events.snapshot b/app/tests/sticky-keys/9-sk-dn-up-dn-up/keycode_events.snapshot index bfe7f615..d5bd587e 100644 --- a/app/tests/sticky-keys/9-sk-dn-up-dn-up/keycode_events.snapshot +++ b/app/tests/sticky-keys/9-sk-dn-up-dn-up/keycode_events.snapshot @@ -1,4 +1,4 @@ -pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -released: usage_page 0x07 keycode 0xe1 mods 0x00 -pressed: usage_page 0x07 keycode 0xe1 mods 0x00 -released: usage_page 0x07 keycode 0xe1 mods 0x00 +pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 +released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/to-layer/normal/keycode_events.snapshot b/app/tests/to-layer/normal/keycode_events.snapshot index 930a977a..5ac5eb68 100644 --- a/app/tests/to-layer/normal/keycode_events.snapshot +++ b/app/tests/to-layer/normal/keycode_events.snapshot @@ -1,16 +1,16 @@ -kp_pressed: usage_page 0x07 keycode 0x16 mods 0x00 -kp_released: usage_page 0x07 keycode 0x16 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x16 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x16 implicit_mods 0x00 explicit_mods 0x00 to_pressed: position 1 layer 1 layer_changed: layer 1 state 1 to_released: position 1 layer 1 -kp_pressed: usage_page 0x07 keycode 0x0e mods 0x00 -kp_released: usage_page 0x07 keycode 0x0e mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x0e implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x0e implicit_mods 0x00 explicit_mods 0x00 to_pressed: position 0 layer 0 layer_changed: layer 1 state 0 layer_changed: layer 0 state 1 to_released: position 0 layer 0 -kp_pressed: usage_page 0x07 keycode 0x16 mods 0x00 -kp_released: usage_page 0x07 keycode 0x16 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x16 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x16 implicit_mods 0x00 explicit_mods 0x00 to_pressed: position 0 layer 0 to_released: position 0 layer 0 to_pressed: position 1 layer 1 diff --git a/app/tests/toggle-layer/early-key-release/keycode_events.snapshot b/app/tests/toggle-layer/early-key-release/keycode_events.snapshot index 6b4d50bd..e0aa502f 100644 --- a/app/tests/toggle-layer/early-key-release/keycode_events.snapshot +++ b/app/tests/toggle-layer/early-key-release/keycode_events.snapshot @@ -1,6 +1,6 @@ -kp_pressed: usage_page 0x07 keycode 0x05 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 tog_pressed: position 1 layer 1 -kp_released: usage_page 0x07 keycode 0x05 mods 0x00 +kp_released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00 tog_released: position 1 layer 1 -kp_pressed: usage_page 0x0c keycode 0xb5 mods 0x00 -kp_released: usage_page 0x0c keycode 0xb5 mods 0x00 +kp_pressed: usage_page 0x0c keycode 0xb5 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x0c keycode 0xb5 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/toggle-layer/normal/keycode_events.snapshot b/app/tests/toggle-layer/normal/keycode_events.snapshot index d03295ef..8b5b0cc5 100644 --- a/app/tests/toggle-layer/normal/keycode_events.snapshot +++ b/app/tests/toggle-layer/normal/keycode_events.snapshot @@ -1,4 +1,4 @@ tog_pressed: position 1 layer 1 tog_released: position 1 layer 1 -kp_pressed: usage_page 0x0c keycode 0xb5 mods 0x00 -kp_released: usage_page 0x0c keycode 0xb5 mods 0x00 +kp_pressed: usage_page 0x0c keycode 0xb5 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x0c keycode 0xb5 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/transparent/layered/keycode_events.snapshot b/app/tests/transparent/layered/keycode_events.snapshot index 5e707b85..570e7d15 100644 --- a/app/tests/transparent/layered/keycode_events.snapshot +++ b/app/tests/transparent/layered/keycode_events.snapshot @@ -1,2 +1,2 @@ -kp_pressed: usage_page 0x07 keycode 0x04 mods 0x00 -kp_released: usage_page 0x07 keycode 0x04 mods 0x00 +kp_pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 +kp_released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00 diff --git a/app/tests/wpm/1-single_keypress/events.patterns b/app/tests/wpm/1-single_keypress/events.patterns new file mode 100644 index 00000000..c49e6c00 --- /dev/null +++ b/app/tests/wpm/1-single_keypress/events.patterns @@ -0,0 +1,2 @@ +s/.*wpm_work_handler: //p +s/.*wpm_event_listener: //p \ No newline at end of file diff --git a/app/tests/wpm/1-single_keypress/keycode_events.snapshot b/app/tests/wpm/1-single_keypress/keycode_events.snapshot new file mode 100644 index 00000000..c86f323b --- /dev/null +++ b/app/tests/wpm/1-single_keypress/keycode_events.snapshot @@ -0,0 +1,7 @@ +key_pressed_count 1 keycode 5 +Raised WPM state changed 12 wpm_update_counter 1 +Raised WPM state changed 6 wpm_update_counter 2 +Raised WPM state changed 4 wpm_update_counter 3 +Raised WPM state changed 3 wpm_update_counter 4 +Raised WPM state changed 2 wpm_update_counter 5 +Raised WPM state changed 0 wpm_update_counter 1 diff --git a/app/tests/wpm/1-single_keypress/native_posix.conf b/app/tests/wpm/1-single_keypress/native_posix.conf new file mode 100644 index 00000000..360e77d5 --- /dev/null +++ b/app/tests/wpm/1-single_keypress/native_posix.conf @@ -0,0 +1,9 @@ +CONFIG_KSCAN=n +CONFIG_ZMK_KSCAN_MOCK_DRIVER=y +CONFIG_ZMK_KSCAN_GPIO_DRIVER=n +CONFIG_GPIO=n +CONFIG_ZMK_BLE=n +CONFIG_LOG=y +CONFIG_LOG_BACKEND_SHOW_COLOR=n +CONFIG_ZMK_LOG_LEVEL_DBG=y +CONFIG_ZMK_WPM=y \ No newline at end of file diff --git a/app/tests/wpm/1-single_keypress/native_posix.keymap b/app/tests/wpm/1-single_keypress/native_posix.keymap new file mode 100644 index 00000000..ec12a286 --- /dev/null +++ b/app/tests/wpm/1-single_keypress/native_posix.keymap @@ -0,0 +1,10 @@ +#include "../behavior_keymap.dtsi" + +&kscan { + events = < + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_RELEASE(0,0,10) + /* Wait for the worker to trigger and reset after 5 seconds, followed by a 0 at 6 seconds */ + ZMK_MOCK_PRESS(0,0,6000) + >; +}; \ No newline at end of file diff --git a/app/tests/wpm/2-multiple_keypress/events.patterns b/app/tests/wpm/2-multiple_keypress/events.patterns new file mode 100644 index 00000000..c49e6c00 --- /dev/null +++ b/app/tests/wpm/2-multiple_keypress/events.patterns @@ -0,0 +1,2 @@ +s/.*wpm_work_handler: //p +s/.*wpm_event_listener: //p \ No newline at end of file diff --git a/app/tests/wpm/2-multiple_keypress/keycode_events.snapshot b/app/tests/wpm/2-multiple_keypress/keycode_events.snapshot new file mode 100644 index 00000000..a0e8f7a8 --- /dev/null +++ b/app/tests/wpm/2-multiple_keypress/keycode_events.snapshot @@ -0,0 +1,4 @@ +key_pressed_count 1 keycode 5 +Raised WPM state changed 12 wpm_update_counter 1 +key_pressed_count 2 keycode 5 +Raised WPM state changed 8 wpm_update_counter 3 diff --git a/app/tests/wpm/2-multiple_keypress/native_posix.conf b/app/tests/wpm/2-multiple_keypress/native_posix.conf new file mode 100644 index 00000000..f0e1a480 --- /dev/null +++ b/app/tests/wpm/2-multiple_keypress/native_posix.conf @@ -0,0 +1,9 @@ +CONFIG_KSCAN=n +CONFIG_ZMK_KSCAN_MOCK_DRIVER=y +CONFIG_ZMK_KSCAN_GPIO_DRIVER=n +CONFIG_GPIO=n +CONFIG_ZMK_BLE=n +CONFIG_LOG=y +CONFIG_LOG_BACKEND_SHOW_COLOR=n +CONFIG_ZMK_LOG_LEVEL_DBG=y +CONFIG_ZMK_WPM=y diff --git a/app/tests/wpm/2-multiple_keypress/native_posix.keymap b/app/tests/wpm/2-multiple_keypress/native_posix.keymap new file mode 100644 index 00000000..f4ba2dfe --- /dev/null +++ b/app/tests/wpm/2-multiple_keypress/native_posix.keymap @@ -0,0 +1,15 @@ +#include "../behavior_keymap.dtsi" + +&kscan { + events = < + ZMK_MOCK_PRESS(0,0,10) + ZMK_MOCK_RELEASE(0,0,10) + //1st WPM worker call - 12wpm - 1 key press in 1 second + ZMK_MOCK_PRESS(0,0,1000) + ZMK_MOCK_RELEASE(0,0,10) + // 2nd WPM worker call - 12wpm - 2 key press in 2 second + // note there is no event for this as WPM hasn't changed + // 3rd WPM worker call - 8wpm - 2 key press in 3 seconds + ZMK_MOCK_PRESS(0,0,2000) + >; +}; \ No newline at end of file diff --git a/app/tests/wpm/behavior_keymap.dtsi b/app/tests/wpm/behavior_keymap.dtsi new file mode 100644 index 00000000..f0c5d0c2 --- /dev/null +++ b/app/tests/wpm/behavior_keymap.dtsi @@ -0,0 +1,17 @@ +#include +#include +#include + +/ { + keymap { + compatible = "zmk,keymap"; + label ="Default keymap"; + + default_layer { + bindings = < + &kp B &none + &none &none + >; + }; + }; +}; diff --git a/docs/blog/2021-01-27-zmk-sotf-4.md b/docs/blog/2021-01-27-zmk-sotf-4.md new file mode 100644 index 00000000..d902b62d --- /dev/null +++ b/docs/blog/2021-01-27-zmk-sotf-4.md @@ -0,0 +1,194 @@ +--- +title: "ZMK State Of The Firmware #4" +author: Pete Johanson +author_title: Project Creator +author_url: https://gitlab.com/petejohanson +author_image_url: https://www.gravatar.com/avatar/2001ceff7e9dc753cf96fcb2e6f41110 +tags: [SOTF, keyboards, firmware, oss, ble] +--- + +Welcome to the fourth ZMK "State Of The Firmware" (SOTF)! + +This update will cover all the major activity since [SOTF #3](/blog/2020/11/09/zmk-sotf-3). + +## Recent Activity + +Here's a summary of the various major changes since last time, broken down by theme: + +### Keymaps/Behaviors + +Since last time, there have been several new powerful keymap features and behaviors added, including one of the most asked for features, combos! + +#### Combos + +The initial [combos](/docs/features/combos) work has landed! The amazing [okke-formsma] has once again delivered another powerful feature for ZMK. Combos are "position based", and are configured in a new toplevel node next to they `keymap` node in user's keymap files. + +An example, that would send the `ESC` keycode when pressing both the first and second positions on your keyboard: + +``` +/ { + combos { + compatible = "zmk,combos"; + combo_esc { + timeout-ms = <50>; + key-positions = <0 1>; + bindings = <&kp ESC>; + }; + }; +}; +``` + +:::note +Combos currently are "global", and not scoped to a given active layer. There is future planned work to allow enabling a certain combo for only certain active layers. +::: + +#### Sticky Keys (One-Shot Mods/Layers) Behavior + +[okke-formsma] also contributed the initial "sticky keys" behavior, which can be used for functionality sometimes called "one shot mods" or "one shot layers". In your keymap, this would like like: + +``` +&sk LEFT_CONTROL +``` + +for a sticky key/modifier, or: + +``` +&sl NAV +``` + +for a sticky layer. + +#### `&to` Layer Behavior + +[mcrosson] contributed the new [`&to`](/docs/behaviors/layers#to-layer) layer related behavior. This can be used to completely replace the active layer with a new one. + +This is most frequently used when using multiple core base layers with different layouts, e.g. QWERTY and DVORAK, to switch between them. + +#### Grave Escape Behavior + +[okke-formsma] added an implementation of the "Grave Escape" behavior, developing a more generic "mod-morph" behavior to do so. Adding + +``` +&gresc +``` + +to your keymap will send `ESC` when pressed on its own, but will send `` ` `` when pressed with a GUI or Shift modifier held. + +#### RGB Underglow Color Selection + +[mcrosson] updated the [RGB Underglow behavior](/docs/behaviors/lighting#rgb-underglow) to allow [binding an explicit color selection](/docs/behaviors/lighting#examples) to a key position. + +#### Keymap Upgrader + +[joelspadin] completed the [Keymap Upgrader](/docs/codes/keymap-upgrader) which can be used to update your keymap to using the latest supported codes, and move away from the old deprecated codes. + +If you've made keymap customizations, please make sure to run your keymaps through the upgrader, since the old deprecated codes will be removed in a future version of ZMK. + +### Displays + +There has been lots of work to get display support complete enough for use by end users. Although not quite ready for prime time, it is incredibly close, and we are looking forward to having the last few items completed and the feature documented! + +#### Idle Blanking + +[petejohanson] added idle blanking for displays, which ensures they will go blank, and into low power mode, after a short period of inactivity from the user. This ensures we avoid burn-in for OLEDs, and helps improve battery life. + +#### Battery and Output Widgets + +[petejohanson] implemented the first two complete, dynamic "widgets" for the displays for ZMK, adding a small battery indicator, which includes charging status, and a small output indicator, showing the currently active output (USB or BLE). When using BLE, the indicator also shows the active profile slot, as well as if the profile slot is open, awaiting connection from the paired host, or is actively connected to the host for that profile slot. + +#### Highest Layer Display + +[mcrosson] has contributed the next display widget, showing the highest active layer in the keymap. [petejohanson] then added a small follow up to allow layers in keymaps to add a `label` property to each layer, e.g. `label = "Nav";` and have that label be displayed in the widget instead of the numeric layer number. + +#### WPM + +New contributor [allymparker](https://github.com/allymparker) added our fourth widget, a words-per-minute display! This widget work also included creating the core state logic for tracking the WPM. + +For now, this widget is only working on the central side of split keyboards. + +### Miscellaneous + +#### Zephyr 2.4 + +[innovaker] is at it again with some crucial core fixes, helping prepare and test the upgrade of ZMK to Zephyr 2.4. The updated Zephyr release brings with it some key BLE stability fixes, as well as various other core improvements that improve ZMK. This was a huge undertaking! + +#### BLE Deadlock Fixes + +[petejohanson] was heads down diagnosing and fixing a deadlock issue on BLE that was frustrating and plaguing many users. After finally pinpointing the underlying root cause, he developed a fix and roped in many testers on Discord to help stress test things before merging. + +#### Central/Peripheral Selection + +Previously overriding the selection of left as central, and right as peripheral for wireless splits required making local edits to the configuration files, and maintaining them in a ZMK fork. + +[petejohanson] updated [the config files](https://github.com/zmkfirmware/zmk/pull/510) to allow users to override this in their `_left.conf`/`_right.conf` files in their user repos. + +#### Improved Docker Containers + +As part of the Zephyr 2.4. prep work, [innovaker], along with lots of testing and input from [mcrosson], developed a brand new pair of [Docker images](https://github.com/zmkfirmware/zmk-docker) which is now published to Docker Hub as [zmkfirmware/zmk-build-arm](https://hub.docker.com/repository/docker/zmkfirmware/zmk-build-arm) and [zmkfirmware/zmk-dev-arm](https://hub.docker.com/repository/docker/zmkfirmware/zmk-build-arm). + +The previously blogged VSCode + Docker integration, as well as our GH Action build automation was all moved over to the new images. + +#### Settings Debounce + +[nicell] contributed settings debounce work, to help avoid unnecessary extra writes to flash when making various changes that should be saved, +such as the active BLE profile, external VCC on/off, etc. + +## New Shields + +- Jorne & Jian in [#331](https://github.com/zmkfirmware/zmk/pull/331) - [krikun98](https://github.com/krikun98) +- tidbit in [#424](https://github.com/zmkfirmware/zmk/pull/424) - [mcrosson](https://github.com/mcrosson) +- Helix in [#429](https://github.com/zmkfirmware/zmk/pull/429) - [KingCoinless](https://github.com/KingCoinless) +- BFO-9000 in [#472](https://github.com/zmkfirmware/zmk/pull/472) - [pbz](https://github.com/pbz) +- CRBN in [#493](https://github.com/zmkfirmware/zmk/pull/483) - [ReFil](https://github.com/ReFil) +- Eek in [#529](https://github.com/zmkfirmware/zmk/pull/529) - [MangoIV](https://github.com/MangoIV) + +## New Boards + +- BDN9 Rev2 in [#557](https://github.com/zmkfirmware/zmk/pull/557) - [petejohanson] + +## Sponsorship + +Since it's inception, quite a few users have inquired whether they could sponsor any of the contributors involved in ZMK. Although we are not intending to directly fund any individual contributors for their work on ZMK, there _is_ good that can come from folks sponsoring ZMK. + +You can see the full discussion on [#497](https://github.com/zmkfirmware/zmk/issues/497), but some items that are being considered with sponsorship funds: + +- Hiring a designer to complete the logo/mascot work. +- Creating stickers to send as thank-yous to first time contributors. +- Hosting costs for GitHub Pro. +- Other hosting costs, e.g. Docker Hub. + +For anyone looking to contribute, you can find the [ZMK Firmware project](https://opencollective.com/zmkfirmware) is now set up on [Open Collective](https://opencollective.com). + +## Coming Soon! + +Some items listed in the last coming soon section are still under active development. + +- A power profiler page for the website, to help users estimate their battery life for a given keyboard - [Nicell] +- Behavior "locality", allowing improved split usage for things like `&reset`, and controlling external power and RGB underglow for both sides - [petejohanson] +- More modular approach to external boards/shields, custom code, user keymaps, etc. +- More shields and boards + +## Statistics + +Some statistics of interest for ZMK: + +- GitHub (lifetime stats) + - 389 Closed PRs + - 199 Stars + - 163 Forks +- Discord Chat + - 702 total registered +- Website (last 30 days) + - 11.5K page views + - 1K new users + +## Thanks! + +Thanks again to the numerous contributors, testers, and users who have made working on ZMK such a pleasure! + +[okke-formsma]: https://github.com/okke-formsma +[mcrosson]: https://github.com/mcrosson +[nicell]: https://github.com/Nicell +[petejohanson]: https://github.com/petejohanson +[innovaker]: https://github.com/innovaker +[joelspadin]: https://github.com/joelspadin diff --git a/docs/docs/behaviors/bluetooth.md b/docs/docs/behaviors/bluetooth.md index 0b66a4ca..f2d1b2f0 100644 --- a/docs/docs/behaviors/bluetooth.md +++ b/docs/docs/behaviors/bluetooth.md @@ -71,7 +71,7 @@ The bluetooth behavior completes an bluetooth action given on press. ## Bluetooth Pairing and Profiles -ZMK support bluetooth β€œprofiles” which allows connection to multiple devices (5 by default, or 4 if you are using split keyboards). Each profile stores the bluetooth MAC address of a peer, which can be empty if a profile has not been paired with a device yet. Upon switching to a profile, ZMK does the following: +ZMK support bluetooth β€œprofiles” which allows connection to multiple devices (5 by default). Each profile stores the bluetooth MAC address of a peer, which can be empty if a profile has not been paired with a device yet. Upon switching to a profile, ZMK does the following: - If a profile has not been paired with a peer yet, ZMK automatically advertise itself as connectable. You can discover you keyboard from bluetooth scanning on your laptop / tablet. If you try to connect, it will trigger the _pairing_ procedure. After pairing, the bluetooth MAC address of the peer device will be stored in the current profile. Pairing also negotiate a random key for secure communication between the device and the keyboard. - If a profile has been paired but the peer is not connected yet, ZMK will also advertise itself as connectable. In the future, the behavior might change to _direct advertising_ which only target the peer with the stored bluetooth MAC address. In this state, if the peer is powered on and moved within the distance of bluetooth signal coverage, it should automatically connect to the keyboard. diff --git a/docs/docs/behaviors/hold-tap.md b/docs/docs/behaviors/hold-tap.md index f3c3c664..0cf48884 100644 --- a/docs/docs/behaviors/hold-tap.md +++ b/docs/docs/behaviors/hold-tap.md @@ -23,9 +23,9 @@ We call this the 'hold-preferred' flavor of hold-taps. While this flavor may wor #### Flavors -- 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 '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. When the hold-tap key is released and the hold behavior has not been triggered, the tap behavior will trigger. @@ -68,7 +68,7 @@ This example configures a hold-tap that works well for homerow mods: ``` -If this config does not work for you, try the flavor "balanced" with a medium tapping_term_ms such as 200ms. +If this config does not work for you, try the flavor "balanced" with a medium `tapping_term_ms` such as 200ms. #### Comparison to QMK diff --git a/docs/docs/behaviors/sticky-key.md b/docs/docs/behaviors/sticky-key.md new file mode 100644 index 00000000..d5627dcb --- /dev/null +++ b/docs/docs/behaviors/sticky-key.md @@ -0,0 +1,51 @@ +--- +title: Sticky Key Behavior +sidebar_label: Sticky Key +--- + +## Summary + +A sticky key stays pressed until another key is pressed. It is often used for 'sticky shift'. By using a sticky shift, you don't have to hold the shift key to write a capital. + +By default, sticky keys stay pressed for a second if you don't press any other key. You can configure this with the `release-after-ms` setting (see below). + +### Behavior Binding + +- Reference: `&sk` +- Parameter #1: The keycode , e.g. `LSHFT` + +Example: + +``` +&sk LSHFT +``` + +You can use any keycode that works for `&kp` as parameter to `&sk`: + +``` +&sk LG(LS(LA(LCTRL))) +``` + +### Configuration + +You can configure a different `release-after-ms` in your keymap: + +``` +&sk { + release-after-ms = <2000>; +}; + +/ { + keymap { + ... + } +} +``` + +### Advanced usage + +Sticky keys can be combined; if you tap `&sk LCTRL` and then `&sk LSHFT` and then `&kp A`, the output will be ctrl+shift+a. + +### Comparison to QMK + +In QMK, sticky keys are known as 'one shot mods'. diff --git a/docs/docs/behaviors/sticky-layer.md b/docs/docs/behaviors/sticky-layer.md new file mode 100644 index 00000000..597ed9f0 --- /dev/null +++ b/docs/docs/behaviors/sticky-layer.md @@ -0,0 +1,45 @@ +--- +title: Sticky Layer Behavior +sidebar_label: Sticky Layer +--- + +## Summary + +A sticky layer stays pressed until another key is pressed. By using a sticky layer, you don't have to hold the layer key to access a layer. Instead, tap the sticky layer key to activate the layer until the next keypress. + +By default, sticky layers stay pressed for a second if you don't press any other key. You can configure this with the `release-after-ms` setting (see below). + +### Behavior Binding + +- Reference: `&sl` +- Parameter #1: The layer to activate , e.g. `1` + +Example: + +``` +&sl 1 +``` + +### Configuration + +You can configure a different `release-after-ms` in your keymap: + +``` +&sl { + release-after-ms = <2000>; +}; + +/ { + keymap { + ... + } +} +``` + +### Advanced usage + +Sticky layers behave slightly different from sticky keys. They are configured to `quick-release`. This means that the layer is released immediately when another key is pressed. "Normal" sticky keys are not `quick-release`; they are released when the next key is released. This makes it possible to combine sticky layers and sticky keys as such: tap `&sl 1`, tap `&sk LSHFT` on layer 1, tap `&kp A` on base layer to output shift+A. + +### Comparison to QMK + +In QMK, sticky layers are known as 'one shot layers'. diff --git a/docs/docs/development/build-flash.md b/docs/docs/development/build-flash.md index e270a7c6..acabfc07 100644 --- a/docs/docs/development/build-flash.md +++ b/docs/docs/development/build-flash.md @@ -118,11 +118,17 @@ Now start VSCode and rebuild the container after being prompted. You should be a ## Flashing -Once built, the previously supplied parameters will be remembered so you can run the following to flash your -board with it in bootloader mode: +The above build commands generate a UF2 file in `build/zephyr` (or +`build/left|right/zephyr` if you followed the instructions for splits) and is by +default named `zmk.uf2`. If your board supports USB Flashing Format (UF2), copy +that file onto the root of the USB mass storage device for your board. The +controller should flash your built firmware and automatically restart once +flashing is complete. + +Alternatively, if your board supports flashing and you're not developing from +within a Dockerized environment, enable Device Firmware Upgrade (DFU) mode on +your board and run the following command to flash: ``` west flash ``` - -For boards that have drag and drop .uf2 flashing capability, the .uf2 file to flash can be found in `build/zephyr` (or `build/left|right/zephyr` if you followed the instructions for splits) and is by default named `zmk.uf2`. diff --git a/docs/docs/development/documentation.md b/docs/docs/development/documentation.md new file mode 100644 index 00000000..221bb160 --- /dev/null +++ b/docs/docs/development/documentation.md @@ -0,0 +1,57 @@ +--- +title: Documentation +sidebar_label: Documentation +--- + +This document outlines how to test your documentation changes locally and prepare the changes for a pull request. + +The documentation is written with [Docusaurus](https://docusaurus.io/). The ZMK source code has all of the necessary Docusaurus dependencies included but referencing their documentation can be helpful at times. + +The general process for updating the ZMK documentation is: + +1. Update the documentation +2. Test the changes locally +3. Ensure the sources are formatted properly and linted +4. Create a Pull Request for review and inclusion into the ZMK sources + +:::note +If you are working with the documentation from within VS Code+Docker please be aware the documentation will not be auto-generated when making changes while the server is running. You'll need to restart the server when saving changes to the documentation. +::: + +:::note +You will need `Node.js` and `npm` installed to update the documentation. If you're using the ZMK dev container (Docker) the necessary dependencies are already installed. +::: + +## Testing Documentation Updates Locally + +To verify documentation updates locally, follow the following procedure. The `npm` commands and first step will need to be run from a terminal. + +1. Navigate to the `docs` folder +2. Run `npm ci` to build the necessary tools if you haven't run it before or the ZMK sources were updated +3. Run `npm start` to start the local server that will let you see your documentation updates via a web browser +4. If a web browser doesn't open automatically: you'll need to open a browser window or tab and navigate to `http://localhost:3000` to view your changes +5. Verify the changes look good + +## Formatting and Linting Your Changes + +Prior to submitting a documentation pull request, you'll want to run the format and check commands. These commands are run as part of the verification process on pull requests so it's good to run them ahead of submitting documentation updates. + +The format command can be run with the following procedure in a terminal that's inside the ZMK source directory. + +1. Navigate to the `docs` folder +2. Run `npm run prettier:format` + +The check commands can be run with the following procedure in a terminal that's inside the ZMK source directory. + +1. Navigate to the `docs` folder +2. Run `npm run prettier:check` +3. Run `npm run lint` +4. Run `npm run build` + +:::warning +If any of the above steps throw an error, they need to be addressed and all of the checks re-run prior to submitting a pull request. +::: + +## Submitting a Pull Request + +Once the above sections are complete the documentation updates are ready to submit as a pull request. diff --git a/docs/docs/development/new-shield.md b/docs/docs/development/new-shield.md index 6fac2075..d82cb8ed 100644 --- a/docs/docs/development/new-shield.md +++ b/docs/docs/development/new-shield.md @@ -463,12 +463,22 @@ you should be able to test with a build command like: west build --pristine -b proton_c -- -DSHIELD=my_board ``` -and then flash with: +The above build command generates `build/zephyr/zmk.uf2`. If your board +supports USB Flashing Format (UF2), copy that file onto the root of the USB mass +storage device for your board. The controller should flash your built firmware +and automatically restart once flashing is complete. + +Alternatively, if your board supports flashing and you're not developing from +within a Dockerized environment, enable Device Firmware Upgrade (DFU) mode on +your board and run the following command to test your build: ``` west flash ``` +Please have a look at documentation specific to +[building and flashing](build-flash) for additional information. + :::note Further testing your keyboard shield without altering the root keymap file can be done with the use of `-DZMK_CONFIG` in your `west build` command, shown [here](build-flash#building-from-zmk-config-folder) diff --git a/docs/docs/behaviors/combos.md b/docs/docs/features/combos.md similarity index 92% rename from docs/docs/behaviors/combos.md rename to docs/docs/features/combos.md index e9b01761..845bb018 100644 --- a/docs/docs/behaviors/combos.md +++ b/docs/docs/features/combos.md @@ -1,6 +1,5 @@ --- -title: Combo Behavior -sidebar_label: Combos +title: Combos --- ## Summary @@ -9,7 +8,7 @@ Combo keys are a way to combine multiple keypresses to output a different key. F ### Configuration -Combos are specified like this: +Combos configured in your `.keymap` file, but are separate from the `keymap` node found there, since they are processed before the normal keymap. They are specified like this: ``` / { diff --git a/docs/docs/intro.md b/docs/docs/intro.md index 2215291c..45aadfdd 100644 --- a/docs/docs/intro.md +++ b/docs/docs/intro.md @@ -26,7 +26,7 @@ ZMK is currently missing some features found in other popular firmware. This tab | [Display Support](features/displays)[^2] | 🚧 | 🚧 | βœ… | | [RGB Underglow](features/underglow) | βœ… | βœ… | βœ… | | One Shot Keys | βœ… | βœ… | βœ… | -| [Combo Keys](behaviors/combos) | βœ… | | βœ… | +| [Combo Keys](features/combos) | βœ… | | βœ… | | Macros | 🚧 | βœ… | βœ… | | Mouse Keys | πŸ’‘ | βœ… | βœ… | | Low Active Power Usage | βœ… | | | diff --git a/docs/docs/troubleshooting.md b/docs/docs/troubleshooting.md index 23403eec..5eccb7c1 100644 --- a/docs/docs/troubleshooting.md +++ b/docs/docs/troubleshooting.md @@ -54,7 +54,7 @@ Since then, a much simpler procedure of performing a bluetooth reset for split k **New Procedure:** -1. [Open the GitHub `Actions` tab and select the `Build` workflow](https://github.com/zmkfirmware/zmk/actions?query=workflow%3ABuild+branch%3Amain). +1. [Open the GitHub `Actions` tab and select the `Build` workflow](https://github.com/zmkfirmware/zmk/actions?query=workflow%3ABuild+branch%3Amain+event%3Apush). 1. Select the top 'result' on that page. 1. From the next page under "Artifacts", download the `$boardname-settings_reset-zmk` zip file. 1. Unzip the downloaded file. diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index acf51f4a..f22610a0 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -23,7 +23,7 @@ module.exports = { }, items: [ { - to: "docs/", + to: "docs", activeBasePath: "docs", label: "Docs", position: "left", diff --git a/docs/sidebars.js b/docs/sidebars.js index d095a47e..98ffb19e 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -10,6 +10,7 @@ module.exports = { ], Features: [ "features/keymaps", + "features/combos", "features/displays", "features/encoders", "features/underglow", @@ -20,7 +21,8 @@ module.exports = { "behaviors/misc", "behaviors/hold-tap", "behaviors/mod-tap", - "behaviors/combos", + "behaviors/sticky-key", + "behaviors/sticky-layer", "behaviors/reset", "behaviors/bluetooth", "behaviors/outputs", @@ -40,6 +42,7 @@ module.exports = { ], Development: [ "development/clean-room", + "development/documentation", "development/setup", "development/build-flash", "development/boards-shields-keymaps", diff --git a/docs/src/pages/index.js b/docs/src/pages/index.js index 7019e579..ccaab508 100644 --- a/docs/src/pages/index.js +++ b/docs/src/pages/index.js @@ -59,7 +59,7 @@ function Home() { return (