forked from kofal.net/zmk
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:
225
docs/docs/config/layout.md
Normal file
225
docs/docs/config/layout.md
Normal 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 | |
|
||||
Reference in New Issue
Block a user