mirror of
https://github.com/openstenoproject/qmk
synced 2024-11-23 00:44:38 +00:00
Allow overriding of all functions in wonderland.c (#7198)
* f * Allow overriding of all functions in wonderland.c - needed for custom LED functions in keymap.c * Example of layer indication via LEDs optimize * Use newer led_update_kb and led_update_user hooks - these allow overriding without use of __attribute((weak))__ * Update led documentation a bit - clarify some of the wording around how to use led_update_user * Update led_update_user example * Update audio example to be complete * trailing spaces smh * spaces * spaces * smh * Less code is good * Update docs/custom_quantum_functions.md Co-Authored-By: fauxpark <fauxpark@gmail.com> * Update docs/custom_quantum_functions.md Co-Authored-By: fauxpark <fauxpark@gmail.com> * Update docs/custom_quantum_functions.md Co-Authored-By: fauxpark <fauxpark@gmail.com> * Update docs/custom_quantum_functions.md Co-Authored-By: fauxpark <fauxpark@gmail.com> * Update docs/custom_quantum_functions.md Co-Authored-By: fauxpark <fauxpark@gmail.com> * Update docs/custom_quantum_functions.md Co-Authored-By: fauxpark <fauxpark@gmail.com>
This commit is contained in:
parent
0270d4d5a1
commit
e62ab7e259
3 changed files with 72 additions and 52 deletions
|
@ -114,7 +114,15 @@ Two more deprecated functions exist that provide the LED state as a `uint8_t`:
|
||||||
|
|
||||||
This function will be called when the state of one of those 5 LEDs changes. It receives the LED state as a struct parameter.
|
This function will be called when the state of one of those 5 LEDs changes. It receives the LED state as a struct parameter.
|
||||||
|
|
||||||
You must return either `true` or `false` from this function, depending on whether you want to override the keyboard-level implementation.
|
By convention, return `true` from `led_update_user()` to get the `led_update_kb()` hook to run its code, and
|
||||||
|
return `false` when you would prefer not to run the code in `led_update_kb()`.
|
||||||
|
|
||||||
|
Some examples include:
|
||||||
|
|
||||||
|
- overriding the LEDs to use them for something else like layer indication
|
||||||
|
- return `false` because you do not want the `_kb()` function to run, as it would override your layer behavior.
|
||||||
|
- play a sound when an LED turns on or off.
|
||||||
|
- return `true` because you want the `_kb` function to run, and this is in addition to the default LED behavior.
|
||||||
|
|
||||||
?> 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.
|
?> 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.
|
||||||
|
|
||||||
|
@ -122,7 +130,8 @@ You must return either `true` or `false` from this function, depending on whethe
|
||||||
|
|
||||||
```c
|
```c
|
||||||
bool led_update_kb(led_t led_state) {
|
bool led_update_kb(led_t led_state) {
|
||||||
if(led_update_user(led_state)) {
|
bool res = led_update_user(led_state);
|
||||||
|
if(res) {
|
||||||
if (led_state.num_lock) {
|
if (led_state.num_lock) {
|
||||||
writePinLow(B0);
|
writePinLow(B0);
|
||||||
} else {
|
} else {
|
||||||
|
@ -148,40 +157,29 @@ bool led_update_kb(led_t led_state) {
|
||||||
} else {
|
} else {
|
||||||
writePinHigh(B4);
|
writePinHigh(B4);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example `led_update_user()` Implementation
|
### Example `led_update_user()` Implementation
|
||||||
|
|
||||||
|
This 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.
|
||||||
|
|
||||||
```c
|
```c
|
||||||
|
#ifdef AUDIO_ENABLE
|
||||||
|
float caps_on[][2] = SONG(CAPS_LOCK_ON_SOUND);
|
||||||
|
float caps_off[][2] = SONG(CAPS_LOCK_OFF_SOUND);
|
||||||
|
#endif
|
||||||
|
|
||||||
bool led_update_user(led_t led_state) {
|
bool led_update_user(led_t led_state) {
|
||||||
if (led_state.num_lock) {
|
#ifdef AUDIO_ENABLE
|
||||||
writePinLow(B0);
|
static uint8_t caps_state = 0;
|
||||||
} else {
|
if (caps_state != led_state.caps_lock) {
|
||||||
writePinHigh(B0);
|
led_state.caps_lock ? PLAY_SONG(caps_on) : PLAY_SONG(caps_off);
|
||||||
}
|
caps_state = led_state.caps_lock;
|
||||||
if (led_state.caps_lock) {
|
|
||||||
writePinLow(B1);
|
|
||||||
} else {
|
|
||||||
writePinHigh(B1);
|
|
||||||
}
|
|
||||||
if (led_state.scroll_lock) {
|
|
||||||
writePinLow(B2);
|
|
||||||
} else {
|
|
||||||
writePinHigh(B2);
|
|
||||||
}
|
|
||||||
if (led_state.compose) {
|
|
||||||
writePinLow(B3);
|
|
||||||
} else {
|
|
||||||
writePinHigh(B3);
|
|
||||||
}
|
|
||||||
if (led_state.kana) {
|
|
||||||
writePinLow(B4);
|
|
||||||
} else {
|
|
||||||
writePinHigh(B4);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -411,7 +409,7 @@ void keyboard_post_init_user(void) {
|
||||||
// Set default layer, if enabled
|
// Set default layer, if enabled
|
||||||
if (user_config.rgb_layer_change) {
|
if (user_config.rgb_layer_change) {
|
||||||
rgblight_enable_noeeprom();
|
rgblight_enable_noeeprom();
|
||||||
rgblight_sethsv_noeeprom_cyan();
|
rgblight_sethsv_noeeprom_cyan();
|
||||||
rgblight_mode_noeeprom(1);
|
rgblight_mode_noeeprom(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -459,18 +457,18 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||||
}
|
}
|
||||||
return true; // Let QMK send the enter press/release events
|
return true; // Let QMK send the enter press/release events
|
||||||
case RGB_LYR: // This allows me to use underglow as layer indication, or as normal
|
case RGB_LYR: // This allows me to use underglow as layer indication, or as normal
|
||||||
if (record->event.pressed) {
|
if (record->event.pressed) {
|
||||||
user_config.rgb_layer_change ^= 1; // Toggles the status
|
user_config.rgb_layer_change ^= 1; // Toggles the status
|
||||||
eeconfig_update_user(user_config.raw); // Writes the new status to EEPROM
|
eeconfig_update_user(user_config.raw); // Writes the new status to EEPROM
|
||||||
if (user_config.rgb_layer_change) { // if layer state indication is enabled,
|
if (user_config.rgb_layer_change) { // if layer state indication is enabled,
|
||||||
layer_state_set(layer_state); // then immediately update the layer color
|
layer_state_set(layer_state); // then immediately update the layer color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false; break;
|
return false; break;
|
||||||
case RGB_MODE_FORWARD ... RGB_MODE_GRADIENT: // For any of the RGB codes (see quantum_keycodes.h, L400 for reference)
|
case RGB_MODE_FORWARD ... RGB_MODE_GRADIENT: // For any of the RGB codes (see quantum_keycodes.h, L400 for reference)
|
||||||
if (record->event.pressed) { //This disables layer indication, as it's assumed that if you're changing this ... you want that disabled
|
if (record->event.pressed) { //This disables layer indication, as it's assumed that if you're changing this ... you want that disabled
|
||||||
if (user_config.rgb_layer_change) { // only if this is enabled
|
if (user_config.rgb_layer_change) { // only if this is enabled
|
||||||
user_config.rgb_layer_change = false; // disable it, and
|
user_config.rgb_layer_change = false; // disable it, and
|
||||||
eeconfig_update_user(user_config.raw); // write the setings to EEPROM
|
eeconfig_update_user(user_config.raw); // write the setings to EEPROM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -483,7 +481,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||||
And 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.
|
And 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.
|
||||||
|
|
||||||
```c
|
```c
|
||||||
void eeconfig_init_user(void) { // EEPROM is getting reset!
|
void eeconfig_init_user(void) { // EEPROM is getting reset!
|
||||||
user_config.raw = 0;
|
user_config.raw = 0;
|
||||||
user_config.rgb_layer_change = true; // We want this enabled by default
|
user_config.rgb_layer_change = true; // We want this enabled by default
|
||||||
eeconfig_update_user(user_config.raw); // Write default value to EEPROM now
|
eeconfig_update_user(user_config.raw); // Write default value to EEPROM now
|
||||||
|
@ -508,7 +506,7 @@ The `val` is the value of the data that you want to write to EEPROM. And the `e
|
||||||
|
|
||||||
By 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`.
|
By 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`.
|
||||||
|
|
||||||
To enable this functionality, you need to add `#define TAPPING_TERM_PER_KEY` to your `config.h`, first.
|
To enable this functionality, you need to add `#define TAPPING_TERM_PER_KEY` to your `config.h`, first.
|
||||||
|
|
||||||
|
|
||||||
## Example `get_tapping_term` Implementation
|
## Example `get_tapping_term` Implementation
|
||||||
|
|
|
@ -22,3 +22,33 @@ RGB_RMOD, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX
|
||||||
_______, KC_LALT, _______, _______, _______, KC_RALT, _______ \
|
_______, KC_LALT, _______, _______, _______, KC_RALT, _______ \
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef USE_LEDS_FOR_LAYERS
|
||||||
|
// example of how to use LEDs as layer indicators
|
||||||
|
static uint8_t top = 1;
|
||||||
|
static uint8_t middle = 0;
|
||||||
|
static uint8_t bottom = 0;
|
||||||
|
|
||||||
|
layer_state_t layer_state_set_user(layer_state_t state) {
|
||||||
|
top = middle = bottom = 0;
|
||||||
|
switch (get_highest_layer(state)) {
|
||||||
|
case _BASE:
|
||||||
|
top = 1;
|
||||||
|
break;
|
||||||
|
case _FUNC:
|
||||||
|
middle = 1;
|
||||||
|
break;
|
||||||
|
default: // for any other layers, or the default layer
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// override kb level function
|
||||||
|
bool led_update_user(led_t usb_led) {
|
||||||
|
writePin(B1, !top);
|
||||||
|
writePin(B2, !middle);
|
||||||
|
writePin(B3, !bottom);
|
||||||
|
return false; // we are using LEDs for something else override kb
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "wonderland.h"
|
#include "wonderland.h"
|
||||||
|
|
||||||
|
__attribute__ ((weak))
|
||||||
void matrix_init_kb(void) {
|
void matrix_init_kb(void) {
|
||||||
// put your keyboard start-up code here
|
// put your keyboard start-up code here
|
||||||
// runs once when the firmware starts up
|
// runs once when the firmware starts up
|
||||||
|
@ -7,12 +8,14 @@ void matrix_init_kb(void) {
|
||||||
led_init_ports();
|
led_init_ports();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
__attribute__ ((weak))
|
||||||
void matrix_scan_kb(void) {
|
void matrix_scan_kb(void) {
|
||||||
// put your looping keyboard code here
|
// put your looping keyboard code here
|
||||||
// runs every cycle (a lot)
|
// runs every cycle (a lot)
|
||||||
matrix_scan_user();
|
matrix_scan_user();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
__attribute__ ((weak))
|
||||||
void led_init_ports(void) {
|
void led_init_ports(void) {
|
||||||
// * Set our LED pins as output
|
// * Set our LED pins as output
|
||||||
setPinOutput(B1);
|
setPinOutput(B1);
|
||||||
|
@ -20,23 +23,12 @@ void led_init_ports(void) {
|
||||||
setPinOutput(B3);
|
setPinOutput(B3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void led_set_kb(uint8_t usb_led) {
|
bool led_update_kb(led_t led_state) {
|
||||||
if (IS_LED_ON(usb_led, USB_LED_NUM_LOCK)) {
|
bool runDefault = led_update_user(led_state);
|
||||||
writePinLow(B1);
|
if (runDefault) {
|
||||||
} else {
|
writePin(B1, !led_state.num_lock);
|
||||||
writePinHigh(B1);
|
writePin(B2, !led_state.caps_lock);
|
||||||
|
writePin(B3, !led_state.scroll_lock);
|
||||||
}
|
}
|
||||||
|
return runDefault;
|
||||||
if (IS_LED_ON(usb_led, USB_LED_CAPS_LOCK)) {
|
|
||||||
writePinLow(B2);
|
|
||||||
} else {
|
|
||||||
writePinHigh(B2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IS_LED_ON(usb_led, USB_LED_SCROLL_LOCK)) {
|
|
||||||
writePinLow(B3);
|
|
||||||
} else {
|
|
||||||
writePinHigh(B3);
|
|
||||||
}
|
|
||||||
led_set_user(usb_led);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue