Commit | Line | Data |
---|---|---|
30680c6e | 1 | /* |
2 | Copyright 2018 Massdrop Inc. | |
3 | ||
4 | This program is free software: you can redistribute it and/or modify | |
5 | it under the terms of the GNU General Public License as published by | |
6 | the Free Software Foundation, either version 2 of the License, or | |
7 | (at your option) any later version. | |
8 | ||
9 | This program is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | GNU General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU General Public License | |
15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | */ | |
17 | ||
18 | #include "arm_atsam_protocol.h" | |
19 | #include "tmk_core/common/led.h" | |
763b26cd | 20 | #include "rgb_matrix.h" |
30680c6e | 21 | #include <string.h> |
d55dc9b8 | 22 | #include <math.h> |
30680c6e | 23 | |
763b26cd DP |
24 | #ifdef USE_MASSDROP_CONFIGURATOR |
25 | __attribute__((weak)) | |
26 | led_instruction_t led_instructions[] = { { .end = 1 } }; | |
27 | static void led_matrix_massdrop_config_override(int i); | |
28 | #endif // USE_MASSDROP_CONFIGURATOR | |
29 | ||
30 | extern rgb_config_t rgb_matrix_config; | |
31 | extern rgb_counters_t g_rgb_counters; | |
32 | ||
30680c6e | 33 | void SERCOM1_0_Handler( void ) |
34 | { | |
35 | if (SERCOM1->I2CM.INTFLAG.bit.ERROR) | |
36 | { | |
37 | SERCOM1->I2CM.INTFLAG.reg = SERCOM_I2CM_INTENCLR_ERROR; | |
38 | } | |
39 | } | |
40 | ||
41 | void DMAC_0_Handler( void ) | |
42 | { | |
43 | if (DMAC->Channel[0].CHINTFLAG.bit.TCMPL) | |
44 | { | |
45 | DMAC->Channel[0].CHINTFLAG.reg = DMAC_CHINTENCLR_TCMPL; | |
46 | ||
47 | i2c1_stop(); | |
48 | ||
49 | i2c_led_q_running = 0; | |
50 | ||
51 | i2c_led_q_run(); | |
52 | ||
53 | return; | |
54 | } | |
55 | ||
56 | if (DMAC->Channel[0].CHINTFLAG.bit.TERR) | |
57 | { | |
58 | DMAC->Channel[0].CHINTFLAG.reg = DMAC_CHINTENCLR_TERR; | |
59 | } | |
60 | } | |
61 | ||
62 | issi3733_driver_t issidrv[ISSI3733_DRIVER_COUNT]; | |
63 | ||
763b26cd DP |
64 | issi3733_led_t led_map[ISSI3733_LED_COUNT] = ISSI3733_LED_MAP; |
65 | RGB led_buffer[ISSI3733_LED_COUNT]; | |
30680c6e | 66 | |
67 | uint8_t gcr_desired; | |
30680c6e | 68 | uint8_t gcr_actual; |
69 | uint8_t gcr_actual_last; | |
763b26cd DP |
70 | #ifdef USE_MASSDROP_CONFIGURATOR |
71 | uint8_t gcr_breathe; | |
72 | float breathe_mult; | |
73 | float pomod; | |
74 | #endif | |
30680c6e | 75 | |
76 | #define ACT_GCR_NONE 0 | |
77 | #define ACT_GCR_INC 1 | |
78 | #define ACT_GCR_DEC 2 | |
79 | ||
80 | #define LED_GCR_STEP_AUTO 2 | |
81 | ||
82 | static uint8_t gcr_min_counter; | |
83 | static uint8_t v_5v_cat_hit; | |
84 | ||
85 | //WARNING: Automatic GCR is in place to prevent USB shutdown and LED driver overloading | |
86 | void gcr_compute(void) | |
87 | { | |
88 | uint8_t action = ACT_GCR_NONE; | |
763b26cd | 89 | uint8_t gcr_use = gcr_desired; |
30680c6e | 90 | |
763b26cd | 91 | #ifdef USE_MASSDROP_CONFIGURATOR |
30680c6e | 92 | if (led_animation_breathing) |
763b26cd | 93 | { |
30680c6e | 94 | gcr_use = gcr_breathe; |
763b26cd DP |
95 | } |
96 | #endif | |
30680c6e | 97 | |
98 | //If the 5v takes a catastrophic hit, disable the LED drivers briefly, assert auto gcr mode, min gcr and let the auto take over | |
99 | if (v_5v < V5_CAT) | |
100 | { | |
101 | I2C3733_Control_Set(0); | |
102 | //CDC_print("USB: WARNING: 5V catastrophic level reached! Disabling LED drivers!\r\n"); //Blocking print is bad here! | |
103 | v_5v_cat_hit = 20; //~100ms recover | |
104 | gcr_actual = 0; //Minimize GCR | |
105 | usb_gcr_auto = 1; //Force auto mode enabled | |
106 | return; | |
107 | } | |
108 | else if (v_5v_cat_hit > 1) | |
109 | { | |
110 | v_5v_cat_hit--; | |
111 | return; | |
112 | } | |
113 | else if (v_5v_cat_hit == 1) | |
114 | { | |
115 | I2C3733_Control_Set(1); | |
116 | CDC_print("USB: WARNING: Re-enabling LED drivers\r\n"); | |
117 | v_5v_cat_hit = 0; | |
118 | return; | |
119 | } | |
120 | ||
121 | if (usb_gcr_auto) | |
122 | { | |
123 | if (v_5v_avg < V5_LOW) action = ACT_GCR_DEC; | |
124 | else if (v_5v_avg > V5_HIGH && gcr_actual < gcr_use) action = ACT_GCR_INC; | |
125 | else if (gcr_actual > gcr_use) action = ACT_GCR_DEC; | |
126 | } | |
127 | else | |
128 | { | |
129 | if (gcr_actual < gcr_use) action = ACT_GCR_INC; | |
130 | else if (gcr_actual > gcr_use) action = ACT_GCR_DEC; | |
131 | } | |
132 | ||
133 | if (action == ACT_GCR_NONE) | |
134 | { | |
135 | gcr_min_counter = 0; | |
136 | } | |
137 | else if (action == ACT_GCR_INC) | |
138 | { | |
139 | if (LED_GCR_STEP_AUTO > LED_GCR_MAX - gcr_actual) gcr_actual = LED_GCR_MAX; //Obey max and prevent wrapping | |
140 | else gcr_actual += LED_GCR_STEP_AUTO; | |
141 | gcr_min_counter = 0; | |
142 | } | |
143 | else if (action == ACT_GCR_DEC) | |
144 | { | |
145 | if (LED_GCR_STEP_AUTO > gcr_actual) //Prevent wrapping | |
146 | { | |
147 | gcr_actual = 0; | |
148 | //At this point, power can no longer be cut from the LED drivers, so focus on cutting out extra port if active | |
149 | if (usb_extra_state != USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG) //If not in a wait for replug state | |
150 | { | |
151 | if (usb_extra_state == USB_EXTRA_STATE_ENABLED) //If extra usb is enabled | |
152 | { | |
153 | gcr_min_counter++; | |
154 | if (gcr_min_counter > 200) //5ms per check = 1s delay | |
155 | { | |
156 | USB_ExtraSetState(USB_EXTRA_STATE_DISABLED_UNTIL_REPLUG); | |
157 | usb_extra_manual = 0; //Force disable manual mode of extra port | |
158 | if (usb_extra_manual) CDC_print("USB: Disabling extra port until replug and manual mode toggle!\r\n"); | |
159 | else CDC_print("USB: Disabling extra port until replug!\r\n"); | |
160 | } | |
161 | } | |
162 | } | |
163 | } | |
164 | else | |
165 | { | |
166 | //Power successfully cut back from LED drivers | |
167 | gcr_actual -= LED_GCR_STEP_AUTO; | |
168 | gcr_min_counter = 0; | |
169 | ||
763b26cd | 170 | #ifdef USE_MASSDROP_CONFIGURATOR |
30680c6e | 171 | //If breathe mode is active, the top end can fluctuate if the host can not supply enough current |
172 | //So set the breathe GCR to where it becomes stable | |
173 | if (led_animation_breathing == 1) | |
174 | { | |
175 | gcr_breathe = gcr_actual; | |
176 | //PS: At this point, setting breathing to exhale makes a noticebly shorter cycle | |
177 | // and the same would happen maybe one or two more times. Therefore I'm favoring | |
178 | // powering through one full breathe and letting gcr settle completely | |
179 | } | |
763b26cd | 180 | #endif |
30680c6e | 181 | } |
182 | } | |
183 | } | |
184 | ||
30680c6e | 185 | void issi3733_prepare_arrays(void) |
186 | { | |
187 | memset(issidrv,0,sizeof(issi3733_driver_t) * ISSI3733_DRIVER_COUNT); | |
188 | ||
189 | int i; | |
190 | uint8_t addrs[ISSI3733_DRIVER_COUNT] = ISSI3773_DRIVER_ADDRESSES; | |
191 | ||
192 | for (i=0;i<ISSI3733_DRIVER_COUNT;i++) | |
193 | { | |
194 | issidrv[i].addr = addrs[i]; | |
195 | } | |
196 | ||
763b26cd | 197 | for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++) |
30680c6e | 198 | { |
199 | //BYTE: 1 + (SW-1)*16 + (CS-1) | |
763b26cd DP |
200 | led_map[i].rgb.g = issidrv[led_map[i].adr.drv-1].pwm + 1 + ((led_map[i].adr.swg-1)*16 + (led_map[i].adr.cs-1)); |
201 | led_map[i].rgb.r = issidrv[led_map[i].adr.drv-1].pwm + 1 + ((led_map[i].adr.swr-1)*16 + (led_map[i].adr.cs-1)); | |
202 | led_map[i].rgb.b = issidrv[led_map[i].adr.drv-1].pwm + 1 + ((led_map[i].adr.swb-1)*16 + (led_map[i].adr.cs-1)); | |
30680c6e | 203 | |
204 | //BYTE: 1 + (SW-1)*2 + (CS-1)/8 | |
205 | //BIT: (CS-1)%8 | |
763b26cd DP |
206 | *(issidrv[led_map[i].adr.drv-1].onoff + 1 + (led_map[i].adr.swg-1)*2+(led_map[i].adr.cs-1)/8) |= (1<<((led_map[i].adr.cs-1)%8)); |
207 | *(issidrv[led_map[i].adr.drv-1].onoff + 1 + (led_map[i].adr.swr-1)*2+(led_map[i].adr.cs-1)/8) |= (1<<((led_map[i].adr.cs-1)%8)); | |
208 | *(issidrv[led_map[i].adr.drv-1].onoff + 1 + (led_map[i].adr.swb-1)*2+(led_map[i].adr.cs-1)/8) |= (1<<((led_map[i].adr.cs-1)%8)); | |
30680c6e | 209 | } |
210 | } | |
211 | ||
763b26cd | 212 | void led_matrix_prepare(void) |
30680c6e | 213 | { |
763b26cd | 214 | for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++) |
30680c6e | 215 | { |
763b26cd DP |
216 | *led_map[i].rgb.r = 0; |
217 | *led_map[i].rgb.g = 0; | |
218 | *led_map[i].rgb.b = 0; | |
30680c6e | 219 | } |
30680c6e | 220 | } |
221 | ||
763b26cd | 222 | void led_set_one(int i, uint8_t r, uint8_t g, uint8_t b) |
30680c6e | 223 | { |
763b26cd | 224 | if (i < ISSI3733_LED_COUNT) |
30680c6e | 225 | { |
763b26cd DP |
226 | #ifdef USE_MASSDROP_CONFIGURATOR |
227 | led_matrix_massdrop_config_override(i); | |
228 | #else | |
229 | led_buffer[i].r = r; | |
230 | led_buffer[i].g = g; | |
231 | led_buffer[i].b = b; | |
232 | #endif | |
30680c6e | 233 | } |
234 | } | |
235 | ||
763b26cd | 236 | void led_set_all(uint8_t r, uint8_t g, uint8_t b) |
30680c6e | 237 | { |
763b26cd DP |
238 | for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++) |
239 | { | |
240 | led_set_one(i, r, g, b); | |
241 | } | |
30680c6e | 242 | } |
243 | ||
763b26cd | 244 | void init(void) |
30680c6e | 245 | { |
763b26cd | 246 | DBGC(DC_LED_MATRIX_INIT_BEGIN); |
30680c6e | 247 | |
763b26cd | 248 | issi3733_prepare_arrays(); |
30680c6e | 249 | |
763b26cd | 250 | led_matrix_prepare(); |
30680c6e | 251 | |
763b26cd DP |
252 | gcr_min_counter = 0; |
253 | v_5v_cat_hit = 0; | |
30680c6e | 254 | |
763b26cd DP |
255 | DBGC(DC_LED_MATRIX_INIT_COMPLETE); |
256 | } | |
30680c6e | 257 | |
763b26cd DP |
258 | void flush(void) |
259 | { | |
260 | #ifdef USE_MASSDROP_CONFIGURATOR | |
261 | if (!led_enabled) { return; } //Prevent calculations and I2C traffic if LED drivers are not enabled | |
262 | #else | |
263 | if (!sr_exp_data.bit.SDB_N) { return; } //Prevent calculations and I2C traffic if LED drivers are not enabled | |
264 | #endif | |
30680c6e | 265 | |
763b26cd DP |
266 | // Wait for previous transfer to complete |
267 | while (i2c_led_q_running) {} | |
30680c6e | 268 | |
763b26cd DP |
269 | // Copy buffer to live DMA region |
270 | for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++) | |
30680c6e | 271 | { |
763b26cd DP |
272 | *led_map[i].rgb.r = led_buffer[i].r; |
273 | *led_map[i].rgb.g = led_buffer[i].g; | |
274 | *led_map[i].rgb.b = led_buffer[i].b; | |
30680c6e | 275 | } |
276 | ||
763b26cd DP |
277 | #ifdef USE_MASSDROP_CONFIGURATOR |
278 | breathe_mult = 1; | |
30680c6e | 279 | |
763b26cd | 280 | if (led_animation_breathing) |
30680c6e | 281 | { |
763b26cd DP |
282 | //+60us 119 LED |
283 | led_animation_breathe_cur += BREATHE_STEP * breathe_dir; | |
284 | ||
285 | if (led_animation_breathe_cur >= BREATHE_MAX_STEP) | |
286 | breathe_dir = -1; | |
287 | else if (led_animation_breathe_cur <= BREATHE_MIN_STEP) | |
288 | breathe_dir = 1; | |
289 | ||
290 | //Brightness curve created for 256 steps, 0 - ~98% | |
291 | breathe_mult = 0.000015 * led_animation_breathe_cur * led_animation_breathe_cur; | |
292 | if (breathe_mult > 1) breathe_mult = 1; | |
293 | else if (breathe_mult < 0) breathe_mult = 0; | |
294 | } | |
30680c6e | 295 | |
763b26cd DP |
296 | //This should only be performed once per frame |
297 | pomod = (float)((g_rgb_counters.tick / 10) % (uint32_t)(1000.0f / led_animation_speed)) / 10.0f * led_animation_speed; | |
298 | pomod *= 100.0f; | |
299 | pomod = (uint32_t)pomod % 10000; | |
300 | pomod /= 100.0f; | |
30680c6e | 301 | |
763b26cd | 302 | #endif // USE_MASSDROP_CONFIGURATOR |
30680c6e | 303 | |
763b26cd | 304 | uint8_t drvid; |
30680c6e | 305 | |
763b26cd DP |
306 | //NOTE: GCR does not need to be timed with LED processing, but there is really no harm |
307 | if (gcr_actual != gcr_actual_last) | |
308 | { | |
309 | for (drvid=0;drvid<ISSI3733_DRIVER_COUNT;drvid++) | |
310 | I2C_LED_Q_GCR(drvid); //Queue data | |
311 | gcr_actual_last = gcr_actual; | |
312 | } | |
30680c6e | 313 | |
763b26cd DP |
314 | for (drvid=0;drvid<ISSI3733_DRIVER_COUNT;drvid++) |
315 | I2C_LED_Q_PWM(drvid); //Queue data | |
30680c6e | 316 | |
763b26cd DP |
317 | i2c_led_q_run(); |
318 | } | |
30680c6e | 319 | |
763b26cd DP |
320 | void led_matrix_indicators(void) |
321 | { | |
322 | uint8_t kbled = keyboard_leds(); | |
323 | if (kbled && rgb_matrix_config.enable) | |
324 | { | |
325 | for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++) | |
30680c6e | 326 | { |
30680c6e | 327 | if ( |
763b26cd DP |
328 | #if USB_LED_NUM_LOCK_SCANCODE != 255 |
329 | (led_map[i].scan == USB_LED_NUM_LOCK_SCANCODE && (kbled & (1<<USB_LED_NUM_LOCK))) || | |
330 | #endif //NUM LOCK | |
331 | #if USB_LED_CAPS_LOCK_SCANCODE != 255 | |
332 | (led_map[i].scan == USB_LED_CAPS_LOCK_SCANCODE && (kbled & (1<<USB_LED_CAPS_LOCK))) || | |
333 | #endif //CAPS LOCK | |
334 | #if USB_LED_SCROLL_LOCK_SCANCODE != 255 | |
335 | (led_map[i].scan == USB_LED_SCROLL_LOCK_SCANCODE && (kbled & (1<<USB_LED_SCROLL_LOCK))) || | |
336 | #endif //SCROLL LOCK | |
337 | #if USB_LED_COMPOSE_SCANCODE != 255 | |
338 | (led_map[i].scan == USB_LED_COMPOSE_SCANCODE && (kbled & (1<<USB_LED_COMPOSE))) || | |
339 | #endif //COMPOSE | |
340 | #if USB_LED_KANA_SCANCODE != 255 | |
341 | (led_map[i].scan == USB_LED_KANA_SCANCODE && (kbled & (1<<USB_LED_KANA))) || | |
342 | #endif //KANA | |
343 | (0)) | |
30680c6e | 344 | { |
763b26cd DP |
345 | led_buffer[i].r = 255 - led_buffer[i].r; |
346 | led_buffer[i].g = 255 - led_buffer[i].g; | |
347 | led_buffer[i].b = 255 - led_buffer[i].b; | |
30680c6e | 348 | } |
349 | } | |
30680c6e | 350 | } |
30680c6e | 351 | |
763b26cd | 352 | } |
30680c6e | 353 | |
763b26cd DP |
354 | const rgb_matrix_driver_t rgb_matrix_driver = { |
355 | .init = init, | |
356 | .flush = flush, | |
357 | .set_color = led_set_one, | |
358 | .set_color_all = led_set_all | |
359 | }; | |
360 | ||
361 | /*============================================================================== | |
362 | = Legacy Lighting Support = | |
363 | ==============================================================================*/ | |
364 | ||
365 | #ifdef USE_MASSDROP_CONFIGURATOR | |
366 | // Ported from Massdrop QMK Github Repo | |
367 | ||
368 | // TODO?: wire these up to keymap.c | |
369 | uint8_t led_animation_orientation = 0; | |
370 | uint8_t led_animation_direction = 0; | |
371 | uint8_t led_animation_breathing = 0; | |
372 | uint8_t led_animation_id = 0; | |
373 | float led_animation_speed = 4.0f; | |
374 | uint8_t led_lighting_mode = LED_MODE_NORMAL; | |
375 | uint8_t led_enabled = 1; | |
376 | uint8_t led_animation_breathe_cur = BREATHE_MIN_STEP; | |
377 | uint8_t breathe_dir = 1; | |
378 | ||
379 | static void led_run_pattern(led_setup_t *f, float* ro, float* go, float* bo, float pos) { | |
380 | float po; | |
30680c6e | 381 | |
763b26cd DP |
382 | while (f->end != 1) |
383 | { | |
384 | po = pos; //Reset po for new frame | |
30680c6e | 385 | |
763b26cd DP |
386 | //Add in any moving effects |
387 | if ((!led_animation_direction && f->ef & EF_SCR_R) || (led_animation_direction && (f->ef & EF_SCR_L))) | |
388 | { | |
389 | po -= pomod; | |
30680c6e | 390 | |
763b26cd DP |
391 | if (po > 100) po -= 100; |
392 | else if (po < 0) po += 100; | |
393 | } | |
394 | else if ((!led_animation_direction && f->ef & EF_SCR_L) || (led_animation_direction && (f->ef & EF_SCR_R))) | |
395 | { | |
396 | po += pomod; | |
30680c6e | 397 | |
763b26cd DP |
398 | if (po > 100) po -= 100; |
399 | else if (po < 0) po += 100; | |
400 | } | |
30680c6e | 401 | |
763b26cd DP |
402 | //Check if LED's po is in current frame |
403 | if (po < f->hs) { f++; continue; } | |
404 | if (po > f->he) { f++; continue; } | |
405 | //note: < 0 or > 100 continue | |
30680c6e | 406 | |
763b26cd DP |
407 | //Calculate the po within the start-stop percentage for color blending |
408 | po = (po - f->hs) / (f->he - f->hs); | |
30680c6e | 409 | |
763b26cd DP |
410 | //Add in any color effects |
411 | if (f->ef & EF_OVER) | |
412 | { | |
413 | *ro = (po * (f->re - f->rs)) + f->rs;// + 0.5; | |
414 | *go = (po * (f->ge - f->gs)) + f->gs;// + 0.5; | |
415 | *bo = (po * (f->be - f->bs)) + f->bs;// + 0.5; | |
416 | } | |
417 | else if (f->ef & EF_SUBTRACT) | |
418 | { | |
419 | *ro -= (po * (f->re - f->rs)) + f->rs;// + 0.5; | |
420 | *go -= (po * (f->ge - f->gs)) + f->gs;// + 0.5; | |
421 | *bo -= (po * (f->be - f->bs)) + f->bs;// + 0.5; | |
422 | } | |
423 | else | |
424 | { | |
425 | *ro += (po * (f->re - f->rs)) + f->rs;// + 0.5; | |
426 | *go += (po * (f->ge - f->gs)) + f->gs;// + 0.5; | |
427 | *bo += (po * (f->be - f->bs)) + f->bs;// + 0.5; | |
428 | } | |
63e212c0 | 429 | |
763b26cd DP |
430 | f++; |
431 | } | |
63e212c0 SD |
432 | } |
433 | ||
763b26cd | 434 | static void led_matrix_massdrop_config_override(int i) |
30680c6e | 435 | { |
763b26cd DP |
436 | float ro = 0; |
437 | float go = 0; | |
438 | float bo = 0; | |
439 | ||
440 | float po = (led_animation_orientation) | |
441 | ? (float)g_rgb_leds[i].point.y / 64.f * 100 | |
442 | : (float)g_rgb_leds[i].point.x / 224.f * 100; | |
443 | ||
444 | uint8_t highest_active_layer = biton32(layer_state); | |
445 | ||
a7113c8e | 446 | if (led_lighting_mode == LED_MODE_KEYS_ONLY && HAS_FLAGS(g_rgb_leds[i].flags, LED_FLAG_UNDERGLOW)) { |
763b26cd | 447 | //Do not act on this LED |
a7113c8e | 448 | } else if (led_lighting_mode == LED_MODE_NON_KEYS_ONLY && !HAS_FLAGS(g_rgb_leds[i].flags, LED_FLAG_UNDERGLOW)) { |
763b26cd DP |
449 | //Do not act on this LED |
450 | } else if (led_lighting_mode == LED_MODE_INDICATORS_ONLY) { | |
451 | //Do not act on this LED (Only show indicators) | |
452 | } else { | |
453 | led_instruction_t* led_cur_instruction = led_instructions; | |
454 | while (!led_cur_instruction->end) { | |
455 | // Check if this applies to current layer | |
456 | if ((led_cur_instruction->flags & LED_FLAG_MATCH_LAYER) && | |
457 | (led_cur_instruction->layer != highest_active_layer)) { | |
458 | goto next_iter; | |
459 | } | |
30680c6e | 460 | |
763b26cd DP |
461 | // Check if this applies to current index |
462 | if (led_cur_instruction->flags & LED_FLAG_MATCH_ID) { | |
463 | uint8_t modid = i / 32; //Calculate which id# contains the led bit | |
464 | uint32_t modidbit = 1 << (i % 32); //Calculate the bit within the id# | |
465 | uint32_t *bitfield = &led_cur_instruction->id0 + modid; //Add modid as offset to id0 address. *bitfield is now idX of the led id | |
466 | if (~(*bitfield) & modidbit) { //Check if led bit is not set in idX | |
467 | goto next_iter; | |
468 | } | |
469 | } | |
30680c6e | 470 | |
763b26cd DP |
471 | if (led_cur_instruction->flags & LED_FLAG_USE_RGB) { |
472 | ro = led_cur_instruction->r; | |
473 | go = led_cur_instruction->g; | |
474 | bo = led_cur_instruction->b; | |
475 | } else if (led_cur_instruction->flags & LED_FLAG_USE_PATTERN) { | |
476 | led_run_pattern(led_setups[led_cur_instruction->pattern_id], &ro, &go, &bo, po); | |
477 | } else if (led_cur_instruction->flags & LED_FLAG_USE_ROTATE_PATTERN) { | |
478 | led_run_pattern(led_setups[led_animation_id], &ro, &go, &bo, po); | |
30680c6e | 479 | } |
480 | ||
763b26cd DP |
481 | next_iter: |
482 | led_cur_instruction++; | |
483 | } | |
30680c6e | 484 | |
763b26cd DP |
485 | if (ro > 255) ro = 255; else if (ro < 0) ro = 0; |
486 | if (go > 255) go = 255; else if (go < 0) go = 0; | |
487 | if (bo > 255) bo = 255; else if (bo < 0) bo = 0; | |
30680c6e | 488 | |
763b26cd DP |
489 | if (led_animation_breathing) |
490 | { | |
491 | ro *= breathe_mult; | |
492 | go *= breathe_mult; | |
493 | bo *= breathe_mult; | |
30680c6e | 494 | } |
495 | } | |
496 | ||
763b26cd DP |
497 | led_buffer[i].r = (uint8_t)ro; |
498 | led_buffer[i].g = (uint8_t)go; | |
499 | led_buffer[i].b = (uint8_t)bo; | |
30680c6e | 500 | } |
501 | ||
763b26cd | 502 | #endif // USE_MASSDROP_CONFIGURATOR |