Implemented basic key combination feature
[jackhill/qmk/firmware.git] / quantum / quantum.c
CommitLineData
1a8c0dd2
EZ
1#include "quantum.h"
2
74a1f007
GN
3#ifndef TAPPING_TERM
4#define TAPPING_TERM 200
5#endif
6
0d28787c
GN
7static void do_code16 (uint16_t code, void (*f) (uint8_t)) {
8 switch (code) {
9 case QK_MODS ... QK_MODS_MAX:
10 break;
11 default:
12 return;
13 }
14
15 if (code & QK_LCTL)
16 f(KC_LCTL);
17 if (code & QK_LSFT)
18 f(KC_LSFT);
19 if (code & QK_LALT)
20 f(KC_LALT);
21 if (code & QK_LGUI)
22 f(KC_LGUI);
23
24 if (code & QK_RCTL)
25 f(KC_RCTL);
26 if (code & QK_RSFT)
27 f(KC_RSFT);
28 if (code & QK_RALT)
29 f(KC_RALT);
30 if (code & QK_RGUI)
31 f(KC_RGUI);
32}
33
34void register_code16 (uint16_t code) {
35 do_code16 (code, register_code);
36 register_code (code);
37}
38
39void unregister_code16 (uint16_t code) {
40 unregister_code (code);
41 do_code16 (code, unregister_code);
42}
43
1a8c0dd2 44__attribute__ ((weak))
1a8c0dd2
EZ
45bool process_action_kb(keyrecord_t *record) {
46 return true;
47}
48
17977a7e
JH
49__attribute__ ((weak))
50bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
51 return process_record_user(keycode, record);
52}
53
54__attribute__ ((weak))
55bool process_record_user(uint16_t keycode, keyrecord_t *record) {
56 return true;
57}
58
a28a6e5b
PV
59void reset_keyboard(void) {
60 clear_keyboard();
61#ifdef AUDIO_ENABLE
62 stop_all_notes();
63 shutdown_user();
64#endif
65 wait_ms(250);
66#ifdef CATERINA_BOOTLOADER
67 *(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific
68#endif
69 bootloader_jump();
70}
71
b70248fa
JH
72// Shift / paren setup
73
74#ifndef LSPO_KEY
75 #define LSPO_KEY KC_9
76#endif
77#ifndef RSPC_KEY
78 #define RSPC_KEY KC_0
79#endif
80
8bc69afc 81static bool shift_interrupted[2] = {0, 0};
ffa5b1e7 82static uint16_t scs_timer = 0;
12370259 83
bf5c2cce 84bool process_record_quantum(keyrecord_t *record) {
1a8c0dd2
EZ
85
86 /* This gets the keycode from the key pressed */
87 keypos_t key = record->event.key;
88 uint16_t keycode;
89
90 #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
644c8c79
WS
91 /* TODO: Use store_or_get_action() or a similar function. */
92 if (!disable_action_cache) {
93 uint8_t layer;
1a8c0dd2 94
644c8c79
WS
95 if (record->event.pressed) {
96 layer = layer_switch_get_layer(key);
97 update_source_layers_cache(key, layer);
98 } else {
99 layer = read_source_layers_cache(key);
100 }
101 keycode = keymap_key_to_keycode(layer, key);
102 } else
1a8c0dd2 103 #endif
644c8c79 104 keycode = keymap_key_to_keycode(layer_switch_get_layer(key), key);
1a8c0dd2 105
bf5c2cce
JH
106 // This is how you use actions here
107 // if (keycode == KC_LEAD) {
108 // action_t action;
109 // action.code = ACTION_DEFAULT_LAYER_SET(0);
110 // process_action(record, action);
111 // return false;
112 // }
113
65faab3b
JH
114 if (!(
115 process_record_kb(keycode, record) &&
eac8fa79
OP
116 #ifdef COMBO_ENABLE
117 process_combo(keycode, record) &&
118 #endif
fde477a9 119 #ifdef MIDI_ENABLE
65faab3b 120 process_midi(keycode, record) &&
fde477a9 121 #endif
1a8c0dd2 122 #ifdef AUDIO_ENABLE
65faab3b 123 process_music(keycode, record) &&
1a8c0dd2 124 #endif
65faab3b
JH
125 #ifdef TAP_DANCE_ENABLE
126 process_tap_dance(keycode, record) &&
127 #endif
128 #ifndef DISABLE_LEADER
129 process_leader(keycode, record) &&
130 #endif
131 #ifndef DISABLE_CHORDING
132 process_chording(keycode, record) &&
133 #endif
134 #ifdef UNICODE_ENABLE
135 process_unicode(keycode, record) &&
857aa5be
GN
136 #endif
137 #ifdef UCIS_ENABLE
138 process_ucis(keycode, record) &&
5f91fb41
JH
139 #endif
140 #ifdef PRINTING_ENABLE
141 process_printer(keycode, record) &&
e9f74875 142 #endif
5b2e455d
PIN
143 #ifdef UNICODEMAP_ENABLE
144 process_unicode_map(keycode, record) &&
65faab3b
JH
145 #endif
146 true)) {
147 return false;
b732b79b
JH
148 }
149
b70248fa
JH
150 // Shift / paren setup
151
12370259 152 switch(keycode) {
db32864c
JH
153 case RESET:
154 if (record->event.pressed) {
a28a6e5b 155 reset_keyboard();
db32864c 156 }
f7a86822 157 return false;
db32864c
JH
158 break;
159 case DEBUG:
160 if (record->event.pressed) {
161 print("\nDEBUG: enabled.\n");
162 debug_enable = true;
db32864c 163 }
f7a86822 164 return false;
db32864c 165 break;
50c68658
T
166 #ifdef RGBLIGHT_ENABLE
167 case RGB_TOG:
168 if (record->event.pressed) {
169 rgblight_toggle();
f7a86822
T
170 }
171 return false;
172 break;
50c68658
T
173 case RGB_MOD:
174 if (record->event.pressed) {
175 rgblight_step();
f7a86822
T
176 }
177 return false;
178 break;
50c68658
T
179 case RGB_HUI:
180 if (record->event.pressed) {
181 rgblight_increase_hue();
f7a86822
T
182 }
183 return false;
184 break;
50c68658
T
185 case RGB_HUD:
186 if (record->event.pressed) {
187 rgblight_decrease_hue();
f7a86822
T
188 }
189 return false;
190 break;
50c68658
T
191 case RGB_SAI:
192 if (record->event.pressed) {
193 rgblight_increase_sat();
f7a86822
T
194 }
195 return false;
196 break;
50c68658
T
197 case RGB_SAD:
198 if (record->event.pressed) {
199 rgblight_decrease_sat();
f7a86822
T
200 }
201 return false;
202 break;
50c68658
T
203 case RGB_VAI:
204 if (record->event.pressed) {
205 rgblight_increase_val();
f7a86822
T
206 }
207 return false;
208 break;
50c68658
T
209 case RGB_VAD:
210 if (record->event.pressed) {
211 rgblight_decrease_val();
f7a86822
T
212 }
213 return false;
214 break;
50c68658 215 #endif
558f3ec1 216 case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_NKRO:
db32864c
JH
217 if (record->event.pressed) {
218 // MAGIC actions (BOOTMAGIC without the boot)
219 if (!eeconfig_is_enabled()) {
220 eeconfig_init();
221 }
222 /* keymap config */
223 keymap_config.raw = eeconfig_read_keymap();
558f3ec1
I
224 switch (keycode)
225 {
226 case MAGIC_SWAP_CONTROL_CAPSLOCK:
227 keymap_config.swap_control_capslock = true;
228 break;
229 case MAGIC_CAPSLOCK_TO_CONTROL:
230 keymap_config.capslock_to_control = true;
231 break;
232 case MAGIC_SWAP_LALT_LGUI:
233 keymap_config.swap_lalt_lgui = true;
234 break;
235 case MAGIC_SWAP_RALT_RGUI:
236 keymap_config.swap_ralt_rgui = true;
237 break;
238 case MAGIC_NO_GUI:
239 keymap_config.no_gui = true;
240 break;
241 case MAGIC_SWAP_GRAVE_ESC:
242 keymap_config.swap_grave_esc = true;
243 break;
244 case MAGIC_SWAP_BACKSLASH_BACKSPACE:
245 keymap_config.swap_backslash_backspace = true;
246 break;
247 case MAGIC_HOST_NKRO:
248 keymap_config.nkro = true;
249 break;
250 case MAGIC_SWAP_ALT_GUI:
251 keymap_config.swap_lalt_lgui = true;
252 keymap_config.swap_ralt_rgui = true;
253 break;
254 case MAGIC_UNSWAP_CONTROL_CAPSLOCK:
255 keymap_config.swap_control_capslock = false;
256 break;
257 case MAGIC_UNCAPSLOCK_TO_CONTROL:
258 keymap_config.capslock_to_control = false;
259 break;
260 case MAGIC_UNSWAP_LALT_LGUI:
261 keymap_config.swap_lalt_lgui = false;
262 break;
263 case MAGIC_UNSWAP_RALT_RGUI:
264 keymap_config.swap_ralt_rgui = false;
265 break;
266 case MAGIC_UNNO_GUI:
267 keymap_config.no_gui = false;
268 break;
269 case MAGIC_UNSWAP_GRAVE_ESC:
270 keymap_config.swap_grave_esc = false;
271 break;
272 case MAGIC_UNSWAP_BACKSLASH_BACKSPACE:
273 keymap_config.swap_backslash_backspace = false;
274 break;
275 case MAGIC_UNHOST_NKRO:
276 keymap_config.nkro = false;
277 break;
278 case MAGIC_UNSWAP_ALT_GUI:
279 keymap_config.swap_lalt_lgui = false;
280 keymap_config.swap_ralt_rgui = false;
281 break;
282 case MAGIC_TOGGLE_NKRO:
283 keymap_config.nkro = !keymap_config.nkro;
284 break;
285 default:
286 break;
db32864c
JH
287 }
288 eeconfig_update_keymap(keymap_config.raw);
558f3ec1
I
289 clear_keyboard(); // clear to prevent stuck keys
290
db32864c
JH
291 return false;
292 }
293 break;
12370259 294 case KC_LSPO: {
db32864c
JH
295 if (record->event.pressed) {
296 shift_interrupted[0] = false;
ffa5b1e7 297 scs_timer = timer_read ();
76076db7 298 register_mods(MOD_BIT(KC_LSFT));
db32864c
JH
299 }
300 else {
b12fe6ab
S
301 #ifdef DISABLE_SPACE_CADET_ROLLOVER
302 if (get_mods() & MOD_BIT(KC_RSFT)) {
303 shift_interrupted[0] = true;
304 shift_interrupted[1] = true;
305 }
306 #endif
ffa5b1e7 307 if (!shift_interrupted[0] && timer_elapsed(scs_timer) < TAPPING_TERM) {
db32864c
JH
308 register_code(LSPO_KEY);
309 unregister_code(LSPO_KEY);
310 }
76076db7 311 unregister_mods(MOD_BIT(KC_LSFT));
db32864c
JH
312 }
313 return false;
558f3ec1 314 // break;
db32864c 315 }
12370259
EZ
316
317 case KC_RSPC: {
db32864c
JH
318 if (record->event.pressed) {
319 shift_interrupted[1] = false;
ffa5b1e7 320 scs_timer = timer_read ();
76076db7 321 register_mods(MOD_BIT(KC_RSFT));
db32864c
JH
322 }
323 else {
b12fe6ab
S
324 #ifdef DISABLE_SPACE_CADET_ROLLOVER
325 if (get_mods() & MOD_BIT(KC_LSFT)) {
326 shift_interrupted[0] = true;
327 shift_interrupted[1] = true;
328 }
329 #endif
ffa5b1e7 330 if (!shift_interrupted[1] && timer_elapsed(scs_timer) < TAPPING_TERM) {
db32864c
JH
331 register_code(RSPC_KEY);
332 unregister_code(RSPC_KEY);
333 }
76076db7 334 unregister_mods(MOD_BIT(KC_RSFT));
db32864c
JH
335 }
336 return false;
558f3ec1 337 // break;
db32864c 338 }
12370259 339 default: {
db32864c
JH
340 shift_interrupted[0] = true;
341 shift_interrupted[1] = true;
342 break;
343 }
12370259
EZ
344 }
345
1a8c0dd2
EZ
346 return process_action_kb(record);
347}
348
794aed37
ET
349const bool ascii_to_qwerty_shift_lut[0x80] PROGMEM = {
350 0, 0, 0, 0, 0, 0, 0, 0,
351 0, 0, 0, 0, 0, 0, 0, 0,
352 0, 0, 0, 0, 0, 0, 0, 0,
353 0, 0, 0, 0, 0, 0, 0, 0,
354 0, 1, 1, 1, 1, 1, 1, 0,
355 1, 1, 1, 1, 0, 0, 0, 0,
356 0, 0, 0, 0, 0, 0, 0, 0,
357 0, 0, 1, 0, 1, 0, 1, 1,
358 1, 1, 1, 1, 1, 1, 1, 1,
359 1, 1, 1, 1, 1, 1, 1, 1,
360 1, 1, 1, 1, 1, 1, 1, 1,
361 1, 1, 1, 0, 0, 0, 1, 1,
362 0, 0, 0, 0, 0, 0, 0, 0,
363 0, 0, 0, 0, 0, 0, 0, 0,
364 0, 0, 0, 0, 0, 0, 0, 0,
365 0, 0, 0, 1, 1, 1, 1, 0
1c9f33c0
JH
366};
367
794aed37
ET
368const uint8_t ascii_to_qwerty_keycode_lut[0x80] PROGMEM = {
369 0, 0, 0, 0, 0, 0, 0, 0,
370 KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0,
371 0, 0, 0, 0, 0, 0, 0, 0,
372 0, 0, 0, KC_ESC, 0, 0, 0, 0,
373 KC_SPC, KC_1, KC_QUOT, KC_3, KC_4, KC_5, KC_7, KC_QUOT,
374 KC_9, KC_0, KC_8, KC_EQL, KC_COMM, KC_MINS, KC_DOT, KC_SLSH,
375 KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7,
376 KC_8, KC_9, KC_SCLN, KC_SCLN, KC_COMM, KC_EQL, KC_DOT, KC_SLSH,
377 KC_2, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
378 KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O,
379 KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
380 KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_6, KC_MINS,
381 KC_GRV, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
382 KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O,
383 KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
384 KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL
1c9f33c0
JH
385};
386
794aed37
ET
387/* for users whose OSes are set to Colemak */
388#if 0
389#include "keymap_colemak.h"
390
391const bool ascii_to_colemak_shift_lut[0x80] PROGMEM = {
392 0, 0, 0, 0, 0, 0, 0, 0,
393 0, 0, 0, 0, 0, 0, 0, 0,
394 0, 0, 0, 0, 0, 0, 0, 0,
395 0, 0, 0, 0, 0, 0, 0, 0,
396 0, 1, 1, 1, 1, 1, 1, 0,
397 1, 1, 1, 1, 0, 0, 0, 0,
398 0, 0, 0, 0, 0, 0, 0, 0,
399 0, 0, 1, 0, 1, 0, 1, 1,
400 1, 1, 1, 1, 1, 1, 1, 1,
401 1, 1, 1, 1, 1, 1, 1, 1,
402 1, 1, 1, 1, 1, 1, 1, 1,
403 1, 1, 1, 0, 0, 0, 1, 1,
404 0, 0, 0, 0, 0, 0, 0, 0,
405 0, 0, 0, 0, 0, 0, 0, 0,
406 0, 0, 0, 0, 0, 0, 0, 0,
407 0, 0, 0, 1, 1, 1, 1, 0
408};
409
410const uint8_t ascii_to_colemak_keycode_lut[0x80] PROGMEM = {
411 0, 0, 0, 0, 0, 0, 0, 0,
412 KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0,
413 0, 0, 0, 0, 0, 0, 0, 0,
414 0, 0, 0, KC_ESC, 0, 0, 0, 0,
415 KC_SPC, KC_1, KC_QUOT, KC_3, KC_4, KC_5, KC_7, KC_QUOT,
416 KC_9, KC_0, KC_8, KC_EQL, KC_COMM, KC_MINS, KC_DOT, KC_SLSH,
417 KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7,
418 KC_8, KC_9, CM_SCLN, CM_SCLN, KC_COMM, KC_EQL, KC_DOT, KC_SLSH,
419 KC_2, CM_A, CM_B, CM_C, CM_D, CM_E, CM_F, CM_G,
420 CM_H, CM_I, CM_J, CM_K, CM_L, CM_M, CM_N, CM_O,
421 CM_P, CM_Q, CM_R, CM_S, CM_T, CM_U, CM_V, CM_W,
422 CM_X, CM_Y, CM_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_6, KC_MINS,
423 KC_GRV, CM_A, CM_B, CM_C, CM_D, CM_E, CM_F, CM_G,
424 CM_H, CM_I, CM_J, CM_K, CM_L, CM_M, CM_N, CM_O,
425 CM_P, CM_Q, CM_R, CM_S, CM_T, CM_U, CM_V, CM_W,
426 CM_X, CM_Y, CM_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL
427};
428
429#endif
430
431void send_string(const char *str) {
432 while (1) {
433 uint8_t keycode;
434 uint8_t ascii_code = pgm_read_byte(str);
435 if (!ascii_code) break;
436 keycode = pgm_read_byte(&ascii_to_qwerty_keycode_lut[ascii_code]);
437 if (pgm_read_byte(&ascii_to_qwerty_shift_lut[ascii_code])) {
438 register_code(KC_LSFT);
439 register_code(keycode);
440 unregister_code(keycode);
441 unregister_code(KC_LSFT);
442 }
443 else {
444 register_code(keycode);
445 unregister_code(keycode);
446 }
447 ++str;
1c9f33c0 448 }
1c9f33c0
JH
449}
450
db32864c
JH
451void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) {
452 if (IS_LAYER_ON(layer1) && IS_LAYER_ON(layer2)) {
453 layer_on(layer3);
454 } else {
455 layer_off(layer3);
456 }
457}
1c9f33c0 458
197f152d 459void tap_random_base64(void) {
60fd885a
JH
460 #if defined(__AVR_ATmega32U4__)
461 uint8_t key = (TCNT0 + TCNT1 + TCNT3 + TCNT4) % 64;
462 #else
463 uint8_t key = rand() % 64;
464 #endif
197f152d
JH
465 switch (key) {
466 case 0 ... 25:
467 register_code(KC_LSFT);
468 register_code(key + KC_A);
469 unregister_code(key + KC_A);
470 unregister_code(KC_LSFT);
471 break;
472 case 26 ... 51:
473 register_code(key - 26 + KC_A);
474 unregister_code(key - 26 + KC_A);
475 break;
476 case 52:
477 register_code(KC_0);
478 unregister_code(KC_0);
479 break;
480 case 53 ... 61:
481 register_code(key - 53 + KC_1);
482 unregister_code(key - 53 + KC_1);
483 break;
484 case 62:
485 register_code(KC_LSFT);
486 register_code(KC_EQL);
487 unregister_code(KC_EQL);
488 unregister_code(KC_LSFT);
489 break;
490 case 63:
491 register_code(KC_SLSH);
492 unregister_code(KC_SLSH);
493 break;
494 }
495}
496
1a8c0dd2 497void matrix_init_quantum() {
13bb6b4b
JH
498 #ifdef BACKLIGHT_ENABLE
499 backlight_init_ports();
500 #endif
1a8c0dd2
EZ
501 matrix_init_kb();
502}
503
504void matrix_scan_quantum() {
15719f35 505 #ifdef AUDIO_ENABLE
65faab3b 506 matrix_scan_music();
15719f35 507 #endif
fde477a9 508
65faab3b
JH
509 #ifdef TAP_DANCE_ENABLE
510 matrix_scan_tap_dance();
511 #endif
1a8c0dd2 512 matrix_scan_kb();
0428214b 513}
13bb6b4b 514
13bb6b4b
JH
515#if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN)
516
517static const uint8_t backlight_pin = BACKLIGHT_PIN;
518
519#if BACKLIGHT_PIN == B7
520# define COM1x1 COM1C1
521# define OCR1x OCR1C
522#elif BACKLIGHT_PIN == B6
523# define COM1x1 COM1B1
524# define OCR1x OCR1B
525#elif BACKLIGHT_PIN == B5
526# define COM1x1 COM1A1
527# define OCR1x OCR1A
528#else
529# error "Backlight pin not supported - use B5, B6, or B7"
530#endif
531
532__attribute__ ((weak))
533void backlight_init_ports(void)
534{
535
536 // Setup backlight pin as output and output low.
537 // DDRx |= n
538 _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF);
539 // PORTx &= ~n
540 _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
541
542 // Use full 16-bit resolution.
543 ICR1 = 0xFFFF;
544
545 // I could write a wall of text here to explain... but TL;DW
546 // Go read the ATmega32u4 datasheet.
547 // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
548
549 // Pin PB7 = OCR1C (Timer 1, Channel C)
550 // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
551 // (i.e. start high, go low when counter matches.)
552 // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
553 // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
554
555 TCCR1A = _BV(COM1x1) | _BV(WGM11); // = 0b00001010;
556 TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
557
558 backlight_init();
559 #ifdef BACKLIGHT_BREATHING
560 breathing_defaults();
561 #endif
562}
563
564__attribute__ ((weak))
565void backlight_set(uint8_t level)
566{
567 // Prevent backlight blink on lowest level
568 // PORTx &= ~n
569 _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
570
571 if ( level == 0 ) {
572 // Turn off PWM control on backlight pin, revert to output low.
573 TCCR1A &= ~(_BV(COM1x1));
574 OCR1x = 0x0;
575 } else if ( level == BACKLIGHT_LEVELS ) {
576 // Turn on PWM control of backlight pin
577 TCCR1A |= _BV(COM1x1);
578 // Set the brightness
579 OCR1x = 0xFFFF;
580 } else {
581 // Turn on PWM control of backlight pin
582 TCCR1A |= _BV(COM1x1);
583 // Set the brightness
584 OCR1x = 0xFFFF >> ((BACKLIGHT_LEVELS - level) * ((BACKLIGHT_LEVELS + 1) / 2));
585 }
586
587 #ifdef BACKLIGHT_BREATHING
588 breathing_intensity_default();
589 #endif
590}
591
592
593#ifdef BACKLIGHT_BREATHING
594
595#define BREATHING_NO_HALT 0
596#define BREATHING_HALT_OFF 1
597#define BREATHING_HALT_ON 2
598
599static uint8_t breath_intensity;
600static uint8_t breath_speed;
601static uint16_t breathing_index;
602static uint8_t breathing_halt;
603
604void breathing_enable(void)
605{
606 if (get_backlight_level() == 0)
607 {
608 breathing_index = 0;
609 }
610 else
611 {
612 // Set breathing_index to be at the midpoint (brightest point)
613 breathing_index = 0x20 << breath_speed;
614 }
615
616 breathing_halt = BREATHING_NO_HALT;
617
618 // Enable breathing interrupt
619 TIMSK1 |= _BV(OCIE1A);
620}
621
622void breathing_pulse(void)
623{
624 if (get_backlight_level() == 0)
625 {
626 breathing_index = 0;
627 }
628 else
629 {
630 // Set breathing_index to be at the midpoint + 1 (brightest point)
631 breathing_index = 0x21 << breath_speed;
632 }
633
634 breathing_halt = BREATHING_HALT_ON;
635
636 // Enable breathing interrupt
637 TIMSK1 |= _BV(OCIE1A);
638}
639
640void breathing_disable(void)
641{
642 // Disable breathing interrupt
643 TIMSK1 &= ~_BV(OCIE1A);
644 backlight_set(get_backlight_level());
645}
646
647void breathing_self_disable(void)
648{
649 if (get_backlight_level() == 0)
650 {
651 breathing_halt = BREATHING_HALT_OFF;
652 }
653 else
654 {
655 breathing_halt = BREATHING_HALT_ON;
656 }
657
658 //backlight_set(get_backlight_level());
659}
660
661void breathing_toggle(void)
662{
663 if (!is_breathing())
664 {
665 if (get_backlight_level() == 0)
666 {
667 breathing_index = 0;
668 }
669 else
670 {
671 // Set breathing_index to be at the midpoint + 1 (brightest point)
672 breathing_index = 0x21 << breath_speed;
673 }
674
675 breathing_halt = BREATHING_NO_HALT;
676 }
677
678 // Toggle breathing interrupt
679 TIMSK1 ^= _BV(OCIE1A);
680
681 // Restore backlight level
682 if (!is_breathing())
683 {
684 backlight_set(get_backlight_level());
685 }
686}
687
688bool is_breathing(void)
689{
690 return (TIMSK1 && _BV(OCIE1A));
691}
692
693void breathing_intensity_default(void)
694{
695 //breath_intensity = (uint8_t)((uint16_t)100 * (uint16_t)get_backlight_level() / (uint16_t)BACKLIGHT_LEVELS);
696 breath_intensity = ((BACKLIGHT_LEVELS - get_backlight_level()) * ((BACKLIGHT_LEVELS + 1) / 2));
697}
698
699void breathing_intensity_set(uint8_t value)
700{
701 breath_intensity = value;
702}
703
704void breathing_speed_default(void)
705{
706 breath_speed = 4;
707}
708
709void breathing_speed_set(uint8_t value)
710{
711 bool is_breathing_now = is_breathing();
712 uint8_t old_breath_speed = breath_speed;
713
714 if (is_breathing_now)
715 {
716 // Disable breathing interrupt
717 TIMSK1 &= ~_BV(OCIE1A);
718 }
719
720 breath_speed = value;
721
722 if (is_breathing_now)
723 {
724 // Adjust index to account for new speed
725 breathing_index = (( (uint8_t)( (breathing_index) >> old_breath_speed ) ) & 0x3F) << breath_speed;
726
727 // Enable breathing interrupt
728 TIMSK1 |= _BV(OCIE1A);
729 }
730
731}
732
733void breathing_speed_inc(uint8_t value)
734{
735 if ((uint16_t)(breath_speed - value) > 10 )
736 {
737 breathing_speed_set(0);
738 }
739 else
740 {
741 breathing_speed_set(breath_speed - value);
742 }
743}
744
745void breathing_speed_dec(uint8_t value)
746{
747 if ((uint16_t)(breath_speed + value) > 10 )
748 {
749 breathing_speed_set(10);
750 }
751 else
752 {
753 breathing_speed_set(breath_speed + value);
754 }
755}
756
757void breathing_defaults(void)
758{
759 breathing_intensity_default();
760 breathing_speed_default();
761 breathing_halt = BREATHING_NO_HALT;
762}
763
764/* Breathing Sleep LED brighness(PWM On period) table
765 * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle
766 *
767 * http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63
768 * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i }
769 */
770static const uint8_t breathing_table[64] PROGMEM = {
771 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10,
772 15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252,
773255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23,
774 15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
775};
776
777ISR(TIMER1_COMPA_vect)
778{
779 // OCR1x = (pgm_read_byte(&breathing_table[ ( (uint8_t)( (breathing_index++) >> breath_speed ) ) & 0x3F ] )) * breath_intensity;
780
781
782 uint8_t local_index = ( (uint8_t)( (breathing_index++) >> breath_speed ) ) & 0x3F;
783
784 if (((breathing_halt == BREATHING_HALT_ON) && (local_index == 0x20)) || ((breathing_halt == BREATHING_HALT_OFF) && (local_index == 0x3F)))
785 {
786 // Disable breathing interrupt
787 TIMSK1 &= ~_BV(OCIE1A);
788 }
789
790 OCR1x = (uint16_t)(((uint16_t)pgm_read_byte(&breathing_table[local_index]) * 257)) >> breath_intensity;
791
792}
793
794
795
796#endif // breathing
797
798#else // backlight
799
800__attribute__ ((weak))
801void backlight_init_ports(void)
802{
803
804}
805
806__attribute__ ((weak))
807void backlight_set(uint8_t level)
808{
809
810}
811
812#endif // backlight
813
814
664c0a03
JH
815// Functions for spitting out values
816//
817
818void send_dword(uint32_t number) { // this might not actually work
819 uint16_t word = (number >> 16);
820 send_word(word);
821 send_word(number & 0xFFFFUL);
822}
823
824void send_word(uint16_t number) {
825 uint8_t byte = number >> 8;
826 send_byte(byte);
827 send_byte(number & 0xFF);
828}
829
830void send_byte(uint8_t number) {
831 uint8_t nibble = number >> 4;
832 send_nibble(nibble);
833 send_nibble(number & 0xF);
834}
835
836void send_nibble(uint8_t number) {
837 switch (number) {
838 case 0:
839 register_code(KC_0);
840 unregister_code(KC_0);
841 break;
842 case 1 ... 9:
843 register_code(KC_1 + (number - 1));
844 unregister_code(KC_1 + (number - 1));
845 break;
846 case 0xA ... 0xF:
847 register_code(KC_A + (number - 0xA));
848 unregister_code(KC_A + (number - 0xA));
849 break;
850 }
851}
852
7edac212
JH
853void api_send_unicode(uint32_t unicode) {
854#ifdef API_ENABLE
cefa8468
JH
855 uint8_t chunk[4];
856 dword_to_bytes(unicode, chunk);
857 MT_SEND_DATA(DT_UNICODE, chunk, 5);
7edac212 858#endif
cefa8468 859}
13bb6b4b
JH
860
861__attribute__ ((weak))
862void led_set_user(uint8_t usb_led) {
863
864}
865
866__attribute__ ((weak))
867void led_set_kb(uint8_t usb_led) {
868 led_set_user(usb_led);
869}
870
871__attribute__ ((weak))
872void led_init_ports(void)
873{
874
875}
876
877__attribute__ ((weak))
878void led_set(uint8_t usb_led)
879{
880
881 // Example LED Code
882 //
883 // // Using PE6 Caps Lock LED
884 // if (usb_led & (1<<USB_LED_CAPS_LOCK))
885 // {
886 // // Output high.
887 // DDRE |= (1<<6);
888 // PORTE |= (1<<6);
889 // }
890 // else
891 // {
892 // // Output low.
893 // DDRE &= ~(1<<6);
894 // PORTE &= ~(1<<6);
895 // }
896
897 led_set_kb(usb_led);
898}
899
900
287eb7ad 901//------------------------------------------------------------------------------
794aed37 902// Override these functions in your keymap file to play different tunes on
287eb7ad
JH
903// different events such as startup and bootloader jump
904
905__attribute__ ((weak))
906void startup_user() {}
907
908__attribute__ ((weak))
909void shutdown_user() {}
910
12370259 911//------------------------------------------------------------------------------