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.md134
1 files changed, 71 insertions, 63 deletions
diff --git a/docs/custom_quantum_functions.md b/docs/custom_quantum_functions.md
index 2d505b075..9c8f89ae1 100644
--- a/docs/custom_quantum_functions.md
+++ b/docs/custom_quantum_functions.md
@@ -114,7 +114,15 @@ Two more deprecated functions exist that provide the LED state as a `uint8_t`:
114 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. 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 116
117You must return either `true` or `false` from this function, depending on whether you want to override the keyboard-level implementation. 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.
118 126
119?> 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. 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.
120 128
@@ -122,66 +130,41 @@ You must return either `true` or `false` from this function, depending on whethe
122 130
123```c 131```c
124bool led_update_kb(led_t led_state) { 132bool led_update_kb(led_t led_state) {
125 if(led_update_user(led_state)) { 133 bool res = led_update_user(led_state);
126 if (led_state.num_lock) { 134 if(res) {
127 writePinLow(B0); 135 // writePin sets the pin high for 1 and low for 0.
128 } else { 136 // In this example the pins are inverted, setting
129 writePinHigh(B0); 137 // it low/0 turns it on, and high/1 turns the LED off.
130 } 138 // This behavior depends on whether the LED is between the pin
131 if (led_state.caps_lock) { 139 // and VCC or the pin and GND.
132 writePinLow(B1); 140 writePin(B0, !led_state.num_lock);
133 } else { 141 writePin(B1, !led_state.caps_lock);
134 writePinHigh(B1); 142 writePin(B2, !led_state.scroll_lock);
135 } 143 writePin(B3, !led_state.compose);
136 if (led_state.scroll_lock) { 144 writePin(B4, !led_state.kana);
137 writePinLow(B2);
138 } else {
139 writePinHigh(B2);
140 }
141 if (led_state.compose) {
142 writePinLow(B3);
143 } else {
144 writePinHigh(B3);
145 }
146 if (led_state.kana) {
147 writePinLow(B4);
148 } else {
149 writePinHigh(B4);
150 }
151 return true;
152 } 145 }
146 return res;
153} 147}
154``` 148```
155 149
156### Example `led_update_user()` Implementation 150### Example `led_update_user()` Implementation
157 151
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.
153
158```c 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
159bool led_update_user(led_t led_state) { 160bool led_update_user(led_t led_state) {
160 if (led_state.num_lock) { 161 #ifdef AUDIO_ENABLE
161 writePinLow(B0); 162 static uint8_t caps_state = 0;
162 } else { 163 if (caps_state != led_state.caps_lock) {
163 writePinHigh(B0); 164 led_state.caps_lock ? PLAY_SONG(caps_on) : PLAY_SONG(caps_off);
164 } 165 caps_state = led_state.caps_lock;
165 if (led_state.caps_lock) {
166 writePinLow(B1);
167 } else {
168 writePinHigh(B1);
169 }
170 if (led_state.scroll_lock) {
171 writePinLow(B2);
172 } else {
173 writePinHigh(B2);
174 }
175 if (led_state.compose) {
176 writePinLow(B3);
177 } else {
178 writePinHigh(B3);
179 }
180 if (led_state.kana) {
181 writePinLow(B4);
182 } else {
183 writePinHigh(B4);
184 } 166 }
167 #endif
185 return true; 168 return true;
186} 169}
187``` 170```
@@ -411,7 +394,7 @@ void keyboard_post_init_user(void) {
411 // Set default layer, if enabled 394 // Set default layer, if enabled
412 if (user_config.rgb_layer_change) { 395 if (user_config.rgb_layer_change) {
413 rgblight_enable_noeeprom(); 396 rgblight_enable_noeeprom();
414 rgblight_sethsv_noeeprom_cyan(); 397 rgblight_sethsv_noeeprom_cyan();
415 rgblight_mode_noeeprom(1); 398 rgblight_mode_noeeprom(1);
416 } 399 }
417} 400}
@@ -459,18 +442,18 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
459 } 442 }
460 return true; // Let QMK send the enter press/release events 443 return true; // Let QMK send the enter press/release events
461 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
462 if (record->event.pressed) { 445 if (record->event.pressed) {
463 user_config.rgb_layer_change ^= 1; // Toggles the status 446 user_config.rgb_layer_change ^= 1; // Toggles the status
464 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
465 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,
466 layer_state_set(layer_state); // then immediately update the layer color 449 layer_state_set(layer_state); // then immediately update the layer color
467 } 450 }
468 } 451 }
469 return false; break; 452 return false; break;
470 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)
471 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
472 if (user_config.rgb_layer_change) { // only if this is enabled 455 if (user_config.rgb_layer_change) { // only if this is enabled
473 user_config.rgb_layer_change = false; // disable it, and 456 user_config.rgb_layer_change = false; // disable it, and
474 eeconfig_update_user(user_config.raw); // write the setings to EEPROM 457 eeconfig_update_user(user_config.raw); // write the setings to EEPROM
475 } 458 }
476 } 459 }
@@ -483,7 +466,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
483And 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.
484 467
485```c 468```c
486void eeconfig_init_user(void) { // EEPROM is getting reset! 469void eeconfig_init_user(void) { // EEPROM is getting reset!
487 user_config.raw = 0; 470 user_config.raw = 0;
488 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
489 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
@@ -506,14 +489,24 @@ The `val` is the value of the data that you want to write to EEPROM. And the `e
506 489
507# Custom Tapping Term 490# Custom Tapping Term
508 491
509By 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 and related options (such as `IGNORE_MOD_TAP_INTERRUPT`) are defined globally, and are not configurable by key. For most users, this is perfectly fine. But in some cases, dual function keys would be greatly improved by different timeout behaviors 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 timeout behaviors.
493
494There are two configurable options to control per-key timeout behaviors:
510 495
511To enable this functionality, you need to add `#define TAPPING_TERM_PER_KEY` to your `config.h`, first. 496- `TAPPING_TERM_PER_KEY`
497- `IGNORE_MOD_TAP_INTERRUPT_PER_KEY`
498
499You need to add `#define` lines to your `config.h` for each feature you want.
500
501```
502#define TAPPING_TERM_PER_KEY
503#define IGNORE_MOD_TAP_INTERRUPT_PER_KEY
504```
512 505
513 506
514## Example `get_tapping_term` Implementation 507## Example `get_tapping_term` Implementation
515 508
516To change the `TAPPING TERM` based on the keycode, you'd want to add something like the following to your `keymap.c` file: 509To change the `TAPPING_TERM` based on the keycode, you'd want to add something like the following to your `keymap.c` file:
517 510
518```c 511```c
519uint16_t get_tapping_term(uint16_t keycode) { 512uint16_t get_tapping_term(uint16_t keycode) {
@@ -528,6 +521,21 @@ uint16_t get_tapping_term(uint16_t keycode) {
528} 521}
529``` 522```
530 523
531### `get_tapping_term` Function Documentation 524## Example `get_ignore_mod_tap_interrupt` Implementation
525
526To change the `IGNORE_MOD_TAP_INTERRUPT` value based on the keycode, you'd want to add something like the following to your `keymap.c` file:
527
528```c
529bool get_ignore_mod_tap_interrupt(uint16_t keycode) {
530 switch (keycode) {
531 case SFT_T(KC_SPC):
532 return true;
533 default:
534 return false;
535 }
536}
537```
538
539## `get_tapping_term` / `get_ignore_mod_tap_interrupt` Function Documentation
532 540
533Unlike many of the other functions here, there isn't a need (or even reason) to have a quantum or keyboard level function. Only a user level function is useful here, so no need to mark it as such. 541Unlike many of the other functions here, there isn't a need (or even reason) to have a quantum or keyboard level function. Only user level functions are useful here, so no need to mark them as such.