diff options
Diffstat (limited to 'app')
34 files changed, 661 insertions, 78 deletions
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 31d28f5..8a3971e 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -46,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) @@ -61,6 +62,7 @@ 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_ifdef(CONFIG_SETTINGS app PRIVATE src/settings.c) target_sources(app PRIVATE src/main.c) zephyr_cc_option(-Wfatal-errors) diff --git a/app/Kconfig b/app/Kconfig index fca4912..285ed91 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -9,6 +9,15 @@ config USB_DEVICE_PRODUCT config BT_DEVICE_NAME default ZMK_KEYBOARD_NAME +config USB_DEVICE_VID + default 0x1D50 + +config USB_DEVICE_PID + default 0x615E + +config USB_DEVICE_MANUFACTURER + default "ZMK Project" + config ZMK_KSCAN_EVENT_QUEUE_SIZE int "Size of the event queue for KSCAN events to buffer events" default 4 @@ -208,6 +217,10 @@ menuconfig ZMK_RGB_UNDERGLOW if ZMK_RGB_UNDERGLOW +# This default value cuts down on tons of excess .conf files, if you're using GPIO, manually disable this +config SPI + default y + config ZMK_RGB_UNDERGLOW_HUE_STEP int "RGB underglow hue step in degrees of 360" default 10 @@ -220,6 +233,30 @@ config ZMK_RGB_UNDERGLOW_BRT_STEP int "RGB underglow brightness step in percent" default 10 +config ZMK_RGB_UNDERGLOW_HUE_START + int "RGB underglow start hue value from 0-359" + default 0 + +config ZMK_RGB_UNDERGLOW_SAT_START + int "RGB underglow start saturations value from 0-100" + default 100 + +config ZMK_RGB_UNDERGLOW_BRT_START + int "RGB underglow start brightness value from 0-100" + default 100 + +config ZMK_RGB_UNDERGLOW_SPD_START + int "RGB underglow start animation speed value from 1-5" + default 3 + +config ZMK_RGB_UNDERGLOW_EFF_START + int "RGB underglow start effect int value related to the effect enum list" + default 0 + +config ZMK_RGB_UNDERGLOW_ON_START + bool "Whether RGB underglow starts on by default" + default y + endif endmenu diff --git a/app/boards/shields/Kconfig.defconfig b/app/boards/shields/Kconfig.defconfig new file mode 100644 index 0000000..5b9ca9a --- /dev/null +++ b/app/boards/shields/Kconfig.defconfig @@ -0,0 +1,14 @@ + + + +config ZMK_KEYBOARD_NAME + default "cradios" + +# Unable to use interrupts as the same pin number is used +# across A & B controllers, and STM32F303CCT6 can't enable +# interrutps for multiple controllers for the same "line" +# for the external interrupts. +config ZMK_KSCAN_GPIO_POLLING + default y + + diff --git a/app/boards/shields/Kconfig.shield b/app/boards/shields/Kconfig.shield new file mode 100644 index 0000000..844d433 --- /dev/null +++ b/app/boards/shields/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright (c) 2020 Pete Johanson +# SPDX-License-Identifier: MIT + +config SHIELD_CRADIOS + def_bool $(shields_list_contains,cradios) diff --git a/app/boards/shields/cradio/Kconfig.defconfig b/app/boards/shields/cradio/Kconfig.defconfig new file mode 100644 index 0000000..4d200c9 --- /dev/null +++ b/app/boards/shields/cradio/Kconfig.defconfig @@ -0,0 +1,23 @@ +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT + +if SHIELD_CRADIO_LEFT + +config ZMK_KEYBOARD_NAME + default "cradio left" + +endif + +if SHIELD_CRADIO_RIGHT + +config ZMK_KEYBOARD_NAME + default "cradio right" + +endif + +if SHIELD_CRADIO_RIGHT || SHIELD_CRADIO_LEFT + +config ZMK_KSCAN_DIRECT_POLLING + default y + +endif diff --git a/app/boards/shields/cradio/Kconfig.shield b/app/boards/shields/cradio/Kconfig.shield new file mode 100644 index 0000000..bb5f073 --- /dev/null +++ b/app/boards/shields/cradio/Kconfig.shield @@ -0,0 +1,8 @@ +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT + +config SHIELD_CRADIO_LEFT + def_bool $(shields_list_contains,cradio_left) + +config SHIELD_CRADIO_RIGHT + def_bool $(shields_list_contains,cradio_right) diff --git a/app/boards/shields/cradio/cradio.dtsi b/app/boards/shields/cradio/cradio.dtsi new file mode 100644 index 0000000..43f9049 --- /dev/null +++ b/app/boards/shields/cradio/cradio.dtsi @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * 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 = <34>; + rows = <1>; + map = < + RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,21) RC(0,20) RC(0,19) RC(0,18) RC(0,17) + RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,26) RC(0,25) RC(0,24) RC(0,23) RC(0,22) + RC(0,10) RC(0,11) RC(0,12) RC(0,13) RC(0,14) RC(0,31) RC(0,30) RC(0,29) RC(0,28) RC(0,27) + RC(0,15) RC(0,16) RC(0,33) RC(0,32) + >; + + kscan0: kscan { + compatible = "zmk,kscan-gpio-direct"; + label = "KSCAN"; + input-gpios + = <&pro_micro_d 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&pro_micro_a 0 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&pro_micro_a 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&pro_micro_a 2 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&pro_micro_a 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&pro_micro_d 15 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&pro_micro_d 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&pro_micro_d 16 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&pro_micro_d 10 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&pro_micro_d 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&pro_micro_d 2 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&pro_micro_d 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&pro_micro_a 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&pro_micro_d 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&pro_micro_d 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)> + , <&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/cradio/cradio.keymap b/app/boards/shields/cradio/cradio.keymap new file mode 100644 index 0000000..487f6dc --- /dev/null +++ b/app/boards/shields/cradio/cradio.keymap @@ -0,0 +1,43 @@ +/* + * 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> + + +/ { + 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 SCLN + &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp CMMA &kp DOT &kp FSLH + &mo 1 &kp LCTL &kp SPC &mo 2 + >; + }; + upper_layer { + 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 + &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &kp H &kp J &kp K &kp L &kp SCLN + &kp LSFT &trans &trans &trans &trans &trans &trans &trans &trans &trans + &mo 1 &kp LCTL &kp SPC &mo 2 + >; + }; + + lower_layer { + bindings = < + &kp BANG &kp ATSN &kp HASH &kp CURU &kp PRCT &kp CRRT &kp AMPS &kp KMLT &kp LPRN &kp RPRN + &trans &trans &trans &trans &trans &kp MINUS &kp EQL &kp LBKT &kp RBKT &kp PIPE + &trans &trans &trans &trans &trans &trans &trans &trans &kp BSLH &kp TILD + &mo 1 &kp LCTL &kp SPC &mo 2 + >; + }; + + }; +}; diff --git a/app/boards/shields/cradio/cradio_left.conf b/app/boards/shields/cradio/cradio_left.conf new file mode 100644 index 0000000..405f04d --- /dev/null +++ b/app/boards/shields/cradio/cradio_left.conf @@ -0,0 +1,5 @@ +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT + +CONFIG_ZMK_SPLIT=y +CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y diff --git a/app/boards/shields/cradio/cradio_left.overlay b/app/boards/shields/cradio/cradio_left.overlay new file mode 100644 index 0000000..6a3704a --- /dev/null +++ b/app/boards/shields/cradio/cradio_left.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include "cradio.dtsi" diff --git a/app/boards/shields/cradio/cradio_right.conf b/app/boards/shields/cradio/cradio_right.conf new file mode 100644 index 0000000..bd2c93b --- /dev/null +++ b/app/boards/shields/cradio/cradio_right.conf @@ -0,0 +1,5 @@ +# Copyright (c) 2020 The ZMK Contributors +# SPDX-License-Identifier: MIT + +CONFIG_ZMK_SPLIT=y +CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y diff --git a/app/boards/shields/cradio/cradio_right.overlay b/app/boards/shields/cradio/cradio_right.overlay new file mode 100644 index 0000000..01aa1ab --- /dev/null +++ b/app/boards/shields/cradio/cradio_right.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include "cradio.dtsi" + +&default_transform { + col-offset = <17>; +}; 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/qaz/qaz.conf b/app/boards/shields/qaz/qaz.conf new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/app/boards/shields/qaz/qaz.conf 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 < 1 BKSP < 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/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/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/src/behaviors/behavior_bt.c b/app/src/behaviors/behavior_bt.c index 922c157..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 */ 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_key_press.c b/app/src/behaviors/behavior_key_press.c index d691e9f..923b098 100644 --- a/app/src/behaviors/behavior_key_press.c +++ b/app/src/behaviors/behavior_key_press.c @@ -54,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/ble.c b/app/src/ble.c index 49e2b3b..9090582 100644 --- a/app/src/ble.c +++ b/app/src/ble.c @@ -45,10 +45,29 @@ static u8_t passkey_digit = 0; #define PROFILE_COUNT CONFIG_BT_MAX_PAIRED #endif +enum advertising_type { + ZMK_ADV_NONE, + ZMK_ADV_DIR, + ZMK_ADV_CONN, +} advertising_status; + +#define CURR_ADV(adv) (adv << 4) + +#define ZMK_ADV_CONN_NAME \ + BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME, BT_GAP_ADV_FAST_INT_MIN_2, \ + BT_GAP_ADV_FAST_INT_MAX_2, NULL) + static struct zmk_ble_profile profiles[PROFILE_COUNT]; static u8_t active_profile; +#define DEVICE_NAME CONFIG_BT_DEVICE_NAME +#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1) + static const struct bt_data zmk_ble_ad[] = { +#if !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL) + BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN), + BT_DATA_BYTES(BT_DATA_GAP_APPEARANCE, 0xC1, 0x03), +#endif BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), BT_DATA_BYTES(BT_DATA_UUID16_SOME, #if !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL) @@ -92,29 +111,101 @@ void set_profile_address(u8_t index, const bt_addr_le_t *addr) { raise_profile_changed_event(); } -int zmk_ble_adv_pause() { - int err = bt_le_adv_stop(); - if (err) { - LOG_ERR("Failed to stop advertising (err %d)", err); - return err; +bool active_profile_is_connected() { + struct bt_conn *conn; + bt_addr_le_t *addr = zmk_ble_active_profile_addr(); + if (!bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) { + return false; + } else if ((conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, addr)) == NULL) { + return false; } - return 0; -}; + bt_conn_unref(conn); -int zmk_ble_adv_resume() { - LOG_DBG("active_profile %d, directed? %s", active_profile, - active_profile_is_open() ? "no" : "yes"); + return true; +} - int err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0); - if (err) { - LOG_ERR("Advertising failed to start (err %d)", err); - return err; +#define CHECKED_ADV_STOP() \ + err = bt_le_adv_stop(); \ + advertising_status = ZMK_ADV_NONE; \ + if (err) { \ + LOG_ERR("Failed to stop advertising (err %d)", err); \ + return err; \ + } + +#define CHECKED_DIR_ADV() \ + addr = zmk_ble_active_profile_addr(); \ + conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, addr); \ + if (conn != NULL) { /* TODO: Check status of connection */ \ + LOG_DBG("Skipping advertising, profile host is already connected"); \ + bt_conn_unref(conn); \ + return 0; \ + } \ + err = bt_le_adv_start(BT_LE_ADV_CONN_DIR_LOW_DUTY(addr), zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), \ + NULL, 0); \ + if (err) { \ + LOG_ERR("Advertising failed to start (err %d)", err); \ + return err; \ + } \ + advertising_status = ZMK_ADV_DIR; + +#define CHECKED_OPEN_ADV() \ + err = bt_le_adv_start(ZMK_ADV_CONN_NAME, zmk_ble_ad, ARRAY_SIZE(zmk_ble_ad), NULL, 0); \ + if (err) { \ + LOG_ERR("Advertising failed to start (err %d)", err); \ + return err; \ + } \ + advertising_status = ZMK_ADV_CONN; + +int update_advertising() { + int err = 0; + bt_addr_le_t *addr; + struct bt_conn *conn; + enum advertising_type desired_adv = ZMK_ADV_NONE; + + if (active_profile_is_open() || !active_profile_is_connected()) { + desired_adv = ZMK_ADV_CONN; + } else if (!active_profile_is_connected()) { + desired_adv = ZMK_ADV_CONN; + // Need to fix directed advertising for privacy centrals. See + // https://github.com/zephyrproject-rtos/zephyr/pull/14984 char + // addr_str[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(zmk_ble_active_profile_addr(), addr_str, + // sizeof(addr_str)); + + // LOG_DBG("Directed advertising to %s", log_strdup(addr_str)); + // desired_adv = ZMK_ADV_DIR; + } + LOG_DBG("advertising from %d to %d", advertising_status, desired_adv); + + switch (desired_adv + CURR_ADV(advertising_status)) { + case ZMK_ADV_NONE + CURR_ADV(ZMK_ADV_DIR): + case ZMK_ADV_NONE + CURR_ADV(ZMK_ADV_CONN): + CHECKED_ADV_STOP(); + break; + case ZMK_ADV_DIR + CURR_ADV(ZMK_ADV_DIR): + case ZMK_ADV_DIR + CURR_ADV(ZMK_ADV_CONN): + CHECKED_ADV_STOP(); + CHECKED_DIR_ADV(); + break; + case ZMK_ADV_DIR + CURR_ADV(ZMK_ADV_NONE): + CHECKED_DIR_ADV(); + break; + case ZMK_ADV_CONN + CURR_ADV(ZMK_ADV_DIR): + CHECKED_ADV_STOP(); + CHECKED_OPEN_ADV(); + break; + case ZMK_ADV_CONN + CURR_ADV(ZMK_ADV_NONE): + CHECKED_OPEN_ADV(); + break; } return 0; }; +static void update_advertising_callback(struct k_work *work) { update_advertising(); } + +K_WORK_DEFINE(update_advertising_work, update_advertising_callback); + int zmk_ble_clear_bonds() { LOG_DBG(""); @@ -124,6 +215,8 @@ int zmk_ble_clear_bonds() { set_profile_address(active_profile, BT_ADDR_LE_ANY); } + update_advertising(); + return 0; }; @@ -134,9 +227,13 @@ int zmk_ble_prof_select(u8_t index) { } active_profile = index; - return settings_save_one("ble/active_profile", &active_profile, sizeof(active_profile)); + settings_save_one("ble/active_profile", &active_profile, sizeof(active_profile)); + + update_advertising(); raise_profile_changed_event(); + + return 0; }; int zmk_ble_prof_next() { @@ -234,8 +331,11 @@ static void connected(struct bt_conn *conn, u8_t err) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + advertising_status = ZMK_ADV_NONE; + if (err) { LOG_WRN("Failed to connect to %s (%u)", log_strdup(addr), err); + update_advertising(); return; } @@ -250,6 +350,8 @@ static void connected(struct bt_conn *conn, u8_t err) { if (bt_conn_set_security(conn, BT_SECURITY_L2)) { LOG_ERR("Failed to set security"); } + + update_advertising(); } static void disconnected(struct bt_conn *conn, u8_t reason) { @@ -259,14 +361,9 @@ static void disconnected(struct bt_conn *conn, u8_t reason) { LOG_DBG("Disconnected from %s (reason 0x%02x)", log_strdup(addr), reason); -#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) - // if (bt_addr_le_cmp(&peripheral_addr, BT_ADDR_LE_ANY) && bt_addr_le_cmp(&peripheral_addr, - // bt_conn_get_dst(conn))) { - // zmk_ble_adv_resume(); - // } -#else - // zmk_ble_adv_resume(); -#endif + // We need to do this in a work callback, otherwise the advertising update will still see the + // connection for a profile as active, and not start advertising yet. + k_work_submit(&update_advertising_work); } static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) { @@ -361,6 +458,7 @@ static void auth_pairing_complete(struct bt_conn *conn, bool bonded) { #endif /* !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL) */ set_profile_address(active_profile, dst); + update_advertising(); }; static struct bt_conn_auth_cb zmk_ble_auth_cb_display = { @@ -383,7 +481,7 @@ static void zmk_ble_ready(int err) { return; } - zmk_ble_adv_resume(); + update_advertising(); } static int zmk_ble_init(struct device *_arg) { 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/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/rgb_underglow.c b/app/src/rgb_underglow.c index 13912e3..b371c94 100644 --- a/app/src/rgb_underglow.c +++ b/app/src/rgb_underglow.c @@ -7,6 +7,7 @@ #include <device.h> #include <init.h> #include <kernel.h> +#include <settings/settings.h> #include <math.h> #include <stdlib.h> @@ -14,7 +15,6 @@ #include <logging/log.h> #include <drivers/led_strip.h> -#include <device.h> LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); @@ -45,12 +45,36 @@ struct rgb_underglow_state { bool on; }; -struct rgb_underglow_state state; - struct device *led_strip; struct led_rgb pixels[STRIP_NUM_PIXELS]; +struct rgb_underglow_state state; + +#if IS_ENABLED(CONFIG_SETTINGS) +static int rgb_settings_set(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg) { + const char *next; + int rc; + + if (settings_name_steq(name, "state", &next) && !next) { + if (len != sizeof(state)) { + return -EINVAL; + } + + rc = read_cb(cb_arg, &state, sizeof(state)); + if (rc >= 0) { + return 0; + } + + return rc; + } + + return -ENOENT; +} + +struct settings_handler rgb_conf = {.name = "rgb/underglow", .h_set = rgb_settings_set}; +#endif + static struct led_rgb hsb_to_rgb(struct led_hsb hsb) { double r, g, b; @@ -100,6 +124,14 @@ static struct led_rgb hsb_to_rgb(struct led_hsb hsb) { return rgb; } +static void zmk_rgb_underglow_off() { + for (int i = 0; i < STRIP_NUM_PIXELS; i++) { + pixels[i] = (struct led_rgb){r : 0, g : 0, b : 0}; + } + + led_strip_update_rgb(led_strip, pixels, STRIP_NUM_PIXELS); +} + static void zmk_rgb_underglow_effect_solid() { for (int i = 0; i < STRIP_NUM_PIXELS; i++) { int hue = state.hue; @@ -182,6 +214,14 @@ static void zmk_rgb_underglow_tick(struct k_work *work) { K_WORK_DEFINE(underglow_work, zmk_rgb_underglow_tick); static void zmk_rgb_underglow_tick_handler(struct k_timer *timer) { + if (!state.on) { + zmk_rgb_underglow_off(); + + k_timer_stop(timer); + + return; + } + k_work_submit(&underglow_work); } @@ -197,20 +237,32 @@ static int zmk_rgb_underglow_init(struct device *_arg) { } state = (struct rgb_underglow_state){ - hue : 0, - saturation : 100, - brightness : 100, - animation_speed : 3, - current_effect : 0, + hue : CONFIG_ZMK_RGB_UNDERGLOW_HUE_START, + saturation : CONFIG_ZMK_RGB_UNDERGLOW_SAT_START, + brightness : CONFIG_ZMK_RGB_UNDERGLOW_BRT_START, + animation_speed : CONFIG_ZMK_RGB_UNDERGLOW_SPD_START, + current_effect : CONFIG_ZMK_RGB_UNDERGLOW_EFF_START, animation_step : 0, - on : true + on : IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_ON_START) }; +#if IS_ENABLED(CONFIG_SETTINGS) + settings_register(&rgb_conf); +#endif + k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50)); return 0; } +int zmk_rgb_underglow_save_state() { +#if IS_ENABLED(CONFIG_SETTINGS) + return settings_save_one("rgb/underglow/state", &state, sizeof(state)); +#else + return 0; +#endif +} + int zmk_rgb_underglow_cycle_effect(int direction) { if (!led_strip) return -ENODEV; @@ -228,7 +280,7 @@ int zmk_rgb_underglow_cycle_effect(int direction) { state.animation_step = 0; - return 0; + return zmk_rgb_underglow_save_state(); } int zmk_rgb_underglow_toggle() { @@ -241,17 +293,12 @@ int zmk_rgb_underglow_toggle() { state.animation_step = 0; k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50)); } else { - - for (int i = 0; i < STRIP_NUM_PIXELS; i++) { - pixels[i] = (struct led_rgb){r : 0, g : 0, b : 0}; - } - - led_strip_update_rgb(led_strip, pixels, STRIP_NUM_PIXELS); + zmk_rgb_underglow_off(); k_timer_stop(&underglow_tick); } - return 0; + return zmk_rgb_underglow_save_state(); } int zmk_rgb_underglow_change_hue(int direction) { @@ -259,17 +306,15 @@ int zmk_rgb_underglow_change_hue(int direction) { return -ENODEV; if (state.hue == 0 && direction < 0) { - state.hue = 350; + state.hue = 360 - CONFIG_ZMK_RGB_UNDERGLOW_HUE_STEP; return 0; } state.hue += direction * CONFIG_ZMK_RGB_UNDERGLOW_HUE_STEP; - if (state.hue > 350) { - state.hue = 0; - } + state.hue = state.hue % 360; - return 0; + return zmk_rgb_underglow_save_state(); } int zmk_rgb_underglow_change_sat(int direction) { @@ -286,7 +331,7 @@ int zmk_rgb_underglow_change_sat(int direction) { state.saturation = 100; } - return 0; + return zmk_rgb_underglow_save_state(); } int zmk_rgb_underglow_change_brt(int direction) { @@ -303,7 +348,7 @@ int zmk_rgb_underglow_change_brt(int direction) { state.brightness = 100; } - return 0; + return zmk_rgb_underglow_save_state(); } int zmk_rgb_underglow_change_spd(int direction) { @@ -320,7 +365,7 @@ int zmk_rgb_underglow_change_spd(int direction) { state.animation_speed = 5; } - return 0; + return zmk_rgb_underglow_save_state(); } SYS_INIT(zmk_rgb_underglow_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); diff --git a/app/src/settings.c b/app/src/settings.c new file mode 100644 index 0000000..8914ccc --- /dev/null +++ b/app/src/settings.c @@ -0,0 +1,8 @@ +#include <device.h> +#include <init.h> +#include <kernel.h> +#include <settings/settings.h> + +static int zmk_settings_init(struct device *_arg) { return settings_load(); } + +SYS_INIT(zmk_settings_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); |