forked from mirrors/qmk_userspace
		
	Initial version of new code for layer switch is added.
This commit is contained in:
		
					parent
					
						
							
								93e33fb8f6
							
						
					
				
			
			
				commit
				
					
						4ae979f6ef
					
				
			
		
					 19 changed files with 592 additions and 495 deletions
				
			
		| 
						 | 
				
			
			@ -2,7 +2,6 @@ COMMON_DIR = common
 | 
			
		|||
SRC +=	$(COMMON_DIR)/host.c \
 | 
			
		||||
	$(COMMON_DIR)/keyboard.c \
 | 
			
		||||
	$(COMMON_DIR)/command.c \
 | 
			
		||||
	$(COMMON_DIR)/layer.c \
 | 
			
		||||
	$(COMMON_DIR)/timer.c \
 | 
			
		||||
	$(COMMON_DIR)/print.c \
 | 
			
		||||
	$(COMMON_DIR)/debug.c \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,7 +23,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		|||
#include "debug.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
#include "layer.h"
 | 
			
		||||
#include "keyboard.h"
 | 
			
		||||
#include "matrix.h"
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
#include "command.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,6 +56,19 @@ uint8_t host_keyboard_leds(void)
 | 
			
		|||
    return (*driver->keyboard_leds)();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* new interface */
 | 
			
		||||
