summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/CMakeLists.txt16
-rw-r--r--app/Kconfig14
-rw-r--r--app/boards/arm/bluemicro840/CMakeLists.txt8
-rw-r--r--app/boards/arm/bluemicro840/Kconfig8
-rw-r--r--app/boards/arm/bluemicro840/Kconfig.board8
-rw-r--r--app/boards/arm/bluemicro840/Kconfig.defconfig30
-rw-r--r--app/boards/arm/bluemicro840/arduino_pro_micro_pins.dtsi52
-rw-r--r--app/boards/arm/bluemicro840/bluemicro840_v1.dts96
-rw-r--r--app/boards/arm/bluemicro840/bluemicro840_v1.yaml15
-rw-r--r--app/boards/arm/bluemicro840/bluemicro840_v1_defconfig20
-rw-r--r--app/boards/arm/bluemicro840/board.cmake5
-rw-r--r--app/boards/arm/nice_nano/Kconfig7
-rw-r--r--app/boards/arm/nice_nano/Kconfig.board1
-rw-r--r--app/boards/arm/nice_nano/Kconfig.defconfig2
-rw-r--r--app/boards/arm/nice_nano/board.cmake2
-rw-r--r--app/boards/arm/nice_nano/nice_nano.dts9
-rw-r--r--app/boards/arm/nrfmicro/CMakeLists.txt14
-rw-r--r--app/boards/arm/nrfmicro/Kconfig10
-rw-r--r--app/boards/arm/nrfmicro/Kconfig.board16
-rw-r--r--app/boards/arm/nrfmicro/Kconfig.defconfig40
-rw-r--r--app/boards/arm/nrfmicro/arduino_pro_micro_pins.dtsi54
-rw-r--r--app/boards/arm/nrfmicro/arduino_pro_micro_pins_flipped.dtsi52
-rw-r--r--app/boards/arm/nrfmicro/board.cmake5
-rw-r--r--app/boards/arm/nrfmicro/nrfmicro_11.dts93
-rw-r--r--app/boards/arm/nrfmicro/nrfmicro_11.yaml15
-rw-r--r--app/boards/arm/nrfmicro/nrfmicro_11_defconfig22
-rw-r--r--app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts93
-rw-r--r--app/boards/arm/nrfmicro/nrfmicro_11_flipped.yaml15
-rw-r--r--app/boards/arm/nrfmicro/nrfmicro_11_flipped_defconfig22
-rw-r--r--app/boards/arm/nrfmicro/nrfmicro_13.dts93
-rw-r--r--app/boards/arm/nrfmicro/nrfmicro_13.yaml15
-rw-r--r--app/boards/arm/nrfmicro/nrfmicro_13_defconfig22
-rw-r--r--app/boards/arm/nrfmicro/pinmux.c41
-rw-r--r--app/boards/arm/planck/planck_rev6.keymap (renamed from app/boards/arm/planck/keymap/keymap.overlay)16
-rw-r--r--app/boards/arm/proton_c/CMakeLists.txt2
-rw-r--r--app/boards/arm/proton_c/pinmux.c2
-rw-r--r--app/boards/native_posix.conf3
-rw-r--r--app/boards/native_posix.overlay73
-rw-r--r--app/boards/shields/clueboard_california/clueboard_california.keymap (renamed from app/boards/shields/clueboard_california/keymap/keymap.overlay)16
-rw-r--r--app/boards/shields/corne/Kconfig.defconfig58
-rw-r--r--app/boards/shields/corne/Kconfig.shield8
-rw-r--r--app/boards/shields/corne/boards/nice_nano.overlay29
-rw-r--r--app/boards/shields/corne/corne.conf6
-rw-r--r--app/boards/shields/corne/corne.dtsi86
-rw-r--r--app/boards/shields/corne/corne.keymap50
-rw-r--r--app/boards/shields/corne/corne_left.conf2
-rw-r--r--app/boards/shields/corne/corne_left.overlay22
-rw-r--r--app/boards/shields/corne/corne_right.conf2
-rw-r--r--app/boards/shields/corne/corne_right.overlay26
-rw-r--r--app/boards/shields/iris/Kconfig.defconfig16
-rw-r--r--app/boards/shields/iris/Kconfig.shield8
-rw-r--r--app/boards/shields/iris/iris.conf (renamed from app/boards/shields/petejohanson_pro_micro_handwire/petejohanson_pro_micro_handwire.conf)0
-rw-r--r--app/boards/shields/iris/iris.dtsi51
-rw-r--r--app/boards/shields/iris/iris.keymap59
-rw-r--r--app/boards/shields/iris/iris_left.conf2
-rw-r--r--app/boards/shields/iris/iris_left.overlay22
-rw-r--r--app/boards/shields/iris/iris_right.conf2
-rw-r--r--app/boards/shields/iris/iris_right.overlay26
-rw-r--r--app/boards/shields/kyria/boards/nice_nano.overlay1
-rw-r--r--app/boards/shields/kyria/boards/nrfmicro_11.overlay29
-rw-r--r--app/boards/shields/kyria/boards/nrfmicro_11_flipped.overlay28
-rw-r--r--app/boards/shields/kyria/boards/nrfmicro_13.overlay28
-rw-r--r--app/boards/shields/kyria/kyria.conf10
-rw-r--r--app/boards/shields/kyria/kyria.dtsi4
-rw-r--r--app/boards/shields/kyria/kyria.keymap (renamed from app/boards/shields/kyria/keymap/keymap.overlay)16
-rw-r--r--app/boards/shields/kyria/kyria_left.overlay4
-rw-r--r--app/boards/shields/kyria/kyria_right.conf2
-rw-r--r--app/boards/shields/kyria/kyria_right.overlay4
-rw-r--r--app/boards/shields/lily58/keymap/keymap.overlay36
-rw-r--r--app/boards/shields/lily58/lily58.conf6
-rw-r--r--app/boards/shields/lily58/lily58.dtsi21
-rw-r--r--app/boards/shields/lily58/lily58.keymap62
-rw-r--r--app/boards/shields/lily58/lily58_left.conf4
-rw-r--r--app/boards/shields/lily58/lily58_left.overlay7
-rw-r--r--app/boards/shields/lily58/lily58_right.overlay3
-rw-r--r--app/boards/shields/petejohanson_handwire/Kconfig.defconfig13
-rw-r--r--app/boards/shields/petejohanson_handwire/Kconfig.shield5
-rw-r--r--app/boards/shields/petejohanson_handwire/keymap/keymap.overlay40
-rw-r--r--app/boards/shields/petejohanson_handwire/petejohanson_handwire.conf1
-rw-r--r--app/boards/shields/petejohanson_handwire/petejohanson_handwire.overlay44
-rw-r--r--app/boards/shields/petejohanson_pro_micro_handwire/Kconfig.defconfig13
-rw-r--r--app/boards/shields/petejohanson_pro_micro_handwire/Kconfig.shield5
-rw-r--r--app/boards/shields/petejohanson_pro_micro_handwire/keymap/keymap.overlay41
-rw-r--r--app/boards/shields/petejohanson_pro_micro_handwire/petejohanson_pro_micro_handwire.overlay17
-rw-r--r--app/boards/shields/qaz/Kconfig.defconfig9
-rw-r--r--app/boards/shields/qaz/Kconfig.shield5
-rw-r--r--app/boards/shields/qaz/qaz.keymap44
-rw-r--r--app/boards/shields/qaz/qaz.overlay53
-rw-r--r--app/boards/shields/romac/Kconfig.defconfig10
-rw-r--r--app/boards/shields/romac/Kconfig.shield5
-rw-r--r--app/boards/shields/romac/romac.conf0
-rw-r--r--app/boards/shields/romac/romac.keymap46
-rw-r--r--app/boards/shields/romac/romac.overlay40
-rw-r--r--app/boards/shields/sofle/Kconfig.defconfig54
-rw-r--r--app/boards/shields/sofle/Kconfig.shield8
-rw-r--r--app/boards/shields/sofle/sofle.conf9
-rw-r--r--app/boards/shields/sofle/sofle.dtsi93
-rw-r--r--app/boards/shields/sofle/sofle.keymap63
-rw-r--r--app/boards/shields/sofle/sofle_left.conf5
-rw-r--r--app/boards/shields/sofle/sofle_left.overlay26
-rw-r--r--app/boards/shields/sofle/sofle_right.conf5
-rw-r--r--app/boards/shields/sofle/sofle_right.overlay30
-rw-r--r--app/boards/shields/splitreus62/Kconfig.defconfig22
-rw-r--r--app/boards/shields/splitreus62/Kconfig.shield8
-rw-r--r--app/boards/shields/splitreus62/splitreus62.conf0
-rw-r--r--app/boards/shields/splitreus62/splitreus62.dtsi50
-rw-r--r--app/boards/shields/splitreus62/splitreus62.keymap31
-rw-r--r--app/boards/shields/splitreus62/splitreus62_left.conf2
-rw-r--r--app/boards/shields/splitreus62/splitreus62_left.overlay18
-rw-r--r--app/boards/shields/splitreus62/splitreus62_right.conf2
-rw-r--r--app/boards/shields/splitreus62/splitreus62_right.overlay22
-rw-r--r--app/cmake/zmk_config.cmake55
-rw-r--r--app/drivers/zephyr/Kconfig5
-rw-r--r--app/drivers/zephyr/ec11_trigger.c2
-rw-r--r--app/drivers/zephyr/kscan_gpio_direct.c4
-rw-r--r--app/drivers/zephyr/kscan_gpio_matrix.c12
-rw-r--r--app/dts/behaviors.dtsi3
-rw-r--r--app/dts/behaviors/layer_tap.dtsi12
-rw-r--r--app/dts/behaviors/mod_tap.dtsi5
-rw-r--r--app/dts/behaviors/none.dtsi15
-rw-r--r--app/dts/behaviors/reset.dtsi9
-rw-r--r--app/dts/behaviors/toggle_layer.dtsi15
-rw-r--r--app/dts/bindings/behaviors/zmk,behavior-hold-tap.yaml23
-rw-r--r--app/dts/bindings/behaviors/zmk,behavior-mod-tap.yaml8
-rw-r--r--app/dts/bindings/behaviors/zmk,behavior-none.yaml8
-rw-r--r--app/dts/bindings/behaviors/zmk,behavior-reset.yaml5
-rw-r--r--app/dts/bindings/behaviors/zmk,behavior-toggle-layer.yaml8
-rw-r--r--app/dts/bindings/zmk,bt-unpair-combo.yaml12
-rw-r--r--app/dts/bindings/zmk,keymap.yaml22
-rw-r--r--app/dts/bindings/zmk,kscan-mock.yaml2
-rw-r--r--app/dts/bindings/zmk,layers.yaml18
-rw-r--r--app/include/dt-bindings/zmk/keys.h13
-rw-r--r--app/include/dt-bindings/zmk/kscan-mock.h (renamed from app/include/zmk/kscan-mock.h)0
-rw-r--r--app/include/dt-bindings/zmk/reset.h12
-rw-r--r--app/include/zmk/ble.h2
-rw-r--r--app/include/zmk/event-manager.h23
-rw-r--r--app/include/zmk/keymap.h2
-rw-r--r--app/prj.conf0
-rwxr-xr-xapp/run-test.sh40
-rw-r--r--app/src/behaviors/behavior_hold_tap.c502
-rw-r--r--app/src/behaviors/behavior_key_press.c14
-rw-r--r--app/src/behaviors/behavior_mod_tap.c83
-rw-r--r--app/src/behaviors/behavior_none.c48
-rw-r--r--app/src/behaviors/behavior_reset.c29
-rw-r--r--app/src/behaviors/behavior_toggle_layer.c56
-rw-r--r--app/src/ble.c53
-rw-r--r--app/src/ble_unpair_combo.c83
-rw-r--r--app/src/event_manager.c68
-rw-r--r--app/src/events/keycode_state_changed.c2
-rw-r--r--app/src/keymap.c173
-rw-r--r--app/src/kscan_mock.c15
-rw-r--r--app/src/split/bluetooth/central.c14
-rw-r--r--app/src/usb_hid.c36
-rw-r--r--app/tests/hold-tap/README.md1
-rw-r--r--app/tests/hold-tap/balanced/1-dn-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/1-dn-up/keycode_events.snapshot5
-rw-r--r--app/tests/hold-tap/balanced/1-dn-up/native_posix.keymap11
-rw-r--r--app/tests/hold-tap/balanced/2-dn-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/2-dn-timer-up/keycode_events.snapshot5
-rw-r--r--app/tests/hold-tap/balanced/2-dn-timer-up/native_posix.keymap11
-rw-r--r--app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/native_posix.keymap13
-rw-r--r--app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/native_posix.keymap13
-rw-r--r--app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/native_posix.keymap13
-rw-r--r--app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/keycode_events.snapshot10
-rw-r--r--app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/balanced/behavior_keymap.dtsi27
-rw-r--r--app/tests/hold-tap/hold-preferred/1-dn-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/1-dn-up/keycode_events.snapshot5
-rw-r--r--app/tests/hold-tap/hold-preferred/1-dn-up/native_posix.keymap11
-rw-r--r--app/tests/hold-tap/hold-preferred/2-dn-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/2-dn-timer-up/keycode_events.snapshot5
-rw-r--r--app/tests/hold-tap/hold-preferred/2-dn-timer-up/native_posix.keymap11
-rw-r--r--app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/native_posix.keymap13
-rw-r--r--app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/native_posix.keymap13
-rw-r--r--app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/native_posix.keymap13
-rw-r--r--app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot10
-rw-r--r--app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/events.patterns4
-rw-r--r--app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/hold-preferred/behavior_keymap.dtsi29
-rw-r--r--app/tests/hold-tap/tap-preferred/1-dn-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/1-dn-up/keycode_events.snapshot5
-rw-r--r--app/tests/hold-tap/tap-preferred/1-dn-up/native_posix.keymap11
-rw-r--r--app/tests/hold-tap/tap-preferred/2-dn-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/2-dn-timer-up/keycode_events.snapshot5
-rw-r--r--app/tests/hold-tap/tap-preferred/2-dn-timer-up/native_posix.keymap11
-rw-r--r--app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/native_posix.keymap13
-rw-r--r--app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/native_posix.keymap13
-rw-r--r--app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/native_posix.keymap13
-rw-r--r--app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot10
-rw-r--r--app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/events.patterns4
-rw-r--r--app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot7
-rw-r--r--app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/native_posix.keymap14
-rw-r--r--app/tests/hold-tap/tap-preferred/behavior_keymap.dtsi27
-rw-r--r--app/tests/hold-tap/zmk-modtap-proposal.odgbin0 -> 23148 bytes
-rw-r--r--app/tests/hold-tap/zmk-modtap-proposal.pdfbin0 -> 25493 bytes
-rw-r--r--app/tests/keypress/behavior_keymap.dtsi28
-rw-r--r--app/tests/keypress/cp-press-release/events.patterns1
-rw-r--r--app/tests/keypress/cp-press-release/keycode_events.snapshot2
-rw-r--r--app/tests/keypress/cp-press-release/native_posix.keymap5
-rw-r--r--app/tests/keypress/kp-press-release/events.patterns1
-rw-r--r--app/tests/keypress/kp-press-release/keycode_events.snapshot2
-rw-r--r--app/tests/keypress/kp-press-release/native_posix.keymap8
-rw-r--r--app/tests/momentary-layer/behavior_keymap.dtsi28
-rw-r--r--app/tests/momentary-layer/early-key-release/events.patterns2
-rw-r--r--app/tests/momentary-layer/early-key-release/keycode_events.snapshot4
-rw-r--r--app/tests/momentary-layer/early-key-release/native_posix.keymap8
-rw-r--r--app/tests/momentary-layer/early-key-release/pending0
-rw-r--r--app/tests/momentary-layer/normal/events.patterns2
-rw-r--r--app/tests/momentary-layer/normal/keycode_events.snapshot4
-rw-r--r--app/tests/momentary-layer/normal/native_posix.keymap8
-rw-r--r--app/tests/none/behavior_keymap.dtsi22
-rw-r--r--app/tests/none/layered/events.patterns1
-rw-r--r--app/tests/none/layered/keycode_events.snapshot0
-rw-r--r--app/tests/none/layered/native_posix.keymap8
-rw-r--r--app/tests/none/normal/events.patterns1
-rw-r--r--app/tests/none/normal/keycode_events.snapshot0
-rw-r--r--app/tests/none/normal/native_posix.keymap8
-rw-r--r--app/tests/toggle-layer/behavior_keymap.dtsi28
-rw-r--r--app/tests/toggle-layer/early-key-release/events.patterns2
-rw-r--r--app/tests/toggle-layer/early-key-release/keycode_events.snapshot6
-rw-r--r--app/tests/toggle-layer/early-key-release/native_posix.keymap9
-rw-r--r--app/tests/toggle-layer/early-key-release/pending0
-rw-r--r--app/tests/toggle-layer/normal/events.patterns2
-rw-r--r--app/tests/toggle-layer/normal/keycode_events.snapshot4
-rw-r--r--app/tests/toggle-layer/normal/native_posix.keymap8
-rw-r--r--app/tests/transparent/behavior_keymap.dtsi22
-rw-r--r--app/tests/transparent/layered/events.patterns1
-rw-r--r--app/tests/transparent/layered/keycode_events.snapshot2
-rw-r--r--app/tests/transparent/layered/native_posix.keymap8
-rw-r--r--app/tests/transparent/normal/events.patterns1
-rw-r--r--app/tests/transparent/normal/keycode_events.snapshot0
-rw-r--r--app/tests/transparent/normal/native_posix.keymap8
-rw-r--r--app/west.yml12
296 files changed, 4583 insertions, 669 deletions
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index 3734101..2e24fdc 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -1,4 +1,3 @@
-# Find Zephyr. This also loads Zephyr's build system.
cmake_minimum_required(VERSION 3.13.1)
set(CONFIG_APPLICATION_DEFINED_SYSCALL true)
@@ -15,13 +14,10 @@ list(APPEND SYSCALL_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/drivers/zephyr)
include(cmake/zmk_config.cmake)
+# Find Zephyr. This also loads Zephyr's build system.
find_package(Zephyr REQUIRED HINTS ../zephyr)
project(zmk)
-if(EXISTS ${KEYMAP_DIR}/keymap.c)
- target_sources(app PRIVATE ${KEYMAP_DIR}/keymap.c)
-endif()
-
zephyr_linker_sources(RODATA include/linker/zmk-events.ld)
# Add your source file to the "app" target. This must come after
@@ -29,8 +25,6 @@ zephyr_linker_sources(RODATA include/linker/zmk-events.ld)
target_include_directories(app PRIVATE include)
target_sources(app PRIVATE src/kscan.c)
target_sources(app PRIVATE src/matrix_transform.c)
-target_sources(app PRIVATE src/keymap.c)
-target_sources(app PRIVATE src/hid_listener.c)
target_sources(app PRIVATE src/hid.c)
target_sources(app PRIVATE src/sensors.c)
target_sources_ifdef(CONFIG_ZMK_DISPLAY app PRIVATE src/display.c)
@@ -41,12 +35,16 @@ target_sources(app PRIVATE src/events/modifiers_state_changed.c)
target_sources(app PRIVATE src/events/sensor_event.c)
target_sources(app PRIVATE src/behaviors/behavior_key_press.c)
target_sources(app PRIVATE src/behaviors/behavior_reset.c)
-target_sources(app PRIVATE src/behaviors/behavior_mod_tap.c)
+target_sources(app PRIVATE src/behaviors/behavior_hold_tap.c)
target_sources(app PRIVATE src/behaviors/behavior_momentary_layer.c)
+target_sources(app PRIVATE src/behaviors/behavior_toggle_layer.c)
target_sources(app PRIVATE src/behaviors/behavior_transparent.c)
+target_sources(app PRIVATE src/behaviors/behavior_none.c)
target_sources(app PRIVATE src/behaviors/behavior_sensor_rotate_key_press.c)
+target_sources(app PRIVATE src/keymap.c)
target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/behaviors/behavior_rgb_underglow.c)
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble.c)
+target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble_unpair_combo.c)
target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL app PRIVATE src/split_listener.c)
target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL app PRIVATE src/split/bluetooth/service.c)
target_sources_ifdef(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL app PRIVATE src/split/bluetooth/central.c)
@@ -56,5 +54,7 @@ target_sources_ifdef(CONFIG_ZMK_USB app PRIVATE src/usb_hid.c)
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/hog.c)
target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/rgb_underglow.c)
target_sources(app PRIVATE src/endpoints.c)
+target_sources(app PRIVATE src/hid_listener.c)
target_sources(app PRIVATE src/main.c)
+zephyr_cc_option(-Wfatal-errors) \ No newline at end of file
diff --git a/app/Kconfig b/app/Kconfig
index 01384a0..877fce4 100644
--- a/app/Kconfig
+++ b/app/Kconfig
@@ -41,7 +41,7 @@ menuconfig ZMK_BLE
select BT_GATT_DIS
select BT_GATT_BAS
select SETTINGS
- select BT_SETTINGS
+ # select BT_SETTINGS
if ZMK_BLE
@@ -88,6 +88,7 @@ config ZMK_SPLIT_BLE
bool "Split keyboard support via BLE transport"
depends on ZMK_BLE
default y
+ select BT_USER_PHY_UPDATE
if ZMK_SPLIT_BLE
@@ -105,6 +106,10 @@ if ZMK_SPLIT_BLE_ROLE_CENTRAL
config BT_MAX_CONN
default 5
+config BT_MAX_PAIRED
+ # Bump this everywhere once we support switching active connections!
+ default 2
+
endif
config ZMK_SPLIT_BLE_ROLE_PERIPHERAL
@@ -119,6 +124,9 @@ config ZMK_USB
config BT_MAX_CONN
default 5
+config BT_GAP_AUTO_UPDATE_CONN_PARAMS
+ default n
+
endif
endchoice
@@ -185,6 +193,10 @@ source "subsys/logging/Kconfig.template.log_config"
rsource "boards/Kconfig"
rsource "boards/shields/*/Kconfig.defconfig"
+rsource "boards/shields/*/Kconfig.shield"
+
+osource "$(ZMK_CONFIG)/boards/shields/*/Kconfig.defconfig"
+osource "$(ZMK_CONFIG)/boards/shields/*/Kconfig.shield"
source "Kconfig.zephyr"
diff --git a/app/boards/arm/bluemicro840/CMakeLists.txt b/app/boards/arm/bluemicro840/CMakeLists.txt
new file mode 100644
index 0000000..00952c3
--- /dev/null
+++ b/app/boards/arm/bluemicro840/CMakeLists.txt
@@ -0,0 +1,8 @@
+set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
+ COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/../tools/uf2/utils/uf2conv.py
+ -c
+ -b 0x26000
+ -f 0xADA52840
+ -o ${PROJECT_BINARY_DIR}/${CONFIG_KERNEL_BIN_NAME}.uf2
+ ${PROJECT_BINARY_DIR}/${CONFIG_KERNEL_BIN_NAME}.bin
+)
diff --git a/app/boards/arm/bluemicro840/Kconfig b/app/boards/arm/bluemicro840/Kconfig
new file mode 100644
index 0000000..0e6743d
--- /dev/null
+++ b/app/boards/arm/bluemicro840/Kconfig
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: MIT
+
+config BOARD_ENABLE_DCDC
+ bool "Enable DCDC mode"
+ select SOC_DCDC_NRF52X
+ default y
+ depends on BOARD_BLUEMICRO840_V1
+
diff --git a/app/boards/arm/bluemicro840/Kconfig.board b/app/boards/arm/bluemicro840/Kconfig.board
new file mode 100644
index 0000000..bc271af
--- /dev/null
+++ b/app/boards/arm/bluemicro840/Kconfig.board
@@ -0,0 +1,8 @@
+# BlueMicro840 board configuration
+
+# Copyright (c) 2020 Pete Johanson, Derek Schmell
+# SPDX-License-Identifier: MIT
+
+config BOARD_BLUEMICRO840_V1
+ bool "BlueMicro840_V1"
+ depends on SOC_NRF52840_QIAA
diff --git a/app/boards/arm/bluemicro840/Kconfig.defconfig b/app/boards/arm/bluemicro840/Kconfig.defconfig
new file mode 100644
index 0000000..566b5a4
--- /dev/null
+++ b/app/boards/arm/bluemicro840/Kconfig.defconfig
@@ -0,0 +1,30 @@
+# BlueMicro840 board configuration
+
+# Copyright (c) 2020 Pete Johanson, Derek Schmell
+# SPDX-License-Identifier: MIT
+
+if BOARD_BLUEMICRO840_V1
+
+config BOARD
+ default "bluemicro840_v1"
+
+if USB
+
+config USB_NRFX
+ default y
+
+config USB_DEVICE_STACK
+ default y
+
+endif # USB
+
+config BT_CTLR
+ default BT
+
+config ZMK_BLE
+ default y
+
+config ZMK_USB
+ default y
+
+endif # BOARD_BLUEMICRO840_V1
diff --git a/app/boards/arm/bluemicro840/arduino_pro_micro_pins.dtsi b/app/boards/arm/bluemicro840/arduino_pro_micro_pins.dtsi
new file mode 100644
index 0000000..940d891
--- /dev/null
+++ b/app/boards/arm/bluemicro840/arduino_pro_micro_pins.dtsi
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2020 Derek Schmell
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+/ {
+ pro_micro_d: connector_d {
+ compatible = "arduino-pro-micro";
+ #gpio-cells = <2>;
+ gpio-map-mask = <0xffffffff 0xffffffc0>;
+ gpio-map-pass-thru = <0 0x3f>;
+ gpio-map
+ = <0 0 &gpio0 8 0> /* D0 D2 */
+ , <1 0 &gpio0 6 0> /* D1 D3*/
+ , <2 0 &gpio0 15 0> /* D2 D1*/
+ , <3 0 &gpio0 17 0> /* D3 D0*/
+ , <4 0 &gpio0 20 0> /* D4/A6 D4*/
+ , <5 0 &gpio0 13 0> /* D5 C6*/
+ , <6 0 &gpio0 24 0> /* D6/A7 D7*/
+ , <7 0 &gpio0 9 0> /* D7 E6*/
+ , <8 0 &gpio0 10 0> /* D8/A8 B4*/
+ , <9 0 &gpio1 6 0> /* D9/A9 B5*/
+ , <10 0 &gpio1 11 0> /* D10/A10 B6*/
+ , <16 0 &gpio0 28 0> /* D16 B2*/
+ , <14 0 &gpio0 3 0> /* D14 B3*/
+ , <15 0 &gpio1 13 0> /* D15 B1*/
+ ;
+ };
+
+ pro_micro_a: connector_a {
+ compatible = "arduino-pro-micro";
+ #gpio-cells = <2>;
+ gpio-map-mask = <0xffffffff 0xffffffc0>;
+ gpio-map-pass-thru = <0 0x3f>;
+ gpio-map
+ = <0 0 &gpio0 2 0> /* A0 F7*/
+ , <1 0 &gpio0 29 0> /* A1 F6*/
+ , <2 0 &gpio0 26 0> /* A2 F5*/
+ , <3 0 &gpio0 30 0> /* A3 F4*/
+ , <6 0 &gpio0 20 0> /* D4/A6 D4*/
+ , <7 0 &gpio0 24 0> /* D6/A7 D7*/
+ , <8 0 &gpio0 10 0> /* D8/A8 B4*/
+ , <9 0 &gpio1 6 0> /* D9/A9 B5*/
+ , <10 0 &gpio1 13 0> /* D10/A10 B6*/
+ ;
+ };
+};
+
+pro_micro_i2c: &i2c0 {};
+pro_micro_spi: &spi0 {};
+pro_micro_serial: &uart0 {};
diff --git a/app/boards/arm/bluemicro840/bluemicro840_v1.dts b/app/boards/arm/bluemicro840/bluemicro840_v1.dts
new file mode 100644
index 0000000..c693662
--- /dev/null
+++ b/app/boards/arm/bluemicro840/bluemicro840_v1.dts
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2020 Pete Johanson, Derek Schmell
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+/dts-v1/;
+#include <nordic/nrf52840_qiaa.dtsi>
+#include "arduino_pro_micro_pins.dtsi"
+
+/ {
+ model = "BlueMicro840_V1";
+ compatible = "bluemicro840,v1";
+
+ chosen {
+ zephyr,code-partition = &code_partition;
+ // zephyr,console = &uart0;
+ //zephyr,bt-mon-uart = &uart0;
+ //zephyr,bt-c2h-uart = &uart0;
+ zephyr,sram = &sram0;
+ zephyr,flash = &flash0;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ blue_led: led_0 {
+ gpios = <&gpio0 42 GPIO_ACTIVE_HIGH>;
+ label = "Blue LED";
+ };
+ };
+
+};
+
+&gpio0 {
+ status = "okay";
+};
+
+&gpio1 {
+ status = "okay";
+};
+
+&i2c0 {
+ compatible = "nordic,nrf-twi";
+ sda-pin = <15>;
+ scl-pin = <17>;
+};
+
+&uart0 {
+ compatible = "nordic,nrf-uarte";
+ status = "okay";
+ current-speed = <115200>;
+ tx-pin = <39>;
+ rx-pin = <34>;
+ rts-pin = <33>;
+ cts-pin = <12>;
+};
+
+&usbd {
+ status = "okay";
+};
+
+
+&flash0 {
+ /*
+ * For more information, see:
+ * http://docs.zephyrproject.org/latest/devices/dts/flash_partitions.html
+ */
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ boot_partition: partition@0 {
+ label = "adafruit_boot";
+ reg = <0x000000000 0x0000C000>;
+ };
+ code_partition: partition@26000 {
+ label = "code_partition";
+ reg = <0x00026000 0x000d2000>;
+ };
+
+ /*
+ * The flash starting at 0x000f8000 and ending at
+ * 0x000fffff is reserved for use by the application.
+ */
+
+ /*
+ * Storage partition will be used by FCB/LittleFS/NVS
+ * if enabled.
+ */
+ storage_partition: partition@f8000 {
+ label = "storage";
+ reg = <0x000f8000 0x00008000>;
+ };
+ };
+};
diff --git a/app/boards/arm/bluemicro840/bluemicro840_v1.yaml b/app/boards/arm/bluemicro840/bluemicro840_v1.yaml
new file mode 100644
index 0000000..9e1dd54
--- /dev/null
+++ b/app/boards/arm/bluemicro840/bluemicro840_v1.yaml
@@ -0,0 +1,15 @@
+identifier: bluemicro840_v1
+name: BlueMicro840_V1
+type: mcu
+arch: arm
+toolchain:
+ - zephyr
+ - gnuarmemb
+ - xtools
+supported:
+ - adc
+ - usb_device
+ - ble
+ - ieee802154
+ - pwm
+ - watchdog
diff --git a/app/boards/arm/bluemicro840/bluemicro840_v1_defconfig b/app/boards/arm/bluemicro840/bluemicro840_v1_defconfig
new file mode 100644
index 0000000..96f03ca
--- /dev/null
+++ b/app/boards/arm/bluemicro840/bluemicro840_v1_defconfig
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: MIT
+
+CONFIG_SOC_SERIES_NRF52X=y
+CONFIG_SOC_NRF52840_QIAA=y
+CONFIG_BOARD_BLUEMICRO840_V1=y
+
+# Enable MPU
+CONFIG_ARM_MPU=y
+
+# enable GPIO
+CONFIG_GPIO=y
+
+CONFIG_USE_DT_CODE_PARTITION=y
+
+CONFIG_MPU_ALLOW_FLASH_WRITE=y
+CONFIG_NVS=y
+CONFIG_SETTINGS_NVS=y
+CONFIG_FLASH=y
+CONFIG_FLASH_PAGE_LAYOUT=y
+CONFIG_FLASH_MAP=y \ No newline at end of file
diff --git a/app/boards/arm/bluemicro840/board.cmake b/app/boards/arm/bluemicro840/board.cmake
new file mode 100644
index 0000000..fa847d5
--- /dev/null
+++ b/app/boards/arm/bluemicro840/board.cmake
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+
+board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset")
+include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake)
+include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
diff --git a/app/boards/arm/nice_nano/Kconfig b/app/boards/arm/nice_nano/Kconfig
new file mode 100644
index 0000000..fb5537a
--- /dev/null
+++ b/app/boards/arm/nice_nano/Kconfig
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: MIT
+
+config BOARD_ENABLE_DCDC
+ bool "Enable DCDC mode"
+ select SOC_DCDC_NRF52X
+ default y
+ depends on BOARD_NICE_NANO
diff --git a/app/boards/arm/nice_nano/Kconfig.board b/app/boards/arm/nice_nano/Kconfig.board
index 60ee58b..4fd394f 100644
--- a/app/boards/arm/nice_nano/Kconfig.board
+++ b/app/boards/arm/nice_nano/Kconfig.board
@@ -6,3 +6,4 @@
config BOARD_NICE_NANO
bool "nice!nano"
depends on SOC_NRF52840_QIAA
+
diff --git a/app/boards/arm/nice_nano/Kconfig.defconfig b/app/boards/arm/nice_nano/Kconfig.defconfig
index 2431813..0961ddd 100644
--- a/app/boards/arm/nice_nano/Kconfig.defconfig
+++ b/app/boards/arm/nice_nano/Kconfig.defconfig
@@ -1,5 +1,3 @@
-# Electronut Labs Papyr board configuration
-
# Copyright (c) 2020 Pete Johanson
# SPDX-License-Identifier: MIT
diff --git a/app/boards/arm/nice_nano/board.cmake b/app/boards/arm/nice_nano/board.cmake
index 12a1d93..fa847d5 100644
--- a/app/boards/arm/nice_nano/board.cmake
+++ b/app/boards/arm/nice_nano/board.cmake
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: Apache-2.0
+# SPDX-License-Identifier: MIT
board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset")
include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake)
diff --git a/app/boards/arm/nice_nano/nice_nano.dts b/app/boards/arm/nice_nano/nice_nano.dts
index 7c676e3..2e9556b 100644
--- a/app/boards/arm/nice_nano/nice_nano.dts
+++ b/app/boards/arm/nice_nano/nice_nano.dts
@@ -24,7 +24,7 @@
leds {
compatible = "gpio-leds";
blue_led: led_0 {
- gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
+ gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
label = "Blue LED";
};
};
@@ -39,13 +39,6 @@
status = "okay";
};
-&uart0 {
- compatible = "nordic,nrf-uart";
- current-speed = <115200>;
- tx-pin = <6>;
- rx-pin = <8>;
-};
-
&i2c0 {
compatible = "nordic,nrf-twi";
sda-pin = <17>;
diff --git a/app/boards/arm/nrfmicro/CMakeLists.txt b/app/boards/arm/nrfmicro/CMakeLists.txt
new file mode 100644
index 0000000..cd4843a
--- /dev/null
+++ b/app/boards/arm/nrfmicro/CMakeLists.txt
@@ -0,0 +1,14 @@
+set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
+ COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/../tools/uf2/utils/uf2conv.py
+ -c
+ -b 0x26000
+ -f 0xADA52840
+ -o ${PROJECT_BINARY_DIR}/${CONFIG_KERNEL_BIN_NAME}.uf2
+ ${PROJECT_BINARY_DIR}/${CONFIG_KERNEL_BIN_NAME}.bin
+)
+
+if(CONFIG_PINMUX)
+zephyr_library()
+zephyr_library_sources(pinmux.c)
+zephyr_library_include_directories(${ZEPHYR_BASE}/drivers)
+endif() \ No newline at end of file
diff --git a/app/boards/arm/nrfmicro/Kconfig b/app/boards/arm/nrfmicro/Kconfig
new file mode 100644
index 0000000..3501972
--- /dev/null
+++ b/app/boards/arm/nrfmicro/Kconfig
@@ -0,0 +1,10 @@
+config BOARD_ENABLE_DCDC
+ bool "Enable DCDC mode"
+ select SOC_DCDC_NRF52X
+ default y
+ depends on (BOARD_NRFMICRO_11 || BOARD_NRFMICRO_11_FLIPPED || BOARD_NRFMICRO_13)
+
+config BOARD_NRFMICRO_CHARGER
+ bool "Enable battery charger"
+ default y
+ depends on (BOARD_NRFMICRO_13)
diff --git a/app/boards/arm/nrfmicro/Kconfig.board b/app/boards/arm/nrfmicro/Kconfig.board
new file mode 100644
index 0000000..177373a
--- /dev/null
+++ b/app/boards/arm/nrfmicro/Kconfig.board
@@ -0,0 +1,16 @@
+# nrfmicro board configuration
+
+# Copyright (c) 2020 Okke Formsma, joric
+# SPDX-License-Identifier: MIT
+
+config BOARD_NRFMICRO_11
+ bool "nrfmicro_11"
+ depends on SOC_NRF52840_QIAA
+
+config BOARD_NRFMICRO_11_FLIPPED
+ bool "nrfmicro_11_flipped"
+ depends on SOC_NRF52840_QIAA
+
+config BOARD_NRFMICRO_13
+ bool "nrfmicro_13"
+ depends on SOC_NRF52840_QIAA
diff --git a/app/boards/arm/nrfmicro/Kconfig.defconfig b/app/boards/arm/nrfmicro/Kconfig.defconfig
new file mode 100644
index 0000000..9cce5a9
--- /dev/null
+++ b/app/boards/arm/nrfmicro/Kconfig.defconfig
@@ -0,0 +1,40 @@
+# Electronut Labs Papyr board configuration
+
+# Copyright (c) 2020 Okke Formsma, joric
+# SPDX-License-Identifier: MIT
+
+if BOARD_NRFMICRO_11 || BOARD_NRFMICRO_11_FLIPPED || BOARD_NRFMICRO_13
+
+config BOARD
+ default "nrfmicro"
+
+if USB
+
+config USB_NRFX
+ default y
+
+config USB_DEVICE_STACK
+ default y
+
+endif # USB
+
+config BT_CTLR
+ default BT
+
+config ZMK_BLE
+ default y
+
+config ZMK_USB
+ default y
+
+config PINMUX
+ default y
+
+if BOARD_NRFMICRO_13
+
+config BOARD_NRFMICRO_CHARGER
+ default y
+
+endif # BOARD_NRFMICRO_13
+
+endif # BOARD_NRFMICRO_11 || BOARD_NRFMICRO_11_FLIPPED || BOARD_NRFMICRO_13
diff --git a/app/boards/arm/nrfmicro/arduino_pro_micro_pins.dtsi b/app/boards/arm/nrfmicro/arduino_pro_micro_pins.dtsi
new file mode 100644
index 0000000..6cde2b4
--- /dev/null
+++ b/app/boards/arm/nrfmicro/arduino_pro_micro_pins.dtsi
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2020 Okke Formsma, joric
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+
+/ {
+ pro_micro_d: connector_d {
+ compatible = "arduino-pro-micro";
+ #gpio-cells = <2>;
+ gpio-map-mask = <0xffffffff 0xffffffc0>;
+ gpio-map-pass-thru = <0 0x3f>;
+ gpio-map
+ = <0 0 &gpio0 8 0> /* D0 */
+ , <1 0 &gpio0 6 0> /* D1 */
+ , <2 0 &gpio0 15 0> /* D2 */
+ , <3 0 &gpio0 17 0> /* D3 */
+ , <4 0 &gpio0 20 0> /* D4/A6 */
+ , <5 0 &gpio0 13 0> /* D5 */
+ , <6 0 &gpio0 24 0> /* D6/A7 */
+ , <7 0 &gpio0 9 0> /* D7 */
+ , <8 0 &gpio0 10 0> /* D8/A8 */
+ , <9 0 &gpio1 6 0> /* D9/A9 */
+ , <10 0 &gpio1 11 0> /* D10/A10 */
+ , <16 0 &gpio0 28 0> /* D16 */
+ , <14 0 &gpio0 3 0> /* D14 */
+ , <15 0 &gpio1 13 0> /* D15 */
+ ;
+ };
+
+ pro_micro_a: connector_a {
+ compatible = "arduino-pro-micro";
+ #gpio-cells = <2>;
+ gpio-map-mask = <0xffffffff 0xffffffc0>;
+ gpio-map-pass-thru = <0 0x3f>;
+ gpio-map
+ = <0 0 &gpio0 2 0> /* A0 */
+ , <1 0 &gpio0 29 0> /* A1 */
+ , <2 0 &gpio0 31 0> /* A2 */
+ , <3 0 &gpio0 30 0> /* A3 */
+ , <6 0 &gpio0 20 0> /* D4/A6 */
+ , <7 0 &gpio0 24 0> /* D6/A7 */
+ , <8 0 &gpio0 10 0> /* D8/A8 */
+ , <9 0 &gpio1 6 0> /* D9/A9 */
+ , <10 0 &gpio1 11 0> /* D10/A10 */
+ ;
+ };
+};
+
+
+pro_micro_i2c: &i2c0 {};
+pro_micro_spi: &spi0 {};
+pro_micro_serial: &uart0 {};
diff --git a/app/boards/arm/nrfmicro/arduino_pro_micro_pins_flipped.dtsi b/app/boards/arm/nrfmicro/arduino_pro_micro_pins_flipped.dtsi
new file mode 100644
index 0000000..9bad7f4
--- /dev/null
+++ b/app/boards/arm/nrfmicro/arduino_pro_micro_pins_flipped.dtsi
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2020 Okke Formsma, joric
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+/ {
+ pro_micro_d: connector_d {
+ compatible = "arduino-pro-micro";
+ #gpio-cells = <2>;
+ gpio-map-mask = <0xffffffff 0xffffffc0>;
+ gpio-map-pass-thru = <0 0x3f>;
+ gpio-map
+ = <0 0 &gpio0 8 0> /* D0 */
+ , <1 0 &gpio0 6 0> /* D1 */
+ , <2 0 &gpio0 30 0> /* D2 */
+ , <3 0 &gpio0 31 0> /* D3 */
+ , <4 0 &gpio0 29 0> /* D4/A6 */
+ , <5 0 &gpio0 2 0> /* D5 */
+ , <6 0 &gpio1 13 0> /* D6/A7 */
+ , <7 0 &gpio0 3 0> /* D7 */
+ , <8 0 &gpio0 28 0> /* D8/A8 */
+ , <9 0 &gpio1 11 0> /* D9/A9 */
+ , <10 0 &gpio1 6 0> /* D10/A10 */
+ , <16 0 &gpio0 10 0> /* D16 */
+ , <14 0 &gpio0 9 0> /* D14 */
+ , <15 0 &gpio0 24 0> /* D15 */
+ ;
+ };
+
+ pro_micro_a: connector_a {
+ compatible = "arduino-pro-micro";
+ #gpio-cells = <2>;
+ gpio-map-mask = <0xffffffff 0xffffffc0>;
+ gpio-map-pass-thru = <0 0x3f>;
+ gpio-map
+ = <0 0 &gpio0 13 0> /* A0 */
+ , <1 0 &gpio0 20 0> /* A1 */
+ , <2 0 &gpio0 17 0> /* A2 */
+ , <3 0 &gpio0 15 0> /* A3 */
+ , <6 0 &gpio0 29 0> /* D4/A6 */
+ , <7 0 &gpio1 13 0> /* D6/A7 */
+ , <8 0 &gpio0 28 0> /* D8/A8 */
+ , <9 0 &gpio1 11 0> /* D9/A9 */
+ , <10 0 &gpio1 6 0> /* D10/A10 */
+ ;
+ };
+};
+
+pro_micro_i2c: &i2c0 {};
+pro_micro_spi: &spi0 {};
+pro_micro_serial: &uart0 {};
diff --git a/app/boards/arm/nrfmicro/board.cmake b/app/boards/arm/nrfmicro/board.cmake
new file mode 100644
index 0000000..fa847d5
--- /dev/null
+++ b/app/boards/arm/nrfmicro/board.cmake
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+
+board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset")
+include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake)
+include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
diff --git a/app/boards/arm/nrfmicro/nrfmicro_11.dts b/app/boards/arm/nrfmicro/nrfmicro_11.dts
new file mode 100644
index 0000000..dc07ac8
--- /dev/null
+++ b/app/boards/arm/nrfmicro/nrfmicro_11.dts
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2020 Okke Formsma, joric
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+/dts-v1/;
+#include <nordic/nrf52840_qiaa.dtsi>
+#include "arduino_pro_micro_pins.dtsi"
+
+/ {
+ model = "nrfmicro";
+ compatible = "joric,nrfmicro";
+
+ chosen {
+ zephyr,code-partition = &code_partition;
+ zephyr,sram = &sram0;
+ zephyr,flash = &flash0;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ blue_led: led_0 {
+ gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+ label = "Blue LED";
+ };
+ };
+
+};
+
+&gpio0 {
+ status = "okay";
+};
+
+&gpio1 {
+ status = "okay";
+};
+
+&i2c0 {
+ compatible = "nordic,nrf-twi";
+ sda-pin = <15>;
+ scl-pin = <17>;
+};
+
+&uart0 {
+ compatible = "nordic,nrf-uarte";
+ status = "okay";
+ current-speed = <115200>;
+ tx-pin = <39>;
+ rx-pin = <34>;
+ rts-pin = <33>;
+ cts-pin = <12>;
+};
+
+&usbd {
+ status = "okay";
+};
+
+
+&flash0 {
+ /*
+ * For more information, see:
+ * http://docs.zephyrproject.org/latest/devices/dts/flash_partitions.html
+ */
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ boot_partition: partition@0 {
+ label = "adafruit_boot";
+ reg = <0x000000000 0x0000C000>;
+ };
+ code_partition: partition@26000 {
+ label = "code_partition";
+ reg = <0x00026000 0x000d2000>;
+ };
+
+ /*
+ * The flash starting at 0x000f8000 and ending at
+ * 0x000fffff is reserved for use by the application.
+ */
+
+ /*
+ * Storage partition will be used by FCB/LittleFS/NVS
+ * if enabled.
+ */
+ storage_partition: partition@f8000 {
+ label = "storage";
+ reg = <0x000f8000 0x00008000>;
+ };
+ };
+};
diff --git a/app/boards/arm/nrfmicro/nrfmicro_11.yaml b/app/boards/arm/nrfmicro/nrfmicro_11.yaml
new file mode 100644
index 0000000..4608130
--- /dev/null
+++ b/app/boards/arm/nrfmicro/nrfmicro_11.yaml
@@ -0,0 +1,15 @@
+identifier: nrfmicro_11
+name: nrfmicro_11
+type: mcu
+arch: arm
+toolchain:
+ - zephyr
+ - gnuarmemb
+ - xtools
+supported:
+ - adc
+ - usb_device
+ - ble
+ - ieee802154
+ - pwm
+ - watchdog
diff --git a/app/boards/arm/nrfmicro/nrfmicro_11_defconfig b/app/boards/arm/nrfmicro/nrfmicro_11_defconfig
new file mode 100644
index 0000000..c1ac836
--- /dev/null
+++ b/app/boards/arm/nrfmicro/nrfmicro_11_defconfig
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: MIT
+
+CONFIG_SOC_SERIES_NRF52X=y
+CONFIG_SOC_NRF52840_QIAA=y
+CONFIG_BOARD_NRFMICRO_11=y
+
+# Enable MPU
+CONFIG_ARM_MPU=y
+
+# enable GPIO
+CONFIG_GPIO=y
+
+CONFIG_USE_DT_CODE_PARTITION=y
+
+CONFIG_MPU_ALLOW_FLASH_WRITE=y
+CONFIG_NVS=y
+CONFIG_SETTINGS_NVS=y
+CONFIG_FLASH=y
+CONFIG_FLASH_PAGE_LAYOUT=y
+CONFIG_FLASH_MAP=y
+CONFIG_CLOCK_CONTROL_NRF=y
+CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
diff --git a/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts b/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts
new file mode 100644
index 0000000..5bf493f
--- /dev/null
+++ b/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2020 Okke Formsma, joric
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+/dts-v1/;
+#include <nordic/nrf52840_qiaa.dtsi>
+#include "arduino_pro_micro_pins_flipped.dtsi"
+
+/ {
+ model = "nrfmicro";
+ compatible = "joric,nrfmicro";
+
+ chosen {
+ zephyr,code-partition = &code_partition;
+ zephyr,sram = &sram0;
+ zephyr,flash = &flash0;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ blue_led: led_0 {
+ gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+ label = "Blue LED";
+ };
+ };
+
+};
+
+&gpio0 {
+ status = "okay";
+};
+
+&gpio1 {
+ status = "okay";
+};
+
+&i2c0 {
+ compatible = "nordic,nrf-twi";
+ sda-pin = <30>;
+ scl-pin = <31>;
+};
+
+&uart0 {
+ compatible = "nordic,nrf-uarte";
+ status = "okay";
+ current-speed = <115200>;
+ tx-pin = <39>;
+ rx-pin = <34>;
+ rts-pin = <33>;
+ cts-pin = <12>;
+};
+
+&usbd {
+ status = "okay";
+};
+
+
+&flash0 {
+ /*
+ * For more information, see:
+ * http://docs.zephyrproject.org/latest/devices/dts/flash_partitions.html
+ */
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ boot_partition: partition@0 {
+ label = "adafruit_boot";
+ reg = <0x000000000 0x0000C000>;
+ };
+ code_partition: partition@26000 {
+ label = "code_partition";
+ reg = <0x00026000 0x000d2000>;
+ };
+
+ /*
+ * The flash starting at 0x000f8000 and ending at
+ * 0x000fffff is reserved for use by the application.
+ */
+
+ /*
+ * Storage partition will be used by FCB/LittleFS/NVS
+ * if enabled.
+ */
+ storage_partition: partition@f8000 {
+ label = "storage";
+ reg = <0x000f8000 0x00008000>;
+ };
+ };
+};
diff --git a/app/boards/arm/nrfmicro/nrfmicro_11_flipped.yaml b/app/boards/arm/nrfmicro/nrfmicro_11_flipped.yaml
new file mode 100644
index 0000000..74461f0
--- /dev/null
+++ b/app/boards/arm/nrfmicro/nrfmicro_11_flipped.yaml
@@ -0,0 +1,15 @@
+identifier: nrfmicro_11_flipped
+name: nrfmicro_11_flipped
+type: mcu
+arch: arm
+toolchain:
+ - zephyr
+ - gnuarmemb
+ - xtools
+supported:
+ - adc
+ - usb_device
+ - ble
+ - ieee802154
+ - pwm
+ - watchdog
diff --git a/app/boards/arm/nrfmicro/nrfmicro_11_flipped_defconfig b/app/boards/arm/nrfmicro/nrfmicro_11_flipped_defconfig
new file mode 100644
index 0000000..b35cb79
--- /dev/null
+++ b/app/boards/arm/nrfmicro/nrfmicro_11_flipped_defconfig
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: MIT
+
+CONFIG_SOC_SERIES_NRF52X=y
+CONFIG_SOC_NRF52840_QIAA=y
+CONFIG_BOARD_NRFMICRO_11_FLIPPED=y
+
+# Enable MPU
+CONFIG_ARM_MPU=y
+
+# enable GPIO
+CONFIG_GPIO=y
+
+CONFIG_USE_DT_CODE_PARTITION=y
+
+CONFIG_MPU_ALLOW_FLASH_WRITE=y
+CONFIG_NVS=y
+CONFIG_SETTINGS_NVS=y
+CONFIG_FLASH=y
+CONFIG_FLASH_PAGE_LAYOUT=y
+CONFIG_FLASH_MAP=y
+CONFIG_CLOCK_CONTROL_NRF=y
+CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
diff --git a/app/boards/arm/nrfmicro/nrfmicro_13.dts b/app/boards/arm/nrfmicro/nrfmicro_13.dts
new file mode 100644
index 0000000..dc07ac8
--- /dev/null
+++ b/app/boards/arm/nrfmicro/nrfmicro_13.dts
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2020 Okke Formsma, joric
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+/dts-v1/;
+#include <nordic/nrf52840_qiaa.dtsi>
+#include "arduino_pro_micro_pins.dtsi"
+
+/ {
+ model = "nrfmicro";
+ compatible = "joric,nrfmicro";
+
+ chosen {
+ zephyr,code-partition = &code_partition;
+ zephyr,sram = &sram0;
+ zephyr,flash = &flash0;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ blue_led: led_0 {
+ gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+ label = "Blue LED";
+ };
+ };
+
+};
+
+&gpio0 {
+ status = "okay";
+};
+
+&gpio1 {
+ status = "okay";
+};
+
+&i2c0 {
+ compatible = "nordic,nrf-twi";
+ sda-pin = <15>;
+ scl-pin = <17>;
+};
+
+&uart0 {
+ compatible = "nordic,nrf-uarte";
+ status = "okay";
+ current-speed = <115200>;
+ tx-pin = <39>;
+ rx-pin = <34>;
+ rts-pin = <33>;
+ cts-pin = <12>;
+};
+
+&usbd {
+ status = "okay";
+};
+
+
+&flash0 {
+ /*
+ * For more information, see:
+ * http://docs.zephyrproject.org/latest/devices/dts/flash_partitions.html
+ */
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ boot_partition: partition@0 {
+ label = "adafruit_boot";
+ reg = <0x000000000 0x0000C000>;
+ };
+ code_partition: partition@26000 {
+ label = "code_partition";
+ reg = <0x00026000 0x000d2000>;
+ };
+
+ /*
+ * The flash starting at 0x000f8000 and ending at
+ * 0x000fffff is reserved for use by the application.
+ */
+
+ /*
+ * Storage partition will be used by FCB/LittleFS/NVS
+ * if enabled.
+ */
+ storage_partition: partition@f8000 {
+ label = "storage";
+ reg = <0x000f8000 0x00008000>;
+ };
+ };
+};
diff --git a/app/boards/arm/nrfmicro/nrfmicro_13.yaml b/app/boards/arm/nrfmicro/nrfmicro_13.yaml
new file mode 100644
index 0000000..a7415e4
--- /dev/null
+++ b/app/boards/arm/nrfmicro/nrfmicro_13.yaml
@@ -0,0 +1,15 @@
+identifier: nrfmicro_13
+name: nrfmicro_13
+type: mcu
+arch: arm
+toolchain:
+ - zephyr
+ - gnuarmemb
+ - xtools
+supported:
+ - adc
+ - usb_device
+ - ble
+ - ieee802154
+ - pwm
+ - watchdog
diff --git a/app/boards/arm/nrfmicro/nrfmicro_13_defconfig b/app/boards/arm/nrfmicro/nrfmicro_13_defconfig
new file mode 100644
index 0000000..cac1164
--- /dev/null
+++ b/app/boards/arm/nrfmicro/nrfmicro_13_defconfig
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: MIT
+
+CONFIG_SOC_SERIES_NRF52X=y
+CONFIG_SOC_NRF52840_QIAA=y
+CONFIG_BOARD_NRFMICRO_13=y
+
+# Enable MPU
+CONFIG_ARM_MPU=y
+
+# enable GPIO
+CONFIG_GPIO=y
+
+CONFIG_USE_DT_CODE_PARTITION=y
+
+CONFIG_MPU_ALLOW_FLASH_WRITE=y
+CONFIG_NVS=y
+CONFIG_SETTINGS_NVS=y
+CONFIG_FLASH=y
+CONFIG_FLASH_PAGE_LAYOUT=y
+CONFIG_FLASH_MAP=y
+CONFIG_CLOCK_CONTROL_NRF=y
+CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
diff --git a/app/boards/arm/nrfmicro/pinmux.c b/app/boards/arm/nrfmicro/pinmux.c
new file mode 100644
index 0000000..3792b59
--- /dev/null
+++ b/app/boards/arm/nrfmicro/pinmux.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2020 Okke Formsma, joric
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <kernel.h>
+#include <device.h>
+#include <init.h>
+#include <drivers/gpio.h>
+#include <sys/sys_io.h>
+#include <devicetree.h>
+
+static int pinmux_nrfmicro_init(struct device *port)
+{
+ ARG_UNUSED(port);
+
+ struct device *p1 = device_get_binding("GPIO_1");
+
+#if CONFIG_BOARD_NRFMICRO_13
+ struct device *p0 = device_get_binding("GPIO_0");
+ // enable EXT_VCC (use 0 for nRFMicro 1.3, use 1 for nRFMicro 1.1)
+ gpio_pin_configure(p1, 9, GPIO_OUTPUT);
+ gpio_pin_set(p1, 9, 0);
+
+#if CONFIG_BOARD_NRFMICRO_CHARGER
+ gpio_pin_configure(p0, 5, GPIO_OUTPUT);
+ gpio_pin_set(p0, 5, 0);
+#else
+ gpio_pin_configure(p0, 5, GPIO_INPUT);
+#endif
+
+#else
+ // enable EXT_VCC (use 0 for nRFMicro 1.3, use 1 for nRFMicro 1.1)
+ gpio_pin_configure(p1, 9, GPIO_OUTPUT);
+ gpio_pin_set(p1, 9, 1);
+#endif
+ return 0;
+}
+
+SYS_INIT(pinmux_nrfmicro_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
diff --git a/app/boards/arm/planck/keymap/keymap.overlay b/app/boards/arm/planck/planck_rev6.keymap
index f474ec9..af1dc7c 100644
--- a/app/boards/arm/planck/keymap/keymap.overlay
+++ b/app/boards/arm/planck/planck_rev6.keymap
@@ -1,23 +1,11 @@
#include <behaviors.dtsi>
#include <dt-bindings/zmk/keys.h>
-#include <dt-bindings/zmk/matrix-transform.h>
/ {
- chosen {
- zmk,keymap = &keymap0;
- };
-
- keymap0: keymap {
+ keymap {
compatible = "zmk,keymap";
- label ="Default Planck Keymap";
- layers = <&default>;
- };
-
- layers {
- compatible = "zmk,layers";
- default: layer_0 {
- label = "DEFAULT";
+ default_layer {
// -----------------------------------------------------------------------------------------
// | TAB | Q | W | E | R | T | Y | U | I | O | P | BSPC |
// | ESC | A | S | D | F | G | H | J | K | L | ; | ' |
diff --git a/app/boards/arm/proton_c/CMakeLists.txt b/app/boards/arm/proton_c/CMakeLists.txt
index d1b8108..940af1f 100644
--- a/app/boards/arm/proton_c/CMakeLists.txt
+++ b/app/boards/arm/proton_c/CMakeLists.txt
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: Apache-2.0
+# SPDX-License-Identifier: MIT
if(CONFIG_PINMUX)
zephyr_library()
diff --git a/app/boards/arm/proton_c/pinmux.c b/app/boards/arm/proton_c/pinmux.c
index 09f3a34..a6aaae0 100644
--- a/app/boards/arm/proton_c/pinmux.c
+++ b/app/boards/arm/proton_c/pinmux.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2017 I-SENSE group of ICCS
*
- * SPDX-License-Identifier: Apache-2.0
+ * SPDX-License-Identifier: MIT
*/
#include <kernel.h>
diff --git a/app/boards/native_posix.conf b/app/boards/native_posix.conf
index 5bfb366..357b1b8 100644
--- a/app/boards/native_posix.conf
+++ b/app/boards/native_posix.conf
@@ -1,9 +1,8 @@
CONFIG_KSCAN=n
CONFIG_ZMK_KSCAN_MOCK_DRIVER=y
-CONFIG_ZMK_KSCAN_COMPOSITE_DRIVER=y
CONFIG_ZMK_KSCAN_GPIO_DRIVER=n
CONFIG_GPIO=n
CONFIG_ZMK_BLE=n
CONFIG_LOG=y
-CONFIG_KSCAN_LOG_LEVEL_DBG=y
+CONFIG_LOG_BACKEND_SHOW_COLOR=n
CONFIG_ZMK_LOG_LEVEL_DBG=y
diff --git a/app/boards/native_posix.overlay b/app/boards/native_posix.overlay
index e9c4c95..bbb23b6 100644
--- a/app/boards/native_posix.overlay
+++ b/app/boards/native_posix.overlay
@@ -1,79 +1,18 @@
-#include <dt-bindings/zmk/keys.h>
#include <behaviors.dtsi>
-#include <zmk/kscan-mock.h>
+#include <dt-bindings/zmk/keys.h>
+#include <dt-bindings/zmk/kscan-mock.h>
/ {
chosen {
- zmk,kscan = &kscan0;
- zmk,keymap = &keymap0;
- };
-
- kscan0: kscan_0 {
- compatible = "zmk,kscan-composite";
- label = "KSCAN_COMP";
- rows = <2>;
- columns = <4>;
-
- left: left {
- kscan = <&left_hand>;
- };
-
- right: right {
- kscan = <&right_hand>;
- column-offset = <2>;
- };
+ zmk,kscan = &kscan;
};
- left_hand: kscan_1 {
+ kscan: kscan {
compatible = "zmk,kscan-mock";
- label = "KSCAN_LEFT";
+ label = "KSCAN_MOCK";
rows = <2>;
columns = <2>;
- events = <ZMK_MOCK_PRESS(0,1,300) ZMK_MOCK_PRESS(0,0,300) ZMK_MOCK_RELEASE(0,0,300) ZMK_MOCK_RELEASE(0,1,300)>;
- // events = <ZMK_MOCK_PRESS(0,0,800) ZMK_MOCK_RELEASE(0,0,800) ZMK_MOCK_PRESS(0,1,800) ZMK_MOCK_RELEASE(0,1,800)>;
- };
-
- right_hand: kscan_2 {
- compatible = "zmk,kscan-mock";
- label = "KSCAN_RIGHT";
-
- rows = <2>;
- columns = <2>;
- events = <ZMK_MOCK_PRESS(1,1,800) ZMK_MOCK_RELEASE(1,1,100) ZMK_MOCK_PRESS(0,1,800) ZMK_MOCK_RELEASE(0,1,100)>;
- };
-
- keymap0: keymap {
- compatible = "zmk,keymap";
- label ="Default keymap";
- layers = <&default &lower &raise>;
- };
-
- layers {
- compatible = "zmk,layers";
-
- default: layer_0 {
- label = "DEFAULT";
-
- bindings = <
- &kp B &mo 1 &kp C &kp E
- &kp D &kp G &kp F &kp Q>;
- };
-
- lower: layer_1 {
- label = "LOWER";
-
- bindings = <
- &cp M_NEXT &trans &kp O &kp Q
- &kp L &kp J &kp P &kp K>;
- };
-
- raise: layer_2 {
- label = "RAISE";
-
- bindings = <
- &kp W &kp U &kp I &kp N
- &kp X &kp M &kp C &kp B>;
- };
+ exit-after;
};
};
diff --git a/app/boards/shields/clueboard_california/keymap/keymap.overlay b/app/boards/shields/clueboard_california/clueboard_california.keymap
index c2fa7f8..7a84b11 100644
--- a/app/boards/shields/clueboard_california/keymap/keymap.overlay
+++ b/app/boards/shields/clueboard_california/clueboard_california.keymap
@@ -1,23 +1,11 @@
-#include <dt-bindings/zmk/keys.h>
-#include <dt-bindings/zmk/matrix-transform.h>
#include <behaviors.dtsi>
+#include <dt-bindings/zmk/keys.h>
/ {
- chosen {
- zmk,keymap = &keymap0;
- };
-
keymap0: keymap {
compatible = "zmk,keymap";
- label ="Default Kyria Keymap";
- layers = <&default>;
- };
-
- layers {
- compatible = "zmk,layers";
- default: layer_0 {
- label = "DEFAULT";
+ default_layer {
bindings = <
&kp NUM_9 &kp NUM_8
&kp NUM_7 &kp NUM_6
diff --git a/app/boards/shields/corne/Kconfig.defconfig b/app/boards/shields/corne/Kconfig.defconfig
new file mode 100644
index 0000000..8878da3
--- /dev/null
+++ b/app/boards/shields/corne/Kconfig.defconfig
@@ -0,0 +1,58 @@
+
+if SHIELD_CORNE_LEFT
+
+config ZMK_KEYBOARD_NAME
+ default "Corne Left"
+
+endif
+
+
+if SHIELD_CORNE_RIGHT
+
+config ZMK_KEYBOARD_NAME
+ default "Corne Right"
+
+endif
+
+if SHIELD_CORNE_LEFT || SHIELD_CORNE_RIGHT
+
+config ZMK_SPLIT
+ default y
+
+if ZMK_DISPLAY
+
+config I2C
+ default y
+
+config SSD1306
+ default y
+
+config SSD1306_REVERSE_MODE
+ default y
+
+endif # ZMK_DISPLAY
+
+if LVGL
+
+config LVGL_HOR_RES
+ default 128
+
+config LVGL_VER_RES
+ default 32
+
+config LVGL_VDB_SIZE
+ default 64
+
+config LVGL_DPI
+ default 148
+
+config LVGL_BITS_PER_PIXEL
+ default 1
+
+choice LVGL_COLOR_DEPTH
+ default LVGL_COLOR_DEPTH_1
+endchoice
+
+endif # LVGL
+
+endif
diff --git a/app/boards/shields/corne/Kconfig.shield b/app/boards/shields/corne/Kconfig.shield
new file mode 100644
index 0000000..3cac86f
--- /dev/null
+++ b/app/boards/shields/corne/Kconfig.shield
@@ -0,0 +1,8 @@
+# Copyright (c) 2020 Pete Johanson
+# SPDX-License-Identifier: MIT
+
+config SHIELD_CORNE_LEFT
+ def_bool $(shields_list_contains,corne_left)
+
+config SHIELD_CORNE_RIGHT
+ def_bool $(shields_list_contains,corne_right)
diff --git a/app/boards/shields/corne/boards/nice_nano.overlay b/app/boards/shields/corne/boards/nice_nano.overlay
new file mode 100644
index 0000000..c7c3eb8
--- /dev/null
+++ b/app/boards/shields/corne/boards/nice_nano.overlay
@@ -0,0 +1,29 @@
+&spi1 {
+ compatible = "nordic,nrf-spi";
+ /* Cannot be used together with i2c0. */
+ status = "okay";
+ mosi-pin = <6>;
+ // Unused pins, needed for SPI definition, but not used by the ws2812 driver itself.
+ sck-pin = <5>;
+ miso-pin = <7>;
+
+ led_strip: ws2812@0 {
+ compatible = "worldsemi,ws2812-spi";
+ label = "SK6812mini";
+
+ /* SPI */
+ reg = <0>; /* ignored, but necessary for SPI bindings */
+ spi-max-frequency = <4000000>;
+
+ /* WS2812 */
+ chain-length = <6>; /* There are per-key RGB, but the first 6 are underglow */
+ spi-one-frame = <0x70>;
+ spi-zero-frame = <0x40>;
+ };
+};
+
+/ {
+ chosen {
+ zmk,underglow = &led_strip;
+ };
+};
diff --git a/app/boards/shields/corne/corne.conf b/app/boards/shields/corne/corne.conf
new file mode 100644
index 0000000..b79385b
--- /dev/null
+++ b/app/boards/shields/corne/corne.conf
@@ -0,0 +1,6 @@
+# Uncomment the following lines to enable the Corne RGB Underglow
+# ZMK_RGB_UNDERGLOW=y
+# CONFIG_WS2812_STRIP=y
+
+# Uncomment the following line to enable the Corne OLED Display
+# CONFIG_ZMK_DISPLAY=y
diff --git a/app/boards/shields/corne/corne.dtsi b/app/boards/shields/corne/corne.dtsi
new file mode 100644
index 0000000..af14bae
--- /dev/null
+++ b/app/boards/shields/corne/corne.dtsi
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2020 Pete Johanson
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <dt-bindings/zmk/matrix-transform.h>
+
+/ {
+ chosen {
+ zmk,kscan = &kscan0;
+ zmk,matrix_transform = &default_transform;
+ };
+
+ default_transform: keymap_transform_0 {
+ compatible = "zmk,matrix-transform";
+ columns = <12>;
+ rows = <4>;
+// | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 | | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 |
+// | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 | | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 |
+// | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 | | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 |
+// | SW19 | SW20 | SW21 | | SW21 | SW20 | SW19 |
+ map = <
+RC(0,0) 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(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(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(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8)
+ >;
+ };
+
+ five_column_transform: keymap_transform_1 {
+ compatible = "zmk,matrix-transform";
+ columns = <10>;
+ rows = <4>;
+// | SW2 | SW3 | SW4 | SW5 | SW6 | | SW6 | SW5 | SW4 | SW3 | SW2 |
+// | SW8 | SW9 | SW10 | SW11 | SW12 | | SW12 | SW11 | SW10 | SW9 | SW8 |
+// | SW14 | SW15 | SW16 | SW17 | SW18 | | SW18 | SW17 | SW16 | SW15 | SW14 |
+// | SW19 | SW20 | SW21 | | SW21 | SW20 | SW19 |
+ 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(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(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(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8)
+ >;
+ };
+
+ kscan0: kscan {
+ compatible = "zmk,kscan-gpio-matrix";
+ label = "KSCAN";
+
+ diode-direction = "col2row";
+ row-gpios
+ = <&pro_micro_d 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ ;
+
+ };
+
+ bt_unpair_combo: bt_unpair_combo {
+ compatible = "zmk,bt-unpair-combo";
+ };
+
+ // TODO: per-key RGB node(s)?
+};
+
+&pro_micro_i2c {
+ status = "okay";
+
+ oled: ssd1306@3c {
+ compatible = "solomon,ssd1306fb";
+ reg = <0x3c>;
+ label = "DISPLAY";
+ width = <128>;
+ height = <32>;
+ segment-offset = <0>;
+ page-offset = <0>;
+ display-offset = <0>;
+ multiplex-ratio = <31>;
+ segment-remap;
+ com-invdir;
+ com-sequential;
+ prechargep = <0x22>;
+ };
+};
diff --git a/app/boards/shields/corne/corne.keymap b/app/boards/shields/corne/corne.keymap
new file mode 100644
index 0000000..c0bbb4a
--- /dev/null
+++ b/app/boards/shields/corne/corne.keymap
@@ -0,0 +1,50 @@
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/keys.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+
+ default_layer {
+// -----------------------------------------------------------------------------------------
+// | TAB | Q | W | E | R | T | | Y | U | I | O | P | BKSP |
+// | CTRL | A | S | D | F | G | | H | J | K | L | ; | ' |
+// | SHFT | Z | X | C | V | B | | N | M | , | . | / | SHFT |
+// | GUI | LWR | SPC | | ENT | RSE | ALT |
+ bindings = <
+ &kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BKSP
+ &kp LCTL &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SCLN &kp QUOT
+ &kp LSFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp CMMA &kp DOT &kp FSLH &kp RSFT
+ &kp LGUI &mo 1 &kp SPC &kp RET &mo 2 &kp RALT
+ >;
+ };
+ lower_layer {
+// -----------------------------------------------------------------------------------------
+// | ESC | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | BKSP |
+// | CTRL | | | | | | | LFT | DWN | UP | RGT | | |
+// | SHFT | | | | | | | | | | | | |
+// | GUI | | SPC | | ENT | | ALT |
+ bindings = <
+ &kp ESC &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &kp BKSP
+ &kp LCTL &trans &trans &trans &trans &trans &kp LARW &kp DARW &kp UARW &kp RARW &trans &trans
+ &kp LSFT &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
+ &kp LGUI &trans &kp SPC &kp RET &trans &kp RALT
+ >;
+ };
+
+ raise_layer {
+// -----------------------------------------------------------------------------------------
+// | ESC | ! | @ | # | $ | % | | ^ | & | * | ( | ) | BKSP |
+// | CTRL | | | | | | | - | = | { | } | "|" | ` |
+// | SHFT | | | | | | | _ | + | [ | ] | \ | ~ | // TODO: Fix this row when &mkp is committed
+// | GUI | | SPC | | ENT | | ALT |
+ bindings = <
+ &kp ESC &kp BANG &kp ATSN &kp HASH &kp CURU &kp PRCT &kp CRRT &kp AMPS &kp KMLT &kp LPRN &kp RPRN &kp BKSP
+ &kp LCTL &trans &trans &trans &trans &trans &kp MINUS &kp EQL &kp LBKT &kp RBKT &kp PIPE &kp GRAV
+ &kp LSFT &trans &trans &trans &trans &trans &trans &trans &trans &trans &kp BSLH &kp TILD
+ &kp LGUI &trans &kp SPC &kp RET &trans &kp RALT
+ >;
+ };
+ };
+};
+
diff --git a/app/boards/shields/corne/corne_left.conf b/app/boards/shields/corne/corne_left.conf
new file mode 100644
index 0000000..1e028a7
--- /dev/null
+++ b/app/boards/shields/corne/corne_left.conf
@@ -0,0 +1,2 @@
+CONFIG_ZMK_SPLIT=y
+CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y
diff --git a/app/boards/shields/corne/corne_left.overlay b/app/boards/shields/corne/corne_left.overlay
new file mode 100644
index 0000000..f12c417
--- /dev/null
+++ b/app/boards/shields/corne/corne_left.overlay
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2020 Pete Johanson
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "corne.dtsi"
+
+&kscan0 {
+ col-gpios
+ = <&pro_micro_a 3 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 2 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 1 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 0 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 15 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 14 GPIO_ACTIVE_HIGH>
+ ;
+};
+
+&bt_unpair_combo {
+ key-positions = <0 38>;
+};
diff --git a/app/boards/shields/corne/corne_right.conf b/app/boards/shields/corne/corne_right.conf
new file mode 100644
index 0000000..990cf7c
--- /dev/null
+++ b/app/boards/shields/corne/corne_right.conf
@@ -0,0 +1,2 @@
+CONFIG_ZMK_SPLIT=y
+CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y
diff --git a/app/boards/shields/corne/corne_right.overlay b/app/boards/shields/corne/corne_right.overlay
new file mode 100644
index 0000000..9d97d85
--- /dev/null
+++ b/app/boards/shields/corne/corne_right.overlay
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020 Pete Johanson
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "corne.dtsi"
+
+&default_transform {
+ col-offset = <6>;
+};
+
+&kscan0 {
+ col-gpios
+ = <&pro_micro_d 14 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 15 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 0 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 1 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 2 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 3 GPIO_ACTIVE_HIGH>
+ ;
+};
+
+&bt_unpair_combo {
+ key-positions = <11 39>;
+};
diff --git a/app/boards/shields/iris/Kconfig.defconfig b/app/boards/shields/iris/Kconfig.defconfig
new file mode 100644
index 0000000..6439780
--- /dev/null
+++ b/app/boards/shields/iris/Kconfig.defconfig
@@ -0,0 +1,16 @@
+# Copyright (c) 2020 Pete Johanson, Kurtis Lew
+# SPDX-License-Identifier: MIT
+
+if SHIELD_IRIS_LEFT
+
+config ZMK_KEYBOARD_NAME
+ default "Iris Left"
+
+endif
+
+if SHIELD_IRIS_RIGHT
+
+config ZMK_KEYBOARD_NAME
+ default "Iris Right"
+
+endif
diff --git a/app/boards/shields/iris/Kconfig.shield b/app/boards/shields/iris/Kconfig.shield
new file mode 100644
index 0000000..370bd22
--- /dev/null
+++ b/app/boards/shields/iris/Kconfig.shield
@@ -0,0 +1,8 @@
+# Copyright (c) 2020 Pete Johanson, Kurtis Lew
+# SPDX-License-Identifier: MIT
+
+config SHIELD_IRIS_LEFT
+ def_bool $(shields_list_contains,iris_left)
+
+config SHIELD_IRIS_RIGHT
+ def_bool $(shields_list_contains,iris_right)
diff --git a/app/boards/shields/petejohanson_pro_micro_handwire/petejohanson_pro_micro_handwire.conf b/app/boards/shields/iris/iris.conf
index e69de29..e69de29 100644
--- a/app/boards/shields/petejohanson_pro_micro_handwire/petejohanson_pro_micro_handwire.conf
+++ b/app/boards/shields/iris/iris.conf
diff --git a/app/boards/shields/iris/iris.dtsi b/app/boards/shields/iris/iris.dtsi
new file mode 100644
index 0000000..f6e32c4
--- /dev/null
+++ b/app/boards/shields/iris/iris.dtsi
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2020 Pete Johanson, Kurtis Lew
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <dt-bindings/zmk/matrix-transform.h>
+
+/ {
+ chosen {
+ zmk,kscan = &kscan0;
+ zmk,matrix_transform = &default_transform;
+ };
+
+ default_transform: keymap_transform_0 {
+ compatible = "zmk,matrix-transform";
+ columns = <16>;
+ rows = <4>;
+// | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 | | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 |
+// | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 | | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 |
+// | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 | | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 |
+// | SW24 | SW23 | SW22 | SW21 | SW20 | SW19 | SW25 | | SW25 | SW19 | SW20 | SW21 | SW22 | SW23 | SW24 |
+// | SW29 | SW28 | SW27 | SW26 | | SW26 | SW27 | SW28 | SW29 |
+ map = <
+RC(0,0) 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(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(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(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(4,2) RC(4,9) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11)
+ RC(4,3) RC(4,4) RC(4,5) RC(4,6) RC(4,7) RC(4,8)
+ >;
+ };
+
+ kscan0: kscan {
+ compatible = "zmk,kscan-gpio-matrix";
+ label = "KSCAN";
+
+ diode-direction = "col2row";
+ row-gpios
+ = <&pro_micro_d 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 0 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ ;
+
+ };
+
+ bt_unpair_combo: bt_unpair_combo {
+ compatible = "zmk,bt-unpair-combo";
+ };
+}; \ No newline at end of file
diff --git a/app/boards/shields/iris/iris.keymap b/app/boards/shields/iris/iris.keymap
new file mode 100644
index 0000000..46b0817
--- /dev/null
+++ b/app/boards/shields/iris/iris.keymap
@@ -0,0 +1,59 @@
+# Copyright (c) 2020 Pete Johanson, Kurtis Lew
+# SPDX-License-Identifier: MIT
+
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/keys.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+
+ default_layer {
+// ------------------------------------------------------------------------------------------------------------
+// | ESC | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | ` |
+// | TAB | Q | W | E | R | T | | Y | U | I | O | P | - |
+// | CTRL | A | S | D | F | G | | H | J | K | L | ; | ' |
+// | SHIFT | Z | X | C | V | B | "[" | | "]" | N | M | , | . | / | SHIFT |
+// | GUI | LOWER| SPACE | | ENTER | RAISE| ALT |
+ bindings = <
+&kp ESC &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &kp GRAV
+&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp MINUS
+&kp LCTL &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SCLN &kp QUOT
+&kp LSFT &kp Z &kp X &kp C &kp V &kp B &kp LBKT &kp RBKT &kp N &kp M &kp CMMA &kp DOT &kp FSLH &kp RSFT
+ &kp LGUI &mo 1 &kp SPC &kp RET &mo 2 &kp RALT
+ >;
+ };
+
+ lower_layer {
+// ------------------------------------------------------------------------------------------------------------
+// | | | | | | | | | | | | | |
+// | F1 | F2 | F3 | F4 | F5 | F6 | | F7 | F8 | F9 | F10 | F11 | F12 |
+// | ` | ! | @ | # | $ | % | | ^ | & | * | ( | ) | ~ |
+// | | | | | | | | | | | _ | + | { | } | "|" |
+// | | | | | | | |
+ bindings = <
+&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
+&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12
+&kp GRAV &kp BANG &kp ATSN &kp HASH &kp CURU &kp PRCT &kp CRRT &kp AMPS &kp KMLT &kp LPRN &kp RPRN &kp TILD
+&trans &trans &trans &trans &trans &trans &trans &trans &trans &kp MINUS &kp KPLS &kp LCUR &kp RCUR &kp PIPE
+ &trans &trans &trans &trans &trans &trans
+ >;
+ };
+
+ raise_layer {
+// ------------------------------------------------------------------------------------------------------------
+// | | | | | | | | | | | | | |
+// | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | |
+// | F1 | F2 | F3 | F4 | F5 | F6 | | | <- | ^ | v | -> | |
+// | F7 | F8 | F9 | F10 | F11 | F12 | | | | + | - | = | [ | ] | \ |
+// | | | | | | | |
+ bindings = <
+&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
+&kp GRAV &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &trans
+&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &trans &kp LARW &kp DARW &kp UARW &kp RARW &trans
+&kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &trans &trans &kp KPLS &kp MINUS &kp EQL &kp LBKT &kp RBKT &kp BSLH
+ &trans &trans &trans &trans &trans &trans
+ >;
+ };
+ };
+};
diff --git a/app/boards/shields/iris/iris_left.conf b/app/boards/shields/iris/iris_left.conf
new file mode 100644
index 0000000..1e028a7
--- /dev/null
+++ b/app/boards/shields/iris/iris_left.conf
@@ -0,0 +1,2 @@
+CONFIG_ZMK_SPLIT=y
+CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y
diff --git a/app/boards/shields/iris/iris_left.overlay b/app/boards/shields/iris/iris_left.overlay
new file mode 100644
index 0000000..e04638e
--- /dev/null
+++ b/app/boards/shields/iris/iris_left.overlay
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2020 Pete Johanson, Kurtis Lew
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "iris.dtsi"
+
+&kscan0 {
+ col-gpios
+ = <&pro_micro_a 1 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 0 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 15 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 14 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 16 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 10 GPIO_ACTIVE_HIGH>
+ ;
+};
+
+&bt_unpair_combo {
+ key-positions = <0 42>;
+};
diff --git a/app/boards/shields/iris/iris_right.conf b/app/boards/shields/iris/iris_right.conf
new file mode 100644
index 0000000..990cf7c
--- /dev/null
+++ b/app/boards/shields/iris/iris_right.conf
@@ -0,0 +1,2 @@
+CONFIG_ZMK_SPLIT=y
+CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y
diff --git a/app/boards/shields/iris/iris_right.overlay b/app/boards/shields/iris/iris_right.overlay
new file mode 100644
index 0000000..2d5dce8
--- /dev/null
+++ b/app/boards/shields/iris/iris_right.overlay
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020 Pete Johanson, Kurtis Lew
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "iris.dtsi"
+
+&default_transform {
+ col-offset = <6>;
+};
+
+&kscan0 {
+ col-gpios
+ = <&pro_micro_d 10 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 16 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 14 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 15 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 0 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 1 GPIO_ACTIVE_HIGH>
+ ;
+};
+
+&bt_unpair_combo {
+ key-positions = <11 43>;
+};
diff --git a/app/boards/shields/kyria/boards/nice_nano.overlay b/app/boards/shields/kyria/boards/nice_nano.overlay
index fe07d17..f51ecfe 100644
--- a/app/boards/shields/kyria/boards/nice_nano.overlay
+++ b/app/boards/shields/kyria/boards/nice_nano.overlay
@@ -1,6 +1,5 @@
&spi1 {
compatible = "nordic,nrf-spi";
- /* Cannot be used together with i2c0. */
status = "okay";
mosi-pin = <6>;
// Unused pins, needed for SPI definition, but not used by the ws2812 driver itself.
diff --git a/app/boards/shields/kyria/boards/nrfmicro_11.overlay b/app/boards/shields/kyria/boards/nrfmicro_11.overlay
new file mode 100644
index 0000000..d7f724f
--- /dev/null
+++ b/app/boards/shields/kyria/boards/nrfmicro_11.overlay
@@ -0,0 +1,29 @@
+&spi1 {
+ compatible = "nordic,nrf-spi";
+ status = "okay";
+ mosi-pin = <6>;
+ // Unused pins, needed for SPI definition, but not used by the ws2812 driver itself.
+ sck-pin = <12>; // 0.12 is not broken out on the nRFMicro
+ miso-pin = <22>; // 0.22 is not broken out on the nRFMicro
+
+ led_strip: ws2812@0 {
+ compatible = "worldsemi,ws2812-spi";
+ label = "WS2812";
+
+ /* SPI */
+ reg = <0>; /* ignored, but necessary for SPI bindings */
+ spi-max-frequency = <4000000>;
+
+ /* WS2812 */
+ chain-length = <10>; /* arbitrary; change at will */
+ spi-one-frame = <0x70>;
+ spi-zero-frame = <0x40>;
+ };
+};
+
+/ {
+ chosen {
+ zmk,underglow = &led_strip;
+ };
+};
+
diff --git a/app/boards/shields/kyria/boards/nrfmicro_11_flipped.overlay b/app/boards/shields/kyria/boards/nrfmicro_11_flipped.overlay
new file mode 100644
index 0000000..c5f2a94
--- /dev/null
+++ b/app/boards/shields/kyria/boards/nrfmicro_11_flipped.overlay
@@ -0,0 +1,28 @@
+&spi1 {
+ compatible = "nordic,nrf-spi";
+ status = "okay";
+ mosi-pin = <6>;
+ // Unused pins, needed for SPI definition, but not used by the ws2812 driver itself.
+ sck-pin = <12>; // 0.12 is not broken out on the nRFMicro
+ miso-pin = <22>; // 0.22 is not broken out on the nRFMicro
+
+ led_strip: ws2812@0 {
+ compatible = "worldsemi,ws2812-spi";
+ label = "WS2812";
+
+ /* SPI */
+ reg = <0>; /* ignored, but necessary for SPI bindings */
+ spi-max-frequency = <4000000>;
+
+ /* WS2812 */
+ chain-length = <10>; /* arbitrary; change at will */
+ spi-one-frame = <0x70>;
+ spi-zero-frame = <0x40>;
+ };
+};
+
+/ {
+ chosen {
+ zmk,underglow = &led_strip;
+ };
+};
diff --git a/app/boards/shields/kyria/boards/nrfmicro_13.overlay b/app/boards/shields/kyria/boards/nrfmicro_13.overlay
new file mode 100644
index 0000000..c5f2a94
--- /dev/null
+++ b/app/boards/shields/kyria/boards/nrfmicro_13.overlay
@@ -0,0 +1,28 @@
+&spi1 {
+ compatible = "nordic,nrf-spi";
+ status = "okay";
+ mosi-pin = <6>;
+ // Unused pins, needed for SPI definition, but not used by the ws2812 driver itself.
+ sck-pin = <12>; // 0.12 is not broken out on the nRFMicro
+ miso-pin = <22>; // 0.22 is not broken out on the nRFMicro
+
+ led_strip: ws2812@0 {
+ compatible = "worldsemi,ws2812-spi";
+ label = "WS2812";
+
+ /* SPI */
+ reg = <0>; /* ignored, but necessary for SPI bindings */
+ spi-max-frequency = <4000000>;
+
+ /* WS2812 */
+ chain-length = <10>; /* arbitrary; change at will */
+ spi-one-frame = <0x70>;
+ spi-zero-frame = <0x40>;
+ };
+};
+
+/ {
+ chosen {
+ zmk,underglow = &led_strip;
+ };
+};
diff --git a/app/boards/shields/kyria/kyria.conf b/app/boards/shields/kyria/kyria.conf
index e69de29..7a0b5b6 100644
--- a/app/boards/shields/kyria/kyria.conf
+++ b/app/boards/shields/kyria/kyria.conf
@@ -0,0 +1,10 @@
+# Uncomment these two line to add support for encoders to your firmware
+# CONFIG_EC11=y
+# CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y
+
+# Uncomment the following line to enable the Kyria OLED Display
+# CONFIG_ZMK_DISPLAY=y
+
+# Uncomment the following lines to enable RGB underglow
+# CONFIG_ZMK_RGB_UNDERGLOW=y
+# CONFIG_WS2812_STRIP=y
diff --git a/app/boards/shields/kyria/kyria.dtsi b/app/boards/shields/kyria/kyria.dtsi
index bbead84..a13f7f0 100644
--- a/app/boards/shields/kyria/kyria.dtsi
+++ b/app/boards/shields/kyria/kyria.dtsi
@@ -81,6 +81,10 @@ 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)
sensors = <&left_encoder &right_encoder>;
};
+ bt_unpair_combo: bt_unpair_combo {
+ compatible = "zmk,bt-unpair-combo";
+ };
+
// TODO: RGB node(s)
};
diff --git a/app/boards/shields/kyria/keymap/keymap.overlay b/app/boards/shields/kyria/kyria.keymap
index 53101ff..f689ef6 100644
--- a/app/boards/shields/kyria/keymap/keymap.overlay
+++ b/app/boards/shields/kyria/kyria.keymap
@@ -1,23 +1,11 @@
#include <behaviors.dtsi>
#include <dt-bindings/zmk/keys.h>
-#include <dt-bindings/zmk/matrix-transform.h>
/ {
- chosen {
- zmk,keymap = &keymap0;
- };
-
- keymap0: keymap {
+ keymap {
compatible = "zmk,keymap";
- label ="Default Kyria Keymap";
- layers = <&default>;
- };
-
- layers {
- compatible = "zmk,layers";
- default: layer_0 {
- label = "DEFAULT";
+ default_layer {
// ---------------------------------------------------------------------------------------------------------------------------------
// | ESC | Q | W | E | R | T | | Y | U | I | O | P | \ |
// | TAB | A | S | D | F | G | | H | J | K | L | ; | ' |
diff --git a/app/boards/shields/kyria/kyria_left.overlay b/app/boards/shields/kyria/kyria_left.overlay
index c8b5be2..441c1a6 100644
--- a/app/boards/shields/kyria/kyria_left.overlay
+++ b/app/boards/shields/kyria/kyria_left.overlay
@@ -22,3 +22,7 @@
&left_encoder {
status = "okay";
};
+
+&bt_unpair_combo {
+ key-positions = <0 44>;
+}; \ No newline at end of file
diff --git a/app/boards/shields/kyria/kyria_right.conf b/app/boards/shields/kyria/kyria_right.conf
index a835adc..990cf7c 100644
--- a/app/boards/shields/kyria/kyria_right.conf
+++ b/app/boards/shields/kyria/kyria_right.conf
@@ -1,2 +1,2 @@
CONFIG_ZMK_SPLIT=y
-CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y \ No newline at end of file
+CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y
diff --git a/app/boards/shields/kyria/kyria_right.overlay b/app/boards/shields/kyria/kyria_right.overlay
index 8163c95..8ee0fcb 100644
--- a/app/boards/shields/kyria/kyria_right.overlay
+++ b/app/boards/shields/kyria/kyria_right.overlay
@@ -27,3 +27,7 @@
&right_encoder {
status = "okay";
};
+
+&bt_unpair_combo {
+ key-positions = <11 45>;
+}; \ No newline at end of file
diff --git a/app/boards/shields/lily58/keymap/keymap.overlay b/app/boards/shields/lily58/keymap/keymap.overlay
deleted file mode 100644
index 9d1f9c6..0000000
--- a/app/boards/shields/lily58/keymap/keymap.overlay
+++ /dev/null
@@ -1,36 +0,0 @@
-#include <behaviors.dtsi>
-#include <dt-bindings/zmk/keys.h>
-#include <dt-bindings/zmk/matrix-transform.h>
-
-/ {
- chosen {
- zmk,keymap = &keymap0;
- };
-
- keymap0: keymap {
- compatible = "zmk,keymap";
- label ="Default Lily58 Keymap";
- layers = <&default>;
- };
-
- layers {
- compatible = "zmk,layers";
-
- default: layer_0 {
- label = "DEFAULT";
-// ---------------------------------------------------------------------------------------------------------------------------------
-// | ESC | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | ` |
-// | TAB | Q | W | E | R | T | | Y | U | I | O | P | \ |
-// | CTRL | A | S | D | F | G | | H | J | K | L | ; | ' |
-// | SHIFT | Z | X | C | V | B | "[" | | "]" | N | M | , | . | / | CTRL |
-// | GUI | DEL | RET | SPACE | | SPACE | TAB | BSPC | R-ALT |
- bindings = <
-&kp ESC &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &kp GRAV
-&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BSLH
-&kp LCTL &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SCLN &kp QUOT
-&kp LSFT &kp Z &kp X &kp C &kp V &kp B &kp LBKT &kp RBKT &kp N &kp M &kp CMMA &kp DOT &kp FSLH &kp RCTL
- &kp LGUI &kp DEL &kp RET &kp SPC &kp SPC &kp TAB &kp BKSP &kp RALT
- >;
- };
- };
-};
diff --git a/app/boards/shields/lily58/lily58.conf b/app/boards/shields/lily58/lily58.conf
index e69de29..31eb7c6 100644
--- a/app/boards/shields/lily58/lily58.conf
+++ b/app/boards/shields/lily58/lily58.conf
@@ -0,0 +1,6 @@
+# Uncomment to enable encoder
+# CONFIG_EC11=y
+# CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y
+
+# Uncomment the following line to enable the Lily58 OLED Display
+# CONFIG_ZMK_DISPLAY=y
diff --git a/app/boards/shields/lily58/lily58.dtsi b/app/boards/shields/lily58/lily58.dtsi
index 8655d8c..556909f 100644
--- a/app/boards/shields/lily58/lily58.dtsi
+++ b/app/boards/shields/lily58/lily58.dtsi
@@ -15,7 +15,7 @@
default_transform: keymap_transform_0 {
compatible = "zmk,matrix-transform";
columns = <16>;
- rows = <4>;
+ rows = <5>;
// | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 | | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 |
// | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 | | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 |
// | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 | | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 |
@@ -44,12 +44,29 @@ RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(4,5) RC(4,6) RC(3,6) RC(3,7)
;
};
+
+ left_encoder: encoder_left {
+ compatible = "alps,ec11";
+ label = "LEFT_ENCODER";
+ a-gpios = <&pro_micro_a 3 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
+ b-gpios = <&pro_micro_a 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
+ resolution = <4>;
+ };
+
+ sensors {
+ compatible = "zmk,keymap-sensors";
+ sensors = <&left_encoder>;
+ };
+
+ bt_unpair_combo: bt_unpair_combo {
+ compatible = "zmk,bt-unpair-combo";
+ };
};
&pro_micro_i2c {
status = "okay";
- ssd1306@3c {
+ oled: ssd1306@3c {
compatible = "solomon,ssd1306fb";
reg = <0x3c>;
label = "DISPLAY";
diff --git a/app/boards/shields/lily58/lily58.keymap b/app/boards/shields/lily58/lily58.keymap
new file mode 100644
index 0000000..afd2694
--- /dev/null
+++ b/app/boards/shields/lily58/lily58.keymap
@@ -0,0 +1,62 @@
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/keys.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+
+ default_layer {
+// ------------------------------------------------------------------------------------------------------------
+// | ESC | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | ` |
+// | TAB | Q | W | E | R | T | | Y | U | I | O | P | - |
+// | CTRL | A | S | D | F | G | | H | J | K | L | ; | ' |
+// | SHIFT | Z | X | C | V | B | "[" | | "]" | N | M | , | . | / | SHIFT |
+// | ALT | GUI | LOWER| SPACE | | ENTER | RAISE| BSPC | GUI |
+ bindings = <
+&kp ESC &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &kp GRAV
+&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp MINUS
+&kp LCTL &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SCLN &kp QUOT
+&kp LSFT &kp Z &kp X &kp C &kp V &kp B &kp LBKT &kp RBKT &kp N &kp M &kp CMMA &kp DOT &kp FSLH &kp RSFT
+ &kp LALT &kp LGUI &mo 1 &kp SPC &kp RET &mo 2 &kp BKSP &kp RGUI
+ >;
+
+ sensor-bindings = <&inc_dec_cp M_VOLU M_VOLD>;
+ };
+
+ lower_layer {
+// ------------------------------------------------------------------------------------------------------------
+// | | | | | | | | | | | | | |
+// | F1 | F2 | F3 | F4 | F5 | F6 | | F7 | F8 | F9 | F10 | F11 | F12 |
+// | ` | ! | @ | # | $ | % | | ^ | & | * | ( | ) | ~ |
+// | | | | | | | | | | | _ | + | { | } | "|" |
+// | | | | | | | | | |
+ bindings = <
+&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
+&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12
+&kp GRAV &kp BANG &kp ATSN &kp HASH &kp CURU &kp PRCT &kp CRRT &kp AMPS &kp KMLT &kp LPRN &kp RPRN &kp TILD
+&trans &trans &trans &trans &trans &trans &trans &trans &trans &kp MINUS &kp KPLS &kp LCUR &kp RCUR &kp PIPE
+ &trans &trans &trans &trans &trans &trans &trans &trans
+ >;
+
+ sensor-bindings = <&inc_dec_cp M_VOLU M_VOLD>;
+ };
+
+ raise_layer {
+// ------------------------------------------------------------------------------------------------------------
+// | | | | | | | | | | | | | |
+// | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | |
+// | F1 | F2 | F3 | F4 | F5 | F6 | | | <- | ^ | v | -> | |
+// | F7 | F8 | F9 | F10 | F11 | F12 | | | | + | - | = | [ | ] | \ |
+// | | | | | | | | | |
+ bindings = <
+&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
+&kp GRAV &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &trans
+&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &trans &kp LARW &kp DARW &kp UARW &kp RARW &trans
+&kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &trans &trans &kp KPLS &kp MINUS &kp EQL &kp LBKT &kp RBKT &kp BSLH
+ &trans &trans &trans &trans &trans &trans &trans &trans
+ >;
+
+ sensor-bindings = <&inc_dec_cp M_VOLU M_VOLD>;
+ };
+ };
+};
diff --git a/app/boards/shields/lily58/lily58_left.conf b/app/boards/shields/lily58/lily58_left.conf
index e51dee4..6ff95d5 100644
--- a/app/boards/shields/lily58/lily58_left.conf
+++ b/app/boards/shields/lily58/lily58_left.conf
@@ -1,2 +1,6 @@
+# Uncomment to enable encoder
+# CONFIG_EC11=y
+# CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y
+
CONFIG_ZMK_SPLIT=y
CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y \ No newline at end of file
diff --git a/app/boards/shields/lily58/lily58_left.overlay b/app/boards/shields/lily58/lily58_left.overlay
index c8e2213..1752b6e 100644
--- a/app/boards/shields/lily58/lily58_left.overlay
+++ b/app/boards/shields/lily58/lily58_left.overlay
@@ -17,3 +17,10 @@
;
};
+&left_encoder {
+ status = "okay";
+};
+
+&bt_unpair_combo {
+ key-positions = <0 53>;
+};
diff --git a/app/boards/shields/lily58/lily58_right.overlay b/app/boards/shields/lily58/lily58_right.overlay
index 748be14..6c8e493 100644
--- a/app/boards/shields/lily58/lily58_right.overlay
+++ b/app/boards/shields/lily58/lily58_right.overlay
@@ -21,3 +21,6 @@
;
};
+&bt_unpair_combo {
+ key-positions = <11 54>;
+};
diff --git a/app/boards/shields/petejohanson_handwire/Kconfig.defconfig b/app/boards/shields/petejohanson_handwire/Kconfig.defconfig
deleted file mode 100644
index 7da09ac..0000000
--- a/app/boards/shields/petejohanson_handwire/Kconfig.defconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-
-if SHIELD_PETEJOHANSON_HANDWIRE
-
-config ZMK_KEYBOARD_NAME
- default "Pete's Handwire Breadboard"
-
-config ZMK_BLE
- default y
-
-config ZMK_ACTION_MOD_TAP
- default y
-
-endif
diff --git a/app/boards/shields/petejohanson_handwire/Kconfig.shield b/app/boards/shields/petejohanson_handwire/Kconfig.shield
deleted file mode 100644
index defb90a..0000000
--- a/app/boards/shields/petejohanson_handwire/Kconfig.shield
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright (c) 2019 Linaro Limited
-# SPDX-License-Identifier: MIT
-
-config SHIELD_PETEJOHANSON_HANDWIRE
- def_bool $(shields_list_contains,petejohanson_handwire)
diff --git a/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay b/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay
deleted file mode 100644
index b294171..0000000
--- a/app/boards/shields/petejohanson_handwire/keymap/keymap.overlay
+++ /dev/null
@@ -1,40 +0,0 @@
-#include <dt-bindings/zmk/keys.h>
-#include <behaviors.dtsi>
-
-/ {
- chosen {
- zmk,keymap = &keymap0;
- };
-
- keymap0: keymap {
- compatible = "zmk,keymap";
- label ="Default keymap";
- layers = <&default &lower &raise>;
- };
-
- layers {
- compatible = "zmk,layers";
-
- default: layer_0 {
- label = "DEFAULT";
- bindings = <
- &cp M_NEXT &mt MOD_LSFT B &trans &trans
- &mo 1 &mo 2 &trans &trans>;
- };
-
- lower: layer_1 {
- label = "LOWER";
-
- bindings = <
- &cp M_PLAY &cp M_NEXT &trans &trans
- &trans &trans &trans &trans>;
- };
-
- raise: layer_2 {
- label = "RAISE";
- bindings = <
- &kp C &kp D &trans &trans
- &trans &kp E &trans &trans>;
- };
- };
-};
diff --git a/app/boards/shields/petejohanson_handwire/petejohanson_handwire.conf b/app/boards/shields/petejohanson_handwire/petejohanson_handwire.conf
deleted file mode 100644
index 63829ba..0000000
--- a/app/boards/shields/petejohanson_handwire/petejohanson_handwire.conf
+++ /dev/null
@@ -1 +0,0 @@
-CONFIG_ZMK_KSCAN_COMPOSITE_DRIVER=y
diff --git a/app/boards/shields/petejohanson_handwire/petejohanson_handwire.overlay b/app/boards/shields/petejohanson_handwire/petejohanson_handwire.overlay
deleted file mode 100644
index 95b0835..0000000
--- a/app/boards/shields/petejohanson_handwire/petejohanson_handwire.overlay
+++ /dev/null
@@ -1,44 +0,0 @@
-
-/ {
- chosen {
- zmk,kscan = &kscan0;
- };
-
- kscan0: kscan_0 {
- compatible = "zmk,kscan-composite";
- label = "KSCAN_COMP";
- rows = <2>;
- columns = <4>;
-
- left {
- kscan = <&left_hand>;
- };
-
- right {
- kscan = <&right_hand>;
- column-offset = <2>;
- };
- };
-
- left_hand: kscan_1 {
- compatible = "zmk,kscan-gpio-matrix";
- label = "KSCAN_LEFT";
-
- diode-direction = "row2col";
- row-gpios = <&arduino_header 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
- <&arduino_header 9 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
- col-gpios = <&arduino_header 10 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
- <&arduino_header 11 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
- };
-
- right_hand: kscan_2 {
- compatible = "zmk,kscan-gpio-matrix";
- label = "KSCAN_RIGHT";
-
- diode-direction = "row2col";
- row-gpios = <&arduino_header 12 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
- <&arduino_header 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
- col-gpios = <&arduino_header 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
- <&arduino_header 15 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
- };
-};
diff --git a/app/boards/shields/petejohanson_pro_micro_handwire/Kconfig.defconfig b/app/boards/shields/petejohanson_pro_micro_handwire/Kconfig.defconfig
deleted file mode 100644
index 5098fc8..0000000
--- a/app/boards/shields/petejohanson_pro_micro_handwire/Kconfig.defconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-
-if SHIELD_PETEJOHANSON_PRO_MICRO_HANDWIRE
-
-config ZMK_KEYBOARD_NAME
- default "Pete's ProMicro Compat Handwire"
-
-config ZMK_USB
- default y
-
-config ZMK_ACTION_MOD_TAP
- default y
-
-endif
diff --git a/app/boards/shields/petejohanson_pro_micro_handwire/Kconfig.shield b/app/boards/shields/petejohanson_pro_micro_handwire/Kconfig.shield
deleted file mode 100644
index b6264db..0000000
--- a/app/boards/shields/petejohanson_pro_micro_handwire/Kconfig.shield
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright (c) 2020 Pete Johanson
-# SPDX-License-Identifier: MIT
-
-config SHIELD_PETEJOHANSON_PRO_MICRO_HANDWIRE
- def_bool $(shields_list_contains,petejohanson_pro_micro_handwire)
diff --git a/app/boards/shields/petejohanson_pro_micro_handwire/keymap/keymap.overlay b/app/boards/shields/petejohanson_pro_micro_handwire/keymap/keymap.overlay
deleted file mode 100644
index ca03557..0000000
--- a/app/boards/shields/petejohanson_pro_micro_handwire/keymap/keymap.overlay
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <behaviors.dtsi>
-#include <dt-bindings/zmk/keys.h>
-
-/ {
- chosen {
- zmk,keymap = &keymap0;
- };
- keymap0: keymap {
- compatible = "zmk,keymap";
- label ="Default keymap";
- layers = <&default &lower &raise>;
- };
-
- layers {
- compatible = "zmk,layers";
-
- default: layer_0 {
- label = "DEFAULT";
-
- bindings = <
- &mo 1 &kp A
- &mo 2 &kp C>;
- };
-
- lower: layer_1 {
- label = "LOWER";
-
- bindings = <
- &trans &kp D
- &trans &kp E>;
- };
-
- raise: layer_2 {
- label = "RAISE";
-
- bindings = <
- &trans &kp I
- &trans &kp H>;
- };
- };
-};
diff --git a/app/boards/shields/petejohanson_pro_micro_handwire/petejohanson_pro_micro_handwire.overlay b/app/boards/shields/petejohanson_pro_micro_handwire/petejohanson_pro_micro_handwire.overlay
deleted file mode 100644
index 1b27b93..0000000
--- a/app/boards/shields/petejohanson_pro_micro_handwire/petejohanson_pro_micro_handwire.overlay
+++ /dev/null
@@ -1,17 +0,0 @@
-
-/ {
- chosen {
- zmk,kscan = &kscan0;
- };
-
- kscan0: kscan {
- compatible = "zmk,kscan-gpio-matrix";
- label = "KSCAN";
-
- diode-direction = "row2col";
- row-gpios = <&pro_micro_d 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
- <&pro_micro_d 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
- col-gpios = <&pro_micro_d 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
- <&pro_micro_d 9 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
- };
-};
diff --git a/app/boards/shields/qaz/Kconfig.defconfig b/app/boards/shields/qaz/Kconfig.defconfig
new file mode 100644
index 0000000..f82f458
--- /dev/null
+++ b/app/boards/shields/qaz/Kconfig.defconfig
@@ -0,0 +1,9 @@
+ # Copyright (c) 2020 TJ Campie
+ # SPDX-License-Identifier: MIT
+
+if SHIELD_QAZ
+
+config ZMK_KEYBOARD_NAME
+ default "QAZ"
+
+endif \ No newline at end of file
diff --git a/app/boards/shields/qaz/Kconfig.shield b/app/boards/shields/qaz/Kconfig.shield
new file mode 100644
index 0000000..9da6077
--- /dev/null
+++ b/app/boards/shields/qaz/Kconfig.shield
@@ -0,0 +1,5 @@
+# Copyright (c) 2020 TJ Campie
+# SPDX-License-Identifier: MIT
+
+ config SHIELD_MY_BOARD
+ def_bool $(shields_list_contains,qaz)
diff --git a/app/boards/shields/qaz/qaz.keymap b/app/boards/shields/qaz/qaz.keymap
new file mode 100644
index 0000000..ffa2f6c
--- /dev/null
+++ b/app/boards/shields/qaz/qaz.keymap
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2020 TJ Campie
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/keys.h>
+
+#define DEFAULT 0
+#define NUM_SYM 1
+#define NAV 2
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+
+ default_layer {
+ bindings = <
+ &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P
+ &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp RET
+ &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp CMMA &kp DOT
+ &kp LSFT &kp LGUI &kp LALT &mo NAV &kp SPC &mo NUM_SYM &kp QUOT &kp FSLH
+ >;
+ };
+ num_sym {
+ bindings = <
+ &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0
+ &trans &trans &trans &trans &trans &trans &trans &trans &kp EQL &kp MINUS
+ &kp DEL &none &none &none &none &none &none &none &kp DOT
+ &bootloader &reset &none &trans &trans &kp RET &trans &kp FSLH
+ >;
+ };
+
+ nav {
+ bindings = <
+ &none &none &none &none &none &none &none &kp UARW &none &kp BKSP
+ &trans &trans &trans &trans &none &none &kp LARW &kp DARW &kp RARW &none
+ &none &none &none &none &none &none &none &none &none
+ &none &none &none &none &none &trans &trans &kp RET &trans &kp FSLH
+ >;
+ };
+ };
+}; \ No newline at end of file
diff --git a/app/boards/shields/qaz/qaz.overlay b/app/boards/shields/qaz/qaz.overlay
new file mode 100644
index 0000000..472005b
--- /dev/null
+++ b/app/boards/shields/qaz/qaz.overlay
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2020 TJ Campie
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <dt-bindings/zmk/matrix-transform.h>
+
+/ {
+ chosen {
+ zmk,kscan = &kscan0;
+ zmk,matrix_transform = &default_transform;
+ };
+
+ default_transform: keymap_transform_0 {
+ compatible = "zmk,matrix-transform";
+ columns = <7>;
+ rows = <6>;
+ map = <
+ RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(4,0) RC(4,1) RC(4,2)
+ RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(5,0) RC(5,1) RC(5,2)
+ RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(4,3) RC(5,3)
+ RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(4,4)
+ >;
+ };
+
+
+ kscan0: kscan_0 {
+ compatible = "zmk,kscan-gpio-matrix";
+ label = "KSCAN";
+ diode-direction = "col2row";
+
+ col-gpios
+ = <&pro_micro_d 8 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 1 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 0 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 2 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 9 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 1 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 6 GPIO_ACTIVE_HIGH>
+ ;
+
+ row-gpios
+ = <&pro_micro_a 3 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 3 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ ;
+ };
+
+}; \ No newline at end of file
diff --git a/app/boards/shields/romac/Kconfig.defconfig b/app/boards/shields/romac/Kconfig.defconfig
new file mode 100644
index 0000000..5352797
--- /dev/null
+++ b/app/boards/shields/romac/Kconfig.defconfig
@@ -0,0 +1,10 @@
+# Copyright (c) 2020 Pete Johanson, Richard Jones
+# SPDX-License-Identifier: MIT
+
+if SHIELD_ROMAC
+
+config ZMK_KEYBOARD_NAME
+ default "RoMac"
+
+endif
+
diff --git a/app/boards/shields/romac/Kconfig.shield b/app/boards/shields/romac/Kconfig.shield
new file mode 100644
index 0000000..59669d3
--- /dev/null
+++ b/app/boards/shields/romac/Kconfig.shield
@@ -0,0 +1,5 @@
+# Copyright (c) 2020 Pete Johanson, Richard Jones
+# SPDX-License-Identifier: MIT
+
+config SHIELD_ROMAC
+ def_bool $(shields_list_contains,romac)
diff --git a/app/boards/shields/romac/romac.conf b/app/boards/shields/romac/romac.conf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/boards/shields/romac/romac.conf
diff --git a/app/boards/shields/romac/romac.keymap b/app/boards/shields/romac/romac.keymap
new file mode 100644
index 0000000..f94a829
--- /dev/null
+++ b/app/boards/shields/romac/romac.keymap
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2020 Pete Johanson, Richard Jones
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/keys.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+
+ default_layer {
+// -------------------
+// | 7 | 8 | 9 |
+// | 4 | 5 | 6 |
+// | 1 | 2 | 3 |
+// | MO(1) | 0 | . |
+// ----------------------
+ bindings = <
+ &kp NUM_7 &kp NUM_8 &kp NUM_9
+ &kp NUM_4 &kp NUM_5 &kp NUM_6
+ &kp NUM_1 &kp NUM_2 &kp NUM_3
+ &mo 1 &kp NUM_0 &kp DOT
+ >;
+ };
+
+ nav_layer {
+// -----------------------
+// | _ | HOME | PGUP |
+// | _ | END | PGDN |
+// | _ | _ | _ |
+// | _ | _ | RET |
+// -----------------------
+ bindings = <
+ &trans &kp HOME &kp PGUP
+ &trans &kp END &kp PGDN
+ &trans &trans &trans
+ &trans &trans &kp RET
+ >;
+ };
+ };
+};
+
+
diff --git a/app/boards/shields/romac/romac.overlay b/app/boards/shields/romac/romac.overlay
new file mode 100644
index 0000000..67d5868
--- /dev/null
+++ b/app/boards/shields/romac/romac.overlay
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020 Pete Johanson, Richard Jones
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <dt-bindings/zmk/matrix-transform.h>
+
+/ {
+ chosen {
+ zmk,kscan = &kscan0;
+ };
+
+ kscan0: kscan {
+ compatible = "zmk,kscan-gpio-matrix";
+ label = "KSCAN";
+
+ diode-direction = "col2row";
+ row-gpios
+ = <&pro_micro_d 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ ;
+
+ col-gpios
+ = <&pro_micro_a 0 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 15 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 14 GPIO_ACTIVE_HIGH>
+ ;
+
+ };
+
+ bt_unpair_combo: bt_unpair_combo {
+ compatible = "zmk,bt-unpair-combo";
+ key-positions = <0 11>;
+ };
+
+};
+
diff --git a/app/boards/shields/sofle/Kconfig.defconfig b/app/boards/shields/sofle/Kconfig.defconfig
new file mode 100644
index 0000000..58d8217
--- /dev/null
+++ b/app/boards/shields/sofle/Kconfig.defconfig
@@ -0,0 +1,54 @@
+# Copyright (c) 2020 Ryan Cross
+# SPDX-License-Identifier: MIT
+
+if SHIELD_SOFLE_LEFT
+
+config ZMK_KEYBOARD_NAME
+ default "Sofle Left"
+endif
+
+if SHIELD_SOFLE_RIGHT
+
+config ZMK_KEYBOARD_NAME
+ default "Sofle Right"
+endif
+
+if SHIELD_SOFLE_LEFT || SHIELD_SOFLE_RIGHT
+
+if ZMK_DISPLAY
+
+config I2C
+ default y
+
+config SSD1306
+ default y
+
+config SSD1306_REVERSE_MODE
+ default y
+
+endif # ZMK_DISPLAY
+
+if LVGL
+
+config LVGL_HOR_RES
+ default 128
+
+config LVGL_VER_RES
+ default 32
+
+config LVGL_VDB_SIZE
+ default 64
+
+config LVGL_DPI
+ default 148
+
+config LVGL_BITS_PER_PIXEL
+ default 1
+
+choice LVGL_COLOR_DEPTH
+ default LVGL_COLOR_DEPTH_1
+endchoice
+
+endif # LVGL
+
+endif
diff --git a/app/boards/shields/sofle/Kconfig.shield b/app/boards/shields/sofle/Kconfig.shield
new file mode 100644
index 0000000..e23a97a
--- /dev/null
+++ b/app/boards/shields/sofle/Kconfig.shield
@@ -0,0 +1,8 @@
+# Copyright (c) 2020 Ryan Cross
+# SPDX-License-Identifier: MIT
+
+config SHIELD_SOFLE_LEFT
+ def_bool $(shields_list_contains,sofle_left)
+
+config SHIELD_SOFLE_RIGHT
+ def_bool $(shields_list_contains,sofle_right)
diff --git a/app/boards/shields/sofle/sofle.conf b/app/boards/shields/sofle/sofle.conf
new file mode 100644
index 0000000..fe3f0f4
--- /dev/null
+++ b/app/boards/shields/sofle/sofle.conf
@@ -0,0 +1,9 @@
+# Copyright (c) 2020 Ryan Cross
+# SPDX-License-Identifier: MIT
+
+# Uncomment the following line to enable the Sofle OLED Display
+# CONFIG_ZMK_DISPLAY=y
+
+# Uncomment these two lines to add support for encoders
+# CONFIG_EC11=y
+# CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y
diff --git a/app/boards/shields/sofle/sofle.dtsi b/app/boards/shields/sofle/sofle.dtsi
new file mode 100644
index 0000000..bff42f6
--- /dev/null
+++ b/app/boards/shields/sofle/sofle.dtsi
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2020 Pete Johanson, Ryan Cross
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <dt-bindings/zmk/matrix-transform.h>
+
+/ {
+ chosen {
+ zmk,kscan = &kscan0;
+ zmk,matrix_transform = &default_transform;
+ };
+
+ default_transform: keymap_transform_0 {
+ compatible = "zmk,matrix-transform";
+ columns = <16>;
+ rows = <4>;
+// | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 | | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 |
+// | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 | | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 |
+// | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 | | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 |
+// | SW24 | SW23 | SW22 | SW21 | SW20 | SW19 | SW25 | | SW25 | SW19 | SW20 | SW21 | SW22 | SW23 | SW24 |
+// | SW30 | SW29 | SW28 | SW27 | SW26 | | SW26 | SW27 | SW28 | SW29 | SW30 |
+ map = <
+RC(0,0) 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(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(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(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(4,5) RC(4,6) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11)
+ RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,7) RC(4,8) RC(4,9) RC(4,10) RC(4,11)
+ >;
+ };
+
+ kscan0: kscan {
+ compatible = "zmk,kscan-gpio-matrix";
+ label = "KSCAN";
+
+ diode-direction = "col2row";
+ row-gpios
+ = <&pro_micro_d 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ ;
+ };
+
+ left_encoder: encoder_left {
+ compatible = "alps,ec11";
+ label = "LEFT_ENCODER";
+ a-gpios = <&pro_micro_a 3 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
+ b-gpios = <&pro_micro_a 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
+ resolution = <4>;
+ status = "disabled";
+ };
+
+ right_encoder: encoder_right {
+ compatible = "alps,ec11";
+ label = "RIGHT_ENCODER";
+ a-gpios = <&pro_micro_a 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
+ b-gpios = <&pro_micro_a 3 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
+ resolution = <4>;
+ status = "disabled";
+ };
+
+ sensors {
+ compatible = "zmk,keymap-sensors";
+ sensors = <&left_encoder &right_encoder>;
+ };
+
+ bt_unpair_combo: bt_unpair_combo {
+ compatible = "zmk,bt-unpair-combo";
+ };
+};
+
+&pro_micro_i2c {
+ status = "okay";
+
+ ssd1306@3c {
+ compatible = "solomon,ssd1306fb";
+ reg = <0x3c>;
+ label = "DISPLAY";
+ width = <128>;
+ height = <32>;
+ segment-offset = <0>;
+ page-offset = <0>;
+ display-offset = <0>;
+ multiplex-ratio = <31>;
+ segment-remap;
+ com-invdir;
+ com-sequential;
+ prechargep = <0x22>;
+ };
+};
diff --git a/app/boards/shields/sofle/sofle.keymap b/app/boards/shields/sofle/sofle.keymap
new file mode 100644
index 0000000..aadffa1
--- /dev/null
+++ b/app/boards/shields/sofle/sofle.keymap
@@ -0,0 +1,63 @@
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/keys.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+
+ default_layer {
+// ------------------------------------------------------------------------------------------------------------
+// | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | |
+// | ESC | Q | W | E | R | T | | Y | U | I | O | P | BKSPC |
+// | TAB | A | S | D | F | G | | H | J | K | L | ; | ' |
+// | SHIFT | Z | X | C | V | B | MUTE | | | N | M | , | . | / | SHIFT |
+// | GUI | ALT | CTRL | LOWER| ENTER | | SPACE | RAISE| CTRL | ALT | GUI |
+ bindings = <
+&kp GRAV &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &none
+&kp ESC &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BKSP
+&kp TAB &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SCLN &kp QUOT
+&kp LSFT &kp Z &kp X &kp C &kp V &kp B &cp M_MUTE &none &kp N &kp M &kp CMMA &kp DOT &kp FSLH &kp RSFT
+ &kp LGUI &kp LALT &kp LCTL &mo 1 &kp RET &kp SPC &mo 2 &kp RCTL &kp RALT &kp RGUI
+ >;
+
+ sensor-bindings = <&inc_dec_cp M_VOLU M_VOLD &inc_dec_kp PGUP PGDN>;
+ };
+
+ lower_layer {
+// TODO: Some binds are waiting for shifted keycode support.
+// ------------------------------------------------------------------------------------------------------------
+// | | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10 | F11 |
+// | ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | F12 |
+// | | ! | @ | # | $ | % | | ^ | & | * | ( | ) | | |
+// | | = | - | + | { | } | | | | [ | ] | ; | : | \ | |
+// | | | | | | | | | | | |
+ bindings = <
+&trans &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11
+&kp GRAV &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &kp F12
+&trans &kp BANG &kp ATSN &kp HASH &kp CURU &kp PRCT &kp CRRT &kp AMPS &kp KMLT &kp LPRN &kp RPRN &kp PIPE
+&trans &kp EQL &kp MINUS &kp KPLS &kp LCUR &kp RCUR &trans &trans &kp LBKT &kp RBKT &kp SCLN &kp COLN &kp BSLH &trans
+ &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
+ >;
+
+ sensor-bindings = <&inc_dec_cp M_VOLU M_VOLD &inc_dec_kp PGUP PGDN>;
+ };
+
+ raise_layer {
+// ------------------------------------------------------------------------------------------------------------
+// | | | | | | | | | | | | | |
+// | | INS | PSCR | GUI | | | | PGUP | | ^ | | | |
+// | | ALT | CTRL | SHIFT | | CAPS | | PGDN | <- | v | -> | DEL | BKSPC |
+// | | UNDO | CUT | COPY | PASTE | | | | | | | | | | |
+// | | | | | | | | | | | |
+ bindings = <
+&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
+&trans &kp INS &kp PRSC &kp GUI &trans &trans &kp PGUP &trans &kp UARW &trans &kp NUM_0 &trans
+&trans &kp LALT &kp LCTL &kp LSFT &trans &kp CLCK &kp PGDN &kp LARW &kp DARW &kp RARW &kp DEL &kp BKSP
+&trans &kp UNDO &kp CUT &kp COPY &kp PSTE &trans &trans &trans &trans &trans &trans &trans &trans &trans
+ &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
+ >;
+
+ sensor-bindings = <&inc_dec_cp M_VOLU M_VOLD &inc_dec_kp PGUP PGDN>;
+ };
+ };
+};
diff --git a/app/boards/shields/sofle/sofle_left.conf b/app/boards/shields/sofle/sofle_left.conf
new file mode 100644
index 0000000..bbac735
--- /dev/null
+++ b/app/boards/shields/sofle/sofle_left.conf
@@ -0,0 +1,5 @@
+# Copyright (c) 2020 Ryan Cross
+# SPDX-License-Identifier: MIT
+
+CONFIG_ZMK_SPLIT=y
+CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y
diff --git a/app/boards/shields/sofle/sofle_left.overlay b/app/boards/shields/sofle/sofle_left.overlay
new file mode 100644
index 0000000..0dfb753
--- /dev/null
+++ b/app/boards/shields/sofle/sofle_left.overlay
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020 Ryan Cross
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "sofle.dtsi"
+
+&kscan0 {
+ col-gpios
+ = <&pro_micro_a 1 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 0 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 15 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 14 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 16 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 10 GPIO_ACTIVE_HIGH>
+ ;
+};
+
+&left_encoder {
+ status = "okay";
+};
+
+&bt_unpair_combo {
+ key-positions = <0 54>;
+};
diff --git a/app/boards/shields/sofle/sofle_right.conf b/app/boards/shields/sofle/sofle_right.conf
new file mode 100644
index 0000000..ca5de38
--- /dev/null
+++ b/app/boards/shields/sofle/sofle_right.conf
@@ -0,0 +1,5 @@
+# Copyright (c) 2020 Ryan Cross
+# SPDX-License-Identifier: MIT
+
+CONFIG_ZMK_SPLIT=y
+CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y
diff --git a/app/boards/shields/sofle/sofle_right.overlay b/app/boards/shields/sofle/sofle_right.overlay
new file mode 100644
index 0000000..8eaf076
--- /dev/null
+++ b/app/boards/shields/sofle/sofle_right.overlay
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2020 Ryan Cross
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "sofle.dtsi"
+
+&default_transform {
+ col-offset = <6>;
+};
+
+&kscan0 {
+ col-gpios
+ = <&pro_micro_d 10 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 16 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 14 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 15 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 0 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 1 GPIO_ACTIVE_HIGH>
+ ;
+};
+
+&right_encoder {
+ status = "okay";
+};
+
+&bt_unpair_combo {
+ key-positions = <11 55>;
+};
diff --git a/app/boards/shields/splitreus62/Kconfig.defconfig b/app/boards/shields/splitreus62/Kconfig.defconfig
new file mode 100644
index 0000000..a2464a7
--- /dev/null
+++ b/app/boards/shields/splitreus62/Kconfig.defconfig
@@ -0,0 +1,22 @@
+
+#Copyright (c) 2020 Derek Schmell
+#SPDX-License-Identifier: MIT
+
+
+if SHIELD_SPLITREUS62_LEFT
+
+config ZMK_KEYBOARD_NAME
+ default "Splitreus62 Left"
+
+endif
+
+if SHIELD_SPLITREUS62_RIGHT
+
+config ZMK_KEYBOARD_NAME
+ default "Splitreus62 Right"
+
+endif
+
+if SHIELD_SPLITREUS62_LEFT || SHIELD_SPLITREUS62_RIGHT
+
+endif
diff --git a/app/boards/shields/splitreus62/Kconfig.shield b/app/boards/shields/splitreus62/Kconfig.shield
new file mode 100644
index 0000000..762d991
--- /dev/null
+++ b/app/boards/shields/splitreus62/Kconfig.shield
@@ -0,0 +1,8 @@
+# Copyright (c) 2020 Derek Schmell
+# SPDX-License-Identifier: MIT
+
+config SHIELD_SPLITREUS62_LEFT
+ def_bool $(shields_list_contains,splitreus62_left)
+
+config SHIELD_SPLITREUS62_RIGHT
+ def_bool $(shields_list_contains,splitreus62_right)
diff --git a/app/boards/shields/splitreus62/splitreus62.conf b/app/boards/shields/splitreus62/splitreus62.conf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/boards/shields/splitreus62/splitreus62.conf
diff --git a/app/boards/shields/splitreus62/splitreus62.dtsi b/app/boards/shields/splitreus62/splitreus62.dtsi
new file mode 100644
index 0000000..c2bfbc4
--- /dev/null
+++ b/app/boards/shields/splitreus62/splitreus62.dtsi
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2020 Derek Schmell
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <dt-bindings/zmk/matrix-transform.h>
+
+/ {
+ chosen {
+ zmk,kscan = &kscan0;
+ zmk,matrix_transform = &default_transform;
+ };
+
+ default_transform: keymap_transform_0 {
+ compatible = "zmk,matrix-transform";
+ columns = <12>;
+ rows = <6>;
+// | SW0 | SW5 | SW10 | SW15 | SW20 | SW25 | SW25 | SW20 | SW15 | SW10 | SW5 | SW1 |
+// | SW1 | SW6 | SW11 | SW16 | SW21 | SW26 | SW26 | SW21 | SW16 | SW11 | SW6 | SW2 |
+// | SW2 | SW7 | SW12 | SW17 | SW22 | SW27 | SW27 | SW22 | SW17 | SW12 | SW7 | SW3 |
+// | SW3 | SW8 | SW13 | SW18 | SW23 | SW28 | SW28 | SW23 | SW18 | SW13 | SW8 | SW4 |
+// | SW4 | SW9 | SW14 | SW19 | SW24 | SW29 | SW29 | SW24 | SW19 | SW14 | SW9 | SW5 |
+// SW30 | SW30
+ map = <
+RC(0,0) 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(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(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(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(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,5) RC(4,6) RC(4,7) RC(4,8) RC(4,9) RC(4,10) RC(4,11)
+ RC(5,5) RC(5,6)
+ >;
+ };
+
+ kscan0: kscan {
+ compatible = "zmk,kscan-gpio-matrix";
+ label = "KSCAN";
+
+ diode-direction = "row2col";
+ row-gpios
+ = <&pro_micro_d 1 GPIO_ACTIVE_HIGH >
+ , <&pro_micro_d 0 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 2 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 4 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 5 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_d 6 GPIO_ACTIVE_HIGH>
+ ;
+
+ };
+};
diff --git a/app/boards/shields/splitreus62/splitreus62.keymap b/app/boards/shields/splitreus62/splitreus62.keymap
new file mode 100644
index 0000000..920e61a
--- /dev/null
+++ b/app/boards/shields/splitreus62/splitreus62.keymap
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2020 Derek Schmell
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/keys.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+
+ default_layer {
+// ------------------------------------------------------------------------------------------------------------
+// | ESC | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | - |
+// | TAB | Q | W | E | R | T | | Y | U | I | O | P | \ |
+// | CTRL | A | S | D | F | G | | H | J | K | L | ; | ' |
+// | SHIFT | Z | X | C | V | B | | N | M | , | . | / | SHIFT |
+// | LCTL | LGUI | LALT | GRAV | | EQL | DEL | BKSP| | RET | SPC | LBKT | RBKT | LBKT | HOME | END |
+ bindings = <
+&kp ESC &kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0 &kp MINUS
+&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BSLH
+&kp LCTL &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SCLN &kp QUOT
+&kp LSFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp CMMA &kp DOT &kp FSLH &kp RSFT
+&kp LCTL &kp LGUI &kp LALT &kp GRAV &kp EQL &kp DEL &kp SPC &kp LBKT &kp RBKT &kp MINUS &kp HOME &kp END
+ &kp BKSP &kp RET
+ >;
+ };
+ };
+};
diff --git a/app/boards/shields/splitreus62/splitreus62_left.conf b/app/boards/shields/splitreus62/splitreus62_left.conf
new file mode 100644
index 0000000..e51dee4
--- /dev/null
+++ b/app/boards/shields/splitreus62/splitreus62_left.conf
@@ -0,0 +1,2 @@
+CONFIG_ZMK_SPLIT=y
+CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y \ No newline at end of file
diff --git a/app/boards/shields/splitreus62/splitreus62_left.overlay b/app/boards/shields/splitreus62/splitreus62_left.overlay
new file mode 100644
index 0000000..b156d60
--- /dev/null
+++ b/app/boards/shields/splitreus62/splitreus62_left.overlay
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020 Derek Schmell
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "splitreus62.dtsi"
+
+&kscan0 {
+ col-gpios
+ = <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 10 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 16 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 14 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ ;
+};
diff --git a/app/boards/shields/splitreus62/splitreus62_right.conf b/app/boards/shields/splitreus62/splitreus62_right.conf
new file mode 100644
index 0000000..a835adc
--- /dev/null
+++ b/app/boards/shields/splitreus62/splitreus62_right.conf
@@ -0,0 +1,2 @@
+CONFIG_ZMK_SPLIT=y
+CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y \ No newline at end of file
diff --git a/app/boards/shields/splitreus62/splitreus62_right.overlay b/app/boards/shields/splitreus62/splitreus62_right.overlay
new file mode 100644
index 0000000..5db87cc
--- /dev/null
+++ b/app/boards/shields/splitreus62/splitreus62_right.overlay
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2020 Derek Schmell
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "splitreus62.dtsi"
+
+&default_transform {
+ col-offset = <6>;
+};
+
+&kscan0 {
+ col-gpios
+ = <&pro_micro_d 14 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 16 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 10 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ ;
+};
diff --git a/app/cmake/zmk_config.cmake b/app/cmake/zmk_config.cmake
index e4d2632..017dd11 100644
--- a/app/cmake/zmk_config.cmake
+++ b/app/cmake/zmk_config.cmake
@@ -44,6 +44,7 @@ endif()
set(CACHED_ZMK_CONFIG ${ZMK_CONFIG} CACHE STRING "Selected user ZMK config")
if (ZMK_CONFIG)
+ set(ENV{ZMK_CONFIG} "${ZMK_CONFIG}")
if(EXISTS ${ZMK_CONFIG}/boards)
message(STATUS "Adding ZMK config directory as board root: ${ZMK_CONFIG}")
list(APPEND BOARD_ROOT ${ZMK_CONFIG})
@@ -62,11 +63,9 @@ foreach(root ${BOARD_ROOT})
NAMES ${BOARD}_defconfig
PATHS ${root}/boards/*/*
NO_DEFAULT_PATH
- )
- if(BOARD_DIR)
- if (EXISTS "${BOARD_DIR}/keymap")
- list(APPEND KEYMAP_DIRS ${BOARD_DIR}/keymap)
- endif()
+ )
+ if(BOARD_DIR)
+ list(APPEND KEYMAP_DIRS ${BOARD_DIR})
endif()
if(DEFINED SHIELD)
@@ -77,37 +76,16 @@ foreach(root ${BOARD_ROOT})
)
foreach(shield_path ${shields_refs_list})
get_filename_component(SHIELD_DIR ${shield_path} NAME)
- if (EXISTS "${shield_path}/keymap")
- list(APPEND KEYMAP_DIRS ${shield_path}/keymap)
- endif()
+ list(APPEND KEYMAP_DIRS ${shield_path})
endforeach()
endif()
endforeach()
-find_path(BASE_KEYMAPS_DIR
- NAMES ${KEYMAP}/keymap.overlay
- PATHS ${KEYMAP_DIRS}
- NO_DEFAULT_PATH
-)
-
-if (BASE_KEYMAPS_DIR)
- set(KEYMAP_DIR "${BASE_KEYMAPS_DIR}/${KEYMAP}" CACHE STRING "Selected keymap directory")
- message(STATUS "Keyboard Base Keymap: ${KEYMAP_DIR}/")
- # Used to let local imports of custom keycodes work as expected
- list(APPEND DTS_ROOT ${KEYMAP_DIR})
- if (EXISTS "${KEYMAP_DIR}/include")
- include_directories("${KEYMAP_DIR}/include")
- endif()
- list(APPEND ZMK_DTC_FILES "${KEYMAP_DIR}keymap.overlay")
-endif()
-
if (ZMK_CONFIG)
if (EXISTS ${ZMK_CONFIG})
message(STATUS "ZMK Config directory: ${ZMK_CONFIG}")
list(APPEND DTS_ROOT ${ZMK_CONFIG})
- if (EXISTS "${ZMK_CONFIG}/include")
- include_directories("${ZMK_CONFIG}/include")
- endif()
+ list(PREPEND KEYMAP_DIRS "${ZMK_CONFIG}")
if (SHIELD)
message(STATUS "Board: ${BOARD}, ${BOARD_DIR}, ${SHIELD}, ${SHIELD_DIR}")
@@ -137,7 +115,7 @@ if (ZMK_CONFIG)
foreach(conf ${config_candidates})
if (EXISTS "${conf}")
- message(STATUS "ZMK Config Kconfig: ${overlay}")
+ message(STATUS "ZMK Config Kconfig: ${conf}")
set(CONF_FILE "${conf}")
break()
endif()
@@ -147,6 +125,25 @@ if (ZMK_CONFIG)
endif()
endif()
+
+if(NOT KEYMAP_FILE)
+ foreach(keymap_dir ${KEYMAP_DIRS})
+ foreach(keymap_prefix ${SHIELD} ${SHIELD_DIR} ${BOARD} ${BOARD_DIR})
+ if (EXISTS ${keymap_dir}/${keymap_prefix}.keymap)
+ set(KEYMAP_FILE "${keymap_dir}/${keymap_prefix}.keymap" CACHE STRING "Selected keymap file")
+ message(STATUS "Using keymap file: ${KEYMAP_FILE}")
+ break()
+ endif()
+ endforeach()
+ endforeach()
+endif()
+
+if (NOT KEYMAP_FILE)
+ message(FATAL_ERROR "Failed to locate keymap file!")
+endif()
+
+list(APPEND ZMK_DTC_FILES ${KEYMAP_FILE})
+
if (ZMK_DTC_FILES)
string(REPLACE ";" " " DTC_OVERLAY_FILE "${ZMK_DTC_FILES}")
endif()
diff --git a/app/drivers/zephyr/Kconfig b/app/drivers/zephyr/Kconfig
index b22c4b1..0237846 100644
--- a/app/drivers/zephyr/Kconfig
+++ b/app/drivers/zephyr/Kconfig
@@ -25,7 +25,7 @@ menuconfig EC11
if EC11
-choice EC11_TRIGGER
+choice
prompt "Trigger mode"
default EC11_TRIGGER_NONE
help
@@ -46,6 +46,9 @@ config EC11_TRIGGER_OWN_THREAD
endchoice
+config EC11_TRIGGER
+ bool
+
config EC11_THREAD_PRIORITY
int "Thread priority"
depends on EC11_TRIGGER_OWN_THREAD
diff --git a/app/drivers/zephyr/ec11_trigger.c b/app/drivers/zephyr/ec11_trigger.c
index 55acf45..709d1fb 100644
--- a/app/drivers/zephyr/ec11_trigger.c
+++ b/app/drivers/zephyr/ec11_trigger.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2016 Intel Corporation
*
- * SPDX-License-Identifier: Apache-2.0
+ * SPDX-License-Identifier: MIT
*/
#define DT_DRV_COMPAT alps_ec11
diff --git a/app/drivers/zephyr/kscan_gpio_direct.c b/app/drivers/zephyr/kscan_gpio_direct.c
index 6e0beb0..a3aa8c4 100644
--- a/app/drivers/zephyr/kscan_gpio_direct.c
+++ b/app/drivers/zephyr/kscan_gpio_direct.c
@@ -156,7 +156,6 @@ static int kscan_gpio_read(struct device *dev)
struct kscan_gpio_data *data = dev->driver_data;
const struct kscan_gpio_config *cfg = dev->config_info;
u32_t read_state = data->pin_state;
- LOG_DBG("Scanning the pins for updated state");
for (int i = 0; i < cfg->num_of_inputs; i++)
{
struct device *in_dev = kscan_gpio_input_devices(dev)[i];
@@ -165,8 +164,9 @@ static int kscan_gpio_read(struct device *dev)
}
for (int i = 0; i < cfg->num_of_inputs; i++)
{
+ bool prev_pressed = BIT(i) & data->pin_state;
bool pressed = BIT(i) & read_state;
- if (pressed != (BIT(i) & data->pin_state))
+ if (pressed != prev_pressed)
{
LOG_DBG("Sending event at %d,%d state %s",
0, i, (pressed ? "on" : "off"));
diff --git a/app/drivers/zephyr/kscan_gpio_matrix.c b/app/drivers/zephyr/kscan_gpio_matrix.c
index 8e27712..b19c492 100644
--- a/app/drivers/zephyr/kscan_gpio_matrix.c
+++ b/app/drivers/zephyr/kscan_gpio_matrix.c
@@ -171,7 +171,7 @@ static int kscan_gpio_config_interrupts(struct device **devices,
({ k_work_submit(&data->work); }), \
({ \
k_delayed_work_cancel(&data->work); \
- k_delayed_work_submit(&data->work, K_MSEC(1)); })) \
+ k_delayed_work_submit(&data->work, K_MSEC(5)); })) \
} \
return 0; \
} \
@@ -205,7 +205,13 @@ static int kscan_gpio_config_interrupts(struct device **devices,
} \
data->callback = callback; \
return 0; \
- } \
+ }; \
+ static int kscan_gpio_enable_##n(struct device *dev) \
+ { \
+ int err = kscan_gpio_enable_interrupts_##n(dev); \
+ if (err) { return err; } \
+ return kscan_gpio_read_##n(dev); \
+ }; \
static int kscan_gpio_init_##n(struct device *dev) \
{ \
struct kscan_gpio_data_##n *data = dev->driver_data; \
@@ -258,7 +264,7 @@ static int kscan_gpio_config_interrupts(struct device **devices,
} \
static const struct kscan_driver_api gpio_driver_api_##n = { \
.config = kscan_gpio_configure_##n, \
- .enable_callback = kscan_gpio_enable_interrupts_##n, \
+ .enable_callback = kscan_gpio_enable_##n, \
.disable_callback = kscan_gpio_disable_interrupts_##n, \
}; \
static const struct kscan_gpio_config_##n kscan_gpio_config_##n = { \
diff --git a/app/dts/behaviors.dtsi b/app/dts/behaviors.dtsi
index 04e42b6..ab70bcc 100644
--- a/app/dts/behaviors.dtsi
+++ b/app/dts/behaviors.dtsi
@@ -1,7 +1,10 @@
#include <behaviors/key_press.dtsi>
#include <behaviors/transparent.dtsi>
+#include <behaviors/none.dtsi>
#include <behaviors/mod_tap.dtsi>
+#include <behaviors/layer_tap.dtsi>
#include <behaviors/momentary_layer.dtsi>
+#include <behaviors/toggle_layer.dtsi>
#include <behaviors/reset.dtsi>
#include <behaviors/sensor_rotate_key_press.dtsi>
#include <behaviors/rgb_underglow.dtsi> \ No newline at end of file
diff --git a/app/dts/behaviors/layer_tap.dtsi b/app/dts/behaviors/layer_tap.dtsi
new file mode 100644
index 0000000..af7319b
--- /dev/null
+++ b/app/dts/behaviors/layer_tap.dtsi
@@ -0,0 +1,12 @@
+/ {
+ behaviors {
+ lt: behavior_layer_tap {
+ compatible = "zmk,behavior-hold-tap";
+ label = "LAYER_TAP";
+ #binding-cells = <2>;
+ flavor = "tap-preferred";
+ tapping_term_ms = <200>;
+ bindings = <&mo>, <&kp>;
+ };
+ };
+};
diff --git a/app/dts/behaviors/mod_tap.dtsi b/app/dts/behaviors/mod_tap.dtsi
index 8e3b4e9..4ce732b 100644
--- a/app/dts/behaviors/mod_tap.dtsi
+++ b/app/dts/behaviors/mod_tap.dtsi
@@ -1,9 +1,12 @@
/ {
behaviors {
mt: behavior_mod_tap {
- compatible = "zmk,behavior-mod-tap";
+ compatible = "zmk,behavior-hold-tap";
label = "MOD_TAP";
#binding-cells = <2>;
+ flavor = "hold-preferred";
+ tapping_term_ms = <200>;
+ bindings = <&kp>, <&kp>;
};
};
};
diff --git a/app/dts/behaviors/none.dtsi b/app/dts/behaviors/none.dtsi
new file mode 100644
index 0000000..e84ed49
--- /dev/null
+++ b/app/dts/behaviors/none.dtsi
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020 Pete Johanson
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+/ {
+ behaviors {
+ none: behavior_none {
+ compatible = "zmk,behavior-none";
+ label = "NONE";
+ #binding-cells = <0>;
+ };
+ };
+};
diff --git a/app/dts/behaviors/reset.dtsi b/app/dts/behaviors/reset.dtsi
index 4e3b444..fc4fa14 100644
--- a/app/dts/behaviors/reset.dtsi
+++ b/app/dts/behaviors/reset.dtsi
@@ -1,3 +1,5 @@
+#include <dt-bindings/zmk/reset.h>
+
/ {
behaviors {
reset: behavior_reset {
@@ -5,5 +7,12 @@
label = "RESET";
#binding-cells = <0>;
};
+
+ bootloader: behavior_reset_dfu {
+ compatible = "zmk,behavior-reset";
+ label = "BOOTLOADER_RESET";
+ type = <RST_UF2>;
+ #binding-cells = <0>;
+ };
};
};
diff --git a/app/dts/behaviors/toggle_layer.dtsi b/app/dts/behaviors/toggle_layer.dtsi
new file mode 100644
index 0000000..86a050d
--- /dev/null
+++ b/app/dts/behaviors/toggle_layer.dtsi
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2020 Cody McGinnis <brainwart@gmail.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+ / {
+ behaviors {
+ tog: behavior_toggle_layer {
+ compatible = "zmk,behavior-toggle-layer";
+ label = "TOGGLE_LAYER";
+ #binding-cells = <1>;
+ };
+ };
+};
diff --git a/app/dts/bindings/behaviors/zmk,behavior-hold-tap.yaml b/app/dts/bindings/behaviors/zmk,behavior-hold-tap.yaml
new file mode 100644
index 0000000..a20578f
--- /dev/null
+++ b/app/dts/bindings/behaviors/zmk,behavior-hold-tap.yaml
@@ -0,0 +1,23 @@
+# Copyright (c) 2020, Cody McGinnis; Okke Formsma
+# SPDX-License-Identifier: MIT
+
+description: Hold or Tap behavior
+
+compatible: "zmk,behavior-hold-tap"
+
+include: two_param.yaml
+
+properties:
+ bindings:
+ type: phandles
+ required: true
+ tapping_term_ms:
+ type: int
+ flavor:
+ type: string
+ required: false
+ default: "hold-preferred"
+ enum:
+ - "hold-preferred"
+ - "balanced"
+ - "tap-preferred" \ No newline at end of file
diff --git a/app/dts/bindings/behaviors/zmk,behavior-mod-tap.yaml b/app/dts/bindings/behaviors/zmk,behavior-mod-tap.yaml
deleted file mode 100644
index 7911082..0000000
--- a/app/dts/bindings/behaviors/zmk,behavior-mod-tap.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2020, Pete Johanson
-# SPDX-License-Identifier: MIT
-
-description: Mod-Tap Beavhior
-
-compatible: "zmk,behavior-mod-tap"
-
-include: two_param.yaml
diff --git a/app/dts/bindings/behaviors/zmk,behavior-none.yaml b/app/dts/bindings/behaviors/zmk,behavior-none.yaml
new file mode 100644
index 0000000..9c66c94
--- /dev/null
+++ b/app/dts/bindings/behaviors/zmk,behavior-none.yaml
@@ -0,0 +1,8 @@
+# Copyright (c) 2020, Pete Johanson
+# SPDX-License-Identifier: MIT
+
+description: None Binding Behavior
+
+compatible: "zmk,behavior-none"
+
+include: zero_param.yaml
diff --git a/app/dts/bindings/behaviors/zmk,behavior-reset.yaml b/app/dts/bindings/behaviors/zmk,behavior-reset.yaml
index c8e5e6f..061b15e 100644
--- a/app/dts/bindings/behaviors/zmk,behavior-reset.yaml
+++ b/app/dts/bindings/behaviors/zmk,behavior-reset.yaml
@@ -6,3 +6,8 @@ description: Keyboard Reset Behavior
compatible: "zmk,behavior-reset"
include: zero_param.yaml
+
+properties:
+ type:
+ type: int
+ default: 0
diff --git a/app/dts/bindings/behaviors/zmk,behavior-toggle-layer.yaml b/app/dts/bindings/behaviors/zmk,behavior-toggle-layer.yaml
new file mode 100644
index 0000000..065949f
--- /dev/null
+++ b/app/dts/bindings/behaviors/zmk,behavior-toggle-layer.yaml
@@ -0,0 +1,8 @@
+# Copyright (c) 2020, Cody McGinnis <brainwart@gmail.com>
+# SPDX-License-Identifier: MIT
+
+description: Toggle Layer
+
+compatible: "zmk,behavior-toggle-layer"
+
+include: one_param.yaml
diff --git a/app/dts/bindings/zmk,bt-unpair-combo.yaml b/app/dts/bindings/zmk,bt-unpair-combo.yaml
new file mode 100644
index 0000000..d781347
--- /dev/null
+++ b/app/dts/bindings/zmk,bt-unpair-combo.yaml
@@ -0,0 +1,12 @@
+# Copyright (c) 2020, Pete Johanson
+# SPDX-License-Identifier: MIT
+
+description: |
+ Defines a set of key positions that will unpair all BT devices if held on startup.
+
+compatible: "zmk,bt-unpair-combo"
+
+properties:
+ key-positions:
+ type: array
+ required: true
diff --git a/app/dts/bindings/zmk,keymap.yaml b/app/dts/bindings/zmk,keymap.yaml
index b9517a3..fb6d914 100644
--- a/app/dts/bindings/zmk,keymap.yaml
+++ b/app/dts/bindings/zmk,keymap.yaml
@@ -3,15 +3,13 @@ description: |
compatible: "zmk,keymap"
-properties:
- transform:
- type: phandle
- required: false
-
- label:
- type: string
- required: true
-
- layers:
- type: phandles
- required: true
+child-binding:
+ description: "A layer to be used in a keymap"
+
+ properties:
+ bindings:
+ type: phandle-array
+ required: true
+ sensor-bindings:
+ type: phandle-array
+ required: false
diff --git a/app/dts/bindings/zmk,kscan-mock.yaml b/app/dts/bindings/zmk,kscan-mock.yaml
index 41dd5b8..f9d83fa 100644
--- a/app/dts/bindings/zmk,kscan-mock.yaml
+++ b/app/dts/bindings/zmk,kscan-mock.yaml
@@ -15,3 +15,5 @@ properties:
type: int
columns:
type: int
+ exit-after:
+ type: boolean
diff --git a/app/dts/bindings/zmk,layers.yaml b/app/dts/bindings/zmk,layers.yaml
deleted file mode 100644
index 1a3592e..0000000
--- a/app/dts/bindings/zmk,layers.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: |
- Allows defining the various keymap layers for use.
-
-compatible: "zmk,layers"
-
-child-binding:
- description: "A layer to be used in a keymap"
-
- properties:
- label:
- type: string
- required: true
- bindings:
- type: phandle-array
- required: true
- sensor-bindings:
- type: phandle-array
- required: false
diff --git a/app/include/dt-bindings/zmk/keys.h b/app/include/dt-bindings/zmk/keys.h
index e2c3160..cd9261d 100644
--- a/app/include/dt-bindings/zmk/keys.h
+++ b/app/include/dt-bindings/zmk/keys.h
@@ -50,12 +50,12 @@
#define LBKT 0x2F
#define RBKT 0x30
#define BSLH 0x31
-
+#define TILD 0x32
#define SCLN 0x33
#define QUOT 0x34
#define GRAV 0x35
#define CMMA 0x36
-#define DOT 0x37
+#define DOT 0x37
#define FSLH 0x38
#define CLCK 0x39
#define F1 0x3A
@@ -92,6 +92,11 @@
#define GUI 0x65
+#define UNDO 0x7A
+#define CUT 0x7B
+#define COPY 0x7C
+#define PSTE 0x7D
+
#define CURU 0xB4
#define LPRN 0xB6
@@ -141,6 +146,4 @@
#define MOD_RCTL (1 << 0x04)
#define MOD_RSFT (1 << 0x05)
#define MOD_RALT (1 << 0x06)
-#define MOD_RGUI (1 << 0x07)
-
-#define ZK_IS_CONSUMER(k) (ZK_KEY(k) >= 0x100)
+#define MOD_RGUI (1 << 0x07) \ No newline at end of file
diff --git a/app/include/zmk/kscan-mock.h b/app/include/dt-bindings/zmk/kscan-mock.h
index d481899..d481899 100644
--- a/app/include/zmk/kscan-mock.h
+++ b/app/include/dt-bindings/zmk/kscan-mock.h
diff --git a/app/include/dt-bindings/zmk/reset.h b/app/include/dt-bindings/zmk/reset.h
new file mode 100644
index 0000000..b513649
--- /dev/null
+++ b/app/include/dt-bindings/zmk/reset.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define RST_WARM 0x00
+#define RST_COLD 0x01
+
+// AdaFruit nrf52 Bootloader Specific. See https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/d6b28e66053eea467166f44875e3c7ec741cb471/src/main.c#L107
+
+#define RST_UF2 0x57 \ No newline at end of file
diff --git a/app/include/zmk/ble.h b/app/include/zmk/ble.h
index a77237d..e760ed7 100644
--- a/app/include/zmk/ble.h
+++ b/app/include/zmk/ble.h
@@ -3,5 +3,5 @@
#include <zmk/keys.h>
-int zmk_ble_init();
+int zmk_ble_unpair_all();
bool zmk_ble_handle_key_user(struct zmk_key_event *key_event);
diff --git a/app/include/zmk/event-manager.h b/app/include/zmk/event-manager.h
index 2ef55e9..d9a56a4 100644
--- a/app/include/zmk/event-manager.h
+++ b/app/include/zmk/event-manager.h
@@ -17,8 +17,12 @@ struct zmk_event_type
struct zmk_event_header {
const struct zmk_event_type* event;
+ u8_t last_listener_index;
};
+#define ZMK_EV_EVENT_HANDLED 1
+#define ZMK_EV_EVENT_CAPTURED 2
+
typedef int (*zmk_listener_callback_t)(const struct zmk_event_header *eh);
struct zmk_listener
{
@@ -33,7 +37,7 @@ 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); \
- const struct event_type* cast_##event_type(const struct zmk_event_header *eh); \
+ struct event_type* cast_##event_type(const struct zmk_event_header *eh); \
extern const struct zmk_event_type zmk_event_##event_type;
#define ZMK_EVENT_IMPL(event_type) \
@@ -49,8 +53,8 @@ struct zmk_event_subscription {
bool is_##event_type(const struct zmk_event_header *eh) { \
return eh->event == &zmk_event_##event_type; \
}; \
- const struct event_type* cast_##event_type(const struct zmk_event_header *eh) {\
- return (const struct event_type*)eh; \
+ struct event_type* cast_##event_type(const struct zmk_event_header *eh) {\
+ return (struct event_type*)eh; \
};
@@ -68,4 +72,17 @@ struct zmk_event_subscription {
#define ZMK_EVENT_RAISE(ev) \
zmk_event_manager_raise((struct zmk_event_header *)ev);
+#define ZMK_EVENT_RAISE_AFTER(ev, mod) \
+ zmk_event_manager_raise_after((struct zmk_event_header *)ev, &zmk_listener_##mod);
+
+
+#define ZMK_EVENT_RAISE_AT(ev, mod) \
+ zmk_event_manager_raise_at((struct zmk_event_header *)ev, &zmk_listener_##mod);
+
+#define ZMK_EVENT_RELEASE(ev) \
+ zmk_event_manager_release((struct zmk_event_header *)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);
diff --git a/app/include/zmk/keymap.h b/app/include/zmk/keymap.h
index 4a6bb37..c1f6393 100644
--- a/app/include/zmk/keymap.h
+++ b/app/include/zmk/keymap.h
@@ -1,6 +1,8 @@
#pragma once
+bool zmk_keymap_layer_active(u8_t layer);
int zmk_keymap_layer_activate(u8_t layer);
int zmk_keymap_layer_deactivate(u8_t layer);
+int zmk_keymap_layer_toggle(u8_t layer);
int zmk_keymap_position_state_changed(u32_t position, bool pressed);
diff --git a/app/prj.conf b/app/prj.conf
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/prj.conf
diff --git a/app/run-test.sh b/app/run-test.sh
new file mode 100755
index 0000000..be335c6
--- /dev/null
+++ b/app/run-test.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+#
+# Copyright (c) 2020 Peter Johanson; Cody McGinnis
+#
+# SPDX-License-Identifier: MIT
+#
+
+if [ -z "$1" ]; then
+ echo "Usage: ./run-test.sh <path to testcase>"
+ exit 1
+elif [ "$1" = "all" ]; then
+ echo "" > ./build/tests/pass-fail.log
+ find tests -name native_posix.keymap -exec dirname \{\} \; | xargs -l -P 4 ./run-test.sh
+ err=$?
+ sort -k2 ./build/tests/pass-fail.log
+ exit $err
+fi
+
+testcase="$1"
+echo "Running $testcase:"
+
+west build -d build/$testcase -b native_posix -- -DZMK_CONFIG=$testcase > /dev/null 2>&1
+if [ $? -gt 0 ]; then
+ echo "FAIL: $testcase did not build" >> ./build/tests/pass-fail.log
+else
+ ./build/$testcase/zephyr/zmk.exe | sed -e "s/.*> //" | tee build/$testcase/keycode_events_full.log | sed -n -f $testcase/events.patterns > build/$testcase/keycode_events.log
+ diff -au $testcase/keycode_events.snapshot build/$testcase/keycode_events.log
+ if [ $? -gt 0 ]; then
+ if [ -f $testcase/pending ]; then
+ echo "PEND: $testcase" >> ./build/tests/pass-fail.log
+ exit 0
+ else
+ echo "FAIL: $testcase" >> ./build/tests/pass-fail.log
+ exit 1
+ fi
+ else
+ echo "PASS: $testcase" >> ./build/tests/pass-fail.log
+ exit 0
+ fi
+fi \ No newline at end of file
diff --git a/app/src/behaviors/behavior_hold_tap.c b/app/src/behaviors/behavior_hold_tap.c
new file mode 100644
index 0000000..2c6d996
--- /dev/null
+++ b/app/src/behaviors/behavior_hold_tap.c
@@ -0,0 +1,502 @@
+/*
+ * Copyright (c) 2020 Cody McGinnis, Okke Formsma
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define DT_DRV_COMPAT zmk_behavior_hold_tap
+
+#include <device.h>
+#include <drivers/behavior.h>
+#include <logging/log.h>
+#include <zmk/behavior.h>
+
+#include <zmk/matrix.h>
+#include <zmk/endpoints.h>
+#include <zmk/event-manager.h>
+#include <zmk/events/position-state-changed.h>
+#include <zmk/events/keycode-state-changed.h>
+#include <zmk/events/modifiers-state-changed.h>
+#include <zmk/hid.h>
+
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
+#if DT_NODE_EXISTS(DT_DRV_INST(0))
+
+#define ZMK_BHV_HOLD_TAP_MAX_HELD 10
+#define ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS 40
+
+// increase if you have keyboard with more keys.
+#define ZMK_BHV_HOLD_TAP_POSITION_NOT_USED 9999
+
+
+enum flavor {
+ ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED = 0,
+ ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED = 1,
+ ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED = 2,
+};
+
+struct behavior_hold_tap_behaviors {
+ struct zmk_behavior_binding tap;
+ struct zmk_behavior_binding hold;
+};
+
+typedef k_timeout_t (*timer_func)();
+
+struct behavior_hold_tap_config {
+ timer_func tapping_term_ms;
+ struct behavior_hold_tap_behaviors *behaviors;
+ enum flavor flavor;
+};
+
+// this data is specific for each hold-tap
+struct active_hold_tap {
+ s32_t position;
+ u32_t param_hold;
+ u32_t param_tap;
+ bool is_decided;
+ bool is_hold;
+ const struct behavior_hold_tap_config *config;
+ struct k_delayed_work work;
+ bool work_is_cancelled;
+};
+
+// The undecided hold tap is the hold tap that needs to be decided before
+// other keypress events can be released. While the undecided_hold_tap is
+// not NULL, most events are captured in captured_events.
+// After the hold_tap is decided, it will stay in the active_hold_taps until
+// its key-up has been processed and the delayed work is cleaned up.
+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] = {};
+
+static int capture_event(const struct zmk_event_header *event)
+{
+ for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_CAPTURED_EVENTS; i++) {
+ if (captured_events[i] == NULL) {
+ captured_events[i] = event;
+ return 0;
+ }
+ }
+ return -ENOMEM;
+}
+
+static struct position_state_changed *find_captured_keydown_event(u32_t position)
+{
+ struct 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];
+ if (eh == NULL) {
+ return last_match;
+ }
+ if (!is_position_state_changed(eh)) {
+ continue;
+ }
+ struct position_state_changed *position_event = cast_position_state_changed(eh);
+ if (position_event->position == position && position_event->state) {
+ last_match = position_event;
+ }
+ }
+ return last_match;
+}
+
+const struct zmk_listener zmk_listener_behavior_hold_tap;
+
+static void release_captured_events()
+{
+ if (undecided_hold_tap != NULL) {
+ return;
+ }
+
+ // We use a trick to prevent copying the captured_events array.
+ //
+ // Events for different mod-tap instances are separated by a NULL pointer.
+ //
+ // The first event popped will never be catched by the next active hold-tap
+ // because to start capturing a mod-tap-key-down event must first completely
+ // go through the events queue.
+ //
+ // Example of this release process;
+ // [mt2_down, k1_down, k1_up, mt2_up, null, ...]
+ // ^
+ // mt2_down position event isn't captured because no hold-tap is active.
+ // mt2_down behavior event is handled, now we have an undecided hold-tap
+ // [null, k1_down, k1_up, mt2_up, null, ...]
+ // ^
+ // k1_down is captured by the mt2 mod-tap
+ // !note that searches for find_captured_keydown_event by the mt2 behavior will stop at the first null encountered
+ // [mt1_down, null, k1_up, mt2_up, null, ...]
+ // ^
+ // k1_up event is captured by the new hold-tap:
+ // [k1_down, k1_up, null, mt2_up, null, ...]
+ // ^
+ // mt2_up event is not captured but causes release of mt2 behavior
+ // [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];
+ if (captured_event == NULL) {
+ return;
+ }
+ captured_events[i] = NULL;
+ 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);
+ 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);
+ LOG_DBG("Releasing mods changed event 0x%02X %s", modifier_event->keycode, (modifier_event->state ? "pressed" : "released"));
+ }
+ ZMK_EVENT_RAISE_AT(captured_event, behavior_hold_tap);
+ }
+}
+
+static struct active_hold_tap *find_hold_tap(u32_t position)
+{
+ for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) {
+ if (active_hold_taps[i].position == position) {
+ return &active_hold_taps[i];
+ }
+ }
+ return NULL;
+}
+
+static struct active_hold_tap *store_hold_tap(u32_t position, u32_t param_hold, u32_t param_tap, const struct behavior_hold_tap_config *config)
+{
+ for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) {
+ if (active_hold_taps[i].position != ZMK_BHV_HOLD_TAP_POSITION_NOT_USED) {
+ continue;
+ }
+ active_hold_taps[i].position = position;
+ active_hold_taps[i].is_decided = false;
+ active_hold_taps[i].is_hold = false;
+ active_hold_taps[i].config = config;
+ active_hold_taps[i].param_hold = param_hold;
+ active_hold_taps[i].param_tap = param_tap;
+ return &active_hold_taps[i];
+ }
+ return NULL;
+}
+
+static void clear_hold_tap(struct active_hold_tap *hold_tap)
+{
+ hold_tap->position = ZMK_BHV_HOLD_TAP_POSITION_NOT_USED;
+ hold_tap->is_decided = false;
+ hold_tap->is_hold = false;
+ hold_tap->work_is_cancelled = false;
+}
+
+enum decision_moment {
+ HT_KEY_UP = 0,
+ HT_OTHER_KEY_DOWN = 1,
+ HT_OTHER_KEY_UP = 2,
+ HT_TIMER_EVENT = 3,
+};
+
+static void decide_balanced(struct active_hold_tap *hold_tap, enum decision_moment event)
+{
+ switch (event) {
+ case HT_KEY_UP:
+ hold_tap->is_hold = 0;
+ hold_tap->is_decided = true;
+ break;
+ case HT_OTHER_KEY_UP:
+ case HT_TIMER_EVENT:
+ hold_tap->is_hold = 1;
+ hold_tap->is_decided = true;
+ break;
+ default: return;
+ }
+}
+
+static void decide_tap_preferred(struct active_hold_tap *hold_tap, enum decision_moment event)
+{
+ switch (event) {
+ case HT_KEY_UP:
+ hold_tap->is_hold = 0;
+ hold_tap->is_decided = true;
+ break;
+ case HT_TIMER_EVENT:
+ hold_tap->is_hold = 1;
+ hold_tap->is_decided = true;
+ break;
+ default: return;
+ }
+}
+
+static void decide_hold_preferred(struct active_hold_tap *hold_tap, enum decision_moment event)
+{
+ switch (event) {
+ case HT_KEY_UP:
+ hold_tap->is_hold = 0;
+ hold_tap->is_decided = true;
+ break;
+ case HT_OTHER_KEY_DOWN:
+ case HT_TIMER_EVENT:
+ hold_tap->is_hold = 1;
+ hold_tap->is_decided = true;
+ break;
+ default: return;
+ }
+}
+
+static inline char* flavor_str(enum flavor flavor) {
+ switch(flavor) {
+ case ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED:
+ return "hold-preferred";
+ case ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED:
+ return "balanced";
+ case ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED:
+ return "tap-preferred";
+ }
+ return "UNKNOWN FLAVOR";
+}
+
+static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_moment event)
+{
+ if (hold_tap->is_decided) {
+ return;
+ }
+
+ if (hold_tap != undecided_hold_tap) {
+ LOG_DBG("ERROR found undecided tap hold that is not the active tap hold");
+ return;
+ }
+
+ switch(hold_tap->config->flavor) {
+ case ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED:
+ decide_hold_preferred(hold_tap, event);
+ case ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED:
+ decide_balanced(hold_tap, event);
+ case ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED:
+ decide_tap_preferred(hold_tap, event);
+ }
+
+ if (!hold_tap->is_decided) {
+ return;
+ }
+
+ LOG_DBG("%d decided %s (%s event %d)",
+ hold_tap->position,
+ hold_tap->is_hold ? "hold" : "tap",
+ flavor_str(hold_tap->config->flavor),
+ event);
+ undecided_hold_tap = NULL;
+
+ struct zmk_behavior_binding *behavior;
+ if (hold_tap->is_hold) {
+ behavior = &hold_tap->config->behaviors->hold;
+ struct device *behavior_device = device_get_binding(behavior->behavior_dev);
+ behavior_keymap_binding_pressed(behavior_device, hold_tap->position, hold_tap->param_hold, 0);
+ } else {
+ behavior = &hold_tap->config->behaviors->tap;
+ struct device *behavior_device = device_get_binding(behavior->behavior_dev);
+ behavior_keymap_binding_pressed(behavior_device, hold_tap->position, hold_tap->param_tap, 0);
+ }
+ release_captured_events();
+}
+
+static int on_hold_tap_binding_pressed(struct device *dev, u32_t position, u32_t param_hold, u32_t param_tap)
+{
+ const struct behavior_hold_tap_config *cfg = dev->config_info;
+
+ if (undecided_hold_tap != NULL) {
+ LOG_DBG("ERROR another hold-tap behavior is undecided.");
+ // if this happens, make sure the behavior events occur AFTER other position events.
+ return 0;
+ }
+
+ struct active_hold_tap *hold_tap = store_hold_tap(position, param_hold, param_tap, cfg);
+ if (hold_tap == NULL) {
+ LOG_ERR("unable to store hold-tap info, did you press more than %d hold-taps?", ZMK_BHV_HOLD_TAP_MAX_HELD);
+ return 0;
+ }
+
+ LOG_DBG("%d new undecided hold_tap", position);
+ undecided_hold_tap = hold_tap;
+ k_delayed_work_submit(&hold_tap->work, cfg->tapping_term_ms());
+
+ // todo: once we get timing info for keypresses, start the timer relative to the original keypress
+ // don't forget to simulate a timer-event before the event after that time was handled.
+
+ return 0;
+}
+
+static int on_hold_tap_binding_released(struct device *dev, u32_t position, u32_t _, u32_t __)
+{
+ struct active_hold_tap *hold_tap = find_hold_tap(position);
+
+ if (hold_tap == NULL) {
+ LOG_ERR("ACTIVE_HOLD_TAP_CLEANED_UP_TOO_EARLY");
+ return 0;
+ }
+
+ int work_cancel_result = k_delayed_work_cancel(&hold_tap->work);
+ decide_hold_tap(hold_tap, HT_KEY_UP);
+
+ struct zmk_behavior_binding *behavior;
+ if (hold_tap->is_hold) {
+ behavior = &hold_tap->config->behaviors->hold;
+ struct device *behavior_device = device_get_binding(behavior->behavior_dev);
+ behavior_keymap_binding_released(behavior_device, hold_tap->position, hold_tap->param_hold, 0);
+ } else {
+ behavior = &hold_tap->config->behaviors->tap;
+ struct device *behavior_device = device_get_binding(behavior->behavior_dev);
+ behavior_keymap_binding_released(behavior_device, hold_tap->position, hold_tap->param_tap, 0);
+ }
+
+
+ if (work_cancel_result == -EINPROGRESS) {
+ // let the timer handler clean up
+ // if we'd clear now, the timer may call back for an uninitialized active_hold_tap.
+ LOG_DBG("%d hold-tap timer work in event queue", position);
+ hold_tap->work_is_cancelled = true;
+ } else {
+ LOG_DBG("%d cleaning up hold-tap", position);
+ clear_hold_tap(hold_tap);
+ }
+
+ return 0;
+}
+
+static const struct behavior_driver_api behavior_hold_tap_driver_api = {
+ .binding_pressed = on_hold_tap_binding_pressed,
+ .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);
+
+ if (undecided_hold_tap == NULL) {
+ LOG_DBG("%d bubble (no undecided hold_tap active)", ev->position);
+ return 0;
+ }
+
+ if (undecided_hold_tap->position == ev->position) {
+ if (ev->state) { // keydown
+ LOG_ERR("hold-tap listener should be called before before most other listeners!");
+ return 0;
+ } else { // keyup
+ LOG_DBG("%d bubble undecided hold-tap keyrelease event", undecided_hold_tap->position);
+ return 0;
+ }
+ }
+
+ if (!ev->state && find_captured_keydown_event(ev->position) == NULL) {
+ // no keydown event has been captured, let it bubble.
+ // we'll catch modifiers later in modifier_state_changed_listener
+ LOG_DBG("%d bubbling %d %s event", undecided_hold_tap->position, ev->position, ev->state ? "down" : "up");
+ return 0;
+ }
+
+ LOG_DBG("%d capturing %d %s event", undecided_hold_tap->position, ev->position, ev->state ? "down" : "up");
+ capture_event(eh);
+ decide_hold_tap(undecided_hold_tap, ev->state ? HT_OTHER_KEY_DOWN : HT_OTHER_KEY_UP);
+ return ZMK_EV_EVENT_CAPTURED;
+}
+
+static bool is_mod(struct keycode_state_changed *ev)
+{
+ return ev->usage_page == USAGE_KEYPAD && ev->keycode >= LCTL && ev->keycode <= RGUI;
+}
+
+static int keycode_state_changed_listener(const struct zmk_event_header *eh)
+{
+ // we want to catch layer-up events too... how?
+ struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
+
+ if (undecided_hold_tap == NULL) {
+ // LOG_DBG("0x%02X bubble (no undecided hold_tap active)", ev->keycode);
+ return 0;
+ }
+
+ if (!is_mod(ev)) {
+ // LOG_DBG("0x%02X bubble (not a mod)", ev->keycode);
+ return 0;
+ }
+
+ // only key-up events will bubble through position_state_changed_listener
+ // if a undecided_hold_tap is active.
+ LOG_DBG("%d capturing 0x%02X %s event", undecided_hold_tap->position, ev->keycode, ev->state ? "down" : "up");
+ capture_event(eh);
+ return ZMK_EV_EVENT_CAPTURED;
+}
+
+
+int behavior_hold_tap_listener(const struct zmk_event_header *eh)
+{
+ if (is_position_state_changed(eh)) {
+ return position_state_changed_listener(eh);
+ } else if (is_keycode_state_changed(eh)) {
+ return keycode_state_changed_listener(eh);
+ }
+ return 0;
+}
+
+ZMK_LISTENER(behavior_hold_tap, behavior_hold_tap_listener);
+ZMK_SUBSCRIPTION(behavior_hold_tap, position_state_changed);
+// this should be modifiers_state_changed, but unfrotunately that's not implemented yet.
+ZMK_SUBSCRIPTION(behavior_hold_tap, 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);
+
+ if (hold_tap->work_is_cancelled) {
+ clear_hold_tap(hold_tap);
+ } else {
+ decide_hold_tap(hold_tap, HT_TIMER_EVENT);
+ }
+}
+
+static int behavior_hold_tap_init(struct device *dev)
+{
+ static bool init_first_run = true;
+
+ if (init_first_run) {
+ for (int i = 0; i < ZMK_BHV_HOLD_TAP_MAX_HELD; i++) {
+ k_delayed_work_init(&active_hold_taps[i].work, behavior_hold_tap_timer_work_handler);
+ active_hold_taps[i].position = ZMK_BHV_HOLD_TAP_POSITION_NOT_USED;
+ }
+ }
+ init_first_run = false;
+ return 0;
+}
+
+struct behavior_hold_tap_data {};
+static struct behavior_hold_tap_data behavior_hold_tap_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 k_timeout_t behavior_hold_tap_config_##n##_gettime() { return K_MSEC(DT_INST_PROP(n, tapping_term_ms)); } \
+ 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 = &behavior_hold_tap_config_##n##_gettime, \
+ .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, \
+ &behavior_hold_tap_data, \
+ &behavior_hold_tap_config_##n, \
+ APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
+ &behavior_hold_tap_driver_api);
+
+DT_INST_FOREACH_STATUS_OKAY(KP_INST)
+
+
+#endif \ No newline at end of file
diff --git a/app/src/behaviors/behavior_key_press.c b/app/src/behaviors/behavior_key_press.c
index 34df1c0..7404c79 100644
--- a/app/src/behaviors/behavior_key_press.c
+++ b/app/src/behaviors/behavior_key_press.c
@@ -28,27 +28,17 @@ static int behavior_key_press_init(struct device *dev)
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t keycode, u32_t _)
{
const struct behavior_key_press_config *cfg = dev->config_info;
- struct keycode_state_changed *ev;
LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode);
- ev = new_keycode_state_changed();
- ev->usage_page = cfg->usage_page;
- ev->keycode = keycode;
- ev->state = true;
- return ZMK_EVENT_RAISE(ev);
+ return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, true));
}
static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t keycode, u32_t _)
{
const struct behavior_key_press_config *cfg = dev->config_info;
- struct keycode_state_changed *ev;
LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode);
- ev = new_keycode_state_changed();
- ev->usage_page = cfg->usage_page;
- ev->keycode = keycode;
- ev->state = false;
- return ZMK_EVENT_RAISE(ev);
+ return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, false));
}
static const struct behavior_driver_api behavior_key_press_driver_api = {
diff --git a/app/src/behaviors/behavior_mod_tap.c b/app/src/behaviors/behavior_mod_tap.c
deleted file mode 100644
index 62604eb..0000000
--- a/app/src/behaviors/behavior_mod_tap.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
- *
- * SPDX-License-Identifier: MIT
- */
-
-#define DT_DRV_COMPAT zmk_behavior_mod_tap
-
-#include <device.h>
-#include <drivers/behavior.h>
-#include <logging/log.h>
-
-#include <zmk/event-manager.h>
-#include <zmk/events/keycode-state-changed.h>
-#include <zmk/events/modifiers-state-changed.h>
-
-LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
-
-struct behavior_mod_tap_config { };
-struct behavior_mod_tap_data {
- u16_t pending_press_positions;
-};
-
-int behavior_mod_tap_listener(const struct zmk_event_header *eh)
-{
- if (is_keycode_state_changed(eh)) {
- struct device *dev = device_get_binding(DT_INST_LABEL(0));
- const struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
- if (ev->state) {
- struct behavior_mod_tap_data *data = dev->driver_data;
- data->pending_press_positions = 0;
- }
- }
- return 0;
-}
-
-ZMK_LISTENER(behavior_mod_tap, behavior_mod_tap_listener);
-ZMK_SUBSCRIPTION(behavior_mod_tap, keycode_state_changed);
-
-static int behavior_mod_tap_init(struct device *dev)
-{
- return 0;
-};
-
-
-static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t mods, u32_t keycode)
-{
- struct behavior_mod_tap_data *data = dev->driver_data;
- LOG_DBG("mods: %d, keycode: %d", mods, keycode);
- WRITE_BIT(data->pending_press_positions, position, true);
- return ZMK_EVENT_RAISE(create_modifiers_state_changed(mods, true));
-}
-
-static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t mods, u32_t keycode)
-{
- struct behavior_mod_tap_data *data = dev->driver_data;
- LOG_DBG("mods: %d, keycode: %d", mods, keycode);
-
- ZMK_EVENT_RAISE(create_modifiers_state_changed(mods, false));
- k_msleep(10); // TODO: Better approach than k_msleep to avoid USB send failures? Retries in the USB endpoint layer?
- if (data->pending_press_positions & BIT(position)) {
- ZMK_EVENT_RAISE(create_keycode_state_changed(USAGE_KEYPAD, keycode, true));
- k_msleep(10);
- ZMK_EVENT_RAISE(create_keycode_state_changed(USAGE_KEYPAD, keycode, false));
- }
-
- return 0;
-}
-
-static const struct behavior_driver_api behavior_mod_tap_driver_api = {
- .binding_pressed = on_keymap_binding_pressed,
- .binding_released = on_keymap_binding_released,
-};
-
-static const struct behavior_mod_tap_config behavior_mod_tap_config = {};
-
-static struct behavior_mod_tap_data behavior_mod_tap_data;
-
-DEVICE_AND_API_INIT(behavior_mod_tap, DT_INST_LABEL(0), behavior_mod_tap_init,
- &behavior_mod_tap_data,
- &behavior_mod_tap_config,
- APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
- &behavior_mod_tap_driver_api);
diff --git a/app/src/behaviors/behavior_none.c b/app/src/behaviors/behavior_none.c
new file mode 100644
index 0000000..e822d5e
--- /dev/null
+++ b/app/src/behaviors/behavior_none.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define DT_DRV_COMPAT zmk_behavior_none
+
+#include <device.h>
+#include <power/reboot.h>
+#include <drivers/behavior.h>
+#include <logging/log.h>
+
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
+struct behavior_none_config { };
+struct behavior_none_data { };
+
+static int behavior_none_init(struct device *dev)
+{
+ return 0;
+};
+
+static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1, u32_t _param2)
+{
+ return 0;
+}
+
+static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1, u32_t _param2)
+{
+ return 0;
+}
+
+static const struct behavior_driver_api behavior_none_driver_api = {
+ .binding_pressed = on_keymap_binding_pressed,
+ .binding_released = on_keymap_binding_released,
+};
+
+
+static const struct behavior_none_config behavior_none_config = {};
+
+static struct behavior_none_data behavior_none_data;
+
+DEVICE_AND_API_INIT(behavior_none, DT_INST_LABEL(0), behavior_none_init,
+ &behavior_none_data,
+ &behavior_none_config,
+ APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
+ &behavior_none_driver_api); \ No newline at end of file
diff --git a/app/src/behaviors/behavior_reset.c b/app/src/behaviors/behavior_reset.c
index 44cbc21..30a96ea 100644
--- a/app/src/behaviors/behavior_reset.c
+++ b/app/src/behaviors/behavior_reset.c
@@ -13,8 +13,9 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
-struct behavior_reset_config { };
-struct behavior_reset_data { };
+struct behavior_reset_config {
+ int type;
+};
static int behavior_reset_init(struct device *dev)
{
@@ -23,9 +24,11 @@ static int behavior_reset_init(struct device *dev)
static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1, u32_t _param2)
{
+ const struct behavior_reset_config *cfg = dev->config_info;
+
// TODO: Correct magic code for going into DFU?
// See https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/d6b28e66053eea467166f44875e3c7ec741cb471/src/main.c#L107
- sys_reboot(0);
+ sys_reboot(cfg->type);
return 0;
}
@@ -34,12 +37,14 @@ static const struct behavior_driver_api behavior_reset_driver_api = {
};
-static const struct behavior_reset_config behavior_reset_config = {};
-
-static struct behavior_reset_data behavior_reset_data;
-
-DEVICE_AND_API_INIT(behavior_reset, DT_INST_LABEL(0), behavior_reset_init,
- &behavior_reset_data,
- &behavior_reset_config,
- APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
- &behavior_reset_driver_api); \ No newline at end of file
+#define RST_INST(n) \
+ static const struct behavior_reset_config behavior_reset_config_##n = { \
+ .type = DT_INST_PROP(n, type) \
+ }; \
+ DEVICE_AND_API_INIT(behavior_reset_##n, DT_INST_LABEL(n), behavior_reset_init, \
+ NULL, \
+ &behavior_reset_config_##n, \
+ APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
+ &behavior_reset_driver_api);
+
+DT_INST_FOREACH_STATUS_OKAY(RST_INST) \ No newline at end of file
diff --git a/app/src/behaviors/behavior_toggle_layer.c b/app/src/behaviors/behavior_toggle_layer.c
new file mode 100644
index 0000000..02a76d2
--- /dev/null
+++ b/app/src/behaviors/behavior_toggle_layer.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2020 Cody McGinnis <brainwart@gmail.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define DT_DRV_COMPAT zmk_behavior_toggle_layer
+
+#include <device.h>
+#include <drivers/behavior.h>
+#include <logging/log.h>
+
+#include <zmk/keymap.h>
+
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
+struct behavior_tog_config
+{
+};
+struct behavior_tog_data
+{
+};
+
+static int behavior_tog_init(struct device *dev)
+{
+ return 0;
+};
+
+static int tog_keymap_binding_pressed(struct device *dev, u32_t position, u32_t layer, u32_t _)
+{
+ LOG_DBG("position %d layer %d", position, layer);
+
+ return zmk_keymap_layer_toggle(layer);
+}
+
+static int tog_keymap_binding_released(struct device *dev, u32_t position, u32_t layer, u32_t _)
+{
+ LOG_DBG("position %d layer %d", position, layer);
+
+ return 0;
+}
+
+static const struct behavior_driver_api behavior_tog_driver_api = {
+ .binding_pressed = tog_keymap_binding_pressed,
+ .binding_released = tog_keymap_binding_released,
+};
+
+static const struct behavior_tog_config behavior_tog_config = {};
+
+static struct behavior_tog_data behavior_tog_data;
+
+DEVICE_AND_API_INIT(behavior_tog, DT_INST_LABEL(0), behavior_tog_init,
+ &behavior_tog_data,
+ &behavior_tog_config,
+ APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
+ &behavior_tog_driver_api);
diff --git a/app/src/ble.c b/app/src/ble.c
index 559b04f..0e96d16 100644
--- a/app/src/ble.c
+++ b/app/src/ble.c
@@ -1,3 +1,8 @@
+/*
+ * Copyright (c) 2020 Peter Johanson
+ *
+ * SPDX-License-Identifier: MIT
+ */
#include <device.h>
#include <init.h>
@@ -23,6 +28,16 @@ static struct bt_conn *auth_passkey_entry_conn;
static u8_t passkey_entries[6] = {0, 0, 0, 0, 0, 0};
static u8_t passkey_digit = 0;
+#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
+#define ZMK_ADV_PARAMS BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | \
+ BT_LE_ADV_OPT_USE_NAME | \
+ BT_LE_ADV_OPT_ONE_TIME, \
+ BT_GAP_ADV_FAST_INT_MIN_2, \
+ BT_GAP_ADV_FAST_INT_MAX_2, NULL)
+#else
+#define ZMK_ADV_PARAMS BT_LE_ADV_CONN_NAME
+#endif
+
static void connected(struct bt_conn *conn, u8_t err)
{
char addr[BT_ADDR_LE_STR_LEN];
@@ -31,17 +46,21 @@ static void connected(struct bt_conn *conn, u8_t err)
if (err)
{
- printk("Failed to connect to %s (%u)\n", addr, err);
+ LOG_WRN("Failed to connect to %s (%u)", log_strdup(addr), err);
return;
}
- printk("Connected %s\n", addr);
+ LOG_DBG("Connected %s", log_strdup(addr));
- bt_conn_le_param_update(conn, BT_LE_CONN_PARAM(0x0006, 0x000c, 5, 400));
+ bt_conn_le_param_update(conn, BT_LE_CONN_PARAM(0x0006, 0x000c, 30, 400));
+
+#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
+ bt_conn_le_phy_update(conn, BT_CONN_LE_PHY_PARAM_2M);
+#endif
if (bt_conn_set_security(conn, BT_SECURITY_L2))
{
- printk("Failed to set security\n");
+ LOG_ERR("Failed to set security");
}
}
@@ -51,7 +70,7 @@ static void disconnected(struct bt_conn *conn, u8_t reason)
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
- printk("Disconnected from %s (reason 0x%02x)\n", addr, reason);
+ LOG_DBG("Disconnected from %s (reason 0x%02x)", log_strdup(addr), reason);
}
static void security_changed(struct bt_conn *conn, bt_security_t level,
@@ -63,11 +82,11 @@ static void security_changed(struct bt_conn *conn, bt_security_t level,
if (!err)
{
- printk("Security changed: %s level %u\n", addr, level);
+ LOG_DBG("Security changed: %s level %u", log_strdup(addr), level);
}
else
{
- printk("Security failed: %s level %u err %d\n", addr, level,
+ LOG_ERR("Security failed: %s level %u err %d", log_strdup(addr), level,
err);
}
}
@@ -84,7 +103,7 @@ static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
- printk("Passkey for %s: %06u\n", addr, passkey);
+ LOG_DBG("Passkey for %s: %06u", log_strdup(addr), passkey);
}
#ifdef CONFIG_ZMK_BLE_PASSKEY_ENTRY
@@ -95,7 +114,7 @@ static void auth_passkey_entry(struct bt_conn *conn)
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
- printk("Passkey entry requested for %s\n", addr);
+ LOG_DBG("Passkey entry requested for %s", log_strdup(addr));
auth_passkey_entry_conn = bt_conn_ref(conn);
}
@@ -115,7 +134,7 @@ static void auth_cancel(struct bt_conn *conn)
passkey_digit = 0;
- printk("Pairing cancelled: %s\n", addr);
+ LOG_DBG("Pairing cancelled: %s", log_strdup(addr));
}
static struct bt_conn_auth_cb zmk_ble_auth_cb_display = {
@@ -146,14 +165,14 @@ static void zmk_ble_ready(int err)
LOG_DBG("ready? %d", err);
if (err)
{
- printk("Bluetooth init failed (err %d)\n", err);
+ LOG_ERR("Bluetooth init failed (err %d)", err);
return;
}
- err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0);
+ err = bt_le_adv_start(ZMK_ADV_PARAMS, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0);
if (err)
{
- printk("Advertising failed to start (err %d)\n", err);
+ LOG_ERR("Advertising failed to start (err %d)", err);
return;
}
}
@@ -164,7 +183,7 @@ static int zmk_ble_init(struct device *_arg)
if (err)
{
- printk("BLUETOOTH FAILED");
+ LOG_ERR("BLUETOOTH FAILED (%d)", err);
return err;
}
@@ -181,6 +200,12 @@ static int zmk_ble_init(struct device *_arg)
return 0;
}
+int zmk_ble_unpair_all()
+{
+ LOG_DBG("");
+ return bt_unpair(BT_ID_DEFAULT, NULL);
+};
+
bool zmk_ble_handle_key_user(struct zmk_key_event *key_event)
{
zmk_key key = key_event->key;
diff --git a/app/src/ble_unpair_combo.c b/app/src/ble_unpair_combo.c
new file mode 100644
index 0000000..82fa834
--- /dev/null
+++ b/app/src/ble_unpair_combo.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2020 Peter Johanson
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <device.h>
+#include <init.h>
+
+#define DT_DRV_COMPAT zmk_bt_unpair_combo
+
+#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
+#include <zmk/ble.h>
+#include <zmk/event-manager.h>
+#include <zmk/events/position-state-changed.h>
+
+
+static u8_t combo_state;
+
+const u32_t key_positions[] = DT_INST_PROP(0, key_positions);
+#define KP_LEN DT_INST_PROP_LEN(0, key_positions)
+
+int index_for_key_position(u32_t kp)
+{
+ for (int i = 0; i < KP_LEN; i++) {
+ if (key_positions[i] == kp) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+int unpair_combo_listener(const struct zmk_event_header *eh)
+{
+ if (is_position_state_changed(eh)) {
+ const struct position_state_changed *psc = cast_position_state_changed(eh);
+
+ int kp_index = index_for_key_position(psc->position);
+ if (kp_index < 0) {
+ return 0;
+ }
+
+ WRITE_BIT(combo_state, kp_index, psc->state);
+ }
+
+ return 0;
+};
+
+void unpair_combo_work_handler(struct k_work *work)
+{
+ for (int i = 0; i < KP_LEN; i++) {
+ if (!(combo_state & BIT(i))) {
+ LOG_DBG("Key position %d not held, skipping unpair combo", key_positions[i]);
+ return;
+ }
+ }
+
+ zmk_ble_unpair_all();
+};
+
+struct k_delayed_work unpair_combo_work;
+
+int zmk_ble_unpair_combo_init(struct device *_unused)
+{
+ k_delayed_work_init(&unpair_combo_work, unpair_combo_work_handler);
+ k_delayed_work_submit(&unpair_combo_work, K_SECONDS(2));
+
+ return 0;
+};
+
+ZMK_LISTENER(zmk_ble_unpair_combo, unpair_combo_listener);
+ZMK_SUBSCRIPTION(zmk_ble_unpair_combo, position_state_changed);
+
+SYS_INIT(zmk_ble_unpair_combo_init,
+ APPLICATION,
+ CONFIG_APPLICATION_INIT_PRIORITY);
+
+#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */
diff --git a/app/src/event_manager.c b/app/src/event_manager.c
index 567cdf0..47ad6b7 100644
--- a/app/src/event_manager.c
+++ b/app/src/event_manager.c
@@ -17,16 +17,30 @@ 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_raise(struct zmk_event_header *event)
+
+int zmk_event_manager_handle_from(struct zmk_event_header *event, u8_t start_index)
{
- int ret;
- struct zmk_event_subscription *ev_sub;
- for (ev_sub = __event_subscriptions_start; ev_sub != __event_subscriptions_end; ev_sub++) {
+ int ret = 0;
+ u8_t len = __event_subscriptions_end - __event_subscriptions_start;
+ for (int i = start_index; i < len; i++) {
+ struct zmk_event_subscription *ev_sub = __event_subscriptions_start + i;
if (ev_sub->event_type == event->event) {
ret = ev_sub->listener->callback(event);
- if (ret) {
+ if (ret < 0) {
LOG_DBG("Listener returned an error: %d", ret);
goto release;
+ } else if (ret > 0) {
+ switch (ret) {
+ case ZMK_EV_EVENT_HANDLED:
+ LOG_DBG("Listener handled the event");
+ ret = 0;
+ goto release;
+ case ZMK_EV_EVENT_CAPTURED:
+ LOG_DBG("Listener captured the event");
+ event->last_listener_index = i;
+ // Listeners are expected to free events they capture
+ return 0;
+ }
}
}
}
@@ -34,4 +48,46 @@ int zmk_event_manager_raise(struct zmk_event_header *event)
release:
k_free(event);
return ret;
-} \ No newline at end of file
+}
+
+int zmk_event_manager_raise(struct zmk_event_header *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)
+{
+ u8_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;
+
+ if (ev_sub->event_type == event->event && ev_sub->listener == listener) {
+ return zmk_event_manager_handle_from(event, i+1);
+ }
+ }
+
+ LOG_WRN("Unable to find where to raise this after event");
+
+ return -EINVAL;
+}
+
+int zmk_event_manager_raise_at(struct zmk_event_header *event, const struct zmk_listener *listener)
+{
+ u8_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;
+
+ if (ev_sub->event_type == event->event && ev_sub->listener == listener) {
+ return zmk_event_manager_handle_from(event, i);
+ }
+ }
+
+ LOG_WRN("Unable to find where to raise this event");
+
+ return -EINVAL;
+}
+
+int zmk_event_manager_release(struct zmk_event_header *event)
+{
+ return zmk_event_manager_handle_from(event, event->last_listener_index + 1);
+}
diff --git a/app/src/events/keycode_state_changed.c b/app/src/events/keycode_state_changed.c
index 964b24a..73508e1 100644
--- a/app/src/events/keycode_state_changed.c
+++ b/app/src/events/keycode_state_changed.c
@@ -7,4 +7,4 @@
#include <kernel.h>
#include <zmk/events/keycode-state-changed.h>
-ZMK_EVENT_IMPL(keycode_state_changed); \ No newline at end of file
+ZMK_EVENT_IMPL(keycode_state_changed);
diff --git a/app/src/keymap.c b/app/src/keymap.c
index 24e249d..57cdad6 100644
--- a/app/src/keymap.c
+++ b/app/src/keymap.c
@@ -17,96 +17,53 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
static u32_t zmk_keymap_layer_state = 0;
static u8_t zmk_keymap_layer_default = 0;
-#define ZMK_KEYMAP_NODE DT_CHOSEN(zmk_keymap)
-#define ZMK_KEYMAP_LAYERS_LEN DT_PROP_LEN(ZMK_KEYMAP_NODE, layers)
+#define DT_DRV_COMPAT zmk_keymap
+
+#define LAYER_CHILD_LEN(node) 1+
+#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 _TRANSFORM_ENTRY(idx, layer) \
- { .behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, layer), bindings, idx)), \
- .param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(LAYER_NODE(layer), bindings, idx, param1), (0), (DT_PHA_BY_IDX(LAYER_NODE(layer), bindings, idx, param1))), \
- .param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(LAYER_NODE(layer), bindings, idx, param2), (0), (DT_PHA_BY_IDX(LAYER_NODE(layer), bindings, idx, param2))), \
+ { .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(idx) \
- { UTIL_LISTIFY(DT_PROP_LEN(DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, idx), bindings), _TRANSFORM_ENTRY, idx) }
+#define TRANSFORMED_LAYER(node) \
+ { UTIL_LISTIFY(DT_PROP_LEN(node, bindings), _TRANSFORM_ENTRY, node) },
-static struct zmk_behavior_binding zmk_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_KEYMAP_LEN] = {
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 0)
- TRANSFORMED_LAYER(0),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 1)
- TRANSFORMED_LAYER(1),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 2)
- TRANSFORMED_LAYER(2),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 3)
- TRANSFORMED_LAYER(3),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 4)
- TRANSFORMED_LAYER(4),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 5)
- TRANSFORMED_LAYER(5),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 6)
- TRANSFORMED_LAYER(6),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 7)
- TRANSFORMED_LAYER(7),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 8)
- TRANSFORMED_LAYER(8),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 9)
- TRANSFORMED_LAYER(9),
-#endif
-};
#if ZMK_KEYMAP_HAS_SENSORS
#define _TRANSFORM_SENSOR_ENTRY(idx, layer) \
- { .behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, layer), sensor_bindings, idx)), \
- .param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(LAYER_NODE(layer), sensor_bindings, idx, param1), (0), (DT_PHA_BY_IDX(LAYER_NODE(layer), sensor_bindings, idx, param1))), \
- .param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(LAYER_NODE(layer), sensor_bindings, idx, param2), (0), (DT_PHA_BY_IDX(LAYER_NODE(layer), sensor_bindings, idx, param2))), \
+ { .behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(layer, sensor_bindings, idx)), \
+ .param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(layer, sensor_bindings, idx, param1), (0), (DT_PHA_BY_IDX(layer, sensor_bindings, idx, param1))), \
+ .param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(layer, sensor_bindings, idx, param2), (0), (DT_PHA_BY_IDX(layer, sensor_bindings, idx, param2))), \
},
-#define SENSOR_LAYER(idx) \
- COND_CODE_1(DT_NODE_HAS_PROP(DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, idx), sensor_bindings), \
- ({ UTIL_LISTIFY(DT_PROP_LEN(DT_PHANDLE_BY_IDX(ZMK_KEYMAP_NODE, layers, idx), sensor_bindings), _TRANSFORM_SENSOR_ENTRY, idx) }), \
- (NULL))
+#define SENSOR_LAYER(node) \
+ COND_CODE_1(DT_NODE_HAS_PROP(node, sensor_bindings), \
+ ({ UTIL_LISTIFY(DT_PROP_LEN(node, sensor_bindings), _TRANSFORM_SENSOR_ENTRY, node) }), \
+ ({})),
+
+#endif /* ZMK_KEYMAP_HAS_SENSORS */
+
+// State
+
+// When a behavior handles a key position "down" event, we record the layer state
+// here so that even if that layer is deactivated before the "up", event, we
+// still send the release event to the behavior in that layer also.
+static u32_t zmk_keymap_active_behavior_layer[ZMK_KEYMAP_LEN];
+
+static struct zmk_behavior_binding zmk_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_KEYMAP_LEN] = {
+ DT_INST_FOREACH_CHILD(0, TRANSFORMED_LAYER)
+};
+
+#if ZMK_KEYMAP_HAS_SENSORS
static struct zmk_behavior_binding zmk_sensor_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_KEYMAP_SENSORS_LEN] = {
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 0)
- SENSOR_LAYER(0),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 1)
- SENSOR_LAYER(1),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 2)
- SENSOR_LAYER(2),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 3)
- SENSOR_LAYER(3),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 4)
- SENSOR_LAYER(4),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 5)
- SENSOR_LAYER(5),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 6)
- SENSOR_LAYER(6),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 7)
- SENSOR_LAYER(7),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 8)
- SENSOR_LAYER(8),
-#endif
-#if DT_PROP_HAS_IDX(ZMK_KEYMAP_NODE, layers, 9)
- SENSOR_LAYER(9),
-#endif
+ DT_INST_FOREACH_CHILD(0, SENSOR_LAYER)
};
#endif /* ZMK_KEYMAP_HAS_SENSORS */
@@ -119,6 +76,11 @@ static struct zmk_behavior_binding zmk_sensor_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_
WRITE_BIT(zmk_keymap_layer_state, layer, state); \
return 0;
+bool zmk_keymap_layer_active(u8_t layer)
+{
+ return (zmk_keymap_layer_state & (BIT(layer))) == (BIT(layer));
+};
+
int zmk_keymap_layer_activate(u8_t layer)
{
SET_LAYER_STATE(layer, true);
@@ -129,30 +91,53 @@ int zmk_keymap_layer_deactivate(u8_t layer)
SET_LAYER_STATE(layer, false);
};
-int zmk_keymap_position_state_changed(u32_t position, bool pressed)
+int zmk_keymap_layer_toggle(u8_t layer)
{
- for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= zmk_keymap_layer_default; layer--)
+ if (zmk_keymap_layer_active(layer))
{
- if ((zmk_keymap_layer_state & BIT(layer)) == BIT(layer) || layer == zmk_keymap_layer_default)
- {
- struct zmk_behavior_binding *binding = &zmk_keymap[layer][position];
- struct device *behavior;
- int ret;
+ return zmk_keymap_layer_deactivate(layer);
+ }
+
+ return zmk_keymap_layer_activate(layer);
+};
- LOG_DBG("layer: %d position: %d, binding name: %s", layer, position, log_strdup(binding->behavior_dev));
+bool is_active_layer(u8_t layer, u32_t layer_state)
+{
+ return (layer_state & BIT(layer)) == BIT(layer)
+ || layer == zmk_keymap_layer_default;
+}
- behavior = device_get_binding(binding->behavior_dev);
+int zmk_keymap_apply_position_state(int layer, u32_t position, bool pressed)
+{
+ struct zmk_behavior_binding *binding = &zmk_keymap[layer][position];
+ struct device *behavior;
- if (!behavior) {
- LOG_DBG("No behavior assigned to %d on layer %d", position, layer);
- continue;
- }
- if (pressed) {
- ret = behavior_keymap_binding_pressed(behavior, position, binding->param1, binding->param2);
- } else {
- ret = behavior_keymap_binding_released(behavior, position, binding->param1, binding->param2);
- }
+ LOG_DBG("layer: %d position: %d, binding name: %s", layer, position, log_strdup(binding->behavior_dev));
+
+ behavior = device_get_binding(binding->behavior_dev);
+
+ if (!behavior) {
+ LOG_DBG("No behavior assigned to %d on layer %d", position, layer);
+ return 1;
+ }
+
+ if (pressed) {
+ return behavior_keymap_binding_pressed(behavior, position, binding->param1, binding->param2);
+ } else {
+ return behavior_keymap_binding_released(behavior, position, binding->param1, binding->param2);
+ }
+}
+int zmk_keymap_position_state_changed(u32_t position, bool pressed)
+{
+ for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= zmk_keymap_layer_default; layer--)
+ {
+ u32_t layer_state = pressed ? zmk_keymap_layer_state : zmk_keymap_active_behavior_layer[position];
+ if (is_active_layer(layer, layer_state))
+ {
+ int ret = zmk_keymap_apply_position_state(layer, position, pressed);
+
+ zmk_keymap_active_behavior_layer[position] = zmk_keymap_layer_state;
if (ret > 0) {
LOG_DBG("behavior processing to continue to next layer");
diff --git a/app/src/kscan_mock.c b/app/src/kscan_mock.c
index b0ba90b..d626c71 100644
--- a/app/src/kscan_mock.c
+++ b/app/src/kscan_mock.c
@@ -6,13 +6,14 @@
#define DT_DRV_COMPAT zmk_kscan_mock
+#include <stdlib.h>
#include <device.h>
#include <drivers/kscan.h>
#include <logging/log.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
-#include <zmk/kscan-mock.h>
+#include <dt-bindings/zmk/kscan-mock.h>
struct kscan_mock_data
{
@@ -50,6 +51,7 @@ static int kscan_mock_configure(struct device *dev, kscan_callback_t callback)
struct kscan_mock_config_##n \
{ \
u32_t events[DT_INST_PROP_LEN(n, events)]; \
+ bool exit_after; \
}; \
static void kscan_mock_schedule_next_event_##n(struct device *dev) \
{ \
@@ -60,6 +62,9 @@ static int kscan_mock_configure(struct device *dev, kscan_callback_t callback)
u32_t ev = cfg->events[data->event_index]; \
LOG_DBG("delaying next keypress: %d", ZMK_MOCK_MSEC(ev)); \
k_delayed_work_submit(&data->work, K_MSEC(ZMK_MOCK_MSEC(ev))); \
+ } else if (cfg->exit_after) { \
+ LOG_DBG("Exiting"); \
+ exit(0); \
} \
} \
static void kscan_mock_work_handler_##n(struct k_work *work) \
@@ -67,12 +72,13 @@ static int kscan_mock_configure(struct device *dev, kscan_callback_t callback)
struct kscan_mock_data *data = \
CONTAINER_OF(work, struct kscan_mock_data, work); \
const struct kscan_mock_config_##n *cfg = data->dev->config_info; \
- u32_t ev = cfg->events[data->event_index++]; \
+ u32_t ev = cfg->events[data->event_index]; \
LOG_DBG("ev %u row %d column %d state %d\n", ev, \
ZMK_MOCK_ROW(ev), ZMK_MOCK_COL(ev), ZMK_MOCK_IS_PRESS(ev)); \
data->callback(data->dev, \
ZMK_MOCK_ROW(ev), ZMK_MOCK_COL(ev), ZMK_MOCK_IS_PRESS(ev)); \
kscan_mock_schedule_next_event_##n(data->dev); \
+ data->event_index++; \
} \
static int kscan_mock_init_##n(struct device *dev) \
{ \
@@ -93,11 +99,12 @@ static int kscan_mock_configure(struct device *dev, kscan_callback_t callback)
}; \
static struct kscan_mock_data kscan_mock_data_##n; \
static const struct kscan_mock_config_##n kscan_mock_config_##n = { \
- .events = DT_INST_PROP(n, events)}; \
+ .events = DT_INST_PROP(n, events), \
+ .exit_after = DT_INST_PROP(n, exit_after) }; \
DEVICE_AND_API_INIT(kscan_mock_##n, DT_INST_LABEL(n), kscan_mock_init_##n, \
&kscan_mock_data_##n, \
&kscan_mock_config_##n, \
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
&mock_driver_api_##n);
-DT_INST_FOREACH_STATUS_OKAY(MOCK_INST_INIT) \ No newline at end of file
+DT_INST_FOREACH_STATUS_OKAY(MOCK_INST_INIT)
diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c
index b6d7222..237096f 100644
--- a/app/src/split/bluetooth/central.c
+++ b/app/src/split/bluetooth/central.c
@@ -149,6 +149,12 @@ static void split_central_process_connection(struct bt_conn *conn) {
return;
}
}
+
+ struct bt_conn_info info;
+
+ bt_conn_get_info(conn, &info);
+
+ LOG_DBG("New connection params: Interval: %d, Latency: %d, PHY: %d", info.le.interval, info.le.latency, info.le.phy->rx_phy);
}
static bool split_central_eir_found(struct bt_data *data, void *user_data)
@@ -199,13 +205,19 @@ static bool split_central_eir_found(struct bt_data *data, void *user_data)
LOG_DBG("Found existing connection");
split_central_process_connection(default_conn);
} else {
- param = BT_LE_CONN_PARAM(0x0006, 0x000c, 5, 400);
+ param = BT_LE_CONN_PARAM(0x0006, 0x0006, 30, 400);
err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
param, &default_conn);
if (err) {
LOG_ERR("Create conn failed (err %d)", err);
start_scan();
}
+
+ err = bt_conn_le_phy_update(default_conn, BT_CONN_LE_PHY_PARAM_2M);
+ if (err) {
+ LOG_ERR("Update phy conn failed (err %d)", err);
+ start_scan();
+ }
}
return false;
diff --git a/app/src/usb_hid.c b/app/src/usb_hid.c
index 4c6dd4b..784fc25 100644
--- a/app/src/usb_hid.c
+++ b/app/src/usb_hid.c
@@ -11,18 +11,42 @@
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
-static enum usb_dc_status_code usb_status;
+static enum usb_dc_status_code usb_status = USB_DC_UNKNOWN;
static struct device *hid_dev;
+static K_SEM_DEFINE(hid_sem, 1, 1);
+
+static void in_ready_cb(void)
+{
+ k_sem_give(&hid_sem);
+}
+
+static const struct hid_ops ops =
+{
+ .int_in_ready = in_ready_cb,
+};
+
int zmk_usb_hid_send_report(const u8_t *report, size_t len)
{
- if (usb_status == USB_DC_SUSPEND)
- {
+ switch(usb_status) {
+ case USB_DC_SUSPEND:
return usb_wakeup_request();
+ case USB_DC_ERROR:
+ case USB_DC_RESET:
+ case USB_DC_DISCONNECTED:
+ case USB_DC_UNKNOWN:
+ return -ENODEV;
+ default:
+ k_sem_take(&hid_sem, K_MSEC(30));
+ int err = hid_int_ep_write(hid_dev, report, len, NULL);
+
+ if (err) {
+ k_sem_give(&hid_sem);
+ }
+
+ return err;
}
-
- return hid_int_ep_write(hid_dev, report, len, NULL);
}
void usb_hid_status_cb(enum usb_dc_status_code status, const u8_t *params)
@@ -43,7 +67,7 @@ static int zmk_usb_hid_init(struct device *_arg)
usb_hid_register_device(hid_dev,
zmk_hid_report_desc, sizeof(zmk_hid_report_desc),
- NULL);
+ &ops);
usb_hid_init(hid_dev);
diff --git a/app/tests/hold-tap/README.md b/app/tests/hold-tap/README.md
new file mode 100644
index 0000000..0630132
--- /dev/null
+++ b/app/tests/hold-tap/README.md
@@ -0,0 +1 @@
+Refer to the pdf/open document "zmk-modtap-proposal.{pdf,odt}" in this directory for a visual representation of the numbered tests for hold-tap.
diff --git a/app/tests/hold-tap/balanced/1-dn-up/events.patterns b/app/tests/hold-tap/balanced/1-dn-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/1-dn-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ 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
new file mode 100644
index 0000000..5f6a266
--- /dev/null
+++ b/app/tests/hold-tap/balanced/1-dn-up/keycode_events.snapshot
@@ -0,0 +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
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/1-dn-up/native_posix.keymap b/app/tests/hold-tap/balanced/1-dn-up/native_posix.keymap
new file mode 100644
index 0000000..10336ef
--- /dev/null
+++ b/app/tests/hold-tap/balanced/1-dn-up/native_posix.keymap
@@ -0,0 +1,11 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/2-dn-timer-up/events.patterns b/app/tests/hold-tap/balanced/2-dn-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/2-dn-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..ddda1ae
--- /dev/null
+++ b/app/tests/hold-tap/balanced/2-dn-timer-up/keycode_events.snapshot
@@ -0,0 +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
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/2-dn-timer-up/native_posix.keymap b/app/tests/hold-tap/balanced/2-dn-timer-up/native_posix.keymap
new file mode 100644
index 0000000..aa93b86
--- /dev/null
+++ b/app/tests/hold-tap/balanced/2-dn-timer-up/native_posix.keymap
@@ -0,0 +1,11 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,500)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/events.patterns b/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..a435103
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0xe4
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided tap (balanced event 0)
+kp_pressed: usage_page 0x07 keycode 0x09
+kp_released: usage_page 0x07 keycode 0xe4
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/native_posix.keymap b/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/native_posix.keymap
new file mode 100644
index 0000000..6f08689
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3a-moddn-dn-modup-up/native_posix.keymap
@@ -0,0 +1,13 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,1,10) /*ctrl*/
+ ZMK_MOCK_PRESS(0,0,100) /*mt f-shift */
+ ZMK_MOCK_RELEASE(1,1,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/events.patterns b/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..c0da94f
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0xe4
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (balanced event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_released: usage_page 0x07 keycode 0xe4
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/native_posix.keymap b/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/native_posix.keymap
new file mode 100644
index 0000000..392d328
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3b-moddn-dn-modup-timer-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,1,10) /*ctrl*/
+ ZMK_MOCK_PRESS(0,0,50) /*mt f-shift */
+ ZMK_MOCK_RELEASE(1,1,300)
+ /*timer*/
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/events.patterns b/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..ce6e7b7
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0x07
+ht_binding_pressed: 0 new undecided hold_tap
+kp_released: usage_page 0x07 keycode 0x07
+ht_decide: 0 decided tap (balanced event 0)
+kp_pressed: usage_page 0x07 keycode 0x09
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/native_posix.keymap b/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/native_posix.keymap
new file mode 100644
index 0000000..77306cd
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3c-kcdn-dn-kcup-up/native_posix.keymap
@@ -0,0 +1,13 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,0,10) /*d*/
+ ZMK_MOCK_PRESS(0,0,100) /*mt f-shift */
+ ZMK_MOCK_RELEASE(1,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/events.patterns b/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..1ec384a
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0x07
+ht_binding_pressed: 0 new undecided hold_tap
+kp_released: usage_page 0x07 keycode 0x07
+ht_decide: 0 decided hold (balanced event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/native_posix.keymap b/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/native_posix.keymap
new file mode 100644
index 0000000..1441331
--- /dev/null
+++ b/app/tests/hold-tap/balanced/3d-kcdn-dn-kcup-timer-up/native_posix.keymap
@@ -0,0 +1,13 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,0,10) /* d */
+ ZMK_MOCK_PRESS(0,0,100) /* mt f-shift */
+ ZMK_MOCK_RELEASE(1,0,400)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/events.patterns b/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..8a1980b
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/keycode_events.snapshot
@@ -0,0 +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
+ht_binding_pressed: 1 new undecided hold_tap
+ht_decide: 1 decided tap (balanced event 0)
+kp_pressed: usage_page 0x07 keycode 0x0d
+kp_released: usage_page 0x07 keycode 0x0d
+ht_binding_released: 1 cleaning up hold-tap
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/native_posix.keymap b/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/native_posix.keymap
new file mode 100644
index 0000000..c10c6d6
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4a-dn-htdn-timer-htup-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,200)
+ ZMK_MOCK_PRESS(0,1,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(0,1,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/events.patterns b/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..b89b21d
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot
@@ -0,0 +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
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/native_posix.keymap b/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/native_posix.keymap
new file mode 100644
index 0000000..ce163f5
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4a-dn-kcdn-timer-kcup-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,200)
+ ZMK_MOCK_PRESS(1,0,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(1,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/events.patterns b/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..798e2ee
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot
@@ -0,0 +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
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/native_posix.keymap b/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/native_posix.keymap
new file mode 100644
index 0000000..7abda41
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4b-dn-kcdn-kcup-timer-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,100)
+ ZMK_MOCK_PRESS(1,0,100)
+ ZMK_MOCK_RELEASE(1,0,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/events.patterns b/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..798e2ee
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/keycode_events.snapshot
@@ -0,0 +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
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/native_posix.keymap b/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/native_posix.keymap
new file mode 100644
index 0000000..ce030af
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4c-dn-kcdn-kcup-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&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)
+ /* timer */
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/events.patterns b/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..5c9f4e3
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot
@@ -0,0 +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
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
+kp_released: usage_page 0x07 keycode 0x07
diff --git a/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/native_posix.keymap b/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/native_posix.keymap
new file mode 100644
index 0000000..5467660
--- /dev/null
+++ b/app/tests/hold-tap/balanced/4d-dn-kcdn-timer-up-kcup/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,100)
+ ZMK_MOCK_PRESS(1,0,100)
+ ZMK_MOCK_RELEASE(0,0,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(1,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/balanced/behavior_keymap.dtsi b/app/tests/hold-tap/balanced/behavior_keymap.dtsi
new file mode 100644
index 0000000..df56fb5
--- /dev/null
+++ b/app/tests/hold-tap/balanced/behavior_keymap.dtsi
@@ -0,0 +1,27 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+
+/ {
+ behaviors {
+ ht_bal: behavior_hold_tap_balanced {
+ compatible = "zmk,behavior-hold-tap";
+ label = "HOLD_TAP_BALANCED";
+ #binding-cells = <2>;
+ flavor = "balanced";
+ tapping_term_ms = <300>;
+ bindings = <&kp>, <&kp>;
+ };
+ };
+
+ keymap {
+ compatible = "zmk,keymap";
+ label ="Default keymap";
+
+ default_layer {
+ bindings = <
+ &ht_bal LSFT F &ht_bal LCTL J
+ &kp D &kp RCTL>;
+ };
+ };
+};
diff --git a/app/tests/hold-tap/hold-preferred/1-dn-up/events.patterns b/app/tests/hold-tap/hold-preferred/1-dn-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/1-dn-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..cf787d8
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/1-dn-up/keycode_events.snapshot
@@ -0,0 +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
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/1-dn-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/1-dn-up/native_posix.keymap
new file mode 100644
index 0000000..10336ef
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/1-dn-up/native_posix.keymap
@@ -0,0 +1,11 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/2-dn-timer-up/events.patterns b/app/tests/hold-tap/hold-preferred/2-dn-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/2-dn-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..03329d5
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/2-dn-timer-up/keycode_events.snapshot
@@ -0,0 +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
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/2-dn-timer-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/2-dn-timer-up/native_posix.keymap
new file mode 100644
index 0000000..aa93b86
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/2-dn-timer-up/native_posix.keymap
@@ -0,0 +1,11 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,500)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/events.patterns b/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..adf4fe2
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0xe4
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided tap (hold-preferred event 0)
+kp_pressed: usage_page 0x07 keycode 0x09
+kp_released: usage_page 0x07 keycode 0xe4
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/native_posix.keymap
new file mode 100644
index 0000000..6f08689
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3a-moddn-dn-modup-up/native_posix.keymap
@@ -0,0 +1,13 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,1,10) /*ctrl*/
+ ZMK_MOCK_PRESS(0,0,100) /*mt f-shift */
+ ZMK_MOCK_RELEASE(1,1,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/events.patterns b/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..69b64a9
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0xe4
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (hold-preferred event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_released: usage_page 0x07 keycode 0xe4
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/native_posix.keymap
new file mode 100644
index 0000000..392d328
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3b-moddn-dn-modup-timer-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,1,10) /*ctrl*/
+ ZMK_MOCK_PRESS(0,0,50) /*mt f-shift */
+ ZMK_MOCK_RELEASE(1,1,300)
+ /*timer*/
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/events.patterns b/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..b06a1d7
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0x07
+ht_binding_pressed: 0 new undecided hold_tap
+kp_released: usage_page 0x07 keycode 0x07
+ht_decide: 0 decided tap (hold-preferred event 0)
+kp_pressed: usage_page 0x07 keycode 0x09
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/native_posix.keymap
new file mode 100644
index 0000000..77306cd
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3c-kcdn-dn-kcup-up/native_posix.keymap
@@ -0,0 +1,13 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,0,10) /*d*/
+ ZMK_MOCK_PRESS(0,0,100) /*mt f-shift */
+ ZMK_MOCK_RELEASE(1,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/events.patterns b/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..bf31955
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0x07
+ht_binding_pressed: 0 new undecided hold_tap
+kp_released: usage_page 0x07 keycode 0x07
+ht_decide: 0 decided hold (hold-preferred event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/native_posix.keymap
new file mode 100644
index 0000000..1441331
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/3d-kcdn-dn-kcup-timer-up/native_posix.keymap
@@ -0,0 +1,13 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,0,10) /* d */
+ ZMK_MOCK_PRESS(0,0,100) /* mt f-shift */
+ ZMK_MOCK_RELEASE(1,0,400)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/events.patterns b/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..3ed7de0
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot
@@ -0,0 +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
+ht_binding_pressed: 1 new undecided hold_tap
+ht_decide: 1 decided tap (hold-preferred event 0)
+kp_pressed: usage_page 0x07 keycode 0x0d
+kp_released: usage_page 0x07 keycode 0x0d
+ht_binding_released: 1 cleaning up hold-tap
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/native_posix.keymap
new file mode 100644
index 0000000..c10c6d6
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4a-dn-htdn-timer-htup-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,200)
+ ZMK_MOCK_PRESS(0,1,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(0,1,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/events.patterns b/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..e0b57fd
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot
@@ -0,0 +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
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/native_posix.keymap
new file mode 100644
index 0000000..ce163f5
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4a-dn-kcdn-timer-kcup-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,200)
+ ZMK_MOCK_PRESS(1,0,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(1,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/events.patterns b/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..e0b57fd
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot
@@ -0,0 +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
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/native_posix.keymap
new file mode 100644
index 0000000..7abda41
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4b-dn-kcdn-kcup-timer-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,100)
+ ZMK_MOCK_PRESS(1,0,100)
+ ZMK_MOCK_RELEASE(1,0,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/events.patterns b/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..e0b57fd
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot
@@ -0,0 +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
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/native_posix.keymap b/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/native_posix.keymap
new file mode 100644
index 0000000..ce030af
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4c-dn-kcdn-kcup-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&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)
+ /* timer */
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/events.patterns b/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..cac579d
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot
@@ -0,0 +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
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
+kp_released: usage_page 0x07 keycode 0x07
diff --git a/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/native_posix.keymap b/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/native_posix.keymap
new file mode 100644
index 0000000..5467660
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/4d-dn-kcdn-timer-up-kcup/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,100)
+ ZMK_MOCK_PRESS(1,0,100)
+ ZMK_MOCK_RELEASE(0,0,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(1,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/hold-preferred/behavior_keymap.dtsi b/app/tests/hold-tap/hold-preferred/behavior_keymap.dtsi
new file mode 100644
index 0000000..375ffd9
--- /dev/null
+++ b/app/tests/hold-tap/hold-preferred/behavior_keymap.dtsi
@@ -0,0 +1,29 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+
+
+
+/ {
+ behaviors {
+ ht_hold: behavior_hold_hold_tap {
+ compatible = "zmk,behavior-hold-tap";
+ label = "hold_hold_tap";
+ #binding-cells = <2>;
+ flavor = "hold-preferred";
+ tapping_term_ms = <300>;
+ bindings = <&kp>, <&kp>;
+ };
+ };
+
+ keymap {
+ compatible = "zmk,keymap";
+ label ="Default keymap";
+
+ default_layer {
+ bindings = <
+ &ht_hold LSFT F &ht_hold LCTL J
+ &kp D &kp RCTL>;
+ };
+ };
+};
diff --git a/app/tests/hold-tap/tap-preferred/1-dn-up/events.patterns b/app/tests/hold-tap/tap-preferred/1-dn-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/1-dn-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..2a250fb
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/1-dn-up/keycode_events.snapshot
@@ -0,0 +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
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/1-dn-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/1-dn-up/native_posix.keymap
new file mode 100644
index 0000000..10336ef
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/1-dn-up/native_posix.keymap
@@ -0,0 +1,11 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/2-dn-timer-up/events.patterns b/app/tests/hold-tap/tap-preferred/2-dn-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/2-dn-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..4f1ee63
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/2-dn-timer-up/keycode_events.snapshot
@@ -0,0 +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
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/2-dn-timer-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/2-dn-timer-up/native_posix.keymap
new file mode 100644
index 0000000..aa93b86
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/2-dn-timer-up/native_posix.keymap
@@ -0,0 +1,11 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,500)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/events.patterns b/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..87d1406
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0xe4
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided tap (tap-preferred event 0)
+kp_pressed: usage_page 0x07 keycode 0x09
+kp_released: usage_page 0x07 keycode 0xe4
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/native_posix.keymap
new file mode 100644
index 0000000..6f08689
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3a-moddn-dn-modup-up/native_posix.keymap
@@ -0,0 +1,13 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,1,10) /*ctrl*/
+ ZMK_MOCK_PRESS(0,0,100) /*mt f-shift */
+ ZMK_MOCK_RELEASE(1,1,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/events.patterns b/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..7455d2a
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0xe4
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (tap-preferred event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_released: usage_page 0x07 keycode 0xe4
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/native_posix.keymap
new file mode 100644
index 0000000..392d328
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3b-moddn-dn-modup-timer-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,1,10) /*ctrl*/
+ ZMK_MOCK_PRESS(0,0,50) /*mt f-shift */
+ ZMK_MOCK_RELEASE(1,1,300)
+ /*timer*/
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/events.patterns b/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..3d7eaf1
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0x07
+ht_binding_pressed: 0 new undecided hold_tap
+kp_released: usage_page 0x07 keycode 0x07
+ht_decide: 0 decided tap (tap-preferred event 0)
+kp_pressed: usage_page 0x07 keycode 0x09
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/native_posix.keymap
new file mode 100644
index 0000000..77306cd
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3c-kcdn-dn-kcup-up/native_posix.keymap
@@ -0,0 +1,13 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,0,10) /*d*/
+ ZMK_MOCK_PRESS(0,0,100) /*mt f-shift */
+ ZMK_MOCK_RELEASE(1,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/events.patterns b/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..059d99c
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/keycode_events.snapshot
@@ -0,0 +1,7 @@
+kp_pressed: usage_page 0x07 keycode 0x07
+ht_binding_pressed: 0 new undecided hold_tap
+kp_released: usage_page 0x07 keycode 0x07
+ht_decide: 0 decided hold (tap-preferred event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/native_posix.keymap
new file mode 100644
index 0000000..1441331
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/3d-kcdn-dn-kcup-timer-up/native_posix.keymap
@@ -0,0 +1,13 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(1,0,10) /* d */
+ ZMK_MOCK_PRESS(0,0,100) /* mt f-shift */
+ ZMK_MOCK_RELEASE(1,0,400)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/events.patterns b/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..a8cf490
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/keycode_events.snapshot
@@ -0,0 +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
+ht_binding_pressed: 1 new undecided hold_tap
+ht_decide: 1 decided tap (tap-preferred event 0)
+kp_pressed: usage_page 0x07 keycode 0x0d
+kp_released: usage_page 0x07 keycode 0x0d
+ht_binding_released: 1 cleaning up hold-tap
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/native_posix.keymap
new file mode 100644
index 0000000..c10c6d6
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4a-dn-htdn-timer-htup-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,200)
+ ZMK_MOCK_PRESS(0,1,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(0,1,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/events.patterns b/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..92a3569
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/keycode_events.snapshot
@@ -0,0 +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
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/native_posix.keymap
new file mode 100644
index 0000000..ce163f5
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4a-dn-kcdn-timer-kcup-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,200)
+ ZMK_MOCK_PRESS(1,0,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(1,0,10)
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/events.patterns b/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..92a3569
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/keycode_events.snapshot
@@ -0,0 +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
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0xe1
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/native_posix.keymap
new file mode 100644
index 0000000..7abda41
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4b-dn-kcdn-kcup-timer-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,100)
+ ZMK_MOCK_PRESS(1,0,100)
+ ZMK_MOCK_RELEASE(1,0,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(0,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/events.patterns b/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..bc8aa8e
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/keycode_events.snapshot
@@ -0,0 +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
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
diff --git a/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/native_posix.keymap b/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/native_posix.keymap
new file mode 100644
index 0000000..ce030af
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4c-dn-kcdn-kcup-up/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&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)
+ /* timer */
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/events.patterns b/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/events.patterns
@@ -0,0 +1,4 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p
+s/.*on_hold_tap_binding/ht_binding/p
+s/.*decide_hold_tap/ht_decide/p \ No newline at end of file
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
new file mode 100644
index 0000000..b106f13
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/keycode_events.snapshot
@@ -0,0 +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
+kp_pressed: usage_page 0x07 keycode 0x07
+kp_released: usage_page 0x07 keycode 0x09
+ht_binding_released: 0 cleaning up hold-tap
+kp_released: usage_page 0x07 keycode 0x07
diff --git a/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/native_posix.keymap b/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/native_posix.keymap
new file mode 100644
index 0000000..5467660
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/4d-dn-kcdn-timer-up-kcup/native_posix.keymap
@@ -0,0 +1,14 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,100)
+ ZMK_MOCK_PRESS(1,0,100)
+ ZMK_MOCK_RELEASE(0,0,200)
+ /* timer fires */
+ ZMK_MOCK_RELEASE(1,0,10)
+ >;
+}; \ No newline at end of file
diff --git a/app/tests/hold-tap/tap-preferred/behavior_keymap.dtsi b/app/tests/hold-tap/tap-preferred/behavior_keymap.dtsi
new file mode 100644
index 0000000..e514fa6
--- /dev/null
+++ b/app/tests/hold-tap/tap-preferred/behavior_keymap.dtsi
@@ -0,0 +1,27 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+
+/ {
+ behaviors {
+ tp: behavior_tap_preferred {
+ compatible = "zmk,behavior-hold-tap";
+ label = "MOD_TAP";
+ #binding-cells = <2>;
+ flavor = "tap-preferred";
+ tapping_term_ms = <300>;
+ bindings = <&kp>, <&kp>;
+ };
+ };
+
+ keymap {
+ compatible = "zmk,keymap";
+ label ="Default keymap";
+
+ default_layer {
+ bindings = <
+ &tp LSFT F &tp LCTL J
+ &kp D &kp RCTL>;
+ };
+ };
+};
diff --git a/app/tests/hold-tap/zmk-modtap-proposal.odg b/app/tests/hold-tap/zmk-modtap-proposal.odg
new file mode 100644
index 0000000..82f8436
--- /dev/null
+++ b/app/tests/hold-tap/zmk-modtap-proposal.odg
Binary files differ
diff --git a/app/tests/hold-tap/zmk-modtap-proposal.pdf b/app/tests/hold-tap/zmk-modtap-proposal.pdf
new file mode 100644
index 0000000..33048ca
--- /dev/null
+++ b/app/tests/hold-tap/zmk-modtap-proposal.pdf
Binary files differ
diff --git a/app/tests/keypress/behavior_keymap.dtsi b/app/tests/keypress/behavior_keymap.dtsi
new file mode 100644
index 0000000..34c445c
--- /dev/null
+++ b/app/tests/keypress/behavior_keymap.dtsi
@@ -0,0 +1,28 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+ label ="Default keymap";
+
+ default_layer {
+ bindings = <
+ &kp B &mo 1
+ &kp D &kp G>;
+ };
+
+ lower_layer {
+ bindings = <
+ &cp M_NEXT &trans
+ &kp L &kp J>;
+ };
+
+ raise_layer {
+ bindings = <
+ &kp W &kp U
+ &kp X &kp M>;
+ };
+ };
+};
diff --git a/app/tests/keypress/cp-press-release/events.patterns b/app/tests/keypress/cp-press-release/events.patterns
new file mode 100644
index 0000000..833100f
--- /dev/null
+++ b/app/tests/keypress/cp-press-release/events.patterns
@@ -0,0 +1 @@
+s/.*hid_listener_keycode_//p \ No newline at end of file
diff --git a/app/tests/keypress/cp-press-release/keycode_events.snapshot b/app/tests/keypress/cp-press-release/keycode_events.snapshot
new file mode 100644
index 0000000..f1ef0ed
--- /dev/null
+++ b/app/tests/keypress/cp-press-release/keycode_events.snapshot
@@ -0,0 +1,2 @@
+pressed: usage_page 0x0c keycode 0xb5
+released: usage_page 0x0c keycode 0xb5
diff --git a/app/tests/keypress/cp-press-release/native_posix.keymap b/app/tests/keypress/cp-press-release/native_posix.keymap
new file mode 100644
index 0000000..0e86f93
--- /dev/null
+++ b/app/tests/keypress/cp-press-release/native_posix.keymap
@@ -0,0 +1,5 @@
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,1,10) ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_RELEASE(0,0,10) ZMK_MOCK_RELEASE(0,1,10)>;
+}; \ No newline at end of file
diff --git a/app/tests/keypress/kp-press-release/events.patterns b/app/tests/keypress/kp-press-release/events.patterns
new file mode 100644
index 0000000..833100f
--- /dev/null
+++ b/app/tests/keypress/kp-press-release/events.patterns
@@ -0,0 +1 @@
+s/.*hid_listener_keycode_//p \ No newline at end of file
diff --git a/app/tests/keypress/kp-press-release/keycode_events.snapshot b/app/tests/keypress/kp-press-release/keycode_events.snapshot
new file mode 100644
index 0000000..f1ef0ed
--- /dev/null
+++ b/app/tests/keypress/kp-press-release/keycode_events.snapshot
@@ -0,0 +1,2 @@
+pressed: usage_page 0x0c keycode 0xb5
+released: usage_page 0x0c keycode 0xb5
diff --git a/app/tests/keypress/kp-press-release/native_posix.keymap b/app/tests/keypress/kp-press-release/native_posix.keymap
new file mode 100644
index 0000000..7f73690
--- /dev/null
+++ b/app/tests/keypress/kp-press-release/native_posix.keymap
@@ -0,0 +1,8 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,1,10) ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_RELEASE(0,0,10) ZMK_MOCK_RELEASE(0,1,10)>;
+}; \ No newline at end of file
diff --git a/app/tests/momentary-layer/behavior_keymap.dtsi b/app/tests/momentary-layer/behavior_keymap.dtsi
new file mode 100644
index 0000000..34c445c
--- /dev/null
+++ b/app/tests/momentary-layer/behavior_keymap.dtsi
@@ -0,0 +1,28 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+ label ="Default keymap";
+
+ default_layer {
+ bindings = <
+ &kp B &mo 1
+ &kp D &kp G>;
+ };
+
+ lower_layer {
+ bindings = <
+ &cp M_NEXT &trans
+ &kp L &kp J>;
+ };
+
+ raise_layer {
+ bindings = <
+ &kp W &kp U
+ &kp X &kp M>;
+ };
+ };
+};
diff --git a/app/tests/momentary-layer/early-key-release/events.patterns b/app/tests/momentary-layer/early-key-release/events.patterns
new file mode 100644
index 0000000..bd7b488
--- /dev/null
+++ b/app/tests/momentary-layer/early-key-release/events.patterns
@@ -0,0 +1,2 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p \ No newline at end of file
diff --git a/app/tests/momentary-layer/early-key-release/keycode_events.snapshot b/app/tests/momentary-layer/early-key-release/keycode_events.snapshot
new file mode 100644
index 0000000..474eef7
--- /dev/null
+++ b/app/tests/momentary-layer/early-key-release/keycode_events.snapshot
@@ -0,0 +1,4 @@
+kp_pressed: usage_page 0x07 keycode 0x05
+mo_pressed: position 1 layer 1
+kp_released: usage_page 0x07 keycode 0x05
+mo_released: position 1 layer 1
diff --git a/app/tests/momentary-layer/early-key-release/native_posix.keymap b/app/tests/momentary-layer/early-key-release/native_posix.keymap
new file mode 100644
index 0000000..e7628c0
--- /dev/null
+++ b/app/tests/momentary-layer/early-key-release/native_posix.keymap
@@ -0,0 +1,8 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_PRESS(0,1,10) ZMK_MOCK_RELEASE(0,0,10) ZMK_MOCK_RELEASE(0,1,10)>;
+}; \ No newline at end of file
diff --git a/app/tests/momentary-layer/early-key-release/pending b/app/tests/momentary-layer/early-key-release/pending
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/tests/momentary-layer/early-key-release/pending
diff --git a/app/tests/momentary-layer/normal/events.patterns b/app/tests/momentary-layer/normal/events.patterns
new file mode 100644
index 0000000..bd7b488
--- /dev/null
+++ b/app/tests/momentary-layer/normal/events.patterns
@@ -0,0 +1,2 @@
+s/.*hid_listener_keycode/kp/p
+s/.*mo_keymap_binding/mo/p \ No newline at end of file
diff --git a/app/tests/momentary-layer/normal/keycode_events.snapshot b/app/tests/momentary-layer/normal/keycode_events.snapshot
new file mode 100644
index 0000000..9dc6101
--- /dev/null
+++ b/app/tests/momentary-layer/normal/keycode_events.snapshot
@@ -0,0 +1,4 @@
+mo_pressed: position 1 layer 1
+kp_pressed: usage_page 0x0c keycode 0xb5
+kp_released: usage_page 0x0c keycode 0xb5
+mo_released: position 1 layer 1
diff --git a/app/tests/momentary-layer/normal/native_posix.keymap b/app/tests/momentary-layer/normal/native_posix.keymap
new file mode 100644
index 0000000..7f73690
--- /dev/null
+++ b/app/tests/momentary-layer/normal/native_posix.keymap
@@ -0,0 +1,8 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,1,10) ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_RELEASE(0,0,10) ZMK_MOCK_RELEASE(0,1,10)>;
+}; \ No newline at end of file
diff --git a/app/tests/none/behavior_keymap.dtsi b/app/tests/none/behavior_keymap.dtsi
new file mode 100644
index 0000000..0a4f7cb
--- /dev/null
+++ b/app/tests/none/behavior_keymap.dtsi
@@ -0,0 +1,22 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+ label ="Default keymap";
+
+ default_layer {
+ bindings = <
+ &none &mo 1
+ &kp A &none>;
+ };
+
+ lower_layer {
+ bindings = <
+ &none &trans
+ &none &kp A>;
+ };
+ };
+};
diff --git a/app/tests/none/layered/events.patterns b/app/tests/none/layered/events.patterns
new file mode 100644
index 0000000..3c9d3f8
--- /dev/null
+++ b/app/tests/none/layered/events.patterns
@@ -0,0 +1 @@
+s/.*hid_listener_keycode/kp/p \ No newline at end of file
diff --git a/app/tests/none/layered/keycode_events.snapshot b/app/tests/none/layered/keycode_events.snapshot
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/tests/none/layered/keycode_events.snapshot
diff --git a/app/tests/none/layered/native_posix.keymap b/app/tests/none/layered/native_posix.keymap
new file mode 100644
index 0000000..59ea481
--- /dev/null
+++ b/app/tests/none/layered/native_posix.keymap
@@ -0,0 +1,8 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,1,10) ZMK_MOCK_PRESS(1,0,10) ZMK_MOCK_RELEASE(1,0,10) ZMK_MOCK_RELEASE(0,1,10)>;
+}; \ No newline at end of file
diff --git a/app/tests/none/normal/events.patterns b/app/tests/none/normal/events.patterns
new file mode 100644
index 0000000..3c9d3f8
--- /dev/null
+++ b/app/tests/none/normal/events.patterns
@@ -0,0 +1 @@
+s/.*hid_listener_keycode/kp/p \ No newline at end of file
diff --git a/app/tests/none/normal/keycode_events.snapshot b/app/tests/none/normal/keycode_events.snapshot
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/tests/none/normal/keycode_events.snapshot
diff --git a/app/tests/none/normal/native_posix.keymap b/app/tests/none/normal/native_posix.keymap
new file mode 100644
index 0000000..94d7539
--- /dev/null
+++ b/app/tests/none/normal/native_posix.keymap
@@ -0,0 +1,8 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_RELEASE(0,0,10)>;
+}; \ No newline at end of file
diff --git a/app/tests/toggle-layer/behavior_keymap.dtsi b/app/tests/toggle-layer/behavior_keymap.dtsi
new file mode 100644
index 0000000..d2b41a9
--- /dev/null
+++ b/app/tests/toggle-layer/behavior_keymap.dtsi
@@ -0,0 +1,28 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+ label ="Default keymap";
+
+ default_layer {
+ bindings = <
+ &kp B &tog 1
+ &kp D &kp G>;
+ };
+
+ lower_layer {
+ bindings = <
+ &cp M_NEXT &trans
+ &kp L &kp J>;
+ };
+
+ raise_layer {
+ bindings = <
+ &kp W &kp U
+ &kp X &kp M>;
+ };
+ };
+};
diff --git a/app/tests/toggle-layer/early-key-release/events.patterns b/app/tests/toggle-layer/early-key-release/events.patterns
new file mode 100644
index 0000000..397fef4
--- /dev/null
+++ b/app/tests/toggle-layer/early-key-release/events.patterns
@@ -0,0 +1,2 @@
+s/.*hid_listener_keycode/kp/p
+s/.*tog_keymap_binding/tog/p \ No newline at end of file
diff --git a/app/tests/toggle-layer/early-key-release/keycode_events.snapshot b/app/tests/toggle-layer/early-key-release/keycode_events.snapshot
new file mode 100644
index 0000000..3ac017c
--- /dev/null
+++ b/app/tests/toggle-layer/early-key-release/keycode_events.snapshot
@@ -0,0 +1,6 @@
+kp_pressed: usage_page 0x07 keycode 0x05
+tog_pressed: position 1 layer 1
+kp_released: usage_page 0x07 keycode 0x05
+tog_released: position 1 layer 1
+kp_pressed: usage_page 0x0c keycode 0xb5
+kp_released: usage_page 0x0c keycode 0xb5
diff --git a/app/tests/toggle-layer/early-key-release/native_posix.keymap b/app/tests/toggle-layer/early-key-release/native_posix.keymap
new file mode 100644
index 0000000..6b2b8f2
--- /dev/null
+++ b/app/tests/toggle-layer/early-key-release/native_posix.keymap
@@ -0,0 +1,9 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_PRESS(0,1,10) ZMK_MOCK_RELEASE(0,0,10) ZMK_MOCK_RELEASE(0,1,10)
+ ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_RELEASE(0,0,10)>;
+}; \ No newline at end of file
diff --git a/app/tests/toggle-layer/early-key-release/pending b/app/tests/toggle-layer/early-key-release/pending
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/tests/toggle-layer/early-key-release/pending
diff --git a/app/tests/toggle-layer/normal/events.patterns b/app/tests/toggle-layer/normal/events.patterns
new file mode 100644
index 0000000..397fef4
--- /dev/null
+++ b/app/tests/toggle-layer/normal/events.patterns
@@ -0,0 +1,2 @@
+s/.*hid_listener_keycode/kp/p
+s/.*tog_keymap_binding/tog/p \ No newline at end of file
diff --git a/app/tests/toggle-layer/normal/keycode_events.snapshot b/app/tests/toggle-layer/normal/keycode_events.snapshot
new file mode 100644
index 0000000..42174cc
--- /dev/null
+++ b/app/tests/toggle-layer/normal/keycode_events.snapshot
@@ -0,0 +1,4 @@
+tog_pressed: position 1 layer 1
+tog_released: position 1 layer 1
+kp_pressed: usage_page 0x0c keycode 0xb5
+kp_released: usage_page 0x0c keycode 0xb5
diff --git a/app/tests/toggle-layer/normal/native_posix.keymap b/app/tests/toggle-layer/normal/native_posix.keymap
new file mode 100644
index 0000000..202c105
--- /dev/null
+++ b/app/tests/toggle-layer/normal/native_posix.keymap
@@ -0,0 +1,8 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,1,10) ZMK_MOCK_RELEASE(0,1,10) ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_RELEASE(0,0,10)>;
+}; \ No newline at end of file
diff --git a/app/tests/transparent/behavior_keymap.dtsi b/app/tests/transparent/behavior_keymap.dtsi
new file mode 100644
index 0000000..d6c5e27
--- /dev/null
+++ b/app/tests/transparent/behavior_keymap.dtsi
@@ -0,0 +1,22 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+ label ="Default keymap";
+
+ default_layer {
+ bindings = <
+ &trans &mo 1
+ &kp A &none>;
+ };
+
+ lower_layer {
+ bindings = <
+ &trans &trans
+ &trans &kp A>;
+ };
+ };
+};
diff --git a/app/tests/transparent/layered/events.patterns b/app/tests/transparent/layered/events.patterns
new file mode 100644
index 0000000..3c9d3f8
--- /dev/null
+++ b/app/tests/transparent/layered/events.patterns
@@ -0,0 +1 @@
+s/.*hid_listener_keycode/kp/p \ No newline at end of file
diff --git a/app/tests/transparent/layered/keycode_events.snapshot b/app/tests/transparent/layered/keycode_events.snapshot
new file mode 100644
index 0000000..d0bd245
--- /dev/null
+++ b/app/tests/transparent/layered/keycode_events.snapshot
@@ -0,0 +1,2 @@
+kp_pressed: usage_page 0x07 keycode 0x04
+kp_released: usage_page 0x07 keycode 0x04
diff --git a/app/tests/transparent/layered/native_posix.keymap b/app/tests/transparent/layered/native_posix.keymap
new file mode 100644
index 0000000..59ea481
--- /dev/null
+++ b/app/tests/transparent/layered/native_posix.keymap
@@ -0,0 +1,8 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,1,10) ZMK_MOCK_PRESS(1,0,10) ZMK_MOCK_RELEASE(1,0,10) ZMK_MOCK_RELEASE(0,1,10)>;
+}; \ No newline at end of file
diff --git a/app/tests/transparent/normal/events.patterns b/app/tests/transparent/normal/events.patterns
new file mode 100644
index 0000000..3c9d3f8
--- /dev/null
+++ b/app/tests/transparent/normal/events.patterns
@@ -0,0 +1 @@
+s/.*hid_listener_keycode/kp/p \ No newline at end of file
diff --git a/app/tests/transparent/normal/keycode_events.snapshot b/app/tests/transparent/normal/keycode_events.snapshot
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/tests/transparent/normal/keycode_events.snapshot
diff --git a/app/tests/transparent/normal/native_posix.keymap b/app/tests/transparent/normal/native_posix.keymap
new file mode 100644
index 0000000..94d7539
--- /dev/null
+++ b/app/tests/transparent/normal/native_posix.keymap
@@ -0,0 +1,8 @@
+#include <dt-bindings/zmk/keys.h>
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/kscan-mock.h>
+#include "../behavior_keymap.dtsi"
+
+&kscan {
+ events = <ZMK_MOCK_PRESS(0,0,10) ZMK_MOCK_RELEASE(0,0,10)>;
+}; \ No newline at end of file
diff --git a/app/west.yml b/app/west.yml
index 3784d97..cba53ab 100644
--- a/app/west.yml
+++ b/app/west.yml
@@ -21,6 +21,18 @@ manifest:
- hal_microchip
- hal_nxp
- hal_openisa
+ - hal_silabs
+ - hal_xtensa
+ - hal_st
+ - hal_ti
+ - loramac-node
+ - mcuboot
+ - mcumgr
+ - net-tools
+ - segger
+ - openthread
+ - edtt
+ - trusted-firmware-m
- name: uf2
remote: microsoft
path: tools/uf2