aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValen Cheung <xvalen214x@gmail.com>2020-07-26 07:45:35 +0800
committerGitHub <noreply@github.com>2020-07-26 09:45:35 +1000
commit12946d056566b2e7915350c52d07540d0e1c973f (patch)
tree25c08735aadc3ebf2074df93dd9f63c4e4158b6a
parent95c742ec276c7ebf2cd996cc3889d3e2d0a2874e (diff)
downloadqmk_firmware-12946d056566b2e7915350c52d07540d0e1c973f.tar.gz
qmk_firmware-12946d056566b2e7915350c52d07540d0e1c973f.zip
Keymap update - massdrop/ctrl/responsive_pattern (#8730)
* rewrite keyboards/massdrop/ctrl/keymaps/responsive_pattern/keymap.c in respopnse to the last update (#5328) * remove print.h * changed default parameters, modified readme
-rw-r--r--keyboards/massdrop/ctrl/keymaps/responsive_pattern/README.md20
-rw-r--r--keyboards/massdrop/ctrl/keymaps/responsive_pattern/keymap.c1085
2 files changed, 474 insertions, 631 deletions
diff --git a/keyboards/massdrop/ctrl/keymaps/responsive_pattern/README.md b/keyboards/massdrop/ctrl/keymaps/responsive_pattern/README.md
index 5ee630dfb..60c2d1f91 100644
--- a/keyboards/massdrop/ctrl/keymaps/responsive_pattern/README.md
+++ b/keyboards/massdrop/ctrl/keymaps/responsive_pattern/README.md
@@ -1,5 +1,17 @@
1# THIS KEYMAP IS BROKEN
2 1
3The CTRL and ALT have both been switched to using the QMK RGB Matrix system, 2
4rendering any custom effects that used the old, custom Massdrop lighting system, 3Fn + P + Esc, Fn + P + `: reset effect to default
5BROKEN. 4
5Fn + P + Tab, Fn + P + Y: select previous color pattern
6Fn + P + Caps, Fn + P + H: select next color pattern
7
8Fn + P + A, Fn + P + J: (no effect for now)
9Fn + P + D, Fn + P + L: (no effect for now)
10
11
12Fn + P + Q, Fn + P + U: wave travel faster
13Fn + P + E, Fn + P + O: wave travel slower
14
15
16Fn + P + W, Fn + P + I: increase wave width
17Fn + P + S, Fn + P + K: decrease wave width
diff --git a/keyboards/massdrop/ctrl/keymaps/responsive_pattern/keymap.c b/keyboards/massdrop/ctrl/keymaps/responsive_pattern/keymap.c
index 58911aa75..dbf90b50a 100644
--- a/keyboards/massdrop/ctrl/keymaps/responsive_pattern/keymap.c
+++ b/keyboards/massdrop/ctrl/keymaps/responsive_pattern/keymap.c
@@ -1,41 +1,33 @@
1#include QMK_KEYBOARD_H 1#include QMK_KEYBOARD_H
2 2
3// uint8_t keyboard_leds(void) 3#include <math.h> // sqrtf, powf
4#include <tmk_core/protocol/arm_atsam/main_arm_atsam.h>
5 4
5#ifdef CONSOLE_ENABLE
6 6
7#if ISSI3733_LED_COUNT == 119 7#include <print.h>
8# define KEY_LED_COUNT 87
9#elif ISSI3733_LED_COUNT == 105
10# define KEY_LED_COUNT 67
11#endif
12
13#define min(x, y) (x < y ? x : y)
14
15 8
16extern issi3733_led_t *lede; 9#endif
17extern issi3733_led_t led_map[];
18 10
19enum ctrl_keycodes { 11enum ctrl_keycodes {
20 L_BRI = SAFE_RANGE, //LED Brightness Increase 12 L_BRI = SAFE_RANGE, //LED Brightness Increase //Working
21 L_BRD, //LED Brightness Decrease 13 L_BRD, //LED Brightness Decrease //Working
22 L_PTN, //LED Pattern Select Next 14 L_PTN, //LED Pattern Select Next //Working
23 L_PTP, //LED Pattern Select Previous 15 L_PTP, //LED Pattern Select Previous //Working
24 L_PSI, //LED Pattern Speed Increase 16 L_PSI, //LED Pattern Speed Increase //Working
25 L_PSD, //LED Pattern Speed Decrease 17 L_PSD, //LED Pattern Speed Decrease //Working
26 L_T_MD, //LED Toggle Mode 18 L_T_MD, //LED Toggle Mode //Working
27 L_T_ONF, //LED Toggle On / Off 19 L_T_ONF, //LED Toggle On / Off //Broken
28 L_ON, //LED On 20 L_ON, //LED On //Broken
29 L_OFF, //LED Off 21 L_OFF, //LED Off //Broken
30 L_T_BR, //LED Toggle Breath Effect 22 L_T_BR, //LED Toggle Breath Effect //Working
31 L_T_PTD, //LED Toggle Scrolling Pattern Direction 23 L_T_PTD, //LED Toggle Scrolling Pattern Direction //Working
32 U_T_AUTO, //USB Extra Port Toggle Auto Detect / Always Active 24 U_T_AGCR, //USB Toggle Automatic GCR control //Working
33 U_T_AGCR, //USB Toggle Automatic GCR control 25 DBG_TOG, //DEBUG Toggle On / Off //
34 DBG_TOG, //DEBUG Toggle On / Off 26 DBG_MTRX, //DEBUG Toggle Matrix Prints //
35 DBG_MTRX, //DEBUG Toggle Matrix Prints 27 DBG_KBD, //DEBUG Toggle Keyboard Prints //
36 DBG_KBD, //DEBUG Toggle Keyboard Prints 28 DBG_MOU, //DEBUG Toggle Mouse Prints //
37 DBG_MOU, //DEBUG Toggle Mouse Prints 29 MD_BOOT, //Restart into bootloader after hold timeout //Working
38 MD_BOOT, //Restart into bootloader after hold timeout 30
39 31
40 L_SP_PR, //LED Splash Pattern Select Previous 32 L_SP_PR, //LED Splash Pattern Select Previous
41 L_SP_NE, //LED Splash Pattern Select Next 33 L_SP_NE, //LED Splash Pattern Select Next
@@ -48,10 +40,9 @@ enum ctrl_keycodes {
48 40
49 L_CP_PR, //LED Color Pattern Select Previous 41 L_CP_PR, //LED Color Pattern Select Previous
50 L_CP_NX, //LEB Color Pattern Select Next 42 L_CP_NX, //LEB Color Pattern Select Next
51};
52 43
53#define TG_NKRO MAGIC_TOGGLE_NKRO //Toggle 6KRO / NKRO mode 44 S_RESET // reset all parameters
54#define ______ KC_TRNS 45};
55 46
56keymap_config_t keymap_config; 47keymap_config_t keymap_config;
57 48
@@ -67,418 +58,46 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
67 [1] = LAYOUT( 58 [1] = LAYOUT(
68 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MUTE, _______, _______, \ 59 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MUTE, _______, _______, \
69 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MPLY, KC_MSTP, KC_VOLU, \ 60 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MPLY, KC_MSTP, KC_VOLU, \
70 L_T_BR, L_PSD, L_BRI, L_PSI, _______, _______, _______, U_T_AUTO,U_T_AGCR,_______, MO(2), _______, _______, _______, KC_MPRV, KC_MNXT, KC_VOLD, \ 61 L_T_BR, L_PSD, L_BRI, L_PSI, _______, _______, _______, _______, U_T_AGCR,_______, MO(2), _______, _______, _______, KC_MPRV, KC_MNXT, KC_VOLD, \
71 L_T_PTD, L_PTP, L_BRD, L_PTN, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ 62 L_T_PTD, L_PTP, L_BRD, L_PTN, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
72 _______, L_T_MD, L_T_ONF, _______, _______, MD_BOOT, TG_NKRO, _______, _______, _______, _______, _______, _______, \ 63 _______, L_T_MD, L_T_ONF, _______, _______, MD_BOOT, NK_TOGG, _______, _______, _______, _______, _______, _______, \
73 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \ 64 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
74 ), 65 ),
75 [2] = LAYOUT( 66 [2] = LAYOUT(
76 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ 67 S_RESET, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
77 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ 68 S_RESET, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
78 L_CP_NX, L_SP_SL, L_SP_WD, L_SP_FA, _______, _______, L_CP_NX, L_SP_SL, L_SP_WD, L_SP_FA, _______, _______, _______, _______, _______, _______, _______, \ 69 L_CP_NX, L_SP_SL, L_SP_WD, L_SP_FA, _______, _______, L_CP_NX, L_SP_SL, L_SP_WD, L_SP_FA, _______, _______, _______, _______, _______, _______, _______, \
79 L_CP_PR, L_SP_PR, L_SP_NW, L_SP_NE, _______, _______, L_CP_PR, L_SP_PR, L_SP_NW, L_SP_NE, _______, _______, _______, \ 70 L_CP_PR, L_SP_PR, L_SP_NW, L_SP_NE, _______, _______, L_CP_PR, L_SP_PR, L_SP_NW, L_SP_NE, _______, _______, _______, \
80 _______, _______, _______, _______, _______, _______, TG_NKRO, _______, _______, _______, _______, _______, _______, \ 71 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
81 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \ 72 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
82 ), 73 )
83 /* 74 /*
84 [X] = LAYOUT( 75 [X] = LAYOUT(
85 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ 76 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
86 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ 77 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
87 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ 78 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
88 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ 79 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
89 _______, _______, _______, _______, _______, _______, TG_NKRO, _______, _______, _______, _______, _______, _______, \ 80 _______, _______, _______, _______, _______, _______, NK_TOGG, _______, _______, _______, _______, _______, _______, \
90 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \ 81 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
91 ), 82 ),
92 */ 83 */
93}; 84};
94 85
95// see: /tmk_core/common/keycode.h 86#define DISTANCE_NORAMLIZING_PARAMETER 3
96uint8_t KEYCODE_TO_LED_ID[256];
97uint8_t DISTANCE_MAP[KEY_LED_COUNT+1][KEY_LED_COUNT+1];
98struct user_led_t {
99 uint8_t state;
100 uint8_t r;
101 uint8_t g;
102 uint8_t b;
103} USER_LED[KEY_LED_COUNT] = {
104
105};
106
107struct { 87struct {
108 uint8_t PATTERN_INDEX; 88 uint8_t PATTERN_INDEX;
109 uint8_t WAVE_FRONT_WIDTH; 89 float WAVE_WIDTH;
110 uint16_t WAVE_PERIOD; 90 float WAVE_SPEED;
111 uint8_t COLOR_PATTERN_INDEX; 91 int COLOR_PATTERN_INDEX;
112 uint8_t TRAVEL_DISTANCE; 92 float TRAVEL_DISTANCE;
113} USER_CONFIG = { 93} USER_CONFIG = {
114 .PATTERN_INDEX = 1, 94 .PATTERN_INDEX = 1,
115 .WAVE_FRONT_WIDTH = 3, 95 .WAVE_WIDTH = 10, // width of the wave in keycaps
116 .WAVE_PERIOD = 50, 96 .WAVE_SPEED = 15, // travel how many keycaps per second
117 .COLOR_PATTERN_INDEX = 0, 97 .COLOR_PATTERN_INDEX = 0,
118 .TRAVEL_DISTANCE = 25, 98 .TRAVEL_DISTANCE = 25,
119}; 99};
120 100
121uint8_t ktli(uint16_t keycode){
122 if(keycode < 256){
123 // the array is initialized in `matrix_init_user()`
124 return KEYCODE_TO_LED_ID[keycode];
125 }
126 switch(keycode){
127 // definition of MO(layer): quantum/quantum_keycodes.h: line 614
128 case MO(1): return 82;
129 }
130 return 0;
131};
132
133// Runs just one time when the keyboard initializes.
134static void init_keycode_to_led_map(void){
135 uint16_t LED_MAP[MATRIX_ROWS][MATRIX_COLS] = LAYOUT(
136 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
137 20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,
138 36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
139 52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,
140#if KEY_LED_COUNT >= 87
141 68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87
142#endif
143 );
144
145 uint16_t key = 0;
146 for(uint8_t y = 0; y < MATRIX_ROWS; ++y){
147 for(uint8_t x = 0; x < MATRIX_COLS; ++x){
148 key = keymaps[0][y][x];
149 if(key < 256){
150 KEYCODE_TO_LED_ID[key] = LED_MAP[y][x];
151 }
152 }
153 }
154}
155// https://docs.qmk.fm/#/feature_terminal
156#define KEY_POSITION_MAP_ROWS 6
157#define KEY_POSITION_MAP_COLUMNS 20
158static void init_distance_map(void){
159 uint16_t KEY_POSITION_MAP[KEY_POSITION_MAP_ROWS][KEY_POSITION_MAP_COLUMNS] = {
160 { KC_NO, KC_ESC, KC_NO, KC_F1, KC_F2, KC_F3, KC_F4, KC_NO, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_PSCR, KC_SLCK, KC_PAUS, },
161 // { KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, },
162 { KC_NO, KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_BSPC, KC_NO, KC_INS, KC_HOME, KC_PGUP, },
163 { KC_NO, KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_BSLS, KC_NO, KC_DEL, KC_END, KC_PGDN, },
164 { KC_NO, KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_ENT, KC_ENT, KC_NO, KC_NO, KC_NO, KC_NO, },
165 { KC_NO, KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_RSFT, KC_RSFT, KC_RSFT, KC_NO, KC_NO, KC_UP, KC_NO, },
166 { KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_SPC, KC_SPC, KC_SPC, KC_SPC, KC_SPC, KC_RALT, KC_NO, MO(1), KC_APP, KC_RCTL, KC_RCTL, KC_RCTL, KC_NO, KC_LEFT, KC_DOWN, KC_RIGHT, },
167 };
168 uint8_t columns = KEY_POSITION_MAP_COLUMNS;
169 uint8_t rows = KEY_POSITION_MAP_ROWS;
170
171 for(uint8_t y = 0; y < rows; ++y){
172 for(uint8_t x = 0; x < columns; ++x){
173 uint8_t id1 = ktli(KEY_POSITION_MAP[y][x]);
174
175 for(uint8_t j = y; j < rows; ++j){
176 for(uint8_t i = 0; i < columns; ++i){
177 uint8_t id2 = ktli(KEY_POSITION_MAP[j][i]);
178
179 if(id1 == id2) continue;
180
181 uint8_t dx = abs(i - x);
182 uint8_t dy = abs(j - y);
183 uint8_t dis = dx + dy;
184 if(i < x && j > y){
185 dis -= min(dx, dy);
186 }
187
188 uint8_t _dis = DISTANCE_MAP[id1][id2];
189 if(_dis && _dis <= dis) continue;
190 DISTANCE_MAP[id1][id2] = dis;
191 DISTANCE_MAP[id2][id1] = dis;
192 }
193 }
194 }
195 }
196}
197void matrix_init_user(void) {
198 init_keycode_to_led_map();
199 init_distance_map();
200};
201
202// /tmk_core/protocol/arm_atsam/led_matrix.c: line 244
203uint8_t led_enabled;
204float led_animation_speed;
205uint8_t led_animation_direction;
206uint8_t led_animation_orientation;
207uint8_t led_animation_breathing;
208uint8_t led_animation_breathe_cur;
209uint8_t breathe_step;
210uint8_t breathe_dir;
211uint64_t led_next_run;
212
213uint8_t led_animation_id;
214uint8_t led_lighting_mode;
215
216issi3733_led_t *led_cur;
217uint8_t led_per_run;
218float breathe_mult;
219
220// overrided /tmk_core/protocol/arm_atsam/led_matrix.c: line 484
221void rgb_matrix_init_user(void){
222 led_animation_speed = ANIMATION_SPEED_STEP * 15;
223 led_per_run = 15;
224}
225
226// overrided /tmk_core/protocol/arm_atsam/led_matrix.c: line 262
227void led_matrix_run(void)
228{
229 float ro;
230 float go;
231 float bo;
232 float po;
233 uint8_t led_this_run = 0;
234 led_setup_t *f = (led_setup_t*)led_setups[led_animation_id];
235
236 if (led_cur == 0) //Denotes start of new processing cycle in the case of chunked processing
237 {
238 led_cur = led_map;
239
240 breathe_mult = 1;
241
242 if (led_animation_breathing)
243 {
244 led_animation_breathe_cur += breathe_step * breathe_dir;
245
246 if (led_animation_breathe_cur >= BREATHE_MAX_STEP)
247 breathe_dir = -1;
248 else if (led_animation_breathe_cur <= BREATHE_MIN_STEP)
249 breathe_dir = 1;
250
251 //Brightness curve created for 256 steps, 0 - ~98%
252 breathe_mult = 0.000015 * led_animation_breathe_cur * led_animation_breathe_cur;
253 if (breathe_mult > 1) breathe_mult = 1;
254 else if (breathe_mult < 0) breathe_mult = 0;
255 }
256 }
257
258 uint8_t fcur = 0;
259 uint8_t fmax = 0;
260
261 //Frames setup
262 while (f[fcur].end != 1)
263 {
264 fcur++; //Count frames
265 }
266
267 fmax = fcur; //Store total frames count
268
269 struct user_led_t user_led_cur;
270 while (led_cur < lede && led_this_run < led_per_run)
271 {
272 ro = 0;
273 go = 0;
274 bo = 0;
275
276 uint8_t led_index = led_cur - led_map; // only this part differs from the original function.
277 if(led_index < KEY_LED_COUNT){ //
278 user_led_cur = USER_LED[led_index]; // `struct user_led_t USER_LED[]` is stored globally.
279 } //
280 //
281 if(led_index < KEY_LED_COUNT && user_led_cur.state){ // `user_led_cur` is just for convenience
282 ro = user_led_cur.r; //
283 go = user_led_cur.g; //
284 bo = user_led_cur.b; //
285 } //
286 else if (led_lighting_mode == LED_MODE_KEYS_ONLY && led_cur->scan == 255)
287 {
288 //Do not act on this LED
289 }
290 else if (led_lighting_mode == LED_MODE_NON_KEYS_ONLY && led_cur->scan != 255)
291 {
292 //Do not act on this LED
293 }
294 else if (led_lighting_mode == LED_MODE_INDICATORS_ONLY)
295 {
296 //Do not act on this LED (Only show indicators)
297 }
298 else
299 {
300 //Act on LED
301 for (fcur = 0; fcur < fmax; fcur++)
302 {
303
304 if (led_animation_orientation)
305 {
306 po = led_cur->py;
307 }
308 else
309 {
310 po = led_cur->px;
311 }
312
313 float pomod;
314 pomod = (float)(g_tick % (uint32_t)(1000.0f / led_animation_speed)) / 10.0f * led_animation_speed;
315
316 //Add in any moving effects
317 if ((!led_animation_direction && f[fcur].ef & EF_SCR_R) || (led_animation_direction && (f[fcur].ef & EF_SCR_L)))
318 {
319 pomod *= 100.0f;
320 pomod = (uint32_t)pomod % 10000;
321 pomod /= 100.0f;
322
323 po -= pomod;
324
325 if (po > 100) po -= 100;
326 else if (po < 0) po += 100;
327 }
328 else if ((!led_animation_direction && f[fcur].ef & EF_SCR_L) || (led_animation_direction && (f[fcur].ef & EF_SCR_R)))
329 {
330 pomod *= 100.0f;
331 pomod = (uint32_t)pomod % 10000;
332 pomod /= 100.0f;
333 po += pomod;
334
335 if (po > 100) po -= 100;
336 else if (po < 0) po += 100;
337 }
338
339 //Check if LED's po is in current frame
340 if (po < f[fcur].hs) continue;
341 if (po > f[fcur].he) continue;
342 //note: < 0 or > 100 continue
343
344 //Calculate the po within the start-stop percentage for color blending
345 po = (po - f[fcur].hs) / (f[fcur].he - f[fcur].hs);
346
347 //Add in any color effects
348 if (f[fcur].ef & EF_OVER)
349 {
350 ro = (po * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5;
351 go = (po * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5;
352 bo = (po * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5;
353 }
354 else if (f[fcur].ef & EF_SUBTRACT)
355 {
356 ro -= (po * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5;
357 go -= (po * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5;
358 bo -= (po * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5;
359 }
360 else
361 {
362 ro += (po * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5;
363 go += (po * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5;
364 bo += (po * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5;
365 }
366 }
367 }
368
369 //Clamp values 0-255
370 if (ro > 255) ro = 255; else if (ro < 0) ro = 0;
371 if (go > 255) go = 255; else if (go < 0) go = 0;
372 if (bo > 255) bo = 255; else if (bo < 0) bo = 0;
373
374 if (led_animation_breathing)
375 {
376 ro *= breathe_mult;
377 go *= breathe_mult;
378 bo *= breathe_mult;
379 }
380
381 *led_cur->rgb.r = (uint8_t)ro;
382 *led_cur->rgb.g = (uint8_t)go;
383 *led_cur->rgb.b = (uint8_t)bo;
384
385#ifdef USB_LED_INDICATOR_ENABLE
386 if (keyboard_leds())
387 {
388 uint8_t kbled = keyboard_leds();
389 if (
390 #if USB_LED_NUM_LOCK_SCANCODE != 255
391 (led_cur->scan == USB_LED_NUM_LOCK_SCANCODE && kbled & (1<<USB_LED_NUM_LOCK)) ||
392 #endif //NUM LOCK
393 #if USB_LED_CAPS_LOCK_SCANCODE != 255
394 (led_cur->scan == USB_LED_CAPS_LOCK_SCANCODE && kbled & (1<<USB_LED_CAPS_LOCK)) ||
395 #endif //CAPS LOCK
396 #if USB_LED_SCROLL_LOCK_SCANCODE != 255
397 (led_cur->scan == USB_LED_SCROLL_LOCK_SCANCODE && kbled & (1<<USB_LED_SCROLL_LOCK)) ||
398 #endif //SCROLL LOCK
399 #if USB_LED_COMPOSE_SCANCODE != 255
400 (led_cur->scan == USB_LED_COMPOSE_SCANCODE && kbled & (1<<USB_LED_COMPOSE)) ||
401 #endif //COMPOSE
402 #if USB_LED_KANA_SCANCODE != 255
403 (led_cur->scan == USB_LED_KANA_SCANCODE && kbled & (1<<USB_LED_KANA)) ||
404 #endif //KANA
405 (0))
406 {
407 if (*led_cur->rgb.r > 127) *led_cur->rgb.r = 0;
408 else *led_cur->rgb.r = 255;
409 if (*led_cur->rgb.g > 127) *led_cur->rgb.g = 0;
410 else *led_cur->rgb.g = 255;
411 if (*led_cur->rgb.b > 127) *led_cur->rgb.b = 0;
412 else *led_cur->rgb.b = 255;
413 }
414 }
415#endif //USB_LED_INDICATOR_ENABLE
416
417 led_cur++;
418 led_this_run++;
419 }
420}
421
422#define KEY_STROKES_LENGTH 20
423struct {
424 bool alive;
425 uint8_t led_id;
426 uint32_t time;
427} KEY_STROKES[KEY_STROKES_LENGTH] = {{}};
428
429
430
431
432void set_led_rgb(uint8_t led_id, uint8_t r, uint8_t g, uint8_t b){
433 issi3733_led_t *target_led = (led_map + led_id);
434 *target_led->rgb.r = r;
435 *target_led->rgb.g = g;
436 *target_led->rgb.b = b;
437}
438
439
440uint8_t DISTANCE_FROM_LAST_KEYSTROKE[KEY_LED_COUNT+1];
441void calculate_keystroke_distance(void){
442 bool alive;
443 uint8_t led_id, period_passed;
444 uint32_t t;
445
446
447 for(uint8_t i = 0; i <= KEY_LED_COUNT; ++i){
448 DISTANCE_FROM_LAST_KEYSTROKE[i] = 0;
449 }
450
451 for(uint8_t i = 0; i < KEY_STROKES_LENGTH; ++i){
452 if(KEY_STROKES[i].alive){
453 t = timer_elapsed32(KEY_STROKES[i].time);
454 alive = 0;
455 led_id = KEY_STROKES[i].led_id;
456 period_passed = t / USER_CONFIG.WAVE_PERIOD;
457
458 uint8_t delta_period;
459 for(uint8_t j = 1; j <= KEY_LED_COUNT; ++j){
460 delta_period = period_passed - DISTANCE_MAP[led_id][j];
461 if(( delta_period < USER_CONFIG.WAVE_FRONT_WIDTH) && (
462 DISTANCE_MAP[led_id][j] <= USER_CONFIG.TRAVEL_DISTANCE
463 )){
464 switch(USER_CONFIG.PATTERN_INDEX){
465 case 3:
466 case 4:
467 case 5:
468 case 6:
469 DISTANCE_FROM_LAST_KEYSTROKE[j] += delta_period;
470 break;
471 default:
472 DISTANCE_FROM_LAST_KEYSTROKE[j] = 1;
473 break;
474 }
475 alive = 1;
476 }
477 }
478 KEY_STROKES[i].alive = alive;
479 }
480 }
481}
482 101
483#define COLOR_PATTERN_RGB_COUNT 18 102#define COLOR_PATTERN_RGB_COUNT 18
484static uint8_t COLOR_PATTERNS[][COLOR_PATTERN_RGB_COUNT][3] = { 103static uint8_t COLOR_PATTERNS[][COLOR_PATTERN_RGB_COUNT][3] = {
@@ -515,191 +134,300 @@ static uint8_t COLOR_PATTERNS[][COLOR_PATTERN_RGB_COUNT][3] = {
515static const uint8_t COLOR_PATTERNS_COUNT = ( 134static const uint8_t COLOR_PATTERNS_COUNT = (
516 sizeof(COLOR_PATTERNS) / sizeof(COLOR_PATTERNS[0])); 135 sizeof(COLOR_PATTERNS) / sizeof(COLOR_PATTERNS[0]));
517 136
518void set_user_led_rgb(uint8_t i, uint8_t r, uint8_t g, uint8_t b){ 137/**
519 USER_LED[i-1].state = 1; 138 * trimed down version of `ISSI3733_LED_MAP`:
520 USER_LED[i-1].r = r; 139 *
521 USER_LED[i-1].g = g; 140 * `ISSI3733_LED_MAP` is defined in keyboards/massdrop/ctrl/config_led.h is not directly usable,
522 USER_LED[i-1].b = b; 141 * the numbers inside this map could probably be related to the PCB layout instead of
523} 142 * the actual physical layout,
524void unset_user_led_rgb(uint8_t i){ 143 *
525 USER_LED[i-1].state = 0; 144 * this `ISSI3733_LED_MAP` is used somewhere in protocol/ but is not globally accessible
526} 145 * so one is created here
527void set_indicator_led_rgb(uint8_t i, 146 *
528 uint8_t layer, uint8_t r, uint8_t g, uint8_t b){ 147 * x and y are coordinates of the physical layout
529 USER_LED[i-1].state |= 1 << layer; 148 * KC_ESC is (0, 0), gap between function keys and number rows is 1.5
530 USER_LED[i-1].r = r; 149 * +y is downwards
531 USER_LED[i-1].g = g; 150 * 1 unit is width/height of 1 standard keycap
532 USER_LED[i-1].b = b; 151 */
533} 152#define MAX_LED_ID ISSI3733_LED_COUNT
534void unset_indicator_led_rgb(uint8_t i, uint8_t layer){ 153typedef struct led_info_s {
535 USER_LED[i-1].state &= ~(1 << layer); 154 uint16_t id;
536} 155 uint16_t scan;
156 float x;
157 float y;
158 uint8_t distance_to[MAX_LED_ID + 1];
159} led_info_t;
160led_info_t led_info[MAX_LED_ID + 1] = {
161 { .id = 0 },
162 { .id = 1, .x = 0.0, .y = 0.0, .scan = 41 }, // ESC
163 { .id = 2, .x = 2.0, .y = 0.0, .scan = 58 }, // F1
164 { .id = 3, .x = 3.0, .y = 0.0, .scan = 59 }, // F2
165 { .id = 4, .x = 3.5, .y = 0.0, .scan = 60 }, // F3
166 { .id = 5, .x = 5.0, .y = 0.0, .scan = 61 }, // F4
167 { .id = 6, .x = 6.5, .y = 0.0, .scan = 62 }, // F5
168 { .id = 7, .x = 7.5, .y = 0.0, .scan = 63 }, // F6
169 { .id = 8, .x = 8.5, .y = 0.0, .scan = 64 }, // F7
170 { .id = 9, .x = 9.5, .y = 0.0, .scan = 65 }, // F8
171 { .id = 10, .x = 11, .y = 0.0, .scan = 66 }, // F9
172 { .id = 11, .x = 12, .y = 0.0, .scan = 67 }, // F10
173 { .id = 12, .x = 13, .y = 0.0, .scan = 68 }, // F11
174 { .id = 13, .x = 14, .y = 0.0, .scan = 69 }, // F12
175 { .id = 14, .x = 15.5, .y = 0.0, .scan = 70 }, // Print
176 { .id = 15, .x = 16.5, .y = 0.0, .scan = 71 }, // Scoll Lock
177 { .id = 16, .x = 17.5, .y = 0.0, .scan = 72 }, // Pause
178 { .id = 17, .x = 0.0, .y = 1.5, .scan = 53 }, // `
179 { .id = 18, .x = 1.0, .y = 1.5, .scan = 30 }, // 1
180 { .id = 19, .x = 2.0, .y = 1.5, .scan = 31 }, // 2
181 { .id = 20, .x = 3.0, .y = 1.5, .scan = 32 }, // 3
182 { .id = 21, .x = 3.5, .y = 1.5, .scan = 33 }, // 4
183 { .id = 22, .x = 5.0, .y = 1.5, .scan = 34 }, // 5
184 { .id = 23, .x = 6.0, .y = 1.5, .scan = 35 }, // 6
185 { .id = 24, .x = 7.0, .y = 1.5, .scan = 36 }, // 7
186 { .id = 25, .x = 8.0, .y = 1.5, .scan = 37 }, // 8
187 { .id = 26, .x = 9.0, .y = 1.5, .scan = 38 }, // 9
188 { .id = 27, .x = 10.0, .y = 1.5, .scan = 39 }, // 0
189 { .id = 28, .x = 11.0, .y = 1.5, .scan = 45 }, // -
190 { .id = 29, .x = 12.0, .y = 1.5, .scan = 46 }, // =
191 { .id = 30, .x = 13.5, .y = 1.5, .scan = 42 }, // Backspace
192 { .id = 31, .x = 15.5, .y = 1.5, .scan = 73 }, // Insert
193 { .id = 32, .x = 16.6, .y = 1.5, .scan = 74 }, // Home
194 { .id = 33, .x = 17.5, .y = 1.5, .scan = 75 }, // Page Up
195 { .id = 34, .x = 0.2, .y = 2.5, .scan = 43 }, // Tab
196 { .id = 35, .x = 1.5, .y = 2.5, .scan = 20 }, // Q
197 { .id = 36, .x = 2.5, .y = 2.5, .scan = 26 }, // W
198 { .id = 37, .x = 3.5, .y = 2.5, .scan = 8 }, // E
199 { .id = 38, .x = 4.5, .y = 2.5, .scan = 21 }, // R
200 { .id = 39, .x = 5.5, .y = 2.5, .scan = 23 }, // T
201 { .id = 40, .x = 6.5, .y = 2.5, .scan = 28 }, // Y
202 { .id = 41, .x = 7.5, .y = 2.5, .scan = 24 }, // U
203 { .id = 42, .x = 8.5, .y = 2.5, .scan = 12 }, // I
204 { .id = 43, .x = 9.5, .y = 2.5, .scan = 18 }, // O
205 { .id = 44, .x = 10.5, .y = 2.5, .scan = 19 }, // P
206 { .id = 45, .x = 11.5, .y = 2.5, .scan = 47 }, // [
207 { .id = 46, .x = 12.5, .y = 2.5, .scan = 48 }, // ]
208 { .id = 47, .x = 13.75, .y = 2.5, .scan = 49 }, /* \ */
209 { .id = 48, .x = 15.5, .y = 2.5, .scan = 76 }, // Delete
210 { .id = 49, .x = 16.5, .y = 2.5, .scan = 77 }, // End
211 { .id = 50, .x = 17.5, .y = 2.5, .scan = 78 }, // Page Down
212 { .id = 51, .x = 0.4, .y = 3.5, .scan = 57 }, // Caps Lock
213 { .id = 52, .x = 2.5, .y = 3.5, .scan = 4 }, // A
214 { .id = 53, .x = 3.5, .y = 3.5, .scan = 22 }, // S
215 { .id = 54, .x = 4.5, .y = 3.5, .scan = 7 }, // D
216 { .id = 55, .x = 5.5, .y = 3.5, .scan = 9 }, // F
217 { .id = 56, .x = 6.5, .y = 3.5, .scan = 10 }, // G
218 { .id = 57, .x = 7.5, .y = 3.5, .scan = 11 }, // H
219 { .id = 58, .x = 8.5, .y = 3.5, .scan = 13 }, // J
220 { .id = 59, .x = 9.5, .y = 3.5, .scan = 14 }, // K
221 { .id = 60, .x = 10.5, .y = 3.5, .scan = 15 }, // L
222 { .id = 61, .x = 11.5, .y = 3.5, .scan = 51 }, // ;
223 { .id = 62, .x = 12.5, .y = 3.5, .scan = 52 }, // '
224 { .id = 63, .x = 13.5, .y = 3.5, .scan = 40 }, // Enter
225 { .id = 64, .x = 0.5, .y = 4.5, .scan = 225 }, // LSHIFT
226 { .id = 65, .x = 2.25, .y = 4.5, .scan = 29 }, // Z
227 { .id = 66, .x = 3.25, .y = 4.5, .scan = 27 }, // X
228 { .id = 67, .x = 4.25, .y = 4.5, .scan = 6 }, // C
229 { .id = 68, .x = 5.25, .y = 4.5, .scan = 25 }, // V
230 { .id = 69, .x = 6.25, .y = 4.5, .scan = 5 }, // B
231 { .id = 70, .x = 7.25, .y = 4.5, .scan = 17 }, // N
232 { .id = 71, .x = 8.25, .y = 4.5, .scan = 16 }, // M
233 { .id = 72, .x = 9.25, .y = 4.5, .scan = 54 }, // COMMA
234 { .id = 73, .x = 10.25, .y = 4.5, .scan = 55 }, // DOT
235 { .id = 74, .x = 11.25, .y = 4.5, .scan = 56 }, // SLASH
236 { .id = 75, .x = 13.2, .y = 4.5, .scan = 229 }, // RSHIFT
237 { .id = 76, .x = 16.5, .y = 4.5, .scan = 82 }, // UP
238 { .id = 77, .x = 0.1, .y = 5.5, .scan = 224 }, // LCTRL
239 { .id = 78, .x = 1.25, .y = 5.5, .scan = 227 }, // WIN
240 { .id = 79, .x = 2.5, .y = 5.5, .scan = 226 }, // LALT
241 { .id = 80, .x = 6.25, .y = 5.5, .scan = 44 }, // SPACE
242
243#define MAX_CACHED_SCAN_CODE 231
244 { .id = 81, .x = 10.25, .y = 5.5, .scan = 230 }, // RALT
245
246#define FN_KEY_LED_ID 82
247#define FN_KEY_SCAN_CODE 20737
248 { .id = 82, .x = 11.5, .y = 5.5, .scan = 20737 }, // FN
249 { .id = 83, .x = 12.7, .y = 5.5, .scan = 101 }, // APP
250 { .id = 84, .x = 13.75, .y = 5.5, .scan = 228 }, // RCTRL
251 { .id = 85, .x = 15.5, .y = 5.5, .scan = 80 }, // LEFT
252 { .id = 86, .x = 16.5, .y = 5.5, .scan = 81 }, // DOWN
253 { .id = 87, .x = 17.5, .y = 5.5, .scan = 79 }, // RIGHT
254
255#define MAX_LED_ID_WITH_SCANCODE 87
256
257 { .id = 88, .x = 18.5, .y = 6.5, .scan = 255 },
258 { .id = 89, .x = 16.917, .y = 6.5, .scan = 255 },
259 { .id = 90, .x = 15.333, .y = 6.5, .scan = 255 },
260 { .id = 91, .x = 13.75, .y = 6.5, .scan = 255 },
261 { .id = 92, .x = 12.167, .y = 6.5, .scan = 255 },
262 { .id = 93, .x = 10.583, .y = 6.5, .scan = 255 },
263 { .id = 94, .x = 9, .y = 6.5, .scan = 255 },
264 { .id = 95, .x = 7.417, .y = 6.5, .scan = 255 },
265 { .id = 96, .x = 5.833, .y = 6.5, .scan = 255 },
266 { .id = 97, .x = 4.25, .y = 6.5, .scan = 255 },
267 { .id = 98, .x = 2.667, .y = 6.5, .scan = 255 },
268 { .id = 99, .x = 1.083, .y = 6.5, .scan = 255 },
269 { .id = 100, .x = -0.5, .y = 6.5, .scan = 255 },
270 { .id = 101, .x = -0.5, .y = 4.75, .scan = 255 },
271 { .id = 102, .x = -0.5, .y = 3, .scan = 255 },
272 { .id = 103, .x = -0.5, .y = 1.25, .scan = 255 },
273 { .id = 104, .x = -0.5, .y = -0.5, .scan = 255 },
274 { .id = 105, .x = 1.083, .y = -0.5, .scan = 255 },
275 { .id = 106, .x = 2.667, .y = -0.5, .scan = 255 },
276 { .id = 107, .x = 4.25, .y = -0.5, .scan = 255 },
277 { .id = 108, .x = 5.833, .y = -0.5, .scan = 255 },
278 { .id = 109, .x = 7.417, .y = -0.5, .scan = 255 },
279 { .id = 110, .x = 9, .y = -0.5, .scan = 255 },
280 { .id = 111, .x = 10.583, .y = -0.5, .scan = 255 },
281 { .id = 112, .x = 12.167, .y = -0.5, .scan = 255 },
282 { .id = 113, .x = 13.75, .y = -0.5, .scan = 255 },
283 { .id = 114, .x = 15.333, .y = -0.5, .scan = 255 },
284 { .id = 115, .x = 16.917, .y = -0.5, .scan = 255 },
285 { .id = 116, .x = 18.5, .y = 1.25, .scan = 255 },
286 { .id = 117, .x = 18.5, .y = 3, .scan = 255 },
287 { .id = 118, .x = 18.5, .y = 4.75, .scan = 255 },
288 { .id = 119, .x = 18.5, .y = 6.5, .scan = 255 },
289};
537 290
538void refresh_pattern_indicators(void){ 291/**
539 static uint8_t GRV_123456[] = { 292 * there are a few variables are used here
540 KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, 293 * keycode, scancode, led id
541 }; 294 *
542 295 * scancode relates to actual physical key press
543 if(layer_state >= 0x04){ 296 *
544 for(uint8_t i = 0; i < 7; ++i){ 297 * keycode is software key press, or scancode with modifiers (shift, ctrl, alt, etc.),
545 if(i == USER_CONFIG.PATTERN_INDEX){ 298 * keycode with the value less than 255 are usually the same with scan code (I hope so)
546 set_indicator_led_rgb(ktli(GRV_123456[i]), 2, 0, 0, 255); 299 *
547 } else{ 300 * the led pattern are running based on led id, because led on the keyboard
548 set_indicator_led_rgb(ktli(GRV_123456[i]), 2, 0, 255, 0); 301 * are not limited to keys only
302 */
303led_info_t* get_led_info_by_scancode(uint16_t scancode){
304 static bool init = false;
305 static led_info_t* scancode_to_led_info[MAX_CACHED_SCAN_CODE + 1];
306 if(!init){
307 for(int i = 1; i <= MAX_LED_ID_WITH_SCANCODE; ++i){
308 uint16_t scan = led_info[i].scan;
309 if(scan <= MAX_CACHED_SCAN_CODE){
310 scancode_to_led_info[scan] = (led_info + i);
549 } 311 }
550 } 312 }
551 } else{ 313 init = true;
552 for(uint8_t i = 0; i < 7; ++i){
553 unset_indicator_led_rgb(ktli(GRV_123456[i]), 2);
554 }
555 } 314 }
556} 315
557void refresh_color_pattern_indicators(void){ 316 if(scancode <= MAX_CACHED_SCAN_CODE){
558 static uint8_t ZXCVBNM_COMM_DOT[] = { 317 return scancode_to_led_info[scancode];
559 KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, 318 } else if(scancode == FN_KEY_SCAN_CODE){ // FN
560 }; 319 return (led_info + FN_KEY_LED_ID);
561
562 if(layer_state >= 0x04){
563 uint8_t (*c)[3] = &COLOR_PATTERNS[USER_CONFIG.COLOR_PATTERN_INDEX][0];
564 for(uint8_t i = 0; i < 9; ++i){
565 set_indicator_led_rgb(ktli(ZXCVBNM_COMM_DOT[i]),
566 2, c[i][0], c[i][1], c[i][2]);
567 }
568 } else{
569 for(uint8_t i = 0; i < 9; ++i){
570 unset_indicator_led_rgb(ktli(ZXCVBNM_COMM_DOT[i]), 2);
571 }
572 } 320 }
321 return led_info;
573} 322}
574 323
575// Runs constantly in the background, in a loop.
576void matrix_scan_user(void) {
577 static uint32_t scan_timer = 0;
578 static uint8_t last_layer = 0;
579
580 uint8_t layer = 0;
581 if(layer_state >= 0x04){
582 layer = 2;
583 } else if(layer_state >= 0x02){
584 layer = 1;
585 }
586 324
587 calculate_keystroke_distance(); 325
588 326void init_led_info(void){
589 327 for(int i = 1; i <= MAX_LED_ID; ++i){
590 #define USE_PATTERN 0 328 led_info_t *entry1 = led_info + i;
591 #define BLACK_RGB 1 329 for(int j = i; j <= MAX_LED_ID; ++j){
592 #define COLOR_RGB 2 330 led_info_t *entry2 = led_info + j;
593 uint8_t ci; // color index 331 /**
594 uint8_t *rgb; 332 * distance is tripled because
595 uint8_t handle_type; 333 * convertion from float to int reduces accuracy
596 uint8_t distance; 334 *
597 for(uint8_t i = 1; i <= KEY_LED_COUNT; ++i){ 335 */
598 if(USER_LED[i-1].state >= 2) continue; 336 uint8_t distance = (uint8_t)sqrtf(
599 337 powf(entry1->x - entry2->x, 2.0) +
600 handle_type = USE_PATTERN; 338 powf(entry1->y - entry2->y, 2.0)) *
601 distance = DISTANCE_FROM_LAST_KEYSTROKE[i]; 339 DISTANCE_NORAMLIZING_PARAMETER;
602 340 entry1->distance_to[j] = distance;
603 switch(USER_CONFIG.PATTERN_INDEX){ 341 entry2->distance_to[i] = distance;
604 case 0: handle_type = USE_PATTERN; break;
605 case 1: handle_type = distance ? USE_PATTERN : BLACK_RGB; break;
606 case 2: handle_type = distance ? BLACK_RGB : USE_PATTERN; break;
607 case 3: handle_type = distance ? COLOR_RGB : BLACK_RGB; break;
608 case 4: handle_type = distance ? COLOR_RGB : USE_PATTERN; break;
609 case 5:
610 case 6: handle_type = distance ? COLOR_RGB : USE_PATTERN; break;
611 }
612 switch(handle_type){
613 case USE_PATTERN: unset_user_led_rgb(i); break;
614 case BLACK_RGB: set_user_led_rgb(i, 0, 0, 0); break;
615 case COLOR_RGB:
616 ci = (DISTANCE_FROM_LAST_KEYSTROKE[i] * COLOR_PATTERN_RGB_COUNT /
617 USER_CONFIG.WAVE_FRONT_WIDTH) % COLOR_PATTERN_RGB_COUNT;
618 rgb = &COLOR_PATTERNS[USER_CONFIG.COLOR_PATTERN_INDEX][ci][0];
619
620 set_user_led_rgb(i, rgb[0], rgb[1], rgb[2]);
621 break;
622 } 342 }
623 } 343 }
344};
624 345
625 346
626 // could be moved to process_record_user() 347// Runs just one time when the keyboard initializes.
627 if(layer != last_layer){ 348void matrix_init_user(void) {
628 349 init_led_info();
629 static uint8_t QWEASDP[] = { 350};
630 KC_Q, KC_W, KC_E, KC_A, KC_S, KC_D, KC_P,
631 };
632 static uint8_t YUIOHJKL[] = {
633 KC_Y, KC_U, KC_I, KC_O, KC_H, KC_J, KC_K, KC_L,
634 };
635
636 switch(last_layer){
637 case 1:
638 for(uint8_t i = 0; i < 7; ++i){
639 unset_indicator_led_rgb(ktli(QWEASDP[i]), 1);
640 }
641 break;
642 case 2:
643 for(uint8_t i = 0; i < 6; ++i){
644 unset_indicator_led_rgb(ktli(QWEASDP[i]), 2);
645 }
646 for(uint8_t i = 0; i < 8; ++i){
647 unset_indicator_led_rgb(ktli(YUIOHJKL[i]), 2);
648 }
649 unset_indicator_led_rgb(ktli(KC_TAB), 2);
650 unset_indicator_led_rgb(ktli(KC_CAPS), 2);
651 break;
652 }
653 351
352typedef struct keystroke_s {
353 uint16_t scancode;
354 uint32_t timer;
355 bool active;
356} keystroke_t;
654 357
655 switch(layer){ 358#define MAX_ACTIVE_KEYSTORKES 10
656 case 1: 359keystroke_t ACTIVE_KEYSTROKES[MAX_ACTIVE_KEYSTORKES];
657 for(uint8_t i = 0; i < 7; ++i){
658 set_indicator_led_rgb(ktli(QWEASDP[i]), 1, 255, 0, 0);
659 }
660 break;
661 case 2:
662 for(uint8_t i = 0; i < 6; ++i){
663 set_indicator_led_rgb(ktli(QWEASDP[i]), 2, 0, 255, 0);
664 }
665 for(uint8_t i = 0; i < 8; ++i){
666 set_indicator_led_rgb(ktli(YUIOHJKL[i]), 2, 0, 255, 0);
667 }
668 set_indicator_led_rgb(ktli(KC_TAB), 2, 0, 255, 0);
669 set_indicator_led_rgb(ktli(KC_CAPS), 2, 0, 255, 0);
670 break;
671 }
672 360
673 refresh_pattern_indicators(); 361void reset_led_for_instruction(int led_instruction_index){
674 refresh_color_pattern_indicators(); 362 led_instructions[led_instruction_index].id0 = 0;
675 last_layer = layer; 363 led_instructions[led_instruction_index].id1 = 0;
364 led_instructions[led_instruction_index].id2 = 0;
365 led_instructions[led_instruction_index].id3 = 0;
366};
367void add_led_to_instruction(int led_instruction_index, int led_id){
368 if(32 >= led_id && led_id >= 1){
369 led_instructions[led_instruction_index].id0 += ( 1 << (led_id - 1) );
370 } else if(64 >= led_id){
371 led_instructions[led_instruction_index].id1 += ( 1 << (led_id - 33) );
372 } else if(96 >= led_id){
373 led_instructions[led_instruction_index].id2 += ( 1 << (led_id - 65) );
374 } else if(128 >= led_id){
375 led_instructions[led_instruction_index].id3 += ( 1 << (led_id - 97) );
676 } 376 }
377};
677 378
678 379
679 switch(layer){ 380void wave_effect(void);
680 case 0: 381void set_wave_color(int);
681 if(timer_elapsed32(scan_timer) > 2000){ 382// Runs constantly in the background, in a loop.
682 scan_timer = timer_read32(); 383void matrix_scan_user(void) {
683 } else if(timer_elapsed32(scan_timer) > 1000){ 384 wave_effect();
684 // set_user_led_rgb(ktli(KC_F5), 255, 255, 255); 385 set_wave_color(USER_CONFIG.PATTERN_INDEX);
685 }
686 break;
687 case 1:
688 break;
689 case 2:
690 break;
691 }
692
693}; 386};
694 387
388
695#define MODS_SHIFT (get_mods() & MOD_BIT(KC_LSHIFT) || get_mods() & MOD_BIT(KC_RSHIFT)) 389#define MODS_SHIFT (get_mods() & MOD_BIT(KC_LSHIFT) || get_mods() & MOD_BIT(KC_RSHIFT))
696#define MODS_CTRL (get_mods() & MOD_BIT(KC_LCTL) || get_mods() & MOD_BIT(KC_RCTRL)) 390#define MODS_CTRL (get_mods() & MOD_BIT(KC_LCTL) || get_mods() & MOD_BIT(KC_RCTRL))
697#define MODS_ALT (get_mods() & MOD_BIT(KC_LALT) || get_mods() & MOD_BIT(KC_RALT)) 391#define MODS_ALT (get_mods() & MOD_BIT(KC_LALT) || get_mods() & MOD_BIT(KC_RALT))
698 392
393void register_keystroke(uint16_t keycode){
394 if(get_led_info_by_scancode(keycode)->id){
395 uint32_t oldest_keystroke_lifespan = 0;
396 int8_t oldest_keystroke_index = -1;
397 bool registered = false;
398
399 keystroke_t *keystroke = ACTIVE_KEYSTROKES;
400 for(int i = 0; i < MAX_ACTIVE_KEYSTORKES; ++i){
401 if(!keystroke->active){
402 keystroke->scancode = keycode;
403 keystroke->timer = timer_read32();
404 keystroke->active = true;
405 registered = true;
406 break;
407 }
408
409 uint32_t lifespan = timer_elapsed32(keystroke->timer);
410 if(lifespan > oldest_keystroke_lifespan){
411 oldest_keystroke_index = i;
412 oldest_keystroke_lifespan = lifespan;
413 }
414
415 ++keystroke;
416 }
417
418 // override the oldest keystroke
419 if(!registered){
420 keystroke = ACTIVE_KEYSTROKES + oldest_keystroke_index;
421 keystroke->scancode = keycode;
422 keystroke->timer = timer_read32();
423 keystroke->active = true; // presumably active already
424 }
425 }
426}
427
699bool process_record_user(uint16_t keycode, keyrecord_t *record) { 428bool process_record_user(uint16_t keycode, keyrecord_t *record) {
700 static uint32_t key_timer; 429 static uint32_t key_timer;
701 430
702
703 switch (keycode) { 431 switch (keycode) {
704 case L_BRI: 432 case L_BRI:
705 if (record->event.pressed) { 433 if (record->event.pressed) {
@@ -777,11 +505,6 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
777 led_animation_direction = !led_animation_direction; 505 led_animation_direction = !led_animation_direction;
778 } 506 }
779 return false; 507 return false;
780 case U_T_AUTO:
781 if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
782 TOGGLE_FLAG_AND_PRINT(usb_extra_manual, "USB extra port manual mode");
783 }
784 return false;
785 case U_T_AGCR: 508 case U_T_AGCR:
786 if (record->event.pressed && MODS_SHIFT && MODS_CTRL) { 509 if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
787 TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode"); 510 TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode");
@@ -819,20 +542,16 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
819 542
820 543
821 544
545 case S_RESET:
546 // reset all parameters
822 547
548 USER_CONFIG.PATTERN_INDEX = 1;
549 USER_CONFIG.WAVE_WIDTH = 10;
550 USER_CONFIG.WAVE_SPEED = 15;
551 USER_CONFIG.COLOR_PATTERN_INDEX = 0;
552 USER_CONFIG.TRAVEL_DISTANCE = 25;
823 553
824 554 return false;
825
826
827
828
829
830
831
832
833
834
835
836 case L_SP_PR: // previous dripple pattern 555 case L_SP_PR: // previous dripple pattern
837 case L_SP_NE: // next dripple pattern 556 case L_SP_NE: // next dripple pattern
838 if (record->event.pressed) { 557 if (record->event.pressed) {
@@ -844,55 +563,53 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
844 if(USER_CONFIG.PATTERN_INDEX <= 4){ 563 if(USER_CONFIG.PATTERN_INDEX <= 4){
845 USER_CONFIG.TRAVEL_DISTANCE = 25; 564 USER_CONFIG.TRAVEL_DISTANCE = 25;
846 USER_CONFIG.COLOR_PATTERN_INDEX = 0; 565 USER_CONFIG.COLOR_PATTERN_INDEX = 0;
847 USER_CONFIG.WAVE_PERIOD = 50; 566 USER_CONFIG.WAVE_SPEED = 10;
848 } 567 }
849 568
850 switch(USER_CONFIG.PATTERN_INDEX){ 569 switch(USER_CONFIG.PATTERN_INDEX){
851 case 0: // None 570 case 0: // None
852 break; 571 break;
853 case 1: // background off, wave on 572 case 1: // background off, wave on
854 USER_CONFIG.WAVE_FRONT_WIDTH = 2; 573 USER_CONFIG.WAVE_WIDTH = 2;
855 break; 574 break;
856 case 2: // background on, wave off 575 case 2: // background on, wave off
857 USER_CONFIG.WAVE_FRONT_WIDTH = 5; 576 USER_CONFIG.WAVE_WIDTH = 5;
858 break; 577 break;
859 case 3: // background off, rainbow wave 578 case 3: // background off, rainbow wave
860 USER_CONFIG.WAVE_FRONT_WIDTH = 10; 579 USER_CONFIG.WAVE_WIDTH = 10;
861 break; 580 break;
862 case 4: // background on, rainbow wave 581 case 4: // background on, rainbow wave
863 USER_CONFIG.WAVE_FRONT_WIDTH = 10; 582 USER_CONFIG.WAVE_WIDTH = 10;
864 break; 583 break;
865 case 5: 584 case 5:
866 USER_CONFIG.WAVE_FRONT_WIDTH = 10; 585 USER_CONFIG.WAVE_WIDTH = 10;
867 586
868 USER_CONFIG.COLOR_PATTERN_INDEX = 2; 587 USER_CONFIG.COLOR_PATTERN_INDEX = 2;
869 USER_CONFIG.TRAVEL_DISTANCE = 0; 588 USER_CONFIG.TRAVEL_DISTANCE = 0;
870 USER_CONFIG.WAVE_PERIOD = 100; 589 USER_CONFIG.WAVE_SPEED = 10;
871 break; 590 break;
872 case 6: 591 case 6:
873 USER_CONFIG.WAVE_FRONT_WIDTH = 25; 592 USER_CONFIG.WAVE_WIDTH = 10;
874 593
875 USER_CONFIG.COLOR_PATTERN_INDEX = 3; 594 USER_CONFIG.COLOR_PATTERN_INDEX = 3;
876 USER_CONFIG.TRAVEL_DISTANCE = 2; 595 USER_CONFIG.TRAVEL_DISTANCE = 2;
877 USER_CONFIG.WAVE_PERIOD = 10; 596 USER_CONFIG.WAVE_SPEED = 10;
878 break; 597 break;
879 } 598 }
880 599
881 // remove effect after changing pattern 600 // remove effect after changing pattern
882 for(int i = 0; i < KEY_STROKES_LENGTH; ++i){ 601 for(int i = 0; i < MAX_ACTIVE_KEYSTORKES; ++i){
883 KEY_STROKES[i].alive = 0; 602 ACTIVE_KEYSTROKES[i].active = 0;
884 } 603 }
885 refresh_pattern_indicators();
886 refresh_color_pattern_indicators();
887 } 604 }
888 return false; 605 return false;
889 case L_SP_WD: 606 case L_SP_WD:
890 case L_SP_NW: 607 case L_SP_NW:
891 if(record->event.pressed){ 608 if(record->event.pressed){
892 short incre = keycode == L_SP_WD ? 1 : -1; 609 short incre = keycode == L_SP_WD ? 1 : -1;
893 USER_CONFIG.WAVE_FRONT_WIDTH += incre; 610 USER_CONFIG.WAVE_WIDTH += incre;
894 if(USER_CONFIG.WAVE_FRONT_WIDTH < 1){ 611 if(USER_CONFIG.WAVE_WIDTH < 1){
895 USER_CONFIG.WAVE_FRONT_WIDTH = 1; 612 USER_CONFIG.WAVE_WIDTH = 1;
896 } 613 }
897 } 614 }
898 return false; 615 return false;
@@ -901,9 +618,11 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
901 if(record->event.pressed){ 618 if(record->event.pressed){
902 short incre = keycode == L_SP_FA ? -1 : 1; 619 short incre = keycode == L_SP_FA ? -1 : 1;
903 620
904 USER_CONFIG.WAVE_PERIOD += 10 * incre; 621 USER_CONFIG.WAVE_SPEED += incre;
905 if(USER_CONFIG.WAVE_PERIOD < 10){ 622 if(USER_CONFIG.WAVE_SPEED > 50){
906 USER_CONFIG.WAVE_PERIOD = 10; 623 USER_CONFIG.WAVE_SPEED = 50;
624 } else if(USER_CONFIG.WAVE_SPEED < 1){
625 USER_CONFIG.WAVE_SPEED = 1;
907 } 626 }
908 } 627 }
909 return false; 628 return false;
@@ -914,23 +633,135 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
914 uint8_t incre = keycode == L_CP_PR ? COLOR_PATTERNS_COUNT - 1 : 1; 633 uint8_t incre = keycode == L_CP_PR ? COLOR_PATTERNS_COUNT - 1 : 1;
915 USER_CONFIG.COLOR_PATTERN_INDEX += incre; 634 USER_CONFIG.COLOR_PATTERN_INDEX += incre;
916 USER_CONFIG.COLOR_PATTERN_INDEX %= COLOR_PATTERNS_COUNT; 635 USER_CONFIG.COLOR_PATTERN_INDEX %= COLOR_PATTERNS_COUNT;
917 refresh_color_pattern_indicators(); 636 set_wave_color(USER_CONFIG.COLOR_PATTERN_INDEX);
918 } 637 }
919 return false; 638 return false;
639
920 default: 640 default:
921 if (record->event.pressed){ 641
922 uint8_t led_id = ktli(keycode); 642
923 if(led_id){ 643 if(record->event.pressed){
924 for(int i = 0; i < KEY_STROKES_LENGTH; ++i){ 644 register_keystroke(keycode);
925 if(!KEY_STROKES[i].alive){ 645
926 KEY_STROKES[i].alive = 1; 646#ifdef CONSOLE_ENABLE
927 KEY_STROKES[i].led_id = led_id; 647 led_info_t *entry = get_led_info_by_scancode(keycode);
928 KEY_STROKES[i].time = timer_read32(); 648 uprintf(("KL: kc: %u, led id: %u, x: %f, y: %f, "
929 break; 649 "col: %u, row: %u, pressed: %u, time: %u\n"),
930 } 650 keycode, entry->id, entry->x, entry->y,
931 } 651 record->event.key.col, record->event.key.row,
932 } 652 record->event.pressed, record->event.time);
653#endif
933 } 654 }
934 return true; //Process all other keycodes normally 655 return true; //Process all other keycodes normally
935 } 656 }
936} 657}
658
659led_instruction_t led_instructions[] = {
660 //LEDs are normally inactive, no processing is performed on them
661 //Flags are used in matching criteria for an LED to be active and indicate how to color it
662 //Flags can be found in tmk_core/protocol/arm_atsam/led_matrix.h (prefixed with LED_FLAG_)
663 //LED IDs can be found in config_led.h in the keyboard's directory
664 //Examples are below
665
666 //All LEDs use the user's selected pattern (this is the factory default)
667 { .flags = LED_FLAG_USE_ROTATE_PATTERN },
668
669 //Specific LEDs use the user's selected pattern while all others are off
670 // { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_ROTATE_PATTERN, .id0 = 0xFFFFFFFF, .id1 = 0xAAAAAAAA, .id2 = 0x55555555, .id3 = 0x11111111 },
671
672 //Specific LEDs use specified RGB values while all others are off
673 // { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0xFF, .id1 = 0x00FF, .id2 = 0x0000FF00, .id3 = 0xFF000000, .r = 75, .g = 150, .b = 225 },
674
675 //All LEDs use the user's selected pattern
676 //On layer 1, all key LEDs (except the top row which keeps active pattern) are red while all edge LEDs are green
677 //When layer 1 is active, key LEDs use red (id0 32 - 17: 1111 1111 1111 1111 0000 0000 0000 0000 = 0xFFFF0000) (except top row 16 - 1)
678 //When layer 1 is active, key LEDs use red (id1 64 - 33: 1111 1111 1111 1111 1111 1111 1111 1111 = 0xFFFFFFFF)
679 //When layer 1 is active, key LEDs use red (id2 87 - 65: 0000 0000 0111 1111 1111 1111 1111 1111 = 0x007FFFFF)
680 //When layer 1 is active, edge LEDs use green (id2 95 - 88: 1111 1111 1000 0000 0000 0000 0000 0000 = 0xFF800000)
681 //When layer 1 is active, edge LEDs use green (id3 119 - 96: 0000 0000 1111 1111 1111 1111 1111 1111 = 0x00FFFFFF)
682 // { .flags = LED_FLAG_USE_ROTATE_PATTERN },
683
684 #define WAVE_LED_INSTRUCTION_START 1
685 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0, .id1 = 0, .id2 = 0, .g = 255 },
686 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0, .id1 = 0, .id2 = 0, .g = 255 },
687 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0, .id1 = 0, .id2 = 0, .g = 255 },
688 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0, .id1 = 0, .id2 = 0, .g = 255 },
689 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0, .id1 = 0, .id2 = 0, .g = 255 },
690 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0, .id1 = 0, .id2 = 0, .g = 255 },
691 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0, .id1 = 0, .id2 = 0, .g = 255 },
692 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0, .id1 = 0, .id2 = 0, .g = 255 },
693 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0, .id1 = 0, .id2 = 0, .g = 255 },
694 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0, .id1 = 0, .id2 = 0, .g = 255 },
695 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0, .id1 = 0, .id2 = 0, .g = 255 },
696 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0, .id1 = 0, .id2 = 0, .g = 255 },
697 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0, .id1 = 0, .id2 = 0, .g = 255 },
698 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0, .id1 = 0, .id2 = 0, .g = 255 },
699 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0, .id1 = 0, .id2 = 0, .g = 255 },
700 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0, .id1 = 0, .id2 = 0, .g = 255 },
701 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0, .id1 = 0, .id2 = 0, .g = 255 },
702 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0, .id1 = 0, .id2 = 0, .g = 255 },
703 #define WAVE_LED_INSTRUCTION_END 18
704
705 //All key LEDs use red while edge LEDs use the active pattern
706 //All key LEDs use red (id0 32 - 1: 1111 1111 1111 1111 1111 1111 1111 1111 = 0xFFFFFFFF)
707 //All key LEDs use red (id1 64 - 33: 1111 1111 1111 1111 1111 1111 1111 1111 = 0xFFFFFFFF)
708 //All key LEDs use red (id2 87 - 65: 0000 0000 0111 1111 1111 1111 1111 1111 = 0x007FFFFF)
709 //Edge uses active pattern (id2 95 - 88: 1111 1111 1000 0000 0000 0000 0000 0000 = 0xFF800000)
710 //Edge uses active pattern (id3 119 - 96: 0000 0000 1111 1111 1111 1111 1111 1111 = 0x00FFFFFF)
711 // { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB, .id0 = 0xFFFFFFFF, .id1 = 0xFFFFFFFF, .id2 = 0x007FFFFF, .r = 255 },
712 // { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_ROTATE_PATTERN , .id2 = 0xFF800000, .id3 = 0x00FFFFFF },
713
714 { .flags = LED_FLAG_MATCH_ID | LED_FLAG_USE_RGB | LED_FLAG_MATCH_LAYER,
715 .id1 = 0b00001111001111000000011110011110,
716 .r = 0, .g = 255, .b = 60, .layer = 2 },
717
718 //end must be set to 1 to indicate end of instruction set
719 { .end = 1 }
720};
721
722
723void set_wave_color(int color_pattern_index){
724 for(int i = WAVE_LED_INSTRUCTION_START; i < WAVE_LED_INSTRUCTION_END; ++i){
725 for(int j = 0; j < COLOR_PATTERN_RGB_COUNT; ++j){
726 led_instructions[i].r = COLOR_PATTERNS[color_pattern_index][i][0];
727 led_instructions[i].g = COLOR_PATTERNS[color_pattern_index][i][1];
728 led_instructions[i].b = COLOR_PATTERNS[color_pattern_index][i][2];
729 }
730 }
731};
732
733void wave_effect(void){
734 for(int i = WAVE_LED_INSTRUCTION_START; i < WAVE_LED_INSTRUCTION_END; ++i){
735 reset_led_for_instruction(i);
736 }
737 int wave_led_instruction_span = WAVE_LED_INSTRUCTION_END - WAVE_LED_INSTRUCTION_START;
738
739
740 keystroke_t *keystroke = ACTIVE_KEYSTROKES;
741 for(int i = 0; i < MAX_ACTIVE_KEYSTORKES; ++i, ++keystroke){
742 if(!keystroke->active) continue;
743 bool active = false;
744
745 uint16_t keystroke_led_id = get_led_info_by_scancode(keystroke->scancode)->id;
746
747 float elapsed_s = timer_elapsed32(keystroke->timer) / 1000.0f;
748 float travel = elapsed_s * USER_CONFIG.WAVE_SPEED;
749
750 for(uint16_t id = 1; id <= MAX_LED_ID; ++id){
751 float normalized_distance =
752 led_info[id].distance_to[keystroke_led_id] /
753 (float)DISTANCE_NORAMLIZING_PARAMETER;
754
755 if(travel >= normalized_distance && travel - normalized_distance >= 0 &&
756 normalized_distance >= travel - USER_CONFIG.WAVE_WIDTH){
757 int portion = (travel - normalized_distance) *
758 wave_led_instruction_span / USER_CONFIG.WAVE_WIDTH;
759 add_led_to_instruction(portion, id);
760
761 active = true;
762 }
763 }
764
765 keystroke->active = active;
766 }
767};