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