commit e9e578aa121be5a3ebd16feaab6715dd03e993b6
parent a1d7185135dcaa41cc914855e68f60cb4e27da21
Author: Jack Sangdahl <jack@pngu.org>
Date: Wed, 17 Sep 2025 21:36:43 -0600
Update layout and add RGB Matrix fadeout functionality
Diffstat:
7 files changed, 156 insertions(+), 20 deletions(-)
diff --git a/users/jack/config.h b/users/jack/config.h
@@ -35,8 +35,7 @@
#endif
#ifdef RGB_MATRIX_ENABLE
-#define RGB_MATRIX_SLEEP
-#define RGB_MATRIX_TIMEOUT 300000
+#define RGB_MATRIX_FADE_TIMEOUT 180000
#define RGB_MATRIX_KEYPRESSES
#define PALETTEFX_ENABLE_ALL_EFFECTS
#define PALETTEFX_ENABLE_ALL_PALETTES
diff --git a/users/jack/jack.c b/users/jack/jack.c
@@ -3,7 +3,12 @@
#include "jack.h"
__attribute__((weak)) void housekeeping_task_keymap(void) {}
-void housekeeping_task_user(void) { housekeeping_task_keymap(); }
+void housekeeping_task_user(void) {
+#ifdef RGB_MATRIX_ENABLE
+ housekeeping_task_rgb_matrix();
+#endif
+ housekeeping_task_keymap();
+}
__attribute__((weak)) void keyboard_post_init_keymap(void) {}
void keyboard_post_init_user(void) {
@@ -12,6 +17,9 @@ void keyboard_post_init_user(void) {
rgblight_sethsv_noeeprom(HSV_CYAN);
rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT);
#endif
+#ifdef RGB_MATRIX_ENABLE
+ keyboard_post_init_rgb_matrix();
+#endif
#ifdef AUTOCORRECT_ENABLE
if (!autocorrect_is_enabled())
autocorrect_enable();
diff --git a/users/jack/jack.h b/users/jack/jack.h
@@ -27,13 +27,23 @@ enum combos {
};
#undef CMB
+#ifdef UNICODE_COMMON_ENABLE
bool process_record_unicode(uint16_t keycode, keyrecord_t *record);
+#endif
+
+#ifdef RGB_MATRIX_ENABLE
+void housekeeping_task_rgb_matrix(void);
+void keyboard_post_init_rgb_matrix(void);
+bool process_record_rgb_matrix(uint16_t keycode, keyrecord_t *record);
+#endif
#ifdef TAP_DANCE_ENABLE
void em_dash_mins(tap_dance_state_t *state, void *user_data);
void ply_nxt_prv(tap_dance_state_t *state, void *user_data);
#endif
+#ifdef OLED_ENABLE
+bool oled_task_keymap(void);
void oled_timer_reset(void);
void render_wpm_graph(void);
void render_felix_dog(void);
@@ -41,11 +51,11 @@ void render_layer_anim(void);
void render_layer_status(void);
void render_mod_status(void);
void render_wpm(void);
+#endif
void keyboard_pre_init_keymap(void);
void keyboard_post_init_keymap(void);
void housekeeping_task_keymap(void);
-bool oled_task_keymap(void);
#ifdef RGB_MATRIX_ENABLE
#define XRGB_TOG RM_TOGG
diff --git a/users/jack/rgb_matrix.c b/users/jack/rgb_matrix.c
@@ -0,0 +1,105 @@
+// Copyright 2025 jack@pngu.org
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include "jack.h"
+#include <lib/lib8tion/lib8tion.h>
+
+#define FADE_TRANSITION 500
+#define FRAME_PERIOD 16
+
+enum {
+ ANIM_SLEEP,
+ ANIM_WAKE,
+ ANIM_TIME_SCALE_Q6 = (255 * 64 + FADE_TRANSITION / 2) / FADE_TRANSITION
+};
+
+static bool illuminated = false;
+static uint8_t anim_start_value = 0;
+static uint8_t anim_end_value = 0;
+static uint8_t anim_type = ANIM_SLEEP;
+static uint8_t awake_value = 0;
+static uint16_t anim_update_time = 0;
+static uint16_t anim_start_time = 0;
+static uint32_t sleep_time = 0;
+
+static uint8_t read_curr_value(void) {
+ return rgb_matrix_is_enabled() ? rgb_matrix_get_val() : 0;
+}
+
+static void update_curr_value(uint8_t value) {
+ if (value > 0 && !rgb_matrix_is_enabled())
+ rgb_matrix_enable_noeeprom();
+ hsv_t hsv = rgb_matrix_get_hsv();
+ hsv.v = value;
+ rgb_matrix_sethsv_noeeprom(hsv.h, hsv.s, hsv.v);
+}
+
+static void update_sleep_timer(void) {
+ sleep_time = (timer_read32() + UINT32_C(RGB_MATRIX_FADE_TIMEOUT)) | 1;
+}
+
+static void anim_play(uint8_t type, uint8_t end_value) {
+ const uint8_t start_value = read_curr_value();
+ if (start_value != end_value) {
+ anim_start_time = timer_read() | 1;
+ anim_update_time = anim_start_time;
+ anim_start_value = start_value;
+ anim_end_value = end_value;
+ anim_type = type;
+ illuminated = true;
+ }
+}
+
+void housekeeping_task_rgb_matrix(void) {
+ if (!illuminated)
+ return;
+ if (anim_start_time) {
+ const uint16_t curr_time = timer_read();
+ if (timer_expired(curr_time, anim_update_time)) {
+ uint8_t value;
+ const uint16_t elapsed_time = curr_time - anim_start_time;
+ const uint8_t t =
+ elapsed_time <= FADE_TRANSITION
+ ? (((uint16_t)elapsed_time * ANIM_TIME_SCALE_Q6) >> 6)
+ : UINT8_MAX;
+ const uint8_t weight = ease8InOutCubic(t);
+ if (weight < UINT8_MAX) {
+ value = lerp8by8(anim_start_value, anim_end_value, weight);
+ anim_update_time = curr_time + FRAME_PERIOD;
+ } else {
+ anim_start_time = 0;
+ value = anim_end_value;
+ switch (anim_type) {
+ case ANIM_SLEEP:
+ illuminated = false;
+ break;
+ case ANIM_WAKE:
+ update_sleep_timer();
+ break;
+ }
+ }
+ update_curr_value(value);
+ }
+ } else if (sleep_time && timer_expired32(timer_read32(), sleep_time)) {
+ awake_value = read_curr_value();
+ anim_play(ANIM_SLEEP, 0);
+ }
+}
+
+void keyboard_post_init_rgb_matrix(void) {
+ if (rgb_matrix_is_enabled()) {
+ awake_value = rgb_matrix_get_val();
+ update_curr_value(0);
+ anim_play(ANIM_WAKE, awake_value);
+ }
+}
+
+bool process_record_rgb_matrix(uint16_t keycode, keyrecord_t *record) {
+ if (record->event.pressed)
+ if (awake_value > 0) {
+ if (!illuminated || (anim_start_time && !anim_end_value))
+ anim_play(ANIM_WAKE, awake_value);
+ else
+ update_sleep_timer();
+ }
+ return true;
+}
diff --git a/users/jack/rules.mk b/users/jack/rules.mk
@@ -26,7 +26,7 @@ ifeq ($(strip $(OLED_ENABLE)), yes)
endif
ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
- SRC += $(USER_PATH)/colour.c
+ SRC += $(USER_PATH)/colour.c $(USER_PATH)/rgb_matrix.c
endif
ifeq ($(strip $(UNICODE_COMMON)), yes)
diff --git a/users/jack/tapping.c b/users/jack/tapping.c
@@ -63,6 +63,10 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (!process_record_unicode(keycode, record))
return false;
#endif
+#ifdef RGB_MATRIX_ENABLE
+ if (!process_record_rgb_matrix(keycode, record))
+ return false;
+#endif
#ifdef OLED_ENABLE
if (record->event.pressed)
oled_timer_reset();
diff --git a/util/layout.svg b/util/layout.svg
@@ -117,8 +117,8 @@ text.footer {
paint-order: stroke;
}
-/* styling for combo tap, and key hold/shifted label text */
-text.combo, text.hold, text.shifted {
+/* styling for combo tap, and key non-tap label text */
+text.combo, text.hold, text.shifted, text.left, text.right {
font-size: 11px;
}
@@ -132,8 +132,20 @@ text.shifted {
dominant-baseline: hanging;
}
+text.left {
+ text-anchor: start;
+}
+
+text.right {
+ text-anchor: end;
+}
+
+text.layer-activator {
+ text-decoration: underline;
+}
+
/* styling for hold/shifted label text in combo box */
-text.combo.hold, text.combo.shifted {
+text.combo.hold, text.combo.shifted, text.combo.left, text.combo.right {
font-size: 8px;
}
@@ -163,7 +175,7 @@ path.combo {
/* End Tabler Icons Cleanup */
</style>
<g transform="translate(30, 0)" class="layer-BASE">
-<text x="0" y="28" class="label">BASE:</text>
+<text x="0" y="28" class="label" id="BASE">BASE:</text>
<g transform="translate(0, 56)">
<g transform="translate(28, 49)" class="key keypos-0">
<rect rx="6" ry="6" x="-26" y="-26" width="52" height="52" class="key"/>
@@ -296,9 +308,9 @@ path.combo {
<text x="0" y="0" class="key tap">/</text>
<text x="0" y="-24" class="key shifted">?</text>
</g>
-<g transform="translate(168, 205)" class="key ghost keypos-30">
-<rect rx="6" ry="6" x="-26" y="-26" width="52" height="52" class="key ghost"/>
-<text x="0" y="0" class="key ghost tap">../</text>
+<g transform="translate(168, 205)" class="key keypos-30">
+<rect rx="6" ry="6" x="-26" y="-26" width="52" height="52" class="key"/>
+<text x="0" y="0" class="key tap">../</text>
</g>
<g transform="translate(230, 213) rotate(15.0)" class="key held keypos-31">
<rect rx="6" ry="6" x="-26" y="-26" width="52" height="52" class="key held"/>
@@ -318,9 +330,9 @@ path.combo {
<use href="#mdi:content-paste" xlink:href="#mdi:content-paste" x="-7" y="-7" height="14" width="14.0" class="key held tap glyph mdi:content-paste"/>
<text x="0" y="24" class="key held hold">RSE</text>
</g>
-<g transform="translate(560, 205)" class="key ghost keypos-35">
-<rect rx="6" ry="6" x="-26" y="-26" width="52" height="52" class="key ghost"/>
-<use href="#mdi:play-pause" xlink:href="#mdi:play-pause" x="-7" y="-7" height="14" width="14.0" class="key ghost tap glyph mdi:play-pause"/>
+<g transform="translate(560, 205)" class="key keypos-35">
+<rect rx="6" ry="6" x="-26" y="-26" width="52" height="52" class="key"/>
+<use href="#mdi:play-pause" xlink:href="#mdi:play-pause" x="-7" y="-7" height="14" width="14.0" class="key tap glyph mdi:play-pause"/>
</g>
<g class="combo combopos-0">
<rect rx="6" ry="6" x="154" y="18" width="28" height="26" class="combo"/>
@@ -381,7 +393,7 @@ path.combo {
</g>
</g>
<g transform="translate(30, 331)" class="layer-LOWER">
-<text x="0" y="28" class="label">LOWER:</text>
+<text x="0" y="28" class="label" id="LOWER">LOWER:</text>
<g transform="translate(0, 56)">
<g transform="translate(28, 49)" class="key keypos-0">
<rect rx="6" ry="6" x="-26" y="-26" width="52" height="52" class="key"/>
@@ -477,9 +489,7 @@ path.combo {
</g>
<g transform="translate(196, 147)" class="key keypos-23">
<rect rx="6" ry="6" x="-26" y="-26" width="52" height="52" class="key"/>
-<text x="0" y="0" class="key tap">
-<tspan x="0" dy="-0.6em">Sel</tspan><tspan x="0" dy="1.2em">Wrd</tspan>
-</text>
+<text x="0" y="0" class="key tap">Remove</text>
</g>
<g transform="translate(252, 154)" class="key keypos-24">
<rect rx="6" ry="6" x="-26" y="-26" width="52" height="52" class="key"/>
@@ -533,7 +543,7 @@ path.combo {
</g>
</g>
<g transform="translate(30, 661)" class="layer-RAISE">
-<text x="0" y="28" class="label">RAISE:</text>
+<text x="0" y="28" class="label" id="RAISE">RAISE:</text>
<g transform="translate(0, 56)">
<g transform="translate(28, 49)" class="key keypos-0">
<rect rx="6" ry="6" x="-26" y="-26" width="52" height="52" class="key"/>