aboutsummaryrefslogtreecommitdiff
path: root/tmk_core/common
diff options
context:
space:
mode:
Diffstat (limited to 'tmk_core/common')
-rw-r--r--tmk_core/common/action.c97
-rw-r--r--tmk_core/common/action_code.h5
-rw-r--r--tmk_core/common/action_util.c70
-rw-r--r--tmk_core/common/action_util.h20
4 files changed, 179 insertions, 13 deletions
diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c
index f9e6c17dc..081e90b2d 100644
--- a/tmk_core/common/action.c
+++ b/tmk_core/common/action.c
@@ -74,6 +74,7 @@ void process_action_kb(keyrecord_t *record) {}
74 74
75void process_action(keyrecord_t *record) 75void process_action(keyrecord_t *record)
76{ 76{
77 bool do_release_oneshot = false;
77 keyevent_t event = record->event; 78 keyevent_t event = record->event;
78#ifndef NO_ACTION_TAPPING 79#ifndef NO_ACTION_TAPPING
79 uint8_t tap_count = record->tap.count; 80 uint8_t tap_count = record->tap.count;
@@ -81,6 +82,13 @@ void process_action(keyrecord_t *record)
81 82
82 if (IS_NOEVENT(event)) { return; } 83 if (IS_NOEVENT(event)) { return; }
83 84
85#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
86 if (has_oneshot_layer_timed_out()) {
87 dprintf("Oneshot layer: timeout\n");
88 clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
89 }
90#endif
91
84 process_action_kb(record); 92 process_action_kb(record);
85 93
86 action_t action = store_or_get_action(event.pressed, event.key); 94 action_t action = store_or_get_action(event.pressed, event.key);
@@ -95,6 +103,15 @@ void process_action(keyrecord_t *record)
95 // clear the potential weak mods left by previously pressed keys 103 // clear the potential weak mods left by previously pressed keys
96 clear_weak_mods(); 104 clear_weak_mods();
97 } 105 }
106
107#ifndef NO_ACTION_ONESHOT
108 // notice we only clear the one shot layer if the pressed key is not a modifier.
109 if (is_oneshot_layer_active() && event.pressed && !IS_MOD(action.key.code)) {
110 clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
111 do_release_oneshot = !is_oneshot_layer_active();
112 }
113#endif
114
98 switch (action.kind.id) { 115 switch (action.kind.id) {
99 /* Key and Mods */ 116 /* Key and Mods */
100 case ACT_LMODS: 117 case ACT_LMODS:
@@ -139,24 +156,37 @@ void process_action(keyrecord_t *record)
139 // Oneshot modifier 156 // Oneshot modifier
140 if (event.pressed) { 157 if (event.pressed) {
141 if (tap_count == 0) { 158 if (tap_count == 0) {
159 dprint("MODS_TAP: Oneshot: 0\n");
142 register_mods(mods); 160 register_mods(mods);
143 } 161 } else if (tap_count == 1) {
144 else if (tap_count == 1) {
145 dprint("MODS_TAP: Oneshot: start\n"); 162 dprint("MODS_TAP: Oneshot: start\n");
146 set_oneshot_mods(mods); 163 set_oneshot_mods(mods);
147 } 164 #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
148 else { 165 } else if (tap_count == ONESHOT_TAP_TOGGLE) {
166 dprint("MODS_TAP: Toggling oneshot");
167 clear_oneshot_mods();
168 set_oneshot_locked_mods(mods);
169 register_mods(mods);
170 #endif
171 } else {
149 register_mods(mods); 172 register_mods(mods);
150 } 173 }
151 } else { 174 } else {
152 if (tap_count == 0) { 175 if (tap_count == 0) {
153 clear_oneshot_mods(); 176 clear_oneshot_mods();
154 unregister_mods(mods); 177 unregister_mods(mods);
155 } 178 } else if (tap_count == 1) {
156 else if (tap_count == 1) {
157 // Retain Oneshot mods 179 // Retain Oneshot mods
158 } 180 #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
159 else { 181 if (mods & get_mods()) {
182 clear_oneshot_locked_mods();
183 clear_oneshot_mods();
184 unregister_mods(mods);
185 }
186 } else if (tap_count == ONESHOT_TAP_TOGGLE) {
187 // Toggle Oneshot Layer
188 #endif
189 } else {
160 clear_oneshot_mods(); 190 clear_oneshot_mods();
161 unregister_mods(mods); 191 unregister_mods(mods);
162 } 192 }
@@ -309,6 +339,44 @@ void process_action(keyrecord_t *record)
309 event.pressed ? layer_move(action.layer_tap.val) : 339 event.pressed ? layer_move(action.layer_tap.val) :
310 layer_clear(); 340 layer_clear();
311 break; 341 break;
342 #ifndef NO_ACTION_ONESHOT
343 case OP_ONESHOT:
344 // Oneshot modifier
345 #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
346 do_release_oneshot = false;
347 if (event.pressed) {
348 del_mods(get_oneshot_locked_mods());
349 if (get_oneshot_layer_state() == ONESHOT_TOGGLED) {
350 reset_oneshot_layer();
351 layer_off(action.layer_tap.val);
352 break;
353 } else if (tap_count < ONESHOT_TAP_TOGGLE) {
354 layer_on(action.layer_tap.val);
355 set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
356 }
357 } else {
358 add_mods(get_oneshot_locked_mods());
359 if (tap_count >= ONESHOT_TAP_TOGGLE) {
360 reset_oneshot_layer();
361 clear_oneshot_locked_mods();
362 set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED);
363 } else {
364 clear_oneshot_layer_state(ONESHOT_PRESSED);
365 }
366 }
367 #else
368 if (event.pressed) {
369 layer_on(action.layer_tap.val);
370 set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
371 } else {
372 clear_oneshot_layer_state(ONESHOT_PRESSED);
373 if (tap_count > 1) {
374 clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
375 }
376 }
377 #endif
378 break;
379 #endif
312 default: 380 default:
313 /* tap key */ 381 /* tap key */
314 if (event.pressed) { 382 if (event.pressed) {
@@ -372,6 +440,18 @@ void process_action(keyrecord_t *record)
372 default: 440 default:
373 break; 441 break;
374 } 442 }
443
444#ifndef NO_ACTION_ONESHOT
445 /* Because we switch layers after a oneshot event, we need to release the
446 * key before we leave the layer or no key up event will be generated.
447 */
448 if (do_release_oneshot && !(get_oneshot_layer_state() & ONESHOT_PRESSED ) ) {
449 record->event.pressed = false;
450 layer_on(get_oneshot_layer());
451 process_action(record);
452 layer_off(get_oneshot_layer());
453 }
454#endif
375} 455}
376 456
377 457
@@ -560,6 +640,7 @@ bool is_tap_key(keypos_t key)
560 switch (action.layer_tap.code) { 640 switch (action.layer_tap.code) {
561 case 0x00 ... 0xdf: 641 case 0x00 ... 0xdf:
562 case OP_TAP_TOGGLE: 642 case OP_TAP_TOGGLE:
643 case OP_ONESHOT:
563 return true; 644 return true;
564 } 645 }
565 return false; 646 return false;
diff --git a/tmk_core/common/action_code.h b/tmk_core/common/action_code.h
index 2b0b0b077..ca729aaec 100644
--- a/tmk_core/common/action_code.h
+++ b/tmk_core/common/action_code.h
@@ -76,7 +76,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
76 * 101E|LLLL|1111 0001 On/Off (0xF1) [NOT TAP] 76 * 101E|LLLL|1111 0001 On/Off (0xF1) [NOT TAP]
77 * 101E|LLLL|1111 0010 Off/On (0xF2) [NOT TAP] 77 * 101E|LLLL|1111 0010 Off/On (0xF2) [NOT TAP]
78 * 101E|LLLL|1111 0011 Set/Clear (0xF3) [NOT TAP] 78 * 101E|LLLL|1111 0011 Set/Clear (0xF3) [NOT TAP]
79 * 101E|LLLL|1111 xxxx Reserved (0xF4-FF) 79 * 101E|LLLL|1111 0100 One Shot Layer (0xF4) [TAP]
80 * 101E|LLLL|1111 xxxx Reserved (0xF5-FF)
80 * ELLLL: layer 0-31(E: extra bit for layer 16-31) 81 * ELLLL: layer 0-31(E: extra bit for layer 16-31)
81 * 82 *
82 * 83 *
@@ -250,6 +251,7 @@ enum layer_pram_tap_op {
250 OP_ON_OFF, 251 OP_ON_OFF,
251 OP_OFF_ON, 252 OP_OFF_ON,
252 OP_SET_CLEAR, 253 OP_SET_CLEAR,
254 OP_ONESHOT,
253}; 255};
254#define ACTION_LAYER_BITOP(op, part, bits, on) (ACT_LAYER<<12 | (op)<<10 | (on)<<8 | (part)<<5 | ((bits)&0x1f)) 256#define ACTION_LAYER_BITOP(op, part, bits, on) (ACT_LAYER<<12 | (op)<<10 | (on)<<8 | (part)<<5 | ((bits)&0x1f))
255#define ACTION_LAYER_TAP(layer, key) (ACT_LAYER_TAP<<12 | (layer)<<8 | (key)) 257#define ACTION_LAYER_TAP(layer, key) (ACT_LAYER_TAP<<12 | (layer)<<8 | (key))
@@ -266,6 +268,7 @@ enum layer_pram_tap_op {
266#define ACTION_LAYER_ON_OFF(layer) ACTION_LAYER_TAP((layer), OP_ON_OFF) 268#define ACTION_LAYER_ON_OFF(layer) ACTION_LAYER_TAP((layer), OP_ON_OFF)
267#define ACTION_LAYER_OFF_ON(layer) ACTION_LAYER_TAP((layer), OP_OFF_ON) 269#define ACTION_LAYER_OFF_ON(layer) ACTION_LAYER_TAP((layer), OP_OFF_ON)
268#define ACTION_LAYER_SET_CLEAR(layer) ACTION_LAYER_TAP((layer), OP_SET_CLEAR) 270#define ACTION_LAYER_SET_CLEAR(layer) ACTION_LAYER_TAP((layer), OP_SET_CLEAR)
271#define ACTION_LAYER_ONESHOT(layer) ACTION_LAYER_TAP((layer), OP_ONESHOT)
269#define ACTION_LAYER_MODS(layer, mods) ACTION_LAYER_TAP((layer), 0xe0 | ((mods)&0x0f)) 272#define ACTION_LAYER_MODS(layer, mods) ACTION_LAYER_TAP((layer), 0xe0 | ((mods)&0x0f))
270/* With Tapping */ 273/* With Tapping */
271#define ACTION_LAYER_TAP_KEY(layer, key) ACTION_LAYER_TAP((layer), (key)) 274#define ACTION_LAYER_TAP_KEY(layer, key) ACTION_LAYER_TAP((layer), (key))
diff --git a/tmk_core/common/action_util.c b/tmk_core/common/action_util.c
index a2d6577b2..61ff202be 100644
--- a/tmk_core/common/action_util.c
+++ b/tmk_core/common/action_util.c
@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
18#include "report.h" 18#include "report.h"
19#include "debug.h" 19#include "debug.h"
20#include "action_util.h" 20#include "action_util.h"
21#include "action_layer.h"
21#include "timer.h" 22#include "timer.h"
22 23
23static inline void add_key_byte(uint8_t code); 24static inline void add_key_byte(uint8_t code);
@@ -47,11 +48,70 @@ report_keyboard_t *keyboard_report = &(report_keyboard_t){};
47 48
48#ifndef NO_ACTION_ONESHOT 49#ifndef NO_ACTION_ONESHOT
49static int8_t oneshot_mods = 0; 50static int8_t oneshot_mods = 0;
51static int8_t oneshot_locked_mods = 0;
52int8_t get_oneshot_locked_mods(void) { return oneshot_locked_mods; }
53void set_oneshot_locked_mods(int8_t mods) { oneshot_locked_mods = mods; }
54void clear_oneshot_locked_mods(void) { oneshot_locked_mods = 0; }
50#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) 55#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
51static int16_t oneshot_time = 0; 56static int16_t oneshot_time = 0;
57inline bool has_oneshot_mods_timed_out() {
58 return TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT;
59}
52#endif 60#endif
53#endif 61#endif
54 62
63/* oneshot layer */
64#ifndef NO_ACTION_ONESHOT
65/* oneshot_layer_data bits
66* LLLL LSSS
67* where:
68* L => are layer bits
69* S => oneshot state bits
70*/
71static int8_t oneshot_layer_data = 0;
72
73inline uint8_t get_oneshot_layer(void) { return oneshot_layer_data >> 3; }
74inline uint8_t get_oneshot_layer_state(void) { return oneshot_layer_data & 0b111; }
75
76#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
77static int16_t oneshot_layer_time = 0;
78inline bool has_oneshot_layer_timed_out() {
79 return TIMER_DIFF_16(timer_read(), oneshot_layer_time) >= ONESHOT_TIMEOUT &&
80 !(get_oneshot_layer_state() & ONESHOT_TOGGLED);
81}
82#endif
83
84/* Oneshot layer */
85void set_oneshot_layer(uint8_t layer, uint8_t state)
86{
87 oneshot_layer_data = layer << 3 | state;
88 layer_on(layer);
89#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
90 oneshot_layer_time = timer_read();
91#endif
92}
93void reset_oneshot_layer(void) {
94 oneshot_layer_data = 0;
95#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
96 oneshot_layer_time = 0;
97#endif
98}
99void clear_oneshot_layer_state(oneshot_fullfillment_t state)
100{
101 uint8_t start_state = oneshot_layer_data;
102 oneshot_layer_data &= ~state;
103 if (!get_oneshot_layer_state() && start_state != oneshot_layer_data) {
104 layer_off(get_oneshot_layer());
105#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
106 oneshot_layer_time = 0;
107#endif
108 }
109}
110bool is_oneshot_layer_active(void)
111{
112 return get_oneshot_layer_state();
113}
114#endif
55 115
56void send_keyboard_report(void) { 116void send_keyboard_report(void) {
57 keyboard_report->mods = real_mods; 117 keyboard_report->mods = real_mods;
@@ -60,7 +120,7 @@ void send_keyboard_report(void) {
60#ifndef NO_ACTION_ONESHOT 120#ifndef NO_ACTION_ONESHOT
61 if (oneshot_mods) { 121 if (oneshot_mods) {
62#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) 122#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
63 if (TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT) { 123 if (has_oneshot_mods_timed_out()) {
64 dprintf("Oneshot: timeout\n"); 124 dprintf("Oneshot: timeout\n");
65 clear_oneshot_mods(); 125 clear_oneshot_mods();
66 } 126 }
@@ -70,6 +130,7 @@ void send_keyboard_report(void) {
70 clear_oneshot_mods(); 130 clear_oneshot_mods();
71 } 131 }
72 } 132 }
133
73#endif 134#endif
74 host_keyboard_send(keyboard_report); 135 host_keyboard_send(keyboard_report);
75} 136}
@@ -143,11 +204,12 @@ void clear_oneshot_mods(void)
143 oneshot_time = 0; 204 oneshot_time = 0;
144#endif 205#endif
145} 206}
207uint8_t get_oneshot_mods(void)
208{
209 return oneshot_mods;
210}
146#endif 211#endif
147 212
148
149
150
151/* 213/*
152 * inspect keyboard state 214 * inspect keyboard state
153 */ 215 */
diff --git a/tmk_core/common/action_util.h b/tmk_core/common/action_util.h
index 1a95cec10..dd0c4c2bf 100644
--- a/tmk_core/common/action_util.h
+++ b/tmk_core/common/action_util.h
@@ -56,10 +56,30 @@ void clear_macro_mods(void);
56 56
57/* oneshot modifier */ 57/* oneshot modifier */
58void set_oneshot_mods(uint8_t mods); 58void set_oneshot_mods(uint8_t mods);
59uint8_t get_oneshot_mods(void);
59void clear_oneshot_mods(void); 60void clear_oneshot_mods(void);
60void oneshot_toggle(void); 61void oneshot_toggle(void);
61void oneshot_enable(void); 62void oneshot_enable(void);
62void oneshot_disable(void); 63void oneshot_disable(void);
64bool has_oneshot_mods_timed_out(void);
65
66int8_t get_oneshot_locked_mods(void);
67void set_oneshot_locked_mods(int8_t mods);
68void clear_oneshot_locked_mods(void);
69
70typedef enum {
71 ONESHOT_PRESSED = 0b01,
72 ONESHOT_OTHER_KEY_PRESSED = 0b10,
73 ONESHOT_START = 0b11,
74 ONESHOT_TOGGLED = 0b100
75} oneshot_fullfillment_t;
76void set_oneshot_layer(uint8_t layer, uint8_t state);
77uint8_t get_oneshot_layer(void);
78void clear_oneshot_layer_state(oneshot_fullfillment_t state);
79void reset_oneshot_layer(void);
80bool is_oneshot_layer_active(void);
81uint8_t get_oneshot_layer_state(void);
82bool has_oneshot_layer_timed_out(void);
63 83
64/* inspect */ 84/* inspect */
65uint8_t has_anykey(void); 85uint8_t has_anykey(void);