Merge branch 'main' into corne-ish-zen-v2
|
@ -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
|
||||
|
||||
|
|
6
app/boards/arm/puchi_ble/CMakeLists.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
if(CONFIG_PINMUX)
|
||||
zephyr_library()
|
||||
zephyr_library_sources(pinmux.c)
|
||||
zephyr_library_include_directories(${ZEPHYR_BASE}/drivers)
|
||||
endif()
|
3
app/boards/arm/puchi_ble/Kconfig
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
8
app/boards/arm/puchi_ble/Kconfig.board
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Puchi-BLE board configuration
|
||||
|
||||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config BOARD_PUCHI_BLE_v1
|
||||
bool "puchi_ble_v1"
|
||||
depends on SOC_NRF52840_QIAA
|
28
app/boards/arm/puchi_ble/Kconfig.defconfig
Normal file
|
@ -0,0 +1,28 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if BOARD_PUCHI_BLE_v1
|
||||
|
||||
config BOARD
|
||||
default "puchi_ble"
|
||||
|
||||
if USB_DEVICE_STACK
|
||||
|
||||
config USB_NRFX
|
||||
default y
|
||||
|
||||
endif # USB_DEVICE_STACK
|
||||
|
||||
config BT_CTLR
|
||||
default BT
|
||||
|
||||
config ZMK_BLE
|
||||
default y
|
||||
|
||||
config ZMK_USB
|
||||
default y
|
||||
|
||||
config PINMUX
|
||||
default y
|
||||
|
||||
endif # BOARD_PUCHI_BLE_v1
|
59
app/boards/arm/puchi_ble/arduino_pro_micro_pins.dtsi
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
|
||||
/ {
|
||||
pro_micro: connector {
|
||||
compatible = "arduino-pro-micro";
|
||||
#gpio-cells = <2>;
|
||||
gpio-map-mask = <0xffffffff 0xffffffc0>;
|
||||
gpio-map-pass-thru = <0 0x3f>;
|
||||
gpio-map
|
||||
= <0 0 &gpio0 8 0> /* D0 */
|
||||
, <1 0 &gpio0 6 0> /* D1 */
|
||||
, <2 0 &gpio0 15 0> /* D2 */
|
||||
, <3 0 &gpio0 17 0> /* D3 */
|
||||
, <4 0 &gpio0 20 0> /* D4/A6 */
|
||||
, <5 0 &gpio0 13 0> /* D5 */
|
||||
, <6 0 &gpio0 24 0> /* D6/A7 */
|
||||
, <7 0 &gpio0 9 0> /* D7 */
|
||||
, <8 0 &gpio0 10 0> /* D8/A8 */
|
||||
, <9 0 &gpio1 6 0> /* D9/A9 */
|
||||
, <10 0 &gpio1 11 0> /* D10/A10 */
|
||||
, <16 0 &gpio0 28 0> /* D16 */
|
||||
, <14 0 &gpio0 3 0> /* D14 */
|
||||
, <15 0 &gpio1 13 0> /* D15 */
|
||||
, <18 0 &gpio0 2 0> /* D18/A0 */
|
||||
, <19 0 &gpio0 29 0> /* D19/A1 */
|
||||
, <20 0 &gpio0 31 0> /* D20/A2 */
|
||||
, <21 0 &gpio0 30 0> /* D21/A3 */
|
||||
;
|
||||
};
|
||||
|
||||
pro_micro_a: connector_a {
|
||||
compatible = "arduino-pro-micro";
|
||||
#gpio-cells = <2>;
|
||||
gpio-map-mask = <0xffffffff 0xffffffc0>;
|
||||
gpio-map-pass-thru = <0 0x3f>;
|
||||
gpio-map
|
||||
= <0 0 &gpio0 2 0> /* D18/A0 */
|
||||
, <1 0 &gpio0 29 0> /* D19/A1 */
|
||||
, <2 0 &gpio0 31 0> /* D20/A2 */
|
||||
, <3 0 &gpio0 30 0> /* D21/A3 */
|
||||
, <6 0 &gpio0 20 0> /* D4/A6 */
|
||||
, <7 0 &gpio0 24 0> /* D6/A7 */
|
||||
, <8 0 &gpio0 10 0> /* D8/A8 */
|
||||
, <9 0 &gpio1 6 0> /* D9/A9 */
|
||||
, <10 0 &gpio1 11 0> /* D10/A10 */
|
||||
;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
pro_micro_d: &pro_micro {};
|
||||
pro_micro_i2c: &i2c0 {};
|
||||
pro_micro_spi: &spi0 {};
|
||||
pro_micro_serial: &uart0 {};
|
6
app/boards/arm/puchi_ble/board.cmake
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset")
|
||||
include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
29
app/boards/arm/puchi_ble/pinmux.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <device.h>
|
||||
#include <init.h>
|
||||
#include <drivers/gpio.h>
|
||||
#include <sys/sys_io.h>
|
||||
#include <devicetree.h>
|
||||
|
||||
static int pinmux_puchi_ble_init(const struct device *port) {
|
||||
ARG_UNUSED(port);
|
||||
|
||||
#if CONFIG_BOARD_PUCHI_BLE_v1
|
||||
const struct device *p0 = device_get_binding("GPIO_0");
|
||||
#if CONFIG_BOARD_PUCHI_BLE_CHARGER
|
||||
gpio_pin_configure(p0, 5, GPIO_OUTPUT);
|
||||
gpio_pin_set(p0, 5, 0);
|
||||
#else
|
||||
gpio_pin_configure(p0, 5, GPIO_INPUT);
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(pinmux_puchi_ble_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
121
app/boards/arm/puchi_ble/puchi_ble_v1.dts
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
#include <nordic/nrf52840_qiaa.dtsi>
|
||||
#include "arduino_pro_micro_pins.dtsi"
|
||||
|
||||
/ {
|
||||
model = "puchi_ble";
|
||||
compatible = "puchi_ble";
|
||||
|
||||
chosen {
|
||||
zephyr,code-partition = &code_partition;
|
||||
zephyr,sram = &sram0;
|
||||
zephyr,flash = &flash0;
|
||||
zephyr,console = &cdc_acm_uart;
|
||||
zmk,battery = &vbatt;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
blue_led: led_0 {
|
||||
gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
|
||||
label = "Blue LED";
|
||||
};
|
||||
};
|
||||
|
||||
ext-power {
|
||||
compatible = "zmk,ext-power-generic";
|
||||
label = "EXT_POWER";
|
||||
control-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
vbatt: vbatt {
|
||||
compatible = "zmk,battery-voltage-divider";
|
||||
label = "BATTERY";
|
||||
io-channels = <&adc 2>;
|
||||
output-ohms = <2000000>;
|
||||
full-ohms = <(2000000 + 820000)>;
|
||||
};
|
||||
};
|
||||
|
||||
&adc {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpiote {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
compatible = "nordic,nrf-twi";
|
||||
sda-pin = <15>;
|
||||
scl-pin = <17>;
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uarte";
|
||||
tx-pin = <6>;
|
||||
rx-pin = <8>;
|
||||
};
|
||||
|
||||
&usbd {
|
||||
status = "okay";
|
||||
cdc_acm_uart: cdc_acm_uart {
|
||||
compatible = "zephyr,cdc-acm-uart";
|
||||
label = "CDC_ACM_0";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
&flash0 {
|
||||
/*
|
||||
* For more information, see:
|
||||
* http://docs.zephyrproject.org/latest/devices/dts/flash_partitions.html
|
||||
*/
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
sd_partition: partition@0 {
|
||||
label = "softdevice";
|
||||
reg = <0x00000000 0x00026000>;
|
||||
};
|
||||
code_partition: partition@26000 {
|
||||
label = "code_partition";
|
||||
reg = <0x00026000 0x000c6000>;
|
||||
};
|
||||
|
||||
/*
|
||||
* The flash starting at 0x000ec000 and ending at
|
||||
* 0x000f3fff is reserved for use by the application.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Storage partition will be used by FCB/LittleFS/NVS
|
||||
* if enabled.
|
||||
*/
|
||||
storage_partition: partition@ec000 {
|
||||
label = "storage";
|
||||
reg = <0x000ec000 0x00008000>;
|
||||
};
|
||||
|
||||
boot_partition: partition@f4000 {
|
||||
label = "adafruit_boot";
|
||||
reg = <0x000f4000 0x0000c000>;
|
||||
};
|
||||
};
|
||||
};
|
15
app/boards/arm/puchi_ble/puchi_ble_v1.yaml
Normal file
|
@ -0,0 +1,15 @@
|
|||
identifier: puchi_ble_v1
|
||||
name: puchi_ble_v1
|
||||
type: mcu
|
||||
arch: arm
|
||||
toolchain:
|
||||
- zephyr
|
||||
- gnuarmemb
|
||||
- xtools
|
||||
supported:
|
||||
- adc
|
||||
- usb_device
|
||||
- ble
|
||||
- ieee802154
|
||||
- pwm
|
||||
- watchdog
|
10
app/boards/arm/puchi_ble/puchi_ble_v1.zmk.yml
Normal file
|
@ -0,0 +1,10 @@
|
|||
file_format: "1"
|
||||
id: puchi_ble_v1
|
||||
name: Puchi-BLE V1
|
||||
type: board
|
||||
arch: arm
|
||||
outputs:
|
||||
- usb
|
||||
- ble
|
||||
url: https://keycapsss.com/keyboard-parts/mcu-controller/202/puchi-ble-wireless-microcontroller
|
||||
exposes: [pro_micro]
|
24
app/boards/arm/puchi_ble/puchi_ble_v1_defconfig
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
CONFIG_SOC_SERIES_NRF52X=y
|
||||
CONFIG_SOC_NRF52840_QIAA=y
|
||||
CONFIG_BOARD_PUCHI_BLE_v1=y
|
||||
|
||||
# Enable MPU
|
||||
CONFIG_ARM_MPU=y
|
||||
|
||||
# enable GPIO
|
||||
CONFIG_GPIO=y
|
||||
|
||||
CONFIG_USE_DT_CODE_PARTITION=y
|
||||
CONFIG_BUILD_OUTPUT_UF2=y
|
||||
|
||||
CONFIG_MPU_ALLOW_FLASH_WRITE=y
|
||||
CONFIG_NVS=y
|
||||
CONFIG_SETTINGS_NVS=y
|
||||
CONFIG_FLASH=y
|
||||
CONFIG_FLASH_PAGE_LAYOUT=y
|
||||
CONFIG_FLASH_MAP=y
|
||||
CONFIG_CLOCK_CONTROL_NRF=y
|
||||
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
|
|
@ -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
|
||||
|
||||
|
|
9
app/boards/shields/eternal_keypad/Kconfig.defconfig
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if SHIELD_ETERNAL_KEYPAD || SHIELD_ETERNAL_KEYPAD_LEFTY
|
||||
|
||||
config ZMK_KEYBOARD_NAME
|
||||
default "Eternal Keypad"
|
||||
|
||||
endif
|
8
app/boards/shields/eternal_keypad/Kconfig.shield
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config SHIELD_ETERNAL_KEYPAD
|
||||
def_bool $(shields_list_contains,eternal_keypad)
|
||||
|
||||
config SHIELD_ETERNAL_KEYPAD_LEFTY
|
||||
def_bool $(shields_list_contains,eternal_keypad_lefty)
|
10
app/boards/shields/eternal_keypad/README.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Eternal Keypad
|
||||
|
||||
Eternal Keypad is an open-source input device for gaming that can be assembled for both right and left hand mouse users.
|
||||
|
||||
Firmware is described in the [Eternal Keypad](https://github.com/duckyb/eternal-keypad) repository [README](https://github.com/duckyb/eternal-keypad#firmware).
|
||||
|
||||
Two keymaps are included:
|
||||
|
||||
- eternal_keypad (default)
|
||||
- eternal_keypad_lefty (for left handed users)
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <dt-bindings/led/led.h>
|
||||
|
||||
&spi1 {
|
||||
compatible = "nordic,nrf-spim";
|
||||
/* Cannot be used together with i2c0. */
|
||||
status = "okay";
|
||||
mosi-pin = <6>;
|
||||
// Unused pins, needed for SPI definition, but not used by the ws2812 driver itself.
|
||||
sck-pin = <5>;
|
||||
miso-pin = <7>;
|
||||
|
||||
led_strip: ws2812@0 {
|
||||
compatible = "worldsemi,ws2812-spi";
|
||||
label = "SK6812mini";
|
||||
|
||||
/* SPI */
|
||||
reg = <0>; /* ignored, but necessary for SPI bindings */
|
||||
spi-max-frequency = <4000000>;
|
||||
|
||||
/* WS2812 */
|
||||
chain-length = <8>;
|
||||
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;
|
||||
};
|
||||
};
|
9
app/boards/shields/eternal_keypad/eternal_keypad.conf
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
# Uncomment to turn on logging, and set ZMK logging to debug output
|
||||
# CONFIG_ZMK_USB_LOGGING=y
|
||||
|
||||
# Uncomment the following lines to enable RGB underglow
|
||||
# CONFIG_ZMK_RGB_UNDERGLOW=y
|
||||
# CONFIG_WS2812_STRIP=y
|
53
app/boards/shields/eternal_keypad/eternal_keypad.dtsi
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <dt-bindings/zmk/matrix_transform.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,kscan = &kscan0;
|
||||
zmk,matrix_transform = &default_transform;
|
||||
};
|
||||
|
||||
kscan0: kscan {
|
||||
compatible = "zmk,kscan-gpio-matrix";
|
||||
label = "KSCAN";
|
||||
|
||||
diode-direction = "col2row";
|
||||
|
||||
row-gpios
|
||||
= <&pro_micro 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
;
|
||||
|
||||
col-gpios
|
||||
= <&pro_micro 10 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 16 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 14 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 15 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 18 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 19 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 20 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
;
|
||||
};
|
||||
|
||||
default_transform: keymap_transform_0 {
|
||||
compatible = "zmk,matrix-transform";
|
||||
columns = <8>;
|
||||
rows = <5>;
|
||||
map = <
|
||||
RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7)
|
||||
RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7)
|
||||
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7)
|
||||
RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7)
|
||||
RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,5) RC(4,7)
|
||||
>;
|
||||
};
|
||||
};
|
56
app/boards/shields/eternal_keypad/eternal_keypad.keymap
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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>
|
||||
#include <dt-bindings/zmk/rgb.h>
|
||||
|
||||
#define BASE 0
|
||||
#define ARROW 1
|
||||
#define FUNC 2
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,kscan = &kscan0;
|
||||
zmk,matrix_transform = &default_transform;
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&kp ESC &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6
|
||||
&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp N7
|
||||
&kp F13 &kp ENTER &kp A &kp S &kp D &kp F &kp G &kp N8
|
||||
&kp F14 &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N9
|
||||
&kp F15 &kp LCTRL &sl FUNC &kp LALT &kp SPACE < ARROW N0
|
||||
>;
|
||||
};
|
||||
|
||||
arrow_layer {
|
||||
bindings = <
|
||||
&bt BT_SEL 0 &bt BT_SEL 1 &trans &trans &trans &out OUT_USB &out OUT_BLE
|
||||
&trans &trans &kp UP &trans &rgb_ug RGB_TOG &rgb_ug RGB_HUI &rgb_ug RGB_HUD
|
||||
&bt BT_CLR &trans &kp LEFT &kp DOWN &kp RIGHT &trans &rgb_ug RGB_BRI &rgb_ug RGB_BRD
|
||||
&reset &trans &trans &trans &trans &trans &rgb_ug RGB_EFF &rgb_ug RGB_EFR
|
||||
&bootloader &trans &trans &trans &trans &trans
|
||||
>;
|
||||
};
|
||||
|
||||
function_layer {
|
||||
bindings = <
|
||||
&trans &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6
|
||||
&trans &kp P &kp O &kp I &kp U &kp Y &kp F7
|
||||
&bt BT_CLR &kp BSPC &kp SEMI &kp L &kp K &kp J &kp H &kp F8
|
||||
&reset &trans &kp LGUI &kp M &kp N &kp F12 &kp F11 &kp F9
|
||||
&bootloader &trans &trans &trans &trans &kp F10
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
7
app/boards/shields/eternal_keypad/eternal_keypad.overlay
Normal file
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "eternal_keypad.dtsi"
|
9
app/boards/shields/eternal_keypad/eternal_keypad.zmk.yml
Normal file
|
@ -0,0 +1,9 @@
|
|||
file_format: "1"
|
||||
id: eternal_keypad
|
||||
name: Eternal Keypad
|
||||
type: shield
|
||||
url: https://github.com/duckyb/eternal-keypad
|
||||
requires: [pro_micro]
|
||||
features:
|
||||
- keys
|
||||
- underglow
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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>
|
||||
#include <dt-bindings/zmk/rgb.h>
|
||||
|
||||
#define BASE 0
|
||||
#define ARROW 1
|
||||
#define FUNC 2
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,kscan = &kscan0;
|
||||
zmk,matrix_transform = &default_transform;
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&kp ESC &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6
|
||||
&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp N7
|
||||
&kp F13 &kp ENTER &kp D &kp S &kp A &kp F &kp G &kp N8
|
||||
&kp F14 &kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N9
|
||||
&kp F15 &kp LCTRL &sl FUNC &kp LALT &kp SPACE < ARROW N0
|
||||
>;
|
||||
};
|
||||
|
||||
arrow_layer {
|
||||
bindings = <
|
||||
&bt BT_SEL 0 &bt BT_SEL 1 &trans &trans &trans &out OUT_USB &out OUT_BLE
|
||||
&trans &trans &kp UP &trans &rgb_ug RGB_TOG &rgb_ug RGB_HUI &rgb_ug RGB_HUD
|
||||
&bt BT_CLR &trans &kp RIGHT &kp DOWN &kp RIGHT &trans &rgb_ug RGB_BRI &rgb_ug RGB_BRD
|
||||
&reset &trans &trans &trans &trans &trans &rgb_ug RGB_EFF &rgb_ug RGB_EFR
|
||||
&bootloader &trans &trans &trans &trans &trans
|
||||
>;
|
||||
};
|
||||
|
||||
function_layer {
|
||||
bindings = <
|
||||
&trans &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6
|
||||
&trans &kp P &kp O &kp I &kp U &kp Y &kp F7
|
||||
&bt BT_CLR &kp BSPC &kp SEMI &kp L &kp K &kp J &kp H &kp F8
|
||||
&reset &trans &kp LGUI &kp M &kp N &kp F12 &kp F11 &kp F9
|
||||
&bootloader &trans &trans &trans &trans &kp F10
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 202 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "eternal_keypad.dtsi"
|
|
@ -0,0 +1,9 @@
|
|||
file_format: "1"
|
||||
id: eternal_keypad_lefty
|
||||
name: Eternal Keypad Lefty
|
||||
type: shield
|
||||
url: https://github.com/duckyb/eternal-keypad
|
||||
requires: [pro_micro]
|
||||
features:
|
||||
- keys
|
||||
- underglow
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -1404,6 +1404,10 @@
|
|||
#define C_AC_DESKTOP_SHOW_ALL_WINDOWS \
|
||||
(ZMK_HID_USAGE(HID_USAGE_CONSUMER, HID_USAGE_CONSUMER_AC_DESKTOP_SHOW_ALL_WINDOWS))
|
||||
|
||||
/* Consumer AC Desktop Show All Applications */
|
||||
#define C_AC_DESKTOP_SHOW_ALL_APPLICATIONS \
|
||||
(ZMK_HID_USAGE(HID_USAGE_CONSUMER, HID_USAGE_CONSUMER_AC_DESKTOP_SHOW_ALL_APPLICATIONS))
|
||||
|
||||
/* Consumer Keyboard Input Assist Previous */
|
||||
#define C_KEYBOARD_INPUT_ASSIST_PREVIOUS \
|
||||
(ZMK_HID_USAGE(HID_USAGE_CONSUMER, HID_USAGE_CONSUMER_KEYBOARD_INPUT_ASSIST_PREVIOUS))
|
||||
|
|
|
@ -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>
|
||||
|
|