~ruther/qmk_firmware

03ea478f205e37419032c15c16143c17a5d2b5ae — Josh Johnson 4 years ago e4d3ff2
Hub16 QMK configurator support + various bugfixes (#11496)

* qmk configurator support + various bugfixes

* Update keyboards/hub16/rules.mk

Co-authored-by: Drashna Jaelre <drashna@live.com>

Co-authored-by: Drashna Jaelre <drashna@live.com>
Co-authored-by: Nick Brassel <nick@tzarc.org>
M keyboards/hub16/config.h => keyboards/hub16/config.h +12 -30
@@ 30,16 30,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
#define MATRIX_ROWS 5
#define MATRIX_COLS 4

/*
 * 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 \
    { F0, C7, C6, B6, E6}
#define MATRIX_COL_PINS \


@@ 49,7 39,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
#define DIODE_DIRECTION COL2ROW

#define RGB_DI_PIN D1
// #ifdef RGB_DI_PIN
#define RGBLED_NUM 11
#define RGBLIGHT_HUE_STEP 8
#define RGBLIGHT_SAT_STEP 8


@@ 57,24 46,17 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
#define RGBLIGHT_LIMIT_VAL 255 /* The maximum brightness level */
#define RGBLIGHT_SLEEP         /* If defined, the RGB lighting will be switched off when the host goes to sleep */
// /*== all animations enable ==*/
// #define RGBLIGHT_ANIMATIONS
#define RGBLIGHT_ANIMATIONS
// /*== or choose animations ==*/
#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
// /*== customize breathing effect ==*/
//   /*==== (DEFAULT) use fixed table instead of exp() and sin() ====*/
//   #define RGBLIGHT_BREATHE_TABLE_SIZE 256      // 256(default) or 128 or 64
//   /*==== use exp() and sin() ====*/
//   #define RGBLIGHT_EFFECT_BREATHE_CENTER 1.85  // 1 to 2.7
//   #define RGBLIGHT_EFFECT_BREATHE_MAX    255   // 0 to 255
// #endif
// #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

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


@@ 82,9 64,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
/* ENCODER THINGS */
// #define ENCODER_DIRECTION_FLIP
#define ENCODERS_PAD_A \
    { F6, B4 }
#define ENCODERS_PAD_B \
    { F5, B5 }
#define ENCODERS_PAD_B \
    { F6, B4 }

/* Tap Dance timing */
#define TAPPING_TERM 200

A keyboards/hub16/info.json => keyboards/hub16/info.json +31 -0
@@ 0,0 1,31 @@
{
    "keyboard_name": "Hub16",
    "url": "https://joshajohnson.com/hub16-keyboard/",
    "maintainer": "Josh Johnson",
    "width": 4,
    "height": 5,
    "layouts": {
        "LAYOUT": {
            "layout": [
                {"label":"Mute", "x":0.5, "y":0},
                {"label":"Play / Pause", "x":2.5, "y":0},
                {"label":"7", "x":0, "y":1},
                {"label":"8", "x":1, "y":1},
                {"label":"9", "x":2, "y":1},
                {"label":"*", "x":3, "y":1},
                {"label":"4", "x":0, "y":2},
                {"label":"5", "x":1, "y":2},
                {"label":"6", "x":2, "y":2},
                {"label":"-", "x":3, "y":2},
                {"label":"1", "x":0, "y":3},
                {"label":"2", "x":1, "y":3},
                {"label":"3", "x":2, "y":3},
                {"label":"+", "x":3, "y":3},
                {"label":"MO(1)", "x":0, "y":4},
                {"label":"0", "x":1, "y":4},
                {"label":".", "x":2, "y":4},
                {"label":"N.ENT", "x":3, "y":4}
            ]
        }
    }
}

M keyboards/hub16/keymaps/ahk_companion/readme.md => keyboards/hub16/keymaps/ahk_companion/readme.md +2 -2
@@ 1,7 1,7 @@
# AutoHotKey Companion

## Overview
AutoHotKey Companion Keymap for <a href="https://www.tindie.com/products/joshajohnson/hub16-programmable-macro-keyboard/">Hub16 macropad</a> is designed be a quick and easy way to get started with AutoHotKey and to provide a foundation for customizing your own macropad. I upgraded to the Super16 from a Super16 because it kept the RGB underglow lights for an easy way (RGB) to identify what layer I was on with a quick glance or peripheral vision and added 2 rotary encoders and a USB 2.0 hub with USB-C ports. The F13 to F24 keys were selected as they are rarely used so you won't run into conflicts with existing application shortcuts and AutoHotKey recognizes them without any issues. *Note:* MacOS does not support/recognize F21 to F24 so these would need to be remapped for Mac users. 
AutoHotKey Companion Keymap for <a href="https://www.tindie.com/products/joshajohnson/hub16-programmable-macro-keyboard/">Hub16 macropad</a> is designed be a quick and easy way to get started with AutoHotKey and to provide a foundation for customizing your own macropad. I upgraded to the Hub16 from a Super16 because it kept the RGB underglow lights for an easy way (RGB) to identify what layer I was on with a quick glance or peripheral vision and added 2 rotary encoders and a USB 2.0 hub with USB-C ports. The F13 to F24 keys were selected as they are rarely used so you won't run into conflicts with existing application shortcuts and AutoHotKey recognizes them without any issues. *Note:* MacOS does not support/recognize F21 to F24 so these would need to be remapped for Mac users. 

Same functionality can be accomplished with other similar applications on the host system like Keyboard Maestro, AutoIt, etc. 



@@ 64,7 64,7 @@ While the first 5 layers are accessible with only 1 key press at most, the 5th (
    
## Host Configuration

Once the keymap has been flashed to the Super16, you can download the accompanying AutoHotKey file or create your own and have it start automatically either via a Windows Task or another way. Using AutoHotKey allows adjustment of functionality of the buttons without the need to change your map and reflash the macropad every time.
Once the keymap has been flashed to the Hub16, you can download the accompanying AutoHotKey file or create your own and have it start automatically either via a Windows Task or another way. Using AutoHotKey allows adjustment of functionality of the buttons without the need to change your map and reflash the macropad every time.
Starting the AHK file can be done either by:
* Creating a Windows Task 
* Adding the AHK to the startup folder

D keyboards/hub16/keymaps/ahk_companion/rules.mk => keyboards/hub16/keymaps/ahk_companion/rules.mk +0 -3
@@ 1,3 0,0 @@
TAP_DANCE_ENABLE = no      # Support for tap dancing



R keyboards/hub16/keymaps/no_mod/keymap.c => keyboards/hub16/keymaps/default/keymap.c +15 -43
@@ 15,64 15,36 @@
 */
#include QMK_KEYBOARD_H

// Keyboard Layers
enum keyboard_layers{
    _BASE = 0,
    _CONTROL
};

// Tap Dance Declarations
enum tap_dance { TD_TO_LED = 0, TD_TO_DEFAULT = 1 };

qk_tap_dance_action_t tap_dance_actions[] = {
    // Tap once for standard key, twice to toggle to control layer
    [TD_TO_LED]     = ACTION_TAP_DANCE_DUAL_ROLE(KC_P, _CONTROL),
    [TD_TO_DEFAULT] = ACTION_TAP_DANCE_DUAL_ROLE(KC_P, _BASE)};

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
  [_BASE] = LAYOUT( /* Base */
        KC_S,      KC_V,    
    KC_A, KC_B, KC_C, KC_D, 
    KC_E, KC_F, KC_G, KC_H, 
    KC_I, KC_J, KC_K, KC_L, 
    KC_M, KC_N, KC_O, TD(TD_TO_LED) 
  [0] = LAYOUT( /* Base */
       KC_MUTE,        KC_MPLY,
    KC_7,   KC_8,   KC_9,   KC_PAST,
    KC_4,   KC_5,   KC_6,   KC_PMNS,
    KC_1,   KC_2,   KC_3,   KC_PPLS,
    MO(1),  KC_0,   KC_PDOT,KC_PENT
  ),

  [_CONTROL] = LAYOUT( /* LED Control */
          KC_NO,            KC_NO,        
  [1] = LAYOUT( /* LED Control */
        _______,           _______,
    _______, RGB_MOD, RGB_RMOD, RGB_TOG,
    RGB_VAD, RGB_VAI, RGB_HUD,  RGB_HUI, 
    RGB_SAD, RGB_SAI, _______,  _______, 
    _______, _______, RESET,    TD(TD_TO_DEFAULT) 
    RGB_VAD, RGB_VAI, RGB_HUD,  RGB_HUI,
    RGB_SAD, RGB_SAI, _______,  _______,
    _______, _______, RESET,    _______
  ),
};

void encoder_update_user(uint8_t index, bool clockwise) {
    if (index == 0) { /* Left Encoder */
        if (clockwise) {
            tap_code(KC_R);
            tap_code(KC_VOLD);
        } else {
            tap_code(KC_Q);
            tap_code(KC_VOLU);
        }
    } else if (index == 1) { /* Right Encoder */
        if (clockwise) {
            tap_code(KC_U);
            tap_code(KC_MPRV);
        } else {
            tap_code(KC_T);
            tap_code(KC_MNXT);
        }
    }
}

bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  switch (keycode) {
    // Example of "pressing" CONTROL+SHIFT+V instead of "A" on keyboard
    // More info: https://docs.qmk.fm/#/feature_macros
    // case KC_A:
    //   if (record->event.pressed) {
    //     SEND_STRING(SS_LCTL(SS_LSFT("v")));
    //   } else {
    //   }
    //   break; 
  }
  return true;
};

D keyboards/hub16/keymaps/default/keymap.json => keyboards/hub16/keymaps/default/keymap.json +0 -1
@@ 1,1 0,0 @@
{"version":1,"notes":"","documentation":"\"This file is a QMK Configurator export. You can import this at <https://config.qmk.fm>. It can also be used directly with QMK's source code.\n\nTo setup your QMK environment check out the tutorial: <https://docs.qmk.fm/#/newbs>\n\nYou can convert this file to a keymap.c using this command: `qmk json2c {keymap}`\n\nYou can compile this keymap using this command: `qmk compile {keymap}`\"\n","keyboard":"hub16","keymap":"default","layout":"LAYOUT","layers":[["KC_NLCK","KC_PSLS","KC_P7","KC_P8","KC_P9","KC_PPLS","KC_P4","KC_P5","KC_P6","KC_PCMM","KC_P1","KC_P2","KC_P3","KC_PEQL","KC_P0","KC_P0","KC_PDOT","KC_PENT"]],"author":""}

D keyboards/hub16/keymaps/default_tap_dance/rules.mk => keyboards/hub16/keymaps/default_tap_dance/rules.mk +0 -1
@@ 1,1 0,0 @@
TAP_DANCE_ENABLE = yes      # Support for tap dancing

R keyboards/hub16/keymaps/default_tap_dance/keymap.c => keyboards/hub16/keymaps/macro/keymap.c +8 -8
@@ 36,18 36,18 @@ qk_tap_dance_action_t tap_dance_actions[] = {

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
  [_BASE] = LAYOUT( /* Base */
        KC_S,      KC_V,    
    KC_A, KC_B, KC_C, KC_D, 
    KC_E, KC_F, KC_G, KC_H, 
    KC_I, KC_J, KC_K, KC_L, 
        KC_S,      KC_V,
    KC_A, KC_B, KC_C, KC_D,
    KC_E, KC_F, KC_G, KC_H,
    KC_I, KC_J, KC_K, KC_L,
    KC_M, KC_N, KC_O, TD(CTRL)
  ),

  [_CTRL] = LAYOUT( /* Control */
          KC_NO,            KC_NO,        
          KC_NO,            KC_NO,
    _______, RGB_MOD, RGB_RMOD, RGB_TOG,
    RGB_VAD, RGB_VAI, RGB_HUD,  RGB_HUI, 
    RGB_SAD, RGB_SAI, _______,  _______, 
    RGB_VAD, RGB_VAI, RGB_HUD,  RGB_HUI,
    RGB_SAD, RGB_SAI, _______,  _______,
    _______, _______, RESET,    TD(BASE)
  ),
};


@@ 112,4 112,4 @@ void td_ctrl (qk_tap_dance_state_t *state, void *user_data) {
  } else if (state->count == 2) {
    layer_move(_CTRL);
  }
}
\ No newline at end of file
}

