Commit | Line | Data |
---|---|---|
23839b8c | 1 | /* Copyright 2016-2017 Jack Humbert |
2 | * | |
3 | * This program is free software: you can redistribute it and/or modify | |
4 | * it under the terms of the GNU General Public License as published by | |
5 | * the Free Software Foundation, either version 2 of the License, or | |
6 | * (at your option) any later version. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
12 | * | |
13 | * You should have received a copy of the GNU General Public License | |
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
1a8c0dd2 | 17 | #include "quantum.h" |
2e8b32b9 | 18 | |
e7c4f621 | 19 | #ifdef PROTOCOL_LUFA |
b624f32f | 20 | # include "outputselect.h" |
2bef8b5b | 21 | #endif |
1a8c0dd2 | 22 | |
abfd6ed9 JC |
23 | #ifdef BACKLIGHT_ENABLE |
24 | # include "backlight.h" | |
542cb0a8 | 25 | extern backlight_config_t backlight_config; |
abfd6ed9 | 26 | #endif |
db1e9a46 | 27 | |
8c93c5d9 | 28 | #ifdef FAUXCLICKY_ENABLE |
b624f32f | 29 | # include "fauxclicky.h" |
8c93c5d9 | 30 | #endif |
8d0fdf10 | 31 | |
53ff8a31 | 32 | #ifdef API_ENABLE |
b624f32f | 33 | # include "api.h" |
53ff8a31 | 34 | #endif |
35 | ||
36 | #ifdef MIDI_ENABLE | |
b624f32f | 37 | # include "process_midi.h" |
53ff8a31 | 38 | #endif |
39 | ||
c1c5922a | 40 | #ifdef VELOCIKEY_ENABLE |
b624f32f | 41 | # include "velocikey.h" |
c1c5922a CL |
42 | #endif |
43 | ||
2cee371b | 44 | #ifdef HAPTIC_ENABLE |
b624f32f | 45 | # include "haptic.h" |
2cee371b | 46 | #endif |
85688e5b JH |
47 | |
48 | #ifdef ENCODER_ENABLE | |
b624f32f | 49 | # include "encoder.h" |
85688e5b JH |
50 | #endif |
51 | ||
6a3c6677 | 52 | #ifdef AUDIO_ENABLE |
b624f32f | 53 | # ifndef GOODBYE_SONG |
54 | # define GOODBYE_SONG SONG(GOODBYE_SOUND) | |
55 | # endif | |
b624f32f | 56 | float goodbye_song[][2] = GOODBYE_SONG; |
b624f32f | 57 | # ifdef DEFAULT_LAYER_SONGS |
58 | float default_layer_songs[][16][2] = DEFAULT_LAYER_SONGS; | |
59 | # endif | |
e5501d48 | 60 | # ifdef SENDSTRING_BELL |
61 | float bell_song[][2] = SONG(TERMINAL_SOUND); | |
62 | # endif | |
b624f32f | 63 | #endif |
64 | ||
65 | static void do_code16(uint16_t code, void (*f)(uint8_t)) { | |
66 | switch (code) { | |
67 | case QK_MODS ... QK_MODS_MAX: | |
68 | break; | |
69 | default: | |
70 | return; | |
71 | } | |
72 | ||
63f4806d | 73 | uint8_t mods_to_send = 0; |
b624f32f | 74 | |
542cb0a8 | 75 | if (code & QK_RMODS_MIN) { // Right mod flag is set |
63f4806d | 76 | if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_RCTL); |
77 | if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_RSFT); | |
78 | if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_RALT); | |
79 | if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_RGUI); | |
80 | } else { | |
81 | if (code & QK_LCTL) mods_to_send |= MOD_BIT(KC_LCTL); | |
82 | if (code & QK_LSFT) mods_to_send |= MOD_BIT(KC_LSFT); | |
83 | if (code & QK_LALT) mods_to_send |= MOD_BIT(KC_LALT); | |
84 | if (code & QK_LGUI) mods_to_send |= MOD_BIT(KC_LGUI); | |
85 | } | |
2b385993 | 86 | |
63f4806d | 87 | f(mods_to_send); |
2b385993 S |
88 | } |
89 | ||
b624f32f | 90 | void register_code16(uint16_t code) { |
91 | if (IS_MOD(code) || code == KC_NO) { | |
63f4806d | 92 | do_code16(code, register_mods); |
b624f32f | 93 | } else { |
63f4806d | 94 | do_code16(code, register_weak_mods); |
b624f32f | 95 | } |
96 | register_code(code); | |
0d28787c GN |
97 | } |
98 | ||
b624f32f | 99 | void unregister_code16(uint16_t code) { |
100 | unregister_code(code); | |
101 | if (IS_MOD(code) || code == KC_NO) { | |
63f4806d | 102 | do_code16(code, unregister_mods); |
b624f32f | 103 | } else { |
63f4806d | 104 | do_code16(code, unregister_weak_mods); |
b624f32f | 105 | } |
0d28787c GN |
106 | } |
107 | ||
02d44beb | 108 | void tap_code16(uint16_t code) { |
b624f32f | 109 | register_code16(code); |
110 | #if TAP_CODE_DELAY > 0 | |
02d44beb | 111 | wait_ms(TAP_CODE_DELAY); |
b624f32f | 112 | #endif |
113 | unregister_code16(code); | |
02d44beb DJ |
114 | } |
115 | ||
b624f32f | 116 | __attribute__((weak)) bool process_action_kb(keyrecord_t *record) { return true; } |
1a8c0dd2 | 117 | |
b624f32f | 118 | __attribute__((weak)) bool process_record_kb(uint16_t keycode, keyrecord_t *record) { return process_record_user(keycode, record); } |
17977a7e | 119 | |
b624f32f | 120 | __attribute__((weak)) bool process_record_user(uint16_t keycode, keyrecord_t *record) { return true; } |
17977a7e | 121 | |
a28a6e5b | 122 | void reset_keyboard(void) { |
b624f32f | 123 | clear_keyboard(); |
e6b91549 | 124 | #if defined(MIDI_ENABLE) && defined(MIDI_BASIC) |
b624f32f | 125 | process_midi_all_notes_off(); |
365b8635 | 126 | #endif |
ef5b161b | 127 | #ifdef AUDIO_ENABLE |
b624f32f | 128 | # ifndef NO_MUSIC_MODE |
ef5b161b | 129 | music_all_notes_off(); |
b624f32f | 130 | # endif |
131 | uint16_t timer_start = timer_read(); | |
132 | PLAY_SONG(goodbye_song); | |
133 | shutdown_user(); | |
134 | while (timer_elapsed(timer_start) < 250) wait_ms(1); | |
135 | stop_all_notes(); | |
6a3c6677 | 136 | #else |
b624f32f | 137 | shutdown_user(); |
138 | wait_ms(250); | |
6a3c6677 | 139 | #endif |
2cee371b | 140 | #ifdef HAPTIC_ENABLE |
b624f32f | 141 | haptic_shutdown(); |
2cee371b | 142 | #endif |
9fdc2762 JH |
143 | // this is also done later in bootloader.c - not sure if it's neccesary here |
144 | #ifdef BOOTLOADER_CATERINA | |
b624f32f | 145 | *(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific |
a28a6e5b | 146 | #endif |
b624f32f | 147 | bootloader_jump(); |
a28a6e5b PV |
148 | } |
149 | ||
5701b75e | 150 | /* Convert record into usable keycode via the contained event. */ |
b624f32f | 151 | uint16_t get_record_keycode(keyrecord_t *record) { return get_event_keycode(record->event); } |
5701b75e DJ |
152 | |
153 | /* Convert event into usable keycode. Checks the layer cache to ensure that it | |
154 | * retains the correct keycode after a layer change, if the key is still pressed. | |
155 | */ | |
156 | uint16_t get_event_keycode(keyevent_t event) { | |
b624f32f | 157 | #if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) |
644c8c79 WS |
158 | /* TODO: Use store_or_get_action() or a similar function. */ |
159 | if (!disable_action_cache) { | |
b624f32f | 160 | uint8_t layer; |
161 | ||
162 | if (event.pressed) { | |
163 | layer = layer_switch_get_layer(event.key); | |
164 | update_source_layers_cache(event.key, layer); | |
165 | } else { | |
166 | layer = read_source_layers_cache(event.key); | |
167 | } | |
168 | return keymap_key_to_keycode(layer, event.key); | |
644c8c79 | 169 | } else |
b624f32f | 170 | #endif |
171 | return keymap_key_to_keycode(layer_switch_get_layer(event.key), event.key); | |
5701b75e DJ |
172 | } |
173 | ||
174 | /* Main keycode processing function. Hands off handling to other functions, | |
175 | * then processes internal Quantum keycodes, then processes ACTIONs. | |
176 | */ | |
177 | bool process_record_quantum(keyrecord_t *record) { | |
178 | uint16_t keycode = get_record_keycode(record); | |
1a8c0dd2 | 179 | |
bf5c2cce JH |
180 | // This is how you use actions here |
181 | // if (keycode == KC_LEAD) { | |
182 | // action_t action; | |
183 | // action.code = ACTION_DEFAULT_LAYER_SET(0); | |
184 | // process_action(record, action); | |
185 | // return false; | |
186 | // } | |
187 | ||
b624f32f | 188 | #ifdef VELOCIKEY_ENABLE |
189 | if (velocikey_enabled() && record->event.pressed) { | |
190 | velocikey_accelerate(); | |
191 | } | |
192 | #endif | |
c1c5922a | 193 | |
b624f32f | 194 | #ifdef TAP_DANCE_ENABLE |
9fcda953 | 195 | preprocess_tap_dance(keycode, record); |
b624f32f | 196 | #endif |
558f3ec1 | 197 | |
b624f32f | 198 | if (!( |
199 | #if defined(KEY_LOCK_ENABLE) | |
200 | // Must run first to be able to mask key_up events. | |
201 | process_key_lock(&keycode, record) && | |
202 | #endif | |
542cb0a8 DJ |
203 | #if defined(DYNAMIC_MACRO_ENABLE) && !defined(DYNAMIC_MACRO_USER_CALL) |
204 | // Must run asap to ensure all keypresses are recorded. | |
205 | process_dynamic_macro(keycode, record) && | |
206 | #endif | |
b624f32f | 207 | #if defined(AUDIO_ENABLE) && defined(AUDIO_CLICKY) |
208 | process_clicky(keycode, record) && | |
209 | #endif // AUDIO_CLICKY | |
210 | #ifdef HAPTIC_ENABLE | |
211 | process_haptic(keycode, record) && | |
212 | #endif // HAPTIC_ENABLE | |
213 | #if defined(RGB_MATRIX_ENABLE) | |
214 | process_rgb_matrix(keycode, record) && | |
320822d7 W |
215 | #endif |
216 | #if defined(VIA_ENABLE) | |
217 | process_record_via(keycode, record) && | |
b624f32f | 218 | #endif |
219 | process_record_kb(keycode, record) && | |
220 | #if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED) | |
221 | process_midi(keycode, record) && | |
222 | #endif | |
223 | #ifdef AUDIO_ENABLE | |
224 | process_audio(keycode, record) && | |
225 | #endif | |
226 | #ifdef STENO_ENABLE | |
227 | process_steno(keycode, record) && | |
228 | #endif | |
229 | #if (defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))) && !defined(NO_MUSIC_MODE) | |
230 | process_music(keycode, record) && | |
231 | #endif | |
232 | #ifdef TAP_DANCE_ENABLE | |
233 | process_tap_dance(keycode, record) && | |
234 | #endif | |
235 | #if defined(UNICODE_ENABLE) || defined(UNICODEMAP_ENABLE) || defined(UCIS_ENABLE) | |
236 | process_unicode_common(keycode, record) && | |
237 | #endif | |
238 | #ifdef LEADER_ENABLE | |
239 | process_leader(keycode, record) && | |
240 | #endif | |
241 | #ifdef COMBO_ENABLE | |
242 | process_combo(keycode, record) && | |
243 | #endif | |
244 | #ifdef PRINTING_ENABLE | |
245 | process_printer(keycode, record) && | |
246 | #endif | |
247 | #ifdef AUTO_SHIFT_ENABLE | |
248 | process_auto_shift(keycode, record) && | |
249 | #endif | |
250 | #ifdef TERMINAL_ENABLE | |
251 | process_terminal(keycode, record) && | |
252 | #endif | |
253 | #ifdef SPACE_CADET_ENABLE | |
254 | process_space_cadet(keycode, record) && | |
d598f01c JC |
255 | #endif |
256 | #ifdef MAGIC_KEYCODE_ENABLE | |
257 | process_magic(keycode, record) && | |
ae40fc49 JC |
258 | #endif |
259 | #if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE) | |
260 | process_rgb(keycode, record) && | |
b624f32f | 261 | #endif |
262 | true)) { | |
db32864c | 263 | return false; |
b624f32f | 264 | } |
8a1e6560 | 265 | |
1604f796 YFL |
266 | if (record->event.pressed) { |
267 | switch (keycode) { | |
268 | case RESET: | |
b624f32f | 269 | reset_keyboard(); |
1604f796 | 270 | return false; |
2048df88 | 271 | #ifndef NO_DEBUG |
1604f796 | 272 | case DEBUG: |
b624f32f | 273 | debug_enable ^= 1; |
274 | if (debug_enable) { | |
275 | print("DEBUG: enabled.\n"); | |
276 | } else { | |
277 | print("DEBUG: disabled.\n"); | |
278 | } | |
2048df88 | 279 | #endif |
1604f796 YFL |
280 | return false; |
281 | case EEPROM_RESET: | |
b624f32f | 282 | eeconfig_init(); |
1604f796 | 283 | return false; |
b624f32f | 284 | #ifdef FAUXCLICKY_ENABLE |
1604f796 | 285 | case FC_TOG: |
b624f32f | 286 | FAUXCLICKY_TOGGLE; |
1604f796 YFL |
287 | return false; |
288 | case FC_ON: | |
b624f32f | 289 | FAUXCLICKY_ON; |
1604f796 YFL |
290 | return false; |
291 | case FC_OFF: | |
b624f32f | 292 | FAUXCLICKY_OFF; |
1604f796 YFL |
293 | return false; |
294 | #endif | |
295 | #ifdef VELOCIKEY_ENABLE | |
296 | case VLK_TOG: | |
297 | velocikey_toggle(); | |
298 | return false; | |
299 | #endif | |
2048df88 | 300 | #ifdef BLUETOOTH_ENABLE |
ae40fc49 | 301 | case OUT_AUTO: |
1604f796 YFL |
302 | set_output(OUTPUT_AUTO); |
303 | return false; | |
ae40fc49 | 304 | case OUT_USB: |
1604f796 YFL |
305 | set_output(OUTPUT_USB); |
306 | return false; | |
ae40fc49 | 307 | case OUT_BT: |
1604f796 YFL |
308 | set_output(OUTPUT_BLUETOOTH); |
309 | return false; | |
de4eb79c JC |
310 | #endif |
311 | #if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_BREATHING) | |
ae40fc49 | 312 | case BL_BRTG: |
de4eb79c JC |
313 | backlight_toggle_breathing(); |
314 | return false; | |
b624f32f | 315 | #endif |
1604f796 YFL |
316 | } |
317 | } | |
318 | ||
1604f796 YFL |
319 | // keycodes that depend on both pressed and non-pressed state |
320 | switch (keycode) { | |
b624f32f | 321 | case GRAVE_ESC: { |
2048df88 JC |
322 | /* true if the last press of GRAVE_ESC was shifted (i.e. GUI or SHIFT were pressed), false otherwise. |
323 | * Used to ensure that the correct keycode is released if the key is released. | |
324 | */ | |
325 | static bool grave_esc_was_shifted = false; | |
326 | ||
b624f32f | 327 | uint8_t shifted = get_mods() & ((MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT) | MOD_BIT(KC_LGUI) | MOD_BIT(KC_RGUI))); |
b4be711a | 328 | |
0b54e7f5 | 329 | #ifdef GRAVE_ESC_ALT_OVERRIDE |
b624f32f | 330 | // if ALT is pressed, ESC is always sent |
331 | // this is handy for the cmd+opt+esc shortcut on macOS, among other things. | |
332 | if (get_mods() & (MOD_BIT(KC_LALT) | MOD_BIT(KC_RALT))) { | |
333 | shifted = 0; | |
334 | } | |
0b54e7f5 | 335 | #endif |
336 | ||
897ceac2 | 337 | #ifdef GRAVE_ESC_CTRL_OVERRIDE |
b624f32f | 338 | // if CTRL is pressed, ESC is always sent |
339 | // this is handy for the ctrl+shift+esc shortcut on windows, among other things. | |
340 | if (get_mods() & (MOD_BIT(KC_LCTL) | MOD_BIT(KC_RCTL))) { | |
341 | shifted = 0; | |
342 | } | |
0b54e7f5 | 343 | #endif |
344 | ||
345 | #ifdef GRAVE_ESC_GUI_OVERRIDE | |
b624f32f | 346 | // if GUI is pressed, ESC is always sent |
347 | if (get_mods() & (MOD_BIT(KC_LGUI) | MOD_BIT(KC_RGUI))) { | |
348 | shifted = 0; | |
349 | } | |
0b54e7f5 | 350 | #endif |
351 | ||
352 | #ifdef GRAVE_ESC_SHIFT_OVERRIDE | |
b624f32f | 353 | // if SHIFT is pressed, ESC is always sent |
354 | if (get_mods() & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) { | |
355 | shifted = 0; | |
356 | } | |
357 | #endif | |
358 | ||
359 | if (record->event.pressed) { | |
360 | grave_esc_was_shifted = shifted; | |
361 | add_key(shifted ? KC_GRAVE : KC_ESCAPE); | |
362 | } else { | |
363 | del_key(grave_esc_was_shifted ? KC_GRAVE : KC_ESCAPE); | |
364 | } | |
365 | ||
366 | send_keyboard_report(); | |
367 | return false; | |
368 | } | |
b624f32f | 369 | } |
1a8c0dd2 | 370 | |
b624f32f | 371 | return process_action_kb(record); |
fdc2e805 SH |
372 | } |
373 | ||
b624f32f | 374 | __attribute__((weak)) const bool ascii_to_shift_lut[128] PROGMEM = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
375 | ||
376 | 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0}; | |
377 | ||
378 | __attribute__((weak)) const bool ascii_to_altgr_lut[128] PROGMEM = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
379 | ||
380 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | |
381 | ||
382 | __attribute__((weak)) const uint8_t ascii_to_keycode_lut[128] PROGMEM = {// NUL SOH STX ETX EOT ENQ ACK BEL | |
383 | XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, | |
384 | // BS TAB LF VT FF CR SO SI | |
385 | KC_BSPC, KC_TAB, KC_ENT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, | |
386 | // DLE DC1 DC2 DC3 DC4 NAK SYN ETB | |
387 | XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, | |
388 | // CAN EM SUB ESC FS GS RS US | |
389 | XXXXXXX, XXXXXXX, XXXXXXX, KC_ESC, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, | |
390 | ||
391 | // ! " # $ % & ' | |
392 | KC_SPC, KC_1, KC_QUOT, KC_3, KC_4, KC_5, KC_7, KC_QUOT, | |
393 | // ( ) * + , - . / | |
394 | KC_9, KC_0, KC_8, KC_EQL, KC_COMM, KC_MINS, KC_DOT, KC_SLSH, | |
395 | // 0 1 2 3 4 5 6 7 | |
396 | KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, | |
397 | // 8 9 : ; < = > ? | |
398 | KC_8, KC_9, KC_SCLN, KC_SCLN, KC_COMM, KC_EQL, KC_DOT, KC_SLSH, | |
399 | // @ A B C D E F G | |
400 | KC_2, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G, | |
401 | // H I J K L M N O | |
402 | KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O, | |
403 | // P Q R S T U V W | |
404 | KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W, | |
405 | // X Y Z [ \ ] ^ _ | |
406 | KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_6, KC_MINS, | |
407 | // ` a b c d e f g | |
408 | KC_GRV, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G, | |
409 | // h i j k l m n o | |
410 | KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O, | |
411 | // p q r s t u v w | |
412 | KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W, | |
413 | // x y z { | } ~ DEL | |
414 | KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL}; | |
415 | ||
416 | void send_string(const char *str) { send_string_with_delay(str, 0); } | |
417 | ||
418 | void send_string_P(const char *str) { send_string_with_delay_P(str, 0); } | |
7ad924ba | 419 | |
fdc2e805 | 420 | void send_string_with_delay(const char *str, uint8_t interval) { |
5dae013f | 421 | while (1) { |
7ad924ba | 422 | char ascii_code = *str; |
5dae013f | 423 | if (!ascii_code) break; |
d15bb05c | 424 | if (ascii_code == SS_TAP_CODE) { |
b624f32f | 425 | // tap |
426 | uint8_t keycode = *(++str); | |
427 | register_code(keycode); | |
428 | unregister_code(keycode); | |
d15bb05c | 429 | } else if (ascii_code == SS_DOWN_CODE) { |
b624f32f | 430 | // down |
431 | uint8_t keycode = *(++str); | |
432 | register_code(keycode); | |
d15bb05c | 433 | } else if (ascii_code == SS_UP_CODE) { |
b624f32f | 434 | // up |
435 | uint8_t keycode = *(++str); | |
436 | unregister_code(keycode); | |
7ad924ba | 437 | } else { |
b624f32f | 438 | send_char(ascii_code); |
5dae013f | 439 | } |
7ad924ba JH |
440 | ++str; |
441 | // interval | |
b624f32f | 442 | { |
443 | uint8_t ms = interval; | |
444 | while (ms--) wait_ms(1); | |
445 | } | |
7ad924ba JH |
446 | } |
447 | } | |
448 | ||
449 | void send_string_with_delay_P(const char *str, uint8_t interval) { | |
450 | while (1) { | |
451 | char ascii_code = pgm_read_byte(str); | |
452 | if (!ascii_code) break; | |
d15bb05c | 453 | if (ascii_code == SS_TAP_CODE) { |
b624f32f | 454 | // tap |
455 | uint8_t keycode = pgm_read_byte(++str); | |
456 | register_code(keycode); | |
457 | unregister_code(keycode); | |
d15bb05c | 458 | } else if (ascii_code == SS_DOWN_CODE) { |
b624f32f | 459 | // down |
460 | uint8_t keycode = pgm_read_byte(++str); | |
461 | register_code(keycode); | |
d15bb05c | 462 | } else if (ascii_code == SS_UP_CODE) { |
b624f32f | 463 | // up |
464 | uint8_t keycode = pgm_read_byte(++str); | |
465 | unregister_code(keycode); | |
7ad924ba | 466 | } else { |
b624f32f | 467 | send_char(ascii_code); |
5dae013f | 468 | } |
469 | ++str; | |
fdc2e805 | 470 | // interval |
b624f32f | 471 | { |
472 | uint8_t ms = interval; | |
473 | while (ms--) wait_ms(1); | |
474 | } | |
5dae013f | 475 | } |
476 | } | |
477 | ||
7ad924ba | 478 | void send_char(char ascii_code) { |
e5501d48 | 479 | #if defined(AUDIO_ENABLE) && defined(SENDSTRING_BELL) |
480 | if (ascii_code == '\a') { // BEL | |
481 | PLAY_SONG(bell_song); | |
482 | return; | |
483 | } | |
484 | #endif | |
485 | ||
b624f32f | 486 | uint8_t keycode = pgm_read_byte(&ascii_to_keycode_lut[(uint8_t)ascii_code]); |
487 | bool is_shifted = pgm_read_byte(&ascii_to_shift_lut[(uint8_t)ascii_code]); | |
488 | bool is_altgred = pgm_read_byte(&ascii_to_altgr_lut[(uint8_t)ascii_code]); | |
489 | ||
490 | if (is_shifted) { | |
491 | register_code(KC_LSFT); | |
492 | } | |
493 | if (is_altgred) { | |
494 | register_code(KC_RALT); | |
495 | } | |
496 | tap_code(keycode); | |
497 | if (is_altgred) { | |
498 | unregister_code(KC_RALT); | |
499 | } | |
500 | if (is_shifted) { | |
501 | unregister_code(KC_LSFT); | |
502 | } | |
7ad924ba JH |
503 | } |
504 | ||
6a3c6677 | 505 | void set_single_persistent_default_layer(uint8_t default_layer) { |
b624f32f | 506 | #if defined(AUDIO_ENABLE) && defined(DEFAULT_LAYER_SONGS) |
6a3c6677 | 507 | PLAY_SONG(default_layer_songs[default_layer]); |
b624f32f | 508 | #endif |
509 | eeconfig_update_default_layer(1U << default_layer); | |
510 | default_layer_set(1U << default_layer); | |
6a3c6677 JH |
511 | } |
512 | ||
b62e160a | 513 | layer_state_t update_tri_layer_state(layer_state_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3) { |
b624f32f | 514 | layer_state_t mask12 = (1UL << layer1) | (1UL << layer2); |
515 | layer_state_t mask3 = 1UL << layer3; | |
516 | return (state & mask12) == mask12 ? (state | mask3) : (state & ~mask3); | |
66e40529 MS |
517 | } |
518 | ||
b624f32f | 519 | void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) { layer_state_set(update_tri_layer_state(layer_state, layer1, layer2, layer3)); } |
1c9f33c0 | 520 | |
197f152d | 521 | void tap_random_base64(void) { |
b624f32f | 522 | #if defined(__AVR_ATmega32U4__) |
60fd885a | 523 | uint8_t key = (TCNT0 + TCNT1 + TCNT3 + TCNT4) % 64; |
b624f32f | 524 | #else |
60fd885a | 525 | uint8_t key = rand() % 64; |
b624f32f | 526 | #endif |
527 | switch (key) { | |
528 | case 0 ... 25: | |
529 | register_code(KC_LSFT); | |
530 | register_code(key + KC_A); | |
531 | unregister_code(key + KC_A); | |
532 | unregister_code(KC_LSFT); | |
533 | break; | |
534 | case 26 ... 51: | |
535 | register_code(key - 26 + KC_A); | |
536 | unregister_code(key - 26 + KC_A); | |
537 | break; | |
538 | case 52: | |
539 | register_code(KC_0); | |
540 | unregister_code(KC_0); | |
541 | break; | |
542 | case 53 ... 61: | |
543 | register_code(key - 53 + KC_1); | |
544 | unregister_code(key - 53 + KC_1); | |
545 | break; | |
546 | case 62: | |
547 | register_code(KC_LSFT); | |
548 | register_code(KC_EQL); | |
549 | unregister_code(KC_EQL); | |
550 | unregister_code(KC_LSFT); | |
551 | break; | |
552 | case 63: | |
553 | register_code(KC_SLSH); | |
554 | unregister_code(KC_SLSH); | |
555 | break; | |
556 | } | |
197f152d JH |
557 | } |
558 | ||
b624f32f | 559 | __attribute__((weak)) void bootmagic_lite(void) { |
560 | // The lite version of TMK's bootmagic based on Wilba. | |
561 | // 100% less potential for accidentally making the | |
562 | // keyboard do stupid things. | |
4ffcacd9 | 563 | |
b624f32f | 564 | // We need multiple scans because debouncing can't be turned off. |
565 | matrix_scan(); | |
320822d7 | 566 | #if defined(DEBOUNCE) && DEBOUNCE > 0 |
4ffcacd9 | 567 | wait_ms(DEBOUNCE * 2); |
b624f32f | 568 | #else |
4ffcacd9 | 569 | wait_ms(30); |
b624f32f | 570 | #endif |
571 | matrix_scan(); | |
572 | ||
573 | // If the Esc and space bar are held down on power up, | |
574 | // reset the EEPROM valid state and jump to bootloader. | |
575 | // Assumes Esc is at [0,0]. | |
576 | // This isn't very generalized, but we need something that doesn't | |
577 | // rely on user's keymaps in firmware or EEPROM. | |
578 | if (matrix_get_row(BOOTMAGIC_LITE_ROW) & (1 << BOOTMAGIC_LITE_COLUMN)) { | |
579 | eeconfig_disable(); | |
580 | // Jump to bootloader. | |
581 | bootloader_jump(); | |
582 | } | |
4ffcacd9 DJ |
583 | } |
584 | ||
1a8c0dd2 | 585 | void matrix_init_quantum() { |
b624f32f | 586 | #ifdef BOOTMAGIC_LITE |
4ffcacd9 | 587 | bootmagic_lite(); |
b624f32f | 588 | #endif |
589 | if (!eeconfig_is_enabled()) { | |
590 | eeconfig_init(); | |
591 | } | |
592 | #ifdef BACKLIGHT_ENABLE | |
593 | # ifdef LED_MATRIX_ENABLE | |
594 | led_matrix_init(); | |
595 | # else | |
596 | backlight_init_ports(); | |
597 | # endif | |
598 | #endif | |
599 | #ifdef AUDIO_ENABLE | |
6a3c6677 | 600 | audio_init(); |
b624f32f | 601 | #endif |
602 | #ifdef RGB_MATRIX_ENABLE | |
bad56a4f | 603 | rgb_matrix_init(); |
b624f32f | 604 | #endif |
605 | #ifdef ENCODER_ENABLE | |
85688e5b | 606 | encoder_init(); |
b624f32f | 607 | #endif |
608 | #if defined(UNICODE_ENABLE) || defined(UNICODEMAP_ENABLE) || defined(UCIS_ENABLE) | |
fdeec296 | 609 | unicode_input_mode_init(); |
b624f32f | 610 | #endif |
611 | #ifdef HAPTIC_ENABLE | |
2cee371b | 612 | haptic_init(); |
b624f32f | 613 | #endif |
614 | #ifdef OUTPUT_AUTO_ENABLE | |
b60413af | 615 | set_output(OUTPUT_AUTO); |
b624f32f | 616 | #endif |
dab4967f DJ |
617 | #ifdef DIP_SWITCH_ENABLE |
618 | dip_switch_init(); | |
619 | #endif | |
620 | ||
b624f32f | 621 | matrix_init_kb(); |
1a8c0dd2 EZ |
622 | } |
623 | ||
624 | void matrix_scan_quantum() { | |
b624f32f | 625 | #if defined(AUDIO_ENABLE) && !defined(NO_MUSIC_MODE) |
65faab3b | 626 | matrix_scan_music(); |
b624f32f | 627 | #endif |
fde477a9 | 628 | |
b624f32f | 629 | #ifdef TAP_DANCE_ENABLE |
65faab3b | 630 | matrix_scan_tap_dance(); |
b624f32f | 631 | #endif |
b6bf4e0d | 632 | |
b624f32f | 633 | #ifdef COMBO_ENABLE |
b6bf4e0d | 634 | matrix_scan_combo(); |
b624f32f | 635 | #endif |
b6bf4e0d | 636 | |
b624f32f | 637 | #if defined(BACKLIGHT_ENABLE) |
638 | # if defined(LED_MATRIX_ENABLE) | |
639 | led_matrix_task(); | |
4531cc87 | 640 | # elif defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS) |
b624f32f | 641 | backlight_task(); |
642 | # endif | |
643 | #endif | |
8d0fdf10 | 644 | |
b624f32f | 645 | #ifdef RGB_MATRIX_ENABLE |
14b7602a | 646 | rgb_matrix_task(); |
b624f32f | 647 | #endif |
14b7602a | 648 | |
b624f32f | 649 | #ifdef ENCODER_ENABLE |
85688e5b | 650 | encoder_read(); |
b624f32f | 651 | #endif |
85688e5b | 652 | |
b624f32f | 653 | #ifdef HAPTIC_ENABLE |
2cee371b | 654 | haptic_task(); |
b624f32f | 655 | #endif |
2cee371b | 656 | |
dab4967f DJ |
657 | #ifdef DIP_SWITCH_ENABLE |
658 | dip_switch_read(false); | |
659 | #endif | |
660 | ||
b624f32f | 661 | matrix_scan_kb(); |
0428214b | 662 | } |
13bb6b4b | 663 | |
bbea9dad | 664 | #ifdef HD44780_ENABLED |
b624f32f | 665 | # include "hd44780.h" |
bbea9dad MA |
666 | #endif |
667 | ||
664c0a03 JH |
668 | // Functions for spitting out values |
669 | // | |
670 | ||
b624f32f | 671 | void send_dword(uint32_t number) { // this might not actually work |
664c0a03 JH |
672 | uint16_t word = (number >> 16); |
673 | send_word(word); | |
674 | send_word(number & 0xFFFFUL); | |
675 | } | |
676 | ||
677 | void send_word(uint16_t number) { | |
678 | uint8_t byte = number >> 8; | |
679 | send_byte(byte); | |
680 | send_byte(number & 0xFF); | |
681 | } | |
682 | ||
683 | void send_byte(uint8_t number) { | |
684 | uint8_t nibble = number >> 4; | |
685 | send_nibble(nibble); | |
686 | send_nibble(number & 0xF); | |
687 | } | |
688 | ||
689 | void send_nibble(uint8_t number) { | |
690 | switch (number) { | |
691 | case 0: | |
692 | register_code(KC_0); | |
693 | unregister_code(KC_0); | |
694 | break; | |
695 | case 1 ... 9: | |
696 | register_code(KC_1 + (number - 1)); | |
697 | unregister_code(KC_1 + (number - 1)); | |
698 | break; | |
699 | case 0xA ... 0xF: | |
700 | register_code(KC_A + (number - 0xA)); | |
701 | unregister_code(KC_A + (number - 0xA)); | |
702 | break; | |
703 | } | |
704 | } | |
705 | ||
b624f32f | 706 | __attribute__((weak)) uint16_t hex_to_keycode(uint8_t hex) { |
707 | hex = hex & 0xF; | |
708 | if (hex == 0x0) { | |
709 | return KC_0; | |
710 | } else if (hex < 0xA) { | |
711 | return KC_1 + (hex - 0x1); | |
712 | } else { | |
713 | return KC_A + (hex - 0xA); | |
714 | } | |
cbabb4d4 JH |
715 | } |
716 | ||
7edac212 JH |
717 | void api_send_unicode(uint32_t unicode) { |
718 | #ifdef API_ENABLE | |
cefa8468 JH |
719 | uint8_t chunk[4]; |
720 | dword_to_bytes(unicode, chunk); | |
721 | MT_SEND_DATA(DT_UNICODE, chunk, 5); | |
7edac212 | 722 | #endif |
cefa8468 | 723 | } |
13bb6b4b | 724 | |
dfb78d2a | 725 | /** \brief Lock LED set callback - keymap/user level |
726 | * | |
727 | * \deprecated Use led_update_user() instead. | |
728 | */ | |
b624f32f | 729 | __attribute__((weak)) void led_set_user(uint8_t usb_led) {} |
13bb6b4b | 730 | |
dfb78d2a | 731 | /** \brief Lock LED set callback - keyboard level |
732 | * | |
733 | * \deprecated Use led_update_kb() instead. | |
734 | */ | |
b624f32f | 735 | __attribute__((weak)) void led_set_kb(uint8_t usb_led) { led_set_user(usb_led); } |
13bb6b4b | 736 | |
dfb78d2a | 737 | /** \brief Lock LED update callback - keymap/user level |
738 | * | |
739 | * \return True if led_update_kb() should run its own code, false otherwise. | |
740 | */ | |
741 | __attribute__((weak)) bool led_update_user(led_t led_state) { return true; } | |
742 | ||
743 | /** \brief Lock LED update callback - keyboard level | |
744 | * | |
745 | * \return Ignored for now. | |
746 | */ | |
747 | __attribute__((weak)) bool led_update_kb(led_t led_state) { return led_update_user(led_state); } | |
748 | ||
b624f32f | 749 | __attribute__((weak)) void led_init_ports(void) {} |
13bb6b4b | 750 | |
b624f32f | 751 | __attribute__((weak)) void led_set(uint8_t usb_led) { |
df251d7a | 752 | #if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE) |
b624f32f | 753 | // Use backlight as Caps Lock indicator |
754 | uint8_t bl_toggle_lvl = 0; | |
755 | ||
756 | if (IS_LED_ON(usb_led, USB_LED_CAPS_LOCK) && !backlight_config.enable) { | |
757 | // Turning Caps Lock ON and backlight is disabled in config | |
758 | // Toggling backlight to the brightest level | |
759 | bl_toggle_lvl = BACKLIGHT_LEVELS; | |
760 | } else if (IS_LED_OFF(usb_led, USB_LED_CAPS_LOCK) && backlight_config.enable) { | |
761 | // Turning Caps Lock OFF and backlight is enabled in config | |
762 | // Toggling backlight and restoring config level | |
763 | bl_toggle_lvl = backlight_config.level; | |
764 | } | |
df251d7a | 765 | |
b624f32f | 766 | // Set level without modify backlight_config to keep ability to restore state |
767 | backlight_set(bl_toggle_lvl); | |
df251d7a R |
768 | #endif |
769 | ||
b624f32f | 770 | led_set_kb(usb_led); |
a91c0c47 | 771 | led_update_kb((led_t)usb_led); |
13bb6b4b JH |
772 | } |
773 | ||
287eb7ad | 774 | //------------------------------------------------------------------------------ |
794aed37 | 775 | // Override these functions in your keymap file to play different tunes on |
287eb7ad JH |
776 | // different events such as startup and bootloader jump |
777 | ||
b624f32f | 778 | __attribute__((weak)) void startup_user() {} |
287eb7ad | 779 | |
b624f32f | 780 | __attribute__((weak)) void shutdown_user() {} |
287eb7ad | 781 | |
12370259 | 782 | //------------------------------------------------------------------------------ |