summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/CMakeLists.txt2
-rw-r--r--app/Kconfig4
-rw-r--r--app/boards/arm/nice_nano/nice_nano.dts5
-rw-r--r--app/boards/arm/nrfmicro/nrfmicro_11.dts5
-rw-r--r--app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts5
-rw-r--r--app/boards/arm/nrfmicro/nrfmicro_13.dts5
-rw-r--r--app/boards/arm/nrfmicro/pinmux.c11
-rw-r--r--app/boards/shields/lily58/lily58.keymap11
-rw-r--r--app/boards/shields/tg4x/Kconfig.defconfig9
-rw-r--r--app/boards/shields/tg4x/Kconfig.shield5
-rw-r--r--app/boards/shields/tg4x/tg4x.keymap58
-rw-r--r--app/boards/shields/tg4x/tg4x.overlay56
-rw-r--r--app/drivers/zephyr/kscan_gpio_matrix.c25
-rw-r--r--app/dts/behaviors.dtsi3
-rw-r--r--app/dts/behaviors/ext_power.dtsi9
-rw-r--r--app/dts/bindings/behaviors/zmk,behavior-ext-power.yaml10
-rw-r--r--app/dts/bindings/behaviors/zmk,behavior-sensor-rotate-key-press.yaml2
-rw-r--r--app/dts/bindings/zmk,ext-power-generic.yaml20
-rw-r--r--app/dts/bindings/zmk,keymap-sensors.yaml5
-rw-r--r--app/include/drivers/behavior.h44
-rw-r--r--app/include/drivers/ext_power.h104
-rw-r--r--app/include/dt-bindings/zmk/bt.h2
-rw-r--r--app/include/dt-bindings/zmk/ext_power.h13
-rw-r--r--app/include/zmk/behavior.h6
-rw-r--r--app/include/zmk/ble/profile.h2
-rw-r--r--app/include/zmk/events/ble-active-profile-changed.h2
-rw-r--r--app/include/zmk/events/keycode-state-changed.h1
-rw-r--r--app/include/zmk/events/position-state-changed.h1
-rw-r--r--app/include/zmk/keymap.h2
-rw-r--r--app/src/behaviors/behavior_bt.c20
-rw-r--r--app/src/behaviors/behavior_ext_power.c57
-rw-r--r--app/src/behaviors/behavior_hold_tap.c114
-rw-r--r--app/src/behaviors/behavior_key_press.c21
-rw-r--r--app/src/behaviors/behavior_momentary_layer.c17
-rw-r--r--app/src/behaviors/behavior_none.c10
-rw-r--r--app/src/behaviors/behavior_reset.c7
-rw-r--r--app/src/behaviors/behavior_rgb_underglow.c6
-rw-r--r--app/src/behaviors/behavior_sensor_rotate_key_press.c11
-rw-r--r--app/src/behaviors/behavior_toggle_layer.c15
-rw-r--r--app/src/behaviors/behavior_transparent.c10
-rw-r--r--app/src/events/ble_active_profile_changed.c2
-rw-r--r--app/src/ext_power_generic.c91
-rw-r--r--app/src/hog.c12
-rw-r--r--app/src/keymap.c22
-rw-r--r--app/src/kscan.c1
-rw-r--r--app/src/main.c9
-rw-r--r--app/src/split/bluetooth/central.c1
-rw-r--r--app/tests/hold-tap/balanced/many-nested/events.patterns4
-rw-r--r--app/tests/hold-tap/balanced/many-nested/keycode_events.snapshot20
-rw-r--r--app/tests/hold-tap/balanced/many-nested/native_posix.keymap41
50 files changed, 755 insertions, 163 deletions
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index 3e59d75..39509ed 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -31,6 +31,7 @@ target_sources(app PRIVATE src/sensors.c)
target_sources_ifdef(CONFIG_ZMK_DISPLAY app PRIVATE src/display.c)
target_sources(app PRIVATE src/event_manager.c)
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble_unpair_combo.c)
+target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/ext_power_generic.c)
target_sources(app PRIVATE src/events/position_state_changed.c)
target_sources(app PRIVATE src/events/keycode_state_changed.c)
target_sources(app PRIVATE src/events/modifiers_state_changed.c)
@@ -45,6 +46,7 @@ if (NOT CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL)
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_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/behaviors/behavior_ext_power.c)
target_sources(app PRIVATE src/keymap.c)
endif()
target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/behaviors/behavior_rgb_underglow.c)
diff --git a/app/Kconfig b/app/Kconfig
index edf5867..fca4912 100644
--- a/app/Kconfig
+++ b/app/Kconfig
@@ -95,6 +95,10 @@ config ZMK_IDLE_SLEEP_TIMEOUT
endif
+config ZMK_EXT_POWER
+ bool "Enable support to control external power output"
+ default y
+
config ZMK_DISPLAY
bool "ZMK display support"
default n
diff --git a/app/boards/arm/nice_nano/nice_nano.dts b/app/boards/arm/nice_nano/nice_nano.dts
index 3ffb0ea..0538b1d 100644
--- a/app/boards/arm/nice_nano/nice_nano.dts
+++ b/app/boards/arm/nice_nano/nice_nano.dts
@@ -29,6 +29,11 @@
};
};
+ ext-power {
+ compatible = "zmk,ext-power-generic";
+ label = "EXT_POWER";
+ control-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
+ };
};
&gpiote {
diff --git a/app/boards/arm/nrfmicro/nrfmicro_11.dts b/app/boards/arm/nrfmicro/nrfmicro_11.dts
index 95bd8ad..87c650e 100644
--- a/app/boards/arm/nrfmicro/nrfmicro_11.dts
+++ b/app/boards/arm/nrfmicro/nrfmicro_11.dts
@@ -26,6 +26,11 @@
};
};
+ ext-power {
+ compatible = "zmk,ext-power-generic";
+ label = "EXT_POWER";
+ control-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ };
};
&gpio0 {
diff --git a/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts b/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts
index 85693a8..ea15b81 100644
--- a/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts
+++ b/app/boards/arm/nrfmicro/nrfmicro_11_flipped.dts
@@ -26,6 +26,11 @@
};
};
+ ext-power {
+ compatible = "zmk,ext-power-generic";
+ label = "EXT_POWER";
+ control-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ };
};
&gpio0 {
diff --git a/app/boards/arm/nrfmicro/nrfmicro_13.dts b/app/boards/arm/nrfmicro/nrfmicro_13.dts
index 95bd8ad..ef43946 100644
--- a/app/boards/arm/nrfmicro/nrfmicro_13.dts
+++ b/app/boards/arm/nrfmicro/nrfmicro_13.dts
@@ -26,6 +26,11 @@
};
};
+ ext-power {
+ compatible = "zmk,ext-power-generic";
+ label = "EXT_POWER";
+ control-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
+ };
};
&gpio0 {
diff --git a/app/boards/arm/nrfmicro/pinmux.c b/app/boards/arm/nrfmicro/pinmux.c
index 4e330b6..30117d0 100644
--- a/app/boards/arm/nrfmicro/pinmux.c
+++ b/app/boards/arm/nrfmicro/pinmux.c
@@ -14,25 +14,14 @@
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;
}
diff --git a/app/boards/shields/lily58/lily58.keymap b/app/boards/shields/lily58/lily58.keymap
index 997a124..d44b3fe 100644
--- a/app/boards/shields/lily58/lily58.keymap
+++ b/app/boards/shields/lily58/lily58.keymap
@@ -7,6 +7,7 @@
#include <behaviors.dtsi>
#include <dt-bindings/zmk/keys.h>
#include <dt-bindings/zmk/bt.h>
+#include <dt-bindings/zmk/ext_power.h>
/ {
keymap {
@@ -38,11 +39,11 @@
// | | | | | | | | | | | _ | + | { | } | "|" |
// | | | | | | | | | |
bindings = <
-&bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &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
+&bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &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 &ext_power EP_ON &ext_power EP_OFF &ext_power EP_TOG &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>;
diff --git a/app/boards/shields/tg4x/Kconfig.defconfig b/app/boards/shields/tg4x/Kconfig.defconfig
new file mode 100644
index 0000000..ca9fa2c
--- /dev/null
+++ b/app/boards/shields/tg4x/Kconfig.defconfig
@@ -0,0 +1,9 @@
+# Copyright (c) 2020 The ZMK Contributors
+# SPDX-License-Identifier: MIT
+
+if SHIELD_TG4X
+
+config ZMK_KEYBOARD_NAME
+ default "TG4X"
+
+endif \ No newline at end of file
diff --git a/app/boards/shields/tg4x/Kconfig.shield b/app/boards/shields/tg4x/Kconfig.shield
new file mode 100644
index 0000000..7e98b71
--- /dev/null
+++ b/app/boards/shields/tg4x/Kconfig.shield
@@ -0,0 +1,5 @@
+# Copyright (c) 2020 The ZMK Contributors
+# SPDX-License-Identifier: MIT
+
+config SHIELD_TG4X
+ def_bool $(shields_list_contains,tg4x)
diff --git a/app/boards/shields/tg4x/tg4x.keymap b/app/boards/shields/tg4x/tg4x.keymap
new file mode 100644
index 0000000..bee5c87
--- /dev/null
+++ b/app/boards/shields/tg4x/tg4x.keymap
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/keys.h>
+#include <dt-bindings/zmk/bt.h>
+
+#define DEFAULT 0
+#define LOWER 1
+#define RAISE 2
+
+/ {
+ behaviors {
+ hm: homerow_mods {
+ compatible = "zmk,behavior-hold-tap";
+ label = "homerow mods";
+ #binding-cells = <2>;
+ tapping_term_ms = <225>;
+ flavor = "tap-preferred";
+ bindings = <&kp>, <&kp>;
+ };
+ };
+};
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+
+ default_layer {
+ bindings = <
+ &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 &hm LGUI A &hm LALT S &hm LCTL D &hm LSFT F &kp G &kp H &hm RSFT J &hm RCTL K &hm RALT L &hm RGUI SCLN &kp RET
+ &kp LSFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp CMMA &kp DOT &kp FSLH &kp QUOT
+ &kp LCTL &kp LALT &kp LGUI &lt 1 BKSP &lt 2 SPC &kp LARW &kp DARW &kp UARW &kp RARW
+ >;
+ };
+ lower {
+ bindings = <
+ &kp GRAV &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 PRSC
+ &kp DEL &trans &kp VOLU &trans &trans &trans &trans &kp LARW &kp DARW &kp UARW &kp RARW &trans
+ &trans &trans &kp VOLD &trans &trans &trans &trans &trans &trans &bt BT_PRV &bt BT_NXT &bt BT_CLR
+ &bootloader &reset &trans &trans &trans &trans &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3
+ >;
+ };
+
+ raise {
+ 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 &kp PRSC
+ &kp DEL &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp MINUS &kp EQL &kp LBKT &kp RBKT &kp BSLH
+ &trans &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp TILD &kp HOME &kp PGUP &kp PGDN &kp END
+ &trans &trans &trans &trans &trans &trans &kp M_NEXT &kp M_VOLD &kp M_VOLU &kp M_PLAY
+ >;
+ };
+ };
+}; \ No newline at end of file
diff --git a/app/boards/shields/tg4x/tg4x.overlay b/app/boards/shields/tg4x/tg4x.overlay
new file mode 100644
index 0000000..10ce524
--- /dev/null
+++ b/app/boards/shields/tg4x/tg4x.overlay
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2020 The ZMK Contrbutors
+ *
+ * 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 = <8>;
+ 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(4,3) RC(4,5)
+ 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(5,3) RC(5,4)
+ RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(6,0) RC(6,1) RC(6,2) RC(6,3) RC(6,4)
+ RC(3,0) RC(3,1) RC(3,2) RC(3,4) RC(3,5) RC(7,1) RC(7,2) RC(7,3) RC(7,4)
+ >;
+ };
+
+ kscan0: kscan {
+ compatible = "zmk,kscan-gpio-matrix";
+ label = "KSCAN";
+ diode-direction = "col2row";
+
+ col-gpios
+ = <&pro_micro_d 1 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>
+ , <&pro_micro_a 2 GPIO_ACTIVE_HIGH>
+ , <&pro_micro_a 3 GPIO_ACTIVE_HIGH>
+ ;
+
+ row-gpios
+ = <&pro_micro_a 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_a 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_a 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_a 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 3 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ , <&pro_micro_d 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
+ ;
+
+ };
+
+};
+
diff --git a/app/drivers/zephyr/kscan_gpio_matrix.c b/app/drivers/zephyr/kscan_gpio_matrix.c
index a0b22e4..ec4fb39 100644
--- a/app/drivers/zephyr/kscan_gpio_matrix.c
+++ b/app/drivers/zephyr/kscan_gpio_matrix.c
@@ -181,19 +181,18 @@ static int kscan_gpio_config_interrupts(struct device **devices,
struct kscan_gpio_data_##n *data = CONTAINER_OF(work, struct kscan_gpio_data_##n, work); \
kscan_gpio_read_##n(data->dev); \
} \
- COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \
- (static void kscan_gpio_irq_callback_handler_##n( \
- struct device *dev, struct gpio_callback *cb, gpio_port_pins_t pin) { \
- struct kscan_gpio_irq_callback_##n *data = \
- CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback); \
- kscan_gpio_disable_interrupts_##n(data->dev); \
- COND_CODE_0(DT_INST_PROP(n, debounce_period), \
- ({ k_work_submit(data->work); }), ({ \
- k_delayed_work_cancel(data->work); \
- k_delayed_work_submit( \
- data->work, K_MSEC(DT_INST_PROP(n, debounce_period))); \
- })) \
- })) \
+ static void kscan_gpio_irq_callback_handler_##n(struct device *dev, struct gpio_callback *cb, \
+ gpio_port_pins_t pin) { \
+ struct kscan_gpio_irq_callback_##n *data = \
+ CONTAINER_OF(cb, struct kscan_gpio_irq_callback_##n, callback); \
+ COND_CODE_1(CONFIG_ZMK_KSCAN_MATRIX_POLLING, (), \
+ (kscan_gpio_disable_interrupts_##n(data->dev);)) \
+ COND_CODE_0(DT_INST_PROP(n, debounce_period), ({ k_work_submit(data->work); }), ({ \
+ k_delayed_work_cancel(data->work); \
+ k_delayed_work_submit(data->work, \
+ K_MSEC(DT_INST_PROP(n, debounce_period))); \
+ })) \
+ } \
\
static struct kscan_gpio_data_##n kscan_gpio_data_##n = { \
.rows = {[INST_MATRIX_ROWS(n) - 1] = NULL}, .cols = {[INST_MATRIX_COLS(n) - 1] = NULL}}; \
diff --git a/app/dts/behaviors.dtsi b/app/dts/behaviors.dtsi
index 202202b..36c918c 100644
--- a/app/dts/behaviors.dtsi
+++ b/app/dts/behaviors.dtsi
@@ -8,4 +8,5 @@
#include <behaviors/reset.dtsi>
#include <behaviors/sensor_rotate_key_press.dtsi>
#include <behaviors/rgb_underglow.dtsi>
-#include <behaviors/bluetooth.dtsi> \ No newline at end of file
+#include <behaviors/bluetooth.dtsi>
+#include <behaviors/ext_power.dtsi>
diff --git a/app/dts/behaviors/ext_power.dtsi b/app/dts/behaviors/ext_power.dtsi
new file mode 100644
index 0000000..92f0035
--- /dev/null
+++ b/app/dts/behaviors/ext_power.dtsi
@@ -0,0 +1,9 @@
+/ {
+ behaviors {
+ ext_power: behavior_ext_power {
+ compatible = "zmk,behavior-ext-power";
+ label = "EXT_POWER_BEHAVIOR";
+ #binding-cells = <1>;
+ };
+ };
+};
diff --git a/app/dts/bindings/behaviors/zmk,behavior-ext-power.yaml b/app/dts/bindings/behaviors/zmk,behavior-ext-power.yaml
new file mode 100644
index 0000000..d86c6f9
--- /dev/null
+++ b/app/dts/bindings/behaviors/zmk,behavior-ext-power.yaml
@@ -0,0 +1,10 @@
+#
+# Copyright (c) 2020, The ZMK Contributors
+# SPDX-License-Identifier: MIT
+#
+
+description: External power control Behavior
+
+compatible: "zmk,behavior-ext-power"
+
+include: one_param.yaml
diff --git a/app/dts/bindings/behaviors/zmk,behavior-sensor-rotate-key-press.yaml b/app/dts/bindings/behaviors/zmk,behavior-sensor-rotate-key-press.yaml
index bbf3537..6b33910 100644
--- a/app/dts/bindings/behaviors/zmk,behavior-sensor-rotate-key-press.yaml
+++ b/app/dts/bindings/behaviors/zmk,behavior-sensor-rotate-key-press.yaml
@@ -1,4 +1,4 @@
-# Copyright (c) 2020, Pete Johanson
+# Copyright (c) 2020, The ZMK Contributors
# SPDX-License-Identifier: MIT
description: Sensor rotate key press/release behavior
diff --git a/app/dts/bindings/zmk,ext-power-generic.yaml b/app/dts/bindings/zmk,ext-power-generic.yaml
new file mode 100644
index 0000000..5a38a09
--- /dev/null
+++ b/app/dts/bindings/zmk,ext-power-generic.yaml
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2020, The ZMK Contributors
+# SPDX-License-Identifier: MIT
+#
+
+description: |
+ Generic driver for controlling the external power output
+ by toggling the control-gpio pin status
+ (Only in supported hardware)
+
+compatible: "zmk,ext-power-generic"
+
+properties:
+ control-gpios:
+ type: phandle-array
+ required: true
+ label:
+ type: string
+ required: true
+
diff --git a/app/dts/bindings/zmk,keymap-sensors.yaml b/app/dts/bindings/zmk,keymap-sensors.yaml
index c56361d..86ae5c2 100644
--- a/app/dts/bindings/zmk,keymap-sensors.yaml
+++ b/app/dts/bindings/zmk,keymap-sensors.yaml
@@ -1,3 +1,8 @@
+#
+# Copyright (c) 2020, The ZMK Contributors
+# SPDX-License-Identifier: MIT
+#
+
description: |
Allows defining the collection of sensors bound in the keymap layers
diff --git a/app/include/drivers/behavior.h b/app/include/drivers/behavior.h
index 45b8bea..cf259b1 100644
--- a/app/include/drivers/behavior.h
+++ b/app/include/drivers/behavior.h
@@ -10,6 +10,7 @@
#include <stddef.h>
#include <device.h>
#include <zmk/keys.h>
+#include <zmk/behavior.h>
/**
* @cond INTERNAL_HIDDEN
@@ -19,10 +20,10 @@
* (Internal use only.)
*/
-typedef int (*behavior_keymap_binding_callback_t)(struct device *dev, u32_t position, u32_t param1,
- u32_t param2);
-typedef int (*behavior_sensor_keymap_binding_callback_t)(struct device *dev, struct device *sensor,
- u32_t param1, u32_t param2);
+typedef int (*behavior_keymap_binding_callback_t)(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event);
+typedef int (*behavior_sensor_keymap_binding_callback_t)(struct zmk_behavior_binding *binding,
+ struct device *sensor);
__subsystem struct behavior_driver_api {
behavior_keymap_binding_callback_t binding_pressed;
@@ -42,18 +43,19 @@ __subsystem struct behavior_driver_api {
* @retval 0 If successful.
* @retval Negative errno code if failure.
*/
-__syscall int behavior_keymap_binding_pressed(struct device *dev, u32_t position, u32_t param1,
- u32_t param2);
+__syscall int behavior_keymap_binding_pressed(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event);
-static inline int z_impl_behavior_keymap_binding_pressed(struct device *dev, u32_t position,
- u32_t param1, u32_t param2) {
+static inline int z_impl_behavior_keymap_binding_pressed(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
+ struct device *dev = device_get_binding(binding->behavior_dev);
const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->driver_api;
if (api->binding_pressed == NULL) {
return -ENOTSUP;
}
- return api->binding_pressed(dev, position, param1, param2);
+ return api->binding_pressed(binding, event);
}
/**
@@ -64,18 +66,19 @@ static inline int z_impl_behavior_keymap_binding_pressed(struct device *dev, u32
* @retval 0 If successful.
* @retval Negative errno code if failure.
*/
-__syscall int behavior_keymap_binding_released(struct device *dev, u32_t position, u32_t param1,
- u32_t param2);
+__syscall int behavior_keymap_binding_released(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event);
-static inline int z_impl_behavior_keymap_binding_released(struct device *dev, u32_t position,
- u32_t param1, u32_t param2) {
+static inline int z_impl_behavior_keymap_binding_released(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
+ struct device *dev = device_get_binding(binding->behavior_dev);
const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->driver_api;
if (api->binding_released == NULL) {
return -ENOTSUP;
}
- return api->binding_released(dev, position, param1, param2);
+ return api->binding_released(binding, event);
}
/**
@@ -88,19 +91,20 @@ static inline int z_impl_behavior_keymap_binding_released(struct device *dev, u3
* @retval 0 If successful.
* @retval Negative errno code if failure.
*/
-__syscall int behavior_sensor_keymap_binding_triggered(struct device *dev, struct device *sensor,
- u32_t param1, u32_t param2);
+__syscall int behavior_sensor_keymap_binding_triggered(struct zmk_behavior_binding *binding,
+ struct device *sensor);
-static inline int z_impl_behavior_sensor_keymap_binding_triggered(struct device *dev,
- struct device *sensor,
- u32_t param1, u32_t param2) {
+static inline int
+z_impl_behavior_sensor_keymap_binding_triggered(struct zmk_behavior_binding *binding,
+ struct device *sensor) {
+ struct device *dev = device_get_binding(binding->behavior_dev);
const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->driver_api;
if (api->sensor_binding_triggered == NULL) {
return -ENOTSUP;
}
- return api->sensor_binding_triggered(dev, sensor, param1, param2);
+ return api->sensor_binding_triggered(binding, sensor);
}
/**
diff --git a/app/include/drivers/ext_power.h b/app/include/drivers/ext_power.h
new file mode 100644
index 0000000..6c1923e
--- /dev/null
+++ b/app/include/drivers/ext_power.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#pragma once
+
+#include <zephyr/types.h>
+#include <stddef.h>
+#include <device.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @cond INTERNAL_HIDDEN
+ *
+ * Behavior driver API definition and system call entry points.
+ *
+ * (Internal use only.)
+ */
+
+typedef int (*ext_power_enable_t)(struct device *dev);
+typedef int (*ext_power_disable_t)(struct device *dev);
+typedef int (*ext_power_get_t)(struct device *dev);
+
+__subsystem struct ext_power_api {
+ ext_power_enable_t enable;
+ ext_power_disable_t disable;
+ ext_power_get_t get;
+};
+/**
+ * @endcond
+ */
+
+/**
+ * @brief Enable the external power output
+ * @param dev Pointer to the device structure for the driver instance.
+ *
+ * @retval 0 If successful.
+ * @retval Negative errno code if failure.
+ */
+__syscall int ext_power_enable(struct device *dev);
+
+static inline int z_impl_ext_power_enable(struct device *dev) {
+ const struct ext_power_api *api = (const struct ext_power_api *)dev->driver_api;
+
+ if (api->enable == NULL) {
+ return -ENOTSUP;
+ }
+
+ return api->enable(dev);
+}
+
+/**
+ * @brief Disable the external power output
+ * @param dev Pointer to the device structure for the driver instance.
+ *
+ * @retval 0 If successful.
+ * @retval Negative errno code if failure.
+ */
+__syscall int ext_power_disable(struct device *dev);
+
+static inline int z_impl_ext_power_disable(struct device *dev) {
+ const struct ext_power_api *api = (const struct ext_power_api *)dev->driver_api;
+
+ if (api->disable == NULL) {
+ return -ENOTSUP;
+ }
+
+ return api->disable(dev);
+}
+
+/**
+ * @brief Get the current status of the external power output
+ * @param dev Pointer to the device structure for the driver instance.
+ *
+ * @retval 0 If ext power is disabled.
+ * @retval 1 if ext power is enabled.
+ * @retval Negative errno code if failure.
+ */
+__syscall int ext_power_get(struct device *dev);
+
+static inline int z_impl_ext_power_get(struct device *dev) {
+ const struct ext_power_api *api = (const struct ext_power_api *)dev->driver_api;
+
+ if (api->get == NULL) {
+ return -ENOTSUP;
+ }
+
+ return api->get(dev);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#include <syscalls/ext_power.h>
diff --git a/app/include/dt-bindings/zmk/bt.h b/app/include/dt-bindings/zmk/bt.h
index a403d35..8ca1060 100644
--- a/app/include/dt-bindings/zmk/bt.h
+++ b/app/include/dt-bindings/zmk/bt.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/include/dt-bindings/zmk/ext_power.h b/app/include/dt-bindings/zmk/ext_power.h
new file mode 100644
index 0000000..2a3e846
--- /dev/null
+++ b/app/include/dt-bindings/zmk/ext_power.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define EXT_POWER_OFF_CMD 0
+#define EXT_POWER_ON_CMD 1
+#define EXT_POWER_TOGGLE_CMD 2
+
+#define EP_ON EXT_POWER_ON_CMD
+#define EP_OFF EXT_POWER_OFF_CMD
+#define EP_TOG EXT_POWER_TOGGLE_CMD
diff --git a/app/include/zmk/behavior.h b/app/include/zmk/behavior.h
index 6f5815f..428ae24 100644
--- a/app/include/zmk/behavior.h
+++ b/app/include/zmk/behavior.h
@@ -10,4 +10,10 @@ struct zmk_behavior_binding {
char *behavior_dev;
u32_t param1;
u32_t param2;
+};
+
+struct zmk_behavior_binding_event {
+ int layer;
+ u32_t position;
+ s64_t timestamp;
}; \ No newline at end of file
diff --git a/app/include/zmk/ble/profile.h b/app/include/zmk/ble/profile.h
index 9a79c6d..1df2743 100644
--- a/app/include/zmk/ble/profile.h
+++ b/app/include/zmk/ble/profile.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/include/zmk/events/ble-active-profile-changed.h b/app/include/zmk/events/ble-active-profile-changed.h
index 66f40c7..1e3a198 100644
--- a/app/include/zmk/events/ble-active-profile-changed.h
+++ b/app/include/zmk/events/ble-active-profile-changed.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/include/zmk/events/keycode-state-changed.h b/app/include/zmk/events/keycode-state-changed.h
index 4c00654..1e2c24e 100644
--- a/app/include/zmk/events/keycode-state-changed.h
+++ b/app/include/zmk/events/keycode-state-changed.h
@@ -24,6 +24,5 @@ inline struct keycode_state_changed *create_keycode_state_changed(u8_t usage_pag
ev->usage_page = usage_page;
ev->keycode = keycode;
ev->state = state;
-
return ev;
} \ No newline at end of file
diff --git a/app/include/zmk/events/position-state-changed.h b/app/include/zmk/events/position-state-changed.h
index f88080d..e4cbbbe 100644
--- a/app/include/zmk/events/position-state-changed.h
+++ b/app/include/zmk/events/position-state-changed.h
@@ -13,6 +13,7 @@ struct position_state_changed {
struct zmk_event_header header;
u32_t position;
bool state;
+ s64_t timestamp;
};
ZMK_EVENT_DECLARE(position_state_changed); \ No newline at end of file
diff --git a/app/include/zmk/keymap.h b/app/include/zmk/keymap.h
index 6192587..b8f4969 100644
--- a/app/include/zmk/keymap.h
+++ b/app/include/zmk/keymap.h
@@ -11,4 +11,4 @@ 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);
+int zmk_keymap_position_state_changed(u32_t position, bool pressed, s64_t timestamp);
diff --git a/app/src/behaviors/behavior_bt.c b/app/src/behaviors/behavior_bt.c
index 09fadba..066c437 100644
--- a/app/src/behaviors/behavior_bt.c
+++ b/app/src/behaviors/behavior_bt.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
@@ -8,18 +8,18 @@
#include <device.h>
#include <drivers/behavior.h>
-
#include <dt-bindings/zmk/bt.h>
-
#include <bluetooth/conn.h>
-
#include <logging/log.h>
+#include <zmk/behavior.h>
+
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/ble.h>
-static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t command, u32_t arg) {
- switch (command) {
+static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
+ switch (binding->param1) {
case BT_CLR_CMD:
return zmk_ble_clear_bonds();
case BT_NXT_CMD:
@@ -27,9 +27,9 @@ static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t c
case BT_PRV_CMD:
return zmk_ble_prof_prev();
case BT_SEL_CMD:
- return zmk_ble_prof_select(arg);
+ return zmk_ble_prof_select(binding->param2);
default:
- LOG_ERR("Unknown BT command: %d", command);
+ LOG_ERR("Unknown BT command: %d", binding->param1);
}
return -ENOTSUP;
@@ -37,8 +37,8 @@ static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t c
static int behavior_bt_init(struct device *dev) { return 0; };
-static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t command,
- u32_t arg) {
+static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
return 0;
}
diff --git a/app/src/behaviors/behavior_ext_power.c b/app/src/behaviors/behavior_ext_power.c
new file mode 100644
index 0000000..825f983
--- /dev/null
+++ b/app/src/behaviors/behavior_ext_power.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define DT_DRV_COMPAT zmk_behavior_ext_power
+
+#include <device.h>
+#include <devicetree.h>
+#include <drivers/behavior.h>
+#include <drivers/ext_power.h>
+
+#include <dt-bindings/zmk/ext_power.h>
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
+static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
+ struct device *ext_power = device_get_binding("EXT_POWER");
+ if (ext_power == NULL) {
+ LOG_ERR("Unable to retrieve ext_power device: %d", binding->param1);
+ return -EIO;
+ }
+
+ switch (binding->param1) {
+ case EXT_POWER_OFF_CMD:
+ return ext_power_disable(ext_power);
+ case EXT_POWER_ON_CMD:
+ return ext_power_enable(ext_power);
+ case EXT_POWER_TOGGLE_CMD:
+ if (ext_power_get(ext_power) > 0)
+ return ext_power_disable(ext_power);
+ else
+ return ext_power_enable(ext_power);
+ default:
+ LOG_ERR("Unknown ext_power command: %d", binding->param1);
+ }
+
+ return -ENOTSUP;
+}
+
+static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
+ return 0;
+}
+
+static int behavior_ext_power_init(struct device *dev) { return 0; };
+
+static const struct behavior_driver_api behavior_ext_power_driver_api = {
+ .binding_pressed = on_keymap_binding_pressed,
+ .binding_released = on_keymap_binding_released,
+};
+
+DEVICE_AND_API_INIT(behavior_ext_power, DT_INST_LABEL(0), behavior_ext_power_init, NULL, NULL,
+ APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY, &behavior_ext_power_driver_api);
diff --git a/app/src/behaviors/behavior_hold_tap.c b/app/src/behaviors/behavior_hold_tap.c
index 8f307a6..8b3620e 100644
--- a/app/src/behaviors/behavior_hold_tap.c
+++ b/app/src/behaviors/behavior_hold_tap.c
@@ -10,7 +10,6 @@
#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>
@@ -18,6 +17,7 @@
#include <zmk/events/keycode-state-changed.h>
#include <zmk/events/modifiers-state-changed.h>
#include <zmk/hid.h>
+#include <zmk/behavior.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
@@ -40,10 +40,8 @@ struct behavior_hold_tap_behaviors {
struct zmk_behavior_binding hold;
};
-typedef k_timeout_t (*timer_func)();
-
struct behavior_hold_tap_config {
- timer_func tapping_term_ms;
+ int tapping_term_ms;
struct behavior_hold_tap_behaviors *behaviors;
enum flavor flavor;
};
@@ -51,8 +49,10 @@ struct behavior_hold_tap_config {
// this data is specific for each hold-tap
struct active_hold_tap {
s32_t position;
+ // todo: move these params into the config->behaviors->tap and
u32_t param_hold;
u32_t param_tap;
+ s64_t timestamp;
bool is_decided;
bool is_hold;
const struct behavior_hold_tap_config *config;
@@ -164,6 +164,7 @@ static struct active_hold_tap *find_hold_tap(u32_t position) {
}
static struct active_hold_tap *store_hold_tap(u32_t position, u32_t param_hold, u32_t param_tap,
+ s64_t timestamp,
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) {
@@ -175,6 +176,7 @@ static struct active_hold_tap *store_hold_tap(u32_t position, u32_t param_hold,
active_hold_taps[i].config = config;
active_hold_taps[i].param_hold = param_hold;
active_hold_taps[i].param_tap = param_tap;
+ active_hold_taps[i].timestamp = timestamp;
return &active_hold_taps[i];
}
return NULL;
@@ -253,7 +255,7 @@ static inline char *flavor_str(enum flavor flavor) {
return "UNKNOWN FLAVOR";
}
-static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_moment event) {
+static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_moment event_type) {
if (hold_tap->is_decided) {
return;
}
@@ -265,11 +267,11 @@ static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_mome
switch (hold_tap->config->flavor) {
case ZMK_BHV_HOLD_TAP_FLAVOR_HOLD_PREFERRED:
- decide_hold_preferred(hold_tap, event);
+ decide_hold_preferred(hold_tap, event_type);
case ZMK_BHV_HOLD_TAP_FLAVOR_BALANCED:
- decide_balanced(hold_tap, event);
+ decide_balanced(hold_tap, event_type);
case ZMK_BHV_HOLD_TAP_FLAVOR_TAP_PREFERRED:
- decide_tap_preferred(hold_tap, event);
+ decide_tap_preferred(hold_tap, event_type);
}
if (!hold_tap->is_decided) {
@@ -277,26 +279,31 @@ static void decide_hold_tap(struct active_hold_tap *hold_tap, enum decision_mome
}
LOG_DBG("%d decided %s (%s event %d)", hold_tap->position, hold_tap->is_hold ? "hold" : "tap",
- flavor_str(hold_tap->config->flavor), event);
+ flavor_str(hold_tap->config->flavor), event_type);
undecided_hold_tap = NULL;
- struct zmk_behavior_binding *behavior;
+ struct zmk_behavior_binding_event event = {
+ .position = hold_tap->position,
+ .timestamp = hold_tap->timestamp,
+ };
+
+ struct zmk_behavior_binding binding;
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);
+ binding.behavior_dev = hold_tap->config->behaviors->hold.behavior_dev;
+ binding.param1 = hold_tap->param_hold;
+ binding.param2 = 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);
+ binding.behavior_dev = hold_tap->config->behaviors->tap.behavior_dev;
+ binding.param1 = hold_tap->param_tap;
+ binding.param2 = 0;
}
+ behavior_keymap_binding_pressed(&binding, event);
release_captured_events();
}
-static int on_hold_tap_binding_pressed(struct device *dev, u32_t position, u32_t param_hold,
- u32_t param_tap) {
+static int on_hold_tap_binding_pressed(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
+ struct device *dev = device_get_binding(binding->behavior_dev);
const struct behavior_hold_tap_config *cfg = dev->config_info;
if (undecided_hold_tap != NULL) {
@@ -305,54 +312,69 @@ static int on_hold_tap_binding_pressed(struct device *dev, u32_t position, u32_t
return 0;
}
- struct active_hold_tap *hold_tap = store_hold_tap(position, param_hold, param_tap, cfg);
+ struct active_hold_tap *hold_tap =
+ store_hold_tap(event.position, binding->param1, binding->param2, event.timestamp, 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);
+ LOG_DBG("%d new undecided hold_tap", event.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.
+ // if this behavior was queued we have to adjust the timer to only
+ // wait for the remaining time.
+ s32_t tapping_term_ms_left = (hold_tap->timestamp + cfg->tapping_term_ms) - k_uptime_get();
+ if (tapping_term_ms_left > 0) {
+ k_delayed_work_submit(&hold_tap->work, K_MSEC(tapping_term_ms_left));
+ }
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);
-
+static int on_hold_tap_binding_released(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
+ struct active_hold_tap *hold_tap = find_hold_tap(event.position);
if (hold_tap == NULL) {
LOG_ERR("ACTIVE_HOLD_TAP_CLEANED_UP_TOO_EARLY");
return 0;
}
+ // If these events were queued, the timer event may be queued too late or not at all.
+ // We insert a timer event before the TH_KEY_UP event to verify.
int work_cancel_result = k_delayed_work_cancel(&hold_tap->work);
+ if (event.timestamp > (hold_tap->timestamp + hold_tap->config->tapping_term_ms)) {
+ decide_hold_tap(hold_tap, HT_TIMER_EVENT);
+ }
+
decide_hold_tap(hold_tap, HT_KEY_UP);
- struct zmk_behavior_binding *behavior;
+ // todo: set up the binding and data items inside of the active_hold_tap struct
+ struct zmk_behavior_binding_event sub_behavior_data = {
+ .position = hold_tap->position,
+ .timestamp = hold_tap->timestamp,
+ };
+
+ struct zmk_behavior_binding sub_behavior_binding;
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);
+ sub_behavior_binding.behavior_dev = hold_tap->config->behaviors->hold.behavior_dev;
+ sub_behavior_binding.param1 = hold_tap->param_hold;
+ sub_behavior_binding.param2 = 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);
+ sub_behavior_binding.behavior_dev = hold_tap->config->behaviors->tap.behavior_dev;
+ sub_behavior_binding.param1 = hold_tap->param_tap;
+ sub_behavior_binding.param2 = 0;
}
+ behavior_keymap_binding_released(&sub_behavior_binding, sub_behavior_data);
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);
+ LOG_DBG("%d hold-tap timer work in event queue", event.position);
hold_tap->work_is_cancelled = true;
} else {
- LOG_DBG("%d cleaning up hold-tap", position);
+ LOG_DBG("%d cleaning up hold-tap", event.position);
clear_hold_tap(hold_tap);
}
@@ -382,6 +404,14 @@ static int position_state_changed_listener(const struct zmk_event_header *eh) {
}
}
+ // If these events were queued, the timer event may be queued too late or not at all.
+ // We make a timer decision before the other key events are handled if the timer would
+ // have run out.
+ if (ev->timestamp >
+ (undecided_hold_tap->timestamp + undecided_hold_tap->config->tapping_term_ms)) {
+ decide_hold_tap(undecided_hold_tap, HT_TIMER_EVENT);
+ }
+
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
@@ -463,6 +493,7 @@ static int behavior_hold_tap_init(struct device *dev) {
struct behavior_hold_tap_data {};
static struct behavior_hold_tap_data behavior_hold_tap_data;
+/* todo: get rid of unused param1 and param2. */
#define _TRANSFORM_ENTRY(idx, node) \
{ \
.behavior_dev = DT_LABEL(DT_INST_PHANDLE_BY_IDX(node, bindings, idx)), \
@@ -473,14 +504,11 @@ static struct behavior_hold_tap_data behavior_hold_tap_data;
},
#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, \
+ .tapping_term_ms = DT_INST_PROP(n, tapping_term_ms), \
.flavor = DT_ENUM_IDX(DT_DRV_INST(n), flavor), \
}; \
DEVICE_AND_API_INIT(behavior_hold_tap_##n, DT_INST_LABEL(n), behavior_hold_tap_init, \
diff --git a/app/src/behaviors/behavior_key_press.c b/app/src/behaviors/behavior_key_press.c
index bbfbe36..923b098 100644
--- a/app/src/behaviors/behavior_key_press.c
+++ b/app/src/behaviors/behavior_key_press.c
@@ -12,6 +12,7 @@
#include <zmk/event-manager.h>
#include <zmk/events/keycode-state-changed.h>
+#include <zmk/behavior.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
@@ -22,18 +23,24 @@ struct behavior_key_press_data {};
static int behavior_key_press_init(struct device *dev) { return 0; };
-static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t keycode, u32_t _) {
+static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
+ struct device *dev = device_get_binding(binding->behavior_dev);
const struct behavior_key_press_config *cfg = dev->config_info;
- LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode);
+ LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", event.position, cfg->usage_page,
+ binding->param1);
- return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, true));
+ return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, binding->param1, true));
}
-static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t keycode, u32_t _) {
+static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
+ struct device *dev = device_get_binding(binding->behavior_dev);
const struct behavior_key_press_config *cfg = dev->config_info;
- LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", position, cfg->usage_page, keycode);
+ LOG_DBG("position %d usage_page 0x%02X keycode 0x%02X", event.position, cfg->usage_page,
+ binding->param1);
- return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, keycode, false));
+ return ZMK_EVENT_RAISE(create_keycode_state_changed(cfg->usage_page, binding->param1, false));
}
static const struct behavior_driver_api behavior_key_press_driver_api = {
@@ -47,4 +54,4 @@ static const struct behavior_driver_api behavior_key_press_driver_api = {
&behavior_key_press_data_##n, &behavior_key_press_config_##n, APPLICATION, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_key_press_driver_api);
-DT_INST_FOREACH_STATUS_OKAY(KP_INST) \ No newline at end of file
+DT_INST_FOREACH_STATUS_OKAY(KP_INST)
diff --git a/app/src/behaviors/behavior_momentary_layer.c b/app/src/behaviors/behavior_momentary_layer.c
index 80b7165..b1fb14b 100644
--- a/app/src/behaviors/behavior_momentary_layer.c
+++ b/app/src/behaviors/behavior_momentary_layer.c
@@ -11,6 +11,7 @@
#include <logging/log.h>
#include <zmk/keymap.h>
+#include <zmk/behavior.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
@@ -19,16 +20,16 @@ struct behavior_mo_data {};
static int behavior_mo_init(struct device *dev) { return 0; };
-static int mo_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_activate(layer);
+static int mo_keymap_binding_pressed(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
+ LOG_DBG("position %d layer %d", event.position, binding->param1);
+ return zmk_keymap_layer_activate(binding->param1);
}
-static int mo_keymap_binding_released(struct device *dev, u32_t position, u32_t layer, u32_t _) {
- LOG_DBG("position %d layer %d", position, layer);
-
- return zmk_keymap_layer_deactivate(layer);
+static int mo_keymap_binding_released(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
+ LOG_DBG("position %d layer %d", event.position, binding->param1);
+ return zmk_keymap_layer_deactivate(binding->param1);
}
static const struct behavior_driver_api behavior_mo_driver_api = {
diff --git a/app/src/behaviors/behavior_none.c b/app/src/behaviors/behavior_none.c
index b548e6f..96ea9d5 100644
--- a/app/src/behaviors/behavior_none.c
+++ b/app/src/behaviors/behavior_none.c
@@ -11,6 +11,8 @@
#include <drivers/behavior.h>
#include <logging/log.h>
+#include <zmk/behavior.h>
+
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
struct behavior_none_config {};
@@ -18,13 +20,13 @@ 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) {
+static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
return 0;
}
-static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1,
- u32_t _param2) {
+static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
return 0;
}
diff --git a/app/src/behaviors/behavior_reset.c b/app/src/behaviors/behavior_reset.c
index 90de20b..d1233a5 100644
--- a/app/src/behaviors/behavior_reset.c
+++ b/app/src/behaviors/behavior_reset.c
@@ -11,6 +11,8 @@
#include <drivers/behavior.h>
#include <logging/log.h>
+#include <zmk/behavior.h>
+
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
struct behavior_reset_config {
@@ -19,8 +21,9 @@ struct behavior_reset_config {
static int behavior_reset_init(struct device *dev) { return 0; };
-static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1,
- u32_t _param2) {
+static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
+ struct device *dev = device_get_binding(binding->behavior_dev);
const struct behavior_reset_config *cfg = dev->config_info;
// TODO: Correct magic code for going into DFU?
diff --git a/app/src/behaviors/behavior_rgb_underglow.c b/app/src/behaviors/behavior_rgb_underglow.c
index 621eab5..2ee6716 100644
--- a/app/src/behaviors/behavior_rgb_underglow.c
+++ b/app/src/behaviors/behavior_rgb_underglow.c
@@ -12,13 +12,15 @@
#include <dt-bindings/zmk/rgb.h>
#include <zmk/rgb_underglow.h>
+#include <zmk/keymap.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
static int behavior_rgb_underglow_init(struct device *dev) { return 0; }
-static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t action, u32_t _) {
- switch (action) {
+static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
+ switch (binding->param1) {
case RGB_TOG:
return zmk_rgb_underglow_toggle();
case RGB_HUI:
diff --git a/app/src/behaviors/behavior_sensor_rotate_key_press.c b/app/src/behaviors/behavior_sensor_rotate_key_press.c
index 1a0bf03..71c4376 100644
--- a/app/src/behaviors/behavior_sensor_rotate_key_press.c
+++ b/app/src/behaviors/behavior_sensor_rotate_key_press.c
@@ -23,15 +23,16 @@ struct behavior_sensor_rotate_key_press_data {};
static int behavior_sensor_rotate_key_press_init(struct device *dev) { return 0; };
-static int on_sensor_binding_triggered(struct device *dev, struct device *sensor,
- u32_t increment_keycode, u32_t decrement_keycode) {
+static int on_sensor_binding_triggered(struct zmk_behavior_binding *binding,
+ struct device *sensor) {
+ struct device *dev = device_get_binding(binding->behavior_dev);
const struct behavior_sensor_rotate_key_press_config *cfg = dev->config_info;
struct sensor_value value;
int err;
u32_t keycode;
struct keycode_state_changed *ev;
LOG_DBG("usage_page 0x%02X inc keycode 0x%02X dec keycode 0x%02X", cfg->usage_page,
- increment_keycode, decrement_keycode);
+ binding->param1, binding->param2);
err = sensor_channel_get(sensor, SENSOR_CHAN_ROTATION, &value);
@@ -42,10 +43,10 @@ static int on_sensor_binding_triggered(struct device *dev, struct device *sensor
switch (value.val1) {
case 1:
- keycode = increment_keycode;
+ keycode = binding->param1;
break;
case -1:
- keycode = decrement_keycode;
+ keycode = binding->param2;
break;
default:
return -ENOTSUP;
diff --git a/app/src/behaviors/behavior_toggle_layer.c b/app/src/behaviors/behavior_toggle_layer.c
index 2819451..b3c6961 100644
--- a/app/src/behaviors/behavior_toggle_layer.c
+++ b/app/src/behaviors/behavior_toggle_layer.c
@@ -11,6 +11,7 @@
#include <logging/log.h>
#include <zmk/keymap.h>
+#include <zmk/behavior.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
@@ -19,15 +20,15 @@ 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_pressed(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
+ LOG_DBG("position %d layer %d", event.position, binding->param1);
+ return zmk_keymap_layer_toggle(binding->param1);
}
-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);
-
+static int tog_keymap_binding_released(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
+ LOG_DBG("position %d layer %d", event.position, binding->param1);
return 0;
}
diff --git a/app/src/behaviors/behavior_transparent.c b/app/src/behaviors/behavior_transparent.c
index f7852f3..cede369 100644
--- a/app/src/behaviors/behavior_transparent.c
+++ b/app/src/behaviors/behavior_transparent.c
@@ -11,6 +11,8 @@
#include <drivers/behavior.h>
#include <logging/log.h>
+#include <zmk/behavior.h>
+
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
struct behavior_transparent_config {};
@@ -18,13 +20,13 @@ struct behavior_transparent_data {};
static int behavior_transparent_init(struct device *dev) { return 0; };
-static int on_keymap_binding_pressed(struct device *dev, u32_t position, u32_t _param1,
- u32_t _param2) {
+static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
return 1;
}
-static int on_keymap_binding_released(struct device *dev, u32_t position, u32_t _param1,
- u32_t _param2) {
+static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
+ struct zmk_behavior_binding_event event) {
return 1;
}
diff --git a/app/src/events/ble_active_profile_changed.c b/app/src/events/ble_active_profile_changed.c
index a270a14..06988e2 100644
--- a/app/src/events/ble_active_profile_changed.c
+++ b/app/src/events/ble_active_profile_changed.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ * Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
diff --git a/app/src/ext_power_generic.c b/app/src/ext_power_generic.c
new file mode 100644
index 0000000..4817030
--- /dev/null
+++ b/app/src/ext_power_generic.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2020 The ZMK Contributors
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#define DT_DRV_COMPAT zmk_ext_power_generic
+
+#include <device.h>
+#include <init.h>
+#include <drivers/gpio.h>
+#include <drivers/ext_power.h>
+
+#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
+struct ext_power_generic_config {
+ const char *label;
+ const u8_t pin;
+ const u8_t flags;
+};
+
+struct ext_power_generic_data {
+ struct device *gpio;
+ bool status;
+};
+
+static int ext_power_generic_enable(struct device *dev) {
+ struct ext_power_generic_data *data = dev->driver_data;
+ const struct ext_power_generic_config *config = dev->config_info;
+
+ if (gpio_pin_set(data->gpio, config->pin, 1)) {
+ LOG_WRN("Failed to set ext-power control pin");
+ return -EIO;
+ }
+ data->status = true;
+ return 0;
+}
+
+static int ext_power_generic_disable(struct device *dev) {
+ struct ext_power_generic_data *data = dev->driver_data;
+ const struct ext_power_generic_config *config = dev->config_info;
+
+ if (gpio_pin_set(data->gpio, config->pin, 0)) {
+ LOG_WRN("Failed to clear ext-power control pin");
+ return -EIO;
+ }
+ data->status = false;
+ return 0;
+}
+
+static int ext_power_generic_get(struct device *dev) {
+ struct ext_power_generic_data *data = dev->driver_data;
+ return data->status;
+}
+
+static int ext_power_generic_init(struct device *dev) {
+ struct ext_power_generic_data *data = dev->driver_data;
+ const struct ext_power_generic_config *config = dev->config_info;
+
+ data->gpio = device_get_binding(config->label);
+ if (data->gpio == NULL) {
+ LOG_ERR("Failed to get ext-power control device");
+ return -EINVAL;
+ }
+
+ if (gpio_pin_configure(data->gpio, config->pin, config->flags | GPIO_OUTPUT)) {
+ LOG_ERR("Failed to configure ext-power control pin");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static const struct ext_power_generic_config config = {
+ .label = DT_INST_GPIO_LABEL(0, control_gpios),
+ .pin = DT_INST_GPIO_PIN(0, control_gpios),
+ .flags = DT_INST_GPIO_FLAGS(0, control_gpios)};
+
+static struct ext_power_generic_data data = {.status = false};
+
+static const struct ext_power_api api = {.enable = ext_power_generic_enable,
+ .disable = ext_power_generic_disable,
+ .get = ext_power_generic_get};
+
+DEVICE_AND_API_INIT(ext_power_generic, DT_INST_LABEL(0), ext_power_generic_init, &data, &config,
+ APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &api);
+
+#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */
diff --git a/app/src/hog.c b/app/src/hog.c
index 11349ac..bcd652d 100644
--- a/app/src/hog.c
+++ b/app/src/hog.c
@@ -164,8 +164,10 @@ int zmk_hog_send_keypad_report(struct zmk_hid_keypad_report_body *report) {
LOG_DBG("Sending to NULL? %s", conn == NULL ? "yes" : "no");
- return bt_gatt_notify(conn, &hog_svc.attrs[5], report,
- sizeof(struct zmk_hid_keypad_report_body));
+ int err =
+ bt_gatt_notify(conn, &hog_svc.attrs[5], report, sizeof(struct zmk_hid_keypad_report_body));
+ bt_conn_unref(conn);
+ return err;
};
int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *report) {
@@ -174,6 +176,8 @@ int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *report) {
return -ENOTCONN;
}
- return bt_gatt_notify(conn, &hog_svc.attrs[10], report,
- sizeof(struct zmk_hid_consumer_report_body));
+ int err = bt_gatt_notify(conn, &hog_svc.attrs[10], report,
+ sizeof(struct zmk_hid_consumer_report_body));
+ bt_conn_unref(conn);
+ return err;
};
diff --git a/app/src/keymap.c b/app/src/keymap.c
index a87ce04..74fe60d 100644
--- a/app/src/keymap.c
+++ b/app/src/keymap.c
@@ -104,9 +104,14 @@ bool is_active_layer(u8_t layer, u32_t layer_state) {
return (layer_state & BIT(layer)) == BIT(layer) || layer == zmk_keymap_layer_default;
}
-int zmk_keymap_apply_position_state(int layer, u32_t position, bool pressed) {
+int zmk_keymap_apply_position_state(int layer, u32_t position, bool pressed, s64_t timestamp) {
struct zmk_behavior_binding *binding = &zmk_keymap[layer][position];
struct device *behavior;
+ struct zmk_behavior_binding_event event = {
+ .layer = layer,
+ .position = position,
+ .timestamp = timestamp,
+ };
LOG_DBG("layer: %d position: %d, binding name: %s", layer, position,
log_strdup(binding->behavior_dev));
@@ -119,20 +124,18 @@ int zmk_keymap_apply_position_state(int layer, u32_t position, bool pressed) {
}
if (pressed) {
- return behavior_keymap_binding_pressed(behavior, position, binding->param1,
- binding->param2);
+ return behavior_keymap_binding_pressed(binding, event);
} else {
- return behavior_keymap_binding_released(behavior, position, binding->param1,
- binding->param2);
+ return behavior_keymap_binding_released(binding, event);
}
}
-int zmk_keymap_position_state_changed(u32_t position, bool pressed) {
+int zmk_keymap_position_state_changed(u32_t position, bool pressed, s64_t timestamp) {
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);
+ int ret = zmk_keymap_apply_position_state(layer, position, pressed, timestamp);
zmk_keymap_active_behavior_layer[position] = zmk_keymap_layer_state;
@@ -171,8 +174,7 @@ int zmk_keymap_sensor_triggered(u8_t sensor_number, struct device *sensor) {
continue;
}
- ret = behavior_sensor_keymap_binding_triggered(behavior, sensor, binding->param1,
- binding->param2);
+ ret = behavior_sensor_keymap_binding_triggered(binding, sensor);
if (ret > 0) {
LOG_DBG("behavior processing to continue to next layer");
@@ -194,7 +196,7 @@ int zmk_keymap_sensor_triggered(u8_t sensor_number, struct device *sensor) {
int keymap_listener(const struct zmk_event_header *eh) {
if (is_position_state_changed(eh)) {
const struct position_state_changed *ev = cast_position_state_changed(eh);
- return zmk_keymap_position_state_changed(ev->position, ev->state);
+ return zmk_keymap_position_state_changed(ev->position, ev->state, ev->timestamp);
#if ZMK_KEYMAP_HAS_SENSORS
} else if (is_sensor_event(eh)) {
const struct sensor_event *ev = cast_sensor_event(eh);
diff --git a/app/src/kscan.c b/app/src/kscan.c
index 0046f5c..8575e70 100644
--- a/app/src/kscan.c
+++ b/app/src/kscan.c
@@ -52,6 +52,7 @@ void zmk_kscan_process_msgq(struct k_work *item) {
pos_ev = new_position_state_changed();
pos_ev->state = pressed;
pos_ev->position = position;
+ pos_ev->timestamp = k_uptime_get();
ZMK_EVENT_RAISE(pos_ev);
}
}
diff --git a/app/src/main.c b/app/src/main.c
index dca923e..0551356 100644
--- a/app/src/main.c
+++ b/app/src/main.c
@@ -15,16 +15,25 @@ LOG_MODULE_REGISTER(zmk, CONFIG_ZMK_LOG_LEVEL);
#include <zmk/matrix.h>
#include <zmk/kscan.h>
#include <zmk/display.h>
+#include <drivers/ext_power.h>
#define ZMK_KSCAN_DEV DT_LABEL(ZMK_MATRIX_NODE_ID)
void main(void) {
+ struct device *ext_power;
LOG_INF("Welcome to ZMK!\n");
if (zmk_kscan_init(ZMK_KSCAN_DEV) != 0) {
return;
}
+ // Enable the external VCC output
+ ext_power = device_get_binding("EXT_POWER");
+ if (ext_power != NULL) {
+ const struct ext_power_api *ext_power_api = ext_power->driver_api;
+ ext_power_api->enable(ext_power);
+ }
+
#ifdef CONFIG_ZMK_DISPLAY
zmk_display_init();
diff --git a/app/src/split/bluetooth/central.c b/app/src/split/bluetooth/central.c
index cb1b68b..ed52ba0 100644
--- a/app/src/split/bluetooth/central.c
+++ b/app/src/split/bluetooth/central.c
@@ -60,6 +60,7 @@ static u8_t split_central_notify_func(struct bt_conn *conn, struct bt_gatt_subsc
struct position_state_changed *pos_ev = new_position_state_changed();
pos_ev->position = position;
pos_ev->state = pressed;
+ pos_ev->timestamp = k_uptime_get();
LOG_DBG("Trigger key position state change for %d", position);
ZMK_EVENT_RAISE(pos_ev);
diff --git a/app/tests/hold-tap/balanced/many-nested/events.patterns b/app/tests/hold-tap/balanced/many-nested/events.patterns
new file mode 100644
index 0000000..fdf2b15
--- /dev/null
+++ b/app/tests/hold-tap/balanced/many-nested/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/many-nested/keycode_events.snapshot b/app/tests/hold-tap/balanced/many-nested/keycode_events.snapshot
new file mode 100644
index 0000000..806896f
--- /dev/null
+++ b/app/tests/hold-tap/balanced/many-nested/keycode_events.snapshot
@@ -0,0 +1,20 @@
+ht_binding_pressed: 0 new undecided hold_tap
+ht_decide: 0 decided hold (balanced event 3)
+kp_pressed: usage_page 0x07 keycode 0xe1
+ht_binding_pressed: 1 new undecided hold_tap
+ht_decide: 1 decided hold (balanced event 3)
+kp_pressed: usage_page 0x07 keycode 0xe0
+ht_binding_pressed: 2 new undecided hold_tap
+ht_binding_released: 0 cleaning up hold-tap
+ht_decide: 2 decided hold (balanced event 3)
+kp_pressed: usage_page 0x07 keycode 0xe3
+ht_binding_pressed: 3 new undecided hold_tap
+ht_binding_released: 1 cleaning up hold-tap
+ht_decide: 3 decided hold (balanced event 3)
+kp_pressed: usage_page 0x07 keycode 0xe2
+kp_released: usage_page 0x07 keycode 0xe1
+kp_released: usage_page 0x07 keycode 0xe0
+kp_released: usage_page 0x07 keycode 0xe3
+ht_binding_released: 2 cleaning up hold-tap
+kp_released: usage_page 0x07 keycode 0xe2
+ht_binding_released: 3 cleaning up hold-tap
diff --git a/app/tests/hold-tap/balanced/many-nested/native_posix.keymap b/app/tests/hold-tap/balanced/many-nested/native_posix.keymap
new file mode 100644
index 0000000..3cb04c3
--- /dev/null
+++ b/app/tests/hold-tap/balanced/many-nested/native_posix.keymap
@@ -0,0 +1,41 @@
+#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
+ &ht_bal LGUI H &ht_bal LALT L
+ >;
+ };
+ };
+};
+
+&kscan {
+ events = <
+ ZMK_MOCK_PRESS(0,0,100)
+ ZMK_MOCK_PRESS(0,1,100)
+ ZMK_MOCK_PRESS(1,0,100)
+ ZMK_MOCK_PRESS(1,1,100)
+ ZMK_MOCK_RELEASE(0,0,100)
+ ZMK_MOCK_RELEASE(0,1,100)
+ ZMK_MOCK_RELEASE(1,0,100)
+ ZMK_MOCK_RELEASE(1,1,100)
+ >;
+};