diff options
Diffstat (limited to 'quantum/quantum.c')
| -rw-r--r-- | quantum/quantum.c | 313 | 
1 files changed, 274 insertions, 39 deletions
| diff --git a/quantum/quantum.c b/quantum/quantum.c index 098312e6ef..4f4cee4e9b 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -1,4 +1,34 @@ +/* Copyright 2016-2017 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ +  #include "quantum.h" +#ifdef PROTOCOL_LUFA +#include "outputselect.h" +#endif + +#ifndef TAPPING_TERM +#define TAPPING_TERM 200 +#endif + +#include "backlight.h" +extern backlight_config_t backlight_config; + +#ifdef FAUXCLICKY_ENABLE +#include "fauxclicky.h" +#endif  static void do_code16 (uint16_t code, void (*f) (uint8_t)) {    switch (code) { @@ -17,6 +47,8 @@ static void do_code16 (uint16_t code, void (*f) (uint8_t)) {    if (code & QK_LGUI)      f(KC_LGUI); +  if (code < QK_RMODS_MIN) return; +    if (code & QK_RCTL)      f(KC_RCTL);    if (code & QK_RSFT) @@ -27,14 +59,42 @@ static void do_code16 (uint16_t code, void (*f) (uint8_t)) {      f(KC_RGUI);  } +static inline void qk_register_weak_mods(uint8_t kc) { +    add_weak_mods(MOD_BIT(kc)); +    send_keyboard_report(); +} + +static inline void qk_unregister_weak_mods(uint8_t kc) { +    del_weak_mods(MOD_BIT(kc)); +    send_keyboard_report(); +} + +static inline void qk_register_mods(uint8_t kc) { +    add_weak_mods(MOD_BIT(kc)); +    send_keyboard_report(); +} + +static inline void qk_unregister_mods(uint8_t kc) { +    del_weak_mods(MOD_BIT(kc)); +    send_keyboard_report(); +} +  void register_code16 (uint16_t code) { -  do_code16 (code, register_code); +  if (IS_MOD(code) || code == KC_NO) { +      do_code16 (code, qk_register_mods); +  } else { +      do_code16 (code, qk_register_weak_mods); +  }    register_code (code);  }  void unregister_code16 (uint16_t code) {    unregister_code (code); -  do_code16 (code, unregister_code); +  if (IS_MOD(code) || code == KC_NO) { +      do_code16 (code, qk_unregister_mods); +  } else { +      do_code16 (code, qk_unregister_weak_mods); +  }  }  __attribute__ ((weak)) @@ -54,8 +114,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {  void reset_keyboard(void) {    clear_keyboard(); -#ifdef AUDIO_ENABLE -  stop_all_notes(); +#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_ENABLE_BASIC)) +  music_all_notes_off();    shutdown_user();  #endif    wait_ms(250); @@ -75,6 +135,7 @@ void reset_keyboard(void) {  #endif  static bool shift_interrupted[2] = {0, 0}; +static uint16_t scs_timer[2] = {0, 0};  bool process_record_quantum(keyrecord_t *record) { @@ -108,10 +169,13 @@ bool process_record_quantum(keyrecord_t *record) {    if (!(      process_record_kb(keycode, record) && -  #ifdef MIDI_ENABLE +  #if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED)      process_midi(keycode, record) &&    #endif    #ifdef AUDIO_ENABLE +    process_audio(keycode, record) && +  #endif +  #if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))      process_music(keycode, record) &&    #endif    #ifdef TAP_DANCE_ENABLE @@ -123,12 +187,18 @@ bool process_record_quantum(keyrecord_t *record) {    #ifndef DISABLE_CHORDING      process_chording(keycode, record) &&    #endif +  #ifdef COMBO_ENABLE +    process_combo(keycode, record) && +  #endif    #ifdef UNICODE_ENABLE      process_unicode(keycode, record) &&    #endif    #ifdef UCIS_ENABLE      process_ucis(keycode, record) &&    #endif +  #ifdef PRINTING_ENABLE +    process_printer(keycode, record) && +  #endif    #ifdef UNICODEMAP_ENABLE      process_unicode_map(keycode, record) &&    #endif @@ -152,6 +222,26 @@ bool process_record_quantum(keyrecord_t *record) {        }  	  return false;        break; +  #ifdef FAUXCLICKY_ENABLE +  case FC_TOG: +    if (record->event.pressed) { +      FAUXCLICKY_TOGGLE; +    } +    return false; +    break; +  case FC_ON: +    if (record->event.pressed) { +      FAUXCLICKY_ON; +    } +    return false; +    break; +  case FC_OFF: +    if (record->event.pressed) { +      FAUXCLICKY_OFF; +    } +    return false; +    break; +  #endif  	#ifdef RGBLIGHT_ENABLE  	case RGB_TOG:  		if (record->event.pressed) { @@ -202,6 +292,28 @@ bool process_record_quantum(keyrecord_t *record) {  	  return false;        break;  	#endif +    #ifdef PROTOCOL_LUFA +    case OUT_AUTO: +      if (record->event.pressed) { +        set_output(OUTPUT_AUTO); +      } +      return false; +      break; +    case OUT_USB: +      if (record->event.pressed) { +        set_output(OUTPUT_USB); +      } +      return false; +      break; +    #ifdef BLUETOOTH_ENABLE +    case OUT_BT: +      if (record->event.pressed) { +        set_output(OUTPUT_BLUETOOTH); +      } +      return false; +      break; +    #endif +    #endif      case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_NKRO:        if (record->event.pressed) {          // MAGIC actions (BOOTMAGIC without the boot) @@ -283,6 +395,7 @@ bool process_record_quantum(keyrecord_t *record) {      case KC_LSPO: {        if (record->event.pressed) {          shift_interrupted[0] = false; +        scs_timer[0] = timer_read ();          register_mods(MOD_BIT(KC_LSFT));        }        else { @@ -292,7 +405,7 @@ bool process_record_quantum(keyrecord_t *record) {              shift_interrupted[1] = true;            }          #endif -        if (!shift_interrupted[0]) { +        if (!shift_interrupted[0] && timer_elapsed(scs_timer[0]) < TAPPING_TERM) {            register_code(LSPO_KEY);            unregister_code(LSPO_KEY);          } @@ -305,6 +418,7 @@ bool process_record_quantum(keyrecord_t *record) {      case KC_RSPC: {        if (record->event.pressed) {          shift_interrupted[1] = false; +        scs_timer[1] = timer_read ();          register_mods(MOD_BIT(KC_RSFT));        }        else { @@ -314,7 +428,7 @@ bool process_record_quantum(keyrecord_t *record) {              shift_interrupted[1] = true;            }          #endif -        if (!shift_interrupted[1]) { +        if (!shift_interrupted[1] && timer_elapsed(scs_timer[1]) < TAPPING_TERM) {            register_code(RSPC_KEY);            unregister_code(RSPC_KEY);          } @@ -496,6 +610,15 @@ void matrix_scan_quantum() {    #ifdef TAP_DANCE_ENABLE      matrix_scan_tap_dance();    #endif + +  #ifdef COMBO_ENABLE +    matrix_scan_combo(); +  #endif + +  #if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN) +    backlight_task(); +  #endif +    matrix_scan_kb();  } @@ -513,34 +636,45 @@ static const uint8_t backlight_pin = BACKLIGHT_PIN;  #  define COM1x1 COM1A1  #  define OCR1x  OCR1A  #else -#  error "Backlight pin not supported - use B5, B6, or B7" +#  define NO_BACKLIGHT_CLOCK +#endif + +#ifndef BACKLIGHT_ON_STATE +#define BACKLIGHT_ON_STATE 0  #endif  __attribute__ ((weak))  void backlight_init_ports(void)  { -  // Setup backlight pin as output and output low. +  // Setup backlight pin as output and output to on state.    // DDRx |= n    _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF); -  // PORTx &= ~n -  _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); +  #if BACKLIGHT_ON_STATE == 0 +    // PORTx &= ~n +    _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); +  #else +    // PORTx |= n +    _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF); +  #endif -  // Use full 16-bit resolution. -  ICR1 = 0xFFFF; +  #ifndef NO_BACKLIGHT_CLOCK +    // 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 +    // 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 +    // 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; +    TCCR1A = _BV(COM1x1) | _BV(WGM11); // = 0b00001010; +    TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001; +  #endif    backlight_init();    #ifdef BACKLIGHT_BREATHING @@ -552,30 +686,73 @@ __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 BACKLIGHT_ON_STATE == 0 +  //   // PORTx &= ~n +  //   _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); +  // #else +  //   // PORTx |= n +  //   _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF); +  // #endif    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)); -  } +    #ifndef NO_BACKLIGHT_CLOCK +      // Turn off PWM control on backlight pin, revert to output low. +      TCCR1A &= ~(_BV(COM1x1)); +      OCR1x = 0x0; +    #else +      // #if BACKLIGHT_ON_STATE == 0 +      //   // PORTx |= n +      //   _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF); +      // #else +      //   // PORTx &= ~n +      //   _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); +      // #endif +    #endif +  }  +  #ifndef NO_BACKLIGHT_CLOCK +    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)); +    } +  #endif    #ifdef BACKLIGHT_BREATHING      breathing_intensity_default();    #endif  } +uint8_t backlight_tick = 0; + +void backlight_task(void) { +  #ifdef NO_BACKLIGHT_CLOCK +  if ((0xFFFF >> ((BACKLIGHT_LEVELS - backlight_config.level) * ((BACKLIGHT_LEVELS + 1) / 2))) & (1 << backlight_tick)) {  +    #if BACKLIGHT_ON_STATE == 0 +      // PORTx &= ~n +      _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); +    #else +      // PORTx |= n +      _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF); +    #endif +  } else { +    #if BACKLIGHT_ON_STATE == 0 +      // PORTx |= n +      _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF); +    #else +      // PORTx &= ~n +      _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); +    #endif +  } +  backlight_tick = (backlight_tick + 1) % 16; +  #endif +}  #ifdef BACKLIGHT_BREATHING @@ -799,6 +976,64 @@ void backlight_set(uint8_t level)  #endif // backlight +// Functions for spitting out values +// + +void send_dword(uint32_t number) { // this might not actually work +    uint16_t word = (number >> 16); +    send_word(word); +    send_word(number & 0xFFFFUL); +} + +void send_word(uint16_t number) { +    uint8_t byte = number >> 8; +    send_byte(byte); +    send_byte(number & 0xFF); +} + +void send_byte(uint8_t number) { +    uint8_t nibble = number >> 4; +    send_nibble(nibble); +    send_nibble(number & 0xF); +} + +void send_nibble(uint8_t number) { +    switch (number) { +        case 0: +            register_code(KC_0); +            unregister_code(KC_0); +            break; +        case 1 ... 9: +            register_code(KC_1 + (number - 1)); +            unregister_code(KC_1 + (number - 1)); +            break; +        case 0xA ... 0xF: +            register_code(KC_A + (number - 0xA)); +            unregister_code(KC_A + (number - 0xA)); +            break; +    } +} + + +__attribute__((weak)) +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 api_send_unicode(uint32_t unicode) { +#ifdef API_ENABLE +    uint8_t chunk[4]; +    dword_to_bytes(unicode, chunk); +    MT_SEND_DATA(DT_UNICODE, chunk, 5); +#endif +}  __attribute__ ((weak))  void led_set_user(uint8_t usb_led) { | 
