diff --git a/keyboards/massdrop/alt/alt.c b/keyboards/massdrop/alt/alt.c new file mode 100644 index 000000000000..0529fe288908 --- /dev/null +++ b/keyboards/massdrop/alt/alt.c @@ -0,0 +1,21 @@ +#include "alt.h" + +void matrix_init_kb(void) { + // Define initial values for the RGB configuration. + rgb_matrix_config.hsv.h = RGB_MATRIX_STARTUP_HUE; + rgb_matrix_config.speed = RGB_MATRIX_STARTUP_SPD; + eeconfig_init_user(); +} + +#ifdef CONSOLE_ENABLE +bool process_record_kb(uint16_t keycode, keyrecord_t *record) { + // put your per-action keyboard code here + // runs for every action, just before processing by the firmware + + if (!record->event.pressed) { + dprintf("RGB: hue: %u, sat: %u, val: %u, spd: %u, mode: %u\n", rgb_matrix_config.hsv.h, rgb_matrix_config.hsv.s, rgb_matrix_config.hsv.v, rgb_matrix_config.speed, rgb_matrix_config.mode); + } + + return process_record_user(keycode, record); +} +#endif diff --git a/keyboards/massdrop/alt/config.h b/keyboards/massdrop/alt/config.h index d8389fc0093e..36ce7d56af95 100644 --- a/keyboards/massdrop/alt/config.h +++ b/keyboards/massdrop/alt/config.h @@ -124,4 +124,19 @@ along with this program. If not, see . #define RGB_MATRIX_LED_PROCESS_LIMIT 15 #define RGB_MATRIX_LED_FLUSH_LIMIT 10 +// Load our custom RGB by default +#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CUSTOM_RGB_CUSTOM + +#define RGB_MATRIX_STARTUP_HUE 136 // blue-magenta +#define RGB_MATRIX_STARTUP_SPD 48 + +#define RGB_MATRIX_UNDERGLOW_OFFSET_HUE 0-RGB_MATRIX_STARTUP_HUE // red-orange +#define RGB_MATRIX_UNDERGLOW_OFFSET_SPD 14-RGB_MATRIX_STARTUP_SPD + +#define RGB_MATRIX_REACTIVE_HIGHLIGHT {80, 255, 0} // GRB!!!! +#define RGB_MATRIX_REACTIVE_CROSS_SPEED 60 +#define RGB_MATRIX_REACTIVE_SIMPLE_SPEED 36 +// This effectively delays the fadout of the keys, max value 254 +#define RGB_MATRIX_REACTIVE_SIMPLE_THRESHOLD 100 + #include "config_led.h" diff --git a/keyboards/massdrop/alt/rgb_matrix_kb.inc b/keyboards/massdrop/alt/rgb_matrix_kb.inc new file mode 100644 index 000000000000..d4d208d2ebd0 --- /dev/null +++ b/keyboards/massdrop/alt/rgb_matrix_kb.inc @@ -0,0 +1,185 @@ +// !!! DO NOT ADD #pragma once !!! // + +// Step 1. +// Declare custom effects using the RGB_MATRIX_EFFECT macro +// (note the lack of semicolon after the macro!) +RGB_MATRIX_EFFECT(RGB_CUSTOM) +RGB_MATRIX_EFFECT(RGB_CUSTOM_MULTICROSS) +RGB_MATRIX_EFFECT(RGB_CUSTOM_SOLID_REACTIVE_SIMPLE) +RGB_MATRIX_EFFECT(RGB_CUSTOM_CYCLE) + +// Step 2. +// Define effects inside the `RGB_MATRIX_CUSTOM_EFFECT_IMPLS` ifdef block +#ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS + +static uint8_t gradient_hue(uint8_t i) { + /* Calculate the custom gradient, and apply an offset gradient to the underglow. */ + + // The x range will be 0..224, map this to 0..7 + // Relies on hue being 8-bit and wrapping + uint8_t hue = rgb_matrix_config.hsv.h; + uint8_t speed = rgb_matrix_config.speed; + + if (HAS_FLAGS(g_led_config.flags[i], LED_FLAG_UNDERGLOW)) { + // Shift the underglow colour. + hue += RGB_MATRIX_UNDERGLOW_OFFSET_HUE; + speed += RGB_MATRIX_UNDERGLOW_OFFSET_SPD; + #ifdef RGB_MATRIX_BLEND_SQRT + uint8_t scale = scale8(64, speed); + return hue + (scale * g_led_config.point[i].x >> 5); + #endif + } + uint8_t scale = scale8(64, speed); + + #ifdef RGB_MATRIX_BLEND_SQRT + int16_t offset16 = g_led_config.point[i].x - 112; // -112 -> 112 + offset16 = offset16 * 112; + if (offset16 < 0) { + offset16 = -sqrt16(-offset16); + } else { + offset16 = sqrt16(offset16); + } + uint8_t offset = offset16 + 112; + return hue + (scale * offset >> 5); + #else + return hue + (scale * g_led_config.point[i].x >> 5); + #endif +} + +static bool RGB_CUSTOM(effect_params_t* params) { + RGB_MATRIX_USE_LIMITS(led_min, led_max); + + HSV hsv = rgb_matrix_config.hsv; + for (uint8_t i = led_min; i < led_max; i++) { + RGB_MATRIX_TEST_LED_FLAGS(); + + hsv.h = gradient_hue(i); + RGB rgb = hsv_to_rgb(hsv); + + rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); + } + return led_max < DRIVER_LED_TOTAL; +} + +static bool RGB_CUSTOM_CYCLE(effect_params_t* params) { + RGB_MATRIX_USE_LIMITS(led_min, led_max); + + HSV hsv = rgb_matrix_config.hsv; + for (uint8_t i = led_min; i < led_max; i++) { + RGB_MATRIX_TEST_LED_FLAGS(); + + hsv.h = gradient_hue(i); + hsv.h += scale16by8(g_rgb_counters.tick, rgb_matrix_config.speed / 24); + RGB rgb = hsv_to_rgb(hsv); + + rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); + } + return led_max < DRIVER_LED_TOTAL; +} + +typedef RGB (*custom_reactive_splash_f)(RGB rgb, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick); + +static bool custom_effect_runner_reactive_splash(uint8_t start, effect_params_t* params, custom_reactive_splash_f effect_func) { + RGB_MATRIX_USE_LIMITS(led_min, led_max); + + uint8_t count = g_last_hit_tracker.count; + for (uint8_t i = led_min; i < led_max; i++) { + RGB_MATRIX_TEST_LED_FLAGS(); + HSV hsv = rgb_matrix_config.hsv; + + // Calculate the base gradient colour. + hsv.h = gradient_hue(i); + RGB rgb = hsv_to_rgb(hsv); + + for (uint8_t j = start; j < count; j++) { + if (g_last_hit_tracker.tick[j] > 2000) continue; // Optimise for keys which are long-expired. + int16_t dx = g_led_config.point[i].x - g_last_hit_tracker.x[j]; + int16_t dy = g_led_config.point[i].y - g_last_hit_tracker.y[j]; + uint8_t dist = sqrt16(dx * dx + dy * dy); + uint16_t tick = scale16by8(g_last_hit_tracker.tick[j], RGB_MATRIX_REACTIVE_CROSS_SPEED); + rgb = effect_func(rgb, dx, dy, dist, tick); + } + + rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); + } + return led_max < DRIVER_LED_TOTAL; +} + +typedef RGB (*custom_reactive_f)(RGB rgb, uint16_t offset); + +static bool custom_effect_runner_reactive(effect_params_t* params, custom_reactive_f effect_func) { + RGB_MATRIX_USE_LIMITS(led_min, led_max); + + uint16_t max_tick = 65535 / RGB_MATRIX_REACTIVE_SIMPLE_SPEED; + for (uint8_t i = led_min; i < led_max; i++) { + RGB_MATRIX_TEST_LED_FLAGS(); + uint16_t tick = max_tick; + // Reverse search to find most recent key hit + for (int8_t j = g_last_hit_tracker.count - 1; j >= 0; j--) { + if (g_last_hit_tracker.index[j] == i && g_last_hit_tracker.tick[j] < tick) { + tick = g_last_hit_tracker.tick[j]; + break; + } + } + HSV hsv = rgb_matrix_config.hsv; + + // Calculate the base gradient colour + hsv.h = gradient_hue(i); + RGB rgb = hsv_to_rgb(hsv); + + uint16_t offset = scale16by8(tick, RGB_MATRIX_REACTIVE_SIMPLE_SPEED); + rgb = effect_func(rgb, offset); + rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); + } + return led_max < DRIVER_LED_TOTAL; +} + +static RGB rgb_sqrt_blend(RGB a, RGB b, uint8_t t) { + RGB rgb; + // Compress the effect so the highlight is more pronounced + t = t * t / 255; + // Blend RGB channels + rgb.r = sqrt16(scale16by8(a.r * a.r, (255 - t)) + scale16by8(b.r * b.r, t)); + rgb.g = sqrt16(scale16by8(a.g * a.g, (255 - t)) + scale16by8(b.g * b.g, t)); + rgb.b = sqrt16(scale16by8(a.b * a.b, (255 - t)) + scale16by8(b.b * b.b, t)); + + return rgb; +} + +static RGB CUSTOM_SOLID_REACTIVE_CROSS_math(RGB bg, int16_t dx, int16_t dy, uint8_t dist, uint16_t tick) { + uint16_t effect = tick - dist; + // effect = 0 fully highlighted, 255 fully faded + if (effect >= 255 || dist > 54) return bg; // effect size, default=72 + if ((dx > 8 || dx < -8) && (dy > 8 || dy < -8)) return bg; // effect spread, default=8 + + // if (rand()/RAND_MAX < 0.0001) dprintf("effect: %u\n", effect); + + // Blend highlight over the gradient colour + RGB fg = RGB_MATRIX_REACTIVE_HIGHLIGHT; + bg = rgb_sqrt_blend(fg, bg, effect); + return bg; +} + +static bool RGB_CUSTOM_MULTICROSS(effect_params_t* params) { + return custom_effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 12), // Use only the previous 12 key samples for performance + params, &CUSTOM_SOLID_REACTIVE_CROSS_math); +} + +static RGB CUSTOM_SOLID_REACTIVE_SIMPLE_math(RGB bg, uint16_t effect) { + // effect = 0 fully highlighted, 255 fully faded + if (effect >= 255) return bg; + + // Hold the effect after initial keypress for a short time + uint8_t shifted = qsub8(effect, RGB_MATRIX_REACTIVE_SIMPLE_THRESHOLD); + effect = shifted * 255 / (255 - RGB_MATRIX_REACTIVE_SIMPLE_THRESHOLD); + // if (rand()/RAND_MAX < 0.0001) dprintf("shifted: %u, effect: %u\n", shifted, effect); + + // Blend highlight over the gradient colour + RGB fg = RGB_MATRIX_REACTIVE_HIGHLIGHT; + bg = rgb_sqrt_blend(fg, bg, effect); + return bg; +} + +static bool RGB_CUSTOM_SOLID_REACTIVE_SIMPLE(effect_params_t* params) { return custom_effect_runner_reactive(params, &CUSTOM_SOLID_REACTIVE_SIMPLE_math); } + +#endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS diff --git a/keyboards/massdrop/alt/rules.mk b/keyboards/massdrop/alt/rules.mk index 3da2610f68fd..3cc333e96bcd 100644 --- a/keyboards/massdrop/alt/rules.mk +++ b/keyboards/massdrop/alt/rules.mk @@ -35,4 +35,7 @@ AUTO_SHIFT_ENABLE = no # Auto Shift # Custom RGB matrix handling RGB_MATRIX_ENABLE = custom +# Enable custom RGB effects +RGB_MATRIX_CUSTOM_KB = yes + LAYOUTS = 65_ansi_blocker