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