A keyboards/hub16/keymaps/macro/rules.mk => keyboards/hub16/keymaps/macro/rules.mk +1 -0
@@ 0,0 1,1 @@
TAP_DANCE_ENABLE = yes

M keyboards/hub16/keymaps/via/rules.mk => keyboards/hub16/keymaps/via/rules.mk +0 -3
@@ 1,4 1,1 @@
VIA_ENABLE = yes
CONSOLE_ENABLE = no
COMMAND_ENABLE = no
TAP_DANCE_ENABLE = no

M keyboards/hub16/matrix.c => keyboards/hub16/matrix.c +14 -152
@@ 19,7 19,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
#include "wait.h"
#include "util.h"
#include "matrix.h"
#include "debounce.h"
#include "quantum.h"

// Encoder things


@@ 27,65 26,12 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
#define SWITCH_2 D7
static bool read_encoder_switches(matrix_row_t current_matrix[], uint8_t current_row);

#ifdef MATRIX_MASKED
extern const matrix_row_t matrix_mask[];
#endif

#ifdef DIRECT_PINS
static pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;
#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
#endif

/* matrix state(1:on, 0:off) */
static matrix_row_t raw_matrix[MATRIX_ROWS];  // raw values
static matrix_row_t matrix[MATRIX_ROWS];      // debounced values

