rgb_stuff.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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. #ifdef RGBLIGHT_ENABLE
  17. # include "drashna.h"
  18. # include "rgb_stuff.h"
  19. # include "eeprom.h"
  20. bool has_initialized;
  21. void rgblight_sethsv_default_helper(uint8_t index) { rgblight_sethsv_at(rgblight_get_hue(), rgblight_get_sat(), rgblight_get_val(), index); }
  22. # ifdef RGBLIGHT_TWINKLE
  23. static rgblight_fadeout lights[RGBLED_NUM];
  24. /* Handler for fading/twinkling effect */
  25. void scan_rgblight_fadeout(void) { // Don't effing change this function .... rgblight_sethsv is supppppper intensive
  26. bool litup = false;
  27. for (uint8_t light_index = 0; light_index < RGBLED_NUM; ++light_index) {
  28. if (lights[light_index].enabled && sync_timer_elapsed(lights[light_index].timer) > 10) {
  29. rgblight_fadeout *light = &lights[light_index];
  30. litup = true;
  31. if (light->life) {
  32. light->life -= 1;
  33. if (get_highest_layer(layer_state) == 0) {
  34. sethsv(light->hue + rand() % 0xF, 255, light->life, (LED_TYPE *)&led[light_index]);
  35. }
  36. light->timer = sync_timer_read();
  37. } else {
  38. if (light->enabled && get_highest_layer(layer_state) == 0) {
  39. rgblight_sethsv_default_helper(light_index);
  40. }
  41. litup = light->enabled = false;
  42. }
  43. }
  44. }
  45. if (litup && get_highest_layer(layer_state) == 0) {
  46. rgblight_set();
  47. }
  48. }
  49. /* Triggers a LED to fade/twinkle.
  50. * This function handles the selection of the LED and prepres for it to be used.
  51. */
  52. void start_rgb_light(void) {
  53. uint8_t indices[RGBLED_NUM];
  54. uint8_t indices_count = 0;
  55. uint8_t min_life = 0xFF;
  56. uint8_t min_life_index = -1;
  57. for (uint8_t index = 0; index < RGBLED_NUM; ++index) {
  58. if (lights[index].enabled) {
  59. if (min_life_index == -1 || lights[index].life < min_life) {
  60. min_life = lights[index].life;
  61. min_life_index = index;
  62. }
  63. continue;
  64. }
  65. indices[indices_count] = index;
  66. ++indices_count;
  67. }
  68. uint8_t light_index;
  69. if (!indices_count) {
  70. light_index = min_life_index;
  71. } else {
  72. light_index = indices[rand() % indices_count];
  73. }
  74. rgblight_fadeout *light = &lights[light_index];
  75. light->enabled = true;
  76. light->timer = sync_timer_read();
  77. light->life = 0xC0 + rand() % 0x40;
  78. light->hue = rgblight_get_hue() + (rand() % 0xB4) - 0x54;
  79. rgblight_sethsv_at(light->hue, 255, light->life, light_index);
  80. }
  81. # endif
  82. bool process_record_user_rgb_light(uint16_t keycode, keyrecord_t *record) {
  83. uint16_t temp_keycode = keycode;
  84. // Filter out the actual keycode from MT and LT keys.
  85. if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) {
  86. temp_keycode &= 0xFF;
  87. }
  88. switch (temp_keycode) {
  89. # ifdef RGBLIGHT_TWINKLE
  90. case KC_A ... KC_SLASH:
  91. case KC_F1 ... KC_F12:
  92. case KC_INSERT ... KC_UP:
  93. case KC_KP_SLASH ... KC_KP_DOT:
  94. case KC_F13 ... KC_F24:
  95. case KC_AUDIO_MUTE ... KC_MEDIA_REWIND:
  96. if (record->event.pressed) {
  97. start_rgb_light();
  98. }
  99. break;
  100. # endif // RGBLIGHT_TWINKLE
  101. }
  102. return true;
  103. }
  104. # if defined(RGBLIGHT_STARTUP_ANIMATION)
  105. static bool is_enabled;
  106. static bool is_rgblight_startup;
  107. static uint8_t old_hue;
  108. static uint16_t rgblight_startup_loop_timer;
  109. # endif
  110. void keyboard_post_init_rgb_light(void) {
  111. # if defined(RGBLIGHT_STARTUP_ANIMATION)
  112. is_enabled = rgblight_is_enabled();
  113. if (userspace_config.rgb_layer_change) {
  114. rgblight_enable_noeeprom();
  115. }
  116. if (rgblight_is_enabled()) {
  117. layer_state_set_rgb_light(layer_state);
  118. old_hue = rgblight_get_hue();
  119. rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT);
  120. is_rgblight_startup = true;
  121. }
  122. # endif
  123. layer_state_set_rgb_light(layer_state);
  124. }
  125. void matrix_scan_rgb_light(void) {
  126. # ifdef RGBLIGHT_TWINKLE
  127. scan_rgblight_fadeout();
  128. # endif // RGBLIGHT_ENABLE
  129. # if defined(RGBLIGHT_STARTUP_ANIMATION)
  130. if (is_rgblight_startup && is_keyboard_master()) {
  131. if (sync_timer_elapsed(rgblight_startup_loop_timer) > 10) {
  132. static uint8_t counter;
  133. counter++;
  134. rgblight_sethsv_noeeprom((counter + old_hue) % 255, 255, 255);
  135. rgblight_startup_loop_timer = sync_timer_read();
  136. if (counter == 255) {
  137. is_rgblight_startup = false;
  138. if (!is_enabled) {
  139. rgblight_disable_noeeprom();
  140. }
  141. if (userspace_config.rgb_layer_change) {
  142. layer_state_set_rgb_light(layer_state);
  143. }
  144. }
  145. }
  146. }
  147. # endif
  148. }
  149. void rgblight_set_hsv_and_mode(uint8_t hue, uint8_t sat, uint8_t val, uint8_t mode) {
  150. rgblight_sethsv_noeeprom(hue, sat, val);
  151. // wait_us(175); // Add a slight delay between color and mode to ensure it's processed correctly
  152. rgblight_mode_noeeprom(mode);
  153. }
  154. layer_state_t layer_state_set_rgb_light(layer_state_t state) {
  155. # ifdef RGBLIGHT_ENABLE
  156. if (userspace_config.rgb_layer_change) {
  157. switch (get_highest_layer(state | default_layer_state)) {
  158. case _MACROS: // mouse
  159. if (!layer_state_cmp(state, _GAMEPAD) && !layer_state_cmp(state, _DIABLO)) {
  160. rgblight_set_hsv_and_mode(HSV_CHARTREUSE, RGBLIGHT_MODE_BREATHING + 3);
  161. }
  162. break;
  163. case _MEDIA:
  164. rgblight_set_hsv_and_mode(HSV_CHARTREUSE, RGBLIGHT_MODE_KNIGHT + 1);
  165. break;
  166. case _GAMEPAD:
  167. rgblight_set_hsv_and_mode(HSV_ORANGE, RGBLIGHT_MODE_SNAKE + 2);
  168. break;
  169. case _DIABLO:
  170. rgblight_set_hsv_and_mode(HSV_RED, RGBLIGHT_MODE_BREATHING + 3);
  171. break;
  172. case _RAISE:
  173. rgblight_set_hsv_and_mode(HSV_YELLOW, RGBLIGHT_MODE_BREATHING + 3);
  174. break;
  175. case _LOWER:
  176. rgblight_set_hsv_and_mode(HSV_GREEN, RGBLIGHT_MODE_BREATHING + 3);
  177. break;
  178. case _ADJUST:
  179. rgblight_set_hsv_and_mode(HSV_RED, RGBLIGHT_MODE_KNIGHT + 2);
  180. break;
  181. case _COLEMAK:
  182. rgblight_set_hsv_and_mode(HSV_MAGENTA, RGBLIGHT_MODE_STATIC_LIGHT);
  183. break;
  184. case _DVORAK:
  185. rgblight_set_hsv_and_mode(HSV_SPRINGGREEN, RGBLIGHT_MODE_STATIC_LIGHT);
  186. break;
  187. case _WORKMAN:
  188. rgblight_set_hsv_and_mode(HSV_GOLDENROD, RGBLIGHT_MODE_STATIC_LIGHT);
  189. break;
  190. case _NORMAN:
  191. rgblight_set_hsv_and_mode(HSV_CORAL, RGBLIGHT_MODE_STATIC_LIGHT);
  192. break;
  193. case _MALTRON:
  194. rgblight_set_hsv_and_mode(HSV_YELLOW, RGBLIGHT_MODE_STATIC_LIGHT);
  195. break;
  196. case _EUCALYN:
  197. rgblight_set_hsv_and_mode(HSV_PINK, RGBLIGHT_MODE_STATIC_LIGHT);
  198. break;
  199. case _CARPLAX:
  200. rgblight_set_hsv_and_mode(HSV_BLUE, RGBLIGHT_MODE_STATIC_LIGHT);
  201. break;
  202. default:
  203. rgblight_set_hsv_and_mode(HSV_CYAN, RGBLIGHT_MODE_STATIC_LIGHT);
  204. break;
  205. }
  206. }
  207. # endif // RGBLIGHT_ENABLE
  208. return state;
  209. }
  210. #endif