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.

457 lines
14 KiB

  1. /**
  2. * @file rgb_ring.c
  3. * @author astro
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "rgb_ring.h"
  19. #include <string.h>
  20. #include "quantum.h"
  21. #include "rgblight.h"
  22. #include "issi/is31fl3731.h"
  23. #include "i2c_master.h"
  24. #ifndef RGBLIGHT_ENABLE
  25. #error "MUST enable rgblight"
  26. #endif
  27. // rgb ring leds setting
  28. const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {
  29. /* Refer to IS31 manual for these locations
  30. * driver
  31. * | R location
  32. * | | G location
  33. * | | | B location
  34. * | | | | */
  35. {0, C1_1, C3_2, C4_2},
  36. {0, C1_2, C2_2, C4_3},
  37. {0, C1_3, C2_3, C3_3},
  38. {0, C1_4, C2_4, C3_4},
  39. {0, C1_5, C2_5, C3_5},
  40. {0, C1_6, C2_6, C3_6},
  41. {0, C1_7, C2_7, C3_7},
  42. {0, C1_8, C2_8, C3_8},
  43. {0, C9_1, C8_1, C7_1},
  44. {0, C9_2, C8_2, C7_2},
  45. {0, C9_3, C8_3, C7_3},
  46. {0, C9_4, C8_4, C7_4},
  47. {0, C9_5, C8_5, C7_5},
  48. {0, C9_6, C8_6, C7_6},
  49. {0, C9_7, C8_7, C6_6},
  50. {0, C9_8, C7_7, C6_7},
  51. {0, C1_9, C3_10, C4_10},
  52. {0, C1_10, C2_10, C4_11},
  53. {0, C1_11, C2_11, C3_11},
  54. {0, C1_12, C2_12, C3_12},
  55. };
  56. #define RING_OUTER_BEGIN 0
  57. #define RING_OUTER_END 15
  58. #define RING_OUTER_SIZE (RING_OUTER_END + 1 - RING_OUTER_BEGIN)
  59. #define RING_INNER_BEGIN 16
  60. #define RING_INNER_END 19
  61. #define RING_INNER_SIZE (RING_INNER_END + 1 - RING_INNER_BEGIN)
  62. #define SPEED_MAX 100
  63. #define SPEED_STEP 10
  64. typedef enum {
  65. RING_STATE_INIT,
  66. RING_STATE_QMK,
  67. RING_STATE_CUSTOM,
  68. } RING_STATE;
  69. typedef enum {
  70. RING_EFFECT_1,
  71. RING_EFFECT_2,
  72. RING_EFFECT_3,
  73. RING_EFFECT_4,
  74. RING_EFFECT_5,
  75. RING_EFFECT_6,
  76. RING_EFFECT_MAX
  77. } RING_EFFECT;
  78. typedef struct {
  79. uint8_t state;
  80. uint8_t effect;
  81. uint8_t speed;
  82. uint8_t outer_index;
  83. uint8_t inner_index;
  84. uint8_t effect_count;
  85. uint8_t led_begin;
  86. uint8_t led_end;
  87. bool led_forward;
  88. bool led_clear;
  89. } rgb_ring_t;
  90. static rgb_ring_t rgb_ring = {
  91. .state = RING_STATE_INIT,
  92. .effect = RING_EFFECT_1,
  93. .speed = 10,
  94. .outer_index = 0,
  95. .inner_index = 0,
  96. .effect_count = 0,
  97. .led_begin = RING_OUTER_BEGIN,
  98. .led_end = RING_OUTER_END,
  99. .led_forward = true,
  100. .led_clear = false,
  101. };
  102. static void rgb_ring_reset(void)
  103. {
  104. rgb_ring.effect_count = 0;
  105. rgb_ring.led_begin = RING_OUTER_BEGIN;
  106. rgb_ring.led_end = RING_OUTER_END;
  107. rgb_ring.led_forward = true;
  108. rgb_ring.led_clear = false;
  109. }
  110. extern animation_status_t animation_status;
  111. extern rgblight_config_t rgblight_config;
  112. #define EFFECT_TEST_INTERVAL 50
  113. #define EFFECT_TEST_COUNT 5
  114. #define EFFECT_TEST_HUE_STEP 85
  115. #define EFFECT_TEST_VAL_STEP 17
  116. static void testing_mode(void)
  117. {
  118. if (timer_elapsed(animation_status.last_timer) > EFFECT_TEST_INTERVAL) {
  119. HSV h = {rgblight_config.hue, rgblight_config.sat, rgblight_config.val};
  120. RGB c = hsv_to_rgb(h);
  121. //IS31FL3731_set_color_all(c.r, c.g, c.b);
  122. IS31FL3731_set_color_all(0, 0, 0);
  123. IS31FL3731_set_color(rgb_ring.outer_index+RING_OUTER_BEGIN, c.r, c.g, c.b);
  124. h.v = EFFECT_TEST_VAL_STEP*rgb_ring.outer_index;
  125. c = hsv_to_rgb(h);
  126. for (uint8_t i = RING_INNER_BEGIN; i <= RING_INNER_END; i++) {
  127. IS31FL3731_set_color(i, c.r, c.g, c.b);
  128. }
  129. rgb_ring.outer_index = (rgb_ring.outer_index + 1) % RING_OUTER_SIZE;
  130. //rgb_ring.inner_index = (rgb_ring.inner_index + 1) % RING_INNER_SIZE;
  131. if (rgb_ring.outer_index == RING_OUTER_BEGIN) {
  132. rgblight_config.hue += EFFECT_TEST_HUE_STEP;
  133. rgb_ring.effect_count++;
  134. }
  135. animation_status.last_timer = timer_read();
  136. }
  137. if (rgb_ring.effect_count > EFFECT_TEST_COUNT) {
  138. rgb_ring_reset();
  139. rgb_ring.state = RING_STATE_QMK;
  140. rgblight_set();
  141. }
  142. }
  143. static bool need_update(uint32_t max_interval)
  144. {
  145. uint32_t interval = timer_elapsed(animation_status.last_timer);
  146. return (interval*rgb_ring.speed) > max_interval;
  147. }
  148. static void update_effect(uint32_t max_count)
  149. {
  150. if (rgb_ring.effect_count > max_count) {
  151. rgb_ring_reset();
  152. rgb_ring.effect = (rgb_ring.effect + 1) % RING_EFFECT_MAX;
  153. }
  154. }
  155. #define EFFECT_1_INTERVAL 1000
  156. #define EFFECT_1_COUNT 64
  157. #define EFFECT_1_HUE_STEP 15
  158. static void ring_effect_no_1(void)
  159. {
  160. if (need_update(EFFECT_1_INTERVAL)) {
  161. HSV h = {rgblight_config.hue, rgblight_config.sat, rgblight_config.val};
  162. for (uint8_t i = RING_OUTER_BEGIN; i <= RING_OUTER_END; i++) {
  163. RGB c = hsv_to_rgb(h);
  164. IS31FL3731_set_color(i, c.r, c.g, c.b);
  165. }
  166. rgblight_config.hue += EFFECT_1_HUE_STEP;
  167. rgb_ring.effect_count++;
  168. animation_status.last_timer = timer_read();
  169. }
  170. update_effect(EFFECT_1_COUNT);
  171. }
  172. #define EFFECT_2_INTERVAL 1000
  173. #define EFFECT_2_COUNT 64
  174. #define EFFECT_2_HUE_STEP 15
  175. static void ring_effect_no_2(void)
  176. {
  177. if (need_update(EFFECT_2_INTERVAL)) {
  178. IS31FL3731_set_color_all(0, 0, 0);
  179. HSV h = {rgblight_config.hue, rgblight_config.sat, rgblight_config.val};
  180. RGB c = hsv_to_rgb(h);
  181. IS31FL3731_set_color(rgb_ring.led_begin, c.r, c.g, c.b);
  182. IS31FL3731_set_color(rgb_ring.led_end, c.r, c.g, c.b);
  183. rgb_ring.led_begin = (rgb_ring.led_begin + 1) % RING_OUTER_SIZE;
  184. rgb_ring.led_end = (rgb_ring.led_end + RING_OUTER_SIZE - 1) % RING_OUTER_SIZE;
  185. rgblight_config.hue += EFFECT_2_HUE_STEP;
  186. rgb_ring.effect_count++;
  187. animation_status.last_timer = timer_read();
  188. }
  189. update_effect(EFFECT_2_COUNT);
  190. }
  191. #define EFFECT_3_INTERVAL 1000
  192. #define EFFECT_3_COUNT 64
  193. #define EFFECT_3_HUE_STEP 15
  194. static void ring_effect_no_3(void)
  195. {
  196. if (rgb_ring.effect_count == 0) {
  197. IS31FL3731_set_color_all(0, 0, 0);
  198. }
  199. if (need_update(EFFECT_3_INTERVAL)) {
  200. HSV h = {rgblight_config.hue, rgblight_config.sat, rgblight_config.val};
  201. if (rgb_ring.led_clear) {
  202. IS31FL3731_set_color(rgb_ring.led_begin, 0, 0, 0);
  203. IS31FL3731_set_color(rgb_ring.led_end, 0, 0, 0);
  204. } else {
  205. RGB c = hsv_to_rgb(h);
  206. IS31FL3731_set_color(rgb_ring.led_begin, c.r, c.g, c.b);
  207. IS31FL3731_set_color(rgb_ring.led_end, c.r, c.g, c.b);
  208. }
  209. rgb_ring.led_begin = (rgb_ring.led_begin + 1) % RING_OUTER_SIZE;
  210. if (rgb_ring.led_begin == rgb_ring.led_end) {
  211. if (rgb_ring.led_forward) {
  212. rgb_ring.led_begin = RING_OUTER_BEGIN;
  213. rgb_ring.led_end = RING_OUTER_END+1;
  214. } else {
  215. rgb_ring.led_begin = RING_OUTER_BEGIN + RING_OUTER_SIZE/2;
  216. rgb_ring.led_end = RING_OUTER_END+1 - RING_OUTER_SIZE/2;
  217. }
  218. if (!rgb_ring.led_clear) {
  219. rgb_ring.led_forward = !rgb_ring.led_forward;
  220. }
  221. rgb_ring.led_clear = !rgb_ring.led_clear;
  222. }
  223. rgb_ring.led_end = (rgb_ring.led_end + RING_OUTER_SIZE - 1) % RING_OUTER_SIZE;
  224. rgblight_config.hue += EFFECT_3_HUE_STEP;
  225. rgb_ring.effect_count++;
  226. animation_status.last_timer = timer_read();
  227. }
  228. update_effect(EFFECT_3_COUNT);
  229. }
  230. #define EFFECT_4_INTERVAL 1000
  231. #define EFFECT_4_COUNT 64
  232. #define EFFECT_4_STEP 3
  233. static void ring_effect_no_4(void)
  234. {
  235. if (need_update(EFFECT_4_INTERVAL)) {
  236. IS31FL3731_set_color_all(0, 0, 0);
  237. HSV h = {rgblight_config.hue, rgblight_config.sat, rgblight_config.val};
  238. RGB c = hsv_to_rgb(h);
  239. IS31FL3731_set_color(rgb_ring.led_begin, c.r, c.g, c.b);
  240. IS31FL3731_set_color(rgb_ring.led_end, c.r, c.g, c.b);
  241. rgb_ring.led_begin = (rgb_ring.led_begin + EFFECT_4_STEP) % RING_OUTER_SIZE;
  242. rgb_ring.led_end = (rgb_ring.led_end + RING_OUTER_SIZE - EFFECT_4_STEP) % RING_OUTER_SIZE;
  243. rgblight_config.hue += EFFECT_1_HUE_STEP;
  244. rgb_ring.effect_count++;
  245. animation_status.last_timer = timer_read();
  246. }
  247. update_effect(EFFECT_4_COUNT);
  248. }
  249. #define EFFECT_5_INTERVAL 1000
  250. #define EFFECT_5_COUNT 64
  251. #define EFFECT_5_HUE_STEP 16
  252. static void ring_effect_no_5(void)
  253. {
  254. if (need_update(EFFECT_5_INTERVAL)) {
  255. IS31FL3731_set_color_all(0, 0, 0);
  256. for (uint8_t i = RING_INNER_BEGIN; i <= RING_INNER_END; i++) {
  257. HSV h = {rgblight_config.hue, rgblight_config.sat, rgblight_config.val};
  258. RGB c = hsv_to_rgb(h);
  259. IS31FL3731_set_color(i, c.r, c.g, c.b);
  260. }
  261. for (uint8_t i = RING_OUTER_BEGIN; i <= RING_OUTER_END; i++) {
  262. HSV h = {rgblight_config.hue+EFFECT_5_HUE_STEP, rgblight_config.sat, rgblight_config.val};
  263. RGB c = hsv_to_rgb(h);
  264. IS31FL3731_set_color(i, c.r, c.g, c.b);
  265. }
  266. rgblight_config.hue += EFFECT_5_HUE_STEP;
  267. rgb_ring.effect_count++;
  268. animation_status.last_timer = timer_read();
  269. }
  270. update_effect(EFFECT_5_COUNT);
  271. }
  272. #define EFFECT_6_INTERVAL 1000
  273. #define EFFECT_6_COUNT 64
  274. #define EFFECT_I_HUE_STEP 10
  275. #define EFFECT_O_HUE_STEP 10
  276. static void ring_effect_no_6(void)
  277. {
  278. if (need_update(EFFECT_6_INTERVAL)) {
  279. IS31FL3731_set_color_all(0, 0, 0);
  280. for (uint8_t i = RING_INNER_BEGIN; i <= RING_INNER_END; i++) {
  281. HSV h = {rgblight_config.hue+i*EFFECT_I_HUE_STEP, rgblight_config.sat, rgblight_config.val};
  282. RGB c = hsv_to_rgb(h);
  283. IS31FL3731_set_color(i, c.r, c.g, c.b);
  284. }
  285. for (uint8_t i = RING_OUTER_BEGIN; i <= RING_OUTER_END; i++) {
  286. HSV h = {rgblight_config.hue+i*EFFECT_O_HUE_STEP, rgblight_config.sat, rgblight_config.val};
  287. RGB c = hsv_to_rgb(h);
  288. IS31FL3731_set_color(i, c.r, c.g, c.b);
  289. }
  290. rgblight_config.hue += EFFECT_I_HUE_STEP;
  291. rgb_ring.effect_count++;
  292. animation_status.last_timer = timer_read();
  293. }
  294. update_effect(EFFECT_6_COUNT);
  295. }
  296. typedef void(*effect_fun)(void);
  297. static effect_fun effect_funcs[RING_EFFECT_MAX] = {
  298. ring_effect_no_1,
  299. ring_effect_no_2,
  300. ring_effect_no_3,
  301. ring_effect_no_4,
  302. ring_effect_no_5,
  303. ring_effect_no_6,
  304. };
  305. static void custom_effects(void)
  306. {
  307. effect_funcs[rgb_ring.effect]();
  308. }
  309. void rgblight_call_driver(LED_TYPE *start_led, uint8_t num_leds)
  310. {
  311. if (rgb_ring.state != RING_STATE_QMK) {
  312. return;
  313. }
  314. for (uint8_t i = 0; i < num_leds; i++) {
  315. IS31FL3731_set_color(i, start_led[i].r, start_led[i].g, start_led[i].b);
  316. }
  317. }
  318. void rgb_ring_init(void)
  319. {
  320. i2c_init();
  321. IS31FL3731_init(DRIVER_ADDR_1);
  322. for (int index = 0; index < DRIVER_LED_TOTAL; index++) {
  323. bool enabled = true;
  324. IS31FL3731_set_led_control_register(index, enabled, enabled, enabled);
  325. }
  326. IS31FL3731_update_led_control_registers(DRIVER_ADDR_1, 0);
  327. }
  328. void rgb_ring_task(void)
  329. {
  330. switch (rgb_ring.state) {
  331. case RING_STATE_INIT: // testing mode
  332. testing_mode();
  333. break;
  334. case RING_STATE_QMK: // qmk effects
  335. //rgblight_task();
  336. break;
  337. case RING_STATE_CUSTOM: // custom effects
  338. custom_effects();
  339. break;
  340. default:
  341. break;
  342. };
  343. IS31FL3731_update_pwm_buffers(DRIVER_ADDR_1, 0);
  344. }
  345. bool process_record_kb(uint16_t keycode, keyrecord_t *record)
  346. {
  347. if (record->event.pressed) {
  348. switch(keycode) {
  349. case RGB_MODE_FORWARD:
  350. if (rgb_ring.state == RING_STATE_INIT) {
  351. // in testing mode, do nothing
  352. return false;
  353. } else if (rgb_ring.state == RING_STATE_CUSTOM) {
  354. // switch to qmk mode
  355. rgblight_config.mode = 1;
  356. rgb_ring.state = RING_STATE_QMK;
  357. rgblight_mode(rgblight_config.mode);
  358. return false;
  359. } else {
  360. // in qmk mode, switch to custom mode?
  361. if (rgblight_config.mode >= RGBLIGHT_MODES) {
  362. rgb_ring.state = RING_STATE_CUSTOM;
  363. return false;
  364. }
  365. }
  366. break;
  367. case RGB_MODE_REVERSE:
  368. if (rgb_ring.state == RING_STATE_INIT) {
  369. // in testing mode, do nothing
  370. return false;
  371. } else if (rgb_ring.state == RING_STATE_CUSTOM) {
  372. // switch to qmk mode
  373. rgblight_config.mode = RGBLIGHT_MODES;
  374. rgb_ring.state = RING_STATE_QMK;
  375. rgblight_mode(rgblight_config.mode);
  376. return false;
  377. } else {
  378. // in qmk mode, switch to custom mode?
  379. if (rgblight_config.mode <= 1) {
  380. rgb_ring.state = RING_STATE_CUSTOM;
  381. return false;
  382. }
  383. }
  384. break;
  385. case KC_F24:
  386. if (rgb_ring.state == RING_STATE_QMK) {
  387. rgb_ring.state = RING_STATE_CUSTOM;
  388. rgb_ring_reset();
  389. return false;
  390. } else if (rgb_ring.state == RING_STATE_CUSTOM) {
  391. rgb_ring.state = RING_STATE_QMK;
  392. return false;
  393. }
  394. break;
  395. default:
  396. break;
  397. }
  398. }
  399. return process_record_user(keycode, record);
  400. }