docs: Physical layout docs improvements (#2533)

* docs: Added layout configuration reference page
* docs: Refactored and revamped physical layout creation information
* docs: Added note in studio features page
* docs: added studio_unlock note in features section
---------

Co-authored-by: Cem Aksoylar <caksoylar@users.noreply.github.com>
Co-authored-by: Joel Spadin <joelspadin@gmail.com>
Co-authored-by: Peter Johanson <peter@peterjohanson.com>
This commit is contained in:
Nicolas Munnich
2024-10-12 21:25:45 +02:00
committed by GitHub
parent d3f2895744
commit a72327bdff
9 changed files with 882 additions and 342 deletions

225
docs/docs/config/layout.md Normal file
View File

@@ -0,0 +1,225 @@
---
title: Layout Configuration
sidebar_label: Layout
---
See [Configuration Overview](index.md) for instructions on how to change these settings.
## Matrix Transform
Defines a mapping from keymap logical positions to physical [kscan](./kscan.md) positions.
You can define multiple matrix transform nodes, one for each layout, and users can select which one they want from the `/chosen` node in their keymaps.
See the [new shield guide](../development/hardware-integration/new-shield.mdx#matrix-transform) for more documentation on how to define a matrix transform.
### Devicetree
Applies to: `compatible = "zmk,matrix-transform"`
Definition file: [zmk/app/dts/bindings/zmk,matrix-transform.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/zmk%2Cmatrix-transform.yaml)
| Property | Type | Description | Default |
| ------------ | ----- | --------------------------------------------------------------------- | ------- |
| `rows` | int | Number of rows in the transformed matrix | |
| `columns` | int | Number of columns in the transformed matrix | |
| `row-offset` | int | Adds an offset to all rows before looking them up in the transform | 0 |
| `col-offset` | int | Adds an offset to all columns before looking them up in the transform | 0 |
| `map` | array | A list of position transforms | |
The `map` array should be defined using the `RC()` macro from [dt-bindings/zmk/matrix_transform.h](https://github.com/zmkfirmware/zmk/blob/main/app/include/dt-bindings/zmk/matrix_transform.h). It should have one item per logical position in the keymap. Each item should list the physical row and column that should trigger the key in that position.
### Example: Skipping Unused Positions
Any keyboard which is not a grid of 1 unit keys will likely have some unused positions in the matrix. A matrix transform can be used to skip the unused positions so users don't have to set them to `&none` in keymaps.
```dts
// numpad.overlay
/ {
chosen {
zmk,kscan = &kscan0;
zmk,matrix-transform = &default_transform;
};
kscan0: kscan {
compatible = "zmk,kscan-gpio-matrix";
// define row-gpios with 5 elements and col-gpios with 4...
};
default_transform: matrix_transform {
compatible = "zmk,matrix-transform";
rows = <5>;
columns = <4>;
// ┌───┬───┬───┬───┐
// │NUM│ / │ * │ - │
// ├───┼───┼───┼───┤
// │ 7 │ 8 │ 9 │ + │
// ├───┼───┼───┤ │
// │ 4 │ 5 │ 6 │ │
// ├───┼───┼───┼───┤
// │ 1 │ 2 │ 3 │RET│
// ├───┴───┼───┤ │
// │ 0 │ . │ │
// └───────┴───┴───┘
map = <
RC(0,0) RC(0,1) RC(0,2) RC(0,3)
RC(1,0) RC(1,1) RC(1,2) RC(1,3)
RC(2,0) RC(2,1) RC(2,2)
RC(3,0) RC(3,1) RC(3,2) RC(3,3)
RC(4,0) RC(4,1)
>;
};
};
```
```dts
// numpad.keymap
/ {
keymap {
compatible = "zmk,keymap";
default {
bindings = <
&kp KP_NUM &kp KP_DIV &kp KP_MULT &kp KP_MINUS
&kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_PLUS
&kp KP_N4 &kp KP_N5 &kp KP_N6
&kp KP_N1 &kp KP_N2 &kp KP_N3 &kp KP_ENTER
&kp KP_N0 &kp KP_DOT
>;
};
}
};
```
### Example: Non-standard Matrix
Consider a keyboard with a [duplex matrix](https://wiki.ai03.com/books/pcb-design/page/matrices-and-duplex-matrix), where the matrix has twice as many rows and half as many columns as the keyboard has keys. A matrix transform can be used to correct for this so that keymaps can match the layout of the keys, not the layout of the matrix.
```dts
/ {
chosen {
zmk,kscan = &kscan0;
zmk,matrix-transform = &default_transform;
};
kscan0: kscan {
compatible = "zmk,kscan-gpio-matrix";
// define row-gpios with 12 elements and col-gpios with 8...
};
default_transform: matrix_transform {
compatible = "zmk,matrix-transform";
rows = <6>;
columns = <16>;
// ESC F1 F2 F3 ...
// ` 1 2 3 ...
// Tab Q W E ...
// Caps A S D ...
// Shift Z X C ...
// Ctrl Alt ...
map = <
RC(0,0) RC(1,0) RC(0,1) RC(1,1) // ...
RC(2,0) RC(3,0) RC(2,1) RC(3,1) // ...
RC(4,0) RC(5,0) RC(4,1) RC(5,1) // ...
RC(6,0) RC(7,0) RC(6,1) RC(7,1) // ...
RC(8,0) RC(9,0) RC(8,1) RC(9,1) // ...
RC(10,0) RC(11,0) // ...
>;
};
};
```
### Example: Charlieplex
Since a charlieplex driver will never align with a keyboard directly due to the un-addressable positions, a matrix transform should be used to map the pairs to the layout of the keys.
Note that the entire addressable space does not need to be mapped.
```devicetree
/ {
chosen {
zmk,kscan = &kscan0;
zmk,matrix-transform = &default_transform;
};
kscan0: kscan {
compatible = "zmk,kscan-gpio-charlieplex";
wakeup-source;
interrupt-gpios = <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN) >;
gpios
= <&pro_micro 16 GPIO_ACTIVE_HIGH>
, <&pro_micro 17 GPIO_ACTIVE_HIGH>
, <&pro_micro 18 GPIO_ACTIVE_HIGH>
, <&pro_micro 19 GPIO_ACTIVE_HIGH>
, <&pro_micro 20 GPIO_ACTIVE_HIGH>
; // addressable space is 5x5, (minus paired values)
};
default_transform: matrix_transform {
compatible = "zmk,matrix-transform";
rows = <3>;
columns = <5>;
// Q W E R
// A S D F
// Z X C V
map = <
RC(0,1) RC(0,2) RC(0,3) RC(0,4)
RC(1,0) RC(1,2) RC(1,3) RC(1,4)
RC(2,0) RC(2,1) RC(2,3) RC(2,4)
>;
};
};
```
## Physical Layout
Defines a keyboard layout by joining together a [matrix transform](#matrix-transform), a [keyboard scan](./kscan.md), and a list of physical key properties.
Multiple physical layouts can be defined for keyboards with multiple physical key layouts.
Read through the [page on physical layouts](../development/hardware-integration/physical-layouts.md) for more information.
### Devicetree
Applies to: `compatible = zmk,physical-layout`
Definition file: [zmk/app/dts/bindings/zmk,physical-layout.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/zmk%2Cphysical-layout.yaml)
| Property | Type | Description | Default |
| -------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------- | ------- |
| `display-name` | string | The name of this layout, for display purposes | |
| `transform` | phandle | The matrix transform to use along with this layout | |
| `kscan` | phandle | The kscan to use along with this layout. The `zmk,kscan` chosen will be used as a fallback if this property is omitted | |
| `keys` | phandle-array | Array of key physical attributes. | |
Each element of the `keys` array has the shape `<&key_physical_attrs w h x y r rx ry>`, with the following properties:
| Property | Type | Description | Unit |
| ---------- | -------- | ------------------------------------ | ------------------------------------------------------- |
| Width | int (>0) | Key(cap) width | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" |
| Height | int (>0) | Key(cap) height | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" |
| X | uint | Key X position (top-left point) | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" |
| Y | uint | Key Y position (top-left point) | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" |
| Rotation | int | Key rotation (positive => clockwise) | [centi-](https://en.wikipedia.org/wiki/Centi-)degree |
| Rotation X | int | Rotation origin X position | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" |
| Rotation Y | int | Rotation origin Y position | [centi-](https://en.wikipedia.org/wiki/Centi-)"keyunit" |
The `key_physical_attrs` node is defined in [`dts/physical_layouts.dtsi`](https://github.com/zmkfirmware/zmk/blob/main/app/dts/physical_layouts.dtsi) and is mandatory.
## Physical Layout Position Map
Defines a mapping between [physical layouts](#physical-layout), allowing key mappings to be preserved in the same locations as previously when using [ZMK Studio](../features/studio.md). Read through the [page on physical layouts](../development/hardware-integration/physical-layouts.md) for more information.
### Devicetree
Applies to: `compatible = zmk,physical-layout-position-map`
Definition file: [zmk/app/dts/bindings/zmk,physical-layout-position-map.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/zmk%2Cphysical-layout-position-map.yaml)
| Property | Type | Description | Default |
| ---------- | ------- | ------------------------------------------------------------------------------------------------ | ------- |
| `complete` | boolean | If the mapping complete describes the key mapping, and no position based mapping should be used. | |
The `zmk,physical-layout-position-map` node should have one child node per physical layout. Each child node should have the following properties:
| Property | Type | Description | Default |
| ----------------- | ------- | --------------------------------------------------------------------------------- | ------- |
| `physical-layout` | phandle | The physical layout that corresponds to this mapping entry | |
| `positions` | array | Array of key positions that match the same array entry in the other sibling nodes | |