Migrate platform independent code from tmk_core -> quantum (#13673)
* Migrate action|keyboard|keycode|eeconfig from tmk_core -> quantum
This commit is contained in:
		
							parent
							
								
									96e2b13d1d
								
							
						
					
					
						commit
						b8e913c8db
					
				
					 19 changed files with 14 additions and 9 deletions
				
			
		
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -1,132 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 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
 | 
			
		||||
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/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "keyboard.h"
 | 
			
		||||
#include "keycode.h"
 | 
			
		||||
#include "action_code.h"
 | 
			
		||||
#include "action_macro.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Disable macro and function features when LTO is enabled, since they break */
 | 
			
		||||
#ifdef LTO_ENABLE
 | 
			
		||||
#    ifndef NO_ACTION_MACRO
 | 
			
		||||
#        define NO_ACTION_MACRO
 | 
			
		||||
#    endif
 | 
			
		||||
#    ifndef NO_ACTION_FUNCTION
 | 
			
		||||
#        define NO_ACTION_FUNCTION
 | 
			
		||||
#    endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* tapping count and state */
 | 
			
		||||
typedef struct {
 | 
			
		||||
    bool    interrupted : 1;
 | 
			
		||||
    bool    reserved2 : 1;
 | 
			
		||||
    bool    reserved1 : 1;
 | 
			
		||||
    bool    reserved0 : 1;
 | 
			
		||||
    uint8_t count : 4;
 | 
			
		||||
} tap_t;
 | 
			
		||||
 | 
			
		||||
/* Key event container for recording */
 | 
			
		||||
typedef struct {
 | 
			
		||||
    keyevent_t event;
 | 
			
		||||
#ifndef NO_ACTION_TAPPING
 | 
			
		||||
    tap_t tap;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef COMBO_ENABLE
 | 
			
		||||
    uint16_t keycode;
 | 
			
		||||
#endif
 | 
			
		||||
} keyrecord_t;
 | 
			
		||||
 | 
			
		||||
/* Execute action per keyevent */
 | 
			
		||||
void action_exec(keyevent_t event);
 | 
			
		||||
 | 
			
		||||
/* action for key */
 | 
			
		||||
action_t action_for_key(uint8_t layer, keypos_t key);
 | 
			
		||||
action_t action_for_keycode(uint16_t keycode);
 | 
			
		||||
 | 
			
		||||
/* macro */
 | 
			
		||||
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt);
 | 
			
		||||
 | 
			
		||||
/* user defined special function */
 | 
			
		||||
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt);
 | 
			
		||||
 | 
			
		||||
/* keyboard-specific key event (pre)processing */
 | 
			
		||||
bool process_record_quantum(keyrecord_t *record);
 | 
			
		||||
 | 
			
		||||
/* Utilities for actions.  */
 | 
			
		||||
#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
 | 
			
		||||
extern bool disable_action_cache;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Code for handling one-handed key modifiers. */
 | 
			
		||||
#ifdef SWAP_HANDS_ENABLE
 | 
			
		||||
extern bool                   swap_hands;
 | 
			
		||||
extern const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS];
 | 
			
		||||
#    if (MATRIX_COLS <= 8)
 | 
			
		||||
typedef uint8_t swap_state_row_t;
 | 
			
		||||
#    elif (MATRIX_COLS <= 16)
 | 
			
		||||
typedef uint16_t swap_state_row_t;
 | 
			
		||||
#    elif (MATRIX_COLS <= 32)
 | 
			
		||||
typedef uint32_t swap_state_row_t;
 | 
			
		||||
#    else
 | 
			
		||||
#        error "MATRIX_COLS: invalid value"
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
void process_hand_swap(keyevent_t *record);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void process_record_nocache(keyrecord_t *record);
 | 
			
		||||
void process_record(keyrecord_t *record);
 | 
			
		||||
void process_record_handler(keyrecord_t *record);
 | 
			
		||||
