~ruther/qmk_firmware

12681bacc4b2d845bd01b0e65b00e3d8775ac515 — Zach White 4 years ago 65e3760 + e6c171b
Merge remote-tracking branch 'origin/master' into develop

Conflicts:
	keyboards/kbdfans/kbd67/mkiirgb/mkiirgb.c
A keyboards/aozora/hotswap/config.h => keyboards/aozora/hotswap/config.h +45 -0
@@ 0,0 1,45 @@
/* Copyright 2021 Salmon Cat Studio
 *
 * 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/>.
 */

#pragma once

#include "config_common.h"

/* USB Device descriptor parameter */
#define VENDOR_ID       0xCA75
#define PRODUCT_ID      0x4014
#define DEVICE_VER      0x0001
#define MANUFACTURER    Salmon Cat Studio
#define PRODUCT         Aozora

/* key matrix size */
#define MATRIX_ROWS 5
#define MATRIX_COLS 16

/*
 * Keyboard Matrix Assignments
 *
 * Change this to how you wired your keyboard
 * COLS: AVR pins used for columns, left to right
 * ROWS: AVR pins used for rows, top to bottom
 * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
 *                  ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
 *
 */
#define MATRIX_ROW_PINS { F6, F5, F4, F1, F0 }
#define MATRIX_COL_PINS { B0, B1, B2, B3, B7, D0, D1, D4, D6, D7, B4, B5, B6, C6, C7, F7 }

#define DIODE_DIRECTION COL2ROW

A keyboards/aozora/hotswap/hotswap.c => keyboards/aozora/hotswap/hotswap.c +17 -0
@@ 0,0 1,17 @@
/* Copyright 2021 Salmon Cat Studio
 *
 * 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/>.
 */

#include "hotswap.h"
\ No newline at end of file

A keyboards/aozora/hotswap/hotswap.h => keyboards/aozora/hotswap/hotswap.h +34 -0
@@ 0,0 1,34 @@
/* Copyright 2021 Salmon Cat Studio
 *
 * 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/>.
 */

#pragma once

#include "quantum.h"

#define LAYOUT( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D,       K0E, K0F,  \
    K10,   K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D,     K1E, K1F,  \
    K20,    K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2D,                    \
    K30,       K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3D,           K3E, K3F,  \
    K40,  K41,  K42,              K44,                K48,  K49,  K4A,     K4D, K4E, K4F   \
) { \
    { K00,   K01,   K02,   K03,   K04,   K05,   K06,   K07,   K08,   K09,   K0A,   K0B,   K0C,   K0D,   K0E,   K0F   }, \
    { K10,   K11,   K12,   K13,   K14,   K15,   K16,   K17,   K18,   K19,   K1A,   K1B,   K1C,   K1D,   K1E,   K1F   }, \
    { K20,   K21,   K22,   K23,   K24,   K25,   K26,   K27,   K28,   K29,   K2A,   K2B,   KC_NO, K2D,   KC_NO, KC_NO }, \
    { K30,   K31,   K32,   K33,   K34,   K35,   K36,   K37,   K38,   K39,   K3A,   KC_NO, KC_NO, K3D,   K3E,   K3F   }, \
    { K40,   K41,   K42,   KC_NO, K44,   KC_NO, KC_NO, KC_NO, K48,   K49,   K4A,   KC_NO, KC_NO, K4D,   K4E,   K4F   }, \
}


A keyboards/aozora/hotswap/info.json => keyboards/aozora/hotswap/info.json +83 -0
@@ 0,0 1,83 @@
{
    "keyboard_name": "Aozora",
    "url": "https://salmoncat.studio/pages/aozora-%E9%9D%92%E7%A9%BA-6-9-21-7-10-21",
    "maintainer": "Food",
    "width": 17.25,
    "height": 5,
    "layouts": {
        "LAYOUT": {
            "layout": [
                {"label":"K00 (F6,B0)", "x":0, "y":0},
                {"label":"K01 (F6,B1)", "x":1, "y":0},
                {"label":"K02 (F6,B2)", "x":2, "y":0},
                {"label":"K03 (F6,B3)", "x":3, "y":0},
                {"label":"K04 (F6,B7)", "x":4, "y":0},
                {"label":"K05 (F6,D0)", "x":5, "y":0},
                {"label":"K06 (F6,D1)", "x":6, "y":0},
                {"label":"K07 (F6,D4)", "x":7, "y":0},
                {"label":"K08 (F6,D6)", "x":8, "y":0},
                {"label":"K09 (F6,D7)", "x":9, "y":0},
                {"label":"K0A (F6,B4)", "x":10, "y":0},
                {"label":"K0B (F6,B5)", "x":11, "y":0},
                {"label":"K0C (F6,B6)", "x":12, "y":0},
                {"label":"K0D (F6,C6)", "x":13, "y":0, "w":2},
                {"label":"K0E (F6,C7)", "x":15.25, "y":0},
                {"label":"K0F (F6,F7)", "x":16.25, "y":0},
                {"label":"K10 (F5,B0)", "x":0, "y":1, "w":1.5},
                {"label":"K11 (F5,B1)", "x":1.5, "y":1},
                {"label":"K12 (F5,B2)", "x":2.5, "y":1},
                {"label":"K13 (F5,B3)", "x":3.5, "y":1},
                {"label":"K14 (F5,B7)", "x":4.5, "y":1},
                {"label":"K15 (F5,D0)", "x":5.5, "y":1},
                {"label":"K16 (F5,D1)", "x":6.5, "y":1},
                {"label":"K17 (F5,D4)", "x":7.5, "y":1},
                {"label":"K18 (F5,D6)", "x":8.5, "y":1},
                {"label":"K19 (F5,D7)", "x":9.5, "y":1},
                {"label":"K1A (F5,B4)", "x":10.5, "y":1},
                {"label":"K1B (F5,B5)", "x":11.5, "y":1},
                {"label":"K1C (F5,B6)", "x":12.5, "y":1},
                {"label":"K1D (F5,C6)", "x":13.5, "y":1, "w":1.5},
                {"label":"K1E (F5,C7)", "x":15.25, "y":1},
                {"label":"K1F (F5,F7)", "x":16.25, "y":1},
                {"label":"K20 (F4,B0)", "x":0, "y":2, "w":1.75},
                {"label":"K21 (F4,B1)", "x":1.75, "y":2},
                {"label":"K22 (F4,B2)", "x":2.75, "y":2},
                {"label":"K23 (F4,B3)", "x":3.75, "y":2},
                {"label":"K24 (F4,B7)", "x":4.75, "y":2},
                {"label":"K25 (F4,D0)", "x":5.75, "y":2},
                {"label":"K26 (F4,D1)", "x":6.75, "y":2},
                {"label":"K27 (F4,D4)", "x":7.75, "y":2},
                {"label":"K28 (F4,D6)", "x":8.75, "y":2},
                {"label":"K29 (F4,D7)", "x":9.75, "y":2},
                {"label":"K2A (F4,B4)", "x":10.75, "y":2},
                {"label":"K2B (F4,B5)", "x":11.75, "y":2},
                {"label":"K2D (F4,C6)", "x":12.75, "y":2, "w":2.25},
                {"label":"K30 (F1,B0)", "x":0, "y":3, "w":2.25},
                {"label":"K31 (F1,B1)", "x":2.25, "y":3},
                {"label":"K32 (F1,B2)", "x":3.25, "y":3},
                {"label":"K33 (F1,B3)", "x":4.25, "y":3},
                {"label":"K34 (F1,B7)", "x":5.25, "y":3},
                {"label":"K35 (F1,D0)", "x":6.25, "y":3},
                {"label":"K36 (F1,D1)", "x":7.25, "y":3},
                {"label":"K37 (F1,D4)", "x":8.25, "y":3},
                {"label":"K38 (F1,D6)", "x":9.25, "y":3},
                {"label":"K39 (F1,D7)", "x":10.25, "y":3},
                {"label":"K3A (F1,B4)", "x":11.25, "y":3},
                {"label":"K3D (F1,C6)", "x":12.25, "y":3, "w":2.75},
                {"label":"K3E (F1,C7)", "x":15.25, "y":3},
                {"label":"K3F (F1,F7)", "x":16.25, "y":3},
                {"label":"K40 (F0,B0)", "x":0, "y":4, "w":1.25},
                {"label":"K41 (F0,B1)", "x":1.25, "y":4, "w":1.25},
                {"label":"K42 (F0,B2)", "x":2.5, "y":4, "w":1.25},
                {"label":"K44 (F0,B7)", "x":3.75, "y":4, "w":6.25},
                {"label":"K48 (F0,D6)", "x":10, "y":4, "w":1.25},
                {"label":"K49 (F0,D7)", "x":11.25, "y":4, "w":1.25},
                {"label":"K4A (F0,B4)", "x":12.5, "y":4, "w":1.25},
                {"label":"K4D (F0,C6)", "x":14.25, "y":4},
                {"label":"K4E (F0,C7)", "x":15.25, "y":4},
                {"label":"K4F (F0,F7)", "x":16.25, "y":4}
            ]
        }
    }
    ,"meta": "https://noroadsleft.github.io/kbf_qmk_converter/"
}

A keyboards/aozora/hotswap/keymaps/default/keymap.c => keyboards/aozora/hotswap/keymaps/default/keymap.c +35 -0
@@ 0,0 1,35 @@
/* Copyright 2021 Salmon Cat Studio
 *
 * 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/>.
 */

#include QMK_KEYBOARD_H

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    [0] = LAYOUT(
        KC_ESC,  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_PSCR, 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_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_LSFT,                   KC_UP,   MO(1),
        KC_LCTL,   KC_LGUI,   KC_LALT,                       KC_SPC,                              KC_LALT,   KC_LGUI,   KC_LCTL,        KC_LEFT, KC_DOWN, KC_RGHT
    ),
    [1] = LAYOUT(
        KC_GRV,  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_F13,             KC_F14,  KC_F15,
        _______,     _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,        _______, _______,
        _______,       _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
        _______,            RESET,   _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,                   _______, _______,
        _______,   _______,   _______,                      _______,                              _______,   _______,   _______,        _______, _______, _______
    ),

};

A keyboards/aozora/hotswap/readme.md => keyboards/aozora/hotswap/readme.md +17 -0
@@ 0,0 1,17 @@
# Aozora 

A 65%-Style 6-Key keyboard featuring a cloud-shaped badge. 

