-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'soft-off-guide' of github.com:Nick-Munnich/zmk into sof…
…t-off-guide
- Loading branch information
Showing
11 changed files
with
383 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
Here is an example for a keyboard with a dedicated on/off push button that is a direct wire between the GPIO pin and ground: | ||
|
||
```dts | ||
/ { | ||
keys { | ||
compatible = "gpio-keys"; | ||
soft_off_gpio_key: soft_off_gpio_key { | ||
gpios = <&gpio0 2 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; | ||
}; | ||
}; | ||
}; | ||
``` | ||
|
||
In the above example the soft on/off would be triggered by pulling the specified pin low, typically by pressing a switch that has the other leg connected to ground. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
Here is an example for a keyboard with a GPIO pin that reads from the matrix: | ||
|
||
```dts | ||
/ { | ||
keys { | ||
compatible = "gpio-keys"; | ||
soft_off_gpio_key: soft_off_gpio_key { | ||
gpios = <&gpio0 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; | ||
}; | ||
}; | ||
}; | ||
``` | ||
|
||
Matrix inputs are triggered by pulling the specified pin high, typically by pressing some combination of switches which connects the matrix input to a matrix output. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
Here is an example for a keyboard with a GPIO pin reused from a matrix kscan: | ||
|
||
```dts | ||
/ { | ||
keys { | ||
compatible = "gpio-keys"; | ||
soft_off_gpio_key: soft_off_gpio_key { | ||
gpios = <&gpio0 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; | ||
}; | ||
}; | ||
}; | ||
``` | ||
|
||
The GPIO settings should match those in the kscan, so the above would be set to `(GPIO_ACTIVE_LOW | GPIO_PULL_UP)` for a direct kscan. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
### KScan sideband behavior | ||
|
||
The kscan sideband behavior driver will be used to trigger the [soft off behavior](../../keymaps/behaviors/soft-off.md) "out of band" from the normal keymap processing. To do so, it will decorate/wrap an underlying kscan driver. | ||
|
||
With a simple direct pin setup, the [direct kscan](../../config/kscan.md) driver can be used with a [GPIO key](#gpio-key), to make a small "side matrix": | ||
|
||
```dts | ||
/ { | ||
wakeup_scan: wakeup_scan { | ||
compatible = "zmk,kscan-gpio-direct"; | ||
input-keys = <&soft_off_gpio_key>; | ||
wakeup-source; | ||
}; | ||
}; | ||
``` | ||
|
||
With that in place, the kscan sideband behavior will wrap the new driver: | ||
|
||
```dts | ||
/ { | ||
side_band_behavior_triggers: side_band_behavior_triggers { | ||
compatible = "zmk,kscan-sideband-behaviors"; | ||
kscan = <&wakeup_scan>; | ||
auto-enable; | ||
wakeup-source; | ||
soft_off { | ||
column = <0>; | ||
row = <0>; | ||
bindings = <&hw_soft_off>; | ||
}; | ||
}; | ||
}; | ||
``` | ||
|
||
As the kscan used only has a single key, both column and row are set to 0. The properties of the `kscan-sideband-behaviors` node can be found in the [appropriate configuration section](../../config/kscan.md#kscan-sideband-behavior-driver). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
### KScan sideband behavior | ||
|
||
The kscan sideband behavior driver will be used to trigger the [soft off behavior](../../keymaps/behaviors/soft-off.md) "out of band" from the normal keymap processing. To do so, it will decorate/wrap an underlying kscan driver. | ||
|
||
For the matrix-integrated approach you will supplement the existing kscan matrix by adding the additional pin as another entry in | ||
the `row-gpios`/`col-gpios` for whichever pins are used to read the matrix state. This approach requires a matrix transform to be present. As an example, consider the following existing kscan matrix: | ||
|
||
```dts | ||
/ { | ||
kscan: kscan { | ||
compatible = "zmk,kscan-gpio-matrix"; | ||
diode-direction = "col2row"; | ||
wakeup-source; | ||
col-gpios | ||
= <&gpio0 12 GPIO_ACTIVE_HIGH> | ||
, <&gpio1 9 GPIO_ACTIVE_HIGH> | ||
; | ||
row-gpios | ||
= <&gpio0 19 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> | ||
, <&gpio0 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> | ||
; | ||
}; | ||
}; | ||
``` | ||
|
||
To supplement it with a soft off input, you would add another row value (without changing the matrix transform): | ||
|
||
```dts | ||
/ { | ||
kscan: kscan { | ||
compatible = "zmk,kscan-gpio-matrix"; | ||
diode-direction = "col2row"; | ||
wakeup-source; | ||
col-gpios | ||
= <&gpio0 12 GPIO_ACTIVE_HIGH> | ||
, <&gpio1 9 GPIO_ACTIVE_HIGH> | ||
; | ||
row-gpios | ||
= <&gpio0 19 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> | ||
, <&gpio0 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> | ||
, <&gpio0 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)> | ||
; | ||
}; | ||
}; | ||
``` | ||
|
||
With that in place, you would decorate the kscan driver: | ||
|
||
```dts | ||
/ { | ||
side_band_behavior_triggers: side_band_behavior_triggers { | ||
compatible = "zmk,kscan-sideband-behaviors"; | ||
wakeup-source; | ||
kscan = <&kscan>; | ||
soft_off { | ||
column = <0>; | ||
row = <2>; | ||
bindings = <&hw_soft_off>; | ||
}; | ||
}; | ||
}; | ||
``` | ||
|
||
Critically, the `column` and `row` values would correspond to the location of the added entry. The properties of the `kscan-sideband-behaviors` node can be found in the [appropriate configuration section](../../config/kscan.md#kscan-sideband-behavior-driver). |
28 changes: 28 additions & 0 deletions
28
docs/docs/advanced-guides/includes/_sideband-wakeup-direct.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
### KScan sideband behavior | ||
|
||
With a simple direct pin setup, the [direct kscan](../../config/kscan.md) driver can be used with a [GPIO key](#gpio-key), to make a small "side matrix": | ||
|
||
```dts | ||
/ { | ||
wakeup_scan: wakeup_scan { | ||
compatible = "zmk,kscan-gpio-direct"; | ||
input-keys = <&soft_off_gpio_key>; | ||
wakeup-source; | ||
}; | ||
}; | ||
``` | ||
|
||
The kscan sideband behavior needs to wrap the new driver to enable it: | ||
|
||
```dts | ||
/ { | ||
side_band_behavior_triggers: side_band_behavior_triggers { | ||
compatible = "zmk,kscan-sideband-behaviors"; | ||
kscan = <&wakeup_scan>; | ||
auto-enable; | ||
wakeup-source; | ||
}; | ||
}; | ||
``` | ||
|
||
The properties of the `kscan-sideband-behaviors` node can be found in the [appropriate configuration section](../../config/kscan.md#kscan-sideband-behavior-driver). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
### Soft off behavior instance | ||
|
||
Behind the scenes, a hardware dedicated GPIO pin utilizes the [soft off behavior](../../keymaps/behaviors/soft-off.md) to trigger entering the soft-off state. To use said behavior outside of a keymap, add an instance of the behavior to your `.overlay`/`.dts` file: | ||
|
||
```dts | ||
/ { | ||
behaviors { | ||
hw_soft_off: hw_soft_off { | ||
compatible = "zmk,behavior-soft-off"; | ||
#binding-cells = <0>; | ||
hold-time-ms = <2000>; // Only turn off if the key is held for 2 seconds or longer. | ||
}; | ||
}; | ||
}; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
### Soft off waker | ||
|
||
We need to add another device which will be enabled only when the keyboard is going into soft off state, and will configure the previously declared GPIO key with the correct interrupt configuration to wake the device from soft off once it is pressed. | ||
|
||
```dts | ||
/ { | ||
wakeup_scan: wakeup_scan { | ||
compatible = "zmk,gpio-key-wakeup-trigger"; | ||
trigger = <&soft_off_gpio_key>; | ||
wakeup-source; | ||
extra-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH> | ||
}; | ||
}; | ||
``` | ||
|
||
The properties for the `gpio-key-wakeup-trigger` node can be found in the [appropriate configuration section](../../config/power.md#gpio-key-wakeup-trigger). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--- | ||
title: Advanced Guides | ||
sidebar_label: Advanced Guides | ||
--- | ||
|
||
import DocCardList from "@theme/DocCardList"; | ||
|
||
ZMK, being built on [Zephyr™](https://zephyrproject.org/), is very modular and flexible. This allows users to combine features, flags, and properties to "construct" features in ZMK, without the need to modify the underlying source code. | ||
|
||
These pages are a collection of guides for users who want a _bit_ more out of their ZMK devices, without the need to delve into the [Zephyr™](https://zephyrproject.org/) documentation. Guides aimed at keyboard designers are also found under this section. | ||
|
||
<DocCardList /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
--- | ||
title: Adding Soft Off To A Keyboard | ||
sidebar_label: Soft Off Setup | ||
--- | ||
|
||
import Tabs from "@theme/Tabs"; | ||
import TabItem from "@theme/TabItem"; | ||
|
||
import SoftOffBehavior from "./includes/_soft-off-behavior.md"; | ||
import SoftOffWaker from "./includes/_soft-off-waker.md"; | ||
import GpioKeyDirect from "./includes/_gpio-key-direct.md"; | ||
import GpioKeyMatrix from "./includes/_gpio-key-matrix.md"; | ||
import GpioKeyWakeup from "./includes/_gpio-key-wakeup.md"; | ||
import SidebandDirect from "./includes/_sideband-direct.md"; | ||
import SidebandMatrix from "./includes/_sideband-matrix.md"; | ||
import SidebandWakeupDirect from "./includes/_sideband-wakeup-direct.md"; | ||
|
||
Advanced methods of adding [soft off](../features/low-power-states.md#soft-off) to a keyboard are detailed below. The first two tabs describe methods involving hardware changes, while the last describes the firmware changes necessary to define a single specific key switch for waking up. | ||
|
||
<Tabs groupId="advanced-methods" defaultValue="direct"> | ||
<TabItem value="direct" label="Direct Pin"></TabItem> | ||
<TabItem value="matrix" label="Matrix Integrated Pin"></TabItem> | ||
<TabItem value="wakeup" label="Wakeup-only Key Switch"> | ||
The exact method of reusing a key switch to wake from the soft off state | ||
differs depending on whether said key switch is part of a direct GPIO kscan | ||
or part of a matrix kscan. | ||
<Tabs groupId="kscan-type" defaultValue="mkscan"> | ||
<TabItem value="dkscan" label="Direct GPIO kscan"></TabItem> | ||
<TabItem value="mkscan" label="Matrix kscan"></TabItem> | ||
</Tabs> | ||
</TabItem> | ||
</Tabs> | ||
|
||
## Hardware Changes | ||
|
||
<Tabs groupId="advanced-methods" defaultValue="direct" className="secrettabs"> | ||
<TabItem value="direct" label="Direct Pin"> | ||
|
||
Add a direct push button between a GPIO pin and ground. This button will act as an on/off switch. | ||
|
||
Alternatively, if you wish to integrate a dedicated GPIO pin into a key switch combination using a direct kscan, tie all of the MCU pins that you wish to combine to the dedicated GPIO pin through an OR gate. All firmware changes then follow identically to the direct push button. | ||
|
||
</TabItem> | ||
<TabItem value="matrix" label="Matrix Integrated Pin"> | ||
To integrate the dedicated GPIO pin into your matrix, you will need to tie multiple switch outputs in the matrix together through AND gates and connect the result to the dedicated GPIO pin. This way you can use a (hardware defined) key combination in your existing keyboard matrix to trigger soft on/off. | ||
|
||
Ideally the switches used should be driven by the same matrix output pin so that both will be active simultaneously on the AND gate inputs. The alternative is to connect the switch to two MOSFETs that trigger both the regular matrix connect and the connect to the AND gate to ensure both pins are active/high at the same time even if scanning sets them high at different times. | ||
|
||
</TabItem> | ||
<TabItem value="wakeup" label="Wakeup-only Key Switch"> | ||
No hardware changes are necessary for this approach. | ||
</TabItem> | ||
</Tabs> | ||
|
||
## Firmware Changes | ||
|
||
Several items work together to make both triggering soft off properly, and setting up the device to _wake_ from soft off work as expected. | ||
|
||
<Tabs groupId="advanced-methods" defaultValue="direct" className="secrettabs"> | ||
<TabItem value="direct" label="Direct Pin"> | ||
<SoftOffBehavior /> | ||
</TabItem> | ||
<TabItem value="matrix" label="Matrix Integrated Pin"> | ||
<SoftOffBehavior /> | ||
</TabItem> | ||
<TabItem value="wakeup" label="Wakeup-only Key Switch"> | ||
|
||
### Soft off behavior | ||
|
||
For this approach, you will need to make sure that the [soft off behavior](../keymaps/behaviors/soft-off.md) is present in your keymap, to trigger soft off. | ||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
### GPIO key | ||
|
||
Zephyr's basic [GPIO Key](https://docs.zephyrproject.org/3.5.0/build/dts/api/bindings/input/gpio-keys.html) concept is used to configure the soft off GPIO pin. | ||
{/* secrettabs hides this tab selector. GPIO key changes its "orientation" between simple pin and matrix integrated. */} | ||
|
||
<Tabs groupId="advanced-methods" defaultValue="direct" className="secrettabs"> | ||
<TabItem value="direct" label="Direct Pin"> | ||
<GpioKeyDirect /> | ||
</TabItem> | ||
<TabItem value="matrix" label="Matrix Integrated Pin"> | ||
<GpioKeyMatrix /> | ||
</TabItem> | ||
<TabItem value="wakeup" label="Wakeup-only Key Switch"> | ||
<GpioKeyWakeup /> | ||
</TabItem> | ||
</Tabs> | ||
|
||
GPIO keys are defined using child nodes under the `gpio-keys` compatible node. Each child needs just one property defined: | ||
|
||
- The `gpios` property should be a [phandle-array](https://docs.zephyrproject.org/3.5.0/build/dts/phandles.html#zero-or-more-nodes-with-metadata-phandle-array-type) with a fully defined GPIO pin and with the correct pull up/down and active high/low flags set. | ||
|
||
<Tabs groupId="advanced-methods" defaultValue="direct" className="secrettabs"> | ||
<TabItem value="direct" label="Direct Pin"> | ||
<SidebandDirect /> | ||
</TabItem> | ||
<TabItem value="matrix" label="Matrix Integrated Pin"> | ||
<SidebandMatrix /> | ||
</TabItem> | ||
<TabItem value="wakeup" label="Wakeup-only Key Switch"> | ||
<Tabs groupId="kscan-type" defaultValue="mkscan" className="secrettabs"> | ||
<TabItem value="dkscan" label="Direct GPIO kscan"> | ||
<SidebandWakeupDirect /> | ||
</TabItem> | ||
<TabItem value="mkscan" label="Matrix kscan"></TabItem> | ||
</Tabs> | ||
</TabItem> | ||
</Tabs> | ||
|
||
<Tabs groupId="advanced-methods" defaultValue="direct" className="secrettabs"> | ||
<TabItem value="direct" label="Direct Pin"></TabItem> | ||
<TabItem value="matrix" label="Matrix Integrated Pin"> | ||
You also need to update the `zmk,kscan` chosen value to point to the new kscan instance: | ||
|
||
```dts | ||
/ { | ||
chosen { | ||
... | ||
zmk,kscan = &side_band_behavior_triggers; | ||
... | ||
}; | ||
}; | ||
``` | ||
|
||
<SoftOffWaker /> | ||
|
||
</TabItem> | ||
<TabItem value="wakeup" label="Wakeup-only Key Switch"> | ||
<Tabs groupId="kscan-type" defaultValue="mkscan" className="secrettabs"> | ||
<TabItem value="dkscan" label="Direct GPIO kscan"></TabItem> | ||
<TabItem value="mkscan" label="Matrix kscan"><SoftOffWaker /></TabItem> | ||
</Tabs> | ||
</TabItem> | ||
</Tabs> | ||
|
||
Finally, we will list the `wakeup_scan` device in an additional configuration section so that the ZMK soft off process knows it needs to enable this device as part of the soft off processing so it can wake the keyboard from soft off when pressed: | ||
|
||
```dts | ||
/ { | ||
soft_off_wakers { | ||
compatible = "zmk,soft-off-wakeup-sources"; | ||
wakeup-sources = <&wakeup_scan>; | ||
}; | ||
}; | ||
``` | ||
|
||
Here are the properties for the node: | ||
|
||
- The `compatible` property for the node must be `zmk,soft-off-wakeup-sources`. | ||
- The `wakeup-sources` property is a [phandle array](../config/index.md#devicetree-property-types) pointing to all the devices that should be enabled during the shutdown process to be sure they can later wake the keyboard. | ||
|
||
:::tip | ||
If you add your kscan to the `wakeup-sources` array, then your keyboard will wake upon pressing any key in your kscan. Essentially, this causes `&soft_off` to behave as one would expect `&sleep` to behave. If you choose to do so, then you can omit everything aside from the `soft_off_wakers` node. | ||
::: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters