Merge remote-tracking branch 'qmk/master' into merge-2022-03-06
This commit is contained in:
157
quantum/action.c
157
quantum/action.c
@@ -23,7 +23,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "led.h"
|
||||
#include "action_layer.h"
|
||||
#include "action_tapping.h"
|
||||
#include "action_macro.h"
|
||||
#include "action_util.h"
|
||||
#include "action.h"
|
||||
#include "wait.h"
|
||||
@@ -55,14 +54,20 @@ int retro_tapping_counter = 0;
|
||||
#endif
|
||||
|
||||
#ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY
|
||||
__attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) { return false; }
|
||||
__attribute__((weak)) bool get_ignore_mod_tap_interrupt(uint16_t keycode, keyrecord_t *record) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef RETRO_TAPPING_PER_KEY
|
||||
__attribute__((weak)) bool get_retro_tapping(uint16_t keycode, keyrecord_t *record) { return false; }
|
||||
__attribute__((weak)) bool get_retro_tapping(uint16_t keycode, keyrecord_t *record) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
__attribute__((weak)) bool pre_process_record_quantum(keyrecord_t *record) { return true; }
|
||||
__attribute__((weak)) bool pre_process_record_quantum(keyrecord_t *record) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \brief Called to execute an action.
|
||||
*
|
||||
@@ -165,10 +170,14 @@ void process_record_nocache(keyrecord_t *record) {
|
||||
disable_action_cache = false;
|
||||
}
|
||||
#else
|
||||
void process_record_nocache(keyrecord_t *record) { process_record(record); }
|
||||
void process_record_nocache(keyrecord_t *record) {
|
||||
process_record(record);
|
||||
}
|
||||
#endif
|
||||
|
||||
__attribute__((weak)) bool process_record_quantum(keyrecord_t *record) { return true; }
|
||||
__attribute__((weak)) bool process_record_quantum(keyrecord_t *record) {
|
||||
return true;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void post_process_record_quantum(keyrecord_t *record) {}
|
||||
|
||||
@@ -633,12 +642,7 @@ if (QS_oneshot_tap_toggle > 1) {
|
||||
break;
|
||||
# endif
|
||||
#endif
|
||||
/* Extentions */
|
||||
#ifndef NO_ACTION_MACRO
|
||||
case ACT_MACRO:
|
||||
action_macro_play(action_get_macro(record, action.func.id, action.func.opt));
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef SWAP_HANDS_ENABLE
|
||||
case ACT_SWAP_HANDS:
|
||||
switch (action.swap.code) {
|
||||
@@ -693,7 +697,7 @@ if (QS_oneshot_tap_toggle > 1) {
|
||||
/* tap key */
|
||||
if (tap_count > 0) {
|
||||
if (swap_held) {
|
||||
swap_hands = !swap_hands; // undo hold set up in _tap_hint
|
||||
swap_hands = !swap_hands; // undo hold set up in _tap_hint
|
||||
swap_held = false;
|
||||
}
|
||||
if (event.pressed) {
|
||||
@@ -701,21 +705,16 @@ if (QS_oneshot_tap_toggle > 1) {
|
||||
} else {
|
||||
qs_wait_ms(QS_tap_code_delay);
|
||||
unregister_code(action.swap.code);
|
||||
*record = (keyrecord_t){}; // hack: reset tap mode
|
||||
*record = (keyrecord_t){}; // hack: reset tap mode
|
||||
}
|
||||
} else {
|
||||
if (swap_held && !event.pressed) {
|
||||
swap_hands = !swap_hands; // undo hold set up in _tap_hint
|
||||
swap_hands = !swap_hands; // undo hold set up in _tap_hint
|
||||
swap_held = false;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
#ifndef NO_ACTION_FUNCTION
|
||||
case ACT_FUNCTION:
|
||||
action_function(record, action.func.id, action.func.opt);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
@@ -793,7 +792,7 @@ if (QS_oneshot_tap_toggle > 1) {
|
||||
*
|
||||
* FIXME: Needs documentation.
|
||||
*/
|
||||
void register_code(uint8_t code) {
|
||||
__attribute__((weak)) void register_code(uint8_t code) {
|
||||
if (code == KC_NO) {
|
||||
return;
|
||||
}
|
||||
@@ -833,10 +832,9 @@ void register_code(uint8_t code) {
|
||||
}
|
||||
#endif
|
||||
|
||||
else if
|
||||
IS_KEY(code) {
|
||||
// TODO: should push command_proc out of this block?
|
||||
if (command_proc(code)) return;
|
||||
else if IS_KEY (code) {
|
||||
// TODO: should push command_proc out of this block?
|
||||
if (command_proc(code)) return;
|
||||
|
||||
#ifndef NO_ACTION_ONESHOT
|
||||
/* TODO: remove
|
||||
@@ -853,35 +851,33 @@ void register_code(uint8_t code) {
|
||||
} else
|
||||
*/
|
||||
#endif
|
||||
{
|
||||
// Force a new key press if the key is already pressed
|
||||
// without this, keys with the same keycode, but different
|
||||
// modifiers will be reported incorrectly, see issue #1708
|
||||
if (is_key_pressed(keyboard_report, code)) {
|
||||
del_key(code);
|
||||
send_keyboard_report();
|
||||
}
|
||||
add_key(code);
|
||||
{
|
||||
// Force a new key press if the key is already pressed
|
||||
// without this, keys with the same keycode, but different
|
||||
// modifiers will be reported incorrectly, see issue #1708
|
||||
if (is_key_pressed(keyboard_report, code)) {
|
||||
del_key(code);
|
||||
send_keyboard_report();
|
||||
}
|
||||
}
|
||||
else if
|
||||
IS_MOD(code) {
|
||||
add_mods(MOD_BIT(code));
|
||||
add_key(code);
|
||||
send_keyboard_report();
|
||||
}
|
||||
} else if IS_MOD (code) {
|
||||
add_mods(MOD_BIT(code));
|
||||
send_keyboard_report();
|
||||
}
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
else if
|
||||
IS_SYSTEM(code) { host_system_send(KEYCODE2SYSTEM(code)); }
|
||||
else if
|
||||
IS_CONSUMER(code) { host_consumer_send(KEYCODE2CONSUMER(code)); }
|
||||
else if IS_SYSTEM (code) {
|
||||
host_system_send(KEYCODE2SYSTEM(code));
|
||||
} else if IS_CONSUMER (code) {
|
||||
host_consumer_send(KEYCODE2CONSUMER(code));
|
||||
}
|
||||
#endif
|
||||
#ifdef MOUSEKEY_ENABLE
|
||||
else if
|
||||
IS_MOUSEKEY(code) {
|
||||
mousekey_on(code);
|
||||
mousekey_send();
|
||||
}
|
||||
else if IS_MOUSEKEY (code) {
|
||||
mousekey_on(code);
|
||||
mousekey_send();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -889,7 +885,7 @@ void register_code(uint8_t code) {
|
||||
*
|
||||
* FIXME: Needs documentation.
|
||||
*/
|
||||
void unregister_code(uint8_t code) {
|
||||
__attribute__((weak)) void unregister_code(uint8_t code) {
|
||||
if (code == KC_NO) {
|
||||
return;
|
||||
}
|
||||
@@ -926,26 +922,22 @@ void unregister_code(uint8_t code) {
|
||||
}
|
||||
#endif
|
||||
|
||||
else if
|
||||
IS_KEY(code) {
|
||||
del_key(code);
|
||||
send_keyboard_report();
|
||||
}
|
||||
else if
|
||||
IS_MOD(code) {
|
||||
del_mods(MOD_BIT(code));
|
||||
send_keyboard_report();
|
||||
}
|
||||
else if
|
||||
IS_SYSTEM(code) { host_system_send(0); }
|
||||
else if
|
||||
IS_CONSUMER(code) { host_consumer_send(0); }
|
||||
else if IS_KEY (code) {
|
||||
del_key(code);
|
||||
send_keyboard_report();
|
||||
} else if IS_MOD (code) {
|
||||
del_mods(MOD_BIT(code));
|
||||
send_keyboard_report();
|
||||
} else if IS_SYSTEM (code) {
|
||||
host_system_send(0);
|
||||
} else if IS_CONSUMER (code) {
|
||||
host_consumer_send(0);
|
||||
}
|
||||
#ifdef MOUSEKEY_ENABLE
|
||||
else if
|
||||
IS_MOUSEKEY(code) {
|
||||
mousekey_off(code);
|
||||
mousekey_send();
|
||||
}
|
||||
else if IS_MOUSEKEY (code) {
|
||||
mousekey_off(code);
|
||||
mousekey_send();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -954,7 +946,7 @@ void unregister_code(uint8_t code) {
|
||||
* \param code The basic keycode to tap.
|
||||
* \param delay The amount of time in milliseconds to leave the keycode registered, before unregistering it.
|
||||
*/
|
||||
void tap_code_delay(uint8_t code, uint16_t delay) {
|
||||
__attribute__((weak)) void tap_code_delay(uint8_t code, uint16_t delay) {
|
||||
register_code(code);
|
||||
for (uint16_t i = delay; i > 0; i--) {
|
||||
wait_ms(1);
|
||||
@@ -966,13 +958,15 @@ void tap_code_delay(uint8_t code, uint16_t delay) {
|
||||
*
|
||||
* \param code The basic keycode to tap. If `code` is `KC_CAPS_LOCK`, the delay will be `TAP_HOLD_CAPS_DELAY`, otherwise `TAP_CODE_DELAY`, if defined.
|
||||
*/
|
||||
void tap_code(uint8_t code) { tap_code_delay(code, code == KC_CAPS ? QS_tap_hold_caps_delay : QS_tap_code_delay); }
|
||||
__attribute__((weak)) void tap_code(uint8_t code) {
|
||||
tap_code_delay(code, code == KC_CAPS ? QS_tap_hold_caps_delay : QS_tap_code_delay);
|
||||
}
|
||||
|
||||
/** \brief Adds the given physically pressed modifiers and sends a keyboard report immediately.
|
||||
*
|
||||
* \param mods A bitfield of modifiers to register.
|
||||
*/
|
||||
void register_mods(uint8_t mods) {
|
||||
__attribute__((weak)) void register_mods(uint8_t mods) {
|
||||
if (mods) {
|
||||
add_mods(mods);
|
||||
send_keyboard_report();
|
||||
@@ -983,7 +977,7 @@ void register_mods(uint8_t mods) {
|
||||
*
|
||||
* \param mods A bitfield of modifiers to unregister.
|
||||
*/
|
||||
void unregister_mods(uint8_t mods) {
|
||||
__attribute__((weak)) void unregister_mods(uint8_t mods) {
|
||||
if (mods) {
|
||||
del_mods(mods);
|
||||
send_keyboard_report();
|
||||
@@ -994,7 +988,7 @@ void unregister_mods(uint8_t mods) {
|
||||
*
|
||||
* \param mods A bitfield of modifiers to register.
|
||||
*/
|
||||
void register_weak_mods(uint8_t mods) {
|
||||
__attribute__((weak)) void register_weak_mods(uint8_t mods) {
|
||||
if (mods) {
|
||||
add_weak_mods(mods);
|
||||
send_keyboard_report();
|
||||
@@ -1005,7 +999,7 @@ void register_weak_mods(uint8_t mods) {
|
||||
*
|
||||
* \param mods A bitfield of modifiers to unregister.
|
||||
*/
|
||||
void unregister_weak_mods(uint8_t mods) {
|
||||
__attribute__((weak)) void unregister_weak_mods(uint8_t mods) {
|
||||
if (mods) {
|
||||
del_weak_mods(mods);
|
||||
send_keyboard_report();
|
||||
@@ -1040,7 +1034,6 @@ void clear_keyboard_but_mods_and_keys() {
|
||||
host_consumer_send(0);
|
||||
#endif
|
||||
clear_weak_mods();
|
||||
clear_macro_mods();
|
||||
send_keyboard_report();
|
||||
#ifdef MOUSEKEY_ENABLE
|
||||
mousekey_clear();
|
||||
@@ -1103,12 +1096,6 @@ bool is_tap_action(action_t action) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case ACT_MACRO:
|
||||
case ACT_FUNCTION:
|
||||
if (action.func.opt & FUNC_TAP) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1117,7 +1104,9 @@ bool is_tap_action(action_t action) {
|
||||
*
|
||||
* FIXME: Needs documentation.
|
||||
*/
|
||||
void debug_event(keyevent_t event) { dprintf("%04X%c(%u)", (event.key.row << 8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time); }
|
||||
void debug_event(keyevent_t event) {
|
||||
dprintf("%04X%c(%u)", (event.key.row << 8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time);
|
||||
}
|
||||
/** \brief Debug print (FIXME: Needs better description)
|
||||
*
|
||||
* FIXME: Needs documentation.
|
||||
@@ -1165,12 +1154,6 @@ void debug_action(action_t action) {
|
||||
case ACT_LAYER_TAP_EXT:
|
||||
dprint("ACT_LAYER_TAP_EXT");
|
||||
break;
|
||||
case ACT_MACRO:
|
||||
dprint("ACT_MACRO");
|
||||
break;
|
||||
case ACT_FUNCTION:
|
||||
dprint("ACT_FUNCTION");
|
||||
break;
|
||||
case ACT_SWAP_HANDS:
|
||||
dprint("ACT_SWAP_HANDS");
|
||||
break;
|
||||
|
||||
@@ -19,25 +19,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "progmem.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
|
||||
|
||||
#ifndef TAP_CODE_DELAY
|
||||
# define TAP_CODE_DELAY 0
|
||||
#endif
|
||||
@@ -72,12 +62,6 @@ void action_exec(keyevent_t event);
|
||||
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);
|
||||
|
||||
@@ -88,7 +72,7 @@ extern bool disable_action_cache;
|
||||
|
||||
/* Code for handling one-handed key modifiers. */
|
||||
#ifdef SWAP_HANDS_ENABLE
|
||||
extern bool swap_hands;
|
||||
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;
|
||||
|
||||
@@ -79,19 +79,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* 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 */
|
||||
@@ -111,9 +98,6 @@ enum action_kind_id {
|
||||
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
|
||||
@@ -164,11 +148,6 @@ typedef union {
|
||||
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;
|
||||
@@ -275,17 +254,6 @@ enum layer_param_tap_op {
|
||||
#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,
|
||||
|
||||
@@ -22,13 +22,17 @@ layer_state_t default_layer_state = 0;
|
||||
*
|
||||
* Run user code on default layer state change
|
||||
*/
|
||||
__attribute__((weak)) layer_state_t default_layer_state_set_user(layer_state_t state) { return state; }
|
||||
__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); }
|
||||
__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
|
||||
*
|
||||
@@ -43,9 +47,9 @@ static void default_layer_state_set(layer_state_t state) {
|
||||
default_layer_debug();
|
||||
debug("\n");
|
||||
#ifdef STRICT_LAYER_RELEASE
|
||||
clear_keyboard_but_mods(); // To avoid stuck keys
|
||||
clear_keyboard_but_mods(); // To avoid stuck keys
|
||||
#else
|
||||
clear_keyboard_but_mods_and_keys(); // Don't reset held keys
|
||||
clear_keyboard_but_mods_and_keys(); // Don't reset held keys
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -53,30 +57,40 @@ static void default_layer_state_set(layer_state_t state) {
|
||||
*
|
||||
* 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)); }
|
||||
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); }
|
||||
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); }
|
||||
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); }
|
||||
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); }
|
||||
void default_layer_xor(layer_state_t state) {
|
||||
default_layer_state_set(default_layer_state ^ state);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NO_ACTION_LAYER
|
||||
@@ -88,13 +102,17 @@ layer_state_t layer_state = 0;
|
||||
*
|
||||
* Runs user code on layer state change
|
||||
*/
|
||||
__attribute__((weak)) layer_state_t layer_state_set_user(layer_state_t state) { return state; }
|
||||
__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); }
|
||||
__attribute__((weak)) layer_state_t layer_state_set_kb(layer_state_t state) {
|
||||
return layer_state_set_user(state);
|
||||
}
|
||||
|
||||
/** \brief Layer state set
|
||||
*
|
||||
@@ -109,9 +127,9 @@ void layer_state_set(layer_state_t state) {
|
||||
layer_debug();
|
||||
dprintln();
|
||||
# ifdef STRICT_LAYER_RELEASE
|
||||
clear_keyboard_but_mods(); // To avoid stuck keys
|
||||
clear_keyboard_but_mods(); // To avoid stuck keys
|
||||
# else
|
||||
clear_keyboard_but_mods_and_keys(); // Don't reset held keys
|
||||
clear_keyboard_but_mods_and_keys(); // Don't reset held keys
|
||||
# endif
|
||||
}
|
||||
|
||||
@@ -119,13 +137,17 @@ void layer_state_set(layer_state_t state) {
|
||||
*
|
||||
* Turn off all layers
|
||||
*/
|
||||
void layer_clear(void) { layer_state_set(0); }
|
||||
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); }
|
||||
bool layer_state_is(uint8_t layer) {
|
||||
return layer_state_cmp(layer_state, layer);
|
||||
}
|
||||
|
||||
/** \brief Layer state compare
|
||||
*
|
||||
@@ -142,47 +164,63 @@ bool layer_state_cmp(layer_state_t cmp_layer_state, uint8_t layer) {
|
||||
*
|
||||
* 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); }
|
||||
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)); }
|
||||
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)); }
|
||||
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)); }
|
||||
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); }
|
||||
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); }
|
||||
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); }
|
||||
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)); }
|
||||
void layer_debug(void) {
|
||||
dprintf("%08lX(%u)", layer_state, get_highest_layer(layer_state));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
|
||||
@@ -288,4 +326,6 @@ uint8_t layer_switch_get_layer(keypos_t key) {
|
||||
*
|
||||
* 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); }
|
||||
action_t layer_switch_get_action(keypos_t key) {
|
||||
return action_for_key(layer_switch_get_layer(key), 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)
|
||||
@@ -26,7 +26,9 @@
|
||||
|
||||
uint16_t g_tapping_term = TAPPING_TERM;
|
||||
|
||||
__attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) { return g_tapping_term; }
|
||||
__attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
|
||||
return g_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))
|
||||
@@ -35,15 +37,21 @@ __attribute__((weak)) uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *r
|
||||
# endif
|
||||
|
||||
# ifdef TAPPING_FORCE_HOLD_PER_KEY
|
||||
__attribute__((weak)) bool get_tapping_force_hold(uint16_t keycode, keyrecord_t *record) { return false; }
|
||||
__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; }
|
||||
__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; }
|
||||
__attribute__((weak)) bool get_hold_on_other_key_press(uint16_t keycode, keyrecord_t *record) {
|
||||
return false;
|
||||
}
|
||||
# endif
|
||||
|
||||
# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
|
||||
@@ -124,7 +132,7 @@ bool process_tapping(keyrecord_t *keyp) {
|
||||
# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
|
||||
|| (
|
||||
# ifdef RETRO_TAPPING_PER_KEY
|
||||
get_retro_tapping(tapping_keycode, keyp) &&
|
||||
get_retro_tapping(tapping_keycode, &tapping_key) &&
|
||||
# endif
|
||||
(RETRO_SHIFT + 0) != 0 && TIMER_DIFF_16(event.time, tapping_key.event.time) < (RETRO_SHIFT + 0)
|
||||
)
|
||||
@@ -158,7 +166,7 @@ bool process_tapping(keyrecord_t *keyp) {
|
||||
(
|
||||
(
|
||||
# ifdef TAPPING_TERM_PER_KEY
|
||||
get_tapping_term(tapping_keycode, keyp)
|
||||
get_tapping_term(tapping_keycode, &tapping_key)
|
||||
# else
|
||||
g_tapping_term
|
||||
# endif
|
||||
@@ -166,7 +174,7 @@ bool process_tapping(keyrecord_t *keyp) {
|
||||
)
|
||||
|
||||
# ifdef PERMISSIVE_HOLD_PER_KEY
|
||||
|| get_permissive_hold(tapping_keycode, keyp)
|
||||
|| get_permissive_hold(tapping_keycode, &tapping_key)
|
||||
# elif defined(PERMISSIVE_HOLD)
|
||||
|| true
|
||||
# endif
|
||||
@@ -177,7 +185,7 @@ bool process_tapping(keyrecord_t *keyp) {
|
||||
# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
|
||||
|| (
|
||||
# ifdef RETRO_TAPPING_PER_KEY
|
||||
get_retro_tapping(tapping_keycode, keyp) &&
|
||||
get_retro_tapping(tapping_keycode, &tapping_key) &&
|
||||
# endif
|
||||
(
|
||||
// Rolled over the two keys.
|
||||
@@ -188,7 +196,7 @@ bool process_tapping(keyrecord_t *keyp) {
|
||||
|| (
|
||||
IS_LT(tapping_keycode)
|
||||
# ifdef HOLD_ON_OTHER_KEY_PRESS_PER_KEY
|
||||
&& get_hold_on_other_key_press(tapping_keycode, keyp)
|
||||
&& get_hold_on_other_key_press(tapping_keycode, &tapping_key)
|
||||
# endif
|
||||
)
|
||||
# endif
|
||||
@@ -196,7 +204,7 @@ bool process_tapping(keyrecord_t *keyp) {
|
||||
|| (
|
||||
IS_MT(tapping_keycode)
|
||||
# ifdef IGNORE_MOD_TAP_INTERRUPT_PER_KEY
|
||||
&& !get_ignore_mod_tap_interrupt(tapping_keycode, keyp)
|
||||
&& !get_ignore_mod_tap_interrupt(tapping_keycode, &tapping_key)
|
||||
# endif
|
||||
)
|
||||
# endif
|
||||
@@ -252,7 +260,7 @@ bool process_tapping(keyrecord_t *keyp) {
|
||||
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(tapping_keycode, keyp))
|
||||
if (get_hold_on_other_key_press(tapping_keycode, &tapping_key))
|
||||
# endif
|
||||
{
|
||||
debug("Tapping: End. No tap. Interfered by pressed key\n");
|
||||
@@ -360,7 +368,7 @@ bool process_tapping(keyrecord_t *keyp) {
|
||||
# if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)
|
||||
|| (
|
||||
# ifdef RETRO_TAPPING_PER_KEY
|
||||
get_retro_tapping(tapping_keycode, keyp) &&
|
||||
get_retro_tapping(tapping_keycode, &tapping_key) &&
|
||||
# endif
|
||||
(RETRO_SHIFT + 0) != 0 && TIMER_DIFF_16(event.time, tapping_key.event.time) < (RETRO_SHIFT + 0)
|
||||
)
|
||||
@@ -373,7 +381,7 @@ bool process_tapping(keyrecord_t *keyp) {
|
||||
# if !defined(TAPPING_FORCE_HOLD) || defined(TAPPING_FORCE_HOLD_PER_KEY)
|
||||
if (
|
||||
# ifdef TAPPING_FORCE_HOLD_PER_KEY
|
||||
!get_tapping_force_hold(tapping_keycode, keyp) &&
|
||||
!get_tapping_force_hold(tapping_keycode, &tapping_key) &&
|
||||
# endif
|
||||
!tapping_key.tap.interrupted && tapping_key.tap.count > 0) {
|
||||
// sequential tap.
|
||||
|
||||
@@ -22,12 +22,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "timer.h"
|
||||
#include "keycode_config.h"
|
||||
#include "qmk_settings.h"
|
||||
#include <string.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;
|
||||
static uint8_t real_mods = 0;
|
||||
static uint8_t weak_mods = 0;
|
||||
#ifdef KEY_OVERRIDE_ENABLE
|
||||
static uint8_t weak_override_mods = 0;
|
||||
static uint8_t suppressed_mods = 0;
|
||||
@@ -44,8 +44,10 @@ 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) {
|
||||
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);
|
||||
@@ -58,7 +60,9 @@ void clear_oneshot_locked_mods(void) {
|
||||
}
|
||||
}
|
||||
static uint16_t oneshot_time = 0;
|
||||
bool has_oneshot_mods_timed_out(void) { return QS_oneshot_timeout > 0 && TIMER_DIFF_16(timer_read(), oneshot_time) >= QS_oneshot_timeout; }
|
||||
bool has_oneshot_mods_timed_out(void) {
|
||||
return QS_oneshot_timeout > 0 && TIMER_DIFF_16(timer_read(), oneshot_time) >= QS_oneshot_timeout;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* oneshot layer */
|
||||
@@ -71,23 +75,31 @@ bool has_oneshot_mods_timed_out(void) { return QS_oneshot_timeout > 0
|
||||
*/
|
||||
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; }
|
||||
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
|
||||
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
|
||||
|
||||
static uint16_t oneshot_layer_time = 0;
|
||||
inline bool has_oneshot_layer_timed_out() { return TIMER_DIFF_16(timer_read(), oneshot_layer_time) >= QS_oneshot_timeout && !(get_oneshot_layer_state() & ONESHOT_TOGGLED); }
|
||||
inline bool has_oneshot_layer_timed_out() {
|
||||
return TIMER_DIFF_16(timer_read(), oneshot_layer_time) >= QS_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) >= QS_oneshot_timeout && (swap_hands_oneshot == SHO_ACTIVE); }
|
||||
inline bool has_oneshot_swaphands_timed_out() {
|
||||
return TIMER_DIFF_16(timer_read(), oneshot_swaphands_time) >= QS_oneshot_timeout && (swap_hands_oneshot == SHO_ACTIVE);
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifdef SWAP_HANDS_ENABLE
|
||||
@@ -166,7 +178,9 @@ void clear_oneshot_layer_state(oneshot_fullfillment_t state) {
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
bool is_oneshot_layer_active(void) { return get_oneshot_layer_state(); }
|
||||
bool is_oneshot_layer_active(void) {
|
||||
return get_oneshot_layer_state();
|
||||
}
|
||||
|
||||
/** \brief set oneshot
|
||||
*
|
||||
@@ -185,21 +199,29 @@ void oneshot_set(bool active) {
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void oneshot_toggle(void) { oneshot_set(!keymap_config.oneshot_disable); }
|
||||
void oneshot_toggle(void) {
|
||||
oneshot_set(!keymap_config.oneshot_disable);
|
||||
}
|
||||
|
||||
/** \brief enable oneshot
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void oneshot_enable(void) { oneshot_set(true); }
|
||||
void oneshot_enable(void) {
|
||||
oneshot_set(true);
|
||||
}
|
||||
|
||||
/** \brief disable oneshot
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void oneshot_disable(void) { oneshot_set(false); }
|
||||
void oneshot_disable(void) {
|
||||
oneshot_set(false);
|
||||
}
|
||||
|
||||
bool is_oneshot_enabled(void) { return keymap_config.oneshot_disable; }
|
||||
bool is_oneshot_enabled(void) {
|
||||
return keymap_config.oneshot_disable;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -210,7 +232,6 @@ bool is_oneshot_enabled(void) { return keymap_config.oneshot_disable; }
|
||||
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) {
|
||||
@@ -232,110 +253,123 @@ void send_keyboard_report(void) {
|
||||
keyboard_report->mods |= weak_override_mods;
|
||||
#endif
|
||||
|
||||
#ifdef PROTOCOL_VUSB
|
||||
host_keyboard_send(keyboard_report);
|
||||
#else
|
||||
static report_keyboard_t last_report;
|
||||
|
||||
/* Only send the report if there are changes to propagate to the host. */
|
||||
if (memcmp(keyboard_report, &last_report, sizeof(report_keyboard_t)) != 0) {
|
||||
memcpy(&last_report, keyboard_report, sizeof(report_keyboard_t));
|
||||
host_keyboard_send(keyboard_report);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \brief Get mods
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
uint8_t get_mods(void) { return real_mods; }
|
||||
uint8_t get_mods(void) {
|
||||
return real_mods;
|
||||
}
|
||||
/** \brief add mods
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void add_mods(uint8_t mods) { real_mods |= mods; }
|
||||
void add_mods(uint8_t mods) {
|
||||
real_mods |= mods;
|
||||
}
|
||||
/** \brief del mods
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void del_mods(uint8_t mods) { real_mods &= ~mods; }
|
||||
void del_mods(uint8_t mods) {
|
||||
real_mods &= ~mods;
|
||||
}
|
||||
/** \brief set mods
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void set_mods(uint8_t mods) { real_mods = mods; }
|
||||
void set_mods(uint8_t mods) {
|
||||
real_mods = mods;
|
||||
}
|
||||
/** \brief clear mods
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void clear_mods(void) { real_mods = 0; }
|
||||
void clear_mods(void) {
|
||||
real_mods = 0;
|
||||
}
|
||||
|
||||
/** \brief get weak mods
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
uint8_t get_weak_mods(void) { return weak_mods; }
|
||||
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; }
|
||||
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; }
|
||||
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; }
|
||||
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; }
|
||||
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; }
|
||||
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; }
|
||||
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; }
|
||||
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; }
|
||||
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; }
|
||||
uint8_t get_oneshot_mods(void) {
|
||||
return oneshot_mods;
|
||||
}
|
||||
|
||||
void add_oneshot_mods(uint8_t mods) {
|
||||
if ((oneshot_mods & mods) != mods) {
|
||||
@@ -390,7 +424,9 @@ __attribute__((weak)) void oneshot_locked_mods_changed_user(uint8_t mods) {}
|
||||
*
|
||||
* \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); }
|
||||
__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.
|
||||
*
|
||||
@@ -402,7 +438,9 @@ __attribute__((weak)) void oneshot_mods_changed_user(uint8_t mods) {}
|
||||
*
|
||||
* \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); }
|
||||
__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.
|
||||
*
|
||||
@@ -414,10 +452,14 @@ __attribute__((weak)) void oneshot_layer_changed_user(uint8_t layer) {}
|
||||
*
|
||||
* \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); }
|
||||
__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); }
|
||||
uint8_t has_anymod(void) {
|
||||
return bitpop(real_mods);
|
||||
}
|
||||
|
||||
@@ -29,11 +29,17 @@ 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 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 del_key(uint8_t key) {
|
||||
del_key_from_report(keyboard_report, key);
|
||||
}
|
||||
|
||||
inline void clear_keys(void) { clear_keys_from_report(keyboard_report); }
|
||||
inline void clear_keys(void) {
|
||||
clear_keys_from_report(keyboard_report);
|
||||
}
|
||||
|
||||
/* modifier */
|
||||
uint8_t get_mods(void);
|
||||
@@ -49,13 +55,6 @@ 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);
|
||||
|
||||
@@ -64,21 +64,21 @@
|
||||
#ifndef AUDIO_TONE_STACKSIZE
|
||||
# define AUDIO_TONE_STACKSIZE 8
|
||||
#endif
|
||||
uint8_t active_tones = 0; // number of tones pushed onto the stack by audio_play_tone - might be more than the hardware is able to reproduce at any single time
|
||||
musical_tone_t tones[AUDIO_TONE_STACKSIZE]; // stack of currently active tones
|
||||
uint8_t active_tones = 0; // number of tones pushed onto the stack by audio_play_tone - might be more than the hardware is able to reproduce at any single time
|
||||
musical_tone_t tones[AUDIO_TONE_STACKSIZE]; // stack of currently active tones
|
||||
|
||||
bool playing_melody = false; // playing a SONG?
|
||||
bool playing_note = false; // or (possibly multiple simultaneous) tones
|
||||
bool state_changed = false; // global flag, which is set if anything changes with the active_tones
|
||||
bool playing_melody = false; // playing a SONG?
|
||||
bool playing_note = false; // or (possibly multiple simultaneous) tones
|
||||
bool state_changed = false; // global flag, which is set if anything changes with the active_tones
|
||||
|
||||
// melody/SONG related state variables
|
||||
float (*notes_pointer)[][2]; // SONG, an array of MUSICAL_NOTEs
|
||||
uint16_t notes_count; // length of the notes_pointer array
|
||||
bool notes_repeat; // PLAY_SONG or PLAY_LOOP?
|
||||
uint16_t melody_current_note_duration = 0; // duration of the currently playing note from the active melody, in ms
|
||||
uint8_t note_tempo = TEMPO_DEFAULT; // beats-per-minute
|
||||
uint16_t current_note = 0; // index into the array at notes_pointer
|
||||
bool note_resting = false; // if a short pause was introduced between two notes with the same frequency while playing a melody
|
||||
float (*notes_pointer)[][2]; // SONG, an array of MUSICAL_NOTEs
|
||||
uint16_t notes_count; // length of the notes_pointer array
|
||||
bool notes_repeat; // PLAY_SONG or PLAY_LOOP?
|
||||
uint16_t melody_current_note_duration = 0; // duration of the currently playing note from the active melody, in ms
|
||||
uint8_t note_tempo = TEMPO_DEFAULT; // beats-per-minute
|
||||
uint16_t current_note = 0; // index into the array at notes_pointer
|
||||
bool note_resting = false; // if a short pause was introduced between two notes with the same frequency while playing a melody
|
||||
uint16_t last_timestamp = 0;
|
||||
|
||||
#ifdef AUDIO_ENABLE_TONE_MULTIPLEXING
|
||||
@@ -86,7 +86,7 @@ uint16_t last_timestamp = 0;
|
||||
# define AUDIO_MAX_SIMULTANEOUS_TONES 3
|
||||
# endif
|
||||
uint16_t tone_multiplexing_rate = AUDIO_TONE_MULTIPLEXING_RATE_DEFAULT;
|
||||
uint8_t tone_multiplexing_index_shift = 0; // offset used on active-tone array access
|
||||
uint8_t tone_multiplexing_index_shift = 0; // offset used on active-tone array access
|
||||
#endif
|
||||
|
||||
// provided and used by voices.c
|
||||
@@ -123,12 +123,12 @@ void audio_init() {
|
||||
eeconfig_init();
|
||||
}
|
||||
audio_config.raw = eeconfig_read_audio();
|
||||
#else // EEPROM settings
|
||||
#else // EEPROM settings
|
||||
audio_config.enable = true;
|
||||
# ifdef AUDIO_CLICKY_ON
|
||||
audio_config.clicky_enable = true;
|
||||
# endif
|
||||
#endif // EEPROM settings
|
||||
#endif // EEPROM settings
|
||||
|
||||
for (uint8_t i = 0; i < AUDIO_TONE_STACKSIZE; i++) {
|
||||
tones[i] = (musical_tone_t){.time_started = 0, .pitch = -1.0f, .duration = 0};
|
||||
@@ -160,6 +160,8 @@ void audio_toggle(void) {
|
||||
eeconfig_update_audio(audio_config.raw);
|
||||
if (audio_config.enable) {
|
||||
audio_on_user();
|
||||
} else {
|
||||
audio_off_user();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,13 +174,16 @@ void audio_on(void) {
|
||||
|
||||
void audio_off(void) {
|
||||
PLAY_SONG(audio_off_song);
|
||||
audio_off_user();
|
||||
wait_ms(100);
|
||||
audio_stop_all();
|
||||
audio_config.enable = 0;
|
||||
eeconfig_update_audio(audio_config.raw);
|
||||
}
|
||||
|
||||
bool audio_is_on(void) { return (audio_config.enable != 0); }
|
||||
bool audio_is_on(void) {
|
||||
return (audio_config.enable != 0);
|
||||
}
|
||||
|
||||
void audio_stop_all() {
|
||||
if (audio_driver_stopped) {
|
||||
@@ -265,7 +270,7 @@ void audio_play_note(float pitch, uint16_t duration) {
|
||||
tones[j] = tones[j + 1];
|
||||
tones[j + 1] = (musical_tone_t){.time_started = timer_read(), .pitch = pitch, .duration = duration};
|
||||
}
|
||||
return; // since this frequency played already, the hardware was already started
|
||||
return; // since this frequency played already, the hardware was already started
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,7 +288,7 @@ void audio_play_note(float pitch, uint16_t duration) {
|
||||
tones[active_tones - 1] = (musical_tone_t){.time_started = timer_read(), .pitch = pitch, .duration = duration};
|
||||
|
||||
// TODO: needs to be handled per note/tone -> use its timestamp instead?
|
||||
voices_timer = timer_read(); // reset to zero, for the effects added by voices.c
|
||||
voices_timer = timer_read(); // reset to zero, for the effects added by voices.c
|
||||
|
||||
if (audio_driver_stopped) {
|
||||
audio_driver_start();
|
||||
@@ -291,7 +296,9 @@ void audio_play_note(float pitch, uint16_t duration) {
|
||||
}
|
||||
}
|
||||
|
||||
void audio_play_tone(float pitch) { audio_play_note(pitch, 0xffff); }
|
||||
void audio_play_tone(float pitch) {
|
||||
audio_play_note(pitch, 0xffff);
|
||||
}
|
||||
|
||||
void audio_play_melody(float (*np)[][2], uint16_t n_count, bool n_repeat) {
|
||||
if (!audio_config.enable) {
|
||||
@@ -313,7 +320,7 @@ void audio_play_melody(float (*np)[][2], uint16_t n_count, bool n_repeat) {
|
||||
notes_count = n_count;
|
||||
notes_repeat = n_repeat;
|
||||
|
||||
current_note = 0; // note in the melody-array/list at note_pointer
|
||||
current_note = 0; // note in the melody-array/list at note_pointer
|
||||
|
||||
// start first note manually, which also starts the audio_driver
|
||||
// all following/remaining notes are played by 'audio_update_state'
|
||||
@@ -344,11 +351,17 @@ void audio_play_click(uint16_t delay, float pitch, uint16_t duration) {
|
||||
}
|
||||
}
|
||||
|
||||
bool audio_is_playing_note(void) { return playing_note; }
|
||||
bool audio_is_playing_note(void) {
|
||||
return playing_note;
|
||||
}
|
||||
|
||||
bool audio_is_playing_melody(void) { return playing_melody; }
|
||||
bool audio_is_playing_melody(void) {
|
||||
return playing_melody;
|
||||
}
|
||||
|
||||
uint8_t audio_get_number_of_active_tones(void) { return active_tones; }
|
||||
uint8_t audio_get_number_of_active_tones(void) {
|
||||
return active_tones;
|
||||
}
|
||||
|
||||
float audio_get_frequency(uint8_t tone_index) {
|
||||
if (tone_index >= active_tones) {
|
||||
@@ -367,7 +380,7 @@ float audio_get_processed_frequency(uint8_t tone_index) {
|
||||
|
||||
#ifdef AUDIO_ENABLE_TONE_MULTIPLEXING
|
||||
index = index - tone_multiplexing_index_shift;
|
||||
if (index < 0) // wrap around
|
||||
if (index < 0) // wrap around
|
||||
index += active_tones;
|
||||
#endif
|
||||
|
||||
@@ -393,7 +406,7 @@ bool audio_update_state(void) {
|
||||
last_timestamp = current_time;
|
||||
uint16_t previous_note = current_note;
|
||||
current_note++;
|
||||
voices_timer = timer_read(); // reset to zero, for the effects added by voices.c
|
||||
voices_timer = timer_read(); // reset to zero, for the effects added by voices.c
|
||||
|
||||
if (current_note >= notes_count) {
|
||||
if (notes_repeat) {
|
||||
@@ -463,11 +476,11 @@ bool audio_update_state(void) {
|
||||
|
||||
// housekeeping: stop notes that have no playtime left
|
||||
for (int i = 0; i < active_tones; i++) {
|
||||
if ((tones[i].duration != 0xffff) // indefinitely playing notes, started by 'audio_play_tone'
|
||||
&& (tones[i].duration != 0) // 'uninitialized'
|
||||
if ((tones[i].duration != 0xffff) // indefinitely playing notes, started by 'audio_play_tone'
|
||||
&& (tones[i].duration != 0) // 'uninitialized'
|
||||
) {
|
||||
if (timer_elapsed(tones[i].time_started) >= tones[i].duration) {
|
||||
audio_stop_tone(tones[i].pitch); // also sets 'state_changed=true'
|
||||
audio_stop_tone(tones[i].pitch); // also sets 'state_changed=true'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -484,9 +497,15 @@ bool audio_update_state(void) {
|
||||
|
||||
// Tone-multiplexing functions
|
||||
#ifdef AUDIO_ENABLE_TONE_MULTIPLEXING
|
||||
void audio_set_tone_multiplexing_rate(uint16_t rate) { tone_multiplexing_rate = rate; }
|
||||
void audio_enable_tone_multiplexing(void) { tone_multiplexing_rate = AUDIO_TONE_MULTIPLEXING_RATE_DEFAULT; }
|
||||
void audio_disable_tone_multiplexing(void) { tone_multiplexing_rate = 0; }
|
||||
void audio_set_tone_multiplexing_rate(uint16_t rate) {
|
||||
tone_multiplexing_rate = rate;
|
||||
}
|
||||
void audio_enable_tone_multiplexing(void) {
|
||||
tone_multiplexing_rate = AUDIO_TONE_MULTIPLEXING_RATE_DEFAULT;
|
||||
}
|
||||
void audio_disable_tone_multiplexing(void) {
|
||||
tone_multiplexing_rate = 0;
|
||||
}
|
||||
void audio_increase_tone_multiplexing_rate(uint16_t change) {
|
||||
if ((0xffff - change) > tone_multiplexing_rate) {
|
||||
tone_multiplexing_rate += change;
|
||||
|
||||
@@ -54,9 +54,9 @@ typedef union {
|
||||
* "A musical tone is characterized by its duration, pitch, intensity (or loudness), and timbre (or quality)"
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t time_started; // timestamp the tone/note was started, system time runs with 1ms resolution -> 16bit timer overflows every ~64 seconds, long enough under normal circumstances; but might be too soon for long-duration notes when the note_tempo is set to a very low value
|
||||
float pitch; // aka frequency, in Hz
|
||||
uint16_t duration; // in ms, converted from the musical_notes.h unit which has 64parts to a beat, factoring in the current tempo in beats-per-minute
|
||||
uint16_t time_started; // timestamp the tone/note was started, system time runs with 1ms resolution -> 16bit timer overflows every ~64 seconds, long enough under normal circumstances; but might be too soon for long-duration notes when the note_tempo is set to a very low value
|
||||
float pitch; // aka frequency, in Hz
|
||||
uint16_t duration; // in ms, converted from the musical_notes.h unit which has 64parts to a beat, factoring in the current tempo in beats-per-minute
|
||||
// float intensity; // aka volume [0,1] TODO: not used at the moment; pwm drivers can't handle it
|
||||
// uint8_t timbre; // range: [0,100] TODO: this currently kept track of globally, should we do this per tone instead?
|
||||
} musical_tone_t;
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
#if __has_include("user_song_list.h")
|
||||
# include "user_song_list.h"
|
||||
#endif // if file exists
|
||||
#endif // if file exists
|
||||
|
||||
#define NO_SOUND
|
||||
|
||||
|
||||
@@ -32,11 +32,17 @@ voice_type voice = AUDIO_VOICE_DEFAULT;
|
||||
voice_type voice = default_voice;
|
||||
#endif
|
||||
|
||||
void set_voice(voice_type v) { voice = v; }
|
||||
void set_voice(voice_type v) {
|
||||
voice = v;
|
||||
}
|
||||
|
||||
void voice_iterate() { voice = (voice + 1) % number_of_voices; }
|
||||
void voice_iterate() {
|
||||
voice = (voice + 1) % number_of_voices;
|
||||
}
|
||||
|
||||
void voice_deiterate() { voice = (voice - 1 + number_of_voices) % number_of_voices; }
|
||||
void voice_deiterate() {
|
||||
voice = (voice - 1 + number_of_voices) % number_of_voices;
|
||||
}
|
||||
|
||||
#ifdef AUDIO_VOICES
|
||||
float mod(float a, int b) {
|
||||
@@ -67,8 +73,8 @@ float voice_envelope(float frequency) {
|
||||
// envelope_index ranges from 0 to 0xFFFF, which is preserved at 880.0 Hz
|
||||
// __attribute__((unused)) uint16_t compensated_index = (uint16_t)((float)envelope_index * (880.0 / frequency));
|
||||
#ifdef AUDIO_VOICES
|
||||
uint16_t envelope_index = timer_elapsed(voices_timer); // TODO: multiply in some factor?
|
||||
uint16_t compensated_index = envelope_index / 100; // TODO: correct factor would be?
|
||||
uint16_t envelope_index = timer_elapsed(voices_timer); // TODO: multiply in some factor?
|
||||
uint16_t compensated_index = envelope_index / 100; // TODO: correct factor would be?
|
||||
#endif
|
||||
|
||||
switch (voice) {
|
||||
@@ -303,7 +309,7 @@ float voice_envelope(float frequency) {
|
||||
// note_timbre = TIMBRE_25;
|
||||
// break;
|
||||
|
||||
#endif // AUDIO_VOICES
|
||||
#endif // AUDIO_VOICES
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -318,19 +324,31 @@ float voice_envelope(float frequency) {
|
||||
// TODO: where to keep track of the start-frequency?
|
||||
// frequency = voice_add_glissando(??, frequency);
|
||||
}
|
||||
#endif // AUDIO_VOICES
|
||||
#endif // AUDIO_VOICES
|
||||
|
||||
return frequency;
|
||||
}
|
||||
|
||||
// Vibrato functions
|
||||
|
||||
void voice_set_vibrato_rate(float rate) { vibrato_rate = rate; }
|
||||
void voice_increase_vibrato_rate(float change) { vibrato_rate *= change; }
|
||||
void voice_decrease_vibrato_rate(float change) { vibrato_rate /= change; }
|
||||
void voice_set_vibrato_strength(float strength) { vibrato_strength = strength; }
|
||||
void voice_increase_vibrato_strength(float change) { vibrato_strength *= change; }
|
||||
void voice_decrease_vibrato_strength(float change) { vibrato_strength /= change; }
|
||||
void voice_set_vibrato_rate(float rate) {
|
||||
vibrato_rate = rate;
|
||||
}
|
||||
void voice_increase_vibrato_rate(float change) {
|
||||
vibrato_rate *= change;
|
||||
}
|
||||
void voice_decrease_vibrato_rate(float change) {
|
||||
vibrato_rate /= change;
|
||||
}
|
||||
void voice_set_vibrato_strength(float strength) {
|
||||
vibrato_strength = strength;
|
||||
}
|
||||
void voice_increase_vibrato_strength(float change) {
|
||||
vibrato_strength *= change;
|
||||
}
|
||||
void voice_decrease_vibrato_strength(float change) {
|
||||
vibrato_strength /= change;
|
||||
}
|
||||
|
||||
// Timbre functions
|
||||
|
||||
@@ -339,4 +357,6 @@ void voice_set_timbre(uint8_t timbre) {
|
||||
note_timbre = timbre;
|
||||
}
|
||||
}
|
||||
uint8_t voice_get_timbre(void) { return note_timbre; }
|
||||
uint8_t voice_get_timbre(void) {
|
||||
return note_timbre;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ typedef enum {
|
||||
// duty_third_down,
|
||||
// duty_fifth_third_down,
|
||||
#endif
|
||||
number_of_voices // important that this is last
|
||||
number_of_voices // important that this is last
|
||||
} voice_type;
|
||||
|
||||
void set_voice(voice_type v);
|
||||
|
||||
@@ -95,10 +95,10 @@ void backlight_toggle(void) {
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void backlight_enable(void) {
|
||||
if (backlight_config.enable) return; // do nothing if backlight is already on
|
||||
if (backlight_config.enable) return; // do nothing if backlight is already on
|
||||
|
||||
backlight_config.enable = true;
|
||||
if (backlight_config.raw == 1) // enabled but level == 0
|
||||
if (backlight_config.raw == 1) // enabled but level == 0
|
||||
backlight_config.level = 1;
|
||||
eeconfig_update_backlight(backlight_config.raw);
|
||||
dprintf("backlight enable\n");
|
||||
@@ -110,7 +110,7 @@ void backlight_enable(void) {
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void backlight_disable(void) {
|
||||
if (!backlight_config.enable) return; // do nothing if backlight is already off
|
||||
if (!backlight_config.enable) return; // do nothing if backlight is already off
|
||||
|
||||
backlight_config.enable = false;
|
||||
eeconfig_update_backlight(backlight_config.raw);
|
||||
@@ -122,7 +122,9 @@ void backlight_disable(void) {
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
bool is_backlight_enabled(void) { return backlight_config.enable; }
|
||||
bool is_backlight_enabled(void) {
|
||||
return backlight_config.enable;
|
||||
}
|
||||
|
||||
/** \brief Backlight step through levels
|
||||
*
|
||||
@@ -158,11 +160,17 @@ void backlight_level(uint8_t level) {
|
||||
eeconfig_update_backlight(backlight_config.raw);
|
||||
}
|
||||
|
||||
uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BACKLIGHT); }
|
||||
uint8_t eeconfig_read_backlight(void) {
|
||||
return eeprom_read_byte(EECONFIG_BACKLIGHT);
|
||||
}
|
||||
|
||||
void eeconfig_update_backlight(uint8_t val) { eeprom_update_byte(EECONFIG_BACKLIGHT, val); }
|
||||
void eeconfig_update_backlight(uint8_t val) {
|
||||
eeprom_update_byte(EECONFIG_BACKLIGHT, val);
|
||||
}
|
||||
|
||||
void eeconfig_update_backlight_current(void) { eeconfig_update_backlight(backlight_config.raw); }
|
||||
void eeconfig_update_backlight_current(void) {
|
||||
eeconfig_update_backlight(backlight_config.raw);
|
||||
}
|
||||
|
||||
void eeconfig_update_backlight_default(void) {
|
||||
backlight_config.enable = 1;
|
||||
@@ -179,7 +187,9 @@ void eeconfig_update_backlight_default(void) {
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
uint8_t get_backlight_level(void) { return backlight_config.level; }
|
||||
uint8_t get_backlight_level(void) {
|
||||
return backlight_config.level;
|
||||
}
|
||||
|
||||
#ifdef BACKLIGHT_BREATHING
|
||||
/** \brief Backlight breathing toggle
|
||||
@@ -200,7 +210,7 @@ void backlight_toggle_breathing(void) {
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void backlight_enable_breathing(void) {
|
||||
if (backlight_config.breathing) return; // do nothing if breathing is already on
|
||||
if (backlight_config.breathing) return; // do nothing if breathing is already on
|
||||
|
||||
backlight_config.breathing = true;
|
||||
eeconfig_update_backlight(backlight_config.raw);
|
||||
@@ -213,7 +223,7 @@ void backlight_enable_breathing(void) {
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void backlight_disable_breathing(void) {
|
||||
if (!backlight_config.breathing) return; // do nothing if breathing is already off
|
||||
if (!backlight_config.breathing) return; // do nothing if breathing is already off
|
||||
|
||||
backlight_config.breathing = false;
|
||||
eeconfig_update_backlight(backlight_config.raw);
|
||||
@@ -225,18 +235,30 @@ void backlight_disable_breathing(void) {
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
bool is_backlight_breathing(void) { return backlight_config.breathing; }
|
||||
bool is_backlight_breathing(void) {
|
||||
return backlight_config.breathing;
|
||||
}
|
||||
|
||||
// following are marked as weak purely for backwards compatibility
|
||||
__attribute__((weak)) void breathing_period_set(uint8_t value) { breathing_period = value ? value : 1; }
|
||||
__attribute__((weak)) void breathing_period_set(uint8_t value) {
|
||||
breathing_period = value ? value : 1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) uint8_t get_breathing_period(void) { return breathing_period; }
|
||||
__attribute__((weak)) uint8_t get_breathing_period(void) {
|
||||
return breathing_period;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void breathing_period_default(void) { breathing_period_set(BREATHING_PERIOD); }
|
||||
__attribute__((weak)) void breathing_period_default(void) {
|
||||
breathing_period_set(BREATHING_PERIOD);
|
||||
}
|
||||
|
||||
__attribute__((weak)) void breathing_period_inc(void) { breathing_period_set(breathing_period + 1); }
|
||||
__attribute__((weak)) void breathing_period_inc(void) {
|
||||
breathing_period_set(breathing_period + 1);
|
||||
}
|
||||
|
||||
__attribute__((weak)) void breathing_period_dec(void) { breathing_period_set(breathing_period - 1); }
|
||||
__attribute__((weak)) void breathing_period_dec(void) {
|
||||
breathing_period_set(breathing_period - 1);
|
||||
}
|
||||
|
||||
__attribute__((weak)) void breathing_toggle(void) {
|
||||
if (is_breathing())
|
||||
|
||||
@@ -39,7 +39,7 @@ typedef union {
|
||||
struct {
|
||||
bool enable : 1;
|
||||
bool breathing : 1;
|
||||
uint8_t reserved : 1; // Reserved for possible future backlight modes
|
||||
uint8_t reserved : 1; // Reserved for possible future backlight modes
|
||||
uint8_t level : 5;
|
||||
};
|
||||
} backlight_config_t;
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
# define TCCRxB TCCR1B
|
||||
# define TIMERx_COMPA_vect TIMER1_COMPA_vect
|
||||
# define TIMERx_OVF_vect TIMER1_OVF_vect
|
||||
# if defined(__AVR_ATmega32A__) // This MCU has only one TIMSK register
|
||||
# if defined(__AVR_ATmega32A__) // This MCU has only one TIMSK register
|
||||
# define TIMSKx TIMSK
|
||||
# else
|
||||
# define TIMSKx TIMSK1
|
||||
@@ -166,7 +166,7 @@ error("Please set 'BACKLIGHT_DRIVER = custom' within rules.mk")
|
||||
error("Please set 'BACKLIGHT_DRIVER = software' within rules.mk")
|
||||
#endif
|
||||
|
||||
#ifndef BACKLIGHT_PWM_TIMER // pwm through software
|
||||
#ifndef BACKLIGHT_PWM_TIMER // pwm through software
|
||||
|
||||
static inline void enable_pwm(void) {
|
||||
# if BACKLIGHT_ON_STATE == 1
|
||||
@@ -203,7 +203,9 @@ static inline void disable_pwm(void) {
|
||||
// or F_CPU/BACKLIGHT_CUSTOM_RESOLUTION if used.
|
||||
|
||||
// Triggered when the counter reaches the OCRx value
|
||||
ISR(TIMERx_COMPA_vect) { backlight_pins_off(); }
|
||||
ISR(TIMERx_COMPA_vect) {
|
||||
backlight_pins_off();
|
||||
}
|
||||
|
||||
// Triggered when the counter reaches the TOP value
|
||||
// this one triggers at F_CPU/ICRx = 16MHz/65536 =~ 244 Hz
|
||||
@@ -232,15 +234,15 @@ ISR(TIMERx_OVF_vect) {
|
||||
|
||||
// See http://jared.geek.nz/2013/feb/linear-led-pwm
|
||||
static uint16_t cie_lightness(uint16_t v) {
|
||||
if (v <= (uint32_t)ICRx / 12) // If the value is less than or equal to ~8% of max
|
||||
if (v <= (uint32_t)ICRx / 12) // If the value is less than or equal to ~8% of max
|
||||
{
|
||||
return v / 9; // Same as dividing by 900%
|
||||
return v / 9; // Same as dividing by 900%
|
||||
} else {
|
||||
// In the next two lines values are bit-shifted. This is to avoid loosing decimals in integer math.
|
||||
uint32_t y = (((uint32_t)v + (uint32_t)ICRx / 6) << 5) / ((uint32_t)ICRx / 6 + ICRx); // If above 8%, add ~16% of max, and normalize with (max + ~16% max)
|
||||
uint32_t out = (y * y * y * ICRx) >> 15; // Cube it and undo the bit-shifting. (which is now three times as much due to the cubing)
|
||||
uint32_t y = (((uint32_t)v + (uint32_t)ICRx / 6) << 5) / ((uint32_t)ICRx / 6 + ICRx); // If above 8%, add ~16% of max, and normalize with (max + ~16% max)
|
||||
uint32_t out = (y * y * y * ICRx) >> 15; // Cube it and undo the bit-shifting. (which is now three times as much due to the cubing)
|
||||
|
||||
if (out > ICRx) // Avoid overflows
|
||||
if (out > ICRx) // Avoid overflows
|
||||
{
|
||||
out = ICRx;
|
||||
}
|
||||
@@ -249,10 +251,14 @@ static uint16_t cie_lightness(uint16_t v) {
|
||||
}
|
||||
|
||||
// rescale the supplied backlight value to be in terms of the value limit // range for val is [0..ICRx]. PWM pin is high while the timer count is below val.
|
||||
static uint32_t rescale_limit_val(uint32_t val) { return (val * (BACKLIGHT_LIMIT_VAL + 1)) / 256; }
|
||||
static uint32_t rescale_limit_val(uint32_t val) {
|
||||
return (val * (BACKLIGHT_LIMIT_VAL + 1)) / 256;
|
||||
}
|
||||
|
||||
// range for val is [0..ICRx]. PWM pin is high while the timer count is below val.
|
||||
static inline void set_pwm(uint16_t val) { OCRxx = val; }
|
||||
static inline void set_pwm(uint16_t val) {
|
||||
OCRxx = val;
|
||||
}
|
||||
|
||||
void backlight_set(uint8_t level) {
|
||||
if (level > BACKLIGHT_LEVELS) level = BACKLIGHT_LEVELS;
|
||||
@@ -303,7 +309,9 @@ static uint16_t breathing_freq_scale_factor = 2;
|
||||
# ifdef BACKLIGHT_PWM_TIMER
|
||||
static bool breathing = false;
|
||||
|
||||
bool is_breathing(void) { return breathing; }
|
||||
bool is_breathing(void) {
|
||||
return breathing;
|
||||
}
|
||||
|
||||
# define breathing_interrupt_enable() \
|
||||
do { \
|
||||
@@ -315,7 +323,9 @@ bool is_breathing(void) { return breathing; }
|
||||
} while (0)
|
||||
# else
|
||||
|
||||
bool is_breathing(void) { return !!(TIMSKx & _BV(TOIEx)); }
|
||||
bool is_breathing(void) {
|
||||
return !!(TIMSKx & _BV(TOIEx));
|
||||
}
|
||||
|
||||
# define breathing_interrupt_enable() \
|
||||
do { \
|
||||
@@ -370,7 +380,9 @@ void breathing_self_disable(void) {
|
||||
static const uint8_t breathing_table[BREATHING_STEPS] PROGMEM = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 17, 20, 24, 28, 32, 36, 41, 46, 51, 57, 63, 70, 76, 83, 91, 98, 106, 113, 121, 129, 138, 146, 154, 162, 170, 178, 185, 193, 200, 207, 213, 220, 225, 231, 235, 240, 244, 247, 250, 252, 253, 254, 255, 254, 253, 252, 250, 247, 244, 240, 235, 231, 225, 220, 213, 207, 200, 193, 185, 178, 170, 162, 154, 146, 138, 129, 121, 113, 106, 98, 91, 83, 76, 70, 63, 57, 51, 46, 41, 36, 32, 28, 24, 20, 17, 15, 12, 10, 8, 6, 5, 4, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
// Use this before the cie_lightness function.
|
||||
static inline uint16_t scale_backlight(uint16_t v) { return v / BACKLIGHT_LEVELS * get_backlight_level(); }
|
||||
static inline uint16_t scale_backlight(uint16_t v) {
|
||||
return v / BACKLIGHT_LEVELS * get_backlight_level();
|
||||
}
|
||||
|
||||
# ifdef BACKLIGHT_PWM_TIMER
|
||||
void breathing_task(void)
|
||||
@@ -403,7 +415,7 @@ ISR(TIMERx_OVF_vect)
|
||||
set_pwm(cie_lightness(rescale_limit_val(scale_backlight((uint16_t)pgm_read_byte(&breathing_table[index]) * ICRx / 255))));
|
||||
}
|
||||
|
||||
#endif // BACKLIGHT_BREATHING
|
||||
#endif // BACKLIGHT_BREATHING
|
||||
|
||||
void backlight_init_ports(void) {
|
||||
// Setup backlight pin as output and output to on state.
|
||||
@@ -415,10 +427,10 @@ void backlight_init_ports(void) {
|
||||
|
||||
#ifdef BACKLIGHT_PWM_TIMER
|
||||
// TimerX setup, Fast PWM mode count to TOP set in ICRx
|
||||
TCCRxA = _BV(WGM11); // = 0b00000010;
|
||||
TCCRxA = _BV(WGM11); // = 0b00000010;
|
||||
// clock select clk/1
|
||||
TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
|
||||
#else // hardware PWM
|
||||
TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
|
||||
#else // hardware PWM
|
||||
// Pin PB7 = OCR1C (Timer 1, Channel C)
|
||||
// Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
|
||||
// (i.e. start high, go low when counter matches.)
|
||||
@@ -430,8 +442,8 @@ void backlight_init_ports(void) {
|
||||
"In fast PWM mode, the compare units allow generation of PWM waveforms on the OCnx pins. Setting the COMnx1:0 bits to two will produce a non-inverted PWM [..]."
|
||||
"In fast PWM mode the counter is incremented until the counter value matches either one of the fixed values 0x00FF, 0x01FF, or 0x03FF (WGMn3:0 = 5, 6, or 7), the value in ICRn (WGMn3:0 = 14), or the value in OCRnA (WGMn3:0 = 15)."
|
||||
*/
|
||||
TCCRxA = _BV(COMxx1) | _BV(WGM11); // = 0b00001010;
|
||||
TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
|
||||
TCCRxA = _BV(COMxx1) | _BV(WGM11); // = 0b00001010;
|
||||
TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
|
||||
#endif
|
||||
|
||||
#ifdef BACKLIGHT_CUSTOM_RESOLUTION
|
||||
|
||||
@@ -53,14 +53,14 @@ static PWMConfig pwmCFG = {0xFFFF, /* PWM clock frequency */
|
||||
|
||||
// See http://jared.geek.nz/2013/feb/linear-led-pwm
|
||||
static uint16_t cie_lightness(uint16_t v) {
|
||||
if (v <= 5243) // if below 8% of max
|
||||
return v / 9; // same as dividing by 900%
|
||||
if (v <= 5243) // if below 8% of max
|
||||
return v / 9; // same as dividing by 900%
|
||||
else {
|
||||
uint32_t y = (((uint32_t)v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare
|
||||
uint32_t y = (((uint32_t)v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare
|
||||
// to get a useful result with integer division, we shift left in the expression above
|
||||
// and revert what we've done again after squaring.
|
||||
y = y * y * y >> 8;
|
||||
if (y > 0xFFFFUL) // prevent overflow
|
||||
if (y > 0xFFFFUL) // prevent overflow
|
||||
return 0xFFFFU;
|
||||
else
|
||||
return (uint16_t)y;
|
||||
@@ -117,7 +117,9 @@ static const uint8_t breathing_table[BREATHING_STEPS] = {0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
void breathing_callback(PWMDriver *pwmp);
|
||||
|
||||
bool is_breathing(void) { return pwmCFG.callback != NULL; }
|
||||
bool is_breathing(void) {
|
||||
return pwmCFG.callback != NULL;
|
||||
}
|
||||
|
||||
void breathing_enable(void) {
|
||||
pwmCFG.callback = breathing_callback;
|
||||
@@ -133,7 +135,9 @@ void breathing_disable(void) {
|
||||
}
|
||||
|
||||
// Use this before the cie_lightness function.
|
||||
static inline uint16_t scale_backlight(uint16_t v) { return v / BACKLIGHT_LEVELS * get_backlight_level(); }
|
||||
static inline uint16_t scale_backlight(uint16_t v) {
|
||||
return v / BACKLIGHT_LEVELS * get_backlight_level();
|
||||
}
|
||||
|
||||
void breathing_callback(PWMDriver *pwmp) {
|
||||
uint8_t breathing_period = get_breathing_period();
|
||||
|
||||
@@ -44,6 +44,10 @@ void backlight_pins_init(void) {
|
||||
FOR_EACH_LED(setPinOutput(backlight_pin); backlight_off(backlight_pin);)
|
||||
}
|
||||
|
||||
void backlight_pins_on(void) { FOR_EACH_LED(backlight_on(backlight_pin);) }
|
||||
void backlight_pins_on(void) {
|
||||
FOR_EACH_LED(backlight_on(backlight_pin);)
|
||||
}
|
||||
|
||||
void backlight_pins_off(void) { FOR_EACH_LED(backlight_off(backlight_pin);) }
|
||||
void backlight_pins_off(void) {
|
||||
FOR_EACH_LED(backlight_off(backlight_pin);)
|
||||
}
|
||||
|
||||
@@ -30,11 +30,17 @@ static const uint16_t backlight_duty_table[] = {
|
||||
|
||||
// clang-format on
|
||||
|
||||
static uint8_t scale_backlight(uint8_t v) { return v * (backlight_duty_table_size - 1) / BACKLIGHT_LEVELS; }
|
||||
static uint8_t scale_backlight(uint8_t v) {
|
||||
return v * (backlight_duty_table_size - 1) / BACKLIGHT_LEVELS;
|
||||
}
|
||||
|
||||
void backlight_init_ports(void) { backlight_pins_init(); }
|
||||
void backlight_init_ports(void) {
|
||||
backlight_pins_init();
|
||||
}
|
||||
|
||||
void backlight_set(uint8_t level) { s_duty_pattern = backlight_duty_table[scale_backlight(level)]; }
|
||||
void backlight_set(uint8_t level) {
|
||||
s_duty_pattern = backlight_duty_table[scale_backlight(level)];
|
||||
}
|
||||
|
||||
void backlight_task(void) {
|
||||
static uint8_t backlight_tick = 0;
|
||||
|
||||
@@ -14,14 +14,14 @@ static uint16_t backlight_timer_get_duty(void);
|
||||
|
||||
// See http://jared.geek.nz/2013/feb/linear-led-pwm
|
||||
static uint16_t cie_lightness(uint16_t v) {
|
||||
if (v <= 5243) // if below 8% of max
|
||||
return v / 9; // same as dividing by 900%
|
||||
if (v <= 5243) // if below 8% of max
|
||||
return v / 9; // same as dividing by 900%
|
||||
else {
|
||||
uint32_t y = (((uint32_t)v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare
|
||||
uint32_t y = (((uint32_t)v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare
|
||||
// to get a useful result with integer division, we shift left in the expression above
|
||||
// and revert what we've done again after squaring.
|
||||
y = y * y * y >> 8;
|
||||
if (y > 0xFFFFUL) // prevent overflow
|
||||
if (y > 0xFFFFUL) // prevent overflow
|
||||
return 0xFFFFU;
|
||||
else
|
||||
return (uint16_t)y;
|
||||
@@ -61,7 +61,9 @@ static void backlight_timer_top(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static void backlight_timer_cmp(void) { backlight_pins_off(); }
|
||||
static void backlight_timer_cmp(void) {
|
||||
backlight_pins_off();
|
||||
}
|
||||
|
||||
void backlight_task(void) {}
|
||||
|
||||
@@ -77,7 +79,9 @@ static uint16_t breathing_counter = 0;
|
||||
static const uint8_t breathing_table[BREATHING_STEPS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 17, 20, 24, 28, 32, 36, 41, 46, 51, 57, 63, 70, 76, 83, 91, 98, 106, 113, 121, 129, 138, 146, 154, 162, 170, 178, 185, 193, 200, 207, 213, 220, 225, 231, 235, 240, 244, 247, 250, 252, 253, 254, 255, 254, 253, 252, 250, 247, 244, 240, 235, 231, 225, 220, 213, 207, 200, 193, 185, 178, 170, 162, 154, 146, 138, 129, 121, 113, 106, 98, 91, 83, 76, 70, 63, 57, 51, 46, 41, 36, 32, 28, 24, 20, 17, 15, 12, 10, 8, 6, 5, 4, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
// Use this before the cie_lightness function.
|
||||
static inline uint16_t scale_backlight(uint16_t v) { return v / BACKLIGHT_LEVELS * get_backlight_level(); }
|
||||
static inline uint16_t scale_backlight(uint16_t v) {
|
||||
return v / BACKLIGHT_LEVELS * get_backlight_level();
|
||||
}
|
||||
|
||||
void breathing_task(void) {
|
||||
uint8_t breathing_period = get_breathing_period();
|
||||
@@ -91,13 +95,17 @@ void breathing_task(void) {
|
||||
backlight_timer_set_duty(cie_lightness(scale_backlight((uint16_t)breathing_table[index] * 256)));
|
||||
}
|
||||
|
||||
bool is_breathing(void) { return breathing; }
|
||||
bool is_breathing(void) {
|
||||
return breathing;
|
||||
}
|
||||
|
||||
void breathing_enable(void) {
|
||||
breathing_counter = 0;
|
||||
breathing = true;
|
||||
}
|
||||
void breathing_disable(void) { breathing = false; }
|
||||
void breathing_disable(void) {
|
||||
breathing = false;
|
||||
}
|
||||
|
||||
void breathing_pulse(void) {
|
||||
backlight_set(is_backlight_enabled() ? 0 : BACKLIGHT_LEVELS);
|
||||
@@ -140,8 +148,12 @@ static void timerCallback(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static void backlight_timer_set_duty(uint16_t duty) { s_duty = duty; }
|
||||
static uint16_t backlight_timer_get_duty(void) { return s_duty; }
|
||||
static void backlight_timer_set_duty(uint16_t duty) {
|
||||
s_duty = duty;
|
||||
}
|
||||
static uint16_t backlight_timer_get_duty(void) {
|
||||
return s_duty;
|
||||
}
|
||||
|
||||
// ChibiOS - Map GPT timer onto Software PWM
|
||||
static void gptTimerCallback(GPTDriver *gptp) {
|
||||
|
||||
@@ -20,7 +20,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// bit population - return number of on-bit
|
||||
__attribute__((noinline)) uint8_t bitpop(uint8_t bits) {
|
||||
uint8_t c;
|
||||
for (c = 0; bits; c++) bits &= bits - 1;
|
||||
for (c = 0; bits; c++)
|
||||
bits &= bits - 1;
|
||||
return c;
|
||||
/*
|
||||
const uint8_t bit_count[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
|
||||
@@ -30,13 +31,15 @@ __attribute__((noinline)) uint8_t bitpop(uint8_t bits) {
|
||||
|
||||
uint8_t bitpop16(uint16_t bits) {
|
||||
uint8_t c;
|
||||
for (c = 0; bits; c++) bits &= bits - 1;
|
||||
for (c = 0; bits; c++)
|
||||
bits &= bits - 1;
|
||||
return c;
|
||||
}
|
||||
|
||||
uint8_t bitpop32(uint32_t bits) {
|
||||
uint8_t c;
|
||||
for (c = 0; bits; c++) bits &= bits - 1;
|
||||
for (c = 0; bits; c++)
|
||||
bits &= bits - 1;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
*
|
||||
* ...just incase someone wants to only change the eeprom behaviour
|
||||
*/
|
||||
__attribute__((weak)) void bootmagic_lite_reset_eeprom(void) { eeconfig_disable(); }
|
||||
__attribute__((weak)) void bootmagic_lite_reset_eeprom(void) {
|
||||
eeconfig_disable();
|
||||
}
|
||||
|
||||
/** \brief The lite version of TMK's bootmagic based on Wilba.
|
||||
*
|
||||
@@ -57,4 +59,6 @@ __attribute__((weak)) void bootmagic_lite(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void bootmagic(void) { bootmagic_lite(); }
|
||||
void bootmagic(void) {
|
||||
bootmagic_lite();
|
||||
}
|
||||
|
||||
@@ -104,7 +104,9 @@ RGB hsv_to_rgb(HSV hsv) {
|
||||
#endif
|
||||
}
|
||||
|
||||
RGB hsv_to_rgb_nocie(HSV hsv) { return hsv_to_rgb_impl(hsv, false); }
|
||||
RGB hsv_to_rgb_nocie(HSV hsv) {
|
||||
return hsv_to_rgb_impl(hsv, false);
|
||||
}
|
||||
|
||||
#ifdef RGBW
|
||||
# ifndef MIN
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
#define HSV_GOLDENROD 30, 218, 218
|
||||
#define HSV_GREEN 85, 255, 255
|
||||
#define HSV_MAGENTA 213, 255, 255
|
||||
#define HSV_ORANGE 28, 255, 255
|
||||
#define HSV_ORANGE 21, 255, 255
|
||||
#define HSV_PINK 234, 128, 255
|
||||
#define HSV_PURPLE 191, 255, 255
|
||||
#define HSV_RED 0, 255, 255
|
||||
|
||||
@@ -453,7 +453,7 @@ static bool command_common(uint8_t code) {
|
||||
|
||||
// NKRO toggle
|
||||
case MAGIC_KC(MAGIC_KEY_NKRO):
|
||||
clear_keyboard(); // clear to prevent stuck keys
|
||||
clear_keyboard(); // clear to prevent stuck keys
|
||||
keymap_config.nkro = !keymap_config.nkro;
|
||||
if (keymap_config.nkro) {
|
||||
print("NKRO: on\n");
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
// changed is true if raw has changed since the last call
|
||||
void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed);
|
||||
|
||||
bool debounce_active(void);
|
||||
|
||||
void debounce_init(uint8_t num_rows);
|
||||
|
||||
void debounce_free(void);
|
||||
|
||||
@@ -165,7 +165,6 @@ static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], ui
|
||||
}
|
||||
}
|
||||
|
||||
bool debounce_active(void) { return true; }
|
||||
#else
|
||||
# include "none.c"
|
||||
#endif
|
||||
|
||||
@@ -26,6 +26,4 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
|
||||
}
|
||||
}
|
||||
|
||||
bool debounce_active(void) { return false; }
|
||||
|
||||
void debounce_free(void) {}
|
||||
|
||||
@@ -44,9 +44,7 @@ void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool
|
||||
}
|
||||
}
|
||||
|
||||
bool debounce_active(void) { return debouncing; }
|
||||
|
||||
void debounce_free(void) {}
|
||||
#else // no debouncing.
|
||||
#else // no debouncing.
|
||||
# include "none.c"
|
||||
#endif
|
||||
|
||||
@@ -134,7 +134,6 @@ static void start_debounce_counters(matrix_row_t raw[], matrix_row_t cooked[], u
|
||||
}
|
||||
}
|
||||
|
||||
bool debounce_active(void) { return true; }
|
||||
#else
|
||||
# include "none.c"
|
||||
#endif
|
||||
|
||||
74
quantum/debounce/sym_defer_pr.c
Normal file
74
quantum/debounce/sym_defer_pr.c
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright 2021 Chad Austin <chad@chadaustin.me>
|
||||
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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
Symmetric per-row debounce algorithm. Changes only apply when
|
||||
DEBOUNCE milliseconds have elapsed since the last change.
|
||||
*/
|
||||
|
||||
#include "matrix.h"
|
||||
#include "timer.h"
|
||||
#include "quantum.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef DEBOUNCE
|
||||
# define DEBOUNCE 5
|
||||
#endif
|
||||
|
||||
static uint16_t last_time;
|
||||
// [row] milliseconds until key's state is considered debounced.
|
||||
static uint8_t* countdowns;
|
||||
// [row]
|
||||
static matrix_row_t* last_raw;
|
||||
|
||||
void debounce_init(uint8_t num_rows) {
|
||||
countdowns = (uint8_t*)calloc(num_rows, sizeof(uint8_t));
|
||||
last_raw = (matrix_row_t*)calloc(num_rows, sizeof(matrix_row_t));
|
||||
|
||||
last_time = timer_read();
|
||||
}
|
||||
|
||||
void debounce_free(void) {
|
||||
free(countdowns);
|
||||
countdowns = NULL;
|
||||
free(last_raw);
|
||||
last_raw = NULL;
|
||||
}
|
||||
|
||||
void debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) {
|
||||
uint16_t now = timer_read();
|
||||
uint16_t elapsed16 = TIMER_DIFF_16(now, last_time);
|
||||
last_time = now;
|
||||
uint8_t elapsed = (elapsed16 > 255) ? 255 : elapsed16;
|
||||
|
||||
uint8_t* countdown = countdowns;
|
||||
|
||||
for (uint8_t row = 0; row < num_rows; ++row, ++countdown) {
|
||||
matrix_row_t raw_row = raw[row];
|
||||
|
||||
if (raw_row != last_raw[row]) {
|
||||
*countdown = DEBOUNCE;
|
||||
last_raw[row] = raw_row;
|
||||
} else if (*countdown > elapsed) {
|
||||
*countdown -= elapsed;
|
||||
} else if (*countdown) {
|
||||
cooked[row] = raw_row;
|
||||
*countdown = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool debounce_active(void) {
|
||||
return true;
|
||||
}
|
||||
@@ -131,7 +131,7 @@ static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], ui
|
||||
if (*debounce_pointer == DEBOUNCE_ELAPSED) {
|
||||
*debounce_pointer = DEBOUNCE;
|
||||
counters_need_update = true;
|
||||
existing_row ^= col_mask; // flip the bit.
|
||||
existing_row ^= col_mask; // flip the bit.
|
||||
}
|
||||
}
|
||||
debounce_pointer++;
|
||||
@@ -140,7 +140,6 @@ static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], ui
|
||||
}
|
||||
}
|
||||
|
||||
bool debounce_active(void) { return true; }
|
||||
#else
|
||||
# include "none.c"
|
||||
#endif
|
||||
|
||||
@@ -132,7 +132,6 @@ static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], ui
|
||||
}
|
||||
}
|
||||
|
||||
bool debounce_active(void) { return true; }
|
||||
#else
|
||||
# include "none.c"
|
||||
#endif
|
||||
|
||||
@@ -31,7 +31,9 @@ void set_time(uint32_t t);
|
||||
void advance_time(uint32_t ms);
|
||||
}
|
||||
|
||||
void DebounceTest::addEvents(std::initializer_list<DebounceTestEvent> events) { events_.insert(events_.end(), events.begin(), events.end()); }
|
||||
void DebounceTest::addEvents(std::initializer_list<DebounceTestEvent> events) {
|
||||
events_.insert(events_.end(), events.begin(), events.end());
|
||||
}
|
||||
|
||||
void DebounceTest::runEvents() {
|
||||
/* Run the test multiple times, from 1kHz to 10kHz scan rate */
|
||||
|
||||
@@ -28,6 +28,11 @@ debounce_sym_defer_pk_SRC := $(DEBOUNCE_COMMON_SRC) \
|
||||
$(QUANTUM_PATH)/debounce/sym_defer_pk.c \
|
||||
$(QUANTUM_PATH)/debounce/tests/sym_defer_pk_tests.cpp
|
||||
|
||||
debounce_sym_defer_pr_DEFS := $(DEBOUNCE_COMMON_DEFS)
|
||||
debounce_sym_defer_pr_SRC := $(DEBOUNCE_COMMON_SRC) \
|
||||
$(QUANTUM_PATH)/debounce/sym_defer_pr.c \
|
||||
$(QUANTUM_PATH)/debounce/tests/sym_defer_pr_tests.cpp
|
||||
|
||||
debounce_sym_eager_pk_DEFS := $(DEBOUNCE_COMMON_DEFS)
|
||||
debounce_sym_eager_pk_SRC := $(DEBOUNCE_COMMON_SRC) \
|
||||
$(QUANTUM_PATH)/debounce/sym_eager_pk.c \
|
||||
|
||||
238
quantum/debounce/tests/sym_defer_pr_tests.cpp
Normal file
238
quantum/debounce/tests/sym_defer_pr_tests.cpp
Normal file
@@ -0,0 +1,238 @@
|
||||
/* Copyright 2021 Simon Arlott
|
||||
*
|
||||
* 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 "gtest/gtest.h"
|
||||
|
||||
#include "debounce_test_common.h"
|
||||
|
||||
TEST_F(DebounceTest, OneKeyShort1) {
|
||||
addEvents({
|
||||
/* Time, Inputs, Outputs */
|
||||
{0, {{0, 1, DOWN}}, {}},
|
||||
|
||||
{5, {}, {{0, 1, DOWN}}},
|
||||
/* 0ms delay (fast scan rate) */
|
||||
{5, {{0, 1, UP}}, {}},
|
||||
|
||||
{10, {}, {{0, 1, UP}}},
|
||||
});
|
||||
runEvents();
|
||||
}
|
||||
|
||||
TEST_F(DebounceTest, OneKeyShort2) {
|
||||
addEvents({
|
||||
/* Time, Inputs, Outputs */
|
||||
{0, {{0, 1, DOWN}}, {}},
|
||||
|
||||
{5, {}, {{0, 1, DOWN}}},
|
||||
/* 1ms delay */
|
||||
{6, {{0, 1, UP}}, {}},
|
||||
|
||||
{11, {}, {{0, 1, UP}}},
|
||||
});
|
||||
runEvents();
|
||||
}
|
||||
|
||||
TEST_F(DebounceTest, OneKeyShort3) {
|
||||
addEvents({
|
||||
/* Time, Inputs, Outputs */
|
||||
{0, {{0, 1, DOWN}}, {}},
|
||||
|
||||
{5, {}, {{0, 1, DOWN}}},
|
||||
/* 2ms delay */
|
||||
{7, {{0, 1, UP}}, {}},
|
||||
|
||||
{12, {}, {{0, 1, UP}}},
|
||||
});
|
||||
runEvents();
|
||||
}
|
||||
|
||||
TEST_F(DebounceTest, OneKeyTooQuick1) {
|
||||
addEvents({
|
||||
/* Time, Inputs, Outputs */
|
||||
{0, {{0, 1, DOWN}}, {}},
|
||||
/* Release key exactly on the debounce time */
|
||||
{5, {{0, 1, UP}}, {}},
|
||||
});
|
||||
runEvents();
|
||||
}
|
||||
|
||||
TEST_F(DebounceTest, OneKeyTooQuick2) {
|
||||
addEvents({
|
||||
/* Time, Inputs, Outputs */
|
||||
{0, {{0, 1, DOWN}}, {}},
|
||||
|
||||
{5, {}, {{0, 1, DOWN}}},
|
||||
{6, {{0, 1, UP}}, {}},
|
||||
|
||||
/* Press key exactly on the debounce time */
|
||||
{11, {{0, 1, DOWN}}, {}},
|
||||
});
|
||||
runEvents();
|
||||
}
|
||||
|
||||
TEST_F(DebounceTest, OneKeyBouncing1) {
|
||||
addEvents({
|
||||
/* Time, Inputs, Outputs */
|
||||
{0, {{0, 1, DOWN}}, {}},
|
||||
{1, {{0, 1, UP}}, {}},
|
||||
{2, {{0, 1, DOWN}}, {}},
|
||||
{3, {{0, 1, UP}}, {}},
|
||||
{4, {{0, 1, DOWN}}, {}},
|
||||
{5, {{0, 1, UP}}, {}},
|
||||
{6, {{0, 1, DOWN}}, {}},
|
||||
{11, {}, {{0, 1, DOWN}}}, /* 5ms after DOWN at time 7 */
|
||||
});
|
||||
runEvents();
|
||||
}
|
||||
|
||||
TEST_F(DebounceTest, OneKeyBouncing2) {
|
||||
addEvents({
|
||||
/* Time, Inputs, Outputs */
|
||||
{0, {{0, 1, DOWN}}, {}},
|
||||
{5, {}, {{0, 1, DOWN}}},
|
||||
{6, {{0, 1, UP}}, {}},
|
||||
{7, {{0, 1, DOWN}}, {}},
|
||||
{8, {{0, 1, UP}}, {}},
|
||||
{9, {{0, 1, DOWN}}, {}},
|
||||
{10, {{0, 1, UP}}, {}},
|
||||
{15, {}, {{0, 1, UP}}}, /* 5ms after UP at time 10 */
|
||||
});
|
||||
runEvents();
|
||||
}
|
||||
|
||||
TEST_F(DebounceTest, OneKeyLong) {
|
||||
addEvents({
|
||||
/* Time, Inputs, Outputs */
|
||||
{0, {{0, 1, DOWN}}, {}},
|
||||
|
||||
{5, {}, {{0, 1, DOWN}}},
|
||||
|
||||
{25, {{0, 1, UP}}, {}},
|
||||
|
||||
{30, {}, {{0, 1, UP}}},
|
||||
|
||||
{50, {{0, 1, DOWN}}, {}},
|
||||
|
||||
{55, {}, {{0, 1, DOWN}}},
|
||||
});
|
||||
runEvents();
|
||||
}
|
||||
|
||||
TEST_F(DebounceTest, TwoKeysShort) {
|
||||
addEvents({
|
||||
/* Time, Inputs, Outputs */
|
||||
{0, {{0, 1, DOWN}}, {}},
|
||||
{1, {{0, 2, DOWN}}, {}},
|
||||
|
||||
{6, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
|
||||
|
||||
{7, {{0, 1, UP}}, {}},
|
||||
{8, {{0, 2, UP}}, {}},
|
||||
|
||||
{13, {}, {{0, 1, UP}, {0, 2, UP}}},
|
||||
});
|
||||
runEvents();
|
||||
}
|
||||
|
||||
TEST_F(DebounceTest, TwoKeysSimultaneous1) {
|
||||
addEvents({
|
||||
/* Time, Inputs, Outputs */
|
||||
{0, {{0, 1, DOWN}, {0, 2, DOWN}}, {}},
|
||||
|
||||
{5, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
|
||||
{6, {{0, 1, UP}, {0, 2, UP}}, {}},
|
||||
|
||||
{11, {}, {{0, 1, UP}, {0, 2, UP}}},
|
||||
});
|
||||
runEvents();
|
||||
}
|
||||
|
||||
TEST_F(DebounceTest, TwoKeysSimultaneous2) {
|
||||
addEvents({
|
||||
/* Time, Inputs, Outputs */
|
||||
{0, {{0, 1, DOWN}}, {}},
|
||||
{1, {{0, 2, DOWN}}, {}},
|
||||
|
||||
{6, {}, {{0, 1, DOWN}, {0, 2, DOWN}}},
|
||||
{7, {{0, 2, UP}}, {}},
|
||||
{9, {{0, 1, UP}}, {}},
|
||||
|
||||
// Debouncing loses the specific ordering -- both events report simultaneously.
|
||||
{14, {}, {{0, 1, UP}, {0, 2, UP}}},
|
||||
});
|
||||
runEvents();
|
||||
}
|
||||
|
||||
TEST_F(DebounceTest, OneKeyDelayedScan1) {
|
||||
addEvents({
|
||||
/* Time, Inputs, Outputs */
|
||||
{0, {{0, 1, DOWN}}, {}},
|
||||
|
||||
/* Processing is very late */
|
||||
{300, {}, {{0, 1, DOWN}}},
|
||||
/* Immediately release key */
|
||||
{300, {{0, 1, UP}}, {}},
|
||||
|
||||
{305, {}, {{0, 1, UP}}},
|
||||
});
|
||||
time_jumps_ = true;
|
||||
runEvents();
|
||||
}
|
||||
|
||||
TEST_F(DebounceTest, OneKeyDelayedScan2) {
|
||||
addEvents({
|
||||
/* Time, Inputs, Outputs */
|
||||
{0, {{0, 1, DOWN}}, {}},
|
||||
|
||||
/* Processing is very late */
|
||||
{300, {}, {{0, 1, DOWN}}},
|
||||
/* Release key after 1ms */
|
||||
{301, {{0, 1, UP}}, {}},
|
||||
|
||||
{306, {}, {{0, 1, UP}}},
|
||||
});
|
||||
time_jumps_ = true;
|
||||
runEvents();
|
||||
}
|
||||
|
||||
TEST_F(DebounceTest, OneKeyDelayedScan3) {
|
||||
addEvents({
|
||||
/* Time, Inputs, Outputs */
|
||||
{0, {{0, 1, DOWN}}, {}},
|
||||
|
||||
/* Release key before debounce expires */
|
||||
{300, {{0, 1, UP}}, {}},
|
||||
});
|
||||
time_jumps_ = true;
|
||||
runEvents();
|
||||
}
|
||||
|
||||
TEST_F(DebounceTest, OneKeyDelayedScan4) {
|
||||
addEvents({
|
||||
/* Time, Inputs, Outputs */
|
||||
{0, {{0, 1, DOWN}}, {}},
|
||||
|
||||
/* Processing is a bit late */
|
||||
{50, {}, {{0, 1, DOWN}}},
|
||||
/* Release key after 1ms */
|
||||
{51, {{0, 1, UP}}, {}},
|
||||
|
||||
{56, {}, {{0, 1, UP}}},
|
||||
});
|
||||
time_jumps_ = true;
|
||||
runEvents();
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
TEST_LIST += \
|
||||
debounce_sym_defer_g \
|
||||
debounce_sym_defer_pk \
|
||||
debounce_sym_defer_pr \
|
||||
debounce_sym_eager_pk \
|
||||
debounce_sym_eager_pr \
|
||||
debounce_asym_eager_defer_pk
|
||||
|
||||
@@ -9,32 +9,27 @@
|
||||
# define MAX_DEFERRED_EXECUTORS 8
|
||||
#endif
|
||||
|
||||
typedef struct deferred_executor_t {
|
||||
deferred_token token;
|
||||
uint32_t trigger_time;
|
||||
deferred_exec_callback callback;
|
||||
void * cb_arg;
|
||||
} deferred_executor_t;
|
||||
//------------------------------------
|
||||
// Helpers
|
||||
//
|
||||
|
||||
static deferred_token current_token = 0;
|
||||
static uint32_t last_deferred_exec_check = 0;
|
||||
static deferred_executor_t executors[MAX_DEFERRED_EXECUTORS] = {0};
|
||||
static deferred_token current_token = 0;
|
||||
|
||||
static inline bool token_can_be_used(deferred_token token) {
|
||||
static inline bool token_can_be_used(deferred_executor_t *table, size_t table_count, deferred_token token) {
|
||||
if (token == INVALID_DEFERRED_TOKEN) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) {
|
||||
if (executors[i].token == token) {
|
||||
for (int i = 0; i < table_count; ++i) {
|
||||
if (table[i].token == token) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline deferred_token allocate_token(void) {
|
||||
static inline deferred_token allocate_token(deferred_executor_t *table, size_t table_count) {
|
||||
deferred_token first = ++current_token;
|
||||
while (!token_can_be_used(current_token)) {
|
||||
while (!token_can_be_used(table, table_count, current_token)) {
|
||||
++current_token;
|
||||
if (current_token == first) {
|
||||
// If we've looped back around to the first, everything is already allocated (yikes!). Need to exit with a failure.
|
||||
@@ -44,18 +39,22 @@ static inline deferred_token allocate_token(void) {
|
||||
return current_token;
|
||||
}
|
||||
|
||||
deferred_token defer_exec(uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg) {
|
||||
// Ignore queueing if it's a zero-time delay, or invalid callback
|
||||
if (delay_ms == 0 || !callback) {
|
||||
//------------------------------------
|
||||
// Advanced API: used when a custom-allocated table is used, primarily for core code.
|
||||
//
|
||||
|
||||
deferred_token defer_exec_advanced(deferred_executor_t *table, size_t table_count, uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg) {
|
||||
// Ignore queueing if the table isn't valid, it's a zero-time delay, or the token is not valid
|
||||
if (!table || table_count == 0 || delay_ms == 0 || !callback) {
|
||||
return INVALID_DEFERRED_TOKEN;
|
||||
}
|
||||
|
||||
// Find an unused slot and claim it
|
||||
for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) {
|
||||
deferred_executor_t *entry = &executors[i];
|
||||
for (int i = 0; i < table_count; ++i) {
|
||||
deferred_executor_t *entry = &table[i];
|
||||
if (entry->token == INVALID_DEFERRED_TOKEN) {
|
||||
// Work out the new token value, dropping out if none were available
|
||||
deferred_token token = allocate_token();
|
||||
deferred_token token = allocate_token(table, table_count);
|
||||
if (token == INVALID_DEFERRED_TOKEN) {
|
||||
return false;
|
||||
}
|
||||
@@ -73,15 +72,15 @@ deferred_token defer_exec(uint32_t delay_ms, deferred_exec_callback callback, vo
|
||||
return INVALID_DEFERRED_TOKEN;
|
||||
}
|
||||
|
||||
bool extend_deferred_exec(deferred_token token, uint32_t delay_ms) {
|
||||
// Ignore queueing if it's a zero-time delay, or the token is not valid
|
||||
if (delay_ms == 0 || token == INVALID_DEFERRED_TOKEN) {
|
||||
bool extend_deferred_exec_advanced(deferred_executor_t *table, size_t table_count, deferred_token token, uint32_t delay_ms) {
|
||||
// Ignore queueing if the table isn't valid, it's a zero-time delay, or the token is not valid
|
||||
if (!table || table_count == 0 || delay_ms == 0 || token == INVALID_DEFERRED_TOKEN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find the entry corresponding to the token
|
||||
for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) {
|
||||
deferred_executor_t *entry = &executors[i];
|
||||
for (int i = 0; i < table_count; ++i) {
|
||||
deferred_executor_t *entry = &table[i];
|
||||
if (entry->token == token) {
|
||||
// Found it, extend the delay
|
||||
entry->trigger_time = timer_read32() + delay_ms;
|
||||
@@ -93,15 +92,15 @@ bool extend_deferred_exec(deferred_token token, uint32_t delay_ms) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cancel_deferred_exec(deferred_token token) {
|
||||
// Ignore request if the token is not valid
|
||||
if (token == INVALID_DEFERRED_TOKEN) {
|
||||
bool cancel_deferred_exec_advanced(deferred_executor_t *table, size_t table_count, deferred_token token) {
|
||||
// Ignore request if the table/token are not valid
|
||||
if (!table || table_count == 0 || token == INVALID_DEFERRED_TOKEN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find the entry corresponding to the token
|
||||
for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) {
|
||||
deferred_executor_t *entry = &executors[i];
|
||||
for (int i = 0; i < table_count; ++i) {
|
||||
deferred_executor_t *entry = &table[i];
|
||||
if (entry->token == token) {
|
||||
// Found it, cancel and clear the table entry
|
||||
entry->token = INVALID_DEFERRED_TOKEN;
|
||||
@@ -116,16 +115,16 @@ bool cancel_deferred_exec(deferred_token token) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void deferred_exec_task(void) {
|
||||
void deferred_exec_advanced_task(deferred_executor_t *table, size_t table_count, uint32_t *last_execution_time) {
|
||||
uint32_t now = timer_read32();
|
||||
|
||||
// Throttle only once per millisecond
|
||||
if (((int32_t)TIMER_DIFF_32(now, last_deferred_exec_check)) > 0) {
|
||||
last_deferred_exec_check = now;
|
||||
if (((int32_t)TIMER_DIFF_32(now, (*last_execution_time))) > 0) {
|
||||
*last_execution_time = now;
|
||||
|
||||
// Run through each of the executors
|
||||
for (int i = 0; i < MAX_DEFERRED_EXECUTORS; ++i) {
|
||||
deferred_executor_t *entry = &executors[i];
|
||||
for (int i = 0; i < table_count; ++i) {
|
||||
deferred_executor_t *entry = &table[i];
|
||||
|
||||
// Check if we're supposed to execute this entry
|
||||
if (entry->token != INVALID_DEFERRED_TOKEN && ((int32_t)TIMER_DIFF_32(entry->trigger_time, now)) <= 0) {
|
||||
@@ -150,3 +149,23 @@ void deferred_exec_task(void) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
// Basic API: used by user-mode code, guaranteed to not collide with core deferred execution
|
||||
//
|
||||
|
||||
static uint32_t last_deferred_exec_check = 0;
|
||||
static deferred_executor_t basic_executors[MAX_DEFERRED_EXECUTORS] = {0};
|
||||
|
||||
deferred_token defer_exec(uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg) {
|
||||
return defer_exec_advanced(basic_executors, MAX_DEFERRED_EXECUTORS, delay_ms, callback, cb_arg);
|
||||
}
|
||||
bool extend_deferred_exec(deferred_token token, uint32_t delay_ms) {
|
||||
return extend_deferred_exec_advanced(basic_executors, MAX_DEFERRED_EXECUTORS, token, delay_ms);
|
||||
}
|
||||
bool cancel_deferred_exec(deferred_token token) {
|
||||
return cancel_deferred_exec_advanced(basic_executors, MAX_DEFERRED_EXECUTORS, token);
|
||||
}
|
||||
void deferred_exec_task(void) {
|
||||
deferred_exec_advanced_task(basic_executors, MAX_DEFERRED_EXECUTORS, &last_deferred_exec_check);
|
||||
}
|
||||
|
||||
@@ -5,34 +5,117 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// A token that can be used to cancel an existing deferred execution.
|
||||
//------------------------------------
|
||||
// Common
|
||||
//------------------------------------
|
||||
|
||||
/**
|
||||
* @typedef A token that can be used to cancel or extend an existing deferred execution.
|
||||
*/
|
||||
typedef uint8_t deferred_token;
|
||||
|
||||
/**
|
||||
* @def The constant used to denote an invalid deferred execution token.
|
||||
*/
|
||||
#define INVALID_DEFERRED_TOKEN 0
|
||||
|
||||
// Callback to execute.
|
||||
// -- Parameter trigger_time: the intended trigger time to execute the callback -- equivalent time-space as timer_read32()
|
||||
// cb_arg: the callback argument specified when enqueueing the deferred executor
|
||||
// -- Return value: Non-zero re-queues the callback to execute after the returned number of milliseconds. Zero cancels repeated execution.
|
||||
/**
|
||||
* @typedef Callback to execute.
|
||||
* @param trigger_time[in] the intended trigger time to execute the callback -- equivalent time-space as timer_read32()
|
||||
* @param cb_arg[in] the callback argument specified when enqueueing the deferred executor
|
||||
* @return non-zero re-queues the callback to execute after the returned number of milliseconds. Zero cancels repeated execution.
|
||||
*/
|
||||
typedef uint32_t (*deferred_exec_callback)(uint32_t trigger_time, void *cb_arg);
|
||||
|
||||
// Configures the supplied deferred executor to be executed after the required number of milliseconds.
|
||||
// -- Parameter delay_ms: the number of milliseconds before executing the callback
|
||||
// -- callback: the executor to invoke
|
||||
// -- cb_arg: the argument to pass to the executor, may be NULL if unused by the executor
|
||||
// -- Return value: a token usable for cancellation, or INVALID_DEFERRED_TOKEN if an error occurred
|
||||
//------------------------------------
|
||||
// Basic API: used by user-mode code, guaranteed to not collide with core deferred execution
|
||||
//------------------------------------
|
||||
|
||||
/**
|
||||
* Configures the supplied deferred executor to be executed after the required number of milliseconds.
|
||||
*
|
||||
* @param delay_ms[in] the number of milliseconds before executing the callback
|
||||
* @param callback[in] the executor to invoke
|
||||
* @param cb_arg[in] the argument to pass to the executor, may be NULL if unused by the executor
|
||||
* @return a token usable for extension/cancellation, or INVALID_DEFERRED_TOKEN if an error occurred
|
||||
*/
|
||||
deferred_token defer_exec(uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg);
|
||||
|
||||
// Allows for extending the timeframe before an existing deferred execution is invoked.
|
||||
// -- Parameter token: the returned value from defer_exec for the deferred execution you wish to extend.
|
||||
// -- delay_ms: the new delay (with respect to the current time)
|
||||
// -- Return value: if the token was found, and the delay was extended
|
||||
/**
|
||||
* Allows for extending the timeframe before an existing deferred execution is invoked.
|
||||
*
|
||||
* @param token[in] the returned value from defer_exec for the deferred execution you wish to extend
|
||||
* @param delay_ms[in] the number of milliseconds before executing the callback
|
||||
* @return true if the token was extended successfully, otherwise false
|
||||
*/
|
||||
bool extend_deferred_exec(deferred_token token, uint32_t delay_ms);
|
||||
|
||||
// Allows for cancellation of an existing deferred execution.
|
||||
// -- Parameter token: the returned value from defer_exec for the deferred execution you wish to cancel.
|
||||
// -- Return value: if the token was found, and the executor was cancelled
|
||||
/**
|
||||
* Allows for cancellation of an existing deferred execution.
|
||||
*
|
||||
* @param token[in] the returned value from defer_exec for the deferred execution you wish to cancel
|
||||
* @return true if the token was cancelled successfully, otherwise false
|
||||
*/
|
||||
bool cancel_deferred_exec(deferred_token token);
|
||||
|
||||
// Forward declaration for the main loop in order to execute any deferred executors. Should not be invoked by keyboard/user code.
|
||||
/**
|
||||
* Forward declaration for the main loop in order to execute any deferred executors. Should not be invoked by keyboard/user code.
|
||||
*/
|
||||
void deferred_exec_task(void);
|
||||
|
||||
//------------------------------------
|
||||
// Advanced API: used when a custom-allocated table is used, primarily for core code.
|
||||
//------------------------------------
|
||||
|
||||
/**
|
||||
* @struct Structure for containing self-hosted deferred executor tables.
|
||||
* @brief Core-side code can use this to create their own tables without impacting on the use of users' ability to add deferred execution.
|
||||
* Code outside deferred_exec.c should not worry about internals of this struct, and should just allocate the required number in an array.
|
||||
*/
|
||||
typedef struct deferred_executor_t {
|
||||
deferred_token token;
|
||||
uint32_t trigger_time;
|
||||
deferred_exec_callback callback;
|
||||
void * cb_arg;
|
||||
} deferred_executor_t;
|
||||
|
||||
/**
|
||||
* Configures the supplied deferred executor to be executed after the required number of milliseconds.
|
||||
*
|
||||
* @param table[in] the custom table used for storage
|
||||
* @param table_count[in] the number of available items in the table
|
||||
* @param delay_ms[in] the number of milliseconds before executing the callback
|
||||
* @param callback[in] the executor to invoke
|
||||
* @param cb_arg[in] the argument to pass to the executor, may be NULL if unused by the executor
|
||||
* @return a token usable for extension/cancellation, or INVALID_DEFERRED_TOKEN if an error occurred
|
||||
*/
|
||||
deferred_token defer_exec_advanced(deferred_executor_t *table, size_t table_count, uint32_t delay_ms, deferred_exec_callback callback, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Allows for extending the timeframe before an existing deferred execution is invoked.
|
||||
*
|
||||
* @param token[in] the returned value from defer_exec for the deferred execution you wish to extend
|
||||
* @param delay_ms[in] the number of milliseconds before executing the callback
|
||||
* @return true if the token was extended successfully, otherwise false
|
||||
*/
|
||||
bool extend_deferred_exec_advanced(deferred_executor_t *table, size_t table_count, deferred_token token, uint32_t delay_ms);
|
||||
|
||||
/**
|
||||
* Allows for cancellation of an existing deferred execution.
|
||||
*
|
||||
* @param token[in] the returned value from defer_exec for the deferred execution you wish to cancel
|
||||
* @return true if the token was cancelled successfully, otherwise false
|
||||
*/
|
||||
bool cancel_deferred_exec_advanced(deferred_executor_t *table, size_t table_count, deferred_token token);
|
||||
|
||||
/**
|
||||
* Forward declaration for the main loop in order to execute any custom table deferred executors. Should not be invoked by keyboard/user code.
|
||||
* Needed for any custom-allocated deferred execution tables. Any core tasks should add appropriate invocation to quantum/main.c.
|
||||
*
|
||||
* @param table[in] the custom table used for storage
|
||||
* @param table_count[in] the number of available items in the table
|
||||
* @param last_execution_time[in,out] the last execution time -- this will be checked first to determine if execution is needed, and updated if execution occurred
|
||||
*/
|
||||
void deferred_exec_advanced_task(deferred_executor_t *table, size_t table_count, uint32_t *last_execution_time);
|
||||
|
||||
@@ -24,9 +24,13 @@ __attribute__((weak)) void digitizer_send(void) {
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((weak)) void digitizer_task(void) { digitizer_send(); }
|
||||
__attribute__((weak)) void digitizer_task(void) {
|
||||
digitizer_send();
|
||||
}
|
||||
|
||||
digitizer_t digitizer_get_report(void) { return digitizerReport; }
|
||||
digitizer_t digitizer_get_report(void) {
|
||||
return digitizerReport;
|
||||
}
|
||||
|
||||
void digitizer_set_report(digitizer_t newDigitizerReport) {
|
||||
digitizerReport = newDigitizerReport;
|
||||
|
||||
@@ -52,13 +52,21 @@ static uint16_t scan_count;
|
||||
static bool dip_switch_state[NUMBER_OF_DIP_SWITCHES] = {0};
|
||||
static bool last_dip_switch_state[NUMBER_OF_DIP_SWITCHES] = {0};
|
||||
|
||||
__attribute__((weak)) bool dip_switch_update_user(uint8_t index, bool active) { return true; }
|
||||
__attribute__((weak)) bool dip_switch_update_user(uint8_t index, bool active) {
|
||||
return true;
|
||||
}
|
||||
|
||||
__attribute__((weak)) bool dip_switch_update_kb(uint8_t index, bool active) { return dip_switch_update_user(index, active); }
|
||||
__attribute__((weak)) bool dip_switch_update_kb(uint8_t index, bool active) {
|
||||
return dip_switch_update_user(index, active);
|
||||
}
|
||||
|
||||
__attribute__((weak)) bool dip_switch_update_mask_user(uint32_t state) { return true; }
|
||||
__attribute__((weak)) bool dip_switch_update_mask_user(uint32_t state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
__attribute__((weak)) bool dip_switch_update_mask_kb(uint32_t state) { return dip_switch_update_mask_user(state); }
|
||||
__attribute__((weak)) bool dip_switch_update_mask_kb(uint32_t state) {
|
||||
return dip_switch_update_mask_user(state);
|
||||
}
|
||||
|
||||
void dip_switch_init(void) {
|
||||
#ifdef DIP_SWITCH_PINS
|
||||
|
||||
@@ -14,14 +14,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "keymap.h" // to get keymaps[][][]
|
||||
#include "keymap.h" // to get keymaps[][][]
|
||||
#include "eeprom.h"
|
||||
#include "progmem.h" // to read default from flash
|
||||
#include "quantum.h" // for send_string()
|
||||
#include "progmem.h" // to read default from flash
|
||||
#include "quantum.h" // for send_string()
|
||||
#include "dynamic_keymap.h"
|
||||
#include "via.h" // for default VIA_EEPROM_ADDR_END
|
||||
#include "dynamic_keymap_eeprom.h"
|
||||
#include "via.h" // for default VIA_EEPROM_ADDR_END
|
||||
|
||||
#ifdef VIAL_ENABLE
|
||||
#include "vial.h"
|
||||
@@ -31,8 +29,22 @@
|
||||
# define DYNAMIC_KEYMAP_MACRO_COUNT 16
|
||||
#endif
|
||||
|
||||
#ifndef TOTAL_EEPROM_BYTE_COUNT
|
||||
# error Unknown total EEPROM size. Cannot derive maximum for dynamic keymaps.
|
||||
#endif
|
||||
|
||||
#ifndef DYNAMIC_KEYMAP_EEPROM_MAX_ADDR
|
||||
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR (TOTAL_EEPROM_BYTE_COUNT - 1)
|
||||
#endif
|
||||
|
||||
#if DYNAMIC_KEYMAP_EEPROM_MAX_ADDR > (TOTAL_EEPROM_BYTE_COUNT - 1)
|
||||
# pragma message STR(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR) " > " STR((TOTAL_EEPROM_BYTE_COUNT - 1))
|
||||
# error DYNAMIC_KEYMAP_EEPROM_MAX_ADDR is configured to use more space than what is available for the selected EEPROM driver
|
||||
#endif
|
||||
|
||||
// Due to usage of uint16_t check for max 65535
|
||||
#if DYNAMIC_KEYMAP_EEPROM_MAX_ADDR > 65535
|
||||
# pragma message STR(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR) " > 65535"
|
||||
# error DYNAMIC_KEYMAP_EEPROM_MAX_ADDR must be less than 65536
|
||||
#endif
|
||||
|
||||
@@ -107,7 +119,9 @@ _Static_assert(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR >= DYNAMIC_KEYMAP_MACRO_EEPROM_ADD
|
||||
# define DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE (DYNAMIC_KEYMAP_EEPROM_MAX_ADDR - DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + 1)
|
||||
#endif
|
||||
|
||||
uint8_t dynamic_keymap_get_layer_count(void) { return DYNAMIC_KEYMAP_LAYER_COUNT; }
|
||||
uint8_t dynamic_keymap_get_layer_count(void) {
|
||||
return DYNAMIC_KEYMAP_LAYER_COUNT;
|
||||
}
|
||||
|
||||
void *dynamic_keymap_key_to_eeprom_address(uint8_t layer, uint8_t row, uint8_t column) {
|
||||
// TODO: optimize this with some left shifts
|
||||
@@ -384,9 +398,13 @@ uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t dynamic_keymap_macro_get_count(void) { return DYNAMIC_KEYMAP_MACRO_COUNT; }
|
||||
uint8_t dynamic_keymap_macro_get_count(void) {
|
||||
return DYNAMIC_KEYMAP_MACRO_COUNT;
|
||||
}
|
||||
|
||||
uint16_t dynamic_keymap_macro_get_buffer_size(void) { return DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE; }
|
||||
uint16_t dynamic_keymap_macro_get_buffer_size(void) {
|
||||
return DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE;
|
||||
}
|
||||
|
||||
void dynamic_keymap_macro_get_buffer(uint16_t offset, uint16_t size, uint8_t *data) {
|
||||
void * source = (void *)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + offset);
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
// This is the default EEPROM max address to use for dynamic keymaps.
|
||||
// The default is the ATmega32u4 EEPROM max address.
|
||||
// Explicitly override it if the keyboard uses a microcontroller with
|
||||
// more EEPROM *and* it makes sense to increase it.
|
||||
#ifndef DYNAMIC_KEYMAP_EEPROM_MAX_ADDR
|
||||
# if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__)
|
||||
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 2047
|
||||
# elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
|
||||
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 4095
|
||||
# elif defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATtiny85__)
|
||||
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 511
|
||||
# elif defined(STM32_EEPROM_ENABLE)
|
||||
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 4095 /* can't access FEE_DENSITY_BYTES because that's defined in eeprom_stm32.c */
|
||||
# else
|
||||
# define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 1023
|
||||
# endif
|
||||
#endif
|
||||
@@ -49,7 +49,7 @@ void eeconfig_init_quantum(void) {
|
||||
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_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);
|
||||
@@ -90,13 +90,17 @@ void eeconfig_init_quantum(void) {
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
void eeconfig_init(void) { eeconfig_init_quantum(); }
|
||||
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); }
|
||||
void eeconfig_enable(void) {
|
||||
eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
|
||||
}
|
||||
|
||||
/** \brief eeconfig disable
|
||||
*
|
||||
@@ -141,29 +145,39 @@ bool eeconfig_is_disabled(void) {
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
uint8_t eeconfig_read_debug(void) { return eeprom_read_byte(EECONFIG_DEBUG); }
|
||||
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); }
|
||||
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); }
|
||||
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); }
|
||||
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)); }
|
||||
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
|
||||
@@ -177,53 +191,73 @@ void eeconfig_update_keymap(uint16_t val) {
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
uint8_t eeconfig_read_audio(void) { return eeprom_read_byte(EECONFIG_AUDIO); }
|
||||
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); }
|
||||
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); }
|
||||
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); }
|
||||
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); }
|
||||
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); }
|
||||
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); }
|
||||
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); }
|
||||
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); }
|
||||
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); }
|
||||
void eeconfig_update_handedness(bool val) {
|
||||
eeprom_update_byte(EECONFIG_HANDEDNESS, !!val);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#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
|
||||
# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEE9 // When changing, decrement this value to avoid future re-init issues
|
||||
#endif
|
||||
#define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF
|
||||
|
||||
@@ -112,28 +112,30 @@ void eeconfig_update_haptic(uint32_t val);
|
||||
bool eeconfig_read_handedness(void);
|
||||
void eeconfig_update_handedness(bool val);
|
||||
|
||||
#define EECONFIG_DEBOUNCE_HELPER(name, offset, config) \
|
||||
static uint8_t dirty_##name = false; \
|
||||
\
|
||||
static inline void eeconfig_init_##name(void) { \
|
||||
eeprom_read_block(&config, offset, sizeof(config)); \
|
||||
dirty_##name = false; \
|
||||
} \
|
||||
static inline void eeconfig_flush_##name(bool force) { \
|
||||
if (force || dirty_##name) { \
|
||||
eeprom_update_block(&config, offset, sizeof(config)); \
|
||||
dirty_##name = false; \
|
||||
} \
|
||||
} \
|
||||
static inline void eeconfig_flush_##name##_task(uint16_t timeout) { \
|
||||
static uint16_t flush_timer = 0; \
|
||||
if (timer_elapsed(flush_timer) > timeout) { \
|
||||
eeconfig_flush_##name(false); \
|
||||
flush_timer = timer_read(); \
|
||||
} \
|
||||
} \
|
||||
static inline void eeconfig_flag_##name(bool v) { dirty_##name |= v; } \
|
||||
static inline void eeconfig_write_##name(typeof(config) conf) { \
|
||||
memcpy(&config, &conf, sizeof(config)); \
|
||||
eeconfig_flag_##name(true); \
|
||||
#define EECONFIG_DEBOUNCE_HELPER(name, offset, config) \
|
||||
static uint8_t dirty_##name = false; \
|
||||
\
|
||||
static inline void eeconfig_init_##name(void) { \
|
||||
eeprom_read_block(&config, offset, sizeof(config)); \
|
||||
dirty_##name = false; \
|
||||
} \
|
||||
static inline void eeconfig_flush_##name(bool force) { \
|
||||
if (force || dirty_##name) { \
|
||||
eeprom_update_block(&config, offset, sizeof(config)); \
|
||||
dirty_##name = false; \
|
||||
} \
|
||||
} \
|
||||
static inline void eeconfig_flush_##name##_task(uint16_t timeout) { \
|
||||
static uint16_t flush_timer = 0; \
|
||||
if (timer_elapsed(flush_timer) > timeout) { \
|
||||
eeconfig_flush_##name(false); \
|
||||
flush_timer = timer_read(); \
|
||||
} \
|
||||
} \
|
||||
static inline void eeconfig_flag_##name(bool v) { \
|
||||
dirty_##name |= v; \
|
||||
} \
|
||||
static inline void eeconfig_write_##name(typeof(config) conf) { \
|
||||
memcpy(&config, &conf, sizeof(config)); \
|
||||
eeconfig_flag_##name(true); \
|
||||
}
|
||||
|
||||
@@ -59,9 +59,17 @@ static uint8_t thisHand, thatHand;
|
||||
static uint8_t encoder_value[NUMBER_OF_ENCODERS] = {0};
|
||||
#endif
|
||||
|
||||
__attribute__((weak)) bool encoder_update_user(uint8_t index, bool clockwise) { return true; }
|
||||
__attribute__((weak)) void encoder_wait_pullup_charge(void) {
|
||||
wait_us(100);
|
||||
}
|
||||
|
||||
__attribute__((weak)) bool encoder_update_kb(uint8_t index, bool clockwise) { return encoder_update_user(index, clockwise); }
|
||||
__attribute__((weak)) bool encoder_update_user(uint8_t index, bool clockwise) {
|
||||
return true;
|
||||
}
|
||||
|
||||
__attribute__((weak)) bool encoder_update_kb(uint8_t index, bool clockwise) {
|
||||
return encoder_update_user(index, clockwise);
|
||||
}
|
||||
|
||||
#ifdef VIAL_ENCODERS_ENABLE
|
||||
#include "vial.h"
|
||||
@@ -89,7 +97,9 @@ void encoder_init(void) {
|
||||
for (int i = 0; i < NUMBER_OF_ENCODERS; i++) {
|
||||
setPinInputHigh(encoders_pad_a[i]);
|
||||
setPinInputHigh(encoders_pad_b[i]);
|
||||
|
||||
}
|
||||
encoder_wait_pullup_charge();
|
||||
for (int i = 0; i < NUMBER_OF_ENCODERS; i++) {
|
||||
encoder_state[i] = (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1);
|
||||
}
|
||||
|
||||
@@ -118,7 +128,7 @@ static bool encoder_update(uint8_t index, uint8_t state) {
|
||||
changed = true;
|
||||
encoder_update_kb(index, ENCODER_COUNTER_CLOCKWISE);
|
||||
}
|
||||
if (encoder_pulses[i] <= -resolution) { // direction is arbitrary here, but this clockwise
|
||||
if (encoder_pulses[i] <= -resolution) { // direction is arbitrary here, but this clockwise
|
||||
encoder_value[index]--;
|
||||
changed = true;
|
||||
encoder_update_kb(index, ENCODER_CLOCKWISE);
|
||||
@@ -145,7 +155,9 @@ bool encoder_read(void) {
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
void last_encoder_activity_trigger(void);
|
||||
|
||||
void encoder_state_raw(uint8_t* slave_state) { memcpy(slave_state, &encoder_value[thisHand], sizeof(uint8_t) * NUMBER_OF_ENCODERS); }
|
||||
void encoder_state_raw(uint8_t* slave_state) {
|
||||
memcpy(slave_state, &encoder_value[thisHand], sizeof(uint8_t) * NUMBER_OF_ENCODERS);
|
||||
}
|
||||
|
||||
void encoder_update_raw(uint8_t* slave_state) {
|
||||
bool changed = false;
|
||||
|
||||
@@ -26,7 +26,9 @@ uint8_t mockSetPinInputHigh(pin_t pin) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool mockReadPin(pin_t pin) { return pins[pin]; }
|
||||
bool mockReadPin(pin_t pin) {
|
||||
return pins[pin];
|
||||
}
|
||||
|
||||
bool setPin(pin_t pin, bool val) {
|
||||
pins[pin] = val;
|
||||
|
||||
@@ -26,7 +26,9 @@ uint8_t mockSetPinInputHigh(pin_t pin) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool mockReadPin(pin_t pin) { return pins[pin]; }
|
||||
bool mockReadPin(pin_t pin) {
|
||||
return pins[pin];
|
||||
}
|
||||
|
||||
bool setPin(pin_t pin, bool val) {
|
||||
pins[pin] = val;
|
||||
|
||||
@@ -247,7 +247,9 @@ void haptic_set_dwell(uint8_t dwell) {
|
||||
xprintf("haptic_config.dwell = %u\n", haptic_config.dwell);
|
||||
}
|
||||
|
||||
uint8_t haptic_get_enable(void) { return haptic_config.enable; }
|
||||
uint8_t haptic_get_enable(void) {
|
||||
return haptic_config.enable;
|
||||
}
|
||||
|
||||
uint8_t haptic_get_mode(void) {
|
||||
if (!haptic_config.enable) {
|
||||
|
||||
@@ -50,7 +50,7 @@ extern joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT];
|
||||
enum joystick_status { JS_INITIALIZED = 1, JS_UPDATED = 2 };
|
||||
|
||||
typedef struct {
|
||||
uint8_t buttons[JOYSTICK_BUTTON_COUNT / 8 + 1];
|
||||
uint8_t buttons[(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1];
|
||||
|
||||
int16_t axes[JOYSTICK_AXES_COUNT];
|
||||
uint8_t status : 2;
|
||||
|
||||
@@ -16,9 +16,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "quantum.h"
|
||||
#include "keyboard.h"
|
||||
#include "matrix.h"
|
||||
#include "keymap.h"
|
||||
#include "magic.h"
|
||||
#include "host.h"
|
||||
#include "led.h"
|
||||
#include "keycode.h"
|
||||
@@ -106,20 +108,42 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#ifdef SLEEP_LED_ENABLE
|
||||
# include "sleep_led.h"
|
||||
#endif
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
# include "split_util.h"
|
||||
#endif
|
||||
#ifdef BLUETOOTH_ENABLE
|
||||
# include "outputselect.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); }
|
||||
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(); }
|
||||
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(); }
|
||||
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)
|
||||
@@ -141,7 +165,9 @@ void matrix_scan_perf_task(void) {
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t get_matrix_scan_rate(void) { return last_matrix_scan_count; }
|
||||
uint32_t get_matrix_scan_rate(void) {
|
||||
return last_matrix_scan_count;
|
||||
}
|
||||
#else
|
||||
# define matrix_scan_perf_task()
|
||||
#endif
|
||||
@@ -161,7 +187,7 @@ static matrix_row_t get_real_keys(uint8_t row, matrix_row_t rowdata) {
|
||||
}
|
||||
|
||||
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
|
||||
rowdata &= rowdata - 1; // if there are less than two bits (keys) set, rowdata will become zero
|
||||
return rowdata;
|
||||
}
|
||||
|
||||
@@ -218,7 +244,9 @@ __attribute__((weak)) void keyboard_pre_init_user(void) {}
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__((weak)) void keyboard_pre_init_kb(void) { keyboard_pre_init_user(); }
|
||||
__attribute__((weak)) void keyboard_pre_init_kb(void) {
|
||||
keyboard_pre_init_user();
|
||||
}
|
||||
|
||||
/** \brief keyboard_post_init_user
|
||||
*
|
||||
@@ -232,7 +260,9 @@ __attribute__((weak)) void keyboard_post_init_user() {}
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
|
||||
__attribute__((weak)) void keyboard_post_init_kb(void) { keyboard_post_init_user(); }
|
||||
__attribute__((weak)) void keyboard_post_init_kb(void) {
|
||||
keyboard_post_init_user();
|
||||
}
|
||||
|
||||
/** \brief keyboard_setup
|
||||
*
|
||||
@@ -262,13 +292,17 @@ void keyboard_setup(void) {
|
||||
*
|
||||
* FIXME: needs doc
|
||||
*/
|
||||
__attribute__((weak)) bool is_keyboard_master(void) { return true; }
|
||||
__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; }
|
||||
__attribute__((weak)) bool is_keyboard_left(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -277,7 +311,9 @@ __attribute__((weak)) bool is_keyboard_left(void) { return true; }
|
||||
* 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(); }
|
||||
__attribute__((weak)) bool should_process_keypress(void) {
|
||||
return is_keyboard_master();
|
||||
}
|
||||
|
||||
/** \brief housekeeping_task_kb
|
||||
*
|
||||
@@ -302,6 +338,36 @@ void housekeeping_task(void) {
|
||||
housekeeping_task_user();
|
||||
}
|
||||
|
||||
/** \brief Init tasks previously located in matrix_init_quantum
|
||||
*
|
||||
* TODO: rationalise against keyboard_init and current split role
|
||||
*/
|
||||
void quantum_init(void) {
|
||||
magic();
|
||||
led_init_ports();
|
||||
#ifdef BACKLIGHT_ENABLE
|
||||
backlight_init_ports();
|
||||
#endif
|
||||
#ifdef AUDIO_ENABLE
|
||||
audio_init();
|
||||
#endif
|
||||
#ifdef LED_MATRIX_ENABLE
|
||||
led_matrix_init();
|
||||
#endif
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
rgb_matrix_init();
|
||||
#endif
|
||||
#if defined(UNICODE_COMMON_ENABLE)
|
||||
unicode_input_mode_init();
|
||||
#endif
|
||||
#ifdef HAPTIC_ENABLE
|
||||
haptic_init();
|
||||
#endif
|
||||
#if defined(BLUETOOTH_ENABLE) && defined(OUTPUT_AUTO_ENABLE)
|
||||
set_output(OUTPUT_AUTO);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \brief keyboard_init
|
||||
*
|
||||
* FIXME: needs doc
|
||||
@@ -311,8 +377,12 @@ void keyboard_init(void) {
|
||||
sync_timer_init();
|
||||
#ifdef VIA_ENABLE
|
||||
via_init();
|
||||
#endif
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
split_pre_init();
|
||||
#endif
|
||||
matrix_init();
|
||||
quantum_init();
|
||||
#if defined(CRC_ENABLE)
|
||||
crc_init();
|
||||
#endif
|
||||
@@ -353,6 +423,9 @@ void keyboard_init(void) {
|
||||
#ifdef VIRTSER_ENABLE
|
||||
virtser_init();
|
||||
#endif
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
split_post_init();
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG_MATRIX_SCAN_RATE) && defined(CONSOLE_ENABLE)
|
||||
debug_enable = true;
|
||||
@@ -375,28 +448,17 @@ void switch_events(uint8_t row, uint8_t col, bool pressed) {
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \brief Keyboard task: Do keyboard routine jobs
|
||||
/** \brief Perform scan of keyboard matrix
|
||||
*
|
||||
* Do routine keyboard jobs:
|
||||
*
|
||||
* * scan matrix
|
||||
* * handle mouse movements
|
||||
* * handle midi commands
|
||||
* * light LEDs
|
||||
*
|
||||
* This is repeatedly called as fast as possible.
|
||||
* Any detected changes in state are sent out as part of the processing
|
||||
*/
|
||||
void keyboard_task(void) {
|
||||
bool matrix_scan_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();
|
||||
@@ -443,10 +505,94 @@ void keyboard_task(void) {
|
||||
|
||||
MATRIX_LOOP_END:
|
||||
|
||||
#ifdef DEBUG_MATRIX_SCAN_RATE
|
||||
matrix_scan_perf_task();
|
||||
return matrix_changed;
|
||||
}
|
||||
|
||||
/** \brief Tasks previously located in matrix_scan_quantum
|
||||
*
|
||||
* TODO: rationalise against keyboard_task and current split role
|
||||
*/
|
||||
void quantum_task(void) {
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
// some tasks should only run on master
|
||||
if (!is_keyboard_master()) return;
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_ENABLE) && defined(AUDIO_INIT_DELAY)
|
||||
// There are some tasks that need to be run a little bit
|
||||
// after keyboard startup, or else they will not work correctly
|
||||
// because of interaction with the USB device state, which
|
||||
// may still be in flux...
|
||||
//
|
||||
// At the moment the only feature that needs this is the
|
||||
// startup song.
|
||||
static bool delayed_tasks_run = false;
|
||||
static uint16_t delayed_task_timer = 0;
|
||||
if (!delayed_tasks_run) {
|
||||
if (!delayed_task_timer) {
|
||||
delayed_task_timer = timer_read();
|
||||
} else if (timer_elapsed(delayed_task_timer) > 300) {
|
||||
audio_startup();
|
||||
delayed_tasks_run = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_ENABLE) && !defined(NO_MUSIC_MODE)
|
||||
music_task();
|
||||
#endif
|
||||
|
||||
#ifdef KEY_OVERRIDE_ENABLE
|
||||
key_override_task();
|
||||
#endif
|
||||
|
||||
#ifdef SEQUENCER_ENABLE
|
||||
sequencer_task();
|
||||
#endif
|
||||
|
||||
#ifdef TAP_DANCE_ENABLE
|
||||
tap_dance_task();
|
||||
#endif
|
||||
|
||||
#ifdef COMBO_ENABLE
|
||||
combo_task();
|
||||
#endif
|
||||
|
||||
#ifdef WPM_ENABLE
|
||||
decay_wpm();
|
||||
#endif
|
||||
|
||||
#ifdef HAPTIC_ENABLE
|
||||
haptic_task();
|
||||
#endif
|
||||
|
||||
#ifdef DIP_SWITCH_ENABLE
|
||||
dip_switch_read(false);
|
||||
#endif
|
||||
|
||||
#ifdef AUTO_SHIFT_ENABLE
|
||||
autoshift_matrix_scan();
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \brief Keyboard task: Do keyboard routine jobs
|
||||
*
|
||||
* Do routine keyboard jobs:
|
||||
*
|
||||
* * scan matrix
|
||||
* * handle mouse movements
|
||||
* * handle midi commands
|
||||
* * light LEDs
|
||||
*
|
||||
* This is repeatedly called as fast as possible.
|
||||
*/
|
||||
void keyboard_task(void) {
|
||||
bool matrix_changed = matrix_scan_task();
|
||||
(void)matrix_changed;
|
||||
|
||||
quantum_task();
|
||||
|
||||
#if defined(RGBLIGHT_ENABLE)
|
||||
rgblight_task();
|
||||
#endif
|
||||
@@ -465,7 +611,7 @@ MATRIX_LOOP_END:
|
||||
#endif
|
||||
|
||||
#ifdef ENCODER_ENABLE
|
||||
encoders_changed = encoder_read();
|
||||
bool encoders_changed = encoder_read();
|
||||
if (encoders_changed) last_encoder_activity_trigger();
|
||||
#endif
|
||||
|
||||
@@ -528,22 +674,5 @@ MATRIX_LOOP_END:
|
||||
programmable_button_send();
|
||||
#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);
|
||||
led_task();
|
||||
}
|
||||
|
||||
@@ -44,13 +44,21 @@ typedef struct {
|
||||
* 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); }
|
||||
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) }
|
||||
#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);
|
||||
@@ -58,8 +66,6 @@ void keyboard_setup(void);
|
||||
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 */
|
||||
@@ -70,18 +76,18 @@ 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
|
||||
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_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_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 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);
|
||||
|
||||
|
||||
@@ -35,8 +35,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#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)
|
||||
@@ -62,11 +60,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#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
|
||||
|
||||
// clang-format off
|
||||
|
||||
/*
|
||||
@@ -258,7 +251,7 @@ enum hid_keyboard_keypad_usage {
|
||||
KC_J,
|
||||
KC_K,
|
||||
KC_L,
|
||||
KC_M, // 0x10
|
||||
KC_M, // 0x10
|
||||
KC_N,
|
||||
KC_O,
|
||||
KC_P,
|
||||
@@ -274,7 +267,7 @@ enum hid_keyboard_keypad_usage {
|
||||
KC_Z,
|
||||
KC_1,
|
||||
KC_2,
|
||||
KC_3, // 0x20
|
||||
KC_3, // 0x20
|
||||
KC_4,
|
||||
KC_5,
|
||||
KC_6,
|
||||
@@ -290,7 +283,7 @@ enum hid_keyboard_keypad_usage {
|
||||
KC_MINUS,
|
||||
KC_EQUAL,
|
||||
KC_LEFT_BRACKET,
|
||||
KC_RIGHT_BRACKET, // 0x30
|
||||
KC_RIGHT_BRACKET, // 0x30
|
||||
KC_BACKSLASH,
|
||||
KC_NONUS_HASH,
|
||||
KC_SEMICOLON,
|
||||
@@ -306,7 +299,7 @@ enum hid_keyboard_keypad_usage {
|
||||
KC_F4,
|
||||
KC_F5,
|
||||
KC_F6,
|
||||
KC_F7, // 0x40
|
||||
KC_F7, // 0x40
|
||||
KC_F8,
|
||||
KC_F9,
|
||||
KC_F10,
|
||||
@@ -322,7 +315,7 @@ enum hid_keyboard_keypad_usage {
|
||||
KC_END,
|
||||
KC_PAGE_DOWN,
|
||||
KC_RIGHT,
|
||||
KC_LEFT, // 0x50
|
||||
KC_LEFT, // 0x50
|
||||
KC_DOWN,
|
||||
KC_UP,
|
||||
KC_NUM_LOCK,
|
||||
@@ -338,7 +331,7 @@ enum hid_keyboard_keypad_usage {
|
||||
KC_KP_5,
|
||||
KC_KP_6,
|
||||
KC_KP_7,
|
||||
KC_KP_8, // 0x60
|
||||
KC_KP_8, // 0x60
|
||||
KC_KP_9,
|
||||
KC_KP_0,
|
||||
KC_KP_DOT,
|
||||
@@ -354,7 +347,7 @@ enum hid_keyboard_keypad_usage {
|
||||
KC_F18,
|
||||
KC_F19,
|
||||
KC_F20,
|
||||
KC_F21, // 0x70
|
||||
KC_F21, // 0x70
|
||||
KC_F22,
|
||||
KC_F23,
|
||||
KC_F24,
|
||||
@@ -370,7 +363,7 @@ enum hid_keyboard_keypad_usage {
|
||||
KC_PASTE,
|
||||
KC_FIND,
|
||||
KC_KB_MUTE,
|
||||
KC_KB_VOLUME_UP, // 0x80
|
||||
KC_KB_VOLUME_UP, // 0x80
|
||||
KC_KB_VOLUME_DOWN,
|
||||
KC_LOCKING_CAPS_LOCK,
|
||||
KC_LOCKING_NUM_LOCK,
|
||||
@@ -386,7 +379,7 @@ enum hid_keyboard_keypad_usage {
|
||||
KC_INTERNATIONAL_7,
|
||||
KC_INTERNATIONAL_8,
|
||||
KC_INTERNATIONAL_9,
|
||||
KC_LANGUAGE_1, // 0x90
|
||||
KC_LANGUAGE_1, // 0x90
|
||||
KC_LANGUAGE_2,
|
||||
KC_LANGUAGE_3,
|
||||
KC_LANGUAGE_4,
|
||||
@@ -402,7 +395,7 @@ enum hid_keyboard_keypad_usage {
|
||||
KC_PRIOR,
|
||||
KC_RETURN,
|
||||
KC_SEPARATOR,
|
||||
KC_OUT, // 0xA0
|
||||
KC_OUT, // 0xA0
|
||||
KC_OPER,
|
||||
KC_CLEAR_AGAIN,
|
||||
KC_CRSEL,
|
||||
@@ -495,7 +488,7 @@ enum internal_special_keycodes {
|
||||
KC_MEDIA_STOP,
|
||||
KC_MEDIA_PLAY_PAUSE,
|
||||
KC_MEDIA_SELECT,
|
||||
KC_MEDIA_EJECT, // 0xB0
|
||||
KC_MEDIA_EJECT, // 0xB0
|
||||
KC_MAIL,
|
||||
KC_CALCULATOR,
|
||||
KC_MY_COMPUTER,
|
||||
@@ -509,41 +502,7 @@ enum internal_special_keycodes {
|
||||
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
|
||||
KC_BRIGHTNESS_DOWN
|
||||
};
|
||||
|
||||
enum mouse_keys {
|
||||
@@ -555,7 +514,7 @@ enum mouse_keys {
|
||||
#endif
|
||||
KC_MS_DOWN,
|
||||
KC_MS_LEFT,
|
||||
KC_MS_RIGHT, // 0xF0
|
||||
KC_MS_RIGHT, // 0xF0
|
||||
KC_MS_BTN1,
|
||||
KC_MS_BTN2,
|
||||
KC_MS_BTN3,
|
||||
@@ -580,7 +539,7 @@ enum mouse_keys {
|
||||
/* Acceleration */
|
||||
KC_MS_ACCEL0,
|
||||
KC_MS_ACCEL1,
|
||||
KC_MS_ACCEL2 // 0xFF
|
||||
KC_MS_ACCEL2 // 0xFF
|
||||
};
|
||||
|
||||
#include "keycode_legacy.h"
|
||||
|
||||
@@ -27,7 +27,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# include <ch.h>
|
||||
#endif
|
||||
#include "keycode.h"
|
||||
#include "action_macro.h"
|
||||
#include "report.h"
|
||||
#include "host.h"
|
||||
// #include "print.h"
|
||||
@@ -35,9 +34,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "keycode_config.h"
|
||||
|
||||
// ChibiOS uses RESET in its FlagStatus enumeration
|
||||
// Therefore define it as QK_RESET here, to avoid name collision
|
||||
// Therefore define it as QK_BOOTLOADER here, to avoid name collision
|
||||
#if defined(PROTOCOL_CHIBIOS)
|
||||
# define RESET QK_RESET
|
||||
# define RESET QK_BOOTLOADER
|
||||
#endif
|
||||
// Gross hack, remove me and change RESET keycode to QK_BOOT
|
||||
#if defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1287__)
|
||||
@@ -49,8 +48,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// translates key to keycode
|
||||
uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key);
|
||||
|
||||
// translates function id to action
|
||||
uint16_t keymap_function_id_to_action(uint16_t function_id);
|
||||
|
||||
extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
|
||||
extern const uint16_t fn_actions[];
|
||||
|
||||
@@ -20,7 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "keycode.h"
|
||||
#include "action_layer.h"
|
||||
#include "action.h"
|
||||
#include "action_macro.h"
|
||||
#include "debug.h"
|
||||
#include "quantum.h"
|
||||
|
||||
@@ -78,26 +77,8 @@ action_t action_for_keycode(uint16_t keycode) {
|
||||
case QK_MODS ... QK_MODS_MAX:;
|
||||
// Has a modifier
|
||||
// Split it up
|
||||
action.code = ACTION_MODS_KEY(keycode >> 8, keycode & 0xFF); // adds modifier to key
|
||||
action.code = ACTION_MODS_KEY(keycode >> 8, keycode & 0xFF); // adds modifier to key
|
||||
break;
|
||||
#ifndef NO_ACTION_FUNCTION
|
||||
case KC_FN0 ... KC_FN31:
|
||||
action.code = keymap_function_id_to_action(FN_INDEX(keycode));
|
||||
break;
|
||||
case QK_FUNCTION ... QK_FUNCTION_MAX:;
|
||||
// Is a shortcut for function action_layer, pull last 12bits
|
||||
// This means we have 4,096 FN macros at our disposal
|
||||
action.code = keymap_function_id_to_action((int)keycode & 0xFFF);
|
||||
break;
|
||||
#endif
|
||||
#ifndef NO_ACTION_MACRO
|
||||
case QK_MACRO ... QK_MACRO_MAX:
|
||||
if (keycode & 0x800) // tap macros have upper bit set
|
||||
action.code = ACTION_MACRO_TAP(keycode & 0xFF);
|
||||
else
|
||||
action.code = ACTION_MACRO(keycode & 0xFF);
|
||||
break;
|
||||
#endif
|
||||
#ifndef NO_ACTION_LAYER
|
||||
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
|
||||
action.code = ACTION_LAYER_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
|
||||
@@ -165,30 +146,8 @@ action_t action_for_keycode(uint16_t keycode) {
|
||||
return action;
|
||||
}
|
||||
|
||||
__attribute__((weak)) const uint16_t PROGMEM fn_actions[] = {
|
||||
|
||||
};
|
||||
|
||||
/* Macro */
|
||||
__attribute__((weak)) const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { return MACRO_NONE; }
|
||||
|
||||
/* Function */
|
||||
__attribute__((weak)) void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) {}
|
||||
|
||||
// translates key to keycode
|
||||
__attribute__((weak)) uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key) {
|
||||
// Read entire word (16bits)
|
||||
return pgm_read_word(&keymaps[(layer)][(key.row)][(key.col)]);
|
||||
}
|
||||
|
||||
// translates function id to action
|
||||
__attribute__((weak)) uint16_t keymap_function_id_to_action(uint16_t function_id) {
|
||||
// The compiler sees the empty (weak) fn_actions and generates a warning
|
||||
// This function should not be called in that case, so the warning is too strict
|
||||
// If this function is called however, the keymap should have overridden fn_actions, and then the compile
|
||||
// is comparing against the wrong array
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Warray-bounds"
|
||||
return pgm_read_word(&fn_actions[function_id]);
|
||||
#pragma GCC diagnostic pop
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
#define LT_CIRC ALGR(LT_COMM) // ^
|
||||
#define LT_AMPR ALGR(LT_DOT) // &
|
||||
#define LT_ASTR ALGR(LT_EQL) // *
|
||||
#define LT_LBRC ALGR(LT_LRPN) // [
|
||||
#define LT_LBRC ALGR(LT_LPRN) // [
|
||||
#define LT_RBRC ALGR(LT_RPRN) // ]
|
||||
#define LT_QUOT ALGR(LT_QUES) // '
|
||||
#define LT_PERC ALGR(LT_X) // %
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#define NO_ACUT KC_EQL
|
||||
|
||||
#define NO_AM KC_LBRC
|
||||
#define NO_QUOT KC_RBRC // this is the "umlaut" char on Nordic keyboards, Apple layout
|
||||
#define NO_QUOT KC_RBRC // this is the "umlaut" char on Nordic keyboards, Apple layout
|
||||
#define NO_AE KC_SCLN
|
||||
#define NO_OSLH KC_QUOT
|
||||
#define NO_APOS KC_NUHS
|
||||
|
||||
@@ -102,10 +102,10 @@
|
||||
// Row 1
|
||||
#define SK_RNGA S(SK_SCLN) // ° (dead)
|
||||
#define SK_1 S(SK_PLUS) // 1
|
||||
#define SK_2 S(SK_LACU) // 2
|
||||
#define SK_2 S(SK_LCAR) // 2
|
||||
#define SK_3 S(SK_SCAR) // 3
|
||||
#define SK_4 S(SK_CCAR) // 4
|
||||
#define SK_5 S(SK_TACU) // 5
|
||||
#define SK_5 S(SK_TCAR) // 5
|
||||
#define SK_6 S(SK_ZCAR) // 6
|
||||
#define SK_7 S(SK_YACU) // 7
|
||||
#define SK_8 S(SK_AACU) // 8
|
||||
@@ -141,9 +141,8 @@
|
||||
*/
|
||||
// Row 1
|
||||
#define SK_TILD ALGR(SK_PLUS) // ~
|
||||
#define SK_CIRC ALGR(SK_LCAR) // ^ (dead)
|
||||
#define SK_BREV ALGR(SK_SCAR) // ˘ (dead)
|
||||
#define SK_RNGA ALGR(SK_CCAR) // ° (dead)
|
||||
#define SK_CIRC ALGR(SK_SCAR) // ^ (dead)
|
||||
#define SK_BREV ALGR(SK_CCAR) // ˘ (dead)
|
||||
#define SK_OGON ALGR(SK_TCAR) // ˛ (dead)
|
||||
#define SK_GRV ALGR(SK_ZCAR) // `
|
||||
#define SK_DOTA ALGR(SK_YACU) // ˙ (dead)
|
||||
|
||||
@@ -70,7 +70,7 @@ enum steno_keycodes {
|
||||
STN_NB,
|
||||
STN_NC,
|
||||
STN_ZR,
|
||||
STN__MAX = STN_ZR, // must be less than QK_STENO_BOLT
|
||||
STN__MAX = STN_ZR, // must be less than QK_STENO_BOLT
|
||||
};
|
||||
|
||||
#ifdef STENO_COMBINEDMAP
|
||||
|
||||
@@ -80,7 +80,7 @@ const uint8_t ascii_to_keycode_lut[128] PROGMEM = {
|
||||
// 0 1 2 3 4 5 6 7
|
||||
CA_0, CA_1, CA_2, CA_3, CA_4, CA_5, CA_6, CA_7,
|
||||
// 8 9 : ; < = > ?
|
||||
CA_8, CA_9, CA_SCLN, CA_SCLN, CA_DOT, CA_EQL, CA_COMM, CA_6,
|
||||
CA_8, CA_9, CA_SCLN, CA_SCLN, CA_COMM, CA_EQL, CA_DOT, CA_6,
|
||||
// @ A B C D E F G
|
||||
CA_2, CA_A, CA_B, CA_C, CA_D, CA_E, CA_F, CA_G,
|
||||
// H I J K L M N O
|
||||
|
||||
@@ -76,9 +76,9 @@ const uint8_t ascii_to_keycode_lut[128] PROGMEM = {
|
||||
// ! " # $ % & '
|
||||
KC_SPC, LT_EXLM, LT_EDOT, LT_SLSH, LT_SCLN, LT_X, LT_DOT, LT_QUES,
|
||||
// ( ) * + , - . /
|
||||
LT_LRPN, LT_RPRN, LT_EQL, LT_QUES, LT_COMM, LT_MINS, LT_DOT, LT_SLSH,
|
||||
LT_LPRN, LT_RPRN, LT_EQL, LT_QUES, LT_COMM, LT_MINS, LT_DOT, LT_SLSH,
|
||||
// 0 1 2 3 4 5 6 7
|
||||
LT_RPRN, LT_EXLM, LT_MINS, LT_SLSH, LT_SLCN, LT_COLN, LT_COMM, LT_DOT,
|
||||
LT_RPRN, LT_EXLM, LT_MINS, LT_SLSH, LT_SCLN, LT_COLN, LT_COMM, LT_DOT,
|
||||
// 8 9 : ; < = > ?
|
||||
LT_EQL, LT_LPRN, LT_COLN, LT_SCLN, LT_LABK, LT_EQL, LT_LABK, LT_QUES,
|
||||
// @ A B C D E F G
|
||||
|
||||
@@ -78,7 +78,7 @@ const uint8_t ascii_to_keycode_lut[128] PROGMEM = {
|
||||
// ( ) * + , - . /
|
||||
SK_ADIA, SK_NCAR, SK_AMPR, SK_PLUS, SK_COMM, SK_MINS, SK_DOT, SK_UACU,
|
||||
// 0 1 2 3 4 5 6 7
|
||||
SK_EACU, SK_PLUS, SK_LACU, SK_SCAR, SK_CCAR, SK_TACU, SK_ZCAR, SK_YACU,
|
||||
SK_EACU, SK_PLUS, SK_LCAR, SK_SCAR, SK_CCAR, SK_TCAR, SK_ZCAR, SK_YACU,
|
||||
// 8 9 : ; < = > ?
|
||||
SK_AACU, SK_IACU, SK_DOT, SK_SCLN, SK_AMPR, SK_EQL, SK_Y, SK_COMM,
|
||||
// @ A B C D E F G
|
||||
|
||||
@@ -13,21 +13,26 @@
|
||||
* 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 "quantum.h"
|
||||
#include "led.h"
|
||||
#include "host.h"
|
||||
#include "debug.h"
|
||||
#include "gpio.h"
|
||||
|
||||
#ifdef BACKLIGHT_ENABLE
|
||||
# include "backlight.h"
|
||||
#ifdef BACKLIGHT_CAPS_LOCK
|
||||
# ifdef BACKLIGHT_ENABLE
|
||||
# include "backlight.h"
|
||||
extern backlight_config_t backlight_config;
|
||||
#else
|
||||
// Cannot use BACKLIGHT_CAPS_LOCK without backlight being enabled
|
||||
# undef BACKLIGHT_CAPS_LOCK
|
||||
# else
|
||||
# pragma message "Cannot use BACKLIGHT_CAPS_LOCK without backlight being enabled"
|
||||
# undef BACKLIGHT_CAPS_LOCK
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef LED_PIN_ON_STATE
|
||||
# define LED_PIN_ON_STATE 1
|
||||
#endif
|
||||
|
||||
#if defined(BACKLIGHT_CAPS_LOCK)
|
||||
#ifdef BACKLIGHT_CAPS_LOCK
|
||||
/** \brief Caps Lock indicator using backlight (for keyboards without dedicated LED)
|
||||
*/
|
||||
static void handle_backlight_caps_lock(led_t led_state) {
|
||||
@@ -59,13 +64,17 @@ __attribute__((weak)) void led_set_user(uint8_t usb_led) {}
|
||||
*
|
||||
* \deprecated Use led_update_kb() instead.
|
||||
*/
|
||||
__attribute__((weak)) void led_set_kb(uint8_t usb_led) { led_set_user(usb_led); }
|
||||
__attribute__((weak)) void led_set_kb(uint8_t usb_led) {
|
||||
led_set_user(usb_led);
|
||||
}
|
||||
|
||||
/** \brief Lock LED update callback - keymap/user level
|
||||
*
|
||||
* \return True if led_update_kb() should run its own code, false otherwise.
|
||||
*/
|
||||
__attribute__((weak)) bool led_update_user(led_t led_state) { return true; }
|
||||
__attribute__((weak)) bool led_update_user(led_t led_state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \brief Lock LED update callback - keyboard level
|
||||
*
|
||||
@@ -135,3 +144,43 @@ __attribute__((weak)) void led_set(uint8_t usb_led) {
|
||||
led_set_kb(usb_led);
|
||||
led_update_kb((led_t)usb_led);
|
||||
}
|
||||
|
||||
/** \brief Trigger behaviour on transition to suspend
|
||||
*/
|
||||
void led_suspend(void) {
|
||||
uint8_t leds_off = 0;
|
||||
#ifdef BACKLIGHT_CAPS_LOCK
|
||||
if (is_backlight_enabled()) {
|
||||
// Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off
|
||||
leds_off |= (1 << USB_LED_CAPS_LOCK);
|
||||
}
|
||||
#endif
|
||||
led_set(leds_off);
|
||||
}
|
||||
|
||||
/** \brief Trigger behaviour on transition from suspend
|
||||
*/
|
||||
void led_wakeup(void) {
|
||||
led_set(host_keyboard_leds());
|
||||
}
|
||||
|
||||
/** \brief set host led state
|
||||
*
|
||||
* Only sets state if change detected
|
||||
*/
|
||||
void led_task(void) {
|
||||
static uint8_t last_led_status = 0;
|
||||
|
||||
// update LED
|
||||
uint8_t led_status = host_keyboard_leds();
|
||||
if (last_led_status != led_status) {
|
||||
last_led_status = led_status;
|
||||
|
||||
if (debug_keyboard) {
|
||||
debug("led_task: ");
|
||||
debug_hex8(led_status);
|
||||
debug("\n");
|
||||
}
|
||||
led_set(led_status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,18 @@ void led_set(uint8_t usb_led);
|
||||
|
||||
void led_init_ports(void);
|
||||
|
||||
void led_suspend(void);
|
||||
|
||||
void led_wakeup(void);
|
||||
|
||||
void led_task(void);
|
||||
|
||||
/* Callbacks */
|
||||
void led_set_user(uint8_t usb_led);
|
||||
void led_set_kb(uint8_t usb_led);
|
||||
bool led_update_user(led_t led_state);
|
||||
bool led_update_kb(led_t led_state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -20,5 +20,5 @@ bool ALPHAS_MODS(effect_params_t* params) {
|
||||
return led_matrix_check_finished_leds(led_max);
|
||||
}
|
||||
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_ALPHAS_MODS
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_ALPHAS_MODS
|
||||
|
||||
@@ -7,7 +7,9 @@ static uint8_t BAND_math(uint8_t val, uint8_t i, uint8_t time) {
|
||||
return scale8(v < 0 ? 0 : v, val);
|
||||
}
|
||||
|
||||
bool BAND(effect_params_t* params) { return effect_runner_i(params, &BAND_math); }
|
||||
bool BAND(effect_params_t* params) {
|
||||
return effect_runner_i(params, &BAND_math);
|
||||
}
|
||||
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_BAND
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_BAND
|
||||
|
||||
@@ -2,9 +2,13 @@
|
||||
LED_MATRIX_EFFECT(BAND_PINWHEEL)
|
||||
# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
|
||||
static uint8_t BAND_PINWHEEL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t time) { return scale8(val - time - atan2_8(dy, dx) * 3, val); }
|
||||
static uint8_t BAND_PINWHEEL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t time) {
|
||||
return scale8(val - time - atan2_8(dy, dx) * 3, val);
|
||||
}
|
||||
|
||||
bool BAND_PINWHEEL(effect_params_t* params) { return effect_runner_dx_dy(params, &BAND_PINWHEEL_math); }
|
||||
bool BAND_PINWHEEL(effect_params_t* params) {
|
||||
return effect_runner_dx_dy(params, &BAND_PINWHEEL_math);
|
||||
}
|
||||
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_BAND_PINWHEEL
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_BAND_PINWHEEL
|
||||
|
||||
@@ -2,9 +2,13 @@
|
||||
LED_MATRIX_EFFECT(BAND_SPIRAL)
|
||||
# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
|
||||
static uint8_t BAND_SPIRAL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint8_t time) { return scale8(val + dist - time - atan2_8(dy, dx), val); }
|
||||
static uint8_t BAND_SPIRAL_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint8_t time) {
|
||||
return scale8(val + dist - time - atan2_8(dy, dx), val);
|
||||
}
|
||||
|
||||
bool BAND_SPIRAL(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_math); }
|
||||
bool BAND_SPIRAL(effect_params_t* params) {
|
||||
return effect_runner_dx_dy_dist(params, &BAND_SPIRAL_math);
|
||||
}
|
||||
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_BAND_SPIRAL
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_BAND_SPIRAL
|
||||
|
||||
@@ -15,5 +15,5 @@ bool BREATHING(effect_params_t* params) {
|
||||
return led_matrix_check_finished_leds(led_max);
|
||||
}
|
||||
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_BREATHING
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_BREATHING
|
||||
|
||||
@@ -2,9 +2,13 @@
|
||||
LED_MATRIX_EFFECT(CYCLE_LEFT_RIGHT)
|
||||
# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
|
||||
static uint8_t CYCLE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { return scale8(g_led_config.point[i].x - time, val); }
|
||||
static uint8_t CYCLE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) {
|
||||
return scale8(g_led_config.point[i].x - time, val);
|
||||
}
|
||||
|
||||
bool CYCLE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math); }
|
||||
bool CYCLE_LEFT_RIGHT(effect_params_t* params) {
|
||||
return effect_runner_i(params, &CYCLE_LEFT_RIGHT_math);
|
||||
}
|
||||
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_CYCLE_LEFT_RIGHT
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_CYCLE_LEFT_RIGHT
|
||||
|
||||
@@ -2,9 +2,13 @@
|
||||
LED_MATRIX_EFFECT(CYCLE_OUT_IN)
|
||||
# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
|
||||
static uint8_t CYCLE_OUT_IN_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint8_t time) { return scale8(3 * dist / 2 + time, val); }
|
||||
static uint8_t CYCLE_OUT_IN_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uint8_t time) {
|
||||
return scale8(3 * dist / 2 + time, val);
|
||||
}
|
||||
|
||||
bool CYCLE_OUT_IN(effect_params_t* params) { return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math); }
|
||||
bool CYCLE_OUT_IN(effect_params_t* params) {
|
||||
return effect_runner_dx_dy_dist(params, &CYCLE_OUT_IN_math);
|
||||
}
|
||||
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_CYCLE_OUT_IN
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_CYCLE_OUT_IN
|
||||
|
||||
@@ -2,9 +2,13 @@
|
||||
LED_MATRIX_EFFECT(CYCLE_UP_DOWN)
|
||||
# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
|
||||
static uint8_t CYCLE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { return scale8(g_led_config.point[i].y - time, val); }
|
||||
static uint8_t CYCLE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) {
|
||||
return scale8(g_led_config.point[i].y - time, val);
|
||||
}
|
||||
|
||||
bool CYCLE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &CYCLE_UP_DOWN_math); }
|
||||
bool CYCLE_UP_DOWN(effect_params_t* params) {
|
||||
return effect_runner_i(params, &CYCLE_UP_DOWN_math);
|
||||
}
|
||||
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_CYCLE_UP_DOWN
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_CYCLE_UP_DOWN
|
||||
|
||||
@@ -2,9 +2,13 @@
|
||||
LED_MATRIX_EFFECT(DUAL_BEACON)
|
||||
# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
|
||||
static uint8_t DUAL_BEACON_math(uint8_t val, int8_t sin, int8_t cos, uint8_t i, uint8_t time) { return scale8(((g_led_config.point[i].y - k_led_matrix_center.y) * cos + (g_led_config.point[i].x - k_led_matrix_center.x) * sin) / 128, val); }
|
||||
static uint8_t DUAL_BEACON_math(uint8_t val, int8_t sin, int8_t cos, uint8_t i, uint8_t time) {
|
||||
return scale8(((g_led_config.point[i].y - k_led_matrix_center.y) * cos + (g_led_config.point[i].x - k_led_matrix_center.x) * sin) / 128, val);
|
||||
}
|
||||
|
||||
bool DUAL_BEACON(effect_params_t* params) { return effect_runner_sin_cos_i(params, &DUAL_BEACON_math); }
|
||||
bool DUAL_BEACON(effect_params_t* params) {
|
||||
return effect_runner_sin_cos_i(params, &DUAL_BEACON_math);
|
||||
}
|
||||
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_DUAL_BEACON
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_DUAL_BEACON
|
||||
|
||||
@@ -25,4 +25,4 @@ bool effect_runner_reactive(effect_params_t* params, reactive_f effect_func) {
|
||||
return led_matrix_check_finished_leds(led_max);
|
||||
}
|
||||
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
|
||||
@@ -23,4 +23,4 @@ bool effect_runner_reactive_splash(uint8_t start, effect_params_t* params, react
|
||||
return led_matrix_check_finished_leds(led_max);
|
||||
}
|
||||
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
|
||||
@@ -12,4 +12,4 @@ bool SOLID(effect_params_t* params) {
|
||||
return led_matrix_check_finished_leds(led_max);
|
||||
}
|
||||
|
||||
#endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
|
||||
@@ -23,13 +23,17 @@ static uint8_t SOLID_REACTIVE_CROSS_math(uint8_t val, int16_t dx, int16_t dy, ui
|
||||
}
|
||||
|
||||
# ifdef ENABLE_LED_MATRIX_SOLID_REACTIVE_CROSS
|
||||
bool SOLID_REACTIVE_CROSS(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_CROSS_math); }
|
||||
bool SOLID_REACTIVE_CROSS(effect_params_t* params) {
|
||||
return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_CROSS_math);
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifdef ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS
|
||||
bool SOLID_REACTIVE_MULTICROSS(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_CROSS_math); }
|
||||
bool SOLID_REACTIVE_MULTICROSS(effect_params_t* params) {
|
||||
return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_CROSS_math);
|
||||
}
|
||||
# endif
|
||||
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
# endif // defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS)
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
# endif // defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_CROSS) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTICROSS)
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
|
||||
@@ -20,13 +20,17 @@ static uint8_t SOLID_REACTIVE_NEXUS_math(uint8_t val, int16_t dx, int16_t dy, ui
|
||||
}
|
||||
|
||||
# ifdef ENABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS
|
||||
bool SOLID_REACTIVE_NEXUS(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_NEXUS_math); }
|
||||
bool SOLID_REACTIVE_NEXUS(effect_params_t* params) {
|
||||
return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_NEXUS_math);
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifdef ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS
|
||||
bool SOLID_REACTIVE_MULTINEXUS(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_NEXUS_math); }
|
||||
bool SOLID_REACTIVE_MULTINEXUS(effect_params_t* params) {
|
||||
return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_NEXUS_math);
|
||||
}
|
||||
# endif
|
||||
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
# endif // defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS)
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
# endif // defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_NEXUS) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTINEXUS)
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
|
||||
@@ -3,10 +3,14 @@
|
||||
LED_MATRIX_EFFECT(SOLID_REACTIVE_SIMPLE)
|
||||
# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
|
||||
static uint8_t SOLID_REACTIVE_SIMPLE_math(uint8_t val, uint16_t offset) { return scale8(255 - offset, val); }
|
||||
static uint8_t SOLID_REACTIVE_SIMPLE_math(uint8_t val, uint16_t offset) {
|
||||
return scale8(255 - offset, val);
|
||||
}
|
||||
|
||||
bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) { return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math); }
|
||||
bool SOLID_REACTIVE_SIMPLE(effect_params_t* params) {
|
||||
return effect_runner_reactive(params, &SOLID_REACTIVE_SIMPLE_math);
|
||||
}
|
||||
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
# endif // ENABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
# endif // ENABLE_LED_MATRIX_SOLID_REACTIVE_SIMPLE
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
# if !defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE)
|
||||
# if defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE)
|
||||
|
||||
# ifdef ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE
|
||||
LED_MATRIX_EFFECT(SOLID_REACTIVE_WIDE)
|
||||
@@ -18,13 +18,17 @@ static uint8_t SOLID_REACTIVE_WIDE_math(uint8_t val, int16_t dx, int16_t dy, uin
|
||||
}
|
||||
|
||||
# ifdef ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE
|
||||
bool SOLID_REACTIVE_WIDE(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_WIDE_math); }
|
||||
bool SOLID_REACTIVE_WIDE(effect_params_t* params) {
|
||||
return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_REACTIVE_WIDE_math);
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifdef ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE
|
||||
bool SOLID_REACTIVE_MULTIWIDE(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_WIDE_math); }
|
||||
bool SOLID_REACTIVE_MULTIWIDE(effect_params_t* params) {
|
||||
return effect_runner_reactive_splash(0, params, &SOLID_REACTIVE_WIDE_math);
|
||||
}
|
||||
# endif
|
||||
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
# endif // !defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || !defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE)
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
# endif // defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_WIDE) || defined(ENABLE_LED_MATRIX_SOLID_REACTIVE_MULTIWIDE)
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
|
||||
@@ -18,13 +18,17 @@ uint8_t SOLID_SPLASH_math(uint8_t val, int16_t dx, int16_t dy, uint8_t dist, uin
|
||||
}
|
||||
|
||||
# ifdef ENABLE_LED_MATRIX_SOLID_SPLASH
|
||||
bool SOLID_SPLASH(effect_params_t* params) { return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_SPLASH_math); }
|
||||
bool SOLID_SPLASH(effect_params_t* params) {
|
||||
return effect_runner_reactive_splash(qsub8(g_last_hit_tracker.count, 1), params, &SOLID_SPLASH_math);
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifdef ENABLE_LED_MATRIX_SOLID_MULTISPLASH
|
||||
bool SOLID_MULTISPLASH(effect_params_t* params) { return effect_runner_reactive_splash(0, params, &SOLID_SPLASH_math); }
|
||||
bool SOLID_MULTISPLASH(effect_params_t* params) {
|
||||
return effect_runner_reactive_splash(0, params, &SOLID_SPLASH_math);
|
||||
}
|
||||
# endif
|
||||
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
# endif // defined(ENABLE_LED_MATRIX_SPLASH) || defined(ENABLE_LED_MATRIX_MULTISPLASH)
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
# endif // defined(ENABLE_LED_MATRIX_SPLASH) || defined(ENABLE_LED_MATRIX_MULTISPLASH)
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
|
||||
@@ -2,9 +2,13 @@
|
||||
LED_MATRIX_EFFECT(WAVE_LEFT_RIGHT)
|
||||
# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
|
||||
static uint8_t WAVE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) { return scale8(sin8(g_led_config.point[i].x - time), val); }
|
||||
static uint8_t WAVE_LEFT_RIGHT_math(uint8_t val, uint8_t i, uint8_t time) {
|
||||
return scale8(sin8(g_led_config.point[i].x - time), val);
|
||||
}
|
||||
|
||||
bool WAVE_LEFT_RIGHT(effect_params_t* params) { return effect_runner_i(params, &WAVE_LEFT_RIGHT_math); }
|
||||
bool WAVE_LEFT_RIGHT(effect_params_t* params) {
|
||||
return effect_runner_i(params, &WAVE_LEFT_RIGHT_math);
|
||||
}
|
||||
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_WAVE_LEFT_RIGHT
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_WAVE_LEFT_RIGHT
|
||||
|
||||
@@ -2,9 +2,13 @@
|
||||
LED_MATRIX_EFFECT(WAVE_UP_DOWN)
|
||||
# ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
|
||||
static uint8_t WAVE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) { return scale8(sin8(g_led_config.point[i].y - time), val); }
|
||||
static uint8_t WAVE_UP_DOWN_math(uint8_t val, uint8_t i, uint8_t time) {
|
||||
return scale8(sin8(g_led_config.point[i].y - time), val);
|
||||
}
|
||||
|
||||
bool WAVE_UP_DOWN(effect_params_t* params) { return effect_runner_i(params, &WAVE_UP_DOWN_math); }
|
||||
bool WAVE_UP_DOWN(effect_params_t* params) {
|
||||
return effect_runner_i(params, &WAVE_UP_DOWN_math);
|
||||
}
|
||||
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_WAVE_UP_DOWN
|
||||
# endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
|
||||
#endif // ENABLE_LED_MATRIX_WAVE_UP_DOWN
|
||||
|
||||
@@ -88,14 +88,14 @@ const led_point_t k_led_matrix_center = LED_MATRIX_CENTER;
|
||||
#endif
|
||||
|
||||
// globals
|
||||
led_eeconfig_t led_matrix_eeconfig; // TODO: would like to prefix this with g_ for global consistancy, do this in another pr
|
||||
led_eeconfig_t led_matrix_eeconfig; // TODO: would like to prefix this with g_ for global consistancy, do this in another pr
|
||||
uint32_t g_led_timer;
|
||||
#ifdef LED_MATRIX_FRAMEBUFFER_EFFECTS
|
||||
uint8_t g_led_frame_buffer[MATRIX_ROWS][MATRIX_COLS] = {{0}};
|
||||
#endif // LED_MATRIX_FRAMEBUFFER_EFFECTS
|
||||
#endif // LED_MATRIX_FRAMEBUFFER_EFFECTS
|
||||
#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
last_hit_t g_last_hit_tracker;
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
|
||||
// internals
|
||||
static bool suspend_state = false;
|
||||
@@ -105,13 +105,13 @@ static effect_params_t led_effect_params = {0, LED_FLAG_ALL, false};
|
||||
static led_task_states led_task_state = SYNCING;
|
||||
#if LED_DISABLE_TIMEOUT > 0
|
||||
static uint32_t led_anykey_timer;
|
||||
#endif // LED_DISABLE_TIMEOUT > 0
|
||||
#endif // LED_DISABLE_TIMEOUT > 0
|
||||
|
||||
// double buffers
|
||||
static uint32_t led_timer_buffer;
|
||||
#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
static last_hit_t last_hit_buffer;
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
|
||||
// split led matrix
|
||||
#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
|
||||
@@ -120,7 +120,9 @@ const uint8_t k_led_matrix_split[2] = LED_MATRIX_SPLIT;
|
||||
|
||||
EECONFIG_DEBOUNCE_HELPER(led_matrix, EECONFIG_LED_MATRIX, led_matrix_eeconfig);
|
||||
|
||||
void eeconfig_update_led_matrix(void) { eeconfig_flush_led_matrix(true); }
|
||||
void eeconfig_update_led_matrix(void) {
|
||||
eeconfig_flush_led_matrix(true);
|
||||
}
|
||||
|
||||
void eeconfig_update_led_matrix_default(void) {
|
||||
dprintf("eeconfig_update_led_matrix_default\n");
|
||||
@@ -141,7 +143,9 @@ void eeconfig_debug_led_matrix(void) {
|
||||
dprintf("led_matrix_eeconfig.flags = %d\n", led_matrix_eeconfig.flags);
|
||||
}
|
||||
|
||||
__attribute__((weak)) uint8_t led_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i) { return 0; }
|
||||
__attribute__((weak)) uint8_t led_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t led_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *led_i) {
|
||||
uint8_t led_count = led_matrix_map_row_column_to_led_kb(row, column, led_i);
|
||||
@@ -153,7 +157,9 @@ uint8_t led_matrix_map_row_column_to_led(uint8_t row, uint8_t column, uint8_t *l
|
||||
return led_count;
|
||||
}
|
||||
|
||||
void led_matrix_update_pwm_buffers(void) { led_matrix_driver.flush(); }
|
||||
void led_matrix_update_pwm_buffers(void) {
|
||||
led_matrix_driver.flush();
|
||||
}
|
||||
|
||||
void led_matrix_set_value(int index, uint8_t value) {
|
||||
#ifdef USE_CIE1931_CURVE
|
||||
@@ -164,7 +170,8 @@ void led_matrix_set_value(int index, uint8_t value) {
|
||||
|
||||
void led_matrix_set_value_all(uint8_t value) {
|
||||
#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
|
||||
for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) led_matrix_set_value(i, value);
|
||||
for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++)
|
||||
led_matrix_set_value(i, value);
|
||||
#else
|
||||
# ifdef USE_CIE1931_CURVE
|
||||
led_matrix_driver.set_value_all(pgm_read_byte(&CIE1931_CURVE[value]));
|
||||
@@ -180,7 +187,7 @@ void process_led_matrix(uint8_t row, uint8_t col, bool pressed) {
|
||||
#endif
|
||||
#if LED_DISABLE_TIMEOUT > 0
|
||||
led_anykey_timer = 0;
|
||||
#endif // LED_DISABLE_TIMEOUT > 0
|
||||
#endif // LED_DISABLE_TIMEOUT > 0
|
||||
|
||||
#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
uint8_t led[LED_HITS_TO_REMEMBER];
|
||||
@@ -190,7 +197,7 @@ void process_led_matrix(uint8_t row, uint8_t col, bool pressed) {
|
||||
if (!pressed)
|
||||
# elif defined(LED_MATRIX_KEYPRESSES)
|
||||
if (pressed)
|
||||
# endif // defined(LED_MATRIX_KEYRELEASES)
|
||||
# endif // defined(LED_MATRIX_KEYRELEASES)
|
||||
{
|
||||
led_count = led_matrix_map_row_column_to_led(row, col, led);
|
||||
}
|
||||
@@ -198,7 +205,7 @@ void process_led_matrix(uint8_t row, uint8_t col, bool pressed) {
|
||||
if (last_hit_buffer.count + led_count > LED_HITS_TO_REMEMBER) {
|
||||
memcpy(&last_hit_buffer.x[0], &last_hit_buffer.x[led_count], LED_HITS_TO_REMEMBER - led_count);
|
||||
memcpy(&last_hit_buffer.y[0], &last_hit_buffer.y[led_count], LED_HITS_TO_REMEMBER - led_count);
|
||||
memcpy(&last_hit_buffer.tick[0], &last_hit_buffer.tick[led_count], (LED_HITS_TO_REMEMBER - led_count) * 2); // 16 bit
|
||||
memcpy(&last_hit_buffer.tick[0], &last_hit_buffer.tick[led_count], (LED_HITS_TO_REMEMBER - led_count) * 2); // 16 bit
|
||||
memcpy(&last_hit_buffer.index[0], &last_hit_buffer.index[led_count], LED_HITS_TO_REMEMBER - led_count);
|
||||
last_hit_buffer.count = LED_HITS_TO_REMEMBER - led_count;
|
||||
}
|
||||
@@ -211,13 +218,13 @@ void process_led_matrix(uint8_t row, uint8_t col, bool pressed) {
|
||||
last_hit_buffer.tick[index] = 0;
|
||||
last_hit_buffer.count++;
|
||||
}
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
|
||||
#if defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_LED_MATRIX_TYPING_HEATMAP)
|
||||
if (led_matrix_eeconfig.mode == LED_MATRIX_TYPING_HEATMAP) {
|
||||
process_led_matrix_typing_heatmap(row, col);
|
||||
}
|
||||
#endif // defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_LED_MATRIX_TYPING_HEATMAP)
|
||||
#endif // defined(LED_MATRIX_FRAMEBUFFER_EFFECTS) && defined(ENABLE_LED_MATRIX_TYPING_HEATMAP)
|
||||
}
|
||||
|
||||
static bool led_matrix_none(effect_params_t *params) {
|
||||
@@ -232,7 +239,7 @@ static bool led_matrix_none(effect_params_t *params) {
|
||||
static void led_task_timers(void) {
|
||||
#if defined(LED_MATRIX_KEYREACTIVE_ENABLED) || LED_DISABLE_TIMEOUT > 0
|
||||
uint32_t deltaTime = sync_timer_elapsed32(led_timer_buffer);
|
||||
#endif // defined(LED_MATRIX_KEYREACTIVE_ENABLED) || LED_DISABLE_TIMEOUT > 0
|
||||
#endif // defined(LED_MATRIX_KEYREACTIVE_ENABLED) || LED_DISABLE_TIMEOUT > 0
|
||||
led_timer_buffer = sync_timer_read32();
|
||||
|
||||
// Update double buffer timers
|
||||
@@ -244,7 +251,7 @@ static void led_task_timers(void) {
|
||||
led_anykey_timer += deltaTime;
|
||||
}
|
||||
}
|
||||
#endif // LED_DISABLE_TIMEOUT > 0
|
||||
#endif // LED_DISABLE_TIMEOUT > 0
|
||||
|
||||
// Update double buffer last hit timers
|
||||
#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
@@ -256,7 +263,7 @@ static void led_task_timers(void) {
|
||||
}
|
||||
last_hit_buffer.tick[i] += deltaTime;
|
||||
}
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
}
|
||||
|
||||
static void led_task_sync(void) {
|
||||
@@ -273,7 +280,7 @@ static void led_task_start(void) {
|
||||
g_led_timer = led_timer_buffer;
|
||||
#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
g_last_hit_tracker = last_hit_buffer;
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
|
||||
// next task
|
||||
led_task_state = RENDERING;
|
||||
@@ -352,7 +359,7 @@ void led_matrix_task(void) {
|
||||
bool suspend_backlight = suspend_state ||
|
||||
#if LED_DISABLE_TIMEOUT > 0
|
||||
(led_anykey_timer > (uint32_t)LED_DISABLE_TIMEOUT) ||
|
||||
#endif // LED_DISABLE_TIMEOUT > 0
|
||||
#endif // LED_DISABLE_TIMEOUT > 0
|
||||
false;
|
||||
|
||||
uint8_t effect = suspend_backlight || !led_matrix_eeconfig.enable ? 0 : led_matrix_eeconfig.mode;
|
||||
@@ -421,7 +428,7 @@ void led_matrix_init(void) {
|
||||
for (uint8_t i = 0; i < LED_HITS_TO_REMEMBER; ++i) {
|
||||
last_hit_buffer.tick[i] = UINT16_MAX;
|
||||
}
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
|
||||
if (!eeconfig_is_enabled()) {
|
||||
dprintf("led_matrix_init_drivers eeconfig is not enabled.\n");
|
||||
@@ -434,20 +441,22 @@ void led_matrix_init(void) {
|
||||
dprintf("led_matrix_init_drivers led_matrix_eeconfig.mode = 0. Write default values to EEPROM.\n");
|
||||
eeconfig_update_led_matrix_default();
|
||||
}
|
||||
eeconfig_debug_led_matrix(); // display current eeprom values
|
||||
eeconfig_debug_led_matrix(); // display current eeprom values
|
||||
}
|
||||
|
||||
void led_matrix_set_suspend_state(bool state) {
|
||||
#ifdef LED_DISABLE_WHEN_USB_SUSPENDED
|
||||
if (state && !suspend_state && is_keyboard_master()) { // only run if turning off, and only once
|
||||
led_task_render(0); // turn off all LEDs when suspending
|
||||
led_task_flush(0); // and actually flash led state to LEDs
|
||||
if (state && !suspend_state && is_keyboard_master()) { // only run if turning off, and only once
|
||||
led_task_render(0); // turn off all LEDs when suspending
|
||||
led_task_flush(0); // and actually flash led state to LEDs
|
||||
}
|
||||
suspend_state = state;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool led_matrix_get_suspend_state(void) { return suspend_state; }
|
||||
bool led_matrix_get_suspend_state(void) {
|
||||
return suspend_state;
|
||||
}
|
||||
|
||||
void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) {
|
||||
led_matrix_eeconfig.enable ^= 1;
|
||||
@@ -455,8 +464,12 @@ void led_matrix_toggle_eeprom_helper(bool write_to_eeprom) {
|
||||
eeconfig_flag_led_matrix(write_to_eeprom);
|
||||
dprintf("led matrix toggle [%s]: led_matrix_eeconfig.enable = %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.enable);
|
||||
}
|
||||
void led_matrix_toggle_noeeprom(void) { led_matrix_toggle_eeprom_helper(false); }
|
||||
void led_matrix_toggle(void) { led_matrix_toggle_eeprom_helper(true); }
|
||||
void led_matrix_toggle_noeeprom(void) {
|
||||
led_matrix_toggle_eeprom_helper(false);
|
||||
}
|
||||
void led_matrix_toggle(void) {
|
||||
led_matrix_toggle_eeprom_helper(true);
|
||||
}
|
||||
|
||||
void led_matrix_enable(void) {
|
||||
led_matrix_enable_noeeprom();
|
||||
@@ -478,7 +491,9 @@ void led_matrix_disable_noeeprom(void) {
|
||||
led_matrix_eeconfig.enable = 0;
|
||||
}
|
||||
|
||||
uint8_t led_matrix_is_enabled(void) { return led_matrix_eeconfig.enable; }
|
||||
uint8_t led_matrix_is_enabled(void) {
|
||||
return led_matrix_eeconfig.enable;
|
||||
}
|
||||
|
||||
void led_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
|
||||
if (!led_matrix_eeconfig.enable) {
|
||||
@@ -495,24 +510,38 @@ void led_matrix_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
|
||||
eeconfig_flag_led_matrix(write_to_eeprom);
|
||||
dprintf("led matrix mode [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.mode);
|
||||
}
|
||||
void led_matrix_mode_noeeprom(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, false); }
|
||||
void led_matrix_mode(uint8_t mode) { led_matrix_mode_eeprom_helper(mode, true); }
|
||||
void led_matrix_mode_noeeprom(uint8_t mode) {
|
||||
led_matrix_mode_eeprom_helper(mode, false);
|
||||
}
|
||||
void led_matrix_mode(uint8_t mode) {
|
||||
led_matrix_mode_eeprom_helper(mode, true);
|
||||
}
|
||||
|
||||
uint8_t led_matrix_get_mode(void) { return led_matrix_eeconfig.mode; }
|
||||
uint8_t led_matrix_get_mode(void) {
|
||||
return led_matrix_eeconfig.mode;
|
||||
}
|
||||
|
||||
void led_matrix_step_helper(bool write_to_eeprom) {
|
||||
uint8_t mode = led_matrix_eeconfig.mode + 1;
|
||||
led_matrix_mode_eeprom_helper((mode < LED_MATRIX_EFFECT_MAX) ? mode : 1, write_to_eeprom);
|
||||
}
|
||||
void led_matrix_step_noeeprom(void) { led_matrix_step_helper(false); }
|
||||
void led_matrix_step(void) { led_matrix_step_helper(true); }
|
||||
void led_matrix_step_noeeprom(void) {
|
||||
led_matrix_step_helper(false);
|
||||
}
|
||||
void led_matrix_step(void) {
|
||||
led_matrix_step_helper(true);
|
||||
}
|
||||
|
||||
void led_matrix_step_reverse_helper(bool write_to_eeprom) {
|
||||
uint8_t mode = led_matrix_eeconfig.mode - 1;
|
||||
led_matrix_mode_eeprom_helper((mode < 1) ? LED_MATRIX_EFFECT_MAX - 1 : mode, write_to_eeprom);
|
||||
}
|
||||
void led_matrix_step_reverse_noeeprom(void) { led_matrix_step_reverse_helper(false); }
|
||||
void led_matrix_step_reverse(void) { led_matrix_step_reverse_helper(true); }
|
||||
void led_matrix_step_reverse_noeeprom(void) {
|
||||
led_matrix_step_reverse_helper(false);
|
||||
}
|
||||
void led_matrix_step_reverse(void) {
|
||||
led_matrix_step_reverse_helper(true);
|
||||
}
|
||||
|
||||
void led_matrix_set_val_eeprom_helper(uint8_t val, bool write_to_eeprom) {
|
||||
if (!led_matrix_eeconfig.enable) {
|
||||
@@ -522,37 +551,77 @@ void led_matrix_set_val_eeprom_helper(uint8_t val, bool write_to_eeprom) {
|
||||
eeconfig_flag_led_matrix(write_to_eeprom);
|
||||
dprintf("led matrix set val [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.val);
|
||||
}
|
||||
void led_matrix_set_val_noeeprom(uint8_t val) { led_matrix_set_val_eeprom_helper(val, false); }
|
||||
void led_matrix_set_val(uint8_t val) { led_matrix_set_val_eeprom_helper(val, true); }
|
||||
void led_matrix_set_val_noeeprom(uint8_t val) {
|
||||
led_matrix_set_val_eeprom_helper(val, false);
|
||||
}
|
||||
void led_matrix_set_val(uint8_t val) {
|
||||
led_matrix_set_val_eeprom_helper(val, true);
|
||||
}
|
||||
|
||||
uint8_t led_matrix_get_val(void) { return led_matrix_eeconfig.val; }
|
||||
uint8_t led_matrix_get_val(void) {
|
||||
return led_matrix_eeconfig.val;
|
||||
}
|
||||
|
||||
void led_matrix_increase_val_helper(bool write_to_eeprom) { led_matrix_set_val_eeprom_helper(qadd8(led_matrix_eeconfig.val, LED_MATRIX_VAL_STEP), write_to_eeprom); }
|
||||
void led_matrix_increase_val_noeeprom(void) { led_matrix_increase_val_helper(false); }
|
||||
void led_matrix_increase_val(void) { led_matrix_increase_val_helper(true); }
|
||||
void led_matrix_increase_val_helper(bool write_to_eeprom) {
|
||||
led_matrix_set_val_eeprom_helper(qadd8(led_matrix_eeconfig.val, LED_MATRIX_VAL_STEP), write_to_eeprom);
|
||||
}
|
||||
void led_matrix_increase_val_noeeprom(void) {
|
||||
led_matrix_increase_val_helper(false);
|
||||
}
|
||||
void led_matrix_increase_val(void) {
|
||||
led_matrix_increase_val_helper(true);
|
||||
}
|
||||
|
||||
void led_matrix_decrease_val_helper(bool write_to_eeprom) { led_matrix_set_val_eeprom_helper(qsub8(led_matrix_eeconfig.val, LED_MATRIX_VAL_STEP), write_to_eeprom); }
|
||||
void led_matrix_decrease_val_noeeprom(void) { led_matrix_decrease_val_helper(false); }
|
||||
void led_matrix_decrease_val(void) { led_matrix_decrease_val_helper(true); }
|
||||
void led_matrix_decrease_val_helper(bool write_to_eeprom) {
|
||||
led_matrix_set_val_eeprom_helper(qsub8(led_matrix_eeconfig.val, LED_MATRIX_VAL_STEP), write_to_eeprom);
|
||||
}
|
||||
void led_matrix_decrease_val_noeeprom(void) {
|
||||
led_matrix_decrease_val_helper(false);
|
||||
}
|
||||
void led_matrix_decrease_val(void) {
|
||||
led_matrix_decrease_val_helper(true);
|
||||
}
|
||||
|
||||
void led_matrix_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) {
|
||||
led_matrix_eeconfig.speed = speed;
|
||||
eeconfig_flag_led_matrix(write_to_eeprom);
|
||||
dprintf("led matrix set speed [%s]: %u\n", (write_to_eeprom) ? "EEPROM" : "NOEEPROM", led_matrix_eeconfig.speed);
|
||||
}
|
||||
void led_matrix_set_speed_noeeprom(uint8_t speed) { led_matrix_set_speed_eeprom_helper(speed, false); }
|
||||
void led_matrix_set_speed(uint8_t speed) { led_matrix_set_speed_eeprom_helper(speed, true); }
|
||||
void led_matrix_set_speed_noeeprom(uint8_t speed) {
|
||||
led_matrix_set_speed_eeprom_helper(speed, false);
|
||||
}
|
||||
void led_matrix_set_speed(uint8_t speed) {
|
||||
led_matrix_set_speed_eeprom_helper(speed, true);
|
||||
}
|
||||
|
||||
uint8_t led_matrix_get_speed(void) { return led_matrix_eeconfig.speed; }
|
||||
uint8_t led_matrix_get_speed(void) {
|
||||
return led_matrix_eeconfig.speed;
|
||||
}
|
||||
|
||||
void led_matrix_increase_speed_helper(bool write_to_eeprom) { led_matrix_set_speed_eeprom_helper(qadd8(led_matrix_eeconfig.speed, LED_MATRIX_SPD_STEP), write_to_eeprom); }
|
||||
void led_matrix_increase_speed_noeeprom(void) { led_matrix_increase_speed_helper(false); }
|
||||
void led_matrix_increase_speed(void) { led_matrix_increase_speed_helper(true); }
|
||||
void led_matrix_increase_speed_helper(bool write_to_eeprom) {
|
||||
led_matrix_set_speed_eeprom_helper(qadd8(led_matrix_eeconfig.speed, LED_MATRIX_SPD_STEP), write_to_eeprom);
|
||||
}
|
||||
void led_matrix_increase_speed_noeeprom(void) {
|
||||
led_matrix_increase_speed_helper(false);
|
||||
}
|
||||
void led_matrix_increase_speed(void) {
|
||||
led_matrix_increase_speed_helper(true);
|
||||
}
|
||||
|
||||
void led_matrix_decrease_speed_helper(bool write_to_eeprom) { led_matrix_set_speed_eeprom_helper(qsub8(led_matrix_eeconfig.speed, LED_MATRIX_SPD_STEP), write_to_eeprom); }
|
||||
void led_matrix_decrease_speed_noeeprom(void) { led_matrix_decrease_speed_helper(false); }
|
||||
void led_matrix_decrease_speed(void) { led_matrix_decrease_speed_helper(true); }
|
||||
void led_matrix_decrease_speed_helper(bool write_to_eeprom) {
|
||||
led_matrix_set_speed_eeprom_helper(qsub8(led_matrix_eeconfig.speed, LED_MATRIX_SPD_STEP), write_to_eeprom);
|
||||
}
|
||||
void led_matrix_decrease_speed_noeeprom(void) {
|
||||
led_matrix_decrease_speed_helper(false);
|
||||
}
|
||||
void led_matrix_decrease_speed(void) {
|
||||
led_matrix_decrease_speed_helper(true);
|
||||
}
|
||||
|
||||
led_flags_t led_matrix_get_flags(void) { return led_matrix_eeconfig.flags; }
|
||||
led_flags_t led_matrix_get_flags(void) {
|
||||
return led_matrix_eeconfig.flags;
|
||||
}
|
||||
|
||||
void led_matrix_set_flags(led_flags_t flags) { led_matrix_eeconfig.flags = flags; }
|
||||
void led_matrix_set_flags(led_flags_t flags) {
|
||||
led_matrix_eeconfig.flags = flags;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright 2017 Jack Humbert
|
||||
* Copyright 2018 Yiancar
|
||||
* Copyright 2019 Clueboard
|
||||
* Copyright 2021 Leo Deng
|
||||
*
|
||||
* 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
|
||||
@@ -26,6 +27,11 @@
|
||||
|
||||
#ifdef IS31FL3731
|
||||
# include "is31fl3731-simple.h"
|
||||
#elif defined(IS31FLCOMMON)
|
||||
# include "is31flcommon.h"
|
||||
#endif
|
||||
#ifdef IS31FL3733
|
||||
# include "is31fl3733-simple.h"
|
||||
#endif
|
||||
|
||||
#ifndef LED_MATRIX_LED_FLUSH_LIMIT
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
* in their own files.
|
||||
*/
|
||||
|
||||
#if defined(IS31FL3731) || defined(IS31FL3733)
|
||||
#if defined(IS31FL3731) || defined(IS31FL3733) || defined(IS31FLCOMMON)
|
||||
# include "i2c_master.h"
|
||||
|
||||
static void init(void) {
|
||||
@@ -66,6 +66,18 @@ static void init(void) {
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# elif defined(IS31FLCOMMON)
|
||||
IS31FL_common_init(DRIVER_ADDR_1, ISSI_SSR_1);
|
||||
# if defined(LED_DRIVER_ADDR_2)
|
||||
IS31FL_common_init(DRIVER_ADDR_2, ISSI_SSR_2);
|
||||
# if defined(LED_DRIVER_ADDR_3)
|
||||
IS31FL_common_init(DRIVER_ADDR_3, ISSI_SSR_3);
|
||||
# if defined(LED_DRIVER_ADDR_4)
|
||||
IS31FL_common_init(DRIVER_ADDR_4, ISSI_SSR_4);
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
|
||||
for (int index = 0; index < DRIVER_LED_TOTAL; index++) {
|
||||
@@ -73,6 +85,8 @@ static void init(void) {
|
||||
IS31FL3731_set_led_control_register(index, true);
|
||||
# elif defined(IS31FL3733)
|
||||
IS31FL3733_set_led_control_register(index, true);
|
||||
# elif defined(IS31FLCOMMON)
|
||||
IS31FL_simple_set_scaling_buffer(index, true);
|
||||
# endif
|
||||
}
|
||||
|
||||
@@ -100,6 +114,21 @@ static void init(void) {
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# elif defined(IS31FLCOMMON)
|
||||
# ifdef ISSI_MANUAL_SCALING
|
||||
IS31FL_set_manual_scaling_buffer();
|
||||
# endif
|
||||
IS31FL_common_update_scaling_register(DRIVER_ADDR_1, 0);
|
||||
# if defined(LED_DRIVER_ADDR_2)
|
||||
IS31FL_common_update_scaling_register(DRIVER_ADDR_2, 1);
|
||||
# if defined(LED_DRIVER_ADDR_3)
|
||||
IS31FL_common_update_scaling_register(DRIVER_ADDR_3, 2);
|
||||
# if defined(LED_DRIVER_ADDR_4)
|
||||
IS31FL_common_update_scaling_register(DRIVER_ADDR_4, 3);
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
}
|
||||
|
||||
@@ -144,5 +173,26 @@ const led_matrix_driver_t led_matrix_driver = {
|
||||
.set_value = IS31FL3733_set_value,
|
||||
.set_value_all = IS31FL3733_set_value_all,
|
||||
};
|
||||
|
||||
# elif defined(IS31FLCOMMON)
|
||||
static void flush(void) {
|
||||
IS31FL_common_update_pwm_register(DRIVER_ADDR_1, 0);
|
||||
# if defined(LED_DRIVER_ADDR_2)
|
||||
IS31FL_common_update_pwm_register(DRIVER_ADDR_2, 1);
|
||||
# if defined(LED_DRIVER_ADDR_3)
|
||||
IS31FL_common_update_pwm_register(DRIVER_ADDR_3, 2);
|
||||
# if defined(LED_DRIVER_ADDR_4)
|
||||
IS31FL_common_update_pwm_register(DRIVER_ADDR_4, 3);
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
}
|
||||
|
||||
const led_matrix_driver_t led_matrix_driver = {
|
||||
.init = init,
|
||||
.flush = flush,
|
||||
.set_value = IS31FL_simple_set_brightness,
|
||||
.set_value_all = IS31FL_simple_set_brigntness_all,
|
||||
};
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
// Last led hit
|
||||
#ifndef LED_HITS_TO_REMEMBER
|
||||
# define LED_HITS_TO_REMEMBER 8
|
||||
#endif // LED_HITS_TO_REMEMBER
|
||||
#endif // LED_HITS_TO_REMEMBER
|
||||
|
||||
#ifdef LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
typedef struct PACKED {
|
||||
@@ -46,7 +46,7 @@ typedef struct PACKED {
|
||||
uint8_t index[LED_HITS_TO_REMEMBER];
|
||||
uint16_t tick[LED_HITS_TO_REMEMBER];
|
||||
} last_hit_t;
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
#endif // LED_MATRIX_KEYREACTIVE_ENABLED
|
||||
|
||||
typedef enum led_task_states { STARTING, RENDERING, FLUSHING, SYNCING } led_task_states;
|
||||
|
||||
@@ -87,7 +87,7 @@ typedef union {
|
||||
uint8_t mode : 6;
|
||||
uint16_t reserved;
|
||||
uint8_t val;
|
||||
uint8_t speed; // EECONFIG needs to be increased to support this
|
||||
uint8_t speed; // EECONFIG needs to be increased to support this
|
||||
led_flags_t flags;
|
||||
};
|
||||
} led_eeconfig_t;
|
||||
|
||||
@@ -17,9 +17,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "debug.h"
|
||||
|
||||
debug_config_t debug_config = {
|
||||
.enable = false, //
|
||||
.matrix = false, //
|
||||
.keyboard = false, //
|
||||
.mouse = false, //
|
||||
.reserved = 0 //
|
||||
.enable = false, //
|
||||
.matrix = false, //
|
||||
.keyboard = false, //
|
||||
.mouse = false, //
|
||||
.reserved = 0 //
|
||||
};
|
||||
|
||||
@@ -19,9 +19,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// bind lib/printf to console interface - sendchar
|
||||
|
||||
static int8_t null_sendchar_func(uint8_t c) { return 0; }
|
||||
static int8_t null_sendchar_func(uint8_t c) {
|
||||
return 0;
|
||||
}
|
||||
static sendchar_func_t func = null_sendchar_func;
|
||||
|
||||
void print_set_sendchar(sendchar_func_t send) { func = send; }
|
||||
void print_set_sendchar(sendchar_func_t send) {
|
||||
func = send;
|
||||
}
|
||||
|
||||
void _putchar(char character) { func(character); }
|
||||
void _putchar(char character) {
|
||||
func(character);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ void print_set_sendchar(sendchar_func_t func);
|
||||
# include_next "_print.h" /* Include the platforms print.h */
|
||||
# else
|
||||
// Fall back to lib/printf
|
||||
# include "printf.h" // lib/printf/printf.h
|
||||
# include "printf.h" // lib/printf/printf.h
|
||||
|
||||
// Create user & normal print defines
|
||||
# define print(s) printf(s)
|
||||
|
||||
@@ -17,4 +17,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "sendchar.h"
|
||||
|
||||
/* default noop "null" implementation */
|
||||
__attribute__((weak)) int8_t sendchar(uint8_t c) { return 0; }
|
||||
__attribute__((weak)) int8_t sendchar(uint8_t c) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ void protocol_task(void) {
|
||||
|
||||
#ifdef DEFERRED_EXEC_ENABLE
|
||||
void deferred_exec_task(void);
|
||||
#endif // DEFERRED_EXEC_ENABLE
|
||||
#endif // DEFERRED_EXEC_ENABLE
|
||||
|
||||
/** \brief Main
|
||||
*
|
||||
@@ -66,7 +66,7 @@ int main(void) {
|
||||
#ifdef DEFERRED_EXEC_ENABLE
|
||||
// Run deferred executions
|
||||
deferred_exec_task();
|
||||
#endif // DEFERRED_EXEC_ENABLE
|
||||
#endif // DEFERRED_EXEC_ENABLE
|
||||
|
||||
housekeeping_task();
|
||||
}
|
||||
|
||||
100
quantum/matrix.c
100
quantum/matrix.c
@@ -47,33 +47,29 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#endif
|
||||
|
||||
#ifdef DIRECT_PINS
|
||||
static SPLIT_MUTABLE pin_t direct_pins[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS;
|
||||
static SPLIT_MUTABLE pin_t direct_pins[ROWS_PER_HAND][MATRIX_COLS] = DIRECT_PINS;
|
||||
#elif (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
|
||||
# ifdef MATRIX_ROW_PINS
|
||||
static SPLIT_MUTABLE_ROW pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
|
||||
# endif // MATRIX_ROW_PINS
|
||||
static SPLIT_MUTABLE_ROW pin_t row_pins[ROWS_PER_HAND] = MATRIX_ROW_PINS;
|
||||
# endif // MATRIX_ROW_PINS
|
||||
# ifdef MATRIX_COL_PINS
|
||||
static SPLIT_MUTABLE_COL pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
|
||||
# endif // MATRIX_COL_PINS
|
||||
static SPLIT_MUTABLE_COL pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
|
||||
# endif // MATRIX_COL_PINS
|
||||
#endif
|
||||
|
||||
/* matrix state(1:on, 0:off) */
|
||||
extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
|
||||
extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
|
||||
extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
|
||||
extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
|
||||
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
// row offsets for each hand
|
||||
uint8_t thisHand, thatHand;
|
||||
extern uint8_t thisHand, thatHand;
|
||||
#endif
|
||||
|
||||
// user-defined overridable functions
|
||||
__attribute__((weak)) void matrix_init_pins(void);
|
||||
__attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row);
|
||||
__attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col, matrix_row_t row_shifter);
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
__attribute__((weak)) void matrix_slave_scan_kb(void) { matrix_slave_scan_user(); }
|
||||
__attribute__((weak)) void matrix_slave_scan_user(void) {}
|
||||
#endif
|
||||
|
||||
static inline void setPinOutput_writeLow(pin_t pin) {
|
||||
ATOMIC_BLOCK_FORCEON {
|
||||
@@ -82,8 +78,17 @@ static inline void setPinOutput_writeLow(pin_t pin) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline void setPinOutput_writeHigh(pin_t pin) {
|
||||
ATOMIC_BLOCK_FORCEON {
|
||||
setPinOutput(pin);
|
||||
writePinHigh(pin);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void setPinInputHigh_atomic(pin_t pin) {
|
||||
ATOMIC_BLOCK_FORCEON { setPinInputHigh(pin); }
|
||||
ATOMIC_BLOCK_FORCEON {
|
||||
setPinInputHigh(pin);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint8_t readMatrixPin(pin_t pin) {
|
||||
@@ -99,7 +104,7 @@ static inline uint8_t readMatrixPin(pin_t pin) {
|
||||
#ifdef DIRECT_PINS
|
||||
|
||||
__attribute__((weak)) void matrix_init_pins(void) {
|
||||
for (int row = 0; row < MATRIX_ROWS; row++) {
|
||||
for (int row = 0; row < ROWS_PER_HAND; row++) {
|
||||
for (int col = 0; col < MATRIX_COLS; col++) {
|
||||
pin_t pin = direct_pins[row][col];
|
||||
if (pin != NO_PIN) {
|
||||
@@ -141,7 +146,11 @@ static bool select_row(uint8_t row) {
|
||||
static void unselect_row(uint8_t row) {
|
||||
pin_t pin = row_pins[row];
|
||||
if (pin != NO_PIN) {
|
||||
# ifdef MATRIX_UNSELECT_DRIVE_HIGH
|
||||
setPinOutput_writeHigh(pin);
|
||||
# else
|
||||
setPinInputHigh_atomic(pin);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,8 +173,8 @@ __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[]
|
||||
// Start with a clear matrix row
|
||||
matrix_row_t current_row_value = 0;
|
||||
|
||||
if (!select_row(current_row)) { // Select row
|
||||
return; // skip NO_PIN row
|
||||
if (!select_row(current_row)) { // Select row
|
||||
return; // skip NO_PIN row
|
||||
}
|
||||
matrix_output_select_delay();
|
||||
|
||||
@@ -180,7 +189,7 @@ __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[]
|
||||
|
||||
// Unselect row
|
||||
unselect_row(current_row);
|
||||
matrix_output_unselect_delay(current_row, current_row_value != 0); // wait for all Col signals to go HIGH
|
||||
matrix_output_unselect_delay(current_row, current_row_value != 0); // wait for all Col signals to go HIGH
|
||||
|
||||
// Update the matrix
|
||||
current_matrix[current_row] = current_row_value;
|
||||
@@ -200,7 +209,11 @@ static bool select_col(uint8_t col) {
|
||||
static void unselect_col(uint8_t col) {
|
||||
pin_t pin = col_pins[col];
|
||||
if (pin != NO_PIN) {
|
||||
# ifdef MATRIX_UNSELECT_DRIVE_HIGH
|
||||
setPinOutput_writeHigh(pin);
|
||||
# else
|
||||
setPinInputHigh_atomic(pin);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,8 +236,8 @@ __attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[]
|
||||
bool key_pressed = false;
|
||||
|
||||
// Select col
|
||||
if (!select_col(current_col)) { // select col
|
||||
return; // skip NO_PIN col
|
||||
if (!select_col(current_col)) { // select col
|
||||
return; // skip NO_PIN col
|
||||
}
|
||||
matrix_output_select_delay();
|
||||
|
||||
@@ -243,34 +256,32 @@ __attribute__((weak)) void matrix_read_rows_on_col(matrix_row_t current_matrix[]
|
||||
|
||||
// Unselect col
|
||||
unselect_col(current_col);
|
||||
matrix_output_unselect_delay(current_col, key_pressed); // wait for all Row signals to go HIGH
|
||||
matrix_output_unselect_delay(current_col, key_pressed); // wait for all Row signals to go HIGH
|
||||
}
|
||||
|
||||
# else
|
||||
# error DIODE_DIRECTION must be one of COL2ROW or ROW2COL!
|
||||
# endif
|
||||
# endif // defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)
|
||||
# endif // defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS)
|
||||
#else
|
||||
# error DIODE_DIRECTION is not defined!
|
||||
#endif
|
||||
|
||||
void matrix_init(void) {
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
split_pre_init();
|
||||
|
||||
// Set pinout for right half if pinout for that half is defined
|
||||
if (!isLeftHand) {
|
||||
# ifdef DIRECT_PINS_RIGHT
|
||||
const pin_t direct_pins_right[MATRIX_ROWS][MATRIX_COLS] = DIRECT_PINS_RIGHT;
|
||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
|
||||
const pin_t direct_pins_right[ROWS_PER_HAND][MATRIX_COLS] = DIRECT_PINS_RIGHT;
|
||||
for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
|
||||
for (uint8_t j = 0; j < MATRIX_COLS; j++) {
|
||||
direct_pins[i][j] = direct_pins_right[i][j];
|
||||
}
|
||||
}
|
||||
# endif
|
||||
# ifdef MATRIX_ROW_PINS_RIGHT
|
||||
const pin_t row_pins_right[MATRIX_ROWS] = MATRIX_ROW_PINS_RIGHT;
|
||||
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
|
||||
const pin_t row_pins_right[ROWS_PER_HAND] = MATRIX_ROW_PINS_RIGHT;
|
||||
for (uint8_t i = 0; i < ROWS_PER_HAND; i++) {
|
||||
row_pins[i] = row_pins_right[i];
|
||||
}
|
||||
# endif
|
||||
@@ -296,46 +307,13 @@ void matrix_init(void) {
|
||||
debounce_init(ROWS_PER_HAND);
|
||||
|
||||
matrix_init_quantum();
|
||||
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
split_post_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
// Fallback implementation for keyboards not using the standard split_util.c
|
||||
__attribute__((weak)) bool transport_master_if_connected(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
|
||||
transport_master(master_matrix, slave_matrix);
|
||||
return true; // Treat the transport as always connected
|
||||
}
|
||||
|
||||
bool matrix_post_scan(void) {
|
||||
bool changed = false;
|
||||
if (is_keyboard_master()) {
|
||||
static bool last_connected = false;
|
||||
matrix_row_t slave_matrix[ROWS_PER_HAND] = {0};
|
||||
if (transport_master_if_connected(matrix + thisHand, slave_matrix)) {
|
||||
changed = memcmp(matrix + thatHand, slave_matrix, sizeof(slave_matrix)) != 0;
|
||||
|
||||
last_connected = true;
|
||||
} else if (last_connected) {
|
||||
// reset other half when disconnected
|
||||
memset(slave_matrix, 0, sizeof(slave_matrix));
|
||||
changed = true;
|
||||
|
||||
last_connected = false;
|
||||
}
|
||||
|
||||
if (changed) memcpy(matrix + thatHand, slave_matrix, sizeof(slave_matrix));
|
||||
|
||||
matrix_scan_quantum();
|
||||
} else {
|
||||
transport_slave(matrix + thatHand, matrix + thisHand);
|
||||
|
||||
matrix_slave_scan_kb();
|
||||
}
|
||||
|
||||
return changed;
|
||||
return true; // Treat the transport as always connected
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -46,8 +46,6 @@ void matrix_setup(void);
|
||||
void matrix_init(void);
|
||||
/* scan all key states on matrix */
|
||||
uint8_t matrix_scan(void);
|
||||
/* whether modified from previous scan. used after matrix_scan. */
|
||||
bool matrix_is_modified(void) __attribute__((deprecated));
|
||||
/* whether a switch is on */
|
||||
bool matrix_is_on(uint8_t row, uint8_t col);
|
||||
/* matrix state on row */
|
||||
@@ -75,6 +73,7 @@ void matrix_init_user(void);
|
||||
void matrix_scan_user(void);
|
||||
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
bool matrix_post_scan(void);
|
||||
void matrix_slave_scan_kb(void);
|
||||
void matrix_slave_scan_user(void);
|
||||
#endif
|
||||
|
||||
@@ -4,6 +4,15 @@
|
||||
#include "wait.h"
|
||||
#include "print.h"
|
||||
#include "debug.h"
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
# include "split_common/split_util.h"
|
||||
# include "split_common/transactions.h"
|
||||
# include <string.h>
|
||||
|
||||
# define ROWS_PER_HAND (MATRIX_ROWS / 2)
|
||||
#else
|
||||
# define ROWS_PER_HAND (MATRIX_ROWS)
|
||||
#endif
|
||||
|
||||
#ifndef MATRIX_IO_DELAY
|
||||
# define MATRIX_IO_DELAY 30
|
||||
@@ -13,15 +22,24 @@
|
||||
matrix_row_t raw_matrix[MATRIX_ROWS];
|
||||
matrix_row_t matrix[MATRIX_ROWS];
|
||||
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
// row offsets for each hand
|
||||
uint8_t thisHand, thatHand;
|
||||
#endif
|
||||
|
||||
#ifdef MATRIX_MASKED
|
||||
extern const matrix_row_t matrix_mask[];
|
||||
#endif
|
||||
|
||||
// user-defined overridable functions
|
||||
|
||||
__attribute__((weak)) void matrix_init_kb(void) { matrix_init_user(); }
|
||||
__attribute__((weak)) void matrix_init_kb(void) {
|
||||
matrix_init_user();
|
||||
}
|
||||
|
||||
__attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); }
|
||||
__attribute__((weak)) void matrix_scan_kb(void) {
|
||||
matrix_scan_user();
|
||||
}
|
||||
|
||||
__attribute__((weak)) void matrix_init_user(void) {}
|
||||
|
||||
@@ -29,11 +47,17 @@ __attribute__((weak)) void matrix_scan_user(void) {}
|
||||
|
||||
// helper functions
|
||||
|
||||
inline uint8_t matrix_rows(void) { return MATRIX_ROWS; }
|
||||
inline uint8_t matrix_rows(void) {
|
||||
return MATRIX_ROWS;
|
||||
}
|
||||
|
||||
inline uint8_t matrix_cols(void) { return MATRIX_COLS; }
|
||||
inline uint8_t matrix_cols(void) {
|
||||
return MATRIX_COLS;
|
||||
}
|
||||
|
||||
inline bool matrix_is_on(uint8_t row, uint8_t col) { return (matrix[row] & ((matrix_row_t)1 << col)); }
|
||||
inline bool matrix_is_on(uint8_t row, uint8_t col) {
|
||||
return (matrix[row] & ((matrix_row_t)1 << col));
|
||||
}
|
||||
|
||||
inline matrix_row_t matrix_get_row(uint8_t row) {
|
||||
// Matrix mask lets you disable switches in the returned matrix data. For example, if you have a
|
||||
@@ -45,12 +69,6 @@ inline matrix_row_t matrix_get_row(uint8_t row) {
|
||||
#endif
|
||||
}
|
||||
|
||||
// Deprecated.
|
||||
bool matrix_is_modified(void) {
|
||||
if (debounce_active()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#if (MATRIX_COLS <= 8)
|
||||
# define print_matrix_header() print("\nr/c 01234567\n")
|
||||
# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
|
||||
@@ -84,18 +102,67 @@ uint8_t matrix_key_count(void) {
|
||||
return count;
|
||||
}
|
||||
|
||||
/* `matrix_io_delay ()` exists for backwards compatibility. From now on, use matrix_output_unselect_delay(). */
|
||||
__attribute__((weak)) void matrix_io_delay(void) { wait_us(MATRIX_IO_DELAY); }
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
bool matrix_post_scan(void) {
|
||||
bool changed = false;
|
||||
if (is_keyboard_master()) {
|
||||
static bool last_connected = false;
|
||||
matrix_row_t slave_matrix[ROWS_PER_HAND] = {0};
|
||||
if (transport_master_if_connected(matrix + thisHand, slave_matrix)) {
|
||||
changed = memcmp(matrix + thatHand, slave_matrix, sizeof(slave_matrix)) != 0;
|
||||
|
||||
__attribute__((weak)) void matrix_output_select_delay(void) { waitInputPinDelay(); }
|
||||
__attribute__((weak)) void matrix_output_unselect_delay(uint8_t line, bool key_pressed) { matrix_io_delay(); }
|
||||
last_connected = true;
|
||||
} else if (last_connected) {
|
||||
// reset other half when disconnected
|
||||
memset(slave_matrix, 0, sizeof(slave_matrix));
|
||||
changed = true;
|
||||
|
||||
last_connected = false;
|
||||
}
|
||||
|
||||
if (changed) memcpy(matrix + thatHand, slave_matrix, sizeof(slave_matrix));
|
||||
|
||||
matrix_scan_quantum();
|
||||
} else {
|
||||
transport_slave(matrix + thatHand, matrix + thisHand);
|
||||
|
||||
matrix_slave_scan_kb();
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* `matrix_io_delay ()` exists for backwards compatibility. From now on, use matrix_output_unselect_delay(). */
|
||||
__attribute__((weak)) void matrix_io_delay(void) {
|
||||
wait_us(MATRIX_IO_DELAY);
|
||||
}
|
||||
__attribute__((weak)) void matrix_output_select_delay(void) {
|
||||
waitInputPinDelay();
|
||||
}
|
||||
__attribute__((weak)) void matrix_output_unselect_delay(uint8_t line, bool key_pressed) {
|
||||
matrix_io_delay();
|
||||
}
|
||||
|
||||
// CUSTOM MATRIX 'LITE'
|
||||
__attribute__((weak)) void matrix_init_custom(void) {}
|
||||
__attribute__((weak)) bool matrix_scan_custom(matrix_row_t current_matrix[]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
__attribute__((weak)) bool matrix_scan_custom(matrix_row_t current_matrix[]) { return true; }
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
__attribute__((weak)) void matrix_slave_scan_kb(void) {
|
||||
matrix_slave_scan_user();
|
||||
}
|
||||
__attribute__((weak)) void matrix_slave_scan_user(void) {}
|
||||
#endif
|
||||
|
||||
__attribute__((weak)) void matrix_init(void) {
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
thisHand = isLeftHand ? 0 : (ROWS_PER_HAND);
|
||||
thatHand = ROWS_PER_HAND - thisHand;
|
||||
#endif
|
||||
|
||||
matrix_init_custom();
|
||||
|
||||
// initialize matrix state: all keys off
|
||||
@@ -104,7 +171,7 @@ __attribute__((weak)) void matrix_init(void) {
|
||||
matrix[i] = 0;
|
||||
}
|
||||
|
||||
debounce_init(MATRIX_ROWS);
|
||||
debounce_init(ROWS_PER_HAND);
|
||||
|
||||
matrix_init_quantum();
|
||||
}
|
||||
@@ -112,10 +179,17 @@ __attribute__((weak)) void matrix_init(void) {
|
||||
__attribute__((weak)) uint8_t matrix_scan(void) {
|
||||
bool changed = matrix_scan_custom(raw_matrix);
|
||||
|
||||
debounce(raw_matrix, matrix, MATRIX_ROWS, changed);
|
||||
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed);
|
||||
changed = (changed || matrix_post_scan());
|
||||
#else
|
||||
debounce(raw_matrix, matrix, ROWS_PER_HAND, changed);
|
||||
matrix_scan_quantum();
|
||||
#endif
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
__attribute__((weak)) bool peek_matrix(uint8_t row_index, uint8_t col_index, bool raw) { return 0 != ((raw ? raw_matrix[row_index] : matrix[row_index]) & (MATRIX_ROW_SHIFTER << col_index)); }
|
||||
__attribute__((weak)) bool peek_matrix(uint8_t row_index, uint8_t col_index, bool raw) {
|
||||
return 0 != ((raw ? raw_matrix[row_index] : matrix[row_index]) & (MATRIX_ROW_SHIFTER << col_index));
|
||||
}
|
||||
|
||||
@@ -520,4 +520,6 @@ static void mousekey_debug(void) {
|
||||
print(")\n");
|
||||
}
|
||||
|
||||
report_mouse_t mousekey_get_report(void) { return mouse_report; }
|
||||
report_mouse_t mousekey_get_report(void) {
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
@@ -37,9 +37,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# ifndef MOUSEKEY_MOVE_DELTA
|
||||
# ifndef MK_KINETIC_SPEED
|
||||
# define MOUSEKEY_MOVE_DELTA 5
|
||||
# define MOUSEKEY_MOVE_DELTA 8
|
||||
# else
|
||||
# define MOUSEKEY_MOVE_DELTA 25
|
||||
# define MOUSEKEY_MOVE_DELTA 5
|
||||
# endif
|
||||
# endif
|
||||
# ifndef MOUSEKEY_WHEEL_DELTA
|
||||
@@ -47,29 +47,29 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# endif
|
||||
# ifndef MOUSEKEY_DELAY
|
||||
# ifndef MK_KINETIC_SPEED
|
||||
# define MOUSEKEY_DELAY 300
|
||||
# define MOUSEKEY_DELAY 10
|
||||
# else
|
||||
# define MOUSEKEY_DELAY 8
|
||||
# define MOUSEKEY_DELAY 5
|
||||
# endif
|
||||
# endif
|
||||
# ifndef MOUSEKEY_INTERVAL
|
||||
# ifndef MK_KINETIC_SPEED
|
||||
# define MOUSEKEY_INTERVAL 50
|
||||
# define MOUSEKEY_INTERVAL 20
|
||||
# else
|
||||
# define MOUSEKEY_INTERVAL 8
|
||||
# define MOUSEKEY_INTERVAL 10
|
||||
# endif
|
||||
# endif
|
||||
# ifndef MOUSEKEY_MAX_SPEED
|
||||
# define MOUSEKEY_MAX_SPEED 10
|
||||
# endif
|
||||
# ifndef MOUSEKEY_TIME_TO_MAX
|
||||
# define MOUSEKEY_TIME_TO_MAX 20
|
||||
# define MOUSEKEY_TIME_TO_MAX 30
|
||||
# endif
|
||||
# ifndef MOUSEKEY_WHEEL_DELAY
|
||||
# define MOUSEKEY_WHEEL_DELAY 300
|
||||
# define MOUSEKEY_WHEEL_DELAY 10
|
||||
# endif
|
||||
# ifndef MOUSEKEY_WHEEL_INTERVAL
|
||||
# define MOUSEKEY_WHEEL_INTERVAL 100
|
||||
# define MOUSEKEY_WHEEL_INTERVAL 80
|
||||
# endif
|
||||
# ifndef MOUSEKEY_WHEEL_MAX_SPEED
|
||||
# define MOUSEKEY_WHEEL_MAX_SPEED 8
|
||||
|
||||
@@ -18,24 +18,115 @@
|
||||
|
||||
#include "pointing_device.h"
|
||||
#include <string.h>
|
||||
#include "timer.h"
|
||||
#ifdef MOUSEKEY_ENABLE
|
||||
# include "mousekey.h"
|
||||
#endif
|
||||
#if (defined(POINTING_DEVICE_ROTATION_90) + defined(POINTING_DEVICE_ROTATION_180) + defined(POINTING_DEVICE_ROTATION_270)) > 1
|
||||
# error More than one rotation selected. This is not supported.
|
||||
#endif
|
||||
#if defined(SPLIT_POINTING_ENABLE)
|
||||
# include "transactions.h"
|
||||
# include "keyboard.h"
|
||||
|
||||
static report_mouse_t mouseReport = {};
|
||||
report_mouse_t shared_mouse_report = {};
|
||||
uint16_t shared_cpi = 0;
|
||||
|
||||
/**
|
||||
* @brief Sets the shared mouse report used be pointing device task
|
||||
*
|
||||
* NOTE : Only available when using SPLIT_POINTING_ENABLE
|
||||
*
|
||||
* @param[in] new_mouse_report report_mouse_t
|
||||
*/
|
||||
void pointing_device_set_shared_report(report_mouse_t new_mouse_report) {
|
||||
shared_mouse_report = new_mouse_report;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets current pointing device CPI if supported
|
||||
*
|
||||
* Gets current cpi of the shared report and returns it as uint16_t
|
||||
*
|
||||
* NOTE : Only available when using SPLIT_POINTING_ENABLE
|
||||
*
|
||||
* @return cpi value as uint16_t
|
||||
*/
|
||||
uint16_t pointing_device_get_shared_cpi(void) {
|
||||
return shared_cpi;
|
||||
}
|
||||
|
||||
# if defined(POINTING_DEVICE_LEFT)
|
||||
# define POINTING_DEVICE_THIS_SIDE is_keyboard_left()
|
||||
# elif defined(POINTING_DEVICE_RIGHT)
|
||||
# define POINTING_DEVICE_THIS_SIDE !is_keyboard_left()
|
||||
# elif defined(POINTING_DEVICE_COMBINED)
|
||||
# define POINTING_DEVICE_THIS_SIDE true
|
||||
# endif
|
||||
|
||||
#endif // defined(SPLIT_POINTING_ENABLE)
|
||||
|
||||
static report_mouse_t local_mouse_report = {};
|
||||
|
||||
extern const pointing_device_driver_t pointing_device_driver;
|
||||
|
||||
__attribute__((weak)) bool has_mouse_report_changed(report_mouse_t new, report_mouse_t old) { return memcmp(&new, &old, sizeof(new)); }
|
||||
/**
|
||||
* @brief Compares 2 mouse reports for difference and returns result
|
||||
*
|
||||
* @param[in] new report_mouse_t
|
||||
* @param[in] old report_mouse_t
|
||||
* @return bool result
|
||||
*/
|
||||
__attribute__((weak)) bool has_mouse_report_changed(report_mouse_t new, report_mouse_t old) {
|
||||
return memcmp(&new, &old, sizeof(new));
|
||||
}
|
||||
|
||||
__attribute__((weak)) void pointing_device_init_kb(void) {}
|
||||
__attribute__((weak)) void pointing_device_init_user(void) {}
|
||||
__attribute__((weak)) report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) { return pointing_device_task_user(mouse_report); }
|
||||
__attribute__((weak)) report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) { return mouse_report; }
|
||||
/**
|
||||
* @brief Keyboard level code pointing device initialisation
|
||||
*
|
||||
*/
|
||||
__attribute__((weak)) void pointing_device_init_kb(void) {}
|
||||
|
||||
/**
|
||||
* @brief User level code pointing device initialisation
|
||||
*
|
||||
*/
|
||||
__attribute__((weak)) void pointing_device_init_user(void) {}
|
||||
|
||||
/**
|
||||
* @brief Weak function allowing for keyboard level mouse report modification
|
||||
*
|
||||
* Takes report_mouse_t struct allowing modification at keyboard level then returns report_mouse_t.
|
||||
*
|
||||
* @param[in] mouse_report report_mouse_t
|
||||
* @return report_mouse_t
|
||||
*/
|
||||
__attribute__((weak)) report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) {
|
||||
return pointing_device_task_user(mouse_report);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Weak function allowing for user level mouse report modification
|
||||
*
|
||||
* Takes report_mouse_t struct allowing modification at user level then returns report_mouse_t.
|
||||
*
|
||||
* @param[in] mouse_report report_mouse_t
|
||||
* @return report_mouse_t
|
||||
*/
|
||||
__attribute__((weak)) report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles pointing device buttons
|
||||
*
|
||||
* Returns modified button bitmask using bool pressed and selected pointing_device_buttons_t button in uint8_t buttons bitmask.
|
||||
*
|
||||
* @param buttons[in] uint8_t bitmask
|
||||
* @param pressed[in] bool
|
||||
* @param button[in] pointing_device_buttons_t value
|
||||
* @return Modified uint8_t bitmask buttons
|
||||
*/
|
||||
__attribute__((weak)) uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, pointing_device_buttons_t button) {
|
||||
if (pressed) {
|
||||
buttons |= 1 << (button);
|
||||
@@ -45,7 +136,17 @@ __attribute__((weak)) uint8_t pointing_device_handle_buttons(uint8_t buttons, bo
|
||||
return buttons;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialises pointing device
|
||||
*
|
||||
* Initialises pointing device, perform driver init and optional keyboard/user level code.
|
||||
*/
|
||||
__attribute__((weak)) void pointing_device_init(void) {
|
||||
#if defined(SPLIT_POINTING_ENABLE)
|
||||
if (!(POINTING_DEVICE_THIS_SIDE)) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
pointing_device_driver.init();
|
||||
#ifdef POINTING_DEVICE_MOTION_PIN
|
||||
setPinInputHigh(POINTING_DEVICE_MOTION_PIN);
|
||||
@@ -54,67 +155,303 @@ __attribute__((weak)) void pointing_device_init(void) {
|
||||
pointing_device_init_user();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends processed mouse report to host
|
||||
*
|
||||
* This sends the mouse report generated by pointing_device_task if changed since the last report. Once send zeros mouse report except buttons.
|
||||
*
|
||||
*/
|
||||
__attribute__((weak)) void pointing_device_send(void) {
|
||||
static report_mouse_t old_report = {};
|
||||
|
||||
// If you need to do other things, like debugging, this is the place to do it.
|
||||
if (has_mouse_report_changed(mouseReport, old_report)) {
|
||||
host_mouse_send(&mouseReport);
|
||||
if (has_mouse_report_changed(local_mouse_report, old_report)) {
|
||||
host_mouse_send(&local_mouse_report);
|
||||
}
|
||||
// send it and 0 it out except for buttons, so those stay until they are explicity over-ridden using update_pointing_device
|
||||
mouseReport.x = 0;
|
||||
mouseReport.y = 0;
|
||||
mouseReport.v = 0;
|
||||
mouseReport.h = 0;
|
||||
local_mouse_report.x = 0;
|
||||
local_mouse_report.y = 0;
|
||||
local_mouse_report.v = 0;
|
||||
local_mouse_report.h = 0;
|
||||
|
||||
memcpy(&old_report, &mouseReport, sizeof(mouseReport));
|
||||
memcpy(&old_report, &local_mouse_report, sizeof(local_mouse_report));
|
||||
}
|
||||
|
||||
__attribute__((weak)) void pointing_device_task(void) {
|
||||
// Gather report info
|
||||
#ifdef POINTING_DEVICE_MOTION_PIN
|
||||
if (!readPin(POINTING_DEVICE_MOTION_PIN))
|
||||
#endif
|
||||
mouseReport = pointing_device_driver.get_report(mouseReport);
|
||||
|
||||
// Support rotation of the sensor data
|
||||
/**
|
||||
* @brief Adjust mouse report by any optional common pointing configuration defines
|
||||
*
|
||||
* This applies rotation or inversion to the mouse report as selected by the pointing device common configuration defines.
|
||||
*
|
||||
* @param mouse_report[in] takes a report_mouse_t to be adjusted
|
||||
* @return report_mouse_t with adjusted values
|
||||
*/
|
||||
report_mouse_t pointing_device_adjust_by_defines(report_mouse_t mouse_report) {
|
||||
// Support rotation of the sensor data
|
||||
#if defined(POINTING_DEVICE_ROTATION_90) || defined(POINTING_DEVICE_ROTATION_180) || defined(POINTING_DEVICE_ROTATION_270)
|
||||
int8_t x = mouseReport.x, y = mouseReport.y;
|
||||
int8_t x = mouse_report.x, y = mouse_report.y;
|
||||
# if defined(POINTING_DEVICE_ROTATION_90)
|
||||
mouseReport.x = y;
|
||||
mouseReport.y = -x;
|
||||
mouse_report.x = y;
|
||||
mouse_report.y = -x;
|
||||
# elif defined(POINTING_DEVICE_ROTATION_180)
|
||||
mouseReport.x = -x;
|
||||
mouseReport.y = -y;
|
||||
mouse_report.x = -x;
|
||||
mouse_report.y = -y;
|
||||
# elif defined(POINTING_DEVICE_ROTATION_270)
|
||||
mouseReport.x = -y;
|
||||
mouseReport.y = x;
|
||||
mouse_report.x = -y;
|
||||
mouse_report.y = x;
|
||||
# else
|
||||
# error "How the heck did you get here?!"
|
||||
# endif
|
||||
#endif
|
||||
// Support Inverting the X and Y Axises
|
||||
#if defined(POINTING_DEVICE_INVERT_X)
|
||||
mouseReport.x = -mouseReport.x;
|
||||
mouse_report.x = -mouse_report.x;
|
||||
#endif
|
||||
#if defined(POINTING_DEVICE_INVERT_Y)
|
||||
mouseReport.y = -mouseReport.y;
|
||||
mouse_report.y = -mouse_report.y;
|
||||
#endif
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves and processes pointing device data.
|
||||
*
|
||||
* This function is part of the keyboard loop and retrieves the mouse report from the pointing device driver.
|
||||
* It applies any optional configuration e.g. rotation or axis inversion and then initiates a send.
|
||||
*
|
||||
*/
|
||||
__attribute__((weak)) void pointing_device_task(void) {
|
||||
#if defined(SPLIT_POINTING_ENABLE)
|
||||
// Don't poll the target side pointing device.
|
||||
if (!is_keyboard_master()) {
|
||||
return;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if (POINTING_DEVICE_TASK_THROTTLE_MS > 0)
|
||||
static uint32_t last_exec = 0;
|
||||
if (timer_elapsed32(last_exec) < POINTING_DEVICE_TASK_THROTTLE_MS) {
|
||||
return;
|
||||
}
|
||||
last_exec = timer_read32();
|
||||
#endif
|
||||
|
||||
// Gather report info
|
||||
#ifdef POINTING_DEVICE_MOTION_PIN
|
||||
# if defined(SPLIT_POINTING_ENABLE)
|
||||
# error POINTING_DEVICE_MOTION_PIN not supported when sharing the pointing device report between sides.
|
||||
# endif
|
||||
if (!readPin(POINTING_DEVICE_MOTION_PIN))
|
||||
#endif
|
||||
|
||||
#if defined(SPLIT_POINTING_ENABLE)
|
||||
# if defined(POINTING_DEVICE_COMBINED)
|
||||
static uint8_t old_buttons = 0;
|
||||
local_mouse_report.buttons = old_buttons;
|
||||
local_mouse_report = pointing_device_driver.get_report(local_mouse_report);
|
||||
old_buttons = local_mouse_report.buttons;
|
||||
# elif defined(POINTING_DEVICE_LEFT) || defined(POINTING_DEVICE_RIGHT)
|
||||
local_mouse_report = POINTING_DEVICE_THIS_SIDE ? pointing_device_driver.get_report(local_mouse_report) : shared_mouse_report;
|
||||
# else
|
||||
# error "You need to define the side(s) the pointing device is on. POINTING_DEVICE_COMBINED / POINTING_DEVICE_LEFT / POINTING_DEVICE_RIGHT"
|
||||
# endif
|
||||
#else
|
||||
local_mouse_report = pointing_device_driver.get_report(local_mouse_report);
|
||||
#endif // defined(SPLIT_POINTING_ENABLE)
|
||||
|
||||
// allow kb to intercept and modify report
|
||||
mouseReport = pointing_device_task_kb(mouseReport);
|
||||
#if defined(SPLIT_POINTING_ENABLE) && defined(POINTING_DEVICE_COMBINED)
|
||||
if (is_keyboard_left()) {
|
||||
local_mouse_report = pointing_device_adjust_by_defines(local_mouse_report);
|
||||
shared_mouse_report = pointing_device_adjust_by_defines_right(shared_mouse_report);
|
||||
} else {
|
||||
local_mouse_report = pointing_device_adjust_by_defines_right(local_mouse_report);
|
||||
shared_mouse_report = pointing_device_adjust_by_defines(shared_mouse_report);
|
||||
}
|
||||
local_mouse_report = is_keyboard_left() ? pointing_device_task_combined_kb(local_mouse_report, shared_mouse_report) : pointing_device_task_combined_kb(shared_mouse_report, local_mouse_report);
|
||||
#else
|
||||
local_mouse_report = pointing_device_adjust_by_defines(local_mouse_report);
|
||||
local_mouse_report = pointing_device_task_kb(local_mouse_report);
|
||||
#endif
|
||||
// combine with mouse report to ensure that the combined is sent correctly
|
||||
#ifdef MOUSEKEY_ENABLE
|
||||
report_mouse_t mousekey_report = mousekey_get_report();
|
||||
mouseReport.buttons = mouseReport.buttons | mousekey_report.buttons;
|
||||
local_mouse_report.buttons = local_mouse_report.buttons | mousekey_report.buttons;
|
||||
#endif
|
||||
pointing_device_send();
|
||||
}
|
||||
|
||||
report_mouse_t pointing_device_get_report(void) { return mouseReport; }
|
||||
/**
|
||||
* @brief Gets current mouse report used by pointing device task
|
||||
*
|
||||
* @return report_mouse_t
|
||||
*/
|
||||
report_mouse_t pointing_device_get_report(void) {
|
||||
return local_mouse_report;
|
||||
}
|
||||
|
||||
void pointing_device_set_report(report_mouse_t newMouseReport) { mouseReport = newMouseReport; }
|
||||
/**
|
||||
* @brief Sets mouse report used be pointing device task
|
||||
*
|
||||
* @param[in] new_mouse_report
|
||||
*/
|
||||
void pointing_device_set_report(report_mouse_t new_mouse_report) {
|
||||
local_mouse_report = new_mouse_report;
|
||||
}
|
||||
|
||||
uint16_t pointing_device_get_cpi(void) { return pointing_device_driver.get_cpi(); }
|
||||
/**
|
||||
* @brief Gets current pointing device CPI if supported
|
||||
*
|
||||
* Gets current cpi from pointing device driver if supported and returns it as uint16_t
|
||||
*
|
||||
* @return cpi value as uint16_t
|
||||
*/
|
||||
uint16_t pointing_device_get_cpi(void) {
|
||||
#if defined(SPLIT_POINTING_ENABLE)
|
||||
return POINTING_DEVICE_THIS_SIDE ? pointing_device_driver.get_cpi() : shared_cpi;
|
||||
#else
|
||||
return pointing_device_driver.get_cpi();
|
||||
#endif
|
||||
}
|
||||
|
||||
void pointing_device_set_cpi(uint16_t cpi) { pointing_device_driver.set_cpi(cpi); }
|
||||
/**
|
||||
* @brief Set pointing device CPI if supported
|
||||
*
|
||||
* Takes a uint16_t value to set pointing device cpi if supported by driver.
|
||||
*
|
||||
* @param[in] cpi uint16_t value.
|
||||
*/
|
||||
void pointing_device_set_cpi(uint16_t cpi) {
|
||||
#if defined(SPLIT_POINTING_ENABLE)
|
||||
if (POINTING_DEVICE_THIS_SIDE) {
|
||||
pointing_device_driver.set_cpi(cpi);
|
||||
} else {
|
||||
shared_cpi = cpi;
|
||||
}
|
||||
#else
|
||||
pointing_device_driver.set_cpi(cpi);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(SPLIT_POINTING_ENABLE) && defined(POINTING_DEVICE_COMBINED)
|
||||
/**
|
||||
* @brief Set pointing device CPI if supported
|
||||
*
|
||||
* Takes a bool and uint16_t and allows setting cpi for a single side when using 2 pointing devices with a split keyboard.
|
||||
*
|
||||
* NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
|
||||
*
|
||||
* @param[in] left true = left, false = right.
|
||||
* @param[in] cpi uint16_t value.
|
||||
*/
|
||||
void pointing_device_set_cpi_on_side(bool left, uint16_t cpi) {
|
||||
bool local = (is_keyboard_left() & left) ? true : false;
|
||||
if (local) {
|
||||
pointing_device_driver.set_cpi(cpi);
|
||||
} else {
|
||||
shared_cpi = cpi;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief clamps int16_t to int8_t
|
||||
*
|
||||
* @param[in] int16_t value
|
||||
* @return int8_t clamped value
|
||||
*/
|
||||
static inline int8_t pointing_device_movement_clamp(int16_t value) {
|
||||
if (value < INT8_MIN) {
|
||||
return INT8_MIN;
|
||||
} else if (value > INT8_MAX) {
|
||||
return INT8_MAX;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief combines 2 mouse reports and returns 2
|
||||
*
|
||||
* Combines 2 report_mouse_t structs, clamping movement values to int8_t and ignores report_id then returns the resulting report_mouse_t struct.
|
||||
*
|
||||
* NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
|
||||
*
|
||||
* @param[in] left_report left report_mouse_t
|
||||
* @param[in] right_report right report_mouse_t
|
||||
* @return combined report_mouse_t of left_report and right_report
|
||||
*/
|
||||
report_mouse_t pointing_device_combine_reports(report_mouse_t left_report, report_mouse_t right_report) {
|
||||
left_report.x = pointing_device_movement_clamp((int16_t)left_report.x + right_report.x);
|
||||
left_report.y = pointing_device_movement_clamp((int16_t)left_report.y + right_report.y);
|
||||
left_report.h = pointing_device_movement_clamp((int16_t)left_report.h + right_report.h);
|
||||
left_report.v = pointing_device_movement_clamp((int16_t)left_report.v + right_report.v);
|
||||
left_report.buttons |= right_report.buttons;
|
||||
return left_report;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adjust mouse report by any optional right pointing configuration defines
|
||||
*
|
||||
* This applies rotation or inversion to the mouse report as selected by the pointing device common configuration defines.
|
||||
*
|
||||
* NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
|
||||
*
|
||||
* @param[in] mouse_report report_mouse_t to be adjusted
|
||||
* @return report_mouse_t with adjusted values
|
||||
*/
|
||||
report_mouse_t pointing_device_adjust_by_defines_right(report_mouse_t mouse_report) {
|
||||
// Support rotation of the sensor data
|
||||
# if defined(POINTING_DEVICE_ROTATION_90_RIGHT) || defined(POINTING_DEVICE_ROTATION_RIGHT) || defined(POINTING_DEVICE_ROTATION_RIGHT)
|
||||
int8_t x = mouse_report.x, y = mouse_report.y;
|
||||
# if defined(POINTING_DEVICE_ROTATION_90_RIGHT)
|
||||
mouse_report.x = y;
|
||||
mouse_report.y = -x;
|
||||
# elif defined(POINTING_DEVICE_ROTATION_180_RIGHT)
|
||||
mouse_report.x = -x;
|
||||
mouse_report.y = -y;
|
||||
# elif defined(POINTING_DEVICE_ROTATION_270_RIGHT)
|
||||
mouse_report.x = -y;
|
||||
mouse_report.y = x;
|
||||
# else
|
||||
# error "How the heck did you get here?!"
|
||||
# endif
|
||||
# endif
|
||||
// Support Inverting the X and Y Axises
|
||||
# if defined(POINTING_DEVICE_INVERT_X_RIGHT)
|
||||
mouse_report.x = -mouse_report.x;
|
||||
# endif
|
||||
# if defined(POINTING_DEVICE_INVERT_Y_RIGHT)
|
||||
mouse_report.y = -mouse_report.y;
|
||||
# endif
|
||||
return mouse_report;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Weak function allowing for keyboard level mouse report modification
|
||||
*
|
||||
* Takes 2 report_mouse_t structs allowing individual modification of sides at keyboard level then returns pointing_device_task_combined_user.
|
||||
*
|
||||
* NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
|
||||
*
|
||||
* @param[in] left_report report_mouse_t
|
||||
* @param[in] right_report report_mouse_t
|
||||
* @return pointing_device_task_combined_user(left_report, right_report) by default
|
||||
*/
|
||||
__attribute__((weak)) report_mouse_t pointing_device_task_combined_kb(report_mouse_t left_report, report_mouse_t right_report) {
|
||||
return pointing_device_task_combined_user(left_report, right_report);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Weak function allowing for user level mouse report modification
|
||||
*
|
||||
* Takes 2 report_mouse_t structs allowing individual modification of sides at user level then returns pointing_device_combine_reports.
|
||||
*
|
||||
* NOTE: Only available when using SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
|
||||
*
|
||||
* @param[in] left_report report_mouse_t
|
||||
* @param[in] right_report report_mouse_t
|
||||
* @return pointing_device_combine_reports(left_report, right_report) by default
|
||||
*/
|
||||
__attribute__((weak)) report_mouse_t pointing_device_task_combined_user(report_mouse_t left_report, report_mouse_t right_report) {
|
||||
return pointing_device_combine_reports(left_report, right_report);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -47,6 +47,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#elif defined(POINTING_DEVICE_DRIVER_pmw3360)
|
||||
# include "spi_master.h"
|
||||
# include "drivers/sensors/pmw3360.h"
|
||||
#elif defined(POINTING_DEVICE_DRIVER_pmw3389)
|
||||
# include "spi_master.h"
|
||||
# include "drivers/sensors/pmw3389.h"
|
||||
#else
|
||||
void pointing_device_driver_init(void);
|
||||
report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report);
|
||||
@@ -86,3 +89,19 @@ void pointing_device_init_user(void);
|
||||
report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report);
|
||||
report_mouse_t pointing_device_task_user(report_mouse_t mouse_report);
|
||||
uint8_t pointing_device_handle_buttons(uint8_t buttons, bool pressed, pointing_device_buttons_t button);
|
||||
report_mouse_t pointing_device_adjust_by_defines(report_mouse_t mouse_report);
|
||||
|
||||
#if defined(SPLIT_POINTING_ENABLE)
|
||||
void pointing_device_set_shared_report(report_mouse_t report);
|
||||
uint16_t pointing_device_get_shared_cpi(void);
|
||||
# if !defined(POINTING_DEVICE_TASK_THROTTLE_MS)
|
||||
# define POINTING_DEVICE_TASK_THROTTLE_MS 1
|
||||
# endif
|
||||
# if defined(POINTING_DEVICE_COMBINED)
|
||||
void pointing_device_set_cpi_on_side(bool left, uint16_t cpi);
|
||||
report_mouse_t pointing_device_combine_reports(report_mouse_t left_report, report_mouse_t right_report);
|
||||
report_mouse_t pointing_device_task_combined_kb(report_mouse_t left_report, report_mouse_t right_report);
|
||||
report_mouse_t pointing_device_task_combined_user(report_mouse_t left_report, report_mouse_t right_report);
|
||||
report_mouse_t pointing_device_adjust_by_defines_right(report_mouse_t mouse_report);
|
||||
# endif // defined(POINTING_DEVICE_COMBINED)
|
||||
#endif // defined(SPLIT_POINTING_ENABLE)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user