qmk_me

QMK Firmware userspace, keyboards, & keymaps
git clone git://git.pngu.org.org/qmk_me
Log | Files | Refs | Submodules | README | LICENSE

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:
Musers/jack/config.h | 3+--
Musers/jack/jack.c | 10+++++++++-
Musers/jack/jack.h | 12+++++++++++-
Ausers/jack/rgb_matrix.c | 105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Musers/jack/rules.mk | 2+-
Musers/jack/tapping.c | 4++++
Mutil/layout.svg | 40+++++++++++++++++++++++++---------------
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"/>