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"
28 #define TAPPING_TERM 200
31 #ifndef BREATHING_PERIOD
32 #define BREATHING_PERIOD 6
35 #include "backlight.h"
36 extern backlight_config_t backlight_config;
38 #ifdef FAUXCLICKY_ENABLE
39 #include "fauxclicky.h"
47 #include "process_midi.h"
50 #ifdef VELOCIKEY_ENABLE
51 #include "velocikey.h"
64 #define GOODBYE_SONG SONG(GOODBYE_SOUND)
67 #define AG_NORM_SONG SONG(AG_NORM_SOUND)
70 #define AG_SWAP_SONG SONG(AG_SWAP_SOUND)
72 float goodbye_song[][2] = GOODBYE_SONG;
73 float ag_norm_song[][2] = AG_NORM_SONG;
74 float ag_swap_song[][2] = AG_SWAP_SONG;
75 #ifdef DEFAULT_LAYER_SONGS
76 float default_layer_songs[][16][2] = DEFAULT_LAYER_SONGS;
80 static void do_code16 (uint16_t code, void (*f) (uint8_t)) {
82 case QK_MODS ... QK_MODS_MAX:
97 if (code < QK_RMODS_MIN) return;
109 static inline void qk_register_weak_mods(uint8_t kc) {
110 add_weak_mods(MOD_BIT(kc));
111 send_keyboard_report();
114 static inline void qk_unregister_weak_mods(uint8_t kc) {
115 del_weak_mods(MOD_BIT(kc));
116 send_keyboard_report();
119 static inline void qk_register_mods(uint8_t kc) {
120 add_weak_mods(MOD_BIT(kc));
121 send_keyboard_report();
124 static inline void qk_unregister_mods(uint8_t kc) {
125 del_weak_mods(MOD_BIT(kc));
126 send_keyboard_report();
129 void register_code16 (uint16_t code) {
130 if (IS_MOD(code) || code == KC_NO) {
131 do_code16 (code, qk_register_mods);
133 do_code16 (code, qk_register_weak_mods);
135 register_code (code);
138 void unregister_code16 (uint16_t code) {
139 unregister_code (code);
140 if (IS_MOD(code) || code == KC_NO) {
141 do_code16 (code, qk_unregister_mods);
143 do_code16 (code, qk_unregister_weak_mods);
147 void tap_code16(uint16_t code) {
148 register_code16(code);
149 #if TAP_CODE_DELAY > 0
150 wait_ms(TAP_CODE_DELAY);
152 unregister_code16(code);
155 __attribute__ ((weak))
156 bool process_action_kb(keyrecord_t *record) {
160 __attribute__ ((weak))
161 bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
162 return process_record_user(keycode, record);
165 __attribute__ ((weak))
166 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
170 void reset_keyboard(void) {
172 #if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
173 process_midi_all_notes_off();
176 #ifndef NO_MUSIC_MODE
177 music_all_notes_off();
179 uint16_t timer_start = timer_read();
180 PLAY_SONG(goodbye_song);
182 while(timer_elapsed(timer_start) < 250)
192 // this is also done later in bootloader.c - not sure if it's neccesary here
193 #ifdef BOOTLOADER_CATERINA
194 *(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific
199 // Shift / paren setup
202 #define LSPO_KEY KC_9
205 #define RSPC_KEY KC_0
209 #define LSPO_MOD KC_LSFT
212 #define RSPC_MOD KC_RSFT
215 // Shift / Enter setup
217 #define SFTENT_KEY KC_ENT
220 static bool shift_interrupted[2] = {0, 0};
221 static uint16_t scs_timer[2] = {0, 0};
223 /* true if the last press of GRAVE_ESC was shifted (i.e. GUI or SHIFT were pressed), false otherwise.
224 * Used to ensure that the correct keycode is released if the key is released.
226 static bool grave_esc_was_shifted = false;
228 /* Convert record into usable keycode via the contained event. */
229 uint16_t get_record_keycode(keyrecord_t *record) {
230 return get_event_keycode(record->event);
234 /* Convert event into usable keycode. Checks the layer cache to ensure that it
235 * retains the correct keycode after a layer change, if the key is still pressed.
237 uint16_t get_event_keycode(keyevent_t event) {
239 #if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
240 /* TODO: Use store_or_get_action() or a similar function. */
241 if (!disable_action_cache) {
245 layer = layer_switch_get_layer(event.key);
246 update_source_layers_cache(event.key, layer);
248 layer = read_source_layers_cache(event.key);
250 return keymap_key_to_keycode(layer, event.key);
253 return keymap_key_to_keycode(layer_switch_get_layer(event.key), event.key);
256 /* Main keycode processing function. Hands off handling to other functions,
257 * then processes internal Quantum keycodes, then processes ACTIONs.
259 bool process_record_quantum(keyrecord_t *record) {
260 uint16_t keycode = get_record_keycode(record);
262 // This is how you use actions here
263 // if (keycode == KC_LEAD) {
265 // action.code = ACTION_DEFAULT_LAYER_SET(0);
266 // process_action(record, action);
270 #ifdef VELOCIKEY_ENABLE
271 if (velocikey_enabled() && record->event.pressed) { velocikey_accelerate(); }
274 #ifdef TAP_DANCE_ENABLE
275 preprocess_tap_dance(keycode, record);
278 #if defined(OLED_DRIVER_ENABLE) && !defined(OLED_DISABLE_TIMEOUT)
279 // Wake up oled if user is using those fabulous keys!
280 if (record->event.pressed)
285 #if defined(KEY_LOCK_ENABLE)
286 // Must run first to be able to mask key_up events.
287 process_key_lock(&keycode, record) &&
289 #if defined(AUDIO_ENABLE) && defined(AUDIO_CLICKY)
290 process_clicky(keycode, record) &&
291 #endif //AUDIO_CLICKY
293 process_haptic(keycode, record) &&
294 #endif //HAPTIC_ENABLE
295 #if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_KEYREACTIVE_ENABLED)
296 process_rgb_matrix(keycode, record) &&
298 process_record_kb(keycode, record) &&
299 #if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED)
300 process_midi(keycode, record) &&
303 process_audio(keycode, record) &&
306 process_steno(keycode, record) &&
308 #if (defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))) && !defined(NO_MUSIC_MODE)
309 process_music(keycode, record) &&
311 #ifdef TAP_DANCE_ENABLE
312 process_tap_dance(keycode, record) &&
314 #if defined(UNICODE_ENABLE) || defined(UNICODEMAP_ENABLE) || defined(UCIS_ENABLE)
315 process_unicode_common(keycode, record) &&
318 process_leader(keycode, record) &&
321 process_combo(keycode, record) &&
323 #ifdef PRINTING_ENABLE
324 process_printer(keycode, record) &&
326 #ifdef AUTO_SHIFT_ENABLE
327 process_auto_shift(keycode, record) &&
329 #ifdef TERMINAL_ENABLE
330 process_terminal(keycode, record) &&
336 // Shift / paren setup
340 if (record->event.pressed) {
345 if (record->event.pressed) {
347 print("DEBUG: enabled.\n");
351 if (record->event.pressed) {
355 #ifdef FAUXCLICKY_ENABLE
357 if (record->event.pressed) {
362 if (record->event.pressed) {
367 if (record->event.pressed) {
372 #if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
374 // Split keyboards need to trigger on key-up for edge-case issue
375 #ifndef SPLIT_KEYBOARD
376 if (record->event.pressed) {
378 if (!record->event.pressed) {
383 case RGB_MODE_FORWARD:
384 if (record->event.pressed) {
385 uint8_t shifted = get_mods() & (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT));
387 rgblight_step_reverse();
394 case RGB_MODE_REVERSE:
395 if (record->event.pressed) {
396 uint8_t shifted = get_mods() & (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT));
401 rgblight_step_reverse();
406 // Split keyboards need to trigger on key-up for edge-case issue
407 #ifndef SPLIT_KEYBOARD
408 if (record->event.pressed) {
410 if (!record->event.pressed) {
412 rgblight_increase_hue();
416 // Split keyboards need to trigger on key-up for edge-case issue
417 #ifndef SPLIT_KEYBOARD
418 if (record->event.pressed) {
420 if (!record->event.pressed) {
422 rgblight_decrease_hue();
426 // Split keyboards need to trigger on key-up for edge-case issue
427 #ifndef SPLIT_KEYBOARD
428 if (record->event.pressed) {
430 if (!record->event.pressed) {
432 rgblight_increase_sat();
436 // Split keyboards need to trigger on key-up for edge-case issue
437 #ifndef SPLIT_KEYBOARD
438 if (record->event.pressed) {
440 if (!record->event.pressed) {
442 rgblight_decrease_sat();
446 // Split keyboards need to trigger on key-up for edge-case issue
447 #ifndef SPLIT_KEYBOARD
448 if (record->event.pressed) {
450 if (!record->event.pressed) {
452 rgblight_increase_val();
456 // Split keyboards need to trigger on key-up for edge-case issue
457 #ifndef SPLIT_KEYBOARD
458 if (record->event.pressed) {
460 if (!record->event.pressed) {
462 rgblight_decrease_val();
466 if (record->event.pressed) {
467 rgblight_increase_speed();
471 if (record->event.pressed) {
472 rgblight_decrease_speed();
476 if (record->event.pressed) {
477 rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
480 case RGB_MODE_BREATHE:
481 #ifdef RGBLIGHT_EFFECT_BREATHING
482 if (record->event.pressed) {
483 if ((RGBLIGHT_MODE_BREATHING <= rgblight_get_mode()) &&
484 (rgblight_get_mode() < RGBLIGHT_MODE_BREATHING_end)) {
487 rgblight_mode(RGBLIGHT_MODE_BREATHING);
492 case RGB_MODE_RAINBOW:
493 #ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
494 if (record->event.pressed) {
495 if ((RGBLIGHT_MODE_RAINBOW_MOOD <= rgblight_get_mode()) &&
496 (rgblight_get_mode() < RGBLIGHT_MODE_RAINBOW_MOOD_end)) {
499 rgblight_mode(RGBLIGHT_MODE_RAINBOW_MOOD);
505 #ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
506 if (record->event.pressed) {
507 if ((RGBLIGHT_MODE_RAINBOW_SWIRL <= rgblight_get_mode()) &&
508 (rgblight_get_mode() < RGBLIGHT_MODE_RAINBOW_SWIRL_end)) {
511 rgblight_mode(RGBLIGHT_MODE_RAINBOW_SWIRL);
517 #ifdef RGBLIGHT_EFFECT_SNAKE
518 if (record->event.pressed) {
519 if ((RGBLIGHT_MODE_SNAKE <= rgblight_get_mode()) &&
520 (rgblight_get_mode() < RGBLIGHT_MODE_SNAKE_end)) {
523 rgblight_mode(RGBLIGHT_MODE_SNAKE);
528 case RGB_MODE_KNIGHT:
529 #ifdef RGBLIGHT_EFFECT_KNIGHT
530 if (record->event.pressed) {
531 if ((RGBLIGHT_MODE_KNIGHT <= rgblight_get_mode()) &&
532 (rgblight_get_mode() < RGBLIGHT_MODE_KNIGHT_end)) {
535 rgblight_mode(RGBLIGHT_MODE_KNIGHT);
541 #ifdef RGBLIGHT_EFFECT_CHRISTMAS
542 if (record->event.pressed) {
543 rgblight_mode(RGBLIGHT_MODE_CHRISTMAS);
547 case RGB_MODE_GRADIENT:
548 #ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
549 if (record->event.pressed) {
550 if ((RGBLIGHT_MODE_STATIC_GRADIENT <= rgblight_get_mode()) &&
551 (rgblight_get_mode() < RGBLIGHT_MODE_STATIC_GRADIENT_end)) {
554 rgblight_mode(RGBLIGHT_MODE_STATIC_GRADIENT);
559 case RGB_MODE_RGBTEST:
560 #ifdef RGBLIGHT_EFFECT_RGB_TEST
561 if (record->event.pressed) {
562 rgblight_mode(RGBLIGHT_MODE_RGB_TEST);
566 #endif // defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
567 #ifdef VELOCIKEY_ENABLE
569 if (record->event.pressed) {
576 if (record->event.pressed) {
577 set_output(OUTPUT_AUTO);
581 if (record->event.pressed) {
582 set_output(OUTPUT_USB);
585 #ifdef BLUETOOTH_ENABLE
587 if (record->event.pressed) {
588 set_output(OUTPUT_BLUETOOTH);
593 case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_NKRO:
594 if (record->event.pressed) {
595 // MAGIC actions (BOOTMAGIC without the boot)
596 if (!eeconfig_is_enabled()) {
600 keymap_config.raw = eeconfig_read_keymap();
603 case MAGIC_SWAP_CONTROL_CAPSLOCK:
604 keymap_config.swap_control_capslock = true;
606 case MAGIC_CAPSLOCK_TO_CONTROL:
607 keymap_config.capslock_to_control = true;
609 case MAGIC_SWAP_LALT_LGUI:
610 keymap_config.swap_lalt_lgui = true;
612 case MAGIC_SWAP_RALT_RGUI:
613 keymap_config.swap_ralt_rgui = true;
616 keymap_config.no_gui = true;
618 case MAGIC_SWAP_GRAVE_ESC:
619 keymap_config.swap_grave_esc = true;
621 case MAGIC_SWAP_BACKSLASH_BACKSPACE:
622 keymap_config.swap_backslash_backspace = true;
624 case MAGIC_HOST_NKRO:
625 keymap_config.nkro = true;
627 case MAGIC_SWAP_ALT_GUI:
628 keymap_config.swap_lalt_lgui = true;
629 keymap_config.swap_ralt_rgui = true;
631 PLAY_SONG(ag_swap_song);
634 case MAGIC_UNSWAP_CONTROL_CAPSLOCK:
635 keymap_config.swap_control_capslock = false;
637 case MAGIC_UNCAPSLOCK_TO_CONTROL:
638 keymap_config.capslock_to_control = false;
640 case MAGIC_UNSWAP_LALT_LGUI:
641 keymap_config.swap_lalt_lgui = false;
643 case MAGIC_UNSWAP_RALT_RGUI:
644 keymap_config.swap_ralt_rgui = false;
647 keymap_config.no_gui = false;
649 case MAGIC_UNSWAP_GRAVE_ESC:
650 keymap_config.swap_grave_esc = false;
652 case MAGIC_UNSWAP_BACKSLASH_BACKSPACE:
653 keymap_config.swap_backslash_backspace = false;
655 case MAGIC_UNHOST_NKRO:
656 keymap_config.nkro = false;
658 case MAGIC_UNSWAP_ALT_GUI:
659 keymap_config.swap_lalt_lgui = false;
660 keymap_config.swap_ralt_rgui = false;
662 PLAY_SONG(ag_norm_song);
665 case MAGIC_TOGGLE_ALT_GUI:
666 keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui;
667 keymap_config.swap_ralt_rgui = !keymap_config.swap_ralt_rgui;
669 if (keymap_config.swap_ralt_rgui) {
670 PLAY_SONG(ag_swap_song);
672 PLAY_SONG(ag_norm_song);
676 case MAGIC_TOGGLE_NKRO:
677 keymap_config.nkro = !keymap_config.nkro;
682 eeconfig_update_keymap(keymap_config.raw);
683 clear_keyboard(); // clear to prevent stuck keys
689 if (record->event.pressed) {
690 shift_interrupted[0] = false;
691 scs_timer[0] = timer_read ();
692 register_mods(MOD_BIT(KC_LSFT));
695 #ifdef DISABLE_SPACE_CADET_ROLLOVER
696 if (get_mods() & MOD_BIT(RSPC_MOD)) {
697 shift_interrupted[0] = true;
698 shift_interrupted[1] = true;
701 if (!shift_interrupted[0] && timer_elapsed(scs_timer[0]) < TAPPING_TERM) {
702 #ifdef DISABLE_SPACE_CADET_MODIFIER
703 unregister_mods(MOD_BIT(KC_LSFT));
705 if( LSPO_MOD != KC_LSFT ){
706 unregister_mods(MOD_BIT(KC_LSFT));
707 register_mods(MOD_BIT(LSPO_MOD));
710 register_code(LSPO_KEY);
711 unregister_code(LSPO_KEY);
712 #ifndef DISABLE_SPACE_CADET_MODIFIER
713 if( LSPO_MOD != KC_LSFT ){
714 unregister_mods(MOD_BIT(LSPO_MOD));
718 unregister_mods(MOD_BIT(KC_LSFT));
724 if (record->event.pressed) {
725 shift_interrupted[1] = false;
726 scs_timer[1] = timer_read ();
727 register_mods(MOD_BIT(KC_RSFT));
730 #ifdef DISABLE_SPACE_CADET_ROLLOVER
731 if (get_mods() & MOD_BIT(LSPO_MOD)) {
732 shift_interrupted[0] = true;
733 shift_interrupted[1] = true;
736 if (!shift_interrupted[1] && timer_elapsed(scs_timer[1]) < TAPPING_TERM) {
737 #ifdef DISABLE_SPACE_CADET_MODIFIER
738 unregister_mods(MOD_BIT(KC_RSFT));
740 if( RSPC_MOD != KC_RSFT ){
741 unregister_mods(MOD_BIT(KC_RSFT));
742 register_mods(MOD_BIT(RSPC_MOD));
745 register_code(RSPC_KEY);
746 unregister_code(RSPC_KEY);
747 #ifndef DISABLE_SPACE_CADET_MODIFIER
748 if ( RSPC_MOD != KC_RSFT ){
749 unregister_mods(MOD_BIT(RSPC_MOD));
753 unregister_mods(MOD_BIT(KC_RSFT));
759 if (record->event.pressed) {
760 shift_interrupted[1] = false;
761 scs_timer[1] = timer_read ();
762 register_mods(MOD_BIT(KC_RSFT));
764 else if (!shift_interrupted[1] && timer_elapsed(scs_timer[1]) < TAPPING_TERM) {
765 unregister_mods(MOD_BIT(KC_RSFT));
766 register_code(SFTENT_KEY);
767 unregister_code(SFTENT_KEY);
770 unregister_mods(MOD_BIT(KC_RSFT));
776 uint8_t shifted = get_mods() & ((MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT)
777 |MOD_BIT(KC_LGUI)|MOD_BIT(KC_RGUI)));
779 #ifdef GRAVE_ESC_ALT_OVERRIDE
780 // if ALT is pressed, ESC is always sent
781 // this is handy for the cmd+opt+esc shortcut on macOS, among other things.
782 if (get_mods() & (MOD_BIT(KC_LALT) | MOD_BIT(KC_RALT))) {
787 #ifdef GRAVE_ESC_CTRL_OVERRIDE
788 // if CTRL is pressed, ESC is always sent
789 // this is handy for the ctrl+shift+esc shortcut on windows, among other things.
790 if (get_mods() & (MOD_BIT(KC_LCTL) | MOD_BIT(KC_RCTL))) {
795 #ifdef GRAVE_ESC_GUI_OVERRIDE
796 // if GUI is pressed, ESC is always sent
797 if (get_mods() & (MOD_BIT(KC_LGUI) | MOD_BIT(KC_RGUI))) {
802 #ifdef GRAVE_ESC_SHIFT_OVERRIDE
803 // if SHIFT is pressed, ESC is always sent
804 if (get_mods() & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) {
809 if (record->event.pressed) {
810 grave_esc_was_shifted = shifted;
811 add_key(shifted ? KC_GRAVE : KC_ESCAPE);
814 del_key(grave_esc_was_shifted ? KC_GRAVE : KC_ESCAPE);
817 send_keyboard_report();
821 #if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_BREATHING)
823 if (record->event.pressed)
830 shift_interrupted[0] = true;
831 shift_interrupted[1] = true;
836 return process_action_kb(record);
839 __attribute__ ((weak))
840 const bool ascii_to_shift_lut[0x80] PROGMEM = {
841 0, 0, 0, 0, 0, 0, 0, 0,
842 0, 0, 0, 0, 0, 0, 0, 0,
843 0, 0, 0, 0, 0, 0, 0, 0,
844 0, 0, 0, 0, 0, 0, 0, 0,
845 0, 1, 1, 1, 1, 1, 1, 0,
846 1, 1, 1, 1, 0, 0, 0, 0,
847 0, 0, 0, 0, 0, 0, 0, 0,
848 0, 0, 1, 0, 1, 0, 1, 1,
849 1, 1, 1, 1, 1, 1, 1, 1,
850 1, 1, 1, 1, 1, 1, 1, 1,
851 1, 1, 1, 1, 1, 1, 1, 1,
852 1, 1, 1, 0, 0, 0, 1, 1,
853 0, 0, 0, 0, 0, 0, 0, 0,
854 0, 0, 0, 0, 0, 0, 0, 0,
855 0, 0, 0, 0, 0, 0, 0, 0,
856 0, 0, 0, 1, 1, 1, 1, 0
859 __attribute__ ((weak))
860 const bool ascii_to_altgr_lut[0x80] PROGMEM = {
861 0, 0, 0, 0, 0, 0, 0, 0,
862 0, 0, 0, 0, 0, 0, 0, 0,
863 0, 0, 0, 0, 0, 0, 0, 0,
864 0, 0, 0, 0, 0, 0, 0, 0,
865 0, 0, 0, 0, 0, 0, 0, 0,
866 0, 0, 0, 0, 0, 0, 0, 0,
867 0, 0, 0, 0, 0, 0, 0, 0,
868 0, 0, 0, 0, 0, 0, 0, 0,
869 0, 0, 0, 0, 0, 0, 0, 0,
870 0, 0, 0, 0, 0, 0, 0, 0,
871 0, 0, 0, 0, 0, 0, 0, 0,
872 0, 0, 0, 0, 0, 0, 0, 0,
873 0, 0, 0, 0, 0, 0, 0, 0,
874 0, 0, 0, 0, 0, 0, 0, 0,
875 0, 0, 0, 0, 0, 0, 0, 0,
876 0, 0, 0, 0, 0, 0, 0, 0
879 __attribute__ ((weak))
880 const uint8_t ascii_to_keycode_lut[0x80] PROGMEM = {
881 0, 0, 0, 0, 0, 0, 0, 0,
882 KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0,
883 0, 0, 0, 0, 0, 0, 0, 0,
884 0, 0, 0, KC_ESC, 0, 0, 0, 0,
885 KC_SPC, KC_1, KC_QUOT, KC_3, KC_4, KC_5, KC_7, KC_QUOT,
886 KC_9, KC_0, KC_8, KC_EQL, KC_COMM, KC_MINS, KC_DOT, KC_SLSH,
887 KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7,
888 KC_8, KC_9, KC_SCLN, KC_SCLN, KC_COMM, KC_EQL, KC_DOT, KC_SLSH,
889 KC_2, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
890 KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O,
891 KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
892 KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_6, KC_MINS,
893 KC_GRV, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
894 KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O,
895 KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
896 KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL
899 void send_string(const char *str) {
900 send_string_with_delay(str, 0);
903 void send_string_P(const char *str) {
904 send_string_with_delay_P(str, 0);
907 void send_string_with_delay(const char *str, uint8_t interval) {
909 char ascii_code = *str;
910 if (!ascii_code) break;
911 if (ascii_code == SS_TAP_CODE) {
913 uint8_t keycode = *(++str);
914 register_code(keycode);
915 unregister_code(keycode);
916 } else if (ascii_code == SS_DOWN_CODE) {
918 uint8_t keycode = *(++str);
919 register_code(keycode);
920 } else if (ascii_code == SS_UP_CODE) {
922 uint8_t keycode = *(++str);
923 unregister_code(keycode);
925 send_char(ascii_code);
929 { uint8_t ms = interval; while (ms--) wait_ms(1); }
933 void send_string_with_delay_P(const char *str, uint8_t interval) {
935 char ascii_code = pgm_read_byte(str);
936 if (!ascii_code) break;
937 if (ascii_code == SS_TAP_CODE) {
939 uint8_t keycode = pgm_read_byte(++str);
940 register_code(keycode);
941 unregister_code(keycode);
942 } else if (ascii_code == SS_DOWN_CODE) {
944 uint8_t keycode = pgm_read_byte(++str);
945 register_code(keycode);
946 } else if (ascii_code == SS_UP_CODE) {
948 uint8_t keycode = pgm_read_byte(++str);
949 unregister_code(keycode);
951 send_char(ascii_code);
955 { uint8_t ms = interval; while (ms--) wait_ms(1); }
959 void send_char(char ascii_code) {
960 uint8_t keycode = pgm_read_byte(&ascii_to_keycode_lut[(uint8_t)ascii_code]);
961 bool is_shifted = pgm_read_byte(&ascii_to_shift_lut[(uint8_t)ascii_code]);
962 bool is_altgred = pgm_read_byte(&ascii_to_altgr_lut[(uint8_t)ascii_code]);
965 register_code(KC_LSFT);
968 register_code(KC_RALT);
972 unregister_code(KC_RALT);
975 unregister_code(KC_LSFT);
979 void set_single_persistent_default_layer(uint8_t default_layer) {
980 #if defined(AUDIO_ENABLE) && defined(DEFAULT_LAYER_SONGS)
981 PLAY_SONG(default_layer_songs[default_layer]);
983 eeconfig_update_default_layer(1U<<default_layer);
984 default_layer_set(1U<<default_layer);
987 uint32_t update_tri_layer_state(uint32_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3) {
988 uint32_t mask12 = (1UL << layer1) | (1UL << layer2);
989 uint32_t mask3 = 1UL << layer3;
990 return (state & mask12) == mask12 ? (state | mask3) : (state & ~mask3);
993 void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) {
994 layer_state_set(update_tri_layer_state(layer_state, layer1, layer2, layer3));
997 void tap_random_base64(void) {
998 #if defined(__AVR_ATmega32U4__)
999 uint8_t key = (TCNT0 + TCNT1 + TCNT3 + TCNT4) % 64;
1001 uint8_t key = rand() % 64;
1005 register_code(KC_LSFT);
1006 register_code(key + KC_A);
1007 unregister_code(key + KC_A);
1008 unregister_code(KC_LSFT);
1011 register_code(key - 26 + KC_A);
1012 unregister_code(key - 26 + KC_A);
1015 register_code(KC_0);
1016 unregister_code(KC_0);
1019 register_code(key - 53 + KC_1);
1020 unregister_code(key - 53 + KC_1);
1023 register_code(KC_LSFT);
1024 register_code(KC_EQL);
1025 unregister_code(KC_EQL);
1026 unregister_code(KC_LSFT);
1029 register_code(KC_SLSH);
1030 unregister_code(KC_SLSH);
1035 __attribute__((weak))
1036 void bootmagic_lite(void) {
1037 // The lite version of TMK's bootmagic based on Wilba.
1038 // 100% less potential for accidentally making the
1039 // keyboard do stupid things.
1041 // We need multiple scans because debouncing can't be turned off.
1043 #if defined(DEBOUNCING_DELAY) && DEBOUNCING_DELAY > 0
1044 wait_ms(DEBOUNCING_DELAY * 2);
1045 #elif defined(DEBOUNCE) && DEBOUNCE > 0
1046 wait_ms(DEBOUNCE * 2);
1052 // If the Esc and space bar are held down on power up,
1053 // reset the EEPROM valid state and jump to bootloader.
1054 // Assumes Esc is at [0,0].
1055 // This isn't very generalized, but we need something that doesn't
1056 // rely on user's keymaps in firmware or EEPROM.
1057 if (matrix_get_row(BOOTMAGIC_LITE_ROW) & (1 << BOOTMAGIC_LITE_COLUMN)) {
1059 // Jump to bootloader.
1064 void matrix_init_quantum() {
1065 #ifdef BOOTMAGIC_LITE
1068 if (!eeconfig_is_enabled()) {
1071 #ifdef BACKLIGHT_ENABLE
1072 #ifdef LED_MATRIX_ENABLE
1075 backlight_init_ports();
1081 #ifdef RGB_MATRIX_ENABLE
1084 #ifdef ENCODER_ENABLE
1087 #if defined(UNICODE_ENABLE) || defined(UNICODEMAP_ENABLE) || defined(UCIS_ENABLE)
1088 unicode_input_mode_init();
1090 #ifdef HAPTIC_ENABLE
1093 #ifdef OUTPUT_AUTO_ENABLE
1094 set_output(OUTPUT_AUTO);
1096 #ifdef OLED_DRIVER_ENABLE
1097 oled_init(OLED_ROTATION_0);
1102 void matrix_scan_quantum() {
1103 #if defined(AUDIO_ENABLE) && !defined(NO_MUSIC_MODE)
1104 matrix_scan_music();
1107 #ifdef TAP_DANCE_ENABLE
1108 matrix_scan_tap_dance();
1112 matrix_scan_combo();
1115 #if defined(BACKLIGHT_ENABLE)
1116 #if defined(LED_MATRIX_ENABLE)
1118 #elif defined(BACKLIGHT_PIN)
1123 #ifdef RGB_MATRIX_ENABLE
1127 #ifdef ENCODER_ENABLE
1131 #ifdef HAPTIC_ENABLE
1135 #ifdef OLED_DRIVER_ENABLE
1141 #if defined(BACKLIGHT_ENABLE) && (defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS))
1143 // The logic is a bit complex, we support 3 setups:
1144 // 1. hardware PWM when backlight is wired to a PWM pin
1145 // depending on this pin, we use a different output compare unit
1146 // 2. software PWM with hardware timers, but the used timer depends
1147 // on the audio setup (audio wins other backlight)
1148 // 3. full software PWM
1150 #if BACKLIGHT_PIN == B7
1151 # define HARDWARE_PWM
1152 # define TCCRxA TCCR1A
1153 # define TCCRxB TCCR1B
1154 # define COMxx1 COM1C1
1155 # define OCRxx OCR1C
1157 #elif BACKLIGHT_PIN == B6
1158 # define HARDWARE_PWM
1159 # define TCCRxA TCCR1A
1160 # define TCCRxB TCCR1B
1161 # define COMxx1 COM1B1
1162 # define OCRxx OCR1B
1164 #elif BACKLIGHT_PIN == B5
1165 # define HARDWARE_PWM
1166 # define TCCRxA TCCR1A
1167 # define TCCRxB TCCR1B
1168 # define COMxx1 COM1A1
1169 # define OCRxx OCR1A
1171 #elif BACKLIGHT_PIN == C6
1172 # define HARDWARE_PWM
1173 # define TCCRxA TCCR3A
1174 # define TCCRxB TCCR3B
1175 # define COMxx1 COM1A1
1176 # define OCRxx OCR3A
1178 #elif defined(__AVR_ATmega32A__) && BACKLIGHT_PIN == D4
1179 # define TCCRxA TCCR1A
1180 # define TCCRxB TCCR1B
1181 # define COMxx1 COM1B1
1182 # define OCRxx OCR1B
1184 # define TIMSK1 TIMSK
1186 # if !defined(BACKLIGHT_CUSTOM_DRIVER)
1187 # if !defined(B5_AUDIO) && !defined(B6_AUDIO) && !defined(B7_AUDIO)
1188 // timer 1 is not used by audio , backlight can use it
1189 #pragma message "Using hardware timer 1 with software PWM"
1190 # define HARDWARE_PWM
1191 # define BACKLIGHT_PWM_TIMER
1192 # define TCCRxA TCCR1A
1193 # define TCCRxB TCCR1B
1194 # define OCRxx OCR1A
1195 # define OCRxAH OCR1AH
1196 # define OCRxAL OCR1AL
1197 # define TIMERx_COMPA_vect TIMER1_COMPA_vect
1198 # define TIMERx_OVF_vect TIMER1_OVF_vect
1199 # define OCIExA OCIE1A
1200 # define TOIEx TOIE1
1203 # define TIMSK TIMSK1
1205 # elif !defined(C6_AUDIO) && !defined(C5_AUDIO) && !defined(C4_AUDIO)
1206 #pragma message "Using hardware timer 3 with software PWM"
1207 // timer 3 is not used by audio, backlight can use it
1208 # define HARDWARE_PWM
1209 # define BACKLIGHT_PWM_TIMER
1210 # define TCCRxA TCCR3A
1211 # define TCCRxB TCCR3B
1212 # define OCRxx OCR3A
1213 # define OCRxAH OCR3AH
1214 # define OCRxAL OCR3AL
1215 # define TIMERx_COMPA_vect TIMER3_COMPA_vect
1216 # define TIMERx_OVF_vect TIMER3_OVF_vect
1217 # define OCIExA OCIE3A
1218 # define TOIEx TOIE3
1221 # define TIMSK TIMSK3
1224 #pragma message "Audio in use - using pure software PWM"
1225 #define NO_HARDWARE_PWM
1228 #pragma message "Custom driver defined - using pure software PWM"
1229 #define NO_HARDWARE_PWM
1233 #ifndef BACKLIGHT_ON_STATE
1234 #define BACKLIGHT_ON_STATE 0
1237 void backlight_on(uint8_t backlight_pin) {
1238 #if BACKLIGHT_ON_STATE == 0
1239 writePinLow(backlight_pin);
1241 writePinHigh(backlight_pin);
1245 void backlight_off(uint8_t backlight_pin) {
1246 #if BACKLIGHT_ON_STATE == 0
1247 writePinHigh(backlight_pin);
1249 writePinLow(backlight_pin);
1254 #if defined(NO_HARDWARE_PWM) || defined(BACKLIGHT_PWM_TIMER) // pwm through software
1256 // we support multiple backlight pins
1257 #ifndef BACKLIGHT_LED_COUNT
1258 #define BACKLIGHT_LED_COUNT 1
1261 #if BACKLIGHT_LED_COUNT == 1
1262 #define BACKLIGHT_PIN_INIT { BACKLIGHT_PIN }
1264 #define BACKLIGHT_PIN_INIT BACKLIGHT_PINS
1267 #define FOR_EACH_LED(x) \
1268 for (uint8_t i = 0; i < BACKLIGHT_LED_COUNT; i++) \
1270 uint8_t backlight_pin = backlight_pins[i]; \
1276 static const uint8_t backlight_pins[BACKLIGHT_LED_COUNT] = BACKLIGHT_PIN_INIT;
1278 #else // full hardware PWM
1280 // we support only one backlight pin
1281 static const uint8_t backlight_pin = BACKLIGHT_PIN;
1282 #define FOR_EACH_LED(x) x
1286 #ifdef NO_HARDWARE_PWM
1287 __attribute__((weak))
1288 void backlight_init_ports(void)
1290 // Setup backlight pin as output and output to on state.
1292 setPinOutput(backlight_pin);
1293 backlight_on(backlight_pin);
1297 __attribute__ ((weak))
1298 void backlight_set(uint8_t level) {}
1300 uint8_t backlight_tick = 0;
1302 #ifndef BACKLIGHT_CUSTOM_DRIVER
1303 void backlight_task(void) {
1304 if ((0xFFFF >> ((BACKLIGHT_LEVELS - get_backlight_level()) * ((BACKLIGHT_LEVELS + 1) / 2))) & (1 << backlight_tick)) {
1306 backlight_on(backlight_pin);
1311 backlight_off(backlight_pin);
1314 backlight_tick = (backlight_tick + 1) % 16;
1318 #ifdef BACKLIGHT_BREATHING
1319 #ifndef BACKLIGHT_CUSTOM_DRIVER
1320 #error "Backlight breathing only available with hardware PWM. Please disable."
1324 #else // hardware pwm through timer
1326 #ifdef BACKLIGHT_PWM_TIMER
1328 // The idea of software PWM assisted by hardware timers is the following
1329 // we use the hardware timer in fast PWM mode like for hardware PWM, but
1330 // instead of letting the Output Match Comparator control the led pin
1331 // (which is not possible since the backlight is not wired to PWM pins on the
1332 // CPU), we do the LED on/off by oursleves.
1333 // The timer is setup to count up to 0xFFFF, and we set the Output Compare
1334 // register to the current 16bits backlight level (after CIE correction).
1335 // This means the CPU will trigger a compare match interrupt when the counter
1336 // reaches the backlight level, where we turn off the LEDs,
1337 // but also an overflow interrupt when the counter rolls back to 0,
1338 // in which we're going to turn on the LEDs.
1339 // The LED will then be on for OCRxx/0xFFFF time, adjusted every 244Hz.
1341 // Triggered when the counter reaches the OCRx value
1342 ISR(TIMERx_COMPA_vect) {
1344 backlight_off(backlight_pin);
1348 // Triggered when the counter reaches the TOP value
1349 // this one triggers at F_CPU/65536 =~ 244 Hz
1350 ISR(TIMERx_OVF_vect) {
1351 #ifdef BACKLIGHT_BREATHING
1354 // for very small values of OCRxx (or backlight level)
1355 // we can't guarantee this whole code won't execute
1356 // at the same time as the compare match interrupt
1357 // which means that we might turn on the leds while
1358 // trying to turn them off, leading to flickering
1359 // artifacts (especially while breathing, because breathing_task
1360 // takes many computation cycles).
1361 // so better not turn them on while the counter TOP is very low.
1364 backlight_on(backlight_pin);
1371 #define TIMER_TOP 0xFFFFU
1373 // See http://jared.geek.nz/2013/feb/linear-led-pwm
1374 static uint16_t cie_lightness(uint16_t v) {
1375 if (v <= 5243) // if below 8% of max
1376 return v / 9; // same as dividing by 900%
1378 uint32_t y = (((uint32_t) v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare
1379 // to get a useful result with integer division, we shift left in the expression above
1380 // and revert what we've done again after squaring.
1382 if (y > 0xFFFFUL) // prevent overflow
1385 return (uint16_t) y;
1389 // range for val is [0..TIMER_TOP]. PWM pin is high while the timer count is below val.
1390 static inline void set_pwm(uint16_t val) {
1394 #ifndef BACKLIGHT_CUSTOM_DRIVER
1395 __attribute__ ((weak))
1396 void backlight_set(uint8_t level) {
1397 if (level > BACKLIGHT_LEVELS)
1398 level = BACKLIGHT_LEVELS;
1401 #ifdef BACKLIGHT_PWM_TIMER
1403 TIMSK &= ~(_BV(OCIExA));
1404 TIMSK &= ~(_BV(TOIEx));
1406 backlight_off(backlight_pin);
1410 // Turn off PWM control on backlight pin
1411 TCCRxA &= ~(_BV(COMxx1));
1414 #ifdef BACKLIGHT_PWM_TIMER
1416 TIMSK |= _BV(OCIExA);
1417 TIMSK |= _BV(TOIEx);
1420 // Turn on PWM control of backlight pin
1421 TCCRxA |= _BV(COMxx1);
1424 // Set the brightness
1425 set_pwm(cie_lightness(TIMER_TOP * (uint32_t)level / BACKLIGHT_LEVELS));
1428 void backlight_task(void) {}
1429 #endif // BACKLIGHT_CUSTOM_DRIVER
1431 #ifdef BACKLIGHT_BREATHING
1433 #define BREATHING_NO_HALT 0
1434 #define BREATHING_HALT_OFF 1
1435 #define BREATHING_HALT_ON 2
1436 #define BREATHING_STEPS 128
1438 static uint8_t breathing_period = BREATHING_PERIOD;
1439 static uint8_t breathing_halt = BREATHING_NO_HALT;
1440 static uint16_t breathing_counter = 0;
1442 #ifdef BACKLIGHT_PWM_TIMER
1443 static bool breathing = false;
1445 bool is_breathing(void) {
1449 #define breathing_interrupt_enable() do { breathing = true; } while (0)
1450 #define breathing_interrupt_disable() do { breathing = false; } while (0)
1453 bool is_breathing(void) {
1454 return !!(TIMSK1 & _BV(TOIE1));
1457 #define breathing_interrupt_enable() do {TIMSK1 |= _BV(TOIE1);} while (0)
1458 #define breathing_interrupt_disable() do {TIMSK1 &= ~_BV(TOIE1);} while (0)
1461 #define breathing_min() do {breathing_counter = 0;} while (0)
1462 #define breathing_max() do {breathing_counter = breathing_period * 244 / 2;} while (0)
1464 void breathing_enable(void)
1466 breathing_counter = 0;
1467 breathing_halt = BREATHING_NO_HALT;
1468 breathing_interrupt_enable();
1471 void breathing_pulse(void)
1473 if (get_backlight_level() == 0)
1477 breathing_halt = BREATHING_HALT_ON;
1478 breathing_interrupt_enable();
1481 void breathing_disable(void)
1483 breathing_interrupt_disable();
1484 // Restore backlight level
1485 backlight_set(get_backlight_level());
1488 void breathing_self_disable(void)
1490 if (get_backlight_level() == 0)
1491 breathing_halt = BREATHING_HALT_OFF;
1493 breathing_halt = BREATHING_HALT_ON;
1496 void breathing_toggle(void) {
1498 breathing_disable();
1503 void breathing_period_set(uint8_t value)
1507 breathing_period = value;
1510 void breathing_period_default(void) {
1511 breathing_period_set(BREATHING_PERIOD);
1514 void breathing_period_inc(void)
1516 breathing_period_set(breathing_period+1);
1519 void breathing_period_dec(void)
1521 breathing_period_set(breathing_period-1);
1524 /* To generate breathing curve in python:
1525 * from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)]
1527 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};
1529 // Use this before the cie_lightness function.
1530 static inline uint16_t scale_backlight(uint16_t v) {
1531 return v / BACKLIGHT_LEVELS * get_backlight_level();
1534 #ifdef BACKLIGHT_PWM_TIMER
1535 void breathing_task(void)
1537 /* Assuming a 16MHz CPU clock and a timer that resets at 64k (ICR1), the following interrupt handler will run
1538 * about 244 times per second.
1540 ISR(TIMER1_OVF_vect)
1543 uint16_t interval = (uint16_t) breathing_period * 244 / BREATHING_STEPS;
1544 // resetting after one period to prevent ugly reset at overflow.
1545 breathing_counter = (breathing_counter + 1) % (breathing_period * 244);
1546 uint8_t index = breathing_counter / interval % BREATHING_STEPS;
1548 if (((breathing_halt == BREATHING_HALT_ON) && (index == BREATHING_STEPS / 2)) ||
1549 ((breathing_halt == BREATHING_HALT_OFF) && (index == BREATHING_STEPS - 1)))
1551 breathing_interrupt_disable();
1554 set_pwm(cie_lightness(scale_backlight((uint16_t) pgm_read_byte(&breathing_table[index]) * 0x0101U)));
1557 #endif // BACKLIGHT_BREATHING
1559 __attribute__ ((weak))
1560 void backlight_init_ports(void)
1562 // Setup backlight pin as output and output to on state.
1564 setPinOutput(backlight_pin);
1565 backlight_on(backlight_pin);
1568 // I could write a wall of text here to explain... but TL;DW
1569 // Go read the ATmega32u4 datasheet.
1570 // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
1572 #ifdef BACKLIGHT_PWM_TIMER
1573 // TimerX setup, Fast PWM mode count to TOP set in ICRx
1574 TCCRxA = _BV(WGM11); // = 0b00000010;
1575 // clock select clk/1
1576 TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
1577 #else // hardware PWM
1578 // Pin PB7 = OCR1C (Timer 1, Channel C)
1579 // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
1580 // (i.e. start high, go low when counter matches.)
1581 // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
1582 // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
1586 "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 [..]."
1587 "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)."
1589 TCCRxA = _BV(COMxx1) | _BV(WGM11); // = 0b00001010;
1590 TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
1592 // Use full 16-bit resolution. Counter counts to ICR1 before reset to 0.
1596 #ifdef BACKLIGHT_BREATHING
1601 #endif // hardware backlight
1603 #else // no backlight
1605 __attribute__ ((weak))
1606 void backlight_init_ports(void) {}
1608 __attribute__ ((weak))
1609 void backlight_set(uint8_t level) {}
1613 #ifdef HD44780_ENABLED
1614 #include "hd44780.h"
1618 // Functions for spitting out values
1621 void send_dword(uint32_t number) { // this might not actually work
1622 uint16_t word = (number >> 16);
1624 send_word(number & 0xFFFFUL);
1627 void send_word(uint16_t number) {
1628 uint8_t byte = number >> 8;
1630 send_byte(number & 0xFF);
1633 void send_byte(uint8_t number) {
1634 uint8_t nibble = number >> 4;
1635 send_nibble(nibble);
1636 send_nibble(number & 0xF);
1639 void send_nibble(uint8_t number) {
1642 register_code(KC_0);
1643 unregister_code(KC_0);
1646 register_code(KC_1 + (number - 1));
1647 unregister_code(KC_1 + (number - 1));
1650 register_code(KC_A + (number - 0xA));
1651 unregister_code(KC_A + (number - 0xA));
1657 __attribute__((weak))
1658 uint16_t hex_to_keycode(uint8_t hex)
1663 } else if (hex < 0xA) {
1664 return KC_1 + (hex - 0x1);
1666 return KC_A + (hex - 0xA);
1670 void api_send_unicode(uint32_t unicode) {
1673 dword_to_bytes(unicode, chunk);
1674 MT_SEND_DATA(DT_UNICODE, chunk, 5);
1678 __attribute__ ((weak))
1679 void led_set_user(uint8_t usb_led) {
1683 __attribute__ ((weak))
1684 void led_set_kb(uint8_t usb_led) {
1685 led_set_user(usb_led);
1688 __attribute__ ((weak))
1689 void led_init_ports(void)
1694 __attribute__ ((weak))
1695 void led_set(uint8_t usb_led)
1700 // // Using PE6 Caps Lock LED
1701 // if (usb_led & (1<<USB_LED_CAPS_LOCK))
1711 // PORTE &= ~(1<<6);
1714 #if defined(BACKLIGHT_CAPS_LOCK) && defined(BACKLIGHT_ENABLE)
1715 // Use backlight as Caps Lock indicator
1716 uint8_t bl_toggle_lvl = 0;
1718 if (IS_LED_ON(usb_led, USB_LED_CAPS_LOCK) && !backlight_config.enable) {
1719 // Turning Caps Lock ON and backlight is disabled in config
1720 // Toggling backlight to the brightest level
1721 bl_toggle_lvl = BACKLIGHT_LEVELS;
1722 } else if (IS_LED_OFF(usb_led, USB_LED_CAPS_LOCK) && backlight_config.enable) {
1723 // Turning Caps Lock OFF and backlight is enabled in config
1724 // Toggling backlight and restoring config level
1725 bl_toggle_lvl = backlight_config.level;
1728 // Set level without modify backlight_config to keep ability to restore state
1729 backlight_set(bl_toggle_lvl);
1732 led_set_kb(usb_led);
1736 //------------------------------------------------------------------------------
1737 // Override these functions in your keymap file to play different tunes on
1738 // different events such as startup and bootloader jump
1740 __attribute__ ((weak))
1741 void startup_user() {}
1743 __attribute__ ((weak))
1744 void shutdown_user() {}
1746 //------------------------------------------------------------------------------