zmkfirmware / zmk

ZMK Firmware Repository
https://zmk.dev/
MIT License
2.48k stars 2.56k forks source link

Feature: Add physical layout support #2283

Closed petejohanson closed 4 days ago

petejohanson commented 2 months ago

This feature enhancement adds support for "physical layouts" that describe a given keyboard layout. Example uses cases for multiple physical layouts include:

To make avoid code duplication, under the hood we are still using a "synthetic physical layout" when none are explicitly specified, using the chosen matrix transform and kscan nodes to set up a single physical layout that is then used.

A Physical Layout includes:

Selecting a physical layout will do the necessary setup for the layout's kscan instance, and when processing kscan events, use the associated matrix transform to map that kscan event to a key position.

The code here also has some tweaks to calculate the ZMK_KEYMAP_LEN, aka the maximum key position index, based on the longest transform available from all the physical layouts defined, which we will use down the road in the ZMK Studio work to ensure we have enough pre-allocated locations for keymaps the user sets up after picking a layout.

Not yet implemented, to come as follow up work:

petejohanson commented 2 months ago

Ok, I've pushed some minor cleanups and fixes, as well as an implementation of this for ZMK Uno to show how this works. Tested working for the ZMK Uno split as well.

caksoylar commented 1 month ago

In case anyone wants to test the physical layout, here is a helper script to convert from QMK-style info.json files or ortho-like specs to a devicetree snippet for keys property, based on https://github.com/caksoylar/keymap-drawer: https://gist.github.com/caksoylar/1f6809446ab2415d4116882ed1c60db2#file-physical_layout_to_dt-py

❯ python physical_layout_to_dt.py -k corne_rotated -l LAYOUT_split_3x5_3

keys  //                     w   h    x    y     rot   rx   ry
    = <&key_physical_attrs 100 100    0   37       0    0    0>
    , <&key_physical_attrs 100 100  100   12       0    0    0>
    , <&key_physical_attrs 100 100  200    0       0    0    0>
    , <&key_physical_attrs 100 100  300   12       0    0    0>
    , <&key_physical_attrs 100 100  400   25       0    0    0>
    , <&key_physical_attrs 100 100  800   25       0    0    0>
    , <&key_physical_attrs 100 100  900   12       0    0    0>
    , <&key_physical_attrs 100 100 1000    0       0    0    0>
    , <&key_physical_attrs 100 100 1100   12       0    0    0>
    , <&key_physical_attrs 100 100 1200   37       0    0    0>
    , <&key_physical_attrs 100 100    0  137       0    0    0>
    , <&key_physical_attrs 100 100  100  112       0    0    0>
    , <&key_physical_attrs 100 100  200  100       0    0    0>
    , <&key_physical_attrs 100 100  300  112       0    0    0>
    , <&key_physical_attrs 100 100  400  125       0    0    0>
    , <&key_physical_attrs 100 100  800  125       0    0    0>
    , <&key_physical_attrs 100 100  900  112       0    0    0>
    , <&key_physical_attrs 100 100 1000  100       0    0    0>
    , <&key_physical_attrs 100 100 1100  112       0    0    0>
    , <&key_physical_attrs 100 100 1200  137       0    0    0>
    , <&key_physical_attrs 100 100    0  237       0    0    0>
    , <&key_physical_attrs 100 100  100  212       0    0    0>
    , <&key_physical_attrs 100 100  200  200       0    0    0>
    , <&key_physical_attrs 100 100  300  212       0    0    0>
    , <&key_physical_attrs 100 100  400  225       0    0    0>
    , <&key_physical_attrs 100 100  800  225       0    0    0>
    , <&key_physical_attrs 100 100  900  212       0    0    0>
    , <&key_physical_attrs 100 100 1000  200       0    0    0>
    , <&key_physical_attrs 100 100 1100  212       0    0    0>
    , <&key_physical_attrs 100 100 1200  237       0    0    0>
    , <&key_physical_attrs 100 100  250  315       0    0    0>
    , <&key_physical_attrs 100 100  360  330    1500  409  380>
    , <&key_physical_attrs 100 150  476  325    3000  527  400>
    , <&key_physical_attrs 100 150  723  325 (-3000)  773  400>
    , <&key_physical_attrs 100 100  840  330 (-1500)  890  380>
    , <&key_physical_attrs 100 100  950  315       0    0    0>
    ;