qmk

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.z3bra.org/qmk.git
Log | Files | Refs | Submodules | LICENSE

rgb_stuff.c (13033B)


      1 #include "drashna.h"
      2 #include "rgb_stuff.h"
      3 #include "eeprom.h"
      4 
      5 #if defined(RGBLIGHT_ENABLE)
      6 extern rgblight_config_t rgblight_config;
      7 bool                     has_initialized;
      8 #endif
      9 
     10 #ifdef RGBLIGHT_ENABLE
     11 void rgblight_sethsv_default_helper(uint8_t index) { rgblight_sethsv_at(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, index); }
     12 #endif  // RGBLIGHT_ENABLE
     13 
     14 #ifdef INDICATOR_LIGHTS
     15 void set_rgb_indicators(uint8_t this_mod, uint8_t this_led, uint8_t this_osm) {
     16     if (userspace_config.rgb_layer_change && biton32(layer_state) == 0) {
     17         if ((this_mod | this_osm) & MOD_MASK_SHIFT || this_led & (1 << USB_LED_CAPS_LOCK)) {
     18 #    ifdef SHFT_LED1
     19             rgblight_sethsv_at(120, 255, 255, SHFT_LED1);
     20 #    endif  // SHFT_LED1
     21 #    ifdef SHFT_LED2
     22             rgblight_sethsv_at(120, 255, 255, SHFT_LED2);
     23 #    endif  // SHFT_LED2
     24         } else {
     25 #    ifdef SHFT_LED1
     26             rgblight_sethsv_default_helper(SHFT_LED1);
     27 #    endif  // SHFT_LED1
     28 #    ifdef SHFT_LED2
     29             rgblight_sethsv_default_helper(SHFT_LED2);
     30 #    endif  // SHFT_LED2
     31         }
     32         if ((this_mod | this_osm) & MOD_MASK_CTRL) {
     33 #    ifdef CTRL_LED1
     34             rgblight_sethsv_at(0, 255, 255, CTRL_LED1);
     35 #    endif  // CTRL_LED1
     36 #    ifdef CTRL_LED2
     37             rgblight_sethsv_at(0, 255, 255, CTRL_LED2);
     38 #    endif  // CTRL_LED2
     39         } else {
     40 #    ifdef CTRL_LED1
     41             rgblight_sethsv_default_helper(CTRL_LED1);
     42 #    endif  // CTRL_LED1
     43 #    ifdef CTRL_LED2
     44             rgblight_sethsv_default_helper(CTRL_LED2);
     45 #    endif  // CTRL_LED2
     46         }
     47         if ((this_mod | this_osm) & MOD_MASK_GUI) {
     48 #    ifdef GUI_LED1
     49             rgblight_sethsv_at(51, 255, 255, GUI_LED1);
     50 #    endif  // GUI_LED1
     51 #    ifdef GUI_LED2
     52             rgblight_sethsv_at(51, 255, 255, GUI_LED2);
     53 #    endif  // GUI_LED2
     54         } else {
     55 #    ifdef GUI_LED1
     56             rgblight_sethsv_default_helper(GUI_LED1);
     57 #    endif  // GUI_LED1
     58 #    ifdef GUI_LED2
     59             rgblight_sethsv_default_helper(GUI_LED2);
     60 #    endif  // GUI_LED2
     61         }
     62         if ((this_mod | this_osm) & MOD_MASK_ALT) {
     63 #    ifdef ALT_LED1
     64             rgblight_sethsv_at(240, 255, 255, ALT_LED1);
     65 #    endif  // ALT_LED1
     66 #    ifdef GUI_LED2
     67             rgblight_sethsv_at(240, 255, 255, ALT_LED2);
     68 #    endif  // GUI_LED2
     69         } else {
     70 #    ifdef GUI_LED1
     71             rgblight_sethsv_default_helper(ALT_LED1);
     72 #    endif  // GUI_LED1
     73 #    ifdef GUI_LED2
     74             rgblight_sethsv_default_helper(ALT_LED2);
     75 #    endif  // GUI_LED2
     76         }
     77     }
     78 }
     79 
     80 void matrix_scan_indicator(void) {
     81     if (has_initialized) {
     82         set_rgb_indicators(get_mods(), host_keyboard_leds(), get_oneshot_mods());
     83     }
     84 }
     85 #endif  // INDICATOR_LIGHTS
     86 
     87 #ifdef RGBLIGHT_TWINKLE
     88 static rgblight_fadeout lights[RGBLED_NUM];
     89 
     90 __attribute__((weak)) bool rgblight_twinkle_is_led_used_keymap(uint8_t index) { return false; }
     91 
     92 bool rgblight_twinkle_is_led_used(uint8_t index) {
     93     switch (index) {
     94 #    ifdef INDICATOR_LIGHTS
     95 #        ifdef SHFT_LED1
     96         case SHFT_LED1:
     97             return true;
     98 #        endif  // SHFT_LED1
     99 #        ifdef SHFT_LED2
    100         case SHFT_LED2:
    101             return true;
    102 #        endif  // SHFT_LED2
    103 #        ifdef CTRL_LED1
    104         case CTRL_LED1:
    105             return true;
    106 #        endif  // CTRL_LED1
    107 #        ifdef CTRL_LED2
    108         case CTRL_LED2:
    109             return true;
    110 #        endif  // CTRL_LED2
    111 #        ifdef GUI_LED1
    112         case GUI_LED1:
    113             return true;
    114 #        endif  // GUI_LED1
    115 #        ifdef GUI_LED2
    116         case GUI_LED2:
    117             return true;
    118 #        endif  // GUI_LED2
    119 #        ifdef ALT_LED1
    120         case ALT_LED1:
    121             return true;
    122 #        endif  // ALT_LED1
    123 #        ifdef ALT_LED2
    124         case ALT_LED2:
    125             return true;
    126 #        endif  // ALT_LED2
    127 #    endif      // INDICATOR_LIGHTS
    128         default:
    129             return rgblight_twinkle_is_led_used_keymap(index);
    130     }
    131 }
    132 
    133 void scan_rgblight_fadeout(void) {  // Don't effing change this function .... rgblight_sethsv is supppppper intensive
    134     bool litup = false;
    135     for (uint8_t light_index = 0; light_index < RGBLED_NUM; ++light_index) {
    136         if (lights[light_index].enabled && timer_elapsed(lights[light_index].timer) > 10) {
    137             rgblight_fadeout *light = &lights[light_index];
    138             litup                   = true;
    139 
    140             if (light->life) {
    141                 light->life -= 1;
    142                 if (biton32(layer_state) == 0) {
    143                     sethsv(light->hue + rand() % 0xF, 255, light->life, (LED_TYPE *)&led[light_index]);
    144                 }
    145                 light->timer = timer_read();
    146             } else {
    147                 if (light->enabled && biton32(layer_state) == 0) {
    148                     rgblight_sethsv_default_helper(light_index);
    149                 }
    150                 litup = light->enabled = false;
    151             }
    152         }
    153     }
    154     if (litup && biton32(layer_state) == 0) {
    155         rgblight_set();
    156     }
    157 }
    158 
    159 void start_rgb_light(void) {
    160     uint8_t indices[RGBLED_NUM];
    161     uint8_t indices_count  = 0;
    162     uint8_t min_life       = 0xFF;
    163     uint8_t min_life_index = -1;
    164     for (uint8_t index = 0; index < RGBLED_NUM; ++index) {
    165         if (rgblight_twinkle_is_led_used(index)) {
    166             continue;
    167         }
    168         if (lights[index].enabled) {
    169             if (min_life_index == -1 || lights[index].life < min_life) {
    170                 min_life       = lights[index].life;
    171                 min_life_index = index;
    172             }
    173             continue;
    174         }
    175 
    176         indices[indices_count] = index;
    177         ++indices_count;
    178     }
    179 
    180     uint8_t light_index;
    181     if (!indices_count) {
    182         light_index = min_life_index;
    183     } else {
    184         light_index = indices[rand() % indices_count];
    185     }
    186 
    187     rgblight_fadeout *light = &lights[light_index];
    188     light->enabled          = true;
    189     light->timer            = timer_read();
    190     light->life             = 0xC0 + rand() % 0x40;
    191 
    192     light->hue = rgblight_config.hue + (rand() % 0xB4) - 0x54;
    193 
    194     rgblight_sethsv_at(light->hue, 255, light->life, light_index);
    195 }
    196 #endif
    197 
    198 bool process_record_user_rgb(uint16_t keycode, keyrecord_t *record) {
    199     if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) {
    200         keycode = keycode & 0xFF;
    201     }
    202     switch (keycode) {
    203 #ifdef RGBLIGHT_TWINKLE
    204         case KC_A ... KC_SLASH:
    205         case KC_F1 ... KC_F12:
    206         case KC_INSERT ... KC_UP:
    207         case KC_KP_SLASH ... KC_KP_DOT:
    208         case KC_F13 ... KC_F24:
    209         case KC_AUDIO_MUTE ... KC_MEDIA_REWIND:
    210             if (record->event.pressed) {
    211                 start_rgb_light();
    212             }
    213             return true;
    214             break;
    215 #endif                  // RGBLIGHT_TWINKLE
    216         case KC_RGB_T:  // This allows me to use underglow as layer indication, or as normal
    217 #if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
    218             if (record->event.pressed) {
    219                 userspace_config.rgb_layer_change ^= 1;
    220                 xprintf("rgblight layer change [EEPROM]: %u\n", userspace_config.rgb_layer_change);
    221                 eeconfig_update_user(userspace_config.raw);
    222                 if (userspace_config.rgb_layer_change) {
    223                     layer_state_set(layer_state);  // This is needed to immediately set the layer color (looks better)
    224                 }
    225             }
    226 #endif  // RGBLIGHT_ENABLE
    227             return false;
    228             break;
    229 #ifdef RGBLIGHT_ENABLE
    230         case RGB_MODE_FORWARD ... RGB_MODE_GRADIENT:  // quantum_keycodes.h L400 for definitions
    231             if (record->event.pressed) {              // This disables layer indication, as it's assumed that if you're changing this ... you want that disabled
    232                 if (userspace_config.rgb_layer_change) {
    233                     userspace_config.rgb_layer_change = false;
    234                     xprintf("rgblight layer change [EEPROM]: %u\n", userspace_config.rgb_layer_change);
    235                     eeconfig_update_user(userspace_config.raw);
    236                 }
    237             }
    238             return true;
    239             break;
    240 #endif  // RGBLIGHT_ENABLE
    241     }
    242     return true;
    243 }
    244 
    245 void keyboard_post_init_rgb(void) {
    246 #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_STARTUP_ANIMATION)
    247     bool is_enabled = rgblight_config.enable;
    248     if (userspace_config.rgb_layer_change) {
    249         rgblight_enable_noeeprom();
    250     }
    251     if (rgblight_config.enable) {
    252         layer_state_set_user(layer_state);
    253         uint16_t old_hue = rgblight_config.hue;
    254         rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT);
    255         for (uint16_t i = 255; i > 0; i--) {
    256             rgblight_sethsv_noeeprom((i + old_hue) % 255, 255, 255);
    257             matrix_scan();
    258             wait_ms(10);
    259         }
    260     }
    261     if (!is_enabled) {
    262         rgblight_disable_noeeprom();
    263     }
    264 
    265 #endif
    266     layer_state_set_user(layer_state);
    267 }
    268 
    269 void matrix_scan_rgb(void) {
    270 #ifdef RGBLIGHT_TWINKLE
    271     scan_rgblight_fadeout();
    272 #endif  // RGBLIGHT_ENABLE
    273 
    274 #ifdef INDICATOR_LIGHTS
    275     matrix_scan_indicator();
    276 #endif
    277 }
    278 
    279 layer_state_t layer_state_set_rgb(layer_state_t state) {
    280 #ifdef RGBLIGHT_ENABLE
    281     if (userspace_config.rgb_layer_change) {
    282         switch (biton32(state)) {
    283             case _MACROS:
    284                 rgblight_sethsv_noeeprom_orange();
    285                 userspace_config.is_overwatch ? rgblight_mode_noeeprom(RGBLIGHT_MODE_SNAKE + 2) : rgblight_mode_noeeprom(RGBLIGHT_MODE_SNAKE + 3);
    286                 break;
    287             case _MEDIA:
    288                 rgblight_sethsv_noeeprom_chartreuse();
    289                 rgblight_mode_noeeprom(RGBLIGHT_MODE_KNIGHT + 1);
    290                 break;
    291             case _GAMEPAD:
    292                 rgblight_sethsv_noeeprom_orange();
    293                 rgblight_mode_noeeprom(RGBLIGHT_MODE_SNAKE + 2);
    294                 break;
    295             case _DIABLO:
    296                 rgblight_sethsv_noeeprom_red();
    297                 rgblight_mode_noeeprom(RGBLIGHT_MODE_BREATHING + 3);
    298                 break;
    299             case _RAISE:
    300                 rgblight_sethsv_noeeprom_yellow();
    301                 rgblight_mode_noeeprom(RGBLIGHT_MODE_BREATHING + 3);
    302                 break;
    303             case _LOWER:
    304                 rgblight_sethsv_noeeprom_green();
    305                 rgblight_mode_noeeprom(RGBLIGHT_MODE_BREATHING + 3);
    306                 break;
    307             case _ADJUST:
    308                 rgblight_sethsv_noeeprom_red();
    309                 rgblight_mode_noeeprom(RGBLIGHT_MODE_KNIGHT + 2);
    310                 break;
    311             default:  //  for any other layers, or the default layer
    312                 switch (biton32(default_layer_state)) {
    313                     case _COLEMAK:
    314                         rgblight_sethsv_noeeprom_magenta();
    315                         break;
    316                     case _DVORAK:
    317                         rgblight_sethsv_noeeprom_springgreen();
    318                         break;
    319                     case _WORKMAN:
    320                         rgblight_sethsv_noeeprom_goldenrod();
    321                         break;
    322                     case _NORMAN:
    323                         rgblight_sethsv_noeeprom_coral();
    324                         break;
    325                     case _MALTRON:
    326                         rgblight_sethsv_noeeprom_yellow();
    327                         break;
    328                     case _EUCALYN:
    329                         rgblight_sethsv_noeeprom_pink();
    330                         break;
    331                     case _CARPLAX:
    332                         rgblight_sethsv_noeeprom_blue();
    333                         break;
    334                     default:
    335                         rgblight_sethsv_noeeprom_cyan();
    336                         break;
    337                 }
    338                 biton32(state) == _MODS ? rgblight_mode_noeeprom(RGBLIGHT_MODE_BREATHING) : rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT);  // if _MODS layer is on, then breath to denote it
    339                 break;
    340         }
    341     }
    342 #endif  // RGBLIGHT_ENABLE
    343 
    344     return state;
    345 }
    346 
    347 #ifdef RGB_MATRIX_ENABLE
    348 #    include "lib/lib8tion/lib8tion.h"
    349 extern led_config_t g_led_config;
    350 void rgb_matrix_layer_helper(uint8_t hue, uint8_t sat, uint8_t val, uint8_t mode, uint8_t speed, uint8_t led_type) {
    351     HSV hsv = {hue, sat, val};
    352     if (hsv.v > rgb_matrix_config.hsv.v) {
    353         hsv.v = rgb_matrix_config.hsv.v;
    354     }
    355 
    356     switch (mode) {
    357         case 1:  // breathing
    358         {
    359             uint16_t time = scale16by8(g_rgb_counters.tick, speed / 8);
    360             hsv.v         = scale8(abs8(sin8(time) - 128) * 2, hsv.v);
    361             RGB rgb       = hsv_to_rgb(hsv);
    362             for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
    363                 if (HAS_FLAGS(g_led_config.flags[i], led_type)) {
    364                     rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
    365                 }
    366             }
    367             break;
    368         }
    369         default:  // Solid Color
    370         {
    371             RGB rgb = hsv_to_rgb(hsv);
    372             for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
    373                 if (HAS_FLAGS(g_led_config.flags[i], led_type)) {
    374                     rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
    375                 }
    376             }
    377             break;
    378         }
    379     }
    380 }
    381 #endif