![SCS Aozora](https://i.imgur.com/dL5nonc.jpg)

* Keyboard Maintainer: [Food](https://github.com/Phooood)
* Hardware Supported: [Aozora](https://salmoncat.studio/pages/aozora-%E9%9D%92%E7%A9%BA-6-9-21-7-10-21)
* Hardware Availability: [salmoncat.studio](https://salmoncat.studio/pages/aozora-%E9%9D%92%E7%A9%BA-6-9-21-7-10-21) | GB is over. 

Make example for this keyboard (after setting up your build environment):

    make aozora/hotswap:default

To reset, press the button on the back of the PCB. 

See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
\ No newline at end of file

A keyboards/aozora/hotswap/rules.mk => keyboards/aozora/hotswap/rules.mk +23 -0
@@ 0,0 1,23 @@
# MCU name
MCU = atmega32u4

# Bootloader selection
BOOTLOADER = atmel-dfu

# Build Options
#   change yes to no to disable
#
BOOTMAGIC_ENABLE = lite     # Virtual DIP switch configuration
MOUSEKEY_ENABLE = yes       # Mouse keys
EXTRAKEY_ENABLE = yes       # Audio control and System control
CONSOLE_ENABLE = yes        # Console for debug
COMMAND_ENABLE = yes        # Commands for debug and configuration
# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
SLEEP_LED_ENABLE = no       # Breathing sleep LED during USB suspend
# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
NKRO_ENABLE = no            # USB Nkey Rollover
BACKLIGHT_ENABLE = no       # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = no        # Enable keyboard RGB underglow
BLUETOOTH_ENABLE = no       # Enable Bluetooth
AUDIO_ENABLE = no           # Audio output


M keyboards/kbdfans/kbd67/mkiirgb/mkiirgb.c => keyboards/kbdfans/kbd67/mkiirgb/mkiirgb.c +16 -0
@@ 1,3 1,19 @@
/* Copyright 2021 DZTECH <moyi4681@live.cn>
 *
 * 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/>.
 */
 
#include "mkiirgb.h"
#ifdef RGB_MATRIX_ENABLE
const is31_led __flash g_is31_leds[DRIVER_LED_TOTAL] = {

M keyboards/kbdfans/kbd67/mkiirgb/mkiirgb.h => keyboards/kbdfans/kbd67/mkiirgb/mkiirgb.h +24 -14
@@ 1,16 1,26 @@
/* Copyright 2021 DZTECH <moyi4681@live.cn>
 *
 * 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/>.
 */

#pragma once
#define XXX KC_NO

#if defined(KEYBOARD_kbdfans_kbd67_mkiirgb_v1)
    #include "v1.h"
#elif defined(KEYBOARD_kbdfans_kbd67_mkiirgb_v2)
    #include "v2.h"
#elif defined(KEYBOARD_kbdfans_kbd67_mkiirgb_v3)
    #include "v3.h"
#endif
#include "quantum.h"
#define LAYOUT_65_ansi_blocker( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K0E, \
    K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E, \
    K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B,      K2D, K2E, \
    K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B,      K3D, K3E, \
    K40, K41, K42,           K45,           K48,      K4A, K4B,      K4D, K4E  \
) { \
    { K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K0E }, \
    { K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E }, \
    { K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, XXX, K2D, K2E }, \
    { K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, XXX, K3D, K3E }, \
    { K40, K41, K42, XXX, XXX, K45, XXX, XXX, K48, XXX, K4A, K4B, XXX, K4D, K4E }  \
}

M keyboards/kbdfans/kbd67/mkiirgb/readme.md => keyboards/kbdfans/kbd67/mkiirgb/readme.md +4 -2
@@ 3,17 3,19 @@
A customizable 65% RGB keyboard.

* Keyboard Maintainer: [moyi4681](https://github.com/moyi4681)
* Hardware Supported: KBD67 Mk.II RGB V1 and V2
* Hardware Supported: KBD67 Mk.II RGB V1, V2, and V3
* Hardware Availability: [kbdfans](https://kbdfans.myshopify.com/)

There are two versions of the KBD67 MKII RGB. Please use the appropriate firmware for your board. 
There are three versions of the KBD67 MKII RGB. Please use the appropriate firmware for your board. 

* V1: STM32F303 (Arm), takes `.bin` files
* V2: ATmega32U4 (AVR), takes `.hex` files
* V3: Atmega32U4 (AVR), takes  `.bin` files

Make example for this keyboard (after setting up your build environment):

    make kbdfans/kbd67/mkiirgb/v1:default # Arm (STM32F303)
    make kbdfans/kbd67/mkiirgb/v2:default # AVR (ATmega32U4)
    make kbdfans/kbd67/mkiirgb/v3:default # AVR (ATmega32U4)

See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).

D keyboards/kbdfans/kbd67/mkiirgb/v1/.noci => keyboards/kbdfans/kbd67/mkiirgb/v1/.noci +0 -0
A keyboards/kbdfans/kbd67/mkiirgb/v1/v1.c => keyboards/kbdfans/kbd67/mkiirgb/v1/v1.c +124 -0
@@ 0,0 1,124 @@
/* Copyright 2021 DZTECH <moyi4681@live.cn>
 *
 * 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/>.
 */

#include "v1.h"
#ifdef RGB_MATRIX_ENABLE
const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
	
	{0, C8_8,  C7_8, C6_8},   // LA17
	{0, C9_8,  C7_7, C6_7},   // LA16
	{0, C9_7,  C8_7, C6_6},   // LA15	
	{0, C9_6,  C8_6, C7_6},   // LA14
	{0, C9_5,  C8_5, C7_5},   // LA13	
	{0, C9_4,  C8_4, C7_4},   // LA12	
	{0, C9_3,  C8_3, C7_3},   // LA11	
	{0, C9_2,  C8_2, C7_2},   // LA10	
	{0, C9_1,  C8_1,  C7_1},  // LA9	
	{0, C2_9,  C3_9,  C4_9},  // LB0
	{0, C1_9,  C3_10, C4_10}, // LB1
	{0, C1_10, C2_10, C4_11}, // LB2
	{0, C1_11, C2_11, C3_11}, // LB3
	{0, C1_13, C2_13, C3_13}, // LB5
	{0, C1_14, C2_14, C3_14}, // LB6
	
	{0, C1_7,  C2_7, C3_7},   // LA7
	{0, C1_6,  C2_6, C3_6},   // LA6	
	{0, C1_5,  C2_5, C3_5},   // LA5	
	{0, C1_4,  C2_4, C3_4},   // LA4	
	{0, C1_3,  C2_3, C3_3},   // LA3	
	{0, C1_2,  C2_2, C4_3},   // LA2	
	{0, C1_1,  C3_2, C4_2},   // LA1	
	{0, C2_1,  C3_1,  C4_1},  // LA0
	{0, C9_9,  C8_9,  C7_9},  // LB9
	{0, C9_10, C8_10, C7_10}, // LB10
	{0, C9_11, C8_11, C7_11}, // LB11
	{0, C9_12, C8_12, C7_12}, // LB12
	{0, C9_13, C8_13, C7_13}, // LB13
	{0, C9_14, C8_14, C7_14}, // LB14
	{0, C1_15, C2_15, C3_15}, // LB7

    {0, C1_8,  C2_8, C3_8},   // LA8
	{1, C9_6,  C8_6, C7_6},   // LC14
	{1, C9_5,  C8_5, C7_5},   // LC13	
	{1, C9_4,  C8_4, C7_4},   // LC12	
	{1, C9_3,  C8_3, C7_3},   // LC11	
	{1, C9_2,  C8_2, C7_2},   // LC10	
	{1, C9_1,  C8_1,  C7_1},  // LC9
	{1, C2_9,  C3_9,  C4_9},  // LD0
	{1, C1_9,  C3_10, C4_10}, // LD1
	{1, C1_10, C2_10, C4_11}, // LD2
	{1, C1_11, C2_11, C3_11}, // LD3
	{1, C1_12, C2_12, C3_12}, // LD4
	{1, C1_13, C2_13, C3_13}, // LD5
	{0, C1_16, C2_16, C3_16}, // LB8

	{1, C9_8,  C7_7, C6_7},   // LC16
	{1, C1_5,  C2_5, C3_5},   // LC5
	{1, C1_4,  C2_4, C3_4},   // LC4
	{1, C1_3,  C2_3, C3_3},   // LC3	
	{1, C1_2,  C2_2, C4_3},   // LC2	
	{1, C1_1,  C3_2, C4_2},   // LC1
	{1, C9_9,  C8_9,  C7_9},  // LD9
	{1, C9_10, C8_10, C7_10}, // LD10
	{1, C9_11, C8_11, C7_11}, // LD11
	{1, C9_12, C8_12, C7_12}, // LD12
	{1, C1_14, C2_14, C3_14}, // LD6
	{1, C1_15, C2_15, C3_15}, // LD7
	{1, C1_16, C2_16, C3_16}, // LD8
	{0, C9_15, C8_15, C6_14}, // LB15

	{1, C8_8,  C7_8, C6_8},   // LC17
	{1, C1_8,  C2_8, C3_8},   // LC8	
	{1, C1_7,  C2_7, C3_7},   // LC7
	{1, C2_1,  C3_1,  C4_1},  // LC0
	{1, C9_14, C8_14, C7_14}, // LD14
	{1, C9_15, C8_15, C6_14}, // LD15
	{1, C8_16, C7_16, C6_16}, // LD17
	{0, C8_16, C7_16, C6_16}, // LB17
	{0, C9_16, C7_15, C6_15}, // LB16

};

led_config_t g_led_config = { {
    {  0,  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, NO_LED,42,  43 },
    {  44, 45, 46, 47, 48, 49, 50, 51,  52, 53, 54,  55, NO_LED,56,  57 },
    {  58, 59, 60, NO_LED, NO_LED,  61, NO_LED, NO_LED,  62,  NO_LED,  63,  64, NO_LED,  65,  66 }
}, {
    {0,0},{15,0},{30,0},{45,0},{60,0},{75,0},{90,0},{105,0},{120,0},{135,0},{150,0},{165,0},{180,0},{203,0},{224,0},
	{4,16},{23,16},{38,16},{53,16},{68,16},{83,16},{98,16},{113,16},{128,16},{143,16},{158,16},{173,16},{188,16},{206,16},{224,16},
	{6,32},{26,32},{41,32},{56,32},{71,32},{86,32},{101,32},{116,32},{131,32},{146,32},{161,32},{176,32},{201,32},{224,32},
	{9,48},{34,48},{49,48},{64,48},{79,48},{94,48},{109,48},{124,48},{139,48},{154,48},{169,48},{189,48},{210,48},{224,48},
	{2,64},{21,64},{39,64},{96,64},{152,64},{171,64},{195,64},{210,64},{224,64}
}, {
    1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1,
    1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1,
    1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 
    1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1,
    1, 1, 1, 4, 1, 1, 1, 1, 1
} };


__attribute__ ((weak))
void rgb_matrix_indicators_user(void)
{
    if (host_keyboard_led_state().caps_lock)
    {
        rgb_matrix_set_color(30, 0xFF, 0xFF, 0xFF);
    }
}
#endif

A keyboards/kbdfans/kbd67/mkiirgb/v1/v1.h => keyboards/kbdfans/kbd67/mkiirgb/v1/v1.h +32 -0
@@ 0,0 1,32 @@
/* Copyright 2021 DZTECH <moyi4681@live.cn>
 *
 * 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/>.
 */

#pragma once
#define XXX KC_NO
#include "quantum.h"
#define LAYOUT_65_ansi_blocker( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K0E, \
    K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E, \
    K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B,      K2D, K2E, \
    K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B,      K3D, K3E, \
    K40, K41, K42,           K45,           K48,      K4A, K4B,      K4D, K4E  \
) { \
    { K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K0E }, \
    { K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E }, \
    { K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, XXX, K2D, K2E }, \
    { K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, XXX, K3D, K3E }, \
    { K40, K41, K42, XXX, XXX, K45, XXX, XXX, K48, XXX, K4A, K4B, XXX, K4D, K4E }  \
}

A keyboards/kbdfans/kbd67/mkiirgb/v2/v2.c => keyboards/kbdfans/kbd67/mkiirgb/v2/v2.c +124 -0
@@ 0,0 1,124 @@
/* Copyright 2021 DZTECH <moyi4681@live.cn>
 *
 * 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/>.
 */

#include "v2.h"
#ifdef RGB_MATRIX_ENABLE
const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
	
	{0, C8_8,  C7_8, C6_8},   // LA17
	{0, C9_8,  C7_7, C6_7},   // LA16
	{0, C9_7,  C8_7, C6_6},   // LA15	
	{0, C9_6,  C8_6, C7_6},   // LA14
	{0, C9_5,  C8_5, C7_5},   // LA13	
	{0, C9_4,  C8_4, C7_4},   // LA12	
	{0, C9_3,  C8_3, C7_3},   // LA11	
	{0, C9_2,  C8_2, C7_2},   // LA10	
	{0, C9_1,  C8_1,  C7_1},  // LA9	
	{0, C2_9,  C3_9,  C4_9},  // LB0
	{0, C1_9,  C3_10, C4_10}, // LB1
	{0, C1_10, C2_10, C4_11}, // LB2
	{0, C1_11, C2_11, C3_11}, // LB3
	{0, C1_13, C2_13, C3_13}, // LB5
	{0, C1_14, C2_14, C3_14}, // LB6
	
	{0, C1_7,  C2_7, C3_7},   // LA7
	{0, C1_6,  C2_6, C3_6},   // LA6	
	{0, C1_5,  C2_5, C3_5},   // LA5	
	{0, C1_4,  C2_4, C3_4},   // LA4	
	{0, C1_3,  C2_3, C3_3},   // LA3	
	{0, C1_2,  C2_2, C4_3},   // LA2	
	{0, C1_1,  C3_2, C4_2},   // LA1	
	{0, C2_1,  C3_1,  C4_1},  // LA0
	{0, C9_9,  C8_9,  C7_9},  // LB9
	{0, C9_10, C8_10, C7_10}, // LB10
	{0, C9_11, C8_11, C7_11}, // LB11
	{0, C9_12, C8_12, C7_12}, // LB12
	{0, C9_13, C8_13, C7_13}, // LB13
	{0, C9_14, C8_14, C7_14}, // LB14
	{0, C1_15, C2_15, C3_15}, // LB7

    {0, C1_8,  C2_8, C3_8},   // LA8
	{1, C9_6,  C8_6, C7_6},   // LC14
	{1, C9_5,  C8_5, C7_5},   // LC13	
	{1, C9_4,  C8_4, C7_4},   // LC12	
	{1, C9_3,  C8_3, C7_3},   // LC11	
	{1, C9_2,  C8_2, C7_2},   // LC10	
	{1, C9_1,  C8_1,  C7_1},  // LC9
	{1, C2_9,  C3_9,  C4_9},  // LD0
	{1, C1_9,  C3_10, C4_10}, // LD1
	{1, C1_10, C2_10, C4_11}, // LD2
	{1, C1_11, C2_11, C3_11}, // LD3
	{1, C1_12, C2_12, C3_12}, // LD4
	{1, C1_13, C2_13, C3_13}, // LD5
	{0, C1_16, C2_16, C3_16}, // LB8

	{1, C9_8,  C7_7, C6_7},   // LC16
	{1, C1_5,  C2_5, C3_5},   // LC5
	{1, C1_4,  C2_4, C3_4},   // LC4
	{1, C1_3,  C2_3, C3_3},   // LC3	
	{1, C1_2,  C2_2, C4_3},   // LC2	
	{1, C1_1,  C3_2, C4_2},   // LC1
	{1, C9_9,  C8_9,  C7_9},  // LD9
	{1, C9_10, C8_10, C7_10}, // LD10
	{1, C9_11, C8_11, C7_11}, // LD11
	{1, C9_12, C8_12, C7_12}, // LD12
	{1, C1_14, C2_14, C3_14}, // LD6
	{1, C1_15, C2_15, C3_15}, // LD7
	{1, C1_16, C2_16, C3_16}, // LD8
	{0, C9_15, C8_15, C6_14}, // LB15

	{1, C8_8,  C7_8, C6_8},   // LC17
	{1, C1_8,  C2_8, C3_8},   // LC8	
	{1, C1_7,  C2_7, C3_7},   // LC7
	{1, C2_1,  C3_1,  C4_1},  // LC0
	{1, C9_14, C8_14, C7_14}, // LD14
	{1, C9_15, C8_15, C6_14}, // LD15
	{1, C8_16, C7_16, C6_16}, // LD17
	{0, C8_16, C7_16, C6_16}, // LB17
	{0, C9_16, C7_15, C6_15}, // LB16

};

led_config_t g_led_config = { {
    {  0,  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, NO_LED,42,  43 },
    {  44, 45, 46, 47, 48, 49, 50, 51,  52, 53, 54,  55, NO_LED,56,  57 },
    {  58, 59, 60, NO_LED, NO_LED,  61, NO_LED, NO_LED,  62,  NO_LED,  63,  64, NO_LED,  65,  66 }
}, {
    {0,0},{15,0},{30,0},{45,0},{60,0},{75,0},{90,0},{105,0},{120,0},{135,0},{150,0},{165,0},{180,0},{203,0},{224,0},
	{4,16},{23,16},{38,16},{53,16},{68,16},{83,16},{98,16},{113,16},{128,16},{143,16},{158,16},{173,16},{188,16},{206,16},{224,16},
	{6,32},{26,32},{41,32},{56,32},{71,32},{86,32},{101,32},{116,32},{131,32},{146,32},{161,32},{176,32},{201,32},{224,32},
	{9,48},{34,48},{49,48},{64,48},{79,48},{94,48},{109,48},{124,48},{139,48},{154,48},{169,48},{189,48},{210,48},{224,48},
	{2,64},{21,64},{39,64},{96,64},{152,64},{171,64},{195,64},{210,64},{224,64}
}, {
    1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1,
    1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1,
    1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 
    1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1,
    1, 1, 1, 4, 1, 1, 1, 1, 1
} };


__attribute__ ((weak))
void rgb_matrix_indicators_user(void)
{
    if (host_keyboard_led_state().caps_lock)
    {
        rgb_matrix_set_color(30, 0xFF, 0xFF, 0xFF);
    }
}
#endif

A keyboards/kbdfans/kbd67/mkiirgb/v2/v2.h => keyboards/kbdfans/kbd67/mkiirgb/v2/v2.h +32 -0
@@ 0,0 1,32 @@
/* Copyright 2021 DZTECH <moyi4681@live.cn>
 *
 * 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/>.
 */

#pragma once
#define XXX KC_NO
#include "quantum.h"
#define LAYOUT_65_ansi_blocker( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K0E, \
    K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E, \
    K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B,      K2D, K2E, \
    K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B,      K3D, K3E, \
    K40, K41, K42,           K45,           K48,      K4A, K4B,      K4D, K4E  \
) { \
    { K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K0E }, \
    { K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E }, \
    { K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, XXX, K2D, K2E }, \
    { K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, XXX, K3D, K3E }, \
    { K40, K41, K42, XXX, XXX, K45, XXX, XXX, K48, XXX, K4A, K4B, XXX, K4D, K4E }  \
}

A keyboards/kbdfans/kbd67/mkiirgb/v3/config.h => keyboards/kbdfans/kbd67/mkiirgb/v3/config.h +75 -0
@@ 0,0 1,75 @@
/* Copyright 2021 DZTECH <moyi4681@live.cn>
 *
 * 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/>.
 */

#pragma once

#include "config_common.h"

/* USB Device descriptor parameter */
#define VENDOR_ID       0x4B42 // KB
#define PRODUCT_ID      0x1226
#define DEVICE_VER      0x0002
#define MANUFACTURER    KBDfans
#define PRODUCT         kbd67mkiirgb v3

/* key matrix size */
#define MATRIX_ROWS 5
#define MATRIX_COLS 15
#define MATRIX_ROW_PINS { F0, F1, F4, E6, C6 }
#define MATRIX_COL_PINS { F7, F6, F5, C7, B0, B1, B2, B3, B4, D7, D6, D4, D5, D3, D2}
#define UNUSED_PINS

/* COL2ROW, ROW2COL*/
#define DIODE_DIRECTION COL2ROW

/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCE 5
/* disable these deprecated features by default */
#define NO_ACTION_MACRO
#define NO_ACTION_FUNCTION
#ifdef RGB_MATRIX_ENABLE
#define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
#define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
#define USB_SUSPEND_WAKEUP_DELAY 5000
#define RGB_MATRIX_KEYPRESSES
#define DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN	
#define DISABLE_RGB_MATRIX_BAND_SAT
#define DISABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
#define DISABLE_RGB_MATRIX_BAND_SPIRAL_SAT
#define DISABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
#define DISABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
#define DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
#define DISABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
#define DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
#define DISABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
#define DISABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
#define DISABLE_RGB_MATRIX_SPLASH
#define DISABLE_RGB_MATRIX_MULTISPLASH
#define DISABLE_RGB_MATRIX_SOLID_SPLASH
#define DISABLE_RGB_MATRIX_SOLID_MULTISPLASH
#define DISABLE_RGB_MATRIX_DIGITAL_RAIN
#define DISABLE_RGB_MATRIX_RAINDROPS
#define DISABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
#define RGB_MATRIX_LED_PROCESS_LIMIT 4
#define RGB_MATRIX_LED_FLUSH_LIMIT 26
#define RGB_MATRIX_STARTUP_MODE RGB_MATRIX_CYCLE_ALL
#define DRIVER_ADDR_1 0b0110000
#define DRIVER_ADDR_2 0b0110000 // this is here for compliancy reasons.
#define DRIVER_COUNT 1
#define DRIVER_1_LED_TOTAL 67
#define DRIVER_LED_TOTAL DRIVER_1_LED_TOTAL
#define DRIVER_INDICATOR_LED_TOTAL 0
#endif

A keyboards/kbdfans/kbd67/mkiirgb/v3/readme.md => keyboards/kbdfans/kbd67/mkiirgb/v3/readme.md +13 -0
@@ 0,0 1,13 @@
# KBD67 Mk.II RGB V3 (Hotswap)

A hotswap 65% keyboard with USB C, inswitch RGB, and ESD protection.

* Keyboard Maintainer: [moyi4681](https://github.com/moyi4681)
* Hardware Supported: KBD67 Mk.II RGB V3
* Hardware Availability: [kbdfans](https://kbdfans.myshopify.com/)

Make example for this keyboard (after setting up your build environment):

    make kbdfans/kbd67/mkiirgb/v3:default

See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).

A keyboards/kbdfans/kbd67/mkiirgb/v3/rules.mk => keyboards/kbdfans/kbd67/mkiirgb/v3/rules.mk +28 -0
@@ 0,0 1,28 @@
# MCU name
MCU = atmega32u4

# Bootloader selection
BOOTLOADER = lufa-ms
BOOTLOADER_SIZE = 6144

# Build Options
#   change yes to no to disable
#
BOOTMAGIC_ENABLE = lite        # Virtual DIP switch configuration
MOUSEKEY_ENABLE = no          # Mouse keys
EXTRAKEY_ENABLE = yes          # Audio control and System control
CONSOLE_ENABLE = no            # Console for debug
COMMAND_ENABLE = no            # Commands for debug and configuration
# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
SLEEP_LED_ENABLE = no          # Breathing sleep LED during USB suspend
# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
NKRO_ENABLE = yes              # USB Nkey Rollover
BACKLIGHT_ENABLE = no          # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = no           # Enable keyboard RGB underglow
BLUETOOTH_ENABLE = no          # Enable Bluetooth
AUDIO_ENABLE = no              # Audio output
RGB_MATRIX_ENABLE = yes        # Use RGB matrix
RGB_MATRIX_DRIVER = IS31FL3741
LTO_ENABLE = yes

LAYOUTS = 65_ansi_blocker

A keyboards/kbdfans/kbd67/mkiirgb/v3/v3.c => keyboards/kbdfans/kbd67/mkiirgb/v3/v3.c +126 -0
@@ 0,0 1,126 @@
/* Copyright 2021 DZTECH <moyi4681@live.cn>
 *
 * 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/>.
 */

#include "v3.h"

#ifdef RGB_MATRIX_ENABLE

const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
    {0, CS21_SW1, CS20_SW1, CS19_SW1},
    {0, CS21_SW2, CS20_SW2, CS19_SW2},
    {0, CS21_SW3, CS20_SW3, CS19_SW3}, 
    {0, CS21_SW4, CS20_SW4, CS19_SW4},    
    {0, CS21_SW5, CS20_SW5, CS19_SW5},
    {0, CS21_SW6, CS20_SW6, CS19_SW6},
    {0, CS21_SW7, CS20_SW7, CS19_SW7}, 
    {0, CS21_SW8, CS20_SW8, CS19_SW8},    
    {0, CS24_SW1, CS23_SW1, CS22_SW1}, 
    {0, CS24_SW2, CS23_SW2, CS22_SW2}, 
    {0, CS24_SW3, CS23_SW3, CS22_SW3},
    {0, CS24_SW4, CS23_SW4, CS22_SW4},   
    {0, CS24_SW5, CS23_SW5, CS22_SW5},
    {0, CS24_SW6, CS23_SW6, CS22_SW6},
    {0, CS24_SW7, CS23_SW7, CS22_SW7}, 
    
    {0, CS15_SW1, CS14_SW1, CS13_SW1},     
    {0, CS15_SW2, CS14_SW2, CS13_SW2},
    {0, CS15_SW3, CS14_SW3, CS13_SW3},
    {0, CS15_SW4, CS14_SW4, CS13_SW4},
    {0, CS15_SW5, CS14_SW5, CS13_SW5},
    {0, CS15_SW6, CS14_SW6, CS13_SW6},
    {0, CS15_SW7, CS14_SW7, CS13_SW7},
    {0, CS15_SW8, CS14_SW8, CS13_SW8},     
    {0, CS30_SW1, CS29_SW1, CS28_SW1}, 
    {0, CS30_SW2, CS29_SW2, CS28_SW2},
    {0, CS30_SW3, CS29_SW3, CS28_SW3},
    {0, CS30_SW4, CS29_SW4, CS28_SW4},
    {0, CS30_SW5, CS29_SW5, CS28_SW5},
    {0, CS30_SW6, CS29_SW6, CS28_SW6},
    {0, CS30_SW7, CS29_SW7, CS28_SW7}, 
    
    {0, CS12_SW1, CS11_SW1, CS10_SW1},     
    {0, CS12_SW2, CS11_SW2, CS10_SW2},  
    {0, CS12_SW3, CS11_SW3, CS10_SW3},      
    {0, CS12_SW4, CS11_SW4, CS10_SW4},      
    {0, CS12_SW5, CS11_SW5, CS10_SW5},      
    {0, CS12_SW6, CS11_SW6, CS10_SW6},      
    {0, CS12_SW7, CS11_SW7, CS10_SW7},  
    {0, CS12_SW8, CS11_SW8, CS10_SW8},     
    {0, CS33_SW1, CS32_SW1, CS31_SW1},      
    {0, CS33_SW2, CS32_SW2, CS31_SW2},     
    {0, CS33_SW3, CS32_SW3, CS31_SW3},     
    {0, CS33_SW4, CS32_SW4, CS31_SW4}, 
    {0, CS33_SW5, CS32_SW5, CS31_SW5}, 
    {0, CS33_SW7, CS32_SW7, CS31_SW7}, 
    
    {0, CS9_SW1, CS8_SW1, CS7_SW1},     
    {0, CS9_SW2, CS8_SW2, CS7_SW2},     
    {0, CS9_SW3, CS8_SW3, CS7_SW3}, 
    {0, CS9_SW4, CS8_SW4, CS7_SW4},     
    {0, CS9_SW5, CS8_SW5, CS7_SW5},     
    {0, CS9_SW6, CS8_SW6, CS7_SW6},     
    {0, CS9_SW7, CS8_SW7, CS7_SW7},     
    {0, CS9_SW8, CS8_SW8, CS7_SW8},    
    {0, CS36_SW1, CS35_SW1, CS34_SW1},
    {0, CS36_SW2, CS35_SW2, CS34_SW2},
    {0, CS36_SW3, CS35_SW3, CS34_SW3},
    {0, CS36_SW4, CS35_SW4, CS34_SW4},
    {0, CS36_SW5, CS35_SW5, CS34_SW5},
    {0, CS36_SW7, CS35_SW7, CS34_SW7},
    
    {0, CS3_SW1, CS2_SW1, CS1_SW1},
    {0, CS3_SW2, CS2_SW2, CS1_SW2},
    {0, CS3_SW3, CS2_SW3, CS1_SW3},
    {0, CS3_SW6, CS2_SW6, CS1_SW6},
//    {0, CS39_SW1, CS38_SW1, CS37_SW1},    
    {0, CS39_SW2, CS38_SW2, CS37_SW2},
    {0, CS39_SW3, CS38_SW3, CS37_SW3},
    {0, CS39_SW4, CS38_SW4, CS37_SW4},
    {0, CS39_SW5, CS38_SW5, CS37_SW5},
    {0, CS39_SW7, CS38_SW7, CS37_SW7}                   
                                                                                                     
};
led_config_t g_led_config = { {
    {  0,  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, NO_LED,42,  43 },
    {  44, 45, 46, 47, 48, 49, 50, 51,  52, 53, 54,  NO_LED,55, 56,  57 },
    {  58, 59, 60, NO_LED, NO_LED,  61, NO_LED, NO_LED,  NO_LED, 62, 63,  64,  65,  66 }
}, {
    {0,0},{15,0},{30,0},{45,0},{60,0},{75,0},{90,0},{105,0},{120,0},{135,0},{150,0},{165,0},{180,0},{203,0},{224,0},
	{4,16},{23,16},{38,16},{53,16},{68,16},{83,16},{98,16},{113,16},{128,16},{143,16},{158,16},{173,16},{188,16},{206,16},{224,16},
	{6,32},{26,32},{41,32},{56,32},{71,32},{86,32},{101,32},{116,32},{131,32},{146,32},{161,32},{176,32},{201,32},{224,32},
	{9,48},{34,48},{49,48},{64,48},{79,48},{94,48},{109,48},{124,48},{139,48},{154,48},{169,48},{189,48},{210,48},{224,48},
        {   2,  64 }, {  21,  64 }, {  39,  64 },                                           {  96,  64 },                             { 150,  64 }, { 165,  64 }, { 195,  64 }, { 210,  64 }, { 224,  64 }

}, {
    1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1,
    1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1,
    1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 
    1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1,
    1, 1, 1, 4, 1, 1, 1, 1, 1	
} };


__attribute__ ((weak))
void rgb_matrix_indicators_user(void)
{
    if (host_keyboard_led_state().caps_lock)
    {
        rgb_matrix_set_color(30, 0xFF, 0xFF, 0xFF);
    }
}
#endif

A keyboards/kbdfans/kbd67/mkiirgb/v3/v3.h => keyboards/kbdfans/kbd67/mkiirgb/v3/v3.h +33 -0
@@ 0,0 1,33 @@
/* Copyright 2021 DZTECH <moyi4681@live.cn>
 *
 * 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/>.
 */
 
#pragma once
#define XXX KC_NO
#include "quantum.h"
#define LAYOUT_65_ansi_blocker( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K0E, \
    K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E, \
    K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B,      K2D, K2E, \
    K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B,      K3D, K3E, \
    K40, K41, K42,           K45,           K48,      K4A, K4B,      K4D, K4E  \
) { \
    { K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K0E }, \
    { K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E }, \
    { K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, XXX, K2D, K2E }, \
    { K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, XXX, K3D, K3E }, \
    { K40, K41, K42, XXX, XXX, K45, XXX, XXX, K48, XXX, K4A, K4B, XXX, K4D, K4E }  \
}


A keyboards/planck/keymaps/rootiest/config.h => keyboards/planck/keymaps/rootiest/config.h +146 -0
@@ 0,0 1,146 @@
/* Copyright 2021 Chris Laprade
 *
 * 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/>.
 */

#pragma once

/*
 * USB/POWER OPTIONS
 */
// #define USB_MAX_POWER_CONSUMPTION 500
#define USB_SUSPEND_WAKEUP_DELAY 200
#define USB_POLLING_INTERVAL_MS 1

/*
 * MUSIC/AUDIO options
 */
#ifdef AUDIO_ENABLE
#    define AUDIO_CLICKY
#    define MUSIC_MAP
#    define AUDIO_VOICES
#    define AUDIO_VOICE_DEFAULT something
#    define AUDIO_DAC_SAMPLE_MAX 2732U

#    define DEFAULT_LAYER_SONGS \
        { SONG(QWERTY_SOUND), SONG(COLEMAK_SOUND), SONG(DVORAK_SOUND) }

/* Plays during keyboard startup */
#    define STARTUP_SONG SONG(NO_SOUND)

#endif

/*
 * MIDI options
 */
/* enable basic MIDI features:
    - MIDI notes can be sent when in Music mode is on
*/
#define MIDI_BASIC

/* enable advanced MIDI features:
    - MIDI notes can be added to the keymap
    - Octave shift and transpose
    - Virtual sustain, portamento, and modulation wheel
    - etc.
*/
#define MIDI_ADVANCED

/*
 * ENCODER options
 */
#define ENCODER_DIRECTION_FLIP
#define ENCODER_RESOLUTION 4  // Define number of stages between detents on encoders
#define ENCODERS_PAD_A \
    { B12 }
#define ENCODERS_PAD_B \
    { B13 }

/*
 * RGB options
 */
#ifdef RGBLIGHT_ENABLE
#    define RGBLIGHT_SLEEP                    // Allows rgb to sleep when the host/keyboard does
#    define RGBLIGHT_ANIMATIONS               // Enable using rgb animations
#    define RGBLIGHT_LAYERS                   // Enable indicating layers using layered rgb assignments
#    define RGBLIGHT_LAYER_BLINK              // Allows rgb layers to be blinked (activate for a set amount of time)
#    define RGBLIGHT_MAX_LAYERS 32            // Overides the default (8) max number of rgb layers
#    define RGBLIGHT_LAYERS_OVERRIDE_RGB_OFF  // Allows rgb layers to work even when rgb is toggled off
#endif

/*
 * UNICODE options
 */
#define UNICODE_SELECTED_MODES UC_WINC, UC_LNX, UC_MAC  // Define the methods used for in/outputting unicode

/*
 * TAP-DANCE options
 */
#define TAPPING_TERM 250     // Default time allowed before resetting a Tap-Dance combo
#define ONESHOT_TAP_TOGGLE 5 /* Tapping this number of times holds the key until tapped once again. */
#define ONESHOT_TIMEOUT 5000 /* Time (in ms) before the one shot key is released */
#define TAPPING_TOGGLE 3

/*
 * LEADER-KEY options
 */     // Used for on-board chording
#define LEADER_PER_KEY_TIMING
#define LEADER_TIMEOUT 500

/*
 * COMBO-KEY options
 */
#define COMBO_COUNT 2
#define COMBO_TERM 300
/*
 * MACRO per-key options
 */
#define RETRO_TAPPING_PER_KEY             // Control Retro-Tap individually by key
#define TAPPING_FORCE_HOLD_PER_KEY        // Control Force-Hold individually by key
#define IGNORE_MOD_TAP_INTERRUPT_PER_KEY  // Control Mod-Tap-Interrupt individually by key
#define PERMISSIVE_HOLD_PER_KEY           // Control Permissive-Hold individually by key

#define MK_KINETIC_SPEED  // Use kinetic acceleration for mouse-keys

// Fall-back defines to prevent compile errors if user_song_list is missing
#ifndef ZELDA_PUZZLE2
#    define ZELDA_PUZZLE2 Q__NOTE(_G5)
#endif
#ifndef SONIC_RING2
#    define SONIC_RING2 E__NOTE(_E6)
#endif
#ifndef ZELDA_CHEST2
#    define ZELDA_CHEST2 Q__NOTE(_G5)
#endif
#ifndef COIN_SOUND2
#    define COIN_SOUND2 E__NOTE(_A5)
#endif
#ifndef ONE_UP_SOUND2
#    define ONE_UP_SOUND2 Q__NOTE(_E6)
#endif
#ifndef IMPERIAL_MARCH
#    define IMPERIAL_MARCH HD_NOTE(_A4)
#endif
#ifndef MARIO_GAMEOVER
#    define MARIO_GAMEOVER HD_NOTE(_C5)
#endif
#ifndef LEAD_START_SOUND
#    define LEAD_START_SOUND E__NOTE(_C5)
#endif
#ifndef LEAD_SUCCESS_SOUND
#    define LEAD_SUCCESS_SOUND E__NOTE(_A5), HD_NOTE(_E6),
#endif
#ifndef LEAD_FAIL_SOUND
#    define LEAD_FAIL_SOUND E__NOTE(_A5), HD_NOTE(_E4),
#endif

A keyboards/planck/keymaps/rootiest/keymap.c => keyboards/planck/keymaps/rootiest/keymap.c +1928 -0
@@ 0,0 1,1928 @@
/* Copyright 2021 Chris Laprade
 *
 * 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/>.
 */

#include QMK_KEYBOARD_H
#include "raw_hid.h"
#include "print.h"
#include "muse.h"

/*
 * Define keyboard name to be used by UI.
 * This allows for using a different name
 * than the one defined by QMK for your board.
 */
#define KEEB_MODEL_NAME "The Rootiest BoogieBoard"

// Give names to the layers so they are easier to reference
enum custom_layers {
    _BASE,
    _QWERTY = _BASE,
    _COLEMAK,
    _DVORAK,
    _SYMBLS,
    _RAISE = _SYMBLS,
    _NUMBRS,
    _LOWER = _NUMBRS,
    _PLOVER,
    _FEATURS,
    _ADJUST = _FEATURS,
    _NUMPD,
    _TABULA,
    _MOUSY,
};

#define LOWER MO(_NUMBRS)
#define RAISE MO(_SYMBLS)

// unicode hexes
#define UC_DEG UC(0x00B0)   // °
#define UC_DEGF UC(0x2109)  // ℉

// Time (ms) to wait between frames for the wake rgb animation
#define WAKE_ANIMATION_TIMER_FREQUENCY 50

// Is a display connected
// #define USING_OLED_DISPLAY false

// wait DELAY ms before unregistering media keys
#define TAP_CODE_DELAY 10

// Modifier remover
#define WITHOUT_MODS(...)                      \
    do {                                       \
        const uint8_t _real_mods = get_mods(); \
        clear_mods();                          \
        {__VA_ARGS__} set_mods(_real_mods);    \
    } while (0)

// A whole boatload of audio "songs" defined for use by the keyboard
#ifdef AUDIO_ENABLE
float planck_song[][2]    = SONG(PLANCK_SOUND);
float hello_song[][2]     = SONG(ONE_UP_SOUND2);
float bye_song[][2]       = SONG(GOODBYE_SOUND);
float num_song[][2]       = SONG(DVORAK_SOUND);
float qwerty_song[][2]    = SONG(QWERTY_SOUND);
float colemak_song[][2]   = SONG(COLEMAK_SOUND);
float dvorak_song[][2]    = SONG(DVORAK_SOUND);
float funk_song[][2]      = SONG(COLEMAK_SOUND);
float workman_song[][2]   = SONG(WORKMAN_SOUND);
float term_song[][2]      = SONG(TERMINAL_SOUND);
float lover_song[][2]     = SONG(PLOVER_SOUND);
float ode_song[][2]       = SONG(ODE_TO_JOY);
float rock_song[][2]      = SONG(ROCK_A_BYE_BABY);
float clue_song[][2]      = SONG(CLUEBOARD_SOUND);
float camp_song[][2]      = SONG(CAMPANELLA);
float imp_march_song[][2] = SONG(IMPERIAL_MARCH);
float gameover_song[][2]  = SONG(MARIO_GAMEOVER);
float puzzle_song[][2]    = SONG(ZELDA_PUZZLE2);
float caps_on[][2]        = SONG(CAPS_LOCK_ON_SOUND);
float caps_off[][2]       = SONG(CAPS_LOCK_OFF_SOUND);
float slctl_on[][2]       = SONG(SCROLL_LOCK_ON_SOUND);
float slctl_off[][2]      = SONG(SCROLL_LOCK_OFF_SOUND);
float slalt_on[][2]       = SONG(NUM_LOCK_ON_SOUND);
float slalt_off[][2]      = SONG(NUM_LOCK_OFF_SOUND);
float leader_started[][2] = SONG(LEAD_START_SOUND);
float leader_succeed[][2] = SONG(LEAD_SUCCESS_SOUND);
float leader_fail[][2]    = SONG(LEAD_FAIL_SOUND);
float plover_song[][2]    = SONG(PLOVER_SOUND);
float plover_gb_song[][2] = SONG(PLOVER_GOODBYE_SOUND);
#endif

// Declare stored memory config
typedef union {
    uint32_t raw;
    struct {
        bool    do_wakeup_animation : 1;
        uint8_t rgbcon_tracker : 8;
        bool    do_wakeup_audio : 1;
    };
} user_config_t;

user_config_t user_config;

// Initialize variable holding the binary
// representation of active modifiers.
uint8_t mod_state = 0;

// Declare custom keycodes
enum custom_keycodes {
    MO_BASE = SAFE_RANGE,
    MO_SYMBLS,
    MO_NUMBRS,
    MO_FEATURS,
    QWERTY,
    COLEMAK,
    DVORAK,
    PLOVER,
    BACKLIT,
    MUSIC_ON,
    MUSIC_OFF,
    EXT_PLV,
    MY_RGBCON,
    MY_DEGREES,
    ALT_TAB,
    PRINT_WPM_KEY,
    IRONY,
    WAKE_ANI_TOG,
    WAKE_AUD_TOG,
    DO_RESET,
    KC_PRVWD,
    KC_NXTWD,
    KC_LSTRT,
    KC_LEND,
    KC_DLINE,
    KC_REDO,
    KC_SAVE,
    KC_SLCTALL,
    KC_ALTF4,
    KC_KILL,
    KC_LCUT,
    KC_LCOPY,
    KC_NXTAB,
    KC_PRVTAB,
};

// Declare unicode map array
enum unicode_names { BANG, SNEK };
const uint32_t PROGMEM unicode_map[] = {
    //[UCD_BANG]  = 0x203D,   // ‽
    //[UCD_IRONY] = 0x2E2E,   // ⸮
    [SNEK] = 0x1F40D,  // 🐍
};

enum combo_events { ZC_COPY, XV_PASTE };

const uint16_t PROGMEM copy_combo[]  = {KC_Z, KC_C, COMBO_END};
const uint16_t PROGMEM paste_combo[] = {KC_X, KC_V, COMBO_END};

combo_t key_combos[COMBO_COUNT] = {
    [ZC_COPY]  = COMBO_ACTION(copy_combo),
    [XV_PASTE] = COMBO_ACTION(paste_combo),
};

// Tap Dance key declarations
enum {
    TD_DEG_DEGF,
    TD_SMILEY,
    TD_LSHFT_CAPS,
    TD_LCTL_STICKY,
    TD_LALT_STICKY,
    TD_LOWER,
    TD_RAISE,
};