void post_process_record_quantum(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 tap_code(uint8_t code);
 | 
			
		||||
void tap_code_delay(uint8_t code, uint16_t delay);
 | 
			
		||||
void register_mods(uint8_t mods);
 | 
			
		||||
void unregister_mods(uint8_t mods);
 | 
			
		||||
void register_weak_mods(uint8_t mods);
 | 
			
		||||
void unregister_weak_mods(uint8_t mods);
 | 
			
		||||
// void set_mods(uint8_t mods);
 | 
			
		||||
void clear_keyboard(void);
 | 
			
		||||
void clear_keyboard_but_mods(void);
 | 
			
		||||
void clear_keyboard_but_mods_and_keys(void);
 | 
			
		||||
void layer_switch(uint8_t new_layer);
 | 
			
		||||
bool is_tap_key(keypos_t key);
 | 
			
		||||
bool is_tap_record(keyrecord_t *record);
 | 
			
		||||
bool is_tap_action(action_t action);
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_TAPPING
 | 
			
		||||
void process_record_tap_hint(keyrecord_t *record);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* debug */
 | 
			
		||||
void debug_event(keyevent_t event);
 | 
			
		||||
void debug_record(keyrecord_t record);
 | 
			
		||||
void debug_action(action_t action);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,308 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 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
 | 
			
		||||
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/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
/** \brief Action codes
 | 
			
		||||
 *
 | 
			
		||||
 * 16bit code: action_kind(4bit) + action_parameter(12bit)
 | 
			
		||||
 *
 | 
			
		||||
 * Key Actions(00xx)
 | 
			
		||||
 * -----------------
 | 
			
		||||
 * ACT_MODS(000r):
 | 
			
		||||
 * 000r|0000|0000 0000    No action code
 | 
			
		||||
 * 000r|0000|0000 0001    Transparent code
 | 
			
		||||
 * 000r|0000| keycode     Key
 | 
			
		||||
 * 000r|mods|0000 0000    Modifiers
 | 
			
		||||
 * 000r|mods| keycode     Modifiers+Key(Modified key)
 | 
			
		||||
 *   r: Left/Right flag(Left:0, Right:1)
 | 
			
		||||
 *
 | 
			
		||||
 * ACT_MODS_TAP(001r):
 | 
			
		||||
 * 001r|mods|0000 0000    Modifiers with OneShot
 | 
			
		||||
 * 001r|mods|0000 0001    Modifiers with tap toggle
 | 
			
		||||
 * 001r|mods|0000 00xx    (reserved)
 | 
			
		||||
 * 001r|mods| keycode     Modifiers with Tap Key(Dual role)
 | 
			
		||||
 *
 | 
			
		||||
 * Other Keys(01xx)
 | 
			
		||||
 * ----------------
 | 
			
		||||
 * ACT_USAGE(0100): TODO: Not needed?
 | 
			
		||||
 * 0100|00| usage(10)     System control(0x80) - General Desktop page(0x01)
 | 
			
		||||
 * 0100|01| usage(10)     Consumer control(0x01) - Consumer page(0x0C)
 | 
			
		||||
 * 0100|10| usage(10)     (reserved)
 | 
			
		||||
 * 0100|11| usage(10)     (reserved)
 | 
			
		||||
 *
 | 
			
		||||
 * ACT_MOUSEKEY(0101): TODO: Merge these two actions to conserve space?
 | 
			
		||||
 * 0101|xxxx| keycode     Mouse key
 | 
			
		||||
 *
 | 
			
		||||
 * ACT_SWAP_HANDS(0110):
 | 
			
		||||
 * 0110|xxxx| keycode     Swap hands (keycode on tap, or options)
 | 
			
		||||
 *
 | 
			
		||||
 * 0111|xxxx xxxx xxxx    (reserved)
 | 
			
		||||
 *
 | 
			
		||||
 * Layer Actions(10xx)
 | 
			
		||||
 * -------------------
 | 
			
		||||
 * ACT_LAYER(1000):
 | 
			
		||||
 * 1000|oo00|pppE BBBB   Default Layer Bitwise operation
 | 
			
		||||
 *   oo:    operation(00:AND, 01:OR, 10:XOR, 11:SET)
 | 
			
		||||
 *   ppp:   4-bit chunk part(0-7)
 | 
			
		||||
 *   EBBBB: bits and extra bit
 | 
			
		||||
 * 1000|ooee|pppE BBBB   Layer Bitwise Operation
 | 
			
		||||
 *   oo:    operation(00:AND, 01:OR, 10:XOR, 11:SET)
 | 
			
		||||
 *   ppp:   4-bit chunk part(0-7)
 | 
			
		||||
 *   EBBBB: bits and extra bit
 | 
			
		||||
 *   ee:    on event(01:press, 10:release, 11:both)
 | 
			
		||||
 *
 | 
			
		||||
 * ACT_LAYER_MODS(1001):
 | 
			
		||||
 * 1001|LLLL| mods       Layer with modifiers held
 | 
			
		||||
 *
 | 
			
		||||
 * ACT_LAYER_TAP(101x):
 | 
			
		||||
 * 101E|LLLL| keycode    On/Off with tap key    (0x00-DF)[TAP]
 | 
			
		||||
 * 101E|LLLL|1110 mods   On/Off with modifiers  (0xE0-EF)[NOT TAP]
 | 
			
		||||
 * 101E|LLLL|1111 0000   Invert with tap toggle (0xF0)   [TAP]
 | 
			
		||||
 * 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 0100   One Shot Layer         (0xF4)   [TAP]
 | 
			
		||||
 * 101E|LLLL|1111 xxxx   Reserved               (0xF5-FF)
 | 
			
		||||
 *   ELLLL: layer 0-31(E: extra bit for layer 16-31)
 | 
			
		||||
 *
 | 
			
		||||
 * Extensions(11xx)
 | 
			
		||||
 * ----------------
 | 
			
		||||
 * ACT_MACRO(1100):
 | 
			
		||||
 * 1100|opt | id(8)      Macro play?
 | 
			
		||||
 * 1100|1111| id(8)      Macro record?
 | 
			
		||||
 *
 | 
			
		||||
 * 1101|xxxx xxxx xxxx   (reserved)
 | 
			
		||||
 * 1110|xxxx xxxx xxxx   (reserved)
 | 
			
		||||
 *
 | 
			
		||||
 * ACT_FUNCTION(1111):
 | 
			
		||||
 * 1111| address(12)     Function?
 | 
			
		||||
 * 1111|opt | id(8)      Function?
 | 
			
		||||
 */
 | 
			
		||||
enum action_kind_id {
 | 
			
		||||
    /* Key Actions */
 | 
			
		||||
    ACT_MODS      = 0b0000,
 | 
			
		||||
    ACT_LMODS     = 0b0000,
 | 
			
		||||
    ACT_RMODS     = 0b0001,
 | 
			
		||||
    ACT_MODS_TAP  = 0b0010,
 | 
			
		||||
    ACT_LMODS_TAP = 0b0010,
 | 
			
		||||
    ACT_RMODS_TAP = 0b0011,
 | 
			
		||||
    /* Other Keys */
 | 
			
		||||
    ACT_USAGE    = 0b0100,
 | 
			
		||||
    ACT_MOUSEKEY = 0b0101,
 | 
			
		||||
    /* One-hand Support */
 | 
			
		||||
    ACT_SWAP_HANDS = 0b0110,
 | 
			
		||||
    /* Layer Actions */
 | 
			
		||||
    ACT_LAYER         = 0b1000,
 | 
			
		||||
    ACT_LAYER_MODS    = 0b1001,
 | 
			
		||||
    ACT_LAYER_TAP     = 0b1010, /* Layer  0-15 */
 | 
			
		||||
    ACT_LAYER_TAP_EXT = 0b1011, /* Layer 16-31 */
 | 
			
		||||
    /* Extensions */
 | 
			
		||||
    ACT_MACRO    = 0b1100,
 | 
			
		||||
    ACT_FUNCTION = 0b1111
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** \brief Action Code Struct
 | 
			
		||||
 *
 | 
			
		||||
 * NOTE:
 | 
			
		||||
 * In avr-gcc bit field seems to be assigned from LSB(bit0) to MSB(bit15).
 | 
			
		||||
 * AVR looks like a little endian in avr-gcc.
 | 
			
		||||
 * Not portable across compiler/endianness?
 | 
			
		||||
 *
 | 
			
		||||
 * Byte order and bit order of 0x1234:
 | 
			
		||||
 *   Big endian:                Little endian:
 | 
			
		||||
 *   --------------------       --------------------
 | 
			
		||||
 *   FEDC BA98  7654 3210       0123 4567  89AB CDEF
 | 
			
		||||
 *   0001 0010  0011 0100       0010 1100  0100 1000
 | 
			
		||||
 *     0x12       0x34            0x34       0x12
 | 
			
		||||
 */
 | 
			
		||||
typedef union {
 | 
			
		||||
    uint16_t code;
 | 
			
		||||
    struct action_kind {
 | 
			
		||||
        uint16_t param : 12;
 | 
			
		||||
        uint8_t  id : 4;
 | 
			
		||||
    } kind;
 | 
			
		||||
    struct action_key {
 | 
			
		||||
        uint8_t code : 8;
 | 
			
		||||
        uint8_t mods : 4;
 | 
			
		||||
        uint8_t kind : 4;
 | 
			
		||||
    } key;
 | 
			
		||||
    struct action_layer_bitop {
 | 
			
		||||
        uint8_t bits : 4;
 | 
			
		||||
        uint8_t xbit : 1;
 | 
			
		||||
        uint8_t part : 3;
 | 
			
		||||
        uint8_t on : 2;
 | 
			
		||||
        uint8_t op : 2;
 | 
			
		||||
        uint8_t kind : 4;
 | 
			
		||||
    } layer_bitop;
 | 
			
		||||
    struct action_layer_mods {
 | 
			
		||||
        uint8_t mods : 8;
 | 
			
		||||
        uint8_t layer : 4;
 | 
			
		||||
        uint8_t kind : 4;
 | 
			
		||||
    } layer_mods;
 | 
			
		||||
    struct action_layer_tap {
 | 
			
		||||
        uint8_t code : 8;
 | 
			
		||||
        uint8_t val : 5;
 | 
			
		||||
        uint8_t kind : 3;
 | 
			
		||||
    } layer_tap;
 | 
			
		||||
    struct action_usage {
 | 
			
		||||
        uint16_t code : 10;
 | 
			
		||||
        uint8_t  page : 2;
 | 
			
		||||
        uint8_t  kind : 4;
 | 
			
		||||
    } usage;
 | 
			
		||||
    struct action_function {
 | 
			
		||||
        uint8_t id : 8;
 | 
			
		||||
        uint8_t opt : 4;
 | 
			
		||||
        uint8_t kind : 4;
 | 
			
		||||
    } func;
 | 
			
		||||
    struct action_swap {
 | 
			
		||||
        uint8_t code : 8;
 | 
			
		||||
        uint8_t opt : 4;
 | 
			
		||||
        uint8_t kind : 4;
 | 
			
		||||
    } swap;
 | 
			
		||||
} action_t;
 | 
			
		||||
 | 
			
		||||
/* action utility */
 | 
			
		||||
#define ACTION_NO 0
 | 
			
		||||
#define ACTION_TRANSPARENT 1
 | 
			
		||||
#define ACTION(kind, param) ((kind) << 12 | (param))
 | 
			
		||||
 | 
			
		||||
/** \brief Key Actions
 | 
			
		||||
 *
 | 
			
		||||
 * Mod bits:    43210
 | 
			
		||||
 *   bit 0      ||||+- Control
 | 
			
		||||
 *   bit 1      |||+-- Shift
 | 
			
		||||
 *   bit 2      ||+--- Alt
 | 
			
		||||
 *   bit 3      |+---- Gui
 | 
			
		||||
 *   bit 4      +----- LR flag(Left:0, Right:1)
 | 
			
		||||
 */
 | 
			
		||||
enum mods_bit {
 | 
			
		||||
    MOD_LCTL = 0x01,
 | 
			
		||||
    MOD_LSFT = 0x02,
 | 
			
		||||
    MOD_LALT = 0x04,
 | 
			
		||||
    MOD_LGUI = 0x08,
 | 
			
		||||
    MOD_RCTL = 0x11,
 | 
			
		||||
    MOD_RSFT = 0x12,
 | 
			
		||||
    MOD_RALT = 0x14,
 | 
			
		||||
    MOD_RGUI = 0x18,
 | 
			
		||||
};
 | 
			
		||||
enum mods_codes {
 | 
			
		||||
    MODS_ONESHOT    = 0x00,
 | 
			
		||||
    MODS_TAP_TOGGLE = 0x01,
 | 
			
		||||
};
 | 
			
		||||
#define ACTION_KEY(key) ACTION(ACT_MODS, (key))
 | 
			
		||||
#define ACTION_MODS(mods) ACTION(ACT_MODS, ((mods)&0x1f) << 8 | 0)
 | 
			
		||||
#define ACTION_MODS_KEY(mods, key) ACTION(ACT_MODS, ((mods)&0x1f) << 8 | (key))
 | 
			
		||||
#define ACTION_MODS_TAP_KEY(mods, key) ACTION(ACT_MODS_TAP, ((mods)&0x1f) << 8 | (key))
 | 
			
		||||
#define ACTION_MODS_ONESHOT(mods) ACTION(ACT_MODS_TAP, ((mods)&0x1f) << 8 | MODS_ONESHOT)
 | 
			
		||||
#define ACTION_MODS_TAP_TOGGLE(mods) ACTION(ACT_MODS_TAP, ((mods)&0x1f) << 8 | MODS_TAP_TOGGLE)
 | 
			
		||||
 | 
			
		||||
/** \brief Other Keys
 | 
			
		||||
 */
 | 
			
		||||
enum usage_pages { PAGE_SYSTEM, PAGE_CONSUMER };
 | 
			
		||||
#define ACTION_USAGE_SYSTEM(id) ACTION(ACT_USAGE, PAGE_SYSTEM << 10 | (id))
 | 
			
		||||
#define ACTION_USAGE_CONSUMER(id) ACTION(ACT_USAGE, PAGE_CONSUMER << 10 | (id))
 | 
			
		||||
#define ACTION_MOUSEKEY(key) ACTION(ACT_MOUSEKEY, key)
 | 
			
		||||
 | 
			
		||||
/** \brief Layer Actions
 | 
			
		||||
 */
 | 
			
		||||
enum layer_param_on {
 | 
			
		||||
    ON_PRESS   = 1,
 | 
			
		||||
    ON_RELEASE = 2,
 | 
			
		||||
    ON_BOTH    = 3,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** \brief Layer Actions
 | 
			
		||||
 */
 | 
			
		||||
enum layer_param_bit_op {
 | 
			
		||||
    OP_BIT_AND = 0,
 | 
			
		||||
    OP_BIT_OR  = 1,
 | 
			
		||||
    OP_BIT_XOR = 2,
 | 
			
		||||
    OP_BIT_SET = 3,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** \brief Layer Actions
 | 
			
		||||
 */
 | 
			
		||||
enum layer_param_tap_op {
 | 
			
		||||
    OP_TAP_TOGGLE = 0xF0,
 | 
			
		||||
    OP_ON_OFF,
 | 
			
		||||
    OP_OFF_ON,
 | 
			
		||||
    OP_SET_CLEAR,
 | 
			
		||||
    OP_ONESHOT,
 | 
			
		||||
};
 | 
			
		||||
#define ACTION_LAYER_BITOP(op, part, bits, on) ACTION(ACT_LAYER, (op) << 10 | (on) << 8 | (part) << 5 | ((bits)&0x1f))
 | 
			
		||||
#define ACTION_LAYER_TAP(layer, key) ACTION(ACT_LAYER_TAP, (layer) << 8 | (key))
 | 
			
		||||
/* Default Layer */
 | 
			
		||||
#define ACTION_DEFAULT_LAYER_SET(layer) ACTION_DEFAULT_LAYER_BIT_SET((layer) / 4, 1 << ((layer) % 4))
 | 
			
		||||
/* Layer Operation */
 | 
			
		||||
#define ACTION_LAYER_CLEAR(on) ACTION_LAYER_BIT_AND(0, 0, (on))
 | 
			
		||||
#define ACTION_LAYER_MOMENTARY(layer) ACTION_LAYER_ON_OFF(layer)
 | 
			
		||||
#define ACTION_LAYER_TOGGLE(layer) ACTION_LAYER_INVERT(layer, ON_RELEASE)
 | 
			
		||||
#define ACTION_LAYER_INVERT(layer, on) ACTION_LAYER_BIT_XOR((layer) / 4, 1 << ((layer) % 4), (on))
 | 
			
		||||
#define ACTION_LAYER_ON(layer, on) ACTION_LAYER_BIT_OR((layer) / 4, 1 << ((layer) % 4), (on))
 | 
			
		||||
#define ACTION_LAYER_OFF(layer, on) ACTION_LAYER_BIT_AND((layer) / 4, ~(1 << ((layer) % 4)), (on))
 | 
			
		||||
#define ACTION_LAYER_SET(layer, on) ACTION_LAYER_BIT_SET((layer) / 4, 1 << ((layer) % 4), (on))
 | 
			
		||||
#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(ACT_LAYER_MODS, (layer) << 8 | (mods))
 | 
			
		||||
/* With Tapping */
 | 
			
		||||
#define ACTION_LAYER_TAP_KEY(layer, key) ACTION_LAYER_TAP((layer), (key))
 | 
			
		||||
#define ACTION_LAYER_TAP_TOGGLE(layer) ACTION_LAYER_TAP((layer), OP_TAP_TOGGLE)
 | 
			
		||||
/* Bitwise Operation */
 | 
			
		||||
#define ACTION_LAYER_BIT_AND(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_AND, (part), (bits), (on))
 | 
			
		||||
#define ACTION_LAYER_BIT_OR(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_OR, (part), (bits), (on))
 | 
			
		||||
#define ACTION_LAYER_BIT_XOR(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), (on))
 | 
			
		||||
#define ACTION_LAYER_BIT_SET(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), (on))
 | 
			
		||||
/* Default Layer Bitwise Operation */
 | 
			
		||||
#define ACTION_DEFAULT_LAYER_BIT_AND(part, bits) ACTION_LAYER_BITOP(OP_BIT_AND, (part), (bits), 0)
 | 
			
		||||
#define ACTION_DEFAULT_LAYER_BIT_OR(part, bits) ACTION_LAYER_BITOP(OP_BIT_OR, (part), (bits), 0)
 | 
			
		||||
#define ACTION_DEFAULT_LAYER_BIT_XOR(part, bits) ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), 0)
 | 
			
		||||
#define ACTION_DEFAULT_LAYER_BIT_SET(part, bits) ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), 0)
 | 
			
		||||
 | 
			
		||||
/* Macro */
 | 
			
		||||
#define ACTION_MACRO(id) ACTION(ACT_MACRO, (id))
 | 
			
		||||
#define ACTION_MACRO_TAP(id) ACTION(ACT_MACRO, FUNC_TAP << 8 | (id))
 | 
			
		||||
#define ACTION_MACRO_OPT(id, opt) ACTION(ACT_MACRO, (opt) << 8 | (id))
 | 
			
		||||
/* Function */
 | 
			
		||||
enum function_opts {
 | 
			
		||||
    FUNC_TAP = 0x8, /* indciates function is tappable */
 | 
			
		||||
};
 | 
			
		||||
#define ACTION_FUNCTION(id) ACTION(ACT_FUNCTION, (id))
 | 
			
		||||
#define ACTION_FUNCTION_TAP(id) ACTION(ACT_FUNCTION, FUNC_TAP << 8 | (id))
 | 
			
		||||
#define ACTION_FUNCTION_OPT(id, opt) ACTION(ACT_FUNCTION, (opt) << 8 | (id))
 | 
			
		||||
/* OneHand Support */
 | 
			
		||||
enum swap_hands_param_tap_op {
 | 
			
		||||
    OP_SH_TOGGLE = 0xF0,
 | 
			
		||||
    OP_SH_TAP_TOGGLE,
 | 
			
		||||
    OP_SH_ON_OFF,
 | 
			
		||||
    OP_SH_OFF_ON,
 | 
			
		||||
    OP_SH_OFF,
 | 
			
		||||
    OP_SH_ON,
 | 
			
		||||
    OP_SH_ONESHOT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define ACTION_SWAP_HANDS() ACTION_SWAP_HANDS_ON_OFF()
 | 
			
		||||
#define ACTION_SWAP_HANDS_TOGGLE() ACTION(ACT_SWAP_HANDS, OP_SH_TOGGLE)
 | 
			
		||||
#define ACTION_SWAP_HANDS_TAP_TOGGLE() ACTION(ACT_SWAP_HANDS, OP_SH_TAP_TOGGLE)
 | 
			
		||||
#define ACTION_SWAP_HANDS_ONESHOT() ACTION(ACT_SWAP_HANDS, OP_SH_ONESHOT)
 | 
			
		||||
#define ACTION_SWAP_HANDS_TAP_KEY(key) ACTION(ACT_SWAP_HANDS, key)
 | 
			
		||||
#define ACTION_SWAP_HANDS_ON_OFF() ACTION(ACT_SWAP_HANDS, OP_SH_ON_OFF)
 | 
			
		||||
#define ACTION_SWAP_HANDS_OFF_ON() ACTION(ACT_SWAP_HANDS, OP_SH_OFF_ON)
 | 
			
		||||
#define ACTION_SWAP_HANDS_ON() ACTION(ACT_SWAP_HANDS, OP_SH_ON)
 | 
			
		||||
#define ACTION_SWAP_HANDS_OFF() ACTION(ACT_SWAP_HANDS, OP_SH_OFF)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,279 +0,0 @@
 | 
			
		|||
#include <stdint.h>
 | 
			
		||||
#include "keyboard.h"
 | 
			
		||||
#include "action.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#include "action_layer.h"
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_ACTION
 | 
			
		||||
#    include "debug.h"
 | 
			
		||||
#else
 | 
			
		||||
#    include "nodebug.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** \brief Default Layer State
 | 
			
		||||
 */
 | 
			
		||||
layer_state_t default_layer_state = 0;
 | 
			
		||||
 | 
			
		||||
/** \brief Default Layer State Set At user Level
 | 
			
		||||
 *
 | 
			
		||||
 * Run user code on default layer state change
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) layer_state_t default_layer_state_set_user(layer_state_t state) { return state; }
 | 
			
		||||
 | 
			
		||||
/** \brief Default Layer State Set At Keyboard Level
 | 
			
		||||
 *
 | 
			
		||||
 *  Run keyboard code on default layer state change
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) layer_state_t default_layer_state_set_kb(layer_state_t state) { return default_layer_state_set_user(state); }
 | 
			
		||||
 | 
			
		||||
/** \brief Default Layer State Set
 | 
			
		||||
 *
 | 
			
		||||
 * Static function to set the default layer state, prints debug info and clears keys
 | 
			
		||||
 */
 | 
			
		||||
static void default_layer_state_set(layer_state_t state) {
 | 
			
		||||
    state = default_layer_state_set_kb(state);
 | 
			
		||||
    debug("default_layer_state: ");
 | 
			
		||||
    default_layer_debug();
 | 
			
		||||
    debug(" to ");
 | 
			
		||||
    default_layer_state = state;
 | 
			
		||||
    default_layer_debug();
 | 
			
		||||
    debug("\n");
 | 
			
		||||
#ifdef STRICT_LAYER_RELEASE
 | 
			
		||||
    clear_keyboard_but_mods();  // To avoid stuck keys
 | 
			
		||||
#else
 | 
			
		||||
    clear_keyboard_but_mods_and_keys();  // Don't reset held keys
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Default Layer Print
 | 
			
		||||
 *
 | 
			
		||||
 * Print out the hex value of the 32-bit default layer state, as well as the value of the highest bit.
 | 
			
		||||
 */
 | 
			
		||||
void default_layer_debug(void) { dprintf("%08lX(%u)", default_layer_state, get_highest_layer(default_layer_state)); }
 | 
			
		||||
 | 
			
		||||
/** \brief Default Layer Set
 | 
			
		||||
 *
 | 
			
		||||
 * Sets the default layer state.
 | 
			
		||||
 */
 | 
			
		||||
void default_layer_set(layer_state_t state) { default_layer_state_set(state); }
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_LAYER
 | 
			
		||||
/** \brief Default Layer Or
 | 
			
		||||
 *
 | 
			
		||||
 * Turns on the default layer based on matching bits between specifed layer and existing layer state
 | 
			
		||||
 */
 | 
			
		||||
void default_layer_or(layer_state_t state) { default_layer_state_set(default_layer_state | state); }
 | 
			
		||||
/** \brief Default Layer And
 | 
			
		||||
 *
 | 
			
		||||
 * Turns on default layer based on matching enabled bits between specifed layer and existing layer state
 | 
			
		||||
 */
 | 
			
		||||
void default_layer_and(layer_state_t state) { default_layer_state_set(default_layer_state & state); }
 | 
			
		||||
/** \brief Default Layer Xor
 | 
			
		||||
 *
 | 
			
		||||
 * Turns on default layer based on non-matching bits between specifed layer and existing layer state
 | 
			
		||||
 */
 | 
			
		||||
void default_layer_xor(layer_state_t state) { default_layer_state_set(default_layer_state ^ state); }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_LAYER
 | 
			
		||||
/** \brief Keymap Layer State
 | 
			
		||||
 */
 | 
			
		||||
layer_state_t layer_state = 0;
 | 
			
		||||
 | 
			
		||||
/** \brief Layer state set user
 | 
			
		||||
 *
 | 
			
		||||
 * Runs user code on layer state change
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) layer_state_t layer_state_set_user(layer_state_t state) { return state; }
 | 
			
		||||
 | 
			
		||||
/** \brief Layer state set keyboard
 | 
			
		||||
 *
 | 
			
		||||
 * Runs keyboard code on layer state change
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) layer_state_t layer_state_set_kb(layer_state_t state) { return layer_state_set_user(state); }
 | 
			
		||||
 | 
			
		||||
/** \brief Layer state set
 | 
			
		||||
 *
 | 
			
		||||
 * Sets the layer to match the specifed state (a bitmask)
 | 
			
		||||
 */
 | 
			
		||||
void layer_state_set(layer_state_t state) {
 | 
			
		||||
    state = layer_state_set_kb(state);
 | 
			
		||||
    dprint("layer_state: ");
 | 
			
		||||
    layer_debug();
 | 
			
		||||
    dprint(" to ");
 | 
			
		||||
    layer_state = state;
 | 
			
		||||
    layer_debug();
 | 
			
		||||
    dprintln();
 | 
			
		||||
#    ifdef STRICT_LAYER_RELEASE
 | 
			
		||||
    clear_keyboard_but_mods();  // To avoid stuck keys
 | 
			
		||||
#    else
 | 
			
		||||
    clear_keyboard_but_mods_and_keys();  // Don't reset held keys
 | 
			
		||||
#    endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Layer clear
 | 
			
		||||
 *
 | 
			
		||||
 * Turn off all layers
 | 
			
		||||
 */
 | 
			
		||||
void layer_clear(void) { layer_state_set(0); }
 | 
			
		||||
 | 
			
		||||
/** \brief Layer state is
 | 
			
		||||
 *
 | 
			
		||||
 * Return whether the given state is on (it might still be shadowed by a higher state, though)
 | 
			
		||||
 */
 | 
			
		||||
bool layer_state_is(uint8_t layer) { return layer_state_cmp(layer_state, layer); }
 | 
			
		||||
 | 
			
		||||
/** \brief Layer state compare
 | 
			
		||||
 *
 | 
			
		||||
 * Used for comparing layers {mostly used for unit testing}
 | 
			
		||||
 */
 | 
			
		||||
bool layer_state_cmp(layer_state_t cmp_layer_state, uint8_t layer) {
 | 
			
		||||
    if (!cmp_layer_state) {
 | 
			
		||||
        return layer == 0;
 | 
			
		||||
    }
 | 
			
		||||
    return (cmp_layer_state & ((layer_state_t)1 << layer)) != 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Layer move
 | 
			
		||||
 *
 | 
			
		||||
 * Turns on the given layer and turn off all other layers
 | 
			
		||||
 */
 | 
			
		||||
void layer_move(uint8_t layer) { layer_state_set((layer_state_t)1 << layer); }
 | 
			
		||||
 | 
			
		||||
/** \brief Layer on
 | 
			
		||||
 *
 | 
			
		||||
 * Turns on given layer
 | 
			
		||||
 */
 | 
			
		||||
void layer_on(uint8_t layer) { layer_state_set(layer_state | ((layer_state_t)1 << layer)); }
 | 
			
		||||
 | 
			
		||||
/** \brief Layer off
 | 
			
		||||
 *
 | 
			
		||||
 * Turns off given layer
 | 
			
		||||
 */
 | 
			
		||||
void layer_off(uint8_t layer) { layer_state_set(layer_state & ~((layer_state_t)1 << layer)); }
 | 
			
		||||
 | 
			
		||||
/** \brief Layer invert
 | 
			
		||||
 *
 | 
			
		||||
 * Toggle the given layer (set it if it's unset, or unset it if it's set)
 | 
			
		||||
 */
 | 
			
		||||
void layer_invert(uint8_t layer) { layer_state_set(layer_state ^ ((layer_state_t)1 << layer)); }
 | 
			
		||||
 | 
			
		||||
/** \brief Layer or
 | 
			
		||||
 *
 | 
			
		||||
 * Turns on layers based on matching bits between specifed layer and existing layer state
 | 
			
		||||
 */
 | 
			
		||||
void layer_or(layer_state_t state) { layer_state_set(layer_state | state); }
 | 
			
		||||
/** \brief Layer and
 | 
			
		||||
 *
 | 
			
		||||
 * Turns on layers based on matching enabled bits between specifed layer and existing layer state
 | 
			
		||||
 */
 | 
			
		||||
void layer_and(layer_state_t state) { layer_state_set(layer_state & state); }
 | 
			
		||||
/** \brief Layer xor
 | 
			
		||||
 *
 | 
			
		||||
 * Turns on layers based on non-matching bits between specifed layer and existing layer state
 | 
			
		||||
 */
 | 
			
		||||
void layer_xor(layer_state_t state) { layer_state_set(layer_state ^ state); }
 | 
			
		||||
 | 
			
		||||
/** \brief Layer debug printing
 | 
			
		||||
 *
 | 
			
		||||
 * Print out the hex value of the 32-bit layer state, as well as the value of the highest bit.
 | 
			
		||||
 */
 | 
			
		||||
void layer_debug(void) { dprintf("%08lX(%u)", layer_state, get_highest_layer(layer_state)); }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
 | 
			
		||||
/** \brief source layer cache
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS] = {{0}};
 | 
			
		||||
 | 
			
		||||
/** \brief update source layers cache
 | 
			
		||||
 *
 | 
			
		||||
 * Updates the cached keys when changing layers
 | 
			
		||||
 */
 | 
			
		||||
void update_source_layers_cache(keypos_t key, uint8_t layer) {
 | 
			
		||||
    const uint8_t key_number  = key.col + (key.row * MATRIX_COLS);
 | 
			
		||||
    const uint8_t storage_row = key_number / 8;
 | 
			
		||||
    const uint8_t storage_bit = key_number % 8;
 | 
			
		||||
 | 
			
		||||
    for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) {
 | 
			
		||||
        source_layers_cache[storage_row][bit_number] ^= (-((layer & (1U << bit_number)) != 0) ^ source_layers_cache[storage_row][bit_number]) & (1U << storage_bit);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief read source layers cache
 | 
			
		||||
 *
 | 
			
		||||
 * reads the cached keys stored when the layer was changed
 | 
			
		||||
 */
 | 
			
		||||
uint8_t read_source_layers_cache(keypos_t key) {
 | 
			
		||||
    const uint8_t key_number  = key.col + (key.row * MATRIX_COLS);
 | 
			
		||||
    const uint8_t storage_row = key_number / 8;
 | 
			
		||||
    const uint8_t storage_bit = key_number % 8;
 | 
			
		||||
    uint8_t       layer       = 0;
 | 
			
		||||
 | 
			
		||||
    for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) {
 | 
			
		||||
        layer |= ((source_layers_cache[storage_row][bit_number] & (1U << storage_bit)) != 0) << bit_number;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return layer;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** \brief Store or get action (FIXME: Needs better summary)
 | 
			
		||||
 *
 | 
			
		||||
 * Make sure the action triggered when the key is released is the same
 | 
			
		||||
 * one as the one triggered on press. It's important for the mod keys
 | 
			
		||||
 * when the layer is switched after the down event but before the up
 | 
			
		||||
 * event as they may get stuck otherwise.
 | 
			
		||||
 */
 | 
			
		||||
action_t store_or_get_action(bool pressed, keypos_t key) {
 | 
			
		||||
#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
 | 
			
		||||
    if (disable_action_cache) {
 | 
			
		||||
        return layer_switch_get_action(key);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint8_t layer;
 | 
			
		||||
 | 
			
		||||
    if (pressed) {
 | 
			
		||||
        layer = layer_switch_get_layer(key);
 | 
			
		||||
        update_source_layers_cache(key, layer);
 | 
			
		||||
    } else {
 | 
			
		||||
        layer = read_source_layers_cache(key);
 | 
			
		||||
    }
 | 
			
		||||
    return action_for_key(layer, key);
 | 
			
		||||
#else
 | 
			
		||||
    return layer_switch_get_action(key);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Layer switch get layer
 | 
			
		||||
 *
 | 
			
		||||
 * Gets the layer based on key info
 | 
			
		||||
 */
 | 
			
		||||
uint8_t layer_switch_get_layer(keypos_t key) {
 | 
			
		||||
#ifndef NO_ACTION_LAYER
 | 
			
		||||
    action_t action;
 | 
			
		||||
    action.code = ACTION_TRANSPARENT;
 | 
			
		||||
 | 
			
		||||
    layer_state_t layers = layer_state | default_layer_state;
 | 
			
		||||
    /* check top layer first */
 | 
			
		||||
    for (int8_t i = MAX_LAYER - 1; i >= 0; i--) {
 | 
			
		||||
        if (layers & ((layer_state_t)1 << i)) {
 | 
			
		||||
            action = action_for_key(i, key);
 | 
			
		||||
            if (action.code != ACTION_TRANSPARENT) {
 | 
			
		||||
                return i;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    /* fall back to layer 0 */
 | 
			
		||||
    return 0;
 | 
			
		||||
#else
 | 
			
		||||
    return get_highest_layer(default_layer_state);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Layer switch get layer
 | 
			
		||||
 *
 | 
			
		||||
 * Gets action code based on key position
 | 
			
		||||
 */
 | 
			
		||||
action_t layer_switch_get_action(keypos_t key) { return action_for_key(layer_switch_get_layer(key), key); }
 | 
			
		||||
| 
						 | 
				
			
			@ -1,147 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 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
 | 
			
		||||
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/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "keyboard.h"
 | 
			
		||||
#include "action.h"
 | 
			
		||||
 | 
			
		||||
#ifdef DYNAMIC_KEYMAP_ENABLE
 | 
			
		||||
#    ifndef DYNAMIC_KEYMAP_LAYER_COUNT
 | 
			
		||||
#        define DYNAMIC_KEYMAP_LAYER_COUNT 4
 | 
			
		||||
#    endif
 | 
			
		||||
#    if DYNAMIC_KEYMAP_LAYER_COUNT <= 8
 | 
			
		||||
#        ifndef LAYER_STATE_8BIT
 | 
			
		||||
#            define LAYER_STATE_8BIT
 | 
			
		||||
#        endif
 | 
			
		||||
#    elif DYNAMIC_KEYMAP_LAYER_COUNT <= 16
 | 
			
		||||
#        ifndef LAYER_STATE_16BIT
 | 
			
		||||
#            define LAYER_STATE_16BIT
 | 
			
		||||
#        endif
 | 
			
		||||
#    else
 | 
			
		||||
#        ifndef LAYER_STATE_32BIT
 | 
			
		||||
#            define LAYER_STATE_32BIT
 | 
			
		||||
#        endif
 | 
			
		||||
#    endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined(LAYER_STATE_8BIT) && !defined(LAYER_STATE_16BIT) && !defined(LAYER_STATE_32BIT)
 | 
			
		||||
#    define LAYER_STATE_32BIT
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(LAYER_STATE_8BIT)
 | 
			
		||||
typedef uint8_t layer_state_t;
 | 
			
		||||
#    define MAX_LAYER_BITS 3
 | 
			
		||||
#    ifndef MAX_LAYER
 | 
			
		||||
#        define MAX_LAYER 8
 | 
			
		||||
#    endif
 | 
			
		||||
#    define get_highest_layer(state) biton(state)
 | 
			
		||||
#elif defined(LAYER_STATE_16BIT)
 | 
			
		||||
typedef uint16_t layer_state_t;
 | 
			
		||||
#    define MAX_LAYER_BITS 4
 | 
			
		||||
#    ifndef MAX_LAYER
 | 
			
		||||
#        define MAX_LAYER 16
 | 
			
		||||
#    endif
 | 
			
		||||
#    define get_highest_layer(state) biton16(state)
 | 
			
		||||
#elif defined(LAYER_STATE_32BIT)
 | 
			
		||||
typedef uint32_t layer_state_t;
 | 
			
		||||
#    define MAX_LAYER_BITS 5
 | 
			
		||||
#    ifndef MAX_LAYER
 | 
			
		||||
#        define MAX_LAYER 32
 | 
			
		||||
#    endif
 | 
			
		||||
#    define get_highest_layer(state) biton32(state)
 | 
			
		||||
#else
 | 
			
		||||
#    error Layer Mask size not specified.  HOW?!
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Default Layer
 | 
			
		||||
 */
 | 
			
		||||
extern layer_state_t default_layer_state;
 | 
			
		||||
void                 default_layer_debug(void);
 | 
			
		||||
void                 default_layer_set(layer_state_t state);
 | 
			
		||||
 | 
			
		||||
__attribute__((weak)) layer_state_t default_layer_state_set_kb(layer_state_t state);
 | 
			
		||||
__attribute__((weak)) layer_state_t default_layer_state_set_user(layer_state_t state);
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_LAYER
 | 
			
		||||
/* bitwise operation */
 | 
			
		||||
void default_layer_or(layer_state_t state);
 | 
			
		||||
void default_layer_and(layer_state_t state);
 | 
			
		||||
void default_layer_xor(layer_state_t state);
 | 
			
		||||
#else
 | 
			
		||||
#    define default_layer_or(state)
 | 
			
		||||
#    define default_layer_and(state)
 | 
			
		||||
#    define default_layer_xor(state)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Keymap Layer
 | 
			
		||||
 */
 | 
			
		||||
#ifndef NO_ACTION_LAYER
 | 
			
		||||
extern layer_state_t layer_state;
 | 
			
		||||
 | 
			
		||||
void layer_state_set(layer_state_t state);
 | 
			
		||||
bool layer_state_is(uint8_t layer);
 | 
			
		||||
bool layer_state_cmp(layer_state_t layer1, uint8_t layer2);
 | 
			
		||||
 | 
			
		||||
void layer_debug(void);
 | 
			
		||||
void layer_clear(void);
 | 
			
		||||
void layer_move(uint8_t layer);
 | 
			
		||||
void layer_on(uint8_t layer);
 | 
			
		||||
void layer_off(uint8_t layer);
 | 
			
		||||
void layer_invert(uint8_t layer);
 | 
			
		||||
/* bitwise operation */
 | 
			
		||||
void          layer_or(layer_state_t state);
 | 
			
		||||
void          layer_and(layer_state_t state);
 | 
			
		||||
void          layer_xor(layer_state_t state);
 | 
			
		||||
layer_state_t layer_state_set_user(layer_state_t state);
 | 
			
		||||
layer_state_t layer_state_set_kb(layer_state_t state);
 | 
			
		||||
#else
 | 
			
		||||
#    define layer_state 0
 | 
			
		||||
 | 
			
		||||
#    define layer_state_set(layer)
 | 
			
		||||
#    define layer_state_is(layer) (layer == 0)
 | 
			
		||||
#    define layer_state_cmp(state, layer) (state == 0 ? layer == 0 : (state & (layer_state_t)1 << layer) != 0)
 | 
			
		||||
 | 
			
		||||
#    define layer_debug()
 | 
			
		||||
#    define layer_clear()
 | 
			
		||||
#    define layer_move(layer) (void)layer
 | 
			
		||||
#    define layer_on(layer) (void)layer
 | 
			
		||||
#    define layer_off(layer) (void)layer
 | 
			
		||||
#    define layer_invert(layer) (void)layer
 | 
			
		||||
#    define layer_or(state) (void)state
 | 
			
		||||
#    define layer_and(state) (void)state
 | 
			
		||||
#    define layer_xor(state) (void)state
 | 
			
		||||
#    define layer_state_set_kb(state) (void)state
 | 
			
		||||
#    define layer_state_set_user(state) (void)state
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* pressed actions cache */
 | 
			
		||||
#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
 | 
			
		||||
 | 
			
		||||
void    update_source_layers_cache(keypos_t key, uint8_t layer);
 | 
			
		||||
uint8_t read_source_layers_cache(keypos_t key);
 | 
			
		||||
#endif
 | 
			
		||||
action_t store_or_get_action(bool pressed, keypos_t key);
 | 
			
		||||
 | 
			
		||||
/* return the topmost non-transparent layer currently associated with key */
 | 
			
		||||
uint8_t layer_switch_get_layer(keypos_t key);
 | 
			
		||||
 | 
			
		||||
/* return action depending on current layer status */
 | 
			
		||||
action_t layer_switch_get_action(keypos_t key);
 | 
			
		||||
| 
						 | 
				
			
			@ -1,93 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 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
 | 
			
		||||
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 "action.h"
 | 
			
		||||
#include "action_util.h"
 | 
			
		||||
#include "action_macro.h"
 | 
			
		||||
#include "wait.h"
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_ACTION
 | 
			
		||||
#    include "debug.h"
 | 
			
		||||
#else
 | 
			
		||||
#    include "nodebug.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_MACRO
 | 
			
		||||
 | 
			
		||||
#    define MACRO_READ() (macro = MACRO_GET(macro_p++))
 | 
			
		||||
/** \brief Action Macro Play
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: Needs doc
 | 
			
		||||
 */
 | 
			
		||||
void action_macro_play(const macro_t *macro_p) {
 | 
			
		||||
    macro_t macro    = END;
 | 
			
		||||
    uint8_t interval = 0;
 | 
			
		||||
 | 
			
		||||
    if (!macro_p) return;
 | 
			
		||||
    while (true) {
 | 
			
		||||
        switch (MACRO_READ()) {
 | 
			
		||||
            case KEY_DOWN:
 | 
			
		||||
                MACRO_READ();
 | 
			
		||||
                dprintf("KEY_DOWN(%02X)\n", macro);
 | 
			
		||||
                if (IS_MOD(macro)) {
 | 
			
		||||
                    add_macro_mods(MOD_BIT(macro));
 | 
			
		||||
                    send_keyboard_report();
 | 
			
		||||
                } else {
 | 
			
		||||
                    register_code(macro);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_UP:
 | 
			
		||||
                MACRO_READ();
 | 
			
		||||
                dprintf("KEY_UP(%02X)\n", macro);
 | 
			
		||||
                if (IS_MOD(macro)) {
 | 
			
		||||
                    del_macro_mods(MOD_BIT(macro));
 | 
			
		||||
                    send_keyboard_report();
 | 
			
		||||
                } else {
 | 
			
		||||
                    unregister_code(macro);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case WAIT:
 | 
			
		||||
                MACRO_READ();
 | 
			
		||||
                dprintf("WAIT(%u)\n", macro);
 | 
			
		||||
                {
 | 
			
		||||
                    uint8_t ms = macro;
 | 
			
		||||
                    while (ms--) wait_ms(1);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case INTERVAL:
 | 
			
		||||
                interval = MACRO_READ();
 | 
			
		||||
                dprintf("INTERVAL(%u)\n", interval);
 | 
			
		||||
                break;
 | 
			
		||||
            case 0x04 ... 0x73:
 | 
			
		||||
                dprintf("DOWN(%02X)\n", macro);
 | 
			
		||||
                register_code(macro);
 | 
			
		||||
                break;
 | 
			
		||||
            case 0x84 ... 0xF3:
 | 
			
		||||
                dprintf("UP(%02X)\n", macro);
 | 
			
		||||
                unregister_code(macro & 0x7F);
 | 
			
		||||
                break;
 | 
			
		||||
            case END:
 | 
			
		||||
            default:
 | 
			
		||||
                return;
 | 
			
		||||
        }
 | 
			
		||||
        // interval
 | 
			
		||||
        {
 | 
			
		||||
            uint8_t ms = interval;
 | 
			
		||||
            while (ms--) wait_ms(1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,123 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 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
 | 
			
		||||
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/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "progmem.h"
 | 
			
		||||
 | 
			
		||||
typedef uint8_t macro_t;
 | 
			
		||||
 | 
			
		||||
#define MACRO_NONE (macro_t *)0
 | 
			
		||||
#define MACRO(...)                                          \
 | 
			
		||||
    ({                                                      \
 | 
			
		||||
        static const macro_t __m[] PROGMEM = {__VA_ARGS__}; \
 | 
			
		||||
        &__m[0];                                            \
 | 
			
		||||
    })
 | 
			
		||||
#define MACRO_GET(p) pgm_read_byte(p)
 | 
			
		||||
 | 
			
		||||
// Sends press when the macro key is pressed, release when release, or tap_macro when the key has been tapped
 | 
			
		||||
#define MACRO_TAP_HOLD(record, press, release, tap_macro) (((record)->event.pressed) ? (((record)->tap.count <= 0 || (record)->tap.interrupted) ? (press) : MACRO_NONE) : (((record)->tap.count > 0 && !((record)->tap.interrupted)) ? (tap_macro) : (release)))
 | 
			
		||||
 | 
			
		||||
// Holds down the modifier mod when the macro key is held, or sends macro instead when tapped
 | 
			
		||||
#define MACRO_TAP_HOLD_MOD(record, macro, mod) MACRO_TAP_HOLD(record, (MACRO(D(mod), END)), MACRO(U(mod), END), macro)
 | 
			
		||||
 | 
			
		||||
// Holds down the modifier mod when the macro key is held, or pressed a shifted key when tapped (eg: shift+3 for #)
 | 
			
		||||
#define MACRO_TAP_SHFT_KEY_HOLD_MOD(record, key, mod) MACRO_TAP_HOLD_MOD(record, (MACRO(I(10), D(LSFT), T(key), U(LSFT), END)), mod)
 | 
			
		||||
 | 
			
		||||
// Momentary switch layer when held, sends macro if tapped
 | 
			
		||||
#define MACRO_TAP_HOLD_LAYER(record, macro, layer)                                                         \
 | 
			
		||||
    (((record)->event.pressed) ? (((record)->tap.count <= 0 || (record)->tap.interrupted) ? ({             \
 | 
			
		||||
        layer_on((layer));                                                                                 \
 | 
			
		||||
        MACRO_NONE;                                                                                        \
 | 
			
		||||
    })                                                                                                     \
 | 
			
		||||
                                                                                          : MACRO_NONE)    \
 | 
			
		||||
                               : (((record)->tap.count > 0 && !((record)->tap.interrupted)) ? (macro) : ({ \
 | 
			
		||||
                                     layer_off((layer));                                                   \
 | 
			
		||||
                                     MACRO_NONE;                                                           \
 | 
			
		||||
                                 })))
 | 
			
		||||
 | 
			
		||||
// Momentary switch layer when held, presses a shifted key when tapped (eg: shift+3 for #)
 | 
			
		||||
#define MACRO_TAP_SHFT_KEY_HOLD_LAYER(record, key, layer) MACRO_TAP_HOLD_LAYER(record, MACRO(I(10), D(LSFT), T(key), U(LSFT), END), layer)
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_MACRO
 | 
			
		||||
void action_macro_play(const macro_t *macro_p);
 | 
			
		||||
#else
 | 
			
		||||
#    define action_macro_play(macro)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Macro commands
 | 
			
		||||
 *   code(0x04-73)                      // key down(1byte)
 | 
			
		||||
 *   code(0x04-73) | 0x80               // key up(1byte)
 | 
			
		||||
 *   { KEY_DOWN, code(0x04-0xff) }      // key down(2bytes)
 | 
			
		||||
 *   { KEY_UP,   code(0x04-0xff) }      // key up(2bytes)
 | 
			
		||||
 *   WAIT                               // wait milli-seconds
 | 
			
		||||
 *   INTERVAL                           // set interval between macro commands
 | 
			
		||||
 *   END                                // stop macro execution
 | 
			
		||||
 *
 | 
			
		||||
 * Ideas(Not implemented):
 | 
			
		||||
 *   modifiers
 | 
			
		||||
 *   system usage
 | 
			
		||||
 *   consumer usage
 | 
			
		||||
 *   unicode usage
 | 
			
		||||
 *   function call
 | 
			
		||||
 *   conditionals
 | 
			
		||||
 *   loop
 | 
			
		||||
 */
 | 
			
		||||
enum macro_command_id {
 | 
			
		||||
    /* 0x00 - 0x03 */
 | 
			
		||||
    END = 0x00,
 | 
			
		||||
    KEY_DOWN,
 | 
			
		||||
    KEY_UP,
 | 
			
		||||
 | 
			
		||||
    /* 0x04 - 0x73 (reserved for keycode down) */
 | 
			
		||||
 | 
			
		||||
    /* 0x74 - 0x83 */
 | 
			
		||||
    WAIT = 0x74,
 | 
			
		||||
    INTERVAL,
 | 
			
		||||
 | 
			
		||||
    /* 0x84 - 0xf3 (reserved for keycode up) */
 | 
			
		||||
 | 
			
		||||
    /* 0xf4 - 0xff */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* TODO: keycode:0x04-0x73 can be handled by 1byte command  else 2bytes are needed
 | 
			
		||||
 * if keycode between 0x04 and 0x73
 | 
			
		||||
 *      keycode / (keycode|0x80)
 | 
			
		||||
 * else
 | 
			
		||||
 *      {KEY_DOWN, keycode} / {KEY_UP, keycode}
 | 
			
		||||
 */
 | 
			
		||||
#define DOWN(key) KEY_DOWN, (key)
 | 
			
		||||
#define UP(key) KEY_UP, (key)
 | 
			
		||||
#define TYPE(key) DOWN(key), UP(key)
 | 
			
		||||
#define WAIT(ms) WAIT, (ms)
 | 
			
		||||
#define INTERVAL(ms) INTERVAL, (ms)
 | 
			
		||||
 | 
			
		||||
/* key down */
 | 
			
		||||
#define D(key) DOWN(KC_##key)
 | 
			
		||||
/* key up */
 | 
			
		||||
#define U(key) UP(KC_##key)
 | 
			
		||||
/* key type */
 | 
			
		||||
#define T(key) TYPE(KC_##key)
 | 
			
		||||
/* wait */
 | 
			
		||||
#define W(ms) WAIT(ms)
 | 
			
		||||
/* interval */
 | 
			
		||||
#define I(ms) INTERVAL(ms)
 | 
			
		||||
 | 
			
		||||
/* for backward comaptibility */
 | 
			
		||||
#define MD(key) DOWN(KC_##key)
 | 
			
		||||
#define MU(key) UP(KC_##key)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,456 +0,0 @@
 | 
			
		|||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "action.h"
 | 
			
		||||
#include "action_layer.h"
 | 
			
		||||
#include "action_tapping.h"
 | 
			
		||||
#include "keycode.h"
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_ACTION
 | 
			
		||||
#    include "debug.h"
 | 
			
		||||
#else
 | 
			
		||||
#    include "nodebug.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_TAPPING
 | 
			
		||||
 | 
			
		||||
#    define IS_TAPPING() !IS_NOEVENT(tapping_key.event)
 | 
			
		||||
#    define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed)
 | 
			
		||||
#    define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed)
 | 
			
		||||
#    define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k)))
 | 
			
		||||
#ifndef COMBO_ENABLE
 | 
			
		||||
#    define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)))
 | 
			
		||||
#else
 | 
			
		||||
#    define IS_TAPPING_RECORD(r) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (r->event.key)) && tapping_key.keycode == r->keycode)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
__attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { return TAPPING_TERM; }
 | 
			
		||||
 | 
			
		||||
#    ifdef TAPPING_TERM_PER_KEY
 | 
			
		||||
#        define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < get_tapping_term(get_record_keycode(&tapping_key, false), &tapping_key))
 | 
			
		||||
#    else
 | 
			
		||||
#        define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM)
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
#    ifdef TAPPING_FORCE_HOLD_PER_KEY
 | 
			
		||||
__attribute__((weak)) bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record) { return false; }
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
#    ifdef PERMISSIVE_HOLD_PER_KEY
 | 
			
		||||
__attribute__((weak)) bool get_permissive_hold(uint16_t keycode, keyrecord_t *record) { return false; }
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
#    ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
 | 
			
		||||
__attribute__((weak)) bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) { return false; }
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
static keyrecord_t tapping_key                         = {};
 | 
			
		||||
static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
 | 
			
		||||
static uint8_t     waiting_buffer_head                 = 0;
 | 
			
		||||
static uint8_t     waiting_buffer_tail                 = 0;
 | 
			
		||||
 | 
			
		||||
static bool process_tapping(keyrecord_t *record);
 | 
			
		||||
static bool waiting_buffer_enq(keyrecord_t record);
 | 
			
		||||
static void waiting_buffer_clear(void);
 | 
			
		||||
static bool waiting_buffer_typed(keyevent_t event);
 | 
			
		||||
static bool waiting_buffer_has_anykey_pressed(void);
 | 
			
		||||
static void waiting_buffer_scan_tap(void);
 | 
			
		||||
static void debug_tapping_key(void);
 | 
			
		||||
static void debug_waiting_buffer(void);
 | 
			
		||||
 | 
			
		||||
/** \brief Action Tapping Process
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: Needs doc
 | 
			
		||||
 */
 | 
			
		||||
void action_tapping_process(keyrecord_t record) {
 | 
			
		||||
    if (process_tapping(&record)) {
 | 
			
		||||
        if (!IS_NOEVENT(record.event)) {
 | 
			
		||||
            debug("processed: ");
 | 
			
		||||
            debug_record(record);
 | 
			
		||||
            debug("\n");
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        if (!waiting_buffer_enq(record)) {
 | 
			
		||||
            // clear all in case of overflow.
 | 
			
		||||
            debug("OVERFLOW: CLEAR ALL STATES\n");
 | 
			
		||||
            clear_keyboard();
 | 
			
		||||
            waiting_buffer_clear();
 | 
			
		||||
            tapping_key = (keyrecord_t){};
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // process waiting_buffer
 | 
			
		||||
    if (!IS_NOEVENT(record.event) && waiting_buffer_head != waiting_buffer_tail) {
 | 
			
		||||
        debug("---- action_exec: process waiting_buffer -----\n");
 | 
			
		||||
    }
 | 
			
		||||
    for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) {
 | 
			
		||||
        if (process_tapping(&waiting_buffer[waiting_buffer_tail])) {
 | 
			
		||||
            debug("processed: waiting_buffer[");
 | 
			
		||||
            debug_dec(waiting_buffer_tail);
 | 
			
		||||
            debug("] = ");
 | 
			
		||||
            debug_record(waiting_buffer[waiting_buffer_tail]);
 | 
			
		||||
            debug("\n\n");
 | 
			
		||||
        } else {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (!IS_NOEVENT(record.event)) {
 | 
			
		||||
        debug("\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Tapping
 | 
			
		||||
 *
 | 
			
		||||
 * Rule: Tap key is typed(pressed and released) within TAPPING_TERM.
 | 
			
		||||
 *       (without interfering by typing other key)
 | 
			
		||||
 */
 | 
			
		||||
/* return true when key event is processed or consumed. */
 | 
			
		||||
bool process_tapping(keyrecord_t *keyp) {
 | 
			
		||||
    keyevent_t event = keyp->event;
 | 
			
		||||
 | 
			
		||||
    // if tapping
 | 
			
		||||
    if (IS_TAPPING_PRESSED()) {
 | 
			
		||||
        if (WITHIN_TAPPING_TERM(event)) {
 | 
			
		||||
            if (tapping_key.tap.count == 0) {
 | 
			
		||||
                if (IS_TAPPING_RECORD(keyp) && !event.pressed) {
 | 
			
		||||
                    // first tap!
 | 
			
		||||
                    debug("Tapping: First tap(0->1).\n");
 | 
			
		||||
                    tapping_key.tap.count = 1;
 | 
			
		||||
                    debug_tapping_key();
 | 
			
		||||
                    process_record(&tapping_key);
 | 
			
		||||
 | 
			
		||||
                    // copy tapping state
 | 
			
		||||
                    keyp->tap = tapping_key.tap;
 | 
			
		||||
                    // enqueue
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
                /* Process a key typed within TAPPING_TERM
 | 
			
		||||
                 * This can register the key before settlement of tapping,
 | 
			
		||||
                 * useful for long TAPPING_TERM but may prevent fast typing.
 | 
			
		||||
                 */
 | 
			
		||||
#    if defined(TAPPING_TERM_PER_KEY) || (TAPPING_TERM >= 500) || defined(PERMISSIVE_HOLD) || defined(PERMISSIVE_HOLD_PER_KEY)
 | 
			
		||||
                else if (((
 | 
			
		||||
#        ifdef TAPPING_TERM_PER_KEY
 | 
			
		||||
                              get_tapping_term(get_record_keycode(&tapping_key, false), keyp)
 | 
			
		||||
#        else
 | 
			
		||||
                              TAPPING_TERM
 | 
			
		||||
#        endif
 | 
			
		||||
                              >= 500)
 | 
			
		||||
 | 
			
		||||
#        ifdef PERMISSIVE_HOLD_PER_KEY
 | 
			
		||||
                          || get_permissive_hold(get_record_keycode(&tapping_key, false), keyp)
 | 
			
		||||
#        elif defined(PERMISSIVE_HOLD)
 | 
			
		||||
                          || true
 | 
			
		||||
#        endif
 | 
			
		||||
                              ) &&
 | 
			
		||||
                         IS_RELEASED(event) && waiting_buffer_typed(event)) {
 | 
			
		||||
                    debug("Tapping: End. No tap. Interfered by typing key\n");
 | 
			
		||||
                    process_record(&tapping_key);
 | 
			
		||||
                    tapping_key = (keyrecord_t){};
 | 
			
		||||
                    debug_tapping_key();
 | 
			
		||||
                    // enqueue
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
#    endif
 | 
			
		||||
                /* Process release event of a key pressed before tapping starts
 | 
			
		||||
                 * Without this unexpected repeating will occur with having fast repeating setting
 | 
			
		||||
                 * https://github.com/tmk/tmk_keyboard/issues/60
 | 
			
		||||
                 */
 | 
			
		||||
                else if (IS_RELEASED(event) && !waiting_buffer_typed(event)) {
 | 
			
		||||
                    // Modifier should be retained till end of this tapping.
 | 
			
		||||
                    action_t action = layer_switch_get_action(event.key);
 | 
			
		||||
                    switch (action.kind.id) {
 | 
			
		||||
                        case ACT_LMODS:
 | 
			
		||||
                        case ACT_RMODS:
 | 
			
		||||
                            if (action.key.mods && !action.key.code) return false;
 | 
			
		||||
                            if (IS_MOD(action.key.code)) return false;
 | 
			
		||||
                            break;
 | 
			
		||||
                        case ACT_LMODS_TAP:
 | 
			
		||||
                        case ACT_RMODS_TAP:
 | 
			
		||||
                            if (action.key.mods && keyp->tap.count == 0) return false;
 | 
			
		||||
                            if (IS_MOD(action.key.code)) return false;
 | 
			
		||||
                            break;
 | 
			
		||||
                    }
 | 
			
		||||
                    // Release of key should be process immediately.
 | 
			
		||||
                    debug("Tapping: release event of a key pressed before tapping\n");
 | 
			
		||||
                    process_record(keyp);
 | 
			
		||||
                    return true;
 | 
			
		||||
                } else {
 | 
			
		||||
                    // set interrupted flag when other key preesed during tapping
 | 
			
		||||
                    if (event.pressed) {
 | 
			
		||||
                        tapping_key.tap.interrupted = true;
 | 
			
		||||
#    if defined(HOLD_ON_OTHER_KEY_PRESS) || defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
 | 
			
		||||
#        if defined(HOLD_ON_OTHER_KEY_PRESS_PER_KEY)
 | 
			
		||||
                        if (get_hold_on_other_key_press(get_record_keycode(&tapping_key, false), keyp))
 | 
			
		||||
#        endif
 | 
			
		||||
                        {
 | 
			
		||||
                            debug("Tapping: End. No tap. Interfered by pressed key\n");
 | 
			
		||||
                            process_record(&tapping_key);
 | 
			
		||||
                            tapping_key = (keyrecord_t){};
 | 
			
		||||
                            debug_tapping_key();
 | 
			
		||||
                            // enqueue
 | 
			
		||||
                            return false;
 | 
			
		||||
                        }
 | 
			
		||||
#    endif
 | 
			
		||||
                    }
 | 
			
		||||
                    // enqueue
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            // tap_count > 0
 | 
			
		||||
            else {
 | 
			
		||||
                if (IS_TAPPING_RECORD(keyp) && !event.pressed) {
 | 
			
		||||
                    debug("Tapping: Tap release(");
 | 
			
		||||
                    debug_dec(tapping_key.tap.count);
 | 
			
		||||
                    debug(")\n");
 | 
			
		||||
                    keyp->tap = tapping_key.tap;
 | 
			
		||||
                    process_record(keyp);
 | 
			
		||||
                    tapping_key = *keyp;
 | 
			
		||||
                    debug_tapping_key();
 | 
			
		||||
                    return true;
 | 
			
		||||
                } else if (is_tap_record(keyp) && event.pressed) {
 | 
			
		||||
                    if (tapping_key.tap.count > 1) {
 | 
			
		||||
                        debug("Tapping: Start new tap with releasing last tap(>1).\n");
 | 
			
		||||
                        // unregister key
 | 
			
		||||
                        process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false,
 | 
			
		||||
#ifdef COMBO_ENABLE
 | 
			
		||||
                                .keycode = tapping_key.keycode,
 | 
			
		||||
#endif
 | 
			
		||||
                                });
 | 
			
		||||
                    } else {
 | 
			
		||||
                        debug("Tapping: Start while last tap(1).\n");
 | 
			
		||||
                    }
 | 
			
		||||
                    tapping_key = *keyp;
 | 
			
		||||
                    waiting_buffer_scan_tap();
 | 
			
		||||
                    debug_tapping_key();
 | 
			
		||||
                    return true;
 | 
			
		||||
                } else {
 | 
			
		||||
                    if (!IS_NOEVENT(event)) {
 | 
			
		||||
                        debug("Tapping: key event while last tap(>0).\n");
 | 
			
		||||
                    }
 | 
			
		||||
                    process_record(keyp);
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // after TAPPING_TERM
 | 
			
		||||
        else {
 | 
			
		||||
            if (tapping_key.tap.count == 0) {
 | 
			
		||||
                debug("Tapping: End. Timeout. Not tap(0): ");
 | 
			
		||||
                debug_event(event);
 | 
			
		||||
                debug("\n");
 | 
			
		||||
                process_record(&tapping_key);
 | 
			
		||||
                tapping_key = (keyrecord_t){};
 | 
			
		||||
                debug_tapping_key();
 | 
			
		||||
                return false;
 | 
			
		||||
            } else {
 | 
			
		||||
                if (IS_TAPPING_RECORD(keyp) && !event.pressed) {
 | 
			
		||||
                    debug("Tapping: End. last timeout tap release(>0).");
 | 
			
		||||
                    keyp->tap = tapping_key.tap;
 | 
			
		||||
                    process_record(keyp);
 | 
			
		||||
                    tapping_key = (keyrecord_t){};
 | 
			
		||||
                    return true;
 | 
			
		||||
                } else if (is_tap_record(keyp) && event.pressed) {
 | 
			
		||||
                    if (tapping_key.tap.count > 1) {
 | 
			
		||||
                        debug("Tapping: Start new tap with releasing last timeout tap(>1).\n");
 | 
			
		||||
                        // unregister key
 | 
			
		||||
                        process_record(&(keyrecord_t){.tap = tapping_key.tap, .event.key = tapping_key.event.key, .event.time = event.time, .event.pressed = false,
 | 
			
		||||
#ifdef COMBO_ENABLE
 | 
			
		||||
                                .keycode = tapping_key.keycode,
 | 
			
		||||
#endif
 | 
			
		||||
                                });
 | 
			
		||||
                    } else {
 | 
			
		||||
                        debug("Tapping: Start while last timeout tap(1).\n");
 | 
			
		||||
                    }
 | 
			
		||||
                    tapping_key = *keyp;
 | 
			
		||||
                    waiting_buffer_scan_tap();
 | 
			
		||||
                    debug_tapping_key();
 | 
			
		||||
                    return true;
 | 
			
		||||
                } else {
 | 
			
		||||
                    if (!IS_NOEVENT(event)) {
 | 
			
		||||
                        debug("Tapping: key event while last timeout tap(>0).\n");
 | 
			
		||||
                    }
 | 
			
		||||
                    process_record(keyp);
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else if (IS_TAPPING_RELEASED()) {
 | 
			
		||||
        if (WITHIN_TAPPING_TERM(event)) {
 | 
			
		||||
            if (event.pressed) {
 | 
			
		||||
                if (IS_TAPPING_RECORD(keyp)) {
 | 
			
		||||
//#    ifndef TAPPING_FORCE_HOLD
 | 
			
		||||
#    if !defined(TAPPING_FORCE_HOLD) || defined(TAPPING_FORCE_HOLD_PER_KEY)
 | 
			
		||||
                    if (
 | 
			
		||||
#        ifdef TAPPING_FORCE_HOLD_PER_KEY
 | 
			
		||||
                        !get_tapping_force_hold(get_record_keycode(&tapping_key, false), keyp) &&
 | 
			
		||||
#        endif
 | 
			
		||||
                        !tapping_key.tap.interrupted && tapping_key.tap.count > 0) {
 | 
			
		||||
                        // sequential tap.
 | 
			
		||||
                        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_record(keyp);
 | 
			
		||||
                        tapping_key = *keyp;
 | 
			
		||||
                        debug_tapping_key();
 | 
			
		||||
                        return true;
 | 
			
		||||
                    }
 | 
			
		||||
#    endif
 | 
			
		||||
                    // FIX: start new tap again
 | 
			
		||||
                    tapping_key = *keyp;
 | 
			
		||||
                    return true;
 | 
			
		||||
                } else if (is_tap_record(keyp)) {
 | 
			
		||||
                    // Sequential tap can be interfered with other tap key.
 | 
			
		||||
                    debug("Tapping: Start with interfering other tap.\n");
 | 
			
		||||
                    tapping_key = *keyp;
 | 
			
		||||
                    waiting_buffer_scan_tap();
 | 
			
		||||
                    debug_tapping_key();
 | 
			
		||||
                    return true;
 | 
			
		||||
                } else {
 | 
			
		||||
                    // should none in buffer
 | 
			
		||||
                    // FIX: interrupted when other key is pressed
 | 
			
		||||
                    tapping_key.tap.interrupted = true;
 | 
			
		||||
                    process_record(keyp);
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n");
 | 
			
		||||
                process_record(keyp);
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            // FIX: process_action here?
 | 
			
		||||
            // timeout. no sequential tap.
 | 
			
		||||
            debug("Tapping: End(Timeout after releasing last tap): ");
 | 
			
		||||
            debug_event(event);
 | 
			
		||||
            debug("\n");
 | 
			
		||||
            tapping_key = (keyrecord_t){};
 | 
			
		||||
            debug_tapping_key();
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // not tapping state
 | 
			
		||||
    else {
 | 
			
		||||
        if (event.pressed && is_tap_record(keyp)) {
 | 
			
		||||
            debug("Tapping: Start(Press tap key).\n");
 | 
			
		||||
            tapping_key = *keyp;
 | 
			
		||||
            process_record_tap_hint(&tapping_key);
 | 
			
		||||
            waiting_buffer_scan_tap();
 | 
			
		||||
            debug_tapping_key();
 | 
			
		||||
            return true;
 | 
			
		||||
        } else {
 | 
			
		||||
            process_record(keyp);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Waiting buffer enq
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: Needs docs
 | 
			
		||||
 */
 | 
			
		||||
bool waiting_buffer_enq(keyrecord_t record) {
 | 
			
		||||
    if (IS_NOEVENT(record.event)) {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((waiting_buffer_head + 1) % WAITING_BUFFER_SIZE == waiting_buffer_tail) {
 | 
			
		||||
        debug("waiting_buffer_enq: Over flow.\n");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    waiting_buffer[waiting_buffer_head] = record;
 | 
			
		||||
    waiting_buffer_head                 = (waiting_buffer_head + 1) % WAITING_BUFFER_SIZE;
 | 
			
		||||
 | 
			
		||||
    debug("waiting_buffer_enq: ");
 | 
			
		||||
    debug_waiting_buffer();
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Waiting buffer clear
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: Needs docs
 | 
			
		||||
 */
 | 
			
		||||
void waiting_buffer_clear(void) {
 | 
			
		||||
    waiting_buffer_head = 0;
 | 
			
		||||
    waiting_buffer_tail = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Waiting buffer typed
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: Needs docs
 | 
			
		||||
 */
 | 
			
		||||
bool waiting_buffer_typed(keyevent_t event) {
 | 
			
		||||
    for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
 | 
			
		||||
        if (KEYEQ(event.key, waiting_buffer[i].event.key) && event.pressed != waiting_buffer[i].event.pressed) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Waiting buffer has anykey pressed
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: Needs docs
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((unused)) bool waiting_buffer_has_anykey_pressed(void) {
 | 
			
		||||
    for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
 | 
			
		||||
        if (waiting_buffer[i].event.pressed) return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Scan buffer for tapping
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: Needs docs
 | 
			
		||||
 */
 | 
			
		||||
void waiting_buffer_scan_tap(void) {
 | 
			
		||||
    // tapping already is settled
 | 
			
		||||
    if (tapping_key.tap.count > 0) return;
 | 
			
		||||
    // invalid state: tapping_key released && tap.count == 0
 | 
			
		||||
    if (!tapping_key.event.pressed) return;
 | 
			
		||||
 | 
			
		||||
    for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
 | 
			
		||||
        if (IS_TAPPING_KEY(waiting_buffer[i].event.key) && !waiting_buffer[i].event.pressed && WITHIN_TAPPING_TERM(waiting_buffer[i].event)) {
 | 
			
		||||
            tapping_key.tap.count       = 1;
 | 
			
		||||
            waiting_buffer[i].tap.count = 1;
 | 
			
		||||
            process_record(&tapping_key);
 | 
			
		||||
 | 
			
		||||
            debug("waiting_buffer_scan_tap: found at [");
 | 
			
		||||
            debug_dec(i);
 | 
			
		||||
            debug("]\n");
 | 
			
		||||
            debug_waiting_buffer();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Tapping key debug print
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: Needs docs
 | 
			
		||||
 */
 | 
			
		||||
static void debug_tapping_key(void) {
 | 
			
		||||
    debug("TAPPING_KEY=");
 | 
			
		||||
    debug_record(tapping_key);
 | 
			
		||||
    debug("\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Waiting buffer debug print
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: Needs docs
 | 
			
		||||
 */
 | 
			
		||||
static void debug_waiting_buffer(void) {
 | 
			
		||||
    debug("{ ");
 | 
			
		||||
    for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
 | 
			
		||||
        debug("[");
 | 
			
		||||
        debug_dec(i);
 | 
			
		||||
        debug("]=");
 | 
			
		||||
        debug_record(waiting_buffer[i]);
 | 
			
		||||
        debug(" ");
 | 
			
		||||
    }
 | 
			
		||||
    debug("}\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,42 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 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
 | 
			
		||||
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/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
/* period of tapping(ms) */
 | 
			
		||||
#ifndef TAPPING_TERM
 | 
			
		||||
#    define TAPPING_TERM 200
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* tap count needed for toggling a feature */
 | 
			
		||||
#ifndef TAPPING_TOGGLE
 | 
			
		||||
#    define TAPPING_TOGGLE 5
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define WAITING_BUFFER_SIZE 8
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_TAPPING
 | 
			
		||||
uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache);
 | 
			
		||||
uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache);
 | 
			
		||||
void     action_tapping_process(keyrecord_t record);
 | 
			
		||||
 | 
			
		||||
uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record);
 | 
			
		||||
bool     get_permissive_hold(uint16_t keycode, keyrecord_t *record);
 | 
			
		||||
bool     get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record);
 | 
			
		||||
bool     get_tapping_force_hold(uint16_t keycode, keyrecord_t *record);
 | 
			
		||||
bool     get_retro_tapping(uint16_t keycode, keyrecord_t *record);
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,455 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 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
 | 
			
		||||
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 "host.h"
 | 
			
		||||
#include "report.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#include "action_util.h"
 | 
			
		||||
#include "action_layer.h"
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
#include "keycode_config.h"
 | 
			
		||||
 | 
			
		||||
extern keymap_config_t keymap_config;
 | 
			
		||||
 | 
			
		||||
static uint8_t real_mods  = 0;
 | 
			
		||||
static uint8_t weak_mods  = 0;
 | 
			
		||||
static uint8_t macro_mods = 0;
 | 
			
		||||
#ifdef KEY_OVERRIDE_ENABLE
 | 
			
		||||
static uint8_t weak_override_mods = 0;
 | 
			
		||||
static uint8_t suppressed_mods    = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USB_6KRO_ENABLE
 | 
			
		||||
#    define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS)
 | 
			
		||||
#    define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS)
 | 
			
		||||
#    define RO_INC(a) RO_ADD(a, 1)
 | 
			
		||||
#    define RO_DEC(a) RO_SUB(a, 1)
 | 
			
		||||
static int8_t cb_head  = 0;
 | 
			
		||||
static int8_t cb_tail  = 0;
 | 
			
		||||
static int8_t cb_count = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// TODO: pointer variable is not needed
 | 
			
		||||
// report_keyboard_t keyboard_report = {};
 | 
			
		||||
report_keyboard_t *keyboard_report = &(report_keyboard_t){};
 | 
			
		||||
 | 
			
		||||
extern inline void add_key(uint8_t key);
 | 
			
		||||
extern inline void del_key(uint8_t key);
 | 
			
		||||
extern inline void clear_keys(void);
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_ONESHOT
 | 
			
		||||
static uint8_t oneshot_mods        = 0;
 | 
			
		||||
static uint8_t oneshot_locked_mods = 0;
 | 
			
		||||
uint8_t        get_oneshot_locked_mods(void) { return oneshot_locked_mods; }
 | 
			
		||||
void           set_oneshot_locked_mods(uint8_t mods) {
 | 
			
		||||
    if (mods != oneshot_locked_mods) {
 | 
			
		||||
        oneshot_locked_mods = mods;
 | 
			
		||||
        oneshot_locked_mods_changed_kb(oneshot_locked_mods);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
void clear_oneshot_locked_mods(void) {
 | 
			
		||||
    if (oneshot_locked_mods) {
 | 
			
		||||
        oneshot_locked_mods = 0;
 | 
			
		||||
        oneshot_locked_mods_changed_kb(oneshot_locked_mods);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#    if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
 | 
			
		||||
static uint16_t oneshot_time = 0;
 | 
			
		||||
bool            has_oneshot_mods_timed_out(void) { return TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT; }
 | 
			
		||||
#    else
 | 
			
		||||
bool has_oneshot_mods_timed_out(void) { return false; }
 | 
			
		||||
#    endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* oneshot layer */
 | 
			
		||||
#ifndef NO_ACTION_ONESHOT
 | 
			
		||||
/** \brief 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; }
 | 
			
		||||
 | 
			
		||||
#    ifdef SWAP_HANDS_ENABLE
 | 
			
		||||
enum {
 | 
			
		||||
    SHO_OFF,
 | 
			
		||||
    SHO_ACTIVE,   // Swap hands button was pressed, and we didn't send any swapped keys yet
 | 
			
		||||
    SHO_PRESSED,  // Swap hands button is currently pressed
 | 
			
		||||
    SHO_USED,     // Swap hands button is still pressed, and we already sent swapped keys
 | 
			
		||||
} swap_hands_oneshot = SHO_OFF;
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
#    if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
 | 
			
		||||
static uint16_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); }
 | 
			
		||||
#        ifdef SWAP_HANDS_ENABLE
 | 
			
		||||
static uint16_t oneshot_swaphands_time = 0;
 | 
			
		||||
inline bool     has_oneshot_swaphands_timed_out() { return TIMER_DIFF_16(timer_read(), oneshot_swaphands_time) >= ONESHOT_TIMEOUT && (swap_hands_oneshot == SHO_ACTIVE); }
 | 
			
		||||
#        endif
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
#    ifdef SWAP_HANDS_ENABLE
 | 
			
		||||
 | 
			
		||||
void set_oneshot_swaphands(void) {
 | 
			
		||||
    swap_hands_oneshot = SHO_PRESSED;
 | 
			
		||||
    swap_hands         = true;
 | 
			
		||||
#        if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
 | 
			
		||||
    oneshot_swaphands_time = timer_read();
 | 
			
		||||
    if (oneshot_layer_time != 0) {
 | 
			
		||||
        oneshot_layer_time = oneshot_swaphands_time;
 | 
			
		||||
    }
 | 
			
		||||
#        endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void release_oneshot_swaphands(void) {
 | 
			
		||||
    if (swap_hands_oneshot == SHO_PRESSED) {
 | 
			
		||||
        swap_hands_oneshot = SHO_ACTIVE;
 | 
			
		||||
    }
 | 
			
		||||
    if (swap_hands_oneshot == SHO_USED) {
 | 
			
		||||
        clear_oneshot_swaphands();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void use_oneshot_swaphands(void) {
 | 
			
		||||
    if (swap_hands_oneshot == SHO_PRESSED) {
 | 
			
		||||
        swap_hands_oneshot = SHO_USED;
 | 
			
		||||
    }
 | 
			
		||||
    if (swap_hands_oneshot == SHO_ACTIVE) {
 | 
			
		||||
        clear_oneshot_swaphands();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void clear_oneshot_swaphands(void) {
 | 
			
		||||
    swap_hands_oneshot = SHO_OFF;
 | 
			
		||||
    swap_hands         = false;
 | 
			
		||||
#        if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
 | 
			
		||||
    oneshot_swaphands_time = 0;
 | 
			
		||||
#        endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#    endif
 | 
			
		||||
 | 
			
		||||
/** \brief Set oneshot layer
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void set_oneshot_layer(uint8_t layer, uint8_t state) {
 | 
			
		||||
    if (!keymap_config.oneshot_disable) {
 | 
			
		||||
        oneshot_layer_data = layer << 3 | state;
 | 
			
		||||
        layer_on(layer);
 | 
			
		||||
#    if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
 | 
			
		||||
        oneshot_layer_time = timer_read();
 | 
			
		||||
#    endif
 | 
			
		||||
        oneshot_layer_changed_kb(get_oneshot_layer());
 | 
			
		||||
    } else {
 | 
			
		||||
        layer_on(layer);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/** \brief Reset oneshot layer
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void reset_oneshot_layer(void) {
 | 
			
		||||
    oneshot_layer_data = 0;
 | 
			
		||||
#    if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
 | 
			
		||||
    oneshot_layer_time = 0;
 | 
			
		||||
#    endif
 | 
			
		||||
    oneshot_layer_changed_kb(get_oneshot_layer());
 | 
			
		||||
}
 | 
			
		||||
/** \brief Clear oneshot layer
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
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) || keymap_config.oneshot_disable) {
 | 
			
		||||
        layer_off(get_oneshot_layer());
 | 
			
		||||
        reset_oneshot_layer();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/** \brief Is oneshot layer active
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
bool is_oneshot_layer_active(void) { return get_oneshot_layer_state(); }
 | 
			
		||||
 | 
			
		||||
/** \brief set oneshot
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void oneshot_set(bool active) {
 | 
			
		||||
    if (keymap_config.oneshot_disable != active) {
 | 
			
		||||
        keymap_config.oneshot_disable = active;
 | 
			
		||||
        eeconfig_update_keymap(keymap_config.raw);
 | 
			
		||||
        dprintf("Oneshot: active: %d\n", active);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief toggle oneshot
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void oneshot_toggle(void) { oneshot_set(!keymap_config.oneshot_disable); }
 | 
			
		||||
 | 
			
		||||
/** \brief enable oneshot
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void oneshot_enable(void) { oneshot_set(true); }
 | 
			
		||||
 | 
			
		||||
/** \brief disable oneshot
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void oneshot_disable(void) { oneshot_set(false); }
 | 
			
		||||
 | 
			
		||||
bool is_oneshot_enabled(void) { return keymap_config.oneshot_disable; }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** \brief Send keyboard report
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void send_keyboard_report(void) {
 | 
			
		||||
    keyboard_report->mods = real_mods;
 | 
			
		||||
    keyboard_report->mods |= weak_mods;
 | 
			
		||||
    keyboard_report->mods |= macro_mods;
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_ONESHOT
 | 
			
		||||
    if (oneshot_mods) {
 | 
			
		||||
#    if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
 | 
			
		||||
        if (has_oneshot_mods_timed_out()) {
 | 
			
		||||
            dprintf("Oneshot: timeout\n");
 | 
			
		||||
            clear_oneshot_mods();
 | 
			
		||||
        }
 | 
			
		||||
#    endif
 | 
			
		||||
        keyboard_report->mods |= oneshot_mods;
 | 
			
		||||
        if (has_anykey(keyboard_report)) {
 | 
			
		||||
            clear_oneshot_mods();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef KEY_OVERRIDE_ENABLE
 | 
			
		||||
    // These need to be last to be able to properly control key overrides
 | 
			
		||||
    keyboard_report->mods &= ~suppressed_mods;
 | 
			
		||||
    keyboard_report->mods |= weak_override_mods;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    host_keyboard_send(keyboard_report);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Get mods
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
uint8_t get_mods(void) { return real_mods; }
 | 
			
		||||
/** \brief add mods
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void add_mods(uint8_t mods) { real_mods |= mods; }
 | 
			
		||||
/** \brief del mods
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void del_mods(uint8_t mods) { real_mods &= ~mods; }
 | 
			
		||||
/** \brief set mods
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void set_mods(uint8_t mods) { real_mods = mods; }
 | 
			
		||||
/** \brief clear mods
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void clear_mods(void) { real_mods = 0; }
 | 
			
		||||
 | 
			
		||||
/** \brief get weak mods
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
uint8_t get_weak_mods(void) { return weak_mods; }
 | 
			
		||||
/** \brief add weak mods
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void add_weak_mods(uint8_t mods) { weak_mods |= mods; }
 | 
			
		||||
/** \brief del weak mods
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void del_weak_mods(uint8_t mods) { weak_mods &= ~mods; }
 | 
			
		||||
/** \brief set weak mods
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void set_weak_mods(uint8_t mods) { weak_mods = mods; }
 | 
			
		||||
/** \brief clear weak mods
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void clear_weak_mods(void) { weak_mods = 0; }
 | 
			
		||||
 | 
			
		||||
#ifdef KEY_OVERRIDE_ENABLE
 | 
			
		||||
/** \brief set weak mods used by key overrides. DO not call this manually
 | 
			
		||||
 */
 | 
			
		||||
void set_weak_override_mods(uint8_t mods) { weak_override_mods = mods; }
 | 
			
		||||
/** \brief clear weak mods used by key overrides. DO not call this manually
 | 
			
		||||
 */
 | 
			
		||||
void clear_weak_override_mods(void) { weak_override_mods = 0; }
 | 
			
		||||
 | 
			
		||||
/** \brief set suppressed mods used by key overrides. DO not call this manually
 | 
			
		||||
 */
 | 
			
		||||
void set_suppressed_override_mods(uint8_t mods) { suppressed_mods = mods; }
 | 
			
		||||
/** \brief clear suppressed mods used by key overrides. DO not call this manually
 | 
			
		||||
 */
 | 
			
		||||
void clear_suppressed_override_mods(void) { suppressed_mods = 0; }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* macro modifier */
 | 
			
		||||
/** \brief get macro mods
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
uint8_t get_macro_mods(void) { return macro_mods; }
 | 
			
		||||
/** \brief add macro mods
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void add_macro_mods(uint8_t mods) { macro_mods |= mods; }
 | 
			
		||||
/** \brief del macro mods
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void del_macro_mods(uint8_t mods) { macro_mods &= ~mods; }
 | 
			
		||||
/** \brief set macro mods
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void set_macro_mods(uint8_t mods) { macro_mods = mods; }
 | 
			
		||||
/** \brief clear macro mods
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void clear_macro_mods(void) { macro_mods = 0; }
 | 
			
		||||
 | 
			
		||||
#ifndef NO_ACTION_ONESHOT
 | 
			
		||||
/** \brief get oneshot mods
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
uint8_t get_oneshot_mods(void) { return oneshot_mods; }
 | 
			
		||||
 | 
			
		||||
void add_oneshot_mods(uint8_t mods) {
 | 
			
		||||
    if ((oneshot_mods & mods) != mods) {
 | 
			
		||||
#    if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
 | 
			
		||||
        oneshot_time = timer_read();
 | 
			
		||||
#    endif
 | 
			
		||||
        oneshot_mods |= mods;
 | 
			
		||||
        oneshot_mods_changed_kb(mods);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void del_oneshot_mods(uint8_t mods) {
 | 
			
		||||
    if (oneshot_mods & mods) {
 | 
			
		||||
        oneshot_mods &= ~mods;
 | 
			
		||||
#    if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
 | 
			
		||||
        oneshot_time = oneshot_mods ? timer_read() : 0;
 | 
			
		||||
#    endif
 | 
			
		||||
        oneshot_mods_changed_kb(oneshot_mods);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief set oneshot mods
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void set_oneshot_mods(uint8_t mods) {
 | 
			
		||||
    if (!keymap_config.oneshot_disable) {
 | 
			
		||||
        if (oneshot_mods != mods) {
 | 
			
		||||
#    if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
 | 
			
		||||
            oneshot_time = timer_read();
 | 
			
		||||
#    endif
 | 
			
		||||
            oneshot_mods = mods;
 | 
			
		||||
            oneshot_mods_changed_kb(mods);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief clear oneshot mods
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void clear_oneshot_mods(void) {
 | 
			
		||||
    if (oneshot_mods) {
 | 
			
		||||
        oneshot_mods = 0;
 | 
			
		||||
#    if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
 | 
			
		||||
        oneshot_time = 0;
 | 
			
		||||
#    endif
 | 
			
		||||
        oneshot_mods_changed_kb(oneshot_mods);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** \brief Called when the one shot modifiers have been changed.
 | 
			
		||||
 *
 | 
			
		||||
 * \param mods Contains the active modifiers active after the change.
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) void oneshot_locked_mods_changed_user(uint8_t mods) {}
 | 
			
		||||
 | 
			
		||||
/** \brief Called when the locked one shot modifiers have been changed.
 | 
			
		||||
 *
 | 
			
		||||
 * \param mods Contains the active modifiers active after the change.
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) void oneshot_locked_mods_changed_kb(uint8_t mods) { oneshot_locked_mods_changed_user(mods); }
 | 
			
		||||
 | 
			
		||||
/** \brief Called when the one shot modifiers have been changed.
 | 
			
		||||
 *
 | 
			
		||||
 * \param mods Contains the active modifiers active after the change.
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) void oneshot_mods_changed_user(uint8_t mods) {}
 | 
			
		||||
 | 
			
		||||
/** \brief Called when the one shot modifiers have been changed.
 | 
			
		||||
 *
 | 
			
		||||
 * \param mods Contains the active modifiers active after the change.
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) void oneshot_mods_changed_kb(uint8_t mods) { oneshot_mods_changed_user(mods); }
 | 
			
		||||
 | 
			
		||||
/** \brief Called when the one shot layers have been changed.
 | 
			
		||||
 *
 | 
			
		||||
 * \param layer Contains the layer that is toggled on, or zero when toggled off.
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) void oneshot_layer_changed_user(uint8_t layer) {}
 | 
			
		||||
 | 
			
		||||
/** \brief Called when the one shot layers have been changed.
 | 
			
		||||
 *
 | 
			
		||||
 * \param layer Contains the layer that is toggled on, or zero when toggled off.
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) void oneshot_layer_changed_kb(uint8_t layer) { oneshot_layer_changed_user(layer); }
 | 
			
		||||
 | 
			
		||||
/** \brief inspect keyboard state
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
uint8_t has_anymod(void) { return bitpop(real_mods); }
 | 
			
		||||
| 
						 | 
				
			
			@ -1,105 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 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
 | 
			
		||||
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/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "report.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern report_keyboard_t *keyboard_report;
 | 
			
		||||
 | 
			
		||||
void send_keyboard_report(void);
 | 
			
		||||
 | 
			
		||||
/* key */
 | 
			
		||||
inline void add_key(uint8_t key) { add_key_to_report(keyboard_report, key); }
 | 
			
		||||
 | 
			
		||||
inline void del_key(uint8_t key) { del_key_from_report(keyboard_report, key); }
 | 
			
		||||
 | 
			
		||||
inline void clear_keys(void) { clear_keys_from_report(keyboard_report); }
 | 
			
		||||
 | 
			
		||||
/* modifier */
 | 
			
		||||
uint8_t get_mods(void);
 | 
			
		||||
void    add_mods(uint8_t mods);
 | 
			
		||||
void    del_mods(uint8_t mods);
 | 
			
		||||
void    set_mods(uint8_t mods);
 | 
			
		||||
void    clear_mods(void);
 | 
			
		||||
 | 
			
		||||
/* weak modifier */
 | 
			
		||||
uint8_t get_weak_mods(void);
 | 
			
		||||
void    add_weak_mods(uint8_t mods);
 | 
			
		||||
void    del_weak_mods(uint8_t mods);
 | 
			
		||||
void    set_weak_mods(uint8_t mods);
 | 
			
		||||
void    clear_weak_mods(void);
 | 
			
		||||
 | 
			
		||||
/* macro modifier */
 | 
			
		||||
uint8_t get_macro_mods(void);
 | 
			
		||||
void    add_macro_mods(uint8_t mods);
 | 
			
		||||
void    del_macro_mods(uint8_t mods);
 | 
			
		||||
void    set_macro_mods(uint8_t mods);
 | 
			
		||||
void    clear_macro_mods(void);
 | 
			
		||||
 | 
			
		||||
/* oneshot modifier */
 | 
			
		||||
uint8_t get_oneshot_mods(void);
 | 
			
		||||
void    add_oneshot_mods(uint8_t mods);
 | 
			
		||||
void    del_oneshot_mods(uint8_t mods);
 | 
			
		||||
void    set_oneshot_mods(uint8_t mods);
 | 
			
		||||
void    clear_oneshot_mods(void);
 | 
			
		||||
bool    has_oneshot_mods_timed_out(void);
 | 
			
		||||
 | 
			
		||||
uint8_t get_oneshot_locked_mods(void);
 | 
			
		||||
void    set_oneshot_locked_mods(uint8_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);
 | 
			
		||||
bool    has_oneshot_swaphands_timed_out(void);
 | 
			
		||||
 | 
			
		||||
void oneshot_locked_mods_changed_user(uint8_t mods);
 | 
			
		||||
void oneshot_locked_mods_changed_kb(uint8_t mods);
 | 
			
		||||
void oneshot_mods_changed_user(uint8_t mods);
 | 
			
		||||
void oneshot_mods_changed_kb(uint8_t mods);
 | 
			
		||||
void oneshot_layer_changed_user(uint8_t layer);
 | 
			
		||||
void oneshot_layer_changed_kb(uint8_t layer);
 | 
			
		||||
 | 
			
		||||
void oneshot_toggle(void);
 | 
			
		||||
void oneshot_enable(void);
 | 
			
		||||
void oneshot_disable(void);
 | 
			
		||||
bool is_oneshot_enabled(void);
 | 
			
		||||
 | 
			
		||||
/* inspect */
 | 
			
		||||
uint8_t has_anymod(void);
 | 
			
		||||
 | 
			
		||||
#ifdef SWAP_HANDS_ENABLE
 | 
			
		||||
void set_oneshot_swaphands(void);
 | 
			
		||||
void release_oneshot_swaphands(void);
 | 
			
		||||
void use_oneshot_swaphands(void);
 | 
			
		||||
void clear_oneshot_swaphands(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,211 +0,0 @@
 | 
			
		|||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "eeprom.h"
 | 
			
		||||
#include "eeconfig.h"
 | 
			
		||||
#include "action_layer.h"
 | 
			
		||||
 | 
			
		||||
#ifdef STM32_EEPROM_ENABLE
 | 
			
		||||
#    include <hal.h>
 | 
			
		||||
#    include "eeprom_stm32.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(EEPROM_DRIVER)
 | 
			
		||||
#    include "eeprom_driver.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(HAPTIC_ENABLE)
 | 
			
		||||
#    include "haptic.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** \brief eeconfig enable
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) void eeconfig_init_user(void) {
 | 
			
		||||
    // Reset user EEPROM value to blank, rather than to a set value
 | 
			
		||||
    eeconfig_update_user(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((weak)) void eeconfig_init_kb(void) {
 | 
			
		||||
    // Reset Keyboard EEPROM value to blank, rather than to a set value
 | 
			
		||||
    eeconfig_update_kb(0);
 | 
			
		||||
 | 
			
		||||
    eeconfig_init_user();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void eeconfig_init_quantum(void) {
 | 
			
		||||
#ifdef STM32_EEPROM_ENABLE
 | 
			
		||||
    EEPROM_Erase();
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(EEPROM_DRIVER)
 | 
			
		||||
    eeprom_driver_erase();
 | 
			
		||||
#endif
 | 
			
		||||
    eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
 | 
			
		||||
    eeprom_update_byte(EECONFIG_DEBUG, 0);
 | 
			
		||||
    eeprom_update_byte(EECONFIG_DEFAULT_LAYER, 0);
 | 
			
		||||
    default_layer_state = 0;
 | 
			
		||||
    eeprom_update_byte(EECONFIG_KEYMAP_LOWER_BYTE, 0);
 | 
			
		||||
    eeprom_update_byte(EECONFIG_KEYMAP_UPPER_BYTE, 0);
 | 
			
		||||
    eeprom_update_byte(EECONFIG_MOUSEKEY_ACCEL, 0);
 | 
			
		||||
    eeprom_update_byte(EECONFIG_BACKLIGHT, 0);
 | 
			
		||||
    eeprom_update_byte(EECONFIG_AUDIO, 0xFF);  // On by default
 | 
			
		||||
    eeprom_update_dword(EECONFIG_RGBLIGHT, 0);
 | 
			
		||||
    eeprom_update_byte(EECONFIG_STENOMODE, 0);
 | 
			
		||||
    eeprom_update_dword(EECONFIG_HAPTIC, 0);
 | 
			
		||||
    eeprom_update_byte(EECONFIG_VELOCIKEY, 0);
 | 
			
		||||
    eeprom_update_dword(EECONFIG_RGB_MATRIX, 0);
 | 
			
		||||
    eeprom_update_word(EECONFIG_RGB_MATRIX_EXTENDED, 0);
 | 
			
		||||
 | 
			
		||||
    // TODO: Remove once ARM has a way to configure EECONFIG_HANDEDNESS
 | 
			
		||||
    //        within the emulated eeprom via dfu-util or another tool
 | 
			
		||||
#if defined INIT_EE_HANDS_LEFT
 | 
			
		||||
#    pragma message "Faking EE_HANDS for left hand"
 | 
			
		||||
    eeprom_update_byte(EECONFIG_HANDEDNESS, 1);
 | 
			
		||||
#elif defined INIT_EE_HANDS_RIGHT
 | 
			
		||||
#    pragma message "Faking EE_HANDS for right hand"
 | 
			
		||||
    eeprom_update_byte(EECONFIG_HANDEDNESS, 0);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(HAPTIC_ENABLE)
 | 
			
		||||
    haptic_reset();
 | 
			
		||||
#else
 | 
			
		||||
    // this is used in case haptic is disabled, but we still want sane defaults
 | 
			
		||||
    // in the haptic configuration eeprom. All zero will trigger a haptic_reset
 | 
			
		||||
    // when a haptic-enabled firmware is loaded onto the keyboard.
 | 
			
		||||
    eeprom_update_dword(EECONFIG_HAPTIC, 0);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    eeconfig_init_kb();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief eeconfig initialization
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void eeconfig_init(void) { eeconfig_init_quantum(); }
 | 
			
		||||
 | 
			
		||||
/** \brief eeconfig enable
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void eeconfig_enable(void) { eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER); }
 | 
			
		||||
 | 
			
		||||
/** \brief eeconfig disable
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void eeconfig_disable(void) {
 | 
			
		||||
#ifdef STM32_EEPROM_ENABLE
 | 
			
		||||
    EEPROM_Erase();
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(EEPROM_DRIVER)
 | 
			
		||||
    eeprom_driver_erase();
 | 
			
		||||
#endif
 | 
			
		||||
    eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER_OFF);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief eeconfig is enabled
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
bool eeconfig_is_enabled(void) { return (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER); }
 | 
			
		||||
 | 
			
		||||
/** \brief eeconfig is disabled
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
bool eeconfig_is_disabled(void) { return (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER_OFF); }
 | 
			
		||||
 | 
			
		||||
/** \brief eeconfig read debug
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
uint8_t eeconfig_read_debug(void) { return eeprom_read_byte(EECONFIG_DEBUG); }
 | 
			
		||||
/** \brief eeconfig update debug
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void eeconfig_update_debug(uint8_t val) { eeprom_update_byte(EECONFIG_DEBUG, val); }
 | 
			
		||||
 | 
			
		||||
/** \brief eeconfig read default layer
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
uint8_t eeconfig_read_default_layer(void) { return eeprom_read_byte(EECONFIG_DEFAULT_LAYER); }
 | 
			
		||||
/** \brief eeconfig update default layer
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void eeconfig_update_default_layer(uint8_t val) { eeprom_update_byte(EECONFIG_DEFAULT_LAYER, val); }
 | 
			
		||||
 | 
			
		||||
/** \brief eeconfig read keymap
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
uint16_t eeconfig_read_keymap(void) { return (eeprom_read_byte(EECONFIG_KEYMAP_LOWER_BYTE) | (eeprom_read_byte(EECONFIG_KEYMAP_UPPER_BYTE) << 8)); }
 | 
			
		||||
/** \brief eeconfig update keymap
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void eeconfig_update_keymap(uint16_t val) {
 | 
			
		||||
    eeprom_update_byte(EECONFIG_KEYMAP_LOWER_BYTE, val & 0xFF);
 | 
			
		||||
    eeprom_update_byte(EECONFIG_KEYMAP_UPPER_BYTE, (val >> 8) & 0xFF);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief eeconfig read audio
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
uint8_t eeconfig_read_audio(void) { return eeprom_read_byte(EECONFIG_AUDIO); }
 | 
			
		||||
/** \brief eeconfig update audio
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void eeconfig_update_audio(uint8_t val) { eeprom_update_byte(EECONFIG_AUDIO, val); }
 | 
			
		||||
 | 
			
		||||
/** \brief eeconfig read kb
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
uint32_t eeconfig_read_kb(void) { return eeprom_read_dword(EECONFIG_KEYBOARD); }
 | 
			
		||||
/** \brief eeconfig update kb
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void eeconfig_update_kb(uint32_t val) { eeprom_update_dword(EECONFIG_KEYBOARD, val); }
 | 
			
		||||
 | 
			
		||||
/** \brief eeconfig read user
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
uint32_t eeconfig_read_user(void) { return eeprom_read_dword(EECONFIG_USER); }
 | 
			
		||||
/** \brief eeconfig update user
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void eeconfig_update_user(uint32_t val) { eeprom_update_dword(EECONFIG_USER, val); }
 | 
			
		||||
 | 
			
		||||
/** \brief eeconfig read haptic
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
uint32_t eeconfig_read_haptic(void) { return eeprom_read_dword(EECONFIG_HAPTIC); }
 | 
			
		||||
/** \brief eeconfig update haptic
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void eeconfig_update_haptic(uint32_t val) { eeprom_update_dword(EECONFIG_HAPTIC, val); }
 | 
			
		||||
 | 
			
		||||
/** \brief eeconfig read split handedness
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
bool eeconfig_read_handedness(void) { return !!eeprom_read_byte(EECONFIG_HANDEDNESS); }
 | 
			
		||||
/** \brief eeconfig update split handedness
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void eeconfig_update_handedness(bool val) { eeprom_update_byte(EECONFIG_HANDEDNESS, !!val); }
 | 
			
		||||
| 
						 | 
				
			
			@ -1,113 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 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
 | 
			
		||||
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/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#ifndef EECONFIG_MAGIC_NUMBER
 | 
			
		||||
#    define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEEA  // When changing, decrement this value to avoid future re-init issues
 | 
			
		||||
#endif
 | 
			
		||||
#define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF
 | 
			
		||||
 | 
			
		||||
/* EEPROM parameter address */
 | 
			
		||||
#define EECONFIG_MAGIC (uint16_t *)0
 | 
			
		||||
#define EECONFIG_DEBUG (uint8_t *)2
 | 
			
		||||
#define EECONFIG_DEFAULT_LAYER (uint8_t *)3
 | 
			
		||||
#define EECONFIG_KEYMAP (uint8_t *)4
 | 
			
		||||
#define EECONFIG_MOUSEKEY_ACCEL (uint8_t *)5
 | 
			
		||||
#define EECONFIG_BACKLIGHT (uint8_t *)6
 | 
			
		||||
#define EECONFIG_AUDIO (uint8_t *)7
 | 
			
		||||
#define EECONFIG_RGBLIGHT (uint32_t *)8
 | 
			
		||||
#define EECONFIG_UNICODEMODE (uint8_t *)12
 | 
			
		||||
#define EECONFIG_STENOMODE (uint8_t *)13
 | 
			
		||||
// EEHANDS for two handed boards
 | 
			
		||||
#define EECONFIG_HANDEDNESS (uint8_t *)14
 | 
			
		||||
#define EECONFIG_KEYBOARD (uint32_t *)15
 | 
			
		||||
#define EECONFIG_USER (uint32_t *)19
 | 
			
		||||
#define EECONFIG_VELOCIKEY (uint8_t *)23
 | 
			
		||||
 | 
			
		||||
#define EECONFIG_HAPTIC (uint32_t *)24
 | 
			
		||||
 | 
			
		||||
// Mutually exclusive
 | 
			
		||||
#define EECONFIG_LED_MATRIX (uint32_t *)28
 | 
			
		||||
#define EECONFIG_RGB_MATRIX (uint32_t *)28
 | 
			
		||||
// Speed & Flags
 | 
			
		||||
#define EECONFIG_LED_MATRIX_EXTENDED (uint16_t *)32
 | 
			
		||||
#define EECONFIG_RGB_MATRIX_EXTENDED (uint16_t *)32
 | 
			
		||||
 | 
			
		||||
// TODO: Combine these into a single word and single block of EEPROM
 | 
			
		||||
#define EECONFIG_KEYMAP_UPPER_BYTE (uint8_t *)34
 | 
			
		||||
// Size of EEPROM being used, other code can refer to this for available EEPROM
 | 
			
		||||
#define EECONFIG_SIZE 35
 | 
			
		||||
/* debug bit */
 | 
			
		||||
#define EECONFIG_DEBUG_ENABLE (1 << 0)
 | 
			
		||||
#define EECONFIG_DEBUG_MATRIX (1 << 1)
 | 
			
		||||
#define EECONFIG_DEBUG_KEYBOARD (1 << 2)
 | 
			
		||||
#define EECONFIG_DEBUG_MOUSE (1 << 3)
 | 
			
		||||
 | 
			
		||||
/* keyconf bit */
 | 
			
		||||
#define EECONFIG_KEYMAP_SWAP_CONTROL_CAPSLOCK (1 << 0)
 | 
			
		||||
#define EECONFIG_KEYMAP_CAPSLOCK_TO_CONTROL (1 << 1)
 | 
			
		||||
#define EECONFIG_KEYMAP_SWAP_LALT_LGUI (1 << 2)
 | 
			
		||||
#define EECONFIG_KEYMAP_SWAP_RALT_RGUI (1 << 3)
 | 
			
		||||
#define EECONFIG_KEYMAP_NO_GUI (1 << 4)
 | 
			
		||||
#define EECONFIG_KEYMAP_SWAP_GRAVE_ESC (1 << 5)
 | 
			
		||||
#define EECONFIG_KEYMAP_SWAP_BACKSLASH_BACKSPACE (1 << 6)
 | 
			
		||||
#define EECONFIG_KEYMAP_NKRO (1 << 7)
 | 
			
		||||
 | 
			
		||||
#define EECONFIG_KEYMAP_LOWER_BYTE EECONFIG_KEYMAP
 | 
			
		||||
 | 
			
		||||
bool eeconfig_is_enabled(void);
 | 
			
		||||
bool eeconfig_is_disabled(void);
 | 
			
		||||
 | 
			
		||||
void eeconfig_init(void);
 | 
			
		||||
void eeconfig_init_quantum(void);
 | 
			
		||||
void eeconfig_init_kb(void);
 | 
			
		||||
void eeconfig_init_user(void);
 | 
			
		||||
 | 
			
		||||
void eeconfig_enable(void);
 | 
			
		||||
 | 
			
		||||
void eeconfig_disable(void);
 | 
			
		||||
 | 
			
		||||
uint8_t eeconfig_read_debug(void);
 | 
			
		||||
void    eeconfig_update_debug(uint8_t val);
 | 
			
		||||
 | 
			
		||||
uint8_t eeconfig_read_default_layer(void);
 | 
			
		||||
void    eeconfig_update_default_layer(uint8_t val);
 | 
			
		||||
 | 
			
		||||
uint16_t eeconfig_read_keymap(void);
 | 
			
		||||
void     eeconfig_update_keymap(uint16_t val);
 | 
			
		||||
 | 
			
		||||
#ifdef AUDIO_ENABLE
 | 
			
		||||
uint8_t eeconfig_read_audio(void);
 | 
			
		||||
void    eeconfig_update_audio(uint8_t val);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
uint32_t eeconfig_read_kb(void);
 | 
			
		||||
void     eeconfig_update_kb(uint32_t val);
 | 
			
		||||
uint32_t eeconfig_read_user(void);
 | 
			
		||||
void     eeconfig_update_user(uint32_t val);
 | 
			
		||||
 | 
			
		||||
#ifdef HAPTIC_ENABLE
 | 
			
		||||
uint32_t eeconfig_read_haptic(void);
 | 
			
		||||
void     eeconfig_update_haptic(uint32_t val);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
bool eeconfig_read_handedness(void);
 | 
			
		||||
void eeconfig_update_handedness(bool val);
 | 
			
		||||
| 
						 | 
				
			
			@ -1,565 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
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
 | 
			
		||||
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 <stdint.h>
 | 
			
		||||
#include "keyboard.h"
 | 
			
		||||
#include "matrix.h"
 | 
			
		||||
#include "keymap.h"
 | 
			
		||||
#include "host.h"
 | 
			
		||||
#include "led.h"
 | 
			
		||||
#include "keycode.h"
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
#include "sync_timer.h"
 | 
			
		||||
#include "print.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#include "command.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#include "sendchar.h"
 | 
			
		||||
#include "eeconfig.h"
 | 
			
		||||
#include "action_layer.h"
 | 
			
		||||
#ifdef BACKLIGHT_ENABLE
 | 
			
		||||
#    include "backlight.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
#    include "mousekey.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef PS2_MOUSE_ENABLE
 | 
			
		||||
#    include "ps2_mouse.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef SERIAL_MOUSE_ENABLE
 | 
			
		||||
#    include "serial_mouse.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef ADB_MOUSE_ENABLE
 | 
			
		||||
#    include "adb.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef RGBLIGHT_ENABLE
 | 
			
		||||
#    include "rgblight.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
#    include "led_matrix.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef RGB_MATRIX_ENABLE
 | 
			
		||||
#    include "rgb_matrix.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef ENCODER_ENABLE
 | 
			
		||||
#    include "encoder.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef STENO_ENABLE
 | 
			
		||||
#    include "process_steno.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef SERIAL_LINK_ENABLE
 | 
			
		||||
#    include "serial_link/system/serial_link.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef VISUALIZER_ENABLE
 | 
			
		||||
#    include "visualizer/visualizer.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef POINTING_DEVICE_ENABLE
 | 
			
		||||
#    include "pointing_device.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef MIDI_ENABLE
 | 
			
		||||
#    include "process_midi.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef JOYSTICK_ENABLE
 | 
			
		||||
#    include "process_joystick.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef HD44780_ENABLE
 | 
			
		||||
#    include "hd44780.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef QWIIC_ENABLE
 | 
			
		||||
#    include "qwiic.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef OLED_DRIVER_ENABLE
 | 
			
		||||
#    include "oled_driver.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef ST7565_ENABLE
 | 
			
		||||
#    include "st7565.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef VELOCIKEY_ENABLE
 | 
			
		||||
#    include "velocikey.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef VIA_ENABLE
 | 
			
		||||
#    include "via.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef DIP_SWITCH_ENABLE
 | 
			
		||||
#    include "dip_switch.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef STM32_EEPROM_ENABLE
 | 
			
		||||
#    include "eeprom_stm32.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef EEPROM_DRIVER
 | 
			
		||||
#    include "eeprom_driver.h"
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(CRC_ENABLE)
 | 
			
		||||
#    include "crc.h"
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef DIGITIZER_ENABLE
 | 
			
		||||
#    include "digitizer.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static uint32_t last_input_modification_time = 0;
 | 
			
		||||
uint32_t        last_input_activity_time(void) { return last_input_modification_time; }
 | 
			
		||||
uint32_t        last_input_activity_elapsed(void) { return timer_elapsed32(last_input_modification_time); }
 | 
			
		||||
 | 
			
		||||
static uint32_t last_matrix_modification_time = 0;
 | 
			
		||||
uint32_t        last_matrix_activity_time(void) { return last_matrix_modification_time; }
 | 
			
		||||
uint32_t        last_matrix_activity_elapsed(void) { return timer_elapsed32(last_matrix_modification_time); }
 | 
			
		||||
void            last_matrix_activity_trigger(void) { last_matrix_modification_time = last_input_modification_time = timer_read32(); }
 | 
			
		||||
 | 
			
		||||
static uint32_t last_encoder_modification_time = 0;
 | 
			
		||||
uint32_t        last_encoder_activity_time(void) { return last_encoder_modification_time; }
 | 
			
		||||
uint32_t        last_encoder_activity_elapsed(void) { return timer_elapsed32(last_encoder_modification_time); }
 | 
			
		||||
void            last_encoder_activity_trigger(void) { last_encoder_modification_time = last_input_modification_time = timer_read32(); }
 | 
			
		||||
 | 
			
		||||
// Only enable this if console is enabled to print to
 | 
			
		||||
#if defined(DEBUG_MATRIX_SCAN_RATE)
 | 
			
		||||
static uint32_t matrix_timer           = 0;
 | 
			
		||||
static uint32_t matrix_scan_count      = 0;
 | 
			
		||||
static uint32_t last_matrix_scan_count = 0;
 | 
			
		||||
 | 
			
		||||
void matrix_scan_perf_task(void) {
 | 
			
		||||
    matrix_scan_count++;
 | 
			
		||||
 | 
			
		||||
    uint32_t timer_now = timer_read32();
 | 
			
		||||
    if (TIMER_DIFF_32(timer_now, matrix_timer) > 1000) {
 | 
			
		||||
#    if defined(CONSOLE_ENABLE)
 | 
			
		||||
        dprintf("matrix scan frequency: %lu\n", matrix_scan_count);
 | 
			
		||||
#    endif
 | 
			
		||||
        last_matrix_scan_count = matrix_scan_count;
 | 
			
		||||
        matrix_timer           = timer_now;
 | 
			
		||||
        matrix_scan_count      = 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t get_matrix_scan_rate(void) { return last_matrix_scan_count; }
 | 
			
		||||
#else
 | 
			
		||||
#    define matrix_scan_perf_task()
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef MATRIX_HAS_GHOST
 | 
			
		||||
extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
 | 
			
		||||
static matrix_row_t   get_real_keys(uint8_t row, matrix_row_t rowdata) {
 | 
			
		||||
    matrix_row_t out = 0;
 | 
			
		||||
    for (uint8_t col = 0; col < MATRIX_COLS; col++) {
 | 
			
		||||
        // read each key in the row data and check if the keymap defines it as a real key
 | 
			
		||||
        if (pgm_read_byte(&keymaps[0][row][col]) && (rowdata & (1 << col))) {
 | 
			
		||||
            // this creates new row data, if a key is defined in the keymap, it will be set here
 | 
			
		||||
            out |= 1 << col;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline bool popcount_more_than_one(matrix_row_t rowdata) {
 | 
			
		||||
    rowdata &= rowdata - 1;  // if there are less than two bits (keys) set, rowdata will become zero
 | 
			
		||||
    return rowdata;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline bool has_ghost_in_row(uint8_t row, matrix_row_t rowdata) {
 | 
			
		||||
    /* No ghost exists when less than 2 keys are down on the row.
 | 
			
		||||
    If there are "active" blanks in the matrix, the key can't be pressed by the user,
 | 
			
		||||
    there is no doubt as to which keys are really being pressed.
 | 
			
		||||
    The ghosts will be ignored, they are KC_NO.   */
 | 
			
		||||
    rowdata = get_real_keys(row, rowdata);
 | 
			
		||||
    if ((popcount_more_than_one(rowdata)) == 0) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    /* Ghost occurs when the row shares a column line with other row,
 | 
			
		||||
    and two columns are read on each row. Blanks in the matrix don't matter,
 | 
			
		||||
    so they are filtered out.
 | 
			
		||||
    If there are two or more real keys pressed and they match columns with
 | 
			
		||||
    at least two of another row's real keys, the row will be ignored. Keep in mind,
 | 
			
		||||
    we are checking one row at a time, not all of them at once.
 | 
			
		||||
    */
 | 
			
		||||
    for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
 | 
			
		||||
        if (i != row && popcount_more_than_one(get_real_keys(i, matrix_get_row(i)) & rowdata)) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void disable_jtag(void) {
 | 
			
		||||
// To use PF4-7 (PC2-5 on ATmega32A), disable JTAG by writing JTD bit twice within four cycles.
 | 
			
		||||
#if (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
 | 
			
		||||
    MCUCR |= _BV(JTD);
 | 
			
		||||
    MCUCR |= _BV(JTD);
 | 
			
		||||
#elif defined(__AVR_ATmega32A__)
 | 
			
		||||
    MCUCSR |= _BV(JTD);
 | 
			
		||||
    MCUCSR |= _BV(JTD);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief matrix_setup
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) void matrix_setup(void) {}
 | 
			
		||||
 | 
			
		||||
/** \brief keyboard_pre_init_user
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) void keyboard_pre_init_user(void) {}
 | 
			
		||||
 | 
			
		||||
/** \brief keyboard_pre_init_kb
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) void keyboard_pre_init_kb(void) { keyboard_pre_init_user(); }
 | 
			
		||||
 | 
			
		||||
/** \brief keyboard_post_init_user
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
__attribute__((weak)) void keyboard_post_init_user() {}
 | 
			
		||||
 | 
			
		||||
/** \brief keyboard_post_init_kb
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
__attribute__((weak)) void keyboard_post_init_kb(void) { keyboard_post_init_user(); }
 | 
			
		||||
 | 
			
		||||
/** \brief keyboard_setup
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void keyboard_setup(void) {
 | 
			
		||||
#ifndef NO_JTAG_DISABLE
 | 
			
		||||
    disable_jtag();
 | 
			
		||||
#endif
 | 
			
		||||
    print_set_sendchar(sendchar);
 | 
			
		||||
#ifdef STM32_EEPROM_ENABLE
 | 
			
		||||
    EEPROM_Init();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef EEPROM_DRIVER
 | 
			
		||||
    eeprom_driver_init();
 | 
			
		||||
#endif
 | 
			
		||||
    matrix_setup();
 | 
			
		||||
    keyboard_pre_init_kb();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief is_keyboard_master
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) bool is_keyboard_master(void) { return true; }
 | 
			
		||||
 | 
			
		||||
/** \brief is_keyboard_left
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) bool is_keyboard_left(void) { return true; }
 | 
			
		||||
 | 
			
		||||
/** \brief should_process_keypress
 | 
			
		||||
 *
 | 
			
		||||
 * Override this function if you have a condition where keypresses processing should change:
 | 
			
		||||
 *   - splits where the slave side needs to process for rgb/oled functionality
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) bool should_process_keypress(void) { return is_keyboard_master(); }
 | 
			
		||||
 | 
			
		||||
/** \brief housekeeping_task_kb
 | 
			
		||||
 *
 | 
			
		||||
 * Override this function if you have a need to execute code for every keyboard main loop iteration.
 | 
			
		||||
 * This is specific to keyboard-level functionality.
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) void housekeeping_task_kb(void) {}
 | 
			
		||||
 | 
			
		||||
/** \brief housekeeping_task_user
 | 
			
		||||
 *
 | 
			
		||||
 * Override this function if you have a need to execute code for every keyboard main loop iteration.
 | 
			
		||||
 * This is specific to user/keymap-level functionality.
 | 
			
		||||
 */
 | 
			
		||||
__attribute__((weak)) void housekeeping_task_user(void) {}
 | 
			
		||||
 | 
			
		||||
/** \brief housekeeping_task
 | 
			
		||||
 *
 | 
			
		||||
 * Invokes hooks for executing code after QMK is done after each loop iteration.
 | 
			
		||||
 */
 | 
			
		||||
void housekeeping_task(void) {
 | 
			
		||||
    housekeeping_task_kb();
 | 
			
		||||
    housekeeping_task_user();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief keyboard_init
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void keyboard_init(void) {
 | 
			
		||||
    timer_init();
 | 
			
		||||
    sync_timer_init();
 | 
			
		||||
    matrix_init();
 | 
			
		||||
#if defined(CRC_ENABLE)
 | 
			
		||||
    crc_init();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef VIA_ENABLE
 | 
			
		||||
    via_init();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef QWIIC_ENABLE
 | 
			
		||||
    qwiic_init();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef OLED_DRIVER_ENABLE
 | 
			
		||||
    oled_init(OLED_ROTATION_0);
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef ST7565_ENABLE
 | 
			
		||||
    st7565_init(DISPLAY_ROTATION_0);
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef PS2_MOUSE_ENABLE
 | 
			
		||||
    ps2_mouse_init();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef SERIAL_MOUSE_ENABLE
 | 
			
		||||
    serial_mouse_init();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef ADB_MOUSE_ENABLE
 | 
			
		||||
    adb_mouse_init();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef BACKLIGHT_ENABLE
 | 
			
		||||
    backlight_init();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef RGBLIGHT_ENABLE
 | 
			
		||||
    rgblight_init();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef ENCODER_ENABLE
 | 
			
		||||
    encoder_init();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef STENO_ENABLE
 | 
			
		||||
    steno_init();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef POINTING_DEVICE_ENABLE
 | 
			
		||||
    pointing_device_init();
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(NKRO_ENABLE) && defined(FORCE_NKRO)
 | 
			
		||||
    keymap_config.nkro = 1;
 | 
			
		||||
    eeconfig_update_keymap(keymap_config.raw);
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef DIP_SWITCH_ENABLE
 | 
			
		||||
    dip_switch_init();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(DEBUG_MATRIX_SCAN_RATE) && defined(CONSOLE_ENABLE)
 | 
			
		||||
    debug_enable = true;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    keyboard_post_init_kb(); /* Always keep this last */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief key_event_task
 | 
			
		||||
 *
 | 
			
		||||
 * This function is responsible for calling into other systems when they need to respond to electrical switch press events.
 | 
			
		||||
 * This is differnet than keycode events as no layer processing, or filtering occurs.
 | 
			
		||||
 */
 | 
			
		||||
void switch_events(uint8_t row, uint8_t col, bool pressed) {
 | 
			
		||||
#if defined(LED_MATRIX_ENABLE)
 | 
			
		||||
    process_led_matrix(row, col, pressed);
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(RGB_MATRIX_ENABLE)
 | 
			
		||||
    process_rgb_matrix(row, col, pressed);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Keyboard task: Do keyboard routine jobs
 | 
			
		||||
 *
 | 
			
		||||
 * Do routine keyboard jobs:
 | 
			
		||||
 *
 | 
			
		||||
 * * scan matrix
 | 
			
		||||
 * * handle mouse movements
 | 
			
		||||
 * * run visualizer code
 | 
			
		||||
 * * handle midi commands
 | 
			
		||||
 * * light LEDs
 | 
			
		||||
 *
 | 
			
		||||
 * This is repeatedly called as fast as possible.
 | 
			
		||||
 */
 | 
			
		||||
void keyboard_task(void) {
 | 
			
		||||
    static matrix_row_t matrix_prev[MATRIX_ROWS];
 | 
			
		||||
    static uint8_t      led_status    = 0;
 | 
			
		||||
    matrix_row_t        matrix_row    = 0;
 | 
			
		||||
    matrix_row_t        matrix_change = 0;
 | 
			
		||||
#ifdef QMK_KEYS_PER_SCAN
 | 
			
		||||
    uint8_t keys_processed = 0;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef ENCODER_ENABLE
 | 
			
		||||
    bool encoders_changed = false;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    uint8_t matrix_changed = matrix_scan();
 | 
			
		||||
    if (matrix_changed) last_matrix_activity_trigger();
 | 
			
		||||
 | 
			
		||||
    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) {
 | 
			
		||||
#ifdef MATRIX_HAS_GHOST
 | 
			
		||||
            if (has_ghost_in_row(r, matrix_row)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
            if (debug_matrix) matrix_print();
 | 
			
		||||
            matrix_row_t col_mask = 1;
 | 
			
		||||
            for (uint8_t c = 0; c < MATRIX_COLS; c++, col_mask <<= 1) {
 | 
			
		||||
                if (matrix_change & col_mask) {
 | 
			
		||||
                    if (should_process_keypress()) {
 | 
			
		||||
                        action_exec((keyevent_t){
 | 
			
		||||
                            .key = (keypos_t){.row = r, .col = c}, .pressed = (matrix_row & col_mask), .time = (timer_read() | 1) /* time should not be 0 */
 | 
			
		||||
                        });
 | 
			
		||||
                    }
 | 
			
		||||
                    // record a processed key
 | 
			
		||||
                    matrix_prev[r] ^= col_mask;
 | 
			
		||||
 | 
			
		||||
                    switch_events(r, c, (matrix_row & col_mask));
 | 
			
		||||
 | 
			
		||||
#ifdef QMK_KEYS_PER_SCAN
 | 
			
		||||
                    // only jump out if we have processed "enough" keys.
 | 
			
		||||
                    if (++keys_processed >= QMK_KEYS_PER_SCAN)
 | 
			
		||||
#endif
 | 
			
		||||
                        // process a key per task call
 | 
			
		||||
                        goto MATRIX_LOOP_END;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // call with pseudo tick event when no real key event.
 | 
			
		||||
#ifdef QMK_KEYS_PER_SCAN
 | 
			
		||||
    // we can get here with some keys processed now.
 | 
			
		||||
    if (!keys_processed)
 | 
			
		||||
#endif
 | 
			
		||||
        action_exec(TICK);
 | 
			
		||||
 | 
			
		||||
MATRIX_LOOP_END:
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_MATRIX_SCAN_RATE
 | 
			
		||||
    matrix_scan_perf_task();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(RGBLIGHT_ENABLE)
 | 
			
		||||
    rgblight_task();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef LED_MATRIX_ENABLE
 | 
			
		||||
    led_matrix_task();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef RGB_MATRIX_ENABLE
 | 
			
		||||
    rgb_matrix_task();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(BACKLIGHT_ENABLE)
 | 
			
		||||
#    if defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS)
 | 
			
		||||
    backlight_task();
 | 
			
		||||
#    endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ENCODER_ENABLE
 | 
			
		||||
    encoders_changed = encoder_read();
 | 
			
		||||
    if (encoders_changed) last_encoder_activity_trigger();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef QWIIC_ENABLE
 | 
			
		||||
    qwiic_task();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef OLED_DRIVER_ENABLE
 | 
			
		||||
    oled_task();
 | 
			
		||||
#    ifndef OLED_DISABLE_TIMEOUT
 | 
			
		||||
    // Wake up oled if user is using those fabulous keys or spinning those encoders!
 | 
			
		||||
#        ifdef ENCODER_ENABLE
 | 
			
		||||
    if (matrix_changed || encoders_changed) oled_on();
 | 
			
		||||
#        else
 | 
			
		||||
    if (matrix_changed) oled_on();
 | 
			
		||||
#        endif
 | 
			
		||||
#    endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ST7565_ENABLE
 | 
			
		||||
    st7565_task();
 | 
			
		||||
#    ifndef ST7565_DISABLE_TIMEOUT
 | 
			
		||||
    // Wake up display if user is using those fabulous keys or spinning those encoders!
 | 
			
		||||
#        ifdef ENCODER_ENABLE
 | 
			
		||||
    if (matrix_changed || encoders_changed) st7565_on();
 | 
			
		||||
#        else
 | 
			
		||||
    if (matrix_changed) st7565_on();
 | 
			
		||||
#        endif
 | 
			
		||||
#    endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef MOUSEKEY_ENABLE
 | 
			
		||||
    // mousekey repeat & acceleration
 | 
			
		||||
    mousekey_task();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef PS2_MOUSE_ENABLE
 | 
			
		||||
    ps2_mouse_task();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef SERIAL_MOUSE_ENABLE
 | 
			
		||||
    serial_mouse_task();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef ADB_MOUSE_ENABLE
 | 
			
		||||
    adb_mouse_task();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef SERIAL_LINK_ENABLE
 | 
			
		||||
    serial_link_update();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef VISUALIZER_ENABLE
 | 
			
		||||
    visualizer_update(default_layer_state, layer_state, visualizer_get_mods(), host_keyboard_leds());
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef POINTING_DEVICE_ENABLE
 | 
			
		||||
    pointing_device_task();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef MIDI_ENABLE
 | 
			
		||||
    midi_task();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef VELOCIKEY_ENABLE
 | 
			
		||||
    if (velocikey_enabled()) {
 | 
			
		||||
        velocikey_decelerate();
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef JOYSTICK_ENABLE
 | 
			
		||||
    joystick_task();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef DIGITIZER_ENABLE
 | 
			
		||||
    digitizer_task();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // update LED
 | 
			
		||||
    if (led_status != host_keyboard_leds()) {
 | 
			
		||||
        led_status = host_keyboard_leds();
 | 
			
		||||
        keyboard_set_leds(led_status);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief keyboard set leds
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: needs doc
 | 
			
		||||
 */
 | 
			
		||||
void keyboard_set_leds(uint8_t leds) {
 | 
			
		||||
    if (debug_keyboard) {
 | 
			
		||||
        debug("keyboard_set_led: ");
 | 
			
		||||
        debug_hex8(leds);
 | 
			
		||||
        debug("\n");
 | 
			
		||||
    }
 | 
			
		||||
    led_set(leds);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,90 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
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
 | 
			
		||||
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/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* key matrix position */
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t col;
 | 
			
		||||
    uint8_t row;
 | 
			
		||||
} keypos_t;
 | 
			
		||||
 | 
			
		||||
/* key event */
 | 
			
		||||
typedef struct {
 | 
			
		||||
    keypos_t key;
 | 
			
		||||
    bool     pressed;
 | 
			
		||||
    uint16_t time;
 | 
			
		||||
} keyevent_t;
 | 
			
		||||
 | 
			
		||||
/* equivalent test of keypos_t */
 | 
			
		||||
#define KEYEQ(keya, keyb) ((keya).row == (keyb).row && (keya).col == (keyb).col)
 | 
			
		||||
 | 
			
		||||
/* Rules for No Event:
 | 
			
		||||
 * 1) (time == 0) to handle (keyevent_t){} as empty event
 | 
			
		||||
 * 2) Matrix(255, 255) to make TICK event available
 | 
			
		||||
 */
 | 
			
		||||
static inline bool IS_NOEVENT(keyevent_t event) { return event.time == 0 || (event.key.row == 255 && event.key.col == 255); }
 | 
			
		||||
static inline bool IS_PRESSED(keyevent_t event) { return (!IS_NOEVENT(event) && event.pressed); }
 | 
			
		||||
static inline bool IS_RELEASED(keyevent_t event) { return (!IS_NOEVENT(event) && !event.pressed); }
 | 
			
		||||
 | 
			
		||||
/* Tick event */
 | 
			
		||||
#define TICK \
 | 
			
		||||
    (keyevent_t) { .key = (keypos_t){.row = 255, .col = 255}, .pressed = false, .time = (timer_read() | 1) }
 | 
			
		||||
 | 
			
		||||
/* it runs once at early stage of startup before keyboard_init. */
 | 
			
		||||
void keyboard_setup(void);
 | 
			
		||||
/* it runs once after initializing host side protocol, debug and MCU peripherals. */
 | 
			
		||||
void keyboard_init(void);
 | 
			
		||||
/* it runs repeatedly in main loop */
 | 
			
		||||
void keyboard_task(void);
 | 
			
		||||
/* it runs when host LED status is updated */
 | 
			
		||||
void keyboard_set_leds(uint8_t leds);
 | 
			
		||||
/* it runs whenever code has to behave differently on a slave */
 | 
			
		||||
bool is_keyboard_master(void);
 | 
			
		||||
/* it runs whenever code has to behave differently on left vs right split */
 | 
			
		||||
bool is_keyboard_left(void);
 | 
			
		||||
 | 
			
		||||
void keyboard_pre_init_kb(void);
 | 
			
		||||
void keyboard_pre_init_user(void);
 | 
			
		||||
void keyboard_post_init_kb(void);
 | 
			
		||||
void keyboard_post_init_user(void);
 | 
			
		||||
 | 
			
		||||
void housekeeping_task(void);       // To be executed by the main loop in each backend TMK protocol
 | 
			
		||||
void housekeeping_task_kb(void);    // To be overridden by keyboard-level code
 | 
			
		||||
void housekeeping_task_user(void);  // To be overridden by user/keymap-level code
 | 
			
		||||
 | 
			
		||||
uint32_t last_input_activity_time(void);     // Timestamp of the last matrix or encoder activity
 | 
			
		||||
uint32_t last_input_activity_elapsed(void);  // Number of milliseconds since the last matrix or encoder activity
 | 
			
		||||
 | 
			
		||||
uint32_t last_matrix_activity_time(void);     // Timestamp of the last matrix activity
 | 
			
		||||
uint32_t last_matrix_activity_elapsed(void);  // Number of milliseconds since the last matrix activity
 | 
			
		||||
 | 
			
		||||
uint32_t last_encoder_activity_time(void);     // Timestamp of the last encoder activity
 | 
			
		||||
uint32_t last_encoder_activity_elapsed(void);  // Number of milliseconds since the last encoder activity
 | 
			
		||||
 | 
			
		||||
uint32_t get_matrix_scan_rate(void);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,560 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
Copyright 2011,2012 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/>.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Keycodes based on HID Keyboard/Keypad Usage Page (0x07) plus media keys from Generic Desktop Page (0x01) and Consumer Page (0x0C)
 | 
			
		||||
 *
 | 
			
		||||
 * See https://web.archive.org/web/20060218214400/http://www.usb.org/developers/devclass_docs/Hut1_12.pdf
 | 
			
		||||
 * or http://www.usb.org/developers/hidpage/Hut1_12v2.pdf (older)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
/* FIXME: Add doxygen comments here */
 | 
			
		||||
 | 
			
		||||
#define IS_ERROR(code) (KC_ROLL_OVER <= (code) && (code) <= KC_UNDEFINED)
 | 
			
		||||
#define IS_ANY(code) (KC_A <= (code) && (code) <= 0xFF)
 | 
			
		||||
#define IS_KEY(code) (KC_A <= (code) && (code) <= KC_EXSEL)
 | 
			
		||||
#define IS_MOD(code) (KC_LCTRL <= (code) && (code) <= KC_RGUI)
 | 
			
		||||
 | 
			
		||||
#define IS_SPECIAL(code) ((0xA5 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF))
 | 
			
		||||
#define IS_SYSTEM(code) (KC_PWR <= (code) && (code) <= KC_WAKE)
 | 
			
		||||
#define IS_CONSUMER(code) (KC_MUTE <= (code) && (code) <= KC_BRID)
 | 
			
		||||
 | 
			
		||||
#define IS_FN(code) (KC_FN0 <= (code) && (code) <= KC_FN31)
 | 
			
		||||
 | 
			
		||||
#define IS_MOUSEKEY(code) (KC_MS_UP <= (code) && (code) <= KC_MS_ACCEL2)
 | 
			
		||||
#define IS_MOUSEKEY_MOVE(code) (KC_MS_UP <= (code) && (code) <= KC_MS_RIGHT)
 | 
			
		||||
#define IS_MOUSEKEY_BUTTON(code) (KC_MS_BTN1 <= (code) && (code) <= KC_MS_BTN8)
 | 
			
		||||
#define IS_MOUSEKEY_WHEEL(code) (KC_MS_WH_UP <= (code) && (code) <= KC_MS_WH_RIGHT)
 | 
			
		||||
#define IS_MOUSEKEY_ACCEL(code) (KC_MS_ACCEL0 <= (code) && (code) <= KC_MS_ACCEL2)
 | 
			
		||||
 | 
			
		||||
#define MOD_BIT(code) (1 << MOD_INDEX(code))
 | 
			
		||||
#define MOD_INDEX(code) ((code)&0x07)
 | 
			
		||||
 | 
			
		||||
#define MOD_MASK_CTRL (MOD_BIT(KC_LCTRL) | MOD_BIT(KC_RCTRL))
 | 
			
		||||
#define MOD_MASK_SHIFT (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))
 | 
			
		||||
#define MOD_MASK_ALT (MOD_BIT(KC_LALT) | MOD_BIT(KC_RALT))
 | 
			
		||||
#define MOD_MASK_GUI (MOD_BIT(KC_LGUI) | MOD_BIT(KC_RGUI))
 | 
			
		||||
#define MOD_MASK_CS (MOD_MASK_CTRL | MOD_MASK_SHIFT)
 | 
			
		||||
#define MOD_MASK_CA (MOD_MASK_CTRL | MOD_MASK_ALT)
 | 
			
		||||
#define MOD_MASK_CG (MOD_MASK_CTRL | MOD_MASK_GUI)
 | 
			
		||||
#define MOD_MASK_SA (MOD_MASK_SHIFT | MOD_MASK_ALT)
 | 
			
		||||
#define MOD_MASK_SG (MOD_MASK_SHIFT | MOD_MASK_GUI)
 | 
			
		||||
#define MOD_MASK_AG (MOD_MASK_ALT | MOD_MASK_GUI)
 | 
			
		||||
#define MOD_MASK_CSA (MOD_MASK_CTRL | MOD_MASK_SHIFT | MOD_MASK_ALT)
 | 
			
		||||
#define MOD_MASK_CSG (MOD_MASK_CTRL | MOD_MASK_SHIFT | MOD_MASK_GUI)
 | 
			
		||||
#define MOD_MASK_CAG (MOD_MASK_CTRL | MOD_MASK_ALT | MOD_MASK_GUI)
 | 
			
		||||
#define MOD_MASK_SAG (MOD_MASK_SHIFT | MOD_MASK_ALT | MOD_MASK_GUI)
 | 
			
		||||
#define MOD_MASK_CSAG (MOD_MASK_CTRL | MOD_MASK_SHIFT | MOD_MASK_ALT | MOD_MASK_GUI)
 | 
			
		||||
 | 
			
		||||
#define FN_BIT(code) (1 << FN_INDEX(code))
 | 
			
		||||
#define FN_INDEX(code) ((code)-KC_FN0)
 | 
			
		||||
#define FN_MIN KC_FN0
 | 
			
		||||
#define FN_MAX KC_FN31
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Short names for ease of definition of keymap
 | 
			
		||||
 */
 | 
			
		||||
/* Transparent */
 | 
			
		||||
#define KC_TRANSPARENT 0x01
 | 
			
		||||
#define KC_TRNS KC_TRANSPARENT
 | 
			
		||||
 | 
			
		||||
/* Punctuation */
 | 
			
		||||
#define KC_ENT KC_ENTER
 | 
			
		||||
#define KC_ESC KC_ESCAPE
 | 
			
		||||
#define KC_BSPC KC_BSPACE
 | 
			
		||||
#define KC_SPC KC_SPACE
 | 
			
		||||
#define KC_MINS KC_MINUS
 | 
			
		||||
#define KC_EQL KC_EQUAL
 | 
			
		||||
#define KC_LBRC KC_LBRACKET
 | 
			
		||||
#define KC_RBRC KC_RBRACKET
 | 
			
		||||
#define KC_BSLS KC_BSLASH
 | 
			
		||||
#define KC_NUHS KC_NONUS_HASH
 | 
			
		||||
#define KC_SCLN KC_SCOLON
 | 
			
		||||
#define KC_QUOT KC_QUOTE
 | 
			
		||||
#define KC_GRV KC_GRAVE
 | 
			
		||||
#define KC_COMM KC_COMMA
 | 
			
		||||
#define KC_SLSH KC_SLASH
 | 
			
		||||
#define KC_NUBS KC_NONUS_BSLASH
 | 
			
		||||
 | 
			
		||||
/* Lock Keys */
 | 
			
		||||
#define KC_CLCK KC_CAPSLOCK
 | 
			
		||||
#define KC_CAPS KC_CAPSLOCK
 | 
			
		||||
#define KC_SLCK KC_SCROLLLOCK
 | 
			
		||||
#define KC_NLCK KC_NUMLOCK
 | 
			
		||||
#define KC_LCAP KC_LOCKING_CAPS
 | 
			
		||||
#define KC_LNUM KC_LOCKING_NUM
 | 
			
		||||
#define KC_LSCR KC_LOCKING_SCROLL
 | 
			
		||||
 | 
			
		||||
/* Commands */
 | 
			
		||||
#define KC_PSCR KC_PSCREEN
 | 
			
		||||
#define KC_PAUS KC_PAUSE
 | 
			
		||||
#define KC_BRK KC_PAUSE
 | 
			
		||||
#define KC_INS KC_INSERT
 | 
			
		||||
#define KC_DEL KC_DELETE
 | 
			
		||||
#define KC_PGDN KC_PGDOWN
 | 
			
		||||
#define KC_RGHT KC_RIGHT
 | 
			
		||||
#define KC_APP KC_APPLICATION
 | 
			
		||||
#define KC_EXEC KC_EXECUTE
 | 
			
		||||
#define KC_SLCT KC_SELECT
 | 
			
		||||
#define KC_AGIN KC_AGAIN
 | 
			
		||||
#define KC_PSTE KC_PASTE
 | 
			
		||||
#define KC_ERAS KC_ALT_ERASE
 | 
			
		||||
#define KC_CLR KC_CLEAR
 | 
			
		||||
 | 
			
		||||
/* Keypad */
 | 
			
		||||
#define KC_PSLS KC_KP_SLASH
 | 
			
		||||
#define KC_PAST KC_KP_ASTERISK
 | 
			
		||||
#define KC_PMNS KC_KP_MINUS
 | 
			
		||||
#define KC_PPLS KC_KP_PLUS
 | 
			
		||||
#define KC_PENT KC_KP_ENTER
 | 
			
		||||
#define KC_P1 KC_KP_1
 | 
			
		||||
#define KC_P2 KC_KP_2
 | 
			
		||||
#define KC_P3 KC_KP_3
 | 
			
		||||
#define KC_P4 KC_KP_4
 | 
			
		||||
#define KC_P5 KC_KP_5
 | 
			
		||||
#define KC_P6 KC_KP_6
 | 
			
		||||
#define KC_P7 KC_KP_7
 | 
			
		||||
#define KC_P8 KC_KP_8
 | 
			
		||||
#define KC_P9 KC_KP_9
 | 
			
		||||
#define KC_P0 KC_KP_0
 | 
			
		||||
#define KC_PDOT KC_KP_DOT
 | 
			
		||||
#define KC_PEQL KC_KP_EQUAL
 | 
			
		||||
#define KC_PCMM KC_KP_COMMA
 | 
			
		||||
 | 
			
		||||
/* Japanese specific */
 | 
			
		||||
#define KC_ZKHK KC_GRAVE
 | 
			
		||||
#define KC_RO KC_INT1
 | 
			
		||||
#define KC_KANA KC_INT2
 | 
			
		||||
#define KC_JYEN KC_INT3
 | 
			
		||||
#define KC_HENK KC_INT4
 | 
			
		||||
#define KC_MHEN KC_INT5
 | 
			
		||||
 | 
			
		||||
/* Korean specific */
 | 
			
		||||
#define KC_HAEN KC_LANG1
 | 
			
		||||
#define KC_HANJ KC_LANG2
 | 
			
		||||
 | 
			
		||||
/* Modifiers */
 | 
			
		||||
#define KC_LCTL KC_LCTRL
 | 
			
		||||
#define KC_LSFT KC_LSHIFT
 | 
			
		||||
#define KC_LOPT KC_LALT
 | 
			
		||||
#define KC_LCMD KC_LGUI
 | 
			
		||||
#define KC_LWIN KC_LGUI
 | 
			
		||||
#define KC_RCTL KC_RCTRL
 | 
			
		||||
#define KC_RSFT KC_RSHIFT
 | 
			
		||||
#define KC_ALGR KC_RALT
 | 
			
		||||
#define KC_ROPT KC_RALT
 | 
			
		||||
#define KC_RCMD KC_RGUI
 | 
			
		||||
#define KC_RWIN KC_RGUI
 | 
			
		||||
 | 
			
		||||
/* Generic Desktop Page (0x01) */
 | 
			
		||||
#define KC_PWR KC_SYSTEM_POWER
 | 
			
		||||
#define KC_SLEP KC_SYSTEM_SLEEP
 | 
			
		||||
#define KC_WAKE KC_SYSTEM_WAKE
 | 
			
		||||
 | 
			
		||||
/* Consumer Page (0x0C) */
 | 
			
		||||
#define KC_MUTE KC_AUDIO_MUTE
 | 
			
		||||
#define KC_VOLU KC_AUDIO_VOL_UP
 | 
			
		||||
#define KC_VOLD KC_AUDIO_VOL_DOWN
 | 
			
		||||
#define KC_MNXT KC_MEDIA_NEXT_TRACK
 | 
			
		||||
#define KC_MPRV KC_MEDIA_PREV_TRACK
 | 
			
		||||
#define KC_MSTP KC_MEDIA_STOP
 | 
			
		||||
#define KC_MPLY KC_MEDIA_PLAY_PAUSE
 | 
			
		||||
#define KC_MSEL KC_MEDIA_SELECT
 | 
			
		||||
#define KC_EJCT KC_MEDIA_EJECT
 | 
			
		||||
#define KC_CALC KC_CALCULATOR
 | 
			
		||||
#define KC_MYCM KC_MY_COMPUTER
 | 
			
		||||
#define KC_WSCH KC_WWW_SEARCH
 | 
			
		||||
#define KC_WHOM KC_WWW_HOME
 | 
			
		||||
#define KC_WBAK KC_WWW_BACK
 | 
			
		||||
#define KC_WFWD KC_WWW_FORWARD
 | 
			
		||||
#define KC_WSTP KC_WWW_STOP
 | 
			
		||||
#define KC_WREF KC_WWW_REFRESH
 | 
			
		||||
#define KC_WFAV KC_WWW_FAVORITES
 | 
			
		||||
#define KC_MFFD KC_MEDIA_FAST_FORWARD
 | 
			
		||||
#define KC_MRWD KC_MEDIA_REWIND
 | 
			
		||||
#define KC_BRIU KC_BRIGHTNESS_UP
 | 
			
		||||
#define KC_BRID KC_BRIGHTNESS_DOWN
 | 
			
		||||
 | 
			
		||||
/* System Specific */
 | 
			
		||||
#define KC_BRMU KC_PAUSE
 | 
			
		||||
#define KC_BRMD KC_SCROLLLOCK
 | 
			
		||||
 | 
			
		||||
/* Mouse Keys */
 | 
			
		||||
#define KC_MS_U KC_MS_UP
 | 
			
		||||
#define KC_MS_D KC_MS_DOWN
 | 
			
		||||
#define KC_MS_L KC_MS_LEFT
 | 
			
		||||
#define KC_MS_R KC_MS_RIGHT
 | 
			
		||||
#define KC_BTN1 KC_MS_BTN1
 | 
			
		||||
#define KC_BTN2 KC_MS_BTN2
 | 
			
		||||
#define KC_BTN3 KC_MS_BTN3
 | 
			
		||||
#define KC_BTN4 KC_MS_BTN4
 | 
			
		||||
#define KC_BTN5 KC_MS_BTN5
 | 
			
		||||
#define KC_BTN6 KC_MS_BTN6
 | 
			
		||||
#define KC_BTN7 KC_MS_BTN7
 | 
			
		||||
#define KC_BTN8 KC_MS_BTN8
 | 
			
		||||
#define KC_WH_U KC_MS_WH_UP
 | 
			
		||||
#define KC_WH_D KC_MS_WH_DOWN
 | 
			
		||||
#define KC_WH_L KC_MS_WH_LEFT
 | 
			
		||||
#define KC_WH_R KC_MS_WH_RIGHT
 | 
			
		||||
#define KC_ACL0 KC_MS_ACCEL0
 | 
			
		||||
#define KC_ACL1 KC_MS_ACCEL1
 | 
			
		||||
#define KC_ACL2 KC_MS_ACCEL2
 | 
			
		||||
 | 
			
		||||
/* Keyboard/Keypad Page (0x07) */
 | 
			
		||||
enum hid_keyboard_keypad_usage {
 | 
			
		||||
    KC_NO = 0x00,
 | 
			
		||||
    KC_ROLL_OVER,
 | 
			
		||||
    KC_POST_FAIL,
 | 
			
		||||
    KC_UNDEFINED,
 | 
			
		||||
    KC_A,
 | 
			
		||||
    KC_B,
 | 
			
		||||
    KC_C,
 | 
			
		||||
    KC_D,
 | 
			
		||||
    KC_E,
 | 
			
		||||
    KC_F,
 | 
			
		||||
    KC_G,
 | 
			
		||||
    KC_H,
 | 
			
		||||
    KC_I,
 | 
			
		||||
    KC_J,
 | 
			
		||||
    KC_K,
 | 
			
		||||
    KC_L,
 | 
			
		||||
    KC_M,  // 0x10
 | 
			
		||||
    KC_N,
 | 
			
		||||
    KC_O,
 | 
			
		||||
    KC_P,
 | 
			
		||||
    KC_Q,
 | 
			
		||||
    KC_R,
 | 
			
		||||
    KC_S,
 | 
			
		||||
    KC_T,
 | 
			
		||||
    KC_U,
 | 
			
		||||
    KC_V,
 | 
			
		||||
    KC_W,
 | 
			
		||||
    KC_X,
 | 
			
		||||
    KC_Y,
 | 
			
		||||
    KC_Z,
 | 
			
		||||
    KC_1,
 | 
			
		||||
    KC_2,
 | 
			
		||||
    KC_3,  // 0x20
 | 
			
		||||
    KC_4,
 | 
			
		||||
    KC_5,
 | 
			
		||||
    KC_6,
 | 
			
		||||
    KC_7,
 | 
			
		||||
    KC_8,
 | 
			
		||||
    KC_9,
 | 
			
		||||
    KC_0,
 | 
			
		||||
    KC_ENTER,
 | 
			
		||||
    KC_ESCAPE,
 | 
			
		||||
    KC_BSPACE,
 | 
			
		||||
    KC_TAB,
 | 
			
		||||
    KC_SPACE,
 | 
			
		||||
    KC_MINUS,
 | 
			
		||||
    KC_EQUAL,
 | 
			
		||||
    KC_LBRACKET,
 | 
			
		||||
    KC_RBRACKET,  // 0x30
 | 
			
		||||
    KC_BSLASH,
 | 
			
		||||
    KC_NONUS_HASH,
 | 
			
		||||
    KC_SCOLON,
 | 
			
		||||
    KC_QUOTE,
 | 
			
		||||
    KC_GRAVE,
 | 
			
		||||
    KC_COMMA,
 | 
			
		||||
    KC_DOT,
 | 
			
		||||
    KC_SLASH,
 | 
			
		||||
    KC_CAPSLOCK,
 | 
			
		||||
    KC_F1,
 | 
			
		||||
    KC_F2,
 | 
			
		||||
    KC_F3,
 | 
			
		||||
    KC_F4,
 | 
			
		||||
    KC_F5,
 | 
			
		||||
    KC_F6,
 | 
			
		||||
    KC_F7,  // 0x40
 | 
			
		||||
    KC_F8,
 | 
			
		||||
    KC_F9,
 | 
			
		||||
    KC_F10,
 | 
			
		||||
    KC_F11,
 | 
			
		||||
    KC_F12,
 | 
			
		||||
    KC_PSCREEN,
 | 
			
		||||
    KC_SCROLLLOCK,
 | 
			
		||||
    KC_PAUSE,
 | 
			
		||||
    KC_INSERT,
 | 
			
		||||
    KC_HOME,
 | 
			
		||||
    KC_PGUP,
 | 
			
		||||
    KC_DELETE,
 | 
			
		||||
    KC_END,
 | 
			
		||||
    KC_PGDOWN,
 | 
			
		||||
    KC_RIGHT,
 | 
			
		||||
    KC_LEFT,  // 0x50
 | 
			
		||||
    KC_DOWN,
 | 
			
		||||
    KC_UP,
 | 
			
		||||
    KC_NUMLOCK,
 | 
			
		||||
    KC_KP_SLASH,
 | 
			
		||||
    KC_KP_ASTERISK,
 | 
			
		||||
    KC_KP_MINUS,
 | 
			
		||||
    KC_KP_PLUS,
 | 
			
		||||
    KC_KP_ENTER,
 | 
			
		||||
    KC_KP_1,
 | 
			
		||||
    KC_KP_2,
 | 
			
		||||
    KC_KP_3,
 | 
			
		||||
    KC_KP_4,
 | 
			
		||||
    KC_KP_5,
 | 
			
		||||
    KC_KP_6,
 | 
			
		||||
    KC_KP_7,
 | 
			
		||||
    KC_KP_8,  // 0x60
 | 
			
		||||
    KC_KP_9,
 | 
			
		||||
    KC_KP_0,
 | 
			
		||||
    KC_KP_DOT,
 | 
			
		||||
    KC_NONUS_BSLASH,
 | 
			
		||||
    KC_APPLICATION,
 | 
			
		||||
    KC_POWER,
 | 
			
		||||
    KC_KP_EQUAL,
 | 
			
		||||
    KC_F13,
 | 
			
		||||
    KC_F14,
 | 
			
		||||
    KC_F15,
 | 
			
		||||
    KC_F16,
 | 
			
		||||
    KC_F17,
 | 
			
		||||
    KC_F18,
 | 
			
		||||
    KC_F19,
 | 
			
		||||
    KC_F20,
 | 
			
		||||
    KC_F21,  // 0x70
 | 
			
		||||
    KC_F22,
 | 
			
		||||
    KC_F23,
 | 
			
		||||
    KC_F24,
 | 
			
		||||
    KC_EXECUTE,
 | 
			
		||||
    KC_HELP,
 | 
			
		||||
    KC_MENU,
 | 
			
		||||
    KC_SELECT,
 | 
			
		||||
    KC_STOP,
 | 
			
		||||
    KC_AGAIN,
 | 
			
		||||
    KC_UNDO,
 | 
			
		||||
    KC_CUT,
 | 
			
		||||
    KC_COPY,
 | 
			
		||||
    KC_PASTE,
 | 
			
		||||
    KC_FIND,
 | 
			
		||||
    KC__MUTE,
 | 
			
		||||
    KC__VOLUP,  // 0x80
 | 
			
		||||
    KC__VOLDOWN,
 | 
			
		||||
    KC_LOCKING_CAPS,
 | 
			
		||||
    KC_LOCKING_NUM,
 | 
			
		||||
    KC_LOCKING_SCROLL,
 | 
			
		||||
    KC_KP_COMMA,
 | 
			
		||||
    KC_KP_EQUAL_AS400,
 | 
			
		||||
    KC_INT1,
 | 
			
		||||
    KC_INT2,
 | 
			
		||||
    KC_INT3,
 | 
			
		||||
    KC_INT4,
 | 
			
		||||
    KC_INT5,
 | 
			
		||||
    KC_INT6,
 | 
			
		||||
    KC_INT7,
 | 
			
		||||
    KC_INT8,
 | 
			
		||||
    KC_INT9,
 | 
			
		||||
    KC_LANG1,  // 0x90
 | 
			
		||||
    KC_LANG2,
 | 
			
		||||
    KC_LANG3,
 | 
			
		||||
    KC_LANG4,
 | 
			
		||||
    KC_LANG5,
 | 
			
		||||
    KC_LANG6,
 | 
			
		||||
    KC_LANG7,
 | 
			
		||||
    KC_LANG8,
 | 
			
		||||
    KC_LANG9,
 | 
			
		||||
    KC_ALT_ERASE,
 | 
			
		||||
    KC_SYSREQ,
 | 
			
		||||
    KC_CANCEL,
 | 
			
		||||
    KC_CLEAR,
 | 
			
		||||
    KC_PRIOR,
 | 
			
		||||
    KC_RETURN,
 | 
			
		||||
    KC_SEPARATOR,
 | 
			
		||||
    KC_OUT,  // 0xA0
 | 
			
		||||
    KC_OPER,
 | 
			
		||||
    KC_CLEAR_AGAIN,
 | 
			
		||||
    KC_CRSEL,
 | 
			
		||||
    KC_EXSEL,
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
  // ***************************************************************
 | 
			
		||||
  // These keycodes are present in the HID spec, but are           *
 | 
			
		||||
  // nonfunctional on modern OSes. QMK uses this range (0xA5-0xDF) *
 | 
			
		||||
  // for the media and function keys instead - see below.          *
 | 
			
		||||
  // ***************************************************************
 | 
			
		||||
 | 
			
		||||
  KC_KP_00                = 0xB0,
 | 
			
		||||
  KC_KP_000,
 | 
			
		||||
  KC_THOUSANDS_SEPARATOR,
 | 
			
		||||
  KC_DECIMAL_SEPARATOR,
 | 
			
		||||
  KC_CURRENCY_UNIT,
 | 
			
		||||
  KC_CURRENCY_SUB_UNIT,
 | 
			
		||||
  KC_KP_LPAREN,
 | 
			
		||||
  KC_KP_RPAREN,
 | 
			
		||||
  KC_KP_LCBRACKET,
 | 
			
		||||
  KC_KP_RCBRACKET,
 | 
			
		||||
  KC_KP_TAB,
 | 
			
		||||
  KC_KP_BSPACE,
 | 
			
		||||
  KC_KP_A,
 | 
			
		||||
  KC_KP_B,
 | 
			
		||||
  KC_KP_C,
 | 
			
		||||
  KC_KP_D,
 | 
			
		||||
  KC_KP_E,                //0xC0
 | 
			
		||||
  KC_KP_F,
 | 
			
		||||
  KC_KP_XOR,
 | 
			
		||||
  KC_KP_HAT,
 | 
			
		||||
  KC_KP_PERC,
 | 
			
		||||
  KC_KP_LT,
 | 
			
		||||
  KC_KP_GT,
 | 
			
		||||
  KC_KP_AND,
 | 
			
		||||
  KC_KP_LAZYAND,
 | 
			
		||||
  KC_KP_OR,
 | 
			
		||||
  KC_KP_LAZYOR,
 | 
			
		||||
  KC_KP_COLON,
 | 
			
		||||
  KC_KP_HASH,
 | 
			
		||||
  KC_KP_SPACE,
 | 
			
		||||
  KC_KP_ATMARK,
 | 
			
		||||
  KC_KP_EXCLAMATION,
 | 
			
		||||
  KC_KP_MEM_STORE,        //0xD0
 | 
			
		||||
  KC_KP_MEM_RECALL,
 | 
			
		||||
  KC_KP_MEM_CLEAR,
 | 
			
		||||
  KC_KP_MEM_ADD,
 | 
			
		||||
  KC_KP_MEM_SUB,
 | 
			
		||||
  KC_KP_MEM_MUL,
 | 
			
		||||
  KC_KP_MEM_DIV,
 | 
			
		||||
  KC_KP_PLUS_MINUS,
 | 
			
		||||
  KC_KP_CLEAR,
 | 
			
		||||
  KC_KP_CLEAR_ENTRY,
 | 
			
		||||
  KC_KP_BINARY,
 | 
			
		||||
  KC_KP_OCTAL,
 | 
			
		||||
  KC_KP_DECIMAL,
 | 
			
		||||
  KC_KP_HEXADECIMAL,
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* Modifiers */
 | 
			
		||||
    KC_LCTRL = 0xE0,
 | 
			
		||||
    KC_LSHIFT,
 | 
			
		||||
    KC_LALT,
 | 
			
		||||
    KC_LGUI,
 | 
			
		||||
    KC_RCTRL,
 | 
			
		||||
    KC_RSHIFT,
 | 
			
		||||
    KC_RALT,
 | 
			
		||||
    KC_RGUI
 | 
			
		||||
 | 
			
		||||
    // **********************************************
 | 
			
		||||
    // * 0xF0-0xFF are unallocated in the HID spec. *
 | 
			
		||||
    // * QMK uses these for Mouse Keys - see below. *
 | 
			
		||||
    // **********************************************
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Media and Function keys */
 | 
			
		||||
enum internal_special_keycodes {
 | 
			
		||||
    /* Generic Desktop Page (0x01) */
 | 
			
		||||
    KC_SYSTEM_POWER = 0xA5,
 | 
			
		||||
    KC_SYSTEM_SLEEP,
 | 
			
		||||
    KC_SYSTEM_WAKE,
 | 
			
		||||
 | 
			
		||||
    /* Consumer Page (0x0C) */
 | 
			
		||||
    KC_AUDIO_MUTE,
 | 
			
		||||
    KC_AUDIO_VOL_UP,
 | 
			
		||||
    KC_AUDIO_VOL_DOWN,
 | 
			
		||||
    KC_MEDIA_NEXT_TRACK,
 | 
			
		||||
    KC_MEDIA_PREV_TRACK,
 | 
			
		||||
    KC_MEDIA_STOP,
 | 
			
		||||
    KC_MEDIA_PLAY_PAUSE,
 | 
			
		||||
    KC_MEDIA_SELECT,
 | 
			
		||||
    KC_MEDIA_EJECT,  // 0xB0
 | 
			
		||||
    KC_MAIL,
 | 
			
		||||
    KC_CALCULATOR,
 | 
			
		||||
    KC_MY_COMPUTER,
 | 
			
		||||
    KC_WWW_SEARCH,
 | 
			
		||||
    KC_WWW_HOME,
 | 
			
		||||
    KC_WWW_BACK,
 | 
			
		||||
    KC_WWW_FORWARD,
 | 
			
		||||
    KC_WWW_STOP,
 | 
			
		||||
    KC_WWW_REFRESH,
 | 
			
		||||
    KC_WWW_FAVORITES,
 | 
			
		||||
    KC_MEDIA_FAST_FORWARD,
 | 
			
		||||
    KC_MEDIA_REWIND,
 | 
			
		||||
    KC_BRIGHTNESS_UP,
 | 
			
		||||
    KC_BRIGHTNESS_DOWN,
 | 
			
		||||
 | 
			
		||||
    /* Fn keys */
 | 
			
		||||
    KC_FN0 = 0xC0,
 | 
			
		||||
    KC_FN1,
 | 
			
		||||
    KC_FN2,
 | 
			
		||||
    KC_FN3,
 | 
			
		||||
    KC_FN4,
 | 
			
		||||
    KC_FN5,
 | 
			
		||||
    KC_FN6,
 | 
			
		||||
    KC_FN7,
 | 
			
		||||
    KC_FN8,
 | 
			
		||||
    KC_FN9,
 | 
			
		||||
    KC_FN10,
 | 
			
		||||
    KC_FN11,
 | 
			
		||||
    KC_FN12,
 | 
			
		||||
    KC_FN13,
 | 
			
		||||
    KC_FN14,
 | 
			
		||||
    KC_FN15,
 | 
			
		||||
    KC_FN16,  // 0xD0
 | 
			
		||||
    KC_FN17,
 | 
			
		||||
    KC_FN18,
 | 
			
		||||
    KC_FN19,
 | 
			
		||||
    KC_FN20,
 | 
			
		||||
    KC_FN21,
 | 
			
		||||
    KC_FN22,
 | 
			
		||||
    KC_FN23,
 | 
			
		||||
    KC_FN24,
 | 
			
		||||
    KC_FN25,
 | 
			
		||||
    KC_FN26,
 | 
			
		||||
    KC_FN27,
 | 
			
		||||
    KC_FN28,
 | 
			
		||||
    KC_FN29,
 | 
			
		||||
    KC_FN30,
 | 
			
		||||
    KC_FN31
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum mouse_keys {
 | 
			
		||||
/* Mouse Buttons */
 | 
			
		||||
#ifdef VIA_ENABLE
 | 
			
		||||
    KC_MS_UP = 0xF0,
 | 
			
		||||
#else
 | 
			
		||||
    KC_MS_UP = 0xED,
 | 
			
		||||
#endif
 | 
			
		||||
    KC_MS_DOWN,
 | 
			
		||||
    KC_MS_LEFT,
 | 
			
		||||
    KC_MS_RIGHT,  // 0xF0
 | 
			
		||||
    KC_MS_BTN1,
 | 
			
		||||
    KC_MS_BTN2,
 | 
			
		||||
    KC_MS_BTN3,
 | 
			
		||||
    KC_MS_BTN4,
 | 
			
		||||
    KC_MS_BTN5,
 | 
			
		||||
#ifdef VIA_ENABLE
 | 
			
		||||
    KC_MS_BTN6 = KC_MS_BTN5,
 | 
			
		||||
    KC_MS_BTN7 = KC_MS_BTN5,
 | 
			
		||||
    KC_MS_BTN8 = KC_MS_BTN5,
 | 
			
		||||
#else
 | 
			
		||||
    KC_MS_BTN6,
 | 
			
		||||
    KC_MS_BTN7,
 | 
			
		||||
    KC_MS_BTN8,
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* Mouse Wheel */
 | 
			
		||||
    KC_MS_WH_UP,
 | 
			
		||||
    KC_MS_WH_DOWN,
 | 
			
		||||
    KC_MS_WH_LEFT,
 | 
			
		||||
    KC_MS_WH_RIGHT,
 | 
			
		||||
 | 
			
		||||
    /* Acceleration */
 | 
			
		||||
    KC_MS_ACCEL0,
 | 
			
		||||
    KC_MS_ACCEL1,
 | 
			
		||||
    KC_MS_ACCEL2  // 0xFF
 | 
			
		||||
};
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue