Merge remote-tracking branch 'upstream/master'

this merge is necessary,
This commit is contained in:
Xyverz 2016-08-17 23:53:56 -07:00
commit 385b827c85
27 changed files with 1619 additions and 112 deletions

View File

@ -198,6 +198,11 @@ ifeq ($(strip $(AUDIO_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/audio/luts.c
endif
ifeq ($(strip $(UCIS_ENABLE)), yes)
OPT_DEFS += -DUCIS_ENABLE
UNICODE_ENABLE = yes
endif
ifeq ($(strip $(UNICODE_ENABLE)), yes)
OPT_DEFS += -DUNICODE_ENABLE
SRC += $(QUANTUM_DIR)/process_keycode/process_unicode.c
@ -273,4 +278,4 @@ BUILD_DATE := $(shell date +"%Y-%m-%d-%H:%M:%S")
OPT_DEFS += -DQMK_KEYBOARD=\"$(KEYBOARD)\" -DQMK_KEYMAP=\"$(KEYMAP)\"
$(shell echo '#define QMK_VERSION "$(GIT_VERSION)"' > $(QUANTUM_PATH)/version.h)
$(shell echo '#define QMK_BUILDDATE "$(BUILD_DATE)"' >> $(QUANTUM_PATH)/version.h)
$(shell echo '#define QMK_BUILDDATE "$(BUILD_DATE)"' >> $(QUANTUM_PATH)/version.h)

View File

@ -853,7 +853,7 @@ void ang_tap_dance_ta_reset (qk_tap_dance_state_t *state, void *user_data) {
td_ta->finished_once = false;
}
const qk_tap_dance_action_t tap_dance_actions[] = {
qk_tap_dance_action_t tap_dance_actions[] = {
[CT_CLN] = ACTION_TAP_DANCE_FN_ADVANCED (NULL, ang_tap_dance_cln_finished, ang_tap_dance_cln_reset)
,[CT_MNS] = ACTION_TAP_DANCE_FN_ADVANCED (NULL, ang_tap_dance_mns_finished, ang_tap_dance_mns_reset)
,[CT_TA] = {

View File

@ -0,0 +1,25 @@
# Build Options
# change to "no" to disable the options, or define them in the makefile.mk in
# the appropriate keymap folder that will get included automatically
#
BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
MOUSEKEY_ENABLE = no # Mouse keys(+4700)
EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
CONSOLE_ENABLE = no # Console for debug(+400)
COMMAND_ENABLE = yes # Commands for debug and configuration
NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
MIDI_ENABLE = no # MIDI controls
AUDIO_ENABLE = no # Audio output on port C6
UNICODE_ENABLE = no # Unicode
BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
TAP_DANCE_ENABLE = yes # Enables the double-tap functionality of keys
# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
ifndef QUANTUM_DIR
include ../../../../Makefile
endif

View File

@ -0,0 +1,44 @@
##Design goals:
1. Arrow keys always available.
2. As close to a to my US layout 107-key QWERTY keyboard as I could manage, (i.e. as few arbitrary decisions as possible).
3. Togglable DVORAK keyboard.
4. most frequently used things in the easiest to reach places.
5. Ability to game on it, just for fun.
My layout differs from most in the placement the ARROW keys, `ESC`, VOL keys, use of double-tap `CAPS`, and the GAME LOCK function.
I put the layer buttons in the usual spots. I originally wanted only function/symbols layer, but that proved detrimental. I use some timed press actions to save some space, but this has been accounted for, (see GAME LOCK below). I'm not fully satisfied with the current product (see NOTES below), so it may change in the future.
##Effective layers:
* Default later is obviously your letters and modifiers.
* Lower layer [NUMBER] is your numbers and punctuation.
* Upper layer [ACTION] is your symbols and actions.
* Function layer is the infrequently used function keys, layout toggle, game lock, and reset.
There is also a toggle for the DVORAK/QWERTY layers, but in normal typing this is not of concern.
###Special keys:
* `RSHFT` and `ENTER` are combined. Tap once for `ENTER` and hold for `RSHFT`. `ENTER` will be registered on release if released within 200 ms, else `RSHFT` is registered starting at 201 ms until release.
* If for some reason, this interferes with the normal usage of the `ENTER` key in any way, (some problem that may never happen), I have added a regular non-modified `ENTER` key on the same key in the [ACTION] layer.
* `LSHFT` and `CAPS` are also combined. The key works like a normal `LSHFT` unless double-tapped, in which case it counts as `CAPS`. This functionality unfortunately delays all key presses by at most 200 ms, but I have added ways to disable this both temporarily or permanently, described below.
* A failsafe `CAPS` key is on the same key in the [ACTION] layer.
* There are `UNDO`, `CUT`, `COPY`, and `PASTE` keys. This was intended to be a universal way to use these commands since in macOS cut is `⌘ + C` but in Windows it is `⌃ + C`. Unfortunately these special keys only work in Windows. ¯\\\_(ツ)\_/¯
##Game lock:
**TL;DR** the game lock toggle disables the double-tap `CAPS`, and disables `GUI` keys (WINDOWS key).
I wished for this keyboard to be fully usable in the most demanding of games. The most demanding game I know of is ARMA 3 which has a binding to practically every individual key of a 107-key keyboard. This means I need to have pretty much every key possible somewhere. I also wanted the keyboard to be responsive in games for every critical keypress. This means having a way to disable features that introduce an inherent delay to registering keys, such as double-tap.
I do not expect to see this used by the pros, but I enjoyed making it. As for use in ARMA 3, I got a little ways into the APEX campaign, but I found a few flaws. For Example, I cannot enable my HUD GPS since that requires `RCTRL`+`M` but `RCTRL` is not bound. The obvious fix is to rebind the action to a new key, but I still take this as a shortcoming of my layout.
###If you wish to disable double-tap
####Disable it temporarily
Turn on the game lock. While on, it registers as normal `LSHFT` and has no delay. Whether in game mode or not, `CAPS` is on the same key in the [ACTION] layer.
####Disable it permanently
Open the `Makefile` and set `TAP_DANCE_ENABLE = no`. I wrote the layout to compensate for this change, and no further changes to the code should be necessary. Whether or not it's disabled, `CAPS` is on the same key in the [ACTION] layer.
##Notes:
* `ALT` and `GUI` are reversed compared to the normal US layout. I will also be using my Planck on my mac, and that's the standard in the Apple ecosystem. I may add a special compiler flag in the future to swap the two.
* The DVORAK `Z` key is to the right of the `S` key instead of under it as part of a compromise I made to keep the ARROW keys available on the default layer. I prioritize the ARROW keys, so the DVORAK layout is the one to suffer.
* I also support the little tones that the default Planck layout features, identical to them too, (minus those for layouts I don't support). To enable it, open the `Makefile` and set `AUDIO_ENABLE = yes`.

View File

@ -0,0 +1,91 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.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/>.
*/
#ifndef CONFIG_H
#define CONFIG_H
#include "config_common.h"
/* Tap-dance interval definition */
#define TAPPING_TERM 200
/* USB Device descriptor parameter */
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x6060
#define MANUFACTURER Ortholinear Keyboards
#define PRODUCT The Planck Keyboard
#define DESCRIPTION A compact ortholinear keyboard
/* key matrix size */
#define MATRIX_ROWS 4
#define MATRIX_COLS 12
/* Planck PCB default pin-out */
#define MATRIX_ROW_PINS { D0, D5, B5, B6 }
#define MATRIX_COL_PINS { F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 }
#define UNUSED_PINS
#define BACKLIGHT_PIN B7
/* COL2ROW or ROW2COL */
#define DIODE_DIRECTION COL2ROW
/* define if matrix has ghost */
//#define MATRIX_HAS_GHOST
/* number of backlight levels */
#define BACKLIGHT_LEVELS 3
/* Set 0 if debouncing isn't needed */
#define DEBOUNCING_DELAY 5
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */
#define LOCKING_RESYNC_ENABLE
/* key combination for command */
#define IS_COMMAND() ( \
keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
)
/*
* Feature disable options
* These options are also useful to firmware size reduction.
*/
/* disable debug print */
//#define NO_DEBUG
/* disable print */
//#define NO_PRINT
/* disable action features */
//#define NO_ACTION_LAYER
//#define NO_ACTION_TAPPING
//#define NO_ACTION_ONESHOT
//#define NO_ACTION_MACRO
//#define NO_ACTION_FUNCTION
#ifdef SUBPROJECT_rev3
#include "rev3/config.h"
#endif
#ifdef SUBPROJECT_rev4
#include "rev4/config.h"
#endif
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

View File

@ -0,0 +1,258 @@
// Layout picture at http://www.keyboard-layout-editor.com/#/gists/125febfad6960add078e6f14256539b6
#include "planck.h"
#include "action_layer.h"
#ifdef AUDIO_ENABLE
#include "audio.h"
#endif
#include "eeconfig.h"
extern keymap_config_t keymap_config;
// 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.
#define _QWERTY 0
#define _DVORAK 1
#define _LOCKED 2
#define _NUMBER 3
#define _ACTION 4
#define _FUNCTN 5
enum planck_keycodes {
QWERTY = SAFE_RANGE,
DVORAK,
NUMBER,
ACTION
};
// Key code names
#define SFT_ENT FUNC(0) // Tap for enter, hold for right shift
#define LOCK FUNC(1)
#define KC_PSTE KC_PASTE
#define _______ KC_TRNS
#define XXXXXXX KC_NO
#ifdef TAP_DANCE_ENABLE
#define SFT_CAP TD(0) // Left shift, double tap for caps
#endif
#ifndef TAP_DANCE_ENABLE
#define SFT_CAP KC_LSFT // Regular left shift
#endif
// Tap Dance Definitions
#ifdef TAP_DANCE_ENABLE
const qk_tap_dance_action_t tap_dance_actions[] = {
[0] = ACTION_TAP_DANCE_DOUBLE(KC_LSFT, KC_CAPS)
};
#endif
// Function definitions
const uint16_t PROGMEM fn_actions[] = {
[0] = ACTION_MODS_TAP_KEY(MOD_RSFT, KC_ENT),
[1] = ACTION_LAYER_TOGGLE(_LOCKED)
};
// Layout definitions
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* QWERTY
* ,-----------------------------------------------------------------------------------.
* | Esc | Q | W | E | R | T | Y | U | I | O | P | BKSP |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | Tab | A | S | D | F | G | H | J | K | L | ; | ' |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* |*Shift| Z | X | C | V | B | N | M | , | . | Up |SftEnt|
* |------+------+------+------+------+-------------+------+------+------+------+------|
* | Ctrl | Alt | Cmd | Vol- | ACTN | Space | NUMS | Vol+ | Left | Down | Left |
* `-----------------------------------------------------------------------------------'
*/
[_QWERTY] = {
{KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
{KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
{SFT_CAP, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_UP, SFT_ENT},
{KC_LCTL, KC_LALT, KC_LGUI, KC_VOLD, ACTION, KC_SPC, KC_SPC, NUMBER, KC_VOLU, KC_LEFT, KC_DOWN, KC_RGHT}
},
/* DVORAK
* ,-----------------------------------------------------------------------------------.
* | | ' | , | . | P | Y | F | G | C | R | L | |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | | A | O | E | U | I | D | H | T | N | S | Z |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | | ; | Q | J | K | X | B | M | W | V | | |
* |------+------+------+------+------+-------------+------+------+------+------+------|
* | | | | | | | | | | | |
* `-----------------------------------------------------------------------------------'
*/
[_DVORAK] = {
{_______, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, _______},
{_______, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_Z },
{_______, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, _______, _______},
{_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______}
},
/* LOCK
* ,-----------------------------------------------------------------------------------.
* | | | | | | | | | | | | |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | | | | | | | | | | | | |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | Shift| | | | | | | | | | | |
* |------+------+------+------+------+-------------+------+------+------+------+------|
* | | | NULL | | | | | | | | |
* `-----------------------------------------------------------------------------------'
*/
[_LOCKED] = {
{_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
{_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
{KC_LSFT, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
{_______, _______, XXXXXXX, _______, _______, _______, _______, _______, _______, _______, _______, _______}
},
/* NUMBERS
* ,-----------------------------------------------------------------------------------.
* | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | | ~ | NULL | NULL | NULL | | | _ | + | { | } | ? | / |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | | ` | NULL | NULL | NULL | \ | - | = | [ | ] | | |
* |------+------+------+------+------+-------------+------+------+------+------+------|
* | | | | | | NULL | | | | | |
* `-----------------------------------------------------------------------------------'
*/
[_NUMBER] = {
{_______, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, _______},
{_______, KC_TILD, XXXXXXX, XXXXXXX, XXXXXXX, KC_PIPE, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_QUES, KC_SLSH},
{_______, KC_GRV, XXXXXXX, XXXXXXX, XXXXXXX, KC_BSLS, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, _______, _______},
{_______, _______, _______, _______, _______, XXXXXXX, XXXXXXX, _______, _______, _______, _______, _______}
},
/* ACTIONS
* ,-----------------------------------------------------------------------------------.
* | | ! | @ | # | $ | % | ^ | & | * | ( | ) | Del |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | CAPS | Undo | Cut | Copy | Paste| NULL | NULL | NULL | NULL | NULL | PgUp | Enter|
* |------+------+------+------+------+-------------+------+------+------+------+------|
* | | | | Mute | | NULL | | NULL | Home | PgDn | End |
* `-----------------------------------------------------------------------------------'
*/
[_ACTION] = {
{_______, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_DEL },
{_______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX},
{KC_CAPS, KC_UNDO, KC_CUT, KC_COPY, KC_PSTE, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_PGUP, KC_ENT },
{_______, _______, _______, KC_MUTE, _______, XXXXXXX, XXXXXXX, _______, XXXXXXX, KC_HOME, KC_PGDN, KC_END }
},
/* FUNCTIONS
* ,-----------------------------------------------------------------------------------.
* | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | F13 | F14 | F15 | F16 | F17 | F18 | F19 | F20 | F21 | F22 | F23 | F24 |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | NULL | NULL | NULL | NULL | NULL |QWERTY|DVORAK| NULL | NULL | NULL | NULL | NULL |
* |------+------+------+------+------+-------------+------+------+------+------+------|
* | Reset| NULL | Lock | NULL | | NULL | | NULL | NULL | NULL | NULL |
* `-----------------------------------------------------------------------------------'
*/
[_FUNCTN] = {
{KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12 },
{KC_F13, KC_F14, KC_F15, KC_F16, KC_F17, KC_F18, KC_F19, KC_F20, KC_F21, KC_F22, KC_F23, KC_F24 },
{XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, QWERTY, DVORAK, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX},
{RESET, XXXXXXX, LOCK, XXXXXXX, _______, XXXXXXX, XXXXXXX, _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX}
}
};
#ifdef AUDIO_ENABLE
float tone_startup[][2] = SONG(STARTUP_SOUND);
float tone_qwerty[][2] = SONG(QWERTY_SOUND);
float tone_dvorak[][2] = SONG(DVORAK_SOUND);
float music_scale[][2] = SONG(MUSIC_SCALE_SOUND);
float tone_goodbye[][2] = SONG(GOODBYE_SOUND);
#endif
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case QWERTY:
if (record->event.pressed) {
if (IS_LAYER_ON(_DVORAK)) {
#ifdef AUDIO_ENABLE
PLAY_NOTE_ARRAY(tone_qwerty, false, 0);
#endif
layer_off(_DVORAK);
}
}
return false;
break;
case DVORAK:
if (record->event.pressed) {
if (!IS_LAYER_ON(_DVORAK)) {
#ifdef AUDIO_ENABLE
PLAY_NOTE_ARRAY(tone_dvorak, false, 0);
#endif
layer_on(_DVORAK);
}
}
return false;
break;
case NUMBER:
if (record->event.pressed) {
layer_on(_NUMBER);
update_tri_layer(_NUMBER, _ACTION, _FUNCTN);
} else {
layer_off(_NUMBER);
update_tri_layer(_NUMBER, _ACTION, _FUNCTN);
}
return false;
break;
case ACTION:
if (record->event.pressed) {
layer_on(_ACTION);
update_tri_layer(_NUMBER, _ACTION, _FUNCTN);
} else {
layer_off(_ACTION);
update_tri_layer(_NUMBER, _ACTION, _FUNCTN);
}
return false;
break;
}
return true;
}
void matrix_init_user(void) {
#ifdef AUDIO_ENABLE
startup_user();
#endif
}
#ifdef AUDIO_ENABLE
void startup_user()
{
_delay_ms(20); // gets rid of tick
PLAY_NOTE_ARRAY(tone_startup, false, 0);
}
void shutdown_user()
{
PLAY_NOTE_ARRAY(tone_goodbye, false, 0);
_delay_ms(150);
stop_all_notes();
}
void music_on_user(void)
{
music_scale_user();
}
void music_scale_user(void)
{
PLAY_NOTE_ARRAY(music_scale, false, 0);
}
#endif

View File

@ -0,0 +1,25 @@
# Build Options
# change to "no" to disable the options, or define them in the Makefile in
# the appropriate keymap folder that will get included automatically
#
BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
CONSOLE_ENABLE = no # Console for debug(+400)
COMMAND_ENABLE = yes # Commands for debug and configuration
NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
MIDI_ENABLE = no # MIDI controls
AUDIO_ENABLE = yes # Audio output on port C6
UNICODE_ENABLE = no # Unicode
BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
ifndef QUANTUM_DIR
include ../../../../Makefile
endif

View File

@ -0,0 +1,231 @@
// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
// this is the style you want to emulate.
#include "planck.h"
#include "action_layer.h"
#ifdef AUDIO_ENABLE
#include "audio.h"
#endif
#include "eeconfig.h"
extern keymap_config_t keymap_config;
// 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.
#define _QWERTY 0
#define _COLEMAK 1
#define _DVORAK 2
#define _LOWER 3
#define _RAISE 4
#define _PLOVER 5
#define _ADJUST 16
enum planck_keycodes {
QWERTY = SAFE_RANGE,
COLEMAK,
DVORAK,
PLOVER,
LOWER,
RAISE,
BACKLIT,
EXT_PLV
};
// Fillers to make layering more clear
#define _______ KC_TRNS
#define XXXXXXX KC_NO
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_QWERTY] = {
{KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_DEL, KC_Y, KC_U, KC_I, KC_O, KC_P },
{KC_LSFT, KC_A, KC_S, KC_D, KC_F, KC_G, KC_TAB, KC_H, KC_J, KC_K, KC_L, KC_SCLN},
{KC_LCTL, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_BSPC, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH},
{KC_LGUI, _______, _______, KC_LALT, LOWER, KC_SPC, KC_ENT, KC_SPC, RAISE, KC_RALT, _______, KC_RGUI}
},
[_COLEMAK] = {
{KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC},
{KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT},
{KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
{BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
},
[_DVORAK] = {
{KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPC},
{KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH},
{KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_ENT },
{BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
},
[_LOWER] = {
{KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, _______, KC_6, KC_7, KC_8, KC_9, KC_0},
{_______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, _______, KC_F6, KC_HOME, KC_PGDN, KC_PGUP, KC_END },
{_______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, _______, KC_F12, KC_PLUS, KC_PIPE, KC_LCBR, KC_RCBR},
{_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______}
},
[_RAISE] = {
{KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, _______, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN},
{_______, _______, _______, KC_QUOT, KC_MINS, _______, _______, _______, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT},
{_______, KC_TILD, KC_GRV, KC_PLUS, KC_EQL, KC_PIPE, _______, KC_BSLS, KC_LBRC, KC_RBRC, KC_LCBR, KC_RCBR},
{_______, _______, _______, _______, _______, _______, _______, _______, _______, KC_VOLD, KC_VOLU, KC_MPLY}
},
[_PLOVER] = {
{KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1 },
{XXXXXXX, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC},
{XXXXXXX, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
{EXT_PLV, XXXXXXX, XXXXXXX, KC_C, KC_V, XXXXXXX, XXXXXXX, KC_N, KC_M, XXXXXXX, XXXXXXX, XXXXXXX}
},
[_ADJUST] = {
{_______, RESET, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_DEL},
{_______, _______, _______, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, PLOVER, _______},
{_______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, _______},
{_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______}
}
};
#ifdef AUDIO_ENABLE
float tone_startup[][2] = SONG(STARTUP_SOUND);
float tone_qwerty[][2] = SONG(QWERTY_SOUND);
float tone_dvorak[][2] = SONG(DVORAK_SOUND);
float tone_colemak[][2] = SONG(COLEMAK_SOUND);
float tone_plover[][2] = SONG(PLOVER_SOUND);
float tone_plover_gb[][2] = SONG(PLOVER_GOODBYE_SOUND);
float music_scale[][2] = SONG(MUSIC_SCALE_SOUND);
float tone_goodbye[][2] = SONG(GOODBYE_SOUND);
#endif
void persistant_default_layer_set(uint16_t default_layer) {
eeconfig_update_default_layer(default_layer);
default_layer_set(default_layer);
}
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
case QWERTY:
if (record->event.pressed) {
#ifdef AUDIO_ENABLE
PLAY_NOTE_ARRAY(tone_qwerty, false, 0);
#endif
persistant_default_layer_set(1UL<<_QWERTY);
}
return false;
break;
case COLEMAK:
if (record->event.pressed) {
#ifdef AUDIO_ENABLE
PLAY_NOTE_ARRAY(tone_colemak, false, 0);
#endif
persistant_default_layer_set(1UL<<_COLEMAK);
}
return false;
break;
case DVORAK:
if (record->event.pressed) {
#ifdef AUDIO_ENABLE
PLAY_NOTE_ARRAY(tone_dvorak, false, 0);
#endif
persistant_default_layer_set(1UL<<_DVORAK);
}
return false;
break;
case LOWER:
if (record->event.pressed) {
layer_on(_LOWER);
update_tri_layer(_LOWER, _RAISE, _ADJUST);
} else {
layer_off(_LOWER);
update_tri_layer(_LOWER, _RAISE, _ADJUST);
}
return false;
break;
case RAISE:
if (record->event.pressed) {
layer_on(_RAISE);
update_tri_layer(_LOWER, _RAISE, _ADJUST);
} else {
layer_off(_RAISE);
update_tri_layer(_LOWER, _RAISE, _ADJUST);
}
return false;
break;
case BACKLIT:
if (record->event.pressed) {
register_code(KC_RSFT);
#ifdef BACKLIGHT_ENABLE
backlight_step();
#endif
} else {
unregister_code(KC_RSFT);
}
return false;
break;
case PLOVER:
if (record->event.pressed) {
#ifdef AUDIO_ENABLE
stop_all_notes();
PLAY_NOTE_ARRAY(tone_plover, false, 0);
#endif
layer_off(_RAISE);
layer_off(_LOWER);
layer_off(_ADJUST);
layer_on(_PLOVER);
if (!eeconfig_is_enabled()) {
eeconfig_init();
}
keymap_config.raw = eeconfig_read_keymap();
keymap_config.nkro = 1;
eeconfig_update_keymap(keymap_config.raw);
}
return false;
break;
case EXT_PLV:
if (record->event.pressed) {
#ifdef AUDIO_ENABLE
PLAY_NOTE_ARRAY(tone_plover_gb, false, 0);
#endif
layer_off(_PLOVER);
}
return false;
break;
}
return true;
}
void matrix_init_user(void) {
#ifdef AUDIO_ENABLE
startup_user();
#endif
}
#ifdef AUDIO_ENABLE
void startup_user()
{
_delay_ms(20); // gets rid of tick
PLAY_NOTE_ARRAY(tone_startup, false, 0);
}
void shutdown_user()
{
PLAY_NOTE_ARRAY(tone_goodbye, false, 0);
_delay_ms(150);
stop_all_notes();
}
void music_on_user(void)
{
music_scale_user();
}
void music_scale_user(void)
{
PLAY_NOTE_ARRAY(music_scale, false, 0);
}
#endif

View File

@ -0,0 +1,4 @@
# Split Layout
Inspired by TECK
[Layout](http://www.keyboard-layout-editor.com/##@_switchMount=cherry&switchBrand=gateron&switchType=KS-3-Tea&pcb:true%3B&@_c=%23e6e6e6&t=%23757575&a:7&fa@:5%3B%3B&=Esc&_a:4&fa@:5&:0&:0&:0&:0&:0&:0&:0&:0&:5%3B%3B&=%0A%0A!%0A1%0A%0A%0A%0A%0A%0AQ&=%0A%0A%2F@%0A2%0A%0A%0A%0A%0A%0AW&=%0A%0A%23%0A3%0A%0A%0A%0A%0A%0AE&=%0A%0A$%0A4%0A%0A%0A%0A%0A%0AR&=%0A%0A%25%0A5%0A%0A%0A%0A%0A%0AT&_c=%23e3b02d&a:7%3B&=Del&_c=%23e6e6e6&a:4%3B&=%0A%0A%5E%0A6%0A%0A%0A%0A%0A%0AY&=%0A%0A%2F&%0A7%0A%0A%0A%0A%0A%0AU&=%0A%0A*%0A8%0A%0A%0A%0A%0A%0AI&=%0A%0A(%0A9%0A%0A%0A%0A%0A%0AO&=%0A%0A)%0A0%0A%0A%0A%0A%0A%0AP%3B&@_a:7%3B&=Shift&_a:4%3B&=%0A%0A%0AF1%0A%0A%0A%0A%0A%0AA&=%0A%0A%0AF2%0A%0A%0A%0A%0A%0AS&=%0A%0A'%0AF3%0A%0A%0A%0A%0A%0AD&_c=%23e3b02d&n:true%3B&=%0A%0A-%0AF4%0A%0A%0A%0A%0A%0AF&_c=%23e6e6e6%3B&=%0A%0A%0AF5%0A%0A%0A%0A%0A%0AG&_c=%23e3b02d&a:7%3B&=Tab&_c=%23e6e6e6&a:4%3B&=%0A%0A%0AF6%0A%0A%0A%0A%0A%0AH&_c=%23e3b02d&n:true%3B&=%0A%0A%2F&larr%2F%3B%0AHom%0A%0A%0A%0A%0A%0AJ&_c=%23e6e6e6%3B&=%0A%0A%2F&darr%2F%3B%0APgD%0A%0A%0A%0A%0A%0AK&=%0A%0A%2F&uarr%2F%3B%0APgU%0A%0A%0A%0A%0A%0AL&=%0A%0A%2F&rarr%2F%3B%0AEnd%0A%0A%0A%0A%0A%0A%2F%3B%3B&@_a:7%3B&=Ctrl&_a:4%3B&=%0A%0A~%0AF7%0A%0A%0A%0A%0A%0AZ&=%0A%0A%60%0AF8%0A%0A%0A%0A%0A%0AX&=%0A%0A+%0AF9%0A%0A%0A%0A%0A%0AC&=%0A%0A%2F=%0AF10%0A%0A%0A%0A%0A%0AV&=%0A%0A%7C%0AF11%0A%0A%0A%0A%0A%0AB&_c=%23e3b02d&a:7%3B&=BSp&_c=%23e6e6e6&a:4%3B&=%0A%0A%5C%0AF12%0A%0A%0A%0A%0A%0AN&=%0A%0A%5B%0A%0A%0A%0A%0A%0A%0AM&=%0A%0A%5D%0A%0A%0A%0A%0A%0A%0A,&=%0A%0A%7B%0A%0A%0A%0A%0A%0A%0A.&=%0A%0A%7D%0A%0A%0A%0A%0A%0A%0A%2F%2F%3B&@_a:7%3B&=&=&=&=Alt&_c=%23e3b02d%3B&=%2F&dArr%2F%3B&_c=%23e6e6e6%3B&=spc&_c=%23e3b02d%3B&=%2F&crarr%2F%3B&_c=%23e6e6e6%3B&=spc&_c=%23e3b02d%3B&=%2F&uArr%2F%3B&_c=%23e6e6e6%3B&=Alt&=&=)

View File

@ -123,7 +123,7 @@ void music_scale_user(void)
}
const qk_tap_dance_action_t tap_dance_actions[] = {
qk_tap_dance_action_t tap_dance_actions[] = {
//Tap once for equal, twice for hyper + X (alfred lock)
[TD_EQ_LOCK] = ACTION_TAP_DANCE_DOUBLE(KC_EQL, HYPR(KC_X)),
//Tap once for minus, twice for time.heals.nothing

View File

@ -0,0 +1,3 @@
updatemerge.sh
clear_flash.hex
resetboard.sh

Binary file not shown.

After

Width:  |  Height:  |  Size: 775 KiB

View File

@ -0,0 +1,16 @@
BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
MOUSEKEY_ENABLE = no # Mouse keys(+4700)
EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
CONSOLE_ENABLE = yes # Console for debug(+400)
COMMAND_ENABLE = yes # Commands for debug and configuration
NKRO_ENABLE = yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
RGBLIGHT_ENABLE = yes # Enable keyboard underlight functionality (+4870)
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality (+1150)
MIDI_ENABLE = no # MIDI controls
AUDIO_ENABLE = no
UNICODE_ENABLE = no # Unicode
BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
ifndef QUANTUM_DIR
include ../../../../Makefile
endif

View File

@ -0,0 +1,42 @@
#!/bin/bash
# adjust for cpu
# -j 16 gave best result on a hyperthreaded quad core core i7
LIMIT=10
THREADS="-j 16"
KMAP=iso_split_rshift
echo "We need sudo later"
sudo ls 2>&1 /dev/null
function wait_bootloader {
echo "Waiting for Bootloader..."
local STARTTIME=$(date +"%s")
local REMIND=0
local EXEC=dfu-programmer
local TARGET=atmega32u4
while true
do
sudo $EXEC $TARGET get > /dev/null 2>&1
[ $? -eq 0 ] && break
ENDTIME=$(date +"%s")
DURATION=$(($ENDTIME-$STARTTIME))
if [ $REMIND -eq 0 -a $DURATION -gt $LIMIT ]
then
echo "Did you forget to press the reset button?"
REMIND=1
fi
sleep 1
done
}
make clean
make KEYMAP=${KMAP} ${THREADS}
if [[ $? -eq 0 ]]
then
echo "please trigger flashing!"
wait_bootloader
sudo make KEYMAP=${KMAP} dfu ${THREADS}
else
echo "make failed"
exit 77
fi

View File

@ -0,0 +1,27 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.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/>.
*/
#ifndef CONFIG_USER_H
#define CONFIG_USER_H
#include "../../config.h"
// only change
#undef RGB_DI_PIN
#define RGB_DI_PIN B2
#endif

View File

@ -0,0 +1,209 @@
// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
// this is the style you want to emulate.
#include "satan.h"
// TODO: replace your ugly german brckets with #defines
// 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.
#define _DEF 0
#define _SPC 1
#define _TAB 2
#define _SFX 3
// dual-role shortcuts
#define TABDUAL LT(_TAB, KC_TAB)
#define CAPSDUAL CTL_T(KC_ESC)
#define SPACEDUAL LT(_SPC, KC_SPACE)
#define ENTERDUAL CTL_T(KC_ENT)
// arrow cluster duality bottom right corner
#define ARRLEFT ALT_T(KC_LEFT)
#define ARRDOWN GUI_T(KC_DOWN)
#define ARRUP SFT_T(KC_UP)
#define ARRRIGHT CTL_T(KC_RIGHT)
// german brackets
#define GER_CUR_L RALT(KC_7) // [
#define GER_CUR_R RALT(KC_0) // ]
#define GER_PAR_L LSFT(KC_8) // (
#define GER_PAR_R LSFT(KC_9) // )
#define GER_ANG_L KC_NUBS // <
#define GER_ANG_R LSFT(KC_NUBS) // >
#define GER_BRC_L RALT(KC_8) // [
#define GER_BRC_R RALT(KC_9) // ]
// increase readability
#define _______ KC_TRNS
#define XXXXXXX KC_NO
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* Keymap _DEF: Default Layer
* ,-----------------------------------------------------------.
* |Grv| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp |
* |-----------------------------------------------------------|
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \ | Tab is Fn1
* |-----------------------------------------------------------|
* |Ctrl | A| S| D| F| G| H| J| K| L| ;| '| Return |
* |-----------------------------------------------------------|
* |Sft | < | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn2| RShift is UP
* |-----------------------------------------------------------|
* |Ctrl|Win |Alt | Space/Fn0 |Alt |Win |Menu|RCtl| Gui Menu, RCtrl is
* `-----------------------------------------------------------' LEFT DWN RIGHT
*/
[_DEF] = KEYMAP_ISO_SPLITRSHIFT(
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, \
TABDUAL, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, \
CAPSDUAL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, ENTERDUAL, \
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, TG(_SFX), ARRUP, \
KC_LCTL, KC_LGUI, KC_LALT, SPACEDUAL, KC_RALT, ARRLEFT, ARRDOWN, ARRRIGHT),
/* Keymap 1: F-and-vim Layer, modified with Space (by holding space)
* ,-----------------------------------------------------------.
* |PrSc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Delete|
* |-----------------------------------------------------------|
* | |Paus| Up| [ | ] | | | | ( | ) | | | | |
* |-----------------------------------------------------------|
* | |Lft|Dwn|Rgt| | |Left|Down|Right|Up| | | PLAY |
* |-----------------------------------------------------------|
* | | | | | < | > | |M0 | | | | | Vol+ | |
* |-----------------------------------------------------------|
* | | | | |Alt |Prev|Vol-|Next|
* `-----------------------------------------------------------'
*/
[_SPC] = KEYMAP_ISO_SPLITRSHIFT(
KC_PSCR, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, \
_______, KC_PAUS, KC_UP, GER_BRC_L, GER_BRC_R, _______, _______, GER_PAR_L, GER_PAR_R, _______, _______, _______, _______, _______, \
_______, KC_LEFT, KC_DOWN, KC_RIGHT, _______, _______, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, _______, _______, _______, KC_MPLY, \
_______, _______, _______, _______, GER_ANG_L, GER_ANG_R, KC_SPACE, M(0), _______, _______, _______, _______, _______, KC_VOLU, \
_______, _______, _______, _______, _______, KC_MPRV, KC_VOLD, KC_MNXT),
/* Keymap 2: Tab Layer w/ vim pageup, modified with Tab (by holding tab)
* ,-----------------------------------------------------------.
* |WAKE| | | | | | | | | | | | |Insert| TAB+GRC = WAKE
* |-----------------------------------------------------------|
* | | | | | | | | | { | } | | | | |
* |-----------------------------------------------------------|
* | | | | | | |Pos1|PgDn|PgUp|End| | |Retrn |
* |-----------------------------------------------------------|
* | | | | | | | |AF2| | | | | PgUp | |
* |-----------------------------------------------------------|
* | | | | |Alt |Pos1|PgDn|End |
* `-----------------------------------------------------------'
*/
[_TAB] = KEYMAP_ISO_SPLITRSHIFT(
KC_WAKE, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_INS, \
_______, _______, _______, _______, _______, _______, _______, GER_CUR_L, GER_CUR_R, _______, _______, _______, _______, _______, \
_______, _______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_PGUP, KC_END, _______, _______, _______, KC_ENT, \
_______, _______, _______, _______, _______, _______, _______, M(1), _______, _______, _______, _______, _______, KC_PGUP, \
_______, _______, _______, _______, _______, KC_HOME, KC_PGDN, KC_END),
/* Keymap 3: Split right shift Numpad toggle Layer (by tapping the split rshift key)
* ,-----------------------------------------------------------.
* |RSET| | | | | | | 7| 8| 9| | | |Backsp |
* |-----------------------------------------------------------|
* | | | | | | | | 4 | 5 | 6 | | | | \ |
* |-----------------------------------------------------------|
* | | L | L | | | | | 1 | 2 | 3 | | | Return |
* |-----------------------------------------------------------|
* | | | L | L | L | L | L | L | | 0 | | /| Up | | All "L"s represent
* |-----------------------------------------------------------| LED controlling
* |Ctrl|Win |Alt | |Alt |Left|Down|Right|
* `-----------------------------------------------------------'
*/
[_SFX] = KEYMAP_ISO_SPLITRSHIFT(
RESET, _______, _______, _______, _______, _______, _______, KC_7, KC_8, KC_9, _______, _______, _______, KC_BSPC, \
_______, _______, _______, _______, _______, _______, _______, KC_4, KC_5, KC_6, _______, _______, _______, KC_BSLS, \
_______, F(2), F(3), _______, _______, _______, _______, KC_1, KC_2, KC_3, _______, _______, XXXXXXX, KC_ENT, \
_______, F(4), F(5), F(6), F(7), F(8), F(9), _______, _______, KC_0, _______, KC_SLSH, _______, KC_UP, \
_______, _______, _______, _______, _______, KC_LEFT, KC_DOWN, KC_RGHT),
};
enum function_id {
LAUNCH,
RGBLED_TOGGLE,
RGBLED_STEP_MODE,
RGBLED_INCREASE_HUE,
RGBLED_DECREASE_HUE,
RGBLED_INCREASE_SAT,
RGBLED_DECREASE_SAT,
RGBLED_INCREASE_VAL,
RGBLED_DECREASE_VAL,
};
const uint16_t PROGMEM fn_actions[] = {
[1] = ACTION_FUNCTION(LAUNCH),
[2] = ACTION_FUNCTION(RGBLED_TOGGLE),
[3] = ACTION_FUNCTION(RGBLED_STEP_MODE),
[4] = ACTION_FUNCTION(RGBLED_INCREASE_HUE),
[5] = ACTION_FUNCTION(RGBLED_DECREASE_HUE),
[6] = ACTION_FUNCTION(RGBLED_INCREASE_SAT),
[7] = ACTION_FUNCTION(RGBLED_DECREASE_SAT),
[8] = ACTION_FUNCTION(RGBLED_INCREASE_VAL),
[9] = ACTION_FUNCTION(RGBLED_DECREASE_VAL),
[10] = ACTION_MODS_TAP_KEY(MOD_LCTL, KC_ENT),
};
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
// MACRODOWN only works in this function
switch(id) {
case 0:
return (record->event.pressed ?
MACRO( D(RALT), T(SPC), U(RALT), END )
:MACRO( END ));
break;
case 1:
return (record->event.pressed ?
MACRO( D(LALT), T(F2), U(LALT), END )
:MACRO( END ));
break;
}
return MACRO_NONE;
};
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) {
switch (id) {
case RGBLED_TOGGLE:
//led operations
if (record->event.pressed) {
rgblight_toggle();
}
break;
case RGBLED_INCREASE_HUE:
if (record->event.pressed) {
rgblight_increase_hue();
}
break;
case RGBLED_DECREASE_HUE:
if (record->event.pressed) {
rgblight_decrease_hue();
}
break;
case RGBLED_INCREASE_SAT:
if (record->event.pressed) {
rgblight_increase_sat();
}
break;
case RGBLED_DECREASE_SAT:
if (record->event.pressed) {
rgblight_decrease_sat();
}
break;
case RGBLED_INCREASE_VAL:
if (record->event.pressed) {
rgblight_increase_val();
}
break;
case RGBLED_DECREASE_VAL:
if (record->event.pressed) {
rgblight_decrease_val();
}
break;
case RGBLED_STEP_MODE:
if (record->event.pressed) {
rgblight_step();
}
break;
}
}

View File

@ -0,0 +1,36 @@
toneman77's Satan Layout
=====================
##Quantum MK Firmware
For the full Quantum feature list, see the parent readme.md.
* heavily modified ISO (!) layout with split right shift key
* spaceFn
* Dual-Role keys:
*
| Original key | when tapped | when held |
| ---------------- | ------------- | ------------- |
| Space | Space | layer change |
| Caps lock | Escape | Control |
| Tab | Tab | layer change |
| Enter | Enter | Control |
* Lockable layer for LED functions and numpad
* vim-style arrow keys on hjkl (spacefn layer)
* corresponding Home/PgDn/PgUp/End on hjkl (tab layer)
* bonus arrow keys in the bottom right corner on Alt/Win/Menu/rCtrl/Shift
* more bonus arrow keys on wasd (spacefn layer)
* media keys prev/next/play/vol+/vol- (spacefn layer)
* firmware bootloader button
* WS2812 RGB Underglow Support (not needed anymore to solder directly to the atmega)
* additional brackets that only work in german layout due to horrible placement
in the default qwertz layout
### Additional Credits
* Keymap has been based on TerryMathews' fork of Aqoush's fork of qmk-satan-rgb. [here](https://github.com/TerryMathews/qmk-satan-rgb/tree/master/keyboard/satan)
* nice visualization of the layers [here](http://www.keyboard-layout-editor.com/#/gists/aba4e4396459ede85bc66a22cee88e48)
* no-need-to-solder-on-chip picture:
![no need to solder directly on the chip anymore](LEDpinSatan.jpg)
* special thanks to /u/TerryMathews who suggested the pin PB2, so soldering
directly on the atmega is not needed anymore. Happened on [reddit](https://www.reddit.com/r/MechanicalKeyboards/comments/4ghq9z/photos_satan_rgb60_w1976/d2k5tra)

View File

@ -0,0 +1,4 @@
#!/bin/bash
sudo dfu-programmer atmega32u4 erase --force
sudo dfu-programmer atmega32u4 flash clear_flash.hex
sudo dfu-programmer atmega32u4 reset

View File

@ -62,6 +62,33 @@
{k40, k41, k42, KC_NO, KC_NO, k45, KC_NO, KC_NO, KC_NO, k49, k4a, k4b, k4c, k4d} \
}
/* ISO w/ split right shift key matrix layout
* ,-----------------------------------------------------------.
* | 00 |01| 02| 03| 04| 05| 06| 07| 08| 09| 0a| 0b| 0c| 0d |
* |-----------------------------------------------------------|
* | 10 | 11| 12| 13| 14| 15| 16| 17| 18| 19| 1a| 1b| 1c| 1d |
* |-----------------------------------------------------------|
* | 20 | 21| 22| 23| 24| 25| 26| 27| 28| 29| 2a| 2b| 2c|2d |
* |-----------------------------------------------------------|
* | 30 | 31| 32| 33| 34| 35| 36| 37| 38| 39| 3a| 3b| 3c| 3d |
* |-----------------------------------------------------------|
* | 40 | 41 | 42 | 45 | 4a | 4b | 4c | 4d |
* `-----------------------------------------------------------'
*/
#define KEYMAP_ISO_SPLITRSHIFT( \
k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d, \
k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, k1d, \
k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, k2c, k2d, \
k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, k3c, k3d, \
k40, k41, k42, k45, k4a, k4b, k4c, k4d \
) \
{ \
{k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d}, \
{k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, k1d}, \
{k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, k2c, k2d}, \
{k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, k3c, k3d}, \
{k40, k41, k42, KC_NO, KC_NO, k45, KC_NO, KC_NO, KC_NO, KC_NO, k4a, k4b, k4c, k4d} \
}
void matrix_init_user(void);
void matrix_scan_user(void);

226
quantum/dynamic_macro.h Normal file
View File

@ -0,0 +1,226 @@
/* Author: Wojciech Siewierski < wojciech dot siewierski at onet dot pl > */
#ifndef DYNAMIC_MACROS_H
#define DYNAMIC_MACROS_H
#include "action_layer.h"
#ifndef DYNAMIC_MACRO_SIZE
/* May be overridden with a custom value. Be aware that the effective
* macro length is half of this value: each keypress is recorded twice
* because of the down-event and up-event. This is not a bug, it's the
* intended behavior. */
#define DYNAMIC_MACRO_SIZE 256
#endif
/* DYNAMIC_MACRO_RANGE must be set as the last element of user's
* "planck_keycodes" enum prior to including this header. This allows
* us to 'extend' it.
*/
enum dynamic_macro_keycodes {
DYN_REC_START1 = DYNAMIC_MACRO_RANGE,
DYN_REC_START2,
DYN_MACRO_PLAY1,
DYN_MACRO_PLAY2,
};
/* Blink the LEDs to notify the user about some event. */
void dynamic_macro_led_blink(void)
{
backlight_toggle();
_delay_ms(100);
backlight_toggle();
}
/**
* Start recording of the dynamic macro.
*
* @param[out] macro_pointer The new macro buffer iterator.
* @param[in] macro_buffer The macro buffer used to initialize macro_pointer.
*/
void dynamic_macro_record_start(
keyrecord_t **macro_pointer, keyrecord_t *macro_buffer)
{
dynamic_macro_led_blink();
clear_keyboard();
layer_clear();
*macro_pointer = macro_buffer;
}
/**
* Play the dynamic macro.
*
* @param macro_buffer[in] The beginning of the macro buffer being played.
* @param macro_end[in] The element after the last macro buffer element.
* @param direction[in] Either +1 or -1, which way to iterate the buffer.
*/
void dynamic_macro_play(
keyrecord_t *macro_buffer, keyrecord_t *macro_end, int8_t direction)
{
uint32_t saved_layer_state = layer_state;
clear_keyboard();
layer_clear();
while (macro_buffer != macro_end) {
process_record(macro_buffer);
macro_buffer += direction;
}
clear_keyboard();
layer_state = saved_layer_state;
}
/**
* Record a single key in a dynamic macro.
*
* @param macro_pointer[in,out] The current buffer position.
* @param macro_end2[in] The end of the other macro which shouldn't be overwritten.
* @param direction[in] Either +1 or -1, which way to iterate the buffer.
* @param record[in] The current keypress.
*/
void dynamic_macro_record_key(
keyrecord_t **macro_pointer,
keyrecord_t *macro_end2,
int8_t direction,
keyrecord_t *record)
{
if (*macro_pointer + direction != macro_end2) {
**macro_pointer = *record;
*macro_pointer += direction;
} else {
/* Notify about the end of buffer. The blinks are paired
* because they should happen on both down and up events. */
backlight_toggle();
}
}
/**
* End recording of the dynamic macro. Essentially just update the
* pointer to the end of the macro.
*/
void dynamic_macro_record_end(keyrecord_t *macro_pointer, keyrecord_t **macro_end)
{
dynamic_macro_led_blink();
*macro_end = macro_pointer;
}
/* Handle the key events related to the dynamic macros. Should be
* called from process_record_user() like this:
*
* bool process_record_user(uint16_t keycode, keyrecord_t *record) {
* if (!process_record_dynamic_macro(keycode, record)) {
* return false;
* }
* <...THE REST OF THE FUNCTION...>
* }
*/
bool process_record_dynamic_macro(uint16_t keycode, keyrecord_t *record)
{
/* Both macros use the same buffer but read/write on different
* ends of it.
*
* Macro1 is written left-to-right starting from the beginning of
* the buffer.
*
* Macro2 is written right-to-left starting from the end of the
* buffer.
*
* &macro_buffer macro_end
* v v
* +------------------------------------------------------------+
* |>>>>>> MACRO1 >>>>>>| |<<<<<<<<<<<<< MACRO2 <<<<<<<<<<<<<|
* +------------------------------------------------------------+
* ^ ^
* r_macro_end r_macro_buffer
*
* During the recording when one macro encounters the end of the
* other macro, the recording is stopped. Apart from this, there
* are no arbitrary limits for the macros' length in relation to
* each other: for example one can either have two medium sized
* macros or one long macro and one short macro. Or even one empty
* and one using the whole buffer.
*/
static keyrecord_t macro_buffer[DYNAMIC_MACRO_SIZE];
/* Pointer to the first buffer element after the first macro.
* Initially points to the very beginning of the buffer since the
* macro is empty. */
static keyrecord_t *macro_end = macro_buffer;
/* The other end of the macro buffer. Serves as the beginning of
* the second macro. */
static keyrecord_t *const r_macro_buffer = macro_buffer + DYNAMIC_MACRO_SIZE - 1;
/* Like macro_end but for the second macro. */
static keyrecord_t *r_macro_end = r_macro_buffer;
/* A persistent pointer to the current macro position (iterator)
* used during the recording. */
static keyrecord_t *macro_pointer = NULL;
/* 0 - no macro is being recorded right now
* 1,2 - either macro 1 or 2 is being recorded */
static uint8_t macro_id = 0;
if (macro_id == 0) {
/* No macro recording in progress. */
if (!record->event.pressed) {
switch (keycode) {
case DYN_REC_START1:
dynamic_macro_record_start(&macro_pointer, macro_buffer);
macro_id = 1;
return false;
case DYN_REC_START2:
dynamic_macro_record_start(&macro_pointer, r_macro_buffer);
macro_id = 2;
return false;
case DYN_MACRO_PLAY1:
dynamic_macro_play(macro_buffer, macro_end, +1);
return false;
case DYN_MACRO_PLAY2:
dynamic_macro_play(r_macro_buffer, r_macro_end, -1);
return false;
}
}
} else {
/* A macro is being recorded right now. */
switch (keycode) {
case MO(_DYN):
/* Use the layer key used to access the macro recording as
* a stop button. */
if (record->event.pressed) { /* Ignore the initial release
* just after the recoding
* starts. */
switch (macro_id) {
case 1:
dynamic_macro_record_end(macro_pointer, &macro_end);
break;
case 2:
dynamic_macro_record_end(macro_pointer, &r_macro_end);
break;
}
macro_id = 0;
}
return false;
default:
/* Store the key in the macro buffer and process it normally. */
switch (macro_id) {
case 1:
dynamic_macro_record_key(&macro_pointer, r_macro_end, +1, record);
break;
case 2:
dynamic_macro_record_key(&macro_pointer, macro_end, -1, record);
break;
}
return true;
break;
}
}
return true;
}
#endif

View File

@ -1,18 +1,8 @@
#include "quantum.h"
#include "action_tapping.h"
static qk_tap_dance_state_t qk_tap_dance_state;
bool td_debug_enable = false;
#if CONSOLE_ENABLE
#define td_debug(s) if (td_debug_enable) \
{ \
xprintf ("D:tap_dance:%s:%s = { keycode = %d, count = %d, active = %d, pressed = %d }\n", __FUNCTION__, s, \
qk_tap_dance_state.keycode, qk_tap_dance_state.count, \
qk_tap_dance_state.active, qk_tap_dance_state.pressed); \
}
#else
#define td_debug(s)
#endif
static uint16_t last_td;
static int8_t highest_td = -1;
void qk_tap_dance_pair_finished (qk_tap_dance_state_t *state, void *user_data) {
qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
@ -35,98 +25,110 @@ void qk_tap_dance_pair_reset (qk_tap_dance_state_t *state, void *user_data) {
}
static inline void _process_tap_dance_action_fn (qk_tap_dance_state_t *state,
void *user_data,
qk_tap_dance_user_fn_t fn)
void *user_data,
qk_tap_dance_user_fn_t fn)
{
if (fn) {
fn(state, user_data);
}
}
static inline void process_tap_dance_action_on_each_tap (qk_tap_dance_action_t action)
static inline void process_tap_dance_action_on_each_tap (qk_tap_dance_action_t *action)
{
td_debug("trigger");
_process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_each_tap);
_process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_each_tap);
}
static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_action_t action)
static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_action_t *action)
{
td_debug("trigger");
_process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_dance_finished);
if (action->state.finished)
return;
action->state.finished = true;
_process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_dance_finished);
}
static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t action)
static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t *action)
{
td_debug("trigger")
_process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_reset);
_process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_reset);
}
bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
bool r = true;
uint16_t idx = keycode - QK_TAP_DANCE;
qk_tap_dance_action_t action;
qk_tap_dance_action_t *action;
if (last_td && last_td != keycode) {
(&tap_dance_actions[last_td - QK_TAP_DANCE])->state.interrupted = true;
}
switch(keycode) {
case QK_TAP_DANCE ... QK_TAP_DANCE_MAX:
action = tap_dance_actions[idx];
if ((int16_t)idx > highest_td)
highest_td = idx;
action = &tap_dance_actions[idx];
process_tap_dance_action_on_each_tap (action);
if (qk_tap_dance_state.keycode && qk_tap_dance_state.keycode != keycode) {
process_tap_dance_action_on_dance_finished (action);
} else if (qk_tap_dance_state.active && qk_tap_dance_state.pressed) {
reset_tap_dance (&qk_tap_dance_state);
} else {
r = false;
}
qk_tap_dance_state.active = true;
qk_tap_dance_state.pressed = record->event.pressed;
action->state.keycode = keycode;
action->state.pressed = record->event.pressed;
if (record->event.pressed) {
qk_tap_dance_state.keycode = keycode;
qk_tap_dance_state.timer = timer_read ();
qk_tap_dance_state.count++;
action->state.count++;
action->state.timer = timer_read();
if (last_td && last_td != keycode) {
qk_tap_dance_action_t *paction = &tap_dance_actions[last_td - QK_TAP_DANCE];
paction->state.interrupted = true;
process_tap_dance_action_on_dance_finished (paction);
reset_tap_dance (&paction->state);
}
}
last_td = keycode;
break;
default:
if (qk_tap_dance_state.keycode) {
// if we are here, the tap dance was interrupted by a different key
idx = qk_tap_dance_state.keycode - QK_TAP_DANCE;
action = tap_dance_actions[idx];
if (!record->event.pressed)
return true;
process_tap_dance_action_on_each_tap (action);
if (highest_td == -1)
return true;
for (int i = 0; i <= highest_td; i++) {
action = &tap_dance_actions[i];
if (action->state.count == 0)
continue;
action->state.interrupted = true;
process_tap_dance_action_on_dance_finished (action);
reset_tap_dance (&qk_tap_dance_state);
qk_tap_dance_state.active = false;
reset_tap_dance (&action->state);
}
break;
}
return r;
return true;
}
void matrix_scan_tap_dance () {
if (qk_tap_dance_state.active && timer_elapsed (qk_tap_dance_state.timer) > TAPPING_TERM) {
// if we are here, the tap dance was timed out
uint16_t idx = qk_tap_dance_state.keycode - QK_TAP_DANCE;
qk_tap_dance_action_t action = tap_dance_actions[idx];
if (highest_td == -1)
return;
process_tap_dance_action_on_dance_finished (action);
reset_tap_dance (&qk_tap_dance_state);
for (int i = 0; i <= highest_td; i++) {
qk_tap_dance_action_t *action = &tap_dance_actions[i];
if (action->state.count && timer_elapsed (action->state.timer) > TAPPING_TERM) {
process_tap_dance_action_on_dance_finished (action);
reset_tap_dance (&action->state);
}
}
}
void reset_tap_dance (qk_tap_dance_state_t *state) {
uint16_t idx = state->keycode - QK_TAP_DANCE;
qk_tap_dance_action_t action;
qk_tap_dance_action_t *action;
if (state->pressed)
return;
action = tap_dance_actions[idx];
action = &tap_dance_actions[state->keycode - QK_TAP_DANCE];
process_tap_dance_action_on_reset (action);
state->keycode = 0;
state->count = 0;
state->active = false;
state->interrupted = false;
state->finished = false;
last_td = 0;
}

View File

@ -11,8 +11,9 @@ typedef struct
uint8_t count;
uint16_t keycode;
uint16_t timer;
bool active:1;
bool pressed:1;
bool interrupted;
bool pressed;
bool finished;
} qk_tap_dance_state_t;
#define TD(n) (QK_TAP_DANCE + n)
@ -26,6 +27,7 @@ typedef struct
qk_tap_dance_user_fn_t on_dance_finished;
qk_tap_dance_user_fn_t on_reset;
} fn;
qk_tap_dance_state_t state;
void *user_data;
} qk_tap_dance_action_t;
@ -48,8 +50,7 @@ typedef struct
.fn = { user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_reset } \
}
extern const qk_tap_dance_action_t tap_dance_actions[];
extern bool td_debug_enable;
extern qk_tap_dance_action_t tap_dance_actions[];
/* To be used internally */

