diff options
Diffstat (limited to 'tmk_core/common')
-rw-r--r-- | tmk_core/common/action.c | 97 | ||||
-rw-r--r-- | tmk_core/common/action_code.h | 5 | ||||
-rw-r--r-- | tmk_core/common/action_util.c | 70 | ||||
-rw-r--r-- | tmk_core/common/action_util.h | 20 |
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 | ||
75 | void process_action(keyrecord_t *record) | 75 | void 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 | ||
23 | static inline void add_key_byte(uint8_t code); | 24 | static 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 |
49 | static int8_t oneshot_mods = 0; | 50 | static int8_t oneshot_mods = 0; |
51 | static int8_t oneshot_locked_mods = 0; | ||
52 | int8_t get_oneshot_locked_mods(void) { return oneshot_locked_mods; } | ||
53 | void set_oneshot_locked_mods(int8_t mods) { oneshot_locked_mods = mods; } | ||
54 | void 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)) |
51 | static int16_t oneshot_time = 0; | 56 | static int16_t oneshot_time = 0; |
57 | inline 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 | */ | ||
71 | static int8_t oneshot_layer_data = 0; | ||
72 | |||
73 | inline uint8_t get_oneshot_layer(void) { return oneshot_layer_data >> 3; } | ||
74 | inline uint8_t get_oneshot_layer_state(void) { return oneshot_layer_data & 0b111; } | ||
75 | |||
76 | #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) | ||
77 | static int16_t oneshot_layer_time = 0; | ||
78 | inline 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 */ | ||
85 | void 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 | } | ||
93 | void 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 | } | ||
99 | void 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 | } | ||
110 | bool is_oneshot_layer_active(void) | ||
111 | { | ||
112 | return get_oneshot_layer_state(); | ||
113 | } | ||
114 | #endif | ||
55 | 115 | ||
56 | void send_keyboard_report(void) { | 116 | void 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 | } |
207 | uint8_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 */ |
58 | void set_oneshot_mods(uint8_t mods); | 58 | void set_oneshot_mods(uint8_t mods); |
59 | uint8_t get_oneshot_mods(void); | ||
59 | void clear_oneshot_mods(void); | 60 | void clear_oneshot_mods(void); |
60 | void oneshot_toggle(void); | 61 | void oneshot_toggle(void); |
61 | void oneshot_enable(void); | 62 | void oneshot_enable(void); |
62 | void oneshot_disable(void); | 63 | void oneshot_disable(void); |
64 | bool has_oneshot_mods_timed_out(void); | ||
65 | |||
66 | int8_t get_oneshot_locked_mods(void); | ||
67 | void set_oneshot_locked_mods(int8_t mods); | ||
68 | void clear_oneshot_locked_mods(void); | ||
69 | |||
70 | typedef enum { | ||
71 | ONESHOT_PRESSED = 0b01, | ||
72 | ONESHOT_OTHER_KEY_PRESSED = 0b10, | ||
73 | ONESHOT_START = 0b11, | ||
74 | ONESHOT_TOGGLED = 0b100 | ||
75 | } oneshot_fullfillment_t; | ||
76 | void set_oneshot_layer(uint8_t layer, uint8_t state); | ||
77 | uint8_t get_oneshot_layer(void); | ||
78 | void clear_oneshot_layer_state(oneshot_fullfillment_t state); | ||
79 | void reset_oneshot_layer(void); | ||
80 | bool is_oneshot_layer_active(void); | ||
81 | uint8_t get_oneshot_layer_state(void); | ||
82 | bool has_oneshot_layer_timed_out(void); | ||
63 | 83 | ||
64 | /* inspect */ | 84 | /* inspect */ |
65 | uint8_t has_anykey(void); | 85 | uint8_t has_anykey(void); |