Merge remote-tracking branch 'upstream/main' into gpio-driver-max7318
|
@ -243,6 +243,13 @@ config ZMK_RGB_UNDERGLOW_ON_START
|
|||
bool "RGB underglow starts on by default"
|
||||
default y
|
||||
|
||||
config ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE
|
||||
bool "Turn off RGB underglow when keyboard goes into idle state"
|
||||
|
||||
config ZMK_RGB_UNDERGLOW_AUTO_OFF_USB
|
||||
bool "Turn off RGB underglow when USB is disconnected"
|
||||
depends on USB_DEVICE_STACK
|
||||
|
||||
#ZMK_RGB_UNDERGLOW
|
||||
endif
|
||||
|
||||
|
|
|
@ -29,23 +29,23 @@
|
|||
compatible = "zmk,kscan-gpio-direct";
|
||||
label = "KSCAN";
|
||||
input-gpios =
|
||||
<&pro_micro_d 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro_d 0 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro_a 0 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro_d 16 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro_a 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro_d 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro_d 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro_a 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro_d 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro_a 2 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro_d 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro_d 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro_d 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro_d 15 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro_d 10 (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)>
|
||||
<&pro_micro 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro 0 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro 18 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro 16 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro 21 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro 19 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro 20 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro 15 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro 10 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>,
|
||||
<&pro_micro 9 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
;
|
||||
};
|
||||
|
||||
|
|
|
@ -28,12 +28,6 @@ endif # ZMK_DISPLAY
|
|||
|
||||
if LVGL
|
||||
|
||||
config LVGL_HOR_RES_MAX
|
||||
default 128
|
||||
|
||||
config LVGL_VER_RES_MAX
|
||||
default 32
|
||||
|
||||
config LVGL_VDB_SIZE
|
||||
default 64
|
||||
|
||||
|
|
|
@ -11,23 +11,23 @@ Some revisions of the aforementioned PCBs have slightly different pin arrangemen
|
|||
/* The position of Q and B keys have been swapped */
|
||||
&kscan0 {
|
||||
input-gpios
|
||||
= <&pro_micro_d 6 (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_d 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro_d 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro_d 7 (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)>
|
||||
= <&pro_micro 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 18 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 19 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 20 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 21 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 15 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 16 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 10 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 2 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 9 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
;
|
||||
};
|
||||
```
|
||||
|
|
|
@ -31,12 +31,6 @@ endif # ZMK_DISPLAY
|
|||
|
||||
if LVGL
|
||||
|
||||
config LVGL_HOR_RES_MAX
|
||||
default 128
|
||||
|
||||
config LVGL_VER_RES_MAX
|
||||
default 32
|
||||
|
||||
config LVGL_VDB_SIZE
|
||||
default 64
|
||||
|
||||
|
|
|
@ -29,12 +29,6 @@ endif # ZMK_DISPLAY
|
|||
|
||||
if LVGL
|
||||
|
||||
config LVGL_HOR_RES_MAX
|
||||
default 128
|
||||
|
||||
config LVGL_VER_RES_MAX
|
||||
default 32
|
||||
|
||||
config LVGL_VDB_SIZE
|
||||
default 64
|
||||
|
||||
|
|
|
@ -21,12 +21,6 @@ endif # ZMK_DISPLAY
|
|||
|
||||
if LVGL
|
||||
|
||||
config LVGL_HOR_RES_MAX
|
||||
default 128
|
||||
|
||||
config LVGL_VER_RES_MAX
|
||||
default 32
|
||||
|
||||
config LVGL_VDB_SIZE
|
||||
default 64
|
||||
|
||||
|
|
|
@ -29,12 +29,6 @@ endif # ZMK_DISPLAY
|
|||
|
||||
if LVGL
|
||||
|
||||
config LVGL_HOR_RES_MAX
|
||||
default 128
|
||||
|
||||
config LVGL_VER_RES_MAX
|
||||
default 64
|
||||
|
||||
config LVGL_VDB_SIZE
|
||||
default 64
|
||||
|
||||
|
|
|
@ -31,11 +31,6 @@ endif # ZMK_DISPLAY
|
|||
|
||||
if LVGL
|
||||
|
||||
config LVGL_HOR_RES_MAX
|
||||
default 128
|
||||
|
||||
config LVGL_VER_RES_MAX
|
||||
default 32
|
||||
|
||||
config LVGL_VDB_SIZE
|
||||
default 64
|
||||
|
|
|
@ -29,12 +29,6 @@ endif # ZMK_DISPLAY
|
|||
|
||||
if LVGL
|
||||
|
||||
config LVGL_HOR_RES_MAX
|
||||
default 128
|
||||
|
||||
config LVGL_VER_RES_MAX
|
||||
default 32
|
||||
|
||||
config LVGL_VDB_SIZE
|
||||
default 64
|
||||
|
||||
|
|
|
@ -31,12 +31,6 @@ endif # ZMK_DISPLAY
|
|||
|
||||
if LVGL
|
||||
|
||||
config LVGL_HOR_RES_MAX
|
||||
default 128
|
||||
|
||||
config LVGL_VER_RES_MAX
|
||||
default 32
|
||||
|
||||
config LVGL_VDB_SIZE
|
||||
default 64
|
||||
|
||||
|
|
|
@ -31,12 +31,6 @@ endif # ZMK_DISPLAY
|
|||
|
||||
if LVGL
|
||||
|
||||
config LVGL_HOR_RES_MAX
|
||||
default 128
|
||||
|
||||
config LVGL_VER_RES_MAX
|
||||
default 32
|
||||
|
||||
config LVGL_VDB_SIZE
|
||||
default 64
|
||||
|
||||
|
|
|
@ -21,12 +21,6 @@ endif # ZMK_DISPLAY
|
|||
|
||||
if LVGL
|
||||
|
||||
config LVGL_HOR_RES_MAX
|
||||
default 128
|
||||
|
||||
config LVGL_VER_RES_MAX
|
||||
default 32
|
||||
|
||||
config LVGL_VDB_SIZE
|
||||
default 64
|
||||
|
||||
|
|
|
@ -25,12 +25,6 @@ endif # ZMK_DISPLAY
|
|||
|
||||
if LVGL
|
||||
|
||||
config LVGL_HOR_RES_MAX
|
||||
default 128
|
||||
|
||||
config LVGL_VER_RES_MAX
|
||||
default 32
|
||||
|
||||
config LVGL_VDB_SIZE
|
||||
default 64
|
||||
|
||||
|
|
9
app/boards/shields/pancake/Kconfig.defconfig
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if SHIELD_PANCAKE
|
||||
|
||||
config ZMK_KEYBOARD_NAME
|
||||
default "Pancake"
|
||||
|
||||
endif
|
5
app/boards/shields/pancake/Kconfig.shield
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config SHIELD_PANCAKE
|
||||
def_bool $(shields_list_contains,pancake)
|
1
app/boards/shields/pancake/pancake.conf
Normal file
|
@ -0,0 +1 @@
|
|||
# CONFIG_ZMK_USB_LOGGING=y
|
57
app/boards/shields/pancake/pancake.keymap
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/bt.h>
|
||||
#include <dt-bindings/zmk/outputs.h>
|
||||
|
||||
#define DEF 0
|
||||
#define LWR 1
|
||||
#define RSE 2
|
||||
#define FNC 3
|
||||
|
||||
/ {
|
||||
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 BSPC
|
||||
&kp TAB &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SQT &kp SEMI
|
||||
&kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp UP &kp ENTER
|
||||
&kp LCTRL &kp LALT &kp LGUI &mo FNC &mo LWR &kp SPACE &kp SPACE &mo RSE &kp SLASH &kp LEFT &kp DOWN &kp RIGHT
|
||||
>;
|
||||
};
|
||||
|
||||
lower_layer {
|
||||
bindings = <
|
||||
&kp TILDE &kp EXCL &kp AT &kp HASH &kp DLLR &kp PRCNT &kp CARET &kp AMPS &kp STAR &kp LPAR &kp RPAR &kp BSPC
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &kp UNDER &kp PLUS &trans &trans
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &kp LBRC &kp RBRC &kp C_VOL_UP &trans
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &kp QMARK &trans &kp C_VOL_DN &trans
|
||||
>;
|
||||
};
|
||||
|
||||
raise_layer {
|
||||
bindings = <
|
||||
&kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp BSPC
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &kp MINUS &kp EQUAL &trans &kp BSLH
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &kp LBKT &kp RBKT &kp C_VOL_UP &trans
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &kp C_VOL_DN &trans
|
||||
>;
|
||||
};
|
||||
|
||||
function_layer {
|
||||
bindings = <
|
||||
&bootloader &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &trans
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &kp MINUS &kp F11 &kp F12 &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
|
||||
&out OUT_BLE &out OUT_USB &out OUT_TOG &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
39
app/boards/shields/pancake/pancake.overlay
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,kscan = &kscan0;
|
||||
};
|
||||
|
||||
kscan0: kscan_0 {
|
||||
compatible = "zmk,kscan-gpio-matrix";
|
||||
label = "KSCAN";
|
||||
diode-direction = "col2row";
|
||||
|
||||
col-gpios
|
||||
= <&pro_micro 21 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 20 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 19 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 18 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 7 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 8 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 9 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 6 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 5 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 4 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 3 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 2 GPIO_ACTIVE_HIGH>
|
||||
;
|
||||
|
||||
row-gpios
|
||||
= <&pro_micro 15 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 14 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 16 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 10 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
;
|
||||
};
|
||||
};
|
8
app/boards/shields/pancake/pancake.zmk.yml
Normal file
|
@ -0,0 +1,8 @@
|
|||
file_format: "1"
|
||||
id: pancake
|
||||
name: Pancake
|
||||
type: shield
|
||||
url: https://mkultra.click/pancake-keyboard-kit
|
||||
requires: [pro_micro]
|
||||
features:
|
||||
- keys
|
|
@ -31,12 +31,6 @@ endif # ZMK_DISPLAY
|
|||
|
||||
if LVGL
|
||||
|
||||
config LVGL_HOR_RES_MAX
|
||||
default 128
|
||||
|
||||
config LVGL_VER_RES_MAX
|
||||
default 32
|
||||
|
||||
config LVGL_VDB_SIZE
|
||||
default 64
|
||||
|
||||
|
|
|
@ -22,12 +22,6 @@ endif # ZMK_DISPLAY
|
|||
|
||||
if LVGL
|
||||
|
||||
config LVGL_HOR_RES_MAX
|
||||
default 128
|
||||
|
||||
config LVGL_VER_RES_MAX
|
||||
default 32
|
||||
|
||||
config LVGL_VDB_SIZE
|
||||
default 64
|
||||
|
||||
|
|
31
app/boards/shields/two_percent_milk/boards/nice_nano.overlay
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include <dt-bindings/led/led.h>
|
||||
|
||||
&spi1 {
|
||||
compatible = "nordic,nrf-spim";
|
||||
status = "okay";
|
||||
mosi-pin = <9>;
|
||||
// Unused pins, needed for SPI definition, but not used by the ws2812 driver itself.
|
||||
sck-pin = <5>;
|
||||
miso-pin = <7>;
|
||||
|
||||
led_strip: ws2812@0 {
|
||||
compatible = "worldsemi,ws2812-spi";
|
||||
label = "WS2812";
|
||||
|
||||
/* SPI */
|
||||
reg = <0>; /* ignored, but necessary for SPI bindings */
|
||||
spi-max-frequency = <4000000>;
|
||||
|
||||
/* WS2812 */
|
||||
chain-length = <2>;
|
||||
spi-one-frame = <0x70>;
|
||||
spi-zero-frame = <0x40>;
|
||||
color-mapping = <LED_COLOR_ID_GREEN LED_COLOR_ID_RED LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
};
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,underglow = &led_strip;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,31 @@
|
|||
#include <dt-bindings/led/led.h>
|
||||
|
||||
&spi1 {
|
||||
compatible = "nordic,nrf-spim";
|
||||
status = "okay";
|
||||
mosi-pin = <9>;
|
||||
// Unused pins, needed for SPI definition, but not used by the ws2812 driver itself.
|
||||
sck-pin = <5>;
|
||||
miso-pin = <7>;
|
||||
|
||||
led_strip: ws2812@0 {
|
||||
compatible = "worldsemi,ws2812-spi";
|
||||
label = "WS2812";
|
||||
|
||||
/* SPI */
|
||||
reg = <0>; /* ignored, but necessary for SPI bindings */
|
||||
spi-max-frequency = <4000000>;
|
||||
|
||||
/* WS2812 */
|
||||
chain-length = <2>;
|
||||
spi-one-frame = <0x70>;
|
||||
spi-zero-frame = <0x40>;
|
||||
color-mapping = <LED_COLOR_ID_GREEN LED_COLOR_ID_RED LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
};
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,underglow = &led_strip;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
#include <dt-bindings/led/led.h>
|
||||
|
||||
&spi1 {
|
||||
compatible = "nordic,nrf-spim";
|
||||
status = "okay";
|
||||
mosi-pin = <43>;
|
||||
// Unused pins, needed for SPI definition, but not used by the ws2812 driver itself.
|
||||
sck-pin = <12>; // 0.12 is not broken out on the nRFMicro
|
||||
miso-pin = <22>; // 0.22 is not broken out on the nRFMicro
|
||||
|
||||
led_strip: ws2812@0 {
|
||||
compatible = "worldsemi,ws2812-spi";
|
||||
label = "WS2812";
|
||||
|
||||
/* SPI */
|
||||
reg = <0>; /* ignored, but necessary for SPI bindings */
|
||||
spi-max-frequency = <4000000>;
|
||||
|
||||
/* WS2812 */
|
||||
chain-length = <2>;
|
||||
spi-one-frame = <0x70>;
|
||||
spi-zero-frame = <0x40>;
|
||||
color-mapping = <LED_COLOR_ID_GREEN LED_COLOR_ID_RED LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
};
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,underglow = &led_strip;
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#include <dt-bindings/led/led.h>
|
||||
|
||||
&spi1 {
|
||||
compatible = "nordic,nrf-spim";
|
||||
status = "okay";
|
||||
mosi-pin = <38>;
|
||||
// Unused pins, needed for SPI definition, but not used by the ws2812 driver itself.
|
||||
sck-pin = <12>; // 0.12 is not broken out on the nRFMicro
|
||||
miso-pin = <22>; // 0.22 is not broken out on the nRFMicro
|
||||
|
||||
led_strip: ws2812@0 {
|
||||
compatible = "worldsemi,ws2812-spi";
|
||||
label = "WS2812";
|
||||
|
||||
/* SPI */
|
||||
reg = <0>; /* ignored, but necessary for SPI bindings */
|
||||
spi-max-frequency = <4000000>;
|
||||
|
||||
/* WS2812 */
|
||||
chain-length = <2>;
|
||||
spi-one-frame = <0x70>;
|
||||
spi-zero-frame = <0x40>;
|
||||
color-mapping = <LED_COLOR_ID_GREEN LED_COLOR_ID_RED LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
};
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,underglow = &led_strip;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,31 @@
|
|||
#include <dt-bindings/led/led.h>
|
||||
|
||||
&spi1 {
|
||||
compatible = "nordic,nrf-spim";
|
||||
status = "okay";
|
||||
mosi-pin = <43>;
|
||||
// Unused pins, needed for SPI definition, but not used by the ws2812 driver itself.
|
||||
sck-pin = <12>; // 0.12 is not broken out on the nRFMicro
|
||||
miso-pin = <22>; // 0.22 is not broken out on the nRFMicro
|
||||
|
||||
led_strip: ws2812@0 {
|
||||
compatible = "worldsemi,ws2812-spi";
|
||||
label = "WS2812";
|
||||
|
||||
/* SPI */
|
||||
reg = <0>; /* ignored, but necessary for SPI bindings */
|
||||
spi-max-frequency = <4000000>;
|
||||
|
||||
/* WS2812 */
|
||||
chain-length = <2>;
|
||||
spi-one-frame = <0x70>;
|
||||
spi-zero-frame = <0x40>;
|
||||
color-mapping = <LED_COLOR_ID_GREEN LED_COLOR_ID_RED LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
};
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,underglow = &led_strip;
|
||||
};
|
||||
};
|
|
@ -1,2 +1,9 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
# Uncomment the following lines to enable RGB Underglow
|
||||
# CONFIG_ZMK_RGB_UNDERGLOW=y
|
||||
# CONFIG_WS2812_STRIP=y
|
||||
|
||||
# Uncomment the following line to turn on logging, and set ZMK logging to debug output
|
||||
# CONFIG_ZMK_USB_LOGGING=y
|
|
@ -4,19 +4,19 @@
|
|||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/bt.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/bt.h>
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&kp X
|
||||
&kp Z
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
default_layer {
|
||||
bindings = <
|
||||
&kp X
|
||||
&kp Z
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -31,12 +31,6 @@ endif # ZMK_DISPLAY
|
|||
|
||||
if LVGL
|
||||
|
||||
config LVGL_HOR_RES_MAX
|
||||
default 128
|
||||
|
||||
config LVGL_VER_RES_MAX
|
||||
default 64
|
||||
|
||||
config LVGL_VDB_SIZE
|
||||
default 64
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ if(DEFINED SHIELD)
|
|||
while(NOT S_PIECES STREQUAL "")
|
||||
list(POP_BACK S_PIECES)
|
||||
list(JOIN S_PIECES "_" s_substr)
|
||||
if ("%{s_substr}" STREQUAL "" OR "${s_substr}" STREQUAL ${shield_dir_name})
|
||||
if ("${s_substr}" STREQUAL "" OR "${s_substr}" STREQUAL "${shield_dir_name}")
|
||||
break()
|
||||
endif()
|
||||
list(APPEND shield_candidate_names ${s_substr})
|
||||
|
|
|
@ -115,28 +115,6 @@ static int il0323_update_display(const struct device *dev) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int il0323_blanking_off(const struct device *dev) {
|
||||
struct il0323_data *driver = dev->data;
|
||||
|
||||
if (blanking_on) {
|
||||
/* Update EPD pannel in normal mode */
|
||||
il0323_busy_wait(driver);
|
||||
if (il0323_update_display(dev)) {
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
blanking_on = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int il0323_blanking_on(const struct device *dev) {
|
||||
blanking_on = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int il0323_write(const struct device *dev, const uint16_t x, const uint16_t y,
|
||||
const struct display_buffer_descriptor *desc, const void *buf) {
|
||||
struct il0323_data *driver = dev->data;
|
||||
|
@ -208,6 +186,58 @@ static int il0323_read(const struct device *dev, const uint16_t x, const uint16_
|
|||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int il0323_clear_and_write_buffer(const struct device *dev, uint8_t pattern, bool update) {
|
||||
struct display_buffer_descriptor desc = {
|
||||
.buf_size = IL0323_NUMOF_PAGES,
|
||||
.width = EPD_PANEL_WIDTH,
|
||||
.height = 1,
|
||||
.pitch = EPD_PANEL_WIDTH,
|
||||
};
|
||||
uint8_t *line;
|
||||
|
||||
line = k_malloc(IL0323_NUMOF_PAGES);
|
||||
if (line == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(line, pattern, IL0323_NUMOF_PAGES);
|
||||
for (int i = 0; i < EPD_PANEL_HEIGHT; i++) {
|
||||
il0323_write(dev, 0, i, &desc, line);
|
||||
}
|
||||
|
||||
k_free(line);
|
||||
|
||||
if (update == true) {
|
||||
if (il0323_update_display(dev)) {
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int il0323_blanking_off(const struct device *dev) {
|
||||
struct il0323_data *driver = dev->data;
|
||||
|
||||
if (blanking_on) {
|
||||
/* Update EPD pannel in normal mode */
|
||||
il0323_busy_wait(driver);
|
||||
if (il0323_clear_and_write_buffer(dev, 0xff, true)) {
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
blanking_on = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int il0323_blanking_on(const struct device *dev) {
|
||||
blanking_on = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *il0323_get_framebuffer(const struct device *dev) {
|
||||
LOG_ERR("not supported");
|
||||
return NULL;
|
||||
|
@ -247,36 +277,6 @@ static int il0323_set_pixel_format(const struct device *dev, const enum display_
|
|||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int il0323_clear_and_write_buffer(const struct device *dev, uint8_t pattern, bool update) {
|
||||
struct display_buffer_descriptor desc = {
|
||||
.buf_size = IL0323_NUMOF_PAGES,
|
||||
.width = EPD_PANEL_WIDTH,
|
||||
.height = 1,
|
||||
.pitch = EPD_PANEL_WIDTH,
|
||||
};
|
||||
uint8_t *line;
|
||||
|
||||
line = k_malloc(IL0323_NUMOF_PAGES);
|
||||
if (line == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(line, pattern, IL0323_NUMOF_PAGES);
|
||||
for (int i = 0; i < EPD_PANEL_HEIGHT; i++) {
|
||||
il0323_write(dev, 0, i, &desc, line);
|
||||
}
|
||||
|
||||
k_free(line);
|
||||
|
||||
if (update == true) {
|
||||
if (il0323_update_display(dev)) {
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int il0323_controller_init(const struct device *dev) {
|
||||
struct il0323_data *driver = dev->data;
|
||||
uint8_t tmp[IL0323_TRES_REG_LENGTH];
|
||||
|
@ -350,10 +350,6 @@ static int il0323_controller_init(const struct device *dev) {
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
if (il0323_clear_and_write_buffer(dev, 0xff, false)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -429,4 +425,4 @@ static struct display_driver_api il0323_driver_api = {
|
|||
};
|
||||
|
||||
DEVICE_DT_INST_DEFINE(0, il0323_init, NULL, &il0323_driver, NULL, POST_KERNEL,
|
||||
CONFIG_APPLICATION_INIT_PRIORITY, &il0323_driver_api);
|
||||
CONFIG_APPLICATION_INIT_PRIORITY, &il0323_driver_api);
|
||||
|
|
|
@ -30,6 +30,20 @@ config ZMK_KSCAN_GPIO_MATRIX
|
|||
default $(dt_compat_enabled,$(DT_COMPAT_ZMK_KSCAN_GPIO_MATRIX))
|
||||
select ZMK_KSCAN_GPIO_DRIVER
|
||||
|
||||
if ZMK_KSCAN_GPIO_MATRIX
|
||||
|
||||
config ZMK_KSCAN_MATRIX_WAIT_BETWEEN_OUTPUTS
|
||||
int "Ticks to wait between each output when scanning"
|
||||
default 0
|
||||
help
|
||||
When iterating over each output to drive it active, read inputs, then set
|
||||
inactive again, some boards may take time for the previous output to
|
||||
"settle" before reading inputs for the next active output column. In that
|
||||
scenario, set this value to a positive value to configure the number of
|
||||
usecs to wait after reading each column of keys.
|
||||
|
||||
endif # ZMK_KSCAN_GPIO_MATRIX
|
||||
|
||||
config ZMK_KSCAN_MOCK_DRIVER
|
||||
bool
|
||||
default $(dt_compat_enabled,$(DT_COMPAT_ZMK_KSCAN_MOCK))
|
||||
|
|
|
@ -250,6 +250,10 @@ static int kscan_matrix_read(const struct device *dev) {
|
|||
LOG_ERR("Failed to set output %i inactive: %i", o, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
#if CONFIG_ZMK_KSCAN_MATRIX_WAIT_BETWEEN_OUTPUTS > 0
|
||||
k_busy_wait(CONFIG_ZMK_KSCAN_MATRIX_WAIT_BETWEEN_OUTPUTS);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Process the new state.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
description: Keyboard Reset Behavior
|
||||
description: Mod Morph Behavior
|
||||
|
||||
compatible: "zmk,behavior-mod-morph"
|
||||
|
||||
|
|
|
@ -91,7 +91,9 @@ static int zmk_backlight_init(const struct device *_arg) {
|
|||
LOG_ERR("Failed to load backlight settings: %d", rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB)
|
||||
state.on = zmk_usb_is_powered();
|
||||
#endif
|
||||
return zmk_backlight_update();
|
||||
}
|
||||
|
||||
|
|
|
@ -612,6 +612,10 @@ static int position_state_changed_listener(const zmk_event_t *eh) {
|
|||
decide_hold_tap(undecided_hold_tap, HT_TIMER_EVENT);
|
||||
}
|
||||
|
||||
if (undecided_hold_tap == NULL) {
|
||||
return ZMK_EV_EVENT_BUBBLE;
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -211,7 +211,7 @@ static int filter_timed_out_candidates(int64_t timestamp) {
|
|||
if (candidate->timeout_at > timestamp) {
|
||||
// reorder candidates so they're contiguous
|
||||
candidates[num_candidates].combo = candidate->combo;
|
||||
candidates[num_candidates].timeout_at = candidates->timeout_at;
|
||||
candidates[num_candidates].timeout_at = candidate->timeout_at;
|
||||
num_candidates++;
|
||||
} else {
|
||||
candidate->combo = NULL;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define DT_DRV_COMPAT zmk_conditional_layers
|
||||
|
||||
#include <stdint.h>
|
||||
#include <kernel.h>
|
||||
|
||||
#include <devicetree.h>
|
||||
#include <logging/log.h>
|
||||
|
@ -19,6 +20,8 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||
|
||||
static K_SEM_DEFINE(conditional_layer_sem, 1, 1);
|
||||
|
||||
// Conditional layer configuration that activates the specified then-layer when all if-layers are
|
||||
// active. With two if-layers, this is referred to as "tri-layer", and is commonly used to activate
|
||||
// a third "adjust" layer if and only if the "lower" and "raise" layers are both active.
|
||||
|
@ -66,22 +69,53 @@ static void conditional_layer_deactivate(int8_t layer) {
|
|||
}
|
||||
}
|
||||
|
||||
// On layer state changes, examines each conditional layer config to determine if then-layer in the
|
||||
// config should activate based on the currently active set of if-layers.
|
||||
static int layer_state_changed_listener(const zmk_event_t *ev) {
|
||||
for (int i = 0; i < NUM_CONDITIONAL_LAYER_CFGS; i++) {
|
||||
const struct conditional_layer_cfg *cfg = CONDITIONAL_LAYER_CFGS + i;
|
||||
zmk_keymap_layers_state_t mask = cfg->if_layers_state_mask;
|
||||
static bool conditional_layer_updates_needed;
|
||||
|
||||
// Activate then-layer if and only if all if-layers are already active. Note that we
|
||||
// reevaluate the current layer state for each config since activation of one layer can also
|
||||
// trigger activation of another.
|
||||
if ((zmk_keymap_layer_state() & mask) == mask) {
|
||||
conditional_layer_activate(cfg->then_layer);
|
||||
} else {
|
||||
conditional_layer_deactivate(cfg->then_layer);
|
||||
conditional_layer_updates_needed = true;
|
||||
|
||||
// Semaphore ensures we don't re-enter the loop in the middle of doing update, and
|
||||
// ensures that "waterfalling layer updates" are all processed to trigger subsequent
|
||||
// nested conditional layers properly.
|
||||
if (k_sem_take(&conditional_layer_sem, K_NO_WAIT) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (conditional_layer_updates_needed) {
|
||||
int8_t max_then_layer = -1;
|
||||
uint32_t then_layers = 0;
|
||||
uint32_t then_layer_state = 0;
|
||||
|
||||
conditional_layer_updates_needed = false;
|
||||
|
||||
// On layer state changes, examines each conditional layer config to determine if then-layer
|
||||
// in the config should activate based on the currently active set of if-layers.
|
||||
for (int i = 0; i < NUM_CONDITIONAL_LAYER_CFGS; i++) {
|
||||
const struct conditional_layer_cfg *cfg = CONDITIONAL_LAYER_CFGS + i;
|
||||
zmk_keymap_layers_state_t mask = cfg->if_layers_state_mask;
|
||||
then_layers |= BIT(cfg->then_layer);
|
||||
max_then_layer = MAX(max_then_layer, cfg->then_layer);
|
||||
|
||||
// Activate then-layer if and only if all if-layers are already active. Note that we
|
||||
// reevaluate the current layer state for each config since activation of one layer can
|
||||
// also trigger activation of another.
|
||||
if ((zmk_keymap_layer_state() & mask) == mask) {
|
||||
then_layer_state |= BIT(cfg->then_layer);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t layer = 0; layer <= max_then_layer; layer++) {
|
||||
if ((BIT(layer) & then_layers) != 0U) {
|
||||
if ((BIT(layer) & then_layer_state) != 0U) {
|
||||
conditional_layer_activate(layer);
|
||||
} else {
|
||||
conditional_layer_deactivate(layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
k_sem_give(&conditional_layer_sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,10 @@ menuconfig ZMK_DISPLAY
|
|||
|
||||
if ZMK_DISPLAY
|
||||
|
||||
config ZMK_DISPLAY_BLANK_ON_IDLE
|
||||
bool "Blank display on idle"
|
||||
default y
|
||||
|
||||
choice LVGL_TXT_ENC
|
||||
default LVGL_TXT_ENC_UTF8
|
||||
|
||||
|
|
|
@ -85,26 +85,20 @@ static void stop_display_updates() {
|
|||
|
||||
int zmk_display_is_initialized() { return initialized; }
|
||||
|
||||
int zmk_display_init() {
|
||||
void initialize_display(struct k_work *work) {
|
||||
LOG_DBG("");
|
||||
|
||||
display = device_get_binding(ZMK_DISPLAY_NAME);
|
||||
if (display == NULL) {
|
||||
LOG_ERR("Failed to find display device");
|
||||
return -EINVAL;
|
||||
return;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_DISPLAY_WORK_QUEUE_DEDICATED)
|
||||
k_work_queue_start(&display_work_q, display_work_stack_area,
|
||||
K_THREAD_STACK_SIZEOF(display_work_stack_area),
|
||||
CONFIG_ZMK_DISPLAY_DEDICATED_THREAD_PRIORITY, NULL);
|
||||
#endif
|
||||
|
||||
screen = zmk_display_status_screen();
|
||||
|
||||
if (screen == NULL) {
|
||||
LOG_ERR("No status screen provided");
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
lv_scr_load(screen);
|
||||
|
@ -112,11 +106,24 @@ int zmk_display_init() {
|
|||
start_display_updates();
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
K_WORK_DEFINE(init_work, initialize_display);
|
||||
|
||||
int zmk_display_init() {
|
||||
#if IS_ENABLED(CONFIG_ZMK_DISPLAY_WORK_QUEUE_DEDICATED)
|
||||
k_work_queue_start(&display_work_q, display_work_stack_area,
|
||||
K_THREAD_STACK_SIZEOF(display_work_stack_area),
|
||||
CONFIG_ZMK_DISPLAY_DEDICATED_THREAD_PRIORITY, NULL);
|
||||
#endif
|
||||
|
||||
k_work_submit_to_queue(zmk_display_work_q(), &init_work);
|
||||
|
||||
LOG_DBG("");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_DISPLAY_BLANK_ON_IDLE)
|
||||
int display_event_handler(const zmk_event_t *eh) {
|
||||
struct zmk_activity_state_changed *ev = as_zmk_activity_state_changed(eh);
|
||||
if (ev == NULL) {
|
||||
|
@ -140,3 +147,5 @@ int display_event_handler(const zmk_event_t *eh) {
|
|||
|
||||
ZMK_LISTENER(display, display_event_handler);
|
||||
ZMK_SUBSCRIPTION(display, zmk_activity_state_changed);
|
||||
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_DISPLAY_BLANK_ON_IDLE) */
|
|
@ -76,7 +76,7 @@ ZMK_SUBSCRIPTION(widget_battery_status, zmk_usb_conn_state_changed);
|
|||
int zmk_widget_battery_status_init(struct zmk_widget_battery_status *widget, lv_obj_t *parent) {
|
||||
widget->obj = lv_label_create(parent, NULL);
|
||||
|
||||
lv_obj_set_size(widget->obj, 40, 15);
|
||||
lv_obj_set_size(widget->obj, 43, 15);
|
||||
|
||||
sys_slist_append(&widgets, &widget->node);
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ int zmk_event_manager_handle_from(zmk_event_t *event, uint8_t start_index) {
|
|||
if (ev_sub->event_type != event->event) {
|
||||
continue;
|
||||
}
|
||||
event->last_listener_index = i;
|
||||
ret = ev_sub->listener->callback(event);
|
||||
switch (ret) {
|
||||
case ZMK_EV_EVENT_BUBBLE:
|
||||
|
@ -35,7 +36,6 @@ int zmk_event_manager_handle_from(zmk_event_t *event, uint8_t start_index) {
|
|||
goto release;
|
||||
case ZMK_EV_EVENT_CAPTURED:
|
||||
LOG_DBG("Listener captured the event");
|
||||
event->last_listener_index = i;
|
||||
// Listeners are expected to free events they capture
|
||||
return 0;
|
||||
default:
|
||||
|
|
|
@ -19,6 +19,12 @@
|
|||
|
||||
#include <zmk/rgb_underglow.h>
|
||||
|
||||
#include <zmk/activity.h>
|
||||
#include <zmk/usb.h>
|
||||
#include <zmk/event_manager.h>
|
||||
#include <zmk/events/activity_state_changed.h>
|
||||
#include <zmk/events/usb_conn_state_changed.h>
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#define STRIP_LABEL DT_LABEL(DT_CHOSEN(zmk_underglow))
|
||||
|
@ -265,7 +271,13 @@ static int zmk_rgb_underglow_init(const struct device *_arg) {
|
|||
settings_load_subtree("rgb/underglow");
|
||||
#endif
|
||||
|
||||
k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50));
|
||||
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB)
|
||||
state.on = zmk_usb_is_powered();
|
||||
#endif
|
||||
|
||||
if (state.on) {
|
||||
k_timer_start(&underglow_tick, K_NO_WAIT, K_MSEC(50));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -444,4 +456,53 @@ int zmk_rgb_underglow_change_spd(int direction) {
|
|||
return zmk_rgb_underglow_save_state();
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE) || \
|
||||
IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB)
|
||||
static int rgb_underglow_auto_state(bool *prev_state, bool new_state) {
|
||||
if (state.on == new_state) {
|
||||
return 0;
|
||||
}
|
||||
if (new_state) {
|
||||
state.on = *prev_state;
|
||||
*prev_state = false;
|
||||
return zmk_rgb_underglow_on();
|
||||
} else {
|
||||
state.on = false;
|
||||
*prev_state = true;
|
||||
return zmk_rgb_underglow_off();
|
||||
}
|
||||
}
|
||||
|
||||
static int rgb_underglow_event_listener(const zmk_event_t *eh) {
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE)
|
||||
if (as_zmk_activity_state_changed(eh)) {
|
||||
static bool prev_state = false;
|
||||
return rgb_underglow_auto_state(&prev_state,
|
||||
zmk_activity_get_state() == ZMK_ACTIVITY_ACTIVE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB)
|
||||
if (as_zmk_usb_conn_state_changed(eh)) {
|
||||
static bool prev_state = false;
|
||||
return rgb_underglow_auto_state(&prev_state, zmk_usb_is_powered());
|
||||
}
|
||||
#endif
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
ZMK_LISTENER(rgb_underglow, rgb_underglow_event_listener);
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE) ||
|
||||
// IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB)
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE)
|
||||
ZMK_SUBSCRIPTION(rgb_underglow, zmk_activity_state_changed);
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB)
|
||||
ZMK_SUBSCRIPTION(rgb_underglow, zmk_usb_conn_state_changed);
|
||||
#endif
|
||||
|
||||
SYS_INIT(zmk_rgb_underglow_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
||||
|
|
|
@ -54,6 +54,16 @@ static const struct bt_uuid_128 split_service_uuid = BT_UUID_INIT_128(ZMK_SPLIT_
|
|||
K_MSGQ_DEFINE(peripheral_event_msgq, sizeof(struct zmk_position_state_changed),
|
||||
CONFIG_ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE, 4);
|
||||
|
||||
void peripheral_event_work_callback(struct k_work *work) {
|
||||
struct zmk_position_state_changed ev;
|
||||
while (k_msgq_get(&peripheral_event_msgq, &ev, K_NO_WAIT) == 0) {
|
||||
LOG_DBG("Trigger key position state change for %d", ev.position);
|
||||
ZMK_EVENT_RAISE(new_zmk_position_state_changed(ev));
|
||||
}
|
||||
}
|
||||
|
||||
K_WORK_DEFINE(peripheral_event_work, peripheral_event_work_callback);
|
||||
|
||||
int peripheral_slot_index_for_conn(struct bt_conn *conn) {
|
||||
for (int i = 0; i < ZMK_BLE_SPLIT_PERIPHERAL_COUNT; i++) {
|
||||
if (peripherals[i].conn == conn) {
|
||||
|
@ -92,6 +102,22 @@ int release_peripheral_slot(int index) {
|
|||
}
|
||||
slot->state = PERIPHERAL_SLOT_STATE_OPEN;
|
||||
|
||||
// Raise events releasing any active positions from this peripheral
|
||||
for (int i = 0; i < POSITION_STATE_DATA_LEN; i++) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if (slot->position_state[i] & BIT(j)) {
|
||||
uint32_t position = (i * 8) + j;
|
||||
struct zmk_position_state_changed ev = {.source = index,
|
||||
.position = position,
|
||||
.state = false,
|
||||
.timestamp = k_uptime_get()};
|
||||
|
||||
k_msgq_put(&peripheral_event_msgq, &ev, K_NO_WAIT);
|
||||
k_work_submit(&peripheral_event_work);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < POSITION_STATE_DATA_LEN; i++) {
|
||||
slot->position_state[i] = 0U;
|
||||
slot->changed_positions[i] = 0U;
|
||||
|
@ -136,16 +162,6 @@ int confirm_peripheral_slot_conn(struct bt_conn *conn) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void peripheral_event_work_callback(struct k_work *work) {
|
||||
struct zmk_position_state_changed ev;
|
||||
while (k_msgq_get(&peripheral_event_msgq, &ev, K_NO_WAIT) == 0) {
|
||||
LOG_DBG("Trigger key position state change for %d", ev.position);
|
||||
ZMK_EVENT_RAISE(new_zmk_position_state_changed(ev));
|
||||
}
|
||||
}
|
||||
|
||||
K_WORK_DEFINE(peripheral_event_work, peripheral_event_work_callback);
|
||||
|
||||
static uint8_t split_central_notify_func(struct bt_conn *conn,
|
||||
struct bt_gatt_subscribe_params *params, const void *data,
|
||||
uint16_t length) {
|
||||
|
|
|
@ -31,16 +31,16 @@ enum usb_dc_status_code zmk_usb_get_status() { return usb_status; }
|
|||
enum zmk_usb_conn_state zmk_usb_get_conn_state() {
|
||||
LOG_DBG("state: %d", usb_status);
|
||||
switch (usb_status) {
|
||||
case USB_DC_SUSPEND:
|
||||
case USB_DC_CONFIGURED:
|
||||
return ZMK_USB_CONN_HID;
|
||||
|
||||
case USB_DC_DISCONNECTED:
|
||||
case USB_DC_UNKNOWN:
|
||||
return ZMK_USB_CONN_NONE;
|
||||
|
||||
case USB_DC_ERROR:
|
||||
case USB_DC_RESET:
|
||||
return ZMK_USB_CONN_POWERED;
|
||||
|
||||
default:
|
||||
return ZMK_USB_CONN_HID;
|
||||
return ZMK_USB_CONN_POWERED;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
1
app/tests/combo/combos-and-holdtaps-3/events.patterns
Normal file
|
@ -0,0 +1 @@
|
|||
s/.*hid_listener_keycode_//p
|
|
@ -0,0 +1,5 @@
|
|||
pressed: usage_page 0x07 keycode 0xE5 implicit_mods 0x00 explicit_mods 0x00
|
||||
pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
||||
pressed: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x06 implicit_mods 0x00 explicit_mods 0x00
|
40
app/tests/combo/combos-and-holdtaps-3/native_posix_64.keymap
Normal file
|
@ -0,0 +1,40 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan-mock.h>
|
||||
|
||||
&mt {
|
||||
flavor = "hold-preferred";
|
||||
};
|
||||
|
||||
/ {
|
||||
combos {
|
||||
compatible = "zmk,combos";
|
||||
combo_one {
|
||||
timeout-ms = <40>;
|
||||
key-positions = <0 1>;
|
||||
bindings = <&kp X>;
|
||||
};
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label = "Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&kp A &kp B
|
||||
&mt RSHFT RET &kp C
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,0,10)
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(0,1,50)
|
||||
ZMK_MOCK_RELEASE(1,1,50)
|
||||
>;
|
||||
};
|
1
app/tests/combo/combos-and-holdtaps-4/events.patterns
Normal file
|
@ -0,0 +1 @@
|
|||
s/.*hid_listener_keycode_//p
|
|
@ -0,0 +1,4 @@
|
|||
pressed: usage_page 0x07 keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00
|
||||
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00
|
46
app/tests/combo/combos-and-holdtaps-4/native_posix_64.keymap
Normal file
|
@ -0,0 +1,46 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan-mock.h>
|
||||
|
||||
|
||||
#define ZMK_COMBO(name, combo_bindings, keypos, combo_term) \
|
||||
/ { \
|
||||
combos { \
|
||||
compatible = "zmk,combos"; \
|
||||
combo_ ## name { \
|
||||
key-positions = <keypos>; \
|
||||
bindings = <combo_bindings>; \
|
||||
timeout-ms = <combo_term>; \
|
||||
}; \
|
||||
}; \
|
||||
};
|
||||
|
||||
ZMK_COMBO(qmark, &kp QMARK, 0 3, 30)
|
||||
ZMK_COMBO(dllr, &kp DLLR, 1 3, 50)
|
||||
ZMK_COMBO(tilde, &kp TILDE, 3 4, 50)
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label = "Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&none &none
|
||||
&kp A &mt LSHFT T
|
||||
&none
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&kscan {
|
||||
rows = <3>;
|
||||
columns = <2>;
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,1,500)
|
||||
ZMK_MOCK_PRESS(1,0,100)
|
||||
ZMK_MOCK_RELEASE(1,0,500)
|
||||
ZMK_MOCK_RELEASE(1,1,0)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,3 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*conditional_layer/cl/p
|
|
@ -0,0 +1,20 @@
|
|||
mo_pressed: position 2 layer 1
|
||||
mo_pressed: position 3 layer 2
|
||||
cl_activate: layer 4
|
||||
mo_pressed: position 1 layer 3
|
||||
kp_pressed: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00
|
||||
mo_released: position 1 layer 3
|
||||
mo_released: position 3 layer 2
|
||||
cl_deactivate: layer 4
|
||||
mo_released: position 2 layer 1
|
||||
mo_pressed: position 1 layer 3
|
||||
mo_pressed: position 2 layer 1
|
||||
cl_activate: layer 4
|
||||
mo_pressed: position 3 layer 2
|
||||
kp_pressed: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00
|
||||
mo_released: position 3 layer 2
|
||||
mo_released: position 2 layer 1
|
||||
cl_deactivate: layer 4
|
||||
mo_released: position 1 layer 3
|
|
@ -0,0 +1,73 @@
|
|||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
|
||||
/ {
|
||||
conditional_layers {
|
||||
compatible = "zmk,conditional-layers";
|
||||
conditional_layer_1 {
|
||||
if-layers = <1 2>;
|
||||
then-layer = <4>;
|
||||
};
|
||||
conditional_layer_2 {
|
||||
if-layers = <1 3>;
|
||||
then-layer = <4>;
|
||||
};
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
default_layer {
|
||||
bindings = <
|
||||
&kp A &mo 3
|
||||
&mo 1 &mo 2
|
||||
>;
|
||||
};
|
||||
layer_1 {
|
||||
bindings = <
|
||||
&kp B &trans
|
||||
&trans &trans
|
||||
>;
|
||||
};
|
||||
layer_2 {
|
||||
bindings = <
|
||||
&kp C &trans
|
||||
&trans &trans
|
||||
>;
|
||||
};
|
||||
layer_3 {
|
||||
bindings = <
|
||||
&kp D &trans
|
||||
&trans &trans
|
||||
>;
|
||||
};
|
||||
layer_4 {
|
||||
bindings = <
|
||||
&kp E &trans
|
||||
&trans &trans
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,0,10)
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_PRESS(1,0,10)
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,3 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*conditional_layer/cl/p
|
|
@ -0,0 +1,16 @@
|
|||
mo_pressed: position 2 layer 1
|
||||
mo_pressed: position 3 layer 2
|
||||
cl_activate: layer 4
|
||||
kp_pressed: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00
|
||||
mo_released: position 3 layer 2
|
||||
cl_deactivate: layer 4
|
||||
mo_released: position 2 layer 1
|
||||
mo_pressed: position 1 layer 3
|
||||
mo_pressed: position 2 layer 1
|
||||
cl_activate: layer 4
|
||||
kp_pressed: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0x08 implicit_mods 0x00 explicit_mods 0x00
|
||||
mo_released: position 2 layer 1
|
||||
cl_deactivate: layer 4
|
||||
mo_released: position 1 layer 3
|
|
@ -0,0 +1,69 @@
|
|||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
|
||||
/ {
|
||||
conditional_layers {
|
||||
compatible = "zmk,conditional-layers";
|
||||
conditional_layer_1 {
|
||||
if-layers = <1 2>;
|
||||
then-layer = <4>;
|
||||
};
|
||||
conditional_layer_2 {
|
||||
if-layers = <1 3>;
|
||||
then-layer = <4>;
|
||||
};
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
default_layer {
|
||||
bindings = <
|
||||
&kp A &mo 3
|
||||
&mo 1 &mo 2
|
||||
>;
|
||||
};
|
||||
layer_1 {
|
||||
bindings = <
|
||||
&kp B &trans
|
||||
&trans &trans
|
||||
>;
|
||||
};
|
||||
layer_2 {
|
||||
bindings = <
|
||||
&kp C &trans
|
||||
&trans &trans
|
||||
>;
|
||||
};
|
||||
layer_3 {
|
||||
bindings = <
|
||||
&kp D &trans
|
||||
&trans &trans
|
||||
>;
|
||||
};
|
||||
layer_4 {
|
||||
bindings = <
|
||||
&kp E &trans
|
||||
&trans &trans
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,0,10)
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_PRESS(1,0,10)
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
>;
|
||||
};
|
3
app/tests/conditional-layer/tri-layer-lt/events.patterns
Normal file
|
@ -0,0 +1,3 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*conditional_layer/cl/p
|
|
@ -0,0 +1,8 @@
|
|||
mo_pressed: position 2 layer 1
|
||||
mo_pressed: position 3 layer 2
|
||||
cl_activate: layer 3
|
||||
kp_pressed: usage_page 0x07 keycode 0x0A implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0x0A implicit_mods 0x00 explicit_mods 0x00
|
||||
mo_released: position 3 layer 2
|
||||
cl_deactivate: layer 3
|
||||
mo_released: position 2 layer 1
|
|
@ -0,0 +1,56 @@
|
|||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
|
||||
< {
|
||||
flavor = "balanced";
|
||||
};
|
||||
|
||||
/ {
|
||||
conditional_layers {
|
||||
compatible = "zmk,conditional-layers";
|
||||
tri_layer {
|
||||
if-layers = <1 2>;
|
||||
then-layer = <3>;
|
||||
};
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
default_layer {
|
||||
bindings = <
|
||||
&kp A &kp B
|
||||
< 1 I < 2 J
|
||||
>;
|
||||
};
|
||||
layer_1 {
|
||||
bindings = <
|
||||
&kp C &kp D
|
||||
&trans &trans
|
||||
>;
|
||||
};
|
||||
layer_2 {
|
||||
bindings = <
|
||||
&kp E &kp F
|
||||
&trans &trans
|
||||
>;
|
||||
};
|
||||
layer_3 {
|
||||
bindings = <
|
||||
&kp G &kp H
|
||||
&trans &trans
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,0,10)
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
>;
|
||||
};
|
|
@ -27,7 +27,6 @@ manifest:
|
|||
- mcuboot
|
||||
- mcumgr
|
||||
- net-tools
|
||||
- segger
|
||||
- openthread
|
||||
- edtt
|
||||
- trusted-firmware-m
|
||||
|
|
Before Width: | Height: | Size: 10 KiB |
21
docs/docs/assets/hold-tap/case1_2.svg
Normal file
After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 6.2 KiB |
23
docs/docs/assets/hold-tap/case_hold_preferred.svg
Normal file
After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 155 KiB |
131
docs/docs/assets/hold-tap/comparison.svg
Normal file
After Width: | Height: | Size: 900 KiB |
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 226 KiB |
|
@ -5,7 +5,7 @@ sidebar_label: Caps Word
|
|||
|
||||
## Summary
|
||||
|
||||
The caps word behavior behaves similar to a caps lock, but will automatically deactivate when one of the configured "break keycodes" is pressed, or if the caps word key is pressed again. For smaller keyboards, using [mod-taps](/docs/behaviors/mod-tap), this can help avoid repeated alternating holds when typing words in all caps.
|
||||
The caps word behavior behaves similar to a caps lock, but will automatically deactivate when any key not in a continue list is pressed, or if the caps word key is pressed again. For smaller keyboards using [mod-taps](/docs/behaviors/mod-tap), this can help avoid repeated alternating holds when typing words in all caps.
|
||||
|
||||
The modifiers are applied only to to the alphabetic (`A` to `Z`) keycodes, to avoid automatically appliying them to numeric values, etc.
|
||||
|
||||
|
|
|
@ -3,6 +3,9 @@ title: Hold-Tap Behavior
|
|||
sidebar_label: Hold-Tap
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
## Summary
|
||||
|
||||
Hold-tap is the basis for other behaviors such as layer-tap and mod-tap.
|
||||
|
@ -13,11 +16,11 @@ Simply put, the hold-tap key will output the 'hold' behavior if it's held for a
|
|||
|
||||
The graph below shows how the hold-tap decides between a 'tap' and a 'hold'.
|
||||
|
||||

|
||||

|
||||
|
||||
By default, the hold-tap is configured to also select the 'hold' functionality if another key is tapped while it's active:
|
||||
|
||||

|
||||

|
||||
|
||||
We call this the 'hold-preferred' flavor of hold-taps. While this flavor may work very well for a ctrl/escape key, it's not very well suited for home-row mods or layer-taps. That's why there are two more flavors to choose from: 'tap-preferred' and 'balanced'.
|
||||
|
||||
|
@ -30,11 +33,11 @@ We call this the 'hold-preferred' flavor of hold-taps. While this flavor may wor
|
|||
|
||||
When the hold-tap key is released and the hold behavior has not been triggered, the tap behavior will trigger.
|
||||
|
||||

|
||||

|
||||
|
||||
### Basic usage
|
||||
|
||||
For basic usage, please see [mod-tap](mod-tap.md) and [layer-tap](layers.md) pages.
|
||||
For basic usage, please see the [mod-tap](mod-tap.md) and [layer-tap](layers.md#layer-tap) pages.
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
|
@ -50,9 +53,9 @@ In QMK, unlike ZMK, this functionality is enabled by default, and you turn it of
|
|||
|
||||
#### `global-quick-tap`
|
||||
|
||||
If global quick tap is enabled, then `quick-tap-ms` will apply not only when the given hold-tap is tapped but for any key tap before it. This effectively disables the hold tap when typing quickly, which can be quite useful for home row mods. It can also have the effect of removing the input delay when typing quickly.
|
||||
If `global-quick-tap` is enabled, then `quick-tap-ms` will apply not only when the given hold-tap is tapped, but for any key tapped before it. This effectively disables the hold-tap when typing quickly, which can be quite useful for homerow mods. It can also have the effect of removing the input delay when typing quickly.
|
||||
|
||||
For example, the following hold-tap configuration enables global quick tap with a 125 millisecond term.
|
||||
For example, the following hold-tap configuration enables `global-quick-tap` with a 125 millisecond `quick-tap-ms` term.
|
||||
|
||||
```
|
||||
gqt: global-quick-tap {
|
||||
|
@ -69,11 +72,11 @@ gqt: global-quick-tap {
|
|||
|
||||
If you press `&kp A` and then `&gqt LEFT_SHIFT B` **within** 125 ms, then `ab` will be output. Importantly, `b` will be output immediately since it was within the `quick-tap-ms`. This quick-tap behavior will work for any key press, whether it is within a behavior like hold-tap, or a simple `&kp`. This means the `&gqt LEFT_SHIFT B` binding will only have its underlying hold-tap behavior if it is pressed 125 ms **after** a key press.
|
||||
|
||||
Note that the higher the `quick-tap-ms` the harder it will be to use the hold behavior, making this less applicable for something like capitalizing letter while typing normally. However, if the hold behavior isn't used during fast typing, then it can be an effective way to mitigate misfires.
|
||||
Note that the greater the value of `quick-tap-ms` is, the harder it will be to invoke the hold behavior, making this feature less applicable for use-cases like capitalizing letters while typing normally. However, if the hold behavior isn't used during fast typing, then it can be an effective way to mitigate misfires.
|
||||
|
||||
#### `retro-tap`
|
||||
|
||||
If retro tap is enabled, the tap behavior is triggered when releasing the hold-tap key if no other key was pressed in the meantime.
|
||||
If `retro-tap` is enabled, the tap behavior is triggered when releasing the hold-tap key if no other key was pressed in the meantime.
|
||||
|
||||
For example, if you press `&mt LEFT_SHIFT A` and then release it without pressing another key, it will output `a`.
|
||||
|
||||
|
@ -85,16 +88,20 @@ For example, if you press `&mt LEFT_SHIFT A` and then release it without pressin
|
|||
|
||||
#### Positional hold-tap and `hold-trigger-key-positions`
|
||||
|
||||
- Including `hold-trigger-key-positions` in your hold-tap definition turns on the positional hold-tap feature.
|
||||
- With positional hold-tap enabled, if you press any key **NOT** listed in `hold-trigger-key-positions` before `tapping-term-ms` expires, it will produce a tap.
|
||||
- In all other situations, positional hold-tap will not modify the behavior of your hold-tap.
|
||||
- Positional hold-tap is useful with home-row modifiers. If you have a home-row modifier key in the left hand for example, by including only keys positions from the right hand in `hold-trigger-key-positions`, you will only get hold behaviors during cross-hand key combinations.
|
||||
- Note that `hold-trigger-key-positions` is an array of key position indexes. Key positions are numbered according to your keymap, starting with 0. So if the first key in your keymap is Q, this key is in position 0. The next key (probably W) will be in position 1, et cetera.
|
||||
- See the following example, which uses a hold-tap behavior definition, configured with the `hold-preferred` flavor, and with positional hold-tap enabled:
|
||||
Including `hold-trigger-key-positions` in your hold-tap definition turns on the positional hold-tap feature. With positional hold-tap enabled, if you press any key **NOT** listed in `hold-trigger-key-positions` before `tapping-term-ms` expires, it will produce a tap.
|
||||
|
||||
In all other situations, positional hold-tap will not modify the behavior of your hold-tap. Positional hold-tap is useful when used with home-row modifiers: for example, if you have a home-row modifier key in the left hand, by including only key positions from the right hand in `hold-trigger-key-positions`, you will only get hold behaviors during cross-hand key combinations.
|
||||
|
||||
:::info
|
||||
Note that `hold-trigger-key-positions` is an array of key position indexes. Key positions are numbered sequentially according to your keymap, starting with 0. So if the first key in your keymap is Q, this key is in position 0. The next key (probably W) will be in position 1, et cetera.
|
||||
:::
|
||||
|
||||
See the following example, which uses a hold-tap behavior definition, configured with the `hold-preferred` flavor, and with positional hold-tap enabled:
|
||||
|
||||
```
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
|
||||
/ {
|
||||
behaviors {
|
||||
pht: positional_hold_tap {
|
||||
|
@ -125,15 +132,26 @@ For example, if you press `&mt LEFT_SHIFT A` and then release it without pressin
|
|||
- The sequence `(pht_down, W_down, W_up, pht_up)` produces `W`. The normal hold behavior (LEFT_SHIFT) **is NOT** modified into a tap behavior (Q) by positional hold-tap because the first key pressed after the hold-tap key is the `W key`, which is in position 1, which **IS** included in `hold-trigger-key-positions`.
|
||||
- If the `LEFT_SHIFT / Q key` is held by itself for longer than `tapping-term-ms`, a hold behavior is produced. This is because positional hold-tap only modifies the behavior of a hold-tap if another key is pressed before the `tapping-term-ms` period expires.
|
||||
|
||||
#### Home row mods
|
||||
### Example Use-Cases
|
||||
|
||||
<Tabs
|
||||
defaultValue="homerow_mods"
|
||||
values={[
|
||||
{label: 'Homerow Mods', value: 'homerow_mods'},
|
||||
{label: 'Autoshift', value: 'autoshift'},
|
||||
{label: 'Toggle-on-Tap, Momentary-on-Hold Layers', value: 'tog_mo'},
|
||||
]}>
|
||||
|
||||
<TabItem value="homerow_mods">
|
||||
|
||||
The following are suggested hold-tap configurations that work well with home row mods:
|
||||
|
||||
##### Option 1: cross-hand only modifiers, using `tap-unless-interrupted` and positional hold-tap (`hold-trigger-key-positions`)
|
||||
|
||||
```
|
||||
```dtsi title="Homerow Mods: Cross-hand Example"
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
|
||||
/ {
|
||||
behaviors {
|
||||
lh_pht: left_hand_positional_hold_tap {
|
||||
|
@ -162,7 +180,7 @@ The following are suggested hold-tap configurations that work well with home row
|
|||
|
||||
##### Option 2: `tap-preferred`
|
||||
|
||||
```
|
||||
```dtsi title="Homerow Mods: Tap-Preferred Example"
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
|
||||
|
@ -188,12 +206,11 @@ The following are suggested hold-tap configurations that work well with home row
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
##### Option 3: `balanced`
|
||||
|
||||
```
|
||||
```dtsi title="Homerow Mods: Balanced Example"
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
|
||||
|
@ -219,9 +236,84 @@ The following are suggested hold-tap configurations that work well with home row
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
#### Comparison to QMK
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="autoshift">
|
||||
|
||||
A popular method of implementing Autoshift in ZMK involves a C-preprocessor macro, commonly defined as `AS(keycode)`. This macro applies the `LSHIFT` modifier to the specified `keycode` when `AS(keycode)` is held, and simply performs a [keypress](key-press.md), `&kp keycode`, when the `AS(keycode)` binding is tapped. This simplifies the use of Autoshift in a keymap, as the complete hold-tap bindings for each desired Autoshift key, as in `&as LS(<keycode 1>) <keycode 1> &as LS(<keycode 2>) <keycode 2> ... &as LS(<keycode n>) <keycode n>`, can be quite cumbersome to use when applied to a large portion of the keymap.
|
||||
|
||||
```dtsi title="Hold-Tap Example: Autoshift"
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
|
||||
#define AS(keycode) &as LS(keycode) keycode // Autoshift Macro
|
||||
|
||||
/ {
|
||||
behaviors {
|
||||
as: auto_shift {
|
||||
compatible = "zmk,behavior-hold-tap";
|
||||
label = "AUTO_SHIFT";
|
||||
#binding-cells = <2>;
|
||||
tapping_term_ms = <135>;
|
||||
quick_tap_ms = <0>;
|
||||
flavor = "tap-preferred";
|
||||
bindings = <&kp>, <&kp>;
|
||||
};
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
default_layer {
|
||||
bindings = <
|
||||
AS(Q) AS(W) AS(E) AS(R) AS(T) AS(Y) // Autoshift applied for QWERTY keys
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="tog_mo">
|
||||
|
||||
This hold-tap example implements a [toggle-layer](layers.md/#toggle-layer) when the keybind is tapped and a [momentary-layer](layers.md/#momentary-layer) when it is held. Similarly to the Autoshift and Sticky Hold use-cases, a `TOG_MO(layer)` macro is defined such that the `&tog` and `&mo` behaviors can target a single layer.
|
||||
|
||||
```dtsi title="Hold-Tap Example: Toggle layer on Tap, Momentary layer on Hold"
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
|
||||
#define TOG_MO(layer) &tog_mo layer layer // Macro to apply toggle-layer-on-tap/momentary-layer-on-hold to a specific layer
|
||||
|
||||
/ {
|
||||
behaviors {
|
||||
tog_mo: behavior_mo_tog {
|
||||
compatible = "zmk,behavior-hold-tap";
|
||||
label = "mo_tog";
|
||||
#binding-cells = <2>;
|
||||
flavor = "hold-preferred";
|
||||
tapping-term-ms = <200>;
|
||||
bindings = <&tog>, <&mo>;
|
||||
};
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
default_layer {
|
||||
bindings = <
|
||||
&tog_mo 2 1 // &mo 2 on hold, &tog 1 on tap
|
||||
TOG_MO(3) // &mo 3 on hold, &tog 3 on tap
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
|
||||
</Tabs>
|
||||
|
||||
### Comparison to QMK
|
||||
|
||||
The hold-preferred flavor works similar to the `HOLD_ON_OTHER_KEY_PRESS` setting in QMK. The 'balanced' flavor is similar to the `PERMISSIVE_HOLD` setting, and the `tap-preferred` flavor is similar to `IGNORE_MOD_TAP_INTERRUPT`.
|
||||
|
|
|
@ -40,7 +40,7 @@ The "key press" behavior sends standard keycodes on press/release.
|
|||
### Behavior Binding
|
||||
|
||||
- Reference: `&kp`
|
||||
- Parameter: The keycode usage ID from the usage page, e.g. `4` or `A`
|
||||
- Parameter: The keycode usage ID from the usage page, e.g. `N4` or `A`
|
||||
|
||||
Example:
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ Example:
|
|||
|
||||
## Layer-tap
|
||||
|
||||
The "layer-tap" behavior enables a layer when a key is held, and output another key when the key is only tapped for a short time. For more information on the inner workings of layer-tap, see [hold-tap](hold-tap.md).
|
||||
The "layer-tap" behavior enables a layer when a key is held, and outputs a [keypress](key-press.md) when the key is only tapped for a short time.
|
||||
|
||||
### Behavior Binding
|
||||
|
||||
|
@ -57,6 +57,15 @@ Example:
|
|||
< LOWER SPACE
|
||||
```
|
||||
|
||||
:::info
|
||||
Functionally, the layer-tap is a [hold-tap](hold-tap.md) of the ["tap-preferred" flavor](hold-tap.md/#flavors) and a [`tapping-term-ms`](hold-tap.md/#tapping-term-ms) of 200 that takes in a [`momentary layer`](#momentary-layer) and a [keypress](key-press.md) as its "hold" and "tap" parameters, respectively.
|
||||
|
||||
For users who want to send a different [keycode](../codes/index.mdx) depending on if the same key is held or tapped, see [Mod-Tap](mod-tap.md).
|
||||
|
||||
Similarly, for users looking to create a keybind like the layer-tap that depending on how long the key is held, invokes behaviors like [sticky keys](sticky-key.md) or [key toggles](key-toggle.md), see [Hold-Tap](hold-tap.md).
|
||||
|
||||
:::
|
||||
|
||||
## To Layer
|
||||
|
||||
The "to layer" behavior enables a layer and disables _all_ other layers _except_ the default layer.
|
||||
|
|
|
@ -134,6 +134,12 @@ bindings
|
|||
;
|
||||
```
|
||||
|
||||
### Behavior Queue Limit
|
||||
|
||||
Macros use an internal queue to invoke each behavior in the bindings list when triggered, which has a size of 64 by default. Bindings in "press" and "release" modes correspond to one event in the queue, whereas "tap" mode bindings correspond to two (one for press and one for release). As a result, the effective number of actions processed might be less than 64 and this can cause problems for long macros.
|
||||
|
||||
To prevent issues with longer macros, you can change the size of this queue via the `CONFIG_ZMK_BEHAVIORS_QUEUE_SIZE` setting in your configuration, [typically through your `.conf` file](../config/index.md). For example, `CONFIG_ZMK_BEHAVIORS_QUEUE_SIZE=512` would allow your macro to type about 256 characters.
|
||||
|
||||
## Common Patterns
|
||||
|
||||
Below are some examples of how the macro behavior can be used for various useful functionality.
|
||||
|
|
|
@ -44,6 +44,11 @@ You can configure a different tapping term in your keymap:
|
|||
};
|
||||
```
|
||||
|
||||
### Additional information
|
||||
:::info
|
||||
Under the hood, the mod-tap is simply a [hold-tap](hold-tap.md) of the ["hold-preferred" flavor](hold-tap.md/#flavors) with a [`tapping-term-ms`](hold-tap.md/#tapping-term-ms) of 200 that takes in two [keypresses](key-press.md) as its "hold" and "tap" parameters. This means that the mod-tap can be used to invoke **any** [keycode](../codes/index.mdx), and is not limited to only activating [modifier keys](../codes/modifiers.mdx) when it is held.
|
||||
|
||||
The mod-tap is a [hold-tap](hold-tap.md) under the hood with the "hold-preferred" flavor and tapping-term-ms 200.
|
||||
For users who want to momentarily access a specific [layer](../features/keymaps#layers) while a key is held and send a keycode when the same key is tapped, see [Layer-Tap](layers.md/#layer-tap).
|
||||
|
||||
Similarly, for users looking to create a keybind like the mod-tap that invokes behaviors _other_ than [keypresses](key-press.md), like [sticky keys](sticky-key.md) or [key toggles](key-toggle.md), see [Hold-Tap](hold-tap.md).
|
||||
|
||||
:::
|
||||
|
|
|
@ -3,39 +3,41 @@ title: Tap-Dance Behavior
|
|||
sidebar_label: Tap-Dance
|
||||
---
|
||||
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
## Summary
|
||||
|
||||
A tap-dance key invokes a different behavior (e.g. `kp`) corresponding
|
||||
to how many times it is pressed. For example, you could configure a
|
||||
tap-dance key that acts as `LSHIFT` if tapped once, or Caps _Lock_ if tapped twice.
|
||||
The expandability of the number of [`bindings`](#bindings) attached to a
|
||||
particular tap-dance is a great way to add more functionality to a single key,
|
||||
especially for keyboards with a limited number of keys.
|
||||
Tap-dances are completely custom, so for every unique tap-dance key,
|
||||
a new tap-dance must be defined in your keymap's `behaviors`.
|
||||
A tap-dance key invokes a different behavior (e.g. `kp`) corresponding to how many times it is pressed. For example, you could configure a tap-dance key that acts as `LSHIFT` if tapped once, or Caps _Lock_ if tapped twice. The expandability of the number of [`bindings`](#bindings) attached to a particular tap-dance is a great way to add more functionality to a single key, especially for keyboards with a limited number of keys. Tap-dances are completely custom, so for every unique tap-dance key,a new tap-dance must be defined in your keymap's `behaviors`.
|
||||
|
||||
Tap-dances are designed to resolve immediately when interrupted by another keypress.
|
||||
Meaning, when a keybind is pressed other than any active tap-dances,
|
||||
the tap-dance will activate according to the current value of its
|
||||
counter before the interrupting keybind is registered.
|
||||
Tap-dances are designed to resolve immediately when interrupted by another keypress. Meaning, when a keybind is pressed other than any active tap-dances, the tap-dance will activate according to the current value of its counter before the interrupting keybind is registered.
|
||||
|
||||
### Configuration
|
||||
|
||||
#### `tapping-term-ms`
|
||||
|
||||
Defines the maximum elapsed time after the last tap-dance keybind press
|
||||
before a binding is selected from [`bindings`](#bindings).
|
||||
Default value is `200`ms.
|
||||
Defines the maximum elapsed time after the last tap-dance keybind press before a binding is selected from [`bindings`](#bindings). Default value is `200`ms.
|
||||
|
||||
#### `bindings`
|
||||
|
||||
An array of one or more keybinds. This list can include [any ZMK keycode](../codes/) and bindings for ZMK behaviors.
|
||||
An array of one or more keybinds. This list can include [any ZMK keycode](../codes/) and any listed ZMK behavior, like [hold-taps](hold-tap.md), or [sticky keys](sticky-key.md). The index of a keybind in the `bindings` array corresponds to the number of times the tap-dance binding is pressed. For example, in the [basic tap-dance counter](#basic-example-counter) shown below, `&kp N2` is the second binding in the array of `bindings`: we then see an output of `2` when the `td0` binding is pressed twice.
|
||||
|
||||
#### Example Usage
|
||||
The number of bindings in this array also determines the tap-dance's maximum number of keypresses. When a tap-dance reaches its maximum number of keypresses, it will immediately invoke the last behavior in its list of `bindings`, rather than waiting for [`tapping-term-ms`](#tapping-term-ms) to expire before the output is displayed.
|
||||
|
||||
This example configures a tap-dance named `td0` that outputs the number of times it is pressed from 1-3.
|
||||
### Example Usage
|
||||
|
||||
```
|
||||
<Tabs
|
||||
defaultValue="basic"
|
||||
values={[
|
||||
{label: 'Basic Example: Counter', value: 'basic'},
|
||||
{label: 'Advanced Example: Mod-Tap Nested inside Tap-Dance', value: 'advanced'},
|
||||
]}>
|
||||
|
||||
<TabItem value="basic">
|
||||
|
||||
This example configures a tap-dance named `td0` that outputs the number of times its binding is pressed from 1-3.
|
||||
|
||||
```title="Basic Tap-Dance Example: Counter"
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
|
||||
|
@ -67,10 +69,41 @@ The following image describes the behavior of this particular tap-dance.
|
|||

|
||||
|
||||
:::note
|
||||
Alphanumeric [`key press`](key-press.md) bindings, like those used for `td0`,
|
||||
will release as soon as an interrupting key press occurs.
|
||||
For instance, if a modifier key like `LSHIFT` were to replace the `N1`
|
||||
binding in the last example above, it would remain pressed until `td0`'s
|
||||
binding is released and the output would instead be `J`. Any following
|
||||
alphanumeric key presses would be capitalized as long as `td0` is held down.
|
||||
Alphanumeric [`key press`](key-press.md) bindings, like those used for `td0`, will release as soon as an interrupting key press occurs. For instance, if a modifier key like `LSHIFT` were to replace the `N1` binding in the last example above, it would remain pressed until `td0`'s binding is released and the output would instead be `J`. Any following alphanumeric key presses would be capitalized as long as `td0` is held down.
|
||||
:::
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="advanced">
|
||||
|
||||
This example configures a mod-tap inside a tap-dance named `td_mt` that outputs `CAPSLOCK` on a single tap, `LSHIFT` on a single press and hold, and `LCTRL` when the tap-dance is pressed twice.
|
||||
|
||||
```title="Advanced Tap-Dance Example: Nested Mod-Tap"
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
|
||||
/ {
|
||||
behaviors {
|
||||
td_mt: tap_dance_mod_tap {
|
||||
compatible = "zmk,behavior-tap-dance";
|
||||
label = "TAP_DANCE_MOD_TAP";
|
||||
#binding-cells = <0>;
|
||||
tapping-term-ms = <200>;
|
||||
bindings = <&mt LSHIFT CAPSLOCK>, <&kp LCTRL>;
|
||||
};
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&td_mt
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
|
|
@ -22,6 +22,8 @@ Here is a table describing the action for each define:
|
|||
|
||||
| Define | Action |
|
||||
| --------------- | ---------------------------------------------------------------------------------------------- |
|
||||
| `RGB_ON` | Turns the RGB feature on |
|
||||
| `RGB_OFF` | Turns the RGB feature off |
|
||||
| `RGB_TOG` | Toggles the RGB feature on and off |
|
||||
| `RGB_HUI` | Increases the hue of the RGB feature |
|
||||
| `RGB_HUD` | Decreases the hue of the RGB feature |
|
||||
|
@ -39,11 +41,11 @@ Here is a table describing the action for each define:
|
|||
|
||||
- Reference: `&rgb_ug`
|
||||
- Parameter #1: The RGB action define, e.g. `RGB_TOG` or `RGB_BRI`
|
||||
- Parameter #2: Only applies to `RGB_COLOR_HSB` and is the HSB values of the color to set within parenthesis and separated by a common (see below for an example)
|
||||
- Parameter #2: Only applies to `RGB_COLOR_HSB` and is the HSB representation of the color to set (see below for an example)
|
||||
|
||||
:::note HSB Values
|
||||
|
||||
When specifying HSB values you'll need to use `RGB_COLOR_HSB(h, s, b)` in your keymap file. See below for an example.
|
||||
When specifying HSB values you'll need to use `RGB_COLOR_HSB(h, s, b)` in your keymap file.
|
||||
|
||||
Value Limits:
|
||||
|
||||
|
|
40
docs/docs/config/backlight.md
Normal file
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
title: Backlight Configuration
|
||||
sidebar_label: Backlight
|
||||
---
|
||||
|
||||
See the [backlight feature page](../features/backlight.md) for more details, including instructions for adding backlight support to a board.
|
||||
|
||||
See [Configuration Overview](index.md) for instructions on how to change these settings.
|
||||
|
||||
## Kconfig
|
||||
|
||||
Definition file: [zmk/app/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/Kconfig)
|
||||
|
||||
| Option | Type | Description | Default |
|
||||
| ------------------------------------ | ---- | ----------------------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_BACKLIGHT` | bool | Enables LED backlight | n |
|
||||
| `CONFIG_ZMK_BACKLIGHT_BRT_STEP` | int | Brightness step in percent | 20 |
|
||||
| `CONFIG_ZMK_BACKLIGHT_BRT_START` | int | Default brightness in percent | 40 |
|
||||
| `CONFIG_ZMK_BACKLIGHT_ON_START` | bool | Default backlight state | y |
|
||||
| `CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE` | bool | Turn off backlight when keyboard goes into idle state | n |
|
||||
| `CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB` | bool | Turn off backlight when USB is disconnected | n |
|
||||
|
||||
:::note
|
||||
The `*_START` settings only determine the initial backlight state. Any changes you make with the [backlight behavior](../behaviors/backlight.md) are saved to flash after a one minute delay and will be used after that.
|
||||
:::
|
||||
|
||||
## Devicetree
|
||||
|
||||
Applies to: [`/chosen` node](https://docs.zephyrproject.org/latest/build/dts/intro.html#aliases-and-chosen-nodes)
|
||||
|
||||
| Property | Type | Description |
|
||||
| --------------- | ---- | -------------------------------------------- |
|
||||
| `zmk,backlight` | path | The node for the backlight LED driver to use |
|
||||
|
||||
See the Zephyr devicetree bindings for LED drivers:
|
||||
|
||||
- [gpio-leds](https://docs.zephyrproject.org/latest/build/dts/api/bindings/gpio/gpio-leds.html)
|
||||
- [pwm-leds](https://docs.zephyrproject.org/latest/build/dts/api/bindings/led/pwm-leds.html)
|
||||
|
||||
See the [backlight feature page](../features/backlight.md) for examples of the properties that must be set to enable backlighting.
|
40
docs/docs/config/battery.md
Normal file
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
title: Battery Level
|
||||
sidebar_label: Battery Level
|
||||
---
|
||||
|
||||
See the [battery level feature page](../features/battery.md) for more details on configuring a battery sensor.
|
||||
|
||||
See [Configuration Overview](index.md) for instructions on how to change these settings.
|
||||
|
||||
### Devicetree
|
||||
|
||||
Applies to: [`/chosen` node](https://docs.zephyrproject.org/latest/guides/dts/intro.html#aliases-and-chosen-nodes)
|
||||
|
||||
| Property | Type | Description |
|
||||
| ------------- | ---- | --------------------------------------------- |
|
||||
| `zmk,battery` | path | The node for the battery sensor driver to use |
|
||||
|
||||
## Battery Voltage Divider Sensor
|
||||
|
||||
Driver for reading the voltage of a battery using an ADC connected to a voltage divider.
|
||||
|
||||
### Devicetree
|
||||
|
||||
Applies to: `compatible = "zmk,battery-voltage-divider"`
|
||||
|
||||
See [Zephyr's voltage divider documentation](https://docs.zephyrproject.org/latest/build/dts/api/bindings/adc/voltage-divider.html).
|
||||
|
||||
## nRF VDDH Battery Sensor
|
||||
|
||||
Driver for reading the voltage of a battery using a Nordic nRF52's VDDH pin. This driver has no configuration except for the required `label` property.
|
||||
|
||||
### Devicetree
|
||||
|
||||
Applies to: `compatible = "zmk,battery-nrf-vddh"`
|
||||
|
||||
Definition file: [zmk/app/drivers/zephyr/dts/bindings/sensor/zmk,battery-nrf-vddh.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/drivers/zephyr/dts/bindings/sensor/zmk%2Cbattery-nrf-vddh.yaml)
|
||||
|
||||
| Property | Type | Description |
|
||||
| -------- | ------ | ------------------------- |
|
||||
| `label` | string | Unique label for the node |
|
216
docs/docs/config/behaviors.md
Normal file
|
@ -0,0 +1,216 @@
|
|||
---
|
||||
title: Behavior Configuration
|
||||
sidebar_label: Behaviors
|
||||
---
|
||||
|
||||
Some behaviors have properties to adjust how they behave. These can also be used as templates to create custom behaviors when none of the built-in behaviors do what you want.
|
||||
|
||||
See [Configuration Overview](index.md) for instructions on how to change these settings.
|
||||
|
||||
See the [zmk/app/dts/behaviors/](https://github.com/zmkfirmware/zmk/tree/main/app/dts/behaviors) folder for all default behaviors.
|
||||
|
||||
## Common
|
||||
|
||||
### Kconfig
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| --------------------------------- | ---- | ------------------------------------------------------------------------------------ | ------- |
|
||||
| `CONFIG_ZMK_BEHAVIORS_QUEUE_SIZE` | int | Maximum number of behaviors to allow queueing from a macro or other complex behavior | 64 |
|
||||
|
||||
## Caps Word
|
||||
|
||||
Creates a custom behavior that behaves similar to a caps lock but deactivates when any key not in a continue list is pressed.
|
||||
|
||||
See the [caps word behavior](../behaviors/caps-word.md) documentation for more details and examples.
|
||||
|
||||
### Devicetree
|
||||
|
||||
Definition file: [zmk/app/dts/bindings/behaviors/zmk,behavior-caps-word.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/behaviors/zmk%2Cbehavior-caps-word.yaml)
|
||||
|
||||
Applies to: `compatible = "zmk,behavior-caps-word"`
|
||||
|
||||
| Property | Type | Description | Default |
|
||||
| ---------------- | ------ | ------------------------------------------------------------------ | ------------------------------- |
|
||||
| `label` | string | Unique label for the node | |
|
||||
| `#binding-cells` | int | Must be `<0>` | |
|
||||
| `continue-list` | array | List of [key codes](/docs/codes) which do not deactivate caps lock | `<UNDERSCORE BACKSPACE DELETE>` |
|
||||
| `mods` | int | A bit field of modifiers to apply | `<MOD_LSFT>` |
|
||||
|
||||
`continue-list` is treated as if it always includes alphanumeric characters (A-Z, 0-9).
|
||||
|
||||
See [dt-bindings/zmk/modifiers.h](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/modifiers.h) for a list of modifiers.
|
||||
|
||||
You can use the following nodes to tweak the default behaviors:
|
||||
|
||||
| Node | Behavior |
|
||||
| ------------ | -------------------------------------- |
|
||||
| `&caps_word` | [Caps Word](../behaviors/caps-word.md) |
|
||||
|
||||
## Hold-Tap
|
||||
|
||||
Creates a custom behavior that triggers one behavior when a key is held or a different one when the key is tapped.
|
||||
|
||||
See the [hold-tap behavior documentation](../behaviors/hold-tap.md) for more details and examples.
|
||||
|
||||
### Devicetree
|
||||
|
||||
Definition file: [zmk/app/dts/bindings/behaviors/zmk,behavior-hold-tap.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/behaviors/zmk%2Cbehavior-hold-tap.yaml)
|
||||
|
||||
Applies to: `compatible = "zmk,behavior-hold-tap"`
|
||||
|
||||
| Property | Type | Description | Default |
|
||||
| ---------------------------- | ------------- | ----------------------------------------------------------------------------------------- | ------------------ |
|
||||
| `label` | string | Unique label for the node | |
|
||||
| `#binding-cells` | int | Must be `<2>` | |
|
||||
| `bindings` | phandle array | A list of two behaviors (without parameters): one for hold and one for tap | |
|
||||
| `flavor` | string | Adjusts how the behavior chooses between hold and tap | `"hold-preferred"` |
|
||||
| `tapping-term-ms` | int | How long in milliseconds the key must be held to trigger a hold | |
|
||||
| `quick-tap-ms` | int | Tap twice within this period (in milliseconds) to trigger a tap, even when held | -1 (disabled) |
|
||||
| `global-quick-tap` | bool | If enabled, `quick-tap-ms` also applies when tapping another key and then this one. | false |
|
||||
| `retro-tap` | bool | Triggers the tap behavior on release if no other key was pressed during a hold | false |
|
||||
| `hold-trigger-key-positions` | array | If set, pressing the hold-tap and then any key position _not_ in the list triggers a tap. | |
|
||||
|
||||
The `flavor` property may be one of:
|
||||
|
||||
- `"hold-preferred"`
|
||||
- `"balanced"`
|
||||
- `"tap-preferred"`
|
||||
- `"tap-unless-interrupted"`
|
||||
|
||||
See the [hold-tap behavior documentation](../behaviors/hold-tap.md) for an explanation of each flavor.
|
||||
|
||||
`hold-trigger-key-positions` is an array of zero-based key position indices.
|
||||
|
||||
You can use the following nodes to tweak the default behaviors:
|
||||
|
||||
| Node | Behavior |
|
||||
| ----- | --------------------------------------------- |
|
||||
| `<` | [Layer-tap](../behaviors/layers.md#layer-tap) |
|
||||
| `&mt` | [Mod-tap](../behaviors/mod-tap.md) |
|
||||
|
||||
## Key Repeat
|
||||
|
||||
Creates a custom behavior that repeats the whatever key code was last sent.
|
||||
|
||||
See the [key repeat behavior](../behaviors/key-repeat.md) documentation for more details and examples.
|
||||
|
||||
### Devicetree
|
||||
|
||||
Definition file: [zmk/app/dts/bindings/behaviors/zmk,behavior-key-repeat.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/behaviors/zmk%2Cbehavior-key-repeat.yaml)
|
||||
|
||||
Applies to: `compatible = "zmk,behavior-key-repeat"`
|
||||
|
||||
| Property | Type | Description | Default |
|
||||
| ---------------- | ------ | -------------------------------- | ----------------- |
|
||||
| `label` | string | Unique label for the node | |
|
||||
| `#binding-cells` | int | Must be `<0>` | |
|
||||
| `usage-pages` | array | List of HID usage pages to track | `<HID_USAGE_KEY>` |
|
||||
|
||||
For the `usage-pages` property, use the `HID_USAGE_*` defines from [dt-bindings/zmk/hid_usage_pages.h](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/hid_usage_pages.h).
|
||||
|
||||
You can use the following nodes to tweak the default behaviors:
|
||||
|
||||
| Node | Behavior |
|
||||
| ------------- | ---------------------------------------- |
|
||||
| `&key_repeat` | [Key repeat](../behaviors/key-repeat.md) |
|
||||
|
||||
## Macro
|
||||
|
||||
Creates a custom behavior which triggers a sequence of other behaviors.
|
||||
|
||||
See the [macro behavior](../behaviors/macros.md) documentation for more details and examples.
|
||||
|
||||
### Devicetree
|
||||
|
||||
Definition file: [zmk/app/dts/bindings/behaviors/zmk,behavior-macro.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/behaviors/zmk%2Cbehavior-macro.yaml)
|
||||
|
||||
Applies to: `compatible = "zmk,behavior-macro"`
|
||||
|
||||
| Property | Type | Description | Default |
|
||||
| ---------------- | ------------- | ----------------------------------------------------------------------------------------------------- | ------- |
|
||||
| `label` | string | Unique label for the node | |
|
||||
| `#binding-cells` | int | Must be `<0>` | |
|
||||
| `bindings` | phandle array | List of behaviors to trigger | |
|
||||
| `wait-ms` | int | The default time to wait (in milliseconds) before triggering the next behavior. | 100 |
|
||||
| `tap-ms` | int | The default time to wait (in milliseconds) between the press and release events of a tapped behavior. | 100 |
|
||||
|
||||
The following macro-specific behaviors can be added at any point in the `bindings` list to change how the macro triggers subsequent behaviors.
|
||||
|
||||
| Behavior | Description |
|
||||
| -------------------------- | ----------------------------------------------------------------------------------------------------- |
|
||||
| `¯o_tap` | Switches to tap mode |
|
||||
| `¯o_press` | Switches to press mode |
|
||||
| `¯o_release` | Switches to release mode |
|
||||
| `¯o_pause_for_release` | Pauses the macro until the macro key itself is released |
|
||||
| `¯o_wait_time TIME` | Changes the time to wait (in milliseconds) before triggering the next behavior. |
|
||||
| `¯o_tap_time TIME` | Changes the time to wait (in milliseconds) between the press and release events of a tapped behavior. |
|
||||
|
||||
## Mod-Morph
|
||||
|
||||
Creates a custom behavior that triggers one of two behaviors depending on whether certain modifiers are held.
|
||||
|
||||
### Devicetree
|
||||
|
||||
Definition file: [zmk/app/dts/bindings/behaviors/zmk,behavior-mod-morph.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/behaviors/zmk%2Cbehavior-mod-morph.yaml)
|
||||
|
||||
Applies to: `compatible = "zmk,behavior-mod-morph"`
|
||||
|
||||
| Property | Type | Description |
|
||||
| ---------------- | ------------- | --------------------------------------------------------------------------------- |
|
||||
| `label` | string | Unique label for the node |
|
||||
| `#binding-cells` | int | Must be `<0>` |
|
||||
| `bindings` | phandle array | A list of two behaviors: one for normal press and one for mod morphed press |
|
||||
| `mods` | int | A bit field of modifiers. The morph behavior is used if any of these are pressed. |
|
||||
|
||||
See [dt-bindings/zmk/modifiers.h](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/modifiers.h) for a list of modifiers.
|
||||
|
||||
You can use the following nodes to tweak the default behaviors:
|
||||
|
||||
| Node | Behavior |
|
||||
| -------- | ----------------------------------------- |
|
||||
| `&gresc` | [Grave escape](../behaviors/mod-morph.md) |
|
||||
|
||||
## Sticky Key
|
||||
|
||||
Creates a custom behavior that triggers a behavior and keeps it pressed it until another key is pressed and released.
|
||||
|
||||
See the [sticky key behavior](../behaviors/sticky-key.md) and [sticky layer behavior](../behaviors/sticky-layer.md) documentation for more details and examples.
|
||||
|
||||
### Devicetree
|
||||
|
||||
Definition file: [zmk/app/dts/bindings/behaviors/zmk,behavior-sticky-key.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/behaviors/zmk%2Cbehavior-sticky-key.yaml)
|
||||
|
||||
Applies to: `compatible = "zmk,behavior-sticky-key"`
|
||||
|
||||
| Property | Type | Description | Default |
|
||||
| ------------------ | ------------- | ------------------------------------------------------------------------ | ------- |
|
||||
| `label` | string | Unique label for the node | |
|
||||
| `#binding-cells` | int | Must match the number of parameters the `bindings` behavior uses | |
|
||||
| `bindings` | phandle array | A behavior (without parameters) to trigger | |
|
||||
| `release-after-ms` | int | Releases the key after this many milliseconds if no other key is pressed | 1000 |
|
||||
| `quick-release` | bool | Release the sticky key on the next key press instead of release | false |
|
||||
| `ignore-modifiers` | bool | If enabled, pressing a modifier key does not cancel the sticky key | true |
|
||||
|
||||
You can use the following nodes to tweak the default behaviors:
|
||||
|
||||
| Node | Behavior |
|
||||
| ----- | -------------------------------------------- |
|
||||
| `&sk` | [Sticky key](../behaviors/sticky-key.md) |
|
||||
| `&sl` | [Sticky layer](../behaviors/sticky-layer.md) |
|
||||
|
||||
## Tap Dance
|
||||
|
||||
Creates a custom behavior that triggers a different behavior corresponding to the number of times the key is tapped.
|
||||
|
||||
### Devicetree
|
||||
|
||||
Definition file: [zmk/app/dts/bindings/behaviors/zmk,behavior-tap-dance.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/behaviors/zmk%2Cbehavior-tap-dance.yaml)
|
||||
|
||||
Applies to: `compatible = "zmk,behavior-tap-dance"`
|
||||
|
||||
| Property | Type | Description | Default |
|
||||
| ----------------- | ------------- | -------------------------------------------------------------------------------------------- | ------- |
|
||||
| `label` | string | Unique label for the node | |
|
||||
| `#binding-cells` | int | Must be `<0>` | |
|
||||
| `bindings` | phandle array | A list of behaviors from which to select | |
|
||||
| `tapping-term-ms` | int | The maximum time (in milliseconds) between taps before an item from `bindings` is triggered. | 200 |
|
42
docs/docs/config/combos.md
Normal file
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
title: Combo Configuration
|
||||
sidebar_label: Combos
|
||||
---
|
||||
|
||||
See the [Combos feature page](../features/combos.md) for more details and examples.
|
||||
|
||||
See [Configuration Overview](index.md) for instructions on how to change these settings.
|
||||
|
||||
## Kconfig
|
||||
|
||||
Definition file: [zmk/app/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/Kconfig)
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ------------------------------------- | ---- | -------------------------------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_COMBO_MAX_PRESSED_COMBOS` | int | Maximum number of combos that can be active at the same time | 4 |
|
||||
| `CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY` | int | Maximum number of active combos that use the same key position | 5 |
|
||||
| `CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO` | int | Maximum number of keys to press to activate a combo | 4 |
|
||||
|
||||
If `CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY` is 5, you can have 5 separate combos that use position `0`, 5 combos that use position `1`, and so on.
|
||||
|
||||
If you want a combo that triggers when pressing 5 keys, you must set `CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO` to 5.
|
||||
|
||||
## Devicetree
|
||||
|
||||
Applies to: `compatible = "zmk,combos"`
|
||||
|
||||
Definition file: [zmk/app/dts/bindings/zmk,combos.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/zmk%2Ccombos.yaml)
|
||||
|
||||
The `zmk,combos` node itself has no properties. It should have one child node per combo.
|
||||
|
||||
Each child node can have the following properties:
|
||||
|
||||
| Property | Type | Description | Default |
|
||||
| --------------- | ------------- | ----------------------------------------------------------------------------------------------------- | ------- |
|
||||
| `bindings` | phandle-array | A [behavior](../features/keymaps.md#behaviors) to run when the combo is triggered | |
|
||||
| `key-positions` | array | A list of key position indices for the keys which should trigger the combo | |
|
||||
| `timeout-ms` | int | All the keys in `key-positions` must be pressed within this time in milliseconds to trigger the combo | 50 |
|
||||
| `slow-release` | bool | Releases the combo when all keys are released instead of when any key is released | false |
|
||||
| `layers` | array | A list of layers on which the combo may be triggered. `-1` allows all layers. | `<-1>` |
|
||||
|
||||
The `key-positions` array must not be longer than the `CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO` setting, which defaults to 4. If you want a combo that triggers when pressing 5 keys, then you must change the setting to 5.
|
60
docs/docs/config/displays.md
Normal file
|
@ -0,0 +1,60 @@
|
|||
---
|
||||
title: Display Configuration
|
||||
sidebar_label: Displays
|
||||
---
|
||||
|
||||
See the [displays feature page](../features/displays.md) for more details.
|
||||
|
||||
See [Configuration Overview](index.md) for instructions on how to change these settings.
|
||||
|
||||
## Kconfig
|
||||
|
||||
Definition files:
|
||||
|
||||
- [zmk/app/src/display/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/src/display/Kconfig)
|
||||
- [zmk/app/src/display/widgets/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/src/display/widgets/Kconfig)
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ---------------------------------- | ---- | ---------------------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_DISPLAY` | bool | Enable support for displays | n |
|
||||
| `CONFIG_ZMK_WIDGET_LAYER_STATUS` | bool | Enable a widget to show the highest, active layer | y |
|
||||
| `CONFIG_ZMK_WIDGET_BATTERY_STATUS` | bool | Enable a widget to show battery charge information | y |
|
||||
| `CONFIG_ZMK_WIDGET_OUTPUT_STATUS` | bool | Enable a widget to show the current output (USB/BLE) | y |
|
||||
| `CONFIG_ZMK_WIDGET_WPM_STATUS` | bool | Enable a widget to show words per minute | n |
|
||||
|
||||
If `CONFIG_ZMK_DISPLAY` is enabled, exactly zero or one of the following options must be set to `y`. The first option is used if none are set.
|
||||
|
||||
| Config | Description |
|
||||
| ------------------------------------------- | ------------------------------ |
|
||||
| `CONFIG_ZMK_DISPLAY_STATUS_SCREEN_BUILT_IN` | Use the built-in status screen |
|
||||
| `CONFIG_ZMK_DISPLAY_STATUS_SCREEN_CUSTOM` | Use a custom status screen |
|
||||
|
||||
If `CONFIG_ZMK_DISPLAY` is enabled, exactly zero or one of the following options must be set to `y`. The first option is used if none are set.
|
||||
|
||||
| Config | Description |
|
||||
| ----------------------------------------- | ----------------------------------------- |
|
||||
| `CONFIG_ZMK_DISPLAY_WORK_QUEUE_SYSTEM` | Use the system main thread for UI updates |
|
||||
| `CONFIG_ZMK_DISPLAY_WORK_QUEUE_DEDICATED` | Use a dedicated thread for UI updates |
|
||||
|
||||
Using a dedicated thread requires more memory but prevents displays with slow updates (e.g. E-paper) from delaying key scanning and other processes. If enabled, the following options configure the thread:
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ------------------------------------------------ | ---- | ---------------------------- | ------- |
|
||||
| `CONFIG_ZMK_DISPLAY_DEDICATED_THREAD_STACK_SIZE` | int | Stack size for the UI thread | 2048 |
|
||||
| `CONFIG_ZMK_DISPLAY_DEDICATED_THREAD_PRIORITY` | int | Priority for the UI thread | 5 |
|
||||
|
||||
You must also configure the driver for your display. ZMK provides the following display drivers:
|
||||
|
||||
- [IL0323](https://github.com/zmkfirmware/zmk/blob/main/app/drivers/display/Kconfig.il0323)
|
||||
|
||||
Zephyr provides several display drivers as well. Search for the name of your display in [Zephyr's Kconfig options](https://docs.zephyrproject.org/latest/kconfig.html) documentation.
|
||||
|
||||
## Devicetree
|
||||
|
||||
See the Devicetree bindings for your display. Here are the bindings for common displays:
|
||||
|
||||
- [IL0323](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/display/gooddisplay%2Cil0323.yaml)
|
||||
- [SSD1306 (i2c)](https://docs.zephyrproject.org/latest/build/dts/api/bindings/display/solomon,ssd1306fb-i2c.html)
|
||||
- [SSD1306 (spi)](https://docs.zephyrproject.org/latest/build/dts/api/bindings/display/solomon,ssd1306fb-spi.html)
|
||||
|
||||
A full list of drivers provided by Zephyr can be found in [Zephyr's Devicetree bindings index](https://docs.zephyrproject.org/latest/build/dts/api/bindings.html).
|
41
docs/docs/config/encoders.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
---
|
||||
title: Encoder Configuration
|
||||
sidebar_label: Encoders
|
||||
---
|
||||
|
||||
See the [Encoders feature page](../features/encoders.md) for more details, including instructions for adding encoder support to a board.
|
||||
|
||||
See [Configuration Overview](index.md) for instructions on how to change these settings.
|
||||
|
||||
## EC11 Encoders
|
||||
|
||||
### Kconfig
|
||||
|
||||
Definition file: [zmk/app/drivers/sensor/ec11/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/drivers/sensor/ec11/Kconfig)
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ------------------------------- | ---- | -------------------------------- | ------- |
|
||||
| `CONFIG_EC11` | bool | Enable EC11 encoders | n |
|
||||
| `CONFIG_EC11_THREAD_PRIORITY` | int | Priority of the encoder thread | 10 |
|
||||
| `CONFIG_EC11_THREAD_STACK_SIZE` | int | Stack size of the encoder thread | 1024 |
|
||||
|
||||
If `CONFIG_EC11` is enabled, exactly one of the following options must be set to `y`:
|
||||
|
||||
| Config | Type | Description |
|
||||
| ----------------------------------- | ---- | ----------------------------------------------- |
|
||||
| `CONFIG_EC11_TRIGGER_NONE` | bool | No trigger (encoders are disabled) |
|
||||
| `CONFIG_EC11_TRIGGER_GLOBAL_THREAD` | bool | Process encoder interrupts on the global thread |
|
||||
| `CONFIG_EC11_TRIGGER_OWN_THREAD` | bool | Process encoder interrupts on their own thread |
|
||||
|
||||
### Devicetree
|
||||
|
||||
Applies to: `compatible = "alps,ec11"`
|
||||
|
||||
Definition file: [zmk/app/drivers/zephyr/dts/bindings/sensor/alps,ec11.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/drivers/zephyr/dts/bindings/sensor/alps%2Cec11.yaml)
|
||||
|
||||
| Property | Type | Description | Default |
|
||||
| ------------ | ---------- | ------------------------------------- | ------- |
|
||||
| `label` | string | Unique label for the node | |
|
||||
| `a-gpios` | GPIO array | GPIO connected to the encoder's A pin | |
|
||||
| `b-gpios` | GPIO array | GPIO connected to the encoder's B pin | |
|
||||
| `resolution` | int | Number of encoder pulses per tick | 1 |
|
259
docs/docs/config/index.md
Normal file
|
@ -0,0 +1,259 @@
|
|||
---
|
||||
title: Configuration Overview
|
||||
sidebar_label: Overview
|
||||
---
|
||||
|
||||
ZMK has many configuration settings that can be changed to change the behavior of your keyboard. They are set in either Kconfig or Devicetree files.
|
||||
|
||||
This page describes the Kconfig and Devicetree file formats and how to change settings in them. See the other pages in the configuration section for a list of settings you can change.
|
||||
|
||||
:::note
|
||||
All configuration is currently set at compile time. After changing any settings, you must build new firmware and flash it for the changes to apply.
|
||||
:::
|
||||
|
||||
## Config File Locations
|
||||
|
||||
ZMK will search multiple folders for the config files described below. There are three primary locations it will search:
|
||||
|
||||
### User Config Folder
|
||||
|
||||
When building with a `zmk-config` folder, ZMK will search the `zmk-config/config` folder for the following config files, where `<name>` is the name of the shield if using a shield, or the name of the board otherwise:
|
||||
|
||||
- `<name>.conf` (Kconfig)
|
||||
- `<name>.keymap` (Devicetree)
|
||||
|
||||
These files hold your personal settings for the keyboard. All files are optional. If present, they override any configuration set in the board or shield folders. Otherwise, the default configuration and/or keymap is used.
|
||||
|
||||
When using a split keyboard, you can use a single file without the `_left` or `_right` suffix to configure both sides. For example, `corne.conf` and `corne.keymap` will apply to both `corne_left` and `corne_right`. If a shared config file exists, any left or right files will be ignored.
|
||||
|
||||
### Board Folder
|
||||
|
||||
ZMK will search for config files in either of:
|
||||
|
||||
- [`zmk/app/boards/arm/<board>`](https://github.com/zmkfirmware/zmk/tree/main/app/boards/arm)
|
||||
- `zmk-config/config/boards/arm/<board>`
|
||||
|
||||
...where `<board>` is the name of the board. These files describe the hardware of the board.
|
||||
|
||||
ZMK will search the board folder for the following config files:
|
||||
|
||||
- `<board>_defconfig` (Kconfig)
|
||||
- `<board>.conf` (Kconfig)
|
||||
- `<board>.dts` (Devicetree)
|
||||
- `<board>.keymap` (Devicetree, keyboards with onboard controllers only)
|
||||
|
||||
Shared config files (excluding any `_left` or `_right` suffix) are not currently supported in board folders.
|
||||
|
||||
For more documentation on creating and configuring a new board, see [Zephyr's board porting guide](https://docs.zephyrproject.org/latest/hardware/porting/board_porting.html#write-kconfig-files).
|
||||
|
||||
### Shield Folder
|
||||
|
||||
When building with a shield, ZMK will search for config files in either of:
|
||||
|
||||
- [`zmk/app/boards/shields/<shield>`](https://github.com/zmkfirmware/zmk/tree/main/app/boards/shields)
|
||||
- `zmk-config/config/boards/shields/<shield>`
|
||||
|
||||
...where `<shield>` is the name of the shield. These files describe the hardware of the shield that the board is plugged into.
|
||||
|
||||
ZMK will search the shield folder for the following config files:
|
||||
|
||||
- `<shield>.conf` (Kconfig)
|
||||
- `<shield>.overlay` (Devicetree)
|
||||
- `<shield>.keymap` (Devicetree)
|
||||
|
||||
Shared config files (excluding any `_left` or `_right` suffix) are not currently supported in shield folders.
|
||||
|
||||
For more documentation on creating and configuring a new shield, see [Zephyr's shield documentation](https://docs.zephyrproject.org/latest/hardware/porting/shields.html) and [ZMK's new keyboard shield](../development/new-shield.md) guide.
|
||||
|
||||
## Kconfig Files
|
||||
|
||||
Kconfig is used to configure global settings such as the keyboard name and enabling certain hardware devices. These typically have a `.conf` file extension and are text files containing `CONFIG_XYZ=value` assignments, with one setting per line.
|
||||
|
||||
Kconfig files look like this:
|
||||
|
||||
```
|
||||
CONFIG_ZMK_SLEEP=y
|
||||
CONFIG_EC11=y
|
||||
CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y
|
||||
```
|
||||
|
||||
The list of available settings is determined by various files in ZMK whose names start with `Kconfig`. Files ending with `_defconfig` use the same syntax, but are intended for setting configuration specific to the hardware which users typically won't need to change. Note that options are _not_ prefixed with `CONFIG_` in these files.
|
||||
|
||||
See [Zephyr's Kconfig documentation](https://docs.zephyrproject.org/latest/build/kconfig/index.html) for more details on Kconfig files.
|
||||
|
||||
### KConfig Value Types
|
||||
|
||||
#### bool
|
||||
|
||||
Either `y` for yes or `n` for no.
|
||||
|
||||
Example: `CONFIG_FOO=y`
|
||||
|
||||
#### int
|
||||
|
||||
An integer.
|
||||
|
||||
Example: `CONFIG_FOO=42`
|
||||
|
||||
#### string
|
||||
|
||||
Text surrounded by double quotes.
|
||||
|
||||
Example: `CONFIG_FOO="foo"`
|
||||
|
||||
## Devicetree Files
|
||||
|
||||
Various Devicetree files are combined to build a tree that describes the hardware for a keyboard. They are also used to define keymaps.
|
||||
|
||||
Devicetree files use various file extensions. These indicate the purpose of the file, but they have no effect on how the file is processed. Common file extensions for Devicetree files include:
|
||||
|
||||
- `.dts`: The base hardware definition.
|
||||
- `.overlay`: Adds to and/or overrides definitions in a `.dts` file.
|
||||
- `.keymap`: Holds a keymap and user-specific hardware configuration.
|
||||
- `.dtsi`: A file which is only intended to be `#include`d from another file.
|
||||
|
||||
Devicetree files look like this:
|
||||
|
||||
```devicetree
|
||||
/ {
|
||||
chosen {
|
||||
zmk,kscan = &kscan0;
|
||||
};
|
||||
|
||||
kscan0: kscan {
|
||||
compatible = "zmk,kscan-gpio-matrix";
|
||||
label = "KSCAN";
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Devicetree properties apply to specific nodes in the tree instead of globally. The properties that can be set for each node are determined by `.yaml` files in ZMK in the various `dts/bindings` folders.
|
||||
|
||||
See [Zephyr's Devicetree guide](https://docs.zephyrproject.org/latest/build/dts/index.html) for more details on Devicetree files.
|
||||
|
||||
### Changing Devicetree Properties
|
||||
|
||||
Since Devicetree properties are set for specific nodes in the tree, you will first need to find the node you want to configure. You will typically need to
|
||||
search through the `.dts` file for your board, `.overlay` file for your shield, or a `.dtsi` file included by those files using an `#include` statement.
|
||||
|
||||
A Devicetree node looks like this:
|
||||
|
||||
```devicetree
|
||||
kscan0: kscan {
|
||||
compatible = "zmk,kscan-gpio-matrix";
|
||||
// more properties and/or nodes...
|
||||
};
|
||||
```
|
||||
|
||||
The part before the colon, `kscan0`, is a label. This is optional, and it provides a shortcut to allow changing the properties of the node. The part after the colon, `kscan`, is the node's name. The values inside the curly braces are the node's properties.
|
||||
|
||||
The `compatible` property indicates what type of node it is. Search this documentation for the text inside the quotes to see which properties the node
|
||||
supports. You can also search ZMK for a file whose name is the value of the `compatible` property with a `.yaml` file extension.
|
||||
|
||||
To set a property, see below for examples for common property types, or see [Zephyr's Devicetree documentation](https://docs.zephyrproject.org/latest/build/dts/intro.html#writing-property-values) for more details on the syntax for properties.
|
||||
|
||||
To change a property for an existing node, first find the node you want to change and find its label. Next, outside of any other node, write an ampersand (`&`)
|
||||
followed by the node's label, an opening curly brace (`{`), one or more new property values, a closing curly brace (`}`), and a semicolon (`;`).
|
||||
|
||||
For example, to adjust the debouncing of the `zmk,kscan-gpio-matrix` node shown above, you could add this to your keymap:
|
||||
|
||||
```devicetree
|
||||
&kscan0 {
|
||||
debounce-press-ms = <0>;
|
||||
};
|
||||
```
|
||||
|
||||
If the node you want to edit doesn't have a label, you can also write a new tree and it will be merged with the existing tree, overriding any properties. Adding this to your keymap would be equivalent to the previous example.
|
||||
|
||||
```devicetree
|
||||
/ {
|
||||
kscan {
|
||||
debounce-press-ms = <0>;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
### Devicetree Property Types
|
||||
|
||||
These are some of the property types you will see most often when working with ZMK. [Zephyr's Devicetree bindings documentation](https://docs.zephyrproject.org/latest/build/dts/bindings.html) provides more detailed information and a full list of types.
|
||||
|
||||
#### bool
|
||||
|
||||
True or false. To set the property to true, list it with no value. To set it to false, do not list it.
|
||||
|
||||
Example: `property;`
|
||||
|
||||
If a property has already been set to true and you need to override it to false, use the following command to delete the existing property:
|
||||
|
||||
```devicetree
|
||||
/delete-property/ the-property-name;
|
||||
```
|
||||
|
||||
#### int
|
||||
|
||||
A single integer surrounded by angle brackets. Also supports mathematical expressions.
|
||||
|
||||
Example: `property = <42>;`
|
||||
|
||||
#### string
|
||||
|
||||
Text surrounded by double quotes.
|
||||
|
||||
Example: `property = "foo";`
|
||||
|
||||
#### array
|
||||
|
||||
A list of integers surrounded by angle brackets and separated with spaces. Mathematical expressions can be used but must be surrounded by parenthesis.
|
||||
|
||||
Example: `property = <1 2 3 4>;`
|
||||
|
||||
Values can also be split into multiple blocks, e.g. `property = <1 2>, <3 4>;`
|
||||
|
||||
#### phandle
|
||||
|
||||
A single node reference surrounded by angle brackets.
|
||||
|
||||
Example: `property = <&label>`
|
||||
|
||||
#### phandles
|
||||
|
||||
A list of node references surrounded by angle brackets.
|
||||
|
||||
Example: `property = <&label1 &label2 &label3>`
|
||||
|
||||
#### phandle array
|
||||
|
||||
A list of node references and possibly numbers to associate with the node. Mathematical expressions can be used but must be surrounded by parenthesis.
|
||||
|
||||
Example: `property = <&none &mo 1>;`
|
||||
|
||||
Values can also be split into multiple blocks, e.g. `property = <&none>, <&mo 1>;`
|
||||
|
||||
See the documentation for "phandle-array" in [Zephyr's Devicetree bindings documentation](https://docs.zephyrproject.org/latest/build/dts/bindings.html)
|
||||
for more details on how parameters are associated with nodes.
|
||||
|
||||
#### GPIO array
|
||||
|
||||
This is just a phandle array. The documentation lists this as a different type to make it clear which properties expect an array of GPIOs.
|
||||
|
||||
Each item in the array should be a label for a GPIO node (the names of which differ between hardware platforms) followed by an index and configuration flags. See [Zephyr's GPIO documentation](https://docs.zephyrproject.org/latest/hardware/peripherals/gpio.html) for a full list of flags.
|
||||
|
||||
Example:
|
||||
|
||||
```devicetree
|
||||
some-gpios =
|
||||
<&gpio0 0 GPIO_ACTIVE_HIGH>,
|
||||
<&gpio0 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
;
|
||||
```
|
||||
|
||||
#### path
|
||||
|
||||
A path to a node, either as a node reference or as a string.
|
||||
|
||||
Examples:
|
||||
|
||||
```
|
||||
property = &label;
|
||||
property = "/path/to/some/node";
|
||||
```
|
42
docs/docs/config/keymap.md
Normal file
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
title: Keymap Configuration
|
||||
sidebar_label: Keymap
|
||||
---
|
||||
|
||||
See [Configuration Overview](index.md) for instructions on how to change these settings.
|
||||
|
||||
## Keymap
|
||||
|
||||
### Devicetree
|
||||
|
||||
Applies to: `compatible = "zmk,keymap"`
|
||||
|
||||
Definition file: [zmk/app/dts/bindings/zmk,keymap.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/zmk%2Ckeymap.yaml)
|
||||
|
||||
The `zmk,keymap` node itself has no properties. It should have one child node per layer of the keymap, starting with the default layer (layer 0).
|
||||
|
||||
Each child node can have the following properties:
|
||||
|
||||
| Property | Type | Description |
|
||||
| ----------------- | ------------- | ---------------------------------------------------------------------- |
|
||||
| `label` | string | Unique label for the node |
|
||||
| `bindings` | phandle-array | List of [key behaviors](../features/keymaps.md#behaviors), one per key |
|
||||
| `sensor-bindings` | phandle-array | List of sensor behaviors, one per sensor |
|
||||
|
||||
Items for `bindings` must be listed in the order the keys are defined in the [keyboard scan configuration](kscan.md).
|
||||
|
||||
Items for `sensor-bindings` must be listed in the order the [sensors](#keymap-sensors) are defined.
|
||||
|
||||
## Keymap Sensors
|
||||
|
||||
### Devicetree
|
||||
|
||||
Applies to: `compatible = "zmk,keymap-sensors"`
|
||||
|
||||
| Property | Type | Description |
|
||||
| --------- | -------- | -------------------- |
|
||||
| `sensors` | phandles | List of sensor nodes |
|
||||
|
||||
The following types of nodes can be used as a sensor:
|
||||
|
||||
- [`alps,ec11`](encoders.md#ec11-encoders)
|
385
docs/docs/config/kscan.md
Normal file
|
@ -0,0 +1,385 @@
|
|||
---
|
||||
title: Keyboard Scan Configuration
|
||||
sidebar_label: Keyboard Scan
|
||||
---
|
||||
|
||||
See [Configuration Overview](index.md) for instructions on how to change these settings.
|
||||
|
||||
## Common
|
||||
|
||||
### Kconfig
|
||||
|
||||
Definition files:
|
||||
|
||||
- [zmk/app/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/Kconfig)
|
||||
- [zmk/app/drivers/kscan/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/drivers/kscan/Kconfig)
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| -------------------------------------- | ---- | ---------------------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_KSCAN_EVENT_QUEUE_SIZE` | int | Size of the event queue for kscan events | 4 |
|
||||
| `CONFIG_ZMK_KSCAN_INIT_PRIORITY` | int | Keyboard scan device driver initialization priority | 40 |
|
||||
| `CONFIG_ZMK_KSCAN_DEBOUNCE_PRESS_MS` | int | Global debounce time for key press in milliseconds | -1 |
|
||||
| `CONFIG_ZMK_KSCAN_DEBOUNCE_RELEASE_MS` | int | Global debounce time for key release in milliseconds | -1 |
|
||||
|
||||
If the debounce press/release values are set to any value other than `-1`, they override the `debounce-press-ms` and `debounce-release-ms` devicetree properties for all keyboard scan drivers which support them. See the [debouncing documentation](../features/debouncing.md) for more details.
|
||||
|
||||
### Devicetree
|
||||
|
||||
Applies to: [`/chosen` node](https://docs.zephyrproject.org/latest/guides/dts/intro.html#aliases-and-chosen-nodes)
|
||||
|
||||
| Property | Type | Description |
|
||||
| ---------------------- | ---- | ------------------------------------------------------------- |
|
||||
| `zmk,kscan` | path | The node for the keyboard scan driver to use |
|
||||
| `zmk,matrix_transform` | path | The node for the [matrix transform](#matrix-transform) to use |
|
||||
|
||||
## Demux Driver
|
||||
|
||||
Keyboard scan driver which works like a regular matrix but uses a demultiplexer to drive the rows or columns. This allows N GPIOs to drive N<sup>2</sup> rows or columns instead of just N like with a regular matrix.
|
||||
|
||||
:::note
|
||||
Currently this driver does not honor the `CONFIG_ZMK_KSCAN_DEBOUNCE_*` settings.
|
||||
:::
|
||||
|
||||
### Devicetree
|
||||
|
||||
Applies to: `compatible = "zmk,kscan-gpio-demux"`
|
||||
|
||||
Definition file: [zmk/app/drivers/zephyr/dts/bindings/kscan/zmk,kscan-gpio-demux.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/drivers/zephyr/dts/bindings/kscan/zmk%2Ckscan-gpio-demux.yaml)
|
||||
|
||||
| Property | Type | Description | Default |
|
||||
| ----------------------- | ---------- | -------------------------------- | ------- |
|
||||
| `label` | string | Unique label for the node | |
|
||||
| `input-gpios` | GPIO array | Input GPIOs | |
|
||||
| `output-gpios` | GPIO array | Demultiplexer address GPIOs | |
|
||||
| `debounce-period` | int | Debounce period in milliseconds | 5 |
|
||||
| `polling-interval-msec` | int | Polling interval in milliseconds | 25 |
|
||||
|
||||
## Direct GPIO Driver
|
||||
|
||||
Keyboard scan driver where each key has a dedicated GPIO.
|
||||
|
||||
### Kconfig
|
||||
|
||||
Definition file: [zmk/app/drivers/kscan/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/drivers/kscan/Kconfig)
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| --------------------------------- | ---- | ------------------------------------------------ | ------- |
|
||||
| `CONFIG_ZMK_KSCAN_DIRECT_POLLING` | bool | Poll for key presses instead of using interrupts | n |
|
||||
|
||||
### Devicetree
|
||||
|
||||
Applies to: `compatible = "zmk,kscan-gpio-direct"`
|
||||
|
||||
Definition file: [zmk/app/drivers/zephyr/dts/bindings/kscan/zmk,kscan-gpio-direct.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/drivers/zephyr/dts/bindings/kscan/zmk%2Ckscan-gpio-direct.yaml)
|
||||
|
||||
| Property | Type | Description | Default |
|
||||
| ------------------------- | ---------- | ----------------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| `label` | string | Unique label for the node | |
|
||||
| `input-gpios` | GPIO array | Input GPIOs (one per key) | |
|
||||
| `debounce-press-ms` | int | Debounce time for key press in milliseconds. Use 0 for eager debouncing. | 5 |
|
||||
| `debounce-release-ms` | int | Debounce time for key release in milliseconds. | 5 |
|
||||
| `debounce-scan-period-ms` | int | Time between reads in milliseconds when any key is pressed. | 1 |
|
||||
| `diode-direction` | string | The direction of the matrix diodes | `"row2col"` |
|
||||
| `poll-period-ms` | int | Time between reads in milliseconds when no key is pressed and `CONFIG_ZMK_KSCAN_DIRECT_POLLING` is enabled. | 10 |
|
||||
| `toggle-mode` | bool | Use toggle switch mode. | n |
|
||||
|
||||
By default, a switch will drain current through the internal pull up/down resistor whenever it is pressed. This is not ideal for a toggle switch, where the switch may be left in the "pressed" state for a long time. Enabling `toggle-mode` will make the driver flip between pull up and down as the switch is toggled to optimize for power.
|
||||
|
||||
`toggle-mode` applies to all switches handled by the instance of the driver. To use a toggle switch with other, non-toggle, direct GPIO switches, create two instances of the direct GPIO driver, one with `toggle-mode` and the other without. Then, use a [composite driver](#composite-driver) to combine them.
|
||||
|
||||
## Matrix Driver
|
||||
|
||||
Keyboard scan driver where keys are arranged on a matrix with one GPIO per row and column.
|
||||
|
||||
Definition file: [zmk/app/drivers/kscan/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/drivers/kscan/Kconfig)
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| --------------------------------- | ---- | ------------------------------------------------ | ------- |
|
||||
| `CONFIG_ZMK_KSCAN_MATRIX_POLLING` | bool | Poll for key presses instead of using interrupts | n |
|
||||
|
||||
### Devicetree
|
||||
|
||||
Applies to: `compatible = "zmk,kscan-gpio-matrix"`
|
||||
|
||||
Definition file: [zmk/app/drivers/zephyr/dts/bindings/kscan/zmk,kscan-gpio-matrix.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/drivers/zephyr/dts/bindings/kscan/zmk%2Ckscan-gpio-matrix.yaml)
|
||||
|
||||
| Property | Type | Description | Default |
|
||||
| ------------------------- | ---------- | ----------------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| `label` | string | Unique label for the node | |
|
||||
| `row-gpios` | GPIO array | Matrix row GPIOs in order, starting from the top row | |
|
||||
| `col-gpios` | GPIO array | Matrix column GPIOs in order, starting from the leftmost row | |
|
||||
| `debounce-press-ms` | int | Debounce time for key press in milliseconds. Use 0 for eager debouncing. | 5 |
|
||||
| `debounce-release-ms` | int | Debounce time for key release in milliseconds. | 5 |
|
||||
| `debounce-scan-period-ms` | int | Time between reads in milliseconds when any key is pressed. | 1 |
|
||||
| `diode-direction` | string | The direction of the matrix diodes | `"row2col"` |
|
||||
| `poll-period-ms` | int | Time between reads in milliseconds when no key is pressed and `CONFIG_ZMK_KSCAN_MATRIX_POLLING` is enabled. | 10 |
|
||||
|
||||
The `diode-direction` property must be one of:
|
||||
|
||||
| Value | Description |
|
||||
| ----------- | --------------------------------------------------------------------- |
|
||||
| `"row2col"` | Diodes point from rows to columns (cathodes are connected to columns) |
|
||||
| `"col2row"` | Diodes point from columns to rows (cathodes are connected to rows) |
|
||||
|
||||
## Composite Driver
|
||||
|
||||
Keyboard scan driver which combines multiple other keyboard scan drivers.
|
||||
|
||||
### Devicetree
|
||||
|
||||
Applies to : `compatible = "zmk,kscan-composite"`
|
||||
|
||||
Definition file: [zmk/app/dts/bindings/zmk,kscan-composite.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/zmk,kscan-composite.yaml)
|
||||
|
||||
| Property | Type | Description | Default |
|
||||
| -------- | ------ | --------------------------------------------- | ------- |
|
||||
| `label` | string | Unique label for the node | |
|
||||
| `rows` | int | The number of rows in the composite matrix | |
|
||||
| `cols` | int | The number of columns in the composite matrix | |
|
||||
|
||||
The `zmk,kscan-composite` node should have one child node per keyboard scan driver that should be composited. Each child node can have the following properties:
|
||||
|
||||
| Property | Type | Description | Default |
|
||||
| --------------- | ------- | ------------------------------------------------------------------------------ | ------- |
|
||||
| `label` | string | Unique label for the node | |
|
||||
| `kscan` | phandle | Label of the kscan driver to include | |
|
||||
| `row-offset` | int | Shifts row 0 of the included driver to a new row in the composite matrix | 0 |
|
||||
| `column-offset` | int | Shifts column 0 of the included driver to a new column in the composite matrix | 0 |
|
||||
|
||||
### Example Configuration
|
||||
|
||||
For example, consider a macropad with a 3x3 matrix and two direct GPIO keys:
|
||||
|
||||
<div style={{columns: 2, marginBottom: '1em'}}>
|
||||
<div style={{breakInside: 'avoid'}}>
|
||||
Matrix:
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th></th><th>Col 0</th><th>Col 1</th><th>Col 2</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><th>Row 0</th><td>A0</td><td>A1</td><td>A2</td></tr>
|
||||
<tr><th>Row 1</th><td>A3</td><td>A4</td><td>A5</td></tr>
|
||||
<tr><th>Row 2</th><td>A6</td><td>A7</td><td>A8</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div style={{breakInside: 'avoid'}}>
|
||||
Direct GPIO:
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th></th><th>Col 0</th><th>Col 1</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><th>Row 0</th><td>B0</td><td>B1</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
To combine them, we need to create a composite matrix with enough rows and columns to fit both sets of keys without overlapping, then set row and/or columns offsets to shift them so they do not overlap.
|
||||
|
||||
One possible way to do this is a 3x4 matrix where the direct GPIO keys are shifted to below the matrix keys...
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th></th><th>Col 0</th><th>Col 1</th><th>Col 2</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><th>Row 0</th><td>A0</td><td>A1</td><td>A2</td></tr>
|
||||
<tr><th>Row 1</th><td>A3</td><td>A4</td><td>A5</td></tr>
|
||||
<tr><th>Row 2</th><td>A6</td><td>A7</td><td>A8</td></tr>
|
||||
<tr><th>Row 3</th><td>B0</td><td>B1</td><td>(none)</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
...which can be configured with the following Devicetree code:
|
||||
|
||||
```devicetree
|
||||
/ {
|
||||
chosen {
|
||||
zmk,kscan = &kscan0;
|
||||
};
|
||||
|
||||
kscan0: kscan_composite {
|
||||
compatible = "zmk,kscan-composite";
|
||||
label = "KSCAN0";
|
||||
rows = <4>;
|
||||
columns = <3>;
|
||||
|
||||
// Include the matrix driver
|
||||
matrix {
|
||||
kscan = <&kscan1>;
|
||||
};
|
||||
|
||||
// Include the direct GPIO driver...
|
||||
direct {
|
||||
kscan = <&kscan2>;
|
||||
row-offset = <3>; // ...and shift it to not overlap
|
||||
};
|
||||
};
|
||||
|
||||
kscan1: kscan_matrix {
|
||||
compatible = "zmk,kscan-gpio-matrix";
|
||||
// define 3x3 matrix here...
|
||||
};
|
||||
|
||||
kscan2: kscan_direct {
|
||||
compatible = "zmk,kscan-gpio-direct";
|
||||
// define 2 direct GPIOs here...
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Mock Driver
|
||||
|
||||
Mock keyboard scan driver that simulates key events.
|
||||
|
||||
### Devicetree
|
||||
|
||||
Applies to: `compatible = "zmk,kscan-mock"`
|
||||
|
||||
Definition file: [zmk/app/dts/bindings/zmk,kscan-mock.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/zmk%2Ckscan-mock.yaml)
|
||||
|
||||
| Property | Type | Description | Default |
|
||||
| -------------- | ------ | --------------------------------------------- | ------- |
|
||||
| `label` | string | Unique label for the node | |
|
||||
| `event-period` | int | Milliseconds between each generated event | |
|
||||
| `events` | array | List of key events to simulate | |
|
||||
| `rows` | int | The number of rows in the composite matrix | |
|
||||
| `cols` | int | The number of columns in the composite matrix | |
|
||||
| `exit-after` | bool | Exit the program after running all events | false |
|
||||
|
||||
The `events` array should be defined using the macros from [dt-bindings/zmk/kscan_mock.h](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/kscan_mock.h).
|
||||
|
||||
## Matrix Transform
|
||||
|
||||
Defines a mapping from keymap logical positions to physical matrix positions.
|
||||
|
||||
Transforms should be used any time the physical layout of a keyboard's keys does not match the layout of its electrical matrix and/or when not all positions in the matrix are used. This applies to most non-ortholinear boards.
|
||||
|
||||
Transforms can also be used for keyboards with multiple layouts. You can define multiple matrix transform nodes, one for each layout, and users can select which one they want from the `/chosen` node in their keymaps.
|
||||
|
||||
See the [new shield guide](../development/new-shield.md#optional-matrix-transform) for more documentation on how to define a matrix transform.
|
||||
|
||||
### Devicetree
|
||||
|
||||
Applies to: `compatible = "zmk,matrix-transform"`
|
||||
|
||||
Definition file: [zmk/app/dts/bindings/zmk,matrix-transform.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/zmk%2Cmatrix-transform.yaml)
|
||||
|
||||
| Property | Type | Description | Default |
|
||||
| ------------ | ----- | --------------------------------------------------------------------- | ------- |
|
||||
| `rows` | int | Number of rows in the transformed matrix | |
|
||||
| `columns` | int | Number of columns in the transformed matrix | |
|
||||
| `row-offset` | int | Adds an offset to all rows before looking them up in the transform | 0 |
|
||||
| `col-offset` | int | Adds an offset to all columns before looking them up in the transform | 0 |
|
||||
| `map` | array | A list of position transforms | |
|
||||
|
||||
The `map` array should be defined using the `RC()` macro from [dt-bindings/zmk/matrix_transform.h](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/matrix_transform.h). It should have one item per logical position in the keymap. Each item should list the physical row and column that should trigger the key in that position.
|
||||
|
||||
### Example: Skipping Unused Positions
|
||||
|
||||
Any keyboard which is not a grid of 1 unit keys will likely have some unused positions in the matrix. A matrix transform can be used to skip the unused positions so users don't have to set them to `&none` in keymaps.
|
||||
|
||||
```devicetree
|
||||
// numpad.overlay
|
||||
/ {
|
||||
chosen {
|
||||
zmk,kscan = &kscan0;
|
||||
zmk,matrix_transform = &default_transform;
|
||||
};
|
||||
|
||||
kscan0: kscan {
|
||||
compatible = "zmk,kscan-gpio-matrix";
|
||||
rows = <5>;
|
||||
columns = <4>;
|
||||
// define the matrix...
|
||||
};
|
||||
|
||||
default_transform: matrix_transform {
|
||||
compatible = "zmk,matrix-transform";
|
||||
rows = <5>;
|
||||
columns = <4>;
|
||||
// ┌───┬───┬───┬───┐
|
||||
// │NUM│ / │ * │ - │
|
||||
// ├───┼───┼───┼───┤
|
||||
// │ 7 │ 8 │ 9 │ + │
|
||||
// ├───┼───┼───┤ │
|
||||
// │ 4 │ 5 │ 6 │ │
|
||||
// ├───┼───┼───┼───┤
|
||||
// │ 1 │ 2 │ 3 │RET│
|
||||
// ├───┴───┼───┤ │
|
||||
// │ 0 │ . │ │
|
||||
// └───────┴───┴───┘
|
||||
map = <
|
||||
RC(0,0) RC(0,1) RC(0,2) RC(0,3)
|
||||
RC(1,0) RC(1,1) RC(1,2) RC(1,3)
|
||||
RC(2,0) RC(2,1) RC(2,2)
|
||||
RC(3,0) RC(3,1) RC(3,2) RC(3,3)
|
||||
RC(4,0) RC(4,1)
|
||||
>;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
```devicetree
|
||||
// numpad.keymap
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
default {
|
||||
bindings = <
|
||||
&kp KP_NUM &kp KP_DIV &kp KP_MULT &kp KP_MINUS
|
||||
&kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS
|
||||
&kp KP_N4 &kp KP_N5 &kp KP_N6
|
||||
&kp KP_N1 &kp KP_N2 &kp KP_N3 &kp KP_ENTER
|
||||
&kp KP_N0 &kp KP_DOT
|
||||
>;
|
||||
};
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Example: Non-standard Matrix
|
||||
|
||||
Consider a keyboard with a [duplex matrix](https://wiki.ai03.com/books/pcb-design/page/matrices-and-duplex-matrix), where the matrix has twice as many rows and half as many columns as the keyboard has keys. A matrix transform can be used to correct for this so that keymaps can match the layout of the keys, not the layout of the matrix.
|
||||
|
||||
```devicetree
|
||||
/ {
|
||||
chosen {
|
||||
zmk,kscan = &kscan0;
|
||||
zmk,matrix_transform = &default_transform;
|
||||
};
|
||||
|
||||
kscan0: kscan {
|
||||
compatible = "zmk,kscan-gpio-matrix";
|
||||
rows = <12>;
|
||||
columns = <8>;
|
||||
// define the matrix...
|
||||
};
|
||||
|
||||
default_transform: matrix_transform {
|
||||
compatible = "zmk,matrix-transform";
|
||||
rows = <6>;
|
||||
columns = <16>;
|
||||
// ESC F1 F2 F3 ...
|
||||
// ` 1 2 3 ...
|
||||
// Tab Q W E ...
|
||||
// Caps A S D ...
|
||||
// Shift Z X C ...
|
||||
// Ctrl Alt ...
|
||||
map = <
|
||||
RC(0,0) RC(1,0) RC(0,1) RC(1,1) // ...
|
||||
RC(2,0) RC(3,0) RC(2,1) RC(3,1) // ...
|
||||
RC(4,0) RC(5,0) RC(4,1) RC(5,1) // ...
|
||||
RC(6,0) RC(7,0) RC(6,1) RC(7,1) // ...
|
||||
RC(8,0) RC(8,1) RC(9,1) // ...
|
||||
RC(10,0) RC(11,0) // ...
|
||||
>;
|
||||
};
|
||||
};
|
||||
```
|
47
docs/docs/config/power.md
Normal file
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
title: Power Management Configuration
|
||||
sidebar_label: Power Management
|
||||
---
|
||||
|
||||
See [Configuration Overview](index.md) for instructions on how to
|
||||
change these settings.
|
||||
|
||||
## Idle/Sleep
|
||||
|
||||
Configuration for entering low power modes when the keyboard is idle.
|
||||
|
||||
In the idle state, peripherals such as displays and lighting are disabled, but the keyboard remains connected to Bluetooth so it can immediately respond when you press a key.
|
||||
|
||||
In the deep sleep state, the keyboard additionally disconnects from Bluetooth and any external power output is disabled. This state uses very little power, but it may take a few seconds to reconnect after waking.
|
||||
|
||||
### Kconfig
|
||||
|
||||
Definition file: [zmk/app/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/Kconfig)
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ------------------------------- | ---- | ----------------------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_IDLE_TIMEOUT` | int | Milliseconds of inactivity before entering idle state | 30000 |
|
||||
| `CONFIG_ZMK_SLEEP` | bool | Enable deep sleep support | n |
|
||||
| `CONFIG_ZMK_IDLE_SLEEP_TIMEOUT` | int | Milliseconds of inactivity before entering deep sleep | 900000 |
|
||||
|
||||
## External Power Control
|
||||
|
||||
Driver for enabling or disabling power to peripherals such as displays and lighting. This driver must be configured to use [power management behaviors](../behaviors/power.md).
|
||||
|
||||
### Kconfig
|
||||
|
||||
Definition file: [zmk/app/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/Kconfig)
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ---------------------- | ---- | ----------------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_EXT_POWER` | bool | Enable support to control external power output | y |
|
||||
|
||||
### Devicetree
|
||||
|
||||
Applies to: `compatible = "zmk,ext-power-generic"`
|
||||
|
||||
| Property | Type | Description |
|
||||
| --------------- | ---------- | ------------------------------------------------------------- |
|
||||
| `label` | string | Unique label for the node |
|
||||
| `control-gpios` | GPIO array | List of GPIOs which should be active to enable external power |
|
||||
| `init-delay-ms` | int | number of milliseconds to delay after initializing the driver |
|
104
docs/docs/config/system.md
Normal file
|
@ -0,0 +1,104 @@
|
|||
---
|
||||
title: System Configuration
|
||||
sidebar_label: System
|
||||
---
|
||||
|
||||
These are general settings that control how the keyboard behaves and which features it supports. Several of these settings come from Zephyr and are not specific to ZMK, but they are listed here because they are relevant to how a keyboard functions.
|
||||
|
||||
See [Configuration Overview](index.md) for instructions on how to change these settings.
|
||||
|
||||
## Kconfig
|
||||
|
||||
Definition file: [zmk/app/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/Kconfig)
|
||||
|
||||
### General
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ------------------------------------ | ------ | ----------------------------------------------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_KEYBOARD_NAME` | string | The name of the keyboard | |
|
||||
| `CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE` | int | Milliseconds to wait after a setting change before writing it to flash memory | 60000 |
|
||||
| `CONFIG_ZMK_WPM` | bool | Enable calculating words per minute | n |
|
||||
| `CONFIG_HEAP_MEM_POOL_SIZE` | int | Size of the heap memory pool | 8192 |
|
||||
| `CONFIG_ZMK_BATTERY_REPORT_INTERVAL` | int | Battery level report interval in seconds | 60 |
|
||||
|
||||
### HID
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ------------------------------------- | ---- | ------------------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_HID_CONSUMER_REPORT_SIZE` | int | Number of consumer keys simultaneously reportable | 6 |
|
||||
|
||||
Exactly zero or one of the following options may be set to `y`. The first is used if none are set.
|
||||
|
||||
| Config | Description |
|
||||
| --------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
||||
| `CONFIG_ZMK_HID_REPORT_TYPE_HKRO` | Enable `CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE` key roll over. |
|
||||
| `CONFIG_ZMK_HID_REPORT_TYPE_NKRO` | Enable full N-key roll over. This may prevent the keyboard from working with some BIOS/UEFI versions. |
|
||||
|
||||
If `CONFIG_ZMK_HID_REPORT_TYPE_HKRO` is enabled, it may be configured with the following options:
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ------------------------------------- | ---- | ------------------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE` | int | Number of keyboard keys simultaneously reportable | 6 |
|
||||
|
||||
Exactly zero or one of the following options may be set to `y`. The first is used if none are set.
|
||||
|
||||
| Config | Description |
|
||||
| --------------------------------------------- | ------------------------------------------------------------------------------------ |
|
||||
| `CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_FULL` | Enable all consumer key codes, but may have compatibility issues with some host OSes |
|
||||
| `CONFIG_ZMK_HID_CONSUMER_REPORT_USAGES_BASIC` | Prevents using some consumer key codes, but allows compatibility with more host OSes |
|
||||
|
||||
### USB
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| --------------------------------- | ------ | --------------------------------------- | --------------- |
|
||||
| `CONFIG_USB` | bool | Enable USB drivers | |
|
||||
| `CONFIG_USB_DEVICE_VID` | int | The vendor ID advertised to USB | `0x1D50` |
|
||||
| `CONFIG_USB_DEVICE_PID` | int | The product ID advertised to USB | `0x615E` |
|
||||
| `CONFIG_USB_DEVICE_MANUFACTURER` | string | The manufacturer name advertised to USB | `"ZMK Project"` |
|
||||
| `CONFIG_USB_HID_POLL_INTERVAL_MS` | int | USB polling interval in milliseconds | 1 |
|
||||
| `CONFIG_ZMK_USB` | bool | Enable ZMK as a USB keyboard | |
|
||||
| `CONFIG_ZMK_USB_INIT_PRIORITY` | int | USB init priority | 50 |
|
||||
|
||||
### Bluetooth
|
||||
|
||||
See [Zephyr's Bluetooth stack architecture documentation](https://docs.zephyrproject.org/latest/guides/bluetooth/bluetooth-arch.html)
|
||||
for more information on configuring Bluetooth.
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ------------------------------------------- | ---- | --------------------------------------------------------------------- | ------- |
|
||||
| `CONFIG_BT` | bool | Enable Bluetooth support | |
|
||||
| `CONFIG_BT_MAX_CONN` | int | Maximum number of simultaneous Bluetooth connections | 5 |
|
||||
| `CONFIG_BT_MAX_PAIRED` | int | Maximum number of paired Bluetooth devices | 5 |
|
||||
| `CONFIG_ZMK_BLE` | bool | Enable ZMK as a Bluetooth keyboard | |
|
||||
| `CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START` | bool | Clears all bond information from the keyboard on startup | n |
|
||||
| `CONFIG_ZMK_BLE_CONSUMER_REPORT_QUEUE_SIZE` | int | Max number of consumer HID reports to queue for sending over BLE | 5 |
|
||||
| `CONFIG_ZMK_BLE_KEYBOARD_REPORT_QUEUE_SIZE` | int | Max number of keyboard HID reports to queue for sending over BLE | 20 |
|
||||
| `CONFIG_ZMK_BLE_INIT_PRIORITY` | int | BLE init priority | 50 |
|
||||
| `CONFIG_ZMK_BLE_THREAD_PRIORITY` | int | Priority of the BLE notify thread | 5 |
|
||||
| `CONFIG_ZMK_BLE_THREAD_STACK_SIZE` | int | Stack size of the BLE notify thread | 512 |
|
||||
| `CONFIG_ZMK_BLE_PASSKEY_ENTRY` | bool | Experimental: require typing passkey from host to pair BLE connection | n |
|
||||
|
||||
Note that `CONFIG_BT_MAX_CONN` and `CONFIG_BT_MAX_PAIRED` should be set to the same value. On a split keyboard they should only be set for the central and must be set to one greater than the desired number of bluetooth profiles.
|
||||
|
||||
### Logging
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ------------------------ | ---- | ---------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_USB_LOGGING` | bool | Enable USB CDC ACM logging for debugging | n |
|
||||
| `CONFIG_ZMK_LOG_LEVEL` | int | Log level for ZMK debug messages | 4 |
|
||||
|
||||
### Split keyboards
|
||||
|
||||
Following split keyboard settings are defined in [zmk/app/src/split/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/src/split/Kconfig) (generic) and [zmk/app/src/split/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/src/split/bluetooth/Kconfig) (bluetooth).
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ----------------------------------------------------- | ---- | ----------------------------------------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_SPLIT` | bool | Enable split keyboard support | n |
|
||||
| `CONFIG_ZMK_SPLIT_BLE` | bool | Use BLE to communicate between split keyboard halves | y |
|
||||
| `CONFIG_ZMK_SPLIT_ROLE_CENTRAL` | bool | `y` for central device, `n` for peripheral | |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE` | int | Max number of key state events to queue when received from peripherals | 5 |
|
||||
| `CONFIG_ZMK_BLE_SPLIT_CENTRAL_SPLIT_RUN_STACK_SIZE` | int | Stack size of the BLE split central write thread | 512 |
|
||||
| `CONFIG_ZMK_BLE_SPLIT_CENTRAL_SPLIT_RUN_QUEUE_SIZE` | int | Max number of behavior run events to queue to send to the peripheral(s) | 5 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE` | int | Stack size of the BLE split peripheral notify thread | 650 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_PRIORITY` | int | Priority of the BLE split peripheral notify thread | 5 |
|
||||
| `CONFIG_ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE` | int | Max number of key state events to queue to send to the central | 10 |
|
49
docs/docs/config/underglow.md
Normal file
|
@ -0,0 +1,49 @@
|
|||
---
|
||||
title: RGB Underglow Configuration
|
||||
sidebar_label: RGB Underglow
|
||||
---
|
||||
|
||||
See the [RGB Underglow feature page](../features/underglow.md) for more details, including instructions for adding underglow support to a board.
|
||||
|
||||
See [Configuration Overview](index.md) for instructions on how to change these settings.
|
||||
|
||||
## Kconfig
|
||||
|
||||
RGB underglow depends on [Zephyr's LED strip driver](https://github.com/zephyrproject-rtos/zephyr/tree/main/drivers/led_strip), which provides additional Kconfig options.
|
||||
|
||||
Definition file: [zmk/app/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/Kconfig)
|
||||
|
||||
| Config | Type | Description | Default |
|
||||
| ---------------------------------------- | ---- | --------------------------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW` | bool | Enable RGB underglow | n |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_EXT_POWER` | bool | Underglow toggling also controls external power | y |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE` | bool | Turn off RGB underglow when keyboard goes into idle state | n |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_USB` | bool | Turn off RGB underglow when USB is disconnected | n |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_HUE_STEP` | int | Hue step in degrees (0-359) used by RGB actions | 10 |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_SAT_STEP` | int | Saturation step in percent used by RGB actions | 10 |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_BRT_STEP` | int | Brightness step in percent used by RGB actions | 10 |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_HUE_START` | int | Default hue in degrees (0-359) | 0 |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_SAT_START` | int | Default saturation percent (0-100) | 100 |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_BRT_START` | int | Default brightness in percent (0-100) | 100 |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_SPD_START` | int | Default effect speed (1-5) | 3 |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_EFF_START` | int | Default effect index from the effect list (see below) | 0 |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_ON_START` | bool | Default on state | y |
|
||||
|
||||
Values for `CONFIG_ZMK_RGB_UNDERGLOW_EFF_START`:
|
||||
|
||||
| Value | Effect |
|
||||
| ----- | ----------- |
|
||||
| 0 | Solid color |
|
||||
| 1 | Breathe |
|
||||
| 2 | Spectrum |
|
||||
| 3 | Swirl |
|
||||
|
||||
:::note
|
||||
The `*_START` settings only determine the initial underglow state. Any changes you make with the [underglow behavior](../behaviors/underglow.md) are saved to flash after a one minute delay and will be used after that.
|
||||
:::
|
||||
|
||||
## Devicetree
|
||||
|
||||
ZMK does not have any Devicetree properties of its own. See the Devicetree bindings for [Zephyr's LED strip drivers](https://github.com/zephyrproject-rtos/zephyr/tree/main/dts/bindings/led_strip).
|
||||
|
||||
See the [RGB underglow feature page](../features/underglow.md) for examples of the properties that must be set to enable underglow.
|
|
@ -9,10 +9,10 @@ with the main `zmk` firmware repository to build your desired firmware. The main
|
|||
working components of ZMK are kept separate from your personal keyboard settings, reducing the amount of file manipulation in the configuration process.
|
||||
This makes flashing ZMK to your keyboard much easier, especially because you don't need to keep an up-to-date copy of zmk on your computer at all times.
|
||||
|
||||
On default `zmk-config` folder should contain two files:
|
||||
By default, the `zmk-config` folder should contain two files:
|
||||
|
||||
- `<shield>.conf`
|
||||
- `<shield>`.keymap
|
||||
- `<shield>.keymap`
|
||||
|
||||
However, your config folder can also be modified to include a `boards/` directory for keymaps and configurations for multiple boards/shields
|
||||
outside of the default keyboard setting definitions.
|
||||
|
@ -23,6 +23,8 @@ The setup script creates a `config/<shield>.conf` file that allows you to add ad
|
|||
control what features and options are built into your firmware. Opening that file with your text editor will allow you to see the
|
||||
various config settings that can be commented/uncommented to modify how your firmware is built.
|
||||
|
||||
Refer to the [Configuration](/docs/config) documentation for more details on this file.
|
||||
|
||||
## Keymap
|
||||
|
||||
Once you have the basic user config completed, you can find the keymap file in `config/<shield>.keymap` and customize from there.
|
||||
|
|
|
@ -347,8 +347,8 @@ endif()
|
|||
For behaviors that do not require central locality, the following options for updating `app/CmakeLists.txt` also exist:
|
||||
|
||||
- Behavior applies to unibody, or central or peripheral half of keyboard: place `target_sources(app PRIVATE <behavior_name>.c)` line _before_ `if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL)`
|
||||
- Behavior applies to _only_ central half of split keyboard: place `target_sources(app PRIVATE <behavior_name>.c)` after `if (CONFIG_ZMK_SPLIT_BLE AND CONFIG_ZMK_SPLIT_ROLE_CENTRAL)`
|
||||
- Behavior applies to _only_ peripheral half of split keyboard: place `target_sources(app PRIVATE <behavior_name>.c)` after `if (CONFIG_ZMK_SPLIT_BLE AND (NOT CONFIG_ZMK_SPLIT_ROLE_CENTRAL))`
|
||||
- Behavior applies to _only_ central half of split keyboard: place `target_sources(app PRIVATE <behavior_name>.c)` after `if (CONFIG_ZMK_SPLIT AND CONFIG_ZMK_SPLIT_ROLE_CENTRAL)`
|
||||
- Behavior applies to _only_ peripheral half of split keyboard: place `target_sources(app PRIVATE <behavior_name>.c)` after `if (CONFIG_ZMK_SPLIT AND (NOT CONFIG_ZMK_SPLIT_ROLE_CENTRAL))`
|
||||
- Behavior requires certain condition in a keyboard's `.conf` file to be met: use `target_sources_ifdef(CONFIG_<Configuration Requirement> app PRIVATE <behavior_name>.c)` instead of `target_sources(<behavior_name>.c)`
|
||||
|
||||
### Defining common use-cases for the behavior (`.dtsi`) (Optional)
|
||||
|
|
|
@ -157,6 +157,8 @@ this might look something like:
|
|||
};
|
||||
```
|
||||
|
||||
See the [Keyboard Scan configuration documentation](../config/kscan.md) for details on configuring the KSCAN driver.
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="split">
|
||||
|
@ -260,6 +262,8 @@ This is exemplified with the iris .overlay files.
|
|||
|
||||
```
|
||||
|
||||
See the [Keyboard Scan configuration documentation](../config/kscan.md) for details on configuring the KSCAN driver.
|
||||
|
||||
### .conf files (Split Shields)
|
||||
|
||||
While unibody boards only have one .conf file that applies configuration characteristics to the entire keyboard,
|
||||
|
@ -341,6 +345,8 @@ Some important things to note:
|
|||
- `RC(row, column)` is placed sequentially to define what row and column values that position corresponds to.
|
||||
- If you have a keyboard with options for `2u` keys in certain positions, or break away portions, it is a good idea to set the chosen `zmk,matrix_transform` to the default arrangement, and include _other_ possible matrix transform nodes in the devicetree that users can select in their user config by overriding the chosen node.
|
||||
|
||||
See the [matrix transform section](../config/kscan.md#matrix-transform) in the Keyboard Scan configuration documentation for details and more examples of matrix transforms.
|
||||
|
||||
## Default Keymap
|
||||
|
||||
Each keyboard should provide an OOTB default keymap to be used when building the firmware, which can be overridden and customized by user configs. For "shield keyboards", this should be placed in the `app/boards/shields/<shield_name>/<shield_name>.keymap` file. The keymap is configured as an additional devicetree overlay that includes the following:
|
||||
|
|
|
@ -80,6 +80,14 @@ Please note, many keyboards only have a single PCB which includes the “brains
|
|||
|
||||
Currently, ZMK only supports wireless split, but wired split is possible and we welcome contributions!
|
||||
|
||||
### How is the latency?
|
||||
|
||||
The latency of ZMK is comparable to other firmware offerings. ZMK is equipped with a variety of scanning methods and [debounce algorithms](features/debouncing.md) that can affect the final measured latency. [This video](https://www.youtube.com/watch?v=jWL4nU-vtWs) shows a latency comparison of ZMK and other keyboard firmwares.
|
||||
|
||||
### Any chance for 2.4GHz dongle implementation?
|
||||
|
||||
At this time, there are no current plans to implement 2.4GHz dongle mode. This is because utilizing Nordic's proprietary 2.4GHz low level protocols requires use of the Nordic Connect SDK, which is licensed with a more restrictive license than ZMK's MIT license. However, ZMK does plan to implement dongle mode using BLE (with encryption). This will result in a 3.75ms average latency from the protocol itself.
|
||||
|
||||
### What bootloader does ZMK use?
|
||||
|
||||
ZMK isn’t designed for any particular bootloader, and supports flashing different boards with different flash utilities (e.g. OpenOCD, nrfjprog, etc.). So if you have any difficulties, please let us know on [Discord](https://zmk.dev/community/discord/invite)!
|
||||
|
|
|
@ -20,6 +20,8 @@ To enable a battery sensor on a new board, add the driver for the sensor to your
|
|||
- `zmk,battery-voltage-divider`: Reads the voltage on an analog input pin.
|
||||
- `zmk,battery-nrf-vddh`: Reads the power supply voltage on a Nordic nRF52's VDDH pin.
|
||||
|
||||
See the [battery level configuration page](../config/battery.md) for the configuration supported by each driver provided by ZMK.
|
||||
|
||||
Zephyr also provides some drivers for fuel gauge ICs such as the TI bq274xx series and Maxim MAX17xxx series. If you use a battery sensor that does not have an existing driver, you will need to write a new driver that supports the `SENSOR_CHAN_GAUGE_STATE_OF_CHARGE` sensor channel and contribute it to Zephyr or ZMK.
|
||||
|
||||
Once you have the sensor driver defined, add a `zmk,battery` property to the `chosen` node and set it to reference the sensor node. For example:
|
||||
|
|
|
@ -25,7 +25,7 @@ Combos configured in your `.keymap` file, but are separate from the `keymap` nod
|
|||
|
||||
- The name of the combo doesn't really matter, but convention is to start the node name with `combo_`.
|
||||
- The `compatible` property should always be `"zmk,combos"` for combos.
|
||||
- `timeout-ms` is the length of the window (in milliseconds) in which all keys of the combo must be pressed in order to successfully trigger the combo.
|
||||
- All the keys in `key-positions` must be pressed within `timeout-ms` milliseconds to trigger the combo.
|
||||
- `key-positions` is an array of key positions. See the info section below about how to figure out the positions on your board.
|
||||
- `layers = <0 1...>` will allow limiting a combo to specific layers. This is an _optional_ parameter, when omitted it defaults to global scope.
|
||||
- `bindings` is the behavior that is activated when the behavior is pressed.
|
||||
|
@ -47,10 +47,4 @@ Key positions are numbered like the keys in your keymap, starting at 0. So, if t
|
|||
Invoking a source-specific behavior such as one of the [reset behaviors](behaviors/reset.md) using a combo will always trigger it on the central side of the keyboard, regardless of the side that the keys corresponding to `key-positions` are on.
|
||||
:::
|
||||
|
||||
### Advanced configuration
|
||||
|
||||
There are three global combo parameters which are set through KConfig. You can set them in the `<boardname>.conf` file in the same directory as your keymap file.
|
||||
|
||||
- `CONFIG_ZMK_COMBO_MAX_PRESSED_COMBOS` is the number of combos that can be active at the same time. Default 4.
|
||||
- `CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY` is the maximum number of combos that can be active on a key position. Defaults to 5. (So you can have 5 separate combos that use position `3` for example)
|
||||
- `CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO` is the maximum number of keys that need to be pressed to activate a combo. Default 4. If you want a combo that triggers when pressing 5 keys, you'd set this to 5 for example.
|
||||
See [combo configuration](/docs/config/combos) for advanced configuration options.
|
||||
|
|
|
@ -19,14 +19,20 @@ socket or using some sharp tweezers to bend the contacts back together.
|
|||
|
||||
## Debounce Configuration
|
||||
|
||||
:::note
|
||||
Currently only the `zmk,kscan-gpio-matrix` driver supports these options. The other drivers have not yet been updated to use the new debouncing code.
|
||||
:::
|
||||
|
||||
### Global Options
|
||||
|
||||
You can set these options in your `.conf` file to control debouncing globally.
|
||||
Values must be <= 127.
|
||||
Values must be <= 16383.
|
||||
|
||||
- `CONFIG_ZMK_KSCAN_DEBOUNCE_PRESS_MS`: Debounce time for key press in milliseconds. Default = 5.
|
||||
- `CONFIG_ZMK_KSCAN_DEBOUNCE_RELEASE_MS`: Debounce time for key release in milliseconds. Default = 5.
|
||||
|
||||
If one of these options is set, it overrides the matching per-driver option described below.
|
||||
|
||||
For example, this would shorten the debounce time for both press and release:
|
||||
|
||||
```ini
|
||||
|
@ -37,7 +43,7 @@ CONFIG_ZMK_KSCAN_DEBOUNCE_RELEASE_MS=3
|
|||
### Per-driver Options
|
||||
|
||||
You can add these Devicetree properties to a kscan node to control debouncing for
|
||||
that instance of the driver. Values must be <= 127.
|
||||
that instance of the driver. Values must be <= 16383.
|
||||
|
||||
- `debounce-press-ms`: Debounce time for key press in milliseconds. Default = 5.
|
||||
- `debounce-release-ms`: Debounce time for key release in milliseconds. Default = 5.
|
||||
|
|
|
@ -58,7 +58,7 @@ in the stack _also_ get the event.
|
|||
|
||||
Binding a behavior at a certain key position may include up to two extra parameters that are used to
|
||||
alter the behavior when that specific key position is activated/deactivated. For example, when binding
|
||||
the "key press" (`kp`) behavior at a certain key position, you must specific _which_ keycode should
|
||||
the "key press" (`kp`) behavior at a certain key position, you must specify _which_ keycode should
|
||||
be used for that key position.
|
||||
|
||||
```
|
||||
|
|
|
@ -25,7 +25,8 @@ Here you can see the RGB underglow feature in action using WS2812 LEDs.
|
|||
|
||||
## Enabling RGB Underglow
|
||||
|
||||
To enable RGB underglow on your board or shield, simply enable the `CONFIG_ZMK_RGB_UNDERGLOW` and `X_STRIP` configuration values in the `.conf` file of your user config directory as such:
|
||||
To enable RGB underglow on your board or shield, simply enable the `CONFIG_ZMK_RGB_UNDERGLOW` and `CONFIG_*_STRIP` configuration values in the `.conf` file for your board or shield.
|
||||
For example:
|
||||
|
||||
```
|
||||
CONFIG_ZMK_RGB_UNDERGLOW=y
|
||||
|
@ -33,24 +34,14 @@ CONFIG_ZMK_RGB_UNDERGLOW=y
|
|||
CONFIG_WS2812_STRIP=y
|
||||
```
|
||||
|
||||
See [Configuration Overview](/docs/config) for more instructions on how to
|
||||
use Kconfig.
|
||||
|
||||
If your board or shield does not have RGB underglow configured, refer to [Adding RGB Underglow to a Board](#adding-rgb-underglow-to-a-board).
|
||||
|
||||
## Configuring RGB Underglow
|
||||
|
||||
There are various Kconfig options used to configure the RGB underglow feature. These can all be set in the `.conf` file.
|
||||
|
||||
| Option | Description | Default |
|
||||
| ------------------------------------ | ----------------------------------------------- | ------- |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_EXT_POWER` | Underglow toggling also controls external power | y |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_HUE_STEP` | Hue step in degrees of 360 used by RGB actions | 10 |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_SAT_STEP` | Saturation step in percent used by RGB actions | 10 |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_BRT_STEP` | Brightness step in percent used by RGB actions | 10 |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_HUE_START` | Default hue 0-359 in degrees | 0 |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_SAT_START` | Default saturation 0-100 in percent | 100 |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_BRT_START` | Default brightness 0-100 in percent | 100 |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_SPD_START` | Default effect speed 1-5 | 3 |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_EFF_START` | Default effect integer from the effect enum | 0 |
|
||||
| `CONFIG_ZMK_RGB_UNDERGLOW_ON_START` | Default on state | y |
|
||||
See [RGB underglow configuration](/docs/config/underglow).
|
||||
|
||||
## Adding RGB Underglow to a Board
|
||||
|
||||
|
@ -154,7 +145,7 @@ Once you have your `led_strip` properly defined you need to add it to the root d
|
|||
};
|
||||
```
|
||||
|
||||
Finally you need to enable the `CONFIG_ZMK_RGB_UNDERGLOW` and `X_STRIP` configuration values in the `.conf` file of your board (or set a default in the `Kconfig.defconfig`):
|
||||
Finally you need to enable the `CONFIG_ZMK_RGB_UNDERGLOW` and `CONFIG_*_STRIP` configuration values in the `.conf` file of your board (or set a default in the `Kconfig.defconfig`):
|
||||
|
||||
```
|
||||
CONFIG_ZMK_RGB_UNDERGLOW=y
|
||||
|
|
|
@ -199,7 +199,7 @@ storage device. Once the flash is complete, the controller should automatically
|
|||
|
||||
ZMK will automatically advertise itself as connectable if it is not currently connected to a device. You should be able to see your keyboard from the bluetooth scanning view of your laptop or phone / tablet. It is reported by some users that the connections with Android / iOS devices are generally smoother than with laptops, so if you have trouble connecting, you could try to connect from your phone or tablet first to eliminate any potential hardware issues.
|
||||
|
||||
ZMK support multiple BLE “profiles”, which allows you to connect to and switch among multiple devices. Please refer to the [Bluetooth behavior](behaviors/bluetooth.md) section for detailed explanations of how to use them.
|
||||
ZMK supports multiple BLE “profiles”, which allows you to connect to and switch among multiple devices. Please refer to the [Bluetooth behavior](behaviors/bluetooth.md) section for detailed explanations on how to use them.
|
||||
|
||||
### Connecting Split Keyboard Halves
|
||||
|
||||
|
|
97
docs/package-lock.json
generated
|
@ -4254,9 +4254,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "7.4.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
|
||||
"integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
|
||||
"version": "8.7.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
|
||||
"integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
|
@ -7107,6 +7107,18 @@
|
|||
"node": "^10.12.0 || >=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/espree/node_modules/acorn": {
|
||||
"version": "7.4.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
|
||||
"integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
|
||||
"devOptional": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/espree/node_modules/eslint-visitor-keys": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
|
||||
|
@ -7801,19 +7813,6 @@
|
|||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
|
@ -8406,17 +8405,6 @@
|
|||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/html-minifier-terser/node_modules/acorn": {
|
||||
"version": "8.7.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
|
||||
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/html-minifier-terser/node_modules/commander": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||
|
@ -14455,17 +14443,6 @@
|
|||
"node": ">= 10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-bundle-analyzer/node_modules/acorn": {
|
||||
"version": "8.7.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
|
||||
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-bundle-analyzer/node_modules/commander": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
||||
|
@ -14696,17 +14673,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz",
|
||||
"integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ=="
|
||||
},
|
||||
"node_modules/webpack/node_modules/acorn": {
|
||||
"version": "8.7.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
|
||||
"integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webpack/node_modules/enhanced-resolve": {
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz",
|
||||
|
@ -18232,9 +18198,9 @@
|
|||
}
|
||||
},
|
||||
"acorn": {
|
||||
"version": "7.4.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
|
||||
"integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A=="
|
||||
"version": "8.7.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
|
||||
"integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A=="
|
||||
},
|
||||
"acorn-import-assertions": {
|
||||
"version": "1.8.0",
|
||||
|
@ -20335,6 +20301,12 @@
|
|||
"eslint-visitor-keys": "^1.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "7.4.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
|
||||
"integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
|
||||
"devOptional": true
|
||||
},
|
||||
"eslint-visitor-keys": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
|
||||
|
@ -20854,12 +20826,6 @@
|
|||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"optional": true
|
||||
},
|
||||
"function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
|
@ -21312,11 +21278,6 @@
|
|||
"terser": "^5.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "8.7.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
|
||||
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ=="
|
||||
},
|
||||
"commander": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||
|
@ -25647,11 +25608,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz",
|
||||
"integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ=="
|
||||
},
|
||||
"acorn": {
|
||||
"version": "8.7.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
|
||||
"integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A=="
|
||||
},
|
||||
"enhanced-resolve": {
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz",
|
||||
|
@ -25679,11 +25635,6 @@
|
|||
"ws": "^7.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "8.7.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
|
||||
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ=="
|
||||
},
|
||||
"commander": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
||||
|
|