#include QMK_KEYBOARD_H // uint8_t keyboard_leds(void) #include #if ISSI3733_LED_COUNT == 119 # define KEY_LED_COUNT 87 #elif ISSI3733_LED_COUNT == 105 # define KEY_LED_COUNT 67 #endif #define min(x, y) (x < y ? x : y) extern issi3733_led_t *lede; extern issi3733_led_t led_map[]; enum ctrl_keycodes { L_BRI = SAFE_RANGE, //LED Brightness Increase L_BRD, //LED Brightness Decrease L_PTN, //LED Pattern Select Next L_PTP, //LED Pattern Select Previous L_PSI, //LED Pattern Speed Increase L_PSD, //LED Pattern Speed Decrease L_T_MD, //LED Toggle Mode L_T_ONF, //LED Toggle On / Off L_ON, //LED On L_OFF, //LED Off L_T_BR, //LED Toggle Breath Effect L_T_PTD, //LED Toggle Scrolling Pattern Direction U_T_AUTO, //USB Extra Port Toggle Auto Detect / Always Active U_T_AGCR, //USB Toggle Automatic GCR control DBG_TOG, //DEBUG Toggle On / Off DBG_MTRX, //DEBUG Toggle Matrix Prints DBG_KBD, //DEBUG Toggle Keyboard Prints DBG_MOU, //DEBUG Toggle Mouse Prints MD_BOOT, //Restart into bootloader after hold timeout L_SP_PR, //LED Splash Pattern Select Previous L_SP_NE, //LED Splash Pattern Select Next L_SP_WD, //LED Splash Widen Wavefront width L_SP_NW, //LED Splash Narrow Wavefront width L_SP_FA, //LED Splash wave travel speed faster (shorter period) L_SP_SL, //LED Splash wave travel speed slower (longer period) L_CP_PR, //LED Color Pattern Select Previous L_CP_NX, //LEB Color Pattern Select Next }; #define TG_NKRO MAGIC_TOGGLE_NKRO //Toggle 6KRO / NKRO mode #define ______ KC_TRNS keymap_config_t keymap_config; const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [0] = LAYOUT( KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR, KC_SLCK, KC_PAUS, \ 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_INS, KC_HOME, KC_PGUP, \ 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_DEL, KC_END, KC_PGDN, \ 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_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, \ KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_APP, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT \ ), [1] = LAYOUT( _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MUTE, _______, _______, \ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_MPLY, KC_MSTP, KC_VOLU, \ L_T_BR, L_PSD, L_BRI, L_PSI, _______, _______, _______, U_T_AUTO,U_T_AGCR,_______, MO(2), _______, _______, _______, KC_MPRV, KC_MNXT, KC_VOLD, \ L_T_PTD, L_PTP, L_BRD, L_PTN, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ _______, L_T_MD, L_T_ONF, _______, _______, MD_BOOT, TG_NKRO, _______, _______, _______, _______, _______, _______, \ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \ ), [2] = LAYOUT( _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ L_CP_NX, L_SP_SL, L_SP_WD, L_SP_FA, _______, _______, L_CP_NX, L_SP_SL, L_SP_WD, L_SP_FA, _______, _______, _______, _______, _______, _______, _______, \ L_CP_PR, L_SP_PR, L_SP_NW, L_SP_NE, _______, _______, L_CP_PR, L_SP_PR, L_SP_NW, L_SP_NE, _______, _______, _______, \ _______, _______, _______, _______, _______, _______, TG_NKRO, _______, _______, _______, _______, _______, _______, \ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \ ), /* [X] = LAYOUT( _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ _______, _______, _______, _______, _______, _______, TG_NKRO, _______, _______, _______, _______, _______, _______, \ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \ ), */ }; // see: /tmk_core/common/keycode.h uint8_t KEYCODE_TO_LED_ID[256]; uint8_t DISTANCE_MAP[KEY_LED_COUNT+1][KEY_LED_COUNT+1]; struct user_led_t { uint8_t state; uint8_t r; uint8_t g; uint8_t b; } USER_LED[KEY_LED_COUNT] = { }; struct { uint8_t PATTERN_INDEX; uint8_t WAVE_FRONT_WIDTH; uint16_t WAVE_PERIOD; uint8_t COLOR_PATTERN_INDEX; uint8_t TRAVEL_DISTANCE; } USER_CONFIG = { .PATTERN_INDEX = 1, .WAVE_FRONT_WIDTH = 3, .WAVE_PERIOD = 50, .COLOR_PATTERN_INDEX = 0, .TRAVEL_DISTANCE = 25, }; uint8_t ktli(uint16_t keycode){ if(keycode < 256){ // the array is initialized in `matrix_init_user()` return KEYCODE_TO_LED_ID[keycode]; } switch(keycode){ // definition of MO(layer): quantum/quantum_keycodes.h: line 614 case MO(1): return 82; } return 0; }; // Runs just one time when the keyboard initializes. static void init_keycode_to_led_map(void){ uint16_t LED_MAP[MATRIX_ROWS][MATRIX_COLS] = LAYOUT( 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, 20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35, 36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51, 52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67, #if KEY_LED_COUNT >= 87 68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87 #endif ); uint16_t key = 0; for(uint8_t y = 0; y < MATRIX_ROWS; ++y){ for(uint8_t x = 0; x < MATRIX_COLS; ++x){ key = keymaps[0][y][x]; if(key < 256){ KEYCODE_TO_LED_ID[key] = LED_MAP[y][x]; } } } } // https://docs.qmk.fm/#/feature_terminal #define KEY_POSITION_MAP_ROWS 6 #define KEY_POSITION_MAP_COLUMNS 20 static void init_distance_map(void){ uint16_t KEY_POSITION_MAP[KEY_POSITION_MAP_ROWS][KEY_POSITION_MAP_COLUMNS] = { { 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, }, // { 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, }, { 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, }, { 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, }, { 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, }, { 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, }, { 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, }, }; uint8_t columns = KEY_POSITION_MAP_COLUMNS; uint8_t rows = KEY_POSITION_MAP_ROWS; for(uint8_t y = 0; y < rows; ++y){ for(uint8_t x = 0; x < columns; ++x){ uint8_t id1 = ktli(KEY_POSITION_MAP[y][x]); for(uint8_t j = y; j < rows; ++j){ for(uint8_t i = 0; i < columns; ++i){ uint8_t id2 = ktli(KEY_POSITION_MAP[j][i]); if(id1 == id2) continue; uint8_t dx = abs(i - x); uint8_t dy = abs(j - y); uint8_t dis = dx + dy; if(i < x && j > y){ dis -= min(dx, dy); } uint8_t _dis = DISTANCE_MAP[id1][id2]; if(_dis && _dis <= dis) continue; DISTANCE_MAP[id1][id2] = dis; DISTANCE_MAP[id2][id1] = dis; } } } } } void matrix_init_user(void) { init_keycode_to_led_map(); init_distance_map(); }; // /tmk_core/protocol/arm_atsam/led_matrix.c: line 244 uint8_t led_enabled; float led_animation_speed; uint8_t led_animation_direction; uint8_t led_animation_orientation; uint8_t led_animation_breathing; uint8_t led_animation_breathe_cur; uint8_t breathe_step; uint8_t breathe_dir; uint64_t led_next_run; uint8_t led_animation_id; uint8_t led_lighting_mode; issi3733_led_t *led_cur; uint8_t led_per_run; float breathe_mult; // overrided /tmk_core/protocol/arm_atsam/led_matrix.c: line 484 void rgb_matrix_init_user(void){ led_animation_speed = ANIMATION_SPEED_STEP * 15; led_per_run = 15; } // overrided /tmk_core/protocol/arm_atsam/led_matrix.c: line 262 void led_matrix_run(void) { float ro; float go; float bo; float po; uint8_t led_this_run = 0; led_setup_t *f = (led_setup_t*)led_setups[led_animation_id]; if (led_cur == 0) //Denotes start of new processing cycle in the case of chunked processing { led_cur = led_map; breathe_mult = 1; if (led_animation_breathing) { led_animation_breathe_cur += breathe_step * breathe_dir; if (led_animation_breathe_cur >= BREATHE_MAX_STEP) breathe_dir = -1; else if (led_animation_breathe_cur <= BREATHE_MIN_STEP) breathe_dir = 1; //Brightness curve created for 256 steps, 0 - ~98% breathe_mult = 0.000015 * led_animation_breathe_cur * led_animation_breathe_cur; if (breathe_mult > 1) breathe_mult = 1; else if (breathe_mult < 0) breathe_mult = 0; } } uint8_t fcur = 0; uint8_t fmax = 0; //Frames setup while (f[fcur].end != 1) { fcur++; //Count frames } fmax = fcur; //Store total frames count struct user_led_t user_led_cur; while (led_cur < lede && led_this_run < led_per_run) { ro = 0; go = 0; bo = 0; uint8_t led_index = led_cur - led_map; // only this part differs from the original function. if(led_index < KEY_LED_COUNT){ // user_led_cur = USER_LED[led_index]; // `struct user_led_t USER_LED[]` is stored globally. } // // if(led_index < KEY_LED_COUNT && user_led_cur.state){ // `user_led_cur` is just for convenience ro = user_led_cur.r; // go = user_led_cur.g; // bo = user_led_cur.b; // } // else if (led_lighting_mode == LED_MODE_KEYS_ONLY && led_cur->scan == 255) { //Do not act on this LED } else if (led_lighting_mode == LED_MODE_NON_KEYS_ONLY && led_cur->scan != 255) { //Do not act on this LED } else if (led_lighting_mode == LED_MODE_INDICATORS_ONLY) { //Do not act on this LED (Only show indicators) } else { //Act on LED for (fcur = 0; fcur < fmax; fcur++) { if (led_animation_orientation) { po = led_cur->py; } else { po = led_cur->px; } float pomod; pomod = (float)(g_tick % (uint32_t)(1000.0f / led_animation_speed)) / 10.0f * led_animation_speed; //Add in any moving effects if ((!led_animation_direction && f[fcur].ef & EF_SCR_R) || (led_animation_direction && (f[fcur].ef & EF_SCR_L))) { pomod *= 100.0f; pomod = (uint32_t)pomod % 10000; pomod /= 100.0f; po -= pomod; if (po > 100) po -= 100; else if (po < 0) po += 100; } else if ((!led_animation_direction && f[fcur].ef & EF_SCR_L) || (led_animation_direction && (f[fcur].ef & EF_SCR_R))) { pomod *= 100.0f; pomod = (uint32_t)pomod % 10000; pomod /= 100.0f; po += pomod; if (po > 100) po -= 100; else if (po < 0) po += 100; } //Check if LED's po is in current frame if (po < f[fcur].hs) continue; if (po > f[fcur].he) continue; //note: < 0 or > 100 continue //Calculate the po within the start-stop percentage for color blending po = (po - f[fcur].hs) / (f[fcur].he - f[fcur].hs); //Add in any color effects if (f[fcur].ef & EF_OVER) { ro = (po * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5; go = (po * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5; bo = (po * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5; } else if (f[fcur].ef & EF_SUBTRACT) { ro -= (po * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5; go -= (po * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5; bo -= (po * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5; } else { ro += (po * (f[fcur].re - f[fcur].rs)) + f[fcur].rs;// + 0.5; go += (po * (f[fcur].ge - f[fcur].gs)) + f[fcur].gs;// + 0.5; bo += (po * (f[fcur].be - f[fcur].bs)) + f[fcur].bs;// + 0.5; } } } //Clamp values 0-255 if (ro > 255) ro = 255; else if (ro < 0) ro = 0; if (go > 255) go = 255; else if (go < 0) go = 0; if (bo > 255) bo = 255; else if (bo < 0) bo = 0; if (led_animation_breathing) { ro *= breathe_mult; go *= breathe_mult; bo *= breathe_mult; } *led_cur->rgb.r = (uint8_t)ro; *led_cur->rgb.g = (uint8_t)go; *led_cur->rgb.b = (uint8_t)bo; #ifdef USB_LED_INDICATOR_ENABLE if (keyboard_leds()) { uint8_t kbled = keyboard_leds(); if ( #if USB_LED_NUM_LOCK_SCANCODE != 255 (led_cur->scan == USB_LED_NUM_LOCK_SCANCODE && kbled & (1<scan == USB_LED_CAPS_LOCK_SCANCODE && kbled & (1<scan == USB_LED_SCROLL_LOCK_SCANCODE && kbled & (1<scan == USB_LED_COMPOSE_SCANCODE && kbled & (1<scan == USB_LED_KANA_SCANCODE && kbled & (1<rgb.r > 127) *led_cur->rgb.r = 0; else *led_cur->rgb.r = 255; if (*led_cur->rgb.g > 127) *led_cur->rgb.g = 0; else *led_cur->rgb.g = 255; if (*led_cur->rgb.b > 127) *led_cur->rgb.b = 0; else *led_cur->rgb.b = 255; } } #endif //USB_LED_INDICATOR_ENABLE led_cur++; led_this_run++; } } #define KEY_STROKES_LENGTH 20 struct { bool alive; uint8_t led_id; uint32_t time; } KEY_STROKES[KEY_STROKES_LENGTH] = {{}}; void set_led_rgb(uint8_t led_id, uint8_t r, uint8_t g, uint8_t b){ issi3733_led_t *target_led = (led_map + led_id); *target_led->rgb.r = r; *target_led->rgb.g = g; *target_led->rgb.b = b; } uint8_t DISTANCE_FROM_LAST_KEYSTROKE[KEY_LED_COUNT+1]; void calculate_keystroke_distance(void){ bool alive; uint8_t led_id, period_passed; uint32_t t; for(uint8_t i = 0; i <= KEY_LED_COUNT; ++i){ DISTANCE_FROM_LAST_KEYSTROKE[i] = 0; } for(uint8_t i = 0; i < KEY_STROKES_LENGTH; ++i){ if(KEY_STROKES[i].alive){ t = timer_elapsed32(KEY_STROKES[i].time); alive = 0; led_id = KEY_STROKES[i].led_id; period_passed = t / USER_CONFIG.WAVE_PERIOD; uint8_t delta_period; for(uint8_t j = 1; j <= KEY_LED_COUNT; ++j){ delta_period = period_passed - DISTANCE_MAP[led_id][j]; if(( delta_period < USER_CONFIG.WAVE_FRONT_WIDTH) && ( DISTANCE_MAP[led_id][j] <= USER_CONFIG.TRAVEL_DISTANCE )){ switch(USER_CONFIG.PATTERN_INDEX){ case 3: case 4: case 5: case 6: DISTANCE_FROM_LAST_KEYSTROKE[j] += delta_period; break; default: DISTANCE_FROM_LAST_KEYSTROKE[j] = 1; break; } alive = 1; } } KEY_STROKES[i].alive = alive; } } } #define COLOR_PATTERN_RGB_COUNT 18 static uint8_t COLOR_PATTERNS[][COLOR_PATTERN_RGB_COUNT][3] = { { // default rainbow color {255, 0, 0}, {255, 0, 0}, {255, 127, 0}, {255, 127, 0}, {255, 255, 0}, {255, 255, 0}, {120, 255, 0}, {120, 255, 0}, { 0, 255, 0}, { 0, 255, 0}, { 0, 255, 120}, { 0, 255, 120}, { 0, 0, 255}, { 0, 0, 255}, { 75, 0, 130}, { 75, 0, 130}, { 43, 0, 130}, { 43, 0, 130}, }, { // light rainbow color {248, 12, 18}, {238, 17, 0}, {255, 51, 17}, {255, 68, 32}, {255, 102, 68}, {255, 153, 51}, {254, 174, 45}, {204, 187, 51}, {208, 195, 16}, {170, 204, 34}, {105, 208, 37}, { 34, 204, 170}, { 18, 189, 185}, { 17, 170, 187}, { 68, 68, 221}, { 51, 17, 187}, { 59, 12, 189}, { 68, 34, 153}, }, { // white flat {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, }, { // white fade, cos curve {255, 255, 255}, {255, 255, 255}, {252, 252, 252}, {247, 247, 247}, {240, 240, 240}, {232, 232, 232}, {221, 221, 221}, {209, 209, 209}, {196, 196, 196}, {181, 181, 181}, {164, 164, 164}, {147, 147, 147}, {128, 128, 128}, {108, 108, 108}, { 88, 88, 88}, { 66, 66, 66}, { 45, 45, 45}, { 23, 23, 23}, }, }; static const uint8_t COLOR_PATTERNS_COUNT = ( sizeof(COLOR_PATTERNS) / sizeof(COLOR_PATTERNS[0])); void set_user_led_rgb(uint8_t i, uint8_t r, uint8_t g, uint8_t b){ USER_LED[i-1].state = 1; USER_LED[i-1].r = r; USER_LED[i-1].g = g; USER_LED[i-1].b = b; } void unset_user_led_rgb(uint8_t i){ USER_LED[i-1].state = 0; } void set_indicator_led_rgb(uint8_t i, uint8_t layer, uint8_t r, uint8_t g, uint8_t b){ USER_LED[i-1].state |= 1 << layer; USER_LED[i-1].r = r; USER_LED[i-1].g = g; USER_LED[i-1].b = b; } void unset_indicator_led_rgb(uint8_t i, uint8_t layer){ USER_LED[i-1].state &= ~(1 << layer); } void refresh_pattern_indicators(void){ static uint8_t GRV_123456[] = { KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, }; if(layer_state >= 0x04){ for(uint8_t i = 0; i < 7; ++i){ if(i == USER_CONFIG.PATTERN_INDEX){ set_indicator_led_rgb(ktli(GRV_123456[i]), 2, 0, 0, 255); } else{ set_indicator_led_rgb(ktli(GRV_123456[i]), 2, 0, 255, 0); } } } else{ for(uint8_t i = 0; i < 7; ++i){ unset_indicator_led_rgb(ktli(GRV_123456[i]), 2); } } } void refresh_color_pattern_indicators(void){ static uint8_t ZXCVBNM_COMM_DOT[] = { KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, }; if(layer_state >= 0x04){ uint8_t (*c)[3] = &COLOR_PATTERNS[USER_CONFIG.COLOR_PATTERN_INDEX][0]; for(uint8_t i = 0; i < 9; ++i){ set_indicator_led_rgb(ktli(ZXCVBNM_COMM_DOT[i]), 2, c[i][0], c[i][1], c[i][2]); } } else{ for(uint8_t i = 0; i < 9; ++i){ unset_indicator_led_rgb(ktli(ZXCVBNM_COMM_DOT[i]), 2); } } } // Runs constantly in the background, in a loop. void matrix_scan_user(void) { static uint32_t scan_timer = 0; static uint8_t last_layer = 0; uint8_t layer = 0; if(layer_state >= 0x04){ layer = 2; } else if(layer_state >= 0x02){ layer = 1; } calculate_keystroke_distance(); #define USE_PATTERN 0 #define BLACK_RGB 1 #define COLOR_RGB 2 uint8_t ci; // color index uint8_t *rgb; uint8_t handle_type; uint8_t distance; for(uint8_t i = 1; i <= KEY_LED_COUNT; ++i){ if(USER_LED[i-1].state >= 2) continue; handle_type = USE_PATTERN; distance = DISTANCE_FROM_LAST_KEYSTROKE[i]; switch(USER_CONFIG.PATTERN_INDEX){ case 0: handle_type = USE_PATTERN; break; case 1: handle_type = distance ? USE_PATTERN : BLACK_RGB; break; case 2: handle_type = distance ? BLACK_RGB : USE_PATTERN; break; case 3: handle_type = distance ? COLOR_RGB : BLACK_RGB; break; case 4: handle_type = distance ? COLOR_RGB : USE_PATTERN; break; case 5: case 6: handle_type = distance ? COLOR_RGB : USE_PATTERN; break; } switch(handle_type){ case USE_PATTERN: unset_user_led_rgb(i); break; case BLACK_RGB: set_user_led_rgb(i, 0, 0, 0); break; case COLOR_RGB: ci = (DISTANCE_FROM_LAST_KEYSTROKE[i] * COLOR_PATTERN_RGB_COUNT / USER_CONFIG.WAVE_FRONT_WIDTH) % COLOR_PATTERN_RGB_COUNT; rgb = &COLOR_PATTERNS[USER_CONFIG.COLOR_PATTERN_INDEX][ci][0]; set_user_led_rgb(i, rgb[0], rgb[1], rgb[2]); break; } } // could be moved to process_record_user() if(layer != last_layer){ static uint8_t QWEASDP[] = { KC_Q, KC_W, KC_E, KC_A, KC_S, KC_D, KC_P, }; static uint8_t YUIOHJKL[] = { KC_Y, KC_U, KC_I, KC_O, KC_H, KC_J, KC_K, KC_L, }; switch(last_layer){ case 1: for(uint8_t i = 0; i < 7; ++i){ unset_indicator_led_rgb(ktli(QWEASDP[i]), 1); } break; case 2: for(uint8_t i = 0; i < 6; ++i){ unset_indicator_led_rgb(ktli(QWEASDP[i]), 2); } for(uint8_t i = 0; i < 8; ++i){ unset_indicator_led_rgb(ktli(YUIOHJKL[i]), 2); } unset_indicator_led_rgb(ktli(KC_TAB), 2); unset_indicator_led_rgb(ktli(KC_CAPS), 2); break; } switch(layer){ case 1: for(uint8_t i = 0; i < 7; ++i){ set_indicator_led_rgb(ktli(QWEASDP[i]), 1, 255, 0, 0); } break; case 2: for(uint8_t i = 0; i < 6; ++i){ set_indicator_led_rgb(ktli(QWEASDP[i]), 2, 0, 255, 0); } for(uint8_t i = 0; i < 8; ++i){ set_indicator_led_rgb(ktli(YUIOHJKL[i]), 2, 0, 255, 0); } set_indicator_led_rgb(ktli(KC_TAB), 2, 0, 255, 0); set_indicator_led_rgb(ktli(KC_CAPS), 2, 0, 255, 0); break; } refresh_pattern_indicators(); refresh_color_pattern_indicators(); last_layer = layer; } switch(layer){ case 0: if(timer_elapsed32(scan_timer) > 2000){ scan_timer = timer_read32(); } else if(timer_elapsed32(scan_timer) > 1000){ // set_user_led_rgb(ktli(KC_F5), 255, 255, 255); } break; case 1: break; case 2: break; } }; #define MODS_SHIFT (get_mods() & MOD_BIT(KC_LSHIFT) || get_mods() & MOD_BIT(KC_RSHIFT)) #define MODS_CTRL (get_mods() & MOD_BIT(KC_LCTL) || get_mods() & MOD_BIT(KC_RCTRL)) #define MODS_ALT (get_mods() & MOD_BIT(KC_LALT) || get_mods() & MOD_BIT(KC_RALT)) bool process_record_user(uint16_t keycode, keyrecord_t *record) { static uint32_t key_timer; switch (keycode) { case L_BRI: if (record->event.pressed) { if (LED_GCR_STEP > LED_GCR_MAX - gcr_desired) gcr_desired = LED_GCR_MAX; else gcr_desired += LED_GCR_STEP; if (led_animation_breathing) gcr_breathe = gcr_desired; } return false; case L_BRD: if (record->event.pressed) { if (LED_GCR_STEP > gcr_desired) gcr_desired = 0; else gcr_desired -= LED_GCR_STEP; if (led_animation_breathing) gcr_breathe = gcr_desired; } return false; case L_PTN: if (record->event.pressed) { if (led_animation_id == led_setups_count - 1) led_animation_id = 0; else led_animation_id++; } return false; case L_PTP: if (record->event.pressed) { if (led_animation_id == 0) led_animation_id = led_setups_count - 1; else led_animation_id--; } return false; case L_PSI: if (record->event.pressed) { led_animation_speed += ANIMATION_SPEED_STEP; } return false; case L_PSD: if (record->event.pressed) { led_animation_speed -= ANIMATION_SPEED_STEP; if (led_animation_speed < 0) led_animation_speed = 0; } return false; case L_T_MD: if (record->event.pressed) { led_lighting_mode++; if (led_lighting_mode > LED_MODE_MAX_INDEX) led_lighting_mode = LED_MODE_NORMAL; } return false; case L_T_ONF: if (record->event.pressed) { led_enabled = !led_enabled; I2C3733_Control_Set(led_enabled); } return false; case L_ON: if (record->event.pressed) { led_enabled = 1; I2C3733_Control_Set(led_enabled); } return false; case L_OFF: if (record->event.pressed) { led_enabled = 0; I2C3733_Control_Set(led_enabled); } return false; case L_T_BR: if (record->event.pressed) { led_animation_breathing = !led_animation_breathing; if (led_animation_breathing) { gcr_breathe = gcr_desired; led_animation_breathe_cur = BREATHE_MIN_STEP; breathe_dir = 1; } } return false; case L_T_PTD: if (record->event.pressed) { led_animation_direction = !led_animation_direction; } return false; case U_T_AUTO: if (record->event.pressed && MODS_SHIFT && MODS_CTRL) { TOGGLE_FLAG_AND_PRINT(usb_extra_manual, "USB extra port manual mode"); } return false; case U_T_AGCR: if (record->event.pressed && MODS_SHIFT && MODS_CTRL) { TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode"); } return false; case DBG_TOG: if (record->event.pressed) { TOGGLE_FLAG_AND_PRINT(debug_enable, "Debug mode"); } return false; case DBG_MTRX: if (record->event.pressed) { TOGGLE_FLAG_AND_PRINT(debug_matrix, "Debug matrix"); } return false; case DBG_KBD: if (record->event.pressed) { TOGGLE_FLAG_AND_PRINT(debug_keyboard, "Debug keyboard"); } return false; case DBG_MOU: if (record->event.pressed) { TOGGLE_FLAG_AND_PRINT(debug_mouse, "Debug mouse"); } return false; case MD_BOOT: if (record->event.pressed) { key_timer = timer_read32(); } else { if (timer_elapsed32(key_timer) >= 500) { reset_keyboard(); } } return false; case L_SP_PR: // previous dripple pattern case L_SP_NE: // next dripple pattern if (record->event.pressed) { #define PATTERN_COUNT 7 uint8_t incre = keycode == L_SP_PR ? PATTERN_COUNT-1 : 1; USER_CONFIG.PATTERN_INDEX += incre; USER_CONFIG.PATTERN_INDEX %= PATTERN_COUNT; if(USER_CONFIG.PATTERN_INDEX <= 4){ USER_CONFIG.TRAVEL_DISTANCE = 25; USER_CONFIG.COLOR_PATTERN_INDEX = 0; USER_CONFIG.WAVE_PERIOD = 50; } switch(USER_CONFIG.PATTERN_INDEX){ case 0: // None break; case 1: // background off, wave on USER_CONFIG.WAVE_FRONT_WIDTH = 2; break; case 2: // background on, wave off USER_CONFIG.WAVE_FRONT_WIDTH = 5; break; case 3: // background off, rainbow wave USER_CONFIG.WAVE_FRONT_WIDTH = 10; break; case 4: // background on, rainbow wave USER_CONFIG.WAVE_FRONT_WIDTH = 10; break; case 5: USER_CONFIG.WAVE_FRONT_WIDTH = 10; USER_CONFIG.COLOR_PATTERN_INDEX = 2; USER_CONFIG.TRAVEL_DISTANCE = 0; USER_CONFIG.WAVE_PERIOD = 100; break; case 6: USER_CONFIG.WAVE_FRONT_WIDTH = 25; USER_CONFIG.COLOR_PATTERN_INDEX = 3; USER_CONFIG.TRAVEL_DISTANCE = 2; USER_CONFIG.WAVE_PERIOD = 10; break; } // remove effect after changing pattern for(int i = 0; i < KEY_STROKES_LENGTH; ++i){ KEY_STROKES[i].alive = 0; } refresh_pattern_indicators(); refresh_color_pattern_indicators(); } return false; case L_SP_WD: case L_SP_NW: if(record->event.pressed){ short incre = keycode == L_SP_WD ? 1 : -1; USER_CONFIG.WAVE_FRONT_WIDTH += incre; if(USER_CONFIG.WAVE_FRONT_WIDTH < 1){ USER_CONFIG.WAVE_FRONT_WIDTH = 1; } } return false; case L_SP_FA: case L_SP_SL: if(record->event.pressed){ short incre = keycode == L_SP_FA ? -1 : 1; USER_CONFIG.WAVE_PERIOD += 10 * incre; if(USER_CONFIG.WAVE_PERIOD < 10){ USER_CONFIG.WAVE_PERIOD = 10; } } return false; // these are the keys not in range 0x04 - 0x52 case L_CP_PR: case L_CP_NX: if(record->event.pressed){ uint8_t incre = keycode == L_CP_PR ? COLOR_PATTERNS_COUNT - 1 : 1; USER_CONFIG.COLOR_PATTERN_INDEX += incre; USER_CONFIG.COLOR_PATTERN_INDEX %= COLOR_PATTERNS_COUNT; refresh_color_pattern_indicators(); } return false; default: if (record->event.pressed){ uint8_t led_id = ktli(keycode); if(led_id){ for(int i = 0; i < KEY_STROKES_LENGTH; ++i){ if(!KEY_STROKES[i].alive){ KEY_STROKES[i].alive = 1; KEY_STROKES[i].led_id = led_id; KEY_STROKES[i].time = timer_read32(); break; } } } } return true; //Process all other keycodes normally } }