Merge branch 'zmkfirmware:main' into main
This commit is contained in:
commit
65d24bfe6e
129 changed files with 2672 additions and 1658 deletions
|
@ -1,4 +1,4 @@
|
|||
FROM zmkfirmware/zmk-dev-arm:2.5
|
||||
FROM docker.io/zmkfirmware/zmk-dev-arm:2.5
|
||||
|
||||
COPY .bashrc tmp
|
||||
RUN mv /tmp/.bashrc ~/.bashrc
|
||||
|
|
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
|
@ -3,7 +3,7 @@
|
|||
- [ ] This board/shield is tested working on real hardware
|
||||
- [ ] Definitions follow the general style of other shields/boards upstream ([Reference](https://zmk.dev/docs/development/new-shield))
|
||||
- [ ] `.zmk.yml` metadata file added
|
||||
- [ ] Proper Copyright + License headers added to applicable files
|
||||
- [ ] Proper Copyright + License headers added to applicable files (Generally, we stick to "The ZMK Contributors" for copyrights to help avoid churn when files get edited)
|
||||
- [ ] General consistent formatting of DeviceTree files
|
||||
- [ ] Keymaps do not use deprecated key defines (Check using the [upgrader tool](https://zmk.dev/docs/codes/keymap-upgrader))
|
||||
- [ ] `&pro_micro` used in favor of `&pro_micro_d/a` if applicable
|
||||
|
|
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
@ -14,7 +14,7 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: zmkfirmware/zmk-build-arm:2.5
|
||||
image: docker.io/zmkfirmware/zmk-build-arm:2.5
|
||||
strategy:
|
||||
matrix:
|
||||
board:
|
||||
|
|
2
.github/workflows/clang-format-lint.yml
vendored
2
.github/workflows/clang-format-lint.yml
vendored
|
@ -23,7 +23,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: DoozyX/clang-format-lint-action@v0.12
|
||||
- uses: DoozyX/clang-format-lint-action@v0.13
|
||||
with:
|
||||
source: "./app"
|
||||
extensions: "h,c"
|
||||
|
|
|
@ -29,7 +29,7 @@ jobs:
|
|||
validate-metadata:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: zmkfirmware/zmk-dev-arm:2.5
|
||||
image: docker.io/zmkfirmware/zmk-dev-arm:2.5
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install dependencies
|
||||
|
|
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
|
@ -16,7 +16,7 @@ jobs:
|
|||
integration_test:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: zmkfirmware/zmk-build-arm:2.5
|
||||
image: docker.io/zmkfirmware/zmk-build-arm:2.5
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
|
33
app/Kconfig
33
app/Kconfig
|
@ -167,6 +167,7 @@ menuconfig ZMK_SPLIT_BLE_ROLE_CENTRAL
|
|||
bool "Central"
|
||||
select BT_CENTRAL
|
||||
select BT_GATT_CLIENT
|
||||
select BT_GATT_AUTO_DISCOVER_CCC
|
||||
|
||||
if ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
|
||||
|
@ -262,36 +263,54 @@ config ZMK_RGB_UNDERGLOW_EXT_POWER
|
|||
bool "RGB underglow toggling also controls external power"
|
||||
default y
|
||||
|
||||
config ZMK_RGB_UNDERGLOW_BRT_MIN
|
||||
int "RGB underglow minimum brightness in percent"
|
||||
range 0 100
|
||||
default 0
|
||||
|
||||
config ZMK_RGB_UNDERGLOW_BRT_MAX
|
||||
int "RGB underglow maximum brightness in percent"
|
||||
range ZMK_RGB_UNDERGLOW_BRT_MIN 100
|
||||
default 100
|
||||
|
||||
config ZMK_RGB_UNDERGLOW_HUE_STEP
|
||||
int "RGB underglow hue step in degrees of 360"
|
||||
int "RGB underglow hue step in degrees"
|
||||
range 0 359
|
||||
default 10
|
||||
|
||||
config ZMK_RGB_UNDERGLOW_SAT_STEP
|
||||
int "RGB underglow sturation step in percent"
|
||||
int "RGB underglow saturation step in percent"
|
||||
range 0 100
|
||||
default 10
|
||||
|
||||
config ZMK_RGB_UNDERGLOW_BRT_STEP
|
||||
int "RGB underglow brightness step in percent"
|
||||
range 0 100
|
||||
default 10
|
||||
|
||||
config ZMK_RGB_UNDERGLOW_HUE_START
|
||||
int "RGB underglow start hue value from 0-359"
|
||||
int "RGB underglow start hue value in degrees"
|
||||
range 0 359
|
||||
default 0
|
||||
|
||||
config ZMK_RGB_UNDERGLOW_SAT_START
|
||||
int "RGB underglow start saturations value from 0-100"
|
||||
int "RGB underglow start saturations value in percent"
|
||||
range 0 100
|
||||
default 100
|
||||
|
||||
config ZMK_RGB_UNDERGLOW_BRT_START
|
||||
int "RGB underglow start brightness value from 0-100"
|
||||
default 100
|
||||
int "RGB underglow start brightness value in percent"
|
||||
range ZMK_RGB_UNDERGLOW_BRT_MIN ZMK_RGB_UNDERGLOW_BRT_MAX
|
||||
default ZMK_RGB_UNDERGLOW_BRT_MAX
|
||||
|
||||
config ZMK_RGB_UNDERGLOW_SPD_START
|
||||
int "RGB underglow start animation speed value from 1-5"
|
||||
int "RGB underglow start animation speed value"
|
||||
range 1 5
|
||||
default 3
|
||||
|
||||
config ZMK_RGB_UNDERGLOW_EFF_START
|
||||
int "RGB underglow start effect int value related to the effect enum list"
|
||||
range 0 3
|
||||
default 0
|
||||
|
||||
config ZMK_RGB_UNDERGLOW_ON_START
|
||||
|
|
14
app/boards/arm/mikoto/CMakeLists.txt
Normal file
14
app/boards/arm/mikoto/CMakeLists.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/../tools/uf2/utils/uf2conv.py
|
||||
-c
|
||||
-b 0x26000
|
||||
-f 0xADA52840
|
||||
-o ${PROJECT_BINARY_DIR}/${CONFIG_KERNEL_BIN_NAME}.uf2
|
||||
${PROJECT_BINARY_DIR}/${CONFIG_KERNEL_BIN_NAME}.bin
|
||||
)
|
||||
|
||||
if(CONFIG_PINMUX)
|
||||
zephyr_library()
|
||||
zephyr_library_sources(pinmux.c)
|
||||
zephyr_library_include_directories(${ZEPHYR_BASE}/drivers)
|
||||
endif()
|
29
app/boards/arm/mikoto/Kconfig
Normal file
29
app/boards/arm/mikoto/Kconfig
Normal file
|
@ -0,0 +1,29 @@
|
|||
config BOARD_ENABLE_DCDC
|
||||
bool "Enable DCDC mode"
|
||||
select SOC_DCDC_NRF52X
|
||||
default y
|
||||
depends on (BOARD_MIKOTO_520)
|
||||
|
||||
choice BOARD_MIKOTO_CHARGER_CURRENT
|
||||
prompt "Charge current to supply to attached batteries"
|
||||
depends on (BOARD_MIKOTO_520)
|
||||
|
||||
config BOARD_MIKOTO_CHARGER_CURRENT_40MA
|
||||
bool "40mA charge current, for battery capacity 40mAh or higher"
|
||||
|
||||
config BOARD_MIKOTO_CHARGER_CURRENT_100MA
|
||||
bool "100mA charge current, for battery capacity 100mAh or higher"
|
||||
|
||||
config BOARD_MIKOTO_CHARGER_CURRENT_150MA
|
||||
bool "150mA charge current, for battery capacity 150mAh or higher"
|
||||
|
||||
config BOARD_MIKOTO_CHARGER_CURRENT_250MA
|
||||
bool "250mA charge current, for battery capacity 250mAh or higher"
|
||||
|
||||
config BOARD_MIKOTO_CHARGER_CURRENT_350MA
|
||||
bool "350mA charge current, for battery capacity 350mAh or higher"
|
||||
|
||||
config BOARD_MIKOTO_CHARGER_CURRENT_NONE
|
||||
bool "Disable charge current"
|
||||
|
||||
endchoice
|
8
app/boards/arm/mikoto/Kconfig.board
Normal file
8
app/boards/arm/mikoto/Kconfig.board
Normal file
|
@ -0,0 +1,8 @@
|
|||
# mikoto board configuration
|
||||
|
||||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config BOARD_MIKOTO_520
|
||||
bool "mikoto_520"
|
||||
depends on SOC_NRF52840_QIAA
|
40
app/boards/arm/mikoto/Kconfig.defconfig
Normal file
40
app/boards/arm/mikoto/Kconfig.defconfig
Normal file
|
@ -0,0 +1,40 @@
|
|||
# Electronut Labs Papyr board configuration
|
||||
|
||||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if BOARD_MIKOTO_520
|
||||
|
||||
config BOARD
|
||||
default "mikoto"
|
||||
|
||||
if USB
|
||||
|
||||
config USB_NRFX
|
||||
default y
|
||||
|
||||
config USB_DEVICE_STACK
|
||||
default y
|
||||
|
||||
endif # USB
|
||||
|
||||
config BT_CTLR
|
||||
default BT
|
||||
|
||||
config ZMK_BLE
|
||||
default y
|
||||
|
||||
config ZMK_USB
|
||||
default y
|
||||
|
||||
config PINMUX
|
||||
default y
|
||||
|
||||
choice BOARD_MIKOTO_CHARGER_CURRENT
|
||||
default BOARD_MIKOTO_CHARGER_CURRENT_100MA
|
||||
endchoice
|
||||
|
||||
config ZMK_BATTERY_VOLTAGE_DIVIDER
|
||||
default y
|
||||
|
||||
endif # BOARD_MIKOTO_520
|
59
app/boards/arm/mikoto/arduino_pro_micro_pins.dtsi
Normal file
59
app/boards/arm/mikoto/arduino_pro_micro_pins.dtsi
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2020 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 4 0> /* D0 */
|
||||
, <1 0 &gpio0 8 0> /* D1 */
|
||||
, <2 0 &gpio0 17 0> /* D2 */
|
||||
, <3 0 &gpio0 20 0> /* D3 */
|
||||
, <4 0 &gpio0 22 0> /* D4/A6 */
|
||||
, <5 0 &gpio0 24 0> /* D5 */
|
||||
, <6 0 &gpio1 0 0> /* D6/A7 */
|
||||
, <7 0 &gpio1 2 0> /* D7 */
|
||||
, <8 0 &gpio1 4 0> /* D8/A8 */
|
||||
, <9 0 &gpio1 6 0> /* D9/A9 */
|
||||
, <10 0 &gpio0 9 0> /* D10/A10 */
|
||||
, <16 0 &gpio0 10 0> /* D16 */
|
||||
, <14 0 &gpio1 13 0> /* D14 */
|
||||
, <15 0 &gpio0 2 0> /* D15 */
|
||||
, <18 0 &gpio0 29 0> /* D18/A0 */
|
||||
, <19 0 &gpio0 31 0> /* D19/A1 */
|
||||
, <20 0 &gpio0 25 0> /* D20/A2 */
|
||||
, <21 0 &gpio0 11 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 29 0> /* D18/A0 */
|
||||
, <1 0 &gpio0 31 0> /* D19/A1 */
|
||||
, <2 0 &gpio0 25 0> /* D20/A2 */
|
||||
, <3 0 &gpio0 11 0> /* D21/A3 */
|
||||
, <6 0 &gpio0 22 0> /* D4/A6 */
|
||||
, <7 0 &gpio1 0 0> /* D6/A7 */
|
||||
, <8 0 &gpio1 4 0> /* D8/A8 */
|
||||
, <9 0 &gpio1 6 0> /* D9/A9 */
|
||||
, <10 0 &gpio0 9 0> /* D10/A10 */
|
||||
;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
pro_micro_d: &pro_micro {};
|
||||
pro_micro_i2c: &i2c0 {};
|
||||
pro_micro_spi: &spi0 {};
|
||||
pro_micro_serial: &uart0 {};
|
5
app/boards/arm/mikoto/board.cmake
Normal file
5
app/boards/arm/mikoto/board.cmake
Normal file
|
@ -0,0 +1,5 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
|
||||
board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset")
|
||||
include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
115
app/boards/arm/mikoto/mikoto_520.dts
Normal file
115
app/boards/arm/mikoto/mikoto_520.dts
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
#include <nordic/nrf52840_qiaa.dtsi>
|
||||
#include "arduino_pro_micro_pins.dtsi"
|
||||
|
||||
/ {
|
||||
model = "mikoto";
|
||||
compatible = "zhiayang,mikoto";
|
||||
|
||||
chosen {
|
||||
zephyr,code-partition = &code_partition;
|
||||
zephyr,sram = &sram0;
|
||||
zephyr,flash = &flash0;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
blue_led: led_0 {
|
||||
gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
|
||||
label = "Blue LED";
|
||||
};
|
||||
};
|
||||
|
||||
ext-power {
|
||||
compatible = "zmk,ext-power-generic";
|
||||
label = "EXT_POWER";
|
||||
control-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
vbatt {
|
||||
compatible = "zmk,battery-voltage-divider";
|
||||
label = "BATTERY";
|
||||
io-channels = <&adc 2>;
|
||||
output-ohms = <10000000>;
|
||||
full-ohms = <(10000000 + 4000000)>;
|
||||
};
|
||||
};
|
||||
|
||||
&adc {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpiote {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
compatible = "nordic,nrf-twi";
|
||||
sda-pin = <17>;
|
||||
scl-pin = <20>;
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uarte";
|
||||
tx-pin = <8>;
|
||||
rx-pin = <4>;
|
||||
};
|
||||
|
||||
&usbd {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
&flash0 {
|
||||
/*
|
||||
* For more information, see:
|
||||
* http://docs.zephyrproject.org/latest/devices/dts/flash_partitions.html
|
||||
*/
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
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/mikoto/mikoto_520.yaml
Normal file
15
app/boards/arm/mikoto/mikoto_520.yaml
Normal file
|
@ -0,0 +1,15 @@
|
|||
identifier: mikoto_520
|
||||
name: mikoto_520
|
||||
type: mcu
|
||||
arch: arm
|
||||
toolchain:
|
||||
- zephyr
|
||||
- gnuarmemb
|
||||
- xtools
|
||||
supported:
|
||||
- adc
|
||||
- usb_device
|
||||
- ble
|
||||
- ieee802154
|
||||
- pwm
|
||||
- watchdog
|
10
app/boards/arm/mikoto/mikoto_520.zmk.yml
Normal file
10
app/boards/arm/mikoto/mikoto_520.zmk.yml
Normal file
|
@ -0,0 +1,10 @@
|
|||
file_format: "1"
|
||||
id: mikoto_520
|
||||
name: Mikoto 5.20
|
||||
type: board
|
||||
arch: arm
|
||||
outputs:
|
||||
- usb
|
||||
- ble
|
||||
url: https://github.com/zhiayang/mikoto
|
||||
exposes: [pro_micro]
|
20
app/boards/arm/mikoto/mikoto_520_defconfig
Normal file
20
app/boards/arm/mikoto/mikoto_520_defconfig
Normal file
|
@ -0,0 +1,20 @@
|
|||
# SPDX-License-Identifier: MIT
|
||||
|
||||
CONFIG_SOC_SERIES_NRF52X=y
|
||||
CONFIG_SOC_NRF52840_QIAA=y
|
||||
CONFIG_BOARD_MIKOTO_520=y
|
||||
|
||||
# Enable MPU
|
||||
CONFIG_ARM_MPU=y
|
||||
|
||||
# enable GPIO
|
||||
CONFIG_GPIO=y
|
||||
|
||||
CONFIG_USE_DT_CODE_PARTITION=y
|
||||
|
||||
CONFIG_MPU_ALLOW_FLASH_WRITE=y
|
||||
CONFIG_NVS=y
|
||||
CONFIG_SETTINGS_NVS=y
|
||||
CONFIG_FLASH=y
|
||||
CONFIG_FLASH_PAGE_LAYOUT=y
|
||||
CONFIG_FLASH_MAP=y
|
48
app/boards/arm/mikoto/pinmux.c
Normal file
48
app/boards/arm/mikoto/pinmux.c
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2020 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_mikoto_init(const struct device *port) {
|
||||
ARG_UNUSED(port);
|
||||
|
||||
#if CONFIG_BOARD_MIKOTO_520
|
||||
const struct device *p0 = device_get_binding("GPIO_0");
|
||||
const struct device *p1 = device_get_binding("GPIO_1");
|
||||
#if CONFIG_BOARD_MIKOTO_CHARGER_CURRENT_40MA
|
||||
gpio_pin_configure(p0, 26, GPIO_INPUT | GPIO_PULL_DOWN);
|
||||
gpio_pin_configure(p1, 15, GPIO_INPUT);
|
||||
#elif CONFIG_BOARD_MIKOTO_CHARGER_CURRENT_100MA
|
||||
gpio_pin_configure(p0, 26, GPIO_OUTPUT);
|
||||
gpio_pin_set(p0, 26, 0);
|
||||
gpio_pin_configure(p1, 15, GPIO_INPUT);
|
||||
#elif CONFIG_BOARD_MIKOTO_CHARGER_CURRENT_150MA
|
||||
gpio_pin_configure(p0, 26, GPIO_OUTPUT);
|
||||
gpio_pin_set(p0, 26, 0);
|
||||
gpio_pin_configure(p1, 15, GPIO_INPUT | GPIO_PULL_DOWN);
|
||||
#elif CONFIG_BOARD_MIKOTO_CHARGER_CURRENT_250MA
|
||||
gpio_pin_configure(p0, 26, GPIO_INPUT);
|
||||
gpio_pin_configure(p1, 15, GPIO_OUTPUT);
|
||||
gpio_pin_set(p1, 15, 0);
|
||||
#elif CONFIG_BOARD_MIKOTO_CHARGER_CURRENT_350MA
|
||||
gpio_pin_configure(p0, 26, GPIO_OUTPUT);
|
||||
gpio_pin_set(p0, 26, 0);
|
||||
gpio_pin_configure(p1, 15, GPIO_OUTPUT);
|
||||
gpio_pin_set(p1, 15, 0);
|
||||
#elif CONFIG_BOARD_MIKOTO_CHARGER_CURRENT_NONE
|
||||
gpio_pin_configure(p0, 26, GPIO_INPUT);
|
||||
gpio_pin_configure(p1, 15, GPIO_INPUT);
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(pinmux_mikoto_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
19
app/boards/shields/ergodash/Kconfig.defconfig
Normal file
19
app/boards/shields/ergodash/Kconfig.defconfig
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if SHIELD_ERGODASH_LEFT
|
||||
|
||||
config ZMK_KEYBOARD_NAME
|
||||
default "Ergodash"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
||||
if SHIELD_ERGODASH_LEFT || SHIELD_ERGODASH_RIGHT
|
||||
|
||||
config ZMK_SPLIT
|
||||
default y
|
||||
|
||||
endif
|
8
app/boards/shields/ergodash/Kconfig.shield
Normal file
8
app/boards/shields/ergodash/Kconfig.shield
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config SHIELD_ERGODASH_LEFT
|
||||
def_bool $(shields_list_contains,ergodash_left)
|
||||
|
||||
config SHIELD_ERGODASH_RIGHT
|
||||
def_bool $(shields_list_contains,ergodash_right)
|
0
app/boards/shields/ergodash/ergodash.conf
Normal file
0
app/boards/shields/ergodash/ergodash.conf
Normal file
61
app/boards/shields/ergodash/ergodash.dtsi
Normal file
61
app/boards/shields/ergodash/ergodash.dtsi
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <dt-bindings/zmk/matrix_transform.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,kscan = &kscan0;
|
||||
zmk,matrix_transform = &default_transform;
|
||||
};
|
||||
|
||||
default_transform: keymap_transform_0 {
|
||||
compatible = "zmk,matrix-transform";
|
||||
columns = <14>;
|
||||
rows = <5>;
|
||||
// Numbering based on rev 1.2 schema
|
||||
// * keys that can be in different positions are denoted as MW
|
||||
// * MW40 can be broken off
|
||||
// | SW1 | SW5 | SW9 | SW13 | SW17 | SW21 | SW25 | | | | SW25 | SW21 | SW17 | SW13 | SW9 | SW5 | SW1 |
|
||||
// | SW2 | SW6 | SW10 | SW14 | SW18 | SW22 | SW26 | | | | SW26 | SW22 | SW18 | SW14 | SW10 | SW6 | SW2 |
|
||||
// | SW3 | SW7 | SW11 | SW15 | SW19 | SW23 | SW27 | | | | SW27 | SW23 | SW19 | SW15 | SW11 | SW7 | SW3 |
|
||||
// | SW4 | SW8 | SW12 | SW16 | SW20 | SW24 | | MW28 | | MW28 | | SW24 | SW20 | SW16 | SW12 | SW8 | SW4 |
|
||||
// | SW30 | SW31 | SW32 | MW33 | SW34 | | MW35 | MW40 | | MW40 | MW35 | | SW34 | MW33 | SW32 | SW31 | SW30 |
|
||||
map = <
|
||||
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,13) RC(0,12) RC(0,11) RC(0,10) RC(0,9) RC(0,8) RC(0,7)
|
||||
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,13) RC(1,12) RC(1,11) RC(1,10) RC(1,9) RC(1,8) 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,13) RC(2,12) RC(2,11) RC(2,10) RC(2,9) RC(2,8) 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,13) RC(3,12) RC(3,11) RC(3,10) RC(3,9) RC(3,8) RC(3,7)
|
||||
RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,5) RC(4,6) RC(4,13) RC(4,12) RC(4,11) RC(4,10) RC(4,9) RC(4,8) RC(4,7)
|
||||
>;
|
||||
};
|
||||
|
||||
kscan0: kscan {
|
||||
compatible = "zmk,kscan-gpio-matrix";
|
||||
label = "KSCAN";
|
||||
|
||||
diode-direction = "col2row";
|
||||
|
||||
row-gpios
|
||||
= <&pro_micro 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
;
|
||||
|
||||
col-gpios
|
||||
= <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 20 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 19 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 18 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&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)>
|
||||
;
|
||||
};
|
||||
};
|
||||
|
86
app/boards/shields/ergodash/ergodash.keymap
Normal file
86
app/boards/shields/ergodash/ergodash.keymap
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/bt.h>
|
||||
|
||||
#define DEFAULT 0
|
||||
#define LOWER 1
|
||||
#define RAISE 2
|
||||
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
|
||||
default_layer {
|
||||
/* QWERTY
|
||||
* .----------------------------------------------------------------------------------------------------------------------.
|
||||
* | ` | 1 | 2 | 3 | 4 | 5 | [ | | ] | 6 | 7 | 8 | 9 | 0 | PScr |
|
||||
* |------+------+------+------+------+------+------+--------------------+------+------+------+------+------+------+------|
|
||||
* | ESC | Q | W | E | R | T | - | | = | Y | U | I | O | P | \ |
|
||||
* |------+------+------+------+------+------+------+--------------------+------+------+------+------+------+------+------|
|
||||
* | Tab | A | S | D | F | G | Del | | Bksp | H | J | K | L | ; | ' |
|
||||
* |------+------+------+------+------+------+---------------------------+------+------+------+------+------+------+------|
|
||||
* | Shift| Z | X | C | V | B | End | | Home | N | M | , | . | / | Shift|
|
||||
* |-------------+------+------+------+------+------+------+------+------+------+------+------+------+------+-------------|
|
||||
* | Ctrl | | PGDN | Win |||||||| Alt | Space| Lower|||||||| Raise| Enter| RAlt |||||||| | PGUP | Ins | RCtrl|
|
||||
* .----------------------------------------------------------------------------------------------------------------------.
|
||||
*/
|
||||
bindings = <
|
||||
&kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp LBKT &kp RBKT &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp PSCRN
|
||||
&kp ESC &kp Q &kp W &kp E &kp R &kp T &kp MINUS &kp EQUAL &kp Y &kp U &kp I &kp O &kp P &kp BSLH
|
||||
&kp TAB &kp A &kp S &kp D &kp F &kp G &kp DEL &kp BSPC &kp H &kp J &kp K &kp L &kp SEMI &kp SQT
|
||||
&kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp END &kp HOME &kp N &kp M &kp COMMA &kp DOT &kp SLASH &kp RSHFT
|
||||
&kp LCTRL &none &kp PG_DN &kp LMETA &kp LALT &kp SPACE &mo LOWER &mo RAISE &kp RET &kp RALT &none &kp PG_UP &kp INS &kp RCTRL
|
||||
>;
|
||||
};
|
||||
lower_layer {
|
||||
/* .----------------------------------------------------------------------------------------------------------------------.
|
||||
* | F11 | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F12 |
|
||||
* |------+------+------+------+------+------+------+--------------------+------+------+------+------+------+------+------|
|
||||
* | | | | | | | | | | | | | | | |
|
||||
* |------+------+------+------+------+------+------+--------------------+------+------+------+------+------+------+------|
|
||||
* | | | | | | | | | | | | | | | |
|
||||
* |------+------+------+------+------+------+---------------------------+------+------+------+------+------+------+------|
|
||||
* | Shift| Boot | Reset| | | | | | | | | | | | Shift|
|
||||
* |-------------+------+------+------+------+------+------+------+------+------+------+------+------+------+-------------|
|
||||
* | Ctlr | | | Win |||||||| Alt | | Lower|||||||| Raise| | RAlt |||||||| | | | RCtrl|
|
||||
* .----------------------------------------------------------------------------------------------------------------------.
|
||||
*/ /* FIXME boot and reset are not yet locale aware */
|
||||
bindings = <
|
||||
&kp F11 &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp &none &kp &none &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F12
|
||||
&none &none &none &none &none &none &none &none &none &none &none &none &none &none
|
||||
&none &none &none &none &none &none &none &none &none &none &none &none &none &none
|
||||
&trans &bootloader &reset &none &none &none &none &none &none &none &none &none &none &trans
|
||||
&trans &none &none &trans &trans &none &trans &trans &none &trans &none &none &none &trans
|
||||
>;
|
||||
};
|
||||
raise_layer {
|
||||
/* .----------------------------------------------------------------------------------------------------------------------.
|
||||
* | | BT 0 | BT 1 | BT 2 | BT 3 | | BTCL | | | | | | | | |
|
||||
* |------+------+------+------+------+------+------+--------------------+------+------+------+------+------+------+------|
|
||||
* | | | | | | | | | | | | | | | |
|
||||
* |------+------+------+------+------+------+------+--------------------+------+------+------+------+------+------+------|
|
||||
* | | | | | | | | | | | | | | | |
|
||||
* |------+------+------+------+------+------+---------------------------+------+------+------+------+------+------+------|
|
||||
* | Shift| | | | | | | | | | | | Boot | Reset| Shift|
|
||||
* |-------------+------+------+------+------+------+------+------+------+------+------+------+------+------+-------------|
|
||||
* | Ctlr | | | Win |||||||| Alt | | Lower|||||||| Raise| | RAlt |||||||| | | | RCtrl|
|
||||
* .----------------------------------------------------------------------------------------------------------------------.
|
||||
*/ /* FIXME boot and reset are not yet locale aware */
|
||||
bindings = <
|
||||
&none &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &none &bt BT_CLR &none &none &none &none &none &none &none
|
||||
&none &none &none &none &none &none &none &none &none &none &none &none &none &none
|
||||
&none &none &none &none &none &none &none &none &none &none &none &none &none &none
|
||||
&trans &none &none &none &none &none &none &none &none &none &none &bootloader &reset &trans
|
||||
&trans &none &none &trans &trans &none &trans &trans &none &trans &none &none &none &trans
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
11
app/boards/shields/ergodash/ergodash.zmk.yml
Normal file
11
app/boards/shields/ergodash/ergodash.zmk.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
file_format: "1"
|
||||
id: ergodash
|
||||
name: Ergodash
|
||||
type: shield
|
||||
url: https://github.com/omkbd/ErgoDash
|
||||
requires: [pro_micro]
|
||||
features:
|
||||
- keys
|
||||
siblings:
|
||||
- ergodash_left
|
||||
- ergodash_right
|
8
app/boards/shields/ergodash/ergodash_left.overlay
Normal file
8
app/boards/shields/ergodash/ergodash_left.overlay
Normal file
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "ergodash.dtsi"
|
||||
|
11
app/boards/shields/ergodash/ergodash_right.overlay
Normal file
11
app/boards/shields/ergodash/ergodash_right.overlay
Normal file
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "ergodash.dtsi"
|
||||
|
||||
&default_transform {
|
||||
col-offset = <7>;
|
||||
};
|
|
@ -35,8 +35,8 @@
|
|||
// | | | RET | ADJ | |
|
||||
bindings = <
|
||||
&trans &kp EXCL &kp AT &kp HASH &kp DLLR &kp PRCNT &kp CARET &kp AMPS &kp N8 &kp LPAR &kp RPAR &kp DEL
|
||||
&trans &kp MINUS &kp KP_PLUS &kp LBRC &kp RBRC &kp PIPE &kp LEFT &kp DOWN &kp UP &kp RIGHT &kp GRAVE &kp GRAVE
|
||||
&trans &kp ESC &kp LGUI &kp LALT &kp CLCK &kp SQT &kp HOME &kp END &kp PG_UP &kp PG_DN &kp PSCRN &mt RSHFT RET
|
||||
&trans &kp MINUS &kp KP_PLUS &kp LBRC &kp RBRC &kp PIPE &kp LEFT &kp DOWN &kp UP &kp RIGHT &kp GRAVE &kp TILDE
|
||||
&trans &kp ESC &kp LGUI &kp LALT &kp CLCK &kp DQT &kp HOME &kp END &kp PG_UP &kp PG_DN &kp PSCRN &mt RSHFT RET
|
||||
&trans &trans &kp RET &mo 3 &trans
|
||||
>;
|
||||
};
|
||||
|
@ -50,7 +50,7 @@
|
|||
bindings = <
|
||||
&trans &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp DEL
|
||||
&trans &kp MINUS &kp EQUAL &kp LBKT &kp RBKT &kp BSLH &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6
|
||||
&trans &kp ESC &kp LGUI &kp RALT &kp CLCK &kp SQT &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12
|
||||
&trans &kp ESC &kp LGUI &kp RALT &kp CLCK &kp DQT &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12
|
||||
&trans &mo 3 &kp BSPC &trans &trans
|
||||
>;
|
||||
};
|
||||
|
@ -58,7 +58,7 @@
|
|||
adjust_layer {
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// | RGB BRI+ | RGB SAT+ | RGB HUE+ | RGB ANI+ | | RGB TOG | | BT1 | BT2 | BT3 | BT4 | BT5 | BT CLR |
|
||||
// | RGB BRI- | RGB SAT- | RGB HUE- | RGB ANI+ | | | | | | | | | |
|
||||
// | RGB BRI- | RGB SAT- | RGB HUE- | RGB ANI- | | | | | | | | | |
|
||||
// | | | | | | | | RESET | | | | | |
|
||||
// | | | | | |
|
||||
bindings = <
|
||||
|
|
|
@ -61,13 +61,16 @@ foreach(root ${BOARD_ROOT})
|
|||
if (EXISTS "${root}/boards/${BOARD}.overlay")
|
||||
list(APPEND ZMK_DTC_FILES "${root}/boards/${BOARD}.overlay")
|
||||
endif()
|
||||
find_path(BOARD_DIR
|
||||
NAMES ${BOARD}_defconfig
|
||||
PATHS ${root}/boards/*/*
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
if(BOARD_DIR)
|
||||
list(APPEND KEYMAP_DIRS ${BOARD_DIR})
|
||||
if (NOT DEFINED BOARD_DIR_NAME)
|
||||
find_path(BOARD_DIR
|
||||
NAMES ${BOARD}_defconfig
|
||||
PATHS ${root}/boards/*/*
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
if(BOARD_DIR)
|
||||
get_filename_component(BOARD_DIR_NAME ${BOARD_DIR} NAME)
|
||||
list(APPEND KEYMAP_DIRS ${BOARD_DIR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(DEFINED SHIELD)
|
||||
|
@ -130,7 +133,7 @@ endif()
|
|||
|
||||
if(NOT KEYMAP_FILE)
|
||||
foreach(keymap_dir ${KEYMAP_DIRS})
|
||||
foreach(keymap_prefix ${SHIELD} ${SHIELD_DIR} ${BOARD} ${BOARD_DIR})
|
||||
foreach(keymap_prefix ${SHIELD} ${SHIELD_DIR} ${BOARD} ${BOARD_DIR_NAME})
|
||||
if (EXISTS ${keymap_dir}/${keymap_prefix}.keymap)
|
||||
set(KEYMAP_FILE "${keymap_dir}/${keymap_prefix}.keymap" CACHE STRING "Selected keymap file")
|
||||
message(STATUS "Using keymap file: ${KEYMAP_FILE}")
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
zephyr_library_named(zmk__drivers__kscan)
|
||||
zephyr_library_include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_DRIVER debounce.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_DRIVER kscan_gpio_matrix.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_DRIVER kscan_gpio_direct.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_ZMK_KSCAN_GPIO_DRIVER kscan_gpio_demux.c)
|
||||
|
|
|
@ -14,6 +14,24 @@ config ZMK_KSCAN_MATRIX_POLLING
|
|||
config ZMK_KSCAN_DIRECT_POLLING
|
||||
bool "Poll for key event triggers instead of using interrupts on direct wired boards."
|
||||
|
||||
config ZMK_KSCAN_DEBOUNCE_PRESS_MS
|
||||
int "Debounce time for key press in milliseconds."
|
||||
default -1
|
||||
help
|
||||
Global debounce time for key press in milliseconds.
|
||||
If this is -1, the debounce time is controlled by the debounce-press-ms
|
||||
Devicetree property, which defaults to 5 ms. Otherwise this overrides the
|
||||
debounce time for all key scan drivers to the chosen value.
|
||||
|
||||
config ZMK_KSCAN_DEBOUNCE_RELEASE_MS
|
||||
int "Debounce time for key release in milliseconds."
|
||||
default -1
|
||||
help
|
||||
Global debounce time for key release in milliseconds.
|
||||
If this is -1, the debounce time is controlled by the debounce-release-ms
|
||||
Devicetree property, which defaults to 5 ms. Otherwise this overrides the
|
||||
debounce time for all key scan drivers to the chosen value.
|
||||
|
||||
endif
|
||||
|
||||
config ZMK_KSCAN_INIT_PRIORITY
|
||||
|
|
62
app/drivers/kscan/debounce.c
Normal file
62
app/drivers/kscan/debounce.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "debounce.h"
|
||||
|
||||
static uint32_t get_threshold(const struct debounce_state *state,
|
||||
const struct debounce_config *config) {
|
||||
return state->pressed ? config->debounce_release_ms : config->debounce_press_ms;
|
||||
}
|
||||
|
||||
static void increment_counter(struct debounce_state *state, const int elapsed_ms) {
|
||||
if (state->counter + elapsed_ms > DEBOUNCE_COUNTER_MAX) {
|
||||
state->counter = DEBOUNCE_COUNTER_MAX;
|
||||
} else {
|
||||
state->counter += elapsed_ms;
|
||||
}
|
||||
}
|
||||
|
||||
static void decrement_counter(struct debounce_state *state, const int elapsed_ms) {
|
||||
if (state->counter < elapsed_ms) {
|
||||
state->counter = 0;
|
||||
} else {
|
||||
state->counter -= elapsed_ms;
|
||||
}
|
||||
}
|
||||
|
||||
void debounce_update(struct debounce_state *state, const bool active, const int elapsed_ms,
|
||||
const struct debounce_config *config) {
|
||||
// This uses a variation of the integrator debouncing described at
|
||||
// https://www.kennethkuhn.com/electronics/debounce.c
|
||||
// Every update where "active" does not match the current state, we increment
|
||||
// a counter, otherwise we decrement it. When the counter reaches a
|
||||
// threshold, the state flips and we reset the counter.
|
||||
state->changed = false;
|
||||
|
||||
if (active == state->pressed) {
|
||||
decrement_counter(state, elapsed_ms);
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t flip_threshold = get_threshold(state, config);
|
||||
|
||||
if (state->counter < flip_threshold) {
|
||||
increment_counter(state, elapsed_ms);
|
||||
return;
|
||||
}
|
||||
|
||||
state->pressed = !state->pressed;
|
||||
state->counter = 0;
|
||||
state->changed = true;
|
||||
}
|
||||
|
||||
bool debounce_is_active(const struct debounce_state *state) {
|
||||
return state->pressed || state->counter > 0;
|
||||
}
|
||||
|
||||
bool debounce_is_pressed(const struct debounce_state *state) { return state->pressed; }
|
||||
|
||||
bool debounce_get_changed(const struct debounce_state *state) { return state->changed; }
|
56
app/drivers/kscan/debounce.h
Normal file
56
app/drivers/kscan/debounce.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/util.h>
|
||||
|
||||
#define DEBOUNCE_COUNTER_BITS 14
|
||||
#define DEBOUNCE_COUNTER_MAX BIT_MASK(DEBOUNCE_COUNTER_BITS)
|
||||
|
||||
struct debounce_state {
|
||||
bool pressed : 1;
|
||||
bool changed : 1;
|
||||
uint16_t counter : DEBOUNCE_COUNTER_BITS;
|
||||
};
|
||||
|
||||
struct debounce_config {
|
||||
/** Duration a switch must be pressed to latch as pressed. */
|
||||
uint32_t debounce_press_ms;
|
||||
/** Duration a switch must be released to latch as released. */
|
||||
uint32_t debounce_release_ms;
|
||||
};
|
||||
|
||||
/**
|
||||
* Debounces one switch.
|
||||
*
|
||||
* @param state The state for the switch to debounce.
|
||||
* @param active Is the switch currently pressed?
|
||||
* @param elapsed_ms Time elapsed since the previous update in milliseconds.
|
||||
* @param config Debounce settings.
|
||||
*/
|
||||
void debounce_update(struct debounce_state *state, const bool active, const int elapsed_ms,
|
||||
const struct debounce_config *config);
|
||||
|
||||
/**
|
||||
* @returns whether the switch is either latched as pressed or it is potentially
|
||||
* pressed but the debouncer has not yet made a decision. If this returns true,
|
||||
* the kscan driver should continue to poll quickly.
|
||||
*/
|
||||
bool debounce_is_active(const struct debounce_state *state);
|
||||
|
||||
/**
|
||||
* @returns whether the switch is latched as pressed.
|
||||
*/
|
||||
bool debounce_is_pressed(const struct debounce_state *state);
|
||||
|
||||
/**
|
||||
* @returns whether the pressed state of the switch changed in the last call to
|
||||
* debounce_update.
|
||||
*/
|
||||
bool debounce_get_changed(const struct debounce_state *state);
|
|
@ -4,10 +4,13 @@
|
|||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "debounce.h"
|
||||
|
||||
#include <device.h>
|
||||
#include <devicetree.h>
|
||||
#include <drivers/gpio.h>
|
||||
#include <drivers/kscan.h>
|
||||
#include <kernel.h>
|
||||
#include <logging/log.h>
|
||||
#include <sys/__assert.h>
|
||||
#include <sys/util.h>
|
||||
|
@ -27,6 +30,20 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
#define INST_MATRIX_LEN(n) (INST_ROWS_LEN(n) * INST_COLS_LEN(n))
|
||||
#define INST_INPUTS_LEN(n) COND_DIODE_DIR(n, (INST_COLS_LEN(n)), (INST_ROWS_LEN(n)))
|
||||
|
||||
#if CONFIG_ZMK_KSCAN_DEBOUNCE_PRESS_MS >= 0
|
||||
#define INST_DEBOUNCE_PRESS_MS(n) CONFIG_ZMK_KSCAN_DEBOUNCE_PRESS_MS
|
||||
#else
|
||||
#define INST_DEBOUNCE_PRESS_MS(n) \
|
||||
DT_INST_PROP_OR(n, debounce_period, DT_INST_PROP(n, debounce_press_ms))
|
||||
#endif
|
||||
|
||||
#if CONFIG_ZMK_KSCAN_DEBOUNCE_RELEASE_MS >= 0
|
||||
#define INST_DEBOUNCE_RELEASE_MS(n) CONFIG_ZMK_KSCAN_DEBOUNCE_RELEASE_MS
|
||||
#else
|
||||
#define INST_DEBOUNCE_RELEASE_MS(n) \
|
||||
DT_INST_PROP_OR(n, debounce_period, DT_INST_PROP(n, debounce_release_ms))
|
||||
#endif
|
||||
|
||||
#define USE_POLLING IS_ENABLED(CONFIG_ZMK_KSCAN_MATRIX_POLLING)
|
||||
#define USE_INTERRUPTS (!USE_POLLING)
|
||||
|
||||
|
@ -66,26 +83,23 @@ enum kscan_diode_direction {
|
|||
struct kscan_matrix_irq_callback {
|
||||
const struct device *dev;
|
||||
struct gpio_callback callback;
|
||||
struct k_delayed_work *work;
|
||||
};
|
||||
|
||||
struct kscan_matrix_data {
|
||||
const struct device *dev;
|
||||
kscan_callback_t callback;
|
||||
struct k_delayed_work work;
|
||||
#if USE_POLLING
|
||||
struct k_timer poll_timer;
|
||||
#else
|
||||
#if USE_INTERRUPTS
|
||||
/** Array of length config->inputs.len */
|
||||
struct kscan_matrix_irq_callback *irqs;
|
||||
#endif
|
||||
/** Timestamp of the current or scheduled scan. */
|
||||
int64_t scan_time;
|
||||
/**
|
||||
* Current state of the matrix as a flattened 2D array of length
|
||||
* (config->rows.len * config->cols.len)
|
||||
*/
|
||||
bool *current_state;
|
||||
/** Buffer for reading in the next matrix state. Parallel array to current_state. */
|
||||
bool *next_state;
|
||||
struct debounce_state *matrix_state;
|
||||
};
|
||||
|
||||
struct kscan_gpio_list {
|
||||
|
@ -102,7 +116,8 @@ struct kscan_matrix_config {
|
|||
struct kscan_gpio_list cols;
|
||||
struct kscan_gpio_list inputs;
|
||||
struct kscan_gpio_list outputs;
|
||||
int32_t debounce_period_ms;
|
||||
struct debounce_config debounce_config;
|
||||
int32_t debounce_scan_period_ms;
|
||||
int32_t poll_period_ms;
|
||||
enum kscan_diode_direction diode_direction;
|
||||
};
|
||||
|
@ -190,19 +205,49 @@ static int kscan_matrix_interrupt_disable(const struct device *dev) {
|
|||
#if USE_INTERRUPTS
|
||||
static void kscan_matrix_irq_callback_handler(const struct device *port, struct gpio_callback *cb,
|
||||
const gpio_port_pins_t pin) {
|
||||
struct kscan_matrix_irq_callback *data =
|
||||
struct kscan_matrix_irq_callback *irq_data =
|
||||
CONTAINER_OF(cb, struct kscan_matrix_irq_callback, callback);
|
||||
const struct kscan_matrix_config *config = data->dev->config;
|
||||
struct kscan_matrix_data *data = irq_data->dev->data;
|
||||
|
||||
// Disable our interrupts temporarily to avoid re-entry while we scan.
|
||||
kscan_matrix_interrupt_disable(data->dev);
|
||||
|
||||
data->scan_time = k_uptime_get();
|
||||
|
||||
// TODO (Zephyr 2.6): use k_work_reschedule()
|
||||
k_delayed_work_cancel(data->work);
|
||||
k_delayed_work_submit(data->work, K_MSEC(config->debounce_period_ms));
|
||||
k_delayed_work_cancel(&data->work);
|
||||
k_delayed_work_submit(&data->work, K_NO_WAIT);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void kscan_matrix_read_continue(const struct device *dev) {
|
||||
const struct kscan_matrix_config *config = dev->config;
|
||||
struct kscan_matrix_data *data = dev->data;
|
||||
|
||||
data->scan_time += config->debounce_scan_period_ms;
|
||||
|
||||
// TODO (Zephyr 2.6): use k_work_reschedule()
|
||||
k_delayed_work_cancel(&data->work);
|
||||
k_delayed_work_submit(&data->work, K_TIMEOUT_ABS_MS(data->scan_time));
|
||||
}
|
||||
|
||||
static void kscan_matrix_read_end(const struct device *dev) {
|
||||
#if USE_INTERRUPTS
|
||||
// Return to waiting for an interrupt.
|
||||
kscan_matrix_interrupt_enable(dev);
|
||||
#else
|
||||
struct kscan_matrix_data *data = dev->data;
|
||||
const struct kscan_matrix_config *config = dev->config;
|
||||
|
||||
data->scan_time += config->poll_period_ms;
|
||||
|
||||
// Return to polling slowly.
|
||||
// TODO (Zephyr 2.6): use k_work_reschedule()
|
||||
k_delayed_work_cancel(&data->work);
|
||||
k_delayed_work_submit(&data->work, K_TIMEOUT_ABS_MS(data->scan_time));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int kscan_matrix_read(const struct device *dev) {
|
||||
struct kscan_matrix_data *data = dev->data;
|
||||
const struct kscan_matrix_config *config = dev->config;
|
||||
|
@ -221,7 +266,10 @@ static int kscan_matrix_read(const struct device *dev) {
|
|||
const struct kscan_gpio_dt_spec *in_gpio = &config->inputs.gpios[i];
|
||||
|
||||
const int index = state_index_io(config, i, o);
|
||||
data->next_state[index] = gpio_pin_get(in_gpio->port, in_gpio->pin);
|
||||
const bool active = gpio_pin_get(in_gpio->port, in_gpio->pin);
|
||||
|
||||
debounce_update(&data->matrix_state[index], active, config->debounce_scan_period_ms,
|
||||
&config->debounce_config);
|
||||
}
|
||||
|
||||
err = gpio_pin_set(out_gpio->port, out_gpio->pin, 0);
|
||||
|
@ -232,50 +280,36 @@ static int kscan_matrix_read(const struct device *dev) {
|
|||
}
|
||||
|
||||
// Process the new state.
|
||||
#if USE_INTERRUPTS
|
||||
bool submit_followup_read = false;
|
||||
#endif
|
||||
bool continue_scan = false;
|
||||
|
||||
for (int r = 0; r < config->rows.len; r++) {
|
||||
for (int c = 0; c < config->cols.len; c++) {
|
||||
const int index = state_index_rc(config, r, c);
|
||||
const bool pressed = data->next_state[index];
|
||||
struct debounce_state *state = &data->matrix_state[index];
|
||||
|
||||
if (debounce_get_changed(state)) {
|
||||
const bool pressed = debounce_is_pressed(state);
|
||||
|
||||
// Follow up reads are needed if any key is pressed because further
|
||||
// interrupts won't fire on already tripped GPIO pins.
|
||||
#if USE_INTERRUPTS
|
||||
submit_followup_read = submit_followup_read || pressed;
|
||||
#endif
|
||||
if (pressed != data->current_state[index]) {
|
||||
LOG_DBG("Sending event at %i,%i state %s", r, c, pressed ? "on" : "off");
|
||||
data->current_state[index] = pressed;
|
||||
data->callback(dev, r, c, pressed);
|
||||
}
|
||||
|
||||
continue_scan = continue_scan || debounce_is_active(state);
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_INTERRUPTS
|
||||
if (submit_followup_read) {
|
||||
// At least one key is pressed. Poll until everything is released.
|
||||
// TODO (Zephyr 2.6): use k_work_reschedule()
|
||||
k_delayed_work_cancel(&data->work);
|
||||
k_delayed_work_submit(&data->work, K_MSEC(config->debounce_period_ms));
|
||||
if (continue_scan) {
|
||||
// At least one key is pressed or the debouncer has not yet decided if
|
||||
// it is pressed. Poll quickly until everything is released.
|
||||
kscan_matrix_read_continue(dev);
|
||||
} else {
|
||||
// All keys are released. Return to waiting for an interrupt.
|
||||
kscan_matrix_interrupt_enable(dev);
|
||||
// All keys are released. Return to normal.
|
||||
kscan_matrix_read_end(dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if USE_POLLING
|
||||
static void kscan_matrix_timer_handler(struct k_timer *timer) {
|
||||
struct kscan_matrix_data *data = CONTAINER_OF(timer, struct kscan_matrix_data, poll_timer);
|
||||
k_delayed_work_submit(&data->work, K_NO_WAIT);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void kscan_matrix_work_handler(struct k_work *work) {
|
||||
struct k_delayed_work *dwork = CONTAINER_OF(work, struct k_delayed_work, work);
|
||||
struct kscan_matrix_data *data = CONTAINER_OF(dwork, struct kscan_matrix_data, work);
|
||||
|
@ -294,27 +328,23 @@ static int kscan_matrix_configure(const struct device *dev, const kscan_callback
|
|||
}
|
||||
|
||||
static int kscan_matrix_enable(const struct device *dev) {
|
||||
#if USE_POLLING
|
||||
struct kscan_matrix_data *data = dev->data;
|
||||
const struct kscan_matrix_config *config = dev->config;
|
||||
|
||||
k_timer_start(&data->poll_timer, K_MSEC(config->poll_period_ms),
|
||||
K_MSEC(config->poll_period_ms));
|
||||
return 0;
|
||||
#else
|
||||
// Read will automatically enable interrupts once done.
|
||||
data->scan_time = k_uptime_get();
|
||||
|
||||
// Read will automatically start interrupts/polling once done.
|
||||
return kscan_matrix_read(dev);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int kscan_matrix_disable(const struct device *dev) {
|
||||
#if USE_POLLING
|
||||
struct kscan_matrix_data *data = dev->data;
|
||||
|
||||
k_timer_stop(&data->poll_timer);
|
||||
return 0;
|
||||
#else
|
||||
k_delayed_work_cancel(&data->work);
|
||||
|
||||
#if USE_INTERRUPTS
|
||||
return kscan_matrix_interrupt_disable(dev);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -338,7 +368,6 @@ static int kscan_matrix_init_input_inst(const struct device *dev,
|
|||
struct kscan_matrix_irq_callback *irq = &data->irqs[index];
|
||||
|
||||
irq->dev = dev;
|
||||
irq->work = &data->work;
|
||||
gpio_init_callback(&irq->callback, kscan_matrix_irq_callback_handler, BIT(gpio->pin));
|
||||
err = gpio_add_callback(gpio->port, &irq->callback);
|
||||
if (err) {
|
||||
|
@ -407,10 +436,6 @@ static int kscan_matrix_init(const struct device *dev) {
|
|||
|
||||
k_delayed_work_init(&data->work, kscan_matrix_work_handler);
|
||||
|
||||
#if USE_POLLING
|
||||
k_timer_init(&data->poll_timer, kscan_matrix_timer_handler, NULL);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -421,21 +446,24 @@ static const struct kscan_driver_api kscan_matrix_api = {
|
|||
};
|
||||
|
||||
#define KSCAN_MATRIX_INIT(index) \
|
||||
BUILD_ASSERT(INST_DEBOUNCE_PRESS_MS(index) <= DEBOUNCE_COUNTER_MAX, \
|
||||
"ZMK_KSCAN_DEBOUNCE_PRESS_MS or debounce-press-ms is too large"); \
|
||||
BUILD_ASSERT(INST_DEBOUNCE_RELEASE_MS(index) <= DEBOUNCE_COUNTER_MAX, \
|
||||
"ZMK_KSCAN_DEBOUNCE_RELEASE_MS or debounce-release-ms is too large"); \
|
||||
\
|
||||
static const struct kscan_gpio_dt_spec kscan_matrix_rows_##index[] = { \
|
||||
UTIL_LISTIFY(INST_ROWS_LEN(index), KSCAN_GPIO_ROW_CFG_INIT, index)}; \
|
||||
\
|
||||
static const struct kscan_gpio_dt_spec kscan_matrix_cols_##index[] = { \
|
||||
UTIL_LISTIFY(INST_COLS_LEN(index), KSCAN_GPIO_COL_CFG_INIT, index)}; \
|
||||
\
|
||||
static bool kscan_current_state_##index[INST_MATRIX_LEN(index)]; \
|
||||
static bool kscan_next_state_##index[INST_MATRIX_LEN(index)]; \
|
||||
static struct debounce_state kscan_matrix_state_##index[INST_MATRIX_LEN(index)]; \
|
||||
\
|
||||
COND_INTERRUPTS((static struct kscan_matrix_irq_callback \
|
||||
kscan_matrix_irqs_##index[INST_INPUTS_LEN(index)];)) \
|
||||
\
|
||||
static struct kscan_matrix_data kscan_matrix_data_##index = { \
|
||||
.current_state = kscan_current_state_##index, \
|
||||
.next_state = kscan_next_state_##index, \
|
||||
.matrix_state = kscan_matrix_state_##index, \
|
||||
COND_INTERRUPTS((.irqs = kscan_matrix_irqs_##index, ))}; \
|
||||
\
|
||||
static struct kscan_matrix_config kscan_matrix_config_##index = { \
|
||||
|
@ -445,7 +473,12 @@ static const struct kscan_driver_api kscan_matrix_api = {
|
|||
COND_DIODE_DIR(index, (kscan_matrix_cols_##index), (kscan_matrix_rows_##index))), \
|
||||
.outputs = KSCAN_GPIO_LIST( \
|
||||
COND_DIODE_DIR(index, (kscan_matrix_rows_##index), (kscan_matrix_cols_##index))), \
|
||||
.debounce_period_ms = DT_INST_PROP(index, debounce_period), \
|
||||
.debounce_config = \
|
||||
{ \
|
||||
.debounce_press_ms = INST_DEBOUNCE_PRESS_MS(index), \
|
||||
.debounce_release_ms = INST_DEBOUNCE_RELEASE_MS(index), \
|
||||
}, \
|
||||
.debounce_scan_period_ms = DT_INST_PROP(index, debounce_scan_period_ms), \
|
||||
.poll_period_ms = DT_INST_PROP(index, poll_period_ms), \
|
||||
.diode_direction = INST_DIODE_DIR(index), \
|
||||
}; \
|
||||
|
|
|
@ -15,13 +15,26 @@ properties:
|
|||
type: phandle-array
|
||||
required: true
|
||||
debounce-period:
|
||||
type: int
|
||||
required: false
|
||||
deprecated: true
|
||||
description: Deprecated. Use debounce-press-ms and debounce-release-ms instead.
|
||||
debounce-press-ms:
|
||||
type: int
|
||||
default: 5
|
||||
description: Debounce time in milliseconds
|
||||
description: Debounce time for key press in milliseconds. Use 0 for eager debouncing.
|
||||
debounce-release-ms:
|
||||
type: int
|
||||
default: 5
|
||||
description: Debounce time for key release in milliseconds.
|
||||
debounce-scan-period-ms:
|
||||
type: int
|
||||
default: 1
|
||||
description: Time between reads in milliseconds when any key is pressed.
|
||||
poll-period-ms:
|
||||
type: int
|
||||
default: 10
|
||||
description: Time between reads in milliseconds when polling is enabled
|
||||
description: Time between reads in milliseconds when no key is pressed and ZMK_KSCAN_MATRIX_POLLING is enabled.
|
||||
diode-direction:
|
||||
type: string
|
||||
default: row2col
|
||||
|
|
|
@ -28,5 +28,10 @@ properties:
|
|||
- "hold-preferred"
|
||||
- "balanced"
|
||||
- "tap-preferred"
|
||||
- "tap-unless-interrupted"
|
||||
retro-tap:
|
||||
type: boolean
|
||||
hold-trigger-key-positions:
|
||||
type: array
|
||||
required: false
|
||||
default: []
|
||||
|
|
|
@ -143,12 +143,14 @@ static const uint8_t zmk_hid_report_desc[] = {
|
|||
/* LOGICAL_MINIMUM (0) */
|
||||
HID_GI_LOGICAL_MIN(1),
|
||||
0x00,
|
||||
/* LOGICAL_MAXIMUM (0xFFFF) */
|
||||
HID_GI_LOGICAL_MAX(1),
|
||||
/* LOGICAL_MAXIMUM (0x00FF) - little endian, and requires two bytes because logical max is
|
||||
signed */
|
||||
HID_GI_LOGICAL_MAX(2),
|
||||
0xFF,
|
||||
0x00,
|
||||
HID_LI_USAGE_MIN(1),
|
||||
0x00,
|
||||
/* USAGE_MAXIMUM (0xFFFF) */
|
||||
/* USAGE_MAXIMUM (0xFF) */
|
||||
HID_LI_USAGE_MAX(1),
|
||||
0xFF,
|
||||
/* INPUT (Data,Ary,Abs) */
|
||||
|
|
|
@ -34,6 +34,7 @@ enum flavor {
|
|||
FLAVOR_HOLD_PREFERRED,
|
||||
FLAVOR_BALANCED,
|
||||
FLAVOR_TAP_PREFERRED,
|
||||
FLAVOR_TAP_UNLESS_INTERRUPTED,
|
||||
};
|
||||
|
||||
enum status {
|
||||
|
@ -58,6 +59,8 @@ struct behavior_hold_tap_config {
|
|||
int quick_tap_ms;
|
||||
enum flavor flavor;
|
||||
bool retro_tap;
|
||||
int32_t hold_trigger_key_positions_len;
|
||||
int32_t hold_trigger_key_positions[];
|
||||
};
|
||||
|
||||
// this data is specific for each hold-tap
|
||||
|
@ -70,6 +73,9 @@ struct active_hold_tap {
|
|||
const struct behavior_hold_tap_config *config;
|
||||
struct k_delayed_work work;
|
||||
bool work_is_cancelled;
|
||||
|
||||
// initialized to -1, which is to be interpreted as "no other key has been pressed yet"
|
||||
int32_t position_of_first_other_key_pressed;
|
||||
};
|
||||
|
||||
// The undecided hold tap is the hold tap that needs to be decided before
|
||||
|
@ -206,6 +212,7 @@ static struct active_hold_tap *store_hold_tap(uint32_t position, uint32_t param_
|
|||
active_hold_taps[i].param_hold = param_hold;
|
||||
active_hold_taps[i].param_tap = param_tap;
|
||||
active_hold_taps[i].timestamp = timestamp;
|
||||
active_hold_taps[i].position_of_first_other_key_pressed = -1;
|
||||
return &active_hold_taps[i];
|
||||
}
|
||||
return NULL;
|
||||
|
@ -252,6 +259,26 @@ static void decide_tap_preferred(struct active_hold_tap *hold_tap, enum decision
|
|||
}
|
||||
}
|
||||
|
||||
static void decide_tap_unless_interrupted(struct active_hold_tap *hold_tap,
|
||||
enum decision_moment event) {
|
||||
switch (event) {
|
||||
case HT_KEY_UP:
|
||||
hold_tap->status = STATUS_TAP;
|
||||
return;
|
||||
case HT_OTHER_KEY_DOWN:
|
||||
hold_tap->status = STATUS_HOLD_INTERRUPT;
|
||||
return;
|
||||
case HT_TIMER_EVENT:
|
||||
hold_tap->status = STATUS_TAP;
|
||||
return;
|
||||
case HT_QUICK_TAP:
|
||||
hold_tap->status = STATUS_TAP;
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void decide_hold_preferred(struct active_hold_tap *hold_tap, enum decision_moment event) {
|
||||
switch (event) {
|
||||
case HT_KEY_UP:
|
||||
|
@ -279,6 +306,8 @@ static inline const char *flavor_str(enum flavor flavor) {
|
|||
return "balanced";
|
||||
case FLAVOR_TAP_PREFERRED:
|
||||
return "tap-preferred";
|
||||
case FLAVOR_TAP_UNLESS_INTERRUPTED:
|
||||
return "tap-unless-interrupted";
|
||||
default:
|
||||
return "UNKNOWN FLAVOR";
|
||||
}
|
||||
|
@ -359,6 +388,39 @@ static int release_binding(struct active_hold_tap *hold_tap) {
|
|||
return behavior_keymap_binding_released(&binding, event);
|
||||
}
|
||||
|
||||
static bool is_first_other_key_pressed_trigger_key(struct active_hold_tap *hold_tap) {
|
||||
for (int i = 0; i < hold_tap->config->hold_trigger_key_positions_len; i++) {
|
||||
if (hold_tap->config->hold_trigger_key_positions[i] ==
|
||||
hold_tap->position_of_first_other_key_pressed) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Force a tap decision if the positional conditions for a hold decision are not met.
|
||||
static void decide_positional_hold(struct active_hold_tap *hold_tap) {
|
||||
// Only force a tap decision if the positional hold/tap feature is enabled.
|
||||
if (!(hold_tap->config->hold_trigger_key_positions_len > 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only force a tap decision if another key was pressed after
|
||||
// the hold/tap key.
|
||||
if (hold_tap->position_of_first_other_key_pressed == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only force a tap decision if the first other key to be pressed
|
||||
// (after the hold/tap key) is not one of the trigger keys.
|
||||
if (is_first_other_key_pressed_trigger_key(hold_tap)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Since the positional key conditions have failed, force a TAP decision.
|
||||
hold_tap->status = STATUS_TAP;
|
||||
}
|
||||
|
||||
static void decide_hold_tap(struct active_hold_tap *hold_tap,
|
||||
enum decision_moment decision_moment) {
|
||||
if (hold_tap->status != STATUS_UNDECIDED) {
|
||||
|
@ -370,19 +432,30 @@ static void decide_hold_tap(struct active_hold_tap *hold_tap,
|
|||
return;
|
||||
}
|
||||
|
||||
// If the hold-tap behavior is still undecided, attempt to decide it.
|
||||
switch (hold_tap->config->flavor) {
|
||||
case FLAVOR_HOLD_PREFERRED:
|
||||
decide_hold_preferred(hold_tap, decision_moment);
|
||||
break;
|
||||
case FLAVOR_BALANCED:
|
||||
decide_balanced(hold_tap, decision_moment);
|
||||
break;
|
||||
case FLAVOR_TAP_PREFERRED:
|
||||
decide_tap_preferred(hold_tap, decision_moment);
|
||||
break;
|
||||
case FLAVOR_TAP_UNLESS_INTERRUPTED:
|
||||
decide_tap_unless_interrupted(hold_tap, decision_moment);
|
||||
break;
|
||||
}
|
||||
|
||||
if (hold_tap->status == STATUS_UNDECIDED) {
|
||||
return;
|
||||
}
|
||||
|
||||
decide_positional_hold(hold_tap);
|
||||
|
||||
// Since the hold-tap has been decided, clean up undecided_hold_tap and
|
||||
// execute the decided behavior.
|
||||
LOG_DBG("%d decided %s (%s decision moment %s)", hold_tap->position,
|
||||
status_str(hold_tap->status), flavor_str(hold_tap->config->flavor),
|
||||
decision_moment_str(decision_moment));
|
||||
|
@ -501,6 +574,14 @@ static int position_state_changed_listener(const zmk_event_t *eh) {
|
|||
return ZMK_EV_EVENT_BUBBLE;
|
||||
}
|
||||
|
||||
// Store the position of pressed key for positional hold-tap purposes.
|
||||
if ((ev->state) // i.e. key pressed (not released)
|
||||
&& (undecided_hold_tap->position_of_first_other_key_pressed ==
|
||||
-1) // i.e. no other key has been pressed yet
|
||||
) {
|
||||
undecided_hold_tap->position_of_first_other_key_pressed = ev->position;
|
||||
}
|
||||
|
||||
if (undecided_hold_tap->position == ev->position) {
|
||||
if (ev->state) { // keydown
|
||||
LOG_ERR("hold-tap listener should be called before before most other listeners!");
|
||||
|
@ -604,6 +685,8 @@ static struct behavior_hold_tap_data behavior_hold_tap_data;
|
|||
.quick_tap_ms = DT_INST_PROP(n, quick_tap_ms), \
|
||||
.flavor = DT_ENUM_IDX(DT_DRV_INST(n), flavor), \
|
||||
.retro_tap = DT_INST_PROP(n, retro_tap), \
|
||||
.hold_trigger_key_positions = DT_INST_PROP(n, hold_trigger_key_positions), \
|
||||
.hold_trigger_key_positions_len = DT_INST_PROP_LEN(n, hold_trigger_key_positions), \
|
||||
}; \
|
||||
DEVICE_DT_INST_DEFINE(n, behavior_hold_tap_init, device_pm_control_nop, \
|
||||
&behavior_hold_tap_data, &behavior_hold_tap_config_##n, APPLICATION, \
|
||||
|
|
|
@ -469,22 +469,12 @@ static int position_state_changed_listener(const zmk_event_t *ev) {
|
|||
ZMK_LISTENER(combo, position_state_changed_listener);
|
||||
ZMK_SUBSCRIPTION(combo, zmk_position_state_changed);
|
||||
|
||||
// todo: remove this once #506 is merged and #include <zmk/keymap.h>
|
||||
#define KEY_BINDING_TO_STRUCT(idx, drv_inst) \
|
||||
{ \
|
||||
.behavior_dev = DT_LABEL(DT_PHANDLE_BY_IDX(drv_inst, bindings, idx)), \
|
||||
.param1 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(drv_inst, bindings, idx, param1), (0), \
|
||||
(DT_PHA_BY_IDX(drv_inst, bindings, idx, param1))), \
|
||||
.param2 = COND_CODE_0(DT_PHA_HAS_CELL_AT_IDX(drv_inst, bindings, idx, param2), (0), \
|
||||
(DT_PHA_BY_IDX(drv_inst, bindings, idx, param2))), \
|
||||
}
|
||||
|
||||
#define COMBO_INST(n) \
|
||||
static struct combo_cfg combo_config_##n = { \
|
||||
.timeout_ms = DT_PROP(n, timeout_ms), \
|
||||
.key_positions = DT_PROP(n, key_positions), \
|
||||
.key_position_len = DT_PROP_LEN(n, key_positions), \
|
||||
.behavior = KEY_BINDING_TO_STRUCT(0, n), \
|
||||
.behavior = ZMK_KEYMAP_EXTRACT_BINDING(0, n), \
|
||||
.virtual_key_position = ZMK_KEYMAP_LEN + __COUNTER__, \
|
||||
.slow_release = DT_PROP(n, slow_release), \
|
||||
.layers = DT_PROP(n, layers), \
|
||||
|
|
|
@ -39,7 +39,7 @@ static struct output_status_state get_state(const zmk_event_t *_eh) {
|
|||
}
|
||||
|
||||
static void set_status_symbol(lv_obj_t *label, struct output_status_state state) {
|
||||
char text[6] = {};
|
||||
char text[9] = {};
|
||||
|
||||
switch (state.selected_endpoint) {
|
||||
case ZMK_ENDPOINT_USB:
|
||||
|
|
|
@ -28,6 +28,9 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
#define SAT_MAX 100
|
||||
#define BRT_MAX 100
|
||||
|
||||
BUILD_ASSERT(CONFIG_ZMK_RGB_UNDERGLOW_BRT_MIN <= CONFIG_ZMK_RGB_UNDERGLOW_BRT_MAX,
|
||||
"ERROR: RGB underglow maximum brightness is less than minimum brightness");
|
||||
|
||||
enum rgb_underglow_effect {
|
||||
UNDERGLOW_EFFECT_SOLID,
|
||||
UNDERGLOW_EFFECT_BREATHE,
|
||||
|
@ -54,6 +57,17 @@ static struct rgb_underglow_state state;
|
|||
static const struct device *ext_power;
|
||||
#endif
|
||||
|
||||
static struct zmk_led_hsb hsb_scale_min_max(struct zmk_led_hsb hsb) {
|
||||
hsb.b = CONFIG_ZMK_RGB_UNDERGLOW_BRT_MIN +
|
||||
(CONFIG_ZMK_RGB_UNDERGLOW_BRT_MAX - CONFIG_ZMK_RGB_UNDERGLOW_BRT_MIN) * hsb.b / BRT_MAX;
|
||||
return hsb;
|
||||
}
|
||||
|
||||
static struct zmk_led_hsb hsb_scale_zero_max(struct zmk_led_hsb hsb) {
|
||||
hsb.b = hsb.b * CONFIG_ZMK_RGB_UNDERGLOW_BRT_MAX / BRT_MAX;
|
||||
return hsb;
|
||||
}
|
||||
|
||||
static struct led_rgb hsb_to_rgb(struct zmk_led_hsb hsb) {
|
||||
double r, g, b;
|
||||
|
||||
|
@ -105,7 +119,7 @@ static struct led_rgb hsb_to_rgb(struct zmk_led_hsb hsb) {
|
|||
|
||||
static void zmk_rgb_underglow_effect_solid() {
|
||||
for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
|
||||
pixels[i] = hsb_to_rgb(state.color);
|
||||
pixels[i] = hsb_to_rgb(hsb_scale_min_max(state.color));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,7 +128,7 @@ static void zmk_rgb_underglow_effect_breathe() {
|
|||
struct zmk_led_hsb hsb = state.color;
|
||||
hsb.b = abs(state.animation_step - 1200) / 12;
|
||||
|
||||
pixels[i] = hsb_to_rgb(hsb);
|
||||
pixels[i] = hsb_to_rgb(hsb_scale_zero_max(hsb));
|
||||
}
|
||||
|
||||
state.animation_step += state.animation_speed * 10;
|
||||
|
@ -129,7 +143,7 @@ static void zmk_rgb_underglow_effect_spectrum() {
|
|||
struct zmk_led_hsb hsb = state.color;
|
||||
hsb.h = state.animation_step;
|
||||
|
||||
pixels[i] = hsb_to_rgb(hsb);
|
||||
pixels[i] = hsb_to_rgb(hsb_scale_min_max(hsb));
|
||||
}
|
||||
|
||||
state.animation_step += state.animation_speed;
|
||||
|
@ -141,7 +155,7 @@ static void zmk_rgb_underglow_effect_swirl() {
|
|||
struct zmk_led_hsb hsb = state.color;
|
||||
hsb.h = (HUE_MAX / STRIP_NUM_PIXELS * i + state.animation_step) % HUE_MAX;
|
||||
|
||||
pixels[i] = hsb_to_rgb(hsb);
|
||||
pixels[i] = hsb_to_rgb(hsb_scale_min_max(hsb));
|
||||
}
|
||||
|
||||
state.animation_step += state.animation_speed * 2;
|
||||
|
@ -371,12 +385,7 @@ struct zmk_led_hsb zmk_rgb_underglow_calc_brt(int direction) {
|
|||
struct zmk_led_hsb color = state.color;
|
||||
|
||||
int b = color.b + (direction * CONFIG_ZMK_RGB_UNDERGLOW_BRT_STEP);
|
||||
if (b < 0) {
|
||||
b = 0;
|
||||
} else if (b > BRT_MAX) {
|
||||
b = BRT_MAX;
|
||||
}
|
||||
color.b = b;
|
||||
color.b = CLAMP(b, 0, BRT_MAX);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
|
|
@ -29,9 +29,10 @@ static int start_scan(void);
|
|||
|
||||
static struct bt_conn *default_conn;
|
||||
|
||||
static struct bt_uuid_128 uuid = BT_UUID_INIT_128(ZMK_SPLIT_BT_SERVICE_UUID);
|
||||
static const struct bt_uuid_128 split_service_uuid = BT_UUID_INIT_128(ZMK_SPLIT_BT_SERVICE_UUID);
|
||||
static struct bt_gatt_discover_params discover_params;
|
||||
static struct bt_gatt_subscribe_params subscribe_params;
|
||||
static struct bt_gatt_discover_params sub_discover_params;
|
||||
|
||||
K_MSGQ_DEFINE(peripheral_event_msgq, sizeof(struct zmk_position_state_changed),
|
||||
CONFIG_ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE, 4);
|
||||
|
@ -83,15 +84,12 @@ static uint8_t split_central_notify_func(struct bt_conn *conn,
|
|||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
static int split_central_subscribe(struct bt_conn *conn) {
|
||||
static void split_central_subscribe(struct bt_conn *conn) {
|
||||
int err = bt_gatt_subscribe(conn, &subscribe_params);
|
||||
switch (err) {
|
||||
case -EALREADY:
|
||||
LOG_DBG("[ALREADY SUBSCRIBED]");
|
||||
break;
|
||||
// break;
|
||||
// bt_gatt_unsubscribe(conn, &subscribe_params);
|
||||
// return split_central_subscribe(conn);
|
||||
case 0:
|
||||
LOG_DBG("[SUBSCRIBED]");
|
||||
break;
|
||||
|
@ -99,14 +97,44 @@ static int split_central_subscribe(struct bt_conn *conn) {
|
|||
LOG_ERR("Subscribe failed (err %d)", err);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t split_central_discovery_func(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
struct bt_gatt_discover_params *params) {
|
||||
int err;
|
||||
static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn,
|
||||
const struct bt_gatt_attr *attr,
|
||||
struct bt_gatt_discover_params *params) {
|
||||
if (!attr) {
|
||||
LOG_DBG("Discover complete");
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
if (!attr->user_data) {
|
||||
LOG_ERR("Required user data not passed to discovery");
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
LOG_DBG("[ATTRIBUTE] handle %u", attr->handle);
|
||||
|
||||
if (!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid,
|
||||
BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID))) {
|
||||
LOG_DBG("Found position state characteristic");
|
||||
discover_params.uuid = NULL;
|
||||
discover_params.start_handle = attr->handle + 2;
|
||||
discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
|
||||
|
||||
subscribe_params.disc_params = &sub_discover_params;
|
||||
subscribe_params.end_handle = discover_params.end_handle;
|
||||
subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);
|
||||
subscribe_params.notify = split_central_notify_func;
|
||||
subscribe_params.value = BT_GATT_CCC_NOTIFY;
|
||||
split_central_subscribe(conn);
|
||||
}
|
||||
|
||||
return subscribe_params.value_handle ? BT_GATT_ITER_STOP : BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
static uint8_t split_central_service_discovery_func(struct bt_conn *conn,
|
||||
const struct bt_gatt_attr *attr,
|
||||
struct bt_gatt_discover_params *params) {
|
||||
if (!attr) {
|
||||
LOG_DBG("Discover complete");
|
||||
(void)memset(params, 0, sizeof(*params));
|
||||
|
@ -115,38 +143,21 @@ static uint8_t split_central_discovery_func(struct bt_conn *conn, const struct b
|
|||
|
||||
LOG_DBG("[ATTRIBUTE] handle %u", attr->handle);
|
||||
|
||||
if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID))) {
|
||||
memcpy(&uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID), sizeof(uuid));
|
||||
discover_params.uuid = &uuid.uuid;
|
||||
discover_params.start_handle = attr->handle + 1;
|
||||
discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
|
||||
|
||||
err = bt_gatt_discover(conn, &discover_params);
|
||||
if (err) {
|
||||
LOG_ERR("Discover failed (err %d)", err);
|
||||
}
|
||||
} else if (!bt_uuid_cmp(discover_params.uuid,
|
||||
BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID))) {
|
||||
memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid));
|
||||
discover_params.uuid = &uuid.uuid;
|
||||
discover_params.start_handle = attr->handle + 2;
|
||||
discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
|
||||
subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);
|
||||
|
||||
err = bt_gatt_discover(conn, &discover_params);
|
||||
if (err) {
|
||||
LOG_ERR("Discover failed (err %d)", err);
|
||||
}
|
||||
} else {
|
||||
subscribe_params.notify = split_central_notify_func;
|
||||
subscribe_params.value = BT_GATT_CCC_NOTIFY;
|
||||
subscribe_params.ccc_handle = attr->handle;
|
||||
|
||||
split_central_subscribe(conn);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
if (bt_uuid_cmp(discover_params.uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID))) {
|
||||
LOG_DBG("Found other service");
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
LOG_DBG("Found split service");
|
||||
discover_params.uuid = NULL;
|
||||
discover_params.func = split_central_chrc_discovery_func;
|
||||
discover_params.start_handle = attr->handle + 1;
|
||||
discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
|
||||
|
||||
int err = bt_gatt_discover(conn, &discover_params);
|
||||
if (err) {
|
||||
LOG_ERR("Failed to start discovering split service characteristics (err %d)", err);
|
||||
}
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
|
@ -161,9 +172,9 @@ static void split_central_process_connection(struct bt_conn *conn) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (conn == default_conn && !subscribe_params.value) {
|
||||
discover_params.uuid = &uuid.uuid;
|
||||
discover_params.func = split_central_discovery_func;
|
||||
if (conn == default_conn && !subscribe_params.value_handle) {
|
||||
discover_params.uuid = &split_service_uuid.uuid;
|
||||
discover_params.func = split_central_service_discovery_func;
|
||||
discover_params.start_handle = 0x0001;
|
||||
discover_params.end_handle = 0xffff;
|
||||
discover_params.type = BT_GATT_DISCOVER_PRIMARY;
|
||||
|
@ -318,6 +329,9 @@ static void split_central_disconnected(struct bt_conn *conn, uint8_t reason) {
|
|||
bt_conn_unref(default_conn);
|
||||
default_conn = NULL;
|
||||
|
||||
// Clean up previously discovered handles;
|
||||
subscribe_params.value_handle = 0;
|
||||
|
||||
start_scan();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,5 @@
|
|||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
ht_decide: 0 decided hold-timer (balanced decision moment timer)
|
||||
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,11 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,500)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,7 @@
|
|||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
ht_decide: 0 decided tap (balanced decision moment timer)
|
||||
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
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
|
||||
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,14 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,200)
|
||||
ZMK_MOCK_PRESS(1,1,200) // non trigger key
|
||||
/* timer fires */
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,7 @@
|
|||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
ht_decide: 0 decided hold-timer (balanced decision moment timer)
|
||||
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,14 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,200)
|
||||
ZMK_MOCK_PRESS(1,0,200) // trigger key
|
||||
/* timer fires */
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,29 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
|
||||
/ {
|
||||
behaviors {
|
||||
ht_bal: behavior_hold_tap_balanced {
|
||||
compatible = "zmk,behavior-hold-tap";
|
||||
label = "HOLD_TAP_BALANCED";
|
||||
#binding-cells = <2>;
|
||||
flavor = "balanced";
|
||||
tapping-term-ms = <300>;
|
||||
quick-tap-ms = <200>;
|
||||
bindings = <&kp>, <&kp>;
|
||||
hold-trigger-key-positions = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label ="Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&ht_bal LEFT_SHIFT F &ht_bal LEFT_CONTROL J
|
||||
&kp D &kp E>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,9 @@
|
|||
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
ht_decide: 0 decided tap (balanced decision moment timer)
|
||||
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
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
|
||||
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,16 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,0,10) // trigger key
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_PRESS(1,1,400) // not trigger key
|
||||
/* timer fires */
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,5 @@
|
|||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
ht_decide: 0 decided hold-timer (hold-preferred decision moment timer)
|
||||
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,11 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,500)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,7 @@
|
|||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
ht_decide: 0 decided tap (hold-preferred decision moment other-key-down)
|
||||
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
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
|
||||
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,14 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,200)
|
||||
ZMK_MOCK_PRESS(1,1,200) // non trigger key
|
||||
/* timer fires */
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,7 @@
|
|||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
ht_decide: 0 decided hold-interrupt (hold-preferred decision moment other-key-down)
|
||||
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,14 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,200)
|
||||
ZMK_MOCK_PRESS(1,0,200) // trigger key
|
||||
/* timer fires */
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,29 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
|
||||
/ {
|
||||
behaviors {
|
||||
ht_hold: behavior_hold_hold_tap {
|
||||
compatible = "zmk,behavior-hold-tap";
|
||||
label = "hold_hold_tap";
|
||||
#binding-cells = <2>;
|
||||
flavor = "hold-preferred";
|
||||
tapping-term-ms = <300>;
|
||||
quick-tap-ms = <200>;
|
||||
bindings = <&kp>, <&kp>;
|
||||
hold-trigger-key-positions = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label ="Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&ht_hold LEFT_SHIFT F &ht_hold LEFT_CONTROL J
|
||||
&kp D &kp E>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,9 @@
|
|||
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
ht_decide: 0 decided tap (hold-preferred decision moment other-key-down)
|
||||
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
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
|
||||
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,16 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,0,10) // trigger key
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_PRESS(1,1,400) // not trigger key
|
||||
/* timer fires */
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,5 @@
|
|||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
ht_decide: 0 decided hold-timer (tap-preferred decision moment timer)
|
||||
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,11 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,500)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,7 @@
|
|||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
ht_decide: 0 decided tap (tap-preferred decision moment timer)
|
||||
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
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
|
||||
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,14 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,200)
|
||||
ZMK_MOCK_PRESS(1,1,200) // non trigger key
|
||||
/* timer fires */
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,7 @@
|
|||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
ht_decide: 0 decided hold-timer (tap-preferred decision moment timer)
|
||||
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,14 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,200)
|
||||
ZMK_MOCK_PRESS(1,0,200) // trigger key
|
||||
/* timer fires */
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,29 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
|
||||
/ {
|
||||
behaviors {
|
||||
tp: behavior_tap_preferred {
|
||||
compatible = "zmk,behavior-hold-tap";
|
||||
label = "MOD_TAP";
|
||||
#binding-cells = <2>;
|
||||
flavor = "tap-preferred";
|
||||
tapping-term-ms = <300>;
|
||||
quick-tap-ms = <200>;
|
||||
bindings = <&kp>, <&kp>;
|
||||
hold-trigger-key-positions = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label ="Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&tp LEFT_SHIFT F &tp LEFT_CONTROL J
|
||||
&kp D &kp E>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,9 @@
|
|||
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
ht_decide: 0 decided tap (tap-preferred decision moment timer)
|
||||
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
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
|
||||
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,16 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,0,10) // trigger key
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_PRESS(1,1,400) // not trigger key
|
||||
/* timer fires */
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,5 @@
|
|||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
ht_decide: 0 decided tap (tap-unless-interrupted decision moment key-up)
|
||||
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,11 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,5 @@
|
|||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
ht_decide: 0 decided tap (tap-unless-interrupted decision moment timer)
|
||||
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,11 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,500)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,7 @@
|
|||
kp_pressed: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
ht_decide: 0 decided tap (tap-unless-interrupted decision moment key-up)
|
||||
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,13 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,1,10) /*ctrl*/
|
||||
ZMK_MOCK_PRESS(0,0,100) /*mt f-shift */
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,7 @@
|
|||
kp_pressed: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
ht_decide: 0 decided tap (tap-unless-interrupted decision moment timer)
|
||||
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0xe4 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,14 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,1,10) /*ctrl*/
|
||||
ZMK_MOCK_PRESS(0,0,50) /*mt f-shift */
|
||||
ZMK_MOCK_RELEASE(1,1,300)
|
||||
/*timer*/
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,7 @@
|
|||
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_decide: 0 decided tap (tap-unless-interrupted decision moment key-up)
|
||||
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,13 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,0,10) /*d*/
|
||||
ZMK_MOCK_PRESS(0,0,100) /*mt f-shift */
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,7 @@
|
|||
kp_pressed: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
kp_released: usage_page 0x07 keycode 0x07 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_decide: 0 decided tap (tap-unless-interrupted decision moment timer)
|
||||
kp_pressed: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0x09 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
|
@ -0,0 +1,13 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(1,0,10) /* d */
|
||||
ZMK_MOCK_PRESS(0,0,100) /* mt f-shift */
|
||||
ZMK_MOCK_RELEASE(1,0,400)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode/kp/p
|
||||
s/.*mo_keymap_binding/mo/p
|
||||
s/.*on_hold_tap_binding/ht_binding/p
|
||||
s/.*decide_hold_tap/ht_decide/p
|
|
@ -0,0 +1,10 @@
|
|||
ht_binding_pressed: 0 new undecided hold_tap
|
||||
ht_decide: 0 decided hold-interrupt (tap-unless-interrupted decision moment other-key-down)
|
||||
kp_pressed: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_pressed: 1 new undecided hold_tap
|
||||
ht_decide: 1 decided tap (tap-unless-interrupted decision moment key-up)
|
||||
kp_pressed: usage_page 0x07 keycode 0x0d implicit_mods 0x00 explicit_mods 0x00
|
||||
kp_released: usage_page 0x07 keycode 0x0d implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 1 cleaning up hold-tap
|
||||
kp_released: usage_page 0x07 keycode 0xe1 implicit_mods 0x00 explicit_mods 0x00
|
||||
ht_binding_released: 0 cleaning up hold-tap
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue