After setting up my layer indicators, I wanted an easy way to turn on/off and cycle through two RGB matrix effects. The idea was to use plain solid light (RGB_MATRIX_SOLID_COLOR
) as a kind of keyboard backlighting and an RGB effect (RGB_MATRIX_CYCLE_LEFT_RIGHT
) for showing off, preferably using just one key to cycle through them. Here are two ways I tried.
Method 1: Use RGB_MOD
or RGB_RMOD
and disable unused effects
The RGB_MOD
and RGB_RMOD
keycodes to cycle between the animation effects. The only problem was that it cycles through all the enabled effects and they were all enabled by default. Fortunately, it's possible to control which effects are enabled.
Initially, all effects were enabled for my keyboard in keyboards/keebio/iris/rev6b/config.h
. There was a # define ENABLE_RGB_MATRIX_<effect name>
for each effect. So I commented out all effects except ENABLE_RGB_MATRIX_SOLID_COLOR
and ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
. However, RGB_MOD
would just cycle between the two effects. I needed a way to "turn off" the effect. I would create a custom effect for this1.
The "no animation" effect is similar to the RGB_MATRIX_SOLID_COLOR
effect. The only difference is the led are set to RGB_OFF
(or 0, 0, 0). I added RGB_MATRIX_CUSTOM_USER=yes
to my rules.mk
and created the file rgb_matrix_user.inc
with the following content to set up this effect:
RGB_MATRIX_EFFECT(no_light)
#ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
static bool no_light(effect_params_t* params) {
RGB_MATRIX_USE_LIMITS(led_min, led_max);
for (uint8_t i = led_min; i < led_max; i++) {
rgb_matrix_set_color(i, RGB_OFF);
}
return rgb_matrix_check_finished_leds(led_max);
}
#endif
The first method required me to edit the keyboard's config.h
to disable the unwanted effects. This didn't seem ideal to me as the file may change as QMK evolves (and, thus, I would need to merge the new changes with mine). On my second try, I use a custom keycode to cycle between just the three effects.
Method 2: Write code to cycle to the next animation in my keymap.c
In this method, a custom keycode is added to cycle between the three effects. I started by adding a function to my keycode.c
to transition to the next effect:
// Transition to the next RGB matrix mode.
void next_light_mode(void) {
switch(rgb_matrix_get_mode()) {
case RGB_MATRIX_NONE:
rgb_matrix_mode(RGB_MATRIX_SOLID_COLOR);
break;
case RGB_MATRIX_SOLID_COLOR:
rgb_matrix_mode(RGB_MATRIX_CYCLE_LEFT_RIGHT);
break;
default:
rgb_matrix_mode(RGB_MATRIX_CUSTOM_no_light);
break;
}
}
Notice the RGB_MATRIX_CUSTOM_no_light
animation. This is the same as the one from the above method2.
The next step is to assign a key. I used a custom keycode for this in keymap.c
(called LIGHT
):
enum custom_keycodes {
LAYOUT = SAFE_RANGE,
LIGHT,
...
};
After then assigning the keycode to a key, update process_record_user
to call next_light_mode
when the key is pressed:
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
// ... (removed for brevity)
case LIGHT:
if (record->event.pressed) {
next_light_mode();
}
return false;
// ...
}
}
The switch
implementation in this method isn't perfect. If the keyboard happens to be at one of the other effects (possible if you have RGB_MOD
somewhere), then the keyboard will go to the custom "no effect" next. But this is still good enough for my purposes.
Conclusion
After trying both methods, I am using the second method. The second method produces a larger firmware because of the additional effects (23,416 bytes vs 27,622 bytes) but still fits. There have also been times where still being able to use RGB_MOD
to access other effects has been handy. If you're curious, here's a video of this transition in action:
Notes
- There is also the
RBG_TOG
keycode which toggles the RBG lighting on and off. Unfortunately, this wasn't going to work for me because I was using lights for layer indicators - the key was also toggling them! - I first tried using
RGB_MATRIX_NONE
but this didn't work. The keyboard cycled between only theRGB_MATRIX_SOLID_COLOR
andRGB_MATRIX_CYCLE_LEFT_RIGHT
. It never turned off! Turns outRGB_MATRIX_NONE
doesn't mean "no animation". See this issue.