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