diff options
Diffstat (limited to 'quantum/quantum.c')
-rw-r--r-- | quantum/quantum.c | 1030 |
1 files changed, 675 insertions, 355 deletions
diff --git a/quantum/quantum.c b/quantum/quantum.c index 34c575af42..bc2da510f2 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -1,11 +1,4 @@ #include "quantum.h" -#include "timer.h" - -__attribute__ ((weak)) -void matrix_init_kb(void) {} - -__attribute__ ((weak)) -void matrix_scan_kb(void) {} __attribute__ ((weak)) bool process_action_kb(keyrecord_t *record) { @@ -13,95 +6,39 @@ bool process_action_kb(keyrecord_t *record) { } __attribute__ ((weak)) -void leader_start(void) {} +bool process_record_kb(uint16_t keycode, keyrecord_t *record) { + return process_record_user(keycode, record); +} __attribute__ ((weak)) -void leader_end(void) {} - -uint8_t starting_note = 0x0C; -int offset = 7; +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + return true; +} +void reset_keyboard(void) { + clear_keyboard(); #ifdef AUDIO_ENABLE - bool music_activated = false; - float music_scale[][2] = SONG(MUSIC_SCALE_SOUND); - - // music sequencer - static bool music_sequence_recording = false; - static bool music_sequence_playing = false; - static float music_sequence[16] = {0}; - static uint8_t music_sequence_count = 0; - static uint8_t music_sequence_position = 0; - - static uint16_t music_sequence_timer = 0; - static uint16_t music_sequence_interval = 100; - -#endif - -#ifdef MIDI_ENABLE - bool midi_activated = false; + stop_all_notes(); + shutdown_user(); #endif - -// Leader key stuff -bool leading = false; -uint16_t leader_time = 0; - -uint16_t leader_sequence[3] = {0, 0, 0}; -uint8_t leader_sequence_size = 0; - -// Chording stuff -#define CHORDING_MAX 4 -bool chording = false; - -uint8_t chord_keys[CHORDING_MAX] = {0}; -uint8_t chord_key_count = 0; -uint8_t chord_key_down = 0; - -#ifdef UNICODE_ENABLE - static uint8_t input_mode; + wait_ms(250); +#ifdef CATERINA_BOOTLOADER + *(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific #endif - -bool keys_chord(uint8_t keys[]) { - uint8_t keys_size = sizeof(keys)/sizeof(keys[0]); - bool pass = true; - uint8_t in = 0; - for (uint8_t i = 0; i < chord_key_count; i++) { - bool found = false; - for (uint8_t j = 0; j < keys_size; j++) { - if (chord_keys[i] == (keys[j] & 0xFF)) { - in++; // detects key in chord - found = true; - break; - } - } - if (found) - continue; - if (chord_keys[i] != 0) { - pass = false; // makes sure rest are blank - } - } - return (pass && (in == keys_size)); + bootloader_jump(); } -#ifdef UNICODE_ENABLE - -uint16_t hex_to_keycode(uint8_t hex) -{ - if (hex == 0x0) { - return KC_0; - } else if (hex < 0xA) { - return KC_1 + (hex - 0x1); - } else { - return KC_A + (hex - 0xA); - } -} - -void set_unicode_mode(uint8_t os_target) -{ - input_mode = os_target; -} +// Shift / paren setup +#ifndef LSPO_KEY + #define LSPO_KEY KC_9 +#endif +#ifndef RSPC_KEY + #define RSPC_KEY KC_0 #endif +static bool shift_interrupted[2] = {0, 0}; + bool process_record_quantum(keyrecord_t *record) { /* This gets the keycode from the key pressed */ @@ -130,334 +67,717 @@ bool process_record_quantum(keyrecord_t *record) { // return false; // } + if (!( + process_record_kb(keycode, record) && #ifdef MIDI_ENABLE - if (keycode == MI_ON && record->event.pressed) { - midi_activated = true; - play_music_scale(); - return false; - } + process_midi(keycode, record) && + #endif + #ifdef AUDIO_ENABLE + process_music(keycode, record) && + #endif + #ifdef TAP_DANCE_ENABLE + process_tap_dance(keycode, record) && + #endif + #ifndef DISABLE_LEADER + process_leader(keycode, record) && + #endif + #ifndef DISABLE_CHORDING + process_chording(keycode, record) && + #endif + #ifdef UNICODE_ENABLE + process_unicode(keycode, record) && + #endif + true)) { + return false; + } - if (keycode == MI_OFF && record->event.pressed) { - midi_activated = false; - midi_send_cc(&midi_device, 0, 0x7B, 0); - return false; - } + // Shift / paren setup - if (midi_activated) { - if (record->event.key.col == (MATRIX_COLS - 1) && record->event.key.row == (MATRIX_ROWS - 1)) { - if (record->event.pressed) { - starting_note++; // Change key - midi_send_cc(&midi_device, 0, 0x7B, 0); - // midi_send_cc(&midi_device, 1, 0x7B, 0); - // midi_send_cc(&midi_device, 2, 0x7B, 0); - // midi_send_cc(&midi_device, 3, 0x7B, 0); - // midi_send_cc(&midi_device, 4, 0x7B, 0); - } - return false; + switch(keycode) { + case RESET: + if (record->event.pressed) { + reset_keyboard(); } - if (record->event.key.col == (MATRIX_COLS - 2) && record->event.key.row == (MATRIX_ROWS - 1)) { - if (record->event.pressed) { - starting_note--; // Change key - midi_send_cc(&midi_device, 0, 0x7B, 0); - // midi_send_cc(&midi_device, 1, 0x7B, 0); - // midi_send_cc(&midi_device, 2, 0x7B, 0); - // midi_send_cc(&midi_device, 3, 0x7B, 0); - // midi_send_cc(&midi_device, 4, 0x7B, 0); - } - return false; + return false; + break; + case DEBUG: + if (record->event.pressed) { + print("\nDEBUG: enabled.\n"); + debug_enable = true; } - if (record->event.key.col == (MATRIX_COLS - 3) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) { - offset++; // Change scale - midi_send_cc(&midi_device, 0, 0x7B, 0); - // midi_send_cc(&midi_device, 1, 0x7B, 0); - // midi_send_cc(&midi_device, 2, 0x7B, 0); - // midi_send_cc(&midi_device, 3, 0x7B, 0); - // midi_send_cc(&midi_device, 4, 0x7B, 0); - return false; + return false; + break; + #ifdef RGBLIGHT_ENABLE + case RGB_TOG: + if (record->event.pressed) { + rgblight_toggle(); } - if (record->event.key.col == (MATRIX_COLS - 4) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) { - offset--; // Change scale - midi_send_cc(&midi_device, 0, 0x7B, 0); - // midi_send_cc(&midi_device, 1, 0x7B, 0); - // midi_send_cc(&midi_device, 2, 0x7B, 0); - // midi_send_cc(&midi_device, 3, 0x7B, 0); - // midi_send_cc(&midi_device, 4, 0x7B, 0); - return false; + return false; + break; + case RGB_MOD: + if (record->event.pressed) { + rgblight_step(); } - // basic - // uint8_t note = (starting_note + SCALE[record->event.key.col + offset])+12*(MATRIX_ROWS - record->event.key.row); - // advanced - // uint8_t note = (starting_note + record->event.key.col + offset)+12*(MATRIX_ROWS - record->event.key.row); - // guitar - uint8_t note = (starting_note + record->event.key.col + offset)+5*(MATRIX_ROWS - record->event.key.row); - // violin - // uint8_t note = (starting_note + record->event.key.col + offset)+7*(MATRIX_ROWS - record->event.key.row); - - if (record->event.pressed) { - // midi_send_noteon(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127); - midi_send_noteon(&midi_device, 0, note, 127); - } else { - // midi_send_noteoff(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127); - midi_send_noteoff(&midi_device, 0, note, 127); + return false; + break; + case RGB_HUI: + if (record->event.pressed) { + rgblight_increase_hue(); } - - if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through + return false; + break; + case RGB_HUD: + if (record->event.pressed) { + rgblight_decrease_hue(); + } + return false; + break; + case RGB_SAI: + if (record->event.pressed) { + rgblight_increase_sat(); + } + return false; + break; + case RGB_SAD: + if (record->event.pressed) { + rgblight_decrease_sat(); + } + return false; + break; + case RGB_VAI: + if (record->event.pressed) { + rgblight_increase_val(); + } + return false; + break; + case RGB_VAD: + if (record->event.pressed) { + rgblight_decrease_val(); + } + return false; + break; + #endif + case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_UNSWAP_ALT_GUI: + if (record->event.pressed) { + // MAGIC actions (BOOTMAGIC without the boot) + if (!eeconfig_is_enabled()) { + eeconfig_init(); + } + /* keymap config */ + keymap_config.raw = eeconfig_read_keymap(); + if (keycode == MAGIC_SWAP_CONTROL_CAPSLOCK) { + keymap_config.swap_control_capslock = 1; + } else if (keycode == MAGIC_CAPSLOCK_TO_CONTROL) { + keymap_config.capslock_to_control = 1; + } else if (keycode == MAGIC_SWAP_LALT_LGUI) { + keymap_config.swap_lalt_lgui = 1; + } else if (keycode == MAGIC_SWAP_RALT_RGUI) { + keymap_config.swap_ralt_rgui = 1; + } else if (keycode == MAGIC_NO_GUI) { + keymap_config.no_gui = 1; + } else if (keycode == MAGIC_SWAP_GRAVE_ESC) { + keymap_config.swap_grave_esc = 1; + } else if (keycode == MAGIC_SWAP_BACKSLASH_BACKSPACE) { + keymap_config.swap_backslash_backspace = 1; + } else if (keycode == MAGIC_HOST_NKRO) { + keymap_config.nkro = 1; + } else if (keycode == MAGIC_SWAP_ALT_GUI) { + keymap_config.swap_lalt_lgui = 1; + keymap_config.swap_ralt_rgui = 1; + } + /* UNs */ + else if (keycode == MAGIC_UNSWAP_CONTROL_CAPSLOCK) { + keymap_config.swap_control_capslock = 0; + } else if (keycode == MAGIC_UNCAPSLOCK_TO_CONTROL) { + keymap_config.capslock_to_control = 0; + } else if (keycode == MAGIC_UNSWAP_LALT_LGUI) { + keymap_config.swap_lalt_lgui = 0; + } else if (keycode == MAGIC_UNSWAP_RALT_RGUI) { + keymap_config.swap_ralt_rgui = 0; + } else if (keycode == MAGIC_UNNO_GUI) { + keymap_config.no_gui = 0; + } else if (keycode == MAGIC_UNSWAP_GRAVE_ESC) { + keymap_config.swap_grave_esc = 0; + } else if (keycode == MAGIC_UNSWAP_BACKSLASH_BACKSPACE) { + keymap_config.swap_backslash_backspace = 0; + } else if (keycode == MAGIC_UNHOST_NKRO) { + keymap_config.nkro = 0; + } else if (keycode == MAGIC_UNSWAP_ALT_GUI) { + keymap_config.swap_lalt_lgui = 0; + keymap_config.swap_ralt_rgui = 0; + } + eeconfig_update_keymap(keymap_config.raw); return false; - } - #endif - - #ifdef AUDIO_ENABLE - if (keycode == AU_ON && record->event.pressed) { - audio_on(); + } + break; + case KC_LSPO: { + if (record->event.pressed) { + shift_interrupted[0] = false; + register_mods(MOD_BIT(KC_LSFT)); + } + else { + #ifdef DISABLE_SPACE_CADET_ROLLOVER + if (get_mods() & MOD_BIT(KC_RSFT)) { + shift_interrupted[0] = true; + shift_interrupted[1] = true; + } + #endif + if (!shift_interrupted[0]) { + register_code(LSPO_KEY); + unregister_code(LSPO_KEY); + } + unregister_mods(MOD_BIT(KC_LSFT)); + } return false; + break; } - if (keycode == AU_OFF && record->event.pressed) { - audio_off(); + case KC_RSPC: { + if (record->event.pressed) { + shift_interrupted[1] = false; + register_mods(MOD_BIT(KC_RSFT)); + } + else { + #ifdef DISABLE_SPACE_CADET_ROLLOVER + if (get_mods() & MOD_BIT(KC_LSFT)) { + shift_interrupted[0] = true; + shift_interrupted[1] = true; + } + #endif + if (!shift_interrupted[1]) { + register_code(RSPC_KEY); + unregister_code(RSPC_KEY); + } + unregister_mods(MOD_BIT(KC_RSFT)); + } return false; + break; + } + default: { + shift_interrupted[0] = true; + shift_interrupted[1] = true; + break; } + } - if (keycode == AU_TOG && record->event.pressed) { - if (is_audio_on()) - { - audio_off(); + return process_action_kb(record); +} + +const bool ascii_to_qwerty_shift_lut[0x80] PROGMEM = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0 +}; + +const uint8_t ascii_to_qwerty_keycode_lut[0x80] PROGMEM = { + 0, 0, 0, 0, 0, 0, 0, 0, + KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, KC_ESC, 0, 0, 0, 0, + KC_SPC, KC_1, KC_QUOT, KC_3, KC_4, KC_5, KC_7, KC_QUOT, + KC_9, KC_0, KC_8, KC_EQL, KC_COMM, KC_MINS, KC_DOT, KC_SLSH, + KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, + KC_8, KC_9, KC_SCLN, KC_SCLN, KC_COMM, KC_EQL, KC_DOT, KC_SLSH, + KC_2, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G, + KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O, + KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W, + KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_6, KC_MINS, + KC_GRV, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G, + KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O, + KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W, + KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL +}; + +/* for users whose OSes are set to Colemak */ +#if 0 +#include "keymap_colemak.h" + +const bool ascii_to_colemak_shift_lut[0x80] PROGMEM = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0 +}; + +const uint8_t ascii_to_colemak_keycode_lut[0x80] PROGMEM = { + 0, 0, 0, 0, 0, 0, 0, 0, + KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, KC_ESC, 0, 0, 0, 0, + KC_SPC, KC_1, KC_QUOT, KC_3, KC_4, KC_5, KC_7, KC_QUOT, + KC_9, KC_0, KC_8, KC_EQL, KC_COMM, KC_MINS, KC_DOT, KC_SLSH, + KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, + KC_8, KC_9, CM_SCLN, CM_SCLN, KC_COMM, KC_EQL, KC_DOT, KC_SLSH, + KC_2, CM_A, CM_B, CM_C, CM_D, CM_E, CM_F, CM_G, + CM_H, CM_I, CM_J, CM_K, CM_L, CM_M, CM_N, CM_O, + CM_P, CM_Q, CM_R, CM_S, CM_T, CM_U, CM_V, CM_W, + CM_X, CM_Y, CM_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_6, KC_MINS, + KC_GRV, CM_A, CM_B, CM_C, CM_D, CM_E, CM_F, CM_G, + CM_H, CM_I, CM_J, CM_K, CM_L, CM_M, CM_N, CM_O, + CM_P, CM_Q, CM_R, CM_S, CM_T, CM_U, CM_V, CM_W, + CM_X, CM_Y, CM_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL +}; + +#endif + +void send_string(const char *str) { + while (1) { + uint8_t keycode; + uint8_t ascii_code = pgm_read_byte(str); + if (!ascii_code) break; + keycode = pgm_read_byte(&ascii_to_qwerty_keycode_lut[ascii_code]); + if (pgm_read_byte(&ascii_to_qwerty_shift_lut[ascii_code])) { + register_code(KC_LSFT); + register_code(keycode); + unregister_code(keycode); + unregister_code(KC_LSFT); } - else - { - audio_on(); + else { + register_code(keycode); + unregister_code(keycode); } - return false; + ++str; } +} - if (keycode == MU_ON && record->event.pressed) { - music_on(); - return false; +void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) { + if (IS_LAYER_ON(layer1) && IS_LAYER_ON(layer2)) { + layer_on(layer3); + } else { + layer_off(layer3); + } +} + +void tap_random_base64(void) { + #if defined(__AVR_ATmega32U4__) + uint8_t key = (TCNT0 + TCNT1 + TCNT3 + TCNT4) % 64; + #else + uint8_t key = rand() % 64; + #endif + switch (key) { + case 0 ... 25: + register_code(KC_LSFT); + register_code(key + KC_A); + unregister_code(key + KC_A); + unregister_code(KC_LSFT); + break; + case 26 ... 51: + register_code(key - 26 + KC_A); + unregister_code(key - 26 + KC_A); + break; + case 52: + register_code(KC_0); + unregister_code(KC_0); + break; + case 53 ... 61: + register_code(key - 53 + KC_1); + unregister_code(key - 53 + KC_1); + break; + case 62: + register_code(KC_LSFT); + register_code(KC_EQL); + unregister_code(KC_EQL); + unregister_code(KC_LSFT); + break; + case 63: + register_code(KC_SLSH); + unregister_code(KC_SLSH); + break; + } +} + +void matrix_init_quantum() { + #ifdef BACKLIGHT_ENABLE + backlight_init_ports(); + #endif + matrix_init_kb(); +} + +void matrix_scan_quantum() { + #ifdef AUDIO_ENABLE + matrix_scan_music(); + #endif + + #ifdef TAP_DANCE_ENABLE + matrix_scan_tap_dance(); + #endif + matrix_scan_kb(); +} + +#if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN) + +static const uint8_t backlight_pin = BACKLIGHT_PIN; + +#if BACKLIGHT_PIN == B7 +# define COM1x1 COM1C1 +# define OCR1x OCR1C +#elif BACKLIGHT_PIN == B6 +# define COM1x1 COM1B1 +# define OCR1x OCR1B +#elif BACKLIGHT_PIN == B5 +# define COM1x1 COM1A1 +# define OCR1x OCR1A +#else +# error "Backlight pin not supported - use B5, B6, or B7" +#endif + +__attribute__ ((weak)) +void backlight_init_ports(void) +{ + + // Setup backlight pin as output and output low. + // DDRx |= n + _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF); + // PORTx &= ~n + _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); + + // Use full 16-bit resolution. + ICR1 = 0xFFFF; + + // I could write a wall of text here to explain... but TL;DW + // Go read the ATmega32u4 datasheet. + // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on + + // Pin PB7 = OCR1C (Timer 1, Channel C) + // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0 + // (i.e. start high, go low when counter matches.) + // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0 + // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1 + + TCCR1A = _BV(COM1x1) | _BV(WGM11); // = 0b00001010; + TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001; + + backlight_init(); + #ifdef BACKLIGHT_BREATHING + breathing_defaults(); + #endif +} + +__attribute__ ((weak)) +void backlight_set(uint8_t level) +{ + // Prevent backlight blink on lowest level + // PORTx &= ~n + _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); + + if ( level == 0 ) { + // Turn off PWM control on backlight pin, revert to output low. + TCCR1A &= ~(_BV(COM1x1)); + OCR1x = 0x0; + } else if ( level == BACKLIGHT_LEVELS ) { + // Turn on PWM control of backlight pin + TCCR1A |= _BV(COM1x1); + // Set the brightness + OCR1x = 0xFFFF; + } else { + // Turn on PWM control of backlight pin + TCCR1A |= _BV(COM1x1); + // Set the brightness + OCR1x = 0xFFFF >> ((BACKLIGHT_LEVELS - level) * ((BACKLIGHT_LEVELS + 1) / 2)); + } + + #ifdef BACKLIGHT_BREATHING + breathing_intensity_default(); + #endif +} + + +#ifdef BACKLIGHT_BREATHING + +#define BREATHING_NO_HALT 0 +#define BREATHING_HALT_OFF 1 +#define BREATHING_HALT_ON 2 + +static uint8_t breath_intensity; +static uint8_t breath_speed; +static uint16_t breathing_index; +static uint8_t breathing_halt; + +void breathing_enable(void) +{ + if (get_backlight_level() == 0) + { + breathing_index = 0; + } + else + { + // Set breathing_index to be at the midpoint (brightest point) + breathing_index = 0x20 << breath_speed; } - if (keycode == MU_OFF && record->event.pressed) { - music_off(); - return false; + breathing_halt = BREATHING_NO_HALT; + + // Enable breathing interrupt + TIMSK1 |= _BV(OCIE1A); +} + +void breathing_pulse(void) +{ + if (get_backlight_level() == 0) + { + breathing_index = 0; + } + else + { + // Set breathing_index to be at the midpoint + 1 (brightest point) + breathing_index = 0x21 << breath_speed; + } + + breathing_halt = BREATHING_HALT_ON; + + // Enable breathing interrupt + TIMSK1 |= _BV(OCIE1A); +} + +void breathing_disable(void) +{ + // Disable breathing interrupt + TIMSK1 &= ~_BV(OCIE1A); + backlight_set(get_backlight_level()); +} + +void breathing_self_disable(void) +{ + if (get_backlight_level() == 0) + { + breathing_halt = BREATHING_HALT_OFF; + } + else + { + breathing_halt = BREATHING_HALT_ON; } - if (keycode == MU_TOG && record->event.pressed) { - if (music_activated) + //backlight_set(get_backlight_level()); +} + +void breathing_toggle(void) +{ + if (!is_breathing()) + { + if (get_backlight_level() == 0) { - music_off(); + breathing_index = 0; } else { - music_on(); + // Set breathing_index to be at the midpoint + 1 (brightest point) + breathing_index = 0x21 << breath_speed; } - return false; - } - if (keycode == MUV_IN && record->event.pressed) { - voice_iterate(); - play_music_scale(); - return false; + breathing_halt = BREATHING_NO_HALT; } - if (keycode == MUV_DE && record->event.pressed) { - voice_deiterate(); - play_music_scale(); - return false; + // Toggle breathing interrupt + TIMSK1 ^= _BV(OCIE1A); + + // Restore backlight level + if (!is_breathing()) + { + backlight_set(get_backlight_level()); } +} - if (music_activated) { +bool is_breathing(void) +{ + return (TIMSK1 && _BV(OCIE1A)); +} - if (keycode == KC_LCTL && record->event.pressed) { // Start recording - stop_all_notes(); - music_sequence_recording = true; - music_sequence_playing = false; - music_sequence_count = 0; - return false; - } - if (keycode == KC_LALT && record->event.pressed) { // Stop recording/playing - stop_all_notes(); - music_sequence_recording = false; - music_sequence_playing = false; - return false; - } - if (keycode == KC_LGUI && record->event.pressed) { // Start playing - stop_all_notes(); - music_sequence_recording = false; - music_sequence_playing = true; - music_sequence_position = 0; - music_sequence_timer = 0; - return false; - } +void breathing_intensity_default(void) +{ + //breath_intensity = (uint8_t)((uint16_t)100 * (uint16_t)get_backlight_level() / (uint16_t)BACKLIGHT_LEVELS); + breath_intensity = ((BACKLIGHT_LEVELS - get_backlight_level()) * ((BACKLIGHT_LEVELS + 1) / 2)); +} - if (keycode == KC_UP) { - if (record->event.pressed) - music_sequence_interval-=10; - return false; - } - if (keycode == KC_DOWN) { - if (record->event.pressed) - music_sequence_interval+=10; - return false; - } +void breathing_intensity_set(uint8_t value) +{ + breath_intensity = value; +} - float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row)); - if (record->event.pressed) { - play_note(freq, 0xF); - if (music_sequence_recording) { - music_sequence[music_sequence_count] = freq; - music_sequence_count++; - } - } else { - stop_note(freq); - } +void breathing_speed_default(void) +{ + breath_speed = 4; +} - if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through - return false; - } - #endif +void breathing_speed_set(uint8_t value) +{ + bool is_breathing_now = is_breathing(); + uint8_t old_breath_speed = breath_speed; -#ifndef DISABLE_LEADER - // Leader key set-up - if (record->event.pressed) { - if (!leading && keycode == KC_LEAD) { - leader_start(); - leading = true; - leader_time = timer_read(); - leader_sequence_size = 0; - leader_sequence[0] = 0; - leader_sequence[1] = 0; - leader_sequence[2] = 0; - return false; - } - if (leading && timer_elapsed(leader_time) < LEADER_TIMEOUT) { - leader_sequence[leader_sequence_size] = keycode; - leader_sequence_size++; - return false; + if (is_breathing_now) + { + // Disable breathing interrupt + TIMSK1 &= ~_BV(OCIE1A); } - } -#endif -#define DISABLE_CHORDING -#ifndef DISABLE_CHORDING + breath_speed = value; - if (keycode >= 0x5700 && keycode <= 0x57FF) { - if (record->event.pressed) { - if (!chording) { - chording = true; - for (uint8_t i = 0; i < CHORDING_MAX; i++) - chord_keys[i] = 0; - chord_key_count = 0; - chord_key_down = 0; - } - chord_keys[chord_key_count] = (keycode & 0xFF); - chord_key_count++; - chord_key_down++; - return false; - } else { - if (chording) { - chord_key_down--; - if (chord_key_down == 0) { - chording = false; - // Chord Dictionary - if (keys_chord((uint8_t[]){KC_ENTER, KC_SPACE})) { - register_code(KC_A); - unregister_code(KC_A); - return false; - } - for (uint8_t i = 0; i < chord_key_count; i++) { - register_code(chord_keys[i]); - unregister_code(chord_keys[i]); - return false; - } - } - } + if (is_breathing_now) + { + // Adjust index to account for new speed + breathing_index = (( (uint8_t)( (breathing_index) >> old_breath_speed ) ) & 0x3F) << breath_speed; + + // Enable breathing interrupt + TIMSK1 |= _BV(OCIE1A); } - } -#endif +} -#ifdef UNICODE_ENABLE - - if (keycode > UNICODE(0) && record->event.pressed) { - uint16_t unicode = keycode & 0x7FFF; - switch(input_mode) { - case UC_OSX: - register_code(KC_LALT); - break; - case UC_LNX: - register_code(KC_LCTL); - register_code(KC_LSFT); - register_code(KC_U); - unregister_code(KC_U); - break; - case UC_WIN: - register_code(KC_LALT); - register_code(KC_PPLS); - unregister_code(KC_PPLS); - break; +void breathing_speed_inc(uint8_t value) +{ + if ((uint16_t)(breath_speed - value) > 10 ) + { + breathing_speed_set(0); } - for(int i = 3; i >= 0; i--) { - uint8_t digit = ((unicode >> (i*4)) & 0xF); - register_code(hex_to_keycode(digit)); - unregister_code(hex_to_keycode(digit)); + else + { + breathing_speed_set(breath_speed - value); } - switch(input_mode) { - case UC_OSX: - case UC_WIN: - unregister_code(KC_LALT); - break; - case UC_LNX: - unregister_code(KC_LCTL); - unregister_code(KC_LSFT); - break; +} + +void breathing_speed_dec(uint8_t value) +{ + if ((uint16_t)(breath_speed + value) > 10 ) + { + breathing_speed_set(10); } - } + else + { + breathing_speed_set(breath_speed + value); + } +} -#endif +void breathing_defaults(void) +{ + breathing_intensity_default(); + breathing_speed_default(); + breathing_halt = BREATHING_NO_HALT; +} + +/* Breathing Sleep LED brighness(PWM On period) table + * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle + * + * http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63 + * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i } + */ +static const uint8_t breathing_table[64] PROGMEM = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10, + 15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252, +255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23, + 15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +ISR(TIMER1_COMPA_vect) +{ + // OCR1x = (pgm_read_byte(&breathing_table[ ( (uint8_t)( (breathing_index++) >> breath_speed ) ) & 0x3F ] )) * breath_intensity; + + + uint8_t local_index = ( (uint8_t)( (breathing_index++) >> breath_speed ) ) & 0x3F; + + if (((breathing_halt == BREATHING_HALT_ON) && (local_index == 0x20)) || ((breathing_halt == BREATHING_HALT_OFF) && (local_index == 0x3F))) + { + // Disable breathing interrupt + TIMSK1 &= ~_BV(OCIE1A); + } + + OCR1x = (uint16_t)(((uint16_t)pgm_read_byte(&breathing_table[local_index]) * 257)) >> breath_intensity; - return process_action_kb(record); } -void matrix_init_quantum() { - matrix_init_kb(); + + +#endif // breathing + +#else // backlight + +__attribute__ ((weak)) +void backlight_init_ports(void) +{ + } -void matrix_scan_quantum() { - #ifdef AUDIO_ENABLE - if (music_sequence_playing) { - if ((music_sequence_timer == 0) || (timer_elapsed(music_sequence_timer) > music_sequence_interval)) { - music_sequence_timer = timer_read(); - stop_note(music_sequence[(music_sequence_position - 1 < 0)?(music_sequence_position - 1 + music_sequence_count):(music_sequence_position - 1)]); - play_note(music_sequence[music_sequence_position], 0xF); - music_sequence_position = (music_sequence_position + 1) % music_sequence_count; - } - } +__attribute__ ((weak)) +void backlight_set(uint8_t level) +{ - #endif +} + +#endif // backlight + + + +__attribute__ ((weak)) +void led_set_user(uint8_t usb_led) { - matrix_scan_kb(); } -#ifdef AUDIO_ENABLE - bool is_music_on(void) { - return (music_activated != 0); - } - void music_toggle(void) { - if (!music_activated) { - music_on(); - } else { - music_off(); - } - } +__attribute__ ((weak)) +void led_set_kb(uint8_t usb_led) { + led_set_user(usb_led); +} - void music_on(void) { - music_activated = 1; - music_on_user(); - } +__attribute__ ((weak)) +void led_init_ports(void) +{ - void music_off(void) { - music_activated = 0; - stop_all_notes(); - } +} -#endif __attribute__ ((weak)) -void music_on_user() {} +void led_set(uint8_t usb_led) +{ + + // Example LED Code + // + // // Using PE6 Caps Lock LED + // if (usb_led & (1<<USB_LED_CAPS_LOCK)) + // { + // // Output high. + // DDRE |= (1<<6); + // PORTE |= (1<<6); + // } + // else + // { + // // Output low. + // DDRE &= ~(1<<6); + // PORTE &= ~(1<<6); + // } + + led_set_kb(usb_led); +} + + +//------------------------------------------------------------------------------ +// Override these functions in your keymap file to play different tunes on +// different events such as startup and bootloader jump + +__attribute__ ((weak)) +void startup_user() {} + +__attribute__ ((weak)) +void shutdown_user() {} + +//------------------------------------------------------------------------------ |