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.

991 lines
32 KiB

  1. /* Copyright 2017 Jason Williams
  2. * Copyright 2017 Jack Humbert
  3. * Copyright 2018 Yiancar
  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_matrix.h"
  19. #include "progmem.h"
  20. #include "config.h"
  21. #include "eeprom.h"
  22. #include <string.h>
  23. #include <math.h>
  24. rgb_config_t rgb_matrix_config;
  25. #ifndef MAX
  26. #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
  27. #endif
  28. #ifndef MIN
  29. #define MIN(a,b) ((a) < (b)? (a): (b))
  30. #endif
  31. #ifndef RGB_DISABLE_AFTER_TIMEOUT
  32. #define RGB_DISABLE_AFTER_TIMEOUT 0
  33. #endif
  34. #ifndef RGB_DISABLE_WHEN_USB_SUSPENDED
  35. #define RGB_DISABLE_WHEN_USB_SUSPENDED false
  36. #endif
  37. #ifndef EECONFIG_RGB_MATRIX
  38. #define EECONFIG_RGB_MATRIX EECONFIG_RGBLIGHT
  39. #endif
  40. #if !defined(RGB_MATRIX_MAXIMUM_BRIGHTNESS) || RGB_MATRIX_MAXIMUM_BRIGHTNESS > 255
  41. #define RGB_MATRIX_MAXIMUM_BRIGHTNESS 255
  42. #endif
  43. #ifndef RGB_DIGITAL_RAIN_DROPS
  44. // lower the number for denser effect/wider keyboard
  45. #define RGB_DIGITAL_RAIN_DROPS 24
  46. #endif
  47. #if !defined(DISABLE_RGB_MATRIX_RAINDROPS) || !defined(DISABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS) || !defined(DISABLE_RGB_MATRIX_DIGITAL_RAIN)
  48. #define TRACK_PREVIOUS_EFFECT
  49. #endif
  50. bool g_suspend_state = false;
  51. // Global tick at 20 Hz
  52. uint32_t g_tick = 0;
  53. // Ticks since this key was last hit.
  54. uint8_t g_key_hit[DRIVER_LED_TOTAL];
  55. // Ticks since any key was last hit.
  56. uint32_t g_any_key_hit = 0;
  57. #ifndef PI
  58. #define PI 3.14159265
  59. #endif
  60. uint32_t eeconfig_read_rgb_matrix(void) {
  61. return eeprom_read_dword(EECONFIG_RGB_MATRIX);
  62. }
  63. void eeconfig_update_rgb_matrix(uint32_t val) {
  64. eeprom_update_dword(EECONFIG_RGB_MATRIX, val);
  65. }
  66. void eeconfig_update_rgb_matrix_default(void) {
  67. dprintf("eeconfig_update_rgb_matrix_default\n");
  68. rgb_matrix_config.enable = 1;
  69. #ifndef DISABLE_RGB_MATRIX_CYCLE_ALL
  70. rgb_matrix_config.mode = RGB_MATRIX_CYCLE_LEFT_RIGHT;
  71. #else
  72. // fallback to solid colors if RGB_MATRIX_CYCLE_LEFT_RIGHT is disabled in userspace
  73. rgb_matrix_config.mode = RGB_MATRIX_SOLID_COLOR;
  74. #endif
  75. rgb_matrix_config.hue = 0;
  76. rgb_matrix_config.sat = 255;
  77. rgb_matrix_config.val = RGB_MATRIX_MAXIMUM_BRIGHTNESS;
  78. rgb_matrix_config.speed = 0;
  79. eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
  80. }
  81. void eeconfig_debug_rgb_matrix(void) {
  82. dprintf("rgb_matrix_config eprom\n");
  83. dprintf("rgb_matrix_config.enable = %d\n", rgb_matrix_config.enable);
  84. dprintf("rgb_matrix_config.mode = %d\n", rgb_matrix_config.mode);
  85. dprintf("rgb_matrix_config.hue = %d\n", rgb_matrix_config.hue);
  86. dprintf("rgb_matrix_config.sat = %d\n", rgb_matrix_config.sat);
  87. dprintf("rgb_matrix_config.val = %d\n", rgb_matrix_config.val);
  88. dprintf("rgb_matrix_config.speed = %d\n", rgb_matrix_config.speed);
  89. }
  90. // Last led hit
  91. #define LED_HITS_TO_REMEMBER 8
  92. uint8_t g_last_led_hit[LED_HITS_TO_REMEMBER] = {255};
  93. uint8_t g_last_led_count = 0;
  94. void map_row_column_to_led( uint8_t row, uint8_t column, uint8_t *led_i, uint8_t *led_count) {
  95. rgb_led led;
  96. *led_count = 0;
  97. for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
  98. // map_index_to_led(i, &led);
  99. led = g_rgb_leds[i];
  100. if (row == led.matrix_co.row && column == led.matrix_co.col) {
  101. led_i[*led_count] = i;
  102. (*led_count)++;
  103. }
  104. }
  105. }
  106. void rgb_matrix_update_pwm_buffers(void) {
  107. rgb_matrix_driver.flush();
  108. }
  109. void rgb_matrix_set_color( int index, uint8_t red, uint8_t green, uint8_t blue ) {
  110. rgb_matrix_driver.set_color(index, red, green, blue);
  111. }
  112. void rgb_matrix_set_color_all( uint8_t red, uint8_t green, uint8_t blue ) {
  113. rgb_matrix_driver.set_color_all(red, green, blue);
  114. }
  115. bool process_rgb_matrix(uint16_t keycode, keyrecord_t *record) {
  116. if ( record->event.pressed ) {
  117. uint8_t led[8], led_count;
  118. map_row_column_to_led(record->event.key.row, record->event.key.col, led, &led_count);
  119. if (led_count > 0) {
  120. for (uint8_t i = LED_HITS_TO_REMEMBER; i > 1; i--) {
  121. g_last_led_hit[i - 1] = g_last_led_hit[i - 2];
  122. }
  123. g_last_led_hit[0] = led[0];
  124. g_last_led_count = MIN(LED_HITS_TO_REMEMBER, g_last_led_count + 1);
  125. }
  126. for(uint8_t i = 0; i < led_count; i++)
  127. g_key_hit[led[i]] = 0;
  128. g_any_key_hit = 0;
  129. } else {
  130. #ifdef RGB_MATRIX_KEYRELEASES
  131. uint8_t led[8], led_count;
  132. map_row_column_to_led(record->event.key.row, record->event.key.col, led, &led_count);
  133. for(uint8_t i = 0; i < led_count; i++)
  134. g_key_hit[led[i]] = 255;
  135. g_any_key_hit = 255;
  136. #endif
  137. }
  138. return true;
  139. }
  140. void rgb_matrix_set_suspend_state(bool state) {
  141. g_suspend_state = state;
  142. }
  143. void rgb_matrix_test(void) {
  144. // Mask out bits 4 and 5
  145. // Increase the factor to make the test animation slower (and reduce to make it faster)
  146. uint8_t factor = 10;
  147. switch ( (g_tick & (0b11 << factor)) >> factor )
  148. {
  149. case 0:
  150. {
  151. rgb_matrix_set_color_all( 20, 0, 0 );
  152. break;
  153. }
  154. case 1:
  155. {
  156. rgb_matrix_set_color_all( 0, 20, 0 );
  157. break;
  158. }
  159. case 2:
  160. {
  161. rgb_matrix_set_color_all( 0, 0, 20 );
  162. break;
  163. }
  164. case 3:
  165. {
  166. rgb_matrix_set_color_all( 20, 20, 20 );
  167. break;
  168. }
  169. }
  170. }
  171. // All LEDs off
  172. void rgb_matrix_all_off(void) {
  173. rgb_matrix_set_color_all( 0, 0, 0 );
  174. }
  175. // Solid color
  176. void rgb_matrix_solid_color(void) {
  177. HSV hsv = { .h = rgb_matrix_config.hue, .s = rgb_matrix_config.sat, .v = rgb_matrix_config.val };
  178. RGB rgb = hsv_to_rgb( hsv );
  179. rgb_matrix_set_color_all( rgb.r, rgb.g, rgb.b );
  180. }
  181. void rgb_matrix_solid_reactive(void) {
  182. // Relies on hue being 8-bit and wrapping
  183. for ( int i=0; i<DRIVER_LED_TOTAL; i++ )
  184. {
  185. uint16_t offset2 = g_key_hit[i]<<2;
  186. offset2 = (offset2<=130) ? (130-offset2) : 0;
  187. HSV hsv = { .h = rgb_matrix_config.hue+offset2, .s = 255, .v = rgb_matrix_config.val };
  188. RGB rgb = hsv_to_rgb( hsv );
  189. rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
  190. }
  191. }
  192. // alphas = color1, mods = color2
  193. void rgb_matrix_alphas_mods(void) {
  194. RGB rgb1 = hsv_to_rgb( (HSV){ .h = rgb_matrix_config.hue, .s = rgb_matrix_config.sat, .v = rgb_matrix_config.val } );
  195. RGB rgb2 = hsv_to_rgb( (HSV){ .h = (rgb_matrix_config.hue + 180) % 360, .s = rgb_matrix_config.sat, .v = rgb_matrix_config.val } );
  196. rgb_led led;
  197. for (int i = 0; i < DRIVER_LED_TOTAL; i++) {
  198. led = g_rgb_leds[i];
  199. if ( led.matrix_co.raw < 0xFF ) {
  200. if ( led.modifier )
  201. {
  202. rgb_matrix_set_color( i, rgb2.r, rgb2.g, rgb2.b );
  203. }
  204. else
  205. {
  206. rgb_matrix_set_color( i, rgb1.r, rgb1.g, rgb1.b );
  207. }
  208. }
  209. }
  210. }
  211. void rgb_matrix_gradient_up_down(void) {
  212. int16_t h1 = rgb_matrix_config.hue;
  213. int16_t h2 = (rgb_matrix_config.hue + 180) % 360;
  214. int16_t deltaH = h2 - h1;
  215. // Take the shortest path between hues
  216. if ( deltaH > 127 )
  217. {
  218. deltaH -= 256;
  219. }
  220. else if ( deltaH < -127 )
  221. {
  222. deltaH += 256;
  223. }
  224. // Divide delta by 4, this gives the delta per row
  225. deltaH /= 4;
  226. int16_t s1 = rgb_matrix_config.sat;
  227. int16_t s2 = rgb_matrix_config.hue;
  228. int16_t deltaS = ( s2 - s1 ) / 4;
  229. HSV hsv = { .h = 0, .s = 255, .v = rgb_matrix_config.val };
  230. RGB rgb;
  231. Point point;
  232. for ( int i=0; i<DRIVER_LED_TOTAL; i++ )
  233. {
  234. // map_led_to_point( i, &point );
  235. point = g_rgb_leds[i].point;
  236. // The y range will be 0..64, map this to 0..4
  237. uint8_t y = (point.y>>4);
  238. // Relies on hue being 8-bit and wrapping
  239. hsv.h = rgb_matrix_config.hue + ( deltaH * y );
  240. hsv.s = rgb_matrix_config.sat + ( deltaS * y );
  241. rgb = hsv_to_rgb( hsv );
  242. rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
  243. }
  244. }
  245. void rgb_matrix_raindrops(bool initialize) {
  246. int16_t h1 = rgb_matrix_config.hue;
  247. int16_t h2 = (rgb_matrix_config.hue + 180) % 360;
  248. int16_t deltaH = h2 - h1;
  249. deltaH /= 4;
  250. // Take the shortest path between hues
  251. if ( deltaH > 127 )
  252. {
  253. deltaH -= 256;
  254. }
  255. else if ( deltaH < -127 )
  256. {
  257. deltaH += 256;
  258. }
  259. int16_t s1 = rgb_matrix_config.sat;
  260. int16_t s2 = rgb_matrix_config.sat;
  261. int16_t deltaS = ( s2 - s1 ) / 4;
  262. HSV hsv;
  263. RGB rgb;
  264. // Change one LED every tick, make sure speed is not 0
  265. uint8_t led_to_change = ( g_tick & ( 0x0A / (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed) ) ) == 0 ? rand() % (DRIVER_LED_TOTAL) : 255;
  266. for ( int i=0; i<DRIVER_LED_TOTAL; i++ )
  267. {
  268. // If initialize, all get set to random colors
  269. // If not, all but one will stay the same as before.
  270. if ( initialize || i == led_to_change )
  271. {
  272. hsv.h = h1 + ( deltaH * ( rand() & 0x03 ) );
  273. hsv.s = s1 + ( deltaS * ( rand() & 0x03 ) );
  274. // Override brightness with global brightness control
  275. hsv.v = rgb_matrix_config.val;
  276. rgb = hsv_to_rgb( hsv );
  277. rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
  278. }
  279. }
  280. }
  281. void rgb_matrix_cycle_all(void) {
  282. uint8_t offset = ( g_tick << rgb_matrix_config.speed ) & 0xFF;
  283. rgb_led led;
  284. // Relies on hue being 8-bit and wrapping
  285. for ( int i=0; i<DRIVER_LED_TOTAL; i++ )
  286. {
  287. // map_index_to_led(i, &led);
  288. led = g_rgb_leds[i];
  289. if (led.matrix_co.raw < 0xFF) {
  290. uint16_t offset2 = g_key_hit[i]<<2;
  291. offset2 = (offset2<=63) ? (63-offset2) : 0;
  292. HSV hsv = { .h = offset+offset2, .s = 255, .v = rgb_matrix_config.val };
  293. RGB rgb = hsv_to_rgb( hsv );
  294. rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
  295. }
  296. }
  297. }
  298. void rgb_matrix_cycle_left_right(void) {
  299. uint8_t offset = ( g_tick << rgb_matrix_config.speed ) & 0xFF;
  300. HSV hsv = { .h = 0, .s = 255, .v = rgb_matrix_config.val };
  301. RGB rgb;
  302. Point point;
  303. rgb_led led;
  304. for ( int i=0; i<DRIVER_LED_TOTAL; i++ )
  305. {
  306. // map_index_to_led(i, &led);
  307. led = g_rgb_leds[i];
  308. if (led.matrix_co.raw < 0xFF) {
  309. uint16_t offset2 = g_key_hit[i]<<2;
  310. offset2 = (offset2<=63) ? (63-offset2) : 0;
  311. // map_led_to_point( i, &point );
  312. point = g_rgb_leds[i].point;
  313. // Relies on hue being 8-bit and wrapping
  314. hsv.h = point.x + offset + offset2;
  315. rgb = hsv_to_rgb( hsv );
  316. rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
  317. }
  318. }
  319. }
  320. void rgb_matrix_cycle_up_down(void) {
  321. uint8_t offset = ( g_tick << rgb_matrix_config.speed ) & 0xFF;
  322. HSV hsv = { .h = 0, .s = 255, .v = rgb_matrix_config.val };
  323. RGB rgb;
  324. Point point;
  325. rgb_led led;
  326. for ( int i=0; i<DRIVER_LED_TOTAL; i++ )
  327. {
  328. // map_index_to_led(i, &led);
  329. led = g_rgb_leds[i];
  330. if (led.matrix_co.raw < 0xFF) {
  331. uint16_t offset2 = g_key_hit[i]<<2;
  332. offset2 = (offset2<=63) ? (63-offset2) : 0;
  333. // map_led_to_point( i, &point );
  334. point = g_rgb_leds[i].point;
  335. // Relies on hue being 8-bit and wrapping
  336. hsv.h = point.y + offset + offset2;
  337. rgb = hsv_to_rgb( hsv );
  338. rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
  339. }
  340. }
  341. }
  342. void rgb_matrix_dual_beacon(void) {
  343. HSV hsv = { .h = rgb_matrix_config.hue, .s = rgb_matrix_config.sat, .v = rgb_matrix_config.val };
  344. RGB rgb;
  345. Point point;
  346. double cos_value = cos(g_tick * PI / 128) / 32;
  347. double sin_value = sin(g_tick * PI / 128) / 112;
  348. for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
  349. point = g_rgb_leds[i].point;
  350. hsv.h = ((point.y - 32.0)* cos_value + (point.x - 112.0) * sin_value) * (180) + rgb_matrix_config.hue;
  351. rgb = hsv_to_rgb( hsv );
  352. rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
  353. }
  354. }
  355. void rgb_matrix_rainbow_beacon(void) {
  356. HSV hsv = { .h = rgb_matrix_config.hue, .s = rgb_matrix_config.sat, .v = rgb_matrix_config.val };
  357. RGB rgb;
  358. Point point;
  359. double cos_value = cos(g_tick * PI / 128);
  360. double sin_value = sin(g_tick * PI / 128);
  361. for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
  362. point = g_rgb_leds[i].point;
  363. hsv.h = (1.5 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * (point.y - 32.0)* cos_value + (1.5 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * (point.x - 112.0) * sin_value + rgb_matrix_config.hue;
  364. rgb = hsv_to_rgb( hsv );
  365. rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
  366. }
  367. }
  368. void rgb_matrix_rainbow_pinwheels(void) {
  369. HSV hsv = { .h = rgb_matrix_config.hue, .s = rgb_matrix_config.sat, .v = rgb_matrix_config.val };
  370. RGB rgb;
  371. Point point;
  372. double cos_value = cos(g_tick * PI / 128);
  373. double sin_value = sin(g_tick * PI / 128);
  374. for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
  375. point = g_rgb_leds[i].point;
  376. hsv.h = (2 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * (point.y - 32.0)* cos_value + (2 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * (66 - abs(point.x - 112.0)) * sin_value + rgb_matrix_config.hue;
  377. rgb = hsv_to_rgb( hsv );
  378. rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
  379. }
  380. }
  381. void rgb_matrix_rainbow_moving_chevron(void) {
  382. HSV hsv = { .h = rgb_matrix_config.hue, .s = rgb_matrix_config.sat, .v = rgb_matrix_config.val };
  383. RGB rgb;
  384. Point point;
  385. uint8_t r = 128;
  386. double cos_value = cos(r * PI / 128);
  387. double sin_value = sin(r * PI / 128);
  388. double multiplier = (g_tick / 256.0 * 224);
  389. for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
  390. point = g_rgb_leds[i].point;
  391. hsv.h = (1.5 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * abs(point.y - 32.0)* sin_value + (1.5 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * (point.x - multiplier) * cos_value + rgb_matrix_config.hue;
  392. rgb = hsv_to_rgb( hsv );
  393. rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
  394. }
  395. }
  396. void rgb_matrix_jellybean_raindrops( bool initialize ) {
  397. HSV hsv;
  398. RGB rgb;
  399. // Change one LED every tick, make sure speed is not 0
  400. uint8_t led_to_change = ( g_tick & ( 0x0A / (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed) ) ) == 0 ? rand() % (DRIVER_LED_TOTAL) : 255;
  401. for ( int i=0; i<DRIVER_LED_TOTAL; i++ )
  402. {
  403. // If initialize, all get set to random colors
  404. // If not, all but one will stay the same as before.
  405. if ( initialize || i == led_to_change )
  406. {
  407. hsv.h = rand() & 0xFF;
  408. hsv.s = rand() & 0xFF;
  409. // Override brightness with global brightness control
  410. hsv.v = rgb_matrix_config.val;
  411. rgb = hsv_to_rgb( hsv );
  412. rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
  413. }
  414. }
  415. }
  416. void rgb_matrix_digital_rain( const bool initialize ) {
  417. // algorithm ported from https://github.com/tremby/Kaleidoscope-LEDEffect-DigitalRain
  418. const uint8_t drop_ticks = 28;
  419. const uint8_t pure_green_intensity = 0xd0;
  420. const uint8_t max_brightness_boost = 0xc0;
  421. const uint8_t max_intensity = 0xff;
  422. static uint8_t map[MATRIX_COLS][MATRIX_ROWS] = {{0}};
  423. static uint8_t drop = 0;
  424. if (initialize) {
  425. rgb_matrix_set_color_all(0, 0, 0);
  426. memset(map, 0, sizeof map);
  427. drop = 0;
  428. }
  429. for (uint8_t col = 0; col < MATRIX_COLS; col++) {
  430. for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
  431. if (row == 0 && drop == 0 && rand() < RAND_MAX / RGB_DIGITAL_RAIN_DROPS) {
  432. // top row, pixels have just fallen and we're
  433. // making a new rain drop in this column
  434. map[col][row] = max_intensity;
  435. }
  436. else if (map[col][row] > 0 && map[col][row] < max_intensity) {
  437. // neither fully bright nor dark, decay it
  438. map[col][row]--;
  439. }
  440. // set the pixel colour
  441. uint8_t led, led_count;
  442. map_row_column_to_led(row, col, &led, &led_count);
  443. if (map[col][row] > pure_green_intensity) {
  444. const uint8_t boost = (uint8_t) ((uint16_t) max_brightness_boost
  445. * (map[col][row] - pure_green_intensity) / (max_intensity - pure_green_intensity));
  446. rgb_matrix_set_color(led, boost, max_intensity, boost);
  447. }
  448. else {
  449. const uint8_t green = (uint8_t) ((uint16_t) max_intensity * map[col][row] / pure_green_intensity);
  450. rgb_matrix_set_color(led, 0, green, 0);
  451. }
  452. }
  453. }
  454. if (++drop > drop_ticks) {
  455. // reset drop timer
  456. drop = 0;
  457. for (uint8_t row = MATRIX_ROWS - 1; row > 0; row--) {
  458. for (uint8_t col = 0; col < MATRIX_COLS; col++) {
  459. // if ths is on the bottom row and bright allow decay
  460. if (row == MATRIX_ROWS - 1 && map[col][row] == max_intensity) {
  461. map[col][row]--;
  462. }
  463. // check if the pixel above is bright
  464. if (map[col][row - 1] == max_intensity) {
  465. // allow old bright pixel to decay
  466. map[col][row - 1]--;
  467. // make this pixel bright
  468. map[col][row] = max_intensity;
  469. }
  470. }
  471. }
  472. }
  473. }
  474. void rgb_matrix_multisplash(void) {
  475. // if (g_any_key_hit < 0xFF) {
  476. HSV hsv = { .h = rgb_matrix_config.hue, .s = rgb_matrix_config.sat, .v = rgb_matrix_config.val };
  477. RGB rgb;
  478. rgb_led led;
  479. for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
  480. led = g_rgb_leds[i];
  481. uint16_t c = 0, d = 0;
  482. rgb_led last_led;
  483. // if (g_last_led_count) {
  484. for (uint8_t last_i = 0; last_i < g_last_led_count; last_i++) {
  485. last_led = g_rgb_leds[g_last_led_hit[last_i]];
  486. uint16_t dist = (uint16_t)sqrt(pow(led.point.x - last_led.point.x, 2) + pow(led.point.y - last_led.point.y, 2));
  487. uint16_t effect = (g_key_hit[g_last_led_hit[last_i]] << 2) - dist;
  488. c += MIN(MAX(effect, 0), 255);
  489. d += 255 - MIN(MAX(effect, 0), 255);
  490. }
  491. // } else {
  492. // d = 255;
  493. // }
  494. hsv.h = (rgb_matrix_config.hue + c) % 256;
  495. hsv.v = MAX(MIN(d, 255), 0);
  496. rgb = hsv_to_rgb( hsv );
  497. rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
  498. }
  499. // } else {
  500. // rgb_matrix_set_color_all( 0, 0, 0 );
  501. // }
  502. }
  503. void rgb_matrix_splash(void) {
  504. g_last_led_count = MIN(g_last_led_count, 1);
  505. rgb_matrix_multisplash();
  506. }
  507. void rgb_matrix_solid_multisplash(void) {
  508. // if (g_any_key_hit < 0xFF) {
  509. HSV hsv = { .h = rgb_matrix_config.hue, .s = rgb_matrix_config.sat, .v = rgb_matrix_config.val };
  510. RGB rgb;
  511. rgb_led led;
  512. for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
  513. led = g_rgb_leds[i];
  514. uint16_t d = 0;
  515. rgb_led last_led;
  516. // if (g_last_led_count) {
  517. for (uint8_t last_i = 0; last_i < g_last_led_count; last_i++) {
  518. last_led = g_rgb_leds[g_last_led_hit[last_i]];
  519. uint16_t dist = (uint16_t)sqrt(pow(led.point.x - last_led.point.x, 2) + pow(led.point.y - last_led.point.y, 2));
  520. uint16_t effect = (g_key_hit[g_last_led_hit[last_i]] << 2) - dist;
  521. d += 255 - MIN(MAX(effect, 0), 255);
  522. }
  523. // } else {
  524. // d = 255;
  525. // }
  526. hsv.v = MAX(MIN(d, 255), 0);
  527. rgb = hsv_to_rgb( hsv );
  528. rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
  529. }
  530. // } else {
  531. // rgb_matrix_set_color_all( 0, 0, 0 );
  532. // }
  533. }
  534. void rgb_matrix_solid_splash(void) {
  535. g_last_led_count = MIN(g_last_led_count, 1);
  536. rgb_matrix_solid_multisplash();
  537. }
  538. // Needs eeprom access that we don't have setup currently
  539. void rgb_matrix_custom(void) {
  540. // HSV hsv;
  541. // RGB rgb;
  542. // for ( int i=0; i<DRIVER_LED_TOTAL; i++ )
  543. // {
  544. // backlight_get_key_color(i, &hsv);
  545. // // Override brightness with global brightness control
  546. // hsv.v = rgb_matrix_config.val;
  547. // rgb = hsv_to_rgb( hsv );
  548. // rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
  549. // }
  550. }
  551. void rgb_matrix_task(void) {
  552. #ifdef TRACK_PREVIOUS_EFFECT
  553. static uint8_t toggle_enable_last = 255;
  554. #endif
  555. if (!rgb_matrix_config.enable) {
  556. rgb_matrix_all_off();
  557. rgb_matrix_indicators();
  558. #ifdef TRACK_PREVIOUS_EFFECT
  559. toggle_enable_last = rgb_matrix_config.enable;
  560. #endif
  561. return;
  562. }
  563. // delay 1 second before driving LEDs or doing anything else
  564. static uint8_t startup_tick = 0;
  565. if ( startup_tick < 20 ) {
  566. startup_tick++;
  567. return;
  568. }
  569. g_tick++;
  570. if ( g_any_key_hit < 0xFFFFFFFF ) {
  571. g_any_key_hit++;
  572. }
  573. for ( int led = 0; led < DRIVER_LED_TOTAL; led++ ) {
  574. if ( g_key_hit[led] < 255 ) {
  575. if (g_key_hit[led] == 254)
  576. g_last_led_count = MAX(g_last_led_count - 1, 0);
  577. g_key_hit[led]++;
  578. }
  579. }
  580. // Factory default magic value
  581. if ( rgb_matrix_config.mode == 255 ) {
  582. rgb_matrix_test();
  583. return;
  584. }
  585. // Ideally we would also stop sending zeros to the LED driver PWM buffers
  586. // while suspended and just do a software shutdown. This is a cheap hack for now.
  587. bool suspend_backlight = ((g_suspend_state && RGB_DISABLE_WHEN_USB_SUSPENDED) ||
  588. (RGB_DISABLE_AFTER_TIMEOUT > 0 && g_any_key_hit > RGB_DISABLE_AFTER_TIMEOUT * 60 * 20));
  589. uint8_t effect = suspend_backlight ? 0 : rgb_matrix_config.mode;
  590. #ifdef TRACK_PREVIOUS_EFFECT
  591. // Keep track of the effect used last time,
  592. // detect change in effect, so each effect can
  593. // have an optional initialization.
  594. static uint8_t effect_last = 255;
  595. bool initialize = (effect != effect_last) || (rgb_matrix_config.enable != toggle_enable_last);
  596. effect_last = effect;
  597. toggle_enable_last = rgb_matrix_config.enable;
  598. #endif
  599. // this gets ticked at 20 Hz.
  600. // each effect can opt to do calculations
  601. // and/or request PWM buffer updates.
  602. switch ( effect ) {
  603. case RGB_MATRIX_SOLID_COLOR:
  604. rgb_matrix_solid_color();
  605. break;
  606. #ifndef DISABLE_RGB_MATRIX_ALPHAS_MODS
  607. case RGB_MATRIX_ALPHAS_MODS:
  608. rgb_matrix_alphas_mods();
  609. break;
  610. #endif
  611. #ifndef DISABLE_RGB_MATRIX_DUAL_BEACON
  612. case RGB_MATRIX_DUAL_BEACON:
  613. rgb_matrix_dual_beacon();
  614. break;
  615. #endif
  616. #ifndef DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
  617. case RGB_MATRIX_GRADIENT_UP_DOWN:
  618. rgb_matrix_gradient_up_down();
  619. break;
  620. #endif
  621. #ifndef DISABLE_RGB_MATRIX_RAINDROPS
  622. case RGB_MATRIX_RAINDROPS:
  623. rgb_matrix_raindrops( initialize );
  624. break;
  625. #endif
  626. #ifndef DISABLE_RGB_MATRIX_CYCLE_ALL
  627. case RGB_MATRIX_CYCLE_ALL:
  628. rgb_matrix_cycle_all();
  629. break;
  630. #endif
  631. #ifndef DISABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
  632. case RGB_MATRIX_CYCLE_LEFT_RIGHT:
  633. rgb_matrix_cycle_left_right();
  634. break;
  635. #endif
  636. #ifndef DISABLE_RGB_MATRIX_CYCLE_UP_DOWN
  637. case RGB_MATRIX_CYCLE_UP_DOWN:
  638. rgb_matrix_cycle_up_down();
  639. break;
  640. #endif
  641. #ifndef DISABLE_RGB_MATRIX_RAINBOW_BEACON
  642. case RGB_MATRIX_RAINBOW_BEACON:
  643. rgb_matrix_rainbow_beacon();
  644. break;
  645. #endif
  646. #ifndef DISABLE_RGB_MATRIX_RAINBOW_PINWHEELS
  647. case RGB_MATRIX_RAINBOW_PINWHEELS:
  648. rgb_matrix_rainbow_pinwheels();
  649. break;
  650. #endif
  651. #ifndef DISABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
  652. case RGB_MATRIX_RAINBOW_MOVING_CHEVRON:
  653. rgb_matrix_rainbow_moving_chevron();
  654. break;
  655. #endif
  656. #ifndef DISABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
  657. case RGB_MATRIX_JELLYBEAN_RAINDROPS:
  658. rgb_matrix_jellybean_raindrops( initialize );
  659. break;
  660. #endif
  661. #ifndef DISABLE_RGB_MATRIX_DIGITAL_RAIN
  662. case RGB_MATRIX_DIGITAL_RAIN:
  663. rgb_matrix_digital_rain( initialize );
  664. break;
  665. #endif
  666. #ifdef RGB_MATRIX_KEYPRESSES
  667. #ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE
  668. case RGB_MATRIX_SOLID_REACTIVE:
  669. rgb_matrix_solid_reactive();
  670. break;
  671. #endif
  672. #ifndef DISABLE_RGB_MATRIX_SPLASH
  673. case RGB_MATRIX_SPLASH:
  674. rgb_matrix_splash();
  675. break;
  676. #endif
  677. #ifndef DISABLE_RGB_MATRIX_MULTISPLASH
  678. case RGB_MATRIX_MULTISPLASH:
  679. rgb_matrix_multisplash();
  680. break;
  681. #endif
  682. #ifndef DISABLE_RGB_MATRIX_SOLID_SPLASH
  683. case RGB_MATRIX_SOLID_SPLASH:
  684. rgb_matrix_solid_splash();
  685. break;
  686. #endif
  687. #ifndef DISABLE_RGB_MATRIX_SOLID_MULTISPLASH
  688. case RGB_MATRIX_SOLID_MULTISPLASH:
  689. rgb_matrix_solid_multisplash();
  690. break;
  691. #endif
  692. #endif
  693. default:
  694. rgb_matrix_custom();
  695. break;
  696. }
  697. if ( ! suspend_backlight ) {
  698. rgb_matrix_indicators();
  699. }
  700. }
  701. void rgb_matrix_indicators(void) {
  702. rgb_matrix_indicators_kb();
  703. rgb_matrix_indicators_user();
  704. }
  705. __attribute__((weak))
  706. void rgb_matrix_indicators_kb(void) {}
  707. __attribute__((weak))
  708. void rgb_matrix_indicators_user(void) {}
  709. // void rgb_matrix_set_indicator_index( uint8_t *index, uint8_t row, uint8_t column )
  710. // {
  711. // if ( row >= MATRIX_ROWS )
  712. // {
  713. // // Special value, 255=none, 254=all
  714. // *index = row;
  715. // }
  716. // else
  717. // {
  718. // // This needs updated to something like
  719. // // uint8_t led[8], led_count;
  720. // // map_row_column_to_led(row,column,led,&led_count);
  721. // // for(uint8_t i = 0; i < led_count; i++)
  722. // map_row_column_to_led( row, column, index );
  723. // }
  724. // }
  725. void rgb_matrix_init(void) {
  726. rgb_matrix_driver.init();
  727. // TODO: put the 1 second startup delay here?
  728. // clear the key hits
  729. for ( int led=0; led<DRIVER_LED_TOTAL; led++ ) {
  730. g_key_hit[led] = 255;
  731. }
  732. if (!eeconfig_is_enabled()) {
  733. dprintf("rgb_matrix_init_drivers eeconfig is not enabled.\n");
  734. eeconfig_init();
  735. eeconfig_update_rgb_matrix_default();
  736. }
  737. rgb_matrix_config.raw = eeconfig_read_rgb_matrix();
  738. if (!rgb_matrix_config.mode) {
  739. dprintf("rgb_matrix_init_drivers rgb_matrix_config.mode = 0. Write default values to EEPROM.\n");
  740. eeconfig_update_rgb_matrix_default();
  741. rgb_matrix_config.raw = eeconfig_read_rgb_matrix();
  742. }
  743. eeconfig_debug_rgb_matrix(); // display current eeprom values
  744. }
  745. // Deals with the messy details of incrementing an integer
  746. static uint8_t increment( uint8_t value, uint8_t step, uint8_t min, uint8_t max ) {
  747. int16_t new_value = value;
  748. new_value += step;
  749. return MIN( MAX( new_value, min ), max );
  750. }
  751. static uint8_t decrement( uint8_t value, uint8_t step, uint8_t min, uint8_t max ) {
  752. int16_t new_value = value;
  753. new_value -= step;
  754. return MIN( MAX( new_value, min ), max );
  755. }
  756. // void *backlight_get_custom_key_color_eeprom_address( uint8_t led )
  757. // {
  758. // // 3 bytes per color
  759. // return EECONFIG_RGB_MATRIX + ( led * 3 );
  760. // }
  761. // void backlight_get_key_color( uint8_t led, HSV *hsv )
  762. // {
  763. // void *address = backlight_get_custom_key_color_eeprom_address( led );
  764. // hsv->h = eeprom_read_byte(address);
  765. // hsv->s = eeprom_read_byte(address+1);
  766. // hsv->v = eeprom_read_byte(address+2);
  767. // }
  768. // void backlight_set_key_color( uint8_t row, uint8_t column, HSV hsv )
  769. // {
  770. // uint8_t led[8], led_count;
  771. // map_row_column_to_led(row,column,led,&led_count);
  772. // for(uint8_t i = 0; i < led_count; i++) {
  773. // if ( led[i] < DRIVER_LED_TOTAL )
  774. // {
  775. // void *address = backlight_get_custom_key_color_eeprom_address(led[i]);
  776. // eeprom_update_byte(address, hsv.h);
  777. // eeprom_update_byte(address+1, hsv.s);
  778. // eeprom_update_byte(address+2, hsv.v);
  779. // }
  780. // }
  781. // }
  782. uint32_t rgb_matrix_get_tick(void) {
  783. return g_tick;
  784. }
  785. void rgb_matrix_toggle(void) {
  786. rgb_matrix_config.enable ^= 1;
  787. eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
  788. }
  789. void rgb_matrix_enable(void) {
  790. rgb_matrix_config.enable = 1;
  791. eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
  792. }
  793. void rgb_matrix_enable_noeeprom(void) {
  794. rgb_matrix_config.enable = 1;
  795. }
  796. void rgb_matrix_disable(void) {
  797. rgb_matrix_config.enable = 0;
  798. eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
  799. }
  800. void rgb_matrix_disable_noeeprom(void) {
  801. rgb_matrix_config.enable = 0;
  802. }
  803. void rgb_matrix_step(void) {
  804. rgb_matrix_config.mode++;
  805. if (rgb_matrix_config.mode >= RGB_MATRIX_EFFECT_MAX)
  806. rgb_matrix_config.mode = 1;
  807. eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
  808. }
  809. void rgb_matrix_step_reverse(void) {
  810. rgb_matrix_config.mode--;
  811. if (rgb_matrix_config.mode < 1)
  812. rgb_matrix_config.mode = RGB_MATRIX_EFFECT_MAX - 1;
  813. eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
  814. }
  815. void rgb_matrix_increase_hue(void) {
  816. rgb_matrix_config.hue = increment( rgb_matrix_config.hue, 8, 0, 255 );
  817. eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
  818. }
  819. void rgb_matrix_decrease_hue(void) {
  820. rgb_matrix_config.hue = decrement( rgb_matrix_config.hue, 8, 0, 255 );
  821. eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
  822. }
  823. void rgb_matrix_increase_sat(void) {
  824. rgb_matrix_config.sat = increment( rgb_matrix_config.sat, 8, 0, 255 );
  825. eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
  826. }
  827. void rgb_matrix_decrease_sat(void) {
  828. rgb_matrix_config.sat = decrement( rgb_matrix_config.sat, 8, 0, 255 );
  829. eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
  830. }
  831. void rgb_matrix_increase_val(void) {
  832. rgb_matrix_config.val = increment( rgb_matrix_config.val, 8, 0, RGB_MATRIX_MAXIMUM_BRIGHTNESS );
  833. eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
  834. }
  835. void rgb_matrix_decrease_val(void) {
  836. rgb_matrix_config.val = decrement( rgb_matrix_config.val, 8, 0, RGB_MATRIX_MAXIMUM_BRIGHTNESS );
  837. eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
  838. }
  839. void rgb_matrix_increase_speed(void) {
  840. rgb_matrix_config.speed = increment( rgb_matrix_config.speed, 1, 0, 3 );
  841. eeconfig_update_rgb_matrix(rgb_matrix_config.raw);//EECONFIG needs to be increased to support this
  842. }
  843. void rgb_matrix_decrease_speed(void) {
  844. rgb_matrix_config.speed = decrement( rgb_matrix_config.speed, 1, 0, 3 );
  845. eeconfig_update_rgb_matrix(rgb_matrix_config.raw);//EECONFIG needs to be increased to support this
  846. }
  847. void rgb_matrix_mode(uint8_t mode) {
  848. rgb_matrix_config.mode = mode;
  849. eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
  850. }
  851. void rgb_matrix_mode_noeeprom(uint8_t mode) {
  852. rgb_matrix_config.mode = mode;
  853. }
  854. uint8_t rgb_matrix_get_mode(void) {
  855. return rgb_matrix_config.mode;
  856. }
  857. void rgb_matrix_sethsv(uint16_t hue, uint8_t sat, uint8_t val) {
  858. rgb_matrix_config.hue = hue;
  859. rgb_matrix_config.sat = sat;
  860. rgb_matrix_config.val = val;
  861. eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
  862. }
  863. void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) {
  864. rgb_matrix_config.hue = hue;
  865. rgb_matrix_config.sat = sat;
  866. rgb_matrix_config.val = val;
  867. }