Develop and modify ZMK firmware configuration for the Sofle split keyboard (Nice Nano v2). Covers Kconfig (.conf), Devicetree keymap (.keymap), build matrix (build.yaml), and module management (west.yml).
Instructions for developing and modifying ZMK firmware configuration files for this Sofle split keyboard.
config/sofle.keymapconfig/sofle.confbuild.yamlconfig/west.ymlKEYMAP_VISUAL.mdbuild.yaml # GitHub Actions build matrix (boards + shields)
KEYMAP_VISUAL.md # Human-readable visual keymap reference
config/
sofle.conf # Kconfig settings (system-level config)
sofle.keymap # Devicetree keymap (layers, bindings, behaviors)
west.yml # West manifest (ZMK source + external modules)
boards/shields/ # Custom shield definitions (currently empty)
zephyr/module.yml # Declares this repo as a Zephyr module
ZMK configuration uses two file types:
.conf)Kconfig controls global system settings. The file config/sofle.conf applies to both halves of the split keyboard.
Syntax: One CONFIG_<NAME>=<value> per line, no spaces around =.
Value types:
bool: y (enable) or n (disable). Example: CONFIG_ZMK_SLEEP=yint: Integer value. Example: CONFIG_ZMK_IDLE_TIMEOUT=180000string: Double-quoted text. Example: CONFIG_ZMK_KEYBOARD_NAME="MySofle"Important notes:
sofle.conf (without _left/_right suffix) applies to both halves.CONFIG_ZMK_KEYBOARD_NAME requires clearing stored settings on the controller.CONFIG_BT_MAX_CONN and CONFIG_BT_MAX_PAIRED should always match; on split keyboards set to desired BT profiles + 1.Common Kconfig categories and settings:
| Setting | Type | Description | Default |
|---|---|---|---|
CONFIG_ZMK_KEYBOARD_NAME | string | BT advertised name (max 16 chars) | — |
CONFIG_ZMK_WPM | bool | Enable words-per-minute tracking | n |
CONFIG_HEAP_MEM_POOL_SIZE | int | Heap memory pool size | 8192 |
| Setting | Type | Description | Default |
|---|---|---|---|
CONFIG_ZMK_HID_INDICATORS | bool | Enable HID/LED indicator state from host | n |
CONFIG_ZMK_HID_CONSUMER_REPORT_SIZE | int | Simultaneous consumer keys | 6 |
CONFIG_ZMK_HID_REPORT_TYPE_HKRO | bool | H-key rollover (default) | — |
CONFIG_ZMK_HID_REPORT_TYPE_NKRO | bool | Full N-key rollover (may break some BIOS) | — |
| Setting | Type | Description | Default |
|---|---|---|---|
CONFIG_ZMK_USB | bool | Enable USB keyboard | — |
CONFIG_ZMK_USB_BOOT | bool | USB Boot protocol (for BitLocker/FileVault) | n |
CONFIG_USB_HID_POLL_INTERVAL_MS | int | USB polling interval in ms | 1 |
| Setting | Type | Description | Default |
|---|---|---|---|
CONFIG_BT_MAX_CONN | int | Max simultaneous BT connections | 5 |
CONFIG_BT_MAX_PAIRED | int | Max paired BT devices | 5 |
CONFIG_ZMK_BLE | bool | Enable BLE keyboard | — |
CONFIG_ZMK_BLE_CLEAR_BONDS_ON_START | bool | Clear bonds on startup | n |
CONFIG_ZMK_BLE_PASSKEY_ENTRY | bool | Require passkey pairing (experimental) | n |
| Setting | Type | Description | Default |
|---|---|---|---|
CONFIG_ZMK_SLEEP | bool | Enable deep sleep | n |
CONFIG_ZMK_IDLE_TIMEOUT | int | Idle timeout in ms before idle state | 30000 |
CONFIG_ZMK_IDLE_SLEEP_TIMEOUT | int | Idle timeout in ms before deep sleep | 900000 |
CONFIG_ZMK_EXT_POWER | bool | Enable external power control | — |
| Setting | Type | Description | Default |
|---|---|---|---|
CONFIG_ZMK_RGB_UNDERGLOW | bool | Enable RGB underglow | n |
CONFIG_ZMK_RGB_UNDERGLOW_HUE_START | int | Starting hue (0-359) | 0 |
CONFIG_ZMK_RGB_UNDERGLOW_SAT_START | int | Starting saturation (0-100) | 100 |
CONFIG_ZMK_RGB_UNDERGLOW_BRT_START | int | Starting brightness (0-100) | 100 |
CONFIG_ZMK_RGB_UNDERGLOW_AUTO_OFF_IDLE | bool | Turn off RGB on idle | n |
CONFIG_WS2812_STRIP | bool | Enable WS2812 LED strip driver | — |
| Setting | Type | Description | Default |
|---|---|---|---|
CONFIG_EC11 | bool | Enable EC11 rotary encoder | n |
CONFIG_EC11_TRIGGER_GLOBAL_THREAD | bool | Use global thread for encoder triggers | n |
| Setting | Type | Description | Default |
|---|---|---|---|
CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY | int | Max combos that share a key | 5 |
CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO | int | Max keys in a single combo | 4 |
CONFIG_ZMK_COMBO_MAX_PRESSED_COMBOS | int | Max simultaneously active combos | 4 |
| Setting | Type | Description | Default |
|---|---|---|---|
CONFIG_ZMK_USB_LOGGING | bool | Enable USB CDC ACM logging | n |
CONFIG_ZMK_LOG_LEVEL | int | ZMK log level (0-4) | 4 |
| Setting | Type | Description | Default |
|---|---|---|---|
CONFIG_ZMK_KSCAN_DEBOUNCE_PRESS_MS | int | Debounce time for key press | 5 |
CONFIG_ZMK_KSCAN_DEBOUNCE_RELEASE_MS | int | Debounce time for key release | 5 |
.keymap)The keymap file config/sofle.keymap defines layers, key bindings, behaviors, combos, macros, and conditional layers using Devicetree syntax.
Required includes:
#include <behaviors.dtsi>
#include <dt-bindings/zmk/keys.h>
#include <dt-bindings/zmk/bt.h>
#include <dt-bindings/zmk/rgb.h>
#include <dt-bindings/zmk/ext_power.h>
Layer definition pattern:
#define BASE 0
#define LOWER 1
#define RAISE 2
/ {
keymap {
compatible = "zmk,keymap";
default_layer {
display-name = "default";
bindings = <
// key bindings here, one per physical key
>;
sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN &inc_dec_kp PG_UP PG_DN>;
};
};
};
Key binding syntax:
&kp <KEYCODE> (e.g., &kp A, &kp N1, &kp LSHFT)&mo <LAYER_NUM> (e.g., &mo 1)&tog <LAYER_NUM>&trans (passes through to lower layer)&none (blocks key)&bt BT_CLR, &bt BT_SEL 0&rgb_ug RGB_TOG, &rgb_ug RGB_HUI, &rgb_ug RGB_BRI&ext_power EP_TOG&inc_dec_kp <CW_KEY> <CCW_KEY>Conditional layers:
conditional_layers {
compatible = "zmk,conditional-layers";
adjust_layer {
if-layers = <LOWER RAISE>;
then-layer = <ADJUST>;
};
};
Combos:
combos {
compatible = "zmk,combos";
combo_name {
timeout-ms = <50>;
key-positions = <POS1 POS2>;
bindings = <&kp KEYCODE>;
layers = <LAYER_NUM>; // optional: restrict to specific layers
};
};
Macros:
macros {
macro_name: macro_name {
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings = <&kp A &kp B &kp C>;
};
};
Tap-dance:
behaviors {
td_example: td_example {
compatible = "zmk,behavior-tap-dance";
#binding-cells = <0>;
tapping-term-ms = <200>;
bindings = <&kp A>, <&kp B>;
};
};
Hold-tap (home row mods):
behaviors {
hm: homerow_mods {
compatible = "zmk,behavior-hold-tap";
#binding-cells = <2>;
tapping-term-ms = <200>;
quick-tap-ms = <150>;
flavor = "tap-preferred";
bindings = <&kp>, <&kp>;
};
};
Changing existing node properties (overlay pattern):
&kscan0 {
debounce-press-ms = <0>;
};
build.yaml)Defines the build matrix for GitHub Actions firmware compilation.