rgb_matrix.c (28684B)
1 /* Copyright 2017 Jason Williams 2 * Copyright 2017 Jack Humbert 3 * Copyright 2018 Yiancar 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include "rgb_matrix.h" 20 #include "progmem.h" 21 #include "eeconfig.h" 22 #include "keyboard.h" 23 #include "sync_timer.h" 24 #include "debug.h" 25 #include <string.h> 26 #include <math.h> 27 #include <stdlib.h> 28 29 #include <lib/lib8tion/lib8tion.h> 30 31 #ifndef RGB_MATRIX_CENTER 32 const led_point_t k_rgb_matrix_center = {112, 32}; 33 #else 34 const led_point_t k_rgb_matrix_center = RGB_MATRIX_CENTER; 35 #endif 36 37 __attribute__((weak)) rgb_t rgb_matrix_hsv_to_rgb(hsv_t hsv) { 38 return hsv_to_rgb(hsv); 39 } 40 41 // Generic effect runners 42 #include "rgb_matrix_runners.inc" 43 44 // ------------------------------------------ 45 // -----Begin rgb effect includes macros----- 46 #define RGB_MATRIX_EFFECT(name) 47 #define RGB_MATRIX_CUSTOM_EFFECT_IMPLS 48 49 #include "rgb_matrix_effects.inc" 50 #ifdef COMMUNITY_MODULES_ENABLE 51 # include "rgb_matrix_community_modules.inc" 52 #endif 53 #ifdef RGB_MATRIX_CUSTOM_KB 54 # include "rgb_matrix_kb.inc" 55 #endif 56 #ifdef RGB_MATRIX_CUSTOM_USER 57 # include "rgb_matrix_user.inc" 58 #endif 59 60 #undef RGB_MATRIX_CUSTOM_EFFECT_IMPLS 61 #undef RGB_MATRIX_EFFECT 62 // -----End rgb effect includes macros------- 63 // ------------------------------------------ 64 65 // globals 66 rgb_config_t rgb_matrix_config; // TODO: would like to prefix this with g_ for global consistancy, do this in another pr 67 uint32_t g_rgb_timer; 68 #ifdef RGB_MATRIX_FRAMEBUFFER_EFFECTS 69 uint8_t g_rgb_frame_buffer[MATRIX_ROWS][MATRIX_COLS] = {{0}}; 70 #endif // RGB_MATRIX_FRAMEBUFFER_EFFECTS 71 #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED 72 last_hit_t g_last_hit_tracker; 73 #endif // RGB_MATRIX_KEYREACTIVE_ENABLED 74 75 #ifndef RGB_MATRIX_FLAG_STEPS 76 # define RGB_MATRIX_FLAG_STEPS {LED_FLAG_ALL, LED_FLAG_KEYLIGHT | LED_FLAG_MODIFIER, LED_FLAG_UNDERGLOW, LED_FLAG_NONE} 77 #endif 78 static const uint8_t rgb_matrix_flag_steps[] = RGB_MATRIX_FLAG_STEPS; 79 #define RGB_MATRIX_FLAG_STEPS_COUNT ARRAY_SIZE(rgb_matrix_flag_steps) 80 81 // internals 82 static bool suspend_state = false; 83 static uint8_t rgb_last_enable = UINT8_MAX; 84 static uint8_t rgb_last_effect = UINT8_MAX; 85 static uint8_t rgb_current_effect = 0; 86 static effect_params_t rgb_effect_params = {0, LED_FLAG_ALL, false}; 87 static rgb_task_states rgb_task_state = SYNCING; 88 89 // double buffers 90 static uint32_t rgb_timer_buffer; 91 #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED 92 static last_hit_t last_hit_buffer; 93 #endif // RGB_MATRIX_KEYREACTIVE_ENABLED 94 95 // split rgb matrix 96 #if defined(RGB_MATRIX_SPLIT) 97 const uint8_t k_rgb_matrix_split[2] = RGB_MATRIX_SPLIT; 98 #endif 99 100 EECONFIG_DEBOUNCE_HELPER(rgb_matrix, rgb_matrix_config); 101 102 void eeconfig_force_flush_rgb_matrix(void) { 103 eeconfig_flush_rgb_matrix(true); 104 } 105 106 void eeconfig_update_rgb_matrix_default(void) { 107 dprintf("eeconfig_update_rgb_matrix_default\n"); 108 rgb_matrix_config.enable = RGB_MATRIX_DEFAULT_ON; 109 rgb_matrix_config.mode = RGB_MATRIX_DEFAULT_MODE; 110 rgb_matrix_config.hsv = (hsv_t){RGB_MATRIX_DEFAULT_HUE, RGB_MATRIX_DEFAULT_SAT, RGB_MATRIX_DEFAULT_VAL}; 111 rgb_matrix_config.speed = RGB_MATRIX_DEFAULT_SPD; 112 rgb_matrix_config.flags = RGB_MATRIX_DEFAULT_FLAGS; 113 eeconfig_flush_rgb_matrix(true); 114 } 115 116 void eeconfig_debug_rgb_matrix(void) { 117 dprintf("rgb_matrix_config EEPROM\n"); 118 dprintf("rgb_matrix_config.enable = %d\n", rgb_matrix_config.enable); 119 #ifdef RGB_MATRIX_MODE_NAME_ENABLE 120 dprintf("rgb_matrix_config.mode = %d (%s)\n", rgb_matrix_config.mode, rgb_matrix_get_mode_name(rgb_matrix_config.mode)); 121 #else 122 dprintf("rgb_matrix_config.mode = %d\n", rgb_matrix_config.mode); 123 #endif // RGB_MATRIX_MODE_NAME_ENABLE 124 dprintf("rgb_matrix_config.hsv.h = %d\n", rgb_matrix_config.hsv.h); 125 dprintf("rgb_matrix_config.hsv.s = %d\n", rgb_matrix_config.hsv.s); 126 dprintf("rgb_matrix_config.hsv.v = %d\n", rgb_matrix_config.hsv.v); 127 dprintf("rgb_matrix_config.speed = %d\n", rgb_matrix_config.speed); 128 dprintf("rgb_matrix_config.flags = %d\n", rgb_matrix_config.flags); 129 } 130 131 void rgb_matrix_reload_from_eeprom(void) { 132 rgb_matrix_disable_noeeprom(); 133 /* Reset back to what we have in eeprom */ 134 eeconfig_init_rgb_matrix(); 135 eeconfig_debug_rgb_matrix(); // display current eeprom values 136 if (rgb_matrix_config.enable) { 137 rgb_matrix_mode_noeeprom(rgb_matrix_config.mode); 138 } 139 } 140 141 __attribute__((weak)) uint8_t rgb_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i) { 142 return 0; 143 } 144 145 uint8_t rgb_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i) { 146 uint8_t led_count = rgb_matrix_map_row_column_to_led_kb(row, column, led_i); 147 uint8_t led_index = g_led_config.matrix_co[row][column]; 148 if (led_index != NO_LED) { 149 led_i[led_count] = led_index; 150 led_count++; 151 } 152 return led_count; 153 } 154 155 void rgb_matrix_update_pwm_buffers(void) { 156 rgb_matrix_driver.flush(); 157 } 158 159 __attribute__((weak)) int rgb_matrix_led_index(int index) { 160 #if defined(RGB_MATRIX_SPLIT) 161 if (!is_keyboard_left() && index >= k_rgb_matrix_split[0]) { 162 return index - k_rgb_matrix_split[0]; 163 } 164 #endif 165 return index; 166 } 167 168 void rgb_matrix_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { 169 rgb_matrix_driver.set_color(rgb_matrix_led_index(index), red, green, blue); 170 } 171 172 void rgb_matrix_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { 173 #if defined(RGB_MATRIX_SPLIT) 174 for (uint8_t i = 0; i < RGB_MATRIX_LED_COUNT; i++) 175 rgb_matrix_set_color(i, red, green, blue); 176 #else 177 rgb_matrix_driver.set_color_all(red, green, blue); 178 #endif 179 } 180 181 void rgb_matrix_handle_key_event(uint8_t row, uint8_t col, bool pressed) { 182 #ifndef RGB_MATRIX_SPLIT 183 if (!is_keyboard_master()) return; 184 #endif 185 186 #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED 187 uint8_t led[LED_HITS_TO_REMEMBER]; 188 uint8_t led_count = 0; 189 190 # if defined(RGB_MATRIX_KEYRELEASES) 191 if (!pressed) 192 # elif defined(RGB_MATRIX_KEYPRESSES) 193 if (pressed) 194 # endif // defined(RGB_MATRIX_KEYRELEASES) 195 { 196 led_count = rgb_matrix_map_row_column_to_led(row, col, led); 197 } 198 199 if (last_hit_buffer.count + led_count > LED_HITS_TO_REMEMBER) { 200 memcpy(&last_hit_buffer.x[0], &last_hit_buffer.x[led_count], LED_HITS_TO_REMEMBER - led_count); 201 memcpy(&last_hit_buffer.y[0], &last_hit_buffer.y[led_count], LED_HITS_TO_REMEMBER - led_count); 202 memcpy(&last_hit_buffer.tick[0], &last_hit_buffer.tick[led_count], (LED_HITS_TO_REMEMBER - led_count) * 2); // 16 bit 203 memcpy(&last_hit_buffer.index[0], &last_hit_buffer.index[led_count], LED_HITS_TO_REMEMBER - led_count); 204 last_hit_buffer.count = LED_HITS_TO_REMEMBER - led_count; 205 } 206 207 for (uint8_t i = 0; i < led_count; i++) { 208 uint8_t index = last_hit_buffer.count; 209 last_hit_buffer.x[index] = g_led_config.point[led[i]].x; 210 last_hit_buffer.y[index] = g_led_config.point[led[i]].y; 211 last_hit_buffer.index[index] = led[i]; 212 last_hit_buffer.tick[index] = 0; 213 last_hit_buffer.count++; 214 } 215 #endif // RGB_MATRIX_KEYREACTIVE_ENABLED 216 217 #if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_RGB_MATRIX_TYPING_HEATMAP) 218 # if defined(RGB_MATRIX_KEYRELEASES) 219 if (!pressed) 220 # else 221 if (pressed) 222 # endif // defined(RGB_MATRIX_KEYRELEASES) 223 { 224 if (rgb_matrix_config.mode == RGB_MATRIX_TYPING_HEATMAP) { 225 process_rgb_matrix_typing_heatmap(row, col); 226 } 227 } 228 #endif // defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_RGB_MATRIX_TYPING_HEATMAP) 229 } 230 231 void rgb_matrix_test(void) { 232 // Mask out bits 4 and 5 233 // Increase the factor to make the test animation slower (and reduce to make it faster) 234 uint8_t factor = 10; 235 switch ((g_rgb_timer & (0b11 << factor)) >> factor) { 236 case 0: { 237 rgb_matrix_set_color_all(20, 0, 0); 238 break; 239 } 240 case 1: { 241 rgb_matrix_set_color_all(0, 20, 0); 242 break; 243 } 244 case 2: { 245 rgb_matrix_set_color_all(0, 0, 20); 246 break; 247 } 248 case 3: { 249 rgb_matrix_set_color_all(20, 20, 20); 250 break; 251 } 252 } 253 } 254 255 static bool rgb_matrix_none(effect_params_t *params) { 256 if (!params->init) { 257 return false; 258 } 259 260 rgb_matrix_set_color_all(0, 0, 0); 261 return false; 262 } 263 264 static void rgb_task_timers(void) { 265 #if defined(RGB_MATRIX_KEYREACTIVE_ENABLED) 266 uint32_t deltaTime = sync_timer_elapsed32(rgb_timer_buffer); 267 #endif // defined(RGB_MATRIX_KEYREACTIVE_ENABLED) 268 rgb_timer_buffer = sync_timer_read32(); 269 270 // Update double buffer last hit timers 271 #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED 272 uint8_t count = last_hit_buffer.count; 273 for (uint8_t i = 0; i < count; ++i) { 274 if (UINT16_MAX - deltaTime < last_hit_buffer.tick[i]) { 275 last_hit_buffer.count--; 276 continue; 277 } 278 last_hit_buffer.tick[i] += deltaTime; 279 } 280 #endif // RGB_MATRIX_KEYREACTIVE_ENABLED 281 } 282 283 static void rgb_task_sync(void) { 284 eeconfig_flush_rgb_matrix(false); 285 // next task 286 if (sync_timer_elapsed32(g_rgb_timer) >= RGB_MATRIX_LED_FLUSH_LIMIT) rgb_task_state = STARTING; 287 } 288 289 static void rgb_task_start(void) { 290 // reset iter 291 rgb_effect_params.iter = 0; 292 293 // update double buffers 294 g_rgb_timer = rgb_timer_buffer; 295 #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED 296 g_last_hit_tracker = last_hit_buffer; 297 #endif // RGB_MATRIX_KEYREACTIVE_ENABLED 298 299 // Ideally we would also stop sending zeros to the LED driver PWM buffers 300 // while suspended and just do a software shutdown. This is a cheap hack for now. 301 bool suspend_backlight = suspend_state || 302 #if RGB_MATRIX_TIMEOUT > 0 303 (last_input_activity_elapsed() > (uint32_t)RGB_MATRIX_TIMEOUT) || 304 #endif // RGB_MATRIX_TIMEOUT > 0 305 false; 306 307 // Set effect to be renedered 308 rgb_current_effect = suspend_backlight || !rgb_matrix_config.enable ? 0 : rgb_matrix_config.mode; 309 310 // next task 311 rgb_task_state = RENDERING; 312 } 313 314 static void rgb_task_render(uint8_t effect) { 315 bool rendering = false; 316 rgb_effect_params.init = (effect != rgb_last_effect) || (rgb_matrix_config.enable != rgb_last_enable); 317 if (rgb_effect_params.flags != rgb_matrix_config.flags) { 318 rgb_effect_params.flags = rgb_matrix_config.flags; 319 rgb_matrix_set_color_all(0, 0, 0); 320 } 321 322 // each effect can opt to do calculations 323 // and/or request PWM buffer updates. 324 switch (effect) { 325 case RGB_MATRIX_NONE: 326 rendering = rgb_matrix_none(&rgb_effect_params); 327 break; 328 329 // --------------------------------------------- 330 // -----Begin rgb effect switch case macros----- 331 #define RGB_MATRIX_EFFECT(name, ...) \ 332 case RGB_MATRIX_##name: \ 333 rendering = name(&rgb_effect_params); \ 334 break; 335 #include "rgb_matrix_effects.inc" 336 #undef RGB_MATRIX_EFFECT 337 338 #ifdef COMMUNITY_MODULES_ENABLE 339 # define RGB_MATRIX_EFFECT(name, ...) \ 340 case RGB_MATRIX_COMMUNITY_MODULE_##name: \ 341 rendering = name(&rgb_effect_params); \ 342 break; 343 # include "rgb_matrix_community_modules.inc" 344 # undef RGB_MATRIX_EFFECT 345 #endif 346 347 #if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER) 348 # define RGB_MATRIX_EFFECT(name, ...) \ 349 case RGB_MATRIX_CUSTOM_##name: \ 350 rendering = name(&rgb_effect_params); \ 351 break; 352 # ifdef RGB_MATRIX_CUSTOM_KB 353 # include "rgb_matrix_kb.inc" 354 # endif 355 # ifdef RGB_MATRIX_CUSTOM_USER 356 # include "rgb_matrix_user.inc" 357 # endif 358 # undef RGB_MATRIX_EFFECT 359 #endif 360 // -----End rgb effect switch case macros------- 361 // --------------------------------------------- 362 363 // Factory default magic value 364 case UINT8_MAX: { 365 rgb_matrix_test(); 366 rgb_task_state = FLUSHING; 367 } 368 return; 369 } 370 371 rgb_effect_params.iter++; 372 373 // next task 374 if (!rendering) { 375 rgb_task_state = FLUSHING; 376 if (!rgb_effect_params.init && effect == RGB_MATRIX_NONE) { 377 // We only need to flush once if we are RGB_MATRIX_NONE 378 rgb_task_state = SYNCING; 379 } 380 } 381 } 382 383 static void rgb_task_flush(uint8_t effect) { 384 // update last trackers after the first full render so we can init over several frames 385 rgb_last_effect = effect; 386 rgb_last_enable = rgb_matrix_config.enable; 387 388 // update pwm buffers 389 rgb_matrix_update_pwm_buffers(); 390 391 // next task 392 rgb_task_state = SYNCING; 393 } 394 395 void rgb_matrix_task(void) { 396 rgb_task_timers(); 397 398 uint8_t effect = rgb_current_effect; 399 400 switch (rgb_task_state) { 401 case STARTING: 402 rgb_task_start(); 403 break; 404 case RENDERING: 405 rgb_task_render(effect); 406 if (effect) { 407 if (rgb_task_state == FLUSHING) { // ensure we only draw basic indicators once rendering is finished 408 rgb_matrix_indicators(); 409 } 410 rgb_matrix_indicators_advanced(&rgb_effect_params); 411 } 412 break; 413 case FLUSHING: 414 rgb_task_flush(effect); 415 break; 416 case SYNCING: 417 rgb_task_sync(); 418 break; 419 } 420 } 421 422 __attribute__((weak)) bool rgb_matrix_indicators_modules(void) { 423 return true; 424 } 425 426 void rgb_matrix_indicators(void) { 427 rgb_matrix_indicators_modules(); 428 rgb_matrix_indicators_kb(); 429 } 430 431 __attribute__((weak)) bool rgb_matrix_indicators_kb(void) { 432 return rgb_matrix_indicators_user(); 433 } 434 435 __attribute__((weak)) bool rgb_matrix_indicators_user(void) { 436 return true; 437 } 438 439 struct rgb_matrix_limits_t rgb_matrix_get_limits(uint8_t iter) { 440 struct rgb_matrix_limits_t limits = {0}; 441 #if defined(RGB_MATRIX_LED_PROCESS_LIMIT) && RGB_MATRIX_LED_PROCESS_LIMIT > 0 && RGB_MATRIX_LED_PROCESS_LIMIT < RGB_MATRIX_LED_COUNT 442 # if defined(RGB_MATRIX_SPLIT) 443 limits.led_min_index = RGB_MATRIX_LED_PROCESS_LIMIT * (iter); 444 limits.led_max_index = limits.led_min_index + RGB_MATRIX_LED_PROCESS_LIMIT; 445 if (limits.led_max_index > RGB_MATRIX_LED_COUNT) limits.led_max_index = RGB_MATRIX_LED_COUNT; 446 if (is_keyboard_left() && (limits.led_max_index > k_rgb_matrix_split[0])) limits.led_max_index = k_rgb_matrix_split[0]; 447 if (!(is_keyboard_left()) && (limits.led_min_index < k_rgb_matrix_split[0])) limits.led_min_index = k_rgb_matrix_split[0]; 448 # else 449 limits.led_min_index = RGB_MATRIX_LED_PROCESS_LIMIT * (iter); 450 limits.led_max_index = limits.led_min_index + RGB_MATRIX_LED_PROCESS_LIMIT; 451 if (limits.led_max_index > RGB_MATRIX_LED_COUNT) limits.led_max_index = RGB_MATRIX_LED_COUNT; 452 # endif 453 #else 454 # if defined(RGB_MATRIX_SPLIT) 455 limits.led_min_index = 0; 456 limits.led_max_index = RGB_MATRIX_LED_COUNT; 457 if (is_keyboard_left() && (limits.led_max_index > k_rgb_matrix_split[0])) limits.led_max_index = k_rgb_matrix_split[0]; 458 if (!(is_keyboard_left()) && (limits.led_min_index < k_rgb_matrix_split[0])) limits.led_min_index = k_rgb_matrix_split[0]; 459 # else 460 limits.led_min_index = 0; 461 limits.led_max_index = RGB_MATRIX_LED_COUNT; 462 # endif 463 #endif 464 return limits; 465 } 466 467 __attribute__((weak)) bool rgb_matrix_indicators_advanced_modules(uint8_t led_min, uint8_t led_max) { 468 return true; 469 } 470 471 void rgb_matrix_indicators_advanced(effect_params_t *params) { 472 /* special handling is needed for "params->iter", since it's already been incremented. 473 * Could move the invocations to rgb_task_render, but then it's missing a few checks 474 * and not sure which would be better. Otherwise, this should be called from 475 * rgb_task_render, right before the iter++ line. 476 */ 477 RGB_MATRIX_USE_LIMITS_ITER(min, max, params->iter - 1); 478 rgb_matrix_indicators_advanced_modules(min, max); 479 rgb_matrix_indicators_advanced_kb(min, max); 480 } 481 482 __attribute__((weak)) bool rgb_matrix_indicators_advanced_kb(uint8_t led_min, uint8_t led_max) { 483 return rgb_matrix_indicators_advanced_user(led_min, led_max); 484 } 485 486 __attribute__((weak)) bool rgb_matrix_indicators_advanced_user(uint8_t led_min, uint8_t led_max) { 487 return true; 488 } 489 490 void rgb_matrix_init(void) { 491 rgb_matrix_driver.init(); 492 493 #ifdef RGB_MATRIX_KEYREACTIVE_ENABLED 494 g_last_hit_tracker.count = 0; 495 for (uint8_t i = 0; i < LED_HITS_TO_REMEMBER; ++i) { 496 g_last_hit_tracker.tick[i] = UINT16_MAX; 497 } 498 499 last_hit_buffer.count = 0; 500 for (uint8_t i = 0; i < LED_HITS_TO_REMEMBER; ++i) { 501 last_hit_buffer.tick[i] = UINT16_MAX; 502 } 503 #endif // RGB_MATRIX_KEYREACTIVE_ENABLED 504 505 eeconfig_init_rgb_matrix(); 506 if (!rgb_matrix_config.mode) { 507 dprintf("rgb_matrix_init_drivers rgb_matrix_config.mode = 0. Write default values to EEPROM.\n"); 508 eeconfig_update_rgb_matrix_default(); 509 } 510 eeconfig_debug_rgb_matrix(); // display current eeprom values 511 } 512 513 void rgb_matrix_set_suspend_state(bool state) { 514 #ifdef RGB_MATRIX_SLEEP 515 if (state && !suspend_state) { // only run if turning off, and only once 516 rgb_task_render(0); // turn off all LEDs when suspending 517 rgb_task_flush(0); // and actually flash led state to LEDs 518 } 519 suspend_state = state; 520 #endif 521 } 522 523 bool rgb_matrix_get_suspend_state(void) { 524 return suspend_state; 525 } 526 527 void rgb_matrix_toggle_eeprom_helper(bool write_to_eeprom) { 528 rgb_matrix_config.enable ^= 1; 529 rgb_task_state = STARTING; 530 eeconfig_flag_rgb_matrix(write_to_eeprom); 531 dprintf("rgb matrix toggle [%s]: rgb_matrix_config.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.enable); 532 } 533 void rgb_matrix_toggle_noeeprom(void) { 534 rgb_matrix_toggle_eeprom_helper(false); 535 } 536 void rgb_matrix_toggle(void) { 537 rgb_matrix_toggle_eeprom_helper(true); 538 } 539 540 void rgb_matrix_enable(void) { 541 rgb_matrix_enable_noeeprom(); 542 eeconfig_flag_rgb_matrix(true); 543 } 544 545 void rgb_matrix_enable_noeeprom(void) { 546 if (!rgb_matrix_config.enable) rgb_task_state = STARTING; 547 rgb_matrix_config.enable = 1; 548 } 549 550 void rgb_matrix_disable(void) { 551 rgb_matrix_disable_noeeprom(); 552 eeconfig_flag_rgb_matrix(true); 553 } 554 555 void rgb_matrix_disable_noeeprom(void) { 556 if (rgb_matrix_config.enable) rgb_task_state = STARTING; 557 rgb_matrix_config.enable = 0; 558 } 559 560 uint8_t rgb_matrix_is_enabled(void) { 561 return rgb_matrix_config.enable; 562 } 563 564 void rgb_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) { 565 if (!rgb_matrix_config.enable) { 566 return; 567 } 568 if (mode < 1) { 569 rgb_matrix_config.mode = 1; 570 } else if (mode >= RGB_MATRIX_EFFECT_MAX) { 571 rgb_matrix_config.mode = RGB_MATRIX_EFFECT_MAX - 1; 572 } else { 573 rgb_matrix_config.mode = mode; 574 } 575 rgb_task_state = STARTING; 576 eeconfig_flag_rgb_matrix(write_to_eeprom); 577 #ifdef RGB_MATRIX_MODE_NAME_ENABLE 578 dprintf("rgb matrix mode [%s]: %u (%s)\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", (unsigned)rgb_matrix_config.mode, rgb_matrix_get_mode_name(rgb_matrix_config.mode)); 579 #else 580 dprintf("rgb matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", (unsigned)rgb_matrix_config.mode); 581 #endif // RGB_MATRIX_MODE_NAME_ENABLE 582 } 583 void rgb_matrix_mode_noeeprom(uint8_t mode) { 584 rgb_matrix_mode_eeprom_helper(mode, false); 585 } 586 void rgb_matrix_mode(uint8_t mode) { 587 rgb_matrix_mode_eeprom_helper(mode, true); 588 } 589 590 uint8_t rgb_matrix_get_mode(void) { 591 return rgb_matrix_config.mode; 592 } 593 594 void rgb_matrix_step_helper(bool write_to_eeprom) { 595 uint8_t mode = rgb_matrix_config.mode + 1; 596 rgb_matrix_mode_eeprom_helper((mode < RGB_MATRIX_EFFECT_MAX) ? mode : 1, write_to_eeprom); 597 } 598 void rgb_matrix_step_noeeprom(void) { 599 rgb_matrix_step_helper(false); 600 } 601 void rgb_matrix_step(void) { 602 rgb_matrix_step_helper(true); 603 } 604 605 void rgb_matrix_step_reverse_helper(bool write_to_eeprom) { 606 uint8_t mode = rgb_matrix_config.mode - 1; 607 rgb_matrix_mode_eeprom_helper((mode < 1) ? RGB_MATRIX_EFFECT_MAX - 1 : mode, write_to_eeprom); 608 } 609 void rgb_matrix_step_reverse_noeeprom(void) { 610 rgb_matrix_step_reverse_helper(false); 611 } 612 void rgb_matrix_step_reverse(void) { 613 rgb_matrix_step_reverse_helper(true); 614 } 615 616 void rgb_matrix_sethsv_eeprom_helper(uint16_t hue, uint8_t sat, uint8_t val, bool write_to_eeprom) { 617 if (!rgb_matrix_config.enable) { 618 return; 619 } 620 rgb_matrix_config.hsv.h = hue; 621 rgb_matrix_config.hsv.s = sat; 622 rgb_matrix_config.hsv.v = (val > RGB_MATRIX_MAXIMUM_BRIGHTNESS) ? RGB_MATRIX_MAXIMUM_BRIGHTNESS : val; 623 eeconfig_flag_rgb_matrix(write_to_eeprom); 624 dprintf("rgb matrix set hsv [%s]: %u,%u,%u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.hsv.h, rgb_matrix_config.hsv.s, rgb_matrix_config.hsv.v); 625 } 626 void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) { 627 rgb_matrix_sethsv_eeprom_helper(hue, sat, val, false); 628 } 629 void rgb_matrix_sethsv(uint16_t hue, uint8_t sat, uint8_t val) { 630 rgb_matrix_sethsv_eeprom_helper(hue, sat, val, true); 631 } 632 633 hsv_t rgb_matrix_get_hsv(void) { 634 return rgb_matrix_config.hsv; 635 } 636 uint8_t rgb_matrix_get_hue(void) { 637 return rgb_matrix_config.hsv.h; 638 } 639 uint8_t rgb_matrix_get_sat(void) { 640 return rgb_matrix_config.hsv.s; 641 } 642 uint8_t rgb_matrix_get_val(void) { 643 return rgb_matrix_config.hsv.v; 644 } 645 646 void rgb_matrix_increase_hue_helper(bool write_to_eeprom) { 647 rgb_matrix_sethsv_eeprom_helper(rgb_matrix_config.hsv.h + RGB_MATRIX_HUE_STEP, rgb_matrix_config.hsv.s, rgb_matrix_config.hsv.v, write_to_eeprom); 648 } 649 void rgb_matrix_increase_hue_noeeprom(void) { 650 rgb_matrix_increase_hue_helper(false); 651 } 652 void rgb_matrix_increase_hue(void) { 653 rgb_matrix_increase_hue_helper(true); 654 } 655 656 void rgb_matrix_decrease_hue_helper(bool write_to_eeprom) { 657 rgb_matrix_sethsv_eeprom_helper(rgb_matrix_config.hsv.h - RGB_MATRIX_HUE_STEP, rgb_matrix_config.hsv.s, rgb_matrix_config.hsv.v, write_to_eeprom); 658 } 659 void rgb_matrix_decrease_hue_noeeprom(void) { 660 rgb_matrix_decrease_hue_helper(false); 661 } 662 void rgb_matrix_decrease_hue(void) { 663 rgb_matrix_decrease_hue_helper(true); 664 } 665 666 void rgb_matrix_increase_sat_helper(bool write_to_eeprom) { 667 rgb_matrix_sethsv_eeprom_helper(rgb_matrix_config.hsv.h, qadd8(rgb_matrix_config.hsv.s, RGB_MATRIX_SAT_STEP), rgb_matrix_config.hsv.v, write_to_eeprom); 668 } 669 void rgb_matrix_increase_sat_noeeprom(void) { 670 rgb_matrix_increase_sat_helper(false); 671 } 672 void rgb_matrix_increase_sat(void) { 673 rgb_matrix_increase_sat_helper(true); 674 } 675 676 void rgb_matrix_decrease_sat_helper(bool write_to_eeprom) { 677 rgb_matrix_sethsv_eeprom_helper(rgb_matrix_config.hsv.h, qsub8(rgb_matrix_config.hsv.s, RGB_MATRIX_SAT_STEP), rgb_matrix_config.hsv.v, write_to_eeprom); 678 } 679 void rgb_matrix_decrease_sat_noeeprom(void) { 680 rgb_matrix_decrease_sat_helper(false); 681 } 682 void rgb_matrix_decrease_sat(void) { 683 rgb_matrix_decrease_sat_helper(true); 684 } 685 686 void rgb_matrix_increase_val_helper(bool write_to_eeprom) { 687 rgb_matrix_sethsv_eeprom_helper(rgb_matrix_config.hsv.h, rgb_matrix_config.hsv.s, qadd8(rgb_matrix_config.hsv.v, RGB_MATRIX_VAL_STEP), write_to_eeprom); 688 } 689 void rgb_matrix_increase_val_noeeprom(void) { 690 rgb_matrix_increase_val_helper(false); 691 } 692 void rgb_matrix_increase_val(void) { 693 rgb_matrix_increase_val_helper(true); 694 } 695 696 void rgb_matrix_decrease_val_helper(bool write_to_eeprom) { 697 rgb_matrix_sethsv_eeprom_helper(rgb_matrix_config.hsv.h, rgb_matrix_config.hsv.s, qsub8(rgb_matrix_config.hsv.v, RGB_MATRIX_VAL_STEP), write_to_eeprom); 698 } 699 void rgb_matrix_decrease_val_noeeprom(void) { 700 rgb_matrix_decrease_val_helper(false); 701 } 702 void rgb_matrix_decrease_val(void) { 703 rgb_matrix_decrease_val_helper(true); 704 } 705 706 void rgb_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) { 707 rgb_matrix_config.speed = speed; 708 eeconfig_flag_rgb_matrix(write_to_eeprom); 709 dprintf("rgb matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.speed); 710 } 711 void rgb_matrix_set_speed_noeeprom(uint8_t speed) { 712 rgb_matrix_set_speed_eeprom_helper(speed, false); 713 } 714 void rgb_matrix_set_speed(uint8_t speed) { 715 rgb_matrix_set_speed_eeprom_helper(speed, true); 716 } 717 718 uint8_t rgb_matrix_get_speed(void) { 719 return rgb_matrix_config.speed; 720 } 721 722 void rgb_matrix_increase_speed_helper(bool write_to_eeprom) { 723 rgb_matrix_set_speed_eeprom_helper(qadd8(rgb_matrix_config.speed, RGB_MATRIX_SPD_STEP), write_to_eeprom); 724 } 725 void rgb_matrix_increase_speed_noeeprom(void) { 726 rgb_matrix_increase_speed_helper(false); 727 } 728 void rgb_matrix_increase_speed(void) { 729 rgb_matrix_increase_speed_helper(true); 730 } 731 732 void rgb_matrix_decrease_speed_helper(bool write_to_eeprom) { 733 rgb_matrix_set_speed_eeprom_helper(qsub8(rgb_matrix_config.speed, RGB_MATRIX_SPD_STEP), write_to_eeprom); 734 } 735 void rgb_matrix_decrease_speed_noeeprom(void) { 736 rgb_matrix_decrease_speed_helper(false); 737 } 738 void rgb_matrix_decrease_speed(void) { 739 rgb_matrix_decrease_speed_helper(true); 740 } 741 742 void rgb_matrix_set_flags_eeprom_helper(led_flags_t flags, bool write_to_eeprom) { 743 rgb_matrix_config.flags = flags; 744 eeconfig_flag_rgb_matrix(write_to_eeprom); 745 dprintf("rgb matrix set flags [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", rgb_matrix_config.flags); 746 } 747 748 led_flags_t rgb_matrix_get_flags(void) { 749 return rgb_matrix_config.flags; 750 } 751 752 void rgb_matrix_set_flags(led_flags_t flags) { 753 rgb_matrix_set_flags_eeprom_helper(flags, true); 754 } 755 756 void rgb_matrix_set_flags_noeeprom(led_flags_t flags) { 757 rgb_matrix_set_flags_eeprom_helper(flags, false); 758 } 759 760 void rgb_matrix_flags_step_helper(bool write_to_eeprom) { 761 led_flags_t flags = rgb_matrix_get_flags(); 762 763 uint8_t next = 0; 764 for (uint8_t i = 0; i < RGB_MATRIX_FLAG_STEPS_COUNT; i++) { 765 if (rgb_matrix_flag_steps[i] == flags) { 766 next = i == RGB_MATRIX_FLAG_STEPS_COUNT - 1 ? 0 : i + 1; 767 break; 768 } 769 } 770 771 rgb_matrix_set_flags_eeprom_helper(rgb_matrix_flag_steps[next], write_to_eeprom); 772 } 773 774 void rgb_matrix_flags_step_noeeprom(void) { 775 rgb_matrix_flags_step_helper(false); 776 } 777 778 void rgb_matrix_flags_step(void) { 779 rgb_matrix_flags_step_helper(true); 780 } 781 782 void rgb_matrix_flags_step_reverse_helper(bool write_to_eeprom) { 783 led_flags_t flags = rgb_matrix_get_flags(); 784 785 uint8_t next = 0; 786 for (uint8_t i = 0; i < RGB_MATRIX_FLAG_STEPS_COUNT; i++) { 787 if (rgb_matrix_flag_steps[i] == flags) { 788 next = i == 0 ? RGB_MATRIX_FLAG_STEPS_COUNT - 1 : i - 1; 789 break; 790 } 791 } 792 793 rgb_matrix_set_flags_eeprom_helper(rgb_matrix_flag_steps[next], write_to_eeprom); 794 } 795 796 void rgb_matrix_flags_step_reverse_noeeprom(void) { 797 rgb_matrix_flags_step_reverse_helper(false); 798 } 799 800 void rgb_matrix_flags_step_reverse(void) { 801 rgb_matrix_flags_step_reverse_helper(true); 802 } 803 804 //---------------------------------------------------------- 805 // RGB Matrix naming 806 #undef RGB_MATRIX_EFFECT 807 #ifdef RGB_MATRIX_MODE_NAME_ENABLE 808 const char *rgb_matrix_get_mode_name(uint8_t mode) { 809 switch (mode) { 810 case RGB_MATRIX_NONE: 811 return "NONE"; 812 813 # define RGB_MATRIX_EFFECT(name, ...) \ 814 case RGB_MATRIX_##name: \ 815 return #name; 816 # include "rgb_matrix_effects.inc" 817 # undef RGB_MATRIX_EFFECT 818 819 # ifdef COMMUNITY_MODULES_ENABLE 820 # define RGB_MATRIX_EFFECT(name, ...) \ 821 case RGB_MATRIX_COMMUNITY_MODULE_##name: \ 822 return #name; 823 # include "rgb_matrix_community_modules.inc" 824 # undef RGB_MATRIX_EFFECT 825 # endif // COMMUNITY_MODULES_ENABLE 826 827 # if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER) 828 # define RGB_MATRIX_EFFECT(name, ...) \ 829 case RGB_MATRIX_CUSTOM_##name: \ 830 return #name; 831 832 # ifdef RGB_MATRIX_CUSTOM_KB 833 # include "rgb_matrix_kb.inc" 834 # endif // RGB_MATRIX_CUSTOM_KB 835 836 # ifdef RGB_MATRIX_CUSTOM_USER 837 # include "rgb_matrix_user.inc" 838 # endif // RGB_MATRIX_CUSTOM_USER 839 840 # undef RGB_MATRIX_EFFECT 841 # endif // RGB_MATRIX_CUSTOM_KB || RGB_MATRIX_CUSTOM_USER 842 843 default: 844 return "UNKNOWN"; 845 } 846 } 847 # undef RGB_MATRIX_EFFECT 848 #endif // RGB_MATRIX_MODE_NAME_ENABLE