aboutsummaryrefslogtreecommitdiff
path: root/docs/custom_quantum_functions.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/custom_quantum_functions.md')
-rw-r--r--docs/custom_quantum_functions.md129
1 files changed, 77 insertions, 52 deletions
diff --git a/docs/custom_quantum_functions.md b/docs/custom_quantum_functions.md
index 839d49ca0..71a30bc7c 100644
--- a/docs/custom_quantum_functions.md
+++ b/docs/custom_quantum_functions.md
@@ -90,68 +90,93 @@ keyrecord_t record {
90 90
91# LED Control 91# LED Control
92 92
93QMK provides methods to read the 5 LEDs defined as part of the HID spec: 93QMK provides methods to read 5 of the LEDs defined in the HID spec:
94 94
95* `USB_LED_NUM_LOCK` 95* Num Lock
96* `USB_LED_CAPS_LOCK` 96* Caps Lock
97* `USB_LED_SCROLL_LOCK` 97* Scroll Lock
98* `USB_LED_COMPOSE` 98* Compose
99* `USB_LED_KANA` 99* Kana
100 100
101These five constants correspond to the positional bits of the host LED state. 101There are two ways to get the lock LED state:
102There are two ways to get the host LED state:
103 102
104* by implementing `led_set_user()` 103* by implementing `bool led_update_kb(led_t led_state)` or `_user(led_t led_state)`; or
105* by calling `host_keyboard_leds()` 104* by calling `led_t host_keyboard_led_state()`
106 105
107## `led_set_user()` 106!> `host_keyboard_led_state()` may already reflect a new value before `led_update_user()` is called.
108 107
109This function will be called when the state of one of those 5 LEDs changes. It receives the LED state as a parameter. 108Two more deprecated functions exist that provide the LED state as a `uint8_t`:
110Use the `IS_LED_ON(usb_led, led_name)` and `IS_LED_OFF(usb_led, led_name)` macros to check the LED status.
111 109
112!> `host_keyboard_leds()` may already reflect a new value before `led_set_user()` is called. 110* `uint8_t led_set_kb(uint8_t usb_led)` and `_user(uint8_t usb_led)`
111* `uint8_t host_keyboard_leds()`
113 112
114### Example `led_set_user()` Implementation 113## `led_update_user()`
114
115This function will be called when the state of one of those 5 LEDs changes. It receives the LED state as a struct parameter.
116
117By convention, return `true` from `led_update_user()` to get the `led_update_kb()` hook to run its code, and
118return `false` when you would prefer not to run the code in `led_update_kb()`.
119
120Some examples include:
121
122 - overriding the LEDs to use them for something else like layer indication
123 - return `false` because you do not want the `_kb()` function to run, as it would override your layer behavior.
124 - play a sound when an LED turns on or off.
125 - return `true` because you want the `_kb` function to run, and this is in addition to the default LED behavior.
126
127?> 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.
128
129### Example `led_update_kb()` Implementation
115 130
116```c 131```c
117void led_set_user(uint8_t usb_led) { 132bool led_update_kb(led_t led_state) {
118 if (IS_LED_ON(usb_led, USB_LED_NUM_LOCK)) { 133 bool res = led_update_user(led_state);
119 writePinLow(B0); 134 if(res) {
120 } else { 135 // writePin sets the pin high for 1 and low for 0.
121 writePinHigh(B0); 136 // In this example the pins are inverted, setting
122 } 137 // it low/0 turns it on, and high/1 turns the LED off.
123 if (IS_LED_ON(usb_led, USB_LED_CAPS_LOCK)) { 138 // This behavior depends on whether the LED is between the pin
124 writePinLow(B1); 139 // and VCC or the pin and GND.
125 } else { 140 writePin(B0, !led_state.num_lock);
126 writePinHigh(B1); 141 writePin(B1, !led_state.caps_lock);
127 } 142 writePin(B2, !led_state.scroll_lock);
128 if (IS_LED_ON(usb_led, USB_LED_SCROLL_LOCK)) { 143 writePin(B3, !led_state.compose);
129 writePinLow(B2); 144 writePin(B4, !led_state.kana);
130 } else {
131 writePinHigh(B2);
132 } 145 }
133 if (IS_LED_ON(usb_led, USB_LED_COMPOSE)) { 146 return res;
134 writePinLow(B3); 147}
135 } else { 148```
136 writePinHigh(B3); 149
137 } 150### Example `led_update_user()` Implementation
138 if (IS_LED_ON(usb_led, USB_LED_KANA)) { 151
139 writePinLow(B4); 152This 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.
140 } else { 153
141 writePinHigh(B4); 154```c
155#ifdef AUDIO_ENABLE
156 float caps_on[][2] = SONG(CAPS_LOCK_ON_SOUND);
157 float caps_off[][2] = SONG(CAPS_LOCK_OFF_SOUND);
158#endif
159
160bool led_update_user(led_t led_state) {
161 #ifdef AUDIO_ENABLE
162 static uint8_t caps_state = 0;
163 if (caps_state != led_state.caps_lock) {
164 led_state.caps_lock ? PLAY_SONG(caps_on) : PLAY_SONG(caps_off);
165 caps_state = led_state.caps_lock;
142 } 166 }
167 #endif
168 return true;
143} 169}
144``` 170```
145 171
146### `led_set_*` Function Documentation 172### `led_update_*` Function Documentation
147 173
148* Keyboard/Revision: `void led_set_kb(uint8_t usb_led)` 174* Keyboard/Revision: `bool led_update_kb(led_t led_state)`
149* Keymap: `void led_set_user(uint8_t usb_led)` 175* Keymap: `bool led_update_user(led_t led_state)`
150 176
151## `host_keyboard_leds()` 177## `host_keyboard_led_state()`
152 178
153Call this function to get the last received LED state. This is useful for reading the LED state outside `led_set_*`, e.g. in [`matrix_scan_user()`](#matrix-scanning-code). 179Call 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).
154For convenience, you can use the `IS_HOST_LED_ON(led_name)` and `IS_HOST_LED_OFF(led_name)` macros instead of calling and checking `host_keyboard_leds()` directly.
155 180
156## Setting Physical LED State 181## Setting Physical LED State
157 182
@@ -369,7 +394,7 @@ void keyboard_post_init_user(void) {
369 // Set default layer, if enabled 394 // Set default layer, if enabled
370 if (user_config.rgb_layer_change) { 395 if (user_config.rgb_layer_change) {
371 rgblight_enable_noeeprom(); 396 rgblight_enable_noeeprom();
372 rgblight_sethsv_noeeprom_cyan(); 397 rgblight_sethsv_noeeprom_cyan();
373 rgblight_mode_noeeprom(1); 398 rgblight_mode_noeeprom(1);
374 } 399 }
375} 400}
@@ -417,18 +442,18 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
417 } 442 }
418 return true; // Let QMK send the enter press/release events 443 return true; // Let QMK send the enter press/release events
419 case RGB_LYR: // This allows me to use underglow as layer indication, or as normal 444 case RGB_LYR: // This allows me to use underglow as layer indication, or as normal
420 if (record->event.pressed) { 445 if (record->event.pressed) {
421 user_config.rgb_layer_change ^= 1; // Toggles the status 446 user_config.rgb_layer_change ^= 1; // Toggles the status
422 eeconfig_update_user(user_config.raw); // Writes the new status to EEPROM 447 eeconfig_update_user(user_config.raw); // Writes the new status to EEPROM
423 if (user_config.rgb_layer_change) { // if layer state indication is enabled, 448 if (user_config.rgb_layer_change) { // if layer state indication is enabled,
424 layer_state_set(layer_state); // then immediately update the layer color 449 layer_state_set(layer_state); // then immediately update the layer color
425 } 450 }
426 } 451 }
427 return false; break; 452 return false; break;
428 case RGB_MODE_FORWARD ... RGB_MODE_GRADIENT: // For any of the RGB codes (see quantum_keycodes.h, L400 for reference) 453 case RGB_MODE_FORWARD ... RGB_MODE_GRADIENT: // For any of the RGB codes (see quantum_keycodes.h, L400 for reference)
429 if (record->event.pressed) { //This disables layer indication, as it's assumed that if you're changing this ... you want that disabled 454 if (record->event.pressed) { //This disables layer indication, as it's assumed that if you're changing this ... you want that disabled
430 if (user_config.rgb_layer_change) { // only if this is enabled 455 if (user_config.rgb_layer_change) { // only if this is enabled
431 user_config.rgb_layer_change = false; // disable it, and 456 user_config.rgb_layer_change = false; // disable it, and
432 eeconfig_update_user(user_config.raw); // write the setings to EEPROM 457 eeconfig_update_user(user_config.raw); // write the setings to EEPROM
433 } 458 }
434 } 459 }
@@ -441,7 +466,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
441And lastly, you want to add the `eeconfig_init_user` function, so that when the EEPROM is reset, you can specify default values, and even custom actions. To force an EEPROM reset, use the `EEP_RST` keycode or [Bootmagic](feature_bootmagic.md) functionallity. For example, if you want to set rgb layer indication by default, and save the default valued. 466And lastly, you want to add the `eeconfig_init_user` function, so that when the EEPROM is reset, you can specify default values, and even custom actions. To force an EEPROM reset, use the `EEP_RST` keycode or [Bootmagic](feature_bootmagic.md) functionallity. For example, if you want to set rgb layer indication by default, and save the default valued.
442 467
443```c 468```c
444void eeconfig_init_user(void) { // EEPROM is getting reset! 469void eeconfig_init_user(void) { // EEPROM is getting reset!
445 user_config.raw = 0; 470 user_config.raw = 0;
446 user_config.rgb_layer_change = true; // We want this enabled by default 471 user_config.rgb_layer_change = true; // We want this enabled by default
447 eeconfig_update_user(user_config.raw); // Write default value to EEPROM now 472 eeconfig_update_user(user_config.raw); // Write default value to EEPROM now
@@ -466,7 +491,7 @@ The `val` is the value of the data that you want to write to EEPROM. And the `e
466 491
467By default, the tapping term is defined globally, and is not configurable by key. For most users, this is perfectly fine. But in come cases, dual function keys would be greatly improved by different timeouts than `LT` keys, or because some keys may be easier to hold than others. Instead of using custom key codes for each, this allows for per key configurable `TAPPING_TERM`. 492By default, the tapping term is defined globally, and is not configurable by key. For most users, this is perfectly fine. But in come cases, dual function keys would be greatly improved by different timeouts than `LT` keys, or because some keys may be easier to hold than others. Instead of using custom key codes for each, this allows for per key configurable `TAPPING_TERM`.
468 493
469To enable this functionality, you need to add `#define TAPPING_TERM_PER_KEY` to your `config.h`, first. 494To enable this functionality, you need to add `#define TAPPING_TERM_PER_KEY` to your `config.h`, first.
470 495
471 496
472## Example `get_tapping_term` Implementation 497## Example `get_tapping_term` Implementation