aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common_features.mk5
-rw-r--r--docs/feature_auto_shift.md161
-rw-r--r--docs/understanding_qmk.md1
-rw-r--r--quantum/process_keycode/process_auto_shift.c168
-rw-r--r--quantum/process_keycode/process_auto_shift.h28
-rw-r--r--quantum/quantum.c3
-rw-r--r--quantum/quantum.h4
-rw-r--r--quantum/quantum_keycodes.h5
8 files changed, 375 insertions, 0 deletions
diff --git a/common_features.mk b/common_features.mk
index 117f84260..bae23bb87 100644
--- a/common_features.mk
+++ b/common_features.mk
@@ -119,6 +119,11 @@ ifeq ($(strip $(PRINTING_ENABLE)), yes)
119 SRC += $(TMK_DIR)/protocol/serial_uart.c 119 SRC += $(TMK_DIR)/protocol/serial_uart.c
120endif 120endif
121 121
122ifeq ($(strip $(AUTO_SHIFT_ENABLE)), yes)
123 OPT_DEFS += -DAUTO_SHIFT_ENABLE
124 SRC += $(QUANTUM_DIR)/process_keycode/process_auto_shift.c
125endif
126
122ifeq ($(strip $(SERIAL_LINK_ENABLE)), yes) 127ifeq ($(strip $(SERIAL_LINK_ENABLE)), yes)
123 SRC += $(patsubst $(QUANTUM_PATH)/%,%,$(SERIAL_SRC)) 128 SRC += $(patsubst $(QUANTUM_PATH)/%,%,$(SERIAL_SRC))
124 OPT_DEFS += $(SERIAL_DEFS) 129 OPT_DEFS += $(SERIAL_DEFS)
diff --git a/docs/feature_auto_shift.md b/docs/feature_auto_shift.md
new file mode 100644
index 000000000..a054c3652
--- /dev/null
+++ b/docs/feature_auto_shift.md
@@ -0,0 +1,161 @@
1# Auto Shift: Why do we need a shift key?
2
3Tap a key and you get its character. Tap a key, but hold it *slightly* longer
4and you get its shifted state. Viola! No shift key needeed!
5
6## Why Auto Shift?
7
8Many people suffer from various forms of RSI. A common cause is stretching your
9fingers repeitively long distances. For us on the keyboard, the pinky does that
10all too often when reaching for the shift key. Auto Shift looks to aliviate that
11problem.
12
13## How does it work?
14
15When you tap a key, it stays depressed for a short period of time before it is
16then released. This depressed time is a different length everyone. Auto Shift
17defines a constant `AUTO_SHIFT_TIMEOUT` which is typically set to twice your
18normal pressed state time. When you press a key, a timer starts and then stops
19when you release the key. If the time depressed is greater than or equal to the
20`AUTO_SHIFT_TIMEOUT` then a shifted version of the key is emitted. If the time
21is less than the `AUTO_SHIFT_TIMEOUT` time, then the normal state is emitted.
22
23## Are there limitations to Auto Shift?
24
25Yes, unfortunately.
26
271. Key repeat will cease to work. For example, before if you wanted 20 'a'
28 characters, you could press and hold the 'a' key for a second or two. This no
29 longer works with Auto Shift because it is timing your depressed time instead
30 of emitting a depressed key state to your operating system.
312. Auto Shift is disabled for any key press that is accompanied by one or more
32 modifiers. Thus, Ctrl+A that you hold for a really long time is not the same
33 as Ctrl+Shift+A.
343. You will have characters that are shifted you did not intend on shifting, and
35 other characters you wanted shifted, but were not. This simply comes down to
36 practice. As we get in a hurry, we think we might have hit the key long enough
37 for a shifted version, but we did not. On the other hand, we may think we are
38 tapping the keys, but really we have held it for a little longer than
39 anticipated.
40
41## How do I enable Auto Shift?
42
43Add to your `rules.mk` in the keymap folder:
44
45 AUTO_SHIFT_ENABLE = YES
46
47If no `rules.mk` exists, you can create one.
48
49Then compile and install your new firmware with Auto Key enabled! That's it!
50
51## Configuring Auto Shift
52
53If desired, there is some configuration that can be done to change the
54behavior of Auto Shift. This is done by setting various variables the
55`config.h` file located in your keymap folder.
56
57If no `config.h` file exists, you can create one. A sample is
58
59 #ifndef CONFIG_USER_H
60 #define CONFIG_USER_H
61
62 #include "../../config.h"
63
64 #define AUTO_SHIFT_TIMEOUT 150
65 #define NO_AUTO_SHIFT_SPECIAL
66
67 #endif
68
69### AUTO_SHIFT_TIMEOUT (value in ms)
70
71This controls how long you have to hold a key before you get the shifted state.
72Obviously, this is different for everyone. For the common person a setting of
73135 to 150 works great but one should start with a value of at least 175, which
74is the default value. Then work down from there. The idea is to have as short
75of a time required to get the shifted state without having false positives.
76
77Play with this value until things are perfect. Many find that all will work well
78at a given value, but one or two keys will still emit the shifted state on
79occassion. This is simply due to habit and holding some keys a little longer
80than others. Once you find this value, work on tapping your problem keys a little
81quicker than normal and you will be set.
82
83{% hint style='info' %}
84Auto Shift has three special keys that can help you get this value right very
85quick. See "Auto Shift Setup" for more details!
86{% endhint %}
87
88### NO_AUTO_SHIFT_SPECIAL (simple define)
89
90Do not Auto Shift special keys, which include -_, =+, [{, ]}, ;:, '", ,<, .>,
91and /?
92
93### NO_AUTO_SHIFT_NUMERIC (simple define)
94
95Do not Auto Shift numeric keys, zero through nine.
96
97### NO_AUTO_SHIFT_ALPHA (simple define)
98
99Do not Auto Shift alpha characters, which include A through Z.
100
101## Using Auto Shift Setup
102
103This will enable you to define three keys temporailiy to increase, decrease and report your `AUTO_SHIFT_TIMEOUT`.
104
105### Setup
106
107Map three keys temporarily in your keymap:
108
109| Key Name | Description |
110|----------|-----------------------------------------------------|
111| KC_ASDN | Lower the Auto Shift timeout variable (down) |
112| KC_ASUP | Raise the Auto Shift timeout variable (up) |
113| KC_ASRP | Report your current Auto Shift timeout value |
114
115Compile and upload your new firmware.
116
117### Use
118
119It is important to note that during these tests, you should be typing
120completely normal and with no intention of shifted keys.
121
1221. Type multiple sentences of alphabetical letters.
1232. Observe any upper case letters.
1243. If there are none, press the key you have mapped to `KC_ASDN` to decrease
125 time Auto Shift timeout value and go back to step 1.
1264. If there are some upper case letters, decide if you need to work on tapping
127 those keys with less down time, or if you need to increase the timeout.
1285. If you decide to increase the timeout, press the key you have mapped to
129 `KC_ASUP` and go back to step 1.
1306. Once you are happy with your results, press the key you have mapped to
131 `KC_ASRP`. The keyboard will type by itself the value of your
132 `AUTO_SHIFT_TIMEOUT`.
1337. Update `AUTO_SHIFT_TIMEOUT` in your `config.h` with the value reported.
1348. Remove `AUTO_SHIFT_SETUP` from your `config.h`.
1359. Remove the key bindings `KC_ASDN`, `KC_ASUP` and `KC_ASRP`.
13610. Compile and upload your new firmware.
137
138#### An example run
139
140\'\'\'
141hello world. my name is john doe. i am a computer programmer playing with
142keyboards right now.
143
144[PRESS KC_ASDN quite a few times]
145
146heLLo woRLd. mY nAMe is JOHn dOE. i AM A compUTeR proGRaMMER PlAYiNG witH
147KEYboArDS RiGHT NOw.
148
149[PRESS KC_ASUP a few times]
150
151hello world. my name is john Doe. i am a computer programmer play with
152keyboarDs right now.
153
154[PRESS KC_ASRP]
155
156115
157\'\'\'
158
159The keyboard typed `115` which represents your current `AUTO_SHIFT_TIMEOUT`
160value. You are now set! Practice on the *D* key a little bit that showed up
161in the testing and you'll be golden.
diff --git a/docs/understanding_qmk.md b/docs/understanding_qmk.md
index 2ac4f3036..99c2306d6 100644
--- a/docs/understanding_qmk.md
+++ b/docs/understanding_qmk.md
@@ -147,6 +147,7 @@ The `process_record()` function itself is deceptively simple, but hidden within
147 * [`bool process_unicode(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_unicode.c#L22) 147 * [`bool process_unicode(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_unicode.c#L22)
148 * [`bool process_ucis(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_ucis.c#L91) 148 * [`bool process_ucis(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_ucis.c#L91)
149 * [`bool process_printer(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_printer.c#L77) 149 * [`bool process_printer(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_printer.c#L77)
150 * [`bool process_auto_shift(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_auto_shift.c#L47)
150 * [`bool process_unicode_map(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_unicodemap.c#L47) 151 * [`bool process_unicode_map(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/master/quantum/process_keycode/process_unicodemap.c#L47)
151 * [Identify and process quantum specific keycodes](https://github.com/qmk/qmk_firmware/blob/master/quantum/quantum.c#L211) 152 * [Identify and process quantum specific keycodes](https://github.com/qmk/qmk_firmware/blob/master/quantum/quantum.c#L211)
152 153
diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c
new file mode 100644
index 000000000..55b524450
--- /dev/null
+++ b/quantum/process_keycode/process_auto_shift.c
@@ -0,0 +1,168 @@
1/* Copyright 2017 Jeremy Cowgar
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifdef AUTO_SHIFT_ENABLE
18
19#include <stdio.h>
20
21#include "process_auto_shift.h"
22
23#define TAP(key) \
24 register_code(key); \
25 unregister_code(key)
26
27#define TAP_WITH_MOD(mod, key) \
28 register_code(mod); \
29 register_code(key); \
30 unregister_code(key); \
31 unregister_code(mod)
32
33uint16_t autoshift_time = 0;
34uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT;
35uint16_t autoshift_lastkey = KC_NO;
36
37void autoshift_timer_report(void) {
38 char display[8];
39
40 snprintf(display, 8, "\n%d\n", autoshift_timeout);
41
42 send_string((const char *)display);
43}
44
45void autoshift_on(uint16_t keycode) {
46 autoshift_time = timer_read();
47 autoshift_lastkey = keycode;
48}
49
50void autoshift_flush(void) {
51 if (autoshift_lastkey != KC_NO) {
52 uint16_t elapsed = timer_elapsed(autoshift_time);
53
54 if (elapsed > autoshift_timeout) {
55 register_code(KC_LSFT);
56 }
57
58 register_code(autoshift_lastkey);
59 unregister_code(autoshift_lastkey);
60
61 if (elapsed > autoshift_timeout) {
62 unregister_code(KC_LSFT);
63 }
64
65 autoshift_time = 0;
66 autoshift_lastkey = KC_NO;
67 }
68}
69
70bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
71 static uint8_t any_mod_pressed;
72
73 if (record->event.pressed) {
74 switch (keycode) {
75 case KC_ASUP:
76 autoshift_timeout += 5;
77 return false;
78
79 case KC_ASDN:
80 autoshift_timeout -= 5;
81 return false;
82
83 case KC_ASRP:
84 autoshift_timer_report();
85 return false;
86
87#ifndef NO_AUTO_SHIFT_ALPHA
88 case KC_A:
89 case KC_B:
90 case KC_C:
91 case KC_D:
92 case KC_E:
93 case KC_F:
94 case KC_G:
95 case KC_H:
96 case KC_I:
97 case KC_J:
98 case KC_K:
99 case KC_L:
100 case KC_M:
101 case KC_N:
102 case KC_O:
103 case KC_P:
104 case KC_Q:
105 case KC_R:
106 case KC_S:
107 case KC_T:
108 case KC_U:
109 case KC_V:
110 case KC_W:
111 case KC_X:
112 case KC_Y:
113 case KC_Z:
114#endif
115#ifndef NO_AUTO_SHIFT_NUMERIC
116 case KC_1:
117 case KC_2:
118 case KC_3:
119 case KC_4:
120 case KC_5:
121 case KC_6:
122 case KC_7:
123 case KC_8:
124 case KC_9:
125 case KC_0:
126#endif
127#ifndef NO_AUTO_SHIFT_SPECIAL
128 case KC_TILD:
129 case KC_MINUS:
130 case KC_EQL:
131 case KC_TAB:
132 case KC_LBRC:
133 case KC_RBRC:
134 case KC_BSLS:
135 case KC_SCLN:
136 case KC_QUOT:
137 case KC_COMM:
138 case KC_DOT:
139 case KC_SLSH:
140#endif
141 autoshift_flush();
142
143 any_mod_pressed = get_mods() & (
144 MOD_BIT(KC_LGUI)|MOD_BIT(KC_RGUI)|
145 MOD_BIT(KC_LALT)|MOD_BIT(KC_RALT)|
146 MOD_BIT(KC_LCTL)|MOD_BIT(KC_RCTL)|
147 MOD_BIT(KC_LSFT)|MOD_BIT(KC_RSFT)
148 );
149
150 if (any_mod_pressed) {
151 return true;
152 }
153
154 autoshift_on(keycode);
155 return false;
156
157 default:
158 autoshift_flush();
159 return true;
160 }
161 } else {
162 autoshift_flush();
163 }
164
165 return true;
166}
167
168#endif
diff --git a/quantum/process_keycode/process_auto_shift.h b/quantum/process_keycode/process_auto_shift.h
new file mode 100644
index 000000000..a0361346b
--- /dev/null
+++ b/quantum/process_keycode/process_auto_shift.h
@@ -0,0 +1,28 @@
1/* Copyright 2017 Jeremy Cowgar
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef PROCESS_AUTO_SHIFT_H
18#define PROCESS_AUTO_SHIFT_H
19
20#include "quantum.h"
21
22#ifndef AUTO_SHIFT_TIMEOUT
23 #define AUTO_SHIFT_TIMEOUT 175
24#endif
25
26bool process_auto_shift(uint16_t keycode, keyrecord_t *record);
27
28#endif
diff --git a/quantum/quantum.c b/quantum/quantum.c
index 1fccaa7d5..a1a1a9d1c 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -235,6 +235,9 @@ bool process_record_quantum(keyrecord_t *record) {
235 #ifdef PRINTING_ENABLE 235 #ifdef PRINTING_ENABLE
236 process_printer(keycode, record) && 236 process_printer(keycode, record) &&
237 #endif 237 #endif
238 #ifdef AUTO_SHIFT_ENABLE
239 process_auto_shift(keycode, record) &&
240 #endif
238 #ifdef UNICODEMAP_ENABLE 241 #ifdef UNICODEMAP_ENABLE
239 process_unicode_map(keycode, record) && 242 process_unicode_map(keycode, record) &&
240 #endif 243 #endif
diff --git a/quantum/quantum.h b/quantum/quantum.h
index f3333a002..534819c81 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -95,6 +95,10 @@ extern uint32_t default_layer_state;
95 #include "process_printer.h" 95 #include "process_printer.h"
96#endif 96#endif
97 97
98#ifdef AUTO_SHIFT_ENABLE
99 #include "process_auto_shift.h"
100#endif
101
98#ifdef COMBO_ENABLE 102#ifdef COMBO_ENABLE
99 #include "process_combo.h" 103 #include "process_combo.h"
100#endif 104#endif
diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h
index 26c3c41a7..212fdc67d 100644
--- a/quantum/quantum_keycodes.h
+++ b/quantum/quantum_keycodes.h
@@ -121,6 +121,11 @@ enum quantum_keycodes {
121 KC_LEAD, 121 KC_LEAD,
122#endif 122#endif
123 123
124 // Auto Shift setup
125 KC_ASUP,
126 KC_ASDN,
127 KC_ASRP,
128
124 // Audio on/off/toggle 129 // Audio on/off/toggle
125 AU_ON, 130 AU_ON,
126 AU_OFF, 131 AU_OFF,