View File

@ -18,40 +18,187 @@ void set_unicode_input_mode(uint8_t os_target)
input_mode = os_target;
}
void unicode_input_start (void) {
switch(input_mode) {
case UC_OSX:
register_code(KC_LALT);
break;
case UC_LNX:
register_code(KC_LCTL);
register_code(KC_LSFT);
register_code(KC_U);
unregister_code(KC_U);
unregister_code(KC_LSFT);
unregister_code(KC_LCTL);
break;
case UC_WIN:
register_code(KC_LALT);
register_code(KC_PPLS);
unregister_code(KC_PPLS);
break;
}
wait_ms(UNICODE_TYPE_DELAY);
}
void unicode_input_finish (void) {
switch(input_mode) {
case UC_OSX:
case UC_WIN:
unregister_code(KC_LALT);
break;
case UC_LNX:
register_code(KC_SPC);
unregister_code(KC_SPC);
break;
}
}
void register_hex(uint16_t hex) {
for(int i = 3; i >= 0; i--) {
uint8_t digit = ((hex >> (i*4)) & 0xF);
register_code(hex_to_keycode(digit));
unregister_code(hex_to_keycode(digit));
}
}
bool process_unicode(uint16_t keycode, keyrecord_t *record) {
if (keycode > QK_UNICODE && record->event.pressed) {
uint16_t unicode = keycode & 0x7FFF;
switch(input_mode) {
case UC_OSX:
register_code(KC_LALT);
break;
case UC_LNX:
register_code(KC_LCTL);
register_code(KC_LSFT);
register_code(KC_U);
unregister_code(KC_U);
break;
case UC_WIN:
register_code(KC_LALT);
register_code(KC_PPLS);
unregister_code(KC_PPLS);
break;
}
for(int i = 3; i >= 0; i--) {
uint8_t digit = ((unicode >> (i*4)) & 0xF);
register_code(hex_to_keycode(digit));
unregister_code(hex_to_keycode(digit));
}
switch(input_mode) {
case UC_OSX:
case UC_WIN:
unregister_code(KC_LALT);
break;
case UC_LNX:
unregister_code(KC_LCTL);
unregister_code(KC_LSFT);
break;
}
unicode_input_start();
register_hex(unicode);
unicode_input_finish();
}
return true;
}
}
#ifdef UCIS_ENABLE
void qk_ucis_start(void) {
qk_ucis_state.count = 0;
qk_ucis_state.in_progress = true;
qk_ucis_start_user();
}
__attribute__((weak))
void qk_ucis_start_user(void) {
unicode_input_start();
register_hex(0x2328);
unicode_input_finish();
}
static bool is_uni_seq(char *seq) {
uint8_t i;
for (i = 0; seq[i]; i++) {
uint16_t code;
if (('1' <= seq[i]) && (seq[i] <= '0'))
code = seq[i] - '1' + KC_1;
else
code = seq[i] - 'a' + KC_A;
if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != code)
return false;
}
return (qk_ucis_state.codes[i] == KC_ENT ||
qk_ucis_state.codes[i] == KC_SPC);
}
__attribute__((weak))
void qk_ucis_symbol_fallback (void) {
for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) {
uint8_t code = qk_ucis_state.codes[i];
register_code(code);
unregister_code(code);
wait_ms(UNICODE_TYPE_DELAY);
}
}
void register_ucis(const char *hex) {
for(int i = 0; hex[i]; i++) {
uint8_t kc = 0;
char c = hex[i];
switch (c) {
case '0':
kc = KC_0;
break;
case '1' ... '9':
kc = c - '1' + KC_1;
break;
case 'a' ... 'f':
kc = c - 'a' + KC_A;
break;
case 'A' ... 'F':
kc = c - 'A' + KC_A;
break;
}
if (kc) {
register_code (kc);
unregister_code (kc);
wait_ms (UNICODE_TYPE_DELAY);
}
}
}
bool process_ucis (uint16_t keycode, keyrecord_t *record) {
uint8_t i;
if (!qk_ucis_state.in_progress)
return true;
if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH &&
!(keycode == KC_BSPC || keycode == KC_ESC || keycode == KC_SPC || keycode == KC_ENT)) {
return false;
}
if (!record->event.pressed)
return true;
qk_ucis_state.codes[qk_ucis_state.count] = keycode;
qk_ucis_state.count++;
if (keycode == KC_BSPC) {
if (qk_ucis_state.count >= 2) {
qk_ucis_state.count -= 2;
return true;
} else {
qk_ucis_state.count--;
return false;
}
}
if (keycode == KC_ENT || keycode == KC_SPC || keycode == KC_ESC) {
bool symbol_found = false;
for (i = qk_ucis_state.count; i > 0; i--) {
register_code (KC_BSPC);
unregister_code (KC_BSPC);
wait_ms(UNICODE_TYPE_DELAY);
}
if (keycode == KC_ESC) {
qk_ucis_state.in_progress = false;
return false;
}
unicode_input_start();
for (i = 0; ucis_symbol_table[i].symbol; i++) {
if (is_uni_seq (ucis_symbol_table[i].symbol)) {
symbol_found = true;
register_ucis(ucis_symbol_table[i].code + 2);
break;
}
}
if (!symbol_found) {
qk_ucis_symbol_fallback();
}
unicode_input_finish();
qk_ucis_state.in_progress = false;
return false;
}
return true;
}
#endif

