---
title: "ZMK State Of The Firmware #4"
authors: petejohanson
tags: [SOTF, keyboards, firmware, oss, ble]
---

Welcome to the fourth ZMK "State Of The Firmware" (SOTF)!

This update will cover all the major activity since [SOTF #3](/blog/2020/11/09/zmk-sotf-3).

<!-- truncate -->

## Recent Activity

Here's a summary of the various major changes since last time, broken down by theme:

### Keymaps/Behaviors

Since last time, there have been several new powerful keymap features and behaviors added, including one of the most asked for features, combos!

#### Combos

The initial [combos](/docs/keymaps/combos) work has landed! The amazing [okke-formsma] has once again delivered another powerful feature for ZMK. Combos are "position based", and are configured in a new toplevel node next to they `keymap` node in user's keymap files.

An example, that would send the `ESC` keycode when pressing both the first and second positions on your keyboard:

```dts
/ {
    combos {
        compatible = "zmk,combos";
        combo_esc {
            timeout-ms = <50>;
            key-positions = <0 1>;
            bindings = <&kp ESC>;
        };
    };
};
```

:::note
Combos currently are "global", and not scoped to a given active layer. There is future planned work to allow enabling a certain combo for only certain active layers.
:::

#### Sticky Keys (One-Shot Mods/Layers) Behavior

[okke-formsma] also contributed the initial "sticky keys" behavior, which can be used for functionality sometimes called "one shot mods" or "one shot layers". In your keymap, this would like like:

```dts
&sk LEFT_CONTROL
```

for a sticky key/modifier, or:

```dts
&sl NAV
```

for a sticky layer.

#### `&to` Layer Behavior

[mcrosson] contributed the new [`&to`](/docs/keymaps/behaviors/layers#to-layer) layer related behavior. This can be used to completely replace the active layer with a new one.

This is most frequently used when using multiple core base layers with different layouts, e.g. QWERTY and DVORAK, to switch between them.

#### Grave Escape Behavior

[okke-formsma] added an implementation of the "Grave Escape" behavior, developing a more generic "mod-morph" behavior to do so. Adding

```dts
&gresc
```

to your keymap will send `ESC` when pressed on its own, but will send `` ` `` when pressed with a GUI or Shift modifier held.

#### RGB Underglow Color Selection

[mcrosson] updated the [RGB Underglow behavior](/docs/keymaps/behaviors/underglow) to allow [binding an explicit color selection](/docs/keymaps/behaviors/underglow#examples) to a key position.

#### Keymap Upgrader

[joelspadin] completed the [Keymap Upgrader](/keymap-upgrader) which can be used to update your keymap to using the latest supported codes, and move away from the old deprecated codes.

If you've made keymap customizations, please make sure to run your keymaps through the upgrader, since the old deprecated codes will be removed in a future version of ZMK.

### Displays

There has been lots of work to get display support complete enough for use by end users. Although not quite ready for prime time, it is incredibly close, and we are looking forward to having the last few items completed and the feature documented!

#### Idle Blanking

[petejohanson] added idle blanking for displays, which ensures they will go blank, and into low power mode, after a short period of inactivity from the user. This ensures we avoid burn-in for OLEDs, and helps improve battery life.

#### Battery and Output Widgets

[petejohanson] implemented the first two complete, dynamic "widgets" for the displays for ZMK, adding a small battery indicator, which includes charging status, and a small output indicator, showing the currently active output (USB or BLE). When using BLE, the indicator also shows the active profile slot, as well as if the profile slot is open, awaiting connection from the paired host, or is actively connected to the host for that profile slot.

#### Highest Layer Display

[mcrosson] has contributed the next display widget, showing the highest active layer in the keymap. [petejohanson] then added a small follow up to allow layers in keymaps to add a `name` property to each layer, e.g. `name = "Nav";` and have that name be displayed in the widget instead of the numeric layer number.

#### WPM

New contributor [allymparker](https://github.com/allymparker) added our fourth widget, a words-per-minute display! This widget work also included creating the core state logic for tracking the WPM.

For now, this widget is only working on the central side of split keyboards.

### Miscellaneous

#### Zephyr 2.4

[innovaker] is at it again with some crucial core fixes, helping prepare and test the upgrade of ZMK to Zephyr 2.4. The updated Zephyr release brings with it some key BLE stability fixes, as well as various other core improvements that improve ZMK. This was a huge undertaking!

#### BLE Deadlock Fixes

[petejohanson] was heads down diagnosing and fixing a deadlock issue on BLE that was frustrating and plaguing many users. After finally pinpointing the underlying root cause, he developed a fix and roped in many testers on Discord to help stress test things before merging.

#### Central/Peripheral Selection

Previously overriding the selection of left as central, and right as peripheral for wireless splits required making local edits to the configuration files, and maintaining them in a ZMK fork.

[petejohanson] updated [the config files](https://github.com/zmkfirmware/zmk/pull/510) to allow users to override this in their `<board>_left.conf`/`<board>_right.conf` files in their user repos.

#### Improved Docker Containers

As part of the Zephyr 2.4. prep work, [innovaker], along with lots of testing and input from [mcrosson], developed a brand new pair of [Docker images](https://github.com/zmkfirmware/zmk-docker) which is now published to Docker Hub as [zmkfirmware/zmk-build-arm](https://hub.docker.com/repository/docker/zmkfirmware/zmk-build-arm) and [zmkfirmware/zmk-dev-arm](https://hub.docker.com/repository/docker/zmkfirmware/zmk-build-arm).

The previously blogged VSCode + Docker integration, as well as our GH Action build automation was all moved over to the new images.

#### Settings Debounce

[nicell] contributed settings debounce work, to help avoid unnecessary extra writes to flash when making various changes that should be saved,
such as the active BLE profile, external VCC on/off, etc.

## New Shields

- Jorne & Jian in [#331](https://github.com/zmkfirmware/zmk/pull/331) - [krikun98](https://github.com/krikun98)
- tidbit in [#424](https://github.com/zmkfirmware/zmk/pull/424) - [mcrosson](https://github.com/mcrosson)
- Helix in [#429](https://github.com/zmkfirmware/zmk/pull/429) - [KingCoinless](https://github.com/KingCoinless)
- BFO-9000 in [#472](https://github.com/zmkfirmware/zmk/pull/472) - [pbz](https://github.com/pbz)
- CRBN in [#493](https://github.com/zmkfirmware/zmk/pull/483) - [ReFil](https://github.com/ReFil)
- Eek in [#529](https://github.com/zmkfirmware/zmk/pull/529) - [MangoIV](https://github.com/MangoIV)

## New Boards

- BDN9 Rev2 in [#557](https://github.com/zmkfirmware/zmk/pull/557) - [petejohanson]

## Sponsorship

Since it's inception, quite a few users have inquired whether they could sponsor any of the contributors involved in ZMK. Although we are not intending to directly fund any individual contributors for their work on ZMK, there _is_ good that can come from folks sponsoring ZMK.

You can see the full discussion on [#497](https://github.com/zmkfirmware/zmk/issues/497), but some items that are being considered with sponsorship funds:

- Hiring a designer to complete the logo/mascot work.
- Creating stickers to send as thank-yous to first time contributors.
- Hosting costs for GitHub Pro.
- Other hosting costs, e.g. Docker Hub.

For anyone looking to contribute, you can find the [ZMK Firmware project](https://opencollective.com/zmkfirmware) is now set up on [Open Collective](https://opencollective.com).

## Coming Soon!

Some items listed in the last coming soon section are still under active development.

- A power profiler page for the website, to help users estimate their battery life for a given keyboard - [Nicell]
- Behavior "locality", allowing improved split usage for things like `&sys_reset`, and controlling external power and RGB underglow for both sides - [petejohanson]
- More modular approach to external boards/shields, custom code, user keymaps, etc.
- More shields and boards

## Statistics

Some statistics of interest for ZMK:

- GitHub (lifetime stats)
  - 389 Closed PRs
  - 199 Stars
  - 163 Forks
- Discord Chat
  - 702 total registered
- Website (last 30 days)
  - 11.5K page views
  - 1K new users

## Thanks!

Thanks again to the numerous contributors, testers, and users who have made working on ZMK such a pleasure!

[okke-formsma]: https://github.com/okke-formsma
[mcrosson]: https://github.com/mcrosson
[nicell]: https://github.com/Nicell
[petejohanson]: https://github.com/petejohanson
[innovaker]: https://github.com/innovaker
[joelspadin]: https://github.com/joelspadin

## Article Updates

- 12/2023: The `label` property for keymap layers was renamed to `display-name`.
