feat: Add keymap

This commit is contained in:
Maël Villerbu 2024-03-26 22:19:22 +01:00
parent 67fac7803e
commit 44aa1f799a
9 changed files with 1303 additions and 1 deletions

View file

@ -0,0 +1,100 @@
/* Copyright 2022 Thomas Baart <thomas@splitkb.com>
*
* 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 SPLIT_WPM_ENABLE
#define SPLIT_ACTIVITY_ENABLE
#define TAPPING_TERM 180
#define QUICK_TAP_TERM 0
#define PERMISSIVE_HOLD
#define TAPPING_TERM_PER_KEY
#define SPLIT_TRANSACTION_IDS_USER USER_SYNC_LUNA
#define SPLIT_LED_STATE_ENABLE
// Space optimizations
#define LAYER_STATE_8BIT
#define NO_ACTION_MACRO
#define NO_ACTION_FUNCTION
#define DISABLE_LEADER
#define NO_ACTION_ONESHOT
#define NO_MUSIC_MODE
#undef LOCKING_SUPPORT_ENABLE
#undef LOCKING_RESYNC_ENABLE
#undef RGBLIGHT_ANIMATIONS
#undef RGBLIGHT_EFFECT_BREATHING
#undef RGBLIGHT_EFFECT_RAINBOW_MOOD
#undef RGBLIGHT_EFFECT_RAINBOW_SWIRL
#undef RGBLIGHT_EFFECT_SNAKE
#undef RGBLIGHT_EFFECT_KNIGHT
#undef RGBLIGHT_EFFECT_CHRISTMAS
#undef RGBLIGHT_EFFECT_STATIC_GRADIENT
#undef RGBLIGHT_EFFECT_RGB_TEST
#undef RGBLIGHT_EFFECT_ALTERNATING
#undef RGBLIGHT_EFFECT_TWINKLE
#undef ENABLE_RGB_MATRIX_ALPHAS_MODS
#undef ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN
#undef ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
#undef ENABLE_RGB_MATRIX_BREATHING
#undef ENABLE_RGB_MATRIX_BAND_SAT
#undef ENABLE_RGB_MATRIX_BAND_VAL
#undef ENABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
#undef ENABLE_RGB_MATRIX_BAND_PINWHEEL_VAL
#undef ENABLE_RGB_MATRIX_BAND_SPIRAL_SAT
#undef ENABLE_RGB_MATRIX_BAND_SPIRAL_VAL
#undef ENABLE_RGB_MATRIX_CYCLE_ALL
#undef ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
#undef ENABLE_RGB_MATRIX_CYCLE_UP_DOWN
#undef ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
#undef ENABLE_RGB_MATRIX_CYCLE_OUT_IN
#undef ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
#undef ENABLE_RGB_MATRIX_CYCLE_PINWHEEL
#undef ENABLE_RGB_MATRIX_CYCLE_SPIRAL
#undef ENABLE_RGB_MATRIX_DUAL_BEACON
#undef ENABLE_RGB_MATRIX_RAINBOW_BEACON
#undef ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS
#undef ENABLE_RGB_MATRIX_FLOWER_BLOOMING
#undef ENABLE_RGB_MATRIX_RAINDROPS
#undef ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
#undef ENABLE_RGB_MATRIX_HUE_BREATHING
#undef ENABLE_RGB_MATRIX_HUE_PENDULUM
#undef ENABLE_RGB_MATRIX_HUE_WAVE
#undef ENABLE_RGB_MATRIX_PIXEL_FRACTAL
#undef ENABLE_RGB_MATRIX_PIXEL_FLOW
#undef ENABLE_RGB_MATRIX_PIXEL_RAIN
#undef ENABLE_RGB_MATRIX_TYPING_HEATMAP
#undef ENABLE_RGB_MATRIX_DIGITAL_RAIN
#undef ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
#undef ENABLE_RGB_MATRIX_SOLID_REACTIVE
#undef ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
#undef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
#undef ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
#undef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
#undef ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
#undef ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
#undef ENABLE_RGB_MATRIX_SPLASH
#undef ENABLE_RGB_MATRIX_MULTISPLASH
#undef ENABLE_RGB_MATRIX_SOLID_SPLASH
#undef ENABLE_RGB_MATRIX_SOLID_MULTISPLASH

View file

@ -0,0 +1,668 @@
#include QMK_KEYBOARD_H
#include "transactions.h"
enum layers {
_COLEMAK_DH = 0,
_NAV,
_SYM,
_FUN,
_MEDIA,
_MOUSE,
_NUM
};
enum custom_keycodes {
QC_EGRV = SAFE_RANGE, // è
QC_EAIG, // é
QC_AGRV, // à
QC_CCED, // ç
QC_UGRV, // ù
QC_ICRC, // î
QC_OCRC, // ù
KC_LEFT_ENC_MODE, // left encoder mode
KC_RIGHT_ENC_MODE, // right encoder mode
ALT_TAB, // alt-tab
QC_QUOT // non-dead quotes
};
enum left_encoder_mode {
LENC_VOL, // volume control
LENC_WORD, // scroll horizontally by word
LENC_NOOP
};
enum right_encoder_mode {
RENC_TAB, // alt tabbing
RENC_SCROLL, // mouse scroll
RENC_PAGE, // scroll half pages
RENC_NOOP
};
typedef struct _master_to_slave_t {
bool is_sneaking;
bool is_barking;
} master_to_slave_t;
enum left_encoder_mode left_encoder = LENC_VOL;
enum right_encoder_mode right_encoder = RENC_TAB;
// Alt tab on steroids
bool is_alt_tab_active = false;
uint16_t alt_tab_timer = 0;
// Luna behaviour
bool is_barking = false;
bool is_sneaking = false;
bool is_jumping = false;
bool showed_jump = true;
#define CTL_ESC MT(MOD_LCTL, KC_ESC)
#define LALT_ENT MT(MOD_LALT, KC_ENT)
#define RALT_ENT MT(MOD_RALT, KC_ENT)
#define KC_LENC LT(0, KC_LEFT_ENC_MODE)
#define KC_RENC KC_RIGHT_ENC_MODE
#define SPC_SYM LT(_SYM, KC_SPC)
#define CUS_MEH MEH_T(MEH(KC_SPC))
// Custom actions
#define KC_COPY LCTL(KC_C)
#define KC_PAST LCTL(KC_V)
#define KC_CUT LCTL(KC_X)
#define KC_REDO LCTL(KC_Y)
#define KC_UNDO LCTL(KC_Z)
// Home row mods
#define HR_GA LGUI_T(KC_A)
#define HR_AR LALT_T(KC_R)
#define HR_CS LCTL_T(KC_S)
#define HR_ST LSFT_T(KC_T)
#define HR_SN LSFT_T(KC_N)
#define HR_CE LCTL_T(KC_E)
#define HR_AI LALT_T(KC_I)
#define HR_GO LGUI_T(KC_O)
// Thumb tap/hold
#define MEH_GUI MEH_T(KC_LGUI)
#define MED_ESC LT(_MEDIA, KC_ESC)
#define NAV_SPC LT(_NAV, KC_SPC)
#define MOU_TAB LT(_MOUSE, KC_TAB)
#define SYM_ENT LT(_SYM, KC_ENT)
#define NUM_BSP LT(_NUM, KC_BSPC)
#define FUN_DEL LT(_FUN, KC_DEL)
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/*
* Base Layer: Colemak DH
*
* ,-------------------------------------------. ,-------------------------------------------.
* | | Q | W | F | P | B | | J | L | U | Y | ; : | |
* |--------+------+------+------+------+------| |------+------+------+------+------+--------|
* | - / _ |GUI/A |R/ALT |S/CTRL|T/SHFT| G | | M |N/SHFT|E/CTRL|I/ALT |O/GUI | ' / " |
* |--------+------+------+------+------+------+-------------. ,-------------+------+------+------+------+------+--------|
* | Lalt / | Z | X | C | D | V | [ { | LENC | | RENC | ] } | K | H | , < | . > | / ? | |
* | Enter | | | | | | | | | | | | | | | | |
* `----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
* | | LGui | Esc | Space| Tab | | Enter| Bspc |Delete| | |
* | | MEH | Media| Nav | Mouse| | Sym | Num | Func | | |
* `----------------------------------' `----------------------------------'
*/
[_COLEMAK_DH] = LAYOUT(
XXXXXXX, KC_Q, KC_W, KC_F, KC_P, KC_B, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, _______,
KC_MINS, HR_GA, HR_AR, HR_CS, HR_ST, KC_G, KC_M, HR_SN, HR_CE, HR_AI, HR_GO, QC_QUOT,
XXXXXXX, KC_Z, KC_X, KC_C, KC_D, KC_V, KC_LBRC, KC_LENC, KC_RENC, KC_RBRC, KC_K, KC_H, KC_COMM, KC_DOT, KC_SLSH, _______,
XXXXXXX, KC_LGUI, MED_ESC, NAV_SPC, MOU_TAB, SYM_ENT, NUM_BSP, FUN_DEL, CUS_MEH, XXXXXXX
),
/*
* Nav Layer: Navigation, editing
*
* ,-------------------------------------------. ,-------------------------------------------.
* | | | | | | | | Redo | Paste| Copy | Cut | Undo | |
* |--------+------+------+------+------+------| |------+------+------+------+------+--------|
* | | LGui | Alt | Ctrl | Shift| | |CapsLk| | | | | |
* |--------+------+------+------+------+------+-------------. ,-------------+------+------+------+------+------+--------|
* | | | | | | | | | | | |Insert| Home |PageUp|PageDn| End | |
* `----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
* | | LGui | Esc | Space| Tab | | Enter| Bspc |Delete| | |
* `----------------------------------' `----------------------------------'
*/
[_NAV] = LAYOUT(
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_REDO, KC_PAST, KC_COPY, KC_CUT, KC_UNDO, XXXXXXX,
XXXXXXX, KC_LGUI, KC_LALT, KC_LCTL, KC_LSFT, XXXXXXX, KC_CAPS, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, XXXXXXX,
XXXXXXX, XXXXXXX, XXXXXXX, KC_COPY, XXXXXXX, KC_PAST, XXXXXXX, _______, _______, XXXXXXX, KC_INS, KC_HOME, KC_PGDN, KC_PGUP, KC_END, XXXXXXX,
_______, _______, KC_ESC, KC_SPC, KC_TAB, KC_ENT, KC_BSPC, KC_DEL, _______, _______
),
/*
* Mouse Layer: Media, navigation
*
* ,-------------------------------------------. ,-------------------------------------------.
* | | | | | | | | Redo | Paste| Copy | Cut | Undo | |
* |--------+------+------+------+------+------| |------+------+------+------+------+--------|
* | | LGui | Alt | Ctrl | Shift| | | Prev |Mouse|Mouse|Mouse|Mouse| |
* |--------+------+------+------+------+------+-------------. ,-------------+------+------+------+------+------+--------|
* | | | | | | | | | | | | Next | Scrl| Scrl| Scrl| Scrl| |
* `----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
* | | | Esc | Space| Tab | | Right| Left |Middle| | |
* `----------------------------------' `----------------------------------'
*/
[_MOUSE] = LAYOUT(
XXXXXXX, _______, _______, _______, _______, _______, KC_REDO, KC_PAST, KC_COPY, KC_CUT, KC_UNDO, XXXXXXX,
XXXXXXX, KC_LGUI, KC_LALT, KC_LCTL, KC_LSFT, _______, KC_BTN4, KC_MS_L, KC_MS_D, KC_MS_U, KC_MS_R, XXXXXXX,
XXXXXXX, _______, _______, _______, _______, _______, _______, _______, _______, XXXXXXX, KC_BTN5, KC_WH_L, KC_WH_D, KC_WH_U, KC_WH_R, XXXXXXX,
_______, _______, _______, _______, _______, KC_BTN2, KC_BTN1, KC_BTN3, _______, _______
),
/*
* Num layer : Numerals and symbols
*
* ,-------------------------------------------. ,-------------------------------------------.
* | | [ / {| 7 / &| 8 / *| 9 / (| ] / }| | | | | | | |
* |--------+------+------+------+------+------| |------+------+------+------+------+--------|
* | | ; / :| 4 / $| 5 / %| 6 / ^| + / =| | | Shift| Ctrl | Alt | LGui | |
* |--------+------+------+------+------+------+-------------. ,-------------+------+------+------+------+------+--------|
* | | ~ / `| 1 / !| 2 / @| 3 / #| \ / || | | | | | | | | | | |
* `----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
* | | | . / >| 0 / )| - / _| | | | | | |
* `----------------------------------' `----------------------------------'
*/
[_NUM ] = LAYOUT(
XXXXXXX, KC_LBRC, KC_7, KC_8, KC_9, KC_RBRC, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
XXXXXXX, KC_SCLN, KC_4, KC_5, KC_6, KC_EQL, XXXXXXX, KC_LSFT, KC_LCTL, KC_LALT, KC_LGUI, XXXXXXX,
XXXXXXX, KC_GRV, KC_1, KC_2, KC_3, KC_BSLS, _______, _______, _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
_______, _______, KC_DOT, KC_0, KC_MINS, _______, _______, _______, _______, _______
),
/*
* Sym Layer: Numbers and symbols
*
* ,-------------------------------------------. ,-------------------------------------------.
* | | | | | | | | | | ù | | | |
* |--------+------+------+------+------+------| |------+------+------+------+------+--------|
* | | à | | | Shift| | | | é | è | î | ô |'/" grv |
* |--------+------+------+------+------+------+-------------. ,-------------+------+------+------+------+------+--------|
* | | | | ç | | | | | | | | | | ^ | | | |
* `----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
* | | | Esc | Space| Tab | | Enter| Bspc | Del | | |
* | | | | | | | | | | | |
* `----------------------------------' `----------------------------------'
*/
[_SYM] = LAYOUT(
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, QC_UGRV, XXXXXXX, XXXXXXX, XXXXXXX,
XXXXXXX, QC_AGRV, XXXXXXX, XXXXXXX, KC_LSFT, XXXXXXX, XXXXXXX, QC_EAIG, QC_EGRV, QC_ICRC, QC_OCRC, KC_QUOT,
XXXXXXX, XXXXXXX, XXXXXXX, QC_CCED, XXXXXXX, XXXXXXX, XXXXXXX, _______, _______, XXXXXXX, XXXXXXX, XXXXXXX, KC_CIRC, XXXXXXX, XXXXXXX, XXXXXXX,
_______, _______, KC_ESC, KC_SPC, KC_TAB, KC_ENT, KC_BSPC, KC_DEL, _______, _______
),
[_FUN] = LAYOUT(
_______, KC_F9 , KC_F10, KC_F11, KC_F12, _______, _______, _______, _______, _______, _______, _______,
_______, KC_F5 , KC_F6 , KC_F7 , KC_F8 , _______, _______, KC_LSFT, KC_LCTL, KC_LALT, KC_RGUI, _______,
_______, KC_F1 , KC_F2 , KC_F3 , KC_F4 , _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______
),
};
// Initialize variable holding the binary
// representation of active modifiers.
uint8_t mod_state;
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
// Store the current modifier state in the variable for later reference
mod_state = get_mods();
switch (keycode) {
case QC_EAIG:
if (record->event.pressed) {
// First temporarily canceling both shifts so that
// shift isn't applied to the X_QUOTE keycode
del_mods(MOD_MASK_SHIFT);
SEND_STRING(SS_TAP(X_QUOTE));
// Reapplying modifier state so that the held shift key(s)
// still work
set_mods(mod_state);
SEND_STRING("e");
}
return true;
case QC_EGRV:
if (record->event.pressed) {
// First temporarily canceling both shifts so that
// shift isn't applied to the X_QUOTE keycode
del_mods(MOD_MASK_SHIFT);
SEND_STRING(SS_TAP(X_GRV));
// Reapplying modifier state so that the held shift key(s)
// still work
set_mods(mod_state);
SEND_STRING("e");
}
return true;
case QC_AGRV:
if (record->event.pressed) {
// First temporarily canceling both shifts so that
// shift isn't applied to the X_QUOTE keycode
del_mods(MOD_MASK_SHIFT);
SEND_STRING(SS_TAP(X_GRV));
// Reapplying modifier state so that the held shift key(s)
// still work
set_mods(mod_state);
SEND_STRING("a");
}
return true;
case QC_ICRC:
if (record->event.pressed) {
// First temporarily canceling both shifts so that
// shift isn't applied to the X_QUOTE keycode
add_mods(MOD_MASK_SHIFT);
SEND_STRING(SS_TAP(X_6));
del_mods(MOD_MASK_SHIFT);
// Reapplying modifier state so that the held shift key(s)
// still work
set_mods(mod_state);
SEND_STRING("i");
}
return true;
case QC_OCRC:
if (record->event.pressed) {
// First temporarily canceling both shifts so that
// shift isn't applied to the X_QUOTE keycode
add_mods(MOD_MASK_SHIFT);
SEND_STRING(SS_TAP(X_6));
del_mods(MOD_MASK_SHIFT);
// Reapplying modifier state so that the held shift key(s)
// still work
set_mods(mod_state);
SEND_STRING("o");
}
return true;
case QC_UGRV:
if (record->event.pressed) {
// First temporarily canceling both shifts so that
// shift isn't applied to the X_QUOTE keycode
del_mods(MOD_MASK_SHIFT);
SEND_STRING(SS_TAP(X_GRV));
// Reapplying modifier state so that the held shift key(s)
// still work
set_mods(mod_state);
SEND_STRING("u");
}
return true;
case QC_CCED:
if (record->event.pressed) {
register_code(KC_RALT);
SEND_STRING(",");
unregister_code(KC_RALT);
}
return true;
case KC_LENC:
if (record->tap.count && record->event.pressed) {
left_encoder++;
if (left_encoder == LENC_NOOP) {
left_encoder = 0;
}
} else if (record->event.pressed) {
tap_code(KC_MUTE);
}
return false;
case KC_RENC:
if (record->event.pressed) {
right_encoder++;
if (right_encoder == RENC_NOOP) {
right_encoder = 0;
}
}
return false;
case CUS_MEH:
if (record->tap.count && record->event.pressed) {
register_code16(MEH(KC_SPC));
unregister_code16(MEH(KC_SPC));
break;
}
case 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);
} else {
unregister_code(KC_TAB);
}
break;
case QC_QUOT:
if (record -> event.pressed) {
SEND_STRING(SS_TAP(X_QUOTE));
SEND_STRING(SS_TAP(X_SPC));
}
return false;
}
return true;
};
uint16_t keycode_config(uint16_t keycode) {
return keycode;
}
uint8_t mod_config(uint8_t mod) {
return mod;
}
tap_dance_action_t tap_dance_actions[] = {};
void matrix_scan_user(void) {
if (is_alt_tab_active) {
if (timer_elapsed(alt_tab_timer) > 750) {
unregister_code(KC_LALT);
is_alt_tab_active = false;
}
}
}
/**************** Encoder *****************/
bool encoder_update_user(uint8_t index, bool clockwise) {
if (index == 0) { // left
switch (left_encoder) {
case LENC_VOL:
if (clockwise) {
tap_code(KC_VOLU);
} else {
tap_code(KC_VOLD);
}
return false;
case LENC_WORD:
if (clockwise) {
tap_code16(C(KC_RIGHT));
} else {
tap_code16(C(KC_LEFT));
}
return false;
default:
return false;
}
} else if (index == 1) { // right
switch (right_encoder) {
case RENC_PAGE:
if (clockwise) {
tap_code(KC_PGDN);
} else {
tap_code(KC_PGUP);
}
return false;
case RENC_TAB:
if (clockwise) {
if (!is_alt_tab_active) {
is_alt_tab_active = true;
register_code(KC_LALT);
}
alt_tab_timer = timer_read();
tap_code16(KC_TAB);
} else {
if (!is_alt_tab_active) {
is_alt_tab_active = true;
register_code(KC_LALT);
}
alt_tab_timer = timer_read();
tap_code16(S(KC_TAB));
}
return false;
case RENC_SCROLL:
if (clockwise) {
tap_code(KC_WH_D);
} else {
tap_code(KC_WH_U);
}
return false;
default:
return false;
}
}
return false;
}
/**************** Oled *****************/
#define MIN_WALK_SPEED 10
#define MIN_RUN_SPEED 40
#define ANIM_FRAME_DURATION 200
#define ANIM_SIZE 96
int current_wpm_luna = 0;
uint8_t current_frame = 0;
uint32_t anim_timer_luna = 0;
uint32_t anim_sleep = 0;
// Draw Luna on OLED
void render_luna(int LUNA_X, int LUNA_Y) {
// Sit
static const char PROGMEM sit[2][3][ANIM_SIZE/3] = {
// 'sit1', 32x22px
{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1c, 0x02, 0x05, 0x02, 0x24, 0x04, 0x04, 0x02, 0xa9, 0x1e, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0x08, 0x68, 0x10, 0x08, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x82, 0x7c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0c, 0x10, 0x10, 0x20, 0x20, 0x20, 0x28, 0x3e, 0x1c, 0x20, 0x20, 0x3e, 0x0f, 0x11, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
},
// 'sit2', 32x22px
{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1c, 0x02, 0x05, 0x02, 0x24, 0x04, 0x04, 0x02, 0xa9, 0x1e, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x90, 0x08, 0x18, 0x60, 0x10, 0x08, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0e, 0x82, 0x7c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0c, 0x10, 0x10, 0x20, 0x20, 0x20, 0x28, 0x3e, 0x1c, 0x20, 0x20, 0x3e, 0x0f, 0x11, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
}
};
// Walk
static const char PROGMEM walk[2][3][ANIM_SIZE/3] = {
// 'walk1', 32x22px
{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x90, 0x90, 0x90, 0xa0, 0xc0, 0x80, 0x80, 0x80, 0x70, 0x08, 0x14, 0x08, 0x90, 0x10, 0x10, 0x08, 0xa4, 0x78, 0x80, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x08, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x18, 0xea, 0x10, 0x0f, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1c, 0x20, 0x20, 0x3c, 0x0f, 0x11, 0x1f, 0x03, 0x06, 0x18, 0x20, 0x20, 0x3c, 0x0c, 0x12, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
},
// 'walk2', 32x22px
{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x20, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0x28, 0x10, 0x20, 0x20, 0x20, 0x10, 0x48, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x20, 0xf8, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x30, 0xd5, 0x20, 0x1f, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x20, 0x30, 0x0c, 0x02, 0x05, 0x09, 0x12, 0x1e, 0x02, 0x1c, 0x14, 0x08, 0x10, 0x20, 0x2c, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
}
};
// Run
static const char PROGMEM run[2][3][ANIM_SIZE/3] = {
// 'run1', 32x22px
{
{0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0x08, 0x08, 0xc8, 0xb0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40, 0x3c, 0x14, 0x04, 0x08, 0x90, 0x18, 0x04, 0x08, 0xb0, 0x40, 0x80, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0xc4, 0xa4, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc8, 0x58, 0x28, 0x2a, 0x10, 0x0f, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x09, 0x04, 0x04, 0x04, 0x04, 0x02, 0x03, 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x08, 0x10, 0x26, 0x2b, 0x32, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00}
},
// 'run2', 32x22px
{
{0x00, 0x00, 0x00, 0xe0, 0x10, 0x10, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x78, 0x28, 0x08, 0x10, 0x20, 0x30, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x03, 0x04, 0x08, 0x10, 0x11, 0xf9, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0xb0, 0x50, 0x55, 0x20, 0x1f, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0c, 0x10, 0x20, 0x28, 0x37, 0x02, 0x1e, 0x20, 0x20, 0x18, 0x0c, 0x14, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
}
};
// Bark
static const char PROGMEM bark[2][3][ANIM_SIZE/3] = {
// 'bark1', 32x22px
{
{0x00, 0xc0, 0x20, 0x10, 0xd0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x40, 0x3c, 0x14, 0x04, 0x08, 0x90, 0x18, 0x04, 0x08, 0xb0, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x03, 0x04, 0x08, 0x10, 0x11, 0xf9, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc8, 0x48, 0x28, 0x2a, 0x10, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0c, 0x10, 0x20, 0x28, 0x37, 0x02, 0x02, 0x04, 0x08, 0x10, 0x26, 0x2b, 0x32, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
},
// 'bark2', 32x22px
{
{0x00, 0xe0, 0x10, 0x10, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x40, 0x40, 0x2c, 0x14, 0x04, 0x08, 0x90, 0x18, 0x04, 0x08, 0xb0, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x03, 0x04, 0x08, 0x10, 0x11, 0xf9, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x48, 0x28, 0x2a, 0x10, 0x0f, 0x20, 0x4a, 0x09, 0x10},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x0c, 0x10, 0x20, 0x28, 0x37, 0x02, 0x02, 0x04, 0x08, 0x10, 0x26, 0x2b, 0x32, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
}
};
// Sneak
static const char PROGMEM sneak[2][3][ANIM_SIZE/3] = {
// 'sneak1', 32x22px
{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x40, 0x80, 0x00, 0x80, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x1e, 0x21, 0xf0, 0x04, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x04, 0x04, 0x04, 0x03, 0x01, 0x00, 0x00, 0x09, 0x01, 0x80, 0x80, 0xab, 0x04, 0xf8, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1c, 0x20, 0x20, 0x3c, 0x0f, 0x11, 0x1f, 0x02, 0x06, 0x18, 0x20, 0x20, 0x38, 0x08, 0x10, 0x18, 0x04, 0x04, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00}
},
// 'sneak2', 32x22px
{
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xa0, 0x20, 0x40, 0x80, 0xc0, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x3e, 0x41, 0xf0, 0x04, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x40, 0x40, 0x55, 0x82, 0x7c, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x20, 0x30, 0x0c, 0x02, 0x05, 0x09, 0x12, 0x1e, 0x04, 0x18, 0x10, 0x08, 0x10, 0x20, 0x28, 0x34, 0x06, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}
}
};
// Draw a frame - needed to draw on 3 different lines without having to store all blank spaces
void draw_frame(const char frame[3][ANIM_SIZE/3]) {
oled_write(" ", false);
oled_write_raw_P(frame[0], ANIM_SIZE/3);
oled_advance_page(false);
oled_write(" ", false);
oled_write_raw_P(frame[1], ANIM_SIZE/3);
oled_advance_page(false);
oled_write(" ", false);
oled_write_raw_P(frame[2], ANIM_SIZE/3);
}
// Handle animation
void animation_phase(void) {
// jump
if (is_jumping || !showed_jump) {
// clear
oled_set_cursor(LUNA_X, LUNA_Y + 2);
oled_write(" ", false);
oled_set_cursor(LUNA_X, LUNA_Y - 1);
showed_jump = true;
} else {
// clear
oled_set_cursor(LUNA_X, LUNA_Y - 1);
oled_write(" ", false);
oled_set_cursor(LUNA_X, LUNA_Y);
}
// switch frame
current_frame = (current_frame + 1) % 2;
// current status
if (is_barking) {
draw_frame(bark[abs(1 - current_frame)]);
} else if (is_sneaking) {
draw_frame(sneak[abs(1 - current_frame)]);
} else if (current_wpm_luna <= MIN_WALK_SPEED) {
draw_frame(sit[abs(1 - current_frame)]);
} else if (current_wpm_luna <= MIN_RUN_SPEED) {
draw_frame(walk[abs(1 - current_frame)]);
} else {
draw_frame(run[abs(1 - current_frame)]);
}
}
// animation timer
if (timer_elapsed32(anim_timer_luna) > ANIM_FRAME_DURATION) {
anim_timer_luna = timer_read32();
current_wpm_luna = get_current_wpm();
animation_phase();
}
// this fixes the screen on and off bug
if (current_wpm_luna > 0) {
oled_on();
anim_sleep = timer_read32();
} else if (timer_elapsed32(anim_sleep) > OLED_TIMEOUT) {
oled_off();
}
}
// Used to draw on to the oled screen
bool oled_task_user(void) {
if (is_keyboard_master()) {
oled_write_P(PSTR("Layer: "), false);
switch (get_highest_layer(layer_state|default_layer_state)) {
case _COLEMAK_DH:
oled_write_P(PSTR("Base\n"), false);
break;
case _NAV:
oled_write_P(PSTR("Nav\n"), false);
break;
case _SYM:
oled_write_P(PSTR("Sym\n"), false);
break;
case _FUN:
oled_write_P(PSTR("Function\n"), false);
break;
case _MOUSE:
oled_write_P(PSTR("Mouse\n"), false);
break;
case _NUM:
oled_write_P(PSTR("Num\n"), false);
break;
default:
oled_write_P(PSTR("Undefined\n"), false);
}
oled_write_P(PSTR("Left: "), false);
switch (left_encoder) {
case LENC_VOL:
oled_write_P(PSTR("Volume\n"), false);
break;
case LENC_WORD:
oled_write_P(PSTR("Word\n"), false);
break;
default:
break;
}
oled_write_P(PSTR("Right: "), false);
switch (right_encoder) {
case RENC_SCROLL:
oled_write_P(PSTR("Mouse scroll\n"), false);
break;
case RENC_TAB:
oled_write_P(PSTR("Alt - Tab\n"), false);
break;
case RENC_PAGE:
oled_write_P(PSTR("Page scroll\n"), false);
break;
default:
break;
}
} else {
render_luna(0,1);
oled_set_cursor(0,6);
oled_write_P(PSTR(" WPM: "), false);
oled_write(get_u8_str(get_current_wpm(), ' '), false);
}
return false;
}
/*** Custom data sync for OLED ***/
void user_sync_slave_handler(uint8_t in_buflen, const void* in_data, uint8_t out_buflen, void* out_data) {
const master_to_slave_t *m2s = (const master_to_slave_t*)in_data;
is_sneaking = m2s->is_sneaking;
is_barking = m2s->is_barking;
}
void keyboard_post_init_user(void) {
transaction_register_rpc(USER_SYNC_LUNA, user_sync_slave_handler);
}
void housekeeping_task_user(void) {
if (is_keyboard_master()) {
static uint32_t last_sync = 0;
if (timer_elapsed32(last_sync) > 50) {
master_to_slave_t m2s = {
get_mods() & MOD_MASK_CTRL,
get_mods() & MOD_MASK_SHIFT || host_keyboard_led_state().caps_lock
};
if (transaction_rpc_send(USER_SYNC_LUNA, sizeof(m2s), &m2s)) {
last_sync = timer_read32();
};
}
}
}

View file

@ -0,0 +1,249 @@
# Kyria's Default Keymap
![KLE render of the default Kyria keymap with QWERTY as the base layer. Layers are shown in sublegends.](https://i.ibb.co/RQZx2dY/default-kyria2.jpg)
The default keymap contains 5 layers which allows it to include all keys found on an ANSI layout TKL keyboard plus media keys.
Hardware features of the Kyria such as OLEDs, rotary encoders and underglow are also supported.
The five different layers are the following:
1. Base layer (QWERTY, Colemak-DH or Dvorak)
2. Navigation layer
3. Symbols/Numbers layer
4. Function layer
5. Adjust layer
## Base layer(s)
```
Base Layer: -
,-------------------------------------------. ,-------------------------------------------.
| Tab | - | - | - | - | - | | - | - | - | - | - | Bksp |
|--------+------+------+------+------+------| |------+------+------+------+------+--------|
|Ctrl/Esc| - | - | - | - | - | | - | - | - | - | - |Ctrl/ - |
|--------+------+------+------+------+------+-------------. ,-------------+------+------+------+------+------+--------|
| LShift | - | - | - | - | - | [ { |CapsLk| |F-Keys| ] } | - | - | - | - | - | RShift |
`----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
|Adjust| LGUI | LAlt/| Space| Nav | | Sym | Space| AltGr| RGUI | Menu |
| | | Enter| | | | | | | | |
`----------------------------------' `----------------------------------'
```
Three different well-known keyboard layouts are provided to fill in the placeholder `-` keys: QWERTY, Colemak-DH, and Dvorak. The default layer can be changed at runtime, more info on that in the section on the [adjust layer](#adjust-layer).
For the rest of this write-up, the base layer will be assumed to be QWERTY and will be used as a reference to describe physical keys, e.g. “<kbd>B</kbd> key” vs, the much more verbose, “lower inner index key”.
```
Base Layer: QWERTY
,-------------------------------------------. ,-------------------------------------------.
| Tab | Q | W | E | R | T | | Y | U | I | O | P | Bksp |
|--------+------+------+------+------+------| |------+------+------+------+------+--------|
|Ctrl/Esc| A | S | D | F | G | | H | J | K | L | ; : |Ctrl/' "|
|--------+------+------+------+------+------+-------------. ,-------------+------+------+------+------+------+--------|
| LShift | Z | X | C | V | B | [ { |CapsLk| |F-keys| ] } | N | M | , < | . > | / ? | RShift |
`----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
|Adjust| LGUI | LAlt/| Space| Nav | | Sym | Space| AltGr| RGUI | Menu |
| | | Enter| | | | | | | | |
`----------------------------------' `----------------------------------'
```
Aside from variations in the alpha cluster, the rest of the base keys remain the same and are designed to feel familiar.
![Step-by-step animation of the transformation of an ortholinear TKL to a Kyria](https://i.imgur.com/uVDCOek.gif)
<details>
After making transformations to the classic ANSI US QWERTY TKL 60% to arrive to the layout of the Kyria, as illustrated in the animation above, the result looks like this:
```
,-------------------------------------------. ,-------------------------------------------.
| Tab | Q | W | E | R | T | | Y | U | I | O | P | Bksp |
|--------+------+------+------+------+------| |------+------+------+------+------+--------|
| Cap Lk | A | S | D | F | G | | H | J | K | L | ; : | ' " |
|--------+------+------+------+------+------+-------------. ,-------------+------+------+------+------+------+--------|
| LShift | Z | X | C | V | B | | | | | | N | M | , < | . > | / ? | RShift |
`----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
| LCtrl| LGUI | LAlt | Space| | | | Space| AltGr| RGUI | Menu |
| | | | | | | | | | | |
`----------------------------------' '----------------------------------'
```
First thing to notice is the presence of blank keys. To fill in the blank keys above the <kbd>Space</kbd> keys, we can take inspiration from other split keyboards featuring an extra inner index column on each half. A common mapping for those kind of keys are the bracket keys that got removed in the fourth step of the animated transformation. The thumb keys besides <kbd>Space</kbd>s is prime real estate for dedicated layer-switching keys. It doesn't matter on which side is assigned the sym-layer-switch key but it helps to keep the nav-layer-switch on the left in order to keep the arrow keys on the right side like on a classic keyboard, so we'll put nav on the left and sym on the right. We'll address the remaining blank thumb keys later.
The base layer is starting to form but there remains some flaws. One glaring issue is the position of Control. Control is a very commonly used function but the key on which it sits right now is way too tucked in under the hand to be able to press it comfortably with either the thumb or the pinky from resting position. In fact, installing a rotary encoder there is a common move among Kyria users and I guarantee you that activating Control by holding down a rotary encoder does not spark joy. Instead, let's employ a popular trick that involves remapping the current Caps Lock key, which is positioned at a comfortable position on the keyboard, to Control.
We can go further though; a variant of this trick makes the Control key produce Escape when tapped. This is called a “modtap”. There is no use to tapping Control by itself without chording it with another key and there is no use to holding down the Esc key so why not combine the two into a single key?
All of this leaves us with three blank keys.
```
,-------------------------------------------. ,-------------------------------------------.
| Tab | Q | W | E | R | T | | Y | U | I | O | P | Bksp |
|--------+------+------+------+------+------| |------+------+------+------+------+--------|
|Ctrl/Esc| A | S | D | F | G | | H | J | K | L | ; : | ' " |
|--------+------+------+------+------+------+-------------. ,-------------+------+------+------+------+------+--------|
| LShift | Z | X | C | V | B | [ { | | | | ] } | N | M | , < | . > | / ? | RShift |
`--------+-------------+--------------------+------+------| |------+------+--------------------+------+---------------'
| | LGUI | LAlt | Space| Nav | | Sym | Space| AltGr| RGUI | Menu |
| | | | | | | | | | | |
`----------------------------------' '----------------------------------'
```
These keys are not easily reachable while touch typing (that is, not reachable without picking up your hand) and should thus be associated with functions that you are not likely to be typed within a stream of text. The idea is that if you have to pick up your hand to hit a key, you want it to be at a time when you are likely to be pausing your interaction with the machine, rather than in the midst of a flurry of typing. They're thus well suited for accessing the adjust layer and the function layer. We can also toss in Caps Lock even though it is an editing-type function that gets used within a stream of text because shouting in ALL-CAPS should be a deliberate action.
```
,-------------------------------------------. ,-------------------------------------------.
| Tab | Q | W | E | R | T | | Y | U | I | O | P | Bksp |
|--------+------+------+------+------+------| |------+------+------+------+------+--------|
|Ctrl/Esc| A | S | D | F | G | | H | J | K | L | ; : | ' " |
|--------+------+------+------+------+------+-------------. ,-------------+------+------+------+------+------+--------|
| LShift | Z | X | C | V | B | [ { |CapsLk| |F-keys| ] } | N | M | , < | . > | / ? | RShift |
`----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
|Adjust| LGUI | LAlt | Space| Nav | | Sym | Space| AltGr| RGUI | Menu |
| | | | | | | | | | | |
`----------------------------------' `----------------------------------'
```
The next glaring issue is the absence of an Enter key on the current base layer this far. Enter is a very frequently used key so it deserves to be placed at a good spot in the keymap. The best way to insert it in the keymap with minimal changes to the current layout is to use modtaps. A tempting solution is to turn the <kbd>RShift</kbd> key into a <kbd>RShift/Enter</kbd> modtap but that can result in chat messages sent too frustratingly early when you're not used to it. Using GUI is also sub-optimal because tapping the GUI modifier actually has a use as opposed to taps of the Control or the Shift key. Pressing and releasing the GUI key by itself opens the App menu in many desktop environments. The natural choice is thus <kbd>LAlt/Enter</kbd>. That way, Enter is 1u away from resting thumb position and is unlikely to get accidentally activated because Alt is very rarely used in the midst of prose.
Finally, we're one Quality-Of-Life update away from the actual base layer. <kbd>Ctrl/' "</kbd> not only preserves symmetry in the keymap with <kbd>Ctrl/Esc</kbd> but also helps balance the load between your pinkies and invites you to use both hands instead of contortions. Perhaps more importantly, it also frees you from the necessity of picking up your hand, breaking touch typing position and pressing a pinky key with your ring finger in order to execute Ctrl+A or Ctrl+Z. That becomes even more important on a board with such an aggressive pinky columnar stagger like the Kyria.
```
,-------------------------------------------. ,-------------------------------------------.
| Tab | Q | W | E | R | T | | Y | U | I | O | P | Bksp |
|--------+------+------+------+------+------| |------+------+------+------+------+--------|
|Ctrl/Esc| A | S | D | F | G | | H | J | K | L | ; : |Ctrl/' "|
|--------+------+------+------+------+------+-------------. ,-------------+------+------+------+------+------+--------|
| LShift | Z | X | C | V | B | [ { |CapsLk| |F-keys| ] } | N | M | , < | . > | / ? | RShift |
`----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
|Adjust| LGUI | LAlt/| Space| Nav | | Sym | Space| AltGr| RGUI | Menu |
| | | Enter| | | | | | | | |
`----------------------------------' `----------------------------------'
```
</details>
## Navigation layer
```
Nav Layer: Media, navigation
,-------------------------------------------. ,-------------------------------------------.
| | | | | | | | PgUp | Home | ↑ | End | VolUp| Delete |
|--------+------+------+------+------+------| |------+------+------+------+------+--------|
| | GUI | Alt | Ctrl | Shift| | | PgDn | ← | ↓ | → | VolDn| Insert |
|--------+------+------+------+------+------+-------------. ,-------------+------+------+------+------+------+--------|
| | | | | | | |ScLck | | | | Pause|M Prev|M Play|M Next|VolMut| PrtSc |
`----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
| | | | | | | | | | | |
| | | | | | | | | | | |
`----------------------------------' `----------------------------------'
```
This is where you'll find all the keys that are generally between the main block of a classic keyboard and the numpad in addition to media controls and modifiers on easy access on the home row for fast and comfortable chording with navigation keys.
Useful mnemonics:
- “GACS” to remember the order of the modifiers on the left-hand home row
- <kbd>Scroll Lock</kbd> is on the same key as <kbd>Caps Lock</kbd> because they're both locks
- <kbd>Delete</kbd> is on the same key as <kbd>Backspace</kbd> because they both erase characters
- <kbd>Home</kbd> is the leftmost position on the current line so it is above <kbd></kbd>. Same logic applies for <kbd>End</kbd>.
- <kbd>Media Previous</kbd> = ⏮, <kbd>Media Next</kbd> = ⏭
- <kbd>Page Up</kbd>, <kbd>Page Down</kbd> and <kbd>Volume Up</kbd>, <kbd>Volume Down</kbd> are positioned like the main <kbd>Up</kbd> and <kbd>Down</kbd> keys.
## Sym layer
```
Sym Layer: Numbers, symbols
,-------------------------------------------. ,-------------------------------------------.
| ` | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | = |
|--------+------+------+------+------+------| |------+------+------+------+------+--------|
| ~ | ! | @ | # | $ | % | | ^ | & | * | ( | ) | + |
|--------+------+------+------+------+------+-------------. ,-------------+------+------+------+------+------+--------|
| | | \ | : | ; | - | [ | { | | | | } | ] | _ | , | . | / | ? |
`----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
| | | | | | | | | | | |
| | | | | | | | | | | |
`----------------------------------' `----------------------------------'
```
The top row is the unshifted num row, the home row of the layer is the shifted num row and the bottom row contains the hyphen `-` and the underscore `_` on the best lower row spot because of how frequent they are as well as redundant symbols that are already present on the base layer but are reproduced here to avoid juggling back and forth between base, shift, and sym when typing a string of symbols.
The layout of the first two rows needs no introduction, you're already used to them but it's worth looking into the structure of the bottom row.
The two halves are mirrored in a sense. On the right, you can find <kbd>,</kbd> <kbd>.</kbd> <kbd>/</kbd> at their usual spots with the addition of <kbd>Shift</kbd>+<kbd>/</kbd>=<kbd>?</kbd> to the right of the <kbd>/</kbd> key to remove the need to press simultaneously <kbd>Sym</kbd> and a <kbd>Shift</kbd> key to access `?`.
Now, if you look at the left side, you'll notice that the mirror of <kbd>,</kbd> is <kbd>;</kbd>, the mirror of <kbd>.</kbd> is <kbd>:</kbd> and the mirror of <kbd>/</kbd> is <kbd>\\</kbd>. The same logic used for <kbd>Shift</kbd>+<kbd>/</kbd>=<kbd>?</kbd> also applies to <kbd>Shift</kbd>+<kbd>\\</kbd>=<kbd>|</kbd>.
In case you wish to combine <kbd>Shift</kbd> with a symbol key anyways, you can hold down <kbd>Shift</kbd> on the base layer with your pinky, activate <kbd>Sym</kbd> with your right thumb and while still holding down the <kbd>Shift</kbd> key, tap your desired symbol key. Same thing if you need <kbd>Ctrl</kbd>+<kbd>Digit</kbd>.
## Function layer
```
Function Layer: Function keys
,-------------------------------------------. ,-------------------------------------------.
| | F9 | F10 | F11 | F12 | | | | | | | | |
|--------+------+------+------+------+------| |------+------+------+------+------+--------|
| | F5 | F6 | F7 | F8 | | | | Shift| Ctrl | Alt | GUI | |
|--------+------+------+------+------+------+-------------. ,-------------+------+------+------+------+------+--------|
| | F1 | F2 | F3 | F4 | | | | | | | | | | | | |
`----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
| | | | | | | | | | | |
| | | | | | | | | | | |
`----------------------------------' `----------------------------------'
```
In a similar fashion to the nav layer, pressing down `FKEYS` with the right thumb enables a numpad of function keys on the opposite hand and modifiers on the right-hand home row. Once again, mirror symmetry is leveraged in this keymap for the order of the right-hand modifiers.
The <kbd>Alt</kbd> modifier, despite being situated on the right half of the keyboard is *not* `KC_RALT`, it is `KC_LALT`. `KC_RALT` is actually the <kbd>AltGr</kbd> key which generally acts very differently to the left <kbd>Alt</kbd> key. Keyboard shortcuts involving <kbd>AltGr</kbd>+<kbd>F#</kbd> are rare and infrequent as opposed to the much more common <kbd>Alt</kbd>+<kbd>F#</kbd> shortcuts. Consequently, `KC_LALT` was chosen for the function layer.
Since there are more than 10 function keys, the cluster of F-keys does not follow the usual 3×3+1 numpad arrangement.
## Adjust layer
```
Adjust Layer: Default layer settings, RGB
,-------------------------------------------. ,-------------------------------------------.
| | | |QWERTY| | | | | | | | | |
|--------+------+------+------+------+------| |------+------+------+------+------+--------|
| | | |Dvorak| | | | TOG | SAI | HUI | VAI | MOD | |
|--------+------+------+------+------+------+-------------. ,-------------+------+------+------+------+------+--------|
| | | |Colmak| | | | | | | | | SAD | HUD | VAD | RMOD | |
`----------------------+------+------+------+------+------| |------+------+------+------+------+----------------------'
| | | | | | | | | | | |
| | | | | | | | | | | |
`----------------------------------' `----------------------------------'
```
Default layer settings on the left and various RGB underglow controls on the right.
The default layer settings are lined up on the middle finger column because the home middle finger key is <kbd>D</kbd> on QWERTY (like the “D” in “Dvorak”) and the lower middle finger key is <kbd>C</kbd> on QWERTY (like the “C” in “Colemak”). I can hear you say that “QWERTY” doesn't start with “E” but Dvorak and Colemak were already aligned in a column so the QWERTY may as well join the formation.
NOTE: The default layer settings set by those keys are *NOT* stored in EEPROM and thus do not persist through boots. If you wish to change the default layer in a non-volatile manner, either change the order of the layers in the firmware, for example like so if you want to set Dvorak as the new default:
```c
enum layers {
_DVORAK = 0,
_QWERTY,
_COLEMAK_DH,
_NAV,
_SYM,
_FUNCTION,
_ADJUST
};
```
or re-define the `QWERTY`, `COLEMAK` and `DVORAK` keys to point to custom keycodes starting on `SAFE_RANGE` and calling the `set_single_persistent_default_layer` function inside of `process_record_user`.
## Hardware Features
### Rotary Encoder
The left rotary encoder is programmed to control the volume whereas the right encoder sends <kbd>PgUp</kbd> or <kbd>PgDn</kbd> on every turn.
### OLEDs
The OLEDs display the current layer at the top of the active layers stack, the Kyria logo and lock status (caps lock, num lock, scroll lock).
### Underglow
The underglow LEDs should be red.
## Going further…
This default keymap can be used as is, unchanged, as a daily driver for your Kyria but you're invited to treat your keymap like a bonsai. At the beginning, it's just like the default keymap but from time to time, you can tweak it a little. Cut a little key here, let another combo grow there. Slowly but surely it will be a unique keymap that will fit you like a glove.
Check out the #keymap-ideas channel on the official SplitKB Discord server for inspiration.

View file

@ -0,0 +1,21 @@
BOOTLOADER=caterina
OLED_ENABLE = yes
ENCODER_ENABLE = yes # Enables the use of one or more encoders
EXTRAFLAGS += -flto
MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
LTO_ENABLE = yes
WPM_ENABLE = yes
TAP_DANCE_ENABLE = yes
# AVR optimizations
RGB_MATRIX_ENABLE = no # Disable keyboard RGB matrix, as it is enabled by default on rev3
CONSOLE_ENABLE = no
SPACE_CADET_ENABLE = no
GRAVE_ESC_ENABLE = no
MAGIC_ENABLE = no
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
UNICODE_ENABLE = no# Unicode
COMMAND_ENABLE = no # Commands for debug and configuration
LEADER_ENABLE = no
MUSIC_ENABLE = no

View file

@ -0,0 +1,27 @@
/* Copyright 2022 splitkb.com <support@splitkb.com>
*
* 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
// `SPLIT_HAND_PIN` can currently be defined in `info.json`,
// but can't yet be given a value
#define SPLIT_HAND_PIN B5
// Not yet available in `info.json`
#ifdef OLED_ENABLE
# define OLED_DISPLAY_128X64
# define SPLIT_OLED_ENABLE
#endif

View file

@ -0,0 +1,198 @@
{
"keyboard_name": "Kyria rev3",
"usb": {
"pid": "0xCF44"
},
"bootmagic": {
"matrix": [0, 6]
},
"build": {
"lto": true
},
"features": {
"mousekey": true,
"bootmagic": true,
"extrakey": true,
"oled": true,
"rgb_matrix": true
},
"layout_aliases": {
"LAYOUT": "LAYOUT_split_3x6_5"
},
"layouts": {
"LAYOUT_split_3x6_5": {
"layout": [
{"label": "L06", "matrix": [0, 6], "x": 0, "y": 0.75},
{"label": "L05", "matrix": [0, 5], "x": 1, "y": 0.75},
{"label": "L04", "matrix": [0, 4], "x": 2, "y": 0.25},
{"label": "L03", "matrix": [0, 3], "x": 3, "y": 0},
{"label": "L02", "matrix": [0, 2], "x": 4, "y": 0.25},
{"label": "L01", "matrix": [0, 1], "x": 5, "y": 0.5},
{"label": "R01", "matrix": [4, 1], "x": 10.5, "y": 0.5},
{"label": "R02", "matrix": [4, 2], "x": 11.5, "y": 0.25},
{"label": "R03", "matrix": [4, 3], "x": 12.5, "y": 0},
{"label": "R04", "matrix": [4, 4], "x": 13.5, "y": 0.25},
{"label": "R05", "matrix": [4, 5], "x": 14.5, "y": 0.75},
{"label": "R06", "matrix": [4, 6], "x": 15.5, "y": 0.75},
{"label": "L12", "matrix": [1, 6], "x": 0, "y": 1.75},
{"label": "L11", "matrix": [1, 5], "x": 1, "y": 1.75},
{"label": "L10", "matrix": [1, 4], "x": 2, "y": 1.25},
{"label": "L09", "matrix": [1, 3], "x": 3, "y": 1},
{"label": "L08", "matrix": [1, 2], "x": 4, "y": 1.25},
{"label": "L07", "matrix": [1, 1], "x": 5, "y": 1.5},
{"label": "R07", "matrix": [5, 1], "x": 10.5, "y": 1.5},
{"label": "R08", "matrix": [5, 2], "x": 11.5, "y": 1.25},
{"label": "R09", "matrix": [5, 3], "x": 12.5, "y": 1},
{"label": "R10", "matrix": [5, 4], "x": 13.5, "y": 1.25},
{"label": "R11", "matrix": [5, 5], "x": 14.5, "y": 1.75},
{"label": "R12", "matrix": [5, 6], "x": 15.5, "y": 1.75},
{"label": "L20", "matrix": [2, 6], "x": 0, "y": 2.75},
{"label": "L19", "matrix": [2, 5], "x": 1, "y": 2.75},
{"label": "L18", "matrix": [2, 4], "x": 2, "y": 2.25},
{"label": "L17", "matrix": [2, 3], "x": 3, "y": 2},
{"label": "L16", "matrix": [2, 2], "x": 4, "y": 2.25},
{"label": "L15", "matrix": [2, 1], "x": 5, "y": 2.5},
{"label": "L14", "matrix": [3, 3], "x": 6, "y": 3},
{"label": "L13", "matrix": [2, 0], "x": 7, "y": 3.25},
{"label": "R13", "matrix": [6, 0], "x": 8.5, "y": 3.25},
{"label": "R14", "matrix": [7, 3], "x": 9.5, "y": 3},
{"label": "R15", "matrix": [6, 1], "x": 10.5, "y": 2.5},
{"label": "R16", "matrix": [6, 2], "x": 11.5, "y": 2.25},
{"label": "R17", "matrix": [6, 3], "x": 12.5, "y": 2},
{"label": "R18", "matrix": [6, 4], "x": 13.5, "y": 2.25},
{"label": "R19", "matrix": [6, 5], "x": 14.5, "y": 2.75},
{"label": "R20", "matrix": [6, 6], "x": 15.5, "y": 2.75},
{"label": "L25", "matrix": [3, 4], "x": 2.5, "y": 3.25},
{"label": "L24", "matrix": [3, 2], "x": 3.5, "y": 3.25},
{"label": "L23", "matrix": [3, 1], "x": 4.5, "y": 3.5},
{"label": "L22", "matrix": [3, 5], "x": 5.5, "y": 4},
{"label": "L21", "matrix": [3, 0], "x": 6.5, "y": 4.25},
{"label": "R21", "matrix": [7, 0], "x": 9, "y": 4.25},
{"label": "R22", "matrix": [7, 5], "x": 10, "y": 4},
{"label": "R23", "matrix": [7, 1], "x": 11, "y": 3.5},
{"label": "R24", "matrix": [7, 2], "x": 12, "y": 3.25},
{"label": "R25", "matrix": [7, 4], "x": 13, "y": 3.25}
]
}
},
"diode_direction": "COL2ROW",
"matrix_pins": {
"rows": ["D4", "C6", "D7", "E6"],
"cols": ["B4", "F6", "F7", "B1", "B3", "B2", "B6"]
},
"encoder": {
"enabled": true,
"rotary": [
{"pin_a": "F4", "pin_b": "F5"}
]
},
"split": {
"bootmagic": {
"matrix": [4, 6]
},
"soft_serial_pin": "D2",
"matrix_pins": {
"right": {
"rows": ["F6", "F7", "B1", "B3"],
"cols": ["B2", "D4", "C6", "D7", "E6", "B4", "B6"]
}
},
"encoder": {
"right": {
"rotary": [
{"pin_a": "F4", "pin_b": "F5"}
]
}
},
"transport": {
"sync": {
"matrix_state": true
}
}
},
"rgblight": {
"led_count": 62,
"split": true,
"split_count": [31, 31],
"max_brightness": 128
},
"ws2812": {
"pin": "D3"
},
"rgb_matrix": {
"driver": "ws2812",
"layout": [
{"flags": 2, "x": 75, "y": 2}, // L RGB1
{"flags": 2, "x": 50, "y": 1}, // L RGB2
{"flags": 2, "x": 14, "y": 4}, // L RGB3
{"flags": 2, "x": 25, "y": 45}, // L RGB4
{"flags": 2, "x": 58, "y": 49}, // L RGB5
{"flags": 2, "x": 94, "y": 53}, // L RGB6
{"flags": 4, "matrix": [3, 0], "x": 94, "y": 64}, // L SW21
{"flags": 4, "matrix": [3, 5], "x": 79, "y": 60}, // L SW22
{"flags": 4, "matrix": [3, 1], "x": 65, "y": 53}, // L SW23
{"flags": 4, "matrix": [3, 2], "x": 51, "y": 49}, // L SW24
{"flags": 4, "matrix": [3, 4], "x": 36, "y": 49}, // L SW25
{"flags": 4, "matrix": [2, 0], "x": 101, "y": 49}, // L SW13
{"flags": 4, "matrix": [3, 3], "x": 87, "y": 45}, // L SW14
{"flags": 4, "matrix": [2, 1], "x": 72, "y": 38}, // L SW15
{"flags": 4, "matrix": [2, 2], "x": 58, "y": 34}, // L SW16
{"flags": 4, "matrix": [2, 3], "x": 43, "y": 30}, // L SW17
{"flags": 4, "matrix": [2, 4], "x": 29, "y": 34}, // L SW18
{"flags": 4, "matrix": [2, 5], "x": 14, "y": 41}, // L SW19
{"flags": 4, "matrix": [2, 6], "x": 0, "y": 41}, // L SW20
{"flags": 4, "matrix": [1, 1], "x": 72, "y": 23}, // L SW07
{"flags": 4, "matrix": [1, 2], "x": 58, "y": 19}, // L SW08
{"flags": 4, "matrix": [1, 3], "x": 43, "y": 15}, // L SW09
{"flags": 4, "matrix": [1, 4], "x": 29, "y": 19}, // L SW10
{"flags": 4, "matrix": [1, 5], "x": 14, "y": 26}, // L SW11
{"flags": 4, "matrix": [1, 6], "x": 0, "y": 26}, // L SW12
{"flags": 4, "matrix": [0, 1], "x": 72, "y": 8}, // L SW01
{"flags": 4, "matrix": [0, 2], "x": 58, "y": 4}, // L SW02
{"flags": 4, "matrix": [0, 3], "x": 43, "y": 0}, // L SW03
{"flags": 4, "matrix": [0, 4], "x": 29, "y": 4}, // L SW04
{"flags": 4, "matrix": [0, 5], "x": 14, "y": 11}, // L SW05
{"flags": 4, "matrix": [0, 6], "x": 0, "y": 11}, // L SW06
{"flags": 2, "x": 149, "y": 2}, // R RGB1
{"flags": 2, "x": 174, "y": 1}, // R RGB2
{"flags": 2, "x": 210, "y": 4}, // R RGB3
{"flags": 2, "x": 199, "y": 45}, // R RGB4
{"flags": 2, "x": 166, "y": 49}, // R RGB5
{"flags": 2, "x": 130, "y": 53}, // R RGB6
{"flags": 4, "matrix": [7, 0], "x": 130, "y": 64}, // R SW21
{"flags": 4, "matrix": [7, 5], "x": 145, "y": 60}, // R SW22
{"flags": 4, "matrix": [7, 1], "x": 159, "y": 53}, // R SW23
{"flags": 4, "matrix": [7, 2], "x": 173, "y": 49}, // R SW24
{"flags": 4, "matrix": [7, 4], "x": 188, "y": 49}, // R SW25
{"flags": 4, "matrix": [6, 0], "x": 123, "y": 49}, // R SW13
{"flags": 4, "matrix": [7, 3], "x": 137, "y": 45}, // R SW14
{"flags": 4, "matrix": [6, 1], "x": 152, "y": 38}, // R SW15
{"flags": 4, "matrix": [6, 2], "x": 166, "y": 34}, // R SW16
{"flags": 4, "matrix": [6, 3], "x": 181, "y": 30}, // R SW17
{"flags": 4, "matrix": [6, 4], "x": 195, "y": 34}, // R SW18
{"flags": 4, "matrix": [6, 5], "x": 210, "y": 41}, // R SW19
{"flags": 4, "matrix": [6, 6], "x": 224, "y": 41}, // R SW20
{"flags": 4, "matrix": [5, 1], "x": 152, "y": 23}, // R SW07
{"flags": 4, "matrix": [5, 2], "x": 166, "y": 19}, // R SW08
{"flags": 4, "matrix": [5, 3], "x": 181, "y": 15}, // R SW09
{"flags": 4, "matrix": [5, 4], "x": 195, "y": 19}, // R SW10
{"flags": 4, "matrix": [5, 5], "x": 210, "y": 26}, // R SW11
{"flags": 4, "matrix": [5, 6], "x": 224, "y": 26}, // R SW12
{"flags": 4, "matrix": [4, 1], "x": 152, "y": 8}, // R SW01
{"flags": 4, "matrix": [4, 2], "x": 166, "y": 4}, // R SW02
{"flags": 4, "matrix": [4, 3], "x": 181, "y": 0}, // R SW03
{"flags": 4, "matrix": [4, 4], "x": 195, "y": 4}, // R SW04
{"flags": 4, "matrix": [4, 5], "x": 210, "y": 11}, // R SW05
{"flags": 4, "matrix": [4, 6], "x": 224, "y": 11} // R SW06
],
"max_brightness": 128,
"split_count": [31, 31]
}
}

View file

@ -0,0 +1,35 @@
/* Copyright 2022 splitkb.com <support@splitkb.com>
*
* 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 "quantum.h"
#ifdef SWAP_HANDS_ENABLE
// clang-format off
__attribute__ ((weak)) const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
{{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}},
{{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}},
{{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}},
{{0, 7}, {1, 7}, {2, 7}, {3, 7}, {4, 7}, {5, 7}},
{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}},
{{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}},
{{0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}},
{{0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}},
};
// clang-format on
# ifdef ENCODER_MAP_ENABLE
const uint8_t PROGMEM encoder_hand_swap_config[NUM_ENCODERS] = {1,0};
# endif
#endif

View file

@ -0,0 +1,2 @@
# Although no rules are defined,
# presence of this file is required for QMK to compile it.

View file

@ -1,4 +1,6 @@
{
"userspace_version": "1.0",
"build_targets": []
"build_targets": [
["splitkb/kyria/rev3", "tyosa"]
]
}