View File

@ -8,10 +8,46 @@
#define UC_WIN 2
#define UC_BSD 3
#ifndef UNICODE_TYPE_DELAY
#define UNICODE_TYPE_DELAY 10
#endif
void set_unicode_input_mode(uint8_t os_target);
void unicode_input_start(void);
void unicode_input_finish(void);
void register_hex(uint16_t hex);
bool process_unicode(uint16_t keycode, keyrecord_t *record);
#ifdef UCIS_ENABLE
#ifndef UCIS_MAX_SYMBOL_LENGTH
#define UCIS_MAX_SYMBOL_LENGTH 32
#endif
typedef struct {
char *symbol;
char *code;
} qk_ucis_symbol_t;
struct {
uint8_t count;
uint16_t codes[UCIS_MAX_SYMBOL_LENGTH];
bool in_progress:1;
} qk_ucis_state;
#define UCIS_TABLE(...) {__VA_ARGS__, {NULL, NULL}}
#define UCIS_SYM(name, code) {name, #code}
extern const qk_ucis_symbol_t ucis_symbol_table[];
void qk_ucis_start(void);
void qk_ucis_start_user(void);
void qk_ucis_symbol_fallback (void);
void register_ucis(const char *hex);
bool process_ucis (uint16_t keycode, keyrecord_t *record);
#endif
#define UC_BSPC UC(0x0008)
#define UC_SPC UC(0x0020)
@ -119,4 +155,4 @@ bool process_unicode(uint16_t keycode, keyrecord_t *record);
#define UC_TILD UC(0x007E)
#define UC_DEL UC(0x007F)
#endif
#endif

