Compare commits

...

22 Commits
0.5.1 ... 0.5.7

Author SHA1 Message Date
Jack Humbert
198a2929ed Merge pull request #1059 from qmk/hf/algr_t
Introduces ALGR_T for dual-function AltGr
2017-02-06 19:33:33 -05:00
Jack Humbert
b5159c964a Merge pull request #1036 from nicinabox/lets-split-improvements
Lets Split flashing improvements
2017-02-06 19:33:07 -05:00
Jack Humbert
4348fb54d6 Merge pull request #960 from ofples/feature/combos
Keyboard combination triggers
2017-02-06 19:31:45 -05:00
Jack Humbert
b6ffda4849 Merge pull request #1010 from SjB/oneshot_timeout_fix
oneshot timeout would only timeout after an event.
2017-02-06 18:57:23 -05:00
Jack Humbert
449ab9109a Merge branch 'master' of github.com:jackhumbert/qmk_firmware 2017-02-06 18:28:50 -05:00
Jack Humbert
35edb382ee [skip build] testing travis script 2017-02-06 18:28:37 -05:00
Jack Humbert
0a3c5c06fe Merge pull request #981 from jonasoberschweiber/osx-surrogate-pairs
Add support for Unicode supplementary planes on OS X
2017-02-06 18:00:47 -05:00
Jack Humbert
5c8cdfd2b5 [skip build] testing travis script 2017-02-06 17:51:20 -05:00
Jack Humbert
246d2583ff Merge pull request #1030 from SjB/refactor_register_code16
speeding up (un)register_code16
2017-02-06 17:06:53 -05:00
Erez Zukerman
f46c2b3ca0 Introduces ALGR_T for dual-function AltGr 2017-01-31 21:31:05 -05:00
SjB
45e0d09414 moved oneshot cancellation code outside of process_record.
The oneshot cancellation code do not depend on the
action_tapping_process and since process_record get called via the
action_tapping_process logic moved the oneshot cancellation code into
the action_exec function just before the action_tapping_process call
2017-01-29 13:01:47 -05:00
SjB
f644b9a07a registering a weak_mods when using register_code16
Scenario:
Locking the KC_LSHIFT, and then using a tap dance key that registers a
S(KC_9) will unregister the KC_LSHIFT.

The tap dance or any keycode that is registered should not have the
side effect of cancelling a locked moditifier. We should be using a
similar logic as the TMK codes in tmk_core/comman/action.c:158.
2017-01-29 12:29:43 -05:00
Nic Aitch
890ecf6a2a Update readme 2017-01-26 09:31:40 -06:00
Nic Aitch
3131d65563 Add avrdude target 2017-01-26 09:31:27 -06:00
SjB
2b3859937b speeding up (un)register_code16
In register_code16 and unregister_code16 we call register_code and
unregister_code twice, once for the mods and once for the keycode.
The (un)register_code have many check to see that keycode we have sent
however because we know that we are sending it a mods key, why not
just skip all of it and call (un)register_mods instead. This will skip
alot of checks and should speedup the loop a little.
2017-01-23 23:16:57 -05:00
SjB
6f44ca7a59 oneshot timeout would only timeout after an event.
After setting a ONESHOT_TIMEOUT value, the oneshot layer state would
not expire without an event being triggered (key pressed). The reason
was that in the process_record function we would return priort to
execute the process_action function if it detected a NOEVENT cycle. The
process_action contained the codes to timeout the oneshot layer state.
The codes to clear the oneshot layer state have been move just in
front of where we check for the NOEVENT cycle in the process_record
function.
2017-01-15 23:29:24 -05:00
Jonas Oberschweiber
0aa413af44 Add support for supplementary planes for OS X 2016-12-31 19:37:56 +01:00
Ofer Plesser
40abf8bc9c Moved combo processing lower down in process logic 2016-12-16 22:00:29 +02:00
Ofer Plesser
6a462c818c Merge branch 'master' into feature/combos 2016-12-16 21:52:51 +02:00
Ofer Plesser
6e7cfa83b9 Refactored as well as added support for action keys in combos 2016-12-16 21:50:28 +02:00
Ofer Plesser
b6bf4e0dce Added support for timing out combos if a key as been pressed for longer than COMBO_TERM 2016-12-10 16:11:59 +02:00
Ofer Plesser
eac8fa7999 Implemented basic key combination feature 2016-12-10 00:49:11 +02:00
12 changed files with 260 additions and 12 deletions

View File