// Declare available Tap-Dance states
typedef enum {
    TD_NONE,
    TD_SINGLE_TAP,
    TD_DOUBLE_TAP,
    TD_TRIPLE_TAP,
    TD_DOUBLE_SINGLE_TAP,
    TD_SINGLE_HOLD,
    TD_DOUBLE_HOLD,
    TD_TRIPLE_HOLD,
    TD_UNKNOWN,
} td_state_t;

// Tap-Dance struct
typedef struct {
    bool       is_press_action;
    td_state_t state;
} td_tap_t;

// Whether or not to do the wake animation+sound
bool do_wake_animation;

// Variable to keep track of the rgb mode assigned by the RGB_CON key
static uint8_t rgbcon_tracker = 0;

// Used by the on-board WPM tracker
char wpm_str[12];

// Variables used for the alt-tab key
bool     is_alt_tab_active = false;
uint16_t alt_tab_timer     = 0;

// Variables used by the Irony key
#define IRONY_HOLD_DELAY 500
uint16_t irony_pressed_time;
bool     irony_active  = false;
bool     irony_shifted = false;
char     irony_str[4]  = "⸮";
char     bang_str[4]   = "‽";

// Variables used for the rgb wakeup animation
static uint16_t wake_rgb_timer;
static uint8_t  wake_rgb_count = 0;
bool            waking_up      = false;
bool            do_wake_audio  = false;

// Muse variables
bool     muse_mode      = false;
bool     musical_mode   = false;
uint8_t  last_muse_note = 0;
uint16_t muse_counter   = 0;
uint8_t  muse_offset    = 70;
uint16_t muse_tempo     = 50;

// Used by Leader key chords
bool did_leader_succeed;
LEADER_EXTERNS();

// Tap-Dance stuffs, initializing functions that are coded further below
td_state_t cur_dance(qk_tap_dance_state_t* state);
void       sml_finished(qk_tap_dance_state_t* state, void* user_data);
void       sml_reset(qk_tap_dance_state_t* state, void* user_data);
void       scap_finished(qk_tap_dance_state_t* state, void* user_data);
void       scap_reset(qk_tap_dance_state_t* state, void* user_data);
void       slctl_finished(qk_tap_dance_state_t* state, void* user_data);
void       slctl_reset(qk_tap_dance_state_t* state, void* user_data);
void       slalt_finished(qk_tap_dance_state_t* state, void* user_data);
void       slalt_reset(qk_tap_dance_state_t* state, void* user_data);
bool       lctl_sticky = false;
bool       lalt_sticky = false;

// This function is called when lock indicators (caps-lock led) are changed/toggled/updated
bool led_update_user(led_t led_state) {
    rgblight_set_layer_state(10, led_state.caps_lock);
#ifdef AUDIO_ENABLE
    static uint8_t caps_state = 0;
    if (caps_state != led_state.caps_lock) {
        // When the caps-lock led state changes play sounds
        led_state.caps_lock ? PLAY_SONG(caps_on) : PLAY_SONG(caps_off);
        caps_state = led_state.caps_lock;
    }
#endif
    return true;
}