// helper functions

inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); }

inline matrix_row_t matrix_get_row(uint8_t row) {
    // Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
    // switch blocker installed and the switch is always pressed.
#ifdef MATRIX_MASKED
    return matrix[row] & matrix_mask[row];
#else
    return matrix[row];
#endif
}

// matrix code

#ifdef DIRECT_PINS

static void init_pins(void) {
    for (int row = 0; row < MATRIX_ROWS; row++) {
        for (int col = 0; col < MATRIX_COLS; col++) {
            pin_t pin = direct_pins[row][col];
            if (pin != NO_PIN) {
                setPinInputHigh(pin);
            }
        }
    }
}

static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) {
    matrix_row_t last_row_value = current_matrix[current_row];
    current_matrix[current_row] = 0;

    for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
        pin_t pin = direct_pins[current_row][col_index];
        if (pin != NO_PIN) {
            current_matrix[current_row] |= readPin(pin) ? 0 : (MATRIX_ROW_SHIFTER << col_index);
        }
    }

    return (last_row_value != current_matrix[current_row]);
}

#elif (DIODE_DIRECTION == COL2ROW)
extern matrix_row_t raw_matrix[MATRIX_ROWS];  // raw values
extern matrix_row_t matrix[MATRIX_ROWS];      // debounced values