View File

@ -46,18 +46,20 @@ bool process_record_quantum(keyrecord_t *record) {
uint16_t keycode;
#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
uint8_t layer;
/* TODO: Use store_or_get_action() or a similar function. */
if (!disable_action_cache) {
uint8_t layer;
if (record->event.pressed) {
layer = layer_switch_get_layer(key);
update_source_layers_cache(key, layer);
} else {
layer = read_source_layers_cache(key);
}
keycode = keymap_key_to_keycode(layer, key);
#else
keycode = keymap_key_to_keycode(layer_switch_get_layer(key), key);
if (record->event.pressed) {
layer = layer_switch_get_layer(key);
update_source_layers_cache(key, layer);
} else {
layer = read_source_layers_cache(key);
}
keycode = keymap_key_to_keycode(layer, key);
} else
#endif
keycode = keymap_key_to_keycode(layer_switch_get_layer(key), key);
// This is how you use actions here
// if (keycode == KC_LEAD) {
@ -86,6 +88,9 @@ bool process_record_quantum(keyrecord_t *record) {
#endif
#ifdef UNICODE_ENABLE
process_unicode(keycode, record) &&
#endif
#ifdef UCIS_ENABLE
process_ucis(keycode, record) &&
#endif
true)) {
return false;

View File

@ -431,7 +431,7 @@ enum {
};
//Tap Dance Definitions
const qk_tap_dance_action_t tap_dance_actions[] = {
qk_tap_dance_action_t tap_dance_actions[] = {
//Tap once for Esc, twice for Caps Lock
[TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS)
// Other declarations would go here, separated by commas, if you have them
@ -517,7 +517,7 @@ void dance_flsh_reset(qk_tap_dance_state_t *state, void *user_data) {
ergodox_right_led_3_off();
}
const qk_tap_dance_action_t tap_dance_actions[] = {
qk_tap_dance_action_t tap_dance_actions[] = {
[CT_SE] = ACTION_TAP_DANCE_DOUBLE (KC_SPC, KC_ENT)
,[CT_CLN] = ACTION_TAP_DANCE_FN_ADVANCED (NULL, dance_cln_finished, dance_cln_reset)
,[CT_EGG] = ACTION_TAP_DANCE_FN (dance_egg)
@ -695,6 +695,49 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
And then, to assign this macro to a key on your keyboard layout, you just use `M(0)` on the key you want to press for copy/paste.
## Dynamic macros: record and replay macros in runtime
In addition to the static macros described above, you may enable the dynamic macros which you may record while writing. They are forgotten as soon as the keyboard is unplugged. Only two such macros may be stored at the same time, with the total length of 128 keypresses.
To enable them, first add a new element to the `planck_keycodes` enum -- `DYNAMIC_MACRO_RANGE`:
enum planck_keycodes {
QWERTY = SAFE_RANGE,
COLEMAK,
DVORAK,
PLOVER,
LOWER,
RAISE,
BACKLIT,
EXT_PLV,
DYNAMIC_MACRO_RANGE,
};
Afterwards create a new layer called `_DYN`:
#define _DYN 6 /* almost any other free number should be ok */
Below these two modifications include the `dynamic_macro.h` header:
#include "dynamic_macro.h"`
Then define the `_DYN` layer with the following keys: `DYN_REC_START1`, `DYN_REC_PLAY1`,`DYN_REC_START2` and `DYN_REC_PLAY2`. It may also contain other keys, it doesn't matter apart from the fact that you won't be able to record these keys in the dynamic macros.
[_DYN]= {
{_______, DYN_REC_START1, DYN_MACRO_PLAY1, _______, _______, _______, _______, _______, _______, _______, _______, _______},
{_______, DYN_REC_START2, DYN_MACRO_PLAY2, _______, _______, _______, _______, _______, _______, _______, _______, _______},
{_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
{_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______}
},
Add the following code to the very beginning of your `process_record_user()` function:
if (!process_record_dynamic_macro(keycode, record)) {
return false;
}
The usage should be pretty self-explanatory. For the details, please read the comments in the `dynamic_macro.h` header.
## Additional keycode aliases for software-implemented layouts (Colemak, Dvorak, etc)
Everything is assuming you're in Qwerty (in software) by default, but there is built-in support for using a Colemak or Dvorak layout by including this at the top of your keymap: