~ruther/qmk_firmware

7216fd0f47bb41d0a49432095767aef6ead33da2 — zer09 7 years ago 3b7b199
My userspace and lets_split keymap (#2842)

* copied lets_slit to splinter

* initial splinter layout

* remove unused keymaps

* implemented second half of the keyboard

* initial definition of tap dance

* the tap dance is working now

tap dance for right hand 4c 2r
hold - shift
single tap - n
double tap - ñ
triple tap - Ñ

* clear the keymap.c

* put the tap state on to array

* the n tilde tap dance should produce right shift if hold

* add esc grv tap dance

* remove the defined SS_LSFT on tap_dance.h

because it was added on the quantum.h

* minor cleanup for the keymap

* use the X_* on tap dance

* added super alt tap dance

* use the NO_TAP on tap dance reset

* allow track what rows and cols pressed

* added the RGUI_ALT

* keymap arrangement

* use i2c

* initial rgb

* layer colors

* initial rgb pressed key

* set the layers led

* SUCCESS!!!

* cleaning

* improve shifted layer

* led brightness

* initial caps rainbow

* rename SET_LED_RGB to SET_LED_RGB_HEX

* clean the SET_LED_RGB_HEX and added SET_LED_RGB

* clean format

* caps lock rainbow

* rename key_led to set_key_led

* caps lock rainbow enhanced

* make varibiables static

* change back the loop max value to 360 for the rainbow

* add scroll lock to the rainbow led

* fix pos calculation of right hand board

* add ative keys and make rainbow color can override by key press

* remove the TOTAL_MATRIX_POINTS

* some improvments for the rgb

* call the rgblight_set on the process_record_user

* some enhancement for the leds

* pass the dim value to set_layer_led and limit the brightness on _VL

set the brightness to 2 if the dim value is less than 2 because
their is not enought power for the leds.

* remove the rgb steps on the config

* use the non rev config

* remove all the revisions

* favor i2c instead of serial and remove all the ref for the serial

* clang formatting

* allow to save to eeprom the brightness value

* add bootloader caterina this will enable soft reset key

* initial commit for the userspace

* added my own keymap for splinter

* first working userspace

* move splinter to handwired keyboards

* handwired splinter default keymap

* move some config to my keymap

* cleanup some headers on the keymap

* move the EECONFIG_RGB_DIM to the user space

* I fix remove the GUI on SPC and ENT

* remove the default include on tap_dance.c

* add lights.c and refactoring

* fix wrong source for led index

* seperate the variable on set_layer_led for readabilty.

* set the usb max power consumption to 50

* fix led lighting

* add new enums for tap dance

* use romeve path avr on eeprom.h

* fix wrong spelling on TP names

* changed the tap dance

* allow to set rainbow on some pressed key

* add reset key

* fix error on matrix.c if ROW2COL is used

* add extraflags -flto

* See e2352d4

* Got no love from i2c, serial to the rescue

* Fix the led will lit up to color red after boot

* Trial if the power can handle yellow color at full

* Add comment

* Use EE_HANDS

* add config.h in the use space

* KC_N on BL should wrap in SFT_T

* See d13567d, put it back but increase 1 level

* Fix led soldering mistake

* set the tapping_term to 100

* Use TT for the changing the layer

* Remove the changing space to enter and vice version on BL and UL

* Increate the tapping term

* Use tap dance on changing layer

* Add assorted layer

* propery way to tapdance

* Remove DA_EGRV

This also fix the wrong placement of the reset and dance lspr should register
the KC_LGUI on finished not unregistered.

* Remove the media control to the up and down layer

* Remove the interrupted state of the tap dance

* swapt the space and enter on to th caps

* Shorthand

* Keymap update

* My keymap for lets_split

* cleaning
A keyboards/lets_split/keymaps/zer09/config.h => keyboards/lets_split/keymaps/zer09/config.h +59 -0
@@ 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

A keyboards/lets_split/keymaps/zer09/keymap.c => keyboards/lets_split/keymaps/zer09/keymap.c +38 -0
@@ 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};

A keyboards/lets_split/keymaps/zer09/keymap.h => keyboards/lets_split/keymaps/zer09/keymap.h +32 -0
@@ 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

A keyboards/lets_split/keymaps/zer09/rules.mk => keyboards/lets_split/keymaps/zer09/rules.mk +6 -0
@@ 0,0 1,6 @@
RGBLIGHT_ENABLE = yes
TAP_DANCE_ENABLE = yes

ifndef QUANTUM_DIR
	include ../../../../Makefile
endif

A users/zer09/config.h => users/zer09/config.h +32 -0
@@ 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

A users/zer09/lights.c => users/zer09/lights.c +189 -0
@@ 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);
  }
}

A users/zer09/lights.h => users/zer09/lights.h +45 -0
@@ 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

A users/zer09/rules.mk => users/zer09/rules.mk +2 -0
@@ 0,0 1,2 @@
SRC += zer09.c tap_dance.c lights.c
EXTRAFLAGS += -flto

A users/zer09/tap_dance.c => users/zer09/tap_dance.c +182 -0
@@ 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;
}

A users/zer09/tap_dance.h => users/zer09/tap_dance.h +55 -0
@@ 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

A users/zer09/zer09.c => users/zer09/zer09.c +88 -0
@@ 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);
}

A users/zer09/zer09.h => users/zer09/zer09.h +18 -0
@@ 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