X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=quantum%2Fquantum.c;h=5bb7b04d53159c459e2c218cfdcafb80827f8734;hb=a25dbaad327f834dad6fb572b074bab7be1e1d0f;hp=d3905decf2d1f76eaf6f05715aae0b0663a350e7;hpb=3f2c0bfa86150c9fc91d8f467ed3728beecbb480;p=qmk_firmware.git diff --git a/quantum/quantum.c b/quantum/quantum.c index d3905decf..5bb7b04d5 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -1,3 +1,19 @@ +/* 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 . + */ + #include "quantum.h" #ifdef PROTOCOL_LUFA #include "outputselect.h" @@ -7,6 +23,13 @@ #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) { case QK_MODS ... QK_MODS_MAX: @@ -91,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); @@ -112,7 +135,7 @@ void reset_keyboard(void) { #endif static bool shift_interrupted[2] = {0, 0}; -static uint16_t scs_timer = 0; +static uint16_t scs_timer[2] = {0, 0}; bool process_record_quantum(keyrecord_t *record) { @@ -146,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 @@ -196,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) { @@ -267,14 +313,6 @@ bool process_record_quantum(keyrecord_t *record) { return false; break; #endif - #ifdef ADAFRUIT_BLE_ENABLE - case OUT_BLE: - if (record->event.pressed) { - set_output(OUTPUT_ADAFRUIT_BLE); - } - return false; - break; - #endif #endif case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_NKRO: if (record->event.pressed) { @@ -357,7 +395,7 @@ bool process_record_quantum(keyrecord_t *record) { case KC_LSPO: { if (record->event.pressed) { shift_interrupted[0] = false; - scs_timer = timer_read (); + scs_timer[0] = timer_read (); register_mods(MOD_BIT(KC_LSFT)); } else { @@ -367,7 +405,7 @@ bool process_record_quantum(keyrecord_t *record) { shift_interrupted[1] = true; } #endif - if (!shift_interrupted[0] && timer_elapsed(scs_timer) < TAPPING_TERM) { + if (!shift_interrupted[0] && timer_elapsed(scs_timer[0]) < TAPPING_TERM) { register_code(LSPO_KEY); unregister_code(LSPO_KEY); } @@ -380,7 +418,7 @@ bool process_record_quantum(keyrecord_t *record) { case KC_RSPC: { if (record->event.pressed) { shift_interrupted[1] = false; - scs_timer = timer_read (); + scs_timer[1] = timer_read (); register_mods(MOD_BIT(KC_RSFT)); } else { @@ -390,7 +428,7 @@ bool process_record_quantum(keyrecord_t *record) { shift_interrupted[1] = true; } #endif - if (!shift_interrupted[1] && timer_elapsed(scs_timer) < TAPPING_TERM) { + if (!shift_interrupted[1] && timer_elapsed(scs_timer[1]) < TAPPING_TERM) { register_code(RSPC_KEY); unregister_code(RSPC_KEY); } @@ -399,6 +437,14 @@ bool process_record_quantum(keyrecord_t *record) { return false; // break; } + case GRAVE_ESC: { + void (*method)(uint8_t) = (record->event.pressed) ? &add_key : &del_key; + uint8_t shifted = get_mods() & ((MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT) + |MOD_BIT(KC_LGUI)|MOD_BIT(KC_RGUI))); + + method(shifted ? KC_GRAVE : KC_ESCAPE); + send_keyboard_report(); + } default: { shift_interrupted[0] = true; shift_interrupted[1] = true; @@ -409,7 +455,103 @@ bool process_record_quantum(keyrecord_t *record) { return process_action_kb(record); } -const bool ascii_to_qwerty_shift_lut[0x80] PROGMEM = { +#ifdef JIS_KEYCODE +static const uint16_t ascii_to_shift_lut[8] PROGMEM = { + 0x0000, /*0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,*/ + 0x0000, /*0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,*/ + 0x7ff0, /*0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0,*/ + 0x000f, /*0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 1,*/ + 0x7fff, /*0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1,*/ + 0xffe1, /*1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 1,*/ + 0x8000, /*1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,*/ + 0x001e, /*0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 0*/ +}; + +static const struct { + uint8_t controls_0[16], + controls_1[16], + numerics[16], + alphabets_0[16], + alphabets_1[16]; +} lower_to_keycode PROGMEM = { + .controls_0 = { + 0, 0, 0, 0, 0, 0, 0, 0, + KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0, + }, + .controls_1 = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, KC_ESC, 0, 0, 0, 0, + }, + .numerics = { + KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, + KC_8, KC_9, KC_QUOT, KC_SCLN, KC_COMM, KC_MINS, KC_DOT, KC_SLSH, + }, + .alphabets_0 = { + KC_LBRC, 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, + }, + .alphabets_1 = { + KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W, + KC_X, KC_Y, KC_Z, KC_RBRC, KC_JYEN, KC_BSLS, KC_EQL, KC_RO, + }, +}; +static const uint8_t* ascii_to_keycode_lut[8] = { + lower_to_keycode.controls_0, + lower_to_keycode.controls_1, + lower_to_keycode.numerics, + lower_to_keycode.numerics, + lower_to_keycode.alphabets_0, + lower_to_keycode.alphabets_1, + lower_to_keycode.alphabets_0, + lower_to_keycode.alphabets_1 +}; + +void send_string(const char *str) { + while (1) { + uint8_t keycode; + bool shift; + uint8_t ascii_code = pgm_read_byte(str); + + if ( ascii_code == 0x00u ){ break; } + else if (ascii_code == 0x20u) { + keycode = KC_SPC; + shift = false; + } + else if (ascii_code == 0x7Fu) { + keycode = KC_DEL; + shift = false; + } + else { + int hi = ascii_code>>4 & 0x0f, + lo = ascii_code & 0x0f; + keycode = pgm_read_byte(&ascii_to_keycode_lut[hi][lo]); + shift = !!( pgm_read_word(&ascii_to_shift_lut[hi]) & (0x8000u>>lo) ); + } + + if (shift) { + register_code(KC_LSFT); + register_code(keycode); + unregister_code(keycode); + unregister_code(KC_LSFT); + } + else { + register_code(keycode); + unregister_code(keycode); + } + ++str; + } +} + +#else +static 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, @@ -428,7 +570,7 @@ const bool ascii_to_qwerty_shift_lut[0x80] PROGMEM = { 0, 0, 0, 1, 1, 1, 1, 0 }; -const uint8_t ascii_to_qwerty_keycode_lut[0x80] PROGMEM = { +static 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, @@ -447,6 +589,28 @@ const uint8_t ascii_to_qwerty_keycode_lut[0x80] PROGMEM = { KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL }; +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 { + register_code(keycode); + unregister_code(keycode); + } + ++str; + } +} + +#endif + /* for users whose OSes are set to Colemak */ #if 0 #include "keymap_colemak.h" @@ -491,26 +655,6 @@ const uint8_t ascii_to_colemak_keycode_lut[0x80] PROGMEM = { #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 { - register_code(keycode); - unregister_code(keycode); - } - ++str; - } -} - 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); @@ -577,6 +721,10 @@ void matrix_scan_quantum() { matrix_scan_combo(); #endif + #if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN) + backlight_task(); + #endif + matrix_scan_kb(); } @@ -594,34 +742,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 @@ -633,30 +792,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 @@ -918,6 +1120,19 @@ void send_nibble(uint8_t number) { } } + +__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];