static void select_row(uint8_t row) {
    setPinOutput(row_pins[row]);


@@ 133,112 79,28 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
    return (last_row_value != current_matrix[current_row]);
}

#elif (DIODE_DIRECTION == ROW2COL)

static void select_col(uint8_t col) {
    setPinOutput(col_pins[col]);
    writePinLow(col_pins[col]);
}

static void unselect_col(uint8_t col) { setPinInputHigh(col_pins[col]); }

static void unselect_cols(void) {
    for (uint8_t x = 0; x < MATRIX_COLS; x++) {
        setPinInputHigh(col_pins[x]);
    }
}

static void init_pins(void) {
    unselect_cols();
    for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
        setPinInputHigh(row_pins[x]);
    }
}

static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) {
    bool matrix_changed = false;

    // Select col and wait for col selecton to stabilize
    select_col(current_col);
    wait_us(30);

    // For each row...
    for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) {
        // Store last value of row prior to reading
        matrix_row_t last_row_value = current_matrix[row_index];

        // Check row pin state
        if (readPin(row_pins[row_index]) == 0) {
            // Pin LO, set col bit
            current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col);
        } else {
            // Pin HI, clear col bit
            current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col);
        }

        // Determine if the matrix changed state
        if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) {
            matrix_changed = true;
        }
    }

    // Unselect col
    unselect_col(current_col);

    return matrix_changed;
}

#endif

void matrix_init(void) {
void matrix_init_custom(void) {
    // initialize key pins
    setPinInput(SWITCH_1);
    setPinInput(SWITCH_2);
    init_pins();

    // initialize matrix state: all keys off
    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
        raw_matrix[i] = 0;
        matrix[i]     = 0;
    }

    debounce_init(MATRIX_ROWS);

    matrix_init_quantum();
}

uint8_t matrix_scan(void) {
bool matrix_scan_custom(void) {
    bool changed = false;

#if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW)
    // Set row, read cols
    for (uint8_t current_row = 0; current_row < MATRIX_ROWS; current_row++) {
        changed |= read_cols_on_row(raw_matrix, current_row);
    }
#elif (DIODE_DIRECTION == ROW2COL)
    // Set col, read rows
    for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) {
        changed |= read_rows_on_col(raw_matrix, current_col);
    }
#endif

    debounce(raw_matrix, matrix, MATRIX_ROWS, changed);

    // Read encoder switches, already debounced
    changed |= read_encoder_switches(matrix, 4);

    matrix_scan_quantum();
    return (uint8_t)changed;
    return changed;
}