void host_register_key(uint8_t key)
 | 
			
		||||
{
 | 
			
		||||
    host_add_key(key);
 | 
			
		||||
    host_send_keyboard_report();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void host_unregister_key(uint8_t key)
 | 
			
		||||
{
 | 
			
		||||
    host_del_key(key);
 | 
			
		||||
    host_send_keyboard_report();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* keyboard report operations */
 | 
			
		||||
void host_add_key(uint8_t key)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -158,6 +171,14 @@ void host_send_keyboard_report(void)
 | 
			
		|||
{
 | 
			
		||||
    if (!driver) return;
 | 
			
		||||
    (*driver->send_keyboard)(keyboard_report);
 | 
			
		||||
 | 
			
		||||
    if (debug_keyboard) {
 | 
			
		||||
        print("keys: ");
 | 
			
		||||
        for (int i = 0; i < REPORT_KEYS; i++) {
 | 
			
		||||
            phex(keyboard_report->keys[i]); print(" ");
 | 
			
		||||
        }
 | 
			
		||||
        print(" mods: "); phex(keyboard_report->mods); print("\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void host_mouse_send(report_mouse_t *report)
 | 
			
		||||
| 
						 | 
				
			
			@ -216,7 +237,6 @@ static inline void del_key_byte(uint8_t code)
 | 
			
		|||
    for (; i < REPORT_KEYS; i++) {
 | 
			
		||||
        if (keyboard_report->keys[i] == code) {
 | 
			
		||||
            keyboard_report->keys[i] = 0;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,6 +39,10 @@ void host_set_driver(host_driver_t *driver);
 | 
			
		|||
host_driver_t *host_get_driver(void);
 | 
			
		||||
uint8_t host_keyboard_leds(void);
 | 
			
		||||
 | 
			
		||||
/* new interface */
 | 
			
		||||
void host_register_key(uint8_t key);
 | 
			
		||||
void host_unregister_key(uint8_t key);
 | 
			
		||||
 | 
			
		||||
/* keyboard report operations */
 | 
			
		||||
void host_add_key(uint8_t key);
 | 
			
		||||
void host_del_key(uint8_t key);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										557
									
								
								common/keyboard.c
									
										
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										557
									
								
								common/keyboard.c
									
										
									
									
									
										
										
										Normal file → Executable file
									
								
							| 
						 | 
				
			
			@ -15,15 +15,16 @@ You should have received a copy of the GNU General Public License
 | 
			
		|||
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
#include "keyboard.h"
 | 
			
		||||
#include "host.h"
 | 
			
		||||
#include "layer.h"
 | 
			
		||||
#include "matrix.h"
 | 
			
		||||
#include "keymap.h"
 | 
			
		||||
#include "host.h"
 | 
			
		||||
#include "led.h"
 | 
			
		||||
#include "usb_keycodes.h"
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
#include "print.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#include "command.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
#include "mousekey.h"
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -32,11 +33,377 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static uint8_t last_leds = 0;
 | 
			
		||||
#define LAYER_DELAY     250
 | 
			
		||||
 | 
			
		||||
typedef enum keykind {
 | 
			
		||||
    NONE,
 | 
			
		||||
    FN_DOWN, FN_UP,
 | 
			
		||||
    FNK_DOWN, FNK_UP,
 | 
			
		||||
    KEY_DOWN, KEY_UP,
 | 
			
		||||
    MOD_DOWN, MOD_UP,
 | 
			
		||||
    MOUSEKEY_DOWN, MOUSEKEY_UP,
 | 
			
		||||
    DELAY
 | 
			
		||||
} keykind_t;
 | 
			
		||||
 | 
			
		||||
typedef enum { IDLE, DELAYING, WAITING, PRESSING } kbdstate_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint8_t current_layer = 0;
 | 
			
		||||
uint8_t default_layer = 0;
 | 
			
		||||
 | 
			
		||||
/* keyboard internal states */
 | 
			
		||||
static kbdstate_t kbdstate = IDLE;
 | 
			
		||||
static uint8_t fn_state_bits = 0;
 | 
			
		||||
static keyrecord_t delayed_fn;
 | 
			
		||||
static keyrecord_t waiting_key;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static const char *state_str(kbdstate_t state)
 | 
			
		||||
{
 | 
			
		||||
    if (state == IDLE)      return PSTR("IDLE");
 | 
			
		||||
    if (state == DELAYING)  return PSTR("DELAYING");
 | 
			
		||||
    if (state == WAITING)   return PSTR("WAITING");
 | 
			
		||||
    if (state == PRESSING)  return PSTR("PRESSING");
 | 
			
		||||
    return PSTR("UNKNOWN");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline keykind_t get_keykind(uint8_t code, bool pressed)
 | 
			
		||||
{
 | 
			
		||||
    if IS_KEY(code) return (pressed ? KEY_DOWN      : KEY_UP);
 | 
			
		||||
    if IS_MOD(code) return (pressed ? MOD_DOWN      : MOD_UP);
 | 
			
		||||
    if IS_FN(code) {
 | 
			
		||||
        if (keymap_fn_keycode(FN_INDEX(code)))
 | 
			
		||||
            return (pressed ? FNK_DOWN : FNK_UP);
 | 
			
		||||
        else
 | 
			
		||||
            return (pressed ? FN_DOWN : FN_UP);
 | 
			
		||||
    }
 | 
			
		||||
    if IS_MOUSEKEY(code)    return (pressed ? MOUSEKEY_DOWN : MOUSEKEY_UP);
 | 
			
		||||
    return  NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void layer_switch_on(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    if (!IS_FN(code)) return;
 | 
			
		||||
    fn_state_bits |= FN_BIT(code);
 | 
			
		||||
    if (current_layer != keymap_fn_layer(FN_INDEX(code))) {
 | 
			
		||||
        //TODO: clear all key execpt Mod key
 | 
			
		||||
        debug("Layer Switch(on): "); debug_hex(current_layer);
 | 
			
		||||
        current_layer = keymap_fn_layer(FN_INDEX(code));
 | 
			
		||||
        debug(" -> "); debug_hex(current_layer); debug("\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void layer_switch_off(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    if (!IS_FN(code)) return;
 | 
			
		||||
    fn_state_bits &= ~FN_BIT(code);
 | 
			
		||||
    if (current_layer != keymap_fn_layer(biton(fn_state_bits))) {
 | 
			
		||||
        //TODO: clear all key execpt Mod key
 | 
			
		||||
        debug("Layer Switch(off): "); debug_hex(current_layer);
 | 
			
		||||
        current_layer = keymap_fn_layer(biton(fn_state_bits));
 | 
			
		||||
        debug(" -> "); debug_hex(current_layer); debug("\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline uint8_t get_keycode(key_t key)
 | 
			
		||||
{
 | 
			
		||||
    return keymap_get_keycode(current_layer, key.row, key.col);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// whether any key except modifier is down or not
 | 
			
		||||
static inline bool is_anykey_down(void)
 | 
			
		||||
{
 | 
			
		||||
    for (int r = 0; r < MATRIX_ROWS; r++) {
 | 
			
		||||
        matrix_row_t matrix_row = matrix_get_row(r);
 | 
			
		||||
        for (int c = 0; c < MATRIX_COLS; c++) {
 | 
			
		||||
            if (matrix_row && (1<<c)) {
 | 
			
		||||
                if (IS_KEY(get_keycode((key_t){ .row = r, .col = c }))) {
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void register_code(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    if IS_KEY(code) {
 | 
			
		||||
        host_add_key(code);
 | 
			
		||||
        host_send_keyboard_report();
 | 
			
		||||
    }
 | 
			
		||||
    else if IS_MOD(code) {
 | 
			
		||||
        host_add_mod_bit(MOD_BIT(code));
 | 
			
		||||
        host_send_keyboard_report();
 | 
			
		||||
    }
 | 
			
		||||
    else if IS_MOUSEKEY(code) {
 | 
			
		||||
        mousekey_on(code);
 | 
			
		||||
        mousekey_send();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void unregister_code(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    if IS_KEY(code) {
 | 
			
		||||
        host_del_key(code);
 | 
			
		||||
        host_send_keyboard_report();
 | 
			
		||||
    }
 | 
			
		||||
    else if IS_MOD(code) {
 | 
			
		||||
        host_del_mod_bit(MOD_BIT(code));
 | 
			
		||||
        host_send_keyboard_report();
 | 
			
		||||
    }
 | 
			
		||||
    else if IS_MOUSEKEY(code) {
 | 
			
		||||
        mousekey_off(code);
 | 
			
		||||
        mousekey_send();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *
 | 
			
		||||
 * Event/State|IDLE             DELAYING[f]     WAITING[f,k]        PRESSING
 | 
			
		||||
 * -----------+------------------------------------------------------------------
 | 
			
		||||
 * Fn  Down   |IDLE(L+)         WAITING(Sk)     WAITING(Sk)         -
 | 
			
		||||
 *     Up     |IDLE(L-)         IDLE(L-)        IDLE(L-)            IDLE(L-)  
 | 
			
		||||
 * Fnk Down   |DELAYING(Sf)     WAITING(Sk)     WAINTING(Sk)        PRESSING(Rf)
 | 
			
		||||
 *     Up     |IDLE(L-)         IDLE(Rf,Uf)     IDLE(Rf,Ps,Uf)*3    PRESSING(Uf)
 | 
			
		||||
 * Key Down   |PRESSING(Rk)     WAITING(Sk)     WAITING(Sk)         PRESSING(Rk)
 | 
			
		||||
 *     Up     |IDLE(Uk)         DELAYING(Uk)    IDLE(L+,Ps,Uk)      IDLE(Uk)*4
 | 
			
		||||
 * Delay      |-                IDLE(L+)        IDLE(L+,Ps)         -
 | 
			
		||||
 *            |
 | 
			
		||||
 * No key Down|IDLE(Ld)         IDLE(Ld)        IDLE(Ld)            IDLE(Ld)
 | 
			
		||||
 *
 | 
			
		||||
 * *2: register Fnk if any key is pressing
 | 
			
		||||
 * *3: when Fnk == Stored Fnk, if not ignore.
 | 
			
		||||
 * *4: when no registered key any more
 | 
			
		||||
 *
 | 
			
		||||
 * States:
 | 
			
		||||
 *      IDLE:
 | 
			
		||||
 *      DELAYING: delay layer switch after pressing Fn with alt keycode
 | 
			
		||||
 *      WAITING: key is pressed during DELAYING
 | 
			
		||||
 *
 | 
			
		||||
 * Events:
 | 
			
		||||
 *      Fn: Fn key without alternative keycode
 | 
			
		||||
 *      Fnk: Fn key with alternative keycode
 | 
			
		||||
 *      -: ignore
 | 
			
		||||
 *
 | 
			
		||||
 * Actions:
 | 
			
		||||
 *      Rk: register key
 | 
			
		||||
 *      Uk: unregister key
 | 
			
		||||
 *      Rf: register stored Fn(alt keycode)
 | 
			
		||||
 *      Uf: unregister stored Fn(alt keycode)
 | 
			
		||||
 *      Rs: register stored key
 | 
			
		||||
 *      Us: unregister stored key
 | 
			
		||||
 *      Sk: store key
 | 
			
		||||
 *      Sf: store Fn
 | 
			
		||||
 *      Ps: play stored key(Interpret stored key and transit state)
 | 
			
		||||
 *      L+: Switch to new layer(*retain* Modifiers only)
 | 
			
		||||
 *      L-: Switch back to last layer(*clear* stored key/Fn, *unregister* all Modifier/key)
 | 
			
		||||
 *      Ld: Switch back to default layer(*clear* stored key/Fn, *unregister* all Modifier/key)
 | 
			
		||||
 */
 | 
			
		||||
#define NEXT(state)     do { \
 | 
			
		||||
    debug("NEXT: "); print_P(state_str(kbdstate)); \
 | 
			
		||||
    kbdstate = state; \
 | 
			
		||||
    debug(" -> "); print_P(state_str(kbdstate)); debug("\n"); \
 | 
			
		||||
} while (0)
 | 
			
		||||
 | 
			
		||||
static inline void process_key(keyevent_t event)
 | 
			
		||||
{
 | 
			
		||||
    
 | 
			
		||||
    /* TODO: ring buffer
 | 
			
		||||
    static keyrecord_t waiting_keys[5];
 | 
			
		||||
    static uint8_t waiting_keys_head = 0;
 | 
			
		||||
    static uint8_t waiting_keys_tail = 0;
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    uint8_t code = get_keycode(event.key);
 | 
			
		||||
    keykind_t kind = get_keykind(code, event.pressed);
 | 
			
		||||
 | 
			
		||||
    uint8_t tmp_mods;
 | 
			
		||||
 | 
			
		||||
    //debug("kbdstate: "); debug_hex(kbdstate);
 | 
			
		||||
    debug("state: "); print_P(state_str(kbdstate));
 | 
			
		||||
    debug(" kind: "); debug_hex(kind);
 | 
			
		||||
    debug(" code: "); debug_hex(code);
 | 
			
		||||
    if (event.pressed) { debug("d"); } else { debug("u"); }
 | 
			
		||||
    debug("\n");
 | 
			
		||||
    switch (kbdstate) {
 | 
			
		||||
        case IDLE:
 | 
			
		||||
            switch (kind) {
 | 
			
		||||
                case FN_DOWN:
 | 
			
		||||
                    layer_switch_on(code);
 | 
			
		||||
                    break;
 | 
			
		||||
                case FN_UP:
 | 
			
		||||
                    layer_switch_off(code);
 | 
			
		||||
                    break;
 | 
			
		||||
                case FNK_DOWN:
 | 
			
		||||
                    // store event
 | 
			
		||||
                    delayed_fn = (keyrecord_t) { .event = event, .code = code, .mods = keyboard_report->mods, .time = timer_read() };
 | 
			
		||||
                    NEXT(DELAYING);
 | 
			
		||||
                    break;
 | 
			
		||||
                case FNK_UP:
 | 
			
		||||
                    layer_switch_off(code);
 | 
			
		||||
                    break;
 | 
			
		||||
                case KEY_DOWN:
 | 
			
		||||
                case MOUSEKEY_DOWN:
 | 
			
		||||
                    register_code(code);
 | 
			
		||||
                    NEXT(PRESSING);
 | 
			
		||||
                    break;
 | 
			
		||||
                case MOD_DOWN:
 | 
			
		||||
                    register_code(code);
 | 
			
		||||
                    break;
 | 
			
		||||
                case KEY_UP:
 | 
			
		||||
                case MOUSEKEY_UP:
 | 
			
		||||
                case MOD_UP:
 | 
			
		||||
                    unregister_code(code);
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case PRESSING:
 | 
			
		||||
            switch (kind) {
 | 
			
		||||
                case FN_DOWN:
 | 
			
		||||
                    // ignored when any key is pressed
 | 
			
		||||
                    break;
 | 
			
		||||
                case FN_UP:
 | 
			
		||||
                    layer_switch_off(code);
 | 
			
		||||
                    NEXT(IDLE);
 | 
			
		||||
                    break;
 | 
			
		||||
                case FNK_DOWN:
 | 
			
		||||
                    register_code(keymap_fn_keycode(FN_INDEX(code)));
 | 
			
		||||
                    break;
 | 
			
		||||
                case FNK_UP:
 | 
			
		||||
                    unregister_code(keymap_fn_keycode(FN_INDEX(code)));
 | 
			
		||||
                    break;
 | 
			
		||||
                case KEY_DOWN:
 | 
			
		||||
                case MOD_DOWN:
 | 
			
		||||
                case MOUSEKEY_DOWN:
 | 
			
		||||
                    register_code(code);
 | 
			
		||||
                    break;
 | 
			
		||||
                case KEY_UP:
 | 
			
		||||
                case MOD_UP:
 | 
			
		||||
                case MOUSEKEY_UP:
 | 
			
		||||
                    unregister_code(code);
 | 
			
		||||
                    // no key registered? mousekey, mediakey, systemkey
 | 
			
		||||
                    if (!host_has_anykey())
 | 
			
		||||
                        NEXT(IDLE);
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case DELAYING:
 | 
			
		||||
            switch (kind) {
 | 
			
		||||
                case FN_DOWN:
 | 
			
		||||
                case FNK_DOWN:
 | 
			
		||||
                case KEY_DOWN:
 | 
			
		||||
                case MOUSEKEY_DOWN:
 | 
			
		||||
                    waiting_key = (keyrecord_t) { .event = event, .code = code, .mods = keyboard_report->mods, .time = timer_read() };
 | 
			
		||||
                    NEXT(WAITING);
 | 
			
		||||
                    break;
 | 
			
		||||
                case MOD_DOWN:
 | 
			
		||||
                    register_code(code);
 | 
			
		||||
                    break;
 | 
			
		||||
                case FN_UP:
 | 
			
		||||
                    layer_switch_off(code);
 | 
			
		||||
                    NEXT(IDLE);
 | 
			
		||||
                    break;
 | 
			
		||||
                case FNK_UP:
 | 
			
		||||
                    if (code == delayed_fn.code) {
 | 
			
		||||
                        // type Fn with alt keycode
 | 
			
		||||
                        // restore the mod status at the time of pressing Fn key
 | 
			
		||||
                        tmp_mods = keyboard_report->mods;
 | 
			
		||||
                        host_set_mods(delayed_fn.mods);
 | 
			
		||||
                        register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
 | 
			
		||||
                        unregister_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
 | 
			
		||||
                        host_set_mods(tmp_mods);
 | 
			
		||||
                        NEXT(IDLE);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        layer_switch_off(code);
 | 
			
		||||
                        NEXT(IDLE);
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                case KEY_UP:
 | 
			
		||||
                case MOUSEKEY_UP:
 | 
			
		||||
                    unregister_code(code);
 | 
			
		||||
                    NEXT(IDLE);
 | 
			
		||||
                    break;
 | 
			
		||||
                case MOD_UP:
 | 
			
		||||
                    unregister_code(code);
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case WAITING:
 | 
			
		||||
            switch (kind) {
 | 
			
		||||
                case FN_DOWN:
 | 
			
		||||
                case FNK_DOWN:
 | 
			
		||||
                case KEY_DOWN:
 | 
			
		||||
                case MOUSEKEY_DOWN:
 | 
			
		||||
                    tmp_mods = keyboard_report->mods;
 | 
			
		||||
                    host_set_mods(delayed_fn.mods);
 | 
			
		||||
                    register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
 | 
			
		||||
                    host_set_mods(waiting_key.mods);
 | 
			
		||||
                    register_code(waiting_key.code);
 | 
			
		||||
                    host_set_mods(tmp_mods);
 | 
			
		||||
                    register_code(code);
 | 
			
		||||
                    NEXT(IDLE);
 | 
			
		||||
                    break;
 | 
			
		||||
                case MOD_DOWN:
 | 
			
		||||
                    register_code(code);
 | 
			
		||||
                    break;
 | 
			
		||||
                case FN_UP:
 | 
			
		||||
                    layer_switch_off(code);
 | 
			
		||||
                    NEXT(IDLE);
 | 
			
		||||
                    break;
 | 
			
		||||
                case FNK_UP:
 | 
			
		||||
                    if (code == delayed_fn.code) {
 | 
			
		||||
                        // alt down, key down, alt up
 | 
			
		||||
                        tmp_mods = keyboard_report->mods;
 | 
			
		||||
                        host_set_mods(delayed_fn.mods);
 | 
			
		||||
                        register_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
 | 
			
		||||
                        host_set_mods(waiting_key.mods);
 | 
			
		||||
                        register_code(waiting_key.code);
 | 
			
		||||
                        unregister_code(keymap_fn_keycode(FN_INDEX(delayed_fn.code)));
 | 
			
		||||
                        host_set_mods(tmp_mods);
 | 
			
		||||
                        NEXT(IDLE);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        layer_switch_off(code);
 | 
			
		||||
                        NEXT(IDLE);
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                case KEY_UP:
 | 
			
		||||
                case MOUSEKEY_UP:
 | 
			
		||||
                    if (code == waiting_key.code) {
 | 
			
		||||
                        layer_switch_on(delayed_fn.code);
 | 
			
		||||
                        NEXT(IDLE);
 | 
			
		||||
                        // process waiting_key
 | 
			
		||||
                        tmp_mods = keyboard_report->mods;
 | 
			
		||||
                        host_set_mods(waiting_key.mods);
 | 
			
		||||
                        process_key(waiting_key.event);
 | 
			
		||||
                        host_set_mods(tmp_mods);
 | 
			
		||||
                        process_key(event);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        unregister_code(code);
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                case MOD_UP:
 | 
			
		||||
                    unregister_code(code);
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO: FAIL SAFE: unregister all keys when no key down
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void keyboard_init(void)
 | 
			
		||||
{
 | 
			
		||||
    debug_keyboard = true;
 | 
			
		||||
 | 
			
		||||
    timer_init();
 | 
			
		||||
    matrix_init();
 | 
			
		||||
#ifdef PS2_MOUSE_ENABLE
 | 
			
		||||
| 
						 | 
				
			
			@ -44,150 +411,66 @@ void keyboard_init(void)
 | 
			
		|||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void keyboard_proc(void)
 | 
			
		||||
void keyboard_task(void)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t fn_bits = 0;
 | 
			
		||||
#ifdef EXTRAKEY_ENABLE
 | 
			
		||||
    uint16_t consumer_code = 0;
 | 
			
		||||
    uint16_t system_code = 0;
 | 
			
		||||
#endif
 | 
			
		||||
    static matrix_row_t matrix_prev[MATRIX_ROWS];
 | 
			
		||||
    matrix_row_t matrix_row = 0;
 | 
			
		||||
    matrix_row_t matrix_change = 0;
 | 
			
		||||
 | 
			
		||||
    matrix_scan();
 | 
			
		||||
 | 
			
		||||
    if (matrix_is_modified()) {
 | 
			
		||||
        if (debug_matrix) matrix_print();
 | 
			
		||||
#ifdef DEBUG_LED
 | 
			
		||||
        // LED flash for debug
 | 
			
		||||
        DEBUG_LED_CONFIG;
 | 
			
		||||
        DEBUG_LED_ON;
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (matrix_has_ghost()) {
 | 
			
		||||
        // should send error?
 | 
			
		||||
        debug("matrix has ghost!!\n");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    host_swap_keyboard_report();
 | 
			
		||||
    host_clear_keyboard_report();
 | 
			
		||||
    for (int row = 0; row < matrix_rows(); row++) {
 | 
			
		||||
        for (int col = 0; col < matrix_cols(); col++) {
 | 
			
		||||
            if (!matrix_is_on(row, col)) continue;
 | 
			
		||||
 | 
			
		||||
            uint8_t code = layer_get_keycode(row, col);
 | 
			
		||||
            if (code == KB_NO) {
 | 
			
		||||
                // do nothing
 | 
			
		||||
            } else if (IS_MOD(code)) {
 | 
			
		||||
                host_add_mod_bit(MOD_BIT(code));
 | 
			
		||||
            } else if (IS_FN(code)) {
 | 
			
		||||
                fn_bits |= FN_BIT(code);
 | 
			
		||||
            }
 | 
			
		||||
// TODO: use table or something
 | 
			
		||||
#ifdef EXTRAKEY_ENABLE
 | 
			
		||||
            // System Control
 | 
			
		||||
            else if (code == KB_SYSTEM_POWER) {
 | 
			
		||||
#ifdef HOST_PJRC
 | 
			
		||||
                if (suspend && remote_wakeup) {
 | 
			
		||||
                    usb_remote_wakeup();
 | 
			
		||||
                }
 | 
			
		||||
#endif
 | 
			
		||||
                system_code = SYSTEM_POWER_DOWN;
 | 
			
		||||
            } else if (code == KB_SYSTEM_SLEEP) {
 | 
			
		||||
                system_code = SYSTEM_SLEEP;
 | 
			
		||||
            } else if (code == KB_SYSTEM_WAKE) {
 | 
			
		||||
                system_code = SYSTEM_WAKE_UP;
 | 
			
		||||
            }
 | 
			
		||||
            // Consumer Page
 | 
			
		||||
            else if (code == KB_AUDIO_MUTE) {
 | 
			
		||||
                consumer_code = AUDIO_MUTE;
 | 
			
		||||
            } else if (code == KB_AUDIO_VOL_UP) {
 | 
			
		||||
                consumer_code = AUDIO_VOL_UP;
 | 
			
		||||
            } else if (code == KB_AUDIO_VOL_DOWN) {
 | 
			
		||||
                consumer_code = AUDIO_VOL_DOWN;
 | 
			
		||||
            }
 | 
			
		||||
            else if (code == KB_MEDIA_NEXT_TRACK) {
 | 
			
		||||
                consumer_code = TRANSPORT_NEXT_TRACK;
 | 
			
		||||
            } else if (code == KB_MEDIA_PREV_TRACK) {
 | 
			
		||||
                consumer_code = TRANSPORT_PREV_TRACK;
 | 
			
		||||
            } else if (code == KB_MEDIA_STOP) {
 | 
			
		||||
                consumer_code = TRANSPORT_STOP;
 | 
			
		||||
            } else if (code == KB_MEDIA_PLAY_PAUSE) {
 | 
			
		||||
                consumer_code = TRANSPORT_PLAY_PAUSE;
 | 
			
		||||
            } else if (code == KB_MEDIA_SELECT) {
 | 
			
		||||
                consumer_code = AL_CC_CONFIG;
 | 
			
		||||
            }
 | 
			
		||||
            else if (code == KB_MAIL) {
 | 
			
		||||
                consumer_code = AL_EMAIL;
 | 
			
		||||
            } else if (code == KB_CALCULATOR) {
 | 
			
		||||
                consumer_code = AL_CALCULATOR;
 | 
			
		||||
            } else if (code == KB_MY_COMPUTER) {
 | 
			
		||||
                consumer_code = AL_LOCAL_BROWSER;
 | 
			
		||||
            }
 | 
			
		||||
            else if (code == KB_WWW_SEARCH) {
 | 
			
		||||
                consumer_code = AC_SEARCH;
 | 
			
		||||
            } else if (code == KB_WWW_HOME) {
 | 
			
		||||
                consumer_code = AC_HOME;
 | 
			
		||||
            } else if (code == KB_WWW_BACK) {
 | 
			
		||||
                consumer_code = AC_BACK;
 | 
			
		||||
            } else if (code == KB_WWW_FORWARD) {
 | 
			
		||||
                consumer_code = AC_FORWARD;
 | 
			
		||||
            } else if (code == KB_WWW_STOP) {
 | 
			
		||||
                consumer_code = AC_STOP;
 | 
			
		||||
            } else if (code == KB_WWW_REFRESH) {
 | 
			
		||||
                consumer_code = AC_REFRESH;
 | 
			
		||||
            } else if (code == KB_WWW_FAVORITES) {
 | 
			
		||||
                consumer_code = AC_BOOKMARKS;
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
            else if (IS_KEY(code)) {
 | 
			
		||||
                host_add_key(code);
 | 
			
		||||
            }
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
            else if (IS_MOUSEKEY(code)) {
 | 
			
		||||
                mousekey_decode(code);
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
            else {
 | 
			
		||||
                debug("ignore keycode: "); debug_hex(code); debug("\n");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    layer_switching(fn_bits);
 | 
			
		||||
 | 
			
		||||
    if (command_proc()) {
 | 
			
		||||
        debug("COMMAND\n");
 | 
			
		||||
        // TODO: clear all keys
 | 
			
		||||
        host_clear_keyboard_report();
 | 
			
		||||
        host_send_keyboard_report();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    for (int r = 0; r < MATRIX_ROWS; r++) {
 | 
			
		||||
        matrix_row = matrix_get_row(r);
 | 
			
		||||
        matrix_change = matrix_row ^ matrix_prev[r];
 | 
			
		||||
        if (matrix_change) {
 | 
			
		||||
            // TODO: print once per scan
 | 
			
		||||
            if (debug_matrix) matrix_print();
 | 
			
		||||
 | 
			
		||||
    // TODO: should send only when changed from last report
 | 
			
		||||
    if (matrix_is_modified()) {
 | 
			
		||||
        host_send_keyboard_report();
 | 
			
		||||
#ifdef EXTRAKEY_ENABLE
 | 
			
		||||
        host_consumer_send(consumer_code);
 | 
			
		||||
        host_system_send(system_code);
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef DEBUG_LED
 | 
			
		||||
        // LED flash for debug
 | 
			
		||||
        DEBUG_LED_CONFIG;
 | 
			
		||||
        DEBUG_LED_OFF;
 | 
			
		||||
#endif
 | 
			
		||||
            for (int c = 0; c < MATRIX_COLS; c++) {
 | 
			
		||||
                if (matrix_change & (1<<c)) {
 | 
			
		||||
                    process_key((keyevent_t){
 | 
			
		||||
                        .key = (key_t){ .row = r, .col = c },
 | 
			
		||||
                        .pressed = (matrix_row & (1<<c))
 | 
			
		||||
                    });
 | 
			
		||||
                    // record a processed key
 | 
			
		||||
                    matrix_prev[r] ^= (1<<c);
 | 
			
		||||
                    // process a key per task call
 | 
			
		||||
                    goto MATRIX_LOOP_END;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    MATRIX_LOOP_END:
 | 
			
		||||
    // TODO: FAIL SAFE: clear all key if no key down
 | 
			
		||||
 | 
			
		||||
    // layer switch when delay term elapses
 | 
			
		||||
    if (kbdstate == DELAYING || kbdstate == WAITING) {
 | 
			
		||||
        if (timer_elapsed(delayed_fn.time) > LAYER_DELAY) {
 | 
			
		||||
            if (kbdstate == DELAYING) {
 | 
			
		||||
                layer_switch_on(delayed_fn.code);
 | 
			
		||||
                NEXT(IDLE);
 | 
			
		||||
            }
 | 
			
		||||
            if (kbdstate == WAITING) {
 | 
			
		||||
                layer_switch_on(delayed_fn.code);
 | 
			
		||||
                NEXT(IDLE);
 | 
			
		||||
                uint8_t tmp_mods = keyboard_report->mods;
 | 
			
		||||
                host_set_mods(waiting_key.mods);
 | 
			
		||||
                process_key(waiting_key.event);
 | 
			
		||||
                host_set_mods(tmp_mods);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
    mousekey_send();
 | 
			
		||||
#endif
 | 
			
		||||
    // mousekey repeat & acceleration
 | 
			
		||||
    mousekey_task();
 | 
			
		||||
 | 
			
		||||
#ifdef PS2_MOUSE_ENABLE
 | 
			
		||||
    // TODO: should comform new API
 | 
			
		||||
    if (ps2_mouse_read() == 0)
 | 
			
		||||
        ps2_mouse_usb_send();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    if (last_leds != host_keyboard_leds()) {
 | 
			
		||||
        keyboard_set_leds(host_keyboard_leds());
 | 
			
		||||
        last_leds = host_keyboard_leds();
 | 
			
		||||
    }
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void keyboard_set_leds(uint8_t leds)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										28
									
								
								common/keyboard.h
									
										
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										28
									
								
								common/keyboard.h
									
										
									
									
									
										
										
										Normal file → Executable file
									
								
							| 
						 | 
				
			
			@ -18,15 +18,41 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		|||
#ifndef KEYBOARD_H
 | 
			
		||||
#define KEYBOARD_H
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t row;
 | 
			
		||||
    uint8_t col;
 | 
			
		||||
} key_t;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    key_t    key;
 | 
			
		||||
    bool     pressed;
 | 
			
		||||
} keyevent_t;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    keyevent_t  event;
 | 
			
		||||
    uint8_t     code;
 | 
			
		||||
    uint8_t     mods;
 | 
			
		||||
    uint16_t    time;
 | 
			
		||||
} keyrecord_t;
 | 
			
		||||
 | 
			
		||||
#define KEYEQ(keya, keyb)     (keya.row == keyb.row && keya.col == keyb.col)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern uint8_t current_layer;
 | 
			
		||||
extern uint8_t default_layer;
 | 
			
		||||
 | 
			
		||||
void keyboard_init(void);
 | 
			
		||||
void keyboard_proc(void);
 | 
			
		||||
void keyboard_task(void);
 | 
			
		||||
void keyboard_set_leds(uint8_t leds);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										207
									
								
								common/layer.c
									
										
									
									
									
								
							
							
						
						
									
										207
									
								
								common/layer.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,207 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 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
 | 
			
		||||
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 <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "keymap.h"
 | 
			
		||||
#include "host.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
#include "usb_keycodes.h"
 | 
			
		||||
#include "layer.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Parameters:
 | 
			
		||||
 *     SWITCH_DELAY        |=======|
 | 
			
		||||
 *     SEND_FN_TERM        |================|
 | 
			
		||||
 *
 | 
			
		||||
 * Fn key processing cases:
 | 
			
		||||
 * 1. release Fn after SEND_FN_TERM.
 | 
			
		||||
 *     Layer sw         ___________|~~~~~~~~~~~|___
 | 
			
		||||
 *     Fn press         ___|~~~~~~~~~~~~~~~~~~~|___
 | 
			
		||||
 *     Fn send          ___________________________
 | 
			
		||||
 *
 | 
			
		||||
 * 2. release Fn during SEND_FN_TERM.(not layer used)
 | 
			
		||||
 *     Layer sw         ___________|~~~~~~|________
 | 
			
		||||
 *     Fn press         ___|~~~~~~~~~~~~~~|________
 | 
			
		||||
 *     Fn key send      __________________|~|______
 | 
			
		||||
 *     other key press  ___________________________
 | 
			
		||||
 *     other key send   ___________________________
 | 
			
		||||
 *
 | 
			
		||||
 * 3. release Fn during SEND_FN_TERM.(layer used)
 | 
			
		||||
 *     Layer sw         ___________|~~~~~~|________
 | 
			
		||||
 *     Fn press         ___|~~~~~~~~~~~~~~|________
 | 
			
		||||
 *     Fn key send      ___________________________
 | 
			
		||||
 *     Fn send          ___________________________
 | 
			
		||||
 *     other key press  _____________|~~|__________
 | 
			
		||||
 *     other key send   _____________|~~|__________
 | 
			
		||||
 *
 | 
			
		||||
 * 4. press other key during SWITCH_DELAY.
 | 
			
		||||
 *     Layer sw         ___________________________
 | 
			
		||||
 *     Fn key press     ___|~~~~~~~~~|_____________
 | 
			
		||||
 *     Fn key send      ______|~~~~~~|_____________
 | 
			
		||||
 *     other key press  ______|~~~|________________
 | 
			
		||||
 *     other key send   _______|~~|________________
 | 
			
		||||
 *
 | 
			
		||||
 * 5. press Fn while press other key.
 | 
			
		||||
 *     Layer sw         ___________________________
 | 
			
		||||
 *     Fn key press     ___|~~~~~~~~~|_____________
 | 
			
		||||
 *     Fn key send      ___|~~~~~~~~~|_____________
 | 
			
		||||
 *     other key press  ~~~~~~~|___________________
 | 
			
		||||
 *     other key send   ~~~~~~~|___________________
 | 
			
		||||
 *
 | 
			
		||||
 * 6. press Fn twice quickly and keep holding down.(repeat)
 | 
			
		||||
 *     Layer sw         ___________________________
 | 
			
		||||
 *     Fn key press     ___|~|____|~~~~~~~~~~~~~~~~
 | 
			
		||||
 *     Fn key send      _____|~|__|~~~~~~~~~~~~~~~~
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// LAYER_SWITCH_DELAY: prevent from moving to new layer
 | 
			
		||||
#ifndef LAYER_SWITCH_DELAY
 | 
			
		||||
#   define LAYER_SWITCH_DELAY 150
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// LAYER_SEND_FN_TERM: send keycode if release key in this term
 | 
			
		||||
#ifndef LAYER_SEND_FN_TERM
 | 
			
		||||
#   define LAYER_SEND_FN_TERM 500
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint8_t default_layer = 0;
 | 
			
		||||
uint8_t current_layer = 0;
 | 
			
		||||
 | 
			
		||||
static bool layer_used = false;
 | 
			
		||||
static uint8_t new_layer(uint8_t fn_bits);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint8_t layer_get_keycode(uint8_t row, uint8_t col)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t code = keymap_get_keycode(current_layer, row, col);
 | 
			
		||||
    // normal key or mouse key
 | 
			
		||||
    if ((IS_KEY(code) || IS_MOUSEKEY(code))) {
 | 
			
		||||
        layer_used = true;
 | 
			
		||||
    }
 | 
			
		||||
    return code;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// bit substract b from a
 | 
			
		||||
#define BIT_SUBST(a, b) (a&(a^b))
 | 
			
		||||
void layer_switching(uint8_t fn_bits)
 | 
			
		||||
{
 | 
			
		||||
    // layer switching
 | 
			
		||||
    static uint8_t last_fn = 0;
 | 
			
		||||
    static uint8_t last_mods = 0;
 | 
			
		||||
    static uint16_t last_timer = 0; 
 | 
			
		||||
    static uint8_t sent_fn = 0;
 | 
			
		||||
 | 
			
		||||
    if (fn_bits == last_fn) { // Fn state is not changed
 | 
			
		||||
        if (fn_bits == 0) {
 | 
			
		||||
            // do nothing
 | 
			
		||||
        } else {
 | 
			
		||||
            if (!keymap_fn_keycode(BIT_SUBST(fn_bits, sent_fn)) ||
 | 
			
		||||
                    timer_elapsed(last_timer) > LAYER_SWITCH_DELAY) {
 | 
			
		||||
                uint8_t _layer_to_switch = new_layer(BIT_SUBST(fn_bits, sent_fn));
 | 
			
		||||
                if (current_layer != _layer_to_switch) { // not switch layer yet
 | 
			
		||||
                    debug("Fn case: 1,2,3(LAYER_SWITCH_DELAY passed)\n");
 | 
			
		||||
                    debug("Switch Layer: "); debug_hex(current_layer);
 | 
			
		||||
                    current_layer = _layer_to_switch;
 | 
			
		||||
                    layer_used = false;
 | 
			
		||||
                    debug(" -> "); debug_hex(current_layer); debug("\n");
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                if (host_has_anykey()) { // other keys is pressed
 | 
			
		||||
                    uint8_t _fn_to_send = BIT_SUBST(fn_bits, sent_fn);
 | 
			
		||||
                    if (_fn_to_send) {
 | 
			
		||||
                        debug("Fn case: 4(press other key during SWITCH_DELAY.)\n");
 | 
			
		||||
                        // send only Fn key first
 | 
			
		||||
                        uint8_t tmp_mods = keyboard_report->mods;
 | 
			
		||||
                        host_add_code(keymap_fn_keycode(_fn_to_send));
 | 
			
		||||
                        host_set_mods(last_mods);
 | 
			
		||||
                        host_send_keyboard_report();
 | 
			
		||||
                        host_set_mods(tmp_mods);
 | 
			
		||||
                        host_del_code(keymap_fn_keycode(_fn_to_send));
 | 
			
		||||
                        sent_fn |= _fn_to_send;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            // add Fn keys to send
 | 
			
		||||
            //host_add_code(keymap_fn_keycode(fn_bits&sent_fn));  // TODO: do all Fn keys
 | 
			
		||||
        }
 | 
			
		||||
    } else { // Fn state is changed(edge)
 | 
			
		||||
        uint8_t fn_changed = 0;
 | 
			
		||||
 | 
			
		||||
        debug("fn_bits: "); debug_bin(fn_bits); debug("\n");
 | 
			
		||||
        debug("sent_fn: "); debug_bin(sent_fn); debug("\n");
 | 
			
		||||
        debug("last_fn: "); debug_bin(last_fn); debug("\n");
 | 
			
		||||
        debug("last_mods: "); debug_hex(last_mods); debug("\n");
 | 
			
		||||
        debug("last_timer: "); debug_hex16(last_timer); debug("\n");
 | 
			
		||||
        debug("timer_count: "); debug_hex16(timer_count); debug("\n");
 | 
			
		||||
 | 
			
		||||
        // pressed Fn
 | 
			
		||||
        if ((fn_changed = BIT_SUBST(fn_bits, last_fn))) {
 | 
			
		||||
            debug("fn_changed: "); debug_bin(fn_changed); debug("\n");
 | 
			
		||||
            if (host_has_anykey()) {
 | 
			
		||||
                debug("Fn case: 5(pressed Fn with other key)\n");
 | 
			
		||||
                sent_fn |= fn_changed;
 | 
			
		||||
            } else if (fn_changed & sent_fn) { // pressed same Fn in a row
 | 
			
		||||
                if (timer_elapsed(last_timer) > LAYER_SEND_FN_TERM) {
 | 
			
		||||
                    debug("Fn case: 6(not repeat)\n");
 | 
			
		||||
                    // time passed: not repeate
 | 
			
		||||
                    sent_fn &= ~fn_changed;
 | 
			
		||||
                } else {
 | 
			
		||||
                    debug("Fn case: 6(repeat)\n");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // released Fn
 | 
			
		||||
        if ((fn_changed = BIT_SUBST(last_fn, fn_bits))) {
 | 
			
		||||
            debug("fn_changed: "); debug_bin(fn_changed); debug("\n");
 | 
			
		||||
            if (timer_elapsed(last_timer) < LAYER_SEND_FN_TERM) {
 | 
			
		||||
                if (!layer_used && BIT_SUBST(fn_changed, sent_fn)) {
 | 
			
		||||
                    debug("Fn case: 2(send Fn one shot: released Fn during LAYER_SEND_FN_TERM)\n");
 | 
			
		||||
                    // send only Fn key first
 | 
			
		||||
                    uint8_t tmp_mods = keyboard_report->mods;
 | 
			
		||||
                    host_add_code(keymap_fn_keycode(fn_changed));
 | 
			
		||||
                    host_set_mods(last_mods);
 | 
			
		||||
                    host_send_keyboard_report();
 | 
			
		||||
                    host_set_mods(tmp_mods);
 | 
			
		||||
                    host_del_code(keymap_fn_keycode(fn_changed));
 | 
			
		||||
                    sent_fn |= fn_changed;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            debug("Switch Layer(released Fn): "); debug_hex(current_layer);
 | 
			
		||||
            current_layer = new_layer(BIT_SUBST(fn_bits, sent_fn));
 | 
			
		||||
            debug(" -> "); debug_hex(current_layer); debug("\n");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        layer_used = false;
 | 
			
		||||
        last_fn = fn_bits;
 | 
			
		||||
        last_mods = keyboard_report->mods;
 | 
			
		||||
        last_timer = timer_read();
 | 
			
		||||
    }
 | 
			
		||||
    // send Fn keys
 | 
			
		||||
    for (uint8_t i = 0; i < 8; i++) {
 | 
			
		||||
        if ((sent_fn & fn_bits) & (1<<i)) {
 | 
			
		||||
            host_add_code(keymap_fn_keycode(1<<i));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
static uint8_t new_layer(uint8_t fn_bits)
 | 
			
		||||
{
 | 
			
		||||
    return (fn_bits ? keymap_fn_layer(fn_bits) : default_layer);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,32 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011 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
 | 
			
		||||
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 <http://www.gnu.org/licenses/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef LAYER_H
 | 
			
		||||
#define LAYER_H 1
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
extern uint8_t default_layer;
 | 
			
		||||
extern uint8_t current_layer;
 | 
			
		||||
 | 
			
		||||
/* return keycode for switch */
 | 
			
		||||
uint8_t layer_get_keycode(uint8_t row, uint8_t col);
 | 
			
		||||
 | 
			
		||||
/* process layer switching */
 | 
			
		||||
void layer_switching(uint8_t fn_bits);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -18,8 +18,23 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		|||
#ifndef MATRIX_H
 | 
			
		||||
#define MATRIX_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if (MATRIX_COLS <= 8)
 | 
			
		||||
typedef  uint8_t    matrix_row_t;
 | 
			
		||||
#elif (MATRIX_COLS <= 16)
 | 
			
		||||
typedef  uint16_t   matrix_row_t;
 | 
			
		||||
#elif (MATRIX_COLS <= 32)
 | 
			
		||||
typedef  uint32_t   matrix_row_t;
 | 
			
		||||
#else
 | 
			
		||||
#error "MATRIX_COLS: invalid value"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define MATRIX_IS_ON(row, col)  (matrix_get_row(row) && (1<<col))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* number of matrix rows */
 | 
			
		||||
uint8_t matrix_rows(void);
 | 
			
		||||
/* number of matrix columns */
 | 
			
		||||
| 
						 | 
				
			
			@ -35,11 +50,7 @@ bool matrix_has_ghost(void);
 | 
			
		|||
/* whether a swtich is on */
 | 
			
		||||
bool matrix_is_on(uint8_t row, uint8_t col);
 | 
			
		||||
/* matrix state on row */
 | 
			
		||||
#if (MATRIX_COLS <= 8)
 | 
			
		||||
uint8_t matrix_get_row(uint8_t row);
 | 
			
		||||
#else
 | 
			
		||||
uint16_t matrix_get_row(uint8_t row);
 | 
			
		||||
#endif
 | 
			
		||||
matrix_row_t  matrix_get_row(uint8_t row);
 | 
			
		||||
/* count keys pressed */
 | 
			
		||||
uint8_t matrix_key_count(void);
 | 
			
		||||
/* print matrix for debug */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
static report_mouse_t report;
 | 
			
		||||
static report_mouse_t report_prev;
 | 
			
		||||
 | 
			
		||||
static uint8_t mousekey_repeat =  0;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -38,84 +37,111 @@ static void mousekey_debug(void);
 | 
			
		|||
 * see wikipedia http://en.wikipedia.org/wiki/Mouse_keys
 | 
			
		||||
 */
 | 
			
		||||
#ifndef MOUSEKEY_DELAY_TIME
 | 
			
		||||
#   define MOUSEKEY_DELAY_TIME 255
 | 
			
		||||
#   define MOUSEKEY_DELAY_TIME 20
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define MOUSEKEY_MOVE_INIT      5
 | 
			
		||||
#define MOUSEKEY_WHEEL_INIT     1
 | 
			
		||||
#define MOUSEKEY_MOVE_ACCEL     5
 | 
			
		||||
#define MOUSEKEY_WHEEL_ACCEL    1
 | 
			
		||||
 | 
			
		||||
static uint16_t last_timer = 0;
 | 
			
		||||
 | 
			
		||||
// acceleration parameters
 | 
			
		||||
uint8_t mousekey_move_unit = 2;
 | 
			
		||||
uint8_t mousekey_resolution = 5;
 | 
			
		||||
//uint8_t mousekey_move_unit = 2;
 | 
			
		||||
//uint8_t mousekey_resolution = 5;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static inline uint8_t move_unit(void)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t unit = 5 + mousekey_repeat*2;
 | 
			
		||||
    uint16_t unit = 5 + mousekey_repeat*4;
 | 
			
		||||
    return (unit > 63 ? 63 : unit);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mousekey_decode(uint8_t code)
 | 
			
		||||
void mousekey_task(void)
 | 
			
		||||
{
 | 
			
		||||
    if      (code == KB_MS_UP)      report.y = -move_unit();
 | 
			
		||||
    else if (code == KB_MS_DOWN)    report.y = move_unit();
 | 
			
		||||
    else if (code == KB_MS_LEFT)    report.x = -move_unit();
 | 
			
		||||
    else if (code == KB_MS_RIGHT)   report.x = move_unit();
 | 
			
		||||
    else if (code == KB_MS_BTN1)    report.buttons |= MOUSE_BTN1;
 | 
			
		||||
    else if (code == KB_MS_BTN2)    report.buttons |= MOUSE_BTN2;
 | 
			
		||||
    else if (code == KB_MS_BTN3)    report.buttons |= MOUSE_BTN3;
 | 
			
		||||
    else if (code == KB_MS_BTN4)    report.buttons |= MOUSE_BTN4;
 | 
			
		||||
    else if (code == KB_MS_BTN5)    report.buttons |= MOUSE_BTN5;
 | 
			
		||||
    else if (code == KB_MS_WH_UP)   report.v += move_unit()/4;
 | 
			
		||||
    else if (code == KB_MS_WH_DOWN) report.v -= move_unit()/4;
 | 
			
		||||
    else if (code == KB_MS_WH_LEFT) report.h -= move_unit()/4;
 | 
			
		||||
    else if (code == KB_MS_WH_RIGHT)report.h += move_unit()/4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool mousekey_changed(void)
 | 
			
		||||
{
 | 
			
		||||
    return (report.buttons != report_prev.buttons ||
 | 
			
		||||
            report.x || report.y || report.v || report.h);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mousekey_send(void)
 | 
			
		||||
{
 | 
			
		||||
    static uint16_t last_timer = 0;
 | 
			
		||||
 | 
			
		||||
    if (!mousekey_changed()) {
 | 
			
		||||
        mousekey_repeat = 0;
 | 
			
		||||
        mousekey_clear_report();
 | 
			
		||||
    if (timer_elapsed(last_timer) < MOUSEKEY_DELAY_TIME)
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // send immediately when buttun state is changed
 | 
			
		||||
    if (report.buttons == report_prev.buttons) {
 | 
			
		||||
        if (timer_elapsed(last_timer) < 100) {
 | 
			
		||||
            mousekey_clear_report();
 | 
			
		||||
    if (report.x == 0 && report.y == 0 && report.v == 0 && report.h == 0)
 | 
			
		||||
        return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (mousekey_repeat != 0xFF) {
 | 
			
		||||
    if (mousekey_repeat != UINT8_MAX)
 | 
			
		||||
        mousekey_repeat++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if (report.x > 0) report.x = move_unit();
 | 
			
		||||
    if (report.x < 0) report.x = move_unit() * -1;
 | 
			
		||||
    if (report.y > 0) report.y = move_unit();
 | 
			
		||||
    if (report.y < 0) report.y = move_unit() * -1;
 | 
			
		||||
 | 
			
		||||
    if (report.x && report.y) {
 | 
			
		||||
        report.x *= 0.7;
 | 
			
		||||
        report.y *= 0.7;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mousekey_debug();
 | 
			
		||||
    host_mouse_send(&report);
 | 
			
		||||
    report_prev = report;
 | 
			
		||||
    last_timer = timer_read();
 | 
			
		||||
    mousekey_clear_report();
 | 
			
		||||
    if (report.v > 0) report.v = move_unit();
 | 
			
		||||
    if (report.v < 0) report.v = move_unit() * -1;
 | 
			
		||||
    if (report.h > 0) report.h = move_unit();
 | 
			
		||||
    if (report.h < 0) report.h = move_unit() * -1;
 | 
			
		||||
 | 
			
		||||
    mousekey_send();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mousekey_clear_report(void)
 | 
			
		||||
void mousekey_on(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    if      (code == KB_MS_UP)       report.y = MOUSEKEY_MOVE_INIT * -1;
 | 
			
		||||
    else if (code == KB_MS_DOWN)     report.y = MOUSEKEY_MOVE_INIT;
 | 
			
		||||
    else if (code == KB_MS_LEFT)     report.x = MOUSEKEY_MOVE_INIT * -1;
 | 
			
		||||
    else if (code == KB_MS_RIGHT)    report.x = MOUSEKEY_MOVE_INIT;
 | 
			
		||||
    else if (code == KB_MS_WH_UP)    report.v = MOUSEKEY_WHEEL_INIT;
 | 
			
		||||
    else if (code == KB_MS_WH_DOWN)  report.v = MOUSEKEY_WHEEL_INIT * -1;
 | 
			
		||||
    else if (code == KB_MS_WH_LEFT)  report.h = MOUSEKEY_WHEEL_INIT * -1;
 | 
			
		||||
    else if (code == KB_MS_WH_RIGHT) report.h = MOUSEKEY_WHEEL_INIT;
 | 
			
		||||
    else if (code == KB_MS_BTN1)     report.buttons |= MOUSE_BTN1;
 | 
			
		||||
    else if (code == KB_MS_BTN2)     report.buttons |= MOUSE_BTN2;
 | 
			
		||||
    else if (code == KB_MS_BTN3)     report.buttons |= MOUSE_BTN3;
 | 
			
		||||
    else if (code == KB_MS_BTN4)     report.buttons |= MOUSE_BTN4;
 | 
			
		||||
    else if (code == KB_MS_BTN5)     report.buttons |= MOUSE_BTN5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mousekey_off(uint8_t code)
 | 
			
		||||
{
 | 
			
		||||
    if      (code == KB_MS_UP    && report.y < 0) report.y = 0;
 | 
			
		||||
    else if (code == KB_MS_DOWN  && report.y > 0) report.y = 0;
 | 
			
		||||
    else if (code == KB_MS_LEFT  && report.x < 0) report.x = 0;
 | 
			
		||||
    else if (code == KB_MS_RIGHT && report.x > 0) report.x = 0;
 | 
			
		||||
    else if (code == KB_MS_WH_UP    && report.v > 0) report.v = 0;
 | 
			
		||||
    else if (code == KB_MS_WH_DOWN  && report.v < 0) report.v = 0;
 | 
			
		||||
    else if (code == KB_MS_WH_LEFT  && report.h < 0) report.h = 0;
 | 
			
		||||
    else if (code == KB_MS_WH_RIGHT && report.h > 0) report.h = 0;
 | 
			
		||||
    else if (code == KB_MS_BTN1) report.buttons &= ~MOUSE_BTN1;
 | 
			
		||||
    else if (code == KB_MS_BTN2) report.buttons &= ~MOUSE_BTN2;
 | 
			
		||||
    else if (code == KB_MS_BTN3) report.buttons &= ~MOUSE_BTN3;
 | 
			
		||||
    else if (code == KB_MS_BTN4) report.buttons &= ~MOUSE_BTN4;
 | 
			
		||||
    else if (code == KB_MS_BTN5) report.buttons &= ~MOUSE_BTN5;
 | 
			
		||||
 | 
			
		||||
    if (report.x == 0 && report.y == 0 && report.v == 0 && report.h == 0)
 | 
			
		||||
        mousekey_repeat = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mousekey_send(void)
 | 
			
		||||
{
 | 
			
		||||
    mousekey_debug();
 | 
			
		||||
    host_mouse_send(&report);
 | 
			
		||||
    last_timer = timer_read();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mousekey_clear(void)
 | 
			
		||||
{
 | 
			
		||||
    report = (report_mouse_t){};
 | 
			
		||||
/*
 | 
			
		||||
    report.buttons = 0;
 | 
			
		||||
    report.x = 0;
 | 
			
		||||
    report.y = 0;
 | 
			
		||||
    report.v = 0;
 | 
			
		||||
    report.h = 0;
 | 
			
		||||
*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void mousekey_debug(void)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,9 +21,10 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		|||
#include <stdbool.h>
 | 
			
		||||
#include "host.h"
 | 
			
		||||
 | 
			
		||||
void mousekey_decode(uint8_t code);
 | 
			
		||||
bool mousekey_changed(void);
 | 
			
		||||
void mousekey_task(void);
 | 
			
		||||
void mousekey_on(uint8_t code);
 | 
			
		||||
void mousekey_off(uint8_t code);
 | 
			
		||||
void mousekey_clear(void);
 | 
			
		||||
void mousekey_send(void);
 | 
			
		||||
void mousekey_clear_report(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
// counter resolution 1ms
 | 
			
		||||
// NOTE: union { uint32_t timer32; struct { uint16_t dummy; uint16_t timer16; }}
 | 
			
		||||
volatile uint32_t timer_count = 0;
 | 
			
		||||
 | 
			
		||||
void timer_init(void)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,6 +35,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		|||
 | 
			
		||||
#define MOD_BIT(code)   (1<<((code) & 0x07))
 | 
			
		||||
#define FN_BIT(code)    (1<<((code) - KB_FN0))
 | 
			
		||||
#define FN_INDEX(code)  ((code) - KB_FN0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Short names */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,19 +17,23 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		|||
 | 
			
		||||
#include "util.h"
 | 
			
		||||
 | 
			
		||||
// bit population
 | 
			
		||||
int bitpop(uint8_t bits)
 | 
			
		||||
// bit population - return number of on-bit
 | 
			
		||||
uint8_t bitpop(uint8_t bits)
 | 
			
		||||
{
 | 
			
		||||
    int c;
 | 
			
		||||
    uint8_t c;
 | 
			
		||||
    for (c = 0; bits; c++)
 | 
			
		||||
        bits &= bits -1;
 | 
			
		||||
    return c;
 | 
			
		||||
/*
 | 
			
		||||
    const uint8_t bit_count[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
 | 
			
		||||
    return bit_count[bits>>4] + bit_count[bits&0x0F]
 | 
			
		||||
*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// most significant on-bit
 | 
			
		||||
int biton(uint8_t bits)
 | 
			
		||||
// most significant on-bit - return highest location of on-bit
 | 
			
		||||
uint8_t biton(uint8_t bits)
 | 
			
		||||
{
 | 
			
		||||
    int n = 0;
 | 
			
		||||
    uint8_t n = 0;
 | 
			
		||||
    if (bits >> 4) { bits >>= 4; n += 4;}
 | 
			
		||||
    if (bits >> 2) { bits >>= 2; n += 2;}
 | 
			
		||||
    if (bits >> 1) { bits >>= 1; n += 1;}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		|||
#define XSTR(s) #s
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int bitpop(uint8_t bits);
 | 
			
		||||
int biton(uint8_t bits);
 | 
			
		||||
uint8_t bitpop(uint8_t bits);
 | 
			
		||||
uint8_t biton(uint8_t bits);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,8 +35,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		|||
/* matrix size */
 | 
			
		||||
#define MATRIX_ROWS 8
 | 
			
		||||
#define MATRIX_COLS 8
 | 
			
		||||
/* define if matrix has ghost */
 | 
			
		||||
//#define MATRIX_HAS_GHOST
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* key combination for command */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -210,12 +210,12 @@ uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col)
 | 
			
		|||
    return KEYCODE(layer, row, col);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t keymap_fn_layer(uint8_t fn_bits)
 | 
			
		||||
uint8_t keymap_fn_layer(uint8_t index)
 | 
			
		||||
{
 | 
			
		||||
    return pgm_read_byte(&fn_layer[biton(fn_bits)]);
 | 
			
		||||
    return pgm_read_byte(&fn_layer[index]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t keymap_fn_keycode(uint8_t fn_bits)
 | 
			
		||||
uint8_t keymap_fn_keycode(uint8_t index)
 | 
			
		||||
{
 | 
			
		||||
    return pgm_read_byte(&fn_keycode[(biton(fn_bits))]);
 | 
			
		||||
    return pgm_read_byte(&fn_keycode[index]);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,22 +43,10 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
// matrix state buffer(1:on, 0:off)
 | 
			
		||||
#if (MATRIX_COLS <= 8)
 | 
			
		||||
static uint8_t *matrix;
 | 
			
		||||
static uint8_t *matrix_prev;
 | 
			
		||||
static uint8_t _matrix0[MATRIX_ROWS];
 | 
			
		||||
static uint8_t _matrix1[MATRIX_ROWS];
 | 
			
		||||
#else
 | 
			
		||||
static uint16_t *matrix;
 | 
			
		||||
static uint16_t *matrix_prev;
 | 
			
		||||
static uint16_t _matrix0[MATRIX_ROWS];
 | 
			
		||||
static uint16_t _matrix1[MATRIX_ROWS];
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// HHKB has no ghost and no bounce.
 | 
			
		||||
#ifdef MATRIX_HAS_GHOST
 | 
			
		||||
static bool matrix_has_ghost_in_row(uint8_t row);
 | 
			
		||||
#endif
 | 
			
		||||
static matrix_row_t *matrix;
 | 
			
		||||
static matrix_row_t *matrix_prev;
 | 
			
		||||
static matrix_row_t _matrix0[MATRIX_ROWS];
 | 
			
		||||
static matrix_row_t _matrix1[MATRIX_ROWS];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Matrix I/O ports
 | 
			
		||||
| 
						 | 
				
			
			@ -192,6 +180,8 @@ uint8_t matrix_scan(void)
 | 
			
		|||
            }
 | 
			
		||||
 | 
			
		||||
            // Ignore if this code region execution time elapses more than 20us.
 | 
			
		||||
            // MEMO: 20[us] * (TIMER_RAW_FREQ / 1000000)[count per us]
 | 
			
		||||
            // MEMO: then change above using this rule: a/(b/c) = a*1/(b/c) = a*(c/b)
 | 
			
		||||
            if (TIMER_DIFF_RAW(TIMER_RAW, last) > 20/(1000000/TIMER_RAW_FREQ)) {
 | 
			
		||||
                matrix[row] = matrix_prev[row];
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -219,12 +209,6 @@ bool matrix_is_modified(void)
 | 
			
		|||
inline
 | 
			
		||||
bool matrix_has_ghost(void)
 | 
			
		||||
{
 | 
			
		||||
#ifdef MATRIX_HAS_GHOST
 | 
			
		||||
    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
 | 
			
		||||
        if (matrix_has_ghost_in_row(i))
 | 
			
		||||
            return true;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -257,11 +241,6 @@ void matrix_print(void)
 | 
			
		|||
        pbin_reverse(matrix_get_row(row));
 | 
			
		||||
#else
 | 
			
		||||
        pbin_reverse16(matrix_get_row(row));
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef MATRIX_HAS_GHOST
 | 
			
		||||
        if (matrix_has_ghost_in_row(row)) {
 | 
			
		||||
            print(" <ghost");
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
        print("\n");
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -279,20 +258,3 @@ uint8_t matrix_key_count(void)
 | 
			
		|||
    }
 | 
			
		||||
    return count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef MATRIX_HAS_GHOST
 | 
			
		||||
inline
 | 
			
		||||
static bool matrix_has_ghost_in_row(uint8_t row)
 | 
			
		||||
{
 | 
			
		||||
    // no ghost exists in case less than 2 keys on
 | 
			
		||||
    if (((matrix[row] - 1) & matrix[row]) == 0)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    // ghost exists in case same state as other row
 | 
			
		||||
    for (uint8_t i=0; i < MATRIX_ROWS; i++) {
 | 
			
		||||
        if (i != row && (matrix[i] & matrix[row]) == matrix[row])
 | 
			
		||||
            return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -475,7 +475,7 @@ int main(void)
 | 
			
		|||
    keyboard_init();
 | 
			
		||||
    host_set_driver(&lufa_driver);
 | 
			
		||||
    while (1) {
 | 
			
		||||
        keyboard_proc();
 | 
			
		||||
        keyboard_task();
 | 
			
		||||
 | 
			
		||||
#if !defined(INTERRUPT_CONTROL_ENDPOINT)
 | 
			
		||||
        USB_USBTask();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue