You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

325 lines
11 KiB

  1. #include "curry.h"
  2. #include "rgb_lighting_user.h"
  3. extern rgblight_config_t rgblight_config;
  4. bool has_initialized;
  5. void rgblight_sethsv_default_helper(uint8_t index) { rgblight_sethsv_at(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, index); }
  6. /* Custom indicators for modifiers.
  7. * This allows for certain lights to be lit up, based on what mods are active, giving some visual feedback.
  8. * This is especially useful for One Shot Mods, since it's not always obvious if they're still lit up.
  9. */
  10. #if defined(INDICATOR_LIGHTS)
  11. void set_rgb_indicators(uint8_t this_mod, uint8_t this_led, uint8_t this_osm) {
  12. if (userspace_config.rgb_layer_change && get_highest_layer(layer_state) == 0) {
  13. if ((this_mod | this_osm) & MOD_MASK_SHIFT || this_led & (1 << USB_LED_CAPS_LOCK)) {
  14. # ifdef SHFT_LED1
  15. rgblight_sethsv_at(120, 255, 255, SHFT_LED1);
  16. # endif // SHFT_LED1
  17. # ifdef SHFT_LED2
  18. rgblight_sethsv_at(120, 255, 255, SHFT_LED2);
  19. # endif // SHFT_LED2
  20. } else {
  21. # ifdef SHFT_LED1
  22. rgblight_sethsv_default_helper(SHFT_LED1);
  23. # endif // SHFT_LED1
  24. # ifdef SHFT_LED2
  25. rgblight_sethsv_default_helper(SHFT_LED2);
  26. # endif // SHFT_LED2
  27. }
  28. if ((this_mod | this_osm) & MOD_MASK_CTRL) {
  29. # ifdef CTRL_LED1
  30. rgblight_sethsv_at(0, 255, 255, CTRL_LED1);
  31. # endif // CTRL_LED1
  32. # ifdef CTRL_LED2
  33. rgblight_sethsv_at(0, 255, 255, CTRL_LED2);
  34. # endif // CTRL_LED2
  35. } else {
  36. # ifdef CTRL_LED1
  37. rgblight_sethsv_default_helper(CTRL_LED1);
  38. # endif // CTRL_LED1
  39. # ifdef CTRL_LED2
  40. rgblight_sethsv_default_helper(CTRL_LED2);
  41. # endif // CTRL_LED2
  42. }
  43. if ((this_mod | this_osm) & MOD_MASK_GUI) {
  44. # ifdef GUI_LED1
  45. rgblight_sethsv_at(51, 255, 255, GUI_LED1);
  46. # endif // GUI_LED1
  47. # ifdef GUI_LED2
  48. rgblight_sethsv_at(51, 255, 255, GUI_LED2);
  49. # endif // GUI_LED2
  50. } else {
  51. # ifdef GUI_LED1
  52. rgblight_sethsv_default_helper(GUI_LED1);
  53. # endif // GUI_LED1
  54. # ifdef GUI_LED2
  55. rgblight_sethsv_default_helper(GUI_LED2);
  56. # endif // GUI_LED2
  57. }
  58. if ((this_mod | this_osm) & MOD_MASK_ALT) {
  59. # ifdef ALT_LED1
  60. rgblight_sethsv_at(240, 255, 255, ALT_LED1);
  61. # endif // ALT_LED1
  62. # ifdef GUI_LED2
  63. rgblight_sethsv_at(240, 255, 255, ALT_LED2);
  64. # endif // GUI_LED2
  65. } else {
  66. # ifdef GUI_LED1
  67. rgblight_sethsv_default_helper(ALT_LED1);
  68. # endif // GUI_LED1
  69. # ifdef GUI_LED2
  70. rgblight_sethsv_default_helper(ALT_LED2);
  71. # endif // GUI_LED2
  72. }
  73. }
  74. }
  75. /* Function for the indicators */
  76. void matrix_scan_indicator(void) {
  77. if (has_initialized) {
  78. set_rgb_indicators(get_mods(), host_keyboard_leds(), get_oneshot_mods());
  79. }
  80. }
  81. #endif // INDICATOR_LIGHTS
  82. #if defined(RGBLIGHT_TWINKLE)
  83. static rgblight_fadeout lights[RGBLED_NUM];
  84. __attribute__((weak)) bool rgblight_twinkle_is_led_used_keymap(uint8_t index) { return false; }
  85. /* This function checks for used LEDs. This way, collisions don't occur and cause weird rendering */
  86. bool rgblight_twinkle_is_led_used(uint8_t index) {
  87. switch (index) {
  88. # ifdef INDICATOR_LIGHTS
  89. # ifdef SHFT_LED1
  90. case SHFT_LED1:
  91. return true;
  92. # endif // SHFT_LED1
  93. # ifdef SHFT_LED2
  94. case SHFT_LED2:
  95. return true;
  96. # endif // SHFT_LED2
  97. # ifdef CTRL_LED1
  98. case CTRL_LED1:
  99. return true;
  100. # endif // CTRL_LED1
  101. # ifdef CTRL_LED2
  102. case CTRL_LED2:
  103. return true;
  104. # endif // CTRL_LED2
  105. # ifdef GUI_LED1
  106. case GUI_LED1:
  107. return true;
  108. # endif // GUI_LED1
  109. # ifdef GUI_LED2
  110. case GUI_LED2:
  111. return true;
  112. # endif // GUI_LED2
  113. # ifdef ALT_LED1
  114. case ALT_LED1:
  115. return true;
  116. # endif // ALT_LED1
  117. # ifdef ALT_LED2
  118. case ALT_LED2:
  119. return true;
  120. # endif // ALT_LED2
  121. # endif // INDICATOR_LIGHTS
  122. default:
  123. return rgblight_twinkle_is_led_used_keymap(index);
  124. }
  125. }
  126. /* Handler for fading/twinkling effect */
  127. void scan_rgblight_fadeout(void) { // Don't effing change this function .... rgblight_sethsv is supppppper intensive
  128. bool litup = false;
  129. for (uint8_t light_index = 0; light_index < RGBLED_NUM; ++light_index) {
  130. if (lights[light_index].enabled && timer_elapsed(lights[light_index].timer) > 10) {
  131. rgblight_fadeout *light = &lights[light_index];
  132. litup = true;
  133. if (light->life) {
  134. light->life -= 1;
  135. if (get_highest_layer(layer_state) == 0) {
  136. sethsv(light->hue + rand() % 0xF, 255, light->life, (LED_TYPE *)&led[light_index]);
  137. }
  138. light->timer = timer_read();
  139. } else {
  140. if (light->enabled && get_highest_layer(layer_state) == 0) {
  141. rgblight_sethsv_default_helper(light_index);
  142. }
  143. litup = light->enabled = false;
  144. }
  145. }
  146. }
  147. if (litup && get_highest_layer(layer_state) == 0) {
  148. rgblight_set();
  149. }
  150. }
  151. /* Triggers a LED to fade/twinkle.
  152. * This function handles the selection of the LED and prepres for it to be used.
  153. */
  154. void start_rgb_light(void) {
  155. uint8_t indices[RGBLED_NUM];
  156. uint8_t indices_count = 0;
  157. uint8_t min_life = 0xFF;
  158. uint8_t min_life_index = -1;
  159. for (uint8_t index = 0; index < RGBLED_NUM; ++index) {
  160. if (rgblight_twinkle_is_led_used(index)) {
  161. continue;
  162. }
  163. if (lights[index].enabled) {
  164. if (min_life_index == -1 || lights[index].life < min_life) {
  165. min_life = lights[index].life;
  166. min_life_index = index;
  167. }
  168. continue;
  169. }
  170. indices[indices_count] = index;
  171. ++indices_count;
  172. }
  173. uint8_t light_index;
  174. if (!indices_count) {
  175. light_index = min_life_index;
  176. } else {
  177. light_index = indices[rand() % indices_count];
  178. }
  179. rgblight_fadeout *light = &lights[light_index];
  180. light->enabled = true;
  181. light->timer = timer_read();
  182. light->life = 0xC0 + rand() % 0x40;
  183. light->hue = rgblight_config.hue + (rand() % 0xB4) - 0x54;
  184. rgblight_sethsv_at(light->hue, 255, light->life, light_index);
  185. }
  186. #endif
  187. bool process_record_user_rgb(uint16_t keycode, keyrecord_t *record) {
  188. uint16_t temp_keycode = keycode;
  189. // Filter out the actual keycode from MT and LT keys.
  190. if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) {
  191. temp_keycode &= 0xFF;
  192. }
  193. switch (temp_keycode) {
  194. #if defined(RGBLIGHT_TWINKLE)
  195. case KC_A ... KC_SLASH:
  196. case KC_F1 ... KC_F12:
  197. case KC_INSERT ... KC_UP:
  198. case KC_KP_SLASH ... KC_KP_DOT:
  199. case KC_F13 ... KC_F24:
  200. case KC_AUDIO_MUTE ... KC_MEDIA_REWIND:
  201. if (record->event.pressed) {
  202. start_rgb_light();
  203. }
  204. break;
  205. #endif // RGBLIGHT_TWINKLE
  206. case KC_RGB_T: // This allows me to use underglow as layer indication, or as normal
  207. if (record->event.pressed) {
  208. userspace_config.rgb_layer_change ^= 1;
  209. dprintf("rgblight layer change [EEPROM]: %u\n", userspace_config.rgb_layer_change);
  210. eeconfig_update_user(userspace_config.raw);
  211. if (userspace_config.rgb_layer_change) {
  212. layer_state_set(layer_state); // This is needed to immediately set the layer color (looks better)
  213. }
  214. }
  215. break;
  216. case RGB_MODE_FORWARD ... RGB_MODE_GRADIENT: // quantum_keycodes.h L400 for definitions
  217. if (record->event.pressed) {
  218. bool is_eeprom_updated = false;
  219. // This disables layer indication, as it's assumed that if you're changing this ... you want that disabled
  220. if (userspace_config.rgb_layer_change) {
  221. userspace_config.rgb_layer_change = false;
  222. dprintf("rgblight layer change [EEPROM]: %u\n", userspace_config.rgb_layer_change);
  223. is_eeprom_updated = true;
  224. }
  225. if (is_eeprom_updated) {
  226. eeconfig_update_user(userspace_config.raw);
  227. }
  228. }
  229. break;
  230. }
  231. return true;
  232. }
  233. void keyboard_post_init_rgb(void) {
  234. #if defined(RGBLIGHT_STARTUP_ANIMATION)
  235. bool is_enabled = rgblight_config.enable;
  236. if (userspace_config.rgb_layer_change) {
  237. rgblight_enable_noeeprom();
  238. }
  239. if (rgblight_config.enable) {
  240. layer_state_set_user(layer_state);
  241. uint16_t old_hue = rgblight_config.hue;
  242. rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT);
  243. for (uint16_t i = 255; i > 0; i--) {
  244. rgblight_sethsv_noeeprom((i + old_hue) % 255, 255, 255);
  245. matrix_scan();
  246. wait_ms(10);
  247. }
  248. }
  249. if (!is_enabled) {
  250. rgblight_disable_noeeprom();
  251. }
  252. #endif
  253. layer_state_set_user(layer_state);
  254. }
  255. void matrix_scan_rgb(void) {
  256. #if defined(RGBLIGHT_TWINKLE)
  257. scan_rgblight_fadeout();
  258. #endif // RGBLIGHT_ENABLE
  259. #if defined(INDICATOR_LIGHTS)
  260. matrix_scan_indicator();
  261. #endif
  262. }
  263. void rgblight_set_hsv_and_mode(uint8_t hue, uint8_t sat, uint8_t val, uint8_t mode) {
  264. rgblight_sethsv_noeeprom(hue, sat, val);
  265. wait_us(175); // Add a slight delay between color and mode to ensure it's processed correctly
  266. rgblight_mode_noeeprom(mode);
  267. }
  268. layer_state_t layer_state_set_rgb(layer_state_t state) {
  269. if (userspace_config.rgb_layer_change) {
  270. switch (get_highest_layer(state)) {
  271. case _RAISE:
  272. rgblight_set_hsv_and_mode(HSV_YELLOW, RGBLIGHT_MODE_BREATHING + 3);
  273. break;
  274. case _LOWER:
  275. rgblight_set_hsv_and_mode(HSV_GREEN, RGBLIGHT_MODE_BREATHING + 3);
  276. break;
  277. case _ADJUST:
  278. rgblight_set_hsv_and_mode(HSV_RED, RGBLIGHT_MODE_KNIGHT + 2);
  279. break;
  280. default: // for any other layers, or the default layer
  281. {
  282. uint8_t mode = get_highest_layer(state) == _MODS ? RGBLIGHT_MODE_BREATHING : RGBLIGHT_MODE_STATIC_LIGHT;
  283. switch (get_highest_layer(default_layer_state)) {
  284. case _COLEMAK:
  285. rgblight_set_hsv_and_mode(HSV_MAGENTA, mode);
  286. break;
  287. case _DVORAK:
  288. rgblight_set_hsv_and_mode(HSV_SPRINGGREEN, mode);
  289. break;
  290. case _WORKMAN:
  291. rgblight_set_hsv_and_mode(HSV_GOLDENROD, mode);
  292. break;
  293. default:
  294. rgblight_set_hsv_and_mode(HSV_CYAN, mode);
  295. break;
  296. }
  297. break;
  298. }
  299. }
  300. }
  301. return state;
  302. }