aboutsummaryrefslogtreecommitdiff
path: root/docs/feature_led_indicators.md
diff options
context:
space:
mode:
authorJoel Challis <git@zvecr.com>2020-11-08 22:31:16 +0000
committerGitHub <noreply@github.com>2020-11-08 22:31:16 +0000
commit1ff5ee255fadcd6bfc4defb68ef097d67ebd40ad (patch)
tree559d771e6c2490ea7816b095b0e6e9a196462ec0 /docs/feature_led_indicators.md
parent9cd3ffa5ba1187c0bc11b613078d89b503dcf419 (diff)
downloadqmk_firmware-1ff5ee255fadcd6bfc4defb68ef097d67ebd40ad.tar.gz
qmk_firmware-1ff5ee255fadcd6bfc4defb68ef097d67ebd40ad.zip
Indicator LEDs as config (#10816)
* First pass * Add config options to docs * Update some wording * Slight tidy up of backlight caps logic * Init pin to correct state * Move init location * Reverse default state
Diffstat (limited to 'docs/feature_led_indicators.md')
-rw-r--r--docs/feature_led_indicators.md116
1 files changed, 116 insertions, 0 deletions
diff --git a/docs/feature_led_indicators.md b/docs/feature_led_indicators.md
new file mode 100644
index 000000000..10e095ab1
--- /dev/null
+++ b/docs/feature_led_indicators.md
@@ -0,0 +1,116 @@
1# LED Indicators
2
3QMK provides methods to read 5 of the LEDs defined in the HID spec:
4
5* Num Lock
6* Caps Lock
7* Scroll Lock
8* Compose
9* Kana
10
11There are three ways to get the lock LED state:
12* by specifying configuration options within `config.h`
13* by implementing `bool led_update_kb(led_t led_state)` or `_user(led_t led_state)`; or
14* by calling `led_t host_keyboard_led_state()`
15
16!> `host_keyboard_led_state()` may already reflect a new value before `led_update_user()` is called.
17
18Two more deprecated functions exist that provide the LED state as a `uint8_t`:
19
20* `uint8_t led_set_kb(uint8_t usb_led)` and `_user(uint8_t usb_led)`
21* `uint8_t host_keyboard_leds()`
22
23## Configuration Options
24
25To configure the indicators, `#define` these in your `config.h`:
26
27|Define |Default |Description |
28|---------------------|-------------|-------------------------------------------|
29|`LED_NUM_LOCK_PIN` |*Not defined*|The pin that controls the `Num Lock` LED |
30|`LED_CAPS_LOCK_PIN` |*Not defined*|The pin that controls the `Caps Lock` LED |
31|`LED_SCROLL_LOCK_PIN`|*Not defined*|The pin that controls the `Scroll Lock` LED|
32|`LED_COMPOSE_PIN` |*Not defined*|The pin that controls the `Compose` LED |
33|`LED_KANA_PIN` |*Not defined*|The pin that controls the `Kana` LED |
34|`LED_PIN_ON_STATE` |`1` |The state of the indicator pins when the LED is "on" - `1` for high, `0` for low|
35
36Unless you are designing your own keyboard, you generally should not need to change the above config options.
37
38## `led_update_*()`
39
40When the configuration options do not provide enough flexibility, the API hooks provided allow custom control of the LED behavior. These functions will be called when the state of one of those 5 LEDs changes. It receives the LED state as a struct parameter.
41
42By convention, return `true` from `led_update_user()` to get the `led_update_kb()` hook to run its code, and
43return `false` when you would prefer not to run the code in `led_update_kb()`.
44
45Some examples include:
46
47 - overriding the LEDs to use them for something else like layer indication
48 - return `false` because you do not want the `_kb()` function to run, as it would override your layer behavior.
49 - play a sound when an LED turns on or off.
50 - return `true` because you want the `_kb` function to run, and this is in addition to the default LED behavior.
51
52?> Because the `led_set_*` functions return `void` instead of `bool`, they do not allow for overriding the keyboard LED control, and thus it's recommended to use `led_update_*` instead.
53
54### Example `led_update_kb()` Implementation
55
56```c
57bool led_update_kb(led_t led_state) {
58 bool res = led_update_user(led_state);
59 if(res) {
60 // writePin sets the pin high for 1 and low for 0.
61 // In this example the pins are inverted, setting
62 // it low/0 turns it on, and high/1 turns the LED off.
63 // This behavior depends on whether the LED is between the pin
64 // and VCC or the pin and GND.
65 writePin(B0, !led_state.num_lock);
66 writePin(B1, !led_state.caps_lock);
67 writePin(B2, !led_state.scroll_lock);
68 writePin(B3, !led_state.compose);
69 writePin(B4, !led_state.kana);
70 }
71 return res;
72}
73```
74
75### Example `led_update_user()` Implementation
76
77This incomplete example would play a sound if Caps Lock is turned on or off. It returns `true`, because you also want the LEDs to maintain their state.
78
79```c
80#ifdef AUDIO_ENABLE
81 float caps_on[][2] = SONG(CAPS_LOCK_ON_SOUND);
82 float caps_off[][2] = SONG(CAPS_LOCK_OFF_SOUND);
83#endif
84
85bool led_update_user(led_t led_state) {
86 #ifdef AUDIO_ENABLE
87 static uint8_t caps_state = 0;
88 if (caps_state != led_state.caps_lock) {
89 led_state.caps_lock ? PLAY_SONG(caps_on) : PLAY_SONG(caps_off);
90 caps_state = led_state.caps_lock;
91 }
92 #endif
93 return true;
94}
95```
96
97### `led_update_*` Function Documentation
98
99* Keyboard/Revision: `bool led_update_kb(led_t led_state)`
100* Keymap: `bool led_update_user(led_t led_state)`
101
102## `host_keyboard_led_state()`
103
104Call this function to get the last received LED state as a `led_t`. This is useful for reading the LED state outside `led_update_*`, e.g. in [`matrix_scan_user()`](#matrix-scanning-code).
105
106## Setting Physical LED State
107
108Some keyboard implementations provide convenience methods for setting the state of the physical LEDs.
109
110### Ergodox Boards
111
112The Ergodox implementations provide `ergodox_right_led_1`/`2`/`3_on`/`off()` to turn individual LEDs on or off, as well as `ergodox_right_led_on`/`off(uint8_t led)` to turn them on or off by their index.
113
114In addition, it is possible to specify the brightness level of all LEDs with `ergodox_led_all_set(uint8_t n)`; of individual LEDs with `ergodox_right_led_1`/`2`/`3_set(uint8_t n)`; or by index with `ergodox_right_led_set(uint8_t led, uint8_t n)`.
115
116Ergodox boards also define `LED_BRIGHTNESS_LO` for the lowest brightness and `LED_BRIGHTNESS_HI` for the highest brightness (which is the default).