diff options
Diffstat (limited to 'tmk_core')
-rw-r--r-- | tmk_core/common.mk | 4 | ||||
-rw-r--r-- | tmk_core/common/action.c | 135 | ||||
-rw-r--r-- | tmk_core/common/action.h | 7 | ||||
-rw-r--r-- | tmk_core/common/action_code.h | 5 | ||||
-rw-r--r-- | tmk_core/common/action_tapping.c | 30 | ||||
-rw-r--r-- | tmk_core/common/action_util.c | 70 | ||||
-rw-r--r-- | tmk_core/common/action_util.h | 20 | ||||
-rw-r--r-- | tmk_core/common/avr/suspend.c | 5 | ||||
-rw-r--r-- | tmk_core/common/backlight.c | 5 | ||||
-rw-r--r-- | tmk_core/common/backlight.h | 1 | ||||
-rw-r--r-- | tmk_core/common/bootmagic.c | 14 | ||||
-rw-r--r-- | tmk_core/common/command.c | 17 | ||||
-rw-r--r-- | tmk_core/common/keyboard.c | 138 | ||||
-rw-r--r-- | tmk_core/common/matrix.h | 65 | ||||
-rw-r--r-- | tmk_core/common/nodebug.h | 12 | ||||
-rw-r--r-- | tmk_core/doc/keymap.md | 8 | ||||
-rw-r--r-- | tmk_core/protocol/lufa/lufa.c | 6 | ||||
-rw-r--r-- | tmk_core/rules.mk | 42 |
18 files changed, 384 insertions, 200 deletions
diff --git a/tmk_core/common.mk b/tmk_core/common.mk index 9cb2eb8ecd..b5d7e39dd1 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk @@ -60,6 +60,10 @@ ifeq ($(strip $(AUDIO_ENABLE)), yes) OPT_DEFS += -DAUDIO_ENABLE endif +ifeq ($(strip $(UNICODE_ENABLE)), yes) + OPT_DEFS += -DUNICODE_ENABLE +endif + ifeq ($(strip $(USB_6KRO_ENABLE)), yes) OPT_DEFS += -DUSB_6KRO_ENABLE endif diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index f9e6c17dc3..be6dea2b79 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -46,7 +46,7 @@ void action_exec(keyevent_t event) #ifndef NO_ACTION_TAPPING action_tapping_process(record); #else - process_action(&record); + process_record(&record); if (!IS_NOEVENT(record.event)) { dprint("processed: "); debug_record(record); dprintln(); } @@ -56,34 +56,32 @@ void action_exec(keyevent_t event) #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) bool disable_action_cache = false; -void process_action_nocache(keyrecord_t *record) +void process_record_nocache(keyrecord_t *record) { disable_action_cache = true; - process_action(record); + process_record(record); disable_action_cache = false; } #else -void process_action_nocache(keyrecord_t *record) +void process_record_nocache(keyrecord_t *record) { - process_action(record); + process_record(record); } #endif __attribute__ ((weak)) -void process_action_kb(keyrecord_t *record) {} +bool process_record_quantum(keyrecord_t *record) { + return true; +} -void process_action(keyrecord_t *record) +void process_record(keyrecord_t *record) { - keyevent_t event = record->event; -#ifndef NO_ACTION_TAPPING - uint8_t tap_count = record->tap.count; -#endif - - if (IS_NOEVENT(event)) { return; } + if (IS_NOEVENT(record->event)) { return; } - process_action_kb(record); + if(!process_record_quantum(record)) + return; - action_t action = store_or_get_action(event.pressed, event.key); + action_t action = store_or_get_action(record->event.pressed, record->event.key); dprint("ACTION: "); debug_action(action); #ifndef NO_ACTION_LAYER dprint(" layer_state: "); layer_debug(); @@ -91,10 +89,37 @@ void process_action(keyrecord_t *record) #endif dprintln(); + process_action(record, action); +} + +void process_action(keyrecord_t *record, action_t action) +{ + bool do_release_oneshot = false; + keyevent_t event = record->event; +#ifndef NO_ACTION_TAPPING + 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(); } + +#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 +164,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 +347,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 +448,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_record(record); + layer_off(get_oneshot_layer()); + } +#endif } @@ -560,6 +648,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.h b/tmk_core/common/action.h index 44ec3047ba..e8aa12a7cb 100644 --- a/tmk_core/common/action.h +++ b/tmk_core/common/action.h @@ -59,14 +59,15 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt); void action_function(keyrecord_t *record, uint8_t id, uint8_t opt); /* keyboard-specific key event (pre)processing */ -void process_action_kb(keyrecord_t *record); +bool process_record_quantum(keyrecord_t *record); /* Utilities for actions. */ #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) extern bool disable_action_cache; #endif -void process_action_nocache(keyrecord_t *record); -void process_action(keyrecord_t *record); +void process_record_nocache(keyrecord_t *record); +void process_record(keyrecord_t *record); +void process_action(keyrecord_t *record, action_t action); void register_code(uint8_t code); void unregister_code(uint8_t code); void register_mods(uint8_t mods); diff --git a/tmk_core/common/action_code.h b/tmk_core/common/action_code.h index 2b0b0b077e..ca729aaece 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_tapping.c b/tmk_core/common/action_tapping.c index e6343e6da7..ff78d7f2ab 100644 --- a/tmk_core/common/action_tapping.c +++ b/tmk_core/common/action_tapping.c @@ -89,7 +89,7 @@ bool process_tapping(keyrecord_t *keyp) debug("Tapping: First tap(0->1).\n"); tapping_key.tap.count = 1; debug_tapping_key(); - process_action(&tapping_key); + process_record(&tapping_key); // copy tapping state keyp->tap = tapping_key.tap; @@ -103,7 +103,7 @@ bool process_tapping(keyrecord_t *keyp) */ else if (IS_RELEASED(event) && waiting_buffer_typed(event)) { debug("Tapping: End. No tap. Interfered by typing key\n"); - process_action(&tapping_key); + process_record(&tapping_key); tapping_key = (keyrecord_t){}; debug_tapping_key(); // enqueue @@ -131,7 +131,7 @@ bool process_tapping(keyrecord_t *keyp) } // Release of key should be process immediately. debug("Tapping: release event of a key pressed before tapping\n"); - process_action(keyp); + process_record(keyp); return true; } else { @@ -148,7 +148,7 @@ bool process_tapping(keyrecord_t *keyp) if (IS_TAPPING_KEY(event.key) && !event.pressed) { debug("Tapping: Tap release("); debug_dec(tapping_key.tap.count); debug(")\n"); keyp->tap = tapping_key.tap; - process_action(keyp); + process_record(keyp); tapping_key = *keyp; debug_tapping_key(); return true; @@ -157,7 +157,7 @@ bool process_tapping(keyrecord_t *keyp) if (tapping_key.tap.count > 1) { debug("Tapping: Start new tap with releasing last tap(>1).\n"); // unregister key - process_action(&(keyrecord_t){ + process_record(&(keyrecord_t){ .tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, @@ -175,7 +175,7 @@ bool process_tapping(keyrecord_t *keyp) if (!IS_NOEVENT(event)) { debug("Tapping: key event while last tap(>0).\n"); } - process_action(keyp); + process_record(keyp); return true; } } @@ -185,7 +185,7 @@ bool process_tapping(keyrecord_t *keyp) if (tapping_key.tap.count == 0) { debug("Tapping: End. Timeout. Not tap(0): "); debug_event(event); debug("\n"); - process_action(&tapping_key); + process_record(&tapping_key); tapping_key = (keyrecord_t){}; debug_tapping_key(); return false; @@ -193,7 +193,7 @@ bool process_tapping(keyrecord_t *keyp) if (IS_TAPPING_KEY(event.key) && !event.pressed) { debug("Tapping: End. last timeout tap release(>0)."); keyp->tap = tapping_key.tap; - process_action(keyp); + process_record(keyp); tapping_key = (keyrecord_t){}; return true; } @@ -201,7 +201,7 @@ bool process_tapping(keyrecord_t *keyp) if (tapping_key.tap.count > 1) { debug("Tapping: Start new tap with releasing last timeout tap(>1).\n"); // unregister key - process_action(&(keyrecord_t){ + process_record(&(keyrecord_t){ .tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, @@ -219,7 +219,7 @@ bool process_tapping(keyrecord_t *keyp) if (!IS_NOEVENT(event)) { debug("Tapping: key event while last timeout tap(>0).\n"); } - process_action(keyp); + process_record(keyp); return true; } } @@ -233,7 +233,7 @@ bool process_tapping(keyrecord_t *keyp) keyp->tap = tapping_key.tap; if (keyp->tap.count < 15) keyp->tap.count += 1; debug("Tapping: Tap press("); debug_dec(keyp->tap.count); debug(")\n"); - process_action(keyp); + process_record(keyp); tapping_key = *keyp; debug_tapping_key(); return true; @@ -253,12 +253,12 @@ bool process_tapping(keyrecord_t *keyp) // should none in buffer // FIX: interrupted when other key is pressed tapping_key.tap.interrupted = true; - process_action(keyp); + process_record(keyp); return true; } } else { if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n"); - process_action(keyp); + process_record(keyp); return true; } } else { @@ -280,7 +280,7 @@ bool process_tapping(keyrecord_t *keyp) debug_tapping_key(); return true; } else { - process_action(keyp); + process_record(keyp); return true; } } @@ -347,7 +347,7 @@ void waiting_buffer_scan_tap(void) WITHIN_TAPPING_TERM(waiting_buffer[i].event)) { tapping_key.tap.count = 1; waiting_buffer[i].tap.count = 1; - process_action(&tapping_key); + process_record(&tapping_key); debug("waiting_buffer_scan_tap: found at ["); debug_dec(i); debug("]\n"); debug_waiting_buffer(); diff --git a/tmk_core/common/action_util.c b/tmk_core/common/action_util.c index a2d6577b24..61ff202bef 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 1a95cec10e..dd0c4c2bfe 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/avr/suspend.c b/tmk_core/common/avr/suspend.c index 4980680198..a6f3c64414 100644 --- a/tmk_core/common/avr/suspend.c +++ b/tmk_core/common/avr/suspend.c @@ -114,9 +114,7 @@ bool suspend_wakeup_condition(void) matrix_power_up(); matrix_scan(); matrix_power_down(); - for (uint8_t r = 0; r < MATRIX_ROWS; r++) { - if (matrix_get_row(r)) return true; - } + if (matrix_key_count()) return true; return false; } @@ -146,4 +144,3 @@ ISR(WDT_vect) } } #endif - diff --git a/tmk_core/common/backlight.c b/tmk_core/common/backlight.c index 2f6fc1cd6c..c9e8fd3fd2 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 525ec8bbef..f573092674 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/bootmagic.c b/tmk_core/common/bootmagic.c index 2c1b1adfc5..30e8a0f20f 100644 --- a/tmk_core/common/bootmagic.c +++ b/tmk_core/common/bootmagic.c @@ -105,15 +105,13 @@ void bootmagic(void) } } -static bool scan_keycode(uint8_t keycode) -{ - for (uint8_t r = 0; r < MATRIX_ROWS; r++) { +static bool scan_keycode(uint8_t keycode) { + for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { matrix_row_t matrix_row = matrix_get_row(r); - for (uint8_t c = 0; c < MATRIX_COLS; c++) { - if (matrix_row & ((matrix_row_t)1<<c)) { - if (keycode == keymap_key_to_keycode(0, (keypos_t){ .row = r, .col = c })) { - return true; - } + for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { + if (matrix_row & (matrix_row_t)1 << c) { + keypos_t key = (keypos_t){ .row = r, .col = c }; + if (keycode == keymap_key_to_keycode(0, key)) return true; } } } diff --git a/tmk_core/common/command.c b/tmk_core/common/command.c index f06abaf7f0..024d7c67a3 100644 --- a/tmk_core/common/command.c +++ b/tmk_core/common/command.c @@ -33,20 +33,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "led.h" #include "command.h" #include "backlight.h" +#include "quantum.h" #ifdef MOUSEKEY_ENABLE #include "mousekey.h" #endif #ifdef PROTOCOL_PJRC -# include "usb_keyboard.h" -# ifdef EXTRAKEY_ENABLE -# include "usb_extra.h" -# endif + #include "usb_keyboard.h" + #ifdef EXTRAKEY_ENABLE + #include "usb_extra.h" + #endif #endif #ifdef PROTOCOL_VUSB -# include "usbdrv.h" + #include "usbdrv.h" #endif #ifdef AUDIO_ENABLE @@ -357,9 +358,11 @@ static bool command_common(uint8_t code) clear_keyboard(); // clear to prevent stuck keys print("\n\nJumping to bootloader... "); #ifdef AUDIO_ENABLE - play_goodbye_tone(); + stop_all_notes(); + shutdown_user(); + #else + _delay_ms(1000); #endif - _delay_ms(1000); bootloader_jump(); // not return break; diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 1d99818481..bd543c45e1 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -1,5 +1,5 @@ /* -Copyright 2011,2012,2013 Jun Wako <wakojun@gmail.com> +Copyright 2011, 2012, 2013 Jun Wako <wakojun@gmail.com> 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 @@ -27,13 +27,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #include "command.h" #include "util.h" #include "sendchar.h" +#include "eeconfig.h" +#include "backlight.h" #ifdef BOOTMAGIC_ENABLE - #include "bootmagic.h" +# include "bootmagic.h" #else - #include "magic.h" +# include "magic.h" #endif -#include "eeconfig.h" -#include "backlight.h" #ifdef MOUSEKEY_ENABLE # include "mousekey.h" #endif @@ -41,40 +41,35 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. # include "ps2_mouse.h" #endif #ifdef SERIAL_MOUSE_ENABLE -#include "serial_mouse.h" +# include "serial_mouse.h" #endif #ifdef ADB_MOUSE_ENABLE -#include "adb.h" +# include "adb.h" #endif - #ifdef MATRIX_HAS_GHOST -static bool has_ghost_in_row(uint8_t row) -{ - matrix_row_t matrix_row = matrix_get_row(row); - // No ghost exists when less than 2 keys are down on the row - if (((matrix_row - 1) & matrix_row) == 0) - return false; - - // Ghost occurs when the row shares column line with other row - for (uint8_t i=0; i < MATRIX_ROWS; i++) { - if (i != row && (matrix_get_row(i) & matrix_row)) - return true; +static bool is_row_ghosting(uint8_t row){ + matrix_row_t state = matrix_get_row(row); + /* no ghosting happens when only one key in the row is pressed */ + if (!(state - 1 & state)) return false; + /* ghosting occurs when two keys in the same column are pressed */ + for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { + if (r != row && matrix_get_row(r) & state) return true; } return false; } + #endif +__attribute__ ((weak)) +void matrix_setup(void) { +} -__attribute__ ((weak)) void matrix_setup(void) {} -void keyboard_setup(void) -{ +void keyboard_setup(void) { matrix_setup(); } -void keyboard_init(void) -{ - +void keyboard_init(void) { timer_init(); matrix_init(); #ifdef PS2_MOUSE_ENABLE @@ -86,104 +81,85 @@ void keyboard_init(void) #ifdef ADB_MOUSE_ENABLE adb_mouse_init(); #endif - - #ifdef BOOTMAGIC_ENABLE bootmagic(); #else magic(); #endif - #ifdef BACKLIGHT_ENABLE backlight_init(); #endif - #if defined(NKRO_ENABLE) && defined(FORCE_NKRO) keyboard_nkro = true; #endif - } -/* - * Do keyboard routine jobs: scan mantrix, light LEDs, ... - * This is repeatedly called as fast as possible. - */ -void keyboard_task(void) -{ - static matrix_row_t matrix_prev[MATRIX_ROWS]; -#ifdef MATRIX_HAS_GHOST - static matrix_row_t matrix_ghost[MATRIX_ROWS]; -#endif - static uint8_t led_status = 0; - matrix_row_t matrix_row = 0; - matrix_row_t matrix_change = 0; - +/* does routine keyboard jobs */ +void keyboard_task(void) { + static uint8_t led_status; matrix_scan(); - for (uint8_t r = 0; r < MATRIX_ROWS; r++) { - matrix_row = matrix_get_row(r); - matrix_change = matrix_row ^ matrix_prev[r]; - if (matrix_change) { + for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { + static matrix_row_t previous_matrix[MATRIX_ROWS]; + matrix_row_t state = matrix_get_row(r); + matrix_row_t changes = state ^ previous_matrix[r]; + if (changes) { #ifdef MATRIX_HAS_GHOST - if (has_ghost_in_row(r)) { - /* Keep track of whether ghosted status has changed for - * debugging. But don't update matrix_prev until un-ghosted, or - * the last key would be lost. + static matrix_row_t deghosting_matrix[MATRIX_ROWS]; + if (is_row_ghosting(r)) { + /* debugs the deghosting mechanism */ + /* doesn't update previous_matrix until the ghosting has stopped + * in order to prevent the last key from being lost */ - if (debug_matrix && matrix_ghost[r] != matrix_row) { + if (debug_matrix && deghosting_matrix[r] != state) { matrix_print(); } - matrix_ghost[r] = matrix_row; + deghosting_matrix[r] = state; continue; } - matrix_ghost[r] = matrix_row; + deghosting_matrix[r] = state; #endif if (debug_matrix) matrix_print(); - for (uint8_t c = 0; c < MATRIX_COLS; c++) { - if (matrix_change & ((matrix_row_t)1<<c)) { - action_exec((keyevent_t){ - .key = (keypos_t){ .row = r, .col = c }, - .pressed = (matrix_row & ((matrix_row_t)1<<c)), - .time = (timer_read() | 1) /* time should not be 0 */ - }); |