From d53432393bc409db0f01a1b668bf3f5fc6bebb4f Mon Sep 17 00:00:00 2001 From: Valen Cheung Date: Fri, 18 Jan 2019 08:57:31 +0800 Subject: [PATCH] [Keymap] added custom led effect keymap.c (#4856) --- .../ctrl/keymaps/responsive_pattern/keymap.c | 939 ++++++++++++++++++ 1 file changed, 939 insertions(+) create mode 100644 keyboards/massdrop/ctrl/keymaps/responsive_pattern/keymap.c diff --git a/keyboards/massdrop/ctrl/keymaps/responsive_pattern/keymap.c b/keyboards/massdrop/ctrl/keymaps/responsive_pattern/keymap.c new file mode 100644 index 000000000..eabd8d23a --- /dev/null +++ b/keyboards/massdrop/ctrl/keymaps/responsive_pattern/keymap.c @@ -0,0 +1,939 @@ +#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[]; +extern led_disp_t disp; + +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; + + disp.frame += 1; + + 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)(disp.frame % (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 (keyboard_report->mods & MOD_BIT(KC_LSHIFT) || keyboard_report->mods & MOD_BIT(KC_RSHIFT)) +#define MODS_CTRL (keyboard_report->mods & MOD_BIT(KC_LCTL) || keyboard_report->mods & MOD_BIT(KC_RCTRL)) +#define MODS_ALT (keyboard_report->mods & MOD_BIT(KC_LALT) || keyboard_report->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 + } +}