]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboards/zeal60/rgb_backlight.c
Added macros to Dynamic Keymaps, Zeal60 RGB backlight improvements (#4520)
[qmk_firmware.git] / keyboards / zeal60 / rgb_backlight.c
1 /* Copyright 2017 Jason Williams (Wilba)
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  */
16 #if RGB_BACKLIGHT_ENABLED
17
18 #if defined (RGB_BACKLIGHT_ZEAL60) || defined (RGB_BACKLIGHT_ZEAL65) || defined (RGB_BACKLIGHT_M60_A) || defined(RGB_BACKLIGHT_M6_B) || defined(RGB_BACKLIGHT_KOYU)
19 #else
20 #error None of the following was defined: RGB_BACKLIGHT_ZEAL60, RGB_BACKLIGHT_ZEAL65, RGB_BACKLIGHT_M60_A, RGB_BACKLIGHT_M6_B, RGB_BACKLIGHT_KOYU
21 #endif
22
23 #include "quantum.h"
24 #include "rgb_backlight.h"
25 #include "rgb_backlight_api.h"
26 #include "rgb_backlight_keycodes.h"
27
28 #include <avr/io.h>
29 #include <util/delay.h>
30 #include <avr/interrupt.h>
31 #include "progmem.h"
32
33 #include "quantum/color.h"
34 #include "drivers/avr/i2c_master.h"
35
36 #if defined (RGB_BACKLIGHT_M6_B)
37 #include "drivers/issi/is31fl3218.h"
38 #define BACKLIGHT_LED_COUNT 6
39 #else
40 #include "drivers/issi/is31fl3731.h"
41 #define BACKLIGHT_LED_COUNT 72
42 #endif
43
44 #define BACKLIGHT_EFFECT_MAX 10
45
46 backlight_config g_config = {
47         .use_split_backspace = RGB_BACKLIGHT_USE_SPLIT_BACKSPACE,
48         .use_split_left_shift = RGB_BACKLIGHT_USE_SPLIT_LEFT_SHIFT,
49         .use_split_right_shift = RGB_BACKLIGHT_USE_SPLIT_RIGHT_SHIFT,
50         .use_7u_spacebar = RGB_BACKLIGHT_USE_7U_SPACEBAR,
51         .use_iso_enter = RGB_BACKLIGHT_USE_ISO_ENTER,
52         .disable_hhkb_blocker_leds = RGB_BACKLIGHT_DISABLE_HHKB_BLOCKER_LEDS,
53         .disable_when_usb_suspended = RGB_BACKLIGHT_DISABLE_WHEN_USB_SUSPENDED,
54         .disable_after_timeout = RGB_BACKLIGHT_DISABLE_AFTER_TIMEOUT,
55         .brightness = 255,
56         .effect = RGB_BACKLIGHT_EFFECT,
57         .effect_speed = 0,
58         .color_1 = { .h = 0, .s = 255 },
59         .color_2 = { .h = 127, .s = 255 },
60         .caps_lock_indicator = { .color = { .h = 0, .s = 0 }, .index = 255 },
61         .layer_1_indicator = { .color = { .h = 0, .s = 0 }, .index = 255 },
62         .layer_2_indicator = { .color = { .h = 0, .s = 0 }, .index = 255 },
63         .layer_3_indicator = { .color = { .h = 0, .s = 0 }, .index = 255 },
64         .alphas_mods = {
65                 RGB_BACKLIGHT_ALPHAS_MODS_ROW_0,
66                 RGB_BACKLIGHT_ALPHAS_MODS_ROW_1,
67                 RGB_BACKLIGHT_ALPHAS_MODS_ROW_2,
68                 RGB_BACKLIGHT_ALPHAS_MODS_ROW_3,
69                 RGB_BACKLIGHT_ALPHAS_MODS_ROW_4 },
70 #if defined(RGB_BACKLIGHT_M6_B)
71         .custom_color = { { 0, 255 }, { 43, 255 }, { 85, 255 }, { 128, 255 }, { 171, 255 }, { 213, 255 } }
72 #endif
73 };
74
75 bool g_suspend_state = false;
76 uint8_t g_indicator_state = 0;
77
78 // Global tick at 20 Hz
79 uint32_t g_tick = 0;
80
81 // Ticks since this key was last hit.
82 uint8_t g_key_hit[BACKLIGHT_LED_COUNT];
83
84 // Ticks since any key was last hit.
85 uint32_t g_any_key_hit = 0;
86
87 #if !defined(RGB_BACKLIGHT_M6_B)
88 // This is a 7-bit address, that gets left-shifted and bit 0
89 // set to 0 for write, 1 for read (as per I2C protocol)
90 #define ISSI_ADDR_1 0x74
91 #define ISSI_ADDR_2 0x76
92
93 const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
94 /* Refer to IS31 manual for these locations
95  *   driver
96  *   |  R location
97  *   |  |      G location
98  *   |  |      |      B location
99  *   |  |      |      | */
100         {0, C2_1,  C3_1,  C4_1},  // LA0
101         {0, C1_1,  C3_2, C4_2},   // LA1
102         {0, C1_2,  C2_2, C4_3},   // LA2
103         {0, C1_3,  C2_3, C3_3},   // LA3
104         {0, C1_4,  C2_4, C3_4},   // LA4
105         {0, C1_5,  C2_5, C3_5},   // LA5
106         {0, C1_6,  C2_6, C3_6},   // LA6
107         {0, C1_7,  C2_7, C3_7},   // LA7
108         {0, C1_8,  C2_8, C3_8},   // LA8
109         {0, C9_1,  C8_1,  C7_1},  // LA9
110         {0, C9_2,  C8_2, C7_2},   // LA10
111         {0, C9_3,  C8_3, C7_3},   // LA11
112         {0, C9_4,  C8_4, C7_4},   // LA12
113         {0, C9_5,  C8_5, C7_5},   // LA13
114         {0, C9_6,  C8_6, C7_6},   // LA14
115         {0, C9_7,  C8_7, C6_6},   // LA15
116         {0, C9_8,  C7_7, C6_7},   // LA16
117         {0, C8_8,  C7_8, C6_8},   // LA17
118
119         {0, C2_9,  C3_9,  C4_9},  // LB0
120         {0, C1_9,  C3_10, C4_10}, // LB1
121         {0, C1_10, C2_10, C4_11}, // LB2
122         {0, C1_11, C2_11, C3_11}, // LB3
123         {0, C1_12, C2_12, C3_12}, // LB4
124         {0, C1_13, C2_13, C3_13}, // LB5
125         {0, C1_14, C2_14, C3_14}, // LB6
126         {0, C1_15, C2_15, C3_15}, // LB7
127         {0, C1_16, C2_16, C3_16}, // LB8
128         {0, C9_9,  C8_9,  C7_9},  // LB9
129         {0, C9_10, C8_10, C7_10}, // LB10
130         {0, C9_11, C8_11, C7_11}, // LB11
131         {0, C9_12, C8_12, C7_12}, // LB12
132         {0, C9_13, C8_13, C7_13}, // LB13
133         {0, C9_14, C8_14, C7_14}, // LB14
134         {0, C9_15, C8_15, C6_14}, // LB15
135         {0, C9_16, C7_15, C6_15}, // LB16
136         {0, C8_16, C7_16, C6_16}, // LB17
137
138         {1, C2_1,  C3_1,  C4_1},  // LC0
139         {1, C1_1,  C3_2, C4_2},   // LC1
140         {1, C1_2,  C2_2, C4_3},   // LC2
141         {1, C1_3,  C2_3, C3_3},   // LC3
142         {1, C1_4,  C2_4, C3_4},   // LC4
143         {1, C1_5,  C2_5, C3_5},   // LC5
144         {1, C1_6,  C2_6, C3_6},   // LC6
145         {1, C1_7,  C2_7, C3_7},   // LC7
146         {1, C1_8,  C2_8, C3_8},   // LC8
147         {1, C9_1,  C8_1,  C7_1},  // LC9
148         {1, C9_2,  C8_2, C7_2},   // LC10
149         {1, C9_3,  C8_3, C7_3},   // LC11
150         {1, C9_4,  C8_4, C7_4},   // LC12
151         {1, C9_5,  C8_5, C7_5},   // LC13
152         {1, C9_6,  C8_6, C7_6},   // LC14
153         {1, C9_7,  C8_7, C6_6},   // LC15
154         {1, C9_8,  C7_7, C6_7},   // LC16
155         {1, C8_8,  C7_8, C6_8},   // LC17
156
157         {1, C2_9,  C3_9,  C4_9},  // LD0
158         {1, C1_9,  C3_10, C4_10}, // LD1
159         {1, C1_10, C2_10, C4_11}, // LD2
160         {1, C1_11, C2_11, C3_11}, // LD3
161         {1, C1_12, C2_12, C3_12}, // LD4
162         {1, C1_13, C2_13, C3_13}, // LD5
163         {1, C1_14, C2_14, C3_14}, // LD6
164         {1, C1_15, C2_15, C3_15}, // LD7
165         {1, C1_16, C2_16, C3_16}, // LD8
166         {1, C9_9,  C8_9,  C7_9},  // LD9
167         {1, C9_10, C8_10, C7_10}, // LD10
168         {1, C9_11, C8_11, C7_11}, // LD11
169         {1, C9_12, C8_12, C7_12}, // LD12
170         {1, C9_13, C8_13, C7_13}, // LD13
171         {1, C9_14, C8_14, C7_14}, // LD14
172         {1, C9_15, C8_15, C6_14}, // LD15
173         {1, C9_16, C7_15, C6_15}, // LD16
174         {1, C8_16, C7_16, C6_16}, // LD17
175 };
176 #endif // !defined(RGB_BACKLIGHT_M6_B)
177
178
179 typedef struct Point {
180         uint8_t x;
181         uint8_t y;
182 } Point;
183
184
185 // index in range 0..71 (LA0..LA17, LB0..LB17, LC0..LC17, LD0..LD17)
186 // point values in range x=0..224 y=0..64
187 // origin is center of top-left key (i.e Esc)
188 #if defined (RGB_BACKLIGHT_ZEAL65)
189 const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
190         // LA0..LA17
191         {120,16}, {104,16}, {88,16}, {72,16}, {56,16}, {40,16}, {24,16}, {4,16}, {4,32},
192         {128,0}, {112,0}, {96,0}, {80,0}, {64,0}, {48,0}, {32,0}, {16,0}, {0,0},
193         // LB0..LB17
194         {144,0}, {160,0}, {176,0}, {192,0}, {216,0}, {224,0}, {240,0}, {240,16}, {240,32},
195         {136,16}, {152,16}, {168,16}, {184,16}, {200,16}, {220,16}, {240,48}, {240,64}, {224,64},
196         // LC0..LC17
197         {96,64}, {100,48}, {84,48}, {68,48}, {52,48}, {36,48}, {255,255}, {48,60}, {28,64},
198         {108,32}, {92,32}, {76,32}, {60,32}, {44,32}, {28,32}, {20,44}, {10,48}, {4,64},
199         // LD0..LD17
200         {124,32}, {140,32}, {156,32}, {172,32}, {188,32}, {214,32}, {180,48}, {202,48}, {224,48},
201         {116,48}, {132,48}, {148,48}, {164,48}, {255,255}, {144,60}, {164,64}, {188,64}, {208,64}
202 };
203 const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
204         // LA0..LA17
205         {64,128}, {75,132}, {84,145}, {91,164}, {97,187}, {102,213}, {105,242}, {109,255}, {128,243},
206         {61,255}, {67,255}, {72,255}, {77,255}, {82,255}, {86,255}, {90,255}, {93,255}, {96,255},
207         // LB0..LB17
208         {56,255}, {51,255}, {46,255}, {42,255}, {37,255}, {35,255}, {32,255}, {19,255}, {0,255},
209         {53,132}, {44,145}, {37,164}, {31,187}, {26,213}, {22,249}, {237,255}, {224,255}, {221,255},
210         // LC0..LC17
211         {184,255}, {179,135}, {170,149}, {163,169}, {157,193}, {153,220}, {255,255}, {167,255}, {165,255},
212         {128,26}, {128,60}, {128,94}, {128,128}, {128,162}, {128,196}, {145,233}, {148,255}, {161,255},
213         // LD0..LD17
214         {0,9}, {0,43}, {0,77}, {0,111}, {0,145}, {0,201}, {224,181}, {230,217}, {235,255},
215         {189,128}, {200,131}, {210,141}, {218,159}, {255,255}, {201,228}, {206,255}, {213,255}, {218,255}
216 };
217 #elif defined (RGB_BACKLIGHT_KOYU)
218 const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
219         // LA0..LA17
220         {120,16}, {104,16}, {88,16}, {72,16}, {56,16}, {40,16}, {24,16}, {4,16}, {4,32},
221         {128,0}, {112,0}, {96,0}, {80,0}, {64,0}, {48,0}, {32,0}, {16,0}, {0,0},
222         // LB0..LB17
223         {144,0}, {160,0}, {176,0}, {192,0}, {208,0}, {224,0}, {240,0}, {240,16}, {240,32},
224         {136,16}, {152,16}, {168,16}, {184,16}, {200,16}, {220,16}, {240,48}, {240,64}, {224,64},
225         // LC0..LC17
226         {112,64}, {100,48}, {84,48}, {68,48}, {52,48}, {36,48}, {64,60}, {44,60}, {24,64},
227         {108,32}, {92,32}, {76,32}, {60,32}, {44,32}, {28,32}, {255,255}, {10,48}, {4,64},
228         // LD0..LD17
229         {124,32}, {140,32}, {156,32}, {172,32}, {188,32}, {214,32}, {180,48}, {202,48}, {224,48},
230         {116,48}, {132,48}, {148,48}, {164,48}, {255,255}, {160,60}, {180,64}, {208,64}, {255,255}
231 };
232 const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
233         // LA0..LA17
234         {64,128}, {75,132}, {84,145}, {91,164}, {97,187}, {102,213}, {105,242}, {109,255}, {128,243},
235         {61,255}, {67,255}, {72,255}, {77,255}, {82,255}, {86,255}, {90,255}, {93,255}, {96,255},
236         // LB0..LB17
237         {56,255}, {51,255}, {46,255}, {42,255}, {38,255}, {35,255}, {32,255}, {19,255}, {0,255},
238         {53,132}, {44,145}, {37,164}, {31,187}, {26,213}, {22,249}, {237,255}, {224,255}, {221,255},
239         // LC0..LC17
240         {189,255}, {179,135}, {170,149}, {163,169}, {157,193}, {153,220}, {172,252}, {169,255}, {165,255},
241         {128,26}, {128,60}, {128,94}, {128,128}, {128,162}, {128,196}, {255,255}, {148,255}, {161,255},
242         // LD0..LD17
243         {0,9}, {0,43}, {0,77}, {0,111}, {0,145}, {0,201}, {224,181}, {230,217}, {235,255},
244         {189,128}, {200,131}, {210,141}, {218,159}, {255,255}, {207,238}, {211,255}, {218,255}, {255,255}
245 };
246 #elif defined (RGB_BACKLIGHT_ZEAL60) || defined (RGB_BACKLIGHT_M60_A)
247 const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
248         // LA0..LA17
249         {120,16}, {104,16}, {88,16}, {72,16}, {56,16}, {40,16}, {24,16}, {4,16}, {4,32},
250         {128,0}, {112,0}, {96,0}, {80,0}, {64,0}, {48,0}, {32,0}, {16,0}, {0,0},
251         // LB0..LB17
252         {144,0}, {160,0}, {176,0}, {192,0}, {216,0}, {224,0}, {255,255}, {255,255}, {255,255},
253         {136,16}, {152,16}, {168,16}, {184,16}, {200,16}, {220,16}, {255,255}, {255,255}, {255,255},
254         // LC0..LC17
255         {102,64}, {100,48}, {84,48}, {68,48}, {52,48}, {36,48}, {60,64}, {43,64}, {23,64},
256         {108,32}, {92,32}, {76,32}, {60,32}, {44,32}, {28,32}, {20,48}, {2,48}, {3,64},
257         // LD0..LD17
258         {124,32}, {140,32}, {156,32}, {172,32}, {188,32}, {214,32}, {180,48}, {210,48}, {224,48},
259         {116,48}, {132,48}, {148,48}, {164,48}, {144,64}, {161,64}, {181,64}, {201,64}, {221,64}
260 };
261 const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
262         // LA0..LA17
263         {58,129}, {70,129}, {80,139}, {89,157}, {96,181}, {101,208}, {105,238}, {109,255}, {128,247}, {58,255},
264         {64,255}, {70,255}, {75,255}, {80,255}, {85,255}, {89,255}, {93,255}, {96,255},
265         // LB0..LB17
266         {53,255}, {48,255}, {43,255}, {39,255}, {34,255}, {32,255}, {255,255}, {255,255}, {255,255},
267         {48,139}, {39,157}, {32,181}, {27,208}, {23,238}, {19,255}, {255,255}, {255,255}, {255,255},
268         // LC0..LC17
269         {188,255}, {183,131}, {173,143}, {165,163}, {159,188}, {154,216}, {172,252}, {170,255}, {165,255},
270         {128,9}, {128,46}, {128,82}, {128,119}, {128,155}, {128,192}, {150,244}, {147,255}, {161,255},
271         // LD0..LD17
272         {0,27}, {0,64}, {0,101}, {0,137}, {0,174}, {255,233}, {228,201}, {235,255}, {237,255},
273         {195,128}, {206,136}, {215,152}, {222,175}, {205,234}, {209,255}, {214,255}, {219,255}, {223,255}
274 };
275 #elif defined (RGB_BACKLIGHT_M6_B)
276 // M6-B is really simple:
277 // 0 3 5
278 // 1 2 4
279 const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
280         {0,0}, {0,16}, {16,16}, {16,0}, {32,16}, {32,0}
281 };
282 const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
283         {160,255}, {96,255}, {77,255}, {179,255}, {51,255}, {205,255}
284 };
285 #endif
286
287 // This may seem counter-intuitive, but it's quite flexible.
288 // For each LED, get it's position to decide what color to make it.
289 // This solves the issue of LEDs (and switches) not aligning to a grid,
290 // or having a large "bitmap" and sampling them.
291 void map_led_to_point( uint8_t index, Point *point )
292 {
293         // Slightly messy way to get Point structs out of progmem.
294         uint8_t *addr = (uint8_t*)&g_map_led_to_point[index];
295         point->x = pgm_read_byte(addr);
296         point->y = pgm_read_byte(addr+1);
297
298 #if defined (RGB_BACKLIGHT_M6_B)
299         return;
300 #endif
301
302         switch (index)
303         {
304                 case 18+4: // LB4A
305                         if ( g_config.use_split_backspace )
306                                 point->x -= 8;
307                         break;
308 #if defined (RGB_BACKLIGHT_ZEAL60)
309                 case 18+14: // LB14A
310                         if ( g_config.use_iso_enter )
311                                 point->y += 8; // extremely pedantic
312                         break;
313                 case 54+5: // LD5A
314                         if ( !g_config.use_iso_enter )
315                                 point->x -= 10;
316                         break;
317                 case 36+16: // LC16A
318                         if ( !g_config.use_split_left_shift )
319                                 point->x += 8;
320                         break;
321 #endif
322 #if defined (RGB_BACKLIGHT_ZEAL60) || defined (RGB_BACKLIGHT_M60_A)
323                 case 36+0: // LC0A
324                         if ( g_config.use_7u_spacebar )
325                                 point->x += 10;
326                         break;
327                 case 36+6: // LC6A
328                         if ( g_config.use_7u_spacebar )
329                                 point->x += 4;
330                         break;
331                 case 54+7: // LD7A
332                         if ( !g_config.use_split_right_shift )
333                                 point->x -= 8;
334                         break;
335 #endif
336         }
337 }
338
339 void map_led_to_point_polar( uint8_t index, Point *point )
340 {
341         // Slightly messy way to get Point structs out of progmem.
342         uint8_t *addr = (uint8_t*)&g_map_led_to_point_polar[index];
343         point->x = pgm_read_byte(addr);
344         point->y = pgm_read_byte(addr+1);
345 }
346
347 //
348 // Maps switch matrix coordinate (row,col) to LED index
349 //
350
351
352 #if defined (RGB_BACKLIGHT_ZEAL65)
353 // Note: Left spacebar stab is at 4,2 (LC7)
354 // Right spacebar stab is at 4,9 (D14)
355 //
356 // A17, A16, A15, A14, A13, A12, A11, A10,  A9,  B0,  B1,  B2,  B3,  B4,  B6
357 //  A7,  A6,  A5,  A4,  A3,  A2,  A1,  A0,  B9, B10, B11, B12, B13, B14,  B7
358 //  A8, C14, C13, C12, C11, C10,  C9,  D0,  D1,  D2,  D3,  D4,  D5,  B5,  B8
359 // C16, C15,  C5,  C4,  C3,  C2,  C1,  D9, D10, D11, D12,  D6,  D7,  D8, B15
360 // C17,  C8,  C7, ---, ---, ---, ---,  C0, ---, D14, D15, D16, D17, B17, B16
361 const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
362         {  0+17,  0+16,  0+15,  0+14,  0+13,  0+12,  0+11,  0+10,   0+9,  18+0,  18+1,  18+2,  18+3,  18+4,  18+6 },
363         {   0+7,   0+6,   0+5,   0+4,   0+3,   0+2,   0+1,   0+0,  18+9, 18+10, 18+11, 18+12, 18+13, 18+14,  18+7 },
364         {   0+8, 36+14, 36+13, 36+12, 36+11, 36+10,  36+9,  54+0,  54+1,  54+2,  54+3,  54+4,  54+5,  18+5,  18+8 },
365         { 36+16, 36+15,  36+5,  36+4,  36+3,  36+2,  36+1,  54+9, 54+10, 54+11, 54+12,  54+6,  54+7,  54+8, 18+15 },
366         { 36+17,  36+8,  36+7,   255,   255,   255,   255,  36+0,  255,  54+14, 54+15, 54+16, 54+17, 18+17, 18+16 }
367 };
368 #elif defined(RGB_BACKLIGHT_KOYU)
369 // Note: Left spacebar stab is at 4,4 (LC6)
370 // Right spacebar stab is at 4,10 (D14)
371 //
372 // A17, A16, A15, A14, A13, A12, A11, A10,  A9,  B0,  B1,  B2,  B3,  B4,  B6
373 //  A7,  A6,  A5,  A4,  A3,  A2,  A1,  A0,  B9, B10, B11, B12, B13, B14,  B7
374 //  A8, C14, C13, C12, C11, C10,  C9,  D0,  D1,  D2,  D3,  D4,  D5,  B5,  B8
375 // C16, C15,  C5,  C4,  C3,  C2,  C1,  D9, D10, D11, D12,  D6,  D7,  D8, B15
376 // C17,  C8,  C7,  C6, ---, ---, ---,  C0, ---, ---, D14, D15, D16, B17, B16
377 const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
378         {  0+17,  0+16,  0+15,  0+14,  0+13,  0+12,  0+11,  0+10,   0+9,  18+0,  18+1,  18+2,  18+3,  18+4,  18+6 },
379         {   0+7,   0+6,   0+5,   0+4,   0+3,   0+2,   0+1,   0+0,  18+9, 18+10, 18+11, 18+12, 18+13, 18+14,  18+7 },
380         {   0+8, 36+14, 36+13, 36+12, 36+11, 36+10,  36+9,  54+0,  54+1,  54+2,  54+3,  54+4,  54+5,  18+5,  18+8 },
381         { 36+16, 36+15,  36+5,  36+4,  36+3,  36+2,  36+1,  54+9, 54+10, 54+11, 54+12,  54+6,  54+7,  54+8, 18+15 },
382         { 36+17,  36+8,  36+7,  36+6,   255,   255,   255,  36+0,  255,    255, 54+14, 54+15, 54+16, 18+17, 18+16 }
383 };
384 #elif defined (RGB_BACKLIGHT_ZEAL60) || defined (RGB_BACKLIGHT_M60_A)
385 // Note: Left spacebar stab is at 4,3 (LC6)
386 // Right spacebar stab is at 4,9 (LD13) or 4,10 (LD14)
387 //
388 // A17, A16, A15, A14, A13, A12, A11, A10,  A9,  B0,  B1,  B2,  B3,  B4,
389 //  A7,  A6,  A5,  A4,  A3,  A2,  A1,  A0,  B9, B10, B11, B12, B13, B14,
390 //  A8, C14, C13, C12, C11, C10,  C9,  D0,  D1,  D2,  D3,  D4,  D5,  B5,
391 // C16, C15,  C5,  C4,  C3,  C2,  C1,  D9, D10, D11, D12,  D6,  D7,  D8,
392 // C17,  C8,  C7,  C6, ---, ---, ---,  C0, ---, D13, D14, D15, D16, D17,
393 const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
394         {  0+17,  0+16,  0+15,  0+14,  0+13,  0+12,  0+11,  0+10,   0+9,  18+0,  18+1,  18+2,  18+3,  18+4 },
395         {   0+7,   0+6,   0+5,   0+4,   0+3,   0+2,   0+1,   0+0,  18+9, 18+10, 18+11, 18+12, 18+13, 18+14 },
396         {   0+8, 36+14, 36+13, 36+12, 36+11, 36+10,  36+9,  54+0,  54+1,  54+2,  54+3,  54+4,  54+5,  18+5 },
397         { 36+16, 36+15,  36+5,  36+4,  36+3,  36+2,  36+1,  54+9, 54+10, 54+11, 54+12,  54+6,  54+7,  54+8 },
398         { 36+17,  36+8,  36+7,  36+6,   255,   255,   255,  36+0,  255,  54+13, 54+14, 54+15, 54+16, 54+17 }
399 };
400 #elif defined (RGB_BACKLIGHT_M6_B)
401 // M6-B is really simple:
402 // 0 3 5
403 // 1 2 4
404 const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
405         {     0,     3,     5,     1,     2,     4 }
406 };
407 #endif
408
409 void map_row_column_to_led( uint8_t row, uint8_t column, uint8_t *led )
410 {
411         *led = 255;
412         if ( row < MATRIX_ROWS && column < MATRIX_COLS )
413         {
414                 *led = pgm_read_byte(&g_map_row_column_to_led[row][column]);
415         }
416 }
417
418 void backlight_update_pwm_buffers(void)
419 {
420 #if defined (RGB_BACKLIGHT_M6_B)
421         IS31FL3218_update_pwm_buffers();
422 #else
423         IS31FL3731_update_pwm_buffers( ISSI_ADDR_1, ISSI_ADDR_2 );
424         IS31FL3731_update_led_control_registers( ISSI_ADDR_1, ISSI_ADDR_2 );
425 #endif
426 }
427
428 void backlight_set_color( int index, uint8_t red, uint8_t green, uint8_t blue )
429 {
430 #if defined (RGB_BACKLIGHT_M6_B)
431         IS31FL3218_set_color( index, red, green, blue );
432 #else
433         IS31FL3731_set_color( index, red, green, blue );
434 #endif
435 }
436
437 void backlight_set_color_all( uint8_t red, uint8_t green, uint8_t blue )
438 {
439 #if defined (RGB_BACKLIGHT_M6_B)
440         IS31FL3218_set_color_all( red, green, blue );
441 #else
442         IS31FL3731_set_color_all( red, green, blue );
443 #endif
444 }
445
446 void backlight_set_key_hit(uint8_t row, uint8_t column)
447 {
448         uint8_t led;
449         map_row_column_to_led(row,column,&led);
450         g_key_hit[led] = 0;
451
452         g_any_key_hit = 0;
453 }
454
455 // This is (F_CPU/1024) / 20 Hz
456 // = 15625 Hz / 20 Hz
457 // = 781
458 #define TIMER3_TOP 781
459
460 void backlight_timer_init(void)
461 {
462         static uint8_t backlight_timer_is_init = 0;
463         if ( backlight_timer_is_init )
464         {
465                 return;
466         }
467         backlight_timer_is_init = 1;
468
469         // Timer 3 setup
470         TCCR3B = _BV(WGM32) |                   // CTC mode OCR3A as TOP
471                          _BV(CS32) | _BV(CS30); // prescale by /1024
472         // Set TOP value
473         uint8_t sreg = SREG;
474         cli();
475
476         OCR3AH = (TIMER3_TOP >> 8) & 0xff;
477         OCR3AL = TIMER3_TOP & 0xff;
478         SREG = sreg;
479 }
480
481 void backlight_timer_enable(void)
482 {
483         TIMSK3 |= _BV(OCIE3A);
484 }
485
486 void backlight_timer_disable(void)
487 {
488         TIMSK3 &= ~_BV(OCIE3A);
489 }
490
491 void backlight_set_suspend_state(bool state)
492 {
493         g_suspend_state = state;
494 }
495
496 void backlight_set_indicator_state(uint8_t state)
497 {
498         g_indicator_state = state;
499 }
500
501 void backlight_effect_rgb_test(void)
502 {
503         // Mask out bits 4 and 5
504         // This 2-bit value will stay the same for 16 ticks.
505         switch ( (g_tick & 0x30) >> 4 )
506         {
507                 case 0:
508                 {
509                         backlight_set_color_all( 255, 0, 0 );
510                         break;
511                 }
512                 case 1:
513                 {
514                         backlight_set_color_all( 0, 255, 0 );
515                         break;
516                 }
517                 case 2:
518                 {
519                         backlight_set_color_all( 0, 0, 255 );
520                         break;
521                 }
522                 case 3:
523                 {
524                         backlight_set_color_all( 255, 255, 255 );
525                         break;
526                 }
527         }
528 }
529
530 #if defined(RGB_DEBUGGING_ONLY)
531 // This tests the LEDs
532 // Note that it will change the LED control registers
533 // in the LED drivers, and leave them in an invalid
534 // state for other backlight effects.
535 // ONLY USE THIS FOR TESTING LEDS!
536 void backlight_effect_single_LED_test(void)
537 {
538         static uint8_t color = 0; // 0,1,2 for R,G,B
539         static uint8_t row = 0;
540         static uint8_t column = 0;
541
542         static uint8_t tick = 0;
543         tick++;
544
545         if ( tick > 2 )
546         {
547                 tick = 0;
548                 column++;
549         }
550         if ( column > 14 )
551         {
552                 column = 0;
553                 row++;
554         }
555         if ( row > 4 )
556         {
557                 row = 0;
558                 color++;
559         }
560         if ( color > 2 )
561         {
562                 color = 0;
563         }
564
565         uint8_t led;
566         map_row_column_to_led( row, column, &led );
567         backlight_set_color_all( 255, 255, 255 );
568         backlight_test_led( led, color==0, color==1, color==2 );
569 }
570 #endif // defined(RGB_DEBUGGING_ONLY)
571
572 // All LEDs off
573 void backlight_effect_all_off(void)
574 {
575         backlight_set_color_all( 0, 0, 0 );
576 }
577
578 // Solid color
579 void backlight_effect_solid_color(void)
580 {
581         HSV hsv = { .h = g_config.color_1.h, .s = g_config.color_1.s, .v = g_config.brightness };
582         RGB rgb = hsv_to_rgb( hsv );
583         backlight_set_color_all( rgb.r, rgb.g, rgb.b );
584 }
585
586 // alphas = color1, mods = color2
587 void backlight_effect_alphas_mods(void)
588 {
589         RGB rgb1 = hsv_to_rgb( (HSV){ .h = g_config.color_1.h, .s = g_config.color_1.s, .v = g_config.brightness } );
590         RGB rgb2 = hsv_to_rgb( (HSV){ .h = g_config.color_2.h, .s = g_config.color_2.s, .v = g_config.brightness } );
591
592         for ( int row = 0; row < MATRIX_ROWS; row++ )
593         {
594                 for ( int column = 0; column < MATRIX_COLS; column++ )
595                 {
596                         uint8_t index;
597                         map_row_column_to_led( row, column, &index );
598                         if ( index < BACKLIGHT_LED_COUNT )
599                         {
600                                 if ( ( g_config.alphas_mods[row] & (1<<column) ) == 0 )
601                                 {
602                                         backlight_set_color( index, rgb1.r, rgb1.g, rgb1.b );
603                                 }
604                                 else
605                                 {
606                                         backlight_set_color( index, rgb2.r, rgb2.g, rgb2.b );
607                                 }
608                         }
609                 }
610         }
611 }
612
613 void backlight_effect_gradient_up_down(void)
614 {
615         int16_t h1 = g_config.color_1.h;
616         int16_t h2 = g_config.color_2.h;
617         int16_t deltaH = h2 - h1;
618
619         // Take the shortest path between hues
620         if ( deltaH > 127 )
621         {
622                 deltaH -= 256;
623         }
624         else if ( deltaH < -127 )
625         {
626                 deltaH += 256;
627         }
628         // Divide delta by 4, this gives the delta per row
629         deltaH /= 4;
630
631         int16_t s1 = g_config.color_1.s;
632         int16_t s2 = g_config.color_2.s;
633         int16_t deltaS = ( s2 - s1 ) / 4;
634
635         HSV hsv = { .h = 0, .s = 255, .v = g_config.brightness };
636         RGB rgb;
637         Point point;
638         for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
639         {
640                 map_led_to_point( i, &point );
641                 // The y range will be 0..64, map this to 0..4
642                 uint8_t y = (point.y>>4);
643                 // Relies on hue being 8-bit and wrapping
644                 hsv.h = g_config.color_1.h + ( deltaH * y );
645                 hsv.s = g_config.color_1.s + ( deltaS * y );
646                 rgb = hsv_to_rgb( hsv );
647                 backlight_set_color( i, rgb.r, rgb.g, rgb.b );
648         }
649 }
650
651 void backlight_effect_raindrops(bool initialize)
652 {
653         int16_t h1 = g_config.color_1.h;
654         int16_t h2 = g_config.color_2.h;
655         int16_t deltaH = h2 - h1;
656         deltaH /= 4;
657
658         // Take the shortest path between hues
659         if ( deltaH > 127 )
660         {
661                 deltaH -= 256;
662         }
663         else if ( deltaH < -127 )
664         {
665                 deltaH += 256;
666         }
667
668         int16_t s1 = g_config.color_1.s;
669         int16_t s2 = g_config.color_2.s;
670         int16_t deltaS = ( s2 - s1 ) / 4;
671
672         HSV hsv;
673         RGB rgb;
674
675         // Change one LED every tick
676         uint8_t led_to_change = ( g_tick & 0x000 ) == 0 ? rand() % BACKLIGHT_LED_COUNT : 255;
677
678         for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
679         {
680                 // If initialize, all get set to random colors
681                 // If not, all but one will stay the same as before.
682                 if ( initialize || i == led_to_change )
683                 {
684                         hsv.h = h1 + ( deltaH * ( rand() & 0x03 ) );
685                         hsv.s = s1 + ( deltaS * ( rand() & 0x03 ) );
686                         // Override brightness with global brightness control
687                         hsv.v = g_config.brightness;;
688
689                         rgb = hsv_to_rgb( hsv );
690                         backlight_set_color( i, rgb.r, rgb.g, rgb.b );
691                 }
692         }
693 }
694
695 void backlight_effect_cycle_all(void)
696 {
697         uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;
698
699         // Relies on hue being 8-bit and wrapping
700         for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
701         {
702                 uint16_t offset2 = g_key_hit[i]<<2;
703                 // stabilizer LEDs use spacebar hits
704                 if ( i == 36+6 || i == 54+13 || // LC6, LD13
705                                 ( g_config.use_7u_spacebar && i == 54+14 ) ) // LD14
706                 {
707                         offset2 = g_key_hit[36+0]<<2;
708                 }
709                 offset2 = (offset2<=63) ? (63-offset2) : 0;
710
711                 HSV hsv = { .h = offset+offset2, .s = 255, .v = g_config.brightness };
712                 RGB rgb = hsv_to_rgb( hsv );
713                 backlight_set_color( i, rgb.r, rgb.g, rgb.b );
714         }
715 }
716
717 void backlight_effect_cycle_left_right(void)
718 {
719         uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;
720         HSV hsv = { .h = 0, .s = 255, .v = g_config.brightness };
721         RGB rgb;
722         Point point;
723         for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
724         {
725                 uint16_t offset2 = g_key_hit[i]<<2;
726                 // stabilizer LEDs use spacebar hits
727                 if ( i == 36+6 || i == 54+13 || // LC6, LD13
728                                 ( g_config.use_7u_spacebar && i == 54+14 ) ) // LD14
729                 {
730                         offset2 = g_key_hit[36+0]<<2;
731                 }
732                 offset2 = (offset2<=63) ? (63-offset2) : 0;
733
734                 map_led_to_point( i, &point );
735                 // Relies on hue being 8-bit and wrapping
736                 hsv.h = point.x + offset + offset2;
737                 rgb = hsv_to_rgb( hsv );
738                 backlight_set_color( i, rgb.r, rgb.g, rgb.b );
739         }
740 }
741
742 void backlight_effect_cycle_up_down(void)
743 {
744         uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;
745         HSV hsv = { .h = 0, .s = 255, .v = g_config.brightness };
746         RGB rgb;
747         Point point;
748         for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
749         {
750                 uint16_t offset2 = g_key_hit[i]<<2;
751                 // stabilizer LEDs use spacebar hits
752                 if ( i == 36+6 || i == 54+13 || // LC6, LD13
753                                 ( g_config.use_7u_spacebar && i == 54+14 ) ) // LD14
754                 {
755                         offset2 = g_key_hit[36+0]<<2;
756                 }
757                 offset2 = (offset2<=63) ? (63-offset2) : 0;
758
759                 map_led_to_point( i, &point );
760                 // Relies on hue being 8-bit and wrapping
761                 hsv.h = point.y + offset + offset2;
762                 rgb = hsv_to_rgb( hsv );
763                 backlight_set_color( i, rgb.r, rgb.g, rgb.b );
764         }
765 }
766
767 void backlight_effect_jellybean_raindrops( bool initialize )
768 {
769         HSV hsv;
770         RGB rgb;
771
772         // Change one LED every tick
773         uint8_t led_to_change = ( g_tick & 0x000 ) == 0 ? rand() % BACKLIGHT_LED_COUNT : 255;
774
775         for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
776         {
777                 // If initialize, all get set to random colors
778                 // If not, all but one will stay the same as before.
779                 if ( initialize || i == led_to_change )
780                 {
781                         hsv.h = rand() & 0xFF;
782                         hsv.s = rand() & 0xFF;
783                         // Override brightness with global brightness control
784                         hsv.v = g_config.brightness;;
785
786                         rgb = hsv_to_rgb( hsv );
787                         backlight_set_color( i, rgb.r, rgb.g, rgb.b );
788                 }
789         }
790 }
791
792 void backlight_effect_cycle_radial1(void)
793 {
794         uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;
795         HSV hsv = { .h = 0, .s = 255, .v = g_config.brightness };
796         RGB rgb;
797         Point point;
798         for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
799         {
800                 map_led_to_point_polar( i, &point );
801                 // Relies on hue being 8-bit and wrapping
802                 hsv.h = point.x + offset;
803                 hsv.s = point.y;
804                 rgb = hsv_to_rgb( hsv );
805                 backlight_set_color( i, rgb.r, rgb.g, rgb.b );
806         }
807 }
808
809 void backlight_effect_cycle_radial2(void)
810 {
811         uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;
812
813         HSV hsv = { .h = 0, .s = g_config.color_1.s, .v = g_config.brightness };
814         RGB rgb;
815         Point point;
816         for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
817         {
818                 map_led_to_point_polar( i, &point );
819                 uint8_t offset2 = offset + point.x;
820                 if ( offset2 & 0x80 )
821                 {
822                         offset2 = ~offset2;
823                 }
824                 offset2 = offset2 >> 2;
825                 hsv.h = g_config.color_1.h + offset2;
826                 hsv.s = 127 + ( point.y >> 1 );
827                 rgb = hsv_to_rgb( hsv );
828                 backlight_set_color( i, rgb.r, rgb.g, rgb.b );
829         }
830 }
831
832 #if defined(RGB_BACKLIGHT_M6_B)
833 void backlight_effect_custom_colors(void)
834 {
835         RGB rgb;
836         for ( uint8_t i = 0; i < 6; i++ )
837         {
838                 HSV hsv = { .h = g_config.custom_color[i].h, .s = g_config.custom_color[i].s, .v = g_config.brightness };
839                 rgb = hsv_to_rgb( hsv );
840                 uint8_t led;
841                 map_row_column_to_led( 0, i, &led );
842                 backlight_set_color( led, rgb.r, rgb.g, rgb.b );
843         }
844 }
845 #endif
846
847 void backlight_effect_indicators_set_colors( uint8_t index, HS color )
848 {
849         HSV hsv = { .h = color.h, .s = color.s, .v = g_config.brightness };
850         RGB rgb = hsv_to_rgb( hsv );
851         if ( index == 254 )
852         {
853                 backlight_set_color_all( rgb.r, rgb.g, rgb.b );
854         }
855         else
856         {
857                 backlight_set_color( index, rgb.r, rgb.g, rgb.b );
858
859                 // If the spacebar LED is the indicator,
860                 // do the same for the spacebar stabilizers
861                 if ( index == 36+0 ) // LC0
862                 {
863 #if defined (RGB_BACKLIGHT_ZEAL65)
864                         backlight_set_color( 36+7, rgb.r, rgb.g, rgb.b ); // LC7
865                         backlight_set_color( 54+14, rgb.r, rgb.g, rgb.b ); // LD14
866 #elif defined (RGB_BACKLIGHT_KOYU)
867                         backlight_set_color( 36+6, rgb.r, rgb.g, rgb.b ); // LC6
868                         backlight_set_color( 54+14, rgb.r, rgb.g, rgb.b ); // LD14
869 #elif defined (RGB_BACKLIGHT_ZEAL60) || defined (RGB_BACKLIGHT_M60_A)
870                         backlight_set_color( 36+6, rgb.r, rgb.g, rgb.b ); // LC6
871                         backlight_set_color( 54+13, rgb.r, rgb.g, rgb.b ); // LD13
872                         if ( g_config.use_7u_spacebar )
873                         {
874                                 backlight_set_color( 54+14, rgb.r, rgb.g, rgb.b ); // LD14
875                         }
876 #endif
877                 }
878         }
879 }
880
881 // This runs after another backlight effect and replaces
882 // colors already set
883 void backlight_effect_indicators(void)
884 {
885         if ( g_config.caps_lock_indicator.index != 255 &&
886                         ( g_indicator_state & (1<<USB_LED_CAPS_LOCK) ) )
887         {
888                 backlight_effect_indicators_set_colors( g_config.caps_lock_indicator.index, g_config.caps_lock_indicator.color );
889         }
890
891         // This if/else if structure allows higher layers to
892         // override lower ones. If we set layer 3's indicator
893         // to none, then it will NOT show layer 2 or layer 1
894         // indicators, even if those layers are on via the
895         // MO13/MO23 Fn combo magic.
896         //
897         // Basically we want to handle the case where layer 3 is
898         // still the backlight configuration layer and we don't
899         // want "all LEDs" indicators hiding the backlight effect,
900         // but still allow end users to do whatever they want.
901         if ( IS_LAYER_ON(3) )
902         {
903                 if ( g_config.layer_3_indicator.index != 255 )
904                 {
905                         backlight_effect_indicators_set_colors( g_config.layer_3_indicator.index, g_config.layer_3_indicator.color );
906                 }
907         }
908         else if ( IS_LAYER_ON(2) )
909         {
910                 if ( g_config.layer_2_indicator.index != 255 )
911                 {
912                         backlight_effect_indicators_set_colors( g_config.layer_2_indicator.index, g_config.layer_2_indicator.color );
913                 }
914         }
915         else if ( IS_LAYER_ON(1) )
916         {
917                 if ( g_config.layer_1_indicator.index != 255 )
918                 {
919                         backlight_effect_indicators_set_colors( g_config.layer_1_indicator.index, g_config.layer_1_indicator.color );
920                 }
921         }
922 }
923
924 ISR(TIMER3_COMPA_vect)
925 {
926         // delay 1 second before driving LEDs or doing anything else
927         static uint8_t startup_tick = 0;
928         if ( startup_tick < 20 )
929         {
930                 startup_tick++;
931                 return;
932         }
933
934         g_tick++;
935
936         if ( g_any_key_hit < 0xFFFFFFFF )
937         {
938                 g_any_key_hit++;
939         }
940
941         for ( int led = 0; led < BACKLIGHT_LED_COUNT; led++ )
942         {
943                 if ( g_key_hit[led] < 255 )
944                 {
945                         g_key_hit[led]++;
946                 }
947         }
948
949         // Factory default magic value
950         if ( g_config.effect == 255 )
951         {
952                 backlight_effect_rgb_test();
953                 return;
954         }
955
956         // Ideally we would also stop sending zeros to the LED driver PWM buffers
957         // while suspended and just do a software shutdown. This is a cheap hack for now.
958         bool suspend_backlight = ((g_suspend_state && g_config.disable_when_usb_suspended) ||
959                         (g_config.disable_after_timeout > 0 && g_any_key_hit > g_config.disable_after_timeout * 60 * 20));
960         uint8_t effect = suspend_backlight ? 0 : g_config.effect;
961
962         // Keep track of the effect used last time,
963         // detect change in effect, so each effect can
964         // have an optional initialization.
965         static uint8_t effect_last = 255;
966         bool initialize = effect != effect_last;
967         effect_last = effect;
968
969         // this gets ticked at 20 Hz.
970         // each effect can opt to do calculations
971         // and/or request PWM buffer updates.
972         switch ( effect )
973         {
974                 case 0:
975                         backlight_effect_all_off();
976                         break;
977                 case 1:
978                         backlight_effect_solid_color();
979                         break;
980                 case 2:
981 #if defined(RGB_BACKLIGHT_M6_B)
982                         backlight_effect_custom_colors();
983 #else
984                         backlight_effect_alphas_mods();
985 #endif
986                         break;
987                 case 3:
988                         backlight_effect_gradient_up_down();
989                         break;
990                 case 4:
991                         backlight_effect_raindrops( initialize );
992                         break;
993                 case 5:
994                         backlight_effect_cycle_all();
995                         break;
996                 case 6:
997                         backlight_effect_cycle_left_right();
998                         break;
999                 case 7:
1000                         backlight_effect_cycle_up_down();
1001                         break;
1002                 case 8:
1003                         backlight_effect_jellybean_raindrops( initialize );
1004                         break;
1005                 case 9:
1006                         backlight_effect_cycle_radial1();
1007                         break;
1008                 case 10:
1009                         backlight_effect_cycle_radial2();
1010                         break;
1011                 default:
1012                         backlight_effect_all_off();
1013                         break;
1014         }
1015
1016         if ( ! suspend_backlight )
1017         {
1018 #if !defined(RGB_BACKLIGHT_M6_B)
1019                 backlight_effect_indicators();
1020 #endif
1021         }
1022 }
1023
1024 void backlight_set_indicator_index( uint8_t *index, uint8_t row, uint8_t column )
1025 {
1026         if ( row >= MATRIX_ROWS )
1027         {
1028                 // Special value, 255=none, 254=all
1029                 *index = row;
1030         }
1031         else
1032         {
1033                 map_row_column_to_led( row, column, index );
1034         }
1035 }
1036
1037 void backlight_get_indicator_row_col( uint8_t index, uint8_t *row, uint8_t *column )
1038 {
1039         if ( index == 255 || index == 254 )
1040         {
1041                 // Special value, 255=none, 254=all
1042                 *row = index;
1043                 *column = 0;
1044                 return;
1045         }
1046         for ( uint8_t r = 0; r < MATRIX_ROWS; r++ )
1047         {
1048                 for ( uint8_t c = 0; c < MATRIX_COLS; c++ )
1049                 {
1050                         uint8_t i = 255;
1051                         map_row_column_to_led( r, c, &i );
1052                         if ( i == index )
1053                         {
1054                                 *row = r;
1055                                 *column = c;
1056                                 return;
1057                         }
1058                 }
1059         }
1060 }
1061
1062 // Some helpers for setting/getting HSV
1063 void _set_color( HS *color, uint8_t *data )
1064 {
1065         color->h = data[0];
1066         color->s = data[1];
1067 }
1068
1069 void _get_color( HS *color, uint8_t *data )
1070 {
1071         data[0] = color->h;
1072         data[1] = color->s;
1073 }
1074
1075 void backlight_config_set_value( uint8_t *data )
1076 {
1077         bool reinitialize = false;
1078         uint8_t *value_id = &(data[0]);
1079         uint8_t *value_data = &(data[1]);
1080         switch ( *value_id )
1081         {
1082 #if defined (RGB_BACKLIGHT_ZEAL60) || defined(RGB_BACKLIGHT_ZEAL65)
1083                 case id_use_split_backspace:
1084                 {
1085                         g_config.use_split_backspace = (bool)*value_data;
1086                         reinitialize = true;
1087                         break;
1088                 }
1089 #endif
1090 #if defined (RGB_BACKLIGHT_ZEAL60)
1091                 case id_use_split_left_shift:
1092                 {
1093                         g_config.use_split_left_shift = (bool)*value_data;
1094                         reinitialize = true;
1095                         break;
1096                 }
1097                 case id_use_split_right_shift:
1098                 {
1099                         g_config.use_split_right_shift = (bool)*value_data;
1100                         reinitialize = true;
1101                         break;
1102                 }
1103                 case id_use_7u_spacebar:
1104                 {
1105                         g_config.use_7u_spacebar = (bool)*value_data;
1106                         reinitialize = true;
1107                         break;
1108                 }
1109                 case id_use_iso_enter:
1110                 {
1111                         g_config.use_iso_enter = (bool)*value_data;
1112                         reinitialize = true;
1113                         break;
1114                 }
1115                 case id_disable_hhkb_blocker_leds:
1116                 {
1117                         g_config.disable_hhkb_blocker_leds = (bool)*value_data;
1118                         reinitialize = true;
1119                         break;
1120                 }
1121 #endif
1122                 case id_disable_when_usb_suspended:
1123                 {
1124                         g_config.disable_when_usb_suspended = (bool)*value_data;
1125                         break;
1126                 }
1127                 case id_disable_after_timeout:
1128                 {
1129                         g_config.disable_after_timeout = *value_data;
1130                         break;
1131                 }
1132                 case id_brightness:
1133                 {
1134                         g_config.brightness = *value_data;
1135                         break;
1136                 }
1137                 case id_effect:
1138                 {
1139                         g_config.effect = *value_data;
1140                         break;
1141                 }
1142                 case id_effect_speed:
1143                 {
1144                         g_config.effect_speed = *value_data;
1145                         break;
1146                 }
1147                 case id_color_1:
1148                 {
1149                         _set_color( &(g_config.color_1), value_data );
1150                         break;
1151                 }
1152                 case id_color_2:
1153                 {
1154                         _set_color( &(g_config.color_2), value_data );
1155                         break;
1156                 }
1157                 case id_caps_lock_indicator_color:
1158                 {
1159                         _set_color( &(g_config.caps_lock_indicator.color), value_data );
1160                         break;
1161                 }
1162                 case id_caps_lock_indicator_row_col:
1163                 {
1164                         backlight_set_indicator_index( &(g_config.caps_lock_indicator.index), value_data[0], value_data[1] );
1165                         break;
1166                 }
1167                 case id_layer_1_indicator_color:
1168                 {
1169                         _set_color( &(g_config.layer_1_indicator.color), value_data );
1170                         break;
1171                 }
1172                 case id_layer_1_indicator_row_col:
1173                 {
1174                         backlight_set_indicator_index( &(g_config.layer_1_indicator.index), value_data[0], value_data[1] );
1175                         break;
1176                 }
1177                 case id_layer_2_indicator_color:
1178                 {
1179                         _set_color( &(g_config.layer_2_indicator.color), value_data );
1180                         break;
1181                 }
1182                 case id_layer_2_indicator_row_col:
1183                 {
1184                         backlight_set_indicator_index( &(g_config.layer_2_indicator.index), value_data[0], value_data[1] );
1185                         break;
1186                 }
1187                 case id_layer_3_indicator_color:
1188                 {
1189                         _set_color( &(g_config.layer_3_indicator.color), value_data );
1190                         break;
1191                 }
1192                 case id_layer_3_indicator_row_col:
1193                 {
1194                         backlight_set_indicator_index( &(g_config.layer_3_indicator.index), value_data[0], value_data[1] );
1195                         break;
1196                 }
1197                 case id_alphas_mods:
1198                 {
1199                         for ( int i=0; i<5; i++ )
1200                         {
1201                                 g_config.alphas_mods[i] = ( *(value_data+i*2) << 8 ) | ( *(value_data+i*2+1) );
1202                         }
1203                 }
1204 #if defined(RGB_BACKLIGHT_M6_B)
1205                 case id_custom_color:
1206                 {
1207                         uint8_t index = value_data[0];
1208                         if ( index >= 0 && index <= 6 )
1209                         {
1210                                 _set_color( &(g_config.custom_color[index]), &(value_data[1]) );
1211                         }
1212                 }
1213 #endif
1214         }
1215
1216         if ( reinitialize )
1217         {
1218                 backlight_init_drivers();
1219         }
1220 }
1221
1222 void backlight_config_get_value( uint8_t *data )
1223 {
1224         uint8_t *value_id = &(data[0]);
1225         uint8_t *value_data = &(data[1]);
1226         switch ( *value_id )
1227         {
1228                 case id_use_split_backspace:
1229                 {
1230                         *value_data = ( g_config.use_split_backspace ? 1 : 0 );
1231                         break;
1232                 }
1233                 case id_use_split_left_shift:
1234                 {
1235                         *value_data = ( g_config.use_split_left_shift ? 1 : 0 );
1236                         break;
1237                 }
1238                 case id_use_split_right_shift:
1239                 {
1240                         *value_data = ( g_config.use_split_right_shift ? 1 : 0 );
1241                         break;
1242                 }
1243                 case id_use_7u_spacebar:
1244                 {
1245                         *value_data = ( g_config.use_7u_spacebar ? 1 : 0 );
1246                         break;
1247                 }
1248                 case id_use_iso_enter:
1249                 {
1250                         *value_data = ( g_config.use_iso_enter ? 1 : 0 );
1251                         break;
1252                 }
1253                 case id_disable_when_usb_suspended:
1254                 {
1255                         *value_data = ( g_config.disable_when_usb_suspended ? 1 : 0 );
1256                         break;
1257                 }
1258                 case id_disable_hhkb_blocker_leds:
1259                 {
1260                         *value_data = ( g_config.disable_hhkb_blocker_leds ? 1 : 0 );
1261                         break;
1262                 }
1263                 case id_disable_after_timeout:
1264                 {
1265                         *value_data = g_config.disable_after_timeout;
1266                         break;
1267                 }
1268                 case id_brightness:
1269                 {
1270                         *value_data = g_config.brightness;
1271                         break;
1272                 }
1273                 case id_effect:
1274                 {
1275                         *value_data = g_config.effect;
1276                         break;
1277                 }
1278                 case id_effect_speed:
1279                 {
1280                         *value_data = g_config.effect_speed;
1281                         break;
1282                 }
1283                 case id_color_1:
1284                 {
1285                         _get_color( &(g_config.color_1), value_data );
1286                         break;
1287                 }
1288                 case id_color_2:
1289                 {
1290                         _get_color( &(g_config.color_2), value_data );
1291                         break;
1292                 }
1293                 case id_caps_lock_indicator_color:
1294                 {
1295                         _get_color( &(g_config.caps_lock_indicator.color), value_data );
1296                         break;
1297                 }
1298                 case id_caps_lock_indicator_row_col:
1299                 {
1300                         backlight_get_indicator_row_col( g_config.caps_lock_indicator.index, &(value_data[0]), &(value_data[1]) );
1301                         break;
1302                 }
1303                 case id_layer_1_indicator_color:
1304                 {
1305                         _get_color( &(g_config.layer_1_indicator.color), value_data );
1306                         break;
1307                 }
1308                 case id_layer_1_indicator_row_col:
1309                 {
1310                         backlight_get_indicator_row_col( g_config.layer_1_indicator.index, &(value_data[0]), &(value_data[1]) );
1311                         break;
1312                 }
1313                 case id_layer_2_indicator_color:
1314                 {
1315                         _get_color( &(g_config.layer_2_indicator.color), value_data );
1316                         break;
1317                 }
1318                 case id_layer_2_indicator_row_col:
1319                 {
1320                         backlight_get_indicator_row_col( g_config.layer_2_indicator.index, &(value_data[0]), &(value_data[1]) );
1321                         break;
1322                 }
1323                 case id_layer_3_indicator_color:
1324                 {
1325                         _get_color( &(g_config.layer_3_indicator.color), value_data );
1326                         break;
1327                 }
1328                 case id_layer_3_indicator_row_col:
1329                 {
1330                         backlight_get_indicator_row_col( g_config.layer_3_indicator.index, &(value_data[0]), &(value_data[1]) );
1331                         break;
1332                 }
1333                 case id_alphas_mods:
1334                 {
1335                         for ( int i=0; i<5; i++ )
1336                         {
1337                                 *(value_data+i*2) = g_config.alphas_mods[i] >> 8;
1338                                 *(value_data+i*2+1)     = g_config.alphas_mods[i] & 0xFF;
1339                         }
1340                 }
1341 #if defined(RGB_BACKLIGHT_M6_B)
1342                 case id_custom_color:
1343                 {
1344                         uint8_t index = value_data[0];
1345                         if ( index >= 0 && index <= 6 )
1346                         {
1347                                 _get_color( &(g_config.custom_color[index]), &(value_data[1]) );
1348                         }
1349                 }
1350 #endif
1351         }
1352 }
1353
1354 void backlight_config_set_alphas_mods( uint16_t *alphas_mods )
1355 {
1356         for ( int i=0; i<5; i++ )
1357         {
1358                 g_config.alphas_mods[i] = alphas_mods[i];
1359         }
1360
1361         backlight_config_save();
1362 }
1363
1364 void backlight_config_load(void)
1365 {
1366         eeprom_read_block( &g_config, ((void*)RGB_BACKLIGHT_CONFIG_EEPROM_ADDR), sizeof(backlight_config) );
1367 }
1368
1369 void backlight_config_save(void)
1370 {
1371         eeprom_update_block( &g_config, ((void*)RGB_BACKLIGHT_CONFIG_EEPROM_ADDR), sizeof(backlight_config) );
1372 }
1373
1374 void backlight_init_drivers(void)
1375 {
1376         // Initialize I2C
1377         i2c_init();
1378
1379 #if defined(RGB_BACKLIGHT_M6_B)
1380         IS31FL3218_init();
1381 #else
1382         IS31FL3731_init( ISSI_ADDR_1 );
1383         IS31FL3731_init( ISSI_ADDR_2 );
1384
1385         for ( int index = 0; index < BACKLIGHT_LED_COUNT; index++ )
1386         {
1387                 // OR the possible "disabled" cases together, then NOT the result to get the enabled state
1388                 // LC6 LD13 not present on Zeal65
1389 #if defined (RGB_BACKLIGHT_ZEAL65)
1390                 bool enabled = !( ( index == 18+5 && !g_config.use_split_backspace ) || // LB5
1391                                                   ( index == 36+6 ) || // LC6
1392                                                   ( index == 54+13 ) ); // LD13
1393 #elif defined (RGB_BACKLIGHT_KOYU)
1394                 bool enabled = !( ( index == 36+15 ) || // LC15
1395                                                   ( index == 54+13 ) || // LD13
1396                                                   ( index == 54+17 ) ); // LD17
1397 #elif defined (RGB_BACKLIGHT_M60_A)
1398                 bool enabled = !(
1399                 // LB6 LB7 LB8 LB15 LB16 LB17 not present on M60-A
1400                                                   ( index == 18+6 ) || // LB6
1401                                                   ( index == 18+7 ) || // LB7
1402                                                   ( index == 18+8 ) || // LB8
1403                                                   ( index == 18+15 ) || // LB15
1404                                                   ( index == 18+16 ) || // LB16
1405                                                   ( index == 18+17 ) || // LB17
1406                 // HHKB blockers (LC17, LD17) and ISO extra keys (LC15,LD13) not present on M60-A
1407                                                   ( index == 36+17 ) || // LC17
1408                                                   ( index == 54+17 ) || // LD17
1409                                                   ( index == 36+15 ) || // LC15
1410                                                   ( index == 54+13 ) ); // LD13
1411 #elif defined (RGB_BACKLIGHT_ZEAL60)
1412                 // LB6 LB7 LB8 LB15 LB16 LB17 not present on Zeal60
1413                 bool enabled = !( ( index == 18+5 && !g_config.use_split_backspace ) || // LB5
1414                                                   ( index == 36+15 && !g_config.use_split_left_shift ) || // LC15
1415                                                   ( index == 54+8 && !g_config.use_split_right_shift ) || // LD8
1416                                                   ( index == 54+13 && g_config.use_7u_spacebar ) || // LD13
1417                                                   ( index == 36+17 && g_config.disable_hhkb_blocker_leds ) || // LC17
1418                                                   ( index == 54+17 && g_config.disable_hhkb_blocker_leds ) ||  // LD17
1419                                                   ( index == 18+6 ) || // LB6
1420                                                   ( index == 18+7 ) || // LB7
1421                                                   ( index == 18+8 ) || // LB8
1422                                                   ( index == 18+15 ) || // LB15
1423                                                   ( index == 18+16 ) || // LB16
1424                                                   ( index == 18+17 ) ); // LB17
1425 #endif
1426                 // This only caches it for later
1427                 IS31FL3731_set_led_control_register( index, enabled, enabled, enabled );
1428         }
1429         // This actually updates the LED drivers
1430         IS31FL3731_update_led_control_registers( ISSI_ADDR_1, ISSI_ADDR_2 );
1431 #endif // !defined(RGB_BACKLIGHT_M6_B)
1432
1433         // TODO: put the 1 second startup delay here?
1434
1435         // clear the key hits
1436         for ( int led=0; led<BACKLIGHT_LED_COUNT; led++ )
1437         {
1438                 g_key_hit[led] = 255;
1439         }
1440 }
1441
1442 bool process_record_backlight(uint16_t keycode, keyrecord_t *record)
1443 {
1444         // Record keypresses for backlight effects
1445         if ( record->event.pressed )
1446         {
1447                 backlight_set_key_hit( record->event.key.row, record->event.key.col );
1448         }
1449
1450         switch(keycode)
1451         {
1452                 case BR_INC:
1453                         if (record->event.pressed)
1454                         {
1455                                 backlight_brightness_increase();
1456                         }
1457                         return false;
1458                         break;
1459                 case BR_DEC:
1460                         if (record->event.pressed)
1461                         {
1462                                 backlight_brightness_decrease();
1463                         }
1464                         return false;
1465                         break;
1466                 case EF_INC:
1467                         if (record->event.pressed)
1468                         {
1469                                 backlight_effect_increase();
1470                         }
1471                         return false;
1472                         break;
1473                 case EF_DEC:
1474                         if (record->event.pressed)
1475                         {
1476                                 backlight_effect_decrease();
1477                         }
1478                         return false;
1479                         break;
1480                 case ES_INC:
1481                         if (record->event.pressed)
1482                         {
1483                                 backlight_effect_speed_increase();
1484                         }
1485                         return false;
1486                         break;
1487                 case ES_DEC:
1488                         if (record->event.pressed)
1489                         {
1490                                 backlight_effect_speed_decrease();
1491                         }
1492                         return false;
1493                         break;
1494                 case H1_INC:
1495                         if (record->event.pressed)
1496                         {
1497                                 backlight_color_1_hue_increase();
1498                         }
1499                         return false;
1500                         break;
1501                 case H1_DEC:
1502                         if (record->event.pressed)
1503                         {
1504                                 backlight_color_1_hue_decrease();
1505                         }
1506                         return false;
1507                         break;
1508                 case S1_INC:
1509                         if (record->event.pressed)
1510                         {
1511                                 backlight_color_1_sat_increase();
1512                         }
1513                         return false;
1514                         break;
1515                 case S1_DEC:
1516                         if (record->event.pressed)
1517                         {
1518                                 backlight_color_1_sat_decrease();
1519                                 break;
1520                         }
1521                         return false;
1522                         break;
1523                 case H2_INC:
1524                         if (record->event.pressed)
1525                         {
1526                                 backlight_color_2_hue_increase();
1527                         }
1528                         return false;
1529                         break;
1530                 case H2_DEC:
1531                         if (record->event.pressed)
1532                         {
1533                                 backlight_color_2_hue_decrease();
1534                         }
1535                         return false;
1536                         break;
1537                 case S2_INC:
1538                         if (record->event.pressed)
1539                         {
1540                                 backlight_color_2_sat_increase();
1541                         }
1542                         return false;
1543                         break;
1544                 case S2_DEC:
1545                         if (record->event.pressed)
1546                         {
1547                                 backlight_color_2_sat_decrease();
1548                                 break;
1549                         }
1550                         return false;
1551                         break;
1552         }
1553
1554         return true;
1555 }
1556
1557 // Deals with the messy details of incrementing an integer
1558 uint8_t increment( uint8_t value, uint8_t step, uint8_t min, uint8_t max )
1559 {
1560         int16_t new_value = value;
1561         new_value += step;
1562         return MIN( MAX( new_value, min ), max );
1563 }
1564
1565 uint8_t decrement( uint8_t value, uint8_t step, uint8_t min, uint8_t max )
1566 {
1567         int16_t new_value = value;
1568         new_value -= step;
1569         return MIN( MAX( new_value, min ), max );
1570 }
1571
1572 void backlight_effect_increase(void)
1573 {
1574         g_config.effect = increment( g_config.effect, 1, 0, BACKLIGHT_EFFECT_MAX );
1575         backlight_config_save();
1576 }
1577
1578 void backlight_effect_decrease(void)
1579 {
1580         g_config.effect = decrement( g_config.effect, 1, 0, BACKLIGHT_EFFECT_MAX );
1581         backlight_config_save();
1582 }
1583
1584 void backlight_effect_speed_increase(void)
1585 {
1586         g_config.effect_speed = increment( g_config.effect_speed, 1, 0, 3 );
1587         backlight_config_save();
1588 }
1589
1590 void backlight_effect_speed_decrease(void)
1591 {
1592         g_config.effect_speed = decrement( g_config.effect_speed, 1, 0, 3 );
1593         backlight_config_save();
1594 }
1595
1596 void backlight_brightness_increase(void)
1597 {
1598         g_config.brightness = increment( g_config.brightness, 8, 0, 255 );
1599         backlight_config_save();
1600 }
1601
1602 void backlight_brightness_decrease(void)
1603 {
1604         g_config.brightness = decrement( g_config.brightness, 8, 0, 255 );
1605         backlight_config_save();
1606 }
1607
1608 void backlight_color_1_hue_increase(void)
1609 {
1610         g_config.color_1.h = increment( g_config.color_1.h, 8, 0, 255 );
1611         backlight_config_save();
1612 }
1613
1614 void backlight_color_1_hue_decrease(void)
1615 {
1616         g_config.color_1.h = decrement( g_config.color_1.h, 8, 0, 255 );
1617         backlight_config_save();
1618 }
1619
1620 void backlight_color_1_sat_increase(void)
1621 {
1622         g_config.color_1.s = increment( g_config.color_1.s, 8, 0, 255 );
1623         backlight_config_save();
1624 }
1625
1626 void backlight_color_1_sat_decrease(void)
1627 {
1628         g_config.color_1.s = decrement( g_config.color_1.s, 8, 0, 255 );
1629         backlight_config_save();
1630 }
1631
1632 void backlight_color_2_hue_increase(void)
1633 {
1634         g_config.color_2.h = increment( g_config.color_2.h, 8, 0, 255 );
1635         backlight_config_save();
1636 }
1637
1638 void backlight_color_2_hue_decrease(void)
1639 {
1640         g_config.color_2.h = decrement( g_config.color_2.h, 8, 0, 255 );
1641         backlight_config_save();
1642 }
1643
1644 void backlight_color_2_sat_increase(void)
1645 {
1646         g_config.color_2.s = increment( g_config.color_2.s, 8, 0, 255 );
1647         backlight_config_save();
1648 }
1649
1650 void backlight_color_2_sat_decrease(void)
1651 {
1652         g_config.color_2.s = decrement( g_config.color_2.s, 8, 0, 255 );
1653         backlight_config_save();
1654 }
1655
1656 #if defined(RGB_DEBUGGING_ONLY)
1657 void backlight_test_led( uint8_t index, bool red, bool green, bool blue )
1658 {
1659         for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
1660         {
1661                 if ( i == index )
1662                 {
1663                         IS31FL3731_set_led_control_register( i, red, green, blue );
1664                 }
1665                 else
1666                 {
1667                         IS31FL3731_set_led_control_register( i, false, false, false );
1668                 }
1669         }
1670 }
1671 #endif // defined(RGB_DEBUGGING_ONLY)
1672
1673 void backlight_debug_led( bool state )
1674 {
1675         if (state)
1676         {
1677                 // Output high.
1678                 DDRE |= (1<<6);
1679                 PORTE |= (1<<6);
1680         }
1681         else
1682         {
1683                 // Output low.
1684                 DDRE &= ~(1<<6);
1685                 PORTE &= ~(1<<6);
1686         }
1687 }
1688
1689 #endif // BACKLIGHT_ENABLED