255 lines
8 KiB
Text
255 lines
8 KiB
Text
---
|
|
title: Backlight
|
|
sidebar_label: Backlight
|
|
---
|
|
|
|
import Tabs from "@theme/Tabs";
|
|
import TabItem from "@theme/TabItem";
|
|
|
|
Backlight is a feature used to control an array of LEDs, usually placed through or under switches.
|
|
|
|
:::info
|
|
Unlike [RGB Underglow](underglow.md), backlight can only control single color LEDs. Additionally, because backlight LEDs all receive the same power, it's not possible to dim individual LEDs.
|
|
:::
|
|
|
|
## Enabling Backlight
|
|
|
|
To enable backlight on your board or shield, add the following line to your `.conf` file of your user config directory as such:
|
|
|
|
```ini
|
|
CONFIG_ZMK_BACKLIGHT=y
|
|
```
|
|
|
|
If your board or shield does not have backlight configured, refer to [Adding Backlight to a board or a shield](#adding-backlight-to-a-board-or-a-shield).
|
|
|
|
## Configuring Backlight
|
|
|
|
There are various Kconfig options used to configure the backlight feature. These can all be set in the `.conf` file.
|
|
|
|
| Option | Description | Default |
|
|
| ------------------------------------ | ----------------------------------------------------- | ------- |
|
|
| `CONFIG_ZMK_BACKLIGHT_BRT_STEP` | Brightness step in percent | 20 |
|
|
| `CONFIG_ZMK_BACKLIGHT_BRT_START` | Default brightness in percent | 40 |
|
|
| `CONFIG_ZMK_BACKLIGHT_ON_START` | Default backlight state | y |
|
|
| `CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE` | Turn off backlight when keyboard goes into idle state | n |
|
|
| `CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB` | Turn off backlight when USB is disconnected | n |
|
|
|
|
## Adding Backlight to a Board or a Shield
|
|
|
|
<Tabs
|
|
defaultValue="shieldpin"
|
|
values={[
|
|
{label: 'Adding to a board', value: 'boardpin'},{label: 'Adding to a shield', value: 'shieldpin'},
|
|
]}>
|
|
|
|
<TabItem value="boardpin">
|
|
|
|
First, you must enable PWM by adding the following lines to your `Kconfig.defconfig` file:
|
|
|
|
```kconfig
|
|
if ZMK_BACKLIGHT
|
|
|
|
config PWM
|
|
default y
|
|
|
|
config LED_PWM
|
|
default y
|
|
|
|
endif # ZMK_BACKLIGHT
|
|
```
|
|
|
|
Create a `<board>-pinctrl.dtsi` file if it does not already exist, and include it at the beginning of the `<board>.dts` file. `CONFIG_PINCTRL=y` must be added to `<board>_defconfig` if it isn't already enabled.
|
|
|
|
The pinctrl file has a `&pinctrl` node that encompasses all pinctrl settings, including I2C or SPI peripherals (e.g. WS2812 LEDs, Battery fuel gauges):
|
|
|
|
```dts
|
|
&pinctrl {
|
|
// Other pinctrl definitions for other hardware
|
|
pwm0_default: pwm0_default {
|
|
group1 {
|
|
psels = <NRF_PSEL(PWM_OUT0, 1, 13)>;
|
|
};
|
|
};
|
|
pwm0_sleep: pwm0_sleep {
|
|
group1 {
|
|
psels = <NRF_PSEL(PWM_OUT0, 1, 13)>;
|
|
low-power-enable;
|
|
};
|
|
};
|
|
};
|
|
```
|
|
|
|
Pin numbers are handled differently depending on the MCU. On nRF MCUs pins are configured using `(PWM_OUTX, Y, Z)`, where `X` is the PWM channel used (usually 0), `Y` is the first part of the hardware port (_PY.01_) and `Z` is the second part of the hardware port (_P1.Z_).
|
|
|
|
For example, _P1.13_ would give you `(PWM_OUT0, 1, 13)` and _P0.15_ would give you `(PWM_OUT0, 0, 15)`.
|
|
|
|
Add the PWM device to the `board.dts` file and assign the pinctrl definitions to it:
|
|
|
|
```dts
|
|
&pwm0 {
|
|
status = "okay";
|
|
pinctrl-0 = <&pwm0_default>;
|
|
pinctrl-1 = <&pwm0_sleep>;
|
|
pinctrl-names = "default", "sleep";
|
|
};
|
|
```
|
|
|
|
Then add the following lines to the same `<board>.dts` file, but inside the root devicetree node:
|
|
|
|
```dts
|
|
/ {
|
|
backlight: pwmleds {
|
|
compatible = "pwm-leds";
|
|
pwm_led_0 {
|
|
pwms = <&pwm0 0 PWM_MSEC(10) PWM_POLARITY_NORMAL>;
|
|
};
|
|
};
|
|
};
|
|
```
|
|
|
|
The value inside `pwm_led_0` after `&pwm0` must be the channel number. Since `PWM_OUT0` is defined in the pinctrl node, the channel in this example is 0.
|
|
|
|
In this example, `PWM_MSEC(10)` is the period of the PWM waveform. This period can be altered if your drive circuitry requires different values or the frequency is audible.
|
|
|
|
If your board uses a P-channel MOSFET to control backlight instead of a N-channel MOSFET, you may want to change `PWM_POLARITY_NORMAL` for `PWM_POLARITY_INVERTED`.
|
|
|
|
Finally you need to add backlight to the `chosen` element of the root devicetree node:
|
|
|
|
```dts
|
|
/ {
|
|
chosen {
|
|
zmk,backlight = &backlight;
|
|
};
|
|
};
|
|
```
|
|
|
|
</TabItem>
|
|
<TabItem value="shieldpin">
|
|
|
|
You must first add a `boards/` directory within your shield folder. For each board that supports the shield you must create a `<board>.defconfig` file and a `<board>.overlay` file inside the `boards/` folder.
|
|
|
|
Inside your `<board>.defconfig` file, add the following lines:
|
|
|
|
```kconfig
|
|
if ZMK_BACKLIGHT
|
|
|
|
config PWM
|
|
default y
|
|
|
|
config LED_PWM
|
|
default y
|
|
|
|
endif # ZMK_BACKLIGHT
|
|
```
|
|
|
|
Then add the following lines to your `.overlay` file:
|
|
|
|
```dts
|
|
&pinctrl {
|
|
// Other pinctrl definitions for other hardware
|
|
pwm0_default: pwm0_default {
|
|
group1 {
|
|
psels = <NRF_PSEL(PWM_OUT0, 1, 13)>;
|
|
};
|
|
};
|
|
pwm0_sleep: pwm0_sleep {
|
|
group1 {
|
|
psels = <NRF_PSEL(PWM_OUT0, 1, 13)>;
|
|
low-power-enable;
|
|
};
|
|
};
|
|
};
|
|
```
|
|
|
|
Pin numbers are handled differently depending on the MCU. On nRF MCUs pins are configured using `(PWM_OUTX, Y, Z)`, where `X` is the PWM channel used (usually 0), `Y` is the first part of the hardware port (_PY.01_) and `Z` is the second part of the hardware port (_P1.Z_).
|
|
|
|
For example, _P1.13_ would give you `(PWM_OUT0, 1, 13)` and _P0.15_ would give you `(PWM_OUT0, 0, 15)`.
|
|
|
|
Add the PWM device to the `<board>.overlay` file and assign the pinctrl definitions to it:
|
|
|
|
```dts
|
|
&pwm0 {
|
|
status = "okay";
|
|
pinctrl-0 = <&pwm0_default>;
|
|
pinctrl-1 = <&pwm0_sleep>;
|
|
pinctrl-names = "default", "sleep";
|
|
};
|
|
```
|
|
|
|
Then add the following lines to the same `<board>.overlay` file, but inside the root devicetree node:
|
|
|
|
```
|
|
/ {
|
|
backlight: pwmleds {
|
|
compatible = "pwm-leds";
|
|
pwm_led_0 {
|
|
pwms = <&pwm0 0 PWM_MSEC(10) PWM_POLARITY_NORMAL>;
|
|
};
|
|
};
|
|
};
|
|
```
|
|
|
|
In this example, `PWM_MSEC(10)` is the period of the PWM waveform. This period can be altered if your drive circuitry requires different values or the frequency is audible.
|
|
|
|
If your board uses a P-channel MOSFET to control backlight instead of a N-channel MOSFET, you may want to change `PWM_POLARITY_NORMAL` for `PWM_POLARITY_INVERTED`.
|
|
|
|
The value inside `pwm_led_0` after `&pwm0` must be the channel number. Since `PWM_OUT0` is defined in the pinctrl node, the channel in this example is 0.
|
|
|
|
Finally you need to add backlight to the `chosen` element of the root devicetree node:
|
|
|
|
```dts
|
|
/ {
|
|
chosen {
|
|
zmk,backlight = &backlight;
|
|
};
|
|
};
|
|
```
|
|
|
|
</TabItem>
|
|
</Tabs>
|
|
|
|
### Multiple Backlight LEDs
|
|
|
|
It is possible to control multiple backlight LEDs at the same time. This is useful if, for example, you have a Caps Lock LED connected to a different pin and you want it to be part of the backlight.
|
|
|
|
In order to do that, first configure PWM for each pin in the pinctrl node:
|
|
|
|
```dts
|
|
&pinctrl {
|
|
// Other Pinctrl definitions go here
|
|
pwm0_default: pwm0_default {
|
|
group1 {
|
|
psels = <NRF_PSEL(PWM_OUT0, 0, 20)>, // LED 0
|
|
<NRF_PSEL(PWM_OUT1, 0, 22)>, // LED 1
|
|
<NRF_PSEL(PWM_OUT2, 0, 24)>; // LED 2
|
|
};
|
|
};
|
|
pwm0_sleep: pwm0_sleep {
|
|
group1 {
|
|
psels = <NRF_PSEL(PWM_OUT0, 0, 20)>, // LED 0
|
|
<NRF_PSEL(PWM_OUT1, 0, 22)>, // LED 1
|
|
<NRF_PSEL(PWM_OUT2, 0, 24)>; // LED 2
|
|
low-power-enable;
|
|
};
|
|
};
|
|
};
|
|
```
|
|
|
|
This part will vary based on your MCU as different MCUs have a different number of modules, channels and configuration options.
|
|
|
|
Add each of your LEDs to the backlight node in the same manner as for one LED, using the channel number definitions in the pinctrl node:
|
|
|
|
```dts
|
|
backlight: pwmleds {
|
|
compatible = "pwm-leds";
|
|
pwm_led_0: pwm_led_0 {
|
|
pwms = <&pwm0 0 PWM_MSEC(10) PWM_POLARITY_NORMAL>;
|
|
};
|
|
pwm_led_1: pwm_led_1 {
|
|
pwms = <&pwm0 1 PWM_MSEC(10) PWM_POLARITY_NORMAL>;
|
|
};
|
|
pwm_led_2: pwm_led_2 {
|
|
pwms = <&pwm0 2 PWM_MSEC(10) PWM_POLARITY_NORMAL>;
|
|
};
|
|
};
|
|
```
|