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