// Define key layout/layers
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {                                             // Define all the layers
    [_BASE] = LAYOUT_planck_mit(                                                                           //
        KC_GESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC,                      //
        LT(_TABULA, KC_TAB), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,       //
        TD(TD_LSHFT_CAPS), KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_SFTENT,  //
        TD(TD_LCTL_STICKY), KC_LEAD, KC_LGUI, TD(TD_LALT_STICKY), MO(_SYMBLS), KC_SPC, MO(_NUMBRS), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT),
    /*
    Base Layer [0]
     * ,-----------------------------------------------------------------------------------.
     * |Gr/ESC|   Q  |   W  |   E  |   R  |   T  |   Y  |   U  |   I  |   O  |   P  |BckSpc|
     * |------+------+------+------+------+------+------+------+------+------+------+------|
     * |Tabula|   A  |   S  |   D  |   F  |   G  |   H  |   J  |   K  |   L  |   ;  |   '  |
     * |------+------+------+------+------+------+------+------+------+------+------+------|
     * |SH/CAP|   Z  |   X  |   C  |   V  |   B  |   N  |   M  |   ,  |   .  |   /  |Enter |
     * |------+------+------+------+------+------+------+------+------+------+------+------|
     * | LCtrl|Leader|  OS  |  Alt |Symbol|    Space    |Number| Left | Dwn  |  Up  | Right|
     * `-----------------------------------------------------------------------------------'
    */

    [_COLEMAK] = LAYOUT_planck_mit(                                                                        //
        KC_GESC, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC,                   //
        LT(_TABULA, KC_TAB), KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT,          //
        TD(TD_LSHFT_CAPS), KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_SFTENT,  //
        TD(TD_LCTL_STICKY), KC_LEAD, KC_LGUI, TD(TD_LALT_STICKY), MO(_SYMBLS), KC_SPC, MO(_NUMBRS), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT),
    /*
    Colemak Layer [1]
     * ,-----------------------------------------------------------------------------------.
     * |Gr/ESC|   Q  |   W  |   F  |   P  |   G  |   J  |   L  |   U  |   Y  |   ;  | Bksp |
     * |------+------+------+------+------+------+------+------+------+------+------+------|
     * |Tabula|   A  |   R  |   S  |   T  |   D  |   H  |   N  |   E  |   I  |   O  |  "   |
     * |------+------+------+------+------+------+------+------+------+------+------+------|
     * |SH/CAP|   Z  |   X  |   C  |   V  |   B  |   K  |   M  |   ,  |   .  |   /  |Enter |
     * |------+------+------+------+------+------+------+------+------+------+------+------|
     * | LCtrl|Leader|  OS  |  Alt |Symbol|    Space    |Number| Left | Dwn  |  Up  | Right|
     * `-----------------------------------------------------------------------------------'
    */

    [_DVORAK] = LAYOUT_planck_mit(                                                                    //
        KC_GESC, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPC,         //
        LT(_TABULA, KC_TAB), KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_TRNS, KC_S, KC_SLSH,  //
        TD(TD_LSHFT_CAPS), KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_SFTENT,  //
        TD(TD_LCTL_STICKY), KC_LEAD, KC_LGUI, TD(TD_LALT_STICKY), MO(_SYMBLS), KC_SPC, MO(_NUMBRS), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT),
    /* Dvorak Layer [2]
     * ,-----------------------------------------------------------------------------------.
     * |Gr/ESC|   "  |   ,  |   .  |   P  |   Y  |   F  |   G  |   C  |   R  |   L  | Bksp |
     * |------+------+------+------+------+------+------+------+------+------+------+------|
     * |Tabula|   A  |   O  |   E  |   U  |   I  |   D  |   H  |   T  |   N  |   S  |  /   |
     * |------+------+------+------+------+------+------+------+------+------+------+------|
     * |SH/CAP|   ;  |   Q  |   J  |   K  |   X  |   B  |   M  |   W  |   V  |   Z  |Enter |
     * |------+------+------+------+------+------+------+------+------+------+------+------|
     * | LCtrl|Leader|  OS  |  Alt |Symbol|    Space    |Number| Left | Dwn  |  Up  | Right|
     * `-----------------------------------------------------------------------------------'
     */
    [_SYMBLS] = LAYOUT_planck_mit(                                                                                     //
        KC_MPLY, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC,       //
        KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE,                 //
        KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, LSFT(KC_LCTL), LSFT(KC_LCTL), KC_HOME, KC_END, KC_TRNS,  //
        TG(_NUMPD), KC_TRNS, KC_TRNS, KC_TRNS, TO(_BASE), KC_TRNS, KC_TRNS, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY),
    /*
    Symbols Layer [3]
    * ,-----------------------------------------------------------------------------------.
    * | Play |   !  |   @  |   #  |   $  |   %  |   ^  |   &  |   *  |   (  |   )  |BckSpc|
    * |------+------+------+------+------+------+------+------+------+------+------+------|
    * |Delete|  F1  |  F2  |  F3  |  F4  |  F5  |  F6  |   _  |   +  |   {  |   }  |   |  |
    * |------+------+------+------+------+------+------+------+------+------+------+------|
    * | Shift|  F7  |  F8  |  F9  |  F10 |  F11 |  F12 |LShLCt|LShLCt| Home |  End |------|
    * |------+------+------+------+------+------+------+------+------+------+------+------|
    * | TG(7)|------|------|------| Base |    -----    | MO(4)| Next | Vol- | Vol+ | Play |
    * `-----------------------------------------------------------------------------------'
    */

    [_NUMBRS] = LAYOUT_planck_mit(                                                                          //
        KC_MPLY, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC,                       //
        KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS,       //
        KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NUHS, KC_NUBS, KC_PGUP, KC_PGDN, KC_TRNS,  //
        TG(_NUMPD), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, TO(_BASE), KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY),

    /*
    Numbers Layer [4]
    * ,-----------------------------------------------------------------------------------.
    * | Play |   1  |   2  |   3  |   4  |   5  |   6  |   7  |   8  |   9  |   0  |BckSpc|
    * |------+------+------+------+------+------+------+------+------+------+------+------|
    * |Delete|  F1  |  F2  |  F3  |  F4  |  F5  |  F6  |   -  |   =  |   [  |   ]  |   \  |
    * |------+------+------+------+------+------+------+------+------+------+------+------|
    * | Shift|  F7  |  F8  |  F9  |  F10 |  F11 |  F12 |   #  |   /  | PgUp | PgDwn|------|
    * |------+------+------+------+------+------+------+------+------+------+------+------|
    * | TG(7)|------|------|------| MO(3)|    -----    | Base | Next | Vol- | Vol+ | Play |
    * `-----------------------------------------------------------------------------------'
    */

    [_PLOVER] = LAYOUT_planck_mit(                                                        //
        KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1,           //
        XXXXXXX, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC,     //
        XXXXXXX, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,  //
        EXT_PLV, XXXXXXX, XXXXXXX, KC_C, KC_V, XXXXXXX, KC_N, KC_M, XXXXXXX, XXXXXXX, XXXXXXX),
    /* Plover Layer [5]
     * ,-----------------------------------------------------------------------------------.
     * |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |
     * |------+------+------+------+------+------+------+------+------+------+------+------|
     * |      |   S  |   T  |   P  |   H  |   *  |   *  |   F  |   P  |   L  |   T  |   D  |
     * |------+------+------+------+------+------+------+------+------+------+------+------|
     * |      |   S  |   K  |   W  |   R  |   *  |   *  |   R  |   B  |   G  |   S  |   Z  |
     * |------+------+------+------+------+------+------+------+------+------+------+------|
     * | Exit |      |      |   A  |   O  |             |   E  |   U  |      |      |      |
     * `-----------------------------------------------------------------------------------'
     */

    [_FEATURS] = LAYOUT_planck_mit(                                                                                                         //
        LCTL(LALT(KC_DEL)), DO_RESET, DEBUG, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, TD(TD_DEG_DEGF), TD(TD_SMILEY), KC_DEL,  //
        RGB_VAI, RGB_VAD, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, DF(_BASE), DF(_COLEMAK), DF(_DVORAK), TO(_PLOVER), MY_RGBCON,            //
        KC_TRNS, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, TERM_ON, TERM_OFF, CK_ON, CK_OFF, KC_ENTER,                                  //
        KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, TG(_MOUSY), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
    /*
    Special Features Layer [6]
    * ,-----------------------------------------------------------------------------------.
    * |C+A+DL| Reset| Debug|RGBTog|RGBMod| Hue+ | Hue- | Sat+ | Sat- |Unicod| Emoji|Delete|
    * |------+------+------+------+------+------+------+------+------+------+------+------|
    * |RGBVAI|RGBVAD|MU_MOD| AU_ON|AU_OFF|RALTGU|SALTGU| Base |Colemk|Dvorak|Plover|RGBCON|
    * |------+------+------+------+------+------+------+------+------+------+------+------|
    * |------|MUV_DE|MUV_IN| MU_ON|MU_OFF| MI_ON|MI_OFF|TERMON|TRMOFF|CLK-ON|CLKOFF|Enter |
    * |------+------+------+------+------+------+------+------+------+------+------+------|
    * |------|------|------|------|------|    TG(8)    |------|------|------|------|------|
    * `-----------------------------------------------------------------------------------'
    */

    [_NUMPD] = LAYOUT_planck_mit(                                                                              //
        KC_ESC, KC_HOME, KC_UP, KC_END, KC_PERC, KC_LCBR, KC_RCBR, KC_TAB, KC_P7, KC_P8, KC_P9, KC_BSPC,       //
        KC_TILD, KC_LEFT, KC_DOWN, KC_RGHT, KC_BSLS, KC_LBRC, KC_RBRC, KC_PSLS, KC_P4, KC_P5, KC_P6, KC_PMNS,  //
        KC_LSFT, KC_SLSH, KC_CUT, KC_COPY, KC_PASTE, KC_LT, KC_GT, KC_PAST, KC_P1, KC_P2, KC_P3, KC_PPLS,      //
        TO(_BASE), KC_LEAD, KC_LGUI, KC_LALT, KC_LCPO, KC_SPC, KC_RCPC, KC_HASH, KC_P0, KC_PDOT, KC_PENT),
    /*
    Numpad Layer [7]
    * ,-----------------------------------------------------------------------------------.
    * | Esc  | Home |  Up  |  End |   %  |   {  |   }  |  Tab |   7  |   8  |   9  |BckSpc|
    * |------+------+------+------+------+------+------+------+------+------+------+------|
    * |   ~  | Left | Down | Right|   \  |   [  |   ]  |   /  |   4  |   5  |   6  |   -  |
    * |------+------+------+------+------+------+------+------+------+------+------+------|
    * | Shift|   /  |Ctrl+X|Ctrl+C|Ctrl+V|   <  |   >  |   *  |   1  |   2  |   3  |   +  |
    * |------+------+------+------+------+------+------+------+------+------+------+------|
    * | Base |Leader|  Alt |  OS  |LCtl/(|    Space    |)/RCtl|   #  |   0  |   .  |Enter |
    * `-----------------------------------------------------------------------------------'
    */
    [_TABULA] = LAYOUT_planck_mit(                                                                                                   //
        KC_ESC, KC_ALTF4, VLK_TOG, PRINT_WPM_KEY, WAKE_ANI_TOG, WAKE_AUD_TOG, KC_REDO, UC_MOD, UC_M_WC, CG_TOGG, AG_TOGG, KC_DLINE,  //
        KC_NXTAB, KC_SLCTALL, KC_SAVE, KC_TRNS, KC_FIND, SH_TG, SH_TG, IRONY, KC_LCUT, KC_LCOPY, KC_TRNS, KC_KILL,                   //
        KC_LSFT, KC_UNDO, KC_CUT, KC_COPY, KC_PASTE, KC_PRVWD, KC_NXTWD, TG(_MOUSY), KC_TRNS, KC_HOME, KC_END, KC_SFTENT,            //
        TO(_BASE), KC_LCTL, KC_LGUI, KC_LALT, KC_LSPO, ALT_TAB, KC_RSPC, KC_PRVWD, KC_BRID, KC_BRIU, KC_NXTWD),
    /* Tabular Layer [8]
     * ,-----------------------------------------------------------------------------------.
     * |  Esc |Alt+F4|Veloci|  WPM |WakANI|WakAUD|Ctrl+Y|UCMode|UCWinC|CtGUTg|AltGTg| DLine|
     * |------+------+------+------+------+------+------+------+------+------+------+------|
     * |  Tab |Ctrl+A|Ctrl+S|------|Ctrl+F| SWAP | SWAP |  ⸮^‽ |CutLin|CpyLin|------|DelLin|
     * |------+------+------+------+------+------+------+------+------+------+------+------|
     * | Shift|Ctrl+Z|Ctrl+X|Ctrl+C|Ctrl+V|PrVWin|NxtWin| TG(8)|------| Home |  End |Enter |
     * |------+------+------+------+------+------+------+------+------+------+------+------|
     * | Base | LCtrl|  Alt |  OS  |LSft/(|   Alt+Tab   |)/RSft|PrvSel|ScrBr-|ScrBr+|NxtSel|
     * `-----------------------------------------------------------------------------------'
     */

    [_MOUSY] = LAYOUT_planck_mit(                                                                                                  //
        KC_ESC, KC_BTN1, KC_MS_U, KC_BTN2, KC_TRNS, KC_TRNS, KC_TRNS, UC_MOD, UC_M_WC, CG_TOGG, AG_TOGG, KC_BSPC,  //
        KC_TAB, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS, KC_TRNS, KC_TRNS, IRONY, VLK_TOG, KC_TRNS, KC_TRNS, KC_TRNS,                   //
        KC_LSFT, KC_UNDO, KC_CUT, KC_COPY, KC_PASTE, KC_PRVWD, KC_NXTWD, KC_TRNS, KC_HOME, KC_BTN3, KC_END, KC_SFTENT,             //
        TO(_BASE), KC_LCTL, KC_LGUI, KC_LALT, KC_BTN1, ALT_TAB, KC_BTN2, KC_WH_L, KC_WH_D, KC_WH_U, KC_WH_R)};
/* MousePad Layer [9]
 * ,-----------------------------------------------------------------------------------.
 * | Esc  |MsBtn1| MsUp |MsBtn2|------|------|------|UCMode|UCWinC|CtGUTg|AltGTg|BckSpc|
 * |------+------+------+------+------+------+------+------+------+------+------+------|
 * |   ~  |MsLeft|MsDown|MsRigt|------|------|------|  ⸮^‽ |Veloci|------|------|------|
 * |------+------+------+------+------+------+------+------+------+------+------+------|
 * | Shift|------|Ctrl+X|Ctrl+C|Ctrl+V|------|------|------| Home |MsBtn3|  End |Enter |
 * |------+------+------+------+------+------+------+------+------+------+------+------|
 * | Base | LCtrl|  Alt |  OS  |MsBtn1|   Alt+Tab   |MsBtn2|MsWhlL|MsWhlD|MsWhlU|MsWhlR|
 * `-----------------------------------------------------------------------------------'
 */

// Define RGB layers | assign leds and their values for each rgb layer
const rgblight_segment_t PROGMEM my_warning_layer[]  = RGBLIGHT_LAYER_SEGMENTS({1, 9, HSV_RED}, {0, 1, HSV_RED});
const rgblight_segment_t PROGMEM my_allgood_layer[]  = RGBLIGHT_LAYER_SEGMENTS({1, 9, HSV_GREEN}, {0, 1, HSV_GREEN});
const rgblight_segment_t PROGMEM my_capslock_layer[] = RGBLIGHT_LAYER_SEGMENTS({1, 1, HSV_RED}, {8, 1, HSV_RED});
const rgblight_segment_t PROGMEM my_number_layer[]   = RGBLIGHT_LAYER_SEGMENTS({1, 1, HSV_MAGENTA}, {8, 1, HSV_MAGENTA});
const rgblight_segment_t PROGMEM my_symbol_layer[]   = RGBLIGHT_LAYER_SEGMENTS({1, 1, HSV_GREEN}, {8, 1, HSV_GREEN});
const rgblight_segment_t PROGMEM my_tabula_layer[]   = RGBLIGHT_LAYER_SEGMENTS({3, 4, HSV_CORAL}, {1, 1, HSV_CORAL}, {8, 1, HSV_CORAL});
const rgblight_segment_t PROGMEM my_mousy_layer[]    = RGBLIGHT_LAYER_SEGMENTS({3, 4, HSV_TURQUOISE}, {1, 1, HSV_TURQUOISE}, {8, 1, HSV_TURQUOISE}, {7, 1, HSV_MAGENTA});
const rgblight_segment_t PROGMEM my_numpad_layer[]   = RGBLIGHT_LAYER_SEGMENTS({3, 4, HSV_GOLD}, {1, 1, HSV_GOLD}, {8, 1, HSV_GOLD}, {7, 1, HSV_BLUE});
const rgblight_segment_t PROGMEM my_features_layer[] = RGBLIGHT_LAYER_SEGMENTS({3, 4, HSV_BLUE}, {1, 1, HSV_BLUE}, {8, 1, HSV_BLUE});
const rgblight_segment_t PROGMEM my_base_layer[]     = RGBLIGHT_LAYER_SEGMENTS({0, 0, HSV_BLACK});
const rgblight_segment_t PROGMEM my_colemak_layer[]  = RGBLIGHT_LAYER_SEGMENTS({1, 1, HSV_GREEN});
const rgblight_segment_t PROGMEM my_dvorak_layer[]   = RGBLIGHT_LAYER_SEGMENTS({1, 1, HSV_ORANGE});
const rgblight_segment_t PROGMEM my_plover_layer[]   = RGBLIGHT_LAYER_SEGMENTS({1, 1, HSV_GOLD});

// Define the array of rgb layers. Later layers take precedence
const rgblight_segment_t* const PROGMEM my_rgb_layers[] = RGBLIGHT_LAYERS_LIST(my_base_layer,      // Base Layer
                                                                               my_colemak_layer,   // Overrides previous layer
                                                                               my_dvorak_layer,    // Overrides previous layers
                                                                               my_symbol_layer,    // Overrides previous layers
                                                                               my_number_layer,    // ...etc                                                                              my_features_layer,  // Overrides  layers
                                                                               my_plover_layer,    //
                                                                               my_features_layer,  //
                                                                               my_numpad_layer,    //
                                                                               my_tabula_layer,    //
                                                                               my_mousy_layer,     //
                                                                               my_capslock_layer,  //
                                                                               my_warning_layer,   //
                                                                               my_allgood_layer);  // CapsLock Layer);

// Configure encoders
bool encoder_update_user(uint8_t index, bool clockwise) {
    if (musical_mode) {
        if (clockwise) {
            tap_code16(MU_MOD);
        } else {
            tap_code16(MU_MOD);
        }
    } else {
        if (muse_mode) {
            if (IS_LAYER_ON(_RAISE)) {
                if (clockwise) {
                    muse_offset++;
                } else {
                    muse_offset--;
                }
            } else {
                if (clockwise) {
                    muse_tempo += 1;
                } else {
                    muse_tempo -= 1;
                }
            }
        } else {
            if (index == 0) { /* First encoder */
                uint16_t held_keycode_timer = timer_read();
                switch (biton32(layer_state)) {
                    case 0:                                 // Base Layer
                        if ((get_mods() & MOD_MASK_GUI)) {  // GUI-ed
                            if (clockwise) {
                                tap_code(KC_RIGHT);

                            } else {
                                tap_code(KC_LEFT);
                            }
                        } else if ((get_mods() & MOD_MASK_ALT)) {  // Alt-ed
                            if (clockwise) {
                                tap_code16(LALT(KC_TAB));  // Alt+Tabbing
                            } else {
                                tap_code16(LSA(KC_TAB));
                            }
                        } else if ((get_mods() & MOD_MASK_SHIFT)) {  // Shifted
                            const uint8_t _real_mods = get_mods();
                            unregister_code16(KC_LSFT);
                            unregister_code16(KC_RSFT);
                            clear_mods();
                            if (clockwise) {
                                tap_code16(KC_MS_WH_DOWN);
                            } else {
                                tap_code16(KC_MS_WH_UP);
                            }
                            set_mods(_real_mods);
                        } else if ((get_mods() & MOD_MASK_CTRL)) {  // Ctrl-ed
                            if (clockwise) {
                                tap_code16(RCTL(KC_TAB));  // Ctrl+Tabbing
                            } else {
                                tap_code16(RCS(KC_TAB));
                            }
                        } else {  // Normal or unspecified modifiers
                            if (clockwise) {
                                // Volume control requires extra timer to function correctly
                                register_code(KC_VOLU);
                                while (timer_elapsed(held_keycode_timer) < TAP_CODE_DELAY) {
                                    // no-op
                                }
                                unregister_code(KC_VOLD);
                            } else {
                                register_code(KC_VOLD);
                                while (timer_elapsed(held_keycode_timer) < TAP_CODE_DELAY) {
                                    // no-op
                                }
                                unregister_code(KC_VOLU);
                            }
                        }
                        return false;
                        break;
                    case 3:  // Symbols Layer
                        if (clockwise) {
                            tap_code(KC_WH_D);  // Mouse wheeling
                        } else {
                            tap_code(KC_WH_U);
                        }
                        return false;
                        break;
                    case 4:  // Numbers Layer
                        if (clockwise) {
                            tap_code(KC_WH_D);  // Mouse wheeling
                        } else {
                            tap_code(KC_WH_U);
                        }
                        return false;
                        break;
                    case 6:  // Features Layer
                        if (clockwise) {
                            tap_code16(KC_DOWN);
                        } else {
                            tap_code16(KC_UP);
                        }
                    default:  // Any other layer
                        if ((get_mods() & MOD_MASK_CSAG)) {
                            if (clockwise) {
                                WITHOUT_MODS({ SEND_STRING(SS_TAP(X_RIGHT)); });
                            } else {
                                WITHOUT_MODS({ SEND_STRING(SS_TAP(X_LEFT)); });
                            }
                        } else {
                            if (clockwise) {
                                tap_code(KC_DOWN);  // Simple Up/Down
                            } else {
                                tap_code(KC_UP);
                            }
                        }
                        return false;
                        break;
                }
            } else if (index == 1) { /* Second encoder (if we had one) */
                if (clockwise) {
                    tap_code16(LCTL(KC_LEFT));  // Ctrl+Left/Right
                } else {
                    tap_code16(LCTL(KC_RIGHT));
                }
            }
        }
    }
    return true;
}

// OLED CONFIGURATION
/*
static void render_logo(void) {
    static const char PROGMEM qmk_logo[] = {0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0x00};

    oled_write_P(qmk_logo, false);
}
*/

// Process Combo events
void process_combo_event(uint16_t combo_index, bool pressed) {
    switch (combo_index) {
        case ZC_COPY:
            if (pressed) {
                tap_code16(LCTL(KC_C));
            }
            break;
        case XV_PASTE:
            if (pressed) {
                tap_code16(LCTL(KC_V));
            }
            break;
    }
}

// Runs every time a key is pressed or released
bool process_record_user(uint16_t keycode, keyrecord_t* record) {
#ifdef CONSOLE_ENABLE
    dprintf("KL: kc: 0x%04X, col: %u, row: %u, pressed: %b, time: %u, interrupt: %b, count: %u\n", keycode, record->event.key.col, record->event.key.row, record->event.pressed, record->event.time, record->tap.interrupted, record->tap.count);
#endif
    // Store the current modifier state in the variable for later reference
    mod_state = get_mods();
    switch (keycode) {
        case QWERTY:
            if (record->event.pressed) {
                set_single_persistent_default_layer(_QWERTY);
                PLAY_SONG(qwerty_song);
            }
            return false;
            break;
        case COLEMAK:
            if (record->event.pressed) {
                set_single_persistent_default_layer(_COLEMAK);
                PLAY_SONG(colemak_song);
            }
            return false;
            break;
        case DVORAK:
            if (record->event.pressed) {
                set_single_persistent_default_layer(_DVORAK);
                PLAY_SONG(dvorak_song);
            }
            return false;
            break;
        case PLOVER:
            if (record->event.pressed) {
#ifdef AUDIO_ENABLE
                stop_all_notes();
                PLAY_SONG(plover_song);
#endif
                layer_off(_RAISE);
                layer_off(_LOWER);
                layer_off(_ADJUST);
                layer_on(_PLOVER);
                if (!eeconfig_is_enabled()) {
                    eeconfig_init();
                }
                keymap_config.raw  = eeconfig_read_keymap();
                keymap_config.nkro = 1;
                eeconfig_update_keymap(keymap_config.raw);
            }
            return false;
            break;
        case EXT_PLV:
            if (record->event.pressed) {
#ifdef AUDIO_ENABLE
                PLAY_SONG(plover_gb_song);
#endif
                layer_off(_PLOVER);
            }
            return false;
            break;
        case MO_SYMBLS:
            if (record->event.pressed) {
                layer_on(_SYMBLS);
            } else {
                layer_off(_SYMBLS);
            }
            return false;
        case MO_NUMBRS:
            if (record->event.pressed) {
                layer_on(_NUMBRS);
            } else {
                layer_off(_NUMBRS);
            }
            return false;
        case MO_FEATURS:
            if (record->event.pressed) {
                layer_on(_FEATURS);
            } else {
                layer_off(_FEATURS);
            }
            return false;
        case MUSIC_ON:
            if (record->event.pressed) {
                musical_mode = true;
                register_code16(MU_ON);
            } else {
                unregister_code16(MU_ON);
            }
            break;
        case MUSIC_OFF:
            if (record->event.pressed) {
                musical_mode = false;
                register_code16(MU_OFF);
            } else {
                unregister_code16(MU_OFF);
            }
            break;
        case KC_PRVWD:  // Control+Left
            if (record->event.pressed) {
                if (keymap_config.swap_lctl_lgui) {
                    register_mods(mod_config(MOD_LALT));
                    register_code(KC_LEFT);
                } else {
                    register_mods(mod_config(MOD_LCTL));
                    register_code(KC_LEFT);
                }
            } else {
                if (keymap_config.swap_lctl_lgui) {
                    unregister_mods(mod_config(MOD_LALT));
                    unregister_code(KC_LEFT);
                } else {
                    unregister_mods(mod_config(MOD_LCTL));
                    unregister_code(KC_LEFT);
                }
            }
            break;
        case KC_NXTWD:  // Control+Right
            if (record->event.pressed) {
                if (keymap_config.swap_lctl_lgui) {
                    register_mods(mod_config(MOD_LALT));
                    register_code(KC_RIGHT);
                } else {
                    register_mods(mod_config(MOD_LCTL));
                    register_code(KC_RIGHT);
                }
            } else {
                if (keymap_config.swap_lctl_lgui) {
                    unregister_mods(mod_config(MOD_LALT));
                    unregister_code(KC_RIGHT);
                } else {
                    unregister_mods(mod_config(MOD_LCTL));
                    unregister_code(KC_RIGHT);
                }
            }
            break;
        case KC_PRVTAB:  // Control+Shift+Tab
            if (record->event.pressed) {
                register_mods(mod_config(MOD_LCTL));
                register_mods(mod_config(MOD_LSFT));
                register_code(KC_TAB);
            } else {
                unregister_mods(mod_config(MOD_LCTL));
                unregister_mods(mod_config(MOD_LSFT));
                unregister_code(KC_TAB);
            }
            break;
        case KC_NXTAB:  // Control+Tab
            if (record->event.pressed) {
                if (keymap_config.swap_lctl_lgui) {
                    register_mods(mod_config(MOD_LCTL));
                    register_code(KC_TAB);
                } else {
                    register_mods(mod_config(MOD_LSFT));
                    register_code(KC_TAB);
                }
            } else {
                if (keymap_config.swap_lctl_lgui) {
                    unregister_mods(mod_config(MOD_LALT));
                    unregister_code(KC_RIGHT);
                } else {
                    unregister_mods(mod_config(MOD_LCTL));
                    unregister_code(KC_RIGHT);
                }
            }
            break;
        case KC_LSTRT:  // Basically just Home
            if (record->event.pressed) {
                if (keymap_config.swap_lctl_lgui) {
                    // CMD-arrow on Mac, but we have CTL and GUI swapped
                    register_mods(mod_config(MOD_LCTL));
                    register_code(KC_LEFT);
                } else {
                    register_code(KC_HOME);
                }
            } else {
                if (keymap_config.swap_lctl_lgui) {
                    unregister_mods(mod_config(MOD_LCTL));
                    unregister_code(KC_LEFT);
                } else {
                    unregister_code(KC_HOME);
                }
            }
            break;
        case KC_LEND:  // Basically just End
            if (record->event.pressed) {
                if (keymap_config.swap_lctl_lgui) {
                    // CMD-arrow on Mac, but we have CTL and GUI swapped
                    register_mods(mod_config(MOD_LCTL));
                    register_code(KC_RIGHT);
                } else {
                    register_code(KC_END);
                }
            } else {
                if (keymap_config.swap_lctl_lgui) {
                    unregister_mods(mod_config(MOD_LCTL));
                    unregister_code(KC_RIGHT);
                } else {
                    unregister_code(KC_END);
                }
            }
            break;
        case KC_DLINE:  // Control+BackSpace
            if (record->event.pressed) {
                register_mods(mod_config(MOD_LCTL));
                register_code(KC_BSPC);
            } else {
                unregister_mods(mod_config(MOD_LCTL));
                unregister_code(KC_BSPC);
            }
            break;
        case KC_COPY:  // Copy: Control+C
            if (record->event.pressed) {
                register_mods(mod_config(MOD_LCTL));
                register_code(KC_C);
            } else {
                unregister_mods(mod_config(MOD_LCTL));
                unregister_code(KC_C);
            }
            return false;
        case KC_PASTE:  // Paste: Control+V
            if (record->event.pressed) {
                register_mods(mod_config(MOD_LCTL));
                register_code(KC_V);
            } else {
                unregister_mods(mod_config(MOD_LCTL));
                unregister_code(KC_V);
            }
            return false;
        case KC_CUT:  // Cut: Control+X
            if (record->event.pressed) {
                register_mods(mod_config(MOD_LCTL));
                register_code(KC_X);
            } else {
                unregister_mods(mod_config(MOD_LCTL));
                unregister_code(KC_X);
            }
            return false;
            break;
        case KC_UNDO:  // Undo: Control+Z
            if (record->event.pressed) {
                register_mods(mod_config(MOD_LCTL));
                register_code(KC_Z);
            } else {
                unregister_mods(mod_config(MOD_LCTL));
                unregister_code(KC_Z);
            }
            return false;
        case KC_REDO:  // Redo: Control+Y
            if (record->event.pressed) {
                register_mods(mod_config(MOD_LCTL));
                register_code(KC_Y);
            } else {
                unregister_mods(mod_config(MOD_LCTL));
                unregister_code(KC_Y);
            }
            break;
        case KC_SAVE:  // Save: Control+S
            if (record->event.pressed) {
                register_mods(mod_config(MOD_LCTL));
                register_code(KC_S);
            } else {
                unregister_mods(mod_config(MOD_LCTL));
                unregister_code(KC_S);
            }
            return false;
        case KC_FIND:  // Find: Control+F
            if (record->event.pressed) {
                register_mods(mod_config(MOD_LCTL));
                register_code(KC_F);
            } else {
                unregister_mods(mod_config(MOD_LCTL));
                unregister_code(KC_F);
            }
            return false;
        case KC_SLCTALL:  // Select All: Control+A
            if (record->event.pressed) {
                register_mods(mod_config(MOD_LCTL));
                register_code(KC_A);
            } else {
                unregister_mods(mod_config(MOD_LCTL));
                unregister_code(KC_A);
            }
            return false;
        case KC_KILL:  // Kill: Delete Line
            if (record->event.pressed) {
                tap_code(KC_HOME);
                register_mods(mod_config(MOD_LSFT));
                tap_code(KC_END);
                unregister_mods(mod_config(MOD_LSFT));
                tap_code(KC_DELETE);
            } else {
            }
            return false;
        case KC_LCUT:  // Cut Line
            if (record->event.pressed) {
                tap_code(KC_HOME);
                register_mods(mod_config(MOD_LSFT));
                tap_code(KC_END);
                unregister_mods(mod_config(MOD_LSFT));
                register_mods(mod_config(MOD_LCTL));
                tap_code(KC_X);
                unregister_mods(mod_config(MOD_LCTL));
            } else {
            }
            return false;
        case KC_LCOPY:  // Copy Line
            if (record->event.pressed) {
                tap_code(KC_HOME);
                register_mods(mod_config(MOD_LSFT));
                tap_code(KC_END);
                unregister_mods(mod_config(MOD_LSFT));
                register_mods(mod_config(MOD_LCTL));
                tap_code(KC_C);
                unregister_mods(mod_config(MOD_LCTL));
                tap_code(KC_END);
            } else {
            }
            return false;
        case KC_ALTF4:  // Close Window: Alt+F4
            if (record->event.pressed) {
                register_mods(mod_config(MOD_LALT));
                register_code(KC_F4);
            } else {
                unregister_mods(mod_config(MOD_LALT));
                unregister_code(KC_F4);
            }
            return false;
        case ALT_TAB:  // Change Window: Super ⭍ Alt+Tab
            if (record->event.pressed) {
                if (!is_alt_tab_active) {
                    is_alt_tab_active = true;
                    register_code(KC_LALT);
                }
                alt_tab_timer = timer_read();
                register_code(KC_TAB);
#ifdef CONSOLE_ENABLE
                dprint("I've tabbed to another window!\n");
#endif
            } else {
                unregister_code(KC_TAB);
            }
            break;
        case KC_BSPC: {
            // Initialize a boolean variable that keeps track
            // of the delete key status: registered or not?
            static bool delkey_registered;
            if (record->event.pressed) {
                // Detect the activation of either shift keys
                if (mod_state & MOD_MASK_SHIFT) {
                    // First temporarily canceling both shifts so that
                    // shift isn't applied to the KC_DEL keycode
                    del_mods(MOD_MASK_SHIFT);
                    register_code(KC_DEL);
                    // Update the boolean variable to reflect the status of KC_DEL
                    delkey_registered = true;
                    // Reapplying modifier state so that the held shift key(s)
                    // still work even after having tapped the Backspace/Delete key.
                    set_mods(mod_state);
                    return false;
                }
            } else {  // on release of KC_BSPC
                // In case KC_DEL is still being sent even after the release of KC_BSPC
                if (delkey_registered) {
                    unregister_code(KC_DEL);
                    delkey_registered = false;
                    return false;
                }
            }
        }
            // Let QMK process the KC_BSPC keycode as usual outside of shift
            return true;

        case DO_RESET:  // Reset button with LED indication
            if (record->event.pressed) {
                rgblight_set_effect_range(0, 9);
                rgblight_sethsv_noeeprom(HSV_RED);
                rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT);
                rgblight_blink_layer(11, 5000);
                reset_keyboard();
            }
            break;
        case WAKE_ANI_TOG:  // Toggle the Wakeup RGB animation
            if (record->event.pressed) {
                user_config.do_wakeup_animation ^= 1;   // Toggles the status
                eeconfig_update_user(user_config.raw);  // Writes the new status to EEPROM
                if (user_config.do_wakeup_animation) {
                    print("Wake animation enabled.\n");
                    PLAY_SONG(slctl_on);

                } else {
                    print("Wake animation disabled.\n");
                    PLAY_SONG(slctl_off);
                }
            }
            break;
        case WAKE_AUD_TOG:  // Toggle the wake-up music
            if (record->event.pressed) {
                user_config.do_wakeup_audio ^= 1;       // Toggles the status
                eeconfig_update_user(user_config.raw);  // Writes the new status to EEPROM
                if (user_config.do_wakeup_audio) {
                    print("Wake music enabled.\n");
                    PLAY_SONG(slctl_on);

                } else {
                    print("Wake music disabled.\n");
                    PLAY_SONG(slctl_off);
                }
            }
            break;
        case IRONY:  // Outputs Irony/Interrobang symbols
            if ((get_mods() & MOD_MASK_SHIFT)) {
                irony_shifted = true;
            } else {
                irony_shifted = false;
            }
            if (record->event.pressed) {
                if (irony_shifted) {
                    send_unicode_string(bang_str);
                } else {
                    send_unicode_string(irony_str);
                }
                irony_active       = true;
                irony_pressed_time = timer_read();
            } else {
                irony_active       = false;
                irony_pressed_time = 0;
                irony_shifted      = false;
            }
            return false;
        case TG(_NUMPD):  // Toggle the NumPad layer
            if (record->event.pressed) {
#ifdef AUDIO_ENABLE
                PLAY_SONG(hello_song);
#endif
                print("I've activated the NumPad!\n");
            } else {
            }
            break;
        case TG(_TABULA):  // Toggle the Tabula layer
            if (record->event.pressed) {
#ifdef AUDIO_ENABLE
                PLAY_SONG(lover_song);
#endif
                print("I've activated Tabular!\n");
            } else {
            }
            break;
        case TG(_MOUSY):  // Toggle the MouseyPad layer
            if (record->event.pressed) {
#ifdef AUDIO_ENABLE
                PLAY_SONG(funk_song);
#endif
                print("I've activated the MousePad!\n");
            } else {
            }
            break;
        case TO(_BASE):  // Return to the base layer
            if (record->event.pressed) {
#ifdef AUDIO_ENABLE
                PLAY_SONG(planck_song);
#endif
                print("I've returned to the Base Layer!\n");
            } else {
            }
            break;
        case PRINT_WPM_KEY:  // Prints the current average words-per-minute to the console
            sprintf(wpm_str, "Current WPM: %hu", get_current_wpm());
            printf("%s\n", wpm_str);
            break;

        case MY_RGBCON:  // Cycles through custom RGB animation presets
            if (record->event.pressed) {
                // when keycode RGB-CON is pressed
                user_config.rgbcon_tracker = rgbcon_tracker + 1;  // Toggles the status
                eeconfig_update_user(user_config.raw);
                switch (rgbcon_tracker) {
                    case 0:
                        rgblight_set_effect_range(0, 9);
                        rgblight_sethsv(HSV_BLACK);
                        rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
                        print("Changed RGB mode to: Disabled RGB\n");
                        rgbcon_tracker++;
                        break;
                    case 1:
                        rgblight_set_effect_range(0, 9);
                        rgblight_sethsv(HSV_WHITE);
                        rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
                        print("Changed RGB mode to: Static White\n");
                        rgbcon_tracker++;
                        break;
                    case 2:
                        rgblight_set_effect_range(0, 9);
                        rgblight_sethsv(HSV_CYAN);
                        rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
                        print("Changed RGB mode to: Static Cyan\n");
                        rgbcon_tracker++;
                        break;
                    case 3:
                        rgblight_set_effect_range(0, 9);
                        rgblight_sethsv(HSV_WHITE);
                        rgblight_mode(RGBLIGHT_MODE_BREATHING);
                        print("Changed RGB mode to: Breathing Lights\n");
#ifdef AUDIO_ENABLE
                        print("Played Marching song!\n");
                        PLAY_SONG(imp_march_song);
#endif
                        rgbcon_tracker++;
                        break;
                    case 4:
                        rgblight_set_effect_range(0, 9);
                        rgblight_sethsv(HSV_RED);
                        rgblight_mode(RGBLIGHT_MODE_RAINBOW_SWIRL);
                        print("Changed RGB mode to: Rainbow Swirl\n");
                        rgbcon_tracker++;
                        break;
                    case 5:
                        rgblight_set_effect_range(0, 9);
                        rgblight_sethsv(HSV_CYAN);
                        rgblight_mode(RGBLIGHT_MODE_RAINBOW_MOOD);
                        print("Changed RGB mode to: Rainbow Mood\n");
#ifdef AUDIO_ENABLE
                        print("Played Game Over song!\n");
                        PLAY_SONG(gameover_song);
#endif
                        rgbcon_tracker = 0;
                        break;
                    case 6:
                        rgblight_set_effect_range(0, 9);
                        rgblight_sethsv(HSV_BLACK);
                        rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
                        print("Changed RGB mode to: Disabled RGB\n");
                        rgbcon_tracker = 1;
                        break;
                }
            } else {
            }
            break;
    }
    return true;
};

