From 5d77108480f1b53a71f1574b9a19441befe2d236 Mon Sep 17 00:00:00 2001 From: Victor Toni Date: Sun, 29 Aug 2021 22:53:36 +0200 Subject: [PATCH 01/12] [Keymap] Add vitoni layout for GMMK Pro (ISO) Keymap has layered cursor keys similar to laptop keyboards. --- .../gmmk/pro/iso/keymaps/vitoni/keymap.c | 67 +++++++++++++++++++ .../gmmk/pro/iso/keymaps/vitoni/readme.adoc | 28 ++++++++ 2 files changed, 95 insertions(+) create mode 100644 keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c create mode 100644 keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c b/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c new file mode 100644 index 000000000000..e076c04dbf2d --- /dev/null +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c @@ -0,0 +1,67 @@ +// Copyright 2021 Glorious, LLC , +// Copyright 2021 Victor Toni (@vitoni) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include QMK_KEYBOARD_H + +enum layer_names { + _BASE, + _FN, + _MOV +}; + +// clang-format off +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + +// ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 Prt Rotary(Mute) +// ~ 1 2 3 4 5 6 7 8 9 0 - (=) BackSpc Del +// Tab Q W E R T Y U I O P [ ] PgUp +// Caps A S D F G H J K L ; " # Enter PgDn +// Sh_L / Z X C V B N M , . ? Sh_R Up End +// Ct_L Win_L Alt_L SPACE Alt_R FN Ct_R Left Down Right + + + // + // This keyboard defaults to 6KRO instead of NKRO for compatibility reasons (some KVMs and BIOSes are incompatible with NKRO). + // Since this is, among other things, a "gaming" keyboard, a key combination to enable NKRO on the fly is provided for convenience. + // Press Fn+N to toggle between 6KRO and NKRO. This setting is persisted to the EEPROM and thus persists between restarts. + [_BASE] = LAYOUT( + KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR, KC_MUTE, + KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL, + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_PGUP, + MO(_MOV), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT, KC_PGDN, + KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_END, + KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(_FN), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT + ), + + [_FN] = LAYOUT( + _______, KC_MYCM, KC_WHOM, KC_CALC, KC_MSEL, KC_MPRV, KC_MNXT, KC_MPLY, KC_MSTP, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, _______, + _______, RGB_TOG, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RESET, _______, + _______, _______, RGB_VAI, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, RGB_VAD, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, RGB_HUI, _______, _______, _______, NK_TOGG, _______, _______, _______, _______, _______, RGB_MOD, _______, + _______, _______, _______, _______, _______, _______, _______, RGB_SPD, RGB_RMOD, RGB_SPI + ), + + [_MOV] = LAYOUT( + RESET, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_INS, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_PGUP, _______, + _______, _______, _______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_END + ), + +}; +// clang-format on + +#if defined(ENCODER_ENABLE) +bool encoder_update_user(uint8_t index, bool clockwise) { + if (clockwise) { + tap_code(KC_VOLU); + } else { + tap_code(KC_VOLD); + } + return true; +} +#endif // ENCODER_ENABLE diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc b/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc new file mode 100644 index 000000000000..0cad49e69647 --- /dev/null +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc @@ -0,0 +1,28 @@ += ViToni's keymap for GMMK Pro ISO + +== Layout +Based on the stock layout but making use of CAPS as FN similar to laptop keyboards. +This frees up the left row for other uses (although not remapped yet). +Since both Delete and Insert are used for coding they are part of the CAPS layer as well. + +The differences are as follows: + +=== Layer 0 (`_BASE`) +Mostly stock + CAPS goes to layer `_MOV`. + +=== Layer 1 (`_FN`), accessed by pressing `FN` on layer `_BASE` +Stock. + +=== Layer 2 (`_MOV`), accessed by pressing `CAPS` on layer `_BASE` +[%header] +|=== +| Key / Action | Mapped to +| ESC | _RESET_ +| Delete | Insert +| Left | Home +| Right | End +| Up | PgUp +| Down | PgDn +|=== + +No other changes have been made. From 004d7b0053fda4d1e21565e3d4e1e2d650a883e9 Mon Sep 17 00:00:00 2001 From: Victor Toni Date: Thu, 9 Sep 2021 14:15:52 +0200 Subject: [PATCH 02/12] Configure RGB defaults for startup --- .../gmmk/pro/iso/keymaps/vitoni/config.h | 8 +++++++ .../gmmk/pro/iso/keymaps/vitoni/keymap.c | 21 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 keyboards/gmmk/pro/iso/keymaps/vitoni/config.h diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h b/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h new file mode 100644 index 000000000000..c7eb925374cc --- /dev/null +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h @@ -0,0 +1,8 @@ +// Copyright 2021 Victor Toni (@vitoni) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#if defined(RGB_MATRIX_ENABLE) + #define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_SOLID_COLOR +#endif diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c b/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c index e076c04dbf2d..f63748836333 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c @@ -65,3 +65,24 @@ bool encoder_update_user(uint8_t index, bool clockwise) { return true; } #endif // ENCODER_ENABLE + +#if defined(RGB_MATRIX_ENABLE) +/* +* Set up default RGB color. +*/ +void rgb_matrix_set_default_color(void) { + rgb_matrix_sethsv_noeeprom(HSV_CHARTREUSE); +} + +/* +* Set up RGB defaults. +*/ +void rgb_matrix_configure_default_settings(void) { + rgb_matrix_set_default_color(); +} + +void keyboard_post_init_user(void) { + rgb_matrix_enable_noeeprom(); + rgb_matrix_configure_default_settings(); +} +#endif // RGB_MATRIX_ENABLE From 7501530e4d1374098ab2ebf0dd9fc9b657a44632 Mon Sep 17 00:00:00 2001 From: Victor Toni Date: Fri, 10 Sep 2021 19:06:10 +0200 Subject: [PATCH 03/12] Configure encoder to change value/brightness on FN layer --- .../gmmk/pro/iso/keymaps/vitoni/keymap.c | 21 +++++++++++++++---- .../gmmk/pro/iso/keymaps/vitoni/readme.adoc | 9 +++++++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c b/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c index f63748836333..8b567f5be67d 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c @@ -57,10 +57,23 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { #if defined(ENCODER_ENABLE) bool encoder_update_user(uint8_t index, bool clockwise) { - if (clockwise) { - tap_code(KC_VOLU); - } else { - tap_code(KC_VOLD); + switch (get_highest_layer(layer_state)) { +#if defined(RGB_MATRIX_ENABLE) + case _FN: + if (clockwise) { + rgb_matrix_increase_val_noeeprom(); + } else { + rgb_matrix_decrease_val_noeeprom(); + } + break; +#endif // RGB_MATRIX_ENABLE + default: + if (clockwise) { + tap_code(KC_VOLU); + } else { + tap_code(KC_VOLD); + } + break; } return true; } diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc b/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc index 0cad49e69647..366321956724 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc @@ -11,7 +11,14 @@ The differences are as follows: Mostly stock + CAPS goes to layer `_MOV`. === Layer 1 (`_FN`), accessed by pressing `FN` on layer `_BASE` -Stock. +Mostly stock. + +[%header] +|=== +| Key / Action | Mapped to +| Knob clockwise | Value/Brightness up +| Knob anti-clockwise | Value/Brightness down +|=== === Layer 2 (`_MOV`), accessed by pressing `CAPS` on layer `_BASE` [%header] From 0f3f1bb4c3e730d4895eb97e7a5ce03e1d722296 Mon Sep 17 00:00:00 2001 From: Victor Toni Date: Thu, 16 Sep 2021 19:58:52 +0200 Subject: [PATCH 04/12] Remove FN layer and add dedicated RGB layer --- .../gmmk/pro/iso/keymaps/vitoni/keymap.c | 39 +++++++++------- .../gmmk/pro/iso/keymaps/vitoni/readme.adoc | 44 ++++++++++++++----- 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c b/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c index 8b567f5be67d..965df995a442 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c @@ -6,8 +6,8 @@ enum layer_names { _BASE, - _FN, - _MOV + _MOV, + _RGB }; // clang-format off @@ -24,42 +24,49 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { // // This keyboard defaults to 6KRO instead of NKRO for compatibility reasons (some KVMs and BIOSes are incompatible with NKRO). // Since this is, among other things, a "gaming" keyboard, a key combination to enable NKRO on the fly is provided for convenience. - // Press Fn+N to toggle between 6KRO and NKRO. This setting is persisted to the EEPROM and thus persists between restarts. + // Press CAPS+N to toggle between 6KRO and NKRO. This setting is persisted to the EEPROM and thus persists between restarts. [_BASE] = LAYOUT( KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR, KC_MUTE, KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL, KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_PGUP, MO(_MOV), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT, KC_PGDN, KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_END, - KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(_FN), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT - ), - - [_FN] = LAYOUT( - _______, KC_MYCM, KC_WHOM, KC_CALC, KC_MSEL, KC_MPRV, KC_MNXT, KC_MPLY, KC_MSTP, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, _______, - _______, RGB_TOG, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RESET, _______, - _______, _______, RGB_VAI, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, - _______, _______, RGB_VAD, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, - _______, _______, _______, RGB_HUI, _______, _______, _______, NK_TOGG, _______, _______, _______, _______, _______, RGB_MOD, _______, - _______, _______, _______, _______, _______, _______, _______, RGB_SPD, RGB_RMOD, RGB_SPI + KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(_RGB),KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT ), [_MOV] = LAYOUT( - RESET, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + RESET, KC_MYCM, KC_WHOM, KC_CALC, KC_MSEL, KC_MPRV, KC_MPLY, KC_MSTP, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_INS, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_PGUP, _______, + _______, _______, _______, _______, _______, _______, _______, NK_TOGG, _______, _______, _______, _______, _______, KC_PGUP, _______, _______, _______, _______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_END ), + [_RGB] = LAYOUT( + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RESET, RGB_MOD, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_RMOD, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_TOG, RGB_SPI, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, RGB_SAI, RGB_SPD, + _______, _______, _______, _______, _______, _______, _______, RGB_HUD, RGB_SAD, RGB_HUI + ), + }; // clang-format on #if defined(ENCODER_ENABLE) bool encoder_update_user(uint8_t index, bool clockwise) { switch (get_highest_layer(layer_state)) { + case _MOV: + if (clockwise) { + tap_code16(C(KC_TAB)); + } else { + tap_code16(S(C(KC_TAB))); + } + break; #if defined(RGB_MATRIX_ENABLE) - case _FN: + case _RGB: if (clockwise) { rgb_matrix_increase_val_noeeprom(); } else { diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc b/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc index 366321956724..0357696e98cf 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc @@ -10,21 +10,23 @@ The differences are as follows: === Layer 0 (`_BASE`) Mostly stock + CAPS goes to layer `_MOV`. -=== Layer 1 (`_FN`), accessed by pressing `FN` on layer `_BASE` -Mostly stock. - -[%header] -|=== -| Key / Action | Mapped to -| Knob clockwise | Value/Brightness up -| Knob anti-clockwise | Value/Brightness down -|=== - -=== Layer 2 (`_MOV`), accessed by pressing `CAPS` on layer `_BASE` +=== Layer 1 (`_MOV`), accessed by pressing `CAPS` on layer `_BASE` [%header] |=== | Key / Action | Mapped to | ESC | _RESET_ +| F1 | KC_MYCM +| F2 | KC_WHOM +| F3 | KC_CALC +| F4 | KC_MSEL +| F5 | KC_MPRV +| F6 | KC_MPLY +| F7 | KC_MSTP +| F8 | KC_MNXT +| F9 | KC_MUTE +| F10 | KC_VOLD +| F11 | KC_VOLU +| N | NK_TOGG | Delete | Insert | Left | Home | Right | End @@ -32,4 +34,24 @@ Mostly stock. | Down | PgDn |=== +=== Layer 2 (`_RGB`), accessed by pressing `FN` on layer `_BASE` +Revamped the stock FN layer to focus on RGB only. + +[%header] +|=== +| Key / Action | Mapped to +| Knob clockwise | Value/Brightness up +| Knob anti-clockwise | Value/Brightness down +| Backspace | _RESET_ +| Enter | RGB_TOG +| Del | RGB_MOD +| PgUp | RGB_RMOD +| PgDn | RGB_SPI +| End | RGB_SPD +| Left | RGB_HUD +| Right | RGB_HUI +| Up | RGB_SAI +| Down | RGB_SAD +|=== + No other changes have been made. From ff055d16c876778a92189b6fe7fc2afd66135d09 Mon Sep 17 00:00:00 2001 From: Victor Toni Date: Mon, 11 Oct 2021 13:07:52 +0200 Subject: [PATCH 05/12] Make RGB layer sticky (using TG) to avoid holding FN while configuring RGB --- keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c | 2 +- keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c b/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c index 965df995a442..dec91ab291cb 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c @@ -31,7 +31,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_PGUP, MO(_MOV), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT, KC_PGDN, KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, KC_END, - KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(_RGB),KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT + KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, TG(_RGB),KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT ), [_MOV] = LAYOUT( diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc b/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc index 0357696e98cf..941b05ac4234 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc @@ -9,6 +9,7 @@ The differences are as follows: === Layer 0 (`_BASE`) Mostly stock + CAPS goes to layer `_MOV`. +FN toggles the layer `_RGB`. === Layer 1 (`_MOV`), accessed by pressing `CAPS` on layer `_BASE` [%header] From 37d035220481b8fde298568aae48bb9b9cd99ef5 Mon Sep 17 00:00:00 2001 From: Victor Toni Date: Thu, 9 Sep 2021 16:00:18 +0200 Subject: [PATCH 06/12] Add RGB indicators for active layers --- keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c b/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c index dec91ab291cb..f1159bec4e1d 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c @@ -105,4 +105,22 @@ void keyboard_post_init_user(void) { rgb_matrix_enable_noeeprom(); rgb_matrix_configure_default_settings(); } + +/* +* Use RGB underglow to indicate specific layers. +*/ +layer_state_t layer_state_set_user(layer_state_t state) { + switch (get_highest_layer(state)) { + case _MOV: + rgb_matrix_sethsv_noeeprom(HSV_SPRINGGREEN); + break; + case _RGB: + rgb_matrix_sethsv_noeeprom(HSV_GREEN); + break; + default: // for any other layer + rgb_matrix_set_default_color(); + break; + } + return state; +} #endif // RGB_MATRIX_ENABLE From ace3a3eb972a962eac852d75f59775f4809198aa Mon Sep 17 00:00:00 2001 From: Victor Toni Date: Sun, 26 Sep 2021 17:06:08 +0200 Subject: [PATCH 07/12] Add RGB indicator for active RESET mode Signed-off-by: Victor Toni --- keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c b/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c index f1159bec4e1d..80106987f19d 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c @@ -123,4 +123,16 @@ layer_state_t layer_state_set_user(layer_state_t state) { } return state; } + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + case RESET: // when activating RESET mode for flashing + if (record->event.pressed) { + rgb_matrix_set_color_all(63, 0, 0); + rgb_matrix_driver.flush(); + } + return true; + } + return true; // Process all other keycodes normally +} #endif // RGB_MATRIX_ENABLE From a1db1307a1bea255c79dbf0ae5b8948f2415944d Mon Sep 17 00:00:00 2001 From: Victor Toni Date: Fri, 10 Sep 2021 19:01:27 +0200 Subject: [PATCH 08/12] Configure idle / USB suspend settings --- keyboards/gmmk/pro/iso/keymaps/vitoni/config.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h b/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h index c7eb925374cc..8e775851a41e 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h @@ -5,4 +5,7 @@ #if defined(RGB_MATRIX_ENABLE) #define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_SOLID_COLOR + // number of milliseconds to wait until turning off RGB automatically + #define RGB_DISABLE_TIMEOUT 300000 // 300 seconds / 5 min + #define RGB_DISABLE_WHEN_USB_SUSPENDED #endif From a8100787069368181a24da8c330843f376f51de3 Mon Sep 17 00:00:00 2001 From: Victor Toni Date: Fri, 10 Sep 2021 19:02:59 +0200 Subject: [PATCH 09/12] Add RGB fade in when resuming after suspend --- .../gmmk/pro/iso/keymaps/vitoni/config.h | 2 + .../gmmk/pro/iso/keymaps/vitoni/keymap.c | 16 +- .../gmmk/pro/iso/keymaps/vitoni/readme.adoc | 22 +++ users/vitoni/readme.adoc | 16 ++ users/vitoni/rgb_matrix_effects.c | 158 ++++++++++++++++++ users/vitoni/rgb_matrix_effects.h | 90 ++++++++++ users/vitoni/rules.mk | 4 + users/vitoni/utils.c | 96 +++++++++++ users/vitoni/utils.h | 67 ++++++++ users/vitoni/vitoni.c | 71 ++++++++ users/vitoni/vitoni.h | 30 ++++ 11 files changed, 569 insertions(+), 3 deletions(-) create mode 100644 users/vitoni/readme.adoc create mode 100644 users/vitoni/rgb_matrix_effects.c create mode 100644 users/vitoni/rgb_matrix_effects.h create mode 100644 users/vitoni/rules.mk create mode 100644 users/vitoni/utils.c create mode 100644 users/vitoni/utils.h create mode 100644 users/vitoni/vitoni.c create mode 100644 users/vitoni/vitoni.h diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h b/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h index 8e775851a41e..d34a239690fd 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h @@ -8,4 +8,6 @@ // number of milliseconds to wait until turning off RGB automatically #define RGB_DISABLE_TIMEOUT 300000 // 300 seconds / 5 min #define RGB_DISABLE_WHEN_USB_SUSPENDED + // fade in when we have been suspended + #define RGB_FADE_IN #endif diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c b/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c index 80106987f19d..d5b64c153ab7 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/keymap.c @@ -4,6 +4,8 @@ #include QMK_KEYBOARD_H +#include "vitoni.h" + enum layer_names { _BASE, _MOV, @@ -91,7 +93,7 @@ bool encoder_update_user(uint8_t index, bool clockwise) { * Set up default RGB color. */ void rgb_matrix_set_default_color(void) { - rgb_matrix_sethsv_noeeprom(HSV_CHARTREUSE); + rgb_matrix_sethsv_noeeprom_user(HSV_CHARTREUSE); } /* @@ -112,10 +114,10 @@ void keyboard_post_init_user(void) { layer_state_t layer_state_set_user(layer_state_t state) { switch (get_highest_layer(state)) { case _MOV: - rgb_matrix_sethsv_noeeprom(HSV_SPRINGGREEN); + rgb_matrix_sethsv_noeeprom_user(HSV_SPRINGGREEN); break; case _RGB: - rgb_matrix_sethsv_noeeprom(HSV_GREEN); + rgb_matrix_sethsv_noeeprom_user(HSV_GREEN); break; default: // for any other layer rgb_matrix_set_default_color(); @@ -124,7 +126,15 @@ layer_state_t layer_state_set_user(layer_state_t state) { return state; } +void matrix_scan_user(void) { + matrix_scan_user_rgb(); +} + bool process_record_user(uint16_t keycode, keyrecord_t *record) { + if (!process_record_user_rgb(keycode, record)) { + return false; + } + switch (keycode) { case RESET: // when activating RESET mode for flashing if (record->event.pressed) { diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc b/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc index 941b05ac4234..0775888c7f6a 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc @@ -56,3 +56,25 @@ Revamped the stock FN layer to focus on RGB only. |=== No other changes have been made. + +== RGB light + +The code customizing RGB light usage is decribed here: + +* link:../../../../../../users/vitoni/readme.adoc[/users/vitoni/readme.adoc] + +When using `RGB_DISABLE_TIMEOUT` addtional options are available: + +* `RGB_FADE_IN` makes the RGB lights fade in instead of setting the value/brightness to 100% (implicitly due to HSV including the brightness) when resuming after RGB lights have been turned off. +Fade in occurs when the keyboard is initialized and when the RGB brightness has been changed (e.g. suspending, fade out, etc.). + +Parameters used to define the behavior are: +[%header] +|=== +|Key | Default | Description + +| RGB_MATRIX_MAXIMUM_BRIGHTNESS +| 200 (<= UNIT8_MAX) +| Maximum assumed value for brightness. +Used to calculate lead time for fade out before suspend timeout. +|=== diff --git a/users/vitoni/readme.adoc b/users/vitoni/readme.adoc new file mode 100644 index 000000000000..69ccfa9e682b --- /dev/null +++ b/users/vitoni/readme.adoc @@ -0,0 +1,16 @@ += User functions + +Functions are mostly related to changing the RGB lights depending on user interaction and when idling. + +== utils.h + +Common functions are declared in link:utils.h[]. These function are not directly RGB related but used to modify state and calculate values. + +== rgb_matrix_effects.h + +Functions in link:rgb_matrix_effects.h[] make use of common function in `utils.h` and are used to create to RGB matrix effects such as fading. + +== vitoni.h + +The functions declared in link:vitoni.h[] are used as entry points for usage of RGB effects. +One entry point is `matrix_scan` based for regular task while the other is `process_record` based for user activity tasks. diff --git a/users/vitoni/rgb_matrix_effects.c b/users/vitoni/rgb_matrix_effects.c new file mode 100644 index 000000000000..42e3f25a043c --- /dev/null +++ b/users/vitoni/rgb_matrix_effects.c @@ -0,0 +1,158 @@ +// Copyright 2021 Victor Toni (@vitoni) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "rgb_matrix_effects.h" + +#include +#include + +#include "utils.h" + +/* + Offset used to start at the right point in th curve to avoid big jumps in brightness + 0 => 0% (signed) => 50% (unsigned) + 64 => 100% (signed) => 100% (unsigned) + 128 => 0% (signed) => 50% (unsigned) + 192 => -100% (signed) => 0% (unsigned) +*/ +enum PHASE { + PHASE_ZERO_RAISING + ,PHASE_HIGH + ,PHASE_ZERO_FALLING + ,PHASE_LOW +}; + +/** + * @brief Calculates the offset so that a specific time is aligned to a specific point in the sine curve. + * @param[in] time The time for which the offset shopuld be calculated. + * @param[in] phase Phase which should be reached with the offset + * @see PHASE + */ +uint8_t offset_for_time(const uint8_t time, const uint8_t phase) { + switch (phase) { + case PHASE_ZERO_RAISING: + return 0 - time; + case PHASE_HIGH: + return 64 - time; + case PHASE_ZERO_FALLING: + return 128 - time; + case PHASE_LOW: + return 192 - time; + default: + return 0; + } +} + +/** + * @brief Scales down `g_rgb_timer` so that it can be used for RGB effects. + * @return scaled down timer + * @see rgb_time_2_scale_w_factor() + */ +uint8_t rgb_time_2_scale(void) { + static const uint8_t factor = 1; + return rgb_time_2_scale_w_factor(factor); +} + +/* + * Used to slow down RGB speed. + */ +static const uint8_t rgb_speed_divisor = 8; + +/** + * @brief Scales down `g_rgb_timer` so that it can be used for RGB effects. + * @details Usually these calculations aredone internally by some RGB effects. + This method exposed to scaling so that all effects to have same timebase. If `rgb_matrix_config.speed` all effects are affected the same. + * @param[in] factor The factor can be used to speed up some operations in relation to others. + * @return scaled down timer taking into account the given factor + * @see g_rgb_timer + * @see rgb_matrix_config.speed + */ +uint8_t rgb_time_2_scale_w_factor(const uint8_t rgb_speed_factor) { + const uint8_t scaled_time = scale16by8(g_rgb_timer, rgb_matrix_config.speed * rgb_speed_factor / rgb_speed_divisor); + + return scaled_time; +} + +/** + * @brief Inverse function to calculate time required to execute `timer` steps. + * @details This method allows calculation of the time needed to execute N `timer`steps. + Usefull when using a scaled down time but requiring the time needed to perform these steps. + * @param[in] scaled_time scaled down timer to inverse to time + * @return time corresponding to scaled down time + * @see rgb_time_2_scale() + */ +uint16_t scale_2_rgb_time(const uint8_t scaled_time) { + const uint16_t time = scaled_time * rgb_speed_divisor * UINT8_MAX / rgb_matrix_config.speed; + + return time; +} + +bool fade_in_ranged(const uint8_t time, const uint8_t range_min, const uint8_t range_max) { + static const uint8_t max_delta = 1; + return scaled_sin_up(time, range_min, range_max, max_delta, &(rgb_matrix_config.hsv.v)); +} + +/** + * @brief Convenience method to eventually skip the value part when setting HSV. + * @details When setting HSV this includes the value/brightness. + As changing brightness might interfer with fading or breathing effects, + this method can skip the value part of HSV (depending on the preprocessor flag: RGB_FADE_IN). + * @param[in] hue Hue + * @param[in] sat Saturation + * @param[in] hue Value (brightness) + * @see rgb_matrix_sethsv_noeeprom() + */ +void rgb_matrix_sethsv_noeeprom_user(const uint16_t hue, const uint8_t sat, const uint8_t val) { +#if defined(RGB_FADE_IN) + rgb_matrix_config.hsv.h = hue; + rgb_matrix_config.hsv.s = sat; + // omitting setting the value to avoid interfering with effects +// rgb_matrix_config.hsv.v = val; +#else + rgb_matrix_sethsv_noeeprom(hue, sat, val); +#endif +} + +#if defined(RGB_FADE_IN) +/** + * @brief Calculates the time offset required by fade in. + * @details Using an arbitrary timer any point on the sine curve might be pointed to. + * The offest is calculated so that + * a) the point is at the lowest point in the curve and the curve is raising + * b) the point is near the current brightness (eg. fade in might be called while fading out and the lowest value has not yet been reached). + * @param[in] time Current time usually represented by (usually scaled) timer + * @return Offset required so that time matches the current brightness + */ +uint8_t calc_fade_in_offset(const uint8_t time) { + static const uint8_t max_steps = UINT8_MAX/2; + static const uint8_t range_min = 0; + static const uint8_t range_max = RGB_MATRIX_MAXIMUM_BRIGHTNESS; + + // start at the right point in the sine curve + uint8_t time_offset = offset_for_time(time, PHASE_LOW); + + // find the right offset to match the current brightness + for (int i = 1; i < max_steps; i++) { + const uint8_t value = scaled_sin(time + time_offset + 1, range_min, range_max); + if (in_range(value, range_min, range_max) && value < rgb_matrix_config.hsv.v) { + time_offset++; + } else { + break; + } + } + + return time_offset; +} + +/** + * @brief Increases value/brightness until reaching RGB_MATRIX_MAXIMUM_BRIGHTNESS based on given timer. + * @param[in] time A (usually scaled) timer + * @return Returns `true` if RGB_MATRIX_MAXIMUM_BRIGHTNESS has been reached, `false` otherwise. + */ +bool fade_in(const uint8_t time) { + static const uint8_t range_min = 0; + static const uint8_t range_max = RGB_MATRIX_MAXIMUM_BRIGHTNESS; + + return fade_in_ranged(time, range_min, range_max); +} +#endif diff --git a/users/vitoni/rgb_matrix_effects.h b/users/vitoni/rgb_matrix_effects.h new file mode 100644 index 000000000000..077614aab474 --- /dev/null +++ b/users/vitoni/rgb_matrix_effects.h @@ -0,0 +1,90 @@ +// Copyright 2021 Victor Toni (@vitoni) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +/** + * States reflecting the state of the keyboard. + * Dependeing on these states various effects can set for the RGB matrix. + */ +enum states { + REGULAR //!< when in regular use +#if defined(RGB_FADE_IN) + ,FADE_IN //!< when starting initially or before going back to REGULAR +#endif + ,SUSPENDED //!< expecting to be suspended by RGB_DISABLE_TIMEOUT any time +}; + +/** + * @brief Scales down `g_rgb_timer` so that it can be used for RGB effects. + * @details Usually these calculations aredone internally by some RGB effects. + This method exposed to scaling so that all effects to have same timebase. If `rgb_matrix_config.speed` all effects are affected the same. + * @param[in] factor The factor can be used to speed up some operations in relation to others. + * @return scaled down timer taking into account the given factor + * @see g_rgb_timer + * @see rgb_matrix_config.speed + */ +uint8_t rgb_time_2_scale_w_factor(const uint8_t factor); + +/** + * @brief Scales down `g_rgb_timer` so that it can be used for RGB effects. + * @return scaled down timer + * @see rgb_time_2_scale_w_factor() + */ +uint8_t rgb_time_2_scale(void); + +/** + * @brief Inverse function to calculate time required to execute `timer` steps. + * @details This method allows calculation of the time needed to execute N `timer`steps. + Usefull when using a scaled down time but requiring the time needed to perform these steps. + * @param[in] scaled_time scaled down timer to inverse to time + * @return time corresponding to scaled down time + * @see rgb_time_2_scale() + */ +uint16_t scale_2_rgb_time(const uint8_t scaled_time); + +/** + * @brief Convenience method to eventually skip the value part when setting HSV. + * @details When setting HSV this includes the value/brightness. + As changing brightness might interfer with fading or breathing effects, + this method can skip the value part of HSV (depending on the preprocessor flag: RGB_FADE_IN). + * @param[in] hue Hue + * @param[in] sat Saturation + * @param[in] hue Value (brightness) + * @see rgb_matrix_sethsv_noeeprom() + */ +void rgb_matrix_sethsv_noeeprom_user(const uint16_t hue, const uint8_t sat, const uint8_t val); + +#if defined(RGB_FADE_IN) +# if defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) +# if (RGB_MATRIX_MAXIMUM_BRIGHTNESS) < 1 +# error "RGB_MATRIX_MAXIMUM_BRIGHTNESS must not be less than ONE" +# endif +# if UINT8_MAX < (RGB_MATRIX_MAXIMUM_BRIGHTNESS) +# error "RGB_MATRIX_MAXIMUM_BRIGHTNESS must not be larger than UINT8_MAX" +# endif +# else +# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 +# endif + +/** + * @brief Calculates the time offset required by fade in. + * @details Using an arbitrary timer any point on the sine curve might be pointed to. + * The offset is calculated so that + * a) the point is at the lowest point in the curve and the curve is raising + * b) the point is near the current brightness (eg. fade in might be called while fading out and the lowest value has not yet been reached). + * @param[in] time Current time usually represented by a(usually scaled) timer + * @return Offset required so that time matches the current brightness + */ +uint8_t calc_fade_in_offset(const uint8_t time); + +/** + * @brief Increases value/brightness until reaching RGB_MATRIX_MAXIMUM_BRIGHTNESS based on given timer. + * @param[in] time A (usually scaled) timer + * @return Returns `true` if RGB_MATRIX_MAXIMUM_BRIGHTNESS has been reached, `false` otherwise. + */ +bool fade_in(const uint8_t time); +#endif diff --git a/users/vitoni/rules.mk b/users/vitoni/rules.mk new file mode 100644 index 000000000000..2f3b0d15e5da --- /dev/null +++ b/users/vitoni/rules.mk @@ -0,0 +1,4 @@ +SRC += \ + vitoni.c \ + utils.c \ + rgb_matrix_effects.c diff --git a/users/vitoni/utils.c b/users/vitoni/utils.c new file mode 100644 index 000000000000..0dbcfd5b4a1c --- /dev/null +++ b/users/vitoni/utils.c @@ -0,0 +1,96 @@ +// Copyright 2021 Victor Toni (@vitoni) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "utils.h" + +#include + +/** +* @brief Changes `*value` to `new_value`. +* @param[in,out] value Pointer to variable to be changed. +* @param[in] new_value Value to be changed. +* @param[in,out] changed Flag indicating `*value` and `new_value` were different. +*/ +void update_value(uint8_t *value, const uint8_t new_value, bool *changed) { + if (new_value != (*value)) { + (*changed) = true; + (*value) = new_value; + } +} + +/** +* @brief Checks whether a value is in the given range. +* @param[in] value Value to be checked. +* @param[in] range_min Lower bound of range (inclusive). +* @param[in] range_max Upper bound of range (inclusive). +* @return `true` if (range_min <= value <= range_max), `false` otherwise +*/ +bool in_range(const uint8_t value, const uint8_t range_min, const uint8_t range_max) { + return range_min <= value && value <= range_max; +} + +/** +* @brief Calculates the sine value based on sin8() and scales it to the given range (unsigned). +* +* Table of values for unscaled sin8() eg. a theta of 0 results to 128 and a theta of 255 (240+15) results to 125. + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +---------------------------------------------------------------- + 0: 128 131 134 137 140 143 146 149 152 155 158 161 164 167 170 173 + 16: 177 179 182 184 187 189 192 194 197 200 202 205 207 210 212 215 + 32: 218 219 221 223 224 226 228 229 231 233 234 236 238 239 241 243 + 48: 245 245 246 246 247 248 248 249 250 250 251 251 252 253 253 254 + 64: 255 254 253 253 252 251 251 250 250 249 248 248 247 246 246 245 + 80: 245 243 241 239 238 236 234 233 231 229 228 226 224 223 221 219 + 96: 218 215 212 210 207 205 202 200 197 194 192 189 187 184 182 179 + 112: 177 173 170 167 164 161 158 155 152 149 146 143 140 137 134 131 + 128: 128 125 122 119 116 113 110 107 104 101 98 95 92 89 86 83 + 144: 79 77 74 72 69 67 64 62 59 56 54 51 49 46 44 41 + 160: 38 37 35 33 32 30 28 27 25 23 22 20 18 17 15 13 + 176: 11 11 10 10 9 8 8 7 6 6 5 5 4 3 3 2 + 192: 1 2 3 3 4 5 5 6 6 7 8 8 9 10 10 11 + 208: 11 13 15 17 18 20 22 23 25 27 28 30 32 33 35 37 + 224: 38 41 44 46 49 51 54 56 59 62 64 67 69 72 74 77 + 240: 79 83 86 89 92 95 98 101 104 107 110 113 116 119 122 125 +* +* @param[in] theta Angle (a full circle mapped to 0-255) used as input for sine calculation. +* @param[in] range_min Lower bound of range (inclusive). +* @param[in] range_max Upper bound of range (inclusive). +* @return Calculated sine value mapped to the given range. +*/ +uint8_t scaled_sin(const uint8_t theta, const uint8_t range_min, const uint8_t range_max) { + const uint8_t range = range_max - range_min; + return scale8(sin8(theta), range) + range_min; +} + +/** +* @brief Increases the given value until reaching range_max. +* The increments occur following an upwards sine wave (scaled from range_min to range_max). +* @param[in] theta Angle (a full circle mapped to 0-255) used as input for sine calculation. +* @param[in] range_min Lower bound of range (inclusive). +* @param[in] range_max Upper bound of range (inclusive). +* @param[in] max_delta Maximum delta between value and range_max (due to values being integers and eventually not fully matching). +* @param[in,out] value Reference of variable to be increased +* @return `true` if value and range_max are within a delta of 3 (chosen by fair dice rolling), `false` otherwise +* @see scaled_sin() +*/ +bool scaled_sin_up(const uint8_t theta, const uint8_t range_min, const uint8_t range_max, const uint8_t max_delta, uint8_t *value) { + // ensure upper range bound + if (range_max <= (*value)) { + (*value) = range_max; + return true; + } + + const uint8_t new_value = scaled_sin(theta, range_min, range_max); + if (in_range(new_value, range_min, range_max) && (*value) < new_value) { + (*value) = new_value; + + return range_max == (*value); + } + + const uint8_t delta = range_max - (*value); + if (delta <= max_delta) { + (*value) = range_max; + } + + return delta <= max_delta; +} diff --git a/users/vitoni/utils.h b/users/vitoni/utils.h new file mode 100644 index 000000000000..8c2716c254f4 --- /dev/null +++ b/users/vitoni/utils.h @@ -0,0 +1,67 @@ +// Copyright 2021 Victor Toni (@vitoni) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +/** +* @brief Changes `*value` to `new_value`. +* @param[in,out] value Pointer to variable to be changed. +* @param[in] new_value Value to be changed. +* @param[in,out] changed Flag indicating `*value` and `new_value` were different. +*/ +void update_value(uint8_t *value, const uint8_t new_value, bool *changed); + +/** +* @brief Checks whether a value is in the given range. +* @param[in] value Value to be checked. +* @param[in] range_min Lower bound of range (inclusive). +* @param[in] range_max Upper bound of range (inclusive). +* @return `true` if (range_min <= value <= range_max), `false` otherwise +*/ +bool in_range(const uint8_t value, const uint8_t range_min, const uint8_t range_max); + +/** +* @brief Calculates the sine value based on sin8() and scales it to the given range (unsigned). +* +* Table of values for unscaled sin8() eg. a theta of 0 results to 128 and a theta of 255 (240+15) results to 125. + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +---------------------------------------------------------------- + 0: 128 131 134 137 140 143 146 149 152 155 158 161 164 167 170 173 + 16: 177 179 182 184 187 189 192 194 197 200 202 205 207 210 212 215 + 32: 218 219 221 223 224 226 228 229 231 233 234 236 238 239 241 243 + 48: 245 245 246 246 247 248 248 249 250 250 251 251 252 253 253 254 + 64: 255 254 253 253 252 251 251 250 250 249 248 248 247 246 246 245 + 80: 245 243 241 239 238 236 234 233 231 229 228 226 224 223 221 219 + 96: 218 215 212 210 207 205 202 200 197 194 192 189 187 184 182 179 + 112: 177 173 170 167 164 161 158 155 152 149 146 143 140 137 134 131 + 128: 128 125 122 119 116 113 110 107 104 101 98 95 92 89 86 83 + 144: 79 77 74 72 69 67 64 62 59 56 54 51 49 46 44 41 + 160: 38 37 35 33 32 30 28 27 25 23 22 20 18 17 15 13 + 176: 11 11 10 10 9 8 8 7 6 6 5 5 4 3 3 2 + 192: 1 2 3 3 4 5 5 6 6 7 8 8 9 10 10 11 + 208: 11 13 15 17 18 20 22 23 25 27 28 30 32 33 35 37 + 224: 38 41 44 46 49 51 54 56 59 62 64 67 69 72 74 77 + 240: 79 83 86 89 92 95 98 101 104 107 110 113 116 119 122 125 +* +* @param[in] theta Angle (a full circle mapped to 0-255) used as input for sine calculation. +* @param[in] range_min Lower bound of range (inclusive). +* @param[in] range_max Upper bound of range (inclusive). +* @return Calculated sine value mapped to the given range. +*/ +uint8_t scaled_sin(const uint8_t theta, const uint8_t range_min, const uint8_t range_max); + +/** +* @brief Increases the given value until reaching range_max. +* The increments occur following an upwards sine wave (scaled from range_min to range_max). +* @param[in] theta Angle (a full circle mapped to 0-255) used as input for sine calculation. +* @param[in] range_min Lower bound of range (inclusive). +* @param[in] range_max Upper bound of range (inclusive). +* @param[in] max_delta Maximum delta between value and range_max (due to values being integers and eventually not fully matching). +* @param[in,out] value Reference of variable to be increased +* @return `true` if value and range_max are within a delta of 3 (chosen by fair dice rolling), `false` otherwise +* @see scaled_sin() +*/ +bool scaled_sin_up(const uint8_t thea, const uint8_t range_min, const uint8_t range_max, const uint8_t max_delta, uint8_t *value); diff --git a/users/vitoni/vitoni.c b/users/vitoni/vitoni.c new file mode 100644 index 000000000000..4f26039120a1 --- /dev/null +++ b/users/vitoni/vitoni.c @@ -0,0 +1,71 @@ +// Copyright 2021 Victor Toni (@vitoni) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "vitoni.h" + +#include +#include + +#include "rgb_matrix_effects.h" +#include "utils.h" + +#if defined(RGB_FADE_IN) +static uint8_t state; + +// flag used to indicate that offset calculation is needed to adjust the timer, +// so that it matches the index used for sine calculation +static bool calc_offset; + +void matrix_scan_user_rgb(void) { + static uint8_t time_offset; + + const uint32_t inactivity_time = last_input_activity_elapsed(); + + // setting brightness to black as starting point for fade in + // for the time when returning from suspended state + if (RGB_DISABLE_TIMEOUT <= inactivity_time + 15) { + rgb_matrix_config.hsv.v = 0; + state = SUSPENDED; + } + + switch(state) { + case FADE_IN: + { + // since we want to be active, fade in should be faster than e.g. fading out + const uint8_t fade_in_time = rgb_time_2_scale_w_factor(4); + if (calc_offset) { + time_offset = calc_fade_in_offset(fade_in_time); + + // resetting flag for subsequent calls + calc_offset = false; + } + if (fade_in(fade_in_time + time_offset)) { + update_value(&state, REGULAR, &calc_offset); + } + } + break; + default: + break; + } +} + +bool process_record_user_rgb(const uint16_t keycode, const keyrecord_t *record) { + // if we are in a non regular state we might have faded out (eventually partially) + // so we restore brightness (to max as we don't keep track of manually changed brightness) + // if (REGULAR != state && FADE_IN != state) { + if (FADE_IN != state && REGULAR != state) { + update_value(&state, FADE_IN, &calc_offset); + } + + return true; // Process all other keycodes normally +} + +void suspend_wakeup_init_user(void) { + if (FADE_IN != state) { + // setting brightness to black as starting point for fade in + rgb_matrix_config.hsv.v = 0; + + update_value(&state, FADE_IN, &calc_offset); + } +} +#endif // defined(RGB_FADE_IN) diff --git a/users/vitoni/vitoni.h b/users/vitoni/vitoni.h new file mode 100644 index 000000000000..1f2603713570 --- /dev/null +++ b/users/vitoni/vitoni.h @@ -0,0 +1,30 @@ +// Copyright 2021 Victor Toni (@vitoni) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +#include + +#include "rgb_matrix_effects.h" + +/** + * @brief Executes periodic tasks, eg. fading or checking for upcoming supend. + * @details Function declaration as weak as the implementation might "disappear" depending on the RGB settings used. + * The weak declaration avoids having to change `keymap.c`. + */ +__attribute__((weak)) +void matrix_scan_user_rgb(void); + +/** + * @brief Executes tasks based on user activity, eg. fading in. + * @details Function declaration as weak as the implementation might "disappear" depending on the RGB settings used. + * The weak declaration avoids having to change `keymap.c`. + * @param[in] keycode + * @param[in] record + * @return `false` if further processing should be stopped, `true` otherwise + */ +__attribute__((weak)) +bool process_record_user_rgb(const uint16_t keycode, const keyrecord_t *record); From ab21c4dff4968e280e209d39e7bd4befcf335c75 Mon Sep 17 00:00:00 2001 From: Victor Toni Date: Mon, 25 Oct 2021 22:32:13 +0200 Subject: [PATCH 10/12] Add RGB fade out before suspend --- .../gmmk/pro/iso/keymaps/vitoni/config.h | 3 ++ .../gmmk/pro/iso/keymaps/vitoni/readme.adoc | 1 + users/vitoni/rgb_matrix_effects.c | 49 +++++++++++++++++++ users/vitoni/rgb_matrix_effects.h | 32 +++++++++++- users/vitoni/utils.c | 33 +++++++++++++ users/vitoni/utils.h | 13 +++++ users/vitoni/vitoni.c | 40 +++++++++++++-- 7 files changed, 166 insertions(+), 5 deletions(-) diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h b/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h index d34a239690fd..81afc46b7a06 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h @@ -7,6 +7,9 @@ #define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_SOLID_COLOR // number of milliseconds to wait until turning off RGB automatically #define RGB_DISABLE_TIMEOUT 300000 // 300 seconds / 5 min + // start fading out before getting disabled + // fading out is timed (depending on the rgb_matrix_config.speed) to have finished before reaching RGB_DISABLE_TIMEOUT + #define RGB_DISABLE_WITH_FADE_OUT #define RGB_DISABLE_WHEN_USB_SUSPENDED // fade in when we have been suspended #define RGB_FADE_IN diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc b/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc index 0775888c7f6a..558c97c83463 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc @@ -67,6 +67,7 @@ When using `RGB_DISABLE_TIMEOUT` addtional options are available: * `RGB_FADE_IN` makes the RGB lights fade in instead of setting the value/brightness to 100% (implicitly due to HSV including the brightness) when resuming after RGB lights have been turned off. Fade in occurs when the keyboard is initialized and when the RGB brightness has been changed (e.g. suspending, fade out, etc.). +* `RGB_DISABLE_WITH_FADE_OUT` activates fade out before the keyboard is disabled by `RGB_DISABLE_TIMEOUT`. Parameters used to define the behavior are: [%header] diff --git a/users/vitoni/rgb_matrix_effects.c b/users/vitoni/rgb_matrix_effects.c index 42e3f25a043c..d6b3d7140170 100644 --- a/users/vitoni/rgb_matrix_effects.c +++ b/users/vitoni/rgb_matrix_effects.c @@ -92,6 +92,11 @@ bool fade_in_ranged(const uint8_t time, const uint8_t range_min, const uint8_t r return scaled_sin_up(time, range_min, range_max, max_delta, &(rgb_matrix_config.hsv.v)); } +bool fade_out_ranged(const uint8_t time, const uint8_t range_min, const uint8_t range_max) { + static const uint8_t max_delta = 1; + return scaled_sin_down(time, range_min, range_max, max_delta, &(rgb_matrix_config.hsv.v)); +} + /** * @brief Convenience method to eventually skip the value part when setting HSV. * @details When setting HSV this includes the value/brightness. @@ -156,3 +161,47 @@ bool fade_in(const uint8_t time) { return fade_in_ranged(time, range_min, range_max); } #endif + +#if defined(RGB_DISABLE_WITH_FADE_OUT) + +/** + * @brief Calculates the time offset required by fade out. + * @details Using an arbitrary timer any point on the Sinus curve might be pointed to. + * The offest is calculated so that + * a) the point is at the highest point in the curve and the curve is failing + * b) the point is near the current brightness (eg. fade out might be called while on breath effect). + * @param[in] time Current time usually represented by a(usually scaled) timer + * @return Offset required so that time matches the current brightness + */ +uint8_t calc_fade_out_offset(const uint8_t time) { + static const uint8_t range_min = 0; + static const uint8_t range_max = RGB_MATRIX_MAXIMUM_BRIGHTNESS; + + // start at the right point in the sin() curve + uint8_t time_offset = offset_for_time(time, PHASE_HIGH); + + // find the right offset to match the current brightness + for (int i = 1; i < 127; i++) { + const uint8_t value = scaled_sin(time + time_offset + 1, range_min, range_max); + if (in_range(value, range_min, range_max) && rgb_matrix_config.hsv.v < value) { + time_offset++; + } else { + break; + } + } + + return time_offset; +} + +/** + * @brief Decreases value/brightness until reaching 0 based on given timer. + * @param[in] time A (usually scaled) timer + * @return Returns `true` if 0 has been reached, `false` otherwise. + */ +bool fade_out(const uint8_t time) { + static const uint8_t range_min = 0; + static const uint8_t range_max = RGB_MATRIX_MAXIMUM_BRIGHTNESS; + + return fade_out_ranged(time, range_min, range_max); +} +#endif diff --git a/users/vitoni/rgb_matrix_effects.h b/users/vitoni/rgb_matrix_effects.h index 077614aab474..157a062f682e 100644 --- a/users/vitoni/rgb_matrix_effects.h +++ b/users/vitoni/rgb_matrix_effects.h @@ -14,6 +14,9 @@ enum states { REGULAR //!< when in regular use #if defined(RGB_FADE_IN) ,FADE_IN //!< when starting initially or before going back to REGULAR +#endif +#if defined(RGB_DISABLE_WITH_FADE_OUT) + ,FADE_OUT //!< before supending #endif ,SUSPENDED //!< expecting to be suspended by RGB_DISABLE_TIMEOUT any time }; @@ -58,7 +61,7 @@ uint16_t scale_2_rgb_time(const uint8_t scaled_time); */ void rgb_matrix_sethsv_noeeprom_user(const uint16_t hue, const uint8_t sat, const uint8_t val); -#if defined(RGB_FADE_IN) +#if defined(RGB_FADE_IN) || defined(RGB_DISABLE_WITH_FADE_OUT) # if defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) # if (RGB_MATRIX_MAXIMUM_BRIGHTNESS) < 1 # error "RGB_MATRIX_MAXIMUM_BRIGHTNESS must not be less than ONE" @@ -69,7 +72,9 @@ void rgb_matrix_sethsv_noeeprom_user(const uint16_t hue, const uint8_t sat, cons # else # define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 # endif +#endif +#if defined(RGB_FADE_IN) /** * @brief Calculates the time offset required by fade in. * @details Using an arbitrary timer any point on the sine curve might be pointed to. @@ -88,3 +93,28 @@ uint8_t calc_fade_in_offset(const uint8_t time); */ bool fade_in(const uint8_t time); #endif + +#if defined(RGB_DISABLE_WITH_FADE_OUT) +# if !defined(RGB_DISABLE_TIMEOUT) +# warning "RGB_DISABLE_WITH_FADE_OUT expects RGB_DISABLE_TIMEOUT to be defined" +# endif + +/** + * @brief Calculates the time offset required by fade out. + * @details Using an arbitrary timer any point on the Sinus curve might be pointed to. + * The offest is calculated so that + * a) the point is at the highest point in the curve and the curve is failing + * b) the point is near the current brightness (eg. fade out might be called while on breath effect). + * @param[in] time Current time usually represented by a(usually scaled) timer + * @return Offset required so that time matches the current brightness + */ +uint8_t calc_fade_out_offset(const uint8_t time); + +/** + * @brief Decreases value/brightness until reaching 0 based on given timer. + * @param[in] time A (usually scaled) timer + * @return Returns `true` if 0 has been reached, `false` otherwise. + */ +bool fade_out(const uint8_t time); +#endif + diff --git a/users/vitoni/utils.c b/users/vitoni/utils.c index 0dbcfd5b4a1c..fb011570e44f 100644 --- a/users/vitoni/utils.c +++ b/users/vitoni/utils.c @@ -94,3 +94,36 @@ bool scaled_sin_up(const uint8_t theta, const uint8_t range_min, const uint8_t r return delta <= max_delta; } + +/** +* @brief Decreases the given value until reaching range_min. +* The decrements occur following an downwards sinus wave (scaled from range_min to range_max). +* @param[in] theta Angle (a full circle mapped to 0-255) used as input for sinus calculation. +* @param[in] range_min Lower bound of range (inclusive). +* @param[in] range_max Upper bound of range (inclusive). +* @param[in] max_delta Maximum delta between value and range_min (due to values being integers and eventually not fully matching). +* @param[in,out] value Reference of variable to be decreased +* @return `true` if value and range_max are within a delta of 3 (chosen by fair dice rolling), `false` otherwise +* @see scaled_sin() +*/ +bool scaled_sin_down(const uint8_t theta, const uint8_t range_min, const uint8_t range_max, const uint8_t max_delta, uint8_t *value) { + // ensure lower range bound + if ((*value) <= range_min) { + (*value) = range_min; + return true; + } + + const uint8_t new_value = scaled_sin(theta, range_min, range_max); + if (in_range(new_value, range_min, range_max) && new_value < (*value)) { + (*value) = new_value; + + return range_min == (*value); + } + + const uint8_t delta = (*value) - range_min; + if (delta <= max_delta) { + (*value) = range_min; + } + + return delta <= max_delta; +} diff --git a/users/vitoni/utils.h b/users/vitoni/utils.h index 8c2716c254f4..987b612d5828 100644 --- a/users/vitoni/utils.h +++ b/users/vitoni/utils.h @@ -65,3 +65,16 @@ uint8_t scaled_sin(const uint8_t theta, const uint8_t range_min, const uint8_t r * @see scaled_sin() */ bool scaled_sin_up(const uint8_t thea, const uint8_t range_min, const uint8_t range_max, const uint8_t max_delta, uint8_t *value); + +/** +* @brief Decreases the given value until reaching range_min. +* The decrements occur following an downwards sinus wave (scaled from range_min to range_max). +* @param[in] theta Angle (a full circle mapped to 0-255) used as input for sinus calculation. +* @param[in] range_min Lower bound of range (inclusive). +* @param[in] range_max Upper bound of range (inclusive). +* @param[in] max_delta Maximum delta between value and range_min (due to values being integers and eventually not fully matching). +* @param[in,out] value Reference of variable to be decreased +* @return `true` if value and range_max are within a delta of 3 (chosen by fair dice rolling), `false` otherwise +* @see scaled_sin() +*/ +bool scaled_sin_down(const uint8_t theta, const uint8_t range_min, const uint8_t range_max, const uint8_t max_delta, uint8_t *value); diff --git a/users/vitoni/vitoni.c b/users/vitoni/vitoni.c index 4f26039120a1..d356fa1aa886 100644 --- a/users/vitoni/vitoni.c +++ b/users/vitoni/vitoni.c @@ -9,7 +9,7 @@ #include "rgb_matrix_effects.h" #include "utils.h" -#if defined(RGB_FADE_IN) +#if defined(RGB_FADE_IN) || defined(RGB_DISABLE_WITH_FADE_OUT) static uint8_t state; // flag used to indicate that offset calculation is needed to adjust the timer, @@ -17,18 +17,46 @@ static uint8_t state; static bool calc_offset; void matrix_scan_user_rgb(void) { +#if defined(RGB_DISABLE_WITH_FADE_OUT) + const uint8_t time = rgb_time_2_scale(); +#endif static uint8_t time_offset; - const uint32_t inactivity_time = last_input_activity_elapsed(); + const uint32_t inactivity_millis = last_input_activity_elapsed(); + +#if defined(RGB_DISABLE_WITH_FADE_OUT) + const uint32_t fade_out_duration = scale_2_rgb_time(128); + const uint32_t start_fade_out_after_millis = (RGB_DISABLE_TIMEOUT) > fade_out_duration + ? (RGB_DISABLE_TIMEOUT) - fade_out_duration + : 0; - // setting brightness to black as starting point for fade in + if (start_fade_out_after_millis <= inactivity_millis) { + update_value(&state, FADE_OUT, &calc_offset); + } +#else + // having to set brightness "manually" to black as starting point for fade in // for the time when returning from suspended state - if (RGB_DISABLE_TIMEOUT <= inactivity_time + 15) { + if (RGB_DISABLE_TIMEOUT <= inactivity_millis + 15) { rgb_matrix_config.hsv.v = 0; state = SUSPENDED; } +#endif switch(state) { +#if defined(RGB_DISABLE_WITH_FADE_OUT) + case FADE_OUT: + if (calc_offset) { + time_offset = calc_fade_out_offset(time); + + // resetting flag for subsequent calls + calc_offset = false; + } + if (fade_out(time + time_offset)) { + update_value(&state, SUSPENDED, &calc_offset); + } + break; +#endif +#if defined(RGB_FADE_IN) case FADE_IN: { // since we want to be active, fade in should be faster than e.g. fading out @@ -44,11 +72,13 @@ void matrix_scan_user_rgb(void) { } } break; +#endif default: break; } } +#if defined(RGB_FADE_IN) bool process_record_user_rgb(const uint16_t keycode, const keyrecord_t *record) { // if we are in a non regular state we might have faded out (eventually partially) // so we restore brightness (to max as we don't keep track of manually changed brightness) @@ -69,3 +99,5 @@ void suspend_wakeup_init_user(void) { } } #endif // defined(RGB_FADE_IN) + +#endif // defined(RGB_FADE_IN) || defined(RGB_DISABLE_WITH_FADE_OUT) From 439aeba64520157d751305fbe221ec2659132d5d Mon Sep 17 00:00:00 2001 From: Victor Toni Date: Tue, 26 Oct 2021 20:41:09 +0200 Subject: [PATCH 11/12] Add fade out before idle --- .../gmmk/pro/iso/keymaps/vitoni/config.h | 2 ++ .../gmmk/pro/iso/keymaps/vitoni/readme.adoc | 16 +++++++++ users/vitoni/rgb_matrix_effects.c | 23 +++++++++--- users/vitoni/rgb_matrix_effects.h | 36 +++++++++++++++++-- users/vitoni/vitoni.c | 30 +++++++++++++--- 5 files changed, 95 insertions(+), 12 deletions(-) diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h b/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h index 81afc46b7a06..ba6008ee3111 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h @@ -11,6 +11,8 @@ // fading out is timed (depending on the rgb_matrix_config.speed) to have finished before reaching RGB_DISABLE_TIMEOUT #define RGB_DISABLE_WITH_FADE_OUT #define RGB_DISABLE_WHEN_USB_SUSPENDED + // number of milliseconds to wait until activating RGB idle effects + #define RGB_IDLE_TIMEOUT 4500 // 4.5 seconds // fade in when we have been suspended #define RGB_FADE_IN #endif diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc b/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc index 558c97c83463..c00575facaf6 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc @@ -78,4 +78,20 @@ Parameters used to define the behavior are: | 200 (<= UNIT8_MAX) | Maximum assumed value for brightness. Used to calculate lead time for fade out before suspend timeout. + +|=== + +`RGB_IDLE_TIMEOUT` enables fading out after being idle for the defined time. + +[%header] +|=== +|Key | Default | Description + +|RGB_IDLE_TIMEOUT +|4500 +|Time in milliseconds without activity before considered to be idle. + +|RGB_IDLE_MINIMUM_BRIGHTNESS +|`RGB_MATRIX_MAXIMUM_BRIGHTNESS` / 5 +|Brightness value RGB is dimmed to when starting to idle. |=== diff --git a/users/vitoni/rgb_matrix_effects.c b/users/vitoni/rgb_matrix_effects.c index d6b3d7140170..199734d393b1 100644 --- a/users/vitoni/rgb_matrix_effects.c +++ b/users/vitoni/rgb_matrix_effects.c @@ -108,7 +108,7 @@ bool fade_out_ranged(const uint8_t time, const uint8_t range_min, const uint8_t * @see rgb_matrix_sethsv_noeeprom() */ void rgb_matrix_sethsv_noeeprom_user(const uint16_t hue, const uint8_t sat, const uint8_t val) { -#if defined(RGB_FADE_IN) +#if defined(RGB_FADE_IN) || defined(RGB_IDLE_TIMEOUT) rgb_matrix_config.hsv.h = hue; rgb_matrix_config.hsv.s = sat; // omitting setting the value to avoid interfering with effects @@ -118,7 +118,7 @@ void rgb_matrix_sethsv_noeeprom_user(const uint16_t hue, const uint8_t sat, cons #endif } -#if defined(RGB_FADE_IN) +#if defined(RGB_FADE_IN) || defined(RGB_IDLE_TIMEOUT) /** * @brief Calculates the time offset required by fade in. * @details Using an arbitrary timer any point on the sine curve might be pointed to. @@ -162,8 +162,7 @@ bool fade_in(const uint8_t time) { } #endif -#if defined(RGB_DISABLE_WITH_FADE_OUT) - +#if defined(RGB_DISABLE_WITH_FADE_OUT) || defined(RGB_IDLE_TIMEOUT) /** * @brief Calculates the time offset required by fade out. * @details Using an arbitrary timer any point on the Sinus curve might be pointed to. @@ -192,7 +191,9 @@ uint8_t calc_fade_out_offset(const uint8_t time) { return time_offset; } +#endif +#if defined(RGB_DISABLE_WITH_FADE_OUT) /** * @brief Decreases value/brightness until reaching 0 based on given timer. * @param[in] time A (usually scaled) timer @@ -205,3 +206,17 @@ bool fade_out(const uint8_t time) { return fade_out_ranged(time, range_min, range_max); } #endif + +#if defined(RGB_IDLE_TIMEOUT) +/** + * @brief Decreases value/brightness until reaching `RGB_IDLE_MINIMUM_BRIGHTNESS` based on given timer. + * @param[in] time A (usually scaled) timer + * @return Returns `true` if `RGB_IDLE_MINIMUM_BRIGHTNESS` has been reached, `false` otherwise. + */ +bool idle_fade_out(const uint8_t time) { + static const uint8_t range_min = RGB_IDLE_MINIMUM_BRIGHTNESS; + static const uint8_t range_max = RGB_MATRIX_MAXIMUM_BRIGHTNESS; + + return fade_out_ranged(time, range_min, range_max); +} +#endif // RGB_IDLE_TIMEOUT diff --git a/users/vitoni/rgb_matrix_effects.h b/users/vitoni/rgb_matrix_effects.h index 157a062f682e..cbdcd0a31cdb 100644 --- a/users/vitoni/rgb_matrix_effects.h +++ b/users/vitoni/rgb_matrix_effects.h @@ -12,7 +12,11 @@ */ enum states { REGULAR //!< when in regular use -#if defined(RGB_FADE_IN) +#if defined(RGB_IDLE_TIMEOUT) + ,IDLE_FADE_OUT //!< when started idling + ,IDLE //!< when idling +#endif +#if defined(RGB_FADE_IN) || defined(RGB_IDLE_TIMEOUT) ,FADE_IN //!< when starting initially or before going back to REGULAR #endif #if defined(RGB_DISABLE_WITH_FADE_OUT) @@ -61,7 +65,7 @@ uint16_t scale_2_rgb_time(const uint8_t scaled_time); */ void rgb_matrix_sethsv_noeeprom_user(const uint16_t hue, const uint8_t sat, const uint8_t val); -#if defined(RGB_FADE_IN) || defined(RGB_DISABLE_WITH_FADE_OUT) +#if defined(RGB_FADE_IN) || defined(RGB_DISABLE_WITH_FADE_OUT) || defined(RGB_IDLE_TIMEOUT) # if defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) # if (RGB_MATRIX_MAXIMUM_BRIGHTNESS) < 1 # error "RGB_MATRIX_MAXIMUM_BRIGHTNESS must not be less than ONE" @@ -74,7 +78,7 @@ void rgb_matrix_sethsv_noeeprom_user(const uint16_t hue, const uint8_t sat, cons # endif #endif -#if defined(RGB_FADE_IN) +#if defined(RGB_FADE_IN) || defined(RGB_IDLE_TIMEOUT) /** * @brief Calculates the time offset required by fade in. * @details Using an arbitrary timer any point on the sine curve might be pointed to. @@ -98,7 +102,9 @@ bool fade_in(const uint8_t time); # if !defined(RGB_DISABLE_TIMEOUT) # warning "RGB_DISABLE_WITH_FADE_OUT expects RGB_DISABLE_TIMEOUT to be defined" # endif +#endif +#if defined(RGB_DISABLE_WITH_FADE_OUT) || defined(RGB_IDLE_TIMEOUT) /** * @brief Calculates the time offset required by fade out. * @details Using an arbitrary timer any point on the Sinus curve might be pointed to. @@ -109,7 +115,9 @@ bool fade_in(const uint8_t time); * @return Offset required so that time matches the current brightness */ uint8_t calc_fade_out_offset(const uint8_t time); +#endif +#if defined(RGB_DISABLE_WITH_FADE_OUT) /** * @brief Decreases value/brightness until reaching 0 based on given timer. * @param[in] time A (usually scaled) timer @@ -118,3 +126,25 @@ uint8_t calc_fade_out_offset(const uint8_t time); bool fade_out(const uint8_t time); #endif +#if defined(RGB_IDLE_TIMEOUT) +# if RGB_IDLE_TIMEOUT < 0 +# error "RGB_IDLE_TIMEOUT must not be less than ZERO" +# endif +# if !defined(RGB_IDLE_MINIMUM_BRIGHTNESS) + // minimum brightness when idling +# define RGB_IDLE_MINIMUM_BRIGHTNESS (RGB_MATRIX_MAXIMUM_BRIGHTNESS/5) +# endif +# if RGB_IDLE_MINIMUM_BRIGHTNESS < 0 +# error "RGB_IDLE_MINIMUM_BRIGHTNESS must not be less than ZERO" +# endif // RGB_IDLE_MINIMUM_BRIGHTNESS < 0 +# if RGB_MATRIX_MAXIMUM_BRIGHTNESS <= RGB_IDLE_MINIMUM_BRIGHTNESS +# error "RGB_IDLE_MINIMUM_BRIGHTNESS must be less than RGB_MATRIX_MAXIMUM_BRIGHTNESS" +# endif // RGB_MATRIX_MAXIMUM_BRIGHTNESS <= RGB_IDLE_MINIMUM_BRIGHTNESS + +/** + * @brief Decreases value/brightness until reaching `RGB_IDLE_MINIMUM_BRIGHTNESS` based on given timer. + * @param[in] time A (usually scaled) timer + * @return Returns `true` if `RGB_IDLE_MINIMUM_BRIGHTNESS` has been reached, `false` otherwise. + */ +bool idle_fade_out(const uint8_t time); +#endif // RGB_IDLE_TIMEOUT diff --git a/users/vitoni/vitoni.c b/users/vitoni/vitoni.c index d356fa1aa886..9744b5359c2d 100644 --- a/users/vitoni/vitoni.c +++ b/users/vitoni/vitoni.c @@ -9,7 +9,7 @@ #include "rgb_matrix_effects.h" #include "utils.h" -#if defined(RGB_FADE_IN) || defined(RGB_DISABLE_WITH_FADE_OUT) +#if defined(RGB_FADE_IN) || defined(RGB_DISABLE_WITH_FADE_OUT) || defined(RGB_IDLE_TIMEOUT) static uint8_t state; // flag used to indicate that offset calculation is needed to adjust the timer, @@ -17,13 +17,18 @@ static uint8_t state; static bool calc_offset; void matrix_scan_user_rgb(void) { -#if defined(RGB_DISABLE_WITH_FADE_OUT) +#if defined(RGB_DISABLE_WITH_FADE_OUT) || defined(RGB_IDLE_TIMEOUT) const uint8_t time = rgb_time_2_scale(); #endif static uint8_t time_offset; const uint32_t inactivity_millis = last_input_activity_elapsed(); +#if defined(RGB_IDLE_TIMEOUT) + if (IDLE != state && RGB_IDLE_TIMEOUT <= inactivity_millis) { + update_value(&state, IDLE_FADE_OUT, &calc_offset); + } +#endif #if defined(RGB_DISABLE_WITH_FADE_OUT) const uint32_t fade_out_duration = scale_2_rgb_time(128); const uint32_t start_fade_out_after_millis = (RGB_DISABLE_TIMEOUT) > fade_out_duration @@ -33,7 +38,7 @@ void matrix_scan_user_rgb(void) { if (start_fade_out_after_millis <= inactivity_millis) { update_value(&state, FADE_OUT, &calc_offset); } -#else +#elif defined(RGB_DISABLE_TIMEOUT) // having to set brightness "manually" to black as starting point for fade in // for the time when returning from suspended state if (RGB_DISABLE_TIMEOUT <= inactivity_millis + 15) { @@ -43,6 +48,21 @@ void matrix_scan_user_rgb(void) { #endif switch(state) { +#if defined(RGB_IDLE_TIMEOUT) + case IDLE_FADE_OUT: + if (calc_offset) { + time_offset = calc_fade_out_offset(time); + + // resetting flag for subsequent calls + calc_offset = false; + } + if (idle_fade_out(time + time_offset)) { + update_value(&state, IDLE, &calc_offset); + } + break; + case IDLE: + break; +#endif #if defined(RGB_DISABLE_WITH_FADE_OUT) case FADE_OUT: if (calc_offset) { @@ -56,7 +76,7 @@ void matrix_scan_user_rgb(void) { } break; #endif -#if defined(RGB_FADE_IN) +#if defined(RGB_FADE_IN) || defined(RGB_IDLE_TIMEOUT) case FADE_IN: { // since we want to be active, fade in should be faster than e.g. fading out @@ -78,7 +98,7 @@ void matrix_scan_user_rgb(void) { } } -#if defined(RGB_FADE_IN) +#if defined(RGB_FADE_IN) || defined(RGB_IDLE_TIMEOUT) bool process_record_user_rgb(const uint16_t keycode, const keyrecord_t *record) { // if we are in a non regular state we might have faded out (eventually partially) // so we restore brightness (to max as we don't keep track of manually changed brightness) From 0e451982a0a4030ae9c37dd3a67a49ac51cd0b11 Mon Sep 17 00:00:00 2001 From: Victor Toni Date: Thu, 28 Oct 2021 20:48:46 +0200 Subject: [PATCH 12/12] Add breathe effect when idle --- .../gmmk/pro/iso/keymaps/vitoni/config.h | 2 ++ .../gmmk/pro/iso/keymaps/vitoni/readme.adoc | 11 +++++++-- users/vitoni/readme.adoc | 2 +- users/vitoni/rgb_matrix_effects.c | 14 +++++++++++ users/vitoni/rgb_matrix_effects.h | 24 +++++++++++++++++++ users/vitoni/vitoni.c | 8 +++++++ 6 files changed, 58 insertions(+), 3 deletions(-) diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h b/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h index ba6008ee3111..fd8f1d6859e7 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/config.h @@ -13,6 +13,8 @@ #define RGB_DISABLE_WHEN_USB_SUSPENDED // number of milliseconds to wait until activating RGB idle effects #define RGB_IDLE_TIMEOUT 4500 // 4.5 seconds + // activate breathe effect when idle + #define RGB_IDLE_BREATHE // fade in when we have been suspended #define RGB_FADE_IN #endif diff --git a/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc b/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc index c00575facaf6..38a74a568bf0 100644 --- a/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc +++ b/keyboards/gmmk/pro/iso/keymaps/vitoni/readme.adoc @@ -81,7 +81,8 @@ Used to calculate lead time for fade out before suspend timeout. |=== -`RGB_IDLE_TIMEOUT` enables fading out after being idle for the defined time. +`RGB_IDLE_TIMEOUT` enables fading out after being idle for the defined time and allows +* `RGB_IDLE_BREATHE` also activates a brethe effect while idling. [%header] |=== @@ -93,5 +94,11 @@ Used to calculate lead time for fade out before suspend timeout. |RGB_IDLE_MINIMUM_BRIGHTNESS |`RGB_MATRIX_MAXIMUM_BRIGHTNESS` / 5 -|Brightness value RGB is dimmed to when starting to idle. +|Brightness value RGB is dimmed to when starting to idle. + +When breathing used as the lower bound of the brightness value. + +|RGB_IDLE_MAXIMUM_BRIGHTNESS +|`RGB_MATRIX_MAXIMUM_BRIGHTNESS` * 2/5 +|Upper bound of brightness value of the RGB light while breathing. + |=== diff --git a/users/vitoni/readme.adoc b/users/vitoni/readme.adoc index 69ccfa9e682b..acf65793d2de 100644 --- a/users/vitoni/readme.adoc +++ b/users/vitoni/readme.adoc @@ -8,7 +8,7 @@ Common functions are declared in link:utils.h[]. These function are not directly == rgb_matrix_effects.h -Functions in link:rgb_matrix_effects.h[] make use of common function in `utils.h` and are used to create to RGB matrix effects such as fading. +Functions in link:rgb_matrix_effects.h[] make use of common function in `utils.h` and are used to create to RGB matrix effects such as fading or breathing. == vitoni.h diff --git a/users/vitoni/rgb_matrix_effects.c b/users/vitoni/rgb_matrix_effects.c index 199734d393b1..3a13e99bc7e2 100644 --- a/users/vitoni/rgb_matrix_effects.c +++ b/users/vitoni/rgb_matrix_effects.c @@ -219,4 +219,18 @@ bool idle_fade_out(const uint8_t time) { return fade_out_ranged(time, range_min, range_max); } + +#if defined(RGB_IDLE_BREATHE) +/** + * @brief Changes value/brightness to create a breathing effect based on given timer. + * @details Brightness will breathe in the range starting from `RGB_IDLE_MINIMUM_BRIGHTNESS` to `RGB_IDLE_MAXIMUM_BRIGHTNESS`. + * @param[in] time A (usually scaled) timer + */ +void idle_breathe(const uint8_t time) { + static const uint8_t range_min = RGB_IDLE_MINIMUM_BRIGHTNESS; + static const uint8_t range_max = RGB_IDLE_MAXIMUM_BRIGHTNESS; + + rgb_matrix_config.hsv.v = scaled_sin(time, range_min, range_max); +} +#endif // RGB_IDLE_BREATHE #endif // RGB_IDLE_TIMEOUT diff --git a/users/vitoni/rgb_matrix_effects.h b/users/vitoni/rgb_matrix_effects.h index cbdcd0a31cdb..ed74500b1827 100644 --- a/users/vitoni/rgb_matrix_effects.h +++ b/users/vitoni/rgb_matrix_effects.h @@ -147,4 +147,28 @@ bool fade_out(const uint8_t time); * @return Returns `true` if `RGB_IDLE_MINIMUM_BRIGHTNESS` has been reached, `false` otherwise. */ bool idle_fade_out(const uint8_t time); + +#if defined(RGB_IDLE_BREATHE) +# if !defined(RGB_IDLE_MAXIMUM_BRIGHTNESS) + // maximum brightness when idling +# define RGB_IDLE_MAXIMUM_BRIGHTNESS (RGB_MATRIX_MAXIMUM_BRIGHTNESS*3/5) +# endif +# if !(0 <= RGB_IDLE_MAXIMUM_BRIGHTNESS) +# error "RGB_IDLE_MINIMUM_BRIGHTNESS must not be less than ZERO, was: " RGB_IDLE_MAXIMUM_BRIGHTNESS +# endif // RGB_IDLE_MAXIMUM_BRIGHTNESS < 0 +# if !(RGB_IDLE_MINIMUM_BRIGHTNESS < RGB_IDLE_MAXIMUM_BRIGHTNESS) +# error "RGB_IDLE_MINIMUM_BRIGHTNESS must be less than RGB_IDLE_MAXIMUM_BRIGHTNESS" +# endif // RGB_IDLE_MAXIMUM_BRIGHTNESS <= RGB_IDLE_MINIMUM_BRIGHTNESS +# if !(RGB_IDLE_MAXIMUM_BRIGHTNESS <= RGB_MATRIX_MAXIMUM_BRIGHTNESS) +# error "RGB_IDLE_MAXIMUM_BRIGHTNESS must be less than or equal to RGB_MATRIX_MAXIMUM_BRIGHTNESS" +# endif // RGB_MATRIX_MAXIMUM_BRIGHTNESS <= RGB_IDLE_MAXIMUM_BRIGHTNESS + +/** + * @brief Changes value/brightness to create a breathing effect based on given timer. + * @details Brightness will breathe in the range starting from `RGB_IDLE_MINIMUM_BRIGHTNESS` to `RGB_IDLE_MAXIMUM_BRIGHTNESS`. + * @param[in] time A (usually scaled) timer + */ +void idle_breathe(const uint8_t time); +#endif // RGB_IDLE_BREATHE + #endif // RGB_IDLE_TIMEOUT diff --git a/users/vitoni/vitoni.c b/users/vitoni/vitoni.c index 9744b5359c2d..2a0ff5c46f54 100644 --- a/users/vitoni/vitoni.c +++ b/users/vitoni/vitoni.c @@ -61,6 +61,14 @@ void matrix_scan_user_rgb(void) { } break; case IDLE: +#if defined(RGB_IDLE_BREATHE) + if (calc_offset) { + // no need to calculate time_offset since we are aligned already due to IDLE_FADE_OUT + // resetting flag for subsequent calls + calc_offset = false; + } + idle_breathe(time + time_offset); +#endif break; #endif #if defined(RGB_DISABLE_WITH_FADE_OUT)