Merge pull request #257 from kurtis-lew/issue138

Adressing Issue #181 - Split Keyboard Documentation
This commit is contained in:
Pete Johanson 2020-10-13 00:04:12 -04:00 committed by GitHub
commit 47cfcb42d2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -21,6 +21,10 @@ The high level steps are:
It may be helpful to review the upstream [shields documentation](https://docs.zephyrproject.org/2.3.0/guides/porting/shields.html#shields) to get a proper understanding of the underlying system before continuing. It may be helpful to review the upstream [shields documentation](https://docs.zephyrproject.org/2.3.0/guides/porting/shields.html#shields) to get a proper understanding of the underlying system before continuing.
:::note
ZMK support for split keyboards requires a few more files than single boards to ensure proper connectivity between the central and peripheral units. Check the following guides thoroughly to ensure that all the files are in place.
:::
## New Shield Directory ## New Shield Directory
Shields for Zephyr applications go into the `boards/shields/` directory; since ZMK's Zephyr application lives in the `app/` subdirectory of the repository, that means the new shield directory should be: Shields for Zephyr applications go into the `boards/shields/` directory; since ZMK's Zephyr application lives in the `app/` subdirectory of the repository, that means the new shield directory should be:
@ -45,6 +49,16 @@ config SHIELD_MY_BOARD
This will make sure the new configuration `SHIELD_MY_BOARD` is set to true whenever `my_board` is added as a shield in your build. This will make sure the new configuration `SHIELD_MY_BOARD` is set to true whenever `my_board` is added as a shield in your build.
**For split boards**, you will need to add configurations for the left and right sides.
```
config SHIELD_MY_BOARD_LEFT
def_bool $(shields_list_contains,my_board_left)
config SHIELD_MY_BOARD_RIGHT
def_bool $(shields_list_contains,my_board_right)
```
### Kconfig.defconfig ### Kconfig.defconfig
The `Kconfig.defconfig` file is where overrides for various configuration settings The `Kconfig.defconfig` file is where overrides for various configuration settings
@ -63,12 +77,41 @@ config ZMK_KEYBOARD_NAME
endif endif
``` ```
## Shield Overlay
Similarly to defining the halves of a split board in `Kconfig.shield` it is important to set the `ZMK_KEYBOARD_NAME` for each half of a split keyboard.
```
if SHIELD_MY_BOARD_LEFT
config ZMK_KEYBOARD_NAME
default "My Awesome Keyboard Left"
endif
if SHIELD_MY_BOARD_RIGHT
config ZMK_KEYBOARD_NAME
default "My Awesome Keyboard Right"
endif
```
## Shield Overlays
![Labelled Pro Micro pins](assets/pro-micro/pro-micro-pins-labelled.jpg) ![Labelled Pro Micro pins](assets/pro-micro/pro-micro-pins-labelled.jpg)
ZMK uses the green color coded pin names to generate devicetree node references. For example, to refer to the node `D0` in the devicetree files, use `&pro_micro_d 0` or to refer to `A1`, use `&pro_micro_a 1`. ZMK uses the green color coded pin names to generate devicetree node references. For example, to refer to the node `D0` in the devicetree files, use `&pro_micro_d 0` or to refer to `A1`, use `&pro_micro_a 1`.
<Tabs
defaultValue="unibody"
values={[
{label: 'Unibody Shields', value: 'unibody'},
{label: 'Split Shields', value: 'split'},
]}>
<TabItem value="unibody">
The `<shield_name>.overlay` is the devicetree description of the keyboard shield that is merged with the primary board devicetree description before the build. For ZMK, this file at a minimum should include the [chosen]() node named `zmk,kscan` that references a KSCAN driver instance. For a simple 3x3 macropad matrix, The `<shield_name>.overlay` is the devicetree description of the keyboard shield that is merged with the primary board devicetree description before the build. For ZMK, this file at a minimum should include the [chosen]() node named `zmk,kscan` that references a KSCAN driver instance. For a simple 3x3 macropad matrix,
this might look something like: this might look something like:
@ -98,6 +141,146 @@ this might look something like:
}; };
``` ```
</TabItem>
<TabItem value="split">
### .dtsi files and Shield Overlays (Split Shields)
Unlike unibody keyboards, split keyboards have a core .dtsi file with shield overlays for each half of the keyboard.
It is preferred to define only the `col-gpios` or `row-gpios` in the common shield .dtsi, depending on the `diode-direction` value.
For `col2row` directed boards like the iris, the shared .dtsi file may look like this:
```
#include <dt-bindings/zmk/matrix-transform.h>
/ {
chosen {
zmk,kscan = &kscan0;
zmk,matrix_transform = &default_transform;
};
default_transform: keymap_transform_0 {
compatible = "zmk,matrix-transform";
columns = <16>;
rows = <4>;
// | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 | | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 |
// | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 | | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 |
// | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 | | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 |
// | SW24 | SW23 | SW22 | SW21 | SW20 | SW19 | SW25 | | SW25 | SW19 | SW20 | SW21 | SW22 | SW23 | SW24 |
// | SW29 | SW28 | SW27 | SW26 | | SW26 | SW27 | SW28 | SW29 |
map = <
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10) RC(0,11)
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10) RC(1,11)
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11)
RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(4,2) RC(4,9) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11)
RC(4,3) RC(4,4) RC(4,5) RC(4,6) RC(4,7) RC(4,8)
>;
};
kscan0: kscan {
compatible = "zmk,kscan-gpio-matrix";
label = "KSCAN";
diode-direction = "col2row";
row-gpios
= <&pro_micro_d 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // Row A from the schematic file
, <&pro_micro_d 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // Row B from the schematic file
, <&pro_micro_d 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // Row C from the schematic file
, <&pro_micro_d 0 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // Row D from the schematic file
, <&pro_micro_d 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> // Row E from the schematic file
;
};
```
:::note
Notice that in addition to the common `row-gpios` that are declared in the kscan, the [matrix transform](#optional-matrix-transform) is defined in the .dtsi.
:::
The missing `col-gpios` would be defined in your `<boardname>_left.overlay` and `<boardname>_right.overlay` files.
Keep in mind that the mirrored position of the GPIOs means that the `col-gpios` will appear reversed when the .overlay files are compared to one another.
Furthermore, the column offset for the [matrix transform](#optional-matrix-transform) should be added to the right half of the keyboard's overlay
because the keyboard's switch matrix is read from left to right, top to bottom.
This is exemplified with the iris .overlay files.
```
// iris_left.overlay
#include "iris.dtsi" // Notice that the main dtsi files are included in the overlay.
&kscan0 {
col-gpios
= <&pro_micro_a 1 GPIO_ACTIVE_HIGH> // col1 in the schematic
, <&pro_micro_a 0 GPIO_ACTIVE_HIGH> // col2 in the schematic
, <&pro_micro_d 15 GPIO_ACTIVE_HIGH> // col3 in the schematic
, <&pro_micro_d 14 GPIO_ACTIVE_HIGH> // col4 in the schematic
, <&pro_micro_d 16 GPIO_ACTIVE_HIGH> // col5 in the schematic
, <&pro_micro_d 10 GPIO_ACTIVE_HIGH> // col6 in the schematic
;
};
```
```
// iris_right.overlay
#include "iris.dtsi"
&default_transform { // The matrix transform for this board is 6 columns over because the left half is 6 columns wide according to the matrix.
col-offset = <6>;
};
&kscan0 {
col-gpios
= <&pro_micro_d 10 GPIO_ACTIVE_HIGH> // col6 in the schematic
, <&pro_micro_d 16 GPIO_ACTIVE_HIGH> // col5 in the schematic
, <&pro_micro_d 14 GPIO_ACTIVE_HIGH> // col4 in the schematic
, <&pro_micro_d 15 GPIO_ACTIVE_HIGH> // col3 in the schematic
, <&pro_micro_a 0 GPIO_ACTIVE_HIGH> // col2 in the schematic
, <&pro_micro_a 1 GPIO_ACTIVE_HIGH> // col1 in the schematic
;
};
```
### .conf files (Split Shields)
While unibody boards only have one .conf file that applies configuration characteristics to the entire keyboard,
split keyboards are unique in that they contain multiple .conf files with different scopes.
For example, a split board called `my_awesome_split_board` would have the following files:
* `my_awesome_split_board.conf` - Configuration elements affect both halves
* `my_awesome_split_board_left.conf` - Configuration elements only affect left half
* `my_awesome_split_board_right.conf` - Configuration elements only affect right half
For proper communication between keyboard halves and that between the central half and the computer,
the **the central and peripheral halves of the keyboard must be defined**. This can be seen below.
```
// Central Half (Usually the left side: my_awesome_split_board_left.conf)
CONFIG_ZMK_SPLIT=y
CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL=y
```
```
// Peripheral Half (Usually the right side: my_awesome_split_board_right.conf)
CONFIG_ZMK_SPLIT=y
CONFIG_ZMK_SPLIT_BLE_ROLE_Peripheral=y
```
Using the .conf file that affects both halves of a split board would be for adding features like deep-sleep or rotary encoders.
```
// my_awesome_split_board.conf
CONFIG_ZMK_SLEEP=y
```
</TabItem>
</Tabs>
## (Optional) Matrix Transform ## (Optional) Matrix Transform
Internally ZMK translates all row/column events into "key position" events to maintain a consistent model that works no matter what any possible GPIO matrix may look like for a certain keyboard. This is particularly helpful when: Internally ZMK translates all row/column events into "key position" events to maintain a consistent model that works no matter what any possible GPIO matrix may look like for a certain keyboard. This is particularly helpful when:
@ -238,6 +421,7 @@ If building locally for split boards, you may need to add these lines to the spe
<TabItem value = "dtsi"> <TabItem value = "dtsi">
In your device tree file you will need to add the following lines to define the encoder sensor: In your device tree file you will need to add the following lines to define the encoder sensor:
``` ```
left_encoder: encoder_left { left_encoder: encoder_left {
compatible = "alps,ec11"; compatible = "alps,ec11";
@ -247,7 +431,6 @@ left_encoder: encoder_left {
resolution = <4>; resolution = <4>;
}; };
``` ```
Here you will have to replace PIN_A and PIN_B with the appropriate pins that your PCB utilizes for the encoder(s). For keyboards that use the Pro Micro or any of the Pro Micro replacements, Sparkfun's [Pro Micro Hookup Guide](https://learn.sparkfun.com/tutorials/pro-micro--fio-v3-hookup-guide/hardware-overview-pro-micro) has a pinout diagram that can be useful to determine the right pins. Reference either the blue numbers labeled "Arduino" (digital pins) or the green numbers labeled "Analog" (analog pins). For pins that are labeled as both digital and analog, refer to your specific board's .dtsi file to determine how you should refer to that pin. Here you will have to replace PIN_A and PIN_B with the appropriate pins that your PCB utilizes for the encoder(s). For keyboards that use the Pro Micro or any of the Pro Micro replacements, Sparkfun's [Pro Micro Hookup Guide](https://learn.sparkfun.com/tutorials/pro-micro--fio-v3-hookup-guide/hardware-overview-pro-micro) has a pinout diagram that can be useful to determine the right pins. Reference either the blue numbers labeled "Arduino" (digital pins) or the green numbers labeled "Analog" (analog pins). For pins that are labeled as both digital and analog, refer to your specific board's .dtsi file to determine how you should refer to that pin.
Add additional encoders as necessary by duplicating the above lines, replacing `left` with whatever you would like to call your encoder, and updating the pins. Note that support for peripheral (right) side sensors over BLE is still in progress. Add additional encoders as necessary by duplicating the above lines, replacing `left` with whatever you would like to call your encoder, and updating the pins. Note that support for peripheral (right) side sensors over BLE is still in progress.
@ -279,15 +462,12 @@ For split keyboards, make sure to add left hand encoders to the left .overlay fi
</TabItem> </TabItem>
<TabItem value = "keymap"> <TabItem value = "keymap">
Add the following line to each layer of your keymap file to add default encoder behavior bindings: Add the following line to your keymap file to add default encoder behavior bindings:
``` ```
sensor-bindings = <&inc_dec_cp M_VOLU M_VOLD>; sensor-bindings = <&inc_dec_cp M_VOLU M_VOLD>;
``` ```
Add additional bindings as necessary to match the default number of encoders on your board. See the [Encoders](/docs/feature/encoders) and [Keymap](/docs/feature/keymaps) feature documentation for more details.
This should be placed after the regular key bindings but within the layer (see the [Default Keymap section](/docs/dev-guide-new-shield#default-keymap) above for an example of where).
Add additional bindings as necessary to match the default number of encoders on your board. Details on the syntax can be found in the [Encoders](/docs/feature/encoders) and [Keymap](/docs/feature/keymaps) feature documentation.
</TabItem> </TabItem>
</Tabs> </Tabs>
@ -307,6 +487,11 @@ and then flash with:
west flash west flash
``` ```
:::note
Further testing your keyboard shield without altering the root keymap file can be done with the use of `-DZMK_CONFIG` in your `west build` command,
shown [here](dev-build-flash#building-from-zmk-config-folder)
:::
## Updating `build.yml` ## Updating `build.yml`
Before publishing your shield to the public via a PR, navigate to `build.yml` found in `.github/workflows` and add your shield to the appropriate list. An example edit to `build.yml` is shown below. Before publishing your shield to the public via a PR, navigate to `build.yml` found in `.github/workflows` and add your shield to the appropriate list. An example edit to `build.yml` is shown below.
@ -336,7 +521,6 @@ jobs:
- board: proton_c - board: proton_c
shield: clueboard_california shield: clueboard_california
``` ```
:::note :::note
Notice that both the left and right halves of a split board need to be added to the list of shields for proper error checking. Notice that both the left and right halves of a split board need to be added to the list of shields for proper error checking.
:::note :::note