// Runs *after* a key is pressed
void post_process_record_user(uint16_t keycode, keyrecord_t* record) {
    switch (keycode) {
        case DEBUG:
            // Blink the warning layer when the debug key is pressed
            rgblight_blink_layer_repeat(debug_enable ? 11 : 12, 1500, 3);

            // Update the console with the debug mode status
            if (debug_enable) {
                print("Debug mode enabled.\n");
                PLAY_SONG(slctl_on);

            } else {
                print("Debug mode disabled.\n");
                PLAY_SONG(slctl_off);
            }
            break;
    }
}

// RGB Default Layer assignments
layer_state_t default_layer_state_set_user(layer_state_t state) {
    state = update_tri_layer_state(state, _SYMBLS, _NUMBRS, _FEATURS);

    // Sets the default RGB layer states
    rgblight_set_layer_state(0, layer_state_cmp(state, _BASE));
    rgblight_set_layer_state(1, layer_state_cmp(state, _COLEMAK));
    rgblight_set_layer_state(2, layer_state_cmp(state, _DVORAK));
    return state;
}

// RGB Layer assignments
layer_state_t layer_state_set_user(layer_state_t state) {
    state = update_tri_layer_state(state, _SYMBLS, _NUMBRS, _FEATURS);

    // Sets the RGB layer states
    rgblight_set_layer_state(5, layer_state_cmp(state, _PLOVER));
    rgblight_set_layer_state(6, layer_state_cmp(state, _FEATURS));
    rgblight_set_layer_state(3, layer_state_cmp(state, _SYMBLS));
    rgblight_set_layer_state(4, layer_state_cmp(state, _NUMBRS));
    rgblight_set_layer_state(7, layer_state_cmp(state, _NUMPD));
    rgblight_set_layer_state(8, layer_state_cmp(state, _TABULA));
    rgblight_set_layer_state(9, layer_state_cmp(state, _MOUSY));
    return state;
}

// Runs the wakeup rgb animation + music
void rgb_wakeup_sequence(void) {
    if (waking_up) {
        if ((timer_elapsed(wake_rgb_timer) > WAKE_ANIMATION_TIMER_FREQUENCY)) {
            if (wake_rgb_count < 1) {
                rgblight_sethsv_noeeprom(HSV_OFF);
                rgblight_set_effect_range(0, 9);
            } else if (wake_rgb_count < 2 && wake_rgb_count > 0) {
                rgblight_sethsv_noeeprom(HSV_BLACK);
                rgblight_set_effect_range(0, 2);
                rgblight_sethsv_noeeprom(HSV_WHITE);
                rgblight_set_effect_range(2, 9);
            } else if (wake_rgb_count < 3 && wake_rgb_count > 1) {
                rgblight_sethsv_noeeprom(HSV_BLACK);
                rgblight_set_effect_range(0, 2);
                rgblight_sethsv_noeeprom(HSV_WHITE);
                rgblight_set_effect_range(2, 9);
            } else if (wake_rgb_count < 4 && wake_rgb_count > 2) {
                rgblight_sethsv_noeeprom(HSV_BLACK);
                rgblight_set_effect_range(0, 3);
                rgblight_sethsv_noeeprom(HSV_WHITE);
                rgblight_set_effect_range(3, 9);
            } else if (wake_rgb_count < 5 && wake_rgb_count > 3) {
                rgblight_sethsv_noeeprom(HSV_BLACK);
                rgblight_set_effect_range(0, 4);
                rgblight_sethsv_noeeprom(HSV_WHITE);
                rgblight_set_effect_range(4, 9);
            } else if (wake_rgb_count < 6 && wake_rgb_count > 4) {
                rgblight_sethsv_noeeprom(HSV_BLACK);
                rgblight_set_effect_range(0, 5);
                rgblight_sethsv_noeeprom(HSV_WHITE);
                rgblight_set_effect_range(5, 9);
            } else if (wake_rgb_count < 7 && wake_rgb_count > 5) {
                rgblight_sethsv_noeeprom(HSV_BLACK);
                rgblight_set_effect_range(0, 6);
                rgblight_sethsv_noeeprom(HSV_WHITE);
                rgblight_set_effect_range(6, 9);
            } else if (wake_rgb_count < 8 && wake_rgb_count > 6) {
                rgblight_sethsv_noeeprom(HSV_BLACK);
                rgblight_set_effect_range(0, 7);
                rgblight_sethsv_noeeprom(HSV_WHITE);
                rgblight_set_effect_range(7, 9);
            } else if (wake_rgb_count < 9 && wake_rgb_count > 7) {
                rgblight_sethsv_noeeprom(HSV_BLACK);
                rgblight_set_effect_range(0, 8);
                rgblight_sethsv_noeeprom(HSV_WHITE);
                rgblight_set_effect_range(8, 9);
            } else if (wake_rgb_count < 10 && wake_rgb_count > 8) {
                rgblight_sethsv_noeeprom(HSV_BLACK);
                rgblight_set_effect_range(0, 0);
                rgblight_sethsv_noeeprom(HSV_WHITE);
                rgblight_set_effect_range(0, 9);
            } else if (wake_rgb_count < 11 && wake_rgb_count > 9) {
                rgblight_sethsv_noeeprom(HSV_BLACK);
                rgblight_set_effect_range(0, 8);
                rgblight_sethsv_noeeprom(HSV_WHITE);
                rgblight_set_effect_range(8, 9);
            } else if (wake_rgb_count < 12 && wake_rgb_count > 10) {
                rgblight_sethsv_noeeprom(HSV_BLACK);
                rgblight_set_effect_range(0, 7);
                rgblight_sethsv_noeeprom(HSV_WHITE);
                rgblight_set_effect_range(7, 9);
            } else if (wake_rgb_count < 13 && wake_rgb_count > 11) {
                rgblight_sethsv_noeeprom(HSV_BLACK);
                rgblight_set_effect_range(0, 6);
                rgblight_sethsv_noeeprom(HSV_WHITE);
                rgblight_set_effect_range(6, 9);
            } else if (wake_rgb_count < 14 && wake_rgb_count > 12) {
                rgblight_sethsv_noeeprom(HSV_BLACK);
                rgblight_set_effect_range(0, 5);
                rgblight_sethsv_noeeprom(HSV_WHITE);
                rgblight_set_effect_range(5, 9);
            } else if (wake_rgb_count < 15 && wake_rgb_count > 13) {
                rgblight_sethsv_noeeprom(HSV_BLACK);
                rgblight_set_effect_range(0, 4);
                rgblight_sethsv_noeeprom(HSV_WHITE);
                rgblight_set_effect_range(4, 9);
            } else if (wake_rgb_count < 16 && wake_rgb_count > 14) {
                rgblight_sethsv_noeeprom(HSV_BLACK);
                rgblight_set_effect_range(0, 3);
                rgblight_sethsv_noeeprom(HSV_WHITE);
                rgblight_set_effect_range(3, 9);
            } else if (wake_rgb_count < 17 && wake_rgb_count > 15) {
                rgblight_sethsv_noeeprom(HSV_BLACK);
                rgblight_set_effect_range(0, 2);
                rgblight_sethsv_noeeprom(HSV_WHITE);
                rgblight_set_effect_range(2, 9);
            } else if (wake_rgb_count < 18 && wake_rgb_count > 16) {
                rgblight_sethsv_noeeprom(HSV_BLACK);
                rgblight_set_effect_range(0, 1);
                rgblight_sethsv_noeeprom(HSV_WHITE);
                rgblight_set_effect_range(1, 9);
            } else if (wake_rgb_count > 17) {
                // Final frame of wake-up rgb animation
                rgblight_sethsv_noeeprom(HSV_BLACK);
                rgblight_set_effect_range(0, 9);
                waking_up = false;
                print("I have awoken!\n");
#ifdef AUDIO_ENABLE
                // Play the wake-up sound *after* we finish the animation
                if (do_wake_audio) {
                    PLAY_SONG(puzzle_song);
                }
#endif
            }
            rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT);
            wake_rgb_count++;
            wake_rgb_timer = timer_read();
        }
    }
}

// Spits out some unicode special characters in response to a tap-dance
void send_degree_symbol(qk_tap_dance_state_t* state, void* user_data) {
    switch (state->count) {
        case 4:
            // ℃
            unicode_input_start();
            register_hex(0x2103);
            unicode_input_finish();
            print("You pressed the Degrees key 4 times!\n");
            reset_tap_dance(state);
            break;
        case 3:
            //℉
            unicode_input_start();
            register_hex(0x2109);
            unicode_input_finish();
            print("You pressed the Degrees key 3 times!\n");
            reset_tap_dance(state);
            break;
        case 2:
            // €
            unicode_input_start();
            register_hex(0x20AC);
            unicode_input_finish();
            print("You pressed the Degrees key 2 times!\n");
            reset_tap_dance(state);
            break;
        case 1:
            // °
            unicode_input_start();
            register_hex(0x00B0);
            unicode_input_finish();
            print("You pressed the Degrees key 1 time!\n");
            reset_tap_dance(state);
            break;
    }
}

// Handles per-key configuration of Retro-Tapping
bool get_retro_tapping(uint16_t keycode, keyrecord_t* record) {
    switch (keycode) {
        default:
            return false;
    }
}
// Handles per-key configuration of Mod-Tap-Interrupt
bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t* record) {
    switch (keycode) {
        default:
            return false;
    }
}
// Handles per-key configuration of Tapping Force-Hold
bool get_tapping_force_hold(uint16_t keycode, keyrecord_t* record) {
    switch (keycode) {
        default:
            return false;
    }
}
// Handles per-key configuration of Permissive-Hold
bool get_permissive_hold(uint16_t keycode, keyrecord_t* record) {
    switch (keycode) {
        default:
            return false;
    }
}
/*
 * The following two functions make leader keys "musical"
 * by playing sound at different stages of the leader chord
 */
// Called when you tap the Leader key
void leader_start(void) {
#ifdef AUDIO_ENABLE
    PLAY_SONG(leader_started);
#endif
}
// Called when either the leader sequence is completed, or the leader timeout is hit
void leader_end(void) {
    if (did_leader_succeed) {
#ifdef AUDIO_ENABLE
        PLAY_SONG(leader_succeed);
#endif
    } else {
#ifdef AUDIO_ENABLE
        PLAY_SONG(leader_fail);
#endif
    }
}

// Monitors and labels the current state of any tap-dances
td_state_t cur_dance(qk_tap_dance_state_t* state) {
    if (state->count == 1) {
        if (state->interrupted || !state->pressed) return TD_SINGLE_TAP;
        // Key has not been interrupted, but the key is still held. Means you want to send a 'HOLD'.
        else
            return TD_SINGLE_HOLD;
    } else if (state->count == 2) {
        if (state->interrupted)
            return TD_DOUBLE_SINGLE_TAP;
        else if (state->pressed)
            return TD_DOUBLE_HOLD;
        else
            return TD_DOUBLE_TAP;
    }
    if (state->count == 3) {
        if (state->interrupted || !state->pressed)
            return TD_TRIPLE_TAP;
        else
            return TD_TRIPLE_HOLD;
    } else
        return TD_UNKNOWN;
}

// Create an instance of 'td_tap_t' for each tap dance.
static td_tap_t sml_state   = {.is_press_action = true, .state = TD_NONE};
static td_tap_t scap_state  = {.is_press_action = true, .state = TD_NONE};
static td_tap_t slctl_state = {.is_press_action = true, .state = TD_NONE};
static td_tap_t slalt_state = {.is_press_action = true, .state = TD_NONE};

// Left-Shift->Sticky-Caps tap-dance finished
void scap_finished(qk_tap_dance_state_t* state, void* user_data) {
    scap_state.state = cur_dance(state);
    switch (scap_state.state) {
        case TD_SINGLE_HOLD:
            register_code(KC_LSFT);
            break;
        default:
            if (host_keyboard_leds() & (1 << USB_LED_CAPS_LOCK)) {
                tap_code(KC_CAPS);
                reset_tap_dance(state);
                break;
            } else {
                if ((state->count) >= TAPPING_TOGGLE) {
                    tap_code(KC_CAPS);
                    reset_tap_dance(state);
                    break;
                } else {
                    register_code(KC_LSFT);
                    break;
                }
            }
    }
}

// Left-Shift->Sticky-Caps tap-dance reset
void scap_reset(qk_tap_dance_state_t* state, void* user_data) {
    unregister_code(KC_LSHIFT);
    scap_state.state = TD_NONE;
}

// Sticky-Left-Control tap-dance finished
void slctl_finished(qk_tap_dance_state_t* state, void* user_data) {
    slctl_state.state = cur_dance(state);
    switch (slctl_state.state) {
        case TD_SINGLE_HOLD:
            register_code(KC_LCTL);
            break;
        default:
            if (lctl_sticky) {
                unregister_code(KC_LCTL);
                lctl_sticky = false;
                PLAY_SONG(slctl_off);
                reset_tap_dance(state);
                break;
            } else {
                if ((state->count) >= TAPPING_TOGGLE) {
                    register_code(KC_LCTL);
                    lctl_sticky = true;
                    PLAY_SONG(slctl_on);
                    reset_tap_dance(state);
                    break;
                } else {
                    register_code(KC_LCTL);
                    reset_tap_dance(state);
                    break;
                }
            }
    }
}

// Sticky-Left-Control tap-dance reset
void slctl_reset(qk_tap_dance_state_t* state, void* user_data) {
    if (!lctl_sticky) {
        unregister_code(KC_LCTL);
        slctl_state.state = TD_NONE;
    } else {
        slctl_state.state = TD_NONE;
    }
}

// Sticky-Left-Alt tap-dance finished
void slalt_finished(qk_tap_dance_state_t* state, void* user_data) {
    slalt_state.state = cur_dance(state);
    switch (slalt_state.state) {
        case TD_SINGLE_HOLD:
            register_code(KC_LALT);
            break;
        default:
            if (lalt_sticky) {
                unregister_code(KC_LALT);
                lalt_sticky = false;
                PLAY_SONG(slalt_off);
                reset_tap_dance(state);
                break;
            } else {
                if ((state->count) >= TAPPING_TOGGLE) {
                    register_code(KC_LALT);
                    lalt_sticky = true;
                    PLAY_SONG(slalt_on);
                    reset_tap_dance(state);
                    break;
                } else {
                    register_code(KC_LALT);
                    reset_tap_dance(state);
                    break;
                }
            }
    }
}

// Sticky-Left-Alt tap-dance reset
void slalt_reset(qk_tap_dance_state_t* state, void* user_data) {
    if (!lalt_sticky) {
        unregister_code(KC_LALT);
        slalt_state.state = TD_NONE;
    } else {
        slalt_state.state = TD_NONE;
    }
}

// Smiley key tap-dance finished
void sml_finished(qk_tap_dance_state_t* state, void* user_data) {
    sml_state.state = cur_dance(state);
    switch (sml_state.state) {
        default:
            switch (state->count) {
                default:
                    // 👍
                    send_unicode_string("👍");
                    print("You pressed the Emoji key at least 11 times!\n");
                    reset_tap_dance(state);
                    break;
                case 10:
                    // 👎
                    send_unicode_string("👎");
                    print("You pressed the Emoji key 10 times!\n");
                    reset_tap_dance(state);
                    break;
                case 9:
                    //🍌
                    send_unicode_string("🍌");
                    print("You pressed the Emoji key 9 times!\n");
                    reset_tap_dance(state);
                    break;
                case 8:
                    // 🍑
                    send_unicode_string("🍑");
                    print("You pressed the Emoji key 8 times!\n");
                    reset_tap_dance(state);
                    break;
                case 7:
                    // 🐕
                    send_unicode_string("🐕");
                    print("You pressed the Emoji key 7 times!\n");
                    reset_tap_dance(state);
                    break;
                case 6:
                    // 🐈
                    send_unicode_string("🐈");
                    print("You pressed the Emoji key 6 times!\n");
                    reset_tap_dance(state);
                    break;
                case 5:
                    // 🐍
                    send_unicode_string("🐍");
                    print("You pressed the Emoji key 5 times!\n");
                    reset_tap_dance(state);
                    break;
                case 4:
                    //🐒
                    send_unicode_string("🐒");
                    print("You pressed the Emoji key 4 times!\n");
                    reset_tap_dance(state);
                    break;
                case 3:
                    // 💩
                    send_unicode_string("💩");
                    print("You pressed the Emoji key 3 times!\n");
                    reset_tap_dance(state);
                    break;
                case 2:
                    // 🙁
                    send_unicode_string("🙁");
                    print("You pressed the Emoji key 2 times!\n");
                    reset_tap_dance(state);
                    break;
                case 1:
                    // 🙂
                    send_unicode_string("🙂");
                    print("You pressed the Emoji key 1 time!\n");
                    reset_tap_dance(state);
                    break;
            }
            break;
        case TD_SINGLE_HOLD:
            // 👍
            send_unicode_string("👍");
            print("You single-held the Emoji key!\n");
            reset_tap_dance(state);
            break;
        case TD_DOUBLE_HOLD:
            // 👎
            send_unicode_string("👎");
            print("You double-held the Emoji key!\n");
            reset_tap_dance(state);
            break;
        case TD_TRIPLE_HOLD:
            //🤯
            send_unicode_string("🤯");
            print("You triple-held the Emoji key!\n");
            reset_tap_dance(state);
            break;
        case TD_NONE:
            reset_tap_dance(state);
            break;
    }
}
void sml_reset(qk_tap_dance_state_t* state, void* user_data) { sml_state.state = TD_NONE; }

// Tap Dance definitions
qk_tap_dance_action_t tap_dance_actions[] = {
    // Tap once for °, twice for ℉, thrice for ℃
    [TD_DEG_DEGF]    = ACTION_TAP_DANCE_FN(send_degree_symbol),                                    //
    [TD_LSHFT_CAPS]  = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, scap_finished, scap_reset, 200),    //
    [TD_LCTL_STICKY] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, slctl_finished, slctl_reset, 200),  //
    [TD_LALT_STICKY] = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, slalt_finished, slalt_reset, 200),  //
    [TD_SMILEY]      = ACTION_TAP_DANCE_FN_ADVANCED_TIME(NULL, sml_finished, sml_reset, 500),
};

// Dip-Switch controls
void dip_switch_update_user(uint8_t index, bool active) {
    switch (index) {
        case 0: {
#ifdef AUDIO_ENABLE
            static bool play_sound = false;
#endif
            if (active) {
#ifdef AUDIO_ENABLE
                if (play_sound) {
                    PLAY_SONG(plover_song);
                }
#endif
                layer_on(_ADJUST);
            } else {
#ifdef AUDIO_ENABLE
                if (play_sound) {
                    PLAY_SONG(plover_gb_song);
                }
#endif
                layer_off(_ADJUST);
            }
#ifdef AUDIO_ENABLE
            play_sound = true;
#endif
            break;
        }
        case 1:
            if (active) {
                muse_mode = true;
            } else {
                muse_mode = false;
            }
    }
}

// Runs at every complete matrix scan
void matrix_scan_user(void) {
    // Some code for controlling MIDI output
#ifdef AUDIO_ENABLE
    if (muse_mode) {
        if (muse_counter == 0) {
            uint8_t muse_note = muse_offset + SCALE[muse_clock_pulse()];
            if (muse_note != last_muse_note) {
                stop_note(compute_freq_for_midi_note(last_muse_note));
                play_note(compute_freq_for_midi_note(muse_note), 0xF);
                last_muse_note = muse_note;
            }
        }
        muse_counter = (muse_counter + 1) % muse_tempo;
    } else {
        if (muse_counter) {
            stop_all_notes();
            muse_counter = 0;
        }
    }
#endif
    // Check the shift-state and hold-time for the Irony key
    if (irony_active) {
        if ((get_mods() & MOD_MASK_SHIFT)) {
            irony_shifted = true;
        } else {
            irony_shifted = false;
        }
        if (timer_elapsed(irony_pressed_time) >= IRONY_HOLD_DELAY) {
            if (irony_shifted) {
                send_unicode_string(bang_str);
            } else {
                send_unicode_string(irony_str);
            }
        }
    }

    // Monitor and respond to the current Alt+Tab state
    if (is_alt_tab_active) {
        if (timer_elapsed(alt_tab_timer) > 1000) {
            unregister_code(KC_LALT);
            is_alt_tab_active = false;
        }
    }
    // Monitor and perform leader-key chords
    LEADER_DICTIONARY() {
        did_leader_succeed = leading = false;

        SEQ_ONE_KEY(KC_E) {
            SEND_STRING(SS_LCTL(SS_LSFT("t")));
            did_leader_succeed = true;
        }
        SEQ_ONE_KEY(KC_C) {
            SEND_STRING(SS_LGUI("r") SS_DELAY(250) "calc\n");
            did_leader_succeed = true;
        }
        else SEQ_ONE_KEY(KC_V) {
            SEND_STRING(SS_LCTL("v"));
            did_leader_succeed = true;
        }
        else SEQ_TWO_KEYS(KC_E, KC_D) {
            SEND_STRING(SS_LGUI("r") "cmd\n" SS_LCTL("c"));
            did_leader_succeed = true;
        }
        else SEQ_TWO_KEYS(KC_A, KC_C) {
            SEND_STRING(SS_LCTL("a") SS_LCTL("c"));
            did_leader_succeed = true;
        }
        else SEQ_THREE_KEYS(KC_C, KC_A, KC_T) {
            send_unicode_string("😸");
            did_leader_succeed = true;
        }
        else SEQ_THREE_KEYS(KC_B, KC_A, KC_T) {
            send_unicode_string("🦇");
            did_leader_succeed = true;
        }
        else SEQ_THREE_KEYS(KC_D, KC_O, KC_G) {
            send_unicode_string("🐶");
            did_leader_succeed = true;
        }
        else SEQ_FIVE_KEYS(KC_S, KC_M, KC_I, KC_L, KC_E) {
            send_unicode_string("🙂");
            did_leader_succeed = true;
        }
        else SEQ_FOUR_KEYS(KC_H, KC_A, KC_P, KC_Y) {
            send_unicode_string("🙂");
            did_leader_succeed = true;
        }
        else SEQ_FIVE_KEYS(KC_H, KC_A, KC_P, KC_P, KC_Y) {
            send_unicode_string("🙂");
            did_leader_succeed = true;
        }
        else SEQ_THREE_KEYS(KC_S, KC_A, KC_D) {
            send_unicode_string("🙁");
            did_leader_succeed = true;
        }
        else SEQ_THREE_KEYS(KC_Y, KC_E, KC_S) {
            send_unicode_string("👍");
            did_leader_succeed = true;
        }
        else SEQ_TWO_KEYS(KC_N, KC_O) {
            send_unicode_string("👎");
            did_leader_succeed = true;
        }
        else SEQ_THREE_KEYS(KC_W, KC_O, KC_W) {
            send_unicode_string("🤯");
            did_leader_succeed = true;
        }
        else SEQ_THREE_KEYS(KC_P, KC_O, KC_O) {
            send_unicode_string("💩");
            did_leader_succeed = true;
        }
        else SEQ_FOUR_KEYS(KC_P, KC_O, KC_O, KC_P) {
            send_unicode_string("💩");
            did_leader_succeed = true;
        }
        else SEQ_FOUR_KEYS(KC_B, KC_O, KC_A, KC_T) {
            send_unicode_string("⛵");
            did_leader_succeed = true;
        }
        leader_end();
    }
    // Run the wake-up RGB animation if performing wake-up
    if (do_wake_animation) {
        rgb_wakeup_sequence();
    }
}

// Music mask controls

bool music_mask_user(uint16_t keycode) {
    switch (keycode) {
        case RAISE:
        case LOWER:
            return false;
        default:
            return true;
    }
}

void suspend_power_down_user(void) {
    // Runs during start of system suspend
    print("Going to sleep.");
}

void suspend_wakeup_init_user(void) {
    // Runs during wake from system suspend
}

void keyboard_post_init_user(void) {
    // Print welcome message to console
    printf("Welcome to %s!\n", KEEB_MODEL_NAME);
    // Read the user config from EEPROM
    user_config.raw   = eeconfig_read_user();
    do_wake_animation = user_config.do_wakeup_animation;
    do_wake_audio     = user_config.do_wakeup_audio;
    rgbcon_tracker    = user_config.rgbcon_tracker;

    // Tell the console the status of saved config
    if (user_config.do_wakeup_animation) {
        print("Wake animation enabled.\n");
    } else {
        print("Wake animation disabled.\n");
    }
    if (user_config.do_wakeup_audio) {
        print("Wake music enabled.\n");
    } else {
        print("Wake music disabled.\n");
    }
    switch (user_config.rgbcon_tracker) {
        case 2:
            print("RGB mode: Static White\n");
            break;
        case 3:
            print("RGB mode: Static Cyan\n");
            break;
        case 4:
            print("RGB mode: Breathing Lights\n");
            break;
        case 5:
            print("RGB mode: Rainbow Swirl\n");
            break;
        case 6:
            print("RGB mode: Rainbow Mood\n");
            break;
        default:
            print("RGB mode: Disabled RGB\n");
            break;
    }

    // Enable the LED layers
    rgblight_enable_noeeprom();  // Enables RGB, without saving settings
    rgblight_layers = my_rgb_layers;

    /*
     * Initialize the LED crawl wake animation here
     * To perform it on just the first wake
     */
    wake_rgb_timer = timer_read();
    waking_up      = true;

    // Initialize OLED display
    /*
        if (USING_OLED_DISPLAY) {
            print("Initializing display!\n");
            render_logo();
        }
    */
}

// EEPROM is getting reset!
void eeconfig_init_user(void) {
    user_config.raw                 = 0;
    eeconfig_update_user(user_config.raw);  // Write default value to EEPROM now
}

// Communicate 2-way with host via HID_RAW
#ifdef RAW_ENABLE
void raw_hid_receive(uint8_t* data, uint8_t length) {
    //  Sample code below simply echoes back to the console any data received by the raw_hid process

#    ifdef CONSOLE_ENABLE
    dprint("Received USB data from host system:\n");
    dprintf("%s\n", data);
#    endif
}
#endif

A keyboards/planck/keymaps/rootiest/readme.md => keyboards/planck/keymaps/rootiest/readme.md +37 -0
@@ 0,0 1,37 @@

![Layout Image](https://github.com/rootiest/rootiest.github.io/raw/main/img/rootiest-planck_legend.png)

# The Rootiest Planck Layout

This layout takes advantage of as many QMK features as possible for a huge complicated beast of a keyboard!

## Features include

- Encoder functions further extended by layers and modifiers
- Extensive use of the on-board speaker
- Extensive use of the backlight LEDs for startup animations, layer indicators, and bootloader/debug warnings, etc
- Many layers, both toggled and momentary.
- A toggled Numpad layer, with an emphasis on coding/accounting and with arrow keys on WASD
- A "Tabular" layer accessed by holding Tab with frequently used functions, including Alt+Tab via pressing Space
- A toggled Mouse-keys layer that allows full control of the mouse movement and buttons from the keyboard
- Use of Space-Cadet Shift/Ctrl keys on various layers
- Hold enter for Right-Shift
- Shift+BackSpace for Delete
- Grave-Esc in the top-left Esc key position
- Music, Terminal, MIDI, and RGB control on Functions layer
- QWERTY, COLEMAK, DVORAK, and PLOVER layers
- Special keys for common Ctrl+ combos like Ctrl+C, Ctrl+V, etc
- Special keys for Copy-Line, Cut-Line, Delete-Line, etc
- Special keys for Ctrl+Alt+Del, Alt+F4, etc
- Settings like rgb animation state and startup animation/sound are stored in the EEPROM to survive restart
- "Sticky keys" with audible indication allow most modifiers to be locked by pressing multiple times in quick succession
- Sticky-locking the Shift key toggles CapsLock instead of locking Shift
- Unicode characters and emoji can be sent via custom tap-dance keys
- Emoji and app-specific functions can be sent via leader-key chording
- VelociKey and word-per-minute tracking are also included

See the layout here: [Keyboard Layout](http://www.keyboard-layout-editor.com/#/gists/e48e19bc251a8d07ff8475fc1a16f43b)

To build and flash this keymap, use this command:

    qmk flash -kb planck/rev6 -km rootiest

A keyboards/planck/keymaps/rootiest/rules.mk => keyboards/planck/keymaps/rootiest/rules.mk +26 -0
@@ 0,0 1,26 @@
SRC += muse.c
ENCODER_ENABLE = yes # Enables basic encoder support
OLED_DRIVER_ENABLE = yes # Enables support for OLED displays
# UNICODE_ENABLE = yes # Allow inputting basic unicode characters
UNICODEMAP_ENABLE = yes # Enable use of Unicode mapping array
# UCIS_ENABLE = yes # Another method for generating Unicode characters via maps
TAP_DANCE_ENABLE = yes # Enable Tap-Dance
NKRO_ENABLE = yes # Enable N-Key rollover
MOUSEKEY_ENABLE = yes # Enable mouse emulation
EXTRAKEY_ENABLE = yes # Allows audio control and System control
RAW_ENABLE = yes # Enable bi-directional communication to host
CONSOLE_ENABLE = yes # Enable outputting debugging data/logs to terminal
WPM_ENABLE = yes # Enable on-board words-per-minute tracking
VELOCIKEY_ENABLE = yes # Enables dynamically changing rgb animation speed based on WPM
LEADER_ENABLE = yes # Enables Leader-Key
COMBO_ENABLE = yes # Enables combo keys
KEY_LOCK_ENABLE = yes # Enables using lock key to maintain holds
# LTO_ENABLE = yes # Does some optimisation to make firmware size smaller
# SWAP_HANDS_ENABLE = yes # Enables the swap hands function
# DEBOUNCE_TYPE = sym_eager_pk # Change debounce algorithm

# NOTE: The following requires a lot of memory to include
TERMINAL_ENABLE = yes # Enables a command-line-like interface designed to communicate through a text editor with keystrokes

# NOTE: The following is not yet available in main qmk branch
KEY_OVERRIDE_ENABLE = yes # Allows overiding modifier combos (change Shift+1 without affecting 1 or Shift's normal operation)

A keyboards/undead60m/config.h => keyboards/undead60m/config.h +75 -0
@@ 0,0 1,75 @@
/*
Copyright 2021 Franciso Escobar
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/>.
*/

#pragma once

#include "config_common.h"

/* USB Device descriptor parameter */
#define VENDOR_ID    0x4D4B // MechanicKeys
#define PRODUCT_ID   0x3C4D
#define DEVICE_VER   0x0001
#define MANUFACTURER    MechanicKeys
#define PRODUCT         Undead 60-M

/* key matrix size */
#define MATRIX_ROWS 5
#define MATRIX_COLS 16

/*
 * Keyboard Matrix Assignments
 *
 * Change this to how you wired your keyboard
 * COLS: AVR pins used for columns, left to right
 * ROWS: AVR pins used for rows, top to bottom
 * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
 *         ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
 *
*/
#define MATRIX_ROW_PINS { D0, D1, D2, D3, D5 }
#define MATRIX_COL_PINS { F0, F1, E6, C7, C6, B6, D4, B1, B0, B7, B5, B4, D7, D6, B3, B2 }
#define UNUSED_PINS

/* COL2ROW or ROW2COL */
#define DIODE_DIRECTION COL2ROW

/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCE 5

/* define if matrix has ghost (lacks anti-ghosting diodes) */
//#define MATRIX_HAS_GHOST

/* RGB Underglow */
#define RGB_DI_PIN F7
#ifdef RGB_DI_PIN
  #define RGBLED_NUM 16
  #define RGBLIGHT_SLEEP
  #define RGBLIGHT_EFFECT_BREATHING
  #define RGBLIGHT_EFFECT_RAINBOW_MOOD
  #define RGBLIGHT_EFFECT_RAINBOW_SWIRL
  #define RGBLIGHT_EFFECT_SNAKE
  #define RGBLIGHT_EFFECT_KNIGHT
  #define RGBLIGHT_EFFECT_CHRISTMAS
  #define RGBLIGHT_EFFECT_STATIC_GRADIENT
  #define RGBLIGHT_EFFECT_RGB_TEST
  #define RGBLIGHT_EFFECT_ALTERNATING
  #define RGBLIGHT_EFFECT_TWINKLE
#endif

/* Rotary encoder */
#define ENCODERS_PAD_A { F6 }
#define ENCODERS_PAD_B { F5 }
#define ENCODER_RESOLUTION 4

A keyboards/undead60m/info.json => keyboards/undead60m/info.json +18 -0
@@ 0,0 1,18 @@
{
  "keyboard_name": "Undead-60M",
  "url": "",
  "maintainer": "qmk",
  "width": 16,
  "height": 5,
  "layouts": {
    "LAYOUT": {
      "layout": [
        {"label": "F1", "x": 0, "y": 0}, {"label": "F2", "x": 1, "y": 0}, {"label": "Esc", "x": 3.5, "y": 0}, {"label": "1", "x": 4.5, "y": 0}, {"label": "2", "x": 5.5, "y": 0}, {"label": "3", "x": 6.5, "y": 0}, {"label": "4", "x": 7.5, "y": 0}, {"label": "5", "x": 8.5, "y": 0}, {"label": "6", "x": 9.5, "y": 0}, {"label": "7", "x": 10.5, "y": 0}, {"label": "8", "x": 11.5, "y": 0}, {"label": "9", "x": 12.5, "y": 0}, {"label": "0", "x": 13.5, "y": 0}, {"label": "-", "x": 14.5, "y": 0}, {"label": "=", "x": 15.5, "y": 0}, {"label": "Backspace", "x": 16.5, "y": 0},
        {"label": "F2", "x": 0, "y": 1}, {"label": "F3", "x": 1, "y": 1}, {"label": "Tab", "x": 3.5, "y": 1}, {"label": "Q", "x": 5, "y": 1}, {"label": "W", "x": 6, "y": 1}, {"label": "E", "x": 7, "y": 1}, {"label": "R", "x": 8, "y": 1}, {"label": "T", "x": 9, "y": 1}, {"label": "Y", "x": 10, "y": 1}, {"label": "U", "x": 11, "y": 1}, {"label": "I", "x": 12, "y": 1}, {"label": "O", "x": 13, "y": 1}, {"label": "P", "x": 14, "y": 1}, {"label": "[", "x": 15, "y": 1}, {"label": "]", "x": 16, "y": 1}, {"label": "|", "x": 17, "y": 1},
        {"label": "F4", "x": 0, "y": 2}, {"label": "F5", "x": 1, "y": 2}, {"label": "Caps", "x": 3.5, "y": 2}, {"label": "A", "x": 5.25, "y": 2}, {"label": "S", "x": 6.25, "y": 2}, {"label": "D", "x": 7.25, "y": 2}, {"label": "F", "x": 8.25, "y": 2}, {"label": "G", "x": 9.25, "y": 2}, {"label": "H", "x": 10.25, "y": 2}, {"label": "J", "x": 11.25, "y": 2}, {"label": "K", "x": 12.25, "y": 2}, {"label": "L", "x": 13.25, "y": 2}, {"label": ";", "x": 14.25, "y": 2}, {"label": "'", "x": 15.25, "y": 2}, {"label": "Enter", "x": 16.25, "y": 2},
        {"label": "F6", "x": 0, "y": 3}, {"label": "F7", "x": 1, "y": 3}, {"label": "Shift", "x": 3.5, "y": 3}, {"label": "Z", "x": 5.5, "y": 3}, {"label": "X", "x": 6.5, "y": 3}, {"label": "C", "x": 7.5, "y": 3}, {"label": "V", "x": 8.5, "y": 3}, {"label": "B", "x": 9.5, "y": 3}, {"label": "N", "x": 10.5, "y": 3}, {"label": "M", "x": 11.5, "y": 3}, {"label": ",", "x": 12.5, "y": 3}, {"label": ".", "x": 13.5, "y": 3}, {"label": "/", "x": 14.5, "y": 3}, {"label": "Shift", "x": 15.5, "y": 3},
        {"label": "F1", "x": 0, "y": 4}, {"label": "F2", "x": 1, "y": 4}, {"label": "Ctrl", "x": 3.5, "y": 4}, {"label": "OS", "x": 4.75, "y": 4}, {"label": "Alt", "x": 6, "y": 4}, {"label": "Space", "x": 7.25, "y": 4}, {"label": "Alt", "x": 13.5, "y": 4}, {"label": "OS", "x": 14.75, "y": 4}, {"label": "Ctrl", "x": 16, "y": 4}, {"label": "Fn", "x": 17.25, "y": 4}
      ]
    }
  }
}

A keyboards/undead60m/keymaps/default/keymap.c => keyboards/undead60m/keymaps/default/keymap.c +51 -0
@@ 0,0 1,51 @@
/* Copyright 2021 Francisco Escobar
  * 
  * 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/>. 
*/ 

#include QMK_KEYBOARD_H

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
  [0] = LAYOUT( /* 0: qwerty */
    KC_MPLY, KC_P1,   KC_ESC,  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_P2,   KC_P3,   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_P4,   KC_P5,   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_P6,   KC_P7,   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_P8,   KC_P9,   KC_LCTL, KC_LGUI, KC_LALT,                            KC_SPC,                             KC_RALT, KC_RGUI, KC_RCTL, MO(1)
  ),

  [1] = LAYOUT( /* 1: fn */
    KC_TRNS, KC_TRNS,   KC_GRV,  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_TRNS,
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_TRNS, KC_UP,   KC_TRNS, RESET,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_TRNS, KC_TRNS,                            KC_TRNS,                            KC_TRNS, KC_TRNS, MO(2),   KC_TRNS
  ),

  [2] = LAYOUT( /* 2: media */
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_TRNS, KC_TRNS,                            KC_TRNS,                            KC_TRNS, MO(3), KC_TRNS, KC_TRNS
  ),

  [3] = LAYOUT( /*3: RGB */
    RGB_TOG, RGB_MOD,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    RGB_HUD, RGB_HUI,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    RGB_SAD, RGB_SAI,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    RGB_VAD, RGB_VAI,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_TRNS, KC_TRNS,                            KC_TRNS,                            KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
  ),
};

A keyboards/undead60m/keymaps/via/keymap.c => keyboards/undead60m/keymaps/via/keymap.c +52 -0
@@ 0,0 1,52 @@
/* Copyright 2021 Francisco Escobar
  * 
  * 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/>. 
*/ 

#include QMK_KEYBOARD_H

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
  [0] = LAYOUT( /* 0: qwerty */
    KC_MPLY, KC_P1,   KC_ESC,  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_P2,   KC_P3,   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_P4,   KC_P5,   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_P6,   KC_P7,   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_P8,   KC_P9,   KC_LCTL, KC_LGUI, KC_LALT,                            KC_SPC,                             KC_RALT, KC_RGUI, KC_RCTL, MO(1)
  ),

  [1] = LAYOUT( /* 1: fn */
    KC_TRNS, KC_TRNS,   KC_GRV,  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_TRNS,
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_TRNS, KC_UP,   KC_TRNS, RESET,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_TRNS, KC_TRNS,                            KC_TRNS,                            KC_TRNS, KC_TRNS, MO(2),   KC_TRNS
  ),

  [2] = LAYOUT( /* 2: media */
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_TRNS, KC_TRNS,                            KC_TRNS,                            KC_TRNS, MO(3), KC_TRNS, KC_TRNS
  ),

  [3] = LAYOUT( /*3: RGB */
    RGB_TOG, RGB_MOD,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    RGB_HUD, RGB_HUI,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    RGB_SAD, RGB_SAI,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    RGB_VAD, RGB_VAI,   KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
    KC_TRNS, KC_TRNS,   KC_TRNS, KC_TRNS, KC_TRNS,                            KC_TRNS,                            KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
  ),
};


A keyboards/undead60m/keymaps/via/rules.mk => keyboards/undead60m/keymaps/via/rules.mk +1 -0
@@ 0,0 1,1 @@
VIA_ENABLE = yes
\ No newline at end of file

A keyboards/undead60m/readme.md => keyboards/undead60m/readme.md +27 -0
@@ 0,0 1,27 @@
# Undead 60M

![Undead 60M](https://i.imgur.com/0EWBzNth.jpeg)

![Undead 60M](https://i.imgur.com/m8z1kMVh.jpeg)

![Undead 60M](https://i.imgur.com/AZIfVzNh.jpeg)

A 60% PCB with some add-ons
  - RGB Underglow
  - Macro cluster
  - Hotswap
  - optional Knob

* Keyboard Maintainer: [jfescobar18](https://github.com/jfescobar18)
* Hardware Supported: Undead 60M PCB
* Hardware Availability: [MechanicKeys](https://www.facebook.com/MechanicKeys-104963764775280)

Make example for this keyboard (after setting up your build environment):

    make undead60m/:default

Flashing example for this keyboard:

    make undead60m:default:flash
    
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).

A keyboards/undead60m/rules.mk => keyboards/undead60m/rules.mk +25 -0
@@ 0,0 1,25 @@
# MCU name
MCU = atmega32u4

# Bootloader selection
BOOTLOADER = atmel-dfu

# Build Options
#   change yes to no to disable
#
BOOTMAGIC_ENABLE = lite		# Virtual DIP switch configuration
MOUSEKEY_ENABLE = yes       # Mouse keys
EXTRAKEY_ENABLE = yes       # Audio control and System control
CONSOLE_ENABLE = no         # Console for debug
COMMAND_ENABLE = no         # Commands for debug and configuration
# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
SLEEP_LED_ENABLE = no       # Breathing sleep LED during USB suspend
# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
NKRO_ENABLE = no            # USB Nkey Rollover
BACKLIGHT_ENABLE = no       # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = yes       # Enable keyboard RGB underglow
BLUETOOTH_ENABLE = no       # Enable Bluetooth
AUDIO_ENABLE = no           # Audio output
KEYBOARD_LOCK_ENABLE = yes
ENCODER_ENABLE = yes
LTO_ENABLE = yes

A keyboards/undead60m/undead60m.c => keyboards/undead60m/undead60m.c +60 -0
@@ 0,0 1,60 @@
 /* Copyright 2021 Francisco Escobar
  * 
  * 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/>. 
  */ 
	  
#include "undead60m.h"
bool encoder_update_kb(uint8_t index, bool clockwise) {
  if (!encoder_update_user(index, clockwise)) { return false; }
    if (index == 0) {
      switch (get_highest_layer(layer_state)) {
        case 0: /* Layer 1: Volume */
          if (clockwise) {
              tap_code(KC_VOLD);
          } else {
              tap_code(KC_VOLU);
          }
          break;
        case 1: /* Layer 2: Scroll */
          if (clockwise) {
              tap_code(KC_WH_U);
          } else {
              tap_code(KC_WH_D);
          }
          break;
        case 2: /* Layer 3: Change Track */
          if (clockwise) {
              tap_code(KC_MPRV);
          } else {
              tap_code(KC_MNXT);
          }
          break;
        case 3: /* Layer 4: Brightness */
          if (clockwise) {
              tap_code(KC_BRID);
          } else {
              tap_code(KC_BRIU);
          }
          break;
        default: /* Default: Volume */
          if (clockwise) {
              tap_code(KC_VOLU);
          } else {
              tap_code(KC_VOLD);
          }
          break;
      }
  }
  return true;
}

A keyboards/undead60m/undead60m.h => keyboards/undead60m/undead60m.h +34 -0
@@ 0,0 1,34 @@
/* Copyright 2021 Francisco Escobar
  * 
  * 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/>. 
*/ 

#pragma once

#include "quantum.h"

#define LAYOUT( \
  K00, K01,   K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K0E, K0F, \
  K10, K11,   K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E, K1F, \
  K20, K21,   K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, K2D, K2E,      \
  K30, K31,   K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D,           \
  K40, K41,   K42, K43, K44,                K48,                K4C, K4D, K4E, K4F  \
) \
{ \
  { K00, K01,   K02, K03, K04, K05,   K06,   K07,   K08, K09,   K0A,   K0B,   K0C, K0D, K0E,   K0F  },  \
  { K10, K11,   K12, K13, K14, K15,   K16,   K17,   K18, K19,   K1A,   K1B,   K1C, K1D, K1E,   K1F  },  \
  { K20, K21,   K22, K23, K24, K25,   K26,   K27,   K28, K29,   K2A,   K2B,   K2C, K2D, K2E,   KC_NO }, \
  { K30, K31,   K32, K33, K34, K35,   K36,   K37,   K38, K39,   K3A,   K3B,   K3C, K3D, KC_NO, KC_NO }, \
  { K40, K41,   K42, K43, K44, KC_NO, KC_NO, KC_NO, K48, KC_NO, KC_NO, KC_NO, K4C, K4D, K4E,   K4F }    \
}

M lib/python/qmk/info.py => lib/python/qmk/info.py +1 -1
@@ 74,7 74,7 @@ def info_json(keyboard):
    except jsonschema.ValidationError as e:
        json_path = '.'.join([str(p) for p in e.absolute_path])
        cli.log.error('Invalid API data: %s: %s: %s', keyboard, json_path, e.message)
        exit()
        exit(1)

    # Make sure we have at least one layout
    if not info_data.get('layouts'):

M lib/python/qmk/json_schema.py => lib/python/qmk/json_schema.py +4 -1
@@ 17,9 17,12 @@ def json_load(json_file):
    try:
        return hjson.load(json_file.open(encoding='utf-8'))

    except json.decoder.JSONDecodeError as e:
    except (json.decoder.JSONDecodeError, hjson.HjsonDecodeError) as e:
        cli.log.error('Invalid JSON encountered attempting to load {fg_cyan}%s{fg_reset}:\n\t{fg_red}%s', json_file, e)
        exit(1)
    except Exception as e:
        cli.log.error('Unknown error attempting to load {fg_cyan}%s{fg_reset}:\n\t{fg_red}%s', json_file, e)
        exit(1)


def load_jsonschema(schema_name):