// Customisations for the encoders
void matrix_init_kb(void) {
    setPinInput(SWITCH_1);
    setPinInput(SWITCH_2);
}

void matrix_scan_kb(void) {}

void matrix_print(void) {}

static bool read_encoder_switches(matrix_row_t current_matrix[], uint8_t current_row) {
    // Store last value of row prior to reading
    matrix_row_t last_row_value = current_matrix[current_row];


@@ 249,18 111,18 @@ static bool read_encoder_switches(matrix_row_t current_matrix[], uint8_t current
    // Debounce the encoder buttons using a shift register
    static uint8_t btn_1_array;
    static uint8_t btn_2_array;
    bool           btn_1_pressed = 0;
    bool           btn_2_pressed = 0;
    bool           btn_1_rise = 0;
    bool           btn_2_rise = 0;
    btn_1_array <<= 1;
    btn_2_array <<= 1;
    btn_1_array |= readPin(SWITCH_1);
    btn_2_array |= readPin(SWITCH_2);
    (btn_1_array == 0b11111111) ? (btn_1_pressed = 1) : (btn_1_pressed = 0);
    (btn_2_array == 0b11111111) ? (btn_2_pressed = 1) : (btn_2_pressed = 0);
    (btn_1_array == 0b01111111) ? (btn_1_rise = 1) : (btn_1_rise = 0);
    (btn_2_array == 0b01111111) ? (btn_2_rise = 1) : (btn_2_rise = 0);

    // Populate the matrix row with the state of the encoder
    current_matrix[current_row] |= btn_1_pressed ? (1 << 0) : 0;
    current_matrix[current_row] |= btn_2_pressed ? (1 << 1) : 0;
    current_matrix[current_row] |= btn_1_rise ? (1 << 0) : 0;
    current_matrix[current_row] |= btn_2_rise ? (1 << 1) : 0;

    return (last_row_value != current_matrix[current_row]);
}
\ No newline at end of file
}

M keyboards/hub16/readme.md => keyboards/hub16/readme.md +2 -2
@@ 1,6 1,6 @@
# Hub16

Hub16 is a 16 Key Macro Pad with an inbuilt USB 2.0 hub and dual rotary encoders. 
Hub16 is a 16 Key Macro Pad with an inbuilt USB 2.0 hub and dual rotary encoders.

For more information regarding the keyboard, please visit the [Hub16 Website](https://www.joshajohnson.com/hub16-keyboard/) or [GitHub Repo](https://github.com/joshajohnson/Hub16).



@@ 10,6 10,6 @@ For more information regarding the keyboard, please visit the [Hub16 Website](ht

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

    make hub16:default
    make hub16: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).

M keyboards/hub16/rules.mk => keyboards/hub16/rules.mk +6 -18
@@ 1,35 1,23 @@
# MCU name
MCU = atmega32u4

# Bootloader selection
#   Teensy       halfkay
#   Pro Micro    caterina
#   Atmel DFU    atmel-dfu
#   LUFA DFU     lufa-dfu
#   QMK DFU      qmk-dfu
#   ATmega32A    bootloadHID
#   ATmega328P   USBasp
BOOTLOADER = caterina

# Build Options
#   change yes to no to disable
#
CUSTOM_MATRIX = yes			# Custom scanning of matrix
CUSTOM_MATRIX = lite		# Custom scanning of matrix
BOOTMAGIC_ENABLE = no       # Virtual DIP switch configuration
MOUSEKEY_ENABLE = no        # Mouse keys
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
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
MIDI_ENABLE = no            # MIDI support
UNICODE_ENABLE = no         # Unicode
BLUETOOTH_ENABLE = no       # Enable Bluetooth with the Adafruit EZ-Key HID
AUDIO_ENABLE = no           # Audio output on port C6
BLUETOOTH_ENABLE = no       # Enable Bluetooth
AUDIO_ENABLE = no           # Audio output
ENCODER_ENABLE = yes        # Rotary Encoder support

SRC = matrix.c