qmk

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.z3bra.org/qmk.git
Log | Files | Refs | Submodules | LICENSE

commit 2c0323bc98f7ec8b6a8e2da393fd220718cf19ad
parent 7fbe6c35944a140cc3b089884350844dddf301e6
Author: Colin T.A. Gray <colinta@gmail.com>
Date:   Sun, 26 Nov 2017 00:08:28 -0700

Adds my XD75 layout (#2040)

* adds my xd75 layout

* add secret strings to 'secrets.h' behind compile flag, assign defaults

* macro keys now have defaults (hidden in colinta.h) before any recording, and after clearing the dynamic macros.

* fixed whitespace - using 4 spaces instead of 2

Diffstat:
keyboards/xd75/keymaps/colinta/config.h | 28++++++++++++++++++++++++++++
keyboards/xd75/keymaps/colinta/keymap.c | 268+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
keyboards/xd75/keymaps/colinta/readme.md | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 360 insertions(+), 0 deletions(-)

diff --git a/keyboards/xd75/keymaps/colinta/config.h b/keyboards/xd75/keymaps/colinta/config.h @@ -0,0 +1,28 @@ +/* Copyright 2017 Colin T.A. Gray + * + * 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" + +// QMK customization: +// - after 1.5s, turn off one-shot keys +#define ONESHOT_TIMEOUT 1500 +// - TT(layer) only needs one press +#define TAPPING_TOGGLE 1 + +#endif diff --git a/keyboards/xd75/keymaps/colinta/keymap.c b/keyboards/xd75/keymaps/colinta/keymap.c @@ -0,0 +1,268 @@ +/* Copyright 2017 Colin T.A. Gray + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include "xd75.h" + +#ifdef IS_COLINTA +#include "secrets.h" +#else +#define SENDSTRING_MM0 "" +#define SENDSTRING_MM1 "" +#define SENDSTRING_MM2 "" +#endif + +// layers: +// - colemak, +// - record-mode (adds stop buttons) +// - qwerty +// - fn (recording, changing layers) +#define LAYER_COLEMAK 0 +#define LAYER_RECORD 1 +#define LAYER_QWERTY 2 +#define LAYER_FN 3 + +// custom keys: +// - goto layer keys +#define GOTO_FN TT(LAYER_FN) +#define GOTO_CM TO(LAYER_COLEMAK) +#define GOTO_QW TO(LAYER_QWERTY) +// - sticky keys, aka one-shot +#define OSCTL OSM(MOD_LCTL) +#define OSALT OSM(MOD_LALT) +#define OSSFT OSM(MOD_LSFT) +#define OSGUI OSM(MOD_LGUI) +// "MMENU" is a macro for "CMD+SPC" (aka Spotlight/Alfred) +#define MMENU LGUI(KC_SPC) +#define _____ KC_TRNS +#define MM_0 DYN_MACRO_PLAY1 +#define MM_1 DYN_MACRO_PLAY2 + +// tap-hold settings +#define LONGPRESS_DELAY 250 +#define TH_EVENTS_COUNT 13 + +enum my_keycods { + TH_M0 = SAFE_RANGE, + TH_M1, + TH_M2, + TH_F1, + TH_F2, + TH_F3, + TH_F4, + TH_F5, + TH_F6, + TH_F7, + TH_F8, + TH_F9, + TH_F10, + TH_LAST, + MM_2, + DM_CLEAR, + DYNAMIC_MACRO_RANGE, +}; + +#include "dynamic_macro.h" + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + +/* COLEMAK + * .--------------------------------------------------------------------------------------------------------------------------------------. + * | ESC | 1 | 2 | 3 | 4 | 5 | M(0) | M(1) | DEL | 6 | 7 | 8 | 9 | 0 | - | + * |--------+-/F1----+-/F2----+-/F3----+-/F4----+-/F5----+--------+--------+--------+-/F6----+-/F7----+-/F8----+-/F9----+-/F10---+--------| + * | TAB | Q | W | F | P | G | M(2) | (FN) | BKSP | J | L | U | Y | ; | = | + * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------+--------| + * | SHIFT | A | R | S | T | D | [ | ] | ENTER | H | N | E | I | O | ' | + * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------------------------+--------| + * | CTRL | Z | X | C | V | B | HOME | END | PG UP | K | M | , | . | / | \ | + * |--------+--------+--------+--------+--------+-----------------+--------+--------+--------+--------+-----------------+--------+--------| + * | VOL- | PLAY | VOL+ | ALT | GUI | SPACE | PG DN | MENU | ESC | LEFT | DOWN | UP | RIGHT | + * '--/RRND----/MUTE----/FFWD-------------------------------------------------------------------------------------------------------------' + */ + + [LAYER_COLEMAK] = KEYMAP( + KC_GRV, TH_F1, TH_F2, TH_F3, TH_F4, TH_F5, MM_0, MM_1, KC_DEL, TH_F6, TH_F7, TH_F8, TH_F9, TH_F10, KC_MINS, + KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, MM_2, GOTO_FN, KC_BSPC, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_EQL, + OSCTL, KC_A, KC_R, KC_S, KC_T, KC_D, KC_LBRC, KC_RBRC, KC_ENT, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT, + OSSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_HOME, KC_END, KC_PGUP, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_BSLS, + TH_M0, TH_M1, TH_M2, OSALT, OSGUI, _____ , KC_SPC, _____ , KC_PGDN, MMENU, KC_ESC, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT + ), + +/* DYN_REC LAYER - recording tap/hold keys is possible, but they will always "tap" (macros don't record holding duration) + * .--------------------------------------------------------------------------------------------------------------------------------------. + * | | | | | | | STOP | STOP | | | | | | | | + * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------| + * | | | | | | | STOP | STOP | | | | | | | | + * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------+--------| + * | | | | | | | | | | | | | | | | + * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------------------------+--------| + * | | | | | | | | | | | | | | | | + * |--------+--------+--------+--------+--------+-----------------+--------+--------+--------+--------+-----------------+--------+--------| + * | | | | | | | | | | | | | | + * '--------------------------------------------------------------------------------------------------------------------------------------' + */ + + [LAYER_RECORD] = KEYMAP( + _____, _____, _____, _____, _____, _____, DYN_REC_STOP, DYN_REC_STOP, _____, _____, _____, _____, _____, _____, _____, + _____, _____, _____, _____, _____, _____, DYN_REC_STOP, DYN_REC_STOP, _____, _____, _____, _____, _____, _____, _____, + _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, + _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, + _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____ + ), + +/* QWERTY - doesn't support recording of macros, btw. Falls through to colemak for most keys, but passes through the recording layer, so heads up. + * .--------------------------------------------------------------------------------------------------------------------------------------. + * | | | | | | | M(0) | M(1) | | | | | | | | + * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------| + * | | Q | W | E | R | T | M(2) | (FN) | | Y | U | I | O | P | | + * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------+--------| + * | SHIFT | A | S | D | F | G | | | | H | J | K | L | ; | | + * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------------------------+--------| + * | CTRL | Z | X | C | V | B | | | | N | M | | | | | + * |--------+--------+--------+--------+--------+-----------------+--------+--------+--------+--------+-----------------+--------+--------| + * | | | | ALT | GUI | | | | | | | | | + * '--------------------------------------------------------------------------------------------------------------------------------------' + */ + + [LAYER_QWERTY] = KEYMAP( + _____, _____, _____, _____, _____, _____, MM_0, MM_1, _____, _____, _____, _____, _____, _____, _____, + _____, KC_Q, KC_W, KC_E, KC_R, KC_T, MM_2, GOTO_FN, _____, KC_Y, KC_U, KC_I, KC_O, KC_P, _____, + MOD_LSFT, KC_A, KC_S, KC_D, KC_F, KC_G, _____, _____, _____, KC_H, KC_J, KC_K, KC_L, KC_SCLN, _____, + MOD_LCTL, KC_Z, KC_X, KC_C, KC_V, KC_B, _____, _____, _____, KC_N, KC_M, _____, _____, _____, _____, + _____, _____, _____, MOD_LALT, MOD_LGUI, _____, _____, _____, _____, _____, _____, _____, _____, _____, _____ + ), + +/* FN LAYER - change layouts and start recording a macro + * .--------------------------------------------------------------------------------------------------------------------------------------. + * | COLEMAK| QWERTY | | | | | REC 1 | REC 2 | | | | | | | | + * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------| + * | | | | | | | | ------ | | | | | | | | + * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------+--------| + * | | | | | | | | | | | | | | | | + * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------------------------+--------| + * | | | | | | | | | | | | | | | | + * |--------+--------+--------+--------+--------+-----------------+--------+--------+--------+--------+-----------------+--------+--------| + * | | | | | RESET | DM_CLEAR | | | RESET | | | | | + * '--------------------------------------------------------------------------------------------------------------------------------------' + */ + + [LAYER_FN] = KEYMAP( + GOTO_CM, GOTO_QW, KC_NO, KC_NO, KC_NO, KC_NO, DYN_REC_START1, DYN_REC_START2, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, RESET, KC_NO, DM_CLEAR, KC_NO, KC_NO, KC_NO, RESET, KC_NO, KC_NO, KC_NO, KC_NO + ) +}; + +typedef struct { + bool is_pressed; + uint16_t timer; + uint16_t kc_tap; + uint16_t kc_hold; +} tap_hold_t; + +static tap_hold_t th_events[] = { + { .is_pressed = false, .timer = 0, .kc_tap = KC_VOLD, .kc_hold = KC_MRWD }, // TH_M0 + { .is_pressed = false, .timer = 0, .kc_tap = KC_MPLY, .kc_hold = KC_MUTE }, // TH_M1 + { .is_pressed = false, .timer = 0, .kc_tap = KC_VOLU, .kc_hold = KC_MFFD }, // TH_M2 + + { .is_pressed = false, .timer = 0, .kc_tap = KC_1, .kc_hold = KC_F1 }, // TH_F1 + { .is_pressed = false, .timer = 0, .kc_tap = KC_2, .kc_hold = KC_F2 }, // TH_F2 + { .is_pressed = false, .timer = 0, .kc_tap = KC_3, .kc_hold = KC_F3 }, // TH_F3 + { .is_pressed = false, .timer = 0, .kc_tap = KC_4, .kc_hold = KC_F4 }, // TH_F4 + { .is_pressed = false, .timer = 0, .kc_tap = KC_5, .kc_hold = KC_F5 }, // TH_F5 + { .is_pressed = false, .timer = 0, .kc_tap = KC_6, .kc_hold = KC_F6 }, // TH_F6 + { .is_pressed = false, .timer = 0, .kc_tap = KC_7, .kc_hold = KC_F7 }, // TH_F7 + { .is_pressed = false, .timer = 0, .kc_tap = KC_8, .kc_hold = KC_F8 }, // TH_F8 + { .is_pressed = false, .timer = 0, .kc_tap = KC_9, .kc_hold = KC_F9 }, // TH_F9 + { .is_pressed = false, .timer = 0, .kc_tap = KC_0, .kc_hold = KC_F10 } // TH_F10 +}; + +void taphold_tapped(uint8_t index, bool pressed) { + if (index >= TH_EVENTS_COUNT) { return; } + + tap_hold_t *th_event = &th_events[index]; + + if (pressed) { + th_event->timer = timer_read(); + th_event->is_pressed = true; + } else if (th_event->is_pressed) { + register_code(th_event->kc_tap); + unregister_code(th_event->kc_tap); + th_event->is_pressed = false; + } +} + +void matrix_scan_user() { + for (uint8_t index = 0 ; index < TH_EVENTS_COUNT ; ++index ) { + tap_hold_t *th_event = &th_events[index]; + if ( th_event->is_pressed && timer_elapsed(th_event->timer) > LONGPRESS_DELAY) { + register_code(th_event->kc_hold); + unregister_code(th_event->kc_hold); + th_event->is_pressed = false; + } + } +} + +// if the dynamic macros haven't been recorded, we send the default macro strings. +bool did_record_m1 = false; +bool did_record_m2 = false; +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + bool try_dynamic_macro = true; + if ((keycode == DYN_MACRO_PLAY1 && !did_record_m1) || (keycode == DYN_MACRO_PLAY2 && !did_record_m2)) { + try_dynamic_macro = false; + } + else if (keycode == DM_CLEAR) { + try_dynamic_macro = false; + did_record_m1 = false; + did_record_m2 = false; + } + + if (try_dynamic_macro && !process_record_dynamic_macro(keycode, record)) { + if (keycode == DYN_MACRO_PLAY1) { + did_record_m1 = true; + } + + if (keycode == DYN_MACRO_PLAY2) { + did_record_m2 = true; + } + + if (keycode == DYN_REC_START1 || keycode == DYN_REC_START2) { + layer_move(LAYER_RECORD); + } + else if (keycode == DYN_REC_STOP) { + layer_move(LAYER_COLEMAK); + } + + return false; + } + + switch (keycode) { + case DYN_MACRO_PLAY1: + SEND_STRING(SENDSTRING_MM0); + return false; + case DYN_MACRO_PLAY2: + SEND_STRING(SENDSTRING_MM1); + return false; + case MM_2: + SEND_STRING(SENDSTRING_MM2); + return false; + case TH_M0 ... TH_LAST: + taphold_tapped(keycode - TH_M0, record->event.pressed); + return false; + } + + return true; +} diff --git a/keyboards/xd75/keymaps/colinta/readme.md b/keyboards/xd75/keymaps/colinta/readme.md @@ -0,0 +1,64 @@ +# colinta's keymap for XD75 + +``` +make xd75:colinta:dfu +``` + +The default layout is a Colemak keyboard with "one-shot" keys assigned to the modifier keys. + + .--------------------------------------------------------------------------------------------------------------------------------------. + | ESC | 1 | 2 | 3 | 4 | 5 | DYN_M1 | DYN_M2 | DEL | 6 | 7 | 8 | 9 | 0 | - | + |--------+-/F1----+-/F2----+-/F3----+-/F4----+-/F5----+--------+--------+--------+-/F6----+-/F7----+-/F8----+-/F9----+-/F10---+--------| + | TAB | Q | W | F | P | G | MACRO | (FN) | BKSP | J | L | U | Y | ; | = | + |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------+--------| + | SHIFT | A | R | S | T | D | [ | ] | ENTER | H | N | E | I | O | ' | + |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------------------------+--------| + | CTRL | Z | X | C | V | B | HOME | END | PG UP | K | M | , | . | / | \ | + |--------+--------+--------+--------+--------+-----------------+--------+--------+--------+--------+-----------------+--------+--------| + | VOL- | PLAY | VOL+ | ALT | GUI | SPACE | PG DN | MENU | ESC | LEFT | DOWN | UP | RIGHT | + '--/RRND----/MUTE----/FFWD-------------------------------------------------------------------------------------------------------------' + + +I've implemented my own "tap/hold" feature, identical in spirit to "Space Cadet", but generic. Tapping "1" sends a 1, but press and hold to send "F1". Or, tap "VOL-" to turn the volume down, but press and hold to rewind. + +The function layer is only to switch to Qwerty (so other people can use this keyboard - also turns off sticky keys) and to start recording keypresses. + +I implemented "stop recording" in a unique way; starting a macro recording sends the keyboard layer to one that has all the macro keys assigned to `DYN_REC_STOP`, and restores the layer to the default when recording is stopped. + +I wish Dynamic Macros supported more, because I'd like to record a third macro in the MACRO slot instead of hardcoding it. I'm using these to store some passwords. + +## Regarding "secrets.h" + +The macros I'm using are sensitive, I'm comfortable having them hardcoded onto my keyboard (no SSN or private GPG keys), but not suitable for public viewing. So I've put them in a header file that is excluded from the project, and I can include this file using a compiler flag. + +If you would *also* like to take advantage of this feature, you'll first want to make sure your "secrets" file isn't included in the repo. Open `.git/info/exclude` and add `secrets.h` to that file, below the comments. + +###### .git/info/exclude +``` +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ +/keyboards/xd75/keymaps/colinta/secrets.h +``` + +Then you can create this file and add your macro strings to it: + +``` +$EDITOR keyboards/xd75/keymaps/colinta/secrets.h +``` + +###### secrets.h +``` +#define SENDSTRING_MM0 "abcd1234" +#define SENDSTRING_MM1 "shhhhh secret" +#define SENDSTRING_MM2 "stop saying pickle rick" +``` + +To include the feature at compile time, include the flag `IS_COLINTA` like so: + +``` +make xd75:colinta:dfu EXTRAFLAGS=-DIS_COLINTA +```