Merge remote-tracking branch 'upstream/main' into split_battery_service
This commit is contained in:
commit
e00d000d63
97 changed files with 17879 additions and 4842 deletions
|
@ -1,18 +1,16 @@
|
|||
cmake_minimum_required(VERSION 3.13.1)
|
||||
|
||||
set(CONFIG_APPLICATION_DEFINED_SYSCALL true)
|
||||
list(APPEND BOARD_ROOT ${CMAKE_SOURCE_DIR})
|
||||
list(APPEND DTS_ROOT ${CMAKE_SOURCE_DIR})
|
||||
|
||||
# Add our custom Zephyr module for drivers w/ syscalls, etc.
|
||||
list(APPEND DTS_ROOT ${CMAKE_SOURCE_DIR}/drivers/zephyr)
|
||||
|
||||
set(ZephyrBuildConfiguration_ROOT ${CMAKE_SOURCE_DIR}/cmake)
|
||||
|
||||
list(APPEND ZEPHYR_EXTRA_MODULES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers
|
||||
)
|
||||
|
||||
include(cmake/zmk_config.cmake)
|
||||
|
||||
# Find Zephyr. This also loads Zephyr's build system.
|
||||
find_package(Zephyr REQUIRED HINTS ../zephyr)
|
||||
project(zmk)
|
||||
|
@ -37,9 +35,10 @@ target_sources_ifdef(CONFIG_ZMK_WPM app PRIVATE src/events/wpm_state_changed.c)
|
|||
target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/events/usb_conn_state_changed.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_reset.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/behaviors/behavior_ext_power.c)
|
||||
if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
||||
target_sources(app PRIVATE src/hid.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_key_press.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_KEY_TOGGLE app PRIVATE src/behaviors/behavior_key_toggle.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_hold_tap.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_sticky_key.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_caps_word.c)
|
||||
|
@ -84,17 +83,9 @@ target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/behaviors/behavior_bac
|
|||
|
||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/battery_state_changed.c)
|
||||
|
||||
if (CONFIG_ZMK_SPLIT_BLE)
|
||||
if (NOT CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
target_sources(app PRIVATE src/split_listener.c)
|
||||
target_sources(app PRIVATE src/split/bluetooth/service.c)
|
||||
target_sources(app PRIVATE src/split/bluetooth/peripheral.c)
|
||||
target_sources(app PRIVATE src/events/split_peripheral_status_changed.c)
|
||||
endif()
|
||||
if (CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
target_sources(app PRIVATE src/split/bluetooth/central.c)
|
||||
endif()
|
||||
endif()
|
||||
target_sources_ifdef(CONFIG_ZMK_SPLIT app PRIVATE src/events/split_peripheral_status_changed.c)
|
||||
add_subdirectory(src/split)
|
||||
|
||||
target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/usb.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_USB app PRIVATE src/usb_hid.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/rgb_underglow.c)
|
||||
|
|
116
app/Kconfig
116
app/Kconfig
|
@ -102,6 +102,7 @@ menuconfig ZMK_BLE
|
|||
select BT_SMP_APP_PAIRING_ACCEPT
|
||||
select BT_PERIPHERAL
|
||||
select BT_DIS
|
||||
select BT_BAS
|
||||
select BT_SETTINGS
|
||||
select SETTINGS
|
||||
|
||||
|
@ -165,114 +166,7 @@ endmenu
|
|||
# HID
|
||||
endmenu
|
||||
|
||||
menu "Split Support"
|
||||
|
||||
config ZMK_SPLIT
|
||||
bool "Split keyboard support"
|
||||
|
||||
if ZMK_SPLIT
|
||||
|
||||
menuconfig ZMK_SPLIT_BLE
|
||||
bool "Split keyboard support via BLE transport"
|
||||
depends on ZMK_BLE
|
||||
default y
|
||||
select BT_USER_PHY_UPDATE
|
||||
select BT_AUTO_PHY_UPDATE
|
||||
|
||||
if ZMK_SPLIT_BLE
|
||||
|
||||
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
|
||||
|
||||
config ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE
|
||||
int "Max number of key position state events to queue when received from peripherals"
|
||||
default 5
|
||||
|
||||
config ZMK_BLE_SPLIT_CENTRAL_SPLIT_RUN_STACK_SIZE
|
||||
int "BLE split central write thread stack size"
|
||||
default 512
|
||||
|
||||
config ZMK_BLE_SPLIT_CENTRAL_SPLIT_RUN_QUEUE_SIZE
|
||||
int "Max number of behavior run events to queue to send to the peripheral(s)"
|
||||
default 5
|
||||
|
||||
endif
|
||||
|
||||
if !ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
|
||||
config ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE
|
||||
int "BLE split peripheral notify thread stack size"
|
||||
default 650
|
||||
|
||||
config ZMK_SPLIT_BLE_PERIPHERAL_PRIORITY
|
||||
int "BLE split peripheral notify thread priority"
|
||||
default 5
|
||||
|
||||
config ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE
|
||||
int "Max number of key position state events to queue to send to the central"
|
||||
default 10
|
||||
|
||||
config ZMK_USB
|
||||
default n
|
||||
|
||||
config BT_MAX_PAIRED
|
||||
default 1
|
||||
|
||||
config BT_MAX_CONN
|
||||
default 1
|
||||
|
||||
config BT_PERIPHERAL_PREF_MAX_INT
|
||||
default 6
|
||||
|
||||
config BT_BAS
|
||||
default y
|
||||
|
||||
#!ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
endif
|
||||
|
||||
#ZMK_SPLIT_BLE
|
||||
endif
|
||||
|
||||
#ZMK_SPLIT
|
||||
endif
|
||||
|
||||
if ZMK_BLE
|
||||
|
||||
if ZMK_SPLIT_BLE && ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
|
||||
config BT_MAX_CONN
|
||||
default 6
|
||||
|
||||
config BT_MAX_PAIRED
|
||||
default 6
|
||||
|
||||
#ZMK_SPLIT_BLE && ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
endif
|
||||
|
||||
if !ZMK_SPLIT_BLE
|
||||
|
||||
config BT_MAX_CONN
|
||||
default 5
|
||||
|
||||
config BT_MAX_PAIRED
|
||||
default 5
|
||||
|
||||
config BT_BAS
|
||||
default y
|
||||
|
||||
#!ZMK_SPLIT_BLE
|
||||
endif
|
||||
|
||||
#ZMK_BLE
|
||||
endif
|
||||
|
||||
#Split Support
|
||||
endmenu
|
||||
rsource "src/split/Kconfig"
|
||||
|
||||
#Basic Keyboard Setup
|
||||
endmenu
|
||||
|
@ -436,6 +330,12 @@ config ZMK_BEHAVIORS_QUEUE_SIZE
|
|||
int "Maximum number of behaviors to allow queueing from a macro or other complex behavior"
|
||||
default 64
|
||||
|
||||
DT_COMPAT_ZMK_BEHAVIOR_KEY_TOGGLE := zmk,behavior-key-toggle
|
||||
|
||||
config ZMK_BEHAVIOR_KEY_TOGGLE
|
||||
bool
|
||||
default $(dt_compat_enabled,$(DT_COMPAT_ZMK_BEHAVIOR_KEY_TOGGLE))
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Advanced"
|
||||
|
|
|
@ -6,7 +6,7 @@ if SHIELD_A_DUX_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "A. Dux"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -6,7 +6,7 @@ if SHIELD_BFO9000_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "BFO-9000"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -6,7 +6,7 @@ if SHIELD_CLOG_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Clog"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -3,7 +3,7 @@ if SHIELD_CORNE_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Corne"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
@ -12,7 +12,7 @@ if SHIELD_CORNE_LEFT || SHIELD_CORNE_RIGHT
|
|||
|
||||
config ZMK_SPLIT
|
||||
default y
|
||||
|
||||
|
||||
if ZMK_DISPLAY
|
||||
|
||||
config I2C
|
||||
|
|
|
@ -6,7 +6,7 @@ if SHIELD_CRADIO_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Cradio"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -6,7 +6,7 @@ if SHIELD_ELEPHANT42_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Elephant42"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -6,7 +6,7 @@ if SHIELD_ERGODASH_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Ergodash"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -7,7 +7,7 @@ if SHIELD_FOURIER_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Fourier"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -6,7 +6,7 @@ if SHIELD_HELIX_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Helix"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -6,7 +6,7 @@ if SHIELD_IRIS_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Iris"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -4,7 +4,7 @@ if SHIELD_JIAN_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Jian"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -6,7 +6,7 @@ if SHIELD_JIRAN_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Jiran"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -4,7 +4,7 @@ if SHIELD_JORNE_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Jorne"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -4,7 +4,7 @@ if SHIELD_KYRIA_LEFT || SHIELD_KYRIA_REV2_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Kyria"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -6,7 +6,7 @@ if SHIELD_LEELOO_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Leeloo"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -32,8 +32,8 @@ Build command for the default keymap of Leeloo:
|
|||
|
||||
Build command for your custom keymap of Leeloo:
|
||||
|
||||
west build -d build/right -p -b nice_nano_v2 -- -DSHIELD=leeloo_right -DZMK_CONFIG="C:\dev\zmk\[yourNmae]\leeloo\config"
|
||||
west build -d build/left -p -b nice_nano_v2 -- -DSHIELD=leeloo_left -DZMK_CONFIG="C:\dev\zmk\[yourName]\leeloo\config"
|
||||
west build -d build/right -p -b nice_nano_v2 -- -DSHIELD=leeloo_right -DZMK_CONFIG="C:/dev/zmk/[yourNmae]/leeloo/config"
|
||||
west build -d build/left -p -b nice_nano_v2 -- -DSHIELD=leeloo_left -DZMK_CONFIG="C:/dev/zmk/[yourName]/leeloo/config"
|
||||
|
||||
# Support
|
||||
If you have any questions with regards to Leeloo, please [Contact Us](https://clicketysplit.ca/pages/contact-us).
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
/ {
|
||||
chosen {
|
||||
zephyr,display = &oled;
|
||||
zmk,kscan = &kscan0;
|
||||
zmk,matrix_transform = &default_transform;
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@ if SHIELD_LILY58_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Lily58"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -6,7 +6,7 @@ if SHIELD_LOTUS58_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Lotus58"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -6,7 +6,7 @@ if SHIELD_MICRODOX_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Microdox"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -7,7 +7,7 @@ if SHIELD_QUEFRENCY_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Quefrency"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -5,7 +5,7 @@ if SHIELD_REDOX_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Redox"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -6,7 +6,7 @@ if SHIELD_SOFLE_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Sofle"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -8,7 +8,7 @@ if SHIELD_SPLITREUS62_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Splitreus62"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -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
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -6,7 +6,7 @@ if SHIELD_ZODIARK_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "Zodiark"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
list(APPEND BOARD_ROOT ${APPLICATION_SOURCE_DIR})
|
||||
list(APPEND DTS_ROOT ${APPLICATION_SOURCE_DIR})
|
||||
|
||||
get_property(cached_user_config_value CACHE ZMK_CONFIG PROPERTY VALUE)
|
||||
|
||||
set(user_config_cli_argument ${cached_user_config_value}) # Either new or old
|
||||
|
@ -57,9 +60,29 @@ if (ZMK_CONFIG)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
if(DEFINED SHIELD)
|
||||
string(REPLACE " " ";" SHIELD_AS_LIST "${SHIELD}")
|
||||
endif()
|
||||
|
||||
foreach(root ${BOARD_ROOT})
|
||||
set(shield_dir ${root}/boards/shields)
|
||||
# Match the Kconfig.shield files in the shield directories to make sure we are
|
||||
# finding shields, e.g. x_nucleo_iks01a1/Kconfig.shield
|
||||
file(GLOB_RECURSE shields_refs_list ${shield_dir}/*/Kconfig.shield)
|
||||
unset(SHIELD_LIST)
|
||||
foreach(shields_refs ${shields_refs_list})
|
||||
get_filename_component(shield_path ${shields_refs} DIRECTORY)
|
||||
file(GLOB shield_overlays RELATIVE ${shield_path} ${shield_path}/*.overlay)
|
||||
foreach(overlay ${shield_overlays})
|
||||
get_filename_component(shield ${overlay} NAME_WE)
|
||||
list(APPEND SHIELD_LIST ${shield})
|
||||
set(SHIELD_DIR_${shield} ${shield_path})
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
if (EXISTS "${root}/boards/${BOARD}.overlay")
|
||||
list(APPEND ZMK_DTC_FILES "${root}/boards/${BOARD}.overlay")
|
||||
list(APPEND shield_dts_files "${root}/boards/${BOARD}.overlay")
|
||||
endif()
|
||||
if (NOT DEFINED BOARD_DIR_NAME)
|
||||
find_path(BOARD_DIR
|
||||
|
@ -74,34 +97,58 @@ foreach(root ${BOARD_ROOT})
|
|||
endif()
|
||||
|
||||
if(DEFINED SHIELD)
|
||||
find_path(shields_refs_list
|
||||
NAMES ${SHIELD}.overlay
|
||||
PATHS ${root}/boards/shields/*
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
foreach(shield_path ${shields_refs_list})
|
||||
get_filename_component(SHIELD_DIR ${shield_path} NAME)
|
||||
list(APPEND KEYMAP_DIRS ${shield_path})
|
||||
foreach(s ${SHIELD_AS_LIST})
|
||||
if(NOT ${s} IN_LIST SHIELD_LIST)
|
||||
message(WARNING "Didn't find ${s}")
|
||||
continue()
|
||||
endif()
|
||||
message(STATUS "Adding ${SHIELD_DIR_${s}}")
|
||||
list(APPEND KEYMAP_DIRS ${SHIELD_DIR_${s}})
|
||||
get_filename_component(shield_dir_name ${SHIELD_DIR_${s}} NAME)
|
||||
list(APPEND SHIELD_DIR ${shield_dir_name})
|
||||
endforeach()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Give a shield like `kyria_rev2_left` we want to use `kyria_rev2` and `kyria` as candidate names for
|
||||
# overlay/conf/keymap files.
|
||||
if(DEFINED SHIELD)
|
||||
foreach(s ${SHIELD_AS_LIST})
|
||||
if (DEFINED $SHIELD_DIR_${s})
|
||||
get_filename_component(shield_dir_name ${SHIELD_DIR_${s}} NAME)
|
||||
endif()
|
||||
string(REPLACE "_" ";" S_PIECES ${s})
|
||||
list(LENGTH S_PIECES S_PIECES_LEN)
|
||||
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}")
|
||||
break()
|
||||
endif()
|
||||
list(APPEND shield_candidate_names ${s_substr})
|
||||
endwhile()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if (ZMK_CONFIG)
|
||||
if (EXISTS ${ZMK_CONFIG})
|
||||
message(STATUS "ZMK Config directory: ${ZMK_CONFIG}")
|
||||
list(APPEND DTS_ROOT ${ZMK_CONFIG})
|
||||
list(PREPEND KEYMAP_DIRS "${ZMK_CONFIG}")
|
||||
|
||||
if (SHIELD)
|
||||
message(STATUS "Board: ${BOARD}, ${BOARD_DIR}, ${SHIELD}, ${SHIELD_DIR}")
|
||||
list(APPEND overlay_candidates "${ZMK_CONFIG}/${SHIELD_DIR}.overlay")
|
||||
list(APPEND overlay_candidates "${ZMK_CONFIG}/${SHIELD_DIR}_${BOARD}.overlay")
|
||||
list(APPEND overlay_candidates "${ZMK_CONFIG}/${SHIELD}_${BOARD}.overlay")
|
||||
list(APPEND overlay_candidates "${ZMK_CONFIG}/${SHIELD}.overlay")
|
||||
list(APPEND config_candidates "${ZMK_CONFIG}/${SHIELD_DIR}.conf")
|
||||
list(APPEND config_candidates "${ZMK_CONFIG}/${SHIELD_DIR}_${BOARD}.conf")
|
||||
list(APPEND config_candidates "${ZMK_CONFIG}/${SHIELD}_${BOARD}.conf")
|
||||
list(APPEND config_candidates "${ZMK_CONFIG}/${SHIELD}.conf")
|
||||
if (DEFINED SHIELD)
|
||||
foreach (s ${shield_candidate_names} ${SHIELD_AS_LIST})
|
||||
if (DEFINED ${SHIELD_DIR_${s}})
|
||||
get_filename_component(shield_dir_name ${SHIELD_DIR_${s}} NAME)
|
||||
endif()
|
||||
list(APPEND overlay_candidates "${ZMK_CONFIG}/${s}_${BOARD}.overlay")
|
||||
list(APPEND overlay_candidates "${ZMK_CONFIG}/${s}.overlay")
|
||||
if (NOT "${shield_dir_name}" STREQUAL "${s}")
|
||||
list(APPEND config_candidates "${ZMK_CONFIG}/${shield_dir_name}_${BOARD}.conf")
|
||||
list(APPEND config_candidates "${ZMK_CONFIG}/${shield_dir_name}.conf")
|
||||
endif()
|
||||
list(APPEND config_candidates "${ZMK_CONFIG}/${s}_${BOARD}.conf")
|
||||
list(APPEND config_candidates "${ZMK_CONFIG}/${s}.conf")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# TODO: Board revisions?
|
||||
|
@ -115,7 +162,7 @@ if (ZMK_CONFIG)
|
|||
foreach(overlay ${overlay_candidates})
|
||||
if (EXISTS "${overlay}")
|
||||
message(STATUS "ZMK Config devicetree overlay: ${overlay}")
|
||||
list(APPEND ZMK_DTC_FILES "${overlay}")
|
||||
list(APPEND shield_dts_files "${overlay}")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
@ -123,8 +170,7 @@ if (ZMK_CONFIG)
|
|||
foreach(conf ${config_candidates})
|
||||
if (EXISTS "${conf}")
|
||||
message(STATUS "ZMK Config Kconfig: ${conf}")
|
||||
set(CONF_FILE "${conf}")
|
||||
break()
|
||||
list(APPEND shield_conf_files "${conf}")
|
||||
endif()
|
||||
endforeach()
|
||||
else()
|
||||
|
@ -135,22 +181,20 @@ endif()
|
|||
|
||||
if(NOT KEYMAP_FILE)
|
||||
foreach(keymap_dir ${KEYMAP_DIRS})
|
||||
foreach(keymap_prefix ${SHIELD} ${SHIELD_DIR} ${BOARD} ${BOARD_DIR_NAME})
|
||||
foreach(keymap_prefix ${shield_candidate_names} ${SHIELD_AS_LIST} ${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}")
|
||||
set(DTC_OVERLAY_FILE ${KEYMAP_FILE})
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
else()
|
||||
message(STATUS "Using keymap file: ${KEYMAP_FILE}")
|
||||
set(DTC_OVERLAY_FILE ${KEYMAP_FILE})
|
||||
endif()
|
||||
|
||||
if (NOT KEYMAP_FILE)
|
||||
message(FATAL_ERROR "Failed to locate keymap file!")
|
||||
endif()
|
||||
|
||||
list(APPEND ZMK_DTC_FILES ${KEYMAP_FILE})
|
||||
|
||||
if (ZMK_DTC_FILES)
|
||||
string(REPLACE ";" " " DTC_OVERLAY_FILE "${ZMK_DTC_FILES}")
|
||||
message(WARNING "Failed to locate keymap file!")
|
||||
endif()
|
|
@ -11,6 +11,8 @@ shield:
|
|||
include:
|
||||
- board: bdn9_rev2
|
||||
- board: nice60
|
||||
- board: seeeduino_xiao_ble
|
||||
shield: hummingbird
|
||||
- board: nrf52840_m2
|
||||
shield: m60
|
||||
- board: planck_rev6
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Copyright (c) 2020 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
add_subdirectory(gpio)
|
||||
add_subdirectory_ifdef(CONFIG_ZMK_DRIVERS_GPIO gpio)
|
||||
add_subdirectory(kscan)
|
||||
add_subdirectory(sensor)
|
||||
add_subdirectory(display)
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
zephyr_library_named(zmk__drivers__gpio)
|
||||
zephyr_library_include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_595 gpio_595.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_MCP23017 gpio_mcp23017.c)
|
||||
zephyr_library_sources_ifndef(CONFIG_GPIO_MCP23017 ${ZEPHYR_BASE}/misc/empty_file.c)
|
||||
|
|
|
@ -1 +1,5 @@
|
|||
menuconfig ZMK_DRIVERS_GPIO
|
||||
bool "GPIO"
|
||||
|
||||
rsource "Kconfig.mcp23017"
|
||||
rsource "Kconfig.595"
|
25
app/drivers/gpio/Kconfig.595
Normal file
25
app/drivers/gpio/Kconfig.595
Normal file
|
@ -0,0 +1,25 @@
|
|||
# 595 GPIO configuration options
|
||||
|
||||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
DT_COMPAT_ZMK_GPIO_595 := zmk,gpio-595
|
||||
|
||||
menuconfig GPIO_595
|
||||
bool "595 Shift Register SPI driver"
|
||||
default $(dt_compat_enabled,$(DT_COMPAT_ZMK_GPIO_595))
|
||||
depends on SPI
|
||||
select HAS_DTS_GPIO
|
||||
select ZMK_DRIVERS_GPIO
|
||||
help
|
||||
Enable driver for 595 shift register chip using SPI.
|
||||
|
||||
if GPIO_595
|
||||
|
||||
config GPIO_595_INIT_PRIORITY
|
||||
int "Init priority"
|
||||
default 75
|
||||
help
|
||||
Device driver initialization priority.
|
||||
|
||||
endif #GPIO_595
|
|
@ -7,6 +7,7 @@ menuconfig GPIO_MCP23017
|
|||
bool "MCP23017 I2C-based GPIO chip"
|
||||
depends on I2C
|
||||
select HAS_DTS_GPIO
|
||||
select ZMK_DRIVERS_GPIO
|
||||
help
|
||||
Enable driver for MCP23017 I2C-based GPIO chip.
|
||||
|
||||
|
|
215
app/drivers/gpio/gpio_595.c
Normal file
215
app/drivers/gpio/gpio_595.c
Normal file
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT zmk_gpio_595
|
||||
|
||||
/**
|
||||
* @file Driver for 595 SPI-based GPIO driver.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <kernel.h>
|
||||
#include <device.h>
|
||||
#include <init.h>
|
||||
#include <sys/byteorder.h>
|
||||
#include <drivers/gpio.h>
|
||||
#include <drivers/spi.h>
|
||||
|
||||
#define LOG_LEVEL CONFIG_GPIO_LOG_LEVEL
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(gpio_595);
|
||||
|
||||
/** Configuration data */
|
||||
struct reg_595_config {
|
||||
/* gpio_driver_data needs to be first */
|
||||
struct gpio_driver_config common;
|
||||
|
||||
struct spi_dt_spec bus;
|
||||
|
||||
uint8_t ngpios;
|
||||
};
|
||||
|
||||
/** Runtime driver data */
|
||||
struct reg_595_drv_data {
|
||||
/* gpio_driver_data needs to be first */
|
||||
struct gpio_driver_config data;
|
||||
|
||||
struct k_sem lock;
|
||||
|
||||
uint32_t gpio_cache;
|
||||
};
|
||||
|
||||
static int reg_595_write_registers(const struct device *dev, uint32_t value) {
|
||||
const struct reg_595_config *config = dev->config;
|
||||
struct reg_595_drv_data *const drv_data = (struct reg_595_drv_data *const)dev->data;
|
||||
int ret = 0;
|
||||
|
||||
uint8_t nwrite = config->ngpios / 8;
|
||||
uint32_t reg_data = sys_cpu_to_be32(value);
|
||||
|
||||
/* Allow a sequence of 1-4 registers in sequence, lowest byte is for the first in the chain */
|
||||
const struct spi_buf tx_buf[1] = {{
|
||||
.buf = ((uint8_t *)®_data) + (4 - nwrite),
|
||||
.len = nwrite,
|
||||
}};
|
||||
|
||||
const struct spi_buf_set tx = {
|
||||
.buffers = tx_buf,
|
||||
.count = ARRAY_SIZE(tx_buf),
|
||||
};
|
||||
|
||||
ret = spi_write_dt(&config->bus, &tx);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("spi_write FAIL %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
drv_data->gpio_cache = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Setup the pin direction (input or output)
|
||||
*
|
||||
* @param dev Device struct of the 595
|
||||
* @param pin The pin number
|
||||
* @param flags Flags of pin or port
|
||||
*
|
||||
* @return 0 if successful, failed otherwise
|
||||
*/
|
||||
static int setup_pin_dir(const struct device *dev, uint32_t pin, int flags) {
|
||||
if ((flags & GPIO_OUTPUT) == 0U) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int reg_595_pin_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) {
|
||||
int ret;
|
||||
|
||||
/* Can't do SPI bus operations from an ISR */
|
||||
if (k_is_in_isr()) {
|
||||
return -EWOULDBLOCK;
|
||||
}
|
||||
|
||||
if ((flags & GPIO_OPEN_DRAIN) != 0U) {
|
||||
return -ENOTSUP;
|
||||
};
|
||||
|
||||
ret = setup_pin_dir(dev, pin, flags);
|
||||
if (ret) {
|
||||
LOG_ERR("595: error setting pin direction (%d)", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int reg_595_port_get_raw(const struct device *dev, uint32_t *value) { return -ENOTSUP; }
|
||||
|
||||
static int reg_595_port_set_masked_raw(const struct device *dev, uint32_t mask, uint32_t value) {
|
||||
struct reg_595_drv_data *const drv_data = (struct reg_595_drv_data *const)dev->data;
|
||||
uint32_t buf;
|
||||
int ret;
|
||||
|
||||
/* Can't do SPI bus operations from an ISR */
|
||||
if (k_is_in_isr()) {
|
||||
return -EWOULDBLOCK;
|
||||
}
|
||||
|
||||
k_sem_take(&drv_data->lock, K_FOREVER);
|
||||
|
||||
buf = drv_data->gpio_cache;
|
||||
buf = (buf & ~mask) | (mask & value);
|
||||
|
||||
ret = reg_595_write_registers(dev, buf);
|
||||
|
||||
k_sem_give(&drv_data->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int reg_595_port_set_bits_raw(const struct device *dev, uint32_t mask) {
|
||||
return reg_595_port_set_masked_raw(dev, mask, mask);
|
||||
}
|
||||
|
||||
static int reg_595_port_clear_bits_raw(const struct device *dev, uint32_t mask) {
|
||||
return reg_595_port_set_masked_raw(dev, mask, 0);
|
||||
}
|
||||
|
||||
static int reg_595_port_toggle_bits(const struct device *dev, uint32_t mask) {
|
||||
struct reg_595_drv_data *const drv_data = (struct reg_595_drv_data *const)dev->data;
|
||||
uint32_t buf;
|
||||
int ret;
|
||||
|
||||
/* Can't do SPI bus operations from an ISR */
|
||||
if (k_is_in_isr()) {
|
||||
return -EWOULDBLOCK;
|
||||
}
|
||||
|
||||
k_sem_take(&drv_data->lock, K_FOREVER);
|
||||
|
||||
buf = drv_data->gpio_cache;
|
||||
buf ^= mask;
|
||||
|
||||
ret = reg_595_write_registers(dev, buf);
|
||||
|
||||
k_sem_give(&drv_data->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct gpio_driver_api api_table = {
|
||||
.pin_configure = reg_595_pin_config,
|
||||
.port_get_raw = reg_595_port_get_raw,
|
||||
.port_set_masked_raw = reg_595_port_set_masked_raw,
|
||||
.port_set_bits_raw = reg_595_port_set_bits_raw,
|
||||
.port_clear_bits_raw = reg_595_port_clear_bits_raw,
|
||||
.port_toggle_bits = reg_595_port_toggle_bits,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initialization function of 595
|
||||
*
|
||||
* @param dev Device struct
|
||||
* @return 0 if successful, failed otherwise.
|
||||
*/
|
||||
static int reg_595_init(const struct device *dev) {
|
||||
const struct reg_595_config *const config = dev->config;
|
||||
struct reg_595_drv_data *const drv_data = (struct reg_595_drv_data *const)dev->data;
|
||||
|
||||
if (!device_is_ready(config->bus.bus)) {
|
||||
LOG_ERR("Unable to get SPI bus device");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
k_sem_init(&drv_data->lock, 1, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define GPIO_PORT_PIN_MASK_FROM_NGPIOS(ngpios) ((gpio_port_pins_t)(((uint64_t)1 << (ngpios)) - 1U))
|
||||
|
||||
#define GPIO_PORT_PIN_MASK_FROM_DT_INST(inst) \
|
||||
GPIO_PORT_PIN_MASK_FROM_NGPIOS(DT_INST_PROP(inst, ngpios))
|
||||
|
||||
#define REG_595_INIT(n) \
|
||||
static struct reg_595_config reg_595_##n##_config = { \
|
||||
.common = \
|
||||
{ \
|
||||
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \
|
||||
}, \
|
||||
.bus = \
|
||||
SPI_DT_SPEC_INST_GET(n, SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8), 0), \
|
||||
.ngpios = DT_INST_PROP(n, ngpios), \
|
||||
}; \
|
||||
\
|
||||
static struct reg_595_drv_data reg_595_##n##_drvdata = {}; \
|
||||
\
|
||||
/* This has to init after SPI master */ \
|
||||
DEVICE_DT_INST_DEFINE(n, reg_595_init, NULL, ®_595_##n##_drvdata, ®_595_##n##_config, \
|
||||
POST_KERNEL, CONFIG_GPIO_595_INIT_PRIORITY, &api_table);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(REG_595_INIT)
|
33
app/drivers/zephyr/dts/bindings/gpio/zmk,gpio-595.yaml
Normal file
33
app/drivers/zephyr/dts/bindings/gpio/zmk,gpio-595.yaml
Normal file
|
@ -0,0 +1,33 @@
|
|||
#
|
||||
# Copyright (c) 2022 The ZMK Contributors
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
description: >
|
||||
This is a representation of the 595 Shift Register.
|
||||
|
||||
compatible: "zmk,gpio-595"
|
||||
|
||||
include: [gpio-controller.yaml, spi-device.yaml]
|
||||
|
||||
properties:
|
||||
label:
|
||||
required: true
|
||||
|
||||
"#gpio-cells":
|
||||
const: 2
|
||||
|
||||
ngpios:
|
||||
type: int
|
||||
required: true
|
||||
enum:
|
||||
- 8
|
||||
- 16
|
||||
- 24
|
||||
- 32
|
||||
description: Number of gpios supported
|
||||
|
||||
gpio-cells:
|
||||
- pin
|
||||
- flags
|
|
@ -1,4 +1,5 @@
|
|||
#include <behaviors/key_press.dtsi>
|
||||
#include <behaviors/key_toggle.dtsi>
|
||||
#include <behaviors/transparent.dtsi>
|
||||
#include <behaviors/none.dtsi>
|
||||
#include <behaviors/mod_tap.dtsi>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
compatible = "zmk,behavior-caps-word";
|
||||
label = "CAPS_WORD";
|
||||
#binding-cells = <0>;
|
||||
continue-list = <UNDERSCORE>;
|
||||
continue-list = <UNDERSCORE BACKSPACE DELETE>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
15
app/dts/behaviors/key_toggle.dtsi
Normal file
15
app/dts/behaviors/key_toggle.dtsi
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/ {
|
||||
behaviors {
|
||||
/omit-if-no-ref/ kt: behavior_key_toggle {
|
||||
compatible = "zmk,behavior-key-toggle";
|
||||
label = "KEY_TOGGLE";
|
||||
#binding-cells = <1>;
|
||||
};
|
||||
};
|
||||
};
|
8
app/dts/bindings/behaviors/zmk,behavior-key-toggle.yaml
Normal file
8
app/dts/bindings/behaviors/zmk,behavior-key-toggle.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
description: Key toggle behavior
|
||||
|
||||
compatible: "zmk,behavior-key-toggle"
|
||||
|
||||
include: one_param.yaml
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#define ZMK_HID_USAGE(page, id) ((page << 16) | id)
|
||||
#define ZMK_HID_USAGE_ID(usage) (usage & 0xFFFF)
|
||||
#define ZMK_HID_USAGE_PAGE(usage) (usage >> 16)
|
||||
#define ZMK_HID_USAGE_PAGE(usage) ((usage >> 16) & 0xFF)
|
||||
|
||||
/* WARNING: DEPRECATED from dt-bindings/zmk/keys.h */
|
||||
#define USAGE_KEYPAD (0x07) // WARNING: DEPRECATED (DO NOT USE)
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
#define ZMK_BLE_IS_CENTRAL \
|
||||
(IS_ENABLED(CONFIG_ZMK_SPLIT) && IS_ENABLED(CONFIG_ZMK_BLE) && \
|
||||
IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL))
|
||||
IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL))
|
||||
|
||||
#if ZMK_BLE_IS_CENTRAL
|
||||
#define ZMK_BLE_PROFILE_COUNT (CONFIG_BT_MAX_PAIRED - 1)
|
||||
|
@ -33,6 +33,6 @@ char *zmk_ble_active_profile_name();
|
|||
|
||||
int zmk_ble_unpair_all();
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
||||
void zmk_ble_set_peripheral_addr(bt_addr_le_t *addr);
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) */
|
||||
|
|
|
@ -23,7 +23,7 @@ ZMK_EVENT_DECLARE(zmk_keycode_state_changed);
|
|||
|
||||
static inline struct zmk_keycode_state_changed_event *
|
||||
zmk_keycode_state_changed_from_encoded(uint32_t encoded, bool pressed, int64_t timestamp) {
|
||||
uint16_t page = ZMK_HID_USAGE_PAGE(encoded) & 0xFF;
|
||||
uint16_t page = ZMK_HID_USAGE_PAGE(encoded);
|
||||
uint16_t id = ZMK_HID_USAGE_ID(encoded);
|
||||
uint8_t implicit_modifiers = 0x00;
|
||||
uint8_t explicit_modifiers = 0x00;
|
||||
|
|
|
@ -129,17 +129,26 @@ struct zmk_hid_consumer_report {
|
|||
zmk_mod_flags_t zmk_hid_get_explicit_mods();
|
||||
int zmk_hid_register_mod(zmk_mod_t modifier);
|
||||
int zmk_hid_unregister_mod(zmk_mod_t modifier);
|
||||
bool zmk_hid_mod_is_pressed(zmk_mod_t modifier);
|
||||
|
||||
int zmk_hid_register_mods(zmk_mod_flags_t explicit_modifiers);
|
||||
int zmk_hid_unregister_mods(zmk_mod_flags_t explicit_modifiers);
|
||||
int zmk_hid_implicit_modifiers_press(zmk_mod_flags_t implicit_modifiers);
|
||||
int zmk_hid_implicit_modifiers_release();
|
||||
|
||||
int zmk_hid_keyboard_press(zmk_key_t key);
|
||||
int zmk_hid_keyboard_release(zmk_key_t key);
|
||||
void zmk_hid_keyboard_clear();
|
||||
bool zmk_hid_keyboard_is_pressed(zmk_key_t key);
|
||||
|
||||
int zmk_hid_consumer_press(zmk_key_t key);
|
||||
int zmk_hid_consumer_release(zmk_key_t key);
|
||||
void zmk_hid_consumer_clear();
|
||||
bool zmk_hid_consumer_is_pressed(zmk_key_t key);
|
||||
|
||||
int zmk_hid_press(uint32_t usage);
|
||||
int zmk_hid_release(uint32_t usage);
|
||||
bool zmk_hid_is_pressed(uint32_t usage);
|
||||
|
||||
struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report();
|
||||
struct zmk_hid_consumer_report *zmk_hid_get_consumer_report();
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <zmk/events/position_state_changed.h>
|
||||
#include <zmk/events/keycode_state_changed.h>
|
||||
#include <zmk/events/modifiers_state_changed.h>
|
||||
#include <zmk/keys.h>
|
||||
#include <zmk/hid.h>
|
||||
#include <zmk/keymap.h>
|
||||
|
||||
|
@ -92,7 +93,9 @@ static bool caps_word_is_caps_includelist(const struct behavior_caps_word_config
|
|||
continuation->id, continuation->implicit_modifiers);
|
||||
|
||||
if (continuation->page == usage_page && continuation->id == usage_id &&
|
||||
continuation->implicit_modifiers == implicit_modifiers) {
|
||||
(continuation->implicit_modifiers &
|
||||
(implicit_modifiers | zmk_hid_get_explicit_mods())) ==
|
||||
continuation->implicit_modifiers) {
|
||||
LOG_DBG("Continuing capsword, found included usage: 0x%02X - 0x%02X", usage_page,
|
||||
usage_id);
|
||||
return true;
|
||||
|
@ -143,6 +146,7 @@ static int caps_word_keycode_state_changed_listener(const zmk_event_t *eh) {
|
|||
caps_word_enhance_usage(config, ev);
|
||||
|
||||
if (!caps_word_is_alpha(ev->keycode) && !caps_word_is_numeric(ev->keycode) &&
|
||||
!is_mod(ev->usage_page, ev->keycode) &&
|
||||
!caps_word_is_caps_includelist(config, ev->usage_page, ev->keycode,
|
||||
ev->implicit_modifiers)) {
|
||||
LOG_DBG("Deactivating caps_word for 0x%02X - 0x%02X", ev->usage_page, ev->keycode);
|
||||
|
@ -162,7 +166,7 @@ static int behavior_caps_word_init(const struct device *dev) {
|
|||
#define CAPS_WORD_LABEL(i, _n) DT_INST_LABEL(i)
|
||||
|
||||
#define PARSE_BREAK(i) \
|
||||
{.page = (ZMK_HID_USAGE_PAGE(i) & 0xFF), \
|
||||
{.page = ZMK_HID_USAGE_PAGE(i), \
|
||||
.id = ZMK_HID_USAGE_ID(i), \
|
||||
.implicit_modifiers = SELECT_MODS(i)},
|
||||
|
||||
|
|
44
app/src/behaviors/behavior_key_toggle.c
Normal file
44
app/src/behaviors/behavior_key_toggle.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT zmk_behavior_key_toggle
|
||||
|
||||
#include <device.h>
|
||||
#include <drivers/behavior.h>
|
||||
#include <logging/log.h>
|
||||
|
||||
#include <zmk/hid.h>
|
||||
#include <zmk/event_manager.h>
|
||||
#include <zmk/events/keycode_state_changed.h>
|
||||
#include <zmk/behavior.h>
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
static int behavior_key_toggle_init(const struct device *dev) { return 0; }
|
||||
|
||||
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
||||
bool pressed = zmk_hid_is_pressed(binding->param1);
|
||||
return ZMK_EVENT_RAISE(
|
||||
zmk_keycode_state_changed_from_encoded(binding->param1, !pressed, event.timestamp));
|
||||
}
|
||||
|
||||
static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_key_toggle_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released,
|
||||
};
|
||||
|
||||
#define KT_INST(n) \
|
||||
DEVICE_DT_INST_DEFINE(n, behavior_key_toggle_init, NULL, NULL, NULL, APPLICATION, \
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_key_toggle_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(KT_INST)
|
|
@ -199,7 +199,7 @@ static int sticky_key_keycode_state_changed_listener(const zmk_event_t *eh) {
|
|||
|
||||
if (strcmp(sticky_key->config->behavior.behavior_dev, "KEY_PRESS") == 0 &&
|
||||
ZMK_HID_USAGE_ID(sticky_key->param1) == ev->keycode &&
|
||||
(ZMK_HID_USAGE_PAGE(sticky_key->param1) & 0xFF) == ev->usage_page &&
|
||||
ZMK_HID_USAGE_PAGE(sticky_key->param1) == ev->usage_page &&
|
||||
SELECT_MODS(sticky_key->param1) == ev->implicit_modifiers) {
|
||||
// don't catch key down events generated by the sticky key behavior itself
|
||||
continue;
|
||||
|
|
|
@ -47,7 +47,7 @@ static uint8_t passkey_digit = 0;
|
|||
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) */
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
||||
#define PROFILE_COUNT (CONFIG_BT_MAX_PAIRED - 1)
|
||||
#else
|
||||
#define PROFILE_COUNT CONFIG_BT_MAX_PAIRED
|
||||
|
@ -82,11 +82,11 @@ static const struct bt_data zmk_ble_ad[] = {
|
|||
),
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
||||
|
||||
static bt_addr_le_t peripheral_addr;
|
||||
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) */
|
||||
|
||||
static void raise_profile_changed_event() {
|
||||
ZMK_EVENT_RAISE(new_zmk_ble_active_profile_changed((struct zmk_ble_active_profile_changed){
|
||||
|
@ -278,14 +278,14 @@ bt_addr_le_t *zmk_ble_active_profile_addr() { return &profiles[active_profile].p
|
|||
|
||||
char *zmk_ble_active_profile_name() { return profiles[active_profile].name; }
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
||||
|
||||
void zmk_ble_set_peripheral_addr(bt_addr_le_t *addr) {
|
||||
memcpy(&peripheral_addr, addr, sizeof(bt_addr_le_t));
|
||||
settings_save_one("ble/peripheral_address", addr, sizeof(bt_addr_le_t));
|
||||
}
|
||||
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL) */
|
||||
#endif /* IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL) */
|
||||
|
||||
#if IS_ENABLED(CONFIG_SETTINGS)
|
||||
|
||||
|
@ -336,7 +336,7 @@ static int ble_profiles_handle_set(const char *name, size_t len, settings_read_c
|
|||
return err;
|
||||
}
|
||||
}
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
||||
else if (settings_name_steq(name, "peripheral_address", &next) && !next) {
|
||||
if (len != sizeof(bt_addr_le_t)) {
|
||||
return -EINVAL;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ menu "ZMK Display Widgets"
|
|||
config ZMK_WIDGET_LAYER_STATUS
|
||||
bool "Widget for highest, active layer using small icons"
|
||||
default y
|
||||
depends on !ZMK_SPLIT || ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
depends on !ZMK_SPLIT || ZMK_SPLIT_ROLE_CENTRAL
|
||||
select LVGL_USE_LABEL
|
||||
|
||||
config ZMK_WIDGET_BATTERY_STATUS
|
||||
|
@ -17,19 +17,19 @@ config ZMK_WIDGET_BATTERY_STATUS
|
|||
|
||||
config ZMK_WIDGET_OUTPUT_STATUS
|
||||
bool "Widget for keyboard output status icons"
|
||||
depends on BT && (!ZMK_SPLIT_BLE || ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
default y if BT && (!ZMK_SPLIT_BLE || ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
depends on BT && (!ZMK_SPLIT_BLE || ZMK_SPLIT_ROLE_CENTRAL)
|
||||
default y if BT && (!ZMK_SPLIT_BLE || ZMK_SPLIT_ROLE_CENTRAL)
|
||||
select LVGL_USE_LABEL
|
||||
|
||||
config ZMK_WIDGET_PERIPHERAL_STATUS
|
||||
bool "Widget for split peripheral status icons"
|
||||
depends on BT && ZMK_SPLIT_BLE && !ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
default y if BT && ZMK_SPLIT_BLE && !ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
depends on BT && ZMK_SPLIT_BLE && !ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y if BT && ZMK_SPLIT_BLE && !ZMK_SPLIT_ROLE_CENTRAL
|
||||
select LVGL_USE_LABEL
|
||||
|
||||
config ZMK_WIDGET_WPM_STATUS
|
||||
bool "Widget for displaying typed words per minute"
|
||||
depends on !ZMK_SPLIT || ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
depends on !ZMK_SPLIT || ZMK_SPLIT_ROLE_CENTRAL
|
||||
select LVGL_USE_LABEL
|
||||
select ZMK_WPM
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "zmk/keys.h"
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
|
@ -55,6 +56,11 @@ int zmk_hid_unregister_mod(zmk_mod_t modifier) {
|
|||
return current == GET_MODIFIERS ? 0 : 1;
|
||||
}
|
||||
|
||||
bool zmk_hid_mod_is_pressed(zmk_mod_t modifier) {
|
||||
zmk_mod_flags_t mod_flag = 1 << modifier;
|
||||
return (zmk_hid_get_explicit_mods() & mod_flag) == mod_flag;
|
||||
}
|
||||
|
||||
int zmk_hid_register_mods(zmk_mod_flags_t modifiers) {
|
||||
int ret = 0;
|
||||
for (zmk_mod_t i = 0; i < 8; i++) {
|
||||
|
@ -96,6 +102,13 @@ static inline int deselect_keyboard_usage(zmk_key_t usage) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline bool check_keyboard_usage(zmk_key_t usage) {
|
||||
if (usage > ZMK_HID_KEYBOARD_NKRO_MAX_USAGE) {
|
||||
return false;
|
||||
}
|
||||
return keyboard_report.body.keys[usage / 8] & (1 << (usage % 8));
|
||||
}
|
||||
|
||||
#elif IS_ENABLED(CONFIG_ZMK_HID_REPORT_TYPE_HKRO)
|
||||
|
||||
#define TOGGLE_KEYBOARD(match, val) \
|
||||
|
@ -119,6 +132,15 @@ static inline int deselect_keyboard_usage(zmk_key_t usage) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int check_keyboard_usage(zmk_key_t usage) {
|
||||
for (int idx = 0; idx < CONFIG_ZMK_HID_KEYBOARD_REPORT_SIZE; idx++) {
|
||||
if (keyboard_report.body.keys[idx] == usage) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
#error "A proper HID report type must be selected"
|
||||
#endif
|
||||
|
@ -164,6 +186,13 @@ int zmk_hid_keyboard_release(zmk_key_t code) {
|
|||
return 0;
|
||||
};
|
||||
|
||||
bool zmk_hid_keyboard_is_pressed(zmk_key_t code) {
|
||||
if (code >= HID_USAGE_KEY_KEYBOARD_LEFTCONTROL && code <= HID_USAGE_KEY_KEYBOARD_RIGHT_GUI) {
|
||||
return zmk_hid_mod_is_pressed(code - HID_USAGE_KEY_KEYBOARD_LEFTCONTROL);
|
||||
}
|
||||
return check_keyboard_usage(code);
|
||||
}
|
||||
|
||||
void zmk_hid_keyboard_clear() { memset(&keyboard_report.body, 0, sizeof(keyboard_report.body)); }
|
||||
|
||||
int zmk_hid_consumer_press(zmk_key_t code) {
|
||||
|
@ -178,6 +207,45 @@ int zmk_hid_consumer_release(zmk_key_t code) {
|
|||
|
||||
void zmk_hid_consumer_clear() { memset(&consumer_report.body, 0, sizeof(consumer_report.body)); }
|
||||
|
||||
bool zmk_hid_consumer_is_pressed(zmk_key_t key) {
|
||||
for (int idx = 0; idx < CONFIG_ZMK_HID_CONSUMER_REPORT_SIZE; idx++) {
|
||||
if (consumer_report.body.keys[idx] == key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int zmk_hid_press(uint32_t usage) {
|
||||
switch (ZMK_HID_USAGE_PAGE(usage)) {
|
||||
case HID_USAGE_KEY:
|
||||
return zmk_hid_keyboard_press(ZMK_HID_USAGE_ID(usage));
|
||||
case HID_USAGE_CONSUMER:
|
||||
return zmk_hid_consumer_press(ZMK_HID_USAGE_ID(usage));
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int zmk_hid_release(uint32_t usage) {
|
||||
switch (ZMK_HID_USAGE_PAGE(usage)) {
|
||||
case HID_USAGE_KEY:
|
||||
return zmk_hid_keyboard_release(ZMK_HID_USAGE_ID(usage));
|
||||
case HID_USAGE_CONSUMER:
|
||||
return zmk_hid_consumer_release(ZMK_HID_USAGE_ID(usage));
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bool zmk_hid_is_pressed(uint32_t usage) {
|
||||
switch (ZMK_HID_USAGE_PAGE(usage)) {
|
||||
case HID_USAGE_KEY:
|
||||
return zmk_hid_keyboard_is_pressed(ZMK_HID_USAGE_ID(usage));
|
||||
case HID_USAGE_CONSUMER:
|
||||
return zmk_hid_consumer_is_pressed(ZMK_HID_USAGE_ID(usage));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report() {
|
||||
return &keyboard_report;
|
||||
}
|
||||
|
|
|
@ -21,21 +21,10 @@ static int hid_listener_keycode_pressed(const struct zmk_keycode_state_changed *
|
|||
|
||||
LOG_DBG("usage_page 0x%02X keycode 0x%02X implicit_mods 0x%02X explicit_mods 0x%02X",
|
||||
ev->usage_page, ev->keycode, ev->implicit_modifiers, ev->explicit_modifiers);
|
||||
switch (ev->usage_page) {
|
||||
case HID_USAGE_KEY:
|
||||
err = zmk_hid_keyboard_press(ev->keycode);
|
||||
if (err < 0) {
|
||||
LOG_ERR("Unable to press keycode");
|
||||
return err;
|
||||
}
|
||||
break;
|
||||
case HID_USAGE_CONSUMER:
|
||||
err = zmk_hid_consumer_press(ev->keycode);
|
||||
if (err < 0) {
|
||||
LOG_ERR("Unable to press keycode");
|
||||
return err;
|
||||
}
|
||||
break;
|
||||
err = zmk_hid_press(ZMK_HID_USAGE(ev->usage_page, ev->keycode));
|
||||
if (err < 0) {
|
||||
LOG_DBG("Unable to press keycode");
|
||||
return err;
|
||||
}
|
||||
explicit_mods_changed = zmk_hid_register_mods(ev->explicit_modifiers);
|
||||
implicit_mods_changed = zmk_hid_implicit_modifiers_press(ev->implicit_modifiers);
|
||||
|
@ -56,20 +45,10 @@ static int hid_listener_keycode_released(const struct zmk_keycode_state_changed
|
|||
|
||||
LOG_DBG("usage_page 0x%02X keycode 0x%02X implicit_mods 0x%02X explicit_mods 0x%02X",
|
||||
ev->usage_page, ev->keycode, ev->implicit_modifiers, ev->explicit_modifiers);
|
||||
switch (ev->usage_page) {
|
||||
case HID_USAGE_KEY:
|
||||
err = zmk_hid_keyboard_release(ev->keycode);
|
||||
if (err < 0) {
|
||||
LOG_ERR("Unable to release keycode");
|
||||
return err;
|
||||
}
|
||||
break;
|
||||
case HID_USAGE_CONSUMER:
|
||||
err = zmk_hid_consumer_release(ev->keycode);
|
||||
if (err < 0) {
|
||||
LOG_ERR("Unable to release keycode");
|
||||
return err;
|
||||
}
|
||||
err = zmk_hid_release(ZMK_HID_USAGE(ev->usage_page, ev->keycode));
|
||||
if (err < 0) {
|
||||
LOG_DBG("Unable to release keycode");
|
||||
return err;
|
||||
}
|
||||
|
||||
explicit_mods_changed = zmk_hid_unregister_mods(ev->explicit_modifiers);
|
||||
|
@ -104,4 +83,4 @@ int hid_listener(const zmk_event_t *eh) {
|
|||
}
|
||||
|
||||
ZMK_LISTENER(hid_listener, hid_listener);
|
||||
ZMK_SUBSCRIPTION(hid_listener, zmk_keycode_state_changed);
|
||||
ZMK_SUBSCRIPTION(hid_listener, zmk_keycode_state_changed);
|
||||
|
|
6
app/src/split/CMakeLists.txt
Normal file
6
app/src/split/CMakeLists.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if (CONFIG_ZMK_SPLIT_BLE)
|
||||
add_subdirectory(bluetooth)
|
||||
endif()
|
26
app/src/split/Kconfig
Normal file
26
app/src/split/Kconfig
Normal file
|
@ -0,0 +1,26 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
menuconfig ZMK_SPLIT
|
||||
bool "Split keyboard support"
|
||||
|
||||
if ZMK_SPLIT
|
||||
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
bool "Split central device"
|
||||
|
||||
choice ZMK_SPLIT_TRANSPORT
|
||||
prompt "Split transport"
|
||||
|
||||
config ZMK_SPLIT_BLE
|
||||
bool "BLE"
|
||||
depends on ZMK_BLE
|
||||
select BT_USER_PHY_UPDATE
|
||||
select BT_AUTO_PHY_UPDATE
|
||||
|
||||
endchoice
|
||||
|
||||
#ZMK_SPLIT
|
||||
endif
|
||||
|
||||
rsource "bluetooth/Kconfig"
|
11
app/src/split/bluetooth/CMakeLists.txt
Normal file
11
app/src/split/bluetooth/CMakeLists.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if (NOT CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
||||
target_sources(app PRIVATE split_listener.c)
|
||||
target_sources(app PRIVATE service.c)
|
||||
target_sources(app PRIVATE peripheral.c)
|
||||
endif()
|
||||
if (CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
||||
target_sources(app PRIVATE central.c)
|
||||
endif()
|
95
app/src/split/bluetooth/Kconfig
Normal file
95
app/src/split/bluetooth/Kconfig
Normal file
|
@ -0,0 +1,95 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if ZMK_SPLIT && ZMK_SPLIT_BLE
|
||||
|
||||
menu "BLE Transport"
|
||||
|
||||
# Added for backwards compatibility. New shields/board should set `ZMK_SPLIT_ROLE_CENTRAL` only.
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
bool
|
||||
select ZMK_SPLIT_ROLE_CENTRAL
|
||||
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
select BT_CENTRAL
|
||||
select BT_GATT_CLIENT
|
||||
select BT_GATT_AUTO_DISCOVER_CCC
|
||||
|
||||
if ZMK_SPLIT_ROLE_CENTRAL
|
||||
|
||||
config ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE
|
||||
int "Max number of key position state events to queue when received from peripherals"
|
||||
default 5
|
||||
|
||||
config ZMK_BLE_SPLIT_CENTRAL_SPLIT_RUN_STACK_SIZE
|
||||
int "BLE split central write thread stack size"
|
||||
default 512
|
||||
|
||||
config ZMK_BLE_SPLIT_CENTRAL_SPLIT_RUN_QUEUE_SIZE
|
||||
int "Max number of behavior run events to queue to send to the peripheral(s)"
|
||||
default 5
|
||||
|
||||
endif # ZMK_SPLIT_ROLE_CENTRAL
|
||||
|
||||
if !ZMK_SPLIT_ROLE_CENTRAL
|
||||
|
||||
config ZMK_SPLIT_BLE_PERIPHERAL_STACK_SIZE
|
||||
int "BLE split peripheral notify thread stack size"
|
||||
default 650
|
||||
|
||||
config ZMK_SPLIT_BLE_PERIPHERAL_PRIORITY
|
||||
int "BLE split peripheral notify thread priority"
|
||||
default 5
|
||||
|
||||
config ZMK_SPLIT_BLE_PERIPHERAL_POSITION_QUEUE_SIZE
|
||||
int "Max number of key position state events to queue to send to the central"
|
||||
default 10
|
||||
|
||||
config ZMK_USB
|
||||
default n
|
||||
|
||||
config BT_MAX_PAIRED
|
||||
default 1
|
||||
|
||||
config BT_MAX_CONN
|
||||
default 1
|
||||
|
||||
config BT_PERIPHERAL_PREF_MAX_INT
|
||||
default 6
|
||||
|
||||
#!ZMK_SPLIT_ROLE_CENTRAL
|
||||
endif
|
||||
|
||||
endmenu
|
||||
|
||||
#ZMK_SPLIT_BLE
|
||||
endif
|
||||
|
||||
|
||||
if ZMK_BLE
|
||||
|
||||
if ZMK_SPLIT_BLE && ZMK_SPLIT_ROLE_CENTRAL
|
||||
|
||||
config BT_MAX_CONN
|
||||
default 6
|
||||
|
||||
config BT_MAX_PAIRED
|
||||
default 6
|
||||
|
||||
#ZMK_SPLIT_BLE && ZMK_SPLIT_ROLE_CENTRAL
|
||||
endif
|
||||
|
||||
if !ZMK_SPLIT_BLE
|
||||
|
||||
config BT_MAX_CONN
|
||||
default 5
|
||||
|
||||
config BT_MAX_PAIRED
|
||||
default 5
|
||||
|
||||
#!ZMK_SPLIT_BLE
|
||||
endif
|
||||
|
||||
#ZMK_BLE
|
||||
endif
|
||||
|
|
@ -60,6 +60,16 @@ K_MSGQ_DEFINE(peripheral_event_msgq, sizeof(struct zmk_position_state_changed),
|
|||
K_MSGQ_DEFINE(peripheral_batt_lvl_msgq, sizeof(struct zmk_peripheral_battery_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) {
|
||||
|
@ -98,6 +108,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;
|
||||
|
@ -142,16 +168,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
s/.*hid_listener_keycode_//p
|
||||
s/.*hid_implicit_modifiers_//p
|
||||
s/.*caps_word_enhance_usage/enhance_usage/p
|
||||
s/.*caps_word_is_caps_includelist/caps_includelist/p
|
|
@ -0,0 +1,20 @@
|
|||
enhance_usage: Enhancing usage 0x04 with modifiers: 0x02
|
||||
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x02 explicit_mods 0x00
|
||||
press: Modifiers set to 0x02
|
||||
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
release: Modifiers set to 0x00
|
||||
pressed: usage_page 0x07 keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00
|
||||
press: Modifiers set to 0x02
|
||||
caps_includelist: Comparing with 0x07 - 0x2D (with implicit mods: 0x02)
|
||||
caps_includelist: Continuing capsword, found included usage: 0x07 - 0x2D
|
||||
pressed: usage_page 0x07 keycode 0x2D implicit_mods 0x00 explicit_mods 0x00
|
||||
press: Modifiers set to 0x02
|
||||
released: usage_page 0x07 keycode 0x2D implicit_mods 0x00 explicit_mods 0x00
|
||||
release: Modifiers set to 0x02
|
||||
released: usage_page 0x07 keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00
|
||||
release: Modifiers set to 0x00
|
||||
enhance_usage: Enhancing usage 0x04 with modifiers: 0x02
|
||||
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x02 explicit_mods 0x00
|
||||
press: Modifiers set to 0x02
|
||||
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
release: Modifiers set to 0x00
|
|
@ -0,0 +1,33 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label = "Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&caps_word &kp A
|
||||
&kp LSHFT &kp MINUS
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
ZMK_MOCK_PRESS(1,0,10)
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
ZMK_MOCK_PRESS(0,1,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,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
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)
|
||||
>;
|
||||
};
|
17
app/tests/keytoggle/behavior_keymap.dtsi
Normal file
17
app/tests/keytoggle/behavior_keymap.dtsi
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label ="Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&kt B &none
|
||||
&none &none
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
1
app/tests/keytoggle/kt-alt-tab/events.patterns
Normal file
1
app/tests/keytoggle/kt-alt-tab/events.patterns
Normal file
|
@ -0,0 +1 @@
|
|||
s/.*\(hid_listener_keycode_\|hid_implicit_modifiers_\)//p
|
28
app/tests/keytoggle/kt-alt-tab/keycode_events.snapshot
Normal file
28
app/tests/keytoggle/kt-alt-tab/keycode_events.snapshot
Normal file
|
@ -0,0 +1,28 @@
|
|||
pressed: usage_page 0x07 keycode 0xE2 implicit_mods 0x00 explicit_mods 0x00
|
||||
press: Modifiers set to 0x04
|
||||
pressed: usage_page 0x07 keycode 0x2B implicit_mods 0x00 explicit_mods 0x00
|
||||
press: Modifiers set to 0x04
|
||||
released: usage_page 0x07 keycode 0x2B implicit_mods 0x00 explicit_mods 0x00
|
||||
release: Modifiers set to 0x04
|
||||
pressed: usage_page 0x07 keycode 0x2B implicit_mods 0x00 explicit_mods 0x00
|
||||
press: Modifiers set to 0x04
|
||||
released: usage_page 0x07 keycode 0x2B implicit_mods 0x00 explicit_mods 0x00
|
||||
release: Modifiers set to 0x04
|
||||
pressed: usage_page 0x07 keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00
|
||||
press: Modifiers set to 0x06
|
||||
pressed: usage_page 0x07 keycode 0x2B implicit_mods 0x00 explicit_mods 0x00
|
||||
press: Modifiers set to 0x06
|
||||
released: usage_page 0x07 keycode 0x2B implicit_mods 0x00 explicit_mods 0x00
|
||||
release: Modifiers set to 0x06
|
||||
released: usage_page 0x07 keycode 0xE2 implicit_mods 0x00 explicit_mods 0x00
|
||||
release: Modifiers set to 0x02
|
||||
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
press: Modifiers set to 0x02
|
||||
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
release: Modifiers set to 0x02
|
||||
released: usage_page 0x07 keycode 0xE1 implicit_mods 0x00 explicit_mods 0x00
|
||||
release: Modifiers set to 0x00
|
||||
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
press: Modifiers set to 0x00
|
||||
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
release: Modifiers set to 0x00
|
48
app/tests/keytoggle/kt-alt-tab/native_posix_64.keymap
Normal file
48
app/tests/keytoggle/kt-alt-tab/native_posix_64.keymap
Normal file
|
@ -0,0 +1,48 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
/* Toggle LALT on */
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
/* Tap TAB twice */
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
/* Toggle LSHFT on */
|
||||
ZMK_MOCK_PRESS(1,0,10)
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
/* Tap TAB once */
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
/* Toggle LALT off */
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
/* Tap A */
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
/* Toggle LSHFT off */
|
||||
ZMK_MOCK_PRESS(1,0,10)
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
/* Tap A */
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
>;
|
||||
};
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label ="Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&kt LALT &kp TAB
|
||||
&kt LSHFT &kp A
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
1
app/tests/keytoggle/kt-modded-alpha/events.patterns
Normal file
1
app/tests/keytoggle/kt-modded-alpha/events.patterns
Normal file
|
@ -0,0 +1 @@
|
|||
s/.*\(hid_listener_keycode_\|hid_implicit_modifiers_\)//p
|
12
app/tests/keytoggle/kt-modded-alpha/keycode_events.snapshot
Normal file
12
app/tests/keytoggle/kt-modded-alpha/keycode_events.snapshot
Normal file
|
@ -0,0 +1,12 @@
|
|||
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x02 explicit_mods 0x00
|
||||
press: Modifiers set to 0x02
|
||||
released: usage_page 0x07 keycode 0x04 implicit_mods 0x02 explicit_mods 0x00
|
||||
release: Modifiers set to 0x00
|
||||
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
press: Modifiers set to 0x00
|
||||
released: usage_page 0x07 keycode 0x04 implicit_mods 0x02 explicit_mods 0x00
|
||||
release: Modifiers set to 0x00
|
||||
pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x02 explicit_mods 0x00
|
||||
press: Modifiers set to 0x02
|
||||
released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||
release: Modifiers set to 0x00
|
38
app/tests/keytoggle/kt-modded-alpha/native_posix_64.keymap
Normal file
38
app/tests/keytoggle/kt-modded-alpha/native_posix_64.keymap
Normal file
|
@ -0,0 +1,38 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
/* Toggle LS(A) on */
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
/* Toggle LS(A) off */
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
/* Press A */
|
||||
ZMK_MOCK_PRESS(1,0,10)
|
||||
/* Toggle LS(A) on */
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
/* Toggle LS(A) off */
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
/* Release A */
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
>;
|
||||
};
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label ="Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&kt LS(A) &trans
|
||||
&kp A &trans
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
s/.*hid_listener_keycode_//p
|
|
@ -0,0 +1,2 @@
|
|||
pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
|
@ -0,0 +1,7 @@
|
|||
CONFIG_GPIO=n
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_BACKEND_SHOW_COLOR=n
|
||||
CONFIG_ZMK_LOG_LEVEL_DBG=y
|
||||
CONFIG_DEBUG=y
|
||||
CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000
|
||||
CONFIG_ZMK_HID_REPORT_TYPE_NKRO=y
|
|
@ -0,0 +1,10 @@
|
|||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
1
app/tests/keytoggle/kt-press-release/events.patterns
Normal file
1
app/tests/keytoggle/kt-press-release/events.patterns
Normal file
|
@ -0,0 +1 @@
|
|||
s/.*hid_listener_keycode_//p
|
|
@ -0,0 +1,2 @@
|
|||
pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
||||
released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
10
app/tests/keytoggle/kt-press-release/native_posix_64.keymap
Normal file
10
app/tests/keytoggle/kt-press-release/native_posix_64.keymap
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
|
@ -23,8 +23,7 @@ Example:
|
|||
|
||||
#### Continue List
|
||||
|
||||
By default, the caps word will remain active when any alphanumeric character or the underscore (`UNDERSCORE`) characters are pressed. Any other keycode sent,
|
||||
will turn off caps word. If you would like to override this, you can set a new array of keys in the `continue-list` property in your keymap:
|
||||
By default, the caps word will remain active when any alphanumeric character or underscore (`UNDERSCORE`), backspace (`BACKSPACE`), or delete (`DELETE`) characters are pressed. Any other non-modifier keycode sent will turn off caps word. If you would like to override this, you can set a new array of keys in the `continue-list` property in your keymap:
|
||||
|
||||
```
|
||||
&caps_word {
|
||||
|
|
26
docs/docs/behaviors/key-toggle.md
Normal file
26
docs/docs/behaviors/key-toggle.md
Normal file
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
title: Key Toggle Behavior
|
||||
sidebar_label: Key Toggle
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
The key toggle behavior toggles the press of a key.
|
||||
If the key is not currently pressed, key toggle will press it, holding it until the key toggle is pressed again or the key is released in some other way.
|
||||
If the key _is_ currently pressed, key toggle will release it.
|
||||
|
||||
Example uses for key toggle include shift lock, or `ALT-TAB` window switching without holding down the `ALT` modifier.
|
||||
|
||||
### Behavior Binding
|
||||
|
||||
- Reference: `&kt`
|
||||
- Parameter: The [keycode](../codes/index.mdx), e.g. `LALT` or `DOWN_ARROW`
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
&kt LALT
|
||||
```
|
||||
|
||||
You can use any keycode that works for `&kp` as parameter to `&kt`, however, [modified keys](../codes/modifiers.mdx#modifier-functions) such as `LA(A)` will be toggled based on the status of the base keycode (in this case `A`).
|
||||
In other words, modifiers are ignored when determining whether or not the key is currently pressed.
|
|
@ -88,6 +88,10 @@ west build -d build/right -b nice_nano -- -DSHIELD=kyria_right
|
|||
|
||||
This produces `left` and `right` subfolders under the `build` directory and two separate .uf2 files. For future work on a specific half, use the `-d` parameter again to ensure you are building into the correct location.
|
||||
|
||||
:::tip
|
||||
Build times can be significantly reduced after the initial build by omitting all build arguments except the build directory, e.g. `west build -d build/left`. The additional options and intermediate build outputs from your initial build are cached and reused for unchanged files.
|
||||
:::
|
||||
|
||||
### Building from `zmk-config` Folder
|
||||
|
||||
Instead of building .uf2 files using the default keymap and config files, you can build directly from your [`zmk-config` folder](../user-setup.md#github-repo) by adding
|
||||
|
|
|
@ -320,10 +320,10 @@ Remember that `.c` files should be formatted according to `clang-format` to ensu
|
|||
|
||||
### Updating `app/CmakeLists.txt` to include the new driver
|
||||
|
||||
Most behavior drivers' are invoked according to the central half's [locality](#api-structure), and are therefore stored after the line `if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)` in the form, `target_sources(app PRIVATE src/behaviors/<behavior_name>.c)`, as shown below.
|
||||
Most behavior drivers' are invoked according to the central half's [locality](#api-structure), and are therefore stored after the line `if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL)` in the form, `target_sources(app PRIVATE src/behaviors/<behavior_name>.c)`, as shown below.
|
||||
|
||||
```txt title="app/CmakeLists.txt"
|
||||
if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_key_press.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_hold_tap.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_sticky_key.c)
|
||||
|
@ -346,9 +346,9 @@ endif()
|
|||
|
||||
For behaviors that do not require central locality, the following options for updating `app/CmakeLists.txt` also exist:
|
||||
|
||||
- Behavior applies to unibody, or central or peripheral half of keyboard: place `target_sources(app PRIVATE <behavior_name>.c)` line _before_ `if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)`
|
||||
- Behavior applies to _only_ central half of split keyboard: place `target_sources(app PRIVATE <behavior_name>.c)` after `if (CONFIG_ZMK_SPLIT_BLE AND CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)`
|
||||
- Behavior applies to _only_ peripheral half of split keyboard: place `target_sources(app PRIVATE <behavior_name>.c)` after `if (CONFIG_ZMK_SPLIT_BLE AND (NOT CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL))`
|
||||
- Behavior applies to unibody, or central or peripheral half of keyboard: place `target_sources(app PRIVATE <behavior_name>.c)` line _before_ `if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL)`
|
||||
- Behavior applies to _only_ central half of split keyboard: place `target_sources(app PRIVATE <behavior_name>.c)` after `if (CONFIG_ZMK_SPLIT_BLE AND CONFIG_ZMK_SPLIT_ROLE_CENTRAL)`
|
||||
- Behavior applies to _only_ peripheral half of split keyboard: place `target_sources(app PRIVATE <behavior_name>.c)` after `if (CONFIG_ZMK_SPLIT_BLE AND (NOT CONFIG_ZMK_SPLIT_ROLE_CENTRAL))`
|
||||
- Behavior requires certain condition in a keyboard's `.conf` file to be met: use `target_sources_ifdef(CONFIG_<Configuration Requirement> app PRIVATE <behavior_name>.c)` instead of `target_sources(<behavior_name>.c)`
|
||||
|
||||
### Defining common use-cases for the behavior (`.dtsi`) (Optional)
|
||||
|
|
|
@ -100,7 +100,7 @@ if SHIELD_MY_BOARD_LEFT
|
|||
config ZMK_KEYBOARD_NAME
|
||||
default "My Board"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
config ZMK_SPLIT_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
|
21097
docs/package-lock.json
generated
21097
docs/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -15,8 +15,8 @@
|
|||
"typecheck": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "^2.0.0-beta.18",
|
||||
"@docusaurus/preset-classic": "^2.0.0-beta.18",
|
||||
"@docusaurus/core": "^2.0.0-beta.21",
|
||||
"@docusaurus/preset-classic": "^2.0.0-beta.21",
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.32",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.15.3",
|
||||
"@fortawesome/react-fontawesome": "^0.1.18",
|
||||
|
@ -43,8 +43,8 @@
|
|||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "^2.0.0-beta.18",
|
||||
"@docusaurus/types": "^2.0.0-beta.18",
|
||||
"@docusaurus/module-type-aliases": "^2.0.0-beta.21",
|
||||
"@docusaurus/types": "^2.0.0-beta.21",
|
||||
"@tsconfig/docusaurus": "^1.0.5",
|
||||
"@types/js-yaml": "^4.0.5",
|
||||
"@types/react": "^17.0.3",
|
||||
|
|
|
@ -28,6 +28,7 @@ module.exports = {
|
|||
"behaviors/mod-tap",
|
||||
"behaviors/mod-morph",
|
||||
"behaviors/macros",
|
||||
"behaviors/key-toggle",
|
||||
"behaviors/sticky-key",
|
||||
"behaviors/sticky-layer",
|
||||
"behaviors/tap-dance",
|
||||
|
|
Loading…
Add table
Reference in a new issue