RGB keycodes RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, and RGB_VAD allow me to increment or decrement hue, saturation, and value on my RGB underglow lights. But I wanted to be able to hold down a key to change the color continually. So I made these changes:
In config.h:
#ifdef RGBLIGHT_ENABLE
#define RGBLIGHT_HUE_STEP 1
#define RGBLIGHT_SAT_STEP 1
#define RGBLIGHT_VAL_STEP 1
#endif
And then in keymap.c I made the custom keycodes:
enum custom_keycodes {
KC_HUI = SAFE_RANGE,
KC_HUD,
KC_SAI,
KC_SAD,
KC_VAI,
KC_VAD
};
And defined some variables:
// flags. 0 = no change, 1 = increment, -1 = decrement.
int8_t change_hue = 0;
int8_t change_saturation = 0;
int8_t change_value = 0;
// timers to control color change speed
uint16_t hue_timer = 0;
uint16_t saturation_timer = 0;
uint16_t value_timer = 0;
// seconds it takes to cycle through 0-255 or back
// technically 1 = 1.024 seconds, yielding even multiples of 4ms per tick (1024 / 256).
const int8_t hue_seconds = 5;
const int8_t saturation_seconds = 5;
const int8_t value_seconds = 5;
Then I use the keycodes to set the flags and timers:
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case KC_HUI:
if (record->event.pressed) {
hue_timer = timer_read();
change_hue = 1;
} else {
change_hue = 0;
}
break;
case KC_HUD:
if (record->event.pressed) {
hue_timer = timer_read();
change_hue = -1;
} else {
change_hue = 0;
}
break;
case KC_SAI:
if (record->event.pressed) {
saturation_timer = timer_read();
change_saturation = 1;
} else {
change_saturation = 0;
}
break;
case KC_SAD:
if (record->event.pressed) {
saturation_timer = timer_read();
change_saturation = -1;
} else {
change_saturation = 0;
}
break;
case KC_VAI:
if (record->event.pressed) {
value_timer = timer_read();
change_value = 1;
} else {
change_value = 0;
}
break;
case KC_VAD:
if (record->event.pressed) {
value_timer = timer_read();
change_value = -1;
} else {
change_value = 0;
}
break;
}
return true;
}
Then I use a matrix scan to change the color using those flags and timers:
void matrix_scan_user(void) {
switch (change_hue) {
case 0:
break;
case 1:
if (timer_elapsed(hue_timer) > (hue_seconds * 4)) {
hue_timer = timer_read();
rgblight_increase_hue();
}
break;
case -1:
if (timer_elapsed(hue_timer) > (hue_seconds * 4)) {
hue_timer = timer_read();
rgblight_decrease_hue();
}
break;
}
switch (change_saturation) {
case 0:
break;
case 1:
if (timer_elapsed(saturation_timer) > (saturation_seconds * 4)) {
saturation_timer = timer_read();
rgblight_increase_sat();
}
break;
case -1:
if (timer_elapsed(saturation_timer) > (saturation_seconds * 4)) {
saturation_timer = timer_read();
rgblight_decrease_sat();
}
break;
}
switch (change_value) {
case 0:
break;
case 1:
if (timer_elapsed(value_timer) > (value_seconds * 4)) {
value_timer = timer_read();
rgblight_increase_val();
}
break;
case -1:
if (timer_elapsed(value_timer) > (value_seconds * 4)) {
value_timer = timer_read();
rgblight_decrease_val();
}
break;
}
}
According to the docs, each of those should wrap around at the max/min hue/saturation/value, respectively.
- That seems to work exactly as expected with
KC_HUIandKC_HUD: If I hold the key down long enough it rounds the bend and hue just keeps on cycling through. KC_SAI,KC_VAI, andKC_VADwork at least normal-ish. I can increase saturation or value to the max and it will just stop there, and likewise if I decrement the value it stops at zero.KC_SADis the problem. When I hold it down long enough (just past white), the keyboard bombs out. It turns a weird orange color and nothing works.
For reference, here is the GitHub commit where I made all the changes, along with the rest of my code of course.
- Any idea why
KC_SADwould bomb out rather than either stopping or wrapping around? - Any idea why both saturation and value just stop, rather than wrapping around as I'd expect based on my read of the docs?
- Might I do better to try this whole thing a different way (question to more seasoned users)?
This is a really nice bit of functionality!
"bomb out"behavior that you are seeing onKC_SAD.rgblight_increase_sat_noeeprom()to adjust the saturation (and its counterparts for hue / saturation, and for decrease). Then when you release the key, only then should you write the current HSV setting to EEPROM (usingrgblight_sethsv()to set the final value into EEPROM.