Merge 63b77fd259
into 0f972f1cc3
This commit is contained in:
commit
6f53189462
66 changed files with 2632 additions and 121 deletions
20
app/Kconfig
20
app/Kconfig
|
@ -258,6 +258,26 @@ rsource "src/split/Kconfig"
|
||||||
#Basic Keyboard Setup
|
#Basic Keyboard Setup
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
menu "Keymaps"
|
||||||
|
|
||||||
|
config ZMK_KEYMAP_LAYER_REORDERING
|
||||||
|
bool "Layer Reordering Support"
|
||||||
|
|
||||||
|
config ZMK_KEYMAP_SETTINGS_STORAGE
|
||||||
|
bool "Settings Save/Load"
|
||||||
|
depends on SETTINGS
|
||||||
|
depends on ZMK_BEHAVIOR_LOCAL_IDS
|
||||||
|
|
||||||
|
if ZMK_KEYMAP_SETTINGS_STORAGE
|
||||||
|
|
||||||
|
config ZMK_KEYMAP_LAYER_NAME_MAX_LEN
|
||||||
|
int "Max Layer Name Length"
|
||||||
|
default 20
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
endmenu # Keymaps
|
||||||
|
|
||||||
rsource "src/studio/Kconfig"
|
rsource "src/studio/Kconfig"
|
||||||
|
|
||||||
menu "Display/LED Options"
|
menu "Display/LED Options"
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#undef ZMK_BEHAVIORS_KEEP_ALL
|
||||||
|
|
||||||
#include <behaviors.dtsi>
|
#include <behaviors.dtsi>
|
||||||
#include <dt-bindings/zmk/keys.h>
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,12 @@
|
||||||
|
|
||||||
#include <dt-bindings/zmk/matrix_transform.h>
|
#include <dt-bindings/zmk/matrix_transform.h>
|
||||||
|
|
||||||
|
#include <layouts/cuddlykeyboards/ferris.dtsi>
|
||||||
|
|
||||||
|
&cuddlykeyboards_ferris_layout {
|
||||||
|
transform = <&transform>;
|
||||||
|
};
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
model = "Ferris rev0.2";
|
model = "Ferris rev0.2";
|
||||||
compatible = "ferris,rev02", "st,stm32f072";
|
compatible = "ferris,rev02", "st,stm32f072";
|
||||||
|
@ -18,7 +24,6 @@
|
||||||
zephyr,sram = &sram0;
|
zephyr,sram = &sram0;
|
||||||
zephyr,flash = &flash0;
|
zephyr,flash = &flash0;
|
||||||
zmk,kscan = &kscan;
|
zmk,kscan = &kscan;
|
||||||
zmk,matrix-transform = &transform;
|
|
||||||
/* TODO: Enable once we support the IC for underglow
|
/* TODO: Enable once we support the IC for underglow
|
||||||
zmk,underglow = &led_strip;
|
zmk,underglow = &led_strip;
|
||||||
*/
|
*/
|
||||||
|
@ -114,6 +119,9 @@ zephyr_udc0: &usb {
|
||||||
|
|
||||||
pinctrl-0 = <&usb_dm_pa11 &usb_dp_pa12>;
|
pinctrl-0 = <&usb_dm_pa11 &usb_dp_pa12>;
|
||||||
pinctrl-names = "default";
|
pinctrl-names = "default";
|
||||||
|
|
||||||
|
// Overridden to lower RAM usage.
|
||||||
|
num-bidir-endpoints = <4>;
|
||||||
};
|
};
|
||||||
|
|
||||||
&clk_hsi {
|
&clk_hsi {
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#undef ZMK_BEHAVIORS_KEEP_ALL
|
||||||
|
|
||||||
#include <behaviors.dtsi>
|
#include <behaviors.dtsi>
|
||||||
#include <dt-bindings/zmk/keys.h>
|
#include <dt-bindings/zmk/keys.h>
|
||||||
#include <dt-bindings/zmk/bt.h>
|
#include <dt-bindings/zmk/bt.h>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include <behaviors.dtsi>
|
|
||||||
#include <dt-bindings/zmk/keys.h>
|
#include <dt-bindings/zmk/keys.h>
|
||||||
#include <dt-bindings/zmk/kscan_mock.h>
|
#include <dt-bindings/zmk/kscan_mock.h>
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
||||||
zmk,kscan = &kscan;
|
zmk,kscan = &kscan;
|
||||||
};
|
};
|
||||||
|
|
||||||
kscan: kscan {
|
kscan: native_posix_64_kscan_mock {
|
||||||
compatible = "zmk,kscan-mock";
|
compatible = "zmk,kscan-mock";
|
||||||
|
|
||||||
rows = <2>;
|
rows = <2>;
|
||||||
|
|
|
@ -6,11 +6,21 @@
|
||||||
|
|
||||||
#include <dt-bindings/zmk/matrix_transform.h>
|
#include <dt-bindings/zmk/matrix_transform.h>
|
||||||
|
|
||||||
|
#include <layouts/foostan/corne.dtsi>
|
||||||
|
|
||||||
|
&foostan_corne_6col_layout {
|
||||||
|
transform = <&default_transform>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&foostan_corne_5col_layout {
|
||||||
|
transform = <&five_column_transform>;
|
||||||
|
};
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
chosen {
|
chosen {
|
||||||
zephyr,display = &oled;
|
zephyr,display = &oled;
|
||||||
zmk,kscan = &kscan0;
|
zmk,kscan = &kscan0;
|
||||||
zmk,matrix-transform = &default_transform;
|
zmk,physical-layout = &foostan_corne_6col_layout;
|
||||||
};
|
};
|
||||||
|
|
||||||
default_transform: keymap_transform_0 {
|
default_transform: keymap_transform_0 {
|
||||||
|
@ -29,7 +39,7 @@ RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9)
|
||||||
>;
|
>;
|
||||||
};
|
};
|
||||||
|
|
||||||
five_column_transform: keymap_transform_1 {
|
five_column_transform: transform_1 {
|
||||||
compatible = "zmk,matrix-transform";
|
compatible = "zmk,matrix-transform";
|
||||||
columns = <10>;
|
columns = <10>;
|
||||||
rows = <4>;
|
rows = <4>;
|
||||||
|
|
|
@ -5,12 +5,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <dt-bindings/zmk/matrix_transform.h>
|
#include <dt-bindings/zmk/matrix_transform.h>
|
||||||
|
#include <layouts/cuddlykeyboards/ferris.dtsi>
|
||||||
|
|
||||||
|
&cuddlykeyboards_ferris_layout {
|
||||||
|
transform = <&default_transform>;
|
||||||
|
};
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
|
|
||||||
chosen {
|
chosen {
|
||||||
zmk,kscan = &kscan0;
|
zmk,kscan = &kscan0;
|
||||||
zmk,matrix-transform = &default_transform;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
default_transform: keymap_transform_0 {
|
default_transform: keymap_transform_0 {
|
||||||
|
|
|
@ -6,12 +6,11 @@
|
||||||
|
|
||||||
#include <dt-bindings/zmk/matrix_transform.h>
|
#include <dt-bindings/zmk/matrix_transform.h>
|
||||||
|
|
||||||
|
#include <physical_layouts.dtsi>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
chosen {
|
chosen {
|
||||||
zmk,kscan = &kscan0;
|
zmk,kscan = &kscan0;
|
||||||
zmk,matrix-transform = &default_transform;
|
|
||||||
/delete-property/ zephyr,console;
|
|
||||||
/delete-property/ zephyr,shell-uart;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
default_transform: keymap_transform_0 {
|
default_transform: keymap_transform_0 {
|
||||||
|
@ -51,7 +50,45 @@
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
layout_0: layout_0 {
|
||||||
|
compatible = "zmk,physical-layout";
|
||||||
|
display-name = "Default";
|
||||||
|
|
||||||
|
transform = <&default_transform>;
|
||||||
|
|
||||||
|
keys // w h x y rot rx ry
|
||||||
|
= <&key_physical_attrs 100 100 0 75 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 25 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 0 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 25 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 75 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 600 75 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 700 25 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 800 0 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 25 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 75 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 0 175 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 125 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 125 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 175 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 600 175 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 700 125 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 800 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 125 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 175 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 225 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 225 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 700 225 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 800 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 225 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 325 350 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 425 375 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 575 375 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 675 350 0 0 0>
|
||||||
|
;
|
||||||
};
|
};
|
||||||
|
|
||||||
&xiao_spi { status = "disabled"; };
|
};
|
||||||
&xiao_serial { status = "disabled"; };
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Copyright (c) 2024 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
if SHIELD_MINIVAN_STUDIO_TESTER
|
||||||
|
|
||||||
|
config ZMK_KEYBOARD_NAME
|
||||||
|
default "MiniVan Tester"
|
||||||
|
|
||||||
|
endif
|
9
app/boards/shields/minivan_studio_tester/Kconfig.shield
Normal file
9
app/boards/shields/minivan_studio_tester/Kconfig.shield
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Copyright (c) 2024 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
config SHIELD_MINIVAN_STUDIO_TESTER
|
||||||
|
def_bool $(shields_list_contains,minivan_studio_tester)
|
||||||
|
select ZMK_STUDIO
|
||||||
|
select UART_NATIVE_POSIX_PORT_1_ENABLE
|
||||||
|
select CBPRINTF_LIBC_SUBSTS
|
||||||
|
select ZMK_STUDIO_TRANSPORT_UART
|
|
@ -0,0 +1 @@
|
||||||
|
CONFIG_ZMK_STUDIO_LOCKING=n
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ZMK_BEHAVIORS_KEEP_ALL
|
||||||
|
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
|
||||||
|
#define NAV_L 1
|
||||||
|
#define NUM_L 2
|
||||||
|
#define MED_L 3
|
||||||
|
#define FUN_L 4
|
||||||
|
|
||||||
|
/ {
|
||||||
|
keymap {
|
||||||
|
compatible = "zmk,keymap";
|
||||||
|
|
||||||
|
base_layer {
|
||||||
|
display-name = "Base";
|
||||||
|
bindings = <
|
||||||
|
&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BKSP
|
||||||
|
&gresc &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp RET
|
||||||
|
&kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp QUOT
|
||||||
|
&kp LGUI &kp LALT &mo NAV_L &kp LEFT_SHIFT &kp SPACE &mo NUM_L &kp LALT &kp RCTL
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
nav_layer {
|
||||||
|
display-name = "Nav";
|
||||||
|
bindings = <
|
||||||
|
&trans &trans &trans &trans &trans &trans &trans &kp GRAVE &kp TILDE &trans &trans &kp DEL
|
||||||
|
&trans &trans &trans &trans &trans &trans &trans &kp LARW &kp DARW &kp UARW &kp RARW &trans
|
||||||
|
&trans &trans &trans &trans &trans &trans &trans &kp HOME &kp PG_DN &kp PG_UP &kp END &trans
|
||||||
|
&trans &trans &trans &trans &trans &trans &trans &trans
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
num_layer {
|
||||||
|
display-name = "Num";
|
||||||
|
bindings = <
|
||||||
|
&trans &trans &kp N7 &kp N8 &kp N9 &kp RBKT &trans &trans &trans &trans &trans &trans
|
||||||
|
&trans &kp MINUS &kp N4 &kp N5 &kp N6 &kp EQUAL &trans &trans &trans &trans &trans &trans
|
||||||
|
&kp PLUS &kp N1 &kp N2 &kp N3 &kp N0 &trans &trans &trans &trans &trans &trans &trans
|
||||||
|
&trans &trans &trans &trans &trans &kp ESC &trans &trans
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
med_layer {
|
||||||
|
display-name = "Sym";
|
||||||
|
bindings = <
|
||||||
|
&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
||||||
|
&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
||||||
|
&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
||||||
|
&trans &trans &trans &trans &trans &trans &trans &trans
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,335 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/matrix_transform.h>
|
||||||
|
#include <physical_layouts.dtsi>
|
||||||
|
|
||||||
|
&kscan {
|
||||||
|
/delete-property/ exit-after;
|
||||||
|
events = <>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&uart1 { status = "okay"; };
|
||||||
|
|
||||||
|
/ {
|
||||||
|
chosen {
|
||||||
|
zmk,physical-layout = &standard_layout;
|
||||||
|
zmk,studio-rpc-uart = &uart1;
|
||||||
|
};
|
||||||
|
|
||||||
|
standard_transform: standard_transform {
|
||||||
|
compatible = "zmk,matrix-transform";
|
||||||
|
rows = <4>;
|
||||||
|
columns = <12>;
|
||||||
|
|
||||||
|
map = <
|
||||||
|
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(1,5) RC(1,4) RC(1,3) RC(1,2) RC(1,1) RC(1,0)
|
||||||
|
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(3,5) RC(3,4) RC(3,3) RC(3,2) RC(3,1) RC(3,0)
|
||||||
|
RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,5) RC(5,5) RC(5,4) RC(5,3) RC(5,2) RC(5,1) RC(5,0)
|
||||||
|
RC(6,0) RC(6,1) RC(6,3) RC(6,4) RC(6,5) RC(7,3) RC(7,2) RC(7,0)
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
arrows_transform: arrows_transform {
|
||||||
|
compatible = "zmk,matrix-transform";
|
||||||
|
rows = <4>;
|
||||||
|
columns = <12>;
|
||||||
|
|
||||||
|
map = <
|
||||||
|
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(1,5) RC(1,4) RC(1,3) RC(1,2) RC(1,1) RC(1,0)
|
||||||
|
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(3,5) RC(3,4) RC(3,3) RC(3,2) RC(3,1) RC(3,0)
|
||||||
|
RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,5) RC(5,5) RC(5,4) RC(5,3) RC(5,2) RC(5,1) RC(5,0)
|
||||||
|
RC(6,0) RC(6,1) RC(6,3) RC(6,4) RC(6,5) RC(7,3) RC(7,2) RC(7,1) RC(7,0)
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
southpaw_transform: southpaw_transform {
|
||||||
|
compatible = "zmk,matrix-transform";
|
||||||
|
rows = <4>;
|
||||||
|
columns = <12>;
|
||||||
|
|
||||||
|
map = <
|
||||||
|
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(1,5) RC(1,4) RC(1,3) RC(1,2) RC(1,1) RC(1,0)
|
||||||
|
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(3,5) RC(3,4) RC(3,3) RC(3,2) RC(3,1) RC(3,0)
|
||||||
|
RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,5) RC(5,5) RC(5,4) RC(5,3) RC(5,2) RC(5,1) RC(5,0)
|
||||||
|
RC(6,0) RC(6,1) RC(6,2) RC(6,3) RC(6,4) RC(6,5) RC(7,3) RC(7,2) RC(7,0)
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
jetvan_transform: jetvan_transform {
|
||||||
|
compatible = "zmk,matrix-transform";
|
||||||
|
rows = <4>;
|
||||||
|
columns = <12>;
|
||||||
|
|
||||||
|
map = <
|
||||||
|
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(1,5) RC(1,4) RC(1,3) RC(1,2) RC(1,1) RC(1,0)
|
||||||
|
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(3,5) RC(3,4) RC(3,3) RC(3,2) RC(3,1) RC(3,0)
|
||||||
|
RC(4,0) RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,5) RC(5,5) RC(5,4) RC(5,3) RC(5,2) RC(5,1) RC(5,0)
|
||||||
|
RC(6,0) RC(6,1) RC(6,2) RC(6,4) RC(7,3) RC(7,2) RC(7,0)
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
standard_layout: standard_layout {
|
||||||
|
compatible = "zmk,physical-layout";
|
||||||
|
display-name = "Standard";
|
||||||
|
|
||||||
|
transform = <&standard_transform>;
|
||||||
|
kscan = <&kscan>;
|
||||||
|
|
||||||
|
keys
|
||||||
|
= <&key_physical_attrs 100 100 000 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 500 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 600 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 700 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 800 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 175 100 1100 000 0 0 0>
|
||||||
|
|
||||||
|
, <&key_physical_attrs 125 100 000 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 125 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 225 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 325 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 425 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 525 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 625 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 725 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 825 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 925 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1025 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 150 100 1125 100 0 0 0>
|
||||||
|
|
||||||
|
, <&key_physical_attrs 175 100 000 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 175 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 275 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 375 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 475 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 575 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 675 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 775 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 875 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 975 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1075 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1175 200 0 0 0>
|
||||||
|
|
||||||
|
, <&key_physical_attrs 125 100 000 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 150 100 125 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 125 100 275 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 225 100 400 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 200 100 625 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 125 100 825 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 150 100 950 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 175 100 1100 300 0 0 0>
|
||||||
|
;
|
||||||
|
};
|
||||||
|
|
||||||
|
southpaw_layout: southpaw_layout {
|
||||||
|
compatible = "zmk,physical-layout";
|
||||||
|
display-name = "Southpaw";
|
||||||
|
|
||||||
|
transform = <&southpaw_transform>;
|
||||||
|
kscan = <&kscan>;
|
||||||
|
|
||||||
|
keys
|
||||||
|
= <&key_physical_attrs 100 100 000 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 500 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 600 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 700 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 800 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 175 100 1100 000 0 0 0>
|
||||||
|
|
||||||
|
, <&key_physical_attrs 125 100 000 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 125 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 225 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 325 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 425 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 525 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 625 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 725 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 825 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 925 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1025 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 150 100 1125 100 0 0 0>
|
||||||
|
|
||||||
|
, <&key_physical_attrs 175 100 000 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 175 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 275 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 375 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 475 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 575 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 675 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 775 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 875 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 975 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1075 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1175 200 0 0 0>
|
||||||
|
|
||||||
|
, <&key_physical_attrs 100 100 000 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 225 100 400 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 200 100 625 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 125 100 825 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 150 100 950 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 175 100 1100 300 0 0 0>
|
||||||
|
;
|
||||||
|
};
|
||||||
|
|
||||||
|
arrows_layout: arrows_layout {
|
||||||
|
compatible = "zmk,physical-layout";
|
||||||
|
display-name = "Arrows";
|
||||||
|
|
||||||
|
transform = <&arrows_transform>;
|
||||||
|
kscan = <&kscan>;
|
||||||
|
|
||||||
|
keys
|
||||||
|
= <&key_physical_attrs 100 100 000 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 500 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 600 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 700 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 800 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 175 100 1100 000 0 0 0>
|
||||||
|
|
||||||
|
, <&key_physical_attrs 125 100 000 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 125 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 225 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 325 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 425 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 525 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 625 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 725 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 825 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 925 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1025 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 150 100 1125 100 0 0 0>
|
||||||
|
|
||||||
|
, <&key_physical_attrs 175 100 000 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 175 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 275 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 375 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 475 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 575 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 675 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 775 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 875 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 975 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1075 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1175 200 0 0 0>
|
||||||
|
|
||||||
|
, <&key_physical_attrs 125 100 000 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 150 100 125 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 125 100 275 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 225 100 400 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 200 100 625 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 150 100 825 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 975 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1075 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1175 300 0 0 0>
|
||||||
|
;
|
||||||
|
};
|
||||||
|
|
||||||
|
jetvan_layout: jetvan_layout {
|
||||||
|
compatible = "zmk,physical-layout";
|
||||||
|
display-name = "JetVan";
|
||||||
|
|
||||||
|
transform = <&jetvan_transform>;
|
||||||
|
kscan = <&kscan>;
|
||||||
|
|
||||||
|
keys
|
||||||
|
= <&key_physical_attrs 100 100 000 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 500 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 600 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 700 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 800 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 000 0 0 0>
|
||||||
|
, <&key_physical_attrs 175 100 1100 000 0 0 0>
|
||||||
|
|
||||||
|
, <&key_physical_attrs 125 100 000 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 125 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 225 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 325 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 425 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 525 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 625 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 725 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 825 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 925 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1025 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 150 100 1125 100 0 0 0>
|
||||||
|
|
||||||
|
, <&key_physical_attrs 175 100 000 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 175 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 275 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 375 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 475 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 575 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 675 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 775 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 875 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 975 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1075 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1175 200 0 0 0>
|
||||||
|
|
||||||
|
, <&key_physical_attrs 125 100 000 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 125 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 125 100 225 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 625 100 350 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 975 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1075 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1175 300 0 0 0>
|
||||||
|
;
|
||||||
|
};
|
||||||
|
|
||||||
|
pos_map {
|
||||||
|
compatible = "zmk,physical-layout-position-map";
|
||||||
|
std {
|
||||||
|
physical-layout = <&standard_layout>;
|
||||||
|
positions
|
||||||
|
= < 36 37 38 39 40 41 42 43 >;
|
||||||
|
};
|
||||||
|
|
||||||
|
arrows {
|
||||||
|
physical-layout = <&arrows_layout>;
|
||||||
|
positions
|
||||||
|
= < 36 37 38 39 40 42 43 44 >;
|
||||||
|
};
|
||||||
|
|
||||||
|
southpaw {
|
||||||
|
physical-layout = <&southpaw_layout>;
|
||||||
|
positions
|
||||||
|
= < 36 37 38 40 41 42 43 44 >;
|
||||||
|
};
|
||||||
|
|
||||||
|
jetvan {
|
||||||
|
physical-layout = <&jetvan_layout>;
|
||||||
|
positions
|
||||||
|
= < 36 37 38 666 39 40 41 42 >;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
9
app/boards/shields/posix_pro_micro/Kconfig.defconfig
Normal file
9
app/boards/shields/posix_pro_micro/Kconfig.defconfig
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Copyright (c) 2024 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
if SHIELD_POSIX_PRO_MICRO
|
||||||
|
|
||||||
|
config ZMK_STUDIO
|
||||||
|
select UART_NATIVE_POSIX_PORT_1_ENABLE
|
||||||
|
|
||||||
|
endif
|
5
app/boards/shields/posix_pro_micro/Kconfig.shield
Normal file
5
app/boards/shields/posix_pro_micro/Kconfig.shield
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Copyright (c) 2024 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
config SHIELD_POSIX_PRO_MICRO
|
||||||
|
def_bool $(shields_list_contains,posix_pro_micro)
|
51
app/boards/shields/posix_pro_micro/posix_pro_micro.overlay
Normal file
51
app/boards/shields/posix_pro_micro/posix_pro_micro.overlay
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Pete Johanson
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
/delete-node/ &kscan;
|
||||||
|
|
||||||
|
&uart1 { status = "okay"; };
|
||||||
|
|
||||||
|
/ {
|
||||||
|
chosen {
|
||||||
|
zmk,studio-rpc-uart = &uart1;
|
||||||
|
};
|
||||||
|
|
||||||
|
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 0 0> /* D0 */
|
||||||
|
, <1 0 &gpio0 1 0> /* D1 */
|
||||||
|
, <2 0 &gpio0 2 0> /* D2 */
|
||||||
|
, <3 0 &gpio0 3 0> /* D3 */
|
||||||
|
, <4 0 &gpio0 4 0> /* D4/A6 */
|
||||||
|
, <5 0 &gpio0 5 0> /* D5 */
|
||||||
|
, <6 0 &gpio0 6 0> /* D6/A7 */
|
||||||
|
, <7 0 &gpio0 7 0> /* D7 */
|
||||||
|
, <8 0 &gpio0 8 0> /* D8/A8 */
|
||||||
|
, <9 0 &gpio0 9 0> /* D9/A9 */
|
||||||
|
, <10 0 &gpio0 10 0> /* D10/A10 */
|
||||||
|
, <16 0 &gpio0 11 0> /* D16 */
|
||||||
|
, <14 0 &gpio0 12 0> /* D14 */
|
||||||
|
, <15 0 &gpio0 13 0> /* D15 */
|
||||||
|
, <18 0 &gpio0 14 0> /* D18/A0 */
|
||||||
|
, <19 0 &gpio0 15 0> /* D19/A1 */
|
||||||
|
, <20 0 &gpio0 16 0> /* D20/A2 */
|
||||||
|
, <21 0 &gpio0 17 0> /* D21/A3 */
|
||||||
|
;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pro_micro_i2c: &i2c0 {};
|
||||||
|
pro_micro_spi: &spi0 {};
|
||||||
|
pro_micro_serial: &uart0 {};
|
9
app/boards/shields/posix_seeed_xiao/Kconfig.defconfig
Normal file
9
app/boards/shields/posix_seeed_xiao/Kconfig.defconfig
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Copyright (c) 2024 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
if SHIELD_POSIX_SEEED_XIAO
|
||||||
|
|
||||||
|
config ZMK_STUDIO
|
||||||
|
select UART_NATIVE_POSIX_PORT_1_ENABLE
|
||||||
|
|
||||||
|
endif
|
5
app/boards/shields/posix_seeed_xiao/Kconfig.shield
Normal file
5
app/boards/shields/posix_seeed_xiao/Kconfig.shield
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Copyright (c) 2024 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
config SHIELD_POSIX_SEEED_XIAO
|
||||||
|
def_bool $(shields_list_contains,posix_seeed_xiao)
|
39
app/boards/shields/posix_seeed_xiao/posix_seeed_xiao.overlay
Normal file
39
app/boards/shields/posix_seeed_xiao/posix_seeed_xiao.overlay
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
/delete-node/ &kscan;
|
||||||
|
|
||||||
|
&uart1 { status = "okay"; };
|
||||||
|
|
||||||
|
/ {
|
||||||
|
chosen {
|
||||||
|
zmk,studio-rpc-uart = &uart1;
|
||||||
|
};
|
||||||
|
|
||||||
|
xiao_d: connector {
|
||||||
|
compatible = "seeed,xiao-gpio";
|
||||||
|
#gpio-cells = <2>;
|
||||||
|
gpio-map-mask = <0xffffffff 0xffffffc0>;
|
||||||
|
gpio-map-pass-thru = <0 0x3f>;
|
||||||
|
gpio-map
|
||||||
|
= <0 0 &gpio0 0 0> /* D0 */
|
||||||
|
, <1 0 &gpio0 1 0> /* D1 */
|
||||||
|
, <2 0 &gpio0 2 0> /* D2 */
|
||||||
|
, <3 0 &gpio0 3 0> /* D3 */
|
||||||
|
, <4 0 &gpio0 4 0> /* D4 */
|
||||||
|
, <5 0 &gpio0 5 0> /* D5 */
|
||||||
|
, <6 0 &gpio0 6 0> /* D6 */
|
||||||
|
, <7 0 &gpio0 7 0> /* D7 */
|
||||||
|
, <8 0 &gpio0 8 0> /* D8 */
|
||||||
|
, <9 0 &gpio0 9 0> /* D9 */
|
||||||
|
, <10 0 &gpio0 10 0> /* D10 */
|
||||||
|
;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
xiao_i2c: &i2c0 {};
|
||||||
|
xiao_spi: &spi0 {};
|
||||||
|
xiao_serial: &uart0 {};
|
|
@ -5,12 +5,16 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <dt-bindings/zmk/matrix_transform.h>
|
#include <dt-bindings/zmk/matrix_transform.h>
|
||||||
|
#include <layouts/josefadamcik/sofle.dtsi>
|
||||||
|
|
||||||
|
&josefadamcik_sofle_layout {
|
||||||
|
transform = <&default_transform>;
|
||||||
|
};
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
chosen {
|
chosen {
|
||||||
zephyr,display = &oled;
|
zephyr,display = &oled;
|
||||||
zmk,kscan = &kscan0;
|
zmk,kscan = &kscan0;
|
||||||
zmk,matrix-transform = &default_transform;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
default_transform: keymap_transform_0 {
|
default_transform: keymap_transform_0 {
|
||||||
|
|
|
@ -6,11 +6,20 @@
|
||||||
|
|
||||||
#include <dt-bindings/zmk/matrix_transform.h>
|
#include <dt-bindings/zmk/matrix_transform.h>
|
||||||
|
|
||||||
|
#include <layouts/foostan/corne.dtsi>
|
||||||
|
|
||||||
|
&foostan_corne_6col_layout {
|
||||||
|
transform = <&default_transform>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&foostan_corne_5col_layout {
|
||||||
|
transform = <&five_column_transform>;
|
||||||
|
};
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
|
|
||||||
chosen {
|
chosen {
|
||||||
zephyr,display = &oled;
|
zephyr,display = &oled;
|
||||||
zmk,matrix-transform = &default_transform;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
default_transform: keymap_transform_0 {
|
default_transform: keymap_transform_0 {
|
||||||
|
|
|
@ -6,11 +6,16 @@
|
||||||
|
|
||||||
#include <dt-bindings/zmk/matrix_transform.h>
|
#include <dt-bindings/zmk/matrix_transform.h>
|
||||||
|
|
||||||
|
#include <layouts/josefadamcik/sofle.dtsi>
|
||||||
|
|
||||||
|
&josefadamcik_sofle_layout {
|
||||||
|
transform = <&default_transform>;
|
||||||
|
};
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
|
|
||||||
chosen {
|
chosen {
|
||||||
zephyr,display = &oled;
|
zephyr,display = &oled;
|
||||||
zmk,matrix-transform = &default_transform;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
default_transform: keymap_transform_0 {
|
default_transform: keymap_transform_0 {
|
||||||
|
|
|
@ -6,11 +6,15 @@
|
||||||
|
|
||||||
#include <dt-bindings/zmk/matrix_transform.h>
|
#include <dt-bindings/zmk/matrix_transform.h>
|
||||||
|
|
||||||
/ {
|
#include <layouts/cuddlykeyboards/ferris.dtsi>
|
||||||
|
|
||||||
|
&cuddlykeyboards_ferris_layout {
|
||||||
|
transform = <&default_transform>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/ {
|
||||||
chosen {
|
chosen {
|
||||||
zephyr,display = &oled;
|
zephyr,display = &oled;
|
||||||
zmk,matrix-transform = &default_transform;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
default_transform: keymap_transform_0 {
|
default_transform: keymap_transform_0 {
|
||||||
|
|
|
@ -4,10 +4,15 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/behaviors.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
|
#if ZMK_BEHAVIOR_OMIT(BL)
|
||||||
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
// Behavior can be invoked on peripherals, so name must be <= 8 characters.
|
// Behavior can be invoked on peripherals, so name must be <= 8 characters.
|
||||||
/omit-if-no-ref/ bl: bcklight {
|
bl: bcklight {
|
||||||
compatible = "zmk,behavior-backlight";
|
compatible = "zmk,behavior-backlight";
|
||||||
#binding-cells = <2>;
|
#binding-cells = <2>;
|
||||||
display-name = "Backlight";
|
display-name = "Backlight";
|
||||||
|
|
|
@ -4,9 +4,14 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/behaviors.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
/omit-if-no-ref/ bt: bluetooth {
|
#if ZMK_BEHAVIOR_OMIT(BT)
|
||||||
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
|
bt: bluetooth {
|
||||||
compatible = "zmk,behavior-bluetooth";
|
compatible = "zmk,behavior-bluetooth";
|
||||||
#binding-cells = <2>;
|
#binding-cells = <2>;
|
||||||
display-name = "Bluetooth";
|
display-name = "Bluetooth";
|
||||||
|
|
|
@ -4,11 +4,15 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/behaviors.h>
|
||||||
#include <dt-bindings/zmk/keys.h>
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
/omit-if-no-ref/ caps_word: caps_word {
|
#if ZMK_BEHAVIOR_OMIT(CAPS_WORD)
|
||||||
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
|
caps_word: caps_word {
|
||||||
compatible = "zmk,behavior-caps-word";
|
compatible = "zmk,behavior-caps-word";
|
||||||
#binding-cells = <0>;
|
#binding-cells = <0>;
|
||||||
continue-list = <UNDERSCORE BACKSPACE DELETE>;
|
continue-list = <UNDERSCORE BACKSPACE DELETE>;
|
||||||
|
|
|
@ -4,11 +4,16 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/behaviors.h>
|
||||||
#include <dt-bindings/zmk/keys.h>
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
/omit-if-no-ref/ gresc: grave_escape {
|
#if ZMK_BEHAVIOR_OMIT(GRESC)
|
||||||
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
|
gresc: grave_escape {
|
||||||
compatible = "zmk,behavior-mod-morph";
|
compatible = "zmk,behavior-mod-morph";
|
||||||
#binding-cells = <0>;
|
#binding-cells = <0>;
|
||||||
bindings = <&kp ESC>, <&kp GRAVE>;
|
bindings = <&kp ESC>, <&kp GRAVE>;
|
||||||
|
|
|
@ -4,10 +4,14 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/behaviors.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
/* DEPRECATED: `cp` will be removed in the future */
|
#if ZMK_BEHAVIOR_OMIT(KP)
|
||||||
/omit-if-no-ref/ cp: kp: key_press {
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
|
kp: key_press {
|
||||||
compatible = "zmk,behavior-key-press";
|
compatible = "zmk,behavior-key-press";
|
||||||
#binding-cells = <1>;
|
#binding-cells = <1>;
|
||||||
display-name = "Key Press";
|
display-name = "Key Press";
|
||||||
|
|
|
@ -4,11 +4,15 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/behaviors.h>
|
||||||
#include <dt-bindings/zmk/keys.h>
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
/omit-if-no-ref/ key_repeat: key_repeat {
|
#if ZMK_BEHAVIOR_OMIT(KEY_REPEAT)
|
||||||
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
|
key_repeat: key_repeat {
|
||||||
compatible = "zmk,behavior-key-repeat";
|
compatible = "zmk,behavior-key-repeat";
|
||||||
#binding-cells = <0>;
|
#binding-cells = <0>;
|
||||||
usage-pages = <HID_USAGE_KEY>;
|
usage-pages = <HID_USAGE_KEY>;
|
||||||
|
|
|
@ -4,9 +4,14 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/behaviors.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
/omit-if-no-ref/ kt: key_toggle {
|
#if ZMK_BEHAVIOR_OMIT(KT)
|
||||||
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
|
kt: key_toggle {
|
||||||
compatible = "zmk,behavior-key-toggle";
|
compatible = "zmk,behavior-key-toggle";
|
||||||
#binding-cells = <1>;
|
#binding-cells = <1>;
|
||||||
display-name = "Key Toggle";
|
display-name = "Key Toggle";
|
||||||
|
|
|
@ -4,9 +4,14 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/behaviors.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
/omit-if-no-ref/ lt: layer_tap {
|
#if ZMK_BEHAVIOR_OMIT(LT)
|
||||||
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
|
lt: layer_tap {
|
||||||
compatible = "zmk,behavior-hold-tap";
|
compatible = "zmk,behavior-hold-tap";
|
||||||
#binding-cells = <2>;
|
#binding-cells = <2>;
|
||||||
flavor = "tap-preferred";
|
flavor = "tap-preferred";
|
||||||
|
|
|
@ -4,9 +4,14 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/behaviors.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
/omit-if-no-ref/ mt: mod_tap {
|
#if ZMK_BEHAVIOR_OMIT(MT)
|
||||||
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
|
mt: mod_tap {
|
||||||
compatible = "zmk,behavior-hold-tap";
|
compatible = "zmk,behavior-hold-tap";
|
||||||
#binding-cells = <2>;
|
#binding-cells = <2>;
|
||||||
flavor = "hold-preferred";
|
flavor = "hold-preferred";
|
||||||
|
|
|
@ -4,9 +4,14 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/behaviors.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
/omit-if-no-ref/ mo: momentary_layer {
|
#if ZMK_BEHAVIOR_OMIT(MO)
|
||||||
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
|
mo: momentary_layer {
|
||||||
compatible = "zmk,behavior-momentary-layer";
|
compatible = "zmk,behavior-momentary-layer";
|
||||||
#binding-cells = <1>;
|
#binding-cells = <1>;
|
||||||
display-name = "Momentary Layer";
|
display-name = "Momentary Layer";
|
||||||
|
|
|
@ -1,6 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/behaviors.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
/omit-if-no-ref/ mkp: mouse_key_press {
|
#if ZMK_BEHAVIOR_OMIT(MKP)
|
||||||
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
|
mkp: mouse_key_press {
|
||||||
compatible = "zmk,behavior-mouse-key-press";
|
compatible = "zmk,behavior-mouse-key-press";
|
||||||
#binding-cells = <1>;
|
#binding-cells = <1>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,9 +4,14 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/behaviors.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
/omit-if-no-ref/ none: none {
|
#if ZMK_BEHAVIOR_OMIT(NONE)
|
||||||
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
|
none: none {
|
||||||
compatible = "zmk,behavior-none";
|
compatible = "zmk,behavior-none";
|
||||||
#binding-cells = <0>;
|
#binding-cells = <0>;
|
||||||
display-name = "None";
|
display-name = "None";
|
||||||
|
|
|
@ -4,9 +4,14 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/behaviors.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
/omit-if-no-ref/ out: outputs {
|
#if ZMK_BEHAVIOR_OMIT(OUT)
|
||||||
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
|
out: outputs {
|
||||||
compatible = "zmk,behavior-outputs";
|
compatible = "zmk,behavior-outputs";
|
||||||
#binding-cells = <1>;
|
#binding-cells = <1>;
|
||||||
display-name = "Output Selection";
|
display-name = "Output Selection";
|
||||||
|
|
|
@ -4,9 +4,14 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/behaviors.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
/omit-if-no-ref/ soft_off: z_so_off {
|
#if ZMK_BEHAVIOR_OMIT(SOFT_OFF)
|
||||||
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
|
soft_off: z_so_off {
|
||||||
compatible = "zmk,behavior-soft-off";
|
compatible = "zmk,behavior-soft-off";
|
||||||
#binding-cells = <0>;
|
#binding-cells = <0>;
|
||||||
split-peripheral-off-on-press;
|
split-peripheral-off-on-press;
|
||||||
|
|
|
@ -4,9 +4,14 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/behaviors.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
/omit-if-no-ref/ sk: sticky_key {
|
#if ZMK_BEHAVIOR_OMIT(SK)
|
||||||
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
|
sk: sticky_key {
|
||||||
compatible = "zmk,behavior-sticky-key";
|
compatible = "zmk,behavior-sticky-key";
|
||||||
#binding-cells = <1>;
|
#binding-cells = <1>;
|
||||||
release-after-ms = <1000>;
|
release-after-ms = <1000>;
|
||||||
|
@ -14,7 +19,10 @@
|
||||||
ignore-modifiers;
|
ignore-modifiers;
|
||||||
display-name = "Sticky Key";
|
display-name = "Sticky Key";
|
||||||
};
|
};
|
||||||
/omit-if-no-ref/ sl: sticky_layer {
|
#if ZMK_BEHAVIOR_OMIT(STICKY_LAYER)
|
||||||
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
|
sl: sticky_layer {
|
||||||
compatible = "zmk,behavior-sticky-key";
|
compatible = "zmk,behavior-sticky-key";
|
||||||
#binding-cells = <1>;
|
#binding-cells = <1>;
|
||||||
release-after-ms = <1000>;
|
release-after-ms = <1000>;
|
||||||
|
|
|
@ -4,9 +4,14 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/behaviors.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
/omit-if-no-ref/ to: to_layer {
|
#if ZMK_BEHAVIOR_OMIT(TO)
|
||||||
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
|
to: to_layer {
|
||||||
compatible = "zmk,behavior-to-layer";
|
compatible = "zmk,behavior-to-layer";
|
||||||
#binding-cells = <1>;
|
#binding-cells = <1>;
|
||||||
display-name = "To Layer";
|
display-name = "To Layer";
|
||||||
|
|
|
@ -4,9 +4,14 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/behaviors.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
/omit-if-no-ref/ tog: toggle_layer {
|
#if ZMK_BEHAVIOR_OMIT(TOG)
|
||||||
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
|
tog: toggle_layer {
|
||||||
compatible = "zmk,behavior-toggle-layer";
|
compatible = "zmk,behavior-toggle-layer";
|
||||||
#binding-cells = <1>;
|
#binding-cells = <1>;
|
||||||
display-name = "Toggle Layer";
|
display-name = "Toggle Layer";
|
||||||
|
|
|
@ -4,9 +4,14 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/behaviors.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
/omit-if-no-ref/ trans: transparent {
|
#if ZMK_BEHAVIOR_OMIT(TRANS)
|
||||||
|
/omit-if-no-ref/
|
||||||
|
#endif
|
||||||
|
trans: transparent {
|
||||||
compatible = "zmk,behavior-transparent";
|
compatible = "zmk,behavior-transparent";
|
||||||
#binding-cells = <0>;
|
#binding-cells = <0>;
|
||||||
display-name = "Transparent";
|
display-name = "Transparent";
|
||||||
|
|
45
app/dts/layouts/cuddlykeyboards/ferris.dtsi
Normal file
45
app/dts/layouts/cuddlykeyboards/ferris.dtsi
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#include <physical_layouts.dtsi>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
cuddlykeyboards_ferris_layout: cuddlykeyboards_ferris_layout {
|
||||||
|
compatible = "zmk,physical-layout";
|
||||||
|
display-name = "Default";
|
||||||
|
|
||||||
|
keys // w h x y rot rx ry
|
||||||
|
= <&key_physical_attrs 100 100 0 95 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 32 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 0 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 28 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 42 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 700 42 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 800 28 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 0 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 32 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1100 95 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 0 195 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 132 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 129 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 142 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 700 142 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 800 129 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 132 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1100 195 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 0 295 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 231 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 229 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 242 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 700 242 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 800 229 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 231 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1100 295 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 330 355 1500 430 455>
|
||||||
|
, <&key_physical_attrs 100 100 430 355 3000 430 455>
|
||||||
|
, <&key_physical_attrs 100 100 670 355 (-3000) 770 455>
|
||||||
|
, <&key_physical_attrs 100 100 770 355 (-1500) 770 455>
|
||||||
|
;
|
||||||
|
};
|
||||||
|
};
|
121
app/dts/layouts/foostan/corne.dtsi
Normal file
121
app/dts/layouts/foostan/corne.dtsi
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
#include <physical_layouts.dtsi>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
foostan_corne_6col_layout: foostan_corne_6col_layout {
|
||||||
|
compatible = "zmk,physical-layout";
|
||||||
|
display-name = "6-column";
|
||||||
|
|
||||||
|
keys // w h x y rot rx ry
|
||||||
|
= <&key_physical_attrs 100 100 0 37 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 37 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 12 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 0 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 12 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 500 24 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 800 24 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 12 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 0 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1100 12 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1200 37 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1300 37 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 0 137 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 137 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 112 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 112 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 500 124 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 800 124 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 112 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1100 112 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1200 137 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1300 137 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 0 237 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 237 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 212 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 212 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 500 224 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 800 224 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 212 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1100 212 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1200 237 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1300 237 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 350 312 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 450 312 1200 450 412>
|
||||||
|
, <&key_physical_attrs 100 150 548 283 2400 548 433>
|
||||||
|
, <&key_physical_attrs 100 150 752 283 (-2400) 852 433>
|
||||||
|
, <&key_physical_attrs 100 100 850 312 (-1200) 950 412>
|
||||||
|
, <&key_physical_attrs 100 100 950 312 0 0 0>
|
||||||
|
;
|
||||||
|
};
|
||||||
|
|
||||||
|
foostan_corne_5col_layout: foostan_corne_5col_layout {
|
||||||
|
compatible = "zmk,physical-layout";
|
||||||
|
display-name = "5-column";
|
||||||
|
|
||||||
|
keys // w h x y rot rx ry
|
||||||
|
= <&key_physical_attrs 100 100 0 37 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 12 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 0 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 12 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 24 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 700 24 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 800 12 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 0 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 12 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1100 37 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 0 137 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 112 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 112 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 124 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 700 124 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 800 112 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 112 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1100 137 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 0 237 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 212 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 212 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 224 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 700 224 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 800 212 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 212 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1100 237 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 250 312 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 350 312 1200 350 412>
|
||||||
|
, <&key_physical_attrs 100 150 448 283 2400 448 433>
|
||||||
|
, <&key_physical_attrs 100 150 652 283 (-2400) 752 433>
|
||||||
|
, <&key_physical_attrs 100 100 750 312 (-1200) 850 412>
|
||||||
|
, <&key_physical_attrs 100 100 850 312 0 0 0>
|
||||||
|
;
|
||||||
|
};
|
||||||
|
|
||||||
|
foostan_corne_position_map {
|
||||||
|
compatible = "zmk,physical-layout-position-map";
|
||||||
|
|
||||||
|
complete;
|
||||||
|
|
||||||
|
twelve {
|
||||||
|
physical-layout = <&foostan_corne_6col_layout>;
|
||||||
|
positions
|
||||||
|
= < 0 1 2 3 4 5 6 7 8 9 10 11>
|
||||||
|
, <12 13 14 15 16 17 18 19 20 21 22 23>
|
||||||
|
, <24 25 26 27 28 29 30 31 32 33 34 35>
|
||||||
|
, < 36 37 38 39 40 41 >;
|
||||||
|
};
|
||||||
|
|
||||||
|
ten {
|
||||||
|
physical-layout = <&foostan_corne_5col_layout>;
|
||||||
|
positions
|
||||||
|
= <36 0 1 2 3 4 5 6 7 8 9 37>
|
||||||
|
, <38 10 11 12 13 14 15 16 17 18 19 39>
|
||||||
|
, <40 20 21 22 23 24 25 26 27 28 29 41>
|
||||||
|
, < 30 31 32 33 34 35 >;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
71
app/dts/layouts/josefadamcik/sofle.dtsi
Normal file
71
app/dts/layouts/josefadamcik/sofle.dtsi
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
#include <physical_layouts.dtsi>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
josefadamcik_sofle_layout: josefadamcik_sofle_layout {
|
||||||
|
compatible = "zmk,physical-layout";
|
||||||
|
display-name = "Sofle";
|
||||||
|
|
||||||
|
keys // w h x y rot rx ry
|
||||||
|
= <&key_physical_attrs 100 100 0 37 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 37 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 12 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 0 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 12 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 500 24 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 24 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 12 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1100 0 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1200 12 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1300 37 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1400 37 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 0 137 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 137 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 112 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 112 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 500 124 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 124 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 112 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1100 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1200 112 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1300 137 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1400 137 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 0 237 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 237 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 212 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 212 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 500 224 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 224 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 212 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1100 200 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1200 212 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1300 237 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1400 237 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 0 337 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 337 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 200 312 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 300 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 400 312 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 500 324 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 600 274 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 800 274 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 900 324 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1000 312 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1100 300 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1200 312 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1300 337 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1400 337 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 175 437 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 275 412 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 375 412 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 490 412 1200 490 412>
|
||||||
|
, <&key_physical_attrs 100 150 600 383 2400 600 433>
|
||||||
|
, <&key_physical_attrs 100 150 800 383 (-2400) 900 433>
|
||||||
|
, <&key_physical_attrs 100 100 910 412 (-1200) 1010 412>
|
||||||
|
, <&key_physical_attrs 100 100 1025 412 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1125 412 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 1225 437 0 0 0>
|
||||||
|
;
|
||||||
|
};
|
||||||
|
};
|
9
app/include/dt-bindings/zmk/behaviors.h
Normal file
9
app/include/dt-bindings/zmk/behaviors.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ZMK_BEHAVIOR_OMIT(_name) \
|
||||||
|
!(defined(ZMK_BEHAVIORS_KEEP_##_name) || \
|
||||||
|
(defined(ZMK_BEHAVIORS_KEEP_ALL) && !defined(ZMK_BEHAVIORS_OMIT_##_name)))
|
9
app/include/linker/zmk-rpc-subsystem-settings-reset.ld
Normal file
9
app/include/linker/zmk-rpc-subsystem-settings-reset.ld
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/linker/linker-defs.h>
|
||||||
|
|
||||||
|
ITERABLE_SECTION_ROM(zmk_rpc_subsystem_settings_reset, 4)
|
|
@ -12,17 +12,63 @@
|
||||||
#define ZMK_KEYMAP_LAYERS_LEN \
|
#define ZMK_KEYMAP_LAYERS_LEN \
|
||||||
(DT_FOREACH_CHILD(DT_INST(0, zmk_keymap), ZMK_LAYER_CHILD_LEN_PLUS_ONE) 0)
|
(DT_FOREACH_CHILD(DT_INST(0, zmk_keymap), ZMK_LAYER_CHILD_LEN_PLUS_ONE) 0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A layer ID is a stable identifier to refer to a layer, regardless of ordering.
|
||||||
|
*/
|
||||||
|
typedef uint8_t zmk_keymap_layer_id_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A way to return/reference a missing or invalid layer ID
|
||||||
|
*/
|
||||||
|
#define ZMK_KEYMAP_LAYER_ID_INVAL UINT8_MAX
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A layer index is a identifier to refer layer at a particular position in the order.
|
||||||
|
*/
|
||||||
|
typedef uint8_t zmk_keymap_layer_index_t;
|
||||||
|
|
||||||
typedef uint32_t zmk_keymap_layers_state_t;
|
typedef uint32_t zmk_keymap_layers_state_t;
|
||||||
|
|
||||||
uint8_t zmk_keymap_layer_default(void);
|
zmk_keymap_layer_id_t zmk_keymap_layer_index_to_id(zmk_keymap_layer_index_t layer_index);
|
||||||
|
|
||||||
|
zmk_keymap_layer_id_t zmk_keymap_layer_default(void);
|
||||||
zmk_keymap_layers_state_t zmk_keymap_layer_state(void);
|
zmk_keymap_layers_state_t zmk_keymap_layer_state(void);
|
||||||
bool zmk_keymap_layer_active(uint8_t layer);
|
bool zmk_keymap_layer_active(zmk_keymap_layer_id_t layer);
|
||||||
uint8_t zmk_keymap_highest_layer_active(void);
|
zmk_keymap_layer_id_t zmk_keymap_highest_layer_active(void);
|
||||||
int zmk_keymap_layer_activate(uint8_t layer);
|
int zmk_keymap_layer_activate(zmk_keymap_layer_id_t layer);
|
||||||
int zmk_keymap_layer_deactivate(uint8_t layer);
|
int zmk_keymap_layer_deactivate(zmk_keymap_layer_id_t layer);
|
||||||
int zmk_keymap_layer_toggle(uint8_t layer);
|
int zmk_keymap_layer_toggle(zmk_keymap_layer_id_t layer);
|
||||||
int zmk_keymap_layer_to(uint8_t layer);
|
int zmk_keymap_layer_to(zmk_keymap_layer_id_t layer);
|
||||||
const char *zmk_keymap_layer_name(uint8_t layer);
|
const char *zmk_keymap_layer_name(zmk_keymap_layer_id_t layer);
|
||||||
|
|
||||||
|
const struct zmk_behavior_binding *zmk_keymap_get_layer_binding_at_idx(zmk_keymap_layer_id_t layer,
|
||||||
|
uint8_t binding_idx);
|
||||||
|
int zmk_keymap_set_layer_binding_at_idx(zmk_keymap_layer_id_t layer, uint8_t binding_idx,
|
||||||
|
const struct zmk_behavior_binding binding);
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)
|
||||||
|
|
||||||
|
int zmk_keymap_add_layer(void);
|
||||||
|
int zmk_keymap_remove_layer(zmk_keymap_layer_index_t index);
|
||||||
|
int zmk_keymap_restore_layer(zmk_keymap_layer_id_t id, zmk_keymap_layer_index_t at_index);
|
||||||
|
|
||||||
|
int zmk_keymap_move_layer(zmk_keymap_layer_index_t start_idx, zmk_keymap_layer_index_t dest_idx);
|
||||||
|
|
||||||
|
int zmk_keymap_set_layer_name(zmk_keymap_layer_id_t id, const char *name, size_t size);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if there are any unsaved keymap changes.
|
||||||
|
*
|
||||||
|
* @retval 0 if there are no changes.
|
||||||
|
* @retval 1 if there are changes.
|
||||||
|
*/
|
||||||
|
int zmk_keymap_check_unsaved_changes(void);
|
||||||
|
|
||||||
|
int zmk_keymap_save_changes(void);
|
||||||
|
int zmk_keymap_discard_changes(void);
|
||||||
|
int zmk_keymap_reset_settings(void);
|
||||||
|
|
||||||
int zmk_keymap_position_state_changed(uint8_t source, uint32_t position, bool pressed,
|
int zmk_keymap_position_state_changed(uint8_t source, uint32_t position, bool pressed,
|
||||||
int64_t timestamp);
|
int64_t timestamp);
|
||||||
|
|
|
@ -40,4 +40,5 @@ int zmk_physical_layouts_check_unsaved_selection(void);
|
||||||
int zmk_physical_layouts_save_selected(void);
|
int zmk_physical_layouts_save_selected(void);
|
||||||
int zmk_physical_layouts_revert_selected(void);
|
int zmk_physical_layouts_revert_selected(void);
|
||||||
|
|
||||||
int zmk_physical_layouts_get_position_map(uint8_t source, uint8_t dest, uint32_t *map);
|
int zmk_physical_layouts_get_position_map(uint8_t source, uint8_t dest, size_t map_size,
|
||||||
|
uint32_t map[map_size]);
|
||||||
|
|
|
@ -56,6 +56,12 @@ struct zmk_rpc_subsystem_handler {
|
||||||
enum zmk_studio_rpc_handler_security security;
|
enum zmk_studio_rpc_handler_security security;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef int (*zmk_rpc_subsystem_settings_reset_func)(void);
|
||||||
|
|
||||||
|
struct zmk_rpc_subsystem_settings_reset {
|
||||||
|
zmk_rpc_subsystem_settings_reset_func callback;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Generate a "meta" subsystem response indicating an "empty" response to an RPC request.
|
* @brief Generate a "meta" subsystem response indicating an "empty" response to an RPC request.
|
||||||
*/
|
*/
|
||||||
|
@ -103,6 +109,14 @@ struct zmk_rpc_subsystem_handler {
|
||||||
.security = _security, \
|
.security = _security, \
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ZMK_RPC_SUBSYSTEM_SETTINGS_RESET(prefix, _callback) \
|
||||||
|
STRUCT_SECTION_ITERABLE(zmk_rpc_subsystem_settings_reset, _##prefix##_settings_reset) = { \
|
||||||
|
.callback = _callback, \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ZMK_RPC_SUBSYSTEM_SETTINGS_RESET_FOREACH(_var) \
|
||||||
|
STRUCT_SECTION_FOREACH(zmk_rpc_subsystem_settings_reset, _var)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a zmk_studio_Notification struct for the given subsystem and type, including
|
* @brief Create a zmk_studio_Notification struct for the given subsystem and type, including
|
||||||
initialization of the inner fields.
|
initialization of the inner fields.
|
||||||
|
|
|
@ -3,5 +3,6 @@
|
||||||
|
|
||||||
name: studio-rpc-usb-uart
|
name: studio-rpc-usb-uart
|
||||||
append:
|
append:
|
||||||
|
DTS_EXTRA_CPPFLAGS: -DZMK_BEHAVIORS_KEEP_ALL
|
||||||
EXTRA_DTC_OVERLAY_FILE: studio-rpc-usb-uart.overlay
|
EXTRA_DTC_OVERLAY_FILE: studio-rpc-usb-uart.overlay
|
||||||
EXTRA_CONF_FILE: studio-rpc-usb-uart.conf
|
EXTRA_CONF_FILE: studio-rpc-usb-uart.conf
|
||||||
|
|
652
app/src/keymap.c
652
app/src/keymap.c
|
@ -6,10 +6,12 @@
|
||||||
|
|
||||||
#include <drivers/behavior.h>
|
#include <drivers/behavior.h>
|
||||||
#include <zephyr/sys/util.h>
|
#include <zephyr/sys/util.h>
|
||||||
|
#include <zephyr/settings/settings.h>
|
||||||
#include <zephyr/bluetooth/bluetooth.h>
|
#include <zephyr/bluetooth/bluetooth.h>
|
||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
|
#include <zmk/stdlib.h>
|
||||||
#include <zmk/behavior.h>
|
#include <zmk/behavior.h>
|
||||||
#include <zmk/keymap.h>
|
#include <zmk/keymap.h>
|
||||||
#include <zmk/matrix.h>
|
#include <zmk/matrix.h>
|
||||||
|
@ -27,7 +29,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
#include <zmk/events/sensor_event.h>
|
#include <zmk/events/sensor_event.h>
|
||||||
|
|
||||||
static zmk_keymap_layers_state_t _zmk_keymap_layer_state = 0;
|
static zmk_keymap_layers_state_t _zmk_keymap_layer_state = 0;
|
||||||
static uint8_t _zmk_keymap_layer_default = 0;
|
static zmk_keymap_layer_id_t _zmk_keymap_layer_default = 0;
|
||||||
|
|
||||||
#define DT_DRV_COMPAT zmk_keymap
|
#define DT_DRV_COMPAT zmk_keymap
|
||||||
|
|
||||||
|
@ -38,7 +40,11 @@ static uint8_t _zmk_keymap_layer_default = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TRANSFORMED_LAYER(node) \
|
#define TRANSFORMED_LAYER(node) \
|
||||||
{ LISTIFY(DT_PROP_LEN(node, bindings), ZMK_KEYMAP_EXTRACT_BINDING, (, ), node) }
|
{ \
|
||||||
|
COND_CODE_1( \
|
||||||
|
DT_NODE_HAS_PROP(node, bindings), \
|
||||||
|
(LISTIFY(DT_PROP_LEN(node, bindings), ZMK_KEYMAP_EXTRACT_BINDING, (, ), node)), ()) \
|
||||||
|
}
|
||||||
|
|
||||||
#if ZMK_KEYMAP_HAS_SENSORS
|
#if ZMK_KEYMAP_HAS_SENSORS
|
||||||
#define _TRANSFORM_SENSOR_ENTRY(idx, layer) \
|
#define _TRANSFORM_SENSOR_ENTRY(idx, layer) \
|
||||||
|
@ -58,7 +64,7 @@ static uint8_t _zmk_keymap_layer_default = 0;
|
||||||
|
|
||||||
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
||||||
|
|
||||||
#define LAYER_NAME(node) DT_PROP_OR(node, display_name, DT_PROP_OR(node, label, NULL))
|
#define LAYER_NAME(node) DT_PROP_OR(node, display_name, DT_PROP_OR(node, label, ""))
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
|
@ -67,12 +73,36 @@ static uint8_t _zmk_keymap_layer_default = 0;
|
||||||
// still send the release event to the behavior in that layer also.
|
// still send the release event to the behavior in that layer also.
|
||||||
static uint32_t zmk_keymap_active_behavior_layer[ZMK_KEYMAP_LEN];
|
static uint32_t zmk_keymap_active_behavior_layer[ZMK_KEYMAP_LEN];
|
||||||
|
|
||||||
static struct zmk_behavior_binding zmk_keymap[ZMK_KEYMAP_LAYERS_LEN][ZMK_KEYMAP_LEN] = {
|
#if IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)
|
||||||
DT_INST_FOREACH_CHILD_SEP(0, TRANSFORMED_LAYER, (, ))};
|
|
||||||
|
static uint8_t keymap_layer_orders[ZMK_KEYMAP_LAYERS_LEN];
|
||||||
|
|
||||||
|
#endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)
|
||||||
|
|
||||||
|
#define KEYMAP_VAR(_name, _opts) \
|
||||||
|
static _opts struct zmk_behavior_binding _name[ZMK_KEYMAP_LAYERS_LEN][ZMK_KEYMAP_LEN] = { \
|
||||||
|
COND_CODE_1(IS_ENABLED(CONFIG_ZMK_STUDIO), \
|
||||||
|
(DT_INST_FOREACH_CHILD_SEP(0, TRANSFORMED_LAYER, (, ))), \
|
||||||
|
(DT_INST_FOREACH_CHILD_STATUS_OKAY_SEP(0, TRANSFORMED_LAYER, (, ))))};
|
||||||
|
|
||||||
|
KEYMAP_VAR(zmk_keymap, )
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE)
|
||||||
|
|
||||||
|
KEYMAP_VAR(zmk_stock_keymap, const)
|
||||||
|
|
||||||
|
static char zmk_keymap_layer_names[ZMK_KEYMAP_LAYERS_LEN][CONFIG_ZMK_KEYMAP_LAYER_NAME_MAX_LEN] = {
|
||||||
|
DT_INST_FOREACH_CHILD_SEP(0, LAYER_NAME, (, ))};
|
||||||
|
|
||||||
|
static uint32_t changed_layer_names = 0;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
static const char *zmk_keymap_layer_names[ZMK_KEYMAP_LAYERS_LEN] = {
|
static const char *zmk_keymap_layer_names[ZMK_KEYMAP_LAYERS_LEN] = {
|
||||||
DT_INST_FOREACH_CHILD_SEP(0, LAYER_NAME, (, ))};
|
DT_INST_FOREACH_CHILD_SEP(0, LAYER_NAME, (, ))};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ZMK_KEYMAP_HAS_SENSORS
|
#if ZMK_KEYMAP_HAS_SENSORS
|
||||||
|
|
||||||
static struct zmk_behavior_binding
|
static struct zmk_behavior_binding
|
||||||
|
@ -81,23 +111,50 @@ static struct zmk_behavior_binding
|
||||||
|
|
||||||
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
||||||
|
|
||||||
static inline int set_layer_state(uint8_t layer, bool state) {
|
#define ASSERT_LAYER_VAL(_layer, _fail_ret) \
|
||||||
|
if ((_layer) >= ZMK_KEYMAP_LAYERS_LEN) { \
|
||||||
|
return (_fail_ret); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)
|
||||||
|
|
||||||
|
uint8_t map_layer_id_to_index(zmk_keymap_layer_id_t layer_id) {
|
||||||
|
for (uint8_t i = 0; i < ZMK_KEYMAP_LAYERS_LEN; i++) {
|
||||||
|
if (keymap_layer_orders[i] == layer_id) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ZMK_KEYMAP_LAYER_ID_INVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LAYER_INDEX_TO_ID(_layer) keymap_layer_orders[_layer]
|
||||||
|
#define LAYER_ID_TO_INDEX(_layer) map_layer_id_to_index(_layer)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define LAYER_INDEX_TO_ID(_layer) _layer
|
||||||
|
#define LAYER_ID_TO_INDEX(_layer) _layer
|
||||||
|
|
||||||
|
#endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)
|
||||||
|
|
||||||
|
static inline int set_layer_state(zmk_keymap_layer_id_t layer_id, bool state) {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
if (layer >= ZMK_KEYMAP_LAYERS_LEN) {
|
if (layer_id >= ZMK_KEYMAP_LAYERS_LEN) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default layer should *always* remain active
|
// Default layer should *always* remain active
|
||||||
if (layer == _zmk_keymap_layer_default && !state) {
|
if (layer_id == _zmk_keymap_layer_default && !state) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
zmk_keymap_layers_state_t old_state = _zmk_keymap_layer_state;
|
zmk_keymap_layers_state_t old_state = _zmk_keymap_layer_state;
|
||||||
WRITE_BIT(_zmk_keymap_layer_state, layer, state);
|
WRITE_BIT(_zmk_keymap_layer_state, layer_id, state);
|
||||||
// Don't send state changes unless there was an actual change
|
// Don't send state changes unless there was an actual change
|
||||||
if (old_state != _zmk_keymap_layer_state) {
|
if (old_state != _zmk_keymap_layer_state) {
|
||||||
LOG_DBG("layer_changed: layer %d state %d", layer, state);
|
LOG_DBG("layer_changed: layer %d state %d", layer_id, state);
|
||||||
ret = raise_layer_state_changed(layer, state);
|
ret = raise_layer_state_changed(layer_id, state);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
LOG_WRN("Failed to raise layer state changed (%d)", ret);
|
LOG_WRN("Failed to raise layer state changed (%d)", ret);
|
||||||
}
|
}
|
||||||
|
@ -106,21 +163,28 @@ static inline int set_layer_state(uint8_t layer, bool state) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t zmk_keymap_layer_default(void) { return _zmk_keymap_layer_default; }
|
zmk_keymap_layer_id_t zmk_keymap_layer_index_to_id(zmk_keymap_layer_index_t layer_index) {
|
||||||
|
ASSERT_LAYER_VAL(layer_index, UINT8_MAX);
|
||||||
|
|
||||||
|
return LAYER_INDEX_TO_ID(layer_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
zmk_keymap_layer_id_t zmk_keymap_layer_default(void) { return _zmk_keymap_layer_default; }
|
||||||
|
|
||||||
zmk_keymap_layers_state_t zmk_keymap_layer_state(void) { return _zmk_keymap_layer_state; }
|
zmk_keymap_layers_state_t zmk_keymap_layer_state(void) { return _zmk_keymap_layer_state; }
|
||||||
|
|
||||||
bool zmk_keymap_layer_active_with_state(uint8_t layer, zmk_keymap_layers_state_t state_to_test) {
|
bool zmk_keymap_layer_active_with_state(zmk_keymap_layer_id_t layer,
|
||||||
|
zmk_keymap_layers_state_t state_to_test) {
|
||||||
// The default layer is assumed to be ALWAYS ACTIVE so we include an || here to ensure nobody
|
// The default layer is assumed to be ALWAYS ACTIVE so we include an || here to ensure nobody
|
||||||
// breaks up that assumption by accident
|
// breaks up that assumption by accident
|
||||||
return (state_to_test & (BIT(layer))) == (BIT(layer)) || layer == _zmk_keymap_layer_default;
|
return (state_to_test & (BIT(layer))) == (BIT(layer)) || layer == _zmk_keymap_layer_default;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool zmk_keymap_layer_active(uint8_t layer) {
|
bool zmk_keymap_layer_active(zmk_keymap_layer_id_t layer) {
|
||||||
return zmk_keymap_layer_active_with_state(layer, _zmk_keymap_layer_state);
|
return zmk_keymap_layer_active_with_state(layer, _zmk_keymap_layer_state);
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t zmk_keymap_highest_layer_active(void) {
|
zmk_keymap_layer_id_t zmk_keymap_highest_layer_active(void) {
|
||||||
for (uint8_t layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer > 0; layer--) {
|
for (uint8_t layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer > 0; layer--) {
|
||||||
if (zmk_keymap_layer_active(layer)) {
|
if (zmk_keymap_layer_active(layer)) {
|
||||||
return layer;
|
return layer;
|
||||||
|
@ -129,11 +193,13 @@ uint8_t zmk_keymap_highest_layer_active(void) {
|
||||||
return zmk_keymap_layer_default();
|
return zmk_keymap_layer_default();
|
||||||
}
|
}
|
||||||
|
|
||||||
int zmk_keymap_layer_activate(uint8_t layer) { return set_layer_state(layer, true); };
|
int zmk_keymap_layer_activate(zmk_keymap_layer_id_t layer) { return set_layer_state(layer, true); };
|
||||||
|
|
||||||
int zmk_keymap_layer_deactivate(uint8_t layer) { return set_layer_state(layer, false); };
|
int zmk_keymap_layer_deactivate(zmk_keymap_layer_id_t layer) {
|
||||||
|
return set_layer_state(layer, false);
|
||||||
|
};
|
||||||
|
|
||||||
int zmk_keymap_layer_toggle(uint8_t layer) {
|
int zmk_keymap_layer_toggle(zmk_keymap_layer_id_t layer) {
|
||||||
if (zmk_keymap_layer_active(layer)) {
|
if (zmk_keymap_layer_active(layer)) {
|
||||||
return zmk_keymap_layer_deactivate(layer);
|
return zmk_keymap_layer_deactivate(layer);
|
||||||
}
|
}
|
||||||
|
@ -141,7 +207,7 @@ int zmk_keymap_layer_toggle(uint8_t layer) {
|
||||||
return zmk_keymap_layer_activate(layer);
|
return zmk_keymap_layer_activate(layer);
|
||||||
};
|
};
|
||||||
|
|
||||||
int zmk_keymap_layer_to(uint8_t layer) {
|
int zmk_keymap_layer_to(zmk_keymap_layer_id_t layer) {
|
||||||
for (int i = ZMK_KEYMAP_LAYERS_LEN - 1; i >= 0; i--) {
|
for (int i = ZMK_KEYMAP_LAYERS_LEN - 1; i >= 0; i--) {
|
||||||
zmk_keymap_layer_deactivate(i);
|
zmk_keymap_layer_deactivate(i);
|
||||||
}
|
}
|
||||||
|
@ -151,18 +217,365 @@ int zmk_keymap_layer_to(uint8_t layer) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_active_layer(uint8_t layer, zmk_keymap_layers_state_t layer_state) {
|
const char *zmk_keymap_layer_name(zmk_keymap_layer_id_t layer_id) {
|
||||||
return (layer_state & BIT(layer)) == BIT(layer) || layer == _zmk_keymap_layer_default;
|
ASSERT_LAYER_VAL(layer_id, NULL)
|
||||||
|
|
||||||
|
return zmk_keymap_layer_names[layer_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *zmk_keymap_layer_name(uint8_t layer) {
|
const struct zmk_behavior_binding *
|
||||||
if (layer >= ZMK_KEYMAP_LAYERS_LEN) {
|
zmk_keymap_get_layer_binding_at_idx(zmk_keymap_layer_id_t layer_id, uint8_t binding_idx) {
|
||||||
|
if (binding_idx >= ZMK_KEYMAP_LEN) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return zmk_keymap_layer_names[layer];
|
ASSERT_LAYER_VAL(layer_id, NULL)
|
||||||
|
|
||||||
|
return &zmk_keymap[layer_id][binding_idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE)
|
||||||
|
|
||||||
|
#define PENDING_ARRAY_SIZE DIV_ROUND_UP(ZMK_KEYMAP_LEN, 8)
|
||||||
|
|
||||||
|
static uint8_t zmk_keymap_layer_pending_changes[ZMK_KEYMAP_LAYERS_LEN][PENDING_ARRAY_SIZE];
|
||||||
|
|
||||||
|
#endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE)
|
||||||
|
|
||||||
|
int zmk_keymap_set_layer_binding_at_idx(zmk_keymap_layer_id_t layer_id, uint8_t binding_idx,
|
||||||
|
struct zmk_behavior_binding binding) {
|
||||||
|
if (binding_idx >= ZMK_KEYMAP_LEN) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_LAYER_VAL(layer_id, -EINVAL)
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE)
|
||||||
|
uint8_t *pending = zmk_keymap_layer_pending_changes[layer_id];
|
||||||
|
|
||||||
|
WRITE_BIT(pending[binding_idx / 8], binding_idx % 8, 1);
|
||||||
|
#endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE)
|
||||||
|
|
||||||
|
// TODO: Need a mutex to protect access to the keymap data?
|
||||||
|
memcpy(&zmk_keymap[layer_id][binding_idx], &binding, sizeof(binding));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE)
|
||||||
|
|
||||||
|
static uint8_t settings_layer_orders[ZMK_KEYMAP_LAYERS_LEN];
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int zmk_keymap_move_layer(zmk_keymap_layer_index_t start_idx, zmk_keymap_layer_index_t dest_idx) {
|
||||||
|
ASSERT_LAYER_VAL(start_idx, -EINVAL)
|
||||||
|
ASSERT_LAYER_VAL(dest_idx, -EINVAL)
|
||||||
|
|
||||||
|
if (start_idx == dest_idx) {
|
||||||
|
return 0;
|
||||||
|
} else if (dest_idx > start_idx) {
|
||||||
|
uint8_t val = keymap_layer_orders[start_idx];
|
||||||
|
|
||||||
|
for (int i = start_idx; i < dest_idx; i++) {
|
||||||
|
keymap_layer_orders[i] = keymap_layer_orders[i + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
keymap_layer_orders[dest_idx] = val;
|
||||||
|
} else {
|
||||||
|
uint8_t val = keymap_layer_orders[start_idx];
|
||||||
|
|
||||||
|
for (int i = start_idx; i > dest_idx; i--) {
|
||||||
|
keymap_layer_orders[i] = keymap_layer_orders[i - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
keymap_layer_orders[dest_idx] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zmk_keymap_add_layer(void) {
|
||||||
|
uint32_t seen_layer_ids = 0;
|
||||||
|
LOG_HEXDUMP_DBG(keymap_layer_orders, ZMK_KEYMAP_LAYERS_LEN, "Order");
|
||||||
|
|
||||||
|
for (int index = 0; index < ZMK_KEYMAP_LAYERS_LEN; index++) {
|
||||||
|
zmk_keymap_layer_id_t id = LAYER_INDEX_TO_ID(index);
|
||||||
|
|
||||||
|
if (id != ZMK_KEYMAP_LAYER_ID_INVAL) {
|
||||||
|
WRITE_BIT(seen_layer_ids, id, 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int candidate_id = 0; candidate_id < ZMK_KEYMAP_LAYERS_LEN; candidate_id++) {
|
||||||
|
if (!(seen_layer_ids & BIT(candidate_id))) {
|
||||||
|
keymap_layer_orders[index] = candidate_id;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOSPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zmk_keymap_remove_layer(zmk_keymap_layer_index_t index) {
|
||||||
|
ASSERT_LAYER_VAL(index, -EINVAL);
|
||||||
|
|
||||||
|
if (keymap_layer_orders[index] == ZMK_KEYMAP_LAYER_ID_INVAL) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG("Removing layer index %d which is ID %d", index, keymap_layer_orders[index]);
|
||||||
|
LOG_HEXDUMP_DBG(keymap_layer_orders, ZMK_KEYMAP_LAYERS_LEN, "Order");
|
||||||
|
|
||||||
|
while (index < ZMK_KEYMAP_LAYERS_LEN - 1) {
|
||||||
|
keymap_layer_orders[index] = keymap_layer_orders[index + 1];
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
keymap_layer_orders[ZMK_KEYMAP_LAYERS_LEN - 1] = ZMK_KEYMAP_LAYER_ID_INVAL;
|
||||||
|
|
||||||
|
LOG_HEXDUMP_DBG(keymap_layer_orders, ZMK_KEYMAP_LAYERS_LEN, "Order");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zmk_keymap_restore_layer(zmk_keymap_layer_id_t id, zmk_keymap_layer_index_t at_index) {
|
||||||
|
ASSERT_LAYER_VAL(at_index, -EINVAL);
|
||||||
|
ASSERT_LAYER_VAL(id, -ENODEV);
|
||||||
|
|
||||||
|
for (zmk_keymap_layer_index_t index = ZMK_KEYMAP_LAYERS_LEN - 1; index > at_index; index--) {
|
||||||
|
keymap_layer_orders[index] = keymap_layer_orders[index - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
keymap_layer_orders[at_index] = id;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zmk_keymap_set_layer_name(zmk_keymap_layer_id_t id, const char *name, size_t size) {
|
||||||
|
ASSERT_LAYER_VAL(id, -EINVAL);
|
||||||
|
|
||||||
|
if (size >= CONFIG_ZMK_KEYMAP_LAYER_NAME_MAX_LEN) {
|
||||||
|
return -ENOSPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
strlcpy(zmk_keymap_layer_names[id], name, CONFIG_ZMK_KEYMAP_LAYER_NAME_MAX_LEN);
|
||||||
|
|
||||||
|
// Ensure we properly null terminate our name if we previously had a longer one.
|
||||||
|
if (size < CONFIG_ZMK_KEYMAP_LAYER_NAME_MAX_LEN - 1) {
|
||||||
|
zmk_keymap_layer_names[id][size] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE_BIT(changed_layer_names, id, 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int zmk_keymap_move_layer(zmk_keymap_layer_index_t layer, zmk_keymap_layer_index_t dest) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zmk_keymap_add_layer(void) { return -ENOTSUP; }
|
||||||
|
|
||||||
|
int zmk_keymap_remove_layer(zmk_keymap_layer_index_t index) { return -ENOTSUP; }
|
||||||
|
|
||||||
|
int zmk_keymap_restore_layer(zmk_keymap_layer_id_t id, zmk_keymap_layer_index_t at_index) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zmk_keymap_set_layer_name(zmk_keymap_layer_id_t id, const char *name, size_t size) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE)
|
||||||
|
|
||||||
|
#define PENDING_ARRAY_SIZE DIV_ROUND_UP(ZMK_KEYMAP_LEN, 8)
|
||||||
|
|
||||||
|
static uint8_t zmk_keymap_layer_pending_changes[ZMK_KEYMAP_LAYERS_LEN][PENDING_ARRAY_SIZE];
|
||||||
|
|
||||||
|
struct zmk_behavior_binding_setting {
|
||||||
|
zmk_behavior_local_id_t behavior_local_id;
|
||||||
|
uint32_t param1;
|
||||||
|
uint32_t param2;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
int zmk_keymap_check_unsaved_changes(void) {
|
||||||
|
for (int l = 0; l < ZMK_KEYMAP_LAYERS_LEN; l++) {
|
||||||
|
uint8_t *pending = zmk_keymap_layer_pending_changes[l];
|
||||||
|
for (int kp = 0; kp < ZMK_KEYMAP_LEN; kp++) {
|
||||||
|
if (pending[kp / 8] & BIT(kp % 8)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)
|
||||||
|
if (settings_layer_orders[l] != keymap_layer_orders[l]) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LAYER_ORDER_SETTINGS_KEY "keymap/layer_order"
|
||||||
|
#define LAYER_NAME_SETTINGS_KEY "keymap/l_n/%d"
|
||||||
|
#define LAYER_BINDING_SETTINGS_KEY "keymap/l/%d/%d"
|
||||||
|
|
||||||
|
static void save_bindings(void) {
|
||||||
|
for (int l = 0; l < ZMK_KEYMAP_LAYERS_LEN; l++) {
|
||||||
|
uint8_t *pending = zmk_keymap_layer_pending_changes[l];
|
||||||
|
|
||||||
|
for (int kp = 0; kp < ZMK_KEYMAP_LEN; kp++) {
|
||||||
|
if (pending[kp / 8] & BIT(kp % 8)) {
|
||||||
|
LOG_DBG("Pending save for layer %d at key position %d", l, kp);
|
||||||
|
|
||||||
|
struct zmk_behavior_binding *binding = &zmk_keymap[l][kp];
|
||||||
|
struct zmk_behavior_binding_setting binding_setting = {
|
||||||
|
.behavior_local_id = zmk_behavior_get_local_id(binding->behavior_dev),
|
||||||
|
.param1 = binding->param1,
|
||||||
|
.param2 = binding->param2,
|
||||||
|
};
|
||||||
|
|
||||||
|
// We can skip any trailing zero params, regardless of the behavior
|
||||||
|
// and if those params are meaningful.
|
||||||
|
size_t len = sizeof(binding_setting);
|
||||||
|
if (binding_setting.param2 == 0) {
|
||||||
|
len -= 4;
|
||||||
|
|
||||||
|
if (binding_setting.param1 == 0) {
|
||||||
|
len -= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char setting_name[20];
|
||||||
|
sprintf(setting_name, LAYER_BINDING_SETTINGS_KEY, l, kp);
|
||||||
|
|
||||||
|
settings_save_one(setting_name, &binding_setting, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*pending = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)
|
||||||
|
static void save_layer_orders(void) {
|
||||||
|
settings_save_one(LAYER_ORDER_SETTINGS_KEY, keymap_layer_orders,
|
||||||
|
ARRAY_SIZE(keymap_layer_orders));
|
||||||
|
memcpy(settings_layer_orders, keymap_layer_orders, ARRAY_SIZE(keymap_layer_orders));
|
||||||
|
}
|
||||||
|
#endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)
|
||||||
|
|
||||||
|
static void save_layer_names(void) {
|
||||||
|
for (int id = 0; id < ZMK_KEYMAP_LAYERS_LEN; id++) {
|
||||||
|
if (changed_layer_names & BIT(id)) {
|
||||||
|
char setting_name[14];
|
||||||
|
sprintf(setting_name, LAYER_NAME_SETTINGS_KEY, id);
|
||||||
|
settings_save_one(setting_name, zmk_keymap_layer_names[id],
|
||||||
|
strlen(zmk_keymap_layer_names[id]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changed_layer_names = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zmk_keymap_save_changes(void) {
|
||||||
|
save_bindings();
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)
|
||||||
|
save_layer_orders();
|
||||||
|
#endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)
|
||||||
|
|
||||||
|
save_layer_names();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)
|
||||||
|
|
||||||
|
#define KEYMAP_LAYER_ORDER_INIT(n) \
|
||||||
|
keymap_layer_orders[i] = i; \
|
||||||
|
settings_layer_orders[i] = i; \
|
||||||
|
i++;
|
||||||
|
|
||||||
|
static void load_stock_keymap_layer_ordering() {
|
||||||
|
int i = 0;
|
||||||
|
DT_INST_FOREACH_CHILD_STATUS_OKAY(0, KEYMAP_LAYER_ORDER_INIT)
|
||||||
|
while (i < ZMK_KEYMAP_LAYERS_LEN) {
|
||||||
|
keymap_layer_orders[i] = ZMK_KEYMAP_LAYER_ID_INVAL;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void reload_from_stock_keymap(void) {
|
||||||
|
for (int l = 0; l < ZMK_KEYMAP_LAYERS_LEN; l++) {
|
||||||
|
for (int k = 0; k < ZMK_KEYMAP_LEN; k++) {
|
||||||
|
zmk_keymap[l][k] = zmk_stock_keymap[l][k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int zmk_keymap_discard_changes(void) {
|
||||||
|
load_stock_keymap_layer_ordering();
|
||||||
|
reload_from_stock_keymap();
|
||||||
|
|
||||||
|
int ret = settings_load_subtree("keymap");
|
||||||
|
if (ret >= 0) {
|
||||||
|
changed_layer_names = 0;
|
||||||
|
|
||||||
|
for (int l = 0; l < ZMK_KEYMAP_LAYERS_LEN; l++) {
|
||||||
|
memset(zmk_keymap_layer_pending_changes[l], 0, PENDING_ARRAY_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zmk_keymap_reset_settings(void) {
|
||||||
|
settings_delete(LAYER_ORDER_SETTINGS_KEY);
|
||||||
|
for (int l = 0; l < ZMK_KEYMAP_LAYERS_LEN; l++) {
|
||||||
|
char layer_name_setting_name[14];
|
||||||
|
sprintf(layer_name_setting_name, LAYER_NAME_SETTINGS_KEY, l);
|
||||||
|
settings_delete(layer_name_setting_name);
|
||||||
|
|
||||||
|
for (int k = 0; k < ZMK_KEYMAP_LEN; k++) {
|
||||||
|
if (memcmp(&zmk_keymap[l][k], &zmk_stock_keymap[l][k],
|
||||||
|
sizeof(struct zmk_behavior_binding_setting)) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char setting_name[20];
|
||||||
|
sprintf(setting_name, LAYER_BINDING_SETTINGS_KEY, l, k);
|
||||||
|
settings_delete(setting_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
load_stock_keymap_layer_ordering();
|
||||||
|
|
||||||
|
reload_from_stock_keymap();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int zmk_keymap_save_changes(void) { return -ENOTSUP; }
|
||||||
|
|
||||||
|
int zmk_keymap_discard_changes(void) { return -ENOTSUP; }
|
||||||
|
|
||||||
|
int zmk_keymap_reset_settings(void) { return -ENOTSUP; }
|
||||||
|
|
||||||
|
#endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE)
|
||||||
|
|
||||||
int invoke_locally(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event,
|
int invoke_locally(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event,
|
||||||
bool pressed) {
|
bool pressed) {
|
||||||
if (pressed) {
|
if (pressed) {
|
||||||
|
@ -172,24 +585,28 @@ int invoke_locally(struct zmk_behavior_binding *binding, struct zmk_behavior_bin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int zmk_keymap_apply_position_state(uint8_t source, int layer, uint32_t position, bool pressed,
|
int zmk_keymap_apply_position_state(uint8_t source, zmk_keymap_layer_id_t layer_id,
|
||||||
int64_t timestamp) {
|
uint32_t position, bool pressed, int64_t timestamp) {
|
||||||
// We want to make a copy of this, since it may be converted from
|
// We want to make a copy of this, since it may be converted from
|
||||||
// relative to absolute before being invoked
|
// relative to absolute before being invoked
|
||||||
struct zmk_behavior_binding binding = zmk_keymap[layer][position];
|
|
||||||
|
ASSERT_LAYER_VAL(layer_id, -EINVAL);
|
||||||
|
|
||||||
|
struct zmk_behavior_binding binding = zmk_keymap[layer_id][position];
|
||||||
const struct device *behavior;
|
const struct device *behavior;
|
||||||
struct zmk_behavior_binding_event event = {
|
struct zmk_behavior_binding_event event = {
|
||||||
.layer = layer,
|
.layer = layer_id,
|
||||||
.position = position,
|
.position = position,
|
||||||
.timestamp = timestamp,
|
.timestamp = timestamp,
|
||||||
};
|
};
|
||||||
|
|
||||||
LOG_DBG("layer: %d position: %d, binding name: %s", layer, position, binding.behavior_dev);
|
LOG_DBG("layer_id: %d position: %d, binding name: %s", layer_id, position,
|
||||||
|
binding.behavior_dev);
|
||||||
|
|
||||||
behavior = zmk_behavior_get_binding(binding.behavior_dev);
|
behavior = zmk_behavior_get_binding(binding.behavior_dev);
|
||||||
|
|
||||||
if (!behavior) {
|
if (!behavior) {
|
||||||
LOG_WRN("No behavior assigned to %d on layer %d", position, layer);
|
LOG_WRN("No behavior assigned to %d on layer %d", position, layer_id);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,9 +653,19 @@ int zmk_keymap_position_state_changed(uint8_t source, uint32_t position, bool pr
|
||||||
if (pressed) {
|
if (pressed) {
|
||||||
zmk_keymap_active_behavior_layer[position] = _zmk_keymap_layer_state;
|
zmk_keymap_active_behavior_layer[position] = _zmk_keymap_layer_state;
|
||||||
}
|
}
|
||||||
for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= _zmk_keymap_layer_default; layer--) {
|
|
||||||
if (zmk_keymap_layer_active_with_state(layer, zmk_keymap_active_behavior_layer[position])) {
|
// We use int here to be sure we don't loop layer_idx back to UINT8_MAX
|
||||||
int ret = zmk_keymap_apply_position_state(source, layer, position, pressed, timestamp);
|
for (int layer_idx = ZMK_KEYMAP_LAYERS_LEN - 1;
|
||||||
|
layer_idx >= LAYER_ID_TO_INDEX(_zmk_keymap_layer_default); layer_idx--) {
|
||||||
|
zmk_keymap_layer_id_t layer_id = LAYER_INDEX_TO_ID(layer_idx);
|
||||||
|
|
||||||
|
if (layer_id == ZMK_KEYMAP_LAYER_ID_INVAL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (zmk_keymap_layer_active_with_state(layer_id,
|
||||||
|
zmk_keymap_active_behavior_layer[position])) {
|
||||||
|
int ret =
|
||||||
|
zmk_keymap_apply_position_state(source, layer_id, position, pressed, timestamp);
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
LOG_DBG("behavior processing to continue to next layer");
|
LOG_DBG("behavior processing to continue to next layer");
|
||||||
continue;
|
continue;
|
||||||
|
@ -260,20 +687,26 @@ int zmk_keymap_sensor_event(uint8_t sensor_index,
|
||||||
size_t channel_data_size, int64_t timestamp) {
|
size_t channel_data_size, int64_t timestamp) {
|
||||||
bool opaque_response = false;
|
bool opaque_response = false;
|
||||||
|
|
||||||
for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= 0; layer--) {
|
for (int layer_idx = ZMK_KEYMAP_LAYERS_LEN - 1; layer_idx >= 0; layer_idx--) {
|
||||||
struct zmk_behavior_binding *binding = &zmk_sensor_keymap[layer][sensor_index];
|
uint8_t layer_id = LAYER_INDEX_TO_ID(layer_idx);
|
||||||
|
|
||||||
LOG_DBG("layer: %d sensor_index: %d, binding name: %s", layer, sensor_index,
|
if (layer_id >= ZMK_KEYMAP_LAYERS_LEN) {
|
||||||
binding->behavior_dev);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct zmk_behavior_binding *binding = &zmk_sensor_keymap[layer_id][sensor_index];
|
||||||
|
|
||||||
|
LOG_DBG("layer idx: %d, layer id: %d sensor_index: %d, binding name: %s", layer_idx,
|
||||||
|
layer_id, sensor_index, binding->behavior_dev);
|
||||||
|
|
||||||
const struct device *behavior = zmk_behavior_get_binding(binding->behavior_dev);
|
const struct device *behavior = zmk_behavior_get_binding(binding->behavior_dev);
|
||||||
if (!behavior) {
|
if (!behavior) {
|
||||||
LOG_DBG("No behavior assigned to %d on layer %d", sensor_index, layer);
|
LOG_DBG("No behavior assigned to %d on layer %d", sensor_index, layer_id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct zmk_behavior_binding_event event = {
|
struct zmk_behavior_binding_event event = {
|
||||||
.layer = layer,
|
.layer = layer_id,
|
||||||
.position = ZMK_VIRTUAL_KEY_POSITION_SENSOR(sensor_index),
|
.position = ZMK_VIRTUAL_KEY_POSITION_SENSOR(sensor_index),
|
||||||
.timestamp = timestamp,
|
.timestamp = timestamp,
|
||||||
};
|
};
|
||||||
|
@ -290,8 +723,8 @@ int zmk_keymap_sensor_event(uint8_t sensor_index,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum behavior_sensor_binding_process_mode mode =
|
enum behavior_sensor_binding_process_mode mode =
|
||||||
(!opaque_response && layer >= _zmk_keymap_layer_default &&
|
(!opaque_response && layer_idx >= LAYER_ID_TO_INDEX(_zmk_keymap_layer_default) &&
|
||||||
zmk_keymap_layer_active(layer))
|
zmk_keymap_layer_active(layer_id))
|
||||||
? BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_TRIGGER
|
? BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_TRIGGER
|
||||||
: BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_DISCARD;
|
: BEHAVIOR_SENSOR_BINDING_PROCESS_MODE_DISCARD;
|
||||||
|
|
||||||
|
@ -335,3 +768,140 @@ ZMK_SUBSCRIPTION(keymap, zmk_position_state_changed);
|
||||||
#if ZMK_KEYMAP_HAS_SENSORS
|
#if ZMK_KEYMAP_HAS_SENSORS
|
||||||
ZMK_SUBSCRIPTION(keymap, zmk_sensor_event);
|
ZMK_SUBSCRIPTION(keymap, zmk_sensor_event);
|
||||||
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
#endif /* ZMK_KEYMAP_HAS_SENSORS */
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE)
|
||||||
|
|
||||||
|
static int keymap_handle_set(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg) {
|
||||||
|
const char *next;
|
||||||
|
|
||||||
|
LOG_DBG("Setting Keymap setting %s", name);
|
||||||
|
|
||||||
|
if (settings_name_steq(name, "l_n", &next) && next) {
|
||||||
|
char *endptr;
|
||||||
|
zmk_keymap_layer_id_t layer = strtoul(next, &endptr, 10);
|
||||||
|
|
||||||
|
if (*endptr != '\0') {
|
||||||
|
LOG_WRN("Invalid layer number: %s with endptr %s", next, endptr);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layer >= ZMK_KEYMAP_LAYERS_LEN) {
|
||||||
|
LOG_WRN("Found layer name for invalid layer ID %d", layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int err = read_cb(cb_arg, zmk_keymap_layer_names[layer],
|
||||||
|
MIN(len, CONFIG_ZMK_KEYMAP_LAYER_NAME_MAX_LEN - 1));
|
||||||
|
if (err <= 0) {
|
||||||
|
LOG_ERR("Failed to handle keymap layer name from settings (err %d)", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
} else if (settings_name_steq(name, "l", &next) && next) {
|
||||||
|
char *endptr;
|
||||||
|
uint8_t layer = strtoul(next, &endptr, 10);
|
||||||
|
if (*endptr != '/') {
|
||||||
|
LOG_WRN("Invalid layer number: %s with endptr %s", next, endptr);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t key_position = strtoul(endptr + 1, &endptr, 10);
|
||||||
|
|
||||||
|
if (*endptr != '\0') {
|
||||||
|
LOG_WRN("Invalid key_position number: %s with endptr %s", next, endptr);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > sizeof(struct zmk_behavior_binding_setting)) {
|
||||||
|
LOG_ERR("Too large binding setting size (got %d expected %d)", len,
|
||||||
|
sizeof(struct zmk_behavior_binding_setting));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layer >= ZMK_KEYMAP_LAYERS_LEN) {
|
||||||
|
LOG_WRN("Layer %d is larger than max of %d", layer, ZMK_KEYMAP_LAYERS_LEN);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_position >= ZMK_KEYMAP_LEN) {
|
||||||
|
LOG_WRN("Key position %d is larger than max of %d", key_position, ZMK_KEYMAP_LEN);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct zmk_behavior_binding_setting binding_setting = {0};
|
||||||
|
int err = read_cb(cb_arg, &binding_setting, len);
|
||||||
|
if (err <= 0) {
|
||||||
|
LOG_ERR("Failed to handle keymap binding from settings (err %d)", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *name =
|
||||||
|
zmk_behavior_find_behavior_name_from_local_id(binding_setting.behavior_local_id);
|
||||||
|
|
||||||
|
if (!name) {
|
||||||
|
LOG_WRN("Loaded device %d from settings but no device found by that local ID",
|
||||||
|
binding_setting.behavior_local_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
zmk_keymap[layer][key_position] = (struct zmk_behavior_binding) {
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_LOCAL_IDS_IN_BINDINGS)
|
||||||
|
.local_id = binding_setting.behavior_local_id,
|
||||||
|
#endif
|
||||||
|
.behavior_dev = name, .param1 = binding_setting.param1,
|
||||||
|
.param2 = binding_setting.param2,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)
|
||||||
|
else if (settings_name_steq(name, "layer_order", &next) && !next) {
|
||||||
|
int err =
|
||||||
|
read_cb(cb_arg, settings_layer_orders, MIN(len, ARRAY_SIZE(settings_layer_orders)));
|
||||||
|
if (err <= 0) {
|
||||||
|
LOG_ERR("Failed to handle keymap layer orders from settings (err %d)", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_HEXDUMP_DBG(settings_layer_orders, ARRAY_SIZE(settings_layer_orders),
|
||||||
|
"Settings Layer Order");
|
||||||
|
|
||||||
|
memcpy(keymap_layer_orders, settings_layer_orders,
|
||||||
|
MIN(len, ARRAY_SIZE(settings_layer_orders)));
|
||||||
|
}
|
||||||
|
#endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int keymap_handle_commit(void) {
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_BEHAVIOR_LOCAL_IDS_IN_BINDINGS)
|
||||||
|
for (int l = 0; l < ZMK_KEYMAP_LAYERS_LEN; l++) {
|
||||||
|
for (int p = 0; p < ZMK_KEYMAP_LEN; p++) {
|
||||||
|
struct zmk_behavior_binding *binding = &zmk_keymap[l][p];
|
||||||
|
|
||||||
|
if (binding->local_id > 0 && !binding->behavior_dev) {
|
||||||
|
binding->behavior_dev =
|
||||||
|
zmk_behavior_find_behavior_name_from_local_id(binding->local_id);
|
||||||
|
|
||||||
|
if (!binding->behavior_dev) {
|
||||||
|
LOG_ERR("Failed to finding device for local ID %d after settings load",
|
||||||
|
binding->local_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SETTINGS_STATIC_HANDLER_DEFINE(keymap, "keymap", NULL, keymap_handle_set, keymap_handle_commit,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
#endif // IS_ENABLED(CONFIG_ZMK_KEYMAP_SETTINGS_STORAGE)
|
||||||
|
|
||||||
|
int keymap_init(void) {
|
||||||
|
#if IS_ENABLED(CONFIG_ZMK_KEYMAP_LAYER_REORDERING)
|
||||||
|
load_stock_keymap_layer_ordering();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_INIT(keymap_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
||||||
|
|
|
@ -70,12 +70,14 @@ DT_INST_FOREACH_STATUS_OKAY(ZMK_LAYOUT_INST)
|
||||||
struct position_map_entry {
|
struct position_map_entry {
|
||||||
const struct zmk_physical_layout *layout;
|
const struct zmk_physical_layout *layout;
|
||||||
const uint32_t positions[ZMK_POS_MAP_LEN];
|
const uint32_t positions[ZMK_POS_MAP_LEN];
|
||||||
|
const size_t positions_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ZMK_POS_MAP_ENTRY(node_id) \
|
#define ZMK_POS_MAP_ENTRY(node_id) \
|
||||||
{ \
|
{ \
|
||||||
.layout = &_CONCAT(_zmk_physical_layout_, DT_PHANDLE(node_id, physical_layout)), \
|
.layout = &_CONCAT(_zmk_physical_layout_, DT_PHANDLE(node_id, physical_layout)), \
|
||||||
.positions = DT_PROP(node_id, positions), \
|
.positions = DT_PROP(node_id, positions), \
|
||||||
|
.positions_len = DT_PROP_LEN(node_id, positions), \
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct position_map_entry positions_maps[] = {
|
static const struct position_map_entry positions_maps[] = {
|
||||||
|
@ -275,13 +277,15 @@ int zmk_physical_layouts_save_selected(void) {
|
||||||
|
|
||||||
int zmk_physical_layouts_revert_selected(void) { return zmk_physical_layouts_select_initial(); }
|
int zmk_physical_layouts_revert_selected(void) { return zmk_physical_layouts_select_initial(); }
|
||||||
|
|
||||||
int zmk_physical_layouts_get_position_map(uint8_t source, uint8_t dest, uint32_t *map) {
|
int zmk_physical_layouts_get_position_map(uint8_t source, uint8_t dest, size_t map_size,
|
||||||
|
uint32_t map[map_size]) {
|
||||||
if (source >= ARRAY_SIZE(layouts) || dest >= ARRAY_SIZE(layouts)) {
|
if (source >= ARRAY_SIZE(layouts) || dest >= ARRAY_SIZE(layouts)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct zmk_physical_layout *src_layout = layouts[source];
|
const struct zmk_physical_layout *src_layout = layouts[source];
|
||||||
const struct zmk_physical_layout *dest_layout = layouts[dest];
|
const struct zmk_physical_layout *dest_layout = layouts[dest];
|
||||||
|
int max_kp = dest_layout->keys_len;
|
||||||
|
|
||||||
#if HAVE_POS_MAP
|
#if HAVE_POS_MAP
|
||||||
const struct position_map_entry *src_pos_map = NULL;
|
const struct position_map_entry *src_pos_map = NULL;
|
||||||
|
@ -296,11 +300,24 @@ int zmk_physical_layouts_get_position_map(uint8_t source, uint8_t dest, uint32_t
|
||||||
dest_pos_map = &positions_maps[pm];
|
dest_pos_map = &positions_maps[pm];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Maps can place items "off the end" of other layouts so they are
|
||||||
|
// preserved but not visible, so adjust our max here if that is being used.
|
||||||
|
if (src_pos_map && dest_pos_map) {
|
||||||
|
for (int mp = 0; mp < ZMK_POS_MAP_LEN; mp++) {
|
||||||
|
max_kp =
|
||||||
|
MAX(max_kp, MAX(src_pos_map->positions[mp] + 1, dest_pos_map->positions[mp] + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memset(map, UINT32_MAX, dest_layout->keys_len);
|
if (map_size < max_kp) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
for (int b = 0; b < dest_layout->keys_len; b++) {
|
memset(map, UINT32_MAX, map_size);
|
||||||
|
|
||||||
|
for (int b = 0; b < max_kp; b++) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
#if HAVE_POS_MAP
|
#if HAVE_POS_MAP
|
||||||
|
@ -329,13 +346,9 @@ int zmk_physical_layouts_get_position_map(uint8_t source, uint8_t dest, uint32_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!found || map[b] >= src_layout->keys_len) {
|
|
||||||
map[b] = UINT32_MAX;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dest_layout->keys_len;
|
return max_kp;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_SETTINGS)
|
#if IS_ENABLED(CONFIG_SETTINGS)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
zephyr_linker_sources(DATA_SECTIONS ../../include/linker/zmk-rpc-subsystems.ld)
|
zephyr_linker_sources(DATA_SECTIONS ../../include/linker/zmk-rpc-subsystems.ld)
|
||||||
zephyr_linker_sources(SECTIONS ../../include/linker/zmk-rpc-subsystem-handlers.ld)
|
zephyr_linker_sources(SECTIONS ../../include/linker/zmk-rpc-subsystem-handlers.ld)
|
||||||
|
zephyr_linker_sources(SECTIONS ../../include/linker/zmk-rpc-subsystem-settings-reset.ld)
|
||||||
zephyr_linker_sources(SECTIONS ../../include/linker/zmk-rpc-event-mappers.ld)
|
zephyr_linker_sources(SECTIONS ../../include/linker/zmk-rpc-event-mappers.ld)
|
||||||
zephyr_linker_sources(SECTIONS ../../include/linker/zmk-rpc-transport.ld)
|
zephyr_linker_sources(SECTIONS ../../include/linker/zmk-rpc-transport.ld)
|
||||||
|
|
||||||
|
@ -11,5 +12,6 @@ target_sources(app PRIVATE rpc.c)
|
||||||
target_sources(app PRIVATE core.c)
|
target_sources(app PRIVATE core.c)
|
||||||
target_sources(app PRIVATE behavior_subsystem.c)
|
target_sources(app PRIVATE behavior_subsystem.c)
|
||||||
target_sources(app PRIVATE core_subsystem.c)
|
target_sources(app PRIVATE core_subsystem.c)
|
||||||
|
target_sources(app PRIVATE keymap_subsystem.c)
|
||||||
target_sources_ifdef(CONFIG_ZMK_STUDIO_TRANSPORT_UART app PRIVATE uart_rpc_transport.c)
|
target_sources_ifdef(CONFIG_ZMK_STUDIO_TRANSPORT_UART app PRIVATE uart_rpc_transport.c)
|
||||||
target_sources_ifdef(CONFIG_ZMK_STUDIO_TRANSPORT_BLE app PRIVATE gatt_rpc_transport.c)
|
target_sources_ifdef(CONFIG_ZMK_STUDIO_TRANSPORT_BLE app PRIVATE gatt_rpc_transport.c)
|
|
@ -41,6 +41,8 @@ menuconfig ZMK_STUDIO_RPC
|
||||||
select ZMK_BEHAVIOR_METADATA
|
select ZMK_BEHAVIOR_METADATA
|
||||||
select ZMK_BEHAVIOR_LOCAL_IDS
|
select ZMK_BEHAVIOR_LOCAL_IDS
|
||||||
select RING_BUFFER
|
select RING_BUFFER
|
||||||
|
select ZMK_KEYMAP_SETTINGS_STORAGE
|
||||||
|
select ZMK_KEYMAP_LAYER_REORDERING
|
||||||
help
|
help
|
||||||
Add firmware support for studio RPC protocol
|
Add firmware support for studio RPC protocol
|
||||||
|
|
||||||
|
|
|
@ -61,8 +61,21 @@ zmk_studio_Response get_lock_state(const zmk_studio_Request *req) {
|
||||||
return CORE_RESPONSE(get_lock_state, resp);
|
return CORE_RESPONSE(get_lock_state, resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zmk_studio_Response reset_settings(const zmk_studio_Request *req) {
|
||||||
|
ZMK_RPC_SUBSYSTEM_SETTINGS_RESET_FOREACH(sub) {
|
||||||
|
int ret = sub->callback();
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("Failed to reset settings: %d", ret);
|
||||||
|
return CORE_RESPONSE(reset_settings, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CORE_RESPONSE(reset_settings, true);
|
||||||
|
}
|
||||||
|
|
||||||
ZMK_RPC_SUBSYSTEM_HANDLER(core, get_device_info, ZMK_STUDIO_RPC_HANDLER_UNSECURED);
|
ZMK_RPC_SUBSYSTEM_HANDLER(core, get_device_info, ZMK_STUDIO_RPC_HANDLER_UNSECURED);
|
||||||
ZMK_RPC_SUBSYSTEM_HANDLER(core, get_lock_state, ZMK_STUDIO_RPC_HANDLER_UNSECURED);
|
ZMK_RPC_SUBSYSTEM_HANDLER(core, get_lock_state, ZMK_STUDIO_RPC_HANDLER_UNSECURED);
|
||||||
|
ZMK_RPC_SUBSYSTEM_HANDLER(core, reset_settings, ZMK_STUDIO_RPC_HANDLER_SECURED);
|
||||||
|
|
||||||
static int core_event_mapper(const zmk_event_t *eh, zmk_studio_Notification *n) {
|
static int core_event_mapper(const zmk_event_t *eh, zmk_studio_Notification *n) {
|
||||||
struct zmk_studio_core_lock_state_changed *lock_ev = as_zmk_studio_core_lock_state_changed(eh);
|
struct zmk_studio_core_lock_state_changed *lock_ev = as_zmk_studio_core_lock_state_changed(eh);
|
||||||
|
|
539
app/src/studio/keymap_subsystem.c
Normal file
539
app/src/studio/keymap_subsystem.c
Normal file
|
@ -0,0 +1,539 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
|
||||||
|
LOG_MODULE_DECLARE(zmk_studio, CONFIG_ZMK_STUDIO_LOG_LEVEL);
|
||||||
|
|
||||||
|
#include <drivers/behavior.h>
|
||||||
|
|
||||||
|
#include <zmk/behavior.h>
|
||||||
|
#include <zmk/matrix.h>
|
||||||
|
#include <zmk/keymap.h>
|
||||||
|
#include <zmk/studio/rpc.h>
|
||||||
|
#include <zmk/physical_layouts.h>
|
||||||
|
|
||||||
|
#include <pb_encode.h>
|
||||||
|
|
||||||
|
ZMK_RPC_SUBSYSTEM(keymap)
|
||||||
|
|
||||||
|
#define KEYMAP_RESPONSE(type, ...) ZMK_RPC_RESPONSE(keymap, type, __VA_ARGS__)
|
||||||
|
#define KEYMAP_NOTIFICATION(type, ...) ZMK_RPC_NOTIFICATION(keymap, type, __VA_ARGS__)
|
||||||
|
|
||||||
|
static bool encode_layer_bindings(pb_ostream_t *stream, const pb_field_t *field, void *const *arg) {
|
||||||
|
const zmk_keymap_layer_id_t layer_id = *(uint8_t *)*arg;
|
||||||
|
|
||||||
|
for (int b = 0; b < ZMK_KEYMAP_LEN; b++) {
|
||||||
|
const struct zmk_behavior_binding *binding =
|
||||||
|
zmk_keymap_get_layer_binding_at_idx(layer_id, b);
|
||||||
|
|
||||||
|
zmk_keymap_BehaviorBinding bb = zmk_keymap_BehaviorBinding_init_zero;
|
||||||
|
|
||||||
|
if (binding && binding->behavior_dev) {
|
||||||
|
bb.behavior_id = zmk_behavior_get_local_id(binding->behavior_dev);
|
||||||
|
bb.param1 = binding->param1;
|
||||||
|
bb.param2 = binding->param2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pb_encode_tag_for_field(stream, field)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pb_encode_submessage(stream, &zmk_keymap_BehaviorBinding_msg, &bb)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool encode_layer_name(pb_ostream_t *stream, const pb_field_t *field, void *const *arg) {
|
||||||
|
const zmk_keymap_layer_index_t layer_idx = *(uint8_t *)*arg;
|
||||||
|
|
||||||
|
const char *name = zmk_keymap_layer_name(layer_idx);
|
||||||
|
|
||||||
|
if (!name) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pb_encode_tag_for_field(stream, field)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pb_encode_string(stream, name, strlen(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool encode_keymap_layers(pb_ostream_t *stream, const pb_field_t *field, void *const *arg) {
|
||||||
|
for (zmk_keymap_layer_index_t l = 0; l < ZMK_KEYMAP_LAYERS_LEN; l++) {
|
||||||
|
zmk_keymap_layer_id_t layer_id = zmk_keymap_layer_index_to_id(l);
|
||||||
|
|
||||||
|
if (layer_id == UINT8_MAX) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pb_encode_tag_for_field(stream, field)) {
|
||||||
|
LOG_WRN("Failed to encode tag");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
zmk_keymap_Layer layer = zmk_keymap_Layer_init_zero;
|
||||||
|
layer.id = layer_id;
|
||||||
|
|
||||||
|
layer.name.funcs.encode = encode_layer_name;
|
||||||
|
layer.name.arg = &layer_id;
|
||||||
|
|
||||||
|
layer.bindings.funcs.encode = encode_layer_bindings;
|
||||||
|
layer.bindings.arg = &layer_id;
|
||||||
|
|
||||||
|
if (!pb_encode_submessage(stream, &zmk_keymap_Layer_msg, &layer)) {
|
||||||
|
LOG_WRN("Failed to encode layer submessage");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
zmk_studio_Response get_keymap(const zmk_studio_Request *req) {
|
||||||
|
zmk_keymap_Keymap resp = zmk_keymap_Keymap_init_zero;
|
||||||
|
|
||||||
|
resp.layers.funcs.encode = encode_keymap_layers;
|
||||||
|
|
||||||
|
resp.available_layers = 0;
|
||||||
|
|
||||||
|
for (zmk_keymap_layer_index_t index = 0; index < ZMK_KEYMAP_LAYERS_LEN; index++) {
|
||||||
|
zmk_keymap_layer_id_t id = zmk_keymap_layer_index_to_id(index);
|
||||||
|
|
||||||
|
if (id == UINT8_MAX) {
|
||||||
|
resp.available_layers = ZMK_KEYMAP_LAYERS_LEN - index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return KEYMAP_RESPONSE(get_keymap, resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
zmk_studio_Response set_layer_binding(const zmk_studio_Request *req) {
|
||||||
|
const zmk_keymap_SetLayerBindingRequest *set_req =
|
||||||
|
&req->subsystem.keymap.request_type.set_layer_binding;
|
||||||
|
|
||||||
|
zmk_behavior_local_id_t bid = set_req->binding.behavior_id;
|
||||||
|
|
||||||
|
const char *behavior_name = zmk_behavior_find_behavior_name_from_local_id(bid);
|
||||||
|
|
||||||
|
if (!behavior_name) {
|
||||||
|
return KEYMAP_RESPONSE(
|
||||||
|
set_layer_binding,
|
||||||
|
zmk_keymap_SetLayerBindingResponse_SET_LAYER_BINDING_RESP_INVALID_BEHAVIOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct zmk_behavior_binding binding = (struct zmk_behavior_binding){
|
||||||
|
.behavior_dev = behavior_name,
|
||||||
|
.param1 = set_req->binding.param1,
|
||||||
|
.param2 = set_req->binding.param2,
|
||||||
|
};
|
||||||
|
|
||||||
|
int ret = zmk_behavior_validate_binding(&binding);
|
||||||
|
if (ret < 0) {
|
||||||
|
return KEYMAP_RESPONSE(
|
||||||
|
set_layer_binding,
|
||||||
|
zmk_keymap_SetLayerBindingResponse_SET_LAYER_BINDING_RESP_INVALID_PARAMETERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = zmk_keymap_set_layer_binding_at_idx(set_req->layer_id, set_req->key_position, binding);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_WRN("Setting the binding failed with %d", ret);
|
||||||
|
switch (ret) {
|
||||||
|
case -EINVAL:
|
||||||
|
return KEYMAP_RESPONSE(
|
||||||
|
set_layer_binding,
|
||||||
|
zmk_keymap_SetLayerBindingResponse_SET_LAYER_BINDING_RESP_INVALID_LOCATION);
|
||||||
|
default:
|
||||||
|
return ZMK_RPC_SIMPLE_ERR(GENERIC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
raise_zmk_studio_rpc_notification((struct zmk_studio_rpc_notification){
|
||||||
|
.notification = KEYMAP_NOTIFICATION(unsaved_changes_status_changed, true)});
|
||||||
|
|
||||||
|
return KEYMAP_RESPONSE(set_layer_binding,
|
||||||
|
zmk_keymap_SetLayerBindingResponse_SET_LAYER_BINDING_RESP_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
zmk_studio_Response check_unsaved_changes(const zmk_studio_Request *req) {
|
||||||
|
int layout_changes = zmk_physical_layouts_check_unsaved_selection();
|
||||||
|
int keymap_changes = zmk_keymap_check_unsaved_changes();
|
||||||
|
|
||||||
|
return KEYMAP_RESPONSE(check_unsaved_changes, layout_changes > 0 || keymap_changes > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
zmk_studio_Response save_changes(const zmk_studio_Request *req) {
|
||||||
|
int ret = zmk_physical_layouts_save_selected();
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
return ZMK_RPC_SIMPLE_ERR(GENERIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = zmk_keymap_save_changes();
|
||||||
|
if (ret < 0) {
|
||||||
|
return ZMK_RPC_SIMPLE_ERR(GENERIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
raise_zmk_studio_rpc_notification((struct zmk_studio_rpc_notification){
|
||||||
|
.notification = KEYMAP_NOTIFICATION(unsaved_changes_status_changed, false)});
|
||||||
|
|
||||||
|
return KEYMAP_RESPONSE(save_changes, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
zmk_studio_Response discard_changes(const zmk_studio_Request *req) {
|
||||||
|
int ret = zmk_physical_layouts_revert_selected();
|
||||||
|
if (ret < 0) {
|
||||||
|
return ZMK_RPC_SIMPLE_ERR(GENERIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = zmk_keymap_discard_changes();
|
||||||
|
if (ret < 0) {
|
||||||
|
return ZMK_RPC_SIMPLE_ERR(GENERIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
raise_zmk_studio_rpc_notification((struct zmk_studio_rpc_notification){
|
||||||
|
.notification = KEYMAP_NOTIFICATION(unsaved_changes_status_changed, false)});
|
||||||
|
|
||||||
|
return KEYMAP_RESPONSE(discard_changes, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int keymap_settings_reset(void) { return zmk_keymap_reset_settings(); }
|
||||||
|
|
||||||
|
ZMK_RPC_SUBSYSTEM_SETTINGS_RESET(keymap, keymap_settings_reset);
|
||||||
|
|
||||||
|
static bool encode_layout_name(pb_ostream_t *stream, const pb_field_t *field, void *const *arg) {
|
||||||
|
struct zmk_physical_layout *layout = (struct zmk_physical_layout *)*arg;
|
||||||
|
|
||||||
|
if (!layout->display_name) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pb_encode_tag_for_field(stream, field)) {
|
||||||
|
LOG_WRN("Failed to encode tag");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pb_encode_string(stream, layout->display_name, strlen(layout->display_name));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool encode_layout_keys(pb_ostream_t *stream, const pb_field_t *field, void *const *arg) {
|
||||||
|
struct zmk_physical_layout *layout = (struct zmk_physical_layout *)*arg;
|
||||||
|
|
||||||
|
for (int kp = 0; kp < layout->keys_len; kp++) {
|
||||||
|
const struct zmk_key_physical_attrs *layout_kp = &layout->keys[kp];
|
||||||
|
|
||||||
|
if (!pb_encode_tag_for_field(stream, field)) {
|
||||||
|
LOG_WRN("Failed to encode tag");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
zmk_keymap_KeyPhysicalAttrs layout_kp_msg = {
|
||||||
|
.width = layout_kp->width,
|
||||||
|
.height = layout_kp->height,
|
||||||
|
.x = layout_kp->x,
|
||||||
|
.y = layout_kp->y,
|
||||||
|
.r = layout_kp->r,
|
||||||
|
.rx = layout_kp->rx,
|
||||||
|
.ry = layout_kp->ry,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!pb_encode_submessage(stream, &zmk_keymap_KeyPhysicalAttrs_msg, &layout_kp_msg)) {
|
||||||
|
LOG_WRN("Failed to encode layout key position submessage");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool encode_layouts(pb_ostream_t *stream, const pb_field_t *field, void *const *arg) {
|
||||||
|
struct zmk_physical_layout const *const *layouts;
|
||||||
|
const size_t layout_count = zmk_physical_layouts_get_list(&layouts);
|
||||||
|
|
||||||
|
for (int i = 0; i < layout_count; i++) {
|
||||||
|
const struct zmk_physical_layout *l = layouts[i];
|
||||||
|
|
||||||
|
if (!pb_encode_tag_for_field(stream, field)) {
|
||||||
|
LOG_WRN("Failed to encode tag");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
zmk_keymap_PhysicalLayout layout = zmk_keymap_PhysicalLayout_init_zero;
|
||||||
|
|
||||||
|
layout.name.funcs.encode = encode_layout_name;
|
||||||
|
layout.name.arg = l;
|
||||||
|
|
||||||
|
layout.keys.funcs.encode = encode_layout_keys;
|
||||||
|
layout.keys.arg = l;
|
||||||
|
|
||||||
|
if (!pb_encode_submessage(stream, &zmk_keymap_PhysicalLayout_msg, &layout)) {
|
||||||
|
LOG_WRN("Failed to encode layout submessage");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
zmk_studio_Response get_physical_layouts(const zmk_studio_Request *req) {
|
||||||
|
zmk_keymap_PhysicalLayouts resp = zmk_keymap_PhysicalLayouts_init_zero;
|
||||||
|
resp.active_layout_index = zmk_physical_layouts_get_selected();
|
||||||
|
resp.layouts.funcs.encode = encode_layouts;
|
||||||
|
return KEYMAP_RESPONSE(get_physical_layouts, resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void migrate_keymap(const uint8_t old) {
|
||||||
|
int new = zmk_physical_layouts_get_selected();
|
||||||
|
|
||||||
|
uint32_t new_to_old_map[ZMK_KEYMAP_LEN];
|
||||||
|
int layout_size =
|
||||||
|
zmk_physical_layouts_get_position_map(old, new, ZMK_KEYMAP_LEN, new_to_old_map);
|
||||||
|
|
||||||
|
if (layout_size < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int l = 0; l < ZMK_KEYMAP_LAYERS_LEN; l++) {
|
||||||
|
struct zmk_behavior_binding new_layer[ZMK_KEYMAP_LEN];
|
||||||
|
|
||||||
|
for (int b = 0; b < layout_size; b++) {
|
||||||
|
uint32_t old_b = new_to_old_map[b];
|
||||||
|
|
||||||
|
if (old_b == UINT32_MAX) {
|
||||||
|
memset(&new_layer[b], 0, sizeof(struct zmk_behavior_binding));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct zmk_behavior_binding *binding =
|
||||||
|
zmk_keymap_get_layer_binding_at_idx(l, old_b);
|
||||||
|
|
||||||
|
if (!binding) {
|
||||||
|
memset(&new_layer[b], 0, sizeof(struct zmk_behavior_binding));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&new_layer[b], binding, sizeof(struct zmk_behavior_binding));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int b = 0; b < layout_size; b++) {
|
||||||
|
zmk_keymap_set_layer_binding_at_idx(l, b, new_layer[b]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Migrate combos?
|
||||||
|
}
|
||||||
|
|
||||||
|
zmk_studio_Response set_active_physical_layout(const zmk_studio_Request *req) {
|
||||||
|
uint8_t index = (uint8_t)req->subsystem.keymap.request_type.set_active_physical_layout;
|
||||||
|
int old = zmk_physical_layouts_get_selected();
|
||||||
|
|
||||||
|
zmk_keymap_SetActivePhysicalLayoutResponse resp =
|
||||||
|
zmk_keymap_SetActivePhysicalLayoutResponse_init_zero;
|
||||||
|
resp.which_result = zmk_keymap_SetActivePhysicalLayoutResponse_ok_tag;
|
||||||
|
resp.result.ok.layers.funcs.encode = encode_keymap_layers;
|
||||||
|
|
||||||
|
if (old == index) {
|
||||||
|
return KEYMAP_RESPONSE(set_active_physical_layout, resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = zmk_physical_layouts_select(index);
|
||||||
|
if (ret >= 0) {
|
||||||
|
migrate_keymap(old);
|
||||||
|
} else {
|
||||||
|
resp.which_result = zmk_keymap_SetActivePhysicalLayoutResponse_err_tag;
|
||||||
|
resp.result.err =
|
||||||
|
zmk_keymap_SetActivePhysicalLayoutErrorCode_SET_ACTIVE_PHYSICAL_LAYOUT_ERR_GENERIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
raise_zmk_studio_rpc_notification((struct zmk_studio_rpc_notification){
|
||||||
|
.notification = KEYMAP_NOTIFICATION(unsaved_changes_status_changed, true)});
|
||||||
|
|
||||||
|
return KEYMAP_RESPONSE(set_active_physical_layout, resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
zmk_studio_Response move_layer(const zmk_studio_Request *req) {
|
||||||
|
const zmk_keymap_MoveLayerRequest *move_req = &req->subsystem.keymap.request_type.move_layer;
|
||||||
|
|
||||||
|
zmk_keymap_MoveLayerResponse resp = zmk_keymap_MoveLayerResponse_init_zero;
|
||||||
|
|
||||||
|
int ret = zmk_keymap_move_layer(move_req->start_index, move_req->dest_index);
|
||||||
|
|
||||||
|
if (ret >= 0) {
|
||||||
|
resp.which_result = zmk_keymap_SetActivePhysicalLayoutResponse_ok_tag;
|
||||||
|
resp.result.ok.layers.funcs.encode = encode_keymap_layers;
|
||||||
|
|
||||||
|
raise_zmk_studio_rpc_notification((struct zmk_studio_rpc_notification){
|
||||||
|
.notification = KEYMAP_NOTIFICATION(unsaved_changes_status_changed, true)});
|
||||||
|
} else {
|
||||||
|
LOG_WRN("Failed to move layer: %d", ret);
|
||||||
|
resp.which_result = zmk_keymap_MoveLayerResponse_err_tag;
|
||||||
|
resp.result.err = zmk_keymap_MoveLayerErrorCode_MOVE_LAYER_ERR_GENERIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
return KEYMAP_RESPONSE(move_layer, resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
zmk_studio_Response add_layer(const zmk_studio_Request *req) {
|
||||||
|
// Use a static here to keep the value valid during serialization
|
||||||
|
static zmk_keymap_layer_id_t layer_id = 0;
|
||||||
|
|
||||||
|
zmk_keymap_AddLayerResponse resp = zmk_keymap_AddLayerResponse_init_zero;
|
||||||
|
|
||||||
|
int ret = zmk_keymap_add_layer();
|
||||||
|
|
||||||
|
if (ret >= 0) {
|
||||||
|
layer_id = zmk_keymap_layer_index_to_id(ret);
|
||||||
|
|
||||||
|
resp.which_result = zmk_keymap_AddLayerResponse_ok_tag;
|
||||||
|
|
||||||
|
resp.result.ok.index = ret;
|
||||||
|
|
||||||
|
resp.result.ok.has_layer = true;
|
||||||
|
resp.result.ok.layer.id = layer_id;
|
||||||
|
|
||||||
|
resp.result.ok.layer.name.funcs.encode = encode_layer_name;
|
||||||
|
resp.result.ok.layer.name.arg = &layer_id;
|
||||||
|
|
||||||
|
resp.result.ok.layer.bindings.funcs.encode = encode_layer_bindings;
|
||||||
|
resp.result.ok.layer.bindings.arg = &layer_id;
|
||||||
|
|
||||||
|
raise_zmk_studio_rpc_notification((struct zmk_studio_rpc_notification){
|
||||||
|
.notification = KEYMAP_NOTIFICATION(unsaved_changes_status_changed, true)});
|
||||||
|
} else {
|
||||||
|
LOG_WRN("Failed to add layer: %d", ret);
|
||||||
|
resp.which_result = zmk_keymap_AddLayerResponse_err_tag;
|
||||||
|
switch (ret) {
|
||||||
|
case -ENOSPC:
|
||||||
|
resp.result.err = zmk_keymap_AddLayerErrorCode_ADD_LAYER_ERR_NO_SPACE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
resp.result.err = zmk_keymap_AddLayerErrorCode_ADD_LAYER_ERR_GENERIC;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return KEYMAP_RESPONSE(add_layer, resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
zmk_studio_Response remove_layer(const zmk_studio_Request *req) {
|
||||||
|
const zmk_keymap_RemoveLayerRequest *rm_req = &req->subsystem.keymap.request_type.remove_layer;
|
||||||
|
|
||||||
|
zmk_keymap_RemoveLayerResponse resp = zmk_keymap_RemoveLayerResponse_init_zero;
|
||||||
|
|
||||||
|
int ret = zmk_keymap_remove_layer(rm_req->layer_index);
|
||||||
|
|
||||||
|
if (ret >= 0) {
|
||||||
|
resp.which_result = zmk_keymap_RemoveLayerResponse_ok_tag;
|
||||||
|
|
||||||
|
raise_zmk_studio_rpc_notification((struct zmk_studio_rpc_notification){
|
||||||
|
.notification = KEYMAP_NOTIFICATION(unsaved_changes_status_changed, true)});
|
||||||
|
} else {
|
||||||
|
LOG_WRN("Failed to rm layer: %d", ret);
|
||||||
|
resp.which_result = zmk_keymap_RemoveLayerResponse_err_tag;
|
||||||
|
switch (ret) {
|
||||||
|
case -EINVAL:
|
||||||
|
resp.result.err = zmk_keymap_RemoveLayerErrorCode_REMOVE_LAYER_ERR_INVALID_INDEX;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
resp.result.err = zmk_keymap_RemoveLayerErrorCode_REMOVE_LAYER_ERR_GENERIC;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return KEYMAP_RESPONSE(remove_layer, resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
zmk_studio_Response restore_layer(const zmk_studio_Request *req) {
|
||||||
|
const zmk_keymap_RestoreLayerRequest *restore_req =
|
||||||
|
&req->subsystem.keymap.request_type.restore_layer;
|
||||||
|
|
||||||
|
zmk_keymap_RestoreLayerResponse resp = zmk_keymap_RestoreLayerResponse_init_zero;
|
||||||
|
|
||||||
|
int ret = zmk_keymap_restore_layer(restore_req->layer_id, restore_req->at_index);
|
||||||
|
|
||||||
|
if (ret >= 0) {
|
||||||
|
resp.which_result = zmk_keymap_RemoveLayerResponse_ok_tag;
|
||||||
|
resp.result.ok.id = restore_req->layer_id;
|
||||||
|
|
||||||
|
resp.result.ok.name.funcs.encode = encode_layer_name;
|
||||||
|
resp.result.ok.name.arg = &restore_req->layer_id;
|
||||||
|
|
||||||
|
resp.result.ok.bindings.funcs.encode = encode_layer_bindings;
|
||||||
|
resp.result.ok.bindings.arg = &restore_req->layer_id;
|
||||||
|
|
||||||
|
raise_zmk_studio_rpc_notification((struct zmk_studio_rpc_notification){
|
||||||
|
.notification = KEYMAP_NOTIFICATION(unsaved_changes_status_changed, true)});
|
||||||
|
} else {
|
||||||
|
LOG_WRN("Failed to restore layer: %d", ret);
|
||||||
|
resp.which_result = zmk_keymap_RestoreLayerResponse_err_tag;
|
||||||
|
switch (ret) {
|
||||||
|
case -EINVAL:
|
||||||
|
resp.result.err = zmk_keymap_RestoreLayerErrorCode_RESTORE_LAYER_ERR_INVALID_INDEX;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
resp.result.err = zmk_keymap_RestoreLayerErrorCode_RESTORE_LAYER_ERR_GENERIC;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return KEYMAP_RESPONSE(restore_layer, resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
zmk_studio_Response set_layer_props(const zmk_studio_Request *req) {
|
||||||
|
const zmk_keymap_SetLayerPropsRequest *set_req =
|
||||||
|
&req->subsystem.keymap.request_type.set_layer_props;
|
||||||
|
|
||||||
|
zmk_keymap_SetLayerPropsResponse resp =
|
||||||
|
zmk_keymap_SetLayerPropsResponse_SET_LAYER_PROPS_RESP_OK;
|
||||||
|
|
||||||
|
if (strlen(set_req->name) <= 0) {
|
||||||
|
return KEYMAP_RESPONSE(set_layer_props, resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = zmk_keymap_set_layer_name(set_req->layer_id, set_req->name, strlen(set_req->name));
|
||||||
|
|
||||||
|
if (ret >= 0) {
|
||||||
|
|
||||||
|
raise_zmk_studio_rpc_notification((struct zmk_studio_rpc_notification){
|
||||||
|
.notification = KEYMAP_NOTIFICATION(unsaved_changes_status_changed, true)});
|
||||||
|
} else {
|
||||||
|
LOG_WRN("Failed to set layer props: %d", ret);
|
||||||
|
switch (ret) {
|
||||||
|
case -EINVAL:
|
||||||
|
resp = zmk_keymap_SetLayerPropsResponse_SET_LAYER_PROPS_RESP_ERR_INVALID_ID;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
resp = zmk_keymap_SetLayerPropsResponse_SET_LAYER_PROPS_RESP_ERR_GENERIC;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return KEYMAP_RESPONSE(set_layer_props, resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZMK_RPC_SUBSYSTEM_HANDLER(keymap, get_keymap, ZMK_STUDIO_RPC_HANDLER_SECURED);
|
||||||
|
ZMK_RPC_SUBSYSTEM_HANDLER(keymap, set_layer_binding, ZMK_STUDIO_RPC_HANDLER_SECURED);
|
||||||
|
ZMK_RPC_SUBSYSTEM_HANDLER(keymap, check_unsaved_changes, ZMK_STUDIO_RPC_HANDLER_SECURED);
|
||||||
|
ZMK_RPC_SUBSYSTEM_HANDLER(keymap, save_changes, ZMK_STUDIO_RPC_HANDLER_SECURED);
|
||||||
|
ZMK_RPC_SUBSYSTEM_HANDLER(keymap, discard_changes, ZMK_STUDIO_RPC_HANDLER_SECURED);
|
||||||
|
ZMK_RPC_SUBSYSTEM_HANDLER(keymap, get_physical_layouts, ZMK_STUDIO_RPC_HANDLER_SECURED);
|
||||||
|
ZMK_RPC_SUBSYSTEM_HANDLER(keymap, set_active_physical_layout, ZMK_STUDIO_RPC_HANDLER_SECURED);
|
||||||
|
ZMK_RPC_SUBSYSTEM_HANDLER(keymap, move_layer, ZMK_STUDIO_RPC_HANDLER_SECURED);
|
||||||
|
ZMK_RPC_SUBSYSTEM_HANDLER(keymap, add_layer, ZMK_STUDIO_RPC_HANDLER_SECURED);
|
||||||
|
ZMK_RPC_SUBSYSTEM_HANDLER(keymap, remove_layer, ZMK_STUDIO_RPC_HANDLER_SECURED);
|
||||||
|
ZMK_RPC_SUBSYSTEM_HANDLER(keymap, restore_layer, ZMK_STUDIO_RPC_HANDLER_SECURED);
|
||||||
|
ZMK_RPC_SUBSYSTEM_HANDLER(keymap, set_layer_props, ZMK_STUDIO_RPC_HANDLER_SECURED);
|
||||||
|
|
||||||
|
static int event_mapper(const zmk_event_t *eh, zmk_studio_Notification *n) { return 0; }
|
||||||
|
|
||||||
|
ZMK_RPC_EVENT_MAPPER(keymap, event_mapper);
|
|
@ -245,7 +245,7 @@ static void refresh_selected_transport(void) {
|
||||||
k_mutex_lock(&rpc_transport_mutex, K_FOREVER);
|
k_mutex_lock(&rpc_transport_mutex, K_FOREVER);
|
||||||
|
|
||||||
if (selected_transport && selected_transport->transport == transport) {
|
if (selected_transport && selected_transport->transport == transport) {
|
||||||
return;
|
goto exit_refresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selected_transport) {
|
if (selected_transport) {
|
||||||
|
@ -272,6 +272,7 @@ static void refresh_selected_transport(void) {
|
||||||
LOG_WRN("Failed to select a transport!");
|
LOG_WRN("Failed to select a transport!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit_refresh:
|
||||||
k_mutex_unlock(&rpc_transport_mutex);
|
k_mutex_unlock(&rpc_transport_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
pos_state: layer: 0 position: 0, binding name: abc_macro
|
pos_state: layer_id: 0 position: 0, binding name: abc_macro
|
||||||
kp_pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
kp_pressed: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||||
pos_state: layer: 0 position: 0, binding name: abc_macro
|
pos_state: layer_id: 0 position: 0, binding name: abc_macro
|
||||||
pos_state: layer: 0 position: 1, binding name: momentary_layer
|
pos_state: layer_id: 0 position: 1, binding name: momentary_layer
|
||||||
pos_state: layer: 0 position: 1, binding name: momentary_layer
|
pos_state: layer_id: 0 position: 1, binding name: momentary_layer
|
||||||
kp_released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
kp_released: usage_page 0x07 keycode 0x04 implicit_mods 0x00 explicit_mods 0x00
|
||||||
kp_pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
kp_pressed: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
||||||
kp_released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
kp_released: usage_page 0x07 keycode 0x05 implicit_mods 0x00 explicit_mods 0x00
|
||||||
|
|
|
@ -34,7 +34,7 @@ manifest:
|
||||||
path: modules/lib/nanopb
|
path: modules/lib/nanopb
|
||||||
remote: zephyrproject-rtos
|
remote: zephyrproject-rtos
|
||||||
- name: zmk-studio-messages
|
- name: zmk-studio-messages
|
||||||
revision: 42446798e357e8021c5202a01ea250a34a776e85
|
revision: a79267a9661241a6603b6da3d2b3f71e8023a9d9
|
||||||
path: modules/msgs/zmk-studio-messages
|
path: modules/msgs/zmk-studio-messages
|
||||||
remote: zmkfirmware
|
remote: zmkfirmware
|
||||||
self:
|
self:
|
||||||
|
|
41
docs/docs/config/studio.md
Normal file
41
docs/docs/config/studio.md
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
---
|
||||||
|
title: ZMK Studio Configuration
|
||||||
|
sidebar_label: ZMK Studio
|
||||||
|
---
|
||||||
|
|
||||||
|
:::warning[Alpha Feature]
|
||||||
|
|
||||||
|
ZMK Studio is still in active development and the below information is for development purposes only. For up to date information, join the [ZMK Discord](https://zmk.dev/community/discord/invite) server and discuss in `#studio-development`.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
The following settings affect the ZMK Studio portions of ZMK. See the [ZMK Studio feature](../features/studio.md) for more information on enabling and building with ZMK Studio enabled.
|
||||||
|
|
||||||
|
See [Configuration Overview](index.md) for instructions on how to change these settings.
|
||||||
|
|
||||||
|
## Kconfig
|
||||||
|
|
||||||
|
Definition file: [zmk/app/src/studio/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/app/src/studio/Kconfig)
|
||||||
|
|
||||||
|
### Keymaps
|
||||||
|
|
||||||
|
| Config | Type | Description | Default |
|
||||||
|
| -------------------------------------- | ---- | --------------------------------------- | ------- |
|
||||||
|
| `CONFIG_ZMK_KEYMAP_LAYER_NAME_MAX_LEN` | int | Max allowable keymap layer display name | 20 |
|
||||||
|
|
||||||
|
### Locking
|
||||||
|
|
||||||
|
| Config | Type | Description | Default |
|
||||||
|
| ----------------------------------------- | ---- | ----------------------------------------------------------------------------------- | ------- |
|
||||||
|
| `CONFIG_ZMK_STUDIO_LOCKING` | bool | Enable/disable locking for ZMK Studio | y |
|
||||||
|
| `CONFIG_ZMK_STUDIO_LOCK_IDLE_TIMEOUT_SEC` | int | Seconds of inactivity in ZMK Studio before automatically locking | 500 |
|
||||||
|
| `CONFIG_ZMK_STUDIO_LOCK_ON_DISCONNECT` | bool | Whether to automatically lock again whenever ZMK Studio disconnects from the device | y |
|
||||||
|
|
||||||
|
### Transport/Protocol Details
|
||||||
|
|
||||||
|
| Config | Type | Description | Default |
|
||||||
|
| ---------------------------------------------- | ---- | ----------------------------------------------------------------------------- | ------- |
|
||||||
|
| `CONFIG_ZMK_STUDIO_TRANSPORT_BLE_PREF_LATENCY` | int | Lower latency to request while ZMK Studio is active to improve responsiveness | 10 |
|
||||||
|
| `CONFIG_ZMK_STUDIO_RPC_THREAD_STACK_SIZE` | int | Stack size for the dedicated RPC thread | 1800 |
|
||||||
|
| `CONFIG_ZMK_STUDIO_RPC_RX_BUF_SIZE` | int | Number of bytes available for buffering incoming messages | 30 |
|
||||||
|
| `CONFIG_ZMK_STUDIO_RPC_TX_BUF_SIZE` | int | Number of bytes available for buffering outgoing messages | 64 |
|
134
docs/docs/development/hardware-integration/studio-setup.md
Normal file
134
docs/docs/development/hardware-integration/studio-setup.md
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
---
|
||||||
|
title: ZMK Studio Setup
|
||||||
|
---
|
||||||
|
|
||||||
|
:::warning[Alpha Feature]
|
||||||
|
|
||||||
|
ZMK Studio support is in alpha. Although best efforts are being made, backwards compatibility during active development is not guaranteed.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
This guide will walk you through enabling ZMK Studio support for a keyboard.
|
||||||
|
|
||||||
|
The main additional pieces needed for ZMK Studio support involve additional metadata needed in order
|
||||||
|
to properly to display the physical layouts available for the particular keyboard.
|
||||||
|
|
||||||
|
# Physical Layout Positions
|
||||||
|
|
||||||
|
Physical layouts are described as part of the [new shield guide](./new-shield.mdx#physical-layouts) with the exception of the `keys` property that is required for ZMK Studio support. This is used to describe the physical attributes of each key position present in that layout and its items are listed in the same order as keymap bindings, matrix transforms, etc. The properties available are:
|
||||||
|
|
||||||
|
| Property | Type | Description | Unit |
|
||||||
|
| ---------- | -------- | ------------------------------------ | ------------------------------------------------------- |
|
||||||
|
| Width | int (>0) | Key(cap) width | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" |
|
||||||
|
| Height | int (>0) | Key(cap) height | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" |
|
||||||
|
| X | uint | Key X position (top-left point) | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" |
|
||||||
|
| Y | uint | Key Y position (top-left point) | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" |
|
||||||
|
| Rotation | int | Key rotation (positive => clockwise) | [centi-](https://en.wikipedia.org/wiki/Centi-)degree |
|
||||||
|
| Rotation X | int | Rotation origin X position | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" |
|
||||||
|
| Rotation Y | int | Rotation origin Y position | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" |
|
||||||
|
|
||||||
|
:::note
|
||||||
|
You can specify negative values in devicetree using parentheses around it, e.g. `(-3000)` for a 30 degree counterclockwise rotation.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Header Include
|
||||||
|
|
||||||
|
To pull in the necessary definition for creating physical layouts, a new include should be added to the top of the devicetree file:
|
||||||
|
|
||||||
|
```
|
||||||
|
#include <physical_layouts.dtsi>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
Here is an example physical layout for a 2x2 macropad:
|
||||||
|
|
||||||
|
```dts
|
||||||
|
macropad_physical_layout: macropad_physical_layout {
|
||||||
|
compatible = "zmk,physical-layout";
|
||||||
|
display-name = "Macro Pad";
|
||||||
|
|
||||||
|
keys // w h x y rot rx ry
|
||||||
|
= <&key_physical_attrs 100 100 0 0 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 0 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 0 100 0 0 0>
|
||||||
|
, <&key_physical_attrs 100 100 100 100 0 0 0>
|
||||||
|
;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
# Position Map
|
||||||
|
|
||||||
|
When switching between layouts with ZMK Studio, the keymap of the previously selected layout is used to populate the keymap in the new layout. To determine which keymap entry maps to which entry in the new layout, keys between the two layouts that share the exact same physical attributes are matched.
|
||||||
|
|
||||||
|
However, keys between layouts might not be in exactly the same positions, in which case a position map can be used. The position map includes a sequence for every relevant layout, and the corresponding entries in `positions` property will be used to determine the mapping between layouts. By default, the physical attribute matching behavior will be used as a fallback for positions not specified in the map, but the `complete` property can be added to the map to specify that no matching fallback should occur.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Basic Map
|
||||||
|
|
||||||
|
For example, the following position map correctly maps the 5-column and 6-column Corne keymap layouts.
|
||||||
|
|
||||||
|
```dts
|
||||||
|
foostan_corne_position_map {
|
||||||
|
compatible = "zmk,physical-layout-position-map";
|
||||||
|
|
||||||
|
complete;
|
||||||
|
|
||||||
|
twelve {
|
||||||
|
physical-layout = <&foostan_corne_6col_layout>;
|
||||||
|
positions
|
||||||
|
= < 1 2 3 4 5 6 7 8 9 10>
|
||||||
|
, <13 14 15 16 17 18 19 20 21 22>
|
||||||
|
, <25 26 27 28 29 30 31 32 33 34>
|
||||||
|
, < 36 37 38 39 40 41 >;
|
||||||
|
};
|
||||||
|
|
||||||
|
ten {
|
||||||
|
physical-layout = <&foostan_corne_5col_layout>;
|
||||||
|
positions
|
||||||
|
= < 0 1 2 3 4 5 6 7 8 9>
|
||||||
|
, <10 11 12 13 14 15 16 17 18 19>
|
||||||
|
, <20 21 22 23 24 25 26 27 28 29>
|
||||||
|
, < 30 31 32 33 34 35 >;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
The first entries in the two mappings have values `1` and `0` respectively, which means that the zero-th entry in the 5-column will map to the first entry in the 6-column layout, the second entries show that the second 6-column keymap entry corresponds to the first 5-column entry, etc.
|
||||||
|
|
||||||
|
### Full Preserving Map
|
||||||
|
|
||||||
|
The above basic example has one major downside. Because the keys on the outer columns of the 6-column layout aren't mapped into any locations in the 5-column layout, when a user switches to the 5-column layout and then back to the 6-column layout, the bindings for those outer columns will have been lost/dropped at the first step.
|
||||||
|
|
||||||
|
In order to preserve those bindings that are in "missing" keys in other layouts, we can include those locations in the map, but map them "off the end" of the smaller layout key positions.
|
||||||
|
|
||||||
|
Here is a fixed up Corne mapping:
|
||||||
|
|
||||||
|
```dts
|
||||||
|
foostan_corne_position_map {
|
||||||
|
compatible = "zmk,physical-layout-position-map";
|
||||||
|
|
||||||
|
complete;
|
||||||
|
|
||||||
|
twelve {
|
||||||
|
physical-layout = <&foostan_corne_6col_layout>;
|
||||||
|
positions
|
||||||
|
= < 0 1 2 3 4 5 6 7 8 9 10 11>
|
||||||
|
, <12 13 14 15 16 17 18 19 20 21 22 23>
|
||||||
|
, <24 25 26 27 28 29 30 31 32 33 34 35>
|
||||||
|
, < 36 37 38 39 40 41 >;
|
||||||
|
};
|
||||||
|
|
||||||
|
ten {
|
||||||
|
physical-layout = <&foostan_corne_5col_layout>;
|
||||||
|
positions
|
||||||
|
= <36 0 1 2 3 4 5 6 7 8 9 37>
|
||||||
|
, <38 10 11 12 13 14 15 16 17 18 19 39>
|
||||||
|
, <40 20 21 22 23 24 25 26 27 28 29 41>
|
||||||
|
, < 30 31 32 33 34 35 >;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Notice how the outer column positions in the 6-column layout are mapped to positions 36, 37, etc. in the 5-column layout. The 5-column layout only uses key positions up to 35, so those bindings in the outer columns will get migrated into the "extra space" that is ignored by the smaller layout, preserved to get mapped back in place when the user switches back.
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
title: Studio RPC Protocol
|
title: ZMK Studio RPC Protocol
|
||||||
---
|
---
|
||||||
|
|
||||||
:::warning[Alpha Feature]
|
:::warning[Alpha Feature]
|
||||||
|
@ -20,13 +20,13 @@ The protocol consists of [protocol buffer](https://protobuf.dev/programming-guid
|
||||||
|
|
||||||
## Protobuf Messages
|
## Protobuf Messages
|
||||||
|
|
||||||
The messages for ZMK Studio are defined in a dedicated [zmk-studio-messages](https://github.com/zmkfirmware/zmk-studio-messages) repository. Fundamentally, the [`Request`](https://github.com/zmkfirmware/zmk-studio-messages/blob/main/proto/zmk/studio.proto#L11) message is used to send any requests from the Studio client to the ZMK device, and the [`Response`](https://github.com/zmkfirmware/zmk-studio-messages/blob/main/proto/zmk/studio.proto#L21) messages are sent from the ZMK device to the Studio client.
|
The messages for ZMK Studio are defined in a dedicated [zmk-studio-messages](https://github.com/zmkfirmware/zmk-studio-messages) repository. Fundamentally, the [`Request`](https://github.com/zmkfirmware/zmk-studio-messages/blob/main/proto/zmk/studio.proto#L11) message is used to send any requests from the ZMK Studio client to the ZMK device, and the [`Response`](https://github.com/zmkfirmware/zmk-studio-messages/blob/main/proto/zmk/studio.proto#L21) messages are sent from the ZMK device to the Studio client.
|
||||||
|
|
||||||
Responses can either be [`RequestResponses`](https://github.com/zmkfirmware/zmk-studio-messages/blob/main/proto/zmk/studio.proto#L28) that are sent in response to an incoming `Request` or a [`Notification`](https://github.com/zmkfirmware/zmk-studio-messages/blob/main/proto/zmk/studio.proto#L38) which is sent at any point from the ZMK device to the Studio client to inform the client about state changes on the device, e.g. that the device is unlocked.
|
Responses can either be [`RequestResponses`](https://github.com/zmkfirmware/zmk-studio-messages/blob/main/proto/zmk/studio.proto#L28) that are sent in response to an incoming `Request` or a [`Notification`](https://github.com/zmkfirmware/zmk-studio-messages/blob/main/proto/zmk/studio.proto#L38) which is sent at any point from the ZMK device to the ZMK Studio client to inform the client about state changes on the device, e.g. that the device is unlocked.
|
||||||
|
|
||||||
## Message Framing
|
## Message Framing
|
||||||
|
|
||||||
Studio uses a simple framing protocol to easily identify the start and end of a given message, with basic escaping to allow for unrestricted content.
|
ZMK Studio uses a simple framing protocol to easily identify the start and end of a given message, with basic escaping to allow for unrestricted content.
|
||||||
|
|
||||||
The following special bytes are used for the framing protocol:
|
The following special bytes are used for the framing protocol:
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ Two transports are available right now, over USB or Bluetooth connections.
|
||||||
|
|
||||||
### USB (Serial)
|
### USB (Serial)
|
||||||
|
|
||||||
The USB transport is actually a basic serial/UART transport, that happens to use the CDC/ACM USB class for a serial connection. Framed messages are sent between Studio client and ZMK device using simple UART transmission.
|
The USB transport is actually a basic serial/UART transport, that happens to use the CDC/ACM USB class for a serial connection. Framed messages are sent between ZMK Studio client and ZMK device using simple UART transmission.
|
||||||
|
|
||||||
### Bluetooth (GATT)
|
### Bluetooth (GATT)
|
||||||
|
|
||||||
|
|
111
docs/docs/features/studio.md
Normal file
111
docs/docs/features/studio.md
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
---
|
||||||
|
title: ZMK Studio
|
||||||
|
---
|
||||||
|
|
||||||
|
:::warning[Alpha Feature]
|
||||||
|
|
||||||
|
ZMK Studio support is in alpha. Although best efforts are being made, keeping compatibility during active development is not guaranteed.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
ZMK Studio provides runtime update functionality to ZMK powered devices, allowing users to change their keymap layers without flashing new firmware to their keyboards. Studio is still under active development, and is not yet ready for casual end user use.
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
Building for ZMK Studio involves two main additional items.
|
||||||
|
|
||||||
|
- Build with the `studio-rpc-usb-uart` snippet to enable the endpoint used for ZMK Studio communication over USB.
|
||||||
|
- Enable the `ZMK_STUDIO` Kconfig setting.
|
||||||
|
|
||||||
|
### GitHub Actions
|
||||||
|
|
||||||
|
First add a `studio-rpc-usb-uart` to the `snippet` property of your build configuration. For a split keyboard, you should do this _only_ for your central/left side, e.g.:
|
||||||
|
|
||||||
|
```
|
||||||
|
---
|
||||||
|
include:
|
||||||
|
- board: nice_nano_v2
|
||||||
|
shield: corne_left
|
||||||
|
snippet: studio-rpc-usb-uart
|
||||||
|
- board: nice_nano_v2
|
||||||
|
shield: corne_right
|
||||||
|
```
|
||||||
|
|
||||||
|
Next, enable the `ZMK_STUDIO` Kconfig symbol, for example by adding the following line to your .conf file:
|
||||||
|
|
||||||
|
```
|
||||||
|
CONFIG_ZMK_STUDIO=y
|
||||||
|
```
|
||||||
|
|
||||||
|
### Local Build
|
||||||
|
|
||||||
|
When building locally, use the `-S` parameter to include the `studio-rpc-usb-uart` snippet. Instead of adding it to your config file, you can also append the `ZMK_STUDIO` Kconfig as an additional CMake argument, e.g.:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
west build -d build/cl_studio -b nice_nano_v2 \
|
||||||
|
-S studio-rpc-usb-uart -- -DSHIELD=corne_left -DCONFIG_ZMK_STUDIO=y
|
||||||
|
```
|
||||||
|
|
||||||
|
## Including Unreferenced Behaviors
|
||||||
|
|
||||||
|
Normally, ZMK will only build and include behaviors that are referenced by your keymap and unused behavior will be skipped. However, ZMK Studio builds using the `studio-rpc-usb-uart` snippet will automatically define the `ZMK_BEHAVIORS_KEEP_ALL` value, which changes the approach and builds all possible behaviors into the firmware. This lets those behaviors be used in ZMK Studio.
|
||||||
|
|
||||||
|
A few controls are available to override this behavior for fine-grained control of what behaviors are built. Behaviors can be kept or omitted by defining certain values in the top of your keymap file, _before_ the standard `behaviors.dtsi` file is included.
|
||||||
|
|
||||||
|
By convention, the defines used to keep/omit a given behavior are based on the behavior label, e.g. for the `&kt` behavior, the suffix to use would be `_KT`.
|
||||||
|
|
||||||
|
### Omit Specific Behaviors
|
||||||
|
|
||||||
|
You can omit a specific behaviors by defining a variable like `ZMK_BEHAVIORS_OMIT_KT` at the top of your keymap:
|
||||||
|
|
||||||
|
```dts
|
||||||
|
#define ZMK_BEHAVIORS_OMIT_KT
|
||||||
|
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Keep Only Selective Behaviors
|
||||||
|
|
||||||
|
To override the default "keep all" functionality, you can undefine the `ZMK_BEHAVIORS_KEEP_ALL` flag, and then keep only specific behaviors with a flag like `ZMK_BEHAVIORS_KEEP_KT`, e.g.:
|
||||||
|
|
||||||
|
```dts
|
||||||
|
#undef ZMK_BEHAVIORS_KEEP_ALL
|
||||||
|
|
||||||
|
#define ZMK_BEHAVIORS_KEEP_SK
|
||||||
|
#define ZMK_BEHAVIORS_KEEP_MT
|
||||||
|
#define ZMK_BEHAVIORS_KEEP_KT
|
||||||
|
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Including Extra Layers
|
||||||
|
|
||||||
|
By default, a build with ZMK Studio enabled will only allow as many layers as are defined in your standard keymap. To make additional layers available for use through ZMK Studio, you simply add new empty layers to your keymap with a status of `reserved`, e.g.:
|
||||||
|
|
||||||
|
```dts
|
||||||
|
/ {
|
||||||
|
keymap {
|
||||||
|
compatible = "zmk,keymap";
|
||||||
|
|
||||||
|
base {
|
||||||
|
display-name = "Base";
|
||||||
|
bindings = // etc.
|
||||||
|
};
|
||||||
|
|
||||||
|
fn_layer {
|
||||||
|
display-name = "Fn";
|
||||||
|
bindings = // etc.
|
||||||
|
};
|
||||||
|
|
||||||
|
extra1 {
|
||||||
|
status = "reserved";
|
||||||
|
};
|
||||||
|
|
||||||
|
extra2 {
|
||||||
|
status = "reserved";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The reserved layers will be ignored during regular ZMK builds but will become available for ZMK Studio enabled builds.
|
|
@ -72,6 +72,12 @@ Below is a summary of pre-defined behavior bindings and user-definable behaviors
|
||||||
| `&ext_power` | [Power management](power.md#behavior-binding) | Allows enabling or disabling the VCC power output to save power |
|
| `&ext_power` | [Power management](power.md#behavior-binding) | Allows enabling or disabling the VCC power output to save power |
|
||||||
| `&soft_off` | [Soft off](soft-off.md#behavior-binding) | Turns the keyboard off. |
|
| `&soft_off` | [Soft off](soft-off.md#behavior-binding) | Turns the keyboard off. |
|
||||||
|
|
||||||
|
## ZMK Studio Behaviors
|
||||||
|
|
||||||
|
| Binding | Behavior | Description |
|
||||||
|
| ---------------- | ------------------------------------------------------ | --------------------------------------------------------- |
|
||||||
|
| `&studio_unlock` | [ZMK Studio Unlock](studio-unlock.md#behavior-binding) | Unlocks the device so that ZMK Studio UI can make changes |
|
||||||
|
|
||||||
## User-Defined Behaviors
|
## User-Defined Behaviors
|
||||||
|
|
||||||
| Behavior | Description |
|
| Behavior | Description |
|
||||||
|
|
25
docs/docs/keymaps/behaviors/studio-unlock.md
Normal file
25
docs/docs/keymaps/behaviors/studio-unlock.md
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
title: ZMK Studio Unlock Behavior
|
||||||
|
sidebar_label: ZMK Studio Unlock
|
||||||
|
---
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
ZMK Studio is still in active development. This behavior is documented in preparation for its general availability.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
## ZMK Studio Unlock
|
||||||
|
|
||||||
|
The ZMK Studio unlock behavior is used to grant [ZMK Studio](../../features/studio.md) access to make changes to your ZMK device. The device will remain unlocked until a certain amount of time of inactivity in ZMK Studio, or on disconnect. Those trigger events for relocking can be configured with [studio configuration](../../config/studio.md).
|
||||||
|
|
||||||
|
### Behavior Binding
|
||||||
|
|
||||||
|
- Reference: `&studio_unlock`
|
||||||
|
- Parameters: None
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```dts
|
||||||
|
&studio_unlock
|
||||||
|
```
|
|
@ -41,6 +41,7 @@ module.exports = {
|
||||||
"features/displays",
|
"features/displays",
|
||||||
"features/backlight",
|
"features/backlight",
|
||||||
"features/underglow",
|
"features/underglow",
|
||||||
|
"features/studio",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -83,6 +84,7 @@ module.exports = {
|
||||||
"keymaps/behaviors/backlight",
|
"keymaps/behaviors/backlight",
|
||||||
"keymaps/behaviors/power",
|
"keymaps/behaviors/power",
|
||||||
"keymaps/behaviors/soft-off",
|
"keymaps/behaviors/soft-off",
|
||||||
|
"keymaps/behaviors/studio-unlock",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"keymaps/modifiers",
|
"keymaps/modifiers",
|
||||||
|
@ -112,6 +114,7 @@ module.exports = {
|
||||||
"config/power",
|
"config/power",
|
||||||
"config/underglow",
|
"config/underglow",
|
||||||
"config/system",
|
"config/system",
|
||||||
|
"config/studio",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -124,6 +127,7 @@ module.exports = {
|
||||||
"development/hardware-integration/new-shield",
|
"development/hardware-integration/new-shield",
|
||||||
"development/hardware-integration/hardware-metadata-files",
|
"development/hardware-integration/hardware-metadata-files",
|
||||||
"development/hardware-integration/boards-shields-keymaps",
|
"development/hardware-integration/boards-shields-keymaps",
|
||||||
|
"development/hardware-integration/studio-setup",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue