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