summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--keyboards/lets_split/keymaps/zer09/config.h59
-rw-r--r--keyboards/lets_split/keymaps/zer09/keymap.c38
-rw-r--r--keyboards/lets_split/keymaps/zer09/keymap.h32
-rw-r--r--keyboards/lets_split/keymaps/zer09/rules.mk6
-rw-r--r--users/zer09/config.h32
-rw-r--r--users/zer09/lights.c189
-rw-r--r--users/zer09/lights.h45
-rw-r--r--users/zer09/rules.mk2
-rw-r--r--users/zer09/tap_dance.c182
-rw-r--r--users/zer09/tap_dance.h55
-rw-r--r--users/zer09/zer09.c88
-rw-r--r--users/zer09/zer09.h18
12 files changed, 746 insertions, 0 deletions
diff --git a/keyboards/lets_split/keymaps/zer09/config.h b/keyboards/lets_split/keymaps/zer09/config.h
new file mode 100644
index 0000000000..73438d8a93
--- /dev/null
+++ b/keyboards/lets_split/keymaps/zer09/config.h
@@ -0,0 +1,59 @@
+/*
+This is the c configuration file for the keymap
+
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+Copyright 2015 Jack Humbert
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_USER_H
+#define CONFIG_USER_H
+
+#include "../../config.h"
+
+/* key matrix size */
+/* Rows are doubled-up */
+#undef MATRIX_ROWS
+#undef MATRIX_COLS
+#define MATRIX_ROWS 10
+#define MATRIX_COLS 5
+
+#undef MATRIX_ROW_PINS
+#undef MATRIX_COL_PINS
+#define MATRIX_ROW_PINS { C6, D7, E6, B4, B5 }
+#define MATRIX_COL_PINS { F7, B1, B3, B2, B6 }
+
+#define CATERINA_BOOTLOADER
+#define USB_MAX_POWER_CONSUMPTION 50
+
+/* Use I2C or Serial, not both */
+
+#define USE_SERIAL
+// #define USE_I2C
+
+/* Select hand configuration */
+
+/* #define MASTER_LEFT */
+// #define MASTER_RIGHT
+#define EE_HANDS
+
+/* ws2812 RGB LED */
+#undef RGBLED_NUM
+#define RGB_DI_PIN D3
+#define RGBLIGHT_TIMER
+#define RGBLED_NUM 50
+#define ws2812_PORTREG PORTD
+#define ws2812_DDRREG DDRD
+#endif
diff --git a/keyboards/lets_split/keymaps/zer09/keymap.c b/keyboards/lets_split/keymaps/zer09/keymap.c
new file mode 100644
index 0000000000..8d0eaf1411
--- /dev/null
+++ b/keyboards/lets_split/keymaps/zer09/keymap.c
@@ -0,0 +1,38 @@
+#include "keymap.h"
+
+extern keymap_config_t keymap_config;
+
+#define _baseLayer LAYOUT( \
+ KC_QUOTE, KC_COMMA, KC_DOT, KC_P, KC_Y, /**/KC_F, KC_G, KC_C, KC_R, KC_L, \
+ CTL_T(KC_A), SFT_T(KC_O), ALT_T(KC_E), KC_U, KC_I, /**/KC_D, KC_H, ALT_T(KC_T), SFT_T(KC_N), CTL_T(KC_S), \
+ KC_SCOLON, KC_Q, KC_J, KC_K, KC_X, /**/KC_B, KC_M, KC_W, KC_V, KC_Z, \
+ TD(DA_UPLY), MO(_VL), KC_TAB, KC_BSPACE, KC_ESC, /**/KC_INS, KC_HOME, KC_PGUP, MO(_VL), TD(DA_UPLY), \
+ TD(DA_DWLY), TD(DA_LCTL), KC_SPC, TD(DA_LSPR), LSFT_T(KC_CAPS),/**/SFT_T(KC_CAPS), TD(DA_RALT), KC_ENT, TD(DA_RCTL), TD(DA_DWLY))
+
+#define _upLayer LAYOUT( \
+ KC_4, KC_5, KC_6, _______, _______,/**/ _______, KC_RBRC, _______, _______, _______, \
+ LCTL_T(KC_1), LSFT_T(KC_2), LALT_T(KC_3), _______, _______,/**/ KC_LBRC, KC_BSLS, _______, _______, _______, \
+ KC_7, KC_8, KC_9, KC_0, KC_GRV, /**/ KC_SLSH, _______, _______, _______, _______, \
+ _______, _______, _______, _______, _______,/**/ KC_DEL, KC_END, KC_PGDN, _______, _______, \
+ _______, _______, _______, _______, _______,/**/ _______, _______, _______, _______, _______)
+
+#define _downLayer LAYOUT( \
+ KC_F4, KC_F5, KC_F6, KC_F12, _______,/**/ _______, KC_RPRN, _______, _______, _______, \
+ LCTL_T(KC_F1), LSFT_T(KC_F2), LALT_T(KC_F3), KC_F11, _______,/**/ KC_LPRN, KC_EQUAL, KC_LEFT, KC_UP, KC_RIGHT, \
+ KC_F7, KC_F8, KC_F9, KC_F10, _______,/**/ KC_MINUS, _______, _______, KC_DOWN, _______, \
+ _______, _______, _______, _______, _______,/**/ KC_PSCR, KC_SLCK, KC_PAUSE, _______, _______, \
+ _______, _______, _______, _______, _______,/**/ _______, _______, _______, _______, _______)
+
+#define _astdLayer LAYOUT( \
+ KC_MPRV, KC_MUTE, _______, _______, _______,/**/KC_PSCR, KC_SLCK, KC_PAUSE, _______, KC_RGUP, \
+ KC_MPLY, KC_VOLD, _______, _______, _______,/**/_______, _______, _______, _______, KC_RGDWN, \
+ KC_MNXT, KC_VOLU, RESET, _______, _______,/**/_______, _______, RESET, _______, _______, \
+ _______, _______, _______, _______, _______,/**/_______, _______, _______, _______, _______, \
+ _______, _______, _______, _______, _______,/**/_______, _______, _______, _______, _______)
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [_BL] = _baseLayer,
+ [_UL] = _upLayer,
+ [_DL] = _downLayer,
+ [_VL] = _upLayer,
+ [_AL] = _astdLayer};
diff --git a/keyboards/lets_split/keymaps/zer09/keymap.h b/keyboards/lets_split/keymaps/zer09/keymap.h
new file mode 100644
index 0000000000..03f8f480af
--- /dev/null
+++ b/keyboards/lets_split/keymaps/zer09/keymap.h
@@ -0,0 +1,32 @@
+#include "lets_split.h"
+#include "action_layer.h"
+#include "eeconfig.h"
+#include "tap_dance.h"
+#include "zer09.h"
+
+#ifdef LAYOUT_ortho_4x12
+#undef LAYOUT_ortho_4x12
+#endif
+
+#ifdef LAYOUT
+#undef LAYOUT
+#define LAYOUT( \
+ L00, L01, L02, L03, L04, R00, R01, R02, R03, R04, \
+ L10, L11, L12, L13, L14, R10, R11, R12, R13, R14, \
+ L20, L21, L22, L23, L24, R20, R21, R22, R23, R24, \
+ L30, L31, L32, L33, L34, R30, R31, R32, R33, R34, \
+ L40, L41, L42, L43, L44, R40, R41, R42, R43, R44 \
+) \
+ { \
+ { L00, L01, L02, L03, L04 }, \
+ { L10, L11, L12, L13, L14 }, \
+ { L20, L21, L22, L23, L24 }, \
+ { L30, L31, L32, L33, L34 }, \
+ { L40, L41, L42, L43, L44 }, \
+ { R00, R01, R02, R03, R04 }, \
+ { R10, R11, R12, R13, R14 }, \
+ { R20, R21, R22, R23, R24 }, \
+ { R30, R31, R32, R33, R34 }, \
+ { R40, R41, R42, R43, R44 } \
+ }
+#endif
diff --git a/keyboards/lets_split/keymaps/zer09/rules.mk b/keyboards/lets_split/keymaps/zer09/rules.mk
new file mode 100644
index 0000000000..d8adc70882
--- /dev/null
+++ b/keyboards/lets_split/keymaps/zer09/rules.mk
@@ -0,0 +1,6 @@
+RGBLIGHT_ENABLE = yes
+TAP_DANCE_ENABLE = yes
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif
diff --git a/users/zer09/config.h b/users/zer09/config.h
new file mode 100644
index 0000000000..7668064622
--- /dev/null
+++ b/users/zer09/config.h
@@ -0,0 +1,32 @@
+#ifndef USERSPACE_CONFIG_H
+#define USERSPACE_CONFIG_H
+
+#ifndef QMK_KEYS_PER_SCAN
+#define QMK_KEYS_PER_SCAN 4
+#endif // !QMK_KEYS_PER_SCAN
+
+// this makes it possible to do rolling combos (zx) with keys that
+// convert to other keys on hold (z becomes ctrl when you hold it,
+// and when this option isn't enabled, z rapidly followed by x
+// actually sends Ctrl-x. That's bad.)
+#define IGNORE_MOD_TAP_INTERRUPT
+#undef PERMISSIVE_HOLD
+#undef PREVENT_STUCK_MODIFIERS
+
+#define FORCE_NKRO
+
+#ifndef TAPPING_TOGGLE
+#define TAPPING_TOGGLE 1
+#endif
+
+#ifdef TAPPING_TERM
+#undef TAPPING_TERM
+#endif
+#define TAPPING_TERM 120
+
+// Disable action_get_macro and fn_actions, since we don't use these
+// and it saves on space in the firmware.
+#define NO_ACTION_MACRO
+#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/users/zer09/lights.c b/users/zer09/lights.c
new file mode 100644
index 0000000000..448ef494e8
--- /dev/null
+++ b/users/zer09/lights.c
@@ -0,0 +1,189 @@
+#include "lights.h"
+
+static bool active_key_pos[50] = {};
+static uint8_t led_dim = 0;
+
+volatile led_key rbw_led_keys[RBW] = {
+ [RBW_LCTL] = {DEFAULT, 21, true}, [RBW_LCAP] = {DEFAULT, 24, false},
+ [RBW_LSPR] = {DEFAULT, 23, true}, [RBW_RCTL] = {DEFAULT, 48, true},
+ [RBW_RCAP] = {DEFAULT, 45, false}, [RBW_RALT] = {DEFAULT, 46, true},
+ [RBW_SCRL] = {DEFAULT, 42, true}};
+
+/* Pressed led color. */
+const uint32_t _PC[3] = {0xFF, 0x00, 0x00};
+
+/* Layer color. */
+const uint8_t _LC[5][3] = {[_BL] = {0x00, 0x00, 0x00},
+ [_UL] = {0x00, 0x00, 0xFF},
+ [_VL] = {0xFF, 0xFF, 0x00},
+ [_DL] = {0x00, 0xFF, 0x00},
+ [_AL] = {0xFF, 0x00, 0x00}};
+
+/* Color table by sine wave */
+const uint8_t _LIGHTS[360] = {
+ 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 4, 5, 6, 7, 8,
+ 11, 12, 9, 13, 15, 17, 18, 20, 22, 24, 26, 28, 30, 32, 35,
+ 37, 39, 42, 44, 47, 49, 52, 55, 58, 60, 63, 66, 69, 72, 75,
+ 78, 81, 85, 88, 91, 94, 97, 101, 104, 107, 111, 114, 117, 121, 124,
+ 127, 131, 134, 137, 141, 144, 147, 150, 154, 157, 160, 163, 167, 170, 173,
+ 176, 179, 182, 185, 188, 191, 194, 197, 200, 202, 205, 208, 210, 213, 215,
+ 217, 220, 222, 224, 226, 229, 231, 232, 234, 236, 238, 239, 241, 242, 244,
+ 245, 246, 248, 249, 250, 251, 251, 252, 253, 253, 254, 254, 255, 255, 255,
+ 255, 255, 255, 255, 254, 254, 253, 253, 252, 251, 251, 250, 249, 248, 246,
+ 245, 244, 242, 241, 239, 238, 236, 234, 232, 231, 229, 226, 224, 222, 220,
+ 217, 215, 213, 210, 208, 205, 202, 200, 197, 194, 191, 188, 185, 182, 179,
+ 176, 173, 170, 167, 163, 160, 157, 154, 150, 147, 144, 141, 137, 134, 131,
+ 127, 124, 121, 117, 114, 111, 107, 104, 101, 97, 94, 91, 88, 85, 81,
+ 78, 75, 72, 69, 66, 63, 60, 58, 55, 52, 49, 47, 44, 42, 39,
+ 37, 35, 32, 30, 28, 26, 24, 22, 20, 18, 17, 15, 13, 12, 11,
+ 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+void set_key_led(keyrecord_t *record, uint8_t lyr) {
+ static uint8_t base = 5;
+
+ uint8_t r = record->event.key.row;
+ uint8_t c = record->event.key.col;
+ uint8_t pos;
+
+ // This was the result of my soldering.
+ // Lesson of the day: always check.
+ if (r < 5) {
+ pos = r % 2 == 0 ? r * base + c : r * base + (base - (c + 1));
+ } else {
+ pos = r % 2 == 0 ? r * base + (base - (c + 1)) : r * base + c;
+ }
+
+ if (record->event.pressed) {
+ active_key_pos[pos] = true;
+ SET_LED_RGB(_PC[0], _PC[1], _PC[2], led_dim, pos);
+ } else {
+ active_key_pos[pos] = false;
+ SET_LED_RGB(_LC[lyr][0], _LC[lyr][1], _LC[lyr][2], led_dim, pos);
+ }
+}
+
+/* Fix for unknown reason after testin flash the eeprom handedness,
+ the leds will ligth up after boot.
+ This should be call in the set layer led.*/
+bool is_first_run(void) {
+ static uint8_t run = 0;
+
+ if (run == 0) {
+ run++;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool set_layer_led(uint8_t lyr) {
+ static uint8_t p_lyr = 0; // Previous layer.
+ static uint8_t p_dim = 0; // Previous dim.
+
+ if (p_lyr == lyr && p_dim == led_dim && !is_first_run()) {
+ return false;
+ }
+
+ p_lyr = lyr;
+ p_dim = led_dim;
+ const uint8_t r = _LC[lyr][0];
+ const uint8_t g = _LC[lyr][1];
+ const uint8_t b = _LC[lyr][2];
+ const uint8_t d = (p_lyr == _VL && p_dim < 1) ? 1 : p_dim;
+
+ for (uint8_t i = 0; i < RGBLED_NUM; i++) {
+ SET_LED_RGB(r, g, b, d, i);
+ }
+
+ return true;
+}
+
+bool rainbow_loop(uint8_t lyr) {
+ static uint16_t last_timer = 0;
+ static uint16_t i = 0;
+ static uint8_t r, g, b, pos;
+
+ if (timer_elapsed(last_timer) < 8) {
+ return false;
+ }
+
+ if (i >= 360) {
+ i = 0;
+ }
+
+ last_timer = timer_read();
+ r = _LIGHTS[(i + 120) % 360];
+ g = _LIGHTS[i];
+ b = _LIGHTS[(i + 240) % 360];
+
+ i++;
+
+ bool set_rbw = false;
+
+ for (uint8_t j = 0; j < RBW; j++) {
+ pos = rbw_led_keys[j].pos;
+
+ switch (rbw_led_keys[j].status) {
+ case ENABLED:
+ if (!active_key_pos[pos] || rbw_led_keys[j].forced) {
+ SET_LED_RGB(r, g, b, led_dim, pos);
+ set_rbw = true;
+ }
+
+ break;
+ case DISABLED:
+ if (!active_key_pos[pos] || rbw_led_keys[j].forced) {
+ SET_LED_RGB(_LC[lyr][0], _LC[lyr][1], _LC[lyr][2], led_dim, pos);
+ set_rbw = true;
+ }
+
+ rbw_led_keys[j].status = DEFAULT;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return set_rbw;
+}
+
+bool led_brightness(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case RGUP:
+ if (record->event.pressed && led_dim > 0) {
+ led_dim--;
+ eeprom_write_byte(EECONFIG_LED_DIM_LVL, led_dim);
+ }
+
+ return true;
+ break;
+ case RGDWN:
+ if (record->event.pressed && led_dim < 8) {
+ led_dim++;
+ eeprom_write_byte(EECONFIG_LED_DIM_LVL, led_dim);
+ }
+
+ return true;
+ break;
+ default:
+ return false;
+ break;
+ }
+}
+
+void eeprom_read_led_dim_lvl(void) {
+ led_dim = eeprom_read_byte(EECONFIG_LED_DIM_LVL);
+
+ if (led_dim > 8 || led_dim < 0) {
+ led_dim = 0;
+ eeprom_write_byte(EECONFIG_LED_DIM_LVL, led_dim);
+ }
+}
diff --git a/users/zer09/lights.h b/users/zer09/lights.h
new file mode 100644
index 0000000000..f1bd7245d5
--- /dev/null
+++ b/users/zer09/lights.h
@@ -0,0 +1,45 @@
+#ifndef LIGHTS_H
+#define LIGHTS_H
+
+#include "eeprom.h"
+#include "tap_dance.h"
+#include "zer09.h"
+
+/* Will hold the RGB brightness level */
+#define EECONFIG_LED_DIM_LVL (uint8_t *)15
+
+#define SET_LED_RGB(r, g, b, led_dim, pos) \
+ setrgb(r >> led_dim, g >> led_dim, b >> led_dim, (LED_TYPE *)&led[pos])
+
+typedef enum {
+ DEFAULT,
+ ENABLED,
+ DISABLED,
+} led_status;
+
+typedef struct {
+ led_status status;
+ uint8_t pos;
+ bool forced;
+} led_key;
+
+enum rbw_keys {
+ RBW_LCTL,
+ RBW_LCAP,
+ RBW_LSPR,
+ RBW_RCTL,
+ RBW_RCAP,
+ RBW_RALT,
+ RBW_SCRL,
+ RBW
+};
+
+extern volatile led_key rbw_led_keys[RBW];
+
+void set_key_led(keyrecord_t *record, uint8_t lyr);
+bool set_layer_led(uint8_t lyr);
+bool rainbow_loop(uint8_t lyr);
+bool led_brightness(uint16_t keycode, keyrecord_t *record);
+void eeprom_read_led_dim_lvl(void);
+
+#endif
diff --git a/users/zer09/rules.mk b/users/zer09/rules.mk
new file mode 100644
index 0000000000..43b409eca7
--- /dev/null
+++ b/users/zer09/rules.mk
@@ -0,0 +1,2 @@
+SRC += zer09.c tap_dance.c lights.c
+EXTRAFLAGS += -flto
diff --git a/users/zer09/tap_dance.c b/users/zer09/tap_dance.c
new file mode 100644
index 0000000000..a23705ad8b
--- /dev/null
+++ b/users/zer09/tap_dance.c
@@ -0,0 +1,182 @@
+#include "tap_dance.h"
+#include "lights.h"
+
+qk_tap_dance_action_t tap_dance_actions[] = {
+ [DA_LCTL] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, dance_lctl_finished,
+ dance_lctl_reset),
+ [DA_LSPR] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, dance_lspr_finished,
+ dance_lspr_reset),
+ [DA_RCTL] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, dance_rctl_finished,
+ dance_rctl_reset),
+ [DA_RALT] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, dance_ralt_finished,
+ dance_ralt_reset),
+ [DA_UPLY] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, dance_uply_finished,
+ dance_uply_reset),
+ [DA_DWLY] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, dance_dwly_finished,
+ dance_dwly_reset),
+};
+
+volatile uint8_t active_layer = _BL;
+static tap upltap_state = {.state = 0};
+static tap dwltap_state = {.state = 0};
+static tap lsprtap_state = {.state = 0};
+static tap ralttap_state = {.state = 0};
+
+void layer_switcher_tap(uint8_t new_layer) {
+ layer_off(active_layer);
+ layer_on(new_layer);
+ active_layer = new_layer;
+}
+
+int cur_dance(qk_tap_dance_state_t *state) {
+ switch (state->count) {
+ case 1:
+ return state->pressed == 0 ? SINGLE_TAP : SINGLE_HOLD;
+ case 2:
+ return state->pressed == 0 ? DOUBLE_TAP : DOUBLE_HOLD;
+ case 3:
+ return state->pressed == 0 ? TRIPLE_TAP : TRIPLE_HOLD;
+ default:
+ return state->pressed == 0 ? DEFAULT_TAP : DEFAULT_HOLD;
+ }
+}
+
+void dance_lctl_finished(qk_tap_dance_state_t *state, void *user_data) {
+ rbw_led_keys[RBW_LCTL].status = ENABLED;
+ register_code(KC_LCTRL);
+};
+
+void dance_lctl_reset(qk_tap_dance_state_t *state, void *user_data) {
+ unregister_code(KC_LCTRL);
+ rbw_led_keys[RBW_LCTL].status = DISABLED;
+};
+
+void dance_lspr_finished(qk_tap_dance_state_t *state, void *user_data) {
+ lsprtap_state.state = cur_dance(state);
+
+ switch (lsprtap_state.state) {
+ case DOUBLE_HOLD:
+ rbw_led_keys[RBW_LSPR].status = ENABLED;
+ register_code(KC_LALT);
+ break;
+ default:
+ register_code(KC_LGUI);
+ break;
+ }
+};
+
+void dance_lspr_reset(qk_tap_dance_state_t *state, void *user_data) {
+ switch (lsprtap_state.state) {
+ case DOUBLE_HOLD:
+ unregister_code(KC_LALT);
+ rbw_led_keys[RBW_LSPR].status = DISABLED;
+ break;
+ default:
+ unregister_code(KC_LGUI);
+ break;
+ }
+};
+
+void dance_rctl_finished(qk_tap_dance_state_t *state, void *user_data) {
+ rbw_led_keys[RBW_RCTL].status = ENABLED;
+ register_code(KC_RCTRL);
+};
+
+void dance_rctl_reset(qk_tap_dance_state_t *state, void *user_data) {
+ unregister_code(KC_RCTRL);
+ rbw_led_keys[RBW_RCTL].status = DISABLED;
+};
+
+void dance_ralt_finished(qk_tap_dance_state_t *state, void *user_data) {
+ ralttap_state.state = cur_dance(state);
+
+ switch (ralttap_state.state) {
+ case DOUBLE_HOLD:
+ rbw_led_keys[RBW_RALT].status = ENABLED;
+ unregister_code(KC_LGUI);
+ break;
+ default:
+ register_code(KC_RALT);
+ break;
+ }
+};
+
+void dance_ralt_reset(qk_tap_dance_state_t *state, void *user_data) {
+ switch (ralttap_state.state) {
+ case DOUBLE_HOLD:
+ unregister_code(KC_RGUI);
+ rbw_led_keys[RBW_RALT].status = DISABLED;
+ break;
+ default:
+ unregister_code(KC_RALT);
+ break;
+ }
+};
+
+void dance_uply_finished(qk_tap_dance_state_t *state, void *user_data) {
+ upltap_state.state = cur_dance(state);
+
+ switch (upltap_state.state) {
+ case SINGLE_TAP:
+ if (active_layer == _UL) {
+ layer_switcher_tap(_BL);
+ } else {
+ layer_switcher_tap(_UL);
+ }
+ break;
+ case SINGLE_HOLD:
+ layer_switcher_tap(_UL);
+ break;
+ default:
+ layer_switcher_tap(_BL);
+ break;
+ }
+}
+
+void dance_uply_reset(qk_tap_dance_state_t *state, void *user_data) {
+ switch (upltap_state.state) {
+ case SINGLE_TAP:
+ break;
+ case SINGLE_HOLD:
+ default:
+ layer_switcher_tap(_BL);
+ break;
+ }
+ upltap_state.state = 0;
+}
+
+void dance_dwly_finished(qk_tap_dance_state_t *state, void *user_data) {
+ dwltap_state.state = cur_dance(state);
+
+ switch (dwltap_state.state) {
+ case SINGLE_TAP:
+ if (active_layer == _DL) {
+ layer_switcher_tap(_BL);
+ } else {
+ layer_switcher_tap(_DL);
+ }
+ break;
+ case SINGLE_HOLD:
+ layer_switcher_tap(_DL);
+ break;
+ case DOUBLE_HOLD:
+ layer_switcher_tap(_AL);
+ break;
+ default:
+ layer_switcher_tap(_BL);
+ break;
+ }
+}
+
+void dance_dwly_reset(qk_tap_dance_state_t *state, void *user_data) {
+ switch (dwltap_state.state) {
+ case SINGLE_TAP:
+ break;
+ case SINGLE_HOLD:
+ case DOUBLE_HOLD:
+ default:
+ layer_switcher_tap(_BL);
+ break;
+ }
+ dwltap_state.state = 0;
+}
diff --git a/users/zer09/tap_dance.h b/users/zer09/tap_dance.h
new file mode 100644
index 0000000000..555c159248
--- /dev/null
+++ b/users/zer09/tap_dance.h
@@ -0,0 +1,55 @@
+#ifndef TAP_DANCE_H
+#define TAP_DANCE_H
+
+#include "zer09.h"
+
+typedef struct {
+ int state;
+} tap;
+
+enum {
+ DEFAULT_TAP,
+ DEFAULT_HOLD,
+ SINGLE_TAP,
+ SINGLE_HOLD,
+ DOUBLE_TAP,
+ DOUBLE_HOLD,
+ TRIPLE_TAP,
+ TRIPLE_HOLD
+};
+
+enum {
+ DA_SAFE_START,
+ DA_LCTL,
+ DA_LSPR,
+ DA_RCTL,
+ DA_RALT,
+ DA_UPLY,
+ DA_DWLY,
+ DA_SAFE_END
+};
+
+extern volatile uint8_t active_layer;
+
+void layer_switcher_tap(uint8_t);
+int cur_dance(qk_tap_dance_state_t *);
+
+void dance_lctl_finished(qk_tap_dance_state_t *, void *);
+void dance_lctl_reset(qk_tap_dance_state_t *, void *);
+
+void dance_lspr_finished(qk_tap_dance_state_t *, void *);
+void dance_lspr_reset(qk_tap_dance_state_t *, void *);
+
+void dance_rctl_finished(qk_tap_dance_state_t *, void *);
+void dance_rctl_reset(qk_tap_dance_state_t *, void *);
+
+void dance_ralt_finished(qk_tap_dance_state_t *, void *);
+void dance_ralt_reset(qk_tap_dance_state_t *, void *);
+
+void dance_uply_finished(qk_tap_dance_state_t *, void *);
+void dance_uply_reset(qk_tap_dance_state_t *, void *);
+
+void dance_dwly_finished(qk_tap_dance_state_t *, void *);
+void dance_dwly_reset(qk_tap_dance_state_t *, void *);
+
+#endif
diff --git a/users/zer09/zer09.c b/users/zer09/zer09.c
new file mode 100644
index 0000000000..a6768f0a1a
--- /dev/null
+++ b/users/zer09/zer09.c
@@ -0,0 +1,88 @@
+#include "zer09.h"
+#include "lights.h"
+#include "tap_dance.h"
+
+__attribute__((weak)) void matrix_init_keymap(void) {}
+
+__attribute__((weak)) void matrix_scan_keymap(void) {}
+
+__attribute__((weak)) bool process_record_keymap(uint16_t keycode,
+ keyrecord_t *record) {
+ return true;
+}
+
+__attribute__((weak)) void led_set_keymap(uint8_t usb_led) {}
+
+static uint8_t c_lyr = 0; // current layer.
+
+bool shifted_layer(void) {
+ static bool is_shifted = false;
+
+ if (c_lyr == _VL) {
+ if (!is_shifted) {
+ register_code(KC_LSFT);
+ is_shifted = true;
+ return true;
+ }
+ } else {
+ if (is_shifted) {
+ unregister_code(KC_LSFT);
+ is_shifted = false;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void matrix_init_user(void) {
+ eeprom_read_led_dim_lvl();
+
+ matrix_init_keymap();
+}
+
+void matrix_scan_user(void) {
+ static uint8_t is_leds_changes = 1;
+ c_lyr = biton32(layer_state);
+
+ is_leds_changes = is_leds_changes << set_layer_led(c_lyr);
+ is_leds_changes = is_leds_changes << shifted_layer();
+ is_leds_changes = is_leds_changes << rainbow_loop(c_lyr);
+
+ if (is_leds_changes > 1) {
+ rgblight_set();
+ is_leds_changes = 1;
+ }
+
+ matrix_scan_keymap();
+}
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ set_key_led(record, c_lyr);
+
+ if (led_brightness(keycode, record)) {
+ rgblight_set();
+ return false;
+ }
+
+ rgblight_set();
+ return process_record_keymap(keycode, record);
+}
+
+void led_set_user(uint8_t usb_led) {
+ if (usb_led & (1 << USB_LED_CAPS_LOCK)) {
+ rbw_led_keys[RBW_LCAP].status = ENABLED;
+ rbw_led_keys[RBW_RCAP].status = ENABLED;
+ } else {
+ rbw_led_keys[RBW_LCAP].status = DISABLED;
+ rbw_led_keys[RBW_RCAP].status = DISABLED;
+ }
+
+ if (usb_led & (1 << USB_LED_SCROLL_LOCK)) {
+ rbw_led_keys[RBW_SCRL].status = ENABLED;
+ } else {
+ rbw_led_keys[RBW_SCRL].status = DISABLED;
+ }
+
+ led_set_keymap(usb_led);
+}
diff --git a/users/zer09/zer09.h b/users/zer09/zer09.h
new file mode 100644
index 0000000000..75c1d3cad4
--- /dev/null
+++ b/users/zer09/zer09.h
@@ -0,0 +1,18 @@
+#ifndef USERSPACE
+#define USERSPACE
+
+#include "quantum.h"
+
+enum custom_keycodes { CK_SAFE = SAFE_RANGE, RGUP, RGDWN, NEWPLACEHOLDER };
+
+#define _______ KC_TRNS
+#define KC_RGUP RGUP
+#define KC_RGDWN RGDWN
+
+#define _BL 0 // The base layer
+#define _UL 1 // The up layer
+#define _DL 2 // The down layer
+#define _VL 3 // The shifted up layer
+#define _AL 4 // The assorted layer
+
+#endif