1 /* Copyright 2016-2017 Jack Humbert
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.
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.
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/>.
19 #if !defined(RGBLIGHT_ENABLE) && !defined(RGB_MATRIX_ENABLE)
24 #include "outputselect.h"
27 #ifndef BREATHING_PERIOD
28 #define BREATHING_PERIOD 6
31 #include "backlight.h"
32 extern backlight_config_t backlight_config;
34 #ifdef FAUXCLICKY_ENABLE
35 #include "fauxclicky.h"
43 #include "process_midi.h"
46 #ifdef VELOCIKEY_ENABLE
47 #include "velocikey.h"
60 #define GOODBYE_SONG SONG(GOODBYE_SOUND)
63 #define AG_NORM_SONG SONG(AG_NORM_SOUND)
66 #define AG_SWAP_SONG SONG(AG_SWAP_SOUND)
68 float goodbye_song[][2] = GOODBYE_SONG;
69 float ag_norm_song[][2] = AG_NORM_SONG;
70 float ag_swap_song[][2] = AG_SWAP_SONG;
71 #ifdef DEFAULT_LAYER_SONGS
72 float default_layer_songs[][16][2] = DEFAULT_LAYER_SONGS;
76 static void do_code16 (uint16_t code, void (*f) (uint8_t)) {
78 case QK_MODS ... QK_MODS_MAX:
93 if (code < QK_RMODS_MIN) return;
105 static inline void qk_register_weak_mods(uint8_t kc) {
106 add_weak_mods(MOD_BIT(kc));
107 send_keyboard_report();
110 static inline void qk_unregister_weak_mods(uint8_t kc) {
111 del_weak_mods(MOD_BIT(kc));
112 send_keyboard_report();
115 static inline void qk_register_mods(uint8_t kc) {
116 add_weak_mods(MOD_BIT(kc));
117 send_keyboard_report();
120 static inline void qk_unregister_mods(uint8_t kc) {
121 del_weak_mods(MOD_BIT(kc));
122 send_keyboard_report();
125 void register_code16 (uint16_t code) {
126 if (IS_MOD(code) || code == KC_NO) {
127 do_code16 (code, qk_register_mods);
129 do_code16 (code, qk_register_weak_mods);
131 register_code (code);
134 void unregister_code16 (uint16_t code) {
135 unregister_code (code);
136 if (IS_MOD(code) || code == KC_NO) {
137 do_code16 (code, qk_unregister_mods);
139 do_code16 (code, qk_unregister_weak_mods);
143 void tap_code16(uint16_t code) {
144 register_code16(code);
145 #if TAP_CODE_DELAY > 0
146 wait_ms(TAP_CODE_DELAY);
148 unregister_code16(code);
151 __attribute__ ((weak))
152 bool process_action_kb(keyrecord_t *record) {
156 __attribute__ ((weak))
157 bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
158 return process_record_user(keycode, record);
161 __attribute__ ((weak))
162 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
166 void reset_keyboard(void) {
168 #if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
169 process_midi_all_notes_off();
172 #ifndef NO_MUSIC_MODE
173 music_all_notes_off();
175 uint16_t timer_start = timer_read();
176 PLAY_SONG(goodbye_song);
178 while(timer_elapsed(timer_start) < 250)
188 // this is also done later in bootloader.c - not sure if it's neccesary here
189 #ifdef BOOTLOADER_CATERINA
190 *(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific
195 /* true if the last press of GRAVE_ESC was shifted (i.e. GUI or SHIFT were pressed), false otherwise.
196 * Used to ensure that the correct keycode is released if the key is released.
198 static bool grave_esc_was_shifted = false;
200 /* Convert record into usable keycode via the contained event. */
201 uint16_t get_record_keycode(keyrecord_t *record) {
202 return get_event_keycode(record->event);
206 /* Convert event into usable keycode. Checks the layer cache to ensure that it
207 * retains the correct keycode after a layer change, if the key is still pressed.
209 uint16_t get_event_keycode(keyevent_t event) {
211 #if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
212 /* TODO: Use store_or_get_action() or a similar function. */
213 if (!disable_action_cache) {
217 layer = layer_switch_get_layer(event.key);
218 update_source_layers_cache(event.key, layer);
220 layer = read_source_layers_cache(event.key);
222 return keymap_key_to_keycode(layer, event.key);
225 return keymap_key_to_keycode(layer_switch_get_layer(event.key), event.key);
228 /* Main keycode processing function. Hands off handling to other functions,
229 * then processes internal Quantum keycodes, then processes ACTIONs.
231 bool process_record_quantum(keyrecord_t *record) {
232 uint16_t keycode = get_record_keycode(record);
234 // This is how you use actions here
235 // if (keycode == KC_LEAD) {
237 // action.code = ACTION_DEFAULT_LAYER_SET(0);
238 // process_action(record, action);
242 #ifdef VELOCIKEY_ENABLE
243 if (velocikey_enabled() && record->event.pressed) { velocikey_accelerate(); }
246 #ifdef TAP_DANCE_ENABLE
247 preprocess_tap_dance(keycode, record);
251 #if defined(KEY_LOCK_ENABLE)
252 // Must run first to be able to mask key_up events.
253 process_key_lock(&keycode, record) &&
255 #if defined(AUDIO_ENABLE) && defined(AUDIO_CLICKY)
256 process_clicky(keycode, record) &&
257 #endif //AUDIO_CLICKY
259 process_haptic(keycode, record) &&
260 #endif //HAPTIC_ENABLE
261 #if defined(RGB_MATRIX_ENABLE)
262 process_rgb_matrix(keycode, record) &&
264 process_record_kb(keycode, record) &&
265 #if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED)
266 process_midi(keycode, record) &&
269 process_audio(keycode, record) &&
272 process_steno(keycode, record) &&
274 #if (defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))) && !defined(NO_MUSIC_MODE)
275 process_music(keycode, record) &&
277 #ifdef TAP_DANCE_ENABLE
278 process_tap_dance(keycode, record) &&
280 #if defined(UNICODE_ENABLE) || defined(UNICODEMAP_ENABLE) || defined(UCIS_ENABLE)
281 process_unicode_common(keycode, record) &&
284 process_leader(keycode, record) &&
287 process_combo(keycode, record) &&
289 #ifdef PRINTING_ENABLE
290 process_printer(keycode, record) &&
292 #ifdef AUTO_SHIFT_ENABLE
293 process_auto_shift(keycode, record) &&
295 #ifdef TERMINAL_ENABLE
296 process_terminal(keycode, record) &&
298 #ifdef SPACE_CADET_ENABLE
299 process_space_cadet(keycode, record) &&
305 // Shift / paren setup
309 if (record->event.pressed) {
314 if (record->event.pressed) {
317 print("DEBUG: enabled.\n");
319 print("DEBUG: disabled.\n");
324 if (record->event.pressed) {
328 #ifdef FAUXCLICKY_ENABLE
330 if (record->event.pressed) {
335 if (record->event.pressed) {
340 if (record->event.pressed) {
345 #if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
347 // Split keyboards need to trigger on key-up for edge-case issue
348 #ifndef SPLIT_KEYBOARD
349 if (record->event.pressed) {
351 if (!record->event.pressed) {
356 case RGB_MODE_FORWARD:
357 if (record->event.pressed) {
358 uint8_t shifted = get_mods() & (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT));
360 rgblight_step_reverse();
367 case RGB_MODE_REVERSE:
368 if (record->event.pressed) {
369 uint8_t shifted = get_mods() & (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT));
374 rgblight_step_reverse();
379 // Split keyboards need to trigger on key-up for edge-case issue
380 #ifndef SPLIT_KEYBOARD
381 if (record->event.pressed) {
383 if (!record->event.pressed) {
385 rgblight_increase_hue();
389 // Split keyboards need to trigger on key-up for edge-case issue
390 #ifndef SPLIT_KEYBOARD
391 if (record->event.pressed) {
393 if (!record->event.pressed) {
395 rgblight_decrease_hue();
399 // Split keyboards need to trigger on key-up for edge-case issue
400 #ifndef SPLIT_KEYBOARD
401 if (record->event.pressed) {
403 if (!record->event.pressed) {
405 rgblight_increase_sat();
409 // Split keyboards need to trigger on key-up for edge-case issue
410 #ifndef SPLIT_KEYBOARD
411 if (record->event.pressed) {
413 if (!record->event.pressed) {
415 rgblight_decrease_sat();
419 // Split keyboards need to trigger on key-up for edge-case issue
420 #ifndef SPLIT_KEYBOARD
421 if (record->event.pressed) {
423 if (!record->event.pressed) {
425 rgblight_increase_val();
429 // Split keyboards need to trigger on key-up for edge-case issue
430 #ifndef SPLIT_KEYBOARD
431 if (record->event.pressed) {
433 if (!record->event.pressed) {
435 rgblight_decrease_val();
439 if (record->event.pressed) {
440 rgblight_increase_speed();
444 if (record->event.pressed) {
445 rgblight_decrease_speed();
449 if (record->event.pressed) {
450 rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
453 case RGB_MODE_BREATHE:
454 #ifdef RGBLIGHT_EFFECT_BREATHING
455 if (record->event.pressed) {
456 if ((RGBLIGHT_MODE_BREATHING <= rgblight_get_mode()) &&
457 (rgblight_get_mode() < RGBLIGHT_MODE_BREATHING_end)) {
460 rgblight_mode(RGBLIGHT_MODE_BREATHING);
465 case RGB_MODE_RAINBOW:
466 #ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
467 if (record->event.pressed) {
468 if ((RGBLIGHT_MODE_RAINBOW_MOOD <= rgblight_get_mode()) &&
469 (rgblight_get_mode() < RGBLIGHT_MODE_RAINBOW_MOOD_end)) {
472 rgblight_mode(RGBLIGHT_MODE_RAINBOW_MOOD);
478 #ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
479 if (record->event.pressed) {
480 if ((RGBLIGHT_MODE_RAINBOW_SWIRL <= rgblight_get_mode()) &&
481 (rgblight_get_mode() < RGBLIGHT_MODE_RAINBOW_SWIRL_end)) {
484 rgblight_mode(RGBLIGHT_MODE_RAINBOW_SWIRL);
490 #ifdef RGBLIGHT_EFFECT_SNAKE
491 if (record->event.pressed) {
492 if ((RGBLIGHT_MODE_SNAKE <= rgblight_get_mode()) &&
493 (rgblight_get_mode() < RGBLIGHT_MODE_SNAKE_end)) {
496 rgblight_mode(RGBLIGHT_MODE_SNAKE);
501 case RGB_MODE_KNIGHT:
502 #ifdef RGBLIGHT_EFFECT_KNIGHT
503 if (record->event.pressed) {
504 if ((RGBLIGHT_MODE_KNIGHT <= rgblight_get_mode()) &&
505 (rgblight_get_mode() < RGBLIGHT_MODE_KNIGHT_end)) {
508 rgblight_mode(RGBLIGHT_MODE_KNIGHT);
514 #ifdef RGBLIGHT_EFFECT_CHRISTMAS
515 if (record->event.pressed) {
516 rgblight_mode(RGBLIGHT_MODE_CHRISTMAS);
520 case RGB_MODE_GRADIENT:
521 #ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
522 if (record->event.pressed) {
523 if ((RGBLIGHT_MODE_STATIC_GRADIENT <= rgblight_get_mode()) &&
524 (rgblight_get_mode() < RGBLIGHT_MODE_STATIC_GRADIENT_end)) {
527 rgblight_mode(RGBLIGHT_MODE_STATIC_GRADIENT);
532 case RGB_MODE_RGBTEST:
533 #ifdef RGBLIGHT_EFFECT_RGB_TEST
534 if (record->event.pressed) {
535 rgblight_mode(RGBLIGHT_MODE_RGB_TEST);
539 #endif // defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
540 #ifdef VELOCIKEY_ENABLE
542 if (record->event.pressed) {
549 if (record->event.pressed) {
550 set_output(OUTPUT_AUTO);
554 if (record->event.pressed) {
555 set_output(OUTPUT_USB);
558 #ifdef BLUETOOTH_ENABLE
560 if (record->event.pressed) {
561 set_output(OUTPUT_BLUETOOTH);
566 case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_NKRO:
567 if (record->event.pressed) {
568 // MAGIC actions (BOOTMAGIC without the boot)
569 if (!eeconfig_is_enabled()) {
573 keymap_config.raw = eeconfig_read_keymap();
576 case MAGIC_SWAP_CONTROL_CAPSLOCK:
577 keymap_config.swap_control_capslock = true;
579 case MAGIC_CAPSLOCK_TO_CONTROL:
580 keymap_config.capslock_to_control = true;
582 case MAGIC_SWAP_LALT_LGUI:
583 keymap_config.swap_lalt_lgui = true;
585 case MAGIC_SWAP_RALT_RGUI:
586 keymap_config.swap_ralt_rgui = true;
589 keymap_config.no_gui = true;
591 case MAGIC_SWAP_GRAVE_ESC:
592 keymap_config.swap_grave_esc = true;
594 case MAGIC_SWAP_BACKSLASH_BACKSPACE:
595 keymap_config.swap_backslash_backspace = true;
597 case MAGIC_HOST_NKRO:
598 keymap_config.nkro = true;
600 case MAGIC_SWAP_ALT_GUI:
601 keymap_config.swap_lalt_lgui = true;
602 keymap_config.swap_ralt_rgui = true;
604 PLAY_SONG(ag_swap_song);
607 case MAGIC_UNSWAP_CONTROL_CAPSLOCK:
608 keymap_config.swap_control_capslock = false;
610 case MAGIC_UNCAPSLOCK_TO_CONTROL:
611 keymap_config.capslock_to_control = false;
613 case MAGIC_UNSWAP_LALT_LGUI:
614 keymap_config.swap_lalt_lgui = false;
616 case MAGIC_UNSWAP_RALT_RGUI:
617 keymap_config.swap_ralt_rgui = false;
620 keymap_config.no_gui = false;
622 case MAGIC_UNSWAP_GRAVE_ESC:
623 keymap_config.swap_grave_esc = false;
625 case MAGIC_UNSWAP_BACKSLASH_BACKSPACE:
626 keymap_config.swap_backslash_backspace = false;
628 case MAGIC_UNHOST_NKRO:
629 keymap_config.nkro = false;
631 case MAGIC_UNSWAP_ALT_GUI:
632 keymap_config.swap_lalt_lgui = false;
633 keymap_config.swap_ralt_rgui = false;
635 PLAY_SONG(ag_norm_song);
638 case MAGIC_TOGGLE_ALT_GUI:
639 keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui;
640 keymap_config.swap_ralt_rgui = !keymap_config.swap_ralt_rgui;
642 if (keymap_config.swap_ralt_rgui) {
643 PLAY_SONG(ag_swap_song);
645 PLAY_SONG(ag_norm_song);
649 case MAGIC_TOGGLE_NKRO:
650 keymap_config.nkro = !keymap_config.nkro;
655 eeconfig_update_keymap(keymap_config.raw);
656 clear_keyboard(); // clear to prevent stuck keys
663 uint8_t shifted = get_mods() & ((MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT)
664 |MOD_BIT(KC_LGUI)|MOD_BIT(KC_RGUI)));
666 #ifdef GRAVE_ESC_ALT_OVERRIDE
667 // if ALT is pressed, ESC is always sent
668 // this is handy for the cmd+opt+esc shortcut on macOS, among other things.
669 if (get_mods() & (MOD_BIT(KC_LALT) | MOD_BIT(KC_RALT))) {
674 #ifdef GRAVE_ESC_CTRL_OVERRIDE
675 // if CTRL is pressed, ESC is always sent
676 // this is handy for the ctrl+shift+esc shortcut on windows, among other things.
677 if (get_mods() & (MOD_BIT(KC_LCTL) | MOD_BIT(KC_RCTL))) {
682 #ifdef GRAVE_ESC_GUI_OVERRIDE
683 // if GUI is pressed, ESC is always sent
684 if (get_mods() & (MOD_BIT(KC_LGUI) | MOD_BIT(KC_RGUI))) {
689 #ifdef GRAVE_ESC_SHIFT_OVERRIDE
690 // if SHIFT is pressed, ESC is always sent
691 if (get_mods() & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) {
696 if (record->event.pressed) {
697 grave_esc_was_shifted = shifted;
698 add_key(shifted ? KC_GRAVE : KC_ESCAPE);
701 del_key(grave_esc_was_shifted ? KC_GRAVE : KC_ESCAPE);
704 send_keyboard_report();
708 #if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_BREATHING)
710 if (record->event.pressed) {
718 return process_action_kb(record);
721 __attribute__ ((weak))
722 const bool ascii_to_shift_lut[128] PROGMEM = {
723 0, 0, 0, 0, 0, 0, 0, 0,
724 0, 0, 0, 0, 0, 0, 0, 0,
725 0, 0, 0, 0, 0, 0, 0, 0,
726 0, 0, 0, 0, 0, 0, 0, 0,
728 0, 1, 1, 1, 1, 1, 1, 0,
729 1, 1, 1, 1, 0, 0, 0, 0,
730 0, 0, 0, 0, 0, 0, 0, 0,
731 0, 0, 1, 0, 1, 0, 1, 1,
732 1, 1, 1, 1, 1, 1, 1, 1,
733 1, 1, 1, 1, 1, 1, 1, 1,
734 1, 1, 1, 1, 1, 1, 1, 1,
735 1, 1, 1, 0, 0, 0, 1, 1,
736 0, 0, 0, 0, 0, 0, 0, 0,
737 0, 0, 0, 0, 0, 0, 0, 0,
738 0, 0, 0, 0, 0, 0, 0, 0,
739 0, 0, 0, 1, 1, 1, 1, 0
742 __attribute__ ((weak))
743 const bool ascii_to_altgr_lut[128] PROGMEM = {
744 0, 0, 0, 0, 0, 0, 0, 0,
745 0, 0, 0, 0, 0, 0, 0, 0,
746 0, 0, 0, 0, 0, 0, 0, 0,
747 0, 0, 0, 0, 0, 0, 0, 0,
749 0, 0, 0, 0, 0, 0, 0, 0,
750 0, 0, 0, 0, 0, 0, 0, 0,
751 0, 0, 0, 0, 0, 0, 0, 0,
752 0, 0, 0, 0, 0, 0, 0, 0,
753 0, 0, 0, 0, 0, 0, 0, 0,
754 0, 0, 0, 0, 0, 0, 0, 0,
755 0, 0, 0, 0, 0, 0, 0, 0,
756 0, 0, 0, 0, 0, 0, 0, 0,
757 0, 0, 0, 0, 0, 0, 0, 0,
758 0, 0, 0, 0, 0, 0, 0, 0,
759 0, 0, 0, 0, 0, 0, 0, 0,
760 0, 0, 0, 0, 0, 0, 0, 0
763 __attribute__ ((weak))
764 const uint8_t ascii_to_keycode_lut[128] PROGMEM = {
765 // NUL SOH STX ETX EOT ENQ ACK BEL
766 XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
767 // BS TAB LF VT FF CR SO SI
768 KC_BSPC, KC_TAB, KC_ENT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
769 // DLE DC1 DC2 DC3 DC4 NAK SYN ETB
770 XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
771 // CAN EM SUB ESC FS GS RS US
772 XXXXXXX, XXXXXXX, XXXXXXX, KC_ESC, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,
775 KC_SPC, KC_1, KC_QUOT, KC_3, KC_4, KC_5, KC_7, KC_QUOT,
777 KC_9, KC_0, KC_8, KC_EQL, KC_COMM, KC_MINS, KC_DOT, KC_SLSH,
779 KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7,
781 KC_8, KC_9, KC_SCLN, KC_SCLN, KC_COMM, KC_EQL, KC_DOT, KC_SLSH,
783 KC_2, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
785 KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O,
787 KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
789 KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_6, KC_MINS,
791 KC_GRV, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
793 KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O,
795 KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
797 KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL
800 void send_string(const char *str) {
801 send_string_with_delay(str, 0);
804 void send_string_P(const char *str) {
805 send_string_with_delay_P(str, 0);
808 void send_string_with_delay(const char *str, uint8_t interval) {
810 char ascii_code = *str;
811 if (!ascii_code) break;
812 if (ascii_code == SS_TAP_CODE) {
814 uint8_t keycode = *(++str);
815 register_code(keycode);
816 unregister_code(keycode);
817 } else if (ascii_code == SS_DOWN_CODE) {
819 uint8_t keycode = *(++str);
820 register_code(keycode);
821 } else if (ascii_code == SS_UP_CODE) {
823 uint8_t keycode = *(++str);
824 unregister_code(keycode);
826 send_char(ascii_code);
830 { uint8_t ms = interval; while (ms--) wait_ms(1); }
834 void send_string_with_delay_P(const char *str, uint8_t interval) {
836 char ascii_code = pgm_read_byte(str);
837 if (!ascii_code) break;
838 if (ascii_code == SS_TAP_CODE) {
840 uint8_t keycode = pgm_read_byte(++str);
841 register_code(keycode);
842 unregister_code(keycode);
843 } else if (ascii_code == SS_DOWN_CODE) {
845 uint8_t keycode = pgm_read_byte(++str);
846 register_code(keycode);
847 } else if (ascii_code == SS_UP_CODE) {
849 uint8_t keycode = pgm_read_byte(++str);
850 unregister_code(keycode);
852 send_char(ascii_code);
856 { uint8_t ms = interval; while (ms--) wait_ms(1); }
860 void send_char(char ascii_code) {
861 uint8_t keycode = pgm_read_byte(&ascii_to_keycode_lut[(uint8_t)ascii_code]);
862 bool is_shifted = pgm_read_byte(&ascii_to_shift_lut[(uint8_t)ascii_code]);
863 bool is_altgred = pgm_read_byte(&ascii_to_altgr_lut[(uint8_t)ascii_code]);
866 register_code(KC_LSFT);
869 register_code(KC_RALT);
873 unregister_code(KC_RALT);
876 unregister_code(KC_LSFT);
880 void set_single_persistent_default_layer(uint8_t default_layer) {
881 #if defined(AUDIO_ENABLE) && defined(DEFAULT_LAYER_SONGS)
882 PLAY_SONG(default_layer_songs[default_layer]);
884 eeconfig_update_default_layer(1U<<default_layer);
885 default_layer_set(1U<<default_layer);
888 uint32_t update_tri_layer_state(uint32_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3) {
889 uint32_t mask12 = (1UL << layer1) | (1UL << layer2);
890 uint32_t mask3 = 1UL << layer3;
891 return (state & mask12) == mask12 ? (state | mask3) : (state & ~mask3);
894 void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) {
895 layer_state_set(update_tri_layer_state(layer_state, layer1, layer2, layer3));
898 void tap_random_base64(void) {
899 #if defined(__AVR_ATmega32U4__)
900 uint8_t key = (TCNT0 + TCNT1 + TCNT3 + TCNT4) % 64;
902 uint8_t key = rand() % 64;
906 register_code(KC_LSFT);
907 register_code(key + KC_A);
908 unregister_code(key + KC_A);
909 unregister_code(KC_LSFT);
912 register_code(key - 26 + KC_A);
913 unregister_code(key - 26 + KC_A);
917 unregister_code(KC_0);
920 register_code(key - 53 + KC_1);
921 unregister_code(key - 53 + KC_1);
924 register_code(KC_LSFT);
925 register_code(KC_EQL);
926 unregister_code(KC_EQL);
927 unregister_code(KC_LSFT);
930 register_code(KC_SLSH);
931 unregister_code(KC_SLSH);
936 __attribute__((weak))
937 void bootmagic_lite(void) {
938 // The lite version of TMK's bootmagic based on Wilba.
939 // 100% less potential for accidentally making the
940 // keyboard do stupid things.
942 // We need multiple scans because debouncing can't be turned off.
944 #if defined(DEBOUNCING_DELAY) && DEBOUNCING_DELAY > 0
945 wait_ms(DEBOUNCING_DELAY * 2);
946 #elif defined(DEBOUNCE) && DEBOUNCE > 0
947 wait_ms(DEBOUNCE * 2);
953 // If the Esc and space bar are held down on power up,
954 // reset the EEPROM valid state and jump to bootloader.
955 // Assumes Esc is at [0,0].
956 // This isn't very generalized, but we need something that doesn't
957 // rely on user's keymaps in firmware or EEPROM.
958 if (matrix_get_row(BOOTMAGIC_LITE_ROW) & (1 << BOOTMAGIC_LITE_COLUMN)) {
960 // Jump to bootloader.
965 void matrix_init_quantum() {
966 #ifdef BOOTMAGIC_LITE
969 if (!eeconfig_is_enabled()) {
972 #ifdef BACKLIGHT_ENABLE
973 #ifdef LED_MATRIX_ENABLE
976 backlight_init_ports();
982 #ifdef RGB_MATRIX_ENABLE
985 #ifdef ENCODER_ENABLE
988 #if defined(UNICODE_ENABLE) || defined(UNICODEMAP_ENABLE) || defined(UCIS_ENABLE)
989 unicode_input_mode_init();
994 #ifdef OUTPUT_AUTO_ENABLE
995 set_output(OUTPUT_AUTO);
1000 void matrix_scan_quantum() {
1001 #if defined(AUDIO_ENABLE) && !defined(NO_MUSIC_MODE)
1002 matrix_scan_music();
1005 #ifdef TAP_DANCE_ENABLE
1006 matrix_scan_tap_dance();
1010 matrix_scan_combo();
1013 #if defined(BACKLIGHT_ENABLE)
1014 #if defined(LED_MATRIX_ENABLE)
1016 #elif defined(BACKLIGHT_PIN)
1021 #ifdef RGB_MATRIX_ENABLE
1025 #ifdef ENCODER_ENABLE
1029 #ifdef HAPTIC_ENABLE
1035 #if defined(BACKLIGHT_ENABLE) && (defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS))
1037 // The logic is a bit complex, we support 3 setups:
1038 // 1. hardware PWM when backlight is wired to a PWM pin
1039 // depending on this pin, we use a different output compare unit
1040 // 2. software PWM with hardware timers, but the used timer depends
1041 // on the audio setup (audio wins other backlight)
1042 // 3. full software PWM
1044 #if BACKLIGHT_PIN == B7
1045 # define HARDWARE_PWM
1046 # define TCCRxA TCCR1A
1047 # define TCCRxB TCCR1B
1048 # define COMxx1 COM1C1
1049 # define OCRxx OCR1C
1050 # define TIMERx_OVF_vect TIMER1_OVF_vect
1051 # define TOIEx TOIE1
1053 # define TIMSKx TIMSK1
1054 #elif BACKLIGHT_PIN == B6
1055 # define HARDWARE_PWM
1056 # define TCCRxA TCCR1A
1057 # define TCCRxB TCCR1B
1058 # define COMxx1 COM1B1
1059 # define OCRxx OCR1B
1060 # define TIMERx_OVF_vect TIMER1_OVF_vect
1061 # define TOIEx TOIE1
1063 # define TIMSKx TIMSK1
1064 #elif BACKLIGHT_PIN == B5
1065 # define HARDWARE_PWM
1066 # define TCCRxA TCCR1A
1067 # define TCCRxB TCCR1B
1068 # define COMxx1 COM1A1
1069 # define OCRxx OCR1A
1070 # define TIMERx_OVF_vect TIMER1_OVF_vect
1071 # define TOIEx TOIE1
1073 # define TIMSKx TIMSK1
1074 #elif BACKLIGHT_PIN == C6
1075 # define HARDWARE_PWM
1076 # define TCCRxA TCCR3A
1077 # define TCCRxB TCCR3B
1078 # define COMxx1 COM3A1
1079 # define OCRxx OCR3A
1080 # define TIMERx_OVF_vect TIMER3_OVF_vect
1081 # define TOIEx TOIE3
1083 # define TIMSKx TIMSK3
1084 #elif defined(__AVR_ATmega32A__) && BACKLIGHT_PIN == D4
1085 # define TCCRxA TCCR1A
1086 # define TCCRxB TCCR1B
1087 # define COMxx1 COM1B1
1088 # define OCRxx OCR1B
1089 # define TIMERx_OVF_vect TIMER1_OVF_vect
1090 # define TOIEx TOIE1
1092 # define TIMSKx TIMSK1
1094 # if !defined(BACKLIGHT_CUSTOM_DRIVER)
1095 # if !defined(B5_AUDIO) && !defined(B6_AUDIO) && !defined(B7_AUDIO)
1096 // timer 1 is not used by audio , backlight can use it
1097 #pragma message "Using hardware timer 1 with software PWM"
1098 # define HARDWARE_PWM
1099 # define BACKLIGHT_PWM_TIMER
1100 # define TCCRxA TCCR1A
1101 # define TCCRxB TCCR1B
1102 # define OCRxx OCR1A
1103 # define TIMERx_COMPA_vect TIMER1_COMPA_vect
1104 # define TIMERx_OVF_vect TIMER1_OVF_vect
1105 # define OCIExA OCIE1A
1106 # define TOIEx TOIE1
1108 # if defined(__AVR_ATmega32A__) // This MCU has only one TIMSK register
1109 # define TIMSKx TIMSK
1111 # define TIMSKx TIMSK1
1113 # elif !defined(C6_AUDIO) && !defined(C5_AUDIO) && !defined(C4_AUDIO)
1114 #pragma message "Using hardware timer 3 with software PWM"
1115 // timer 3 is not used by audio, backlight can use it
1116 # define HARDWARE_PWM
1117 # define BACKLIGHT_PWM_TIMER
1118 # define TCCRxA TCCR3A
1119 # define TCCRxB TCCR3B
1120 # define OCRxx OCR3A
1121 # define TIMERx_COMPA_vect TIMER3_COMPA_vect
1122 # define TIMERx_OVF_vect TIMER3_OVF_vect
1123 # define OCIExA OCIE3A
1124 # define TOIEx TOIE3
1126 # define TIMSKx TIMSK3
1128 #pragma message "Audio in use - using pure software PWM"
1129 #define NO_HARDWARE_PWM
1132 #pragma message "Custom driver defined - using pure software PWM"
1133 #define NO_HARDWARE_PWM
1137 #ifndef BACKLIGHT_ON_STATE
1138 #define BACKLIGHT_ON_STATE 0
1141 void backlight_on(uint8_t backlight_pin) {
1142 #if BACKLIGHT_ON_STATE == 0
1143 writePinLow(backlight_pin);
1145 writePinHigh(backlight_pin);
1149 void backlight_off(uint8_t backlight_pin) {
1150 #if BACKLIGHT_ON_STATE == 0
1151 writePinHigh(backlight_pin);
1153 writePinLow(backlight_pin);
1158 #if defined(NO_HARDWARE_PWM) || defined(BACKLIGHT_PWM_TIMER) // pwm through software
1160 // we support multiple backlight pins
1161 #ifndef BACKLIGHT_LED_COUNT
1162 #define BACKLIGHT_LED_COUNT 1
1165 #if BACKLIGHT_LED_COUNT == 1
1166 #define BACKLIGHT_PIN_INIT { BACKLIGHT_PIN }
1168 #define BACKLIGHT_PIN_INIT BACKLIGHT_PINS
1171 #define FOR_EACH_LED(x) \
1172 for (uint8_t i = 0; i < BACKLIGHT_LED_COUNT; i++) \
1174 uint8_t backlight_pin = backlight_pins[i]; \
1180 static const uint8_t backlight_pins[BACKLIGHT_LED_COUNT] = BACKLIGHT_PIN_INIT;
1182 #else // full hardware PWM
1184 // we support only one backlight pin
1185 static const uint8_t backlight_pin = BACKLIGHT_PIN;
1186 #define FOR_EACH_LED(x) x
1190 #ifdef NO_HARDWARE_PWM
1191 __attribute__((weak))
1192 void backlight_init_ports(void)
1194 // Setup backlight pin as output and output to on state.
1196 setPinOutput(backlight_pin);
1197 backlight_on(backlight_pin);
1201 __attribute__ ((weak))
1202 void backlight_set(uint8_t level) {}
1204 uint8_t backlight_tick = 0;
1206 #ifndef BACKLIGHT_CUSTOM_DRIVER
1207 void backlight_task(void) {
1208 if ((0xFFFF >> ((BACKLIGHT_LEVELS - get_backlight_level()) * ((BACKLIGHT_LEVELS + 1) / 2))) & (1 << backlight_tick)) {
1210 backlight_on(backlight_pin);
1215 backlight_off(backlight_pin);
1218 backlight_tick = (backlight_tick + 1) % 16;
1222 #ifdef BACKLIGHT_BREATHING
1223 #ifndef BACKLIGHT_CUSTOM_DRIVER
1224 #error "Backlight breathing only available with hardware PWM. Please disable."
1228 #else // hardware pwm through timer
1230 #ifdef BACKLIGHT_PWM_TIMER
1232 // The idea of software PWM assisted by hardware timers is the following
1233 // we use the hardware timer in fast PWM mode like for hardware PWM, but
1234 // instead of letting the Output Match Comparator control the led pin
1235 // (which is not possible since the backlight is not wired to PWM pins on the
1236 // CPU), we do the LED on/off by oursleves.
1237 // The timer is setup to count up to 0xFFFF, and we set the Output Compare
1238 // register to the current 16bits backlight level (after CIE correction).
1239 // This means the CPU will trigger a compare match interrupt when the counter
1240 // reaches the backlight level, where we turn off the LEDs,
1241 // but also an overflow interrupt when the counter rolls back to 0,
1242 // in which we're going to turn on the LEDs.
1243 // The LED will then be on for OCRxx/0xFFFF time, adjusted every 244Hz.
1245 // Triggered when the counter reaches the OCRx value
1246 ISR(TIMERx_COMPA_vect) {
1248 backlight_off(backlight_pin);
1252 // Triggered when the counter reaches the TOP value
1253 // this one triggers at F_CPU/65536 =~ 244 Hz
1254 ISR(TIMERx_OVF_vect) {
1255 #ifdef BACKLIGHT_BREATHING
1256 if(is_breathing()) {
1260 // for very small values of OCRxx (or backlight level)
1261 // we can't guarantee this whole code won't execute
1262 // at the same time as the compare match interrupt
1263 // which means that we might turn on the leds while
1264 // trying to turn them off, leading to flickering
1265 // artifacts (especially while breathing, because breathing_task
1266 // takes many computation cycles).
1267 // so better not turn them on while the counter TOP is very low.
1270 backlight_on(backlight_pin);
1277 #define TIMER_TOP 0xFFFFU
1279 // See http://jared.geek.nz/2013/feb/linear-led-pwm
1280 static uint16_t cie_lightness(uint16_t v) {
1281 if (v <= 5243) // if below 8% of max
1282 return v / 9; // same as dividing by 900%
1284 uint32_t y = (((uint32_t) v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare
1285 // to get a useful result with integer division, we shift left in the expression above
1286 // and revert what we've done again after squaring.
1288 if (y > 0xFFFFUL) // prevent overflow
1291 return (uint16_t) y;
1295 // range for val is [0..TIMER_TOP]. PWM pin is high while the timer count is below val.
1296 static inline void set_pwm(uint16_t val) {
1300 #ifndef BACKLIGHT_CUSTOM_DRIVER
1301 __attribute__ ((weak))
1302 void backlight_set(uint8_t level) {
1303 if (level > BACKLIGHT_LEVELS)
1304 level = BACKLIGHT_LEVELS;
1307 #ifdef BACKLIGHT_PWM_TIMER
1309 TIMSKx &= ~(_BV(OCIExA));
1310 TIMSKx &= ~(_BV(TOIEx));
1312 backlight_off(backlight_pin);
1316 // Turn off PWM control on backlight pin
1317 TCCRxA &= ~(_BV(COMxx1));
1320 #ifdef BACKLIGHT_PWM_TIMER
1322 TIMSKx |= _BV(OCIExA);
1323 TIMSKx |= _BV(TOIEx);
1326 // Turn on PWM control of backlight pin
1327 TCCRxA |= _BV(COMxx1);
1330 // Set the brightness
1331 set_pwm(cie_lightness(TIMER_TOP * (uint32_t)level / BACKLIGHT_LEVELS));
1334 void backlight_task(void) {}
1335 #endif // BACKLIGHT_CUSTOM_DRIVER
1337 #ifdef BACKLIGHT_BREATHING
1339 #define BREATHING_NO_HALT 0
1340 #define BREATHING_HALT_OFF 1
1341 #define BREATHING_HALT_ON 2
1342 #define BREATHING_STEPS 128
1344 static uint8_t breathing_period = BREATHING_PERIOD;
1345 static uint8_t breathing_halt = BREATHING_NO_HALT;
1346 static uint16_t breathing_counter = 0;
1348 #ifdef BACKLIGHT_PWM_TIMER
1349 static bool breathing = false;
1351 bool is_breathing(void) {
1355 #define breathing_interrupt_enable() do { breathing = true; } while (0)
1356 #define breathing_interrupt_disable() do { breathing = false; } while (0)
1359 bool is_breathing(void) {
1360 return !!(TIMSKx & _BV(TOIEx));
1363 #define breathing_interrupt_enable() do {TIMSKx |= _BV(TOIEx);} while (0)
1364 #define breathing_interrupt_disable() do {TIMSKx &= ~_BV(TOIEx);} while (0)
1367 #define breathing_min() do {breathing_counter = 0;} while (0)
1368 #define breathing_max() do {breathing_counter = breathing_period * 244 / 2;} while (0)
1370 void breathing_enable(void)
1372 breathing_counter = 0;
1373 breathing_halt = BREATHING_NO_HALT;
1374 breathing_interrupt_enable();
1377 void breathing_pulse(void)
1379 if (get_backlight_level() == 0)
1383 breathing_halt = BREATHING_HALT_ON;
1384 breathing_interrupt_enable();
1387 void breathing_disable(void)
1389 breathing_interrupt_disable();
1390 // Restore backlight level
1391 backlight_set(get_backlight_level());
1394 void breathing_self_disable(void)
1396 if (get_backlight_level() == 0)
1397 breathing_halt = BREATHING_HALT_OFF;
1399 breathing_halt = BREATHING_HALT_ON;
1402 void breathing_toggle(void) {
1404 breathing_disable();
1409 void breathing_period_set(uint8_t value)
1413 breathing_period = value;
1416 void breathing_period_default(void) {
1417 breathing_period_set(BREATHING_PERIOD);
1420 void breathing_period_inc(void)
1422 breathing_period_set(breathing_period+1);
1425 void breathing_period_dec(void)
1427 breathing_period_set(breathing_period-1);
1430 /* To generate breathing curve in python:
1431 * from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)]
1433 static const uint8_t breathing_table[BREATHING_STEPS] PROGMEM = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 17, 20, 24, 28, 32, 36, 41, 46, 51, 57, 63, 70, 76, 83, 91, 98, 106, 113, 121, 129, 138, 146, 154, 162, 170, 178, 185, 193, 200, 207, 213, 220, 225, 231, 235, 240, 244, 247, 250, 252, 253, 254, 255, 254, 253, 252, 250, 247, 244, 240, 235, 231, 225, 220, 213, 207, 200, 193, 185, 178, 170, 162, 154, 146, 138, 129, 121, 113, 106, 98, 91, 83, 76, 70, 63, 57, 51, 46, 41, 36, 32, 28, 24, 20, 17, 15, 12, 10, 8, 6, 5, 4, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1435 // Use this before the cie_lightness function.
1436 static inline uint16_t scale_backlight(uint16_t v) {
1437 return v / BACKLIGHT_LEVELS * get_backlight_level();
1440 #ifdef BACKLIGHT_PWM_TIMER
1441 void breathing_task(void)
1443 /* Assuming a 16MHz CPU clock and a timer that resets at 64k (ICR1), the following interrupt handler will run
1444 * about 244 times per second.
1446 ISR(TIMERx_OVF_vect)
1449 uint16_t interval = (uint16_t) breathing_period * 244 / BREATHING_STEPS;
1450 // resetting after one period to prevent ugly reset at overflow.
1451 breathing_counter = (breathing_counter + 1) % (breathing_period * 244);
1452 uint8_t index = breathing_counter / interval % BREATHING_STEPS;
1454 if (((breathing_halt == BREATHING_HALT_ON) && (index == BREATHING_STEPS / 2)) ||
1455 ((breathing_halt == BREATHING_HALT_OFF) && (index == BREATHING_STEPS - 1)))
1457 breathing_interrupt_disable();
1460 set_pwm(cie_lightness(scale_backlight((uint16_t) pgm_read_byte(&breathing_table[index]) * 0x0101U)));
1463 #endif // BACKLIGHT_BREATHING
1465 __attribute__ ((weak))
1466 void backlight_init_ports(void)
1468 // Setup backlight pin as output and output to on state.
1470 setPinOutput(backlight_pin);
1471 backlight_on(backlight_pin);
1474 // I could write a wall of text here to explain... but TL;DW
1475 // Go read the ATmega32u4 datasheet.
1476 // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
1478 #ifdef BACKLIGHT_PWM_TIMER
1479 // TimerX setup, Fast PWM mode count to TOP set in ICRx
1480 TCCRxA = _BV(WGM11); // = 0b00000010;
1481 // clock select clk/1
1482 TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
1483 #else // hardware PWM
1484 // Pin PB7 = OCR1C (Timer 1, Channel C)
1485 // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
1486 // (i.e. start high, go low when counter matches.)
1487 // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
1488 // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
1492 "In fast PWM mode, the compare units allow generation of PWM waveforms on the OCnx pins. Setting the COMnx1:0 bits to two will produce a non-inverted PWM [..]."
1493 "In fast PWM mode the counter is incremented until the counter value matches either one of the fixed values 0x00FF, 0x01FF, or 0x03FF (WGMn3:0 = 5, 6, or 7), the value in ICRn (WGMn3:0 = 14), or the value in OCRnA (WGMn3:0 = 15)."
1495 TCCRxA = _BV(COMxx1) | _BV(WGM11); // = 0b00001010;
1496 TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
1498 // Use full 16-bit resolution. Counter counts to ICR1 before reset to 0.
1502 #ifdef BACKLIGHT_BREATHING
1507 #endif // hardware backlight
1509 #else // no backlight
1511 __attribute__ ((weak))
1512 void backlight_init_ports(void) {}
1514 __attribute__ ((weak))
1515 void backlight_set(uint8_t level) {}
1519 #ifdef HD44780_ENABLED
1520 #include "hd44780.h"
1524 // Functions for spitting out values
1527 void send_dword(uint32_t number) { // this might not actually work
1528 uint16_t word = (number >> 16);
1530 send_word(number & 0xFFFFUL);
1533 void send_word(uint16_t number) {
1534 uint8_t byte = number >> 8;
1536 send_byte(number & 0xFF);
1539 void send_byte(uint8_t number) {
1540 uint8_t nibble = number >> 4;
1541 send_nibble(nibble);
1542 send_nibble(number & 0xF);
1545 void send_nibble(uint8_t number) {
1548 register_code(KC_0);
1549 unregister_code(KC_0);
1552 register_code(KC_1 + (number - 1));
1553 unregister_code(KC_1 + (number - 1));
1556 register_code(KC_A + (number - 0xA));
1557 unregister_code(KC_A + (number - 0xA));
1563 __attribute__((weak))
1564 uint16_t hex_to_keycode(uint8_t hex)
1569 } else if (hex < 0xA) {
1570 return KC_1 + (hex - 0x1);
1572 return KC_A + (hex - 0xA);
1576 void api_send_unicode(uint32_t unicode) {
1579 dword_to_bytes(unicode, chunk);
1580 MT_SEND_DATA(DT_UNICODE, chunk, 5);
1584 __attribute__ ((weak))
1585 void led_set_user(uint8_t usb_led) {
1589 __attribute__ ((weak))
1590 void led_set_kb(uint8_t usb_led) {
1591 led_set_user(usb_led);
1594 __attribute__ ((weak))
1595 void led_init_ports(void)
1600 __attribute__ ((weak))
1601 void led_set(uint8_t usb_led)
1603 #if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE)
1604 // Use backlight as Caps Lock indicator
1605 uint8_t bl_toggle_lvl = 0;
1607 if (IS_LED_ON(usb_led, USB_LED_CAPS_LOCK) && !backlight_config.enable) {
1608 // Turning Caps Lock ON and backlight is disabled in config
1609 // Toggling backlight to the brightest level
1610 bl_toggle_lvl = BACKLIGHT_LEVELS;
1611 } else if (IS_LED_OFF(usb_led, USB_LED_CAPS_LOCK) && backlight_config.enable) {
1612 // Turning Caps Lock OFF and backlight is enabled in config
1613 // Toggling backlight and restoring config level
1614 bl_toggle_lvl = backlight_config.level;
1617 // Set level without modify backlight_config to keep ability to restore state
1618 backlight_set(bl_toggle_lvl);
1621 led_set_kb(usb_led);
1625 //------------------------------------------------------------------------------
1626 // Override these functions in your keymap file to play different tunes on
1627 // different events such as startup and bootloader jump
1629 __attribute__ ((weak))
1630 void startup_user() {}
1632 __attribute__ ((weak))
1633 void shutdown_user() {}
1635 //------------------------------------------------------------------------------