aboutsummaryrefslogtreecommitdiff
path: root/quantum/process_keycode
diff options
context:
space:
mode:
authorskullY <skullydazed@gmail.com>2019-08-30 11:19:03 -0700
committerskullydazed <skullydazed@users.noreply.github.com>2019-08-30 15:01:52 -0700
commitb624f32f944acdc59dcb130674c09090c5c404cb (patch)
treebc13adbba137d122d9a2c2fb2fafcbb08ac10e25 /quantum/process_keycode
parent61af76a10d00aba185b8338604171de490a13e3b (diff)
downloadqmk_firmware-b624f32f944acdc59dcb130674c09090c5c404cb.tar.gz
qmk_firmware-b624f32f944acdc59dcb130674c09090c5c404cb.zip
clang-format changes
Diffstat (limited to 'quantum/process_keycode')
-rw-r--r--quantum/process_keycode/process_audio.c31
-rw-r--r--quantum/process_keycode/process_auto_shift.c296
-rw-r--r--quantum/process_keycode/process_auto_shift.h2
-rw-r--r--quantum/process_keycode/process_clicky.c131
-rw-r--r--quantum/process_keycode/process_combo.c259
-rw-r--r--quantum/process_keycode/process_combo.h28
-rw-r--r--quantum/process_keycode/process_key_lock.c48
-rw-r--r--quantum/process_keycode/process_key_lock.h2
-rw-r--r--quantum/process_keycode/process_leader.c86
-rw-r--r--quantum/process_keycode/process_leader.h7
-rw-r--r--quantum/process_keycode/process_midi.c115
-rw-r--r--quantum/process_keycode/process_midi.h30
-rw-r--r--quantum/process_keycode/process_music.c354
-rw-r--r--quantum/process_keycode/process_music.h28
-rw-r--r--quantum/process_keycode/process_printer.c443
-rw-r--r--quantum/process_keycode/process_printer_bb.c435
-rw-r--r--quantum/process_keycode/process_space_cadet.c175
-rw-r--r--quantum/process_keycode/process_steno.c208
-rw-r--r--quantum/process_keycode/process_steno.h8
-rw-r--r--quantum/process_keycode/process_tap_dance.c268
-rw-r--r--quantum/process_keycode/process_tap_dance.h113
-rw-r--r--quantum/process_keycode/process_terminal.c271
-rw-r--r--quantum/process_keycode/process_terminal.h2
-rw-r--r--quantum/process_keycode/process_ucis.c213
-rw-r--r--quantum/process_keycode/process_ucis.h24
-rw-r--r--quantum/process_keycode/process_unicode.c12
-rw-r--r--quantum/process_keycode/process_unicode_common.c321
-rw-r--r--quantum/process_keycode/process_unicode_common.h246
-rw-r--r--quantum/process_keycode/process_unicodemap.c95
-rw-r--r--quantum/process_keycode/process_unicodemap.h4
30 files changed, 2028 insertions, 2227 deletions
diff --git a/quantum/process_keycode/process_audio.c b/quantum/process_keycode/process_audio.c
index 0a25aa535..3b5fa8490 100644
--- a/quantum/process_keycode/process_audio.c
+++ b/quantum/process_keycode/process_audio.c
@@ -2,30 +2,28 @@
2#include "process_audio.h" 2#include "process_audio.h"
3 3
4#ifndef VOICE_CHANGE_SONG 4#ifndef VOICE_CHANGE_SONG
5 #define VOICE_CHANGE_SONG SONG(VOICE_CHANGE_SOUND) 5# define VOICE_CHANGE_SONG SONG(VOICE_CHANGE_SOUND)
6#endif 6#endif
7float voice_change_song[][2] = VOICE_CHANGE_SONG; 7float voice_change_song[][2] = VOICE_CHANGE_SONG;
8 8
9#ifndef PITCH_STANDARD_A 9#ifndef PITCH_STANDARD_A
10 #define PITCH_STANDARD_A 440.0f 10# define PITCH_STANDARD_A 440.0f
11#endif 11#endif
12 12
13float compute_freq_for_midi_note(uint8_t note) 13float compute_freq_for_midi_note(uint8_t note) {
14{
15 // https://en.wikipedia.org/wiki/MIDI_tuning_standard 14 // https://en.wikipedia.org/wiki/MIDI_tuning_standard
16 return pow(2.0, (note - 69) / 12.0) * PITCH_STANDARD_A; 15 return pow(2.0, (note - 69) / 12.0) * PITCH_STANDARD_A;
17} 16}
18 17
19bool process_audio(uint16_t keycode, keyrecord_t *record) { 18bool process_audio(uint16_t keycode, keyrecord_t *record) {
20
21 if (keycode == AU_ON && record->event.pressed) { 19 if (keycode == AU_ON && record->event.pressed) {
22 audio_on(); 20 audio_on();
23 return false; 21 return false;
24 } 22 }
25 23
26 if (keycode == AU_OFF && record->event.pressed) { 24 if (keycode == AU_OFF && record->event.pressed) {
27 audio_off(); 25 audio_off();
28 return false; 26 return false;
29 } 27 }
30 28
31 if (keycode == AU_TOG && record->event.pressed) { 29 if (keycode == AU_TOG && record->event.pressed) {
@@ -52,17 +50,10 @@ bool process_audio(uint16_t keycode, keyrecord_t *record) {
52 return true; 50 return true;
53} 51}
54 52
55void process_audio_noteon(uint8_t note) { 53void process_audio_noteon(uint8_t note) { play_note(compute_freq_for_midi_note(note), 0xF); }
56 play_note(compute_freq_for_midi_note(note), 0xF);
57}
58 54
59void process_audio_noteoff(uint8_t note) { 55void process_audio_noteoff(uint8_t note) { stop_note(compute_freq_for_midi_note(note)); }
60 stop_note(compute_freq_for_midi_note(note));
61}
62 56
63void process_audio_all_notes_off(void) { 57void process_audio_all_notes_off(void) { stop_all_notes(); }
64 stop_all_notes();
65}
66 58
67__attribute__ ((weak)) 59__attribute__((weak)) void audio_on_user() {}
68void audio_on_user() {}
diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c
index 0d0930ee6..4ae3fe446 100644
--- a/quantum/process_keycode/process_auto_shift.c
+++ b/quantum/process_keycode/process_auto_shift.c
@@ -16,195 +16,185 @@
16 16
17#ifdef AUTO_SHIFT_ENABLE 17#ifdef AUTO_SHIFT_ENABLE
18 18
19#include <stdio.h> 19# include <stdio.h>
20 20
21#include "process_auto_shift.h" 21# include "process_auto_shift.h"
22 22
23#define TAP(key) \ 23# define TAP(key) \
24 register_code(key); \ 24 register_code(key); \
25 unregister_code(key) 25 unregister_code(key)
26 26
27#define TAP_WITH_MOD(mod, key) \ 27# define TAP_WITH_MOD(mod, key) \
28 register_code(mod); \ 28 register_code(mod); \
29 register_code(key); \ 29 register_code(key); \
30 unregister_code(key); \ 30 unregister_code(key); \
31 unregister_code(mod) 31 unregister_code(mod)
32 32
33uint16_t autoshift_time = 0; 33uint16_t autoshift_time = 0;
34uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT; 34uint16_t autoshift_timeout = AUTO_SHIFT_TIMEOUT;
35uint16_t autoshift_lastkey = KC_NO; 35uint16_t autoshift_lastkey = KC_NO;
36 36
37void autoshift_timer_report(void) { 37void autoshift_timer_report(void) {
38 char display[8]; 38 char display[8];
39 39
40 snprintf(display, 8, "\n%d\n", autoshift_timeout); 40 snprintf(display, 8, "\n%d\n", autoshift_timeout);
41 41
42 send_string((const char *)display); 42 send_string((const char *)display);
43} 43}
44 44
45void autoshift_on(uint16_t keycode) { 45void autoshift_on(uint16_t keycode) {
46 autoshift_time = timer_read(); 46 autoshift_time = timer_read();
47 autoshift_lastkey = keycode; 47 autoshift_lastkey = keycode;
48} 48}
49 49
50void autoshift_flush(void) { 50void autoshift_flush(void) {
51 if (autoshift_lastkey != KC_NO) { 51 if (autoshift_lastkey != KC_NO) {
52 uint16_t elapsed = timer_elapsed(autoshift_time); 52 uint16_t elapsed = timer_elapsed(autoshift_time);
53 53
54 if (elapsed > autoshift_timeout) { 54 if (elapsed > autoshift_timeout) {
55 register_code(KC_LSFT); 55 register_code(KC_LSFT);
56 } 56 }
57 57
58 register_code(autoshift_lastkey); 58 register_code(autoshift_lastkey);
59 unregister_code(autoshift_lastkey); 59 unregister_code(autoshift_lastkey);
60 60
61 if (elapsed > autoshift_timeout) { 61 if (elapsed > autoshift_timeout) {
62 unregister_code(KC_LSFT); 62 unregister_code(KC_LSFT);
63 } 63 }
64 64
65 autoshift_time = 0; 65 autoshift_time = 0;
66 autoshift_lastkey = KC_NO; 66 autoshift_lastkey = KC_NO;
67 } 67 }
68} 68}
69 69
70bool autoshift_enabled = true; 70bool autoshift_enabled = true;
71 71
72void autoshift_enable(void) { 72void autoshift_enable(void) { autoshift_enabled = true; }
73 autoshift_enabled = true;
74}
75void autoshift_disable(void) { 73void autoshift_disable(void) {
76 autoshift_enabled = false;
77 autoshift_flush();
78}
79
80void autoshift_toggle(void) {
81 if (autoshift_enabled) {
82 autoshift_enabled = false; 74 autoshift_enabled = false;
83 autoshift_flush(); 75 autoshift_flush();
84 }
85 else {
86 autoshift_enabled = true;
87 }
88} 76}
89 77
90bool autoshift_state(void) { 78void autoshift_toggle(void) {
91 return autoshift_enabled; 79 if (autoshift_enabled) {
80 autoshift_enabled = false;
81 autoshift_flush();
82 } else {
83 autoshift_enabled = true;
84 }
92} 85}
93 86
94bool process_auto_shift(uint16_t keycode, keyrecord_t *record) { 87bool autoshift_state(void) { return autoshift_enabled; }
95#ifndef AUTO_SHIFT_MODIFIERS
96 static uint8_t any_mod_pressed;
97#endif
98
99 if (record->event.pressed) {
100 switch (keycode) {
101 case KC_ASUP:
102 autoshift_timeout += 5;
103 return false;
104
105 case KC_ASDN:
106 autoshift_timeout -= 5;
107 return false;
108
109 case KC_ASRP:
110 autoshift_timer_report();
111 return false;
112
113 case KC_ASTG:
114 autoshift_toggle();
115 return false;
116 case KC_ASON:
117 autoshift_enable();
118 return false;
119 case KC_ASOFF:
120 autoshift_disable();
121 return false;
122
123#ifndef NO_AUTO_SHIFT_ALPHA
124 case KC_A:
125 case KC_B:
126 case KC_C:
127 case KC_D:
128 case KC_E:
129 case KC_F:
130 case KC_G:
131 case KC_H:
132 case KC_I:
133 case KC_J:
134 case KC_K:
135 case KC_L:
136 case KC_M:
137 case KC_N:
138 case KC_O:
139 case KC_P:
140 case KC_Q:
141 case KC_R:
142 case KC_S:
143 case KC_T:
144 case KC_U:
145 case KC_V:
146 case KC_W:
147 case KC_X:
148 case KC_Y:
149 case KC_Z:
150#endif
151#ifndef NO_AUTO_SHIFT_NUMERIC
152 case KC_1:
153 case KC_2:
154 case KC_3:
155 case KC_4:
156 case KC_5:
157 case KC_6:
158 case KC_7:
159 case KC_8:
160 case KC_9:
161 case KC_0:
162#endif
163#ifndef NO_AUTO_SHIFT_SPECIAL
164 case KC_MINUS:
165 case KC_EQL:
166 case KC_TAB:
167 case KC_LBRC:
168 case KC_RBRC:
169 case KC_BSLS:
170 case KC_SCLN:
171 case KC_QUOT:
172 case KC_COMM:
173 case KC_DOT:
174 case KC_SLSH:
175 case KC_GRAVE:
176 case KC_NONUS_BSLASH:
177 case KC_NONUS_HASH:
178#endif
179 88
180 autoshift_flush(); 89bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
181 if (!autoshift_enabled) return true; 90# ifndef AUTO_SHIFT_MODIFIERS
182 91 static uint8_t any_mod_pressed;
183#ifndef AUTO_SHIFT_MODIFIERS 92# endif
184 any_mod_pressed = get_mods() & ( 93
185 MOD_BIT(KC_LGUI)|MOD_BIT(KC_RGUI)| 94 if (record->event.pressed) {
186 MOD_BIT(KC_LALT)|MOD_BIT(KC_RALT)| 95 switch (keycode) {
187 MOD_BIT(KC_LCTL)|MOD_BIT(KC_RCTL)| 96 case KC_ASUP:
188 MOD_BIT(KC_LSFT)|MOD_BIT(KC_RSFT) 97 autoshift_timeout += 5;
189 ); 98 return false;
190 99
191 if (any_mod_pressed) { 100 case KC_ASDN:
192 return true; 101 autoshift_timeout -= 5;
102 return false;
103
104 case KC_ASRP:
105 autoshift_timer_report();
106 return false;
107
108 case KC_ASTG:
109 autoshift_toggle();
110 return false;
111 case KC_ASON:
112 autoshift_enable();
113 return false;
114 case KC_ASOFF:
115 autoshift_disable();
116 return false;
117
118# ifndef NO_AUTO_SHIFT_ALPHA
119 case KC_A:
120 case KC_B:
121 case KC_C:
122 case KC_D:
123 case KC_E:
124 case KC_F:
125 case KC_G:
126 case KC_H:
127 case KC_I:
128 case KC_J:
129 case KC_K:
130 case KC_L:
131 case KC_M:
132 case KC_N:
133 case KC_O:
134 case KC_P:
135 case KC_Q:
136 case KC_R:
137 case KC_S:
138 case KC_T:
139 case KC_U:
140 case KC_V:
141 case KC_W:
142 case KC_X:
143 case KC_Y:
144 case KC_Z:
145# endif
146# ifndef NO_AUTO_SHIFT_NUMERIC
147 case KC_1:
148 case KC_2:
149 case KC_3:
150 case KC_4:
151 case KC_5:
152 case KC_6:
153 case KC_7:
154 case KC_8:
155 case KC_9:
156 case KC_0:
157# endif
158# ifndef NO_AUTO_SHIFT_SPECIAL
159 case KC_MINUS:
160 case KC_EQL:
161 case KC_TAB:
162 case KC_LBRC:
163 case KC_RBRC:
164 case KC_BSLS:
165 case KC_SCLN:
166 case KC_QUOT:
167 case KC_COMM:
168 case KC_DOT:
169 case KC_SLSH:
170 case KC_GRAVE:
171 case KC_NONUS_BSLASH:
172 case KC_NONUS_HASH:
173# endif
174
175 autoshift_flush();
176 if (!autoshift_enabled) return true;
177
178# ifndef AUTO_SHIFT_MODIFIERS
179 any_mod_pressed = get_mods() & (MOD_BIT(KC_LGUI) | MOD_BIT(KC_RGUI) | MOD_BIT(KC_LALT) | MOD_BIT(KC_RALT) | MOD_BIT(KC_LCTL) | MOD_BIT(KC_RCTL) | MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT));
180
181 if (any_mod_pressed) {
182 return true;
183 }
184# endif
185
186 autoshift_on(keycode);
187 return false;
188
189 default:
190 autoshift_flush();
191 return true;
193 } 192 }
194#endif 193 } else {
195
196 autoshift_on(keycode);
197 return false;
198
199 default:
200 autoshift_flush(); 194 autoshift_flush();
201 return true;
202 } 195 }
203 } else {
204 autoshift_flush();
205 }
206 196
207 return true; 197 return true;
208} 198}
209 199
210#endif 200#endif
diff --git a/quantum/process_keycode/process_auto_shift.h b/quantum/process_keycode/process_auto_shift.h
index a4abf0414..083325d8e 100644
--- a/quantum/process_keycode/process_auto_shift.h
+++ b/quantum/process_keycode/process_auto_shift.h
@@ -20,7 +20,7 @@
20#include "quantum.h" 20#include "quantum.h"
21 21
22#ifndef AUTO_SHIFT_TIMEOUT 22#ifndef AUTO_SHIFT_TIMEOUT
23 #define AUTO_SHIFT_TIMEOUT 175 23# define AUTO_SHIFT_TIMEOUT 175
24#endif 24#endif
25 25
26bool process_auto_shift(uint16_t keycode, keyrecord_t *record); 26bool process_auto_shift(uint16_t keycode, keyrecord_t *record);
diff --git a/quantum/process_keycode/process_clicky.c b/quantum/process_keycode/process_clicky.c
index 43b803afe..6ab382d4a 100644
--- a/quantum/process_keycode/process_clicky.c
+++ b/quantum/process_keycode/process_clicky.c
@@ -3,104 +3,111 @@
3 3
4#ifdef AUDIO_CLICKY 4#ifdef AUDIO_CLICKY
5 5
6#ifndef AUDIO_CLICKY_DELAY_DURATION 6# ifndef AUDIO_CLICKY_DELAY_DURATION
7#define AUDIO_CLICKY_DELAY_DURATION 1 7# define AUDIO_CLICKY_DELAY_DURATION 1
8#endif // !AUDIO_CLICKY_DELAY_DURATION 8# endif // !AUDIO_CLICKY_DELAY_DURATION
9#ifndef AUDIO_CLICKY_FREQ_DEFAULT 9# ifndef AUDIO_CLICKY_FREQ_DEFAULT
10#define AUDIO_CLICKY_FREQ_DEFAULT 440.0f 10# define AUDIO_CLICKY_FREQ_DEFAULT 440.0f
11#endif // !AUDIO_CLICKY_FREQ_DEFAULT 11# endif // !AUDIO_CLICKY_FREQ_DEFAULT
12#ifndef AUDIO_CLICKY_FREQ_MIN 12# ifndef AUDIO_CLICKY_FREQ_MIN
13#define AUDIO_CLICKY_FREQ_MIN 65.0f 13# define AUDIO_CLICKY_FREQ_MIN 65.0f
14#endif // !AUDIO_CLICKY_FREQ_MIN 14# endif // !AUDIO_CLICKY_FREQ_MIN
15#ifndef AUDIO_CLICKY_FREQ_MAX 15# ifndef AUDIO_CLICKY_FREQ_MAX
16#define AUDIO_CLICKY_FREQ_MAX 1500.0f 16# define AUDIO_CLICKY_FREQ_MAX 1500.0f
17#endif // !AUDIO_CLICKY_FREQ_MAX 17# endif // !AUDIO_CLICKY_FREQ_MAX
18#ifndef AUDIO_CLICKY_FREQ_FACTOR 18# ifndef AUDIO_CLICKY_FREQ_FACTOR
19#define AUDIO_CLICKY_FREQ_FACTOR 1.18921f 19# define AUDIO_CLICKY_FREQ_FACTOR 1.18921f
20#endif // !AUDIO_CLICKY_FREQ_FACTOR 20# endif // !AUDIO_CLICKY_FREQ_FACTOR
21#ifndef AUDIO_CLICKY_FREQ_RANDOMNESS 21# ifndef AUDIO_CLICKY_FREQ_RANDOMNESS
22#define AUDIO_CLICKY_FREQ_RANDOMNESS 0.05f 22# define AUDIO_CLICKY_FREQ_RANDOMNESS 0.05f
23#endif // !AUDIO_CLICKY_FREQ_RANDOMNESS 23# endif // !AUDIO_CLICKY_FREQ_RANDOMNESS
24 24
25float clicky_freq = AUDIO_CLICKY_FREQ_DEFAULT; 25float clicky_freq = AUDIO_CLICKY_FREQ_DEFAULT;
26float clicky_rand = AUDIO_CLICKY_FREQ_RANDOMNESS; 26float clicky_rand = AUDIO_CLICKY_FREQ_RANDOMNESS;
27 27
28// the first "note" is an intentional delay; the 2nd and 3rd notes are the "clicky" 28// the first "note" is an intentional delay; the 2nd and 3rd notes are the "clicky"
29float clicky_song[][2] = {{AUDIO_CLICKY_FREQ_MIN, AUDIO_CLICKY_DELAY_DURATION}, {AUDIO_CLICKY_FREQ_DEFAULT, 3}, {AUDIO_CLICKY_FREQ_DEFAULT, 1}}; // 3 and 1 --> durations 29float clicky_song[][2] = {{AUDIO_CLICKY_FREQ_MIN, AUDIO_CLICKY_DELAY_DURATION}, {AUDIO_CLICKY_FREQ_DEFAULT, 3}, {AUDIO_CLICKY_FREQ_DEFAULT, 1}}; // 3 and 1 --> durations
30 30
31extern audio_config_t audio_config; 31extern audio_config_t audio_config;
32 32
33#ifndef NO_MUSIC_MODE 33# ifndef NO_MUSIC_MODE
34extern bool music_activated; 34extern bool music_activated;
35extern bool midi_activated; 35extern bool midi_activated;
36#endif // !NO_MUSIC_MODE 36# endif // !NO_MUSIC_MODE
37 37
38void clicky_play(void) { 38void clicky_play(void) {
39#ifndef NO_MUSIC_MODE 39# ifndef NO_MUSIC_MODE
40 if (music_activated || midi_activated || !audio_config.enable) return; 40 if (music_activated || midi_activated || !audio_config.enable) return;
41#endif // !NO_MUSIC_MODE 41# endif // !NO_MUSIC_MODE
42 clicky_song[1][0] = 2.0f * clicky_freq * (1.0f + clicky_rand * ( ((float)rand()) / ((float)(RAND_MAX)) ) ); 42 clicky_song[1][0] = 2.0f * clicky_freq * (1.0f + clicky_rand * (((float)rand()) / ((float)(RAND_MAX))));
43 clicky_song[2][0] = clicky_freq * (1.0f + clicky_rand * ( ((float)rand()) / ((float)(RAND_MAX)) ) ); 43 clicky_song[2][0] = clicky_freq * (1.0f + clicky_rand * (((float)rand()) / ((float)(RAND_MAX))));
44 PLAY_SONG(clicky_song); 44 PLAY_SONG(clicky_song);
45} 45}
46 46
47void clicky_freq_up(void) { 47void clicky_freq_up(void) {
48 float new_freq = clicky_freq * AUDIO_CLICKY_FREQ_FACTOR; 48 float new_freq = clicky_freq * AUDIO_CLICKY_FREQ_FACTOR;
49 if (new_freq < AUDIO_CLICKY_FREQ_MAX) { 49 if (new_freq < AUDIO_CLICKY_FREQ_MAX) {
50 clicky_freq = new_freq; 50 clicky_freq = new_freq;
51 } 51 }
52} 52}
53 53
54void clicky_freq_down(void) { 54void clicky_freq_down(void) {
55 float new_freq = clicky_freq / AUDIO_CLICKY_FREQ_FACTOR; 55 float new_freq = clicky_freq / AUDIO_CLICKY_FREQ_FACTOR;
56 if (new_freq > AUDIO_CLICKY_FREQ_MIN) { 56 if (new_freq > AUDIO_CLICKY_FREQ_MIN) {
57 clicky_freq = new_freq; 57 clicky_freq = new_freq;
58 } 58 }
59} 59}
60 60
61void clicky_freq_reset(void) { 61void clicky_freq_reset(void) { clicky_freq = AUDIO_CLICKY_FREQ_DEFAULT; }
62 clicky_freq = AUDIO_CLICKY_FREQ_DEFAULT;
63}
64 62
65void clicky_toggle(void) { 63void clicky_toggle(void) {
66 audio_config.clicky_enable ^= 1; 64 audio_config.clicky_enable ^= 1;
67 eeconfig_update_audio(audio_config.raw); 65 eeconfig_update_audio(audio_config.raw);
68} 66}
69 67
70void clicky_on(void) { 68void clicky_on(void) {
71 audio_config.clicky_enable = 1; 69 audio_config.clicky_enable = 1;
72 eeconfig_update_audio(audio_config.raw); 70 eeconfig_update_audio(audio_config.raw);
73} 71}
74 72
75void clicky_off(void) { 73void clicky_off(void) {
76 audio_config.clicky_enable = 0; 74 audio_config.clicky_enable = 0;
77 eeconfig_update_audio(audio_config.raw); 75 eeconfig_update_audio(audio_config.raw);
78} 76}
79 77
80bool is_clicky_on(void) { 78bool is_clicky_on(void) { return (audio_config.clicky_enable != 0); }
81 return (audio_config.clicky_enable != 0);
82}
83 79
84bool process_clicky(uint16_t keycode, keyrecord_t *record) { 80bool process_clicky(uint16_t keycode, keyrecord_t *record) {
85 if (keycode == CLICKY_TOGGLE && record->event.pressed) { clicky_toggle(); } 81 if (keycode == CLICKY_TOGGLE && record->event.pressed) {
86 82 clicky_toggle();
87 if (keycode == CLICKY_ENABLE && record->event.pressed) { clicky_on(); } 83 }
88 if (keycode == CLICKY_DISABLE && record->event.pressed) { clicky_off(); }
89 84
90 if (keycode == CLICKY_RESET && record->event.pressed) { clicky_freq_reset(); } 85 if (keycode == CLICKY_ENABLE && record->event.pressed) {
86 clicky_on();
87 }
88 if (keycode == CLICKY_DISABLE && record->event.pressed) {
89 clicky_off();
90 }
91 91
92 if (keycode == CLICKY_UP && record->event.pressed) { clicky_freq_up(); } 92 if (keycode == CLICKY_RESET && record->event.pressed) {
93 if (keycode == CLICKY_DOWN && record->event.pressed) { clicky_freq_down(); } 93 clicky_freq_reset();
94 }
94 95
96 if (keycode == CLICKY_UP && record->event.pressed) {
97 clicky_freq_up();
98 }
99 if (keycode == CLICKY_DOWN && record->event.pressed) {
100 clicky_freq_down();
101 }
95 102
96 if (audio_config.enable && audio_config.clicky_enable) { 103 if (audio_config.enable && audio_config.clicky_enable) {
97 if (record->event.pressed) { // Leave this separate so it's easier to add upstroke sound 104 if (record->event.pressed) { // Leave this separate so it's easier to add upstroke sound
98 if (keycode != AU_OFF && keycode != AU_TOG) { // DO NOT PLAY if audio will be disabled, and causes issuse on ARM 105 if (keycode != AU_OFF && keycode != AU_TOG) { // DO NOT PLAY if audio will be disabled, and causes issuse on ARM
99 clicky_play(); 106 clicky_play();
100 } 107 }
108 }
101 } 109 }
102 } 110 return true;
103 return true;
104} 111}
105 112
106#endif //AUDIO_CLICKY 113#endif // AUDIO_CLICKY
diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c
index d3c3b1673..f40ca7452 100644
--- a/quantum/process_keycode/process_combo.c
+++ b/quantum/process_keycode/process_combo.c
@@ -21,14 +21,13 @@ __attribute__((weak)) combo_t key_combos[COMBO_COUNT] = {
21 21
22}; 22};
23 23
24__attribute__((weak)) void process_combo_event(uint8_t combo_index, 24__attribute__((weak)) void process_combo_event(uint8_t combo_index, bool pressed) {}
25 bool pressed) {}
26 25
27static uint16_t timer = 0; 26static uint16_t timer = 0;
28static uint8_t current_combo_index = 0; 27static uint8_t current_combo_index = 0;
29static bool drop_buffer = false; 28static bool drop_buffer = false;
30static bool is_active = false; 29static bool is_active = false;
31static bool b_combo_enable = true; // defaults to enabled 30static bool b_combo_enable = true; // defaults to enabled
32 31
33static uint8_t buffer_size = 0; 32static uint8_t buffer_size = 0;
34#ifdef COMBO_ALLOW_ACTION_KEYS 33#ifdef COMBO_ALLOW_ACTION_KEYS
@@ -38,171 +37,163 @@ static uint16_t key_buffer[MAX_COMBO_LENGTH];
38#endif 37#endif
39 38
40static inline void send_combo(uint16_t action, bool pressed) { 39static inline void send_combo(uint16_t action, bool pressed) {
41 if (action) { 40 if (action) {
42 if (pressed) { 41 if (pressed) {
43 register_code16(action); 42 register_code16(action);
43 } else {
44 unregister_code16(action);
45 }
44 } else { 46 } else {
45 unregister_code16(action); 47 process_combo_event(current_combo_index, pressed);
46 } 48 }
47 } else {
48 process_combo_event(current_combo_index, pressed);
49 }
50} 49}
51 50
52static inline void dump_key_buffer(bool emit) { 51static inline void dump_key_buffer(bool emit) {
53 if (buffer_size == 0) { 52 if (buffer_size == 0) {
54 return; 53 return;
55 } 54 }
56 55
57 if (emit) { 56 if (emit) {
58 for (uint8_t i = 0; i < buffer_size; i++) { 57 for (uint8_t i = 0; i < buffer_size; i++) {
59#ifdef COMBO_ALLOW_ACTION_KEYS 58#ifdef COMBO_ALLOW_ACTION_KEYS
60 const action_t action = store_or_get_action(key_buffer[i].event.pressed, 59 const action_t action = store_or_get_action(key_buffer[i].event.pressed, key_buffer[i].event.key);
61 key_buffer[i].event.key); 60 process_action(&(key_buffer[i]), action);
62 process_action(&(key_buffer[i]), action);
63#else 61#else
64 register_code16(key_buffer[i]); 62 register_code16(key_buffer[i]);
65 send_keyboard_report(); 63 send_keyboard_report();
66#endif 64#endif
65 }
67 } 66 }
68 }
69 67
70 buffer_size = 0; 68 buffer_size = 0;
71} 69}
72 70
73#define ALL_COMBO_KEYS_ARE_DOWN (((1 << count) - 1) == combo->state) 71#define ALL_COMBO_KEYS_ARE_DOWN (((1 << count) - 1) == combo->state)
74#define KEY_STATE_DOWN(key) \ 72#define KEY_STATE_DOWN(key) \
75 do { \ 73 do { \
76 combo->state |= (1 << key); \ 74 combo->state |= (1 << key); \
77 } while (0) 75 } while (0)
78#define KEY_STATE_UP(key) \ 76#define KEY_STATE_UP(key) \
79 do { \ 77 do { \
80 combo->state &= ~(1 << key); \ 78 combo->state &= ~(1 << key); \
81 } while (0) 79 } while (0)
82 80
83static bool process_single_combo(combo_t *combo, uint16_t keycode, 81static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record) {
84 keyrecord_t *record) { 82 uint8_t count = 0;
85 uint8_t count = 0; 83 uint8_t index = -1;
86 uint8_t index = -1; 84 /* Find index of keycode and number of combo keys */
87 /* Find index of keycode and number of combo keys */ 85 for (const uint16_t *keys = combo->keys;; ++count) {
88 for (const uint16_t *keys = combo->keys;; ++count) { 86 uint16_t key = pgm_read_word(&keys[count]);
89 uint16_t key = pgm_read_word(&keys[count]); 87 if (keycode == key) index = count;
90 if (keycode == key) 88 if (COMBO_END == key) break;
91 index = count;
92 if (COMBO_END == key)
93 break;
94 }
95
96 /* Continue processing if not a combo key */
97 if (-1 == (int8_t)index)
98 return false;
99
100 bool is_combo_active = is_active;
101
102 if (record->event.pressed) {
103 KEY_STATE_DOWN(index);
104
105 if (is_combo_active) {
106 if (ALL_COMBO_KEYS_ARE_DOWN) { /* Combo was pressed */
107 send_combo(combo->keycode, true);
108 drop_buffer = true;
109 }
110 } 89 }
111 } else { 90
112 if (ALL_COMBO_KEYS_ARE_DOWN) { /* Combo was released */ 91 /* Continue processing if not a combo key */
113 send_combo(combo->keycode, false); 92 if (-1 == (int8_t)index) return false;
93
94 bool is_combo_active = is_active;
95
96 if (record->event.pressed) {
97 KEY_STATE_DOWN(index);
98
99 if (is_combo_active) {
100 if (ALL_COMBO_KEYS_ARE_DOWN) { /* Combo was pressed */
101 send_combo(combo->keycode, true);
102 drop_buffer = true;
103 }
104 }
114 } else { 105 } else {
115 /* continue processing without immediately returning */ 106 if (ALL_COMBO_KEYS_ARE_DOWN) { /* Combo was released */
116 is_combo_active = false; 107 send_combo(combo->keycode, false);
108 } else {
109 /* continue processing without immediately returning */
110 is_combo_active = false;
111 }
112
113 KEY_STATE_UP(index);
117 } 114 }
118 115
119 KEY_STATE_UP(index); 116 return is_combo_active;
120 }
121
122 return is_combo_active;
123} 117}
124 118
125#define NO_COMBO_KEYS_ARE_DOWN (0 == combo->state) 119#define NO_COMBO_KEYS_ARE_DOWN (0 == combo->state)
126 120
127bool process_combo(uint16_t keycode, keyrecord_t *record) { 121bool process_combo(uint16_t keycode, keyrecord_t *record) {
128 bool is_combo_key = false; 122 bool is_combo_key = false;
129 drop_buffer = false; 123 drop_buffer = false;
130 bool no_combo_keys_pressed = true; 124 bool no_combo_keys_pressed = true;
131 125
132 if (keycode == CMB_ON && record->event.pressed) { 126 if (keycode == CMB_ON && record->event.pressed) {
133 combo_enable(); 127 combo_enable();
134 return true; 128 return true;
135 } 129 }
136
137 if (keycode == CMB_OFF && record->event.pressed) {
138 combo_disable();
139 return true;
140 }
141
142 if (keycode == CMB_TOG && record->event.pressed) {
143 combo_toggle();
144 return true;
145 }
146
147 if (!is_combo_enabled()) { return true; }
148
149 for (current_combo_index = 0; current_combo_index < COMBO_COUNT;
150 ++current_combo_index) {
151 combo_t *combo = &key_combos[current_combo_index];
152 is_combo_key |= process_single_combo(combo, keycode, record);
153 no_combo_keys_pressed = no_combo_keys_pressed && NO_COMBO_KEYS_ARE_DOWN;
154 }
155
156 if (drop_buffer) {
157 /* buffer is only dropped when we complete a combo, so we refresh the timer
158 * here */
159 timer = timer_read();
160 dump_key_buffer(false);
161 } else if (!is_combo_key) {
162 /* if no combos claim the key we need to emit the keybuffer */
163 dump_key_buffer(true);
164 130
165 // reset state if there are no combo keys pressed at all 131 if (keycode == CMB_OFF && record->event.pressed) {
166 if (no_combo_keys_pressed) { 132 combo_disable();
167 timer = 0; 133 return true;
168 is_active = true;
169 } 134 }
170 } else if (record->event.pressed && is_active) {
171 /* otherwise the key is consumed and placed in the buffer */
172 timer = timer_read();
173 135
174 if (buffer_size < MAX_COMBO_LENGTH) { 136 if (keycode == CMB_TOG && record->event.pressed) {
137 combo_toggle();
138 return true;
139 }
140
141 if (!is_combo_enabled()) {
142 return true;
143 }
144
145 for (current_combo_index = 0; current_combo_index < COMBO_COUNT; ++current_combo_index) {
146 combo_t *combo = &key_combos[current_combo_index];
147 is_combo_key |= process_single_combo(combo, keycode, record);
148 no_combo_keys_pressed = no_combo_keys_pressed && NO_COMBO_KEYS_ARE_DOWN;
149 }
150
151 if (drop_buffer) {
152 /* buffer is only dropped when we complete a combo, so we refresh the timer
153 * here */
154 timer = timer_read();
155 dump_key_buffer(false);
156 } else if (!is_combo_key) {
157 /* if no combos claim the key we need to emit the keybuffer */
158 dump_key_buffer(true);
159
160 // reset state if there are no combo keys pressed at all
161 if (no_combo_keys_pressed) {
162 timer = 0;
163 is_active = true;
164 }
165 } else if (record->event.pressed && is_active) {
166 /* otherwise the key is consumed and placed in the buffer */
167 timer = timer_read();
168
169 if (buffer_size < MAX_COMBO_LENGTH) {
175#ifdef COMBO_ALLOW_ACTION_KEYS 170#ifdef COMBO_ALLOW_ACTION_KEYS
176 key_buffer[buffer_size++] = *record; 171 key_buffer[buffer_size++] = *record;
177#else 172#else
178 key_buffer[buffer_size++] = keycode; 173 key_buffer[buffer_size++] = keycode;
179#endif 174#endif
175 }
180 } 176 }
181 }
182 177
183 return !is_combo_key; 178 return !is_combo_key;
184} 179}
185 180
186void matrix_scan_combo(void) { 181void matrix_scan_combo(void) {
187 if (b_combo_enable && is_active && timer && timer_elapsed(timer) > COMBO_TERM) { 182 if (b_combo_enable && is_active && timer && timer_elapsed(timer) > COMBO_TERM) {
188 183 /* This disables the combo, meaning key events for this
189 /* This disables the combo, meaning key events for this 184 * combo will be handled by the next processors in the chain
190 * combo will be handled by the next processors in the chain 185 */
191 */ 186 is_active = false;
192 is_active = false; 187 dump_key_buffer(true);
193 dump_key_buffer(true); 188 }
194 }
195} 189}
196 190
197void combo_enable(void) { 191void combo_enable(void) { b_combo_enable = true; }
198 b_combo_enable = true;
199}
200 192
201void combo_disable(void) { 193void combo_disable(void) {
202 b_combo_enable = is_active = false; 194 b_combo_enable = is_active = false;
203 timer = 0; 195 timer = 0;
204 dump_key_buffer(true); 196 dump_key_buffer(true);
205
206} 197}
207 198
208void combo_toggle(void) { 199void combo_toggle(void) {
@@ -213,6 +204,4 @@ void combo_toggle(void) {
213 } 204 }
214} 205}
215 206
216bool is_combo_enabled(void) { 207bool is_combo_enabled(void) { return b_combo_enable; }
217 return b_combo_enable;
218}
diff --git a/quantum/process_keycode/process_combo.h b/quantum/process_keycode/process_combo.h
index aab284957..e21ee1960 100644
--- a/quantum/process_keycode/process_combo.h
+++ b/quantum/process_keycode/process_combo.h
@@ -22,36 +22,36 @@
22#include <stdint.h> 22#include <stdint.h>
23 23
24#ifdef EXTRA_EXTRA_LONG_COMBOS 24#ifdef EXTRA_EXTRA_LONG_COMBOS
25#define MAX_COMBO_LENGTH 32 25# define MAX_COMBO_LENGTH 32
26#elif EXTRA_LONG_COMBOS 26#elif EXTRA_LONG_COMBOS
27#define MAX_COMBO_LENGTH 16 27# define MAX_COMBO_LENGTH 16
28#else 28#else
29#define MAX_COMBO_LENGTH 8 29# define MAX_COMBO_LENGTH 8
30#endif 30#endif
31 31
32typedef struct { 32typedef struct {
33 const uint16_t *keys; 33 const uint16_t *keys;
34 uint16_t keycode; 34 uint16_t keycode;
35#ifdef EXTRA_EXTRA_LONG_COMBOS 35#ifdef EXTRA_EXTRA_LONG_COMBOS
36 uint32_t state; 36 uint32_t state;
37#elif EXTRA_LONG_COMBOS 37#elif EXTRA_LONG_COMBOS
38 uint16_t state; 38 uint16_t state;
39#else 39#else
40 uint8_t state; 40 uint8_t state;
41#endif 41#endif
42} combo_t; 42} combo_t;
43 43
44#define COMBO(ck, ca) \ 44#define COMBO(ck, ca) \
45 { .keys = &(ck)[0], .keycode = (ca) } 45 { .keys = &(ck)[0], .keycode = (ca) }
46#define COMBO_ACTION(ck) \ 46#define COMBO_ACTION(ck) \
47 { .keys = &(ck)[0] } 47 { .keys = &(ck)[0] }
48 48
49#define COMBO_END 0 49#define COMBO_END 0
50#ifndef COMBO_COUNT 50#ifndef COMBO_COUNT
51#define COMBO_COUNT 0 51# define COMBO_COUNT 0
52#endif 52#endif
53#ifndef COMBO_TERM 53#ifndef COMBO_TERM
54#define COMBO_TERM TAPPING_TERM 54# define COMBO_TERM TAPPING_TERM
55#endif 55#endif
56 56
57bool process_combo(uint16_t keycode, keyrecord_t *record); 57bool process_combo(uint16_t keycode, keyrecord_t *record);
diff --git a/quantum/process_keycode/process_key_lock.c b/quantum/process_keycode/process_key_lock.c
index 50cc0a5cc..602127a74 100644
--- a/quantum/process_keycode/process_key_lock.c
+++ b/quantum/process_keycode/process_key_lock.c
@@ -19,36 +19,33 @@
19#include "process_key_lock.h" 19#include "process_key_lock.h"
20 20
21#define BV_64(shift) (((uint64_t)1) << (shift)) 21#define BV_64(shift) (((uint64_t)1) << (shift))
22#define GET_KEY_ARRAY(code) (((code) < 0x40) ? key_state[0] : \ 22#define GET_KEY_ARRAY(code) (((code) < 0x40) ? key_state[0] : ((code) < 0x80) ? key_state[1] : ((code) < 0xC0) ? key_state[2] : key_state[3])
23 ((code) < 0x80) ? key_state[1] : \ 23#define GET_CODE_INDEX(code) (((code) < 0x40) ? (code) : ((code) < 0x80) ? (code)-0x40 : ((code) < 0xC0) ? (code)-0x80 : (code)-0xC0)
24 ((code) < 0xC0) ? key_state[2] : key_state[3]) 24#define KEY_STATE(code) (GET_KEY_ARRAY(code) & BV_64(GET_CODE_INDEX(code))) == BV_64(GET_CODE_INDEX(code))
25#define GET_CODE_INDEX(code) (((code) < 0x40) ? (code) : \ 25#define SET_KEY_ARRAY_STATE(code, val) \
26 ((code) < 0x80) ? (code) - 0x40 : \ 26 do { \
27 ((code) < 0xC0) ? (code) - 0x80 : (code) - 0xC0) 27 switch (code) { \
28#define KEY_STATE(code) (GET_KEY_ARRAY(code) & BV_64(GET_CODE_INDEX(code))) == BV_64(GET_CODE_INDEX(code)) 28 case 0x00 ... 0x3F: \
29#define SET_KEY_ARRAY_STATE(code, val) do { \ 29 key_state[0] = (val); \
30 switch (code) { \ 30 break; \
31 case 0x00 ... 0x3F: \ 31 case 0x40 ... 0x7F: \
32 key_state[0] = (val); \ 32 key_state[1] = (val); \
33 break; \ 33 break; \
34 case 0x40 ... 0x7F: \ 34 case 0x80 ... 0xBF: \
35 key_state[1] = (val); \ 35 key_state[2] = (val); \
36 break; \ 36 break; \
37 case 0x80 ... 0xBF: \ 37 case 0xC0 ... 0xFF: \
38 key_state[2] = (val); \ 38 key_state[3] = (val); \
39 break; \ 39 break; \
40 case 0xC0 ... 0xFF: \ 40 } \
41 key_state[3] = (val); \ 41 } while (0)
42 break; \
43 } \
44} while(0)
45#define SET_KEY_STATE(code) SET_KEY_ARRAY_STATE(code, (GET_KEY_ARRAY(code) | BV_64(GET_CODE_INDEX(code)))) 42#define SET_KEY_STATE(code) SET_KEY_ARRAY_STATE(code, (GET_KEY_ARRAY(code) | BV_64(GET_CODE_INDEX(code))))
46#define UNSET_KEY_STATE(code) SET_KEY_ARRAY_STATE(code, (GET_KEY_ARRAY(code)) & ~(BV_64(GET_CODE_INDEX(code)))) 43#define UNSET_KEY_STATE(code) SET_KEY_ARRAY_STATE(code, (GET_KEY_ARRAY(code)) & ~(BV_64(GET_CODE_INDEX(code))))
47#define IS_STANDARD_KEYCODE(code) ((code) <= 0xFF) 44#define IS_STANDARD_KEYCODE(code) ((code) <= 0xFF)
48 45
49// Locked key state. This is an array of 256 bits, one for each of the standard keys supported qmk. 46// Locked key state. This is an array of 256 bits, one for each of the standard keys supported qmk.
50uint64_t key_state[4] = { 0x0, 0x0, 0x0, 0x0 }; 47uint64_t key_state[4] = {0x0, 0x0, 0x0, 0x0};
51bool watching = false; 48bool watching = false;
52 49
53// Translate any OSM keycodes back to their unmasked versions. 50// Translate any OSM keycodes back to their unmasked versions.
54static inline uint16_t translate_keycode(uint16_t keycode) { 51static inline uint16_t translate_keycode(uint16_t keycode) {
@@ -135,4 +132,3 @@ bool process_key_lock(uint16_t *keycode, keyrecord_t *record) {
135 return !(IS_STANDARD_KEYCODE(translated_keycode) && KEY_STATE(translated_keycode)); 132 return !(IS_STANDARD_KEYCODE(translated_keycode) && KEY_STATE(translated_keycode));
136 } 133 }
137} 134}
138
diff --git a/quantum/process_keycode/process_key_lock.h b/quantum/process_keycode/process_key_lock.h
index 876db4a32..a8e110a4b 100644
--- a/quantum/process_keycode/process_key_lock.h
+++ b/quantum/process_keycode/process_key_lock.h
@@ -21,4 +21,4 @@
21 21
22bool process_key_lock(uint16_t *keycode, keyrecord_t *record); 22bool process_key_lock(uint16_t *keycode, keyrecord_t *record);
23 23
24#endif // PROCESS_KEY_LOCK_H 24#endif // PROCESS_KEY_LOCK_H
diff --git a/quantum/process_keycode/process_leader.c b/quantum/process_keycode/process_leader.c
index f787e6b01..58a615d85 100644
--- a/quantum/process_keycode/process_leader.c
+++ b/quantum/process_keycode/process_leader.c
@@ -16,64 +16,64 @@
16 16
17#ifdef LEADER_ENABLE 17#ifdef LEADER_ENABLE
18 18
19#include "process_leader.h" 19# include "process_leader.h"
20#include <string.h> 20# include <string.h>
21 21
22#ifndef LEADER_TIMEOUT 22# ifndef LEADER_TIMEOUT
23 #define LEADER_TIMEOUT 300 23# define LEADER_TIMEOUT 300
24#endif 24# endif
25 25
26__attribute__ ((weak)) 26__attribute__((weak)) void leader_start(void) {}
27void leader_start(void) {}
28 27
29__attribute__ ((weak)) 28__attribute__((weak)) void leader_end(void) {}
30void leader_end(void) {}
31 29
32// Leader key stuff 30// Leader key stuff
33bool leading = false; 31bool leading = false;
34uint16_t leader_time = 0; 32uint16_t leader_time = 0;
35 33
36uint16_t leader_sequence[5] = {0, 0, 0, 0, 0}; 34uint16_t leader_sequence[5] = {0, 0, 0, 0, 0};
37uint8_t leader_sequence_size = 0; 35uint8_t leader_sequence_size = 0;
38 36
39void qk_leader_start(void) { 37void qk_leader_start(void) {
40 if (leading) { return; } 38 if (leading) {
41 leader_start(); 39 return;
42 leading = true; 40 }
43 leader_time = timer_read(); 41 leader_start();
44 leader_sequence_size = 0; 42 leading = true;
45 memset(leader_sequence, 0, sizeof(leader_sequence)); 43 leader_time = timer_read();
44 leader_sequence_size = 0;
45 memset(leader_sequence, 0, sizeof(leader_sequence));
46} 46}
47 47
48bool process_leader(uint16_t keycode, keyrecord_t *record) { 48bool process_leader(uint16_t keycode, keyrecord_t *record) {
49 // Leader key set-up 49 // Leader key set-up
50 if (record->event.pressed) { 50 if (record->event.pressed) {
51 if (leading) { 51 if (leading) {
52 if (timer_elapsed(leader_time) < LEADER_TIMEOUT) { 52 if (timer_elapsed(leader_time) < LEADER_TIMEOUT) {
53#ifndef LEADER_KEY_STRICT_KEY_PROCESSING 53# ifndef LEADER_KEY_STRICT_KEY_PROCESSING
54 if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) { 54 if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) {
55 keycode = keycode & 0xFF; 55 keycode = keycode & 0xFF;
56 } 56 }
57#endif // LEADER_KEY_STRICT_KEY_PROCESSING 57# endif // LEADER_KEY_STRICT_KEY_PROCESSING
58 if ( leader_sequence_size < ( sizeof(leader_sequence) / sizeof(leader_sequence[0]) ) ) { 58 if (leader_sequence_size < (sizeof(leader_sequence) / sizeof(leader_sequence[0]))) {
59 leader_sequence[leader_sequence_size] = keycode; 59 leader_sequence[leader_sequence_size] = keycode;
60 leader_sequence_size++; 60 leader_sequence_size++;
61 } else {
62 leading = false;
63 leader_end();
64 }
65# ifdef LEADER_PER_KEY_TIMING
66 leader_time = timer_read();
67# endif
68 return false;
69 }
61 } else { 70 } else {
62 leading = false; 71 if (keycode == KC_LEAD) {
63 leader_end(); 72 qk_leader_start();
73 }
64 } 74 }
65#ifdef LEADER_PER_KEY_TIMING
66 leader_time = timer_read();
67#endif
68 return false;
69 }
70 } else {
71 if (keycode == KC_LEAD) {
72 qk_leader_start();
73 }
74 } 75 }
75 } 76 return true;
76 return true;
77} 77}
78 78
79#endif 79#endif
diff --git a/quantum/process_keycode/process_leader.h b/quantum/process_keycode/process_leader.h
index 15bccc3f6..e0edf57b3 100644
--- a/quantum/process_keycode/process_leader.h
+++ b/quantum/process_keycode/process_leader.h
@@ -19,7 +19,6 @@
19 19
20#include "quantum.h" 20#include "quantum.h"
21 21
22
23bool process_leader(uint16_t keycode, keyrecord_t *record); 22bool process_leader(uint16_t keycode, keyrecord_t *record);
24 23
25void leader_start(void); 24void leader_start(void);
@@ -32,7 +31,11 @@ void qk_leader_start(void);
32#define SEQ_FOUR_KEYS(key1, key2, key3, key4) if (leader_sequence[0] == (key1) && leader_sequence[1] == (key2) && leader_sequence[2] == (key3) && leader_sequence[3] == (key4) && leader_sequence[4] == 0) 31#define SEQ_FOUR_KEYS(key1, key2, key3, key4) if (leader_sequence[0] == (key1) && leader_sequence[1] == (key2) && leader_sequence[2] == (key3) && leader_sequence[3] == (key4) && leader_sequence[4] == 0)
33#define SEQ_FIVE_KEYS(key1, key2, key3, key4, key5) if (leader_sequence[0] == (key1) && leader_sequence[1] == (key2) && leader_sequence[2] == (key3) && leader_sequence[3] == (key4) && leader_sequence[4] == (key5)) 32#define SEQ_FIVE_KEYS(key1, key2, key3, key4, key5) if (leader_sequence[0] == (key1) && leader_sequence[1] == (key2) && leader_sequence[2] == (key3) && leader_sequence[3] == (key4) && leader_sequence[4] == (key5))
34 33
35#define LEADER_EXTERNS() extern bool leading; extern uint16_t leader_time; extern uint16_t leader_sequence[5]; extern uint8_t leader_sequence_size 34#define LEADER_EXTERNS() \
35 extern bool leading; \
36 extern uint16_t leader_time; \
37 extern uint16_t leader_sequence[5]; \
38 extern uint8_t leader_sequence_size
36#define LEADER_DICTIONARY() if (leading && timer_elapsed(leader_time) > LEADER_TIMEOUT) 39#define LEADER_DICTIONARY() if (leading && timer_elapsed(leader_time) > LEADER_TIMEOUT)
37 40
38#endif 41#endif
diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c
index be6455ee9..b2fb902eb 100644
--- a/quantum/process_keycode/process_midi.c
+++ b/quantum/process_keycode/process_midi.c
@@ -16,86 +16,65 @@
16#include "process_midi.h" 16#include "process_midi.h"
17 17
18#ifdef MIDI_ENABLE 18#ifdef MIDI_ENABLE
19#include <LUFA/Drivers/USB/USB.h> 19# include <LUFA/Drivers/USB/USB.h>
20#include "midi.h" 20# include "midi.h"
21#include "qmk_midi.h" 21# include "qmk_midi.h"
22 22
23#ifdef MIDI_BASIC 23# ifdef MIDI_BASIC
24 24
25void process_midi_basic_noteon(uint8_t note) 25void process_midi_basic_noteon(uint8_t note) { midi_send_noteon(&midi_device, 0, note, 127); }
26{
27 midi_send_noteon(&midi_device, 0, note, 127);
28}
29 26
30void process_midi_basic_noteoff(uint8_t note) 27void process_midi_basic_noteoff(uint8_t note) { midi_send_noteoff(&midi_device, 0, note, 0); }
31{
32 midi_send_noteoff(&midi_device, 0, note, 0);
33}
34 28
35void process_midi_all_notes_off(void) 29void process_midi_all_notes_off(void) { midi_send_cc(&midi_device, 0, 0x7B, 0); }
36{
37 midi_send_cc(&midi_device, 0, 0x7B, 0);
38}
39 30
40#endif // MIDI_BASIC 31# endif // MIDI_BASIC
41 32
42#ifdef MIDI_ADVANCED 33# ifdef MIDI_ADVANCED
43 34
44#include "timer.h" 35# include "timer.h"
45 36
46static uint8_t tone_status[MIDI_TONE_COUNT]; 37static uint8_t tone_status[MIDI_TONE_COUNT];
47 38
48static uint8_t midi_modulation; 39static uint8_t midi_modulation;
49static int8_t midi_modulation_step; 40static int8_t midi_modulation_step;
50static uint16_t midi_modulation_timer; 41static uint16_t midi_modulation_timer;
51midi_config_t midi_config; 42midi_config_t midi_config;
52 43
53inline uint8_t compute_velocity(uint8_t setting) 44inline uint8_t compute_velocity(uint8_t setting) { return (setting + 1) * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN + 1)); }
54{
55 return (setting + 1) * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN + 1));
56}
57 45
58void midi_init(void) 46void midi_init(void) {
59{ 47 midi_config.octave = MI_OCT_2 - MIDI_OCTAVE_MIN;
60 midi_config.octave = MI_OCT_2 - MIDI_OCTAVE_MIN; 48 midi_config.transpose = 0;
61 midi_config.transpose = 0; 49 midi_config.velocity = (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN);
62 midi_config.velocity = (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN); 50 midi_config.channel = 0;
63 midi_config.channel = 0;
64 midi_config.modulation_interval = 8; 51 midi_config.modulation_interval = 8;
65 52
66 for (uint8_t i = 0; i < MIDI_TONE_COUNT; i++) 53 for (uint8_t i = 0; i < MIDI_TONE_COUNT; i++) {
67 {
68 tone_status[i] = MIDI_INVALID_NOTE; 54 tone_status[i] = MIDI_INVALID_NOTE;
69 } 55 }
70 56
71 midi_modulation = 0; 57 midi_modulation = 0;
72 midi_modulation_step = 0; 58 midi_modulation_step = 0;
73 midi_modulation_timer = 0; 59 midi_modulation_timer = 0;
74} 60}
75 61
76uint8_t midi_compute_note(uint16_t keycode) 62uint8_t midi_compute_note(uint16_t keycode) { return 12 * midi_config.octave + (keycode - MIDI_TONE_MIN) + midi_config.transpose; }
77{
78 return 12 * midi_config.octave + (keycode - MIDI_TONE_MIN) + midi_config.transpose;
79}
80 63
81bool process_midi(uint16_t keycode, keyrecord_t *record) 64bool process_midi(uint16_t keycode, keyrecord_t *record) {
82{
83 switch (keycode) { 65 switch (keycode) {
84 case MIDI_TONE_MIN ... MIDI_TONE_MAX: 66 case MIDI_TONE_MIN ... MIDI_TONE_MAX: {
85 { 67 uint8_t channel = midi_config.channel;
86 uint8_t channel = midi_config.channel; 68 uint8_t tone = keycode - MIDI_TONE_MIN;
87 uint8_t tone = keycode - MIDI_TONE_MIN;
88 uint8_t velocity = compute_velocity(midi_config.velocity); 69 uint8_t velocity = compute_velocity(midi_config.velocity);
89 if (record->event.pressed) { 70 if (record->event.pressed) {
90 uint8_t note = midi_compute_note(keycode); 71 uint8_t note = midi_compute_note(keycode);
91 midi_send_noteon(&midi_device, channel, note, velocity); 72 midi_send_noteon(&midi_device, channel, note, velocity);
92 dprintf("midi noteon channel:%d note:%d velocity:%d\n", channel, note, velocity); 73 dprintf("midi noteon channel:%d note:%d velocity:%d\n", channel, note, velocity);
93 tone_status[tone] = note; 74 tone_status[tone] = note;
94 } 75 } else {
95 else {
96 uint8_t note = tone_status[tone]; 76 uint8_t note = tone_status[tone];
97 if (note != MIDI_INVALID_NOTE) 77 if (note != MIDI_INVALID_NOTE) {
98 {
99 midi_send_noteoff(&midi_device, channel, note, velocity); 78 midi_send_noteoff(&midi_device, channel, note, velocity);
100 dprintf("midi noteoff channel:%d note:%d velocity:%d\n", channel, note, velocity); 79 dprintf("midi noteoff channel:%d note:%d velocity:%d\n", channel, note, velocity);
101 } 80 }
@@ -137,8 +116,7 @@ bool process_midi(uint16_t keycode, keyrecord_t *record)
137 if (record->event.pressed && midi_config.transpose < (MIDI_TRANSPOSE_MAX - MI_TRNS_0)) { 116 if (record->event.pressed && midi_config.transpose < (MIDI_TRANSPOSE_MAX - MI_TRNS_0)) {
138 const bool positive = midi_config.transpose > 0; 117 const bool positive = midi_config.transpose > 0;
139 midi_config.transpose++; 118 midi_config.transpose++;
140 if (positive && midi_config.transpose < 0) 119 if (positive && midi_config.transpose < 0) midi_config.transpose--;
141 midi_config.transpose--;
142 dprintf("midi transpose %d\n", midi_config.transpose); 120 dprintf("midi transpose %d\n", midi_config.transpose);
143 } 121 }
144 return false; 122 return false;
@@ -211,8 +189,7 @@ bool process_midi(uint16_t keycode, keyrecord_t *record)
211 if (record->event.pressed) { 189 if (record->event.pressed) {
212 midi_config.modulation_interval++; 190 midi_config.modulation_interval++;
213 // prevent overflow 191 // prevent overflow
214 if (midi_config.modulation_interval == 0) 192 if (midi_config.modulation_interval == 0) midi_config.modulation_interval--;
215 midi_config.modulation_interval--;
216 dprintf("midi modulation interval %d\n", midi_config.modulation_interval); 193 dprintf("midi modulation interval %d\n", midi_config.modulation_interval);
217 } 194 }
218 return false; 195 return false;
@@ -226,8 +203,7 @@ bool process_midi(uint16_t keycode, keyrecord_t *record)
226 if (record->event.pressed) { 203 if (record->event.pressed) {
227 midi_send_pitchbend(&midi_device, midi_config.channel, -0x2000); 204 midi_send_pitchbend(&midi_device, midi_config.channel, -0x2000);
228 dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, -0x2000); 205 dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, -0x2000);
229 } 206 } else {
230 else {
231 midi_send_pitchbend(&midi_device, midi_config.channel, 0); 207 midi_send_pitchbend(&midi_device, midi_config.channel, 0);
232 dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, 0); 208 dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, 0);
233 } 209 }
@@ -236,8 +212,7 @@ bool process_midi(uint16_t keycode, keyrecord_t *record)
236 if (record->event.pressed) { 212 if (record->event.pressed) {
237 midi_send_pitchbend(&midi_device, midi_config.channel, 0x1fff); 213 midi_send_pitchbend(&midi_device, midi_config.channel, 0x1fff);
238 dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, 0x1fff); 214 dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, 0x1fff);
239 } 215 } else {
240 else {
241 midi_send_pitchbend(&midi_device, midi_config.channel, 0); 216 midi_send_pitchbend(&midi_device, midi_config.channel, 0);
242 dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, 0); 217 dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, 0);
243 } 218 }
@@ -247,35 +222,29 @@ bool process_midi(uint16_t keycode, keyrecord_t *record)
247 return true; 222 return true;
248} 223}
249 224
250#endif // MIDI_ADVANCED 225# endif // MIDI_ADVANCED
251 226
252void midi_task(void) 227void midi_task(void) {
253{
254 midi_device_process(&midi_device); 228 midi_device_process(&midi_device);
255#ifdef MIDI_ADVANCED 229# ifdef MIDI_ADVANCED
256 if (timer_elapsed(midi_modulation_timer) < midi_config.modulation_interval) 230 if (timer_elapsed(midi_modulation_timer) < midi_config.modulation_interval) return;
257 return;
258 midi_modulation_timer = timer_read(); 231 midi_modulation_timer = timer_read();
259 232
260 if (midi_modulation_step != 0) 233 if (midi_modulation_step != 0) {
261 {
262 dprintf("midi modulation %d\n", midi_modulation); 234 dprintf("midi modulation %d\n", midi_modulation);
263 midi_send_cc(&midi_device, midi_config.channel, 0x1, midi_modulation); 235 midi_send_cc(&midi_device, midi_config.channel, 0x1, midi_modulation);
264 236
265 if (midi_modulation_step < 0 && midi_modulation < -midi_modulation_step) { 237 if (midi_modulation_step < 0 && midi_modulation < -midi_modulation_step) {
266 midi_modulation = 0; 238 midi_modulation = 0;
267 midi_modulation_step = 0; 239 midi_modulation_step = 0;
268 return; 240 return;
269 } 241 }
270 242
271 midi_modulation += midi_modulation_step; 243 midi_modulation += midi_modulation_step;
272 244
273 if (midi_modulation > 127) 245 if (midi_modulation > 127) midi_modulation = 127;
274 midi_modulation = 127;
275 } 246 }
276#endif 247# endif
277} 248}
278 249
279 250#endif // MIDI_ENABLE
280
281#endif // MIDI_ENABLE
diff --git a/quantum/process_keycode/process_midi.h b/quantum/process_keycode/process_midi.h
index 1968fbe3f..0007b3ed2 100644
--- a/quantum/process_keycode/process_midi.h
+++ b/quantum/process_keycode/process_midi.h
@@ -21,24 +21,24 @@
21 21
22#ifdef MIDI_ENABLE 22#ifdef MIDI_ENABLE
23 23
24#ifdef MIDI_BASIC 24# ifdef MIDI_BASIC
25void process_midi_basic_noteon(uint8_t note); 25void process_midi_basic_noteon(uint8_t note);
26void process_midi_basic_noteoff(uint8_t note); 26void process_midi_basic_noteoff(uint8_t note);
27void process_midi_all_notes_off(void); 27void process_midi_all_notes_off(void);
28#endif 28# endif
29 29
30void midi_task(void); 30void midi_task(void);
31 31
32#ifdef MIDI_ADVANCED 32# ifdef MIDI_ADVANCED
33typedef union { 33typedef union {
34 uint32_t raw; 34 uint32_t raw;
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 : 4;
39 uint8_t channel :4; 39 uint8_t channel : 4;
40 uint8_t modulation_interval :4; 40 uint8_t modulation_interval : 4;
41 }; 41 };
42} midi_config_t; 42} midi_config_t;
43 43
44extern midi_config_t midi_config; 44extern midi_config_t midi_config;
@@ -46,12 +46,12 @@ extern midi_config_t midi_config;
46void midi_init(void); 46void midi_init(void);
47bool process_midi(uint16_t keycode, keyrecord_t *record); 47bool process_midi(uint16_t keycode, keyrecord_t *record);
48 48
49#define MIDI_INVALID_NOTE 0xFF 49# define MIDI_INVALID_NOTE 0xFF
50#define MIDI_TONE_COUNT (MIDI_TONE_MAX - MIDI_TONE_MIN + 1) 50# define MIDI_TONE_COUNT (MIDI_TONE_MAX - MIDI_TONE_MIN + 1)
51 51
52uint8_t midi_compute_note(uint16_t keycode); 52uint8_t midi_compute_note(uint16_t keycode);
53#endif // MIDI_ADVANCED 53# endif // MIDI_ADVANCED
54 54
55#endif // MIDI_ENABLE 55#endif // MIDI_ENABLE
56 56
57#endif 57#endif
diff --git a/quantum/process_keycode/process_music.c b/quantum/process_keycode/process_music.c
index 697aa237f..b61a16e87 100644
--- a/quantum/process_keycode/process_music.c
+++ b/quantum/process_keycode/process_music.c
@@ -16,103 +16,91 @@
16#include "process_music.h" 16#include "process_music.h"
17 17
18#ifdef AUDIO_ENABLE 18#ifdef AUDIO_ENABLE
19#include "process_audio.h" 19# include "process_audio.h"
20#endif 20#endif
21#if defined(MIDI_ENABLE) && defined(MIDI_BASIC) 21#if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
22#include "process_midi.h" 22# include "process_midi.h"
23#endif 23#endif
24 24
25#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) 25#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
26 26
27bool music_activated = false; 27bool music_activated = false;
28bool midi_activated = false; 28bool midi_activated = false;
29uint8_t music_starting_note = 0x0C; 29uint8_t music_starting_note = 0x0C;
30int music_offset = 7; 30int music_offset = 7;
31uint8_t music_mode = MUSIC_MODE_MAJOR; 31uint8_t music_mode = MUSIC_MODE_MAJOR;
32 32
33// music sequencer 33// music sequencer
34static bool music_sequence_recording = false; 34static bool music_sequence_recording = false;
35static bool music_sequence_recorded = false; 35static bool music_sequence_recorded = false;
36static bool music_sequence_playing = false; 36static bool music_sequence_playing = false;
37static uint8_t music_sequence[16] = {0}; 37static uint8_t music_sequence[16] = {0};
38static uint8_t music_sequence_count = 0; 38static uint8_t music_sequence_count = 0;
39static uint8_t music_sequence_position = 0; 39static uint8_t music_sequence_position = 0;
40 40
41static uint16_t music_sequence_timer = 0; 41static uint16_t music_sequence_timer = 0;
42static uint16_t music_sequence_interval = 100; 42static uint16_t music_sequence_interval = 100;
43 43
44#ifdef AUDIO_ENABLE 44# ifdef AUDIO_ENABLE
45 #ifndef MUSIC_ON_SONG 45# ifndef MUSIC_ON_SONG
46 #define MUSIC_ON_SONG SONG(MUSIC_ON_SOUND) 46# define MUSIC_ON_SONG SONG(MUSIC_ON_SOUND)
47 #endif 47# endif
48 #ifndef MUSIC_OFF_SONG 48# ifndef MUSIC_OFF_SONG
49 #define MUSIC_OFF_SONG SONG(MUSIC_OFF_SOUND) 49# define MUSIC_OFF_SONG SONG(MUSIC_OFF_SOUND)
50 #endif 50# endif
51 #ifndef MIDI_ON_SONG 51# ifndef MIDI_ON_SONG
52 #define MIDI_ON_SONG SONG(MUSIC_ON_SOUND) 52# define MIDI_ON_SONG SONG(MUSIC_ON_SOUND)
53 #endif 53# endif
54 #ifndef MIDI_OFF_SONG 54# ifndef MIDI_OFF_SONG
55 #define MIDI_OFF_SONG SONG(MUSIC_OFF_SOUND) 55# define MIDI_OFF_SONG SONG(MUSIC_OFF_SOUND)
56 #endif 56# endif
57 #ifndef CHROMATIC_SONG 57# ifndef CHROMATIC_SONG
58 #define CHROMATIC_SONG SONG(CHROMATIC_SOUND) 58# define CHROMATIC_SONG SONG(CHROMATIC_SOUND)
59 #endif 59# endif
60 #ifndef GUITAR_SONG 60# ifndef GUITAR_SONG
61 #define GUITAR_SONG SONG(GUITAR_SOUND) 61# define GUITAR_SONG SONG(GUITAR_SOUND)
62 #endif 62# endif
63 #ifndef VIOLIN_SONG 63# ifndef VIOLIN_SONG
64 #define VIOLIN_SONG SONG(VIOLIN_SOUND) 64# define VIOLIN_SONG SONG(VIOLIN_SOUND)
65 #endif 65# endif
66 #ifndef MAJOR_SONG 66# ifndef MAJOR_SONG
67 #define MAJOR_SONG SONG(MAJOR_SOUND) 67# define MAJOR_SONG SONG(MAJOR_SOUND)
68 #endif 68# endif
69 float music_mode_songs[NUMBER_OF_MODES][5][2] = { 69float music_mode_songs[NUMBER_OF_MODES][5][2] = {CHROMATIC_SONG, GUITAR_SONG, VIOLIN_SONG, MAJOR_SONG};
70 CHROMATIC_SONG, 70float music_on_song[][2] = MUSIC_ON_SONG;
71 GUITAR_SONG, 71float music_off_song[][2] = MUSIC_OFF_SONG;
72 VIOLIN_SONG, 72float midi_on_song[][2] = MIDI_ON_SONG;
73 MAJOR_SONG 73float midi_off_song[][2] = MIDI_OFF_SONG;
74 }; 74# endif
75 float music_on_song[][2] = MUSIC_ON_SONG;
76 float music_off_song[][2] = MUSIC_OFF_SONG;
77 float midi_on_song[][2] = MIDI_ON_SONG;
78 float midi_off_song[][2] = MIDI_OFF_SONG;
79#endif
80 75
81static void music_noteon(uint8_t note) { 76static void music_noteon(uint8_t note) {
82 #ifdef AUDIO_ENABLE 77# ifdef AUDIO_ENABLE
83 if (music_activated) 78 if (music_activated) process_audio_noteon(note);
84 process_audio_noteon(note); 79# endif
85 #endif 80# if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
86 #if defined(MIDI_ENABLE) && defined(MIDI_BASIC) 81 if (midi_activated) process_midi_basic_noteon(note);
87 if (midi_activated) 82# endif
88 process_midi_basic_noteon(note);
89 #endif
90} 83}
91 84
92static void music_noteoff(uint8_t note) { 85static void music_noteoff(uint8_t note) {
93 #ifdef AUDIO_ENABLE 86# ifdef AUDIO_ENABLE
94 if (music_activated) 87 if (music_activated) process_audio_noteoff(note);
95 process_audio_noteoff(note); 88# endif
96 #endif 89# if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
97 #if defined(MIDI_ENABLE) && defined(MIDI_BASIC) 90 if (midi_activated) process_midi_basic_noteoff(note);
98 if (midi_activated) 91# endif
99 process_midi_basic_noteoff(note);
100 #endif
101} 92}
102 93
103void music_all_notes_off(void) { 94void music_all_notes_off(void) {
104 #ifdef AUDIO_ENABLE 95# ifdef AUDIO_ENABLE
105 if (music_activated) 96 if (music_activated) process_audio_all_notes_off();
106 process_audio_all_notes_off(); 97# endif
107 #endif 98# if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
108 #if defined(MIDI_ENABLE) && defined(MIDI_BASIC) 99 if (midi_activated) process_midi_all_notes_off();
109 if (midi_activated) 100# endif
110 process_midi_all_notes_off();
111 #endif
112} 101}
113 102
114bool process_music(uint16_t keycode, keyrecord_t *record) { 103bool process_music(uint16_t keycode, keyrecord_t *record) {
115
116 if (keycode == MU_ON && record->event.pressed) { 104 if (keycode == MU_ON && record->event.pressed) {
117 music_on(); 105 music_on();
118 return false; 106 return false;
@@ -152,110 +140,101 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
152 } 140 }
153 141
154 if (keycode == MU_MOD && record->event.pressed) { 142 if (keycode == MU_MOD && record->event.pressed) {
155 music_mode_cycle(); 143 music_mode_cycle();
156 return false; 144 return false;
157 } 145 }
158 146
159 if (music_activated || midi_activated) { 147 if (music_activated || midi_activated) {
160 if (record->event.pressed) { 148 if (record->event.pressed) {
161 if (keycode == KC_LCTL) { // Start recording 149 if (keycode == KC_LCTL) { // Start recording
162 music_all_notes_off(); 150 music_all_notes_off();
163 music_sequence_recording = true; 151 music_sequence_recording = true;
164 music_sequence_recorded = false; 152 music_sequence_recorded = false;
165 music_sequence_playing = false; 153 music_sequence_playing = false;
166 music_sequence_count = 0; 154 music_sequence_count = 0;
167 return false; 155 return false;
168 } 156 }
169 157
170 if (keycode == KC_LALT) { // Stop recording/playing 158 if (keycode == KC_LALT) { // Stop recording/playing
171 music_all_notes_off(); 159 music_all_notes_off();
172 if (music_sequence_recording) { // was recording 160 if (music_sequence_recording) { // was recording
173 music_sequence_recorded = true; 161 music_sequence_recorded = true;
174 } 162 }
175 music_sequence_recording = false; 163 music_sequence_recording = false;
176 music_sequence_playing = false; 164 music_sequence_playing = false;
177 return false; 165 return false;
178 } 166 }
179 167
180 if (keycode == KC_LGUI && music_sequence_recorded) { // Start playing 168 if (keycode == KC_LGUI && music_sequence_recorded) { // Start playing
181 music_all_notes_off(); 169 music_all_notes_off();
182 music_sequence_recording = false; 170 music_sequence_recording = false;
183 music_sequence_playing = true; 171 music_sequence_playing = true;
184 music_sequence_position = 0; 172 music_sequence_position = 0;
185 music_sequence_timer = 0; 173 music_sequence_timer = 0;
186 return false; 174 return false;
187 } 175 }
188 176
189 if (keycode == KC_UP) { 177 if (keycode == KC_UP) {
190 music_sequence_interval-=10; 178 music_sequence_interval -= 10;
191 return false; 179 return false;
180 }
181
182 if (keycode == KC_DOWN) {
183 music_sequence_interval += 10;
184 return false;
185 }
192 } 186 }
193 187
194 if (keycode == KC_DOWN) { 188 uint8_t note = 36;
195 music_sequence_interval+=10; 189# ifdef MUSIC_MAP
196 return false;
197 }
198 }
199
200 uint8_t note = 36;
201 #ifdef MUSIC_MAP
202 if (music_mode == MUSIC_MODE_CHROMATIC) { 190 if (music_mode == MUSIC_MODE_CHROMATIC) {
203 note = music_starting_note + music_offset + 36 + music_map[record->event.key.row][record->event.key.col]; 191 note = music_starting_note + music_offset + 36 + music_map[record->event.key.row][record->event.key.col];
204 } else { 192 } else {
205 uint8_t position = music_map[record->event.key.row][record->event.key.col]; 193 uint8_t position = music_map[record->event.key.row][record->event.key.col];
206 note = music_starting_note + music_offset + 36 + SCALE[position % 12] + (position / 12)*12; 194 note = music_starting_note + music_offset + 36 + SCALE[position % 12] + (position / 12) * 12;
207 } 195 }
208 #else 196# else
209 if (music_mode == MUSIC_MODE_CHROMATIC) 197 if (music_mode == MUSIC_MODE_CHROMATIC)
210 note = (music_starting_note + record->event.key.col + music_offset - 3)+12*(MATRIX_ROWS - record->event.key.row); 198 note = (music_starting_note + record->event.key.col + music_offset - 3) + 12 * (MATRIX_ROWS - record->event.key.row);
211 else if (music_mode == MUSIC_MODE_GUITAR) 199 else if (music_mode == MUSIC_MODE_GUITAR)
212 note = (music_starting_note + record->event.key.col + music_offset + 32)+5*(MATRIX_ROWS - record->event.key.row); 200 note = (music_starting_note + record->event.key.col + music_offset + 32) + 5 * (MATRIX_ROWS - record->event.key.row);
213 else if (music_mode == MUSIC_MODE_VIOLIN) 201 else if (music_mode == MUSIC_MODE_VIOLIN)
214 note = (music_starting_note + record->event.key.col + music_offset + 32)+7*(MATRIX_ROWS - record->event.key.row); 202 note = (music_starting_note + record->event.key.col + music_offset + 32) + 7 * (MATRIX_ROWS - record->event.key.row);
215 else if (music_mode == MUSIC_MODE_MAJOR) 203 else if (music_mode == MUSIC_MODE_MAJOR)
216 note = (music_starting_note + SCALE[record->event.key.col + music_offset] - 3)+12*(MATRIX_ROWS - record->event.key.row); 204 note = (music_starting_note + SCALE[record->event.key.col + music_offset] - 3) + 12 * (MATRIX_ROWS - record->event.key.row);
217 else 205 else
218 note = music_starting_note; 206 note = music_starting_note;
219 #endif 207# endif
220 208
221 if (record->event.pressed) { 209 if (record->event.pressed) {
222 music_noteon(note); 210 music_noteon(note);
223 if (music_sequence_recording) { 211 if (music_sequence_recording) {
224 music_sequence[music_sequence_count] = note; 212 music_sequence[music_sequence_count] = note;
225 music_sequence_count++; 213 music_sequence_count++;
214 }
215 } else {
216 music_noteoff(note);
226 } 217 }
227 } else {
228 music_noteoff(note);
229 }
230 218
231 if (music_mask(keycode)) 219 if (music_mask(keycode)) return false;
232 return false;
233 } 220 }
234 221
235 return true; 222 return true;
236} 223}
237 224
238bool music_mask(uint16_t keycode) { 225bool music_mask(uint16_t keycode) {
239 #ifdef MUSIC_MASK 226# ifdef MUSIC_MASK
240 return MUSIC_MASK; 227 return MUSIC_MASK;
241 #else 228# else
242 return music_mask_kb(keycode); 229 return music_mask_kb(keycode);
243 #endif 230# endif
244} 231}
245 232
246__attribute__((weak)) 233__attribute__((weak)) bool music_mask_kb(uint16_t keycode) { return music_mask_user(keycode); }
247bool music_mask_kb(uint16_t keycode) {
248 return music_mask_user(keycode);
249}
250 234
251__attribute__((weak)) 235__attribute__((weak)) bool music_mask_user(uint16_t keycode) { return keycode < 0xFF; }
252bool music_mask_user(uint16_t keycode) {
253 return keycode < 0xFF;
254}
255 236
256bool is_music_on(void) { 237bool is_music_on(void) { return (music_activated != 0); }
257 return (music_activated != 0);
258}
259 238
260void music_toggle(void) { 239void music_toggle(void) {
261 if (!music_activated) { 240 if (!music_activated) {
@@ -267,23 +246,21 @@ void music_toggle(void) {
267 246
268void music_on(void) { 247void music_on(void) {
269 music_activated = 1; 248 music_activated = 1;
270 #ifdef AUDIO_ENABLE 249# ifdef AUDIO_ENABLE
271 PLAY_SONG(music_on_song); 250 PLAY_SONG(music_on_song);
272 #endif 251# endif
273 music_on_user(); 252 music_on_user();
274} 253}
275 254
276void music_off(void) { 255void music_off(void) {
277 music_all_notes_off(); 256 music_all_notes_off();
278 music_activated = 0; 257 music_activated = 0;
279 #ifdef AUDIO_ENABLE 258# ifdef AUDIO_ENABLE
280 PLAY_SONG(music_off_song); 259 PLAY_SONG(music_off_song);
281 #endif 260# endif
282} 261}
283 262
284bool is_midi_on(void) { 263bool is_midi_on(void) { return (midi_activated != 0); }
285 return (midi_activated != 0);
286}
287 264
288void midi_toggle(void) { 265void midi_toggle(void) {
289 if (!midi_activated) { 266 if (!midi_activated) {
@@ -295,50 +272,47 @@ void midi_toggle(void) {
295 272
296void midi_on(void) { 273void midi_on(void) {
297 midi_activated = 1; 274 midi_activated = 1;
298 #ifdef AUDIO_ENABLE 275# ifdef AUDIO_ENABLE
299 PLAY_SONG(midi_on_song); 276 PLAY_SONG(midi_on_song);
300 #endif 277# endif
301 midi_on_user(); 278 midi_on_user();
302} 279}
303 280
304void midi_off(void) { 281void midi_off(void) {
305 #if defined(MIDI_ENABLE) && defined(MIDI_BASIC) 282# if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
306 process_midi_all_notes_off(); 283 process_midi_all_notes_off();
307 #endif 284# endif
308 midi_activated = 0; 285 midi_activated = 0;
309 #ifdef AUDIO_ENABLE 286# ifdef AUDIO_ENABLE
310 PLAY_SONG(midi_off_song); 287 PLAY_SONG(midi_off_song);
311 #endif 288# endif
312} 289}
313 290
314void music_mode_cycle(void) { 291void music_mode_cycle(void) {
315 music_all_notes_off(); 292 music_all_notes_off();
316 music_mode = (music_mode + 1) % NUMBER_OF_MODES; 293 music_mode = (music_mode + 1) % NUMBER_OF_MODES;
317 #ifdef AUDIO_ENABLE 294# ifdef AUDIO_ENABLE
318 PLAY_SONG(music_mode_songs[music_mode]); 295 PLAY_SONG(music_mode_songs[music_mode]);
319 #endif 296# endif
320} 297}
321 298
322void matrix_scan_music(void) { 299void matrix_scan_music(void) {
323 if (music_sequence_playing) { 300 if (music_sequence_playing) {
324 if ((music_sequence_timer == 0) || (timer_elapsed(music_sequence_timer) > music_sequence_interval)) { 301 if ((music_sequence_timer == 0) || (timer_elapsed(music_sequence_timer) > music_sequence_interval)) {
325 music_sequence_timer = timer_read(); 302 music_sequence_timer = timer_read();
326 uint8_t prev_note = music_sequence[(music_sequence_position - 1 < 0)?(music_sequence_position - 1 + music_sequence_count):(music_sequence_position - 1)]; 303 uint8_t prev_note = music_sequence[(music_sequence_position - 1 < 0) ? (music_sequence_position - 1 + music_sequence_count) : (music_sequence_position - 1)];
327 uint8_t next_note = music_sequence[music_sequence_position]; 304 uint8_t next_note = music_sequence[music_sequence_position];
328 music_noteoff(prev_note); 305 music_noteoff(prev_note);
329 music_noteon(next_note); 306 music_noteon(next_note);
330 music_sequence_position = (music_sequence_position + 1) % music_sequence_count; 307 music_sequence_position = (music_sequence_position + 1) % music_sequence_count;
308 }
331 } 309 }
332 }
333} 310}
334 311
335__attribute__ ((weak)) 312__attribute__((weak)) void music_on_user() {}
336void music_on_user() {}
337 313
338__attribute__ ((weak)) 314__attribute__((weak)) void midi_on_user() {}
339void midi_on_user() {}
340 315
341__attribute__ ((weak)) 316__attribute__((weak)) void music_scale_user() {}
342void music_scale_user() {}
343 317
344#endif // defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) 318#endif // defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
diff --git a/quantum/process_keycode/process_music.h b/quantum/process_keycode/process_music.h
index f6753d4f2..292bc5374 100644
--- a/quantum/process_keycode/process_music.h
+++ b/quantum/process_keycode/process_music.h
@@ -21,18 +21,11 @@
21 21
22#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) 22#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
23 23
24enum music_modes { 24enum music_modes { MUSIC_MODE_CHROMATIC, MUSIC_MODE_GUITAR, MUSIC_MODE_VIOLIN, MUSIC_MODE_MAJOR, NUMBER_OF_MODES };
25 MUSIC_MODE_CHROMATIC,
26 MUSIC_MODE_GUITAR,
27 MUSIC_MODE_VIOLIN,
28 MUSIC_MODE_MAJOR,
29 NUMBER_OF_MODES
30};
31 25
32 26# ifdef MUSIC_MAP
33#ifdef MUSIC_MAP 27extern const uint8_t music_map[MATRIX_ROWS][MATRIX_COLS];
34 extern const uint8_t music_map[MATRIX_ROWS][MATRIX_COLS]; 28# endif
35#endif
36 29
37bool process_music(uint16_t keycode, keyrecord_t *record); 30bool process_music(uint16_t keycode, keyrecord_t *record);
38 31
@@ -58,14 +51,11 @@ bool music_mask(uint16_t keycode);
58bool music_mask_kb(uint16_t keycode); 51bool music_mask_kb(uint16_t keycode);
59bool music_mask_user(uint16_t keycode); 52bool music_mask_user(uint16_t keycode);
60 53
61#ifndef SCALE 54# ifndef SCALE
62#define SCALE (int8_t []){ 0 + (12*0), 2 + (12*0), 4 + (12*0), 5 + (12*0), 7 + (12*0), 9 + (12*0), 11 + (12*0), \ 55# define SCALE \
63 0 + (12*1), 2 + (12*1), 4 + (12*1), 5 + (12*1), 7 + (12*1), 9 + (12*1), 11 + (12*1), \ 56 (int8_t[]) { 0 + (12 * 0), 2 + (12 * 0), 4 + (12 * 0), 5 + (12 * 0), 7 + (12 * 0), 9 + (12 * 0), 11 + (12 * 0), 0 + (12 * 1), 2 + (12 * 1), 4 + (12 * 1), 5 + (12 * 1), 7 + (12 * 1), 9 + (12 * 1), 11 + (12 * 1), 0 + (12 * 2), 2 + (12 * 2), 4 + (12 * 2), 5 + (12 * 2), 7 + (12 * 2), 9 + (12 * 2), 11 + (12 * 2), 0 + (12 * 3), 2 + (12 * 3), 4 + (12 * 3), 5 + (12 * 3), 7 + (12 * 3), 9 + (12 * 3), 11 + (12 * 3), 0 + (12 * 4), 2 + (12 * 4), 4 + (12 * 4), 5 + (12 * 4), 7 + (12 * 4), 9 + (12 * 4), 11 + (12 * 4), }
64 0 + (12*2), 2 + (12*2), 4 + (12*2), 5 + (12*2), 7 + (12*2), 9 + (12*2), 11 + (12*2), \ 57# endif
65 0 + (12*3), 2 + (12*3), 4 + (12*3), 5 + (12*3), 7 + (12*3), 9 + (12*3), 11 + (12*3), \
66 0 + (12*4), 2 + (12*4), 4 + (12*4), 5 + (12*4), 7 + (12*4), 9 + (12*4), 11 + (12*4), }
67#endif
68 58
69#endif // defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) 59#endif // defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
70 60
71#endif 61#endif
diff --git a/quantum/process_keycode/process_printer.c b/quantum/process_keycode/process_printer.c
index 613af7018..7c5e4169a 100644
--- a/quantum/process_keycode/process_printer.c
+++ b/quantum/process_keycode/process_printer.c
@@ -17,17 +17,15 @@
17#include "process_printer.h" 17#include "process_printer.h"
18#include "action_util.h" 18#include "action_util.h"
19 19
20bool printing_enabled = false; 20bool printing_enabled = false;
21uint8_t character_shift = 0; 21uint8_t character_shift = 0;
22 22
23void enable_printing(void) { 23void enable_printing(void) {
24 printing_enabled = true; 24 printing_enabled = true;
25 serial_init(); 25 serial_init();
26} 26}
27 27
28void disable_printing(void) { 28void disable_printing(void) { printing_enabled = false; }
29 printing_enabled = false;
30}
31 29
32uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29}; 30uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29};
33 31
@@ -36,235 +34,232 @@ uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0
36// keycode_to_ascii[KC_MINS] = {0x2D, 0x5F}; 34// keycode_to_ascii[KC_MINS] = {0x2D, 0x5F};
37 35
38void print_char(char c) { 36void print_char(char c) {
39 USB_Disable(); 37 USB_Disable();
40 serial_send(c); 38 serial_send(c);
41 USB_Init(); 39 USB_Init();
42} 40}
43 41
44void print_string(char c[]) { 42void print_string(char c[]) {
45 for(uint8_t i = 0; i < strlen(c); i++) 43 for (uint8_t i = 0; i < strlen(c); i++) print_char(c[i]);
46 print_char(c[i]);
47} 44}
48 45
49void print_box_string(const char text[]) { 46void print_box_string(const char text[]) {
50 size_t len = strlen(text); 47 size_t len = strlen(text);
51 char out[len * 3 + 8]; 48 char out[len * 3 + 8];
52 out[0] = 0xDA; 49 out[0] = 0xDA;
53 for (uint8_t i = 0; i < len; i++) { 50 for (uint8_t i = 0; i < len; i++) {
54 out[i+1] = 0xC4; 51 out[i + 1] = 0xC4;
55 } 52 }
56 out[len + 1] = 0xBF; 53 out[len + 1] = 0xBF;
57 out[len + 2] = '\n'; 54 out[len + 2] = '\n';
58
59 out[len + 3] = 0xB3;
60 for (uint8_t i = 0; i < len; i++) {
61 out[len + 4 + i] = text[i];
62 }
63 out[len * 2 + 4] = 0xB3;
64 out[len * 2 + 5] = '\n';
65 55
56 out[len + 3] = 0xB3;
57 for (uint8_t i = 0; i < len; i++) {
58 out[len + 4 + i] = text[i];
59 }
60 out[len * 2 + 4] = 0xB3;
61 out[len * 2 + 5] = '\n';
66 62
67 out[len * 2 + 6] = 0xC0; 63 out[len * 2 + 6] = 0xC0;
68 for (uint8_t i = 0; i < len; i++) { 64 for (uint8_t i = 0; i < len; i++) {
69 out[len * 2 + 7 + i] = 0xC4; 65 out[len * 2 + 7 + i] = 0xC4;
70 } 66 }
71 out[len * 3 + 7] = 0xD9; 67 out[len * 3 + 7] = 0xD9;
72 out[len * 3 + 8] = '\n'; 68 out[len * 3 + 8] = '\n';
73 69
74 print_string(out); 70 print_string(out);
75} 71}
76 72
77bool process_printer(uint16_t keycode, keyrecord_t *record) { 73bool process_printer(uint16_t keycode, keyrecord_t *record) {
78 if (keycode == PRINT_ON) { 74 if (keycode == PRINT_ON) {
79 enable_printing(); 75 enable_printing();
80 return false; 76 return false;
81 } 77 }
82 if (keycode == PRINT_OFF) { 78 if (keycode == PRINT_OFF) {
83 disable_printing(); 79 disable_printing();
84 return false; 80 return false;
85 } 81 }
86
87 if (printing_enabled) {
88 switch(keycode) {
89 case KC_EXLM ... KC_RPRN:
90 case KC_UNDS:
91 case KC_PLUS:
92 case KC_LCBR:
93 case KC_RCBR:
94 case KC_PIPE:
95 case KC_TILD:
96 keycode &= 0xFF;
97 case KC_LSFT:
98 case KC_RSFT:
99 if (record->event.pressed) {
100 character_shift++;
101 } else {
102 character_shift--;
103 }
104 return false;
105 break;
106 }
107 82
108 switch(keycode) { 83 if (printing_enabled) {
109 case KC_F1: 84 switch (keycode) {
110 if (record->event.pressed) { 85 case KC_EXLM ... KC_RPRN:
111 print_box_string("This is a line of text!"); 86 case KC_UNDS:
112 } 87 case KC_PLUS:
113 return false; 88 case KC_LCBR:
114 case KC_ESC: 89 case KC_RCBR:
115 if (record->event.pressed) { 90 case KC_PIPE:
116 print_char(0x1B); 91 case KC_TILD:
117 } 92 keycode &= 0xFF;
118 return false; 93 case KC_LSFT:
119 break; 94 case KC_RSFT:
120 case KC_SPC: 95 if (record->event.pressed) {
121 if (record->event.pressed) { 96 character_shift++;
122 print_char(0x20); 97 } else {
123 } 98 character_shift--;
124 return false; 99 }
125 break; 100 return false;
126 case KC_A ... KC_Z: 101 break;
127 if (record->event.pressed) { 102 }
128 if (character_shift) {
129 print_char(0x41 + (keycode - KC_A));
130 } else {
131 print_char(0x61 + (keycode - KC_A));
132 }
133 }
134 return false;
135 break;
136 case KC_1 ... KC_0:
137 if (record->event.pressed) {
138 if (character_shift) {
139 print_char(shifted_numbers[keycode - KC_1]);
140 } else {
141 print_char(0x30 + ((keycode - KC_1 + 1) % 10));
142 }
143 }
144 return false;
145 break;
146 case KC_ENT:
147 if (record->event.pressed) {
148 if (character_shift) {
149 print_char(0x0C);
150 } else {
151 print_char(0x0A);
152 }
153 }
154 return false;
155 break;
156 case KC_BSPC:
157 if (record->event.pressed) {
158 if (character_shift) {
159 print_char(0x18);
160 } else {
161 print_char(0x1A);
162 }
163 }
164 return false;
165 break;
166 case KC_DOT:
167 if (record->event.pressed) {
168 if (character_shift) {
169 print_char(0x3E);
170 } else {
171 print_char(0x2E);
172 }
173 }
174 return false;
175 break;
176 case KC_COMM:
177 if (record->event.pressed) {
178 if (character_shift) {
179 print_char(0x3C);
180 } else {
181 print_char(0x2C);
182 }
183 }
184 return false;
185 break;
186 case KC_SLSH:
187 if (record->event.pressed) {
188 if (character_shift) {
189 print_char(0x3F);
190 } else {
191 print_char(0x2F);
192 }
193 }
194 return false;
195 break;
196 case KC_QUOT:
197 if (record->event.pressed) {
198 if (character_shift) {
199 print_char(0x22);
200 } else {
201 print_char(0x27);
202 }
203 }
204 return false;
205 break;
206 case KC_GRV:
207 if (record->event.pressed) {
208 if (character_shift) {
209 print_char(0x7E);
210 } else {
211 print_char(0x60);
212 }
213 }
214 return false;
215 break;
216 case KC_MINS:
217 if (record->event.pressed) {
218 if (character_shift) {
219 print_char(0x5F);
220 } else {
221 print_char(0x2D);
222 }
223 }
224 return false;
225 break;
226 case KC_EQL:
227 if (record->event.pressed) {
228 if (character_shift) {
229 print_char(0x2B);
230 } else {
231 print_char(0x3D);
232 }
233 }
234 return false;
235 break;
236 case KC_LBRC:
237 if (record->event.pressed) {
238 if (character_shift) {
239 print_char(0x7B);
240 } else {
241 print_char(0x5B);
242 }
243 }
244 return false;
245 break;
246 case KC_RBRC:
247 if (record->event.pressed) {
248 if (character_shift) {
249 print_char(0x7D);
250 } else {
251 print_char(0x5D);
252 }
253 }
254 return false;
255 break;
256 case KC_BSLS:
257 if (record->event.pressed) {
258 if (character_shift) {
259 print_char(0x7C);
260 } else {
261 print_char(0x5C);
262 }
263 }
264 return false;
265 break;
266 }
267 }
268 return true;
269 103
104 switch (keycode) {
105 case KC_F1:
106 if (record->event.pressed) {
107 print_box_string("This is a line of text!");
108 }
109 return false;
110 case KC_ESC:
111 if (record->event.pressed) {
112 print_char(0x1B);
113 }
114 return false;
115 break;
116 case KC_SPC:
117 if (record->event.pressed) {
118 print_char(0x20);
119 }
120 return false;
121 break;
122 case KC_A ... KC_Z:
123 if (record->event.pressed) {
124 if (character_shift) {
125 print_char(0x41 + (keycode - KC_A));
126 } else {
127 print_char(0x61 + (keycode - KC_A));
128 }
129 }
130 return false;
131 break;
132 case KC_1 ... KC_0:
133 if (record->event.pressed) {
134 if (character_shift) {
135 print_char(shifted_numbers[keycode - KC_1]);
136 } else {
137 print_char(0x30 + ((keycode - KC_1 + 1) % 10));
138 }
139 }
140 return false;
141 break;
142 case KC_ENT:
143 if (record->event.pressed) {
144 if (character_shift) {
145 print_char(0x0C);
146 } else {
147 print_char(0x0A);
148 }
149 }
150 return false;
151 break;
152 case KC_BSPC:
153 if (record->event.pressed) {
154 if (character_shift) {
155 print_char(0x18);
156 } else {
157 print_char(0x1A);
158 }
159 }
160 return false;
161 break;
162 case KC_DOT:
163 if (record->event.pressed) {
164 if (character_shift) {
165 print_char(0x3E);
166 } else {
167 print_char(0x2E);
168 }
169 }
170 return false;
171 break;
172 case KC_COMM:
173 if (record->event.pressed) {
174 if (character_shift) {
175 print_char(0x3C);
176 } else {
177 print_char(0x2C);
178 }
179 }
180 return false;
181 break;
182 case KC_SLSH:
183 if (record->event.pressed) {
184 if (character_shift) {
185 print_char(0x3F);
186 } else {
187 print_char(0x2F);
188 }
189 }
190 return false;
191 break;
192 case KC_QUOT:
193 if (record->event.pressed) {
194 if (character_shift) {
195 print_char(0x22);
196 } else {
197 print_char(0x27);
198 }
199 }
200 return false;
201 break;
202 case KC_GRV:
203 if (record->event.pressed) {
204 if (character_shift) {
205 print_char(0x7E);
206 } else {
207 print_char(0x60);
208 }
209 }
210 return false;
211 break;
212 case KC_MINS:
213 if (record->event.pressed) {
214 if (character_shift) {
215 print_char(0x5F);
216 } else {
217 print_char(0x2D);
218 }
219 }
220 return false;
221 break;
222 case KC_EQL:
223 if (record->event.pressed) {
224 if (character_shift) {
225 print_char(0x2B);
226 } else {
227 print_char(0x3D);
228 }
229 }
230 return false;
231 break;
232 case KC_LBRC:
233 if (record->event.pressed) {
234 if (character_shift) {
235 print_char(0x7B);
236 } else {
237 print_char(0x5B);
238 }
239 }
240 return false;
241 break;
242 case KC_RBRC:
243 if (record->event.pressed) {
244 if (character_shift) {
245 print_char(0x7D);
246 } else {
247 print_char(0x5D);
248 }
249 }
250 return false;
251 break;
252 case KC_BSLS:
253 if (record->event.pressed) {
254 if (character_shift) {
255 print_char(0x7C);
256 } else {
257 print_char(0x5C);
258 }
259 }
260 return false;
261 break;
262 }
263 }
264 return true;
270} 265}
diff --git a/quantum/process_keycode/process_printer_bb.c b/quantum/process_keycode/process_printer_bb.c
index 3a00f169d..e482d8259 100644
--- a/quantum/process_keycode/process_printer_bb.c
+++ b/quantum/process_keycode/process_printer_bb.c
@@ -17,44 +17,29 @@
17#include "process_printer.h" 17#include "process_printer.h"
18#include "action_util.h" 18#include "action_util.h"
19 19
20bool printing_enabled = false; 20bool printing_enabled = false;
21uint8_t character_shift = 0; 21uint8_t character_shift = 0;
22 22
23#define SERIAL_PIN_DDR DDRD 23#define SERIAL_PIN_DDR DDRD
24#define SERIAL_PIN_PORT PORTD 24#define SERIAL_PIN_PORT PORTD
25#define SERIAL_PIN_MASK _BV(PD3) 25#define SERIAL_PIN_MASK _BV(PD3)
26#define SERIAL_DELAY 52 26#define SERIAL_DELAY 52
27 27
28inline static 28inline static void serial_delay(void) { _delay_us(SERIAL_DELAY); }
29void serial_delay(void) {
30 _delay_us(SERIAL_DELAY);
31}
32 29
33inline static 30inline static void serial_high(void) { SERIAL_PIN_PORT |= SERIAL_PIN_MASK; }
34void serial_high(void) {
35 SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
36}
37 31
38inline static 32inline static void serial_low(void) { SERIAL_PIN_PORT &= ~SERIAL_PIN_MASK; }
39void serial_low(void) {
40 SERIAL_PIN_PORT &= ~SERIAL_PIN_MASK;
41}
42
43inline static
44void serial_output(void) {
45 SERIAL_PIN_DDR |= SERIAL_PIN_MASK;
46}
47 33
34inline static void serial_output(void) { SERIAL_PIN_DDR |= SERIAL_PIN_MASK; }
48 35
49void enable_printing() { 36void enable_printing() {
50 printing_enabled = true; 37 printing_enabled = true;
51 serial_output(); 38 serial_output();
52 serial_high(); 39 serial_high();
53} 40}
54 41
55void disable_printing() { 42void disable_printing() { printing_enabled = false; }
56 printing_enabled = false;
57}
58 43
59uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29}; 44uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29};
60 45
@@ -63,214 +48,212 @@ uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0
63// keycode_to_ascii[KC_MINS] = {0x2D, 0x5F}; 48// keycode_to_ascii[KC_MINS] = {0x2D, 0x5F};
64 49
65void print_char(char c) { 50void print_char(char c) {
66 uint8_t b = 8; 51 uint8_t b = 8;
67 serial_output(); 52 serial_output();
68 while( b-- ) { 53 while (b--) {
69 if(c & (1 << b)) { 54 if (c & (1 << b)) {
70 serial_high(); 55 serial_high();
71 } else { 56 } else {
72 serial_low(); 57 serial_low();
58 }
59 serial_delay();
73 } 60 }
74 serial_delay();
75 }
76} 61}
77 62
78void print_string(char c[]) { 63void print_string(char c[]) {
79 for(uint8_t i = 0; i < strlen(c); i++) 64 for (uint8_t i = 0; i < strlen(c); i++) print_char(c[i]);
80 print_char(c[i]);
81} 65}
82 66
83bool process_printer(uint16_t keycode, keyrecord_t *record) { 67bool process_printer(uint16_t keycode, keyrecord_t *record) {
84 if (keycode == PRINT_ON) { 68 if (keycode == PRINT_ON) {
85 enable_printing(); 69 enable_printing();
86 return false; 70 return false;
87 } 71 }
88 if (keycode == PRINT_OFF) { 72 if (keycode == PRINT_OFF) {
89 disable_printing(); 73 disable_printing();
90 return false; 74 return false;
91 } 75 }
92
93 if (printing_enabled) {
94 switch(keycode) {
95 case KC_EXLM ... KC_RPRN:
96 case KC_UNDS:
97 case KC_PLUS:
98 case KC_LCBR:
99 case KC_RCBR:
100 case KC_PIPE:
101 case KC_TILD:
102 keycode &= 0xFF;
103 case KC_LSFT:
104 case KC_RSFT:
105 if (record->event.pressed) {
106 character_shift++;
107 } else {
108 character_shift--;
109 }
110 return false;
111 break;
112 }
113 76
114 switch(keycode) { 77 if (printing_enabled) {
115 case KC_F1: 78 switch (keycode) {
116 if (record->event.pressed) { 79 case KC_EXLM ... KC_RPRN:
117 print_string("This is a line of text!\n\n\n"); 80 case KC_UNDS:
118 } 81 case KC_PLUS:
119 return false; 82 case KC_LCBR:
120 case KC_ESC: 83 case KC_RCBR:
121 if (record->event.pressed) { 84 case KC_PIPE:
122 print_char(0x1B); 85 case KC_TILD:
123 } 86 keycode &= 0xFF;
124 return false; 87 case KC_LSFT:
125 break; 88 case KC_RSFT:
126 case KC_SPC: 89 if (record->event.pressed) {
127 if (record->event.pressed) { 90 character_shift++;
128 print_char(0x20); 91 } else {
129 } 92 character_shift--;
130 return false; 93 }
131 break; 94 return false;
132 case KC_A ... KC_Z: 95 break;
133 if (record->event.pressed) { 96 }
134 if (character_shift) {
135 print_char(0x41 + (keycode - KC_A));
136 } else {
137 print_char(0x61 + (keycode - KC_A));
138 }
139 }
140 return false;
141 break;
142 case KC_1 ... KC_0:
143 if (record->event.pressed) {
144 if (character_shift) {
145 print_char(shifted_numbers[keycode - KC_1]);
146 } else {
147 print_char(0x30 + ((keycode - KC_1 + 1) % 10));
148 }
149 }
150 return false;
151 break;
152 case KC_ENT:
153 if (record->event.pressed) {
154 if (character_shift) {
155 print_char(0x0C);
156 } else {
157 print_char(0x0A);
158 }
159 }
160 return false;
161 break;
162 case KC_BSPC:
163 if (record->event.pressed) {
164 if (character_shift) {
165 print_char(0x18);
166 } else {
167 print_char(0x1A);
168 }
169 }
170 return false;
171 break;
172 case KC_DOT:
173 if (record->event.pressed) {
174 if (character_shift) {
175 print_char(0x3E);
176 } else {
177 print_char(0x2E);
178 }
179 }
180 return false;
181 break;
182 case KC_COMM:
183 if (record->event.pressed) {
184 if (character_shift) {
185 print_char(0x3C);
186 } else {
187 print_char(0x2C);
188 }
189 }
190 return false;
191 break;
192 case KC_SLSH:
193 if (record->event.pressed) {
194 if (character_shift) {
195 print_char(0x3F);
196 } else {
197 print_char(0x2F);
198 }
199 }
200 return false;
201 break;
202 case KC_QUOT:
203 if (record->event.pressed) {
204 if (character_shift) {
205 print_char(0x22);
206 } else {
207 print_char(0x27);
208 }
209 }
210 return false;
211 break;
212 case KC_GRV:
213 if (record->event.pressed) {
214 if (character_shift) {
215 print_char(0x7E);
216 } else {
217 print_char(0x60);
218 }
219 }
220 return false;
221 break;
222 case KC_MINS:
223 if (record->event.pressed) {
224 if (character_shift) {
225 print_char(0x5F);
226 } else {
227 print_char(0x2D);
228 }
229 }
230 return false;
231 break;
232 case KC_EQL:
233 if (record->event.pressed) {
234 if (character_shift) {
235 print_char(0x2B);
236 } else {
237 print_char(0x3D);
238 }
239 }
240 return false;
241 break;
242 case KC_LBRC:
243 if (record->event.pressed) {
244 if (character_shift) {
245 print_char(0x7B);
246 } else {
247 print_char(0x5B);
248 }
249 }
250 return false;
251 break;
252 case KC_RBRC:
253 if (record->event.pressed) {
254 if (character_shift) {
255 print_char(0x7D);
256 } else {
257 print_char(0x5D);
258 }
259 }
260 return false;
261 break;
262 case KC_BSLS:
263 if (record->event.pressed) {
264 if (character_shift) {
265 print_char(0x7C);
266 } else {
267 print_char(0x5C);
268 }
269 }
270 return false;
271 break;
272 }
273 }
274 return true;
275 97
98 switch (keycode) {
99 case KC_F1:
100 if (record->event.pressed) {
101 print_string("This is a line of text!\n\n\n");
102 }
103 return false;
104 case KC_ESC:
105 if (record->event.pressed) {
106 print_char(0x1B);
107 }
108 return false;
109 break;
110 case KC_SPC:
111 if (record->event.pressed) {
112 print_char(0x20);
113 }
114 return false;
115 break;
116 case KC_A ... KC_Z:
117 if (record->event.pressed) {
118 if (character_shift) {
119 print_char(0x41 + (keycode - KC_A));
120 } else {
121 print_char(0x61 + (keycode - KC_A));
122 }
123 }
124 return false;
125 break;
126 case KC_1 ... KC_0:
127 if (record->event.pressed) {
128 if (character_shift) {
129 print_char(shifted_numbers[keycode - KC_1]);
130 } else {
131 print_char(0x30 + ((keycode - KC_1 + 1) % 10));
132 }
133 }
134 return false;
135 break;
136 case KC_ENT:
137 if (record->event.pressed) {
138 if (character_shift) {
139 print_char(0x0C);
140 } else {
141 print_char(0x0A);
142 }
143 }
144 return false;
145 break;
146 case KC_BSPC:
147 if (record->event.pressed) {
148 if (character_shift) {
149 print_char(0x18);
150 } else {
151 print_char(0x1A);
152 }
153 }
154 return false;
155 break;
156 case KC_DOT:
157 if (record->event.pressed) {
158 if (character_shift) {
159 print_char(0x3E);
160 } else {
161 print_char(0x2E);
162 }
163 }
164 return false;
165 break;
166 case KC_COMM:
167 if (record->event.pressed) {
168 if (character_shift) {
169 print_char(0x3C);
170 } else {
171 print_char(0x2C);
172 }
173 }
174 return false;
175 break;
176 case KC_SLSH:
177 if (record->event.pressed) {
178 if (character_shift) {
179 print_char(0x3F);
180 } else {
181 print_char(0x2F);
182 }
183 }
184 return false;
185 break;
186 case KC_QUOT:
187 if (record->event.pressed) {
188 if (character_shift) {
189 print_char(0x22);
190 } else {
191 print_char(0x27);
192 }
193 }
194 return false;
195 break;
196 case KC_GRV:
197 if (record->event.pressed) {
198 if (character_shift) {
199 print_char(0x7E);
200 } else {
201 print_char(0x60);
202 }
203 }
204 return false;
205 break;
206 case KC_MINS:
207 if (record->event.pressed) {
208 if (character_shift) {
209 print_char(0x5F);
210 } else {
211 print_char(0x2D);
212 }
213 }
214 return false;
215 break;
216 case KC_EQL:
217 if (record->event.pressed) {
218 if (character_shift) {
219 print_char(0x2B);
220 } else {
221 print_char(0x3D);
222 }
223 }
224 return false;
225 break;
226 case KC_LBRC:
227 if (record->event.pressed) {
228 if (character_shift) {
229 print_char(0x7B);
230 } else {
231 print_char(0x5B);
232 }
233 }
234 return false;
235 break;
236 case KC_RBRC:
237 if (record->event.pressed) {
238 if (character_shift) {
239 print_char(0x7D);
240 } else {
241 print_char(0x5D);
242 }
243 }
244 return false;
245 break;
246 case KC_BSLS:
247 if (record->event.pressed) {
248 if (character_shift) {
249 print_char(0x7C);
250 } else {
251 print_char(0x5C);
252 }
253 }
254 return false;
255 break;
256 }
257 }
258 return true;
276} 259}
diff --git a/quantum/process_keycode/process_space_cadet.c b/quantum/process_keycode/process_space_cadet.c
index c8721d446..6833fdb9f 100644
--- a/quantum/process_keycode/process_space_cadet.c
+++ b/quantum/process_keycode/process_space_cadet.c
@@ -16,150 +16,149 @@
16#include "process_space_cadet.h" 16#include "process_space_cadet.h"
17 17
18#ifndef TAPPING_TERM 18#ifndef TAPPING_TERM
19 #define TAPPING_TERM 200 19# define TAPPING_TERM 200
20#endif 20#endif
21 21
22// ********** OBSOLETE DEFINES, STOP USING! (pls?) ********** 22// ********** OBSOLETE DEFINES, STOP USING! (pls?) **********
23// Shift / paren setup 23// Shift / paren setup
24#ifndef LSPO_KEY 24#ifndef LSPO_KEY
25 #define LSPO_KEY KC_9 25# define LSPO_KEY KC_9
26#endif 26#endif
27#ifndef RSPC_KEY 27#ifndef RSPC_KEY
28 #define RSPC_KEY KC_0 28# define RSPC_KEY KC_0
29#endif 29#endif
30 30
31// Shift / Enter setup 31// Shift / Enter setup
32#ifndef SFTENT_KEY 32#ifndef SFTENT_KEY
33 #define SFTENT_KEY KC_ENT 33# define SFTENT_KEY KC_ENT
34#endif 34#endif
35 35
36#ifdef DISABLE_SPACE_CADET_MODIFIER 36#ifdef DISABLE_SPACE_CADET_MODIFIER
37 #ifndef LSPO_MOD 37# ifndef LSPO_MOD
38 #define LSPO_MOD KC_TRNS 38# define LSPO_MOD KC_TRNS
39 #endif 39# endif
40 #ifndef RSPC_MOD 40# ifndef RSPC_MOD
41 #define RSPC_MOD KC_TRNS 41# define RSPC_MOD KC_TRNS
42 #endif 42# endif
43#else 43#else
44 #ifndef LSPO_MOD 44# ifndef LSPO_MOD
45 #define LSPO_MOD KC_LSFT 45# define LSPO_MOD KC_LSFT
46 #endif 46# endif
47 #ifndef RSPC_MOD 47# ifndef RSPC_MOD
48 #define RSPC_MOD KC_RSFT 48# define RSPC_MOD KC_RSFT
49 #endif 49# endif
50#endif 50#endif
51// ********************************************************** 51// **********************************************************
52 52
53// Shift / paren setup 53// Shift / paren setup
54#ifndef LSPO_KEYS 54#ifndef LSPO_KEYS
55 #define LSPO_KEYS KC_LSFT, LSPO_MOD, LSPO_KEY 55# define LSPO_KEYS KC_LSFT, LSPO_MOD, LSPO_KEY
56#endif 56#endif
57#ifndef RSPC_KEYS 57#ifndef RSPC_KEYS
58 #define RSPC_KEYS KC_RSFT, RSPC_MOD, RSPC_KEY 58# define RSPC_KEYS KC_RSFT, RSPC_MOD, RSPC_KEY
59#endif 59#endif
60 60
61// Control / paren setup 61// Control / paren setup
62#ifndef LCPO_KEYS 62#ifndef LCPO_KEYS
63 #define LCPO_KEYS KC_LCTL, KC_LSFT, KC_9 63# define LCPO_KEYS KC_LCTL, KC_LSFT, KC_9
64#endif 64#endif
65#ifndef RCPC_KEYS 65#ifndef RCPC_KEYS
66 #define RCPC_KEYS KC_RCTL, KC_RSFT, KC_0 66# define RCPC_KEYS KC_RCTL, KC_RSFT, KC_0
67#endif 67#endif
68 68
69// Alt / paren setup 69// Alt / paren setup
70#ifndef LAPO_KEYS 70#ifndef LAPO_KEYS
71 #define LAPO_KEYS KC_LALT, KC_LSFT, KC_9 71# define LAPO_KEYS KC_LALT, KC_LSFT, KC_9
72#endif 72#endif
73#ifndef RAPC_KEYS 73#ifndef RAPC_KEYS
74 #define RAPC_KEYS KC_RALT, KC_RSFT, KC_0 74# define RAPC_KEYS KC_RALT, KC_RSFT, KC_0
75#endif 75#endif
76 76
77// Shift / Enter setup 77// Shift / Enter setup
78#ifndef SFTENT_KEYS 78#ifndef SFTENT_KEYS
79 #define SFTENT_KEYS KC_RSFT, KC_TRNS, SFTENT_KEY 79# define SFTENT_KEYS KC_RSFT, KC_TRNS, SFTENT_KEY
80#endif 80#endif
81 81
82static uint8_t sc_last = 0; 82static uint8_t sc_last = 0;
83static uint16_t sc_timer = 0; 83static uint16_t sc_timer = 0;
84#ifdef SPACE_CADET_MODIFIER_CARRYOVER 84#ifdef SPACE_CADET_MODIFIER_CARRYOVER
85static uint8_t sc_mods = 0; 85static uint8_t sc_mods = 0;
86#endif 86#endif
87 87
88void perform_space_cadet(keyrecord_t *record, uint8_t holdMod, uint8_t tapMod, uint8_t keycode) { 88void perform_space_cadet(keyrecord_t *record, uint8_t holdMod, uint8_t tapMod, uint8_t keycode) {
89 if (record->event.pressed) { 89 if (record->event.pressed) {
90 sc_last = holdMod; 90 sc_last = holdMod;
91 sc_timer = timer_read (); 91 sc_timer = timer_read();
92#ifdef SPACE_CADET_MODIFIER_CARRYOVER 92#ifdef SPACE_CADET_MODIFIER_CARRYOVER
93 sc_mods = get_mods(); 93 sc_mods = get_mods();
94#endif 94#endif
95 if (IS_MOD(holdMod)) {
96 register_mods(MOD_BIT(holdMod));
97 }
98 }
99 else {
100 if (sc_last == holdMod && timer_elapsed(sc_timer) < TAPPING_TERM) {
101 if (holdMod != tapMod) {
102 if (IS_MOD(holdMod)) { 95 if (IS_MOD(holdMod)) {
103 unregister_mods(MOD_BIT(holdMod)); 96 register_mods(MOD_BIT(holdMod));
104 }
105 if (IS_MOD(tapMod)) {
106 register_mods(MOD_BIT(tapMod));
107 } 97 }
108 } 98 } else {
99 if (sc_last == holdMod && timer_elapsed(sc_timer) < TAPPING_TERM) {
100 if (holdMod != tapMod) {
101 if (IS_MOD(holdMod)) {
102 unregister_mods(MOD_BIT(holdMod));
103 }
104 if (IS_MOD(tapMod)) {
105 register_mods(MOD_BIT(tapMod));
106 }
107 }
109#ifdef SPACE_CADET_MODIFIER_CARRYOVER 108#ifdef SPACE_CADET_MODIFIER_CARRYOVER
110 set_weak_mods(sc_mods); 109 set_weak_mods(sc_mods);
111#endif 110#endif
112 tap_code(keycode); 111 tap_code(keycode);
113#ifdef SPACE_CADET_MODIFIER_CARRYOVER 112#ifdef SPACE_CADET_MODIFIER_CARRYOVER
114 clear_weak_mods(); 113 clear_weak_mods();
115#endif 114#endif
116 if (IS_MOD(tapMod)) { 115 if (IS_MOD(tapMod)) {
117 unregister_mods(MOD_BIT(tapMod)); 116 unregister_mods(MOD_BIT(tapMod));
118 } 117 }
119 } else { 118 } else {
120 if (IS_MOD(holdMod)) { 119 if (IS_MOD(holdMod)) {
121 unregister_mods(MOD_BIT(holdMod)); 120 unregister_mods(MOD_BIT(holdMod));
122 } 121 }
122 }
123 } 123 }
124 }
125} 124}
126 125
127bool process_space_cadet(uint16_t keycode, keyrecord_t *record) { 126bool process_space_cadet(uint16_t keycode, keyrecord_t *record) {
128 switch(keycode) { 127 switch (keycode) {
129 case KC_LSPO: { 128 case KC_LSPO: {
130 perform_space_cadet(record, LSPO_KEYS); 129 perform_space_cadet(record, LSPO_KEYS);
131 return false; 130 return false;
132 } 131 }
133 case KC_RSPC: { 132 case KC_RSPC: {
134 perform_space_cadet(record, RSPC_KEYS); 133 perform_space_cadet(record, RSPC_KEYS);
135 return false; 134 return false;
136 } 135 }
137 case KC_LCPO: { 136 case KC_LCPO: {
138 perform_space_cadet(record, LCPO_KEYS); 137 perform_space_cadet(record, LCPO_KEYS);
139 return false; 138 return false;
140 } 139 }
141 case KC_RCPC: { 140 case KC_RCPC: {
142 perform_space_cadet(record, RCPC_KEYS); 141 perform_space_cadet(record, RCPC_KEYS);
143 return false; 142 return false;
144 } 143 }
145 case KC_LAPO: { 144 case KC_LAPO: {
146 perform_space_cadet(record, LAPO_KEYS); 145 perform_space_cadet(record, LAPO_KEYS);
147 return false; 146 return false;
148 } 147 }
149 case KC_RAPC: { 148 case KC_RAPC: {
150 perform_space_cadet(record, RAPC_KEYS); 149 perform_space_cadet(record, RAPC_KEYS);
151 return false; 150 return false;
152 } 151 }
153 case KC_SFTENT: { 152 case KC_SFTENT: {
154 perform_space_cadet(record, SFTENT_KEYS); 153 perform_space_cadet(record, SFTENT_KEYS);
155 return false; 154 return false;
156 } 155 }
157 default: { 156 default: {
158 if (record->event.pressed) { 157 if (record->event.pressed) {
159 sc_last = 0; 158 sc_last = 0;
160 } 159 }
161 break; 160 break;
161 }
162 } 162 }
163 } 163 return true;
164 return true;
165} 164}
diff --git a/quantum/process_keycode/process_steno.c b/quantum/process_keycode/process_steno.c
index 50a1ef2fc..e0b33ec86 100644
--- a/quantum/process_keycode/process_steno.c
+++ b/quantum/process_keycode/process_steno.c
@@ -58,150 +58,136 @@
58#define GEMINI_STATE_SIZE 6 58#define GEMINI_STATE_SIZE 6
59#define MAX_STATE_SIZE GEMINI_STATE_SIZE 59#define MAX_STATE_SIZE GEMINI_STATE_SIZE
60 60
61static uint8_t state[MAX_STATE_SIZE] = {0}; 61static uint8_t state[MAX_STATE_SIZE] = {0};
62static uint8_t chord[MAX_STATE_SIZE] = {0}; 62static uint8_t chord[MAX_STATE_SIZE] = {0};
63static int8_t pressed = 0; 63static int8_t pressed = 0;
64static steno_mode_t mode; 64static steno_mode_t mode;
65 65
66static const uint8_t boltmap[64] PROGMEM = { 66static const uint8_t boltmap[64] PROGMEM = {TXB_NUL, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_S_L, TXB_S_L, TXB_T_L, TXB_K_L, TXB_P_L, TXB_W_L, TXB_H_L, TXB_R_L, TXB_A_L, TXB_O_L, TXB_STR, TXB_STR, TXB_NUL, TXB_NUL, TXB_NUL, TXB_STR, TXB_STR, TXB_E_R, TXB_U_R, TXB_F_R, TXB_R_R, TXB_P_R, TXB_B_R, TXB_L_R, TXB_G_R, TXB_T_R, TXB_S_R, TXB_D_R, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_Z_R};
67 TXB_NUL, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM,
68 TXB_S_L, TXB_S_L, TXB_T_L, TXB_K_L, TXB_P_L, TXB_W_L, TXB_H_L,
69 TXB_R_L, TXB_A_L, TXB_O_L, TXB_STR, TXB_STR, TXB_NUL, TXB_NUL,
70 TXB_NUL, TXB_STR, TXB_STR, TXB_E_R, TXB_U_R, TXB_F_R, TXB_R_R,
71 TXB_P_R, TXB_B_R, TXB_L_R, TXB_G_R, TXB_T_R, TXB_S_R, TXB_D_R,
72 TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_NUM, TXB_Z_R
73};
74 67
75static void steno_clear_state(void) { 68static void steno_clear_state(void) {
76 memset(state, 0, sizeof(state)); 69 memset(state, 0, sizeof(state));
77 memset(chord, 0, sizeof(chord)); 70 memset(chord, 0, sizeof(chord));
78} 71}
79 72
80static void send_steno_state(uint8_t size, bool send_empty) { 73static void send_steno_state(uint8_t size, bool send_empty) {
81 for (uint8_t i = 0; i < size; ++i) { 74 for (uint8_t i = 0; i < size; ++i) {
82 if (chord[i] || send_empty) { 75 if (chord[i] || send_empty) {
83 virtser_send(chord[i]); 76 virtser_send(chord[i]);
77 }
84 } 78 }
85 }
86} 79}
87 80
88void steno_init() { 81void steno_init() {
89 if (!eeconfig_is_enabled()) { 82 if (!eeconfig_is_enabled()) {
90 eeconfig_init(); 83 eeconfig_init();
91 } 84 }
92 mode = eeprom_read_byte(EECONFIG_STENOMODE); 85 mode = eeprom_read_byte(EECONFIG_STENOMODE);
93} 86}
94 87
95void steno_set_mode(steno_mode_t new_mode) { 88void steno_set_mode(steno_mode_t new_mode) {
96 steno_clear_state(); 89 steno_clear_state();
97 mode = new_mode; 90 mode = new_mode;
98 eeprom_update_byte(EECONFIG_STENOMODE, mode); 91 eeprom_update_byte(EECONFIG_STENOMODE, mode);
99} 92}
100 93
101/* override to intercept chords right before they get sent. 94/* override to intercept chords right before they get sent.
102 * return zero to suppress normal sending behavior. 95 * return zero to suppress normal sending behavior.
103 */ 96 */
104__attribute__ ((weak)) 97__attribute__((weak)) bool send_steno_chord_user(steno_mode_t mode, uint8_t chord[6]) { return true; }
105bool send_steno_chord_user(steno_mode_t mode, uint8_t chord[6]) { return true; }
106 98
107__attribute__ ((weak)) 99__attribute__((weak)) bool postprocess_steno_user(uint16_t keycode, keyrecord_t *record, steno_mode_t mode, uint8_t chord[6], int8_t pressed) { return true; }
108bool postprocess_steno_user(uint16_t keycode, keyrecord_t *record, steno_mode_t mode, uint8_t chord[6], int8_t pressed) { return true; }
109 100
110__attribute__ ((weak)) 101__attribute__((weak)) bool process_steno_user(uint16_t keycode, keyrecord_t *record) { return true; }
111bool process_steno_user(uint16_t keycode, keyrecord_t *record) { return true; }
112 102
113static void send_steno_chord(void) { 103static void send_steno_chord(void) {
114 if (send_steno_chord_user(mode, chord)) { 104 if (send_steno_chord_user(mode, chord)) {
115 switch(mode) { 105 switch (mode) {
116 case STENO_MODE_BOLT: 106 case STENO_MODE_BOLT:
117 send_steno_state(BOLT_STATE_SIZE, false); 107 send_steno_state(BOLT_STATE_SIZE, false);
118 virtser_send(0); // terminating byte 108 virtser_send(0); // terminating byte
119 break; 109 break;
120 case STENO_MODE_GEMINI: 110 case STENO_MODE_GEMINI:
121 chord[0] |= 0x80; // Indicate start of packet 111 chord[0] |= 0x80; // Indicate start of packet
122 send_steno_state(GEMINI_STATE_SIZE, true); 112 send_steno_state(GEMINI_STATE_SIZE, true);
123 break; 113 break;
114 }
124 } 115 }
125 } 116 steno_clear_state();
126 steno_clear_state();
127} 117}
128 118
129uint8_t *steno_get_state(void) { 119uint8_t *steno_get_state(void) { return &state[0]; }
130 return &state[0];
131}
132 120
133uint8_t *steno_get_chord(void) { 121uint8_t *steno_get_chord(void) { return &chord[0]; }
134 return &chord[0];
135}
136 122
137static bool update_state_bolt(uint8_t key, bool press) { 123static bool update_state_bolt(uint8_t key, bool press) {
138 uint8_t boltcode = pgm_read_byte(boltmap + key); 124 uint8_t boltcode = pgm_read_byte(boltmap + key);
139 if (press) { 125 if (press) {
140 state[TXB_GET_GROUP(boltcode)] |= boltcode; 126 state[TXB_GET_GROUP(boltcode)] |= boltcode;
141 chord[TXB_GET_GROUP(boltcode)] |= boltcode; 127 chord[TXB_GET_GROUP(boltcode)] |= boltcode;
142 } else { 128 } else {
143 state[TXB_GET_GROUP(boltcode)] &= ~boltcode; 129 state[TXB_GET_GROUP(boltcode)] &= ~boltcode;
144 } 130 }
145 return false; 131 return false;
146} 132}
147 133
148static bool update_state_gemini(uint8_t key, bool press) { 134static bool update_state_gemini(uint8_t key, bool press) {
149 int idx = key / 7; 135 int idx = key / 7;
150 uint8_t bit = 1 << (6 - (key % 7)); 136 uint8_t bit = 1 << (6 - (key % 7));
151 if (press) { 137 if (press) {
152 state[idx] |= bit; 138 state[idx] |= bit;
153 chord[idx] |= bit; 139 chord[idx] |= bit;
154 } else { 140 } else {
155 state[idx] &= ~bit; 141 state[idx] &= ~bit;
156 } 142 }
157 return false; 143 return false;
158} 144}
159 145
160bool process_steno(uint16_t keycode, keyrecord_t *record) { 146bool process_steno(uint16_t keycode, keyrecord_t *record) {
161 switch (keycode) { 147 switch (keycode) {
162 case QK_STENO_BOLT: 148 case QK_STENO_BOLT:
163 if (!process_steno_user(keycode, record)) { 149 if (!process_steno_user(keycode, record)) {
164 return false; 150 return false;
165 } 151 }
166 if (IS_PRESSED(record->event)) { 152 if (IS_PRESSED(record->event)) {
167 steno_set_mode(STENO_MODE_BOLT); 153 steno_set_mode(STENO_MODE_BOLT);
168 } 154 }
169 return false; 155 return false;
170 156
171 case QK_STENO_GEMINI: 157 case QK_STENO_GEMINI:
172 if (!process_steno_user(keycode, record)) { 158 if (!process_steno_user(keycode, record)) {
173 return false; 159 return false;
174 } 160 }
175 if (IS_PRESSED(record->event)) { 161 if (IS_PRESSED(record->event)) {
176 steno_set_mode(STENO_MODE_GEMINI); 162 steno_set_mode(STENO_MODE_GEMINI);
177 } 163 }
178 return false; 164 return false;
179 165
180 case STN__MIN...STN__MAX: 166 case STN__MIN ... STN__MAX:
181 if (!process_steno_user(keycode, record)) { 167 if (!process_steno_user(keycode, record)) {
182 return false; 168 return false;
183 } 169 }
184 switch(mode) { 170 switch (mode) {
185 case STENO_MODE_BOLT: 171 case STENO_MODE_BOLT:
186 update_state_bolt(keycode - QK_STENO, IS_PRESSED(record->event)); 172 update_state_bolt(keycode - QK_STENO, IS_PRESSED(record->event));
187 break; 173 break;
188 case STENO_MODE_GEMINI: 174 case STENO_MODE_GEMINI:
189 update_state_gemini(keycode - QK_STENO, IS_PRESSED(record->event)); 175 update_state_gemini(keycode - QK_STENO, IS_PRESSED(record->event));
190 break; 176 break;
191 } 177 }
192 // allow postprocessing hooks 178 // allow postprocessing hooks
193 if (postprocess_steno_user(keycode, record, mode, chord, pressed)) { 179 if (postprocess_steno_user(keycode, record, mode, chord, pressed)) {
194 if (IS_PRESSED(record->event)) { 180 if (IS_PRESSED(record->event)) {
195 ++pressed; 181 ++pressed;
196 } else { 182 } else {
197 --pressed; 183 --pressed;
198 if (pressed <= 0) { 184 if (pressed <= 0) {
199 pressed = 0; 185 pressed = 0;
200 send_steno_chord(); 186 send_steno_chord();
201 } 187 }
202 } 188 }
203 } 189 }
204 return false; 190 return false;
205 } 191 }
206 return true; 192 return true;
207} 193}
diff --git a/quantum/process_keycode/process_steno.h b/quantum/process_keycode/process_steno.h
index 71f973122..367542372 100644
--- a/quantum/process_keycode/process_steno.h
+++ b/quantum/process_keycode/process_steno.h
@@ -19,14 +19,14 @@
19#include "quantum.h" 19#include "quantum.h"
20 20
21#if defined(STENO_ENABLE) && !defined(VIRTSER_ENABLE) 21#if defined(STENO_ENABLE) && !defined(VIRTSER_ENABLE)
22 #error "must have virtser enabled to use steno" 22# error "must have virtser enabled to use steno"
23#endif 23#endif
24 24
25typedef enum { STENO_MODE_BOLT, STENO_MODE_GEMINI } steno_mode_t; 25typedef enum { STENO_MODE_BOLT, STENO_MODE_GEMINI } steno_mode_t;
26 26
27bool process_steno(uint16_t keycode, keyrecord_t *record); 27bool process_steno(uint16_t keycode, keyrecord_t *record);
28void steno_init(void); 28void steno_init(void);
29void steno_set_mode(steno_mode_t mode); 29void steno_set_mode(steno_mode_t mode);
30uint8_t *steno_get_state(void); 30uint8_t *steno_get_state(void);
31uint8_t *steno_get_chord(void); 31uint8_t *steno_get_chord(void);
32 32
diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c
index 16d33ddde..c27fe4834 100644
--- a/quantum/process_keycode/process_tap_dance.c
+++ b/quantum/process_keycode/process_tap_dance.c
@@ -17,7 +17,7 @@
17#include "action_tapping.h" 17#include "action_tapping.h"
18 18
19#ifndef TAPPING_TERM 19#ifndef TAPPING_TERM
20#define TAPPING_TERM 200 20# define TAPPING_TERM 200
21#endif 21#endif
22 22
23#ifndef NO_ACTION_ONESHOT 23#ifndef NO_ACTION_ONESHOT
@@ -25,191 +25,173 @@ uint8_t get_oneshot_mods(void);
25#endif 25#endif
26 26
27static uint16_t last_td; 27static uint16_t last_td;
28static int8_t highest_td = -1; 28static int8_t highest_td = -1;
29 29
30void qk_tap_dance_pair_on_each_tap (qk_tap_dance_state_t *state, void *user_data) { 30void qk_tap_dance_pair_on_each_tap(qk_tap_dance_state_t *state, void *user_data) {
31 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data; 31 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
32 32
33 if (state->count == 2) { 33 if (state->count == 2) {
34 register_code16 (pair->kc2); 34 register_code16(pair->kc2);
35 state->finished = true; 35 state->finished = true;
36 } 36 }
37} 37}
38 38
39void qk_tap_dance_pair_finished (qk_tap_dance_state_t *state, void *user_data) { 39void qk_tap_dance_pair_finished(qk_tap_dance_state_t *state, void *user_data) {
40 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data; 40 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
41 41
42 if (state->count == 1) { 42 if (state->count == 1) {
43 register_code16 (pair->kc1); 43 register_code16(pair->kc1);
44 } else if (state->count == 2) { 44 } else if (state->count == 2) {
45 register_code16 (pair->kc2); 45 register_code16(pair->kc2);
46 } 46 }
47} 47}
48 48
49void qk_tap_dance_pair_reset (qk_tap_dance_state_t *state, void *user_data) { 49void qk_tap_dance_pair_reset(qk_tap_dance_state_t *state, void *user_data) {
50 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data; 50 qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data;
51 51
52 if (state->count == 1) { 52 if (state->count == 1) {
53 unregister_code16 (pair->kc1); 53 unregister_code16(pair->kc1);
54 } else if (state->count == 2) { 54 } else if (state->count == 2) {
55 unregister_code16 (pair->kc2); 55 unregister_code16(pair->kc2);
56 } 56 }
57} 57}
58 58
59void qk_tap_dance_dual_role_on_each_tap (qk_tap_dance_state_t *state, void *user_data) { 59void qk_tap_dance_dual_role_on_each_tap(qk_tap_dance_state_t *state, void *user_data) {
60 qk_tap_dance_dual_role_t *pair = (qk_tap_dance_dual_role_t *)user_data; 60 qk_tap_dance_dual_role_t *pair = (qk_tap_dance_dual_role_t *)user_data;
61 61
62 if (state->count == 2) { 62 if (state->count == 2) {
63 layer_move (pair->layer); 63 layer_move(pair->layer);
64 state->finished = true; 64 state->finished = true;
65 } 65 }
66} 66}
67 67
68void qk_tap_dance_dual_role_finished (qk_tap_dance_state_t *state, void *user_data) { 68void qk_tap_dance_dual_role_finished(qk_tap_dance_state_t *state, void *user_data) {
69 qk_tap_dance_dual_role_t *pair = (qk_tap_dance_dual_role_t *)user_data; 69 qk_tap_dance_dual_role_t *pair = (qk_tap_dance_dual_role_t *)user_data;
70 70
71 if (state->count == 1) { 71 if (state->count == 1) {
72 register_code16 (pair->kc); 72 register_code16(pair->kc);
73 } else if (state->count == 2) { 73 } else if (state->count == 2) {
74 layer_move (pair->layer); 74 layer_move(pair->layer);
75 } 75 }
76} 76}
77 77
78void qk_tap_dance_dual_role_reset (qk_tap_dance_state_t *state, void *user_data) { 78void qk_tap_dance_dual_role_reset(qk_tap_dance_state_t *state, void *user_data) {
79 qk_tap_dance_dual_role_t *pair = (qk_tap_dance_dual_role_t *)user_data; 79 qk_tap_dance_dual_role_t *pair = (qk_tap_dance_dual_role_t *)user_data;
80 80
81 if (state->count == 1) { 81 if (state->count == 1) {
82 unregister_code16 (pair->kc); 82 unregister_code16(pair->kc);
83 } 83 }
84} 84}
85 85
86static inline void _process_tap_dance_action_fn (qk_tap_dance_state_t *state, 86static inline void _process_tap_dance_action_fn(qk_tap_dance_state_t *state, void *user_data, qk_tap_dance_user_fn_t fn) {
87 void *user_data, 87 if (fn) {
88 qk_tap_dance_user_fn_t fn) 88 fn(state, user_data);
89{ 89 }
90 if (fn) {
91 fn(state, user_data);
92 }
93} 90}
94 91
95static inline void process_tap_dance_action_on_each_tap (qk_tap_dance_action_t *action) 92static inline void process_tap_dance_action_on_each_tap(qk_tap_dance_action_t *action) { _process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_each_tap); }
96{
97 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_each_tap);
98}
99 93
100static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_action_t *action) 94static inline void process_tap_dance_action_on_dance_finished(qk_tap_dance_action_t *action) {
101{ 95 if (action->state.finished) return;
102 if (action->state.finished) 96 action->state.finished = true;
103 return; 97 add_mods(action->state.oneshot_mods);
104 action->state.finished = true; 98 add_weak_mods(action->state.weak_mods);
105 add_mods(action->state.oneshot_mods); 99 send_keyboard_report();
106 add_weak_mods(action->state.weak_mods); 100 _process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_dance_finished);
107 send_keyboard_report();
108 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_dance_finished);
109} 101}
110 102
111static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t *action) 103static inline void process_tap_dance_action_on_reset(qk_tap_dance_action_t *action) {
112{ 104 _process_tap_dance_action_fn(&action->state, action->user_data, action->fn.on_reset);
113 _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_reset); 105 del_mods(action->state.oneshot_mods);
114 del_mods(action->state.oneshot_mods); 106 del_weak_mods(action->state.weak_mods);
115 del_weak_mods(action->state.weak_mods); 107 send_keyboard_report();
116 send_keyboard_report();
117} 108}
118 109
119void preprocess_tap_dance(uint16_t keycode, keyrecord_t *record) { 110void preprocess_tap_dance(uint16_t keycode, keyrecord_t *record) {
120 qk_tap_dance_action_t *action; 111 qk_tap_dance_action_t *action;
121 112
122 if (!record->event.pressed) 113 if (!record->event.pressed) return;
123 return; 114
124 115 if (highest_td == -1) return;
125 if (highest_td == -1) 116
126 return; 117 for (int i = 0; i <= highest_td; i++) {
127 118 action = &tap_dance_actions[i];
128 for (int i = 0; i <= highest_td; i++) { 119 if (action->state.count) {
129 action = &tap_dance_actions[i]; 120 if (keycode == action->state.keycode && keycode == last_td) continue;
130 if (action->state.count) { 121 action->state.interrupted = true;
131 if (keycode == action->state.keycode && keycode == last_td) 122 action->state.interrupting_keycode = keycode;
132 continue; 123 process_tap_dance_action_on_dance_finished(action);
133 action->state.interrupted = true; 124 reset_tap_dance(&action->state);
134 action->state.interrupting_keycode = keycode; 125 }
135 process_tap_dance_action_on_dance_finished (action);
136 reset_tap_dance (&action->state);
137 } 126 }
138 }
139} 127}
140 128
141bool process_tap_dance(uint16_t keycode, keyrecord_t *record) { 129bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
142 uint16_t idx = keycode - QK_TAP_DANCE; 130 uint16_t idx = keycode - QK_TAP_DANCE;
143 qk_tap_dance_action_t *action; 131 qk_tap_dance_action_t *action;
144 132
145 switch(keycode) { 133 switch (keycode) {
146 case QK_TAP_DANCE ... QK_TAP_DANCE_MAX: 134 case QK_TAP_DANCE ... QK_TAP_DANCE_MAX:
147 if ((int16_t)idx > highest_td) 135 if ((int16_t)idx > highest_td) highest_td = idx;
148 highest_td = idx; 136 action = &tap_dance_actions[idx];
149 action = &tap_dance_actions[idx]; 137
150 138 action->state.pressed = record->event.pressed;
151 action->state.pressed = record->event.pressed; 139 if (record->event.pressed) {
152 if (record->event.pressed) { 140 action->state.keycode = keycode;
153 action->state.keycode = keycode; 141 action->state.count++;
154 action->state.count++; 142 action->state.timer = timer_read();
155 action->state.timer = timer_read();
156#ifndef NO_ACTION_ONESHOT 143#ifndef NO_ACTION_ONESHOT
157 action->state.oneshot_mods = get_oneshot_mods(); 144 action->state.oneshot_mods = get_oneshot_mods();
158#else 145#else
159 action->state.oneshot_mods = 0; 146 action->state.oneshot_mods = 0;
160#endif 147#endif
161 action->state.weak_mods = get_mods(); 148 action->state.weak_mods = get_mods();
162 action->state.weak_mods |= get_weak_mods(); 149 action->state.weak_mods |= get_weak_mods();
163 process_tap_dance_action_on_each_tap (action); 150 process_tap_dance_action_on_each_tap(action);
164 151
165 last_td = keycode; 152 last_td = keycode;
166 } else { 153 } else {
167 if (action->state.count && action->state.finished) { 154 if (action->state.count && action->state.finished) {
168 reset_tap_dance (&action->state); 155 reset_tap_dance(&action->state);
169 } 156 }
157 }
158
159 break;
170 } 160 }
171 161
172 break; 162 return true;
173 }
174
175 return true;
176} 163}
177 164
178 165void matrix_scan_tap_dance() {
179 166 if (highest_td == -1) return;
180void matrix_scan_tap_dance () { 167 uint16_t tap_user_defined;
181 if (highest_td == -1) 168
182 return; 169 for (uint8_t i = 0; i <= highest_td; i++) {
183 uint16_t tap_user_defined; 170 qk_tap_dance_action_t *action = &tap_dance_actions[i];
184 171 if (action->custom_tapping_term > 0) {
185 for (uint8_t i = 0; i <= highest_td; i++) { 172 tap_user_defined = action->custom_tapping_term;
186 qk_tap_dance_action_t *action = &tap_dance_actions[i]; 173 } else {
187 if(action->custom_tapping_term > 0 ) { 174 tap_user_defined = TAPPING_TERM;
188 tap_user_defined = action->custom_tapping_term; 175 }
189 } 176 if (action->state.count && timer_elapsed(action->state.timer) > tap_user_defined) {
190 else{ 177 process_tap_dance_action_on_dance_finished(action);
191 tap_user_defined = TAPPING_TERM; 178 reset_tap_dance(&action->state);
192 } 179 }
193 if (action->state.count && timer_elapsed (action->state.timer) > tap_user_defined) {
194 process_tap_dance_action_on_dance_finished (action);
195 reset_tap_dance (&action->state);
196 } 180 }
197 }
198} 181}
199 182
200void reset_tap_dance (qk_tap_dance_state_t *state) { 183void reset_tap_dance(qk_tap_dance_state_t *state) {
201 qk_tap_dance_action_t *action; 184 qk_tap_dance_action_t *action;
202 185
203 if (state->pressed) 186 if (state->pressed) return;
204 return;
205 187
206 action = &tap_dance_actions[state->keycode - QK_TAP_DANCE]; 188 action = &tap_dance_actions[state->keycode - QK_TAP_DANCE];
207 189
208 process_tap_dance_action_on_reset (action); 190 process_tap_dance_action_on_reset(action);
209 191
210 state->count = 0; 192 state->count = 0;
211 state->interrupted = false; 193 state->interrupted = false;
212 state->finished = false; 194 state->finished = false;
213 state->interrupting_keycode = 0; 195 state->interrupting_keycode = 0;
214 last_td = 0; 196 last_td = 0;
215} 197}
diff --git a/quantum/process_keycode/process_tap_dance.h b/quantum/process_keycode/process_tap_dance.h
index 00d70cbc5..b2d0cb829 100644
--- a/quantum/process_keycode/process_tap_dance.h
+++ b/quantum/process_keycode/process_tap_dance.h
@@ -18,75 +18,60 @@
18 18
19#ifdef TAP_DANCE_ENABLE 19#ifdef TAP_DANCE_ENABLE
20 20
21#include <stdbool.h> 21# include <stdbool.h>
22#include <inttypes.h> 22# include <inttypes.h>
23 23
24typedef struct 24typedef struct {
25{ 25 uint8_t count;
26 uint8_t count; 26 uint8_t oneshot_mods;
27 uint8_t oneshot_mods; 27 uint8_t weak_mods;
28 uint8_t weak_mods; 28 uint16_t keycode;
29 uint16_t keycode; 29 uint16_t interrupting_keycode;
30 uint16_t interrupting_keycode; 30 uint16_t timer;
31 uint16_t timer; 31 bool interrupted;
32 bool interrupted; 32 bool pressed;
33 bool pressed; 33 bool finished;
34 bool finished;
35} qk_tap_dance_state_t; 34} qk_tap_dance_state_t;
36 35
37#define TD(n) (QK_TAP_DANCE | ((n) & 0xFF)) 36# define TD(n) (QK_TAP_DANCE | ((n)&0xFF))
38 37
39typedef void (*qk_tap_dance_user_fn_t) (qk_tap_dance_state_t *state, void *user_data); 38typedef void (*qk_tap_dance_user_fn_t)(qk_tap_dance_state_t *state, void *user_data);
40 39
41typedef struct 40typedef struct {
42{ 41 struct {
43 struct { 42 qk_tap_dance_user_fn_t on_each_tap;
44 qk_tap_dance_user_fn_t on_each_tap; 43 qk_tap_dance_user_fn_t on_dance_finished;
45 qk_tap_dance_user_fn_t on_dance_finished; 44 qk_tap_dance_user_fn_t on_reset;
46 qk_tap_dance_user_fn_t on_reset; 45 } fn;
47 } fn; 46 qk_tap_dance_state_t state;
48 qk_tap_dance_state_t state; 47 uint16_t custom_tapping_term;
49 uint16_t custom_tapping_term; 48 void * user_data;
50 void *user_data;
51} qk_tap_dance_action_t; 49} qk_tap_dance_action_t;
52 50
53typedef struct 51typedef struct {
54{ 52 uint16_t kc1;
55 uint16_t kc1; 53 uint16_t kc2;
56 uint16_t kc2;
57} qk_tap_dance_pair_t; 54} qk_tap_dance_pair_t;
58 55
59typedef struct 56typedef struct {
60{ 57 uint16_t kc;
61 uint16_t kc; 58 uint8_t layer;
62 uint8_t layer;
63} qk_tap_dance_dual_role_t; 59} qk_tap_dance_dual_role_t;
64 60
65#define ACTION_TAP_DANCE_DOUBLE(kc1, kc2) { \ 61# define ACTION_TAP_DANCE_DOUBLE(kc1, kc2) \
66 .fn = { qk_tap_dance_pair_on_each_tap, qk_tap_dance_pair_finished, qk_tap_dance_pair_reset }, \ 62 { .fn = {qk_tap_dance_pair_on_each_tap, qk_tap_dance_pair_finished, qk_tap_dance_pair_reset}, .user_data = (void *)&((qk_tap_dance_pair_t){kc1, kc2}), }
67 .user_data = (void *)&((qk_tap_dance_pair_t) { kc1, kc2 }), \
68 }
69 63
70#define ACTION_TAP_DANCE_DUAL_ROLE(kc, layer) { \ 64# define ACTION_TAP_DANCE_DUAL_ROLE(kc, layer) \
71 .fn = { qk_tap_dance_dual_role_on_each_tap, qk_tap_dance_dual_role_finished, qk_tap_dance_dual_role_reset }, \ 65 { .fn = {qk_tap_dance_dual_role_on_each_tap, qk_tap_dance_dual_role_finished, qk_tap_dance_dual_role_reset}, .user_data = (void *)&((qk_tap_dance_dual_role_t){kc, layer}), }
72 .user_data = (void *)&((qk_tap_dance_dual_role_t) { kc, layer }), \
73 }
74 66
75#define ACTION_TAP_DANCE_FN(user_fn) { \ 67# define ACTION_TAP_DANCE_FN(user_fn) \
76 .fn = { NULL, user_fn, NULL }, \ 68 { .fn = {NULL, user_fn, NULL}, .user_data = NULL, }
77 .user_data = NULL, \
78 }
79 69
80#define ACTION_TAP_DANCE_FN_ADVANCED(user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset) { \ 70# define ACTION_TAP_DANCE_FN_ADVANCED(user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset) \
81 .fn = { user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset }, \ 71 { .fn = {user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset}, .user_data = NULL, }
82 .user_data = NULL, \
83 }
84 72
85#define ACTION_TAP_DANCE_FN_ADVANCED_TIME(user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset, tap_specific_tapping_term) { \ 73# define ACTION_TAP_DANCE_FN_ADVANCED_TIME(user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset, tap_specific_tapping_term) \
86 .fn = { user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset }, \ 74 { .fn = {user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_dance_reset}, .user_data = NULL, .custom_tapping_term = tap_specific_tapping_term, }
87 .user_data = NULL, \
88 .custom_tapping_term = tap_specific_tapping_term, \
89 }
90 75
91extern qk_tap_dance_action_t tap_dance_actions[]; 76extern qk_tap_dance_action_t tap_dance_actions[];
92 77
@@ -94,20 +79,20 @@ extern qk_tap_dance_action_t tap_dance_actions[];
94 79
95void preprocess_tap_dance(uint16_t keycode, keyrecord_t *record); 80void preprocess_tap_dance(uint16_t keycode, keyrecord_t *record);
96bool process_tap_dance(uint16_t keycode, keyrecord_t *record); 81bool process_tap_dance(uint16_t keycode, keyrecord_t *record);
97void matrix_scan_tap_dance (void); 82void matrix_scan_tap_dance(void);
98void reset_tap_dance (qk_tap_dance_state_t *state); 83void reset_tap_dance(qk_tap_dance_state_t *state);
99 84
100void qk_tap_dance_pair_on_each_tap (qk_tap_dance_state_t *state, void *user_data); 85void qk_tap_dance_pair_on_each_tap(qk_tap_dance_state_t *state, void *user_data);
101void qk_tap_dance_pair_finished (qk_tap_dance_state_t *state, void *user_data); 86void qk_tap_dance_pair_finished(qk_tap_dance_state_t *state, void *user_data);
102void qk_tap_dance_pair_reset (qk_tap_dance_state_t *state, void *user_data); 87void qk_tap_dance_pair_reset(qk_tap_dance_state_t *state, void *user_data);
103 88
104void qk_tap_dance_dual_role_on_each_tap (qk_tap_dance_state_t *state, void *user_data); 89void qk_tap_dance_dual_role_on_each_tap(qk_tap_dance_state_t *state, void *user_data);
105void qk_tap_dance_dual_role_finished (qk_tap_dance_state_t *state, void *user_data); 90void qk_tap_dance_dual_role_finished(qk_tap_dance_state_t *state, void *user_data);
106void qk_tap_dance_dual_role_reset (qk_tap_dance_state_t *state, void *user_data); 91void qk_tap_dance_dual_role_reset(qk_tap_dance_state_t *state, void *user_data);
107 92
108#else 93#else
109 94
110#define TD(n) KC_NO 95# define TD(n) KC_NO
111 96
112#endif 97#endif
113 98
diff --git a/quantum/process_keycode/process_terminal.c b/quantum/process_keycode/process_terminal.c
index e791deffc..f48f3d702 100644
--- a/quantum/process_keycode/process_terminal.c
+++ b/quantum/process_keycode/process_terminal.c
@@ -21,62 +21,45 @@
21#include <math.h> 21#include <math.h>
22 22
23#ifndef CMD_BUFF_SIZE 23#ifndef CMD_BUFF_SIZE
24 #define CMD_BUFF_SIZE 5 24# define CMD_BUFF_SIZE 5
25#endif 25#endif
26 26
27
28bool terminal_enabled = false; 27bool terminal_enabled = false;
29char buffer[80] = ""; 28char buffer[80] = "";
30char cmd_buffer[CMD_BUFF_SIZE][80]; 29char cmd_buffer[CMD_BUFF_SIZE][80];
31bool cmd_buffer_enabled = true; //replace with ifdef? 30bool cmd_buffer_enabled = true; // replace with ifdef?
32char newline[2] = "\n"; 31char newline[2] = "\n";
33char arguments[6][20]; 32char arguments[6][20];
34bool firstTime = true; 33bool firstTime = true;
35 34
36short int current_cmd_buffer_pos = 0; //used for up/down arrows - keeps track of where you are in the command buffer 35short int current_cmd_buffer_pos = 0; // used for up/down arrows - keeps track of where you are in the command buffer
37 36
38__attribute__ ((weak)) 37__attribute__((weak)) const char terminal_prompt[8] = "> ";
39const char terminal_prompt[8] = "> ";
40 38
41#ifdef AUDIO_ENABLE 39#ifdef AUDIO_ENABLE
42 #ifndef TERMINAL_SONG 40# ifndef TERMINAL_SONG
43 #define TERMINAL_SONG SONG(TERMINAL_SOUND) 41# define TERMINAL_SONG SONG(TERMINAL_SOUND)
44 #endif 42# endif
45 float terminal_song[][2] = TERMINAL_SONG; 43float terminal_song[][2] = TERMINAL_SONG;
46 #define TERMINAL_BELL() PLAY_SONG(terminal_song) 44# define TERMINAL_BELL() PLAY_SONG(terminal_song)
47#else 45#else
48 #define TERMINAL_BELL() 46# define TERMINAL_BELL()
49#endif 47#endif
50 48
51__attribute__ ((weak)) 49__attribute__((weak)) const char keycode_to_ascii_lut[58] = {0, 0, 0, 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0, 0, 0, '\t', ' ', '-', '=', '[', ']', '\\', 0, ';', '\'', '`', ',', '.', '/'};
52const char keycode_to_ascii_lut[58] = { 50
53 0, 0, 0, 0, 51__attribute__((weak)) const char shifted_keycode_to_ascii_lut[58] = {0, 0, 0, 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', 0, 0, 0, '\t', ' ', '_', '+', '{', '}', '|', 0, ':', '\'', '~', '<', '>', '?'};
54 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
55 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
56 '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0, 0, 0, '\t',
57 ' ', '-', '=', '[', ']', '\\', 0, ';', '\'', '`', ',', '.', '/'
58};
59
60__attribute__ ((weak))
61const char shifted_keycode_to_ascii_lut[58] = {
62 0, 0, 0, 0,
63 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
64 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
65 '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', 0, 0, 0, '\t',
66 ' ', '_', '+', '{', '}', '|', 0, ':', '\'', '~', '<', '>', '?'
67};
68 52
69struct stringcase { 53struct stringcase {
70 char* string; 54 char *string;
71 void (*func)(void); 55 void (*func)(void);
72} typedef stringcase; 56} typedef stringcase;
73 57
74void enable_terminal(void) { 58void enable_terminal(void) {
75 terminal_enabled = true; 59 terminal_enabled = true;
76 strcpy(buffer, ""); 60 strcpy(buffer, "");
77 memset(cmd_buffer,0,CMD_BUFF_SIZE * 80); 61 memset(cmd_buffer, 0, CMD_BUFF_SIZE * 80);
78 for (int i = 0; i < 6; i++) 62 for (int i = 0; i < 6; i++) strcpy(arguments[i], "");
79 strcpy(arguments[i], "");
80 // select all text to start over 63 // select all text to start over
81 // SEND_STRING(SS_LCTRL("a")); 64 // SEND_STRING(SS_LCTRL("a"));
82 send_string(terminal_prompt); 65 send_string(terminal_prompt);
@@ -88,41 +71,41 @@ void disable_terminal(void) {
88} 71}
89 72
90void push_to_cmd_buffer(void) { 73void push_to_cmd_buffer(void) {
91if (cmd_buffer_enabled) { 74 if (cmd_buffer_enabled) {
92 if (cmd_buffer == NULL) { 75 if (cmd_buffer == NULL) {
93 return; 76 return;
94 } else { 77 } else {
95 if (firstTime) { 78 if (firstTime) {
96 firstTime = false; 79 firstTime = false;
97 strcpy(cmd_buffer[0],buffer); 80 strcpy(cmd_buffer[0], buffer);
98 return; 81 return;
99 } 82 }
100 83
101 for (int i= CMD_BUFF_SIZE - 1;i > 0 ;--i) { 84 for (int i = CMD_BUFF_SIZE - 1; i > 0; --i) {
102 strncpy(cmd_buffer[i],cmd_buffer[i-1],80); 85 strncpy(cmd_buffer[i], cmd_buffer[i - 1], 80);
103 } 86 }
104 87
105 strcpy(cmd_buffer[0],buffer); 88 strcpy(cmd_buffer[0], buffer);
106 89
107 return; 90 return;
91 }
108 } 92 }
109 }
110} 93}
111 94
112void terminal_about(void) { 95void terminal_about(void) {
113 SEND_STRING("QMK Firmware\n"); 96 SEND_STRING("QMK Firmware\n");
114 SEND_STRING(" v"); 97 SEND_STRING(" v");
115 SEND_STRING(QMK_VERSION); 98 SEND_STRING(QMK_VERSION);
116 SEND_STRING("\n"SS_TAP(X_HOME)" Built: "); 99 SEND_STRING("\n" SS_TAP(X_HOME) " Built: ");
117 SEND_STRING(QMK_BUILDDATE); 100 SEND_STRING(QMK_BUILDDATE);
118 send_string(newline); 101 send_string(newline);
119 #ifdef TERMINAL_HELP 102#ifdef TERMINAL_HELP
120 if (strlen(arguments[1]) != 0) { 103 if (strlen(arguments[1]) != 0) {
121 SEND_STRING("You entered: "); 104 SEND_STRING("You entered: ");
122 send_string(arguments[1]); 105 send_string(arguments[1]);
123 send_string(newline); 106 send_string(newline);
124 } 107 }
125 #endif 108#endif
126} 109}
127 110
128void terminal_help(void); 111void terminal_help(void);
@@ -131,11 +114,11 @@ extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
131 114
132void terminal_keycode(void) { 115void terminal_keycode(void) {
133 if (strlen(arguments[1]) != 0 && strlen(arguments[2]) != 0 && strlen(arguments[3]) != 0) { 116 if (strlen(arguments[1]) != 0 && strlen(arguments[2]) != 0 && strlen(arguments[3]) != 0) {
134 char keycode_dec[5]; 117 char keycode_dec[5];
135 char keycode_hex[5]; 118 char keycode_hex[5];
136 uint16_t layer = strtol(arguments[1], (char **)NULL, 10); 119 uint16_t layer = strtol(arguments[1], (char **)NULL, 10);
137 uint16_t row = strtol(arguments[2], (char **)NULL, 10); 120 uint16_t row = strtol(arguments[2], (char **)NULL, 10);
138 uint16_t col = strtol(arguments[3], (char **)NULL, 10); 121 uint16_t col = strtol(arguments[3], (char **)NULL, 10);
139 uint16_t keycode = pgm_read_word(&keymaps[layer][row][col]); 122 uint16_t keycode = pgm_read_word(&keymaps[layer][row][col]);
140 itoa(keycode, keycode_dec, 10); 123 itoa(keycode, keycode_dec, 10);
141 itoa(keycode, keycode_hex, 16); 124 itoa(keycode, keycode_hex, 16);
@@ -145,9 +128,9 @@ void terminal_keycode(void) {
145 send_string(keycode_dec); 128 send_string(keycode_dec);
146 SEND_STRING(")\n"); 129 SEND_STRING(")\n");
147 } else { 130 } else {
148 #ifdef TERMINAL_HELP 131#ifdef TERMINAL_HELP
149 SEND_STRING("usage: keycode <layer> <row> <col>\n"); 132 SEND_STRING("usage: keycode <layer> <row> <col>\n");
150 #endif 133#endif
151 } 134 }
152} 135}
153 136
@@ -157,53 +140,44 @@ void terminal_keymap(void) {
157 for (int r = 0; r < MATRIX_ROWS; r++) { 140 for (int r = 0; r < MATRIX_ROWS; r++) {
158 for (int c = 0; c < MATRIX_COLS; c++) { 141 for (int c = 0; c < MATRIX_COLS; c++) {
159 uint16_t keycode = pgm_read_word(&keymaps[layer][r][c]); 142 uint16_t keycode = pgm_read_word(&keymaps[layer][r][c]);
160 char keycode_s[8]; 143 char keycode_s[8];
161 sprintf(keycode_s, "0x%04x,", keycode); 144 sprintf(keycode_s, "0x%04x,", keycode);
162 send_string(keycode_s); 145 send_string(keycode_s);
163 } 146 }
164 send_string(newline); 147 send_string(newline);
165 } 148 }
166 } else { 149 } else {
167 #ifdef TERMINAL_HELP 150#ifdef TERMINAL_HELP
168 SEND_STRING("usage: keymap <layer>\n"); 151 SEND_STRING("usage: keymap <layer>\n");
169 #endif 152#endif
170 } 153 }
171} 154}
172 155
173void print_cmd_buff(void) { 156void print_cmd_buff(void) {
174 /* without the below wait, a race condition can occur wherein the 157 /* without the below wait, a race condition can occur wherein the
175 buffer can be printed before it has been fully moved */ 158 buffer can be printed before it has been fully moved */
176 wait_ms(250); 159 wait_ms(250);
177 for(int i=0;i<CMD_BUFF_SIZE;i++){ 160 for (int i = 0; i < CMD_BUFF_SIZE; i++) {
178 char tmpChar = ' '; 161 char tmpChar = ' ';
179 itoa(i ,&tmpChar,10); 162 itoa(i, &tmpChar, 10);
180 const char * tmpCnstCharStr = &tmpChar; //because sned_string wont take a normal char * 163 const char *tmpCnstCharStr = &tmpChar; // because sned_string wont take a normal char *
181 send_string(tmpCnstCharStr); 164 send_string(tmpCnstCharStr);
182 SEND_STRING(". "); 165 SEND_STRING(". ");
183 send_string(cmd_buffer[i]); 166 send_string(cmd_buffer[i]);
184 SEND_STRING("\n"); 167 SEND_STRING("\n");
185 } 168 }
186} 169}
187 170
188
189void flush_cmd_buffer(void) { 171void flush_cmd_buffer(void) {
190 memset(cmd_buffer,0,CMD_BUFF_SIZE * 80); 172 memset(cmd_buffer, 0, CMD_BUFF_SIZE * 80);
191 SEND_STRING("Buffer Cleared!\n"); 173 SEND_STRING("Buffer Cleared!\n");
192} 174}
193 175
194stringcase terminal_cases[] = { 176stringcase terminal_cases[] = {{"about", terminal_about}, {"help", terminal_help}, {"keycode", terminal_keycode}, {"keymap", terminal_keymap}, {"flush-buffer", flush_cmd_buffer}, {"print-buffer", print_cmd_buff}, {"exit", disable_terminal}};
195 { "about", terminal_about },
196 { "help", terminal_help },
197 { "keycode", terminal_keycode },
198 { "keymap", terminal_keymap },
199 { "flush-buffer" , flush_cmd_buffer},
200 { "print-buffer" , print_cmd_buff},
201 { "exit", disable_terminal }
202};
203 177
204void terminal_help(void) { 178void terminal_help(void) {
205 SEND_STRING("commands available:\n "); 179 SEND_STRING("commands available:\n ");
206 for( stringcase* case_p = terminal_cases; case_p != terminal_cases + sizeof( terminal_cases ) / sizeof( terminal_cases[0] ); case_p++ ) { 180 for (stringcase *case_p = terminal_cases; case_p != terminal_cases + sizeof(terminal_cases) / sizeof(terminal_cases[0]); case_p++) {
207 send_string(case_p->string); 181 send_string(case_p->string);
208 SEND_STRING(" "); 182 SEND_STRING(" ");
209 } 183 }
@@ -211,7 +185,7 @@ void terminal_help(void) {
211} 185}
212 186
213void command_not_found(void) { 187void command_not_found(void) {
214 wait_ms(50); //sometimes buffer isnt grabbed quick enough 188 wait_ms(50); // sometimes buffer isnt grabbed quick enough
215 SEND_STRING("command \""); 189 SEND_STRING("command \"");
216 send_string(buffer); 190 send_string(buffer);
217 SEND_STRING("\" not found\n"); 191 SEND_STRING("\" not found\n");
@@ -221,9 +195,9 @@ void process_terminal_command(void) {
221 // we capture return bc of the order of events, so we need to manually send a newline 195 // we capture return bc of the order of events, so we need to manually send a newline
222 send_string(newline); 196 send_string(newline);
223 197
224 char * pch; 198 char * pch;
225 uint8_t i = 0; 199 uint8_t i = 0;
226 pch = strtok(buffer, " "); 200 pch = strtok(buffer, " ");
227 while (pch != NULL) { 201 while (pch != NULL) {
228 strcpy(arguments[i], pch); 202 strcpy(arguments[i], pch);
229 pch = strtok(NULL, " "); 203 pch = strtok(NULL, " ");
@@ -231,38 +205,32 @@ void process_terminal_command(void) {
231 } 205 }
232 206
233 bool command_found = false; 207 bool command_found = false;
234 for( stringcase* case_p = terminal_cases; case_p != terminal_cases + sizeof( terminal_cases ) / sizeof( terminal_cases[0] ); case_p++ ) { 208 for (stringcase *case_p = terminal_cases; case_p != terminal_cases + sizeof(terminal_cases) / sizeof(terminal_cases[0]); case_p++) {
235 if( 0 == strcmp( case_p->string, buffer ) ) { 209 if (0 == strcmp(case_p->string, buffer)) {
236 command_found = true; 210 command_found = true;
237 (*case_p->func)(); 211 (*case_p->func)();
238 break; 212 break;
239 } 213 }
240 } 214 }
241 215
242 if (!command_found) 216 if (!command_found) command_not_found();
243 command_not_found();
244 217
245 if (terminal_enabled) { 218 if (terminal_enabled) {
246 strcpy(buffer, ""); 219 strcpy(buffer, "");
247 for (int i = 0; i < 6; i++) 220 for (int i = 0; i < 6; i++) strcpy(arguments[i], "");
248 strcpy(arguments[i], "");
249 SEND_STRING(SS_TAP(X_HOME)); 221 SEND_STRING(SS_TAP(X_HOME));
250 send_string(terminal_prompt); 222 send_string(terminal_prompt);
251 } 223 }
252} 224}
253void check_pos(void) { 225void check_pos(void) {
254 if (current_cmd_buffer_pos >= CMD_BUFF_SIZE) { //if over the top, move it back down to the top of the buffer so you can climb back down... 226 if (current_cmd_buffer_pos >= CMD_BUFF_SIZE) { // if over the top, move it back down to the top of the buffer so you can climb back down...
255 current_cmd_buffer_pos = CMD_BUFF_SIZE - 1; 227 current_cmd_buffer_pos = CMD_BUFF_SIZE - 1;
256 } else if (current_cmd_buffer_pos < 0) { //...and if you fall under the bottom of the buffer, reset back to 0 so you can climb back up 228 } else if (current_cmd_buffer_pos < 0) { //...and if you fall under the bottom of the buffer, reset back to 0 so you can climb back up
257 current_cmd_buffer_pos = 0; 229 current_cmd_buffer_pos = 0;
258 } 230 }
259} 231}
260 232
261
262
263
264bool process_terminal(uint16_t keycode, keyrecord_t *record) { 233bool process_terminal(uint16_t keycode, keyrecord_t *record) {
265
266 if (keycode == TERM_ON && record->event.pressed) { 234 if (keycode == TERM_ON && record->event.pressed) {
267 enable_terminal(); 235 enable_terminal();
268 return false; 236 return false;
@@ -280,59 +248,66 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) {
280 248
281 if (keycode < 256) { 249 if (keycode < 256) {
282 uint8_t str_len; 250 uint8_t str_len;
283 char char_to_add; 251 char char_to_add;
284 switch (keycode) { 252 switch (keycode) {
285 case KC_ENTER: 253 case KC_ENTER:
286 case KC_KP_ENTER: 254 case KC_KP_ENTER:
287 push_to_cmd_buffer(); 255 push_to_cmd_buffer();
288 current_cmd_buffer_pos = 0; 256 current_cmd_buffer_pos = 0;
289 process_terminal_command(); 257 process_terminal_command();
290 return false; break; 258 return false;
259 break;
291 case KC_ESC: 260 case KC_ESC:
292 SEND_STRING("\n"); 261 SEND_STRING("\n");
293 enable_terminal(); 262 enable_terminal();
294 return false; break; 263 return false;
264 break;
295 case KC_BSPC: 265 case KC_BSPC:
296 str_len = strlen(buffer); 266 str_len = strlen(buffer);
297 if (str_len > 0) { 267 if (str_len > 0) {
298 buffer[str_len-1] = 0; 268 buffer[str_len - 1] = 0;
299 return true; 269 return true;
300 } else { 270 } else {
301 TERMINAL_BELL(); 271 TERMINAL_BELL();
302 return false; 272 return false;
303 } break; 273 }
274 break;
304 case KC_LEFT: 275 case KC_LEFT:
305 return false; break; 276 return false;
277 break;
306 case KC_RIGHT: 278 case KC_RIGHT:
307 return false; break; 279 return false;
308 case KC_UP: // 0 = recent 280 break;
309 check_pos(); //check our current buffer position is valid 281 case KC_UP: // 0 = recent
310 if (current_cmd_buffer_pos <= CMD_BUFF_SIZE - 1) { //once we get to the top, dont do anything 282 check_pos(); // check our current buffer position is valid
311 str_len = strlen(buffer); 283 if (current_cmd_buffer_pos <= CMD_BUFF_SIZE - 1) { // once we get to the top, dont do anything
312 for(int i= 0;i < str_len ;++i) { 284 str_len = strlen(buffer);
313 send_string(SS_TAP(X_BSPACE)); //clear w/e is on the line already 285 for (int i = 0; i < str_len; ++i) {
314 //process_terminal(KC_BSPC,record); 286 send_string(SS_TAP(X_BSPACE)); // clear w/e is on the line already
315 } 287 // process_terminal(KC_BSPC,record);
316 strncpy(buffer,cmd_buffer[current_cmd_buffer_pos],80); 288 }
289 strncpy(buffer, cmd_buffer[current_cmd_buffer_pos], 80);
317 290
318 send_string(buffer); 291 send_string(buffer);
319 ++current_cmd_buffer_pos; //get ready to access the above cmd if up/down is pressed again 292 ++current_cmd_buffer_pos; // get ready to access the above cmd if up/down is pressed again
320 } 293 }
321 return false; break; 294 return false;
295 break;
322 case KC_DOWN: 296 case KC_DOWN:
323 check_pos(); 297 check_pos();
324 if (current_cmd_buffer_pos >= 0) { //once we get to the bottom, dont do anything 298 if (current_cmd_buffer_pos >= 0) { // once we get to the bottom, dont do anything
325 str_len = strlen(buffer); 299 str_len = strlen(buffer);
326 for(int i= 0;i < str_len ;++i) { 300 for (int i = 0; i < str_len; ++i) {
327 send_string(SS_TAP(X_BSPACE)); //clear w/e is on the line already 301 send_string(SS_TAP(X_BSPACE)); // clear w/e is on the line already
328 //process_terminal(KC_BSPC,record); 302 // process_terminal(KC_BSPC,record);
329 } 303 }
330 strncpy(buffer,cmd_buffer[current_cmd_buffer_pos],79); 304 strncpy(buffer, cmd_buffer[current_cmd_buffer_pos], 79);
331 305
332 send_string(buffer); 306 send_string(buffer);
333 --current_cmd_buffer_pos; //get ready to access the above cmd if down/up is pressed again 307 --current_cmd_buffer_pos; // get ready to access the above cmd if down/up is pressed again
334 } 308 }
335 return false; break; 309 return false;
310 break;
336 default: 311 default:
337 if (keycode <= 58) { 312 if (keycode <= 58) {
338 char_to_add = 0; 313 char_to_add = 0;
@@ -344,11 +319,9 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) {
344 if (char_to_add != 0) { 319 if (char_to_add != 0) {
345 strncat(buffer, &char_to_add, 1); 320 strncat(buffer, &char_to_add, 1);
346 } 321 }
347 } break; 322 }
323 break;
348 } 324 }
349
350
351
352 } 325 }
353 } 326 }
354 return true; 327 return true;
diff --git a/quantum/process_keycode/process_terminal.h b/quantum/process_keycode/process_terminal.h
index d945949a4..8426f442b 100644
--- a/quantum/process_keycode/process_terminal.h
+++ b/quantum/process_keycode/process_terminal.h
@@ -22,6 +22,6 @@
22extern const char keycode_to_ascii_lut[58]; 22extern const char keycode_to_ascii_lut[58];
23extern const char shifted_keycode_to_ascii_lut[58]; 23extern const char shifted_keycode_to_ascii_lut[58];
24extern const char terminal_prompt[8]; 24extern const char terminal_prompt[8];
25bool process_terminal(uint16_t keycode, keyrecord_t *record); 25bool process_terminal(uint16_t keycode, keyrecord_t *record);
26 26
27#endif \ No newline at end of file 27#endif \ No newline at end of file
diff --git a/quantum/process_keycode/process_ucis.c b/quantum/process_keycode/process_ucis.c
index fd4508b53..024077317 100644
--- a/quantum/process_keycode/process_ucis.c
+++ b/quantum/process_keycode/process_ucis.c
@@ -19,144 +19,133 @@
19qk_ucis_state_t qk_ucis_state; 19qk_ucis_state_t qk_ucis_state;
20 20
21void qk_ucis_start(void) { 21void qk_ucis_start(void) {
22 qk_ucis_state.count = 0; 22 qk_ucis_state.count = 0;
23 qk_ucis_state.in_progress = true; 23 qk_ucis_state.in_progress = true;
24 24
25 qk_ucis_start_user(); 25 qk_ucis_start_user();
26} 26}
27 27
28__attribute__((weak)) 28__attribute__((weak)) void qk_ucis_start_user(void) {
29void qk_ucis_start_user(void) { 29 unicode_input_start();
30 unicode_input_start(); 30 register_hex(0x2328);
31 register_hex(0x2328); 31 unicode_input_finish();
32 unicode_input_finish();
33} 32}
34 33
35__attribute__((weak)) 34__attribute__((weak)) void qk_ucis_success(uint8_t symbol_index) {}
36void qk_ucis_success(uint8_t symbol_index) {
37}
38 35
39static bool is_uni_seq(char *seq) { 36static bool is_uni_seq(char *seq) {
40 uint8_t i; 37 uint8_t i;
41 38
42 for (i = 0; seq[i]; i++) { 39 for (i = 0; seq[i]; i++) {
43 uint16_t code; 40 uint16_t code;
44 if (('1' <= seq[i]) && (seq[i] <= '0')) 41 if (('1' <= seq[i]) && (seq[i] <= '0'))
45 code = seq[i] - '1' + KC_1; 42 code = seq[i] - '1' + KC_1;
46 else 43 else
47 code = seq[i] - 'a' + KC_A; 44 code = seq[i] - 'a' + KC_A;
48 45
49 if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != code) 46 if (i > qk_ucis_state.count || qk_ucis_state.codes[i] != code) return false;
50 return false; 47 }
51 }
52 48
53 return (qk_ucis_state.codes[i] == KC_ENT || 49 return (qk_ucis_state.codes[i] == KC_ENT || qk_ucis_state.codes[i] == KC_SPC);
54 qk_ucis_state.codes[i] == KC_SPC);
55} 50}
56 51
57__attribute__((weak)) 52__attribute__((weak)) void qk_ucis_symbol_fallback(void) {
58void qk_ucis_symbol_fallback (void) { 53 for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) {
59 for (uint8_t i = 0; i < qk_ucis_state.count - 1; i++) { 54 uint8_t code = qk_ucis_state.codes[i];
60 uint8_t code = qk_ucis_state.codes[i]; 55 register_code(code);
61 register_code(code); 56 unregister_code(code);
62 unregister_code(code); 57 wait_ms(UNICODE_TYPE_DELAY);
63 wait_ms(UNICODE_TYPE_DELAY); 58 }
64 }
65} 59}
66 60
67__attribute__((weak)) 61__attribute__((weak)) void qk_ucis_cancel(void) {}
68void qk_ucis_cancel(void) {
69}
70 62
71void register_ucis(const char *hex) { 63void register_ucis(const char *hex) {
72 for(int i = 0; hex[i]; i++) { 64 for (int i = 0; hex[i]; i++) {
73 uint8_t kc = 0; 65 uint8_t kc = 0;
74 char c = hex[i]; 66 char c = hex[i];
75 67
76 switch (c) { 68 switch (c) {
77 case '0': 69 case '0':
78 kc = KC_0; 70 kc = KC_0;
79 break; 71 break;
80 case '1' ... '9': 72 case '1' ... '9':
81 kc = c - '1' + KC_1; 73 kc = c - '1' + KC_1;
82 break; 74 break;
83 case 'a' ... 'f': 75 case 'a' ... 'f':
84 kc = c - 'a' + KC_A; 76 kc = c - 'a' + KC_A;
85 break; 77 break;
86 case 'A' ... 'F': 78 case 'A' ... 'F':
87 kc = c - 'A' + KC_A; 79 kc = c - 'A' + KC_A;
88 break; 80 break;
81 }
82
83 if (kc) {
84 register_code(kc);
85 unregister_code(kc);
86 wait_ms(UNICODE_TYPE_DELAY);
87 }
89 } 88 }
90
91 if (kc) {
92 register_code (kc);
93 unregister_code (kc);
94 wait_ms (UNICODE_TYPE_DELAY);
95 }
96 }
97} 89}
98 90
99bool process_ucis (uint16_t keycode, keyrecord_t *record) { 91bool process_ucis(uint16_t keycode, keyrecord_t *record) {
100 uint8_t i; 92 uint8_t i;
101 93
102 if (!qk_ucis_state.in_progress) 94 if (!qk_ucis_state.in_progress) return true;
103 return true;
104 95
105 if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH && 96 if (qk_ucis_state.count >= UCIS_MAX_SYMBOL_LENGTH && !(keycode == KC_BSPC || keycode == KC_ESC || keycode == KC_SPC || keycode == KC_ENT)) {
106 !(keycode == KC_BSPC || keycode == KC_ESC || keycode == KC_SPC || keycode == KC_ENT)) { 97 return false;
107 return false;
108 }
109
110 if (!record->event.pressed)
111 return true;
112
113 qk_ucis_state.codes[qk_ucis_state.count] = keycode;
114 qk_ucis_state.count++;
115
116 if (keycode == KC_BSPC) {
117 if (qk_ucis_state.count >= 2) {
118 qk_ucis_state.count -= 2;
119 return true;
120 } else {
121 qk_ucis_state.count--;
122 return false;
123 } 98 }
124 }
125 99
126 if (keycode == KC_ENT || keycode == KC_SPC || keycode == KC_ESC) { 100 if (!record->event.pressed) return true;
127 bool symbol_found = false;
128 101
129 for (i = qk_ucis_state.count; i > 0; i--) { 102 qk_ucis_state.codes[qk_ucis_state.count] = keycode;
130 register_code (KC_BSPC); 103 qk_ucis_state.count++;
131 unregister_code (KC_BSPC);
132 wait_ms(UNICODE_TYPE_DELAY);
133 }
134
135 if (keycode == KC_ESC) {
136 qk_ucis_state.in_progress = false;
137 qk_ucis_cancel();
138 return false;
139 }
140 104
141 unicode_input_start(); 105 if (keycode == KC_BSPC) {
142 for (i = 0; ucis_symbol_table[i].symbol; i++) { 106 if (qk_ucis_state.count >= 2) {
143 if (is_uni_seq (ucis_symbol_table[i].symbol)) { 107 qk_ucis_state.count -= 2;
144 symbol_found = true; 108 return true;
145 register_ucis(ucis_symbol_table[i].code + 2); 109 } else {
146 break; 110 qk_ucis_state.count--;
147 } 111 return false;
148 } 112 }
149 if (!symbol_found) {
150 qk_ucis_symbol_fallback();
151 } 113 }
152 unicode_input_finish();
153 114
154 if (symbol_found) { 115 if (keycode == KC_ENT || keycode == KC_SPC || keycode == KC_ESC) {
155 qk_ucis_success(i); 116 bool symbol_found = false;
117
118 for (i = qk_ucis_state.count; i > 0; i--) {
119 register_code(KC_BSPC);
120 unregister_code(KC_BSPC);
121 wait_ms(UNICODE_TYPE_DELAY);
122 }
123
124 if (keycode == KC_ESC) {
125 qk_ucis_state.in_progress = false;
126 qk_ucis_cancel();
127 return false;
128 }
129
130 unicode_input_start();
131 for (i = 0; ucis_symbol_table[i].symbol; i++) {
132 if (is_uni_seq(ucis_symbol_table[i].symbol)) {
133 symbol_found = true;
134 register_ucis(ucis_symbol_table[i].code + 2);
135 break;
136 }
137 }
138 if (!symbol_found) {
139 qk_ucis_symbol_fallback();
140 }
141 unicode_input_finish();
142
143 if (symbol_found) {
144 qk_ucis_success(i);
145 }
146
147 qk_ucis_state.in_progress = false;
148 return false;
156 } 149 }
157 150 return true;
158 qk_ucis_state.in_progress = false;
159 return false;
160 }
161 return true;
162} 151}
diff --git a/quantum/process_keycode/process_ucis.h b/quantum/process_keycode/process_ucis.h
index b114d839a..0f93a198b 100644
--- a/quantum/process_keycode/process_ucis.h
+++ b/quantum/process_keycode/process_ucis.h
@@ -20,30 +20,34 @@
20#include "process_unicode_common.h" 20#include "process_unicode_common.h"
21 21
22#ifndef UCIS_MAX_SYMBOL_LENGTH 22#ifndef UCIS_MAX_SYMBOL_LENGTH
23#define UCIS_MAX_SYMBOL_LENGTH 32 23# define UCIS_MAX_SYMBOL_LENGTH 32
24#endif 24#endif
25 25
26typedef struct { 26typedef struct {
27 char *symbol; 27 char *symbol;
28 char *code; 28 char *code;
29} qk_ucis_symbol_t; 29} qk_ucis_symbol_t;
30 30
31typedef struct { 31typedef struct {
32 uint8_t count; 32 uint8_t count;
33 uint16_t codes[UCIS_MAX_SYMBOL_LENGTH]; 33 uint16_t codes[UCIS_MAX_SYMBOL_LENGTH];
34 bool in_progress:1; 34 bool in_progress : 1;
35} qk_ucis_state_t; 35} qk_ucis_state_t;
36 36
37extern qk_ucis_state_t qk_ucis_state; 37extern qk_ucis_state_t qk_ucis_state;
38 38
39#define UCIS_TABLE(...) {__VA_ARGS__, {NULL, NULL}} 39#define UCIS_TABLE(...) \
40#define UCIS_SYM(name, code) {name, #code} 40 { \
41 __VA_ARGS__, { NULL, NULL } \
42 }
43#define UCIS_SYM(name, code) \
44 { name, #code }
41 45
42extern const qk_ucis_symbol_t ucis_symbol_table[]; 46extern const qk_ucis_symbol_t ucis_symbol_table[];
43 47
44void qk_ucis_start(void); 48void qk_ucis_start(void);
45void qk_ucis_start_user(void); 49void qk_ucis_start_user(void);
46void qk_ucis_symbol_fallback (void); 50void qk_ucis_symbol_fallback(void);
47void qk_ucis_success(uint8_t symbol_index); 51void qk_ucis_success(uint8_t symbol_index);
48void register_ucis(const char *hex); 52void register_ucis(const char *hex);
49bool process_ucis (uint16_t keycode, keyrecord_t *record); 53bool process_ucis(uint16_t keycode, keyrecord_t *record);
diff --git a/quantum/process_keycode/process_unicode.c b/quantum/process_keycode/process_unicode.c
index 2c914013a..18a1d8bc1 100644
--- a/quantum/process_keycode/process_unicode.c
+++ b/quantum/process_keycode/process_unicode.c
@@ -19,10 +19,10 @@
19#include "eeprom.h" 19#include "eeprom.h"
20 20
21bool process_unicode(uint16_t keycode, keyrecord_t *record) { 21bool process_unicode(uint16_t keycode, keyrecord_t *record) {
22 if (keycode >= QK_UNICODE && keycode <= QK_UNICODE_MAX && record->event.pressed) { 22 if (keycode >= QK_UNICODE && keycode <= QK_UNICODE_MAX && record->event.pressed) {
23 unicode_input_start(); 23 unicode_input_start();
24 register_hex(keycode & 0x7FFF); 24 register_hex(keycode & 0x7FFF);
25 unicode_input_finish(); 25 unicode_input_finish();
26 } 26 }
27 return true; 27 return true;
28} 28}
diff --git a/quantum/process_keycode/process_unicode_common.c b/quantum/process_keycode/process_unicode_common.c
index 21ac2291d..94383f19b 100644
--- a/quantum/process_keycode/process_unicode_common.c
+++ b/quantum/process_keycode/process_unicode_common.c
@@ -23,220 +23,215 @@ unicode_config_t unicode_config;
23uint8_t unicode_saved_mods; 23uint8_t unicode_saved_mods;
24 24
25#if UNICODE_SELECTED_MODES != -1 25#if UNICODE_SELECTED_MODES != -1
26static uint8_t selected[] = { UNICODE_SELECTED_MODES }; 26static uint8_t selected[] = {UNICODE_SELECTED_MODES};
27static uint8_t selected_count = sizeof selected / sizeof *selected; 27static uint8_t selected_count = sizeof selected / sizeof *selected;
28static uint8_t selected_index; 28static uint8_t selected_index;
29#endif 29#endif
30 30
31void unicode_input_mode_init(void) { 31void unicode_input_mode_init(void) {
32 unicode_config.raw = eeprom_read_byte(EECONFIG_UNICODEMODE); 32 unicode_config.raw = eeprom_read_byte(EECONFIG_UNICODEMODE);
33#if UNICODE_SELECTED_MODES != -1 33#if UNICODE_SELECTED_MODES != -1
34 #if UNICODE_CYCLE_PERSIST 34# if UNICODE_CYCLE_PERSIST
35 // Find input_mode in selected modes 35 // Find input_mode in selected modes
36 uint8_t i; 36 uint8_t i;
37 for (i = 0; i < selected_count; i++) { 37 for (i = 0; i < selected_count; i++) {
38 if (selected[i] == unicode_config.input_mode) { 38 if (selected[i] == unicode_config.input_mode) {
39 selected_index = i; 39 selected_index = i;
40 break; 40 break;
41 }
41 } 42 }
42 } 43 if (i == selected_count) {
43 if (i == selected_count) { 44 // Not found: input_mode isn't selected, change to one that is
44 // Not found: input_mode isn't selected, change to one that is 45 unicode_config.input_mode = selected[selected_index = 0];
46 }
47# else
48 // Always change to the first selected input mode
45 unicode_config.input_mode = selected[selected_index = 0]; 49 unicode_config.input_mode = selected[selected_index = 0];
46 } 50# endif
47 #else
48 // Always change to the first selected input mode
49 unicode_config.input_mode = selected[selected_index = 0];
50 #endif
51#endif 51#endif
52 dprintf("Unicode input mode init to: %u\n", unicode_config.input_mode); 52 dprintf("Unicode input mode init to: %u\n", unicode_config.input_mode);
53} 53}
54 54
55uint8_t get_unicode_input_mode(void) { 55uint8_t get_unicode_input_mode(void) { return unicode_config.input_mode; }
56 return unicode_config.input_mode;
57}
58 56
59void set_unicode_input_mode(uint8_t mode) { 57void set_unicode_input_mode(uint8_t mode) {
60 unicode_config.input_mode = mode; 58 unicode_config.input_mode = mode;
61 persist_unicode_input_mode(); 59 persist_unicode_input_mode();
62 dprintf("Unicode input mode set to: %u\n", unicode_config.input_mode); 60 dprintf("Unicode input mode set to: %u\n", unicode_config.input_mode);
63} 61}
64 62
65void cycle_unicode_input_mode(uint8_t offset) { 63void cycle_unicode_input_mode(uint8_t offset) {
66#if UNICODE_SELECTED_MODES != -1 64#if UNICODE_SELECTED_MODES != -1
67 selected_index = (selected_index + offset) % selected_count; 65 selected_index = (selected_index + offset) % selected_count;
68 unicode_config.input_mode = selected[selected_index]; 66 unicode_config.input_mode = selected[selected_index];
69 #if UNICODE_CYCLE_PERSIST 67# if UNICODE_CYCLE_PERSIST
70 persist_unicode_input_mode(); 68 persist_unicode_input_mode();
71 #endif 69# endif
72 dprintf("Unicode input mode cycle to: %u\n", unicode_config.input_mode); 70 dprintf("Unicode input mode cycle to: %u\n", unicode_config.input_mode);
73#endif 71#endif
74} 72}
75 73
76void persist_unicode_input_mode(void) { 74void persist_unicode_input_mode(void) { eeprom_update_byte(EECONFIG_UNICODEMODE, unicode_config.input_mode); }
77 eeprom_update_byte(EECONFIG_UNICODEMODE, unicode_config.input_mode); 75
78} 76__attribute__((weak)) void unicode_input_start(void) {
77 unicode_saved_mods = get_mods(); // Save current mods
78 clear_mods(); // Unregister mods to start from a clean state
79
80 switch (unicode_config.input_mode) {
81 case UC_OSX:
82 register_code(UNICODE_KEY_OSX);
83 break;
84 case UC_LNX:
85 tap_code16(UNICODE_KEY_LNX);
86 break;
87 case UC_WIN:
88 register_code(KC_LALT);
89 tap_code(KC_PPLS);
90 break;
91 case UC_WINC:
92 tap_code(UNICODE_KEY_WINC);
93 tap_code(KC_U);
94 break;
95 }
79 96
80__attribute__((weak)) 97 wait_ms(UNICODE_TYPE_DELAY);
81void unicode_input_start(void) {
82 unicode_saved_mods = get_mods(); // Save current mods
83 clear_mods(); // Unregister mods to start from a clean state
84
85 switch (unicode_config.input_mode) {
86 case UC_OSX:
87 register_code(UNICODE_KEY_OSX);
88 break;
89 case UC_LNX:
90 tap_code16(UNICODE_KEY_LNX);
91 break;
92 case UC_WIN:
93 register_code(KC_LALT);
94 tap_code(KC_PPLS);
95 break;
96 case UC_WINC:
97 tap_code(UNICODE_KEY_WINC);
98 tap_code(KC_U);
99 break;
100 }
101
102 wait_ms(UNICODE_TYPE_DELAY);
103} 98}
104 99
105__attribute__((weak)) 100__attribute__((weak)) void unicode_input_finish(void) {
106void unicode_input_finish(void) { 101 switch (unicode_config.input_mode) {
107 switch (unicode_config.input_mode) { 102 case UC_OSX:
108 case UC_OSX: 103 unregister_code(UNICODE_KEY_OSX);
109 unregister_code(UNICODE_KEY_OSX); 104 break;
110 break; 105 case UC_LNX:
111 case UC_LNX: 106 tap_code(KC_SPC);
112 tap_code(KC_SPC); 107 break;
113 break; 108 case UC_WIN:
114 case UC_WIN: 109 unregister_code(KC_LALT);
115 unregister_code(KC_LALT); 110 break;
116 break; 111 case UC_WINC:
117 case UC_WINC: 112 tap_code(KC_ENTER);
118 tap_code(KC_ENTER); 113 break;
119 break; 114 }
120 } 115
121 116 set_mods(unicode_saved_mods); // Reregister previously set mods
122 set_mods(unicode_saved_mods); // Reregister previously set mods
123} 117}
124 118
125__attribute__((weak)) 119__attribute__((weak)) void unicode_input_cancel(void) {
126void unicode_input_cancel(void) { 120 switch (unicode_config.input_mode) {
127 switch (unicode_config.input_mode) { 121 case UC_OSX:
128 case UC_OSX: 122 unregister_code(UNICODE_KEY_OSX);
129 unregister_code(UNICODE_KEY_OSX); 123 break;
130 break; 124 case UC_LNX:
131 case UC_LNX: 125 case UC_WINC:
132 case UC_WINC: 126 tap_code(KC_ESC);
133 tap_code(KC_ESC); 127 break;
134 break; 128 case UC_WIN:
135 case UC_WIN: 129 unregister_code(KC_LALT);
136 unregister_code(KC_LALT); 130 break;
137 break; 131 }
138 } 132
139 133 set_mods(unicode_saved_mods); // Reregister previously set mods
140 set_mods(unicode_saved_mods); // Reregister previously set mods
141} 134}
142 135
143__attribute__((weak)) 136__attribute__((weak)) uint16_t hex_to_keycode(uint8_t hex) {
144uint16_t hex_to_keycode(uint8_t hex) { 137 if (hex == 0x0) {
145 if (hex == 0x0) { 138 return KC_0;
146 return KC_0; 139 } else if (hex < 0xA) {
147 } else if (hex < 0xA) { 140 return KC_1 + (hex - 0x1);
148 return KC_1 + (hex - 0x1); 141 } else {
149 } else { 142 return KC_A + (hex - 0xA);
150 return KC_A + (hex - 0xA); 143 }
151 }
152} 144}
153 145
154void register_hex(uint16_t hex) { 146void register_hex(uint16_t hex) {
155 for(int i = 3; i >= 0; i--) { 147 for (int i = 3; i >= 0; i--) {
156 uint8_t digit = ((hex >> (i*4)) & 0xF); 148 uint8_t digit = ((hex >> (i * 4)) & 0xF);
157 tap_code(hex_to_keycode(digit)); 149 tap_code(hex_to_keycode(digit));
158 } 150 }
159} 151}
160 152
161void send_unicode_hex_string(const char *str) { 153void send_unicode_hex_string(const char *str) {
162 if (!str) { return; } 154 if (!str) {
163 155 return;
164 while (*str) {
165 // Find the next code point (token) in the string
166 for (; *str == ' '; str++);
167 size_t n = strcspn(str, " "); // Length of the current token
168 char code_point[n+1];
169 strncpy(code_point, str, n);
170 code_point[n] = '\0'; // Make sure it's null-terminated
171
172 // Normalize the code point: make all hex digits lowercase
173 for (char *p = code_point; *p; p++) {
174 *p = tolower((unsigned char)*p);
175 } 156 }
176 157
177 // Send the code point as a Unicode input string 158 while (*str) {
178 unicode_input_start(); 159 // Find the next code point (token) in the string
179 send_string(code_point); 160 for (; *str == ' '; str++)
180 unicode_input_finish(); 161 ;
181 162 size_t n = strcspn(str, " "); // Length of the current token
182 str += n; // Move to the first ' ' (or '\0') after the current token 163 char code_point[n + 1];
183 } 164 strncpy(code_point, str, n);
165 code_point[n] = '\0'; // Make sure it's null-terminated
166
167 // Normalize the code point: make all hex digits lowercase
168 for (char *p = code_point; *p; p++) {
169 *p = tolower((unsigned char)*p);
170 }
171
172 // Send the code point as a Unicode input string
173 unicode_input_start();
174 send_string(code_point);
175 unicode_input_finish();
176
177 str += n; // Move to the first ' ' (or '\0') after the current token
178 }
184} 179}
185 180
186bool process_unicode_common(uint16_t keycode, keyrecord_t *record) { 181bool process_unicode_common(uint16_t keycode, keyrecord_t *record) {
187 if (record->event.pressed) { 182 if (record->event.pressed) {
188 switch (keycode) { 183 switch (keycode) {
189 case UNICODE_MODE_FORWARD: 184 case UNICODE_MODE_FORWARD:
190 cycle_unicode_input_mode(+1); 185 cycle_unicode_input_mode(+1);
191 break; 186 break;
192 case UNICODE_MODE_REVERSE: 187 case UNICODE_MODE_REVERSE:
193 cycle_unicode_input_mode(-1); 188 cycle_unicode_input_mode(-1);
194 break; 189 break;
195 190
196 case UNICODE_MODE_OSX: 191 case UNICODE_MODE_OSX:
197 set_unicode_input_mode(UC_OSX); 192 set_unicode_input_mode(UC_OSX);
198#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_OSX) 193#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_OSX)
199 static float song_osx[][2] = UNICODE_SONG_OSX; 194 static float song_osx[][2] = UNICODE_SONG_OSX;
200 PLAY_SONG(song_osx); 195 PLAY_SONG(song_osx);
201#endif 196#endif
202 break; 197 break;
203 case UNICODE_MODE_LNX: 198 case UNICODE_MODE_LNX:
204 set_unicode_input_mode(UC_LNX); 199 set_unicode_input_mode(UC_LNX);
205#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_LNX) 200#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_LNX)
206 static float song_lnx[][2] = UNICODE_SONG_LNX; 201 static float song_lnx[][2] = UNICODE_SONG_LNX;
207 PLAY_SONG(song_lnx); 202 PLAY_SONG(song_lnx);
208#endif 203#endif
209 break; 204 break;
210 case UNICODE_MODE_WIN: 205 case UNICODE_MODE_WIN:
211 set_unicode_input_mode(UC_WIN); 206 set_unicode_input_mode(UC_WIN);
212#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_WIN) 207#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_WIN)
213 static float song_win[][2] = UNICODE_SONG_WIN; 208 static float song_win[][2] = UNICODE_SONG_WIN;
214 PLAY_SONG(song_win); 209 PLAY_SONG(song_win);
215#endif 210#endif
216 break; 211 break;
217 case UNICODE_MODE_BSD: 212 case UNICODE_MODE_BSD:
218 set_unicode_input_mode(UC_BSD); 213 set_unicode_input_mode(UC_BSD);
219#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_BSD) 214#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_BSD)
220 static float song_bsd[][2] = UNICODE_SONG_BSD; 215 static float song_bsd[][2] = UNICODE_SONG_BSD;
221 PLAY_SONG(song_bsd); 216 PLAY_SONG(song_bsd);
222#endif 217#endif
223 break; 218 break;
224 case UNICODE_MODE_WINC: 219 case UNICODE_MODE_WINC:
225 set_unicode_input_mode(UC_WINC); 220 set_unicode_input_mode(UC_WINC);
226#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_WINC) 221#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_WINC)
227 static float song_winc[][2] = UNICODE_SONG_WINC; 222 static float song_winc[][2] = UNICODE_SONG_WINC;
228 PLAY_SONG(song_winc); 223 PLAY_SONG(song_winc);
229#endif 224#endif
230 break; 225 break;
226 }
231 } 227 }
232 } 228#if defined(UNICODE_ENABLE)
233#if defined(UNICODE_ENABLE) 229 return process_unicode(keycode, record);
234 return process_unicode(keycode, record);
235#elif defined(UNICODEMAP_ENABLE) 230#elif defined(UNICODEMAP_ENABLE)
236 return process_unicodemap(keycode, record); 231 return process_unicodemap(keycode, record);
237#elif defined(UCIS_ENABLE) 232#elif defined(UCIS_ENABLE)
238 return process_ucis(keycode, record); 233 return process_ucis(keycode, record);
239#else 234#else
240 return true; 235 return true;
241#endif 236#endif
242} 237}
diff --git a/quantum/process_keycode/process_unicode_common.h b/quantum/process_keycode/process_unicode_common.h
index 7340800e5..cab6eea6e 100644
--- a/quantum/process_keycode/process_unicode_common.h
+++ b/quantum/process_keycode/process_unicode_common.h
@@ -19,60 +19,60 @@
19#include "quantum.h" 19#include "quantum.h"
20 20
21#if defined(UNICODE_ENABLE) + defined(UNICODEMAP_ENABLE) + defined(UCIS_ENABLE) > 1 21#if defined(UNICODE_ENABLE) + defined(UNICODEMAP_ENABLE) + defined(UCIS_ENABLE) > 1
22 #error "Cannot enable more than one Unicode method (UNICODE, UNICODEMAP, UCIS) at the same time" 22# error "Cannot enable more than one Unicode method (UNICODE, UNICODEMAP, UCIS) at the same time"
23#endif 23#endif
24 24
25// Keycodes used for starting Unicode input on different platforms 25// Keycodes used for starting Unicode input on different platforms
26#ifndef UNICODE_KEY_OSX 26#ifndef UNICODE_KEY_OSX
27 #define UNICODE_KEY_OSX KC_LALT 27# define UNICODE_KEY_OSX KC_LALT
28#endif 28#endif
29#ifndef UNICODE_KEY_LNX 29#ifndef UNICODE_KEY_LNX
30 #define UNICODE_KEY_LNX LCTL(LSFT(KC_U)) 30# define UNICODE_KEY_LNX LCTL(LSFT(KC_U))
31#endif 31#endif
32#ifndef UNICODE_KEY_WINC 32#ifndef UNICODE_KEY_WINC
33 #define UNICODE_KEY_WINC KC_RALT 33# define UNICODE_KEY_WINC KC_RALT
34#endif 34#endif
35 35
36// Comma-delimited, ordered list of input modes selected for use (e.g. in cycle) 36// Comma-delimited, ordered list of input modes selected for use (e.g. in cycle)
37// Example: #define UNICODE_SELECTED_MODES UC_WINC, UC_LNX 37// Example: #define UNICODE_SELECTED_MODES UC_WINC, UC_LNX
38#ifndef UNICODE_SELECTED_MODES 38#ifndef UNICODE_SELECTED_MODES
39 #define UNICODE_SELECTED_MODES -1 39# define UNICODE_SELECTED_MODES -1
40#endif 40#endif
41 41
42// Whether input mode changes in cycle should be written to EEPROM 42// Whether input mode changes in cycle should be written to EEPROM
43#ifndef UNICODE_CYCLE_PERSIST 43#ifndef UNICODE_CYCLE_PERSIST
44 #define UNICODE_CYCLE_PERSIST true 44# define UNICODE_CYCLE_PERSIST true
45#endif 45#endif
46 46
47// Delay between starting Unicode input and sending a sequence, in ms 47// Delay between starting Unicode input and sending a sequence, in ms
48#ifndef UNICODE_TYPE_DELAY 48#ifndef UNICODE_TYPE_DELAY
49 #define UNICODE_TYPE_DELAY 10 49# define UNICODE_TYPE_DELAY 10
50#endif 50#endif
51 51
52enum unicode_input_modes { 52enum unicode_input_modes {
53 UC_OSX, // Mac OS X using Unicode Hex Input 53 UC_OSX, // Mac OS X using Unicode Hex Input
54 UC_LNX, // Linux using IBus 54 UC_LNX, // Linux using IBus
55 UC_WIN, // Windows using EnableHexNumpad 55 UC_WIN, // Windows using EnableHexNumpad
56 UC_BSD, // BSD (not implemented) 56 UC_BSD, // BSD (not implemented)
57 UC_WINC, // Windows using WinCompose (https://github.com/samhocevar/wincompose) 57 UC_WINC, // Windows using WinCompose (https://github.com/samhocevar/wincompose)
58 UC__COUNT // Number of available input modes (always leave at the end) 58 UC__COUNT // Number of available input modes (always leave at the end)
59}; 59};
60 60
61typedef union { 61typedef union {
62 uint32_t raw; 62 uint32_t raw;
63 struct { 63 struct {
64 uint8_t input_mode : 8; 64 uint8_t input_mode : 8;
65 }; 65 };
66} unicode_config_t; 66} unicode_config_t;
67 67
68extern unicode_config_t unicode_config; 68extern unicode_config_t unicode_config;
69extern uint8_t unicode_saved_mods; 69extern uint8_t unicode_saved_mods;
70 70
71void unicode_input_mode_init(void); 71void unicode_input_mode_init(void);
72uint8_t get_unicode_input_mode(void); 72uint8_t get_unicode_input_mode(void);
73void set_unicode_input_mode(uint8_t mode); 73void set_unicode_input_mode(uint8_t mode);
74void cycle_unicode_input_mode(uint8_t offset); 74void cycle_unicode_input_mode(uint8_t offset);
75void persist_unicode_input_mode(void); 75void persist_unicode_input_mode(void);
76 76
77void unicode_input_start(void); 77void unicode_input_start(void);
78void unicode_input_finish(void); 78void unicode_input_finish(void);
@@ -83,108 +83,108 @@ void send_unicode_hex_string(const char *str);
83 83
84bool process_unicode_common(uint16_t keycode, keyrecord_t *record); 84bool process_unicode_common(uint16_t keycode, keyrecord_t *record);
85 85
86#define UC_BSPC UC(0x0008) 86#define UC_BSPC UC(0x0008)
87#define UC_SPC UC(0x0020) 87#define UC_SPC UC(0x0020)
88 88
89#define UC_EXLM UC(0x0021) 89#define UC_EXLM UC(0x0021)
90#define UC_DQUT UC(0x0022) 90#define UC_DQUT UC(0x0022)
91#define UC_HASH UC(0x0023) 91#define UC_HASH UC(0x0023)
92#define UC_DLR UC(0x0024) 92#define UC_DLR UC(0x0024)
93#define UC_PERC UC(0x0025) 93#define UC_PERC UC(0x0025)
94#define UC_AMPR UC(0x0026) 94#define UC_AMPR UC(0x0026)
95#define UC_QUOT UC(0x0027) 95#define UC_QUOT UC(0x0027)
96#define UC_LPRN UC(0x0028) 96#define UC_LPRN UC(0x0028)
97#define UC_RPRN UC(0x0029) 97#define UC_RPRN UC(0x0029)
98#define UC_ASTR UC(0x002A) 98#define UC_ASTR UC(0x002A)
99#define UC_PLUS UC(0x002B) 99#define UC_PLUS UC(0x002B)
100#define UC_COMM UC(0x002C) 100#define UC_COMM UC(0x002C)
101#define UC_DASH UC(0x002D) 101#define UC_DASH UC(0x002D)
102#define UC_DOT UC(0x002E) 102#define UC_DOT UC(0x002E)
103#define UC_SLSH UC(0x002F) 103#define UC_SLSH UC(0x002F)
104 104
105#define UC_0 UC(0x0030) 105#define UC_0 UC(0x0030)
106#define UC_1 UC(0x0031) 106#define UC_1 UC(0x0031)
107#define UC_2 UC(0x0032) 107#define UC_2 UC(0x0032)
108#define UC_3 UC(0x0033) 108#define UC_3 UC(0x0033)
109#define UC_4 UC(0x0034) 109#define UC_4 UC(0x0034)
110#define UC_5 UC(0x0035) 110#define UC_5 UC(0x0035)
111#define UC_6 UC(0x0036) 111#define UC_6 UC(0x0036)
112#define UC_7 UC(0x0037) 112#define UC_7 UC(0x0037)
113#define UC_8 UC(0x0038) 113#define UC_8 UC(0x0038)
114#define UC_9 UC(0x0039) 114#define UC_9 UC(0x0039)
115 115
116#define UC_COLN UC(0x003A) 116#define UC_COLN UC(0x003A)
117#define UC_SCLN UC(0x003B) 117#define UC_SCLN UC(0x003B)
118#define UC_LT UC(0x003C) 118#define UC_LT UC(0x003C)
119#define UC_EQL UC(0x003D) 119#define UC_EQL UC(0x003D)
120#define UC_GT UC(0x003E) 120#define UC_GT UC(0x003E)
121#define UC_QUES UC(0x003F) 121#define UC_QUES UC(0x003F)
122#define UC_AT UC(0x0040) 122#define UC_AT UC(0x0040)
123 123
124#define UC_A UC(0x0041) 124#define UC_A UC(0x0041)
125#define UC_B UC(0x0042) 125#define UC_B UC(0x0042)
126#define UC_C UC(0x0043) 126#define UC_C UC(0x0043)
127#define UC_D UC(0x0044) 127#define UC_D UC(0x0044)
128#define UC_E UC(0x0045) 128#define UC_E UC(0x0045)
129#define UC_F UC(0x0046) 129#define UC_F UC(0x0046)
130#define UC_G UC(0x0047) 130#define UC_G UC(0x0047)
131#define UC_H UC(0x0048) 131#define UC_H UC(0x0048)
132#define UC_I UC(0x0049) 132#define UC_I UC(0x0049)
133#define UC_J UC(0x004A) 133#define UC_J UC(0x004A)
134#define UC_K UC(0x004B) 134#define UC_K UC(0x004B)
135#define UC_L UC(0x004C) 135#define UC_L UC(0x004C)
136#define UC_M UC(0x004D) 136#define UC_M UC(0x004D)
137#define UC_N UC(0x004E) 137#define UC_N UC(0x004E)
138#define UC_O UC(0x004F) 138#define UC_O UC(0x004F)
139#define UC_P UC(0x0050) 139#define UC_P UC(0x0050)
140#define UC_Q UC(0x0051) 140#define UC_Q UC(0x0051)
141#define UC_R UC(0x0052) 141#define UC_R UC(0x0052)
142#define UC_S UC(0x0053) 142#define UC_S UC(0x0053)
143#define UC_T UC(0x0054) 143#define UC_T UC(0x0054)
144#define UC_U UC(0x0055) 144#define UC_U UC(0x0055)
145#define UC_V UC(0x0056) 145#define UC_V UC(0x0056)
146#define UC_W UC(0x0057) 146#define UC_W UC(0x0057)
147#define UC_X UC(0x0058) 147#define UC_X UC(0x0058)
148#define UC_Y UC(0x0059) 148#define UC_Y UC(0x0059)
149#define UC_Z UC(0x005A) 149#define UC_Z UC(0x005A)
150 150
151#define UC_LBRC UC(0x005B) 151#define UC_LBRC UC(0x005B)
152#define UC_BSLS UC(0x005C) 152#define UC_BSLS UC(0x005C)
153#define UC_RBRC UC(0x005D) 153#define UC_RBRC UC(0x005D)
154#define UC_CIRM UC(0x005E) 154#define UC_CIRM UC(0x005E)
155#define UC_UNDR UC(0x005F) 155#define UC_UNDR UC(0x005F)
156 156
157#define UC_GRV UC(0x0060) 157#define UC_GRV UC(0x0060)
158 158
159#define UC_a UC(0x0061) 159#define UC_a UC(0x0061)
160#define UC_b UC(0x0062) 160#define UC_b UC(0x0062)
161#define UC_c UC(0x0063) 161#define UC_c UC(0x0063)
162#define UC_d UC(0x0064) 162#define UC_d UC(0x0064)
163#define UC_e UC(0x0065) 163#define UC_e UC(0x0065)
164#define UC_f UC(0x0066) 164#define UC_f UC(0x0066)
165#define UC_g UC(0x0067) 165#define UC_g UC(0x0067)
166#define UC_h UC(0x0068) 166#define UC_h UC(0x0068)
167#define UC_i UC(0x0069) 167#define UC_i UC(0x0069)
168#define UC_j UC(0x006A) 168#define UC_j UC(0x006A)
169#define UC_k UC(0x006B) 169#define UC_k UC(0x006B)
170#define UC_l UC(0x006C) 170#define UC_l UC(0x006C)
171#define UC_m UC(0x006D) 171#define UC_m UC(0x006D)
172#define UC_n UC(0x006E) 172#define UC_n UC(0x006E)
173#define UC_o UC(0x006F) 173#define UC_o UC(0x006F)
174#define UC_p UC(0x0070) 174#define UC_p UC(0x0070)
175#define UC_q UC(0x0071) 175#define UC_q UC(0x0071)
176#define UC_r UC(0x0072) 176#define UC_r UC(0x0072)
177#define UC_s UC(0x0073) 177#define UC_s UC(0x0073)
178#define UC_t UC(0x0074) 178#define UC_t UC(0x0074)
179#define UC_u UC(0x0075) 179#define UC_u UC(0x0075)
180#define UC_v UC(0x0076) 180#define UC_v UC(0x0076)
181#define UC_w UC(0x0077) 181#define UC_w UC(0x0077)
182#define UC_x UC(0x0078) 182#define UC_x UC(0x0078)
183#define UC_y UC(0x0079) 183#define UC_y UC(0x0079)
184#define UC_z UC(0x007A) 184#define UC_z UC(0x007A)
185 185
186#define UC_LCBR UC(0x007B) 186#define UC_LCBR UC(0x007B)
187#define UC_PIPE UC(0x007C) 187#define UC_PIPE UC(0x007C)
188#define UC_RCBR UC(0x007D) 188#define UC_RCBR UC(0x007D)
189#define UC_TILD UC(0x007E) 189#define UC_TILD UC(0x007E)
190#define UC_DEL UC(0x007F) 190#define UC_DEL UC(0x007F)
diff --git a/quantum/process_keycode/process_unicodemap.c b/quantum/process_keycode/process_unicodemap.c
index b88787986..4364f156c 100644
--- a/quantum/process_keycode/process_unicodemap.c
+++ b/quantum/process_keycode/process_unicodemap.c
@@ -17,62 +17,63 @@
17#include "process_unicodemap.h" 17#include "process_unicodemap.h"
18 18
19void register_hex32(uint32_t hex) { 19void register_hex32(uint32_t hex) {
20 bool onzerostart = true; 20 bool onzerostart = true;
21 for(int i = 7; i >= 0; i--) { 21 for (int i = 7; i >= 0; i--) {
22 if (i <= 3) { 22 if (i <= 3) {
23 onzerostart = false; 23 onzerostart = false;
24 }
25 uint8_t digit = ((hex >> (i * 4)) & 0xF);
26 if (digit == 0) {
27 if (!onzerostart) {
28 register_code(hex_to_keycode(digit));
29 unregister_code(hex_to_keycode(digit));
30 }
31 } else {
32 register_code(hex_to_keycode(digit));
33 unregister_code(hex_to_keycode(digit));
34 onzerostart = false;
35 }
24 } 36 }
25 uint8_t digit = ((hex >> (i*4)) & 0xF);
26 if (digit == 0) {
27 if (!onzerostart) {
28 register_code(hex_to_keycode(digit));
29 unregister_code(hex_to_keycode(digit));
30 }
31 } else {
32 register_code(hex_to_keycode(digit));
33 unregister_code(hex_to_keycode(digit));
34 onzerostart = false;
35 }
36 }
37} 37}
38 38
39__attribute__((weak)) 39__attribute__((weak)) uint16_t unicodemap_index(uint16_t keycode) {
40uint16_t unicodemap_index(uint16_t keycode) { 40 if (keycode >= QK_UNICODEMAP_PAIR) {
41 if (keycode >= QK_UNICODEMAP_PAIR) { 41 // Keycode is a pair: extract index based on Shift / Caps Lock state
42 // Keycode is a pair: extract index based on Shift / Caps Lock state 42 uint16_t index = keycode - QK_UNICODEMAP_PAIR;
43 uint16_t index = keycode - QK_UNICODEMAP_PAIR;
44 43
45 bool shift = unicode_saved_mods & MOD_MASK_SHIFT, caps = IS_HOST_LED_ON(USB_LED_CAPS_LOCK); 44 bool shift = unicode_saved_mods & MOD_MASK_SHIFT, caps = IS_HOST_LED_ON(USB_LED_CAPS_LOCK);
46 if (shift ^ caps) { index >>= 7; } 45 if (shift ^ caps) {
46 index >>= 7;
47 }
47 48
48 return index & 0x7F; 49 return index & 0x7F;
49 } else { 50 } else {
50 // Keycode is a regular index 51 // Keycode is a regular index
51 return keycode - QK_UNICODEMAP; 52 return keycode - QK_UNICODEMAP;
52 } 53 }
53} 54}
54 55
55bool process_unicodemap(uint16_t keycode, keyrecord_t *record) { 56bool process_unicodemap(uint16_t keycode, keyrecord_t *record) {
56 if (keycode >= QK_UNICODEMAP && keycode <= QK_UNICODEMAP_PAIR_MAX && record->event.pressed) { 57 if (keycode >= QK_UNICODEMAP && keycode <= QK_UNICODEMAP_PAIR_MAX && record->event.pressed) {
57 unicode_input_start(); 58 unicode_input_start();
58 59
59 uint32_t code = pgm_read_dword(unicode_map + unicodemap_index(keycode)); 60 uint32_t code = pgm_read_dword(unicode_map + unicodemap_index(keycode));
60 uint8_t input_mode = get_unicode_input_mode(); 61 uint8_t input_mode = get_unicode_input_mode();
61 62
62 if (code > 0x10FFFF || (code > 0xFFFF && input_mode == UC_WIN)) { 63 if (code > 0x10FFFF || (code > 0xFFFF && input_mode == UC_WIN)) {
63 // Character is out of range supported by the platform 64 // Character is out of range supported by the platform
64 unicode_input_cancel(); 65 unicode_input_cancel();
65 } else if (code > 0xFFFF && input_mode == UC_OSX) { 66 } else if (code > 0xFFFF && input_mode == UC_OSX) {
66 // Convert to UTF-16 surrogate pair on Mac 67 // Convert to UTF-16 surrogate pair on Mac
67 code -= 0x10000; 68 code -= 0x10000;
68 uint32_t lo = code & 0x3FF, hi = (code & 0xFFC00) >> 10; 69 uint32_t lo = code & 0x3FF, hi = (code & 0xFFC00) >> 10;
69 register_hex32(hi + 0xD800); 70 register_hex32(hi + 0xD800);
70 register_hex32(lo + 0xDC00); 71 register_hex32(lo + 0xDC00);
71 unicode_input_finish(); 72 unicode_input_finish();
72 } else { 73 } else {
73 register_hex32(code); 74 register_hex32(code);
74 unicode_input_finish(); 75 unicode_input_finish();
76 }
75 } 77 }
76 } 78 return true;
77 return true;
78} 79}
diff --git a/quantum/process_keycode/process_unicodemap.h b/quantum/process_keycode/process_unicodemap.h
index 51709c5dc..a4b6d77f3 100644
--- a/quantum/process_keycode/process_unicodemap.h
+++ b/quantum/process_keycode/process_unicodemap.h
@@ -20,6 +20,6 @@
20 20
21extern const uint32_t PROGMEM unicode_map[]; 21extern const uint32_t PROGMEM unicode_map[];
22 22
23void register_hex32(uint32_t hex); 23void register_hex32(uint32_t hex);
24uint16_t unicodemap_index(uint16_t keycode); 24uint16_t unicodemap_index(uint16_t keycode);
25bool process_unicodemap(uint16_t keycode, keyrecord_t *record); 25bool process_unicodemap(uint16_t keycode, keyrecord_t *record);