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