Compare commits
2 commits
97ef3f60ce
...
78a3e5e752
Author | SHA1 | Date | |
---|---|---|---|
kemonine | 78a3e5e752 | ||
kemonine | dec50b3d3f |
|
@ -7,5 +7,8 @@
|
||||||
"settings": {
|
"settings": {
|
||||||
"terminal.integrated.shell.linux": "/bin/bash"
|
"terminal.integrated.shell.linux": "/bin/bash"
|
||||||
},
|
},
|
||||||
|
"mounts": [
|
||||||
|
"type=volume,source=zmk-config,target=/workspaces/zmk-config"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
4
zmk/.github/workflows/build.yml
vendored
4
zmk/.github/workflows/build.yml
vendored
|
@ -25,6 +25,10 @@ jobs:
|
||||||
- lily58_right
|
- lily58_right
|
||||||
- iris_left
|
- iris_left
|
||||||
- iris_right
|
- iris_right
|
||||||
|
- jorne_left
|
||||||
|
- jorne_right
|
||||||
|
- jian_left
|
||||||
|
- jian_right
|
||||||
- reviung41
|
- reviung41
|
||||||
- romac
|
- romac
|
||||||
- romac_plus
|
- romac_plus
|
||||||
|
|
2
zmk/.github/workflows/test.yml
vendored
2
zmk/.github/workflows/test.yml
vendored
|
@ -61,7 +61,7 @@ jobs:
|
||||||
id: west-build
|
id: west-build
|
||||||
with:
|
with:
|
||||||
entrypoint: /bin/bash
|
entrypoint: /bin/bash
|
||||||
args: '-c "cd app && ./run-test.sh all"'
|
args: '-c "west test"'
|
||||||
- name: Archive Build
|
- name: Archive Build
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
|
|
1
zmk/.gitignore
vendored
1
zmk/.gitignore
vendored
|
@ -6,3 +6,4 @@
|
||||||
/zmk-config
|
/zmk-config
|
||||||
/build
|
/build
|
||||||
*.DS_Store
|
*.DS_Store
|
||||||
|
__pycache__
|
|
@ -1,3 +1,6 @@
|
||||||
|
# Copyright (c) 2020 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
mainmenu "ZMK Firmware"
|
mainmenu "ZMK Firmware"
|
||||||
|
|
||||||
menu "ZMK"
|
menu "ZMK"
|
||||||
|
|
|
@ -1 +1,4 @@
|
||||||
|
# Copyright (c) 2020 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
rsource "shields/*/Kconfig.shield"
|
rsource "shields/*/Kconfig.shield"
|
||||||
|
|
23
zmk/app/boards/shields/jian/Kconfig.defconfig
Normal file
23
zmk/app/boards/shields/jian/Kconfig.defconfig
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
if SHIELD_JIAN_LEFT
|
||||||
|
|
||||||
|
config ZMK_KEYBOARD_NAME
|
||||||
|
default "Jian Left"
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
if SHIELD_JIAN_RIGHT
|
||||||
|
|
||||||
|
config ZMK_KEYBOARD_NAME
|
||||||
|
default "Jian Right"
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
if SHIELD_JIAN_LEFT || SHIELD_JIAN_RIGHT
|
||||||
|
|
||||||
|
config ZMK_SPLIT
|
||||||
|
default y
|
||||||
|
|
||||||
|
|
||||||
|
endif
|
8
zmk/app/boards/shields/jian/Kconfig.shield
Normal file
8
zmk/app/boards/shields/jian/Kconfig.shield
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Copyright (c) 2020 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
config SHIELD_JIAN_LEFT
|
||||||
|
def_bool $(shields_list_contains,jian_left)
|
||||||
|
|
||||||
|
config SHIELD_JIAN_RIGHT
|
||||||
|
def_bool $(shields_list_contains,jian_right)
|
0
zmk/app/boards/shields/jian/jian.conf
Normal file
0
zmk/app/boards/shields/jian/jian.conf
Normal file
76
zmk/app/boards/shields/jian/jian.dtsi
Normal file
76
zmk/app/boards/shields/jian/jian.dtsi
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/matrix-transform.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
chosen {
|
||||||
|
zmk,kscan = &kscan0;
|
||||||
|
zmk,matrix_transform = &default_transform;
|
||||||
|
};
|
||||||
|
|
||||||
|
default_transform: keymap_transform_0 {
|
||||||
|
compatible = "zmk,matrix-transform";
|
||||||
|
columns = <12>;
|
||||||
|
rows = <4>;
|
||||||
|
// | SW0 | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 | | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 | SW0 |
|
||||||
|
// | | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 | | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 |
|
||||||
|
// | | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 | | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 |
|
||||||
|
// | SW19 | SW20 | SW21 | | SW21 | SW20 | SW19 |
|
||||||
|
map = <
|
||||||
|
RC(2,0) RC(0,0) RC(0,1) RC(1,2) RC(0,2) RC(0,3) RC(0,4) RC(0,7) RC(0,8) RC(0,9) RC(1,9) RC(0,10) RC(0,11) RC(2,11)
|
||||||
|
RC(1,0) RC(1,1) RC(2,2) RC(1,3) RC(1,4) RC(0,5) RC(0,6) RC(1,7) RC(1,8) RC(2,9) RC(1,10) RC(1,11)
|
||||||
|
RC(2,1) RC(3,2) RC(3,3) RC(2,3) RC(2,4) RC(1,5) RC(1,6) RC(2,7) RC(2,8) RC(3,8) RC(3,9) RC(2,10)
|
||||||
|
RC(3,4) RC(2,5) RC(3,5) RC(3,6) RC(2,6) RC(3,7)
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
crkbd_transform: keymap_transform_1 {
|
||||||
|
compatible = "zmk,matrix-transform";
|
||||||
|
columns = <12>;
|
||||||
|
rows = <4>;
|
||||||
|
// | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 | | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 |
|
||||||
|
// | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 | | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 |
|
||||||
|
// | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 | | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 |
|
||||||
|
// | SW19 | SW20 | SW21 | | SW21 | SW20 | SW19 |
|
||||||
|
map = <
|
||||||
|
RC(0,0) RC(0,1) RC(1,2) RC(0,2) RC(0,3) RC(0,4) RC(0,7) RC(0,8) RC(0,9) RC(1,9) RC(0,10) RC(0,11)
|
||||||
|
RC(1,0) RC(1,1) RC(2,2) RC(1,3) RC(1,4) RC(0,5) RC(0,6) RC(1,7) RC(1,8) RC(2,9) RC(1,10) RC(1,11)
|
||||||
|
RC(2,1) RC(3,2) RC(3,3) RC(2,3) RC(2,4) RC(1,5) RC(1,6) RC(2,7) RC(2,8) RC(3,8) RC(3,9) RC(2,10)
|
||||||
|
RC(3,4) RC(2,5) RC(3,5) RC(3,6) RC(2,6) RC(3,7)
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
five_column_transform: keymap_transform_2 {
|
||||||
|
compatible = "zmk,matrix-transform";
|
||||||
|
columns = <10>;
|
||||||
|
rows = <4>;
|
||||||
|
// | SW2 | SW3 | SW4 | SW5 | SW6 | | SW6 | SW5 | SW4 | SW3 | SW2 |
|
||||||
|
// | SW8 | SW9 | SW10 | SW11 | SW12 | | SW12 | SW11 | SW10 | SW9 | SW8 |
|
||||||
|
// | SW14 | SW15 | SW16 | SW17 | SW18 | | SW18 | SW17 | SW16 | SW15 | SW14 |
|
||||||
|
// | SW19 | SW20 | SW21 | | SW21 | SW20 | SW19 |
|
||||||
|
map = <
|
||||||
|
RC(0,1) RC(1,2) RC(0,2) RC(0,3) RC(0,4) RC(0,7) RC(0,8) RC(0,9) RC(1,9) RC(0,10)
|
||||||
|
RC(1,1) RC(2,2) RC(1,3) RC(1,4) RC(0,5) RC(0,6) RC(1,7) RC(1,8) RC(2,9) RC(1,10)
|
||||||
|
RC(3,2) RC(3,3) RC(2,3) RC(2,4) RC(1,5) RC(1,6) RC(2,7) RC(2,8) RC(3,8) RC(3,9)
|
||||||
|
RC(3,4) RC(2,5) RC(3,5) RC(3,6) RC(2,6) RC(3,7)
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
kscan0: kscan {
|
||||||
|
compatible = "zmk,kscan-gpio-matrix";
|
||||||
|
label = "KSCAN";
|
||||||
|
|
||||||
|
diode-direction = "col2row";
|
||||||
|
row-gpios
|
||||||
|
= <&pro_micro_a 3 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||||
|
, <&pro_micro_a 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||||
|
, <&pro_micro_d 15 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||||
|
, <&pro_micro_d 14 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||||
|
;
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
74
zmk/app/boards/shields/jian/jian.keymap
Normal file
74
zmk/app/boards/shields/jian/jian.keymap
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <dt-bindings/zmk/bt.h>
|
||||||
|
|
||||||
|
#define DEF 0
|
||||||
|
#define LWR 1
|
||||||
|
#define RSE 2
|
||||||
|
#define ADJ 3
|
||||||
|
|
||||||
|
/ {
|
||||||
|
keymap {
|
||||||
|
compatible = "zmk,keymap";
|
||||||
|
|
||||||
|
default_layer {
|
||||||
|
// -----------------------------------------------------------------------------------------
|
||||||
|
// | GUI | ~ | Q | W | E | R | T | | Y | U | I | O | P | [ | GUI/] |
|
||||||
|
// | CTRL | A | S | D | F | G | | H | J | K | L | ; |CTRL/'|
|
||||||
|
// | LALT | Z | X | C | V | B | | N | M | , | . | / | RALT |
|
||||||
|
// | RSE | SPC | LWR | | LWR | BKSP | RSE |
|
||||||
|
bindings = <
|
||||||
|
&kp LWIN &kp GRAVE &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp LBKT &mt RWIN RBKT
|
||||||
|
&kp LCTRL &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SCLN &mt RCTRL QUOT
|
||||||
|
&kp LALT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp BSLH
|
||||||
|
< RSE TAB &mt LSHFT SPC < LWR RET < LWR ESC &mt RSHFT BSPC < RSE DEL
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
lower_layer {
|
||||||
|
// -----------------------------------------------------------------------------------------
|
||||||
|
// | | _ | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10 | F11 | F12 |
|
||||||
|
// | + | ! | @ | # | $ | % | | ^ | & | * | ( | ) | - |
|
||||||
|
// | = | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | |
|
||||||
|
// | GUI | | SPC | | ENT | | ALT |
|
||||||
|
bindings = <
|
||||||
|
&trans &kp UNDER &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &mt RGUI F12
|
||||||
|
&mt LCTRL PLUS &kp EXCL &kp AT &kp HASH &kp DLLR &kp PRCNT &kp CRRT &kp AMPS &kp STAR &kp LPAR &kp RPAR &mt RCTRL MINUS
|
||||||
|
&mt LALT EQUAL &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &trans
|
||||||
|
< ADJ TAB &trans &trans &trans &trans < ADJ DEL
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
raise_layer {
|
||||||
|
// -----------------------------------------------------------------------------------------
|
||||||
|
// | | NMLK | / | 7 | 8 | 9 | - | | VOLU| HOME| PRSC| PGUP| SCLK| CLCK| |
|
||||||
|
// | CTRL | * | 4 | 5 | 6 | + | | MUT | LEFT| UP | RGHT| INS | APP |
|
||||||
|
// | | 0 | 1 | 2 | 3 | . | | VOLD| END | DOWN| PGDN| PAUS| |
|
||||||
|
// | | | ADJ | | ADJ | | |
|
||||||
|
bindings = <
|
||||||
|
&trans &kp KP_NUM &kp KP_SLASH &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_MINUS &kp C_VOL_UP &kp HOME &kp PSCRN &kp PG_UP &kp SLCK &kp CAPS &trans
|
||||||
|
&mt LCTRL EQL &kp KP_MULTIPLY &kp KP_N4 &kp KP_N5 &kp KP_N6 &kp KP_PLUS &kp C_MUTE &kp LEFT &kp UP &kp RIGHT &kp INS &mt RCTRL K_APP
|
||||||
|
&trans &kp KP_N0 &kp KP_N1 &kp KP_N2 &kp KP_N3 &kp KP_DOT &kp C_VOL_DN &kp END &kp DOWN &kp PG_DN &kp PAUS &trans
|
||||||
|
&trans &trans < ADJ RET < ADJ ESC &trans &trans
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
adjust_layer {
|
||||||
|
// -----------------------------------------------------------------------------------------
|
||||||
|
// | RST | BLDR | | | | | | | | | | | | BLDR | RST |
|
||||||
|
// | BTCLR| BT0 | BT1 | BT2 | BT3 | BT4 | | BT4 | BT3 | BT2 | BT1 | BT0 | BTCLR|
|
||||||
|
// | | | | | | | | | | | | | |
|
||||||
|
// | | | | | | | |
|
||||||
|
bindings = <
|
||||||
|
&reset &bootloader &none &none &none &none &none &none &none &none &none &none &bootloader &reset
|
||||||
|
&bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &bt BT_SEL 4 &bt BT_SEL 3 &bt BT_SEL 2 &bt BT_SEL 1 &bt BT_SEL 0 &bt BT_CLR
|
||||||
|
&none &none &none &none &none &none &none &none &none &none &none &none
|
||||||
|
&trans &none &trans &trans &none &trans
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
2
zmk/app/boards/shields/jian/jian_left.conf
Normal file
2
zmk/app/boards/shields/jian/jian_left.conf
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIG_ZMK_SPLIT=y
|
||||||
|
CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y
|
18
zmk/app/boards/shields/jian/jian_left.overlay
Normal file
18
zmk/app/boards/shields/jian/jian_left.overlay
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "jian.dtsi"
|
||||||
|
|
||||||
|
&kscan0 {
|
||||||
|
col-gpios
|
||||||
|
= <&pro_micro_d 1 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_d 0 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_d 8 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_a 1 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_a 0 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_d 16 GPIO_ACTIVE_HIGH>
|
||||||
|
;
|
||||||
|
};
|
2
zmk/app/boards/shields/jian/jian_right.conf
Normal file
2
zmk/app/boards/shields/jian/jian_right.conf
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIG_ZMK_SPLIT=y
|
||||||
|
CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y
|
22
zmk/app/boards/shields/jian/jian_right.overlay
Normal file
22
zmk/app/boards/shields/jian/jian_right.overlay
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "jian.dtsi"
|
||||||
|
|
||||||
|
&default_transform {
|
||||||
|
col-offset = <6>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&kscan0 {
|
||||||
|
col-gpios
|
||||||
|
= <&pro_micro_d 16 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_a 0 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_a 1 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_d 8 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_d 0 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_d 1 GPIO_ACTIVE_HIGH>
|
||||||
|
;
|
||||||
|
};
|
58
zmk/app/boards/shields/jorne/Kconfig.defconfig
Normal file
58
zmk/app/boards/shields/jorne/Kconfig.defconfig
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
|
||||||
|
if SHIELD_JORNE_LEFT
|
||||||
|
|
||||||
|
config ZMK_KEYBOARD_NAME
|
||||||
|
default "Jorne Left"
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
if SHIELD_JORNE_RIGHT
|
||||||
|
|
||||||
|
config ZMK_KEYBOARD_NAME
|
||||||
|
default "Jorne Right"
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
if SHIELD_JORNE_LEFT || SHIELD_JORNE_RIGHT
|
||||||
|
|
||||||
|
config ZMK_SPLIT
|
||||||
|
default y
|
||||||
|
|
||||||
|
if ZMK_DISPLAY
|
||||||
|
|
||||||
|
config I2C
|
||||||
|
default y
|
||||||
|
|
||||||
|
config SSD1306
|
||||||
|
default y
|
||||||
|
|
||||||
|
config SSD1306_REVERSE_MODE
|
||||||
|
default y
|
||||||
|
|
||||||
|
endif # ZMK_DISPLAY
|
||||||
|
|
||||||
|
if LVGL
|
||||||
|
|
||||||
|
config LVGL_HOR_RES
|
||||||
|
default 128
|
||||||
|
|
||||||
|
config LVGL_VER_RES
|
||||||
|
default 32
|
||||||
|
|
||||||
|
config LVGL_VDB_SIZE
|
||||||
|
default 64
|
||||||
|
|
||||||
|
config LVGL_DPI
|
||||||
|
default 148
|
||||||
|
|
||||||
|
config LVGL_BITS_PER_PIXEL
|
||||||
|
default 1
|
||||||
|
|
||||||
|
choice LVGL_COLOR_DEPTH
|
||||||
|
default LVGL_COLOR_DEPTH_1
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
endif # LVGL
|
||||||
|
|
||||||
|
endif
|
8
zmk/app/boards/shields/jorne/Kconfig.shield
Normal file
8
zmk/app/boards/shields/jorne/Kconfig.shield
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Copyright (c) 2020 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
config SHIELD_JORNE_LEFT
|
||||||
|
def_bool $(shields_list_contains,jorne_left)
|
||||||
|
|
||||||
|
config SHIELD_JORNE_RIGHT
|
||||||
|
def_bool $(shields_list_contains,jorne_right)
|
29
zmk/app/boards/shields/jorne/boards/nice_nano.overlay
Normal file
29
zmk/app/boards/shields/jorne/boards/nice_nano.overlay
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
&spi1 {
|
||||||
|
compatible = "nordic,nrf-spim";
|
||||||
|
/* Cannot be used together with i2c0. */
|
||||||
|
status = "okay";
|
||||||
|
mosi-pin = <6>;
|
||||||
|
// Unused pins, needed for SPI definition, but not used by the ws2812 driver itself.
|
||||||
|
sck-pin = <5>;
|
||||||
|
miso-pin = <7>;
|
||||||
|
|
||||||
|
led_strip: ws2812@0 {
|
||||||
|
compatible = "worldsemi,ws2812-spi";
|
||||||
|
label = "WS2812";
|
||||||
|
|
||||||
|
/* SPI */
|
||||||
|
reg = <0>; /* ignored, but necessary for SPI bindings */
|
||||||
|
spi-max-frequency = <4000000>;
|
||||||
|
|
||||||
|
/* WS2812 */
|
||||||
|
chain-length = <6>; /* There are per-key RGB, but the first 6 are underglow */
|
||||||
|
spi-one-frame = <0x70>;
|
||||||
|
spi-zero-frame = <0x40>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/ {
|
||||||
|
chosen {
|
||||||
|
zmk,underglow = &led_strip;
|
||||||
|
};
|
||||||
|
};
|
6
zmk/app/boards/shields/jorne/jorne.conf
Normal file
6
zmk/app/boards/shields/jorne/jorne.conf
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# Uncomment the following lines to enable the Jorne RGB Underglow
|
||||||
|
# CONFIG_ZMK_RGB_UNDERGLOW=y
|
||||||
|
# CONFIG_WS2812_STRIP=y
|
||||||
|
|
||||||
|
# Uncomment the following line to enable the Jorne OLED Display
|
||||||
|
# CONFIG_ZMK_DISPLAY=y
|
98
zmk/app/boards/shields/jorne/jorne.dtsi
Normal file
98
zmk/app/boards/shields/jorne/jorne.dtsi
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dt-bindings/zmk/matrix-transform.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
chosen {
|
||||||
|
zmk,kscan = &kscan0;
|
||||||
|
zmk,matrix_transform = &default_transform;
|
||||||
|
};
|
||||||
|
|
||||||
|
default_transform: keymap_transform_0 {
|
||||||
|
compatible = "zmk,matrix-transform";
|
||||||
|
columns = <12>;
|
||||||
|
rows = <4>;
|
||||||
|
// | SW0 | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 | | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 | SW0 |
|
||||||
|
// | | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 | | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 |
|
||||||
|
// | | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 | | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 |
|
||||||
|
// | SW19 | SW20 | SW21 | | SW21 | SW20 | SW19 |
|
||||||
|
map = <
|
||||||
|
RC(3,0) RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10) RC(0,11) RC(3,11)
|
||||||
|
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10) RC(1,11)
|
||||||
|
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) RC(2,10) RC(2,11)
|
||||||
|
RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8)
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
crkbd_transform: keymap_transform_1 {
|
||||||
|
compatible = "zmk,matrix-transform";
|
||||||
|
columns = <12>;
|
||||||
|
rows = <4>;
|
||||||
|
// | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 | | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 |
|
||||||
|
// | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 | | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 |
|
||||||
|
// | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 | | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 |
|
||||||
|
// | SW19 | SW20 | SW21 | | SW21 | SW20 | SW19 |
|
||||||
|
map = <
|
||||||
|
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10) RC(0,11)
|
||||||
|
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10) RC(1,11)
|
||||||
|
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) RC(2,10) RC(2,11)
|
||||||
|
RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8)
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
five_column_transform: keymap_transform_2 {
|
||||||
|
compatible = "zmk,matrix-transform";
|
||||||
|
columns = <10>;
|
||||||
|
rows = <4>;
|
||||||
|
// | SW2 | SW3 | SW4 | SW5 | SW6 | | SW6 | SW5 | SW4 | SW3 | SW2 |
|
||||||
|
// | SW8 | SW9 | SW10 | SW11 | SW12 | | SW12 | SW11 | SW10 | SW9 | SW8 |
|
||||||
|
// | SW14 | SW15 | SW16 | SW17 | SW18 | | SW18 | SW17 | SW16 | SW15 | SW14 |
|
||||||
|
// | SW19 | SW20 | SW21 | | SW21 | SW20 | SW19 |
|
||||||
|
map = <
|
||||||
|
RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10)
|
||||||
|
RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10)
|
||||||
|
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) RC(2,10)
|
||||||
|
RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8)
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
kscan0: kscan {
|
||||||
|
compatible = "zmk,kscan-gpio-matrix";
|
||||||
|
label = "KSCAN";
|
||||||
|
|
||||||
|
diode-direction = "col2row";
|
||||||
|
row-gpios
|
||||||
|
= <&pro_micro_d 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||||
|
, <&pro_micro_d 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||||
|
, <&pro_micro_d 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||||
|
, <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||||
|
;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: per-key RGB node(s)?
|
||||||
|
};
|
||||||
|
|
||||||
|
&pro_micro_i2c {
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
oled: ssd1306@3c {
|
||||||
|
compatible = "solomon,ssd1306fb";
|
||||||
|
reg = <0x3c>;
|
||||||
|
label = "DISPLAY";
|
||||||
|
width = <128>;
|
||||||
|
height = <32>;
|
||||||
|
segment-offset = <0>;
|
||||||
|
page-offset = <0>;
|
||||||
|
display-offset = <0>;
|
||||||
|
multiplex-ratio = <31>;
|
||||||
|
segment-remap;
|
||||||
|
com-invdir;
|
||||||
|
com-sequential;
|
||||||
|
prechargep = <0x22>;
|
||||||
|
};
|
||||||
|
};
|
74
zmk/app/boards/shields/jorne/jorne.keymap
Normal file
74
zmk/app/boards/shields/jorne/jorne.keymap
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <dt-bindings/zmk/bt.h>
|
||||||
|
|
||||||
|
#define DEF 0
|
||||||
|
#define LWR 1
|
||||||
|
#define RSE 2
|
||||||
|
#define ADJ 3
|
||||||
|
|
||||||
|
/ {
|
||||||
|
keymap {
|
||||||
|
compatible = "zmk,keymap";
|
||||||
|
|
||||||
|
default_layer {
|
||||||
|
// -----------------------------------------------------------------------------------------
|
||||||
|
// | GUI | ~ | Q | W | E | R | T | | Y | U | I | O | P | [ | GUI/] |
|
||||||
|
// | CTRL | A | S | D | F | G | | H | J | K | L | ; |CTRL/'|
|
||||||
|
// | LALT | Z | X | C | V | B | | N | M | , | . | / | RALT |
|
||||||
|
// | RSE | SPC | LWR | | LWR | BKSP | RSE |
|
||||||
|
bindings = <
|
||||||
|
&kp LWIN &kp GRAVE &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp LBKT &mt RWIN RBKT
|
||||||
|
&kp LCTRL &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SCLN &mt RCTRL QUOT
|
||||||
|
&kp LALT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp BSLH
|
||||||
|
< RSE TAB &mt LSHFT SPC < LWR RET < LWR ESC &mt RSHFT BSPC < RSE DEL
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
lower_layer {
|
||||||
|
// -----------------------------------------------------------------------------------------
|
||||||
|
// | | _ | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10 | F11 | F12 |
|
||||||
|
// | + | ! | @ | # | $ | % | | ^ | & | * | ( | ) | - |
|
||||||
|
// | = | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | |
|
||||||
|
// | GUI | | SPC | | ENT | | ALT |
|
||||||
|
bindings = <
|
||||||
|
&trans &kp UNDER &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &mt RGUI F12
|
||||||
|
&mt LCTRL PLUS &kp EXCL &kp AT &kp HASH &kp DLLR &kp PRCNT &kp CRRT &kp AMPS &kp STAR &kp LPAR &kp RPAR &mt RCTRL MINUS
|
||||||
|
&mt LALT EQUAL &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &trans
|
||||||
|
< ADJ TAB &trans &trans &trans &trans < ADJ DEL
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
raise_layer {
|
||||||
|
// -----------------------------------------------------------------------------------------
|
||||||
|
// | | NMLK | / | 7 | 8 | 9 | - | | VOLU| HOME| PRSC| PGUP| SCLK| CLCK| |
|
||||||
|
// | CTRL | * | 4 | 5 | 6 | + | | MUT | LEFT| UP | RGHT| INS | APP |
|
||||||
|
// | | 0 | 1 | 2 | 3 | . | | VOLD| END | DOWN| PGDN| PAUS| |
|
||||||
|
// | | | ADJ | | ADJ | | |
|
||||||
|
bindings = <
|
||||||
|
&trans &kp KP_NUM &kp KP_SLASH &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_MINUS &kp C_VOL_UP &kp HOME &kp PSCRN &kp PG_UP &kp SLCK &kp CAPS &trans
|
||||||
|
&mt LCTRL EQL &kp KP_MULTIPLY &kp KP_N4 &kp KP_N5 &kp KP_N6 &kp KP_PLUS &kp C_MUTE &kp LEFT &kp UP &kp RIGHT &kp INS &mt RCTRL K_APP
|
||||||
|
&trans &kp KP_N0 &kp KP_N1 &kp KP_N2 &kp KP_N3 &kp KP_DOT &kp C_VOL_DN &kp END &kp DOWN &kp PG_DN &kp PAUS &trans
|
||||||
|
&trans &trans < ADJ RET < ADJ ESC &trans &trans
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
adjust_layer {
|
||||||
|
// -----------------------------------------------------------------------------------------
|
||||||
|
// | RST | BLDR | | | | | | | | | | | | BLDR | RST |
|
||||||
|
// | BTCLR| BT0 | BT1 | BT2 | BT3 | BT4 | | BT4 | BT3 | BT2 | BT1 | BT0 | BTCLR|
|
||||||
|
// | | | | | | | | | | | | | |
|
||||||
|
// | | | | | | | |
|
||||||
|
bindings = <
|
||||||
|
&reset &bootloader &none &none &none &none &none &none &none &none &none &none &bootloader &reset
|
||||||
|
&bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &bt BT_SEL 4 &bt BT_SEL 3 &bt BT_SEL 2 &bt BT_SEL 1 &bt BT_SEL 0 &bt BT_CLR
|
||||||
|
&none &none &none &none &none &none &none &none &none &none &none &none
|
||||||
|
&trans &none &trans &trans &none &trans
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
2
zmk/app/boards/shields/jorne/jorne_left.conf
Normal file
2
zmk/app/boards/shields/jorne/jorne_left.conf
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIG_ZMK_SPLIT=y
|
||||||
|
CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y
|
18
zmk/app/boards/shields/jorne/jorne_left.overlay
Normal file
18
zmk/app/boards/shields/jorne/jorne_left.overlay
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "jorne.dtsi"
|
||||||
|
|
||||||
|
&kscan0 {
|
||||||
|
col-gpios
|
||||||
|
= <&pro_micro_a 3 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_a 2 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_a 1 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_a 0 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_d 15 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_d 14 GPIO_ACTIVE_HIGH>
|
||||||
|
;
|
||||||
|
};
|
2
zmk/app/boards/shields/jorne/jorne_right.conf
Normal file
2
zmk/app/boards/shields/jorne/jorne_right.conf
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
CONFIG_ZMK_SPLIT=y
|
||||||
|
CONFIG_ZMK_SPLIT_BLE_ROLE_PERIPHERAL=y
|
22
zmk/app/boards/shields/jorne/jorne_right.overlay
Normal file
22
zmk/app/boards/shields/jorne/jorne_right.overlay
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "jorne.dtsi"
|
||||||
|
|
||||||
|
&default_transform {
|
||||||
|
col-offset = <6>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&kscan0 {
|
||||||
|
col-gpios
|
||||||
|
= <&pro_micro_d 14 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_d 15 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_a 0 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_a 1 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_a 2 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_a 3 GPIO_ACTIVE_HIGH>
|
||||||
|
;
|
||||||
|
};
|
|
@ -39,7 +39,7 @@
|
||||||
};
|
};
|
||||||
num_sym {
|
num_sym {
|
||||||
bindings = <
|
bindings = <
|
||||||
&kp NUM_1 &kp NUM_2 &kp NUM_3 &kp NUM_4 &kp NUM_5 &kp NUM_6 &kp NUM_7 &kp NUM_8 &kp NUM_9 &kp NUM_0
|
&kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0
|
||||||
&trans &trans &trans &trans &trans &trans &trans &trans &kp EQL &kp MINUS
|
&trans &trans &trans &trans &trans &trans &trans &trans &kp EQL &kp MINUS
|
||||||
&kp DEL &none &none &none &none &none &none &none &kp DOT
|
&kp DEL &none &none &none &none &none &none &none &kp DOT
|
||||||
&bootloader &reset &none &trans &trans &kp RET &trans &kp FSLH
|
&bootloader &reset &none &trans &trans &kp RET &trans &kp FSLH
|
||||||
|
|
|
@ -4,9 +4,13 @@
|
||||||
if SHIELD_TIDBIT
|
if SHIELD_TIDBIT
|
||||||
|
|
||||||
config ZMK_KEYBOARD_NAME
|
config ZMK_KEYBOARD_NAME
|
||||||
default "TIDBIT"
|
default "TIDBIT_DEFAULT"
|
||||||
|
|
||||||
config ZMK_USB
|
endif
|
||||||
default y
|
|
||||||
|
if SHIELD_TIDBIT_19
|
||||||
|
|
||||||
|
config ZMK_KEYBOARD_NAME
|
||||||
|
default "TIDBIT_19"
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -2,4 +2,7 @@
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
config SHIELD_TIDBIT
|
config SHIELD_TIDBIT
|
||||||
def_bool $(shields_list_contains,tidbit)
|
def_bool $(shields_list_contains,tidbit_default)
|
||||||
|
|
||||||
|
config SHIELD_TIDBIT_19
|
||||||
|
def_bool $(shields_list_contains,tidbit_19keys)
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
&spi1 {
|
&spi1 {
|
||||||
compatible = "nordic,nrf-spim";
|
compatible = "nordic,nrf-spim";
|
||||||
status = "okay";
|
status = "okay";
|
||||||
mosi-pin = <10>;
|
mosi-pin = <9>;
|
||||||
// Unused pins, needed for SPI definition, but not used by the ws2812 driver itself.
|
// Unused pins, needed for SPI definition, but not used by the ws2812 driver itself.
|
||||||
sck-pin = <5>;
|
sck-pin = <5>;
|
||||||
miso-pin = <7>;
|
miso-pin = <7>;
|
||||||
|
@ -15,14 +21,8 @@
|
||||||
spi-max-frequency = <4000000>;
|
spi-max-frequency = <4000000>;
|
||||||
|
|
||||||
/* WS2812 */
|
/* WS2812 */
|
||||||
chain-length = <8>; /* arbitrary; change at will */
|
chain-length = <10>; /* number of LEDs */
|
||||||
spi-one-frame = <0x70>;
|
spi-one-frame = <0x70>;
|
||||||
spi-zero-frame = <0x40>;
|
spi-zero-frame = <0x40>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/ {
|
|
||||||
chosen {
|
|
||||||
zmk,underglow = &led_strip;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
# Copyright (c) 2020 The ZMK Contributors
|
# Copyright (c) 2020 The ZMK Contributors
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
# Uncomment to enable encoder
|
# Enable Encoders
|
||||||
CONFIG_EC11=y
|
CONFIG_EC11=y
|
||||||
CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y
|
CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y
|
||||||
|
|
||||||
|
# Enable underglow
|
||||||
|
CONFIG_ZMK_RGB_UNDERGLOW=y
|
||||||
|
# Use the STRIP config specific to the LEDs you're using
|
||||||
|
CONFIG_WS2812_STRIP=y
|
||||||
|
|
|
@ -92,5 +92,6 @@
|
||||||
chosen {
|
chosen {
|
||||||
zmk,kscan = &kscan0;
|
zmk,kscan = &kscan0;
|
||||||
zmk,matrix_transform = &default_transform;
|
zmk,matrix_transform = &default_transform;
|
||||||
|
zmk,underglow = &led_strip;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,15 +7,9 @@
|
||||||
#include <behaviors.dtsi>
|
#include <behaviors.dtsi>
|
||||||
#include <dt-bindings/zmk/bt.h>
|
#include <dt-bindings/zmk/bt.h>
|
||||||
#include <dt-bindings/zmk/outputs.h>
|
#include <dt-bindings/zmk/outputs.h>
|
||||||
#include <dt-bindings/zmk/rgb.h>
|
|
||||||
#include <dt-bindings/zmk/keys.h>
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
sensors {
|
|
||||||
compatible = "zmk,keymap-sensors";
|
|
||||||
sensors = <&encoder_1_top_row>;
|
|
||||||
};
|
|
||||||
|
|
||||||
keymap {
|
keymap {
|
||||||
compatible = "zmk,keymap";
|
compatible = "zmk,keymap";
|
||||||
|
|
||||||
|
@ -33,11 +27,11 @@
|
||||||
|
|
||||||
func_layer {
|
func_layer {
|
||||||
bindings = <
|
bindings = <
|
||||||
&none &rgb_ug RGB_TOG &none
|
&none &none &none
|
||||||
&none &bt BT_CLR_CMD &rgb_ug RGB_EFF &out OUT_TOG
|
&none &bt BT_CLR_CMD &none &out OUT_TOG
|
||||||
&none &bt BT_NXT_CMD &rgb_ug RGB_HUI &out OUT_BLE
|
&none &bt BT_NXT_CMD &none &out OUT_BLE
|
||||||
&reset &bt BT_PRV_CMD &rgb_ug RGB_SAI &out OUT_USB
|
&reset &bt BT_PRV_CMD &none &out OUT_USB
|
||||||
&bootloader &bt BT_SEL_CMD &rgb_ug RGB_BRI &tog 0
|
&bootloader &bt BT_SEL_CMD &none &tog 0
|
||||||
>;
|
>;
|
||||||
|
|
||||||
sensor-bindings = <&inc_dec_kp K_VOLUME_UP K_VOLUME_DOWN>;
|
sensor-bindings = <&inc_dec_kp K_VOLUME_UP K_VOLUME_DOWN>;
|
||||||
|
|
|
@ -23,19 +23,19 @@
|
||||||
&none &kp KP_NUMBER_0 &kp KP_DOT &kp KP_ENTER
|
&none &kp KP_NUMBER_0 &kp KP_DOT &kp KP_ENTER
|
||||||
>;
|
>;
|
||||||
|
|
||||||
sensor-bindings = <&inc_dec_kp &none &none &inc_dec_kp &none &none &inc_dec_kp &none &none &inc_dec_kp &none &none &inc_dec_kp K_VOLUME_UP K_VOLUME_DOWN>;
|
sensor-bindings = <&inc_dec_kp K_VOLUME_UP K_VOLUME_DOWN>;
|
||||||
};
|
};
|
||||||
|
|
||||||
func_layer {
|
func_layer {
|
||||||
bindings = <
|
bindings = <
|
||||||
&tog 0 &bootloader &reset
|
&tog 0 &bootloader &reset
|
||||||
&none &bt BT_CLR_CMD &kp RGB_EFF &out OUT_TOG
|
&none &bt BT_CLR_CMD &none &out OUT_TOG
|
||||||
&none &bt BT_NEXT_CMD &kp RGB_HUI &out OUT_BLE
|
&none &bt BT_NEXT_CMD &none &out OUT_BLE
|
||||||
&none &bt BT_PRV_CMD &kp RGB_SAI &out OUT_USB
|
&none &bt BT_PRV_CMD &none &out OUT_USB
|
||||||
&none &bt BT_SEL_CMD &kp RGB_BRI &none
|
&none &bt BT_SEL_CMD &none &none
|
||||||
>;
|
>;
|
||||||
|
|
||||||
sensor-bindings = <&inc_dec_kp &none &none &inc_dec_kp &none &none &inc_dec_kp &none &none &inc_dec_kp &none &none &inc_dec_kp K_VOLUME_UP K_VOLUME_DOWN>;
|
sensor-bindings = <&inc_dec_kp K_VOLUME_UP K_VOLUME_DOWN>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
11
zmk/app/boards/shields/tidbit/tidbit_19key.overlay
Normal file
11
zmk/app/boards/shields/tidbit/tidbit_19key.overlay
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tidbit.dtsi"
|
||||||
|
|
||||||
|
&encoder_4 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
|
@ -5,6 +5,8 @@
|
||||||
# * single overlay,
|
# * single overlay,
|
||||||
# * or per board/shield.
|
# * or per board/shield.
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
|
||||||
get_property(cached_user_config_value CACHE ZMK_CONFIG PROPERTY VALUE)
|
get_property(cached_user_config_value CACHE ZMK_CONFIG PROPERTY VALUE)
|
||||||
|
|
||||||
set(user_config_cli_argument ${cached_user_config_value}) # Either new or old
|
set(user_config_cli_argument ${cached_user_config_value}) # Either new or old
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
# Copyright (c) 2020 The ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
config ZMK_KSCAN_GPIO_DRIVER
|
config ZMK_KSCAN_GPIO_DRIVER
|
||||||
bool "Enable GPIO kscan driver to simulate key presses"
|
bool "Enable GPIO kscan driver to simulate key presses"
|
||||||
default y
|
default y
|
||||||
|
|
3
zmk/app/drivers/zephyr/module.yml
Normal file
3
zmk/app/drivers/zephyr/module.yml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
build:
|
||||||
|
cmake: zephyr
|
||||||
|
kconfig: zephyr/Kconfig
|
|
@ -1,3 +1,9 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
bt: behavior_bluetooth {
|
bt: behavior_bluetooth {
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
ext_power: behavior_ext_power {
|
ext_power: behavior_ext_power {
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
lt: behavior_layer_tap {
|
lt: behavior_layer_tap {
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
mt: behavior_mod_tap {
|
mt: behavior_mod_tap {
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
mo: behavior_momentary_layer {
|
mo: behavior_momentary_layer {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020 Pete Johanson
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
out: behavior_outputs {
|
out: behavior_outputs {
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
#include <dt-bindings/zmk/reset.h>
|
#include <dt-bindings/zmk/reset.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
rgb_ug: behavior_rgb_underglow {
|
rgb_ug: behavior_rgb_underglow {
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 The ZMK Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
behaviors {
|
behaviors {
|
||||||
trans: behavior_transparent {
|
trans: behavior_transparent {
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
#define COLLECTION_REPORT 0x03
|
#define COLLECTION_REPORT 0x03
|
||||||
|
|
||||||
#define ZMK_HID_KEYPAD_NKRO_SIZE 6
|
#define ZMK_HID_KEYBOARD_NKRO_SIZE 6
|
||||||
|
|
||||||
#define ZMK_HID_CONSUMER_NKRO_SIZE 6
|
#define ZMK_HID_CONSUMER_NKRO_SIZE 6
|
||||||
|
|
||||||
|
@ -37,10 +37,10 @@ static const u8_t zmk_hid_report_desc[] = {
|
||||||
HID_USAGE_KEY,
|
HID_USAGE_KEY,
|
||||||
/* USAGE_MINIMUM (Keyboard LeftControl) */
|
/* USAGE_MINIMUM (Keyboard LeftControl) */
|
||||||
HID_LI_USAGE_MIN(1),
|
HID_LI_USAGE_MIN(1),
|
||||||
0xE0,
|
HID_USAGE_KEY_KEYBOARD_LEFTCONTROL,
|
||||||
/* USAGE_MAXIMUM (Keyboard Right GUI) */
|
/* USAGE_MAXIMUM (Keyboard Right GUI) */
|
||||||
HID_LI_USAGE_MAX(1),
|
HID_LI_USAGE_MAX(1),
|
||||||
0xE7,
|
HID_USAGE_KEY_KEYBOARD_RIGHT_GUI,
|
||||||
/* LOGICAL_MINIMUM (0) */
|
/* LOGICAL_MINIMUM (0) */
|
||||||
HID_GI_LOGICAL_MIN(1),
|
HID_GI_LOGICAL_MIN(1),
|
||||||
0x00,
|
0x00,
|
||||||
|
@ -89,9 +89,9 @@ static const u8_t zmk_hid_report_desc[] = {
|
||||||
/* REPORT_SIZE (1) */
|
/* REPORT_SIZE (1) */
|
||||||
HID_GI_REPORT_SIZE,
|
HID_GI_REPORT_SIZE,
|
||||||
0x08,
|
0x08,
|
||||||
/* REPORT_COUNT (ZMK_HID_KEYPAD_NKRO_SIZE) */
|
/* REPORT_COUNT (ZMK_HID_KEYBOARD_NKRO_SIZE) */
|
||||||
HID_GI_REPORT_COUNT,
|
HID_GI_REPORT_COUNT,
|
||||||
ZMK_HID_KEYPAD_NKRO_SIZE,
|
ZMK_HID_KEYBOARD_NKRO_SIZE,
|
||||||
/* INPUT (Data,Ary,Abs) */
|
/* INPUT (Data,Ary,Abs) */
|
||||||
HID_MI_INPUT,
|
HID_MI_INPUT,
|
||||||
0x00,
|
0x00,
|
||||||
|
@ -146,15 +146,15 @@ static const u8_t zmk_hid_report_desc[] = {
|
||||||
// u8_t keys[6];
|
// u8_t keys[6];
|
||||||
// } __packed;
|
// } __packed;
|
||||||
|
|
||||||
struct zmk_hid_keypad_report_body {
|
struct zmk_hid_keyboard_report_body {
|
||||||
zmk_mod_flags modifiers;
|
zmk_mod_flags modifiers;
|
||||||
u8_t _reserved;
|
u8_t _reserved;
|
||||||
u8_t keys[ZMK_HID_KEYPAD_NKRO_SIZE];
|
u8_t keys[ZMK_HID_KEYBOARD_NKRO_SIZE];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct zmk_hid_keypad_report {
|
struct zmk_hid_keyboard_report {
|
||||||
u8_t report_id;
|
u8_t report_id;
|
||||||
struct zmk_hid_keypad_report_body body;
|
struct zmk_hid_keyboard_report_body body;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct zmk_hid_consumer_report_body {
|
struct zmk_hid_consumer_report_body {
|
||||||
|
@ -170,13 +170,13 @@ int zmk_hid_register_mod(zmk_mod modifier);
|
||||||
int zmk_hid_unregister_mod(zmk_mod modifier);
|
int zmk_hid_unregister_mod(zmk_mod modifier);
|
||||||
int zmk_hid_implicit_modifiers_press(zmk_mod_flags implicit_modifiers);
|
int zmk_hid_implicit_modifiers_press(zmk_mod_flags implicit_modifiers);
|
||||||
int zmk_hid_implicit_modifiers_release();
|
int zmk_hid_implicit_modifiers_release();
|
||||||
int zmk_hid_keypad_press(zmk_key key);
|
int zmk_hid_keyboard_press(zmk_key key);
|
||||||
int zmk_hid_keypad_release(zmk_key key);
|
int zmk_hid_keyboard_release(zmk_key key);
|
||||||
void zmk_hid_keypad_clear();
|
void zmk_hid_keyboard_clear();
|
||||||
|
|
||||||
int zmk_hid_consumer_press(zmk_key key);
|
int zmk_hid_consumer_press(zmk_key key);
|
||||||
int zmk_hid_consumer_release(zmk_key key);
|
int zmk_hid_consumer_release(zmk_key key);
|
||||||
void zmk_hid_consumer_clear();
|
void zmk_hid_consumer_clear();
|
||||||
|
|
||||||
struct zmk_hid_keypad_report *zmk_hid_get_keypad_report();
|
struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report();
|
||||||
struct zmk_hid_consumer_report *zmk_hid_get_consumer_report();
|
struct zmk_hid_consumer_report *zmk_hid_get_consumer_report();
|
||||||
|
|
|
@ -11,5 +11,5 @@
|
||||||
|
|
||||||
int zmk_hog_init();
|
int zmk_hog_init();
|
||||||
|
|
||||||
int zmk_hog_send_keypad_report(struct zmk_hid_keypad_report_body *body);
|
int zmk_hog_send_keyboard_report(struct zmk_hid_keyboard_report_body *body);
|
||||||
int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *body);
|
int zmk_hog_send_consumer_report(struct zmk_hid_consumer_report_body *body);
|
||||||
|
|
9
zmk/app/scripts/west-commands.yml
Normal file
9
zmk/app/scripts/west-commands.yml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Copyright (c) 2020, ZMK Contributors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
west-commands:
|
||||||
|
- file: scripts/west_commands/test.py
|
||||||
|
commands:
|
||||||
|
- name: test
|
||||||
|
class: Test
|
||||||
|
help: run zmk testsuite
|
33
zmk/app/scripts/west_commands/test.py
Normal file
33
zmk/app/scripts/west_commands/test.py
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# Copyright (c) 2020 The ZMK Contributors
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
'''Test runner for ZMK.'''
|
||||||
|
|
||||||
|
import os
|
||||||
|
from textwrap import dedent # just for nicer code indentation
|
||||||
|
|
||||||
|
from west.commands import WestCommand
|
||||||
|
from west import log # use this for user output
|
||||||
|
|
||||||
|
|
||||||
|
class Test(WestCommand):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(
|
||||||
|
'test', # gets stored as self.name
|
||||||
|
'run zmk testsuite', # self.help
|
||||||
|
# self.description:
|
||||||
|
dedent('''Run the zmk testsuite.'''))
|
||||||
|
|
||||||
|
def do_add_parser(self, parser_adder):
|
||||||
|
parser = parser_adder.add_parser(self.name,
|
||||||
|
help=self.help,
|
||||||
|
description=self.description)
|
||||||
|
|
||||||
|
parser.add_argument('test_path', default="all",
|
||||||
|
help='The path to the test. Defaults to "all".', nargs="?")
|
||||||
|
return parser # gets stored as self.parser
|
||||||
|
|
||||||
|
def do_run(self, args, unknown_args):
|
||||||
|
# the run-test script assumes the app directory is the current dir.
|
||||||
|
os.chdir(f'{self.topdir}/app')
|
||||||
|
exit(os.system(f'{self.topdir}/app/run-test.sh {args.test_path}'))
|
|
@ -53,13 +53,13 @@ int zmk_endpoints_toggle() {
|
||||||
return zmk_endpoints_select(new_endpoint);
|
return zmk_endpoints_select(new_endpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int send_keypad_report() {
|
static int send_keyboard_report() {
|
||||||
struct zmk_hid_keypad_report *keypad_report = zmk_hid_get_keypad_report();
|
struct zmk_hid_keyboard_report *keyboard_report = zmk_hid_get_keyboard_report();
|
||||||
|
|
||||||
switch (current_endpoint) {
|
switch (current_endpoint) {
|
||||||
#if IS_ENABLED(CONFIG_ZMK_USB)
|
#if IS_ENABLED(CONFIG_ZMK_USB)
|
||||||
case ZMK_ENDPOINT_USB: {
|
case ZMK_ENDPOINT_USB: {
|
||||||
int err = zmk_usb_hid_send_report((u8_t *)keypad_report, sizeof(*keypad_report));
|
int err = zmk_usb_hid_send_report((u8_t *)keyboard_report, sizeof(*keyboard_report));
|
||||||
if (err) {
|
if (err) {
|
||||||
LOG_ERR("FAILED TO SEND OVER USB: %d", err);
|
LOG_ERR("FAILED TO SEND OVER USB: %d", err);
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ static int send_keypad_report() {
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_ZMK_BLE)
|
#if IS_ENABLED(CONFIG_ZMK_BLE)
|
||||||
case ZMK_ENDPOINT_BLE: {
|
case ZMK_ENDPOINT_BLE: {
|
||||||
int err = zmk_hog_send_keypad_report(&keypad_report->body);
|
int err = zmk_hog_send_keyboard_report(&keyboard_report->body);
|
||||||
if (err) {
|
if (err) {
|
||||||
LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
|
LOG_ERR("FAILED TO SEND OVER HOG: %d", err);
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ int zmk_endpoints_send_report(u8_t usage_page) {
|
||||||
LOG_DBG("usage page 0x%02X", usage_page);
|
LOG_DBG("usage page 0x%02X", usage_page);
|
||||||
switch (usage_page) {
|
switch (usage_page) {
|
||||||
case HID_USAGE_KEY:
|
case HID_USAGE_KEY:
|
||||||
return send_keypad_report();
|
return send_keyboard_report();
|
||||||
case HID_USAGE_CONSUMER:
|
case HID_USAGE_CONSUMER:
|
||||||
return send_consumer_report();
|
return send_consumer_report();
|
||||||
default:
|
default:
|
||||||
|
@ -207,7 +207,7 @@ static enum zmk_endpoint get_selected_endpoint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void disconnect_current_endpoint() {
|
static void disconnect_current_endpoint() {
|
||||||
zmk_hid_keypad_clear();
|
zmk_hid_keyboard_clear();
|
||||||
zmk_hid_consumer_clear();
|
zmk_hid_consumer_clear();
|
||||||
|
|
||||||
zmk_endpoints_send_report(HID_USAGE_KEY);
|
zmk_endpoints_send_report(HID_USAGE_KEY);
|
||||||
|
|
|
@ -10,7 +10,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
#include <zmk/hid.h>
|
#include <zmk/hid.h>
|
||||||
#include <dt-bindings/zmk/modifiers.h>
|
#include <dt-bindings/zmk/modifiers.h>
|
||||||
|
|
||||||
static struct zmk_hid_keypad_report kp_report = {
|
static struct zmk_hid_keyboard_report kp_report = {
|
||||||
.report_id = 1, .body = {.modifiers = 0, ._reserved = 0, .keys = {0}}};
|
.report_id = 1, .body = {.modifiers = 0, ._reserved = 0, .keys = {0}}};
|
||||||
|
|
||||||
static struct zmk_hid_consumer_report consumer_report = {.report_id = 2, .body = {.keys = {0}}};
|
static struct zmk_hid_consumer_report consumer_report = {.report_id = 2, .body = {.keys = {0}}};
|
||||||
|
@ -49,8 +49,8 @@ int zmk_hid_unregister_mod(zmk_mod modifier) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TOGGLE_KEYPAD(match, val) \
|
#define TOGGLE_KEYBOARD(match, val) \
|
||||||
for (int idx = 0; idx < ZMK_HID_KEYPAD_NKRO_SIZE; idx++) { \
|
for (int idx = 0; idx < ZMK_HID_KEYBOARD_NKRO_SIZE; idx++) { \
|
||||||
if (kp_report.body.keys[idx] != match) { \
|
if (kp_report.body.keys[idx] != match) { \
|
||||||
continue; \
|
continue; \
|
||||||
} \
|
} \
|
||||||
|
@ -77,23 +77,23 @@ int zmk_hid_implicit_modifiers_release() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int zmk_hid_keypad_press(zmk_key code) {
|
int zmk_hid_keyboard_press(zmk_key code) {
|
||||||
if (code >= HID_USAGE_KEY_KEYBOARD_LEFTCONTROL && code <= HID_USAGE_KEY_KEYBOARD_RIGHT_GUI) {
|
if (code >= HID_USAGE_KEY_KEYBOARD_LEFTCONTROL && code <= HID_USAGE_KEY_KEYBOARD_RIGHT_GUI) {
|
||||||
return zmk_hid_register_mod(code - HID_USAGE_KEY_KEYBOARD_LEFTCONTROL);
|
return zmk_hid_register_mod(code - HID_USAGE_KEY_KEYBOARD_LEFTCONTROL);
|
||||||
}
|
}
|
||||||
TOGGLE_KEYPAD(0U, code);
|
TOGGLE_KEYBOARD(0U, code);
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
int zmk_hid_keypad_release(zmk_key code) {
|
int zmk_hid_keyboard_release(zmk_key code) {
|
||||||
if (code >= HID_USAGE_KEY_KEYBOARD_LEFTCONTROL && code <= HID_USAGE_KEY_KEYBOARD_RIGHT_GUI) {
|
if (code >= HID_USAGE_KEY_KEYBOARD_LEFTCONTROL && code <= HID_USAGE_KEY_KEYBOARD_RIGHT_GUI) {
|
||||||
return zmk_hid_unregister_mod(code - HID_USAGE_KEY_KEYBOARD_LEFTCONTROL);
|
return zmk_hid_unregister_mod(code - HID_USAGE_KEY_KEYBOARD_LEFTCONTROL);
|
||||||
}
|
}
|
||||||
TOGGLE_KEYPAD(code, 0U);
|
TOGGLE_KEYBOARD(code, 0U);
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void zmk_hid_keypad_clear() { memset(&kp_report.body, 0, sizeof(kp_report.body)); }
|
void zmk_hid_keyboard_clear() { memset(&kp_report.body, 0, sizeof(kp_report.body)); }
|
||||||
|
|
||||||
int zmk_hid_consumer_press(zmk_key code) {
|
int zmk_hid_consumer_press(zmk_key code) {
|
||||||
TOGGLE_CONSUMER(0U, code);
|
TOGGLE_CONSUMER(0U, code);
|
||||||
|
@ -107,7 +107,7 @@ int zmk_hid_consumer_release(zmk_key code) {
|
||||||
|
|
||||||
void zmk_hid_consumer_clear() { memset(&consumer_report.body, 0, sizeof(consumer_report.body)); }
|
void zmk_hid_consumer_clear() { memset(&consumer_report.body, 0, sizeof(consumer_report.body)); }
|
||||||
|
|
||||||
struct zmk_hid_keypad_report *zmk_hid_get_keypad_report() {
|
struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report() {
|
||||||
return &kp_report;
|
return &kp_report;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ static int hid_listener_keycode_pressed(u8_t usage_page, u32_t keycode,
|
||||||
implicit_modifiers);
|
implicit_modifiers);
|
||||||
switch (usage_page) {
|
switch (usage_page) {
|
||||||
case HID_USAGE_KEY:
|
case HID_USAGE_KEY:
|
||||||
err = zmk_hid_keypad_press(keycode);
|
err = zmk_hid_keyboard_press(keycode);
|
||||||
if (err) {
|
if (err) {
|
||||||
LOG_ERR("Unable to press keycode");
|
LOG_ERR("Unable to press keycode");
|
||||||
return err;
|
return err;
|
||||||
|
@ -48,7 +48,7 @@ static int hid_listener_keycode_released(u8_t usage_page, u32_t keycode,
|
||||||
implicit_modifiers);
|
implicit_modifiers);
|
||||||
switch (usage_page) {
|
switch (usage_page) {
|
||||||
case HID_USAGE_KEY:
|
case HID_USAGE_KEY:
|
||||||
err = zmk_hid_keypad_release(keycode);
|
err = zmk_hid_keyboard_release(keycode);
|
||||||
if (err) {
|
if (err) {
|
||||||
LOG_ERR("Unable to release keycode");
|
LOG_ERR("Unable to release keycode");
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -79,9 +79,9 @@ static ssize_t read_hids_report_map(struct bt_conn *conn, const struct bt_gatt_a
|
||||||
|
|
||||||
static ssize_t read_hids_input_report(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
static ssize_t read_hids_input_report(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||||
void *buf, u16_t len, u16_t offset) {
|
void *buf, u16_t len, u16_t offset) {
|
||||||
struct zmk_hid_keypad_report_body *report_body = &zmk_hid_get_keypad_report()->body;
|
struct zmk_hid_keyboard_report_body *report_body = &zmk_hid_get_keyboard_report()->body;
|
||||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, report_body,
|
return bt_gatt_attr_read(conn, attr, buf, len, offset, report_body,
|
||||||
sizeof(struct zmk_hid_keypad_report_body));
|
sizeof(struct zmk_hid_keyboard_report_body));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t read_hids_consumer_input_report(struct bt_conn *conn,
|
static ssize_t read_hids_consumer_input_report(struct bt_conn *conn,
|
||||||
|
@ -156,7 +156,7 @@ struct bt_conn *destination_connection() {
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
int zmk_hog_send_keypad_report(struct zmk_hid_keypad_report_body *report) {
|
int zmk_hog_send_keyboard_report(struct zmk_hid_keyboard_report_body *report) {
|
||||||
struct bt_conn *conn = destination_connection();
|
struct bt_conn *conn = destination_connection();
|
||||||
if (conn == NULL) {
|
if (conn == NULL) {
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
|
@ -164,8 +164,8 @@ int zmk_hog_send_keypad_report(struct zmk_hid_keypad_report_body *report) {
|
||||||
|
|
||||||
LOG_DBG("Sending to NULL? %s", conn == NULL ? "yes" : "no");
|
LOG_DBG("Sending to NULL? %s", conn == NULL ? "yes" : "no");
|
||||||
|
|
||||||
int err =
|
int err = bt_gatt_notify(conn, &hog_svc.attrs[5], report,
|
||||||
bt_gatt_notify(conn, &hog_svc.attrs[5], report, sizeof(struct zmk_hid_keypad_report_body));
|
sizeof(struct zmk_hid_keyboard_report_body));
|
||||||
bt_conn_unref(conn);
|
bt_conn_unref(conn);
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
|
|
|
@ -130,14 +130,12 @@ int zmk_keymap_apply_position_state(int layer, u32_t position, bool pressed, s64
|
||||||
}
|
}
|
||||||
|
|
||||||
int zmk_keymap_position_state_changed(u32_t position, bool pressed, s64_t timestamp) {
|
int zmk_keymap_position_state_changed(u32_t position, bool pressed, s64_t timestamp) {
|
||||||
for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= zmk_keymap_layer_default; layer--) {
|
if (pressed) {
|
||||||
u32_t layer_state =
|
|
||||||
pressed ? zmk_keymap_layer_state : zmk_keymap_active_behavior_layer[position];
|
|
||||||
if (is_active_layer(layer, layer_state)) {
|
|
||||||
int ret = zmk_keymap_apply_position_state(layer, position, pressed, timestamp);
|
|
||||||
|
|
||||||
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 (is_active_layer(layer, zmk_keymap_active_behavior_layer[position])) {
|
||||||
|
int ret = zmk_keymap_apply_position_state(layer, 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;
|
||||||
|
|
2
zmk/app/tests/momentary-layer/1-normal/events.patterns
Normal file
2
zmk/app/tests/momentary-layer/1-normal/events.patterns
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
s/.*hid_listener_keycode/kp/p
|
||||||
|
s/.*mo_keymap_binding/mo/p
|
|
@ -0,0 +1,4 @@
|
||||||
|
mo_pressed: position 1 layer 1
|
||||||
|
kp_pressed: usage_page 0x07 keycode 0x06 mods 0x00
|
||||||
|
kp_released: usage_page 0x07 keycode 0x06 mods 0x00
|
||||||
|
mo_released: position 1 layer 1
|
32
zmk/app/tests/momentary-layer/1-normal/native_posix.keymap
Normal file
32
zmk/app/tests/momentary-layer/1-normal/native_posix.keymap
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan-mock.h>
|
||||||
|
#include "../behavior_keymap.dtsi"
|
||||||
|
|
||||||
|
/ {
|
||||||
|
keymap {
|
||||||
|
compatible = "zmk,keymap";
|
||||||
|
label ="Default keymap";
|
||||||
|
|
||||||
|
default_layer {
|
||||||
|
bindings = <
|
||||||
|
&kp B &mo 1
|
||||||
|
&none &none>;
|
||||||
|
};
|
||||||
|
|
||||||
|
layer_1 {
|
||||||
|
bindings = <
|
||||||
|
&kp C &trans
|
||||||
|
&none &none>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&kscan {
|
||||||
|
events = <
|
||||||
|
ZMK_MOCK_PRESS(0,1,10)
|
||||||
|
ZMK_MOCK_PRESS(0,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,1,10)
|
||||||
|
>;
|
||||||
|
};
|
|
@ -0,0 +1,2 @@
|
||||||
|
s/.*hid_listener_keycode/kp/p
|
||||||
|
s/.*mo_keymap_binding/mo/p
|
|
@ -0,0 +1,4 @@
|
||||||
|
kp_pressed: usage_page 0x07 keycode 0x05 mods 0x00
|
||||||
|
mo_pressed: position 1 layer 1
|
||||||
|
kp_released: usage_page 0x07 keycode 0x05 mods 0x00
|
||||||
|
mo_released: position 1 layer 1
|
|
@ -0,0 +1,32 @@
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan-mock.h>
|
||||||
|
#include "../behavior_keymap.dtsi"
|
||||||
|
|
||||||
|
/ {
|
||||||
|
keymap {
|
||||||
|
compatible = "zmk,keymap";
|
||||||
|
label ="Default keymap";
|
||||||
|
|
||||||
|
default_layer {
|
||||||
|
bindings = <
|
||||||
|
&kp B &mo 1
|
||||||
|
&none &none>;
|
||||||
|
};
|
||||||
|
|
||||||
|
layer_1 {
|
||||||
|
bindings = <
|
||||||
|
&kp C &none
|
||||||
|
&none &none>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&kscan {
|
||||||
|
events = <
|
||||||
|
ZMK_MOCK_PRESS(0,0,10)
|
||||||
|
ZMK_MOCK_PRESS(0,1,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,1,10)
|
||||||
|
>;
|
||||||
|
};
|
3
zmk/app/tests/momentary-layer/3-covered/events.patterns
Normal file
3
zmk/app/tests/momentary-layer/3-covered/events.patterns
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
s/.*hid_listener_keycode/kp/p
|
||||||
|
s/.*mo_keymap_binding/mo/p
|
||||||
|
s/.*keymap_position_state_changed/kp_st/p
|
|
@ -0,0 +1,2 @@
|
||||||
|
mo_pressed: position 1 layer 1
|
||||||
|
mo_released: position 1 layer 1
|
33
zmk/app/tests/momentary-layer/3-covered/native_posix.keymap
Normal file
33
zmk/app/tests/momentary-layer/3-covered/native_posix.keymap
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan-mock.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
this test verifies that the correct key is released when a layer is enabled "on top"
|
||||||
|
and the original key is "covered".
|
||||||
|
*/
|
||||||
|
/ {
|
||||||
|
keymap {
|
||||||
|
compatible = "zmk,keymap";
|
||||||
|
label ="Default keymap";
|
||||||
|
|
||||||
|
default_layer {
|
||||||
|
bindings = <
|
||||||
|
&trans &mo 1
|
||||||
|
&trans &trans>;
|
||||||
|
};
|
||||||
|
|
||||||
|
layer_1 {
|
||||||
|
bindings = <
|
||||||
|
&trans &kp A
|
||||||
|
&trans &trans>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&kscan {
|
||||||
|
events = <
|
||||||
|
ZMK_MOCK_PRESS(0,1,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,1,10)
|
||||||
|
>;
|
||||||
|
};
|
3
zmk/app/tests/momentary-layer/4-nested/events.patterns
Normal file
3
zmk/app/tests/momentary-layer/4-nested/events.patterns
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
s/.*hid_listener_keycode/kp/p
|
||||||
|
s/.*mo_keymap_binding/mo/p
|
||||||
|
s/.*keymap_position_state_changed/kp_st/p
|
|
@ -0,0 +1,6 @@
|
||||||
|
mo_pressed: position 1 layer 1
|
||||||
|
mo_pressed: position 0 layer 2
|
||||||
|
kp_pressed: usage_page 0x07 keycode 0x05 mods 0x00
|
||||||
|
kp_released: usage_page 0x07 keycode 0x05 mods 0x00
|
||||||
|
mo_released: position 0 layer 2
|
||||||
|
mo_released: position 1 layer 1
|
39
zmk/app/tests/momentary-layer/4-nested/native_posix.keymap
Normal file
39
zmk/app/tests/momentary-layer/4-nested/native_posix.keymap
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan-mock.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
keymap {
|
||||||
|
compatible = "zmk,keymap";
|
||||||
|
label ="Default keymap";
|
||||||
|
|
||||||
|
default_layer {
|
||||||
|
bindings = <
|
||||||
|
&none &mo 1
|
||||||
|
&none &none>;
|
||||||
|
};
|
||||||
|
|
||||||
|
layer_1 {
|
||||||
|
bindings = <
|
||||||
|
&mo 2 &none
|
||||||
|
&none &none>;
|
||||||
|
};
|
||||||
|
|
||||||
|
layer_2 {
|
||||||
|
bindings = <
|
||||||
|
&none &none
|
||||||
|
&kp B &none>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&kscan {
|
||||||
|
events = <
|
||||||
|
ZMK_MOCK_PRESS(0,1,10)
|
||||||
|
ZMK_MOCK_PRESS(0,0,10)
|
||||||
|
ZMK_MOCK_PRESS(1,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(1,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,1,10)
|
||||||
|
>;
|
||||||
|
};
|
|
@ -0,0 +1,3 @@
|
||||||
|
s/.*hid_listener_keycode/kp/p
|
||||||
|
s/.*mo_keymap_binding/mo/p
|
||||||
|
s/.*keymap_position_state_changed/kp_st/p
|
|
@ -0,0 +1,6 @@
|
||||||
|
mo_pressed: position 1 layer 1
|
||||||
|
mo_pressed: position 0 layer 2
|
||||||
|
kp_pressed: usage_page 0x07 keycode 0x05 mods 0x00
|
||||||
|
mo_released: position 1 layer 1
|
||||||
|
mo_released: position 0 layer 2
|
||||||
|
kp_released: usage_page 0x07 keycode 0x05 mods 0x00
|
|
@ -0,0 +1,39 @@
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/kscan-mock.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
keymap {
|
||||||
|
compatible = "zmk,keymap";
|
||||||
|
label ="Default keymap";
|
||||||
|
|
||||||
|
default_layer {
|
||||||
|
bindings = <
|
||||||
|
&none &mo 1
|
||||||
|
&none &none>;
|
||||||
|
};
|
||||||
|
|
||||||
|
layer_1 {
|
||||||
|
bindings = <
|
||||||
|
&mo 2 &none
|
||||||
|
&none &none>;
|
||||||
|
};
|
||||||
|
|
||||||
|
layer_2 {
|
||||||
|
bindings = <
|
||||||
|
&none &none
|
||||||
|
&kp B &none>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&kscan {
|
||||||
|
events = <
|
||||||
|
ZMK_MOCK_PRESS(0,1,10)
|
||||||
|
ZMK_MOCK_PRESS(0,0,10)
|
||||||
|
ZMK_MOCK_PRESS(1,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,1,10)
|
||||||
|
ZMK_MOCK_RELEASE(0,0,10)
|
||||||
|
ZMK_MOCK_RELEASE(1,0,10)
|
||||||
|
>;
|
||||||
|
};
|
|
@ -10,19 +10,13 @@
|
||||||
default_layer {
|
default_layer {
|
||||||
bindings = <
|
bindings = <
|
||||||
&kp B &mo 1
|
&kp B &mo 1
|
||||||
&kp D &kp G>;
|
&trans &trans>;
|
||||||
};
|
};
|
||||||
|
|
||||||
lower_layer {
|
layer_1 {
|
||||||
bindings = <
|
bindings = <
|
||||||
&kp C_NEXT &trans
|
&kp C_NEXT &trans
|
||||||
&kp L &kp J>;
|
&trans &trans>;
|
||||||
};
|
|
||||||
|
|
||||||
raise_layer {
|
|
||||||
bindings = <
|
|
||||||
&kp W &kp U
|
|
||||||
&kp X &kp M>;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,4 +37,4 @@ manifest:
|
||||||
remote: microsoft
|
remote: microsoft
|
||||||
path: tools/uf2
|
path: tools/uf2
|
||||||
self:
|
self:
|
||||||
path: zmk
|
west-commands: scripts/west-commands.yml
|
|
@ -15,13 +15,13 @@ With interest and Discord activity growing, it seemed important to lay out the p
|
||||||
|
|
||||||
There's been lots of various activity in ZMK land!
|
There's been lots of various activity in ZMK land!
|
||||||
|
|
||||||
- [Nicell](https://github.com/Nicell) (nice!nano creator) contributed initial [RGB Underglow](/docs/feature/underglow) ([#64](https://github.com/zmkfirmware/zmk/pull/64)) support to ZMK.
|
- [Nicell](https://github.com/Nicell) (nice!nano creator) contributed initial [RGB Underglow](/docs/features/underglow) ([#64](https://github.com/zmkfirmware/zmk/pull/64)) support to ZMK.
|
||||||
- Tons of [documentation](/docs) work.
|
- Tons of [documentation](/docs) work.
|
||||||
- Refactoring ([#73](https://github.com/zmkfirmware/zmk/pull/73), [#74](https://github.com/zmkfirmware/zmk/pull/74)) of [keymaps](/docs/feature/keymaps) to make them simpler for users.
|
- Refactoring ([#73](https://github.com/zmkfirmware/zmk/pull/73), [#74](https://github.com/zmkfirmware/zmk/pull/74)) of [keymaps](/docs/features/keymaps) to make them simpler for users.
|
||||||
- Mod-Tap Behavior (docs coming!) is much improved ([#69](https://github.com/zmkfirmware/zmk/pull/69)) and usable now.
|
- Mod-Tap Behavior (docs coming!) is much improved ([#69](https://github.com/zmkfirmware/zmk/pull/69)) and usable now.
|
||||||
- An initial [`setup.sh`](http://localhost:3000/docs/user-setup#user-config-setup-script) script was created, allowing users to quickly bootstrap a "user config" setup and push it to GitHub, where GitHub Actions will build the firmware for you.
|
- An initial [`setup.sh`](http://localhost:3000/docs/user-setup#user-config-setup-script) script was created, allowing users to quickly bootstrap a "user config" setup and push it to GitHub, where GitHub Actions will build the firmware for you.
|
||||||
- Corne shield ([#80](https://github.com/zmkfirmware/zmk/pull/80)) shield definition was added.
|
- Corne shield ([#80](https://github.com/zmkfirmware/zmk/pull/80)) shield definition was added.
|
||||||
- Initial [encoder](/docs/feature/encoders) support ([#61](https://github.com/zmkfirmware/zmk/pull/61)) was added.
|
- Initial [encoder](/docs/features/encoders) support ([#61](https://github.com/zmkfirmware/zmk/pull/61)) was added.
|
||||||
|
|
||||||
## Bugs and Showstoppers
|
## Bugs and Showstoppers
|
||||||
|
|
||||||
|
|
|
@ -16,16 +16,16 @@ Hacktoberfest activity, and a current open call for community feedback on a ZMK
|
||||||
|
|
||||||
So much going on in ZMK!
|
So much going on in ZMK!
|
||||||
|
|
||||||
- Added a new generic [Hold Tap behavior](https://zmkfirmware.dev/docs/behavior/hold-tap)
|
- Added a new generic [Hold Tap behavior](https://zmkfirmware.dev/docs/behaviors/hold-tap)
|
||||||
in [#146](https://github.com/zmkfirmware/zmk/pull/146) which now powers mod-tap, layer-tap, etc. - [okke-formsma]
|
in [#146](https://github.com/zmkfirmware/zmk/pull/146) which now powers mod-tap, layer-tap, etc. - [okke-formsma]
|
||||||
- [BLE profile/connection management](https://zmkfirmware.dev/docs/behavior/bluetooth)
|
- [BLE profile/connection management](https://zmkfirmware.dev/docs/behaviors/bluetooth)
|
||||||
in [#133](https://github.com/zmkfirmware/zmk/pull/133) - [petejohanson]
|
in [#133](https://github.com/zmkfirmware/zmk/pull/133) - [petejohanson]
|
||||||
- Integration tests were added to automate testing of behaviors in [#131](https://github.com/zmkfirmware/zmk/pull/131) by [BrainWart] & [petejohanson]
|
- Integration tests were added to automate testing of behaviors in [#131](https://github.com/zmkfirmware/zmk/pull/131) by [BrainWart] & [petejohanson]
|
||||||
- [Toggle layer behavior](https://zmkfirmware.dev/docs/behavior/layers#toggle-layer), e.g. `&tog LOWER`, in
|
- [Toggle layer behavior](https://zmkfirmware.dev/docs/behaviors/layers#toggle-layer), e.g. `&tog LOWER`, in
|
||||||
[#98](https://github.com/zmkfirmware/zmk/pull/98) - [BrainWart]
|
[#98](https://github.com/zmkfirmware/zmk/pull/98) - [BrainWart]
|
||||||
- Key fix for dropped press/release over HID [#93](https://github.com/zmkfirmware/zmk/pull/93)/[#96](https://github.com/zmkfirmware/zmk/pull/96) - [careyk007](https://github.com/careyk007) & [petejohanson]
|
- Key fix for dropped press/release over HID [#93](https://github.com/zmkfirmware/zmk/pull/93)/[#96](https://github.com/zmkfirmware/zmk/pull/96) - [careyk007](https://github.com/careyk007) & [petejohanson]
|
||||||
- Code formatting standardized using `clang-format` in [#183](https://github.com/zmkfirmware/zmk/pull/183) - [petejohanson]
|
- Code formatting standardized using `clang-format` in [#183](https://github.com/zmkfirmware/zmk/pull/183) - [petejohanson]
|
||||||
- [Bootloader reset behavior](https://zmkfirmware.dev/docs/behavior/reset#bootloader-reset), e.g. `&bootloader`, in [#116](https://github.com/zmkfirmware/zmk/pull/116) - [petejohanson]
|
- [Bootloader reset behavior](https://zmkfirmware.dev/docs/behaviors/reset#bootloader-reset), e.g. `&bootloader`, in [#116](https://github.com/zmkfirmware/zmk/pull/116) - [petejohanson]
|
||||||
- Various bug fixes and documentation
|
- Various bug fixes and documentation
|
||||||
|
|
||||||
## New Shields
|
## New Shields
|
||||||
|
|
|
@ -67,7 +67,7 @@ With this change, you can add
|
||||||
&ext_power EP_TOG
|
&ext_power EP_TOG
|
||||||
```
|
```
|
||||||
|
|
||||||
to toggle (on/off) the power to external hardware like RGB underglow or OLEDs. Check out the [external power control](/docs/behavior/power#external-power-control) docs for more info.
|
to toggle (on/off) the power to external hardware like RGB underglow or OLEDs. Check out the [external power control](/docs/behaviors/power#external-power-control) docs for more info.
|
||||||
|
|
||||||
#### Deep Sleep
|
#### Deep Sleep
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ included some automatic power savings by switching to PORT events on the nRF52 c
|
||||||
|
|
||||||
#### Output Selection
|
#### Output Selection
|
||||||
|
|
||||||
[joelspadin] added [output selection](/docs/behavior/outputs) to allow selecting whether to send output over USB or BLE if both are connected. This should now help avoid having "double keypresses" when your keyboard is plugged into a host.
|
[joelspadin] added [output selection](/docs/behaviors/outputs) to allow selecting whether to send output over USB or BLE if both are connected. This should now help avoid having "double keypresses" when your keyboard is plugged into a host.
|
||||||
|
|
||||||
#### Bootloader Corruption Fix
|
#### Bootloader Corruption Fix
|
||||||
|
|
||||||
|
|
76
zmk/docs/docs/behaviors/bluetooth.md
Normal file
76
zmk/docs/docs/behaviors/bluetooth.md
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
---
|
||||||
|
title: Bluetooth Behavior
|
||||||
|
sidebar_label: Bluetooth
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
The bluetooth behavior allows management of various settings and states related to the bluetooth connection(s)
|
||||||
|
between the keyboard and the host. By default, ZMK supports five "profiles" for selecting which bonded host
|
||||||
|
computer/laptop/keyboard should receive the keyboard input; many of the commands here operation on those profiles.
|
||||||
|
|
||||||
|
## Bluetooth Command Defines
|
||||||
|
|
||||||
|
Bluetooth command defines are provided through the [`dt-bindings/zmk/bt.h`](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/bt.h) header,
|
||||||
|
which is added at the top of the keymap file:
|
||||||
|
|
||||||
|
```
|
||||||
|
#include <dt-bindings/zmk/bt.h>
|
||||||
|
```
|
||||||
|
|
||||||
|
This will allow you to reference the actions defined in this header such as `BT_CLR_CMD`.
|
||||||
|
|
||||||
|
Here is a table describing the command for each define:
|
||||||
|
|
||||||
|
| Define | Action |
|
||||||
|
| ------------ | ---------------------------------------------------------------------------------------------- |
|
||||||
|
| `BT_CLR_CMD` | Clear bond information between the keyboard and host for the selected profile. |
|
||||||
|
| `BT_NXT_CMD` | Switch to the next profile, cycling through to the first one when the end is reached. |
|
||||||
|
| `BT_PRV_CMD` | Switch to the previous profile, cycling through to the last one when the beginning is reached. |
|
||||||
|
| `BT_SEL_CMD` | Select the 0-indexed profile by number. |
|
||||||
|
|
||||||
|
Because at least one bluetooth commands takes an additional parameter, it is recommended to use
|
||||||
|
the following aliases in your keymap to avoid having to specify an ignored second parameter:
|
||||||
|
|
||||||
|
| Define | Action |
|
||||||
|
| -------- | -------------------------------------------------------------------------------- |
|
||||||
|
| `BT_CLR` | Alias for `BT_CLR_CMD 0` to clear the current profile's bond to the current host |
|
||||||
|
| `BT_NXT` | Alias for `BT_NXT_CMD 0` to select the next profile |
|
||||||
|
| `BT_PRV` | Alias for `BT_PRV_CMD 0` to select the previous profile |
|
||||||
|
| `BT_SEL` | Alias for `BT_SEL_CMD` to select the given profile, e.g. `&bt BT_SEL 1` |
|
||||||
|
|
||||||
|
## Bluetooth Behavior
|
||||||
|
|
||||||
|
The bluetooth behavior completes an bluetooth action given on press.
|
||||||
|
|
||||||
|
### Behavior Binding
|
||||||
|
|
||||||
|
- Reference: `&bt`
|
||||||
|
- Parameter #1: The bluetooth command define, e.g. `BT_CLR_CMD`
|
||||||
|
- Parameter #2: (Reserved for future bluetooth command types)
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
1. Behavior binding to clear the paired host for the selected profile:
|
||||||
|
|
||||||
|
```
|
||||||
|
&bt BT_CLR
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Behavior binding to select the next profile:
|
||||||
|
|
||||||
|
```
|
||||||
|
&bt BT_NXT
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Behavior binding to select the previous profile:
|
||||||
|
|
||||||
|
```
|
||||||
|
&bt BT_PRV
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Behavior binding to select the 2nd profile (passed parameters are [zero based](https://en.wikipedia.org/wiki/Zero-based_numbering)):
|
||||||
|
|
||||||
|
```
|
||||||
|
&bt BT_SEL 1
|
||||||
|
```
|
75
zmk/docs/docs/behaviors/hold-tap.md
Normal file
75
zmk/docs/docs/behaviors/hold-tap.md
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
---
|
||||||
|
title: Hold-Tap Behavior
|
||||||
|
sidebar_label: Hold-Tap
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Hold-tap is the basis for other behaviors such as layer-tap and mod-tap.
|
||||||
|
|
||||||
|
Simply put, the hold-tap key will output the 'hold' behavior if it's held for a while, and output the 'tap' behavior when it's tapped quickly.
|
||||||
|
|
||||||
|
### Hold-Tap
|
||||||
|
|
||||||
|
The `tapping_term_ms` parameter decides between a 'tap' and a 'hold'.
|
||||||
|
|
||||||
|
![Simple behavior](../assets/hold-tap/case1_2.png)
|
||||||
|
|
||||||
|
By default, the hold-tap is configured to also select the 'hold' functionality if another key is tapped while it's active:
|
||||||
|
|
||||||
|
![Hold preferred behavior](../assets/hold-tap/case1_2.png)
|
||||||
|
|
||||||
|
We call this the 'hold-preferred' flavor of hold-taps. While this flavor may work very well for a ctrl/escape key, it's not very well suited for home-row mods or layer-taps. That's why there are two more flavors to choose from: 'tap-preferred' and 'balanced'.
|
||||||
|
|
||||||
|
#### Flavors
|
||||||
|
|
||||||
|
- The 'hold-preferred' flavor triggers the hold behavior when the tapping_term_ms has expired or another key is pressed.
|
||||||
|
- The 'balanced' flavor will trigger the hold behavior when the tapping_term_ms has expired or another key is pressed and released.
|
||||||
|
- The 'tap-preferred' flavor triggers the hold behavior when the tapping_term_ms has expired. It triggers the tap behavior when another key is pressed.
|
||||||
|
|
||||||
|
When the hold-tap key is released and the hold behavior has not been triggered, the tap behavior will trigger.
|
||||||
|
|
||||||
|
![Hold-tap comparison](../assets/hold-tap/comparison.png)
|
||||||
|
|
||||||
|
### Basic usage
|
||||||
|
|
||||||
|
For basic usage, please see [mod-tap](./mod-tap.md) and [layer-tap](./layers.md) pages.
|
||||||
|
|
||||||
|
### Advanced Configuration
|
||||||
|
|
||||||
|
This example configures a hold-tap that works well for homerow mods:
|
||||||
|
|
||||||
|
```
|
||||||
|
#include <behaviors.dtsi>
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
behaviors {
|
||||||
|
hm: homerow_mods {
|
||||||
|
compatible = "zmk,behavior-hold-tap";
|
||||||
|
label = "HOMEROW_MODS";
|
||||||
|
#binding-cells = <2>;
|
||||||
|
tapping_term_ms = <150>;
|
||||||
|
flavor = "tap-preferred";
|
||||||
|
bindings = <&kp>, <&kp>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
keymap {
|
||||||
|
compatible = "zmk,keymap";
|
||||||
|
|
||||||
|
default_layer {
|
||||||
|
bindings = <
|
||||||
|
&hm LCTRL A &hm LGUI S &hm LALT D &hm LSHFT F
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
If this config does not work for you, try the flavor "balanced" with a medium tapping_term_ms such as 200ms.
|
||||||
|
|
||||||
|
#### Comparison to QMK
|
||||||
|
|
||||||
|
The hold-preferred flavor works similar to the `HOLD_ON_OTHER_KEY_PRESS` setting in QMK. The 'balanced' flavor is similar to the `PERMISSIVE_HOLD` setting, and the `tap-preferred` flavor is similar to `IGNORE_MOD_TAP_INTERRUPT`.
|
54
zmk/docs/docs/behaviors/key-press.md
Normal file
54
zmk/docs/docs/behaviors/key-press.md
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
---
|
||||||
|
title: Key Press Behaviors
|
||||||
|
sidebar_label: Key Press
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
The most basic of behaviors, is the ability to send certain keycode presses and releases in response to activating
|
||||||
|
a certain key.
|
||||||
|
|
||||||
|
The categories of supported codes are:
|
||||||
|
|
||||||
|
- [Keyboard & Keypad](../codes/keyboard-keypad)
|
||||||
|
- [Editing](../codes/editing)
|
||||||
|
- [Media](../codes/media)
|
||||||
|
- [Applications](../codes/applications)
|
||||||
|
- [Input Assist](../codes/input-assist)
|
||||||
|
- [Power](../codes/power)
|
||||||
|
|
||||||
|
Please visit the [codes](../codes) section for a comprehensive list.
|
||||||
|
|
||||||
|
For advanced users, user-defined HID usages are also supported but must be encoded, please see [`dt-bindings/zmk/keys.h`](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/keys.h) for further insight.
|
||||||
|
|
||||||
|
## Keycode Defines
|
||||||
|
|
||||||
|
To make it easier to encode the HID keycode numeric values, most keymaps include
|
||||||
|
the [`dt-bindings/zmk/keys.h`](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/keys.h) header
|
||||||
|
provided by ZMK near the top:
|
||||||
|
|
||||||
|
```
|
||||||
|
#include <dt-bindings/zmk/keys.h>
|
||||||
|
```
|
||||||
|
|
||||||
|
Doing so makes a set of defines such as `A`, `N1`, etc. available for use with these behaviors
|
||||||
|
|
||||||
|
### Improperly defined keymap - `dtlib.DTError: <board>.dts.pre.tmp:<line number>`
|
||||||
|
|
||||||
|
When compiling firmware from a keymap, it may be common to encounter an error in the form of a`dtlib.DTError: <board>.dts.pre.tmp:<line number>`.
|
||||||
|
For instructions to resolve such an error, click [here](../troubleshooting###Improperly-defined-keymap)
|
||||||
|
|
||||||
|
## Key Press
|
||||||
|
|
||||||
|
The "key press" behavior sends standard keycodes on press/release.
|
||||||
|
|
||||||
|
### Behavior Binding
|
||||||
|
|
||||||
|
- Reference: `&kp`
|
||||||
|
- Parameter: The keycode usage ID from the usage page, e.g. `4` or `A`
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
&kp A
|
||||||
|
```
|
110
zmk/docs/docs/behaviors/layers.md
Normal file
110
zmk/docs/docs/behaviors/layers.md
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
---
|
||||||
|
title: Layer Behaviors
|
||||||
|
sidebar_label: Layers
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Often, you may want a certain key position to alter which layers are enabled, change the default layer, etc.
|
||||||
|
Some of those behaviors are still in the works; the ones that are working now are documented here.
|
||||||
|
|
||||||
|
## Defines To Refer To Layers
|
||||||
|
|
||||||
|
When working with layers, you may have several different key positions with bindings that enable/disable those layers.
|
||||||
|
To make it easier to refer to those layers in your key bindings, and to change which layers are where later, you can
|
||||||
|
add a set of `#define`s at the top of your keymap file, and use those layer in your keymap.
|
||||||
|
|
||||||
|
For example, if you have three layers, you can add the following to the top of your keymap:
|
||||||
|
|
||||||
|
```
|
||||||
|
#define DEFAULT 0
|
||||||
|
#define LOWER 1
|
||||||
|
#define RAISE 2
|
||||||
|
```
|
||||||
|
|
||||||
|
This allows you to use those defines, e.g. `LOWER` later in your keymap.
|
||||||
|
|
||||||
|
## Momentary Layer
|
||||||
|
|
||||||
|
The "momentary layer" behavior enables a layer while a certain key is pressed. Immediately upon
|
||||||
|
activation of the key, the layer is enabled, and immediately open release of the key, the layer is disabled
|
||||||
|
again.
|
||||||
|
|
||||||
|
### Behavior Binding
|
||||||
|
|
||||||
|
- Reference: `&mo`
|
||||||
|
- Parameter: The layer number to enable/disable, e.g. `1`
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
&mo LOWER
|
||||||
|
```
|
||||||
|
|
||||||
|
## Layer-tap
|
||||||
|
|
||||||
|
The "layer-tap" behavior enables a layer when a key is held, and output another key when the key is only tapped for a short time. For more information on the inner workings of layer-tap, see [hold-tap](./hold-tap.md).
|
||||||
|
|
||||||
|
### Behavior Binding
|
||||||
|
|
||||||
|
- Reference: `<`
|
||||||
|
- Parameter: The layer number to enable when held, e.g. `1`
|
||||||
|
- Parameter: The keycode to send when tapped, e.g. `A`
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
< LOWER SPACE
|
||||||
|
```
|
||||||
|
|
||||||
|
## Toggle Layer
|
||||||
|
|
||||||
|
The "toggle layer" behavior enables a layer until the layer is manually disabled.
|
||||||
|
|
||||||
|
### Behavior Binding
|
||||||
|
|
||||||
|
- Reference: `&tog`
|
||||||
|
- Parameter: The layer number to enable/disable, e.g. `1`
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
&tog LOWER
|
||||||
|
```
|
||||||
|
|
||||||
|
"Toggle layer" for a :
|
||||||
|
|
||||||
|
```
|
||||||
|
#define DEFAULT 0
|
||||||
|
#define NAVI 1
|
||||||
|
|
||||||
|
#define NONE 0
|
||||||
|
|
||||||
|
/ {
|
||||||
|
keymap {
|
||||||
|
compatible = "zmk,keymap";
|
||||||
|
|
||||||
|
default_layer {
|
||||||
|
bindings = <
|
||||||
|
&tog NAVI &kp KP_DIVIDE &kp KP_MULTIPLY &kp KP_MINUS
|
||||||
|
&kp NUMBER_7 &kp NUMBER_8 &kp NUMBER_9 &kp KP_PLUS
|
||||||
|
&kp NUMBER_4 &kp NUMBER_5 &kp NUMBER_6 &kp KP_PLUS
|
||||||
|
&kp NUMBER_1 &kp NUMBER_2 &kp NUMBER_3 &kp RETURN
|
||||||
|
&kp NUMBER_0 &kp NUMBER_0 &kp DOT &kp RETURN
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
nav_layer {
|
||||||
|
bindings = <
|
||||||
|
&tog NAVI &kp KP_DIVIDE &kp KP_MULTIPLY &kp KP_MINUS
|
||||||
|
&kp HOME &kp UP &kp PAGE_UP &kp KP_PLUS
|
||||||
|
&kp LEFT &none &kp RIGHT &kp KP_PLUS
|
||||||
|
&kp END &kp DOWN &kp PAGE_DOWN &kp RETURN
|
||||||
|
&kp INSERT &kp INSERT &kp DEL &kp RETURN
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
It is possible to use "toggle layer" to have keys that raise and lower the layers as well.
|
51
zmk/docs/docs/behaviors/lighting.md
Normal file
51
zmk/docs/docs/behaviors/lighting.md
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
---
|
||||||
|
title: Lighting Behavior
|
||||||
|
sidebar_label: Lighting
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Lighting is often used for either aesthetics or for the practical purposes of lighting up keys in the dark.
|
||||||
|
Currently ZMK supports RGB underglow, which can be changed and configured using its behavior.
|
||||||
|
|
||||||
|
## RGB Action Defines
|
||||||
|
|
||||||
|
RGB actions defines are provided through the [`dt-bindings/zmk/rgb.h`](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/rgb.h) header,
|
||||||
|
which is added at the top of the keymap file:
|
||||||
|
|
||||||
|
```
|
||||||
|
#include <dt-bindings/zmk/rgb.h>
|
||||||
|
```
|
||||||
|
|
||||||
|
This will allow you to reference the actions defined in this header such as `RGB_TOG`.
|
||||||
|
|
||||||
|
Here is a table describing the action for each define:
|
||||||
|
|
||||||
|
| Define | Action |
|
||||||
|
| --------- | --------------------------------------------------------- |
|
||||||
|
| `RGB_TOG` | Toggles the RGB feature on and off |
|
||||||
|
| `RGB_HUI` | Increases the hue of the RGB feature |
|
||||||
|
| `RGB_HUD` | Decreases the hue of the RGB feature |
|
||||||
|
| `RGB_SAI` | Increases the saturation of the RGB feature |
|
||||||
|
| `RGB_SAD` | Decreases the saturation of the RGB feature |
|
||||||
|
| `RGB_BRI` | Increases the brightness of the RGB feature |
|
||||||
|
| `RGB_BRD` | Decreases the brightness of the RGB feature |
|
||||||
|
| `RGB_SPI` | Increases the speed of the RGB feature effect's animation |
|
||||||
|
| `RGB_SPD` | Decreases the speed of the RGB feature effect's animation |
|
||||||
|
| `RGB_EFF` | Cycles the RGB feature's effect forwards |
|
||||||
|
| `RGB_EFR` | Cycles the RGB feature's effect reverse |
|
||||||
|
|
||||||
|
## RGB Underglow
|
||||||
|
|
||||||
|
The "RGB underglow" behavior completes an RGB action given on press.
|
||||||
|
|
||||||
|
### Behavior Binding
|
||||||
|
|
||||||
|
- Reference: `&rgb_ug`
|
||||||
|
- Parameter: The RGB action define, e.g. `RGB_TOG` or `RGB_BRI`
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
&rgb_ug RGB_TOG
|
||||||
|
```
|
42
zmk/docs/docs/behaviors/misc.md
Normal file
42
zmk/docs/docs/behaviors/misc.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
---
|
||||||
|
title: Miscellaneous Behaviors
|
||||||
|
sidebar_label: Miscellaneous
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
There are a few miscellaneous behaviors that are helpful when working with layers in keymaps,
|
||||||
|
in particular, with handling what happens in higher layers, and if events are passed to
|
||||||
|
the next layer or not
|
||||||
|
|
||||||
|
## Transparent
|
||||||
|
|
||||||
|
The transparent behavior simply ignores key position presses/releases, so they will be
|
||||||
|
passed down to the next active layer in the stack.
|
||||||
|
|
||||||
|
### Behavior Binding
|
||||||
|
|
||||||
|
- Reference: `&trans`
|
||||||
|
- Parameters: None
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
&trans
|
||||||
|
```
|
||||||
|
|
||||||
|
## None
|
||||||
|
|
||||||
|
The none behavior simply swallows and stops key position presses/releases, so they will **not**
|
||||||
|
be passed down to the next active layer in the stack.
|
||||||
|
|
||||||
|
### Behavior Binding
|
||||||
|
|
||||||
|
- Reference: `&none`
|
||||||
|
- Parameters: None
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
&none
|
||||||
|
```
|
42
zmk/docs/docs/behaviors/mod-tap.md
Normal file
42
zmk/docs/docs/behaviors/mod-tap.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
---
|
||||||
|
title: Mod-Tap Behavior
|
||||||
|
sidebar_label: Mod-Tap
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
The Mod-Tap sends a different keypress, if it's tapped or held. When you tap the key shortly, the first keycode is sent. If you hold the key for longer than 200ms, the second keycode is sent.
|
||||||
|
|
||||||
|
If you press another key within the 200ms, the 'mod' behavior is also activated.
|
||||||
|
|
||||||
|
## Mod-Tap
|
||||||
|
|
||||||
|
The Mod-Tap behavior either acts as a held modifier, or as a tapped keycode.
|
||||||
|
|
||||||
|
### Behavior Binding
|
||||||
|
|
||||||
|
- Reference: `&mt`
|
||||||
|
- Parameter #1: The keycode to be sent when activating as a modifier, e.g. `LSHFT`
|
||||||
|
- Parameter #2: The keycode to sent when used as a tap, e.g. `A`, `B`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
&mt LSHFT A
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
You can configure a different tapping term in your keymap:
|
||||||
|
|
||||||
|
```
|
||||||
|
&mt {
|
||||||
|
tapping_term_ms = <400>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/ {
|
||||||
|
keymap {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
59
zmk/docs/docs/behaviors/outputs.md
Normal file
59
zmk/docs/docs/behaviors/outputs.md
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
---
|
||||||
|
title: Output Selection Behavior
|
||||||
|
sidebar_label: Output Selection
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
The output behavior allows selecting whether keyboard output is sent to the
|
||||||
|
USB or bluetooth connection when both are connected. This allows connecting a
|
||||||
|
keyboard to USB for power but outputting to a different device over bluetooth.
|
||||||
|
|
||||||
|
By default, output is sent to USB when both USB and BLE are connected.
|
||||||
|
Once you select a different output, it will be remembered until you change it again.
|
||||||
|
|
||||||
|
## Output Command Defines
|
||||||
|
|
||||||
|
Output command defines are provided through the [`dt-bindings/zmk/outputs.h`](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/outputs.h)
|
||||||
|
header, which is added at the top of the keymap file:
|
||||||
|
|
||||||
|
```
|
||||||
|
#include <dt-bindings/zmk/outputs.h>
|
||||||
|
```
|
||||||
|
|
||||||
|
This allows you to reference the actions defined in this header:
|
||||||
|
|
||||||
|
| Define | Action |
|
||||||
|
| --------- | ----------------------------------------------- |
|
||||||
|
| `OUT_USB` | Prefer sending to USB |
|
||||||
|
| `OUT_BLE` | Prefer sending to the current bluetooth profile |
|
||||||
|
| `OUT_TOG` | Toggle between USB and BLE |
|
||||||
|
|
||||||
|
## Output Selection Behavior
|
||||||
|
|
||||||
|
The output selection behavior changes the preferred output on press.
|
||||||
|
|
||||||
|
### Behavior Binding
|
||||||
|
|
||||||
|
- Reference: `&out`
|
||||||
|
- Parameter #1: Command, e.g. `OUT_BLE`
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
1. Behavior binding to prefer sending keyboard output to USB
|
||||||
|
|
||||||
|
```
|
||||||
|
&out OUT_USB
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Behavior binding to prefer sending keyboard output to the current bluetooth profile
|
||||||
|
|
||||||
|
```
|
||||||
|
&out OUT_BLE
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Behavior binding to toggle between preferring USB and BLE
|
||||||
|
|
||||||
|
```
|
||||||
|
&out OUT_TOG
|
||||||
|
```
|
64
zmk/docs/docs/behaviors/power.md
Normal file
64
zmk/docs/docs/behaviors/power.md
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
---
|
||||||
|
title: Power Management Behaviors
|
||||||
|
sidebar_label: Power Management
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
These page contains some of the power management behaviors currently supported by ZMK.
|
||||||
|
|
||||||
|
## External Power Control
|
||||||
|
|
||||||
|
The External power control behavior allows enabling or disabling the VCC power output
|
||||||
|
to save power. Some of the LEDs will consume power even in OFF state. To preserve
|
||||||
|
battery life in this scenario, some controller boards have support to disable the
|
||||||
|
external power completely.
|
||||||
|
|
||||||
|
The following boards currently support this feature:
|
||||||
|
|
||||||
|
- nRFMicro
|
||||||
|
- nice!nano
|
||||||
|
|
||||||
|
## External Power Control Command Defines
|
||||||
|
|
||||||
|
External power control command defines are provided through the [`dt-bindings/zmk/ext_power.h`](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/ext_power.h) header,
|
||||||
|
which is added at the top of the keymap file:
|
||||||
|
|
||||||
|
```
|
||||||
|
#include <dt-bindings/zmk/ext_power.h>
|
||||||
|
```
|
||||||
|
|
||||||
|
This will allow you to reference the actions defined in this header such as `EXT_POWER_OFF_CMD`.
|
||||||
|
|
||||||
|
Here is a table describing the command for each define:
|
||||||
|
|
||||||
|
| Define | Action | Alias |
|
||||||
|
| ---------------------- | --------------------------- | -------- |
|
||||||
|
| `EXT_POWER_OFF_CMD` | Disable the external power. | `EP_OFF` |
|
||||||
|
| `EXT_POWER_ON_CMD` | Enable the external power. | `EP_ON` |
|
||||||
|
| `EXT_POWER_TOGGLE_CMD` | Toggle the external power. | `EP_TOG` |
|
||||||
|
|
||||||
|
### Behavior Binding
|
||||||
|
|
||||||
|
- Reference: `&ext_power`
|
||||||
|
- Parameter#1: Command, e.g `EP_ON`
|
||||||
|
|
||||||
|
### Example:
|
||||||
|
|
||||||
|
1. Behavior binding to enable the external power
|
||||||
|
|
||||||
|
```
|
||||||
|
&ext_power EP_ON
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Behavior binding to disable the external power
|
||||||
|
|
||||||
|
```
|
||||||
|
&ext_power EP_OFF
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Behavior binding to toggle the external power
|
||||||
|
|
||||||
|
```
|
||||||
|
&ext_power EP_TOG
|
||||||
|
```
|
43
zmk/docs/docs/behaviors/reset.md
Normal file
43
zmk/docs/docs/behaviors/reset.md
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
---
|
||||||
|
title: Reset Behaviors
|
||||||
|
sidebar_label: Reset
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
There are two available behaviors that can be used to trigger a reset of the keyboard.
|
||||||
|
The first is a soft reset, that will simply reset and re-run the currently flashed
|
||||||
|
firmware; the second when triggered will reset into the bootloader, allowing you to
|
||||||
|
flash a new firmware to the keyboard.
|
||||||
|
|
||||||
|
## Reset
|
||||||
|
|
||||||
|
The basic reset behavior will reset the keyboard and re-run the firmware flashed
|
||||||
|
to the device
|
||||||
|
|
||||||
|
### Behavior Binding
|
||||||
|
|
||||||
|
- Reference: `&reset`
|
||||||
|
- Parameters: None
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
&reset
|
||||||
|
```
|
||||||
|
|
||||||
|
## Bootloader Reset
|
||||||
|
|
||||||
|
The bootloader reset behavior will reset the keyboard and put it into bootloader mode, allowing
|
||||||
|
you to flash a new firmware.
|
||||||
|
|
||||||
|
### Behavior Binding
|
||||||
|
|
||||||
|
- Reference: `&bootloader`
|
||||||
|
- Parameters: None
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
&bootloader
|
||||||
|
```
|
|
@ -26,7 +26,7 @@ various config settings that can be commented/uncommented to modify how your fir
|
||||||
## Keymap
|
## Keymap
|
||||||
|
|
||||||
Once you have the basic user config completed, you can find the keymap file in `config/<shield>.keymap` and customize from there.
|
Once you have the basic user config completed, you can find the keymap file in `config/<shield>.keymap` and customize from there.
|
||||||
Refer to the [Keymap](/docs/feature/keymaps) documentation to learn more.
|
Refer to the [Keymap](/docs/features/keymaps) documentation to learn more.
|
||||||
|
|
||||||
## Publishing
|
## Publishing
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ If you need to, a review of [Learn The Basics Of Git In Under 10 Minutes](https:
|
||||||
|
|
||||||
## Building from a local `zmk` fork using `zmk-config`
|
## Building from a local `zmk` fork using `zmk-config`
|
||||||
|
|
||||||
[As outlined here](dev-build-flash), firmware comes in the form of .uf2 files, which can be built locally using the command `west build`. Normally,
|
[As outlined here](development/build-flash), firmware comes in the form of .uf2 files, which can be built locally using the command `west build`. Normally,
|
||||||
`west build` will default to using the in-tree .keymap and .conf files found in your local copy of the `zmk` repository. However, you can append the command, `-DZMK_CONFIG="C:/the/absolute/path/config"` to `west build` in order to use the contents of your `zmk-config` folder instead of the
|
`west build` will default to using the in-tree .keymap and .conf files found in your local copy of the `zmk` repository. However, you can append the command, `-DZMK_CONFIG="C:/the/absolute/path/config"` to `west build` in order to use the contents of your `zmk-config` folder instead of the
|
||||||
default keyboard settings.
|
default keyboard settings.
|
||||||
**Notice that this path should point to the folder labelled `config` within your `zmk-config` folder.**
|
**Notice that this path should point to the folder labelled `config` within your `zmk-config` folder.**
|
||||||
|
|
52
zmk/docs/docs/development/boards-shields-keymaps.md
Normal file
52
zmk/docs/docs/development/boards-shields-keymaps.md
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
---
|
||||||
|
title: Boards, Shields, and Keymaps
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture Overview
|
||||||
|
|
||||||
|
The foundational elements needed to get a specific keyboard working with ZMK can be broken down into:
|
||||||
|
|
||||||
|
- A [KSCAN driver](https://docs.zephyrproject.org/2.3.0/reference/peripherals/kscan.html), which uses `compatible="zmk,kscan-gpio-matrix"` for GPIO matrix based keyboards, or uses `compatible="zmk,kscan-gpio-direct"` for small direct wires.
|
||||||
|
- An optional matrix transform, which defines how the KSCAN row/column events are translated into logical "key positions". This is required for non-rectangular keyboards/matrices, where the key positions don't naturally follow the row/columns from the GPIO matrix.
|
||||||
|
- A keymap, which binds each key position to a behavior, e.g. key press, mod-tap, momentary layer, in a set of layers.
|
||||||
|
|
||||||
|
These three core architectural elements are defined per-keyboard, and _where_ they are defined depends on the specifics of how that
|
||||||
|
keyboard works. For an overview on the general concepts of boards and shields, please see the [FAQs on boards and shields](/docs/faq#why-boards-and-shields--why-not-just-keyboard).
|
||||||
|
|
||||||
|
## Self-Contained Keyboard
|
||||||
|
|
||||||
|
For a self-contained keyboard that includes the microprocessor, all of the above architecture components are included in the Zephyr _board_ definition. You can see an example for the [Planck V6](https://github.com/zmkfirmware/zmk/tree/main/app/boards/arm/planck) board directory.
|
||||||
|
|
||||||
|
With this type of keyboard, the full ZMK definition for the keyboard exists
|
||||||
|
in the `app/boards/${arch}/${board_name}` directory, e.g. `app/boards/arm/planck/`. In that directory, you'll have the following:
|
||||||
|
|
||||||
|
- A `Kconfig.board` file that defines the toplevel Kconfig item for the board, including which SoC Kconfig setting it depends on.
|
||||||
|
- A `Kconfig.defconfig` file that sets some initial defaults when building this keyboard. This usually includes:
|
||||||
|
- Setting `ZMK_KEYBOARD_NAME` to a value, for the product name to be used for USB/BLE info.
|
||||||
|
- Setting `ZMK_USB` and/or `ZMK_BLE` for the default values for which HID transport(s) to enable by default
|
||||||
|
- A `${board_name}_defconfig` file that forces specific Kconfig settings that are specific to this hardware configuration. Mostly this is SoC settings around the specific hardware configuration.
|
||||||
|
- `${board_name}.dts` which contains all the devicetree definitions, including:
|
||||||
|
- An `#include` line that pulls in the specific microprocessor that is used, e.g. `#include <st/f3/stm32f303Xc.dtsi>`.
|
||||||
|
- A [chosen](https://docs.zephyrproject.org/2.3.0/guides/dts/intro.html#aliases-and-chosen-nodes) node named `zmk,kscan` which references the configured KSCAN driver (usually a GPIO matrix)
|
||||||
|
- (Optional) A [chosen](https://docs.zephyrproject.org/2.3.0/guides/dts/intro.html#aliases-and-chosen-nodes) node named `zmk,matrix_transform` that defines the mapping from KSCAN row/column values to the logical key position for the keyboard.
|
||||||
|
- A `board.cmake` file with CMake directives for how to flash to the device.
|
||||||
|
- A `keymap/keymap.overlay` file that includes the default keymap for that keyboard. Users will be able to override this keymap in their user configs.
|
||||||
|
|
||||||
|
## Pro Micro Compatible Keyboard
|
||||||
|
|
||||||
|
![Labelled Pro Micro pins](../assets/pro-micro/pro-micro-pins-labelled.jpg)
|
||||||
|
|
||||||
|
For keyboards that require a (usually Pro Micro compatible) add-on board to operate, the ZMK integration pieces are places
|
||||||
|
in the _shield_ definition for that keyboard, allowing users to
|
||||||
|
swap in different Pro Micro compatible boards (e.g. Proton-C, or nice!nano) and build a firmware the matches their actual
|
||||||
|
combination of physical components.
|
||||||
|
|
||||||
|
With this type of keyboard, the partial definition for the keyboard exists
|
||||||
|
in the `app/boards/shields/${board_name}` directory, e.g. `app/boards/shields/clueboard_california/`. In that directory, you'll have the following:
|
||||||
|
|
||||||
|
- A `Kconfig.shield` that defines the toplevel Kconfig value for the shield, which uses a supplied utility to function to default the value based on the shield list, e.g. `def_bool $(shields_list_contains,clueboard_california)`.
|
||||||
|
- A `Kconfig.defconfig` file to set default values for things like `ZMK_KEYBOARD_NAME`
|
||||||
|
- A `${shield_name}.overlay` file, which is a devicetree overlay file, that includes:
|
||||||
|
- A [chosen](https://docs.zephyrproject.org/2.3.0/guides/dts/intro.html#aliases-and-chosen-nodes) node named `zmk,kscan` which references the configured KSCAN driver (usually a GPIO matrix). For these keyboards, to be compatible with any Pro Micro compatible boards, the KSCAN configuration should reference the [nexus node](https://docs.zephyrproject.org/2.3.0/guides/porting/shields.html#gpio-nexus-nodes) that ZMK has standardized on. In particular, the `&pro_micro_a` and `&pro_micro_d` aliases can be used to reference the standard `A#` and `D#` pins in shields.
|
||||||
|
- (Optional) A [chosen](https://docs.zephyrproject.org/2.3.0/guides/dts/intro.html#aliases-and-chosen-nodes) node named `zmk,matrix_transform` that defines the mapping from KSCAN row/column values to the logical key position for the keyboard.
|
||||||
|
- A `keymap/keymap.overlay` file that includes the default keymap for that keyboard. Users will be able to override this keymap in their user configs.
|
128
zmk/docs/docs/development/build-flash.md
Normal file
128
zmk/docs/docs/development/build-flash.md
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
---
|
||||||
|
title: Building and Flashing
|
||||||
|
sidebar_label: Building and Flashing
|
||||||
|
---
|
||||||
|
|
||||||
|
import Tabs from '@theme/Tabs';
|
||||||
|
import TabItem from '@theme/TabItem';
|
||||||
|
|
||||||
|
export const OsTabs = (props) => (<Tabs
|
||||||
|
groupId="operating-systems"
|
||||||
|
defaultValue="debian"
|
||||||
|
values={[
|
||||||
|
{label: 'Debian/Ubuntu', value: 'debian'},
|
||||||
|
{label: 'Raspberry OS', value: 'raspberryos'},
|
||||||
|
{label: 'Fedora', value: 'fedora'},
|
||||||
|
{label: 'Windows', value: 'win'},
|
||||||
|
{label: 'macOS', value: 'mac'},
|
||||||
|
]
|
||||||
|
}>{props.children}</Tabs>);
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
From here on, building and flashing ZMK should all be done from the `app/` subdirectory of the ZMK checkout:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd app
|
||||||
|
```
|
||||||
|
|
||||||
|
To build for your particular keyboard, the behaviour varies slightly depending on if you are building for a keyboard with
|
||||||
|
an onboard MCU, or one that uses an MCU board addon.
|
||||||
|
|
||||||
|
### Keyboard (Shield) + MCU Board
|
||||||
|
|
||||||
|
ZMK treats keyboards that take an MCU addon board as [shields](https://docs.zephyrproject.org/2.3.0/guides/porting/shields.html), and treats the smaller MCU board as the true [board](https://docs.zephyrproject.org/2.3.0/guides/porting/board_porting.html)
|
||||||
|
|
||||||
|
Given the following:
|
||||||
|
|
||||||
|
- MCU Board: Proton-C
|
||||||
|
- Keyboard PCB: kyria_left
|
||||||
|
- Keymap: default
|
||||||
|
|
||||||
|
You can build ZMK with the following:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
west build -b proton_c -- -DSHIELD=kyria_left
|
||||||
|
```
|
||||||
|
|
||||||
|
### Keyboard With Onboard MCU
|
||||||
|
|
||||||
|
Keyboards with onboard MCU chips are simply treated as the [board](https://docs.zephyrproject.org/2.3.0/guides/porting/board_porting.html) as far as Zephyr™ is concerned.
|
||||||
|
|
||||||
|
Given the following:
|
||||||
|
|
||||||
|
- Keyboard: Planck (rev6)
|
||||||
|
- Keymap: default
|
||||||
|
|
||||||
|
you can build ZMK with the following:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
west build -b planck_rev6
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pristine Building
|
||||||
|
|
||||||
|
When building for a new board and/or shield after having built one previously, you may need to enable the pristine build option. This option removes all existing files in the build directory before regenerating them, and can be enabled by adding either --pristine or -p to the command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
west build -p -b proton_c -- -DSHIELD=kyria_left
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building For Split Keyboards
|
||||||
|
|
||||||
|
:::note
|
||||||
|
For split keyboards, you will have to build and flash each side separately the first time you install ZMK.
|
||||||
|
:::
|
||||||
|
|
||||||
|
By default, the `build` command outputs a single .uf2 file named `zmk.uf2` so building left and then right immediately after will overwrite your left firmware. In addition, you will need to pristine build each side to ensure the correct files are used. To avoid having to pristine build every time and separate the left and right build files, we recommend setting up separate build directories for each half. You can do this by using the `-d` parameter and first building left into `build/left`:
|
||||||
|
|
||||||
|
```
|
||||||
|
west build -d build/left -b nice_nano -- -DSHIELD=kyria_left
|
||||||
|
```
|
||||||
|
|
||||||
|
and then building right into `build/right`:
|
||||||
|
|
||||||
|
```
|
||||||
|
west build -d build/right -b nice_nano -- -DSHIELD=kyria_right
|
||||||
|
```
|
||||||
|
|
||||||
|
This produces `left` and `right` subfolders under the `build` directory and two separate .uf2 files. For future work on a specific half, use the `-d` parameter again to ensure you are building into the correct location.
|
||||||
|
|
||||||
|
### Building from `zmk-config` Folder
|
||||||
|
|
||||||
|
Instead of building .uf2 files using the default keymap and config files, you can build directly from your [`zmk-config` folder](../user-setup#github-repo) by adding
|
||||||
|
`-DZMK_CONFIG="C:/the/absolute/path/config"` to your `west build` command. **Notice that this path should point to the folder labelled `config` within your `zmk-config` folder.**
|
||||||
|
|
||||||
|
For instance, building kyria firmware from a user `myUser`'s `zmk-config` folder on Windows 10 may look something like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
west build -b nice_nano -- -DSHIELD=kyria_left -DZMK_CONFIG="C:/Users/myUser/Documents/Github/zmk-config/config"
|
||||||
|
```
|
||||||
|
|
||||||
|
In order to make your `zmk-config` folder available when building within the VSCode Remote Container, you need to create a docker volume named `zmk-config`
|
||||||
|
by binding it to the full path of your config directory. If you have run the VSCode Remote Container before, it is likely that docker has created this
|
||||||
|
volume automatically -- we need to delete the default volume before binding it to the correct path. Follow the following steps:
|
||||||
|
|
||||||
|
1. Stop the container by exiting VSCode. You can verify no container is running via the command `docker ps`.
|
||||||
|
1. Remove all the containers that are not running via the command `docker container prune`. We need to remove the ZMK container before we can delete the default `zmk-config` volume referenced by it. If you do not want to delete all the containers that are not running, you can find the id of the ZMK container and use `docker rm` to delete that one only.
|
||||||
|
1. Remove the default volume via the command `docker volume rm zmk-config`.
|
||||||
|
|
||||||
|
Then you can bind the `zmk-config` volume to the correct path pointing to your local [zmk-config](./customization.md) folder:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker volume create --driver local -o o=bind -o type=none -o \
|
||||||
|
device="/full/path/to/your/zmk-config/" zmk-config
|
||||||
|
```
|
||||||
|
|
||||||
|
Now start VSCode and rebuild the container after being prompted. You should be able to see your zmk-config mounted to `/workspaces/zmk-config` inside the container. So you can build your custom firmware with `-DZMK_CONFIG="/workspaces/zmk-config/config"`.
|
||||||
|
|
||||||
|
## Flashing
|
||||||
|
|
||||||
|
Once built, the previously supplied parameters will be remembered so you can run the following to flash your
|
||||||
|
board with it in bootloader mode:
|
||||||
|
|
||||||
|
```
|
||||||
|
west flash
|
||||||
|
```
|
||||||
|
|
||||||
|
For boards that have drag and drop .uf2 flashing capability, the .uf2 file to flash can be found in `build/zephyr` (or `build/left|right/zephyr` if you followed the instructions for splits) and is by default named `zmk.uf2`.
|
28
zmk/docs/docs/development/clean-room.md
Normal file
28
zmk/docs/docs/development/clean-room.md
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
---
|
||||||
|
title: Clean Room Implementation
|
||||||
|
sidebar_label: Clean Room
|
||||||
|
---
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
|
||||||
|
Anyone wanting to contribute code to ZMK _MUST_ read this, and adhere to the steps outlines in order to not violate any licenses/copyright of other projects
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
ZMK Firmware is a [clean room design](https://en.wikipedia.org/wiki/Clean_room_design) keyboard firmware, that
|
||||||
|
borrows/implements a lot of the features found in popular keyboard firmwares projects like [QMK](https://qmk.fm)
|
||||||
|
and [TMK](https://github.com/tmk/tmk_keyboard). However, in order for ZMK to use the MIT, it _must_ not
|
||||||
|
incorporate any of the GPL licensed code from those projects.
|
||||||
|
|
||||||
|
In order to achieve this, all code for ZMK has been implemented completely fresh, _without_ referencing, copying,
|
||||||
|
or duplicating any of the GPL code found in those other projects, even though they are open source software.
|
||||||
|
|
||||||
|
## Contributor Requirements
|
||||||
|
|
||||||
|
Contributors to ZMK must adhere to the following standard.
|
||||||
|
|
||||||
|
- Implementations of features for ZMK _MUST NOT_ reuse any existing code from any projects not licensed with the MIT license.
|
||||||
|
- Contributors _MUST NOT_ study or refer to any GPL licensed source code while working on ZMK.
|
||||||
|
- Contributors _MAY_ read the documentation from other GPL licensed projects, to gain a broad understanding of the behavior of certain features in order to implement equivalent features for ZMK.
|
||||||
|
- Contributors _MAY_ refer to the [QMK Configurator](https://config.qmk.fm/) to inspect existing layouts/keymaps for
|
||||||
|
keyboards, and re-implement them for ZMK.
|
512
zmk/docs/docs/development/new-shield.md
Normal file
512
zmk/docs/docs/development/new-shield.md
Normal file
|
@ -0,0 +1,512 @@
|
||||||
|
---
|
||||||
|
title: New Keyboard Shield
|
||||||
|
---
|
||||||
|
|
||||||
|
import Tabs from '@theme/Tabs';
|
||||||
|
import TabItem from '@theme/TabItem';
|
||||||
|
import KeymapExampleFile from '../keymap-example-file.md';
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This guide will walk through the steps necessary to add ZMK support for a keyboard the uses a (Pro Micro compatible) addon MCU board to provide the microprocessor.
|
||||||
|
The high level steps are:
|
||||||
|
|
||||||
|
- Create a new shield directory.
|
||||||
|
- Add the base Kconfig files.
|
||||||
|
- Add the shield overlay file to define the KSCAN driver for detecting key press/release.
|
||||||
|
- (Optional) Add the matrix transform for mapping KSCAN row/column values to sane key positions. This is needed for non-rectangular keyboards, or where the underlying row/column pin arrangement does not map one to one with logical locations on the keyboard.
|
||||||
|
- Add a default keymap, which users can override in their own configs as needed.
|
||||||
|
- Add support for features such as encoders, OLED displays, or RGB underglow.
|
||||||
|
- Update build.yml
|
||||||
|
|
||||||
|
It may be helpful to review the upstream [shields documentation](https://docs.zephyrproject.org/2.3.0/guides/porting/shields.html#shields) to get a proper understanding of the underlying system before continuing.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
ZMK support for split keyboards requires a few more files than single boards to ensure proper connectivity between the central and peripheral units. Check the following guides thoroughly to ensure that all the files are in place.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## New Shield Directory
|
||||||
|
|
||||||
|
:::note
|
||||||
|
This guide describes how to add shield to the ZMK main repository. If you are building firmware for your
|
||||||
|
own prototype or handwired keyboard, it is recommended to use your own user config repository. Follow the
|
||||||
|
[user setup guide](./user-setup.md) to create your user config repository first. When following the rest
|
||||||
|
of this guide, replace the `app/` directory in the ZMK main repository with the `config/` directory in your
|
||||||
|
user config repository. For example, `app/boards/shields/<keyboard_name>` should now be
|
||||||
|
`config/boards/shields/<keyboard_name>`.
|
||||||
|
:::
|
||||||
|
|
||||||
|
Shields for Zephyr applications go into the `boards/shields/` directory; since ZMK's Zephyr application lives in the `app/` subdirectory of the repository, that means the new shield directory should be:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir app/boards/shields/<keyboard_name>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Base Kconfig Files
|
||||||
|
|
||||||
|
There are two required Kconfig files that need to be created for your new keyboard
|
||||||
|
shield to get it picked up for ZMK, `Kconfig.shield` and `Kconfig.defconfig`.
|
||||||
|
|
||||||
|
### Kconfig.shield
|
||||||
|
|
||||||
|
The `Kconfig.shield` file defines any additional Kconfig settings that may be relevant when using this keyboard. For most keyboards, there is just one additional configuration value for the shield itself, e.g.:
|
||||||
|
|
||||||
|
```
|
||||||
|
config SHIELD_MY_BOARD
|
||||||
|
def_bool $(shields_list_contains,my_board)
|
||||||
|
```
|
||||||
|
|
||||||
|
This will make sure the new configuration `SHIELD_MY_BOARD` is set to true whenever `my_board` is added as a shield in your build.
|
||||||
|
|
||||||
|
**For split boards**, you will need to add configurations for the left and right sides.
|
||||||
|
|
||||||
|
```
|
||||||
|
config SHIELD_MY_BOARD_LEFT
|
||||||
|
def_bool $(shields_list_contains,my_board_left)
|
||||||
|
|
||||||
|
config SHIELD_MY_BOARD_RIGHT
|
||||||
|
def_bool $(shields_list_contains,my_board_right)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Kconfig.defconfig
|
||||||
|
|
||||||
|
The `Kconfig.defconfig` file is where overrides for various configuration settings
|
||||||
|
that make sense to have different defaults when this shield is used. One main item
|
||||||
|
that usually has a new default value set here is the `ZMK_KEYBOARD_NAME` value,
|
||||||
|
which controls the display name of the device over USB and BLE.
|
||||||
|
|
||||||
|
The updated new default values should always be wrapped inside a conditional on the shield config name defined in the `Kconfig.shield` file. Here's the simplest example file.
|
||||||
|
|
||||||
|
:::warning
|
||||||
|
Do not make the keyboard name too long, otherwise the bluetooth advertising might fail and you will not be able to find your keyboard from your laptop / tablet.
|
||||||
|
:::
|
||||||
|
|
||||||
|
```
|
||||||
|
if SHIELD_MY_BOARD
|
||||||
|
|
||||||
|
config ZMK_KEYBOARD_NAME
|
||||||
|
default "My Awesome Keyboard"
|
||||||
|
|
||||||
|
endif
|
||||||
|
```
|
||||||
|
|
||||||
|
Similarly to defining the halves of a split board in `Kconfig.shield` it is important to set the `ZMK_KEYBOARD_NAME` for each half of a split keyboard.
|
||||||
|
|
||||||
|
```
|
||||||
|
if SHIELD_MY_BOARD_LEFT
|
||||||
|
|
||||||
|
config ZMK_KEYBOARD_NAME
|
||||||
|
default "My Awesome Keyboard Left"
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
if SHIELD_MY_BOARD_RIGHT
|
||||||
|
|
||||||
|
config ZMK_KEYBOARD_NAME
|
||||||
|
default "My Awesome Keyboard Right"
|
||||||
|
|
||||||
|
endif
|
||||||
|
```
|
||||||
|
|
||||||
|
## Shield Overlays
|
||||||
|
|
||||||
|
![Labelled Pro Micro pins](../assets/pro-micro/pro-micro-pins-labelled.jpg)
|
||||||
|
|
||||||
|
ZMK uses the green color coded pin names to generate devicetree node references. For example, to refer to the node `D0` in the devicetree files, use `&pro_micro_d 0` or to refer to `A1`, use `&pro_micro_a 1`.
|
||||||
|
|
||||||
|
<Tabs
|
||||||
|
defaultValue="unibody"
|
||||||
|
values={[
|
||||||
|
{label: 'Unibody Shields', value: 'unibody'},
|
||||||
|
{label: 'Split Shields', value: 'split'},
|
||||||
|
]}>
|
||||||
|
|
||||||
|
<TabItem value="unibody">
|
||||||
|
|
||||||
|
The `<shield_name>.overlay` is the devicetree description of the keyboard shield that is merged with the primary board devicetree description before the build. For ZMK, this file at a minimum should include the chosen node named `zmk,kscan` that references a KSCAN driver instance. For a simple 3x3 macropad matrix,
|
||||||
|
this might look something like:
|
||||||
|
|
||||||
|
```
|
||||||
|
/ {
|
||||||
|
chosen {
|
||||||
|
zmk,kscan = &kscan0;
|
||||||
|
};
|
||||||
|
|
||||||
|
kscan0: kscan_0 {
|
||||||
|
compatible = "zmk,kscan-gpio-matrix";
|
||||||
|
label = "KSCAN";
|
||||||
|
diode-direction = "col2row";
|
||||||
|
|
||||||
|
col-gpios
|
||||||
|
= <&pro_micro_d 15 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_d 14 GPIO_ACTIVE_HIGH>
|
||||||
|
, <&pro_micro_d 16 GPIO_ACTIVE_HIGH>
|
||||||
|
;
|
||||||
|
|
||||||
|
row-gpios
|
||||||
|
= <&pro_micro_a 1 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||||
|
, <&pro_micro_a 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||||
|
, <&pro_micro_a 3 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||||
|
;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
|
||||||
|
<TabItem value="split">
|
||||||
|
|
||||||
|
### .dtsi files and Shield Overlays (Split Shields)
|
||||||
|
|
||||||
|
Unlike unibody keyboards, split keyboards have a core .dtsi file with shield overlays for each half of the keyboard.
|
||||||
|
It is preferred to define only the `col-gpios` or `row-gpios` in the common shield .dtsi, depending on the `diode-direction` value.
|
||||||
|
For `col2row` directed boards like the iris, the shared .dtsi file may look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
#include <dt-bindings/zmk/matrix-transform.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
chosen {
|
||||||
|
zmk,kscan = &kscan0;
|
||||||
|
zmk,matrix_transform = &default_transform;
|
||||||
|
};
|
||||||
|
|
||||||
|
default_transform: keymap_transform_0 {
|
||||||
|
compatible = "zmk,matrix-transform";
|
||||||
|
columns = <16>;
|
||||||
|
rows = <4>;
|
||||||
|
// | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 | | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 |
|
||||||
|
// | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 | | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 |
|
||||||
|
// | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 | | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 |
|
||||||
|
// | SW24 | SW23 | SW22 | SW21 | SW20 | SW19 | SW25 | | SW25 | SW19 | SW20 | SW21 | SW22 | SW23 | SW24 |
|
||||||
|
// | SW29 | SW28 | SW27 | SW26 | | SW26 | SW27 | SW28 | SW29 |
|
||||||
|
map = <
|
||||||
|
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10) RC(0,11)
|
||||||
|
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10) RC(1,11)
|
||||||
|
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) RC(2,10) RC(2,11)
|
||||||
|
RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(4,2) RC(4,9) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11)
|
||||||
|
RC(4,3) RC(4,4) RC(4,5) RC(4,6) RC(4,7) RC(4,8)
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
kscan0: kscan {
|
||||||
|
compatible = "zmk,kscan-gpio-matrix";
|
||||||
|
label = "KSCAN";
|
||||||
|
|
||||||
|
diode-direction = "col2row";
|
||||||
|
row-gpios
|
||||||
|
= <&pro_micro_d 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // Row A from the schematic file
|
||||||
|
, <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // Row B from the schematic file
|
||||||
|
, <&pro_micro_d 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // Row C from the schematic file
|
||||||
|
, <&pro_micro_d 0 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // Row D from the schematic file
|
||||||
|
, <&pro_micro_d 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // Row E from the schematic file
|
||||||
|
;
|
||||||
|
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Notice that in addition to the common `row-gpios` that are declared in the kscan, the [matrix transform](#optional-matrix-transform) is defined in the .dtsi.
|
||||||
|
:::
|
||||||
|
|
||||||
|
The missing `col-gpios` would be defined in your `<boardname>_left.overlay` and `<boardname>_right.overlay` files.
|
||||||
|
Keep in mind that the mirrored position of the GPIOs means that the `col-gpios` will appear reversed when the .overlay files are compared to one another.
|
||||||
|
Furthermore, the column offset for the [matrix transform](#optional-matrix-transform) should be added to the right half of the keyboard's overlay
|
||||||
|
because the keyboard's switch matrix is read from left to right, top to bottom.
|
||||||
|
This is exemplified with the iris .overlay files.
|
||||||
|
|
||||||
|
```
|
||||||
|
// iris_left.overlay
|
||||||
|
|
||||||
|
#include "iris.dtsi" // Notice that the main dtsi files are included in the overlay.
|
||||||
|
|
||||||
|
&kscan0 {
|
||||||
|
col-gpios
|
||||||
|
= <&pro_micro_a 1 GPIO_ACTIVE_HIGH> // col1 in the schematic
|
||||||
|
, <&pro_micro_a 0 GPIO_ACTIVE_HIGH> // col2 in the schematic
|
||||||
|
, <&pro_micro_d 15 GPIO_ACTIVE_HIGH> // col3 in the schematic
|
||||||
|
, <&pro_micro_d 14 GPIO_ACTIVE_HIGH> // col4 in the schematic
|
||||||
|
, <&pro_micro_d 16 GPIO_ACTIVE_HIGH> // col5 in the schematic
|
||||||
|
, <&pro_micro_d 10 GPIO_ACTIVE_HIGH> // col6 in the schematic
|
||||||
|
;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
// iris_right.overlay
|
||||||
|
|
||||||
|
#include "iris.dtsi"
|
||||||
|
|
||||||
|
&default_transform { // The matrix transform for this board is 6 columns over because the left half is 6 columns wide according to the matrix.
|
||||||
|
col-offset = <6>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&kscan0 {
|
||||||
|
col-gpios
|
||||||
|
= <&pro_micro_d 10 GPIO_ACTIVE_HIGH> // col6 in the schematic
|
||||||
|
, <&pro_micro_d 16 GPIO_ACTIVE_HIGH> // col5 in the schematic
|
||||||
|
, <&pro_micro_d 14 GPIO_ACTIVE_HIGH> // col4 in the schematic
|
||||||
|
, <&pro_micro_d 15 GPIO_ACTIVE_HIGH> // col3 in the schematic
|
||||||
|
, <&pro_micro_a 0 GPIO_ACTIVE_HIGH> // col2 in the schematic
|
||||||
|
, <&pro_micro_a 1 GPIO_ACTIVE_HIGH> // col1 in the schematic
|
||||||
|
;
|
||||||
|
};
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### .conf files (Split Shields)
|
||||||
|
|
||||||
|
While unibody boards only have one .conf file that applies configuration characteristics to the entire keyboard,
|
||||||
|
split keyboards are unique in that they contain multiple .conf files with different scopes.
|
||||||
|
For example, a split board called `my_awesome_split_board` would have the following files:
|
||||||
|
|
||||||
|
- `my_awesome_split_board.conf` - Configuration elements affect both halves
|
||||||
|
- `my_awesome_split_board_left.conf` - Configuration elements only affect left half
|
||||||
|
- `my_awesome_split_board_right.conf` - Configuration elements only affect right half
|
||||||
|
|
||||||
|
For proper communication between keyboard halves and that between the central half and the computer,
|
||||||
|
the **the central and peripheral halves of the keyboard must be defined**. This can be seen below.
|
||||||
|
|
||||||
|
```
|
||||||
|
// Central Half (Usually the left side: my_awesome_split_board_left.conf)
|
||||||
|
|
||||||
|
CONFIG_ZMK_SPLIT=y
|
||||||
|
CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
// Peripheral Half (Usually the right side: my_awesome_split_board_right.conf)
|
||||||
|
|
||||||
|
CONFIG_ZMK_SPLIT=y
|
||||||
|
CONFIG_ZMK_SPLIT_BLE_ROLE_Peripheral=y
|
||||||
|
```
|
||||||
|
|
||||||
|
Using the .conf file that affects both halves of a split board would be for adding features like deep-sleep or rotary encoders.
|
||||||
|
|
||||||
|
```
|
||||||
|
// my_awesome_split_board.conf
|
||||||
|
|
||||||
|
CONFIG_ZMK_SLEEP=y
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
## (Optional) Matrix Transform
|
||||||
|
|
||||||
|
Internally ZMK translates all row/column events into "key position" events to maintain a consistent model that works no matter what any possible GPIO matrix may look like for a certain keyboard. This is particularly helpful when:
|
||||||
|
|
||||||
|
1. To reduce the used pins, an "efficient" number of rows/columns for the GPIO matrix is used, that does _not_ match the physical layout of rows/columns of the actual key switches.
|
||||||
|
1. For non rectangular keyboards with thumb clusters, non `1u` locations, etc.
|
||||||
|
|
||||||
|
A "key position" is the numeric index (zero-based) of a given key, which identifies
|
||||||
|
the logical key location as perceived by the end user. All _keymap_ mappings actually bind behaviors to _key positions_, not to row/column values.
|
||||||
|
|
||||||
|
_Without_ a matrix transform, that intentionally map each key position to the row/column pair that position corresponds to, the default equation to determine that is:
|
||||||
|
|
||||||
|
```
|
||||||
|
($row * NUMBER_OF_COLUMNS) + $column
|
||||||
|
```
|
||||||
|
|
||||||
|
Which effectively amounts to numbering the key positions by traversing each row from top to bottom and assigning numerically incrementing key positions.
|
||||||
|
|
||||||
|
Whenever that default key position mapping is insufficient, the `<shield_name>.overlay` file should _also_ include a matrix transform.
|
||||||
|
|
||||||
|
Here is an example for the [nice60](https://github.com/Nicell/nice60), which uses an efficient 8x8 GPIO matrix, and uses a transform:
|
||||||
|
|
||||||
|
```
|
||||||
|
#include <dt-bindings/zmk/matrix-transform.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
chosen {
|
||||||
|
zmk,kscan = &kscan0;
|
||||||
|
zmk,matrix_transform = &default_transform;
|
||||||
|
};
|
||||||
|
|
||||||
|
default_transform: keymap_transform_0 {
|
||||||
|
compatible = "zmk,matrix-transform";
|
||||||
|
columns = <8>;
|
||||||
|
rows = <8>;
|
||||||
|
// | MX1 | MX2 | MX3 | MX4 | MX5 | MX6 | MX7 | MX8 | MX9 | MX10 | MX11 | MX12 | MX13 | MX14 |
|
||||||
|
// | MX15 | MX16 | MX17 | MX18 | MX19 | MX20 | MX21 | MX22 | MX23 | MX34 | MX25 | MX26 | MX27 | MX28 |
|
||||||
|
// | MX29 | MX30 | MX31 | MX32 | MX33 | MX34 | MX35 | MX36 | MX37 | MX38 | MX39 | MX40 | MX41 |
|
||||||
|
// | MX42 | MX43 | MX44 | MX45 | MX46 | MX47 | MX48 | MX49 | MX50 | MX51 | MX52 | MX53 |
|
||||||
|
// | MX54 | MX55 | MX56 | MX57 | MX58 | MX59 | MX60 | MX61 |
|
||||||
|
map = <
|
||||||
|
RC(3,0) RC(2,0) RC(1,0) RC(0,0) RC(1,1) RC(0,1) RC(0,2) RC(1,3) RC(0,3) RC(1,4) RC(0,4) RC(0,5) RC(1,6) RC(1,7)
|
||||||
|
RC(4,0) RC(4,1) RC(3,1) RC(2,1) RC(2,2) RC(1,2) RC(2,3) RC(3,4) RC(2,4) RC(2,5) RC(1,5) RC(2,6) RC(2,7) RC(3,7)
|
||||||
|
RC(5,0) RC(5,1) RC(5,2) RC(4,2) RC(3,2) RC(4,3) RC(3,3) RC(4,4) RC(4,5) RC(3,5) RC(4,6) RC(3,6) RC(4,7)
|
||||||
|
RC(6,0) RC(6,1) RC(6,2) RC(6,3) RC(5,3) RC(6,4) RC(5,4) RC(6,5) RC(5,5) RC(6,6) RC(5,6) RC(5,7)
|
||||||
|
RC(7,0) RC(7,1) RC(7,2) RC(7,3) RC(7,5) RC(7,6) RC(6,7) RC(7,7)
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Some important things to note:
|
||||||
|
|
||||||
|
- The `#include <dt-bindings/zmk/matrix-transform.h>` is critical. The `RC` macro is used to generate the internal storage in the matrix transform, and is actually replaced by a C preprocessor before the final devicetree is compiled into ZMK.
|
||||||
|
- `RC(row, column)` is placed sequentially to define what row and column values that position corresponds to.
|
||||||
|
- If you have a keyboard with options for `2u` keys in certain positions, or break away portions, it is a good idea to set the chosen `zmk,matrix_transform` to the default arrangement, and include _other_ possible matrix transform nodes in the devicetree that users can select in their user config by overriding the chosen node.
|
||||||
|
|
||||||
|
## Default Keymap
|
||||||
|
|
||||||
|
Each keyboard should provide an OOTB default keymap to be used when building the firmware, which can be overridden and customized by user configs. For "shield keyboards", this should be placed in the `app/boards/shields/<shield_name>/<shield_name>.keymap` file. The keymap is configured as an additional devicetree overlay that includes the following:
|
||||||
|
|
||||||
|
- A node with `compatible="zmk,keymap"` where each child node is a layer with a `bindings` array that binds each key position to a given behavior (e.g. key press, momentarily layer, etc).
|
||||||
|
|
||||||
|
Here is an example simple keymap for the Kyria, with only one layer:
|
||||||
|
|
||||||
|
<KeymapExampleFile/>
|
||||||
|
|
||||||
|
:::note
|
||||||
|
The two `#include` lines at the top of the keymap are required in order to bring in the default set of behaviors to make them available to bind, and to import a set of defines for the key codes, so keymaps can use parameters like `N2` or `K` instead of the raw keycode numeric values.
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Keymap Behaviors
|
||||||
|
|
||||||
|
Further documentation on behaviors and bindings is forthcoming, but a summary of the current behaviors you can bind to key positions is as follows:
|
||||||
|
|
||||||
|
- `kp` is the "key press" behavior, and takes a single binding argument of the key code from the 'keyboard/keypad" HID usage table.
|
||||||
|
- `mo` is the "momentary layer" behaviour, and takes a single binding argument of the numeric ID of the layer to momentarily enable when that key is held.
|
||||||
|
- `trans` is the "transparent" behavior, useful to be place in higher layers above `mo` bindings to be sure the key release is handled by the lower layer. No binding arguments are required.
|
||||||
|
- `mt` is the "mod-tap" behavior, and takes two binding arguments, the modifier to use if held, and the keycode to send if tapped.
|
||||||
|
|
||||||
|
## Adding Features
|
||||||
|
|
||||||
|
### Encoders
|
||||||
|
|
||||||
|
EC11 encoder support can be added to your board or shield by adding the appropriate lines to your board/shield's configuration (.conf), device tree (.dtsi), overlay (.overlay), and keymap (.keymap) files.
|
||||||
|
|
||||||
|
<Tabs
|
||||||
|
defaultValue="conf"
|
||||||
|
values={[
|
||||||
|
{label: '.conf', value: 'conf'},
|
||||||
|
{label: '.dtsi', value: 'dtsi'},
|
||||||
|
{label: '.overlay', value: 'overlay'},
|
||||||
|
{label: '.keymap', value: 'keymap'},
|
||||||
|
]}>
|
||||||
|
<TabItem value="conf">
|
||||||
|
|
||||||
|
In your configuration file you will need to add the following lines so that the encoders can be enabled/disabled:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Uncomment to enable encoder
|
||||||
|
# CONFIG_EC11=y
|
||||||
|
# CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y
|
||||||
|
```
|
||||||
|
|
||||||
|
These should be commented by default for encoders that are optional/can be swapped with switches, but can be uncommented if encoders are part of the default design.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
If building locally for split boards, you may need to add these lines to the specific half's configuration file as well as the combined configuration file.
|
||||||
|
:::
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value = "dtsi">
|
||||||
|
In your device tree file you will need to add the following lines to define the encoder sensor:
|
||||||
|
|
||||||
|
```
|
||||||
|
left_encoder: encoder_left {
|
||||||
|
compatible = "alps,ec11";
|
||||||
|
label = "LEFT_ENCODER";
|
||||||
|
a-gpios = <PIN_A (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
|
||||||
|
b-gpios = <PIN_B (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
|
||||||
|
resolution = <4>;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Here you will have to replace PIN_A and PIN_B with the appropriate pins that your PCB utilizes for the encoder(s). For keyboards that use the Pro Micro or any of the Pro Micro replacements, Sparkfun's [Pro Micro Hookup Guide](https://learn.sparkfun.com/tutorials/pro-micro--fio-v3-hookup-guide/hardware-overview-pro-micro) has a pinout diagram that can be useful to determine the right pins. Reference either the blue numbers labeled "Arduino" (digital pins) or the green numbers labeled "Analog" (analog pins). For pins that are labeled as both digital and analog, refer to your specific board's .dtsi file to determine how you should refer to that pin.
|
||||||
|
|
||||||
|
Add additional encoders as necessary by duplicating the above lines, replacing `left` with whatever you would like to call your encoder, and updating the pins. Note that support for peripheral (right) side sensors over BLE is still in progress.
|
||||||
|
|
||||||
|
Once you have defined the encoder sensors, you will have to add them to the list of sensors:
|
||||||
|
|
||||||
|
```
|
||||||
|
sensors {
|
||||||
|
compatible = "zmk,keymap-sensors";
|
||||||
|
sensors = <&left_encoder &right_encoder>;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, a left_encoder and right_encoder are both added. Additional encoders can be added with spaces separating each, and the order they are added here determines the order in which you define their behavior in your keymap.
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value = "overlay">
|
||||||
|
Add the following lines to your overlay file(s) to enable the encoder:
|
||||||
|
|
||||||
|
```
|
||||||
|
&left_encoder {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
For split keyboards, make sure to add left hand encoders to the left .overlay file and right hand encoders to the right .overlay file.
|
||||||
|
:::
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value = "keymap">
|
||||||
|
Add the following line to your keymap file to add default encoder behavior bindings:
|
||||||
|
|
||||||
|
```
|
||||||
|
sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>;
|
||||||
|
```
|
||||||
|
|
||||||
|
Add additional bindings as necessary to match the default number of encoders on your board. See the [Encoders](/docs/features/encoders) and [Keymap](/docs/features/keymaps) feature documentation for more details.
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Once you've fully created the new keyboard shield definition,
|
||||||
|
you should be able to test with a build command like:
|
||||||
|
|
||||||
|
```
|
||||||
|
west build --pristine -b proton_c -- -DSHIELD=my_board
|
||||||
|
```
|
||||||
|
|
||||||
|
and then flash with:
|
||||||
|
|
||||||
|
```
|
||||||
|
west flash
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Further testing your keyboard shield without altering the root keymap file can be done with the use of `-DZMK_CONFIG` in your `west build` command,
|
||||||
|
shown [here](build-flash#building-from-zmk-config-folder)
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Updating `build.yml`
|
||||||
|
|
||||||
|
Before publishing your shield to the public via a PR, navigate to `build.yml` found in `.github/workflows` and add your shield to the appropriate list. An example edit to `build.yml` is shown below.
|
||||||
|
|
||||||
|
```
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Build Test
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
board: [proton_c, nice_nano, bluemicro840_v1, nrfmicro_13]
|
||||||
|
shield:
|
||||||
|
- corne_left
|
||||||
|
- corne_right
|
||||||
|
- kyria_left
|
||||||
|
- kyria_right
|
||||||
|
- lily58_left
|
||||||
|
- lily58_right
|
||||||
|
- iris_left
|
||||||
|
- iris_right
|
||||||
|
- romac
|
||||||
|
- <MY_BOARD>
|
||||||
|
- <MY_SPLIT_BOARD_left>
|
||||||
|
- <MY_SPLIT_BOARD_right>
|
||||||
|
include:
|
||||||
|
- board: proton_c
|
||||||
|
shield: clueboard_california
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Notice that both the left and right halves of a split board need to be added to the list of shields for proper error checking.
|
||||||
|
:::note
|
38
zmk/docs/docs/development/posix-board.md
Normal file
38
zmk/docs/docs/development/posix-board.md
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
title: Native Posix board target
|
||||||
|
---
|
||||||
|
|
||||||
|
In order to iterate quickly on firmware features, it can
|
||||||
|
be helpful to build and run the firmware on your local
|
||||||
|
workstation, with generated virtual press/release events
|
||||||
|
flowing into the handler functions.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
In order to build targeting the `native_posix` board, you need to setup your system
|
||||||
|
with a compiler that can target 32-bit POSIX.
|
||||||
|
|
||||||
|
On Debian, you can do this with:
|
||||||
|
|
||||||
|
```
|
||||||
|
apt install -y gcc-multilib
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
To do this, you can build ZMK targeting the
|
||||||
|
`native_posix` board.
|
||||||
|
|
||||||
|
```
|
||||||
|
west build --pristine --board native_posix
|
||||||
|
```
|
||||||
|
|
||||||
|
Once built, you can run the firmware locally:
|
||||||
|
|
||||||
|
```
|
||||||
|
./build/zephyr/zephyr.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
## Virtual Key Events
|
||||||
|
|
||||||
|
The virtual key presses are hardcoded in `boards/native_posix.overlay` file, should you want to change the sequence to test various actions like Mod-Tap, etc.
|
554
zmk/docs/docs/development/setup.md
Normal file
554
zmk/docs/docs/development/setup.md
Normal file
|
@ -0,0 +1,554 @@
|
||||||
|
---
|
||||||
|
title: Basic Setup
|
||||||
|
sidebar_label: Basic Setup
|
||||||
|
---
|
||||||
|
|
||||||
|
import Tabs from '@theme/Tabs';
|
||||||
|
import TabItem from '@theme/TabItem';
|
||||||
|
|
||||||
|
export const OsTabs = (props) => (<Tabs
|
||||||
|
groupId="operating-systems"
|
||||||
|
defaultValue="debian"
|
||||||
|
values={[
|
||||||
|
{label: 'Debian/Ubuntu', value: 'debian'},
|
||||||
|
{label: 'Windows', value: 'win'},
|
||||||
|
{label: 'macOS', value: 'mac'},
|
||||||
|
{label: 'Raspberry OS', value: 'raspberryos'},
|
||||||
|
{label: 'Fedora', value: 'fedora'},
|
||||||
|
{label: 'VS Code & Docker', value: 'docker'},
|
||||||
|
]
|
||||||
|
}>{props.children}</Tabs>);
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
ZMK requires the following base packages to first be installed:
|
||||||
|
|
||||||
|
- Git
|
||||||
|
- Python 3
|
||||||
|
- `pip`
|
||||||
|
- `wget`
|
||||||
|
- devicetree compiler
|
||||||
|
- CMake
|
||||||
|
- `dfu-util`
|
||||||
|
- Various build essentials, e.g. gcc, automake, autoconf
|
||||||
|
|
||||||
|
<OsTabs>
|
||||||
|
<TabItem value="debian">
|
||||||
|
|
||||||
|
On Debian and Ubuntu, we'll use `apt` to install our base dependencies:
|
||||||
|
|
||||||
|
First, if you haven't updated recently, or if this is a new install,
|
||||||
|
you should update to get the latest package information:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo apt update
|
||||||
|
```
|
||||||
|
|
||||||
|
With the latest package information, you can now install the base dependencies:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo apt install -y \
|
||||||
|
git \
|
||||||
|
wget \
|
||||||
|
autoconf \
|
||||||
|
automake \
|
||||||
|
build-essential \
|
||||||
|
bzip2 \
|
||||||
|
ccache \
|
||||||
|
device-tree-compiler \
|
||||||
|
dfu-util \
|
||||||
|
g++ \
|
||||||
|
gcc \
|
||||||
|
libtool \
|
||||||
|
make \
|
||||||
|
ninja-build \
|
||||||
|
cmake \
|
||||||
|
python3-dev \
|
||||||
|
python3-pip \
|
||||||
|
python3-setuptools \
|
||||||
|
xz-utils
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Ubuntu 18.04 LTS release packages a version of CMake that is too old. Please upgrade to Ubuntu 20.04 LTS
|
||||||
|
or download and install CMake version 3.13.1 or newer manually.
|
||||||
|
:::
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="raspberryos">
|
||||||
|
|
||||||
|
On Raspberry OS, we'll use `apt` to install our base dependencies:
|
||||||
|
|
||||||
|
First, if you haven't updated recently, or if this is a new install,
|
||||||
|
you should update to get the latest package information:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo apt update
|
||||||
|
```
|
||||||
|
|
||||||
|
With the latest package information, you can now install the base dependencies:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo apt install -y \
|
||||||
|
git \
|
||||||
|
wget \
|
||||||
|
autoconf \
|
||||||
|
automake \
|
||||||
|
build-essential \
|
||||||
|
bzip2 \
|
||||||
|
ccache \
|
||||||
|
device-tree-compiler \
|
||||||
|
dfu-util \
|
||||||
|
g++ \
|
||||||
|
gcc \
|
||||||
|
libtool \
|
||||||
|
make \
|
||||||
|
ninja-build \
|
||||||
|
cmake \
|
||||||
|
python3-dev \
|
||||||
|
python3-pip \
|
||||||
|
python3-setuptools \
|
||||||
|
xz-utils
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="fedora">
|
||||||
|
|
||||||
|
On Fedora, we'll use `dnf` to install our base dependencies:
|
||||||
|
|
||||||
|
#### DNF Update
|
||||||
|
|
||||||
|
First, if you haven't updated recently, or if this is a new install,
|
||||||
|
you should update to get the latest package information:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo dnf update
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Install Dependencies
|
||||||
|
|
||||||
|
With the latest package information, you can now install the base dependencies:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo dnf install -y \
|
||||||
|
git \
|
||||||
|
wget \
|
||||||
|
autoconf \
|
||||||
|
automake \
|
||||||
|
bzip2 \
|
||||||
|
ccache \
|
||||||
|
dtc \
|
||||||
|
dfu-util \
|
||||||
|
g++ \
|
||||||
|
gcc \
|
||||||
|
libtool \
|
||||||
|
make \
|
||||||
|
ninja-build \
|
||||||
|
cmake \
|
||||||
|
python3-devel \
|
||||||
|
python3-pip \
|
||||||
|
python3-setuptools \
|
||||||
|
xz
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="win">
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Use `cmd.exe` with these instructions rather than PowerShell.
|
||||||
|
:::
|
||||||
|
|
||||||
|
Chocolatey is recommended and used for the following instructions. You can manually install each of these applications and add them to your `PATH` if you don't want to use Chocolatey.
|
||||||
|
|
||||||
|
1. [Install Chocolatey](https://chocolatey.org/install)
|
||||||
|
2. Open `cmd.exe` as **Administrator**
|
||||||
|
3. Run the following `choco` commands:
|
||||||
|
```shell
|
||||||
|
choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System'
|
||||||
|
choco install ninja gperf python git
|
||||||
|
```
|
||||||
|
|
||||||
|
It is recommended to install `dfu-util` to avoid any later confusion while flashing devices. You can do this by running this command with chocolatey:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
choco install dfu-util
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="mac">
|
||||||
|
|
||||||
|
#### Homebrew
|
||||||
|
|
||||||
|
Homebrew is required to install the system dependencies. If you haven't done so, visit [Homebrew](https://brew.sh/) for instructions. Once installed, use it to install the base dependencies:
|
||||||
|
|
||||||
|
```
|
||||||
|
brew install cmake ninja python3 ccache dtc git wget dfu-util
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="docker">
|
||||||
|
|
||||||
|
This setup leverages the same [image which is used by the GitHub action](https://github.com/zmkfirmware/zephyr-west-action) for local development. Beyond the benefits of [dev/prod parity](https://12factor.net/dev-prod-parity), this approach is also the easiest to set up. No toolchain or dependencies are necessary when using Docker; the container image you'll be using already has the toolchain installed and set up to use.
|
||||||
|
|
||||||
|
1. Install [Docker Desktop](https://www.docker.com/products/docker-desktop) for your operating system.
|
||||||
|
2. Install [VS Code](https://code.visualstudio.com/)
|
||||||
|
3. Install the [Remote - Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
|
||||||
|
|
||||||
|
:::info
|
||||||
|
The docker container includes `west` and the compilation toolchain. If you're using docker and VS Code, you can skip right to [Source Code](#source-code).
|
||||||
|
:::
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
</OsTabs>
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
### West Installation
|
||||||
|
|
||||||
|
`west` is the [Zephyr™ meta-tool](https://docs.zephyrproject.org/2.3.0/guides/west/index.html) used to configure and build Zephyr™ applications.
|
||||||
|
|
||||||
|
West can be installed by using the `pip` python package manager. The [Zephyr™ instructions](https://docs.zephyrproject.org/latest/guides/west/install.html#installing-west) are summarized here:
|
||||||
|
|
||||||
|
<Tabs
|
||||||
|
defaultValue="linux"
|
||||||
|
values={[
|
||||||
|
{label: 'Linux', value: 'linux'},
|
||||||
|
{label: 'Windows', value: 'win'},
|
||||||
|
]}>
|
||||||
|
<TabItem value = 'linux'>
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pip3 install --user -U west
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value = 'win'>
|
||||||
|
|
||||||
|
In `cmd.exe` as **Administrator**:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pip3 install -U west
|
||||||
|
```
|
||||||
|
|
||||||
|
:::note
|
||||||
|
**For Windows, do not use the `--user` argument** that Linux uses otherwise `west` will be installed in a different location and the below instructions for adding Python `pip` will no longer apply.
|
||||||
|
:::
|
||||||
|
|
||||||
|
Once `west` is installed, close Command Prompt and open a new session as a **user** for the remainder of the instructions.
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
:::danger `pip` user packages
|
||||||
|
If you haven't done so yet, you may need to add the Python `pip` package directory to your `PATH` otherwise your computer will not be able to find the `west` command.
|
||||||
|
:::
|
||||||
|
|
||||||
|
<Tabs
|
||||||
|
defaultValue="linux"
|
||||||
|
values={[
|
||||||
|
{label: 'Linux', value: 'linux'},
|
||||||
|
{label: 'Windows', value: 'win'},
|
||||||
|
]}>
|
||||||
|
<TabItem value = 'linux'>
|
||||||
|
Run the following commands:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
echo 'export PATH=~/.local/bin:"$PATH"' >> ~/.bashrc
|
||||||
|
source ~/.bashrc
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value = 'win'>
|
||||||
|
|
||||||
|
1. See the [Environment Variables](#environment-variables) section on how to get to the Environment Variables page.
|
||||||
|
2. Under "System variables" select the "Path" variable. Click "Edit..." and then "New" to add the directory where your `west.exe` is located. By default this should be `C:\Python##\Scripts` where ## is your Python version number.
|
||||||
|
3. Close Command Prompt and open a new session for the changes to take effect, or run `refreshenv`.
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
### Toolchain Installation
|
||||||
|
|
||||||
|
The toolchain provides the compiler, linker, etc., necessary to build for the target
|
||||||
|
platform.
|
||||||
|
|
||||||
|
<OsTabs>
|
||||||
|
<TabItem value="debian">
|
||||||
|
|
||||||
|
#### Zephyr™ ARM SDK
|
||||||
|
|
||||||
|
To build firmwares for the ARM architecture (all supported MCUs/keyboards at this point), you'll need to install the Zephyr™ ARM SDK to your system:
|
||||||
|
|
||||||
|
```
|
||||||
|
export ZSDK_VERSION=0.11.2
|
||||||
|
wget -q "https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v${ZSDK_VERSION}/zephyr-toolchain-arm-${ZSDK_VERSION}-setup.run" && \
|
||||||
|
sh "zephyr-toolchain-arm-${ZSDK_VERSION}-setup.run" --quiet -- -d ~/.local/zephyr-sdk-${ZSDK_VERSION} && \
|
||||||
|
rm "zephyr-toolchain-arm-${ZSDK_VERSION}-setup.run"
|
||||||
|
```
|
||||||
|
|
||||||
|
The installation will prompt with several questions about installation location, and creating a default `~/.zephyrrc` for you with various variables. The defaults should normally work as expected.
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="raspberryos">
|
||||||
|
|
||||||
|
Because Raspberry OS (Raspbian) runs on the same architecture (but different ABI) as the keyboard MCUs,
|
||||||
|
the operating system's installed [cross compilers](https://docs.zephyrproject.org/2.3.0/getting_started/toolchain_other_x_compilers.html) can be used to target the different ABI.
|
||||||
|
|
||||||
|
First, the cross compiler should be installed:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo apt install gcc-arm-none-eabi
|
||||||
|
```
|
||||||
|
|
||||||
|
Next, we'll configure Zephyr™ with some extra environment variables needed to find the cross compiler by adding the following to `~/.zephyrrc`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export ZEPHYR_TOOLCHAIN_VARIANT=cross-compile
|
||||||
|
export CROSS_COMPILE=/usr/bin/arm-none-eabi-
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="fedora">
|
||||||
|
|
||||||
|
#### Zephyr™ ARM SDK
|
||||||
|
|
||||||
|
To build firmwares for the ARM architecture (all supported MCUs/keyboards at this point), you'll need to install the Zephyr™ ARM SDK to your system:
|
||||||
|
|
||||||
|
```
|
||||||
|
export ZSDK_VERSION=0.11.2
|
||||||
|
wget -q "https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v${ZSDK_VERSION}/zephyr-toolchain-arm-${ZSDK_VERSION}-setup.run" && \
|
||||||
|
sh "zephyr-toolchain-arm-${ZSDK_VERSION}-setup.run" --quiet -- -d ~/.local/zephyr-sdk-${ZSDK_VERSION} && \
|
||||||
|
rm "zephyr-toolchain-arm-\${ZSDK_VERSION}-setup.run"
|
||||||
|
```
|
||||||
|
|
||||||
|
The installation will prompt with several questions about installation location, and creating a default `~/.zephyrrc` for you with various variables. The defaults should normally work as expected.
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="win">
|
||||||
|
|
||||||
|
#### GNU ARM Embedded
|
||||||
|
|
||||||
|
Since the Zephyr™ SDK is not available for Windows, we recommending following the [Zephyr documentation](https://docs.zephyrproject.org/2.3.0/getting_started/toolchain_3rd_party_x_compilers.html#gnu-arm-embedded) to install a GNU ARM Embedded build. Note the warnings regarding installing the toolchain into a path with spaces, and make sure to follow the steps to add the environment variables which are also summarized with screenshots in the [Environment Variables](#environment-variables) section below.
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="mac">
|
||||||
|
|
||||||
|
#### GNU ARM Embedded
|
||||||
|
|
||||||
|
Since the Zephyr™ SDK is not available for macOS, we recommending following the steps to install the [GNU ARM Embedded](https://docs.zephyrproject.org/2.3.0/getting_started/toolchain_3rd_party_x_compilers.html#gnu-arm-embedded).
|
||||||
|
|
||||||
|
:::warning Security Controls Workaround
|
||||||
|
|
||||||
|
Please be sure to read the [additional setup instructions](https://docs.zephyrproject.org/2.3.0/getting_started/installation_mac.html#mac-gatekeeper) needed to address security controls found in macOS 10.15 Catalina and newer
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
</OsTabs>
|
||||||
|
|
||||||
|
:::note
|
||||||
|
If you intend to build firmware straight away, make sure to correctly setup the current shell.
|
||||||
|
|
||||||
|
Notes on setting this up can be found in the [Environment Variables](#environment-variables) section.
|
||||||
|
The transient instructions can be used to setup the current shell, and the automatic instructions can setup any newly made shells automatically.
|
||||||
|
|
||||||
|
The transient instructions must be run to build firmware using the current shell.
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Source Code
|
||||||
|
|
||||||
|
Next, you'll need to clone the ZMK source repository if you haven't already. Navigate to the folder you would like to place your `zmk` directory in and run the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://github.com/zmkfirmware/zmk.git
|
||||||
|
```
|
||||||
|
|
||||||
|
### Initialize & Update Zephyr Workspace
|
||||||
|
|
||||||
|
Since ZMK is built as a Zephyr™ application, the next step is
|
||||||
|
to use `west` to initialize and update your workspace. The ZMK
|
||||||
|
Zephyr™ application is in the `app/` source directory:
|
||||||
|
|
||||||
|
#### Step into the repository
|
||||||
|
|
||||||
|
<OsTabs>
|
||||||
|
<TabItem value="debian">
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd zmk
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="raspberryos">
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd zmk
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="fedora">
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd zmk
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="mac">
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd zmk
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="win">
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd zmk
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
|
||||||
|
<TabItem value="docker">
|
||||||
|
|
||||||
|
Open the `zmk` checkout folder in VS Code. The repository includes a configuration for containerized development, so an alert will pop up:
|
||||||
|
|
||||||
|
![VS Code Dev Container Configuration Alert](../assets/dev-setup/vscode_devcontainer.png)
|
||||||
|
|
||||||
|
Click `Reopen in Container` in order to reopen the VS Code with the running container.
|
||||||
|
|
||||||
|
The first time you do this on your machine, it will pull the docker image down from the registry and build the container. Subsequent launches are much faster!
|
||||||
|
|
||||||
|
:::caution
|
||||||
|
All subsequent steps must be performed from the VS Code terminal _inside_ the container.
|
||||||
|
:::
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
</OsTabs>
|
||||||
|
|
||||||
|
#### Initialize West
|
||||||
|
|
||||||
|
```sh
|
||||||
|
west init -l app/
|
||||||
|
```
|
||||||
|
|
||||||
|
:::caution Command Not Found?
|
||||||
|
If you encounter errors like `command not found: west` then your `PATH` environment variable is likely
|
||||||
|
missing the Python 3 user packages directory. See the [West Build Command](#west-build-command)
|
||||||
|
section again for links to how to do this
|
||||||
|
:::
|
||||||
|
|
||||||
|
#### Update To Fetch Modules
|
||||||
|
|
||||||
|
```sh
|
||||||
|
west update
|
||||||
|
```
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
This step pulls down quite a bit of tooling. Go grab a cup of coffee, it can take 10-15 minutes even on a good internet connection!
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::info
|
||||||
|
If you're using Docker, you're done with setup! You must restart the container at this point. The easiest way to do so is to close the VS Code window, verify that the container has stopped in Docker Dashboard, and reopen the container with VS Code.
|
||||||
|
|
||||||
|
Once your container is restarted, proceed to [Building and Flashing](./development/build-flash.md).
|
||||||
|
:::
|
||||||
|
|
||||||
|
#### Export Zephyr™ Core
|
||||||
|
|
||||||
|
```sh
|
||||||
|
west zephyr-export
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Install Zephyr Python Dependencies
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pip3 install --user -r zephyr/scripts/requirements-base.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
<Tabs
|
||||||
|
defaultValue="win"
|
||||||
|
values={[
|
||||||
|
{label: 'Windows', value: 'win'},
|
||||||
|
{label: 'Other OS', value: 'other'},
|
||||||
|
]}>
|
||||||
|
<TabItem value = 'win'>
|
||||||
|
|
||||||
|
#### For GNU ARM Embedded on Windows
|
||||||
|
|
||||||
|
On Windows, only two environment variables need to be set for ZMK to build properly: `ZEPHYR_TOOLCHAIN_VARIANT` and `GNUARMEMB_TOOLCHAIN_PATH`.
|
||||||
|
|
||||||
|
1. Open Start Menu and type 'env' to find the 'Edit the system environment variables' option. Open it.
|
||||||
|
|
||||||
|
![Environment variables in Start Menu](../assets/env-var/start_menu.png)
|
||||||
|
|
||||||
|
2. Click 'Environment Variables...'.
|
||||||
|
|
||||||
|
![Environment variables button](../assets/env-var/env_var.png)
|
||||||
|
|
||||||
|
3. Click "New..." under System variables to create a new system variable.
|
||||||
|
|
||||||
|
![Environment variables menu](../assets/env-var/new_variable.png)
|
||||||
|
|
||||||
|
4. Set the variable name to 'ZEPHYR_TOOLCHAIN_VARIANT' and value to 'gnuarmemb'. Click OK to save.
|
||||||
|
|
||||||
|
![Adding Zephyr toolchain variable](../assets/env-var/zephyr_toolchain.png)
|
||||||
|
|
||||||
|
5. Create another variable with variable name 'GNUARMEMB_TOOLCHAIN_PATH' and value set to wherever you installed your toolchain. **Make sure this path does not contain any spaces.** If it does, rename the folder and update here. Click OK to save.
|
||||||
|
|
||||||
|
![Adding GNUARMEMB variable](../assets/env-var/gnuarmemb.png)
|
||||||
|
|
||||||
|
6. Close Command Prompt and reopen, or run `refreshenv` to apply the changes.
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
|
||||||
|
<TabItem value = 'other'>
|
||||||
|
|
||||||
|
#### For Zephyr
|
||||||
|
|
||||||
|
By default, the Zephyr™ SDK will create a file named `~/.zephyrrc` with the correct environment variables to build ZMK.
|
||||||
|
We suggest two main [options](https://docs.zephyrproject.org/2.3.0/guides/env_vars.html?highlight=zephyrrc) for how to load those settings.
|
||||||
|
|
||||||
|
##### Per Shell
|
||||||
|
|
||||||
|
To load the Zephyr environment properly for just one transient shell, run the following from your ZMK checkout directory:
|
||||||
|
|
||||||
|
```
|
||||||
|
source zephyr/zephyr-env.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
##### All Shells
|
||||||
|
|
||||||
|
To load the environment variables for your shell every time,
|
||||||
|
append the existing `~/.zephyrrc` file to your shell's RC file and then start a new shell.
|
||||||
|
|
||||||
|
<Tabs
|
||||||
|
groupId="shell"
|
||||||
|
defaultValue="bash"
|
||||||
|
values={[
|
||||||
|
{label: 'bash', value: 'bash'},
|
||||||
|
{label: 'zsh', value: 'zsh'},
|
||||||
|
]
|
||||||
|
}>
|
||||||
|
|
||||||
|
<TabItem value="bash">
|
||||||
|
|
||||||
|
```
|
||||||
|
cat ~/.zephyrrc >> ~/.bashrc
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
|
||||||
|
<TabItem value="zsh">
|
||||||
|
|
||||||
|
```
|
||||||
|
cat ~/.zephyrrc >> ~/.zshrc
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
|
||||||
|
</Tabs>
|
22
zmk/docs/docs/development/tests.md
Normal file
22
zmk/docs/docs/development/tests.md
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
---
|
||||||
|
title: Tests
|
||||||
|
sidebar_label: Tests
|
||||||
|
---
|
||||||
|
|
||||||
|
Running tests requires [native posix support](posix-board). Any folder under `/app/tests`
|
||||||
|
containing `native_posix.keymap` will be selected when running `west test`.
|
||||||
|
|
||||||
|
Run a single test with `west test <testname>`, like `west test tests/toggle-layer/normal`.
|
||||||
|
|
||||||
|
## Creating a New Test Set
|
||||||
|
|
||||||
|
1. Copy the test set that most closely resembles the tests you will be creating.
|
||||||
|
2. Rename the newly created test set to the behavior you're testing e.g, toggle-layer
|
||||||
|
3. Modify `behavior_keymap.dtsi` to create a keymap using the behavior and related behaviors
|
||||||
|
4. Modify `test_case/native_posix.keymap` for a simulated use case
|
||||||
|
5. Modify `test_case/events.patterns` to collect relevant logs to the test
|
||||||
|
- See: [sed manual](https://www.gnu.org/software/sed/manual/sed.html) and
|
||||||
|
[tutorial](https://www.digitalocean.com/community/tutorials/the-basics-of-using-the-sed-stream-editor-to-manipulate-text-in-linux)
|
||||||
|
6. Modify `test_case/keycode_events.snapshot` for to include the expected output
|
||||||
|
7. Rename the `test_case` folder to describe the test.
|
||||||
|
8. Repeat steps 4 to 7 for every test case
|
103
zmk/docs/docs/development/usb-logging.md
Normal file
103
zmk/docs/docs/development/usb-logging.md
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
---
|
||||||
|
title: USB Logging
|
||||||
|
---
|
||||||
|
|
||||||
|
import Tabs from '@theme/Tabs';
|
||||||
|
import TabItem from '@theme/TabItem';
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
If you are developing ZMK on a device that does not have a built in UART for debugging and log/console output,
|
||||||
|
Zephyr can be configured to create a USB CDC ACM device and the direct all `printk`, console output, and log
|
||||||
|
messages to that device instead.
|
||||||
|
|
||||||
|
:::warning Battery Life Impact
|
||||||
|
|
||||||
|
Enabling logging increases the power usage of your keyboard, and can have a non-trivial impact to your time on battery.
|
||||||
|
It is recommended to only enable logging when needed, and not leaving it on by default.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Kconfig
|
||||||
|
|
||||||
|
The following KConfig values need to be set, either by copy and pasting into the `app/prj.conf` file, or by running
|
||||||
|
`west build -t menuconfig` and manually enabling the various settings in that UI.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
If you are debugging your own keyboard in your [user config repository](./user-setup.md), use
|
||||||
|
`config/boards/shields/<your_keyboard>/<your_keyboard>.conf` instead of `app/prj.conf`. In Github
|
||||||
|
Actions, you can search the `Kconfig file` build log to verify the options above have been enabled
|
||||||
|
for you successfully.
|
||||||
|
:::
|
||||||
|
|
||||||
|
```
|
||||||
|
# Turn on logging, and set ZMK logging to debug output
|
||||||
|
CONFIG_LOG=y
|
||||||
|
CONFIG_ZMK_LOG_LEVEL_DBG=y
|
||||||
|
|
||||||
|
# Turn on USB CDC ACM device
|
||||||
|
CONFIG_USB=y
|
||||||
|
CONFIG_USB_DEVICE_STACK=y
|
||||||
|
CONFIG_USB_CDC_ACM=y
|
||||||
|
CONFIG_USB_CDC_ACM_RINGBUF_SIZE=1024
|
||||||
|
CONFIG_USB_CDC_ACM_DEVICE_NAME="CDC_ACM"
|
||||||
|
CONFIG_USB_CDC_ACM_DEVICE_COUNT=1
|
||||||
|
|
||||||
|
# Enable serial console
|
||||||
|
CONFIG_SERIAL=y
|
||||||
|
CONFIG_CONSOLE=y
|
||||||
|
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||||
|
CONFIG_UART_LINE_CTRL=y
|
||||||
|
|
||||||
|
# Enable USB UART, and set the console device
|
||||||
|
CONFIG_UART_CONSOLE=y
|
||||||
|
CONFIG_USB_UART_CONSOLE=y
|
||||||
|
CONFIG_UART_CONSOLE_ON_DEV_NAME="CDC_ACM_0"
|
||||||
|
CONFIG_USB_UART_DTR_WAIT=n
|
||||||
|
```
|
||||||
|
|
||||||
|
## Viewing Logs
|
||||||
|
|
||||||
|
After flashing the updated ZMK image, the board should expose a USB CDC ACM device that you can connect to and view the logs.
|
||||||
|
|
||||||
|
<Tabs
|
||||||
|
defaultValue="linux"
|
||||||
|
values={[
|
||||||
|
{label: 'Linux', value: 'linux'},
|
||||||
|
{label: 'Windows', value: 'win'},
|
||||||
|
{label: 'MacOS', value: 'macos'}
|
||||||
|
]}>
|
||||||
|
<TabItem value="linux">
|
||||||
|
|
||||||
|
On Linux, this should be a device like `/dev/ttyACM0` and you can connect with `minicom` or `tio` as usual, e.g.:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo tio /dev/ttyACM0
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="win">
|
||||||
|
|
||||||
|
On Windows, you can use [PuTTY](https://www.putty.org/). Once installed, use Device Manager to figure out which COM port your controller is communicating on (listed under 'Ports (COM & LPT)') and specify that as the 'Serial line' in PuTTY.
|
||||||
|
|
||||||
|
![Controller COM port](../assets/usb-logging/com.jpg)
|
||||||
|
|
||||||
|
![PuTTY settings](../assets/usb-logging/putty.jpg)
|
||||||
|
|
||||||
|
If you already have the Ardunio IDE installed you can also use its built-in Serial Monitor.
|
||||||
|
|
||||||
|
</TabItem>
|
||||||
|
<TabItem value="macos">
|
||||||
|
|
||||||
|
On MacOS, the device name is something like `/dev/tty.usbmodemXXXXX` where `XXXXX` is some numerical ID.
|
||||||
|
You can connect to the device with [tio](https://tio.github.io/) (can be installed via [Homebrew](https://formulae.brew.sh/formula/tio)):
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo tio /dev/tty.usbmodem14401
|
||||||
|
```
|
||||||
|
|
||||||
|
You should see tio printing `Disconnected` or `Connected` when you disconnect or reconnect the USB cable.
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
From there, you should see the various log messages from ZMK and Zephyr, depending on which systems you have set to what log levels.
|
|
@ -76,6 +76,10 @@ Therefore in ZMK, [board](#what-is-a-board) and [shield](#what-is-a-shield) are
|
||||||
|
|
||||||
Please note, many keyboards only have a single PCB which includes the “brains” (MCU) onboard. In ZMK, these have no [shield](#what-is-a-shield), only a [board](#what-is-a-board).
|
Please note, many keyboards only have a single PCB which includes the “brains” (MCU) onboard. In ZMK, these have no [shield](#what-is-a-shield), only a [board](#what-is-a-board).
|
||||||
|
|
||||||
|
### Does ZMK support wired split?
|
||||||
|
|
||||||
|
Currently, ZMK only supports wireless split, but wired split is possible and we welcome contributions!
|
||||||
|
|
||||||
### What bootloader does ZMK use?
|
### What bootloader does ZMK use?
|
||||||
|
|
||||||
ZMK isn’t designed for any particular bootloader, and supports flashing different boards with different flash utilities (e.g. OpenOCD, nrfjprog, etc.). So if you have any difficulties, please let us know on [Discord](https://zmkfirmware.dev/community/discord/invite)!
|
ZMK isn’t designed for any particular bootloader, and supports flashing different boards with different flash utilities (e.g. OpenOCD, nrfjprog, etc.). So if you have any difficulties, please let us know on [Discord](https://zmkfirmware.dev/community/discord/invite)!
|
||||||
|
|
6
zmk/docs/docs/features/displays.md
Normal file
6
zmk/docs/docs/features/displays.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
title: OLED Displays
|
||||||
|
sidebar_label: OLED Displays
|
||||||
|
---
|
||||||
|
|
||||||
|
TODO: Documentation on OLED displays.
|
44
zmk/docs/docs/features/encoders.md
Normal file
44
zmk/docs/docs/features/encoders.md
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
---
|
||||||
|
title: Encoders
|
||||||
|
sidebar_label: Encoders
|
||||||
|
---
|
||||||
|
|
||||||
|
Existing support for encoders in ZMK is focused around the five pin EC11 rotary encoder with push button design used in the majority of current keyboard and macropad designs.
|
||||||
|
|
||||||
|
## Enabling EC11 Encoders
|
||||||
|
|
||||||
|
To enable encoders for boards that have existing encoder support, uncomment the `EC11_CONFIG=y` and `CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y` lines in your board's .conf file in your `zmk-config/config` folder. Save and push your changes, then download and flash the new firmware.
|
||||||
|
|
||||||
|
## Customizing EC11 Encoder Behavior
|
||||||
|
|
||||||
|
Encoder behavior in ZMK is configured in two different locations as the push button and rotation behaviors are handled in two separate ways.
|
||||||
|
|
||||||
|
### Push Button
|
||||||
|
|
||||||
|
Keyboards and macropads with encoder support will typically take the two EC11 pins responsible for the push button and include them as part of the matrix for the keys. To configure what is sent by the push button, find the encoder's position in the keyboard matrix and assign it a behavior the same as you would any other key.
|
||||||
|
|
||||||
|
### Rotation
|
||||||
|
|
||||||
|
Rotation is handled separately as a type of sensor. The behavior for this is set in `sensor-bindings`, which is defined in each keymap layer in the following format:
|
||||||
|
|
||||||
|
```
|
||||||
|
sensor-bindings = <BINDING CW_KEY CCW_KEY>;
|
||||||
|
```
|
||||||
|
|
||||||
|
- `BINDING`, for now, has only one behavior available; `&inc_dec_kp` for key presses (see [Key Press](/docs/behaviors/key-press) for details on available keycodes).
|
||||||
|
- `CW_KEY` is the keycode activated by a clockwise turn.
|
||||||
|
- `CCW_KEY` is the keycode activated by a counter-clockwise turn.
|
||||||
|
|
||||||
|
Additional encoders can be configured by adding more `BINDING CW_KEY CCW_KEY` sets immediately after the first.
|
||||||
|
|
||||||
|
As an example, a complete `sensor-bindings` for a Kyria with two encoders could look like:
|
||||||
|
|
||||||
|
```
|
||||||
|
sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN &inc_dec_kp PG_UP PG_DN>;
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, the left encoder is configured to control volume up and down while the right encoder sends either Page Up or Page Down.
|
||||||
|
|
||||||
|
## Adding Encoder Support
|
||||||
|
|
||||||
|
See the [New Keyboard Shield](../development/new-shield#encoders) documentation for how to add or modify additional encoders to your shield.
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue