Add keycodes for swap-hands feature.
[jackhill/qmk/firmware.git] / quantum / quantum.c
CommitLineData
23839b8c 1/* Copyright 2016-2017 Jack Humbert
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
1a8c0dd2 17#include "quantum.h"
e7c4f621 18#ifdef PROTOCOL_LUFA
c17070ec 19#include "outputselect.h"
2bef8b5b 20#endif
1a8c0dd2 21
74a1f007
GN
22#ifndef TAPPING_TERM
23#define TAPPING_TERM 200
24#endif
25
4931510a
BG
26#ifndef BREATHING_PERIOD
27#define BREATHING_PERIOD 6
28#endif
29
8d0fdf10
JH
30#include "backlight.h"
31extern backlight_config_t backlight_config;
db1e9a46 32
8c93c5d9
PIN
33#ifdef FAUXCLICKY_ENABLE
34#include "fauxclicky.h"
35#endif
8d0fdf10 36
53ff8a31 37#ifdef API_ENABLE
38#include "api.h"
39#endif
40
41#ifdef MIDI_ENABLE
42#include "process_midi.h"
43#endif
44
6a3c6677
JH
45#ifdef AUDIO_ENABLE
46 #ifndef GOODBYE_SONG
47 #define GOODBYE_SONG SONG(GOODBYE_SOUND)
48 #endif
49 #ifndef AG_NORM_SONG
50 #define AG_NORM_SONG SONG(AG_NORM_SOUND)
51 #endif
52 #ifndef AG_SWAP_SONG
53 #define AG_SWAP_SONG SONG(AG_SWAP_SOUND)
54 #endif
6a3c6677
JH
55 float goodbye_song[][2] = GOODBYE_SONG;
56 float ag_norm_song[][2] = AG_NORM_SONG;
57 float ag_swap_song[][2] = AG_SWAP_SONG;
6895c451
JH
58 #ifdef DEFAULT_LAYER_SONGS
59 float default_layer_songs[][16][2] = DEFAULT_LAYER_SONGS;
60 #endif
6a3c6677
JH
61#endif
62
0d28787c
GN
63static void do_code16 (uint16_t code, void (*f) (uint8_t)) {
64 switch (code) {
65 case QK_MODS ... QK_MODS_MAX:
66 break;
67 default:
68 return;
69 }
70
71 if (code & QK_LCTL)
72 f(KC_LCTL);
73 if (code & QK_LSFT)
74 f(KC_LSFT);
75 if (code & QK_LALT)
76 f(KC_LALT);
77 if (code & QK_LGUI)
78 f(KC_LGUI);
79
01038ab5
OP
80 if (code < QK_RMODS_MIN) return;
81
0d28787c
GN
82 if (code & QK_RCTL)
83 f(KC_RCTL);
84 if (code & QK_RSFT)
85 f(KC_RSFT);
86 if (code & QK_RALT)
87 f(KC_RALT);
88 if (code & QK_RGUI)
89 f(KC_RGUI);
90}
91
f644b9a0
S
92static inline void qk_register_weak_mods(uint8_t kc) {
93 add_weak_mods(MOD_BIT(kc));
94 send_keyboard_report();
95}
96
97static inline void qk_unregister_weak_mods(uint8_t kc) {
98 del_weak_mods(MOD_BIT(kc));
99 send_keyboard_report();
100}
101
2b385993 102static inline void qk_register_mods(uint8_t kc) {
f644b9a0
S
103 add_weak_mods(MOD_BIT(kc));
104 send_keyboard_report();
2b385993
S
105}
106
107static inline void qk_unregister_mods(uint8_t kc) {
f644b9a0
S
108 del_weak_mods(MOD_BIT(kc));
109 send_keyboard_report();
2b385993
S
110}
111
0d28787c 112void register_code16 (uint16_t code) {
f644b9a0
S
113 if (IS_MOD(code) || code == KC_NO) {
114 do_code16 (code, qk_register_mods);
115 } else {
116 do_code16 (code, qk_register_weak_mods);
117 }
0d28787c
GN
118 register_code (code);
119}
120
121void unregister_code16 (uint16_t code) {
122 unregister_code (code);
f644b9a0
S
123 if (IS_MOD(code) || code == KC_NO) {
124 do_code16 (code, qk_unregister_mods);
125 } else {
126 do_code16 (code, qk_unregister_weak_mods);
127 }
0d28787c
GN
128}
129
1a8c0dd2 130__attribute__ ((weak))
1a8c0dd2
EZ
131bool process_action_kb(keyrecord_t *record) {
132 return true;
133}
134
17977a7e
JH
135__attribute__ ((weak))
136bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
137 return process_record_user(keycode, record);
138}
139
140__attribute__ ((weak))
141bool process_record_user(uint16_t keycode, keyrecord_t *record) {
142 return true;
143}
144
a28a6e5b
PV
145void reset_keyboard(void) {
146 clear_keyboard();
e6b91549
JH
147#if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
148 process_midi_all_notes_off();
365b8635 149#endif
6835ae82 150#if defined(AUDIO_ENABLE) && !defined(NO_MUSIC_MODE)
a64ae106 151 music_all_notes_off();
6a3c6677
JH
152 uint16_t timer_start = timer_read();
153 PLAY_SONG(goodbye_song);
a28a6e5b 154 shutdown_user();
365b8635 155 while(timer_elapsed(timer_start) < 250)
6a3c6677
JH
156 wait_ms(1);
157 stop_all_notes();
158#else
a28a6e5b 159 wait_ms(250);
6a3c6677 160#endif
9fdc2762
JH
161// this is also done later in bootloader.c - not sure if it's neccesary here
162#ifdef BOOTLOADER_CATERINA
a28a6e5b
PV
163 *(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific
164#endif
165 bootloader_jump();
166}
167
b70248fa
JH
168// Shift / paren setup
169
170#ifndef LSPO_KEY
171 #define LSPO_KEY KC_9
172#endif
173#ifndef RSPC_KEY
174 #define RSPC_KEY KC_0
175#endif
176
8a1e6560
ZR
177// Shift / Enter setup
178#ifndef SFTENT_KEY
179 #define SFTENT_KEY KC_ENT
180#endif
181
8bc69afc 182static bool shift_interrupted[2] = {0, 0};
de52bd5d 183static uint16_t scs_timer[2] = {0, 0};
12370259 184
b4be711a
BG
185/* true if the last press of GRAVE_ESC was shifted (i.e. GUI or SHIFT were pressed), false otherwise.
186 * Used to ensure that the correct keycode is released if the key is released.
187 */
188static bool grave_esc_was_shifted = false;
189
bf5c2cce 190bool process_record_quantum(keyrecord_t *record) {
1a8c0dd2
EZ
191
192 /* This gets the keycode from the key pressed */
193 keypos_t key = record->event.key;
194 uint16_t keycode;
195
196 #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
644c8c79
WS
197 /* TODO: Use store_or_get_action() or a similar function. */
198 if (!disable_action_cache) {
199 uint8_t layer;
1a8c0dd2 200
644c8c79
WS
201 if (record->event.pressed) {
202 layer = layer_switch_get_layer(key);
203 update_source_layers_cache(key, layer);
204 } else {
205 layer = read_source_layers_cache(key);
206 }
207 keycode = keymap_key_to_keycode(layer, key);
208 } else
1a8c0dd2 209 #endif
644c8c79 210 keycode = keymap_key_to_keycode(layer_switch_get_layer(key), key);
1a8c0dd2 211
bf5c2cce
JH
212 // This is how you use actions here
213 // if (keycode == KC_LEAD) {
214 // action_t action;
215 // action.code = ACTION_DEFAULT_LAYER_SET(0);
216 // process_action(record, action);
217 // return false;
218 // }
219
9fcda953 220 #ifdef TAP_DANCE_ENABLE
221 preprocess_tap_dance(keycode, record);
222 #endif
223
65faab3b 224 if (!(
8e1be7c7
FS
225 #if defined(KEY_LOCK_ENABLE)
226 // Must run first to be able to mask key_up events.
a3e1d9a8 227 process_key_lock(&keycode, record) &&
8e1be7c7 228 #endif
65faab3b 229 process_record_kb(keycode, record) &&
525be99e 230 #if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED)
65faab3b 231 process_midi(keycode, record) &&
fde477a9 232 #endif
1a8c0dd2 233 #ifdef AUDIO_ENABLE
1000799d
GY
234 process_audio(keycode, record) &&
235 #endif
5987f679
JW
236 #ifdef STENO_ENABLE
237 process_steno(keycode, record) &&
238 #endif
6835ae82 239 #if ( defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))) && !defined(NO_MUSIC_MODE)
65faab3b 240 process_music(keycode, record) &&
1a8c0dd2 241 #endif
65faab3b
JH
242 #ifdef TAP_DANCE_ENABLE
243 process_tap_dance(keycode, record) &&
244 #endif
245 #ifndef DISABLE_LEADER
246 process_leader(keycode, record) &&
247 #endif
248 #ifndef DISABLE_CHORDING
249 process_chording(keycode, record) &&
250 #endif
40abf8bc
OP
251 #ifdef COMBO_ENABLE
252 process_combo(keycode, record) &&
253 #endif
65faab3b
JH
254 #ifdef UNICODE_ENABLE
255 process_unicode(keycode, record) &&
857aa5be
GN
256 #endif
257 #ifdef UCIS_ENABLE
258 process_ucis(keycode, record) &&
5f91fb41
JH
259 #endif
260 #ifdef PRINTING_ENABLE
261 process_printer(keycode, record) &&
e9f74875 262 #endif
abba393f
JC
263 #ifdef AUTO_SHIFT_ENABLE
264 process_auto_shift(keycode, record) &&
265 #endif
5b2e455d
PIN
266 #ifdef UNICODEMAP_ENABLE
267 process_unicode_map(keycode, record) &&
7ad924ba
JH
268 #endif
269 #ifdef TERMINAL_ENABLE
270 process_terminal(keycode, record) &&
65faab3b
JH
271 #endif
272 true)) {
273 return false;
b732b79b
JH
274 }
275
b70248fa
JH
276 // Shift / paren setup
277
12370259 278 switch(keycode) {
db32864c
JH
279 case RESET:
280 if (record->event.pressed) {
a28a6e5b 281 reset_keyboard();
db32864c 282 }
4580d3a7 283 return false;
db32864c
JH
284 case DEBUG:
285 if (record->event.pressed) {
db32864c 286 debug_enable = true;
4d5eeb3d 287 print("DEBUG: enabled.\n");
db32864c 288 }
4580d3a7 289 return false;
8c93c5d9
PIN
290 #ifdef FAUXCLICKY_ENABLE
291 case FC_TOG:
292 if (record->event.pressed) {
293 FAUXCLICKY_TOGGLE;
294 }
295 return false;
8c93c5d9
PIN
296 case FC_ON:
297 if (record->event.pressed) {
298 FAUXCLICKY_ON;
299 }
300 return false;
8c93c5d9
PIN
301 case FC_OFF:
302 if (record->event.pressed) {
303 FAUXCLICKY_OFF;
304 }
305 return false;
8c93c5d9 306 #endif
4580d3a7 307 #ifdef RGBLIGHT_ENABLE
308 case RGB_TOG:
309 if (record->event.pressed) {
310 rgblight_toggle();
311 }
312 return false;
53b043d4 313 case RGB_MODE_FORWARD:
4580d3a7 314 if (record->event.pressed) {
53b043d4
CG
315 uint8_t shifted = get_mods() & (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT));
316 if(shifted) {
317 rgblight_step_reverse();
318 }
319 else {
320 rgblight_step();
321 }
4580d3a7 322 }
323 return false;
53b043d4 324 case RGB_MODE_REVERSE:
1f434959
SK
325 if (record->event.pressed) {
326 uint8_t shifted = get_mods() & (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT));
327 if(shifted) {
53b043d4 328 rgblight_step();
1f434959
SK
329 }
330 else {
53b043d4 331 rgblight_step_reverse();
1f434959
SK
332 }
333 }
334 return false;
4580d3a7 335 case RGB_HUI:
336 if (record->event.pressed) {
337 rgblight_increase_hue();
338 }
339 return false;
340 case RGB_HUD:
341 if (record->event.pressed) {
342 rgblight_decrease_hue();
343 }
344 return false;
345 case RGB_SAI:
346 if (record->event.pressed) {
347 rgblight_increase_sat();
348 }
349 return false;
350 case RGB_SAD:
351 if (record->event.pressed) {
352 rgblight_decrease_sat();
353 }
354 return false;
355 case RGB_VAI:
356 if (record->event.pressed) {
357 rgblight_increase_val();
358 }
359 return false;
360 case RGB_VAD:
361 if (record->event.pressed) {
362 rgblight_decrease_val();
363 }
364 return false;
365 case RGB_MODE_PLAIN:
366 if (record->event.pressed) {
367 rgblight_mode(1);
368 }
369 return false;
370 case RGB_MODE_BREATHE:
371 if (record->event.pressed) {
372 if ((2 <= rgblight_get_mode()) && (rgblight_get_mode() < 5)) {
373 rgblight_step();
374 } else {
375 rgblight_mode(2);
f7a86822 376 }
4580d3a7 377 }
378 return false;
379 case RGB_MODE_RAINBOW:
380 if (record->event.pressed) {
381 if ((6 <= rgblight_get_mode()) && (rgblight_get_mode() < 8)) {
382 rgblight_step();
383 } else {
384 rgblight_mode(6);
f7a86822 385 }
4580d3a7 386 }
387 return false;
388 case RGB_MODE_SWIRL:
389 if (record->event.pressed) {
390 if ((9 <= rgblight_get_mode()) && (rgblight_get_mode() < 14)) {
391 rgblight_step();
392 } else {
393 rgblight_mode(9);
f7a86822 394 }
4580d3a7 395 }
396 return false;
397 case RGB_MODE_SNAKE:
398 if (record->event.pressed) {
399 if ((15 <= rgblight_get_mode()) && (rgblight_get_mode() < 20)) {
400 rgblight_step();
401 } else {
402 rgblight_mode(15);
f7a86822 403 }
4580d3a7 404 }
405 return false;
406 case RGB_MODE_KNIGHT:
407 if (record->event.pressed) {
408 if ((21 <= rgblight_get_mode()) && (rgblight_get_mode() < 23)) {
409 rgblight_step();
410 } else {
411 rgblight_mode(21);
f7a86822 412 }
4580d3a7 413 }
414 return false;
415 case RGB_MODE_XMAS:
416 if (record->event.pressed) {
417 rgblight_mode(24);
418 }
419 return false;
420 case RGB_MODE_GRADIENT:
421 if (record->event.pressed) {
422 if ((25 <= rgblight_get_mode()) && (rgblight_get_mode() < 34)) {
423 rgblight_step();
424 } else {
425 rgblight_mode(25);
f7a86822 426 }
4580d3a7 427 }
428 return false;
429 #endif
e7c4f621 430 #ifdef PROTOCOL_LUFA
c17070ec
PIN
431 case OUT_AUTO:
432 if (record->event.pressed) {
433 set_output(OUTPUT_AUTO);
434 }
435 return false;
c17070ec
PIN
436 case OUT_USB:
437 if (record->event.pressed) {
438 set_output(OUTPUT_USB);
439 }
440 return false;
c17070ec
PIN
441 #ifdef BLUETOOTH_ENABLE
442 case OUT_BT:
443 if (record->event.pressed) {
444 set_output(OUTPUT_BLUETOOTH);
445 }
446 return false;
c17070ec 447 #endif
2bef8b5b 448 #endif
558f3ec1 449 case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_NKRO:
db32864c
JH
450 if (record->event.pressed) {
451 // MAGIC actions (BOOTMAGIC without the boot)
452 if (!eeconfig_is_enabled()) {
453 eeconfig_init();
454 }
455 /* keymap config */
456 keymap_config.raw = eeconfig_read_keymap();
558f3ec1
I
457 switch (keycode)
458 {
459 case MAGIC_SWAP_CONTROL_CAPSLOCK:
460 keymap_config.swap_control_capslock = true;
461 break;
462 case MAGIC_CAPSLOCK_TO_CONTROL:
463 keymap_config.capslock_to_control = true;
464 break;
465 case MAGIC_SWAP_LALT_LGUI:
466 keymap_config.swap_lalt_lgui = true;
467 break;
468 case MAGIC_SWAP_RALT_RGUI:
469 keymap_config.swap_ralt_rgui = true;
470 break;
471 case MAGIC_NO_GUI:
472 keymap_config.no_gui = true;
473 break;
474 case MAGIC_SWAP_GRAVE_ESC:
475 keymap_config.swap_grave_esc = true;
476 break;
477 case MAGIC_SWAP_BACKSLASH_BACKSPACE:
478 keymap_config.swap_backslash_backspace = true;
479 break;
480 case MAGIC_HOST_NKRO:
481 keymap_config.nkro = true;
482 break;
483 case MAGIC_SWAP_ALT_GUI:
484 keymap_config.swap_lalt_lgui = true;
485 keymap_config.swap_ralt_rgui = true;
6a3c6677
JH
486 #ifdef AUDIO_ENABLE
487 PLAY_SONG(ag_swap_song);
488 #endif
558f3ec1
I
489 break;
490 case MAGIC_UNSWAP_CONTROL_CAPSLOCK:
491 keymap_config.swap_control_capslock = false;
492 break;
493 case MAGIC_UNCAPSLOCK_TO_CONTROL:
494 keymap_config.capslock_to_control = false;
495 break;
496 case MAGIC_UNSWAP_LALT_LGUI:
497 keymap_config.swap_lalt_lgui = false;
498 break;
499 case MAGIC_UNSWAP_RALT_RGUI:
500 keymap_config.swap_ralt_rgui = false;
501 break;
502 case MAGIC_UNNO_GUI:
503 keymap_config.no_gui = false;
504 break;
505 case MAGIC_UNSWAP_GRAVE_ESC:
506 keymap_config.swap_grave_esc = false;
507 break;
508 case MAGIC_UNSWAP_BACKSLASH_BACKSPACE:
509 keymap_config.swap_backslash_backspace = false;
510 break;
511 case MAGIC_UNHOST_NKRO:
512 keymap_config.nkro = false;
513 break;
514 case MAGIC_UNSWAP_ALT_GUI:
515 keymap_config.swap_lalt_lgui = false;
516 keymap_config.swap_ralt_rgui = false;
6a3c6677
JH
517 #ifdef AUDIO_ENABLE
518 PLAY_SONG(ag_norm_song);
519 #endif
558f3ec1
I
520 break;
521 case MAGIC_TOGGLE_NKRO:
522 keymap_config.nkro = !keymap_config.nkro;
523 break;
524 default:
525 break;
db32864c
JH
526 }
527 eeconfig_update_keymap(keymap_config.raw);
558f3ec1
I
528 clear_keyboard(); // clear to prevent stuck keys
529
db32864c
JH
530 return false;
531 }
532 break;
12370259 533 case KC_LSPO: {
db32864c
JH
534 if (record->event.pressed) {
535 shift_interrupted[0] = false;
de52bd5d 536 scs_timer[0] = timer_read ();
76076db7 537 register_mods(MOD_BIT(KC_LSFT));
db32864c
JH
538 }
539 else {
b12fe6ab
S
540 #ifdef DISABLE_SPACE_CADET_ROLLOVER
541 if (get_mods() & MOD_BIT(KC_RSFT)) {
542 shift_interrupted[0] = true;
543 shift_interrupted[1] = true;
544 }
545 #endif
de52bd5d 546 if (!shift_interrupted[0] && timer_elapsed(scs_timer[0]) < TAPPING_TERM) {
db32864c
JH
547 register_code(LSPO_KEY);
548 unregister_code(LSPO_KEY);
549 }
76076db7 550 unregister_mods(MOD_BIT(KC_LSFT));
db32864c
JH
551 }
552 return false;
db32864c 553 }
12370259
EZ
554
555 case KC_RSPC: {
db32864c
JH
556 if (record->event.pressed) {
557 shift_interrupted[1] = false;
de52bd5d 558 scs_timer[1] = timer_read ();
76076db7 559 register_mods(MOD_BIT(KC_RSFT));
db32864c
JH
560 }
561 else {
b12fe6ab
S
562 #ifdef DISABLE_SPACE_CADET_ROLLOVER
563 if (get_mods() & MOD_BIT(KC_LSFT)) {
564 shift_interrupted[0] = true;
565 shift_interrupted[1] = true;
566 }
567 #endif
de52bd5d 568 if (!shift_interrupted[1] && timer_elapsed(scs_timer[1]) < TAPPING_TERM) {
db32864c
JH
569 register_code(RSPC_KEY);
570 unregister_code(RSPC_KEY);
571 }
76076db7 572 unregister_mods(MOD_BIT(KC_RSFT));
db32864c
JH
573 }
574 return false;
db32864c 575 }
8a1e6560
ZR
576
577 case KC_SFTENT: {
578 if (record->event.pressed) {
579 shift_interrupted[1] = false;
580 scs_timer[1] = timer_read ();
581 register_mods(MOD_BIT(KC_RSFT));
582 }
583 else if (!shift_interrupted[1] && timer_elapsed(scs_timer[1]) < TAPPING_TERM) {
584 unregister_mods(MOD_BIT(KC_RSFT));
585 register_code(SFTENT_KEY);
586 unregister_code(SFTENT_KEY);
587 }
588 else {
589 unregister_mods(MOD_BIT(KC_RSFT));
590 }
591 return false;
592 }
593
98316ef0 594 case GRAVE_ESC: {
98316ef0 595 uint8_t shifted = get_mods() & ((MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT)
596 |MOD_BIT(KC_LGUI)|MOD_BIT(KC_RGUI)));
b4be711a 597
0b54e7f5 598#ifdef GRAVE_ESC_ALT_OVERRIDE
599 // if ALT is pressed, ESC is always sent
600 // this is handy for the cmd+opt+esc shortcut on macOS, among other things.
601 if (get_mods() & (MOD_BIT(KC_LALT) | MOD_BIT(KC_RALT))) {
602 shifted = 0;
603 }
604#endif
605
897ceac2 606#ifdef GRAVE_ESC_CTRL_OVERRIDE
0b54e7f5 607 // if CTRL is pressed, ESC is always sent
188ed682 608 // this is handy for the ctrl+shift+esc shortcut on windows, among other things.
0b54e7f5 609 if (get_mods() & (MOD_BIT(KC_LCTL) | MOD_BIT(KC_RCTL))) {
897ceac2 610 shifted = 0;
0b54e7f5 611 }
612#endif
613
614#ifdef GRAVE_ESC_GUI_OVERRIDE
615 // if GUI is pressed, ESC is always sent
616 if (get_mods() & (MOD_BIT(KC_LGUI) | MOD_BIT(KC_RGUI))) {
617 shifted = 0;
618 }
619#endif
620
621#ifdef GRAVE_ESC_SHIFT_OVERRIDE
622 // if SHIFT is pressed, ESC is always sent
623 if (get_mods() & (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) {
624 shifted = 0;
625 }
897ceac2 626#endif
98316ef0 627
b4be711a
BG
628 if (record->event.pressed) {
629 grave_esc_was_shifted = shifted;
630 add_key(shifted ? KC_GRAVE : KC_ESCAPE);
631 }
632 else {
633 del_key(grave_esc_was_shifted ? KC_GRAVE : KC_ESCAPE);
634 }
635
636 send_keyboard_report();
4931510a 637 return false;
98316ef0 638 }
4931510a
BG
639
640#if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_BREATHING)
641 case BL_BRTG: {
642 if (record->event.pressed)
643 breathing_toggle();
644 return false;
645 }
646#endif
647
12370259 648 default: {
db32864c
JH
649 shift_interrupted[0] = true;
650 shift_interrupted[1] = true;
651 break;
652 }
12370259
EZ
653 }
654
1a8c0dd2
EZ
655 return process_action_kb(record);
656}
657
48ff9358 658__attribute__ ((weak))
fdc2e805 659const bool ascii_to_shift_lut[0x80] PROGMEM = {
794aed37
ET
660 0, 0, 0, 0, 0, 0, 0, 0,
661 0, 0, 0, 0, 0, 0, 0, 0,
662 0, 0, 0, 0, 0, 0, 0, 0,
663 0, 0, 0, 0, 0, 0, 0, 0,
664 0, 1, 1, 1, 1, 1, 1, 0,
665 1, 1, 1, 1, 0, 0, 0, 0,
666 0, 0, 0, 0, 0, 0, 0, 0,
667 0, 0, 1, 0, 1, 0, 1, 1,
668 1, 1, 1, 1, 1, 1, 1, 1,
669 1, 1, 1, 1, 1, 1, 1, 1,
670 1, 1, 1, 1, 1, 1, 1, 1,
671 1, 1, 1, 0, 0, 0, 1, 1,
672 0, 0, 0, 0, 0, 0, 0, 0,
673 0, 0, 0, 0, 0, 0, 0, 0,
674 0, 0, 0, 0, 0, 0, 0, 0,
675 0, 0, 0, 1, 1, 1, 1, 0
1c9f33c0
JH
676};
677
48ff9358 678__attribute__ ((weak))
fdc2e805 679const uint8_t ascii_to_keycode_lut[0x80] PROGMEM = {
794aed37
ET
680 0, 0, 0, 0, 0, 0, 0, 0,
681 KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0,
682 0, 0, 0, 0, 0, 0, 0, 0,
683 0, 0, 0, KC_ESC, 0, 0, 0, 0,
684 KC_SPC, KC_1, KC_QUOT, KC_3, KC_4, KC_5, KC_7, KC_QUOT,
685 KC_9, KC_0, KC_8, KC_EQL, KC_COMM, KC_MINS, KC_DOT, KC_SLSH,
686 KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7,
687 KC_8, KC_9, KC_SCLN, KC_SCLN, KC_COMM, KC_EQL, KC_DOT, KC_SLSH,
688 KC_2, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
689 KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O,
690 KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
691 KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_6, KC_MINS,
692 KC_GRV, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
693 KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O,
694 KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
695 KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL
1c9f33c0
JH
696};
697
5dae013f 698void send_string(const char *str) {
fdc2e805
SH
699 send_string_with_delay(str, 0);
700}
701
7ad924ba
JH
702void send_string_P(const char *str) {
703 send_string_with_delay_P(str, 0);
704}
705
fdc2e805 706void send_string_with_delay(const char *str, uint8_t interval) {
5dae013f 707 while (1) {
7ad924ba 708 char ascii_code = *str;
5dae013f 709 if (!ascii_code) break;
7ad924ba
JH
710 if (ascii_code == 1) {
711 // tap
712 uint8_t keycode = *(++str);
713 register_code(keycode);
714 unregister_code(keycode);
715 } else if (ascii_code == 2) {
716 // down
717 uint8_t keycode = *(++str);
718 register_code(keycode);
719 } else if (ascii_code == 3) {
720 // up
721 uint8_t keycode = *(++str);
722 unregister_code(keycode);
723 } else {
724 send_char(ascii_code);
5dae013f 725 }
7ad924ba
JH
726 ++str;
727 // interval
728 { uint8_t ms = interval; while (ms--) wait_ms(1); }
729 }
730}
731
732void send_string_with_delay_P(const char *str, uint8_t interval) {
733 while (1) {
734 char ascii_code = pgm_read_byte(str);
735 if (!ascii_code) break;
736 if (ascii_code == 1) {
737 // tap
738 uint8_t keycode = pgm_read_byte(++str);
739 register_code(keycode);
740 unregister_code(keycode);
741 } else if (ascii_code == 2) {
742 // down
743 uint8_t keycode = pgm_read_byte(++str);
744 register_code(keycode);
745 } else if (ascii_code == 3) {
746 // up
747 uint8_t keycode = pgm_read_byte(++str);
748 unregister_code(keycode);
749 } else {
750 send_char(ascii_code);
5dae013f 751 }
752 ++str;
fdc2e805
SH
753 // interval
754 { uint8_t ms = interval; while (ms--) wait_ms(1); }
5dae013f 755 }
756}
757
7ad924ba
JH
758void send_char(char ascii_code) {
759 uint8_t keycode;
760 keycode = pgm_read_byte(&ascii_to_keycode_lut[(uint8_t)ascii_code]);
761 if (pgm_read_byte(&ascii_to_shift_lut[(uint8_t)ascii_code])) {
762 register_code(KC_LSFT);
763 register_code(keycode);
764 unregister_code(keycode);
765 unregister_code(KC_LSFT);
766 } else {
767 register_code(keycode);
768 unregister_code(keycode);
769 }
770}
771
6a3c6677 772void set_single_persistent_default_layer(uint8_t default_layer) {
6895c451 773 #if defined(AUDIO_ENABLE) && defined(DEFAULT_LAYER_SONGS)
6a3c6677
JH
774 PLAY_SONG(default_layer_songs[default_layer]);
775 #endif
776 eeconfig_update_default_layer(1U<<default_layer);
777 default_layer_set(1U<<default_layer);
778}
779
db32864c
JH
780void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) {
781 if (IS_LAYER_ON(layer1) && IS_LAYER_ON(layer2)) {
782 layer_on(layer3);
783 } else {
784 layer_off(layer3);
785 }
786}
1c9f33c0 787
197f152d 788void tap_random_base64(void) {
60fd885a
JH
789 #if defined(__AVR_ATmega32U4__)
790 uint8_t key = (TCNT0 + TCNT1 + TCNT3 + TCNT4) % 64;
791 #else
792 uint8_t key = rand() % 64;
793 #endif
197f152d
JH
794 switch (key) {
795 case 0 ... 25:
796 register_code(KC_LSFT);
797 register_code(key + KC_A);
798 unregister_code(key + KC_A);
799 unregister_code(KC_LSFT);
800 break;
801 case 26 ... 51:
802 register_code(key - 26 + KC_A);
803 unregister_code(key - 26 + KC_A);
804 break;
805 case 52:
806 register_code(KC_0);
807 unregister_code(KC_0);
808 break;
809 case 53 ... 61:
810 register_code(key - 53 + KC_1);
811 unregister_code(key - 53 + KC_1);
812 break;
813 case 62:
814 register_code(KC_LSFT);
815 register_code(KC_EQL);
816 unregister_code(KC_EQL);
817 unregister_code(KC_LSFT);
818 break;
819 case 63:
820 register_code(KC_SLSH);
821 unregister_code(KC_SLSH);
822 break;
823 }
824}
825
1a8c0dd2 826void matrix_init_quantum() {
13bb6b4b
JH
827 #ifdef BACKLIGHT_ENABLE
828 backlight_init_ports();
829 #endif
6a3c6677
JH
830 #ifdef AUDIO_ENABLE
831 audio_init();
832 #endif
1a8c0dd2
EZ
833 matrix_init_kb();
834}
835
836void matrix_scan_quantum() {
6835ae82 837 #if defined(AUDIO_ENABLE)
65faab3b 838 matrix_scan_music();
15719f35 839 #endif
fde477a9 840
65faab3b
JH
841 #ifdef TAP_DANCE_ENABLE
842 matrix_scan_tap_dance();
843 #endif
b6bf4e0d
OP
844
845 #ifdef COMBO_ENABLE
846 matrix_scan_combo();
847 #endif
848
8d0fdf10
JH
849 #if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN)
850 backlight_task();
851 #endif
852
1a8c0dd2 853 matrix_scan_kb();
0428214b 854}
13bb6b4b 855
13bb6b4b
JH
856#if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN)
857
858static const uint8_t backlight_pin = BACKLIGHT_PIN;
859
4931510a 860// depending on the pin, we use a different output compare unit
13bb6b4b
JH
861#if BACKLIGHT_PIN == B7
862# define COM1x1 COM1C1
863# define OCR1x OCR1C
864#elif BACKLIGHT_PIN == B6
865# define COM1x1 COM1B1
866# define OCR1x OCR1B
867#elif BACKLIGHT_PIN == B5
868# define COM1x1 COM1A1
869# define OCR1x OCR1A
870#else
4931510a 871# define NO_HARDWARE_PWM
b4e30d39
JH
872#endif
873
874#ifndef BACKLIGHT_ON_STATE
875#define BACKLIGHT_ON_STATE 0
13bb6b4b
JH
876#endif
877
4931510a
BG
878#ifdef NO_HARDWARE_PWM // pwm through software
879
13bb6b4b
JH
880__attribute__ ((weak))
881void backlight_init_ports(void)
882{
b4e30d39 883 // Setup backlight pin as output and output to on state.
13bb6b4b
JH
884 // DDRx |= n
885 _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF);
b4e30d39
JH
886 #if BACKLIGHT_ON_STATE == 0
887 // PORTx &= ~n
888 _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
889 #else
890 // PORTx |= n
891 _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
892 #endif
13bb6b4b
JH
893}
894
895__attribute__ ((weak))
4931510a 896void backlight_set(uint8_t level) {}
13bb6b4b 897
8d0fdf10
JH
898uint8_t backlight_tick = 0;
899
365b8635 900#ifndef BACKLIGHT_CUSTOM_DRIVER
8d0fdf10 901void backlight_task(void) {
4931510a 902 if ((0xFFFF >> ((BACKLIGHT_LEVELS - get_backlight_level()) * ((BACKLIGHT_LEVELS + 1) / 2))) & (1 << backlight_tick)) {
8d0fdf10
JH
903 #if BACKLIGHT_ON_STATE == 0
904 // PORTx &= ~n
905 _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
906 #else
907 // PORTx |= n
908 _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
909 #endif
910 } else {
911 #if BACKLIGHT_ON_STATE == 0
912 // PORTx |= n
913 _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
914 #else
915 // PORTx &= ~n
916 _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
917 #endif
918 }
91c133f4 919 backlight_tick = (backlight_tick + 1) % 16;
8d0fdf10 920}
365b8635 921#endif
13bb6b4b
JH
922
923#ifdef BACKLIGHT_BREATHING
365b8635
KA
924 #ifndef BACKLIGHT_CUSTOM_DRIVER
925 #error "Backlight breathing only available with hardware PWM. Please disable."
926 #endif
4931510a 927#endif
13bb6b4b 928
4931510a
BG
929#else // pwm through timer
930
931#define TIMER_TOP 0xFFFFU
932
933// See http://jared.geek.nz/2013/feb/linear-led-pwm
934static uint16_t cie_lightness(uint16_t v) {
935 if (v <= 5243) // if below 8% of max
936 return v / 9; // same as dividing by 900%
937 else {
938 uint32_t y = (((uint32_t) v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare
939 // to get a useful result with integer division, we shift left in the expression above
940 // and revert what we've done again after squaring.
941 y = y * y * y >> 8;
942 if (y > 0xFFFFUL) // prevent overflow
943 return 0xFFFFU;
944 else
945 return (uint16_t) y;
946 }
947}
948
949// range for val is [0..TIMER_TOP]. PWM pin is high while the timer count is below val.
950static inline void set_pwm(uint16_t val) {
951 OCR1x = val;
952}
953
365b8635 954#ifndef BACKLIGHT_CUSTOM_DRIVER
4931510a
BG
955__attribute__ ((weak))
956void backlight_set(uint8_t level) {
957 if (level > BACKLIGHT_LEVELS)
958 level = BACKLIGHT_LEVELS;
959
960 if (level == 0) {
961 // Turn off PWM control on backlight pin
962 TCCR1A &= ~(_BV(COM1x1));
963 } else {
964 // Turn on PWM control of backlight pin
965 TCCR1A |= _BV(COM1x1);
966 }
967 // Set the brightness
968 set_pwm(cie_lightness(TIMER_TOP * (uint32_t)level / BACKLIGHT_LEVELS));
969}
970
971void backlight_task(void) {}
365b8635 972#endif // BACKLIGHT_CUSTOM_DRIVER
4931510a
BG
973
974#ifdef BACKLIGHT_BREATHING
b7c76fda 975
13bb6b4b
JH
976#define BREATHING_NO_HALT 0
977#define BREATHING_HALT_OFF 1
978#define BREATHING_HALT_ON 2
4931510a 979#define BREATHING_STEPS 128
13bb6b4b 980
4931510a
BG
981static uint8_t breathing_period = BREATHING_PERIOD;
982static uint8_t breathing_halt = BREATHING_NO_HALT;
983static uint16_t breathing_counter = 0;
13bb6b4b 984
4931510a
BG
985bool is_breathing(void) {
986 return !!(TIMSK1 & _BV(TOIE1));
987}
13bb6b4b 988
4931510a
BG
989#define breathing_interrupt_enable() do {TIMSK1 |= _BV(TOIE1);} while (0)
990#define breathing_interrupt_disable() do {TIMSK1 &= ~_BV(TOIE1);} while (0)
991#define breathing_min() do {breathing_counter = 0;} while (0)
992#define breathing_max() do {breathing_counter = breathing_period * 244 / 2;} while (0)
13bb6b4b 993
4931510a
BG
994void breathing_enable(void)
995{
996 breathing_counter = 0;
997 breathing_halt = BREATHING_NO_HALT;
998 breathing_interrupt_enable();
13bb6b4b
JH
999}
1000
1001void breathing_pulse(void)
1002{
1003 if (get_backlight_level() == 0)
4931510a 1004 breathing_min();
13bb6b4b 1005 else
4931510a 1006 breathing_max();
13bb6b4b 1007 breathing_halt = BREATHING_HALT_ON;
4931510a 1008 breathing_interrupt_enable();
13bb6b4b
JH
1009}
1010
1011void breathing_disable(void)
1012{
4931510a
BG
1013 breathing_interrupt_disable();
1014 // Restore backlight level
13bb6b4b
JH
1015 backlight_set(get_backlight_level());
1016}
1017
1018void breathing_self_disable(void)
1019{
4931510a
BG
1020 if (get_backlight_level() == 0)
1021 breathing_halt = BREATHING_HALT_OFF;
1022 else
1023 breathing_halt = BREATHING_HALT_ON;
13bb6b4b
JH
1024}
1025
4931510a
BG
1026void breathing_toggle(void) {
1027 if (is_breathing())
1028 breathing_disable();
1029 else
1030 breathing_enable();
13bb6b4b
JH
1031}
1032
4931510a 1033void breathing_period_set(uint8_t value)
13bb6b4b 1034{
4931510a
BG
1035 if (!value)
1036 value = 1;
1037 breathing_period = value;
13bb6b4b
JH
1038}
1039
4931510a
BG
1040void breathing_period_default(void) {
1041 breathing_period_set(BREATHING_PERIOD);
13bb6b4b
JH
1042}
1043
4931510a 1044void breathing_period_inc(void)
13bb6b4b 1045{
4931510a 1046 breathing_period_set(breathing_period+1);
13bb6b4b
JH
1047}
1048
4931510a 1049void breathing_period_dec(void)
13bb6b4b 1050{
4931510a 1051 breathing_period_set(breathing_period-1);
13bb6b4b
JH
1052}
1053
4931510a
BG
1054/* To generate breathing curve in python:
1055 * from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)]
1056 */
1057static 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};
13bb6b4b 1058
4931510a
BG
1059// Use this before the cie_lightness function.
1060static inline uint16_t scale_backlight(uint16_t v) {
1061 return v / BACKLIGHT_LEVELS * get_backlight_level();
13bb6b4b
JH
1062}
1063
4931510a
BG
1064/* Assuming a 16MHz CPU clock and a timer that resets at 64k (ICR1), the following interrupt handler will run
1065 * about 244 times per second.
1066 */
1067ISR(TIMER1_OVF_vect)
13bb6b4b 1068{
4931510a
BG
1069 uint16_t interval = (uint16_t) breathing_period * 244 / BREATHING_STEPS;
1070 // resetting after one period to prevent ugly reset at overflow.
1071 breathing_counter = (breathing_counter + 1) % (breathing_period * 244);
1072 uint8_t index = breathing_counter / interval % BREATHING_STEPS;
1073
1074 if (((breathing_halt == BREATHING_HALT_ON) && (index == BREATHING_STEPS / 2)) ||
1075 ((breathing_halt == BREATHING_HALT_OFF) && (index == BREATHING_STEPS - 1)))
1076 {
1077 breathing_interrupt_disable();
1078 }
13bb6b4b 1079
4931510a 1080 set_pwm(cie_lightness(scale_backlight((uint16_t) pgm_read_byte(&breathing_table[index]) * 0x0101U)));
13bb6b4b
JH
1081}
1082
4931510a 1083#endif // BACKLIGHT_BREATHING
13bb6b4b 1084
4931510a
BG
1085__attribute__ ((weak))
1086void backlight_init_ports(void)
13bb6b4b 1087{
4931510a
BG
1088 // Setup backlight pin as output and output to on state.
1089 // DDRx |= n
1090 _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF);
1091 #if BACKLIGHT_ON_STATE == 0
1092 // PORTx &= ~n
1093 _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
1094 #else
1095 // PORTx |= n
1096 _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
1097 #endif
1098 // I could write a wall of text here to explain... but TL;DW
1099 // Go read the ATmega32u4 datasheet.
1100 // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
1101
1102 // Pin PB7 = OCR1C (Timer 1, Channel C)
1103 // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
1104 // (i.e. start high, go low when counter matches.)
1105 // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
1106 // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
1107
1108 /*
1109 14.8.3:
1110 "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 [..]."
1111 "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)."
1112 */
1113
1114 TCCR1A = _BV(COM1x1) | _BV(WGM11); // = 0b00001010;
1115 TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
1116 // Use full 16-bit resolution. Counter counts to ICR1 before reset to 0.
1117 ICR1 = TIMER_TOP;
13bb6b4b 1118
4931510a
BG
1119 backlight_init();
1120 #ifdef BACKLIGHT_BREATHING
1121 breathing_enable();
1122 #endif
13bb6b4b
JH
1123}
1124
4931510a 1125#endif // NO_HARDWARE_PWM
13bb6b4b
JH
1126
1127#else // backlight
1128
1129__attribute__ ((weak))
4931510a 1130void backlight_init_ports(void) {}
13bb6b4b
JH
1131
1132__attribute__ ((weak))
4931510a 1133void backlight_set(uint8_t level) {}
13bb6b4b
JH
1134
1135#endif // backlight
1136
1137
664c0a03
JH
1138// Functions for spitting out values
1139//
1140
1141void send_dword(uint32_t number) { // this might not actually work
1142 uint16_t word = (number >> 16);
1143 send_word(word);
1144 send_word(number & 0xFFFFUL);
1145}
1146
1147void send_word(uint16_t number) {
1148 uint8_t byte = number >> 8;
1149 send_byte(byte);
1150 send_byte(number & 0xFF);
1151}
1152
1153void send_byte(uint8_t number) {
1154 uint8_t nibble = number >> 4;
1155 send_nibble(nibble);
1156 send_nibble(number & 0xF);
1157}
1158
1159void send_nibble(uint8_t number) {
1160 switch (number) {
1161 case 0:
1162 register_code(KC_0);
1163 unregister_code(KC_0);
1164 break;
1165 case 1 ... 9:
1166 register_code(KC_1 + (number - 1));
1167 unregister_code(KC_1 + (number - 1));
1168 break;
1169 case 0xA ... 0xF:
1170 register_code(KC_A + (number - 0xA));
1171 unregister_code(KC_A + (number - 0xA));
1172 break;
1173 }
1174}
1175
cbabb4d4
JH
1176
1177__attribute__((weak))
1178uint16_t hex_to_keycode(uint8_t hex)
1179{
b669d115 1180 hex = hex & 0xF;
cbabb4d4
JH
1181 if (hex == 0x0) {
1182 return KC_0;
1183 } else if (hex < 0xA) {
1184 return KC_1 + (hex - 0x1);
1185 } else {
1186 return KC_A + (hex - 0xA);
1187 }
1188}
1189
7edac212
JH
1190void api_send_unicode(uint32_t unicode) {
1191#ifdef API_ENABLE
cefa8468
JH
1192 uint8_t chunk[4];
1193 dword_to_bytes(unicode, chunk);
1194 MT_SEND_DATA(DT_UNICODE, chunk, 5);
7edac212 1195#endif
cefa8468 1196}
13bb6b4b
JH
1197
1198__attribute__ ((weak))
1199void led_set_user(uint8_t usb_led) {
1200
1201}
1202
1203__attribute__ ((weak))
1204void led_set_kb(uint8_t usb_led) {
1205 led_set_user(usb_led);
1206}
1207
1208__attribute__ ((weak))
1209void led_init_ports(void)
1210{
1211
1212}
1213
1214__attribute__ ((weak))
1215void led_set(uint8_t usb_led)
1216{
1217
1218 // Example LED Code
1219 //
1220 // // Using PE6 Caps Lock LED
1221 // if (usb_led & (1<<USB_LED_CAPS_LOCK))
1222 // {
1223 // // Output high.
1224 // DDRE |= (1<<6);
1225 // PORTE |= (1<<6);
1226 // }
1227 // else
1228 // {
1229 // // Output low.
1230 // DDRE &= ~(1<<6);
1231 // PORTE &= ~(1<<6);
1232 // }
1233
1234 led_set_kb(usb_led);
1235}
1236
1237
287eb7ad 1238//------------------------------------------------------------------------------
794aed37 1239// Override these functions in your keymap file to play different tunes on
287eb7ad
JH
1240// different events such as startup and bootloader jump
1241
1242__attribute__ ((weak))
1243void startup_user() {}
1244
1245__attribute__ ((weak))
1246void shutdown_user() {}
1247
12370259 1248//------------------------------------------------------------------------------