@@ -5,6 +5,7 @@ language: c
branches:
except:
- /^.*-automated-build$/
- /^[0-9]+\.[0-9]+\.[0-9]+/
env:
global:
- secure: vBTSL34BDPxDilKUuTXqU4CJ26Pv5hogD2nghatkxSQkI1/jbdnLj/DQdPUrMJFDIY6TK3AltsBx72MaMsLQ1JO/Ou24IeHINHXzUC1FlS9yQa48cpxnhX5kzXNyGs3oa0qaFbvnr7RgYRWtmD52n4bIZuSuW+xpBv05x2OCizdT2ZonH33nATaHGFasxROm4qYZ241VfzcUv766V6RVHgL4x9V08warugs+RENVkfzxxwhk3NmkrISabze0gSVJLHBPHxroZC6EUcf/ocobcuDrCwFqtEt90i7pNIAFUE7gZsN2uE75LmpzAWin21G7lLPcPL2k4FJVd8an1HiP2WmscJU6U89fOfMb2viObnKcCzebozBCmKGtHEuXZo9FcReOx49AnQSpmESJGs+q2dL/FApkTjQiyT4J6O5dJpoww0/r57Wx0cmmqjETKBb5rSgXM51Etk3wO09mvcPHsEwrT7qH8r9XWdyCDoEn7FCLX3/LYnf/D4SmZ633YPl5gv3v9XEwxR5+04akjgnvWDSNIaDbWBdxHNb7l4pMc+WR1bwCyMyA7KXj0RrftEGOrm9ZRLe6BkbT4cycA+j77nbPOMcyZChliV9pPQos+4TOJoTzcK2L8yWVoY409aDNVuAjdP6Yum0R2maBGl/etLmIMpJC35C5/lZ+dUNjJAM=

View File

@@ -144,6 +144,11 @@ ifeq ($(strip $(MIDI_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/process_keycode/process_midi.c
endif
ifeq ($(strip $(COMBO_ENABLE)), yes)
OPT_DEFS += -DCOMBO_ENABLE
SRC += $(QUANTUM_DIR)/process_keycode/process_combo.c
endif
ifeq ($(strip $(VIRTSER_ENABLE)), yes)
OPT_DEFS += -DVIRTSER_ENABLE
endif

View File

@@ -74,6 +74,10 @@ not be very difficult to adapt it to support more if required.
Flashing
--------
From the keymap directory run `make SUBPROJECT-KEYMAP-avrdude` for automatic serial port resolution and flashing.
Example: `make rev2-serial-avrdude`
If you define `EE_HANDS` in your `config.h`, you will need to set the
EEPROM for the left and right halves. The EEPROM is used to store whether the
half is left handed or right handed. This makes it so that the same firmware

View File

@@ -73,3 +73,13 @@ USE_I2C ?= yes
SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
CUSTOM_MATRIX = yes
avrdude: build
ls /dev/tty* > /tmp/1; \
echo "Reset your Pro Micro then hit any key to continue..."; \
read -n 1 -s; \
ls /dev/tty* > /tmp/2; \
USB=`diff /tmp/1 /tmp/2 | grep '>' | sed -e 's/> //'`; \
avrdude -p $(MCU) -c avr109 -P $$USB -U flash:w:$(BUILD_DIR)/$(TARGET).hex
.PHONY: avrdude

View File

@@ -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
}
}
}

View File

@@ -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

View File

@@ -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 {

View File

@@ -33,14 +33,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))
@@ -130,6 +158,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
@@ -508,6 +539,11 @@ void matrix_scan_quantum() {
#ifdef TAP_DANCE_ENABLE
matrix_scan_tap_dance();
#endif
#ifdef COMBO_ENABLE
matrix_scan_combo();
#endif
matrix_scan_kb();
}

View File

@@ -63,6 +63,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);

View File

@@ -290,6 +290,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

View File

@@ -49,6 +49,13 @@ void action_exec(keyevent_t event)
keyrecord_t record = { .event = event };
#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
if (has_oneshot_layer_timed_out()) {
dprintf("Oneshot layer: timeout\n");
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
}
#endif
#ifndef NO_ACTION_TAPPING
action_tapping_process(record);
#else
@@ -100,7 +107,7 @@ bool process_record_quantum(keyrecord_t *record) {
return true;
}
void process_record(keyrecord_t *record)
void process_record(keyrecord_t *record)
{
if (IS_NOEVENT(record->event)) { return; }
@@ -126,13 +133,6 @@ void process_action(keyrecord_t *record, action_t action)
uint8_t tap_count = record->tap.count;
#endif
#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
if (has_oneshot_layer_timed_out()) {
dprintf("Oneshot layer: timeout\n");
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
}
#endif
if (event.pressed) {
// clear the potential weak mods left by previously pressed keys
clear_weak_mods();

View File

@@ -20,7 +20,8 @@ increment_version ()
NEFM=$(git diff --name-only -n 1 ${TRAVIS_COMMIT_RANGE} | grep -Ev '^(keyboards/)' | wc -l)
if [[ $NEFM -gt 0 ]] ; then
echo "Essential files modified."
lasttag=$(git tag | grep -Ev '\-' | head -1)
git fetch --tags
lasttag=$(git tag | grep -Ev '\-' | xargs -I@ git log --format=format:"%ai @%n" -1 @ | sort -V | awk '{print $4}' | tail -1)
newtag=$(increment_version $lasttag)
git tag $newtag
git push --tags -q https://$GH_TOKEN@github.com/qmk/qmk_firmware