rgb_stuff.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "drashna.h"
  17. #include "rgb_stuff.h"
  18. #include "eeprom.h"
  19. bool has_initialized;
  20. void rgblight_sethsv_default_helper(uint8_t index) { rgblight_sethsv_at(rgblight_get_hue(), rgblight_get_sat(), rgblight_get_val(), index); }
  21. #ifdef RGBLIGHT_TWINKLE
  22. static rgblight_fadeout lights[RGBLED_NUM];
  23. /* Handler for fading/twinkling effect */
  24. void scan_rgblight_fadeout(void) { // Don't effing change this function .... rgblight_sethsv is supppppper intensive
  25. bool litup = false;
  26. for (uint8_t light_index = 0; light_index < RGBLED_NUM; ++light_index) {
  27. if (lights[light_index].enabled && timer_elapsed(lights[light_index].timer) > 10) {
  28. rgblight_fadeout *light = &lights[light_index];
  29. litup = true;
  30. if (light->life) {
  31. light->life -= 1;
  32. if (get_highest_layer(layer_state) == 0) {
  33. sethsv(light->hue + rand() % 0xF, 255, light->life, (LED_TYPE *)&led[light_index]);
  34. }
  35. light->timer = timer_read();
  36. } else {
  37. if (light->enabled && get_highest_layer(layer_state) == 0) {
  38. rgblight_sethsv_default_helper(light_index);
  39. }
  40. litup = light->enabled = false;
  41. }
  42. }
  43. }
  44. if (litup && get_highest_layer(layer_state) == 0) {
  45. rgblight_set();
  46. }
  47. }
  48. /* Triggers a LED to fade/twinkle.
  49. * This function handles the selection of the LED and prepres for it to be used.
  50. */
  51. void start_rgb_light(void) {
  52. uint8_t indices[RGBLED_NUM];
  53. uint8_t indices_count = 0;
  54. uint8_t min_life = 0xFF;
  55. uint8_t min_life_index = -1;
  56. for (uint8_t index = 0; index < RGBLED_NUM; ++index) {
  57. if (lights[index].enabled) {
  58. if (min_life_index == -1 || lights[index].life < min_life) {
  59. min_life = lights[index].life;
  60. min_life_index = index;
  61. }
  62. continue;
  63. }
  64. indices[indices_count] = index;
  65. ++indices_count;
  66. }
  67. uint8_t light_index;
  68. if (!indices_count) {
  69. light_index = min_life_index;
  70. } else {
  71. light_index = indices[rand() % indices_count];
  72. }
  73. rgblight_fadeout *light = &lights[light_index];
  74. light->enabled = true;
  75. light->timer = timer_read();
  76. light->life = 0xC0 + rand() % 0x40;
  77. light->hue = rgblight_get_hue() + (rand() % 0xB4) - 0x54;
  78. rgblight_sethsv_at(light->hue, 255, light->life, light_index);
  79. }
  80. #endif
  81. bool process_record_user_rgb_light(uint16_t keycode, keyrecord_t *record) {
  82. uint16_t temp_keycode = keycode;
  83. // Filter out the actual keycode from MT and LT keys.
  84. if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) {
  85. temp_keycode &= 0xFF;
  86. }
  87. switch (temp_keycode) {
  88. #ifdef RGBLIGHT_TWINKLE
  89. case KC_A ... KC_SLASH:
  90. case KC_F1 ... KC_F12:
  91. case KC_INSERT ... KC_UP:
  92. case KC_KP_SLASH ... KC_KP_DOT:
  93. case KC_F13 ... KC_F24:
  94. case KC_AUDIO_MUTE ... KC_MEDIA_REWIND:
  95. if (record->event.pressed) {
  96. start_rgb_light();
  97. }
  98. break;
  99. #endif // RGBLIGHT_TWINKLE
  100. }
  101. return true;
  102. }
  103. #if defined(RGBLIGHT_STARTUP_ANIMATION)
  104. static bool is_enabled;
  105. static bool is_rgblight_startup;
  106. static uint8_t old_hue;
  107. static uint16_t rgblight_startup_loop_timer;
  108. #endif
  109. void keyboard_post_init_rgb_light(void) {
  110. #if defined(RGBLIGHT_STARTUP_ANIMATION)
  111. is_enabled = rgblight_is_enabled();
  112. if (userspace_config.rgb_layer_change) {
  113. rgblight_enable_noeeprom();
  114. }
  115. if (rgblight_is_enabled()) {
  116. layer_state_set_rgb_light(layer_state);
  117. old_hue = rgblight_get_hue();
  118. rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT);
  119. is_rgblight_startup = true;
  120. }
  121. #endif
  122. layer_state_set_rgb_light(layer_state);
  123. }
  124. void matrix_scan_rgb_light(void) {
  125. # ifdef RGBLIGHT_TWINKLE
  126. scan_rgblight_fadeout();
  127. # endif // RGBLIGHT_ENABLE
  128. #if defined(RGBLIGHT_STARTUP_ANIMATION)
  129. if (is_rgblight_startup && is_keyboard_master()) {
  130. if (timer_elapsed(rgblight_startup_loop_timer) > 10) {
  131. static uint8_t counter;
  132. counter++;
  133. rgblight_sethsv_noeeprom((counter + old_hue) % 255, 255, 255);
  134. rgblight_startup_loop_timer = timer_read();
  135. if (counter == 255) {
  136. is_rgblight_startup = false;
  137. if (!is_enabled) {
  138. rgblight_disable_noeeprom();
  139. }
  140. if (userspace_config.rgb_layer_change) {
  141. layer_state_set_rgb_light(layer_state);
  142. }
  143. }
  144. }
  145. }
  146. #endif
  147. }
  148. void rgblight_set_hsv_and_mode(uint8_t hue, uint8_t sat, uint8_t val, uint8_t mode) {
  149. rgblight_sethsv_noeeprom(hue, sat, val);
  150. // wait_us(175); // Add a slight delay between color and mode to ensure it's processed correctly
  151. rgblight_mode_noeeprom(mode);
  152. }
  153. layer_state_t layer_state_set_rgb_light(layer_state_t state) {
  154. #ifdef RGBLIGHT_ENABLE
  155. if (userspace_config.rgb_layer_change) {
  156. uint8_t mode = layer_state_cmp(state,_MODS) ? RGBLIGHT_MODE_BREATHING : RGBLIGHT_MODE_STATIC_LIGHT;
  157. switch (get_highest_layer(state|default_layer_state)) {
  158. case _MACROS:
  159. rgblight_set_hsv_and_mode(HSV_ORANGE, userspace_config.is_overwatch ? RGBLIGHT_MODE_SNAKE + 2 : RGBLIGHT_MODE_SNAKE + 3);
  160. break;
  161. case _MEDIA:
  162. rgblight_set_hsv_and_mode(HSV_CHARTREUSE, RGBLIGHT_MODE_KNIGHT + 1);
  163. break;
  164. case _GAMEPAD:
  165. rgblight_set_hsv_and_mode(HSV_ORANGE, RGBLIGHT_MODE_SNAKE + 2);
  166. break;
  167. case _DIABLO:
  168. rgblight_set_hsv_and_mode(HSV_RED, RGBLIGHT_MODE_BREATHING + 3);
  169. break;
  170. case _RAISE:
  171. rgblight_set_hsv_and_mode(HSV_YELLOW, RGBLIGHT_MODE_BREATHING + 3);
  172. break;
  173. case _LOWER:
  174. rgblight_set_hsv_and_mode(HSV_GREEN, RGBLIGHT_MODE_BREATHING + 3);
  175. break;
  176. case _ADJUST:
  177. rgblight_set_hsv_and_mode(HSV_RED, RGBLIGHT_MODE_KNIGHT + 2);
  178. break;
  179. case _COLEMAK:
  180. rgblight_set_hsv_and_mode(HSV_MAGENTA, mode);
  181. break;
  182. case _DVORAK:
  183. rgblight_set_hsv_and_mode(HSV_SPRINGGREEN, mode);
  184. break;
  185. case _WORKMAN:
  186. rgblight_set_hsv_and_mode(HSV_GOLDENROD, mode);
  187. break;
  188. case _NORMAN:
  189. rgblight_set_hsv_and_mode(HSV_CORAL, mode);
  190. break;
  191. case _MALTRON:
  192. rgblight_set_hsv_and_mode(HSV_YELLOW, mode);
  193. break;
  194. case _EUCALYN:
  195. rgblight_set_hsv_and_mode(HSV_PINK, mode);
  196. break;
  197. case _CARPLAX:
  198. rgblight_set_hsv_and_mode(HSV_BLUE, mode);
  199. break;
  200. default:
  201. rgblight_set_hsv_and_mode(HSV_CYAN, mode);
  202. break;
  203. }
  204. }
  205. #endif // RGBLIGHT_ENABLE
  206. return state;
  207. }