Commit | Line | Data |
---|---|---|
23839b8c | 1 | /* Copyright 2016-2017 Yang Liu |
2 | * | |
3 | * This program is free software: you can redistribute it and/or modify | |
4 | * it under the terms of the GNU General Public License as published by | |
5 | * the Free Software Foundation, either version 2 of the License, or | |
6 | * (at your option) any later version. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
12 | * | |
13 | * You should have received a copy of the GNU General Public License | |
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
ad49db8c | 16 | #include <math.h> |
6d6d91c8 | 17 | #include <string.h> |
ade22f8e JH |
18 | #ifdef __AVR__ |
19 | #include <avr/eeprom.h> | |
20 | #include <avr/interrupt.h> | |
21 | #endif | |
0f507f01 AK |
22 | #ifdef STM32_EEPROM_ENABLE |
23 | #include "hal.h" | |
24 | #include "eeprom.h" | |
25 | #include "eeprom_stm32.h" | |
26 | #endif | |
ade22f8e | 27 | #include "wait.h" |
0a40654b YL |
28 | #include "progmem.h" |
29 | #include "timer.h" | |
30 | #include "rgblight.h" | |
22ba36a4 | 31 | #include "color.h" |
0a40654b | 32 | #include "debug.h" |
f113f954 | 33 | #include "led_tables.h" |
22ba36a4 | 34 | #include "lib/lib8tion/lib8tion.h" |
c1c5922a CL |
35 | #ifdef VELOCIKEY_ENABLE |
36 | #include "velocikey.h" | |
37 | #endif | |
0a40654b | 38 | |
dfab177f TI |
39 | #ifdef RGBLIGHT_SPLIT |
40 | /* for split keyboard */ | |
41 | #define RGBLIGHT_SPLIT_SET_CHANGE_MODE rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_MODE | |
42 | #define RGBLIGHT_SPLIT_SET_CHANGE_HSVS rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_HSVS | |
5312131d | 43 | #define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS rgblight_status.change_flags |= (RGBLIGHT_STATUS_CHANGE_MODE|RGBLIGHT_STATUS_CHANGE_HSVS) |
dfab177f TI |
44 | #define RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE rgblight_status.change_flags |= RGBLIGHT_STATUS_CHANGE_TIMER |
45 | #define RGBLIGHT_SPLIT_ANIMATION_TICK rgblight_status.change_flags |= RGBLIGHT_STATUS_ANIMATION_TICK | |
46 | #else | |
47 | #define RGBLIGHT_SPLIT_SET_CHANGE_MODE | |
48 | #define RGBLIGHT_SPLIT_SET_CHANGE_HSVS | |
5312131d | 49 | #define RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS |
dfab177f TI |
50 | #define RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE |
51 | #define RGBLIGHT_SPLIT_ANIMATION_TICK | |
52 | #endif | |
53 | ||
6d6d91c8 TI |
54 | #define _RGBM_SINGLE_STATIC(sym) RGBLIGHT_MODE_ ## sym, |
55 | #define _RGBM_SINGLE_DYNAMIC(sym) | |
56 | #define _RGBM_MULTI_STATIC(sym) RGBLIGHT_MODE_ ## sym, | |
57 | #define _RGBM_MULTI_DYNAMIC(sym) | |
dfab177f TI |
58 | #define _RGBM_TMP_STATIC(sym, msym) RGBLIGHT_MODE_ ## sym, |
59 | #define _RGBM_TMP_DYNAMIC(sym, msym) | |
6d6d91c8 | 60 | static uint8_t static_effect_table [] = { |
dfab177f TI |
61 | #include "rgblight_modes.h" |
62 | }; | |
63 | ||
64 | #define _RGBM_SINGLE_STATIC(sym) RGBLIGHT_MODE_ ## sym, | |
65 | #define _RGBM_SINGLE_DYNAMIC(sym) RGBLIGHT_MODE_ ## sym, | |
66 | #define _RGBM_MULTI_STATIC(sym) RGBLIGHT_MODE_ ## sym, | |
67 | #define _RGBM_MULTI_DYNAMIC(sym) RGBLIGHT_MODE_ ## sym, | |
68 | #define _RGBM_TMP_STATIC(sym, msym) RGBLIGHT_MODE_ ## msym, | |
69 | #define _RGBM_TMP_DYNAMIC(sym, msym) RGBLIGHT_MODE_ ## msym, | |
70 | static uint8_t mode_base_table [] = { | |
71 | 0, // RGBLIGHT_MODE_zero | |
72 | #include "rgblight_modes.h" | |
6d6d91c8 TI |
73 | }; |
74 | ||
75 | static inline int is_static_effect(uint8_t mode) { | |
76 | return memchr(static_effect_table, mode, sizeof(static_effect_table)) != NULL; | |
77 | } | |
78 | ||
f7fd7f67 TI |
79 | #ifdef RGBLIGHT_LED_MAP |
80 | const uint8_t led_map[] PROGMEM = RGBLIGHT_LED_MAP; | |
81 | #endif | |
82 | ||
6d6d91c8 | 83 | #ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT |
a7882b1f | 84 | __attribute__ ((weak)) |
22ba36a4 | 85 | const uint8_t RGBLED_GRADIENT_RANGES[] PROGMEM = {255, 170, 127, 85, 64}; |
6d6d91c8 | 86 | #endif |
0a40654b YL |
87 | |
88 | rgblight_config_t rgblight_config; | |
dfab177f | 89 | rgblight_status_t rgblight_status = { .timer_enabled = false }; |
cc146e32 | 90 | bool is_rgblight_initialized = false; |
0a40654b | 91 | |
dfab177f TI |
92 | #ifdef RGBLIGHT_USE_TIMER |
93 | animation_status_t animation_status = {}; | |
94 | #endif | |
95 | ||
5fcd744d | 96 | #ifndef LED_ARRAY |
e9f74875 | 97 | LED_TYPE led[RGBLED_NUM]; |
5fcd744d X |
98 | #define LED_ARRAY led |
99 | #endif | |
100 | ||
0a40654b | 101 | |
f077204f D |
102 | static uint8_t clipping_start_pos = 0; |
103 | static uint8_t clipping_num_leds = RGBLED_NUM; | |
670a9b7f TI |
104 | static uint8_t effect_start_pos = 0; |
105 | static uint8_t effect_end_pos = RGBLED_NUM; | |
106 | static uint8_t effect_num_leds = RGBLED_NUM; | |
f077204f D |
107 | |
108 | void rgblight_set_clipping_range(uint8_t start_pos, uint8_t num_leds) { | |
109 | clipping_start_pos = start_pos; | |
110 | clipping_num_leds = num_leds; | |
111 | } | |
112 | ||
670a9b7f TI |
113 | void rgblight_set_effect_range(uint8_t start_pos, uint8_t num_leds) { |
114 | if (start_pos >= RGBLED_NUM) return; | |
115 | if (start_pos + num_leds > RGBLED_NUM) return; | |
116 | effect_start_pos = start_pos; | |
117 | effect_end_pos = start_pos + num_leds; | |
118 | effect_num_leds = num_leds; | |
119 | } | |
f077204f | 120 | |
670a9b7f TI |
121 | void sethsv_raw(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) { |
122 | HSV hsv = { hue, sat, val }; | |
22ba36a4 X |
123 | RGB rgb = hsv_to_rgb(hsv); |
124 | setrgb(rgb.r, rgb.g, rgb.b, led1); | |
0a40654b YL |
125 | } |
126 | ||
670a9b7f TI |
127 | void sethsv(uint8_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) { |
128 | sethsv_raw( hue, sat, | |
129 | val > RGBLIGHT_LIMIT_VAL ? RGBLIGHT_LIMIT_VAL : val, | |
130 | led1); | |
131 | } | |
132 | ||
e9f74875 | 133 | void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1) { |
0a40654b YL |
134 | (*led1).r = r; |
135 | (*led1).g = g; | |
136 | (*led1).b = b; | |
137 | } | |
138 | ||
cc146e32 DJ |
139 | void rgblight_check_config(void) { |
140 | /* Add some out of bound checks for RGB light config */ | |
141 | ||
142 | if (rgblight_config.mode < RGBLIGHT_MODE_STATIC_LIGHT) { | |
143 | rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT; | |
144 | } | |
145 | else if (rgblight_config.mode > RGBLIGHT_MODES) { | |
146 | rgblight_config.mode = RGBLIGHT_MODES; | |
147 | } | |
148 | ||
22ba36a4 | 149 | if (rgblight_config.val > RGBLIGHT_LIMIT_VAL) { |
cc146e32 DJ |
150 | rgblight_config.val = RGBLIGHT_LIMIT_VAL; |
151 | } | |
cc146e32 | 152 | } |
0a40654b YL |
153 | |
154 | uint32_t eeconfig_read_rgblight(void) { | |
0f507f01 | 155 | #if defined(__AVR__) || defined(STM32_EEPROM_ENABLE) || defined(PROTOCOL_ARM_ATSAM) || defined(EEPROM_SIZE) |
ade22f8e JH |
156 | return eeprom_read_dword(EECONFIG_RGBLIGHT); |
157 | #else | |
158 | return 0; | |
159 | #endif | |
0a40654b | 160 | } |
cc146e32 | 161 | |
620ac4b2 | 162 | void eeconfig_update_rgblight(uint32_t val) { |
0f507f01 | 163 | #if defined(__AVR__) || defined(STM32_EEPROM_ENABLE) || defined(PROTOCOL_ARM_ATSAM) || defined(EEPROM_SIZE) |
cc146e32 | 164 | rgblight_check_config(); |
ade22f8e JH |
165 | eeprom_update_dword(EECONFIG_RGBLIGHT, val); |
166 | #endif | |
0a40654b | 167 | } |
cc146e32 | 168 | |
620ac4b2 | 169 | void eeconfig_update_rgblight_default(void) { |
0fab3bbd | 170 | //dprintf("eeconfig_update_rgblight_default\n"); |
3a860c4b | 171 | rgblight_config.enable = 1; |
6d6d91c8 | 172 | rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT; |
e9f74875 | 173 | rgblight_config.hue = 0; |
22ba36a4 | 174 | rgblight_config.sat = UINT8_MAX; |
2038a515 | 175 | rgblight_config.val = RGBLIGHT_LIMIT_VAL; |
afacd423 | 176 | rgblight_config.speed = 0; |
5312131d | 177 | RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS; |
3a860c4b | 178 | eeconfig_update_rgblight(rgblight_config.raw); |
0a40654b | 179 | } |
cc146e32 | 180 | |
0a40654b | 181 | void eeconfig_debug_rgblight(void) { |
3a860c4b JO |
182 | dprintf("rgblight_config eprom\n"); |
183 | dprintf("rgblight_config.enable = %d\n", rgblight_config.enable); | |
184 | dprintf("rghlight_config.mode = %d\n", rgblight_config.mode); | |
185 | dprintf("rgblight_config.hue = %d\n", rgblight_config.hue); | |
186 | dprintf("rgblight_config.sat = %d\n", rgblight_config.sat); | |
187 | dprintf("rgblight_config.val = %d\n", rgblight_config.val); | |
afacd423 | 188 | dprintf("rgblight_config.speed = %d\n", rgblight_config.speed); |
0a40654b YL |
189 | } |
190 | ||
191 | void rgblight_init(void) { | |
cc146e32 DJ |
192 | /* if already initialized, don't do it again. |
193 | If you must do it again, extern this and set to false, first. | |
194 | This is a dirty, dirty hack until proper hooks can be added for keyboard startup. */ | |
195 | if (is_rgblight_initialized) { return; } | |
196 | ||
0a40654b | 197 | debug_enable = 1; // Debug ON! |
3a860c4b | 198 | dprintf("rgblight_init called.\n"); |
3a860c4b | 199 | dprintf("rgblight_init start!\n"); |
0a40654b | 200 | if (!eeconfig_is_enabled()) { |
3a860c4b | 201 | dprintf("rgblight_init eeconfig is not enabled.\n"); |
0a40654b | 202 | eeconfig_init(); |
3a860c4b | 203 | eeconfig_update_rgblight_default(); |
0a40654b YL |
204 | } |
205 | rgblight_config.raw = eeconfig_read_rgblight(); | |
5312131d | 206 | RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS; |
3a860c4b JO |
207 | if (!rgblight_config.mode) { |
208 | dprintf("rgblight_init rgblight_config.mode = 0. Write default values to EEPROM.\n"); | |
209 | eeconfig_update_rgblight_default(); | |
210 | rgblight_config.raw = eeconfig_read_rgblight(); | |
211 | } | |
cc146e32 DJ |
212 | rgblight_check_config(); |
213 | ||
3a860c4b | 214 | eeconfig_debug_rgblight(); // display current eeprom values |
0a40654b | 215 | |
6d6d91c8 | 216 | #ifdef RGBLIGHT_USE_TIMER |
3a860c4b | 217 | rgblight_timer_init(); // setup the timer |
6d6d91c8 | 218 | #endif |
0a40654b YL |
219 | |
220 | if (rgblight_config.enable) { | |
751719e6 | 221 | rgblight_mode_noeeprom(rgblight_config.mode); |
0a40654b | 222 | } |
cc146e32 DJ |
223 | |
224 | is_rgblight_initialized = true; | |
225 | ||
0a40654b YL |
226 | } |
227 | ||
9c4424ae LT |
228 | uint32_t rgblight_read_dword(void) { |
229 | return rgblight_config.raw; | |
230 | } | |
231 | ||
2e23689b | 232 | void rgblight_update_dword(uint32_t dword) { |
9f8c8c53 | 233 | RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS; |
2e23689b | 234 | rgblight_config.raw = dword; |
2e23689b | 235 | if (rgblight_config.enable) |
9c4424ae | 236 | rgblight_mode_noeeprom(rgblight_config.mode); |
2e23689b | 237 | else { |
6d6d91c8 | 238 | #ifdef RGBLIGHT_USE_TIMER |
2e23689b | 239 | rgblight_timer_disable(); |
6d6d91c8 | 240 | #endif |
2e23689b JH |
241 | rgblight_set(); |
242 | } | |
243 | } | |
244 | ||
0a40654b | 245 | void rgblight_increase(void) { |
3a860c4b | 246 | uint8_t mode = 0; |
0a40654b YL |
247 | if (rgblight_config.mode < RGBLIGHT_MODES) { |
248 | mode = rgblight_config.mode + 1; | |
249 | } | |
3a860c4b | 250 | rgblight_mode(mode); |
0a40654b | 251 | } |
0a40654b | 252 | void rgblight_decrease(void) { |
3a860c4b JO |
253 | uint8_t mode = 0; |
254 | // Mode will never be < 1. If it ever is, eeprom needs to be initialized. | |
6d6d91c8 | 255 | if (rgblight_config.mode > RGBLIGHT_MODE_STATIC_LIGHT) { |
3a860c4b | 256 | mode = rgblight_config.mode - 1; |
0a40654b | 257 | } |
3a860c4b | 258 | rgblight_mode(mode); |
0a40654b | 259 | } |
9e6ee477 | 260 | void rgblight_step_helper(bool write_to_eeprom) { |
3a860c4b | 261 | uint8_t mode = 0; |
0a40654b YL |
262 | mode = rgblight_config.mode + 1; |
263 | if (mode > RGBLIGHT_MODES) { | |
264 | mode = 1; | |
265 | } | |
9e6ee477 | 266 | rgblight_mode_eeprom_helper(mode, write_to_eeprom); |
0a40654b | 267 | } |
9e6ee477 FS |
268 | void rgblight_step_noeeprom(void) { |
269 | rgblight_step_helper(false); | |
270 | } | |
271 | void rgblight_step(void) { | |
272 | rgblight_step_helper(true); | |
273 | } | |
274 | void rgblight_step_reverse_helper(bool write_to_eeprom) { | |
5a1b68d5 | 275 | uint8_t mode = 0; |
276 | mode = rgblight_config.mode - 1; | |
277 | if (mode < 1) { | |
278 | mode = RGBLIGHT_MODES; | |
279 | } | |
9e6ee477 FS |
280 | rgblight_mode_eeprom_helper(mode, write_to_eeprom); |
281 | } | |
282 | void rgblight_step_reverse_noeeprom(void) { | |
283 | rgblight_step_reverse_helper(false); | |
284 | } | |
285 | void rgblight_step_reverse(void) { | |
286 | rgblight_step_reverse_helper(true); | |
5a1b68d5 | 287 | } |
0a40654b | 288 | |
b7688590 | 289 | uint8_t rgblight_get_mode(void) { |
4580d3a7 | 290 | if (!rgblight_config.enable) { |
291 | return false; | |
292 | } | |
293 | ||
294 | return rgblight_config.mode; | |
295 | } | |
296 | ||
751719e6 | 297 | void rgblight_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) { |
3a860c4b JO |
298 | if (!rgblight_config.enable) { |
299 | return; | |
300 | } | |
6d6d91c8 TI |
301 | if (mode < RGBLIGHT_MODE_STATIC_LIGHT) { |
302 | rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT; | |
3a860c4b JO |
303 | } else if (mode > RGBLIGHT_MODES) { |
304 | rgblight_config.mode = RGBLIGHT_MODES; | |
305 | } else { | |
306 | rgblight_config.mode = mode; | |
307 | } | |
dfab177f | 308 | RGBLIGHT_SPLIT_SET_CHANGE_MODE; |
751719e6 DJ |
309 | if (write_to_eeprom) { |
310 | eeconfig_update_rgblight(rgblight_config.raw); | |
311 | xprintf("rgblight mode [EEPROM]: %u\n", rgblight_config.mode); | |
312 | } else { | |
313 | xprintf("rgblight mode [NOEEPROM]: %u\n", rgblight_config.mode); | |
314 | } | |
6d6d91c8 TI |
315 | if( is_static_effect(rgblight_config.mode) ) { |
316 | #ifdef RGBLIGHT_USE_TIMER | |
3a860c4b | 317 | rgblight_timer_disable(); |
6d6d91c8 TI |
318 | #endif |
319 | } else { | |
320 | #ifdef RGBLIGHT_USE_TIMER | |
3a860c4b | 321 | rgblight_timer_enable(); |
6d6d91c8 | 322 | #endif |
3a860c4b | 323 | } |
dfab177f TI |
324 | #ifdef RGBLIGHT_USE_TIMER |
325 | animation_status.restart = true; | |
326 | #endif | |
751719e6 DJ |
327 | rgblight_sethsv_noeeprom(rgblight_config.hue, rgblight_config.sat, rgblight_config.val); |
328 | } | |
329 | ||
330 | void rgblight_mode(uint8_t mode) { | |
331 | rgblight_mode_eeprom_helper(mode, true); | |
332 | } | |
333 | ||
334 | void rgblight_mode_noeeprom(uint8_t mode) { | |
335 | rgblight_mode_eeprom_helper(mode, false); | |
0a40654b YL |
336 | } |
337 | ||
751719e6 | 338 | |
0a40654b | 339 | void rgblight_toggle(void) { |
751719e6 | 340 | xprintf("rgblight toggle [EEPROM]: rgblight_config.enable = %u\n", !rgblight_config.enable); |
3a860c4b | 341 | if (rgblight_config.enable) { |
16546ee0 CG |
342 | rgblight_disable(); |
343 | } | |
344 | else { | |
345 | rgblight_enable(); | |
3a860c4b | 346 | } |
0a40654b YL |
347 | } |
348 | ||
751719e6 DJ |
349 | void rgblight_toggle_noeeprom(void) { |
350 | xprintf("rgblight toggle [NOEEPROM]: rgblight_config.enable = %u\n", !rgblight_config.enable); | |
351 | if (rgblight_config.enable) { | |
352 | rgblight_disable_noeeprom(); | |
353 | } | |
354 | else { | |
355 | rgblight_enable_noeeprom(); | |
356 | } | |
357 | } | |
358 | ||
285c5a91 EZ |
359 | void rgblight_enable(void) { |
360 | rgblight_config.enable = 1; | |
751719e6 DJ |
361 | // No need to update EEPROM here. rgblight_mode() will do that, actually |
362 | //eeconfig_update_rgblight(rgblight_config.raw); | |
363 | xprintf("rgblight enable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable); | |
285c5a91 EZ |
364 | rgblight_mode(rgblight_config.mode); |
365 | } | |
366 | ||
751719e6 DJ |
367 | void rgblight_enable_noeeprom(void) { |
368 | rgblight_config.enable = 1; | |
369 | xprintf("rgblight enable [NOEEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable); | |
370 | rgblight_mode_noeeprom(rgblight_config.mode); | |
371 | } | |
372 | ||
16546ee0 CG |
373 | void rgblight_disable(void) { |
374 | rgblight_config.enable = 0; | |
375 | eeconfig_update_rgblight(rgblight_config.raw); | |
751719e6 | 376 | xprintf("rgblight disable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable); |
6d6d91c8 TI |
377 | #ifdef RGBLIGHT_USE_TIMER |
378 | rgblight_timer_disable(); | |
379 | #endif | |
dfab177f | 380 | RGBLIGHT_SPLIT_SET_CHANGE_MODE; |
ade22f8e | 381 | wait_ms(50); |
16546ee0 CG |
382 | rgblight_set(); |
383 | } | |
384 | ||
751719e6 DJ |
385 | void rgblight_disable_noeeprom(void) { |
386 | rgblight_config.enable = 0; | |
387 | xprintf("rgblight disable [noEEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable); | |
6d6d91c8 | 388 | #ifdef RGBLIGHT_USE_TIMER |
751719e6 | 389 | rgblight_timer_disable(); |
6d6d91c8 | 390 | #endif |
dfab177f | 391 | RGBLIGHT_SPLIT_SET_CHANGE_MODE; |
0f507f01 | 392 | wait_ms(50); |
751719e6 DJ |
393 | rgblight_set(); |
394 | } | |
395 | ||
9e6ee477 | 396 | void rgblight_increase_hue_helper(bool write_to_eeprom) { |
22ba36a4 | 397 | uint8_t hue = rgblight_config.hue + RGBLIGHT_HUE_STEP; |
9e6ee477 | 398 | rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom); |
0a40654b | 399 | } |
9e6ee477 FS |
400 | void rgblight_increase_hue_noeeprom(void) { |
401 | rgblight_increase_hue_helper(false); | |
402 | } | |
403 | void rgblight_increase_hue(void) { | |
404 | rgblight_increase_hue_helper(true); | |
405 | } | |
406 | void rgblight_decrease_hue_helper(bool write_to_eeprom) { | |
22ba36a4 | 407 | uint8_t hue = rgblight_config.hue - RGBLIGHT_HUE_STEP; |
9e6ee477 | 408 | rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom); |
0a40654b | 409 | } |
9e6ee477 FS |
410 | void rgblight_decrease_hue_noeeprom(void) { |
411 | rgblight_decrease_hue_helper(false); | |
412 | } | |
413 | void rgblight_decrease_hue(void) { | |
414 | rgblight_decrease_hue_helper(true); | |
415 | } | |
416 | void rgblight_increase_sat_helper(bool write_to_eeprom) { | |
22ba36a4 | 417 | uint8_t sat = qadd8(rgblight_config.sat, RGBLIGHT_SAT_STEP); |
9e6ee477 | 418 | rgblight_sethsv_eeprom_helper(rgblight_config.hue, sat, rgblight_config.val, write_to_eeprom); |
0a40654b | 419 | } |
9e6ee477 FS |
420 | void rgblight_increase_sat_noeeprom(void) { |
421 | rgblight_increase_sat_helper(false); | |
422 | } | |
423 | void rgblight_increase_sat(void) { | |
424 | rgblight_increase_sat_helper(true); | |
425 | } | |
426 | void rgblight_decrease_sat_helper(bool write_to_eeprom) { | |
22ba36a4 | 427 | uint8_t sat = qsub8(rgblight_config.sat, RGBLIGHT_SAT_STEP); |
9e6ee477 | 428 | rgblight_sethsv_eeprom_helper(rgblight_config.hue, sat, rgblight_config.val, write_to_eeprom); |
0a40654b | 429 | } |
9e6ee477 FS |
430 | void rgblight_decrease_sat_noeeprom(void) { |
431 | rgblight_decrease_sat_helper(false); | |
432 | } | |
433 | void rgblight_decrease_sat(void) { | |
434 | rgblight_decrease_sat_helper(true); | |
435 | } | |
436 | void rgblight_increase_val_helper(bool write_to_eeprom) { | |
22ba36a4 | 437 | uint8_t val = qadd8(rgblight_config.val, RGBLIGHT_VAL_STEP); |
9e6ee477 | 438 | rgblight_sethsv_eeprom_helper(rgblight_config.hue, rgblight_config.sat, val, write_to_eeprom); |
0a40654b | 439 | } |
9e6ee477 FS |
440 | void rgblight_increase_val_noeeprom(void) { |
441 | rgblight_increase_val_helper(false); | |
442 | } | |
443 | void rgblight_increase_val(void) { | |
444 | rgblight_increase_val_helper(true); | |
445 | } | |
446 | void rgblight_decrease_val_helper(bool write_to_eeprom) { | |
22ba36a4 | 447 | uint8_t val = qsub8(rgblight_config.val, RGBLIGHT_VAL_STEP); |
9e6ee477 FS |
448 | rgblight_sethsv_eeprom_helper(rgblight_config.hue, rgblight_config.sat, val, write_to_eeprom); |
449 | } | |
450 | void rgblight_decrease_val_noeeprom(void) { | |
451 | rgblight_decrease_val_helper(false); | |
452 | } | |
453 | void rgblight_decrease_val(void) { | |
454 | rgblight_decrease_val_helper(true); | |
0a40654b | 455 | } |
afacd423 | 456 | void rgblight_increase_speed(void) { |
22ba36a4 X |
457 | if (rgblight_config.speed < 3) |
458 | rgblight_config.speed++; | |
dfab177f | 459 | //RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED? |
afacd423 | 460 | eeconfig_update_rgblight(rgblight_config.raw);//EECONFIG needs to be increased to support this |
461 | } | |
462 | ||
463 | void rgblight_decrease_speed(void) { | |
22ba36a4 X |
464 | if (rgblight_config.speed > 0) |
465 | rgblight_config.speed--; | |
dfab177f | 466 | //RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED?? |
afacd423 | 467 | eeconfig_update_rgblight(rgblight_config.raw);//EECONFIG needs to be increased to support this |
468 | } | |
0a40654b | 469 | |
22ba36a4 | 470 | void rgblight_sethsv_noeeprom_old(uint8_t hue, uint8_t sat, uint8_t val) { |
0a40654b | 471 | if (rgblight_config.enable) { |
e9f74875 | 472 | LED_TYPE tmp_led; |
0a40654b | 473 | sethsv(hue, sat, val, &tmp_led); |
0a40654b YL |
474 | // dprintf("rgblight set hue [MEMORY]: %u,%u,%u\n", inmem_config.hue, inmem_config.sat, inmem_config.val); |
475 | rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b); | |
476 | } | |
477 | } | |
751719e6 | 478 | |
22ba36a4 | 479 | void rgblight_sethsv_eeprom_helper(uint8_t hue, uint8_t sat, uint8_t val, bool write_to_eeprom) { |
0a40654b | 480 | if (rgblight_config.enable) { |
dfab177f | 481 | rgblight_status.base_mode = mode_base_table[rgblight_config.mode]; |
6d6d91c8 | 482 | if (rgblight_config.mode == RGBLIGHT_MODE_STATIC_LIGHT) { |
3a860c4b | 483 | // same static color |
751719e6 DJ |
484 | LED_TYPE tmp_led; |
485 | sethsv(hue, sat, val, &tmp_led); | |
486 | rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b); | |
3a860c4b JO |
487 | } else { |
488 | // all LEDs in same color | |
6d6d91c8 TI |
489 | if ( 1 == 0 ) { //dummy |
490 | } | |
491 | #ifdef RGBLIGHT_EFFECT_BREATHING | |
dfab177f | 492 | else if (rgblight_status.base_mode == RGBLIGHT_MODE_BREATHING ) { |
3a860c4b JO |
493 | // breathing mode, ignore the change of val, use in memory value instead |
494 | val = rgblight_config.val; | |
6d6d91c8 TI |
495 | } |
496 | #endif | |
497 | #ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD | |
dfab177f | 498 | else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_MOOD) { |
6d6d91c8 TI |
499 | // rainbow mood, ignore the change of hue |
500 | hue = rgblight_config.hue; | |
501 | } | |
502 | #endif | |
503 | #ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL | |
dfab177f | 504 | else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_SWIRL) { |
6d6d91c8 | 505 | // rainbow swirl, ignore the change of hue |
3a860c4b | 506 | hue = rgblight_config.hue; |
6d6d91c8 TI |
507 | } |
508 | #endif | |
509 | #ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT | |
dfab177f | 510 | else if (rgblight_status.base_mode == RGBLIGHT_MODE_STATIC_GRADIENT) { |
a7882b1f | 511 | // static gradient |
dfab177f | 512 | uint8_t delta = rgblight_config.mode - rgblight_status.base_mode; |
22ba36a4 X |
513 | bool direction = (delta % 2) == 0; |
514 | #ifdef __AVR__ | |
515 | // probably due to how pgm_read_word is defined for ARM, but the ARM compiler really hates this line | |
516 | uint8_t range = pgm_read_word(&RGBLED_GRADIENT_RANGES[delta / 2]); | |
517 | #else | |
518 | uint8_t range = RGBLED_GRADIENT_RANGES[delta / 2]; | |
519 | #endif | |
670a9b7f TI |
520 | for (uint8_t i = 0; i < effect_num_leds; i++) { |
521 | uint8_t _hue = ((uint16_t)i * (uint16_t)range) / effect_num_leds; | |
22ba36a4 X |
522 | if (direction) { |
523 | _hue = hue + _hue; | |
524 | } else { | |
525 | _hue = hue - _hue; | |
526 | } | |
527 | dprintf("rgblight rainbow set hsv: %d,%d,%d,%u\n", i, _hue, direction, range); | |
670a9b7f | 528 | sethsv(_hue, sat, val, (LED_TYPE *)&led[i + effect_start_pos]); |
a7882b1f | 529 | } |
530 | rgblight_set(); | |
3a860c4b | 531 | } |
6d6d91c8 | 532 | #endif |
3a860c4b | 533 | } |
dfab177f TI |
534 | #ifdef RGBLIGHT_SPLIT |
535 | if( rgblight_config.hue != hue || | |
536 | rgblight_config.sat != sat || | |
537 | rgblight_config.val != val ) { | |
538 | RGBLIGHT_SPLIT_SET_CHANGE_HSVS; | |
539 | } | |
540 | #endif | |
3a860c4b JO |
541 | rgblight_config.hue = hue; |
542 | rgblight_config.sat = sat; | |
543 | rgblight_config.val = val; | |
751719e6 DJ |
544 | if (write_to_eeprom) { |
545 | eeconfig_update_rgblight(rgblight_config.raw); | |
546 | xprintf("rgblight set hsv [EEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val); | |
547 | } else { | |
548 | xprintf("rgblight set hsv [NOEEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val); | |
549 | } | |
3a860c4b JO |
550 | } |
551 | } | |
552 | ||
22ba36a4 | 553 | void rgblight_sethsv(uint8_t hue, uint8_t sat, uint8_t val) { |
751719e6 DJ |
554 | rgblight_sethsv_eeprom_helper(hue, sat, val, true); |
555 | } | |
556 | ||
22ba36a4 | 557 | void rgblight_sethsv_noeeprom(uint8_t hue, uint8_t sat, uint8_t val) { |
751719e6 DJ |
558 | rgblight_sethsv_eeprom_helper(hue, sat, val, false); |
559 | } | |
560 | ||
22ba36a4 | 561 | uint8_t rgblight_get_hue(void) { |
12e66330 | 562 | return rgblight_config.hue; |
563 | } | |
564 | ||
565 | uint8_t rgblight_get_sat(void) { | |
566 | return rgblight_config.sat; | |
567 | } | |
568 | ||
569 | uint8_t rgblight_get_val(void) { | |
570 | return rgblight_config.val; | |
571 | } | |
572 | ||
3a860c4b | 573 | void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) { |
16546ee0 CG |
574 | if (!rgblight_config.enable) { return; } |
575 | ||
670a9b7f | 576 | for (uint8_t i = effect_start_pos; i < effect_end_pos; i++) { |
0a40654b YL |
577 | led[i].r = r; |
578 | led[i].g = g; | |
579 | led[i].b = b; | |
580 | } | |
581 | rgblight_set(); | |
0a40654b YL |
582 | } |
583 | ||
16546ee0 CG |
584 | void rgblight_setrgb_at(uint8_t r, uint8_t g, uint8_t b, uint8_t index) { |
585 | if (!rgblight_config.enable || index >= RGBLED_NUM) { return; } | |
586 | ||
587 | led[index].r = r; | |
588 | led[index].g = g; | |
589 | led[index].b = b; | |
590 | rgblight_set(); | |
591 | } | |
592 | ||
22ba36a4 | 593 | void rgblight_sethsv_at(uint8_t hue, uint8_t sat, uint8_t val, uint8_t index) { |
16546ee0 CG |
594 | if (!rgblight_config.enable) { return; } |
595 | ||
596 | LED_TYPE tmp_led; | |
597 | sethsv(hue, sat, val, &tmp_led); | |
598 | rgblight_setrgb_at(tmp_led.r, tmp_led.g, tmp_led.b, index); | |
599 | } | |
600 | ||
c1c5922a CL |
601 | #if defined(RGBLIGHT_EFFECT_BREATHING) || defined(RGBLIGHT_EFFECT_RAINBOW_MOOD) || defined(RGBLIGHT_EFFECT_RAINBOW_SWIRL) \ |
602 | || defined(RGBLIGHT_EFFECT_SNAKE) || defined(RGBLIGHT_EFFECT_KNIGHT) | |
603 | ||
604 | static uint8_t get_interval_time(const uint8_t* default_interval_address, uint8_t velocikey_min, uint8_t velocikey_max) { | |
f077204f | 605 | return |
c1c5922a CL |
606 | #ifdef VELOCIKEY_ENABLE |
607 | velocikey_enabled() ? velocikey_match_speed(velocikey_min, velocikey_max) : | |
608 | #endif | |
609 | pgm_read_byte(default_interval_address); | |
610 | } | |
611 | ||
612 | #endif | |
613 | ||
642f6cf1 E |
614 | void rgblight_setrgb_range(uint8_t r, uint8_t g, uint8_t b, uint8_t start, uint8_t end) { |
615 | if (!rgblight_config.enable || start < 0 || start >= end || end > RGBLED_NUM) { return; } | |
616 | ||
617 | for (uint8_t i = start; i < end; i++) { | |
618 | led[i].r = r; | |
619 | led[i].g = g; | |
620 | led[i].b = b; | |
621 | } | |
622 | rgblight_set(); | |
623 | wait_ms(1); | |
624 | } | |
625 | ||
22ba36a4 | 626 | void rgblight_sethsv_range(uint8_t hue, uint8_t sat, uint8_t val, uint8_t start, uint8_t end) { |
642f6cf1 E |
627 | if (!rgblight_config.enable) { return; } |
628 | ||
629 | LED_TYPE tmp_led; | |
630 | sethsv(hue, sat, val, &tmp_led); | |
631 | rgblight_setrgb_range(tmp_led.r, tmp_led.g, tmp_led.b, start, end); | |
632 | } | |
633 | ||
670a9b7f | 634 | #ifndef RGBLIGHT_SPLIT |
642f6cf1 E |
635 | void rgblight_setrgb_master(uint8_t r, uint8_t g, uint8_t b) { |
636 | rgblight_setrgb_range(r, g, b, 0 , (uint8_t) RGBLED_NUM/2); | |
637 | } | |
638 | ||
639 | void rgblight_setrgb_slave(uint8_t r, uint8_t g, uint8_t b) { | |
640 | rgblight_setrgb_range(r, g, b, (uint8_t) RGBLED_NUM/2, (uint8_t) RGBLED_NUM); | |
641 | } | |
642 | ||
22ba36a4 | 643 | void rgblight_sethsv_master(uint8_t hue, uint8_t sat, uint8_t val) { |
642f6cf1 E |
644 | rgblight_sethsv_range(hue, sat, val, 0, (uint8_t) RGBLED_NUM/2); |
645 | } | |
646 | ||
22ba36a4 | 647 | void rgblight_sethsv_slave(uint8_t hue, uint8_t sat, uint8_t val) { |
642f6cf1 E |
648 | rgblight_sethsv_range(hue, sat, val, (uint8_t) RGBLED_NUM/2, (uint8_t) RGBLED_NUM); |
649 | } | |
670a9b7f | 650 | #endif // ifndef RGBLIGHT_SPLIT |
642f6cf1 | 651 | |
d4cd5dda | 652 | #ifndef RGBLIGHT_CUSTOM_DRIVER |
0a40654b | 653 | void rgblight_set(void) { |
670a9b7f | 654 | LED_TYPE *start_led; |
f077204f | 655 | uint16_t num_leds = clipping_num_leds; |
670a9b7f TI |
656 | |
657 | if (!rgblight_config.enable) { | |
658 | for (uint8_t i = effect_start_pos; i < effect_end_pos; i++) { | |
3a860c4b JO |
659 | led[i].r = 0; |
660 | led[i].g = 0; | |
661 | led[i].b = 0; | |
662 | } | |
3a860c4b | 663 | } |
670a9b7f TI |
664 | #ifdef RGBLIGHT_LED_MAP |
665 | LED_TYPE led0[RGBLED_NUM]; | |
666 | for(uint8_t i = 0; i < RGBLED_NUM; i++) { | |
667 | led0[i] = led[pgm_read_byte(&led_map[i])]; | |
668 | } | |
669 | start_led = led0 + clipping_start_pos; | |
670 | #else | |
671 | start_led = led + clipping_start_pos; | |
672 | #endif | |
673 | #ifdef RGBW | |
674 | ws2812_setleds_rgbw(start_led, num_leds); | |
675 | #else | |
676 | ws2812_setleds(start_led, num_leds); | |
677 | #endif | |
0a40654b | 678 | } |
d4cd5dda | 679 | #endif |
0a40654b | 680 | |
dfab177f TI |
681 | #ifdef RGBLIGHT_SPLIT |
682 | /* for split keyboard master side */ | |
683 | uint8_t rgblight_get_change_flags(void) { | |
684 | return rgblight_status.change_flags; | |
685 | } | |
686 | ||
687 | void rgblight_clear_change_flags(void) { | |
688 | rgblight_status.change_flags = 0; | |
689 | } | |
690 | ||
691 | void rgblight_get_syncinfo(rgblight_syncinfo_t *syncinfo) { | |
692 | syncinfo->config = rgblight_config; | |
693 | syncinfo->status = rgblight_status; | |
694 | } | |
695 | ||
696 | /* for split keyboard slave side */ | |
697 | void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom) { | |
698 | if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_MODE) { | |
699 | if (syncinfo->config.enable) { | |
700 | rgblight_config.enable = 1; // == rgblight_enable_noeeprom(); | |
701 | rgblight_mode_eeprom_helper(syncinfo->config.mode, write_to_eeprom); | |
702 | } else { | |
703 | rgblight_disable_noeeprom(); | |
704 | } | |
705 | } | |
706 | if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_HSVS) { | |
707 | rgblight_sethsv_eeprom_helper(syncinfo->config.hue, syncinfo->config.sat, syncinfo->config.val, write_to_eeprom); | |
708 | // rgblight_config.speed = config->speed; // NEED??? | |
709 | } | |
710 | #ifdef RGBLIGHT_USE_TIMER | |
711 | if (syncinfo->status.change_flags & RGBLIGHT_STATUS_CHANGE_TIMER) { | |
712 | if (syncinfo->status.timer_enabled) { | |
713 | rgblight_timer_enable(); | |
714 | } else { | |
715 | rgblight_timer_disable(); | |
716 | } | |
717 | } | |
718 | #ifndef RGBLIGHT_SPLIT_NO_ANIMATION_SYNC | |
719 | if (syncinfo->status.change_flags & RGBLIGHT_STATUS_ANIMATION_TICK) { | |
720 | animation_status.restart = true; | |
721 | } | |
722 | #endif /* RGBLIGHT_SPLIT_NO_ANIMATION_SYNC */ | |
723 | #endif /* RGBLIGHT_USE_TIMER */ | |
724 | } | |
725 | #endif /* RGBLIGHT_SPLIT */ | |
726 | ||
6d6d91c8 | 727 | #ifdef RGBLIGHT_USE_TIMER |
57e08eb8 | 728 | |
dfab177f TI |
729 | typedef void (*effect_func_t)(animation_status_t *anim); |
730 | ||
731 | // Animation timer -- use system timer (AVR Timer0) | |
0a40654b | 732 | void rgblight_timer_init(void) { |
dfab177f | 733 | // OLD!!!! Animation timer -- AVR Timer3 |
e9f74875 JH |
734 | // static uint8_t rgblight_timer_is_init = 0; |
735 | // if (rgblight_timer_is_init) { | |
736 | // return; | |
737 | // } | |
738 | // rgblight_timer_is_init = 1; | |
739 | // /* Timer 3 setup */ | |
740 | // TCCR3B = _BV(WGM32) // CTC mode OCR3A as TOP | |
741 | // | _BV(CS30); // Clock selelct: clk/1 | |
742 | // /* Set TOP value */ | |
743 | // uint8_t sreg = SREG; | |
744 | // cli(); | |
745 | // OCR3AH = (RGBLED_TIMER_TOP >> 8) & 0xff; | |
746 | // OCR3AL = RGBLED_TIMER_TOP & 0xff; | |
747 | // SREG = sreg; | |
748 | ||
dfab177f TI |
749 | rgblight_status.timer_enabled = false; |
750 | RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE; | |
0a40654b YL |
751 | } |
752 | void rgblight_timer_enable(void) { | |
dfab177f TI |
753 | if( !is_static_effect(rgblight_config.mode) ) { |
754 | rgblight_status.timer_enabled = true; | |
755 | } | |
756 | animation_status.last_timer = timer_read(); | |
757 | RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE; | |
758 | dprintf("rgblight timer enabled.\n"); | |
0a40654b YL |
759 | } |
760 | void rgblight_timer_disable(void) { | |
dfab177f TI |
761 | rgblight_status.timer_enabled = false; |
762 | RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE; | |
763 | dprintf("rgblight timer disable.\n"); | |
0a40654b YL |
764 | } |
765 | void rgblight_timer_toggle(void) { | |
dfab177f TI |
766 | dprintf("rgblight timer toggle.\n"); |
767 | if(rgblight_status.timer_enabled) { | |
768 | rgblight_timer_disable(); | |
769 | } else { | |
770 | rgblight_timer_enable(); | |
771 | } | |
0a40654b YL |
772 | } |
773 | ||
4094544d EZ |
774 | void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b) { |
775 | rgblight_enable(); | |
6d6d91c8 | 776 | rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT); |
4094544d EZ |
777 | rgblight_setrgb(r, g, b); |
778 | } | |
779 | ||
dfab177f TI |
780 | static void rgblight_effect_dummy(animation_status_t *anim) { |
781 | // do nothing | |
782 | /******** | |
783 | dprintf("rgblight_task() what happened?\n"); | |
784 | dprintf("is_static_effect %d\n", is_static_effect(rgblight_config.mode)); | |
785 | dprintf("mode = %d, base_mode = %d, timer_enabled %d, ", | |
786 | rgblight_config.mode, rgblight_status.base_mode, | |
787 | rgblight_status.timer_enabled); | |
788 | dprintf("last_timer = %d\n",anim->last_timer); | |
789 | **/ | |
790 | } | |
791 | ||
e9f74875 | 792 | void rgblight_task(void) { |
dfab177f TI |
793 | if (rgblight_status.timer_enabled) { |
794 | effect_func_t effect_func = rgblight_effect_dummy; | |
795 | uint16_t interval_time = 2000; // dummy interval | |
796 | uint8_t delta = rgblight_config.mode - rgblight_status.base_mode; | |
797 | animation_status.delta = delta; | |
c1c5922a | 798 | |
6d6d91c8 TI |
799 | // static light mode, do nothing here |
800 | if ( 1 == 0 ) { //dummy | |
801 | } | |
802 | #ifdef RGBLIGHT_EFFECT_BREATHING | |
dfab177f | 803 | else if (rgblight_status.base_mode == RGBLIGHT_MODE_BREATHING) { |
6d6d91c8 | 804 | // breathing mode |
dfab177f TI |
805 | interval_time = get_interval_time(&RGBLED_BREATHING_INTERVALS[delta], 1, 100); |
806 | effect_func = rgblight_effect_breathing; | |
6d6d91c8 TI |
807 | } |
808 | #endif | |
809 | #ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD | |
dfab177f | 810 | else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_MOOD) { |
6d6d91c8 | 811 | // rainbow mood mode |
dfab177f TI |
812 | interval_time = get_interval_time(&RGBLED_RAINBOW_MOOD_INTERVALS[delta], 5, 100); |
813 | effect_func = rgblight_effect_rainbow_mood; | |
6d6d91c8 TI |
814 | } |
815 | #endif | |
816 | #ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL | |
dfab177f | 817 | else if (rgblight_status.base_mode == RGBLIGHT_MODE_RAINBOW_SWIRL) { |
6d6d91c8 | 818 | // rainbow swirl mode |
dfab177f TI |
819 | interval_time = get_interval_time(&RGBLED_RAINBOW_SWIRL_INTERVALS[delta / 2], 1, 100); |
820 | effect_func = rgblight_effect_rainbow_swirl; | |
6d6d91c8 TI |
821 | } |
822 | #endif | |
823 | #ifdef RGBLIGHT_EFFECT_SNAKE | |
dfab177f | 824 | else if (rgblight_status.base_mode == RGBLIGHT_MODE_SNAKE) { |
6d6d91c8 | 825 | // snake mode |
dfab177f TI |
826 | interval_time = get_interval_time(&RGBLED_SNAKE_INTERVALS[delta / 2], 1, 200); |
827 | effect_func = rgblight_effect_snake; | |
6d6d91c8 TI |
828 | } |
829 | #endif | |
830 | #ifdef RGBLIGHT_EFFECT_KNIGHT | |
dfab177f | 831 | else if (rgblight_status.base_mode == RGBLIGHT_MODE_KNIGHT) { |
6d6d91c8 | 832 | // knight mode |
dfab177f TI |
833 | interval_time = get_interval_time(&RGBLED_KNIGHT_INTERVALS[delta], 5, 100); |
834 | effect_func = rgblight_effect_knight; | |
6d6d91c8 TI |
835 | } |
836 | #endif | |
837 | #ifdef RGBLIGHT_EFFECT_CHRISTMAS | |
dfab177f | 838 | else if (rgblight_status.base_mode == RGBLIGHT_MODE_CHRISTMAS) { |
6d6d91c8 | 839 | // christmas mode |
dfab177f TI |
840 | interval_time = RGBLIGHT_EFFECT_CHRISTMAS_INTERVAL; |
841 | effect_func = (effect_func_t)rgblight_effect_christmas; | |
6d6d91c8 TI |
842 | } |
843 | #endif | |
844 | #ifdef RGBLIGHT_EFFECT_RGB_TEST | |
dfab177f | 845 | else if (rgblight_status.base_mode == RGBLIGHT_MODE_RGB_TEST) { |
6d6d91c8 | 846 | // RGB test mode |
dfab177f TI |
847 | interval_time = pgm_read_word(&RGBLED_RGBTEST_INTERVALS[0]); |
848 | effect_func = (effect_func_t)rgblight_effect_rgbtest; | |
6d6d91c8 TI |
849 | } |
850 | #endif | |
851 | #ifdef RGBLIGHT_EFFECT_ALTERNATING | |
dfab177f TI |
852 | else if (rgblight_status.base_mode == RGBLIGHT_MODE_ALTERNATING){ |
853 | interval_time = 500; | |
854 | effect_func = (effect_func_t)rgblight_effect_alternating; | |
855 | } | |
856 | #endif | |
857 | if (animation_status.restart) { | |
858 | animation_status.restart = false; | |
859 | animation_status.last_timer = timer_read() - interval_time - 1; | |
860 | animation_status.pos16 = 0; // restart signal to local each effect | |
e9f74875 | 861 | } |
dfab177f TI |
862 | if (timer_elapsed(animation_status.last_timer) >= interval_time) { |
863 | #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) | |
864 | static uint16_t report_last_timer = 0; | |
865 | static bool tick_flag = false; | |
866 | uint16_t oldpos16; | |
867 | if (tick_flag) { | |
868 | tick_flag = false; | |
869 | //dprintf("rgblight animation tick\n"); | |
870 | if (timer_elapsed(report_last_timer) >= 30000) { | |
871 | report_last_timer = timer_read(); | |
872 | dprintf("rgblight animation tick report to slave\n"); | |
873 | RGBLIGHT_SPLIT_ANIMATION_TICK; | |
874 | } | |
875 | } | |
876 | oldpos16 = animation_status.pos16; | |
877 | //dprintf("call effect function\n"); | |
878 | #endif | |
879 | animation_status.last_timer += interval_time; | |
880 | effect_func(&animation_status); | |
881 | #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) | |
882 | //dprintf("pos16, oldpos16 = %d %d\n", | |
883 | // animation_status.pos16,oldpos16); | |
884 | if (animation_status.pos16 == 0 && oldpos16 != 0) { | |
885 | //dprintf("flag on\n"); | |
886 | tick_flag = true; | |
887 | } | |
6d6d91c8 | 888 | #endif |
dfab177f | 889 | } |
3a860c4b JO |
890 | } |
891 | } | |
892 | ||
6d6d91c8 TI |
893 | #endif /* RGBLIGHT_USE_TIMER */ |
894 | ||
3a860c4b | 895 | // Effects |
6d6d91c8 | 896 | #ifdef RGBLIGHT_EFFECT_BREATHING |
3da8d46a TI |
897 | |
898 | #ifndef RGBLIGHT_EFFECT_BREATHE_CENTER | |
899 | #ifndef RGBLIGHT_BREATHE_TABLE_SIZE | |
900 | #define RGBLIGHT_BREATHE_TABLE_SIZE 256 // 256 or 128 or 64 | |
901 | #endif | |
902 | #include <rgblight_breathe_table.h> | |
903 | #endif | |
904 | ||
6d6d91c8 TI |
905 | __attribute__ ((weak)) |
906 | const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5}; | |
907 | ||
dfab177f | 908 | void rgblight_effect_breathing(animation_status_t *anim) { |
ad49db8c | 909 | float val; |
0a40654b | 910 | |
ad49db8c | 911 | // http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/ |
3da8d46a TI |
912 | #ifdef RGBLIGHT_EFFECT_BREATHE_TABLE |
913 | val = pgm_read_byte(&rgblight_effect_breathe_table[anim->pos / table_scale]); | |
914 | #else | |
dfab177f | 915 | val = (exp(sin((anim->pos/255.0)*M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER/M_E)*(RGBLIGHT_EFFECT_BREATHE_MAX/(M_E-1/M_E)); |
3da8d46a | 916 | #endif |
751719e6 | 917 | rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val); |
22ba36a4 | 918 | anim->pos = (anim->pos + 1); |
0a40654b | 919 | } |
6d6d91c8 TI |
920 | #endif |
921 | ||
922 | #ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD | |
923 | __attribute__ ((weak)) | |
924 | const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30}; | |
925 | ||
dfab177f TI |
926 | void rgblight_effect_rainbow_mood(animation_status_t *anim) { |
927 | rgblight_sethsv_noeeprom_old(anim->current_hue, rgblight_config.sat, rgblight_config.val); | |
22ba36a4 | 928 | anim->current_hue++; |
0a40654b | 929 | } |
6d6d91c8 TI |
930 | #endif |
931 | ||
932 | #ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL | |
94f58322 | 933 | #ifndef RGBLIGHT_RAINBOW_SWIRL_RANGE |
22ba36a4 | 934 | #define RGBLIGHT_RAINBOW_SWIRL_RANGE 255 |
94f58322 FT |
935 | #endif |
936 | ||
6d6d91c8 TI |
937 | __attribute__ ((weak)) |
938 | const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20}; | |
939 | ||
dfab177f | 940 | void rgblight_effect_rainbow_swirl(animation_status_t *anim) { |
22ba36a4 | 941 | uint8_t hue; |
3a860c4b | 942 | uint8_t i; |
c1c5922a | 943 | |
670a9b7f TI |
944 | for (i = 0; i < effect_num_leds; i++) { |
945 | hue = (RGBLIGHT_RAINBOW_SWIRL_RANGE / effect_num_leds * i + anim->current_hue); | |
946 | sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i + effect_start_pos]); | |
3a860c4b JO |
947 | } |
948 | rgblight_set(); | |
949 | ||
dfab177f | 950 | if (anim->delta % 2) { |
22ba36a4 | 951 | anim->current_hue++; |
3a860c4b | 952 | } else { |
22ba36a4 | 953 | anim->current_hue--; |
3a860c4b | 954 | } |
0a40654b | 955 | } |
6d6d91c8 TI |
956 | #endif |
957 | ||
958 | #ifdef RGBLIGHT_EFFECT_SNAKE | |
959 | __attribute__ ((weak)) | |
960 | const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20}; | |
961 | ||
dfab177f | 962 | void rgblight_effect_snake(animation_status_t *anim) { |
3a860c4b | 963 | static uint8_t pos = 0; |
3a860c4b JO |
964 | uint8_t i, j; |
965 | int8_t k; | |
899c88cd | 966 | int8_t increment = 1; |
dfab177f TI |
967 | |
968 | if (anim->delta % 2) { | |
899c88cd | 969 | increment = -1; |
3a860c4b | 970 | } |
c1c5922a | 971 | |
dfab177f TI |
972 | #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) |
973 | if (anim->pos == 0) { // restart signal | |
974 | if (increment == 1) { | |
670a9b7f | 975 | pos = effect_num_leds - 1; |
dfab177f TI |
976 | } else { |
977 | pos = 0; | |
978 | } | |
979 | anim->pos = 1; | |
3a860c4b | 980 | } |
dfab177f TI |
981 | #endif |
982 | ||
670a9b7f TI |
983 | for (i = 0; i < effect_num_leds; i++) { |
984 | LED_TYPE *ledp = led + i + effect_start_pos; | |
985 | ledp->r = 0; | |
986 | ledp->g = 0; | |
987 | ledp->b = 0; | |
3a860c4b | 988 | for (j = 0; j < RGBLIGHT_EFFECT_SNAKE_LENGTH; j++) { |
899c88cd | 989 | k = pos + j * increment; |
3a860c4b | 990 | if (k < 0) { |
670a9b7f | 991 | k = k + effect_num_leds; |
3a860c4b JO |
992 | } |
993 | if (i == k) { | |
dfab177f TI |
994 | sethsv(rgblight_config.hue, rgblight_config.sat, |
995 | (uint8_t)(rgblight_config.val*(RGBLIGHT_EFFECT_SNAKE_LENGTH-j)/RGBLIGHT_EFFECT_SNAKE_LENGTH), | |
670a9b7f | 996 | ledp); |
3a860c4b JO |
997 | } |
998 | } | |
999 | } | |
1000 | rgblight_set(); | |
899c88cd | 1001 | if (increment == 1) { |
3a860c4b | 1002 | if (pos - 1 < 0) { |
670a9b7f | 1003 | pos = effect_num_leds - 1; |
dfab177f TI |
1004 | #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) |
1005 | anim->pos = 0; | |
1006 | #endif | |
3a860c4b JO |
1007 | } else { |
1008 | pos -= 1; | |
dfab177f TI |
1009 | #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) |
1010 | anim->pos = 1; | |
1011 | #endif | |
3a860c4b JO |
1012 | } |
1013 | } else { | |
670a9b7f | 1014 | pos = (pos + 1) % effect_num_leds; |
dfab177f TI |
1015 | #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) |
1016 | anim->pos = pos; | |
1017 | #endif | |
3a860c4b | 1018 | } |
0a40654b | 1019 | } |
6d6d91c8 TI |
1020 | #endif |
1021 | ||
1022 | #ifdef RGBLIGHT_EFFECT_KNIGHT | |
1023 | __attribute__ ((weak)) | |
1024 | const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31}; | |
1025 | ||
dfab177f | 1026 | void rgblight_effect_knight(animation_status_t *anim) { |
4edfa97e DS |
1027 | |
1028 | static int8_t low_bound = 0; | |
1029 | static int8_t high_bound = RGBLIGHT_EFFECT_KNIGHT_LENGTH - 1; | |
1030 | static int8_t increment = 1; | |
1031 | uint8_t i, cur; | |
1032 | ||
dfab177f TI |
1033 | #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) |
1034 | if (anim->pos == 0) { // restart signal | |
1035 | anim->pos = 1; | |
1036 | low_bound = 0; | |
1037 | high_bound = RGBLIGHT_EFFECT_KNIGHT_LENGTH - 1; | |
1038 | increment = 1; | |
1039 | } | |
1040 | #endif | |
4580d3a7 | 1041 | // Set all the LEDs to 0 |
670a9b7f | 1042 | for (i = effect_start_pos; i < effect_end_pos; i++) { |
4580d3a7 | 1043 | led[i].r = 0; |
1044 | led[i].g = 0; | |
1045 | led[i].b = 0; | |
1046 | } | |
1047 | // Determine which LEDs should be lit up | |
1048 | for (i = 0; i < RGBLIGHT_EFFECT_KNIGHT_LED_NUM; i++) { | |
670a9b7f | 1049 | cur = (i + RGBLIGHT_EFFECT_KNIGHT_OFFSET) % effect_num_leds + effect_start_pos; |
4edfa97e DS |
1050 | |
1051 | if (i >= low_bound && i <= high_bound) { | |
1052 | sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[cur]); | |
3a860c4b | 1053 | } else { |
4edfa97e DS |
1054 | led[cur].r = 0; |
1055 | led[cur].g = 0; | |
1056 | led[cur].b = 0; | |
3a860c4b JO |
1057 | } |
1058 | } | |
4edfa97e DS |
1059 | rgblight_set(); |
1060 | ||
4580d3a7 | 1061 | // Move from low_bound to high_bound changing the direction we increment each |
1062 | // time a boundary is hit. | |
4edfa97e DS |
1063 | low_bound += increment; |
1064 | high_bound += increment; | |
1065 | ||
4580d3a7 | 1066 | if (high_bound <= 0 || low_bound >= RGBLIGHT_EFFECT_KNIGHT_LED_NUM - 1) { |
4edfa97e | 1067 | increment = -increment; |
dfab177f TI |
1068 | #if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC) |
1069 | if (increment == 1) { | |
1070 | anim->pos = 0; | |
1071 | } | |
1072 | #endif | |
4edfa97e | 1073 | } |
3a860c4b | 1074 | } |
6d6d91c8 | 1075 | #endif |
3a860c4b | 1076 | |
6d6d91c8 | 1077 | #ifdef RGBLIGHT_EFFECT_CHRISTMAS |
dfab177f | 1078 | void rgblight_effect_christmas(animation_status_t *anim) { |
22ba36a4 | 1079 | uint8_t hue; |
cae269b0 | 1080 | uint8_t i; |
dfab177f TI |
1081 | |
1082 | anim->current_offset = (anim->current_offset + 1) % 2; | |
670a9b7f | 1083 | for (i = 0; i < effect_num_leds; i++) { |
22ba36a4 | 1084 | hue = 0 + ((i/RGBLIGHT_EFFECT_CHRISTMAS_STEP + anim->current_offset) % 2) * 85; |
670a9b7f | 1085 | sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i + effect_start_pos]); |
cae269b0 JH |
1086 | } |
1087 | rgblight_set(); | |
1088 | } | |
6d6d91c8 TI |
1089 | #endif |
1090 | ||
1091 | #ifdef RGBLIGHT_EFFECT_RGB_TEST | |
1092 | __attribute__ ((weak)) | |
1093 | const uint16_t RGBLED_RGBTEST_INTERVALS[] PROGMEM = {1024}; | |
cae269b0 | 1094 | |
dfab177f | 1095 | void rgblight_effect_rgbtest(animation_status_t *anim) { |
52297346 TI |
1096 | static uint8_t maxval = 0; |
1097 | uint8_t g; uint8_t r; uint8_t b; | |
1098 | ||
52297346 TI |
1099 | if( maxval == 0 ) { |
1100 | LED_TYPE tmp_led; | |
1101 | sethsv(0, 255, RGBLIGHT_LIMIT_VAL, &tmp_led); | |
1102 | maxval = tmp_led.r; | |
1103 | } | |
52297346 | 1104 | g = r = b = 0; |
dfab177f | 1105 | switch( anim->pos ) { |
52297346 TI |
1106 | case 0: r = maxval; break; |
1107 | case 1: g = maxval; break; | |
1108 | case 2: b = maxval; break; | |
1109 | } | |
1110 | rgblight_setrgb(r, g, b); | |
dfab177f | 1111 | anim->pos = (anim->pos + 1) % 3; |
52297346 | 1112 | } |
6d6d91c8 | 1113 | #endif |
52297346 | 1114 | |
6d6d91c8 | 1115 | #ifdef RGBLIGHT_EFFECT_ALTERNATING |
dfab177f | 1116 | void rgblight_effect_alternating(animation_status_t *anim) { |
595f3cbe | 1117 | |
670a9b7f TI |
1118 | for (int i = 0; i < effect_num_leds; i++) { |
1119 | LED_TYPE *ledp = led + i + effect_start_pos; | |
1120 | if (i<effect_num_leds/2 && anim->pos) { | |
1121 | sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, ledp); | |
1122 | } else if (i>=effect_num_leds/2 && !anim->pos) { | |
1123 | sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, ledp); | |
1124 | } else { | |
1125 | sethsv(rgblight_config.hue, rgblight_config.sat, 0, ledp); | |
db03b769 | 1126 | } |
595f3cbe B |
1127 | } |
1128 | rgblight_set(); | |
dfab177f | 1129 | anim->pos = (anim->pos + 1) % 2; |
595f3cbe | 1130 | } |
6d6d91c8 | 1131 | #endif |