summaryrefslogtreecommitdiffstats
path: root/tmk_core
diff options
context:
space:
mode:
authorTobias Matt <t.matt81+github@gmail.com>2016-05-13 10:08:29 +0200
committerTobias Matt <t.matt81+github@gmail.com>2016-05-13 10:08:29 +0200
commit65645fb8cad05307b9faf9a897eefd5ae8c46dad (patch)
treec522c0cd320c4930b7532d892c0831b148c98e93 /tmk_core
parent4122ad3f7b0e0dc1083a54b51430c8d7207d74ef (diff)
parent69f05e1afd2e046938209e00db62d18efead4932 (diff)
downloadqmk_firmware-65645fb8cad05307b9faf9a897eefd5ae8c46dad.tar.gz
qmk_firmware-65645fb8cad05307b9faf9a897eefd5ae8c46dad.tar.xz
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'tmk_core')
-rw-r--r--tmk_core/common/action.c105
-rw-r--r--tmk_core/common/action_code.h5
-rw-r--r--tmk_core/common/action_layer.c8
-rw-r--r--tmk_core/common/action_macro.c8
-rw-r--r--tmk_core/common/action_tapping.c8
-rw-r--r--tmk_core/common/action_util.c70
-rw-r--r--tmk_core/common/action_util.h20
-rw-r--r--tmk_core/common/backlight.c5
-rw-r--r--tmk_core/common/backlight.h1
-rw-r--r--tmk_core/common/command.c4
-rw-r--r--tmk_core/common/nodebug.h12
-rw-r--r--tmk_core/doc/keymap.md8
-rw-r--r--tmk_core/rules.mk9
13 files changed, 228 insertions, 35 deletions
diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c
index 0162fbd63..081e90b2d 100644
--- a/tmk_core/common/action.c
+++ b/tmk_core/common/action.c
@@ -27,11 +27,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "action_util.h"
#include "action.h"
-//#ifdef DEBUG_ACTION
+#ifdef DEBUG_ACTION
#include "debug.h"
-//#else
-//#include "nodebug.h"
-//#endif
+#else
+#include "nodebug.h"
+#endif
void action_exec(keyevent_t event)
@@ -74,6 +74,7 @@ void process_action_kb(keyrecord_t *record) {}
void process_action(keyrecord_t *record)
{
+ bool do_release_oneshot = false;
keyevent_t event = record->event;
#ifndef NO_ACTION_TAPPING
uint8_t tap_count = record->tap.count;
@@ -81,6 +82,13 @@ void process_action(keyrecord_t *record)
if (IS_NOEVENT(event)) { return; }
+#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
+
process_action_kb(record);
action_t action = store_or_get_action(event.pressed, event.key);
@@ -95,6 +103,15 @@ void process_action(keyrecord_t *record)
// clear the potential weak mods left by previously pressed keys
clear_weak_mods();
}
+
+#ifndef NO_ACTION_ONESHOT
+ // notice we only clear the one shot layer if the pressed key is not a modifier.
+ if (is_oneshot_layer_active() && event.pressed && !IS_MOD(action.key.code)) {
+ clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
+ do_release_oneshot = !is_oneshot_layer_active();
+ }
+#endif
+
switch (action.kind.id) {
/* Key and Mods */
case ACT_LMODS:
@@ -139,24 +156,37 @@ void process_action(keyrecord_t *record)
// Oneshot modifier
if (event.pressed) {
if (tap_count == 0) {
+ dprint("MODS_TAP: Oneshot: 0\n");
register_mods(mods);
- }
- else if (tap_count == 1) {
+ } else if (tap_count == 1) {
dprint("MODS_TAP: Oneshot: start\n");
set_oneshot_mods(mods);
- }
- else {
+ #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
+ } else if (tap_count == ONESHOT_TAP_TOGGLE) {
+ dprint("MODS_TAP: Toggling oneshot");
+ clear_oneshot_mods();
+ set_oneshot_locked_mods(mods);
+ register_mods(mods);
+ #endif
+ } else {
register_mods(mods);
}
} else {
if (tap_count == 0) {
clear_oneshot_mods();
unregister_mods(mods);
- }
- else if (tap_count == 1) {
+ } else if (tap_count == 1) {
// Retain Oneshot mods
- }
- else {
+ #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
+ if (mods & get_mods()) {
+ clear_oneshot_locked_mods();
+ clear_oneshot_mods();
+ unregister_mods(mods);
+ }
+ } else if (tap_count == ONESHOT_TAP_TOGGLE) {
+ // Toggle Oneshot Layer
+ #endif
+ } else {
clear_oneshot_mods();
unregister_mods(mods);
}
@@ -309,6 +339,44 @@ void process_action(keyrecord_t *record)
event.pressed ? layer_move(action.layer_tap.val) :
layer_clear();
break;
+ #ifndef NO_ACTION_ONESHOT
+ case OP_ONESHOT:
+ // Oneshot modifier
+ #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
+ do_release_oneshot = false;
+ if (event.pressed) {
+ del_mods(get_oneshot_locked_mods());
+ if (get_oneshot_layer_state() == ONESHOT_TOGGLED) {
+ reset_oneshot_layer();
+ layer_off(action.layer_tap.val);
+ break;
+ } else if (tap_count < ONESHOT_TAP_TOGGLE) {
+ layer_on(action.layer_tap.val);
+ set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
+ }
+ } else {
+ add_mods(get_oneshot_locked_mods());
+ if (tap_count >= ONESHOT_TAP_TOGGLE) {
+ reset_oneshot_layer();
+ clear_oneshot_locked_mods();
+ set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED);
+ } else {
+ clear_oneshot_layer_state(ONESHOT_PRESSED);
+ }
+ }
+ #else
+ if (event.pressed) {
+ layer_on(action.layer_tap.val);
+ set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
+ } else {
+ clear_oneshot_layer_state(ONESHOT_PRESSED);
+ if (tap_count > 1) {
+ clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
+ }
+ }
+ #endif
+ break;
+ #endif
default:
/* tap key */
if (event.pressed) {
@@ -372,6 +440,18 @@ void process_action(keyrecord_t *record)
default:
break;
}
+
+#ifndef NO_ACTION_ONESHOT
+ /* Because we switch layers after a oneshot event, we need to release the
+ * key before we leave the layer or no key up event will be generated.
+ */
+ if (do_release_oneshot && !(get_oneshot_layer_state() & ONESHOT_PRESSED ) ) {
+ record->event.pressed = false;
+ layer_on(get_oneshot_layer());
+ process_action(record);
+ layer_off(get_oneshot_layer());
+ }
+#endif
}
@@ -560,6 +640,7 @@ bool is_tap_key(keypos_t key)
switch (action.layer_tap.code) {
case 0x00 ... 0xdf:
case OP_TAP_TOGGLE:
+ case OP_ONESHOT:
return true;
}
return false;
diff --git a/tmk_core/common/action_code.h b/tmk_core/common/action_code.h
index 2b0b0b077..ca729aaec 100644
--- a/tmk_core/common/action_code.h
+++ b/tmk_core/common/action_code.h
@@ -76,7 +76,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* 101E|LLLL|1111 0001 On/Off (0xF1) [NOT TAP]
* 101E|LLLL|1111 0010 Off/On (0xF2) [NOT TAP]
* 101E|LLLL|1111 0011 Set/Clear (0xF3) [NOT TAP]
- * 101E|LLLL|1111 xxxx Reserved (0xF4-FF)
+ * 101E|LLLL|1111 0100 One Shot Layer (0xF4) [TAP]
+ * 101E|LLLL|1111 xxxx Reserved (0xF5-FF)
* ELLLL: layer 0-31(E: extra bit for layer 16-31)
*
*
@@ -250,6 +251,7 @@ enum layer_pram_tap_op {
OP_ON_OFF,
OP_OFF_ON,
OP_SET_CLEAR,
+ OP_ONESHOT,
};
#define ACTION_LAYER_BITOP(op, part, bits, on) (ACT_LAYER<<12 | (op)<<10 | (on)<<8 | (part)<<5 | ((bits)&0x1f))
#define ACTION_LAYER_TAP(layer, key) (ACT_LAYER_TAP<<12 | (layer)<<8 | (key))
@@ -266,6 +268,7 @@ enum layer_pram_tap_op {
#define ACTION_LAYER_ON_OFF(layer) ACTION_LAYER_TAP((layer), OP_ON_OFF)
#define ACTION_LAYER_OFF_ON(layer) ACTION_LAYER_TAP((layer), OP_OFF_ON)
#define ACTION_LAYER_SET_CLEAR(layer) ACTION_LAYER_TAP((layer), OP_SET_CLEAR)
+#define ACTION_LAYER_ONESHOT(layer) ACTION_LAYER_TAP((layer), OP_ONESHOT)
#define ACTION_LAYER_MODS(layer, mods) ACTION_LAYER_TAP((layer), 0xe0 | ((mods)&0x0f))
/* With Tapping */
#define ACTION_LAYER_TAP_KEY(layer, key) ACTION_LAYER_TAP((layer), (key))
diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c
index 845fbbb21..63fa2b5ae 100644
--- a/tmk_core/common/action_layer.c
+++ b/tmk_core/common/action_layer.c
@@ -4,11 +4,11 @@
#include "util.h"
#include "action_layer.h"
-//#ifdef DEBUG_ACTION
+#ifdef DEBUG_ACTION
#include "debug.h"
-//#else
-//#include "nodebug.h"
-//#endif
+#else
+#include "nodebug.h"
+#endif
/*
diff --git a/tmk_core/common/action_macro.c b/tmk_core/common/action_macro.c
index cc78c8232..7726b1190 100644
--- a/tmk_core/common/action_macro.c
+++ b/tmk_core/common/action_macro.c
@@ -19,11 +19,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "action_macro.h"
#include "wait.h"
-//#ifdef DEBUG_ACTION
+#ifdef DEBUG_ACTION
#include "debug.h"
-//#else
-//#include "nodebug.h"
-//#endif
+#else
+#include "nodebug.h"
+#endif
#ifndef NO_ACTION_MACRO
diff --git a/tmk_core/common/action_tapping.c b/tmk_core/common/action_tapping.c
index 6b6fa1dfe..e6343e6da 100644
--- a/tmk_core/common/action_tapping.c
+++ b/tmk_core/common/action_tapping.c
@@ -6,11 +6,11 @@
#include "keycode.h"
#include "timer.h"
-//#ifdef DEBUG_ACTION
+#ifdef DEBUG_ACTION
#include "debug.h"
-//#else
-//#include "nodebug.h"
-//#endif
+#else
+#include "nodebug.h"
+#endif
#ifndef NO_ACTION_TAPPING
diff --git a/tmk_core/common/action_util.c b/tmk_core/common/action_util.c
index a2d6577b2..61ff202be 100644
--- a/tmk_core/common/action_util.c
+++ b/tmk_core/common/action_util.c
@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "report.h"
#include "debug.h"
#include "action_util.h"
+#include "action_layer.h"
#include "timer.h"
static inline void add_key_byte(uint8_t code);
@@ -47,11 +48,70 @@ report_keyboard_t *keyboard_report = &(report_keyboard_t){};
#ifndef NO_ACTION_ONESHOT
static int8_t oneshot_mods = 0;
+static int8_t oneshot_locked_mods = 0;
+int8_t get_oneshot_locked_mods(void) { return oneshot_locked_mods; }
+void set_oneshot_locked_mods(int8_t mods) { oneshot_locked_mods = mods; }
+void clear_oneshot_locked_mods(void) { oneshot_locked_mods = 0; }
#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
static int16_t oneshot_time = 0;
+inline bool has_oneshot_mods_timed_out() {
+ return TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT;
+}
#endif
#endif
+/* oneshot layer */
+#ifndef NO_ACTION_ONESHOT
+/* oneshot_layer_data bits
+* LLLL LSSS
+* where:
+* L => are layer bits
+* S => oneshot state bits
+*/
+static int8_t oneshot_layer_data = 0;
+
+inline uint8_t get_oneshot_layer(void) { return oneshot_layer_data >> 3; }
+inline uint8_t get_oneshot_layer_state(void) { return oneshot_layer_data & 0b111; }
+
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+static int16_t oneshot_layer_time = 0;
+inline bool has_oneshot_layer_timed_out() {
+ return TIMER_DIFF_16(timer_read(), oneshot_layer_time) >= ONESHOT_TIMEOUT &&
+ !(get_oneshot_layer_state() & ONESHOT_TOGGLED);
+}
+#endif
+
+/* Oneshot layer */
+void set_oneshot_layer(uint8_t layer, uint8_t state)
+{
+ oneshot_layer_data = layer << 3 | state;
+ layer_on(layer);
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+ oneshot_layer_time = timer_read();
+#endif
+}
+void reset_oneshot_layer(void) {
+ oneshot_layer_data = 0;
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+ oneshot_layer_time = 0;
+#endif
+}
+void clear_oneshot_layer_state(oneshot_fullfillment_t state)
+{
+ uint8_t start_state = oneshot_layer_data;
+ oneshot_layer_data &= ~state;
+ if (!get_oneshot_layer_state() && start_state != oneshot_layer_data) {
+ layer_off(get_oneshot_layer());
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+ oneshot_layer_time = 0;
+#endif
+ }
+}
+bool is_oneshot_layer_active(void)
+{
+ return get_oneshot_layer_state();
+}
+#endif
void send_keyboard_report(void) {
keyboard_report->mods = real_mods;
@@ -60,7 +120,7 @@ void send_keyboard_report(void) {
#ifndef NO_ACTION_ONESHOT
if (oneshot_mods) {
#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
- if (TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT) {
+ if (has_oneshot_mods_timed_out()) {
dprintf("Oneshot: timeout\n");
clear_oneshot_mods();
}
@@ -70,6 +130,7 @@ void send_keyboard_report(void) {
clear_oneshot_mods();
}
}
+
#endif
host_keyboard_send(keyboard_report);
}
@@ -143,11 +204,12 @@ void clear_oneshot_mods(void)
oneshot_time = 0;
#endif
}
+uint8_t get_oneshot_mods(void)
+{
+ return oneshot_mods;
+}
#endif
-
-
-
/*
* inspect keyboard state
*/
diff --git a/tmk_core/common/action_util.h b/tmk_core/common/action_util.h
index 1a95cec10..dd0c4c2bf 100644
--- a/tmk_core/common/action_util.h
+++ b/tmk_core/common/action_util.h
@@ -56,10 +56,30 @@ void clear_macro_mods(void);
/* oneshot modifier */
void set_oneshot_mods(uint8_t mods);
+uint8_t get_oneshot_mods(void);
void clear_oneshot_mods(void);
void oneshot_toggle(void);
void oneshot_enable(void);
void oneshot_disable(void);
+bool has_oneshot_mods_timed_out(void);
+
+int8_t get_oneshot_locked_mods(void);
+void set_oneshot_locked_mods(int8_t mods);
+void clear_oneshot_locked_mods(void);
+
+typedef enum {
+ ONESHOT_PRESSED = 0b01,
+ ONESHOT_OTHER_KEY_PRESSED = 0b10,
+ ONESHOT_START = 0b11,
+ ONESHOT_TOGGLED = 0b100
+} oneshot_fullfillment_t;
+void set_oneshot_layer(uint8_t layer, uint8_t state);
+uint8_t get_oneshot_layer(void);
+void clear_oneshot_layer_state(oneshot_fullfillment_t state);
+void reset_oneshot_layer(void);
+bool is_oneshot_layer_active(void);
+uint8_t get_oneshot_layer_state(void);
+bool has_oneshot_layer_timed_out(void);
/* inspect */
uint8_t has_anykey(void);
diff --git a/tmk_core/common/backlight.c b/tmk_core/common/backlight.c
index 2f6fc1cd6..c9e8fd3fd 100644
--- a/tmk_core/common/backlight.c
+++ b/tmk_core/common/backlight.c
@@ -83,3 +83,8 @@ void backlight_level(uint8_t level)
eeconfig_update_backlight(backlight_config.raw);
backlight_set(backlight_config.level);
}
+
+uint8_t get_backlight_level(void)
+{
+ return backlight_config.level;
+} \ No newline at end of file
diff --git a/tmk_core/common/backlight.h b/tmk_core/common/backlight.h
index 525ec8bbe..f57309267 100644
--- a/tmk_core/common/backlight.h
+++ b/tmk_core/common/backlight.h
@@ -36,5 +36,6 @@ void backlight_toggle(void);
void backlight_step(void);
void backlight_set(uint8_t level);
void backlight_level(uint8_t level);
+uint8_t get_backlight_level(void);
#endif
diff --git a/tmk_core/common/command.c b/tmk_core/common/command.c
index f06abaf7f..9edcc42a0 100644
--- a/tmk_core/common/command.c
+++ b/tmk_core/common/command.c
@@ -357,9 +357,11 @@ static bool command_common(uint8_t code)
clear_keyboard(); // clear to prevent stuck keys
print("\n\nJumping to bootloader... ");
#ifdef AUDIO_ENABLE
+ stop_all_notes();
play_goodbye_tone();
+ #else
+ _delay_ms(1000);
#endif
- _delay_ms(1000);
bootloader_jump(); // not return
break;
diff --git a/tmk_core/common/nodebug.h b/tmk_core/common/nodebug.h
index 93309ada4..5e18656e5 100644
--- a/tmk_core/common/nodebug.h
+++ b/tmk_core/common/nodebug.h
@@ -16,10 +16,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NODEBUG_H
-#define NODEBUG_H 1
+#define NODEBUG_H
-#define NO_DEBUG
-#include "debug.h"
-#undef NO_DEBUG
+#ifndef NO_DEBUG
+ #define NO_DEBUG
+ #include "debug.h"
+ #undef NO_DEBUG
+#else
+ #include "debug.h"
+#endif
#endif
diff --git a/tmk_core/doc/keymap.md b/tmk_core/doc/keymap.md
index d4a129b20..4d42fbe5c 100644
--- a/tmk_core/doc/keymap.md
+++ b/tmk_core/doc/keymap.md
@@ -528,14 +528,20 @@ This is a feature to assign both toggle layer and momentary switch layer action
### 4.3 Oneshot Modifier
-This runs onetime effects which modify only on just one following key. It works as normal modifier key when holding down while oneshot modifier when tapping.
+This runs onetime effects which modify only on just one following key. It works as normal modifier key when holding down while oneshot modifier when tapping. The behavior of oneshot modifiers is similar to the [sticky keys](https://en.wikipedia.org/wiki/StickyKeys) functionality found in most operating systems.
ACTION_MODS_ONESHOT(MOD_LSFT)
+Oneshot layer key:
+
+ ACTION_LAYER_ONESHOT(MY_LAYER)
+
Say you want to type 'The', you have to push and hold Shift key before type 't' then release it before type 'h' and 'e', otherwise you'll get 'THe' or 'the' unintentionally. With Oneshot Modifier you can tap Shift then type 't', 'h' and 'e' normally, you don't need to holding Shift key properly here. This mean you can release Shift before 't' is pressed down.
Oneshot effect is cancel unless following key is pressed down within `ONESHOT_TIMEOUT` of `config.h`. No timeout when it is `0` or not defined.
+Most implementations of sticky keys allow you to lock a modifier by double tapping the modifier. The layer then remains locked untill the modifier is tapped again. To enable this behaviour for oneshot modifiers set `ONESHOT_TAP_TOGGLE` to the number taps required. The feature is disabled if `ONESHOT_TAP_TOGGLE<2` or not defined.
+
### 4.4 Tap Toggle Mods
Similar to layer tap toggle, this works as a momentary modifier when holding, but toggles on with several taps. A single tap will 'unstick' the modifier again.
diff --git a/tmk_core/rules.mk b/tmk_core/rules.mk
index 860fc1a93..69c7985b4 100644
--- a/tmk_core/rules.mk
+++ b/tmk_core/rules.mk
@@ -142,6 +142,9 @@ CFLAGS += $(CSTANDARD)
ifdef CONFIG_H
CFLAGS += -include $(CONFIG_H)
endif
+ifdef CONFIG_USER_H
+ CFLAGS += -include $(CONFIG_USER_H)
+endif
#---------------- Compiler Options C++ ----------------
@@ -176,6 +179,9 @@ CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
ifdef CONFIG_H
CPPFLAGS += -include $(CONFIG_H)
endif
+ifdef CONFIG_USER_H
+ CPPFLAGS += -include $(CONFIG_USER_H)
+endif
#---------------- Assembler Options ----------------
@@ -192,6 +198,9 @@ ASFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
ifdef CONFIG_H
ASFLAGS += -include $(CONFIG_H)
endif
+ifdef CONFIG_USER_H
+ ASFLAGS += -include $(CONFIG_USER_H)
+endif
#---------------- Library Options ----------------