<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>ZMK Firmware Blog</title>
        <link>https://zmk.dev/blog</link>
        <description>ZMK Firmware Blog</description>
        <lastBuildDate>Tue, 09 Dec 2025 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Zephyr 4.1 Update]]></title>
            <link>https://zmk.dev/blog/2025/12/09/zephyr-4-1</link>
            <guid>https://zmk.dev/blog/2025/12/09/zephyr-4-1</guid>
            <pubDate>Tue, 09 Dec 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[We're happy to announce that after a long wait, ZMK's main branch is now running Zephyr 4.1!]]></description>
            <content:encoded><![CDATA[<p>We're happy to announce that after a long wait, ZMK's <code>main</code> branch is now running <a href="https://docs.zephyrproject.org/latest/releases/release-notes-4.1.html" target="_blank" rel="noopener noreferrer" class="">Zephyr 4.1</a>!</p>
<!-- -->
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>The following changes have been made since this blog post was originally published:</p><ul>
<li class="">The <a href="https://github.com/zmkfirmware/zmk/pull/3145" target="_blank" rel="noopener noreferrer" class="">move to <code>zmk</code> variants by default</a> for ZMK boards was documented.</li>
</ul></div></div>
<p>Zephyr 4.1 is a large leap forward from our previous version of 3.5, featuring:</p>
<ul>
<li class="">Support for lots of new SoCs, boards, and shields, such as the WCH CH32V003, the Raspberry Pi Pico 2, and <a href="https://docs.zephyrproject.org/4.1.0/boards/index.html#boards" target="_blank" rel="noopener noreferrer" class="">many many more</a>.</li>
<li class="">Hardware Model V2 (HWMv2), providing better support for SoCs which have multiple cores on the same chip, such as the nRF5340.</li>
<li class="">Lots of new drivers for chips such as the nPM1300.</li>
</ul>
<p>This was a very large undertaking, and a big congratulations and thanks to <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> is due for all of his hard work in making this possible.</p>
<p>After we have verified functionality, ironed out any major bugs, and given any third party module maintainers time to update their code, we will be releasing ZMK <code>v0.4</code> as the first version to include this Zephyr version update.</p>
<p><strong>All</strong> out-of-tree keyboards will need to be updated to use HWMv2. If you maintain such a keyboard, you can find instructions on doing so <a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#moving-to-hwmv2" class="">below</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="switching-to-the-previous-release">Switching To the Previous Release<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#switching-to-the-previous-release" class="hash-link" aria-label="Direct link to Switching To the Previous Release" title="Direct link to Switching To the Previous Release" translate="no">​</a></h2>
<p>Some readers may be coming here because the above changes have <em>broken</em> their builds. ZMK uses a formal release process that allows users to build against a specific release, instead of following the unstable/development version found in the <code>main</code> branch. However, since this is a relatively new process, many users may still be tracking <code>main</code>.</p>
<p>For all users, except those willing to accept periodic breaks they need to track down, we highly recommend <a class="" href="https://zmk.dev/blog/2025/06/20/pinned-zmk">pinning your ZMK version</a>. Doing so will allow you to avoid any issues related to the Zephyr upgrade, and allow you to choose when to upgrade to a future ZMK release when you are ready.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="getting-the-changes">Getting The Changes<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#getting-the-changes" class="hash-link" aria-label="Direct link to Getting The Changes" title="Direct link to Getting The Changes" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="user-config-repositories-using-github-actions">User Config Repositories Using GitHub Actions<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#user-config-repositories-using-github-actions" class="hash-link" aria-label="Direct link to User Config Repositories Using GitHub Actions" title="Direct link to User Config Repositories Using GitHub Actions" translate="no">​</a></h3>
<p>Existing user repositories that have <code>revision: main</code> in their <code>west.yml</code> will receive the changes automatically when rebuilding.</p>
<p>Any user repositories created on or after <code>2025-07-03</code> are currently pinned to the most recent ZMK release. You will need to change over to <code>main</code> to get these changes immediately, or wait for <code>v0.4</code> and upgrade your version then.
See the recent <a class="" href="https://zmk.dev/blog/2025/06/20/pinned-zmk">blog post on pinning ZMK versions</a> for more information.</p>
<p>Likewise, if you are currently on <code>main</code> but do not wish to upgrade yet, please pin your ZMK version to <code>v0.3</code> by following the instructions in said blog post.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="vs-code--docker-dev-container">VS Code &amp; Docker (Dev Container)<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#vs-code--docker-dev-container" class="hash-link" aria-label="Direct link to VS Code &amp; Docker (Dev Container)" title="Direct link to VS Code &amp; Docker (Dev Container)" translate="no">​</a></h3>
<p>If you build locally using VS Code &amp; Docker then:</p>
<ul>
<li class="">Pull the latest ZMK <code>main</code> with <code>git pull</code> for your ZMK checkout</li>
<li class="">Reload the project</li>
<li class="">If you are prompted to rebuild the remote container, click <code>Rebuild</code></li>
<li class="">Otherwise, press <code>F1</code> and run <code>Remote Containers: Rebuild Container</code></li>
<li class="">Once the container has rebuilt and reloaded, run <code>west update</code> to pull the updated Zephyr version and its dependencies.</li>
</ul>
<p>Once the container has rebuilt, VS Code will be running the 4.1 Docker image.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="local-host-development">Local Host Development<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#local-host-development" class="hash-link" aria-label="Direct link to Local Host Development" title="Direct link to Local Host Development" translate="no">​</a></h3>
<p>The following steps will get you building ZMK locally against Zephyr 4.1:</p>
<ul>
<li class="">Run the updated <a class="" href="https://zmk.dev/docs/development/local-toolchain/setup">toolchain installation</a> steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)</li>
<li class="">Install the latest version of <code>west</code> by running <code>pip3 install --upgrade west</code> in a virtual environment, or add the <code>--user</code> flag if <code>west</code> is installed globally: <code>pip3 install --user --upgrade west</code>.</li>
<li class="">Pull the latest ZMK <code>main</code> with <code>git pull</code> for your ZMK checkout</li>
<li class="">Run <code>west update</code> to pull the updated Zephyr version and its dependencies</li>
<li class="">Run <code>west packages pip --install</code> to update required Python packages</li>
</ul>
<p>From there, you should be ready to build as normal!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="zmk-board-variant">ZMK Board Variant<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#zmk-board-variant" class="hash-link" aria-label="Direct link to ZMK Board Variant" title="Direct link to ZMK Board Variant" translate="no">​</a></h2>
<p>The new Zephyr version includes a <a href="https://docs.zephyrproject.org/4.1.0/hardware/porting/board_porting.html#board-extensions" target="_blank" rel="noopener noreferrer" class="">standard mechanism for extending boards</a> found in Zephyr (like the Seeeduino XIAO, or Raspberry Pi Pico) with new variants that include additional configuration/defaults that are relevant to the application. This also means the original "stock" board can still be used as is, if consumers don't want to use those customizations for any reason.</p>
<p>As a result, all board definitions found in the ZMK tree now must be used with a <code>zmk</code> variant. For example, the previous board ID of <code>adv360pro_left</code> would now be <code>adv360pro_left/nrf52840/zmk</code>, which can be shortened to <code>adv360pro_left//zmk</code> since there's only one SoC on the board.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="board-revisions">Board Revisions<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#board-revisions" class="hash-link" aria-label="Direct link to Board Revisions" title="Direct link to Board Revisions" translate="no">​</a></h2>
<p>As part of this change, ZMK is now using board/shield revisions, rather than duplicate board/shield definitions. This means that instead of having e.g. <code>nice_nano</code>, and <code>nice_nano_v2</code>, we only have <code>nice_nano</code>, which by default points to the <code>2.0.0</code> revision. To point to the original Nice!Nano V1, you would need to use <code>nice_nano@1.0.0</code> where you would have previously used <code>nice_nano</code>. Of course, you could also put <code>nice_nano@2.0.0</code> if you wished to make that explicit, instead of merely replacing <code>nice_nano_v2</code> with <code>nice_nano</code>. Some boards, such as the <code>nrfmicro</code>, also have additional <em>board qualifiers</em> such as the choice between multiple SoCs. Board qualifiers must always be specified, and do not have defaults. See <a href="https://docs.zephyrproject.org/4.1.0/hardware/porting/board_porting.html#board-terminology" target="_blank" rel="noopener noreferrer" class="">Zephyr's overview</a> for more information on board qualifiers. The below table provides an overview of some of the differences in in-tree boards we have in ZMK, and how they are selected in the new build system. The shorthand shows the minimum needed to build with a specific board, taking into account defaults.</p>
<ul>
<li class="">nice!nano (<code>nice_nano</code>)
<ul>
<li class=""><code>nice_nano</code> -&gt; <code>nice_nano@1.0.0</code> (short: <code>nice_nano@1</code>)</li>
<li class=""><code>nice_nano_v2</code> -&gt; <code>nice_nano@2.0.0</code> (short: <code>nice_nano</code>)</li>
</ul>
</li>
<li class="">nRFMicro (<code>nrfmicro/nrf52840</code>)
<ul>
<li class=""><code>nrfmicro_11</code> -&gt; <code>nrfmicro@1.1.0/nrf52840</code> (short: <code>nrfmicro@1.1/nrf52840</code>)</li>
<li class=""><code>nrfmicro_11_flipped</code> -&gt; <code>nrfmicro@1.1.0/nrf52840/flipped</code> (short: <code>nrfmicro@1.1/nrf52840/flipped</code>)</li>
<li class=""><code>nrfmicro_13</code> -&gt; <code>nrfmicro@1.3.0/nrf52840</code> (short: <code>nrfmicro/nrf52840</code>)</li>
<li class=""><code>nrfmicro_13_52833</code> -&gt; <code>nrfmicro@1.3.0/nrf52833</code> (short: <code>nrfmicro/nrf52833</code>)</li>
</ul>
</li>
<li class="">Mikoto (<code>mikoto</code>)
<ul>
<li class=""><code>mikoto</code> -&gt; <code>mikoto@5.20.0</code> (short: <code>mikoto</code>)</li>
<li class=""><code>mikoto@6.1</code> -&gt; <code>mikoto@6.1.0</code> (short: <code>mikoto@6</code>)</li>
<li class=""><code>mikoto@7.2</code> -&gt; <code>mikoto@7.2.0</code> (short: <code>mikoto@7</code>)</li>
</ul>
</li>
<li class="">XIAO RP2040 (<code>xiao_rp2040</code>)
<ul>
<li class=""><code>seeeduino_xiao_rp2040</code> -&gt; <code>xiao_rp2040</code></li>
</ul>
</li>
<li class="">XIAO nRF52840/BLE (<code>xiao_ble</code>)
<ul>
<li class=""><code>seeeduino_xiao_ble</code> -&gt; <code>xiao_ble</code></li>
</ul>
</li>
<li class="">BT60 (<code>bt60</code>)
<ul>
<li class=""><code>bt60_v1</code> -&gt; <code>bt60@1.0.0</code></li>
<li class=""><code>bt60_v2</code> -&gt; <code>bt60@2.0.0</code></li>
<li class=""><code>bt60_hs</code> -&gt; <code>bt60_hs</code></li>
</ul>
</li>
<li class="">Planck (<code>planck</code>)
<ul>
<li class=""><code>planck_rev6</code> -&gt; <code>planck</code></li>
</ul>
</li>
<li class="">BDN9 (<code>bdn9</code>)
<ul>
<li class=""><code>bdn9_rev2</code> -&gt; <code>bdn9</code></li>
</ul>
</li>
<li class="">Ferris Rev2 (<code>ferris</code>)
<ul>
<li class=""><code>ferris_rev02</code> -&gt; <code>ferris@2.0.0</code> (short: <code>ferris</code>)</li>
</ul>
</li>
<li class="">Corne-ish Zen (<code>corneish_zen</code>)
<ul>
<li class=""><code>corneish_zen_v2_left</code> -&gt; <code>corneish_zen_left@2.0.0</code> (short: <code>corneish_zen_left</code>)</li>
<li class=""><code>corneish_zen_v2_right</code> -&gt; <code>corneish_zen_right@2.0.0</code> (short: <code>corneish_zen_right</code>)</li>
<li class=""><code>corneish_zen_v1_left</code> -&gt; <code>corneish_zen_left@1.0.0</code> (short: <code>corneish_zen_left@1</code>)</li>
<li class=""><code>corneish_zen_v1_right</code> -&gt; <code>corneish_zen_right@1.0.0</code> (short: <code>corneish_zen_right@1</code>)</li>
</ul>
</li>
</ul>
<p>The boards above are those which have changed in ZMK's tree, with the addition of the very popular XIAO series. For other boards in Zephyr's tree, please refer to the Zephyr documentation or source files directly.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="moving-to-hwmv2">Moving To HWMv2<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#moving-to-hwmv2" class="hash-link" aria-label="Direct link to Moving To HWMv2" title="Direct link to Moving To HWMv2" translate="no">​</a></h2>
<p>The move to HWMv2 has already been completed for all boards in ZMK's <code>main</code> branch. For out-of-tree boards, those need to be converted using either an automated script provided by the Zephyr project, or manually.</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>This <em>only</em> applies to boards. Shields do not need any changes to account for the move to HWMv2.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="board-upgrade-script">Board Upgrade Script<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#board-upgrade-script" class="hash-link" aria-label="Direct link to Board Upgrade Script" title="Direct link to Board Upgrade Script" translate="no">​</a></h3>
<p>The Zephyr project provides a script to automate updating a board to HWMv2. To run the script, you'll need to have a local <a class="" href="https://zmk.dev/docs/development/local-toolchain/setup">development setup</a> ready to use. You'll need to ensure you've updated to the new ZMK version and run <code>west update</code> to ensure you've got the new Zephyr version with the script available.</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>The board upgrade script does <em>not</em> work well with split designs. If upgrading a split keyboard board definition, you'll need to update it by hand.</p></div></div>
<p>The following parameters are relevant for out-of-tree boards:</p>
<ul>
<li class=""><code>--board-root &lt;/the/path/to/the/module/</code> -- the full path to the module directory that contains a <code>boards/</code> directory, e.g. <code>/home/peter/git/my-zmk-module/</code>.</li>
<li class=""><code>-b &lt;board_id&gt;</code> -- The board ID to update, e.g. <code>tenbit</code>.</li>
<li class=""><code>-v &lt;vendor_id&gt;</code> -- The vendor for the board, this should be a vendor ID, or designer nickname.</li>
<li class=""><code>-g &lt;group_id&gt;</code> -- The name of the group directory under which to place the new board files. Typically this will match the vendor ID.</li>
<li class=""><code>-s &lt;soc_id&gt;</code> -- The SoC identifier, e.g. <code>nrf52840</code>, <code>rp2040</code>, <code>stm32f411xe</code>.</li>
</ul>
<p>For example:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token plain">$ python3 zmk/zephyr/scripts/utils/board_v1_to_v2.py </span><span class="token punctuation">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    --board-root my-zmk-module </span><span class="token parameter variable" style="color:#005cc5">-b</span><span class="token plain"> my_board </span><span class="token punctuation">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token parameter variable" style="color:#005cc5">-v</span><span class="token plain"> my_company </span><span class="token parameter variable" style="color:#005cc5">-g</span><span class="token plain"> my_group </span><span class="token parameter variable" style="color:#005cc5">-s</span><span class="token plain"> nrf52840</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="migrating-an-out-of-tree-board-manually">Migrating an Out-Of-Tree Board Manually<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#migrating-an-out-of-tree-board-manually" class="hash-link" aria-label="Direct link to Migrating an Out-Of-Tree Board Manually" title="Direct link to Migrating an Out-Of-Tree Board Manually" translate="no">​</a></h3>
<p>The following steps can be completed manually if you encounter issues with the upgrade script, or don't have a local development setup available.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="vendor-directory">Vendor Directory<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#vendor-directory" class="hash-link" aria-label="Direct link to Vendor Directory" title="Direct link to Vendor Directory" translate="no">​</a></h4>
<p>Boards no longer need to live in a parent directory named after the architecture of the board (.e.g <code>boards/arm</code>), and should instead be placed in a vendor/designer named directory (e.g. <code>boards/my_company</code>).</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="write-a-boardyml">Write a <code>board.yml</code><a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#write-a-boardyml" class="hash-link" aria-label="Direct link to write-a-boardyml" title="Direct link to write-a-boardyml" translate="no">​</a></h4>
<p>In your board's folder, next to other files such as <code>&lt;your_board&gt;.dts</code>, add a file called <code>board.yml</code>. This file should have the following structure:</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockTitle_OeMC">board.yml</div><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token key atrule" style="color:#d73a49">board</span><span class="token punctuation">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token key atrule" style="color:#d73a49">name</span><span class="token punctuation">:</span><span class="token plain"> &lt;board</span><span class="token punctuation">-</span><span class="token plain">name</span><span class="token punctuation">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token key atrule" style="color:#d73a49">vendor</span><span class="token punctuation">:</span><span class="token plain"> &lt;board</span><span class="token punctuation">-</span><span class="token plain">vendor</span><span class="token punctuation">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token key atrule" style="color:#d73a49">revision</span><span class="token punctuation">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token key atrule" style="color:#d73a49">format</span><span class="token punctuation">:</span><span class="token plain"> &lt;major.minor.patch</span><span class="token punctuation">|</span><span class="token plain">letter</span><span class="token punctuation">|</span><span class="token plain">number</span><span class="token punctuation">|</span><span class="token plain">custom</span><span class="token punctuation">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token key atrule" style="color:#d73a49">default</span><span class="token punctuation">:</span><span class="token plain"> &lt;default</span><span class="token punctuation">-</span><span class="token plain">revision</span><span class="token punctuation">-</span><span class="token plain">value</span><span class="token punctuation">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token key atrule" style="color:#d73a49">exact</span><span class="token punctuation">:</span><span class="token plain"> &lt;true</span><span class="token punctuation">|</span><span class="token plain">false</span><span class="token punctuation">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token key atrule" style="color:#d73a49">revisions</span><span class="token punctuation">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#d73a49">name</span><span class="token punctuation">:</span><span class="token plain"> &lt;revA</span><span class="token punctuation">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#d73a49">name</span><span class="token punctuation">:</span><span class="token plain"> &lt;revB</span><span class="token punctuation">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">      </span><span class="token punctuation">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token key atrule" style="color:#d73a49">socs</span><span class="token punctuation">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token punctuation">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#d73a49">name</span><span class="token punctuation">:</span><span class="token plain"> &lt;soc</span><span class="token punctuation">-</span><span class="token plain">1</span><span class="token punctuation">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token key atrule" style="color:#d73a49">variants</span><span class="token punctuation">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#d73a49">name</span><span class="token punctuation">:</span><span class="token plain"> &lt;variant</span><span class="token punctuation">-</span><span class="token plain">1</span><span class="token punctuation">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#d73a49">name</span><span class="token punctuation">:</span><span class="token plain"> &lt;variant</span><span class="token punctuation">-</span><span class="token plain">2</span><span class="token punctuation">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">      </span><span class="token key atrule" style="color:#d73a49">variants</span><span class="token punctuation">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">      </span><span class="token punctuation">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#d73a49">name</span><span class="token punctuation">:</span><span class="token plain"> &lt;sub</span><span class="token punctuation">-</span><span class="token plain">variant</span><span class="token punctuation">-</span><span class="token plain">2</span><span class="token punctuation">-</span><span class="token plain">1</span><span class="token punctuation">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token punctuation">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token punctuation">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#d73a49">name</span><span class="token punctuation">:</span><span class="token plain"> &lt;soc</span><span class="token punctuation">-</span><span class="token plain">2</span><span class="token punctuation">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">...</span><br></span></code></pre></div></div>
<p>In the above:</p>
<ul>
<li class=""><code>&lt;board-name&gt;</code> is the name of the board as specified when selecting a build target, such as <code>nice_nano</code>.</li>
<li class=""><code>&lt;vendor-name&gt;</code> is the name of the board's vendor, such as <code>nicekeyboards</code>. If you are an individual, rather than acting as an organization, please use your name/online id/similar (e.g. <code>zhiayang</code> in the case of the <code>mikoto</code>). This value should match the vendor directory name that the board definition folder is placed in the previous section.</li>
<li class=""><code>revision</code> defines any board revisions. See <a href="https://docs.zephyrproject.org/4.1.0/hardware/porting/board_porting.html#multiple-board-revisions" target="_blank" rel="noopener noreferrer" class="">Zephyr's overview</a> for more information on board revisions. If your board does not have any revisions, you can omit this section.</li>
<li class=""><code>socs</code> lists all SoCs that your board could have, e.g. <code>nrf52840</code> or <code>stm32f072xb</code>. If your board only has one SoC available and no variants, then the SoC can be omitted when selecting a build target, but must still be specified in this file. For an understanding of SoC variants, refer to the Zephyr documentation.</li>
</ul>
<p>If you need to define multiple boards in the same <code>board.yml</code>, such as for a split keyboard, you can do so like this:</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token key atrule" style="color:#d73a49">boards</span><span class="token punctuation">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"> </span><span class="token punctuation">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#d73a49">name</span><span class="token punctuation">:</span><span class="token plain"> &lt;board_name_1</span><span class="token punctuation">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">   </span><span class="token punctuation">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"> </span><span class="token punctuation">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#d73a49">name</span><span class="token punctuation">:</span><span class="token plain"> &lt;board_name_2</span><span class="token punctuation">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">   </span><span class="token punctuation">...</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="revision-adjustments">Revision adjustments<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#revision-adjustments" class="hash-link" aria-label="Direct link to Revision adjustments" title="Direct link to Revision adjustments" translate="no">​</a></h4>
<p>If, as a side effect of adding revisions, you renamed the board (e.g. <code>ferris_rev02</code> -&gt; <code>ferris</code>), you should adjust the other places where the board name was previously -- <code>&lt;board&gt;.zmk.yml</code> and <code>&lt;board&gt;.yaml</code>. You may also need to rearrange/consolidate other Kconfig flags and devicetree nodes. See <a href="https://docs.zephyrproject.org/latest/hardware/porting/board_porting.html#multiple-board-revisions" target="_blank" rel="noopener noreferrer" class="">the Zephyr documentation</a> for more details.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="adjust-kconfig-files">Adjust Kconfig files<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#adjust-kconfig-files" class="hash-link" aria-label="Direct link to Adjust Kconfig files" title="Direct link to Adjust Kconfig files" translate="no">​</a></h4>
<h5 class="anchor anchorTargetStickyNavbar_Vzrq" id="kconfigboard"><code>Kconfig.&lt;board&gt;</code><a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#kconfigboard" class="hash-link" aria-label="Direct link to kconfigboard" title="Direct link to kconfigboard" translate="no">​</a></h5>
<p>Previously, your board folder will have had a file named <code>Kconfig.board</code>. This should be renamed to <code>Kconfig.&lt;board&gt;</code>, where <code>&lt;board&gt;</code> is the board name given in <code>board.yml</code>. The contents of this file will previously look something like this:</p>
<div class="language-title=&quot;Kconfig.board&quot; language-title=&quot;kconfig.board&quot; codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-title=&quot;kconfig.board&quot; codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token plain">config BOARD_FERRIS</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    bool "Ferris rev 0.2"</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    depends on SOC_STM32F072XB</span><br></span></code></pre></div></div>
<p>Remove the <code>bool</code> and change the <code>depends on</code> to a <code>select</code>:</p>
<div class="language-title=&quot;Kconfig.ferris&quot; language-title=&quot;kconfig.ferris&quot; codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-title=&quot;kconfig.ferris&quot; codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token plain">config BOARD_FERRIS</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    select SOC_STM32F072XB</span><br></span></code></pre></div></div>
<p>If you had multiple boards specified for different SoCs, you should consolidate them to one:</p>
<div class="language-title=&quot;Kconfig.nrfmicro&quot; language-title=&quot;kconfig.nrfmicro&quot; codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-title=&quot;kconfig.nrfmicro&quot; codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token plain">config BOARD_NRFMICRO</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    select SOC_NRF52840_QIAA if BOARD_NRFMICRO_NRF52840</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    select SOC_NRF52840_QIAA if BOARD_NRFMICRO_NRF52840_FLIPPED</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    select SOC_NRF52833_QIAA if BOARD_NRFMICRO_NRF52833</span><br></span></code></pre></div></div>
<h5 class="anchor anchorTargetStickyNavbar_Vzrq" id="board_defconfig"><code>&lt;board&gt;_defconfig</code><a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#board_defconfig" class="hash-link" aria-label="Direct link to board_defconfig" title="Direct link to board_defconfig" translate="no">​</a></h5>
<p>Previously, this file was used to select the board and SOC with Kconfig flags. All such selections should be removed from this file. For example, all of the below flags should be removed:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token plain">CONFIG_SOC_SERIES_NRF52X=y</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">CONFIG_SOC_NRF52833_QIAA=y</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">CONFIG_SOC_NRF52840_QIAA=y</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">CONFIG_BOARD_&lt;BOARDNAME&gt;=y</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">CONFIG_SOC_SERIES_STM32F0X=y</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">CONFIG_SOC_STM32F072XB=y</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="devicetree-changes">DeviceTree changes<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#devicetree-changes" class="hash-link" aria-label="Direct link to DeviceTree changes" title="Direct link to DeviceTree changes" translate="no">​</a></h4>
<p>For most boards, aside from rearranging due to moving to revisions, there should be no changes necessary to the devicetree nodes. However, if your board makes use of upstream Zephyr drivers, these may have been renamed (e.g. Ferris' <code>microchip,mcp230xx</code> has been changed to <code>microchip,mcp23017</code>).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="general-boardshield-changes">General Board/Shield Changes<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#general-boardshield-changes" class="hash-link" aria-label="Direct link to General Board/Shield Changes" title="Direct link to General Board/Shield Changes" translate="no">​</a></h2>
<p>A few other changes, unrelated to the HWMv2 move, may impact out-of-tree boards/shields:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="bootloader-setup">Bootloader Setup<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#bootloader-setup" class="hash-link" aria-label="Direct link to Bootloader Setup" title="Direct link to Bootloader Setup" translate="no">​</a></h3>
<p>With the version bump, the previous method to enable <code>&amp;bootloader</code> has been disabled. Instead, ZMK is introducing <em>boot retention</em>, which as a side effect also enables <code>&amp;bootloader</code> for SoCs which previously didn't work with said behavior, such as the STM32F072. To set up boot retention for your board, please read through <a class="" href="https://zmk.dev/docs/development/hardware-integration/bootloader">the dedicated page</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="nrf52840-nfc-pins-as-gpio">nRF52840 NFC Pins as GPIO<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#nrf52840-nfc-pins-as-gpio" class="hash-link" aria-label="Direct link to nRF52840 NFC Pins as GPIO" title="Direct link to nRF52840 NFC Pins as GPIO" translate="no">​</a></h3>
<p>If your board or shield is using either of the nRF52840 NFC pins, as is often done with the XIAO nRF52840, you'll need to perform an additional update.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="remove-deprecated-kconfig-symbol">Remove deprecated Kconfig symbol<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#remove-deprecated-kconfig-symbol" class="hash-link" aria-label="Direct link to Remove deprecated Kconfig symbol" title="Direct link to Remove deprecated Kconfig symbol" translate="no">​</a></h4>
<p>Previously, using those pins required enabling <code>CONFIG_NFCT_PINS_AS_GPIOS=y</code> in some Kconfig file. That Kconfig symbol has been removed, so remove any use of that Kconfig symbol from your board/shield.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="set-up-nfc-gpio-devicetree">Set up NFC GPIO devicetree<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#set-up-nfc-gpio-devicetree" class="hash-link" aria-label="Direct link to Set up NFC GPIO devicetree" title="Direct link to Set up NFC GPIO devicetree" translate="no">​</a></h4>
<p>The following should be added to the board or shield's devicetree, e.g. in <code>&lt;board&gt;.dtsi</code> or in a board specific shield overlay file like <code>&lt;my_shield&gt;/boards/xiao_ble.overlay</code>:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token reference variable" style="color:#005cc5">&amp;uicr</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">nfct-pins-as-gpios</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="nrf52840-dcdc-modes">nRF52840 DC/DC Modes<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#nrf52840-dcdc-modes" class="hash-link" aria-label="Direct link to nRF52840 DC/DC Modes" title="Direct link to nRF52840 DC/DC Modes" translate="no">​</a></h3>
<p>For boards with the necessary additional hardware to enable DC/DC modes for the reg0 and/or reg1 power stages, the configuration to enable DC/DC has also moved out of Kconfig and into devicetree.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="remove-kconfig-settings">Remove Kconfig Settings<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#remove-kconfig-settings" class="hash-link" aria-label="Direct link to Remove Kconfig Settings" title="Direct link to Remove Kconfig Settings" translate="no">​</a></h4>
<p>Usually, the DC/DC modes were enabled in the board's <code>Kconfig.defconfig</code> file, looking like:</p>
<div class="language-Kconfig language-kconfig codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kconfig codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token keyword" style="color:#d73a49">config</span><span class="token plain"> </span><span class="token variable" style="color:#005cc5">BOARD_ENABLE_DCDC</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token keyword" style="color:#d73a49">bool</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"Enable DCDC mode"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token keyword" style="color:#d73a49">select</span><span class="token plain"> SOC_DCDC_NRF52X</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token keyword" style="color:#d73a49">default</span><span class="token plain"> </span><span class="token boolean number" style="color:#005cc5">y</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token keyword" style="color:#d73a49">depends</span><span class="token plain"> </span><span class="token keyword" style="color:#d73a49">on</span><span class="token plain"> </span><span class="token punctuation">(</span><span class="token variable" style="color:#005cc5">BOARD_MY_BOARD</span><span class="token punctuation">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token keyword" style="color:#d73a49">config</span><span class="token plain"> </span><span class="token variable" style="color:#005cc5">BOARD_ENABLE_DCDC_HV</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token keyword" style="color:#d73a49">bool</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"High voltage DCDC converter"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token keyword" style="color:#d73a49">select</span><span class="token plain"> SOC_DCDC_NRF52X_HV</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token keyword" style="color:#d73a49">default</span><span class="token plain"> </span><span class="token boolean number" style="color:#005cc5">n</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token keyword" style="color:#d73a49">depends</span><span class="token plain"> </span><span class="token keyword" style="color:#d73a49">on</span><span class="token plain"> </span><span class="token punctuation">(</span><span class="token variable" style="color:#005cc5">BOARD_MY_BOARD</span><span class="token punctuation">)</span><br></span></code></pre></div></div>
<p>Remove the lines from the file that look like above, or remove the <code>Kconfig.defconfig</code> file entirely if that is the only content contained therein.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="add-dcdc-setup-to-devicetree">Add DC/DC setup to devicetree<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#add-dcdc-setup-to-devicetree" class="hash-link" aria-label="Direct link to Add DC/DC setup to devicetree" title="Direct link to Add DC/DC setup to devicetree" translate="no">​</a></h4>
<p>The DC/DC mode is now enabled for the <code>&amp;reg0</code> and <code>&amp;reg1</code> devicetree nodes, depending on which stage you want to use in that mode.</p>
<p>For a high voltage board, where the necessary inductor is connected to the <code>DCCH</code> pin, enable the following in the board's <code>.dts</code> file:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token reference variable" style="color:#005cc5">&amp;reg0</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">status</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"okay"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<p>For both high voltage and non-HV boards, where the necessary inductor is connected to the <code>DCC</code> pin, enable the following in the board's <code>.dts</code> file:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token reference variable" style="color:#005cc5">&amp;reg1</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">regulator-initial-mode</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token plain">NRF5X_REG_MODE_DCDC</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="rp2040-board-adjustments">RP2040 Board Adjustments<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#rp2040-board-adjustments" class="hash-link" aria-label="Direct link to RP2040 Board Adjustments" title="Direct link to RP2040 Board Adjustments" translate="no">​</a></h3>
<p>A few small tweaks are required for custom/out-of-tree RP2040 based boards:</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="clock-control">Clock control<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#clock-control" class="hash-link" aria-label="Direct link to Clock control" title="Direct link to Clock control" translate="no">​</a></h4>
<p>RP2040 boards now require clock control enabled to use several peripherals, including USB.</p>
<p>The following should be added to the board's <code>&lt;board&gt;_defconfig</code> file:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token attr-name" style="color:#005cc5">CONFIG_CLOCK_CONTROL</span><span class="token operator" style="color:#005cc5">=</span><span class="token plain">y</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="base-devicetree-changes">Base devicetree changes<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#base-devicetree-changes" class="hash-link" aria-label="Direct link to Base devicetree changes" title="Direct link to Base devicetree changes" translate="no">​</a></h4>
<p>The location for the base set of devicetree these boards need to include has changed. In the board's <code>&lt;board&gt;.dts</code> file, replace:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="color:#d73a49">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:#032f62">&lt;rpi_pico/rp2040.dtsi&gt;</span><br></span></code></pre></div></div>
<p>with</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="color:#d73a49">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:#032f62">&lt;raspberrypi/rpi_pico/rp2040.dtsi&gt;</span><br></span></code></pre></div></div>
<p>Next, any fixed clock node needs to be removed:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token label symbol" style="color:#e36209">xtal_clk:</span><span class="token plain"> </span><span class="token node class-name" style="color:#6f42c1">xtal-clk</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"fixed-clock"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">clock-frequency</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">12000000</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">#clock-cells</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">0</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<p>And the following added, to set up the core device hardware properly:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token reference variable" style="color:#005cc5">&amp;timer</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">status</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"okay"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token reference variable" style="color:#005cc5">&amp;rtc</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">clocks</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;clocks</span><span class="token plain"> RPI_PICO_CLKID_CLK_RTC</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">status</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"okay"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token reference variable" style="color:#005cc5">&amp;vreg</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">regulator-always-on</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">regulator-allowed-modes</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token plain">REGULATOR_RPI_PICO_MODE_NORMAL</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<p>Lastly, an additional property must be added to the <code>chosen</code> node to supplement the existing properties there:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token node class-name" style="color:#6f42c1">/</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token node class-name" style="color:#6f42c1">chosen</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">zephyr,flash-controller</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token reference variable" style="color:#005cc5">&amp;ssi</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="led-strip-kconfig-changes">LED Strip Kconfig Changes<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#led-strip-kconfig-changes" class="hash-link" aria-label="Direct link to LED Strip Kconfig Changes" title="Direct link to LED Strip Kconfig Changes" translate="no">​</a></h3>
<p>If your board or shield uses RGB underglow, the following Kconfig flag which was previously enabled should now be removed:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token plain">CONFIG_WS2812_STRIP=y</span><br></span></code></pre></div></div>
<p>If this is the only SPI device your shield uses, also remove the Kconfig flag enabling SPI (assuming it is present). It will be automatically enabled.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="cirque-pinnacle-input-driver">Cirque Pinnacle Input Driver<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#cirque-pinnacle-input-driver" class="hash-link" aria-label="Direct link to Cirque Pinnacle Input Driver" title="Direct link to Cirque Pinnacle Input Driver" translate="no">​</a></h3>
<p>Upstream Zephyr now contains a driver for the popular small Cirque Pinnacle trackpads. To transition to the new upstream driver, instead of the <a href="https://github.com/petejohanson/cirque-input-module" target="_blank" rel="noopener noreferrer" class="">out-of-tree module</a>, some small adjustments are needed.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="remove-module-references">Remove module references<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#remove-module-references" class="hash-link" aria-label="Direct link to Remove module references" title="Direct link to Remove module references" translate="no">​</a></h4>
<p>Often, the out-of-tree module is referenced from the <code>west.yml</code> in user's repos. The entry pointing to the module should be removed from your <code>projects</code> list there. If building locally, be sure you are not adding the module directory to the <code>ZMK_EXTRA_MODULES</code> CMake parameter.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="devicetree-changes-1">Devicetree changes<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#devicetree-changes-1" class="hash-link" aria-label="Direct link to Devicetree changes" title="Direct link to Devicetree changes" translate="no">​</a></h4>
<p>The properties for the upstream driver can be found <a href="https://docs.zephyrproject.org/4.1.0/build/dts/api/bindings/input/cirque%2Cpinnacle-i2c.html#dtbinding-cirque-pinnacle-i2c" target="_blank" rel="noopener noreferrer" class="">here</a>. The following changes are required when migrating:</p>
<ul>
<li class="">The <code>dr-gpios</code> property in out-of-tree module is named <code>data-ready-gpios</code>, so renaming the property is required.</li>
<li class="">Instead of an opt-out <code>no-taps</code> property to disable taps, you can enable primary taps with <code>primary-tap-enable</code>.</li>
<li class="">The <code>sleep</code> property is now named <code>sleep-mode-enable</code>.</li>
<li class="">Use <code>invert-x</code>/<code>invert-y</code> instead of <code>x-invert</code>/<code>y-invert</code>.</li>
<li class="">Use <code>swap-xy</code> instead of <code>rotate-90</code>.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="other-changes">Other Changes<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#other-changes" class="hash-link" aria-label="Direct link to Other Changes" title="Direct link to Other Changes" translate="no">​</a></h2>
<p>LVGL was updated to 9.3.0, which comes with breaking API changes. If you are using custom widgets or displays from a module, these will likely need fixing. See the <a href="https://docs.lvgl.io/master/CHANGELOG.html#v9-3-0-3-june-2025" target="_blank" rel="noopener noreferrer" class="">LVGL changelog</a> for details.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="board-extensions">Board Extensions<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#board-extensions" class="hash-link" aria-label="Direct link to Board Extensions" title="Direct link to Board Extensions" translate="no">​</a></h2>
<p>Zephyr has formalized the concept of "board extensions", allowing modules/applications to extend boards that are defined elsewhere. If using a board from the upstream Zephyr project that ZMK hasn't yet extended with default settings, e.g. enabling the <code>CONFIG_ZMK_USB</code> symbol, users can add their own extensions to their modules under the <code>&lt;board_root&gt;/boards/extensions/&lt;board_dir_name&gt;/</code> directory. See <a href="https://github.com/zmkfirmware/zmk/tree/main/app/boards/extensions" target="_blank" rel="noopener noreferrer" class="">https://github.com/zmkfirmware/zmk/tree/main/app/boards/extensions</a> for the extensions that ZMK has added.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="zephyr-upgrade-instructions">Zephyr Upgrade Instructions<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#zephyr-upgrade-instructions" class="hash-link" aria-label="Direct link to Zephyr Upgrade Instructions" title="Direct link to Zephyr Upgrade Instructions" translate="no">​</a></h2>
<p>Should you encounter any other issues with custom or out-of-tree Zephyr code, consider consulting the following Zephyr upgrade guides:</p>
<ul>
<li class=""><a href="https://docs.zephyrproject.org/4.1.0/releases/migration-guide-3.7.html" target="_blank" rel="noopener noreferrer" class="">3.7 Upgrade</a></li>
<li class=""><a href="https://docs.zephyrproject.org/4.1.0/releases/migration-guide-4.1.html" target="_blank" rel="noopener noreferrer" class="">4.1 Upgrade</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="thanks">Thanks!<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#thanks" class="hash-link" aria-label="Direct link to Thanks!" title="Direct link to Thanks!" translate="no">​</a></h2>
<p>Thanks to all the testers who have helped verify ZMK functionality on the newer Zephyr version.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="future">Future<a href="https://zmk.dev/blog/2025/12/09/zephyr-4-1#future" class="hash-link" aria-label="Direct link to Future" title="Direct link to Future" translate="no">​</a></h2>
<p>Once a ZMK version based on Zephyr 4.1 is released, we'll be working towards updating Zephyr even further, to try to catch up with the latest actual Zephyr release. This will likely mean a jump to the upcoming Zephyr 4.3. As part of that work, some other semi-disruptive changes will be required, including:</p>
<ul>
<li class="">Removing ZMK's use of the deprecated, and now removed, <code>kscan</code> APIs in favor of the newer matrix input API. ZMK already supports the matrix input API, but has not yet converted our existing drivers to that API. Advanced users looking to test can try leveraging the upstream Zephyr drivers today to test that functionality, but that is <em>not</em> officially supported and is likely to have bugs or untested side effects.</li>
<li class="">Move the new USB stack, that includes better High-Speed USB support.</li>
</ul>]]></content:encoded>
            <category>firmware</category>
            <category>zephyr</category>
            <category>core</category>
        </item>
        <item>
            <title><![CDATA[Pin your ZMK version]]></title>
            <link>https://zmk.dev/blog/2025/06/20/pinned-zmk</link>
            <guid>https://zmk.dev/blog/2025/06/20/pinned-zmk</guid>
            <pubDate>Fri, 20 Jun 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[ZMK is preparing for a big breaking change. As such, users should consider pinning their ZMK version. Read on to find out more about our versioning system and how you can pin your ZMK version.]]></description>
            <content:encoded><![CDATA[<p>ZMK is preparing for a big breaking change. As such, users should consider pinning their ZMK version. Read on to find out more about our versioning system and how you can pin your ZMK version.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="zmk-versioning----the-what-and-the-why">ZMK Versioning -- The 'what' and the 'why'<a href="https://zmk.dev/blog/2025/06/20/pinned-zmk#zmk-versioning----the-what-and-the-why" class="hash-link" aria-label="Direct link to ZMK Versioning -- The 'what' and the 'why'" title="Direct link to ZMK Versioning -- The 'what' and the 'why'" translate="no">​</a></h2>
<p>Around 6 months ago, ZMK began using versioning. Prior to this point, all ZMK users ran their firmware off of <code>main</code>. This meant that users would always get the latest and greatest changes whenever they built new firmware, but on occasion there would be breaking changes in <code>main</code> that resulted in user confusion.</p>
<p>Avoiding this user confusion became a limiting factor when it came to making changes. <a href="https://www.zephyrproject.org/" target="_blank" rel="noopener noreferrer" class="">Zephyr</a>, the RTOS that ZMK is based off of, made some breaking changes in version 3.6. Hence ZMK has been stuck on Zephyr 3.5 for over 1.5 years, while Zephyr has already moved on to version 4.1. Asking when ZMK will upgrade is a frequent question we get asked, as the new version comes with plenty of improvements and drivers for newer, exciting hardware.</p>
<p>With versioning now in place, users can pin their ZMK configuration to a particular version. This prevents sudden breaking changes from happening without user opt-in and frees ZMK contributors to make breaking changes more frequently, as is necessary.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="zmks-versioning-system">ZMK's Versioning System<a href="https://zmk.dev/blog/2025/06/20/pinned-zmk#zmks-versioning-system" class="hash-link" aria-label="Direct link to ZMK's Versioning System" title="Direct link to ZMK's Versioning System" translate="no">​</a></h3>
<p>ZMK follows the <a href="https://semver.org/" target="_blank" rel="noopener noreferrer" class="">Semantic Versioning</a> standard. Versions are <code>vX.Y.Z</code>. ZMK uses release branches and tags: Every major or minor version bump, a new branch and tag are created. The tag points to the latest patch version. For example, when releasing <code>v0.2.0</code> the branch <code>v0.2-branch</code> and tag <code>v0.2</code> were created. When patches are made, such as for <code>v0.2.1</code>, the branch and tag are updated to point to <code>v0.2.1</code> instead of <code>v0.2.0</code>. This way, users can receive non-breaking security and bug fixes without needing to bump their version.</p>
<p>Whenever ZMK releases a major version with breaking changes, a proper changelog will be provided detailing the major changes from the previous version, along with clear instructions on how to upgrade and fix any breaking changes.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="to-pin-or-not-to-pin">To Pin or Not To Pin<a href="https://zmk.dev/blog/2025/06/20/pinned-zmk#to-pin-or-not-to-pin" class="hash-link" aria-label="Direct link to To Pin or Not To Pin" title="Direct link to To Pin or Not To Pin" translate="no">​</a></h2>
<p>For casual users of ZMK, pinning your version is recommended. Unpinned ZMK configurations are mainly suitable for those more heavily involved or interested in ZMK development. Moving forward, if you are on the <code>main</code> branch of ZMK you will be considered a (highly valued) tester, rather than a user.</p>
<p>To ensure that you still update your ZMK version regularly and get the latest and greatest features that interest you, I would recommend setting up notifications about new releases. You can do so on the <a href="https://github.com/zmkfirmware/zmk" target="_blank" rel="noopener noreferrer" class="">GitHub repository</a>:</p>
<p><img decoding="async" loading="lazy" alt="Image of where to find the custom notifications" src="https://zmk.dev/assets/images/release1-fb17027314c39ed5a63d7d6844956093.png" width="1469" height="473" class="img_ev3q">
<img decoding="async" loading="lazy" alt="Image of setting custom notification" src="https://zmk.dev/assets/images/release2-a4078ce955056f84958f0a5990d105f9.png" width="450" height="353" class="img_ev3q"></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-to-pin-your-zmk-version">How To Pin Your ZMK Version<a href="https://zmk.dev/blog/2025/06/20/pinned-zmk#how-to-pin-your-zmk-version" class="hash-link" aria-label="Direct link to How To Pin Your ZMK Version" title="Direct link to How To Pin Your ZMK Version" translate="no">​</a></h2>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>If you created your ZMK config on or after <code>2025-07-03</code>, then you are already pinned to what was the most recent ZMK version at the time of creation.</p></div></div>
<p>To pin your ZMK version, you need to edit two files:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="west-manifest">West Manifest<a href="https://zmk.dev/blog/2025/06/20/pinned-zmk#west-manifest" class="hash-link" aria-label="Direct link to West Manifest" title="Direct link to West Manifest" translate="no">​</a></h3>
<p>You need to edit the <code>config/west.yml</code> file in your <code>zmk-config</code> repository. The <code>config</code> folder also contains your keymaps, and is located next to the <code>build.yaml</code> file defining which keyboards are built in the first place.</p>
<p>Your <code>west.yml</code> should look something like this (example without <a class="" href="https://zmk.dev/docs/features/modules">modules</a> shown for simplicity):</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv codeBlockLinesWithNumbering_o6Pm" style="counter-reset:line-count 0"><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token key atrule" style="color:#d73a49">manifest</span><span class="token punctuation">:</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">  </span><span class="token key atrule" style="color:#d73a49">remotes</span><span class="token punctuation">:</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token punctuation">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#d73a49">name</span><span class="token punctuation">:</span><span class="token plain"> zmkfirmware</span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">      </span><span class="token key atrule" style="color:#d73a49">url-base</span><span class="token punctuation">:</span><span class="token plain"> https</span><span class="token punctuation">:</span><span class="token plain">//github.com/zmkfirmware</span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">  </span><span class="token key atrule" style="color:#d73a49">projects</span><span class="token punctuation">:</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token punctuation">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#d73a49">name</span><span class="token punctuation">:</span><span class="token plain"> zmk</span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">      </span><span class="token key atrule" style="color:#d73a49">remote</span><span class="token punctuation">:</span><span class="token plain"> zmkfirmware</span></span><br></span><span class="token-line theme-code-block-highlighted-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">      </span><span class="token key atrule" style="color:#d73a49">revision</span><span class="token punctuation">:</span><span class="token plain"> main</span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">      </span><span class="token key atrule" style="color:#d73a49">import</span><span class="token punctuation">:</span><span class="token plain"> app/west.yml</span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">  </span><span class="token key atrule" style="color:#d73a49">self</span><span class="token punctuation">:</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token key atrule" style="color:#d73a49">path</span><span class="token punctuation">:</span><span class="token plain"> config</span></span><br></span></code></pre></div></div>
<p>Simply edit the line <code>revision</code> to point to the release tag instead of <code>main</code>. At the time of writing, the latest release is <code>v0.2</code>, making your <code>west.yml</code> look something like this:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv codeBlockLinesWithNumbering_o6Pm" style="counter-reset:line-count 0"><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token key atrule" style="color:#d73a49">manifest</span><span class="token punctuation">:</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">  </span><span class="token key atrule" style="color:#d73a49">remotes</span><span class="token punctuation">:</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token punctuation">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#d73a49">name</span><span class="token punctuation">:</span><span class="token plain"> zmkfirmware</span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">      </span><span class="token key atrule" style="color:#d73a49">url-base</span><span class="token punctuation">:</span><span class="token plain"> https</span><span class="token punctuation">:</span><span class="token plain">//github.com/zmkfirmware</span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">  </span><span class="token key atrule" style="color:#d73a49">projects</span><span class="token punctuation">:</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token punctuation">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#d73a49">name</span><span class="token punctuation">:</span><span class="token plain"> zmk</span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">      </span><span class="token key atrule" style="color:#d73a49">remote</span><span class="token punctuation">:</span><span class="token plain"> zmkfirmware</span></span><br></span><span class="token-line theme-code-block-highlighted-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">      </span><span class="token key atrule" style="color:#d73a49">revision</span><span class="token punctuation">:</span><span class="token plain"> v0.2</span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">      </span><span class="token key atrule" style="color:#d73a49">import</span><span class="token punctuation">:</span><span class="token plain"> app/west.yml</span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">  </span><span class="token key atrule" style="color:#d73a49">self</span><span class="token punctuation">:</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token key atrule" style="color:#d73a49">path</span><span class="token punctuation">:</span><span class="token plain"> config</span></span><br></span></code></pre></div></div>
<p>See that <code>main</code> has changed to <code>v0.2</code> on the 8th line.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="github-action">GitHub Action<a href="https://zmk.dev/blog/2025/06/20/pinned-zmk#github-action" class="hash-link" aria-label="Direct link to GitHub Action" title="Direct link to GitHub Action" translate="no">​</a></h3>
<p>You need to edit <code>.github/workflows/build.yml</code> in your <code>zmk-config</code>. Again, we are simply replacing <code>main</code> with the latest release tag (<code>v0.2</code> at time of writing):</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv codeBlockLinesWithNumbering_o6Pm" style="counter-reset:line-count 0"><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token key atrule" style="color:#d73a49">name</span><span class="token punctuation">:</span><span class="token plain"> Build ZMK firmware</span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain"></span><span class="token key atrule" style="color:#d73a49">on</span><span class="token punctuation">:</span><span class="token plain"> </span><span class="token punctuation">[</span><span class="token plain">push</span><span class="token punctuation">,</span><span class="token plain"> pull_request</span><span class="token punctuation">,</span><span class="token plain"> workflow_dispatch</span><span class="token punctuation">]</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain" style="display:inline-block"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain"></span><span class="token key atrule" style="color:#d73a49">jobs</span><span class="token punctuation">:</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">  </span><span class="token key atrule" style="color:#d73a49">build</span><span class="token punctuation">:</span><span class="token plain"></span></span><br></span><span class="token-line theme-code-block-highlighted-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token key atrule" style="color:#d73a49">uses</span><span class="token punctuation">:</span><span class="token plain"> zmkfirmware/zmk/.github/workflows/build</span><span class="token punctuation">-</span><span class="token plain">user</span><span class="token punctuation">-</span><span class="token plain">config.yml@main</span></span><br></span></code></pre></div></div>
<p>Your file's contents should look identical to the above. Replace with the below:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv codeBlockLinesWithNumbering_o6Pm" style="counter-reset:line-count 0"><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token key atrule" style="color:#d73a49">name</span><span class="token punctuation">:</span><span class="token plain"> Build ZMK firmware</span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain"></span><span class="token key atrule" style="color:#d73a49">on</span><span class="token punctuation">:</span><span class="token plain"> </span><span class="token punctuation">[</span><span class="token plain">push</span><span class="token punctuation">,</span><span class="token plain"> pull_request</span><span class="token punctuation">,</span><span class="token plain"> workflow_dispatch</span><span class="token punctuation">]</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain" style="display:inline-block"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain"></span><span class="token key atrule" style="color:#d73a49">jobs</span><span class="token punctuation">:</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">  </span><span class="token key atrule" style="color:#d73a49">build</span><span class="token punctuation">:</span><span class="token plain"></span></span><br></span><span class="token-line theme-code-block-highlighted-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token key atrule" style="color:#d73a49">uses</span><span class="token punctuation">:</span><span class="token plain"> zmkfirmware/zmk/.github/workflows/build</span><span class="token punctuation">-</span><span class="token plain">user</span><span class="token punctuation">-</span><span class="token plain">config.yml@v0.2</span></span><br></span></code></pre></div></div>
<p>The change occurred on the last line.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="version-bumping">Version Bumping<a href="https://zmk.dev/blog/2025/06/20/pinned-zmk#version-bumping" class="hash-link" aria-label="Direct link to Version Bumping" title="Direct link to Version Bumping" translate="no">​</a></h3>
<p>If in the future you wish to upgrade your ZMK's version, simply change the tag in both of these files. For example, change from <code>v0.1</code> to <code>v0.2</code>.</p>]]></content:encoded>
            <category>keyboards</category>
            <category>firmware</category>
            <category>oss</category>
            <category>versioning</category>
        </item>
        <item>
            <title><![CDATA[Contributor Sync February 2025]]></title>
            <link>https://zmk.dev/blog/2025/03/20/contributor-sync-1</link>
            <guid>https://zmk.dev/blog/2025/03/20/contributor-sync-1</guid>
            <pubDate>Thu, 20 Mar 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[On the 26th of February some of the ZMK contributors got together for a contributor sync. In the interest of transparency, it was decided that meeting notes from the sync would be published on the ZMK webpage.]]></description>
            <content:encoded><![CDATA[<p>On the 26th of February some of the ZMK contributors got together for a contributor sync. In the interest of transparency, it was decided that meeting notes from the sync would be published on the ZMK webpage.</p>
<!-- -->
<p>The following contributors were able to attend the sync:</p>
<ul>
<li class=""><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a></li>
<li class=""><a href="https://github.com/caksoylar" target="_blank" rel="noopener noreferrer" class="">caksoylar</a></li>
<li class=""><a href="https://github.com/nmunnich" target="_blank" rel="noopener noreferrer" class="">nmunnich</a></li>
</ul>
<p><a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">joelspadin</a> was also able to comment on the meeting notes after the meeting. The notes have been adjusted accordingly.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="meeting-notes">Meeting Notes<a href="https://zmk.dev/blog/2025/03/20/contributor-sync-1#meeting-notes" class="hash-link" aria-label="Direct link to Meeting Notes" title="Direct link to Meeting Notes" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="meeting-purpose">Meeting Purpose<a href="https://zmk.dev/blog/2025/03/20/contributor-sync-1#meeting-purpose" class="hash-link" aria-label="Direct link to Meeting Purpose" title="Direct link to Meeting Purpose" translate="no">​</a></h3>
<ul>
<li class="">Purpose of meeting is to sync up, discuss blockers, talk about big picture work.</li>
<li class="">Meeting notes should be published on the webpage, while the meetings themselves are private.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="petes-summary">Pete's Summary<a href="https://zmk.dev/blog/2025/03/20/contributor-sync-1#petes-summary" class="hash-link" aria-label="Direct link to Pete's Summary" title="Direct link to Pete's Summary" translate="no">​</a></h3>
<ul>
<li class="">Starting a new job Mon. 2025-03-03. Reduced time for ZMK, but more freedom to work on what Pete wants/ZMK needs.</li>
<li class="">Two main ZMK-contracts need to be finished:
<ul>
<li class="">Pointer work. Basically good to go, just needs 2721 to be tested and verified as as fix. Then ZMK release v0.2 will happen. (This has already happened at time of publishing these notes)</li>
<li class="">Wired split work. Separated into parts:
<ul>
<li class="">UART full duplex, PR 2766. What's there seems very solid, barring some final touchups. Should have v0.2 released prior to merging this. (This has already happened at time of publishing these notes)</li>
<li class="">Half-duplex with a single wire. To be a separate PR, but framework should be good for when that happens. To work on after UART full duplex is merged.</li>
<li class="">Runtime dynamic switching between wired and wireless split using a GPIO as sense pin for wired.</li>
</ul>
</li>
</ul>
</li>
<li class="">After contracts finish, look at versioning again. Better documentation, defaults, workflow improvements, etc.</li>
<li class="">More Studio work is also on the cards. Studio work will continue, but slowly.
<ul>
<li class="">Hoping for help from community around UI/UX, in particular clarity around saving edited keymaps would be good.</li>
<li class="">Want to add runtime property modification next, allowing for e.g. changing hold-tap flavors in Studio.</li>
</ul>
</li>
<li class="">Investigate zmk-cli a bit; Pete has not investigated this enough and wants to get a solid overview of it.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="nicks-summary">Nick's summary:<a href="https://zmk.dev/blog/2025/03/20/contributor-sync-1#nicks-summary" class="hash-link" aria-label="Direct link to Nick's summary:" title="Direct link to Nick's summary:" translate="no">​</a></h3>
<ul>
<li class="">Trying to make combo PR feasible (allows combo triggers inside behaviors, enabling e.g. tap-only combos)
<ul>
<li class="">Adding <code>behavior_state_changed</code> event has a precursor (see 573, 532)
<ul>
<li class="">Requires deleting ZMK_BEHAVIOR_TRANSPARENT</li>
<li class="">Requires some refactoring/investigating of sensors/encoders, as they rely on ZMK_BEHAVIOR_TRANSPARENT</li>
</ul>
</li>
</ul>
</li>
<li class="">Locking PR, needs review. Same with 2811.</li>
<li class="">RP2040-Zero board definition matches upstream, acts as a temporary board definition until we update Zephyr (introduced to Zephyr in 4.1)</li>
<li class="">Parameterised mod-morph and tap-dance
<ul>
<li class="">Question: Do we move hold-tap over to the same system?
<ul>
<li class="">Plan after discussion is to add a second hold-tap <code>compatible</code> and move over to it, to avoid breaking existing keymaps.</li>
</ul>
</li>
</ul>
</li>
<li class="">Config index page and "Customising ZMK" docs overhaul, making them more visible and easier to understand.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="cems-summary">Cem's summary:<a href="https://zmk.dev/blog/2025/03/20/contributor-sync-1#cems-summary" class="hash-link" aria-label="Direct link to Cem's summary:" title="Direct link to Cem's summary:" translate="no">​</a></h3>
<ul>
<li class="">Keymap recipes has been shelved for the time being. Prefer to have better examples in the behavior pages themselves, e.g. timeless homerow mods as an example under hold-tap.</li>
<li class="">Hold-tap page needs overhauling. (This has already happened at time of publishing these notes)</li>
<li class="">New behavior guide needs overhauling and should be aimed towards modules.</li>
<li class="">2758 needs a review and merge. (This has already happened at time of publishing these notes)</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="other-discussion">Other Discussion:<a href="https://zmk.dev/blog/2025/03/20/contributor-sync-1#other-discussion" class="hash-link" aria-label="Direct link to Other Discussion:" title="Direct link to Other Discussion:" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="zmk-cli">ZMK-CLI:<a href="https://zmk.dev/blog/2025/03/20/contributor-sync-1#zmk-cli" class="hash-link" aria-label="Direct link to ZMK-CLI:" title="Direct link to ZMK-CLI:" translate="no">​</a></h4>
<ul>
<li class="">It is likely time to rip the bandaid off and switch over to it, getting rid of the old setup script.</li>
<li class="">CLI has some flaws that may need improvement (e.g. around modules), but is already much better than the existing script.</li>
<li class="">New shield guide should be adjusted to take advantage of ZMK-CLI's templates.</li>
<li class="">Joel requests issues be opened talking about points to improve on.</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="zmk-locales">zmk-locales:<a href="https://zmk.dev/blog/2025/03/20/contributor-sync-1#zmk-locales" class="hash-link" aria-label="Direct link to zmk-locales:" title="Direct link to zmk-locales:" translate="no">​</a></h4>
<ul>
<li class="">Should be moved under zmkfirmware organisation
<ul>
<li class="">Should do the same for zmk-locales-generator, and maybe figure out a way to set up a GH action that makes it send PRs to zmk-locales.
<ul>
<li class="">Move first, make these adjustments afterwards</li>
</ul>
</li>
<li class="">Documenting them in list of keycodes page with a locale selector would be ideal, but complex
<ul>
<li class="">Refer people to headers directly in the docs for the time being</li>
</ul>
</li>
</ul>
</li>
<li class="">Runtime locale changing would be preferred, but would also be a lot of work.
<ul>
<li class="">zmk-locales could be viewed as a (semi-permanent) bandaid until such a time</li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="modules">Modules:<a href="https://zmk.dev/blog/2025/03/20/contributor-sync-1#modules" class="hash-link" aria-label="Direct link to Modules:" title="Direct link to Modules:" translate="no">​</a></h4>
<ul>
<li class="">Need to find the right balance between overloading contributers and overfragmentation</li>
<li class="">ZMK module collection <a href="https://github.com/nmunnich/zmk-module-collection" target="_blank" rel="noopener noreferrer" class="">https://github.com/nmunnich/zmk-module-collection</a> seems like a good way to go forward
<ul>
<li class="">Main concerns:
<ul>
<li class="">Need to handle breaking changes elegantly, informing users <em>which</em> module is to blame for the new version not working</li>
<li class="">Need to have tests for modules (can assume keyboard works if it builds, what about other stuff?)</li>
<li class="">Maintainability
<ul>
<li class="">Hopefully have more volunteers from the community to look at modules and verify them, should be much easier than reviewing PRs</li>
<li class="">Automated tests</li>
<li class="">Add an "experimental" group tag for unverified modules</li>
</ul>
</li>
</ul>
</li>
<li class="">Despite concerns, plenty of upsides. Seems like the best way forwards, and it is worth putting more time into.</li>
<li class="">Some upsides:
<ul>
<li class="">Very easy for users to add modules, particularly ones that depend on other modules</li>
<li class="">Automated testing and notification for module owners</li>
<li class="">Better discoverability</li>
<li class="">Versioning parity between the collection and ZMK itself to allow for easy upgrades</li>
</ul>
</li>
<li class="">Likely will want to introduce "RC" releases, to allow module owners the time to fix any issues with their module before an actual release</li>
<li class="">Likely will only accept keyboards and drivers initially, until better tooling and systems are in place, given they are easier to validate</li>
</ul>
</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="minor-notes">Minor notes:<a href="https://zmk.dev/blog/2025/03/20/contributor-sync-1#minor-notes" class="hash-link" aria-label="Direct link to Minor notes:" title="Direct link to Minor notes:" translate="no">​</a></h4>
<ul>
<li class="">Documenting BLE tests would be useful</li>
<li class="">Need new display and lighting systems at some point</li>
<li class="">Zephyr upgrade was not discussed in this meeting</li>
<li class="">Would be good to give some extra priority to PRs from new contributors, to help motivate them.</li>
<li class="">Would be nice to have another SOTF at some point. Doing a full commit overview is unfeasible at this point, but touching on the major issues seems doable.</li>
</ul>]]></content:encoded>
            <category>sync</category>
            <category>keyboards</category>
            <category>firmware</category>
            <category>oss</category>
            <category>ble</category>
        </item>
        <item>
            <title><![CDATA[ZMK Studio MVP General Availability]]></title>
            <link>https://zmk.dev/blog/2024/11/11/zmk-studio-mvp-ga</link>
            <guid>https://zmk.dev/blog/2024/11/11/zmk-studio-mvp-ga</guid>
            <pubDate>Mon, 11 Nov 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[I'm delighted to announce that after many months of work, the ZMK Studio Minimum Viable Product (MVP) has reached General Availability (GA) status. I'm very excited with the feature set and foundation we've gotten into this first release, and equally excited for the upcoming work to add even more features.]]></description>
            <content:encoded><![CDATA[<p>I'm delighted to announce that after many months of work, the ZMK Studio Minimum Viable Product (MVP) has reached General Availability (GA) status. I'm very excited with the feature set and foundation we've gotten into this first release, and equally excited for the upcoming work to add even more features.</p>
<p>ZMK Studio provides runtime keymap functionality for ZMK powered devices, allowing you to make changes without the need to flash new firmware. It is a combination of major firmware enhancements paired with a new frontend application for interacting with your keyboard.</p>
<p>The app is available for compatible browsers, and as an installable desktop application for Linux, macOS, and Windows.</p>
<img src="https://zmk.dev/assets/images/zmk-studio-screenshot-9f487364ec289231696fb0f3a6166146.png" alt="ZMK Studio Application" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="https://zmk.dev/assets/images/zmk-studio-screenshot-dark-mode-ab62f5b9ecb16a3b64a96487793a4eab.png" alt="ZMK Studio Application" class="themedComponent_mlkZ themedComponent--dark_xIcU">
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="gratitude">Gratitude<a href="https://zmk.dev/blog/2024/11/11/zmk-studio-mvp-ga#gratitude" class="hash-link" aria-label="Direct link to Gratitude" title="Direct link to Gratitude" translate="no">​</a></h2>
<p>I'm extremely grateful for everyone who has helped make this release possible, which includes testers, code reviewers/contributors, including <a href="https://github.com/Nick-Munnich" target="_blank" rel="noopener noreferrer" class="">Nick-Munnich</a>, <a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">joelspadin</a>, and <a href="https://github.com/caksoylar" target="_blank" rel="noopener noreferrer" class="">caksoylar</a>, as well as the collection of vendors who have directly sponsored my work on the project, allowing it to come to fruition <em>much</em> faster than it would have taken me to do in my spare time.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="vendor-sponsors">Vendor Sponsors<a href="https://zmk.dev/blog/2024/11/11/zmk-studio-mvp-ga#vendor-sponsors" class="hash-link" aria-label="Direct link to Vendor Sponsors" title="Direct link to Vendor Sponsors" translate="no">​</a></h3>
<p>The following sponsors were instrumental in making ZMK Studio possible by sponsoring my work on the firmware and frontend application:</p>
<div><h4>Platinum<!-- --> Level</h4><div style="display:grid;grid-template-columns:repeat(auto-fit, minmax(250px, 1fr));place-items:center;gap:2em 2em"><a href="https://typeractive.xyz/"><img src="data:image/png;base64,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" alt="nice!keyboards / typeractive" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="data:image/png;base64,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" alt="nice!keyboards / typeractive" class="themedComponent_mlkZ themedComponent--dark_xIcU"></a><a href="https://kinesis-ergo.com/"><img src="data:image/png;base64,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" alt="Kinesis" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="data:image/png;base64,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" alt="Kinesis" class="themedComponent_mlkZ themedComponent--dark_xIcU"></a></div></div><div><h4>Gold+<!-- --> Level</h4><div style="display:grid;grid-template-columns:repeat(auto-fit, minmax(250px, 1fr));place-items:center;gap:2em 2em"><a href="https://cannonkeys.com/"><img src="data:image/png;base64,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" alt="CannonKeys" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAVEAAABMCAMAAADjl3SBAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAJcEhZcwAAG9sAABvbAYX6YjkAAAAHdElNRQfoCwsTACi9xzCMAAADAFBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8HPQsIAAAA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" alt="CannonKeys" class="themedComponent_mlkZ themedComponent--dark_xIcU"></a><a href="https://keychron.com/"><img src="data:image/png;base64,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" alt="Keychron" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="data:image/png;base64,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xddlvhqOJJDjLfKZ85JmcZBrsI+tcqPDFWisQCeXWqjUqFQHUWxs/Uq5LT6N7gVXiRf7g61ecKb9NdVUW709bJNZDvvaOOq5yueWuMLBmmusla7uVOy9hIx+ZRwpMRlLrTFIjtSyZ5VabZpJpllpkzdcFGmUKs//wHt4QH2Zf+VlqVLvmGyyBdYrNiEyzZKqdFEGHCNtT8GxUb8M/c5zlqlKLfOySWb4xDp/TEhGSNgdv6kJxzgj5KrpJ0juMSJy0qm08E51pye96GnjDNK2+rY+vm7+ltWR/ZHxN4A6utQjnvOC/3GdoyttHUEjV0aGdpUnTzA6voWe4xy3Oziz9aKVs4z1lBdMdIvelfZnCIKO7jRQ9bVnhHFfykeRwZOQK7/mA0RBcI0dfpW+XGdou0HKEr8Hz8mXO7FL+SyvetthD23/HXzdguBgi72v4x7si7+bx/wf5JAz+V6iDf13/cRVkKufcYq8EXnTvusnaPWMs9O8aD+abemvGzIwy3BGQ0sAAADQZVhJZklJKgAIAAAACgAAAQQAAQAAAOMAAAABAQQAAQAAAIAAAAACAQMAAwAAAIYAAAASAQMAAQAAAAEAAAAaAQUAAQAAAIwAAAAbAQUAAQAAAJQAAAAoAQMAAQAAAAMAAAAxAQIADQAAAJwAAAAyAQIAFAAAAKoAAABphwQAAQAAAL4AAAAAAAAACAAIAAgABwAAAAEAAAAHAAAAAQAAAEdJTVAgMi4xMC4zOAAAMjAyNDowODowNyAwOTo1NTozNgABAAGgAwABAAAAAQAAAAAAAAAAwMasAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDI0LTExLTA5VDIzOjA3OjM2KzAwOjAwbOTB8QAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyNC0xMS0wOVQyMzowNzozNiswMDowMB25eU0AAAAodEVYdGRhdGU6dGltZXN0YW1wADIwMjQtMTEtMTFUMTk6MDE6NTQrMDA6MDCkySeKAAAAGnRFWHRleGlmOkJpdHNQZXJTYW1wbGUAOCwgOCwgOBLtPicAAAARdEVYdGV4aWY6Q29sb3JTcGFjZQAxD5sCSQAAACF0RVh0ZXhpZjpEYXRlVGltZQAyMDI0OjA4OjA3IDA5OjU1OjM2WQ3q7AAAABN0RVh0ZXhpZjpFeGlmT2Zmc2V0ADE5MEyO88IAAAAUdEVYdGV4aWY6SW1hZ2VMZW5ndGgAMTI4QXTDtQAAABN0RVh0ZXhpZjpJbWFnZVdpZHRoADIyNwDxcPAAAAAadEVYdGV4aWY6U29mdHdhcmUAR0lNUCAyLjEwLjM4EdA/sQAAABt0RVh0aWNjOmNvcHlyaWdodABQdWJsaWMgRG9tYWlutpExWwAAACJ0RVh0aWNjOmRlc2NyaXB0aW9uAEdJTVAgYnVpbHQtaW4gc1JHQkxnQRMAAAAVdEVYdGljYzptYW51ZmFjdHVyZXIAR0lNUEyekMoAAAAOdEVYdGljYzptb2RlbABzUkdCW2BJQwAAAABJRU5ErkJggg==" alt="Keychron" class="themedComponent_mlkZ themedComponent--dark_xIcU"></a></div></div><div><h4>Gold<!-- --> Level</h4><div style="display:grid;grid-template-columns:repeat(auto-fit, minmax(250px, 1fr));place-items:center;gap:2em 2em"><a href="https://littlekeyboards.com/"><img src="data:image/avif;base64,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" alt="Little Keyboards" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="data:image/avif;base64,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" alt="Little Keyboards" class="themedComponent_mlkZ themedComponent--dark_xIcU"></a><a href="https://keebmaker.com/"><img src="https://zmk.dev/assets/images/keebmaker-b4c79daba92a13cb4986a01ec7e5436d.png" alt="Keebmaker" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="https://zmk.dev/assets/images/keebmaker-dark-mode-f02093566f7597eea0fb201e771e2368.png" alt="Keebmaker" class="themedComponent_mlkZ themedComponent--dark_xIcU"></a></div></div><div><h4>Silver<!-- --> Level</h4><div style="display:grid;grid-template-columns:repeat(auto-fit, minmax(250px, 1fr));place-items:center;gap:2em 2em"><a href="https://keeb.io/"><img src="data:image/avif;base64,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" alt="keeb.io" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="data:image/avif;base64,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" alt="keeb.io" class="themedComponent_mlkZ themedComponent--dark_xIcU"></a><a href="https://modedesigns.com/"><img src="data:image/png;base64,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" alt="Mode Designs" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUIAAABMCAMAAAAvDk5qAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAJcEhZcwAAh6kAAIepAQJ4iFsAAAAHdElNRQfoCwsTAS5Nv6T4AAAC/VBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+G1NxwAAAA/nRS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" alt="Mode Designs" class="themedComponent_mlkZ themedComponent--dark_xIcU"></a></div></div><div><h4>Bronze<!-- --> Level</h4><div style="display:grid;grid-template-columns:repeat(auto-fit, minmax(250px, 1fr));place-items:center;gap:2em 2em"><a href="https://deskhero.ca/"><img src="https://zmk.dev/assets/images/deskhero-e828da28e37a0f24c2ad89adb649d2fc.webp" alt="deskhero" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="https://zmk.dev/assets/images/deskhero-dark-mode-eecd26126b7b26165cffef6834f37fbf.webp" alt="deskhero" class="themedComponent_mlkZ themedComponent--dark_xIcU"></a><a href="https://phasebyte.com/"><img src="data:image/png;base64,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aqelQKciMmEVU90KI6c1C6wXCapAhcWyOFUwKAJM4ksG0kk2jiyvA8W+1AR4RUIce7Dgl+OCZjEOSM4kz7aAehUmx3AazvRAoU3A/QwxOwPm+7sYxBu5p568pzlCIIYb4FGkERUwx+2VCBo/SqiNSWc3Qae8hEYuxgEaA1A6/gF8awwsqDosVHU+rMwStOEdWNS9pGM5hVDXBYhRvk6enwLFu7VJTls70q4x6K/LELecj6VzHvq2Ixs0Tq1MoioPR3ESdgrA0Adt0byN1i6hgYfmIDaHm+hFjPsSGBEjYbxlm/B7Oizru3Ck06E1hC0AtwE6RS1EGDKtznhys9CyScpQJvhIjeHdaUj9yZROerFZtTzLrA+iyMbNwHvSI9xXG0r5ShNXyOluZk0Xo+avRb9n8ck1IIp223WLbBAssIANMe5aZe94p2K7vd0uWj4LD+U3CCNmruCj07rbHdFmaMSjHXaeKZaKV9sBnH8l9DSepy30p6leHL4Xj4b6gEueMhFdBUs/BF36xMN+MzMB3GpBV2jsAy7hgGvA3DIbYfgcf0TsnkcDjsepeUthkSxFCKOBD7jEjkXhq2UBJGKuwZGVbbmhc7he/wMwzRCF5Tg9YgAAANBlWElmSUkqAAgAAAAKAAABBAABAAAADgIAAAEBBAABAAAAAAEAAAIBAwADAAAAhgAAABIBAwABAAAAAQAAABoBBQABAAAAjAAAABsBBQABAAAAlAAAACgBAwABAAAAAwAAADEBAgANAAAAnAAAADIBAgAUAAAAqgAAAGmHBAABAAAAvgAAAAAAAAAIAAgACAB2AAAAAQAAAHYAAAABAAAAR0lNUCAyLjEwLjM4AAAyMDI0OjA4OjA3IDEzOjEzOjQ0AAEAAaADAAEAAAABAAAAAAAAAKfNXsAAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjQtMTEtMDlUMjM6MDc6MzYrMDA6MDBs5MHxAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDI0LTExLTA5VDIzOjA3OjM2KzAwOjAwHbl5TQAAACh0RVh0ZGF0ZTp0aW1lc3RhbXAAMjAyNC0xMS0xMVQxOTowMDo1NyswMDowMHrjVikAAAAadEVYdGV4aWY6Qml0c1BlclNhbXBsZQA4LCA4LCA4Eu0+JwAAABF0RVh0ZXhpZjpDb2xvclNwYWNlADEPmwJJAAAAIXRFWHRleGlmOkRhdGVUaW1lADIwMjQ6MDg6MDcgMTM6MTM6NDRAc7vLAAAAE3RFWHRleGlmOkV4aWZPZmZzZXQAMTkwTI7zwgAAABR0RVh0ZXhpZjpJbWFnZUxlbmd0aAAyNTbry8YsAAAAE3RFWHRleGlmOkltYWdlV2lkdGgANTI2crlW4wAAABp0RVh0ZXhpZjpTb2Z0d2FyZQBHSU1QIDIuMTAuMzgR0D+xAAAAG3RFWHRpY2M6Y29weXJpZ2h0AFB1YmxpYyBEb21haW62kTFbAAAAInRFWHRpY2M6ZGVzY3JpcHRpb24AR0lNUCBidWlsdC1pbiBzUkdCTGdBEwAAABV0RVh0aWNjOm1hbnVmYWN0dXJlcgBHSU1QTJ6QygAAAA50RVh0aWNjOm1vZGVsAHNSR0JbYElDAAAAAElFTkSuQmCC" alt="PhaseByte" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="data:image/png;base64,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aqelQKciMmEVU90KI6c1C6wXCapAhcWyOFUwKAJM4ksG0kk2jiyvA8W+1AR4RUIce7Dgl+OCZjEOSM4kz7aAehUmx3AazvRAoU3A/QwxOwPm+7sYxBu5p568pzlCIIYb4FGkERUwx+2VCBo/SqiNSWc3Qae8hEYuxgEaA1A6/gF8awwsqDosVHU+rMwStOEdWNS9pGM5hVDXBYhRvk6enwLFu7VJTls70q4x6K/LELecj6VzHvq2Ixs0Tq1MoioPR3ESdgrA0Adt0byN1i6hgYfmIDaHm+hFjPsSGBEjYbxlm/B7Oizru3Ck06E1hC0AtwE6RS1EGDKtznhys9CyScpQJvhIjeHdaUj9yZROerFZtTzLrA+iyMbNwHvSI9xXG0r5ShNXyOluZk0Xo+avRb9n8ck1IIp223WLbBAssIANMe5aZe94p2K7vd0uWj4LD+U3CCNmruCj07rbHdFmaMSjHXaeKZaKV9sBnH8l9DSepy30p6leHL4Xj4b6gEueMhFdBUs/BF36xMN+MzMB3GpBV2jsAy7hgGvA3DIbYfgcf0TsnkcDjsepeUthkSxFCKOBD7jEjkXhq2UBJGKuwZGVbbmhc7he/wMwzRCF5Tg9YgAAANBlWElmSUkqAAgAAAAKAAABBAABAAAADgIAAAEBBAABAAAAAAEAAAIBAwADAAAAhgAAABIBAwABAAAAAQAAABoBBQABAAAAjAAAABsBBQABAAAAlAAAACgBAwABAAAAAwAAADEBAgANAAAAnAAAADIBAgAUAAAAqgAAAGmHBAABAAAAvgAAAAAAAAAIAAgACAB2AAAAAQAAAHYAAAABAAAAR0lNUCAyLjEwLjM4AAAyMDI0OjA4OjA3IDEzOjEzOjQ0AAEAAaADAAEAAAABAAAAAAAAAKfNXsAAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjQtMTEtMDlUMjM6MDc6MzYrMDA6MDBs5MHxAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDI0LTExLTA5VDIzOjA3OjM2KzAwOjAwHbl5TQAAACh0RVh0ZGF0ZTp0aW1lc3RhbXAAMjAyNC0xMS0xMVQxOTowMDo1NyswMDowMHrjVikAAAAadEVYdGV4aWY6Qml0c1BlclNhbXBsZQA4LCA4LCA4Eu0+JwAAABF0RVh0ZXhpZjpDb2xvclNwYWNlADEPmwJJAAAAIXRFWHRleGlmOkRhdGVUaW1lADIwMjQ6MDg6MDcgMTM6MTM6NDRAc7vLAAAAE3RFWHRleGlmOkV4aWZPZmZzZXQAMTkwTI7zwgAAABR0RVh0ZXhpZjpJbWFnZUxlbmd0aAAyNTbry8YsAAAAE3RFWHRleGlmOkltYWdlV2lkdGgANTI2crlW4wAAABp0RVh0ZXhpZjpTb2Z0d2FyZQBHSU1QIDIuMTAuMzgR0D+xAAAAG3RFWHRpY2M6Y29weXJpZ2h0AFB1YmxpYyBEb21haW62kTFbAAAAInRFWHRpY2M6ZGVzY3JpcHRpb24AR0lNUCBidWlsdC1pbiBzUkdCTGdBEwAAABV0RVh0aWNjOm1hbnVmYWN0dXJlcgBHSU1QTJ6QygAAAA50RVh0aWNjOm1vZGVsAHNSR0JbYElDAAAAAElFTkSuQmCC" alt="PhaseByte" class="themedComponent_mlkZ themedComponent--dark_xIcU"></a><a href="https://mechlovin.studio/"><img src="data:image/png;base64,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" alt="Mechlovin'" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="data:image/png;base64,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" alt="Mechlovin'" class="themedComponent_mlkZ themedComponent--dark_xIcU"></a></div></div><div><h4>Additional<!-- --> Level</h4><div style="display:grid;grid-template-columns:repeat(auto-fit, minmax(250px, 1fr));place-items:center;gap:2em 2em"><a href="https://splitkb.com/"><img src="data:image/png;base64,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LTExLTA5VDIzOjA3OjM2KzAwOjAwbOTB8QAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyNC0xMS0wOVQyMzowNzozNiswMDowMB25eU0AAAAodEVYdGRhdGU6dGltZXN0YW1wADIwMjQtMTEtMTFUMTk6MDA6MTgrMDA6MDAI4Sg6AAAAGnRFWHRleGlmOkJpdHNQZXJTYW1wbGUAOCwgOCwgOBLtPicAAAARdEVYdGV4aWY6Q29sb3JTcGFjZQAxD5sCSQAAACB0RVh0ZXhpZjpDb21wb25lbnRzQ29uZmlndXJhdGlvbgAuLi5q8qFkAAAAIXRFWHRleGlmOkRhdGVUaW1lADIwMjQ6MDg6MDcgMTA6NTM6MzjC7N16AAAAE3RFWHRleGlmOkV4aWZPZmZzZXQAMjAycQSX/gAAABV0RVh0ZXhpZjpFeGlmVmVyc2lvbgAwMjEwuHZWeAAAABl0RVh0ZXhpZjpGbGFzaFBpeFZlcnNpb24AMDEwMBLUKKwAAAAUdEVYdGV4aWY6SW1hZ2VMZW5ndGgAMzIwTCuf6QAAABR0RVh0ZXhpZjpJbWFnZVdpZHRoADE3OTYq+DnzAAAAGXRFWHRleGlmOlBpeGVsWERpbWVuc2lvbgAxNzk2+nD4fQAAABh0RVh0ZXhpZjpQaXhlbFlEaW1lbnNpb24AMzIw6o8X9wAAABp0RVh0ZXhpZjpTb2Z0d2FyZQBHSU1QIDIuMTAuMzgR0D+xAAAAF3RFWHRleGlmOllDYkNyUG9zaXRpb25pbmcAMawPgGMAAAAbdEVYdGljYzpjb3B5cmlnaHQAUHVibGljIERvbWFpbraRMVsAAAAidEVYdGljYzpkZXNjcmlwdGlvbgBHSU1QIGJ1aWx0LWluIHNSR0JMZ0ETAAAAFXRFWHRpY2M6bWFudWZhY3R1cmVyAEdJTVBMnpDKAAAADnRFWHRpY2M6bW9kZWwAc1JHQltgSUMAAAAASUVORK5CYII=" alt="splitkb.com" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="data:image/png;base64,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TpRUbaRal0aSqVIbuoq7VpJvx/SnS5tgYDBNjZW6IJGkryOmkvrP8VV/xibOC8cqkkgiibCKJJISxmpqhFUkkURYRRJJxmM1JcIqkkgirCKJJOOxeiDCKpJI0o3V/RFWkUQSYRVJJBmP1X0RVpFEEmEVSSQZj9XkCKtIIomwiiSSjMdqUoRVJJFEWEUSSTHI/wGKY7fD5YO0UQAAAQxlWElmSUkqAAgAAAALAAABBAABAAAABAcAAAEBBAABAAAAQAEAAAIBAwADAAAAkgAAABIBAwABAAAAAQAAABoBBQABAAAAmAAAABsBBQABAAAAoAAAACgBAwABAAAAAgAAADEBAgANAAAAqAAAADIBAgAUAAAAtgAAABMCAwABAAAAAQAAAGmHBAABAAAAygAAAAAAAAAIAAgACABIAAAAAQAAAEgAAAABAAAAR0lNUCAyLjEwLjM2AAAyMDI0OjAxOjI5IDExOjUwOjQ2AAUAAJAHAAQAAAAwMjEwAZEHAAQAAAABAgMAAKAHAAQAAAAwMTAwAqAEAAEAAAAEBwAAA6AEAAEAAABAAQAAAAAAAKQnlQAAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjQtMTEtMDlUMjM6MDc6MzYrMDA6MDBs5MHxAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDI0LTExLTA5VDIzOjA3OjM2KzAwOjAwHbl5TQAAACh0RVh0ZGF0ZTp0aW1lc3RhbXAAMjAyNC0xMS0xMVQxOTowMDoyMiswMDowMCIecJcAAAAadEVYdGV4aWY6Qml0c1BlclNhbXBsZQA4LCA4LCA4Eu0+JwAAACB0RVh0ZXhpZjpDb21wb25lbnRzQ29uZmlndXJhdGlvbgAuLi5q8qFkAAAAIXRFWHRleGlmOkRhdGVUaW1lADIwMjQ6MDE6MjkgMTE6NTA6NDYf50F6AAAAE3RFWHRleGlmOkV4aWZPZmZzZXQAMjAycQSX/gAAABV0RVh0ZXhpZjpFeGlmVmVyc2lvbgAwMjEwuHZWeAAAABl0RVh0ZXhpZjpGbGFzaFBpeFZlcnNpb24AMDEwMBLUKKwAAAAUdEVYdGV4aWY6SW1hZ2VMZW5ndGgAMzIwTCuf6QAAABR0RVh0ZXhpZjpJbWFnZVdpZHRoADE3OTYq+DnzAAAAGXRFWHRleGlmOlBpeGVsWERpbWVuc2lvbgAxNzk2+nD4fQAAABh0RVh0ZXhpZjpQaXhlbFlEaW1lbnNpb24AMzIw6o8X9wAAABp0RVh0ZXhpZjpTb2Z0d2FyZQBHSU1QIDIuMTAuMzb2aBK2AAAAF3RFWHRleGlmOllDYkNyUG9zaXRpb25pbmcAMawPgGMAAAARdEVYdGljYzpjb3B5cmlnaHQAQ0Mw/dRWLQAAABR0RVh0aWNjOmRlc2NyaXB0aW9uAGMyY2n/CvdeAAAAAElFTkSuQmCC" alt="splitkb.com" class="themedComponent_mlkZ themedComponent--dark_xIcU"></a><a href="https://keycapsss.com/"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUUAAABMCAYAAAD6DKUhAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAJcEhZcwAAJ7MAACezAY7L3XMAAAAHdElNRQfoCwsTADHZrJhMAAAABmJLR0QA/wD/AP+gvaeTAAAk8klEQVR42u1dCbxV0/7f507doXlQaaBCSTQJaUTCiwpRHi/Dy5P8K0lz99xKKEUh0yM8Y2YRHg/1MmWIpFSiutEtDbc7drvjeWu73/Xv18/a5+y9z97n3ljr8/l96p59zh7W/q3vb/4tw9BDDz300EMPPfTQQ4/wI3SzoFsFZWjSFCNKB00SdLugIDs+XdAd+P9UcnyGz6S61yCjWNzHH5GCESjW/DfDChBNMBwvaGKi+HI3QecLOk+TJh+pn2DK5kZolsl3EhQbiM/PAv+Zxxsbodni85mC5pvH24nPBwlGvthfyrhE0JDDKSg+Dw4+RBkDxXcv1OSILhJzN4jMo/l/8XlwwCHKuCBG/NdLXK9mJTiOtgLF31DcvKktgrIF7dOkyWdaAiA0+c8UyPME7QX/CQouFtpiCo4LAM34QFCBoPwYkHmdQpC8Zh6hXEE5mhxRLpvDPHy+n1AssMe8xi5BN1daIkpQ/IdRKZEzrhZULCikSVMMaJWgo2Ge1qgESXo8KEAwvTbMndaC1ug50+QhCSF8pxUovi81xSbiizcJmqNJk880W/BbfyM0OcEITRO8d5XJf13F5+mC5gqaKf7uLfgyUOlPNL8XFCZ1xgTx2USfaJI4/+TDKThdUPohyhB/z9DknjLEHN5GaDb4Ye4hCprkM/8FJ1e6Y9KtQNEgTlDTf3OfoAc0afKJHoRlEkQAxQyo3IK/78R3aHBjWgwDLTrA4i/dJuhxQYtBj+J9LwKZ/7+f/N8vuu3QOw0fgZ4EmqxJk880HcBIon+/Ac4EQVPAsJN1VsgfJrvFBMRxeLfVgf+AdXrooYceeuihhx566KGHHnrooYceeuihhx566KGHHnr4P+oLaiwowD43/z5KUCPFsWhHgqBUi2PxMaY4zQJ66KGHHCcKWipohaD+7FgvQR8I+o+gbh5e82hB8wQ9J+h08nlTQSK70lgcY3pMkCjzMdLIvdQQdI0gUYRrtGP3X1vQXwR19khY1BR0naARguo4/G0SftMQ81cP91RL0EmCLhH0f4JE8p9hJmmZeQmjBF2Ed1+7GvGiKSRvEDRH0PEenjdFUD9B5wlKZoL5fPBchg2aSubuBMyxH6M23t3Fgm7CdeX1zb8HC2rvglfsjHjwkrnerxAkOscY0wnvjMA8tgqj1ER7fVNJ6ypoqOL65jq9QFAbtl49HTfLdG5BT7Jj95NjGR5dL1HQXeS8zxBgGSOoghyLJeUJ6kPu02TKH3HsOQCXHCMF5Qj6VlAnD+bkr4JyBR0QdKXNOewIBnlE0HJBGwVl4v8iI994R9AOPFcJmddyQcW43i+C3hMkiuGNDtVAYzbnPxv3uRiA79V5swTtFjQW82eOUwVtdcAjFWTufsYcj4VwiVY4xuGdmgv/fYt3R6+/AwrLJPwu3gPBcRbW5peYqwJBZez5Dwraj3l7GSB5jAfvyBRWvQWJ4mRjlaBfI1x/m6DXsRZbe82I6eSir7JjT5Jj8zzSikzpt4885J2EKe6uIkAMgQm6k/s0X/TXOGYC4ACLObsvSoZsAGCS55sSQYqeAc12KwDOq+c3BYBoYWO0qCJAjGNC+BcPrZOryHlzIHzN6/XAAotm3kwe3gRB1NLl/bXBOtji8h62AMzauJx3k++fFrRHce6DAOE8/J8fL8E6GQMrxekIQDg9DiC0ur5JRYrjJmiuhWBv6BUzTg8Dik+QY3d5AIrHCfqCnPO/hJGsQNGUCPcImgHG84NMLXggTGY+N+VkbqS22A2LVt5flyjmZBg0RPNcexUuDGpSifIPY7vNhWLe9wZoXCbQ3ijoepjS5nOJeivjMyKg5AL/LyR2rMfxuF/6DEGPBPHfmAWSAw2vHjSdfwEUngpDz0Iz+lDQD9Boy9ncfSToHAf3bPL8IEFfsfOY4LRS0CJogiNhFZjAcxssl/XQpOh8rYI7wK7Gb5r/4xhP5UNTvA+ugssEXQi6HJ8tFPQp5lH+ztRgX4SF5cRdMooJgwKA7APg1cvJ9S8DH9+Duc4mvyuF5tjpSALFFDyoZM6d8E0YEUCxEBpMGpEsXpPVaAuzNASN4iLix3uAzU2CizkxfUJvk/O8aOGnqQNNvYgtnh/DgGQhQNDKBK0BydoHTJ5JfrsRfptYjpHMVAphcTb1ARSpxpiEuUiJQKkQinUFNcO8mcL0c3bf5gIfYtgLNN6AdcA1vu4A7CQLzSoV9zAEQJ1HzrEd7piAjeDqAsJTRYgtXIKga2IE901D+NWXAEjl9U2wPM2m3/ROAuzFWAtD8c6TIsxdfSgQTzFw/gqxkCMCFK8kL68E1423AMVyMMtBssAzfHLsRpLkM4hG8AoJTJwBv45k5lNcnP9SMic5FkCUBkAsZqbuZEj5X5imsJL8vdKmSSfN8qXkWTfEUGOsi2BeiPnQCuHs9woUK2CiFZE5Hx0BACKNFtDgM5l1c24Ek/FaoqWbfP4CzEinft1aAMH15PpZcFNZjTRoW6UESG/EezBcBAmvFrSZ8WGHCArS7YSnsxDbqG+4C86Z1tb35PrfRGm9xQQU2yMoIc/1psL+p6BYBiC4mwDjAZi6NWMMjO3gM5LBmEFEW3yQPNNch75FU/t7g/z+JcWzxWHRHiDC4t9YPMdDS5G//xD32plot+XQBpJt3lMTmJISGD/xw4mtGOcT394SEuAKASzSPATFBwAIB5nGWCPKa5gguI7c9ydhAhA9WYAnkwX53AxTqK0m5/wujKAeSXjKpI8VGRZOR3/23l4O42MczrTbr1wqFXT0ZsD4llGZTlgtQTENfi15nq1wcBthQLEcmlAtpGcUMWBMjbG2OJvc/+tEWzwTUi4ESXmSw4BTLn6bS0xzOrowRjM1ueYAX+pq+JZJxuuJWZINk8iJ5vM+MdHnR6lJGTYi6VK47IDps4A82y6b5phd83k2BNICBoxjPXjOgQjYSR6eptD8akMAcv/vavjNoskAOI9YLyH4jVMUQv57xfU/A7AHonSBHCDm+EjFd1qTACZ1BX3twfMPJ6a8aXHc4vZ5/AbFEeRGiyCVAzZAcSpRz2fBlJLAOEPxsv0cJxNw4triY2SOZhr289BeY/NeW2HS3sf8fB1xrDNSQqRj/EqFIKLv7guHkcm+ZHH9As3U8DFP9ifiU01ETuFecv+3eQiKdxBNfSEx4bwwpRMhROS1NiGfkY4BREsqZhFdU8BOdGnGyjWUTszi3QoXSAaL7BYzf+SYKPIv6zLAX4WcZDomEEukiPlj5fPXiSLf919MWTi2uoFiJ2LKyZzEOmFeqAoUDTheV7MgwowYmtJxLLdyKWGcniSV4HsEZyKNi5gvcVAEs70czCLHNLLwllokYHOXxSIHZnQ8S4+Z5ePcjsPzHUSkUfrJ3iHXXw0N2UtQ5HMsg2ljozSl2xL/XgmSrem8UiFqCsbxzC9cjODBCS6v35JpYvOZe+RLcuwJRPhpKk4RNMxWUZjRe8m5hrDgzkeEp++GmyzHw+fvSYJXJfB3VhtQNMHvefL7dRGcr+FAsSHUe6pyS1M6LUbA2Jk403NQVWAAaJ4gZsDUCPOUBn+LfI43LCTzECLxf4K2Kq/3FklDCJfsfSUDXydBi3PIbz+IUgAFwuRoLrfQKq4nWkSRzaR2p6DYBr43VVQ6MYpnnc18xSkElNaQxT+UmL2fs/uQ5mxclNdfjnmW73QfsXjOxvmHsEBNiKRmBVxoa+8bh+fxytED7hCZfdIF83wNcxPJKLab509mvvrF1QkURxPTIA+MaXgAimVE/T4AcyAWpnQi83W9TrTes4gv6bsIwYkLSH5VQRh/H00Q/zfR8o4lGuAulEMZYSJziwggfOPAod6CaOcbbWrAqusPh/mrui41JYOKhOZ1zHGf6jEoHkdAkfJVtKb0BeS5viEBl9OJW2IT45N2yD8sYQnsY10IpIuIb28zXBTSlUVBpzHzXy9juZfb4BdMdQjKM8k5lhHevYKcfxlTBnpA+FZ48PwTyTk+cOMO8AMUuxM/UQiO9BSPQHEb/AZ5LF0nFhpjV6It5iGlxsCzPUEW16QwILGEMUxdi7lYYFF+2YFI1R9sgFwrpmU/ZnOumpHf/eIy2DGERJWfZuY79cf+TPyldA7ms4BLdx9BcQPeTRExpUe7LDVsT1JUfoVJZzBf6TYIBZrfWg/rcTeziP7p0Jw9lZjkO0kQ7hYWne7FNLEmCnO2AK6U5g7nW/5+BYlC/4Npwh0ZprTAtfKjfP5LmF+zcVWDYkOmvq6y6eS3C4obYcpOJcEX6WNMi4G2eB9LLZKgdjZh5jUWL7E/MV8KiA9NNRf0Og+TYx1JBcB6m40TBpHFmG/DzxJAFUwxeZ7WLpL1n2f+qxoM3LeSY8kW/iHq77rTZXTSDiiuQvbAPeS595MEb8Nh5dZ65lIxMIerWWBhOktdSYCwVZmzfW1evzHyPsuRqtWMaLB7WSbIGEUjlOtYlUkFznemzeufDuWhBHycSAJ4u8g5N8KnXJvxzY2KooSVDp6/I4RSKQRvclWCYhxSaaQJsAdpCoaHoCgjeskwMQtjnOBNk7ap+ZuMUjCpLY5TaInPkPl8J0yyqtegmIg8ygqb/t1+RNMohNnlRqveQaT9Zez4JNxPLvHPGorE5FfJPKxx2XzADih+AZ9mbRaV3o9yswSHPJJF7vsmls+4hQUWnlNo/F0gdMuYOXuDTXdRe/hhT2Ta+RiyZiQPP2QcnuQfgD9xBTNnN8P/V8MGv/WCz7QJ+/x6koom/cVPMMUpACXjY0XJr53nT4BVMYwIhCoDxb5kMZUhaz3BB1BsS6TKdJau47cpnYjONNQErk3AZB8pUWvBAhdUSxwWYS68BEUD5s9ycs6nLTIBjoFWIr/3uMsgS5BZC02YmfYx0QDqRwC0oiijiXZBsRkJEi5gwOjElKbdnvKZhtMBbg9elvmFom65CbRjbs4+GEXziaEMFGlApqeCFx5kid65mJujXV7/QgaKNNmd1423wlo7oHj+Y3xc456Boqmyv0u+/77DulU3oCg1sPQYm9I9SBpOHkk7oD7DUhS7Sy3yKTI370XoKOIHKErQziIS+kbj95G7hcQZ/rXLSocmrPHHdOP3ieuFAI6bbfg2v2bpUGk+g6IExnsVwJhoo6Z4OasWoQJhFuHxz1l54C/QStOYdnct89FXIIBwpuG8JPAdorR8xGqvNyMwVoNlS4xlmm85znOqC5fKK0TALWdNHbbB75jKotnj2PXdPn9MQTEBGlopeblnG85zAd2AonxxsTSlk6FBqQImF5DgwqfoWt6bgKid9BK/QDEe77uUzGVX1rEnh0Rgh7mcn8vJu9jBqm2SiBvBbhXQLDIXvyo0Gj9AUQY+7nVoSv+dPHsZyy9tSFJvCtBQ4SxoSVQTeoAFNgIwR5e7NGcNRU7tbgj3gSRNSL73O1gZbhz4+gum3W1ARDnRQQDoZxIk7Iy1sIl16VnAFKp4i+s7ff6YguL5ZLKLkbUeF0NQlFIolsDYlzxzPsk5q4l6XVrB8xhLEWhURaBo4NrLWGeeWjDr1pLPF7pkthTiW5VmegrzNW4nz2WnXvw0pinMcchfbkFRVfkigTHRwoLYyCKsLVkn+12k3rcZMxOLWGCjuyJNSmXO3m3TnB1FfvcusVZOAs+WECvnVZIba5DE9GdZFUw2THw7Ed5riBXyPHFHdEPubTlZ/28rNNETwE/FLp/fFSi+wo49zhoeGBb5bCttFoL7CYpyQQYVwJjmk7b4L4vAyQBiFmQSH0qRTZ+Yn6AoNYZtxA87jUWKP42ioqErAbB8RRutaYSZz3UAtEtYOknLGIGiASvg3gg+xrORk0ibFg9W9M48SFwoTRRmIq1d/gENcpOYVTSGVcFUWIAItxLmMWFYk5n9M1h/zTXIXIhn2nM6i2KXozqnoxE+o4GWGD7EBEtTRP7zmCY6jH2vLrDhV4fP7xoUP8CDSVrKcuU6seMdsXjLiTp7ahSldHZB8USLDa4CCHrMZMAY9Elj7EdSRgpJhDWNRU1pzlbjagCKcViAB4nJVkIW80VRzMkMAkCrWKeSxsR8/LfDVlFDWbOBv8cQFCkwHiTAeBPM3DGKRqm3KszsYWSei+BnPp4B1/msumU/3AcN2PdUVTDfw5xNsnBxzWdm6iJmpieBh79j+aG3sgToRAi7dez63yKdKMEClO9iGubtzGpKxXul/tO9WL/12PUHM7NfPv9fvdjGYjqrKd5CKJ/5Gray41uJyl8AJ6nhMygWQDN9C9KB01uInhay55rig++B5+K9Q3yLAxWpB393MBd+gqJc5EsYU5WiRMxtJUcz5veZrACFQgDDjQ7P3RQgS8sj68QQFKWW9ChJk8kGENDmv3tQz5xs8Qy8amUVfIvxzEx8ikXdX1SkUbWDOXuQgc0dFm2zTmNAKgMWvJyvEyq2SgnvLlbkG6vShvZAI2xgqCPP2xXdsrso3BDvE2WrBOusPfveKbBMS5gQud2Gi8o2KEZD70TR3cNN7bNT2h5t48kw/tRcYip3Ng51wnndODz5tFE1AkXpF93NFmg0na4vJwt0K2sNn0YEyHqX5vkUAm7ZDprg2gHFPRASj0XY+fFD5tMKseamQyIEYlRm6i744WkSc21oaDuZOTuQ+VPrYF52s31LllqUgLZVAGmmIv+vEcoz97G0mb4MQBtDA8xhYPeiAsQCSLv51EbAprmiuuVrCJA4Np8ZzJwP9/yOQbEckjw/AhUoNk36EUmrfoOi3Xvkre3XuNzYx7Cx6dD3JKWgs3F4grK8j3SHc+E3KAYQGS1mPiy3zT6TmOb5FGPybmSBz3e52dfJxBcaQpQy4BEoRrNx1VY8U1sHczWUVa1Ibew4ZvJeqKiCuYWZswkWTR3WAkRUGu80Vi2Up8g/TII5upFtmXAds7pUVTBS+1ZhgtSEKTDvg7BowMzpkYq0pdEsTpAIK2SDwpzvFS0oZkLanwpVW0VdAViqnbWWRaG22gXFTPg9uirurRtoEpNc2xxU1jgdrcnC4qA4jpgg46oZKPa22N/lWZcafzeSblGmCCjdHqbHn2GzB+UVLMCwzqag8xIUy6Cl/gC/6HiAtZs9errADVAWoTuMjA4Xk+CYqr1XZ5yvlLXri7PwMQ5mOaDliHr3ULzbZeQ+VQncAbJPPO2XOMiw7qI1gQVMSuCL78jO2wcuMbpNxT8VCdxd2PMfcNvRnILiJht9zJrChJA391/yskohgeJ9BMWNTJoaisjqt6y+c7Dh32hNHM4cFG+ppqDYhCXa55CoXxFSTpx0RAqwCpZymFo3wLxqSbQdp8nXScjle4mZUpLfRngEiqUIpNyA1BVON8InPAyg1c6j7kyNkdKSzbShMSw6rGoWsUKRs3kUq8Z5JML1OeBKq+8a5hdtjAyUHKIhL2P8Ls3exTiehzpoI0xEfJCiE/dalM9SS+NYrINCFhg+U/H8DxMB3NYLUDzRCF/iNodIgmfAHG8x9b5/FaXk9GKSfxsAMaBB8bBzZxCpXwweCBKH9Y8O91zmzUtpZ+eVSO06iPMPd2guL2B+tUK2V/PbNsoQ7YBiEcC3KkYSkpg3sud8hGmDCQCLtQzArmMAdg7xcwdtXL8+vreXCcp5zMdcQ9H7cK3CjzoE/PVzBAXGIKWPLzINd7eiWUZNCIufWQL31cycH0ssiZZ+g+Jg4odYR/xPPZndv8LFzUQLit1Zntg2nzXEIxUU+7FE6FfBeA0UG2nZNaOvIBJ8A0lQDik0ADt80RLBgx+Y2foZQHU80Wz22KiesgOKBzE3VTlOg4JRRrQxVXcYHnXNQ7BDRpxvJcBq120k/ZJrmcb/tqJtXHdYGuUkbWYa4Zf5RGDZzVluiNSjPaxZxgss6h4HTf0TlsB9J1x3NUg63EtumyPbBcU2JJzPm8bKvDfqZ7zHYb5QNKB4ZhUB4pEGikcT14d0RXRlzL6FgMTNNrTsNBJg2Qlg6YtIcw4DxR0Au2ZhNJZrwWflLAA0ieTUHcty5BZE8OkdKaAozdQ5bO4yYcKHS7aWEddzSLONb1xs43AyALeU4cLfmDbaFOuVbhT1NNnVsAL872QkIF6wXhHVH8jecWtigcjnfwXulCz8fZPhQfTZChRrsD07Hlb4U+qSYm+ZMnFpDECxG4vOxRIQjyRQTESwo4xoEdcrfINjWVpNdxv1rDvJniMpBCwHQfM5wPyAnwD86hP+Og+Lmn53J/x8HRg480TgSH7mIwkU5XxczTTlQkV3nEREsdexOSvGe57qsv9kI+Sr7mfm9FxWhZOC3OQtRLPdhXe8LopsD5n/WM5q3qcw66UOrIYsljgvgbSVn6BIGwV8GWYhdmObYn/lYAMaN6DYlSWjxhoQjyRQHMCc9P+0MC3qkdptmSTdMMx5ZxJT50qL812JjiwlrKPyMiz+R5nZlAN/da8w1kYvErmkHYmqOyg2hJYVsNmX8T0CDhXQ9HvaiGLvRToP56tmNk3aJLhF1ivy/zpZNKvgTXHbWnSfD9hM1p/HCiCKoY2eYKNZxPMOK6YcgeKJpJxmnw3tbxST9o/a3CPBaZPZU1hC9za0pDL+ZKBox5F9DGvY+UWE33UiOV+leBeJFhUsXxIB2CICk98AIVbMFhrN1XsHGmakssxUlhz/bhgfaHUBxS64z4+hGdt1eSxkkfefFC22jmJmdwXWbV8CXkPx7l+zyTdWVSvroCglMT/wQ0RTq8CzNiJa7Uh8NsFmN2ypMW9W5D8OYFkuvLrnAObNc59iTbKRfTnU5yQb+WTPMLV/hMcpOUPJVolVCYh+guJCJliok30LqfU8wYbZPI9pEINt7tddQEyyHoa6HrnI4d7MAy3yI6WJdJMDRh7OmjT0q+agOIUJujgH5aTXK+qr72X+2Rp4VtqK6wGylpcS/98Ih37OuczPma2oyU7D+8skPuQ2BDR/JBkq7Rz2L+WbWu2E6VyLufCmEAtijdutccOB4nVkYaxwcIFTmNq9wUaJnV1QzGYF47FIu4k1KBqso8hrRCqeQLS4LEWemBEmY6AcUTo7tc1Hke5HhYrKiGQSYMmy0QjkeKR9bFJUG4VYZcUb0ARSbWjAtCnA/RZAUx1B8RWHWkwAZvOHLDr8rqJqZAgBsAUKUHRaYSXf91UMcEsQlDlF0VOyDHPbnKyTn4kAO8vFftYPsDzFIgRbjmPm9ERSWnuUl6DYiZSv7XKRe3gNU/kjpXi4qX3OrEIN0W9QHErAYy1xGtcjYFWGgIVhI2NAtquy23fuGJJUq9rNrxtpc/V0GABrgtyytUzSV0BwTgRYfM+OZ8McOidCkvQcG8UH1QUUhxN+WO1Si5HgkM9yFa8lJunlAKxSlMSpNl17wmUVzmlwcZSxVKtLibAdRdoI1iJ7fH9LwOw6w92WubzsT9bs060cZpHOXslegGI7qMHPEp9S0EWVSioxvSXTjQ9jMoQDxQYKUNxWDQDRT1BsTzTigyzpeZFxeJ5hsoVkv5+AQabD8rrepMrlUxZsoXv75lv4mevinleyAIsE2btYw4C2AKyt7Lv7sIB7WGi4Z5AAUimqceyCYpsYgyLtPF0YpgTOLjhsYxr2PAjPp4ir5DRm+ZVFuZe39A/PZ0GQvcCSVmTLg1vD9B990mWLL7mp1UeKdK/REIoypWuU4VGgpT0mXAZL3nKrgrIgjexU09sFKHZjJrPUEAN/YFDkG2QtJ70Y/0I0hSyLvSouIybUQVzfrg8rDj4kurWoYRFg+ZTVu6cgGrhUsUHSfiyMMywALgFulvtZmoVk+vtxPI75vV8m3/uPIrpqBYodmeDxGxRTmQn7OuuM4xQc+rIGz6V4L9lkC946LBixiayxoBFdk2W+d0wRrl8A/2eHMD7gnS62leBW0OOsqUQeAn4Hkc7U1gtQ3ACz9weSpxbt5jBXsHyndy3aU1mB4insxWeSbUWNPzAoGmT/XOm/mQmNvS4Y3ir94HiWu/m8g96DBhbbdiLIuireqWTGCQTQeiLIto8BWiHAYIDNZr+J4LvHFNUxWwHSHQg4XkWEeI4isqsCxRaYlzKyoHrHgF+GED99IbSbuCjO1wpBG14Xnq/YY4cLu0wHeylbjTPhluF+4jkK67IZs/hejiZthrRXy1J0LpodzbxOZ33d1hHJOdbwJhH1fuYcvk0xYRwUJ4PxP67GgOg3KMbjpRcRU3IUQONcEmUrAVCkQoI/TOZsfYQ28YZiO4HPiM9yNvM9JaNOVaaGdIJ1cY+COUuQqD3cISgbJFeuL1w5+xWt6mZCYzia1V4/wu6ZguJsVMS8Rj4rhwZbPwb8UotlZ2Q5LHKwWmNTmWb+vEUq3Ams+muVQ/6wMqfpM32OdaEaV5P7LAFIp0bZcvAC1jbs82gStzkoUkf3C1E2jQ3n8P8VWoMVKJZhIaxQAGLgTwSKUho+RBJ4c5Gu0xFlXkVE65gFzSOXaD/DHZhj58L8oFp9M4WjXQZYPgTIbFYEwb4DoDfzYI7TsEXCm2zhl8PJP55tDraZZVFIUKwAX7/JTM4nvd74yIjcAGE14+0RLsEhAKH0LNHW1kXIShjCWnZ9hoBWnMt90PsRQbrdoocjdXc8TLCmAP7lxi7nMgGguJG4WQZ6uR0BLZvq7DEjXMzaI/HNkSgoVrA66m3VJKhSFaBoIMjxCAtYbIS2s5dl/OcRwLCzI18cfC8zWK/Cz1jlAt98qMKimW8mTNS2Psx1XZiEH7ACgWL4qKjmN9YCFA+Q75WidK5hFfBNH5a2lo+tCvrb7ElaC1r9LNZdZ7ONTJF4xA32MZ/tXQgG1bJZCngOc3FsQ+Q7YGPbipfYe/gP0scaOVAWeuD97SJa9/Ao3RFKUMyLkOZhRNEeaR4rWVpEpCMFxRBrITQCpk09/Os11YtiX5JYgKIEhHQL/4kq368IEcJu0IIa4lkbIE2mAwBmEUyPCqKlv23Rgbsp03B4lHgx/KBxhv+lclezXp6qTcLqKcxnmg2xwOXOk4aH2+Ty+cxFUO1uVK1cCADthbSTa4zKGvY3FbzwlYP91hNQYbSDnSML/t+ZmLfzcO0+uJeRELYrWPR5Ne7PcJBa9AKrb87Hs9+BQOGpWF/N4PLoDOAM4vn3MCXhUq94L51NyqM+7pXckgVNciFZwoHiPmiVH8G/6AetwIto5AMolnkEipKR+yAvcFcYQKQa1F74/r6Gf28VGOhXRXQ4C+ZwUxstwmgQ5XWYMCkxBpWmyIH8RrE9Rg4x4zgoFgJY6hhVP06G6VtgqPtR5sLCysYzHVB8Lx9pOCe58McNwNpSJdQfwDXl9XMVQigb7p0TDXcdgeYya4dW7OyBBbADvLkbSlsF+94SL7c3NZDXRdG+rc9McD7zZ8wgxyZ7tImWGyp0GYlrQaT9T4wxRxNmu9XwdhfBU9Ha60XUgm5AGsR6/L3XsN9e/0cIwx4REnqnsCDKSgBlnWrgwphCig0k3YeFfzmzhKb6tBe4EYXf+HKkv+12wLN7UP1zsdsaX2LOjoffv8DmtQug1V3sNkGaWJD9UeHj5NlLoCxdEUVaU1iGegpbCg6IAQPEA/yyIOG7s3u5FwnJr8SQXsKiqufS0TwRgHQvW2xdoaH9otgU3sv5rI80nI6Yw/owoyYgl+s9+Ah/QPLwJjD0QyjJ6mCzuqELtM3VAPwm1cy/2w6a7iYIhbl4P63Qked7bCtQw6ieoybSgsYjmrsKfPUzaCvm/kUAe1+b/j8nmvcgaNFvIIiVCf7dDv55H26Hi6PdRtT4fQ5nH7jzluFau/AesyEAslAV8zTcJ839fBkpQNtYRXZTYGY2U/gAkgAssaTUKH0RNcBQaYrAxHEIWFTVQkzGu60HJjoGyfh1XFQUBACERxnVd8QDBHuwZgV1cO9xxpExUvDOGsOf1hr3X99H9xY1q2ti/poie6QFQLC2y/JAJzxWE8/aEf7Mc5AP2R73kGzooYceeuihhx566KGHHnrooYceeuihhx566KGHHnrooYceeuihhx566KGHHtV/hESOZEhU+IVEGWFI1PiHZmjS5DOZfDaV8J0keSwd/wbJ/zW5pyCjjD8572FO1IA4Dsw5PVF86XTx5YHih5o0+UnnCz5rZoRCEMi/LdQGgvpVHs8Qx6c3rmRgExCnBcRn7QRdImiIpoh0maBhh1NQfBa89BCZc/ln5b+MvoJqVvLWP6xAcaaJnAMEbRWUKyhHkyYfab9YmM8Jqg+txRTId4l/95HvPC4YOAVSvbmgDwTlC8rTFJHMeSpgxL/zZ17nuwWNM0KiIXjoBhUoTpaq5NXi3xJBIU2aYkCfCzoaZlwN8e+Sw48HPxQaYm2AZmtBa/ScafKQ5huh2yuVwt+DYp70LzQR/44WTLhQ0AJNmvyjjLmC+gueS6g0kSeZPNhF0Czw3x3CtOlthMYIs3ma6d4R38s4W9BUQTM0KWm2oDmExBwH79G89jsy+WuaoHaVAjekAkXqgBQNckLjEzRp8peCcZW+xJngu2kQzLcIELxVHB8XV/nZdPi7p+B7oulNSHRdC03QdBiZQmWUmLtJcYdosqCJmteU9JdAJT/dWclX6mDLZDi7p4AJNWnyk0wAnFUJiv8vmGcSEJx2CDB/Oz4VPJquo/aWlK6gaZrXLGliJU/poYceeuhhPf4H8iTfOixjL5UAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjQtMTEtMDlUMjM6MDc6MzYrMDA6MDBs5MHxAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDI0LTExLTA5VDIzOjA3OjM2KzAwOjAwHbl5TQAAACh0RVh0ZGF0ZTp0aW1lc3RhbXAAMjAyNC0xMS0xMVQxOTowMDo0OSswMDowMOZ2LeoAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC" alt="keycapsss" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="https://zmk.dev/assets/images/keycapsss-dark-mode-9d9b78e9318d5d67c2ef832c0a9b6628.png" alt="keycapsss" class="themedComponent_mlkZ themedComponent--dark_xIcU"></a><a href="https://mekibo.com/"><img src="https://zmk.dev/assets/images/mekibo-09b858530d41e5fc60429acdb7f5d575.png" alt="mekibo" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="https://zmk.dev/assets/images/mekibo-dark-mode-5cb5f99c1b372e1a425da149b825780a.png" alt="mekibo" class="themedComponent_mlkZ themedComponent--dark_xIcU"></a></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="using-zmk-studio">Using ZMK Studio<a href="https://zmk.dev/blog/2024/11/11/zmk-studio-mvp-ga#using-zmk-studio" class="hash-link" aria-label="Direct link to Using ZMK Studio" title="Direct link to Using ZMK Studio" translate="no">​</a></h2>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>For keyboard maintainers, additional changes are needed to add metadata about the keyboard's physical layouts in order to use ZMK Studio. See the documentation on <a class="" href="https://zmk.dev/docs/development/hardware-integration/physical-layouts#optional-keys-property">physical layouts</a> for more information.</p></div></div>
<p>To use ZMK Studio, you need to have a firmware for your keyboard with the feature enabled, as well as a small keymap change to add an unlock key. See <a class="" href="https://zmk.dev/docs/features/studio#building">Building with ZMK Studio</a> and <a class="" href="https://zmk.dev/docs/features/studio#keymap-changes">ZMK Studio keymap changes</a> for more details.</p>
<p>See <a class="" href="https://zmk.dev/docs/features/studio#accessing-zmk-studio">Accessing ZMK Studio</a> for more details on the browser and desktop options for using the ZMK Studio application.
Note: Depending on your browser, operating system, and app vs website selection, you may be limited to connecting over USB. See the previous link for details.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="in-tree-supported-keyboards">In-Tree Supported Keyboards<a href="https://zmk.dev/blog/2024/11/11/zmk-studio-mvp-ga#in-tree-supported-keyboards" class="hash-link" aria-label="Direct link to In-Tree Supported Keyboards" title="Direct link to In-Tree Supported Keyboards" translate="no">​</a></h2>
<p>The following in-tree keyboards have been updated to support ZMK Studio.
If your keyboard is supported by an external module/config, check with the maintainer to see
if support has been added.</p>
<ul><li>Advantage 360 Pro</li><li>Corneish Zen</li><li>Glove80</li><li>nice!60</li><li>BT60 V1 Hotswap</li><li>BT60 V2</li><li>BT65</li><li>BT75 V1</li><li>Boardsource 3x4 Macropad</li><li>Boardsource 5x12</li><li>Contra</li><li>Corne</li><li>Cradio/Sweep</li><li>CRBN Featherlight</li><li>Hummingbird</li><li>Jian</li><li>Jiran</li><li>Jorne</li><li>Kyria Rev3</li><li>Kyria</li><li>Lily58</li><li>Lotus58</li><li>MakerDiary m60</li><li>QAZ</li><li>REVIUNG41</li><li>Sofle</li><li>splitkb.com Aurora Corne</li><li>splitkb.com Aurora Lily58</li><li>splitkb.com Aurora Sofle</li><li>splitkb.com Aurora Sweep</li><li>ZMK Uno</li></ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="next-steps">Next Steps<a href="https://zmk.dev/blog/2024/11/11/zmk-studio-mvp-ga#next-steps" class="hash-link" aria-label="Direct link to Next Steps" title="Direct link to Next Steps" translate="no">​</a></h2>
<p>The ZMK Studio MVP is truly that, a "minimum viable product". It establishes the core firmware functionality and frontend application infrastructure in order to validate the technology, prove the approaches, and get initial core features into user's hands as early as possible.</p>
<p>There are many ZMK features that are not yet possible to update in ZMK Studio. For a better understanding of where ZMK Studio is today, and where we are headed, please have a look at the <a class="" href="https://zmk.dev/docs/features/studio#capabilities">ZMK Studio capabilities</a> table.</p>]]></content:encoded>
            <category>firmware</category>
            <category>studio</category>
            <category>core</category>
        </item>
        <item>
            <title><![CDATA[Zephyr 3.5 Update]]></title>
            <link>https://zmk.dev/blog/2024/02/09/zephyr-3-5</link>
            <guid>https://zmk.dev/blog/2024/02/09/zephyr-3-5</guid>
            <pubDate>Fri, 09 Feb 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[I'm happy to announce that we have completed the work to upgrade ZMK to Zephyr 3.5!]]></description>
            <content:encoded><![CDATA[<p>I'm happy to announce that we have completed the <a href="https://github.com/zmkfirmware/zmk/pull/1995" target="_blank" rel="noopener noreferrer" class="">work</a> to upgrade ZMK to <a href="https://docs.zephyrproject.org/3.5.0/releases/release-notes-3.5.html" target="_blank" rel="noopener noreferrer" class="">Zephyr 3.5</a>!</p>
<!-- -->
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> did the upgrade work to adjust ZMK for the Zephyr changes:</p>
<ul>
<li class="">Add <code>west flash</code> support to all UF2 capable boards.</li>
<li class="">Adjust for LVGL DTS/Kconfig changes</li>
<li class="">Zephyr core API changes, including <code>CONTAINER_OF</code> work API changes, init priority/callback, and others</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="getting-the-changes">Getting The Changes<a href="https://zmk.dev/blog/2024/02/09/zephyr-3-5#getting-the-changes" class="hash-link" aria-label="Direct link to Getting The Changes" title="Direct link to Getting The Changes" translate="no">​</a></h2>
<p>Use the following steps to update to the latest tooling in order to properly use the new ZMK changes:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="user-config-repositories-using-github-actions">User Config Repositories Using GitHub Actions<a href="https://zmk.dev/blog/2024/02/09/zephyr-3-5#user-config-repositories-using-github-actions" class="hash-link" aria-label="Direct link to User Config Repositories Using GitHub Actions" title="Direct link to User Config Repositories Using GitHub Actions" translate="no">​</a></h3>
<p>Existing user config repositories using Github Actions to build will pull down Zephyr 3.5 automatically, however if you created your user config a while ago, you may need to update it to reference our shared build configuration to leverage the correct Docker image.</p>
<ol>
<li class="">
<p>Replace the contents of your <code>.github/workflows/build.yml</code> with:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token key atrule" style="color:#d73a49">on</span><span class="token punctuation">:</span><span class="token plain"> </span><span class="token punctuation">[</span><span class="token plain">push</span><span class="token punctuation">,</span><span class="token plain"> pull_request</span><span class="token punctuation">,</span><span class="token plain"> workflow_dispatch</span><span class="token punctuation">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token key atrule" style="color:#d73a49">jobs</span><span class="token punctuation">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token key atrule" style="color:#d73a49">build</span><span class="token punctuation">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token key atrule" style="color:#d73a49">uses</span><span class="token punctuation">:</span><span class="token plain"> zmkfirmware/zmk/.github/workflows/build</span><span class="token punctuation">-</span><span class="token plain">user</span><span class="token punctuation">-</span><span class="token plain">config.yml@main</span><br></span></code></pre></div></div>
</li>
<li class="">
<p>If it doesn't exist already, add a new file to your repository named <code>build.yaml</code>:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token comment" style="color:#6a737d"># This file generates the GitHub Actions matrix</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d"># For simple board + shield combinations, add them</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d"># to the top level board and shield arrays, for more</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d"># control, add individual board + shield combinations to</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d"># the `include` property, e.g:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d">#</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d"># board: [ "nice_nano_v2" ]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d"># shield: [ "corne_left", "corne_right" ]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d"># include:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d">#   - board: bdn9_rev2</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d">#   - board: nice_nano_v2</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d">#     shield: reviung41</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d">#</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">---</span><br></span></code></pre></div></div>
</li>
</ol>
<p>and then update it as appropriate to build the right shields/boards for your configuration.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="vs-code--docker-dev-container">VS Code &amp; Docker (Dev Container)<a href="https://zmk.dev/blog/2024/02/09/zephyr-3-5#vs-code--docker-dev-container" class="hash-link" aria-label="Direct link to VS Code &amp; Docker (Dev Container)" title="Direct link to VS Code &amp; Docker (Dev Container)" translate="no">​</a></h3>
<p>If you build locally using VS Code &amp; Docker then:</p>
<ul>
<li class="">Pull the latest ZMK <code>main</code> with <code>git pull</code> for your ZMK checkout</li>
<li class="">Reload the project</li>
<li class="">If you are prompted to rebuild the remote container, click <code>Rebuild</code></li>
<li class="">Otherwise, press <code>F1</code> and run <code>Remote Containers: Rebuild Container</code></li>
<li class="">Once the container has rebuilt and reloaded, run <code>west update</code> to pull the updated Zephyr version and its dependencies.</li>
</ul>
<p>Once the container has rebuilt, VS Code will be running the 3.5 Docker image.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="local-host-development">Local Host Development<a href="https://zmk.dev/blog/2024/02/09/zephyr-3-5#local-host-development" class="hash-link" aria-label="Direct link to Local Host Development" title="Direct link to Local Host Development" translate="no">​</a></h3>
<p>The following steps will get you building ZMK locally against Zephyr 3.5:</p>
<ul>
<li class="">Run the updated <a class="" href="https://zmk.dev/docs/development/local-toolchain/setup">toolchain installation</a> steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)</li>
<li class="">Install the latest version of <code>west</code> by running <code>pip3 install --user --update west</code>.</li>
<li class="">Pull the latest ZMK <code>main</code> with <code>git pull</code> for your ZMK checkout</li>
<li class="">Run <code>west update</code> to pull the updated Zephyr version and its dependencies</li>
</ul>
<p>From there, you should be ready to build as normal!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="boardshield-changes">Board/Shield Changes<a href="https://zmk.dev/blog/2024/02/09/zephyr-3-5#boardshield-changes" class="hash-link" aria-label="Direct link to Board/Shield Changes" title="Direct link to Board/Shield Changes" translate="no">​</a></h2>
<p>The following changes have <a href="https://github.com/zmkfirmware/zmk/pull/1995/commits" target="_blank" rel="noopener noreferrer" class="">already been completed</a> for all boards/shields in ZMK <code>main</code> branch. For existing or new PRs, or out of tree boards, the following changes are necessary to properly work with the latest changes.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="west-flash-support">West Flash Support<a href="https://zmk.dev/blog/2024/02/09/zephyr-3-5#west-flash-support" class="hash-link" aria-label="Direct link to West Flash Support" title="Direct link to West Flash Support" translate="no">​</a></h3>
<p>If you have a custom board for a target that has a UF2 supporting bootloader, you can easily add support for
flashing via <code>west flash</code>. Note that using <code>west flash</code> isn't mandatory, it is merely a convenient way to automate copying to the mass storage device, which you can continue to do manually.
To add support, add a line to your board's <code>board.cmake</code> file like so:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token plain">include(${ZEPHYR_BASE}/boards/common/uf2.board.cmake)</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="lvgl-dtskconfig-changes">LVGL DTS/Kconfig Changes<a href="https://zmk.dev/blog/2024/02/09/zephyr-3-5#lvgl-dtskconfig-changes" class="hash-link" aria-label="Direct link to LVGL DTS/Kconfig Changes" title="Direct link to LVGL DTS/Kconfig Changes" translate="no">​</a></h3>
<p>Two items were changed for LVGL use for displays that may need adjusting for custom shields:</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="dpi-kconfig-rename">DPI Kconfig Rename<a href="https://zmk.dev/blog/2024/02/09/zephyr-3-5#dpi-kconfig-rename" class="hash-link" aria-label="Direct link to DPI Kconfig Rename" title="Direct link to DPI Kconfig Rename" translate="no">​</a></h4>
<p>The old <code>LV_Z_DPI</code> Kconfig symbol was promoted to a Kconfig in upstream LVGL, and is now named <code>LV_DPI_DEF</code>. You
will need to replace this symbol in your board/shield's <code>Kconfig.defconfig</code> file.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="ssd1306-oled-inverse-refactor">SSD1306 OLED Inverse Refactor<a href="https://zmk.dev/blog/2024/02/09/zephyr-3-5#ssd1306-oled-inverse-refactor" class="hash-link" aria-label="Direct link to SSD1306 OLED Inverse Refactor" title="Direct link to SSD1306 OLED Inverse Refactor" translate="no">​</a></h4>
<p>Inverting black/white pixels has moved out of the Kconfig system and into a new DTS property. If you have a custom
shield that uses an SSD1306, you should:</p>
<ul>
<li class="">Remove any override for the <code>SSD1306_REVERSE_MODE</code> from your Kconfig files.</li>
<li class="">Add the new <code>inversion-on;</code> boolean property to the SSD1306 node in your devicetree file.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="maxim-max17048-sensor-driver">Maxim max17048 Sensor Driver<a href="https://zmk.dev/blog/2024/02/09/zephyr-3-5#maxim-max17048-sensor-driver" class="hash-link" aria-label="Direct link to Maxim max17048 Sensor Driver" title="Direct link to Maxim max17048 Sensor Driver" translate="no">​</a></h3>
<p>Upstream Zephyr has added a driver for the max17048 fuel gauge, but using the new <a href="https://docs.zephyrproject.org/3.5.0/hardware/peripherals/fuel_gauge.html" target="_blank" rel="noopener noreferrer" class="">fuel gauge API</a> that ZMK
does not yet consume. To avoid a conflict with the new upstream and keep our existing sensor driver, our driver has been renamed to be namespaced with a ZMK prefix. The following changes are needed for any boards using the driver:</p>
<ul>
<li class="">Change the <code>compatible</code> value for the node to be <code>zmk,maxim-17048</code>, e.g. <code>compatible = "zmk,maxim-max17048";</code>.</li>
<li class="">If enabling the driver explicitly via Kconfig, rename <code>MAX17048</code> to the new <code>ZMK_MAX17048</code> in your <code>Kconfig.defconfig</code> or <code>&lt;board&gt;_defconfig</code> files.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="upcoming-changes">Upcoming Changes<a href="https://zmk.dev/blog/2024/02/09/zephyr-3-5#upcoming-changes" class="hash-link" aria-label="Direct link to Upcoming Changes" title="Direct link to Upcoming Changes" translate="no">​</a></h2>
<p>Moving to Zephyr 3.5 will unblock several exciting efforts that were dependent on that Zephyr release.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="ble-stability-improvements">BLE Stability Improvements<a href="https://zmk.dev/blog/2024/02/09/zephyr-3-5#ble-stability-improvements" class="hash-link" aria-label="Direct link to BLE Stability Improvements" title="Direct link to BLE Stability Improvements" translate="no">​</a></h3>
<p>Many users have reported various BLE issues with some hardware combinations, including challenges with updated
Intel drivers, and macOS general stability problems. The Zephyr 3.5 release includes many fixes for the BT host and controller portions that, combined with some small upcoming ZMK changes, have been reported to completely resolve previous issues. Further focused testing will immediately commence to fully verify the ZMK changes before
making them the default.</p>
<p>If you'd like to test those changes, enable <code>CONFIG_ZMK_BLE_EXPERIMENTAL_CONN=y</code> for your builds.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="pointer-integration">Pointer Integration<a href="https://zmk.dev/blog/2024/02/09/zephyr-3-5#pointer-integration" class="hash-link" aria-label="Direct link to Pointer Integration" title="Direct link to Pointer Integration" translate="no">​</a></h3>
<p>The Zephyr 3.5 release includes a new <a href="https://docs.zephyrproject.org/3.5.0/services/input/index.html" target="_blank" rel="noopener noreferrer" class="">input subsystem</a> that we will be leveraging for our upcoming pointer support. The open PR for that work is now unblocked and further testing and code review will begin to work on getting that feature integrated into ZMK as well.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="power-domains">Power Domains<a href="https://zmk.dev/blog/2024/02/09/zephyr-3-5#power-domains" class="hash-link" aria-label="Direct link to Power Domains" title="Direct link to Power Domains" translate="no">​</a></h3>
<p>Several power domain related changes are now available as well, which were a necessity for continued work on the improved peripheral power handling that's planned to supersede the existing "VCC cutoff" code that currently exists but causes problems for builds that include multiple powered peripherals like Displays + RGB.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="thanks">Thanks!<a href="https://zmk.dev/blog/2024/02/09/zephyr-3-5#thanks" class="hash-link" aria-label="Direct link to Thanks!" title="Direct link to Thanks!" translate="no">​</a></h2>
<p>Thanks to all the testers who have helped verify ZMK functionality on the newer Zephyr version.</p>]]></content:encoded>
            <category>firmware</category>
            <category>zephyr</category>
            <category>core</category>
        </item>
        <item>
            <title><![CDATA[Community Spotlight Series #3: ZMK Tools and ZMK Locale Generator]]></title>
            <link>https://zmk.dev/blog/2024/01/05/zmk-tools</link>
            <guid>https://zmk.dev/blog/2024/01/05/zmk-tools</guid>
            <pubDate>Fri, 05 Jan 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[This blog continues our series of posts where we highlight projects within the ZMK ecosystem]]></description>
            <content:encoded><![CDATA[<p>This blog continues our series of posts where we highlight projects within the ZMK ecosystem
that we think are interesting and that the users might benefit from knowing about them.</p>
<p>In this installment, we are highlighting two projects (and a bonus one!) from <a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">Joel Spadin</a>,
a member of the core ZMK team.</p>
<!-- -->
<p>The first one is <a href="https://zmk.dev/blog/2024/01/05/zmk-tools#zmk-tools" class="">ZMK Tools</a>, a handy Visual Studio Code extension to ease working with ZMK configurations, and the second is <a href="https://zmk.dev/blog/2024/01/05/zmk-tools#zmk-locale-generator" class="">ZMK Locale Generator</a>, a tool to help users that use non-US English keyboard locales in their operating systems.</p>
<p>In the rest of the post we leave it to Joel to introduce and explain the motivations of his ZMK-related projects.
Stay tuned for future installments in the series!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="zmk-tools">ZMK Tools<a href="https://zmk.dev/blog/2024/01/05/zmk-tools#zmk-tools" class="hash-link" aria-label="Direct link to ZMK Tools" title="Direct link to ZMK Tools" translate="no">​</a></h2>
<p><a href="https://github.com/joelspadin/zmk-tools" target="_blank" rel="noopener noreferrer" class="">ZMK Tools</a> is an extension for <a href="https://code.visualstudio.com/" target="_blank" rel="noopener noreferrer" class="">Visual Studio Code</a> that helps with editing a ZMK user config repo or a fork of ZMK. I originally created it to add some code completion in <code>.keymap</code> files, but then I realized that with the web version of VS Code, I could also let you set up a user config repo and build firmware, much like the <a class="" href="https://zmk.dev/docs/user-setup#user-config-setup-script">user setup script</a>, except without downloading a single thing.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="user-config-setup-in-browser">User Config Setup in Browser<a href="https://zmk.dev/blog/2024/01/05/zmk-tools#user-config-setup-in-browser" class="hash-link" aria-label="Direct link to User Config Setup in Browser" title="Direct link to User Config Setup in Browser" translate="no">​</a></h3>
<p>Here is how you can use ZMK Tools to get started with writing a ZMK keymap entirely within your browser. More detailed instructions can be found on the <a href="https://github.com/joelspadin/zmk-tools/blob/main/README.md" target="_blank" rel="noopener noreferrer" class="">ZMK Tools README</a>.</p>
<ol>
<li class="">Open the <a href="https://github.com/zmkfirmware/unified-zmk-config-template" target="_blank" rel="noopener noreferrer" class="">ZMK config template repo</a> on GitHub.</li>
<li class="">Click the <strong>Use this template</strong> button and follow the instructions to create your own repo.
<ul>
<li class="">If you don't see this button, make sure you're signed in to GitHub first.</li>
<li class="">You can name the repo anything you want, but "zmk-config" is the conventional name.</li>
</ul>
</li>
<li class="">From the GitHub page for your new repo, press <kbd>.</kbd> (period) and it will re-open the repo in github.dev.</li>
<li class="">Press <kbd>Ctrl + P</kbd> and enter the following to install the ZMK Tools extension:
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token plain">ext install spadin.zmk-tools</span><br></span></code></pre></div></div>
</li>
<li class="">Press <kbd>Ctrl + Shift + P</kbd> and run the <strong>ZMK: Add Keyboard</strong> command.</li>
<li class="">Follow the prompts to select a keyboard. ZMK Tools will copy the default keymap for that keyboard if you don't already have one, and it will automatically add it to your <code>build.yaml</code> file so GitHub will build it for you.</li>
</ol>
<p>You can then edit your <code>.keymap</code> and <code>.conf</code> files. Once you're done:</p>
<ol>
<li class="">Click the <strong>Source Control</strong> tab on the side bar.</li>
<li class="">Hover over the header for the <strong>Changes</strong> list and click the <code>+</code> (Stage All Changes) button.</li>
<li class="">Write a commit message and click <strong>Commit &amp; Push</strong> to push your changes to GitHub.</li>
</ol>
<p>GitHub will start building the new firmware. To check the results:</p>
<ol>
<li class="">Use your browser's back button to go back to your repo's GitHub page.</li>
<li class="">Click the <strong>Actions</strong> tab at the top of the page.</li>
<li class="">Click the latest build (it should show the commit message you entered earlier). If it's still in progress, wait for it to finish.</li>
<li class="">If the build was successful, go to the <strong>Artifacts</strong> section and click <strong>firmware</strong> to download the firmware. If it failed, check the error and go back to github.dev to fix it.</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="keymap-code-completion">Keymap Code Completion<a href="https://zmk.dev/blog/2024/01/05/zmk-tools#keymap-code-completion" class="hash-link" aria-label="Direct link to Keymap Code Completion" title="Direct link to Keymap Code Completion" translate="no">​</a></h3>
<p>ZMK Tools also provides some basic code completion in <code>.keymap</code> files. It will suggest any of ZMK's built-in behaviors inside <code>bindings</code> and <code>sensor-bindings</code> properties, and it will automatically add the necessary headers.</p>
<p>For example, with the cursor at the end of line 6 in the following keymap...</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv codeBlockLinesWithNumbering_o6Pm" style="counter-reset:line-count 0"><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token node class-name" style="color:#6f42c1">/</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token node class-name" style="color:#6f42c1">keymap</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"zmk,keymap"</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        </span><span class="token node class-name" style="color:#6f42c1">default_layer</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">bindings</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token plain"></span></span><br></span><span class="token-line theme-code-block-highlighted-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">                </span><span class="token operator" style="color:#005cc5">&amp;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">            </span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span></span><br></span></code></pre></div></div>
<p>...it will suggest things such as <code>&amp;kp</code>, <code>&amp;mo</code>, etc., and upon entering one, it will recognize that <code>#include &lt;behaviors.dtsi&gt;</code> is missing and add it to the top of the keymap:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv codeBlockLinesWithNumbering_o6Pm" style="counter-reset:line-count 0"><span class="token-line theme-code-block-highlighted-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="color:#d73a49">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:#032f62">&lt;behaviors.dtsi&gt;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain"></span><span class="token node class-name" style="color:#6f42c1">/</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token node class-name" style="color:#6f42c1">keymap</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"zmk,keymap"</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        </span><span class="token node class-name" style="color:#6f42c1">default_layer</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">bindings</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">                </span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">            </span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span></span><br></span></code></pre></div></div>
<p>Press space after <code>&amp;kp</code>, and it will suggest all of ZMK's key codes. Upon entering one, it will again recognize that <code>#include &lt;dt-bindings/zmk/keys.h&gt;</code> is missing and add it too:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv codeBlockLinesWithNumbering_o6Pm" style="counter-reset:line-count 0"><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="color:#d73a49">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:#032f62">&lt;behaviors.dtsi&gt;</span><span class="token plain"></span></span><br></span><span class="token-line theme-code-block-highlighted-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain"></span><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="color:#d73a49">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:#032f62">&lt;dt-bindings/zmk/keys.h&gt;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain"></span><span class="token node class-name" style="color:#6f42c1">/</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token node class-name" style="color:#6f42c1">keymap</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"zmk,keymap"</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        </span><span class="token node class-name" style="color:#6f42c1">default_layer</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">bindings</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">                </span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> A</span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">            </span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span></span><br></span></code></pre></div></div>
<p>This can be very helpful for making sure you spelled key codes correctly and included all the correct headers.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="future-work">Future Work<a href="https://zmk.dev/blog/2024/01/05/zmk-tools#future-work" class="hash-link" aria-label="Direct link to Future Work" title="Direct link to Future Work" translate="no">​</a></h3>
<p>Unfortunately, all the code completion info currently comes from a config file baked into the extension, so it won't pick up any custom behaviors or key code aliases you've defined. I'd like to make that work eventually, but it's a much more difficult problem to solve.</p>
<p>ZMK Tools will discover all the boards/shields from both ZMK and your user config repo. With some recent changes in ZMK to allow pulling in features from other Zephyr modules, it's now possible to use board/shields defined in other repos, but ZMK Tools doesn't know about this yet. I'd like to support this too, but making it work in the web version of the extension will be challenging.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="zmk-locale-generator">ZMK Locale Generator<a href="https://zmk.dev/blog/2024/01/05/zmk-tools#zmk-locale-generator" class="hash-link" aria-label="Direct link to ZMK Locale Generator" title="Direct link to ZMK Locale Generator" translate="no">​</a></h2>
<p>ZMK's key codes follow the <a href="https://www.usb.org/hid" target="_blank" rel="noopener noreferrer" class="">HID specification</a>, and many key codes indicate the <em>position</em> of a key on US keyboard layout, not the key's function. If your operating system is set to a different keyboard locale, then the character each key types won't necessarily line up with the key code name. For example, on a German "QWERTZ" layout, <code>&amp;kp Y</code> will type <kbd>Z</kbd> and <code>&amp;kp Z</code> will type <kbd>Y</kbd>, so you have to write your layout as if it were QWERTY instead. Other layouts can be even more confusing!</p>
<p><a href="https://github.com/joelspadin/zmk-locale-generator" target="_blank" rel="noopener noreferrer" class="">ZMK Locale Generator</a> is another tool I made to help with this. It reads <a href="https://cldr.unicode.org/index/charts/keyboards" target="_blank" rel="noopener noreferrer" class="">CLDR keyboard layouts</a> and generates <code>#define</code>s to alias key codes to names that make sense in other locales. To use it, first go to the <a href="https://github.com/joelspadin/zmk-locale-generator/releases/latest" target="_blank" rel="noopener noreferrer" class="">latest release</a> and download the header that matches the locale you use. Next, copy it into the same folder as your keymap and <code>#include</code> it:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="color:#d73a49">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:#032f62">"keys_de.h"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token node class-name" style="color:#6f42c1">/</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<p>If you open the header file in a text editor, you'll see that it contains many of the standard ZMK key codes, except they are prefixed by the locale code. Depending on the locale, it may also define key codes for special characters specific to that locale, e.g. <code>DE_A_UMLAUT</code> for "ä" and <code>DE_SZ</code> for "ß". If you use these in your keymap, then ZMK will send the correct key codes to type those characters.</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token macro property directive-hash">#</span><span class="token macro property directive keyword" style="color:#d73a49">include</span><span class="token macro property"> </span><span class="token macro property string" style="color:#032f62">"keys_de.h"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token node class-name" style="color:#6f42c1">/</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token node class-name" style="color:#6f42c1">keymap</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"zmk,keymap"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token node class-name" style="color:#6f42c1">default_layer</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">bindings</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                </span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> DE_Q </span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> DE_W </span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> DE_E </span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> DE_R </span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> DE_T </span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> DE_Z </span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<p>I should note that, as a native English speaker and typer, I don't use any of this myself! I just saw that many people were asking for help with this, and I realized I could automate a solution. If you find something that isn't generated correctly, please <a href="https://github.com/joelspadin/zmk-locale-generator/issues" target="_blank" rel="noopener noreferrer" class="">file an issue</a> or PR a fix on GitHub.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="keyboard-latency-testing">Keyboard Latency Testing<a href="https://zmk.dev/blog/2024/01/05/zmk-tools#keyboard-latency-testing" class="hash-link" aria-label="Direct link to Keyboard Latency Testing" title="Direct link to Keyboard Latency Testing" translate="no">​</a></h2>
<p>The last project I want to mention is a tool for testing keyboard latency. It requires only a Raspberry Pi, an optocoupler IC, a resistor, and some wire. If you've ever wondered how ZMK's latency compares to other keyboards, you can <a href="https://github.com/joelspadin/keyboard-latency-tester/blob/main/results/chart.ipynb" target="_blank" rel="noopener noreferrer" class="">check the results here</a>!</p>
<p>I don't have a very large collection of keyboards though, so the data is pretty limited so far. If you want to try it on your own keyboard, see the instructions on the <a href="https://github.com/joelspadin/keyboard-latency-tester" target="_blank" rel="noopener noreferrer" class="">keyboard latency tester README</a>, and please send me a PR with your results!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="about-me">About Me<a href="https://zmk.dev/blog/2024/01/05/zmk-tools#about-me" class="hash-link" aria-label="Direct link to About Me" title="Direct link to About Me" translate="no">​</a></h2>
<p>I got a degree in electrical engineering but promptly became a software engineer instead. I still like tinkering with electronics though, so I discovered ZMK when I was making wireless macropad with a nice!nano, and I became a regular contributor after that. I use mostly larger keyboards with standard layouts and rarely use anything more complicated than momentary layers, so I've mostly focused on improving core features and tooling.</p>
<p>The keyboards I regularly use are a Ducky One 2 TKL that I leave at work, a Freebird TKL[^1], a custom <a href="https://github.com/joelspadin/NumBLE" target="_blank" rel="noopener noreferrer" class="">wireless numpad</a>, and a Yamaha CP4.</p>
<p>[^1] Running QMK, but I have designs to make a wireless PCB for it someday...</p>]]></content:encoded>
            <category>keyboards</category>
            <category>firmware</category>
            <category>community</category>
        </item>
        <item>
            <title><![CDATA[Community Spotlight Series #2: Node-free Config]]></title>
            <link>https://zmk.dev/blog/2023/12/17/nodefree-config</link>
            <guid>https://zmk.dev/blog/2023/12/17/nodefree-config</guid>
            <pubDate>Sun, 17 Dec 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[This blog continues our series of posts where we highlight projects within the ZMK ecosystem]]></description>
            <content:encoded><![CDATA[<p>This blog continues our series of posts where we highlight projects within the ZMK ecosystem
that we think are interesting and that the users might benefit from knowing about them. You might
be aware that ZMK configurations in the <a class="" href="https://zmk.dev/docs/config#devicetree-files">Devicetree format</a>
use the <a href="https://en.wikipedia.org/wiki/C_preprocessor" target="_blank" rel="noopener noreferrer" class="">C preprocessor</a> so that directives like
<code>#define RAISE 2</code> or <code>#include &lt;behaviors.dtsi&gt;</code> can be used in them. In this installment we are
highlighting the <a href="https://github.com/urob/zmk-nodefree-config" target="_blank" rel="noopener noreferrer" class=""><code>zmk-nodefree-config</code> project</a>
by <a href="https://github.com/urob" target="_blank" rel="noopener noreferrer" class="">urob</a> that contains helper methods that utilizes this fact
for users who prefer editing and maintaining their ZMK config directly using the Devicetree
syntax format.</p>
<!-- -->
<p>In the rest of the post we leave it to urob to introduce and explain the motivations of the
project, and various ways it can be used to help maintain ZMK keymaps. Stay tuned for future
installments in the series!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="overview">Overview<a href="https://zmk.dev/blog/2023/12/17/nodefree-config#overview" class="hash-link" aria-label="Direct link to Overview" title="Direct link to Overview" translate="no">​</a></h2>
<p>Loosely speaking the <em>nodefree</em> repo -- more on the name later -- is a
collection of helper functions that simplify configuring keymap files. Unlike
the graphical keymap editor covered in the <a href="https://zmk.dev/blog/2023/11/09/keymap-editor" target="_blank" rel="noopener noreferrer" class="">previous spotlight
post</a>, it is aimed at users who
edit and maintain directly the source code of their keymap files.</p>
<p>The provided helpers fall into roughly one of three categories:</p>
<ol>
<li class="">Helpers that eliminate boilerplate, reduce the complexity of keymaps, and improve readability.</li>
<li class="">Helpers that improve portability of "position-based" properties such as combos.</li>
<li class="">Helpers that define international and other unicode characters.</li>
</ol>
<p>The reminder of this post details each of these three categories.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="eliminating-boilerplate">Eliminating Boilerplate<a href="https://zmk.dev/blog/2023/12/17/nodefree-config#eliminating-boilerplate" class="hash-link" aria-label="Direct link to Eliminating Boilerplate" title="Direct link to Eliminating Boilerplate" translate="no">​</a></h2>
<p>In ZMK, keymaps are configured using so-called <em>Devicetree</em> files. Devicetree files
define a collection of nested <em>nodes</em>, whereas each node in turn specifies a variety of
<em>properties</em> through which one can customize the keymap.</p>
<p>For example, the following snippet sets up a
<a href="https://zmk.dev/docs/keymaps/behaviors/mod-morph" target="_blank" rel="noopener noreferrer" class="">mod-morph</a> behavior that sends <kbd>.</kbd>
("dot") when pressed by itself and sends <kbd>:</kbd> ("colon") when shifted:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv codeBlockLinesWithNumbering_o6Pm" style="counter-reset:line-count 0"><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token node class-name" style="color:#6f42c1">/</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token node class-name" style="color:#6f42c1">behaviors</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        </span><span class="token label symbol" style="color:#e36209">dot_colon:</span><span class="token plain"> </span><span class="token node class-name" style="color:#6f42c1">dot_colon_behavior</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"zmk,behavior-mod-morph"</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">#binding-cells</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">0</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line theme-code-block-highlighted-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">bindings</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> DOT</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> COLON</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line theme-code-block-highlighted-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">mods</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token punctuation">(</span><span class="token plain">MOD_LSFT</span><span class="token operator" style="color:#005cc5">|</span><span class="token plain">MOD_RSFT</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">        </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span></span><br></span></code></pre></div></div>
<p>Adding this snippet to the keymap will create a new node <code>dot_colon_behavior</code>
(nested underneath the <code>behaviors</code> and root <code>/</code> nodes), and assigns it four
properties (<code>compatible</code>, <code>#binding-cells</code>, etc). Here, the crucial properties are <code>bindings</code>
and <code>mods</code>, which spell out the actual functionality of the new behavior. The rest
of the snippet (including the nested node-structure) is boilerplate.</p>
<p>The idea of the <em>nodefree</em> repo is to use C preprocessor macros to improve
readability by eliminating as much boilerplate as possible. Besides hiding
redundant behavior properties from the user, it also automatically creates and
nests all required behavior nodes, making for a "node-free" and less
error-prone user experience (hence the name of the repo).</p>
<p>For example, using <code>ZMK_BEHAVIOR</code>, one of the repo's helper functions, the
above snippet simplifies to:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv codeBlockLinesWithNumbering_o6Pm" style="counter-reset:line-count 0"><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token function" style="color:#6f42c1">ZMK_BEHAVIOR</span><span class="token punctuation">(</span><span class="token plain">dot_colon</span><span class="token punctuation">,</span><span class="token plain"> mod_morph</span><span class="token punctuation">,</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">bindings</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> DOT</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> COLON</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">mods</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token punctuation">(</span><span class="token plain">MOD_LSFT</span><span class="token operator" style="color:#005cc5">|</span><span class="token plain">MOD_RSFT</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span></span><br></span><span class="token-line codeLine_lJS_" style="color:#24292e"><span class="codeLineNumber_Tfdd"></span><span class="codeLineContent_feaV"><span class="token plain"></span><span class="token punctuation">)</span></span><br></span></code></pre></div></div>
<p>For complex keymap files, the gains from eliminating boilerplate can be
enormous. To provide a benchmark, consider my <a href="https://github.com/urob/zmk-config" target="_blank" rel="noopener noreferrer" class="">personal
config</a>, which uses the <em>nodefree</em> repo to
create various behaviors, set up combos, and add layers to the keymap. Without
the <em>nodefree</em> helpers, the total size of my keymap would have been 41 kB. Using
the helper macros, the actual size is instead reduced to a more sane 12 kB.<sup><a href="https://zmk.dev/blog/2023/12/17/nodefree-config#user-content-fn-1-54748e" id="user-content-fnref-1-54748e" data-footnote-ref="" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">1</a></sup></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="simplifying-position-based-behaviors">Simplifying "Position-based" Behaviors<a href="https://zmk.dev/blog/2023/12/17/nodefree-config#simplifying-position-based-behaviors" class="hash-link" aria-label="Direct link to Simplifying &quot;Position-based&quot; Behaviors" title="Direct link to Simplifying &quot;Position-based&quot; Behaviors" translate="no">​</a></h2>
<p>In ZMK, there are several features that are position-based. As of today, these
are <a class="" href="https://zmk.dev/docs/keymaps/combos">combos</a> and <a class="" href="https://zmk.dev/docs/keymaps/behaviors/hold-tap#positional-hold-tap-and-hold-trigger-key-positions">positional
hold-taps</a>,
with behaviors like the <a href="https://github.com/zmkfirmware/zmk/pull/1366" target="_blank" rel="noopener noreferrer" class="">"Swapper"</a> and <a href="https://github.com/zmkfirmware/zmk/pull/1380" target="_blank" rel="noopener noreferrer" class="">Leader
key</a> currently
developed by <a href="https://github.com/nickconway" target="_blank" rel="noopener noreferrer" class="">Nick Conway</a> in pull requests also utilizing them.</p>
<p>Configuring these behaviors involves lots of key counting, which can be
cumbersome and error-prone, especially on larger keyboards. It also reduces the
portability of configuration files across keyboards with different layouts.</p>
<p>To facilitate configuring position-based behaviors, the <em>nodefree</em> repo comes
with a community-maintained library of "key-position labels" for a variety of
popular layouts. The idea is to provide a standardized naming convention that
is consistent across different keyboards. For instance, the labels for a 36-key
layout are as follows:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token plain">    ╭─────────────────────┬─────────────────────╮</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    │ LT4 LT3 LT2 LT1 LT0 │ RT0 RT1 RT2 RT3 RT4 │</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    │ LM4 LM3 LM2 LM1 LM0 │ RM0 RM1 RM2 RM3 RM4 │</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    │ LB4 LB3 LB2 LB1 LB0 │ RB0 RB1 RB2 RB3 RB4 │</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    ╰───────╮ LH2 LH1 LH0 │ RH0 RH1 RH2 ╭───────╯</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            ╰─────────────┴─────────────╯</span><br></span></code></pre></div></div>
<p>The labels are all of the following form:</p>
<ul>
<li class=""><code>L/R</code> for <strong>L</strong>eft/<strong>R</strong>ight side</li>
<li class=""><code>T/M/B/H</code> for <strong>T</strong>op/<strong>M</strong>iddle/<strong>B</strong>ottom and t<strong>H</strong>umb row.</li>
<li class=""><code>0/1/2/3/4</code> for the finger position, counting from the inside to the outside</li>
</ul>
<p>The library currently contains definitions for 17 physical
layouts, ranging from the tiny <a href="https://github.com/smores56/osprette" target="_blank" rel="noopener noreferrer" class="">Osprette</a> to the large-ish
<a href="https://www.moergo.com/collections/glove80-keyboards" target="_blank" rel="noopener noreferrer" class="">Glove80</a>.
While some of these layouts contain more keys than others, the idea behind the
library is that keys that for all practical purposes are in the "same" location
share the same label. That is, the 3 rows containing the alpha keys are
always labeled <code>T/M/B</code> with <code>LM1</code> and <code>RM1</code> defining the home position of
the index fingers. For larger boards, the numbers row is always labeled
<code>N</code>. For even larger boards, the function key row and the row below <code>B</code> are
labeled <code>C</code> and <code>F</code> (mnemonics for <strong>C</strong>eiling and <strong>F</strong>loor), etc.</p>
<p>Besides sparing the user from counting keys, the library also makes it easy to
port an entire, say, combo configuration from one keyboard to the next by simply
switching layout headers.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="unicode-and-international-keycodes">Unicode and International Keycodes<a href="https://zmk.dev/blog/2023/12/17/nodefree-config#unicode-and-international-keycodes" class="hash-link" aria-label="Direct link to Unicode and International Keycodes" title="Direct link to Unicode and International Keycodes" translate="no">​</a></h2>
<p>The final category of helpers is targeted at people who wish to type international characters
without switching the input language of their operation system. To do so, the repo comes with
helper functions that can be used to define Unicode behaviors.</p>
<p>In addition, the repo also ships with a community-maintained library of
language-files that define Unicode behaviors for all relevant characters in a
given language. For instance, after loading the German language file, one can
add <code>&amp;de_ae</code> to the keymap, which will send <kbd>ä</kbd>/<kbd>Ä</kbd> when pressed or shifted.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="about-me">About Me<a href="https://zmk.dev/blog/2023/12/17/nodefree-config#about-me" class="hash-link" aria-label="Direct link to About Me" title="Direct link to About Me" translate="no">​</a></h2>
<p>My path to ZMK and programmable keyboards started in the early pandemic, when I
built a <a href="https://geekhack.org/index.php?topic=88719.0" target="_blank" rel="noopener noreferrer" class="">Katana60</a> and learned
how to touch-type Colemak. Soon after I purchased a Planck, which turned out
to be the real gateway drug for me.</p>
<p>Committed to making the best out of the Planck's 48 keys, I have since
discovered my love for tinkering with tiny layouts and finding new ways of
<a href="https://xkcd.com/2583/" target="_blank" rel="noopener noreferrer" class="">squeezing out</a> a bit more ergonomics. Along the way, I
also made the switch from QMK to ZMK, whose "object-oriented" approach to
behaviors I found more appealing for complex keymaps.<sup><a href="https://zmk.dev/blog/2023/12/17/nodefree-config#user-content-fn-2-54748e" id="user-content-fnref-2-54748e" data-footnote-ref="" aria-describedby="footnote-label" class="anchorTargetStickyNavbar_Vzrq">2</a></sup></p>
<p>These days I mostly type on a Corne-ish Zen and are waiting for the day when I
will finally put together the
<a href="https://github.com/davidphilipbarr/hypergolic" target="_blank" rel="noopener noreferrer" class="">Hypergolic</a> that's been sitting
on my desk for months. My current keymap is designed for 34 keys, making
liberal use of combos and <a href="https://github.com/urob/zmk-config#timeless-homerow-mods" target="_blank" rel="noopener noreferrer" class="">timerless homerow
mods</a> to make up for
a lack of keys.</p>
<!-- -->
<section data-footnotes="" class="footnotes"><h2 class="anchor anchorTargetStickyNavbar_Vzrq sr-only" id="footnote-label">Footnotes<a href="https://zmk.dev/blog/2023/12/17/nodefree-config#footnote-label" class="hash-link" aria-label="Direct link to Footnotes" title="Direct link to Footnotes" translate="no">​</a></h2>
<ol>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-1-54748e">
<p>To compute the impact on file size, I ran <code>pcpp --passthru-unfound-includes</code> on the <code>base.keymap</code> file, comparing two
variants. First, I ran the pre-processor on the actual file. Second, I ran
it on a version where I commented out all the <em>nodefree</em> headers,
preventing any of the helper functions from getting expanded. The
difference isolates precisely the size gains from eliminating boilerplate,
which in my ZMK config are especially large due to a vast number of
behaviors used to add various Unicode characters to my keymap. <a href="https://zmk.dev/blog/2023/12/17/nodefree-config#user-content-fnref-1-54748e" data-footnote-backref="" aria-label="Back to reference 1" class="data-footnote-backref">↩</a></p>
</li>
<li class="anchorTargetStickyNavbar_Vzrq" id="user-content-fn-2-54748e">
<p>I am using the term object-oriented somewhat loosely here. What I mean by
that is the differentiation between abstract behavior classes (such as
hold-taps) and specific behavior instances that are added to the keymap.
Allowing to set up multiple, reusable instances of each behavior has been a
<em>huge</em> time-saver compared to QMK's more limited behavior settings that are
either global or key-specific. <a href="https://zmk.dev/blog/2023/12/17/nodefree-config#user-content-fnref-2-54748e" data-footnote-backref="" aria-label="Back to reference 2" class="data-footnote-backref">↩</a></p>
</li>
</ol>
</section>]]></content:encoded>
            <category>keyboards</category>
            <category>firmware</category>
            <category>community</category>
        </item>
        <item>
            <title><![CDATA[Community Spotlight Series #1: Keymap Editor]]></title>
            <link>https://zmk.dev/blog/2023/11/09/keymap-editor</link>
            <guid>https://zmk.dev/blog/2023/11/09/keymap-editor</guid>
            <pubDate>Thu, 09 Nov 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[This blog post is the first in a series of posts where we highlight projects within the ZMK ecosystem that we think are cool and that the users might benefit from knowing about them. We are starting the series with a big one, Keymap Editor by Nick Coutsos!]]></description>
            <content:encoded><![CDATA[<p>This blog post is the first in a series of posts where we highlight projects within the ZMK ecosystem that we think are cool and that the users might benefit from knowing about them. We are starting the series with a big one, <a href="http://nickcoutsos.github.io/keymap-editor" target="_blank" rel="noopener noreferrer" class="">Keymap Editor</a> by <a href="https://github.com/nickcoutsos" target="_blank" rel="noopener noreferrer" class="">Nick Coutsos</a>!</p>
<!-- -->
<img src="https://zmk.dev/assets/images/editor-screenshot-light-707323ca782303b6830ed3d3750a0b52.png" alt="Shows a screenshot of the Keymap Editor application featuring a graphical layout of the Corne Keyboard with a keymap loaded from the nickcoutsos/keymap-editor-demo-crkbd GitHub repository." class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="https://zmk.dev/assets/images/editor-screenshot-dark-4c109007871ed8f09907e58e035c8df8.png" alt="Shows a screenshot of the Keymap Editor application featuring a graphical layout of the Corne Keyboard with a keymap loaded from the nickcoutsos/keymap-editor-demo-crkbd GitHub repository." class="themedComponent_mlkZ themedComponent--dark_xIcU">
<p>In the rest of the post we leave it to Nick himself to introduce the project, detail his goals and motivation in developing such a tool, and talk about the future of the project. Stay tuned for future installments in the series!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-is-keymap-editor">What is Keymap Editor?<a href="https://zmk.dev/blog/2023/11/09/keymap-editor#what-is-keymap-editor" class="hash-link" aria-label="Direct link to What is Keymap Editor?" title="Direct link to What is Keymap Editor?" translate="no">​</a></h2>
<p><em><a href="http://nickcoutsos.github.io/keymap-editor" target="_blank" rel="noopener noreferrer" class="">Keymap Editor</a></em> is a web based graphical editor for ZMK keymaps. It provides a visual way to manage the contents of your keymap and if nothing else offers two critical features:</p>
<ol>
<li class="">Automatic formatting of the keymap file, so that bindings arrays remain readable</li>
<li class="">Searchable behaviors, keycodes, commands, etc, so you won't have to remember if it's <code>LCTL</code> or <code>LCTRL</code> (I just had to double check myself and I guessed wrong, apparently)</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-can-keymap-editor-do">What can Keymap Editor do?<a href="https://zmk.dev/blog/2023/11/09/keymap-editor#what-can-keymap-editor-do" class="hash-link" aria-label="Direct link to What can Keymap Editor do?" title="Direct link to What can Keymap Editor do?" translate="no">​</a></h2>
<ul>
<li class="">Render <a class="" href="https://zmk.dev/docs/keymaps">devicetree keymaps</a> using pre-defined, auto-generated, or side-loadable keyboard layouts</li>
<li class="">Integrate with a GitHub repo to streamline firmware builds, or FileSystem/Clipboard if you'd still rather build locally</li>
<li class="">Edit <a class="" href="https://zmk.dev/docs/keymaps/combos">combos</a>, <a class="" href="https://zmk.dev/docs/keymaps/behaviors/key-press">behaviors</a>, <a class="" href="https://zmk.dev/docs/keymaps/behaviors/macros">macros</a>, <a class="" href="https://zmk.dev/docs/keymaps/conditional-layers">conditional layers</a> and <a class="" href="https://zmk.dev/docs/keymaps/behaviors/sensor-rotate">rotary encoder bindings</a></li>
<li class="">Manage references: moving a layer or renaming a behavior will look for references throughout your keymap and update them.</li>
</ul>
<p>But check back regularly, because I update pretty often. A recent significant achievement was enabling <a class="" href="https://zmk.dev/docs/keymaps/behaviors/macros#parameterized-macros">parameterized macros</a> and tying it in with my existing parameter type resolution so, yeah, you can finally create that reusable macro combining bluetooth profile selection with RGB backlight colour. Or use it for an actual useful thing, even. <em>(See also: <a href="https://github.com/nickcoutsos/keymap-editor/wiki/Using-Parameterized-Macros-in-Keymap-Editor" target="_blank" rel="noopener noreferrer" class="">Using Parameterized Macros in Keymap Editor</a>)</em></p>
<p>My goals are, broadly:</p>
<ul>
<li class=""><strong>Treat code as a first-class entity:</strong> as long as ZMK keymaps are described in devicetree code then an editor needs to produce readable devicetree code.</li>
<li class=""><strong>Flexibly support ZMK features:</strong> use of any ZMK keymap feature should theoretically be achievable within the app. In some cases this can mean more initial setup <em>(See also: <a href="https://github.com/nickcoutsos/keymap-editor/wiki/Autoshift-using-ZMK-behaviors" target="_blank" rel="noopener noreferrer" class="">my thoughts on implementing "autoshift"</a>)</em> but having that foundation makes its easier to add shortcuts and niceties — something I do quite often now.</li>
<li class=""><strong>Don't get in the way of not-yet-supported features:</strong> If a new ZMK feature is released and the app isn't able to add it natively, you can always edit your keymap file directly. While the app may not <em>recognize</em> the new features, further changes through the app should not break your keymap.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="history-of-keymap-editor">History of Keymap Editor<a href="https://zmk.dev/blog/2023/11/09/keymap-editor#history-of-keymap-editor" class="hash-link" aria-label="Direct link to History of Keymap Editor" title="Direct link to History of Keymap Editor" translate="no">​</a></h2>
<p>When I started writing Keymap Editor I had a handwired Dactyl variant running QMK. Manually editing keymap code was fine, but keeping things readable was important to me, and automating that was the best way to ensure consistency. Programmatically modifying source code was beyond me at the time so the first version persisted keymap data in JSON and spat out formatted versions of both the JSON and C keymaps.</p>
<p>After switching to ZMK I added a few more features, I guess as a pandemic project, and then gradually migrated from generating a templated keymap file to manipulating devicetree syntax directly, and that has made a big difference in adding new ZMK features.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-am-i-doing-this">Why am I doing this?<a href="https://zmk.dev/blog/2023/11/09/keymap-editor#why-am-i-doing-this" class="hash-link" aria-label="Direct link to Why am I doing this?" title="Direct link to Why am I doing this?" translate="no">​</a></h2>
<p>It started out as a useful tool for me. I shared it with the ZMK community and gained a little traction, and then apparently quite a bit of traction — turns out it's useful for a lot of people.</p>
<p>I'm a software developer because I enjoy building things. Much of my day-to-day work isn't user facing, so seeing how helpful the keymap editor has been for people in the ZMK community is a big motivator to keep improving it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="future-plans">Future plans<a href="https://zmk.dev/blog/2023/11/09/keymap-editor#future-plans" class="hash-link" aria-label="Direct link to Future plans" title="Direct link to Future plans" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="runtime-updates">Runtime updates<a href="https://zmk.dev/blog/2023/11/09/keymap-editor#runtime-updates" class="hash-link" aria-label="Direct link to Runtime updates" title="Direct link to Runtime updates" translate="no">​</a></h3>
<p>Streamlining the keymap update process is probably top of mind for most users, but that involves a really big <em>firmware</em> feature, and I'm the wrong person to tackle it.</p>
<p>That said, once there's a protocol I would <em>absolutely</em> be down to integrate it as an additional keymap source. Being able to pull data directly from the keyboard should unlock a lot of possibilities and ease some of the constraints imposed by using devicetree code as a medium.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="simplifying-behavior-use">Simplifying behavior use<a href="https://zmk.dev/blog/2023/11/09/keymap-editor#simplifying-behavior-use" class="hash-link" aria-label="Direct link to Simplifying behavior use" title="Direct link to Simplifying behavior use" translate="no">​</a></h3>
<p>I think a lot of people would like to see the concept of behaviors abstracted away for new users and to prompt them with</p>
<ul>
<li class=""><em>"When the key is tapped..."</em>,</li>
<li class=""><em>"When the key is held..."</em>,</li>
<li class=""><em>"When the key is double-tapped..."</em> and so on.</li>
</ul>
<p>Users who are less familiar with ZMK's behaviors and how they are composed may find these prompts to be more intuitive, and their answers could be mapped to an appropriate combination of behaviors managed internally by an editor.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="uh-what-else">Uh, what else?<a href="https://zmk.dev/blog/2023/11/09/keymap-editor#uh-what-else" class="hash-link" aria-label="Direct link to Uh, what else?" title="Direct link to Uh, what else?" translate="no">​</a></h3>
<p>This has been long enough already, if you're looking for a feature I haven't mentioned don't assume I won't add it. Feel free to make feature requests on the GitHub repo, and I'd be happy to discuss it!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="about-me-and-my-keebs">About Me And My Keebs<a href="https://zmk.dev/blog/2023/11/09/keymap-editor#about-me-and-my-keebs" class="hash-link" aria-label="Direct link to About Me And My Keebs" title="Direct link to About Me And My Keebs" translate="no">​</a></h2>
<p>I like computers and write software. Many in this field enjoy using mechanical
keyboards for their feel or aesthetics, but what piqued my interest was the
Dactyl keyboard. I think, ergonomics aside, I'm more interested in the DIY/maker
aspect than the collecting of keyboards and switches.</p>
<p>So <a href="https://github.com/nickcoutsos/dactyl-flatpacked/" target="_blank" rel="noopener noreferrer" class="">I made a Dactyl</a>, and
then <a href="https://github.com/nickcoutsos/dactyl-deskmount/" target="_blank" rel="noopener noreferrer" class="">I made another Dactyl</a>
and I made a third Dactyl that isn't interesting enough to photograph, but now
I'm using ZMK so I left room for 18650 cells.</p>
<p>That last Dactyl (with MX browns and a cheap blank XDA keycap set) serves me
well the eight or so hours a day I'll spend at my desk, but I also spend a good
deal of time computing on my couch where I'll use... my Macbook's built-in
keyboard.</p>
<p>In case that's not surprising enough I'll leave you with this: despite all of
the work and testing I've put into the keymap editor project, I've only updated
an actual keymap once in the last year.</p>
<p>Thank you and good night.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="more-information">More information<a href="https://zmk.dev/blog/2023/11/09/keymap-editor#more-information" class="hash-link" aria-label="Direct link to More information" title="Direct link to More information" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://github.com/nickcoutsos/keymap-editor/wiki" target="_blank" rel="noopener noreferrer" class="">Keymap Editor Wiki</a></li>
<li class=""><a href="https://github.com/nickcoutsos/keymap-editor/discussions" target="_blank" rel="noopener noreferrer" class="">Keymap Editor Discussions</a></li>
<li class="">(YouTube video) <a href="https://www.youtube.com/watch?v=Vy7IoQAe3oU" target="_blank" rel="noopener noreferrer" class="">Ben Frain's overview of the Keymap Editor</a></li>
</ul>]]></content:encoded>
            <category>keyboards</category>
            <category>firmware</category>
            <category>community</category>
        </item>
        <item>
            <title><![CDATA[ZMK State Of The Firmware #6]]></title>
            <link>https://zmk.dev/blog/2023/10/05/zmk-sotf-6</link>
            <guid>https://zmk.dev/blog/2023/10/05/zmk-sotf-6</guid>
            <pubDate>Thu, 05 Oct 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Welcome to the sixth ZMK "State Of The Firmware" (SOTF)!]]></description>
            <content:encoded><![CDATA[<p>Welcome to the sixth ZMK "State Of The Firmware" (SOTF)!</p>
<p>This update will cover all the major activity since <a class="" href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5">SOTF #5</a>. That was over a year ago (again!), so there are many new exciting features and plenty of improvements to cover!</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="recent-activity">Recent Activity<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#recent-activity" class="hash-link" aria-label="Direct link to Recent Activity" title="Direct link to Recent Activity" translate="no">​</a></h2>
<p>Here's a summary of the various major changes since last time, broken down by theme:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="keymapsbehaviors">Keymaps/Behaviors<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#keymapsbehaviors" class="hash-link" aria-label="Direct link to Keymaps/Behaviors" title="Direct link to Keymaps/Behaviors" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="hold-tap-improvements">Hold-tap improvements<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#hold-tap-improvements" class="hash-link" aria-label="Direct link to Hold-tap improvements" title="Direct link to Hold-tap improvements" translate="no">​</a></h4>
<p><a href="https://github.com/andrewjrae" target="_blank" rel="noopener noreferrer" class="">andrewjrae</a> added the <a class="" href="https://zmk.dev/docs/keymaps/behaviors/hold-tap#require-prior-idle-ms"><code>require-prior-idle-ms</code> property</a> to the hold-tap behavior in <a href="https://github.com/zmkfirmware/zmk/pull/1187" target="_blank" rel="noopener noreferrer" class="">#1187</a> and <a href="https://github.com/zmkfirmware/zmk/pull/1387" target="_blank" rel="noopener noreferrer" class="">#1387</a>, which prevents the hold behavior from triggering if it hasn't been a certain duration since the last key press. This is a useful feature to prevent accidental hold activations during quick typing and made its way into many keymaps! The same property was added to <a class="" href="https://zmk.dev/docs/keymaps/combos#configuration">combos</a> as well to help prevent false combo activations.</p>
<p>Note that an earlier iteration of this feature was supported with the <code>global-quick-tap</code> property, which did not allow customizing the timeout and used the value of <code>quick-tap-ms</code> for it. This property is now deprecated and users are encouraged to use <code>require-prior-idle-ms</code> instead.</p>
<p><a href="https://github.com/urob" target="_blank" rel="noopener noreferrer" class="">urob</a> added the <a class="" href="https://zmk.dev/docs/keymaps/behaviors/hold-tap#positional-hold-tap-and-hold-trigger-key-positions"><code>hold-trigger-on-release</code> property</a> in <a href="https://github.com/zmkfirmware/zmk/pull/1423" target="_blank" rel="noopener noreferrer" class="">#1423</a>. This significantly increases the usefulness of positional constraints on hold-taps, since it allows combining multiple holds such as different modifiers for home row mods usage.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="masking-mods-in-mod-morphs">Masking mods in mod-morphs<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#masking-mods-in-mod-morphs" class="hash-link" aria-label="Direct link to Masking mods in mod-morphs" title="Direct link to Masking mods in mod-morphs" translate="no">​</a></h4>
<p><a href="https://github.com/aumuell" target="_blank" rel="noopener noreferrer" class="">aumuell</a>, <a href="https://github.com/vrinek" target="_blank" rel="noopener noreferrer" class="">vrinek</a> and <a href="https://github.com/urob" target="_blank" rel="noopener noreferrer" class="">urob</a> contributed to improving the behavior of <a class="" href="https://zmk.dev/docs/keymaps/behaviors/mod-morph">mod-morphs</a> by masking the triggering modifiers and added <code>keep-mods</code> property in <a href="https://github.com/zmkfirmware/zmk/pull/1412" target="_blank" rel="noopener noreferrer" class="">#1412</a>. This unlocks more use cases for mod-morphs, since you are no longer constrained to emitting keycodes that work well with the triggering modifier keycodes.</p>
<p>As an example, you can now define a mod-morph that swaps <code>;</code> and <code>:</code> so that the former is the shifted version of the latter, which wasn't previously possible:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token label symbol" style="color:#e36209">col_semi:</span><span class="token plain"> </span><span class="token node class-name" style="color:#6f42c1">colon_semicolon</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"zmk,behavior-mod-morph"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">#binding-cells</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">0</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">bindings</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> COLON</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> SEMI</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">mods</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token punctuation">(</span><span class="token plain">MOD_LSFT</span><span class="token operator" style="color:#005cc5">|</span><span class="token plain">MOD_RSFT</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="parameterized-macros">Parameterized macros<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#parameterized-macros" class="hash-link" aria-label="Direct link to Parameterized macros" title="Direct link to Parameterized macros" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> added <a class="" href="https://zmk.dev/docs/keymaps/behaviors/macros#parameterized-macros">macros that can be parameterized</a> with one or two parameters in <a href="https://github.com/zmkfirmware/zmk/pull/1232" target="_blank" rel="noopener noreferrer" class="">#1232</a>. This allows users to define macros in a more modular way and is a nice quality-of-life improvement.</p>
<p>As a simple example, you could define a macro that puts any keycode provided between double quotes as below, then use it like <code>&amp;ql A</code> in your keymap:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token label symbol" style="color:#e36209">ql:</span><span class="token plain"> </span><span class="token node class-name" style="color:#6f42c1">quoted_letter</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">#binding-cells</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">1</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"zmk,behavior-macro-one-param"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">bindings</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> DQT</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;macro_param_1to1</span><span class="token plain"> </span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> MACRO_PLACEHOLDER</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> DQT</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<p>Please see the documentation page linked above for usage and more examples.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="arbitrary-behaviors-on-encoder-rotation">Arbitrary behaviors on encoder rotation<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#arbitrary-behaviors-on-encoder-rotation" class="hash-link" aria-label="Direct link to Arbitrary behaviors on encoder rotation" title="Direct link to Arbitrary behaviors on encoder rotation" translate="no">​</a></h4>
<p><a href="https://github.com/nickconway" target="_blank" rel="noopener noreferrer" class="">nickconway</a> and <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> added <a class="" href="https://zmk.dev/docs/keymaps/behaviors/sensor-rotate">sensor rotation behaviors</a> to allow invoking arbitrary behaviors from encoders <a href="https://github.com/zmkfirmware/zmk/pull/1758" target="_blank" rel="noopener noreferrer" class="">#1758</a>. Previously encoder rotations could only invoke the key-press behavior <code>&amp;kp</code> through the <code>&amp;inc_dec_kp</code> binding, whereas now you can define new sensor rotation behaviors to invoke others.</p>
<p>(Note that currently behaviors that have "locality" such as <code>&amp;rgb_ug</code> do not work as expected via encoder rotation bindings in split keyboards, due to issue <a href="https://github.com/zmkfirmware/zmk/issues/1494" target="_blank" rel="noopener noreferrer" class="">#1494</a>.)</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="pre-releasing-already-pressed-keys">Pre-releasing already pressed keys<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#pre-releasing-already-pressed-keys" class="hash-link" aria-label="Direct link to Pre-releasing already pressed keys" title="Direct link to Pre-releasing already pressed keys" translate="no">​</a></h4>
<p><a href="https://github.com/andrewjrae" target="_blank" rel="noopener noreferrer" class="">andrewjrae</a> contributed a tweak to emitting keycodes in <a href="https://github.com/zmkfirmware/zmk/pull/1828" target="_blank" rel="noopener noreferrer" class="">#1828</a>, where rolling multiple keys that involve the same keycode now releases the keycode before sending a press event again. While this might sound like a technical distinction, it leads to more correct behavior when quickly typing sequences like <code>+=</code> and makes the <a class="" href="https://zmk.dev/docs/keymaps/behaviors/key-repeat">key repeat behavior</a> work properly when it is pressed before the previous key is released.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="key-toggle-behavior">Key toggle behavior<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#key-toggle-behavior" class="hash-link" aria-label="Direct link to Key toggle behavior" title="Direct link to Key toggle behavior" translate="no">​</a></h4>
<p><a href="https://github.com/cgoates" target="_blank" rel="noopener noreferrer" class="">cgoates</a> added the <a class="" href="https://zmk.dev/docs/keymaps/behaviors/key-toggle">key toggle behavior</a> in <a href="https://github.com/zmkfirmware/zmk/pull/1278" target="_blank" rel="noopener noreferrer" class="">#1278</a>, which can be used via its <code>&amp;kt</code> binding to toggle the state of a keycode between pressed and released.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="apple-globe-key">Apple Globe key<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#apple-globe-key" class="hash-link" aria-label="Direct link to Apple Globe key" title="Direct link to Apple Globe key" translate="no">​</a></h4>
<p><a href="https://github.com/ReFil" target="_blank" rel="noopener noreferrer" class="">ReFil</a> added support for the <code>C_AC_NEXT_KEYBOARD_LAYOUT_SELECT</code> keycode with alias <code>GLOBE</code> which acts as the Globe key in macOS and iOS in <a href="https://github.com/zmkfirmware/zmk/pull/1938" target="_blank" rel="noopener noreferrer" class="">#1938</a>. Note that this keycode doesn't exactly behave like a Globe key that is present on an Apple keyboard and its limitations are documented in <a href="https://github.com/zmkfirmware/zmk/pull/1938#issuecomment-1744579039" target="_blank" rel="noopener noreferrer" class="">this comment</a> thanks to testing by <a href="https://github.com/SethMilliken" target="_blank" rel="noopener noreferrer" class="">SethMilliken</a>. These limitations will be noted in the official <a class="" href="https://zmk.dev/docs/keymaps/list-of-keycodes">keycodes documentation</a> shortly.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="bug-fixes-and-other-improvements">Bug fixes and other improvements<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#bug-fixes-and-other-improvements" class="hash-link" aria-label="Direct link to Bug fixes and other improvements" title="Direct link to Bug fixes and other improvements" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a>, <a href="https://github.com/andrewjrae" target="_blank" rel="noopener noreferrer" class="">andrewjrae</a> and <a href="https://github.com/okke-formsma" target="_blank" rel="noopener noreferrer" class="">okke-formsma</a> tracked down and fixed an issue causing stuck keys when there are combos on key positions involving hold-tap behaviors in <a href="https://github.com/zmkfirmware/zmk/pull/1411" target="_blank" rel="noopener noreferrer" class="">#1411</a>. This was an elusive bug that took a lot of effort from the community to nail down and fix!</p>
<p><a href="https://github.com/nguyendown" target="_blank" rel="noopener noreferrer" class="">nguyendown</a> and <a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">joelspadin</a> tracked down and fixed a couple issues causing stuck keys with <a class="" href="https://zmk.dev/docs/keymaps/behaviors/sticky-key">sticky keys</a> in <a href="https://github.com/zmkfirmware/zmk/pull/1586" target="_blank" rel="noopener noreferrer" class="">#1586</a>, <a href="https://github.com/zmkfirmware/zmk/pull/1745" target="_blank" rel="noopener noreferrer" class="">#1745</a>.</p>
<p><a href="https://github.com/okke-formsma" target="_blank" rel="noopener noreferrer" class="">okke-formsma</a> fixed an issue allowing tap dances to be invoked by combos in <a href="https://github.com/zmkfirmware/zmk/pull/1518" target="_blank" rel="noopener noreferrer" class="">#1518</a>.</p>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> tweaked the caps word behavior to ignore modifiers in <a href="https://github.com/zmkfirmware/zmk/pull/1330" target="_blank" rel="noopener noreferrer" class="">#1330</a>.</p>
<p><a href="https://github.com/HelloThisIsFlo" target="_blank" rel="noopener noreferrer" class="">HelloThisIsFlo</a> documented a bug with combos involving overlapping keys and different timeouts, produced a reproducing unit test, then proceeded to fix it in <a href="https://github.com/zmkfirmware/zmk/pull/1945" target="_blank" rel="noopener noreferrer" class="">#1945</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="bluetooth-and-split-improvements">Bluetooth and Split Improvements<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#bluetooth-and-split-improvements" class="hash-link" aria-label="Direct link to Bluetooth and Split Improvements" title="Direct link to Bluetooth and Split Improvements" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="multiple-peripherals">Multiple peripherals<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#multiple-peripherals" class="hash-link" aria-label="Direct link to Multiple peripherals" title="Direct link to Multiple peripherals" translate="no">​</a></h4>
<p><a href="https://github.com/xudongzheng" target="_blank" rel="noopener noreferrer" class="">xudongzheng</a> contributed to add support for more than one peripheral per keyboard in <a href="https://github.com/zmkfirmware/zmk/pull/836" target="_blank" rel="noopener noreferrer" class="">#836</a>. This allows setups such as split keyboards with more than two halves, or enable a BLE-based "dongle mode" via a third device running ZMK that can stay connected to a computer via USB.</p>
<p>Note that documentation is still lacking for utilizing more than one peripheral and there will potentially be future changes in the build system to allow for more seamless configuration.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="pairing-passkey-requirement">Pairing passkey requirement<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#pairing-passkey-requirement" class="hash-link" aria-label="Direct link to Pairing passkey requirement" title="Direct link to Pairing passkey requirement" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> added <a class="" href="https://zmk.dev/docs/config/bluetooth">the option to require passkey input</a> while pairing to new devices in <a href="https://github.com/zmkfirmware/zmk/pull/1822" target="_blank" rel="noopener noreferrer" class="">#1822</a>. Enabling this will require you to enter a six digit passcode via the number keys on your keymap and press enter when pairing to a new device, enhancing security during the pairing procedure.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="split-keyboard-improvements">Split keyboard improvements<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#split-keyboard-improvements" class="hash-link" aria-label="Direct link to Split keyboard improvements" title="Direct link to Split keyboard improvements" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> contributed a fix to release held keys on peripheral disconnect <a href="https://github.com/zmkfirmware/zmk/pull/1340" target="_blank" rel="noopener noreferrer" class="">#1340</a>, which makes scenarios where a split disconnects unexpectedly less painful.</p>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> also improved <a class="" href="https://zmk.dev/docs/troubleshooting/connection-issues#split-keyboard-parts-unable-to-pair">the <code>settings_reset</code> shield</a> by making it clear bonds more reliably, and allow it to build for all boards in <a href="https://github.com/zmkfirmware/zmk/pull/1879" target="_blank" rel="noopener noreferrer" class="">#1879</a>.</p>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> and <a href="https://github.com/xudongzheng" target="_blank" rel="noopener noreferrer" class="">xudongzheng</a> contributed additional split connectivity improvements, via using directed advertising in <a href="https://github.com/zmkfirmware/zmk/pull/1913" target="_blank" rel="noopener noreferrer" class="">#1913</a> and improving the robustness of central scanning in <a href="https://github.com/zmkfirmware/zmk/pull/1912" target="_blank" rel="noopener noreferrer" class="">#1912</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="hardware-support">Hardware Support<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#hardware-support" class="hash-link" aria-label="Direct link to Hardware Support" title="Direct link to Hardware Support" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="encoders">Encoders<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#encoders" class="hash-link" aria-label="Direct link to Encoders" title="Direct link to Encoders" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> contributed a major refactor of encoder (and more generally sensor) functionality in <a href="https://github.com/zmkfirmware/zmk/pull/1039" target="_blank" rel="noopener noreferrer" class="">#1039</a>. While the documentation for these changes are still in progress, check out the <a class="" href="https://zmk.dev/blog/2023/06/18/encoder-refactors">dedicated blog post</a> for more details.</p>
<p>This refactor paved way to implementing a long-awaited feature, encoder support in peripheral halves of split keyboards! Building upon the work by <a href="https://github.com/stephen" target="_blank" rel="noopener noreferrer" class="">stephen</a> in <a href="https://github.com/zmkfirmware/zmk/pull/728" target="_blank" rel="noopener noreferrer" class="">#728</a>, <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> implemented support in <a href="https://github.com/zmkfirmware/zmk/pull/1841" target="_blank" rel="noopener noreferrer" class="">#1841</a>.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="direct-gpio-driver">Direct GPIO driver<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#direct-gpio-driver" class="hash-link" aria-label="Direct link to Direct GPIO driver" title="Direct link to Direct GPIO driver" translate="no">​</a></h4>
<p><a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">joelspadin</a> extended the comprehensive debouncing framework used for matrix scan driver to the <a class="" href="https://zmk.dev/docs/config/kscan#direct-gpio-driver">direct GPIO driver</a> in <a href="https://github.com/zmkfirmware/zmk/pull/1288" target="_blank" rel="noopener noreferrer" class="">#1288</a>.</p>
<p><a href="https://github.com/kurtis-lew" target="_blank" rel="noopener noreferrer" class="">kurtis-lew</a> added toggle mode support for direct GPIO driver in <a href="https://github.com/zmkfirmware/zmk/pull/1305" target="_blank" rel="noopener noreferrer" class="">#1305</a>. This allows for adding toggle switches to a keyboard, by properly reading their initial state on boot and making sure the power use is efficient.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="io-peripheral-drivers">IO peripheral drivers<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#io-peripheral-drivers" class="hash-link" aria-label="Direct link to IO peripheral drivers" title="Direct link to IO peripheral drivers" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> added support for the 595 shift register commonly used with smaller controllers like Seeeduino Xiaos, in <a href="https://github.com/zmkfirmware/zmk/pull/1325" target="_blank" rel="noopener noreferrer" class="">#1325</a>.</p>
<p><a href="https://github.com/zhiayang" target="_blank" rel="noopener noreferrer" class="">zhiayang</a> added the driver for the MAX7318 GPIO expander in <a href="https://github.com/zmkfirmware/zmk/pull/1295" target="_blank" rel="noopener noreferrer" class="">#1295</a>.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="underglow-auto-off-options">Underglow auto-off options<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#underglow-auto-off-options" class="hash-link" aria-label="Direct link to Underglow auto-off options" title="Direct link to Underglow auto-off options" translate="no">​</a></h4>
<p><a href="https://github.com/ReFil" target="_blank" rel="noopener noreferrer" class="">ReFil</a> added two <a class="" href="https://zmk.dev/docs/config/lighting#rgb-underglow">new RGB auto off options</a>, one using an idle timeout and the other USB status in <a href="https://github.com/zmkfirmware/zmk/pull/1010" target="_blank" rel="noopener noreferrer" class="">#1010</a>.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="niceview-support">nice!view support<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#niceview-support" class="hash-link" aria-label="Direct link to nice!view support" title="Direct link to nice!view support" translate="no">​</a></h4>
<p><a href="https://github.com/Nicell" target="_blank" rel="noopener noreferrer" class="">nicell</a> added support for nice!view, a memory display optimized for low power use in <a href="https://github.com/zmkfirmware/zmk/pull/1462" target="_blank" rel="noopener noreferrer" class="">#1462</a>.
He also contributed a custom vertically-oriented status screen that is automatically enabled when the <code>nice_view</code> shield is used in <a href="https://github.com/zmkfirmware/zmk/pull/1768" target="_blank" rel="noopener noreferrer" class="">#1768</a>, since the default status screen has a horizontal orientation.
Please see the instructions in the <a href="https://github.com/zmkfirmware/zmk/blob/main/app/boards/shields/nice_view/README.md" target="_blank" rel="noopener noreferrer" class="">nice!view README</a> if you would like to restore the stock status screen.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="e-paper-display-initialization">E-paper display initialization<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#e-paper-display-initialization" class="hash-link" aria-label="Direct link to E-paper display initialization" title="Direct link to E-paper display initialization" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> contributed EPD initialization improvements in <a href="https://github.com/zmkfirmware/zmk/pull/1098" target="_blank" rel="noopener noreferrer" class="">#1098</a>, which makes the keyboards using slow refresh displays such as the Corne-ish Zen much more responsive during initial boot.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="xiao-ble-improvements">Xiao BLE improvements<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#xiao-ble-improvements" class="hash-link" aria-label="Direct link to Xiao BLE improvements" title="Direct link to Xiao BLE improvements" translate="no">​</a></h4>
<p>Various improvements were made for the Seeeduino Xiao BLE board in <a href="https://github.com/zmkfirmware/zmk/pull/1293" target="_blank" rel="noopener noreferrer" class="">#1293</a>, <a href="https://github.com/zmkfirmware/zmk/commit/d0176f36" target="_blank" rel="noopener noreferrer" class="">d0176f36</a>, <a href="https://github.com/zmkfirmware/zmk/pull/1545" target="_blank" rel="noopener noreferrer" class="">#1545</a> and <a href="https://github.com/zmkfirmware/zmk/pull/1927" target="_blank" rel="noopener noreferrer" class="">#1927</a> by <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> and <a href="https://github.com/caksoylar" target="_blank" rel="noopener noreferrer" class="">caksoylar</a>, enabling features necessary for ZMK and improving its power use.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="zephyr-32-upgrade">Zephyr 3.2 Upgrade<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#zephyr-32-upgrade" class="hash-link" aria-label="Direct link to Zephyr 3.2 Upgrade" title="Direct link to Zephyr 3.2 Upgrade" translate="no">​</a></h3>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> once again contributed the massive work necessary for upgrading ZMK to Zephyr 3.2 in <a href="https://github.com/zmkfirmware/zmk/pull/1499" target="_blank" rel="noopener noreferrer" class="">#1499</a>, with review help from <a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">joelspadin</a> and testing by the community. This Zephyr release brings with it upgrades to the display library LVGL, adds official support for the RP2040 controllers and many internal refactors to help future development.
Check out the <a class="" href="https://zmk.dev/blog/2023/04/06/zephyr-3-2">dedicated blog post</a> for more details!</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="documentation">Documentation<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#documentation" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="configuration-docs">Configuration docs<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#configuration-docs" class="hash-link" aria-label="Direct link to Configuration docs" title="Direct link to Configuration docs" translate="no">​</a></h4>
<p><a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">joelspadin</a>, through a massive amount of work in <a href="https://github.com/zmkfirmware/zmk/pull/722" target="_blank" rel="noopener noreferrer" class="">#722</a>, contributed a whole new section to the documentation: <a class="" href="https://zmk.dev/docs/config">configuration</a>! It enumerates the configuration options for each ZMK feature that might be relevant to users in dedicated pages, making it a very handy reference.</p>
<p>In addition, the <a class="" href="https://zmk.dev/docs/config">overview page</a> presents an overview of how configuration works in Zephyr in the context of ZMK, in terms of devicetree files (like the keymap files or shield overlays), and Kconfig ones (like the <code>.conf</code> files). It is very helpful in de-mystifying what the various files do and what syntax is expected in them.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-behavior-guide">New behavior guide<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#new-behavior-guide" class="hash-link" aria-label="Direct link to New behavior guide" title="Direct link to New behavior guide" translate="no">​</a></h4>
<p>For users or future contributors that might want to dive into writing their own ZMK behaviors, <a href="https://github.com/kurtis-lew" target="_blank" rel="noopener noreferrer" class="">kurtis-lew</a> wrote a useful <a class="" href="https://zmk.dev/docs/development/new-behavior">guide on how to create new behaviors</a> in <a href="https://github.com/zmkfirmware/zmk/pull/1268" target="_blank" rel="noopener noreferrer" class="">#1268</a>.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="tap-dance-and-hold-tap-documentation-improvements">Tap dance and hold-tap documentation improvements<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#tap-dance-and-hold-tap-documentation-improvements" class="hash-link" aria-label="Direct link to Tap dance and hold-tap documentation improvements" title="Direct link to Tap dance and hold-tap documentation improvements" translate="no">​</a></h4>
<p><a href="https://github.com/kurtis-lew" target="_blank" rel="noopener noreferrer" class="">kurtis-lew</a> also improved the documentation for these two behaviors in <a href="https://github.com/zmkfirmware/zmk/pull/1298" target="_blank" rel="noopener noreferrer" class="">#1298</a>, by updating the diagrams to better clarify how their timings work and adding examples for scenarios that are frequently asked by users.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="battery-sensor-documentation">Battery sensor documentation<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#battery-sensor-documentation" class="hash-link" aria-label="Direct link to Battery sensor documentation" title="Direct link to Battery sensor documentation" translate="no">​</a></h4>
<p><a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">joelspadin</a> also added documentation for setting up battery sensors, typically required for new boards, in <a href="https://github.com/zmkfirmware/zmk/pull/868" target="_blank" rel="noopener noreferrer" class="">#868</a>.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="shield-interconnects">Shield interconnects<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#shield-interconnects" class="hash-link" aria-label="Direct link to Shield interconnects" title="Direct link to Shield interconnects" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> updated the <a class="" href="https://zmk.dev/docs/development/hardware-integration/new-shield">new shield guide</a> for non-Pro Micro interconnects including Xiao, Arduino Uno and Blackpill in <a href="https://github.com/zmkfirmware/zmk/pull/1607" target="_blank" rel="noopener noreferrer" class="">#1607</a>.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="bluetooth-feature-page">Bluetooth feature page<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#bluetooth-feature-page" class="hash-link" aria-label="Direct link to Bluetooth feature page" title="Direct link to Bluetooth feature page" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> and <a href="https://github.com/caksoylar" target="_blank" rel="noopener noreferrer" class="">caksoylar</a> added a new <a class="" href="https://zmk.dev/docs/features/bluetooth">Bluetooth feature page</a> as part of <a href="https://github.com/zmkfirmware/zmk/pull/1499" target="_blank" rel="noopener noreferrer" class="">#1499</a> and in <a href="https://github.com/zmkfirmware/zmk/pull/1499" target="_blank" rel="noopener noreferrer" class="">#1818</a>, detailing ZMK's Bluetooth implementation and troubleshooting for common problems.</p>
<p>In addition to the specific contributions listed above, various improvements and fixes to documentation are made by many users from the community, including but not limited to <a href="https://github.com/kurtis-lew" target="_blank" rel="noopener noreferrer" class="">kurtis-lew</a>, <a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">joelspadin</a>, <a href="https://github.com/filterpaper" target="_blank" rel="noopener noreferrer" class="">filterpaper</a>, <a href="https://github.com/byran.tech" target="_blank" rel="noopener noreferrer" class="">byran.tech</a>, <a href="https://github.com/dxmh" target="_blank" rel="noopener noreferrer" class="">dxmh</a> and <a href="https://github.com/caksoylar" target="_blank" rel="noopener noreferrer" class="">caksoylar</a>. These contributions are are all very appreciated!</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="miscellaneous">Miscellaneous<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#miscellaneous" class="hash-link" aria-label="Direct link to Miscellaneous" title="Direct link to Miscellaneous" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="reusable-github-build-workflow">Reusable GitHub build workflow<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#reusable-github-build-workflow" class="hash-link" aria-label="Direct link to Reusable GitHub build workflow" title="Direct link to Reusable GitHub build workflow" translate="no">​</a></h4>
<p><a href="https://github.com/elagil" target="_blank" rel="noopener noreferrer" class="">elagil</a> helped switch the build workflow used by the <a class="" href="https://zmk.dev/docs/user-setup">user config repos</a> to a reusable one in <a href="https://github.com/zmkfirmware/zmk/pull/1183" target="_blank" rel="noopener noreferrer" class="">#1183</a> and it was further tweaked by <a href="https://github.com/filterpaper" target="_blank" rel="noopener noreferrer" class="">filterpaper</a> in <a href="https://github.com/zmkfirmware/zmk/pull/1258" target="_blank" rel="noopener noreferrer" class="">#1258</a>. This allows any changes in the workflow to be propagated automatically to users, rather than requiring them to make the updates. The build workflow can be customized by the users <a href="https://github.com/zmkfirmware/zmk/blob/main/.github/workflows/build-user-config.yml#L5" target="_blank" rel="noopener noreferrer" class="">using input parameters</a> if desired.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="pre-commit-hooks">Pre-commit hooks<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#pre-commit-hooks" class="hash-link" aria-label="Direct link to Pre-commit hooks" title="Direct link to Pre-commit hooks" translate="no">​</a></h4>
<p><a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">joelspadin</a> added various <a href="https://pre-commit.com/" target="_blank" rel="noopener noreferrer" class="">pre-commit</a> hooks and added checks to the repo to run them for each commit in <a href="https://github.com/zmkfirmware/zmk/pull/1651" target="_blank" rel="noopener noreferrer" class="">#1651</a>. These hooks and resulting updates standardize formatting across devicetree and other source files, reducing busywork on both contributors and reviewers.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="zephyr-usage-and-other-refactors">Zephyr usage and other refactors<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#zephyr-usage-and-other-refactors" class="hash-link" aria-label="Direct link to Zephyr usage and other refactors" title="Direct link to Zephyr usage and other refactors" translate="no">​</a></h4>
<p><a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">joelspadin</a> also contributed a few refactor PRs such as <a href="https://github.com/zmkfirmware/zmk/pull/1269" target="_blank" rel="noopener noreferrer" class="">#1269</a>, <a href="https://github.com/zmkfirmware/zmk/pull/1255" target="_blank" rel="noopener noreferrer" class="">#1255</a> and <a href="https://github.com/zmkfirmware/zmk/pull/1803" target="_blank" rel="noopener noreferrer" class="">#1803</a>, generally improving code quality and bringing the codebase in line with the latest Zephyr conventions.</p>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> refactored the drivers structure to bring it in line with the current Zephyr conventions for out-of-tree drivers in <a href="https://github.com/zmkfirmware/zmk/pull/1919" target="_blank" rel="noopener noreferrer" class="">#1919</a>.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="updated-usb-polling-interval-default">Updated USB polling interval default<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#updated-usb-polling-interval-default" class="hash-link" aria-label="Direct link to Updated USB polling interval default" title="Direct link to Updated USB polling interval default" translate="no">​</a></h4>
<p>USB HID polling interval now defaults to 1 ms, i.e. a 1000Hz polling rate, thanks to <a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">joelspadin</a>'s tweak in <a href="https://github.com/zmkfirmware/zmk/pull/1271" target="_blank" rel="noopener noreferrer" class="">#1271</a>.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="additional-display-config-options">Additional display config options<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#additional-display-config-options" class="hash-link" aria-label="Direct link to Additional display config options" title="Direct link to Additional display config options" translate="no">​</a></h4>
<p><a href="https://github.com/caksoylar" target="_blank" rel="noopener noreferrer" class="">caksoylar</a> added a couple configuration options for displays, including a setting to invert display colors in <a href="https://github.com/zmkfirmware/zmk/pull/1754" target="_blank" rel="noopener noreferrer" class="">#1754</a> and an option to display the battery percentage for the stock status screen in <a href="https://github.com/zmkfirmware/zmk/pull/1563" target="_blank" rel="noopener noreferrer" class="">#1563</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-shields">New Shields<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#new-shields" class="hash-link" aria-label="Direct link to New Shields" title="Direct link to New Shields" translate="no">​</a></h2>
<ul>
<li class="">Eternal keypad <a href="https://github.com/zmkfirmware/zmk/pull/1136" target="_blank" rel="noopener noreferrer" class="">#1136</a> - <a href="https://github.com/halcyonCorsair" target="_blank" rel="noopener noreferrer" class="">halcyonCorsair</a></li>
<li class="">nullbits SNAP <a href="https://github.com/zmkfirmware/zmk/pull/1319" target="_blank" rel="noopener noreferrer" class="">#1319</a> - <a href="https://github.com/jaygreco" target="_blank" rel="noopener noreferrer" class="">jaygreco</a></li>
<li class="">Aurora Sweep <a href="https://github.com/zmkfirmware/zmk/pull/1504" target="_blank" rel="noopener noreferrer" class="">#1504</a>, Corne <a href="https://github.com/zmkfirmware/zmk/pull/1520" target="_blank" rel="noopener noreferrer" class="">#1520</a>, Lily58 <a href="https://github.com/zmkfirmware/zmk/pull/1553" target="_blank" rel="noopener noreferrer" class="">#1553</a>, Sofle <a href="https://github.com/zmkfirmware/zmk/pull/1864" target="_blank" rel="noopener noreferrer" class="">#1864</a>, and Helix <a href="https://github.com/zmkfirmware/zmk/pull/1873" target="_blank" rel="noopener noreferrer" class="">#1873</a> - <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a></li>
<li class="">ZMK Uno shield <a href="https://github.com/zmkfirmware/zmk/pull/1576" target="_blank" rel="noopener noreferrer" class="">#1576</a> - <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a></li>
<li class="">Waterfowl <a href="https://github.com/zmkfirmware/zmk/pull/1554" target="_blank" rel="noopener noreferrer" class="">#1554</a> - <a href="https://github.com/JW2586" target="_blank" rel="noopener noreferrer" class="">JW2586</a></li>
<li class="">Kyria Rev 3 <a href="https://github.com/zmkfirmware/zmk/pull/1627" target="_blank" rel="noopener noreferrer" class="">#1627</a> - <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a></li>
<li class="">Leeloo v2 and Leeloo-Micro <a href="https://github.com/zmkfirmware/zmk/pull/1762" target="_blank" rel="noopener noreferrer" class="">#1762</a> - <a href="https://github.com/ClicketySplit" target="_blank" rel="noopener noreferrer" class="">ClicketySplit</a></li>
<li class="">Spaceboards Pancake <a href="https://github.com/zmkfirmware/zmk/pull/1400" target="_blank" rel="noopener noreferrer" class="">#1400</a> - <a href="https://github.com/jasonhazel" target="_blank" rel="noopener noreferrer" class="">jasonhazel</a></li>
<li class="">Reviung5 <a href="https://github.com/zmkfirmware/zmk/pull/1548" target="_blank" rel="noopener noreferrer" class="">#1548</a> - <a href="https://github.com/zblesk" target="_blank" rel="noopener noreferrer" class="">zblesk</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-boards">New Boards<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#new-boards" class="hash-link" aria-label="Direct link to New Boards" title="Direct link to New Boards" translate="no">​</a></h2>
<ul>
<li class="">RP2040 boards, including Sparkfun Pro Micro, Adafruit KB2040 and Seeeduino Xiao RP2040 were added as part of the Zephyr 3.2 upgrade in <a href="https://github.com/zmkfirmware/zmk/pull/1499" target="_blank" rel="noopener noreferrer" class="">#1499</a> - <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a></li>
<li class="">Puchi BLE <a href="https://github.com/zmkfirmware/zmk/pull/1445" target="_blank" rel="noopener noreferrer" class="">#1445</a> - <a href="https://github.com/BenRoe" target="_blank" rel="noopener noreferrer" class="">BenRoe</a></li>
<li class="">nRFMicro 1.3/1.4 (nRF52833) <a href="https://github.com/zmkfirmware/zmk/pull/912" target="_blank" rel="noopener noreferrer" class="">#912</a> - <a href="https://github.com/pashutk" target="_blank" rel="noopener noreferrer" class="">pashutk</a></li>
<li class="">nRF5340 DK <a href="https://github.com/zmkfirmware/zmk/pull/1562" target="_blank" rel="noopener noreferrer" class="">#1562</a> - <a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">joelspadin</a></li>
<li class="">PillBug <a href="https://github.com/zmkfirmware/zmk/pull/1530" target="_blank" rel="noopener noreferrer" class="">#1530</a> - <a href="https://github.com/kylemccreery" target="_blank" rel="noopener noreferrer" class="">kylemccreery</a></li>
<li class="">Preonic Rev 3 <a href="https://github.com/zmkfirmware/zmk/pull/1575" target="_blank" rel="noopener noreferrer" class="">#1575</a> - <a href="https://github.com/jeromeOlivier" target="_blank" rel="noopener noreferrer" class="">jeromeOlivier</a></li>
<li class="">Corne-ish Zen v2 <a href="https://github.com/zmkfirmware/zmk/pull/1498" target="_blank" rel="noopener noreferrer" class="">#1498</a> and v1 <a href="https://github.com/zmkfirmware/zmk/pull/1593" target="_blank" rel="noopener noreferrer" class="">#1593</a> - <a href="https://github.com/LOWPROKB" target="_blank" rel="noopener noreferrer" class="">LOWPROKB</a> and <a href="https://github.com/caksoylar" target="_blank" rel="noopener noreferrer" class="">caksoylar</a></li>
<li class="">Polarity Works CKP family of boards <a href="https://github.com/zmkfirmware/zmk/pull/1547" target="_blank" rel="noopener noreferrer" class="">#1547</a> - <a href="https://github.com/ReFil" target="_blank" rel="noopener noreferrer" class="">ReFil</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="coming-soon">Coming Soon!<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#coming-soon" class="hash-link" aria-label="Direct link to Coming Soon!" title="Direct link to Coming Soon!" translate="no">​</a></h2>
<p>Some items listed in the last coming soon section are still under active development and other new exciting items are in progress:</p>
<ul>
<li class="">Automatic/simple BLE profile management</li>
<li class="">Soft off support for turning the keyboard "off" through firmware</li>
<li class="">Improved automatic power management for devices with multiple peripherals, e.g. OLED displays and RGB LEDs</li>
<li class="">Caps/Scroll/Num Lock LED support</li>
<li class="">Mouse keys</li>
<li class="">Wired split support</li>
<li class="">More modular approach to external boards/shields, custom code, user keymaps, etc.</li>
<li class="">More shields and boards</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="statistics">Statistics<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#statistics" class="hash-link" aria-label="Direct link to Statistics" title="Direct link to Statistics" translate="no">​</a></h2>
<p>Some statistics of interest for ZMK:</p>
<ul>
<li class="">GitHub (lifetime stats)
<ul>
<li class="">166 Contributors</li>
<li class="">1256 Closed PRs</li>
<li class="">1883 Stars</li>
<li class="">1949 Forks</li>
</ul>
</li>
<li class="">Discord Chat
<ul>
<li class="">8055 total registered (130% up from last SOTF!)</li>
</ul>
</li>
<li class="">Website (last 30 days)
<ul>
<li class="">52K page views</li>
<li class="">4.7K new users</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="sponsorship">Sponsorship<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#sponsorship" class="hash-link" aria-label="Direct link to Sponsorship" title="Direct link to Sponsorship" translate="no">​</a></h2>
<p>While ZMK is an open source project that uses the permissive MIT license, below are opportunities for anyone who would like to show their support to the project financially.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="open-collective">Open Collective<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#open-collective" class="hash-link" aria-label="Direct link to Open Collective" title="Direct link to Open Collective" translate="no">​</a></h3>
<p>The ZMK project has an <a href="https://opencollective.com/zmkfirmware" target="_blank" rel="noopener noreferrer" class="">Open Collective sponsorship</a> that has been going for two and a half years.
This fund helps pay for project costs like domain registration or development of hardware such as the <a href="https://github.com/zmkfirmware/zmk-uno" target="_blank" rel="noopener noreferrer" class="">ZMK Uno shield</a>.
Note that donations to this fund do <em>not</em> pay for the work of any individual contributor directly.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="contributor-sponsorships">Contributor sponsorships<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#contributor-sponsorships" class="hash-link" aria-label="Direct link to Contributor sponsorships" title="Direct link to Contributor sponsorships" translate="no">​</a></h3>
<p>Project creator and lead Pete Johanson has a <a href="https://github.com/sponsors/petejohanson" target="_blank" rel="noopener noreferrer" class="">GitHub sponsorship</a> set up that you can contribute to, in order to directly support his time and efforts in developing and maintaining ZMK.
He has also been traveling full time while focusing on ZMK and keyboard hardware design for more than a year now!
If you are curious, you can check out <a href="https://petejohanson.dev/blog/new-journey-2022" target="_blank" rel="noopener noreferrer" class="">his blog post</a> on deciding to embark on this adventure, in addition to his thoughts on contributor vs. project sponsorship, and sustainability of open source projects in general.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="thanks">Thanks!<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#thanks" class="hash-link" aria-label="Direct link to Thanks!" title="Direct link to Thanks!" translate="no">​</a></h2>
<p>As the first person to author a State Of The Firmware post besides Pete, I'd like to take the opportunity to thank him for his efforts on leading and developing ZMK, along with fostering a great community of contributors and users around it.</p>
<p>Also a big thank you to contributors that submit patches and perform reviews, testers that help validate changes, and users that take time out of their day to help out folks with ZMK usage on <a href="https://zmk.dev/community/discord/invite" target="_blank" rel="noopener noreferrer" class="">Discord channels</a>, GitHub issues and other communities.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="article-updates">Article Updates<a href="https://zmk.dev/blog/2023/10/05/zmk-sotf-6#article-updates" class="hash-link" aria-label="Direct link to Article Updates" title="Direct link to Article Updates" translate="no">​</a></h2>
<ul>
<li class="">12/2023: Removed the deprecated <code>label</code> property from code snippets.</li>
</ul>]]></content:encoded>
            <category>SOTF</category>
            <category>keyboards</category>
            <category>firmware</category>
            <category>oss</category>
            <category>ble</category>
        </item>
        <item>
            <title><![CDATA[Major Encoder Refactor]]></title>
            <link>https://zmk.dev/blog/2023/06/18/encoder-refactors</link>
            <guid>https://zmk.dev/blog/2023/06/18/encoder-refactors</guid>
            <pubDate>Sun, 18 Jun 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Today, we merged a significant change to the low level sensor code that is used to support encoders. In particular,]]></description>
            <content:encoded><![CDATA[<p>Today, we merged a significant change to the low level sensor code that is used to support encoders. In particular,
this paves the way for completing the work on supporting split peripheral sensors/encoders, and other future sensors
like pointing devices.</p>
<!-- -->
<p>As part of the work, backwards compatibility for existing shields has been retained, but only for a grace period to allow out-of-tree shields to move to the new approach for encoders.</p>
<p>Special thanks to <a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">joelspadin</a> for the <em>thorough</em> code review and testing throughout the development of the refactor.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="summary-of-changes">Summary of Changes<a href="https://zmk.dev/blog/2023/06/18/encoder-refactors#summary-of-changes" class="hash-link" aria-label="Direct link to Summary of Changes" title="Direct link to Summary of Changes" translate="no">​</a></h2>
<p>The following items have been merged:</p>
<ol>
<li class="">Split configuration of hardware details, and behavior configuration to allow more flexible functionality of sensors/encoders, in particular linear encoders that lack detents/"clicks" as they rotate.</li>
<li class="">Support for upstream Zephyr sensor drivers, including the NRFX QDEC driver that can be used on nRF52 based keyboards.</li>
<li class="">Sensor data handling changes that pave the way for split sensor handling easily.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="configuration-changes">Configuration Changes<a href="https://zmk.dev/blog/2023/06/18/encoder-refactors#configuration-changes" class="hash-link" aria-label="Direct link to Configuration Changes" title="Direct link to Configuration Changes" translate="no">​</a></h2>
<p>The major changes to configuration in the devicetree files relates to how the number of steps/triggers for a given encoder are set. In particular, the number of pulses/steps for a given encoder is configured first, allowing ZMK to determine the exact angular degrees of change that is represented by a single pulse on the data lines to that encoder.</p>
<p>Once that angular degrees mapping is completed, now independently there is a configuration setting to control how many triggers of the behavior in the keymap should occur for each full rotation of the sensor. Another way to think of this is "how many degrees of rotation results in a triggering of the sensor behavior in your keymap layer".</p>
<p>Splitting these two parts of the encoder configuration allows greater flexibility, and fine grained control of encoder behavior for linear encoders that don't have fixed detents.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="old-configuration">Old Configuration<a href="https://zmk.dev/blog/2023/06/18/encoder-refactors#old-configuration" class="hash-link" aria-label="Direct link to Old Configuration" title="Direct link to Old Configuration" translate="no">​</a></h3>
<p>Previously, an encoder configuration looked like:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token label symbol" style="color:#e36209">left_encoder:</span><span class="token plain"> </span><span class="token node class-name" style="color:#6f42c1">encoder_left</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"alps,ec11"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">a-gpios</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;pro_micro</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">21</span><span class="token plain"> </span><span class="token punctuation">(</span><span class="token plain">GPIO_ACTIVE_HIGH </span><span class="token operator" style="color:#005cc5">|</span><span class="token plain"> GPIO_PULL_UP</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">b-gpios</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;pro_micro</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">20</span><span class="token plain"> </span><span class="token punctuation">(</span><span class="token plain">GPIO_ACTIVE_HIGH </span><span class="token operator" style="color:#005cc5">|</span><span class="token plain"> GPIO_PULL_UP</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">resolution</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">4</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<p>Here, the <code>resolution</code> property was used to indicate how many encoder pulses should trigger the sensor behavior one time. Next, the encoder is selected in the sensors node:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token node class-name" style="color:#6f42c1">sensors</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"zmk,keymap-sensors"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">sensors</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;left_encoder</span><span class="token plain"> </span><span class="token reference variable" style="color:#005cc5">&amp;right_encoder</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<p>That was the entirety of the configuration for encoders.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-configuration">New Configuration<a href="https://zmk.dev/blog/2023/06/18/encoder-refactors#new-configuration" class="hash-link" aria-label="Direct link to New Configuration" title="Direct link to New Configuration" translate="no">​</a></h3>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token label symbol" style="color:#e36209">left_encoder:</span><span class="token plain"> </span><span class="token node class-name" style="color:#6f42c1">encoder_left</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"alps,ec11"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">a-gpios</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;pro_micro</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">21</span><span class="token plain"> </span><span class="token punctuation">(</span><span class="token plain">GPIO_ACTIVE_HIGH </span><span class="token operator" style="color:#005cc5">|</span><span class="token plain"> GPIO_PULL_UP</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">b-gpios</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;pro_micro</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">20</span><span class="token plain"> </span><span class="token punctuation">(</span><span class="token plain">GPIO_ACTIVE_HIGH </span><span class="token operator" style="color:#005cc5">|</span><span class="token plain"> GPIO_PULL_UP</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">steps</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">80</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<p>Here, the <code>steps</code> property is now used to indicate how many encoder pulses there are in a single complete rotation of the encoder. Next, the encoder is selected in the sensors node as before, but an additional configuration is used to indicate how many times the encoder should trigger the behavior in your keymap per rotation:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token node class-name" style="color:#6f42c1">sensors</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"zmk,keymap-sensors"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">sensors</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;left_encoder</span><span class="token plain"> </span><span class="token reference variable" style="color:#005cc5">&amp;right_encoder</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">triggers-per-rotation</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">20</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<p>For tactile encoders that have detents, the <code>triggers-per-rotation</code> would match the number of detents on the encoder. For linear encoders, the value can be chosen to suit your needs.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="zephyr-sensor-drivers">Zephyr Sensor Drivers<a href="https://zmk.dev/blog/2023/06/18/encoder-refactors#zephyr-sensor-drivers" class="hash-link" aria-label="Direct link to Zephyr Sensor Drivers" title="Direct link to Zephyr Sensor Drivers" translate="no">​</a></h2>
<p>The configuration changes bring ZMK's code in line with how upstream Zephyr sensor drivers handle rotations. This has the added advantage of allowing us to leverage other sensor drivers. On Nordic MCUs, like nRF52840, the NRFX QDEC driver can be used, for example:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token reference variable" style="color:#005cc5">&amp;pinctrl</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token label symbol" style="color:#e36209">qdec_default:</span><span class="token plain"> </span><span class="token node class-name" style="color:#6f42c1">qdec_default</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token node class-name" style="color:#6f42c1">group1</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">psels</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token function" style="color:#6f42c1">NRF_PSEL</span><span class="token punctuation">(</span><span class="token plain">QDEC_A</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">1</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">11</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                    </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token function" style="color:#6f42c1">NRF_PSEL</span><span class="token punctuation">(</span><span class="token plain">QDEC_B</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">1</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">10</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">bias-pull-up</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d">// Set up the QDEC hardware based driver and give it the same label as the deleted node.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token label symbol" style="color:#e36209">encoder:</span><span class="token plain"> </span><span class="token reference variable" style="color:#005cc5">&amp;qdec0</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">status</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"okay"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">led-pre</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">0</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">steps</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">80</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">pinctrl-0</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;qdec_default</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">pinctrl-names</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"default"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<p>The NRFX QDEC driver has the advantage of supporting optical encoders as well, and although it polls, it does so in hardware without waking the MCU core; initial basic power profiling is promising.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="split-sensorencoder-support">Split Sensor/Encoder Support<a href="https://zmk.dev/blog/2023/06/18/encoder-refactors#split-sensorencoder-support" class="hash-link" aria-label="Direct link to Split Sensor/Encoder Support" title="Direct link to Split Sensor/Encoder Support" translate="no">​</a></h2>
<p>In addition to the refactors for splitting the configuration, the changes merged included refactors designed to simplify and move forward with the long outstanding feature of supporting encoders on the peripheral side of split keyboards. That work is planned as a follow up.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="deprecation">Deprecation<a href="https://zmk.dev/blog/2023/06/18/encoder-refactors#deprecation" class="hash-link" aria-label="Direct link to Deprecation" title="Direct link to Deprecation" translate="no">​</a></h2>
<p>The old configuration will be supported for a period of one month, and then removed, giving users a grace period to complete the migration to the new separated configuration.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="article-updates">Article Updates<a href="https://zmk.dev/blog/2023/06/18/encoder-refactors#article-updates" class="hash-link" aria-label="Direct link to Article Updates" title="Direct link to Article Updates" translate="no">​</a></h2>
<ul>
<li class="">12/2023: Removed the deprecated <code>label</code> property from code snippets.</li>
</ul>]]></content:encoded>
            <category>firmware</category>
            <category>zephyr</category>
            <category>sensors</category>
            <category>encoders</category>
        </item>
        <item>
            <title><![CDATA[Zephyr 3.2 Update]]></title>
            <link>https://zmk.dev/blog/2023/04/06/zephyr-3-2</link>
            <guid>https://zmk.dev/blog/2023/04/06/zephyr-3-2</guid>
            <pubDate>Thu, 06 Apr 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[I'm happy to announce that we have completed the work to upgrade ZMK to Zephyr 3.2!]]></description>
            <content:encoded><![CDATA[<p>I'm happy to announce that we have completed the <a href="https://github.com/zmkfirmware/zmk/pull/1499" target="_blank" rel="noopener noreferrer" class="">work</a> to upgrade ZMK to <a href="https://docs.zephyrproject.org/3.2.0/releases/release-notes-3.2.html" target="_blank" rel="noopener noreferrer" class="">Zephyr 3.2</a>!</p>
<!-- -->
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> did the upgrade work to adjust ZMK for the Zephyr changes, with help from <a href="https://github.com/Nicell" target="_blank" rel="noopener noreferrer" class="">Nicell</a> on the LVGL pieces.</p>
<ul>
<li class="">Upgrade to LVGL 8.x API, and move to the new Kconfig settings.</li>
<li class="">Tons of RP2040 work.</li>
<li class="">Zephyr core API changes, including DTS <code>label</code> use changes.</li>
<li class="">Move to <a href="https://docs.zephyrproject.org/3.2.0/hardware/pinctrl/index.html" target="_blank" rel="noopener noreferrer" class="">pinctrl</a> Zephyr subsystem.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="getting-the-changes">Getting The Changes<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#getting-the-changes" class="hash-link" aria-label="Direct link to Getting The Changes" title="Direct link to Getting The Changes" translate="no">​</a></h2>
<p>Use the following steps to update to the latest tooling in order to properly use the new ZMK changes:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="user-config-repositories-using-github-actions">User Config Repositories Using GitHub Actions<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#user-config-repositories-using-github-actions" class="hash-link" aria-label="Direct link to User Config Repositories Using GitHub Actions" title="Direct link to User Config Repositories Using GitHub Actions" translate="no">​</a></h3>
<p>Existing user config repositories using Github Actions to build will pull down Zephyr 3.2 automatically, however if you created your user config a while ago, you may need to update it to reference our shared build configuration to leverage the correct Docker image.</p>
<ol>
<li class="">
<p>Replace the contents of your <code>.github/workflows/build.yml</code> with:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token key atrule" style="color:#d73a49">on</span><span class="token punctuation">:</span><span class="token plain"> </span><span class="token punctuation">[</span><span class="token plain">push</span><span class="token punctuation">,</span><span class="token plain"> pull_request</span><span class="token punctuation">,</span><span class="token plain"> workflow_dispatch</span><span class="token punctuation">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token key atrule" style="color:#d73a49">jobs</span><span class="token punctuation">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token key atrule" style="color:#d73a49">build</span><span class="token punctuation">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token key atrule" style="color:#d73a49">uses</span><span class="token punctuation">:</span><span class="token plain"> zmkfirmware/zmk/.github/workflows/build</span><span class="token punctuation">-</span><span class="token plain">user</span><span class="token punctuation">-</span><span class="token plain">config.yml@main</span><br></span></code></pre></div></div>
</li>
<li class="">
<p>If it doesn't exist already, add a new file to your repository named <code>build.yaml</code>:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token comment" style="color:#6a737d"># This file generates the GitHub Actions matrix</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d"># For simple board + shield combinations, add them</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d"># to the top level board and shield arrays, for more</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d"># control, add individual board + shield combinations to</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d"># the `include` property, e.g:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d">#</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d"># board: [ "nice_nano_v2" ]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d"># shield: [ "corne_left", "corne_right" ]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d"># include:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d">#   - board: bdn9_rev2</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d">#   - board: nice_nano_v2</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d">#     shield: reviung41</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d">#</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">---</span><br></span></code></pre></div></div>
</li>
</ol>
<p>and then update it as appropriate to build the right shields/boards for your configuration.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="upgrade-a-manual-script">Upgrade a manual script<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#upgrade-a-manual-script" class="hash-link" aria-label="Direct link to Upgrade a manual script" title="Direct link to Upgrade a manual script" translate="no">​</a></h3>
<p>If you have a custom GitHub Actions workflow you need to maintain for some reason, you can update the workflow to use the <code>stable</code> Docker image tag for the build:</p>
<ul>
<li class="">
<p>Open <code>.github/workflows/build.yml</code> in your editor/IDE</p>
</li>
<li class="">
<p>Change <code>zmkfirmware/zmk-build-arm:2.5</code> to <code>zmkfirmware/zmk-build-arm:stable</code> wherever it is found</p>
</li>
<li class="">
<p>Locate and delete the lines for the DTS output step, which is no longer needed:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token punctuation">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#d73a49">name</span><span class="token punctuation">:</span><span class="token plain"> $</span><span class="token punctuation">{</span><span class="token punctuation">{</span><span class="token plain"> steps.variables.outputs.display</span><span class="token punctuation">-</span><span class="token plain">name </span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token plain"> DTS File</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token key atrule" style="color:#d73a49">if</span><span class="token punctuation">:</span><span class="token plain"> $</span><span class="token punctuation">{</span><span class="token punctuation">{</span><span class="token plain"> always() </span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token key atrule" style="color:#d73a49">run</span><span class="token punctuation">:</span><span class="token plain"> </span><span class="token punctuation">|</span><span class="token scalar string" style="color:#032f62"></span><br></span><span class="token-line" style="color:#24292e"><span class="token scalar string" style="color:#032f62">    if [ -f "build/zephyr/${{ matrix.board }}.pre.tmp" ]; then cat -n build/zephyr/${{ matrix.board }}.pre.tmp; fi</span><br></span><span class="token-line" style="color:#24292e"><span class="token scalar string" style="color:#032f62">    if [ -f "build/zephyr/zephyr.dts" ]; then cat -n build/zephyr/zephyr.dts; fi</span><br></span></code></pre></div></div>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="vs-code--docker-dev-container">VS Code &amp; Docker (Dev Container)<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#vs-code--docker-dev-container" class="hash-link" aria-label="Direct link to VS Code &amp; Docker (Dev Container)" title="Direct link to VS Code &amp; Docker (Dev Container)" translate="no">​</a></h3>
<p>If you build locally using VS Code &amp; Docker then:</p>
<ul>
<li class="">pull the latest ZMK <code>main</code> with <code>git pull</code> for your ZMK checkout</li>
<li class="">reload the project</li>
<li class="">if you are prompted to rebuild the remote container, click <code>Rebuild</code></li>
<li class="">otherwise, press <code>F1</code> and run <code>Remote Containers: Rebuild Container</code></li>
<li class="">Once the container has rebuilt and reloaded, run <code>west update</code> to pull the updated Zephyr version and its dependencies.</li>
</ul>
<p>Once the container has rebuilt, VS Code will be running the 3.2 Docker image.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="local-host-development">Local Host Development<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#local-host-development" class="hash-link" aria-label="Direct link to Local Host Development" title="Direct link to Local Host Development" translate="no">​</a></h3>
<p>The following steps will get you building ZMK locally against Zephyr 3.2:</p>
<ul>
<li class="">Run the updated <a class="" href="https://zmk.dev/docs/development/local-toolchain/setup">toolchain installation</a> steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)</li>
<li class="">Install the latest version of <code>west</code> by running <code>pip3 install --user --update west</code>.</li>
<li class="">pull the latest ZMK <code>main</code> with <code>git pull</code> for your ZMK checkout</li>
<li class="">run <code>west update</code> to pull the updated Zephyr version and its dependencies</li>
</ul>
<p>From there, you should be ready to build as normal!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="known-issues">Known Issues<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#known-issues" class="hash-link" aria-label="Direct link to Known Issues" title="Direct link to Known Issues" translate="no">​</a></h2>
<p>A few testers have reported inconsistent issues with bluetooth connections on Windows after upgrading, which can be resolved by re-pairing your keyboard by:</p>
<ol>
<li class="">Remove the device from Windows.</li>
<li class="">Clear the profile on your keyboard that is associated with the Windows device by triggering <code>&amp;bt BT_CLR</code> on your keymap while that profile is active.</li>
<li class="">Restart Windows.</li>
<li class="">Re-connect Windows to your keyboard.</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="windows-battery-reporting-fix">Windows Battery Reporting Fix<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#windows-battery-reporting-fix" class="hash-link" aria-label="Direct link to Windows Battery Reporting Fix" title="Direct link to Windows Battery Reporting Fix" translate="no">​</a></h2>
<p>Zephyr 3.2 introduced <a href="https://github.com/zephyrproject-rtos/zephyr/pull/48929" target="_blank" rel="noopener noreferrer" class="">a new Kconfig setting</a> that can be used to work around a bug in Windows related to battery reporting. Check out our <a class="" href="https://zmk.dev/docs/config/bluetooth">bluetooth config</a> for the full details. The key new configuration that can be set if using Windows is:</p>
<div class="language-ini codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ini codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token key attr-name" style="color:#005cc5">CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION</span><span class="token punctuation">=</span><span class="token value attr-value">n</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="keymap-changes">Keymap Changes<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#keymap-changes" class="hash-link" aria-label="Direct link to Keymap Changes" title="Direct link to Keymap Changes" translate="no">​</a></h2>
<p>Due to conflicts with new devicetree node labels added for Zephyr's <a href="https://docs.zephyrproject.org/3.2.0/hardware/peripherals/reset.html" target="_blank" rel="noopener noreferrer" class="">reset system</a>, the <code>&amp;reset</code> behavior has been renamed to <code>&amp;sys_reset</code>.</p>
<p>All of the in-tree keymaps have been fixed, but you may encounter build failures about duplicate names, requiring you rename the behavior reference in your keymap. Use the <a class="" href="https://zmk.dev/keymap-upgrader">Keymap Upgrader</a> and this will get fixed for you automatically.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="boardshield-changes">Board/Shield Changes<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#boardshield-changes" class="hash-link" aria-label="Direct link to Board/Shield Changes" title="Direct link to Board/Shield Changes" translate="no">​</a></h2>
<p>The following changes have <a href="https://github.com/zmkfirmware/zmk/pull/1499/commits" target="_blank" rel="noopener noreferrer" class="">already been completed</a> for all boards/shields in ZMK <code>main</code> branch. For existing or new PRs, or out of tree boards, the following changes are necessary to properly work with the latest changes.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="move-to-pinctrl-driver">Move to <code>pinctrl</code> driver<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#move-to-pinctrl-driver" class="hash-link" aria-label="Direct link to move-to-pinctrl-driver" title="Direct link to move-to-pinctrl-driver" translate="no">​</a></h3>
<p>Before this change, setting up the details of pins to use them for peripherals like SPI, I2C, etc. was a mix of platform specific driver code. Zephyr has moved to the newer <code>pinctrl</code> system to unify the handling of pin configuration, with additional flexibility for things like low power modes for those pins, etc.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="board-specific-shield-overlays">Board specific shield overlays<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#board-specific-shield-overlays" class="hash-link" aria-label="Direct link to Board specific shield overlays" title="Direct link to Board specific shield overlays" translate="no">​</a></h4>
<p>The main area this affects existing shields is those with board specific overrides, e.g. <code>&lt;shield&gt;/boards/seeeduino_xiao_ble.overlay</code>, that sets up additional components on custom buses, e.g. addressable RGB LEDs leveraging the SPI MOSI pin.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="nrf52-pin-assignments">nRF52 Pin Assignments<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#nrf52-pin-assignments" class="hash-link" aria-label="Direct link to nRF52 Pin Assignments" title="Direct link to nRF52 Pin Assignments" translate="no">​</a></h4>
<p>Previously in ZMK, we relied on per-driver devicetree source properties to set the alternate pin functions for things like SPI or I2C. For example, here is the I2C bus setup as it was previously on the <code>nice_nano</code> board:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token reference variable" style="color:#005cc5">&amp;i2c0</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"nordic,nrf-twi"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">sda-pin</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">17</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">scl-pin</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">20</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<p>With the move to the <code>pinctrl</code> system, this setup now look like:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token plain"> </span><span class="token reference variable" style="color:#005cc5">&amp;i2c0</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"nordic,nrf-twi"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">pinctrl-0</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;i2c0_default</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">pinctrl-1</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;i2c0_sleep</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">pinctrl-names</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"default"</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"sleep"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"> </span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<p>which references the <code>pinctrl</code> configuration:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token reference variable" style="color:#005cc5">&amp;pinctrl</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">       </span><span class="token label symbol" style="color:#e36209">i2c0_default:</span><span class="token plain"> </span><span class="token node class-name" style="color:#6f42c1">i2c0_default</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">               </span><span class="token node class-name" style="color:#6f42c1">group1</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                       </span><span class="token attr-name" style="color:#005cc5">psels</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token function" style="color:#6f42c1">NRF_PSEL</span><span class="token punctuation">(</span><span class="token plain">TWIM_SDA</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">17</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                               </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token function" style="color:#6f42c1">NRF_PSEL</span><span class="token punctuation">(</span><span class="token plain">TWIM_SCL</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">20</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">               </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">       </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">       </span><span class="token label symbol" style="color:#e36209">i2c0_sleep:</span><span class="token plain"> </span><span class="token node class-name" style="color:#6f42c1">i2c0_sleep</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">               </span><span class="token node class-name" style="color:#6f42c1">group1</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                       </span><span class="token attr-name" style="color:#005cc5">psels</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token function" style="color:#6f42c1">NRF_PSEL</span><span class="token punctuation">(</span><span class="token plain">TWIM_SDA</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">17</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                               </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token function" style="color:#6f42c1">NRF_PSEL</span><span class="token punctuation">(</span><span class="token plain">TWIM_SCL</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">20</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                       </span><span class="token attr-name" style="color:#005cc5">low-power-enable</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">               </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">       </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<p>Although slightly more <em>verbose</em> this allows pin configuration infrastructure to be re-used, specify other modes, like sleep, etc. in a standard way across architectures.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="out-of-tree-boardsshields">Out of Tree Boards/Shields<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#out-of-tree-boardsshields" class="hash-link" aria-label="Direct link to Out of Tree Boards/Shields" title="Direct link to Out of Tree Boards/Shields" translate="no">​</a></h4>
<p>All of the in-tree boards and shields have been upgraded, but if you maintain/use an out-of-tree board or shield that uses the converted boards and overrides pins for various buses, you may need to switch to <code>pinctrl</code> to match ZMK's new approach.</p>
<p>The approach is the following when updating a <em>board</em>:</p>
<ol>
<li class="">
<p>Add an entry <code>CONFIG_PINCTRL=y</code> to the <code>&lt;board&gt;_defconfig</code> file in the board directory.</p>
</li>
<li class="">
<p>Add a new file with the naming convention <code>&lt;board&gt;-pinctrl.dtsi</code> to your board directory.</p>
</li>
<li class="">
<p>In the new file, add your <code>pinctrl</code> entries that set up different pin control configurations for whatever peripherals/buses are needed. Here's the nice!nano file as an example:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token comment" style="color:#6a737d">/*</span><br></span><span class="token-line" style="color:#24292e"><span class="token comment" style="color:#6a737d">* Copyright (c) 2022 The ZMK Contributors</span><br></span><span class="token-line" style="color:#24292e"><span class="token comment" style="color:#6a737d">* SPDX-License-Identifier: MIT</span><br></span><span class="token-line" style="color:#24292e"><span class="token comment" style="color:#6a737d">*/</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token reference variable" style="color:#005cc5">&amp;pinctrl</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token label symbol" style="color:#e36209">uart0_default:</span><span class="token plain"> </span><span class="token node class-name" style="color:#6f42c1">uart0_default</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                </span><span class="token node class-name" style="color:#6f42c1">group1</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                        </span><span class="token attr-name" style="color:#005cc5">psels</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token function" style="color:#6f42c1">NRF_PSEL</span><span class="token punctuation">(</span><span class="token plain">UART_RX</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">8</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                        </span><span class="token attr-name" style="color:#005cc5">bias-pull-up</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                </span><span class="token node class-name" style="color:#6f42c1">group2</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                        </span><span class="token attr-name" style="color:#005cc5">psels</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token function" style="color:#6f42c1">NRF_PSEL</span><span class="token punctuation">(</span><span class="token plain">UART_TX</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">6</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token label symbol" style="color:#e36209">uart0_sleep:</span><span class="token plain"> </span><span class="token node class-name" style="color:#6f42c1">uart0_sleep</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                </span><span class="token node class-name" style="color:#6f42c1">group1</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                        </span><span class="token attr-name" style="color:#005cc5">psels</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token function" style="color:#6f42c1">NRF_PSEL</span><span class="token punctuation">(</span><span class="token plain">UART_RX</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">8</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                                </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token function" style="color:#6f42c1">NRF_PSEL</span><span class="token punctuation">(</span><span class="token plain">UART_TX</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">6</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                        </span><span class="token attr-name" style="color:#005cc5">low-power-enable</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token label symbol" style="color:#e36209">i2c0_default:</span><span class="token plain"> </span><span class="token node class-name" style="color:#6f42c1">i2c0_default</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                </span><span class="token node class-name" style="color:#6f42c1">group1</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                        </span><span class="token attr-name" style="color:#005cc5">psels</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token function" style="color:#6f42c1">NRF_PSEL</span><span class="token punctuation">(</span><span class="token plain">TWIM_SDA</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">17</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                                </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token function" style="color:#6f42c1">NRF_PSEL</span><span class="token punctuation">(</span><span class="token plain">TWIM_SCL</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">20</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token label symbol" style="color:#e36209">i2c0_sleep:</span><span class="token plain"> </span><span class="token node class-name" style="color:#6f42c1">i2c0_sleep</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                </span><span class="token node class-name" style="color:#6f42c1">group1</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                        </span><span class="token attr-name" style="color:#005cc5">psels</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token function" style="color:#6f42c1">NRF_PSEL</span><span class="token punctuation">(</span><span class="token plain">TWIM_SDA</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">17</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                                </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token function" style="color:#6f42c1">NRF_PSEL</span><span class="token punctuation">(</span><span class="token plain">TWIM_SCL</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">20</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                        </span><span class="token attr-name" style="color:#005cc5">low-power-enable</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
</li>
<li class="">
<p>From the main <code>&lt;board&gt;.dts</code> file, add an <code>#include "&lt;board&gt;-pinctrl.dtsi"</code> to have the C-preprocessor combine the files.</p>
</li>
<li class="">
<p>Update the various peripheral nodes to use the new <code>pinctrl</code> configurations. For example, the following old configuration:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token reference variable" style="color:#005cc5">&amp;i2c0</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"nordic,nrf-twi"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">sda-pin</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">15</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">scl-pin</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">17</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<p>would be changed to:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token reference variable" style="color:#005cc5">&amp;i2c0</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"nordic,nrf-twi"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">pinctrl-0</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;i2c0_default</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">pinctrl-1</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;i2c0_sleep</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">pinctrl-names</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"default"</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"sleep"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
</li>
</ol>
<p>Because <code>pinctrl</code> configuration is very dependent on the specific target SoC, you will rarely need to consider it for a shield overlay that leverages a pro micro or XIAO abstraction. As noted, you're more likely to need to fix up pinctrl settings is using a board specific shield overlay, e.g. <code>&lt;shield&gt;/boards/&lt;board&gt;.overlay</code> to set things up.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="lvgl-kconfig-changes">LVGL Kconfig changes.<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#lvgl-kconfig-changes" class="hash-link" aria-label="Direct link to LVGL Kconfig changes." title="Direct link to LVGL Kconfig changes." translate="no">​</a></h3>
<p>With the update to LVGL 8.x, Zephyr now leverages an upstream Kconfig file for most LVGL settings. Due to this, the naming for many existing configs has been adjusted. For any configs moved upstream, the naming mostly involves a prefix change from <code>LVGL_</code> to the shorter <code>LV_</code>. For any that are still Zephyr specific configs, they are now prefixed with <code>LV_Z_</code> prefix.</p>
<p>If you maintain or use an out of tree board/shield with a display, the following will need to be changed in your Kconfig files:</p>
<ul>
<li class=""><code>LVGL_VDB_SIZE</code> -&gt; <code>LV_Z_VDB_SIZE</code></li>
<li class=""><code>LVGL_DPI</code> -&gt; <code>LV_DPI_DEF</code></li>
<li class=""><code>LVGL_BITS_PER_PIXEL</code> -&gt; <code>LV_Z_BITS_PER_PIXEL</code></li>
</ul>
<p>Other than those specific examples, most other Kconfig values can simply change the <code>LVGL_</code> prefix to <code>LV_</code>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="raspberry-pi-picorp2040-support">Raspberry Pi Pico/RP2040 Support<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#raspberry-pi-picorp2040-support" class="hash-link" aria-label="Direct link to Raspberry Pi Pico/RP2040 Support" title="Direct link to Raspberry Pi Pico/RP2040 Support" translate="no">​</a></h2>
<p>This Zephyr update allows ZMK to support the new(-ish) RP2040 SoC found in the Raspberry Pi Pico.</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>ZMK does <em>not</em> support wired split communication yet, so RP2040 is only usable for non-split keyboards. To follow progress on wired splits, see <a href="https://github.com/zmkfirmware/zmk/pull/1117" target="_blank" rel="noopener noreferrer" class="">#1117</a>.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="supported-controllers">Supported Controllers<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#supported-controllers" class="hash-link" aria-label="Direct link to Supported Controllers" title="Direct link to Supported Controllers" translate="no">​</a></h3>
<p>The following RP2040 powered controllers have board definitions for folks to test:</p>
<ul>
<li class="">Raspberry Pi Pico (<code>rpi_pico</code>)</li>
<li class="">SparkFun Pro Micro RP2040 (<code>sparkfun_pro_micro_rp2040</code>)</li>
<li class="">Adafruit Keyboar/KB2040 (<code>adafruit_kb2040</code>)</li>
<li class="">Seeeduino XIAO RP2040 (<code>seeeduino_xiao_rp2040</code>)</li>
<li class="">Adafruit Qt PY RP2040 (<code>adafruit_qt_py_rp2040</code>)</li>
<li class="">BoardSource blok (<code>boardsource_blok</code>)</li>
<li class="">Elite-Pi (compatible with the <code>sparkfun_pro_micro_rp2040</code> board)</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="upcoming-changes">Upcoming Changes<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#upcoming-changes" class="hash-link" aria-label="Direct link to Upcoming Changes" title="Direct link to Upcoming Changes" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="display-re-init">Display re-init<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#display-re-init" class="hash-link" aria-label="Direct link to Display re-init" title="Direct link to Display re-init" translate="no">​</a></h3>
<p>Zephyr's improved <a href="https://docs.zephyrproject.org/3.2.0/services/pm/power_domain.html#pm-power-domain" target="_blank" rel="noopener noreferrer" class="">power domain</a> support is a foundation
upon which we can provide a proper fix for the <a href="https://github.com/zmkfirmware/zmk/issues/674" target="_blank" rel="noopener noreferrer" class="">longstanding display re-init bug</a> which has prevented
ZMK from formally supporting our display code.</p>
<p>There is work still remaining to fully leverage the power domain system within ZMK to fix the bug, but upgrading Zephyr is the first necessary step.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="thanks">Thanks!<a href="https://zmk.dev/blog/2023/04/06/zephyr-3-2#thanks" class="hash-link" aria-label="Direct link to Thanks!" title="Direct link to Thanks!" translate="no">​</a></h2>
<p>Thanks to all the testers who have helped verify ZMK functionality on the newer Zephyr version.</p>]]></content:encoded>
            <category>firmware</category>
            <category>zephyr</category>
            <category>core</category>
        </item>
        <item>
            <title><![CDATA[ZMK's Second Birthday]]></title>
            <link>https://zmk.dev/blog/2022/04/21/zmk-2yo</link>
            <guid>https://zmk.dev/blog/2022/04/21/zmk-2yo</guid>
            <pubDate>Thu, 21 Apr 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Two years ago, today, I minted the first ever commit for ZMK:]]></description>
            <content:encoded><![CDATA[<p>Two years ago, today, I minted the first ever commit for ZMK:</p>
<!-- -->
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token plain">commit 85c8be89dea8f7a00e8efb06d38e2b32f3459935</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">Author: Pete Johanson &lt;peter@peterjohanson.com&gt;</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">Date:   Tue Apr 21 16:20:34 2020 -0400</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    Initial work.</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"> .gitignore     |  1 +</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"> .gitmodules    |  3 +++</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"> CMakeLists.txt | 40 +++++++++++++++++++++++++++++++++++++++</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"> src/main.c     | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"> src/zmk_lib.h  |  7 +++++++</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"> zephyr-rust    |  1 +</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"> 6 files changed, 112 insertions(+)</span><br></span></code></pre></div></div>
<p>I will never forget that commit. Not because of the code it contained (please don't look, it's not worth it!), but for what it started.</p>
<p>Working on ZMK has given me the opportunity to reconnect with old friends (<a href="https://twitter.com/brixmeister" target="_blank" rel="noopener noreferrer" class="">@brixmeister</a> was my Gentoo mentor/sponsor when I became a contributor there on my first ever OSS project, and is a current active Zephyr RTOS contributor!), make new ones, and learn so much from the amazing mechanical keyboard community.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="first-keyboard">First Keyboard<a href="https://zmk.dev/blog/2022/04/21/zmk-2yo#first-keyboard" class="hash-link" aria-label="Direct link to First Keyboard" title="Direct link to First Keyboard" translate="no">​</a></h2>
<p>But I'm getting ahead of myself! Back to early ZMK. I present you the first ZMK keyboard:</p>
<p><img decoding="async" loading="lazy" alt="stm32wb55rg dev kit keyboard" src="https://zmk.dev/assets/images/first-zmk-keyboard-3c5775374e51ac12d0d35fd6f0d8b504.jpg" width="504" height="378" class="img_ev3q"></p>
<p>That first "keyboard" taught me a <em>lot</em>. It forced me to dust off my long forgotten, rudimentary electronics knowledge, and gave me my first taste of really combining the physical/tangible with code in a way that years of doing backend API development never had.</p>
<p>I was <em>hooked</em>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="zephyr-rtos">Zephyr RTOS<a href="https://zmk.dev/blog/2022/04/21/zmk-2yo#zephyr-rtos" class="hash-link" aria-label="Direct link to Zephyr RTOS" title="Direct link to Zephyr RTOS" translate="no">​</a></h2>
<p>Early in my brainstorming, I knew I needed a foundation to build upon that would get me "a lot for free." I evaluated several different real-time operating systems (RTOSes) and happened upon <a href="https://zephyrproject.org/" target="_blank" rel="noopener noreferrer" class="">Zephyr</a>. It immediately ticked all the boxes I wanted:</p>
<ul>
<li class="">Robust, open source Bluetooth stack, supporting multiple SoCs. At the time, I was trying out stm32wb thanks to some interest among keyboard designers, but I also so there were other compelling choices that might be a good fit.</li>
<li class="">An open source, non-copyleft license. I am a firm believer in F/OSS, and wanted to use a license that was as unrestricted as possible.</li>
<li class="">Had a lot of core APIs available, so I could focus on the keyboard functionality, not the plumbing. I love tinkering, but I wanted to focus my time on the interesting bits, not infrastructure.</li>
</ul>
<p>I'm really happy with the choice, it has served us incredibly well the past two years.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="real-keyboard">Real Keyboard<a href="https://zmk.dev/blog/2022/04/21/zmk-2yo#real-keyboard" class="hash-link" aria-label="Direct link to Real Keyboard" title="Direct link to Real Keyboard" translate="no">​</a></h2>
<p>At some point, somehow, <a href="https://github.com/innovaker" target="_blank" rel="noopener noreferrer" class="">innovaker</a> introduced me to <a href="https://github.com/Nicell" target="_blank" rel="noopener noreferrer" class="">nicell</a> who graciously sent me a few of the early pre-production nice!nano controllers, which I was able to get running on my Kyria. Doing so required the first split code, as well as lots of general improvements.</p>
<p><img decoding="async" loading="lazy" alt="kyria keyboard" src="https://zmk.dev/assets/images/kyria-first-split-03c98164487465df434ade83bf386638.jpg" width="265" height="297" class="img_ev3q"></p>
<p>The day I was finally able to type on a wireless, split keyboard running ZMK was deeply momentous for me!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="onward-and-upward">Onward and Upward<a href="https://zmk.dev/blog/2022/04/21/zmk-2yo#onward-and-upward" class="hash-link" aria-label="Direct link to Onward and Upward" title="Direct link to Onward and Upward" translate="no">​</a></h2>
<p>We've come a long way since then, with our <a class="" href="https://zmk.dev/docs/hardware">supported hardware</a>, <a class="" href="https://zmk.dev/docs/keymaps">features</a> and <a class="" href="https://zmk.dev/docs/keymaps/behaviors/key-press">behaviors</a> growing regularly.</p>
<p>ZMK powered keyboards are now available in group buys and in stock at various vendors; compatible controllers have been used in a wide range of builds to empower our users to free themselves from their USB/TRRS cables and move about untethered.</p>
<p>This progress is only possible thanks to all of the contributors who've joined me in the vision for a wireless-first world. I am so grateful for everyone who has given their time to contribute code, answer questions on our Discord server, write more documentation, and especially all the users who have trusted us to make their input devices work.</p>
<p>I can't wait to see what we can accomplish together in the next two years.</p>]]></content:encoded>
            <category>keyboards</category>
            <category>firmware</category>
            <category>oss</category>
        </item>
        <item>
            <title><![CDATA[ZMK State Of The Firmware #5]]></title>
            <link>https://zmk.dev/blog/2022/04/10/zmk-sotf-5</link>
            <guid>https://zmk.dev/blog/2022/04/10/zmk-sotf-5</guid>
            <pubDate>Sun, 10 Apr 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Welcome to the fifth ZMK "State Of The Firmware" (SOTF)!]]></description>
            <content:encoded><![CDATA[<p>Welcome to the fifth ZMK "State Of The Firmware" (SOTF)!</p>
<p>This update will cover all the major activity since <a class="" href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4">SOTF #4</a>. That was over a year ago, so lots to cover!</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="recent-activity">Recent Activity<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#recent-activity" class="hash-link" aria-label="Direct link to Recent Activity" title="Direct link to Recent Activity" translate="no">​</a></h2>
<p>Here's a summary of the various major changes since last time, broken down by theme:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="keymapsbehaviors">Keymaps/Behaviors<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#keymapsbehaviors" class="hash-link" aria-label="Direct link to Keymaps/Behaviors" title="Direct link to Keymaps/Behaviors" translate="no">​</a></h3>
<p>Since last time, there have been several new powerful keymap features and behaviors added, including several asked for features, such as tap-dance and macros.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="caps-word">Caps Word<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#caps-word" class="hash-link" aria-label="Direct link to Caps Word" title="Direct link to Caps Word" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> added the <a class="" href="https://zmk.dev/docs/keymaps/behaviors/caps-word">caps word</a> behavior, i.e. <code>&amp;caps_word</code>, in <a href="https://github.com/zmkfirmware/zmk/pull/823" target="_blank" rel="noopener noreferrer" class="">#823</a> that allows toggling a mode where all all alpha characters are sent
to the host capitalized until a non-alpha, non-"continue list" keycode is sent. This can be useful for typing things like <code>CONFIG_ENABLE_CAPS_WORD</code> without having to hold down shift. This is similar in spirit to using the caps lock key, but with the added benefit of turning itself off automatically.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="key-repeat">Key Repeat<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#key-repeat" class="hash-link" aria-label="Direct link to Key Repeat" title="Direct link to Key Repeat" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> added the new <a class="" href="https://zmk.dev/docs/keymaps/behaviors/key-repeat">key repeat</a> behavior in <a href="https://github.com/zmkfirmware/zmk/pull/1034" target="_blank" rel="noopener noreferrer" class="">#1034</a> to allow repeating the last sent key-press again, including any modifiers that were applied to that key press. It can be added to your keymap using the simple <code>&amp;key_repeat</code> reference.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="macros">Macros<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#macros" class="hash-link" aria-label="Direct link to Macros" title="Direct link to Macros" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a>, taking heavy inspiration on the initial work from <a href="https://github.com/okke-formsma" target="_blank" rel="noopener noreferrer" class="">okke-formsma</a>, added <a class="" href="https://zmk.dev/docs/keymaps/behaviors/macros">macro support</a> in <a href="https://github.com/zmkfirmware/zmk/pull/1166" target="_blank" rel="noopener noreferrer" class="">#1168</a>. Several <a class="" href="https://zmk.dev/docs/keymaps/behaviors/macros#common-patterns">common patterns</a> are documented, but one example, changing the underglow color as you activate/deactivate a layer, looks like:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token function" style="color:#6f42c1">ZMK_MACRO</span><span class="token punctuation">(</span><span class="token plain">layer_color_macro</span><span class="token punctuation">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">wait-ms</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">0</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">tap-ms</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">0</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">bindings</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">      </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;macro_press</span><span class="token plain"> </span><span class="token reference variable" style="color:#005cc5">&amp;mo</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">1</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">      </span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;macro_tap</span><span class="token plain"> </span><span class="token reference variable" style="color:#005cc5">&amp;rgb_ug</span><span class="token plain"> </span><span class="token function" style="color:#6f42c1">RGB_COLOR_HSB</span><span class="token punctuation">(</span><span class="token number" style="color:#005cc5">128</span><span class="token punctuation">,</span><span class="token number" style="color:#005cc5">100</span><span class="token punctuation">,</span><span class="token number" style="color:#005cc5">100</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">      </span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;macro_pause_for_release</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">      </span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;macro_release</span><span class="token plain"> </span><span class="token reference variable" style="color:#005cc5">&amp;mo</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">1</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">      </span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;macro_tap</span><span class="token plain"> </span><span class="token reference variable" style="color:#005cc5">&amp;rgb_ug</span><span class="token plain"> </span><span class="token function" style="color:#6f42c1">RGB_COLOR_HSB</span><span class="token punctuation">(</span><span class="token number" style="color:#005cc5">300</span><span class="token punctuation">,</span><span class="token number" style="color:#005cc5">100</span><span class="token punctuation">,</span><span class="token number" style="color:#005cc5">50</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">)</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="tap-dance">Tap Dance<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#tap-dance" class="hash-link" aria-label="Direct link to Tap Dance" title="Direct link to Tap Dance" translate="no">​</a></h4>
<p><a href="https://github.com/kurtis-lew" target="_blank" rel="noopener noreferrer" class="">kurtis-lew</a> worked diligently to add the <a class="" href="https://zmk.dev/docs/keymaps/behaviors/tap-dance">tap-dance behavior</a> in <a href="https://github.com/zmkfirmware/zmk/pull/1139" target="_blank" rel="noopener noreferrer" class="">#1139</a>, allowing different behaviors to be invoked based on the number of times
a user taps a single key in their keymap, e.g.</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token node class-name" style="color:#6f42c1">/</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token node class-name" style="color:#6f42c1">behaviors</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token label symbol" style="color:#e36209">td0:</span><span class="token plain"> </span><span class="token node class-name" style="color:#6f42c1">tap_dance_0</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"zmk,behavior-tap-dance"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">#binding-cells</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">0</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">tapping-term-ms</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">200</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">bindings</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> N1</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> N2</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">,</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> N3</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token node class-name" style="color:#6f42c1">keymap</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"zmk,keymap"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token node class-name" style="color:#6f42c1">default_layer</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">bindings</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                </span><span class="token reference variable" style="color:#005cc5">&amp;td0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="conditional-layers">Conditional Layers<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#conditional-layers" class="hash-link" aria-label="Direct link to Conditional Layers" title="Direct link to Conditional Layers" translate="no">​</a></h4>
<p><a href="https://github.com/bcat" target="_blank" rel="noopener noreferrer" class="">bcat</a> added <a class="" href="https://zmk.dev/docs/keymaps/conditional-layers">conditional layers</a> in <a href="https://github.com/zmkfirmware/zmk/pull/830" target="_blank" rel="noopener noreferrer" class="">#830</a> as a generalized version of the common "adjust layer" pattern on smaller keyboards.</p>
<p>Example:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token node class-name" style="color:#6f42c1">/</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token node class-name" style="color:#6f42c1">conditional_layers</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"zmk,conditional-layers"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token node class-name" style="color:#6f42c1">tri_layer</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">if-layers</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">1</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">2</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">then-layer</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">3</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="combos">Combos<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#combos" class="hash-link" aria-label="Direct link to Combos" title="Direct link to Combos" translate="no">​</a></h4>
<p><a href="https://github.com/mcrosson" target="_blank" rel="noopener noreferrer" class="">mcrosson</a> added the <a href="https://zmk.dev/docs/keymaps/combos#configuration" target="_blank" rel="noopener noreferrer" class="">layer specific combos</a> in <a href="https://github.com/zmkfirmware/zmk/pull/661" target="_blank" rel="noopener noreferrer" class="">#661</a>, so users can make certain combos only triggerable when the layers set for the combo are active.</p>
<p>This is used by the <a href="https://github.com/artseyio/zmk-artsey" target="_blank" rel="noopener noreferrer" class="">ZMK implementation</a> of <a href="https://artsey.io/" target="_blank" rel="noopener noreferrer" class="">ARTSEY</a> extensively.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="sticky-keys">Sticky Keys<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#sticky-keys" class="hash-link" aria-label="Direct link to Sticky Keys" title="Direct link to Sticky Keys" translate="no">​</a></h4>
<p><a href="https://github.com/okke-formsma" target="_blank" rel="noopener noreferrer" class="">okke-formsma</a> updated <a class="" href="https://zmk.dev/docs/keymaps/behaviors/sticky-key">sticky keys</a> in <a href="https://github.com/zmkfirmware/zmk/pull/1122" target="_blank" rel="noopener noreferrer" class="">#1122</a> to add the <code>ignore-modifiers;</code> property; when set, sticky keys won't release when other modifiers are pressed. This allows you to combine sticky modifiers, which is popularly used with <a href="https://github.com/callum-oakley/qmk_firmware/tree/master/users/callum#oneshot-modifiers" target="_blank" rel="noopener noreferrer" class="">"callum-style mods"</a>.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="hold-tap-improvements">Hold-Tap Improvements<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#hold-tap-improvements" class="hash-link" aria-label="Direct link to Hold-Tap Improvements" title="Direct link to Hold-Tap Improvements" translate="no">​</a></h4>
<p><a href="https://github.com/jmding8" target="_blank" rel="noopener noreferrer" class="">jmding8</a> added an additional <a href="https://zmk.dev/docs/keymaps/behaviors/hold-tap#positional-hold-tap-and-hold-trigger-key-positions" target="_blank" rel="noopener noreferrer" class="">positional hold-tap configuration</a> in <a href="https://github.com/zmkfirmware/zmk/pull/835" target="_blank" rel="noopener noreferrer" class="">#835</a> to help certain sequences produce the expected results.</p>
<p><a href="https://github.com/jmding8" target="_blank" rel="noopener noreferrer" class="">jmding8</a> also added an additional <a href="https://zmk.dev/docs/keymaps/behaviors/hold-tap#flavors" target="_blank" rel="noopener noreferrer" class="">hold-tap flavor: <code>tap-unless-interrupted</code></a> in <a href="https://github.com/zmkfirmware/zmk/pull/1018" target="_blank" rel="noopener noreferrer" class="">#1018</a> which works very well with the new positional hold-tap config.</p>
<p><a href="https://github.com/okke-formsma" target="_blank" rel="noopener noreferrer" class="">okke-formsma</a> implemented <a href="https://zmk.dev/docs/keymaps/behaviors/hold-tap#retro-tap" target="_blank" rel="noopener noreferrer" class=""><code>retro-tap</code> hold-tap property</a> in <a href="https://github.com/zmkfirmware/zmk/pull/667" target="_blank" rel="noopener noreferrer" class="">#667</a></p>
<p><a href="https://github.com/okke-formsma" target="_blank" rel="noopener noreferrer" class="">okke-formsma</a> <em>also</em> added <a href="https://zmk.dev/docs/keymaps/behaviors/hold-tap#quick-tap-ms" target="_blank" rel="noopener noreferrer" class=""><code>quick-tap-ms</code> hold-tap property</a> in <a href="https://github.com/zmkfirmware/zmk/pull/655" target="_blank" rel="noopener noreferrer" class="">#655</a></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="apple-device-compatibility-improvements">Apple Device Compatibility Improvements<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#apple-device-compatibility-improvements" class="hash-link" aria-label="Direct link to Apple Device Compatibility Improvements" title="Direct link to Apple Device Compatibility Improvements" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="pairing">Pairing<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#pairing" class="hash-link" aria-label="Direct link to Pairing" title="Direct link to Pairing" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> did some sleuthing and fixed a long standing problem with inconsistent pairing with macOS in [#946]](<a href="https://github.com/zmkfirmware/zmk/pull/946" target="_blank" rel="noopener noreferrer" class="">https://github.com/zmkfirmware/zmk/pull/946</a>). With the changes, macOS more reliably pairs with ZMK devices.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="consumer-media-codes">Consumer (Media) Codes<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#consumer-media-codes" class="hash-link" aria-label="Direct link to Consumer (Media) Codes" title="Direct link to Consumer (Media) Codes" translate="no">​</a></h4>
<p>Another persistent bug that Apple users experienced was related to crashes and problems with keyboard configurations, that was traced to an issue with ZMK's HID usage that was fixed by <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> in <a href="https://github.com/zmkfirmware/zmk/pull/726" target="_blank" rel="noopener noreferrer" class="">#726</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="debounce-enhancements">Debounce Enhancements<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#debounce-enhancements" class="hash-link" aria-label="Direct link to Debounce Enhancements" title="Direct link to Debounce Enhancements" translate="no">​</a></h3>
<p><a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">joelspadin</a> applied some major enhancements to our <a class="" href="https://zmk.dev/docs/features/debouncing">debouncing</a> approach to allow fine grained control of our debouncing in <a href="https://github.com/zmkfirmware/zmk/pull/888" target="_blank" rel="noopener noreferrer" class="">#888</a>, including allowing <a class="" href="https://zmk.dev/docs/features/debouncing#eager-debouncing">eager debouncing</a> which can reduce key press latency.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="split-improvements">Split Improvements<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#split-improvements" class="hash-link" aria-label="Direct link to Split Improvements" title="Direct link to Split Improvements" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="behavior-locality">Behavior Locality<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#behavior-locality" class="hash-link" aria-label="Direct link to Behavior Locality" title="Direct link to Behavior Locality" translate="no">​</a></h4>
<p>The long awaited locality enhancement was finally merged by <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> in <a href="https://github.com/zmkfirmware/zmk/pull/547" target="_blank" rel="noopener noreferrer" class="">#547</a>, allowing more fine grained control of where certain behaviors are invoked. Some key improvements thanks to the changes:</p>
<ul>
<li class=""><a class="" href="https://zmk.dev/docs/features/lighting#rgb-underglow">RGB Underglow</a> behaviors now run globally, so enabling/disabling RGB, changing the color, animation, etc. applies to both sides of a split properly.</li>
<li class=""><a class="" href="https://zmk.dev/docs/keymaps/behaviors/reset#reset">Reset</a>/<a class="" href="https://zmk.dev/docs/keymaps/behaviors/reset#bootloader-reset">Bootloader</a> behaviors now run wherever the key was pressed. For example, adding a <code>&amp;bootloader</code> reference to the peripheral side of a split will now put that side of the split into the bootloader when pressed.</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="split-connections">Split Connections<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#split-connections" class="hash-link" aria-label="Direct link to Split Connections" title="Direct link to Split Connections" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> also added fixes to improve split re-connection for certain scenarios in <a href="https://github.com/zmkfirmware/zmk/pull/984" target="_blank" rel="noopener noreferrer" class="">#984</a>, helping ensure splits properly connect when one side or the other is reset.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="hardware-support">Hardware Support<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#hardware-support" class="hash-link" aria-label="Direct link to Hardware Support" title="Direct link to Hardware Support" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="backlight">Backlight<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#backlight" class="hash-link" aria-label="Direct link to Backlight" title="Direct link to Backlight" translate="no">​</a></h4>
<p><a href="https://github.com/bortoz" target="_blank" rel="noopener noreferrer" class="">bortoz</a> added <a class="" href="https://zmk.dev/docs/features/lighting#backlight">single color backlight support</a> in <a href="https://github.com/zmkfirmware/zmk/pull/904" target="_blank" rel="noopener noreferrer" class="">#904</a> for those keyboards that have it as an alternative to RGB underglow.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="e-paper-display-epd-driver">E-Paper Display (EPD) Driver<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#e-paper-display-epd-driver" class="hash-link" aria-label="Direct link to E-Paper Display (EPD) Driver" title="Direct link to E-Paper Display (EPD) Driver" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> worked with <a href="https://github.com/LOWPROKB" target="_blank" rel="noopener noreferrer" class="">LOWPROKB</a> to add support for the E-Paper Displays (EPD) in <a href="https://github.com/zmkfirmware/zmk/pull/895" target="_blank" rel="noopener noreferrer" class="">#895</a> used in keyboards like the Corne-ish Zen.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="nrf-vddh-battery-sensing">nRF VDDH Battery Sensing<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#nrf-vddh-battery-sensing" class="hash-link" aria-label="Direct link to nRF VDDH Battery Sensing" title="Direct link to nRF VDDH Battery Sensing" translate="no">​</a></h4>
<p><a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">joelspadin</a> added a new sensor driver to support battery charge calculation by sensing voltage on the VDDH pin on nRF52 chips in <a href="https://github.com/zmkfirmware/zmk/pull/750" target="_blank" rel="noopener noreferrer" class="">#750</a>, which is particularly useful for designs
using "high voltage mode" with that SoC.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="miscellaneous">Miscellaneous<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#miscellaneous" class="hash-link" aria-label="Direct link to Miscellaneous" title="Direct link to Miscellaneous" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="documentation">Documentation<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#documentation" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation" translate="no">​</a></h4>
<p><a href="https://github.com/dxmh" target="_blank" rel="noopener noreferrer" class="">dxmh</a> and <a href="https://github.com/caksoylar" target="_blank" rel="noopener noreferrer" class="">caksoylar</a> have joined the ZMK organization to help with documentation, and have been doing an amazing job adding new docs, and leading reviewing docs related PRs to free other contributors up to focus on other areas. It's been an incredible addition to ZMK!</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="nkro-support">NKRO Support<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#nkro-support" class="hash-link" aria-label="Direct link to NKRO Support" title="Direct link to NKRO Support" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a>'s work on the HID foundation also included adding support for full NKRO HID in <a href="https://github.com/zmkfirmware/zmk/pull/726" target="_blank" rel="noopener noreferrer" class="">#726</a> that can be enabled by adding the following to your <code>.conf</code> file for your config:</p>
<div class="language-ini codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ini codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token key attr-name" style="color:#005cc5">CONFIG_ZMK_HID_REPORT_TYPE_NKRO</span><span class="token punctuation">=</span><span class="token value attr-value">y</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="power-profiler">Power Profiler<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#power-profiler" class="hash-link" aria-label="Direct link to Power Profiler" title="Direct link to Power Profiler" translate="no">​</a></h4>
<p>It's been live for a while, but <a href="https://github.com/Nicell" target="_blank" rel="noopener noreferrer" class="">nicell</a> added an amazing <a class="" href="https://zmk.dev/power-profiler">power profiler</a> in <a href="https://github.com/zmkfirmware/zmk/pull/312" target="_blank" rel="noopener noreferrer" class="">#312</a> to allow users to estimate their battery life for various hardware configurations.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="minmax-underglow-brightness">Min/Max Underglow Brightness<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#minmax-underglow-brightness" class="hash-link" aria-label="Direct link to Min/Max Underglow Brightness" title="Direct link to Min/Max Underglow Brightness" translate="no">​</a></h4>
<p><a href="https://github.com/malinges" target="_blank" rel="noopener noreferrer" class="">malinges</a> added support for configuring min/max underglow brightness in <a href="https://github.com/zmkfirmware/zmk/pull/944" target="_blank" rel="noopener noreferrer" class="">#944</a> by setting the values in your <code>.conf</code> file as percentages of full:</p>
<div class="language-ini codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ini codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token key attr-name" style="color:#005cc5">CONFIG_ZMK_RGB_UNDERGLOW_BRT_MIN</span><span class="token punctuation">=</span><span class="token value attr-value">20</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token key attr-name" style="color:#005cc5">CONFIG_ZMK_RGB_UNDERGLOW_BRT_MAX</span><span class="token punctuation">=</span><span class="token value attr-value">80</span><br></span></code></pre></div></div>
<p>This can be useful to be sure that lowering brightness doesn't set the brightness to zero, and raising the brightness doesn't consume too much power.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="zephyr-30">Zephyr 3.0<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#zephyr-30" class="hash-link" aria-label="Direct link to Zephyr 3.0" title="Direct link to Zephyr 3.0" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> helped prepare and test the upgrade of ZMK to Zephyr 3.0 in <a href="https://github.com/zmkfirmware/zmk/pull/1143" target="_blank" rel="noopener noreferrer" class="">#1143</a>. 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!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-shields">New Shields<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#new-shields" class="hash-link" aria-label="Direct link to New Shields" title="Direct link to New Shields" translate="no">​</a></h2>
<ul>
<li class="">Contra in <a href="https://github.com/zmkfirmware/zmk/pull/633" target="_blank" rel="noopener noreferrer" class="">#633</a> - <a href="https://github.com/iangus" target="_blank" rel="noopener noreferrer" class="">iangus</a></li>
<li class="">Naked60 in <a href="https://github.com/zmkfirmware/zmk/pull/681" target="_blank" rel="noopener noreferrer" class="">#681</a> - <a href="https://github.com/xiushak" target="_blank" rel="noopener noreferrer" class="">xiushak</a></li>
<li class="">Murphpad in <a href="https://github.com/zmkfirmware/zmk/pull/806" target="_blank" rel="noopener noreferrer" class="">#806</a> - <a href="https://github.com/kylemccreery" target="_blank" rel="noopener noreferrer" class="">kylemccreery</a></li>
<li class="">A. Dux in <a href="https://github.com/zmkfirmware/zmk/pull/951" target="_blank" rel="noopener noreferrer" class="">#951</a> - <a href="https://github.com/dxmh" target="_blank" rel="noopener noreferrer" class="">dxmh</a></li>
<li class="">Bat43 in <a href="https://github.com/zmkfirmware/zmk/pull/956" target="_blank" rel="noopener noreferrer" class="">#956</a> - <a href="https://github.com/dnaq" target="_blank" rel="noopener noreferrer" class="">dnaq</a></li>
<li class="">Zodiark in <a href="https://github.com/zmkfirmware/zmk/pull/959" target="_blank" rel="noopener noreferrer" class="">#959</a> - <a href="https://github.com/Aleblazer" target="_blank" rel="noopener noreferrer" class="">Aleblazer</a></li>
<li class="">Osprette in <a href="https://github.com/zmkfirmware/zmk/pull/974" target="_blank" rel="noopener noreferrer" class="">#974</a> - <a href="https://github.com/smores56" target="_blank" rel="noopener noreferrer" class="">smores56</a></li>
<li class="">Knob Goblin in <a href="https://github.com/zmkfirmware/zmk/pull/990" target="_blank" rel="noopener noreferrer" class="">#990</a> - <a href="https://github.com/lucasuyezu" target="_blank" rel="noopener noreferrer" class="">lucasuyezu</a></li>
<li class="">Redox in <a href="https://github.com/zmkfirmware/zmk/pull/1002" target="_blank" rel="noopener noreferrer" class="">#1002</a> - <a href="https://github.com/toddmok" target="_blank" rel="noopener noreferrer" class="">toddmok</a></li>
<li class="">Elephant42 in <a href="https://github.com/zmkfirmware/zmk/pull/1009" target="_blank" rel="noopener noreferrer" class="">#1009</a> - <a href="https://github.com/filoxo" target="_blank" rel="noopener noreferrer" class="">filoxo</a></li>
<li class="">Chalice in <a href="https://github.com/zmkfirmware/zmk/pull/1022" target="_blank" rel="noopener noreferrer" class="">#1022</a> - <a href="https://github.com/joshajohnson" target="_blank" rel="noopener noreferrer" class="">joshajohnson</a></li>
<li class="">Boardsource 5x12 in <a href="https://github.com/zmkfirmware/zmk/pull/1027" target="_blank" rel="noopener noreferrer" class="">#1027</a> - <a href="https://github.com/fsargent" target="_blank" rel="noopener noreferrer" class="">fsargent</a></li>
<li class="">Jiran in <a href="https://github.com/zmkfirmware/zmk/pull/1048" target="_blank" rel="noopener noreferrer" class="">#1048</a> - <a href="https://github.com/krikun98" target="_blank" rel="noopener noreferrer" class="">krikun98</a></li>
<li class="">keeb.io Fourier in <a href="https://github.com/zmkfirmware/zmk/pull/1056" target="_blank" rel="noopener noreferrer" class="">#1056</a> - <a href="https://github.com/TheButlah" target="_blank" rel="noopener noreferrer" class="">TheButlah</a></li>
<li class="">Lotus58 in <a href="https://github.com/zmkfirmware/zmk/pull/1090" target="_blank" rel="noopener noreferrer" class="">#1090</a> - <a href="https://github.com/nettema" target="_blank" rel="noopener noreferrer" class="">nettema</a></li>
<li class="">Clog in <a href="https://github.com/zmkfirmware/zmk/pull/1092" target="_blank" rel="noopener noreferrer" class="">#1092</a> - <a href="https://github.com/smores56" target="_blank" rel="noopener noreferrer" class="">smores56</a></li>
<li class="">Kyria rev2 in <a href="https://github.com/zmkfirmware/zmk/pull/1112" target="_blank" rel="noopener noreferrer" class="">#1112</a> - <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a></li>
<li class="">Leeloo in <a href="https://github.com/zmkfirmware/zmk/pull/1165" target="_blank" rel="noopener noreferrer" class="">#1165</a> - <a href="https://github.com/ClicketySplit" target="_blank" rel="noopener noreferrer" class="">ClicketySplit</a></li>
<li class="">2% Milk in <a href="https://github.com/zmkfirmware/zmk/pull/1135" target="_blank" rel="noopener noreferrer" class="">#1135</a> - <a href="https://github.com/kurtis-lew" target="_blank" rel="noopener noreferrer" class="">kurtis-lew</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-boards">New Boards<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#new-boards" class="hash-link" aria-label="Direct link to New Boards" title="Direct link to New Boards" translate="no">​</a></h2>
<ul>
<li class="">Ferris rev02 in <a href="https://github.com/zmkfirmware/zmk/pull/642" target="_blank" rel="noopener noreferrer" class="">#642</a> - <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a></li>
<li class="">nice!60 in <a href="https://github.com/zmkfirmware/zmk/pull/810" target="_blank" rel="noopener noreferrer" class="">#810</a> - <a href="https://github.com/Nicell" target="_blank" rel="noopener noreferrer" class="">nicell</a></li>
<li class="">nice!nano v2 in <a href="https://github.com/zmkfirmware/zmk/pull/867" target="_blank" rel="noopener noreferrer" class="">#867</a> - <a href="https://github.com/Nicell" target="_blank" rel="noopener noreferrer" class="">nicell</a></li>
<li class="">Mikoto 520 in <a href="https://github.com/zmkfirmware/zmk/pull/985" target="_blank" rel="noopener noreferrer" class="">#985</a> - <a href="https://github.com/mrninhvn" target="_blank" rel="noopener noreferrer" class="">mrninhvn</a></li>
<li class="">S40NC in <a href="https://github.com/zmkfirmware/zmk/pull/1021" target="_blank" rel="noopener noreferrer" class="">#1021</a> - <a href="https://github.com/kylemccreery" target="_blank" rel="noopener noreferrer" class="">kylemccreery</a></li>
<li class="">BT60 in <a href="https://github.com/zmkfirmware/zmk/pull/1029" target="_blank" rel="noopener noreferrer" class="">#1029</a> - <a href="https://github.com/ReFil" target="_blank" rel="noopener noreferrer" class="">ReFil</a></li>
<li class="">Seeeduino XIAO BLE (as part of the Zephyr 3.0 work) in <a href="https://github.com/zmkfirmware/zmk/pull/1143" target="_blank" rel="noopener noreferrer" class="">#1143</a> - <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="boardshield-metadata">Board/Shield Metadata<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#boardshield-metadata" class="hash-link" aria-label="Direct link to Board/Shield Metadata" title="Direct link to Board/Shield Metadata" translate="no">​</a></h2>
<p><a href="https://github.com/Nicell" target="_blank" rel="noopener noreferrer" class="">nicell</a> and <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> worked together in <a href="https://github.com/zmkfirmware/zmk/pull/883" target="_blank" rel="noopener noreferrer" class="">#883</a> to settle on a <a class="" href="https://zmk.dev/docs/development/hardware-integration/hardware-metadata-files">metadata format</a> that is used to document every board and shield. This now drives automatic generation of our <a class="" href="https://zmk.dev/docs/hardware">supported hardware</a> page and our
more nuanced GH Actions automation for testing changes to ZMK.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="coming-soon">Coming Soon!<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#coming-soon" class="hash-link" aria-label="Direct link to Coming Soon!" title="Direct link to Coming Soon!" translate="no">​</a></h2>
<p>Some items listed in the last coming soon section are still under active development.</p>
<ul>
<li class="">RP2040 support</li>
<li class="">Peripheral rotary encoder support</li>
<li class="">Caps/Scroll/Num Lock LED support</li>
<li class="">Mouse Keys</li>
<li class="">Wired split support</li>
<li class="">More modular approach to external boards/shields, custom code, user keymaps, etc.</li>
<li class="">More shields and boards</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="statistics">Statistics<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#statistics" class="hash-link" aria-label="Direct link to Statistics" title="Direct link to Statistics" translate="no">​</a></h2>
<p>Some statistics of interest for ZMK:</p>
<ul>
<li class="">GitHub (lifetime stats)
<ul>
<li class="">105 Contributors</li>
<li class="">791 Closed PRs</li>
<li class="">849 Stars</li>
<li class="">832 Forks</li>
</ul>
</li>
<li class="">Discord Chat
<ul>
<li class="">3430 total registered</li>
</ul>
</li>
<li class="">Website (last 30 days)
<ul>
<li class="">35.9K page views</li>
<li class="">3.29K new users</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="thanks">Thanks!<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#thanks" class="hash-link" aria-label="Direct link to Thanks!" title="Direct link to Thanks!" translate="no">​</a></h2>
<p>As we approach the two year birthday for ZMK, I am reminded of how far we have come in such a short time, in large part thanks to the <em>amazing</em> community that has grown around it. I am so grateful to have so many contributors, testers, and user believing in the project and helping make it a joy to work on.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="article-updates">Article Updates<a href="https://zmk.dev/blog/2022/04/10/zmk-sotf-5#article-updates" class="hash-link" aria-label="Direct link to Article Updates" title="Direct link to Article Updates" translate="no">​</a></h2>
<ul>
<li class="">12/2023: Removed the deprecated <code>label</code> property from code snippets.</li>
</ul>]]></content:encoded>
            <category>SOTF</category>
            <category>keyboards</category>
            <category>firmware</category>
            <category>oss</category>
            <category>ble</category>
        </item>
        <item>
            <title><![CDATA[Zephyr 3.0 Update]]></title>
            <link>https://zmk.dev/blog/2022/04/02/zephyr-3-0</link>
            <guid>https://zmk.dev/blog/2022/04/02/zephyr-3-0</guid>
            <pubDate>Sat, 02 Apr 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[I'm happy to announce that we have completed the work to upgrade ZMK to Zephyr 3.0!]]></description>
            <content:encoded><![CDATA[<p>I'm happy to announce that we have completed the <a href="https://github.com/zmkfirmware/zmk/pull/1143" target="_blank" rel="noopener noreferrer" class="">work</a> to upgrade ZMK to <a href="https://docs.zephyrproject.org/3.0.0/releases/release-notes-3.0.html" target="_blank" rel="noopener noreferrer" class="">Zephyr 3.0</a>!</p>
<!-- -->
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> did the upgrade work to adjust ZMK for the Zephyr changes.</p>
<ul>
<li class="">Moving to Zephyr's UF2 build integration that was submitted upstream by <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a></li>
<li class="">Additional <code>color-mapping</code> property needed for ws2812 LED strep devicetree nodes</li>
<li class="">Zephyr core API changes, including delayed work, USB/HID</li>
<li class="">Adjust for pinctrl changes on stm32</li>
<li class="">Fixes for power management and log formatter changes</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="getting-the-changes">Getting The Changes<a href="https://zmk.dev/blog/2022/04/02/zephyr-3-0#getting-the-changes" class="hash-link" aria-label="Direct link to Getting The Changes" title="Direct link to Getting The Changes" translate="no">​</a></h2>
<p>Use the following steps to update to the latest tooling in order to properly use the new ZMK changes:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="user-config-repositories-using-github-actions">User Config Repositories Using GitHub Actions<a href="https://zmk.dev/blog/2022/04/02/zephyr-3-0#user-config-repositories-using-github-actions" class="hash-link" aria-label="Direct link to User Config Repositories Using GitHub Actions" title="Direct link to User Config Repositories Using GitHub Actions" translate="no">​</a></h3>
<p>Existing user config repositories using Github Actions to build will pull down Zephyr 3.0 automatically, however to build properly, the repository needs to be updated to use the <code>stable</code> Docker image tag for the build:</p>
<ul>
<li class="">
<p>Open <code>.github/workflows/build.yml</code> in your editor/IDE</p>
</li>
<li class="">
<p>Change <code>zmkfirmware/zmk-build-arm:2.5</code> to <code>zmkfirmware/zmk-build-arm:stable</code> wherever it is found</p>
</li>
<li class="">
<p>Locate and delete the lines for the DTS output step, which is no longer needed:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token punctuation">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#d73a49">name</span><span class="token punctuation">:</span><span class="token plain"> $</span><span class="token punctuation">{</span><span class="token punctuation">{</span><span class="token plain"> steps.variables.outputs.display</span><span class="token punctuation">-</span><span class="token plain">name </span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token plain"> DTS File</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token key atrule" style="color:#d73a49">if</span><span class="token punctuation">:</span><span class="token plain"> $</span><span class="token punctuation">{</span><span class="token punctuation">{</span><span class="token plain"> always() </span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token key atrule" style="color:#d73a49">run</span><span class="token punctuation">:</span><span class="token plain"> </span><span class="token punctuation">|</span><span class="token scalar string" style="color:#032f62"></span><br></span><span class="token-line" style="color:#24292e"><span class="token scalar string" style="color:#032f62">    if [ -f "build/zephyr/${{ matrix.board }}.pre.tmp" ]; then cat -n build/zephyr/${{ matrix.board }}.pre.tmp; fi</span><br></span><span class="token-line" style="color:#24292e"><span class="token scalar string" style="color:#032f62">    if [ -f "build/zephyr/zephyr.dts" ]; then cat -n build/zephyr/zephyr.dts; fi</span><br></span></code></pre></div></div>
</li>
</ul>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>If you created your user config repository a while ago, you may find that your <code>build.yml</code> file instead references
a <code>zephyr-west-action-arm</code> custom GitHub Action instead. In this case, the upgrade is not as direct. We suggest that
instead you <a class="" href="https://zmk.dev/docs/user-setup">re-create your config repository</a> to get an updated setup using the new automation
approach.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="vs-code--docker-dev-container">VS Code &amp; Docker (Dev Container)<a href="https://zmk.dev/blog/2022/04/02/zephyr-3-0#vs-code--docker-dev-container" class="hash-link" aria-label="Direct link to VS Code &amp; Docker (Dev Container)" title="Direct link to VS Code &amp; Docker (Dev Container)" translate="no">​</a></h3>
<p>If you build locally using VS Code &amp; Docker then:</p>
<ul>
<li class="">pull the latest ZMK <code>main</code> with <code>git pull</code> for your ZMK checkout</li>
<li class="">reload the project</li>
<li class="">if you are prompted to rebuild the remote container, click <code>Rebuild</code></li>
<li class="">otherwise, press <code>F1</code> and run <code>Remote Containers: Rebuild Container</code></li>
<li class="">Once the container has rebuilt and reloaded, run <code>west update</code> to pull the updated Zephyr version and its dependencies.</li>
</ul>
<p>Once the container has rebuilt, VS Code will be running the 3.0 Docker image.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="local-host-development">Local Host Development<a href="https://zmk.dev/blog/2022/04/02/zephyr-3-0#local-host-development" class="hash-link" aria-label="Direct link to Local Host Development" title="Direct link to Local Host Development" translate="no">​</a></h3>
<p>The following steps will get you building ZMK locally against Zephyr 3.0:</p>
<ul>
<li class="">Run the updated <a class="" href="https://zmk.dev/docs/development/local-toolchain/setup">toolchain installation</a> steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)</li>
<li class="">pull the latest ZMK <code>main</code> with <code>git pull</code> for your ZMK checkout</li>
<li class="">run <code>west update</code> to pull the updated Zephyr version and its dependencies</li>
</ul>
<p>From there, you should be ready to build as normal!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="boardshield-changes">Board/Shield Changes<a href="https://zmk.dev/blog/2022/04/02/zephyr-3-0#boardshield-changes" class="hash-link" aria-label="Direct link to Board/Shield Changes" title="Direct link to Board/Shield Changes" translate="no">​</a></h2>
<p>The following changes have <a href="https://github.com/zmkfirmware/zmk/pull/1143/commits" target="_blank" rel="noopener noreferrer" class="">already been completed</a> for all boards/shields in ZMK <code>main</code> branch. For existing or new PRs, or out of tree boards, the following changes are necessary to properly work with the latest changes.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="rgb-underglow">RGB Underglow<a href="https://zmk.dev/blog/2022/04/02/zephyr-3-0#rgb-underglow" class="hash-link" aria-label="Direct link to RGB Underglow" title="Direct link to RGB Underglow" translate="no">​</a></h3>
<p>Zephyr's WS2812 <code>led_strip</code> driver added a new required property. When adding <a class="" href="https://zmk.dev/docs/features/lighting#adding-rgb-underglow-support-to-a-keyboard">underglow</a> to a board, you now must also add the additional include <code>#include &lt;dt-bindings/led/led.h&gt;</code> at the top of your devicetree file, and add a <code>color-mapping</code> property like:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token label symbol" style="color:#e36209">led_strip:</span><span class="token plain"> </span><span class="token node class-name" style="color:#6f42c1">ws2812@</span><span class="token node class-name number" style="color:#005cc5">0</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"worldsemi,ws2812-spi"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token comment" style="color:#6a737d">/* SPI */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">reg</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">0</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"> </span><span class="token comment" style="color:#6a737d">/* ignored, but necessary for SPI bindings */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">spi-max-frequency</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">4000000</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token comment" style="color:#6a737d">/* WS2812 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">chain-length</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">10</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"> </span><span class="token comment" style="color:#6a737d">/* number of LEDs */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">spi-one-frame</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">0x70</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">spi-zero-frame</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">0x40</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">color-mapping</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token plain">LED_COLOR_ID_GREEN</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                   LED_COLOR_ID_RED</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">                   LED_COLOR_ID_BLUE</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>Standard WS2812 LEDs use a wire protocol where the bits for the colors green, red, and blue values are sent in that order.
If your board/shield uses LEDs that require the data sent in a different order, the <code>color-mapping</code> property ordering should be changed to match.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="display-selection">Display Selection<a href="https://zmk.dev/blog/2022/04/02/zephyr-3-0#display-selection" class="hash-link" aria-label="Direct link to Display Selection" title="Direct link to Display Selection" translate="no">​</a></h3>
<p>Zephyr moved to using a <code>chosen</code> node named <code>zephyr,display</code> to select the display device to be used with LVGL, the underlying display library we use.</p>
<p>For example, for a shield with:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token reference variable" style="color:#005cc5">&amp;pro_micro_i2c</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">status</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"okay"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token label symbol" style="color:#e36209">oled:</span><span class="token plain"> </span><span class="token node class-name" style="color:#6f42c1">ssd1306@</span><span class="token node class-name number" style="color:#005cc5">3</span><span class="token node class-name" style="color:#6f42c1">c</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"solomon,ssd1306fb"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">reg</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">0x3c</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">width</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">128</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">height</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">32</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">segment-offset</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">0</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">page-offset</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">0</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">display-offset</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">0</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">multiplex-ratio</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">31</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">com-invdir</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">segment-remap</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">com-sequential</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">prechargep</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">0x22</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<p>You would add a <code>chosen</code> node like:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token node class-name" style="color:#6f42c1">/</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token node class-name" style="color:#6f42c1">chosen</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">zephyr,display</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token reference variable" style="color:#005cc5">&amp;oled</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="usb-logging">USB Logging<a href="https://zmk.dev/blog/2022/04/02/zephyr-3-0#usb-logging" class="hash-link" aria-label="Direct link to USB Logging" title="Direct link to USB Logging" translate="no">​</a></h3>
<p>Zephyr unified the way the console/logging device is selected, removing the hacks that special-cased the USB CDC ACM output.
Now, the CDC ACM device is configured in the devicetree as well. To ensure that USB logging properly works with custom board definitions,
two sections of the <code>&lt;board&gt;.dts</code> file need updating.</p>
<p>Underneath the USB device, add the CDC ACM node:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token reference variable" style="color:#005cc5">&amp;usbd</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">status</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"okay"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token label symbol" style="color:#e36209">cdc_acm_uart:</span><span class="token plain"> </span><span class="token node class-name" style="color:#6f42c1">cdc_acm_uart</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"zephyr,cdc-acm-uart"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<p>Then, an additional <code>chosen</code> node (near the top of the file) will mark the CDC ACM device as the console:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token node class-name" style="color:#6f42c1">/</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token node class-name" style="color:#6f42c1">chosen</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token attr-name" style="color:#005cc5">zephyr,console</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token reference variable" style="color:#005cc5">&amp;cdc_acm_uart</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="uf2-builds">UF2 Builds<a href="https://zmk.dev/blog/2022/04/02/zephyr-3-0#uf2-builds" class="hash-link" aria-label="Direct link to UF2 Builds" title="Direct link to UF2 Builds" translate="no">​</a></h3>
<p>Previously, to get ZMK to build a UF2 image to flash to a given board required adding a <code>CMakeLists.txt</code> file that added a custom post build command.
Now, the only thing necessary to have Zephyr build a UF2 is to add the following to your <code>&lt;board&gt;_defconfig</code> file:</p>
<div class="language-ini codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-ini codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token key attr-name" style="color:#005cc5">CONFIG_BUILD_OUTPUT_UF2</span><span class="token punctuation">=</span><span class="token value attr-value">y</span><br></span></code></pre></div></div>
<p>If updating an existing board, be sure to remove the previous <code>CMakeLists.txt</code> file to avoid generating the UF2 twice during a <code>west build</code>.</p>
<p>For more details on the implementation, see <a href="https://github.com/zephyrproject-rtos/zephyr/pull/31066" target="_blank" rel="noopener noreferrer" class="">zephyr#31066</a>.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="stm32-clock-configuration">STM32 Clock Configuration<a href="https://zmk.dev/blog/2022/04/02/zephyr-3-0#stm32-clock-configuration" class="hash-link" aria-label="Direct link to STM32 Clock Configuration" title="Direct link to STM32 Clock Configuration" translate="no">​</a></h3>
<p>Clock configuration moved to devicetree as well, out of the Kconfig files. Here is a sample config for a board that uses the HSI for the PLL source:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token reference variable" style="color:#005cc5">&amp;clk_hsi</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">status</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"okay"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token reference variable" style="color:#005cc5">&amp;pll</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">prediv</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">1</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">mul</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">12</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">clocks</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;clk_hsi</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">status</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"okay"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token reference variable" style="color:#005cc5">&amp;rcc</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">clocks</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;pll</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">clock-frequency</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token function" style="color:#6f42c1">DT_FREQ_M</span><span class="token punctuation">(</span><span class="token number" style="color:#005cc5">72</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">ahb-prescaler</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">1</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">  </span><span class="token attr-name" style="color:#005cc5">apb1-prescaler</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">2</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<p>After adding the nodes, be sure to remove the clock/PLL related configuration from the <code>&lt;board&gt;_defconfig</code> file.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="seeeduino-xiao">Seeeduino XIAO<a href="https://zmk.dev/blog/2022/04/02/zephyr-3-0#seeeduino-xiao" class="hash-link" aria-label="Direct link to Seeeduino XIAO" title="Direct link to Seeeduino XIAO" translate="no">​</a></h2>
<p>The Seeed(uino) XIAO has gained in popularity for use on smaller boards, and gained more traction with the release of the new XIAO BLE board,
powered by the popular nRF52840 SoC. As part of the 3.0 update, we've also more fully integrated the XIAO and XIAO BLE to make it easier to
build keyboard (shields) using either controller.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="future-hardware">Future Hardware<a href="https://zmk.dev/blog/2022/04/02/zephyr-3-0#future-hardware" class="hash-link" aria-label="Direct link to Future Hardware" title="Direct link to Future Hardware" translate="no">​</a></h2>
<p>One of the exciting items that's one step closer as part of this work is <a href="https://github.com/zmkfirmware/zmk/issues/1085" target="_blank" rel="noopener noreferrer" class="">support for Raspberry Pi Pico/RP2040</a>.
With Zephyr 3.0 merged, this start the process for getting those controllers/chips supported by ZMK. Follow the issue to keep track of progress.
This will also enable us to support the XIAO compatible Adafruit Qt Py RP2040 and XIAO RP2040.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="thanks">Thanks!<a href="https://zmk.dev/blog/2022/04/02/zephyr-3-0#thanks" class="hash-link" aria-label="Direct link to Thanks!" title="Direct link to Thanks!" translate="no">​</a></h2>
<p>Thanks to all the testers who have helped verify ZMK functionality on the newer Zephyr version.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="article-updates">Article Updates<a href="https://zmk.dev/blog/2022/04/02/zephyr-3-0#article-updates" class="hash-link" aria-label="Direct link to Article Updates" title="Direct link to Article Updates" translate="no">​</a></h2>
<ul>
<li class="">12/2023: Removed the deprecated <code>label</code> property from code snippets.</li>
</ul>]]></content:encoded>
            <category>firmware</category>
            <category>zephyr</category>
            <category>core</category>
        </item>
        <item>
            <title><![CDATA[Zephyr 3.0 Update Preparation]]></title>
            <link>https://zmk.dev/blog/2022/03/08/zephyr-3-0-upgrade-prep</link>
            <guid>https://zmk.dev/blog/2022/03/08/zephyr-3-0-upgrade-prep</guid>
            <pubDate>Tue, 08 Mar 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[As preparation for completing the work to upgrade ZMK to Zephyr 3.0, users with user config repositories who wish to avoid future build failures with their GitHub Actions workflows can take steps to adjust]]></description>
            <content:encoded><![CDATA[<p>As preparation for completing the <a href="https://github.com/zmkfirmware/zmk/pull/1143" target="_blank" rel="noopener noreferrer" class="">work</a> to upgrade ZMK to <a href="https://docs.zephyrproject.org/3.0.0/releases/release-notes-3.0.html" target="_blank" rel="noopener noreferrer" class="">Zephyr 3.0</a>, users with user config repositories who wish to avoid future build failures with their GitHub Actions workflows can take steps to adjust
their repositories now.</p>
<!-- -->
<p>GitHub Actions needs to use our latest Docker image to ensure continued compatibility with the ZMK codebase on Zephyr 3.0 (and beyond). You should:</p>
<ul>
<li class="">Open <code>.github/workflows/build.yml</code> in your editor/IDE</li>
<li class="">Change <code>zmkfirmware/zmk-build-arm:2.5</code> to <code>zmkfirmware/zmk-build-arm:stable</code> wherever it is found</li>
</ul>
<p>Once the changes are committed and pushed, the build will run as expected.</p>
<p>A future blog post will outline the complete Zephyr 3.0 changes once that work is finalized.</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>If you created your user config repository a while ago, you may find that your <code>build.yml</code> file instead references
a <code>zephyr-west-action-arm</code> custom GitHub Action instead. In this case, the upgrade is not as direct. We suggest that
instead you <a class="" href="https://zmk.dev/docs/user-setup">re-create your config repository</a> to get an updated setup using the new automation
approach.</p></div></div>]]></content:encoded>
            <category>firmware</category>
            <category>zephyr</category>
            <category>core</category>
        </item>
        <item>
            <title><![CDATA[Zephyr 2.5 Update]]></title>
            <link>https://zmk.dev/blog/2021/07/17/zephyr-2-5</link>
            <guid>https://zmk.dev/blog/2021/07/17/zephyr-2-5</guid>
            <pubDate>Sat, 17 Jul 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[I'm happy to announce that we have completed the work to upgrade ZMK to Zephyr 2.5!]]></description>
            <content:encoded><![CDATA[<p>I'm happy to announce that we have completed the <a href="https://github.com/zmkfirmware/zmk/pull/736/" target="_blank" rel="noopener noreferrer" class="">work</a> to upgrade ZMK to <a href="https://docs.zephyrproject.org/2.5.0/releases/release-notes-2.5.html" target="_blank" rel="noopener noreferrer" class="">Zephyr 2.5</a>!</p>
<!-- -->
<p>A big part of this work was some <em>major</em> refactors and improvements by <a href="https://github.com/innovaker" target="_blank" rel="noopener noreferrer" class="">innovaker</a> to our <a href="https://github.com/zmkfirmware/zmk-docker/" target="_blank" rel="noopener noreferrer" class="">zmk-docker</a> Docker image and GH Actions automation.</p>
<ul>
<li class="">Faster build times with improved caching.</li>
<li class="">Integration tests which automatically verify new images.</li>
<li class="">PRs to the repo now build properly and run the tests as well.</li>
<li class="">Build images for multiple target architectures, e.g. <code>zmk-build-riscv64</code>, all in parallel.</li>
<li class="">Nightly builds to be sure we're pulling in the latest OS/package updates, to ensure we keep our images up to date, address any reported vulnerabilities, etc.</li>
<li class="">Faster upgrade paths for future Zephyr SDK and Zephyr versions.</li>
</ul>
<p>In addition, <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> did the upgrade work to adjust ZMK for the Zephyr changes.</p>
<ul>
<li class="">Updated to newer devicetree/driver Zephyr API</li>
<li class="">Adjustment for Zephyr pinmux changes</li>
<li class="">Fixes for power management, LVGL, and formatter changes</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="getting-the-changes">Getting The Changes<a href="https://zmk.dev/blog/2021/07/17/zephyr-2-5#getting-the-changes" class="hash-link" aria-label="Direct link to Getting The Changes" title="Direct link to Getting The Changes" translate="no">​</a></h2>
<p>Use the following steps to update to the latest tooling in order to properly use the new ZMK changes:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="user-config-repositories-using-github-actions">User Config Repositories Using GitHub Actions<a href="https://zmk.dev/blog/2021/07/17/zephyr-2-5#user-config-repositories-using-github-actions" class="hash-link" aria-label="Direct link to User Config Repositories Using GitHub Actions" title="Direct link to User Config Repositories Using GitHub Actions" translate="no">​</a></h3>
<p>Existing user config repositories using Github Actions to build will pull down Zephyr 2.5 automatically,
and should work, fine as is. However, to upgrade to the newer Docker image, you should:</p>
<ul>
<li class="">Open <code>.github/workflows/build.yml</code> in your editor/IDE</li>
<li class="">Change <code>zmkfirmware/zmk-build-arm:2.4</code> to <code>zmkfirmware/zmk-build-arm:2.5</code> wherever it is found</li>
</ul>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>If you created your user config repository a while ago, you may find that your <code>build.yml</code> file instead references
a <code>zephyr-west-action-arm</code> custom GitHub Action instead. In this case, the upgrade is not as direct. We suggest that
instead you <a class="" href="https://zmk.dev/docs/user-setup">re-create your config repository</a> to get an updated setup using the new automation
approach.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="vs-code--docker-dev-container">VS Code &amp; Docker (Dev Container)<a href="https://zmk.dev/blog/2021/07/17/zephyr-2-5#vs-code--docker-dev-container" class="hash-link" aria-label="Direct link to VS Code &amp; Docker (Dev Container)" title="Direct link to VS Code &amp; Docker (Dev Container)" translate="no">​</a></h3>
<p>If you build locally using VS Code &amp; Docker then:</p>
<ul>
<li class="">pull the latest ZMK <code>main</code> with <code>git pull</code> for your ZMK checkout</li>
<li class="">reload the project</li>
<li class="">if you are prompted to rebuild the remote container, click <code>Rebuild</code></li>
<li class="">otherwise, press <code>F1</code> and run <code>Remote Containers: Rebuild Container</code></li>
<li class="">Once the container has rebuilt and reloaded, run <code>west update</code> to pull the updated Zephyr version and its dependencies.</li>
</ul>
<p>Once the container has rebuilt, VS Code will be running the 2.5 Docker image.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="local-host-development">Local Host Development<a href="https://zmk.dev/blog/2021/07/17/zephyr-2-5#local-host-development" class="hash-link" aria-label="Direct link to Local Host Development" title="Direct link to Local Host Development" translate="no">​</a></h3>
<p>The following steps will get you building ZMK locally against Zephyr 2.5:</p>
<ul>
<li class="">Run the updated <a class="" href="https://zmk.dev/docs/development/local-toolchain/setup">toolchain installation</a> steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)</li>
<li class="">pull the latest ZMK <code>main</code> with <code>git pull</code> for your ZMK checkout</li>
<li class="">run <code>west update</code> to pull the updated Zephyr version and its dependencies</li>
</ul>
<p>From there, you should be ready to build as normal!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="thanks">Thanks!<a href="https://zmk.dev/blog/2021/07/17/zephyr-2-5#thanks" class="hash-link" aria-label="Direct link to Thanks!" title="Direct link to Thanks!" translate="no">​</a></h2>
<p>Thanks again to <a href="https://github.com/innovaker" target="_blank" rel="noopener noreferrer" class="">innovaker</a> for all the hard work, and to all the testers who have helped verify ZMK functionality on the newer Zephyr version.</p>]]></content:encoded>
            <category>firmware</category>
            <category>zephyr</category>
            <category>core</category>
        </item>
        <item>
            <title><![CDATA[ZMK State Of The Firmware #4]]></title>
            <link>https://zmk.dev/blog/2021/01/27/zmk-sotf-4</link>
            <guid>https://zmk.dev/blog/2021/01/27/zmk-sotf-4</guid>
            <pubDate>Wed, 27 Jan 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Welcome to the fourth ZMK "State Of The Firmware" (SOTF)!]]></description>
            <content:encoded><![CDATA[<p>Welcome to the fourth ZMK "State Of The Firmware" (SOTF)!</p>
<p>This update will cover all the major activity since <a class="" href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3">SOTF #3</a>.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="recent-activity">Recent Activity<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#recent-activity" class="hash-link" aria-label="Direct link to Recent Activity" title="Direct link to Recent Activity" translate="no">​</a></h2>
<p>Here's a summary of the various major changes since last time, broken down by theme:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="keymapsbehaviors">Keymaps/Behaviors<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#keymapsbehaviors" class="hash-link" aria-label="Direct link to Keymaps/Behaviors" title="Direct link to Keymaps/Behaviors" translate="no">​</a></h3>
<p>Since last time, there have been several new powerful keymap features and behaviors added, including one of the most asked for features, combos!</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="combos">Combos<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#combos" class="hash-link" aria-label="Direct link to Combos" title="Direct link to Combos" translate="no">​</a></h4>
<p>The initial <a class="" href="https://zmk.dev/docs/keymaps/combos">combos</a> work has landed! The amazing <a href="https://github.com/okke-formsma" target="_blank" rel="noopener noreferrer" class="">okke-formsma</a> has once again delivered another powerful feature for ZMK. Combos are "position based", and are configured in a new toplevel node next to they <code>keymap</code> node in user's keymap files.</p>
<p>An example, that would send the <code>ESC</code> keycode when pressing both the first and second positions on your keyboard:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token node class-name" style="color:#6f42c1">/</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token node class-name" style="color:#6f42c1">combos</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token attr-name" style="color:#005cc5">compatible</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token string" style="color:#032f62">"zmk,combos"</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token node class-name" style="color:#6f42c1">combo_esc</span><span class="token plain"> </span><span class="token punctuation">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">timeout-ms</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">50</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">key-positions</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token number" style="color:#005cc5">0</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">1</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">            </span><span class="token attr-name" style="color:#005cc5">bindings</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> ESC</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">        </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain">    </span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">}</span><span class="token punctuation">;</span><br></span></code></pre></div></div>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>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.</p></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="sticky-keys-one-shot-modslayers-behavior">Sticky Keys (One-Shot Mods/Layers) Behavior<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#sticky-keys-one-shot-modslayers-behavior" class="hash-link" aria-label="Direct link to Sticky Keys (One-Shot Mods/Layers) Behavior" title="Direct link to Sticky Keys (One-Shot Mods/Layers) Behavior" translate="no">​</a></h4>
<p><a href="https://github.com/okke-formsma" target="_blank" rel="noopener noreferrer" class="">okke-formsma</a> 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:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token reference variable" style="color:#005cc5">&amp;sk</span><span class="token plain"> LEFT_CONTROL</span><br></span></code></pre></div></div>
<p>for a sticky key/modifier, or:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token reference variable" style="color:#005cc5">&amp;sl</span><span class="token plain"> NAV</span><br></span></code></pre></div></div>
<p>for a sticky layer.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="to-layer-behavior"><code>&amp;to</code> Layer Behavior<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#to-layer-behavior" class="hash-link" aria-label="Direct link to to-layer-behavior" title="Direct link to to-layer-behavior" translate="no">​</a></h4>
<p><a href="https://github.com/mcrosson" target="_blank" rel="noopener noreferrer" class="">mcrosson</a> contributed the new <a class="" href="https://zmk.dev/docs/keymaps/behaviors/layers#to-layer"><code>&amp;to</code></a> layer related behavior. This can be used to completely replace the active layer with a new one.</p>
<p>This is most frequently used when using multiple core base layers with different layouts, e.g. QWERTY and DVORAK, to switch between them.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="grave-escape-behavior">Grave Escape Behavior<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#grave-escape-behavior" class="hash-link" aria-label="Direct link to Grave Escape Behavior" title="Direct link to Grave Escape Behavior" translate="no">​</a></h4>
<p><a href="https://github.com/okke-formsma" target="_blank" rel="noopener noreferrer" class="">okke-formsma</a> added an implementation of the "Grave Escape" behavior, developing a more generic "mod-morph" behavior to do so. Adding</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token reference variable" style="color:#005cc5">&amp;gresc</span><br></span></code></pre></div></div>
<p>to your keymap will send <code>ESC</code> when pressed on its own, but will send <code>`</code> when pressed with a GUI or Shift modifier held.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="rgb-underglow-color-selection">RGB Underglow Color Selection<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#rgb-underglow-color-selection" class="hash-link" aria-label="Direct link to RGB Underglow Color Selection" title="Direct link to RGB Underglow Color Selection" translate="no">​</a></h4>
<p><a href="https://github.com/mcrosson" target="_blank" rel="noopener noreferrer" class="">mcrosson</a> updated the <a class="" href="https://zmk.dev/docs/keymaps/behaviors/underglow">RGB Underglow behavior</a> to allow <a class="" href="https://zmk.dev/docs/keymaps/behaviors/underglow#examples">binding an explicit color selection</a> to a key position.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="keymap-upgrader">Keymap Upgrader<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#keymap-upgrader" class="hash-link" aria-label="Direct link to Keymap Upgrader" title="Direct link to Keymap Upgrader" translate="no">​</a></h4>
<p><a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">joelspadin</a> completed the <a class="" href="https://zmk.dev/keymap-upgrader">Keymap Upgrader</a> which can be used to update your keymap to using the latest supported codes, and move away from the old deprecated codes.</p>
<p>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.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="displays">Displays<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#displays" class="hash-link" aria-label="Direct link to Displays" title="Direct link to Displays" translate="no">​</a></h3>
<p>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!</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="idle-blanking">Idle Blanking<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#idle-blanking" class="hash-link" aria-label="Direct link to Idle Blanking" title="Direct link to Idle Blanking" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> 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.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="battery-and-output-widgets">Battery and Output Widgets<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#battery-and-output-widgets" class="hash-link" aria-label="Direct link to Battery and Output Widgets" title="Direct link to Battery and Output Widgets" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> 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.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="highest-layer-display">Highest Layer Display<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#highest-layer-display" class="hash-link" aria-label="Direct link to Highest Layer Display" title="Direct link to Highest Layer Display" translate="no">​</a></h4>
<p><a href="https://github.com/mcrosson" target="_blank" rel="noopener noreferrer" class="">mcrosson</a> has contributed the next display widget, showing the highest active layer in the keymap. <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> then added a small follow up to allow layers in keymaps to add a <code>name</code> property to each layer, e.g. <code>name = "Nav";</code> and have that name be displayed in the widget instead of the numeric layer number.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="wpm">WPM<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#wpm" class="hash-link" aria-label="Direct link to WPM" title="Direct link to WPM" translate="no">​</a></h4>
<p>New contributor <a href="https://github.com/allymparker" target="_blank" rel="noopener noreferrer" class="">allymparker</a> added our fourth widget, a words-per-minute display! This widget work also included creating the core state logic for tracking the WPM.</p>
<p>For now, this widget is only working on the central side of split keyboards.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="miscellaneous">Miscellaneous<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#miscellaneous" class="hash-link" aria-label="Direct link to Miscellaneous" title="Direct link to Miscellaneous" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="zephyr-24">Zephyr 2.4<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#zephyr-24" class="hash-link" aria-label="Direct link to Zephyr 2.4" title="Direct link to Zephyr 2.4" translate="no">​</a></h4>
<p><a href="https://github.com/innovaker" target="_blank" rel="noopener noreferrer" class="">innovaker</a> 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!</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="ble-deadlock-fixes">BLE Deadlock Fixes<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#ble-deadlock-fixes" class="hash-link" aria-label="Direct link to BLE Deadlock Fixes" title="Direct link to BLE Deadlock Fixes" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> 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.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="centralperipheral-selection">Central/Peripheral Selection<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#centralperipheral-selection" class="hash-link" aria-label="Direct link to Central/Peripheral Selection" title="Direct link to Central/Peripheral Selection" translate="no">​</a></h4>
<p>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.</p>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> updated <a href="https://github.com/zmkfirmware/zmk/pull/510" target="_blank" rel="noopener noreferrer" class="">the config files</a> to allow users to override this in their <code>&lt;board&gt;_left.conf</code>/<code>&lt;board&gt;_right.conf</code> files in their user repos.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="improved-docker-containers">Improved Docker Containers<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#improved-docker-containers" class="hash-link" aria-label="Direct link to Improved Docker Containers" title="Direct link to Improved Docker Containers" translate="no">​</a></h4>
<p>As part of the Zephyr 2.4. prep work, <a href="https://github.com/innovaker" target="_blank" rel="noopener noreferrer" class="">innovaker</a>, along with lots of testing and input from <a href="https://github.com/mcrosson" target="_blank" rel="noopener noreferrer" class="">mcrosson</a>, developed a brand new pair of <a href="https://github.com/zmkfirmware/zmk-docker" target="_blank" rel="noopener noreferrer" class="">Docker images</a> which is now published to Docker Hub as <a href="https://hub.docker.com/repository/docker/zmkfirmware/zmk-build-arm" target="_blank" rel="noopener noreferrer" class="">zmkfirmware/zmk-build-arm</a> and <a href="https://hub.docker.com/repository/docker/zmkfirmware/zmk-build-arm" target="_blank" rel="noopener noreferrer" class="">zmkfirmware/zmk-dev-arm</a>.</p>
<p>The previously blogged VSCode + Docker integration, as well as our GH Action build automation was all moved over to the new images.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="settings-debounce">Settings Debounce<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#settings-debounce" class="hash-link" aria-label="Direct link to Settings Debounce" title="Direct link to Settings Debounce" translate="no">​</a></h4>
<p><a href="https://github.com/Nicell" target="_blank" rel="noopener noreferrer" class="">nicell</a> 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.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-shields">New Shields<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#new-shields" class="hash-link" aria-label="Direct link to New Shields" title="Direct link to New Shields" translate="no">​</a></h2>
<ul>
<li class="">Jorne &amp; Jian in <a href="https://github.com/zmkfirmware/zmk/pull/331" target="_blank" rel="noopener noreferrer" class="">#331</a> - <a href="https://github.com/krikun98" target="_blank" rel="noopener noreferrer" class="">krikun98</a></li>
<li class="">tidbit in <a href="https://github.com/zmkfirmware/zmk/pull/424" target="_blank" rel="noopener noreferrer" class="">#424</a> - <a href="https://github.com/mcrosson" target="_blank" rel="noopener noreferrer" class="">mcrosson</a></li>
<li class="">Helix in <a href="https://github.com/zmkfirmware/zmk/pull/429" target="_blank" rel="noopener noreferrer" class="">#429</a> - <a href="https://github.com/KingCoinless" target="_blank" rel="noopener noreferrer" class="">KingCoinless</a></li>
<li class="">BFO-9000 in <a href="https://github.com/zmkfirmware/zmk/pull/472" target="_blank" rel="noopener noreferrer" class="">#472</a> - <a href="https://github.com/pbz" target="_blank" rel="noopener noreferrer" class="">pbz</a></li>
<li class="">CRBN in <a href="https://github.com/zmkfirmware/zmk/pull/483" target="_blank" rel="noopener noreferrer" class="">#493</a> - <a href="https://github.com/ReFil" target="_blank" rel="noopener noreferrer" class="">ReFil</a></li>
<li class="">Eek in <a href="https://github.com/zmkfirmware/zmk/pull/529" target="_blank" rel="noopener noreferrer" class="">#529</a> - <a href="https://github.com/MangoIV" target="_blank" rel="noopener noreferrer" class="">MangoIV</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-boards">New Boards<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#new-boards" class="hash-link" aria-label="Direct link to New Boards" title="Direct link to New Boards" translate="no">​</a></h2>
<ul>
<li class="">BDN9 Rev2 in <a href="https://github.com/zmkfirmware/zmk/pull/557" target="_blank" rel="noopener noreferrer" class="">#557</a> - <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="sponsorship">Sponsorship<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#sponsorship" class="hash-link" aria-label="Direct link to Sponsorship" title="Direct link to Sponsorship" translate="no">​</a></h2>
<p>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 <em>is</em> good that can come from folks sponsoring ZMK.</p>
<p>You can see the full discussion on <a href="https://github.com/zmkfirmware/zmk/issues/497" target="_blank" rel="noopener noreferrer" class="">#497</a>, but some items that are being considered with sponsorship funds:</p>
<ul>
<li class="">Hiring a designer to complete the logo/mascot work.</li>
<li class="">Creating stickers to send as thank-yous to first time contributors.</li>
<li class="">Hosting costs for GitHub Pro.</li>
<li class="">Other hosting costs, e.g. Docker Hub.</li>
</ul>
<p>For anyone looking to contribute, you can find the <a href="https://opencollective.com/zmkfirmware" target="_blank" rel="noopener noreferrer" class="">ZMK Firmware project</a> is now set up on <a href="https://opencollective.com/" target="_blank" rel="noopener noreferrer" class="">Open Collective</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="coming-soon">Coming Soon!<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#coming-soon" class="hash-link" aria-label="Direct link to Coming Soon!" title="Direct link to Coming Soon!" translate="no">​</a></h2>
<p>Some items listed in the last coming soon section are still under active development.</p>
<ul>
<li class="">A power profiler page for the website, to help users estimate their battery life for a given keyboard - <a href="https://github.com/Nicell" target="_blank" rel="noopener noreferrer" class="">Nicell</a></li>
<li class="">Behavior "locality", allowing improved split usage for things like <code>&amp;sys_reset</code>, and controlling external power and RGB underglow for both sides - <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a></li>
<li class="">More modular approach to external boards/shields, custom code, user keymaps, etc.</li>
<li class="">More shields and boards</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="statistics">Statistics<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#statistics" class="hash-link" aria-label="Direct link to Statistics" title="Direct link to Statistics" translate="no">​</a></h2>
<p>Some statistics of interest for ZMK:</p>
<ul>
<li class="">GitHub (lifetime stats)
<ul>
<li class="">389 Closed PRs</li>
<li class="">199 Stars</li>
<li class="">163 Forks</li>
</ul>
</li>
<li class="">Discord Chat
<ul>
<li class="">702 total registered</li>
</ul>
</li>
<li class="">Website (last 30 days)
<ul>
<li class="">11.5K page views</li>
<li class="">1K new users</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="thanks">Thanks!<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#thanks" class="hash-link" aria-label="Direct link to Thanks!" title="Direct link to Thanks!" translate="no">​</a></h2>
<p>Thanks again to the numerous contributors, testers, and users who have made working on ZMK such a pleasure!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="article-updates">Article Updates<a href="https://zmk.dev/blog/2021/01/27/zmk-sotf-4#article-updates" class="hash-link" aria-label="Direct link to Article Updates" title="Direct link to Article Updates" translate="no">​</a></h2>
<ul>
<li class="">12/2023: The <code>label</code> property for keymap layers was renamed to <code>display-name</code>.</li>
</ul>]]></content:encoded>
            <category>SOTF</category>
            <category>keyboards</category>
            <category>firmware</category>
            <category>oss</category>
            <category>ble</category>
        </item>
        <item>
            <title><![CDATA[ZMK State Of The Firmware #3]]></title>
            <link>https://zmk.dev/blog/2020/11/09/zmk-sotf-3</link>
            <guid>https://zmk.dev/blog/2020/11/09/zmk-sotf-3</guid>
            <pubDate>Mon, 09 Nov 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Welcome to the third ZMK "State Of The Firmware" (SOTF)!]]></description>
            <content:encoded><![CDATA[<p>Welcome to the third ZMK "State Of The Firmware" (SOTF)!</p>
<p>This update will cover all the major activity since <a class="" href="https://zmk.dev/blog/2020/09/21/zmk-sotf-2">SOTF #2</a>. This edition comes a bit later than planned, but the amount of features and changes will hopefully make it worth it!</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="recent-activity">Recent Activity<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#recent-activity" class="hash-link" aria-label="Direct link to Recent Activity" title="Direct link to Recent Activity" translate="no">​</a></h2>
<p>Here's a summary of the various major changes since last time, broken down by theme:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="keymapsbehaviors">Keymaps/Behaviors<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#keymapsbehaviors" class="hash-link" aria-label="Direct link to Keymaps/Behaviors" title="Direct link to Keymaps/Behaviors" translate="no">​</a></h3>
<p>Tons of activity related to keymaps, so we'll go into more detail this time.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="codes-overhaul">Codes Overhaul<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#codes-overhaul" class="hash-link" aria-label="Direct link to Codes Overhaul" title="Direct link to Codes Overhaul" translate="no">​</a></h4>
<p><a href="https://github.com/innovaker" target="_blank" rel="noopener noreferrer" class="">innovaker</a> <em>completely</em> overhauled the set of available codes for keymaps, and simultaneously has created
<em>beautiful</em> <a class="" href="https://zmk.dev/docs/keymaps/list-of-keycodes">documentation</a> to help users visualize the codes, and also understand if they are supported on their particular operating system.</p>
<p>This also laid the foundation for the other keymap related changes that are now available.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="modified-shifted-codes">Modified (Shifted) Codes<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#modified-shifted-codes" class="hash-link" aria-label="Direct link to Modified (Shifted) Codes" title="Direct link to Modified (Shifted) Codes" translate="no">​</a></h4>
<p><a href="https://github.com/okke-formsma" target="_blank" rel="noopener noreferrer" class="">okke-formsma</a> added the ability to apply modifiers to a code, e.g.:</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token reference variable" style="color:#005cc5">&amp;kp</span><span class="token plain"> </span><span class="token function" style="color:#6f42c1">LC</span><span class="token punctuation">(</span><span class="token plain">C</span><span class="token punctuation">)</span><br></span></code></pre></div></div>
<p>which sends <code>Control + c</code> when pressed. This feature is often used on smaller keyboards to achieve "shifted keycodes", e.g. <code>LS(N1)</code> to send a <code>!</code>.
To make this easier, in addition to all the normal codes, we now have defines for common shifted codes, e.g. <code>EXCL</code> for <code>!</code>, <code>AT</code> for <code>@</code>, etc.</p>
<p>To learn more, check out the <a class="" href="https://zmk.dev/docs/keymaps/modifiers">Modifiers</a> documentation.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="simplified-key-press-behavior">Simplified Key Press Behavior<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#simplified-key-press-behavior" class="hash-link" aria-label="Direct link to Simplified Key Press Behavior" title="Direct link to Simplified Key Press Behavior" translate="no">​</a></h4>
<p>In previous versions of ZMK, users needed to be careful to select between the <code>&amp;kp</code> and <code>&amp;cp</code> behaviors in their keymaps, depending on
whether the particular keycode they wanted to send was in the "HID consumer page" or not. Forcing users to understand the difference and get
this right was awkward and error prone.</p>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> and <a href="https://github.com/innovaker" target="_blank" rel="noopener noreferrer" class="">innovaker</a> have reduced this complexity. Users can now simply use <code>&amp;kp</code> with all available codes and ZMK will
handle sending the right events to the connected host.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="power-management">Power Management<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#power-management" class="hash-link" aria-label="Direct link to Power Management" title="Direct link to Power Management" translate="no">​</a></h3>
<p>Several important power management features have been added to ZMK, helping save power for many use cases.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="ble-battery-level-reporting">BLE Battery Level Reporting<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#ble-battery-level-reporting" class="hash-link" aria-label="Direct link to BLE Battery Level Reporting" title="Direct link to BLE Battery Level Reporting" translate="no">​</a></h4>
<p><a href="https://github.com/Nicell" target="_blank" rel="noopener noreferrer" class="">Nicell</a> added the necessary <a href="https://github.com/zmkfirmware/zmk/pull/293" target="_blank" rel="noopener noreferrer" class="">driver</a> and <a href="https://github.com/zmkfirmware/zmk/pull/306" target="_blank" rel="noopener noreferrer" class="">core code</a> to send BLE battery level notifications to hosts that support displaying them. Testing seems to show this works with Windows and GNOME, but macOS does not display the battery info.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="external-power-control">External Power Control<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#external-power-control" class="hash-link" aria-label="Direct link to External Power Control" title="Direct link to External Power Control" translate="no">​</a></h4>
<p><a href="https://github.com/megamind4089" target="_blank" rel="noopener noreferrer" class="">megamind4089</a> added a new <a href="https://github.com/zmkfirmware/zmk/pull/242" target="_blank" rel="noopener noreferrer" class="">driver</a> and <a href="https://github.com/zmkfirmware/zmk/pull/258" target="_blank" rel="noopener noreferrer" class="">behavior</a> to allow users to toggle (on/off) the external power supplied by boards such as the nRFMicro
and nice!nano that have specialized hardware for this purpose.</p>
<p>With this change, you can add</p>
<div class="language-dts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-dts codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token reference variable" style="color:#005cc5">&amp;ext_power</span><span class="token plain"> EP_TOG</span><br></span></code></pre></div></div>
<p>to toggle (on/off) the power to external hardware like RGB underglow or OLEDs. Check out the <a class="" href="https://zmk.dev/docs/keymaps/behaviors/power#external-power-control">external power control</a> docs for more info.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="deep-sleep">Deep Sleep<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#deep-sleep" class="hash-link" aria-label="Direct link to Deep Sleep" title="Direct link to Deep Sleep" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> has contributed the initial <a href="https://github.com/zmkfirmware/zmk/pull/211" target="_blank" rel="noopener noreferrer" class="">deep sleep</a> support to ZMK. This work also
included some automatic power savings by switching to PORT events on the nRF52 chips, which reduces the idle power draw, even without deep sleep. Deep sleep is currently not turned on by default, but will be soon.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="miscellaneous">Miscellaneous<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#miscellaneous" class="hash-link" aria-label="Direct link to Miscellaneous" title="Direct link to Miscellaneous" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="output-selection">Output Selection<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#output-selection" class="hash-link" aria-label="Direct link to Output Selection" title="Direct link to Output Selection" translate="no">​</a></h4>
<p><a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">joelspadin</a> added <a class="" href="https://zmk.dev/docs/keymaps/behaviors/outputs">output selection</a> 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.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="bootloader-corruption-fix">Bootloader Corruption Fix<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#bootloader-corruption-fix" class="hash-link" aria-label="Direct link to Bootloader Corruption Fix" title="Direct link to Bootloader Corruption Fix" translate="no">​</a></h4>
<p><a href="https://github.com/Nicell" target="_blank" rel="noopener noreferrer" class="">Nicell</a> has already <a class="" href="https://zmk.dev/blog/2020/10/03/bootloader-fix">blogged about this</a>, but for those that missed it, a <em>major</em>, and incredibly difficult to pin down bug involving corruption of the bootloader on devices using the Adafruit nRF52 bootloader has been fixed by <a href="https://github.com/Nicell" target="_blank" rel="noopener noreferrer" class="">Nicell</a>. If you've encountered this bug, flashing the latest firmware should prevent it from reoccurring. Unfortunately, due to the nature of this fix, you will need to re-pair your keyboard with your hosts, as the fix involves changing where settings are stored in the flash of the controller.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="official-usb-product-id">Official USB Product ID<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#official-usb-product-id" class="hash-link" aria-label="Direct link to Official USB Product ID" title="Direct link to Official USB Product ID" translate="no">​</a></h4>
<p><a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a> has gotten an official <a href="https://github.com/openmoko/openmoko-usb-oui/pull/15" target="_blank" rel="noopener noreferrer" class="">USB product ID</a> assigned to the ZMK Firmware. For anyone looking to uniquely identify a USB device running the ZMK Firmware, you can match on:</p>
<ul>
<li class="">Vendor ID: <code>0x1d50</code></li>
<li class="">Product ID: <code>0x615e</code></li>
</ul>
<p>We are incredibly grateful that Openmoko Inc., in the wake of discontinuing the openmoko projects, has made this an option for OSS projects.</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="development-remote-docker-container-integration">Development: Remote Docker Container Integration<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#development-remote-docker-container-integration" class="hash-link" aria-label="Direct link to Development: Remote Docker Container Integration" title="Direct link to Development: Remote Docker Container Integration" translate="no">​</a></h4>
<p><a href="https://github.com/idan" target="_blank" rel="noopener noreferrer" class="">idan</a> contributed <a href="https://github.com/zmkfirmware/zmk/pull/209" target="_blank" rel="noopener noreferrer" class="">VSCode devcontainer integration</a> to make it easier for developers to build and develop ZMK without having to do complicated local toolchain setup and configuration. This also opens up some amazing future flexibility for things like <a href="https://twitter.com/ZMKFirmware/status/1315760616779505678?s=20" target="_blank" rel="noopener noreferrer" class="">GitHub Codespaces</a>.</p>
<p>There's some follow up tweaks necessary for better supporting using this with user config repositories, which will be available soon.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-shields">New Shields<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#new-shields" class="hash-link" aria-label="Direct link to New Shields" title="Direct link to New Shields" translate="no">​</a></h2>
<ul>
<li class="">Reviung41 in <a href="https://github.com/zmkfirmware/zmk/pull/297" target="_blank" rel="noopener noreferrer" class="">#297</a> - <a href="https://github.com/Nicell" target="_blank" rel="noopener noreferrer" class="">Nicell</a></li>
<li class="">Boardsource 3x4 in <a href="https://github.com/zmkfirmware/zmk/pull/296" target="_blank" rel="noopener noreferrer" class="">#296</a> - <a href="https://github.com/neegool" target="_blank" rel="noopener noreferrer" class="">neegool</a></li>
<li class="">NIBBLE in <a href="https://github.com/zmkfirmware/zmk/pull/292" target="_blank" rel="noopener noreferrer" class="">#292</a> - <a href="https://github.com/jaygreco" target="_blank" rel="noopener noreferrer" class="">jaygreco</a></li>
<li class="">Microdox in <a href="https://github.com/zmkfirmware/zmk/pull/245" target="_blank" rel="noopener noreferrer" class="">#245</a> - <a href="https://github.com/careyk007" target="_blank" rel="noopener noreferrer" class="">careyk007</a></li>
<li class="">MakerDiary M60 in <a href="https://github.com/zmkfirmware/zmk/pull/233" target="_blank" rel="noopener noreferrer" class="">#233</a> - <a href="https://github.com/megamind4089" target="_blank" rel="noopener noreferrer" class="">megamind4089</a></li>
<li class="">TGX4 in <a href="https://github.com/zmkfirmware/zmk/pull/226" target="_blank" rel="noopener noreferrer" class="">#226</a> - <a href="https://github.com/mubeenkhan94" target="_blank" rel="noopener noreferrer" class="">mubeenkhan94</a></li>
<li class="">Quefrency V1 in <a href="https://github.com/zmkfirmware/zmk/pull/216" target="_blank" rel="noopener noreferrer" class="">#216</a> - <a href="https://github.com/noar-t" target="_blank" rel="noopener noreferrer" class="">noar-t</a></li>
<li class="">Cradio in <a href="https://github.com/zmkfirmware/zmk/pull/224" target="_blank" rel="noopener noreferrer" class="">#224</a> - <a href="https://github.com/davidphilipbarr" target="_blank" rel="noopener noreferrer" class="">davidphilipbarr</a></li>
<li class="">Romac+ in <a href="https://github.com/zmkfirmware/zmk/pull/198" target="_blank" rel="noopener noreferrer" class="">#198</a> - <a href="https://github.com/reizero00" target="_blank" rel="noopener noreferrer" class="">reizero00</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-boards">New Boards<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#new-boards" class="hash-link" aria-label="Direct link to New Boards" title="Direct link to New Boards" translate="no">​</a></h2>
<ul>
<li class="">MakerDiary nRF52840 M.2 Module in <a href="https://github.com/zmkfirmware/zmk/pull/233" target="_blank" rel="noopener noreferrer" class="">#233</a> - <a href="https://github.com/megamind4089" target="_blank" rel="noopener noreferrer" class="">megamind4089</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="testing">Testing<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#testing" class="hash-link" aria-label="Direct link to Testing" title="Direct link to Testing" translate="no">​</a></h2>
<p>There has been an <em>amazing</em> amount of testing from various users as we develop new features. In particular, we'd like to give a shout out to <a href="https://github.com/tominabox1" target="_blank" rel="noopener noreferrer" class="">tominabox1</a> who has been tireless in providing detailed and thorough testing of
changes as they are being developed.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="coming-soon">Coming Soon!<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#coming-soon" class="hash-link" aria-label="Direct link to Coming Soon!" title="Direct link to Coming Soon!" translate="no">​</a></h2>
<p>Some items listed in the last coming soon section are still under active development.</p>
<ul>
<li class="">OLED work, including battery and USB/BLE connection status - <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a></li>
<li class="">One shot mod/layer behaviors - <a href="https://github.com/okke-formsma" target="_blank" rel="noopener noreferrer" class="">okke-formsma</a></li>
<li class="">A power profiler page for the website, to help users estimate their battery life for a given keyboard - <a href="https://github.com/Nicell" target="_blank" rel="noopener noreferrer" class="">Nicell</a></li>
<li class="">A keymap converter to automatically update keymaps to the new codes and use of <code>&amp;kp</code> everywhere - <a href="https://github.com/joelspadin" target="_blank" rel="noopener noreferrer" class="">joelspadin</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="statistics">Statistics<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#statistics" class="hash-link" aria-label="Direct link to Statistics" title="Direct link to Statistics" translate="no">​</a></h2>
<p>Some statistics of interest for ZMK:</p>
<ul>
<li class="">GitHub (lifetime stats)
<ul>
<li class="">210 Closed PRs</li>
<li class="">116 Stars</li>
<li class="">101 Forks</li>
</ul>
</li>
<li class="">Discord Chat
<ul>
<li class="">363 total registered</li>
</ul>
</li>
<li class="">Website (last 30 days)
<ul>
<li class="">8.5K page views</li>
<li class="">766 new users</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="thanks">Thanks!<a href="https://zmk.dev/blog/2020/11/09/zmk-sotf-3#thanks" class="hash-link" aria-label="Direct link to Thanks!" title="Direct link to Thanks!" translate="no">​</a></h2>
<p>Thanks again to the numerous contributors and users who have made working on ZMK such a pleasure!</p>]]></content:encoded>
            <category>SOTF</category>
            <category>keyboards</category>
            <category>firmware</category>
            <category>oss</category>
            <category>ble</category>
        </item>
        <item>
            <title><![CDATA[Fixing the Mysterious Broken Bootloader]]></title>
            <link>https://zmk.dev/blog/2020/10/03/bootloader-fix</link>
            <guid>https://zmk.dev/blog/2020/10/03/bootloader-fix</guid>
            <pubDate>Sat, 03 Oct 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Recently I was able to fix the "stuck in the bootloader" issue in]]></description>
            <content:encoded><![CDATA[<p>Recently I was able to fix the "stuck in the bootloader" issue in
<a href="https://github.com/zmkfirmware/zmk/pull/322" target="_blank" rel="noopener noreferrer" class="">#322</a> that had been plaguing us
for quite some time. I want to go over what the issue was, how the issue was
diagnosed, and how it was fixed.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="background">Background<a href="https://zmk.dev/blog/2020/10/03/bootloader-fix#background" class="hash-link" aria-label="Direct link to Background" title="Direct link to Background" translate="no">​</a></h2>
<p>What exactly is the "stuck in the bootloader" issue? Seemingly randomly, users'
keyboards would suddenly stop working and when they would reset their keyboard
they would get put into the bootloader instead of back into the firmware. This
would require the user to re-flash the firmware again to get into the firmware.
That wouldn't be so bad except for the fact that once this occurs, every reset
would require the user to re-flash the firmware again. The only way to really
fix this issue was to re-flash the bootloader itself, which is a huge pain.</p>
<p>Going into this, all we knew was that this issue was most likely introduced
somewhere in the <a href="https://github.com/zmkfirmware/zmk/pull/133" target="_blank" rel="noopener noreferrer" class="">#133</a>, which
added Bluetooth profile management. We've had quite a few attempts at trying to
recreate the issue, but we never were able to get it to happen consistently.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="diagnosing-the-issue">Diagnosing the issue<a href="https://zmk.dev/blog/2020/10/03/bootloader-fix#diagnosing-the-issue" class="hash-link" aria-label="Direct link to Diagnosing the issue" title="Direct link to Diagnosing the issue" translate="no">​</a></h2>
<p>This issue had been happening sporadically for the past month, and I finally
decided to dig in to see what was going on. We started in the Discord and
discussed what was common between all of the people who have experienced this
issue. Everyone who had this issue reported that they did quite a bit of profile
switching. This lined up with the possible connection to the Bluetooth profile
management pull request.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="pinpointing-the-cause">Pinpointing the cause<a href="https://zmk.dev/blog/2020/10/03/bootloader-fix#pinpointing-the-cause" class="hash-link" aria-label="Direct link to Pinpointing the cause" title="Direct link to Pinpointing the cause" translate="no">​</a></h3>
<p>I had a hunch that this was related to the settings system. The settings system
is used by profile Bluetooth switching, and the settings system works directly
with the system flash. Based on this hunch, I tried spamming the RGB underglow
cycle behavior on my main keyboard. Sure enough after a couple minutes, I got
stuck in the bootloader. I was even able to reproduce it again.</p>
<p>This was an important discovery for two reasons. First, I was able to recreate
the issue consistently, which meant I could set up logging and more closely
monitor what the board was doing. Second, this more or less proved that it was
specifically the settings system at fault. Both Bluetooth profile switching and
RGB underglow cycling trigger it, and the one common piece is they save their
state to settings.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="settings-system-overview">Settings system overview<a href="https://zmk.dev/blog/2020/10/03/bootloader-fix#settings-system-overview" class="hash-link" aria-label="Direct link to Settings system overview" title="Direct link to Settings system overview" translate="no">​</a></h3>
<p>To understand what's going wrong, we first need to understand how the settings
system works. Here's a diagram to explain the flash space that the settings
system holds for our nRF52840 based boards (nice!nano, nRFMicro, BlueMicro).</p>
<p><img decoding="async" loading="lazy" src="https://i.imgur.com/DF2t3Oq.png" alt="Settings Diagram" class="img_ev3q"></p>
<p>The settings flash space lives at the end of the flash of the chip. In this case
it starts at <code>0xF8000</code> and is <code>0x8000</code> bytes long, which is 32KB in more
comprehensible units. Then due to the chip's architecture, this flash space is
broken into pages, which are <code>0x1000</code> bytes in size (4KB).</p>
<p>The backend that carries out the settings save and read operation in ZMK is
called NVS. NVS calls these pages sectors. Due to how flash works, you can't
write to the same bytes multiple times without erasing them first, and to erase
bytes, you need to erase the entire sector of flash. This means when NVS writes
to the settings flash if there's no erased space available for the new value, it
will need to erase a sector.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="logging-discoveries">Logging discoveries<a href="https://zmk.dev/blog/2020/10/03/bootloader-fix#logging-discoveries" class="hash-link" aria-label="Direct link to Logging discoveries" title="Direct link to Logging discoveries" translate="no">​</a></h3>
<p>So first I enabled logging of the NVS module by adding
<code>CONFIG_NVS_LOG_LEVEL_DBG=y</code> to my <code>.conf</code> file. I repeated the same test of
spamming RGB underglow effect cycle and the resulting logs I got were this:</p>
<div class="language-log codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-log codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token punctuation">[</span><span class="token time number" style="color:#005cc5">00:00:00.000</span><span class="token punctuation">,</span><span class="token number" style="color:#005cc5">671</span><span class="token punctuation">]</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token plain">inf</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token plain"> fs_nvs</span><span class="token operator" style="color:#005cc5">:</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">8</span><span class="token plain"> Sectors of </span><span class="token number" style="color:#005cc5">4096</span><span class="token plain"> bytes</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">[</span><span class="token time number" style="color:#005cc5">00:00:00.000</span><span class="token punctuation">,</span><span class="token number" style="color:#005cc5">671</span><span class="token punctuation">]</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token plain">inf</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token plain"> fs_nvs</span><span class="token operator" style="color:#005cc5">:</span><span class="token plain"> alloc wra</span><span class="token operator" style="color:#005cc5">:</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">3</span><span class="token punctuation">,</span><span class="token plain"> f70</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">[</span><span class="token time number" style="color:#005cc5">00:00:00.000</span><span class="token punctuation">,</span><span class="token number" style="color:#005cc5">671</span><span class="token punctuation">]</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token plain">inf</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token plain"> fs_nvs</span><span class="token operator" style="color:#005cc5">:</span><span class="token plain"> data wra</span><span class="token operator" style="color:#005cc5">:</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">3</span><span class="token punctuation">,</span><span class="token plain"> f40</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token operator" style="color:#005cc5">/</span><span class="token operator" style="color:#005cc5">/</span><span class="token plain"> A bunch of effect cycle spam</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">[</span><span class="token time number" style="color:#005cc5">00:02:34.781</span><span class="token punctuation">,</span><span class="token number" style="color:#005cc5">188</span><span class="token punctuation">]</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token plain">dbg</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token plain"> fs_nvs</span><span class="token operator" style="color:#005cc5">:</span><span class="token plain"> Erasing flash at fd000</span><span class="token punctuation">,</span><span class="token plain"> len </span><span class="token number" style="color:#005cc5">4096</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token operator" style="color:#005cc5">/</span><span class="token operator" style="color:#005cc5">/</span><span class="token plain"> A bunch more effect cycle spam</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token punctuation">[</span><span class="token time number" style="color:#005cc5">00:06:42.219</span><span class="token punctuation">,</span><span class="token number" style="color:#005cc5">970</span><span class="token punctuation">]</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">&lt;</span><span class="token plain">dbg</span><span class="token operator" style="color:#005cc5">&gt;</span><span class="token plain"> fs_nvs</span><span class="token operator" style="color:#005cc5">:</span><span class="token plain"> Erasing flash at ff000</span><span class="token punctuation">,</span><span class="token plain"> len </span><span class="token number" style="color:#005cc5">4096</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token operator" style="color:#005cc5">/</span><span class="token operator" style="color:#005cc5">/</span><span class="token plain"> A bunch more effect cycle spam</span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token operator" style="color:#005cc5">/</span><span class="token operator" style="color:#005cc5">/</span><span class="token plain"> KABOOM </span><span class="token operator" style="color:#005cc5">-</span><span class="token plain"> bootloader issue</span><br></span></code></pre></div></div>
<p>So at start up, we can see that the 8 sectors of 4KB are found by NVS properly,
however, I wasn't sure what the second and third lines meant, but we'll get back
to that. Nonetheless the next two logs from NVS showed erasing the sector at
<code>0xFD000</code> and then erasing the <code>0xFF000</code> sector.</p>
<p><img decoding="async" loading="lazy" src="https://i.imgur.com/DmLycMJ.png" alt="Erased Sectors" class="img_ev3q"></p>
<p>It's really odd that the third to last sector and the last sector are erased,
and then shortly after the bootloader issue is hit. I really had no explanation
for this behavior.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="reaching-out-to-zephyr">Reaching out to Zephyr<a href="https://zmk.dev/blog/2020/10/03/bootloader-fix#reaching-out-to-zephyr" class="hash-link" aria-label="Direct link to Reaching out to Zephyr" title="Direct link to Reaching out to Zephyr" translate="no">​</a></h3>
<p>At this point, I nor anyone else working on the ZMK project knew enough about
NVS to explain what was going on here. <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">Pete
Johanson</a>, project founder, reached out on the
Zephyr Project's Slack (ZMK is built on top of Zephyr if you weren't aware).
Justin B and Laczen assisted by first explaining that those <code>alloc wra</code> and
<code>data wra</code> logs from earlier are showing what data NVS found at startup.</p>
<p>More specifically, <code>data wra</code> should be <code>0</code> when it first starts up on a clean
flash. As we can see from my earlier logging on a clean flash I was instead
getting <code>f40</code>. NVS is finding data in our settings sectors when they should be
blank! We were then given the advice to double check our bootloader.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-adafruit-nrf52-bootloader">The Adafruit nRF52 Bootloader<a href="https://zmk.dev/blog/2020/10/03/bootloader-fix#the-adafruit-nrf52-bootloader" class="hash-link" aria-label="Direct link to The Adafruit nRF52 Bootloader" title="Direct link to The Adafruit nRF52 Bootloader" translate="no">​</a></h3>
<p>Most of the boards the contributors of ZMK use have the <a href="https://github.com/adafruit/Adafruit_nRF52_Bootloader" target="_blank" rel="noopener noreferrer" class="">Adafruit nRF52
Bootloader</a>, which allows
for extremely easy flashing by dragging and dropping <code>.uf2</code> files onto the board
as a USB drive. Every bootloader takes up a portion of the flash, and in the
README explains that the first <code>0x26000</code> is reserved for the bootloader with the
nRF52840, and we've properly allocated that.</p>
<p>However, there isn't a full explanation of the flash allocation of the
bootloader in the README. There's a possibility that the bootloader is using
part of the same flash area we're using. I reached out on the Adafruit Discord,
and <a href="https://github.com/dhalbert" target="_blank" rel="noopener noreferrer" class="">Dan Halbert</a> pointed me towards the <a href="https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/master/linker/nrf52840.ld" target="_blank" rel="noopener noreferrer" class="">linker
map</a>
of the nRF52840. Let's take a look.</p>
<div class="language-linker-script codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-linker-script codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token function" style="color:#6f42c1">FLASH</span><span class="token plain"> </span><span class="token punctuation">(</span><span class="token plain">rx</span><span class="token punctuation">)</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">:</span><span class="token plain"> ORIGIN </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0xF4000</span><span class="token punctuation">,</span><span class="token plain"> LENGTH </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0xFE000</span><span class="token operator" style="color:#005cc5">-</span><span class="token number" style="color:#005cc5">0xF4000</span><span class="token operator" style="color:#005cc5">-</span><span class="token number" style="color:#005cc5">2048</span><span class="token plain"> </span><span class="token comment" style="color:#6a737d">/* 38 KB */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token function" style="color:#6f42c1">BOOTLOADER_CONFIG</span><span class="token plain"> </span><span class="token punctuation">(</span><span class="token plain">r</span><span class="token punctuation">)</span><span class="token operator" style="color:#005cc5">:</span><span class="token plain"> ORIGIN </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0xFE000</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">-</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">2048</span><span class="token punctuation">,</span><span class="token plain"> LENGTH </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">2048</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d">/** Location of mbr params page in flash. */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token function" style="color:#6f42c1">MBR_PARAMS_PAGE</span><span class="token plain"> </span><span class="token punctuation">(</span><span class="token plain">rw</span><span class="token punctuation">)</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">:</span><span class="token plain"> ORIGIN </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0xFE000</span><span class="token punctuation">,</span><span class="token plain"> LENGTH </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0x1000</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token comment" style="color:#6a737d">/** Location of bootloader setting in flash. */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token function" style="color:#6f42c1">BOOTLOADER_SETTINGS</span><span class="token plain"> </span><span class="token punctuation">(</span><span class="token plain">rw</span><span class="token punctuation">)</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">:</span><span class="token plain"> ORIGIN </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0xFF000</span><span class="token punctuation">,</span><span class="token plain"> LENGTH </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0x1000</span><br></span></code></pre></div></div>
<p>Here's a diagram to show this a bit better.</p>
<p><img decoding="async" loading="lazy" src="https://i.imgur.com/TEOA31m.png" alt="Adafruit Bootloader Diagram" class="img_ev3q"></p>
<p>We've found the issue! As you can see from the red bar (representing our
settings flash area), we've put the settings flash area <em>right on top</em> of the
Adafruit bootloader's flash space. Oops!</p>
<p>This also shines some light on why NVS erased <code>0xFD000</code> and <code>0xFF000</code> sectors.
It's possible there was no flash written to <code>0xFD000</code> because the bootloader
didn't use up all of that space it has, and then there possibly weren't any
bootloader settings set yet, so <code>0xFF000</code> could be used and erased by NVS too.</p>
<p>After erasing <code>0xFF000</code>, NVS probably next erased a rather important part of the
bootloader that resulted in this issue at hand. In my opinion, we're pretty
lucky that it didn't delete an even more vital part of the bootloader. At least
we could still get to it, so that we could re-flash the bootloader easily!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-solution">The solution<a href="https://zmk.dev/blog/2020/10/03/bootloader-fix#the-solution" class="hash-link" aria-label="Direct link to The solution" title="Direct link to The solution" translate="no">​</a></h2>
<p>Now that we've found the issue, we can pretty easily fix this. We'll need to
move the settings flash area back so that it doesn't overlap with the
bootloader. First we calculate the size of the of flash area the bootloader is using.</p>
<div class="language-linker-script codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-linker-script codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token number" style="color:#005cc5">0x100000</span><span class="token plain"> </span><span class="token punctuation">(</span><span class="token plain">end of flash</span><span class="token punctuation">)</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">-</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0x0F4000</span><span class="token plain"> </span><span class="token punctuation">(</span><span class="token plain">start of bootloader</span><span class="token punctuation">)</span><span class="token plain"> </span><span class="token operator" style="color:#005cc5">=</span><span class="token plain"> </span><span class="token number" style="color:#005cc5">0xC000</span><span class="token plain"> </span><span class="token punctuation">(</span><span class="token plain">48KB</span><span class="token punctuation">)</span><br></span></code></pre></div></div>
<p>So the bootloader is using the last 48KB of the flash, this means all we need to
do is shift back the settings area and code space <code>0xC000</code> bytes. We'll apply
this to all of the <code>.dts</code> files for the boards that were affected by this issue.</p>
<div class="language-diff codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#24292e;--prism-background-color:#f9f9f9"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-diff codeBlock_bY9V thin-scrollbar" style="color:#24292e;background-color:#f9f9f9"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#24292e"><span class="token unchanged prefix unchanged"> </span><span class="token unchanged line">       code_partition: partition@26000 {</span><br></span><span class="token-line" style="color:#24292e"><span class="token unchanged line"></span><span class="token deleted-sign deleted prefix deleted" style="color:#b31d28;background-color:#ffeef0">-</span><span class="token deleted-sign deleted line" style="color:#b31d28;background-color:#ffeef0">           reg = &lt;0x00026000 0x000d2000&gt;;</span><br></span><span class="token-line" style="color:#24292e"><span class="token deleted-sign deleted line" style="color:#b31d28;background-color:#ffeef0"></span><span class="token inserted-sign inserted prefix inserted" style="color:#22863a;background-color:#f0fff4">+</span><span class="token inserted-sign inserted line" style="color:#22863a;background-color:#f0fff4">           reg = &lt;0x00026000 0x000c6000&gt;;</span><br></span><span class="token-line" style="color:#24292e"><span class="token inserted-sign inserted line" style="color:#22863a;background-color:#f0fff4"></span><span class="token unchanged prefix unchanged"> </span><span class="token unchanged line">       };</span><br></span><span class="token-line" style="color:#24292e"><span class="token unchanged line"></span><span class="token plain"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#24292e"><span class="token plain"></span><span class="token deleted-sign deleted prefix deleted" style="color:#b31d28;background-color:#ffeef0">-</span><span class="token deleted-sign deleted line" style="color:#b31d28;background-color:#ffeef0">       storage_partition: partition@f8000 {</span><br></span><span class="token-line" style="color:#24292e"><span class="token deleted-sign deleted line" style="color:#b31d28;background-color:#ffeef0"></span><span class="token inserted-sign inserted prefix inserted" style="color:#22863a;background-color:#f0fff4">+</span><span class="token inserted-sign inserted line" style="color:#22863a;background-color:#f0fff4">       storage_partition: partition@ec000 {</span><br></span><span class="token-line" style="color:#24292e"><span class="token inserted-sign inserted line" style="color:#22863a;background-color:#f0fff4"></span><span class="token deleted-sign deleted prefix deleted" style="color:#b31d28;background-color:#ffeef0">-</span><span class="token deleted-sign deleted line" style="color:#b31d28;background-color:#ffeef0">           reg = &lt;0x000f8000 0x00008000&gt;;</span><br></span><span class="token-line" style="color:#24292e"><span class="token deleted-sign deleted line" style="color:#b31d28;background-color:#ffeef0"></span><span class="token inserted-sign inserted prefix inserted" style="color:#22863a;background-color:#f0fff4">+</span><span class="token inserted-sign inserted line" style="color:#22863a;background-color:#f0fff4">           reg = &lt;0x000ec000 0x00008000&gt;;</span><br></span><span class="token-line" style="color:#24292e"><span class="token inserted-sign inserted line" style="color:#22863a;background-color:#f0fff4"></span><span class="token unchanged prefix unchanged"> </span><span class="token unchanged line">       };</span><br></span></code></pre></div></div>
<p>And with those changes, we should no longer run into this issue! In the process
of these changes, we lost 48KB of space for application code, but we're only
using around 20% of it anyways. 🎉</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="article-updates">Article Updates<a href="https://zmk.dev/blog/2020/10/03/bootloader-fix#article-updates" class="hash-link" aria-label="Direct link to Article Updates" title="Direct link to Article Updates" translate="no">​</a></h2>
<ul>
<li class="">12/2023: Removed the deprecated <code>label</code> property from code snippets.</li>
</ul>]]></content:encoded>
            <category>bootloader</category>
            <category>keyboards</category>
            <category>firmware</category>
            <category>oss</category>
            <category>ble</category>
        </item>
        <item>
            <title><![CDATA[ZMK State Of The Firmware #2]]></title>
            <link>https://zmk.dev/blog/2020/09/21/zmk-sotf-2</link>
            <guid>https://zmk.dev/blog/2020/09/21/zmk-sotf-2</guid>
            <pubDate>Mon, 21 Sep 2020 00:00:00 GMT</pubDate>
            <description><![CDATA[Welcome to the second ZMK "State Of The Firmware" (SOTF)!]]></description>
            <content:encoded><![CDATA[<p>Welcome to the second ZMK "State Of The Firmware" (SOTF)!</p>
<p>This update will cover all the major activity since <a class="" href="https://zmk.dev/blog/2020/08/12/zmk-sotf-1">SOTF #1</a>, preparations for the upcoming
Hacktoberfest activity, and a current open call for community feedback on a ZMK mascot.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="recent-activity">Recent Activity<a href="https://zmk.dev/blog/2020/09/21/zmk-sotf-2#recent-activity" class="hash-link" aria-label="Direct link to Recent Activity" title="Direct link to Recent Activity" translate="no">​</a></h2>
<p>So much going on in ZMK!</p>
<ul>
<li class="">Added a new generic <a href="https://zmk.dev/docs/behaviors/hold-tap" target="_blank" rel="noopener noreferrer" class="">Hold Tap behavior</a>
in <a href="https://github.com/zmkfirmware/zmk/pull/146" target="_blank" rel="noopener noreferrer" class="">#146</a> which now powers mod-tap, layer-tap, etc. - <a href="https://github.com/okke-formsma" target="_blank" rel="noopener noreferrer" class="">okke-formsma</a></li>
<li class=""><a href="https://zmk.dev/docs/behaviors/bluetooth" target="_blank" rel="noopener noreferrer" class="">BLE profile/connection management</a>
in <a href="https://github.com/zmkfirmware/zmk/pull/133" target="_blank" rel="noopener noreferrer" class="">#133</a> - <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a></li>
<li class="">Integration tests were added to automate testing of behaviors in <a href="https://github.com/zmkfirmware/zmk/pull/131" target="_blank" rel="noopener noreferrer" class="">#131</a> by <a href="https://github.com/BrainWart" target="_blank" rel="noopener noreferrer" class="">BrainWart</a> &amp; <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a></li>
<li class=""><a href="https://zmk.dev/docs/behaviors/layers#toggle-layer" target="_blank" rel="noopener noreferrer" class="">Toggle layer behavior</a>, e.g. <code>&amp;tog LOWER</code>, in
<a href="https://github.com/zmkfirmware/zmk/pull/98" target="_blank" rel="noopener noreferrer" class="">#98</a> - <a href="https://github.com/BrainWart" target="_blank" rel="noopener noreferrer" class="">BrainWart</a></li>
<li class="">Key fix for dropped press/release over HID <a href="https://github.com/zmkfirmware/zmk/pull/93" target="_blank" rel="noopener noreferrer" class="">#93</a>/<a href="https://github.com/zmkfirmware/zmk/pull/96" target="_blank" rel="noopener noreferrer" class="">#96</a> - <a href="https://github.com/careyk007" target="_blank" rel="noopener noreferrer" class="">careyk007</a> &amp; <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a></li>
<li class="">Code formatting standardized using <code>clang-format</code> in <a href="https://github.com/zmkfirmware/zmk/pull/183" target="_blank" rel="noopener noreferrer" class="">#183</a> - <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a></li>
<li class=""><a href="https://zmk.dev/docs/behaviors/reset#bootloader-reset" target="_blank" rel="noopener noreferrer" class="">Bootloader reset behavior</a>, e.g. <code>&amp;bootloader</code>, in <a href="https://github.com/zmkfirmware/zmk/pull/116" target="_blank" rel="noopener noreferrer" class="">#116</a> - <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a></li>
<li class="">Various bug fixes and documentation</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-shields">New Shields<a href="https://zmk.dev/blog/2020/09/21/zmk-sotf-2#new-shields" class="hash-link" aria-label="Direct link to New Shields" title="Direct link to New Shields" translate="no">​</a></h2>
<ul>
<li class="">QAZ in <a href="https://github.com/zmkfirmware/zmk/pull/130" target="_blank" rel="noopener noreferrer" class="">#130</a> - <a href="https://github.com/tominabox1" target="_blank" rel="noopener noreferrer" class="">tominabox1</a></li>
<li class="">Iris in <a href="https://github.com/zmkfirmware/zmk/pull/151" target="_blank" rel="noopener noreferrer" class="">#151</a> - <a href="https://github.com/kurtis-lew" target="_blank" rel="noopener noreferrer" class="">kurtis-lew</a></li>
<li class="">RoMac 2.1 in <a href="https://github.com/zmkfirmware/zmk/pull/122" target="_blank" rel="noopener noreferrer" class="">#122</a> - <a href="https://github.com/bmcgavin" target="_blank" rel="noopener noreferrer" class="">bmcgavin</a></li>
<li class="">Sofle in <a href="https://github.com/zmkfirmware/zmk/pull/118" target="_blank" rel="noopener noreferrer" class="">#118</a> - <a href="https://github.com/CrossR" target="_blank" rel="noopener noreferrer" class="">CrossR</a></li>
<li class="">splitreus62 in <a href="https://github.com/zmkfirmware/zmk/pull/92" target="_blank" rel="noopener noreferrer" class="">#92</a> - <a href="https://github.com/Na-Cly" target="_blank" rel="noopener noreferrer" class="">Na-Cly</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="new-boards">New Boards<a href="https://zmk.dev/blog/2020/09/21/zmk-sotf-2#new-boards" class="hash-link" aria-label="Direct link to New Boards" title="Direct link to New Boards" translate="no">​</a></h2>
<ul>
<li class="">DZ60RGB rev1 in <a href="https://github.com/zmkfirmware/zmk/pull/166" target="_blank" rel="noopener noreferrer" class="">#166</a> - <a href="https://github.com/Nicell" target="_blank" rel="noopener noreferrer" class="">Nicell</a></li>
<li class="">nrfMicro in <a href="https://github.com/zmkfirmware/zmk/pull/101" target="_blank" rel="noopener noreferrer" class="">#101</a> - <a href="https://github.com/okke-formsma" target="_blank" rel="noopener noreferrer" class="">okke-formsma</a></li>
<li class="">BlueMicro840 <a href="https://github.com/zmkfirmware/zmk/pull/91" target="_blank" rel="noopener noreferrer" class="">#91</a> - <a href="https://github.com/Na-Cly" target="_blank" rel="noopener noreferrer" class="">Na-Cly</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="hacktoberfest-preparation">Hacktoberfest Preparation<a href="https://zmk.dev/blog/2020/09/21/zmk-sotf-2#hacktoberfest-preparation" class="hash-link" aria-label="Direct link to Hacktoberfest Preparation" title="Direct link to Hacktoberfest Preparation" translate="no">​</a></h2>
<p><a href="https://hacktoberfest.digitalocean.com/" target="_blank" rel="noopener noreferrer" class="">Hacktoberfest</a> is a yearly celebration of open source,
which encourages participation in OSS, especially from new contributors.</p>
<p>The ZMK contributors have been busy preparing for folks to join in on the fun by contributing to
ZMK!</p>
<ul>
<li class="">There is now a basic <a href="https://github.com/zmkfirmware/zmk/blob/main/CONTRIBUTING.md" target="_blank" rel="noopener noreferrer" class="">Contributing Guide</a> to help newcomers get oriented, and get up to speed.</li>
<li class="">The <a href="https://github.com/zmkfirmware/zmk/issues?q=is%3Aissue+is%3Aopen+label%3AHacktoberfest" target="_blank" rel="noopener noreferrer" class=""><code>Hacktoberfest</code></a>
issue label will help participants discover good issues to work on.
(The existing <a href="https://github.com/zmkfirmware/zmk/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22" target="_blank" rel="noopener noreferrer" class=""><code>good first issue</code></a> label also helps with this)</li>
</ul>
<p>We're looking forward to the launch of Hacktoberfest!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="mascot-selection-feedback">Mascot Selection Feedback<a href="https://zmk.dev/blog/2020/09/21/zmk-sotf-2#mascot-selection-feedback" class="hash-link" aria-label="Direct link to Mascot Selection Feedback" title="Direct link to Mascot Selection Feedback" translate="no">​</a></h2>
<p>The ZMK project would like to settle on a mascot! We're soliciting community feedback as part of
the process before a final mascot is selected.</p>
<p>The current mascots up for consideration are:</p>
<ul>
<li class="">Griffin</li>
<li class="">Peregrine Falcon</li>
<li class="">Zapata Wren</li>
<li class="">Zorro (south american fox)</li>
</ul>
<p>If you're interested in helping with the decision, head over to <a href="https://github.com/zmkfirmware/zmk/issues/195" target="_blank" rel="noopener noreferrer" class="">Issue #195</a> and add a reaction!</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="coming-soon">Coming Soon!<a href="https://zmk.dev/blog/2020/09/21/zmk-sotf-2#coming-soon" class="hash-link" aria-label="Direct link to Coming Soon!" title="Direct link to Coming Soon!" translate="no">​</a></h2>
<p>There still lots of activity in ZMK, and plenty of exciting upcoming changes.</p>
<ul>
<li class="">Improved modifier infrastructure, including "shifted keycodes" - <a href="https://github.com/okke-formsma" target="_blank" rel="noopener noreferrer" class="">okke-formsma</a></li>
<li class="">Battery percentage reporting over BLE - <a href="https://github.com/Nicell" target="_blank" rel="noopener noreferrer" class="">Nicell</a></li>
<li class="">Complete defines for HID keycodes/usage IDs - <a href="https://github.com/innovaker" target="_blank" rel="noopener noreferrer" class="">innovaker</a></li>
<li class="">Additional core BLE connection/bond management work - <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a></li>
<li class="">Improved power management - <a href="https://github.com/petejohanson" target="_blank" rel="noopener noreferrer" class="">petejohanson</a>, <a href="https://github.com/Nicell" target="_blank" rel="noopener noreferrer" class="">Nicell</a></li>
<li class="">One shot mod/layer behaviors - <a href="https://github.com/okke-formsma" target="_blank" rel="noopener noreferrer" class="">okke-formsma</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="statistics">Statistics<a href="https://zmk.dev/blog/2020/09/21/zmk-sotf-2#statistics" class="hash-link" aria-label="Direct link to Statistics" title="Direct link to Statistics" translate="no">​</a></h2>
<p>Some statistics of interest for ZMK:</p>
<ul>
<li class="">GitHub
<ul>
<li class="">115 Closed PRs</li>
<li class="">64 Stars</li>
<li class="">48 Forks</li>
</ul>
</li>
<li class="">Discord Chat
<ul>
<li class="">186 total registered</li>
</ul>
</li>
<li class="">Website (last 30 days)
<ul>
<li class="">7.4K page views</li>
<li class="">474 new users</li>
</ul>
</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="thanks">Thanks!<a href="https://zmk.dev/blog/2020/09/21/zmk-sotf-2#thanks" class="hash-link" aria-label="Direct link to Thanks!" title="Direct link to Thanks!" translate="no">​</a></h2>
<p>Thanks again to the numerous contributors and users who have made working on ZMK such a pleasure!</p>]]></content:encoded>
            <category>SOTF</category>
            <category>keyboards</category>
            <category>firmware</category>
            <category>oss</category>
            <category>ble</category>
        </item>
    </channel>
</rss>