diff options
Diffstat (limited to 'quantum')
-rw-r--r-- | quantum/config_common.h | 6 | ||||
-rw-r--r-- | quantum/keymap_common.c | 5 | ||||
-rwxr-xr-x | quantum/light_ws2812.c | 6 | ||||
-rw-r--r-- | quantum/matrix.c | 14 | ||||
-rw-r--r-- | quantum/process_keycode/process_combo.c | 134 | ||||
-rw-r--r-- | quantum/process_keycode/process_combo.h | 43 | ||||
-rw-r--r-- | quantum/process_keycode/process_unicode.c | 11 | ||||
-rw-r--r-- | quantum/quantum.c | 41 | ||||
-rw-r--r-- | quantum/quantum.h | 5 | ||||
-rw-r--r-- | quantum/quantum_keycodes.h | 13 | ||||
-rw-r--r-- | quantum/template/config.h | 2 |
11 files changed, 264 insertions, 16 deletions
diff --git a/quantum/config_common.h b/quantum/config_common.h index 4bdb2065d9..28f68b9c70 100644 --- a/quantum/config_common.h +++ b/quantum/config_common.h @@ -2,8 +2,10 @@ #define CONFIG_DEFINITIONS_H /* diode directions */ -#define COL2ROW 0 -#define ROW2COL 1 +#define COL2ROW 0 +#define ROW2COL 1 +#define CUSTOM_MATRIX 2 /* Disables built-in matrix scanning code */ + /* I/O pins */ #ifndef F0 #define B0 0x30 diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c index eced3d2bba..5190f24e87 100644 --- a/quantum/keymap_common.c +++ b/quantum/keymap_common.c @@ -80,7 +80,10 @@ action_t action_for_key(uint8_t layer, keypos_t key) action.code = keymap_function_id_to_action( (int)keycode & 0xFFF ); break; case QK_MACRO ... QK_MACRO_MAX: - action.code = ACTION_MACRO(keycode & 0xFF); + if (keycode & 0x800) // tap macros have upper bit set + action.code = ACTION_MACRO_TAP(keycode & 0xFF); + else + action.code = ACTION_MACRO(keycode & 0xFF); break; case QK_LAYER_TAP ... QK_LAYER_TAP_MAX: action.code = ACTION_LAYER_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF); diff --git a/quantum/light_ws2812.c b/quantum/light_ws2812.c index a883b13884..55bdd9cd81 100755 --- a/quantum/light_ws2812.c +++ b/quantum/light_ws2812.c @@ -70,7 +70,7 @@ void I2C_WriteBit(unsigned char c) // Inits bitbanging port, must be called before using the functions below // -void I2C_Init() +void I2C_Init(void) { I2C_PORT &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK)); @@ -82,7 +82,7 @@ void I2C_Init() // Send a START Condition // -void I2C_Start() +void I2C_Start(void) { // set both to high at the same time I2C_DDR &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK)); @@ -97,7 +97,7 @@ void I2C_Start() // Send a STOP Condition // -void I2C_Stop() +void I2C_Stop(void) { I2C_CLOCK_HI(); _delay_us(I2C_DELAY); diff --git a/quantum/matrix.c b/quantum/matrix.c index 07eb87bc36..ac523482ad 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c @@ -60,13 +60,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. extern const matrix_row_t matrix_mask[]; #endif +#if (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW) static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; +#endif /* matrix state(1:on, 0:off) */ static matrix_row_t matrix[MATRIX_ROWS]; -static matrix_row_t matrix_raw[MATRIX_ROWS]; static matrix_row_t matrix_debouncing[MATRIX_ROWS]; @@ -76,7 +77,7 @@ static matrix_row_t matrix_debouncing[MATRIX_ROWS]; static void unselect_rows(void); static void select_row(uint8_t row); static void unselect_row(uint8_t row); -#else // ROW2COL +#elif (DIODE_DIRECTION == ROW2COL) static void init_rows(void); static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col); static void unselect_cols(void); @@ -133,7 +134,7 @@ uint8_t matrix_cols(void) { // /* PORTxn */ // _SFR_IO8((col_pins[c] >> 4) + 2) |= _BV(col_pins[c] & 0xF); // } -// #else +// #elif (DIODE_DIRECTION == ROW2COL) // for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { // /* DDRxn */ // _SFR_IO8((col_pins[c] >> 4) + 1) |= _BV(col_pins[c] & 0xF); @@ -158,7 +159,7 @@ void matrix_init(void) { #if (DIODE_DIRECTION == COL2ROW) unselect_rows(); init_cols(); -#else // ROW2COL +#elif (DIODE_DIRECTION == ROW2COL) unselect_cols(); init_rows(); #endif @@ -166,7 +167,6 @@ void matrix_init(void) { // initialize matrix state: all keys off for (uint8_t i=0; i < MATRIX_ROWS; i++) { matrix[i] = 0; - matrix_raw[i] = 0; matrix_debouncing[i] = 0; } @@ -194,7 +194,7 @@ uint8_t matrix_scan(void) } -#else // ROW2COL +#elif (DIODE_DIRECTION == ROW2COL) // Set col, read rows for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { @@ -336,7 +336,7 @@ static void unselect_rows(void) } } -#else // ROW2COL +#elif (DIODE_DIRECTION == ROW2COL) static void init_rows(void) { diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c new file mode 100644 index 0000000000..e2189ad98b --- /dev/null +++ b/quantum/process_keycode/process_combo.c @@ -0,0 +1,134 @@ +#include "process_combo.h" +#include "print.h" + + +#define COMBO_TIMER_ELAPSED -1 + + +__attribute__ ((weak)) +combo_t key_combos[] = { + +}; + +__attribute__ ((weak)) +void process_combo_event(uint8_t combo_index, bool pressed) { + +} + +static uint8_t current_combo_index = 0; + +static inline void send_combo(uint16_t action, bool pressed) +{ + if (action) { + if (pressed) { + register_code16(action); + } else { + unregister_code16(action); + } + } else { + process_combo_event(current_combo_index, pressed); + } +} + +#define ALL_COMBO_KEYS_ARE_DOWN (((1<<count)-1) == combo->state) +#define NO_COMBO_KEYS_ARE_DOWN (0 == combo->state) +#define KEY_STATE_DOWN(key) do{ combo->state |= (1<<key); } while(0) +#define KEY_STATE_UP(key) do{ combo->state &= ~(1<<key); } while(0) +static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record) +{ + uint8_t count = 0; + uint8_t index = -1; + /* Find index of keycode and number of combo keys */ + for (const uint16_t *keys = combo->keys; ;++count) { + uint16_t key = pgm_read_word(&keys[count]); + if (keycode == key) index = count; + if (COMBO_END == key) break; + } + + /* Return if not a combo key */ + if (-1 == (int8_t)index) return false; + + /* The combos timer is used to signal whether the combo is active */ + bool is_combo_active = COMBO_TIMER_ELAPSED == combo->timer ? false : true; + + if (record->event.pressed) { + KEY_STATE_DOWN(index); + + if (is_combo_active) { + if (ALL_COMBO_KEYS_ARE_DOWN) { /* Combo was pressed */ + send_combo(combo->keycode, true); + combo->timer = COMBO_TIMER_ELAPSED; + } else { /* Combo key was pressed */ + combo->timer = timer_read(); +#ifdef COMBO_ALLOW_ACTION_KEYS + combo->prev_record = *record; +#else + combo->prev_key = keycode; +#endif + } + } + } else { + if (ALL_COMBO_KEYS_ARE_DOWN) { /* Combo was released */ + send_combo(combo->keycode, false); + } + + if (is_combo_active) { /* Combo key was tapped */ +#ifdef COMBO_ALLOW_ACTION_KEYS + record->event.pressed = true; + process_action(record, store_or_get_action(record->event.pressed, record->event.key)); + record->event.pressed = false; + process_action(record, store_or_get_action(record->event.pressed, record->event.key)); +#else + register_code16(keycode); + send_keyboard_report(); + unregister_code16(keycode); +#endif + combo->timer = 0; + } + + KEY_STATE_UP(index); + } + + if (NO_COMBO_KEYS_ARE_DOWN) { + combo->timer = 0; + } + + return is_combo_active; +} + +bool process_combo(uint16_t keycode, keyrecord_t *record) +{ + bool is_combo_key = false; + + for (current_combo_index = 0; current_combo_index < COMBO_COUNT; ++current_combo_index) { + combo_t *combo = &key_combos[current_combo_index]; + is_combo_key |= process_single_combo(combo, keycode, record); + } + + return !is_combo_key; +} + +void matrix_scan_combo(void) +{ + for (int i = 0; i < COMBO_COUNT; ++i) { + combo_t *combo = &key_combos[i]; + if (combo->timer && + combo->timer != COMBO_TIMER_ELAPSED && + timer_elapsed(combo->timer) > COMBO_TERM) { + + /* This disables the combo, meaning key events for this + * combo will be handled by the next processors in the chain + */ + combo->timer = COMBO_TIMER_ELAPSED; + +#ifdef COMBO_ALLOW_ACTION_KEYS + process_action(&combo->prev_record, + store_or_get_action(combo->prev_record.event.pressed, + combo->prev_record.event.key)); +#else + unregister_code16(combo->prev_key); + register_code16(combo->prev_key); +#endif + } + } +} diff --git a/quantum/process_keycode/process_combo.h b/quantum/process_keycode/process_combo.h new file mode 100644 index 0000000000..847f2b7376 --- /dev/null +++ b/quantum/process_keycode/process_combo.h @@ -0,0 +1,43 @@ +#ifndef PROCESS_COMBO_H +#define PROCESS_COMBO_H + +#include <stdint.h> +#include "progmem.h" +#include "quantum.h" + +typedef struct +{ + const uint16_t *keys; + uint16_t keycode; +#ifdef EXTRA_EXTRA_LONG_COMBOS + uint32_t state; +#elif EXTRA_LONG_COMBOS + uint16_t state; +#else + uint8_t state; +#endif + uint16_t timer; +#ifdef COMBO_ALLOW_ACTION_KEYS + keyrecord_t prev_record; +#else + uint16_t prev_key; +#endif +} combo_t; + + +#define COMBO(ck, ca) {.keys = &(ck)[0], .keycode = (ca)} +#define COMBO_ACTION(ck) {.keys = &(ck)[0]} + +#define COMBO_END 0 +#ifndef COMBO_COUNT +#define COMBO_COUNT 0 +#endif +#ifndef COMBO_TERM +#define COMBO_TERM TAPPING_TERM +#endif + +bool process_combo(uint16_t keycode, keyrecord_t *record); +void matrix_scan_combo(void); +void process_combo_event(uint8_t combo_index, bool pressed); + +#endif diff --git a/quantum/process_keycode/process_unicode.c b/quantum/process_keycode/process_unicode.c index a30e93ae32..9995ba9bde 100644 --- a/quantum/process_keycode/process_unicode.c +++ b/quantum/process_keycode/process_unicode.c @@ -141,7 +141,16 @@ bool process_unicode_map(uint16_t keycode, keyrecord_t *record) { const uint32_t* map = unicode_map; uint16_t index = keycode & 0x7FF; uint32_t code = pgm_read_dword_far(&map[index]); - if ((code > 0xFFFF && input_mode == UC_OSX) || (code > 0xFFFFF && input_mode == UC_LNX)) { + if (code > 0xFFFF && code <= 0x10ffff && input_mode == UC_OSX) { + // Convert to UTF-16 surrogate pair + code -= 0x10000; + uint32_t lo = code & 0x3ff; + uint32_t hi = (code & 0xffc00) >> 10; + unicode_input_start(); + register_hex32(hi + 0xd800); + register_hex32(lo + 0xdc00); + unicode_input_finish(); + } else if ((code > 0x10ffff && input_mode == UC_OSX) || (code > 0xFFFFF && input_mode == UC_LNX)) { // when character is out of range supported by the OS unicode_map_input_error(); } else { diff --git a/quantum/quantum.c b/quantum/quantum.c index 0aecd238e4..d3905decf2 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -1,4 +1,7 @@ #include "quantum.h" +#ifdef PROTOCOL_LUFA +#include "outputselect.h" +#endif #ifndef TAPPING_TERM #define TAPPING_TERM 200 @@ -158,6 +161,9 @@ 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 @@ -240,6 +246,36 @@ 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 + #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) { // MAGIC actions (BOOTMAGIC without the boot) @@ -536,6 +572,11 @@ void matrix_scan_quantum() { #ifdef TAP_DANCE_ENABLE matrix_scan_tap_dance(); #endif + + #ifdef COMBO_ENABLE + matrix_scan_combo(); + #endif + matrix_scan_kb(); } diff --git a/quantum/quantum.h b/quantum/quantum.h index e6adf974ab..18f072189d 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -15,7 +15,6 @@ #ifdef RGBLIGHT_ENABLE #include "rgblight.h" #endif - #include "action_layer.h" #include "eeconfig.h" #include <stddef.h> @@ -63,6 +62,10 @@ extern uint32_t default_layer_state; #include "process_printer.h" #endif +#ifdef COMBO_ENABLE + #include "process_combo.h" +#endif + #define SEND_STRING(str) send_string(PSTR(str)) void send_string(const char *str); diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index 4853655f95..8a78a58c9f 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -141,6 +141,16 @@ enum quantum_keycodes { PRINT_ON, PRINT_OFF, + // output selection + OUT_AUTO, + OUT_USB, +#ifdef BLUETOOTH_ENABLE + OUT_BT, +#endif +#ifdef ADAFRUIT_BLE_ENABLE + OUT_BLE, +#endif + // always leave at the end SAFE_RANGE }; @@ -246,8 +256,10 @@ enum quantum_keycodes { #define M(kc) (kc | QK_MACRO) +#define MACROTAP(kc) (kc | QK_MACRO | FUNC_TAP<<8) #define MACRODOWN(...) (record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE) + // L-ayer, T-ap - 256 keycode max, 16 layer max #define LT(layer, kc) (kc | QK_LAYER_TAP | ((layer & 0xF) << 8)) @@ -290,6 +302,7 @@ enum quantum_keycodes { #define CTL_T(kc) MT(MOD_LCTL, kc) #define SFT_T(kc) MT(MOD_LSFT, kc) #define ALT_T(kc) MT(MOD_LALT, kc) +#define ALGR_T(kc) MT(MOD_RALT, kc) // dual-function AltGR #define GUI_T(kc) MT(MOD_LGUI, kc) #define C_S_T(kc) MT((MOD_LCTL | MOD_LSFT), kc) // Control + Shift e.g. for gnome-terminal #define MEH_T(kc) MT((MOD_LCTL | MOD_LSFT | MOD_LALT), kc) // Meh is a less hyper version of the Hyper key -- doesn't include Win or Cmd, so just alt+shift+ctrl diff --git a/quantum/template/config.h b/quantum/template/config.h index b02f0c7ebc..c61c4a6181 100644 --- a/quantum/template/config.h +++ b/quantum/template/config.h @@ -46,7 +46,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define MATRIX_COL_PINS { F1, F0, B0 } #define UNUSED_PINS -/* COL2ROW or ROW2COL */ +/* COL2ROW, ROW2COL, or CUSTOM_MATRIX */ #define DIODE_DIRECTION COL2ROW // #define BACKLIGHT_PIN B7 |