aboutsummaryrefslogtreecommitdiff
path: root/quantum/process_keycode
diff options
context:
space:
mode:
Diffstat (limited to 'quantum/process_keycode')
-rw-r--r--quantum/process_keycode/process_auto_shift.c199
-rw-r--r--quantum/process_keycode/process_auto_shift.h1
-rw-r--r--quantum/process_keycode/process_joystick.c8
-rw-r--r--quantum/process_keycode/process_midi.c25
-rw-r--r--quantum/process_keycode/process_midi.h2
-rw-r--r--quantum/process_keycode/process_sequencer.c62
-rw-r--r--quantum/process_keycode/process_sequencer.h21
7 files changed, 256 insertions, 62 deletions
diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c
index b1267922c..a2d315408 100644
--- a/quantum/process_keycode/process_auto_shift.c
+++ b/quantum/process_keycode/process_auto_shift.c
@@ -16,48 +16,149 @@
16 16
17#ifdef AUTO_SHIFT_ENABLE 17#ifdef AUTO_SHIFT_ENABLE
18 18
19# include <stdbool.h>
19# include <stdio.h> 20# include <stdio.h>
20 21
21# include "process_auto_shift.h" 22# include "process_auto_shift.h"
22 23
23static bool autoshift_enabled = true;
24static uint16_t autoshift_time = 0; 24static uint16_t autoshift_time = 0;
25static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT; 25static uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT;
26static uint16_t autoshift_lastkey = KC_NO; 26static uint16_t autoshift_lastkey = KC_NO;
27static struct {
28 // Whether autoshift is enabled.
29 bool enabled : 1;
30 // Whether the last auto-shifted key was released after the timeout. This
31 // is used to replicate the last key for a tap-then-hold.
32 bool lastshifted : 1;
33 // Whether an auto-shiftable key has been pressed but not processed.
34 bool in_progress : 1;
35 // Whether the auto-shifted keypress has been registered.
36 bool holding_shift : 1;
37} autoshift_flags = {true, false, false, false};
38
39/** \brief Record the press of an autoshiftable key
40 *
41 * \return Whether the record should be further processed.
42 */
43static bool autoshift_press(uint16_t keycode, uint16_t now, keyrecord_t *record) {
44 if (!autoshift_flags.enabled) {
45 return true;
46 }
47
48# ifndef AUTO_SHIFT_MODIFIERS
49 if (get_mods() & (~MOD_BIT(KC_LSFT))) {
50 return true;
51 }
52# endif
53# ifdef AUTO_SHIFT_REPEAT
54 const uint16_t elapsed = TIMER_DIFF_16(now, autoshift_time);
55# ifndef AUTO_SHIFT_NO_AUTO_REPEAT
56 if (!autoshift_flags.lastshifted) {
57# endif
58 if (elapsed < TAPPING_TERM && keycode == autoshift_lastkey) {
59 // Allow a tap-then-hold for keyrepeat.
60 if (!autoshift_flags.lastshifted) {
61 register_code(autoshift_lastkey);
62 } else {
63 // Simulate pressing the shift key.
64 add_weak_mods(MOD_BIT(KC_LSFT));
65 register_code(autoshift_lastkey);
66 }
67 return false;
68 }
69# ifndef AUTO_SHIFT_NO_AUTO_REPEAT
70 }
71# endif
72# endif
27 73
28void autoshift_flush(void) { 74 // Record the keycode so we can simulate it later.
29 if (autoshift_lastkey != KC_NO) { 75 autoshift_lastkey = keycode;
30 uint16_t elapsed = timer_elapsed(autoshift_time); 76 autoshift_time = now;
77 autoshift_flags.in_progress = true;
31 78
32 if (elapsed > autoshift_timeout) { 79# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)
33 tap_code16(LSFT(autoshift_lastkey)); 80 clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
81# endif
82 return false;
83}
84
85/** \brief Registers an autoshiftable key under the right conditions
86 *
87 * If the autoshift delay has elapsed, register a shift and the key.
88 *
89 * If the autoshift key is released before the delay has elapsed, register the
90 * key without a shift.
91 */
92static void autoshift_end(uint16_t keycode, uint16_t now, bool matrix_trigger) {
93 // Called on key down with KC_NO, auto-shifted key up, and timeout.
94 if (autoshift_flags.in_progress) {
95 // Process the auto-shiftable key.
96 autoshift_flags.in_progress = false;
97
98 // Time since the initial press was recorded.
99 const uint16_t elapsed = TIMER_DIFF_16(now, autoshift_time);
100 if (elapsed < autoshift_timeout) {
101 register_code(autoshift_lastkey);
102 autoshift_flags.lastshifted = false;
34 } else { 103 } else {
35 tap_code(autoshift_lastkey); 104 // Simulate pressing the shift key.
105 add_weak_mods(MOD_BIT(KC_LSFT));
106 register_code(autoshift_lastkey);
107 autoshift_flags.lastshifted = true;
108# if defined(AUTO_SHIFT_REPEAT) && !defined(AUTO_SHIFT_NO_AUTO_REPEAT)
109 if (matrix_trigger) {
110 // Prevents release.
111 return;
112 }
113# endif
36 } 114 }
37 115
38 autoshift_time = 0; 116# if TAP_CODE_DELAY > 0
39 autoshift_lastkey = KC_NO; 117 wait_ms(TAP_CODE_DELAY);
118# endif
119 unregister_code(autoshift_lastkey);
120 del_weak_mods(MOD_BIT(KC_LSFT));
121 } else {
122 // Release after keyrepeat.
123 unregister_code(keycode);
124 if (keycode == autoshift_lastkey) {
125 // This will only fire when the key was the last auto-shiftable
126 // pressed. That prevents aaaaBBBB then releasing a from unshifting
127 // later Bs (if B wasn't auto-shiftable).
128 del_weak_mods(MOD_BIT(KC_LSFT));
129 }
40 } 130 }
131 send_keyboard_report(); // del_weak_mods doesn't send one.
132 // Roll the autoshift_time forward for detecting tap-and-hold.
133 autoshift_time = now;
41} 134}
42 135
43void autoshift_on(uint16_t keycode) { 136/** \brief Simulates auto-shifted key releases when timeout is hit
44 autoshift_time = timer_read(); 137 *
45 autoshift_lastkey = keycode; 138 * Can be called from \c matrix_scan_user so that auto-shifted keys are sent
139 * immediately after the timeout has expired, rather than waiting for the key
140 * to be released.
141 */
142void autoshift_matrix_scan(void) {
143 if (autoshift_flags.in_progress) {
144 const uint16_t now = timer_read();
145 const uint16_t elapsed = TIMER_DIFF_16(now, autoshift_time);
146 if (elapsed >= autoshift_timeout) {
147 autoshift_end(autoshift_lastkey, now, true);
148 }
149 }
46} 150}
47 151
48void autoshift_toggle(void) { 152void autoshift_toggle(void) {
49 if (autoshift_enabled) { 153 autoshift_flags.enabled = !autoshift_flags.enabled;
50 autoshift_enabled = false; 154 del_weak_mods(MOD_BIT(KC_LSFT));
51 autoshift_flush();
52 } else {
53 autoshift_enabled = true;
54 }
55} 155}
56 156
57void autoshift_enable(void) { autoshift_enabled = true; } 157void autoshift_enable(void) { autoshift_flags.enabled = true; }
158
58void autoshift_disable(void) { 159void autoshift_disable(void) {
59 autoshift_enabled = false; 160 autoshift_flags.enabled = false;
60 autoshift_flush(); 161 del_weak_mods(MOD_BIT(KC_LSFT));
61} 162}
62 163
63# ifndef AUTO_SHIFT_NO_SETUP 164# ifndef AUTO_SHIFT_NO_SETUP
@@ -70,19 +171,30 @@ void autoshift_timer_report(void) {
70} 171}
71# endif 172# endif
72 173
73bool get_autoshift_state(void) { return autoshift_enabled; } 174bool get_autoshift_state(void) { return autoshift_flags.enabled; }
74 175
75uint16_t get_autoshift_timeout(void) { return autoshift_timeout; } 176uint16_t get_autoshift_timeout(void) { return autoshift_timeout; }
76 177
77void set_autoshift_timeout(uint16_t timeout) { autoshift_timeout = timeout; } 178void set_autoshift_timeout(uint16_t timeout) { autoshift_timeout = timeout; }
78 179
79bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { 180bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
181 // Note that record->event.time isn't reliable, see:
182 // https://github.com/qmk/qmk_firmware/pull/9826#issuecomment-733559550
183 const uint16_t now = timer_read();
184
80 if (record->event.pressed) { 185 if (record->event.pressed) {
186 if (autoshift_flags.in_progress) {
187 // Evaluate previous key if there is one. Doing this elsewhere is
188 // more complicated and easier to break.
189 autoshift_end(KC_NO, now, false);
190 }
191 // For pressing another key while keyrepeating shifted autoshift.
192 del_weak_mods(MOD_BIT(KC_LSFT));
193
81 switch (keycode) { 194 switch (keycode) {
82 case KC_ASTG: 195 case KC_ASTG:
83 autoshift_toggle(); 196 autoshift_toggle();
84 return true; 197 return true;
85
86 case KC_ASON: 198 case KC_ASON:
87 autoshift_enable(); 199 autoshift_enable();
88 return true; 200 return true;
@@ -102,41 +214,28 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
102 autoshift_timer_report(); 214 autoshift_timer_report();
103 return true; 215 return true;
104# endif 216# endif
217 }
218 }
219
220 switch (keycode) {
105# ifndef NO_AUTO_SHIFT_ALPHA 221# ifndef NO_AUTO_SHIFT_ALPHA
106 case KC_A ... KC_Z: 222 case KC_A ... KC_Z:
107# endif 223# endif
108# ifndef NO_AUTO_SHIFT_NUMERIC 224# ifndef NO_AUTO_SHIFT_NUMERIC
109 case KC_1 ... KC_0: 225 case KC_1 ... KC_0:
110# endif 226# endif
111# ifndef NO_AUTO_SHIFT_SPECIAL 227# ifndef NO_AUTO_SHIFT_SPECIAL
112 case KC_TAB: 228 case KC_TAB:
113 case KC_MINUS ... KC_SLASH: 229 case KC_MINUS ... KC_SLASH:
114 case KC_NONUS_BSLASH: 230 case KC_NONUS_BSLASH:
115# endif
116 autoshift_flush();
117 if (!autoshift_enabled) return true;
118
119# ifndef AUTO_SHIFT_MODIFIERS
120 if (get_mods()) {
121 return true;
122 }
123# endif
124 autoshift_on(keycode);
125
126 // We need some extra handling here for OSL edge cases
127# if !defined(NO_ACTION_ONESHOT) && !defined(NO_ACTION_TAPPING)
128 clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
129# endif 231# endif
232 if (record->event.pressed) {
233 return autoshift_press(keycode, now, record);
234 } else {
235 autoshift_end(keycode, now, false);
130 return false; 236 return false;
131 237 }
132 default:
133 autoshift_flush();
134 return true;
135 }
136 } else {
137 autoshift_flush();
138 } 238 }
139
140 return true; 239 return true;
141} 240}
142 241
diff --git a/quantum/process_keycode/process_auto_shift.h b/quantum/process_keycode/process_auto_shift.h
index e86c4658e..5b2718f11 100644
--- a/quantum/process_keycode/process_auto_shift.h
+++ b/quantum/process_keycode/process_auto_shift.h
@@ -30,3 +30,4 @@ void autoshift_toggle(void);
30bool get_autoshift_state(void); 30bool get_autoshift_state(void);
31uint16_t get_autoshift_timeout(void); 31uint16_t get_autoshift_timeout(void);
32void set_autoshift_timeout(uint16_t timeout); 32void set_autoshift_timeout(uint16_t timeout);
33void autoshift_matrix_scan(void);
diff --git a/quantum/process_keycode/process_joystick.c b/quantum/process_keycode/process_joystick.c
index 5778a7434..3ffaf42bf 100644
--- a/quantum/process_keycode/process_joystick.c
+++ b/quantum/process_keycode/process_joystick.c
@@ -129,17 +129,17 @@ bool process_joystick_analogread_quantum() {
129 // test the converted value against the lower range 129 // test the converted value against the lower range
130 int32_t ref = joystick_axes[axis_index].mid_digit; 130 int32_t ref = joystick_axes[axis_index].mid_digit;
131 int32_t range = joystick_axes[axis_index].min_digit; 131 int32_t range = joystick_axes[axis_index].min_digit;
132 int32_t ranged_val = ((axis_val - ref) * -127) / (range - ref); 132 int32_t ranged_val = ((axis_val - ref) * -JOYSTICK_RESOLUTION) / (range - ref);
133 133
134 if (ranged_val > 0) { 134 if (ranged_val > 0) {
135 // the value is in the higher range 135 // the value is in the higher range
136 range = joystick_axes[axis_index].max_digit; 136 range = joystick_axes[axis_index].max_digit;
137 ranged_val = ((axis_val - ref) * 127) / (range - ref); 137 ranged_val = ((axis_val - ref) * JOYSTICK_RESOLUTION) / (range - ref);
138 } 138 }
139 139
140 // clamp the result in the valid range 140 // clamp the result in the valid range
141 ranged_val = ranged_val < -127 ? -127 : ranged_val; 141 ranged_val = ranged_val < -JOYSTICK_RESOLUTION ? -JOYSTICK_RESOLUTION : ranged_val;
142 ranged_val = ranged_val > 127 ? 127 : ranged_val; 142 ranged_val = ranged_val > JOYSTICK_RESOLUTION ? JOYSTICK_RESOLUTION : ranged_val;
143 143
144 if (ranged_val != joystick_status.axes[axis_index]) { 144 if (ranged_val != joystick_status.axes[axis_index]) {
145 joystick_status.axes[axis_index] = ranged_val; 145 joystick_status.axes[axis_index] = ranged_val;
diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c
index e52577014..8e2fb955e 100644
--- a/quantum/process_keycode/process_midi.c
+++ b/quantum/process_keycode/process_midi.c
@@ -41,12 +41,12 @@ static int8_t midi_modulation_step;
41static uint16_t midi_modulation_timer; 41static uint16_t midi_modulation_timer;
42midi_config_t midi_config; 42midi_config_t midi_config;
43 43
44inline uint8_t compute_velocity(uint8_t setting) { return (setting + 1) * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN + 1)); } 44inline uint8_t compute_velocity(uint8_t setting) { return setting * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN)); }
45 45
46void midi_init(void) { 46void midi_init(void) {
47 midi_config.octave = MI_OCT_2 - MIDI_OCTAVE_MIN; 47 midi_config.octave = MI_OCT_2 - MIDI_OCTAVE_MIN;
48 midi_config.transpose = 0; 48 midi_config.transpose = 0;
49 midi_config.velocity = (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN); 49 midi_config.velocity = 127;
50 midi_config.channel = 0; 50 midi_config.channel = 0;
51 midi_config.modulation_interval = 8; 51 midi_config.modulation_interval = 8;
52 52
@@ -66,7 +66,7 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) {
66 case MIDI_TONE_MIN ... MIDI_TONE_MAX: { 66 case MIDI_TONE_MIN ... MIDI_TONE_MAX: {
67 uint8_t channel = midi_config.channel; 67 uint8_t channel = midi_config.channel;
68 uint8_t tone = keycode - MIDI_TONE_MIN; 68 uint8_t tone = keycode - MIDI_TONE_MIN;
69 uint8_t velocity = compute_velocity(midi_config.velocity); 69 uint8_t velocity = midi_config.velocity;
70 if (record->event.pressed) { 70 if (record->event.pressed) {
71 if (tone_status[tone] == MIDI_INVALID_NOTE) { 71 if (tone_status[tone] == MIDI_INVALID_NOTE) {
72 uint8_t note = midi_compute_note(keycode); 72 uint8_t note = midi_compute_note(keycode);
@@ -124,19 +124,30 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) {
124 return false; 124 return false;
125 case MIDI_VELOCITY_MIN ... MIDI_VELOCITY_MAX: 125 case MIDI_VELOCITY_MIN ... MIDI_VELOCITY_MAX:
126 if (record->event.pressed) { 126 if (record->event.pressed) {
127 midi_config.velocity = keycode - MIDI_VELOCITY_MIN; 127 midi_config.velocity = compute_velocity(keycode - MIDI_VELOCITY_MIN);
128 dprintf("midi velocity %d\n", midi_config.velocity); 128 dprintf("midi velocity %d\n", midi_config.velocity);
129 } 129 }
130 return false; 130 return false;
131 case MI_VELD: 131 case MI_VELD:
132 if (record->event.pressed && midi_config.velocity > 0) { 132 if (record->event.pressed && midi_config.velocity > 0) {
133 midi_config.velocity--; 133 if (midi_config.velocity == 127) {
134 midi_config.velocity -= 10;
135 } else if (midi_config.velocity > 12) {
136 midi_config.velocity -= 13;
137 } else {
138 midi_config.velocity = 0;
139 }
140
134 dprintf("midi velocity %d\n", midi_config.velocity); 141 dprintf("midi velocity %d\n", midi_config.velocity);
135 } 142 }
136 return false; 143 return false;
137 case MI_VELU: 144 case MI_VELU:
138 if (record->event.pressed) { 145 if (record->event.pressed && midi_config.velocity < 127) {
139 midi_config.velocity++; 146 if (midi_config.velocity < 115) {
147 midi_config.velocity += 13;
148 } else {
149 midi_config.velocity = 127;
150 }
140 dprintf("midi velocity %d\n", midi_config.velocity); 151 dprintf("midi velocity %d\n", midi_config.velocity);
141 } 152 }
142 return false; 153 return false;
diff --git a/quantum/process_keycode/process_midi.h b/quantum/process_keycode/process_midi.h
index 0007b3ed2..ef5661dd4 100644
--- a/quantum/process_keycode/process_midi.h
+++ b/quantum/process_keycode/process_midi.h
@@ -35,7 +35,7 @@ typedef union {
35 struct { 35 struct {
36 uint8_t octave : 4; 36 uint8_t octave : 4;
37 int8_t transpose : 4; 37 int8_t transpose : 4;
38 uint8_t velocity : 4; 38 uint8_t velocity : 7;
39 uint8_t channel : 4; 39 uint8_t channel : 4;
40 uint8_t modulation_interval : 4; 40 uint8_t modulation_interval : 4;
41 }; 41 };
diff --git a/quantum/process_keycode/process_sequencer.c b/quantum/process_keycode/process_sequencer.c
new file mode 100644
index 000000000..334b4c009
--- /dev/null
+++ b/quantum/process_keycode/process_sequencer.c
@@ -0,0 +1,62 @@
1/* Copyright 2020 Rodolphe Belouin
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#include "process_sequencer.h"
18
19bool process_sequencer(uint16_t keycode, keyrecord_t *record) {
20 if (record->event.pressed) {
21 switch (keycode) {
22 case SQ_ON:
23 sequencer_on();
24 return false;
25 case SQ_OFF:
26 sequencer_off();
27 return false;
28 case SQ_TOG:
29 sequencer_toggle();
30 return false;
31 case SQ_TMPD:
32 sequencer_decrease_tempo();
33 return false;
34 case SQ_TMPU:
35 sequencer_increase_tempo();
36 return false;
37 case SEQUENCER_RESOLUTION_MIN ... SEQUENCER_RESOLUTION_MAX:
38 sequencer_set_resolution(keycode - SEQUENCER_RESOLUTION_MIN);
39 return false;
40 case SQ_RESD:
41 sequencer_decrease_resolution();
42 return false;
43 case SQ_RESU:
44 sequencer_increase_resolution();
45 return false;
46 case SQ_SALL:
47 sequencer_set_all_steps_on();
48 return false;
49 case SQ_SCLR:
50 sequencer_set_all_steps_off();
51 return false;
52 case SEQUENCER_STEP_MIN ... SEQUENCER_STEP_MAX:
53 sequencer_toggle_step(keycode - SEQUENCER_STEP_MIN);
54 return false;
55 case SEQUENCER_TRACK_MIN ... SEQUENCER_TRACK_MAX:
56 sequencer_toggle_single_active_track(keycode - SEQUENCER_TRACK_MIN);
57 return false;
58 }
59 }
60
61 return true;
62}
diff --git a/quantum/process_keycode/process_sequencer.h b/quantum/process_keycode/process_sequencer.h
new file mode 100644
index 000000000..2b85f2429
--- /dev/null
+++ b/quantum/process_keycode/process_sequencer.h
@@ -0,0 +1,21 @@
1/* Copyright 2020 Rodolphe Belouin
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#pragma once
18
19#include "quantum.h"
20
21bool process_sequencer(uint16_t keycode, keyrecord_t *record);