[Keymap] Add issmirnov {user, ergodox, levinson} files. (#7239)

* Add issmirnov {user, ergodox, levinson} files.

There are enough interesting QMK tricks in these layouts that it seems
worth it to share with the broader community. Big thanks to Drashna for
inspiration, as well as all the wonderful creators of QMK documentation.

Some highlights:
- Common layout shared between levinson and ergodox_ez
- TAP_TOG macro for fast layer switching
- Autogenerated keymaps ascii art with git hooks

I will do my best to do periodic rolls here, but the source of truth
will always be https://github.com/issmirnov/qmk-keebs

* Incorporate review feedback.

- Remove CLEAR_EEPROM in favor of built in EEP_RST
- Remove custom handlers for audio on bootup and shutdown
- Remove plethora of unneeded includes
- Remove deprecated and dupliated config options

HUGE thanks to drashna for the review!

* Apply suggestions from code review

Huge thanks to drashna@ for a very thorough review and the very useful suggestions.

Co-Authored-By: Drashna Jaelre <drashna@live.com>

* Remove unclear optimization

This was an artifact from some other keymap I saw.
master
Ivan Smirnov 2019-11-08 19:17:21 -08:00 committed by James Young
parent 5414ff709f
commit 2b30776dd0
25 changed files with 1023 additions and 0 deletions

View File

@ -0,0 +1,15 @@
# Levinson
## Colors
- https://github.com/qmk/qmk_firmware/blob/master/docs/feature_rgblight.md
- main docs.
- https://github.com/qmk/qmk_firmware/blob/master/quantum/rgblight_list.h
- list of colors
- https://github.com/qmk/qmk_firmware/blob/master/quantum/rgblight.h
- list of functions for RGB manipulation
## Troubleshooting
- When in doubt, flash both sides of the keyboard. For some reason that helps with LEDs and reponsiveness.
- `cd qmk_firmware && make keebio/levinson/rev2:issmirnov:dfu-split-right`

View File

@ -0,0 +1,55 @@
Qwerty
,-----------------------------------. ,-----------------------------------.
| Esc | Q | W | E | R | T | | Y | U | I | O | P |⌘ + d|
|-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----|
| Tab | A | S | D | F | G | | H | J | K | L |TapTo|Mo(Na|
|-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----|
|⇧(1) | Z | X | C | V | B | | N | M | . |Comma|Tg(Nu| ' |
|-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----|
|Ctrl | ⌘⇧ | Alt | Mod | ⌫ | Spc | |Enter| Tab | ↑ | ↓ | ← | → |
`-----------------------------------' ------------------------------------'
Symb
,-----------------------------------. ,-----------------------------------.
| | - | @ | { | } | ` | | * | ! | | | % | + | Esc |
|-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----|
| | ^ | _ | ( | ) | $ | | # | = | : | ; |TapTo| " |
|-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----|
| | < | > | [ | ] | ~ | | & | ? | / | \ |Tg(Nu| ' |
|-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----|
| | | | | | | | | | Esc | : | % | 🔒 |
`-----------------------------------' ------------------------------------'
Nump
,-----------------------------------. ,-----------------------------------.
| | No | No |Lgui(| | | | , | 7 | 8 | 9 | |Reset|
|-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----|
| | |Lgui(|Lgui(|Lgui(| | | 0 | 4 | 5 | 6 |To(Sy| |
|-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----|
| | | | |Audio|Audio| | . | 1 | 2 | 3 |To(Qw| |
|-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----|
| | | | | | | | | | | |To(Ov| |
`-----------------------------------' ------------------------------------'
Overwatch
,-----------------------------------. ,-----------------------------------.
| Tab | Q | W | E | R | T | |To(0)| | | | |Clear|
|-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----|
|Ctrl | A | S | D | F | P | |RgbMo|RgbMo|RgbVa|RgbVa| |RgbTo|
|-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----|
|Lshif| Z | X | C | V |Grave| |RgbMo|RgbMo|RgbMo|RgbMo|RgbMo|RgbMo|
|-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----|
|Ctrl | F9 |Pscre| H | R | ⎵ | |RgbHu|RgbHu|RgbSa|RgbSa|RgbMo|RgbMo|
`-----------------------------------' ------------------------------------'
Navi
,-----------------------------------. ,-----------------------------------.
| | | | ↑ | | | | | | | | | |
|-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----|
| | | ← | ↓ | → | | | |Ctrl | | | | |
|-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----|
| | | | | | | | | | | | | |
|-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----|
| | | | | |⌘ + d| | Mod | ⌘⇧ | | | | |
`-----------------------------------' ------------------------------------'

View File

@ -0,0 +1,2 @@
#!/bin/bash
make keebio/levinson/rev2:issmirnov

View File

@ -0,0 +1,34 @@
#pragma once
// Use serial comms for split keyboard
// DO NOT enable USE_IDC - board will not respond.
#define USE_SERIAL
//#define USE_I2C
#ifdef RGBLIGHT_ENABLE
// Enable animations. +5500 bytes
#define RGBLIGHT_ANIMATIONS
// Map my custom number of LED's
#undef RGBLED_NUM
#define RGBLED_NUM 16
#define RGBLIGHT_LED_MAP { 0, 1, 2, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10, 9, 8 } // When changed, BE SURE to flash EEPROM on both halves and clear it.
// DO NOT USE RGBLED_SPLIT - the slave board will stop responding.
// Turn off RGB when computer sleeps
#define RGBLIGHT_SLEEP
// custom colors
#define RGB_CLEAR 0x00, 0x00, 0x00
// MOD indicators
#define SHFT_LED1 7
#define GUI_LED1 8
#endif
#ifdef AUDIO_ENABLE
#define QMK_SPEAKER C6
#define C6_AUDIO
#define NO_MUSIC_MODE // Save 2000 bytes
#endif

View File

@ -0,0 +1,124 @@
#include "tap_tog.h"
#ifdef AUDIO_ENABLE
#include "audio.h"
#include "sounds.h"
#endif
#ifdef RGBLIGHT_ENABLE
#include "rgb.h"
#endif
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// Run `./qmk show levinson` from parent dir to see this layer.
[_QWERTY] = LAYOUT_ortho_4x12_wrapper(
KC_ESC , _________________QWERTY_L1_________________, _________________QWERTY_R1_________________ , APPS ,
KC_TAB , _________________QWERTY_L2_________________, _________________QWERTY_R2_________________ , MO(_NAVI) ,
OSMSFT , _________________QWERTY_L3_________________, _________________QWERTY_R3_________________ , KC_QUOTE ,
KC_LCTL , MODSFT , KC_LALT , KC_LGUI , KC_BSPACE , KC_SPC , KC_ENTER , KC_TAB , KC_UP , KC_DOWN , KC_LEFT , KC_RGHT
), // Note: visualizer expects this closing parens to be right at the start of the line.
// Run `./qmk show levinson` from parent dir to see this layer.
[_SYMB] = LAYOUT_ortho_4x12_wrapper(
_______ , _________________SYMB_L1___________________, _________________SYMB_R1___________________ , KC_ESC ,
_______ , _________________SYMB_L2___________________, _________________SYMB_R2___________________ , KC_DQT ,
_______ , _________________SYMB_L3___________________, _________________SYMB_R3___________________ , KC_QUOTE ,
_______ , ___________________BLANK___________________, _______ , _______ , KC_ESC , KC_COLN , KC_PERC , LOCK
), // Note: visualizer expects this closing parens to be right at the start of the line.
// Run `./qmk show levinson` from parent dir to see this layer.
[_NUMP] = LAYOUT_ortho_4x12_wrapper(
_______ , _________________NUMP_L1___________________ , _________________NUMP_R1___________________ , RESET ,
_______ , _________________NUMP_L2___________________ , _________________NUMP_R2___________________ , _______ ,
_______ , _________________NUMP_L3___________________ , _________________NUMP_R3___________________ , _______ ,
_______ , ___________________BLANK___________________ , _______ , _______ , _______ , _______ , TO(_OVERWATCH) , _______
), // Note: visualizer expects this closing parens to be right at the start of the line.
// Run `./qmk show levinson` from parent dir to see this layer.
[_OVERWATCH] = LAYOUT_ortho_4x12_wrapper(
______________OVERWATCH_L1_________________ , TO(0) , XXXXXXX , XXXXXXX , XXXXXXX , XXXXXXX , EEP_RST ,
______________OVERWATCH_L2_________________ , RGB_MODE_FORWARD , RGB_MODE_REVERSE , RGB_VAI , RGB_VAD , XXXXXXX , RGB_TOG ,
______________OVERWATCH_L3_________________ , RGB_MODE_PLAIN , RGB_MODE_BREATHE , RGB_MODE_RAINBOW , RGB_MODE_SWIRL , RGB_MODE_SNAKE , RGB_MODE_XMAS ,
______________OVERWATCH_L4_________________ , KC_SPACE, RGB_HUI , RGB_HUD , RGB_SAI , RGB_SAD , RGB_MODE_RGBTEST , RGB_MODE_GRADIENT
), // Note: visualizer expects this closing parens to be right at the start of the line.
// Run `./qmk show levinson` from parent dir to see this layer.
[_NAVI] = LAYOUT_ortho_4x12_wrapper(
XXXXXXX , _________________NAVI_L1___________________ , _________________NAVI_R1___________________ , XXXXXXX ,
XXXXXXX , _________________NAVI_L2___________________ , _________________NAVI_R2___________________ , XXXXXXX ,
XXXXXXX , _________________NAVI_L3___________________ , _________________NAVI_R3___________________ , XXXXXXX ,
XXXXXXX , XXXXXXX , XXXXXXX , XXXXXXX , XXXXXXX , APPS , KC_LGUI , MODSFT , XXXXXXX , XXXXXXX , XXXXXXX , XXXXXXX
), // Note: visualizer expects this closing parens to be right at the start of the line.
};
// called by QMK during key processing before the actual key event is handled. Useful for macros.
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case LOCK:
if (record->event.pressed) {
rgblight_mode(RGBLIGHT_MODE_RAINBOW_SWIRL);
}
return true; // Let QMK send the press/release events
break;
case TAP_TOG_LAYER:
process_tap_tog(_SYMB,record);
return false;
break;
default:
tap_tog_count = 0; // reset counter.
tap_tog_layer_other_key_pressed = true; // always set this to true, TAP_TOG_LAYER handlers will handle interpreting this
break;
}
return true;
}
// Runs constantly in the background, in a loop every 100ms or so.
// Best used for LED status output triggered when user isn't actively typing.
void matrix_scan_user(void) {
#ifdef RGBLIGHT_ENABLE
matrix_scan_rgb();
#endif // RGBLIGHT_ENABLE
}
// only runs when when the layer is changed, good for updating LED's and clearing sticky state
// RGB modes: https://github.com/qmk/qmk_firmware/blob/master/quantum/rgblight.h
uint32_t layer_state_set_user(uint32_t state) {
#ifdef RGBLIGHT_ENABLE
layer_state_set_rgb(state);
#endif
uint8_t layer = biton32(state);
combo_enable(); // by default, enable combos.
switch (layer) {
case 0:
break;
case 1:
clear_mods();
break;
case 2:
clear_mods();
break;
case _OVERWATCH:
clear_mods();
combo_disable(); // We don't want combos in overwatch
#ifdef AUDIO_ENABLE
// PLAY_SONG(song_overwatch);
#endif
break;
default:
break;
}
return state;
};
// Runs boot tasks for keyboard.
// Plays a welcome song and clears RGB state.
void matrix_init_user(void) {
#ifdef RGBLIGHT_ENABLE
keyboard_post_init_rgb();
#endif
}

View File

@ -0,0 +1,2 @@
#!/bin/bash
make keebio/levinson/rev2:issmirnov:dfu-split-left

View File

@ -0,0 +1,61 @@
#include "rgb.h"
// TODO gate this debugging header
#include <print.h>
// Wired up in layer_state_set_user in keymap.c
layer_state_t layer_state_set_rgb(layer_state_t state) {
switch (get_highest_layer(state)) {
case _QWERTY:
rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
rgblight_sethsv_noeeprom(RGB_CLEAR);
break;
case _SYMB:
rgblight_sethsv_noeeprom_red();
break;
case _NUMP:
rgblight_sethsv_noeeprom_green();
break;
case _OVERWATCH:
rgblight_sethsv_noeeprom_blue();
// TODO set up animated rainbow swirl with overwatch colors.
// rgblight_mode_noeeprom(RGBLIGHT_MODE_RAINBOW_SWIRL);
// rgblight_effect_breathing(&animation_status);
// rgblight_mode_noeeprom(RGBLIGHT_MODE_BREATHING + 3);
break;
case _NAVI:
rgblight_sethsv_noeeprom(HSV_AZURE);
break;
default: // for any other layers, or the default layer
break;
}
return state;
}
void keyboard_post_init_rgb(void) {
rgblight_enable();
rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
rgblight_setrgb(RGB_CLEAR);
uprintf("Reset RGB colors");
}
void matrix_scan_rgb(void) {
set_rgb_indicators(get_mods(), get_oneshot_mods());
}
void set_rgb_indicators(uint8_t this_mod, uint8_t this_osm) {
if (biton32(layer_state) == _QWERTY) {
if ((this_mod | this_osm) & MOD_MASK_SHIFT) {
rgblight_setrgb_gold_at(SHFT_LED1);
} else {
rgblight_setrgb_at(RGB_CLEAR, SHFT_LED1);
}
if ((this_mod | this_osm) & MOD_MASK_GUI) {
rgblight_setrgb_purple_at(GUI_LED1);
} else {
rgblight_setrgb_at(RGB_CLEAR, GUI_LED1);
}
}
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "quantum.h"
#include "issmirnov.h"
// Welcome animation when keyboard boots
void keyboard_post_init_rgb(void);
// If rgb enabled, set underglow for layer
uint32_t layer_state_set_rgb(uint32_t state);
// Enhance matrix scan code. Note: keep this light, since it runs every 100ms
void matrix_scan_rgb(void);
// Light up SHIFT and GUI indicator when pressed.
void set_rgb_indicators(uint8_t this_mod, uint8_t this_osm);

View File

@ -0,0 +1,14 @@
# Enable RGB underglow
# https://beta.docs.qmk.fm/features/feature_rgblight
RGBLIGHT_ENABLE = yes # +5500 bytes
ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
# Include my fancy rgb functions source here
SRC += rgb.c
endif
# Disable backlight, since I use RGB underglow.
# https://beta.docs.qmk.fm/features/feature_backlight
BACKLIGHT_ENABLE = no
# Control piezo speaker on C6
AUDIO_ENABLE = yes # +4000 bytes

View File

@ -0,0 +1,9 @@
// ................................................................ Audio Sounds
#pragma once
#ifdef AUDIO_ENABLE
// Songs come from quantum/audio/song_list.h
float song_startup [][2] = SONG(STARTUP_SOUND);
float song_goodbye [][2] = SONG(GOODBYE_SOUND);
float song_overwatch[][2] = SONG(OVERWATCH_THEME);
#undef AUDIO_VOICES
#endif

View File

@ -0,0 +1,9 @@
,-----------------------------------. ,-----------------------------------.
| 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 | | 42 | 43 | 44 | 45 | 46 | 47 |
`-----------------------------------' ------------------------------------'

View File

@ -0,0 +1,49 @@
# Ivan's Ergodox Config
## Details about the layout
- Shift and Cmd are One Shot Modifiers, so tapping them once will apply them to the next key. When tapped twice they will lock, until tapped again to clear.
- When switching to other layers, any stuck modifiers are cleared in order to avoid unintended key combos
- There are a few leader key combinations. Right now, `KC_LEAD` + `s` will open my wiki homepage.
- All transparent keys have been replaced with noops to avoid layer bleeding.
## Initial Setup
### QMK
```
brew tap osx-cross/avr
brew tap PX4/homebrew-px4
brew update
brew install avr-gcc
brew install dfu-programmer
brew install gcc-arm-none-eabi
brew install avrdude
git clone https://github.com/qmk/qmk_firmware.git
git clone https://github.com/issmirnov/ergodox-layout.git \
layouts/community/ergodox/ismirnov
```
### Teensy utils
Download and add both of these to $PATH
- [hid_listen](https://www.pjrc.com/teensy/hid_listen.html)
- [teensy loader cli](https://www.pjrc.com/teensy/loader_cli.html)
## Flashing
```
make ergodox_ez:ismirnov
teensy_loader_cli -mmcu=atmega32u4 -w -v ergodox_ez_ismirnov.hex
# or just
make ergodox_ez:ismirnov:flash
```
## Gotchas
- If you get error: `dyld: Library not loaded: /usr/local/opt/isl/lib/libisl.15.dylib` then do `brew reinstall avr-gcc`
- If `hid_listen` just prints out a ton of dots, update makefile with `CONSOLE_ENABLE = yes`

View File

@ -0,0 +1,95 @@
Qwerty
,--------------------------------------------. ,--------------------------------------------.
| Escape | 1 | 2 | 3 | 4 | 5 | ! | | = | 6 | 7 | 8 | 9 | 0 | Escape |
|--------+-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----+--------|
|Lctl(Spa| Q | W | E | R | T | * | | + | Y | U | I | O | P |Lgui(Spa|
|--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
| Tab | A | S | D | F | G |-----| |-----| H | J | K | L |TapTo|Mo(Navi)|
|--------+-----+-----+-----+-----+-----| / | | - |-----+-----+-----+-----+-----+--------|
|Osm(ModL| Z | X | C | V | B | | | | N | M | . |Comma|Tg(Nu| ' |
`--------+-----+-----+-----+-----+-----------' `-----------+-----+-----+-----+-----+--------'
|Ctrl |Lsft(|Lsft(| Alt | Mod | |Escap| : | % | |Lgui(|
`-----------------------------' ,-----------. ,-----------. `-----------------------------'
| | | | ← | → |
,-----|-----|-----| |-----+-----+-----.
| | | | | ↑ | | |
| ⎵ | ⌫ |-----| |-----| Tab |Enter|
| | | Del | | ↓ | | |
`-----------------' `-----------------'
Symb
,--------------------------------------------. ,--------------------------------------------.
| Escape | F1 | F2 | F3 | F4 | F5 | F6 | | F7 | F8 | F9 | F10 | F11 | F12 | |
|--------+-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----+--------|
| | - | @ | { | } | ` | * | | + | * | ! | | | % | + |Mo(Navi)|
|--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
| Tab | ^ | _ | ( | ) | $ |-----| |-----| # | = | : | ; |TapTo| Dquo |
|--------+-----+-----+-----+-----+-----| / | | - |-----+-----+-----+-----+-----+--------|
| Lshift | < | > | [ | ] | ~ | | | | & | ? | / | \ |Tg(Nu| ' |
`--------+-----+-----+-----+-----+-----------' `-----------+-----+-----+-----+-----+--------'
|Ctrl |Lsft(|Lsft(| Alt |WkspL| |Escap| : | % | | |
`-----------------------------' ,-----------. ,-----------. `-----------------------------'
| | | | ← | → |
,-----|-----|-----| |-----+-----+-----.
| | | | | ↑ | | |
|WkspR| ⌫ |-----| |-----| Tab |Enter|
| | | Del | | ↓ | | |
`-----------------' `-----------------'
Nump
,--------------------------------------------. ,--------------------------------------------.
| | | | | | | | | = | | | | | | Reset |
|--------+-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----+--------|
| | No | No |Lgui(| | | * | | + | , | 7 | 8 | 9 | | |
|--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
| Tab | |Lgui(|Lgui(|Lgui(| |-----| |-----| 0 | 4 | 5 | 6 |To(Sy| |
|--------+-----+-----+-----+-----+-----| / | | - |-----+-----+-----+-----+-----+--------|
| | | | |Audio|Audio| | | | . | 1 | 2 | 3 |To(Qw| |
`--------+-----+-----+-----+-----+-----------' `-----------+-----+-----+-----+-----+--------'
|To(0)| | | | | | 0 | | |To(3)| |
`-----------------------------' ,-----------. ,-----------. `-----------------------------'
| | | | ← | → |
,-----|-----|-----| |-----+-----+-----.
| | | | | ↑ | | |
| ⎵ | ⌫ |-----| |-----| Alt |Shift|
| | | Del | | ↓ | | |
`-----------------' `-----------------'
Overwatch
,--------------------------------------------. ,--------------------------------------------.
| Escape | 1 | 2 | 3 | 4 | 5 |To(0)| | | | | | | | |
|--------+-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----+--------|
| Tab | Q | W | E | R | T | | | | | | | | | |
|--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
| Ctrl | A | S | D | F | P |-----| |-----| | | | | | |
|--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
| Lshift | Z | X | C | V |Grave| | | | | | | | | |
`--------+-----+-----+-----+-----+-----------' `-----------+-----+-----+-----+-----+--------'
|Ctrl | F9 |Pscre| H | R | | | | | | |
`-----------------------------' ,-----------. ,-----------. `-----------------------------'
| | | | | |
,-----|-----|-----| |-----+-----+-----.
| | | | | | | |
| ⎵ | |-----| |-----| | |
| | | | | | | |
`-----------------' `-----------------'
Navi
,--------------------------------------------. ,--------------------------------------------.
| Escape | 1 | 2 | 3 | 4 | 5 | 6 | | | | | | | | |
|--------+-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----+--------|
| | | | ↑ | | | | | | | | | | | |
|--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
| | | ← | ↓ | → | |-----| |-----| |Ctrl | | | | |
|--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
| | | | | | | | | | | | | | | |
`--------+-----+-----+-----+-----+-----------' `-----------+-----+-----+-----+-----+--------'
| | | | |WkspL| | ⌘⇧ | | | | |
`-----------------------------' ,-----------. ,-----------. `-----------------------------'
| | | | | |
,-----|-----|-----| |-----+-----+-----.
| | | | | | | |
|WkspR| |-----| |-----| | Mod |
| | | | | | | |
`-----------------' `-----------------'

View File

@ -0,0 +1,2 @@
#!/bin/bash
make ergodox_ez:issmirnov

View File

@ -0,0 +1,3 @@
// Reference: https://beta.docs.qmk.fm/reference/config-options
// and https://github.com/qmk/qmk_firmware/blob/master/docs/config_options.md
#include QMK_KEYBOARD_CONFIG_H

View File

@ -0,0 +1,250 @@
#include QMK_KEYBOARD_H
// Custom user includes
#include "issmirnov.h"
#include "tap_tog.h"
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_QWERTY] = LAYOUT_ergodox_wrapper(
KC_ESCAPE, KC_1, KC_2, KC_3, KC_4, KC_5, KC_EXLM,
LCTL(KC_SPACE), _________________QWERTY_L1_________________, KC_ASTR,
KC_TAB, _________________QWERTY_L2_________________,
OSM(MOD_LSFT), _________________QWERTY_L3_________________, KC_SLASH,
KC_LCTL, LSFT(KC_LGUI), LSFT(KC_LALT), KC_LALT, KC_LGUI,
XXXXXXX, XXXXXXX,
XXXXXXX,
KC_SPACE, KC_BSPACE, KC_DEL,
KC_EQL , KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , KC_ESCAPE ,
KC_PLUS , _________________QWERTY_R1_________________ , LGUI(KC_SPACE) ,
_________________QWERTY_R2_________________ , MO(_NAVI) ,
KC_MINS , _________________QWERTY_R3_________________ , KC_QUOTE ,
KC_ESCAPE , KC_COLN , KC_PERC , XXXXXXX , LGUI(KC_L) ,
KC_LEFT, KC_RGHT,
KC_UP,
KC_DOWN, KC_TAB, KC_ENTER
),
// layer 1
[_SYMB] = LAYOUT_ergodox_wrapper(
KC_ESCAPE , KC_F1 , KC_F2 , KC_F3 , KC_F4 , KC_F5 , KC_F6 ,
XXXXXXX , _________________SYMB_L1___________________ ,KC_ASTR ,
KC_TAB , _________________SYMB_L2___________________,
KC_LSHIFT , _________________SYMB_L3___________________, KC_SLASH ,
KC_LCTL , LSFT(KC_LGUI) , LSFT(KC_LALT) , KC_LALT , WKSP_LEFT ,
XXXXXXX, XXXXXXX,
XXXXXXX,
WKSP_RIGHT, KC_BSPACE, KC_DEL,
KC_F7 , KC_F8 , KC_F9 , KC_F10 , KC_F11 , KC_F12 , XXXXXXX ,
KC_PLUS , _________________SYMB_R1___________________ , MO(_NAVI) ,
_________________SYMB_R2___________________ , KC_DQUO ,
KC_MINS , _________________SYMB_R3___________________ , KC_QUOTE ,
KC_ESCAPE , KC_COLN , KC_PERC , XXXXXXX , XXXXXXX ,
KC_LEFT, KC_RGHT,
KC_UP,
KC_DOWN, KC_TAB, KC_ENTER
),
// layer 2
[_NUMP] = LAYOUT_ergodox_wrapper(
XXXXXXX , ___________________XXXXX___________________, XXXXXXX ,
XXXXXXX , _________________NUMP_L1___________________ , KC_ASTR ,
KC_TAB , _________________NUMP_L2___________________ ,
XXXXXXX , _________________NUMP_L3___________________ , KC_SLASH ,
TO(0) , XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
XXXXXXX , XXXXXXX ,
XXXXXXX ,
KC_SPACE , KC_BSPACE , KC_DEL ,
KC_EQL , ___________________XXXXX___________________ , RESET ,
KC_PLUS , _________________NUMP_R1___________________ , XXXXXXX ,
_________________NUMP_R2___________________ , XXXXXXX ,
KC_MINS , _________________NUMP_R3___________________ , XXXXXXX ,
KC_0 , XXXXXXX , XXXXXXX , TO(3) , XXXXXXX ,
KC_LEFT, KC_RGHT,
KC_UP,
KC_DOWN, KC_LALT, KC_LSFT
),
// layer 3
[_OVERWATCH] = LAYOUT_ergodox_wrapper(
KC_ESCAPE, KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , TO(0) ,
______________OVERWATCH_L1_________________ , XXXXXXX ,
______________OVERWATCH_L2_________________ ,
______________OVERWATCH_L3_________________ , XXXXXXX ,
______________OVERWATCH_L4_________________ ,
XXXXXXX , XXXXXXX ,
XXXXXXX ,
KC_SPACE , XXXXXXX , XXXXXXX ,
_______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______,
_______, _______,
_______,
_______, _______, _______
),
// layer 4
[_NAVI] = LAYOUT_ergodox_wrapper(
KC_ESCAPE, KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , KC_6 ,
XXXXXXX, _________________NAVI_L1___________________ , XXXXXXX ,
XXXXXXX, _________________NAVI_L2___________________ ,
XXXXXXX, _________________NAVI_L3___________________ , XXXXXXX ,
XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, WKSP_LEFT,
XXXXXXX , XXXXXXX ,
XXXXXXX ,
WKSP_RIGHT , XXXXXXX , XXXXXXX ,
_______, _______, _______, _______, _______, _______, _______,
_______, _________________NAVI_R1___________________, _______,
_________________NAVI_R2___________________, _______,
_______, _________________NAVI_R3___________________, _______,
MODSFT, _______, _______, _______, _______,
_______, _______,
_______,
_______, _______, KC_LGUI
),
};
// called by QMK during key processing before the actual key event is handled. Useful for macros.
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
uint8_t layer = biton32(layer_state);
switch (keycode) {
case TAP_TOG_LAYER:
process_tap_tog(_SYMB,record);
return false;
break;
case WKSP_LEFT:
// Only if TAP_TOG_LAYER is being held right now do we want to do actions.
if (record->event.pressed && (!tap_tog_layer_toggled_on || layer == _NAVI)) {
tap_code16(LGUI(LSFT(KC_Z)));
tap_tog_layer_other_key_pressed = true; // Add flag so layer resets
}
break;
case WKSP_RIGHT:
// Only if TAP_TOG_LAYER is being held right now do we want to do actions.
if (record->event.pressed && (!tap_tog_layer_toggled_on || layer == _NAVI)) {
tap_code16(LGUI(LSFT(KC_X)));
tap_tog_layer_other_key_pressed = true; // Add flag so layer resets
}
break;
default:
tap_tog_count = 0; // reset counter.
tap_tog_layer_other_key_pressed = true; // always set this to true, TAP_TOG_LAYER handlers will handle interpreting this
break;
}
return true;
}
// Runs constantly in the background, in a loop every 100ms or so.
// Best used for LED status output triggered when user isn't actively typing.
void matrix_scan_user(void) {
uint8_t layer = biton32(layer_state);
if (layer == 0) {
// Set up LED indicators for stuck modifier keys.
// https://github.com/qmk/qmk_firmware/blob/master/tmk_core/common/report.h#L118
switch (keyboard_report->mods) {
case MOD_BIT(KC_LSFT): // LSHIFT
ergodox_right_led_1_set (LED_BRIGHTNESS_LO);
ergodox_right_led_1_on ();
ergodox_right_led_2_set (LED_BRIGHTNESS_LO);
ergodox_right_led_2_on ();
ergodox_right_led_3_set (LED_BRIGHTNESS_HI);
ergodox_right_led_3_off ();
break;
case MOD_BIT(KC_LGUI): // LGUI
ergodox_right_led_1_set (LED_BRIGHTNESS_HI);
ergodox_right_led_1_off ();
ergodox_right_led_2_set (LED_BRIGHTNESS_LO);
ergodox_right_led_2_on ();
ergodox_right_led_3_set (LED_BRIGHTNESS_LO);
ergodox_right_led_3_on ();
break;
case MOD_BIT(KC_LSFT) ^ MOD_BIT(KC_LGUI):
ergodox_right_led_1_set (70);
ergodox_right_led_1_on ();
ergodox_right_led_2_set (70);
ergodox_right_led_2_on ();
ergodox_right_led_3_set (70);
ergodox_right_led_3_on ();
break;
default: // reset leds
ergodox_right_led_1_set (LED_BRIGHTNESS_HI);
ergodox_right_led_1_off ();
ergodox_right_led_2_set (LED_BRIGHTNESS_HI);
ergodox_right_led_2_off ();
ergodox_right_led_3_set (LED_BRIGHTNESS_HI);
ergodox_right_led_3_off ();
}
}
}
// only runs when when the layer is changed, good for updating LED's and clearing sticky state
uint32_t layer_state_set_user(uint32_t state) {
uint8_t layer = biton32(state);
ergodox_board_led_off();
ergodox_right_led_1_off();
ergodox_right_led_2_off();
ergodox_right_led_3_off();
combo_enable(); // by default, enable combos.
switch (layer) {
case 0:
break;
case 1:
clear_mods();
ergodox_right_led_1_on();
break;
case 2:
clear_mods();
ergodox_right_led_2_on();
break;
case _OVERWATCH:
clear_mods();
combo_disable(); // We don't want combos in overwatch
ergodox_right_led_3_on();
break;
case 4:
ergodox_right_led_1_on();
ergodox_right_led_2_on();
break;
case 5:
ergodox_right_led_1_on();
ergodox_right_led_3_on();
break;
case 6:
ergodox_right_led_2_on();
ergodox_right_led_3_on();
break;
case 7:
ergodox_right_led_1_on();
ergodox_right_led_2_on();
ergodox_right_led_3_on();
break;
default:
break;
}
return state;
};

View File

@ -0,0 +1,2 @@
#!/bin/bash
make ergodox_ez:issmirnov:teensy

View File

@ -0,0 +1,17 @@
,--------------------------------------------. ,--------------------------------------------.
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
|--------+-----+-----+-----+-----+-----+-----| |-----+-----+-----+-----+-----+-----+--------|
| 7 | 8 | 9 | 10 | 11 | 12 | 13 | | 45 | 46 | 47 | 48 | 49 | 50 | 51 |
|--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
| 14 | 15 | 16 | 17 | 18 | 19 |-----| |-----| 52 | 53 | 54 | 55 | 56 | 57 |
|--------+-----+-----+-----+-----+-----| 26 | | 58 |-----+-----+-----+-----+-----+--------|
| 20 | 21 | 22 | 23 | 24 | 25 | | | | 59 | 60 | 61 | 62 | 63 | 64 |
`--------+-----+-----+-----+-----+-----------' `-----------+-----+-----+-----+-----+--------'
| 27 | 28 | 29 | 30 | 31 | | 65 | 66 | 67 | 68 | 69 |
`-----------------------------' ,-----------. ,-----------. `-----------------------------'
| 32 | 33 | | 70 | 71 |
,-----|-----|-----| |-----+-----+-----.
| | | 34 | | 72 | | |
| 35 | 36 |-----| |-----| 74 | 75 |
| | | 37 | | 73 | | |
`-----------------' `-----------------'

View File

@ -0,0 +1,45 @@
#pragma once
// Allows sending more than one key per scan. Useful for chords.
#define QMK_KEYS_PER_SCAN 4
// how long before a tap becomes a hold
#undef TAPPING_TERM
#define TAPPING_TERM 100
// makes tap and hold keys work better for fast typers who don't want
// tapping term set above 500
#define PERMISSIVE_HOLD
// tap anyway, even after TAPPING_TERM, if there was no other key
// interruption between press and release
#define RETRO_TAPPING
// how many taps before triggering the toggle
#undef ONESHOT_TAP_TOGGLE
#define ONESHOT_TAP_TOGGLE 2
// how long before oneshot modifier key times out (currently only shift)
#undef ONESHOT_TIMEOUT
#define ONESHOT_TIMEOUT 2000
// Enable combos for vim
#define COMBO_COUNT 5 // Specify the number of combos used. BE SURE TO INCREMENT AS NEEDED
#define COMBO_TERM 50 // window in milliseconds to trigger combo
// Allow more than 4 keys to be sent to the system. Useful for gaming.
// #define FORCE_NKRO
// Save 200 bytes on unused keycodes
#undef LOCKING_SUPPORT_ENABLE
#undef LOCKING_RESYNC_ENABLE
// Enable HID_listen commands.
#define NO_DEBUG
#undef NO_PRINT
#define USER_PRINT
// Note: Defining the following does not have any impact on space:
// - NO_ACTION_MACRO
// - NO_ACTION_FUNCTION
// - DISABLE_LEADER

View File

@ -0,0 +1,43 @@
#include "issmirnov.h"
enum combo_events {
JK_ESC,
DF_CLN,
SD_SLASH,
XC_COPY,
XV_PASTE
};
const uint16_t PROGMEM jk_combo[] = {KC_J, KC_K, COMBO_END};
const uint16_t PROGMEM df_combo[] = {KC_D, KC_F, COMBO_END};
const uint16_t PROGMEM sd_combo[] = {KC_S, KC_D, COMBO_END};
const uint16_t PROGMEM copy_combo[] = {KC_X, KC_C, COMBO_END};
const uint16_t PROGMEM paste_combo[] = {KC_X, KC_V, COMBO_END};
// BE SURE TO UPDATE THE CONFIG.H "COMBO_COUNT" value when you add elements here!
combo_t key_combos[COMBO_COUNT] = {
COMBO(jk_combo, KC_ESC),
COMBO(df_combo, KC_COLON),
COMBO(sd_combo, KC_SLASH),
[XC_COPY] = COMBO_ACTION(copy_combo),
[XV_PASTE] = COMBO_ACTION(paste_combo),
};
void process_combo_event(uint8_t combo_index, bool pressed) {
switch(combo_index) {
case XC_COPY:
if (pressed) {
tap_code16(LCTL(KC_C));
}
break;
case XV_PASTE:
if (pressed) {
tap_code16(LCTL(KC_V));
}
break;
}
}

View File

@ -0,0 +1,35 @@
#pragma once
#include QMK_KEYBOARD_H
#include "rows.h"
// Each layer gets a name for readability, which is then used in the keymap matrix below.
// The underscores don't mean anything - you can have a layer called STUFF or any other name.
// Layer names don't all need to be of the same length, obviously, and you can also skip them
// entirely and just use numbers
enum {
_QWERTY = 0,
_SYMB,
_NUMP,
_OVERWATCH,
_NAVI
};
enum custom_keycodes {
PLACEHOLDER = SAFE_RANGE,
TAP_TOG_LAYER,
CLEAR_EEPROM,
WKSP_LEFT, // Smart key that only activates when we are momentarily in a layer
WKSP_RIGHT, // Smart key that only activates when we are momentarily in a layer
};
#define LOWER MO(_SYMB)
#define RAISE MO(_NUMP)
#define CTL_SPC MT(MOD_LCTL, KC_SPC)
#define OSMSFT OSM(MOD_LSFT)
#define LOCK LGUI(KC_L)
#define MODSFT LSFT(KC_LGUI)
#define APPS LGUI(KC_SPC)

View File

@ -0,0 +1,55 @@
#pragma once
#include QMK_KEYBOARD_H
// This wrapper is required in order to expand the row macro inside the keymap configs.
#define LAYOUT_ergodox_wrapper(...) LAYOUT_ergodox(__VA_ARGS__)
#define LAYOUT_ortho_4x12_wrapper(...) LAYOUT_ortho_4x12(__VA_ARGS__)
// Share common config. We'll skip the mod rows and func rows.
// Note, it's also really neat the way the scoping works. Since we perform the expansion in the keymap.c file
// so we can use our enums for custom keycodes
#define _________________QWERTY_L1_________________ KC_Q , KC_W , KC_E , KC_R , KC_T
#define _________________QWERTY_L2_________________ KC_A , KC_S , KC_D , KC_F , KC_G
#define _________________QWERTY_L3_________________ KC_Z , KC_X , KC_C , KC_V , KC_B
#define _________________QWERTY_R1_________________ KC_Y , KC_U , KC_I , KC_O , KC_P
#define _________________QWERTY_R2_________________ KC_H , KC_J , KC_K , KC_L , TAP_TOG_LAYER
#define _________________QWERTY_R3_________________ KC_N , KC_M , KC_DOT , KC_COMMA , TG(_NUMP)
#define ___________________BLANK___________________ _______ , _______ , _______ , _______ , _______
#define ___________________XXXXX___________________ XXXXXXX , XXXXXXX , XXXXXXX , XXXXXXX , XXXXXXX
#define _________________SYMB_L1___________________ KC_MINS , KC_AT , KC_LCBR , KC_RCBR , KC_GRV
#define _________________SYMB_L2___________________ KC_CIRC , KC_UNDS , KC_LPRN , KC_RPRN , KC_DLR
#define _________________SYMB_L3___________________ KC_LABK , KC_RABK , KC_LBRACKET , KC_RBRACKET , KC_TILD
#define _________________SYMB_R1___________________ KC_ASTR , KC_EXLM , KC_PIPE , KC_PERC , KC_PLUS
#define _________________SYMB_R2___________________ KC_HASH , KC_EQL , KC_COLN , KC_SCLN , TAP_TOG_LAYER
#define _________________SYMB_R3___________________ KC_AMPR , KC_QUES , KC_SLASH , KC_BSLASH , TG(_NUMP)
#define _________________NUMP_L1___________________ KC_NO , KC_NO , LGUI(KC_UP) , XXXXXXX , XXXXXXX
#define _________________NUMP_L2___________________ XXXXXXX , LGUI(KC_LEFT) , LGUI(KC_DOWN) , LGUI(KC_RIGHT) , XXXXXXX
#define _________________NUMP_L3___________________ XXXXXXX , XXXXXXX , XXXXXXX , KC_AUDIO_VOL_DOWN , KC_AUDIO_VOL_UP
#define _________________NUMP_R1___________________ KC_COMM , KC_7 , KC_8 , KC_9 , XXXXXXX
#define _________________NUMP_R2___________________ KC_0 , KC_4 , KC_5 , KC_6 , TO(_SYMB)
#define _________________NUMP_R3___________________ KC_DOT , KC_1 , KC_2 , KC_3 , TO(_QWERTY)
// Note: These are 6x1 blocks, since modifiers are also adjusted.
#define ______________OVERWATCH_L1_________________ KC_TAB , KC_Q , KC_W , KC_E , KC_R , KC_T
#define ______________OVERWATCH_L2_________________ KC_LCTL , KC_A , KC_S , KC_D , KC_F , KC_P
#define ______________OVERWATCH_L3_________________ KC_LSHIFT , KC_Z , KC_X , KC_C , KC_V , KC_GRAVE
// Ergodox only has 5 keys on bottom row:
#define ______________OVERWATCH_L4_________________ KC_LCTL , KC_F9 , KC_PSCREEN , KC_H , KC_R
#define _________________NAVI_L1___________________ XXXXXXX , XXXXXXX , KC_UP , XXXXXXX , XXXXXXX
#define _________________NAVI_L2___________________ XXXXXXX , KC_LEFT , KC_DOWN , KC_RGHT , XXXXXXX
#define _________________NAVI_L3___________________ XXXXXXX , XXXXXXX , XXXXXXX , XXXXXXX , XXXXXXX
#define _________________NAVI_R1___________________ XXXXXXX , XXXXXXX , XXXXXXX , XXXXXXX , XXXXXXX
#define _________________NAVI_R2___________________ XXXXXXX , KC_LCTL , XXXXXXX , XXXXXXX , XXXXXXX
#define _________________NAVI_R3___________________ XXXXXXX , XXXXXXX , XXXXXXX , XXXXXXX , XXXXXXX

View File

@ -0,0 +1,25 @@
SRC += tap_tog.c
SRC += issmirnov.c
# https://www.reddit.com/r/olkb/comments/bmpgjm/programming_help/
# Should shave 2000 bytes
LINK_TIME_OPTIMIZATION_ENABLE = yes
# Enable debugging only when needed.
CONSOLE_ENABLE = yes # +400 bytes (hid_listen support)
# Enable combo keys for vim usage.
# https://github.com/qmk/qmk_firmware/blob/master/docs/feature_combo.md
COMBO_ENABLE = yes
# This allows the keyboard to tell the host OS that up to 248 keys are held down at once
NKRO_ENABLE = no # note: also needs FORCE_NKRO in config.h
# Disable unused features to save on space
# https://thomasbaart.nl/2018/12/01/reducing-firmware-size-in-qmk/
MOUSEKEY_ENABLE = no # 2000 bytes
BOOTMAGIC_ENABLE = no
COMMAND_ENABLE = no # https://beta.docs.qmk.fm/features/feature_command
UNICODE_ENABLE = no # Unicode
SWAP_HANDS_ENABLE = no # Allow swapping hands of keyboard

View File

@ -0,0 +1,52 @@
#include QMK_KEYBOARD_H
#include "tap_tog.h"
bool tap_tog_layer_other_key_pressed = false;
bool tap_tog_layer_toggled_on = false;
uint8_t tap_tog_count = 0;
void process_tap_tog(uint8_t layer, keyrecord_t *record) {
tap_tog_count++;
// press
if (record->event.pressed) {
// TTL has already been pressed and we are toggled into that layer
// so now we need to leave
if(tap_tog_layer_toggled_on) {
layer_clear();
tap_tog_layer_toggled_on = false;
}
// this means we're in our default layer
// so switch the layer immediately
// whether we'll switch back when it's released depends on if a button gets pressed while this is held down
else {
// switch layer
layer_on(layer);
tap_tog_layer_other_key_pressed = false; // if this becomes true before it gets released, it will act as a held modifier
}
}
// release
else {
// if it was used as a held modifier (like traditional shift)
if(tap_tog_layer_other_key_pressed) {
// switch layer back
layer_clear();
}
// if it was used as a toggle button
else {
// next time, it will turn layer off
tap_tog_layer_toggled_on = true;
// If it's been tapped twice, reset the toggle flag.
// Otherwise, we get stuck oscillating between this code block and the
// pressed && TTL_toggled_on block.
if (tap_tog_count >= 4 ) {
tap_tog_count = 0;
tap_tog_layer_toggled_on = false;
}
}
}
}

View File

@ -0,0 +1,10 @@
#pragma once
#include "issmirnov.h"
extern bool tap_tog_layer_other_key_pressed; // set to true if any key pressed while TAP_TOG_LAYER held down
extern bool tap_tog_layer_toggled_on; // will become true if no keys are pressed while TTL held down
extern uint8_t tap_tog_count; // number of presses on TAP_TOG_LAYER button.
// Tap dance analog with momentary toggle when held, switch when tapped
void process_tap_tog(uint8_t layer, keyrecord_t *record);